@defai.digital/automatosx 12.5.1 → 12.5.3

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/README.md CHANGED
@@ -12,7 +12,7 @@
12
12
  [![Ubuntu](https://img.shields.io/badge/Ubuntu-24.04-blue.svg)](https://ubuntu.com)
13
13
  [![License](https://img.shields.io/badge/license-Apache--2.0-yellow.svg)](LICENSE)
14
14
 
15
- **Status**: ✅ **Production Ready** | v12.5.1 | MCP Hybrid Framing & Multi-Protocol Support
15
+ **Status**: ✅ **Production Ready** | v12.5.3 | Performance & Reliability Improvements
16
16
 
17
17
  > 🎯 **What AutomatosX Does**: Adds 20+ specialized agents, persistent memory, workflow automation, and 80% cost savings to Claude Code/Codex - **without changing how you work**.
18
18
 
package/dist/index.js CHANGED
@@ -401,7 +401,9 @@ var init_validation_limits = __esm({
401
401
  /** Quick CLI command timeout (3 seconds) */
402
402
  QUICK_COMMAND: 3e3,
403
403
  /** CLI version check timeout (10 seconds) */
404
- VERSION_CHECK: 1e4
404
+ VERSION_CHECK: 1e4,
405
+ /** MCP agent execution timeout (5 minutes) */
406
+ MCP_AGENT_EXECUTION: 3e5
405
407
  };
406
408
  DATABASE = {
407
409
  /** SQLite busy timeout in milliseconds */
@@ -4975,6 +4977,37 @@ var init_flags = __esm({
4975
4977
  }
4976
4978
  });
4977
4979
 
4980
+ // src/shared/errors/error-wrapper.ts
4981
+ function getErrorMessage(error) {
4982
+ if (error instanceof Error) {
4983
+ return error.message;
4984
+ }
4985
+ if (typeof error === "string") {
4986
+ return error;
4987
+ }
4988
+ if (error && typeof error === "object") {
4989
+ const obj = error;
4990
+ if (obj.error && typeof obj.error === "object") {
4991
+ const nested = obj.error;
4992
+ if (typeof nested.message === "string") {
4993
+ return nested.message;
4994
+ }
4995
+ }
4996
+ if (typeof obj.error === "string") {
4997
+ return obj.error;
4998
+ }
4999
+ if ("message" in obj) {
5000
+ return String(obj.message);
5001
+ }
5002
+ }
5003
+ return String(error);
5004
+ }
5005
+ var init_error_wrapper = __esm({
5006
+ "src/shared/errors/error-wrapper.ts"() {
5007
+ init_esm_shims();
5008
+ }
5009
+ });
5010
+
4978
5011
  // src/providers/fallback-decision.ts
4979
5012
  function decideFallback(error, providerName) {
4980
5013
  const errorMessage = getErrorMessage(error).toLowerCase();
@@ -5045,30 +5078,6 @@ function decideFallback(error, providerName) {
5045
5078
  severity: "error"
5046
5079
  };
5047
5080
  }
5048
- function getErrorMessage(error) {
5049
- if (error instanceof Error) {
5050
- return error.message;
5051
- }
5052
- if (typeof error === "string") {
5053
- return error;
5054
- }
5055
- if (error && typeof error === "object") {
5056
- const obj = error;
5057
- if (typeof obj.message === "string") {
5058
- return obj.message;
5059
- }
5060
- if (typeof obj.error === "string") {
5061
- return obj.error;
5062
- }
5063
- if (obj.error && typeof obj.error === "object") {
5064
- const innerError = obj.error;
5065
- if (typeof innerError.message === "string") {
5066
- return innerError.message;
5067
- }
5068
- }
5069
- }
5070
- return String(error);
5071
- }
5072
5081
  function getErrorCode(error) {
5073
5082
  if (error && typeof error === "object") {
5074
5083
  const obj = error;
@@ -5108,6 +5117,7 @@ var init_fallback_decision = __esm({
5108
5117
  init_esm_shims();
5109
5118
  init_logger();
5110
5119
  init_flags();
5120
+ init_error_wrapper();
5111
5121
  SDK_UNAVAILABLE_PATTERNS = [
5112
5122
  "module not found",
5113
5123
  "cannot find module",
@@ -9431,7 +9441,7 @@ var PRECOMPILED_CONFIG = {
9431
9441
  "enableFreeTierPrioritization": true,
9432
9442
  "enableWorkloadAwareRouting": true
9433
9443
  },
9434
- "version": "12.5.1"
9444
+ "version": "12.5.3"
9435
9445
  };
9436
9446
 
9437
9447
  // src/core/config/schemas.ts
@@ -12369,16 +12379,21 @@ var ProfileLoader = class {
12369
12379
  logger.debug("Building displayName mapping table");
12370
12380
  this.displayNameMap.clear();
12371
12381
  try {
12372
- const localProfiles = await this.listProfilesFromDir(this.profilesDir);
12382
+ const [localProfiles, fallbackProfiles] = await Promise.all([
12383
+ this.listProfilesFromDir(this.profilesDir),
12384
+ this.listProfilesFromDir(this.fallbackProfilesDir)
12385
+ ]);
12373
12386
  for (const name of localProfiles) {
12374
12387
  await this.addToDisplayNameMap(name, "local");
12375
12388
  }
12376
- const fallbackProfiles = await this.listProfilesFromDir(this.fallbackProfilesDir);
12377
- for (const name of fallbackProfiles) {
12389
+ const fallbacksToProcess = fallbackProfiles.filter((name) => {
12378
12390
  if (localProfiles.includes(name)) {
12379
12391
  logger.debug("Skipping fallback profile (local override)", { name });
12380
- continue;
12392
+ return false;
12381
12393
  }
12394
+ return true;
12395
+ });
12396
+ for (const name of fallbacksToProcess) {
12382
12397
  await this.addToDisplayNameMap(name, "fallback");
12383
12398
  }
12384
12399
  this.mapInitialized = true;
@@ -19172,6 +19187,7 @@ Run 'ax doctor' to diagnose provider setup.` : "";
19172
19187
  logger.error("Health check interval failed", { error: err.message });
19173
19188
  });
19174
19189
  }, intervalMs);
19190
+ if (this.healthCheckInterval.unref) this.healthCheckInterval.unref();
19175
19191
  logger.debug("Starting background health checks", {
19176
19192
  interval: intervalMs,
19177
19193
  providers: this.providers.map((p) => p.name)
@@ -26428,6 +26444,12 @@ function mapNormalizedCallerToActual(caller) {
26428
26444
  }
26429
26445
 
26430
26446
  // src/mcp/tools/run-agent.ts
26447
+ init_validation_limits();
26448
+ function checkAborted(signal) {
26449
+ if (signal?.aborted) {
26450
+ throw new Error("Request was cancelled");
26451
+ }
26452
+ }
26431
26453
  async function executeViaMcpPool(provider, agent, task, pool) {
26432
26454
  const startTime = Date.now();
26433
26455
  const client = await pool.acquire(provider);
@@ -26448,17 +26470,20 @@ async function executeViaMcpPool(provider, agent, task, pool) {
26448
26470
  pool.release(provider, client);
26449
26471
  }
26450
26472
  }
26451
- async function executeViaCli(agent, task, actualProvider, no_memory, deps, isFallback, signal) {
26473
+ var MCP_DEFAULT_AGENT_TIMEOUT_MS = TIMEOUTS.MCP_AGENT_EXECUTION;
26474
+ async function executeViaCli(agent, task, actualProvider, no_memory, deps, isFallback, signal, timeout) {
26452
26475
  const context = await deps.contextManager.createContext(agent, task, {
26453
26476
  provider: actualProvider,
26454
26477
  skipMemory: no_memory
26455
26478
  });
26456
26479
  const executor = new AgentExecutor(deps.executorConfig);
26457
26480
  const startTime = Date.now();
26481
+ const effectiveTimeout = timeout ?? MCP_DEFAULT_AGENT_TIMEOUT_MS;
26458
26482
  const result = await executor.execute(context, {
26459
26483
  showProgress: false,
26460
26484
  verbose: false,
26461
- signal
26485
+ signal,
26486
+ timeout: effectiveTimeout
26462
26487
  });
26463
26488
  const latencyMs = Date.now() - startTime;
26464
26489
  const executionMode = isFallback ? "cli_fallback" : "cli_spawn";
@@ -26533,9 +26558,7 @@ function createRunAgentHandler(deps) {
26533
26558
  return async (input, context) => {
26534
26559
  const { task, provider, no_memory, mode = "auto" } = input;
26535
26560
  let { agent } = input;
26536
- if (context?.signal?.aborted) {
26537
- throw new Error("Request was cancelled");
26538
- }
26561
+ checkAborted(context?.signal);
26539
26562
  validateStringParameter(task, "task", {
26540
26563
  required: true,
26541
26564
  minLength: 1,
@@ -26580,9 +26603,7 @@ function createRunAgentHandler(deps) {
26580
26603
  bestProvider = selectedProvider?.name || "claude-code";
26581
26604
  }
26582
26605
  const shouldReturnContext = mode === "context" || mode === "auto" && callerActual === bestProvider && callerProvider !== "unknown";
26583
- if (context?.signal?.aborted) {
26584
- throw new Error("Request was cancelled");
26585
- }
26606
+ checkAborted(context?.signal);
26586
26607
  logger.info("[Smart Routing] Decision", {
26587
26608
  mode,
26588
26609
  callerProvider,
@@ -26617,7 +26638,7 @@ function createRunAgentHandler(deps) {
26617
26638
  const shouldTryMcp = !!deps.mcpPool;
26618
26639
  if (shouldTryMcp && deps.mcpPool) {
26619
26640
  try {
26620
- if (context?.signal?.aborted) throw new Error("Request was cancelled");
26641
+ checkAborted(context?.signal);
26621
26642
  const result = await executeViaMcpPool(
26622
26643
  bestProvider,
26623
26644
  agent,
@@ -26647,10 +26668,8 @@ function createRunAgentHandler(deps) {
26647
26668
  }
26648
26669
  }
26649
26670
  try {
26650
- if (context?.signal?.aborted) {
26651
- throw new Error("Request was cancelled");
26652
- }
26653
- const result = await executeViaCli(agent, task, actualProvider, no_memory, deps, shouldTryMcp, context?.signal);
26671
+ checkAborted(context?.signal);
26672
+ const result = await executeViaCli(agent, task, actualProvider, no_memory, deps, shouldTryMcp, context?.signal, MCP_DEFAULT_AGENT_TIMEOUT_MS);
26654
26673
  logger.info("[MCP] run_agent completed (CLI spawn mode)", {
26655
26674
  agent,
26656
26675
  latencyMs: result.latencyMs,
@@ -26684,8 +26703,9 @@ function createListAgentsHandler(deps) {
26684
26703
  }
26685
26704
  })
26686
26705
  );
26706
+ const validProfiles = profiles.filter((profile) => profile !== null);
26687
26707
  const result = {
26688
- agents: profiles.filter((profile) => profile !== null).map((profile) => ({
26708
+ agents: validProfiles.map((profile) => ({
26689
26709
  name: profile.name,
26690
26710
  displayName: profile.displayName,
26691
26711
  role: profile.role,
@@ -27522,29 +27542,34 @@ function createGetCapabilitiesHandler(deps) {
27522
27542
  }
27523
27543
  providers.sort((a, b) => b.priority - a.priority);
27524
27544
  const agentNames = await deps.profileLoader.listProfiles();
27525
- const agents = [];
27526
- for (const agentName of agentNames) {
27527
- try {
27528
- const profile = await deps.profileLoader.loadProfile(agentName);
27529
- agents.push({
27530
- name: profile.name,
27531
- displayName: profile.displayName,
27532
- role: profile.role,
27533
- description: profile.systemPrompt?.substring(0, 200),
27534
- team: profile.team,
27535
- abilities: profile.abilities || []
27536
- });
27537
- } catch (error) {
27538
- logger.warn(`Failed to load profile for ${agentName}`, { error });
27539
- }
27540
- }
27545
+ const agentResults = await Promise.all(
27546
+ agentNames.map(async (agentName) => {
27547
+ try {
27548
+ const profile = await deps.profileLoader.loadProfile(agentName);
27549
+ return {
27550
+ name: profile.name,
27551
+ displayName: profile.displayName,
27552
+ role: profile.role,
27553
+ description: profile.systemPrompt?.substring(0, 200),
27554
+ team: profile.team,
27555
+ abilities: profile.abilities || []
27556
+ };
27557
+ } catch (error) {
27558
+ logger.warn(`Failed to load profile for ${agentName}`, { error });
27559
+ return null;
27560
+ }
27561
+ })
27562
+ );
27563
+ const agents = agentResults.filter((a) => a !== null);
27541
27564
  const tools = deps.toolSchemas.map((schema) => ({
27542
27565
  name: schema.name,
27543
27566
  description: schema.description,
27544
27567
  category: categorizeTools(schema.name)
27545
27568
  }));
27546
- const memoryStats = await deps.memoryManager.getStats();
27547
- const activeSessions = await deps.sessionManager.getActiveSessions();
27569
+ const [memoryStats, activeSessions] = await Promise.all([
27570
+ deps.memoryManager.getStats(),
27571
+ deps.sessionManager.getActiveSessions()
27572
+ ]);
27548
27573
  const result = {
27549
27574
  version,
27550
27575
  providers,
@@ -30196,17 +30221,18 @@ var ConnectionTimeoutError = class extends McpClientError {
30196
30221
  };
30197
30222
 
30198
30223
  // src/providers/mcp/pool-manager.ts
30224
+ init_validation_limits();
30199
30225
  var DEFAULT_CONFIG6 = {
30200
30226
  maxConnectionsPerProvider: 2,
30201
- idleTimeoutMs: 3e5,
30227
+ idleTimeoutMs: TIMEOUTS.IDLE_CONNECTION,
30202
30228
  // 5 minutes
30203
- healthCheckIntervalMs: 3e4,
30229
+ healthCheckIntervalMs: TIMEOUTS.MCP_HEALTH_CHECK,
30204
30230
  // 30 seconds
30205
- acquireTimeoutMs: 1e4,
30231
+ acquireTimeoutMs: TIMEOUTS.VERSION_CHECK,
30206
30232
  // 10 seconds
30207
30233
  fallbackToCli: true
30208
30234
  };
30209
- var IDLE_CLEANUP_INTERVAL_MS = 6e4;
30235
+ var IDLE_CLEANUP_INTERVAL_MS = TIMEOUTS.CONFIG_CACHE_TTL;
30210
30236
  var McpClientPool = class extends EventEmitter {
30211
30237
  config;
30212
30238
  pools = /* @__PURE__ */ new Map();
@@ -30535,6 +30561,7 @@ var McpClientPool = class extends EventEmitter {
30535
30561
  });
30536
30562
  }
30537
30563
  }, this.config.healthCheckIntervalMs);
30564
+ if (this.healthCheckTimer.unref) this.healthCheckTimer.unref();
30538
30565
  }
30539
30566
  startIdleCleanup() {
30540
30567
  this.idleCheckTimer = setInterval(() => {
@@ -30565,6 +30592,7 @@ var McpClientPool = class extends EventEmitter {
30565
30592
  }
30566
30593
  }
30567
30594
  }, IDLE_CLEANUP_INTERVAL_MS);
30595
+ if (this.idleCheckTimer.unref) this.idleCheckTimer.unref();
30568
30596
  }
30569
30597
  emitEvent(type, provider, details) {
30570
30598
  const event = {
@@ -31821,7 +31849,12 @@ async function resolveResourceTemplate(uri, variables, profileLoader, workspaceM
31821
31849
  profile.role ? `**Role:** ${profile.role}` : "",
31822
31850
  profile.abilities?.length ? `**Abilities:** ${profile.abilities.join(", ")}` : "",
31823
31851
  "",
31824
- profile.systemPrompt || "No system prompt defined."
31852
+ profile.systemPrompt || "No system prompt defined.",
31853
+ "",
31854
+ "## Profile JSON",
31855
+ "```json",
31856
+ JSON.stringify(profile, null, 2),
31857
+ "```"
31825
31858
  ].filter(Boolean).join("\n");
31826
31859
  return {
31827
31860
  uri: `agent/${agent}`,
@@ -31829,8 +31862,7 @@ async function resolveResourceTemplate(uri, variables, profileLoader, workspaceM
31829
31862
  description: `AutomatosX agent profile for ${agent}`,
31830
31863
  mimeType: "text/markdown",
31831
31864
  contents: [
31832
- { type: "text", text: summary },
31833
- { type: "application/json", json: profile }
31865
+ { type: "text", text: summary }
31834
31866
  ]
31835
31867
  };
31836
31868
  }
@@ -31848,8 +31880,7 @@ async function resolveResourceTemplate(uri, variables, profileLoader, workspaceM
31848
31880
  description: `Workspace ${isPrd ? "PRD" : "tmp"} file`,
31849
31881
  mimeType: "text/markdown",
31850
31882
  contents: [
31851
- { type: "text", text: content },
31852
- { type: "application/json", json: { path: path7, content, workspace: isPrd ? "PRD" : "tmp" } }
31883
+ { type: "text", text: content }
31853
31884
  ]
31854
31885
  };
31855
31886
  }
@@ -32495,8 +32526,10 @@ v12.5.1: Agent auto-selection - if agent is omitted, system automatically select
32495
32526
  const profile = await this.profileLoader.loadProfile(agent);
32496
32527
  const content = [
32497
32528
  { type: "text", text: `System prompt for ${agent}:
32498
- ${profile.systemPrompt || "No system prompt defined."}` },
32499
- { type: "application/json", json: profile }
32529
+ ${profile.systemPrompt || "No system prompt defined."}
32530
+
32531
+ Profile:
32532
+ ${JSON.stringify(profile, null, 2)}` }
32500
32533
  ];
32501
32534
  return { jsonrpc: "2.0", id, result: { prompt: { name, description: "Agent context", arguments: [{ name: "agent", required: true }] }, content } };
32502
32535
  } catch (error) {
@@ -32513,8 +32546,10 @@ ${profile.systemPrompt || "No system prompt defined."}` },
32513
32546
  { type: "text", text: `AutomatosX MCP status:
32514
32547
  Version: ${summary.version}
32515
32548
  Providers: ${summary.providerCount}
32516
- Streaming: ${summary.streamingNotifications}` },
32517
- { type: "application/json", json: summary }
32549
+ Streaming: ${summary.streamingNotifications}
32550
+
32551
+ Details:
32552
+ ${JSON.stringify(summary, null, 2)}` }
32518
32553
  ];
32519
32554
  return { jsonrpc: "2.0", id, result: { prompt: { name, description: "AutomatosX status" }, content } };
32520
32555
  }
@@ -32539,11 +32574,15 @@ Streaming: ${summary.streamingNotifications}` },
32539
32574
  profile.role ? `**Role:** ${profile.role}` : "",
32540
32575
  profile.abilities?.length ? `**Abilities:** ${profile.abilities.join(", ")}` : "",
32541
32576
  "",
32542
- profile.systemPrompt || "No system prompt defined."
32577
+ profile.systemPrompt || "No system prompt defined.",
32578
+ "",
32579
+ "## Profile JSON",
32580
+ "```json",
32581
+ JSON.stringify(profile, null, 2),
32582
+ "```"
32543
32583
  ].filter(Boolean).join("\n");
32544
32584
  const contents = [
32545
- { type: "text", text: summary },
32546
- { type: "application/json", json: profile }
32585
+ { type: "text", text: summary }
32547
32586
  ];
32548
32587
  return { jsonrpc: "2.0", id, result: { uri, mimeType: "text/markdown", contents } };
32549
32588
  } catch (error) {
@@ -32586,15 +32625,8 @@ Streaming: ${summary.streamingNotifications}` },
32586
32625
  }
32587
32626
  /** Create MCP tool response wrapper */
32588
32627
  createToolResponse(id, result, isError = false) {
32589
- let content;
32590
- if (typeof result === "string") {
32591
- content = [{ type: "text", text: result }];
32592
- } else {
32593
- content = [
32594
- { type: "application/json", json: result },
32595
- { type: "text", text: JSON.stringify(result, null, 2) }
32596
- ];
32597
- }
32628
+ const text = typeof result === "string" ? result : JSON.stringify(result, null, 2);
32629
+ const content = [{ type: "text", text }];
32598
32630
  const response = { content, ...isError && { isError } };
32599
32631
  return { jsonrpc: "2.0", id, result: response };
32600
32632
  }
@@ -33119,6 +33151,7 @@ var MetricsCollector = class {
33119
33151
  this.collectionInterval = setInterval(() => {
33120
33152
  this.cleanup();
33121
33153
  }, this.collectionIntervalMs);
33154
+ if (this.collectionInterval.unref) this.collectionInterval.unref();
33122
33155
  }
33123
33156
  /**
33124
33157
  * Stop metrics collection
@@ -33410,6 +33443,7 @@ var ResourceEnforcer = class {
33410
33443
  });
33411
33444
  }
33412
33445
  }, this.checkIntervalMs);
33446
+ if (this.checkInterval.unref) this.checkInterval.unref();
33413
33447
  }
33414
33448
  /**
33415
33449
  * Stop enforcing resource limits
@@ -33656,6 +33690,7 @@ function createResourceEnforcer(config) {
33656
33690
  }
33657
33691
 
33658
33692
  // src/mcp/unified-manager.ts
33693
+ init_validation_limits();
33659
33694
  var UnifiedMCPManager = class {
33660
33695
  constructor(config) {
33661
33696
  this.config = config;
@@ -33975,35 +34010,36 @@ var UnifiedMCPManager = class {
33975
34010
  }
33976
34011
  /**
33977
34012
  * Run health check on all servers
34013
+ * v12.5.3: Parallelized health checks for better performance
33978
34014
  *
33979
34015
  * @returns Array of health check results
33980
34016
  */
33981
34017
  async healthCheck() {
33982
34018
  logger.debug("UnifiedMCPManager: Running health checks");
33983
- const results = [];
33984
- for (const [serverName, serverProcess] of this.servers) {
33985
- const result = await this.healthCheckServer(serverName, serverProcess);
33986
- results.push(result);
33987
- }
34019
+ const serverEntries = Array.from(this.servers.entries());
34020
+ const results = await Promise.all(
34021
+ serverEntries.map(
34022
+ ([serverName, serverProcess]) => this.healthCheckServer(serverName, serverProcess)
34023
+ )
34024
+ );
33988
34025
  return results;
33989
34026
  }
33990
34027
  /**
33991
34028
  * Get metrics for all servers (Phase 4D)
34029
+ * v12.5.3: Parallelized metrics collection for better performance
33992
34030
  *
33993
34031
  * @returns Array of server metrics
33994
34032
  */
33995
34033
  async getMetrics() {
33996
- const metrics = [];
33997
- for (const [serverName, serverProcess] of this.servers) {
33998
- if (!serverProcess.running || !serverProcess.process.pid) {
33999
- continue;
34000
- }
34001
- const serverMetrics = await this.metricsCollector.collectServerMetrics(
34002
- serverName,
34003
- serverProcess.process.pid
34004
- );
34005
- metrics.push(serverMetrics);
34006
- }
34034
+ const runningServers = Array.from(this.servers.entries()).filter(([, serverProcess]) => serverProcess.running && serverProcess.process.pid);
34035
+ const metrics = await Promise.all(
34036
+ runningServers.map(
34037
+ ([serverName, serverProcess]) => this.metricsCollector.collectServerMetrics(
34038
+ serverName,
34039
+ serverProcess.process.pid
34040
+ )
34041
+ )
34042
+ );
34007
34043
  return metrics;
34008
34044
  }
34009
34045
  /**
@@ -34214,9 +34250,10 @@ var UnifiedMCPManager = class {
34214
34250
  }
34215
34251
  /**
34216
34252
  * Start periodic health checking
34253
+ * v12.5.3: Use centralized TIMEOUTS.CONFIG_CACHE_TTL for default
34217
34254
  */
34218
34255
  startHealthChecking() {
34219
- const intervalMs = this.config.healthCheck?.intervalMs || 6e4;
34256
+ const intervalMs = this.config.healthCheck?.intervalMs || TIMEOUTS.CONFIG_CACHE_TTL;
34220
34257
  logger.info("UnifiedMCPManager: Starting health checks", {
34221
34258
  intervalMs
34222
34259
  });
@@ -34236,6 +34273,7 @@ var UnifiedMCPManager = class {
34236
34273
  });
34237
34274
  }
34238
34275
  }, intervalMs);
34276
+ if (this.healthCheckInterval.unref) this.healthCheckInterval.unref();
34239
34277
  }
34240
34278
  /**
34241
34279
  * Discover and add servers from registry
@@ -41640,13 +41678,11 @@ function installExitHandler() {
41640
41678
  });
41641
41679
  process.on("exit", () => {
41642
41680
  });
41643
- process.on("SIGINT", async () => {
41644
- await flushAllSessions();
41645
- process.exit(130);
41681
+ process.on("SIGINT", () => {
41682
+ void flushAllSessions().catch((err) => logger.error("SIGINT flush failed", { error: err.message })).finally(() => process.exit(130));
41646
41683
  });
41647
- process.on("SIGTERM", async () => {
41648
- await flushAllSessions();
41649
- process.exit(143);
41684
+ process.on("SIGTERM", () => {
41685
+ void flushAllSessions().catch((err) => logger.error("SIGTERM flush failed", { error: err.message })).finally(() => process.exit(143));
41650
41686
  });
41651
41687
  exitHandlerInstalled = true;
41652
41688
  logger.debug("Session manager exit handler installed");
package/dist/mcp/index.js CHANGED
@@ -193,7 +193,9 @@ var init_validation_limits = __esm({
193
193
  /** Quick CLI command timeout (3 seconds) */
194
194
  QUICK_COMMAND: 3e3,
195
195
  /** CLI version check timeout (10 seconds) */
196
- VERSION_CHECK: 1e4
196
+ VERSION_CHECK: 1e4,
197
+ /** MCP agent execution timeout (5 minutes) */
198
+ MCP_AGENT_EXECUTION: 3e5
197
199
  };
198
200
  DATABASE = {
199
201
  /** SQLite busy timeout in milliseconds */
@@ -4719,6 +4721,37 @@ var init_flags = __esm({
4719
4721
  }
4720
4722
  });
4721
4723
 
4724
+ // src/shared/errors/error-wrapper.ts
4725
+ function getErrorMessage(error) {
4726
+ if (error instanceof Error) {
4727
+ return error.message;
4728
+ }
4729
+ if (typeof error === "string") {
4730
+ return error;
4731
+ }
4732
+ if (error && typeof error === "object") {
4733
+ const obj = error;
4734
+ if (obj.error && typeof obj.error === "object") {
4735
+ const nested = obj.error;
4736
+ if (typeof nested.message === "string") {
4737
+ return nested.message;
4738
+ }
4739
+ }
4740
+ if (typeof obj.error === "string") {
4741
+ return obj.error;
4742
+ }
4743
+ if ("message" in obj) {
4744
+ return String(obj.message);
4745
+ }
4746
+ }
4747
+ return String(error);
4748
+ }
4749
+ var init_error_wrapper = __esm({
4750
+ "src/shared/errors/error-wrapper.ts"() {
4751
+ init_esm_shims();
4752
+ }
4753
+ });
4754
+
4722
4755
  // src/providers/fallback-decision.ts
4723
4756
  function decideFallback(error, providerName) {
4724
4757
  const errorMessage = getErrorMessage(error).toLowerCase();
@@ -4789,30 +4822,6 @@ function decideFallback(error, providerName) {
4789
4822
  severity: "error"
4790
4823
  };
4791
4824
  }
4792
- function getErrorMessage(error) {
4793
- if (error instanceof Error) {
4794
- return error.message;
4795
- }
4796
- if (typeof error === "string") {
4797
- return error;
4798
- }
4799
- if (error && typeof error === "object") {
4800
- const obj = error;
4801
- if (typeof obj.message === "string") {
4802
- return obj.message;
4803
- }
4804
- if (typeof obj.error === "string") {
4805
- return obj.error;
4806
- }
4807
- if (obj.error && typeof obj.error === "object") {
4808
- const innerError = obj.error;
4809
- if (typeof innerError.message === "string") {
4810
- return innerError.message;
4811
- }
4812
- }
4813
- }
4814
- return String(error);
4815
- }
4816
4825
  function getErrorCode(error) {
4817
4826
  if (error && typeof error === "object") {
4818
4827
  const obj = error;
@@ -4852,6 +4861,7 @@ var init_fallback_decision = __esm({
4852
4861
  init_esm_shims();
4853
4862
  init_logger();
4854
4863
  init_flags();
4864
+ init_error_wrapper();
4855
4865
  SDK_UNAVAILABLE_PATTERNS = [
4856
4866
  "module not found",
4857
4867
  "cannot find module",
@@ -8727,7 +8737,7 @@ var PRECOMPILED_CONFIG = {
8727
8737
  "enableFreeTierPrioritization": true,
8728
8738
  "enableWorkloadAwareRouting": true
8729
8739
  },
8730
- "version": "12.5.1"
8740
+ "version": "12.5.3"
8731
8741
  };
8732
8742
 
8733
8743
  // src/core/config/schemas.ts
@@ -12425,6 +12435,7 @@ Run 'ax doctor' to diagnose provider setup.` : "";
12425
12435
  logger.error("Health check interval failed", { error: err.message });
12426
12436
  });
12427
12437
  }, intervalMs);
12438
+ if (this.healthCheckInterval.unref) this.healthCheckInterval.unref();
12428
12439
  logger.debug("Starting background health checks", {
12429
12440
  interval: intervalMs,
12430
12441
  providers: this.providers.map((p) => p.name)
@@ -16609,16 +16620,21 @@ var ProfileLoader = class {
16609
16620
  logger.debug("Building displayName mapping table");
16610
16621
  this.displayNameMap.clear();
16611
16622
  try {
16612
- const localProfiles = await this.listProfilesFromDir(this.profilesDir);
16623
+ const [localProfiles, fallbackProfiles] = await Promise.all([
16624
+ this.listProfilesFromDir(this.profilesDir),
16625
+ this.listProfilesFromDir(this.fallbackProfilesDir)
16626
+ ]);
16613
16627
  for (const name of localProfiles) {
16614
16628
  await this.addToDisplayNameMap(name, "local");
16615
16629
  }
16616
- const fallbackProfiles = await this.listProfilesFromDir(this.fallbackProfilesDir);
16617
- for (const name of fallbackProfiles) {
16630
+ const fallbacksToProcess = fallbackProfiles.filter((name) => {
16618
16631
  if (localProfiles.includes(name)) {
16619
16632
  logger.debug("Skipping fallback profile (local override)", { name });
16620
- continue;
16633
+ return false;
16621
16634
  }
16635
+ return true;
16636
+ });
16637
+ for (const name of fallbacksToProcess) {
16622
16638
  await this.addToDisplayNameMap(name, "fallback");
16623
16639
  }
16624
16640
  this.mapInitialized = true;
@@ -20770,6 +20786,12 @@ function mapNormalizedCallerToActual(caller) {
20770
20786
  }
20771
20787
 
20772
20788
  // src/mcp/tools/run-agent.ts
20789
+ init_validation_limits();
20790
+ function checkAborted(signal) {
20791
+ if (signal?.aborted) {
20792
+ throw new Error("Request was cancelled");
20793
+ }
20794
+ }
20773
20795
  async function executeViaMcpPool(provider, agent, task, pool) {
20774
20796
  const startTime = Date.now();
20775
20797
  const client = await pool.acquire(provider);
@@ -20790,17 +20812,20 @@ async function executeViaMcpPool(provider, agent, task, pool) {
20790
20812
  pool.release(provider, client);
20791
20813
  }
20792
20814
  }
20793
- async function executeViaCli(agent, task, actualProvider, no_memory, deps, isFallback, signal) {
20815
+ var MCP_DEFAULT_AGENT_TIMEOUT_MS = TIMEOUTS.MCP_AGENT_EXECUTION;
20816
+ async function executeViaCli(agent, task, actualProvider, no_memory, deps, isFallback, signal, timeout) {
20794
20817
  const context = await deps.contextManager.createContext(agent, task, {
20795
20818
  provider: actualProvider,
20796
20819
  skipMemory: no_memory
20797
20820
  });
20798
20821
  const executor = new AgentExecutor(deps.executorConfig);
20799
20822
  const startTime = Date.now();
20823
+ const effectiveTimeout = timeout ?? MCP_DEFAULT_AGENT_TIMEOUT_MS;
20800
20824
  const result = await executor.execute(context, {
20801
20825
  showProgress: false,
20802
20826
  verbose: false,
20803
- signal
20827
+ signal,
20828
+ timeout: effectiveTimeout
20804
20829
  });
20805
20830
  const latencyMs = Date.now() - startTime;
20806
20831
  const executionMode = isFallback ? "cli_fallback" : "cli_spawn";
@@ -20875,9 +20900,7 @@ function createRunAgentHandler(deps) {
20875
20900
  return async (input, context) => {
20876
20901
  const { task, provider, no_memory, mode = "auto" } = input;
20877
20902
  let { agent } = input;
20878
- if (context?.signal?.aborted) {
20879
- throw new Error("Request was cancelled");
20880
- }
20903
+ checkAborted(context?.signal);
20881
20904
  validateStringParameter(task, "task", {
20882
20905
  required: true,
20883
20906
  minLength: 1,
@@ -20922,9 +20945,7 @@ function createRunAgentHandler(deps) {
20922
20945
  bestProvider = selectedProvider?.name || "claude-code";
20923
20946
  }
20924
20947
  const shouldReturnContext = mode === "context" || mode === "auto" && callerActual === bestProvider && callerProvider !== "unknown";
20925
- if (context?.signal?.aborted) {
20926
- throw new Error("Request was cancelled");
20927
- }
20948
+ checkAborted(context?.signal);
20928
20949
  logger.info("[Smart Routing] Decision", {
20929
20950
  mode,
20930
20951
  callerProvider,
@@ -20959,7 +20980,7 @@ function createRunAgentHandler(deps) {
20959
20980
  const shouldTryMcp = !!deps.mcpPool;
20960
20981
  if (shouldTryMcp && deps.mcpPool) {
20961
20982
  try {
20962
- if (context?.signal?.aborted) throw new Error("Request was cancelled");
20983
+ checkAborted(context?.signal);
20963
20984
  const result = await executeViaMcpPool(
20964
20985
  bestProvider,
20965
20986
  agent,
@@ -20989,10 +21010,8 @@ function createRunAgentHandler(deps) {
20989
21010
  }
20990
21011
  }
20991
21012
  try {
20992
- if (context?.signal?.aborted) {
20993
- throw new Error("Request was cancelled");
20994
- }
20995
- const result = await executeViaCli(agent, task, actualProvider, no_memory, deps, shouldTryMcp, context?.signal);
21013
+ checkAborted(context?.signal);
21014
+ const result = await executeViaCli(agent, task, actualProvider, no_memory, deps, shouldTryMcp, context?.signal, MCP_DEFAULT_AGENT_TIMEOUT_MS);
20996
21015
  logger.info("[MCP] run_agent completed (CLI spawn mode)", {
20997
21016
  agent,
20998
21017
  latencyMs: result.latencyMs,
@@ -21026,8 +21045,9 @@ function createListAgentsHandler(deps) {
21026
21045
  }
21027
21046
  })
21028
21047
  );
21048
+ const validProfiles = profiles.filter((profile) => profile !== null);
21029
21049
  const result = {
21030
- agents: profiles.filter((profile) => profile !== null).map((profile) => ({
21050
+ agents: validProfiles.map((profile) => ({
21031
21051
  name: profile.name,
21032
21052
  displayName: profile.displayName,
21033
21053
  role: profile.role,
@@ -21864,29 +21884,34 @@ function createGetCapabilitiesHandler(deps) {
21864
21884
  }
21865
21885
  providers.sort((a, b) => b.priority - a.priority);
21866
21886
  const agentNames = await deps.profileLoader.listProfiles();
21867
- const agents = [];
21868
- for (const agentName of agentNames) {
21869
- try {
21870
- const profile = await deps.profileLoader.loadProfile(agentName);
21871
- agents.push({
21872
- name: profile.name,
21873
- displayName: profile.displayName,
21874
- role: profile.role,
21875
- description: profile.systemPrompt?.substring(0, 200),
21876
- team: profile.team,
21877
- abilities: profile.abilities || []
21878
- });
21879
- } catch (error) {
21880
- logger.warn(`Failed to load profile for ${agentName}`, { error });
21881
- }
21882
- }
21887
+ const agentResults = await Promise.all(
21888
+ agentNames.map(async (agentName) => {
21889
+ try {
21890
+ const profile = await deps.profileLoader.loadProfile(agentName);
21891
+ return {
21892
+ name: profile.name,
21893
+ displayName: profile.displayName,
21894
+ role: profile.role,
21895
+ description: profile.systemPrompt?.substring(0, 200),
21896
+ team: profile.team,
21897
+ abilities: profile.abilities || []
21898
+ };
21899
+ } catch (error) {
21900
+ logger.warn(`Failed to load profile for ${agentName}`, { error });
21901
+ return null;
21902
+ }
21903
+ })
21904
+ );
21905
+ const agents = agentResults.filter((a) => a !== null);
21883
21906
  const tools = deps.toolSchemas.map((schema) => ({
21884
21907
  name: schema.name,
21885
21908
  description: schema.description,
21886
21909
  category: categorizeTools(schema.name)
21887
21910
  }));
21888
- const memoryStats = await deps.memoryManager.getStats();
21889
- const activeSessions = await deps.sessionManager.getActiveSessions();
21911
+ const [memoryStats, activeSessions] = await Promise.all([
21912
+ deps.memoryManager.getStats(),
21913
+ deps.sessionManager.getActiveSessions()
21914
+ ]);
21890
21915
  const result = {
21891
21916
  version,
21892
21917
  providers,
@@ -24538,17 +24563,18 @@ var ConnectionTimeoutError = class extends McpClientError {
24538
24563
  };
24539
24564
 
24540
24565
  // src/providers/mcp/pool-manager.ts
24566
+ init_validation_limits();
24541
24567
  var DEFAULT_CONFIG6 = {
24542
24568
  maxConnectionsPerProvider: 2,
24543
- idleTimeoutMs: 3e5,
24569
+ idleTimeoutMs: TIMEOUTS.IDLE_CONNECTION,
24544
24570
  // 5 minutes
24545
- healthCheckIntervalMs: 3e4,
24571
+ healthCheckIntervalMs: TIMEOUTS.MCP_HEALTH_CHECK,
24546
24572
  // 30 seconds
24547
- acquireTimeoutMs: 1e4,
24573
+ acquireTimeoutMs: TIMEOUTS.VERSION_CHECK,
24548
24574
  // 10 seconds
24549
24575
  fallbackToCli: true
24550
24576
  };
24551
- var IDLE_CLEANUP_INTERVAL_MS = 6e4;
24577
+ var IDLE_CLEANUP_INTERVAL_MS = TIMEOUTS.CONFIG_CACHE_TTL;
24552
24578
  var McpClientPool = class extends EventEmitter {
24553
24579
  config;
24554
24580
  pools = /* @__PURE__ */ new Map();
@@ -24877,6 +24903,7 @@ var McpClientPool = class extends EventEmitter {
24877
24903
  });
24878
24904
  }
24879
24905
  }, this.config.healthCheckIntervalMs);
24906
+ if (this.healthCheckTimer.unref) this.healthCheckTimer.unref();
24880
24907
  }
24881
24908
  startIdleCleanup() {
24882
24909
  this.idleCheckTimer = setInterval(() => {
@@ -24907,6 +24934,7 @@ var McpClientPool = class extends EventEmitter {
24907
24934
  }
24908
24935
  }
24909
24936
  }, IDLE_CLEANUP_INTERVAL_MS);
24937
+ if (this.idleCheckTimer.unref) this.idleCheckTimer.unref();
24910
24938
  }
24911
24939
  emitEvent(type, provider, details) {
24912
24940
  const event = {
@@ -26163,7 +26191,12 @@ async function resolveResourceTemplate(uri, variables, profileLoader, workspaceM
26163
26191
  profile.role ? `**Role:** ${profile.role}` : "",
26164
26192
  profile.abilities?.length ? `**Abilities:** ${profile.abilities.join(", ")}` : "",
26165
26193
  "",
26166
- profile.systemPrompt || "No system prompt defined."
26194
+ profile.systemPrompt || "No system prompt defined.",
26195
+ "",
26196
+ "## Profile JSON",
26197
+ "```json",
26198
+ JSON.stringify(profile, null, 2),
26199
+ "```"
26167
26200
  ].filter(Boolean).join("\n");
26168
26201
  return {
26169
26202
  uri: `agent/${agent}`,
@@ -26171,8 +26204,7 @@ async function resolveResourceTemplate(uri, variables, profileLoader, workspaceM
26171
26204
  description: `AutomatosX agent profile for ${agent}`,
26172
26205
  mimeType: "text/markdown",
26173
26206
  contents: [
26174
- { type: "text", text: summary },
26175
- { type: "application/json", json: profile }
26207
+ { type: "text", text: summary }
26176
26208
  ]
26177
26209
  };
26178
26210
  }
@@ -26190,8 +26222,7 @@ async function resolveResourceTemplate(uri, variables, profileLoader, workspaceM
26190
26222
  description: `Workspace ${isPrd ? "PRD" : "tmp"} file`,
26191
26223
  mimeType: "text/markdown",
26192
26224
  contents: [
26193
- { type: "text", text: content },
26194
- { type: "application/json", json: { path: path7, content, workspace: isPrd ? "PRD" : "tmp" } }
26225
+ { type: "text", text: content }
26195
26226
  ]
26196
26227
  };
26197
26228
  }
@@ -26837,8 +26868,10 @@ v12.5.1: Agent auto-selection - if agent is omitted, system automatically select
26837
26868
  const profile = await this.profileLoader.loadProfile(agent);
26838
26869
  const content = [
26839
26870
  { type: "text", text: `System prompt for ${agent}:
26840
- ${profile.systemPrompt || "No system prompt defined."}` },
26841
- { type: "application/json", json: profile }
26871
+ ${profile.systemPrompt || "No system prompt defined."}
26872
+
26873
+ Profile:
26874
+ ${JSON.stringify(profile, null, 2)}` }
26842
26875
  ];
26843
26876
  return { jsonrpc: "2.0", id, result: { prompt: { name, description: "Agent context", arguments: [{ name: "agent", required: true }] }, content } };
26844
26877
  } catch (error) {
@@ -26855,8 +26888,10 @@ ${profile.systemPrompt || "No system prompt defined."}` },
26855
26888
  { type: "text", text: `AutomatosX MCP status:
26856
26889
  Version: ${summary.version}
26857
26890
  Providers: ${summary.providerCount}
26858
- Streaming: ${summary.streamingNotifications}` },
26859
- { type: "application/json", json: summary }
26891
+ Streaming: ${summary.streamingNotifications}
26892
+
26893
+ Details:
26894
+ ${JSON.stringify(summary, null, 2)}` }
26860
26895
  ];
26861
26896
  return { jsonrpc: "2.0", id, result: { prompt: { name, description: "AutomatosX status" }, content } };
26862
26897
  }
@@ -26881,11 +26916,15 @@ Streaming: ${summary.streamingNotifications}` },
26881
26916
  profile.role ? `**Role:** ${profile.role}` : "",
26882
26917
  profile.abilities?.length ? `**Abilities:** ${profile.abilities.join(", ")}` : "",
26883
26918
  "",
26884
- profile.systemPrompt || "No system prompt defined."
26919
+ profile.systemPrompt || "No system prompt defined.",
26920
+ "",
26921
+ "## Profile JSON",
26922
+ "```json",
26923
+ JSON.stringify(profile, null, 2),
26924
+ "```"
26885
26925
  ].filter(Boolean).join("\n");
26886
26926
  const contents = [
26887
- { type: "text", text: summary },
26888
- { type: "application/json", json: profile }
26927
+ { type: "text", text: summary }
26889
26928
  ];
26890
26929
  return { jsonrpc: "2.0", id, result: { uri, mimeType: "text/markdown", contents } };
26891
26930
  } catch (error) {
@@ -26928,15 +26967,8 @@ Streaming: ${summary.streamingNotifications}` },
26928
26967
  }
26929
26968
  /** Create MCP tool response wrapper */
26930
26969
  createToolResponse(id, result, isError = false) {
26931
- let content;
26932
- if (typeof result === "string") {
26933
- content = [{ type: "text", text: result }];
26934
- } else {
26935
- content = [
26936
- { type: "application/json", json: result },
26937
- { type: "text", text: JSON.stringify(result, null, 2) }
26938
- ];
26939
- }
26970
+ const text = typeof result === "string" ? result : JSON.stringify(result, null, 2);
26971
+ const content = [{ type: "text", text }];
26940
26972
  const response = { content, ...isError && { isError } };
26941
26973
  return { jsonrpc: "2.0", id, result: response };
26942
26974
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@defai.digital/automatosx",
3
- "version": "12.5.1",
3
+ "version": "12.5.3",
4
4
  "description": "Provider-agnostic AI orchestration platform with 20+ specialized agents, persistent memory, and multi-provider routing for Claude Code, Gemini CLI, Codex CLI, GLM, and Grok",
5
5
  "type": "module",
6
6
  "publishConfig": {