@defai.digital/automatosx 11.3.1 → 11.3.2

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
@@ -2,8 +2,9 @@
2
2
  import * as path4 from 'path';
3
3
  import path4__default, { dirname, join, isAbsolute, basename, resolve, extname as extname$1, relative, sep, normalize, parse as parse$1, delimiter } from 'path';
4
4
  import { fileURLToPath } from 'url';
5
- import * as fs4 from 'fs/promises';
5
+ import * as fs5 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';
7
+ import * as fs3 from 'fs';
7
8
  import { access, realpath, existsSync, readFileSync, constants, writeFileSync, mkdirSync, promises, statSync, readdirSync, createWriteStream, unlinkSync } from 'fs';
8
9
  import Database2 from 'better-sqlite3';
9
10
  import os2, { homedir, cpus } from 'os';
@@ -17,9 +18,9 @@ import * as readline2 from 'readline';
17
18
  import readline2__default, { createInterface } from 'readline';
18
19
  import { Mutex } from 'async-mutex';
19
20
  import { promisify } from 'util';
21
+ import crypto2, { randomUUID, createHash } from 'crypto';
20
22
  import yargs from 'yargs';
21
23
  import { hideBin } from 'yargs/helpers';
22
- import crypto2, { randomUUID, createHash } from 'crypto';
23
24
  import * as yaml4 from 'js-yaml';
24
25
  import yaml4__default, { load, dump } from 'js-yaml';
25
26
  import Table from 'cli-table3';
@@ -32,9 +33,7 @@ import yaml from 'yaml';
32
33
  import { parse } from '@iarna/toml';
33
34
 
34
35
  var __defProp = Object.defineProperty;
35
- var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
36
36
  var __getOwnPropNames = Object.getOwnPropertyNames;
