@synap-core/cli 1.1.0 → 1.2.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/README.md +158 -115
- package/dist/commands/finish.d.ts +15 -8
- package/dist/commands/finish.js +153 -41
- package/dist/commands/finish.js.map +1 -1
- package/dist/commands/openclaw.d.ts +15 -1
- package/dist/commands/openclaw.js +292 -177
- package/dist/commands/openclaw.js.map +1 -1
- package/dist/index.js +28 -4
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"finish.js","sourceRoot":"","sources":["../../src/commands/finish.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"finish.js","sourceRoot":"","sources":["../../src/commands/finish.ts"],"names":[],"mappings":"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"}
|
|
@@ -16,9 +16,23 @@ export declare function openclawConnect(opts: {
|
|
|
16
16
|
}): Promise<void>;
|
|
17
17
|
export declare function openclawDashboard(): void;
|
|
18
18
|
export declare function openclawSetupDomain(): Promise<void>;
|
|
19
|
-
export
|
|
19
|
+
export interface ConfigureOpts {
|
|
20
|
+
interactive?: boolean;
|
|
21
|
+
provider?: "anthropic" | "openai" | "google";
|
|
22
|
+
key?: string;
|
|
23
|
+
model?: string;
|
|
24
|
+
show?: boolean;
|
|
25
|
+
}
|
|
26
|
+
export declare function openclawConfigure(opts?: ConfigureOpts): Promise<void>;
|
|
20
27
|
export declare function openclawLogs(opts: {
|
|
21
28
|
lines?: number;
|
|
22
29
|
follow?: boolean;
|
|
23
30
|
}): void;
|
|
31
|
+
export declare function openclawToken(opts: {
|
|
32
|
+
copy?: boolean;
|
|
33
|
+
for?: string;
|
|
34
|
+
}): void;
|
|
35
|
+
export declare function openclawDoctor(opts: {
|
|
36
|
+
fix?: boolean;
|
|
37
|
+
}): void;
|
|
24
38
|
export declare function openclawRestart(): Promise<void>;
|
|
@@ -50,10 +50,18 @@ export async function openclawOverview() {
|
|
|
50
50
|
log.dim(`Version: ${oc.version}`);
|
|
51
51
|
// ── AI provider ─────────────────────────────────────────────────────────
|
|
52
52
|
log.heading("AI Provider");
|
|
53
|
-
const
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
53
|
+
const aiConfig = readOpenClawAiConfig(oc);
|
|
54
|
+
const hasAnyKey = !!(aiConfig.anthropicKey || aiConfig.openaiKey || aiConfig.geminiKey);
|
|
55
|
+
const apiKeyStatus = { configured: hasAnyKey };
|
|
56
|
+
if (hasAnyKey) {
|
|
57
|
+
if (aiConfig.anthropicKey)
|
|
58
|
+
log.success(`Anthropic: ${maskKey(aiConfig.anthropicKey)}`);
|
|
59
|
+
if (aiConfig.openaiKey)
|
|
60
|
+
log.success(`OpenAI: ${maskKey(aiConfig.openaiKey)}`);
|
|
61
|
+
if (aiConfig.geminiKey)
|
|
62
|
+
log.success(`Google: ${maskKey(aiConfig.geminiKey)}`);
|
|
63
|
+
if (aiConfig.primaryModel)
|
|
64
|
+
log.dim(`Model: ${aiConfig.primaryModel}`);
|
|
57
65
|
}
|
|
58
66
|
else {
|
|
59
67
|
log.warn("No AI API key configured — OpenClaw cannot process requests");
|
|
@@ -134,37 +142,49 @@ export async function openclawConnect(opts) {
|
|
|
134
142
|
const gatewayPort = oc.gatewayPort ?? 18789;
|
|
135
143
|
const isDocker = oc.runtime === "docker";
|
|
136
144
|
// OpenClaw MCP is stdio-based — clients run `openclaw mcp serve` as a local process
|
|
137
|
-
// which connects to the gateway over WebSocket.
|
|
138
|
-
//
|
|
145
|
+
// which connects to the gateway over WebSocket. The gateway token authenticates
|
|
146
|
+
// the connection — we fetch it from the container so the config is ready to paste.
|
|
147
|
+
const token = readGatewayToken(oc) ?? undefined;
|
|
148
|
+
if (!token) {
|
|
149
|
+
log.warn("Could not read gateway token from OpenClaw.");
|
|
150
|
+
log.dim("The MCP configs below will require you to add --token manually.");
|
|
151
|
+
log.dim("Run: synap openclaw token");
|
|
152
|
+
log.blank();
|
|
153
|
+
}
|
|
139
154
|
const client = opts.client?.toLowerCase();
|
|
140
155
|
if (!client || client === "claude") {
|
|
141
|
-
printMcpConfig("Claude Desktop", gatewayPort, isDocker, "claude");
|
|
156
|
+
printMcpConfig("Claude Desktop", gatewayPort, isDocker, "claude", token);
|
|
142
157
|
}
|
|
143
158
|
if (!client || client === "cursor") {
|
|
144
|
-
printMcpConfig("Cursor", gatewayPort, isDocker, "cursor");
|
|
159
|
+
printMcpConfig("Cursor", gatewayPort, isDocker, "cursor", token);
|
|
145
160
|
}
|
|
146
161
|
if (!client || client === "windsurf") {
|
|
147
|
-
printMcpConfig("Windsurf", gatewayPort, isDocker, "windsurf");
|
|
162
|
+
printMcpConfig("Windsurf", gatewayPort, isDocker, "windsurf", token);
|
|
148
163
|
}
|
|
149
164
|
if (client && !["claude", "cursor", "windsurf"].includes(client)) {
|
|
150
165
|
log.warn(`Unknown client "${client}". Showing generic config.`);
|
|
151
|
-
printMcpConfig("MCP Client", gatewayPort, isDocker, "generic");
|
|
166
|
+
printMcpConfig("MCP Client", gatewayPort, isDocker, "generic", token);
|
|
152
167
|
}
|
|
153
168
|
if (isDocker) {
|
|
154
169
|
log.blank();
|
|
155
170
|
log.info("Remote server? Tunnel the gateway port first:");
|
|
156
|
-
log.dim(
|
|
157
|
-
log.dim(" Then use the configs above (they point to localhost
|
|
171
|
+
log.dim(` ssh -N -L ${gatewayPort}:localhost:${gatewayPort} user@your-server`);
|
|
172
|
+
log.dim(" Then use the configs above (they point to localhost)");
|
|
158
173
|
log.blank();
|
|
159
|
-
log.dim("openclaw must be installed locally
|
|
174
|
+
log.dim("openclaw must be installed locally on the client machine:");
|
|
175
|
+
log.dim(" npm i -g openclaw");
|
|
160
176
|
}
|
|
161
177
|
}
|
|
162
|
-
function printMcpConfig(label, gatewayPort, isRemote, client) {
|
|
178
|
+
function printMcpConfig(label, gatewayPort, isRemote, client, token) {
|
|
163
179
|
log.heading(label);
|
|
164
180
|
// MCP config: stdio command that connects to the local (or tunneled) gateway
|
|
165
|
-
const args =
|
|
166
|
-
|
|
167
|
-
|
|
181
|
+
const args = ["mcp", "serve"];
|
|
182
|
+
if (isRemote) {
|
|
183
|
+
args.push("--url", `ws://localhost:${gatewayPort}`);
|
|
184
|
+
}
|
|
185
|
+
if (token) {
|
|
186
|
+
args.push("--token", token);
|
|
187
|
+
}
|
|
168
188
|
const config = JSON.stringify({ mcpServers: { openclaw: { command: "openclaw", args } } }, null, 2);
|
|
169
189
|
const paths = {
|
|
170
190
|
claude: "macOS: ~/Library/Application Support/Claude/claude_desktop_config.json",
|
|
@@ -390,52 +410,68 @@ export async function openclawSetupDomain() {
|
|
|
390
410
|
log.dim("This takes ~30s the first time.");
|
|
391
411
|
log.blank();
|
|
392
412
|
}
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
// Show current status
|
|
399
|
-
const current = getAiKeyStatus();
|
|
400
|
-
if (current.configured) {
|
|
401
|
-
log.success(`Currently using: ${current.provider}`);
|
|
402
|
-
log.dim(`Model: ${current.model ?? "default"}`);
|
|
403
|
-
log.blank();
|
|
413
|
+
export async function openclawConfigure(opts = {}) {
|
|
414
|
+
const oc = detectOpenClaw();
|
|
415
|
+
if (!oc.found) {
|
|
416
|
+
log.error("OpenClaw is not running.");
|
|
417
|
+
return;
|
|
404
418
|
}
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
{
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
}
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
title: "Google (Gemini)",
|
|
421
|
-
value: "google",
|
|
422
|
-
},
|
|
423
|
-
{
|
|
424
|
-
title: "Synap IS (via pod)",
|
|
425
|
-
description: "Uses your pod AI — no external key needed",
|
|
426
|
-
value: "synap",
|
|
427
|
-
},
|
|
428
|
-
],
|
|
429
|
-
});
|
|
430
|
-
if (!provider)
|
|
419
|
+
// ── Show current config ─────────────────────────────────────────────────
|
|
420
|
+
if (opts.show) {
|
|
421
|
+
log.heading("OpenClaw AI Config");
|
|
422
|
+
const current = readOpenClawAiConfig(oc);
|
|
423
|
+
if (current.anthropicKey)
|
|
424
|
+
log.success(`Anthropic: ${maskKey(current.anthropicKey)}`);
|
|
425
|
+
if (current.openaiKey)
|
|
426
|
+
log.success(`OpenAI: ${maskKey(current.openaiKey)}`);
|
|
427
|
+
if (current.geminiKey)
|
|
428
|
+
log.success(`Google: ${maskKey(current.geminiKey)}`);
|
|
429
|
+
if (current.primaryModel)
|
|
430
|
+
log.info(`Model: ${current.primaryModel}`);
|
|
431
|
+
if (!current.anthropicKey && !current.openaiKey && !current.geminiKey) {
|
|
432
|
+
log.warn("No AI provider key configured");
|
|
433
|
+
}
|
|
431
434
|
return;
|
|
432
|
-
|
|
435
|
+
}
|
|
436
|
+
// ── Interactive (delegate to OpenClaw's own wizard) ──────────────────────
|
|
437
|
+
if (opts.interactive && oc.runtime === "docker") {
|
|
438
|
+
const containerName = oc.containerName ?? "openclaw";
|
|
439
|
+
log.heading("Handing off to OpenClaw");
|
|
440
|
+
log.dim(`Running: docker exec -it ${containerName} openclaw configure`);
|
|
433
441
|
log.blank();
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
442
|
+
try {
|
|
443
|
+
execSync(`docker exec -it ${containerName} openclaw configure`, { stdio: "inherit" });
|
|
444
|
+
}
|
|
445
|
+
catch (err) {
|
|
446
|
+
log.error(`openclaw configure failed: ${err instanceof Error ? err.message : String(err)}`);
|
|
447
|
+
}
|
|
437
448
|
return;
|
|
438
449
|
}
|
|
450
|
+
banner();
|
|
451
|
+
log.heading("Configure AI Provider");
|
|
452
|
+
// ── Scripted path (--provider + --key) ───────────────────────────────────
|
|
453
|
+
let provider = opts.provider;
|
|
454
|
+
let apiKey = opts.key;
|
|
455
|
+
let model = opts.model;
|
|
456
|
+
if (!provider) {
|
|
457
|
+
const pick = await prompts({
|
|
458
|
+
type: "select",
|
|
459
|
+
name: "provider",
|
|
460
|
+
message: "Which AI provider?",
|
|
461
|
+
choices: [
|
|
462
|
+
{ title: "Anthropic (Claude)", description: "recommended", value: "anthropic" },
|
|
463
|
+
{ title: "OpenAI (GPT-4o)", value: "openai" },
|
|
464
|
+
{ title: "Google (Gemini)", value: "google" },
|
|
465
|
+
{ title: "Run OpenClaw's own wizard", description: "interactive", value: "wizard" },
|
|
466
|
+
],
|
|
467
|
+
});
|
|
468
|
+
if (!pick.provider)
|
|
469
|
+
return;
|
|
470
|
+
if (pick.provider === "wizard") {
|
|
471
|
+
return openclawConfigure({ interactive: true });
|
|
472
|
+
}
|
|
473
|
+
provider = pick.provider;
|
|
474
|
+
}
|
|
439
475
|
const envKey = provider === "anthropic"
|
|
440
476
|
? "ANTHROPIC_API_KEY"
|
|
441
477
|
: provider === "openai"
|
|
@@ -446,64 +482,47 @@ export async function openclawConfigure() {
|
|
|
446
482
|
: provider === "openai"
|
|
447
483
|
? "openai/gpt-4o"
|
|
448
484
|
: "google/gemini-2.0-flash";
|
|
449
|
-
|
|
450
|
-
type: "password",
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
});
|
|
462
|
-
if (deployDir) {
|
|
463
|
-
// Write to .env file
|
|
464
|
-
const envFile = `${deployDir}/.env`;
|
|
465
|
-
writeEnvVar(envFile, envKey, apiKey);
|
|
466
|
-
if (model && model !== modelDefault) {
|
|
467
|
-
writeEnvVar(envFile, "OPENCLAW_MODEL", model);
|
|
468
|
-
}
|
|
469
|
-
else {
|
|
470
|
-
writeEnvVar(envFile, "OPENCLAW_MODEL", modelDefault);
|
|
471
|
-
}
|
|
472
|
-
log.blank();
|
|
473
|
-
log.success(`${envKey} written to ${deployDir}/.env`);
|
|
474
|
-
// Restart container to pick up new env vars
|
|
475
|
-
const oc = detectOpenClaw();
|
|
476
|
-
const containerName = oc.containerName ?? "openclaw";
|
|
477
|
-
const { doRestart } = await prompts({
|
|
478
|
-
type: "confirm",
|
|
479
|
-
name: "doRestart",
|
|
480
|
-
message: `Restart ${containerName} to apply?`,
|
|
481
|
-
initial: true,
|
|
485
|
+
if (!apiKey) {
|
|
486
|
+
const res = await prompts({ type: "password", name: "apiKey", message: `${envKey}:` });
|
|
487
|
+
if (!res.apiKey)
|
|
488
|
+
return;
|
|
489
|
+
apiKey = res.apiKey;
|
|
490
|
+
}
|
|
491
|
+
if (!model) {
|
|
492
|
+
const res = await prompts({
|
|
493
|
+
type: "text",
|
|
494
|
+
name: "model",
|
|
495
|
+
message: "Model:",
|
|
496
|
+
initial: modelDefault,
|
|
482
497
|
});
|
|
483
|
-
if (
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
execSync(`docker restart ${containerName}`, { stdio: "pipe", timeout: 30000 });
|
|
487
|
-
log.success("Restarted. Give it 30s to come back up.");
|
|
488
|
-
log.dim(`Check: synap openclaw`);
|
|
489
|
-
}
|
|
490
|
-
catch {
|
|
491
|
-
log.warn("Restart failed — restart manually:");
|
|
492
|
-
log.dim(` docker restart ${containerName}`);
|
|
493
|
-
}
|
|
494
|
-
}
|
|
498
|
+
if (!res.model)
|
|
499
|
+
return;
|
|
500
|
+
model = res.model;
|
|
495
501
|
}
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
502
|
+
// ── Write via OpenClaw's own config system ──────────────────────────────
|
|
503
|
+
const containerName = oc.containerName ?? "openclaw";
|
|
504
|
+
const spinner = ora("Writing OpenClaw config...").start();
|
|
505
|
+
try {
|
|
506
|
+
// Set the API key inside OpenClaw's env block
|
|
507
|
+
execSync(`docker exec ${containerName} openclaw config set env.${envKey} ${JSON.stringify(apiKey)}`, { stdio: "pipe", timeout: 15000 });
|
|
508
|
+
// Set the primary model
|
|
509
|
+
execSync(`docker exec ${containerName} openclaw config set agents.defaults.model.primary ${JSON.stringify(model)}`, { stdio: "pipe", timeout: 15000 });
|
|
510
|
+
spinner.succeed("Config written");
|
|
511
|
+
}
|
|
512
|
+
catch (err) {
|
|
513
|
+
spinner.fail(`openclaw config set failed: ${err instanceof Error ? err.message : String(err)}`);
|
|
514
|
+
log.dim("Make sure OpenClaw is running: synap openclaw");
|
|
515
|
+
return;
|
|
516
|
+
}
|
|
517
|
+
// ── Restart to apply ─────────────────────────────────────────────────────
|
|
518
|
+
log.info("Restarting OpenClaw to apply...");
|
|
519
|
+
try {
|
|
520
|
+
execSync(`docker restart ${containerName}`, { stdio: "pipe", timeout: 30000 });
|
|
521
|
+
log.success("Restarted — give it ~30s to come back up");
|
|
522
|
+
log.dim("Check: synap openclaw");
|
|
523
|
+
}
|
|
524
|
+
catch {
|
|
525
|
+
log.warn("Restart failed — run manually: docker restart openclaw");
|
|
507
526
|
}
|
|
508
527
|
log.blank();
|
|
509
528
|
}
|
|
@@ -528,6 +547,138 @@ export function openclawLogs(opts) {
|
|
|
528
547
|
log.dim(`Try: docker logs ${containerName} --tail 50`);
|
|
529
548
|
}
|
|
530
549
|
}
|
|
550
|
+
// ─── Token: print the gateway token ──────────────────────────────────────────
|
|
551
|
+
export function openclawToken(opts) {
|
|
552
|
+
const oc = detectOpenClaw();
|
|
553
|
+
if (!oc.found) {
|
|
554
|
+
log.error("OpenClaw is not running.");
|
|
555
|
+
return;
|
|
556
|
+
}
|
|
557
|
+
const token = readGatewayToken(oc);
|
|
558
|
+
if (!token) {
|
|
559
|
+
log.error("Could not read gateway token from OpenClaw.");
|
|
560
|
+
log.dim("Try: synap openclaw doctor");
|
|
561
|
+
return;
|
|
562
|
+
}
|
|
563
|
+
if (opts.for) {
|
|
564
|
+
// Print a pre-filled MCP client config with the token embedded
|
|
565
|
+
const client = opts.for.toLowerCase();
|
|
566
|
+
const gatewayPort = oc.gatewayPort ?? 18789;
|
|
567
|
+
const config = {
|
|
568
|
+
mcpServers: {
|
|
569
|
+
openclaw: {
|
|
570
|
+
command: "openclaw",
|
|
571
|
+
args: [
|
|
572
|
+
"mcp",
|
|
573
|
+
"serve",
|
|
574
|
+
"--url",
|
|
575
|
+
`ws://localhost:${gatewayPort}`,
|
|
576
|
+
"--token",
|
|
577
|
+
token,
|
|
578
|
+
],
|
|
579
|
+
},
|
|
580
|
+
},
|
|
581
|
+
};
|
|
582
|
+
const paths = {
|
|
583
|
+
claude: "~/Library/Application Support/Claude/claude_desktop_config.json",
|
|
584
|
+
cursor: "~/.cursor/mcp.json",
|
|
585
|
+
windsurf: "~/.windsurf/mcp.json",
|
|
586
|
+
};
|
|
587
|
+
log.heading(client.charAt(0).toUpperCase() + client.slice(1));
|
|
588
|
+
if (paths[client])
|
|
589
|
+
log.dim(`Config file: ${paths[client]}`);
|
|
590
|
+
log.blank();
|
|
591
|
+
console.log(chalk.cyan(JSON.stringify(config, null, 2)));
|
|
592
|
+
log.blank();
|
|
593
|
+
return;
|
|
594
|
+
}
|
|
595
|
+
if (opts.copy) {
|
|
596
|
+
try {
|
|
597
|
+
const pbcopy = process.platform === "darwin"
|
|
598
|
+
? "pbcopy"
|
|
599
|
+
: process.platform === "linux"
|
|
600
|
+
? "xclip -selection clipboard"
|
|
601
|
+
: null;
|
|
602
|
+
if (pbcopy) {
|
|
603
|
+
execSync(`echo -n ${JSON.stringify(token)} | ${pbcopy}`, { stdio: "pipe" });
|
|
604
|
+
log.success("Token copied to clipboard");
|
|
605
|
+
return;
|
|
606
|
+
}
|
|
607
|
+
}
|
|
608
|
+
catch {
|
|
609
|
+
// fall through to print
|
|
610
|
+
}
|
|
611
|
+
}
|
|
612
|
+
// Plain print
|
|
613
|
+
console.log(token);
|
|
614
|
+
}
|
|
615
|
+
function readGatewayToken(oc) {
|
|
616
|
+
if (!oc.found)
|
|
617
|
+
return null;
|
|
618
|
+
if (oc.runtime === "docker") {
|
|
619
|
+
const containerName = oc.containerName ?? "openclaw";
|
|
620
|
+
// Try OpenClaw's own config first — works even if token file path changes
|
|
621
|
+
try {
|
|
622
|
+
const raw = execSync(`docker exec ${containerName} openclaw config get gateway.token 2>/dev/null`, { encoding: "utf-8", timeout: 5000 }).trim();
|
|
623
|
+
if (raw && raw !== "undefined" && raw !== "null") {
|
|
624
|
+
return raw.replace(/^["']|["']$/g, "");
|
|
625
|
+
}
|
|
626
|
+
}
|
|
627
|
+
catch {
|
|
628
|
+
// fall through
|
|
629
|
+
}
|
|
630
|
+
// Fallback: read the token file directly
|
|
631
|
+
try {
|
|
632
|
+
const raw = execSync(`docker exec ${containerName} cat /root/.openclaw/gateway.token 2>/dev/null`, { encoding: "utf-8", timeout: 5000 }).trim();
|
|
633
|
+
return raw || null;
|
|
634
|
+
}
|
|
635
|
+
catch {
|
|
636
|
+
return null;
|
|
637
|
+
}
|
|
638
|
+
}
|
|
639
|
+
// Local install — read from host filesystem
|
|
640
|
+
try {
|
|
641
|
+
const tokenPath = `${process.env.HOME}/.openclaw/gateway.token`;
|
|
642
|
+
if (fs.existsSync(tokenPath)) {
|
|
643
|
+
return fs.readFileSync(tokenPath, "utf-8").trim();
|
|
644
|
+
}
|
|
645
|
+
}
|
|
646
|
+
catch {
|
|
647
|
+
// ignore
|
|
648
|
+
}
|
|
649
|
+
return null;
|
|
650
|
+
}
|
|
651
|
+
// ─── Doctor: run OpenClaw's own diagnostic ───────────────────────────────────
|
|
652
|
+
export function openclawDoctor(opts) {
|
|
653
|
+
const oc = detectOpenClaw();
|
|
654
|
+
if (!oc.found) {
|
|
655
|
+
log.error("OpenClaw is not running.");
|
|
656
|
+
return;
|
|
657
|
+
}
|
|
658
|
+
const fixFlag = opts.fix ? " --fix" : "";
|
|
659
|
+
if (oc.runtime === "docker") {
|
|
660
|
+
const containerName = oc.containerName ?? "openclaw";
|
|
661
|
+
log.dim(`Running: docker exec ${containerName} openclaw doctor${fixFlag}`);
|
|
662
|
+
log.blank();
|
|
663
|
+
try {
|
|
664
|
+
execSync(`docker exec ${containerName} openclaw doctor${fixFlag}`, {
|
|
665
|
+
stdio: "inherit",
|
|
666
|
+
timeout: 60000,
|
|
667
|
+
});
|
|
668
|
+
}
|
|
669
|
+
catch {
|
|
670
|
+
log.warn("openclaw doctor reported issues or failed");
|
|
671
|
+
}
|
|
672
|
+
}
|
|
673
|
+
else {
|
|
674
|
+
try {
|
|
675
|
+
execSync(`openclaw doctor${fixFlag}`, { stdio: "inherit", timeout: 60000 });
|
|
676
|
+
}
|
|
677
|
+
catch {
|
|
678
|
+
log.warn("openclaw doctor reported issues or failed");
|
|
679
|
+
}
|
|
680
|
+
}
|
|
681
|
+
}
|
|
531
682
|
// ─── Restart ─────────────────────────────────────────────────────────────────
|
|
532
683
|
export async function openclawRestart() {
|
|
533
684
|
const oc = detectOpenClaw();
|
|
@@ -571,54 +722,6 @@ function getOpenClawPublicUrl() {
|
|
|
571
722
|
return null;
|
|
572
723
|
}
|
|
573
724
|
}
|
|
574
|
-
function getAiKeyStatus() {
|
|
575
|
-
// Check deploy dir .env first (most accurate for Docker deployments)
|
|
576
|
-
const deployDir = findSynapDeployDir();
|
|
577
|
-
if (deployDir) {
|
|
578
|
-
const envFile = `${deployDir}/.env`;
|
|
579
|
-
try {
|
|
580
|
-
const envContent = fs.readFileSync(envFile, "utf-8");
|
|
581
|
-
const vars = parseEnvFile(envContent);
|
|
582
|
-
if (vars.ANTHROPIC_API_KEY) {
|
|
583
|
-
return { configured: true, provider: "Anthropic", model: vars.OPENCLAW_MODEL };
|
|
584
|
-
}
|
|
585
|
-
if (vars.OPENAI_API_KEY) {
|
|
586
|
-
return { configured: true, provider: "OpenAI", model: vars.OPENCLAW_MODEL };
|
|
587
|
-
}
|
|
588
|
-
if (vars.GEMINI_API_KEY) {
|
|
589
|
-
return { configured: true, provider: "Google", model: vars.OPENCLAW_MODEL };
|
|
590
|
-
}
|
|
591
|
-
}
|
|
592
|
-
catch {
|
|
593
|
-
// unreadable
|
|
594
|
-
}
|
|
595
|
-
}
|
|
596
|
-
// Fallback: check live container env (via docker inspect)
|
|
597
|
-
const oc = detectOpenClaw();
|
|
598
|
-
if (oc.runtime === "docker") {
|
|
599
|
-
try {
|
|
600
|
-
const containerName = oc.containerName ?? "openclaw";
|
|
601
|
-
const raw = execSync(`docker inspect --format '{{range .Config.Env}}{{.}}\\n{{end}}' ${containerName} 2>/dev/null`, { encoding: "utf-8", timeout: 5000 });
|
|
602
|
-
const envLines = raw.split("\\n").filter(Boolean);
|
|
603
|
-
const env = {};
|
|
604
|
-
for (const line of envLines) {
|
|
605
|
-
const idx = line.indexOf("=");
|
|
606
|
-
if (idx > 0)
|
|
607
|
-
env[line.slice(0, idx)] = line.slice(idx + 1);
|
|
608
|
-
}
|
|
609
|
-
if (env.ANTHROPIC_API_KEY)
|
|
610
|
-
return { configured: true, provider: "Anthropic", model: env.OPENCLAW_MODEL };
|
|
611
|
-
if (env.OPENAI_API_KEY)
|
|
612
|
-
return { configured: true, provider: "OpenAI", model: env.OPENCLAW_MODEL };
|
|
613
|
-
if (env.GEMINI_API_KEY)
|
|
614
|
-
return { configured: true, provider: "Google", model: env.OPENCLAW_MODEL };
|
|
615
|
-
}
|
|
616
|
-
catch {
|
|
617
|
-
// docker not available
|
|
618
|
-
}
|
|
619
|
-
}
|
|
620
|
-
return { configured: false };
|
|
621
|
-
}
|
|
622
725
|
function checkSkillInstalled(oc) {
|
|
623
726
|
if (!oc.found)
|
|
624
727
|
return false;
|
|
@@ -652,21 +755,6 @@ function writeEnvVar(envFile, key, value) {
|
|
|
652
755
|
: content + "\n" + line + "\n";
|
|
653
756
|
fs.writeFileSync(envFile, content, { mode: 0o600 });
|
|
654
757
|
}
|
|
655
|
-
function parseEnvFile(content) {
|
|
656
|
-
const result = {};
|
|
657
|
-
for (const line of content.split("\n")) {
|
|
658
|
-
const trimmed = line.trim();
|
|
659
|
-
if (!trimmed || trimmed.startsWith("#"))
|
|
660
|
-
continue;
|
|
661
|
-
const idx = trimmed.indexOf("=");
|
|
662
|
-
if (idx > 0) {
|
|
663
|
-
const key = trimmed.slice(0, idx);
|
|
664
|
-
const val = trimmed.slice(idx + 1).replace(/^["']|["']$/g, "");
|
|
665
|
-
result[key] = val;
|
|
666
|
-
}
|
|
667
|
-
}
|
|
668
|
-
return result;
|
|
669
|
-
}
|
|
670
758
|
// ─── Domain setup helpers ────────────────────────────────────────────────────
|
|
671
759
|
function readEnvVar(deployDir, key) {
|
|
672
760
|
try {
|
|
@@ -735,6 +823,33 @@ basicauth {
|
|
|
735
823
|
}
|
|
736
824
|
`;
|
|
737
825
|
}
|
|
826
|
+
function readOpenClawAiConfig(oc) {
|
|
827
|
+
if (!oc.found || oc.runtime !== "docker")
|
|
828
|
+
return {};
|
|
829
|
+
const containerName = oc.containerName ?? "openclaw";
|
|
830
|
+
const read = (key) => {
|
|
831
|
+
try {
|
|
832
|
+
const out = execSync(`docker exec ${containerName} openclaw config get ${key} 2>/dev/null`, { encoding: "utf-8", timeout: 5000 }).trim();
|
|
833
|
+
if (!out || out === "undefined" || out === "null")
|
|
834
|
+
return undefined;
|
|
835
|
+
return out.replace(/^["']|["']$/g, "");
|
|
836
|
+
}
|
|
837
|
+
catch {
|
|
838
|
+
return undefined;
|
|
839
|
+
}
|
|
840
|
+
};
|
|
841
|
+
return {
|
|
842
|
+
anthropicKey: read("env.ANTHROPIC_API_KEY"),
|
|
843
|
+
openaiKey: read("env.OPENAI_API_KEY"),
|
|
844
|
+
geminiKey: read("env.GEMINI_API_KEY"),
|
|
845
|
+
primaryModel: read("agents.defaults.model.primary"),
|
|
846
|
+
};
|
|
847
|
+
}
|
|
848
|
+
function maskKey(key) {
|
|
849
|
+
if (key.length <= 8)
|
|
850
|
+
return "•".repeat(key.length);
|
|
851
|
+
return `${key.slice(0, 4)}...${key.slice(-4)}`;
|
|
852
|
+
}
|
|
738
853
|
async function requestDashboardDomainFromCp(cpToken, podId) {
|
|
739
854
|
const cpUrl = process.env.SYNAP_CP_URL ?? "https://api.synap.live";
|
|
740
855
|
const res = await fetch(`${cpUrl}/openclaw/expose-dashboard`, {
|