@defai.digital/automatosx 12.3.1 → 12.4.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/mcp/index.js CHANGED
@@ -1,18 +1,19 @@
1
1
  #!/usr/bin/env node
2
2
  import * as path4 from 'path';
3
- import path4__default, { dirname, join, extname as extname$1, basename, resolve, relative, isAbsolute, sep, parse, delimiter } from 'path';
3
+ import path4__default, { dirname, join, extname as extname$1, basename, resolve, relative, isAbsolute, sep, delimiter, parse } from 'path';
4
4
  import { fileURLToPath } from 'url';
5
5
  import { mkdir, appendFile, readFile, readdir, writeFile, rename, unlink, copyFile, access, stat, realpath } from 'fs/promises';
6
6
  import * as fs4 from 'fs';
7
7
  import { existsSync, readFileSync, promises, mkdirSync, createWriteStream, writeFileSync, unlinkSync, constants } from 'fs';
8
8
  import Database2 from 'better-sqlite3';
9
9
  import { glob } from 'glob';
10
- import { spawn, spawnSync } from 'child_process';
10
+ import { spawn, exec, spawnSync } from 'child_process';
11
11
  import { z, ZodError } from 'zod';
12
12
  import chalk4 from 'chalk';
13
13
  import ora2 from 'ora';
14
14
  import readline, { createInterface } from 'readline';
15
15
  import { Mutex } from 'async-mutex';
16
+ import { promisify } from 'util';
16
17
  import Ajv from 'ajv';
17
18
  import addFormats from 'ajv-formats';
18
19
  import os2, { cpus } from 'os';
@@ -37,6 +38,226 @@ var init_esm_shims = __esm({
37
38
  "node_modules/.pnpm/tsup@8.5.1_jiti@2.6.1_postcss@8.5.6_tsx@4.20.6_typescript@5.9.3_yaml@2.8.2/node_modules/tsup/assets/esm_shims.js"() {
38
39
  }
39
40
  });
