galaxy-opc 0.3.8 → 0.4.0
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/bin/cli.mjs +177 -9
- package/package.json +1 -1
package/bin/cli.mjs
CHANGED
|
@@ -5,6 +5,7 @@
|
|
|
5
5
|
* npx galaxy-opc # 安装并初始化(首次使用)
|
|
6
6
|
* npx galaxy-opc setup # 重新配置 AI 模型
|
|
7
7
|
* npx galaxy-opc start # 启动服务
|
|
8
|
+
* npx galaxy-opc doctor # 诊断安装状态
|
|
8
9
|
*/
|
|
9
10
|
|
|
10
11
|
import fs from "node:fs";
|
|
@@ -137,6 +138,8 @@ if (command === "start") {
|
|
|
137
138
|
await cmdStart();
|
|
138
139
|
} else if (command === "setup") {
|
|
139
140
|
await cmdSetup();
|
|
141
|
+
} else if (command === "doctor") {
|
|
142
|
+
await cmdDoctor();
|
|
140
143
|
} else {
|
|
141
144
|
await cmdInstall();
|
|
142
145
|
}
|
|
@@ -165,6 +168,31 @@ ${bold(cyan(" ╚════════════════════
|
|
|
165
168
|
}
|
|
166
169
|
console.log(green(` ✓ Node.js v${process.versions.node}`));
|
|
167
170
|
|
|
171
|
+
// 检查 git 是否可用(macOS 没装 Xcode CLT 时 git 会失败)
|
|
172
|
+
const hasGit = checkTool("git");
|
|
173
|
+
if (!hasGit) {
|
|
174
|
+
if (process.platform === "darwin") {
|
|
175
|
+
console.log(yellow("\n ! git 未安装 — macOS 需要先安装 Xcode Command Line Tools"));
|
|
176
|
+
console.log(dim(" 正在尝试自动安装(弹窗后点击「安装」,等待完成)...\n"));
|
|
177
|
+
try {
|
|
178
|
+
execSync("xcode-select --install 2>/dev/null", { stdio: "inherit" });
|
|
179
|
+
} catch { /* 已安装时会报错,忽略 */ }
|
|
180
|
+
// 再次检测
|
|
181
|
+
if (!checkTool("git")) {
|
|
182
|
+
console.error(red("\n ✗ git 仍不可用,请手动执行后重试:"));
|
|
183
|
+
console.error(gray(" xcode-select --install\n"));
|
|
184
|
+
process.exit(1);
|
|
185
|
+
}
|
|
186
|
+
console.log(green(" ✓ git 已就绪"));
|
|
187
|
+
} else {
|
|
188
|
+
console.error(red("\n ✗ git 未安装,请先安装 git:"));
|
|
189
|
+
console.error(gray(" https://git-scm.com/downloads\n"));
|
|
190
|
+
process.exit(1);
|
|
191
|
+
}
|
|
192
|
+
} else {
|
|
193
|
+
console.log(green(" ✓ git 已安装"));
|
|
194
|
+
}
|
|
195
|
+
|
|
168
196
|
// ── 步骤 2:安装 openclaw ────────────────────────────────────────────────
|
|
169
197
|
separator();
|
|
170
198
|
console.log(bold(" 步骤 2 / 4 安装 OpenClaw 核心"));
|
|
@@ -175,18 +203,23 @@ ${bold(cyan(" ╚════════════════════
|
|
|
175
203
|
console.log(green(` ✓ OpenClaw 已安装 (${ocVersion})`));
|
|
176
204
|
} else {
|
|
177
205
|
console.log(dim(" 正在安装 OpenClaw(首次安装约 80MB+,使用国内镜像加速)...\n"));
|
|
178
|
-
// 临时覆盖 git url rewrite
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
206
|
+
// 临时覆盖 git url rewrite(强制 SSH 协议转 HTTPS,覆盖两种格式)
|
|
207
|
+
const gitRewrites = [
|
|
208
|
+
["url.https://github.com/.insteadOf", "git@github.com:"],
|
|
209
|
+
["url.https://github.com/.insteadOf", "ssh://git@github.com/"],
|
|
210
|
+
];
|
|
211
|
+
const gitRewritesSet = [];
|
|
212
|
+
for (const [key, val] of gitRewrites) {
|
|
213
|
+
try {
|
|
214
|
+
execSync(`git config --global ${key} "${val}"`, { stdio: "ignore" });
|
|
215
|
+
gitRewritesSet.push(key);
|
|
216
|
+
} catch { /* ignore */ }
|
|
217
|
+
}
|
|
184
218
|
|
|
185
219
|
try {
|
|
186
220
|
await runCommand("npm", [
|
|
187
221
|
"install", "-g", "openclaw@latest",
|
|
188
222
|
"--registry", "https://registry.npmmirror.com",
|
|
189
|
-
"--git-protocol", "https",
|
|
190
223
|
]);
|
|
191
224
|
console.log(green("\n ✓ OpenClaw 安装完成"));
|
|
192
225
|
} catch {
|
|
@@ -195,8 +228,8 @@ ${bold(cyan(" ╚════════════════════
|
|
|
195
228
|
process.exit(1);
|
|
196
229
|
} finally {
|
|
197
230
|
// 还原 git 配置
|
|
198
|
-
|
|
199
|
-
try { execSync(
|
|
231
|
+
for (const key of gitRewritesSet) {
|
|
232
|
+
try { execSync(`git config --global --unset-all ${key}`, { stdio: "ignore" }); } catch { /* ignore */ }
|
|
200
233
|
}
|
|
201
234
|
}
|
|
202
235
|
}
|
|
@@ -219,6 +252,19 @@ ${bold(cyan(" ╚════════════════════
|
|
|
219
252
|
await installPlugin();
|
|
220
253
|
}
|
|
221
254
|
|
|
255
|
+
// ── 安装后自检 ────────────────────────────────────────────────────────
|
|
256
|
+
const checks = verifyInstall();
|
|
257
|
+
const failures = checks.filter((c) => !c.ok && c.check !== "AI 模型" && c.check !== "Gateway Token");
|
|
258
|
+
if (failures.length > 0) {
|
|
259
|
+
separator();
|
|
260
|
+
console.log(yellow("\n 安装自检发现问题:"));
|
|
261
|
+
for (const f of failures) {
|
|
262
|
+
console.log(` ${red("✗")} ${f.check}: ${f.msg}`);
|
|
263
|
+
if (f.fix) console.log(` ${gray("修复: " + f.fix)}`);
|
|
264
|
+
}
|
|
265
|
+
console.log(gray("\n 可运行 npx galaxy-opc doctor 查看完整诊断\n"));
|
|
266
|
+
}
|
|
267
|
+
|
|
222
268
|
// ── 步骤 4:配置模型 ────────────────────────────────────────────────────
|
|
223
269
|
await cmdSetup();
|
|
224
270
|
}
|
|
@@ -453,6 +499,128 @@ async function cmdSetup() {
|
|
|
453
499
|
separator("═");
|
|
454
500
|
}
|
|
455
501
|
|
|
502
|
+
// ─── 安装后自检 ──────────────────────────────────────────────────────────────
|
|
503
|
+
function verifyInstall() {
|
|
504
|
+
const issues = [];
|
|
505
|
+
|
|
506
|
+
// 检查 openclaw 命令
|
|
507
|
+
const ocVer = getOpenclawVersion();
|
|
508
|
+
if (!ocVer) {
|
|
509
|
+
issues.push({
|
|
510
|
+
check: "OpenClaw 命令",
|
|
511
|
+
ok: false,
|
|
512
|
+
msg: "openclaw 命令不可用",
|
|
513
|
+
fix: "npm install -g openclaw@latest --registry https://registry.npmmirror.com",
|
|
514
|
+
});
|
|
515
|
+
} else {
|
|
516
|
+
issues.push({ check: "OpenClaw 命令", ok: true, msg: `已安装 (${ocVer})` });
|
|
517
|
+
}
|
|
518
|
+
|
|
519
|
+
// 检查插件目录
|
|
520
|
+
const pluginDir = path.join(STATE_DIR, "extensions", "galaxy-opc-plugin");
|
|
521
|
+
const pluginEntry = path.join(pluginDir, "index.ts");
|
|
522
|
+
if (fs.existsSync(pluginEntry)) {
|
|
523
|
+
issues.push({ check: "OPC 插件", ok: true, msg: pluginDir });
|
|
524
|
+
} else {
|
|
525
|
+
issues.push({
|
|
526
|
+
check: "OPC 插件",
|
|
527
|
+
ok: false,
|
|
528
|
+
msg: "插件目录不存在或缺少入口文件",
|
|
529
|
+
fix: "openclaw plugins install galaxy-opc-plugin",
|
|
530
|
+
});
|
|
531
|
+
}
|
|
532
|
+
|
|
533
|
+
// 检查配置文件
|
|
534
|
+
if (fs.existsSync(CONFIG_PATH)) {
|
|
535
|
+
const cfg = readJson(CONFIG_PATH);
|
|
536
|
+
issues.push({ check: "配置文件", ok: true, msg: CONFIG_PATH });
|
|
537
|
+
|
|
538
|
+
// 检查模型配置
|
|
539
|
+
const model = cfg.agents?.defaults?.model?.primary;
|
|
540
|
+
if (model) {
|
|
541
|
+
issues.push({ check: "AI 模型", ok: true, msg: model });
|
|
542
|
+
} else {
|
|
543
|
+
issues.push({
|
|
544
|
+
check: "AI 模型",
|
|
545
|
+
ok: false,
|
|
546
|
+
msg: "未配置默认模型",
|
|
547
|
+
fix: "npx galaxy-opc setup",
|
|
548
|
+
});
|
|
549
|
+
}
|
|
550
|
+
|
|
551
|
+
// 检查 gateway token
|
|
552
|
+
const token = cfg.gateway?.auth?.token;
|
|
553
|
+
if (token && token !== "change-me-to-a-long-random-token") {
|
|
554
|
+
issues.push({ check: "Gateway Token", ok: true, msg: "已配置" });
|
|
555
|
+
} else {
|
|
556
|
+
issues.push({
|
|
557
|
+
check: "Gateway Token",
|
|
558
|
+
ok: false,
|
|
559
|
+
msg: "未配置访问令牌",
|
|
560
|
+
fix: "npx galaxy-opc setup",
|
|
561
|
+
});
|
|
562
|
+
}
|
|
563
|
+
} else {
|
|
564
|
+
issues.push({
|
|
565
|
+
check: "配置文件",
|
|
566
|
+
ok: false,
|
|
567
|
+
msg: "openclaw.json 不存在",
|
|
568
|
+
fix: "npx galaxy-opc setup",
|
|
569
|
+
});
|
|
570
|
+
}
|
|
571
|
+
|
|
572
|
+
// 检查数据库目录可写
|
|
573
|
+
const dbDir = path.join(STATE_DIR, "opc-platform");
|
|
574
|
+
if (fs.existsSync(dbDir)) {
|
|
575
|
+
issues.push({ check: "数据库目录", ok: true, msg: dbDir });
|
|
576
|
+
} else {
|
|
577
|
+
// 尝试创建
|
|
578
|
+
try {
|
|
579
|
+
fs.mkdirSync(dbDir, { recursive: true });
|
|
580
|
+
issues.push({ check: "数据库目录", ok: true, msg: `已创建 ${dbDir}` });
|
|
581
|
+
} catch {
|
|
582
|
+
issues.push({
|
|
583
|
+
check: "数据库目录",
|
|
584
|
+
ok: false,
|
|
585
|
+
msg: "无法创建数据库目录",
|
|
586
|
+
fix: `mkdir -p ${dbDir}`,
|
|
587
|
+
});
|
|
588
|
+
}
|
|
589
|
+
}
|
|
590
|
+
|
|
591
|
+
return issues;
|
|
592
|
+
}
|
|
593
|
+
|
|
594
|
+
// ─── doctor 命令 ──────────────────────────────────────────────────────────────
|
|
595
|
+
async function cmdDoctor() {
|
|
596
|
+
console.log(`\n${bold(cyan(" Galaxy OPC — 安装诊断"))}\n`);
|
|
597
|
+
separator();
|
|
598
|
+
|
|
599
|
+
const issues = verifyInstall();
|
|
600
|
+
let hasError = false;
|
|
601
|
+
|
|
602
|
+
for (const item of issues) {
|
|
603
|
+
if (item.ok) {
|
|
604
|
+
console.log(` ${green("✓")} ${bold(item.check)}: ${item.msg}`);
|
|
605
|
+
} else {
|
|
606
|
+
hasError = true;
|
|
607
|
+
console.log(` ${red("✗")} ${bold(item.check)}: ${item.msg}`);
|
|
608
|
+
if (item.fix) {
|
|
609
|
+
console.log(` ${gray("修复: " + item.fix)}`);
|
|
610
|
+
}
|
|
611
|
+
}
|
|
612
|
+
}
|
|
613
|
+
|
|
614
|
+
separator();
|
|
615
|
+
if (hasError) {
|
|
616
|
+
console.log(`\n ${yellow("存在问题,请按上述提示修复。")}\n`);
|
|
617
|
+
process.exit(1);
|
|
618
|
+
} else {
|
|
619
|
+
console.log(`\n ${green("所有检查通过,系统就绪!")}`);
|
|
620
|
+
console.log(` ${dim("启动命令: openclaw gateway")}\n`);
|
|
621
|
+
}
|
|
622
|
+
}
|
|
623
|
+
|
|
456
624
|
// ─── start 命令 ──────────────────────────────────────────────────────────────
|
|
457
625
|
async function cmdStart() {
|
|
458
626
|
const ocVersion = getOpenclawVersion();
|