Lazy-load daemon status adapters

This commit is contained in:
Junebugg1214 2026-03-20 23:54:45 -04:00
parent 03c54162b8
commit 465f8aaa14
2 changed files with 99 additions and 6 deletions

View File

@ -1,7 +1,16 @@
import { resolveNodeService } from "../daemon/node-service.js";
import { resolveGatewayService } from "../daemon/service.js";
import {
NODE_SERVICE_KIND,
NODE_SERVICE_MARKER,
NODE_WINDOWS_TASK_SCRIPT_NAME,
resolveNodeLaunchAgentLabel,
resolveNodeSystemdServiceName,
resolveNodeWindowsTaskName,
} from "../daemon/constants.js";
import { formatDaemonRuntimeShort } from "./status.format.js";
import { readServiceStatusSummary } from "./status.service-summary.js";
import {
readServiceStatusSummary,
type GatewayServiceStatusReader,
} from "./status.service-summary.js";
type DaemonStatusSummary = {
label: string;
@ -12,10 +21,81 @@ type DaemonStatusSummary = {
runtimeShort: string | null;
};
function withNodeServiceEnv(
env: Record<string, string | undefined>,
): Record<string, string | undefined> {
return {
...env,
OPENCLAW_LAUNCHD_LABEL: resolveNodeLaunchAgentLabel(),
OPENCLAW_SYSTEMD_UNIT: resolveNodeSystemdServiceName(),
OPENCLAW_WINDOWS_TASK_NAME: resolveNodeWindowsTaskName(),
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,
};
}
async function loadGatewayServiceStatusReader(): Promise<GatewayServiceStatusReader> {
if (process.platform === "darwin") {
const launchd = await import("../daemon/launchd.js");
return {
label: "LaunchAgent",
loadedText: "loaded",
notLoadedText: "not loaded",
isLoaded: launchd.isLaunchAgentLoaded,
readCommand: launchd.readLaunchAgentProgramArguments,
readRuntime: launchd.readLaunchAgentRuntime,
};
}
if (process.platform === "linux") {
const systemd = await import("../daemon/systemd.js");
return {
label: "systemd",
loadedText: "enabled",
notLoadedText: "disabled",
isLoaded: systemd.isSystemdServiceEnabled,
readCommand: systemd.readSystemdServiceExecStart,
readRuntime: systemd.readSystemdServiceRuntime,
};
}
if (process.platform === "win32") {
const schtasks = await import("../daemon/schtasks.js");
return {
label: "Scheduled Task",
loadedText: "registered",
notLoadedText: "missing",
isLoaded: schtasks.isScheduledTaskInstalled,
readCommand: schtasks.readScheduledTaskCommand,
readRuntime: schtasks.readScheduledTaskRuntime,
};
}
throw new Error(`Gateway service install not supported on ${process.platform}`);
}
async function loadNodeServiceStatusReader(): Promise<GatewayServiceStatusReader> {
const base = await loadGatewayServiceStatusReader();
return {
...base,
isLoaded: async (args) => {
return base.isLoaded({ env: withNodeServiceEnv(args.env ?? {}) });
},
readCommand: async (env) => {
return base.readCommand(withNodeServiceEnv(env));
},
readRuntime: async (env) => {
return base.readRuntime(withNodeServiceEnv(env));
},
};
}
async function buildDaemonStatusSummary(
serviceLabel: "gateway" | "node",
): Promise<DaemonStatusSummary> {
const service = serviceLabel === "gateway" ? resolveGatewayService() : resolveNodeService();
const service =
serviceLabel === "gateway"
? await loadGatewayServiceStatusReader()
: await loadNodeServiceStatusReader();
const fallbackLabel = serviceLabel === "gateway" ? "Daemon" : "Node";
const summary = await readServiceStatusSummary(service, fallbackLabel);
return {

View File

@ -1,5 +1,18 @@
import type { GatewayServiceRuntime } from "../daemon/service-runtime.js";
import type { GatewayService } from "../daemon/service.js";
import type {
GatewayServiceCommandConfig,
GatewayServiceEnv,
GatewayServiceEnvArgs,
} from "../daemon/service-types.js";
export type GatewayServiceStatusReader = {
label: string;
loadedText: string;
notLoadedText: string;
isLoaded: (args: GatewayServiceEnvArgs) => Promise<boolean>;
readCommand: (env: GatewayServiceEnv) => Promise<GatewayServiceCommandConfig | null>;
readRuntime: (env: GatewayServiceEnv) => Promise<GatewayServiceRuntime | undefined>;
};
export type ServiceStatusSummary = {
label: string;
@ -12,7 +25,7 @@ export type ServiceStatusSummary = {
};
export async function readServiceStatusSummary(
service: GatewayService,
service: GatewayServiceStatusReader,
fallbackLabel: string,
): Promise<ServiceStatusSummary> {
try {