@xagent-ai/cli 1.3.0 → 1.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.
Files changed (190) hide show
  1. package/.github/release.yml +76 -0
  2. package/.github/workflows/ci.yml +3 -0
  3. package/.github/workflows/release.yml +11 -17
  4. package/README.md +2 -2
  5. package/README_CN.md +2 -2
  6. package/dist/agents.d.ts.map +1 -1
  7. package/dist/agents.js +7 -3
  8. package/dist/agents.js.map +1 -1
  9. package/dist/ai-client/factory.d.ts +0 -12
  10. package/dist/ai-client/factory.d.ts.map +1 -1
  11. package/dist/ai-client/factory.js +0 -32
  12. package/dist/ai-client/factory.js.map +1 -1
  13. package/dist/ai-client/index.js +1 -1
  14. package/dist/ai-client/index.js.map +1 -1
  15. package/dist/ai-client/providers/anthropic.d.ts.map +1 -1
  16. package/dist/ai-client/providers/anthropic.js +10 -4
  17. package/dist/ai-client/providers/anthropic.js.map +1 -1
  18. package/dist/ai-client/providers/openai.d.ts.map +1 -1
  19. package/dist/ai-client/providers/openai.js +8 -4
  20. package/dist/ai-client/providers/openai.js.map +1 -1
  21. package/dist/ai-client/providers/remote.d.ts +0 -1
  22. package/dist/ai-client/providers/remote.d.ts.map +1 -1
  23. package/dist/ai-client/providers/remote.js +11 -10
  24. package/dist/ai-client/providers/remote.js.map +1 -1
  25. package/dist/ai-client/types.d.ts +14 -0
  26. package/dist/ai-client/types.d.ts.map +1 -1
  27. package/dist/ai-client/types.js +17 -0
  28. package/dist/ai-client/types.js.map +1 -1
  29. package/dist/ai-client-factory.d.ts.map +1 -1
  30. package/dist/ai-client-factory.js +4 -4
  31. package/dist/ai-client-factory.js.map +1 -1
  32. package/dist/auth.d.ts.map +1 -1
  33. package/dist/auth.js +10 -12
  34. package/dist/auth.js.map +1 -1
  35. package/dist/cancellation.d.ts.map +1 -1
  36. package/dist/cancellation.js +3 -5
  37. package/dist/cancellation.js.map +1 -1
  38. package/dist/checkpoint.d.ts +1 -0
  39. package/dist/checkpoint.d.ts.map +1 -1
  40. package/dist/checkpoint.js +38 -4
  41. package/dist/checkpoint.js.map +1 -1
  42. package/dist/cli.js +132 -32
  43. package/dist/cli.js.map +1 -1
  44. package/dist/config.js +1 -1
  45. package/dist/config.js.map +1 -1
  46. package/dist/context-compressor.d.ts +1 -2
  47. package/dist/context-compressor.d.ts.map +1 -1
  48. package/dist/context-compressor.js +22 -17
  49. package/dist/context-compressor.js.map +1 -1
  50. package/dist/conversation.d.ts +1 -1
  51. package/dist/conversation.d.ts.map +1 -1
  52. package/dist/conversation.js +8 -7
  53. package/dist/conversation.js.map +1 -1
  54. package/dist/gui-subagent/action-parser/actionParser.js +2 -2
  55. package/dist/gui-subagent/action-parser/actionParser.js.map +1 -1
  56. package/dist/gui-subagent/agent/gui-agent.d.ts +10 -0
  57. package/dist/gui-subagent/agent/gui-agent.d.ts.map +1 -1
  58. package/dist/gui-subagent/agent/gui-agent.js +105 -32
  59. package/dist/gui-subagent/agent/gui-agent.js.map +1 -1
  60. package/dist/gui-subagent/index.d.ts +7 -0
  61. package/dist/gui-subagent/index.d.ts.map +1 -1
  62. package/dist/gui-subagent/index.js +2 -0
  63. package/dist/gui-subagent/index.js.map +1 -1
  64. package/dist/gui-subagent/operator/computer-operator.d.ts.map +1 -1
  65. package/dist/gui-subagent/operator/computer-operator.js +2 -0
  66. package/dist/gui-subagent/operator/computer-operator.js.map +1 -1
  67. package/dist/input-processor.js +2 -2
  68. package/dist/input-processor.js.map +1 -1
  69. package/dist/logger.d.ts.map +1 -1
  70. package/dist/logger.js +1 -1
  71. package/dist/logger.js.map +1 -1
  72. package/dist/mcp.d.ts +2 -1
  73. package/dist/mcp.d.ts.map +1 -1
  74. package/dist/mcp.js +84 -21
  75. package/dist/mcp.js.map +1 -1
  76. package/dist/memory.d.ts.map +1 -1
  77. package/dist/memory.js +3 -3
  78. package/dist/memory.js.map +1 -1
  79. package/dist/output-util.d.ts +27 -0
  80. package/dist/output-util.d.ts.map +1 -0
  81. package/dist/output-util.js +74 -0
  82. package/dist/output-util.js.map +1 -0
  83. package/dist/retry.js +1 -1
  84. package/dist/retry.js.map +1 -1
  85. package/dist/ripgrep.d.ts.map +1 -1
  86. package/dist/ripgrep.js +5 -3
  87. package/dist/ripgrep.js.map +1 -1
  88. package/dist/sdk-output-adapter.d.ts +265 -0
  89. package/dist/sdk-output-adapter.d.ts.map +1 -0
  90. package/dist/sdk-output-adapter.js +701 -0
  91. package/dist/sdk-output-adapter.js.map +1 -0
  92. package/dist/sdk-session.d.ts +13 -0
  93. package/dist/sdk-session.d.ts.map +1 -0
  94. package/dist/sdk-session.js +50 -0
  95. package/dist/sdk-session.js.map +1 -0
  96. package/dist/session-manager.js +3 -3
  97. package/dist/session-manager.js.map +1 -1
  98. package/dist/session.d.ts +96 -2
  99. package/dist/session.d.ts.map +1 -1
  100. package/dist/session.js +849 -262
  101. package/dist/session.js.map +1 -1
  102. package/dist/shell.d.ts.map +1 -1
  103. package/dist/shell.js +5 -4
  104. package/dist/shell.js.map +1 -1
  105. package/dist/skill-installer.js +3 -3
  106. package/dist/skill-installer.js.map +1 -1
  107. package/dist/skill-invoker.d.ts +1 -1
  108. package/dist/skill-invoker.d.ts.map +1 -1
  109. package/dist/skill-invoker.js +2 -2
  110. package/dist/skill-invoker.js.map +1 -1
  111. package/dist/skill-loader.js +6 -5
  112. package/dist/skill-loader.js.map +1 -1
  113. package/dist/skill-manager.d.ts.map +1 -1
  114. package/dist/skill-manager.js +3 -2
  115. package/dist/skill-manager.js.map +1 -1
  116. package/dist/slash-commands.d.ts +1 -1
  117. package/dist/slash-commands.d.ts.map +1 -1
  118. package/dist/slash-commands.js +24 -11
  119. package/dist/slash-commands.js.map +1 -1
  120. package/dist/smart-approval.d.ts +20 -1
  121. package/dist/smart-approval.d.ts.map +1 -1
  122. package/dist/smart-approval.js +58 -1
  123. package/dist/smart-approval.js.map +1 -1
  124. package/dist/system-prompt-generator.js +3 -3
  125. package/dist/system-prompt-generator.js.map +1 -1
  126. package/dist/theme.d.ts.map +1 -1
  127. package/dist/theme.js +9 -8
  128. package/dist/theme.js.map +1 -1
  129. package/dist/tools.d.ts +15 -0
  130. package/dist/tools.d.ts.map +1 -1
  131. package/dist/tools.js +487 -215
  132. package/dist/tools.js.map +1 -1
  133. package/dist/types.d.ts +57 -0
  134. package/dist/types.d.ts.map +1 -1
  135. package/dist/types.js +49 -0
  136. package/dist/types.js.map +1 -1
  137. package/dist/update.d.ts.map +1 -1
  138. package/dist/update.js +12 -9
  139. package/dist/update.js.map +1 -1
  140. package/dist/workflow.d.ts.map +1 -1
  141. package/dist/workflow.js +1 -2
  142. package/dist/workflow.js.map +1 -1
  143. package/docs/third-party-models.md +16 -15
  144. package/package.json +3 -1
  145. package/src/agents.ts +7 -3
  146. package/src/ai-client/factory.ts +1 -36
  147. package/src/ai-client/index.ts +1 -1
  148. package/src/ai-client/providers/anthropic.ts +12 -3
  149. package/src/ai-client/providers/openai.ts +10 -4
  150. package/src/ai-client/providers/remote.ts +13 -10
  151. package/src/ai-client/types.ts +19 -0
  152. package/src/ai-client-factory.ts +5 -5
  153. package/src/auth.ts +11 -13
  154. package/src/cancellation.ts +3 -6
  155. package/src/checkpoint.ts +41 -4
  156. package/src/cli.ts +154 -37
  157. package/src/config.ts +1 -1
  158. package/src/context-compressor.ts +27 -22
  159. package/src/conversation.ts +9 -7
  160. package/src/gui-subagent/action-parser/actionParser.ts +2 -2
  161. package/src/gui-subagent/agent/gui-agent.ts +117 -34
  162. package/src/gui-subagent/index.ts +8 -0
  163. package/src/gui-subagent/operator/computer-operator.ts +2 -1
  164. package/src/input-processor.ts +2 -2
  165. package/src/logger.ts +2 -4
  166. package/src/mcp.ts +87 -23
  167. package/src/memory.ts +3 -4
  168. package/src/output-util.ts +80 -0
  169. package/src/retry.ts +1 -1
  170. package/src/ripgrep.ts +5 -3
  171. package/src/sdk-output-adapter.ts +842 -0
  172. package/src/sdk-session.ts +62 -0
  173. package/src/session-manager.ts +3 -3
  174. package/src/session.ts +942 -302
  175. package/src/shell.ts +6 -5
  176. package/src/skill-installer.ts +3 -3
  177. package/src/skill-invoker.ts +3 -4
  178. package/src/skill-loader.ts +7 -7
  179. package/src/skill-manager.ts +4 -3
  180. package/src/slash-commands.ts +24 -16
  181. package/src/smart-approval.ts +76 -1
  182. package/src/system-prompt-generator.ts +3 -3
  183. package/src/theme.ts +10 -9
  184. package/src/tools.ts +563 -267
  185. package/src/types.ts +118 -0
  186. package/src/update.ts +12 -9
  187. package/src/workflow.ts +2 -4
  188. package/test/cli-launch.test.ts +279 -0
  189. package/vitest.config.ts +2 -0
  190. /package/{.eslintrc.js → .eslintrc.cjs} +0 -0
