110 lines
3.3 KiB
TypeScript
110 lines
3.3 KiB
TypeScript
import {
|
|
resolveGatewayLaunchAgentLabel,
|
|
resolveGatewaySystemdServiceName,
|
|
resolveGatewayWindowsTaskName,
|
|
} from "../../daemon/constants.js";
|
|
import { resolveGatewayService } from "../../daemon/service.js";
|
|
import { defaultRuntime } from "../../runtime.js";
|
|
import { formatCliCommand } from "../command-format.js";
|
|
import { parsePort } from "../shared/parse-port.js";
|
|
|
|
export { parsePort };
|
|
|
|
export const toOptionString = (value: unknown): string | undefined => {
|
|
if (typeof value === "string") {
|
|
return value;
|
|
}
|
|
if (typeof value === "number" || typeof value === "bigint") {
|
|
return value.toString();
|
|
}
|
|
return undefined;
|
|
};
|
|
|
|
export function describeUnknownError(err: unknown): string {
|
|
if (err instanceof Error) {
|
|
return err.message;
|
|
}
|
|
if (typeof err === "string") {
|
|
return err;
|
|
}
|
|
if (typeof err === "number" || typeof err === "bigint") {
|
|
return err.toString();
|
|
}
|
|
if (typeof err === "boolean") {
|
|
return err ? "true" : "false";
|
|
}
|
|
if (err && typeof err === "object") {
|
|
if ("message" in err && typeof err.message === "string") {
|
|
return err.message;
|
|
}
|
|
try {
|
|
return JSON.stringify(err);
|
|
} catch {
|
|
return "Unknown error";
|
|
}
|
|
}
|
|
return "Unknown error";
|
|
}
|
|
|
|
export function extractGatewayMiskeys(parsed: unknown): {
|
|
hasGatewayToken: boolean;
|
|
hasRemoteToken: boolean;
|
|
} {
|
|
if (!parsed || typeof parsed !== "object") {
|
|
return { hasGatewayToken: false, hasRemoteToken: false };
|
|
}
|
|
const gateway = (parsed as Record<string, unknown>).gateway;
|
|
if (!gateway || typeof gateway !== "object") {
|
|
return { hasGatewayToken: false, hasRemoteToken: false };
|
|
}
|
|
const hasGatewayToken = "token" in (gateway as Record<string, unknown>);
|
|
const remote = (gateway as Record<string, unknown>).remote;
|
|
const hasRemoteToken =
|
|
remote && typeof remote === "object" ? "token" in (remote as Record<string, unknown>) : false;
|
|
return { hasGatewayToken, hasRemoteToken };
|
|
}
|
|
|
|
export function renderGatewayServiceStopHints(env: NodeJS.ProcessEnv = process.env): string[] {
|
|
const profile = env.OPENCLAW_PROFILE;
|
|
switch (process.platform) {
|
|
case "darwin":
|
|
return [
|
|
`Tip: ${formatCliCommand("openclaw gateway stop")}`,
|
|
`Or: launchctl bootout gui/$UID/${resolveGatewayLaunchAgentLabel(profile)}`,
|
|
];
|
|
case "linux":
|
|
return [
|
|
`Tip: ${formatCliCommand("openclaw gateway stop")}`,
|
|
`Or: systemctl --user stop ${resolveGatewaySystemdServiceName(profile)}.service`,
|
|
];
|
|
case "win32":
|
|
return [
|
|
`Tip: ${formatCliCommand("openclaw gateway stop")}`,
|
|
`Or: schtasks /End /TN "${resolveGatewayWindowsTaskName(profile)}"`,
|
|
];
|
|
default:
|
|
return [`Tip: ${formatCliCommand("openclaw gateway stop")}`];
|
|
}
|
|
}
|
|
|
|
export async function maybeExplainGatewayServiceStop() {
|
|
const service = resolveGatewayService();
|
|
let loaded: boolean | null = null;
|
|
try {
|
|
loaded = await service.isLoaded({ env: process.env });
|
|
} catch {
|
|
loaded = null;
|
|
}
|
|
if (loaded === false) {
|
|
return;
|
|
}
|
|
defaultRuntime.error(
|
|
loaded
|
|
? `Gateway service appears ${service.loadedText}. Stop it first.`
|
|
: "Gateway service status unknown; if supervised, stop it first.",
|
|
);
|
|
for (const hint of renderGatewayServiceStopHints()) {
|
|
defaultRuntime.error(hint);
|
|
}
|
|
}
|