feat(cli): colorize gateway health + daemon output
This commit is contained in:
@@ -67,6 +67,7 @@ import {
|
|||||||
GOOGLE_GEMINI_DEFAULT_MODEL,
|
GOOGLE_GEMINI_DEFAULT_MODEL,
|
||||||
} from "./google-gemini-model-default.js";
|
} from "./google-gemini-model-default.js";
|
||||||
import { healthCommand } from "./health.js";
|
import { healthCommand } from "./health.js";
|
||||||
|
import { formatHealthCheckFailure } from "./health-format.js";
|
||||||
import {
|
import {
|
||||||
applyAuthProfileConfig,
|
applyAuthProfileConfig,
|
||||||
applyMinimaxConfig,
|
applyMinimaxConfig,
|
||||||
@@ -1286,7 +1287,7 @@ export async function runConfigureWizard(
|
|||||||
try {
|
try {
|
||||||
await healthCommand({ json: false, timeoutMs: 10_000 }, runtime);
|
await healthCommand({ json: false, timeoutMs: 10_000 }, runtime);
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
runtime.error(`Health check failed: ${String(err)}`);
|
runtime.error(formatHealthCheckFailure(err));
|
||||||
note(
|
note(
|
||||||
[
|
[
|
||||||
"Docs:",
|
"Docs:",
|
||||||
|
|||||||
@@ -80,6 +80,7 @@ import {
|
|||||||
shouldSuggestMemorySystem,
|
shouldSuggestMemorySystem,
|
||||||
} from "./doctor-workspace.js";
|
} from "./doctor-workspace.js";
|
||||||
import { healthCommand } from "./health.js";
|
import { healthCommand } from "./health.js";
|
||||||
|
import { formatHealthCheckFailure } from "./health-format.js";
|
||||||
import { applyWizardMetadata, printWizardHeader } from "./onboard-helpers.js";
|
import { applyWizardMetadata, printWizardHeader } from "./onboard-helpers.js";
|
||||||
import { ensureSystemdUserLingerInteractive } from "./systemd-linger.js";
|
import { ensureSystemdUserLingerInteractive } from "./systemd-linger.js";
|
||||||
|
|
||||||
@@ -310,7 +311,7 @@ export async function doctorCommand(
|
|||||||
note("Gateway not running.", "Gateway");
|
note("Gateway not running.", "Gateway");
|
||||||
note(gatewayDetails.message, "Gateway connection");
|
note(gatewayDetails.message, "Gateway connection");
|
||||||
} else {
|
} else {
|
||||||
runtime.error(`Health check failed: ${message}`);
|
runtime.error(formatHealthCheckFailure(err));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -455,7 +456,7 @@ export async function doctorCommand(
|
|||||||
note("Gateway not running.", "Gateway");
|
note("Gateway not running.", "Gateway");
|
||||||
note(gatewayDetails.message, "Gateway connection");
|
note(gatewayDetails.message, "Gateway connection");
|
||||||
} else {
|
} else {
|
||||||
runtime.error(`Health check failed: ${message}`);
|
runtime.error(formatHealthCheckFailure(err));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
43
src/commands/health-format.test.ts
Normal file
43
src/commands/health-format.test.ts
Normal file
@@ -0,0 +1,43 @@
|
|||||||
|
import { describe, expect, it } from "vitest";
|
||||||
|
|
||||||
|
import { formatHealthCheckFailure } from "./health-format.js";
|
||||||
|
|
||||||
|
const stripAnsi = (input: string) =>
|
||||||
|
input.replace(
|
||||||
|
// biome-ignore lint/suspicious/noControlCharactersInRegex: strip ANSI escape sequences
|
||||||
|
/\u001b\[[0-9;]*m/g,
|
||||||
|
"",
|
||||||
|
);
|
||||||
|
|
||||||
|
describe("formatHealthCheckFailure", () => {
|
||||||
|
it("keeps non-rich output stable", () => {
|
||||||
|
const err = new Error(
|
||||||
|
"gateway closed (1006 abnormal closure): no close reason",
|
||||||
|
);
|
||||||
|
expect(formatHealthCheckFailure(err, { rich: false })).toBe(
|
||||||
|
`Health check failed: ${String(err)}`,
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("formats gateway connection details as indented key/value lines", () => {
|
||||||
|
const err = new Error(
|
||||||
|
[
|
||||||
|
"gateway closed (1006 abnormal closure (no close frame)): no close reason",
|
||||||
|
"Gateway target: ws://127.0.0.1:19001",
|
||||||
|
"Source: local loopback",
|
||||||
|
"Config: /Users/steipete/.clawdbot-dev/clawdbot.json",
|
||||||
|
"Bind: loopback",
|
||||||
|
].join("\n"),
|
||||||
|
);
|
||||||
|
|
||||||
|
expect(stripAnsi(formatHealthCheckFailure(err, { rich: true }))).toBe(
|
||||||
|
[
|
||||||
|
"Health check failed: gateway closed (1006 abnormal closure (no close frame)): no close reason",
|
||||||
|
" Gateway target: ws://127.0.0.1:19001",
|
||||||
|
" Source: local loopback",
|
||||||
|
" Config: /Users/steipete/.clawdbot-dev/clawdbot.json",
|
||||||
|
" Bind: loopback",
|
||||||
|
].join("\n"),
|
||||||
|
);
|
||||||
|
});
|
||||||
|
});
|
||||||
48
src/commands/health-format.ts
Normal file
48
src/commands/health-format.ts
Normal file
@@ -0,0 +1,48 @@
|
|||||||
|
import { colorize, isRich, theme } from "../terminal/theme.js";
|
||||||
|
|
||||||
|
const formatKv = (line: string, rich: boolean) => {
|
||||||
|
const idx = line.indexOf(": ");
|
||||||
|
if (idx <= 0) return colorize(rich, theme.muted, line);
|
||||||
|
const key = line.slice(0, idx);
|
||||||
|
const value = line.slice(idx + 2);
|
||||||
|
|
||||||
|
const valueColor =
|
||||||
|
key === "Gateway target" || key === "Config"
|
||||||
|
? theme.command
|
||||||
|
: key === "Source"
|
||||||
|
? theme.muted
|
||||||
|
: theme.info;
|
||||||
|
|
||||||
|
return `${colorize(rich, theme.muted, `${key}:`)} ${colorize(rich, valueColor, value)}`;
|
||||||
|
};
|
||||||
|
|
||||||
|
export function formatHealthCheckFailure(
|
||||||
|
err: unknown,
|
||||||
|
opts: { rich?: boolean } = {},
|
||||||
|
): string {
|
||||||
|
const rich = opts.rich ?? isRich();
|
||||||
|
const raw = String(err);
|
||||||
|
const message = err instanceof Error ? err.message : raw;
|
||||||
|
|
||||||
|
if (!rich) return `Health check failed: ${raw}`;
|
||||||
|
|
||||||
|
const lines = message
|
||||||
|
.split("\n")
|
||||||
|
.map((l) => l.trimEnd())
|
||||||
|
.filter(Boolean);
|
||||||
|
const detailsIdx = lines.findIndex((l) => l.startsWith("Gateway target: "));
|
||||||
|
|
||||||
|
const summaryLines = (detailsIdx >= 0 ? lines.slice(0, detailsIdx) : lines)
|
||||||
|
.map((l) => l.trim())
|
||||||
|
.filter(Boolean);
|
||||||
|
const detailLines = detailsIdx >= 0 ? lines.slice(detailsIdx) : [];
|
||||||
|
|
||||||
|
const summary = summaryLines.length > 0 ? summaryLines.join(" ") : message;
|
||||||
|
const header = colorize(rich, theme.error.bold, "Health check failed");
|
||||||
|
|
||||||
|
const out: string[] = [`${header}: ${summary}`];
|
||||||
|
for (const line of detailLines) {
|
||||||
|
out.push(` ${formatKv(line, rich)}`);
|
||||||
|
}
|
||||||
|
return out.join("\n");
|
||||||
|
}
|
||||||
@@ -3,6 +3,7 @@ import fs from "node:fs/promises";
|
|||||||
import path from "node:path";
|
import path from "node:path";
|
||||||
import { promisify } from "node:util";
|
import { promisify } from "node:util";
|
||||||
|
|
||||||
|
import { colorize, isRich, theme } from "../terminal/theme.js";
|
||||||
import {
|
import {
|
||||||
GATEWAY_LAUNCH_AGENT_LABEL,
|
GATEWAY_LAUNCH_AGENT_LABEL,
|
||||||
LEGACY_GATEWAY_LAUNCH_AGENT_LABELS,
|
LEGACY_GATEWAY_LAUNCH_AGENT_LABELS,
|
||||||
@@ -11,6 +12,11 @@ import { parseKeyValueOutput } from "./runtime-parse.js";
|
|||||||
import type { GatewayServiceRuntime } from "./service-runtime.js";
|
import type { GatewayServiceRuntime } from "./service-runtime.js";
|
||||||
|
|
||||||
const execFileAsync = promisify(execFile);
|
const execFileAsync = promisify(execFile);
|
||||||
|
|
||||||
|
const formatLine = (label: string, value: string) => {
|
||||||
|
const rich = isRich();
|
||||||
|
return `${colorize(rich, theme.muted, `${label}:`)} ${colorize(rich, theme.command, value)}`;
|
||||||
|
};
|
||||||
function resolveHomeDir(env: Record<string, string | undefined>): string {
|
function resolveHomeDir(env: Record<string, string | undefined>): string {
|
||||||
const home = env.HOME?.trim() || env.USERPROFILE?.trim();
|
const home = env.HOME?.trim() || env.USERPROFILE?.trim();
|
||||||
if (!home) throw new Error("Missing HOME");
|
if (!home) throw new Error("Missing HOME");
|
||||||
@@ -378,7 +384,9 @@ export async function uninstallLegacyLaunchAgents({
|
|||||||
const dest = path.join(trashDir, `${agent.label}.plist`);
|
const dest = path.join(trashDir, `${agent.label}.plist`);
|
||||||
try {
|
try {
|
||||||
await fs.rename(agent.plistPath, dest);
|
await fs.rename(agent.plistPath, dest);
|
||||||
stdout.write(`Moved legacy LaunchAgent to Trash: ${dest}\n`);
|
stdout.write(
|
||||||
|
`${formatLine("Moved legacy LaunchAgent to Trash", dest)}\n`,
|
||||||
|
);
|
||||||
} catch {
|
} catch {
|
||||||
stdout.write(
|
stdout.write(
|
||||||
`Legacy LaunchAgent remains at ${agent.plistPath} (could not move)\n`,
|
`Legacy LaunchAgent remains at ${agent.plistPath} (could not move)\n`,
|
||||||
@@ -414,7 +422,7 @@ export async function uninstallLaunchAgent({
|
|||||||
try {
|
try {
|
||||||
await fs.mkdir(trashDir, { recursive: true });
|
await fs.mkdir(trashDir, { recursive: true });
|
||||||
await fs.rename(plistPath, dest);
|
await fs.rename(plistPath, dest);
|
||||||
stdout.write(`Moved LaunchAgent to Trash: ${dest}\n`);
|
stdout.write(`${formatLine("Moved LaunchAgent to Trash", dest)}\n`);
|
||||||
} catch {
|
} catch {
|
||||||
stdout.write(`LaunchAgent remains at ${plistPath} (could not move)\n`);
|
stdout.write(`LaunchAgent remains at ${plistPath} (could not move)\n`);
|
||||||
}
|
}
|
||||||
@@ -446,7 +454,7 @@ export async function stopLaunchAgent({
|
|||||||
`launchctl bootout failed: ${res.stderr || res.stdout}`.trim(),
|
`launchctl bootout failed: ${res.stderr || res.stdout}`.trim(),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
stdout.write(`Stopped LaunchAgent: ${domain}/${label}\n`);
|
stdout.write(`${formatLine("Stopped LaunchAgent", `${domain}/${label}`)}\n`);
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function installLaunchAgent({
|
export async function installLaunchAgent({
|
||||||
@@ -507,8 +515,8 @@ export async function installLaunchAgent({
|
|||||||
`${domain}/${GATEWAY_LAUNCH_AGENT_LABEL}`,
|
`${domain}/${GATEWAY_LAUNCH_AGENT_LABEL}`,
|
||||||
]);
|
]);
|
||||||
|
|
||||||
stdout.write(`Installed LaunchAgent: ${plistPath}\n`);
|
stdout.write(`${formatLine("Installed LaunchAgent", plistPath)}\n`);
|
||||||
stdout.write(`Logs: ${stdoutPath}\n`);
|
stdout.write(`${formatLine("Logs", stdoutPath)}\n`);
|
||||||
return { plistPath };
|
return { plistPath };
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -525,5 +533,7 @@ export async function restartLaunchAgent({
|
|||||||
`launchctl kickstart failed: ${res.stderr || res.stdout}`.trim(),
|
`launchctl kickstart failed: ${res.stderr || res.stdout}`.trim(),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
stdout.write(`Restarted LaunchAgent: ${domain}/${label}\n`);
|
stdout.write(
|
||||||
|
`${formatLine("Restarted LaunchAgent", `${domain}/${label}`)}\n`,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ import fs from "node:fs/promises";
|
|||||||
import path from "node:path";
|
import path from "node:path";
|
||||||
import { promisify } from "node:util";
|
import { promisify } from "node:util";
|
||||||
|
|
||||||
|
import { colorize, isRich, theme } from "../terminal/theme.js";
|
||||||
import {
|
import {
|
||||||
GATEWAY_WINDOWS_TASK_NAME,
|
GATEWAY_WINDOWS_TASK_NAME,
|
||||||
LEGACY_GATEWAY_WINDOWS_TASK_NAMES,
|
LEGACY_GATEWAY_WINDOWS_TASK_NAMES,
|
||||||
@@ -12,6 +13,11 @@ import type { GatewayServiceRuntime } from "./service-runtime.js";
|
|||||||
|
|
||||||
const execFileAsync = promisify(execFile);
|
const execFileAsync = promisify(execFile);
|
||||||
|
|
||||||
|
const formatLine = (label: string, value: string) => {
|
||||||
|
const rich = isRich();
|
||||||
|
return `${colorize(rich, theme.muted, `${label}:`)} ${colorize(rich, theme.command, value)}`;
|
||||||
|
};
|
||||||
|
|
||||||
function resolveHomeDir(env: Record<string, string | undefined>): string {
|
function resolveHomeDir(env: Record<string, string | undefined>): string {
|
||||||
const home = env.USERPROFILE?.trim() || env.HOME?.trim();
|
const home = env.USERPROFILE?.trim() || env.HOME?.trim();
|
||||||
if (!home) throw new Error("Missing HOME");
|
if (!home) throw new Error("Missing HOME");
|
||||||
@@ -229,8 +235,10 @@ export async function installScheduledTask({
|
|||||||
}
|
}
|
||||||
|
|
||||||
await execSchtasks(["/Run", "/TN", GATEWAY_WINDOWS_TASK_NAME]);
|
await execSchtasks(["/Run", "/TN", GATEWAY_WINDOWS_TASK_NAME]);
|
||||||
stdout.write(`Installed Scheduled Task: ${GATEWAY_WINDOWS_TASK_NAME}\n`);
|
stdout.write(
|
||||||
stdout.write(`Task script: ${scriptPath}\n`);
|
`${formatLine("Installed Scheduled Task", GATEWAY_WINDOWS_TASK_NAME)}\n`,
|
||||||
|
);
|
||||||
|
stdout.write(`${formatLine("Task script", scriptPath)}\n`);
|
||||||
return { scriptPath };
|
return { scriptPath };
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -247,7 +255,7 @@ export async function uninstallScheduledTask({
|
|||||||
const scriptPath = resolveTaskScriptPath(env);
|
const scriptPath = resolveTaskScriptPath(env);
|
||||||
try {
|
try {
|
||||||
await fs.unlink(scriptPath);
|
await fs.unlink(scriptPath);
|
||||||
stdout.write(`Removed task script: ${scriptPath}\n`);
|
stdout.write(`${formatLine("Removed task script", scriptPath)}\n`);
|
||||||
} catch {
|
} catch {
|
||||||
stdout.write(`Task script not found at ${scriptPath}\n`);
|
stdout.write(`Task script not found at ${scriptPath}\n`);
|
||||||
}
|
}
|
||||||
@@ -272,7 +280,9 @@ export async function stopScheduledTask({
|
|||||||
if (res.code !== 0 && !isTaskNotRunning(res)) {
|
if (res.code !== 0 && !isTaskNotRunning(res)) {
|
||||||
throw new Error(`schtasks end failed: ${res.stderr || res.stdout}`.trim());
|
throw new Error(`schtasks end failed: ${res.stderr || res.stdout}`.trim());
|
||||||
}
|
}
|
||||||
stdout.write(`Stopped Scheduled Task: ${GATEWAY_WINDOWS_TASK_NAME}\n`);
|
stdout.write(
|
||||||
|
`${formatLine("Stopped Scheduled Task", GATEWAY_WINDOWS_TASK_NAME)}\n`,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function restartScheduledTask({
|
export async function restartScheduledTask({
|
||||||
@@ -286,7 +296,9 @@ export async function restartScheduledTask({
|
|||||||
if (res.code !== 0) {
|
if (res.code !== 0) {
|
||||||
throw new Error(`schtasks run failed: ${res.stderr || res.stdout}`.trim());
|
throw new Error(`schtasks run failed: ${res.stderr || res.stdout}`.trim());
|
||||||
}
|
}
|
||||||
stdout.write(`Restarted Scheduled Task: ${GATEWAY_WINDOWS_TASK_NAME}\n`);
|
stdout.write(
|
||||||
|
`${formatLine("Restarted Scheduled Task", GATEWAY_WINDOWS_TASK_NAME)}\n`,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function isScheduledTaskInstalled(): Promise<boolean> {
|
export async function isScheduledTaskInstalled(): Promise<boolean> {
|
||||||
@@ -400,7 +412,9 @@ export async function uninstallLegacyScheduledTasks({
|
|||||||
|
|
||||||
try {
|
try {
|
||||||
await fs.unlink(task.scriptPath);
|
await fs.unlink(task.scriptPath);
|
||||||
stdout.write(`Removed legacy task script: ${task.scriptPath}\n`);
|
stdout.write(
|
||||||
|
`${formatLine("Removed legacy task script", task.scriptPath)}\n`,
|
||||||
|
);
|
||||||
} catch {
|
} catch {
|
||||||
stdout.write(`Legacy task script not found at ${task.scriptPath}\n`);
|
stdout.write(`Legacy task script not found at ${task.scriptPath}\n`);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ import os from "node:os";
|
|||||||
import path from "node:path";
|
import path from "node:path";
|
||||||
import { promisify } from "node:util";
|
import { promisify } from "node:util";
|
||||||
import { runCommandWithTimeout, runExec } from "../process/exec.js";
|
import { runCommandWithTimeout, runExec } from "../process/exec.js";
|
||||||
|
import { colorize, isRich, theme } from "../terminal/theme.js";
|
||||||
import {
|
import {
|
||||||
GATEWAY_SYSTEMD_SERVICE_NAME,
|
GATEWAY_SYSTEMD_SERVICE_NAME,
|
||||||
LEGACY_GATEWAY_SYSTEMD_SERVICE_NAMES,
|
LEGACY_GATEWAY_SYSTEMD_SERVICE_NAMES,
|
||||||
@@ -13,6 +14,11 @@ import type { GatewayServiceRuntime } from "./service-runtime.js";
|
|||||||
|
|
||||||
const execFileAsync = promisify(execFile);
|
const execFileAsync = promisify(execFile);
|
||||||
|
|
||||||
|
const formatLine = (label: string, value: string) => {
|
||||||
|
const rich = isRich();
|
||||||
|
return `${colorize(rich, theme.muted, `${label}:`)} ${colorize(rich, theme.command, value)}`;
|
||||||
|
};
|
||||||
|
|
||||||
function resolveHomeDir(env: Record<string, string | undefined>): string {
|
function resolveHomeDir(env: Record<string, string | undefined>): string {
|
||||||
const home = env.HOME?.trim() || env.USERPROFILE?.trim();
|
const home = env.HOME?.trim() || env.USERPROFILE?.trim();
|
||||||
if (!home) throw new Error("Missing HOME");
|
if (!home) throw new Error("Missing HOME");
|
||||||
@@ -410,7 +416,7 @@ export async function installSystemdService({
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
stdout.write(`Installed systemd service: ${unitPath}\n`);
|
stdout.write(`${formatLine("Installed systemd service", unitPath)}\n`);
|
||||||
return { unitPath };
|
return { unitPath };
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -428,7 +434,7 @@ export async function uninstallSystemdService({
|
|||||||
const unitPath = resolveSystemdUnitPath(env);
|
const unitPath = resolveSystemdUnitPath(env);
|
||||||
try {
|
try {
|
||||||
await fs.unlink(unitPath);
|
await fs.unlink(unitPath);
|
||||||
stdout.write(`Removed systemd service: ${unitPath}\n`);
|
stdout.write(`${formatLine("Removed systemd service", unitPath)}\n`);
|
||||||
} catch {
|
} catch {
|
||||||
stdout.write(`Systemd service not found at ${unitPath}\n`);
|
stdout.write(`Systemd service not found at ${unitPath}\n`);
|
||||||
}
|
}
|
||||||
@@ -447,7 +453,7 @@ export async function stopSystemdService({
|
|||||||
`systemctl stop failed: ${res.stderr || res.stdout}`.trim(),
|
`systemctl stop failed: ${res.stderr || res.stdout}`.trim(),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
stdout.write(`Stopped systemd service: ${unitName}\n`);
|
stdout.write(`${formatLine("Stopped systemd service", unitName)}\n`);
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function restartSystemdService({
|
export async function restartSystemdService({
|
||||||
@@ -463,7 +469,7 @@ export async function restartSystemdService({
|
|||||||
`systemctl restart failed: ${res.stderr || res.stdout}`.trim(),
|
`systemctl restart failed: ${res.stderr || res.stdout}`.trim(),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
stdout.write(`Restarted systemd service: ${unitName}\n`);
|
stdout.write(`${formatLine("Restarted systemd service", unitName)}\n`);
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function isSystemdServiceEnabled(): Promise<boolean> {
|
export async function isSystemdServiceEnabled(): Promise<boolean> {
|
||||||
@@ -584,7 +590,9 @@ export async function uninstallLegacySystemdUnits({
|
|||||||
|
|
||||||
try {
|
try {
|
||||||
await fs.unlink(unit.unitPath);
|
await fs.unlink(unit.unitPath);
|
||||||
stdout.write(`Removed legacy systemd service: ${unit.unitPath}\n`);
|
stdout.write(
|
||||||
|
`${formatLine("Removed legacy systemd service", unit.unitPath)}\n`,
|
||||||
|
);
|
||||||
} catch {
|
} catch {
|
||||||
stdout.write(`Legacy systemd unit not found at ${unit.unitPath}\n`);
|
stdout.write(`Legacy systemd unit not found at ${unit.unitPath}\n`);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -13,6 +13,7 @@ import {
|
|||||||
type GatewayDaemonRuntime,
|
type GatewayDaemonRuntime,
|
||||||
} from "../commands/daemon-runtime.js";
|
} from "../commands/daemon-runtime.js";
|
||||||
import { healthCommand } from "../commands/health.js";
|
import { healthCommand } from "../commands/health.js";
|
||||||
|
import { formatHealthCheckFailure } from "../commands/health-format.js";
|
||||||
import {
|
import {
|
||||||
applyWizardMetadata,
|
applyWizardMetadata,
|
||||||
DEFAULT_WORKSPACE,
|
DEFAULT_WORKSPACE,
|
||||||
@@ -664,7 +665,7 @@ export async function runOnboardingWizard(
|
|||||||
try {
|
try {
|
||||||
await healthCommand({ json: false, timeoutMs: 10_000 }, runtime);
|
await healthCommand({ json: false, timeoutMs: 10_000 }, runtime);
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
runtime.error(`Health check failed: ${String(err)}`);
|
runtime.error(formatHealthCheckFailure(err));
|
||||||
await prompter.note(
|
await prompter.note(
|
||||||
[
|
[
|
||||||
"Docs:",
|
"Docs:",
|
||||||
@@ -740,7 +741,7 @@ export async function runOnboardingWizard(
|
|||||||
"Start TUI (best option!)",
|
"Start TUI (best option!)",
|
||||||
);
|
);
|
||||||
const wantsTui = await prompter.confirm({
|
const wantsTui = await prompter.confirm({
|
||||||
message: "Start TUI now? (best option!)",
|
message: "Do you want to hatch your bot now?",
|
||||||
initialValue: true,
|
initialValue: true,
|
||||||
});
|
});
|
||||||
if (wantsTui) {
|
if (wantsTui) {
|
||||||
|
|||||||
Reference in New Issue
Block a user