fix(update): verify daemon restart port

This commit is contained in:
Vincent Koc
2026-05-01 04:54:19 -07:00
parent f6a1d70080
commit debb8ac76c
3 changed files with 42 additions and 5 deletions

View File

@@ -38,6 +38,7 @@ Docs: https://docs.openclaw.ai
- Auto-reply/docking: require `/dock-*` route switches to start from direct chats, so group or channel participants cannot reroute a shared session's future replies into a linked DM. Thanks @vincentkoc.
- Discord: keep text-DM main-session route updates pinned to the configured DM owner, matching component interactions so another direct-message sender cannot redirect future main-session replies. Thanks @vincentkoc.
- Mattermost/Matrix: keep direct-message main-session route updates pinned to the configured DM owner so paired or temporarily allowed senders cannot redirect future shared-session replies. Thanks @vincentkoc.
- CLI/update: verify managed gateway restarts against the installed service port instead of the caller shell port, so package updates do not report a healthy daemon as failed when profiles use different gateway ports. Thanks @vincentkoc.
- Gateway/agent: reject strict `openclaw agent --deliver` requests with missing delivery targets before starting the agent run, so users do not wait for a completed turn that cannot send anywhere. Thanks @vincentkoc.
- Setup/import: honor non-interactive `--import-from` onboarding flags by running the migration import path instead of silently completing normal setup without importing anything. Thanks @vincentkoc.
- Discord/voice: run voice-channel turns under a voice-output policy that hides the agent `tts` tool and asks for spoken reply text, so `/vc join` sessions synthesize and play agent replies instead of ending with `NO_REPLY`. Fixes #61536. Thanks @aounakram.

View File

@@ -6,6 +6,7 @@ import {
} from "../../daemon/gateway-entrypoint.js";
import {
shouldPrepareUpdatedInstallRestart,
resolveUpdatedGatewayRestartPort,
shouldUseLegacyProcessRestartAfterUpdate,
} from "./update-command.js";
@@ -83,6 +84,28 @@ describe("shouldPrepareUpdatedInstallRestart", () => {
});
});
describe("resolveUpdatedGatewayRestartPort", () => {
it("uses the managed service port ahead of the caller environment", () => {
expect(
resolveUpdatedGatewayRestartPort({
config: { gateway: { port: 19000 } } as never,
processEnv: { OPENCLAW_GATEWAY_PORT: "19001" },
serviceEnv: { OPENCLAW_GATEWAY_PORT: "19002" },
}),
).toBe(19002);
});
it("falls back to the post-update config when no service port is available", () => {
expect(
resolveUpdatedGatewayRestartPort({
config: { gateway: { port: 19000 } } as never,
processEnv: {},
serviceEnv: {},
}),
).toBe(19000);
});
});
describe("shouldUseLegacyProcessRestartAfterUpdate", () => {
it("never restarts package updates through the pre-update process", () => {
expect(shouldUseLegacyProcessRestartAfterUpdate({ updateMode: "npm" })).toBe(false);

View File

@@ -320,6 +320,14 @@ function resolveUpdatedInstallCommandEnv(
return disableUpdatedPackageCompileCacheEnv(resolveServiceRefreshEnv(env, invocationCwd));
}
export function resolveUpdatedGatewayRestartPort(params: {
config?: OpenClawConfig;
processEnv?: NodeJS.ProcessEnv;
serviceEnv?: NodeJS.ProcessEnv;
}): number {
return resolveGatewayPort(params.config, params.serviceEnv ?? params.processEnv ?? process.env);
}
type UpdateDryRunPreview = {
dryRun: true;
root: string;
@@ -944,7 +952,7 @@ async function maybeRestartService(params: {
const diagnosticLines = [
"Gateway did not become healthy after restart.",
...renderRestartDiagnostics(health),
`Restart log: ${resolveGatewayRestartLogPath(process.env)}`,
`Restart log: ${resolveGatewayRestartLogPath(params.serviceEnv ?? process.env)}`,
`Run \`${replaceCliName(formatCliCommand("openclaw gateway status --deep"), CLI_NAME)}\` for details.`,
];
if (params.opts.json) {
@@ -1771,10 +1779,10 @@ export async function updateCommand(opts: UpdateCommandOptions): Promise<void> {
let restartScriptPath: string | null = null;
let refreshGatewayServiceEnv = false;
let gatewayServiceEnv: NodeJS.ProcessEnv | undefined;
const gatewayPort = resolveGatewayPort(
postUpdateConfigSnapshot.valid ? postUpdateConfigSnapshot.config : undefined,
process.env,
);
let gatewayPort = resolveUpdatedGatewayRestartPort({
config: postUpdateConfigSnapshot.valid ? postUpdateConfigSnapshot.config : undefined,
processEnv: process.env,
});
if (shouldRestart) {
try {
const serviceState = await readGatewayServiceState(resolveGatewayService(), {
@@ -1788,6 +1796,11 @@ export async function updateCommand(opts: UpdateCommandOptions): Promise<void> {
})
) {
gatewayServiceEnv = serviceState.env;
gatewayPort = resolveUpdatedGatewayRestartPort({
config: postUpdateConfigSnapshot.valid ? postUpdateConfigSnapshot.config : undefined,
processEnv: process.env,
serviceEnv: gatewayServiceEnv,
});
restartScriptPath = await prepareRestartScript(serviceState.env, gatewayPort);
refreshGatewayServiceEnv = true;
}