@xagent-ai/cli 1.3.0 → 1.3.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.github/release.yml +76 -0
- package/.github/workflows/ci.yml +3 -0
- package/.github/workflows/release.yml +11 -17
- package/README.md +2 -2
- package/README_CN.md +2 -2
- package/dist/agents.d.ts.map +1 -1
- package/dist/agents.js +7 -3
- package/dist/agents.js.map +1 -1
- package/dist/ai-client/factory.d.ts +0 -12
- package/dist/ai-client/factory.d.ts.map +1 -1
- package/dist/ai-client/factory.js +0 -32
- package/dist/ai-client/factory.js.map +1 -1
- package/dist/ai-client/index.js +1 -1
- package/dist/ai-client/index.js.map +1 -1
- package/dist/ai-client/providers/anthropic.d.ts.map +1 -1
- package/dist/ai-client/providers/anthropic.js +10 -4
- package/dist/ai-client/providers/anthropic.js.map +1 -1
- package/dist/ai-client/providers/openai.d.ts.map +1 -1
- package/dist/ai-client/providers/openai.js +8 -4
- package/dist/ai-client/providers/openai.js.map +1 -1
- package/dist/ai-client/providers/remote.d.ts +0 -1
- package/dist/ai-client/providers/remote.d.ts.map +1 -1
- package/dist/ai-client/providers/remote.js +11 -10
- package/dist/ai-client/providers/remote.js.map +1 -1
- package/dist/ai-client/types.d.ts +14 -0
- package/dist/ai-client/types.d.ts.map +1 -1
- package/dist/ai-client/types.js +17 -0
- package/dist/ai-client/types.js.map +1 -1
- package/dist/ai-client-factory.d.ts.map +1 -1
- package/dist/ai-client-factory.js +4 -4
- package/dist/ai-client-factory.js.map +1 -1
- package/dist/auth.d.ts.map +1 -1
- package/dist/auth.js +10 -12
- package/dist/auth.js.map +1 -1
- package/dist/cancellation.d.ts.map +1 -1
- package/dist/cancellation.js +3 -5
- package/dist/cancellation.js.map +1 -1
- package/dist/checkpoint.d.ts +1 -0
- package/dist/checkpoint.d.ts.map +1 -1
- package/dist/checkpoint.js +37 -4
- package/dist/checkpoint.js.map +1 -1
- package/dist/cli.js +132 -32
- package/dist/cli.js.map +1 -1
- package/dist/config.js +1 -1
- package/dist/config.js.map +1 -1
- package/dist/context-compressor.d.ts +1 -2
- package/dist/context-compressor.d.ts.map +1 -1
- package/dist/context-compressor.js +23 -18
- package/dist/context-compressor.js.map +1 -1
- package/dist/conversation.d.ts +1 -1
- package/dist/conversation.d.ts.map +1 -1
- package/dist/conversation.js +8 -7
- package/dist/conversation.js.map +1 -1
- package/dist/gui-subagent/action-parser/actionParser.js +2 -2
- package/dist/gui-subagent/action-parser/actionParser.js.map +1 -1
- package/dist/gui-subagent/agent/gui-agent.d.ts +10 -0
- package/dist/gui-subagent/agent/gui-agent.d.ts.map +1 -1
- package/dist/gui-subagent/agent/gui-agent.js +105 -32
- package/dist/gui-subagent/agent/gui-agent.js.map +1 -1
- package/dist/gui-subagent/index.d.ts +7 -0
- package/dist/gui-subagent/index.d.ts.map +1 -1
- package/dist/gui-subagent/index.js +2 -0
- package/dist/gui-subagent/index.js.map +1 -1
- package/dist/gui-subagent/operator/computer-operator.d.ts.map +1 -1
- package/dist/gui-subagent/operator/computer-operator.js +2 -0
- package/dist/gui-subagent/operator/computer-operator.js.map +1 -1
- package/dist/input-processor.js +2 -2
- package/dist/input-processor.js.map +1 -1
- package/dist/logger.d.ts.map +1 -1
- package/dist/logger.js +1 -1
- package/dist/logger.js.map +1 -1
- package/dist/mcp.d.ts +2 -1
- package/dist/mcp.d.ts.map +1 -1
- package/dist/mcp.js +83 -21
- package/dist/mcp.js.map +1 -1
- package/dist/memory.d.ts.map +1 -1
- package/dist/memory.js +3 -3
- package/dist/memory.js.map +1 -1
- package/dist/output-util.d.ts +27 -0
- package/dist/output-util.d.ts.map +1 -0
- package/dist/output-util.js +74 -0
- package/dist/output-util.js.map +1 -0
- package/dist/retry.js +1 -1
- package/dist/retry.js.map +1 -1
- package/dist/ripgrep.d.ts.map +1 -1
- package/dist/ripgrep.js +5 -3
- package/dist/ripgrep.js.map +1 -1
- package/dist/sdk-output-adapter.d.ts +265 -0
- package/dist/sdk-output-adapter.d.ts.map +1 -0
- package/dist/sdk-output-adapter.js +701 -0
- package/dist/sdk-output-adapter.js.map +1 -0
- package/dist/sdk-session.d.ts +13 -0
- package/dist/sdk-session.d.ts.map +1 -0
- package/dist/sdk-session.js +50 -0
- package/dist/sdk-session.js.map +1 -0
- package/dist/session-manager.js +3 -3
- package/dist/session-manager.js.map +1 -1
- package/dist/session.d.ts +96 -2
- package/dist/session.d.ts.map +1 -1
- package/dist/session.js +849 -262
- package/dist/session.js.map +1 -1
- package/dist/shell.d.ts.map +1 -1
- package/dist/shell.js +5 -4
- package/dist/shell.js.map +1 -1
- package/dist/skill-installer.js +3 -3
- package/dist/skill-installer.js.map +1 -1
- package/dist/skill-invoker.d.ts +1 -1
- package/dist/skill-invoker.d.ts.map +1 -1
- package/dist/skill-invoker.js +2 -2
- package/dist/skill-invoker.js.map +1 -1
- package/dist/skill-loader.js +6 -5
- package/dist/skill-loader.js.map +1 -1
- package/dist/skill-manager.d.ts.map +1 -1
- package/dist/skill-manager.js +3 -2
- package/dist/skill-manager.js.map +1 -1
- package/dist/slash-commands.d.ts +1 -1
- package/dist/slash-commands.d.ts.map +1 -1
- package/dist/slash-commands.js +24 -11
- package/dist/slash-commands.js.map +1 -1
- package/dist/smart-approval.d.ts +20 -1
- package/dist/smart-approval.d.ts.map +1 -1
- package/dist/smart-approval.js +58 -1
- package/dist/smart-approval.js.map +1 -1
- package/dist/system-prompt-generator.js +3 -3
- package/dist/system-prompt-generator.js.map +1 -1
- package/dist/theme.d.ts.map +1 -1
- package/dist/theme.js +8 -7
- package/dist/theme.js.map +1 -1
- package/dist/tools.d.ts +15 -0
- package/dist/tools.d.ts.map +1 -1
- package/dist/tools.js +487 -215
- package/dist/tools.js.map +1 -1
- package/dist/types.d.ts +57 -0
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js +49 -0
- package/dist/types.js.map +1 -1
- package/dist/update.d.ts.map +1 -1
- package/dist/update.js +12 -9
- package/dist/update.js.map +1 -1
- package/dist/workflow.d.ts.map +1 -1
- package/dist/workflow.js +1 -2
- package/dist/workflow.js.map +1 -1
- package/docs/third-party-models.md +16 -15
- package/package.json +3 -1
- package/src/agents.ts +7 -3
- package/src/ai-client/factory.ts +1 -36
- package/src/ai-client/index.ts +1 -1
- package/src/ai-client/providers/anthropic.ts +12 -3
- package/src/ai-client/providers/openai.ts +10 -4
- package/src/ai-client/providers/remote.ts +13 -10
- package/src/ai-client/types.ts +19 -0
- package/src/ai-client-factory.ts +5 -5
- package/src/auth.ts +11 -13
- package/src/cancellation.ts +3 -6
- package/src/checkpoint.ts +40 -4
- package/src/cli.ts +154 -37
- package/src/config.ts +1 -1
- package/src/context-compressor.ts +28 -23
- package/src/conversation.ts +9 -7
- package/src/gui-subagent/action-parser/actionParser.ts +2 -2
- package/src/gui-subagent/agent/gui-agent.ts +117 -34
- package/src/gui-subagent/index.ts +8 -0
- package/src/gui-subagent/operator/computer-operator.ts +2 -1
- package/src/input-processor.ts +2 -2
- package/src/logger.ts +2 -4
- package/src/mcp.ts +86 -23
- package/src/memory.ts +3 -4
- package/src/output-util.ts +80 -0
- package/src/retry.ts +1 -1
- package/src/ripgrep.ts +5 -3
- package/src/sdk-output-adapter.ts +842 -0
- package/src/sdk-session.ts +62 -0
- package/src/session-manager.ts +3 -3
- package/src/session.ts +942 -302
- package/src/shell.ts +6 -5
- package/src/skill-installer.ts +3 -3
- package/src/skill-invoker.ts +3 -4
- package/src/skill-loader.ts +7 -7
- package/src/skill-manager.ts +4 -3
- package/src/slash-commands.ts +24 -16
- package/src/smart-approval.ts +76 -1
- package/src/system-prompt-generator.ts +3 -3
- package/src/theme.ts +9 -8
- package/src/tools.ts +563 -267
- package/src/types.ts +118 -0
- package/src/update.ts +12 -9
- package/src/workflow.ts +2 -4
- package/test/cli-launch.test.ts +279 -0
- package/vitest.config.ts +2 -0
- /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 {
|
|
14
|
-
import {
|
|
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
|
|
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
|
|
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
|
|
368
|
+
const mcpServers = configManager.getMcpServers();
|
|
369
|
+
const serverNames = Object.keys(mcpServers);
|
|
350
370
|
|
|
351
|
-
if (
|
|
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
|
-
|
|
364
|
-
const
|
|
365
|
-
const
|
|
366
|
-
const
|
|
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(
|
|
369
|
-
console.log(` ${colors.textDim(`
|
|
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
|
-
|
|
495
|
+
headers['Authorization'] = `Bearer ${options.token}`;
|
|
410
496
|
}
|
|
411
|
-
|
|
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
|
-
|
|
424
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
|
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
|
|
905
|
+
const _execAsync = promisify(exec);
|
|
797
906
|
const userSkillsPath = configManager.getUserSkillsPath() || pathModule.join(os.homedir(), '.xagent', 'skills');
|
|
798
|
-
const
|
|
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
|
-
|
|
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
|
-
|
|
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
|
|
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
|
-
|
|
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
|
|
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
|
-
|
|
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
|
-
|
|
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,
|
|
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
|
|
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':
|
|
48
|
+
'glm-4.7': 200000,
|
|
49
|
+
'glm-5': 200000,
|
|
49
50
|
|
|
50
51
|
// MiniMax
|
|
51
|
-
'MiniMax-M2':
|
|
52
|
-
'MiniMax-M2.1':
|
|
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
|
|
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
|
|
453
|
-
let
|
|
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:
|
|
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
|
-
|
|
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
|
-
|
|
486
|
+
_matchedToolCalls++;
|
|
485
487
|
} else if (isWriteTool(toolName) || isEditTool(toolName) || isDeleteTool(toolName)) {
|
|
486
488
|
fileOps.modified.add(filePath);
|
|
487
|
-
|
|
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
|
-
|
|
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
|
-
|
|
507
|
+
_matchedToolCalls++;
|
|
506
508
|
} else if (isWriteTool(toolName) || isEditTool(toolName) || isDeleteTool(toolName)) {
|
|
507
509
|
fileOps.modified.add(filePath);
|
|
508
|
-
|
|
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
|
|
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
|
|
789
|
+
const _originalTokens = this.estimateContextTokens(messages);
|
|
786
790
|
const contextWindow = getModelContextWindow(modelName);
|
|
787
791
|
|
|
788
792
|
// Check if compression is needed
|
|
@@ -894,7 +898,7 @@ export class ContextCompressor {
|
|
|
894
898
|
} else {
|
|
895
899
|
// No user message in kept messages (rare case)
|
|
896
900
|
// Insert summary as a user message, then add all kept messages
|
|
897
|
-
// This ensures valid message order: user
|
|
901
|
+
// This ensures valid message order: user �?assistant �?tool �?tool...
|
|
898
902
|
compressedMessages.push({
|
|
899
903
|
role: 'user',
|
|
900
904
|
content: `[Conversation Summary - ${messagesToSummarize.length} messages compressed]\n\n${summary}`,
|
|
@@ -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
|
|
936
|
-
const
|
|
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
|
+
|