@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.
- 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 +38 -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 +22 -17
- 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 +84 -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 +9 -8
- 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 +41 -4
- package/src/cli.ts +154 -37
- package/src/config.ts +1 -1
- package/src/context-compressor.ts +27 -22
- 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 +87 -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 +10 -9
- 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/types.ts
CHANGED
|
@@ -217,3 +217,121 @@ export interface ToolCallItem {
|
|
|
217
217
|
type?: string;
|
|
218
218
|
function: ToolCallFunction;
|
|
219
219
|
}
|
|
220
|
+
|
|
221
|
+
// ============================================================================
|
|
222
|
+
// SDK Message Types (for programmatic access)
|
|
223
|
+
// ============================================================================
|
|
224
|
+
|
|
225
|
+
/**
|
|
226
|
+
* SDK input message from client
|
|
227
|
+
*/
|
|
228
|
+
export interface SdkInputMessage {
|
|
229
|
+
type: 'user';
|
|
230
|
+
content: string;
|
|
231
|
+
request_id?: string; // Optional request ID for tracking
|
|
232
|
+
uuid?: string;
|
|
233
|
+
parent_tool_use_id?: string | null;
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
/**
|
|
237
|
+
* SDK control request message
|
|
238
|
+
*/
|
|
239
|
+
export interface SdkControlRequest {
|
|
240
|
+
type: 'control_request';
|
|
241
|
+
request_id: string;
|
|
242
|
+
request: {
|
|
243
|
+
subtype: 'interrupt' | 'initialize' | 'set_permission_mode' | 'set_model';
|
|
244
|
+
[key: string]: unknown;
|
|
245
|
+
};
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
/**
|
|
249
|
+
* SDK ping message (heartbeat)
|
|
250
|
+
*/
|
|
251
|
+
export interface SdkPingMessage {
|
|
252
|
+
type: 'ping';
|
|
253
|
+
request_id?: string;
|
|
254
|
+
timestamp: number;
|
|
255
|
+
}
|
|
256
|
+
|
|
257
|
+
/**
|
|
258
|
+
* SDK approval response message (for responding to approval requests in SDK mode)
|
|
259
|
+
*/
|
|
260
|
+
export interface SdkApprovalResponse {
|
|
261
|
+
type: 'approval_response';
|
|
262
|
+
request_id: string;
|
|
263
|
+
approved: boolean;
|
|
264
|
+
}
|
|
265
|
+
|
|
266
|
+
/**
|
|
267
|
+
* SDK question response message (for responding to ask_user_question in SDK mode)
|
|
268
|
+
*/
|
|
269
|
+
export interface SdkQuestionResponse {
|
|
270
|
+
type: 'question_response';
|
|
271
|
+
request_id: string;
|
|
272
|
+
answers: string[];
|
|
273
|
+
}
|
|
274
|
+
|
|
275
|
+
/**
|
|
276
|
+
* SDK input message union type
|
|
277
|
+
*/
|
|
278
|
+
export type SdkInputMessageType = SdkInputMessage | SdkControlRequest | SdkPingMessage | SdkApprovalResponse | SdkQuestionResponse;
|
|
279
|
+
|
|
280
|
+
/**
|
|
281
|
+
* Check if a string is a JSON SDK message
|
|
282
|
+
*/
|
|
283
|
+
export function isSdkMessage(input: string): boolean {
|
|
284
|
+
const trimmed = input.trim();
|
|
285
|
+
if (!trimmed.startsWith('{')) {
|
|
286
|
+
return false;
|
|
287
|
+
}
|
|
288
|
+
|
|
289
|
+
try {
|
|
290
|
+
const parsed = JSON.parse(trimmed);
|
|
291
|
+
// Check for known message types
|
|
292
|
+
return (
|
|
293
|
+
parsed.type === 'user' ||
|
|
294
|
+
parsed.type === 'control_request' ||
|
|
295
|
+
parsed.type === 'ping' ||
|
|
296
|
+
parsed.type === 'approval_response' ||
|
|
297
|
+
parsed.type === 'question_response'
|
|
298
|
+
);
|
|
299
|
+
} catch {
|
|
300
|
+
return false;
|
|
301
|
+
}
|
|
302
|
+
}
|
|
303
|
+
|
|
304
|
+
/**
|
|
305
|
+
* Try to parse SDK message from string
|
|
306
|
+
*/
|
|
307
|
+
export function parseSdkMessage(input: string): SdkInputMessageType | null {
|
|
308
|
+
const trimmed = input.trim();
|
|
309
|
+
|
|
310
|
+
try {
|
|
311
|
+
const parsed = JSON.parse(trimmed);
|
|
312
|
+
|
|
313
|
+
if (parsed.type === 'user') {
|
|
314
|
+
return parsed as SdkInputMessage;
|
|
315
|
+
}
|
|
316
|
+
|
|
317
|
+
if (parsed.type === 'control_request') {
|
|
318
|
+
return parsed as SdkControlRequest;
|
|
319
|
+
}
|
|
320
|
+
|
|
321
|
+
if (parsed.type === 'ping') {
|
|
322
|
+
return parsed as SdkPingMessage;
|
|
323
|
+
}
|
|
324
|
+
|
|
325
|
+
if (parsed.type === 'approval_response') {
|
|
326
|
+
return parsed as SdkApprovalResponse;
|
|
327
|
+
}
|
|
328
|
+
|
|
329
|
+
if (parsed.type === 'question_response') {
|
|
330
|
+
return parsed as SdkQuestionResponse;
|
|
331
|
+
}
|
|
332
|
+
|
|
333
|
+
return null;
|
|
334
|
+
} catch {
|
|
335
|
+
return null;
|
|
336
|
+
}
|
|
337
|
+
}
|
package/src/update.ts
CHANGED
|
@@ -37,7 +37,7 @@ export class UpdateManager {
|
|
|
37
37
|
latestVersion,
|
|
38
38
|
updateAvailable,
|
|
39
39
|
releaseNotes: response.data.versions[latestVersion]?.description,
|
|
40
|
-
downloadUrl: `https://www.npmjs.com/package/@xagent-ai/
|
|
40
|
+
downloadUrl: `https://www.npmjs.com/package/@xagent-ai/cli/v/${latestVersion}`,
|
|
41
41
|
};
|
|
42
42
|
|
|
43
43
|
return versionInfo;
|
|
@@ -103,7 +103,7 @@ export class UpdateManager {
|
|
|
103
103
|
return false;
|
|
104
104
|
}
|
|
105
105
|
|
|
106
|
-
private async promptUpdate(
|
|
106
|
+
private async promptUpdate(_versionInfo: VersionInfo): Promise<{ shouldUpdate: boolean }> {
|
|
107
107
|
const shouldUpdate = await confirm({
|
|
108
108
|
message: 'Do you want to update now?',
|
|
109
109
|
});
|
|
@@ -120,7 +120,7 @@ export class UpdateManager {
|
|
|
120
120
|
try {
|
|
121
121
|
console.log('Updating xAgent CLI...');
|
|
122
122
|
|
|
123
|
-
await execAsync('npm install -g @xagent-ai/
|
|
123
|
+
await execAsync('npm install -g @xagent-ai/cli@latest', {
|
|
124
124
|
timeout: 120000,
|
|
125
125
|
});
|
|
126
126
|
|
|
@@ -135,8 +135,8 @@ export class UpdateManager {
|
|
|
135
135
|
|
|
136
136
|
if (tryManual === true) {
|
|
137
137
|
console.log('\nManual update instructions:');
|
|
138
|
-
console.log('1. Run: npm uninstall -g @xagent-ai/
|
|
139
|
-
console.log('2. Run: npm install -g @xagent-ai/
|
|
138
|
+
console.log('1. Run: npm uninstall -g @xagent-ai/cli');
|
|
139
|
+
console.log('2. Run: npm install -g @xagent-ai/cli@latest');
|
|
140
140
|
console.log('3. Restart: xagent\n');
|
|
141
141
|
}
|
|
142
142
|
|
|
@@ -150,7 +150,7 @@ export class UpdateManager {
|
|
|
150
150
|
if (versionInfo.updateAvailable) {
|
|
151
151
|
console.log(`\n📦 A new version is available: ${versionInfo.latestVersion}`);
|
|
152
152
|
console.log(`Current version: ${versionInfo.currentVersion}`);
|
|
153
|
-
console.log(`Update with: npm install -g @xagent-ai/
|
|
153
|
+
console.log(`Update with: npm install -g @xagent-ai/cli@latest\n`);
|
|
154
154
|
}
|
|
155
155
|
}
|
|
156
156
|
|
|
@@ -223,9 +223,12 @@ export class UpdateManager {
|
|
|
223
223
|
}
|
|
224
224
|
|
|
225
225
|
async enableAutoUpdate(enabled: boolean): Promise<void> {
|
|
226
|
-
|
|
227
|
-
const
|
|
228
|
-
|
|
226
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
227
|
+
const _fs = await import('fs/promises');
|
|
228
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
229
|
+
const _path = await import('path');
|
|
230
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
231
|
+
const _os = await import('os');
|
|
229
232
|
const { getConfigManager } = await import('./config.js');
|
|
230
233
|
|
|
231
234
|
const configManager = getConfigManager();
|
package/src/workflow.ts
CHANGED
|
@@ -1,10 +1,9 @@
|
|
|
1
1
|
import fs from 'fs/promises';
|
|
2
|
-
import fsSync from 'fs';
|
|
3
2
|
import path from 'path';
|
|
4
3
|
import os from 'os';
|
|
5
4
|
import axios from 'axios';
|
|
6
5
|
import { AgentConfig, MCPServerConfig } from './types.js';
|
|
7
|
-
import {
|
|
6
|
+
import { getSkillLoader } from './skill-loader.js';
|
|
8
7
|
import { getConfigManager } from './config.js';
|
|
9
8
|
|
|
10
9
|
export interface WorkflowConfig {
|
|
@@ -78,7 +77,7 @@ export class WorkflowManager {
|
|
|
78
77
|
}
|
|
79
78
|
}
|
|
80
79
|
|
|
81
|
-
private async loadWorkflowsFromDirectory(dirPath: string,
|
|
80
|
+
private async loadWorkflowsFromDirectory(dirPath: string, _scope: 'global' | 'project'): Promise<void> {
|
|
82
81
|
try {
|
|
83
82
|
const files = await fs.readdir(dirPath);
|
|
84
83
|
|
|
@@ -449,7 +448,6 @@ export class WorkflowManager {
|
|
|
449
448
|
}
|
|
450
449
|
|
|
451
450
|
async createWorkflowPackage(projectRoot: string): Promise<Buffer> {
|
|
452
|
-
const workflowId = path.basename(projectRoot);
|
|
453
451
|
const workflowConfigPath = path.join(projectRoot, '.xagent', 'workflow.json');
|
|
454
452
|
|
|
455
453
|
let workflowConfig: WorkflowConfig;
|
|
@@ -0,0 +1,279 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* xAgent CLI Launch Tests
|
|
3
|
+
*
|
|
4
|
+
* 这些测试用于验证 CLI 的基本启动和命令行为。
|
|
5
|
+
* 测试不依赖外部服务,可以离线运行。
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
import { describe, it, expect } from 'vitest';
|
|
9
|
+
import { fileURLToPath } from 'url';
|
|
10
|
+
import { dirname, join } from 'path';
|
|
11
|
+
import { execSync } from 'child_process';
|
|
12
|
+
|
|
13
|
+
const __filename = fileURLToPath(import.meta.url);
|
|
14
|
+
const __dirname = dirname(__filename);
|
|
15
|
+
const cliPath = join(__dirname, '../dist/cli.js');
|
|
16
|
+
|
|
17
|
+
// commander.js 的 --help 行为会导致退出码为 1,这是正常行为
|
|
18
|
+
const HELP_EXIT_CODE = 1;
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* 运行 CLI 命令并返回结果(使用 execSync)
|
|
22
|
+
*/
|
|
23
|
+
function runCli(args: string[], options: { env?: Record<string, string> } = {}): {
|
|
24
|
+
exitCode: number;
|
|
25
|
+
stdout: string;
|
|
26
|
+
stderr: string;
|
|
27
|
+
} {
|
|
28
|
+
try {
|
|
29
|
+
const env = { ...process.env, ...options.env, NODE_ENV: 'test' };
|
|
30
|
+
const stdout = execSync(`"${process.execPath}" "${cliPath}" ${args.join(' ')}`, {
|
|
31
|
+
encoding: 'utf-8',
|
|
32
|
+
env,
|
|
33
|
+
timeout: 30000,
|
|
34
|
+
stdio: ['pipe', 'pipe', 'pipe']
|
|
35
|
+
});
|
|
36
|
+
return {
|
|
37
|
+
exitCode: 0,
|
|
38
|
+
stdout,
|
|
39
|
+
stderr: ''
|
|
40
|
+
};
|
|
41
|
+
} catch (error: any) {
|
|
42
|
+
// execSync 在命令失败时会抛出错误
|
|
43
|
+
const stdout = error.stdout || '';
|
|
44
|
+
const stderr = error.stderr || '';
|
|
45
|
+
const exitCode = error.status || -1;
|
|
46
|
+
// 合并 stdout 和 stderr,因为 Windows PowerShell 可能将输出重定向
|
|
47
|
+
const combinedOutput = stdout + stderr;
|
|
48
|
+
return {
|
|
49
|
+
exitCode,
|
|
50
|
+
stdout: combinedOutput,
|
|
51
|
+
stderr
|
|
52
|
+
};
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
describe('xAgent CLI Launch Tests', () => {
|
|
57
|
+
/**
|
|
58
|
+
* 测试版本号输出
|
|
59
|
+
*/
|
|
60
|
+
describe('version', () => {
|
|
61
|
+
it('should output version with --version flag', () => {
|
|
62
|
+
const result = runCli(['--version']);
|
|
63
|
+
|
|
64
|
+
expect(result.exitCode).toBe(0);
|
|
65
|
+
expect(result.stdout).toMatch(/\d+\.\d+\.\d+/); // 匹配语义化版本号
|
|
66
|
+
});
|
|
67
|
+
|
|
68
|
+
it('should exit with code 0 on --version', () => {
|
|
69
|
+
const result = runCli(['--version']);
|
|
70
|
+
expect(result.exitCode).toBe(0);
|
|
71
|
+
});
|
|
72
|
+
});
|
|
73
|
+
|
|
74
|
+
/**
|
|
75
|
+
* 测试帮助信息
|
|
76
|
+
*/
|
|
77
|
+
describe('help', () => {
|
|
78
|
+
it('should output help with --help flag', () => {
|
|
79
|
+
const result = runCli(['--help']);
|
|
80
|
+
|
|
81
|
+
// commander.js --help 退出码为 1 是正常行为
|
|
82
|
+
expect([0, HELP_EXIT_CODE]).toContain(result.exitCode);
|
|
83
|
+
// stdout 可能为空,输出在 stderr 中
|
|
84
|
+
const output = result.stdout || result.stderr;
|
|
85
|
+
expect(output).toContain('xagent');
|
|
86
|
+
expect(output).toContain('AI-powered');
|
|
87
|
+
});
|
|
88
|
+
|
|
89
|
+
it('should list available commands in help', () => {
|
|
90
|
+
const result = runCli(['--help']);
|
|
91
|
+
const output = result.stdout || result.stderr;
|
|
92
|
+
|
|
93
|
+
expect(output).toContain('start');
|
|
94
|
+
expect(output).toContain('auth');
|
|
95
|
+
expect(output).toContain('agent');
|
|
96
|
+
expect(output).toContain('mcp');
|
|
97
|
+
expect(output).toContain('init');
|
|
98
|
+
});
|
|
99
|
+
|
|
100
|
+
it('should show help for auth command', () => {
|
|
101
|
+
const result = runCli(['auth', '--help']);
|
|
102
|
+
const output = result.stdout || result.stderr;
|
|
103
|
+
|
|
104
|
+
expect([0, HELP_EXIT_CODE]).toContain(result.exitCode);
|
|
105
|
+
expect(output).toContain('auth');
|
|
106
|
+
// 检查认证相关文本
|
|
107
|
+
expect(output).toMatch(/authentication|authenticate|Auth/i);
|
|
108
|
+
});
|
|
109
|
+
|
|
110
|
+
it('should show help for mcp command', () => {
|
|
111
|
+
const result = runCli(['mcp', '--help']);
|
|
112
|
+
const output = result.stdout || result.stderr;
|
|
113
|
+
|
|
114
|
+
expect([0, HELP_EXIT_CODE]).toContain(result.exitCode);
|
|
115
|
+
expect(output).toContain('mcp');
|
|
116
|
+
expect(output).toContain('--list');
|
|
117
|
+
expect(output).toContain('--add');
|
|
118
|
+
expect(output).toContain('--remove');
|
|
119
|
+
});
|
|
120
|
+
});
|
|
121
|
+
|
|
122
|
+
/**
|
|
123
|
+
* 测试 start 命令启动
|
|
124
|
+
*/
|
|
125
|
+
describe('start command', () => {
|
|
126
|
+
it('should start and output when running xagent start', () => {
|
|
127
|
+
// start 命令会启动交互式会话
|
|
128
|
+
// 我们使用 timeout 强制终止并检查是否有输出
|
|
129
|
+
const result = runCli(['start']);
|
|
130
|
+
|
|
131
|
+
// 由于是交互式命令,退出码可能是 0 或超时 -1
|
|
132
|
+
// 关键是验证命令能够启动并产生输出
|
|
133
|
+
const output = result.stdout || result.stderr;
|
|
134
|
+
|
|
135
|
+
// 验证命令能够启动(没有立即崩溃)
|
|
136
|
+
expect([0, -1]).toContain(result.exitCode);
|
|
137
|
+
|
|
138
|
+
// 验证有输出内容(启动提示信息)
|
|
139
|
+
expect(output).toBeTruthy();
|
|
140
|
+
|
|
141
|
+
// 验证输出包含 CLI 相关内容
|
|
142
|
+
expect(output.toLowerCase()).toMatch(/xagent|agent|start|welcome/i);
|
|
143
|
+
});
|
|
144
|
+
});
|
|
145
|
+
|
|
146
|
+
/**
|
|
147
|
+
* 测试错误处理
|
|
148
|
+
*/
|
|
149
|
+
describe('error handling', () => {
|
|
150
|
+
it('should show error for unknown command', () => {
|
|
151
|
+
const result = runCli(['unknown-command-xyz']);
|
|
152
|
+
|
|
153
|
+
expect(result.exitCode).toBeGreaterThan(0);
|
|
154
|
+
const output = result.stdout || result.stderr;
|
|
155
|
+
expect(output).toBeTruthy();
|
|
156
|
+
});
|
|
157
|
+
|
|
158
|
+
it('should show error for unknown option', () => {
|
|
159
|
+
const result = runCli(['--unknown-option-xyz']);
|
|
160
|
+
|
|
161
|
+
expect(result.exitCode).toBeGreaterThan(0);
|
|
162
|
+
const output = result.stdout || result.stderr;
|
|
163
|
+
expect(output).toBeTruthy();
|
|
164
|
+
});
|
|
165
|
+
});
|
|
166
|
+
|
|
167
|
+
/**
|
|
168
|
+
* 测试 agent 命令
|
|
169
|
+
*/
|
|
170
|
+
describe('agent command', () => {
|
|
171
|
+
it('should show agent help', () => {
|
|
172
|
+
const result = runCli(['agent', '--help']);
|
|
173
|
+
const output = result.stdout || result.stderr;
|
|
174
|
+
|
|
175
|
+
expect([0, HELP_EXIT_CODE]).toContain(result.exitCode);
|
|
176
|
+
// 检查帮助输出中包含关键选项
|
|
177
|
+
expect(output).toContain('--list');
|
|
178
|
+
expect(output).toContain('--add');
|
|
179
|
+
expect(output).toContain('--remove');
|
|
180
|
+
// 检查输出与 agent 相关
|
|
181
|
+
expect(output.toLowerCase()).toMatch(/agent|specify an action/i);
|
|
182
|
+
});
|
|
183
|
+
|
|
184
|
+
it('should list agents with --list flag', () => {
|
|
185
|
+
const result = runCli(['agent', '--list']);
|
|
186
|
+
|
|
187
|
+
// agent --list 可能会因为没有配置而返回非零退出码
|
|
188
|
+
expect([0, HELP_EXIT_CODE]).toContain(result.exitCode);
|
|
189
|
+
const output = result.stdout || result.stderr;
|
|
190
|
+
expect(output).toBeTruthy();
|
|
191
|
+
});
|
|
192
|
+
});
|
|
193
|
+
|
|
194
|
+
/**
|
|
195
|
+
* 测试 mcp 命令
|
|
196
|
+
*/
|
|
197
|
+
describe('mcp command', () => {
|
|
198
|
+
it('should show mcp help', () => {
|
|
199
|
+
const result = runCli(['mcp', '--help']);
|
|
200
|
+
const output = result.stdout || result.stderr;
|
|
201
|
+
|
|
202
|
+
expect([0, HELP_EXIT_CODE]).toContain(result.exitCode);
|
|
203
|
+
expect(output).toContain('--list');
|
|
204
|
+
// 检查输出中包含 mcp 相关的选项
|
|
205
|
+
expect(output.toLowerCase()).toMatch(/mcp|transport|server|--add/i);
|
|
206
|
+
});
|
|
207
|
+
|
|
208
|
+
it('should list MCP servers with --list flag', () => {
|
|
209
|
+
const result = runCli(['mcp', '--list']);
|
|
210
|
+
|
|
211
|
+
// mcp --list 可能会因为没有配置而返回非零退出码
|
|
212
|
+
expect([0, HELP_EXIT_CODE]).toContain(result.exitCode);
|
|
213
|
+
});
|
|
214
|
+
});
|
|
215
|
+
|
|
216
|
+
/**
|
|
217
|
+
* 测试 init 命令
|
|
218
|
+
*/
|
|
219
|
+
describe('init command', () => {
|
|
220
|
+
it('should show init help', () => {
|
|
221
|
+
const result = runCli(['init', '--help']);
|
|
222
|
+
const output = result.stdout || result.stderr;
|
|
223
|
+
|
|
224
|
+
expect([0, HELP_EXIT_CODE]).toContain(result.exitCode);
|
|
225
|
+
expect(output.toLowerCase()).toContain('init');
|
|
226
|
+
// init 命令会实际执行初始化,检查是否有关键内容
|
|
227
|
+
expect(output.toLowerCase()).toMatch(/project|xagent\.md|initial/i);
|
|
228
|
+
});
|
|
229
|
+
});
|
|
230
|
+
|
|
231
|
+
/**
|
|
232
|
+
* 测试 workflow 命令
|
|
233
|
+
*/
|
|
234
|
+
describe('workflow command', () => {
|
|
235
|
+
it('should show workflow help', () => {
|
|
236
|
+
const result = runCli(['workflow', '--help']);
|
|
237
|
+
const output = result.stdout || result.stderr;
|
|
238
|
+
|
|
239
|
+
expect([0, HELP_EXIT_CODE]).toContain(result.exitCode);
|
|
240
|
+
// workflow 命令可能输出"Please specify an action"或帮助信息
|
|
241
|
+
expect(output.toLowerCase()).toMatch(/workflow|specify an action|--list/i);
|
|
242
|
+
expect(output).toContain('--list');
|
|
243
|
+
});
|
|
244
|
+
|
|
245
|
+
it('should list workflows with --list flag', () => {
|
|
246
|
+
const result = runCli(['workflow', '--list']);
|
|
247
|
+
|
|
248
|
+
expect([0, HELP_EXIT_CODE]).toContain(result.exitCode);
|
|
249
|
+
});
|
|
250
|
+
});
|
|
251
|
+
|
|
252
|
+
/**
|
|
253
|
+
* 测试 skill 命令
|
|
254
|
+
*/
|
|
255
|
+
describe('skill command', () => {
|
|
256
|
+
it('should show skill help', () => {
|
|
257
|
+
const result = runCli(['skill', '--help']);
|
|
258
|
+
const output = result.stdout || result.stderr;
|
|
259
|
+
|
|
260
|
+
expect([0, HELP_EXIT_CODE]).toContain(result.exitCode);
|
|
261
|
+
expect(output.toLowerCase()).toContain('skill');
|
|
262
|
+
// skill 命令使用 -l 而不是 --list
|
|
263
|
+
expect(output.toLowerCase()).toMatch(/skill|-l|--add|--remove/i);
|
|
264
|
+
});
|
|
265
|
+
});
|
|
266
|
+
|
|
267
|
+
/**
|
|
268
|
+
* 测试环境变量处理
|
|
269
|
+
*/
|
|
270
|
+
describe('environment handling', () => {
|
|
271
|
+
it('should handle empty XAGENT_BASE_URL gracefully', () => {
|
|
272
|
+
const result = runCli(['--help'], {
|
|
273
|
+
env: { XAGENT_BASE_URL: '' }
|
|
274
|
+
});
|
|
275
|
+
|
|
276
|
+
expect([0, HELP_EXIT_CODE]).toContain(result.exitCode);
|
|
277
|
+
});
|
|
278
|
+
});
|
|
279
|
+
});
|
package/vitest.config.ts
CHANGED
|
File without changes
|