fix: improve WSL2 systemd daemon hints

This commit is contained in:
Peter Steinberger
2026-01-17 18:19:47 +00:00
parent 408f4f2dac
commit 8a67d29748
10 changed files with 110 additions and 36 deletions

View File

@@ -4,6 +4,11 @@ import {
resolveGatewayWindowsTaskName,
} from "../daemon/constants.js";
import { resolveGatewayLogPaths } from "../daemon/launchd.js";
import {
isSystemdUnavailableDetail,
renderSystemdUnavailableHints,
} from "../daemon/systemd-hints.js";
import { isWSLEnv } from "../infra/wsl.js";
import type { GatewayServiceRuntime } from "../daemon/service-runtime.js";
import { getResolvedLoggerSettings } from "../logging.js";
@@ -54,6 +59,11 @@ export function buildGatewayRuntimeHints(
return null;
}
})();
if (platform === "linux" && isSystemdUnavailableDetail(runtime.detail)) {
hints.push(...renderSystemdUnavailableHints({ wsl: isWSLEnv() }));
if (fileLog) hints.push(`File logs: ${fileLog}`);
return hints;
}
if (runtime.cachedLabel && platform === "darwin") {
const label = resolveGatewayLaunchAgentLabel(env.CLAWDBOT_PROFILE);
hints.push(

View File

@@ -12,7 +12,10 @@ import {
} from "../daemon/runtime-paths.js";
import { resolveGatewayService } from "../daemon/service.js";
import { buildServiceEnvironment } from "../daemon/service-env.js";
import { isSystemdUserServiceAvailable } from "../daemon/systemd.js";
import { renderSystemdUnavailableHints } from "../daemon/systemd-hints.js";
import { formatPortDiagnostics, inspectPortUsage } from "../infra/ports.js";
import { isWSL } from "../infra/wsl.js";
import type { RuntimeEnv } from "../runtime.js";
import { note } from "../terminal/note.js";
import { sleep } from "../utils.js";
@@ -55,6 +58,14 @@ export async function maybeRepairGatewayDaemon(params: {
}
if (!loaded) {
if (process.platform === "linux") {
const systemdAvailable = await isSystemdUserServiceAvailable().catch(() => false);
if (!systemdAvailable) {
const wsl = await isWSL();
note(renderSystemdUnavailableHints({ wsl }).join("\n"), "Gateway");
return;
}
}
note("Gateway daemon not installed.", "Gateway");
if (params.cfg.gateway?.mode !== "remote") {
const install = await params.prompter.confirmSkipInNonInteractive({

View File

@@ -1,14 +1,4 @@
import { readFileSync } from "node:fs";
function isWSL(): boolean {
if (process.platform !== "linux") return false;
try {
const release = readFileSync("/proc/version", "utf8").toLowerCase();
return release.includes("microsoft") || release.includes("wsl");
} catch {
return false;
}
}
import { isWSLEnv } from "../infra/wsl.js";
export function isRemoteEnvironment(): boolean {
if (process.env.SSH_CLIENT || process.env.SSH_TTY || process.env.SSH_CONNECTION) {
@@ -23,7 +13,7 @@ export function isRemoteEnvironment(): boolean {
process.platform === "linux" &&
!process.env.DISPLAY &&
!process.env.WAYLAND_DISPLAY &&
!isWSL()
!isWSLEnv()
) {
return true;
}

View File

@@ -13,6 +13,7 @@ import { callGateway } from "../gateway/call.js";
import { normalizeControlUiBasePath } from "../gateway/control-ui.js";
import { isSafeExecutableValue } from "../infra/exec-safety.js";
import { pickPrimaryTailnetIPv4 } from "../infra/tailnet.js";
import { isWSL } from "../infra/wsl.js";
import { runCommandWithTimeout } from "../process/exec.js";
import type { RuntimeEnv } from "../runtime.js";
import { stylePromptTitle } from "../terminal/prompt-style.js";
@@ -91,27 +92,6 @@ type BrowserOpenSupport = {
command?: string;
};
let wslCached: boolean | null = null;
async function isWSL(): Promise<boolean> {
if (wslCached !== null) return wslCached;
if (process.platform !== "linux") {
wslCached = false;
return wslCached;
}
if (process.env.WSL_INTEROP || process.env.WSL_DISTRO_NAME || process.env.WSLENV) {
wslCached = true;
return wslCached;
}
try {
const release = (await fs.readFile("/proc/version", "utf8")).toLowerCase();
wslCached = release.includes("microsoft") || release.includes("wsl");
} catch {
wslCached = false;
}
return wslCached;
}
type BrowserOpenCommand = {
argv: string[] | null;
reason?: string;