aico-cli 0.4.6 → 0.4.8
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/chunks/simple-config.mjs +1 -1
- package/dist/cli.mjs +66 -26
- package/package.json +1 -1
|
@@ -13,7 +13,7 @@ import { join as join$1 } from 'node:path';
|
|
|
13
13
|
import { join, dirname, basename } from 'pathe';
|
|
14
14
|
import { fileURLToPath } from 'node:url';
|
|
15
15
|
|
|
16
|
-
const version = "0.4.
|
|
16
|
+
const version = "0.4.8";
|
|
17
17
|
|
|
18
18
|
function displayBanner(subtitle) {
|
|
19
19
|
const defaultSubtitle = "\u4E00\u952E\u914D\u7F6E\u4F60\u7684\u5F00\u53D1\u73AF\u5883";
|
package/dist/cli.mjs
CHANGED
|
@@ -47,32 +47,57 @@ class ProcessManager extends EventEmitter {
|
|
|
47
47
|
this.cleanup();
|
|
48
48
|
});
|
|
49
49
|
}
|
|
50
|
+
/**
|
|
51
|
+
* 获取适用于当前平台的命令路径
|
|
52
|
+
*/
|
|
53
|
+
getPlatformCommand(command) {
|
|
54
|
+
const isWindows = process.platform === "win32";
|
|
55
|
+
if (isWindows) {
|
|
56
|
+
const commandMappings = {
|
|
57
|
+
"npm": "npm.cmd",
|
|
58
|
+
"npx": "npx.cmd",
|
|
59
|
+
"node": "node.exe",
|
|
60
|
+
"claude": "claude.cmd"
|
|
61
|
+
};
|
|
62
|
+
return commandMappings[command] || command;
|
|
63
|
+
}
|
|
64
|
+
return command;
|
|
65
|
+
}
|
|
66
|
+
/**
|
|
67
|
+
* 检查命令是否存在
|
|
68
|
+
*/
|
|
69
|
+
async checkCommandExists(command) {
|
|
70
|
+
try {
|
|
71
|
+
const { execSync } = await import('node:child_process');
|
|
72
|
+
const isWindows = process.platform === "win32";
|
|
73
|
+
if (isWindows) {
|
|
74
|
+
execSync(`where ${command}`, { stdio: "ignore" });
|
|
75
|
+
} else {
|
|
76
|
+
execSync(`which ${command}`, { stdio: "ignore" });
|
|
77
|
+
}
|
|
78
|
+
return true;
|
|
79
|
+
} catch {
|
|
80
|
+
return false;
|
|
81
|
+
}
|
|
82
|
+
}
|
|
50
83
|
/**
|
|
51
84
|
* 启动进程
|
|
52
85
|
*/
|
|
53
86
|
async spawn(command, args = [], options = {}) {
|
|
54
87
|
const startTime = Date.now();
|
|
55
88
|
const processName = options.name || command;
|
|
56
|
-
const isWindows = process.platform === "win32";
|
|
57
89
|
this.log(`\u542F\u52A8\u8FDB\u7A0B: ${processName}`, "info");
|
|
58
90
|
try {
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
if (
|
|
62
|
-
|
|
63
|
-
finalCommand = "npx.cmd";
|
|
64
|
-
} else if (command === "claude") {
|
|
65
|
-
finalCommand = "claude.cmd";
|
|
66
|
-
}
|
|
91
|
+
const platformCommand = this.getPlatformCommand(command);
|
|
92
|
+
const commandExists = await this.checkCommandExists(platformCommand);
|
|
93
|
+
if (!commandExists) {
|
|
94
|
+
throw new Error(`\u547D\u4EE4 '${platformCommand}' \u4E0D\u5B58\u5728\uFF0C\u8BF7\u786E\u4FDD\u5DF2\u5B89\u88C5\u5E76\u6DFB\u52A0\u5230PATH\u73AF\u5883\u53D8\u91CF`);
|
|
67
95
|
}
|
|
68
|
-
const child = spawn(
|
|
96
|
+
const child = spawn(platformCommand, args, {
|
|
69
97
|
cwd: options.cwd || process.cwd(),
|
|
70
98
|
env: { ...process.env, ...options.env },
|
|
71
99
|
stdio: options.stdio || "pipe",
|
|
72
|
-
shell:
|
|
73
|
-
// 禁用shell模式,避免进程泄漏
|
|
74
|
-
windowsHide: isWindows
|
|
75
|
-
// Windows上隐藏子进程窗口
|
|
100
|
+
shell: options.shell || process.platform === "win32"
|
|
76
101
|
});
|
|
77
102
|
this.registerProcess(child, processName);
|
|
78
103
|
let timeoutId;
|
|
@@ -104,13 +129,25 @@ class ProcessManager extends EventEmitter {
|
|
|
104
129
|
const exitCode = await new Promise((resolve, reject) => {
|
|
105
130
|
child.on("close", (code) => {
|
|
106
131
|
if (timeoutId) clearTimeout(timeoutId);
|
|
107
|
-
|
|
132
|
+
if (child.pid) {
|
|
133
|
+
this.unregisterProcess(child.pid);
|
|
134
|
+
}
|
|
108
135
|
resolve(code ?? 0);
|
|
109
136
|
});
|
|
110
137
|
child.on("error", (error) => {
|
|
111
138
|
if (timeoutId) clearTimeout(timeoutId);
|
|
112
|
-
|
|
113
|
-
|
|
139
|
+
if (child.pid) {
|
|
140
|
+
this.unregisterProcess(child.pid);
|
|
141
|
+
}
|
|
142
|
+
let enhancedError = error;
|
|
143
|
+
if (error.message?.includes("ENOENT")) {
|
|
144
|
+
const isWindows = process.platform === "win32";
|
|
145
|
+
const commandInfo = isWindows ? `\u547D\u4EE4 '${platformCommand}' \u4E0D\u5B58\u5728\u3002\u5728Windows\u4E0A\uFF0C\u8BF7\u786E\u4FDD\u5DF2\u5B89\u88C5Node.js\u5E76\u6DFB\u52A0\u5230PATH\u73AF\u5883\u53D8\u91CF\u3002\u5C1D\u8BD5\u4F7F\u7528\u5B8C\u6574\u8DEF\u5F84\u6216\u68C0\u67E5\u547D\u4EE4\u662F\u5426\u6B63\u786E\u3002` : `\u547D\u4EE4 '${platformCommand}' \u4E0D\u5B58\u5728\u3002\u8BF7\u786E\u4FDD\u5DF2\u5B89\u88C5\u5E76\u6DFB\u52A0\u5230PATH\u73AF\u5883\u53D8\u91CF\u3002`;
|
|
146
|
+
enhancedError = new Error(`${error.message}
|
|
147
|
+
${commandInfo}`);
|
|
148
|
+
enhancedError.stack = error.stack;
|
|
149
|
+
}
|
|
150
|
+
reject(enhancedError);
|
|
114
151
|
});
|
|
115
152
|
});
|
|
116
153
|
const duration = Date.now() - startTime;
|
|
@@ -143,6 +180,12 @@ class ProcessManager extends EventEmitter {
|
|
|
143
180
|
registerProcess(child, name) {
|
|
144
181
|
if (!child.pid) {
|
|
145
182
|
this.log(`\u65E0\u6CD5\u6CE8\u518C\u8FDB\u7A0B ${name}: \u6CA1\u6709PID`, "error");
|
|
183
|
+
child.on("close", (code) => {
|
|
184
|
+
this.log(`\u8FDB\u7A0B ${name} (\u65E0PID) \u5DF2\u5173\u95ED\uFF0C\u9000\u51FA\u7801: ${code}`, "info");
|
|
185
|
+
});
|
|
186
|
+
child.on("error", (error) => {
|
|
187
|
+
this.log(`\u8FDB\u7A0B ${name} (\u65E0PID) \u53D1\u751F\u9519\u8BEF: ${error}`, "error");
|
|
188
|
+
});
|
|
146
189
|
return;
|
|
147
190
|
}
|
|
148
191
|
if (this.processes.has(child.pid)) {
|
|
@@ -186,6 +229,10 @@ class ProcessManager extends EventEmitter {
|
|
|
186
229
|
* 注销进程
|
|
187
230
|
*/
|
|
188
231
|
unregisterProcess(pid) {
|
|
232
|
+
if (!pid) {
|
|
233
|
+
this.log(`\u5C1D\u8BD5\u6CE8\u9500\u65E0\u6548\u7684\u8FDB\u7A0B (PID: undefined)`, "warning");
|
|
234
|
+
return;
|
|
235
|
+
}
|
|
189
236
|
const info = this.processes.get(pid);
|
|
190
237
|
if (info) {
|
|
191
238
|
this.log(`\u6CE8\u9500\u8FDB\u7A0B: ${info.name} (PID: ${pid})`, "info");
|
|
@@ -443,15 +490,8 @@ class ProcessManager extends EventEmitter {
|
|
|
443
490
|
try {
|
|
444
491
|
this.cleanup();
|
|
445
492
|
const { spawn: spawn2 } = await import('node:child_process');
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
if (isWindows) {
|
|
449
|
-
if (command === "npx") {
|
|
450
|
-
finalCommand = "npx.cmd";
|
|
451
|
-
} else if (command === "claude") {
|
|
452
|
-
finalCommand = "claude.cmd";
|
|
453
|
-
}
|
|
454
|
-
}
|
|
493
|
+
const finalCommand = this.getPlatformCommand(command);
|
|
494
|
+
const finalArgs = args;
|
|
455
495
|
const child = spawn2(finalCommand, finalArgs, {
|
|
456
496
|
stdio: "inherit",
|
|
457
497
|
// 继承所有 stdio
|