package/src/cli.ts CHANGED
@@ -1,7 +1,6 @@
1
1
  #!/usr/bin/env node
2
2
 
3
3
  import { Command } from 'commander';
4
- import chalk from 'chalk';
5
4
  import { confirm } from '@clack/prompts';
6
5
  import { startInteractiveSession } from './session.js';
7
6
  import { getConfigManager } from './config.js';
@@ -10,14 +9,13 @@ import { AuthType } from './types.js';
10
9
  import { fetchDefaultModels } from './ai-client/providers/remote.js';
11
10
  import { getAgentManager } from './agents.js';
12
11
  import { getMCPManager } from './mcp.js';
13
- import { getLogger, setConfigProvider } from './logger.js';
14
- import { theme, icons, colors } from './theme.js';
12
+ import { setConfigProvider } from './logger.js';
13
+ import { icons, colors } from './theme.js';
15
14
  import { getCancellationManager } from './cancellation.js';
16
- import { readFileSync, promises as fs, writeFileSync, existsSync } from 'fs';
15
+ import { readFileSync, promises as fs } from 'fs';
17
16
  import path from 'path';
18
17
  import { dirname, join } from 'path';
19
18
  import { fileURLToPath } from 'url';
20
- import { glob } from 'glob';
21
19
 
22
20
  // Get current directory
