refactor: dedupe cli daemon readers

This commit is contained in:
Peter Steinberger
2026-04-07 06:31:16 +01:00
parent cd313c7f67
commit 829fe14188
6 changed files with 26 additions and 13 deletions

View File

@@ -1,5 +1,11 @@
import { normalizeOptionalString } from "../shared/string-coerce.js";
export function resolveDaemonContainerContext(
env: Record<string, string | undefined> = process.env,
): string | null {
return env.OPENCLAW_CONTAINER_HINT?.trim() || env.OPENCLAW_CONTAINER?.trim() || null;
return (
normalizeOptionalString(env.OPENCLAW_CONTAINER_HINT) ||
normalizeOptionalString(env.OPENCLAW_CONTAINER) ||
null
);
}

View File

@@ -2,6 +2,7 @@ import { spawn } from "node:child_process";
import os from "node:os";
import path from "node:path";
import { formatErrorMessage } from "../infra/errors.js";
import { normalizeOptionalString } from "../shared/string-coerce.js";
import { resolveGatewayLaunchAgentLabel } from "./constants.js";
export type LaunchdRestartHandoffMode = "kickstart" | "start-after-exit";
@@ -27,7 +28,7 @@ function resolveGuiDomain(): string {
}
function resolveLaunchAgentLabel(env?: Record<string, string | undefined>): string {
const envLabel = env?.OPENCLAW_LAUNCHD_LABEL?.trim();
const envLabel = normalizeOptionalString(env?.OPENCLAW_LAUNCHD_LABEL);
if (envLabel) {
return envLabel;
}
@@ -39,7 +40,7 @@ export function resolveLaunchdRestartTarget(
): LaunchdRestartTarget {
const domain = resolveGuiDomain();
const label = resolveLaunchAgentLabel(env);
const home = env.HOME?.trim() || os.homedir();
const home = normalizeOptionalString(env.HOME) || os.homedir();
const plistPath = path.join(home, "Library", "LaunchAgents", `${label}.plist`);
return {
domain,
@@ -54,11 +55,13 @@ export function isCurrentProcessLaunchdServiceLabel(
env: NodeJS.ProcessEnv = process.env,
): boolean {
const launchdLabel =
env.LAUNCH_JOB_LABEL?.trim() || env.LAUNCH_JOB_NAME?.trim() || env.XPC_SERVICE_NAME?.trim();
normalizeOptionalString(env.LAUNCH_JOB_LABEL) ||
normalizeOptionalString(env.LAUNCH_JOB_NAME) ||
normalizeOptionalString(env.XPC_SERVICE_NAME);
if (launchdLabel) {
return launchdLabel === label;
}
const configuredLabel = env.OPENCLAW_LAUNCHD_LABEL?.trim();
const configuredLabel = normalizeOptionalString(env.OPENCLAW_LAUNCHD_LABEL);
return Boolean(configuredLabel && configuredLabel === label);
}

View File

@@ -1,11 +1,12 @@
import path from "node:path";
import { normalizeOptionalString } from "../shared/string-coerce.js";
import { resolveGatewayProfileSuffix } from "./constants.js";
const windowsAbsolutePath = /^[a-zA-Z]:[\\/]/;
const windowsUncPath = /^\\\\/;
export function resolveHomeDir(env: Record<string, string | undefined>): string {
const home = env.HOME?.trim() || env.USERPROFILE?.trim();
const home = normalizeOptionalString(env.HOME) || normalizeOptionalString(env.USERPROFILE);
if (!home) {
throw new Error("Missing HOME");
}
@@ -31,7 +32,7 @@ export function resolveUserPathWithHome(input: string, home?: string): string {
}
export function resolveGatewayStateDir(env: Record<string, string | undefined>): string {
const override = env.OPENCLAW_STATE_DIR?.trim();
const override = normalizeOptionalString(env.OPENCLAW_STATE_DIR);
if (override) {
const home = override.startsWith("~") ? resolveHomeDir(env) : undefined;
return resolveUserPathWithHome(override, home);

View File

@@ -1,9 +1,10 @@
import os from "node:os";
import { formatErrorMessage } from "../infra/errors.js";
import { runCommandWithTimeout, runExec } from "../process/exec.js";
import { normalizeOptionalString } from "../shared/string-coerce.js";
function resolveLoginctlUser(env: Record<string, string | undefined>): string | null {
const fromEnv = env.USER?.trim() || env.LOGNAME?.trim();
const fromEnv = normalizeOptionalString(env.USER) || normalizeOptionalString(env.LOGNAME);
if (fromEnv) {
return fromEnv;
}
@@ -34,7 +35,7 @@ export async function readSystemdUserLingerStatus(
.split("\n")
.map((entry) => entry.trim())
.find((entry) => entry.startsWith("Linger="));
const value = line?.split("=")[1]?.trim().toLowerCase();
const value = normalizeOptionalString(line?.split("=")[1])?.toLowerCase();
if (value === "yes" || value === "no") {
return { user, linger: value };
}