@defai.digital/automatosx 8.3.0 → 8.3.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -8,6 +8,7 @@ import { realpathSync as realpathSync$1, access, realpath, existsSync, readFileS
8
8
  import os2, { homedir, cpus } from 'os';
9
9
  import { findUp } from 'find-up';
10
10
  import { exec, spawn, execSync, spawnSync } from 'child_process';
11
+ import { z } from 'zod';
11
12
  import { promisify } from 'util';
12
13
  import yargs from 'yargs';
13
14
  import { hideBin } from 'yargs/helpers';
@@ -1031,22 +1032,207 @@ var init_path_resolver = __esm({
1031
1032
  };
1032
1033
  }
1033
1034
  });
1034
-
1035
- // src/providers/base-provider.ts
1036
- var BaseProvider;
1035
+ function findOnPath(cmdBase) {
1036
+ const isWindows2 = process.platform === "win32";
1037
+ if (isWindows2) {
1038
+ return findOnPathWindows(cmdBase);
1039
+ }
1040
+ return findOnPathUnix(cmdBase);
1041
+ }
1042
+ function findOnPathWindows(cmdBase) {
1043
+ try {
1044
+ const where = spawnSync("where", [cmdBase], {
1045
+ windowsHide: true,
1046
+ timeout: 3e3
1047
+ });
1048
+ if (where.status === 0) {
1049
+ const lines = where.stdout.toString().split(/\r?\n/).map((s) => s.trim()).filter(Boolean);
1050
+ const firstPath = lines[0];
1051
+ if (firstPath) {
1052
+ logger.debug("Found via where.exe", { cmdBase, path: firstPath });
1053
+ return { found: true, path: firstPath };
1054
+ }
1055
+ }
1056
+ } catch (error) {
1057
+ logger.debug("where.exe failed, falling back to PATH scan", { error });
1058
+ }
1059
+ const pathext = (process.env.PATHEXT || ".EXE;.CMD;.BAT;.COM").toUpperCase().split(";").filter(Boolean);
1060
+ const pathEntries = (process.env.PATH || "").split(delimiter).filter(Boolean);
1061
+ for (const dir of pathEntries) {
1062
+ for (const ext2 of pathext) {
1063
+ const fullPath = `${dir}\\${cmdBase}${ext2}`;
1064
+ if (existsSync(fullPath)) {
1065
+ logger.debug("Found via PATH \xD7 PATHEXT", { cmdBase, path: fullPath });
1066
+ return { found: true, path: fullPath };
1067
+ }
1068
+ }
1069
+ const pathWithoutExt = `${dir}\\${cmdBase}`;
1070
+ if (existsSync(pathWithoutExt)) {
1071
+ logger.debug("Found via PATH (no ext)", { cmdBase, path: pathWithoutExt });
1072
+ return { found: true, path: pathWithoutExt };
1073
+ }
1074
+ }
1075
+ return { found: false };
1076
+ }
1077
+ function findOnPathUnix(cmdBase) {
1078
+ try {
1079
+ const which = spawnSync("which", [cmdBase], { timeout: 3e3 });
1080
+ if (which.status === 0) {
1081
+ const path6 = which.stdout.toString().trim();
1082
+ if (path6) {
1083
+ logger.debug("Found via which", { cmdBase, path: path6 });
1084
+ return { found: true, path: path6 };
1085
+ }
1086
+ }
1087
+ } catch (error) {
1088
+ logger.debug("which failed", { cmdBase, error });
1089
+ }
1090
+ return { found: false };
1091
+ }
1092
+ var init_cli_provider_detector = __esm({
1093
+ "src/core/cli-provider-detector.ts"() {
1094
+ init_esm_shims();
1095
+ init_logger();
1096
+ }
1097
+ });
1098
+ function safeValidateExecutionRequest(request) {
1099
+ return executionRequestSchema.safeParse(request);
1100
+ }
1101
+ function safeValidateExecutionResponse(response) {
1102
+ return executionResponseSchema.safeParse(response);
1103
+ }
1104
+ var executionRequestSchema, tokenUsageSchema, finishReasonSchema, executionResponseSchema, costBreakdownSchema, providerErrorTypeSchema;
1105
+ var init_provider_schemas = __esm({
1106
+ "src/providers/provider-schemas.ts"() {
1107
+ init_esm_shims();
1108
+ executionRequestSchema = z.object({
1109
+ prompt: z.string().min(1, "Prompt cannot be empty"),
1110
+ systemPrompt: z.string().optional(),
1111
+ model: z.string().optional(),
1112
+ maxTokens: z.number().int().positive().optional(),
1113
+ temperature: z.number().min(0).max(2).optional(),
1114
+ topP: z.number().min(0).max(1).optional(),
1115
+ topK: z.number().int().positive().optional(),
1116
+ stopSequences: z.array(z.string()).optional(),
1117
+ stream: z.boolean().optional(),
1118
+ metadata: z.record(z.string(), z.any()).optional()
1119
+ }).describe("Provider execution request");
1120
+ tokenUsageSchema = z.object({
1121
+ prompt: z.number().int().nonnegative(),
1122
+ completion: z.number().int().nonnegative(),
1123
+ total: z.number().int().nonnegative()
1124
+ }).refine(
1125
+ (data) => data.total === data.prompt + data.completion,
1126
+ "Total tokens must equal prompt + completion"
1127
+ ).describe("Token usage information");
1128
+ finishReasonSchema = z.enum([
1129
+ "stop",
1130
+ // Natural completion
1131
+ "length",
1132
+ // Max tokens reached
1133
+ "content_filter",
1134
+ // Content filtered
1135
+ "tool_calls",
1136
+ // Function/tool called
1137
+ "error"
1138
+ // Error occurred
1139
+ ]).describe("Response finish reason");
1140
+ executionResponseSchema = z.object({
1141
+ content: z.string(),
1142
+ model: z.string(),
1143
+ tokensUsed: tokenUsageSchema,
1144
+ latencyMs: z.number().nonnegative(),
1145
+ finishReason: finishReasonSchema,
1146
+ cached: z.boolean().default(false),
1147
+ metadata: z.record(z.string(), z.any()).optional()
1148
+ }).describe("Provider execution response");
1149
+ z.object({
1150
+ available: z.boolean(),
1151
+ latencyMs: z.number().nonnegative(),
1152
+ errorRate: z.number().min(0).max(1),
1153
+ consecutiveFailures: z.number().int().nonnegative(),
1154
+ lastCheckTime: z.number().int().nonnegative().optional()
1155
+ }).describe("Provider health status");
1156
+ z.object({
1157
+ supportsStreaming: z.boolean().default(false),
1158
+ supportsEmbedding: z.boolean().default(false),
1159
+ supportsVision: z.boolean().default(false),
1160
+ supportsFunctionCalling: z.boolean().default(false),
1161
+ maxContextTokens: z.number().int().positive(),
1162
+ supportedModels: z.array(z.string()).min(1)
1163
+ }).describe("Provider capabilities");
1164
+ z.object({
1165
+ hasCapacity: z.boolean(),
1166
+ requestsRemaining: z.number().int().nonnegative(),
1167
+ tokensRemaining: z.number().int().nonnegative(),
1168
+ resetAtMs: z.number().int().positive()
1169
+ }).describe("Rate limit status");
1170
+ costBreakdownSchema = z.object({
1171
+ prompt: z.number().nonnegative(),
1172
+ completion: z.number().nonnegative(),
1173
+ embedding: z.number().nonnegative().optional(),
1174
+ other: z.number().nonnegative().optional()
1175
+ }).describe("Cost breakdown");
1176
+ z.object({
1177
+ amount: z.number().nonnegative(),
1178
+ currency: z.string().length(3).default("USD"),
1179
+ breakdown: costBreakdownSchema
1180
+ }).describe("Cost estimate");
1181
+ z.object({
1182
+ totalRequests: z.number().int().nonnegative(),
1183
+ totalTokens: z.number().int().nonnegative(),
1184
+ totalCost: z.number().nonnegative(),
1185
+ successRate: z.number().min(0).max(1),
1186
+ averageLatencyMs: z.number().nonnegative().optional(),
1187
+ lastRequestTime: z.number().int().nonnegative().optional()
1188
+ }).describe("Provider usage statistics");
1189
+ providerErrorTypeSchema = z.enum([
1190
+ "not_found",
1191
+ "timeout",
1192
+ "rate_limit",
1193
+ "auth_error",
1194
+ "invalid_request",
1195
+ "api_error",
1196
+ "network_error",
1197
+ "config_error",
1198
+ "exec_error",
1199
+ "unknown"
1200
+ ]).describe("Provider error type");
1201
+ z.object({
1202
+ type: providerErrorTypeSchema,
1203
+ message: z.string(),
1204
+ code: z.string().optional(),
1205
+ retryable: z.boolean().default(false),
1206
+ details: z.record(z.string(), z.any()).optional()
1207
+ }).describe("Provider error");
1208
+ }
1209
+ });
1210
+ var execAsync, BaseProvider;
1037
1211
  var init_base_provider = __esm({
1038
1212
  "src/providers/base-provider.ts"() {
1039
1213
  init_esm_shims();
1040
1214
  init_logger();
1041
1215
  init_errors();
1216
+ init_cli_provider_detector();
1217
+ init_provider_schemas();
1218
+ execAsync = promisify(exec);
1042
1219
  BaseProvider = class _BaseProvider {
1043
1220
  /**
1044
1221
  * Whitelist of allowed provider names for security
1222
+ * v8.3.0: Support both old (claude-code, gemini-cli) and new (claude, gemini) names for backward compatibility
1223
+ * v8.3.1: Added 'grok' for Grok CLI integration
1045
1224
  */
1046
1225
  static ALLOWED_PROVIDER_NAMES = [
1047
1226
  "claude",
1227
+ "claude-code",
1228
+ // Backward compatibility - maps to claude CLI
1048
1229
  "gemini",
1230
+ "gemini-cli",
1231
+ // Backward compatibility - maps to gemini CLI
1232
+ "openai",
1049
1233
  "codex",
1234
+ "grok",
1235
+ // Grok CLI (Z.AI GLM 4.6 or X.AI Grok)
1050
1236
  "test-provider"
1051
1237
  // For unit tests
1052
1238
  ];
@@ -1060,7 +1246,7 @@ var init_base_provider = __esm({
1060
1246
  "E1001" /* CONFIG_INVALID */
1061
1247
  );
1062
1248
  }
1063
- this.config = config;
1249
+ this.config = { ...config, name: providerName };
1064
1250
  this.health = {
1065
1251
  available: false,
1066
1252
  latencyMs: 0,
@@ -1069,6 +1255,78 @@ var init_base_provider = __esm({
1069
1255
  lastCheck: Date.now()
1070
1256
  };
1071
1257
  }
1258
+ /**
1259
+ * Execute CLI command - Template method pattern
1260
+ * Common logic here, provider-specific parts via getCLICommand() and getMockResponse()
1261
+ */
1262
+ async executeCLI(prompt) {
1263
+ if (process.env.AUTOMATOSX_MOCK_PROVIDERS === "true") {
1264
+ logger.debug("Mock mode: returning test response");
1265
+ return this.getMockResponse();
1266
+ }
1267
+ try {
1268
+ const escapedPrompt = this.escapeShellArg(prompt);
1269
+ const cliCommand = this.getCLICommand();
1270
+ logger.debug(`Executing ${cliCommand} CLI`, {
1271
+ command: cliCommand,
1272
+ promptLength: prompt.length
1273
+ });
1274
+ const { stdout, stderr } = await execAsync(
1275
+ `${cliCommand} ${escapedPrompt}`,
1276
+ {
1277
+ timeout: this.config.timeout || 12e4,
1278
+ maxBuffer: 10 * 1024 * 1024,
1279
+ shell: "/bin/bash",
1280
+ // Enable shell to support complex commands
1281
+ env: {
1282
+ ...process.env,
1283
+ // Force non-interactive mode for CLIs
1284
+ TERM: "dumb",
1285
+ NO_COLOR: "1",
1286
+ // Disable TTY checks for codex and other CLIs
1287
+ FORCE_COLOR: "0",
1288
+ CI: "true",
1289
+ // Many CLIs disable TTY checks in CI mode
1290
+ NO_UPDATE_NOTIFIER: "1",
1291
+ // Disable interactive prompts
1292
+ DEBIAN_FRONTEND: "noninteractive"
1293
+ }
1294
+ }
1295
+ );
1296
+ if (stderr) {
1297
+ logger.warn(`${cliCommand} CLI stderr output`, { stderr: stderr.trim() });
1298
+ }
1299
+ if (!stdout) {
1300
+ throw new Error(`${cliCommand} CLI returned empty output. stderr: ${stderr || "none"}`);
1301
+ }
1302
+ logger.debug(`${cliCommand} CLI execution successful`, {
1303
+ responseLength: stdout.trim().length
1304
+ });
1305
+ return stdout.trim();
1306
+ } catch (error) {
1307
+ logger.error(`${this.getCLICommand()} CLI execution failed`, { error });
1308
+ throw this.handleError(error);
1309
+ }
1310
+ }
1311
+ /**
1312
+ * Check if CLI is available - Template method pattern
1313
+ * Uses getCLICommand() to determine which CLI to check
1314
+ */
1315
+ async checkCLIAvailable() {
1316
+ try {
1317
+ const cliCommand = this.getCLICommand();
1318
+ const path6 = await findOnPath(cliCommand);
1319
+ const available = path6 !== null;
1320
+ logger.debug(`${cliCommand} CLI availability check`, {
1321
+ available,
1322
+ path: path6 || "not found"
1323
+ });
1324
+ return available;
1325
+ } catch (error) {
1326
+ logger.debug(`${this.getCLICommand()} CLI availability check failed`, { error });
1327
+ return false;
1328
+ }
1329
+ }
1072
1330
  /**
1073
1331
  * Get provider name
1074
1332
  */
@@ -1081,6 +1339,16 @@ var init_base_provider = __esm({
1081
1339
  async execute(request) {
1082
1340
  const startTime = Date.now();
1083
1341
  try {
1342
+ const requestValidation = safeValidateExecutionRequest(request);
1343
+ if (!requestValidation.success) {
1344
+ const validationErrors = requestValidation.error.issues.map(
1345
+ (e) => `${e.path.join(".")}: ${e.message}`
1346
+ ).join("; ");
1347
+ throw new ProviderError(
1348
+ `Invalid execution request: ${validationErrors}`,
1349
+ "E1305" /* PROVIDER_EXEC_ERROR */
1350
+ );
1351
+ }
1084
1352
  logger.debug(`Executing request with ${this.config.name}`, {
1085
1353
  prompt: request.prompt.substring(0, 100) + "..."
1086
1354
  });
@@ -1093,7 +1361,7 @@ ${request.prompt}`;
1093
1361
  const result = await this.executeCLI(fullPrompt);
1094
1362
  this.health.consecutiveFailures = 0;
1095
1363
  this.health.available = true;
1096
- return {
1364
+ const response = {
1097
1365
  content: result,
1098
1366
  model: "default",
1099
1367
  // v8.3.0: CLI determines model
@@ -1107,6 +1375,14 @@ ${request.prompt}`;
1107
1375
  finishReason: "stop",
1108
1376
  cached: false
1109
1377
  };
1378
+ const responseValidation = safeValidateExecutionResponse(response);
1379
+ if (!responseValidation.success) {
1380
+ logger.error("Invalid execution response generated", {
1381
+ errors: responseValidation.error.issues,
1382
+ response
1383
+ });
1384
+ }
1385
+ return response;
1110
1386
  } catch (error) {
1111
1387
  this.health.consecutiveFailures++;
1112
1388
  this.health.available = false;
@@ -1164,9 +1440,15 @@ ${request.prompt}`;
1164
1440
  }
1165
1441
  /**
1166
1442
  * Escape shell command arguments to prevent injection
1443
+ *
1444
+ * v8.3.0 Security Fix: Use POSIX shell single-quote escaping
1445
+ * Wraps argument in single quotes and escapes any existing single quotes
1446
+ * This prevents command injection by ensuring the entire string is treated as a literal.
1447
+ *
1448
+ * Example: hello'world becomes 'hello'\''world'
1167
1449
  */
1168
1450
  escapeShellArg(arg) {
1169
- return arg.replace(/["'\\]/g, "\\$&");
1451
+ return "'" + arg.replace(/'/g, "'\\''") + "'";
1170
1452
  }
1171
1453
  // v8.3.0: Stub implementations for backward compatibility with Provider interface
1172
1454
  // These will be removed when we update the interface in Phase 4
@@ -1267,128 +1549,28 @@ ${request.prompt}`;
1267
1549
  };
1268
1550
  }
1269
1551
  });
1270
- function findOnPath(cmdBase) {
1271
- const isWindows2 = process.platform === "win32";
1272
- if (isWindows2) {
1273
- return findOnPathWindows(cmdBase);
1274
- }
1275
- return findOnPathUnix(cmdBase);
1276
- }
1277
- function findOnPathWindows(cmdBase) {
1278
- try {
1279
- const where = spawnSync("where", [cmdBase], {
1280
- windowsHide: true,
1281
- timeout: 3e3
1282
- });
1283
- if (where.status === 0) {
1284
- const lines = where.stdout.toString().split(/\r?\n/).map((s) => s.trim()).filter(Boolean);
1285
- const firstPath = lines[0];
1286
- if (firstPath) {
1287
- logger.debug("Found via where.exe", { cmdBase, path: firstPath });
1288
- return { found: true, path: firstPath };
1289
- }
1290
- }
1291
- } catch (error) {
1292
- logger.debug("where.exe failed, falling back to PATH scan", { error });
1293
- }
1294
- const pathext = (process.env.PATHEXT || ".EXE;.CMD;.BAT;.COM").toUpperCase().split(";").filter(Boolean);
1295
- const pathEntries = (process.env.PATH || "").split(delimiter).filter(Boolean);
1296
- for (const dir of pathEntries) {
1297
- for (const ext2 of pathext) {
1298
- const fullPath = `${dir}\\${cmdBase}${ext2}`;
1299
- if (existsSync(fullPath)) {
1300
- logger.debug("Found via PATH \xD7 PATHEXT", { cmdBase, path: fullPath });
1301
- return { found: true, path: fullPath };
1302
- }
1303
- }
1304
- const pathWithoutExt = `${dir}\\${cmdBase}`;
1305
- if (existsSync(pathWithoutExt)) {
1306
- logger.debug("Found via PATH (no ext)", { cmdBase, path: pathWithoutExt });
1307
- return { found: true, path: pathWithoutExt };
1308
- }
1309
- }
1310
- return { found: false };
1311
- }
1312
- function findOnPathUnix(cmdBase) {
1313
- try {
1314
- const which = spawnSync("which", [cmdBase], { timeout: 3e3 });
1315
- if (which.status === 0) {
1316
- const path6 = which.stdout.toString().trim();
1317
- if (path6) {
1318
- logger.debug("Found via which", { cmdBase, path: path6 });
1319
- return { found: true, path: path6 };
1320
- }
1321
- }
1322
- } catch (error) {
1323
- logger.debug("which failed", { cmdBase, error });
1324
- }
1325
- return { found: false };
1326
- }
1327
- var init_cli_provider_detector = __esm({
1328
- "src/core/cli-provider-detector.ts"() {
1329
- init_esm_shims();
1330
- init_logger();
1331
- }
1332
- });
1333
1552
 
1334
1553
  // src/providers/claude-provider.ts
1335
1554
  var claude_provider_exports = {};
1336
1555
  __export(claude_provider_exports, {
1337
1556
  ClaudeProvider: () => ClaudeProvider
1338
1557
  });
1339
- var execAsync, ClaudeProvider;
1558
+ var ClaudeProvider;
1340
1559
  var init_claude_provider = __esm({
1341
1560
  "src/providers/claude-provider.ts"() {
1342
1561
  init_esm_shims();
1343
1562
  init_base_provider();
1344
- init_logger();
1345
- init_cli_provider_detector();
1346
- execAsync = promisify(exec);
1347
1563
  ClaudeProvider = class extends BaseProvider {
1348
1564
  constructor(config) {
1349
1565
  super(config);
1350
1566
  }
1351
- /**
1352
- * Execute CLI command: claude "<prompt>"
1353
- */
1354
- async executeCLI(prompt) {
1355
- if (process.env.AUTOMATOSX_MOCK_PROVIDERS === "true") {
1356
- return `[Mock Claude Response]
1357
-
1358
- ${prompt.substring(0, 100)}...
1359
-
1360
- Mock response.`;
1361
- }
1362
- try {
1363
- const escapedPrompt = this.escapeShellArg(prompt);
1364
- const { stdout, stderr } = await execAsync(
1365
- `claude "${escapedPrompt}"`,
1366
- {
1367
- timeout: this.config.timeout || 12e4,
1368
- // 2 min default
1369
- maxBuffer: 10 * 1024 * 1024
1370
- // 10MB
1371
- }
1372
- );
1373
- if (stderr && !stdout) {
1374
- throw new Error(`Claude CLI error: ${stderr}`);
1375
- }
1376
- return stdout.trim();
1377
- } catch (error) {
1378
- logger.error("Claude CLI execution failed", { error });
1379
- throw this.handleError(error);
1380
- }
1567
+ getCLICommand() {
1568
+ return "claude";
1381
1569
  }
1382
- /**
1383
- * Check if claude CLI is available
1384
- */
1385
- async checkCLIAvailable() {
1386
- try {
1387
- const path6 = await findOnPath("claude");
1388
- return path6 !== null;
1389
- } catch {
1390
- return false;
1391
- }
1570
+ getMockResponse() {
1571
+ return `[Mock Claude Response]
1572
+
1573
+ This is a mock response for testing purposes.`;
1392
1574
  }
1393
1575
  };
1394
1576
  }
@@ -1399,134 +1581,44 @@ var gemini_provider_exports = {};
1399
1581
  __export(gemini_provider_exports, {
1400
1582
  GeminiProvider: () => GeminiProvider
1401
1583
  });
1402
- var execAsync2, GeminiProvider;
1584
+ var GeminiProvider;
1403
1585
  var init_gemini_provider = __esm({
1404
1586
  "src/providers/gemini-provider.ts"() {
1405
1587
  init_esm_shims();
1406
1588
  init_base_provider();
1407
- init_logger();
1408
- init_cli_provider_detector();
1409
- execAsync2 = promisify(exec);
1410
1589
  GeminiProvider = class extends BaseProvider {
1411
1590
  constructor(config) {
1412
1591
  super(config);
1413
1592
  }
1414
- /**
1415
- * Execute: gemini "prompt"
1416
- */
1417
- async executeCLI(prompt) {
1418
- if (process.env.AUTOMATOSX_MOCK_PROVIDERS === "true") {
1419
- logger.debug("Using mock Gemini provider");
1420
- return `[Mock Gemini Response]
1421
-
1422
- Received: ${prompt.substring(0, 100)}...
1423
-
1424
- This is a mock response.`;
1425
- }
1426
- try {
1427
- const escapedPrompt = this.escapeShellArg(prompt);
1428
- logger.debug("Executing Gemini CLI", {
1429
- command: "gemini",
1430
- promptLength: prompt.length
1431
- });
1432
- const { stdout, stderr } = await execAsync2(
1433
- `gemini "${escapedPrompt}"`,
1434
- {
1435
- timeout: this.config.timeout || 12e4,
1436
- // 2 min default
1437
- maxBuffer: 10 * 1024 * 1024,
1438
- // 10MB buffer
1439
- env: { ...process.env }
1440
- }
1441
- );
1442
- if (stderr && !stdout) {
1443
- throw new Error(`Gemini CLI error: ${stderr}`);
1444
- }
1445
- const result = stdout.trim();
1446
- logger.debug("Gemini CLI execution successful", {
1447
- responseLength: result.length
1448
- });
1449
- return result;
1450
- } catch (error) {
1451
- logger.error("Gemini CLI execution failed", {
1452
- error: error instanceof Error ? error.message : String(error)
1453
- });
1454
- throw this.handleError(error);
1455
- }
1593
+ getCLICommand() {
1594
+ return "gemini";
1456
1595
  }
1457
- /**
1458
- * Check if gemini CLI is available on PATH
1459
- */
1460
- async checkCLIAvailable() {
1461
- try {
1462
- const path6 = await findOnPath("gemini");
1463
- const available = path6 !== null;
1464
- logger.debug("Gemini CLI availability check", {
1465
- available,
1466
- path: path6 || "not found"
1467
- });
1468
- return available;
1469
- } catch (error) {
1470
- logger.debug("Gemini CLI availability check failed", { error });
1471
- return false;
1472
- }
1596
+ getMockResponse() {
1597
+ return `[Mock Gemini Response]
1598
+
1599
+ This is a mock response for testing purposes.`;
1473
1600
  }
1474
1601
  };
1475
1602
  }
1476
1603
  });
1477
- var execAsync3, OpenAIProvider;
1604
+
1605
+ // src/providers/openai-provider.ts
1606
+ var OpenAIProvider;
1478
1607
  var init_openai_provider = __esm({
1479
1608
  "src/providers/openai-provider.ts"() {
1480
1609
  init_esm_shims();
1481
1610
  init_base_provider();
1482
- init_logger();
1483
- init_cli_provider_detector();
1484
- execAsync3 = promisify(exec);
1485
1611
  OpenAIProvider = class extends BaseProvider {
1486
1612
  constructor(config) {
1487
1613
  super(config);
1488
1614
  }
1489
- /**
1490
- * Execute CLI command: codex "<prompt>"
1491
- */
1492
- async executeCLI(prompt) {
1493
- if (process.env.AUTOMATOSX_MOCK_PROVIDERS === "true") {
1494
- return `[Mock OpenAI/Codex Response]
1495
-
1496
- ${prompt.substring(0, 100)}...
1497
-
1498
- Mock response.`;
1499
- }
1500
- try {
1501
- const escapedPrompt = this.escapeShellArg(prompt);
1502
- const { stdout, stderr } = await execAsync3(
1503
- `codex "${escapedPrompt}"`,
1504
- {
1505
- timeout: this.config.timeout || 12e4,
1506
- // 2 min default
1507
- maxBuffer: 10 * 1024 * 1024
1508
- // 10MB
1509
- }
1510
- );
1511
- if (stderr && !stdout) {
1512
- throw new Error(`Codex CLI error: ${stderr}`);
1513
- }
1514
- return stdout.trim();
1515
- } catch (error) {
1516
- logger.error("Codex CLI execution failed", { error });
1517
- throw this.handleError(error);
1518
- }
1615
+ getCLICommand() {
1616
+ return "codex";
1519
1617
  }
1520
- /**
1521
- * Check if codex CLI is available
1522
- */
1523
- async checkCLIAvailable() {
1524
- try {
1525
- const path6 = await findOnPath("codex");
1526
- return path6 !== null;
1527
- } catch {
1528
- return false;
1529
- }
1618
+ getMockResponse() {
1619
+ return `[Mock OpenAI/Codex Response]
1620
+
1621
+ This is a mock response for testing purposes.`;
1530
1622
  }
1531
1623
  };
1532
1624
  }
@@ -2498,6 +2590,25 @@ var DEFAULT_CONFIG = {
2498
2590
  limitTracking: GLOBAL_PROVIDER_DEFAULTS.limitTracking
2499
2591
  // OpenAI: daily limits
2500
2592
  // v5.0.5: Removed defaults - let provider CLI use optimal defaults
2593
+ },
2594
+ "grok": {
2595
+ enabled: true,
2596
+ priority: 4,
2597
+ timeout: 27e5,
2598
+ // 45 minutes
2599
+ command: "grok",
2600
+ healthCheck: {
2601
+ enabled: true,
2602
+ interval: 3e5,
2603
+ // 5 minutes
2604
+ timeout: 5e3
2605
+ },
2606
+ // v8.3.2: Grok provider defaults
2607
+ circuitBreaker: GLOBAL_PROVIDER_DEFAULTS.circuitBreaker,
2608
+ processManagement: GLOBAL_PROVIDER_DEFAULTS.processManagement,
2609
+ versionDetection: GLOBAL_PROVIDER_DEFAULTS.versionDetection,
2610
+ limitTracking: GLOBAL_PROVIDER_DEFAULTS.limitTracking
2611
+ // Grok: daily limits
2501
2612
  }
2502
2613
  },
2503
2614
  execution: {
@@ -3332,6 +3443,36 @@ var PRECOMPILED_CONFIG = {
3332
3443
  "window": "daily",
3333
3444
  "resetHourUtc": 0
3334
3445
  }
3446
+ },
3447
+ "grok": {
3448
+ "enabled": true,
3449
+ "priority": 4,
3450
+ "timeout": 27e5,
3451
+ "command": "grok",
3452
+ "healthCheck": {
3453
+ "enabled": true,
3454
+ "interval": 3e5,
3455
+ "timeout": 5e3
3456
+ },
3457
+ "circuitBreaker": {
3458
+ "enabled": true,
3459
+ "failureThreshold": 3,
3460
+ "recoveryTimeout": 6e4
3461
+ },
3462
+ "processManagement": {
3463
+ "gracefulShutdownTimeout": 5e3,
3464
+ "forceKillDelay": 1e3
3465
+ },
3466
+ "versionDetection": {
3467
+ "timeout": 5e3,
3468
+ "forceKillDelay": 1e3,
3469
+ "cacheEnabled": true
3470
+ },
3471
+ "limitTracking": {
3472
+ "enabled": true,
3473
+ "window": "daily",
3474
+ "resetHourUtc": 0
3475
+ }
3335
3476
  }
3336
3477
  },
3337
3478
  "execution": {
@@ -3538,11 +3679,311 @@ var PRECOMPILED_CONFIG = {
3538
3679
  },
3539
3680
  "router": {
3540
3681
  "healthCheckInterval": 6e4,
3541
- "providerCooldownMs": 3e4
3682
+ "providerCooldownMs": 3e4,
3683
+ "enableFreeTierPrioritization": true,
3684
+ "enableWorkloadAwareRouting": true
3542
3685
  },
3543
- "version": "8.3.0"
3686
+ "version": "8.3.1"
3544
3687
  };
3545
3688
 
3689
+ // src/core/config-schemas.ts
3690
+ init_esm_shims();
3691
+ z.enum([
3692
+ "claude",
3693
+ "claude-code",
3694
+ "gemini",
3695
+ "gemini-cli",
3696
+ "openai",
3697
+ "codex",
3698
+ "grok",
3699
+ "test-provider"
3700
+ ]).describe("Provider name (whitelisted for security)");
3701
+ var commandSchema = z.string().min(1, "command is required").max(VALIDATION_LIMITS.MAX_COMMAND_LENGTH).regex(
3702
+ /^[a-zA-Z0-9_-]+$/,
3703
+ "Command must be alphanumeric with dash/underscore only (prevents command injection)"
3704
+ ).describe("CLI command name");
3705
+ var safeNameSchema = z.string().min(1).max(VALIDATION_LIMITS.MAX_NAME_LENGTH).regex(
3706
+ /^[a-zA-Z0-9_-]+$/,
3707
+ "Name must be alphanumeric with dash/underscore only"
3708
+ ).describe("Safe identifier name");
3709
+ var relativePathSchema = z.string().min(1).refine(
3710
+ (path6) => !path6.includes("..") && !path6.startsWith("/"),
3711
+ "Path must be relative (no ../, no absolute paths)"
3712
+ ).describe("Relative path within project");
3713
+ var fileExtensionSchema = z.string().regex(
3714
+ /^\.[a-zA-Z0-9]{1,10}$/,
3715
+ "Extension must start with dot and be alphanumeric (max 10 chars)"
3716
+ ).describe("File extension");
3717
+ var positiveIntSchema = z.number().int().positive("must be a positive integer").describe("Positive integer");
3718
+ var nonNegativeIntSchema = z.number().int().nonnegative().describe("Non-negative integer");
3719
+ var timeoutSchema = z.number().int().min(VALIDATION_LIMITS.MIN_TIMEOUT, `Timeout must be >= ${VALIDATION_LIMITS.MIN_TIMEOUT}ms`).max(VALIDATION_LIMITS.MAX_TIMEOUT, `Timeout must be <= ${VALIDATION_LIMITS.MAX_TIMEOUT}ms`).describe("Timeout in milliseconds");
3720
+ var intervalSchema = z.number().int().min(VALIDATION_LIMITS.MIN_INTERVAL, `Interval must be >= ${VALIDATION_LIMITS.MIN_INTERVAL}ms`).max(VALIDATION_LIMITS.MAX_TIMEOUT, `Interval must be <= ${VALIDATION_LIMITS.MAX_TIMEOUT}ms`).describe("Interval in milliseconds");
3721
+ var healthCheckConfigSchema = z.object({
3722
+ enabled: z.boolean().default(true),
3723
+ interval: intervalSchema,
3724
+ timeout: timeoutSchema.min(100, "Health check timeout must be >= 100ms")
3725
+ }).describe("Health check configuration");
3726
+ var circuitBreakerConfigSchema = z.object({
3727
+ enabled: z.boolean().default(true),
3728
+ failureThreshold: z.number().int().min(1).max(10).default(3),
3729
+ recoveryTimeout: timeoutSchema
3730
+ }).describe("Circuit breaker configuration");
3731
+ var processManagementConfigSchema = z.object({
3732
+ gracefulShutdownTimeout: timeoutSchema,
3733
+ forceKillDelay: positiveIntSchema
3734
+ }).describe("Process management configuration");
3735
+ var versionDetectionConfigSchema = z.object({
3736
+ timeout: timeoutSchema,
3737
+ forceKillDelay: positiveIntSchema,
3738
+ cacheEnabled: z.boolean().default(true)
3739
+ }).describe("Version detection configuration");
3740
+ var limitTrackingConfigSchema = z.object({
3741
+ enabled: z.boolean().default(true),
3742
+ window: z.enum(["daily", "weekly", "custom"]).default("daily"),
3743
+ resetHourUtc: z.number().int().min(0).max(23).default(0),
3744
+ customResetMs: positiveIntSchema.optional()
3745
+ }).describe("Provider limit tracking configuration");
3746
+ var providerConfigSchema = z.object({
3747
+ enabled: z.boolean().default(true),
3748
+ priority: positiveIntSchema,
3749
+ timeout: timeoutSchema,
3750
+ command: commandSchema,
3751
+ healthCheck: healthCheckConfigSchema.optional(),
3752
+ circuitBreaker: circuitBreakerConfigSchema.optional(),
3753
+ processManagement: processManagementConfigSchema.optional(),
3754
+ versionDetection: versionDetectionConfigSchema.optional(),
3755
+ limitTracking: limitTrackingConfigSchema.optional()
3756
+ }).describe("Provider configuration");
3757
+ var providersConfigSchema = z.record(
3758
+ safeNameSchema,
3759
+ providerConfigSchema
3760
+ ).describe("Providers configuration map");
3761
+ var retryConfigSchema = z.object({
3762
+ maxAttempts: z.number().int().min(1).max(10).default(3),
3763
+ initialDelay: nonNegativeIntSchema.max(VALIDATION_LIMITS.MAX_TIMEOUT),
3764
+ maxDelay: timeoutSchema,
3765
+ backoffFactor: z.number().min(VALIDATION_LIMITS.MIN_BACKOFF_FACTOR).max(VALIDATION_LIMITS.MAX_BACKOFF_FACTOR).default(2),
3766
+ retryableErrors: z.array(z.string()).max(VALIDATION_LIMITS.MAX_ARRAY_LENGTH).optional()
3767
+ }).refine(
3768
+ (data) => data.maxDelay >= data.initialDelay,
3769
+ "maxDelay must be >= initialDelay"
3770
+ ).describe("Retry configuration");
3771
+ var providerExecutionConfigSchema = z.object({
3772
+ maxWaitMs: timeoutSchema
3773
+ }).describe("Provider execution configuration");
3774
+ var concurrencyConfigSchema = z.object({
3775
+ maxConcurrentAgents: z.number().int().min(1).max(VALIDATION_LIMITS.MAX_CONCURRENT_AGENTS).optional(),
3776
+ autoDetect: z.boolean().default(false),
3777
+ cpuMultiplier: z.number().min(0.1).max(10).default(1),
3778
+ minConcurrency: positiveIntSchema.default(2),
3779
+ maxConcurrency: positiveIntSchema.max(VALIDATION_LIMITS.MAX_CONCURRENT_AGENTS).default(16)
3780
+ }).describe("Concurrency configuration");
3781
+ var stagesConfigSchema = z.object({
3782
+ enabled: z.boolean().default(true),
3783
+ defaultTimeout: timeoutSchema.default(18e5),
3784
+ checkpointPath: relativePathSchema.default(".automatosx/checkpoints"),
3785
+ autoSaveCheckpoint: z.boolean().default(true),
3786
+ cleanupAfterDays: positiveIntSchema.max(365).default(7),
3787
+ retry: z.object({
3788
+ defaultMaxRetries: nonNegativeIntSchema.default(1),
3789
+ defaultRetryDelay: positiveIntSchema.default(2e3)
3790
+ }).optional(),
3791
+ prompts: z.object({
3792
+ timeout: timeoutSchema.default(6e5),
3793
+ autoConfirm: z.boolean().default(false),
3794
+ locale: z.string().default("en")
3795
+ }).optional(),
3796
+ progress: z.object({
3797
+ updateInterval: positiveIntSchema.default(2e3),
3798
+ syntheticProgress: z.boolean().default(true)
3799
+ }).optional()
3800
+ }).describe("Stages configuration");
3801
+ var executionConfigSchema = z.object({
3802
+ defaultTimeout: timeoutSchema,
3803
+ concurrency: concurrencyConfigSchema.optional(),
3804
+ retry: retryConfigSchema,
3805
+ provider: providerExecutionConfigSchema,
3806
+ stages: stagesConfigSchema.optional()
3807
+ }).describe("Execution configuration");
3808
+ var sessionConfigSchema = z.object({
3809
+ maxSessions: positiveIntSchema.max(VALIDATION_LIMITS.MAX_SESSIONS),
3810
+ maxMetadataSize: positiveIntSchema.min(VALIDATION_LIMITS.MIN_BYTES).max(VALIDATION_LIMITS.MAX_FILE_SIZE),
3811
+ saveDebounce: nonNegativeIntSchema.max(VALIDATION_LIMITS.MAX_TIMEOUT),
3812
+ cleanupAfterDays: positiveIntSchema.max(365),
3813
+ maxUuidAttempts: positiveIntSchema.max(1e3),
3814
+ persistPath: relativePathSchema
3815
+ }).describe("Session configuration");
3816
+ var delegationConfigSchema = z.object({
3817
+ maxDepth: positiveIntSchema.max(5, "Delegation depth limited to 5 to prevent deep chains"),
3818
+ timeout: timeoutSchema,
3819
+ enableCycleDetection: z.boolean().default(true)
3820
+ }).describe("Delegation configuration");
3821
+ var orchestrationConfigSchema = z.object({
3822
+ session: sessionConfigSchema,
3823
+ delegation: delegationConfigSchema
3824
+ }).describe("Orchestration configuration");
3825
+ var memorySearchConfigSchema = z.object({
3826
+ defaultLimit: positiveIntSchema.max(1e3),
3827
+ maxLimit: positiveIntSchema.max(1e4),
3828
+ timeout: timeoutSchema.min(100)
3829
+ }).refine(
3830
+ (data) => data.maxLimit >= data.defaultLimit,
3831
+ "maxLimit must be >= defaultLimit"
3832
+ ).describe("Memory search configuration");
3833
+ var memoryConfigSchema = z.object({
3834
+ maxEntries: positiveIntSchema.max(VALIDATION_LIMITS.MAX_ENTRIES),
3835
+ persistPath: relativePathSchema.default(".automatosx/memory"),
3836
+ autoCleanup: z.boolean().default(true),
3837
+ cleanupDays: positiveIntSchema.max(365).default(30),
3838
+ busyTimeout: positiveIntSchema.default(5e3),
3839
+ search: memorySearchConfigSchema.optional()
3840
+ }).describe("Memory configuration");
3841
+ var abilitiesCacheConfigSchema = z.object({
3842
+ enabled: z.boolean().default(true),
3843
+ maxEntries: positiveIntSchema.max(1e3),
3844
+ ttl: intervalSchema.max(VALIDATION_LIMITS.MAX_TTL),
3845
+ maxSize: positiveIntSchema.min(VALIDATION_LIMITS.MIN_BYTES).max(VALIDATION_LIMITS.MAX_CACHE_SIZE),
3846
+ cleanupInterval: intervalSchema
3847
+ }).describe("Abilities cache configuration");
3848
+ var abilitiesLimitsConfigSchema = z.object({
3849
+ maxFileSize: positiveIntSchema.min(VALIDATION_LIMITS.MIN_FILE_SIZE).max(VALIDATION_LIMITS.MAX_FILE_SIZE)
3850
+ }).describe("Abilities limits configuration");
3851
+ var abilitiesConfigSchema = z.object({
3852
+ basePath: relativePathSchema,
3853
+ fallbackPath: relativePathSchema,
3854
+ cache: abilitiesCacheConfigSchema,
3855
+ limits: abilitiesLimitsConfigSchema
3856
+ }).describe("Abilities configuration");
3857
+ var workspaceConfigSchema = z.object({
3858
+ prdPath: z.string().min(1),
3859
+ tmpPath: z.string().min(1),
3860
+ autoCleanupTmp: z.boolean().default(true),
3861
+ tmpCleanupDays: positiveIntSchema.max(365)
3862
+ }).describe("Workspace configuration");
3863
+ var loggingRetentionConfigSchema = z.object({
3864
+ maxSizeBytes: positiveIntSchema.min(VALIDATION_LIMITS.MIN_BYTES).max(VALIDATION_LIMITS.MAX_FILE_SIZE * 10),
3865
+ maxAgeDays: positiveIntSchema.max(365),
3866
+ compress: z.boolean().default(true)
3867
+ }).describe("Logging retention configuration");
3868
+ var loggingConfigSchema = z.object({
3869
+ level: z.enum(["debug", "info", "warn", "error"]).default("info"),
3870
+ path: relativePathSchema,
3871
+ console: z.boolean().default(true),
3872
+ retention: loggingRetentionConfigSchema.optional()
3873
+ }).describe("Logging configuration");
3874
+ var cacheConfigSchema = z.object({
3875
+ enabled: z.boolean().default(true),
3876
+ maxEntries: positiveIntSchema.max(1e4),
3877
+ ttl: intervalSchema.max(VALIDATION_LIMITS.MAX_TTL),
3878
+ cleanupInterval: intervalSchema
3879
+ }).describe("Cache configuration");
3880
+ var adaptiveCacheConfigSchema = z.object({
3881
+ maxEntries: positiveIntSchema.max(1e4),
3882
+ baseTTL: intervalSchema,
3883
+ minTTL: intervalSchema,
3884
+ maxTTL: intervalSchema.max(VALIDATION_LIMITS.MAX_TTL),
3885
+ adaptiveMultiplier: z.number().min(1).max(10),
3886
+ lowFreqDivisor: z.number().min(1).max(10),
3887
+ frequencyThreshold: positiveIntSchema,
3888
+ cleanupInterval: intervalSchema
3889
+ }).refine(
3890
+ (data) => data.maxTTL >= data.baseTTL && data.baseTTL >= data.minTTL,
3891
+ "TTL order must be: minTTL <= baseTTL <= maxTTL"
3892
+ ).describe("Adaptive cache configuration");
3893
+ var responseCacheConfigSchema = z.object({
3894
+ enabled: z.boolean().default(false),
3895
+ ttl: positiveIntSchema,
3896
+ maxSize: positiveIntSchema,
3897
+ maxMemorySize: positiveIntSchema,
3898
+ dbPath: relativePathSchema
3899
+ }).describe("Response cache configuration");
3900
+ var rateLimitConfigSchema = z.object({
3901
+ enabled: z.boolean().default(false),
3902
+ requestsPerMinute: positiveIntSchema.max(1e3),
3903
+ burstSize: positiveIntSchema.max(100)
3904
+ }).describe("Rate limit configuration");
3905
+ var performanceConfigSchema = z.object({
3906
+ profileCache: cacheConfigSchema,
3907
+ teamCache: cacheConfigSchema,
3908
+ providerCache: cacheConfigSchema,
3909
+ adaptiveCache: adaptiveCacheConfigSchema,
3910
+ responseCache: responseCacheConfigSchema.optional(),
3911
+ rateLimit: rateLimitConfigSchema.optional()
3912
+ }).describe("Performance configuration");
3913
+ var embeddingConfigSchema = z.object({
3914
+ timeout: timeoutSchema,
3915
+ retryDelay: positiveIntSchema,
3916
+ dimensions: positiveIntSchema.max(1e4),
3917
+ maxRetries: nonNegativeIntSchema.max(10)
3918
+ }).describe("Embedding configuration");
3919
+ var securityConfigSchema = z.object({
3920
+ enablePathValidation: z.boolean().default(true),
3921
+ allowedExtensions: z.array(fileExtensionSchema).max(VALIDATION_LIMITS.MAX_ARRAY_LENGTH).optional()
3922
+ }).describe("Security configuration");
3923
+ var developmentConfigSchema = z.object({
3924
+ mockProviders: z.boolean().default(false),
3925
+ profileMode: z.boolean().default(false)
3926
+ }).describe("Development configuration");
3927
+ var advancedConfigSchema = z.object({
3928
+ embedding: embeddingConfigSchema.optional(),
3929
+ security: securityConfigSchema.optional(),
3930
+ development: developmentConfigSchema.optional()
3931
+ }).describe("Advanced configuration");
3932
+ var vscodeConfigSchema = z.object({
3933
+ enabled: z.boolean().default(false),
3934
+ apiPort: z.number().int().min(VALIDATION_LIMITS.MIN_PORT).max(VALIDATION_LIMITS.MAX_PORT),
3935
+ autoStart: z.boolean().default(true),
3936
+ outputPanel: z.boolean().default(true),
3937
+ notifications: z.boolean().default(true)
3938
+ }).describe("VSCode integration configuration");
3939
+ var integrationConfigSchema = z.object({
3940
+ vscode: vscodeConfigSchema.optional()
3941
+ }).describe("Integration configuration");
3942
+ var cliRunConfigSchema = z.object({
3943
+ defaultMemory: z.boolean().default(true),
3944
+ defaultSaveMemory: z.boolean().default(true),
3945
+ defaultFormat: z.enum(["text", "json"]).default("text"),
3946
+ defaultVerbose: z.boolean().default(false)
3947
+ }).describe("CLI run configuration");
3948
+ var cliSessionConfigSchema = z.object({
3949
+ defaultShowAgents: z.boolean().default(true)
3950
+ }).describe("CLI session configuration");
3951
+ var cliMemoryConfigSchema = z.object({
3952
+ defaultLimit: positiveIntSchema.default(10)
3953
+ }).describe("CLI memory configuration");
3954
+ var cliConfigSchema = z.object({
3955
+ run: cliRunConfigSchema.optional(),
3956
+ session: cliSessionConfigSchema.optional(),
3957
+ memory: cliMemoryConfigSchema.optional()
3958
+ }).describe("CLI configuration");
3959
+ var routerConfigSchema = z.object({
3960
+ healthCheckInterval: intervalSchema,
3961
+ providerCooldownMs: positiveIntSchema,
3962
+ circuitBreakerThreshold: positiveIntSchema.max(10).optional(),
3963
+ // v8.3.2: Make optional to match interface
3964
+ enableFreeTierPrioritization: z.boolean().default(true),
3965
+ enableWorkloadAwareRouting: z.boolean().default(true)
3966
+ }).describe("Router configuration");
3967
+ var automatosXConfigSchema = z.object({
3968
+ providers: providersConfigSchema.optional(),
3969
+ execution: executionConfigSchema.optional(),
3970
+ orchestration: orchestrationConfigSchema.optional(),
3971
+ memory: memoryConfigSchema.optional(),
3972
+ abilities: abilitiesConfigSchema.optional(),
3973
+ workspace: workspaceConfigSchema.optional(),
3974
+ logging: loggingConfigSchema.optional(),
3975
+ performance: performanceConfigSchema.optional(),
3976
+ advanced: advancedConfigSchema.optional(),
3977
+ integration: integrationConfigSchema.optional(),
3978
+ cli: cliConfigSchema.optional(),
3979
+ router: routerConfigSchema.optional(),
3980
+ version: z.string().regex(/^\d+\.\d+\.\d+$/, "Version must be semver format (x.y.z)").optional()
3981
+ }).describe("AutomatosX configuration");
3982
+ function safeValidateConfig(config) {
3983
+ return automatosXConfigSchema.safeParse(config);
3984
+ }
3985
+ automatosXConfigSchema.partial().passthrough();
3986
+
3546
3987
  // src/core/config.ts
3547
3988
  var configCache = new TTLCache({
3548
3989
  ttl: 6e4,
@@ -3667,7 +4108,21 @@ async function loadConfigFile(path6) {
3667
4108
  function mergeConfig(defaults2, user) {
3668
4109
  return deepMerge(defaults2, user);
3669
4110
  }
4111
+ function validateConfigWithZod(config) {
4112
+ const result = safeValidateConfig(config);
4113
+ if (result.success) {
4114
+ return [];
4115
+ }
4116
+ return result.error.issues.map((err) => {
4117
+ const path6 = err.path.join(".");
4118
+ return `${path6}: ${err.message}`;
4119
+ });
4120
+ }
3670
4121
  function validateConfig(config) {
4122
+ const zodErrors = validateConfigWithZod(config);
4123
+ if (zodErrors.length > 0) {
4124
+ return zodErrors;
4125
+ }
3671
4126
  const errors = [];
3672
4127
  for (const [name, provider] of Object.entries(config.providers)) {
3673
4128
  if (!isValidName(name)) {
@@ -5211,6 +5666,17 @@ var setupCommand = {
5211
5666
  console.log(chalk5.cyan("\u{1F4D6} Setting up GEMINI.md with AutomatosX integration..."));
5212
5667
  await setupProjectGeminiMd(projectDir, packageRoot, argv.force ?? false);
5213
5668
  console.log(chalk5.green(" \u2713 GEMINI.md configured"));
5669
+ console.log(chalk5.cyan("\u{1F50C} Setting up Grok CLI integration..."));
5670
+ const grokDir = join(projectDir, ".grok");
5671
+ const grokDirExistedBefore = await checkExists2(grokDir);
5672
+ await setupGrokIntegration(projectDir, packageRoot);
5673
+ if (!grokDirExistedBefore) {
5674
+ createdResources.push(grokDir);
5675
+ }
5676
+ console.log(chalk5.green(" \u2713 Grok CLI integration configured"));
5677
+ console.log(chalk5.cyan("\u{1F4D6} Setting up GROK.md with AutomatosX integration..."));
5678
+ await setupProjectGrokMd(projectDir, packageRoot, argv.force ?? false);
5679
+ console.log(chalk5.green(" \u2713 GROK.md configured"));
5214
5680
  console.log(chalk5.cyan("\u{1F4D6} Setting up AGENTS.md with AutomatosX integration..."));
5215
5681
  await setupProjectAgentsMd(projectDir, packageRoot, argv.force ?? false);
5216
5682
  console.log(chalk5.green(" \u2713 AGENTS.md configured"));
@@ -5273,6 +5739,11 @@ var setupCommand = {
5273
5739
  console.log(chalk5.gray(" \u2022 Use natural language to work with ax agents"));
5274
5740
  console.log(chalk5.gray(' \u2022 Example: "Use ax agent backend to create a REST API"'));
5275
5741
  console.log(chalk5.gray(" \u2022 No special commands needed - just ask naturally!\n"));
5742
+ console.log(chalk5.cyan("Grok CLI Integration:"));
5743
+ console.log(chalk5.gray(" \u2022 Configure .grok/settings.json with your API key"));
5744
+ console.log(chalk5.gray(" \u2022 Supports X.AI (grok-3-fast) and Z.AI (glm-4.6)"));
5745
+ console.log(chalk5.gray(' \u2022 Enable in automatosx.config.json: "grok": { "enabled": true }'));
5746
+ console.log(chalk5.gray(" \u2022 See GROK.md for setup instructions\n"));
5276
5747
  console.log(chalk5.cyan("OpenAI Codex Provider:"));
5277
5748
  console.log(chalk5.gray(" \u2022 Use natural language to work with ax agents"));
5278
5749
  console.log(chalk5.gray(' \u2022 Or use terminal: ax run <agent> "task"'));
@@ -5829,6 +6300,104 @@ async function setupProjectGeminiMd(projectDir, packageRoot, force) {
5829
6300
  });
5830
6301
  }
5831
6302
  }
6303
+ async function setupGrokIntegration(projectDir, packageRoot) {
6304
+ const examplesBaseDir = join(packageRoot, "examples/grok");
6305
+ const templatesDir = join(packageRoot, "templates/providers");
6306
+ const grokDir = join(projectDir, ".grok");
6307
+ await mkdir(grokDir, { recursive: true });
6308
+ try {
6309
+ const settingsSource = join(examplesBaseDir, "settings.json");
6310
+ const settingsTarget = join(grokDir, "settings.json");
6311
+ const exists = await checkExists2(settingsTarget);
6312
+ if (!exists) {
6313
+ await copyFile(settingsSource, settingsTarget);
6314
+ logger.info("Created .grok/settings.json template", { path: settingsTarget });
6315
+ } else {
6316
+ logger.info(".grok/settings.json already exists, skipping", { path: settingsTarget });
6317
+ }
6318
+ } catch (error) {
6319
+ logger.warn("Failed to copy Grok settings template", {
6320
+ error: error.message
6321
+ });
6322
+ }
6323
+ try {
6324
+ const providersDir = join(projectDir, ".automatosx/providers");
6325
+ await mkdir(providersDir, { recursive: true });
6326
+ const xaiTemplateSource = join(templatesDir, "grok.yaml.template");
6327
+ const xaiTemplateTarget = join(providersDir, "grok.yaml.template");
6328
+ const xaiExists = await checkExists2(xaiTemplateTarget);
6329
+ if (!xaiExists) {
6330
+ await copyFile(xaiTemplateSource, xaiTemplateTarget);
6331
+ logger.info("Created .automatosx/providers/grok.yaml.template (X.AI Grok)", { path: xaiTemplateTarget });
6332
+ }
6333
+ const zaiTemplateSource = join(templatesDir, "grok-zai.yaml.template");
6334
+ const zaiTemplateTarget = join(providersDir, "grok-zai.yaml.template");
6335
+ const zaiExists = await checkExists2(zaiTemplateTarget);
6336
+ if (!zaiExists) {
6337
+ await copyFile(zaiTemplateSource, zaiTemplateTarget);
6338
+ logger.info("Created .automatosx/providers/grok-zai.yaml.template (Z.AI GLM 4.6)", { path: zaiTemplateTarget });
6339
+ }
6340
+ const readmeSource = join(templatesDir, "README.md");
6341
+ const readmeTarget = join(providersDir, "README.md");
6342
+ const readmeExists = await checkExists2(readmeTarget);
6343
+ if (!readmeExists) {
6344
+ await copyFile(readmeSource, readmeTarget);
6345
+ logger.info("Created .automatosx/providers/README.md", { path: readmeTarget });
6346
+ }
6347
+ } catch (error) {
6348
+ logger.warn("Failed to copy Grok provider YAML templates", {
6349
+ error: error.message
6350
+ });
6351
+ }
6352
+ }
6353
+ async function setupProjectGrokMd(projectDir, packageRoot, force) {
6354
+ const grokMdPath = join(projectDir, "GROK.md");
6355
+ const templatePath = join(packageRoot, "examples/grok/GROK_INTEGRATION.md");
6356
+ try {
6357
+ const { readFile: readFile14 } = await import('fs/promises');
6358
+ const template = await readFile14(templatePath, "utf-8");
6359
+ const exists = await checkExists2(grokMdPath);
6360
+ if (!exists) {
6361
+ const content = [
6362
+ "# GROK.md",
6363
+ "",
6364
+ "This file provides guidance for Grok CLI integration with AutomatosX.",
6365
+ "",
6366
+ "---",
6367
+ "",
6368
+ template
6369
+ ].join("\n");
6370
+ await writeFile(grokMdPath, content, "utf-8");
6371
+ logger.info("Created GROK.md with AutomatosX integration", { path: grokMdPath });
6372
+ } else {
6373
+ const existingContent = await readFile14(grokMdPath, "utf-8");
6374
+ if (existingContent.includes("# Grok CLI Integration")) {
6375
+ if (!force) {
6376
+ logger.info("GROK.md already contains AutomatosX integration", { path: grokMdPath });
6377
+ return;
6378
+ }
6379
+ const updatedContent = replaceAutomatosXSection(existingContent, template);
6380
+ await writeFile(grokMdPath, updatedContent, "utf-8");
6381
+ logger.info("Updated AutomatosX integration in GROK.md", { path: grokMdPath });
6382
+ } else {
6383
+ const updatedContent = [
6384
+ existingContent.trimEnd(),
6385
+ "",
6386
+ "---",
6387
+ "",
6388
+ template
6389
+ ].join("\n");
6390
+ await writeFile(grokMdPath, updatedContent, "utf-8");
6391
+ logger.info("Added AutomatosX integration to existing GROK.md", { path: grokMdPath });
6392
+ }
6393
+ }
6394
+ } catch (error) {
6395
+ logger.warn("Failed to setup GROK.md", {
6396
+ error: error.message,
6397
+ path: grokMdPath
6398
+ });
6399
+ }
6400
+ }
5832
6401
  async function setupProjectAgentsMd(projectDir, packageRoot, force) {
5833
6402
  const agentsMdPath = join(projectDir, "AGENTS.md");
5834
6403
  const templatePath = join(packageRoot, "examples/agents/AGENTS_INTEGRATION.md");
@@ -6263,8 +6832,8 @@ var initCommand = {
6263
6832
  console.log(chalk5.white(" Using backend agent to analyze your project..."));
6264
6833
  console.log(chalk5.dim(" This will take 1-2 minutes\n"));
6265
6834
  const { spawn: spawn5 } = await import('child_process');
6266
- const { promisify: promisify7 } = await import('util');
6267
- const execFile = promisify7((await import('child_process')).execFile);
6835
+ const { promisify: promisify5 } = await import('util');
6836
+ const execFile = promisify5((await import('child_process')).execFile);
6268
6837
  try {
6269
6838
  const analysisTask = `Analyze this project and create a comprehensive ax.md file:
6270
6839
 
@@ -8480,8 +9049,6 @@ var Router = class {
8480
9049
  providers;
8481
9050
  fallbackEnabled;
8482
9051
  healthCheckInterval;
8483
- penalizedProviders;
8484
- // provider name -> penalty expiry timestamp
8485
9052
  providerCooldownMs;
8486
9053
  cache;
8487
9054
  routerConfig;
@@ -8500,14 +9067,15 @@ var Router = class {
8500
9067
  tracer;
8501
9068
  // v8.3.0: Circuit breaker for simple failover
8502
9069
  circuitState = /* @__PURE__ */ new Map();
9070
+ circuitBreakerThreshold;
8503
9071
  constructor(config) {
8504
9072
  this.routerConfig = config;
8505
9073
  this.providers = [...config.providers].sort((a, b) => {
8506
9074
  return a.priority - b.priority;
8507
9075
  });
8508
9076
  this.fallbackEnabled = config.fallbackEnabled;
8509
- this.penalizedProviders = /* @__PURE__ */ new Map();
8510
9077
  this.providerCooldownMs = config.providerCooldownMs ?? 3e4;
9078
+ this.circuitBreakerThreshold = config.circuitBreakerThreshold ?? 3;
8511
9079
  this.cache = config.cache;
8512
9080
  const limitManager = getProviderLimitManager();
8513
9081
  void limitManager.initialize().catch((err) => {
@@ -8643,8 +9211,8 @@ var Router = class {
8643
9211
  const providerNames = providersToTry.map((p) => p.name);
8644
9212
  const healthMultipliers = /* @__PURE__ */ new Map();
8645
9213
  for (const provider of providersToTry) {
8646
- const isPenalized = this.penalizedProviders.has(provider.name);
8647
- healthMultipliers.set(provider.name, isPenalized ? 0.5 : 1);
9214
+ const isCircuitOpen = this.isCircuitOpen(provider.name);
9215
+ healthMultipliers.set(provider.name, isCircuitOpen ? 0.5 : 1);
8648
9216
  }
8649
9217
  const scores = await getProviderMetricsTracker().getAllScores(
8650
9218
  providerNames,
@@ -8736,21 +9304,20 @@ var Router = class {
8736
9304
  modelParams
8737
9305
  );
8738
9306
  }
8739
- this.penalizedProviders.delete(provider.name);
9307
+ this.recordSuccess(provider.name);
8740
9308
  if (this.tracer) {
8741
- const estimatedCost = this.estimateCost(provider.name, response.tokensUsed);
8742
9309
  this.tracer.logExecution(
8743
9310
  provider.name,
8744
9311
  true,
8745
9312
  // success
8746
9313
  response.latencyMs,
8747
- estimatedCost,
9314
+ 0,
9315
+ // v8.3.0: No cost tracking in CLI-only mode
8748
9316
  response.tokensUsed
8749
9317
  );
8750
9318
  }
8751
9319
  if (this.useMultiFactorRouting) {
8752
9320
  const metricsTracker = getProviderMetricsTracker();
8753
- const estimatedCost = this.estimateCost(provider.name, response.tokensUsed);
8754
9321
  void metricsTracker.recordRequest(
8755
9322
  provider.name,
8756
9323
  response.latencyMs,
@@ -8762,7 +9329,8 @@ var Router = class {
8762
9329
  completion: response.tokensUsed.completion,
8763
9330
  total: response.tokensUsed.total
8764
9331
  },
8765
- estimatedCost,
9332
+ 0,
9333
+ // v8.3.0: No cost tracking in CLI-only mode
8766
9334
  response.model
8767
9335
  ).catch((error) => {
8768
9336
  logger.warn("Metrics recording failed (non-critical)", {
@@ -8820,9 +9388,7 @@ var Router = class {
8820
9388
  error: lastError.message,
8821
9389
  willFallback: this.fallbackEnabled && attemptNumber < availableProviders.length
8822
9390
  });
8823
- const penaltyExpiry = Date.now() + this.providerCooldownMs;
8824
- this.penalizedProviders.set(provider.name, penaltyExpiry);
8825
- logger.debug(`Provider ${provider.name} penalized until ${new Date(penaltyExpiry).toISOString()}`);
9391
+ this.recordFailure(provider.name);
8826
9392
  if (this.tracer) {
8827
9393
  const nextProvider = providersToTry[attemptNumber]?.name;
8828
9394
  this.tracer.logDegradation(
@@ -8910,17 +9476,12 @@ var Router = class {
8910
9476
  /**
8911
9477
  * Get available providers sorted by priority
8912
9478
  * v5.7.0: Enhanced with provider limit detection
8913
- * Filters out penalized providers (those in cooldown period) and limited providers (quota exceeded)
9479
+ * v8.3.0: Uses circuit breaker state instead of separate penalty tracking
9480
+ * Filters out providers with open circuit breakers and limited providers (quota exceeded)
8914
9481
  */
8915
9482
  async getAvailableProviders() {
8916
9483
  const now = Date.now();
8917
9484
  const limitManager = getProviderLimitManager();
8918
- for (const [providerName, expiryTime] of this.penalizedProviders.entries()) {
8919
- if (now >= expiryTime) {
8920
- this.penalizedProviders.delete(providerName);
8921
- logger.debug(`Provider ${providerName} penalty expired`);
8922
- }
8923
- }
8924
9485
  const checks = this.providers.map(async (provider) => {
8925
9486
  try {
8926
9487
  const limitCheck = limitManager.isProviderLimited(provider.name, now);
@@ -8930,10 +9491,8 @@ var Router = class {
8930
9491
  logger.debug(`Skipping limited provider ${provider.name} (resets in ${remainingHours}h)`);
8931
9492
  return null;
8932
9493
  }
8933
- if (this.penalizedProviders.has(provider.name)) {
8934
- const expiryTime = this.penalizedProviders.get(provider.name);
8935
- const remainingMs = expiryTime - now;
8936
- logger.debug(`Skipping penalized provider ${provider.name} (${Math.ceil(remainingMs / 1e3)}s remaining)`);
9494
+ if (this.isCircuitOpen(provider.name)) {
9495
+ logger.debug(`Skipping provider ${provider.name} (circuit breaker open)`);
8937
9496
  return null;
8938
9497
  }
8939
9498
  const isAvailable = await provider.isAvailable();
@@ -9080,7 +9639,7 @@ var Router = class {
9080
9639
  clearInterval(this.healthCheckInterval);
9081
9640
  this.healthCheckInterval = void 0;
9082
9641
  }
9083
- this.penalizedProviders.clear();
9642
+ this.circuitState.clear();
9084
9643
  if (this.tracer) {
9085
9644
  this.tracer.close();
9086
9645
  logger.debug("Router trace logger closed");
@@ -9114,10 +9673,49 @@ var Router = class {
9114
9673
  };
9115
9674
  }
9116
9675
  /**
9117
- * v8.3.0: Cost estimation removed - returns 0
9676
+ * v8.3.0: Check if circuit breaker is open for a provider
9118
9677
  */
9119
- estimateCost(providerName, tokensUsed) {
9120
- return 0;
9678
+ isCircuitOpen(providerName) {
9679
+ const state = this.circuitState.get(providerName);
9680
+ if (!state || !state.isOpen) return false;
9681
+ const cooldownMs = this.providerCooldownMs || 6e4;
9682
+ if (Date.now() - state.lastFailure > cooldownMs) {
9683
+ state.isOpen = false;
9684
+ state.failures = 0;
9685
+ this.circuitState.set(providerName, state);
9686
+ logger.info(`Circuit breaker closed for ${providerName} after cooldown`);
9687
+ return false;
9688
+ }
9689
+ return true;
9690
+ }
9691
+ /**
9692
+ * v8.3.0: Record provider success - resets circuit breaker
9693
+ */
9694
+ recordSuccess(providerName) {
9695
+ const state = this.circuitState.get(providerName);
9696
+ if (state) {
9697
+ state.failures = 0;
9698
+ state.isOpen = false;
9699
+ this.circuitState.set(providerName, state);
9700
+ logger.debug(`Circuit breaker reset for ${providerName} after success`);
9701
+ }
9702
+ }
9703
+ /**
9704
+ * v8.3.0: Record provider failure - opens circuit after threshold
9705
+ */
9706
+ recordFailure(providerName) {
9707
+ const state = this.circuitState.get(providerName) || {
9708
+ failures: 0,
9709
+ lastFailure: 0,
9710
+ isOpen: false
9711
+ };
9712
+ state.failures++;
9713
+ state.lastFailure = Date.now();
9714
+ if (state.failures >= this.circuitBreakerThreshold) {
9715
+ state.isOpen = true;
9716
+ logger.warn(`Circuit breaker opened for ${providerName} after ${state.failures} failures (threshold: ${this.circuitBreakerThreshold})`);
9717
+ }
9718
+ this.circuitState.set(providerName, state);
9121
9719
  }
9122
9720
  };
9123
9721
 
@@ -12474,6 +13072,155 @@ var AgentNotFoundError = class extends Error {
12474
13072
 
12475
13073
  // src/agents/profile-loader.ts
12476
13074
  init_logger();
13075
+
13076
+ // src/agents/agent-schemas.ts
13077
+ init_esm_shims();
13078
+ var stageSchema = z.object({
13079
+ name: z.string().min(1),
13080
+ description: z.string().min(1),
13081
+ key_questions: z.array(z.string()).optional(),
13082
+ outputs: z.array(z.string()).optional(),
13083
+ // Deprecated but still accepted for backward compatibility
13084
+ model: z.string().optional(),
13085
+ temperature: z.number().min(0).max(2).optional(),
13086
+ // Advanced stage features
13087
+ dependencies: z.array(z.string()).optional(),
13088
+ condition: z.string().optional(),
13089
+ parallel: z.boolean().optional(),
13090
+ streaming: z.boolean().optional(),
13091
+ saveToMemory: z.boolean().optional(),
13092
+ // Checkpoint and retry
13093
+ checkpoint: z.boolean().optional(),
13094
+ timeout: z.number().int().positive().optional(),
13095
+ maxRetries: z.number().int().nonnegative().max(10).optional(),
13096
+ retryDelay: z.number().int().nonnegative().optional()
13097
+ }).describe("Agent workflow stage");
13098
+ var personalitySchema = z.object({
13099
+ traits: z.array(z.string()).optional(),
13100
+ catchphrase: z.string().optional(),
13101
+ communication_style: z.string().optional(),
13102
+ decision_making: z.string().optional()
13103
+ }).describe("Agent personality");
13104
+ var abilitySelectionSchema = z.object({
13105
+ core: z.array(z.string()).optional(),
13106
+ taskBased: z.record(z.string(), z.array(z.string())).optional(),
13107
+ loadAll: z.boolean().optional()
13108
+ }).describe("Ability selection strategy");
13109
+ var redirectRuleSchema = z.object({
13110
+ phrase: z.string().regex(/.+/, "Redirect phrase must be a valid regex pattern"),
13111
+ suggest: z.string().min(1)
13112
+ }).describe("Agent redirect rule");
13113
+ var selectionMetadataSchema = z.object({
13114
+ primaryIntents: z.array(z.string()).optional(),
13115
+ secondarySignals: z.array(z.string()).optional(),
13116
+ negativeIntents: z.array(z.string()).optional(),
13117
+ redirectWhen: z.array(redirectRuleSchema).optional(),
13118
+ keywords: z.array(z.string()).optional(),
13119
+ antiKeywords: z.array(z.string()).optional()
13120
+ }).describe("Agent selection metadata");
13121
+ var agentProfileSchema = z.object({
13122
+ // Basic information
13123
+ name: z.string().min(1).max(50).regex(/^[a-zA-Z0-9_-]+$/, "Agent name must be alphanumeric with dash/underscore only").optional(),
13124
+ // Optional - uses filename if not provided
13125
+ displayName: z.string().max(100).optional().or(z.literal("")).transform((val) => val === "" ? void 0 : val),
13126
+ version: z.string().regex(/^\d+\.\d+\.\d+$/, "Version must be semver format").optional(),
13127
+ description: z.string().min(1),
13128
+ // Role and expertise
13129
+ role: z.string().min(1).optional(),
13130
+ expertise: z.array(z.string()).min(1).optional(),
13131
+ capabilities: z.array(z.string()).optional(),
13132
+ // System prompt (required by profile-loader validateProfile, but optional here for flexibility)
13133
+ systemPrompt: z.string().min(1).optional(),
13134
+ // Workflow
13135
+ workflow: z.array(stageSchema).min(1).optional(),
13136
+ // Personality
13137
+ personality: personalitySchema.optional(),
13138
+ // Abilities - accepts both array (legacy) and object (new) formats
13139
+ abilities: z.union([
13140
+ z.array(z.string()),
13141
+ // Legacy format: ['ability1', 'ability2']
13142
+ abilitySelectionSchema
13143
+ // New format: { core: [...], taskBased: {...}, loadAll: true }
13144
+ ]).optional(),
13145
+ // Ability selection strategy (v4.5.8+)
13146
+ abilitySelection: abilitySelectionSchema.optional(),
13147
+ // Thinking patterns
13148
+ thinking_patterns: z.array(z.string()).optional(),
13149
+ // Dependencies
13150
+ dependencies: z.array(z.string()).optional(),
13151
+ // Parallel execution
13152
+ parallel: z.boolean().optional(),
13153
+ // Model parameters (deprecated but still accepted)
13154
+ temperature: z.number().min(0).max(2).optional(),
13155
+ maxTokens: z.number().int().positive().optional(),
13156
+ // Orchestration (v4.7.0+)
13157
+ orchestration: z.object({
13158
+ maxDelegationDepth: z.number().int().nonnegative().optional(),
13159
+ canReadWorkspaces: z.array(z.string()).optional(),
13160
+ canWriteToShared: z.boolean().optional()
13161
+ }).optional(),
13162
+ // Selection metadata (v5.7.0+)
13163
+ selectionMetadata: selectionMetadataSchema.optional(),
13164
+ // Team and collaboration
13165
+ team: z.string().optional(),
13166
+ collaboratesWith: z.array(z.string()).optional(),
13167
+ // Deprecated fields (accepted but ignored)
13168
+ model: z.string().optional(),
13169
+ provider: z.string().optional(),
13170
+ fallbackProvider: z.string().optional(),
13171
+ // Additional metadata
13172
+ tags: z.array(z.string()).optional(),
13173
+ priority: z.number().int().min(1).max(100).optional(),
13174
+ enabled: z.boolean().default(true),
13175
+ // Custom metadata
13176
+ metadata: z.record(z.string(), z.any()).optional()
13177
+ }).describe("Agent profile");
13178
+ z.object({
13179
+ memory: z.boolean().optional(),
13180
+ saveMemory: z.boolean().optional(),
13181
+ session: z.string().optional(),
13182
+ sessionCreate: z.boolean().optional(),
13183
+ provider: z.string().optional(),
13184
+ format: z.enum(["text", "json"]).optional(),
13185
+ verbose: z.boolean().optional(),
13186
+ debug: z.boolean().optional(),
13187
+ quiet: z.boolean().optional(),
13188
+ config: z.string().optional(),
13189
+ parallel: z.boolean().optional(),
13190
+ streaming: z.boolean().optional(),
13191
+ resumable: z.boolean().optional(),
13192
+ checkpoint: z.boolean().optional()
13193
+ }).describe("Agent run command options");
13194
+ z.object({
13195
+ template: z.string().optional(),
13196
+ interactive: z.boolean().optional(),
13197
+ force: z.boolean().optional(),
13198
+ description: z.string().optional(),
13199
+ role: z.string().optional(),
13200
+ expertise: z.array(z.string()).optional(),
13201
+ displayName: z.string().optional()
13202
+ }).describe("Agent create command options");
13203
+ z.object({
13204
+ limit: z.number().int().positive().max(1e4).optional(),
13205
+ agent: z.string().optional(),
13206
+ session: z.string().optional(),
13207
+ format: z.enum(["text", "json"]).optional(),
13208
+ before: z.string().optional(),
13209
+ // ISO date string
13210
+ after: z.string().optional()
13211
+ // ISO date string
13212
+ }).describe("Memory search options");
13213
+ z.object({
13214
+ agents: z.array(z.string()).min(1),
13215
+ description: z.string().optional(),
13216
+ metadata: z.record(z.string(), z.any()).optional()
13217
+ }).describe("Session create options");
13218
+ function safeValidateAgentProfile(profile) {
13219
+ return agentProfileSchema.safeParse(profile);
13220
+ }
13221
+ agentProfileSchema.partial();
13222
+
13223
+ // src/agents/profile-loader.ts
12477
13224
  var __filename3 = fileURLToPath(import.meta.url);
12478
13225
  var __dirname4 = dirname(__filename3);
12479
13226
  function getPackageRoot2() {
@@ -13004,6 +13751,25 @@ var ProfileLoader = class {
13004
13751
  if (!data || typeof data !== "object" || Array.isArray(data)) {
13005
13752
  throw new AgentValidationError(`Invalid profile data for ${name}: expected object, got ${typeof data}`);
13006
13753
  }
13754
+ if (data.name && typeof data.name === "string") {
13755
+ if (!/^[a-zA-Z0-9_-]+$/.test(data.name)) {
13756
+ if (!data.displayName) {
13757
+ data.displayName = data.name;
13758
+ }
13759
+ data.name = name;
13760
+ }
13761
+ } else if (!data.name) {
13762
+ data.name = name;
13763
+ }
13764
+ const validationResult = safeValidateAgentProfile(data);
13765
+ if (!validationResult.success) {
13766
+ const validationErrors = validationResult.error.issues.map(
13767
+ (e) => `${e.path.join(".")}: ${e.message}`
13768
+ ).join("; ");
13769
+ throw new AgentValidationError(
13770
+ `Invalid profile for ${name}: ${validationErrors}`
13771
+ );
13772
+ }
13007
13773
  let teamConfig;
13008
13774
  if (data.team && this.teamManager) {
13009
13775
  try {
@@ -21340,6 +22106,55 @@ init_esm_shims();
21340
22106
  init_path_resolver();
21341
22107
  init_claude_provider();
21342
22108
  init_gemini_provider();
22109
+
22110
+ // src/providers/grok-provider.ts
22111
+ init_esm_shims();
22112
+ init_base_provider();
22113
+ init_logger();
22114
+ var GrokProvider = class extends BaseProvider {
22115
+ constructor(config) {
22116
+ super(config);
22117
+ logger.debug("GrokProvider initialized", {
22118
+ name: config.name,
22119
+ enabled: config.enabled,
22120
+ priority: config.priority,
22121
+ command: config.command || "grok"
22122
+ });
22123
+ }
22124
+ /**
22125
+ * Get the CLI command name for Grok
22126
+ * Returns 'grok' which can point to either:
22127
+ * - Z.AI GLM 4.6 CLI
22128
+ * - X.AI Official Grok CLI
22129
+ */
22130
+ getCLICommand() {
22131
+ return this.config.command || "grok";
22132
+ }
22133
+ /**
22134
+ * Get mock response for testing
22135
+ * Returns a realistic Grok-style response
22136
+ */
22137
+ getMockResponse() {
22138
+ return `[Mock Grok Response]
22139
+
22140
+ This is a mock response from Grok for testing purposes.
22141
+
22142
+ Grok is designed to provide helpful, accurate, and witty responses to your queries. This mock response simulates the typical output you would receive from the Grok CLI.
22143
+
22144
+ Key features:
22145
+ - Direct and informative answers
22146
+ - Occasional humor and personality
22147
+ - Factual accuracy
22148
+ - Clear formatting
22149
+
22150
+ For actual Grok responses, ensure:
22151
+ 1. Grok CLI is installed (grok --version)
22152
+ 2. API credentials are configured (if using X.AI)
22153
+ 3. AUTOMATOSX_MOCK_PROVIDERS is not set to 'true'`;
22154
+ }
22155
+ };
22156
+
22157
+ // src/cli/commands/status.ts
21343
22158
  init_openai_provider_factory();
21344
22159
  init_logger();
21345
22160
  var VERSION = getVersion();
@@ -21426,6 +22241,15 @@ var statusCommand3 = {
21426
22241
  );
21427
22242
  providers.push(provider);
21428
22243
  }
22244
+ if (providerConfigs["grok"]?.enabled) {
22245
+ providers.push(new GrokProvider({
22246
+ name: "grok",
22247
+ enabled: true,
22248
+ priority: providerConfigs["grok"].priority,
22249
+ timeout: providerConfigs["grok"].timeout,
22250
+ command: providerConfigs["grok"].command
22251
+ }));
22252
+ }
21429
22253
  const providerHealth = await Promise.all(
21430
22254
  providers.map(async (p) => ({
21431
22255
  name: p.name,
@@ -21776,7 +22600,7 @@ function formatUptime(seconds) {
21776
22600
  // src/cli/commands/update.ts
21777
22601
  init_esm_shims();
21778
22602
  init_logger();
21779
- var execAsync4 = promisify(exec);
22603
+ var execAsync2 = promisify(exec);
21780
22604
  var updateCommand = {
21781
22605
  command: "update",
21782
22606
  describe: "Check for updates and upgrade AutomatosX to the latest version",
@@ -21855,7 +22679,7 @@ var updateCommand = {
21855
22679
  };
21856
22680
  async function getCurrentVersion() {
21857
22681
  try {
21858
- const { stdout } = await execAsync4("npm list -g @defai.digital/automatosx --depth=0 --json");
22682
+ const { stdout } = await execAsync2("npm list -g @defai.digital/automatosx --depth=0 --json");
21859
22683
  const result = JSON.parse(stdout);
21860
22684
  return result.dependencies["@defai.digital/automatosx"]?.version || "unknown";
21861
22685
  } catch (error) {
@@ -21871,7 +22695,7 @@ async function getCurrentVersion() {
21871
22695
  }
21872
22696
  }
21873
22697
  async function getLatestVersion() {
21874
- const { stdout } = await execAsync4("npm view @defai.digital/automatosx version");
22698
+ const { stdout } = await execAsync2("npm view @defai.digital/automatosx version");
21875
22699
  return stdout.trim();
21876
22700
  }
21877
22701
  function isNewer(a, b) {
@@ -21886,7 +22710,7 @@ function isNewer(a, b) {
21886
22710
  async function showChangelog(from, to) {
21887
22711
  try {
21888
22712
  console.log(chalk5.cyan("What's new:\n"));
21889
- const { stdout } = await execAsync4(
22713
+ const { stdout } = await execAsync2(
21890
22714
  `curl -s https://api.github.com/repos/defai-digital/automatosx/releases/tags/v${to}`
21891
22715
  );
21892
22716
  const release = JSON.parse(stdout);
@@ -21908,7 +22732,7 @@ async function showChangelog(from, to) {
21908
22732
  }
21909
22733
  async function installUpdate(version) {
21910
22734
  try {
21911
- const { stdout, stderr } = await execAsync4(
22735
+ const { stdout, stderr } = await execAsync2(
21912
22736
  `npm install -g @defai.digital/automatosx@${version}`,
21913
22737
  { maxBuffer: 10 * 1024 * 1024 }
21914
22738
  );
@@ -23900,11 +24724,11 @@ function expand_(str, isTop) {
23900
24724
  if (pad) {
23901
24725
  const need = width - c.length;
23902
24726
  if (need > 0) {
23903
- const z = new Array(need + 1).join("0");
24727
+ const z4 = new Array(need + 1).join("0");
23904
24728
  if (i < 0) {
23905
- c = "-" + z + c.slice(1);
24729
+ c = "-" + z4 + c.slice(1);
23906
24730
  } else {
23907
- c = z + c;
24731
+ c = z4 + c;
23908
24732
  }
23909
24733
  }
23910
24734
  }
@@ -40600,9 +41424,9 @@ var doctorCommand2 = {
40600
41424
  describe: "Run diagnostic checks and validate system setup",
40601
41425
  builder: (yargs2) => {
40602
41426
  return yargs2.positional("provider", {
40603
- describe: "Check specific provider (openai, gemini, claude) or all if omitted",
41427
+ describe: "Check specific provider (openai, gemini, claude, grok) or all if omitted",
40604
41428
  type: "string",
40605
- choices: ["openai", "gemini", "claude"]
41429
+ choices: ["openai", "gemini", "claude", "grok"]
40606
41430
  }).option("verbose", {
40607
41431
  describe: "Show detailed diagnostic information",
40608
41432
  type: "boolean",
@@ -40638,7 +41462,7 @@ var doctorCommand2 = {
40638
41462
  details: error.message
40639
41463
  });
40640
41464
  }
40641
- const providersToCheck = argv.provider ? [argv.provider] : ["openai", "gemini", "claude"];
41465
+ const providersToCheck = argv.provider ? [argv.provider] : ["openai", "gemini", "claude", "grok"];
40642
41466
  const verbose = argv.verbose ?? false;
40643
41467
  for (const provider of providersToCheck) {
40644
41468
  if (config && !config.providers[provider]?.enabled) {
@@ -40655,6 +41479,8 @@ ${getProviderEmoji(provider)} ${capitalize(provider)} Provider`));
40655
41479
  results.push(...await checkGeminiProvider(verbose));
40656
41480
  } else if (provider === "claude") {
40657
41481
  results.push(...await checkClaudeProvider(verbose));
41482
+ } else if (provider === "grok") {
41483
+ results.push(...await checkGrokProvider(verbose));
40658
41484
  }
40659
41485
  }
40660
41486
  console.log(chalk5.bold("\n\u{1F4C1} File System"));
@@ -40702,17 +41528,6 @@ async function checkOpenAIProvider(verbose) {
40702
41528
  details: verbose ? authCheck.details : void 0
40703
41529
  });
40704
41530
  }
40705
- if (cliCheck.success) {
40706
- const connCheck = await checkAPIConnectivity2("https://api.openai.com/v1/models");
40707
- results.push({
40708
- name: "API Connectivity",
40709
- category: "OpenAI",
40710
- passed: connCheck.success,
40711
- message: connCheck.message,
40712
- fix: connCheck.success ? void 0 : "Check firewall/proxy settings\n OR: export AUTOMATOSX_CLI_ONLY=true (for CLI-only mode)",
40713
- details: verbose ? connCheck.details : void 0
40714
- });
40715
- }
40716
41531
  results.forEach((r) => displayCheck(r));
40717
41532
  return results;
40718
41533
  }
@@ -40728,14 +41543,14 @@ async function checkGeminiProvider(verbose) {
40728
41543
  details: verbose ? cliCheck.error : void 0
40729
41544
  });
40730
41545
  if (cliCheck.success) {
40731
- const authCheck = await checkCommand("gemini", "models list");
41546
+ const helpCheck = await checkCommand("gemini", "--help");
40732
41547
  results.push({
40733
- name: "Authentication",
41548
+ name: "CLI Ready",
40734
41549
  category: "Gemini",
40735
- passed: authCheck.success,
40736
- message: authCheck.success ? "Authenticated" : "Authentication failed",
40737
- fix: authCheck.success ? void 0 : "Run: gemini auth login",
40738
- details: verbose ? authCheck.error : void 0
41550
+ passed: helpCheck.success,
41551
+ message: helpCheck.success ? "CLI is functional" : "CLI not responding",
41552
+ fix: helpCheck.success ? void 0 : "Check Gemini CLI installation: npm install -g @google/generative-ai-cli",
41553
+ details: verbose ? helpCheck.success ? "Gemini CLI uses API keys from environment or config" : helpCheck.error : void 0
40739
41554
  });
40740
41555
  }
40741
41556
  results.forEach((r) => displayCheck(r));
@@ -40753,14 +41568,39 @@ async function checkClaudeProvider(verbose) {
40753
41568
  details: verbose ? cliCheck.error : void 0
40754
41569
  });
40755
41570
  if (cliCheck.success) {
40756
- const authCheck = await checkCommand("claude", "auth whoami");
41571
+ const helpCheck = await checkCommand("claude", "--help");
40757
41572
  results.push({
40758
- name: "Authentication",
41573
+ name: "CLI Ready",
40759
41574
  category: "Claude",
40760
- passed: authCheck.success,
40761
- message: authCheck.success ? "Authenticated" : "Not authenticated",
40762
- fix: authCheck.success ? void 0 : "Run: claude auth login",
40763
- details: verbose ? authCheck.error : void 0
41575
+ passed: helpCheck.success,
41576
+ message: helpCheck.success ? "CLI is functional" : "CLI not responding",
41577
+ fix: helpCheck.success ? void 0 : "Check Claude Code CLI installation",
41578
+ details: verbose ? helpCheck.success ? "Claude Code CLI authenticated via desktop app" : helpCheck.error : void 0
41579
+ });
41580
+ }
41581
+ results.forEach((r) => displayCheck(r));
41582
+ return results;
41583
+ }
41584
+ async function checkGrokProvider(verbose) {
41585
+ const results = [];
41586
+ const cliCheck = await checkCommand("grok", "--version");
41587
+ results.push({
41588
+ name: "CLI Installation",
41589
+ category: "Grok",
41590
+ passed: cliCheck.success,
41591
+ message: cliCheck.success ? `Installed: ${cliCheck.output?.trim() || "version unknown"}` : "Grok CLI not found",
41592
+ fix: cliCheck.success ? void 0 : "npm install -g @vibe-kit/grok-cli",
41593
+ details: verbose ? cliCheck.error : void 0
41594
+ });
41595
+ if (cliCheck.success) {
41596
+ const helpCheck = await checkCommand("grok", "--help");
41597
+ results.push({
41598
+ name: "CLI Ready",
41599
+ category: "Grok",
41600
+ passed: helpCheck.success,
41601
+ message: helpCheck.success ? "CLI is functional" : "CLI not responding",
41602
+ fix: helpCheck.success ? void 0 : "Check Grok CLI installation: npm install -g @vibe-kit/grok-cli",
41603
+ details: verbose ? helpCheck.success ? "Grok CLI uses API keys from environment (GROK_API_KEY) or config files" : helpCheck.error : void 0
40764
41604
  });
40765
41605
  }
40766
41606
  results.forEach((r) => displayCheck(r));
@@ -40828,69 +41668,39 @@ async function checkCommand(command, args) {
40828
41668
  }
40829
41669
  }
40830
41670
  async function checkOpenAIAuth() {
40831
- if (process.env.OPENAI_API_KEY) {
40832
- return {
40833
- success: true,
40834
- message: "API key configured",
40835
- details: "OPENAI_API_KEY environment variable is set"
40836
- };
40837
- }
40838
41671
  try {
40839
- execSync('codex exec "test" --max-tokens 1', {
41672
+ const output = execSync("codex login status 2>&1", {
40840
41673
  encoding: "utf-8",
40841
- stdio: ["pipe", "pipe", "pipe"],
40842
41674
  timeout: 1e4
40843
41675
  });
40844
- return {
40845
- success: true,
40846
- message: "Authenticated via CLI",
40847
- details: "Successfully executed test command"
40848
- };
40849
- } catch (error) {
40850
- const errorMsg = error.message.toLowerCase();
40851
- if (errorMsg.includes("unauthorized") || errorMsg.includes("401")) {
41676
+ const statusText = output.toLowerCase();
41677
+ if (statusText.includes("logged in") || statusText.includes("authenticated")) {
40852
41678
  return {
40853
- success: false,
40854
- message: "Not authenticated",
40855
- fix: 'Run: codex login\n OR: export OPENAI_API_KEY="sk-..."',
40856
- details: "Test command returned unauthorized"
41679
+ success: true,
41680
+ message: "Authenticated via CLI",
41681
+ details: output.trim()
40857
41682
  };
40858
41683
  }
40859
41684
  return {
40860
41685
  success: false,
40861
- message: "Cannot verify authentication",
40862
- fix: 'Run: codex login\n OR: export OPENAI_API_KEY="sk-..."',
40863
- details: errorMsg
40864
- };
40865
- }
40866
- }
40867
- async function checkAPIConnectivity2(url) {
40868
- try {
40869
- const controller = new AbortController();
40870
- const timeout = setTimeout(() => controller.abort(), 5e3);
40871
- const response = await fetch(url, {
40872
- method: "HEAD",
40873
- signal: controller.signal
40874
- });
40875
- clearTimeout(timeout);
40876
- return {
40877
- success: response.ok || response.status === 401,
40878
- // 401 means we reached API
40879
- message: response.ok || response.status === 401 ? "Connected" : `HTTP ${response.status}`,
40880
- details: `Status: ${response.status} ${response.statusText}`
41686
+ message: "Not authenticated",
41687
+ fix: "Run: codex login",
41688
+ details: output.trim()
40881
41689
  };
40882
41690
  } catch (error) {
40883
- const errorMsg = error.message;
40884
- if (errorMsg.includes("aborted")) {
41691
+ const errorMsg = error.message.toLowerCase();
41692
+ if (errorMsg.includes("not logged in") || errorMsg.includes("not authenticated")) {
40885
41693
  return {
40886
41694
  success: false,
40887
- message: "Connection timeout",
40888
- details: "Request timed out after 5 seconds"
41695
+ message: "Not authenticated",
41696
+ fix: "Run: codex login",
41697
+ details: "codex login status: not logged in"
40889
41698
  };
40890
41699
  }
40891
41700
  return {
40892
41701
  success: false,
40893
- message: "Cannot connect",
41702
+ message: "Cannot verify authentication",
41703
+ fix: "Run: codex login",
40894
41704
  details: errorMsg
40895
41705
  };
40896
41706
  }
@@ -40943,6 +41753,8 @@ function getProviderEmoji(provider) {
40943
41753
  return "\u2728";
40944
41754
  case "claude":
40945
41755
  return "\u{1F9E0}";
41756
+ case "grok":
41757
+ return "\u{1F680}";
40946
41758
  default:
40947
41759
  return "\u{1F527}";
40948
41760
  }
@@ -40954,7 +41766,7 @@ function capitalize(str) {
40954
41766
  // src/cli/commands/cleanup.ts
40955
41767
  init_esm_shims();
40956
41768
  init_logger();
40957
- var execAsync5 = promisify(exec);
41769
+ var execAsync3 = promisify(exec);
40958
41770
  var cleanupCommand2 = {
40959
41771
  command: "cleanup [provider]",
40960
41772
  describe: "Clean up orphaned provider processes (v6.0.7 Phase 3)",
@@ -41083,7 +41895,7 @@ async function findProcesses(processName, verbose) {
41083
41895
  throw new Error(`Invalid process name: ${processName}. Only alphanumeric characters, dashes, and underscores are allowed.`);
41084
41896
  }
41085
41897
  try {
41086
- const { stdout } = await execAsync5("ps -eo pid,comm,etime,rss");
41898
+ const { stdout } = await execAsync3("ps -eo pid,comm,etime,rss");
41087
41899
  if (!stdout.trim()) {
41088
41900
  return processes;
41089
41901
  }