23
21
  const __filename = fileURLToPath(import.meta.url);
@@ -39,7 +37,7 @@ async function notifySkillUpdate(userSkillsPath: string): Promise<void> {
39
37
  await fs.writeFile(stateFilePath, JSON.stringify(state, null, 2), 'utf-8');
40
38
 
41
39
  console.log(colors.textMuted(' ℹ️ Skills updated for running xAgent sessions'));
42
- } catch (error) {
40
+ } catch {
43
41
  // Silent fail - notification is optional
44
42
  }
45
43
  }
@@ -48,8 +46,6 @@ async function notifySkillUpdate(userSkillsPath: string): Promise<void> {
48
46
  const packageJsonPath = join(__dirname, '../package.json');
49
47
  const packageJson = JSON.parse(readFileSync(packageJsonPath, 'utf-8'));
50
48
 
51
- const logger = getLogger();
52
-
53
49
  // Initialize CancellationManager early to set up ESC handler
54
50
  getCancellationManager();
55
51
 
@@ -167,7 +163,15 @@ program
167
163
  .command('start')
168
164
  .description('Start the xAgent CLI interactive session')
169
165
  .option('--approval-mode <mode>', 'Set approval mode (yolo, accept_edits, plan, default, smart)')
166
+ .option('--sdk', 'Run in SDK mode for programmatic access (stdin/stdout JSON communication)')
170
167
  .action(async (options) => {
168
+ // Check if running in SDK mode
169
+ if (options.sdk || process.env.XAGENT_SDK === 'true') {
170
+ const { startSdkSession } = await import('./sdk-session.js');
171
+ await startSdkSession();
172
+ return;
173
+ }
174
+
171
175
  if (options.approvalMode) {
172
176
  const { getConfigManager } = await import('./config.js');
173
177
  const { ExecutionMode } = await import('./types.js');
@@ -261,6 +265,7 @@ program
261
265
  console.log(colors.success('Authentication configured successfully!'));
262
266
  console.log(colors.textMuted('You can now run "xagent start" to begin'));
263
267
  console.log('');
268
+ process.exit(0);
264
269
  } else {
265
270
  console.log('');
266
271
  console.log(colors.error('Authentication failed. Please try again.'));
@@ -302,6 +307,7 @@ program
302
307
  console.log('');
303
308
  });
304
309
  }
310
+ process.exit(0);
305
311
  } else if (options.add) {
306
312
  console.log('');
307
313
  console.log(colors.warning('Agent creation wizard not implemented yet'));
@@ -329,8 +335,9 @@ program
329
335
 
330
336
  program
331
337
  .command('mcp')
332
- .description('Add, list, or remove MCP servers')
338
+ .description('Add, list, get, or remove MCP servers')
333
339
  .option('-l, --list', 'List all MCP servers')
340
+ .option('-g, --get <name>', 'Get details of a specific MCP server')
334
341
  .option('-a, --add [name]', 'Add a new MCP server (interactive if no name provided)')
335
342
  .option('-r, --remove <name>', 'Remove an MCP server')
336
343
  .option('--scope <scope>', 'Scope (global or project)', 'global')
@@ -342,34 +349,110 @@ program
342
349
  .option('--header <headers>', 'Custom headers (can be used multiple times)')
343
350
  .option('-y, --yes', 'Skip confirmation')
344
351
  .action(async (options) => {
352
+ if (options.help) {
353
+ program.parse(['node', 'mcp', '--help']);
354
+ return;
355
+ }
356
+
345
357
  const configManager = getConfigManager(process.cwd());
358
+ configManager.load(); // Load config from file
346
359
  const mcpManager = getMCPManager();
347
360
 
361
+ // Register all MCP servers from config to manager (for --list and --remove)
362
+ const mcpServers = configManager.getMcpServers();
363
+ Object.entries(mcpServers).forEach(([name, config]) => {
364
+ mcpManager.registerServer(name, config);
365
+ });
366
+
348
367
  if (options.list) {
349
- const servers = mcpManager.getAllServers();
368
+ const mcpServers = configManager.getMcpServers();
369
+ const serverNames = Object.keys(mcpServers);
350
370
 
351
- if (servers.length === 0) {
371
+ if (serverNames.length === 0) {
352
372
  console.log('');
353
373
  console.log(colors.warning('No MCP servers configured'));
354
374
  console.log(colors.textMuted('Use "xagent mcp --add" to add servers'));
355
375
  console.log('');
356
376
  } else {
377
+ console.log(colors.textMuted('Connecting to MCP servers...'));
378
+
379
+ for (const name of serverNames) {
380
+ try {
381
+ await mcpManager.connectServer(name);
382
+ } catch {
383
+ // Connection failed, continue with next server
384
+ }
385
+ }
386
+
357
387
  const separator = icons.separator.repeat(40);
358
388
  console.log('');
359
389
  console.log(colors.primaryBright(`${icons.tool} MCP Servers`));
360
390
  console.log(colors.border(separator));
361
391
  console.log('');
362
392
 
363
- servers.forEach((server, index) => {
364
- const connected = server.isServerConnected() ? icons.success : icons.error;
365
- const status = server.isServerConnected() ? colors.success(connected) : colors.error(connected);
366
- const toolNames = server.getToolNames().join(', ');
393
+ serverNames.forEach((name) => {
394
+ const server = mcpManager.getServer(name);
395
+ const connected = server?.isServerConnected() ? icons.success : icons.error;
396
+ const status = server?.isServerConnected() ? colors.success(connected) : colors.error(connected);
397
+ const toolNames = server?.getToolNames().join(', ') || '';
367
398
 
368
- console.log(` ${status} ${colors.primaryBright(`Server ${index + 1}`)}`);
369
- console.log(` ${colors.textDim(` Tools: ${toolNames}`)}`);
399
+ console.log(` ${status} ${colors.primaryBright(name)}`);
400
+ console.log(` ${colors.textDim(`Tools: ${toolNames}`)}`);
370
401
  console.log('');
371
402
  });
372
403
  }
404
+ process.exit(0);
405
+ } else if (options.get) {
406
+ const server = mcpManager.getServer(options.get);
407
+
408
+ if (!server) {
409
+ console.log('');
410
+ console.log(colors.error(`MCP server '${options.get}' not found`));
411
+ console.log(colors.textMuted('Use "xagent mcp --list" to see all configured servers'));
412
+ console.log('');
413
+ process.exit(1);
414
+ }
415
+
416
+ const config = (server as any).config;
417
+ const isConnected = server.isServerConnected();
418
+ const toolNames = server.getToolNames();
419
+ const tools = server.getTools();
420
+
421
+ console.log('');
422
+ console.log(colors.primaryBright(`${icons.tool} MCP Server: ${options.get}`));
423
+ console.log(colors.border(icons.separator.repeat(40)));
424
+ console.log('');
425
+
426
+ console.log(` ${colors.primaryBright('Status:')} ${isConnected ? colors.success('Connected') : colors.error('Disconnected')}`);
427
+ console.log(` ${colors.primaryBright('Transport:')} ${config.transport || 'stdio'}`);
428
+
429
+ if (config.url) {
430
+ console.log(` ${colors.primaryBright('URL:')} ${config.url}`);
431
+ }
432
+
433
+ if (config.command) {
434
+ console.log(` ${colors.primaryBright('Command:')} ${config.command} ${(config.args || []).join(' ')}`);
435
+ }
436
+
437
+ if (config.headers) {
438
+ console.log(` ${colors.primaryBright('Headers:')} ${JSON.stringify(config.headers)}`);
439
+ }
440
+
441
+ console.log(` ${colors.primaryBright('Tools:')} ${toolNames.length > 0 ? toolNames.join(', ') : colors.textMuted('(none)')}`);
442
+
443
+ if (tools.length > 0) {
444
+ console.log('');
445
+ console.log(colors.textMuted(' Available tools:'));
446
+ tools.forEach((tool: any) => {
447
+ console.log(` - ${colors.primaryBright(tool.name)}`);
448
+ if (tool.description) {
449
+ console.log(` ${colors.textDim(tool.description.substring(0, 60))}${tool.description.length > 60 ? '...' : ''}`);
450
+ }
451
+ });
452
+ }
453
+
454
+ console.log('');
455
+ process.exit(0);
373
456
  } else if (options.add !== undefined) {
374
457
  // Check if running in non-interactive mode (transport and required params provided)
375
458
  const hasTransport = options.transport;
@@ -405,12 +488,14 @@ program
405
488
  process.exit(1);
406
489
  }
407
490
  config.url = options.url;
491
+
492
+ const headers: Record<string, string> = {};
493
+
408
494
  if (options.token) {
409
- config.authToken = options.token;
495
+ headers['Authorization'] = `Bearer ${options.token}`;
410
496
  }
411
- // Handle multiple --header flags
497
+
412
498
  if (options.header) {
413
- const headers: Record<string, string> = {};
414
499
  const headerArray = Array.isArray(options.header) ? options.header : [options.header];
415
500
  for (const h of headerArray) {
416
501
  const colonIndex = h.indexOf(':');
@@ -420,9 +505,10 @@ program
420
505
  headers[key] = value;
421
506
  }
422
507
  }
423
- if (Object.keys(headers).length > 0) {
424
- config.headers = headers;
425
- }
508
+ }
509
+
510
+ if (Object.keys(headers).length > 0) {
511
+ config.headers = headers;
426
512
  }
427
513
  } else {
428
514
  console.log('');
@@ -476,10 +562,12 @@ program
476
562
  console.log(colors.success(`✅ MCP server '${name}' added successfully`));
477
563
  }
478
564
  console.log('');
565
+ process.exit(0);
479
566
  } catch (error: any) {
480
567
  console.log('');
481
568
  console.log(colors.error(`Failed to add MCP server: ${error.message}`));
482
569
  console.log('');
570
+ process.exit(1);
483
571
  }
484
572
  } else {
485
573
  // Interactive mode
@@ -566,12 +654,18 @@ program
566
654
  }
567
655
  config.url = url;
568
656
 
657
+ const headers: Record<string, string> = {};
658
+
569
659
  // Step 4: Enter auth token (optional)
570
- config.authToken = await text({
660
+ const authToken = await text({
571
661
  message: 'Enter Bearer token (optional):',
572
662
  defaultValue: '',
573
663
  }) as string;
574
664
 
665
+ if (authToken.trim()) {
666
+ headers['Authorization'] = `Bearer ${authToken}`;
667
+ }
668
+
575
669
  // Step 5: Enter custom headers (optional)
576
670
  const headersInput = await text({
577
671
  message: 'Enter custom headers as JSON (optional):',
@@ -580,11 +674,16 @@ program
580
674
 
581
675
  if (headersInput.trim()) {
582
676
  try {
583
- config.headers = JSON.parse(headersInput);
677
+ const customHeaders = JSON.parse(headersInput);
678
+ Object.assign(headers, customHeaders);
584
679
  } catch {
585
680
  // Ignore invalid JSON
586
681
  }
587
682
  }
683
+
684
+ if (Object.keys(headers).length > 0) {
685
+ config.headers = headers;
686
+ }
588
687
  }
589
688
 
590
689
  // Step 6: Confirm and save
@@ -652,19 +751,22 @@ program
652
751
  console.log('');
653
752
  console.log(colors.success(`MCP server ${options.remove} removed successfully`));
654
753
  console.log('');
754
+ process.exit(0);
655
755
  } catch (error: any) {
656
756
  const { message, suggestion } = formatError(error);
657
757
  console.log('');
658
758
  console.log(colors.error(`Failed to remove MCP server: ${message}`));
659
759
  console.log(colors.textMuted(suggestion));
660
760
  console.log('');
761
+ process.exit(1);
661
762
  }
662
763
  } else {
663
764
  console.log('');
664
- console.log(colors.warning('Please specify an action: --list, --add, or --remove'));
765
+ console.log(colors.warning('Please specify an action: --list, --get, --add, or --remove'));
665
766
  console.log('');
666
767
  console.log(colors.textMuted('Usage:'));
667
768
  console.log(` ${colors.primaryBright('xagent mcp --list')} ${colors.textMuted('| List all MCP servers')}`);
769
+ console.log(` ${colors.primaryBright('xagent mcp --get <name>')} ${colors.textMuted('| Get MCP server details')}`);
668
770
  console.log(` ${colors.primaryBright('xagent mcp --add')} ${colors.textMuted('| Add MCP server (interactive)')}`);
669
771
  console.log('');
670
772
  console.log(colors.textMuted('Non-interactive examples:'));
@@ -680,6 +782,7 @@ program
680
782
  console.log(` ${colors.primaryBright('--header')} ${colors.textMuted('Custom header (key:value)')}`);
681
783
  console.log(` ${colors.primaryBright('-y, --yes')} ${colors.textMuted('Skip confirmation')}`);
682
784
  console.log('');
785
+ process.exit(1);
683
786
  }
684
787
  });
685
788
 
@@ -701,6 +804,7 @@ program
701
804
  console.log(colors.success('Project initialized successfully!'));
702
805
  console.log(colors.textMuted('You can now run "xagent start" to begin'));
703
806
  console.log('');
807
+ process.exit(0);
704
808
  } catch (error: any) {
705
809
  const { message, suggestion } = formatError(error);
706
810
  console.log(colors.error(`Initialization failed: ${message}`));
@@ -729,6 +833,7 @@ program
729
833
  console.log(colors.warning('No workflows installed'));
730
834
  console.log(colors.textMuted('Use --add to install workflows from the marketplace'));
731
835
  console.log('');
836
+ process.exit(0);
732
837
  } else {
733
838
  const separator = icons.separator.repeat(40);
734
839
  console.log('');
@@ -742,6 +847,7 @@ program
742
847
  console.log(` ${colors.textDim(` ${workflow.description}`)}`);
743
848
  console.log('');
744
849
  });
