diff --git a/CHANGELOG.md b/CHANGELOG.md index 76971c58a99..05b29a0f909 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -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. diff --git a/src/cli/update-cli/update-command.test.ts b/src/cli/update-cli/update-command.test.ts index f642463f599..3a087c58b9c 100644 --- a/src/cli/update-cli/update-command.test.ts +++ b/src/cli/update-cli/update-command.test.ts @@ -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); diff --git a/src/cli/update-cli/update-command.ts b/src/cli/update-cli/update-command.ts index 7bdfb47d03e..9ff87552bc3 100644 --- a/src/cli/update-cli/update-command.ts +++ b/src/cli/update-cli/update-command.ts @@ -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 { 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 { }) ) { gatewayServiceEnv = serviceState.env; + gatewayPort = resolveUpdatedGatewayRestartPort({ + config: postUpdateConfigSnapshot.valid ? postUpdateConfigSnapshot.config : undefined, + processEnv: process.env, + serviceEnv: gatewayServiceEnv, + }); restartScriptPath = await prepareRestartScript(serviceState.env, gatewayPort); refreshGatewayServiceEnv = true; }