myagent-ai 1.15.56 → 1.15.57

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 (3) hide show
  1. package/main.py +5 -36
  2. package/package.json +1 -1
  3. package/start.js +225 -548
package/main.py CHANGED
@@ -39,7 +39,7 @@ from core.config_broadcast import ConfigBroadcaster, ReloadType
39
39
  from core.update_manager import UpdateManager, UpdateType
40
40
  from core.version import get_version
41
41
  from core.permissions import PermissionManager
42
- from core.deps_checker import check_and_install_deps
42
+ from core.deps_checker import check_and_install_deps # 保留导入供其他模块使用
43
43
 
44
44
 
45
45
  def _get_screen_resolution() -> tuple[int, int]:
@@ -154,21 +154,8 @@ class MyAgentApp:
154
154
  self.logger.info(f"数据目录: {self.config_mgr.data_dir}")
155
155
  self.logger.info("=" * 60)
156
156
 
157
- # 1.5 自动检测并安装缺失依赖(开箱即用)
158
- # 可通过 --skip-deps 参数或 MYAGENT_SKIP_DEPS=1 环境变量跳过
159
- if os.environ.get("MYAGENT_SKIP_DEPS") == "1":
160
- self.logger.info("跳过依赖检查(--skip-deps)")
161
- else:
162
- self.logger.info("检查依赖...")
163
- deps_result = check_and_install_deps(auto_fix=True, silent=False)
164
- if deps_result["installed"] > 0:
165
- self.logger.info(
166
- f"自动安装了 {deps_result['installed']} 个依赖"
167
- )
168
- if deps_result["failed"] > 0:
169
- self.logger.warning(
170
- f"{deps_result['failed']} 个依赖安装失败,相关功能可能不可用"
171
- )
157
+ # 1.5 依赖检查已移至 start.js (install/reinstall 命令)
158
+ # 启动时不再检查依赖,确保启动速度干净利落
172
159
 
173
160
  # 2. LLM 客户端
174
161
  llm_cfg = self.config.llm
@@ -692,26 +679,8 @@ def create_tray_icon(app: MyAgentApp, web_port: int = 8767):
692
679
  from PIL import Image, ImageDraw, ImageFont
693
680
  except Exception:
694
681
  # pystray 可能因缺少 GUI 环境 (X11/Wayland) 或未安装而失败
695
- if os.environ.get('MYAGENT_SKIP_DEPS') == '1':
696
- logger.info("pystray/PIL 未安装,跳过自动安装(--skip-deps)")
697
- return None
698
- try:
699
- from core.deps_checker import _pip_install
700
- logger.info("pystray/PIL 未安装,正在自动安装...")
701
- success, msg = _pip_install(["pystray>=0.19.5", "Pillow>=10.0.0"])
702
- if success:
703
- logger.info(f"pystray/PIL 自动安装成功: {msg}")
704
- import importlib
705
- import pystray as _pystray
706
- importlib.reload(_pystray)
707
- import pystray
708
- from PIL import Image, ImageDraw, ImageFont
709
- else:
710
- logger.warning(f"pystray/PIL 自动安装失败: {msg}")
711
- return None
712
- except Exception as e:
713
- logger.warning(f"pystray 初始化失败 (可能缺少 GUI 环境): {e}")
714
- return None
682
+ logger.info("pystray 不可用(未安装或缺少 GUI 环境),跳过系统托盘")
683
+ return None
715
684
 
716
685
  # ── 图标颜色主题 ──
717
686
  _COLOR_NORMAL = "#4A90D9" # 蓝色 = 运行中
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "myagent-ai",
3
- "version": "1.15.56",
3
+ "version": "1.15.57",
4
4
  "description": "本地桌面端执行型AI助手 - Open Interpreter 风格 | Local Desktop Execution-Oriented AI Assistant",
5
5
  "main": "main.py",