850
+ process.exit(0);
745
851
  }
746
852
  } else if (options.add) {
747
853
  try {
@@ -749,6 +855,7 @@ program
749
855
  console.log('');
750
856
  console.log(colors.success(`Workflow ${options.add} added successfully!`));
751
857
  console.log('');
858
+ process.exit(0);
752
859
  } catch (error: any) {
753
860
  const { message, suggestion } = formatError(error);
754
861
  console.log('');
@@ -763,6 +870,7 @@ program
763
870
  console.log('');
764
871
  console.log(colors.success(`Workflow ${options.remove} removed successfully!`));
765
872
  console.log('');
873
+ process.exit(0);
766
874
  } catch (error: any) {
767
875
  const { message, suggestion } = formatError(error);
768
876
  console.log('');
@@ -775,6 +883,7 @@ program
775
883
  console.log('');
776
884
  console.log(colors.warning('Please specify an action: --list, --add, or --remove'));
777
885
  console.log('');
886
+ process.exit(1);
778
887
  }
779
888
  });
780
889
 
@@ -789,13 +898,13 @@ program
789
898
  const configManager = getConfigManager();
790
899
  const { promises: fs } = await import('fs');
791
900
  const pathModule = await import('path');
792
- const { exec, spawn } = await import('child_process');
901
+ const { exec } = await import('child_process');
793
902
  const { promisify } = await import('util');