41
+
42
+ // src/core/validation-limits.ts
43
+ function isValidRelativePath(path7) {
44
+ if (!path7 || typeof path7 !== "string") {
45
+ return false;
46
+ }
47
+ const normalizedPath = path7.replace(/\\/g, "/");
48
+ if (normalizedPath.startsWith("/")) {
49
+ return false;
50
+ }
51
+ if (normalizedPath.includes("..")) {
52
+ return false;
53
+ }
54
+ if (/^[a-zA-Z]:/.test(normalizedPath)) {
55
+ return false;
56
+ }
57
+ if (normalizedPath.startsWith("//")) {
58
+ return false;
59
+ }
60
+ return true;
61
+ }
62
+ function isValidCommand(command) {
63
+ if (!command || typeof command !== "string") {
64
+ return false;
65
+ }
66
+ if (command.length > VALIDATION_LIMITS.MAX_COMMAND_LENGTH) {
67
+ return false;
68
+ }
69
+ if (!/^[a-z0-9_-]+$/i.test(command)) {
70
+ return false;
71
+ }
72
+ return true;
73
+ }
74
+ function isValidName(name) {
75
+ if (!name || typeof name !== "string") {
76
+ return false;
77
+ }
78
+ if (name.length > VALIDATION_LIMITS.MAX_NAME_LENGTH) {
79
+ return false;
80
+ }
81
+ if (!/^[a-z0-9][a-z0-9-_]*$/i.test(name)) {
82
+ return false;
83
+ }
84
+ return true;
85
+ }
86
+ function isValidExtension(ext) {
87
+ if (!ext || typeof ext !== "string") {
88
+ return false;
89
+ }
90
+ const normalized = ext.startsWith(".") ? ext : `.${ext}`;
91
+ if (normalized.length > 10 || normalized.length < 2) {
92
+ return false;
93
+ }
94
+ if (!/^\.[a-z0-9]+$/i.test(normalized)) {
95
+ return false;
96
+ }
97
+ return true;
98
+ }
99
+ function isPositiveInteger(value) {
100
+ return typeof value === "number" && Number.isInteger(value) && value > 0;
101
+ }
102
+ function isNonNegativeInteger(value) {
103
+ return typeof value === "number" && Number.isInteger(value) && value >= 0;
104
+ }
105
+ var AX_PATHS, TIMEOUTS, DATABASE, VALIDATION_LIMITS;
106
+ var init_validation_limits = __esm({
107
+ "src/core/validation-limits.ts"() {
108
+ init_esm_shims();
109
+ AX_PATHS = {
110
+ /** Root directory for AutomatosX data */
111
+ ROOT: ".automatosx",
112
+ /** Log files directory */
113
+ LOGS: ".automatosx/logs",
114
+ /** Memory/database directory */
115
+ MEMORY: ".automatosx/memory",
116
+ /** Agent workspaces directory */
117
+ WORKSPACES: ".automatosx/workspaces",
118
+ /** Session data directory */
119
+ SESSIONS: ".automatosx/sessions",
120
+ /** Team configurations directory */
121
+ TEAMS: ".automatosx/teams",
122
+ /** Agent profiles directory */
123
+ AGENTS: ".automatosx/agents",
124
+ /** Workflow definitions directory */
125
+ WORKFLOWS: ".automatosx/workflows",
126
+ /** Abilities/skills directory */
127
+ ABILITIES: ".automatosx/abilities",
128
+ /** Checkpoints directory */
129
+ CHECKPOINTS: ".automatosx/checkpoints",
130
+ /** Cache directory */
131
+ CACHE: ".automatosx/cache",
132
+ /** Task database directory */
133
+ TASKS: ".automatosx/tasks",
134
+ /** Status files directory */
135
+ STATUS: ".automatosx/status",
136
+ /** Provider configurations directory */
137
+ PROVIDERS: ".automatosx/providers",
138
+ /** Iterate mode directory */
139
+ ITERATE: ".automatosx/iterate",
140
+ /** State directory (mode, provider overrides) */
141
+ STATE: ".automatosx/state",
142
+ /** Usage tracking directory */
143
+ USAGE: ".automatosx/usage",
144
+ /** Context store directory */
145
+ CONTEXT: ".automatosx/context",
146
+ /** Telemetry directory */
147
+ TELEMETRY: ".automatosx/telemetry",
148
+ /** Workspace index directory */
149
+ WORKSPACE: ".automatosx/workspace",
150
+ /** Config file paths */
151
+ CONFIG_YAML: ".automatosx/config.yaml",
152
+ CONFIG_JSON: ".automatosx/config.json"
153
+ };
154
+ TIMEOUTS = {
155
+ /** Default provider execution timeout (2 minutes) */
156
+ PROVIDER_DEFAULT: 12e4,
157
+ /** Provider detection/health check timeout (5 seconds) */
158
+ PROVIDER_DETECTION: 5e3,
159
+ /** Database busy timeout (5 seconds) */
160
+ DATABASE_BUSY: 5e3,
161
+ /** Provider cooldown after failure (30 seconds) */
162
+ PROVIDER_COOLDOWN: 3e4,
163
+ /** Circuit breaker recovery timeout (1 minute) */
164
+ CIRCUIT_BREAKER_RECOVERY: 6e4,
165
+ /** Circuit breaker failure window (5 minutes) */
166
+ CIRCUIT_BREAKER_WINDOW: 3e5,
167
+ /** Health check interval (5 minutes) */
168
+ HEALTH_CHECK_INTERVAL: 3e5,
169
+ /** Idle connection timeout (5 minutes) */
170
+ IDLE_CONNECTION: 3e5,
171
+ /** User decision/prompt timeout (10 minutes) */
172
+ USER_DECISION: 6e5,
173
+ /** Maximum execution timeout (1 hour) */
174
+ MAX_EXECUTION: 36e5,
175
+ /** Default global timeout (25 minutes) */
176
+ GLOBAL_DEFAULT: 15e5,
177
+ /** Config cache TTL (1 minute) */
178
+ CONFIG_CACHE_TTL: 6e4,
179
+ /** Score cache TTL (5 minutes) */
180
+ SCORE_CACHE_TTL: 3e5,
181
+ /** MCP health check interval (30 seconds) */
182
+ MCP_HEALTH_CHECK: 3e4,
183
+ /** CLI command confirmation delay (5 seconds) */
184
+ CLI_CONFIRM_DELAY: 5e3,
185
+ /** Kill switch confirmation delay (5 seconds) */
186
+ KILL_SWITCH_DELAY: 5e3,
187
+ /** Minimum rollout duration (1 hour) */
188
+ MIN_ROLLOUT_DURATION: 36e5,
189
+ /** Graceful shutdown timeout (30 seconds) */
190
+ GRACEFUL_SHUTDOWN: 3e4,
191
+ /** Package installation timeout (1 minute) */
192
+ PACKAGE_INSTALL: 6e4,
193
+ /** Quick CLI command timeout (3 seconds) */
194
+ QUICK_COMMAND: 3e3,
195
+ /** CLI version check timeout (10 seconds) */
196
+ VERSION_CHECK: 1e4
197
+ };
198
+ DATABASE = {
199
+ /** SQLite busy timeout in milliseconds */
200
+ BUSY_TIMEOUT: 5e3,
201
+ /** Maximum database connections in pool */
202
+ MAX_CONNECTIONS: 10,
203
+ /** Connection idle timeout (5 minutes) */
204
+ IDLE_TIMEOUT: 3e5,
205
+ /** Default query limit */
206
+ DEFAULT_QUERY_LIMIT: 1e3,
207
+ /** Maximum query limit */
208
+ MAX_QUERY_LIMIT: 1e4
209
+ };
210
+ VALIDATION_LIMITS = {
211
+ // Resource limits (prevent DoS)
212
+ MAX_ENTRIES: 1e6,
213
+ // 1 million entries (memory, cache)
214
+ MAX_TIMEOUT: 36e5,
215
+ // 1 hour (execution, delegation)
216
+ MAX_FILE_SIZE: 104857600,
217
+ // 100 MB (workspace, abilities)
218
+ MAX_CACHE_SIZE: 524288e3,
219
+ // 500 MB (cache storage)
220
+ MAX_SESSIONS: 1e4,
221
+ // 10k concurrent sessions
222
+ // Performance limits (prevent resource exhaustion)
223
+ MAX_CONCURRENT_AGENTS: 100,
224
+ // Maximum concurrent agents
225
+ MAX_CPU_PERCENT: 80,
226
+ // Maximum CPU usage percent
227
+ MAX_MEMORY_MB: 2048,
228
+ // Maximum memory usage in MB
229
+ // Config validation limits
230
+ MAX_CONFIG_FILE_SIZE: 1048576,
231
+ // 1MB max config file size
232
+ MAX_NAME_LENGTH: 50,
233
+ // Max name length for agents/providers
234
+ MAX_COMMAND_LENGTH: 100,
235
+ // Max command length
236
+ MAX_ARRAY_LENGTH: 1e4,
237
+ // Max array elements in config
238
+ // Path and file limits
239
+ MIN_FILE_SIZE: 1,
240
+ // Minimum file size in bytes
241
+ MIN_TIMEOUT: 1e3,
242
+ // Minimum timeout in ms (1 second)
243
+ MIN_INTERVAL: 100,
244
+ // Minimum interval in ms
245
+ MIN_BACKOFF_FACTOR: 1,
246
+ // Minimum backoff multiplier
247
+ MAX_BACKOFF_FACTOR: 5,
248
+ // Maximum backoff multiplier
249
+ MAX_TTL: 864e5,
250
+ // Maximum TTL in ms (24 hours)
251
+ MIN_BYTES: 1,
252
+ // Minimum bytes for file sizes
253
+ // Network limits
254
+ MIN_PORT: 1024,
255
+ // Minimum port number
256
+ MAX_PORT: 65535
257
+ // Maximum port number
258
+ };
259
+ }
260
+ });
40
261
  function sanitizeObject(obj, maxDepth = 5, currentDepth = 0) {
41
262
  if (currentDepth > maxDepth) {
42
263
  return "[Max Depth Reached]";
@@ -581,7 +802,7 @@ function installExitHandlers() {
581
802
  if (process.stderr.writable) {
582
803
  process.stderr.end();
583
804
  }
584
- } catch (error) {
805
+ } catch (_error) {
585
806
  }
586
807
  process.exit(signal === "SIGTERM" || signal === "SIGINT" ? 0 : 1);
587
808
  };
@@ -602,6 +823,7 @@ var init_process_manager = __esm({
602
823
  "src/shared/process/process-manager.ts"() {
603
824
  init_esm_shims();
604
825
  init_logger();
826
+ init_validation_limits();
605
827
  ProcessManager = class {
606
828
  childProcesses = /* @__PURE__ */ new Set();
607
829
  isShuttingDown = false;
@@ -638,7 +860,7 @@ var init_process_manager = __esm({
638
860
  *
639
861
  * @param timeout Maximum time to wait for graceful shutdown (ms)
640
862
  */
641
- async shutdown(timeout = 5e3) {
863
+ async shutdown(timeout = TIMEOUTS.PROVIDER_DETECTION) {
642
864
  if (this.isShuttingDown) {
643
865
  return;
644
866
  }
@@ -767,9 +989,10 @@ var init_factory = __esm({
767
989
  "src/core/database/factory.ts"() {
768
990
  init_esm_shims();
769
991
  init_logger();
992
+ init_validation_limits();
770
993
  DEFAULT_OPTIONS = {
771
994
  readonly: false,
772
- busyTimeout: 5e3,
995
+ busyTimeout: DATABASE.BUSY_TIMEOUT,
773
996
  verbose: false,
774
997
  enableWal: true,
775
998
  createDir: true
@@ -1615,8 +1838,8 @@ var init_verbosity_manager = __esm({
1615
1838
  }
1616
1839
  });
1617
1840
  function findOnPath(cmdBase) {
1618
- const isWindows2 = process.platform === "win32";
1619
- if (isWindows2) {
1841
+ const isWindows = process.platform === "win32";
1842
+ if (isWindows) {
1620
1843
  return findOnPathWindows(cmdBase);
1621
1844
  }
1622
1845
  return findOnPathUnix(cmdBase);
@@ -1964,9 +2187,10 @@ var init_streaming_progress_parser = __esm({
1964
2187
  // src/providers/error-patterns.ts
1965
2188
  function isQuotaError(error, providerName) {
1966
2189
  const patterns = PROVIDER_ERROR_PATTERNS[providerName] || GENERIC_ERROR_PATTERNS;
1967
- const message = (error?.message || "").toLowerCase();
1968
- const code = error?.code || "";
1969
- const statusCode = error?.status || error?.statusCode;
2190
+ const errorObj = error;
2191
+ const message = (errorObj?.message || "").toLowerCase();
2192
+ const code = errorObj?.code || "";
2193
+ const statusCode = errorObj?.status || errorObj?.statusCode;
1970
2194
  if (patterns.quota.some((pattern) => message.includes(pattern.toLowerCase()))) {
1971
2195
  return true;
1972
2196
  }
@@ -1983,9 +2207,10 @@ function isQuotaError(error, providerName) {
1983
2207
  }
1984
2208
  function isRateLimitError(error, providerName) {
1985
2209
  const patterns = PROVIDER_ERROR_PATTERNS[providerName] || GENERIC_ERROR_PATTERNS;
1986
- const message = (error?.message || "").toLowerCase();
1987
- const code = error?.code || "";
1988
- const statusCode = error?.status || error?.statusCode;
2210
+ const errorObj = error;
2211
+ const message = (errorObj?.message || "").toLowerCase();
2212
+ const code = errorObj?.code || "";
2213
+ const statusCode = errorObj?.status || errorObj?.statusCode;
1989
2214
  if (patterns.rateLimit.some((pattern) => message.includes(pattern.toLowerCase()))) {
1990
2215
  return true;
1991
2216
  }
@@ -2224,6 +2449,7 @@ var init_base_provider = __esm({
2224
2449
  init_esm_shims();
2225
2450
  init_logger();
2226
2451
  init_errors();
2452
+ init_validation_limits();
2227
2453
  init_cli_provider_detector();
2228
2454
  init_provider_schemas();
2229
2455
  init_streaming_progress_parser();
@@ -2266,15 +2492,16 @@ var init_base_provider = __esm({
2266
2492
  DEBIAN_FRONTEND: "noninteractive"
2267
2493
  };
2268
2494
  /** Default CLI execution timeout in milliseconds */
2269
- static DEFAULT_TIMEOUT_MS = 12e4;
2495
+ static DEFAULT_TIMEOUT_MS = TIMEOUTS.PROVIDER_DEFAULT;
2270
2496
  /** Time to wait after SIGTERM before escalating to SIGKILL */
2271
- static SIGKILL_ESCALATION_MS = 5e3;
2497
+ static SIGKILL_ESCALATION_MS = TIMEOUTS.PROVIDER_DETECTION;
2272
2498
  config;
2273
2499
  logger = logger;
2274
2500
  health;
2275
2501
  constructor(config) {
2276
2502
  const providerName = config.name.toLowerCase();
2277
- if (!_BaseProvider.ALLOWED_PROVIDER_NAMES.includes(providerName)) {
2503
+ const allowedNames = _BaseProvider.ALLOWED_PROVIDER_NAMES;
2504
+ if (!allowedNames.includes(providerName)) {
2278
2505
  throw new ProviderError(
2279
2506
  `Invalid provider name: ${config.name}. Allowed: ${_BaseProvider.ALLOWED_PROVIDER_NAMES.join(", ")}`,
2280
2507
  "E1001" /* CONFIG_INVALID */
@@ -2319,8 +2546,8 @@ var init_base_provider = __esm({
2319
2546
  const escapedPrompt = this.escapeShellArg(prompt);
2320
2547
  const fullCommand = `${cliCommand} ${argsString}${escapedPrompt}`;
2321
2548
  const commandLength = fullCommand.length;
2322
- const isWindows2 = process.platform === "win32";
2323
- const useStdin = isWindows2 && commandLength > 7e3;
2549
+ const isWindows = process.platform === "win32";
2550
+ const useStdin = isWindows && commandLength > 7e3;
2324
2551
  logger.debug(`Executing ${cliCommand} CLI with streaming support`, {
2325
2552
  command: cliCommand,
2326
2553
  promptLength: prompt.length,
@@ -2909,8 +3136,8 @@ ${fullPrompt}
2909
3136
  * - Windows: hello"world → "hello\"world"
2910
3137
  */
2911
3138
  escapeShellArg(arg) {
2912
- const isWindows2 = process.platform === "win32";
2913
- if (isWindows2) {
3139
+ const isWindows = process.platform === "win32";
3140
+ if (isWindows) {
2914
3141
  return '"' + arg.replace(/"/g, '\\"').replace(/%/g, "%%") + '"';
2915
3142
  } else {
2916
3143
  return "'" + arg.replace(/'/g, "'\\''") + "'";
@@ -3778,7 +4005,7 @@ var init_sdk_adapter = __esm({
3778
4005
  this.codex = new this.sdkModule.Codex();
3779
4006
  this.initialized = true;
3780
4007
  logger.info("Codex SDK initialized");
3781
- } catch (error) {
4008
+ } catch (_error) {
3782
4009
  throw new CodexError(
3783
4010
  "CLI_NOT_FOUND" /* CLI_NOT_FOUND */,
3784
4011
  "Codex SDK not available. Install with: npm install @openai/codex-sdk"
@@ -4050,117 +4277,3317 @@ var init_openai_provider = __esm({
4050
4277
  getCLICommand() {
4051
4278
  return "codex";
4052
4279
  }
4053
- getCLIArgs() {
4054
- return ["--json"];
4280
+ getCLIArgs() {
4281
+ return ["--json"];
4282
+ }
4283
+ getMockResponse() {
4284
+ return "[Mock OpenAI/Codex Response]\n\nThis is a mock response for testing purposes.";
4285
+ }
4286
+ get capabilities() {
4287
+ return {
4288
+ supportsStreaming: true,
4289
+ supportsEmbedding: false,
4290
+ supportsVision: true,
4291
+ maxContextTokens: 128e3,
4292
+ supportedModels: ["codex"]
4293
+ };
4294
+ }
4295
+ getActiveMode() {
4296
+ return this.hybridAdapter?.getActiveMode() || null;
4297
+ }
4298
+ switchToCliMode() {
4299
+ this.hybridAdapter?.switchToCliMode();
4300
+ }
4301
+ async destroy() {
4302
+ this.isDestroyed = true;
4303
+ if (this.hybridAdapter) {
4304
+ await this.hybridAdapter.destroy();
4305
+ this.hybridAdapter = null;
4306
+ }
4307
+ }
4308
+ };
4309
+ }
4310
+ });
4311
+
4312
+ // src/providers/openai-provider-factory.ts
4313
+ var openai_provider_factory_exports = {};
4314
+ __export(openai_provider_factory_exports, {
4315
+ createOpenAIProviderAsync: () => createOpenAIProviderAsync,
4316
+ createOpenAIProviderSync: () => createOpenAIProviderSync,
4317
+ getIntegrationMode: () => getIntegrationMode,
4318
+ isCLIModeAvailable: () => isCLIModeAvailable,
4319
+ isSDKModeAvailable: () => isSDKModeAvailable
4320
+ });
4321
+ function createOpenAIProviderSync(config, integrationMode) {
4322
+ logger.debug("Created OpenAI CLI provider (v8.3.0: CLI-only)", {
4323
+ provider: config.name,
4324
+ mode: "cli"
4325
+ });
4326
+ return new OpenAIProvider(config);
4327
+ }
4328
+ async function createOpenAIProviderAsync(config, integrationMode, interactive = false) {
4329
+ logger.info("Creating OpenAI CLI provider (v8.3.0: CLI-only)", {
4330
+ provider: config.name,
4331
+ mode: "cli"
4332
+ });
4333
+ return new OpenAIProvider(config);
4334
+ }
4335
+ function getIntegrationMode(config) {
4336
+ return config.integration;
4337
+ }
4338
+ function isSDKModeAvailable() {
4339
+ const hasAPIKey = !!process.env.OPENAI_API_KEY;
4340
+ let hasSDK = false;
4341
+ try {
4342
+ if (typeof import.meta.resolve === "function") {
4343
+ import.meta.resolve("openai");
4344
+ hasSDK = true;
4345
+ } else {
4346
+ hasSDK = true;
4347
+ }
4348
+ } catch {
4349
+ hasSDK = false;
4350
+ }
4351
+ return hasAPIKey && hasSDK;
4352
+ }
4353
+ async function isCLIModeAvailable() {
4354
+ try {
4355
+ const { execSync } = await import('child_process');
4356
+ execSync("codex --version", {
4357
+ encoding: "utf-8",
4358
+ stdio: ["pipe", "pipe", "pipe"],
4359
+ timeout: TIMEOUTS.QUICK_COMMAND
4360
+ });
4361
+ return true;
4362
+ } catch {
4363
+ return false;
4364
+ }
4365
+ }
4366
+ var init_openai_provider_factory = __esm({
4367
+ "src/providers/openai-provider-factory.ts"() {
4368
+ init_esm_shims();
4369
+ init_openai_provider();
4370
+ init_logger();
4371
+ init_validation_limits();
4372
+ }
4373
+ });
4374
+ var FeatureFlagManager;
4375
+ var init_flag_manager = __esm({
4376
+ "src/core/feature-flags/flag-manager.ts"() {
4377
+ init_esm_shims();
4378
+ init_logger();
4379
+ FeatureFlagManager = class {
4380
+ flags = /* @__PURE__ */ new Map();
4381
+ storagePath;
4382
+ flagsDir;
4383
+ workspacePath;
4384
+ constructor(workspacePath = process.cwd()) {
4385
+ this.workspacePath = workspacePath;
4386
+ this.flagsDir = join(workspacePath, ".automatosx");
4387
+ this.storagePath = join(this.flagsDir, "feature-flags.json");
4388
+ this.loadFlags();
4389
+ }
4390
+ /**
4391
+ * Check if workspace has a storage directory
4392
+ */
4393
+ hasStorage() {
4394
+ return existsSync(this.flagsDir);
4395
+ }
4396
+ /**
4397
+ * Get workspace path for diagnostics
4398
+ */
4399
+ getWorkspacePath() {
4400
+ return this.workspacePath;
4401
+ }
4402
+ /**
4403
+ * Load flags from storage
4404
+ */
4405
+ loadFlags() {
4406
+ try {
4407
+ if (!this.hasStorage()) {
4408
+ logger.debug("Feature flag storage not initialized", {
4409
+ workspacePath: this.workspacePath
4410
+ });
4411
+ return;
4412
+ }
4413
+ if (existsSync(this.storagePath)) {
4414
+ const data = readFileSync(this.storagePath, "utf-8");
4415
+ const flags = JSON.parse(data);
4416
+ for (const flag of flags) {
4417
+ this.flags.set(flag.name, flag);
4418
+ }
4419
+ logger.info("Feature flags loaded", {
4420
+ count: flags.length,
4421
+ path: this.storagePath
4422
+ });
4423
+ } else {
4424
+ logger.info("No feature flags file found, starting fresh");
4425
+ }
4426
+ } catch (error) {
4427
+ logger.error("Failed to load feature flags", {
4428
+ error: error.message
4429
+ });
4430
+ }
4431
+ }
4432
+ /**
4433
+ * Save flags to storage
4434
+ */
4435
+ saveFlags() {
4436
+ try {
4437
+ this.ensureStorageDir();
4438
+ const flagsArray = Array.from(this.flags.values());
4439
+ const data = JSON.stringify(flagsArray, null, 2);
4440
+ writeFileSync(this.storagePath, data, "utf-8");
4441
+ } catch (error) {
4442
+ logger.error("Failed to save feature flags", {
4443
+ error: error.message
4444
+ });
4445
+ }
4446
+ }
4447
+ /**
4448
+ * Ensure storage directory exists before writing
4449
+ */
4450
+ ensureStorageDir() {
4451
+ if (!existsSync(this.flagsDir)) {
4452
+ mkdirSync(this.flagsDir, { recursive: true });
4453
+ }
4454
+ }
4455
+ /**
4456
+ * Define a feature flag
4457
+ */
4458
+ defineFlag(flag) {
4459
+ this.flags.set(flag.name, flag);
4460
+ this.saveFlags();
4461
+ logger.info("Feature flag defined", { name: flag.name });
4462
+ }
4463
+ /**
4464
+ * Check if flag is enabled
4465
+ */
4466
+ isEnabled(flagName, context) {
4467
+ const flag = this.flags.get(flagName);
4468
+ if (!flag) return false;
4469
+ if (flag.killSwitch?.enabled) {
4470
+ logger.warn(`Feature flag ${flagName} killed`, {
4471
+ reason: flag.killSwitch.reason,
4472
+ timestamp: flag.killSwitch.timestamp
4473
+ });
4474
+ return false;
4475
+ }
4476
+ const envOverride = process.env[`FEATURE_${flagName.toUpperCase()}`];
4477
+ if (envOverride === "false" || envOverride === "0") {
4478
+ logger.warn(`Feature flag ${flagName} disabled by env var`);
4479
+ return false;
4480
+ }
4481
+ if (flag.rolloutPercentage !== void 0) {
4482
+ const hash = this.hashContext(context);
4483
+ const bucket = hash % 100;
4484
+ const enabled = bucket < flag.rolloutPercentage;
4485
+ return enabled;
4486
+ }
4487
+ return flag.enabled;
4488
+ }
4489
+ /**
4490
+ * Gradually increase rollout percentage
4491
+ */
4492
+ async increaseRollout(flagName, newPercentage, options) {
4493
+ const flag = this.flags.get(flagName);
4494
+ if (!flag) throw new Error(`Flag ${flagName} not found`);
4495
+ const currentPercentage = flag.rolloutPercentage || 0;
4496
+ if (newPercentage > currentPercentage * 5 && newPercentage !== 100 && currentPercentage > 0) {
4497
+ throw new Error(
4498
+ `Rollout increase too aggressive: ${currentPercentage}% \u2192 ${newPercentage}%
4499
+ Maximum safe increase: ${currentPercentage * 5}%`
4500
+ );
4501
+ }
4502
+ if (options?.minimumDuration && flag.lastUpdated) {
4503
+ const timeSinceLastChange = Date.now() - flag.lastUpdated;
4504
+ if (timeSinceLastChange < options.minimumDuration) {
4505
+ throw new Error(
4506
+ `Must wait ${options.minimumDuration}ms before increasing rollout
4507
+ Time since last change: ${timeSinceLastChange}ms`
4508
+ );
4509
+ }
4510
+ }
4511
+ flag.rolloutPercentage = newPercentage;
4512
+ flag.lastUpdated = Date.now();
4513
+ this.flags.set(flagName, flag);
4514
+ this.saveFlags();
4515
+ logger.info(`Feature flag ${flagName} rollout increased`, {
4516
+ from: currentPercentage,
4517
+ to: newPercentage,
4518
+ timestamp: (/* @__PURE__ */ new Date()).toISOString()
4519
+ });
4520
+ }
4521
+ /**
4522
+ * Emergency kill switch
4523
+ */
4524
+ async killSwitch(flagName, reason) {
4525
+ const flag = this.flags.get(flagName);
4526
+ if (!flag) throw new Error(`Flag ${flagName} not found`);
4527
+ flag.killSwitch = {
4528
+ enabled: true,
4529
+ reason,
4530
+ timestamp: Date.now(),
4531
+ by: process.env.USER || "unknown"
4532
+ };
4533
+ this.flags.set(flagName, flag);
4534
+ this.saveFlags();
4535
+ logger.error(`\u{1F6A8} KILL SWITCH ACTIVATED: ${flagName}`, {
4536
+ reason,
4537
+ timestamp: (/* @__PURE__ */ new Date()).toISOString()
4538
+ });
4539
+ }
4540
+ /**
4541
+ * Get all flags
4542
+ */
4543
+ getAllFlags() {
4544
+ return Array.from(this.flags.values());
4545
+ }
4546
+ /**
4547
+ * Get a specific flag
4548
+ */
4549
+ getFlag(flagName) {
4550
+ return this.flags.get(flagName);
4551
+ }
4552
+ /**
4553
+ * Hash context for deterministic bucketing
4554
+ */
4555
+ hashContext(context) {
4556
+ const str = JSON.stringify(context || {});
4557
+ let hash = 0;
4558
+ for (let i = 0; i < str.length; i++) {
4559
+ const char = str.charCodeAt(i);
4560
+ hash = (hash << 5) - hash + char;
4561
+ hash = hash & hash;
4562
+ }
4563
+ return hash >>> 0;
4564
+ }
4565
+ };
4566
+ }
4567
+ });
4568
+
4569
+ // src/core/feature-flags/flags.ts
4570
+ function getFlagManager(workspacePath) {
4571
+ const path7 = process.cwd();
4572
+ if (!flagManagerInstances.has(path7)) {
4573
+ const manager = new FeatureFlagManager(path7);
4574
+ initializeFlags(manager);
4575
+ flagManagerInstances.set(path7, manager);
4576
+ }
4577
+ return flagManagerInstances.get(path7);
4578
+ }
4579
+ function initializeFlags(manager) {
4580
+ if (!manager.hasStorage()) {
4581
+ logger.debug("Skipping feature flag initialization; workspace not initialized", {
4582
+ workspacePath: manager.getWorkspacePath()
4583
+ });
4584
+ return;
4585
+ }
4586
+ initializeGeminiStreamingFlag(manager);
4587
+ initializeProviderArchitectureFlags(manager);
4588
+ }
4589
+ function initializeGeminiStreamingFlag(manager) {
4590
+ const existingFlag = manager.getFlag("gemini_streaming");
4591
+ if (!existingFlag) {
4592
+ manager.defineFlag({
4593
+ name: "gemini_streaming",
4594
+ description: "Enable Gemini as a valid option for streaming workloads",
4595
+ enabled: true,
4596
+ rolloutPercentage: 0,
4597
+ metadata: {
4598
+ owner: "platform-team",
4599
+ jiraTicket: "AUTO-1234",
4600
+ expectedImpact: "96% cost reduction on streaming tasks"
4601
+ }
4602
+ });
4603
+ logger.info("Feature flag gemini_streaming initialized at 0%");
4604
+ }
4605
+ }
4606
+ function initializeProviderArchitectureFlags(manager) {
4607
+ for (const flagDef of DEFAULT_PROVIDER_FLAGS) {
4608
+ const existingFlag = manager.getFlag(flagDef.name);
4609
+ if (!existingFlag) {
4610
+ manager.defineFlag(flagDef);
4611
+ logger.info(`Feature flag ${flagDef.name} initialized`, {
4612
+ enabled: flagDef.enabled,
4613
+ rolloutPercentage: flagDef.rolloutPercentage
4614
+ });
4615
+ }
4616
+ }
4617
+ }
4618
+ function isSDKFirstModeEnabled(context) {
4619
+ const manager = getFlagManager();
4620
+ return manager.isEnabled(PROVIDER_ARCHITECTURE_FLAGS.SDK_FIRST_MODE, context);
4621
+ }
4622
+ function isSDKFallbackEnabled() {
4623
+ const manager = getFlagManager();
4624
+ return manager.isEnabled(PROVIDER_ARCHITECTURE_FLAGS.SDK_FALLBACK_ENABLED);
4625
+ }
4626
+ function shouldCollectProviderMetrics() {
4627
+ const manager = getFlagManager();
4628
+ return manager.isEnabled(PROVIDER_ARCHITECTURE_FLAGS.PROVIDER_METRICS);
4629
+ }
4630
+ var flagManagerInstances, PROVIDER_ARCHITECTURE_FLAGS, DEFAULT_PROVIDER_FLAGS;
4631
+ var init_flags = __esm({
4632
+ "src/core/feature-flags/flags.ts"() {
4633
+ init_esm_shims();
4634
+ init_flag_manager();
4635
+ init_logger();
4636
+ flagManagerInstances = /* @__PURE__ */ new Map();
4637
+ PROVIDER_ARCHITECTURE_FLAGS = {
4638
+ /** Enable SDK-first execution pattern (SDK primary, CLI fallback) */
4639
+ SDK_FIRST_MODE: "sdk_first_mode",
4640
+ /** Enable MCP bidirectional communication for agentic providers */
4641
+ MCP_BIDIRECTIONAL: "mcp_bidirectional",
4642
+ /** Auto-inject MCP server config into provider config files */
4643
+ AUTO_INJECT_MCP_CONFIG: "auto_inject_mcp_config",
4644
+ /** Allow CLI fallback when SDK fails */
4645
+ SDK_FALLBACK_ENABLED: "sdk_fallback_enabled",
4646
+ /** Show deprecation warnings (legacy providers, etc.) */
4647
+ DEPRECATION_WARNINGS: "deprecation_warnings",
4648
+ /** Enable provider metrics collection */
4649
+ PROVIDER_METRICS: "provider_metrics"
4650
+ };
4651
+ DEFAULT_PROVIDER_FLAGS = [
4652
+ {
4653
+ name: PROVIDER_ARCHITECTURE_FLAGS.SDK_FIRST_MODE,
4654
+ description: "Enable SDK-first execution pattern (SDK primary, CLI fallback) for GLM, Grok, and Codex providers",
4655
+ enabled: false,
4656
+ // Disabled by default, enable in v11.7.0
4657
+ rolloutPercentage: 0,
4658
+ metadata: {
4659
+ owner: "platform-team",
4660
+ expectedImpact: "Lower latency (~5ms vs ~200ms), better type safety"
4661
+ }
4662
+ },
4663
+ {
4664
+ name: PROVIDER_ARCHITECTURE_FLAGS.MCP_BIDIRECTIONAL,
4665
+ description: "Enable MCP bidirectional communication for Claude and Gemini agents",
4666
+ enabled: false,
4667
+ // Disabled by default, enable in v11.8.0
4668
+ rolloutPercentage: 0,
4669
+ metadata: {
4670
+ owner: "platform-team",
4671
+ expectedImpact: "Faster agent communication via MCP instead of stdout parsing"
4672
+ }
4673
+ },
4674
+ {
4675
+ name: PROVIDER_ARCHITECTURE_FLAGS.AUTO_INJECT_MCP_CONFIG,
4676
+ description: "Automatically inject AutomatosX MCP server config into provider config files",
4677
+ enabled: false,
4678
+ // Disabled by default, requires careful testing
4679
+ rolloutPercentage: 0,
4680
+ metadata: {
4681
+ owner: "platform-team",
4682
+ expectedImpact: "Seamless MCP setup for agents"
4683
+ }
4684
+ },
4685
+ {
4686
+ name: PROVIDER_ARCHITECTURE_FLAGS.SDK_FALLBACK_ENABLED,
4687
+ description: "Allow CLI fallback when SDK execution fails",
4688
+ enabled: true,
4689
+ // Enabled by default for safety
4690
+ rolloutPercentage: 100,
4691
+ metadata: {
4692
+ owner: "platform-team",
4693
+ expectedImpact: "Graceful degradation when SDK unavailable"
4694
+ }
4695
+ },
4696
+ {
4697
+ name: PROVIDER_ARCHITECTURE_FLAGS.DEPRECATION_WARNINGS,
4698
+ description: "Show deprecation warnings for legacy features",
4699
+ enabled: true,
4700
+ // Enabled by default to warn users
4701
+ rolloutPercentage: 100,
4702
+ metadata: {
4703
+ owner: "platform-team",
4704
+ expectedImpact: "v13.0.0: ax-cli removed, GLM/Grok are SDK-first"
4705
+ }
4706
+ },
4707
+ {
4708
+ name: PROVIDER_ARCHITECTURE_FLAGS.PROVIDER_METRICS,
4709
+ description: "Enable provider metrics collection (SDK/CLI usage, fallback rate, MCP connections)",
4710
+ enabled: true,
4711
+ // Enabled by default for observability
4712
+ rolloutPercentage: 100,
4713
+ metadata: {
4714
+ owner: "platform-team",
4715
+ expectedImpact: "Better visibility into provider performance"
4716
+ }
4717
+ }
4718
+ ];
4719
+ }
4720
+ });
4721
+
4722
+ // src/providers/fallback-decision.ts
4723
+ function decideFallback(error, providerName) {
4724
+ const errorMessage = getErrorMessage(error).toLowerCase();
4725
+ const errorCode = getErrorCode(error);
4726
+ const statusCode = getStatusCode(error);
4727
+ logger.debug("Classifying error for fallback decision", {
4728
+ provider: providerName,
4729
+ message: errorMessage.substring(0, 100),
4730
+ code: errorCode,
4731
+ statusCode
4732
+ });
4733
+ if (matchesPatterns(errorMessage, SDK_UNAVAILABLE_PATTERNS)) {
4734
+ return {
4735
+ decision: "use_cli" /* USE_CLI */,
4736
+ reason: "SDK not available or not installed",
4737
+ severity: "warn"
4738
+ };
4739
+ }
4740
+ if (matchesPatterns(errorMessage, AUTH_ERROR_PATTERNS) || statusCode === 401 || statusCode === 403) {
4741
+ return {
4742
+ decision: "propagate" /* PROPAGATE */,
4743
+ reason: "Authentication error - CLI would fail with same credentials",
4744
+ severity: "error"
4745
+ };
4746
+ }
4747
+ if (matchesPatterns(errorMessage, RATE_LIMIT_PATTERNS) || statusCode === 429) {
4748
+ return {
4749
+ decision: "retry_sdk" /* RETRY_SDK */,
4750
+ reason: "Rate limited - retrying with backoff",
4751
+ severity: "warn",
4752
+ retryDelayMs: 5e3
4753
+ // Longer delay for rate limits
4754
+ };
4755
+ }
4756
+ if (matchesPatterns(errorMessage, TRANSIENT_ERROR_PATTERNS)) {
4757
+ return {
4758
+ decision: "retry_sdk" /* RETRY_SDK */,
4759
+ reason: "Transient network error - retrying",
4760
+ severity: "warn",
4761
+ retryDelayMs: 1e3
4762
+ };
4763
+ }
4764
+ if (matchesPatterns(errorMessage, SERVER_ERROR_PATTERNS) || statusCode && statusCode >= 500 && statusCode < 600) {
4765
+ return {
4766
+ decision: "retry_sdk" /* RETRY_SDK */,
4767
+ reason: "Server error - retrying",
4768
+ severity: "warn",
4769
+ retryDelayMs: 2e3
4770
+ };
4771
+ }
4772
+ if (matchesPatterns(errorMessage, CLIENT_ERROR_PATTERNS) || statusCode && statusCode >= 400 && statusCode < 500) {
4773
+ return {
4774
+ decision: "propagate" /* PROPAGATE */,
4775
+ reason: "Client error - request is invalid",
4776
+ severity: "error"
4777
+ };
4778
+ }
4779
+ if (isSDKFallbackEnabled()) {
4780
+ return {
4781
+ decision: "use_cli" /* USE_CLI */,
4782
+ reason: "Unknown error - falling back to CLI",
4783
+ severity: "warn"
4784
+ };
4785
+ }
4786
+ return {
4787
+ decision: "propagate" /* PROPAGATE */,
4788
+ reason: "Unknown error and fallback is disabled",
4789
+ severity: "error"
4790
+ };
4791
+ }
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
+ function getErrorCode(error) {
4817
+ if (error && typeof error === "object") {
4818
+ const obj = error;
4819
+ if (typeof obj.code === "string") {
4820
+ return obj.code;
4821
+ }
4822
+ if (typeof obj.errorCode === "string") {
4823
+ return obj.errorCode;
4824
+ }
4825
+ }
4826
+ return void 0;
4827
+ }
4828
+ function getStatusCode(error) {
4829
+ if (error && typeof error === "object") {
4830
+ const obj = error;
4831
+ if (typeof obj.status === "number") {
4832
+ return obj.status;
4833
+ }
4834
+ if (typeof obj.statusCode === "number") {
4835
+ return obj.statusCode;
4836
+ }
4837
+ if (obj.response && typeof obj.response === "object") {
4838
+ const response = obj.response;
4839
+ if (typeof response.status === "number") {
4840
+ return response.status;
4841
+ }
4842
+ }
4843
+ }
4844
+ return void 0;
4845
+ }
4846
+ function matchesPatterns(message, patterns) {
4847
+ return patterns.some((pattern) => message.includes(pattern.toLowerCase()));
4848
+ }
4849
+ var SDK_UNAVAILABLE_PATTERNS, AUTH_ERROR_PATTERNS, TRANSIENT_ERROR_PATTERNS, RATE_LIMIT_PATTERNS, SERVER_ERROR_PATTERNS, CLIENT_ERROR_PATTERNS;
4850
+ var init_fallback_decision = __esm({
4851
+ "src/providers/fallback-decision.ts"() {
4852
+ init_esm_shims();
4853
+ init_logger();
4854
+ init_flags();
4855
+ SDK_UNAVAILABLE_PATTERNS = [
4856
+ "module not found",
4857
+ "cannot find module",
4858
+ "sdk not available",
4859
+ "sdk not installed",
4860
+ "failed to initialize sdk",
4861
+ "sdk initialization failed",
4862
+ "package not found",
4863
+ "@zhipuai/sdk",
4864
+ "@xai-org/grok-sdk",
4865
+ "@openai/codex-sdk",
4866
+ "enoent",
4867
+ // File not found (npm module missing)
4868
+ "cannot resolve",
4869
+ "dynamic import failed"
4870
+ ];
4871
+ AUTH_ERROR_PATTERNS = [
4872
+ "authentication failed",
4873
+ "invalid api key",
4874
+ "invalid_api_key",
4875
+ "unauthorized",
4876
+ "api key not found",
4877
+ "api_key_invalid",
4878
+ "invalid credentials",
4879
+ "authentication required",
4880
+ "access denied",
4881
+ "401",
4882
+ "403",
4883
+ "forbidden",
4884
+ "invalid_grant",
4885
+ "token expired",
4886
+ "invalid token"
4887
+ ];
4888
+ TRANSIENT_ERROR_PATTERNS = [
4889
+ "timeout",
4890
+ "etimedout",
4891
+ "econnreset",
4892
+ "econnrefused",
4893
+ "enotfound",
4894
+ "network error",
4895
+ "socket hang up",
4896
+ "connection reset",
4897
+ "temporary failure",
4898
+ "service unavailable",
4899
+ "503",
4900
+ "504",
4901
+ "gateway timeout",
4902
+ "bad gateway",
4903
+ "502"
4904
+ ];
4905
+ RATE_LIMIT_PATTERNS = [
4906
+ "rate limit",
4907
+ "rate_limit",
4908
+ "too many requests",
4909
+ "429",
4910
+ "throttled",
4911
+ "quota exceeded",
4912
+ "resource_exhausted",
4913
+ "overloaded"
4914
+ ];
4915
+ SERVER_ERROR_PATTERNS = [
4916
+ "500",
4917
+ "502",
4918
+ "503",
4919
+ "504",
4920
+ "internal server error",
4921
+ "internal error",
4922
+ "server error"
4923
+ ];
4924
+ CLIENT_ERROR_PATTERNS = [
4925
+ "400",
4926
+ "bad request",
4927
+ "invalid request",
4928
+ "validation error",
4929
+ "invalid parameter",
4930
+ "missing parameter",
4931
+ "malformed request"
4932
+ ];
4933
+ }
4934
+ });
4935
+
4936
+ // src/core/metrics/provider-metrics.ts
4937
+ function getProviderMetrics() {
4938
+ return ProviderMetricsCollector.getInstance();
4939
+ }
4940
+ var ProviderMetricsCollector;
4941
+ var init_provider_metrics = __esm({
4942
+ "src/core/metrics/provider-metrics.ts"() {
4943
+ init_esm_shims();
4944
+ init_logger();
4945
+ init_flags();
4946
+ ProviderMetricsCollector = class _ProviderMetricsCollector {
4947
+ static instance = null;
4948
+ // Per-provider metrics
4949
+ providerMetrics = /* @__PURE__ */ new Map();
4950
+ // MCP metrics
4951
+ mcpMetrics = {
4952
+ totalConnections: 0,
4953
+ activeConnections: 0,
4954
+ failedConnections: 0,
4955
+ totalToolCalls: 0,
4956
+ avgToolCallLatencyMs: 0,
4957
+ sessionsByProvider: {}
4958
+ };
4959
+ // Latency tracking (for averages)
4960
+ sdkLatencies = /* @__PURE__ */ new Map();
4961
+ cliLatencies = /* @__PURE__ */ new Map();
4962
+ mcpLatencies = [];
4963
+ // Max samples to keep for latency averaging
4964
+ MAX_LATENCY_SAMPLES = 100;
4965
+ constructor() {
4966
+ }
4967
+ /**
4968
+ * Get singleton instance
4969
+ */
4970
+ static getInstance() {
4971
+ if (!_ProviderMetricsCollector.instance) {
4972
+ _ProviderMetricsCollector.instance = new _ProviderMetricsCollector();
4973
+ }
4974
+ return _ProviderMetricsCollector.instance;
4975
+ }
4976
+ /**
4977
+ * Reset singleton instance (for testing)
4978
+ */
4979
+ static resetInstance() {
4980
+ _ProviderMetricsCollector.instance = null;
4981
+ }
4982
+ /**
4983
+ * Check if metrics collection is enabled
4984
+ */
4985
+ isEnabled() {
4986
+ return shouldCollectProviderMetrics();
4987
+ }
4988
+ /**
4989
+ * Get or create provider metrics data
4990
+ */
4991
+ getOrCreateProviderMetrics(providerName) {
4992
+ if (!this.providerMetrics.has(providerName)) {
4993
+ this.providerMetrics.set(providerName, {
4994
+ providerName,
4995
+ executionMode: "cli",
4996
+ // Default mode
4997
+ circuitBreakerState: "closed",
4998
+ metrics: {
4999
+ sdkExecutions: 0,
5000
+ cliExecutions: 0,
5001
+ mcpToolCalls: 0,
5002
+ sdkFallbacks: 0,
5003
+ sdkErrors: 0,
5004
+ cliErrors: 0,
5005
+ mcpConnectionFailures: 0,
5006
+ avgSdkLatencyMs: 0,
5007
+ avgCliLatencyMs: 0,
5008
+ avgMcpLatencyMs: 0,
5009
+ fallbackRate: 0,
5010
+ sdkSuccessRate: 1,
5011
+ cliSuccessRate: 1,
5012
+ mcpSuccessRate: 1
5013
+ },
5014
+ lastUpdated: Date.now()
5015
+ });
5016
+ }
5017
+ return this.providerMetrics.get(providerName);
5018
+ }
5019
+ /**
5020
+ * Record SDK execution
5021
+ */
5022
+ recordSDKExecution(providerName, latencyMs, success) {
5023
+ if (!this.isEnabled()) return;
5024
+ const data = this.getOrCreateProviderMetrics(providerName);
5025
+ data.metrics.sdkExecutions++;
5026
+ if (!success) {
5027
+ data.metrics.sdkErrors++;
5028
+ }
5029
+ this.addLatencySample(this.sdkLatencies, providerName, latencyMs);
5030
+ data.metrics.avgSdkLatencyMs = this.calculateAverageLatency(
5031
+ this.sdkLatencies.get(providerName) || []
5032
+ );
5033
+ data.metrics.sdkSuccessRate = this.calculateSuccessRate(
5034
+ data.metrics.sdkExecutions,
5035
+ data.metrics.sdkErrors
5036
+ );
5037
+ data.lastUpdated = Date.now();
5038
+ logger.debug("SDK execution recorded", {
5039
+ provider: providerName,
5040
+ latencyMs,
5041
+ success,
5042
+ totalExecutions: data.metrics.sdkExecutions
5043
+ });
5044
+ }
5045
+ /**
5046
+ * Record CLI execution
5047
+ */
5048
+ recordCLIExecution(providerName, latencyMs, success) {
5049
+ if (!this.isEnabled()) return;
5050
+ const data = this.getOrCreateProviderMetrics(providerName);
5051
+ data.metrics.cliExecutions++;
5052
+ if (!success) {
5053
+ data.metrics.cliErrors++;
5054
+ }
5055
+ this.addLatencySample(this.cliLatencies, providerName, latencyMs);
5056
+ data.metrics.avgCliLatencyMs = this.calculateAverageLatency(
5057
+ this.cliLatencies.get(providerName) || []
5058
+ );
5059
+ data.metrics.cliSuccessRate = this.calculateSuccessRate(
5060
+ data.metrics.cliExecutions,
5061
+ data.metrics.cliErrors
5062
+ );
5063
+ data.lastUpdated = Date.now();
5064
+ logger.debug("CLI execution recorded", {
5065
+ provider: providerName,
5066
+ latencyMs,
5067
+ success,
5068
+ totalExecutions: data.metrics.cliExecutions
5069
+ });
5070
+ }
5071
+ /**
5072
+ * Record SDK fallback to CLI
5073
+ */
5074
+ recordSDKFallback(providerName, reason) {
5075
+ if (!this.isEnabled()) return;
5076
+ const data = this.getOrCreateProviderMetrics(providerName);
5077
+ data.metrics.sdkFallbacks++;
5078
+ if (data.metrics.sdkExecutions > 0) {
5079
+ data.metrics.fallbackRate = data.metrics.sdkFallbacks / data.metrics.sdkExecutions;
5080
+ }
5081
+ data.lastUpdated = Date.now();
5082
+ logger.info("SDK fallback recorded", {
5083
+ provider: providerName,
5084
+ reason,
5085
+ fallbackRate: data.metrics.fallbackRate
5086
+ });
5087
+ }
5088
+ /**
5089
+ * Record MCP connection
5090
+ */
5091
+ recordMCPConnection(providerName, success) {
5092
+ if (!this.isEnabled()) return;
5093
+ this.mcpMetrics.totalConnections++;
5094
+ if (success) {
5095
+ this.mcpMetrics.activeConnections++;
5096
+ this.mcpMetrics.sessionsByProvider[providerName] = (this.mcpMetrics.sessionsByProvider[providerName] || 0) + 1;
5097
+ } else {
5098
+ this.mcpMetrics.failedConnections++;
5099
+ const data = this.getOrCreateProviderMetrics(providerName);
5100
+ data.metrics.mcpConnectionFailures++;
5101
+ data.lastUpdated = Date.now();
5102
+ }
5103
+ logger.debug("MCP connection recorded", {
5104
+ provider: providerName,
5105
+ success,
5106
+ activeConnections: this.mcpMetrics.activeConnections
5107
+ });
5108
+ }
5109
+ /**
5110
+ * Record MCP connection closed
5111
+ */
5112
+ recordMCPDisconnection(providerName) {
5113
+ if (!this.isEnabled()) return;
5114
+ if (this.mcpMetrics.activeConnections > 0) {
5115
+ this.mcpMetrics.activeConnections--;
5116
+ }
5117
+ const currentCount = this.mcpMetrics.sessionsByProvider[providerName];
5118
+ if (currentCount !== void 0 && currentCount > 0) {
5119
+ this.mcpMetrics.sessionsByProvider[providerName] = currentCount - 1;
5120
+ }
5121
+ logger.debug("MCP disconnection recorded", {
5122
+ provider: providerName,
5123
+ activeConnections: this.mcpMetrics.activeConnections
5124
+ });
5125
+ }
5126
+ /**
5127
+ * Record MCP tool call
5128
+ */
5129
+ recordMCPToolCall(providerName, toolName, latencyMs, success) {
5130
+ if (!this.isEnabled()) return;
5131
+ const data = this.getOrCreateProviderMetrics(providerName);
5132
+ data.metrics.mcpToolCalls++;
5133
+ this.mcpMetrics.totalToolCalls++;
5134
+ this.mcpLatencies.push(latencyMs);
5135
+ if (this.mcpLatencies.length > this.MAX_LATENCY_SAMPLES) {
5136
+ this.mcpLatencies.shift();
5137
+ }
5138
+ data.metrics.avgMcpLatencyMs = this.calculateAverageLatency(this.mcpLatencies);
5139
+ this.mcpMetrics.avgToolCallLatencyMs = data.metrics.avgMcpLatencyMs;
5140
+ data.lastUpdated = Date.now();
5141
+ logger.debug("MCP tool call recorded", {
5142
+ provider: providerName,
5143
+ tool: toolName,
5144
+ latencyMs,
5145
+ success
5146
+ });
5147
+ }
5148
+ /**
5149
+ * Update circuit breaker state
5150
+ */
5151
+ updateCircuitBreakerState(providerName, state) {
5152
+ if (!this.isEnabled()) return;
5153
+ const data = this.getOrCreateProviderMetrics(providerName);
5154
+ const previousState = data.circuitBreakerState;
5155
+ data.circuitBreakerState = state;
5156
+ data.lastUpdated = Date.now();
5157
+ if (previousState !== state) {
5158
+ logger.info("Circuit breaker state changed", {
5159
+ provider: providerName,
5160
+ from: previousState,
5161
+ to: state
5162
+ });
5163
+ }
5164
+ }
5165
+ /**
5166
+ * Update execution mode
5167
+ */
5168
+ updateExecutionMode(providerName, mode) {
5169
+ if (!this.isEnabled()) return;
5170
+ const data = this.getOrCreateProviderMetrics(providerName);
5171
+ data.executionMode = mode;
5172
+ data.lastUpdated = Date.now();
5173
+ }
5174
+ /**
5175
+ * Get metrics for a specific provider
5176
+ */
5177
+ getProviderMetrics(providerName) {
5178
+ return this.providerMetrics.get(providerName);
5179
+ }
5180
+ /**
5181
+ * Get all provider metrics
5182
+ */
5183
+ getAllProviderMetrics() {
5184
+ return Array.from(this.providerMetrics.values());
5185
+ }
5186
+ /**
5187
+ * Get MCP session metrics
5188
+ */
5189
+ getMCPMetrics() {
5190
+ return { ...this.mcpMetrics };
5191
+ }
5192
+ /**
5193
+ * Get aggregated metrics summary
5194
+ */
5195
+ getMetricsSummary() {
5196
+ let totalSDK = 0;
5197
+ let totalCLI = 0;
5198
+ let totalFallbacks = 0;
5199
+ let sdkLatencySum = 0;
5200
+ let cliLatencySum = 0;
5201
+ let sdkCount = 0;
5202
+ let cliCount = 0;
5203
+ const openCircuitBreakers = [];
5204
+ for (const data of this.providerMetrics.values()) {
5205
+ totalSDK += data.metrics.sdkExecutions;
5206
+ totalCLI += data.metrics.cliExecutions;
5207
+ totalFallbacks += data.metrics.sdkFallbacks;
5208
+ if (data.metrics.avgSdkLatencyMs > 0) {
5209
+ sdkLatencySum += data.metrics.avgSdkLatencyMs;
5210
+ sdkCount++;
5211
+ }
5212
+ if (data.metrics.avgCliLatencyMs > 0) {
5213
+ cliLatencySum += data.metrics.avgCliLatencyMs;
5214
+ cliCount++;
5215
+ }
5216
+ if (data.circuitBreakerState === "open") {
5217
+ openCircuitBreakers.push(data.providerName);
5218
+ }
5219
+ }
5220
+ return {
5221
+ totalSDKExecutions: totalSDK,
5222
+ totalCLIExecutions: totalCLI,
5223
+ totalMCPConnections: this.mcpMetrics.totalConnections,
5224
+ overallFallbackRate: totalSDK > 0 ? totalFallbacks / totalSDK : 0,
5225
+ avgSDKLatencyMs: sdkCount > 0 ? sdkLatencySum / sdkCount : 0,
5226
+ avgCLILatencyMs: cliCount > 0 ? cliLatencySum / cliCount : 0,
5227
+ providersWithOpenCircuitBreaker: openCircuitBreakers
5228
+ };
5229
+ }
5230
+ /**
5231
+ * Reset all metrics (for testing)
5232
+ */
5233
+ reset() {
5234
+ this.providerMetrics.clear();
5235
+ this.sdkLatencies.clear();
5236
+ this.cliLatencies.clear();
5237
+ this.mcpLatencies = [];
5238
+ this.mcpMetrics = {
5239
+ totalConnections: 0,
5240
+ activeConnections: 0,
5241
+ failedConnections: 0,
5242
+ totalToolCalls: 0,
5243
+ avgToolCallLatencyMs: 0,
5244
+ sessionsByProvider: {}
5245
+ };
5246
+ }
5247
+ /**
5248
+ * Add latency sample to provider's latency array
5249
+ */
5250
+ addLatencySample(latencyMap, providerName, latencyMs) {
5251
+ if (!latencyMap.has(providerName)) {
5252
+ latencyMap.set(providerName, []);
5253
+ }
5254
+ const latencies = latencyMap.get(providerName);
5255
+ latencies.push(latencyMs);
5256
+ if (latencies.length > this.MAX_LATENCY_SAMPLES) {
5257
+ latencies.shift();
5258
+ }
5259
+ }
5260
+ /**
5261
+ * Calculate average latency from samples
5262
+ */
5263
+ calculateAverageLatency(latencies) {
5264
+ if (latencies.length === 0) return 0;
5265
+ const sum = latencies.reduce((a, b) => a + b, 0);
5266
+ return Math.round(sum / latencies.length);
5267
+ }
5268
+ /**
5269
+ * Calculate success rate
5270
+ */
5271
+ calculateSuccessRate(total, errors) {
5272
+ if (total === 0) return 1;
5273
+ return Math.max(0, (total - errors) / total);
5274
+ }
5275
+ };
5276
+ }
5277
+ });
5278
+
5279
+ // src/providers/hybrid-adapter-base.ts
5280
+ var DEFAULT_CIRCUIT_BREAKER_CONFIG, CircuitBreaker2, HybridAdapterBase;
5281
+ var init_hybrid_adapter_base = __esm({
5282
+ "src/providers/hybrid-adapter-base.ts"() {
5283
+ init_esm_shims();
5284
+ init_logger();
5285
+ init_flags();
5286
+ init_fallback_decision();
5287
+ init_provider_metrics();
5288
+ DEFAULT_CIRCUIT_BREAKER_CONFIG = {
5289
+ failureThreshold: 3,
5290
+ resetTimeout: 6e4,
5291
+ // 1 minute
5292
+ halfOpenSuccessThreshold: 2
5293
+ };
5294
+ CircuitBreaker2 = class {
5295
+ state = "closed";
5296
+ failures = 0;
5297
+ successes = 0;
5298
+ lastFailureTime = 0;
5299
+ config;
5300
+ constructor(config = {}) {
5301
+ this.config = { ...DEFAULT_CIRCUIT_BREAKER_CONFIG, ...config };
5302
+ }
5303
+ /**
5304
+ * Check if circuit is open (requests should not be attempted)
5305
+ */
5306
+ isOpen() {
5307
+ if (this.state === "open") {
5308
+ if (Date.now() - this.lastFailureTime >= this.config.resetTimeout) {
5309
+ this.state = "half-open";
5310
+ this.successes = 0;
5311
+ logger.debug("Circuit breaker transitioning to half-open");
5312
+ return false;
5313
+ }
5314
+ return true;
5315
+ }
5316
+ return false;
5317
+ }
5318
+ /**
5319
+ * Get current state
5320
+ */
5321
+ getState() {
5322
+ if (this.state === "open" && Date.now() - this.lastFailureTime >= this.config.resetTimeout) {
5323
+ this.state = "half-open";
5324
+ this.successes = 0;
5325
+ }
5326
+ return this.state;
5327
+ }
5328
+ /**
5329
+ * Record successful execution
5330
+ */
5331
+ recordSuccess() {
5332
+ if (this.state === "half-open") {
5333
+ this.successes++;
5334
+ if (this.successes >= this.config.halfOpenSuccessThreshold) {
5335
+ this.state = "closed";
5336
+ this.failures = 0;
5337
+ this.successes = 0;
5338
+ logger.debug("Circuit breaker closed after recovery");
5339
+ }
5340
+ } else if (this.state === "closed") {
5341
+ this.failures = 0;
5342
+ }
5343
+ }
5344
+ /**
5345
+ * Record failed execution
5346
+ */
5347
+ recordFailure() {
5348
+ this.failures++;
5349
+ this.lastFailureTime = Date.now();
5350
+ if (this.state === "half-open") {
5351
+ this.state = "open";
5352
+ logger.warn("Circuit breaker opened after half-open failure");
5353
+ } else if (this.failures >= this.config.failureThreshold) {
5354
+ this.state = "open";
5355
+ logger.warn("Circuit breaker opened after consecutive failures", {
5356
+ failures: this.failures,
5357
+ threshold: this.config.failureThreshold
5358
+ });
5359
+ }
5360
+ }
5361
+ /**
5362
+ * Reset circuit breaker to closed state
5363
+ */
5364
+ reset() {
5365
+ this.state = "closed";
5366
+ this.failures = 0;
5367
+ this.successes = 0;
5368
+ this.lastFailureTime = 0;
5369
+ }
5370
+ };
5371
+ HybridAdapterBase = class {
5372
+ mode;
5373
+ activeMode = null;
5374
+ providerName;
5375
+ sdkCircuitBreaker;
5376
+ cliCircuitBreaker;
5377
+ maxRetries;
5378
+ // Track initialization state
5379
+ sdkInitialized = false;
5380
+ cliInitialized = false;
5381
+ initPromise = null;
5382
+ constructor(options) {
5383
+ this.mode = options.mode || "auto";
5384
+ this.providerName = options.providerName;
5385
+ this.maxRetries = options.maxRetries ?? 1;
5386
+ this.sdkCircuitBreaker = new CircuitBreaker2(options.sdkCircuitBreaker);
5387
+ this.cliCircuitBreaker = new CircuitBreaker2(options.cliCircuitBreaker);
5388
+ logger.debug("HybridAdapterBase initialized", {
5389
+ provider: this.providerName,
5390
+ mode: this.mode,
5391
+ maxRetries: this.maxRetries
5392
+ });
5393
+ }
5394
+ /**
5395
+ * Execute a request using the appropriate mode
5396
+ *
5397
+ * Mode selection logic:
5398
+ * 1. If mode is 'cli' or SDK-first is disabled → use CLI directly
5399
+ * 2. If mode is 'sdk' → use SDK only (throw if unavailable)
5400
+ * 3. If mode is 'auto' → try SDK first, fallback to CLI
5401
+ */
5402
+ async execute(request) {
5403
+ await this.ensureInitialized();
5404
+ const useSDKFirst = this.shouldUseSDKFirst();
5405
+ if (!useSDKFirst || this.mode === "cli") {
5406
+ return this.executeWithCLI(request);
5407
+ }
5408
+ if (this.mode === "sdk") {
5409
+ return this.executeWithSDK(request);
5410
+ }
5411
+ return this.executeWithFallback(request);
5412
+ }
5413
+ /**
5414
+ * Execute with SDK-first and CLI fallback
5415
+ */
5416
+ async executeWithFallback(request) {
5417
+ if (this.sdkCircuitBreaker.isOpen()) {
5418
+ logger.debug("SDK circuit breaker is open, using CLI", {
5419
+ provider: this.providerName
5420
+ });
5421
+ return this.executeWithCLI(request);
5422
+ }
5423
+ const startTime = Date.now();
5424
+ let lastError;
5425
+ for (let attempt = 0; attempt <= this.maxRetries; attempt++) {
5426
+ try {
5427
+ const result = await this.executeViaSDK(request);
5428
+ this.sdkCircuitBreaker.recordSuccess();
5429
+ this.recordSDKMetrics(Date.now() - startTime, true);
5430
+ return result;
5431
+ } catch (error) {
5432
+ lastError = error;
5433
+ const classification = decideFallback(error, this.providerName);
5434
+ logger.debug("SDK execution failed", {
5435
+ provider: this.providerName,
5436
+ attempt: attempt + 1,
5437
+ decision: classification.decision,
5438
+ reason: classification.reason
5439
+ });
5440
+ if (classification.decision === "retry_sdk" /* RETRY_SDK */ && attempt < this.maxRetries) {
5441
+ const delay = classification.retryDelayMs || 1e3;
5442
+ await this.sleep(delay);
5443
+ continue;
5444
+ }
5445
+ if (classification.decision === "use_cli" /* USE_CLI */ || classification.decision === "retry_sdk" /* RETRY_SDK */ && attempt >= this.maxRetries) {
5446
+ this.sdkCircuitBreaker.recordFailure();
5447
+ this.recordSDKMetrics(Date.now() - startTime, false);
5448
+ this.recordFallbackMetrics(classification.reason || "max retries exceeded");
5449
+ if (isSDKFallbackEnabled()) {
5450
+ logger.info("Falling back to CLI execution", {
5451
+ provider: this.providerName,
5452
+ reason: classification.reason || "max retries exceeded"
5453
+ });
5454
+ return this.executeWithCLI(request);
5455
+ }
5456
+ }
5457
+ this.sdkCircuitBreaker.recordFailure();
5458
+ this.recordSDKMetrics(Date.now() - startTime, false);
5459
+ throw error;
5460
+ }
5461
+ }
5462
+ this.sdkCircuitBreaker.recordFailure();
5463
+ this.recordSDKMetrics(Date.now() - startTime, false);
5464
+ if (isSDKFallbackEnabled()) {
5465
+ this.recordFallbackMetrics("max retries exceeded");
5466
+ return this.executeWithCLI(request);
5467
+ }
5468
+ throw lastError || new Error(`SDK execution failed after ${this.maxRetries + 1} attempts`);
5469
+ }
5470
+ /**
5471
+ * Execute using SDK only
5472
+ */
5473
+ async executeWithSDK(request) {
5474
+ if (this.sdkCircuitBreaker.isOpen()) {
5475
+ throw new Error(`SDK circuit breaker is open for ${this.providerName}`);
5476
+ }
5477
+ const startTime = Date.now();
5478
+ try {
5479
+ const result = await this.executeViaSDK(request);
5480
+ this.sdkCircuitBreaker.recordSuccess();
5481
+ this.recordSDKMetrics(Date.now() - startTime, true);
5482
+ return result;
5483
+ } catch (error) {
5484
+ this.sdkCircuitBreaker.recordFailure();
5485
+ this.recordSDKMetrics(Date.now() - startTime, false);
5486
+ throw error;
5487
+ }
5488
+ }
5489
+ /**
5490
+ * Execute using CLI only
5491
+ */
5492
+ async executeWithCLI(request) {
5493
+ if (this.cliCircuitBreaker.isOpen()) {
5494
+ throw new Error(`CLI circuit breaker is open for ${this.providerName}`);
5495
+ }
5496
+ const startTime = Date.now();
5497
+ try {
5498
+ const result = await this.executeViaCLI(request);
5499
+ this.cliCircuitBreaker.recordSuccess();
5500
+ this.recordCLIMetrics(Date.now() - startTime, true);
5501
+ return result;
5502
+ } catch (error) {
5503
+ this.cliCircuitBreaker.recordFailure();
5504
+ this.recordCLIMetrics(Date.now() - startTime, false);
5505
+ throw error;
5506
+ }
5507
+ }
5508
+ /**
5509
+ * Check if SDK-first mode should be used
5510
+ */
5511
+ shouldUseSDKFirst() {
5512
+ if (!isSDKFirstModeEnabled()) {
5513
+ return false;
5514
+ }
5515
+ if (this.mode === "cli") {
5516
+ return false;
5517
+ }
5518
+ return true;
5519
+ }
5520
+ /**
5521
+ * Ensure adapters are initialized
5522
+ */
5523
+ async ensureInitialized() {
5524
+ if (this.initPromise) {
5525
+ return this.initPromise;
5526
+ }
5527
+ this.initPromise = this.initialize();
5528
+ return this.initPromise;
5529
+ }
5530
+ /**
5531
+ * Initialize adapters based on mode
5532
+ */
5533
+ async initialize() {
5534
+ const useSDKFirst = this.shouldUseSDKFirst();
5535
+ if (this.mode === "cli" || !useSDKFirst) {
5536
+ if (!this.cliInitialized) {
5537
+ const available = await this.isCLIAvailable();
5538
+ if (!available) {
5539
+ throw new Error(`CLI not available for ${this.providerName}`);
5540
+ }
5541
+ await this.initializeCLI();
5542
+ this.cliInitialized = true;
5543
+ this.activeMode = "cli";
5544
+ }
5545
+ return;
5546
+ }
5547
+ if (this.mode === "sdk") {
5548
+ if (!this.sdkInitialized) {
5549
+ const available = await this.isSDKAvailable();
5550
+ if (!available) {
5551
+ throw new Error(`SDK not available for ${this.providerName}`);
5552
+ }
5553
+ await this.initializeSDK();
5554
+ this.sdkInitialized = true;
5555
+ this.activeMode = "sdk";
5556
+ }
5557
+ return;
5558
+ }
5559
+ if (!this.sdkInitialized) {
5560
+ const sdkAvailable = await this.isSDKAvailable();
5561
+ if (sdkAvailable) {
5562
+ try {
5563
+ await this.initializeSDK();
5564
+ this.sdkInitialized = true;
5565
+ this.activeMode = "sdk";
5566
+ } catch (error) {
5567
+ logger.warn("SDK initialization failed, will use CLI", {
5568
+ provider: this.providerName,
5569
+ error: error instanceof Error ? error.message : String(error)
5570
+ });
5571
+ }
5572
+ }
5573
+ }
5574
+ if (!this.cliInitialized) {
5575
+ const cliAvailable = await this.isCLIAvailable();
5576
+ if (cliAvailable) {
5577
+ await this.initializeCLI();
5578
+ this.cliInitialized = true;
5579
+ if (!this.sdkInitialized) {
5580
+ this.activeMode = "cli";
5581
+ }
5582
+ } else if (!this.sdkInitialized) {
5583
+ throw new Error(`Neither SDK nor CLI available for ${this.providerName}`);
5584
+ }
5585
+ }
5586
+ }
5587
+ /**
5588
+ * Record SDK execution metrics
5589
+ */
5590
+ recordSDKMetrics(latencyMs, success) {
5591
+ try {
5592
+ const collector = getProviderMetrics();
5593
+ collector.recordSDKExecution(this.providerName, latencyMs, success);
5594
+ } catch {
5595
+ }
5596
+ }
5597
+ /**
5598
+ * Record CLI execution metrics
5599
+ */
5600
+ recordCLIMetrics(latencyMs, success) {
5601
+ try {
5602
+ const collector = getProviderMetrics();
5603
+ collector.recordCLIExecution(this.providerName, latencyMs, success);
5604
+ } catch {
5605
+ }
5606
+ }
5607
+ /**
5608
+ * Record fallback event metrics
5609
+ */
5610
+ recordFallbackMetrics(reason) {
5611
+ try {
5612
+ const collector = getProviderMetrics();
5613
+ collector.recordSDKFallback(this.providerName, reason);
5614
+ } catch {
5615
+ }
5616
+ }
5617
+ /**
5618
+ * Sleep utility
5619
+ */
5620
+ sleep(ms) {
5621
+ return new Promise((resolve5) => setTimeout(resolve5, ms));
5622
+ }
5623
+ /**
5624
+ * Get current active mode
5625
+ */
5626
+ getActiveMode() {
5627
+ return this.activeMode;
5628
+ }
5629
+ /**
5630
+ * Get SDK circuit breaker state
5631
+ */
5632
+ getSDKCircuitBreakerState() {
5633
+ return this.sdkCircuitBreaker.getState();
5634
+ }
5635
+ /**
5636
+ * Get CLI circuit breaker state
5637
+ */
5638
+ getCLICircuitBreakerState() {
5639
+ return this.cliCircuitBreaker.getState();
5640
+ }
5641
+ /**
5642
+ * Reset both circuit breakers
5643
+ */
5644
+ resetCircuitBreakers() {
5645
+ this.sdkCircuitBreaker.reset();
5646
+ this.cliCircuitBreaker.reset();
5647
+ logger.debug("Circuit breakers reset", { provider: this.providerName });
5648
+ }
5649
+ /**
5650
+ * Clean up resources
5651
+ */
5652
+ async destroy() {
5653
+ await this.destroySDK();
5654
+ await this.destroyCLI();
5655
+ this.sdkInitialized = false;
5656
+ this.cliInitialized = false;
5657
+ this.activeMode = null;
5658
+ this.initPromise = null;
5659
+ }
5660
+ };
5661
+ }
5662
+ });
5663
+
5664
+ // src/integrations/ax-glm/types.ts
5665
+ function normalizeGLMModel(model) {
5666
+ return GLM_MODEL_MAPPING[model] || model;
5667
+ }
5668
+ var GLM_MODEL_MAPPING, GLM_DEFAULT_BASE_URL, GLM_DEFAULT_MODEL, GLM_DEFAULT_COMMAND;
5669
+ var init_types2 = __esm({
5670
+ "src/integrations/ax-glm/types.ts"() {
5671
+ init_esm_shims();
5672
+ GLM_MODEL_MAPPING = {
5673
+ "glm-4-plus": "glm-4.6",
5674
+ "glm-4v": "glm-4.5v",
5675
+ "glm-4-air": "glm-4-flash",
5676
+ "glm-4-airx": "glm-4-flash"
5677
+ };
5678
+ GLM_DEFAULT_BASE_URL = "https://open.bigmodel.cn/api/paas/v4";
5679
+ GLM_DEFAULT_MODEL = "glm-4";
5680
+ GLM_DEFAULT_COMMAND = "ax-glm";
5681
+ }
5682
+ });
5683
+
5684
+ // src/integrations/ax-glm/sdk-adapter.ts
5685
+ var GLMSdkAdapter;
5686
+ var init_sdk_adapter2 = __esm({
5687
+ "src/integrations/ax-glm/sdk-adapter.ts"() {
5688
+ init_esm_shims();
5689
+ init_logger();
5690
+ init_validation_limits();
5691
+ init_types2();
5692
+ GLMSdkAdapter = class {
5693
+ client = null;
5694
+ config;
5695
+ initialized = false;
5696
+ constructor(config = {}) {
5697
+ this.config = {
5698
+ apiKey: config.apiKey || process.env.ZAI_API_KEY || "",
5699
+ baseUrl: config.baseUrl || GLM_DEFAULT_BASE_URL,
5700
+ model: config.model || GLM_DEFAULT_MODEL,
5701
+ timeout: config.timeout || TIMEOUTS.PROVIDER_DEFAULT
5702
+ };
5703
+ logger.debug("[GLM SDK] Adapter created", {
5704
+ model: this.config.model,
5705
+ baseUrl: this.config.baseUrl,
5706
+ hasApiKey: !!this.config.apiKey
5707
+ });
5708
+ }
5709
+ /**
5710
+ * Check if SDK is available (OpenAI package installed)
5711
+ */
5712
+ async isAvailable() {
5713
+ try {
5714
+ if (!this.config.apiKey) {
5715
+ logger.debug("[GLM SDK] No API key configured");
5716
+ return false;
5717
+ }
5718
+ await import('openai');
5719
+ return true;
5720
+ } catch (error) {
5721
+ logger.debug("[GLM SDK] OpenAI SDK not available", {
5722
+ error: error instanceof Error ? error.message : String(error)
5723
+ });
5724
+ return false;
5725
+ }
5726
+ }
5727
+ /**
5728
+ * Initialize the SDK client
5729
+ */
5730
+ async initialize() {
5731
+ if (this.initialized) {
5732
+ return;
5733
+ }
5734
+ try {
5735
+ const OpenAI = (await import('openai')).default;
5736
+ this.client = new OpenAI({
5737
+ apiKey: this.config.apiKey,
5738
+ baseURL: this.config.baseUrl,
5739
+ timeout: this.config.timeout
5740
+ });
5741
+ this.initialized = true;
5742
+ logger.debug("[GLM SDK] Client initialized", {
5743
+ model: this.config.model
5744
+ });
5745
+ } catch (error) {
5746
+ throw new Error(
5747
+ `Failed to initialize GLM SDK: ${error instanceof Error ? error.message : String(error)}`
5748
+ );
5749
+ }
5750
+ }
5751
+ /**
5752
+ * Execute a request using the GLM SDK
5753
+ */
5754
+ async execute(request) {
5755
+ if (!this.initialized) {
5756
+ await this.initialize();
5757
+ }
5758
+ const startTime = Date.now();
5759
+ try {
5760
+ const messages = [];
5761
+ if (request.systemPrompt) {
5762
+ messages.push({
5763
+ role: "system",
5764
+ content: request.systemPrompt
5765
+ });
5766
+ }
5767
+ messages.push({
5768
+ role: "user",
5769
+ content: request.prompt
5770
+ });
5771
+ const model = normalizeGLMModel(this.config.model);
5772
+ logger.debug("[GLM SDK] Executing request", {
5773
+ model,
5774
+ messageCount: messages.length,
5775
+ promptLength: request.prompt.length
5776
+ });
5777
+ const openaiClient = this.client;
5778
+ const response = await openaiClient.chat.completions.create({
5779
+ model,
5780
+ messages,
5781
+ max_tokens: request.maxTokens,
5782
+ temperature: request.temperature,
5783
+ stream: false
5784
+ });
5785
+ const latencyMs = Date.now() - startTime;
5786
+ if (!response.choices || response.choices.length === 0) {
5787
+ throw new Error("GLM API returned empty choices array");
5788
+ }
5789
+ const choice = response.choices[0];
5790
+ const content = choice?.message?.content || "";
5791
+ const finishReason = choice?.finish_reason || "unknown";
5792
+ logger.debug("[GLM SDK] Request completed", {
5793
+ model: response.model,
5794
+ latencyMs,
5795
+ tokensUsed: response.usage?.total_tokens
5796
+ });
5797
+ return {
5798
+ content,
5799
+ model: response.model,
5800
+ tokensUsed: response.usage ? {
5801
+ prompt: response.usage.prompt_tokens,
5802
+ completion: response.usage.completion_tokens,
5803
+ total: response.usage.total_tokens
5804
+ } : { prompt: 0, completion: 0, total: 0 },
5805
+ latencyMs,
5806
+ finishReason,
5807
+ cached: false
5808
+ };
5809
+ } catch (error) {
5810
+ const latencyMs = Date.now() - startTime;
5811
+ logger.error("[GLM SDK] Request failed", {
5812
+ error: error instanceof Error ? error.message : String(error),
5813
+ latencyMs
5814
+ });
5815
+ throw error;
5816
+ }
5817
+ }
5818
+ /**
5819
+ * Get the configured model
5820
+ */
5821
+ getModel() {
5822
+ return this.config.model;
5823
+ }
5824
+ /**
5825
+ * Clean up resources
5826
+ */
5827
+ async destroy() {
5828
+ this.client = null;
5829
+ this.initialized = false;
5830
+ logger.debug("[GLM SDK] Adapter destroyed");
5831
+ }
5832
+ };
5833
+ }
5834
+ });
5835
+ var execAsync, GLMCliWrapper;
5836
+ var init_cli_wrapper2 = __esm({
5837
+ "src/integrations/ax-glm/cli-wrapper.ts"() {
5838
+ init_esm_shims();
5839
+ init_logger();
5840
+ init_validation_limits();
5841
+ init_types2();
5842
+ execAsync = promisify(exec);
5843
+ GLMCliWrapper = class {
5844
+ config;
5845
+ cliPath = null;
5846
+ cliVersion = null;
5847
+ constructor(config = {}) {
5848
+ this.config = {
5849
+ command: config.command || GLM_DEFAULT_COMMAND,
5850
+ model: config.model || GLM_DEFAULT_MODEL,
5851
+ timeout: config.timeout || TIMEOUTS.PROVIDER_DEFAULT
5852
+ };
5853
+ logger.debug("[GLM CLI] Wrapper created", {
5854
+ command: this.config.command,
5855
+ model: this.config.model
5856
+ });
5857
+ }
5858
+ /**
5859
+ * Check if CLI is available
5860
+ */
5861
+ async isAvailable() {
5862
+ try {
5863
+ const { stdout } = await execAsync(`which ${this.config.command}`, {
5864
+ timeout: TIMEOUTS.PROVIDER_DETECTION
5865
+ });
5866
+ this.cliPath = stdout.trim();
5867
+ if (this.cliPath) {
5868
+ try {
5869
+ const { stdout: versionOutput } = await execAsync(
5870
+ `${this.config.command} --version`,
5871
+ { timeout: TIMEOUTS.PROVIDER_DETECTION }
5872
+ );
5873
+ this.cliVersion = versionOutput.trim();
5874
+ } catch {
5875
+ this.cliVersion = "unknown";
5876
+ }
5877
+ logger.debug("[GLM CLI] CLI available", {
5878
+ path: this.cliPath,
5879
+ version: this.cliVersion
5880
+ });
5881
+ return true;
5882
+ }
5883
+ return false;
5884
+ } catch (error) {
5885
+ logger.debug("[GLM CLI] CLI not available", {
5886
+ error: error instanceof Error ? error.message : String(error)
5887
+ });
5888
+ return false;
5889
+ }
5890
+ }
5891
+ /**
5892
+ * Initialize the CLI wrapper
5893
+ */
5894
+ async initialize() {
5895
+ const available = await this.isAvailable();
5896
+ if (!available) {
5897
+ throw new Error(`${this.config.command} CLI is not installed or not in PATH`);
5898
+ }
5899
+ }
5900
+ /**
5901
+ * Execute a request using the CLI
5902
+ */
5903
+ async execute(request) {
5904
+ const startTime = Date.now();
5905
+ try {
5906
+ const args2 = this.buildArgs(request);
5907
+ logger.debug("[GLM CLI] Executing", {
5908
+ command: this.config.command,
5909
+ args: args2,
5910
+ promptLength: request.prompt.length
5911
+ });
5912
+ const result = await this.spawnCLI(args2, request.prompt);
5913
+ const latencyMs = Date.now() - startTime;
5914
+ const response = this.parseResponse(result);
5915
+ logger.debug("[GLM CLI] Request completed", {
5916
+ latencyMs,
5917
+ contentLength: response.content.length
5918
+ });
5919
+ return {
5920
+ ...response,
5921
+ latencyMs,
5922
+ cached: false
5923
+ };
5924
+ } catch (error) {
5925
+ const latencyMs = Date.now() - startTime;
5926
+ logger.error("[GLM CLI] Request failed", {
5927
+ error: error instanceof Error ? error.message : String(error),
5928
+ latencyMs
5929
+ });
5930
+ throw error;
5931
+ }
5932
+ }
5933
+ /**
5934
+ * Build CLI arguments
5935
+ */
5936
+ buildArgs(request) {
5937
+ const args2 = ["-p"];
5938
+ const model = normalizeGLMModel(this.config.model);
5939
+ if (model !== "glm-4") {
5940
+ args2.push("--model", model);
5941
+ }
5942
+ if (request.systemPrompt) {
5943
+ args2.push("--system", request.systemPrompt);
5944
+ }
5945
+ if (request.maxTokens) {
5946
+ args2.push("--max-tokens", String(request.maxTokens));
5947
+ }
5948
+ if (request.temperature !== void 0) {
5949
+ args2.push("--temperature", String(request.temperature));
5950
+ }
5951
+ return args2;
5952
+ }
5953
+ /**
5954
+ * Spawn CLI process and get output
5955
+ */
5956
+ spawnCLI(args2, prompt) {
5957
+ return new Promise((resolve5, reject) => {
5958
+ const process2 = spawn(this.config.command, args2, {
5959
+ stdio: ["pipe", "pipe", "pipe"],
5960
+ timeout: this.config.timeout
5961
+ });
5962
+ let stdout = "";
5963
+ let stderr = "";
5964
+ process2.stdout.on("data", (data) => {
5965
+ stdout += data.toString();
5966
+ });
5967
+ process2.stderr.on("data", (data) => {
5968
+ stderr += data.toString();
5969
+ });
5970
+ process2.on("error", (error) => {
5971
+ reject(new Error(`CLI process error: ${error.message}`));
5972
+ });
5973
+ process2.on("close", (code) => {
5974
+ if (code === 0) {
5975
+ resolve5(stdout);
5976
+ } else {
5977
+ reject(new Error(
5978
+ `CLI exited with code ${code}: ${stderr || "No error message"}`
5979
+ ));
5980
+ }
5981
+ });
5982
+ process2.stdin.write(prompt);
5983
+ process2.stdin.end();
5984
+ });
5985
+ }
5986
+ /**
5987
+ * Parse CLI response
5988
+ */
5989
+ parseResponse(output) {
5990
+ try {
5991
+ const parsed = JSON.parse(output.trim());
5992
+ if (parsed.content || parsed.message) {
5993
+ return {
5994
+ content: parsed.content || parsed.message || "",
5995
+ model: parsed.model || normalizeGLMModel(this.config.model),
5996
+ tokensUsed: parsed.usage ? {
5997
+ prompt: parsed.usage.prompt_tokens || 0,
5998
+ completion: parsed.usage.completion_tokens || 0,
5999
+ total: parsed.usage.total_tokens || 0
6000
+ } : { prompt: 0, completion: 0, total: 0 },
6001
+ finishReason: parsed.finish_reason || "stop"
6002
+ };
6003
+ }
6004
+ } catch {
6005
+ }
6006
+ return {
6007
+ content: output.trim(),
6008
+ model: normalizeGLMModel(this.config.model),
6009
+ tokensUsed: { prompt: 0, completion: 0, total: 0 },
6010
+ finishReason: "stop"
6011
+ };
6012
+ }
6013
+ /**
6014
+ * Get the configured model
6015
+ */
6016
+ getModel() {
6017
+ return this.config.model;
6018
+ }
6019
+ /**
6020
+ * Get CLI version
6021
+ */
6022
+ getVersion() {
6023
+ return this.cliVersion;
6024
+ }
6025
+ /**
6026
+ * Get CLI command
6027
+ */
6028
+ getCommand() {
6029
+ return this.config.command;
6030
+ }
6031
+ /**
6032
+ * Clean up resources
6033
+ */
6034
+ async destroy() {
6035
+ logger.debug("[GLM CLI] Wrapper destroyed");
6036
+ }
6037
+ };
6038
+ }
6039
+ });
6040
+
6041
+ // src/integrations/ax-glm/hybrid-adapter.ts
6042
+ var GLMHybridAdapter;
6043
+ var init_hybrid_adapter2 = __esm({
6044
+ "src/integrations/ax-glm/hybrid-adapter.ts"() {
6045
+ init_esm_shims();
6046
+ init_hybrid_adapter_base();
6047
+ init_sdk_adapter2();
6048
+ init_cli_wrapper2();
6049
+ init_types2();
6050
+ init_logger();
6051
+ GLMHybridAdapter = class extends HybridAdapterBase {
6052
+ sdkAdapter = null;
6053
+ cliWrapper = null;
6054
+ model;
6055
+ sdkConfig;
6056
+ cliConfig;
6057
+ constructor(options = {}) {
6058
+ const baseOptions = {
6059
+ mode: options.mode || "auto",
6060
+ providerName: "glm",
6061
+ maxRetries: options.maxRetries ?? 1
6062
+ };
6063
+ super(baseOptions);
6064
+ this.model = options.model || GLM_DEFAULT_MODEL;
6065
+ this.sdkConfig = {
6066
+ apiKey: options.apiKey,
6067
+ baseUrl: options.baseUrl,
6068
+ timeout: options.timeout
6069
+ };
6070
+ this.cliConfig = {
6071
+ command: options.command,
6072
+ timeout: options.timeout
6073
+ };
6074
+ logger.debug("[GLM Hybrid] Adapter created", {
6075
+ mode: this.mode,
6076
+ model: this.model
6077
+ });
6078
+ }
6079
+ /**
6080
+ * Execute request via SDK
6081
+ */
6082
+ async executeViaSDK(request) {
6083
+ if (!this.sdkAdapter) {
6084
+ throw new Error("GLM SDK adapter not initialized");
6085
+ }
6086
+ return this.sdkAdapter.execute(request);
6087
+ }
6088
+ /**
6089
+ * Execute request via CLI
6090
+ */
6091
+ async executeViaCLI(request) {
6092
+ if (!this.cliWrapper) {
6093
+ throw new Error("GLM CLI wrapper not initialized");
6094
+ }
6095
+ return this.cliWrapper.execute(request);
6096
+ }
6097
+ /**
6098
+ * Check if SDK is available
6099
+ */
6100
+ async isSDKAvailable() {
6101
+ try {
6102
+ const adapter = new GLMSdkAdapter({
6103
+ ...this.sdkConfig,
6104
+ model: this.model
6105
+ });
6106
+ const available = await adapter.isAvailable();
6107
+ if (!available) {
6108
+ return false;
6109
+ }
6110
+ this.sdkAdapter = adapter;
6111
+ return true;
6112
+ } catch (error) {
6113
+ logger.debug("[GLM Hybrid] SDK availability check failed", {
6114
+ error: error instanceof Error ? error.message : String(error)
6115
+ });
6116
+ return false;
6117
+ }
6118
+ }
6119
+ /**
6120
+ * Check if CLI is available
6121
+ */
6122
+ async isCLIAvailable() {
6123
+ try {
6124
+ const wrapper = new GLMCliWrapper({
6125
+ ...this.cliConfig,
6126
+ model: this.model
6127
+ });
6128
+ const available = await wrapper.isAvailable();
6129
+ if (!available) {
6130
+ return false;
6131
+ }
6132
+ this.cliWrapper = wrapper;
6133
+ return true;
6134
+ } catch (error) {
6135
+ logger.debug("[GLM Hybrid] CLI availability check failed", {
6136
+ error: error instanceof Error ? error.message : String(error)
6137
+ });
6138
+ return false;
6139
+ }
6140
+ }
6141
+ /**
6142
+ * Initialize SDK adapter
6143
+ */
6144
+ async initializeSDK() {
6145
+ if (!this.sdkAdapter) {
6146
+ this.sdkAdapter = new GLMSdkAdapter({
6147
+ ...this.sdkConfig,
6148
+ model: this.model
6149
+ });
6150
+ }
6151
+ await this.sdkAdapter.initialize();
6152
+ logger.debug("[GLM Hybrid] SDK initialized", {
6153
+ model: this.model
6154
+ });
6155
+ }
6156
+ /**
6157
+ * Initialize CLI wrapper
6158
+ */
6159
+ async initializeCLI() {
6160
+ if (!this.cliWrapper) {
6161
+ this.cliWrapper = new GLMCliWrapper({
6162
+ ...this.cliConfig,
6163
+ model: this.model
6164
+ });
6165
+ }
6166
+ await this.cliWrapper.initialize();
6167
+ logger.debug("[GLM Hybrid] CLI initialized", {
6168
+ model: this.model,
6169
+ version: this.cliWrapper.getVersion()
6170
+ });
6171
+ }
6172
+ /**
6173
+ * Clean up SDK resources
6174
+ */
6175
+ async destroySDK() {
6176
+ if (this.sdkAdapter) {
6177
+ await this.sdkAdapter.destroy();
6178
+ this.sdkAdapter = null;
6179
+ }
6180
+ }
6181
+ /**
6182
+ * Clean up CLI resources
6183
+ */
6184
+ async destroyCLI() {
6185
+ if (this.cliWrapper) {
6186
+ await this.cliWrapper.destroy();
6187
+ this.cliWrapper = null;
6188
+ }
6189
+ }
6190
+ /**
6191
+ * Get the configured model
6192
+ */
6193
+ getModel() {
6194
+ return this.model;
6195
+ }
6196
+ /**
6197
+ * Get the CLI command being used
6198
+ */
6199
+ getCommand() {
6200
+ return this.cliWrapper?.getCommand() || this.cliConfig.command || "ax-glm";
6201
+ }
6202
+ /**
6203
+ * Get CLI version
6204
+ */
6205
+ getCLIVersion() {
6206
+ return this.cliWrapper?.getVersion() || null;
6207
+ }
6208
+ };
6209
+ }
6210
+ });
6211
+
6212
+ // src/integrations/ax-glm/sdk-only-adapter.ts
6213
+ var GLMSdkOnlyAdapter;
6214
+ var init_sdk_only_adapter = __esm({
6215
+ "src/integrations/ax-glm/sdk-only-adapter.ts"() {
6216
+ init_esm_shims();
6217
+ init_logger();
6218
+ init_sdk_adapter2();
6219
+ init_types2();
6220
+ GLMSdkOnlyAdapter = class {
6221
+ sdkAdapter;
6222
+ initialized = false;
6223
+ model;
6224
+ maxRetries;
6225
+ retryDelayMs;
6226
+ constructor(options = {}) {
6227
+ this.model = options.model || GLM_DEFAULT_MODEL;
6228
+ this.maxRetries = options.maxRetries ?? 2;
6229
+ this.retryDelayMs = options.retryDelayMs ?? 1e3;
6230
+ this.sdkAdapter = new GLMSdkAdapter({
6231
+ model: this.model,
6232
+ apiKey: options.apiKey,
6233
+ baseUrl: options.baseUrl,
6234
+ timeout: options.timeout
6235
+ });
6236
+ logger.debug("[GLM SDK-Only] Adapter created", {
6237
+ model: this.model,
6238
+ maxRetries: this.maxRetries
6239
+ });
6240
+ }
6241
+ /**
6242
+ * Check if SDK is available
6243
+ */
6244
+ async isAvailable() {
6245
+ return this.sdkAdapter.isAvailable();
6246
+ }
6247
+ /**
6248
+ * Initialize the adapter
6249
+ */
6250
+ async initialize() {
6251
+ if (this.initialized) {
6252
+ return;
6253
+ }
6254
+ const available = await this.sdkAdapter.isAvailable();
6255
+ if (!available) {
6256
+ throw new Error("GLM SDK not available - check API key and openai package");
6257
+ }
6258
+ await this.sdkAdapter.initialize();
6259
+ this.initialized = true;
6260
+ logger.debug("[GLM SDK-Only] Initialized", { model: this.model });
6261
+ }
6262
+ /**
6263
+ * Execute a request using GLM SDK
6264
+ *
6265
+ * Retries transient errors up to maxRetries times with exponential backoff.
6266
+ * Does NOT fall back to CLI - throws on persistent failure.
6267
+ */
6268
+ async execute(request) {
6269
+ if (!this.initialized) {
6270
+ await this.initialize();
6271
+ }
6272
+ const startTime = Date.now();
6273
+ let lastError;
6274
+ for (let attempt = 0; attempt <= this.maxRetries; attempt++) {
6275
+ try {
6276
+ const response = await this.sdkAdapter.execute(request);
6277
+ logger.debug("[GLM SDK-Only] Execution succeeded", {
6278
+ model: this.model,
6279
+ attempt: attempt + 1,
6280
+ latencyMs: response.latencyMs
6281
+ });
6282
+ return response;
6283
+ } catch (error) {
6284
+ lastError = error;
6285
+ logger.warn("[GLM SDK-Only] Execution failed", {
6286
+ model: this.model,
6287
+ attempt: attempt + 1,
6288
+ maxRetries: this.maxRetries,
6289
+ error: lastError.message
6290
+ });
6291
+ if (attempt < this.maxRetries && this.isRetryableError(lastError)) {
6292
+ const delay = this.retryDelayMs * Math.pow(2, attempt);
6293
+ logger.debug("[GLM SDK-Only] Retrying after delay", {
6294
+ attempt: attempt + 1,
6295
+ delayMs: delay
6296
+ });
6297
+ await this.sleep(delay);
6298
+ continue;
6299
+ }
6300
+ break;
6301
+ }
6302
+ }
6303
+ const totalTime = Date.now() - startTime;
6304
+ logger.error("[GLM SDK-Only] All retries exhausted", {
6305
+ model: this.model,
6306
+ totalAttempts: this.maxRetries + 1,
6307
+ totalTimeMs: totalTime,
6308
+ lastError: lastError?.message
6309
+ });
6310
+ throw new Error(
6311
+ `GLM SDK execution failed after ${this.maxRetries + 1} attempts: ${lastError?.message || "Unknown error"}`
6312
+ );
6313
+ }
6314
+ /**
6315
+ * Check if error is retryable
6316
+ */
6317
+ isRetryableError(error) {
6318
+ const message = error.message.toLowerCase();
6319
+ if (message.includes("rate limit") || message.includes("429")) {
6320
+ return true;
6321
+ }
6322
+ if (message.includes("500") || message.includes("502") || message.includes("503") || message.includes("504")) {
6323
+ return true;
6324
+ }
6325
+ if (message.includes("timeout") || message.includes("etimedout")) {
6326
+ return true;
6327
+ }
6328
+ if (message.includes("econnreset") || message.includes("econnrefused")) {
6329
+ return true;
6330
+ }
6331
+ return false;
6332
+ }
6333
+ /**
6334
+ * Sleep utility
6335
+ */
6336
+ sleep(ms) {
6337
+ return new Promise((resolve5) => setTimeout(resolve5, ms));
6338
+ }
6339
+ /**
6340
+ * Get the configured model
6341
+ */
6342
+ getModel() {
6343
+ return this.model;
6344
+ }
6345
+ /**
6346
+ * Clean up resources
6347
+ */
6348
+ async destroy() {
6349
+ await this.sdkAdapter.destroy();
6350
+ this.initialized = false;
6351
+ logger.debug("[GLM SDK-Only] Adapter destroyed");
6352
+ }
6353
+ };
6354
+ }
6355
+ });
6356
+
6357
+ // src/integrations/ax-glm/mcp-client-mode.ts
6358
+ var init_mcp_client_mode = __esm({
6359
+ "src/integrations/ax-glm/mcp-client-mode.ts"() {
6360
+ init_esm_shims();
6361
+ init_logger();
6362
+ init_sdk_adapter2();
6363
+ }
6364
+ });
6365
+
6366
+ // src/integrations/ax-glm/index.ts
6367
+ var init_ax_glm = __esm({
6368
+ "src/integrations/ax-glm/index.ts"() {
6369
+ init_esm_shims();
6370
+ init_hybrid_adapter2();
6371
+ init_sdk_adapter2();
6372
+ init_cli_wrapper2();
6373
+ init_sdk_only_adapter();
6374
+ init_mcp_client_mode();
6375
+ init_types2();
6376
+ }
6377
+ });
6378
+
6379
+ // src/providers/glm-provider.ts
6380
+ var glm_provider_exports = {};
6381
+ __export(glm_provider_exports, {
6382
+ GLMProvider: () => GLMProvider,
6383
+ default: () => GLMProvider
6384
+ });
6385
+ var MODEL_MAPPING, GLMProvider;
6386
+ var init_glm_provider = __esm({
6387
+ "src/providers/glm-provider.ts"() {
6388
+ init_esm_shims();
6389
+ init_base_provider();
6390
+ init_logger();
6391
+ init_ax_glm();
6392
+ MODEL_MAPPING = {
6393
+ "glm-4-plus": "glm-4.6",
6394
+ "glm-4v": "glm-4.5v",
6395
+ "glm-4-air": "glm-4-flash",
6396
+ "glm-4-airx": "glm-4-flash"
6397
+ };
6398
+ GLMProvider = class _GLMProvider extends BaseProvider {
6399
+ /** Selected model */
6400
+ model;
6401
+ /** SDK-only adapter for direct execution (v13.0.0) */
6402
+ sdkOnlyAdapter = null;
6403
+ /** Legacy hybrid adapter for 'auto' mode (backwards compatibility) */
6404
+ hybridAdapter = null;
6405
+ /** Provider configuration */
6406
+ glmConfig;
6407
+ /** Supported models */
6408
+ static SUPPORTED_MODELS = [
6409
+ "glm-4.6",
6410
+ "glm-4.5v",
6411
+ "glm-4",
6412
+ "glm-4-flash",
6413
+ // Legacy aliases
6414
+ "glm-4-plus",
6415
+ "glm-4v",
6416
+ "glm-4-air",
6417
+ "glm-4-airx"
6418
+ ];
6419
+ constructor(config) {
6420
+ super({
6421
+ ...config,
6422
+ command: "ax-glm"
6423
+ });
6424
+ this.glmConfig = config;
6425
+ const requestedModel = config.model || "glm-4";
6426
+ if (!_GLMProvider.SUPPORTED_MODELS.includes(requestedModel)) {
6427
+ logger.warn(`[GLM] Unknown model: ${requestedModel}. Using glm-4.`);
6428
+ this.model = "glm-4";
6429
+ } else {
6430
+ this.model = requestedModel;
6431
+ }
6432
+ logger.debug("[GLM Provider] Initialized", {
6433
+ model: this.model,
6434
+ mode: config.mode || "auto"
6435
+ });
6436
+ }
6437
+ /**
6438
+ * Get the normalized model name
6439
+ */
6440
+ getNormalizedModel() {
6441
+ return MODEL_MAPPING[this.model] || this.model;
6442
+ }
6443
+ /**
6444
+ * Get or create SDK-only adapter (v13.0.0 default)
6445
+ */
6446
+ getSdkOnlyAdapter() {
6447
+ if (!this.sdkOnlyAdapter) {
6448
+ this.sdkOnlyAdapter = new GLMSdkOnlyAdapter({
6449
+ model: this.model,
6450
+ apiKey: this.glmConfig.apiKey,
6451
+ baseUrl: this.glmConfig.baseUrl,
6452
+ timeout: this.glmConfig.timeout
6453
+ });
6454
+ }
6455
+ return this.sdkOnlyAdapter;
6456
+ }
6457
+ /**
6458
+ * Get or create hybrid adapter (legacy, for 'auto' mode only)
6459
+ */
6460
+ getHybridAdapter() {
6461
+ if (!this.hybridAdapter) {
6462
+ const options = {
6463
+ mode: this.glmConfig.mode || "auto",
6464
+ model: this.model,
6465
+ apiKey: this.glmConfig.apiKey,
6466
+ baseUrl: this.glmConfig.baseUrl,
6467
+ command: "ax-glm",
6468
+ timeout: this.glmConfig.timeout
6469
+ };
6470
+ this.hybridAdapter = new GLMHybridAdapter(options);
6471
+ }
6472
+ return this.hybridAdapter;
6473
+ }
6474
+ /**
6475
+ * Execute a task using GLM
6476
+ *
6477
+ * Execution flow (v13.0.0):
6478
+ * 1. Mock mode → return mock response
6479
+ * 2. mode='sdk' (default) → use SDK-only adapter (NO CLI fallback)
6480
+ * 3. mode='auto' (legacy) → use hybrid adapter (SDK with CLI fallback)
6481
+ * 4. mode='cli' → use CLI via BaseProvider (deprecated for GLM)
6482
+ */
6483
+ async execute(request) {
6484
+ if (process.env.AX_MOCK_PROVIDERS === "true") {
6485
+ return this.createMockResponse(request.prompt);
6486
+ }
6487
+ const effectiveMode = this.glmConfig.mode || "sdk";
6488
+ if (effectiveMode === "cli") {
6489
+ logger.warn("[GLM Provider] CLI mode is deprecated for GLM. Consider using SDK mode.", {
6490
+ model: this.model
6491
+ });
6492
+ return super.execute(request);
6493
+ }
6494
+ if (effectiveMode === "auto") {
6495
+ logger.debug("[GLM Provider] Executing via hybrid adapter (legacy auto mode)", {
6496
+ promptLength: request.prompt.length,
6497
+ model: this.model
6498
+ });
6499
+ const adapter2 = this.getHybridAdapter();
6500
+ return adapter2.execute(request);
6501
+ }
6502
+ logger.debug("[GLM Provider] Executing via SDK-only adapter", {
6503
+ promptLength: request.prompt.length,
6504
+ model: this.model
6505
+ });
6506
+ const adapter = this.getSdkOnlyAdapter();
6507
+ return adapter.execute(request);
6508
+ }
6509
+ /**
6510
+ * Get CLI command
6511
+ */
6512
+ getCLICommand() {
6513
+ const adapter = this.hybridAdapter;
6514
+ if (adapter) {
6515
+ const activeMode = adapter.getActiveMode();
6516
+ if (activeMode === "sdk") {
6517
+ return "glm-sdk";
6518
+ }
6519
+ }
6520
+ return "ax-glm";
6521
+ }
6522
+ /**
6523
+ * Get CLI arguments for ax-glm headless mode
6524
+ */
6525
+ getCLIArgs() {
6526
+ const args2 = ["-p"];
6527
+ const normalizedModel = this.getNormalizedModel();
6528
+ if (normalizedModel !== "glm-4") {
6529
+ args2.push("--model", normalizedModel);
6530
+ }
6531
+ return args2;
6532
+ }
6533
+ /**
6534
+ * Create mock response for testing
6535
+ */
6536
+ createMockResponse(prompt) {
6537
+ return {
6538
+ content: this.getMockResponse(),
6539
+ model: this.getNormalizedModel(),
6540
+ tokensUsed: {
6541
+ prompt: this.estimateTokens(prompt),
6542
+ completion: 50,
6543
+ total: this.estimateTokens(prompt) + 50
6544
+ },
6545
+ latencyMs: 10,
6546
+ finishReason: "stop",
6547
+ cached: false
6548
+ };
6549
+ }
6550
+ /**
6551
+ * Estimate token count
6552
+ */
6553
+ estimateTokens(text) {
6554
+ return Math.ceil(text.length / 4);
6555
+ }
6556
+ /**
6557
+ * Get mock response for testing
6558
+ */
6559
+ getMockResponse() {
6560
+ return `[Mock GLM Response]
6561
+
6562
+ This is a mock response from the GLM provider (${this.getNormalizedModel()}).
6563
+ In production, this would be a response from ${this.glmConfig.mode === "sdk" ? "GLM SDK" : "ax-glm CLI"}.
6564
+
6565
+ Model: ${this.getNormalizedModel()}
6566
+ Provider: GLM (Zhipu AI)
6567
+ Mode: ${this.glmConfig.mode || "auto"}`;
6568
+ }
6569
+ /**
6570
+ * Get provider capabilities
6571
+ */
6572
+ get capabilities() {
6573
+ const model = this.getNormalizedModel();
6574
+ const isVision = model.includes("v") || model === "glm-4.5v";
6575
+ let maxContextTokens = 128e3;
6576
+ if (model === "glm-4.6") maxContextTokens = 2e5;
6577
+ if (model === "glm-4.5v") maxContextTokens = 64e3;
6578
+ const activeMode = this.hybridAdapter?.getActiveMode();
6579
+ const integrationMode = activeMode === "sdk" ? "sdk" : "cli";
6580
+ return {
6581
+ ...super.capabilities,
6582
+ supportsStreaming: true,
6583
+ supportsVision: isVision,
6584
+ maxContextTokens,
6585
+ supportedModels: _GLMProvider.SUPPORTED_MODELS,
6586
+ integrationMode
6587
+ };
6588
+ }
6589
+ /**
6590
+ * Get the active execution mode
6591
+ */
6592
+ getActiveMode() {
6593
+ return this.hybridAdapter?.getActiveMode() || null;
6594
+ }
6595
+ /**
6596
+ * Reset circuit breakers
6597
+ */
6598
+ resetCircuitBreakers() {
6599
+ this.hybridAdapter?.resetCircuitBreakers();
6600
+ }
6601
+ /**
6602
+ * Clean up resources
6603
+ */
6604
+ async destroy() {
6605
+ if (this.sdkOnlyAdapter) {
6606
+ await this.sdkOnlyAdapter.destroy();
6607
+ this.sdkOnlyAdapter = null;
6608
+ }
6609
+ if (this.hybridAdapter) {
6610
+ await this.hybridAdapter.destroy();
6611
+ this.hybridAdapter = null;
6612
+ }
6613
+ }
6614
+ /**
6615
+ * Get the list of supported models
6616
+ */
6617
+ static getSupportedModels() {
6618
+ return [..._GLMProvider.SUPPORTED_MODELS];
6619
+ }
6620
+ };
6621
+ }
6622
+ });
6623
+
6624
+ // src/integrations/ax-grok/types.ts
6625
+ function normalizeGrokModel(model) {
6626
+ return GROK_MODEL_MAPPING[model] || model;
6627
+ }
6628
+ var GROK_MODEL_MAPPING, GROK_DEFAULT_BASE_URL, GROK_DEFAULT_MODEL, GROK_DEFAULT_COMMAND;
6629
+ var init_types3 = __esm({
6630
+ "src/integrations/ax-grok/types.ts"() {
6631
+ init_esm_shims();
6632
+ GROK_MODEL_MAPPING = {
6633
+ "grok-beta": "grok-3"
6634
+ };
6635
+ GROK_DEFAULT_BASE_URL = "https://api.x.ai/v1";
6636
+ GROK_DEFAULT_MODEL = "grok-3";
6637
+ GROK_DEFAULT_COMMAND = "ax-grok";
6638
+ }
6639
+ });
6640
+
6641
+ // src/integrations/ax-grok/sdk-adapter.ts
6642
+ var GrokSdkAdapter;
6643
+ var init_sdk_adapter3 = __esm({
6644
+ "src/integrations/ax-grok/sdk-adapter.ts"() {
6645
+ init_esm_shims();
6646
+ init_logger();
6647
+ init_validation_limits();
6648
+ init_types3();
6649
+ GrokSdkAdapter = class {
6650
+ client = null;
6651
+ config;
6652
+ initialized = false;
6653
+ constructor(config = {}) {
6654
+ this.config = {
6655
+ apiKey: config.apiKey || process.env.XAI_API_KEY || "",
6656
+ baseUrl: config.baseUrl || GROK_DEFAULT_BASE_URL,
6657
+ model: config.model || GROK_DEFAULT_MODEL,
6658
+ timeout: config.timeout || TIMEOUTS.PROVIDER_DEFAULT
6659
+ };
6660
+ logger.debug("[Grok SDK] Adapter created", {
6661
+ model: this.config.model,
6662
+ baseUrl: this.config.baseUrl,
6663
+ hasApiKey: !!this.config.apiKey
6664
+ });
6665
+ }
6666
+ /**
6667
+ * Check if SDK is available (OpenAI package installed and API key present)
6668
+ */
6669
+ async isAvailable() {
6670
+ try {
6671
+ if (!this.config.apiKey) {
6672
+ logger.debug("[Grok SDK] No API key configured");
6673
+ return false;
6674
+ }
6675
+ await import('openai');
6676
+ return true;
6677
+ } catch (error) {
6678
+ logger.debug("[Grok SDK] OpenAI SDK not available", {
6679
+ error: error instanceof Error ? error.message : String(error)
6680
+ });
6681
+ return false;
6682
+ }
6683
+ }
6684
+ /**
6685
+ * Initialize the SDK client
6686
+ */
6687
+ async initialize() {
6688
+ if (this.initialized) {
6689
+ return;
6690
+ }
6691
+ try {
6692
+ const OpenAI = (await import('openai')).default;
6693
+ this.client = new OpenAI({
6694
+ apiKey: this.config.apiKey,
6695
+ baseURL: this.config.baseUrl,
6696
+ timeout: this.config.timeout
6697
+ });
6698
+ this.initialized = true;
6699
+ logger.debug("[Grok SDK] Client initialized", {
6700
+ model: this.config.model
6701
+ });
6702
+ } catch (error) {
6703
+ throw new Error(
6704
+ `Failed to initialize Grok SDK: ${error instanceof Error ? error.message : String(error)}`
6705
+ );
6706
+ }
6707
+ }
6708
+ /**
6709
+ * Execute a request using the Grok SDK
6710
+ */
6711
+ async execute(request) {
6712
+ if (!this.initialized) {
6713
+ await this.initialize();
6714
+ }
6715
+ const startTime = Date.now();
6716
+ try {
6717
+ const messages = [];
6718
+ if (request.systemPrompt) {
6719
+ messages.push({
6720
+ role: "system",
6721
+ content: request.systemPrompt
6722
+ });
6723
+ }
6724
+ messages.push({
6725
+ role: "user",
6726
+ content: request.prompt
6727
+ });
6728
+ const model = normalizeGrokModel(this.config.model);
6729
+ logger.debug("[Grok SDK] Executing request", {
6730
+ model,
6731
+ messageCount: messages.length,
6732
+ promptLength: request.prompt.length
6733
+ });
6734
+ const openaiClient = this.client;
6735
+ const response = await openaiClient.chat.completions.create({
6736
+ model,
6737
+ messages,
6738
+ max_tokens: request.maxTokens,
6739
+ temperature: request.temperature,
6740
+ stream: false
6741
+ });
6742
+ const latencyMs = Date.now() - startTime;
6743
+ if (!response.choices || response.choices.length === 0) {
6744
+ throw new Error("Grok API returned empty choices array");
6745
+ }
6746
+ const choice = response.choices[0];
6747
+ const content = choice?.message?.content || "";
6748
+ const finishReason = choice?.finish_reason || "unknown";
6749
+ logger.debug("[Grok SDK] Request completed", {
6750
+ model: response.model,
6751
+ latencyMs,
6752
+ tokensUsed: response.usage?.total_tokens
6753
+ });
6754
+ return {
6755
+ content,
6756
+ model: response.model,
6757
+ tokensUsed: response.usage ? {
6758
+ prompt: response.usage.prompt_tokens,
6759
+ completion: response.usage.completion_tokens,
6760
+ total: response.usage.total_tokens
6761
+ } : { prompt: 0, completion: 0, total: 0 },
6762
+ latencyMs,
6763
+ finishReason,
6764
+ cached: false
6765
+ };
6766
+ } catch (error) {
6767
+ const latencyMs = Date.now() - startTime;
6768
+ logger.error("[Grok SDK] Request failed", {
6769
+ error: error instanceof Error ? error.message : String(error),
6770
+ latencyMs
6771
+ });
6772
+ throw error;
6773
+ }
6774
+ }
6775
+ /**
6776
+ * Get the configured model
6777
+ */
6778
+ getModel() {
6779
+ return this.config.model;
6780
+ }
6781
+ /**
6782
+ * Clean up resources
6783
+ */
6784
+ async destroy() {
6785
+ this.client = null;
6786
+ this.initialized = false;
6787
+ logger.debug("[Grok SDK] Adapter destroyed");
6788
+ }
6789
+ };
6790
+ }
6791
+ });
6792
+ var execAsync2, GrokCliWrapper;
6793
+ var init_cli_wrapper3 = __esm({
6794
+ "src/integrations/ax-grok/cli-wrapper.ts"() {
6795
+ init_esm_shims();
6796
+ init_logger();
6797
+ init_validation_limits();
6798
+ init_types3();
6799
+ execAsync2 = promisify(exec);
6800
+ GrokCliWrapper = class {
6801
+ config;
6802
+ cliPath = null;
6803
+ cliVersion = null;
6804
+ constructor(config = {}) {
6805
+ this.config = {
6806
+ command: config.command || GROK_DEFAULT_COMMAND,
6807
+ model: config.model || GROK_DEFAULT_MODEL,
6808
+ timeout: config.timeout || TIMEOUTS.PROVIDER_DEFAULT
6809
+ };
6810
+ logger.debug("[Grok CLI] Wrapper created", {
6811
+ command: this.config.command,
6812
+ model: this.config.model
6813
+ });
6814
+ }
6815
+ /**
6816
+ * Check if CLI is available
6817
+ */
6818
+ async isAvailable() {
6819
+ try {
6820
+ const { stdout } = await execAsync2(`which ${this.config.command}`, {
6821
+ timeout: TIMEOUTS.PROVIDER_DETECTION
6822
+ });
6823
+ this.cliPath = stdout.trim();
6824
+ if (this.cliPath) {
6825
+ try {
6826
+ const { stdout: versionOutput } = await execAsync2(
6827
+ `${this.config.command} --version`,
6828
+ { timeout: TIMEOUTS.PROVIDER_DETECTION }
6829
+ );
6830
+ this.cliVersion = versionOutput.trim();
6831
+ } catch {
6832
+ this.cliVersion = "unknown";
6833
+ }
6834
+ logger.debug("[Grok CLI] CLI available", {
6835
+ path: this.cliPath,
6836
+ version: this.cliVersion
6837
+ });
6838
+ return true;
6839
+ }
6840
+ return false;
6841
+ } catch (error) {
6842
+ logger.debug("[Grok CLI] CLI not available", {
6843
+ error: error instanceof Error ? error.message : String(error)
6844
+ });
6845
+ return false;
6846
+ }
6847
+ }
6848
+ /**
6849
+ * Initialize the CLI wrapper
6850
+ */
6851
+ async initialize() {
6852
+ const available = await this.isAvailable();
6853
+ if (!available) {
6854
+ throw new Error(`${this.config.command} CLI is not installed or not in PATH`);
6855
+ }
6856
+ }
6857
+ /**
6858
+ * Execute a request using the CLI
6859
+ */
6860
+ async execute(request) {
6861
+ const startTime = Date.now();
6862
+ try {
6863
+ const args2 = this.buildArgs(request);
6864
+ logger.debug("[Grok CLI] Executing", {
6865
+ command: this.config.command,
6866
+ args: args2,
6867
+ promptLength: request.prompt.length
6868
+ });
6869
+ const result = await this.spawnCLI(args2, request.prompt);
6870
+ const latencyMs = Date.now() - startTime;
6871
+ const response = this.parseResponse(result);
6872
+ logger.debug("[Grok CLI] Request completed", {
6873
+ latencyMs,
6874
+ contentLength: response.content.length
6875
+ });
6876
+ return {
6877
+ ...response,
6878
+ latencyMs,
6879
+ cached: false
6880
+ };
6881
+ } catch (error) {
6882
+ const latencyMs = Date.now() - startTime;
6883
+ logger.error("[Grok CLI] Request failed", {
6884
+ error: error instanceof Error ? error.message : String(error),
6885
+ latencyMs
6886
+ });
6887
+ throw error;
6888
+ }
6889
+ }
6890
+ /**
6891
+ * Build CLI arguments
6892
+ */
6893
+ buildArgs(request) {
6894
+ const args2 = ["-p"];
6895
+ const model = normalizeGrokModel(this.config.model);
6896
+ if (model !== "grok-3") {
6897
+ args2.push("--model", model);
6898
+ }
6899
+ if (request.systemPrompt) {
6900
+ args2.push("--system", request.systemPrompt);
6901
+ }
6902
+ if (request.maxTokens) {
6903
+ args2.push("--max-tokens", String(request.maxTokens));
6904
+ }
6905
+ if (request.temperature !== void 0) {
6906
+ args2.push("--temperature", String(request.temperature));
6907
+ }
6908
+ return args2;
6909
+ }
6910
+ /**
6911
+ * Spawn CLI process and get output
6912
+ */
6913
+ spawnCLI(args2, prompt) {
6914
+ return new Promise((resolve5, reject) => {
6915
+ const process2 = spawn(this.config.command, args2, {
6916
+ stdio: ["pipe", "pipe", "pipe"],
6917
+ timeout: this.config.timeout
6918
+ });
6919
+ let stdout = "";
6920
+ let stderr = "";
6921
+ process2.stdout.on("data", (data) => {
6922
+ stdout += data.toString();
6923
+ });
6924
+ process2.stderr.on("data", (data) => {
6925
+ stderr += data.toString();
6926
+ });
6927
+ process2.on("error", (error) => {
6928
+ reject(new Error(`CLI process error: ${error.message}`));
6929
+ });
6930
+ process2.on("close", (code) => {
6931
+ if (code === 0) {
6932
+ resolve5(stdout);
6933
+ } else {
6934
+ reject(new Error(
6935
+ `CLI exited with code ${code}: ${stderr || "No error message"}`
6936
+ ));
6937
+ }
6938
+ });
6939
+ process2.stdin.write(prompt);
6940
+ process2.stdin.end();
6941
+ });
6942
+ }
6943
+ /**
6944
+ * Parse CLI response
6945
+ */
6946
+ parseResponse(output) {
6947
+ try {
6948
+ const parsed = JSON.parse(output.trim());
6949
+ if (parsed.content || parsed.message) {
6950
+ return {
6951
+ content: parsed.content || parsed.message || "",
6952
+ model: parsed.model || normalizeGrokModel(this.config.model),
6953
+ tokensUsed: parsed.usage ? {
6954
+ prompt: parsed.usage.prompt_tokens || 0,
6955
+ completion: parsed.usage.completion_tokens || 0,
6956
+ total: parsed.usage.total_tokens || 0
6957
+ } : { prompt: 0, completion: 0, total: 0 },
6958
+ finishReason: parsed.finish_reason || "stop"
6959
+ };
6960
+ }
6961
+ } catch {
6962
+ }
6963
+ return {
6964
+ content: output.trim(),
6965
+ model: normalizeGrokModel(this.config.model),
6966
+ tokensUsed: { prompt: 0, completion: 0, total: 0 },
6967
+ finishReason: "stop"
6968
+ };
6969
+ }
6970
+ /**
6971
+ * Get the configured model
6972
+ */
6973
+ getModel() {
6974
+ return this.config.model;
6975
+ }
6976
+ /**
6977
+ * Get CLI version
6978
+ */
6979
+ getVersion() {
6980
+ return this.cliVersion;
6981
+ }
6982
+ /**
6983
+ * Get CLI command
6984
+ */
6985
+ getCommand() {
6986
+ return this.config.command;
6987
+ }
6988
+ /**
6989
+ * Clean up resources
6990
+ */
6991
+ async destroy() {
6992
+ logger.debug("[Grok CLI] Wrapper destroyed");
6993
+ }
6994
+ };
6995
+ }
6996
+ });
6997
+
6998
+ // src/integrations/ax-grok/hybrid-adapter.ts
6999
+ var GrokHybridAdapter;
7000
+ var init_hybrid_adapter3 = __esm({
7001
+ "src/integrations/ax-grok/hybrid-adapter.ts"() {
7002
+ init_esm_shims();
7003
+ init_hybrid_adapter_base();
7004
+ init_sdk_adapter3();
7005
+ init_cli_wrapper3();
7006
+ init_types3();
7007
+ init_logger();
7008
+ GrokHybridAdapter = class extends HybridAdapterBase {
7009
+ sdkAdapter = null;
7010
+ cliWrapper = null;
7011
+ model;
7012
+ sdkConfig;
7013
+ cliConfig;
7014
+ constructor(options = {}) {
7015
+ const baseOptions = {
7016
+ mode: options.mode || "auto",
7017
+ providerName: "grok",
7018
+ maxRetries: options.maxRetries ?? 1
7019
+ };
7020
+ super(baseOptions);
7021
+ this.model = options.model || GROK_DEFAULT_MODEL;
7022
+ this.sdkConfig = {
7023
+ apiKey: options.apiKey,
7024
+ baseUrl: options.baseUrl,
7025
+ timeout: options.timeout
7026
+ };
7027
+ this.cliConfig = {
7028
+ command: options.command,
7029
+ timeout: options.timeout
7030
+ };
7031
+ logger.debug("[Grok Hybrid] Adapter created", {
7032
+ mode: this.mode,
7033
+ model: this.model
7034
+ });
7035
+ }
7036
+ /**
7037
+ * Execute request via SDK
7038
+ */
7039
+ async executeViaSDK(request) {
7040
+ if (!this.sdkAdapter) {
7041
+ throw new Error("Grok SDK adapter not initialized");
7042
+ }
7043
+ return this.sdkAdapter.execute(request);
7044
+ }
7045
+ /**
7046
+ * Execute request via CLI
7047
+ */
7048
+ async executeViaCLI(request) {
7049
+ if (!this.cliWrapper) {
7050
+ throw new Error("Grok CLI wrapper not initialized");
7051
+ }
7052
+ return this.cliWrapper.execute(request);
7053
+ }
7054
+ /**
7055
+ * Check if SDK is available
7056
+ */
7057
+ async isSDKAvailable() {
7058
+ try {
7059
+ const adapter = new GrokSdkAdapter({
7060
+ ...this.sdkConfig,
7061
+ model: this.model
7062
+ });
7063
+ const available = await adapter.isAvailable();
7064
+ if (!available) {
7065
+ return false;
7066
+ }
7067
+ this.sdkAdapter = adapter;
7068
+ return true;
7069
+ } catch (error) {
7070
+ logger.debug("[Grok Hybrid] SDK availability check failed", {
7071
+ error: error instanceof Error ? error.message : String(error)
7072
+ });
7073
+ return false;
7074
+ }
7075
+ }
7076
+ /**
7077
+ * Check if CLI is available
7078
+ */
7079
+ async isCLIAvailable() {
7080
+ try {
7081
+ const wrapper = new GrokCliWrapper({
7082
+ ...this.cliConfig,
7083
+ model: this.model
7084
+ });
7085
+ const available = await wrapper.isAvailable();
7086
+ if (!available) {
7087
+ return false;
7088
+ }
7089
+ this.cliWrapper = wrapper;
7090
+ return true;
7091
+ } catch (error) {
7092
+ logger.debug("[Grok Hybrid] CLI availability check failed", {
7093
+ error: error instanceof Error ? error.message : String(error)
7094
+ });
7095
+ return false;
7096
+ }
7097
+ }
7098
+ /**
7099
+ * Initialize SDK adapter
7100
+ */
7101
+ async initializeSDK() {
7102
+ if (!this.sdkAdapter) {
7103
+ this.sdkAdapter = new GrokSdkAdapter({
7104
+ ...this.sdkConfig,
7105
+ model: this.model
7106
+ });
7107
+ }
7108
+ await this.sdkAdapter.initialize();
7109
+ logger.debug("[Grok Hybrid] SDK initialized", {
7110
+ model: this.model
7111
+ });
7112
+ }
7113
+ /**
7114
+ * Initialize CLI wrapper
7115
+ */
7116
+ async initializeCLI() {
7117
+ if (!this.cliWrapper) {
7118
+ this.cliWrapper = new GrokCliWrapper({
7119
+ ...this.cliConfig,
7120
+ model: this.model
7121
+ });
7122
+ }
7123
+ await this.cliWrapper.initialize();
7124
+ logger.debug("[Grok Hybrid] CLI initialized", {
7125
+ model: this.model,
7126
+ version: this.cliWrapper.getVersion()
7127
+ });
7128
+ }
7129
+ /**
7130
+ * Clean up SDK resources
7131
+ */
7132
+ async destroySDK() {
7133
+ if (this.sdkAdapter) {
7134
+ await this.sdkAdapter.destroy();
7135
+ this.sdkAdapter = null;
7136
+ }
7137
+ }
7138
+ /**
7139
+ * Clean up CLI resources
7140
+ */
7141
+ async destroyCLI() {
7142
+ if (this.cliWrapper) {
7143
+ await this.cliWrapper.destroy();
7144
+ this.cliWrapper = null;
7145
+ }
7146
+ }
7147
+ /**
7148
+ * Get the configured model
7149
+ */
7150
+ getModel() {
7151
+ return this.model;
7152
+ }
7153
+ /**
7154
+ * Get the CLI command being used
7155
+ */
7156
+ getCommand() {
7157
+ return this.cliWrapper?.getCommand() || this.cliConfig.command || "ax-grok";
7158
+ }
7159
+ /**
7160
+ * Get CLI version
7161
+ */
7162
+ getCLIVersion() {
7163
+ return this.cliWrapper?.getVersion() || null;
7164
+ }
7165
+ };
7166
+ }
7167
+ });
7168
+
7169
+ // src/integrations/ax-grok/sdk-only-adapter.ts
7170
+ var GrokSdkOnlyAdapter;
7171
+ var init_sdk_only_adapter2 = __esm({
7172
+ "src/integrations/ax-grok/sdk-only-adapter.ts"() {
7173
+ init_esm_shims();
7174
+ init_logger();
7175
+ init_sdk_adapter3();
7176
+ init_types3();
7177
+ GrokSdkOnlyAdapter = class {
7178
+ sdkAdapter;
7179
+ initialized = false;
7180
+ model;
7181
+ maxRetries;
7182
+ retryDelayMs;
7183
+ constructor(options = {}) {
7184
+ this.model = options.model || GROK_DEFAULT_MODEL;
7185
+ this.maxRetries = options.maxRetries ?? 2;
7186
+ this.retryDelayMs = options.retryDelayMs ?? 1e3;
7187
+ this.sdkAdapter = new GrokSdkAdapter({
7188
+ model: this.model,
7189
+ apiKey: options.apiKey,
7190
+ baseUrl: options.baseUrl,
7191
+ timeout: options.timeout
7192
+ });
7193
+ logger.debug("[Grok SDK-Only] Adapter created", {
7194
+ model: this.model,
7195
+ maxRetries: this.maxRetries
7196
+ });
7197
+ }
7198
+ /**
7199
+ * Check if SDK is available
7200
+ */
7201
+ async isAvailable() {
7202
+ return this.sdkAdapter.isAvailable();
7203
+ }
7204
+ /**
7205
+ * Initialize the adapter
7206
+ */
7207
+ async initialize() {
7208
+ if (this.initialized) {
7209
+ return;
7210
+ }
7211
+ const available = await this.sdkAdapter.isAvailable();
7212
+ if (!available) {
7213
+ throw new Error("Grok SDK not available - check API key and openai package");
7214
+ }
7215
+ await this.sdkAdapter.initialize();
7216
+ this.initialized = true;
7217
+ logger.debug("[Grok SDK-Only] Initialized", { model: this.model });
7218
+ }
7219
+ /**
7220
+ * Execute a request using Grok SDK
7221
+ *
7222
+ * Retries transient errors up to maxRetries times with exponential backoff.
7223
+ * Does NOT fall back to CLI - throws on persistent failure.
7224
+ */
7225
+ async execute(request) {
7226
+ if (!this.initialized) {
7227
+ await this.initialize();
7228
+ }
7229
+ const startTime = Date.now();
7230
+ let lastError;
7231
+ for (let attempt = 0; attempt <= this.maxRetries; attempt++) {
7232
+ try {
7233
+ const response = await this.sdkAdapter.execute(request);
7234
+ logger.debug("[Grok SDK-Only] Execution succeeded", {
7235
+ model: this.model,
7236
+ attempt: attempt + 1,
7237
+ latencyMs: response.latencyMs
7238
+ });
7239
+ return response;
7240
+ } catch (error) {
7241
+ lastError = error;
7242
+ logger.warn("[Grok SDK-Only] Execution failed", {
7243
+ model: this.model,
7244
+ attempt: attempt + 1,
7245
+ maxRetries: this.maxRetries,
7246
+ error: lastError.message
7247
+ });
7248
+ if (attempt < this.maxRetries && this.isRetryableError(lastError)) {
7249
+ const delay = this.retryDelayMs * Math.pow(2, attempt);
7250
+ logger.debug("[Grok SDK-Only] Retrying after delay", {
7251
+ attempt: attempt + 1,
7252
+ delayMs: delay
7253
+ });
7254
+ await this.sleep(delay);
7255
+ continue;
7256
+ }
7257
+ break;
7258
+ }
7259
+ }
7260
+ const totalTime = Date.now() - startTime;
7261
+ logger.error("[Grok SDK-Only] All retries exhausted", {
7262
+ model: this.model,
7263
+ totalAttempts: this.maxRetries + 1,
7264
+ totalTimeMs: totalTime,
7265
+ lastError: lastError?.message
7266
+ });
7267
+ throw new Error(
7268
+ `Grok SDK execution failed after ${this.maxRetries + 1} attempts: ${lastError?.message || "Unknown error"}`
7269
+ );
7270
+ }
7271
+ /**
7272
+ * Check if error is retryable
7273
+ */
7274
+ isRetryableError(error) {
7275
+ const message = error.message.toLowerCase();
7276
+ if (message.includes("rate limit") || message.includes("429")) {
7277
+ return true;
7278
+ }
7279
+ if (message.includes("500") || message.includes("502") || message.includes("503") || message.includes("504")) {
7280
+ return true;
7281
+ }
7282
+ if (message.includes("timeout") || message.includes("etimedout")) {
7283
+ return true;
7284
+ }
7285
+ if (message.includes("econnreset") || message.includes("econnrefused")) {
7286
+ return true;
7287
+ }
7288
+ return false;
7289
+ }
7290
+ /**
7291
+ * Sleep utility
7292
+ */
7293
+ sleep(ms) {
7294
+ return new Promise((resolve5) => setTimeout(resolve5, ms));
7295
+ }
7296
+ /**
7297
+ * Get the configured model
7298
+ */
7299
+ getModel() {
7300
+ return this.model;
7301
+ }
7302
+ /**
7303
+ * Clean up resources
7304
+ */
7305
+ async destroy() {
7306
+ await this.sdkAdapter.destroy();
7307
+ this.initialized = false;
7308
+ logger.debug("[Grok SDK-Only] Adapter destroyed");
7309
+ }
7310
+ };
7311
+ }
7312
+ });
7313
+
7314
+ // src/integrations/ax-grok/mcp-client-mode.ts
7315
+ var init_mcp_client_mode2 = __esm({
7316
+ "src/integrations/ax-grok/mcp-client-mode.ts"() {
7317
+ init_esm_shims();
7318
+ init_logger();
7319
+ init_sdk_adapter3();
7320
+ }
7321
+ });
7322
+
7323
+ // src/integrations/ax-grok/index.ts
7324
+ var init_ax_grok = __esm({
7325
+ "src/integrations/ax-grok/index.ts"() {
7326
+ init_esm_shims();
7327
+ init_hybrid_adapter3();
7328
+ init_sdk_adapter3();
7329
+ init_cli_wrapper3();
7330
+ init_sdk_only_adapter2();
7331
+ init_mcp_client_mode2();
7332
+ init_types3();
7333
+ }
7334
+ });
7335
+
7336
+ // src/providers/grok-provider.ts
7337
+ var grok_provider_exports = {};
7338
+ __export(grok_provider_exports, {
7339
+ GrokProvider: () => GrokProvider,
7340
+ default: () => GrokProvider
7341
+ });
7342
+ var MODEL_MAPPING2, GrokProvider;
7343
+ var init_grok_provider = __esm({
7344
+ "src/providers/grok-provider.ts"() {
7345
+ init_esm_shims();
7346
+ init_base_provider();
7347
+ init_logger();
7348
+ init_ax_grok();
7349
+ MODEL_MAPPING2 = {
7350
+ "grok-beta": "grok-3"
7351
+ };
7352
+ GrokProvider = class _GrokProvider extends BaseProvider {
7353
+ /** Selected model */
7354
+ model;
7355
+ /** SDK-only adapter for direct execution (v13.0.0) */
7356
+ sdkOnlyAdapter = null;
7357
+ /** Legacy hybrid adapter for 'auto' mode (backwards compatibility) */
7358
+ hybridAdapter = null;
7359
+ /** Provider configuration */
7360
+ grokConfig;
7361
+ /** Supported models */
7362
+ static SUPPORTED_MODELS = [
7363
+ "grok-3",
7364
+ "grok-3-mini",
7365
+ "grok-2-vision",
7366
+ "grok-2",
7367
+ // Legacy alias
7368
+ "grok-beta"
7369
+ ];
7370
+ constructor(config) {
7371
+ super({
7372
+ ...config,
7373
+ command: "ax-grok"
7374
+ });
7375
+ this.grokConfig = config;
7376
+ const requestedModel = config.model || "grok-3";
7377
+ if (!_GrokProvider.SUPPORTED_MODELS.includes(requestedModel)) {
7378
+ logger.warn(`[Grok] Unknown model: ${requestedModel}. Using grok-3.`);
7379
+ this.model = "grok-3";
7380
+ } else {
7381
+ this.model = requestedModel;
7382
+ }
7383
+ logger.debug("[Grok Provider] Initialized", {
7384
+ model: this.model,
7385
+ mode: config.mode || "auto"
7386
+ });
7387
+ }
7388
+ /**
7389
+ * Get the normalized model name
7390
+ */
7391
+ getNormalizedModel() {
7392
+ return MODEL_MAPPING2[this.model] || this.model;
7393
+ }
7394
+ /**
7395
+ * Get or create SDK-only adapter (v13.0.0 default)
7396
+ */
7397
+ getSdkOnlyAdapter() {
7398
+ if (!this.sdkOnlyAdapter) {
7399
+ this.sdkOnlyAdapter = new GrokSdkOnlyAdapter({
7400
+ model: this.model,
7401
+ apiKey: this.grokConfig.apiKey,
7402
+ baseUrl: this.grokConfig.baseUrl,
7403
+ timeout: this.grokConfig.timeout
7404
+ });
7405
+ }
7406
+ return this.sdkOnlyAdapter;
7407
+ }
7408
+ /**
7409
+ * Get or create hybrid adapter (legacy, for 'auto' mode only)
7410
+ */
7411
+ getHybridAdapter() {
7412
+ if (!this.hybridAdapter) {
7413
+ const options = {
7414
+ mode: this.grokConfig.mode || "auto",
7415
+ model: this.model,
7416
+ apiKey: this.grokConfig.apiKey,
7417
+ baseUrl: this.grokConfig.baseUrl,
7418
+ command: "ax-grok",
7419
+ timeout: this.grokConfig.timeout
7420
+ };
7421
+ this.hybridAdapter = new GrokHybridAdapter(options);
7422
+ }
7423
+ return this.hybridAdapter;
7424
+ }
7425
+ /**
7426
+ * Execute a task using Grok
7427
+ *
7428
+ * Execution flow (v13.0.0):
7429
+ * 1. Mock mode → return mock response
7430
+ * 2. mode='sdk' (default) → use SDK-only adapter (NO CLI fallback)
7431
+ * 3. mode='auto' (legacy) → use hybrid adapter (SDK with CLI fallback)
7432
+ * 4. mode='cli' → use CLI via BaseProvider (deprecated for Grok)
7433
+ */
7434
+ async execute(request) {
7435
+ if (process.env.AX_MOCK_PROVIDERS === "true") {
7436
+ return this.createMockResponse(request.prompt);
7437
+ }
7438
+ const effectiveMode = this.grokConfig.mode || "sdk";
7439
+ if (effectiveMode === "cli") {
7440
+ logger.warn("[Grok Provider] CLI mode is deprecated for Grok. Consider using SDK mode.", {
7441
+ model: this.model
7442
+ });
7443
+ return super.execute(request);
7444
+ }
7445
+ if (effectiveMode === "auto") {
7446
+ logger.debug("[Grok Provider] Executing via hybrid adapter (legacy auto mode)", {
7447
+ promptLength: request.prompt.length,
7448
+ model: this.model
7449
+ });
7450
+ const adapter2 = this.getHybridAdapter();
7451
+ return adapter2.execute(request);
7452
+ }
7453
+ logger.debug("[Grok Provider] Executing via SDK-only adapter", {
7454
+ promptLength: request.prompt.length,
7455
+ model: this.model
7456
+ });
7457
+ const adapter = this.getSdkOnlyAdapter();
7458
+ return adapter.execute(request);
7459
+ }
7460
+ /**
7461
+ * Get CLI command
7462
+ */
7463
+ getCLICommand() {
7464
+ const adapter = this.hybridAdapter;
7465
+ if (adapter) {
7466
+ const activeMode = adapter.getActiveMode();
7467
+ if (activeMode === "sdk") {
7468
+ return "grok-sdk";
7469
+ }
7470
+ }
7471
+ return "ax-grok";
7472
+ }
7473
+ /**
7474
+ * Get CLI arguments for ax-grok headless mode
7475
+ */
7476
+ getCLIArgs() {
7477
+ const args2 = ["-p"];
7478
+ const normalizedModel = this.getNormalizedModel();
7479
+ if (normalizedModel !== "grok-3") {
7480
+ args2.push("--model", normalizedModel);
7481
+ }
7482
+ return args2;
7483
+ }
7484
+ /**
7485
+ * Create mock response for testing
7486
+ */
7487
+ createMockResponse(prompt) {
7488
+ return {
7489
+ content: this.getMockResponse(),
7490
+ model: this.getNormalizedModel(),
7491
+ tokensUsed: {
7492
+ prompt: this.estimateTokens(prompt),
7493
+ completion: 50,
7494
+ total: this.estimateTokens(prompt) + 50
7495
+ },
7496
+ latencyMs: 10,
7497
+ finishReason: "stop",
7498
+ cached: false
7499
+ };
7500
+ }
7501
+ /**
7502
+ * Estimate token count
7503
+ */
7504
+ estimateTokens(text) {
7505
+ return Math.ceil(text.length / 4);
4055
7506
  }
7507
+ /**
7508
+ * Get mock response for testing
7509
+ */
4056
7510
  getMockResponse() {
4057
- return "[Mock OpenAI/Codex Response]\n\nThis is a mock response for testing purposes.";
7511
+ return `[Mock Grok Response]
7512
+
7513
+ This is a mock response from the Grok provider (${this.getNormalizedModel()}).
7514
+ In production, this would be a response from ${this.grokConfig.mode === "sdk" ? "Grok SDK" : "ax-grok CLI"}.
7515
+
7516
+ Model: ${this.getNormalizedModel()}
7517
+ Provider: Grok (xAI)
7518
+ Mode: ${this.grokConfig.mode || "auto"}`;
4058
7519
  }
7520
+ /**
7521
+ * Get provider capabilities
7522
+ */
4059
7523
  get capabilities() {
7524
+ const model = this.getNormalizedModel();
7525
+ const isVision = model.includes("vision") || model === "grok-2-vision";
7526
+ const maxContextTokens = 131072;
7527
+ const activeMode = this.hybridAdapter?.getActiveMode();
7528
+ const integrationMode = activeMode === "sdk" ? "sdk" : "cli";
4060
7529
  return {
7530
+ ...super.capabilities,
4061
7531
  supportsStreaming: true,
4062
- supportsEmbedding: false,
4063
- supportsVision: true,
4064
- maxContextTokens: 128e3,
4065
- supportedModels: ["codex"]
7532
+ supportsVision: isVision,
7533
+ maxContextTokens,
7534
+ supportedModels: _GrokProvider.SUPPORTED_MODELS,
7535
+ integrationMode
4066
7536
  };
4067
7537
  }
7538
+ /**
7539
+ * Get the active execution mode
7540
+ */
4068
7541
  getActiveMode() {
4069
7542
  return this.hybridAdapter?.getActiveMode() || null;
4070
7543
  }
4071
- switchToCliMode() {
4072
- this.hybridAdapter?.switchToCliMode();
7544
+ /**
7545
+ * Reset circuit breakers
7546
+ */
7547
+ resetCircuitBreakers() {
7548
+ this.hybridAdapter?.resetCircuitBreakers();
4073
7549
  }
7550
+ /**
7551
+ * Clean up resources
7552
+ */
4074
7553
  async destroy() {
4075
- this.isDestroyed = true;
7554
+ if (this.sdkOnlyAdapter) {
7555
+ await this.sdkOnlyAdapter.destroy();
7556
+ this.sdkOnlyAdapter = null;
7557
+ }
4076
7558
  if (this.hybridAdapter) {
4077
7559
  await this.hybridAdapter.destroy();
4078
7560
  this.hybridAdapter = null;
4079
7561
  }
4080
7562
  }
7563
+ /**
7564
+ * Get the list of supported models
7565
+ */
7566
+ static getSupportedModels() {
7567
+ return [..._GrokProvider.SUPPORTED_MODELS];
7568
+ }
4081
7569
  };
4082
7570
  }
4083
7571
  });
4084
7572
 
4085
- // src/providers/openai-provider-factory.ts
4086
- var openai_provider_factory_exports = {};
4087
- __export(openai_provider_factory_exports, {
4088
- createOpenAIProviderAsync: () => createOpenAIProviderAsync,
4089
- createOpenAIProviderSync: () => createOpenAIProviderSync,
4090
- getIntegrationMode: () => getIntegrationMode,
4091
- isCLIModeAvailable: () => isCLIModeAvailable,
4092
- isSDKModeAvailable: () => isSDKModeAvailable
4093
- });
4094
- function createOpenAIProviderSync(config, integrationMode) {
4095
- logger.debug("Created OpenAI CLI provider (v8.3.0: CLI-only)", {
4096
- provider: config.name,
4097
- mode: "cli"
4098
- });
4099
- return new OpenAIProvider(config);
4100
- }
4101
- async function createOpenAIProviderAsync(config, integrationMode, interactive = false) {
4102
- logger.info("Creating OpenAI CLI provider (v8.3.0: CLI-only)", {
4103
- provider: config.name,
4104
- mode: "cli"
4105
- });
4106
- return new OpenAIProvider(config);
4107
- }
4108
- function getIntegrationMode(config) {
4109
- return config.integration;
4110
- }
4111
- function isSDKModeAvailable() {
4112
- const hasAPIKey = !!process.env.OPENAI_API_KEY;
4113
- let hasSDK = false;
4114
- try {
4115
- if (typeof import.meta.resolve === "function") {
4116
- import.meta.resolve("openai");
4117
- hasSDK = true;
4118
- } else {
4119
- hasSDK = true;
4120
- }
4121
- } catch {
4122
- hasSDK = false;
4123
- }
4124
- return hasAPIKey && hasSDK;
4125
- }
4126
- async function isCLIModeAvailable() {
4127
- try {
4128
- const { execSync } = await import('child_process');
4129
- execSync("codex --version", {
4130
- encoding: "utf-8",
4131
- stdio: ["pipe", "pipe", "pipe"],
4132
- timeout: 3e3
4133
- });
4134
- return true;
4135
- } catch {
4136
- return false;
4137
- }
4138
- }
4139
- var init_openai_provider_factory = __esm({
4140
- "src/providers/openai-provider-factory.ts"() {
4141
- init_esm_shims();
4142
- init_openai_provider();
4143
- init_logger();
4144
- }
4145
- });
4146
-
4147
7573
  // src/mcp/index.ts
4148
7574
  init_esm_shims();
4149
7575
 
4150
7576
  // src/mcp/server.ts
4151
7577
  init_esm_shims();
7578
+ init_validation_limits();
4152
7579
 
4153
7580
  // src/shared/helpers/version.ts
4154
7581
  init_esm_shims();
4155
- var __dirname$1 = dirname(fileURLToPath(import.meta.url));
7582
+ var __dirname2 = dirname(fileURLToPath(import.meta.url));
4156
7583
  function getVersion() {
4157
7584
  try {
4158
7585
  const possiblePaths = [
4159
- join(__dirname$1, "../../../package.json"),
7586
+ join(__dirname2, "../../../package.json"),
4160
7587
  // From src/shared/helpers
4161
- join(__dirname$1, "../../package.json"),
7588
+ join(__dirname2, "../../package.json"),
4162
7589
  // From dist/mcp (bundled MCP entry)
4163
- join(__dirname$1, "../package.json")
7590
+ join(__dirname2, "../package.json")
4164
7591
  // From dist
4165
7592
  ];
4166
7593
  for (const pkgPath of possiblePaths) {
@@ -4182,8 +7609,8 @@ function getVersion() {
4182
7609
 
4183
7610
  // src/mcp/types.ts
4184
7611
  init_esm_shims();
4185
- var MCP_PROTOCOL_VERSION = "2024-12-05";
4186
- var MCP_SUPPORTED_VERSIONS = ["2024-12-05", "2024-11-05"];
7612
+ var MCP_PROTOCOL_VERSION = "2025-11-25";
7613
+ var MCP_SUPPORTED_VERSIONS = ["2025-11-25", "2024-12-05", "2024-11-05"];
4187
7614
 
4188
7615
  // src/mcp/server.ts
4189
7616
  init_logger();
@@ -4619,119 +8046,8 @@ function deepMerge(defaults, user) {
4619
8046
  return result;
4620
8047
  }
4621
8048
 
4622
- // src/core/validation-limits.ts
4623
- init_esm_shims();
4624
- var VALIDATION_LIMITS = {
4625
- // Resource limits (prevent DoS)
4626
- MAX_ENTRIES: 1e6,
4627
- // 1 million entries (memory, cache)
4628
- MAX_TIMEOUT: 36e5,
4629
- // 1 hour (execution, delegation)
4630
- MAX_FILE_SIZE: 104857600,
4631
- // 100 MB (workspace, abilities)
4632
- MAX_CACHE_SIZE: 524288e3,
4633
- // 500 MB (cache storage)
4634
- MAX_SESSIONS: 1e4,
4635
- // 10k concurrent sessions
4636
- // Performance limits (prevent resource exhaustion)
4637
- MAX_CONCURRENT_AGENTS: 100,
4638
- // Maximum concurrent agents
4639
- MAX_CPU_PERCENT: 80,
4640
- // Maximum CPU usage percent
4641
- MAX_MEMORY_MB: 2048,
4642
- // Maximum memory usage in MB
4643
- // Config validation limits
4644
- MAX_CONFIG_FILE_SIZE: 1048576,
4645
- // 1MB max config file size
4646
- MAX_NAME_LENGTH: 50,
4647
- // Max name length for agents/providers
4648
- MAX_COMMAND_LENGTH: 100,
4649
- // Max command length
4650
- MAX_ARRAY_LENGTH: 1e4,
4651
- // Max array elements in config
4652
- // Path and file limits
4653
- MIN_FILE_SIZE: 1,
4654
- // Minimum file size in bytes
4655
- MIN_TIMEOUT: 1e3,
4656
- // Minimum timeout in ms (1 second)
4657
- MIN_INTERVAL: 100,
4658
- // Minimum interval in ms
4659
- MIN_BACKOFF_FACTOR: 1,
4660
- // Minimum backoff multiplier
4661
- MAX_BACKOFF_FACTOR: 5,
4662
- // Maximum backoff multiplier
4663
- MAX_TTL: 864e5,
4664
- // Maximum TTL in ms (24 hours)
4665
- MIN_BYTES: 1,
4666
- // Minimum bytes for file sizes
4667
- // Network limits
4668
- MIN_PORT: 1024,
4669
- // Minimum port number
4670
- MAX_PORT: 65535
4671
- // Maximum port number
4672
- };
4673
- function isValidRelativePath(path7) {
4674
- if (!path7 || typeof path7 !== "string") {
4675
- return false;
4676
- }
4677
- const normalizedPath = path7.replace(/\\/g, "/");
4678
- if (normalizedPath.startsWith("/")) {
4679
- return false;
4680
- }
4681
- if (normalizedPath.includes("..")) {
4682
- return false;
4683
- }
4684
- if (/^[a-zA-Z]:/.test(normalizedPath)) {
4685
- return false;
4686
- }
4687
- if (normalizedPath.startsWith("//")) {
4688
- return false;
4689
- }
4690
- return true;
4691
- }
4692
- function isValidCommand(command) {
4693
- if (!command || typeof command !== "string") {
4694
- return false;
4695
- }
4696
- if (command.length > VALIDATION_LIMITS.MAX_COMMAND_LENGTH) {
4697
- return false;
4698
- }
4699
- if (!/^[a-z0-9_-]+$/i.test(command)) {
4700
- return false;
4701
- }
4702
- return true;
4703
- }
4704
- function isValidName(name) {
4705
- if (!name || typeof name !== "string") {
4706
- return false;
4707
- }
4708
- if (name.length > VALIDATION_LIMITS.MAX_NAME_LENGTH) {
4709
- return false;
4710
- }
4711
- if (!/^[a-z0-9][a-z0-9-_]*$/i.test(name)) {
4712
- return false;
4713
- }
4714
- return true;
4715
- }
4716
- function isValidExtension(ext) {
4717
- if (!ext || typeof ext !== "string") {
4718
- return false;
4719
- }
4720
- const normalized = ext.startsWith(".") ? ext : `.${ext}`;
4721
- if (normalized.length > 10 || normalized.length < 2) {
4722
- return false;
4723
- }
4724
- if (!/^\.[a-z0-9]+$/i.test(normalized)) {
4725
- return false;
4726
- }
4727
- return true;
4728
- }
4729
- function isPositiveInteger(value) {
4730
- return typeof value === "number" && Number.isInteger(value) && value > 0;
4731
- }
4732
- function isNonNegativeInteger(value) {
4733
- return typeof value === "number" && Number.isInteger(value) && value >= 0;
4734
- }
8049
+ // src/core/config/loader.ts
8050
+ init_validation_limits();
4735
8051
 
4736
8052
  // src/core/cache/cache.ts
4737
8053
  init_esm_shims();
@@ -4807,7 +8123,7 @@ var TTLCache = class {
4807
8123
  * @param value Value to cache
4808
8124
  * @param customTTL Optional custom TTL for this entry (ms)
4809
8125
  */
4810
- set(key, value, customTTL) {
8126
+ set(key, value, _customTTL) {
4811
8127
  const size = this.estimateSize(value);
4812
8128
  if (this.config.maxSize > 0 && size > this.config.maxSize) {
4813
8129
  logger.warn("Entry too large for cache", {
@@ -5064,11 +8380,12 @@ function calculateMaxConcurrentAgents(staticLimit) {
5064
8380
  init_esm_shims();
5065
8381
  var PRECOMPILED_CONFIG = {
5066
8382
  "providers": {
5067
- "claude-code": {
8383
+ "gemini-cli": {
5068
8384
  "enabled": true,
5069
- "priority": 3,
8385
+ "priority": 1,
5070
8386
  "timeout": 27e5,
5071
- "command": "claude",
8387
+ "command": "gemini",
8388
+ "description": "#1 Frontend/Design, multimodal, free tier, WebDev Arena leader",
5072
8389
  "healthCheck": {
5073
8390
  "enabled": true,
5074
8391
  "interval": 3e5,
@@ -5090,15 +8407,16 @@ var PRECOMPILED_CONFIG = {
5090
8407
  },
5091
8408
  "limitTracking": {
5092
8409
  "enabled": true,
5093
- "window": "weekly",
8410
+ "window": "daily",
5094
8411
  "resetHourUtc": 0
5095
8412
  }
5096
8413
  },
5097
- "gemini-cli": {
8414
+ "openai": {
5098
8415
  "enabled": true,
5099
- "priority": 2,
8416
+ "priority": 3,
5100
8417
  "timeout": 27e5,
5101
- "command": "gemini",
8418
+ "command": "codex",
8419
+ "description": "Best reasoning (o3), strategy, 75% accuracy, 192k context",
5102
8420
  "healthCheck": {
5103
8421
  "enabled": true,
5104
8422
  "interval": 3e5,
@@ -5124,11 +8442,12 @@ var PRECOMPILED_CONFIG = {
5124
8442
  "resetHourUtc": 0
5125
8443
  }
5126
8444
  },
5127
- "openai": {
8445
+ "claude-code": {
5128
8446
  "enabled": true,
5129
- "priority": 1,
8447
+ "priority": 2,
5130
8448
  "timeout": 27e5,
5131
- "command": "codex",
8449
+ "command": "claude",
8450
+ "description": "#1 Coding model, agentic workflows, security, 0% edit error rate",
5132
8451
  "healthCheck": {
5133
8452
  "enabled": true,
5134
8453
  "interval": 3e5,
@@ -5148,6 +8467,50 @@ var PRECOMPILED_CONFIG = {
5148
8467
  "forceKillDelay": 1e3,
5149
8468
  "cacheEnabled": true
5150
8469
  },
8470
+ "limitTracking": {
8471
+ "enabled": true,
8472
+ "window": "weekly",
8473
+ "resetHourUtc": 0
8474
+ }
8475
+ },
8476
+ "glm": {
8477
+ "enabled": true,
8478
+ "priority": 4,
8479
+ "timeout": 27e5,
8480
+ "type": "sdk",
8481
+ "description": "Near Claude coding (48.6%), low cost $3/mo, 200k context, agentic",
8482
+ "healthCheck": {
8483
+ "enabled": true,
8484
+ "interval": 3e5,
8485
+ "timeout": 5e3
8486
+ },
8487
+ "circuitBreaker": {
8488
+ "enabled": true,
8489
+ "failureThreshold": 3,
8490
+ "recoveryTimeout": 6e4
8491
+ },
8492
+ "limitTracking": {
8493
+ "enabled": true,
8494
+ "window": "daily",
8495
+ "resetHourUtc": 0
8496
+ }
8497
+ },
8498
+ "grok": {
8499
+ "enabled": true,
8500
+ "priority": 5,
8501
+ "timeout": 27e5,
8502
+ "type": "sdk",
8503
+ "description": "Fastest (67ms), reasoning (93% AIME), 1M context, DeepSearch",
8504
+ "healthCheck": {
8505
+ "enabled": true,
8506
+ "interval": 3e5,
8507
+ "timeout": 5e3
8508
+ },
8509
+ "circuitBreaker": {
8510
+ "enabled": true,
8511
+ "failureThreshold": 3,
8512
+ "recoveryTimeout": 6e4
8513
+ },
5151
8514
  "limitTracking": {
5152
8515
  "enabled": true,
5153
8516
  "window": "daily",
@@ -5364,11 +8727,12 @@ var PRECOMPILED_CONFIG = {
5364
8727
  "enableFreeTierPrioritization": true,
5365
8728
  "enableWorkloadAwareRouting": true
5366
8729
  },
5367
- "version": "12.3.1"
8730
+ "version": "12.4.1"
5368
8731
  };
5369
8732
 
5370
8733
  // src/core/config/schemas.ts
5371
8734
  init_esm_shims();
8735
+ init_validation_limits();
5372
8736
  z.enum([
5373
8737
  "claude",
5374
8738
  "claude-code",
@@ -5431,17 +8795,35 @@ var limitTrackingConfigSchema = z.object({
5431
8795
  resetHourUtc: z.number().int().min(0).max(23).default(0),
5432
8796
  customResetMs: positiveIntSchema.optional()
5433
8797
  }).describe("Provider limit tracking configuration");
8798
+ var providerTypeSchema = z.enum(["cli", "sdk", "hybrid"]).default("cli");
5434
8799
  var providerConfigSchema = z.object({
5435
8800
  enabled: z.boolean().default(true),
5436
8801
  priority: positiveIntSchema,
5437
8802
  timeout: timeoutSchema,
5438
- command: commandSchema,
8803
+ type: providerTypeSchema.optional(),
8804
+ command: commandSchema.optional(),
8805
+ // Optional for SDK providers (glm, grok)
8806
+ description: z.string().optional(),
8807
+ // Provider description
8808
+ model: z.string().optional(),
8809
+ // Model name override
5439
8810
  healthCheck: healthCheckConfigSchema.optional(),
5440
8811
  circuitBreaker: circuitBreakerConfigSchema.optional(),
5441
8812
  processManagement: processManagementConfigSchema.optional(),
5442
8813
  versionDetection: versionDetectionConfigSchema.optional(),
5443
8814
  limitTracking: limitTrackingConfigSchema.optional()
5444
- }).describe("Provider configuration");
8815
+ }).refine(
8816
+ (data) => {
8817
+ if (data.type === "sdk") {
8818
+ return true;
8819
+ }
8820
+ return data.command !== void 0;
8821
+ },
8822
+ {
8823
+ message: "CLI and hybrid providers require a command field",
8824
+ path: ["command"]
8825
+ }
8826
+ ).describe("Provider configuration");
5445
8827
  var providersConfigSchema = z.record(
5446
8828
  safeNameSchema,
5447
8829
  providerConfigSchema
@@ -5827,9 +9209,15 @@ function validateConfig(config) {
5827
9209
  if (!isValidName(name)) {
5828
9210
  errors.push(`Provider "${name}": name invalid (use alphanumeric, dash, underscore only, max 50 chars)`);
5829
9211
  }
5830
- if (!provider.command) {
5831
- errors.push(`Provider ${name}: command is required`);
5832
- } else if (!isValidCommand(provider.command)) {
9212
+ const providerType = provider.type;
9213
+ const isSDKProvider = providerType === "sdk";
9214
+ if (!isSDKProvider) {
9215
+ if (!provider.command) {
9216
+ errors.push(`Provider ${name}: command is required for CLI/hybrid providers`);
9217
+ } else if (!isValidCommand(provider.command)) {
9218
+ errors.push(`Provider ${name}: command invalid (alphanumeric, dash, underscore only, max 100 chars, no shell metacharacters)`);
9219
+ }
9220
+ } else if (provider.command && !isValidCommand(provider.command)) {
5833
9221
  errors.push(`Provider ${name}: command invalid (alphanumeric, dash, underscore only, max 100 chars, no shell metacharacters)`);
5834
9222
  }
5835
9223
  if (!isPositiveInteger(provider.priority)) {
@@ -6205,6 +9593,7 @@ function validateConfig(config) {
6205
9593
  init_esm_shims();
6206
9594
  init_logger();
6207
9595
  init_errors();
9596
+ init_validation_limits();
6208
9597
 
6209
9598
  // src/core/provider-limit-manager.ts
6210
9599
  init_esm_shims();
@@ -6415,6 +9804,9 @@ var PathResolver = class {
6415
9804
  }
6416
9805
  }
6417
9806
  };
9807
+
9808
+ // src/core/provider-limit-manager.ts
9809
+ init_validation_limits();
6418
9810
  var ProviderLimitManager = class _ProviderLimitManager extends EventEmitter {
6419
9811
  static instance = null;
6420
9812
  stateFilePath;
@@ -6440,7 +9832,7 @@ var ProviderLimitManager = class _ProviderLimitManager extends EventEmitter {
6440
9832
  /**
6441
9833
  * Get singleton instance
6442
9834
  */
6443
- static getInstance(stateDirectory = ".automatosx/state") {
9835
+ static getInstance(stateDirectory = AX_PATHS.STATE) {
6444
9836
  if (!_ProviderLimitManager.instance) {
6445
9837
  _ProviderLimitManager.instance = new _ProviderLimitManager(stateDirectory);
6446
9838
  }
@@ -6528,7 +9920,9 @@ var ProviderLimitManager = class _ProviderLimitManager extends EventEmitter {
6528
9920
  return { isLimited: false };
6529
9921
  }
6530
9922
  if (now >= state.resetAtMs) {
6531
- void this.clearLimit(providerName, "expired");
9923
+ void this.clearLimit(providerName, "expired").catch((err) => {
9924
+ logger.warn("Failed to clear expired limit", { provider: providerName, error: err.message });
9925
+ });
6532
9926
  return { isLimited: false };
6533
9927
  }
6534
9928
  const remainingMs = state.resetAtMs - now;
@@ -6617,9 +10011,10 @@ var ProviderLimitManager = class _ProviderLimitManager extends EventEmitter {
6617
10011
  getManualOverride() {
6618
10012
  if (this.manualOverride && this.manualOverride.expiresAtMs) {
6619
10013
  if (Date.now() >= this.manualOverride.expiresAtMs) {
6620
- this.manualOverride;
6621
10014
  this.manualOverride = void 0;
6622
- void this.clearManualOverride();
10015
+ void this.clearManualOverride().catch((err) => {
10016
+ logger.warn("Failed to clear expired manual override", { error: err.message });
10017
+ });
6623
10018
  return void 0;
6624
10019
  }
6625
10020
  }
@@ -6756,10 +10151,10 @@ var ProviderLimitManager = class _ProviderLimitManager extends EventEmitter {
6756
10151
  async function getProviderLimitManager(stateDirectory) {
6757
10152
  if (!stateDirectory) {
6758
10153
  if (process.env.NODE_ENV === "test" || process.env.VITEST) {
6759
- stateDirectory = ".automatosx/state";
10154
+ stateDirectory = AX_PATHS.STATE;
6760
10155
  } else {
6761
10156
  const projectRoot = await detectProjectRoot();
6762
- stateDirectory = path4.join(projectRoot, ".automatosx", "state");
10157
+ stateDirectory = path4.join(projectRoot, AX_PATHS.STATE);
6763
10158
  }
6764
10159
  }
6765
10160
  return ProviderLimitManager.getInstance(stateDirectory);
@@ -7742,13 +11137,12 @@ function getRoutingStrategyManager(config) {
7742
11137
  // src/core/router/circuit-breaker.ts
7743
11138
  init_esm_shims();
7744
11139
  init_logger();
11140
+ init_validation_limits();
7745
11141
  var DEFAULT_CONFIG2 = {
7746
11142
  failureThreshold: 3,
7747
- cooldownMs: 6e4,
7748
- // 1 minute
11143
+ cooldownMs: TIMEOUTS.CIRCUIT_BREAKER_RECOVERY,
7749
11144
  successThreshold: 2,
7750
- failureWindowMs: 3e5
7751
- // v11.1.0: 5 minutes - failures outside this window don't count
11145
+ failureWindowMs: TIMEOUTS.CIRCUIT_BREAKER_WINDOW
7752
11146
  };
7753
11147
  var CircuitBreaker = class {
7754
11148
  config;
@@ -7905,6 +11299,7 @@ var CircuitBreaker = class {
7905
11299
  // src/core/router/trace-logger.ts
7906
11300
  init_esm_shims();
7907
11301
  init_logger();
11302
+ init_validation_limits();
7908
11303
  var RouterTraceLogger = class {
7909
11304
  traceFile;
7910
11305
  stream;
@@ -7916,7 +11311,7 @@ var RouterTraceLogger = class {
7916
11311
  sigintHandler = () => this.close();
7917
11312
  sigtermHandler = () => this.close();
7918
11313
  constructor(options) {
7919
- this.traceFile = join(options.workspacePath, ".automatosx/logs/router.trace.jsonl");
11314
+ this.traceFile = join(options.workspacePath, AX_PATHS.LOGS, "router.trace.jsonl");
7920
11315
  this.enabled = options.enabled ?? true;
7921
11316
  this.autoFlush = options.autoFlush ?? true;
7922
11317
  if (this.enabled) {
@@ -8303,13 +11698,12 @@ var Router = class {
8303
11698
  return a.priority - b.priority;
8304
11699
  });
8305
11700
  this.fallbackEnabled = config.fallbackEnabled;
8306
- this.providerCooldownMs = config.providerCooldownMs ?? 3e4;
11701
+ this.providerCooldownMs = config.providerCooldownMs ?? TIMEOUTS.PROVIDER_COOLDOWN;
8307
11702
  this.cache = config.cache;
8308
11703
  this.circuitBreaker = new CircuitBreaker({
8309
11704
  failureThreshold: config.circuitBreakerThreshold ?? 3,
8310
- cooldownMs: config.providerCooldownMs ?? 3e4,
8311
- failureWindowMs: config.circuitBreakerWindowMs ?? 3e5
8312
- // 5 min default
11705
+ cooldownMs: config.providerCooldownMs ?? TIMEOUTS.PROVIDER_COOLDOWN,
11706
+ failureWindowMs: config.circuitBreakerWindowMs ?? TIMEOUTS.CIRCUIT_BREAKER_WINDOW
8313
11707
  });
8314
11708
  void (async () => {
8315
11709
  try {
@@ -10345,9 +13739,9 @@ var MemoryManager = class _MemoryManager {
10345
13739
  throw new MemoryError("Memory manager not initialized", "DATABASE_ERROR");
10346
13740
  }
10347
13741
  try {
10348
- const { mkdir: mkdir5 } = await import('fs/promises');
13742
+ const { mkdir: mkdir4 } = await import('fs/promises');
10349
13743
  const destDir = dirname3(destPath);
10350
- await mkdir5(destDir, { recursive: true });
13744
+ await mkdir4(destDir, { recursive: true });
10351
13745
  await this.db.backup(destPath);
10352
13746
  logger.info("Database backup created", { destPath: normalizePath(destPath) });
10353
13747
  } catch (error) {
@@ -10795,7 +14189,7 @@ var LazyMemoryManager = class {
10795
14189
  /**
10796
14190
  * Backup database to destination path (lazy initialization on first call)
10797
14191
  */
10798
- async backup(destPath, onProgress) {
14192
+ async backup(destPath, _onProgress) {
10799
14193
  const manager = await this.ensureInitialized();
10800
14194
  return manager.backup(destPath);
10801
14195
  }
@@ -11689,12 +15083,13 @@ var SessionManager = class _SessionManager {
11689
15083
  */
11690
15084
  async getStats() {
11691
15085
  const sessions = Array.from(this.activeSessions.values());
11692
- return {
11693
- total: sessions.length,
11694
- active: sessions.filter((s) => s.status === "active").length,
11695
- completed: sessions.filter((s) => s.status === "completed").length,
11696
- failed: sessions.filter((s) => s.status === "failed").length
11697
- };
15086
+ let active = 0, completed = 0, failed = 0;
15087
+ for (const s of sessions) {
15088
+ if (s.status === "active") active++;
15089
+ else if (s.status === "completed") completed++;
15090
+ else if (s.status === "failed") failed++;
15091
+ }
15092
+ return { total: sessions.length, active, completed, failed };
11698
15093
  }
11699
15094
  /**
11700
15095
  * Load sessions from persistence file
@@ -12975,11 +16370,13 @@ var ContextManager = class {
12975
16370
  * Cleanup context
12976
16371
  *
12977
16372
  * v5.2: No cleanup needed - agent workspaces no longer created
16373
+ * Note: Returns Promise for interface compatibility
12978
16374
  */
12979
- async cleanup(context) {
16375
+ cleanup(context) {
12980
16376
  logger.debug("Context cleanup (no-op in v5.2)", {
12981
16377
  agent: context.agent.name
12982
16378
  });
16379
+ return Promise.resolve();
12983
16380
  }
12984
16381
  };
12985
16382
 
@@ -13003,6 +16400,7 @@ var AgentNotFoundError = class extends Error {
13003
16400
 
13004
16401
  // src/agents/profile-loader.ts
13005
16402
  init_logger();
16403
+ init_validation_limits();
13006
16404
 
13007
16405
  // src/agents/agent-schemas.ts
13008
16406
  init_esm_shims();
@@ -13403,7 +16801,7 @@ var ProfileLoader = class {
13403
16801
  const files = await readdir(this.fallbackProfilesDir);
13404
16802
  const profiles = files.filter((file) => extname$1(file) === ".yaml" || extname$1(file) === ".yml").map((file) => basename(file, extname$1(file)));
13405
16803
  profiles.forEach((p) => profileSet.add(p));
13406
- } catch (error) {
16804
+ } catch (_error) {
13407
16805
  logger.debug("Fallback profiles directory not found", {
13408
16806
  dir: this.fallbackProfilesDir
13409
16807
  });
@@ -13680,7 +17078,7 @@ var ProfileLoader = class {
13680
17078
  * Protected by mutex to prevent race conditions
13681
17079
  */
13682
17080
  async clearCache() {
13683
- await this.initMutex.runExclusive(async () => {
17081
+ await this.initMutex.runExclusive(() => {
13684
17082
  this.cache.clear();
13685
17083
  this.displayNameMap.clear();
13686
17084
  this.mapInitialized = false;
@@ -14455,7 +17853,7 @@ var DelegationParser = class _DelegationParser {
14455
17853
  await this.extractMatches(_DelegationParser.DELEGATION_PATTERNS.chineseRequest, response, fromAgent, delegations, "\u8ACB", resolvedNameCache);
14456
17854
  await this.extractMatches(_DelegationParser.DELEGATION_PATTERNS.chineseFormal, response, fromAgent, delegations, "\u59D4\u6D3E\u7D66", resolvedNameCache);
14457
17855
  delegations.sort((a, b) => a.position - b.position);
14458
- const result = delegations.map(({ position, ...rest }) => rest);
17856
+ const result = delegations.map(({ position: _position, ...rest }) => rest);
14459
17857
  logger.info(`Parsed ${delegations.length} delegation(s)`, {
14460
17858
  fromAgent,
14461
17859
  delegations: result.map((d) => ({ toAgent: d.toAgent, taskPreview: d.task.substring(0, 50) }))
@@ -15495,7 +18893,7 @@ var ParallelAgentExecutor = class {
15495
18893
  /**
15496
18894
  * Execute a batch of agents in parallel
15497
18895
  */
15498
- async executeBatchParallel(batch, graph, context, options, results, timeline, executionStartTime) {
18896
+ async executeBatchParallel(batch, graph, context, options, results, timeline, _executionStartTime) {
15499
18897
  logger.info("Executing batch in parallel", { agents: batch });
15500
18898
  const promises = batch.map(async (agentName) => {
15501
18899
  const node = graph.nodes.get(agentName);
@@ -15729,7 +19127,7 @@ var ParallelAgentExecutor = class {
15729
19127
  /**
15730
19128
  * Mark batch as cancelled
15731
19129
  */
15732
- markBatchAsCancelled(batch, graph, timeline, executionStartTime) {
19130
+ markBatchAsCancelled(batch, graph, timeline, _executionStartTime) {
15733
19131
  const now = Date.now();
15734
19132
  for (const agentName of batch) {
15735
19133
  const node = graph.nodes.get(agentName);
@@ -15869,6 +19267,9 @@ var ParallelAgentExecutor = class {
15869
19267
  };
15870
19268
 
15871
19269
  // src/agents/executor.ts
19270
+ function isErrorLike(error) {
19271
+ return typeof error === "object" && error !== null;
19272
+ }
15872
19273
  var AgentExecutor = class {
15873
19274
  sessionManager;
15874
19275
  workspaceManager;
@@ -15998,7 +19399,7 @@ Retry attempt ${attempt}/${maxAttempts}...`));
15998
19399
  }
15999
19400
  return await this.executeInternal(context, options);
16000
19401
  } catch (error) {
16001
- lastError = error;
19402
+ lastError = error instanceof Error ? error : new Error(String(error));
16002
19403
  const isRetryable = this.isRetryableError(error, retryableErrors);
16003
19404
  if (!isRetryable || attempt >= maxAttempts) {
16004
19405
  throw error;
@@ -16008,7 +19409,8 @@ Retry attempt ${attempt}/${maxAttempts}...`));
16008
19409
  maxDelay
16009
19410
  );
16010
19411
  if (verbose) {
16011
- console.log(chalk4.yellow(`Retryable error occurred: ${error.message}`));
19412
+ const errorMessage = error instanceof Error ? error.message : String(error);
19413
+ console.log(chalk4.yellow(`Retryable error occurred: ${errorMessage}`));
16012
19414
  console.log(chalk4.gray(`Waiting ${delay}ms before retry...`));
16013
19415
  }
16014
19416
  await this.sleep(delay, signal);
@@ -16023,7 +19425,7 @@ Retry attempt ${attempt}/${maxAttempts}...`));
16023
19425
  */
16024
19426
  async executeWithTimeout(context, options) {
16025
19427
  const timeout = options.timeout;
16026
- const { verbose = false } = options;
19428
+ const { verbose: _verbose = false } = options;
16027
19429
  let timeoutId = null;
16028
19430
  const controller = new AbortController();
16029
19431
  const executionOptions = {
@@ -16721,7 +20123,12 @@ ${context.task}`;
16721
20123
  */
16722
20124
  isRetryableError(error, retryableErrors) {
16723
20125
  const patterns = retryableErrors || this.defaultRetryConfig.retryableErrors;
16724
- const errorString = (error.message || error.code || "").toLowerCase();
20126
+ let errorString = "";
20127
+ if (isErrorLike(error)) {
20128
+ errorString = (error.message || error.code || "").toLowerCase();
20129
+ } else if (typeof error === "string") {
20130
+ errorString = error.toLowerCase();
20131
+ }
16725
20132
  return patterns.some(
16726
20133
  (pattern) => errorString.includes(pattern.toLowerCase())
16727
20134
  );
@@ -18149,7 +21556,7 @@ function categorizeTools(name) {
18149
21556
  if (name.includes("context")) return "context";
18150
21557
  return "execution";
18151
21558
  }
18152
- function getExecutionMode(providerName, providerConfig) {
21559
+ function getExecutionMode(providerName, _providerConfig) {
18153
21560
  if (providerName === "glm" || providerName === "grok") {
18154
21561
  return "sdk";
18155
21562
  }
@@ -18608,13 +22015,14 @@ function compressWithInfo(payload, options = {}) {
18608
22015
  init_esm_shims();
18609
22016
  init_factory();
18610
22017
  init_logger();
22018
+ init_validation_limits();
18611
22019
  var NATIVE_MODULE_ERROR_PATTERNS = [
18612
22020
  "NODE_MODULE_VERSION",
18613
22021
  "was compiled against a different Node.js version",
18614
22022
  "better_sqlite3.node"
18615
22023
  ];
18616
22024
  var DEFAULT_CONFIG3 = {
18617
- dbPath: ".automatosx/tasks/tasks.db",
22025
+ dbPath: `${AX_PATHS.TASKS}/tasks.db`,
18618
22026
  maxPayloadBytes: 1024 * 1024,
18619
22027
  // 1MB
18620
22028
  compressionEnabled: true,
@@ -18622,7 +22030,7 @@ var DEFAULT_CONFIG3 = {
18622
22030
  defaultTtlHours: 24,
18623
22031
  maxTtlHours: 168,
18624
22032
  // 7 days
18625
- busyTimeout: 5e3
22033
+ busyTimeout: DATABASE.BUSY_TIMEOUT
18626
22034
  };
18627
22035
  var SQL = {
18628
22036
  CREATE_TABLE: `
@@ -20141,7 +23549,6 @@ function createRunTaskHandler(deps) {
20141
23549
  });
20142
23550
  try {
20143
23551
  const taskEngine = getTaskEngine();
20144
- const session = deps.getSession();
20145
23552
  const options = {
20146
23553
  engineOverride: input.engine_override,
20147
23554
  timeoutMs: input.timeout_ms,
@@ -22398,7 +25805,6 @@ var CodexEventNormalizer = class extends BaseEventNormalizer {
22398
25805
  const inputTokens = event.inputTokens ?? 0;
22399
25806
  const outputTokens = event.outputTokens ?? 0;
22400
25807
  this.tokenCount = inputTokens + outputTokens;
22401
- Date.now() - this.startTime;
22402
25808
  return this.createEvent("execution.progress", {
22403
25809
  agent: "codex",
22404
25810
  progress: 100,
@@ -22783,36 +26189,61 @@ Use this tool first to understand what AutomatosX offers.`,
22783
26189
  const projectDir = process.cwd();
22784
26190
  const config = await loadConfig(projectDir);
22785
26191
  const teamManager = new TeamManager(
22786
- join(projectDir, ".automatosx", "teams")
26192
+ join(projectDir, AX_PATHS.TEAMS)
22787
26193
  );
22788
26194
  this.profileLoader = new ProfileLoader(
22789
- join(projectDir, ".automatosx", "agents"),
26195
+ join(projectDir, AX_PATHS.AGENTS),
22790
26196
  void 0,
22791
26197
  teamManager
22792
26198
  );
22793
26199
  const abilitiesManager = new AbilitiesManager(
22794
- join(projectDir, ".automatosx", "abilities")
26200
+ join(projectDir, AX_PATHS.ABILITIES)
22795
26201
  );
22796
26202
  this.memoryManager = new LazyMemoryManager({
22797
- dbPath: join(projectDir, ".automatosx", "memory", "memory.db")
26203
+ dbPath: join(projectDir, AX_PATHS.MEMORY, "memory.db")
22798
26204
  });
22799
26205
  this.pathResolver = new PathResolver({
22800
26206
  projectDir,
22801
26207
  workingDir: process.cwd(),
22802
- agentWorkspace: join(projectDir, ".automatosx", "workspaces")
26208
+ agentWorkspace: join(projectDir, AX_PATHS.WORKSPACES)
22803
26209
  });
22804
26210
  const providers = [];
22805
26211
  if (config.providers["claude-code"]?.enabled) {
22806
26212
  const { ClaudeProvider: ClaudeProvider2 } = await Promise.resolve().then(() => (init_claude_provider(), claude_provider_exports));
22807
- providers.push(new ClaudeProvider2({ ...config.providers["claude-code"], name: "claude-code" }));
26213
+ const claudeConfig = config.providers["claude-code"];
26214
+ providers.push(new ClaudeProvider2({ ...claudeConfig, name: "claude-code", command: claudeConfig.command || "claude" }));
22808
26215
  }
22809
26216
  if (config.providers["gemini-cli"]?.enabled) {
22810
26217
  const { GeminiProvider: GeminiProvider2 } = await Promise.resolve().then(() => (init_gemini_provider(), gemini_provider_exports));
22811
- providers.push(new GeminiProvider2({ ...config.providers["gemini-cli"], name: "gemini-cli" }));
26218
+ const geminiConfig = config.providers["gemini-cli"];
26219
+ providers.push(new GeminiProvider2({ ...geminiConfig, name: "gemini-cli", command: geminiConfig.command || "gemini" }));
22812
26220
  }
22813
26221
  if (config.providers["openai"]?.enabled) {
22814
26222
  const { createOpenAIProviderSync: createOpenAIProviderSync2 } = await Promise.resolve().then(() => (init_openai_provider_factory(), openai_provider_factory_exports));
22815
- providers.push(createOpenAIProviderSync2({ ...config.providers["openai"], name: "openai" }, config.providers["openai"].integration));
26223
+ const openaiConfig = config.providers["openai"];
26224
+ providers.push(createOpenAIProviderSync2({ ...openaiConfig, name: "openai", command: openaiConfig.command || "codex" }, openaiConfig.integration));
26225
+ }
26226
+ if (config.providers["glm"]?.enabled) {
26227
+ const { GLMProvider: GLMProvider2 } = await Promise.resolve().then(() => (init_glm_provider(), glm_provider_exports));
26228
+ const glmConfig = config.providers["glm"];
26229
+ providers.push(new GLMProvider2({
26230
+ name: "glm",
26231
+ enabled: true,
26232
+ priority: glmConfig.priority,
26233
+ timeout: glmConfig.timeout,
26234
+ mode: "sdk"
26235
+ }));
26236
+ }
26237
+ if (config.providers["grok"]?.enabled) {
26238
+ const { GrokProvider: GrokProvider2 } = await Promise.resolve().then(() => (init_grok_provider(), grok_provider_exports));
26239
+ const grokConfig = config.providers["grok"];
26240
+ providers.push(new GrokProvider2({
26241
+ name: "grok",
26242
+ enabled: true,
26243
+ priority: grokConfig.priority,
26244
+ timeout: grokConfig.timeout,
26245
+ mode: "sdk"
26246
+ }));
22816
26247
  }
22817
26248
  const healthCheckInterval = config.router?.healthCheckInterval;
22818
26249
  this.router = new Router({
@@ -22966,9 +26397,7 @@ Use this tool first to understand what AutomatosX offers.`,
22966
26397
  register("create_task", createCreateTaskHandler({
22967
26398
  getSession: () => this.session
22968
26399
  }));
22969
- register("run_task", createRunTaskHandler({
22970
- getSession: () => this.session
22971
- }));
26400
+ register("run_task", createRunTaskHandler());
22972
26401
  register("get_task_result", createGetTaskResultHandler());
22973
26402
  register("list_tasks", createListTasksHandler());
22974
26403
  register("delete_task", createDeleteTaskHandler());
@@ -23050,7 +26479,7 @@ Use this tool first to understand what AutomatosX offers.`,
23050
26479
  normalizedProvider: this.session.normalizedProvider
23051
26480
  });
23052
26481
  const requestedProtocol = request.params?.protocolVersion;
23053
- const negotiated = MCP_SUPPORTED_VERSIONS.find((version) => version === requestedProtocol) ?? MCP_SUPPORTED_VERSIONS[0];
26482
+ const negotiated = MCP_SUPPORTED_VERSIONS.find((version) => version === requestedProtocol) ?? "2024-11-05";
23054
26483
  this.negotiatedProtocolVersion = negotiated;
23055
26484
  const response = {
23056
26485
  protocolVersion: negotiated,
@@ -23363,20 +26792,21 @@ Streaming: ${summary.streamingNotifications}` },
23363
26792
  logger.debug("[MCP Server] Response sent", { id: response.id, length: json.length });
23364
26793
  }
23365
26794
  /**
23366
- * Start stdio server with newline-delimited framing
26795
+ * Start stdio server with hybrid framing support
23367
26796
  *
23368
- * v12.2.0: Changed from Content-Length to newline-delimited framing
23369
- * per official MCP specification: https://spec.modelcontextprotocol.io/specification/basic/transports/
26797
+ * v12.3.1: Supports BOTH framing formats for maximum compatibility:
26798
+ * 1. Newline-delimited (official MCP spec, used by Claude Code, @modelcontextprotocol/sdk)
26799
+ * 2. Content-Length (LSP-style, used by ax-glm, ax-grok, some older clients)
23370
26800
  *
23371
- * Format: Each JSON-RPC message is terminated by a newline character.
23372
- * Messages MUST NOT contain embedded newlines.
23373
- * Reference: @modelcontextprotocol/sdk ReadBuffer uses: buffer.indexOf('\n')
26801
+ * Detection: If first line starts with "Content-Length:", use LSP framing.
26802
+ * Otherwise, use newline-delimited framing.
23374
26803
  *
23375
26804
  * BUG FIX (v9.0.1): Added iteration limit and buffer size checks to prevent infinite loops
23376
26805
  */
23377
26806
  async start() {
23378
26807
  logger.info("[MCP Server] Starting stdio JSON-RPC server...");
23379
26808
  let buffer = "";
26809
+ let detectedFraming = null;
23380
26810
  process.stdin.on("data", (chunk) => {
23381
26811
  void this.stdinMutex.runExclusive(async () => {
23382
26812
  buffer += chunk.toString("utf-8");
@@ -23388,17 +26818,49 @@ Streaming: ${summary.streamingNotifications}` },
23388
26818
  buffer = "";
23389
26819
  return;
23390
26820
  }
26821
+ if (detectedFraming === null) {
26822
+ if (buffer.startsWith("Content-Length:")) {
26823
+ detectedFraming = "content-length";
26824
+ logger.info("[MCP Server] Detected Content-Length framing (LSP-style)");
26825
+ } else if (buffer.includes("{")) {
26826
+ detectedFraming = "newline";
26827
+ logger.info("[MCP Server] Detected newline-delimited framing (MCP spec)");
26828
+ }
26829
+ }
23391
26830
  let iterations = 0;
23392
26831
  while (iterations < STDIO_MAX_ITERATIONS) {
23393
26832
  iterations++;
23394
- const newlineIndex = buffer.indexOf("\n");
23395
- if (newlineIndex === -1) break;
23396
- let jsonMessage = buffer.slice(0, newlineIndex);
23397
- if (jsonMessage.endsWith("\r")) {
23398
- jsonMessage = jsonMessage.slice(0, -1);
26833
+ let jsonMessage = null;
26834
+ if (detectedFraming === "content-length") {
26835
+ const headerEnd = buffer.indexOf("\r\n\r\n");
26836
+ if (headerEnd === -1) break;
26837
+ const headers = buffer.slice(0, headerEnd);
26838
+ const contentLengthMatch = headers.match(/Content-Length:\s*(\d+)/i);
26839
+ if (!contentLengthMatch) {
26840
+ const lineEnd = buffer.indexOf("\n");
26841
+ if (lineEnd !== -1) {
26842
+ buffer = buffer.slice(lineEnd + 1);
26843
+ continue;
26844
+ }
26845
+ break;
26846
+ }
26847
+ const contentLength = parseInt(contentLengthMatch[1], 10);
26848
+ const bodyStart = headerEnd + 4;
26849
+ const bodyEnd = bodyStart + contentLength;
26850
+ if (buffer.length < bodyEnd) break;
26851
+ jsonMessage = buffer.slice(bodyStart, bodyEnd);
26852
+ buffer = buffer.slice(bodyEnd);
26853
+ } else {
26854
+ const newlineIndex = buffer.indexOf("\n");
26855
+ if (newlineIndex === -1) break;
26856
+ jsonMessage = buffer.slice(0, newlineIndex);
26857
+ if (jsonMessage.endsWith("\r")) {
26858
+ jsonMessage = jsonMessage.slice(0, -1);
26859
+ }
26860
+ buffer = buffer.slice(newlineIndex + 1);
26861
+ if (jsonMessage.trim() === "") continue;
23399
26862
  }
23400
- buffer = buffer.slice(newlineIndex + 1);
23401
- if (jsonMessage.trim() === "") continue;
26863
+ if (!jsonMessage) break;
23402
26864
  if (jsonMessage.length > STDIO_MAX_MESSAGE_SIZE) {
23403
26865
  logger.error("[MCP Server] Message size exceeded maximum", {
23404
26866
  messageSize: jsonMessage.length,
@@ -23441,7 +26903,7 @@ Streaming: ${summary.streamingNotifications}` },
23441
26903
  process.stdin.on("end", () => shutdown("Server stopped (stdin closed)"));
23442
26904
  process.on("SIGINT", () => shutdown("Received SIGINT, shutting down..."));
23443
26905
  process.on("SIGTERM", () => shutdown("Received SIGTERM, shutting down..."));
23444
- logger.info("[MCP Server] Server started successfully (newline-delimited framing)");
26906
+ logger.info("[MCP Server] Server started successfully (hybrid framing: newline + Content-Length)");
23445
26907
  }
23446
26908
  };
23447
26909