Skip to content

Commit cad2cef

Browse files
committed
fix(update): use service env for doctor
1 parent debb8ac commit cad2cef

3 files changed

Lines changed: 76 additions & 1 deletion

File tree

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ Docs: https://docs.openclaw.ai
3838
- 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.
3939
- 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.
4040
- 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.
41+
- Updates: run package post-install doctor repair with the managed Gateway service profile and state paths when a daemon is installed, so shell/profile mismatches no longer repair the caller state while the restarted Gateway keeps stale config. Thanks @vincentkoc.
4142
- 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.
4243
- 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.
4344
- 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.

src/cli/update-cli/update-command.test.ts

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import {
55
resolveGatewayInstallEntrypoint,
66
} from "../../daemon/gateway-entrypoint.js";
77
import {
8+
resolvePostInstallDoctorEnv,
89
shouldPrepareUpdatedInstallRestart,
910
resolveUpdatedGatewayRestartPort,
1011
shouldUseLegacyProcessRestartAfterUpdate,
@@ -106,6 +107,48 @@ describe("resolveUpdatedGatewayRestartPort", () => {
106107
});
107108
});
108109

110+
describe("resolvePostInstallDoctorEnv", () => {
111+
it("uses the managed service profile paths for post-install doctor", () => {
112+
const env = resolvePostInstallDoctorEnv({
113+
invocationCwd: "/srv/openclaw",
114+
baseEnv: {
115+
PATH: "/bin",
116+
OPENCLAW_STATE_DIR: "/wrong/state",
117+
OPENCLAW_CONFIG_PATH: "/wrong/openclaw.json",
118+
OPENCLAW_PROFILE: "wrong",
119+
},
120+
serviceEnv: {
121+
OPENCLAW_STATE_DIR: "daemon-state",
122+
OPENCLAW_CONFIG_PATH: "daemon-state/openclaw.json",
123+
OPENCLAW_PROFILE: "work",
124+
},
125+
});
126+
127+
expect(env.PATH).toBe("/bin");
128+
expect(env.NODE_DISABLE_COMPILE_CACHE).toBe("1");
129+
expect(env.OPENCLAW_STATE_DIR).toBe(path.join("/srv/openclaw", "daemon-state"));
130+
expect(env.OPENCLAW_CONFIG_PATH).toBe(
131+
path.join("/srv/openclaw", "daemon-state", "openclaw.json"),
132+
);
133+
expect(env.OPENCLAW_PROFILE).toBe("work");
134+
});
135+
136+
it("keeps the caller env when no managed service env is available", () => {
137+
const env = resolvePostInstallDoctorEnv({
138+
baseEnv: {
139+
PATH: "/bin",
140+
OPENCLAW_STATE_DIR: "/caller/state",
141+
OPENCLAW_PROFILE: "caller",
142+
},
143+
});
144+
145+
expect(env.PATH).toBe("/bin");
146+
expect(env.NODE_DISABLE_COMPILE_CACHE).toBe("1");
147+
expect(env.OPENCLAW_STATE_DIR).toBe("/caller/state");
148+
expect(env.OPENCLAW_PROFILE).toBe("caller");
149+
});
150+
});
151+
109152
describe("shouldUseLegacyProcessRestartAfterUpdate", () => {
110153
it("never restarts package updates through the pre-update process", () => {
111154
expect(shouldUseLegacyProcessRestartAfterUpdate({ updateMode: "npm" })).toBe(false);

src/cli/update-cli/update-command.ts

Lines changed: 32 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -103,6 +103,10 @@ const SERVICE_REFRESH_PATH_ENV_KEYS = [
103103
"OPENCLAW_STATE_DIR",
104104
"OPENCLAW_CONFIG_PATH",
105105
] as const;
106+
const POST_INSTALL_DOCTOR_SERVICE_ENV_KEYS = [
107+
...SERVICE_REFRESH_PATH_ENV_KEYS,
108+
"OPENCLAW_PROFILE",
109+
] as const;
106110

107111
const UPDATE_QUIPS = [
108112
"Leveled up! New skills unlocked. You're welcome.",
@@ -320,6 +324,26 @@ function resolveUpdatedInstallCommandEnv(
320324
return disableUpdatedPackageCompileCacheEnv(resolveServiceRefreshEnv(env, invocationCwd));
321325
}
322326

327+
export function resolvePostInstallDoctorEnv(params?: {
328+
baseEnv?: NodeJS.ProcessEnv;
329+
serviceEnv?: NodeJS.ProcessEnv;
330+
invocationCwd?: string;
331+
}): NodeJS.ProcessEnv {
332+
const resolvedEnv = disableUpdatedPackageCompileCacheEnv(params?.baseEnv ?? process.env);
333+
if (!params?.serviceEnv) {
334+
return resolvedEnv;
335+
}
336+
337+
const serviceEnv = resolveServiceRefreshEnv(params.serviceEnv, params.invocationCwd);
338+
for (const key of POST_INSTALL_DOCTOR_SERVICE_ENV_KEYS) {
339+
const value = serviceEnv[key]?.trim();
340+
if (value) {
341+
resolvedEnv[key] = serviceEnv[key];
342+
}
343+
}
344+
return resolvedEnv;
345+
}
346+
323347
export function resolveUpdatedGatewayRestartPort(params: {
324348
config?: OpenClawConfig;
325349
processEnv?: NodeJS.ProcessEnv;
@@ -515,6 +539,8 @@ async function runPackageInstallUpdate(params: {
515539
startedAt: number;
516540
progress: ReturnType<typeof createUpdateProgress>["progress"];
517541
jsonMode: boolean;
542+
managedServiceEnv?: NodeJS.ProcessEnv;
543+
invocationCwd?: string;
518544
}): Promise<UpdateRunResult> {
519545
const manager = await resolveGlobalManager({
520546
root: params.root,
@@ -579,7 +605,10 @@ async function runPackageInstallUpdate(params: {
579605
name: `${CLI_NAME} doctor`,
580606
argv: [resolveNodeRunner(), entryPath, "doctor", "--non-interactive", "--fix"],
581607
env: {
582-
...disableUpdatedPackageCompileCacheEnv(process.env),
608+
...resolvePostInstallDoctorEnv({
609+
serviceEnv: params.managedServiceEnv,
610+
invocationCwd: params.invocationCwd,
611+
}),
583612
OPENCLAW_UPDATE_IN_PROGRESS: "1",
584613
[UPDATE_PARENT_SUPPORTS_DOCTOR_CONFIG_WRITE_ENV]: "1",
585614
},
@@ -1619,6 +1648,8 @@ export async function updateCommand(opts: UpdateCommandOptions): Promise<void> {
16191648
startedAt,
16201649
progress,
16211650
jsonMode: Boolean(opts.json),
1651+
managedServiceEnv: prePackageServiceStop?.serviceEnv,
1652+
invocationCwd,
16221653
})
16231654
: await runGitUpdate({
16241655
root,

0 commit comments

Comments
 (0)