794
903
  const os = await import('os');
795
904
 
796
- const execAsync = promisify(exec);
905
+ const _execAsync = promisify(exec);
797
906
  const userSkillsPath = configManager.getUserSkillsPath() || pathModule.join(os.homedir(), '.xagent', 'skills');
798
- const userNodeModulesPath = configManager.getUserNodeModulesPath() || pathModule.join(os.homedir(), '.xagent', 'node_modules');
907
+ const _userNodeModulesPath = configManager.getUserNodeModulesPath() || pathModule.join(os.homedir(), '.xagent', 'node_modules');
799
908
 
800
909
  if (options.add) {
801
910
  const separator = icons.separator.repeat(40);
@@ -858,6 +967,7 @@ program
858
967
  // Notify running xAgent to update system prompt
859
968
  await notifySkillUpdate(userSkillsPath);
860
969
  console.log('');
970
+ process.exit(0);
861
971
  } catch (error: any) {
862
972
  const { message, suggestion } = formatError(error);
863
973
  console.log(colors.error(`Failed to install skill: ${message}`));
@@ -883,6 +993,7 @@ program
883
993
  await notifySkillUpdate(userSkillsPath);
884
994
  console.log(colors.textMuted('Note: Run "xagent start" to use the new skill'));
885
995
  console.log('');
996
+ process.exit(0);
886
997
  } else {
887
998
  console.log(colors.error(`Failed to install skill: ${result.error}`));
888
999
  console.log('');
@@ -937,7 +1048,8 @@ program
937
1048
 
938
1049
  console.log(colors.textMuted(`Skills directory: ${userSkillsPath}`));
939
1050
  console.log('');
940
- } catch (error) {
1051
+ process.exit(0);
1052
+ } catch {
941
1053
  console.log(colors.textMuted('No user skills installed'));
942
1054
  console.log('');
943
1055
  }
