

























@@ -3,19 +3,24 @@ import { buildGatewayInstallPlan } from "../../commands/daemon-install-helpers.j
33import {
44DEFAULT_GATEWAY_DAEMON_RUNTIME,
55isGatewayDaemonRuntime,
6+type GatewayDaemonRuntime,
67} from "../../commands/daemon-runtime.js";
78import { resolveGatewayInstallToken } from "../../commands/gateway-install-token.js";
89import { resolveFutureConfigActionBlock } from "../../config/future-version-guard.js";
910import { readConfigFileSnapshotForWrite } from "../../config/io.js";
1011import { resolveGatewayPort } from "../../config/paths.js";
12+import type { OpenClawConfig } from "../../config/types.js";
13+import { readEmbeddedGatewayToken } from "../../daemon/service-audit.js";
1114import { resolveGatewayService } from "../../daemon/service.js";
15+import type { GatewayServiceCommandConfig } from "../../daemon/service.js";
1216import { isNonFatalSystemdInstallProbeError } from "../../daemon/systemd.js";
1317import {
1418isDangerousHostEnvOverrideVarName,
1519isDangerousHostEnvVarName,
1620normalizeEnvVarKey,
1721} from "../../infra/host-env-security.js";
1822import { defaultRuntime } from "../../runtime.js";
23+import { normalizeOptionalString } from "../../shared/string-coerce.js";
1924import { formatCliCommand } from "../command-format.js";
2025import { buildDaemonServiceSnapshot, installDaemonServiceAndEmit } from "./response.js";
2126import {
@@ -98,6 +103,7 @@ export async function runDaemonInstall(opts: DaemonInstallOptions) {
98103const service = resolveGatewayService();
99104let loaded = false;
100105let existingServiceEnv: Record<string, string> | undefined;
106+let existingServiceCommand: GatewayServiceCommandConfig | null = null;
101107try {
102108loaded = await service.isLoaded({ env: process.env });
103109} catch (err) {
@@ -109,20 +115,29 @@ export async function runDaemonInstall(opts: DaemonInstallOptions) {
109115}
110116}
111117if (loaded) {
112-existingServiceEnv = (await service.readCommand(process.env).catch(() => null))?.environment;
118+existingServiceCommand = await service.readCommand(process.env).catch(() => null);
119+existingServiceEnv = existingServiceCommand?.environment;
113120}
114121const installEnv = mergeInstallInvocationEnv({
115122env: process.env,
116123 existingServiceEnv,
117124});
118125if (loaded) {
119126if (!opts.force) {
120-if (await gatewayServiceNeedsAutoNodeExtraCaCertsRefresh({ service, env: process.env })) {
121-const message = "Gateway service is missing the nvm TLS CA bundle; refreshing the install.";
127+const autoRefreshMessage = await getGatewayServiceAutoRefreshMessage({
128+currentCommand: existingServiceCommand,
129+env: process.env,
130+ installEnv,
131+ port,
132+runtime: runtimeRaw,
133+existingEnvironment: existingServiceEnv,
134+config: cfg,
135+});
136+if (autoRefreshMessage) {
122137if (json) {
123-warnings.push(message);
138+warnings.push(autoRefreshMessage);
124139} else {
125-defaultRuntime.log(message);
140+defaultRuntime.log(autoRefreshMessage);
126141}
127142} else {
128143emit({
@@ -196,18 +211,40 @@ export async function runDaemonInstall(opts: DaemonInstallOptions) {
196211});
197212}
198213199-async function gatewayServiceNeedsAutoNodeExtraCaCertsRefresh(params: {
200-service: ReturnType<typeof resolveGatewayService>;
214+async function getGatewayServiceAutoRefreshMessage(params: {
215+currentCommand: GatewayServiceCommandConfig | null;
201216env: Record<string, string | undefined>;
202-}): Promise<boolean> {
217+installEnv: NodeJS.ProcessEnv;
218+port: number;
219+runtime: GatewayDaemonRuntime;
220+existingEnvironment?: Record<string, string | undefined>;
221+config: OpenClawConfig;
222+}): Promise<string | undefined> {
203223try {
204-const currentCommand = await params.service.readCommand(params.env);
224+const currentCommand = params.currentCommand;
205225if (!currentCommand) {
206-return false;
226+return undefined;
227+}
228+const currentEmbeddedToken = readEmbeddedGatewayToken(currentCommand);
229+if (currentEmbeddedToken) {
230+const plannedInstall = await buildGatewayInstallPlan({
231+env: params.installEnv,
232+port: params.port,
233+runtime: params.runtime,
234+existingEnvironment: params.existingEnvironment,
235+warn: () => undefined,
236+config: params.config,
237+});
238+const plannedEmbeddedToken = normalizeOptionalString(
239+plannedInstall.environment.OPENCLAW_GATEWAY_TOKEN,
240+);
241+if (currentEmbeddedToken !== plannedEmbeddedToken) {
242+return "Gateway service OPENCLAW_GATEWAY_TOKEN differs from the current install plan; refreshing the install.";
243+}
207244}
208245const currentExecPath = currentCommand.programArguments[0]?.trim();
209246if (!currentExecPath) {
210-return false;
247+return undefined;
211248}
212249const currentEnvironment = currentCommand.environment ?? {};
213250const currentNodeExtraCaCerts = currentEnvironment.NODE_EXTRA_CA_CERTS?.trim();
@@ -221,10 +258,13 @@ async function gatewayServiceNeedsAutoNodeExtraCaCertsRefresh(params: {
221258includeDarwinDefaults: false,
222259}).NODE_EXTRA_CA_CERTS;
223260if (!expectedNodeExtraCaCerts) {
224-return false;
261+return undefined;
262+}
263+if (currentNodeExtraCaCerts !== expectedNodeExtraCaCerts) {
264+return "Gateway service is missing the nvm TLS CA bundle; refreshing the install.";
225265}
226-return currentNodeExtraCaCerts !== expectedNodeExtraCaCerts;
266+return undefined;
227267} catch {
228-return false;
268+return undefined;
229269}
230270}
此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。