File size: 5,352 Bytes
d197cf3 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 | /** Cross-platform daemon service names, labels, and profile-aware descriptions. */
import { normalizeLowercaseStringOrEmpty } from "@openclaw/normalization-core/string-coerce";
// Default service labels (canonical + legacy compatibility)
export const GATEWAY_LAUNCH_AGENT_LABEL = "ai.openclaw.gateway";
const GATEWAY_SYSTEMD_SERVICE_NAME = "openclaw-gateway";
const GATEWAY_WINDOWS_TASK_NAME = "OpenClaw Gateway";
export const GATEWAY_SERVICE_MARKER = "openclaw";
export const GATEWAY_SERVICE_KIND = "gateway";
export const GATEWAY_SERVICE_RUNTIME_PID_ENV = "OPENCLAW_GATEWAY_SERVICE_PID";
export const GATEWAY_SERVICE_SELECTOR_ENV_KEYS = [
"OPENCLAW_STATE_DIR",
"OPENCLAW_CONFIG_PATH",
"OPENCLAW_PROFILE",
"OPENCLAW_GATEWAY_PORT",
"OPENCLAW_LAUNCHD_LABEL",
"OPENCLAW_SYSTEMD_UNIT",
"OPENCLAW_WINDOWS_TASK_NAME",
] as const;
export function isGatewayServiceEnv(env: Record<string, string | undefined>): boolean {
if (env.OPENCLAW_SERVICE_MARKER?.trim() !== GATEWAY_SERVICE_MARKER) {
return false;
}
const serviceKind = env.OPENCLAW_SERVICE_KIND?.trim();
return !serviceKind || serviceKind === GATEWAY_SERVICE_KIND;
}
const NODE_LAUNCH_AGENT_LABEL = "ai.openclaw.node";
const NODE_SYSTEMD_SERVICE_NAME = "openclaw-node";
const NODE_WINDOWS_TASK_NAME = "OpenClaw Node";
const NODE_SERVICE_MARKER = "openclaw";
export const NODE_SERVICE_KIND = "node";
const NODE_WINDOWS_TASK_SCRIPT_NAME = "node.cmd";
export const LEGACY_GATEWAY_SYSTEMD_SERVICE_NAMES: string[] = ["clawdbot-gateway"];
function normalizeGatewayProfile(profile?: string): string | null {
const trimmed = profile?.trim();
if (!trimmed || normalizeLowercaseStringOrEmpty(trimmed) === "default") {
// The default profile keeps the historical unqualified service names.
return null;
}
return trimmed;
}
export function resolveGatewayProfileSuffix(profile?: string): string {
const normalized = normalizeGatewayProfile(profile);
return normalized ? `-${normalized}` : "";
}
export function resolveGatewayLaunchAgentLabel(profile?: string): string {
const normalized = normalizeGatewayProfile(profile);
if (!normalized) {
return GATEWAY_LAUNCH_AGENT_LABEL;
}
return `ai.openclaw.${normalized}`;
}
export function resolveGatewaySystemdServiceName(profile?: string): string {
const suffix = resolveGatewayProfileSuffix(profile);
if (!suffix) {
return GATEWAY_SYSTEMD_SERVICE_NAME;
}
return `openclaw-gateway${suffix}`;
}
export function resolveGatewayWindowsTaskName(profile?: string): string {
const normalized = normalizeGatewayProfile(profile);
if (!normalized) {
return GATEWAY_WINDOWS_TASK_NAME;
}
return `OpenClaw Gateway (${normalized})`;
}
type GatewayNativeServiceIdentityConflict = {
envKey: "OPENCLAW_LAUNCHD_LABEL" | "OPENCLAW_SYSTEMD_UNIT" | "OPENCLAW_WINDOWS_TASK_NAME";
expected: string;
};
export function resolveGatewayNativeServiceIdentityConflict(
env: Record<string, string | undefined>,
platform: NodeJS.Platform = process.platform,
): GatewayNativeServiceIdentityConflict | null {
const profile = normalizeGatewayProfile(env.OPENCLAW_PROFILE);
if (!profile) {
return null;
}
if (platform === "darwin") {
const envKey = "OPENCLAW_LAUNCHD_LABEL";
const actual = env[envKey]?.trim();
const expected = resolveGatewayLaunchAgentLabel(profile);
return actual && actual !== expected ? { envKey, expected } : null;
}
if (platform === "linux") {
const envKey = "OPENCLAW_SYSTEMD_UNIT";
const actual = env[envKey]?.trim();
const normalizedActual = actual?.endsWith(".service") ? actual : actual && `${actual}.service`;
const expected = `${resolveGatewaySystemdServiceName(profile)}.service`;
return normalizedActual && normalizedActual !== expected ? { envKey, expected } : null;
}
if (platform === "win32") {
const envKey = "OPENCLAW_WINDOWS_TASK_NAME";
const actual = env[envKey]?.trim();
const expected = resolveGatewayWindowsTaskName(profile);
return actual && actual !== expected ? { envKey, expected } : null;
}
return null;
}
function formatGatewayServiceDescription(profile?: string): string {
const normalized = normalizeGatewayProfile(profile);
if (!normalized) {
return "OpenClaw Gateway";
}
return `OpenClaw Gateway (profile: ${normalized})`;
}
export function resolveGatewayServiceDescription(params: {
env: Record<string, string | undefined>;
description?: string;
}): string {
return params.description ?? formatGatewayServiceDescription(params.env.OPENCLAW_PROFILE);
}
export function resolveNodeLaunchAgentLabel(): string {
return NODE_LAUNCH_AGENT_LABEL;
}
export function resolveNodeSystemdServiceName(): string {
return NODE_SYSTEMD_SERVICE_NAME;
}
export function resolveNodeWindowsTaskName(): string {
return NODE_WINDOWS_TASK_NAME;
}
export function resolveNodeServiceIdentityEnvironment(): Record<string, string> {
return {
OPENCLAW_LAUNCHD_LABEL: resolveNodeLaunchAgentLabel(),
OPENCLAW_SYSTEMD_UNIT: resolveNodeSystemdServiceName(),
OPENCLAW_WINDOWS_TASK_NAME: resolveNodeWindowsTaskName(),
OPENCLAW_WINDOWS_TASK_HIDDEN_LAUNCHER: "1",
OPENCLAW_TASK_SCRIPT_NAME: NODE_WINDOWS_TASK_SCRIPT_NAME,
OPENCLAW_LOG_PREFIX: "node",
OPENCLAW_SERVICE_MARKER: NODE_SERVICE_MARKER,
OPENCLAW_SERVICE_KIND: NODE_SERVICE_KIND,
};
}
|