@@ -972,7 +1084,8 @@ program
972
1084
  // Notify running xAgent to update system prompt
973
1085
  await notifySkillUpdate(userSkillsPath);
974
1086
  console.log('');
975
- } catch (error) {
1087
+ process.exit(0);
1088
+ } catch {
976
1089
  console.log('');
977
1090
  console.log(colors.error(`Skill not found: ${options.remove}`));
978
1091
  console.log('');
@@ -995,6 +1108,7 @@ program
995
1108
  console.log(colors.textMuted('To install a new skill, use the interactive command:'));
996
1109
  console.log(` ${colors.primaryBright('/skill add')}`);
997
1110
  console.log('');
1111
+ process.exit(0);
998
1112
  }
999
1113
  });
1000
1114
 
@@ -1022,6 +1136,7 @@ program
1022
1136
  console.log(` ${colors.primaryBright('📚 Documentation:')} ${colors.primaryBright('https://platform.xagent.cn/cli/')}`);
1023
1137
  console.log(` ${colors.primaryBright('💻 GitHub:')} ${colors.primaryBright('https://github.com/xagent-ai/xagent-cli')}`);
1024
1138
  console.log('');
1139
+ process.exit(0);
1025
1140
  });
1026
1141
 
1027
1142
  program
@@ -1101,7 +1216,7 @@ program
1101
1216
  };
1102
1217
  }
1103
1218
 
