refactor(daemon): share service arg types across backends

This commit is contained in:
Peter Steinberger
2026-02-19 10:03:09 +00:00
parent be7462af1e
commit 70900feaa7
5 changed files with 109 additions and 144 deletions

View File

@@ -15,6 +15,14 @@ import { formatLine, toPosixPath, writeFormattedLines } from "./output.js";
import { resolveGatewayStateDir, resolveHomeDir } from "./paths.js";
import { parseKeyValueOutput } from "./runtime-parse.js";
import type { GatewayServiceRuntime } from "./service-runtime.js";
import type {
GatewayServiceCommandConfig,
GatewayServiceControlArgs,
GatewayServiceEnv,
GatewayServiceEnvArgs,
GatewayServiceInstallArgs,
GatewayServiceManageArgs,
} from "./service-types.js";
function resolveLaunchAgentLabel(args?: { env?: Record<string, string | undefined> }): string {
const envLabel = args?.env?.OPENCLAW_LAUNCHD_LABEL?.trim();
@@ -32,12 +40,12 @@ function resolveLaunchAgentPlistPathForLabel(
return path.posix.join(home, "Library", "LaunchAgents", `${label}.plist`);
}
export function resolveLaunchAgentPlistPath(env: Record<string, string | undefined>): string {
export function resolveLaunchAgentPlistPath(env: GatewayServiceEnv): string {
const label = resolveLaunchAgentLabel({ env });
return resolveLaunchAgentPlistPathForLabel(env, label);
}
export function resolveGatewayLogPaths(env: Record<string, string | undefined>): {
export function resolveGatewayLogPaths(env: GatewayServiceEnv): {
logDir: string;
stdoutPath: string;
stderrPath: string;
@@ -53,13 +61,8 @@ export function resolveGatewayLogPaths(env: Record<string, string | undefined>):
}
export async function readLaunchAgentProgramArguments(
env: Record<string, string | undefined>,
): Promise<{
programArguments: string[];
workingDirectory?: string;
environment?: Record<string, string>;
sourcePath?: string;
} | null> {
env: GatewayServiceEnv,
): Promise<GatewayServiceCommandConfig | null> {
const plistPath = resolveLaunchAgentPlistPath(env);
return readLaunchAgentProgramArgumentsFromFile(plistPath);
}
@@ -143,18 +146,14 @@ export function parseLaunchctlPrint(output: string): LaunchctlPrintInfo {
return info;
}
export async function isLaunchAgentLoaded(args: {
env?: Record<string, string | undefined>;
}): Promise<boolean> {
export async function isLaunchAgentLoaded(args: GatewayServiceEnvArgs): Promise<boolean> {
const domain = resolveGuiDomain();
const label = resolveLaunchAgentLabel({ env: args.env });
const res = await execLaunchctl(["print", `${domain}/${label}`]);
return res.code === 0;
}
export async function isLaunchAgentListed(args: {
env?: Record<string, string | undefined>;
}): Promise<boolean> {
export async function isLaunchAgentListed(args: GatewayServiceEnvArgs): Promise<boolean> {
const label = resolveLaunchAgentLabel({ env: args.env });
const res = await execLaunchctl(["list"]);
if (res.code !== 0) {
@@ -163,9 +162,7 @@ export async function isLaunchAgentListed(args: {
return res.stdout.split(/\r?\n/).some((line) => line.trim().split(/\s+/).at(-1) === label);
}
export async function launchAgentPlistExists(
env: Record<string, string | undefined>,
): Promise<boolean> {
export async function launchAgentPlistExists(env: GatewayServiceEnv): Promise<boolean> {
try {
const plistPath = resolveLaunchAgentPlistPath(env);
await fs.access(plistPath);
@@ -227,9 +224,7 @@ export type LegacyLaunchAgent = {
exists: boolean;
};
export async function findLegacyLaunchAgents(
env: Record<string, string | undefined>,
): Promise<LegacyLaunchAgent[]> {
export async function findLegacyLaunchAgents(env: GatewayServiceEnv): Promise<LegacyLaunchAgent[]> {
const domain = resolveGuiDomain();
const results: LegacyLaunchAgent[] = [];
for (const label of resolveLegacyGatewayLaunchAgentLabels(env.OPENCLAW_PROFILE)) {
@@ -253,10 +248,7 @@ export async function findLegacyLaunchAgents(
export async function uninstallLegacyLaunchAgents({
env,
stdout,
}: {
env: Record<string, string | undefined>;
stdout: NodeJS.WritableStream;
}): Promise<LegacyLaunchAgent[]> {
}: GatewayServiceManageArgs): Promise<LegacyLaunchAgent[]> {
const domain = resolveGuiDomain();
const agents = await findLegacyLaunchAgents(env);
if (agents.length === 0) {
@@ -296,10 +288,7 @@ export async function uninstallLegacyLaunchAgents({
export async function uninstallLaunchAgent({
env,
stdout,
}: {
env: Record<string, string | undefined>;
stdout: NodeJS.WritableStream;
}): Promise<void> {
}: GatewayServiceManageArgs): Promise<void> {
const domain = resolveGuiDomain();
const label = resolveLaunchAgentLabel({ env });
const plistPath = resolveLaunchAgentPlistPath(env);
@@ -342,13 +331,7 @@ function isUnsupportedGuiDomain(detail: string): boolean {
);
}
export async function stopLaunchAgent({
stdout,
env,
}: {
stdout: NodeJS.WritableStream;
env?: Record<string, string | undefined>;
}): Promise<void> {
export async function stopLaunchAgent({ stdout, env }: GatewayServiceControlArgs): Promise<void> {
const domain = resolveGuiDomain();
const label = resolveLaunchAgentLabel({ env });
const res = await execLaunchctl(["bootout", `${domain}/${label}`]);
@@ -365,14 +348,7 @@ export async function installLaunchAgent({
workingDirectory,
environment,
description,
}: {
env: Record<string, string | undefined>;
stdout: NodeJS.WritableStream;
programArguments: string[];
workingDirectory?: string;
environment?: Record<string, string | undefined>;
description?: string;
}): Promise<{ plistPath: string }> {
}: GatewayServiceInstallArgs): Promise<{ plistPath: string }> {
const { logDir, stdoutPath, stderrPath } = resolveGatewayLogPaths(env);
await fs.mkdir(logDir, { recursive: true });
@@ -441,10 +417,7 @@ export async function installLaunchAgent({
export async function restartLaunchAgent({
stdout,
env,
}: {
stdout: NodeJS.WritableStream;
env?: Record<string, string | undefined>;
}): Promise<void> {
}: GatewayServiceControlArgs): Promise<void> {
const domain = resolveGuiDomain();
const label = resolveLaunchAgentLabel({ env });
const res = await execLaunchctl(["kickstart", "-k", `${domain}/${label}`]);