File size: 3,575 Bytes
fc93158 | 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 | import { buildGatewayInstallPlan } from "../../commands/daemon-install-helpers.js";
import {
DEFAULT_GATEWAY_DAEMON_RUNTIME,
isGatewayDaemonRuntime,
} from "../../commands/daemon-runtime.js";
import { resolveGatewayInstallToken } from "../../commands/gateway-install-token.js";
import { readBestEffortConfig, resolveGatewayPort } from "../../config/config.js";
import { resolveGatewayService } from "../../daemon/service.js";
import { isNonFatalSystemdInstallProbeError } from "../../daemon/systemd.js";
import { defaultRuntime } from "../../runtime.js";
import { formatCliCommand } from "../command-format.js";
import { buildDaemonServiceSnapshot, installDaemonServiceAndEmit } from "./response.js";
import {
createDaemonInstallActionContext,
failIfNixDaemonInstallMode,
parsePort,
} from "./shared.js";
import type { DaemonInstallOptions } from "./types.js";
export async function runDaemonInstall(opts: DaemonInstallOptions) {
const { json, stdout, warnings, emit, fail } = createDaemonInstallActionContext(opts.json);
if (failIfNixDaemonInstallMode(fail)) {
return;
}
const cfg = await readBestEffortConfig();
const portOverride = parsePort(opts.port);
if (opts.port !== undefined && portOverride === null) {
fail("Invalid port");
return;
}
const port = portOverride ?? resolveGatewayPort(cfg);
if (!Number.isFinite(port) || port <= 0) {
fail("Invalid port");
return;
}
const runtimeRaw = opts.runtime ? String(opts.runtime) : DEFAULT_GATEWAY_DAEMON_RUNTIME;
if (!isGatewayDaemonRuntime(runtimeRaw)) {
fail('Invalid --runtime (use "node" or "bun")');
return;
}
const service = resolveGatewayService();
let loaded = false;
try {
loaded = await service.isLoaded({ env: process.env });
} catch (err) {
if (isNonFatalSystemdInstallProbeError(err)) {
loaded = false;
} else {
fail(`Gateway service check failed: ${String(err)}`);
return;
}
}
if (loaded) {
if (!opts.force) {
emit({
ok: true,
result: "already-installed",
message: `Gateway service already ${service.loadedText}.`,
service: buildDaemonServiceSnapshot(service, loaded),
});
if (!json) {
defaultRuntime.log(`Gateway service already ${service.loadedText}.`);
defaultRuntime.log(
`Reinstall with: ${formatCliCommand("openclaw gateway install --force")}`,
);
}
return;
}
}
const tokenResolution = await resolveGatewayInstallToken({
config: cfg,
env: process.env,
explicitToken: opts.token,
autoGenerateWhenMissing: true,
persistGeneratedToken: true,
});
if (tokenResolution.unavailableReason) {
fail(`Gateway install blocked: ${tokenResolution.unavailableReason}`);
return;
}
for (const warning of tokenResolution.warnings) {
if (json) {
warnings.push(warning);
} else {
defaultRuntime.log(warning);
}
}
const { programArguments, workingDirectory, environment } = await buildGatewayInstallPlan({
env: process.env,
port,
runtime: runtimeRaw,
warn: (message) => {
if (json) {
warnings.push(message);
} else {
defaultRuntime.log(message);
}
},
config: cfg,
});
await installDaemonServiceAndEmit({
serviceNoun: "Gateway",
service,
warnings,
emit,
fail,
install: async () => {
await service.install({
env: process.env,
stdout,
programArguments,
workingDirectory,
environment,
});
},
});
}
|