6
6
  "bin": {
package/start.js CHANGED
@@ -2,22 +2,10 @@
2
2
  /**
3
3
  * start.js - 跨平台入口脚本 (Windows/macOS/Linux)
4
4
  * ================================================
5
- * npm bin 入口,自动管理独立虚拟环境:
6
- * - 虚拟环境位置: ~/.myagent/venv (与其他项目完全隔离)
7
- * - 首次运行自动创建 venv 并安装所有依赖
8
- * - 后续运行直接使用 venv,无需重复安装
9
- * - pip 升级/重装: myagent-ai reinstall
10
- *
11
- * 用法:
12
- * myagent-ai # 交互式选择运行模式
13
- * myagent-ai web # Web 管理后台
14
- * myagent-ai cli # CLI 模式
15
- * myagent-ai tray # 系统托盘模式
16
- * myagent-ai server # API 服务模式
17
- * myagent-ai setup # 配置向导
18
- * myagent-ai reinstall # 重新安装依赖到 venv
19
- * myagent-ai uninstall # 卸载 MyAgent(删除npm包+数据)
20
- * myagent-ai --skip-deps # 跳过依赖检查,直接启动
5
+ * 职责分明:
6
+ * - install/reinstall: 创建 venv + 安装所有依赖
7
+ * - web/cli/tray/server: 直接启动,不检查依赖
8
+ * - uninstall: 卸载
21
9
  */
22
10
  "use strict";
23
11
 
@@ -26,35 +14,19 @@ const path = require("path");
26
14
  const fs = require("fs");
27
15
  const os = require("os");
28
16
 
29
- // ── 常量 ──────────────────────────────────────────────────
30
17
  const IS_WIN = process.platform === "win32";
18
+ const PKG_NAME = "myagent-ai";
31
19
 
32
- // 虚拟环境目录
33
- function getVenvDir() {
34
- const homeDir = os.homedir();
35
- return path.join(homeDir, ".myagent", "venv");
36
- }
37
-
38
- // venv 中 Python 可执行文件的路径
39
- function getVenvPython(venvDir) {
40
- return IS_WIN
41
- ? path.join(venvDir, "Scripts", "python.exe")
42
- : path.join(venvDir, "bin", "python");
43
- }
20
+ // ── 路径工具 ──────────────────────────────────────────────
44
21
 
45
- // venv pip 可执行文件的路径
46
- function getVenvPip(venvDir) {
47
- return IS_WIN
48
- ? path.join(venvDir, "Scripts", "pip.exe")
49
- : path.join(venvDir, "bin", "pip");
22
+ function getHome() { return os.homedir(); }
23
+ function getDataDir() { return path.join(getHome(), ".myagent"); }
24
+ function getVenvDir() { return path.join(getDataDir(), "venv"); }
25
+ function getSentinelFile() { return path.join(getDataDir(), ".deps_installed"); }
26
+ function getVenvPython(d) {
27
+ return IS_WIN ? path.join(d, "Scripts", "python.exe") : path.join(d, "bin", "python");
50
28
  }
51
29
 
52
- // MyAgent 数据目录
53
- function getDataDir() {
54
- return path.join(os.homedir(), ".myagent");
55
- }
56
-
57
- // ── 解析包目录 ────────────────────────────────────────────
58
30
  function resolvePackageDir() {
59
31
  let dir = __dirname;
60
32
  if (!fs.existsSync(path.join(dir, "main.py"))) {
@@ -62,8 +34,8 @@ function resolvePackageDir() {
62
34
  const npmRoot = execSync("npm root -g", {
63
35
  encoding: "utf8", stdio: ["pipe", "pipe", "pipe"],
64
36
  }).trim();
65
- const candidate = path.join(npmRoot, "myagent-ai");
66
- if (fs.existsSync(path.join(candidate, "main.py"))) dir = candidate;
37
+ const c = path.join(npmRoot, PKG_NAME);
38
+ if (fs.existsSync(path.join(c, "main.py"))) dir = c;
67
39
  } catch (_) {}
68
40
  }
69
41
  if (!fs.existsSync(path.join(dir, "main.py"))) {
@@ -76,651 +48,356 @@ function resolvePackageDir() {
76
48
  return dir;
77
49
  }
78
50
 
79
- // ── 查找系统 Python(用于创建 venv) ─────────────────────
80
51
  function findSystemPython() {
81
52
  const candidates = IS_WIN
82
53
  ? ["python", "python3", "python3.14", "python3.13"]
83
54
  : ["python3", "python3.14", "python3.13", "python"];
84
-
85
55
  for (const cmd of candidates) {
86
56
  try {
87
- const result = execFileSync(
88
- IS_WIN ? `${cmd}.exe` : cmd,
89
- ["--version"],
57
+ const r = execFileSync(
58
+ IS_WIN ? `${cmd}.exe` : cmd, ["--version"],
90
59
  { encoding: "utf8", stdio: ["pipe", "pipe", "pipe"], timeout: 5000 }
91
60
  );
92
- const match = result.match(/Python (\d+)\.(\d+)/);
93
- if (match) {
94
- const major = parseInt(match[1], 10);
95
- const minor = parseInt(match[2], 10);
96
- if (major >= 3 && minor >= 13) return cmd;
97
- }
61
+ const m = r.match(/Python (\d+)\.(\d+)/);
62
+ if (m && parseInt(m[1]) >= 3 && parseInt(m[2]) >= 13) return cmd;
98
63
  } catch (_) {}
99
64
  }
100
-
101
- // Windows: 搜索常见安装路径
102
65
  if (IS_WIN) {
103
66
  const localAppData = process.env.LOCALAPPDATA || "";
104
67
  const programFiles = process.env.ProgramFiles || "";
105
- const programFilesX86 = process.env["ProgramFiles(x86)"] || "";
106
- const searchPaths = [
68
+ for (const p of [
107
69
  path.join(localAppData, "Programs", "Python", "Python314", "python.exe"),
108
70
  path.join(localAppData, "Programs", "Python", "Python313", "python.exe"),
109
71
  path.join(programFiles, "Python314", "python.exe"),
110
72
  path.join(programFiles, "Python313", "python.exe"),
111
73
  "C:\\Python314\\python.exe", "C:\\Python313\\python.exe",
112
- ];
113
- for (const pyPath of searchPaths) {
114
- if (fs.existsSync(pyPath)) return pyPath;
74
+ ]) {
75
+ if (fs.existsSync(p)) return p;
115
76
  }
116
77
  }
117
-
118
78
  return null;
119
79
  }
120
80
 
121
- // ── 虚拟环境管理 ─────────────────────────────────────────
122
-
123
- /**
124
- * 尝试自动安装 python3.xx-venv 模块 (Debian/Ubuntu)
125
- * Returns: true if successfully installed
126
- */
127
- function tryAutoInstallVenvModule(systemPython) {
128
- try {
129
- // 先检测是否是 apt 系统
130
- execFileSync("which", ["apt-get"], {
131
- encoding: "utf8", stdio: ["pipe", "pipe", "pipe"], timeout: 5000,
132
- });
133
- } catch (_) {
134
- // 不是 apt 系统
135
- return false;
81
+ function getPipMirrorArgs() {
82
+ const envMirror = process.env.MYAGENT_PIP_MIRROR || "";
83
+ if (envMirror === "1" || envMirror === "true" || envMirror === "cn") {
84
+ return ["-i", "https://pypi.tuna.tsinghua.edu.cn/simple", "--trusted-host", "pypi.tuna.tsinghua.edu.cn"];
136
85
  }
137
-
138
- try {
139
- // 获取 Python 版本号
140
- const ver = execFileSync(systemPython, ["-c", "import sys; print(f'{sys.version_info.major}.{sys.version_info.minor}')"], {
141
- encoding: "utf8", stdio: ["pipe", "pipe", "pipe"], timeout: 5000,
142
- }).trim();
143
-
144
- console.log(` \x1b[90m[i]\x1b[0m 正在安装 python${ver}-venv (需要 sudo 权限)...`);
145
-
146
- execFileSync("sudo", ["apt-get", "install", "-y", `python${ver}-venv`], {
147
- encoding: "utf8", stdio: "inherit", timeout: 120000,
148
- });
149
-
150
- console.log(` \x1b[32m[✓]\x1b[0m python${ver}-venv 已安装`);
151
- return true;
152
- } catch (err) {
153
- console.log(` \x1b[33m[!]\x1b[0m 自动安装 venv 模块失败: ${err.message}`);
154
- console.log(` \x1b[90m[i]\x1b[0m 请手动运行: sudo apt install python3-venv`);
155
- return false;
86
+ const lang = (process.env.LANG || process.env.LC_ALL || "").toLowerCase();
87
+ if (lang.includes("zh_cn") || lang.includes("chinese")) {
88
+ return ["-i", "https://pypi.tuna.tsinghua.edu.cn/simple", "--trusted-host", "pypi.tuna.tsinghua.edu.cn"];
156
89
  }
90
+ return [];
157
91
  }
158
92
 
159
- /**
160
- * 确保 venv 存在且可用
161
- * Returns: { venvDir, venvPython, venvPip }
162
- */
93
+ // ── 虚拟环境 ──────────────────────────────────────────────
94
+
163
95
  function ensureVenv() {
164
96
  const venvDir = getVenvDir();
165
97
  const venvPython = getVenvPython(venvDir);
166
- const venvPip = getVenvPip(venvDir);
167
-
168
- // 检查现有 venv 是否完整
169
98
  if (fs.existsSync(venvPython)) {
170
99
  try {
171
100
  execFileSync(venvPython, ["--version"], {
172
101
  encoding: "utf8", stdio: ["pipe", "pipe", "pipe"], timeout: 5000,
173
102
  });
174
- return { venvDir, venvPython, venvPip, isNew: false };
103
+ return venvPython;
175
104
  } catch (_) {
176
- // venv 损坏,需要重建
177
- console.log(" \x1b[33m[!]\x1b[0m 虚拟环境已损坏,正在重建...");
178
105
  fs.rmSync(venvDir, { recursive: true, force: true });
179
106
  }
180
107
  }
181
-
182
- // 创建 venv
183
- const systemPython = findSystemPython();
184
- if (!systemPython) {
185
- console.error("\x1b[31m[✗]\x1b[0m 未找到 Python 3.13+");
186
- console.error(" 请先安装 Python: https://www.python.org/downloads/");
187
- console.error(" 安装时请勾选 'Add Python to PATH'");
188
- console.error("");
189
- console.error(" 或一键安装:");
190
- if (IS_WIN) {
191
- console.error(" powershell -c \"irm https://raw.githubusercontent.com/ctz168/myagent/main/install/install.ps1 | iex\"");
192
- } else {
193
- console.error(" curl -fsSL https://raw.githubusercontent.com/ctz168/myagent/main/install/install.sh | bash");
194
- }
108
+ const sysPy = findSystemPython();
109
+ if (!sysPy) {
110
+ console.error("\x1b[31m未找到 Python 3.13+\x1b[0m");
111
+ console.error("请先安装 Python: https://www.python.org/downloads/");
195
112
  process.exit(1);
196
113
  }
197
-
198
- // 确保 ~/.myagent 目录存在
199
114
  const dataDir = getDataDir();
200
- if (!fs.existsSync(dataDir)) {
201
- fs.mkdirSync(dataDir, { recursive: true });
202
- }
203
-
204
- console.log(" \x1b[36m[*]\x1b[0m 创建独立虚拟环境...");
205
- console.log(` \x1b[90m[i]\x1b[0m 位置: ${venvDir}`);
206
- console.log(` \x1b[90m[i]\x1b[0m 系统Python: ${systemPython}`);
115
+ if (!fs.existsSync(dataDir)) fs.mkdirSync(dataDir, { recursive: true });
207
116
 
117
+ console.log(" 创建虚拟环境...");
208
118
  try {
209
- execFileSync(systemPython, ["-m", "venv", venvDir], {
119
+ execFileSync(sysPy, ["-m", "venv", venvDir], {
210
120
  encoding: "utf8", stdio: "inherit", timeout: 60000,
211
121
  });
212
- } catch (err) {
213
- // Debian/Ubuntu python3.xx-venv 需要单独安装
214
- console.log(`\x1b[33m[!]\x1b[0m 虚拟环境创建失败,尝试自动安装 venv 模块...`);
215
-
216
- const autoInstalled = !IS_WIN && tryAutoInstallVenvModule(systemPython);
217
-
218
- if (autoInstalled) {
219
- // 重试创建 venv
122
+ } catch (_) {
123
+ // Debian/Ubuntu: 尝试安装 venv 模块
124
+ if (!IS_WIN) {
220
125
  try {
221
- execFileSync(systemPython, ["-m", "venv", venvDir], {
126
+ execFileSync("sudo", ["apt-get", "install", "-y", "python3-venv"], {
127
+ encoding: "utf8", stdio: "inherit", timeout: 120000,
128
+ });
129
+ execFileSync(sysPy, ["-m", "venv", venvDir], {
222
130
  encoding: "utf8", stdio: "inherit", timeout: 60000,
223
131
  });
224
- } catch (retryErr) {
225
- console.error(`\x1b[31m[✗]\x1b[0m 重试创建虚拟环境仍然失败: ${retryErr.message}`);
132
+ } catch (_) {
133
+ console.error("\x1b[31m创建虚拟环境失败\x1b[0m");
134
+ console.error("请手动运行: sudo apt install python3-venv");
226
135
  process.exit(1);
227
136
  }
228
137
  } else {
229
- console.error(`\x1b[31m[✗]\x1b[0m 创建虚拟环境失败: ${err.message}`);
230
- if (!IS_WIN) {
231
- console.error("");
232
- console.error(" 在 Debian/Ubuntu 上,python3.xx-venv 需要单独安装:");
233
- console.error(" sudo apt install python3-venv");
234
- console.error(" 然后运行: myagent-ai reinstall");
235
- console.error("");
236
- }
138
+ console.error("\x1b[31m创建虚拟环境失败\x1b[0m");
237
139
  process.exit(1);
238
140
  }
239
141
  }
240
-
241
- // 验证创建成功
242
- if (!fs.existsSync(venvPython)) {
243
- console.error("\x1b[31m[✗]\x1b[0m 虚拟环境创建后未找到 Python,请检查系统 Python 安装");
142
+ if (!fs.existsSync(getVenvPython(venvDir))) {
143
+ console.error("\x1b[31m虚拟环境创建失败\x1b[0m");
244
144
  process.exit(1);
245
145
  }
246
-
247
- console.log(" \x1b[32m[✓]\x1b[0m 虚拟环境已创建");
248
- return { venvDir, venvPython, venvPip, isNew: true };
249
- }
250
-
251
- // ── 依赖安装 ─────────────────────────────────────────────
252
-
253
- // 从 requirements.txt 解析出 Python 模块名(用于 import 检查)
254
- function parseRequirements(reqFile) {
255
- const modules = [];
256
- try {
257
- const lines = fs.readFileSync(reqFile, "utf8").split("\n");
258
- for (const raw of lines) {
259
- const line = raw.trim();
260
- if (!line || line.startsWith("#")) continue;
261
- // 解析: openai>=1.12.0 → openai, python-telegram-bot>=21.0 → telegram
262
- const match = line.match(/^([a-zA-Z0-9_-]+)/);
263
- if (match) {
264
- const pkg = match[1].toLowerCase().replace(/-/g, "_");
265
- // 特殊映射: pip 包名和 import 名不一致的
266
- const importMap = {
267
- "beautifulsoup4": "bs4",
268
- "py_getwindow": "pygetwindow",
269
- "python_telegram_bot": "telegram",
270
- "pillow": "PIL",
271
- "psutil": "psutil",
272
- "edge_tts": "edge_tts",
273
- };
274
- modules.push(importMap[pkg] || pkg);
275
- }
276
- }
277
- } catch (_) {
278
- // 解析失败,回退到核心包列表
279
- modules.push("openai", "aiohttp", "requests");
280
- }
281
- return modules;
146
+ console.log(" \x1b[32m✓\x1b[0m 虚拟环境已创建");
147
+ return getVenvPython(venvDir);
282
148
  }
283
149
 
284
- // 核心依赖包(fallback 用,不依赖文件解析)
285
- // 包含 tray (pystray/Pillow) 等关键依赖,确保回退安装时也能装上
286
- const CORE_PACKAGES = [
287
- "openai>=1.12.0",
288
- "aiohttp>=3.9.0",
289
- "requests>=2.31.0",
290
- "duckduckgo-search>=6.0.0",
291
- "beautifulsoup4>=4.12.0",
292
- "lxml>=5.0.0",
293
- "psutil>=5.9.0",
294
- "pystray>=0.19.5",
295
- "Pillow>=10.0.0",
296
- "edge-tts>=6.1.0",
297
- "faster-whisper>=1.0.0",
298
- "anthropic>=0.18.0",
299
- ];
300
-
301
- // 获取 pip 镜像源参数(国内用户自动使用清华镜像)
302
- function getPipMirrorArgs() {
303
- const envMirror = process.env.MYAGENT_PIP_MIRROR || "";
304
- if (envMirror === "1" || envMirror === "true" || envMirror === "cn") {
305
- return ["-i", "https://pypi.tuna.tsinghua.edu.cn/simple",
306
- "--trusted-host", "pypi.tuna.tsinghua.edu.cn"];
307
- }
308
- // 通过语言环境判断是否在国内(Windows 通过环境变量,其他通过 LANG)
309
- const lang = (process.env.LANG || process.env.LC_ALL || "").toLowerCase();
310
- if (lang.includes("zh_cn") || lang.includes("chinese")) {
311
- return ["-i", "https://pypi.tuna.tsinghua.edu.cn/simple",
312
- "--trusted-host", "pypi.tuna.tsinghua.edu.cn"];
313
- }
314
- return [];
315
- }
150
+ // ── 依赖安装(仅在 install/reinstall/首次运行时调用) ───
316
151
 
317
- function installDeps(venvPython, venvPip, pkgDir) {
152
+ function installAllDeps(venvPython, pkgDir) {
318
153
  const reqFile = path.join(pkgDir, "requirements.txt");
319
- const allModules = parseRequirements(reqFile);
320
-
321
- // 快速检查关键模块是否都存在
322
- let missing = [];
323
- console.log(" \x1b[36m[*]\x1b[0m 检查依赖...");
324
-
325
- // 检查所有模块(不超过 30 个),托盘和 GUI 依赖也必须检测
326
- const checkLimit = Math.min(allModules.length, 30);
327
- for (let i = 0; i < checkLimit; i++) {
328
- const mod = allModules[i];
329
- try {
330
- execFileSync(venvPython, ["-c", `import ${mod}`], {
331
- encoding: "utf8", stdio: ["pipe", "pipe", "pipe"], timeout: 5000,
332
- });
333
- } catch (_) {
334
- missing.push(mod);
335
- }
336
- }
337
-
338
- if (missing.length === 0) {
339
- console.log(` \x1b[32m[✓]\x1b[0m 全部 ${checkLimit} 个依赖检查通过`);
340
- return;
341
- }
342
-
343
- console.log(` \x1b[33m[!]\x1b[0m 缺失 ${missing.length} 个包: ${missing.join(", ")}`);
154
+ const mirrorArgs = getPipMirrorArgs();
155
+ if (mirrorArgs.length) console.log(" 使用国内镜像源 (清华)");
344
156
 
345
- // 策略1: 升级 pip
157
+ // 升级 pip
346
158
  try {
347
- console.log(" \x1b[90m[i]\x1b[0m 升级 pip...");
348
- execFileSync(venvPython, ["-m", "pip", "install", "--upgrade", "pip", "--quiet"], {
159
+ execFileSync(venvPython, ["-m", "pip", "install", "--upgrade", "pip", "-q"], {
349
160
  encoding: "utf8", stdio: ["pipe", "pipe", "pipe"], timeout: 120000,
350
161
  });
351
162
  } catch (_) {}
352
163
 
353
- // pip 镜像源参数
354
- const mirrorArgs = getPipMirrorArgs();
355
-
356
- // Linux: 预装 evdev 预编译包,避免 pynput 安装时编译失败
164
+ // Linux: 预装 evdev
357
165
  if (!IS_WIN) {
358
166
  try {
359
- execFileSync(venvPython, ["-m", "pip", "install", "evdev-binary", "--quiet", "--disable-pip-version-check"], {
167
+ execFileSync(venvPython, ["-m", "pip", "install", "evdev-binary", "-q", "--disable-pip-version-check"], {
360
168
  encoding: "utf8", stdio: ["pipe", "pipe", "pipe"], timeout: 60000,
361
169
  });
362
170
  } catch (_) {}
363
171
  }
364
172
 
365
- // 策略2: pip install -r requirements.txt(venv 内无 PEP668 限制)
366
- let installed = false;
173
+ // 安装全部依赖
367
174
  if (fs.existsSync(reqFile)) {
368
- console.log(`\x1b[33m[!]\x1b[0m 正在安装 ${missing.length} 个缺失依赖到虚拟环境...`);
369
- if (mirrorArgs.length > 0) {
370
- console.log(" \x1b[90m[i]\x1b[0m 使用国内镜像源 (清华)");
371
- }
175
+ console.log(" 安装依赖 (可能需要几分钟)...");
372
176
  try {
373
177
  execFileSync(venvPython, ["-m", "pip", "install", "-r", reqFile, "--disable-pip-version-check", ...mirrorArgs], {
374
- encoding: "utf8", stdio: "inherit", timeout: 300000,
178
+ encoding: "utf8", stdio: "inherit", timeout: 600000,
375
179
  });
376
- console.log(" \x1b[32m[✓]\x1b[0m 依赖安装完成");
377
- installed = true;
180
+ console.log(" \x1b[32m✓\x1b[0m 全部依赖安装完成");
181
+ return true;
378
182
  } catch (err) {
379
- console.log(" \x1b[33m[!]\x1b[0m requirements.txt 整体安装失败,逐个安装缺失依赖...");
380
- console.log(` \x1b[90m[i]\x1b[0m 错误: ${err.message}`);
183
+ console.log(` \x1b[33m安装失败: ${err.message.split("\n").pop().trim()}\x1b[0m`);
381
184
  }
382
185
  }
383
186
 
384
- // 策略2.5: 逐个安装缺失的包(当整体安装失败时)
385
- if (!installed && missing.length > 0) {
386
- console.log(` \x1b[90m[i]\x1b[0m 逐个安装 ${missing.length} 个缺失包...`);
387
- // 构建反向映射: import名 → pip包名(含版本)
388
- const importToPip = {};
187
+ // 回退: 核心依赖
188
+ const CORE = [
189
+ "openai>=1.12.0", "aiohttp>=3.9.0", "requests>=2.31.0",
190
+ "duckduckgo-search>=6.0.0", "beautifulsoup4>=4.12.0", "lxml>=5.0.0",
191
+ "psutil>=5.9.0", "Pillow>=10.0.0", "edge-tts>=6.1.0",
192
+ "anthropic>=0.18.0",
193
+ ];
194
+ for (const mirrors of [mirrorArgs, ["-i", "https://mirrors.aliyun.com/pypi/simple/", "--trusted-host", "mirrors.aliyun.com"]]) {
389
195
  try {
390
- const lines = fs.readFileSync(reqFile, "utf8").split("\n");
391
- for (const raw of lines) {
392
- const line = raw.trim();
393
- if (!line || line.startsWith("#")) continue;
394
- const m = line.match(/^([a-zA-Z0-9_-]+)/);
395
- if (m) {
396
- const pipName = m[1].toLowerCase().replace(/-/g, "_");
397
- const pipSpec = line.split(/[;#]/)[0].trim();
398
- importToPip[pipName] = pipSpec;
399
- // 特殊映射 (和 parseRequirements 中的 importMap 一致)
400
- const specialMap = {
401
- "beautifulsoup4": "bs4",
402
- "py_getwindow": "pygetwindow",
403
- "python_telegram_bot": "telegram",
404
- "pillow": "PIL",
405
- "psutil": "psutil",
406
- "edge_tts": "edge_tts",
407
- };
408
- const importName = specialMap[pipName] || pipName;
409
- importToPip[importName] = pipSpec;
410
- }
411
- }
196
+ console.log(" 尝试安装核心依赖...");
197
+ execFileSync(venvPython, ["-m", "pip", "install", "-q", "--disable-pip-version-check", ...mirrors, ...CORE], {
198
+ encoding: "utf8", stdio: "inherit", timeout: 300000,
199
+ });
200
+ console.log(" \x1b[32m✓\x1b[0m 核心依赖安装完成");
201
+ return true;
412
202
  } catch (_) {}
413
-
414
- let failCount = 0;
415
- for (const mod of missing) {
416
- try {
417
- const pkgSpec = importToPip[mod] || mod;
418
- execFileSync(venvPython, ["-m", "pip", "install", "--disable-pip-version-check", ...mirrorArgs, pkgSpec], {
419
- encoding: "utf8", stdio: ["pipe", "pipe", "pipe"], timeout: 120000,
420
- });
421
- console.log(` \x1b[32m[✓]\x1b[0m ${mod} 安装成功`);
422
- } catch (_) {
423
- failCount++;
424
- console.log(` \x1b[31m[✗]\x1b[0m ${mod} 安装失败`);
425
- }
426
- }
427
- if (failCount === 0) {
428
- console.log(" \x1b[32m[✓]\x1b[0m 所有缺失依赖安装成功");
429
- installed = true;
430
- } else if (failCount < missing.length) {
431
- console.log(` \x1b[33m[!]\x1b[0m ${missing.length - failCount}/${missing.length} 个依赖安装成功,${failCount} 个失败`);
432
- installed = true; // 部分成功也算,核心依赖优先
433
- }
434
203
  }
204
+ return false;
205
+ }
435
206
 
436
- // 策略3: 直接按包名安装核心依赖(最终兜底)
437
- if (!installed) {
438
- try {
439
- execFileSync(venvPython, ["-m", "pip", "install", "--quiet", "--disable-pip-version-check", ...mirrorArgs, ...CORE_PACKAGES], {
440
- encoding: "utf8", stdio: "inherit", timeout: 180000,
441
- });
442
- console.log(" \x1b[32m[✓]\x1b[0m 核心依赖安装完成");
443
- console.log(" \x1b[90m[i]\x1b[0m 其他依赖将在启动时自动安装");
444
- } catch (_) {
445
- // 策略4: 尝试阿里云镜像
446
- console.log(" \x1b[33m[!]\x1b[0m 核心依赖安装失败,尝试阿里云镜像...");
447
- try {
448
- const aliyunArgs = ["-i", "https://mirrors.aliyun.com/pypi/simple/", "--trusted-host", "mirrors.aliyun.com"];
449
- execFileSync(venvPython, ["-m", "pip", "install", "--quiet", "--disable-pip-version-check", ...aliyunArgs, ...CORE_PACKAGES], {
450
- encoding: "utf8", stdio: "inherit", timeout: 180000,
451
- });
452
- console.log(" \x1b[32m[✓]\x1b[0m 核心依赖安装完成(阿里云镜像)");
453
- } catch (_) {
454
- console.error(" \x1b[31m[✗]\x1b[0m 依赖安装失败,请手动运行:");
455
- console.error(` ${venvPython} -m pip install -r "${reqFile}"`);
456
- console.error("");
457
- console.error(" 或使用重新安装命令: myagent-ai reinstall");
458
- console.error("");
459
- }
460
- }
461
- }
207
+ // 标记依赖已安装
208
+ function markDepsInstalled(version) {
209
+ try {
210
+ const dir = getDataDir();
211
+ if (!fs.existsSync(dir)) fs.mkdirSync(dir, { recursive: true });
212
+ fs.writeFileSync(getSentinelFile(), version);
213
+ } catch (_) {}
462
214
  }
463
215
 
464
- // ── 构建 main.py 参数 ────────────────────────────────────
465
- function buildArgs(userArgs) {
466
- const mode = userArgs[0] || "";
467
- switch (mode) {
468
- case "cli": return ["main.py"];
469
- case "web": return ["main.py", "--web"];
470
- case "tray": return ["main.py", "--tray"];
471
- case "server": return ["main.py", "--server"];
472
- case "setup": return ["main.py", "--setup"];
473
- case "reinstall":
474
- return []; // 特殊处理
475
- case "uninstall":
476
- return []; // 特殊处理
477
- default:
478
- return ["main.py", ...userArgs];
216
+ function isDepsInstalled(pkgVersion) {
217
+ try {
218
+ if (!fs.existsSync(getSentinelFile())) return false;
219
+ return fs.readFileSync(getSentinelFile(), "utf8").trim() === pkgVersion;
220
+ } catch (_) {
221
+ return false;
479
222
  }
480
223
  }
481
224
 
482
- // ── 主入口 ─────────────────────────────────────────────────
483
- function main() {
484
- const userArgs = process.argv.slice(2);
485
- const pkgDir = resolvePackageDir();
486
-
487
- if (!fs.existsSync(path.join(pkgDir, "main.py"))) {
488
- console.error("\x1b[31m[✗]\x1b[0m 错误: 找不到 main.py");
489
- console.error(` 搜索路径: ${pkgDir}`);
490
- console.error(' 请重新安装: npm install -g myagent-ai');
491
- process.exit(1);
492
- }
225
+ // ── 命令处理 ──────────────────────────────────────────────
493
226
 
494
- // 特殊命令: uninstall
495
- if (userArgs[0] === "uninstall") {
496
- const venvDir = getVenvDir();
497
- const purgeArg = userArgs.includes("--purge") || userArgs.includes("-p");
498
- const dataDir = getDataDir();
227
+ function cmdInstall(pkgDir) {
228
+ console.log("");
229
+ console.log(" \x1b[36mMyAgent 安装依赖\x1b[0m");
230
+ console.log("");
231
+ const venvPython = ensureVenv();
232
+ installAllDeps(venvPython, pkgDir);
233
+ let ver = "";
234
+ try { ver = JSON.parse(fs.readFileSync(path.join(pkgDir, "package.json"), "utf8")).version || ""; } catch (_) {}
235
+ markDepsInstalled(ver);
236
+ console.log("");
237
+ console.log(" \x1b[32m✓ 安装完成,可以启动了: myagent-ai web\x1b[0m");
238
+ console.log("");
239
+ }
499
240
 
500
- // Step 1: 停止服务
501
- console.log(" \x1b[36m[*]\x1b[0m 停止 MyAgent 服务...");
502
- try {
503
- const http = require("http");
504
- const req = http.request({ hostname: "127.0.0.1", port: 8767, path: "/api/shutdown", method: "POST", timeout: 5000 }, () => {
505
- // 忽略响应
506
- });
507
- req.on("error", () => {});
508
- req.end();
509
- console.log(" \x1b[32m[✓]\x1b[0m 已发送关闭请求");
510
- setTimeout(() => {}, 2000);
511
- } catch (_) {
512
- console.log(" \x1b[90m[i]\x1b[0m 服务未运行");
513
- }
241
+ function cmdReinstall(pkgDir) {
242
+ console.log("");
243
+ console.log(" \x1b[36mMyAgent 重装依赖\x1b[0m");
244
+ console.log("");
245
+ const venvDir = getVenvDir();
246
+ if (fs.existsSync(venvDir)) {
247
+ console.log(" 删除旧虚拟环境...");
248
+ fs.rmSync(venvDir, { recursive: true, force: true });
249
+ }
250
+ const venvPython = ensureVenv();
251
+ installAllDeps(venvPython, pkgDir);
252
+ let ver = "";
253
+ try { ver = JSON.parse(fs.readFileSync(path.join(pkgDir, "package.json"), "utf8")).version || ""; } catch (_) {}
254
+ markDepsInstalled(ver);
255
+ console.log("");
256
+ console.log(" \x1b[32m✓ 重装完成\x1b[0m");
257
+ console.log("");
258
+ }
514
259
 
515
- // Step 2: 终止 Python/Node 进程
516
- try {
517
- if (IS_WIN) {
518
- execSync("taskkill /F /IM python.exe /FI \"WINDOWTITLE eq myagent*\"", { encoding: "utf8", stdio: ["pipe", "pipe", "pipe"], timeout: 5000 });
519
- } else {
520
- execSync("pkill -f 'myagent|main.py' 2>/dev/null; sleep 1", { encoding: "utf8", stdio: ["pipe", "pipe", "pipe"], timeout: 10000 });
521
- }
522
- } catch (_) {}
523
- console.log(" \x1b[32m[✓]\x1b[0m 进程已停止");
260
+ function cmdUninstall() {
261
+ const venvDir = getVenvDir();
262
+ const dataDir = getDataDir();
263
+ const purgeArg = process.argv.includes("--purge") || process.argv.includes("-p");
524
264
 
525
- // Step 3: npm uninstall
526
- console.log(" \x1b[36m[*]\x1b[0m 卸载 npm 全局包...");
527
- try {
528
- execFileSync("npm", ["uninstall", "-g", PKG_NAME], {
529
- encoding: "utf8", stdio: "inherit", timeout: 60000,
530
- });
531
- console.log(" \x1b[32m[✓]\x1b[0m npm 全局包已卸载");
532
- } catch (_) {
533
- console.log(" \x1b[90m[i]\x1b[0m npm 全局包未找到");
534
- }
265
+ console.log("");
266
+ console.log(" \x1b[36mMyAgent 卸载\x1b[0m");
267
+ console.log("");
535
268
 
536
- // Step 4: 清理数据(--purge)
537
- if (purgeArg) {
538
- console.log("");
539
- console.log(" \x1b[36m[*]\x1b[0m 清除所有数据...");
540
- if (fs.existsSync(dataDir)) {
541
- fs.rmSync(dataDir, { recursive: true, force: true });
542
- console.log(" \x1b[32m[✓]\x1b[0m 数据目录已删除: " + dataDir);
543
- } else {
544
- console.log(" \x1b[90m[i]\x1b[0m 数据目录不存在");
545
- }
269
+ // 停止服务
270
+ try {
271
+ const http = require("http");
272
+ const req = http.request({ hostname: "127.0.0.1", port: 8767, path: "/api/shutdown", method: "POST", timeout: 5000 }, () => {});
273
+ req.on("error", () => {});
274
+ req.end();
275
+ } catch (_) {}
276
+ try {
277
+ if (IS_WIN) {
278
+ execSync('taskkill /F /IM python.exe /FI "WINDOWTITLE eq myagent*" 2>nul', { encoding: "utf8", timeout: 5000 });
546
279
  } else {
547
- console.log("");
548
- console.log(" \x1b[90m[i]\x1b[0m 保留数据目录: " + dataDir);
549
- console.log(" \x1b[90m[i]\x1b[0m 如需彻底清除: myagent-ai uninstall --purge");
550
- }
551
-
552
- console.log("");
553
- console.log(" \x1b[32m[✓]\x1b[0m 卸载完成!");
554
- console.log(" \x1b[90m[i]\x1b[0m 重新安装: npm install -g myagent-ai");
555
- console.log("");
556
- return;
557
- }
558
-
559
- // 特殊命令: reinstall
560
- if (userArgs[0] === "reinstall") {
561
- const venvDir = getVenvDir();
562
- if (fs.existsSync(venvDir)) {
563
- console.log(" \x1b[36m[*]\x1b[0m 删除旧虚拟环境...");
564
- fs.rmSync(venvDir, { recursive: true, force: true });
280
+ execSync("pkill -f 'myagent|main.py' 2>/dev/null", { encoding: "utf8", timeout: 10000 });
565
281
  }
566
- const { venvPython, venvPip } = ensureVenv();
567
- installDeps(venvPython, venvPip, pkgDir);
568
- console.log("");
569
- console.log(" \x1b[32m[✓]\x1b[0m 依赖已全部重新安装到虚拟环境");
570
- console.log(` \x1b[90m[i]\x1b[0m 虚拟环境: ${venvDir}`);
571
- console.log("");
572
- return;
573
- }
282
+ } catch (_) {}
574
283
 
575
- // 打印 Banner(显示版本号)
576
- let pkgVersion = "";
577
284
  try {
578
- const pkgJson = path.join(pkgDir, "package.json");
579
- const pkg = JSON.parse(fs.readFileSync(pkgJson, "utf8"));
580
- pkgVersion = pkg.version || "";
285
+ execFileSync("npm", ["uninstall", "-g", PKG_NAME], {
286
+ encoding: "utf8", stdio: "inherit", timeout: 60000,
287
+ });
581
288
  } catch (_) {}
582
- console.log("");
583
- if (pkgVersion) {
584
- console.log(` \x1b[1m\x1b[36mMyAgent\x1b[0m v${pkgVersion} - 本地桌面端执行型 AI 助手`);
585
- } else {
586
- console.log(" \x1b[1m\x1b[36mMyAgent\x1b[0m - 本地桌面端执行型 AI 助手");
289
+
290
+ if (purgeArg && fs.existsSync(dataDir)) {
291
+ fs.rmSync(dataDir, { recursive: true, force: true });
292
+ console.log(" 数据已清除");
587
293
  }
588
294
  console.log("");
295
+ console.log(" \x1b[32m✓ 卸载完成\x1b[0m");
296
+ console.log("");
297
+ }
589
298
 
590
- // 是否跳过依赖检查
591
- const skipDeps = userArgs.includes("--skip-deps") || userArgs.includes("--no-deps");
592
- // 从参数中移除 --skip-deps/--no-deps,避免传入 main.py
593
- const filteredArgs = userArgs.filter(a => a !== "--skip-deps" && a !== "--no-deps");
594
-
595
- // 确保 venv 存在
596
- const { venvDir, venvPython, isNew } = ensureVenv();
597
-
598
- // 检查并安装依赖(--skip-deps 时跳过)
599
- if (skipDeps) {
600
- console.log(" \x1b[90m[i]\x1b[0m 跳过依赖检查(--skip-deps)");
601
- } else if (isNew) {
602
- installDeps(venvPython, getVenvPip(venvDir), pkgDir);
603
- } else {
604
- // 即使 venv 已存在,也快速检查核心依赖
605
- const venvPip = getVenvPip(venvDir);
606
- installDeps(venvPython, venvPip, pkgDir);
299
+ function cmdRun(pkgDir, userArgs) {
300
+ const venvPython = getVenvPython(getVenvDir());
301
+ if (!fs.existsSync(venvPython)) {
302
+ console.error("\x1b[31m虚拟环境不存在,请先运行: myagent-ai install\x1b[0m");
303
+ process.exit(1);
607
304
  }
608
305
 
609
- // 首次运行检测
610
- const configFile = path.join(getDataDir(), "config.json");
611
- const isFirstRun = !fs.existsSync(configFile);
612
- if (isFirstRun) {
306
+ let ver = "";
307
+ try { ver = JSON.parse(fs.readFileSync(path.join(pkgDir, "package.json"), "utf8")).version || ""; } catch (_) {}
308
+
309
+ // 首次运行自动安装
310
+ if (!isDepsInstalled(ver)) {
311
+ console.log("");
312
+ console.log(" \x1b[36m首次运行,正在安装依赖...\x1b[0m");
613
313
  console.log("");
614
- console.log(" \x1b[90m[i]\x1b[0m 检测到首次运行,MyAgent 将引导你完成 LLM 配置。");
314
+ installAllDeps(venvPython, pkgDir);
315
+ markDepsInstalled(ver);
615
316
  console.log("");
616
317
  }
617
318
 
618
- // 显示环境信息
619
- console.log(` \x1b[90m[i]\x1b[0m 虚拟环境: ${venvDir}`);
620
- console.log(` \x1b[90m[i]\x1b[0m Python: ${venvPython}`);
319
+ // 显示版本
621
320
  console.log("");
321
+ if (ver) {
322
+ console.log(` MyAgent v${ver}`);
323
+ }
622
324
 
623
- // 构建 Python 参数(使用过滤后的参数)
624
- let mode = filteredArgs[0] || "";
625
- let pyArgs = buildArgs(filteredArgs);
325
+ // 首次运行检测
326
+ const configFile = path.join(getDataDir(), "config.json");
327
+ const isFirstRun = !fs.existsSync(configFile);
328
+
329
+ // 构建参数
330
+ let mode = userArgs[0] || "";
331
+ let pyArgs;
332
+ switch (mode) {
333
+ case "cli": pyArgs = ["main.py"]; break;
334
+ case "web": pyArgs = ["main.py", "--web"]; break;
335
+ case "tray": pyArgs = ["main.py", "--tray"]; break;
336
+ case "server": pyArgs = ["main.py", "--server"]; break;
337
+ case "setup": pyArgs = ["main.py", "--setup"]; break;
338
+ default: pyArgs = ["main.py", ...userArgs]; mode = "";
339
+ }
626
340
 
627
- // 首次运行且未指定模式 → 自动选择 web 模式
628
341
  if (isFirstRun && !mode) {
629
342
  mode = "web";
630
343
  pyArgs = ["main.py", "--web"];
631
- console.log(" \x1b[90m[i]\x1b[0m 首次运行,自动启动 Web 模式进行配置...");
632
- console.log("");
633
- }
634
-
635
- if (mode) {
636
- const modeNames = {
637
- web: "Web 管理后台 (http://localhost:8767)",
638
- cli: "CLI 交互模式",
639
- tray: "系统托盘模式",
640
- server: "API 服务模式",
641
- setup: "配置向导",
642
- };
643
- console.log(`\x1b[36m启动 ${modeNames[mode] || mode}...\x1b[0m`);
644
- } else {
645
- console.log(`\x1b[36m启动...\x1b[0m`);
646
344
  }
647
345
 
648
- // 使用 venv 的 Python 启动
346
+ const venvDir = getVenvDir();
649
347
  const spawnEnv = {
650
348
  ...process.env,
651
- // 设置 VIRTUAL_ENV 环境变量,让 Python 程序知道自己运行在 venv 中
652
349
  VIRTUAL_ENV: venvDir,
653
350
  PATH: IS_WIN
654
351
  ? `${path.join(venvDir, "Scripts")};${process.env.PATH}`
655
352
  : `${path.join(venvDir, "bin")}:${process.env.PATH}`,
656
353
  };
657
- // 将 --skip-deps 信号传递给 Python,让 main.py 也跳过依赖检查
658
- if (skipDeps) {
659
- spawnEnv.MYAGENT_SKIP_DEPS = "1";
660
- }
661
- const child = spawn(venvPython, pyArgs, {
662
- cwd: pkgDir,
663
- stdio: "inherit",
664
- env: spawnEnv,
665
- });
666
-
667
- child.on("error", (err) => {
668
- console.error(`\x1b[31m[✗]\x1b[0m 启动失败: ${err.message}`);
669
- process.exit(1);
670
- });
671
354
 
672
- child.on("exit", (code) => {
673
- process.exit(code || 0);
674
- });
355
+ const child = spawn(venvPython, pyArgs, { cwd: pkgDir, stdio: "inherit", env: spawnEnv });
356
+ child.on("error", (err) => { console.error(`\x1b[31m启动失败: ${err.message}\x1b[0m`); process.exit(1); });
357
+ child.on("exit", (code) => { process.exit(code || 0); });
675
358
 
676
- // Web 模式:等服务启动后自动打开浏览器
359
+ // Web 模式自动打开浏览器
677
360
  if (mode === "web") {
678
- const port = 8767;
679
- const url = `http://127.0.0.1:${port}`;
361
+ const url = "http://127.0.0.1:8767";
680
362
  let opened = false;
681
-
682
- // 轮询等待服务就绪
683
- const pollInterval = setInterval(() => {
363
+ const poll = setInterval(() => {
684
364
  const http = require("http");
685
365
  const req = http.get(`${url}/api/status`, (res) => {
686
- clearInterval(pollInterval);
366
+ clearInterval(poll);
687
367
  if (!opened) {
688
368
  opened = true;
689
- console.log(` \x1b[32m[✓]\x1b[0m 管理后台已就绪: ${url}`);
690
- console.log(" \x1b[90m[i]\x1b[0m 正在打开浏览器...");
691
- console.log("");
692
- // 跨平台打开浏览器
693
369
  try {
694
- const { exec } = require("child_process");
695
- if (IS_WIN) {
696
- // Windows: start "" "url" — 空字符串防止 URL 被当作标题
697
- exec(`start "" "${url}"`);
698
- } else if (process.platform === "darwin") {
699
- exec(`open "${url}"`);
700
- } else {
701
- exec(`xdg-open "${url}"`);
702
- }
703
- } catch (_) {
704
- console.log(` \x1b[90m[i]\x1b[0m 请手动打开浏览器访问: ${url}`);
705
- }
370
+ if (IS_WIN) execSync(`start "" "${url}"`);
371
+ else if (process.platform === "darwin") execSync(`open "${url}"`);
372
+ else execSync(`xdg-open "${url}"`);
373
+ } catch (_) {}
706
374
  }
707
375
  });
708
- req.on("error", () => {
709
- // 服务尚未就绪,继续等待
710
- });
711
- req.setTimeout(2000, () => {
712
- req.destroy();
713
- });
376
+ req.on("error", () => {});
377
+ req.setTimeout(2000, () => { req.destroy(); });
714
378
  }, 1500);
379
+ setTimeout(() => { clearInterval(poll); }, 120000);
380
+ }
381
+ }
715
382
 
716
- // 最多等待 120 秒(首次安装 venv + 依赖可能需要较长时间)
717
- setTimeout(() => {
718
- clearInterval(pollInterval);
719
- if (!opened) {
720
- console.log(` \x1b[33m[!]\x1b[0m 等待超时,请手动打开浏览器访问: ${url}`);
721
- }
722
- }, 120000);
383
+ // ── 主入口 ──────────────────────────────────────────────
384
+
385
+ function main() {
386
+ const args = process.argv.slice(2);
387
+ const cmd = args[0];
388
+ const pkgDir = resolvePackageDir();
389
+
390
+ if (!fs.existsSync(path.join(pkgDir, "main.py"))) {
391
+ console.error("\x1b[31m找不到 main.py,请重新安装: npm install -g myagent-ai\x1b[0m");
392
+ process.exit(1);
723
393
  }
394
+
395
+ if (cmd === "uninstall") { cmdUninstall(); return; }
396
+ if (cmd === "reinstall") { cmdReinstall(pkgDir); return; }
397
+ if (cmd === "install") { cmdInstall(pkgDir); return; }
398
+
399
+ // 默认: 直接启动
400
+ cmdRun(pkgDir, args);
724
401
  }
725
402
 
726
403
  main();