1104
- const guiAgent = await createGUISubAgent({
1219
+ const _guiAgent = await createGUISubAgent({
1105
1220
  headless: options.headless ?? false,
1106
1221
  model: isLocalMode ? modelName : undefined,
1107
1222
  modelBaseUrl: isLocalMode ? baseUrl : undefined,
@@ -1175,7 +1290,7 @@ program
1175
1290
  if (files.length === 0) {
1176
1291
  console.log(colors.textMuted('No memory files found.'));
1177
1292
  console.log('');
1178
- return;
1293
+ process.exit(0);
1179
1294
  }
1180
1295
 
1181
1296
  const globalFile = files.find(f => f === 'global.md');
@@ -1211,7 +1326,7 @@ program
1211
1326
 
1212
1327
  console.log(colors.textMuted(`Total: ${files.length} memory file(s)`));
1213
1328
  console.log('');
1214
- } catch (error) {
1329
+ } catch {
1215
1330
  console.log(colors.textMuted('No memory files found.'));
1216
1331
  console.log('');
1217
1332
  }
@@ -1228,7 +1343,7 @@ program
1228
1343
  if (projectFiles.length === 0) {
1229
1344
  console.log(colors.textMuted('No project memories to clean.'));
1230
1345
  console.log('');
1231
- return;
1346
+ process.exit(0);
1232
1347
  }
1233
1348
 
1234
1349
  let cleaned = 0;
@@ -1292,7 +1407,7 @@ program
1292
1407
  if (files.length === 0) {
1293
1408
  console.log(colors.textMuted('No memory files to clean.'));
1294
1409
  console.log('');
1295
- return;
1410
+ process.exit(0);
1296
1411
  }
1297
1412
 
1298
1413
  let cleaned = 0;
@@ -1363,10 +1478,12 @@ program
1363
1478
  if (shouldUpdate === true) {
1364
1479
  console.log('');
1365
1480
  await updateManager.autoUpdate();
1481
+ process.exit(0);
1366
1482
  }
1367
1483
  } else {
1368
1484
  console.log(colors.success(` ✅ You are using the latest version`));
1369
1485
  console.log('');
1486
+ process.exit(0);
1370
1487
  }
1371
1488
  } catch (error: any) {
1372
1489
  console.log(colors.error(` ❌ Failed to check for updates: ${error.message}`));
@@ -1385,7 +1502,7 @@ if (!process.argv.slice(2).length) {
1385
1502
  // ============================================================
1386
1503
 
1387
1504
  // Handle uncaught promise rejections
1388
- process.on('unhandledRejection', (reason: any, promise: Promise<any>) => {
1505
+ process.on('unhandledRejection', (reason: any, _promise: Promise<any>) => {
1389
1506
  console.error('\n❌ An unexpected error occurred');
1390
1507
  if (reason instanceof Error) {
1391
1508
  console.error(` ${reason.message}`);
package/src/config.ts CHANGED
@@ -9,7 +9,7 @@ const logger = getLogger();
9
9
  // Environment variable support for backend URL configuration
10
10
  // Set these to use local development server instead of cloud
11
11
  const CLOUD_BASE_URL = 'https://www.xagent-colife.net';
12
- const LOCAL_BASE_URL = process.env.XAGENT_BASE_URL || CLOUD_BASE_URL;
12
+ const _LOCAL_BASE_URL = process.env.XAGENT_BASE_URL || CLOUD_BASE_URL;
13
13
 
14
14
  const DEFAULT_SETTINGS: Settings = {
15
15
  theme: 'Default',
@@ -1,8 +1,8 @@
1
- import { ChatMessage, CompressionConfig } from './types.js';
1
+ import { ChatMessage, CompressionConfig, AuthConfig } from './types.js';
2
2
  import type { Message } from './ai-client/types.js';
3
- import { AuthConfig } from './types.js';
4
3
  import { getCancellationManager } from './cancellation.js';
5
4
  import { createAIClient, AIClientInterface } from './ai-client-factory.js';
5
+ import { output as logOutput } from './output-util.js';
6
6
 
7
7
  /**
8
8
  * Model context window sizes (in tokens)
@@ -45,11 +45,13 @@ const MODEL_CONTEXT_WINDOWS: Record<string, number> = {
45
45
  'glm-4': 128000,
46
46
  'glm-4-plus': 128000,
47
47
  'glm-4-air': 128000,
48
- 'glm-4.7': 128000,
48
+ 'glm-4.7': 200000,
49
+ 'glm-5': 200000,
49
50
 
50
51
  // MiniMax
51
- 'MiniMax-M2': 1000000,
52
- 'MiniMax-M2.1': 1000000,
52
+ 'MiniMax-M2': 200000,
53
+ 'MiniMax-M2.1': 200000,
54
+ 'MiniMax-M2.5': 200000,
53
55
 
54
56
  // Moonshot (Kimi)
55
57
  'moonshot-v1-8k': 8192,
@@ -291,9 +293,9 @@ export class ContextCompressor {
291
293
  config?: Partial<CompressionConfig>,
292
294
  modelName?: string
293
295
  ): { needsCompression: boolean; reason: string; tokenCount: number } {
294
- const cfg = { ...this.defaultConfig, ...config };
296
+ const _cfg = { ...this.defaultConfig, ...config };
297
+ const _messageCount = messages.length;
295
298
  const tokenCount = this.estimateContextTokens(messages);
296
- const messageCount = messages.length;
297
299
 
298
300
  // Get model context window
299
301
  const contextWindow = getModelContextWindow(modelName);
@@ -449,8 +451,8 @@ export class ContextCompressor {
449
451
  modified: new Set<string>()
450
452
  };
451
453
 
452
- let totalToolCalls = 0;
453
- let matchedToolCalls = 0;
454
+ let _totalToolCalls = 0;
455
+ let _matchedToolCalls = 0;
454
456
 
455
457
  // Normalize tool name (handle both API format and internal format)
456
458
  const isReadTool = (name: string) => name === 'read_file' || name === 'Read';
@@ -458,17 +460,17 @@ export class ContextCompressor {
458
460
  const isEditTool = (name: string) => name === 'Edit';
459
461
  const isDeleteTool = (name: string) => name === 'DeleteFile';
460
462
 
461
- const getFilePath = (args: any): string => {
462
- return args.filePath || args.absolute_path || args.path || '';
463
+ const getFilePath = (args: Record<string, unknown>): string => {
464
+ return (args.filePath as string) || (args.absolute_path as string) || (args.path as string) || '';
463
465
  };
464
466
 
465
467
  for (const msg of messages) {
466
468
  // Case 1: assistant with tool_calls field
467
469
  if (msg.role === 'assistant' && msg.tool_calls) {
468
470
  for (const toolCall of msg.tool_calls) {
469
- totalToolCalls++;
471
+ _totalToolCalls++;
470
472
  const toolName = toolCall.function?.name || '';
471
- let args = {};
473
+ let args: Record<string, unknown> = {};
472
474
 
473
475
  try {
474
476
  args = JSON.parse(toolCall.function?.arguments || '{}');
@@ -481,10 +483,10 @@ export class ContextCompressor {
481
483
 
482
484
  if (isReadTool(toolName)) {
483
485
  fileOps.read.add(filePath);
484
- matchedToolCalls++;
486
+ _matchedToolCalls++;
485
487
  } else if (isWriteTool(toolName) || isEditTool(toolName) || isDeleteTool(toolName)) {
486
488
  fileOps.modified.add(filePath);
487
- matchedToolCalls++;
489
+ _matchedToolCalls++;
488
490
  }
489
491
  }
490
492
  }
@@ -493,7 +495,7 @@ export class ContextCompressor {
493
495
  if (msg.role === 'tool' && typeof msg.content === 'string') {
494
496
  try {
495
497
  const content = JSON.parse(msg.content);
496
- totalToolCalls++;
498
+ _totalToolCalls++;
497
499
  const toolName = content.name || '';
498
500
  const args = content.parameters || {};
499
501
 
@@ -502,10 +504,10 @@ export class ContextCompressor {
502
504
 
503
505
  if (isReadTool(toolName)) {
504
506
  fileOps.read.add(filePath);
505
- matchedToolCalls++;
507
+ _matchedToolCalls++;
506
508
  } else if (isWriteTool(toolName) || isEditTool(toolName) || isDeleteTool(toolName)) {
507
509
  fileOps.modified.add(filePath);
508
- matchedToolCalls++;
510
+ _matchedToolCalls++;
509
511
  }
510
512
  } catch {
511
513
  // Not JSON, skip
@@ -713,6 +715,7 @@ export class ContextCompressor {
713
715
  throw error;
714
716
  }
715
717
  console.error('Failed to generate summary:', error);
718
+ await logOutput('error', 'Failed to generate summary', { error: error.message });
716
719
  const userCount = messages.filter(m => m.role === 'user').length;
717
720
  const toolCount = messages.filter(m => m.role === 'tool').length;
718
721
  return `[Summary of ${messages.length} messages: ${userCount} user exchanges, ${toolCount} tool calls. Key topics discussed but details unavailable due to summarization error.]`;
@@ -765,6 +768,7 @@ export class ContextCompressor {
765
768
  throw error;
766
769
  }
767
770
  console.error('Failed to generate turn prefix summary:', error);
771
+ await logOutput('error', 'Failed to generate turn prefix summary', { error: error.message });
768
772
  return '[Turn prefix summary unavailable]';
769
773
  }
770
774
  }
@@ -779,10 +783,10 @@ export class ContextCompressor {
779
783
  previousSummary?: string,
780
784
  modelName?: string
781
785
  ): Promise<CompressionResult> {
782
- const cfg = { ...this.defaultConfig, ...config };
786
+ const _cfg = { ...this.defaultConfig, ...config };
783
787
  const originalMessageCount = messages.length;
784
788
  const originalSize = messages.reduce((total, msg) => total + msg.content.length, 0);
785
- const originalTokens = this.estimateContextTokens(messages);
789
+ const _originalTokens = this.estimateContextTokens(messages);
786
790
  const contextWindow = getModelContextWindow(modelName);
787
791
 
788
792
  // Check if compression is needed
@@ -932,8 +936,8 @@ export class ContextCompressor {
932
936
  }
933
937
 
934
938
  const compressedSize = compressedMessages.reduce((total, msg) => total + msg.content.length, 0);
935
- const compressedTokens = this.estimateContextTokens(compressedMessages);
936
- const reductionPercent = Math.round((1 - compressedSize / originalSize) * 100);
939
+ const _compressedTokens = this.estimateContextTokens(compressedMessages);
940
+ const _reductionPercent = Math.round((1 - compressedSize / originalSize) * 100);
937
941
 
938
942
  return {
939
943
  compressedMessages,
@@ -980,3 +984,4 @@ export function getContextCompressor(authConfig?: AuthConfig): ContextCompressor
980
984
  }
981
985
  return compressorInstance;
982
986
  }
987
+