37
- var __hasOwnProp = Object.prototype.hasOwnProperty;
38
37
  var __require = /* @__PURE__ */ ((x) => typeof require !== "undefined" ? require : typeof Proxy !== "undefined" ? new Proxy(x, {
39
38
  get: (a, b) => (typeof require !== "undefined" ? require : a)[b]
40
39
  }) : x)(function(x) {
@@ -48,15 +47,6 @@ var __export = (target, all) => {
48
47
  for (var name in all)
49
48
  __defProp(target, name, { get: all[name], enumerable: true });
50
49
  };
51
- var __copyProps = (to, from, except, desc) => {
52
- if (from && typeof from === "object" || typeof from === "function") {
53
- for (let key of __getOwnPropNames(from))
54
- if (!__hasOwnProp.call(to, key) && key !== except)
55
- __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
56
- }
57
- return to;
58
- };
59
- var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
60
50
  var init_esm_shims = __esm({
61
51
  "node_modules/tsup/assets/esm_shims.js"() {
62
52
  }
@@ -753,16 +743,16 @@ var init_errors = __esm({
753
743
  constructor(message, code = "E1001" /* CONFIG_INVALID */, suggestions = [], context) {
754
744
  super(message, code, suggestions, context);
755
745
  }
756
- static notFound(path7) {
746
+ static notFound(path8) {
757
747
  return new _ConfigError(
758
- `Configuration file not found: ${path7}`,
748
+ `Configuration file not found: ${path8}`,
759
749
  "E1000" /* CONFIG_NOT_FOUND */,
760
750
  [
761
751
  'Run "automatosx setup" to create a new configuration',
762
752
  "Specify a custom config path with --config option",
763
753
  "Check that you are in a valid AutomatosX project directory"
764
754
  ],
765
- { path: path7 }
755
+ { path: path8 }
766
756
  );
767
757
  }
768
758
  static invalid(reason, context) {
@@ -777,7 +767,7 @@ var init_errors = __esm({
777
767
  context
778
768
  );
779
769
  }
780
- static parseError(error, path7) {
770
+ static parseError(error, path8) {
781
771
  return new _ConfigError(
782
772
  `Failed to parse configuration: ${error.message}`,
783
773
  "E1002" /* CONFIG_PARSE_ERROR */,
@@ -786,7 +776,7 @@ var init_errors = __esm({
786
776
  "Use a JSON validator to find syntax errors",
787
777
  'Reset to default with "automatosx setup --force"'
788
778
  ],
789
- { path: path7, originalError: error.message }
779
+ { path: path8, originalError: error.message }
790
780
  );
791
781
  }
792
782
  };
@@ -1014,8 +1004,8 @@ __export(path_resolver_exports, {
1014
1004
  PathResolver: () => PathResolver,
1015
1005
  detectProjectRoot: () => detectProjectRoot
1016
1006
  });
1017
- function isWindowsPath(path7) {
1018
- return /^[a-zA-Z]:[/\\]/.test(path7);
1007
+ function isWindowsPath(path8) {
1008
+ return /^[a-zA-Z]:[/\\]/.test(path8);
1019
1009
  }
1020
1010
  async function detectProjectRoot(startDir = process.cwd()) {
1021
1011
  if (process.env.AUTOMATOSX_PROJECT_ROOT) {
@@ -1121,8 +1111,8 @@ var init_path_resolver = __esm({
1121
1111
  /**
1122
1112
  * Validate path is within allowed base directory
1123
1113
  */
1124
- validatePath(path7, baseDir) {
1125
- const normalized = normalizePath(resolvePath(path7));
1114
+ validatePath(path8, baseDir) {
1115
+ const normalized = normalizePath(resolvePath(path8));
1126
1116
  const base = normalizePath(resolvePath(baseDir));
1127
1117
  const separator = "/";
1128
1118
  const pathWithSep = normalized + separator;
@@ -1132,15 +1122,15 @@ var init_path_resolver = __esm({
1132
1122
  /**
1133
1123
  * Check if path is within allowed boundaries
1134
1124
  */
1135
- isPathAllowed(path7) {
1136
- const boundary = this.checkBoundaries(path7);
1125
+ isPathAllowed(path8) {
1126
+ const boundary = this.checkBoundaries(path8);
1137
1127
  return boundary === "agent_workspace" || boundary === "user_project";
1138
1128
  }
1139
1129
  /**
1140
1130
  * Check which boundary a path belongs to
1141
1131
  */
1142
- checkBoundaries(path7) {
1143
- const normalized = resolvePath(path7);
1132
+ checkBoundaries(path8) {
1133
+ const normalized = resolvePath(path8);
1144
1134
  if (this.validatePath(normalized, this.config.agentWorkspace)) {
1145
1135
  return "agent_workspace";
1146
1136
  }
@@ -1158,15 +1148,15 @@ var init_path_resolver = __esm({
1158
1148
  /**
1159
1149
  * Get relative path from project root
1160
1150
  */
1161
- getRelativeToProject(path7) {
1162
- const normalized = resolvePath(path7);
1151
+ getRelativeToProject(path8) {
1152
+ const normalized = resolvePath(path8);
1163
1153
  return normalizePath(getRelativePath(this.config.projectDir, normalized));
1164
1154
  }
1165
1155
  /**
1166
1156
  * Get relative path from working directory
1167
1157
  */
1168
- getRelativeToWorking(path7) {
1169
- const normalized = resolvePath(path7);
1158
+ getRelativeToWorking(path8) {
1159
+ const normalized = resolvePath(path8);
1170
1160
  return normalizePath(getRelativePath(this.config.workingDir, normalized));
1171
1161
  }
1172
1162
  /**
@@ -1185,11 +1175,11 @@ var init_path_resolver = __esm({
1185
1175
  * Validate path is within project boundaries
1186
1176
  * @throws PathError if outside project
1187
1177
  */
1188
- validateInProject(path7) {
1189
- const boundary = this.checkBoundaries(path7);
1178
+ validateInProject(path8) {
1179
+ const boundary = this.checkBoundaries(path8);
1190
1180
  if (boundary === "outside_boundaries" || boundary === "system_restricted") {
1191
1181
  throw new PathError("Path outside project directory", {
1192
- path: path7,
1182
+ path: path8,
1193
1183
  projectDir: this.config.projectDir,
1194
1184
  boundary
1195
1185
  });
@@ -1432,11 +1422,11 @@ var init_workspace_indexer = __esm({
1432
1422
  /**
1433
1423
  * Detect file type and language
1434
1424
  */
1435
- detectTypeAndLanguage(path7, ext) {
1436
- if (path7.match(/package\.json|tsconfig\.json|\.config\.(js|ts|json|yaml|yml)|\.eslintrc|\.prettierrc/)) {
1425
+ detectTypeAndLanguage(path8, ext) {
1426
+ if (path8.match(/package\.json|tsconfig\.json|\.config\.(js|ts|json|yaml|yml)|\.eslintrc|\.prettierrc/)) {
1437
1427
  return { type: "config", language: "json" };
1438
1428
  }
1439
- if (path7.match(/\.(test|spec)\.(ts|js|tsx|jsx)$/) || path7.includes("__tests__")) {
1429
+ if (path8.match(/\.(test|spec)\.(ts|js|tsx|jsx)$/) || path8.includes("__tests__")) {
1440
1430
  const lang = LANGUAGE_MAP[ext];
1441
1431
  return { type: "test", language: lang };
1442
1432
  }
@@ -1453,15 +1443,15 @@ var init_workspace_indexer = __esm({
1453
1443
  *
1454
1444
  * Higher score = more likely to be relevant
1455
1445
  */
1456
- calculateImportance(path7, type, size) {
1446
+ calculateImportance(path8, type, size) {
1457
1447
  let score = 0.5;
1458
- if (path7.match(/^(index|main|app)\.(ts|js|tsx|jsx)$/)) score = 1;
1459
- if (path7.match(/^src\/(index|main|app)\.(ts|js|tsx|jsx)$/)) score = 0.95;
1460
- if (path7.match(/^src\/cli\/(index|main)\.(ts|js)$/)) score = 0.9;
1448
+ if (path8.match(/^(index|main|app)\.(ts|js|tsx|jsx)$/)) score = 1;
1449
+ if (path8.match(/^src\/(index|main|app)\.(ts|js|tsx|jsx)$/)) score = 0.95;
1450
+ if (path8.match(/^src\/cli\/(index|main)\.(ts|js)$/)) score = 0.9;
1461
1451
  if (type === "config") score = 0.85;
1462
- if (path7.includes("/core/")) score += 0.15;
1463
- if (path7.includes("/types/")) score += 0.1;
1464
- if (path7.includes("/utils/")) score += 0.05;
1452
+ if (path8.includes("/core/")) score += 0.15;
1453
+ if (path8.includes("/types/")) score += 0.1;
1454
+ if (path8.includes("/utils/")) score += 0.05;
1465
1455
  if (type === "test") score = Math.max(0.3, score - 0.3);
1466
1456
  if (type === "doc") score = Math.max(0.4, score - 0.2);
1467
1457
  if (size > 1e4) score += 0.05;
@@ -1937,10 +1927,10 @@ function findOnPathUnix(cmdBase) {
1937
1927
  try {
1938
1928
  const which = spawnSync("which", [cmdBase], { timeout: 3e3 });
1939
1929
  if (which.status === 0) {
1940
- const path7 = which.stdout.toString().trim();
1941
- if (path7) {
1942
- logger.debug("Found via which", { cmdBase, path: path7 });
1943
- return { found: true, path: path7 };
1930
+ const path8 = which.stdout.toString().trim();
1931
+ if (path8) {
1932
+ logger.debug("Found via which", { cmdBase, path: path8 });
1933
+ return { found: true, path: path8 };
1944
1934
  }
1945
1935
  }
1946
1936
  } catch (error) {
@@ -2239,15 +2229,6 @@ var init_streaming_progress_parser = __esm({
2239
2229
  });
2240
2230
 
2241
2231
  // src/providers/error-patterns.ts
2242
- var error_patterns_exports = {};
2243
- __export(error_patterns_exports, {
2244
- GENERIC_ERROR_PATTERNS: () => GENERIC_ERROR_PATTERNS,
2245
- PROVIDER_ERROR_PATTERNS: () => PROVIDER_ERROR_PATTERNS,
2246
- getProviderErrorPatterns: () => getProviderErrorPatterns,
2247
- isLimitError: () => isLimitError,
2248
- isQuotaError: () => isQuotaError,
2249
- isRateLimitError: () => isRateLimitError
2250
- });
2251
2232
  function isQuotaError(error, providerName) {
2252
2233
  const patterns = PROVIDER_ERROR_PATTERNS[providerName] || GENERIC_ERROR_PATTERNS;
2253
2234
  const message = (error?.message || "").toLowerCase();
@@ -2289,9 +2270,6 @@ function isRateLimitError(error, providerName) {
2289
2270
  function isLimitError(error, providerName) {
2290
2271
  return isQuotaError(error, providerName) || isRateLimitError(error, providerName);
2291
2272
  }
2292
- function getProviderErrorPatterns(providerName) {
2293
- return PROVIDER_ERROR_PATTERNS[providerName] || GENERIC_ERROR_PATTERNS;
2294
- }
2295
2273
  var PROVIDER_ERROR_PATTERNS, GENERIC_ERROR_PATTERNS;
2296
2274
  var init_error_patterns = __esm({
2297
2275
  "src/providers/error-patterns.ts"() {
@@ -2512,6 +2490,7 @@ var init_base_provider = __esm({
2512
2490
  init_provider_schemas();
2513
2491
  init_streaming_progress_parser();
2514
2492
  init_verbosity_manager();
2493
+ init_error_patterns();
2515
2494
  BaseProvider = class _BaseProvider {
2516
2495
  /**
2517
2496
  * Whitelist of allowed provider names for security
@@ -2544,6 +2523,10 @@ var init_base_provider = __esm({
2544
2523
  NO_UPDATE_NOTIFIER: "1",
2545
2524
  DEBIAN_FRONTEND: "noninteractive"
2546
2525
  };
2526
+ /** Default CLI execution timeout in milliseconds */
2527
+ static DEFAULT_TIMEOUT_MS = 12e4;
2528
+ /** Time to wait after SIGTERM before escalating to SIGKILL */
2529
+ static SIGKILL_ESCALATION_MS = 5e3;
2547
2530
  config;
2548
2531
  logger = logger;
2549
2532
  health;
@@ -2601,7 +2584,7 @@ var init_base_provider = __esm({
2601
2584
  useStdin,
2602
2585
  streaming: process.env.AUTOMATOSX_SHOW_PROVIDER_OUTPUT === "true"
2603
2586
  });
2604
- const result = useStdin ? await this.executeWithStdin(cliCommand2, argsString.trim(), prompt) : await this.executeWithSpawn(fullCommand, cliCommand2);
2587
+ const result = useStdin ? await this.executeWithStdin(cliCommand2, cliArgs, prompt) : await this.executeWithSpawn(fullCommand, cliCommand2);
2605
2588
  if (!result.stdout) {
2606
2589
  throw new Error(`${cliCommand2} CLI returned empty output. stderr: ${result.stderr || "none"}`);
2607
2590
  }
@@ -2623,8 +2606,8 @@ var init_base_provider = __esm({
2623
2606
  /**
2624
2607
  * Execute command using spawn() with streaming support (v8.4.18)
2625
2608
  *
2626
- * Replaces execWithCleanup to support real-time line-by-line output streaming.
2627
- * Maintains all timeout and cleanup behaviors from execWithCleanup.
2609
+ * Supports real-time line-by-line output streaming with proper timeout
2610
+ * and cleanup behaviors (SIGTERM → SIGKILL escalation pattern).
2628
2611
  *
2629
2612
  * @param command - Full command string to execute
2630
2613
  * @param cliCommand - CLI command name (for logging)
@@ -2635,7 +2618,7 @@ var init_base_provider = __esm({
2635
2618
  const child = spawn(command, [], {
2636
2619
  shell: true,
2637
2620
  // Auto-detects: cmd.exe on Windows, /bin/sh on Unix
2638
- timeout: this.config.timeout || 12e4,
2621
+ timeout: this.config.timeout || _BaseProvider.DEFAULT_TIMEOUT_MS,
2639
2622
  env: { ...process.env, ..._BaseProvider.NON_INTERACTIVE_ENV }
2640
2623
  });
2641
2624
  let stdout = "";
@@ -2746,7 +2729,7 @@ var init_base_provider = __esm({
2746
2729
  });
2747
2730
  reject(new Error(`Failed to spawn ${cliCommand2} CLI: ${error.message}`));
2748
2731
  });
2749
- const timeout = this.config.timeout || 12e4;
2732
+ const timeout = this.config.timeout || _BaseProvider.DEFAULT_TIMEOUT_MS;
2750
2733
  timeoutId = setTimeout(() => {
2751
2734
  if (child.pid && !child.killed) {
2752
2735
  logger.warn("Killing child process due to timeout", {
@@ -2760,7 +2743,7 @@ var init_base_provider = __esm({
2760
2743
  logger.warn("Force killing child process", { pid: child.pid });
2761
2744
  child.kill("SIGKILL");
2762
2745
  }
2763
- }, 5e3);
2746
+ }, _BaseProvider.SIGKILL_ESCALATION_MS);
2764
2747
  }
2765
2748
  }, timeout);
2766
2749
  });
@@ -2778,14 +2761,13 @@ var init_base_provider = __esm({
2778
2761
  */
2779
2762
  async executeWithStdin(cliCommand2, cliArgs, prompt) {
2780
2763
  return new Promise((resolve13, reject) => {
2781
- const commandArgs = cliArgs ? cliArgs.split(" ").filter(Boolean) : [];
2782
2764
  logger.debug(`Executing ${cliCommand2} CLI with stdin`, {
2783
2765
  command: cliCommand2,
2784
- args: commandArgs,
2766
+ args: cliArgs,
2785
2767
  promptLength: prompt.length
2786
2768
  });
2787
- const child = spawn(cliCommand2, commandArgs, {
2788
- timeout: this.config.timeout || 12e4,
2769
+ const child = spawn(cliCommand2, cliArgs, {
2770
+ timeout: this.config.timeout || _BaseProvider.DEFAULT_TIMEOUT_MS,
2789
2771
  env: { ...process.env, ..._BaseProvider.NON_INTERACTIVE_ENV }
2790
2772
  });
2791
2773
  let stdout = "";
@@ -2921,7 +2903,7 @@ var init_base_provider = __esm({
2921
2903
  });
2922
2904
  reject(new Error(`Failed to spawn ${cliCommand2} CLI: ${error.message}`));
2923
2905
  });
2924
- const timeout = this.config.timeout || 12e4;
2906
+ const timeout = this.config.timeout || _BaseProvider.DEFAULT_TIMEOUT_MS;
2925
2907
  timeoutId = setTimeout(() => {
2926
2908
  if (child.pid && !child.killed) {
2927
2909
  logger.warn("Killing child process due to timeout", {
@@ -2935,7 +2917,7 @@ var init_base_provider = __esm({
2935
2917
  logger.warn("Force killing child process", { pid: child.pid });
2936
2918
  child.kill("SIGKILL");
2937
2919
  }
2938
- }, 5e3);
2920
+ }, _BaseProvider.SIGKILL_ESCALATION_MS);
2939
2921
  }
2940
2922
  }, timeout);
2941
2923
  });
@@ -3001,10 +2983,8 @@ var init_base_provider = __esm({
3001
2983
  ${request.prompt}`;
3002
2984
  }
3003
2985
  if (process.env.AUTOMATOSX_DEBUG_PROMPT === "true") {
3004
- const fs7 = await import('fs');
3005
- const path7 = await import('path');
3006
- const debugPath = path7.join(process.cwd(), "automatosx/tmp/debug-prompt.txt");
3007
- fs7.writeFileSync(debugPath, `=== FULL PROMPT SENT TO ${this.getCLICommand()} ===
2986
+ const debugPath = path4.join(process.cwd(), "automatosx/tmp/debug-prompt.txt");
2987
+ fs3.writeFileSync(debugPath, `=== FULL PROMPT SENT TO ${this.getCLICommand()} ===
3008
2988
 
3009
2989
  ${fullPrompt}
3010
2990
 
@@ -3127,26 +3107,16 @@ ${fullPrompt}
3127
3107
  * @returns true if this is a rate limit or quota error
3128
3108
  */
3129
3109
  detectRateLimitError(error) {
3130
- const { isLimitError: isLimitError2 } = (init_error_patterns(), __toCommonJS(error_patterns_exports));
3131
- try {
3132
- const isLimited = isLimitError2(error, this.config.name);
3133
- if (isLimited) {
3134
- this.logger.debug("Rate limit error detected", {
3135
- provider: this.config.name,
3136
- message: error?.message,
3137
- code: error?.code,
3138
- status: error?.status || error?.statusCode
3139
- });
3140
- }
3141
- return isLimited;
3142
- } catch (detectionError) {
3143
- this.logger.warn("Rate limit detection failed, using fallback", {
3110
+ const isLimited = isLimitError(error, this.config.name);
3111
+ if (isLimited) {
3112
+ this.logger.debug("Rate limit error detected", {
3144
3113
  provider: this.config.name,
3145
- error: detectionError
3114
+ message: error?.message,
3115
+ code: error?.code,
3116
+ status: error?.status || error?.statusCode
3146
3117
  });
3147
- const message = (error?.message || "").toLowerCase();
3148
- return message.includes("rate limit") || message.includes("quota") || message.includes("resource_exhausted") || message.includes("too many requests");
3149
3118
  }
3119
+ return isLimited;
3150
3120
  }
3151
3121
  /**
3152
3122
  * Escape shell command arguments to prevent injection
@@ -4874,24 +4844,25 @@ var init_token_estimator = __esm({
4874
4844
  };
4875
4845
  }
4876
4846
  });
4877
-
4878
- // src/integrations/ax-cli-sdk/subagent-adapter.ts
4879
- var TOKEN_SPLIT, SubagentAdapter;
4847
+ var TOKEN_SPLIT, DEFAULT_MAX_PARALLEL, DEFAULT_TIMEOUT_MS, DEFAULT_SUBAGENT_MAX_TOOL_ROUNDS, SubagentAdapter;
4880
4848
  var init_subagent_adapter = __esm({
4881
4849
  "src/integrations/ax-cli-sdk/subagent-adapter.ts"() {
4882
4850
  init_esm_shims();
4883
4851
  init_logger();
4884
4852
  TOKEN_SPLIT = { PROMPT: 0.3, COMPLETION: 0.7 };
4853
+ DEFAULT_MAX_PARALLEL = 4;
4854
+ DEFAULT_TIMEOUT_MS = 3e5;
4855
+ DEFAULT_SUBAGENT_MAX_TOOL_ROUNDS = 100;
4885
4856
  SubagentAdapter = class {
4886
4857
  orchestrator = null;
4887
4858
  subagents = /* @__PURE__ */ new Map();
4859
+ busySubagents = /* @__PURE__ */ new Set();
4888
4860
  sdkAvailable = null;
4889
4861
  options;
4890
4862
  constructor(options = {}) {
4891
4863
  this.options = {
4892
- maxParallel: options.maxParallel ?? 4,
4893
- timeout: options.timeout ?? 3e5,
4894
- // 5 minutes
4864
+ maxParallel: options.maxParallel ?? DEFAULT_MAX_PARALLEL,
4865
+ timeout: options.timeout ?? DEFAULT_TIMEOUT_MS,
4895
4866
  sharedContext: options.sharedContext ?? true,
4896
4867
  continueOnError: options.continueOnError ?? true,
4897
4868
  events: options.events,
@@ -4946,23 +4917,41 @@ var init_subagent_adapter = __esm({
4946
4917
  taskCount: tasks.length,
4947
4918
  maxParallel: this.options.maxParallel
4948
4919
  });
4949
- const sortedTasks = [...tasks].sort((a, b) => (a.priority ?? 0) - (b.priority ?? 0));
4950
- const results = [];
4920
+ const tasksWithIndex = tasks.map((task, index) => ({ task, index }));
4921
+ const sortedTasks = [...tasksWithIndex].sort(
4922
+ (a, b) => (a.task.priority ?? 0) - (b.task.priority ?? 0)
4923
+ );
4924
+ const results = new Array(tasks.length);
4951
4925
  const batchSize = this.options.maxParallel;
4952
4926
  for (let i = 0; i < sortedTasks.length; i += batchSize) {
4953
4927
  const batch = sortedTasks.slice(i, i + batchSize);
4954
- const batchResults = await this.executeBatch(batch);
4955
- results.push(...batchResults);
4928
+ const batchResults = await this.executeBatch(batch.map((item) => item.task));
4929
+ batch.forEach((item, idx) => {
4930
+ results[item.index] = batchResults[idx];
4931
+ });
4956
4932
  if (this.options.sharedContext && i + batchSize < sortedTasks.length) {
4957
4933
  await this.propagateContext(batchResults);
4958
4934
  }
4959
4935
  }
4936
+ const finalResults = results.map((result, index) => {
4937
+ if (result) {
4938
+ return result;
4939
+ }
4940
+ return {
4941
+ task: tasks[index]?.task ?? "unknown",
4942
+ role: tasks[index]?.config.role ?? "custom",
4943
+ content: "",
4944
+ success: false,
4945
+ error: "Subagent result missing",
4946
+ latencyMs: 0
4947
+ };
4948
+ });
4960
4949
  logger.info("Parallel execution complete", {
4961
4950
  taskCount: tasks.length,
4962
- successCount: results.filter((r) => r.success).length,
4951
+ successCount: finalResults.filter((r) => r.success).length,
4963
4952
  totalLatencyMs: Date.now() - startTime
4964
4953
  });
4965
- return results;
4954
+ return finalResults;
4966
4955
  }
4967
4956
  /**
4968
4957
  * Execute tasks sequentially with context propagation
@@ -4980,18 +4969,27 @@ var init_subagent_adapter = __esm({
4980
4969
  const results = [];
4981
4970
  let accumulatedContext = "";
4982
4971
  for (const task of tasks) {
4983
- const taskWithContext = {
4984
- ...task,
4985
- context: task.context ? `${task.context}
4972
+ let combinedContext;
4973
+ if (task.context && accumulatedContext) {
4974
+ combinedContext = `${task.context}
4986
4975
 
4987
4976
  Previous results:
4988
- ${accumulatedContext}` : accumulatedContext || void 0
4977
+ ${accumulatedContext}`;
4978
+ } else if (task.context) {
4979
+ combinedContext = task.context;
4980
+ } else if (accumulatedContext) {
4981
+ combinedContext = accumulatedContext;
4982
+ }
4983
+ const taskWithContext = {
4984
+ ...task,
4985
+ context: combinedContext
4989
4986
  };
4990
4987
  const result = await this.executeTask(taskWithContext);
4991
4988
  results.push(result);
4992
4989
  if (result.success && this.options.sharedContext) {
4990
+ const truncated = result.content.length > 500;
4993
4991
  accumulatedContext += `
4994
- [${result.role}]: ${result.content.substring(0, 500)}...
4992
+ [${result.role}]: ${result.content.substring(0, 500)}${truncated ? "..." : ""}
4995
4993
  `;
4996
4994
  }
4997
4995
  if (!result.success && !this.options.continueOnError) {
@@ -5017,6 +5015,7 @@ ${accumulatedContext}` : accumulatedContext || void 0
5017
5015
  const startTime = Date.now();
5018
5016
  const subagentKey = this.getSubagentKey(task.config);
5019
5017
  const taskId = `${subagentKey}:${Date.now()}`;
5018
+ let release = null;
5020
5019
  this.emitEvent("task_start", task.task);
5021
5020
  this.emitEvent("state_change", {
5022
5021
  previousState: "idle",
@@ -5029,7 +5028,9 @@ ${accumulatedContext}` : accumulatedContext || void 0
5029
5028
  message: `Starting ${task.config.role} task`
5030
5029
  });
5031
5030
  try {
5032
- const subagent = await this.getOrCreateSubagent(task.config);
5031
+ const acquired = await this.acquireSubagent(task.config);
5032
+ const subagent = acquired.subagent;
5033
+ release = acquired.release;
5033
5034
  const prompt = task.context ? `Context:
5034
5035
  ${task.context}
5035
5036
 
@@ -5120,6 +5121,10 @@ ${task.task}` : task.task;
5120
5121
  error: errorMessage,
5121
5122
  latencyMs
5122
5123
  };
5124
+ } finally {
5125
+ if (release) {
5126
+ release();
5127
+ }
5123
5128
  }
5124
5129
  }
5125
5130
  /**
@@ -5142,7 +5147,11 @@ ${task.task}` : task.task;
5142
5147
  * Propagate context from completed tasks
5143
5148
  */
5144
5149
  async propagateContext(results) {
5145
- const contextSummary = results.filter((r) => r.success).map((r) => `[${r.role}]: ${r.content.substring(0, 200)}...`).join("\n");
5150
+ const contextSummary = results.filter((r) => r.success).map((r) => {
5151
+ const truncated = r.content.length > 200;
5152
+ const summary = r.content.substring(0, 200);
5153
+ return `[${r.role}]: ${summary}${truncated ? "..." : ""}`;
5154
+ }).join("\n");
5146
5155
  if (contextSummary && this.orchestrator?.setSharedContext) {
5147
5156
  try {
5148
5157
  await this.orchestrator.setSharedContext(contextSummary);
@@ -5168,7 +5177,7 @@ ${task.task}` : task.task;
5168
5177
  const { createSubagent } = await import('@defai.digital/ax-cli/sdk');
5169
5178
  const subagent = createSubagent(config.role, {
5170
5179
  systemPrompt: config.instructions,
5171
- maxToolRounds: config.maxToolRounds ?? 100
5180
+ maxToolRounds: config.maxToolRounds ?? DEFAULT_SUBAGENT_MAX_TOOL_ROUNDS
5172
5181
  });
5173
5182
  this.subagents.set(key, subagent);
5174
5183
  logger.debug("Created new subagent", {
@@ -5185,11 +5194,70 @@ ${task.task}` : task.task;
5185
5194
  throw error;
5186
5195
  }
5187
5196
  }
5197
+ /**
5198
+ * Create a temporary subagent instance. Used when the cached subagent is busy.
5199
+ */
5200
+ async createEphemeralSubagent(config) {
5201
+ const { createSubagent } = await import('@defai.digital/ax-cli/sdk');
5202
+ return createSubagent(config.role, {
5203
+ systemPrompt: config.instructions,
5204
+ maxToolRounds: config.maxToolRounds ?? DEFAULT_SUBAGENT_MAX_TOOL_ROUNDS
5205
+ });
5206
+ }
5207
+ /**
5208
+ * Acquire a subagent instance for a task. If a cached instance is already
5209
+ * running another task, create a short-lived one to avoid interleaved
5210
+ * streams from concurrent executions.
5211
+ */
5212
+ async acquireSubagent(config) {
5213
+ const key = this.getSubagentKey(config);
5214
+ if (!this.busySubagents.has(key)) {
5215
+ this.busySubagents.add(key);
5216
+ let subagent;
5217
+ try {
5218
+ subagent = await this.getOrCreateSubagent(config);
5219
+ } catch (error) {
5220
+ this.busySubagents.delete(key);
5221
+ throw error;
5222
+ }
5223
+ return {
5224
+ subagent,
5225
+ release: () => this.releaseSubagent(key)
5226
+ };
5227
+ }
5228
+ logger.debug("Cached subagent busy, creating ephemeral instance", { key });
5229
+ const ephemeral = await this.createEphemeralSubagent(config);
5230
+ return {
5231
+ subagent: ephemeral,
5232
+ release: () => {
5233
+ try {
5234
+ if (ephemeral.dispose) {
5235
+ const result = ephemeral.dispose();
5236
+ if (result instanceof Promise) {
5237
+ result.catch((err) => logger.warn("Error disposing ephemeral subagent", { error: err instanceof Error ? err.message : String(err) }));
5238
+ }
5239
+ }
5240
+ } catch (error) {
5241
+ logger.warn("Error disposing ephemeral subagent", {
5242
+ error: error instanceof Error ? error.message : String(error)
5243
+ });
5244
+ }
5245
+ }
5246
+ };
5247
+ }
5248
+ /**
5249
+ * Release a cached subagent so it can be reused.
5250
+ */
5251
+ releaseSubagent(key) {
5252
+ this.busySubagents.delete(key);
5253
+ }
5188
5254
  /**
5189
5255
  * Generate unique key for subagent config
5190
5256
  */
5191
5257
  getSubagentKey(config) {
5192
- return `${config.role}:${config.specialization || "default"}`;
5258
+ const instructionsHash = config.instructions ? createHash("sha256").update(config.instructions).digest("hex").slice(0, 12) : "noinstr";
5259
+ const maxToolRounds = config.maxToolRounds ?? DEFAULT_SUBAGENT_MAX_TOOL_ROUNDS;
5260
+ return `${config.role}:${config.specialization || "default"}:${maxToolRounds}:${instructionsHash}`;
5193
5261
  }
5194
5262
  /**
5195
5263
  * Ensure orchestrator is initialized
@@ -5245,8 +5313,11 @@ ${task.task}` : task.task;
5245
5313
  }
5246
5314
  /**
5247
5315
  * Cleanup all subagents
5316
+ * BUG FIX: Continue cleanup even if individual subagent disposal fails,
5317
+ * and report all errors at the end to ensure no resources are leaked.
5248
5318
  */
5249
5319
  async destroy() {
5320
+ const errors = [];
5250
5321
  for (const [key, subagent] of this.subagents) {
5251
5322
  try {
5252
5323
  if (subagent.dispose) {
@@ -5257,24 +5328,54 @@ ${task.task}` : task.task;
5257
5328
  }
5258
5329
  logger.debug("Subagent disposed", { key });
5259
5330
  } catch (error) {
5331
+ const errorMsg = error instanceof Error ? error.message : String(error);
5260
5332
  logger.warn("Error disposing subagent", {
5261
5333
  key,
5262
- error: error instanceof Error ? error.message : String(error)
5334
+ error: errorMsg
5263
5335
  });
5336
+ errors.push({ key, error: errorMsg });
5264
5337
  }
5265
5338
  }
5339
+ const orchestrator = this.orchestrator;
5266
5340
  this.subagents.clear();
5341
+ this.busySubagents.clear();
5342
+ if (orchestrator && typeof orchestrator.dispose === "function") {
5343
+ try {
5344
+ await orchestrator.dispose();
5345
+ } catch (error) {
5346
+ logger.warn("Error disposing subagent orchestrator", {
5347
+ error: error instanceof Error ? error.message : String(error)
5348
+ });
5349
+ }
5350
+ } else if (orchestrator && typeof orchestrator.shutdown === "function") {
5351
+ try {
5352
+ await orchestrator.shutdown();
5353
+ } catch (error) {
5354
+ logger.warn("Error shutting down subagent orchestrator", {
5355
+ error: error instanceof Error ? error.message : String(error)
5356
+ });
5357
+ }
5358
+ }
5267
5359
  this.orchestrator = null;
5360
+ if (errors.length > 0) {
5361
+ logger.error("SubagentAdapter cleanup had errors", {
5362
+ errorCount: errors.length,
5363
+ errors
5364
+ });
5365
+ }
5268
5366
  logger.debug("SubagentAdapter destroyed");
5269
5367
  }
5270
5368
  };
5271
5369
  }
5272
5370
  });
5273
- var CheckpointAdapter;
5371
+ var DEFAULT_CHECKPOINT_DIR, DEFAULT_MAX_CHECKPOINTS, FLUSH_TIMEOUT_MS, CheckpointAdapter;
5274
5372
  var init_checkpoint_adapter = __esm({
5275
5373
  "src/integrations/ax-cli-sdk/checkpoint-adapter.ts"() {
5276
5374
  init_esm_shims();
5277
5375
  init_logger();
5376
+ DEFAULT_CHECKPOINT_DIR = ".automatosx/checkpoints";
5377
+ DEFAULT_MAX_CHECKPOINTS = 10;
5378
+ FLUSH_TIMEOUT_MS = 5e3;
5278
5379
  CheckpointAdapter = class {
5279
5380
  checkpointDir;
5280
5381
  sdkCheckpointManager = null;
@@ -5282,11 +5383,12 @@ var init_checkpoint_adapter = __esm({
5282
5383
  options;
5283
5384
  autoSaveTimer = null;
5284
5385
  pendingCheckpoint = null;
5386
+ fsLock = Promise.resolve();
5285
5387
  constructor(options = {}) {
5286
5388
  this.options = {
5287
- checkpointDir: options.checkpointDir ?? ".automatosx/checkpoints",
5389
+ checkpointDir: options.checkpointDir ?? DEFAULT_CHECKPOINT_DIR,
5288
5390
  autoSaveInterval: options.autoSaveInterval ?? 0,
5289
- maxCheckpoints: options.maxCheckpoints ?? 10,
5391
+ maxCheckpoints: options.maxCheckpoints ?? DEFAULT_MAX_CHECKPOINTS,
5290
5392
  compress: options.compress ?? false
5291
5393
  };
5292
5394
  this.checkpointDir = this.options.checkpointDir;
@@ -5328,8 +5430,10 @@ var init_checkpoint_adapter = __esm({
5328
5430
  });
5329
5431
  }
5330
5432
  }
5331
- await this.saveToFileSystem(checkpoint);
5332
- await this.cleanupOldCheckpoints(workflowId);
5433
+ await this.withFsLock(async () => {
5434
+ await this.saveToFileSystem(checkpoint);
5435
+ await this.cleanupOldCheckpoints(workflowId);
5436
+ });
5333
5437
  logger.info("Checkpoint saved", {
5334
5438
  workflowId,
5335
5439
  phase: checkpoint.phase,
@@ -5387,7 +5491,7 @@ var init_checkpoint_adapter = __esm({
5387
5491
  });
5388
5492
  }
5389
5493
  }
5390
- await this.deleteFromFileSystem(workflowId);
5494
+ await this.withFsLock(() => this.deleteFromFileSystem(workflowId));
5391
5495
  logger.info("Checkpoints deleted", { workflowId });
5392
5496
  }
5393
5497
  /**
@@ -5395,15 +5499,15 @@ var init_checkpoint_adapter = __esm({
5395
5499
  */
5396
5500
  async list(workflowId) {
5397
5501
  try {
5398
- await fs4.mkdir(this.checkpointDir, { recursive: true });
5399
- const files = await fs4.readdir(this.checkpointDir);
5502
+ await fs5.mkdir(this.checkpointDir, { recursive: true });
5503
+ const files = await fs5.readdir(this.checkpointDir);
5400
5504
  const matchingFiles = files.filter(
5401
- (file) => file.startsWith(workflowId) && file.endsWith(".json")
5505
+ (file) => file.startsWith(`${workflowId}-`) && file.endsWith(".json")
5402
5506
  );
5403
5507
  const results = await Promise.all(
5404
5508
  matchingFiles.map(async (file) => {
5405
5509
  try {
5406
- const content = await fs4.readFile(
5510
+ const content = await fs5.readFile(
5407
5511
  path4.join(this.checkpointDir, file),
5408
5512
  "utf-8"
5409
5513
  );
@@ -5433,6 +5537,13 @@ var init_checkpoint_adapter = __esm({
5433
5537
  async savePhase(workflowId, phaseId, result, workflow) {
5434
5538
  let checkpoint = await this.load(workflowId);
5435
5539
  const phaseIndex = workflow.phases.findIndex((p) => p.id === phaseId);
5540
+ if (phaseIndex === -1) {
5541
+ logger.warn("Phase not found in workflow", {
5542
+ workflowId,
5543
+ phaseId,
5544
+ availablePhases: workflow.phases.map((p) => p.id)
5545
+ });
5546
+ }
5436
5547
  if (!checkpoint) {
5437
5548
  checkpoint = {
5438
5549
  id: `${workflowId}-${Date.now()}`,
@@ -5449,9 +5560,12 @@ var init_checkpoint_adapter = __esm({
5449
5560
  }
5450
5561
  if (result.success) {
5451
5562
  checkpoint.completedTasks.push(phaseId);
5452
- checkpoint.phase = phaseIndex + 1;
5563
+ if (phaseIndex >= 0) {
5564
+ checkpoint.phase = phaseIndex + 1;
5565
+ }
5566
+ const phaseLabel = phaseIndex >= 0 ? `Phase ${phaseIndex + 1}` : "Unknown Phase";
5453
5567
  checkpoint.context += `
5454
- [Phase ${phaseIndex + 1}: ${phaseId}]
5568
+ [${phaseLabel}: ${phaseId}]
5455
5569
  ${result.content.substring(0, 1e3)}
5456
5570
  `;
5457
5571
  if (result.tokensUsed && checkpoint.tokensUsed) {
@@ -5498,11 +5612,11 @@ ${result.content.substring(0, 1e3)}
5498
5612
  await this.sdkCheckpointManager.delete(workflowId);
5499
5613
  }
5500
5614
  async saveToFileSystem(checkpoint) {
5501
- await fs4.mkdir(this.checkpointDir, { recursive: true });
5615
+ await fs5.mkdir(this.checkpointDir, { recursive: true });
5502
5616
  const filename = `${checkpoint.workflowId}-${checkpoint.phase}.json`;
5503
5617
  const filepath = path4.join(this.checkpointDir, filename);
5504
5618
  const content = JSON.stringify(checkpoint, null, 2);
5505
- await fs4.writeFile(filepath, content, "utf-8");
5619
+ await this.atomicWrite(filepath, content);
5506
5620
  }
5507
5621
  async loadFromFileSystem(workflowId) {
5508
5622
  try {
@@ -5514,10 +5628,10 @@ ${result.content.substring(0, 1e3)}
5514
5628
  }
5515
5629
  async deleteFromFileSystem(workflowId) {
5516
5630
  try {
5517
- const files = await fs4.readdir(this.checkpointDir);
5631
+ const files = await fs5.readdir(this.checkpointDir);
5518
5632
  for (const file of files) {
5519
- if (file.startsWith(workflowId) && file.endsWith(".json")) {
5520
- await fs4.unlink(path4.join(this.checkpointDir, file));
5633
+ if (file.startsWith(`${workflowId}-`) && file.endsWith(".json")) {
5634
+ await fs5.unlink(path4.join(this.checkpointDir, file));
5521
5635
  }
5522
5636
  }
5523
5637
  } catch (error) {
@@ -5535,7 +5649,7 @@ ${result.content.substring(0, 1e3)}
5535
5649
  for (const checkpoint of toDelete) {
5536
5650
  try {
5537
5651
  const filename = `${checkpoint.workflowId}-${checkpoint.phase}.json`;
5538
- await fs4.unlink(path4.join(this.checkpointDir, filename));
5652
+ await fs5.unlink(path4.join(this.checkpointDir, filename));
5539
5653
  } catch {
5540
5654
  }
5541
5655
  }
@@ -5559,8 +5673,11 @@ ${result.content.substring(0, 1e3)}
5559
5673
  }
5560
5674
  }
5561
5675
  setupAutoSave() {
5676
+ let autoSaveRunning = false;
5562
5677
  this.autoSaveTimer = setInterval(async () => {
5678
+ if (autoSaveRunning) return;
5563
5679
  if (this.pendingCheckpoint) {
5680
+ autoSaveRunning = true;
5564
5681
  try {
5565
5682
  await this.save(
5566
5683
  this.pendingCheckpoint.workflowId,
@@ -5571,6 +5688,8 @@ ${result.content.substring(0, 1e3)}
5571
5688
  logger.warn("Auto-save failed", {
5572
5689
  error: error instanceof Error ? error.message : String(error)
5573
5690
  });
5691
+ } finally {
5692
+ autoSaveRunning = false;
5574
5693
  }
5575
5694
  }
5576
5695
  }, this.options.autoSaveInterval);
@@ -5584,6 +5703,7 @@ ${result.content.substring(0, 1e3)}
5584
5703
  /**
5585
5704
  * Cleanup resources
5586
5705
  * BUG FIX: Flush pending checkpoint before destroying to prevent data loss
5706
+ * BUG FIX: Add timeout to prevent hanging during cleanup
5587
5707
  */
5588
5708
  async destroy() {
5589
5709
  if (this.autoSaveTimer) {
@@ -5592,10 +5712,15 @@ ${result.content.substring(0, 1e3)}
5592
5712
  }
5593
5713
  if (this.pendingCheckpoint) {
5594
5714
  try {
5595
- await this.save(
5596
- this.pendingCheckpoint.workflowId,
5597
- this.pendingCheckpoint
5598
- );
5715
+ await Promise.race([
5716
+ this.save(
5717
+ this.pendingCheckpoint.workflowId,
5718
+ this.pendingCheckpoint
5719
+ ),
5720
+ new Promise(
5721
+ (_, reject) => setTimeout(() => reject(new Error("Checkpoint flush timed out")), FLUSH_TIMEOUT_MS)
5722
+ )
5723
+ ]);
5599
5724
  logger.debug("Pending checkpoint flushed on destroy", {
5600
5725
  workflowId: this.pendingCheckpoint.workflowId
5601
5726
  });
@@ -5609,12 +5734,44 @@ ${result.content.substring(0, 1e3)}
5609
5734
  this.sdkCheckpointManager = null;
5610
5735
  logger.debug("CheckpointAdapter destroyed");
5611
5736
  }
5737
+ /**
5738
+ * Serialize filesystem operations to avoid race conditions between auto-save and manual saves.
5739
+ */
5740
+ async withFsLock(fn) {
5741
+ const resultPromise = this.fsLock.then(fn, fn);
5742
+ this.fsLock = resultPromise.then(
5743
+ () => Promise.resolve(),
5744
+ () => Promise.resolve()
5745
+ );
5746
+ return resultPromise;
5747
+ }
5748
+ /**
5749
+ * Write checkpoint atomically to avoid partial files being read by list/load.
5750
+ * BUG FIX: Clean up temp file on rename failure to prevent resource leak.
5751
+ */
5752
+ async atomicWrite(filepath, content) {
5753
+ const tempFile = `${filepath}.tmp-${Date.now()}-${Math.random().toString(16).slice(2)}`;
5754
+ await fs5.writeFile(tempFile, content, "utf-8");
5755
+ try {
5756
+ await fs5.rename(tempFile, filepath);
5757
+ } catch (renameError) {
5758
+ try {
5759
+ await fs5.unlink(tempFile);
5760
+ } catch {
5761
+ }
5762
+ throw renameError;
5763
+ }
5764
+ }
5612
5765
  };
5613
5766
  }
5614
5767
  });
5615
5768
  function getInstructionsBridge(options) {
5616
5769
  if (!defaultBridge) {
5617
5770
  defaultBridge = new InstructionsBridge(options);
5771
+ } else if (options) {
5772
+ logger.warn("InstructionsBridge already initialized, ignoring new options", {
5773
+ hint: "Use resetInstructionsBridge() to recreate with new options"
5774
+ });
5618
5775
  }
5619
5776
  return defaultBridge;
5620
5777
  }
@@ -5646,8 +5803,9 @@ var init_instructions_bridge = __esm({
5646
5803
  * @returns Combined instructions from all sources
5647
5804
  */
5648
5805
  async getInstructions(agentName, additionalContext) {
5806
+ const cacheSignature = await this.buildCacheSignature(agentName);
5649
5807
  const cached = this.cache.get(agentName);
5650
- if (cached && Date.now() - cached.timestamp < this.CACHE_TTL) {
5808
+ if (cached && cached.signature === cacheSignature && Date.now() - cached.timestamp < this.CACHE_TTL) {
5651
5809
  logger.debug("Using cached instructions", { agentName });
5652
5810
  if (additionalContext) {
5653
5811
  return {
@@ -5685,7 +5843,11 @@ var init_instructions_bridge = __esm({
5685
5843
  projectMemory: !!projectContext
5686
5844
  }
5687
5845
  };
5688
- this.cache.set(agentName, { instructions: combined, timestamp: Date.now() });
5846
+ this.cache.set(agentName, {
5847
+ instructions: combined,
5848
+ timestamp: Date.now(),
5849
+ signature: cacheSignature
5850
+ });
5689
5851
  logger.info("Instructions combined", {
5690
5852
  agentName,
5691
5853
  sources: combined.sources,
@@ -5726,7 +5888,7 @@ var init_instructions_bridge = __esm({
5726
5888
  async loadAgentProfile(agentName) {
5727
5889
  const profilePath = path4.join(this.options.agentsDir, `${agentName}.ax.yaml`);
5728
5890
  try {
5729
- const content = await fs4.readFile(profilePath, "utf-8");
5891
+ const content = await fs5.readFile(profilePath, "utf-8");
5730
5892
  const profile = this.parseYamlProfile(content);
5731
5893
  logger.debug("Agent profile loaded", { agentName, profilePath });
5732
5894
  return profile;
@@ -5761,7 +5923,7 @@ var init_instructions_bridge = __esm({
5761
5923
  }
5762
5924
  }
5763
5925
  try {
5764
- const content = await fs4.readFile(this.options.axCliCustomPath, "utf-8");
5926
+ const content = await fs5.readFile(this.options.axCliCustomPath, "utf-8");
5765
5927
  logger.debug("Custom instructions loaded from file", {
5766
5928
  path: this.options.axCliCustomPath
5767
5929
  });
@@ -5880,8 +6042,8 @@ ${profile.expertise.map((e) => `- ${e}`).join("\n")}
5880
6042
  ${profile.instructions}
5881
6043
  `;
5882
6044
  try {
5883
- await fs4.mkdir(path4.dirname(this.options.axCliCustomPath), { recursive: true });
5884
- await fs4.writeFile(this.options.axCliCustomPath, customContent, "utf-8");
6045
+ await fs5.mkdir(path4.dirname(this.options.axCliCustomPath), { recursive: true });
6046
+ await fs5.writeFile(this.options.axCliCustomPath, customContent, "utf-8");
5885
6047
  logger.info("Agent synced to ax-cli custom instructions", {
5886
6048
  agentName,
5887
6049
  path: this.options.axCliCustomPath
@@ -5923,6 +6085,26 @@ ${profile.instructions}
5923
6085
  this.cache.delete(agentName);
5924
6086
  logger.debug("Agent cache cleared", { agentName });
5925
6087
  }
6088
+ /**
6089
+ * Build a cache signature from underlying file mtimes to invalidate cache when
6090
+ * agent profiles or custom instructions change on disk.
6091
+ */
6092
+ async buildCacheSignature(agentName) {
6093
+ const profilePath = path4.join(this.options.agentsDir, `${agentName}.ax.yaml`);
6094
+ const [profileSig, customSig] = await Promise.all([
6095
+ this.getFileSignature(profilePath),
6096
+ this.getFileSignature(this.options.axCliCustomPath)
6097
+ ]);
6098
+ return [profileSig, customSig, this.options.includeProjectMemory ? "mem" : "nomem"].join("|");
6099
+ }
6100
+ async getFileSignature(filePath) {
6101
+ try {
6102
+ const stats = await fs5.stat(filePath);
6103
+ return `${stats.mtimeMs}:${stats.size}`;
6104
+ } catch {
6105
+ return "missing";
6106
+ }
6107
+ }
5926
6108
  };
5927
6109
  defaultBridge = null;
5928
6110
  }
@@ -5932,14 +6114,19 @@ ${profile.instructions}
5932
6114
  function getAxCliMCPManager(options) {
5933
6115
  if (!defaultManager2) {
5934
6116
  defaultManager2 = new AxCliMCPManager(options);
6117
+ } else if (options) {
6118
+ logger.warn("AxCliMCPManager already initialized, ignoring new options", {
6119
+ hint: "Use resetAxCliMCPManager() to recreate with new options"
6120
+ });
5935
6121
  }
5936
6122
  return defaultManager2;
5937
6123
  }
5938
- var AxCliMCPManager, defaultManager2;
6124
+ var SDK_NOT_AVAILABLE_ERROR, AxCliMCPManager, defaultManager2;
5939
6125
  var init_mcp_manager = __esm({
5940
6126
  "src/integrations/ax-cli-sdk/mcp-manager.ts"() {
5941
6127
  init_esm_shims();
5942
6128
  init_logger();
6129
+ SDK_NOT_AVAILABLE_ERROR = "ax-cli SDK not available";
5943
6130
  AxCliMCPManager = class {
5944
6131
  sdkAvailable = null;
5945
6132
  mcpModule = null;
@@ -5976,7 +6163,7 @@ var init_mcp_manager = __esm({
5976
6163
  async getTemplateNames() {
5977
6164
  try {
5978
6165
  if (!await this.isAvailable()) {
5979
- return { ok: false, error: new Error("ax-cli SDK not available") };
6166
+ return { ok: false, error: new Error(SDK_NOT_AVAILABLE_ERROR) };
5980
6167
  }
5981
6168
  const { MCPManager } = this.mcpModule;
5982
6169
  if (MCPManager?.getTemplateNames) {
@@ -6013,7 +6200,7 @@ var init_mcp_manager = __esm({
6013
6200
  async getTemplate(name) {
6014
6201
  try {
6015
6202
  if (!await this.isAvailable()) {
6016
- return { ok: false, error: new Error("ax-cli SDK not available") };
6203
+ return { ok: false, error: new Error(SDK_NOT_AVAILABLE_ERROR) };
6017
6204
  }
6018
6205
  const { MCPManager } = this.mcpModule;
6019
6206
  if (MCPManager?.getTemplate) {
@@ -6037,7 +6224,7 @@ var init_mcp_manager = __esm({
6037
6224
  async getTemplatesByCategory(category) {
6038
6225
  try {
6039
6226
  if (!await this.isAvailable()) {
6040
- return { ok: false, error: new Error("ax-cli SDK not available") };
6227
+ return { ok: false, error: new Error(SDK_NOT_AVAILABLE_ERROR) };
6041
6228
  }
6042
6229
  const { MCPManager } = this.mcpModule;
6043
6230
  if (MCPManager?.getTemplatesByCategory) {
@@ -6058,7 +6245,7 @@ var init_mcp_manager = __esm({
6058
6245
  async searchTemplates(keyword) {
6059
6246
  try {
6060
6247
  if (!await this.isAvailable()) {
6061
- return { ok: false, error: new Error("ax-cli SDK not available") };
6248
+ return { ok: false, error: new Error(SDK_NOT_AVAILABLE_ERROR) };
6062
6249
  }
6063
6250
  const { MCPManager } = this.mcpModule;
6064
6251
  if (MCPManager?.searchTemplates) {
@@ -6079,7 +6266,7 @@ var init_mcp_manager = __esm({
6079
6266
  async generateConfigFromTemplate(templateName, env) {
6080
6267
  try {
6081
6268
  if (!await this.isAvailable()) {
6082
- return { ok: false, error: new Error("ax-cli SDK not available") };
6269
+ return { ok: false, error: new Error(SDK_NOT_AVAILABLE_ERROR) };
6083
6270
  }
6084
6271
  const { MCPManager } = this.mcpModule;
6085
6272
  if (MCPManager?.generateConfigFromTemplate) {
@@ -6100,7 +6287,7 @@ var init_mcp_manager = __esm({
6100
6287
  async loadConfig() {
6101
6288
  try {
6102
6289
  if (!await this.isAvailable()) {
6103
- return { ok: false, error: new Error("ax-cli SDK not available") };
6290
+ return { ok: false, error: new Error(SDK_NOT_AVAILABLE_ERROR) };
6104
6291
  }
6105
6292
  const { MCPManager } = this.mcpModule;
6106
6293
  if (MCPManager?.loadMCPConfig) {
@@ -6121,7 +6308,7 @@ var init_mcp_manager = __esm({
6121
6308
  async addServer(name, config) {
6122
6309
  try {
6123
6310
  if (!await this.isAvailable()) {
6124
- return { ok: false, error: new Error("ax-cli SDK not available") };
6311
+ return { ok: false, error: new Error(SDK_NOT_AVAILABLE_ERROR) };
6125
6312
  }
6126
6313
  const { MCPManager } = this.mcpModule;
6127
6314
  if (MCPManager?.addMCPServer) {
@@ -6143,7 +6330,7 @@ var init_mcp_manager = __esm({
6143
6330
  async removeServer(name) {
6144
6331
  try {
6145
6332
  if (!await this.isAvailable()) {
6146
- return { ok: false, error: new Error("ax-cli SDK not available") };
6333
+ return { ok: false, error: new Error(SDK_NOT_AVAILABLE_ERROR) };
6147
6334
  }
6148
6335
  const { MCPManager } = this.mcpModule;
6149
6336
  if (MCPManager?.removeMCPServer) {
@@ -6165,7 +6352,7 @@ var init_mcp_manager = __esm({
6165
6352
  async getPredefinedServers() {
6166
6353
  try {
6167
6354
  if (!await this.isAvailable()) {
6168
- return { ok: false, error: new Error("ax-cli SDK not available") };
6355
+ return { ok: false, error: new Error(SDK_NOT_AVAILABLE_ERROR) };
6169
6356
  }
6170
6357
  const { MCPManager } = this.mcpModule;
6171
6358
  if (MCPManager?.PREDEFINED_SERVERS) {
@@ -6217,7 +6404,7 @@ var init_mcp_manager = __esm({
6217
6404
  async getServerStatus(name) {
6218
6405
  try {
6219
6406
  if (!await this.isAvailable()) {
6220
- return { ok: false, error: new Error("ax-cli SDK not available") };
6407
+ return { ok: false, error: new Error(SDK_NOT_AVAILABLE_ERROR) };
6221
6408
  }
6222
6409
  const { MCPManagerV2 } = this.mcpModule;
6223
6410
  if (MCPManagerV2?.getServerStatus) {
@@ -6251,7 +6438,7 @@ var init_mcp_manager = __esm({
6251
6438
  async getAllServerStatuses() {
6252
6439
  try {
6253
6440
  if (!await this.isAvailable()) {
6254
- return { ok: false, error: new Error("ax-cli SDK not available") };
6441
+ return { ok: false, error: new Error(SDK_NOT_AVAILABLE_ERROR) };
6255
6442
  }
6256
6443
  const { MCPManagerV2 } = this.mcpModule;
6257
6444
  if (MCPManagerV2?.getAllServerStatuses) {
@@ -6275,7 +6462,7 @@ var init_mcp_manager = __esm({
6275
6462
  async healthCheck() {
6276
6463
  try {
6277
6464
  if (!await this.isAvailable()) {
6278
- return { ok: false, error: new Error("ax-cli SDK not available") };
6465
+ return { ok: false, error: new Error(SDK_NOT_AVAILABLE_ERROR) };
6279
6466
  }
6280
6467
  const { MCPManagerV2 } = this.mcpModule;
6281
6468
  if (MCPManagerV2?.healthCheck) {
@@ -6300,7 +6487,7 @@ var init_mcp_manager = __esm({
6300
6487
  async startServer(name) {
6301
6488
  try {
6302
6489
  if (!await this.isAvailable()) {
6303
- return { ok: false, error: new Error("ax-cli SDK not available") };
6490
+ return { ok: false, error: new Error(SDK_NOT_AVAILABLE_ERROR) };
6304
6491
  }
6305
6492
  const { MCPManagerV2 } = this.mcpModule;
6306
6493
  if (MCPManagerV2?.startServer) {
@@ -6315,9 +6502,16 @@ var init_mcp_manager = __esm({
6315
6502
  }
6316
6503
  return { ok: false, error: new Error("startServer not available in SDK") };
6317
6504
  } catch (error) {
6505
+ const errorMessage = error instanceof Error ? error.message : String(error);
6506
+ this.serverStatuses.set(name, {
6507
+ name,
6508
+ status: "error",
6509
+ lastHealthCheck: /* @__PURE__ */ new Date(),
6510
+ error: errorMessage
6511
+ });
6318
6512
  return {
6319
6513
  ok: false,
6320
- error: error instanceof Error ? error : new Error(String(error))
6514
+ error: error instanceof Error ? error : new Error(errorMessage)
6321
6515
  };
6322
6516
  }
6323
6517
  }
@@ -6327,7 +6521,7 @@ var init_mcp_manager = __esm({
6327
6521
  async stopServer(name) {
6328
6522
  try {
6329
6523
  if (!await this.isAvailable()) {
6330
- return { ok: false, error: new Error("ax-cli SDK not available") };
6524
+ return { ok: false, error: new Error(SDK_NOT_AVAILABLE_ERROR) };
6331
6525
  }
6332
6526
  const { MCPManagerV2 } = this.mcpModule;
6333
6527
  if (MCPManagerV2?.stopServer) {
@@ -6342,9 +6536,16 @@ var init_mcp_manager = __esm({
6342
6536
  }
6343
6537
  return { ok: false, error: new Error("stopServer not available in SDK") };
6344
6538
  } catch (error) {
6539
+ const errorMessage = error instanceof Error ? error.message : String(error);
6540
+ this.serverStatuses.set(name, {
6541
+ name,
6542
+ status: "error",
6543
+ lastHealthCheck: /* @__PURE__ */ new Date(),
6544
+ error: errorMessage
6545
+ });
6345
6546
  return {
6346
6547
  ok: false,
6347
- error: error instanceof Error ? error : new Error(String(error))
6548
+ error: error instanceof Error ? error : new Error(errorMessage)
6348
6549
  };
6349
6550
  }
6350
6551
  }
@@ -6354,7 +6555,7 @@ var init_mcp_manager = __esm({
6354
6555
  async restartServer(name) {
6355
6556
  try {
6356
6557
  if (!await this.isAvailable()) {
6357
- return { ok: false, error: new Error("ax-cli SDK not available") };
6558
+ return { ok: false, error: new Error(SDK_NOT_AVAILABLE_ERROR) };
6358
6559
  }
6359
6560
  const { MCPManagerV2 } = this.mcpModule;
6360
6561
  if (MCPManagerV2?.restartServer) {
@@ -6373,9 +6574,16 @@ var init_mcp_manager = __esm({
6373
6574
  }
6374
6575
  return this.startServer(name);
6375
6576
  } catch (error) {
6577
+ const errorMessage = error instanceof Error ? error.message : String(error);
6578
+ this.serverStatuses.set(name, {
6579
+ name,
6580
+ status: "error",
6581
+ lastHealthCheck: /* @__PURE__ */ new Date(),
6582
+ error: errorMessage
6583
+ });
6376
6584
  return {
6377
6585
  ok: false,
6378
- error: error instanceof Error ? error : new Error(String(error))
6586
+ error: error instanceof Error ? error : new Error(errorMessage)
6379
6587
  };
6380
6588
  }
6381
6589
  }
@@ -6385,7 +6593,7 @@ var init_mcp_manager = __esm({
6385
6593
  async shutdown() {
6386
6594
  try {
6387
6595
  if (!await this.isAvailable()) {
6388
- return { ok: false, error: new Error("ax-cli SDK not available") };
6596
+ return { ok: false, error: new Error(SDK_NOT_AVAILABLE_ERROR) };
6389
6597
  }
6390
6598
  const { MCPManagerV2 } = this.mcpModule;
6391
6599
  if (MCPManagerV2?.shutdown) {
@@ -6420,7 +6628,7 @@ var init_mcp_manager = __esm({
6420
6628
  });
6421
6629
 
6422
6630
  // src/integrations/ax-cli-sdk/adapter.ts
6423
- var AxCliSdkAdapter;
6631
+ var DEFAULT_MAX_TOOL_ROUNDS, AxCliSdkAdapter;
6424
6632
  var init_adapter2 = __esm({
6425
6633
  "src/integrations/ax-cli-sdk/adapter.ts"() {
6426
6634
  init_esm_shims();
@@ -6431,10 +6639,13 @@ var init_adapter2 = __esm({
6431
6639
  init_instructions_bridge();
6432
6640
  init_mcp_manager();
6433
6641
  init_mcp_manager();
6642
+ DEFAULT_MAX_TOOL_ROUNDS = 400;
6434
6643
  AxCliSdkAdapter = class _AxCliSdkAdapter {
6435
6644
  agent = null;
6436
6645
  // Will type as LLMAgent after import
6437
6646
  agentConfig = null;
6647
+ initPromise = null;
6648
+ executionLock = Promise.resolve();
6438
6649
  reuseEnabled;
6439
6650
  streamingEnabled;
6440
6651
  sdkAvailable = null;
@@ -6457,6 +6668,9 @@ var init_adapter2 = __esm({
6457
6668
  /**
6458
6669
  * Get or create SubagentAdapter for parallel multi-agent execution
6459
6670
  *
6671
+ * BUG FIX: Log warning when options are provided but adapter already exists,
6672
+ * as the options will be ignored.
6673
+ *
6460
6674
  * @example
6461
6675
  * ```typescript
6462
6676
  * const subagents = adapter.getSubagentAdapter();
@@ -6470,6 +6684,10 @@ var init_adapter2 = __esm({
6470
6684
  if (!this.subagentAdapter) {
6471
6685
  this.subagentAdapter = new SubagentAdapter(options);
6472
6686
  logger.debug("SubagentAdapter created");
6687
+ } else if (options) {
6688
+ logger.warn("SubagentAdapter already exists, ignoring new options", {
6689
+ hint: "Call destroy() first to recreate with new options"
6690
+ });
6473
6691
  }
6474
6692
  return this.subagentAdapter;
6475
6693
  }
@@ -6495,6 +6713,9 @@ var init_adapter2 = __esm({
6495
6713
  /**
6496
6714
  * Get or create CheckpointAdapter for resumable workflows
6497
6715
  *
6716
+ * BUG FIX: Log warning when options are provided but adapter already exists,
6717
+ * as the options will be ignored.
6718
+ *
6498
6719
  * @example
6499
6720
  * ```typescript
6500
6721
  * const checkpoints = adapter.getCheckpointAdapter();
@@ -6506,6 +6727,10 @@ var init_adapter2 = __esm({
6506
6727
  if (!this.checkpointAdapter) {
6507
6728
  this.checkpointAdapter = new CheckpointAdapter(options);
6508
6729
  logger.debug("CheckpointAdapter created");
6730
+ } else if (options) {
6731
+ logger.warn("CheckpointAdapter already exists, ignoring new options", {
6732
+ hint: "Call destroy() first to recreate with new options"
6733
+ });
6509
6734
  }
6510
6735
  return this.checkpointAdapter;
6511
6736
  }
@@ -6545,6 +6770,9 @@ var init_adapter2 = __esm({
6545
6770
  /**
6546
6771
  * Get or create InstructionsBridge for unified agent instructions
6547
6772
  *
6773
+ * BUG FIX: Log warning when options are provided but bridge already exists,
6774
+ * as the options will be ignored.
6775
+ *
6548
6776
  * @example
6549
6777
  * ```typescript
6550
6778
  * const bridge = adapter.getInstructionsBridge();
@@ -6556,6 +6784,10 @@ var init_adapter2 = __esm({
6556
6784
  if (!this.instructionsBridge) {
6557
6785
  this.instructionsBridge = getInstructionsBridge(options);
6558
6786
  logger.debug("InstructionsBridge created");
6787
+ } else if (options) {
6788
+ logger.warn("InstructionsBridge already exists, ignoring new options", {
6789
+ hint: "Call destroy() first to recreate with new options"
6790
+ });
6559
6791
  }
6560
6792
  return this.instructionsBridge;
6561
6793
  }
@@ -6580,6 +6812,9 @@ var init_adapter2 = __esm({
6580
6812
  /**
6581
6813
  * Get or create MCP Manager for ax-cli MCP server management
6582
6814
  *
6815
+ * BUG FIX: Log warning when options are provided but manager already exists,
6816
+ * as the options will be ignored.
6817
+ *
6583
6818
  * @example
6584
6819
  * ```typescript
6585
6820
  * const mcp = adapter.getMCPManager();
@@ -6591,6 +6826,10 @@ var init_adapter2 = __esm({
6591
6826
  if (!this.mcpManager) {
6592
6827
  this.mcpManager = getAxCliMCPManager(options);
6593
6828
  logger.debug("AxCliMCPManager created");
6829
+ } else if (options) {
6830
+ logger.warn("AxCliMCPManager already exists, ignoring new options", {
6831
+ hint: "Call destroy() first to recreate with new options"
6832
+ });
6594
6833
  }
6595
6834
  return this.mcpManager;
6596
6835
  }
@@ -6636,15 +6875,28 @@ var init_adapter2 = __esm({
6636
6875
  * Performance: ~5ms overhead vs ~50-200ms for CLI spawning
6637
6876
  */
6638
6877
  async execute(prompt, options) {
6878
+ return this.runExclusive(() => this.executeInternal(prompt, options));
6879
+ }
6880
+ /**
6881
+ * Serialize executions to avoid chat history corruption and token mis-tracking
6882
+ * when the same adapter instance is used concurrently.
6883
+ */
6884
+ async runExclusive(fn) {
6885
+ const resultPromise = this.executionLock.then(fn, fn);
6886
+ this.executionLock = resultPromise.then(
6887
+ () => Promise.resolve(),
6888
+ () => Promise.resolve()
6889
+ );
6890
+ return resultPromise;
6891
+ }
6892
+ async executeInternal(prompt, options) {
6639
6893
  const startTime = Date.now();
6640
6894
  let totalTokens = 0;
6641
6895
  try {
6642
6896
  if (!await this.ensureSDKAvailable()) {
6643
6897
  throw new Error("ax-cli SDK not available. Install with: npm install @defai.digital/ax-cli");
6644
6898
  }
6645
- if (!this.agent || this.hasConfigChanged(options)) {
6646
- await this.initializeAgent(options);
6647
- }
6899
+ await this.ensureAgent(options);
6648
6900
  logger.debug("Executing via SDK (streaming mode for token tracking)", {
6649
6901
  promptLength: prompt.length,
6650
6902
  userWantsCallbacks: !!(options.onStream || options.onTool),
@@ -6728,10 +6980,11 @@ var init_adapter2 = __esm({
6728
6980
  * We do NOT pass credentials to the SDK - it manages its own configuration.
6729
6981
  */
6730
6982
  async initializeAgent(options) {
6983
+ await this.destroyAgentInstance();
6731
6984
  const { createAgent } = await import('@defai.digital/ax-cli/sdk');
6732
6985
  try {
6733
6986
  const config = {
6734
- maxToolRounds: options.maxToolRounds || 400
6987
+ maxToolRounds: options.maxToolRounds || DEFAULT_MAX_TOOL_ROUNDS
6735
6988
  };
6736
6989
  logger.debug("Creating SDK agent (credentials from ax-cli settings)", {
6737
6990
  maxToolRounds: config.maxToolRounds,
@@ -6793,22 +7046,50 @@ var init_adapter2 = __esm({
6793
7046
  */
6794
7047
  hasConfigChanged(options) {
6795
7048
  if (!this.agentConfig) return true;
6796
- const changed = this.agentConfig.maxToolRounds !== (options.maxToolRounds || 400);
7049
+ const changed = this.agentConfig.maxToolRounds !== (options.maxToolRounds || DEFAULT_MAX_TOOL_ROUNDS);
6797
7050
  if (changed) {
6798
7051
  logger.debug("Agent config changed, will reinitialize", {
6799
7052
  oldMaxToolRounds: this.agentConfig.maxToolRounds,
6800
- newMaxToolRounds: options.maxToolRounds || 400,
7053
+ newMaxToolRounds: options.maxToolRounds || DEFAULT_MAX_TOOL_ROUNDS,
6801
7054
  note: "SDK credentials managed by ax-cli setup"
6802
7055
  });
6803
7056
  }
6804
7057
  return changed;
6805
7058
  }
7059
+ /**
7060
+ * Ensure agent is initialized exactly once even if execute() is called
7061
+ * concurrently. Reinitializes when config changes.
7062
+ *
7063
+ * BUG FIX: If config changes while initialization is in progress, we need to
7064
+ * wait for current init to complete, then reinitialize with new config.
7065
+ */
7066
+ async ensureAgent(options) {
7067
+ if (this.agent && !this.hasConfigChanged(options)) {
7068
+ return;
7069
+ }
7070
+ if (this.initPromise) {
7071
+ await this.initPromise;
7072
+ if (this.agent && !this.hasConfigChanged(options)) {
7073
+ return;
7074
+ }
7075
+ }
7076
+ this.initPromise = this.initializeAgent(options).finally(() => {
7077
+ this.initPromise = null;
7078
+ });
7079
+ await this.initPromise;
7080
+ }
6806
7081
  /**
6807
7082
  * Set up streaming event handlers (for initialization)
7083
+ *
7084
+ * BUG FIX: Remove existing listeners before adding new ones to prevent
7085
+ * listener accumulation when agent is reinitialized.
6808
7086
  */
6809
7087
  setupEventHandlers() {
6810
7088
  if (!this.agent) return;
6811
7089
  try {
7090
+ this.agent.removeAllListeners("stream");
7091
+ this.agent.removeAllListeners("tool");
7092
+ this.agent.removeAllListeners("error");
6812
7093
  this.agent.on("stream", (chunk) => {
6813
7094
  logger.debug("Stream chunk received", {
6814
7095
  type: chunk.type,
@@ -6831,50 +7112,6 @@ var init_adapter2 = __esm({
6831
7112
  });
6832
7113
  }
6833
7114
  }
6834
- /**
6835
- * Set up streaming callbacks for execution
6836
- */
6837
- setupStreamingCallbacks(options) {
6838
- if (!this.agent) return;
6839
- try {
6840
- this.agent.removeAllListeners("stream");
6841
- this.agent.removeAllListeners("tool");
6842
- if (options.onStream) {
6843
- this.agent.on("stream", (chunk) => {
6844
- try {
6845
- options.onStream({
6846
- type: chunk.type || "content",
6847
- content: chunk.content,
6848
- tool: chunk.tool,
6849
- timestamp: (/* @__PURE__ */ new Date()).toISOString()
6850
- });
6851
- } catch (error) {
6852
- logger.warn("Stream callback error", {
6853
- error: error instanceof Error ? error.message : String(error)
6854
- });
6855
- }
6856
- });
6857
- }
6858
- if (options.onTool) {
6859
- this.agent.on("tool", (data) => {
6860
- try {
6861
- options.onTool({
6862
- name: data.name,
6863
- args: data.args
6864
- });
6865
- } catch (error) {
6866
- logger.warn("Tool callback error", {
6867
- error: error instanceof Error ? error.message : String(error)
6868
- });
6869
- }
6870
- });
6871
- }
6872
- } catch (error) {
6873
- logger.warn("Failed to setup streaming callbacks", {
6874
- error: error instanceof Error ? error.message : String(error)
6875
- });
6876
- }
6877
- }
6878
7115
  /**
6879
7116
  * Extract token usage from various sources with priority:
6880
7117
  * 1. SDK events (token_count emissions) - most accurate
@@ -6898,9 +7135,9 @@ var init_adapter2 = __esm({
6898
7135
  }
6899
7136
  const usage = usageObject || {};
6900
7137
  const actualTokens = {
6901
- prompt: usage.prompt_tokens || usage.prompt || usage.input || usage.promptTokens || 0,
6902
- completion: usage.completion_tokens || usage.completion || usage.output || usage.completionTokens || 0,
6903
- total: usage.total_tokens || usage.total || usage.totalTokens || 0
7138
+ prompt: usage.prompt_tokens ?? usage.prompt ?? usage.input ?? usage.promptTokens ?? 0,
7139
+ completion: usage.completion_tokens ?? usage.completion ?? usage.output ?? usage.completionTokens ?? 0,
7140
+ total: usage.total_tokens ?? usage.total ?? usage.totalTokens ?? 0
6904
7141
  };
6905
7142
  if (actualTokens.total > 0) {
6906
7143
  logger.info(`Using token counts from ${sourceName || "usage object"}`, {
@@ -7058,21 +7295,7 @@ var init_adapter2 = __esm({
7058
7295
  * Cleanup resources
7059
7296
  */
7060
7297
  async destroy() {
7061
- if (this.agent) {
7062
- try {
7063
- const result = this.agent.dispose();
7064
- if (result instanceof Promise) {
7065
- await result;
7066
- }
7067
- this.agent = null;
7068
- this.agentConfig = null;
7069
- logger.debug("SDK agent destroyed");
7070
- } catch (error) {
7071
- logger.warn("Error during agent cleanup", {
7072
- error: error instanceof Error ? error.message : String(error)
7073
- });
7074
- }
7075
- }
7298
+ await this.destroyAgentInstance();
7076
7299
  if (this.subagentAdapter) {
7077
7300
  try {
7078
7301
  await this.subagentAdapter.destroy();
@@ -7110,8 +7333,41 @@ var init_adapter2 = __esm({
7110
7333
  }
7111
7334
  }
7112
7335
  if (this.mcpManager) {
7113
- this.mcpManager = null;
7114
- logger.debug("MCP Manager cleared");
7336
+ try {
7337
+ const shutdownResult = await this.mcpManager.shutdown();
7338
+ if (!shutdownResult.ok) {
7339
+ logger.warn("Error while shutting down MCP servers", {
7340
+ error: shutdownResult.error instanceof Error ? shutdownResult.error.message : String(shutdownResult.error)
7341
+ });
7342
+ }
7343
+ } catch (error) {
7344
+ logger.warn("Error during MCP Manager cleanup", {
7345
+ error: error instanceof Error ? error.message : String(error)
7346
+ });
7347
+ } finally {
7348
+ this.mcpManager = null;
7349
+ logger.debug("MCP Manager cleared");
7350
+ }
7351
+ }
7352
+ }
7353
+ /**
7354
+ * Dispose the primary agent without touching ancillary adapters.
7355
+ */
7356
+ async destroyAgentInstance() {
7357
+ if (!this.agent) return;
7358
+ try {
7359
+ const result = this.agent.dispose();
7360
+ if (result instanceof Promise) {
7361
+ await result;
7362
+ }
7363
+ } catch (error) {
7364
+ logger.warn("Error during agent cleanup", {
7365
+ error: error instanceof Error ? error.message : String(error)
7366
+ });
7367
+ } finally {
7368
+ this.agent = null;
7369
+ this.agentConfig = null;
7370
+ logger.debug("SDK agent destroyed");
7115
7371
  }
7116
7372
  }
7117
7373
  };
@@ -7158,10 +7414,13 @@ var init_hybrid_adapter2 = __esm({
7158
7414
  }
7159
7415
  throw new Error(`No adapter available for mode: ${this.mode}`);
7160
7416
  } catch (error) {
7161
- if (this.mode === "auto" && this.activeMode === "sdk" && this.cliAdapter) {
7417
+ if (this.mode === "auto" && this.activeMode === "sdk") {
7162
7418
  logger.warn("SDK execution failed, falling back to CLI", {
7163
7419
  error: error instanceof Error ? error.message : String(error)
7164
7420
  });
7421
+ if (!this.cliAdapter) {
7422
+ this.initializeCli();
7423
+ }
7165
7424
  this.activeMode = "cli";
7166
7425
  return await this.executeCli(prompt, options);
7167
7426
  }
@@ -7303,6 +7562,9 @@ var init_hybrid_adapter2 = __esm({
7303
7562
  }
7304
7563
  /**
7305
7564
  * Get command name
7565
+ *
7566
+ * BUG FIX: Handle 'auto' mode correctly - return 'ax-cli-auto' to indicate
7567
+ * the actual command hasn't been determined yet (will be sdk or cli after initialization)
7306
7568
  */
7307
7569
  getCommand() {
7308
7570
  if (this.activeMode === "sdk") {
@@ -7310,7 +7572,13 @@ var init_hybrid_adapter2 = __esm({
7310
7572
  } else if (this.activeMode === "cli") {
7311
7573
  return "ax-cli";
7312
7574
  }
7313
- return this.mode === "sdk" ? "ax-cli-sdk" : "ax-cli";
7575
+ if (this.mode === "sdk") {
7576
+ return "ax-cli-sdk";
7577
+ } else if (this.mode === "cli") {
7578
+ return "ax-cli";
7579
+ } else {
7580
+ return "ax-cli-auto";
7581
+ }
7314
7582
  }
7315
7583
  /**
7316
7584
  * Get display name
@@ -7331,9 +7599,22 @@ var init_hybrid_adapter2 = __esm({
7331
7599
  }
7332
7600
  /**
7333
7601
  * Force switch to CLI mode (for debugging or fallback)
7602
+ *
7603
+ * BUG FIX: Destroy SDK adapter when switching to CLI to prevent resource leaks
7604
+ * (memory, event listeners) from the unused SDK adapter.
7334
7605
  */
7335
- switchToCliMode() {
7606
+ async switchToCliMode() {
7336
7607
  logger.info("Forcing switch to CLI mode");
7608
+ if (this.sdkAdapter) {
7609
+ try {
7610
+ await this.sdkAdapter.destroy();
7611
+ } catch (error) {
7612
+ logger.warn("Error destroying SDK adapter during mode switch", {
7613
+ error: error instanceof Error ? error.message : String(error)
7614
+ });
7615
+ }
7616
+ this.sdkAdapter = null;
7617
+ }
7337
7618
  this.initializeCli();
7338
7619
  this.activeMode = "cli";
7339
7620
  }
@@ -7353,13 +7634,22 @@ var init_hybrid_adapter2 = __esm({
7353
7634
  }
7354
7635
  /**
7355
7636
  * Cleanup resources
7637
+ * BUG FIX: Use Promise.allSettled to ensure cleanup completes even if SDK destroy fails
7356
7638
  */
7357
7639
  async destroy() {
7358
7640
  const destroyPromises = [];
7359
7641
  if (this.sdkAdapter) {
7360
7642
  destroyPromises.push(this.sdkAdapter.destroy());
7361
7643
  }
7362
- await Promise.all(destroyPromises);
7644
+ const results = await Promise.allSettled(destroyPromises);
7645
+ results.forEach((result, index) => {
7646
+ if (result.status === "rejected") {
7647
+ logger.warn("Adapter cleanup failed", {
7648
+ index,
7649
+ error: result.reason instanceof Error ? result.reason.message : String(result.reason)
7650
+ });
7651
+ }
7652
+ });
7363
7653
  this.sdkAdapter = null;
7364
7654
  this.cliAdapter = null;
7365
7655
  this.activeMode = null;
@@ -7375,7 +7665,7 @@ __export(ax_cli_provider_exports, {
7375
7665
  AxCliProvider: () => AxCliProvider,
7376
7666
  GlmProvider: () => GlmProvider
7377
7667
  });
7378
- var SDK_ADAPTER_UNAVAILABLE_ERROR, AxCliProvider, GlmProvider;
7668
+ var SDK_ADAPTER_UNAVAILABLE_ERROR, DEFAULT_MAX_TOOL_ROUNDS2, AxCliProvider, GlmProvider;
7379
7669
  var init_ax_cli_provider = __esm({
7380
7670
  "src/providers/ax-cli-provider.ts"() {
7381
7671
  init_esm_shims();
@@ -7383,6 +7673,7 @@ var init_ax_cli_provider = __esm({
7383
7673
  init_hybrid_adapter2();
7384
7674
  init_logger();
7385
7675
  SDK_ADAPTER_UNAVAILABLE_ERROR = 'SDK adapter not available. Ensure mode="sdk" or "auto" with SDK installed.';
7676
+ DEFAULT_MAX_TOOL_ROUNDS2 = 400;
7386
7677
  AxCliProvider = class extends BaseProvider {
7387
7678
  adapter;
7388
7679
  config;
@@ -7413,7 +7704,7 @@ var init_ax_cli_provider = __esm({
7413
7704
  const options = {
7414
7705
  model: request.model || axCliConfig.model,
7415
7706
  // Optional model override
7416
- maxToolRounds: axCliConfig.maxToolRounds || 400,
7707
+ maxToolRounds: axCliConfig.maxToolRounds || DEFAULT_MAX_TOOL_ROUNDS2,
7417
7708
  timeout: this.config.timeout,
7418
7709
  // Note: apiKey and baseUrl are ignored by SDK adapter (v3.7.0+)
7419
7710
  // SDK loads credentials from ax-cli setup (~/.ax-cli/config.json)
@@ -7499,9 +7790,11 @@ var init_ax_cli_provider = __esm({
7499
7790
  }
7500
7791
  /**
7501
7792
  * Force switch to CLI mode (for debugging or fallback)
7793
+ *
7794
+ * This method is async because it needs to clean up SDK adapter resources.
7502
7795
  */
7503
- switchToCliMode() {
7504
- this.adapter.switchToCliMode();
7796
+ async switchToCliMode() {
7797
+ await this.adapter.switchToCliMode();
7505
7798
  }
7506
7799
  // ==========================================
7507
7800
  // SDK Advanced Features (v10.4.0)
@@ -7520,7 +7813,7 @@ var init_ax_cli_provider = __esm({
7520
7813
  * ]);
7521
7814
  * ```
7522
7815
  */
7523
- async executeParallelTasks(tasks, options) {
7816
+ async executeParallelTasks(tasks) {
7524
7817
  const sdkAdapter = this.adapter.getSdkAdapter();
7525
7818
  if (!sdkAdapter) {
7526
7819
  throw new Error(SDK_ADAPTER_UNAVAILABLE_ERROR);
@@ -8626,11 +8919,11 @@ var VALIDATION_LIMITS = {
8626
8919
  MAX_PORT: 65535
8627
8920
  // Maximum port number
8628
8921
  };
8629
- function isValidRelativePath(path7) {
8630
- if (!path7 || typeof path7 !== "string") {
8922
+ function isValidRelativePath(path8) {
8923
+ if (!path8 || typeof path8 !== "string") {
8631
8924
  return false;
8632
8925
  }
8633
- const normalizedPath = path7.replace(/\\/g, "/");
8926
+ const normalizedPath = path8.replace(/\\/g, "/");
8634
8927
  if (normalizedPath.startsWith("/")) {
8635
8928
  return false;
8636
8929
  }
@@ -9260,11 +9553,16 @@ var PRECOMPILED_CONFIG = {
9260
9553
  },
9261
9554
  "advanced": {
9262
9555
  "embedding": {
9556
+ "model": "text-embedding-3-small",
9263
9557
  "timeout": 3e4,
9264
9558
  "retryDelay": 1e3,
9265
9559
  "dimensions": 1536,
9266
9560
  "maxRetries": 3
9267
9561
  },
9562
+ "projectContext": {
9563
+ "maxSizeBytes": 102400,
9564
+ "cacheTtlMs": 3e5
9565
+ },
9268
9566
  "security": {
9269
9567
  "enablePathValidation": true,
9270
9568
  "allowedExtensions": [
@@ -9320,7 +9618,23 @@ var PRECOMPILED_CONFIG = {
9320
9618
  "enableFreeTierPrioritization": true,
9321
9619
  "enableWorkloadAwareRouting": true
9322
9620
  },
9323
- "version": "11.3.1"
9621
+ "axCliSdk": {
9622
+ "maxToolRounds": 400,
9623
+ "checkpoint": {
9624
+ "maxCheckpoints": 10,
9625
+ "flushTimeoutMs": 5e3
9626
+ },
9627
+ "subagent": {
9628
+ "maxParallel": 4,
9629
+ "timeoutMs": 3e5,
9630
+ "maxToolRounds": 100
9631
+ },
9632
+ "instructions": {
9633
+ "cacheTtlMs": 3e5,
9634
+ "maxContextLength": 32e3
9635
+ }
9636
+ },
9637
+ "version": "11.3.2"
9324
9638
  };
9325
9639
 
9326
9640
  // src/core/config/schemas.ts
@@ -9347,7 +9661,7 @@ var safeNameSchema = z.string().min(1).max(VALIDATION_LIMITS.MAX_NAME_LENGTH).re
9347
9661
  "Name must be alphanumeric with dash/underscore only"
9348
9662
  ).describe("Safe identifier name");
9349
9663
  var relativePathSchema = z.string().min(1).refine(
9350
- (path7) => !path7.includes("..") && !path7.startsWith("/"),
9664
+ (path8) => !path8.includes("..") && !path8.startsWith("/"),
9351
9665
  "Path must be relative (no ../, no absolute paths)"
9352
9666
  ).describe("Relative path within project");
9353
9667
  var fileExtensionSchema = z.string().regex(
@@ -9687,16 +10001,16 @@ async function loadConfigUncached(projectDir) {
9687
10001
  });
9688
10002
  return config;
9689
10003
  }
9690
- async function loadConfigFile(path7) {
10004
+ async function loadConfigFile(path8) {
9691
10005
  try {
9692
- const content = await readFile(path7, "utf-8");
10006
+ const content = await readFile(path8, "utf-8");
9693
10007
  if (content.length > VALIDATION_LIMITS.MAX_CONFIG_FILE_SIZE) {
9694
10008
  throw ConfigError.parseError(
9695
10009
  new Error(`Config file too large (max ${VALIDATION_LIMITS.MAX_CONFIG_FILE_SIZE / 1024}KB, got ${Math.ceil(content.length / 1024)}KB)`),
9696
- path7
10010
+ path8
9697
10011
  );
9698
10012
  }
9699
- const ext = extname(path7).toLowerCase();
10013
+ const ext = extname(path8).toLowerCase();
9700
10014
  let userConfig;
9701
10015
  try {
9702
10016
  if (ext === ".yaml" || ext === ".yml") {
@@ -9705,7 +10019,7 @@ async function loadConfigFile(path7) {
9705
10019
  userConfig = JSON.parse(content);
9706
10020
  }
9707
10021
  } catch (parseError) {
9708
- throw ConfigError.parseError(parseError, path7);
10022
+ throw ConfigError.parseError(parseError, path8);
9709
10023
  }
9710
10024
  const config = mergeConfig(DEFAULT_CONFIG, userConfig);
9711
10025
  if (config.execution && userConfig.execution?.maxConcurrentAgents === void 0) {
@@ -9721,35 +10035,35 @@ async function loadConfigFile(path7) {
9721
10035
  if (validationErrors.length > 0) {
9722
10036
  throw ConfigError.invalid(
9723
10037
  validationErrors.join("; "),
9724
- { path: path7, errors: validationErrors }
10038
+ { path: path8, errors: validationErrors }
9725
10039
  );
9726
10040
  }
9727
- logger.info("Config loaded successfully", { path: normalizePath(path7), format: ext });
10041
+ logger.info("Config loaded successfully", { path: normalizePath(path8), format: ext });
9728
10042
  return config;
9729
10043
  } catch (error) {
9730
10044
  if (error instanceof ConfigError) {
9731
10045
  throw error;
9732
10046
  }
9733
10047
  if (error.code === "ENOENT") {
9734
- throw ConfigError.notFound(path7);
10048
+ throw ConfigError.notFound(path8);
9735
10049
  }
9736
10050
  if (error.code === "EACCES") {
9737
10051
  throw new ConfigError(
9738
- `Permission denied reading config: ${path7}`,
10052
+ `Permission denied reading config: ${path8}`,
9739
10053
  "E1002" /* CONFIG_PARSE_ERROR */,
9740
10054
  [
9741
10055
  "Check file permissions",
9742
10056
  "Run with appropriate user privileges",
9743
10057
  "Verify the file is accessible"
9744
10058
  ],
9745
- { path: path7, error: error.message }
10059
+ { path: path8, error: error.message }
9746
10060
  );
9747
10061
  }
9748
10062
  throw new ConfigError(
9749
10063
  `Failed to load config: ${error.message}`,
9750
10064
  "E1002" /* CONFIG_PARSE_ERROR */,
9751
10065
  ["Check file format and permissions"],
9752
- { path: path7, originalError: error.message }
10066
+ { path: path8, originalError: error.message }
9753
10067
  );
9754
10068
  }
9755
10069
  }
@@ -9765,8 +10079,8 @@ function validateConfigWithZod(config) {
9765
10079
  return ["Configuration validation failed with unknown error structure"];
9766
10080
  }
9767
10081
  return result.error.issues.map((err) => {
9768
- const path7 = err.path.join(".");
9769
- return `${path7}: ${err.message}`;
10082
+ const path8 = err.path.join(".");
10083
+ return `${path8}: ${err.message}`;
9770
10084
  });
9771
10085
  }
9772
10086
  function validateConfig(config) {
@@ -10152,16 +10466,16 @@ function validateConfig(config) {
10152
10466
  }
10153
10467
  return errors;
10154
10468
  }
10155
- async function saveConfigFile(path7, config) {
10469
+ async function saveConfigFile(path8, config) {
10156
10470
  try {
10157
10471
  const validationErrors = validateConfig(config);
10158
10472
  if (validationErrors.length > 0) {
10159
10473
  throw ConfigError.invalid(
10160
10474
  validationErrors.join("; "),
10161
- { path: path7, errors: validationErrors }
10475
+ { path: path8, errors: validationErrors }
10162
10476
  );
10163
10477
  }
10164
- const ext = extname(path7).toLowerCase();
10478
+ const ext = extname(path8).toLowerCase();
10165
10479
  let content;
10166
10480
  if (ext === ".yaml" || ext === ".yml") {
10167
10481
  content = dump(config, {
@@ -10173,30 +10487,30 @@ async function saveConfigFile(path7, config) {
10173
10487
  } else {
10174
10488
  content = JSON.stringify(config, null, 2);
10175
10489
  }
10176
- await writeFile(path7, content, "utf-8");
10490
+ await writeFile(path8, content, "utf-8");
10177
10491
  configCache.clear();
10178
- logger.info("Config saved successfully", { path: normalizePath(path7), format: ext });
10492
+ logger.info("Config saved successfully", { path: normalizePath(path8), format: ext });
10179
10493
  } catch (error) {
10180
10494
  if (error instanceof ConfigError) {
10181
10495
  throw error;
10182
10496
  }
10183
10497
  if (error.code === "EACCES") {
10184
10498
  throw new ConfigError(
10185
- `Permission denied writing config: ${path7}`,
10499
+ `Permission denied writing config: ${path8}`,
10186
10500
  "E1002" /* CONFIG_PARSE_ERROR */,
10187
10501
  [
10188
10502
  "Check file permissions",
10189
10503
  "Run with appropriate user privileges",
10190
10504
  "Verify the directory is writable"
10191
10505
  ],
10192
- { path: path7, error: error.message }
10506
+ { path: path8, error: error.message }
10193
10507
  );
10194
10508
  }
10195
10509
  throw new ConfigError(
10196
10510
  `Failed to save config: ${error.message}`,
10197
10511
  "E1002" /* CONFIG_PARSE_ERROR */,
10198
10512
  ["Check file path and permissions"],
10199
- { path: path7, originalError: error.message }
10513
+ { path: path8, originalError: error.message }
10200
10514
  );
10201
10515
  }
10202
10516
  }
@@ -10946,10 +11260,10 @@ var configCommand = {
10946
11260
  } else {
10947
11261
  const projectConfig = resolve(process.cwd(), "ax.config.json");
10948
11262
  const hiddenConfig = resolve(process.cwd(), ".automatosx", "config.json");
10949
- const fs7 = await import('fs');
10950
- if (fs7.existsSync(projectConfig)) {
11263
+ const fs8 = await import('fs');
11264
+ if (fs8.existsSync(projectConfig)) {
10951
11265
  configPath = projectConfig;
10952
- } else if (fs7.existsSync(hiddenConfig)) {
11266
+ } else if (fs8.existsSync(hiddenConfig)) {
10953
11267
  configPath = hiddenConfig;
10954
11268
  } else {
10955
11269
  configPath = projectConfig;
@@ -10996,9 +11310,9 @@ var configCommand = {
10996
11310
  }
10997
11311
  }
10998
11312
  };
10999
- async function checkExists(path7) {
11313
+ async function checkExists(path8) {
11000
11314
  try {
11001
- await access$1(path7, constants.F_OK);
11315
+ await access$1(path8, constants.F_OK);
11002
11316
  return true;
11003
11317
  } catch {
11004
11318
  return false;
@@ -11029,7 +11343,7 @@ async function validateConfigFile(config, verbose) {
11029
11343
  }
11030
11344
  console.log();
11031
11345
  }
11032
- async function resetConfig(path7, verbose) {
11346
+ async function resetConfig(path8, verbose) {
11033
11347
  const { createRequire } = await import('module');
11034
11348
  const require2 = createRequire(import.meta.url);
11035
11349
  let version = "11.2.6";
@@ -11044,14 +11358,14 @@ async function resetConfig(path7, verbose) {
11044
11358
  // Users should rely on IDE JSON Schema plugins that fetch from npm package
11045
11359
  version
11046
11360
  };
11047
- await saveConfigFile(path7, config);
11361
+ await saveConfigFile(path8, config);
11048
11362
  printSuccess("Configuration reset to defaults");
11049
11363
  if (verbose) {
11050
11364
  console.log(chalk5.gray(`
11051
- Config file: ${path7}
11365
+ Config file: ${path8}
11052
11366
  `));
11053
11367
  }
11054
- logger.info("Configuration reset", { path: path7 });
11368
+ logger.info("Configuration reset", { path: path8 });
11055
11369
  }
11056
11370
  async function listConfig(config, verbose) {
11057
11371
  console.log(chalk5.bold.cyan("\n\u{1F4CB} AutomatosX Configuration\n"));
@@ -11130,7 +11444,7 @@ async function getConfig(config, key, verbose) {
11130
11444
  }
11131
11445
  }
11132
11446
  }
11133
- async function setConfig(path7, config, key, value, verbose) {
11447
+ async function setConfig(path8, config, key, value, verbose) {
11134
11448
  let parsedValue = value;
11135
11449
  try {
11136
11450
  parsedValue = JSON.parse(value);
@@ -11149,21 +11463,21 @@ async function setConfig(path7, config, key, value, verbose) {
11149
11463
  console.log();
11150
11464
  process.exit(1);
11151
11465
  }
11152
- await saveConfigFile(path7, config);
11466
+ await saveConfigFile(path8, config);
11153
11467
  printSuccess(`Configuration updated: ${key} = ${value}`);
11154
11468
  if (verbose) {
11155
11469
  console.log(chalk5.gray(`
11156
- Config file: ${path7}`));
11470
+ Config file: ${path8}`));
11157
11471
  console.log(chalk5.gray("Configuration validated successfully\n"));
11158
11472
  }
11159
11473
  logger.info("Configuration updated", { key, value });
11160
11474
  }
11161
- function getNestedValue(obj, path7) {
11162
- if (!path7 || !path7.trim()) return void 0;
11163
- return path7.split(".").filter(Boolean).reduce((current, key) => current?.[key], obj);
11475
+ function getNestedValue(obj, path8) {
11476
+ if (!path8 || !path8.trim()) return void 0;
11477
+ return path8.split(".").filter(Boolean).reduce((current, key) => current?.[key], obj);
11164
11478
  }
11165
- function setNestedValue(obj, path7, value) {
11166
- const keys = path7.split(".");
11479
+ function setNestedValue(obj, path8, value) {
11480
+ const keys = path8.split(".");
11167
11481
  const lastKey = keys.pop();
11168
11482
  if (!lastKey) return false;
11169
11483
  const target = keys.reduce((current, key) => {
@@ -13263,7 +13577,7 @@ var setupCommand = {
13263
13577
  let version = "11.2.6";
13264
13578
  try {
13265
13579
  const packageJson = JSON.parse(
13266
- await import('fs/promises').then((fs7) => fs7.readFile(join(packageRoot, "package.json"), "utf-8"))
13580
+ await import('fs/promises').then((fs8) => fs8.readFile(join(packageRoot, "package.json"), "utf-8"))
13267
13581
  );
13268
13582
  version = packageJson.version;
13269
13583
  } catch {
@@ -13583,9 +13897,9 @@ var setupCommand = {
13583
13897
  }
13584
13898
  }
13585
13899
  };
13586
- async function checkExists2(path7) {
13900
+ async function checkExists2(path8) {
13587
13901
  try {
13588
- await access$1(path7, constants.F_OK);
13902
+ await access$1(path8, constants.F_OK);
13589
13903
  return true;
13590
13904
  } catch {
13591
13905
  return false;
@@ -14932,11 +15246,11 @@ async function detectExpressRoutes(projectDir) {
14932
15246
  while ((match = routeRegex.exec(content)) !== null) {
14933
15247
  if (match[1] && match[2]) {
14934
15248
  const method = match[1].toUpperCase();
14935
- const path7 = match[2];
15249
+ const path8 = match[2];
14936
15250
  endpoints.push({
14937
15251
  method,
14938
- path: path7,
14939
- group: path7.split("/")[1] || "api"
15252
+ path: path8,
15253
+ group: path8.split("/")[1] || "api"
14940
15254
  });
14941
15255
  }
14942
15256
  }
@@ -17930,18 +18244,18 @@ var ProviderSessionManager = class {
17930
18244
  };
17931
18245
  var providerSessionInstances = /* @__PURE__ */ new Map();
17932
18246
  async function getProviderSession(workspacePath) {
17933
- let path7;
18247
+ let path8;
17934
18248
  {
17935
18249
  if (process.env.NODE_ENV === "test" || process.env.VITEST) {
17936
- path7 = process.cwd();
18250
+ path8 = process.cwd();
17937
18251
  } else {
17938
- path7 = await detectProjectRoot();
18252
+ path8 = await detectProjectRoot();
17939
18253
  }
17940
18254
  }
17941
- if (!providerSessionInstances.has(path7)) {
17942
- providerSessionInstances.set(path7, new ProviderSessionManager(path7));
18255
+ if (!providerSessionInstances.has(path8)) {
18256
+ providerSessionInstances.set(path8, new ProviderSessionManager(path8));
17943
18257
  }
17944
- return providerSessionInstances.get(path7);
18258
+ return providerSessionInstances.get(path8);
17945
18259
  }
17946
18260
 
17947
18261
  // src/core/router/router.ts
@@ -19711,6 +20025,9 @@ var MemoryManager = class _MemoryManager {
19711
20025
  if (!Number.isInteger(offsetValue) || offsetValue < 0) {
19712
20026
  throw new Error(`Invalid offset value: ${options.offset}. Must be a non-negative integer.`);
19713
20027
  }
20028
+ if (!limitClause) {
20029
+ limitClause = "LIMIT -1";
20030
+ }
19714
20031
  offsetClause = `OFFSET ${offsetValue}`;
19715
20032
  }
19716
20033
  const sql = `
@@ -20056,14 +20373,21 @@ var MemoryManager = class _MemoryManager {
20056
20373
  this.initialized = false;
20057
20374
  this.entryCount = 0;
20058
20375
  this.statements = {};
20059
- const { rename: rename4 } = await import('fs/promises');
20060
- await rename4(tempPath, this.config.dbPath);
20376
+ const { rename: rename5 } = await import('fs/promises');
20377
+ await rename5(tempPath, this.config.dbPath);
20061
20378
  this.db = new Database2(this.config.dbPath);
20062
20379
  this.db.pragma("journal_mode = WAL");
20063
20380
  this.db.pragma(`busy_timeout = ${this.config.busyTimeout}`);
20064
20381
  await this.initialize();
20065
20382
  logger.info("Database restored successfully (atomic operation)", { srcPath: normalizePath(srcPath) });
20066
20383
  } catch (error) {
20384
+ try {
20385
+ DatabaseFactory.close(this.db);
20386
+ } finally {
20387
+ this.initialized = false;
20388
+ this.entryCount = 0;
20389
+ this.statements = {};
20390
+ }
20067
20391
  throw new MemoryError(
20068
20392
  `Failed to restore database: ${error.message}`,
20069
20393
  "DATABASE_ERROR",
@@ -20614,6 +20938,10 @@ var SessionManager = class _SessionManager {
20614
20938
  MAX_TASKS_PER_SESSION = 1e3;
20615
20939
  /** UUID v4 validation regex (static for performance) */
20616
20940
  static UUID_V4_REGEX = /^[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i;
20941
+ /** Tracks whether manager has been destroyed to prevent late saves */
20942
+ destroyed = false;
20943
+ /** Last persistence error (reported during flush) */
20944
+ lastSaveError;
20617
20945
  /**
20618
20946
  * Validate session ID format (must be valid UUID v4)
20619
20947
  *
@@ -21208,6 +21536,7 @@ var SessionManager = class _SessionManager {
21208
21536
  * ```
21209
21537
  */
21210
21538
  async destroy() {
21539
+ this.destroyed = true;
21211
21540
  if (this.saveTimeout) {
21212
21541
  clearTimeout(this.saveTimeout);
21213
21542
  this.saveTimeout = void 0;
@@ -21218,9 +21547,12 @@ var SessionManager = class _SessionManager {
21218
21547
  logger.error("Error flushing save during destroy", {
21219
21548
  error: error.message
21220
21549
  });
21550
+ this.lastSaveError = void 0;
21221
21551
  }
21552
+ const sessionCount = this.activeSessions.size;
21553
+ this.activeSessions.clear();
21222
21554
  logger.debug("SessionManager destroyed", {
21223
- sessions: this.activeSessions.size
21555
+ sessions: sessionCount
21224
21556
  });
21225
21557
  }
21226
21558
  /**
@@ -21245,11 +21577,21 @@ var SessionManager = class _SessionManager {
21245
21577
  this.pendingSave = void 0;
21246
21578
  });
21247
21579
  await this.pendingSave;
21580
+ if (this.lastSaveError) {
21581
+ const err = this.lastSaveError;
21582
+ this.lastSaveError = void 0;
21583
+ throw err;
21584
+ }
21248
21585
  return;
21249
21586
  }
21250
21587
  if (this.pendingSave) {
21251
21588
  try {
21252
21589
  await this.pendingSave;
21590
+ if (this.lastSaveError) {
21591
+ const err = this.lastSaveError;
21592
+ this.lastSaveError = void 0;
21593
+ throw err;
21594
+ }
21253
21595
  } catch (err) {
21254
21596
  throw err;
21255
21597
  }
@@ -21414,7 +21756,7 @@ var SessionManager = class _SessionManager {
21414
21756
  * @private
21415
21757
  */
21416
21758
  saveToFile() {
21417
- if (!this.persistencePath) {
21759
+ if (!this.persistencePath || this.destroyed) {
21418
21760
  return;
21419
21761
  }
21420
21762
  if (this.saveTimeout) {
@@ -21427,18 +21769,18 @@ var SessionManager = class _SessionManager {
21427
21769
  }
21428
21770
  this.saveNeeded = false;
21429
21771
  const executeNextSave = async () => {
21430
- await this.doSave();
21772
+ try {
21773
+ await this.doSave();
21774
+ this.lastSaveError = void 0;
21775
+ } catch (err) {
21776
+ this.lastSaveError = err;
21777
+ }
21431
21778
  if (this.saveNeeded) {
21432
21779
  this.saveNeeded = false;
21433
21780
  return executeNextSave();
21434
21781
  }
21435
21782
  };
21436
- this.pendingSave = executeNextSave().catch((err) => {
21437
- logger.error("Debounced save failed", {
21438
- error: err.message
21439
- });
21440
- throw err;
21441
- }).finally(() => {
21783
+ this.pendingSave = executeNextSave().finally(() => {
21442
21784
  this.pendingSave = void 0;
21443
21785
  });
21444
21786
  }, 100);
@@ -23759,9 +24101,9 @@ var DependencyGraphBuilder = class {
23759
24101
  detectCycles(graph) {
23760
24102
  const visiting = /* @__PURE__ */ new Set();
23761
24103
  const visited = /* @__PURE__ */ new Set();
23762
- const visit = (nodeName, path7) => {
24104
+ const visit = (nodeName, path8) => {
23763
24105
  if (visiting.has(nodeName)) {
23764
- throw new Error(`Circular dependency detected: ${[...path7, nodeName].join(" \u2192 ")}`);
24106
+ throw new Error(`Circular dependency detected: ${[...path8, nodeName].join(" \u2192 ")}`);
23765
24107
  }
23766
24108
  if (visited.has(nodeName)) {
23767
24109
  return;
@@ -23776,7 +24118,7 @@ var DependencyGraphBuilder = class {
23776
24118
  }
23777
24119
  visiting.add(nodeName);
23778
24120
  for (const dependency of node.dependencies) {
23779
- visit(dependency, [...path7, nodeName]);
24121
+ visit(dependency, [...path8, nodeName]);
23780
24122
  }
23781
24123
  visiting.delete(nodeName);
23782
24124
  visited.add(nodeName);
@@ -25509,59 +25851,59 @@ var DANGEROUS_PATH_PATTERNS = [
25509
25851
  // Common data drive (Windows, alt format)
25510
25852
  ];
25511
25853
  var SUSPICIOUS_PATH_CHARS = /[<>:|"]/;
25512
- function validatePathParameter(path7, paramName, projectRoot = process.cwd()) {
25513
- if (!path7 || path7.trim() === "") {
25854
+ function validatePathParameter(path8, paramName, projectRoot = process.cwd()) {
25855
+ if (!path8 || path8.trim() === "") {
25514
25856
  throw new ValidationError(
25515
25857
  `Invalid ${paramName}: path cannot be empty`,
25516
25858
  -32602 /* InvalidParams */,
25517
- { path: path7, paramName }
25859
+ { path: path8, paramName }
25518
25860
  );
25519
25861
  }
25520
25862
  for (const pattern of DANGEROUS_PATH_PATTERNS) {
25521
- if (path7.includes(pattern)) {
25863
+ if (path8.includes(pattern)) {
25522
25864
  throw new ValidationError(
25523
25865
  `Invalid ${paramName}: path contains dangerous pattern "${pattern}"`,
25524
25866
  -32602 /* InvalidParams */,
25525
- { path: path7, paramName, pattern }
25867
+ { path: path8, paramName, pattern }
25526
25868
  );
25527
25869
  }
25528
25870
  }
25529
- if (isAbsolute(path7)) {
25871
+ if (isAbsolute(path8)) {
25530
25872
  throw new ValidationError(
25531
25873
  `Invalid ${paramName}: absolute paths are not allowed`,
25532
25874
  -32602 /* InvalidParams */,
25533
- { path: path7, paramName }
25875
+ { path: path8, paramName }
25534
25876
  );
25535
25877
  }
25536
25878
  try {
25537
- const resolvedPath = resolve(projectRoot, path7);
25879
+ const resolvedPath = resolve(projectRoot, path8);
25538
25880
  const normalizedRoot = resolve(projectRoot);
25539
25881
  if (!resolvedPath.startsWith(normalizedRoot + sep) && resolvedPath !== normalizedRoot) {
25540
25882
  throw new ValidationError(
25541
25883
  `Invalid ${paramName}: path escapes project boundary`,
25542
25884
  -32602 /* InvalidParams */,
25543
- { path: path7, paramName, projectRoot, resolvedPath }
25885
+ { path: path8, paramName, projectRoot, resolvedPath }
25544
25886
  );
25545
25887
  }
25546
25888
  } catch (error) {
25547
25889
  throw new ValidationError(
25548
25890
  `Invalid ${paramName}: path resolution failed`,
25549
25891
  -32602 /* InvalidParams */,
25550
- { path: path7, paramName, error: String(error) }
25892
+ { path: path8, paramName, error: String(error) }
25551
25893
  );
25552
25894
  }
25553
- if (path7.includes("\0")) {
25895
+ if (path8.includes("\0")) {
25554
25896
  throw new ValidationError(
25555
25897
  `Invalid ${paramName}: path contains null byte`,
25556
25898
  -32602 /* InvalidParams */,
25557
- { path: path7, paramName }
25899
+ { path: path8, paramName }
25558
25900
  );
25559
25901
  }
25560
- if (SUSPICIOUS_PATH_CHARS.test(path7)) {
25902
+ if (SUSPICIOUS_PATH_CHARS.test(path8)) {
25561
25903
  throw new ValidationError(
25562
25904
  `Invalid ${paramName}: path contains invalid characters`,
25563
25905
  -32602 /* InvalidParams */,
25564
- { path: path7, paramName }
25906
+ { path: path8, paramName }
25565
25907
  );
25566
25908
  }
25567
25909
  }
@@ -26257,8 +26599,8 @@ function createMemoryExportHandler(deps) {
26257
26599
  return async (input) => {
26258
26600
  logger.info("[MCP] memory_export called", { input });
26259
26601
  try {
26260
- const { path: path7 } = input;
26261
- const absolutePath = resolveExportPath(deps.pathResolver, path7);
26602
+ const { path: path8 } = input;
26603
+ const absolutePath = resolveExportPath(deps.pathResolver, path8);
26262
26604
  const exported = await deps.memoryManager.exportToJSON(absolutePath);
26263
26605
  const result = {
26264
26606
  success: true,
@@ -26294,8 +26636,8 @@ function createMemoryImportHandler(deps) {
26294
26636
  return async (input) => {
26295
26637
  logger.info("[MCP] memory_import called", { input });
26296
26638
  try {
26297
- const { path: path7 } = input;
26298
- const absolutePath = resolveImportPath(deps.pathResolver, path7);
26639
+ const { path: path8 } = input;
26640
+ const absolutePath = resolveImportPath(deps.pathResolver, path8);
26299
26641
  const imported = await deps.memoryManager.importFromJSON(absolutePath);
26300
26642
  const result = {
26301
26643
  success: true,
@@ -26870,7 +27212,18 @@ var McpClient = class extends EventEmitter {
26870
27212
  timeout: timeoutHandle
26871
27213
  });
26872
27214
  const message = JSON.stringify(request) + "\n";
26873
- this.process.stdin.write(message);
27215
+ try {
27216
+ this.process.stdin.write(message);
27217
+ } catch (error) {
27218
+ const pending = this.pendingRequests.get(id);
27219
+ if (pending) {
27220
+ clearTimeout(pending.timeout);
27221
+ this.pendingRequests.delete(id);
27222
+ }
27223
+ const err = error instanceof Error ? error : new Error(String(error));
27224
+ reject(err);
27225
+ return;
27226
+ }
26874
27227
  logger.debug("[MCP Client] Sent request", {
26875
27228
  id,
26876
27229
  method,
@@ -29618,8 +29971,8 @@ var LifecycleLogger = class {
29618
29971
  if (sizeMB > this.maxLogSizeMB) {
29619
29972
  const timestamp = (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-");
29620
29973
  const archivePath = logPath.replace(".jsonl", `-${timestamp}.jsonl`);
29621
- const { rename: rename4 } = await import('fs/promises');
29622
- await rename4(logPath, archivePath);
29974
+ const { rename: rename5 } = await import('fs/promises');
29975
+ await rename5(logPath, archivePath);
29623
29976
  logger.info("LifecycleLogger: Rotated log file", {
29624
29977
  oldPath: logPath,
29625
29978
  newPath: archivePath,
@@ -31402,9 +31755,9 @@ var ProgressIndicator = class {
31402
31755
  // src/cli/commands/memory.ts
31403
31756
  var DEFAULT_DB_PATH = ".automatosx/memory/memory.db";
31404
31757
  function getMemoryManager(dbPath) {
31405
- const path7 = dbPath || DEFAULT_DB_PATH;
31758
+ const path8 = dbPath || DEFAULT_DB_PATH;
31406
31759
  return new LazyMemoryManager({
31407
- dbPath: resolve(path7),
31760
+ dbPath: resolve(path8),
31408
31761
  maxEntries: 1e5,
31409
31762
  autoCleanup: false,
31410
31763
  trackAccess: true
@@ -34405,14 +34758,14 @@ var IterateClassifier = class {
34405
34758
  * **Phase 1 (Week 1)**: Skeleton only (no-op)
34406
34759
  * **Phase 2 (Week 2)**: Full implementation with YAML loading and validation
34407
34760
  */
34408
- async loadPatterns(path7) {
34409
- logger.debug("Loading pattern library", { path: path7 });
34410
- if (!existsSync(path7)) {
34411
- logger.warn("Pattern library file not found", { path: path7 });
34761
+ async loadPatterns(path8) {
34762
+ logger.debug("Loading pattern library", { path: path8 });
34763
+ if (!existsSync(path8)) {
34764
+ logger.warn("Pattern library file not found", { path: path8 });
34412
34765
  return;
34413
34766
  }
34414
34767
  try {
34415
- const fileContent = await readFile(path7, "utf-8");
34768
+ const fileContent = await readFile(path8, "utf-8");
34416
34769
  const parsed = load(fileContent);
34417
34770
  if (!parsed || typeof parsed !== "object") {
34418
34771
  throw new Error("Invalid pattern library format: not an object");
@@ -34455,7 +34808,7 @@ var IterateClassifier = class {
34455
34808
  });
34456
34809
  } catch (error) {
34457
34810
  logger.error("Failed to load pattern library", {
34458
- path: path7,
34811
+ path: path8,
34459
34812
  error: error.message
34460
34813
  });
34461
34814
  throw error;
@@ -34809,14 +35162,14 @@ var IterateAutoResponder = class {
34809
35162
  * **Phase 1 (Week 1)**: Skeleton only (no-op)
34810
35163
  * **Phase 3 (Week 3)**: Full implementation with YAML loading and validation
34811
35164
  */
34812
- async loadTemplates(path7) {
34813
- logger.debug("Loading template library", { path: path7 });
34814
- if (!existsSync(path7)) {
34815
- logger.warn("Template library file not found", { path: path7 });
35165
+ async loadTemplates(path8) {
35166
+ logger.debug("Loading template library", { path: path8 });
35167
+ if (!existsSync(path8)) {
35168
+ logger.warn("Template library file not found", { path: path8 });
34816
35169
  return;
34817
35170
  }
34818
35171
  try {
34819
- const fileContent = await readFile(path7, "utf-8");
35172
+ const fileContent = await readFile(path8, "utf-8");
34820
35173
  const parsed = load(fileContent);
34821
35174
  if (!parsed || typeof parsed !== "object") {
34822
35175
  throw new Error("Invalid template library format: not an object");
@@ -34858,7 +35211,7 @@ var IterateAutoResponder = class {
34858
35211
  });
34859
35212
  } catch (error) {
34860
35213
  logger.error("Failed to load template library", {
34861
- path: path7,
35214
+ path: path8,
34862
35215
  error: error.message
34863
35216
  });
34864
35217
  throw error;
@@ -38670,11 +39023,11 @@ async function getCurrentVersion() {
38670
39023
  return result.dependencies["@defai.digital/automatosx"]?.version || "unknown";
38671
39024
  } catch (error) {
38672
39025
  const { readFile: readFile24 } = await import('fs/promises');
38673
- const { dirname: dirname15, join: join50 } = await import('path');
39026
+ const { dirname: dirname15, join: join51 } = await import('path');
38674
39027
  const { fileURLToPath: fileURLToPath5 } = await import('url');
38675
39028
  const __filename3 = fileURLToPath5(import.meta.url);
38676
39029
  const __dirname4 = dirname15(__filename3);
38677
- const pkgPath = join50(__dirname4, "../../../package.json");
39030
+ const pkgPath = join51(__dirname4, "../../../package.json");
38678
39031
  const content = await readFile24(pkgPath, "utf-8");
38679
39032
  const pkg = JSON.parse(content);
38680
39033
  return pkg.version;
@@ -40744,8 +41097,8 @@ var ConfigManager = class {
40744
41097
  * @returns User configuration or empty object if not found
40745
41098
  */
40746
41099
  async readUserConfig() {
40747
- const path7 = getUserConfigPath();
40748
- return this.readConfig(path7, "user");
41100
+ const path8 = getUserConfigPath();
41101
+ return this.readConfig(path8, "user");
40749
41102
  }
40750
41103
  /**
40751
41104
  * Read project-level Gemini CLI configuration
@@ -40753,8 +41106,8 @@ var ConfigManager = class {
40753
41106
  * @returns Project configuration or empty object if not found
40754
41107
  */
40755
41108
  async readProjectConfig() {
40756
- const path7 = getProjectConfigPath();
40757
- return this.readConfig(path7, "project");
41109
+ const path8 = getProjectConfigPath();
41110
+ return this.readConfig(path8, "project");
40758
41111
  }
40759
41112
  /**
40760
41113
  * Read configuration from a specific path with caching
@@ -40764,7 +41117,7 @@ var ConfigManager = class {
40764
41117
  * @returns Configuration object
40765
41118
  * @private
40766
41119
  */
40767
- async readConfig(path7, scope) {
41120
+ async readConfig(path8, scope) {
40768
41121
  const cached = this.cache.get(scope);
40769
41122
  if (cached && Date.now() - cached.timestamp < this.ttl) {
40770
41123
  return cached.data;
@@ -40775,13 +41128,13 @@ var ConfigManager = class {
40775
41128
  }
40776
41129
  const readOperation = (async () => {
40777
41130
  try {
40778
- const exists = await fileExists(path7);
41131
+ const exists = await fileExists(path8);
40779
41132
  if (!exists) {
40780
41133
  const emptyConfig = {};
40781
41134
  this.cache.set(scope, { data: emptyConfig, timestamp: Date.now() });
40782
41135
  return emptyConfig;
40783
41136
  }
40784
- const config = await readJsonFile(path7);
41137
+ const config = await readJsonFile(path8);
40785
41138
  this.cache.set(scope, { data: config, timestamp: Date.now() });
40786
41139
  return config;
40787
41140
  } catch (error) {
@@ -40790,8 +41143,8 @@ var ConfigManager = class {
40790
41143
  }
40791
41144
  throw new GeminiCLIError(
40792
41145
  "INVALID_CONFIG" /* INVALID_CONFIG */,
40793
- `Failed to read configuration from ${path7}`,
40794
- { path: path7, originalError: error }
41146
+ `Failed to read configuration from ${path8}`,
41147
+ { path: path8, originalError: error }
40795
41148
  );
40796
41149
  } finally {
40797
41150
  this.pendingReads.delete(scope);
@@ -41461,8 +41814,8 @@ var CommandTranslator = class {
41461
41814
  paths.push(getProjectCommandsPath());
41462
41815
  }
41463
41816
  }
41464
- for (const path7 of paths) {
41465
- const discovered = await this.scanDirectory(path7);
41817
+ for (const path8 of paths) {
41818
+ const discovered = await this.scanDirectory(path8);
41466
41819
  commands.push(...discovered);
41467
41820
  }
41468
41821
  return commands;
@@ -41503,8 +41856,8 @@ var CommandTranslator = class {
41503
41856
  const results = [];
41504
41857
  for (const name of commandNames) {
41505
41858
  try {
41506
- const path7 = await this.importCommand(name, outputDir, options);
41507
- results.push(path7);
41859
+ const path8 = await this.importCommand(name, outputDir, options);
41860
+ results.push(path8);
41508
41861
  } catch (error) {
41509
41862
  if (error instanceof GeminiCLIError) {
41510
41863
  console.error(`Failed to import ${name}: ${error.message}`);
@@ -42836,7 +43189,7 @@ var SpecSchemaValidator = class {
42836
43189
  * Convert Ajv error to ValidationIssue
42837
43190
  */
42838
43191
  convertAjvError(error) {
42839
- const path7 = error.instancePath.replace(/^\//, "").replace(/\//g, ".");
43192
+ const path8 = error.instancePath.replace(/^\//, "").replace(/\//g, ".");
42840
43193
  const keyword = error.keyword;
42841
43194
  let message = error.message || "Validation error";
42842
43195
  let suggestion;
@@ -42887,7 +43240,7 @@ var SpecSchemaValidator = class {
42887
43240
  ruleId: `SCHEMA-${keyword.toUpperCase()}`,
42888
43241
  severity: "error",
42889
43242
  message,
42890
- path: path7 || void 0,
43243
+ path: path8 || void 0,
42891
43244
  suggestion
42892
43245
  };
42893
43246
  }
@@ -45707,8 +46060,8 @@ async function handleReset() {
45707
46060
  }
45708
46061
  async function handleTrace(workspacePath, argv) {
45709
46062
  const { existsSync: existsSync26, readFileSync: readFileSync9, watchFile } = await import('fs');
45710
- const { join: join50 } = await import('path');
45711
- const traceFile = join50(workspacePath, ".automatosx/logs/router.trace.jsonl");
46063
+ const { join: join51 } = await import('path');
46064
+ const traceFile = join51(workspacePath, ".automatosx/logs/router.trace.jsonl");
45712
46065
  if (!existsSync26(traceFile)) {
45713
46066
  console.log(chalk5.yellow("\n\u26A0\uFE0F No trace log found\n"));
45714
46067
  console.log(chalk5.gray(`Expected location: ${traceFile}
@@ -48617,13 +48970,13 @@ Time since last change: ${timeSinceLastChange}ms`
48617
48970
  init_logger();
48618
48971
  var flagManagerInstances = /* @__PURE__ */ new Map();
48619
48972
  function getFlagManager(workspacePath) {
48620
- const path7 = process.cwd();
48621
- if (!flagManagerInstances.has(path7)) {
48622
- const manager = new FeatureFlagManager(path7);
48973
+ const path8 = process.cwd();
48974
+ if (!flagManagerInstances.has(path8)) {
48975
+ const manager = new FeatureFlagManager(path8);
48623
48976
  initializeFlags(manager);
48624
- flagManagerInstances.set(path7, manager);
48977
+ flagManagerInstances.set(path8, manager);
48625
48978
  }
48626
- return flagManagerInstances.get(path7);
48979
+ return flagManagerInstances.get(path8);
48627
48980
  }
48628
48981
  function initializeFlags(manager) {
48629
48982
  if (!manager.hasStorage()) {
@@ -48944,9 +49297,9 @@ var cliCommand = {
48944
49297
  // src/cli/commands/uninstall.ts
48945
49298
  init_esm_shims();
48946
49299
  init_logger();
48947
- async function fileExists2(path7) {
49300
+ async function fileExists2(path8) {
48948
49301
  try {
48949
- await access$1(path7);
49302
+ await access$1(path8);
48950
49303
  return true;
48951
49304
  } catch {
48952
49305
  return false;
@@ -49519,7 +49872,6 @@ var OrchestrationInstructionInjector = class {
49519
49872
  providers = /* @__PURE__ */ new Map();
49520
49873
  budgetManager;
49521
49874
  config;
49522
- lastInjectionTime = 0;
49523
49875
  constructor(config) {
49524
49876
  this.config = {
49525
49877
  ...DEFAULT_ORCHESTRATION_CONFIG,
@@ -49612,7 +49964,6 @@ var OrchestrationInstructionInjector = class {
49612
49964
  allocation = this.budgetManager.allocateBudget(activeInstructions);
49613
49965
  }
49614
49966
  const formattedText = this.formatInstructions(allocation.included);
49615
- this.lastInjectionTime = Date.now();
49616
49967
  const duration = Date.now() - startTime;
49617
49968
  logger.debug("Instruction injection complete", {
49618
49969
  providers: this.providers.size,
@@ -50226,7 +50577,7 @@ var SessionInstructionProvider = class {
50226
50577
  if (!this.config.enabled) {
50227
50578
  return false;
50228
50579
  }
50229
- if (!context.sessionId && !this.stateProvider) {
50580
+ if (!context.sessionId && !this.stateProvider && !context.parentAgent) {
50230
50581
  return false;
50231
50582
  }
50232
50583
  const turnsSinceReminder = context.turnCount - this.lastReminderTurn;
@@ -50238,7 +50589,7 @@ var SessionInstructionProvider = class {
50238
50589
  async getInstructions(context) {
50239
50590
  const instructions = [];
50240
50591
  const state = await this.getSessionState(context);
50241
- if (!state && !context.sessionId) {
50592
+ if (!state && !context.sessionId && !context.parentAgent) {
50242
50593
  return instructions;
50243
50594
  }
50244
50595
  const content = this.formatSessionContext(context, state);
@@ -51190,7 +51541,6 @@ var AgentInstructionInjector = class {
51190
51541
  var OrchestrationService = class {
51191
51542
  config;
51192
51543
  injector;
51193
- tokenBudgetManager;
51194
51544
  workflowModeManager;
51195
51545
  agentInjector;
51196
51546
  todoProvider;
@@ -51204,7 +51554,6 @@ var OrchestrationService = class {
51204
51554
  ...serviceConfig
51205
51555
  };
51206
51556
  this.injector = new OrchestrationInstructionInjector(this.config);
51207
- this.tokenBudgetManager = new TokenBudgetManager(this.config.tokenBudget);
51208
51557
  this.workflowModeManager = new WorkflowModeManager();
51209
51558
  this.agentInjector = new AgentInstructionInjector({
51210
51559
  enabled: this.config.agentTemplates?.enabled ?? true,
@@ -51381,7 +51730,7 @@ ${content}
51381
51730
  * Get debug information about current orchestration state
51382
51731
  */
51383
51732
  getDebugInfo() {
51384
- const budgetConfig = this.tokenBudgetManager.getConfig();
51733
+ const budgetConfig = this.injector.getBudgetManager().getConfig();
51385
51734
  const providers = this.injector.getProviders().map((p) => p.name);
51386
51735
  return {
51387
51736
  turnCount: this.turnCount,
@@ -51429,9 +51778,6 @@ ${content}
51429
51778
  sessionIntegration: updates.sessionIntegration ? { ...this.config.sessionIntegration, ...updates.sessionIntegration } : this.config.sessionIntegration,
51430
51779
  agentTemplates: updates.agentTemplates ? { ...this.config.agentTemplates, ...updates.agentTemplates } : this.config.agentTemplates
51431
51780
  };
51432
- if (updates.tokenBudget) {
51433
- this.tokenBudgetManager.updateConfig(this.config.tokenBudget);
51434
- }
51435
51781
  this.injector.updateConfig(updates);
51436
51782
  if (updates.todoIntegration && this.todoProvider) {
51437
51783
  const current = this.todoProvider.getConfig();