mirror of
https://github.com/openclaw/openclaw.git
synced 2026-05-28 02:33:08 +00:00
fix(update): suppress internal handoff version warnings
This commit is contained in:
@@ -104,6 +104,7 @@ Docs: https://docs.openclaw.ai
|
||||
### Fixes
|
||||
|
||||
- Gateway/update: avoid fetching unrelated tags during dev-channel git updates so moved release tags do not block branch-based updates. (#84737) Thanks @rubencu.
|
||||
- CLI/update: suppress the expected future-config warning while an old update parent hands off to the freshly installed post-core process.
|
||||
- MiniMax: store OAuth token expiry as an absolute millisecond timestamp so OAuth profiles no longer appear expired on every request. (#83480) Thanks @NianJiuZst.
|
||||
- Agents/Anthropic: strip missing or blank thinking signatures for signed-thinking providers even when recovery supplies a narrow replay policy without signature preservation. Fixes #84430. (#84448) Thanks @NianJiuZst.
|
||||
- Agents/channels: send a visible notice when an aborted main session cannot be resumed after restart, including Telegram group targets. (#85805) Thanks @pfrederiksen.
|
||||
|
||||
@@ -896,6 +896,10 @@ describe("update-cli", () => {
|
||||
expect(call?.[2]?.env?.OPENCLAW_UPDATE_POST_CORE).toBe("1");
|
||||
expect(call?.[2]?.env?.OPENCLAW_UPDATE_POST_CORE_CHANNEL).toBe("dev");
|
||||
expect(call?.[2]?.env?.OPENCLAW_COMPATIBILITY_HOST_VERSION).toBe("1.0.0");
|
||||
expect(vi.mocked(readConfigFileSnapshot).mock.calls[1]?.[0]).toEqual({
|
||||
skipPluginValidation: true,
|
||||
suppressFutureVersionWarning: true,
|
||||
});
|
||||
expect(updateNpmInstalledPlugins).not.toHaveBeenCalled();
|
||||
expect(runDaemonInstall).not.toHaveBeenCalled();
|
||||
expect(runDaemonRestart).not.toHaveBeenCalled();
|
||||
@@ -1179,7 +1183,11 @@ describe("update-cli", () => {
|
||||
expect(
|
||||
vi
|
||||
.mocked(readConfigFileSnapshot)
|
||||
.mock.calls.some(([options]) => options?.skipPluginValidation === true),
|
||||
.mock.calls.some(
|
||||
([options]) =>
|
||||
options?.skipPluginValidation === true &&
|
||||
options.suppressFutureVersionWarning === true,
|
||||
),
|
||||
).toBe(true);
|
||||
expect(defaultRuntime.exit).toHaveBeenCalledWith(0);
|
||||
expect(syncPluginsForUpdateChannel).toHaveBeenCalledTimes(1);
|
||||
|
||||
@@ -2950,7 +2950,10 @@ export async function updateCommand(opts: UpdateCommandOptions): Promise<void> {
|
||||
|
||||
process.env.OPENCLAW_COMPATIBILITY_HOST_VERSION = (await readPackageVersion(root)) ?? VERSION;
|
||||
|
||||
let postCoreConfigSnapshot = await readConfigFileSnapshot({ skipPluginValidation: true });
|
||||
let postCoreConfigSnapshot = await readConfigFileSnapshot({
|
||||
skipPluginValidation: true,
|
||||
suppressFutureVersionWarning: true,
|
||||
});
|
||||
const preUpdateSourceConfig = await readPostCorePreUpdateSourceConfig({
|
||||
sourceConfigPath: process.env[POST_CORE_UPDATE_SOURCE_CONFIG_PATH_ENV],
|
||||
currentSnapshot: postCoreConfigSnapshot,
|
||||
@@ -3416,7 +3419,10 @@ export async function updateCommand(opts: UpdateCommandOptions): Promise<void> {
|
||||
|
||||
let postUpdateConfigSnapshot =
|
||||
result.status === "ok" && !opts.dryRun
|
||||
? await readConfigFileSnapshot({ skipPluginValidation: true })
|
||||
? await readConfigFileSnapshot({
|
||||
skipPluginValidation: true,
|
||||
suppressFutureVersionWarning: shouldResumePostCoreInFreshProcess,
|
||||
})
|
||||
: configSnapshot;
|
||||
if (!shouldResumePostCoreInFreshProcess) {
|
||||
postUpdateConfigSnapshot = await persistRequestedUpdateChannel({
|
||||
|
||||
@@ -150,6 +150,38 @@ describe("config io paths", () => {
|
||||
});
|
||||
});
|
||||
|
||||
it("does not warn about newer config during internal update handoff reads", async () => {
|
||||
await withTempHome(async (home) => {
|
||||
const configPath = path.join(home, ".openclaw", "openclaw.json");
|
||||
await fs.mkdir(path.dirname(configPath), { recursive: true });
|
||||
await fs.writeFile(
|
||||
configPath,
|
||||
JSON.stringify(
|
||||
{
|
||||
meta: { lastTouchedVersion: "9999.1.1" },
|
||||
gateway: { mode: "local" },
|
||||
},
|
||||
null,
|
||||
2,
|
||||
),
|
||||
);
|
||||
const logger = {
|
||||
error: vi.fn(),
|
||||
warn: vi.fn(),
|
||||
};
|
||||
|
||||
const io = createConfigIO({
|
||||
configPath,
|
||||
env: { OPENCLAW_UPDATE_POST_CORE: "1" } as NodeJS.ProcessEnv,
|
||||
homedir: () => home,
|
||||
logger,
|
||||
});
|
||||
io.loadConfig();
|
||||
|
||||
expect(logger.warn).not.toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
|
||||
it("normalizes safe-bin config entries at config load time", () => {
|
||||
const cfg = {
|
||||
tools: {
|
||||
|
||||
@@ -7,6 +7,7 @@ import { resolveAgentWorkspaceDir, resolveDefaultAgentId } from "../agents/agent
|
||||
import { ensureOwnerDisplaySecret } from "../agents/owner-display.js";
|
||||
import { isVerbose } from "../global-state.js";
|
||||
import { loadDotEnv } from "../infra/dotenv.js";
|
||||
import { isTruthyEnvValue } from "../infra/env.js";
|
||||
import { formatErrorMessage } from "../infra/errors.js";
|
||||
import { resolveRequiredHomeDir } from "../infra/home-dir.js";
|
||||
import { replaceFileAtomic, replaceFileAtomicSync } from "../infra/replace-file.js";
|
||||
@@ -956,6 +957,7 @@ export type ConfigSnapshotReadOptions = {
|
||||
observe?: boolean;
|
||||
skipPluginValidation?: boolean;
|
||||
preservedLegacyRootKeys?: readonly string[];
|
||||
suppressFutureVersionWarning?: boolean;
|
||||
};
|
||||
|
||||
function warnOnConfigMiskeys(raw: unknown, logger: Pick<typeof console, "warn">): void {
|
||||
@@ -997,6 +999,13 @@ function warnIfConfigFromFuture(cfg: OpenClawConfig, logger: Pick<typeof console
|
||||
}
|
||||
}
|
||||
|
||||
function shouldSuppressFutureVersionWarningForEnv(env: NodeJS.ProcessEnv): boolean {
|
||||
return (
|
||||
isTruthyEnvValue(env.OPENCLAW_UPDATE_IN_PROGRESS) ||
|
||||
isTruthyEnvValue(env.OPENCLAW_UPDATE_POST_CORE)
|
||||
);
|
||||
}
|
||||
|
||||
function resolveConfigPathForDeps(deps: Required<ConfigIoDeps>): string {
|
||||
if (deps.configPath) {
|
||||
return deps.configPath;
|
||||
@@ -1005,16 +1014,17 @@ function resolveConfigPathForDeps(deps: Required<ConfigIoDeps>): string {
|
||||
}
|
||||
|
||||
function normalizeDeps(overrides: ConfigIoDeps = {}): Required<ConfigIoDeps> {
|
||||
const env = overrides.env ?? process.env;
|
||||
return {
|
||||
fs: overrides.fs ?? fs,
|
||||
json5: overrides.json5 ?? JSON5,
|
||||
env: overrides.env ?? process.env,
|
||||
homedir:
|
||||
overrides.homedir ?? (() => resolveRequiredHomeDir(overrides.env ?? process.env, os.homedir)),
|
||||
env,
|
||||
homedir: overrides.homedir ?? (() => resolveRequiredHomeDir(env, os.homedir)),
|
||||
configPath: overrides.configPath ?? "",
|
||||
logger: overrides.logger ?? console,
|
||||
measure: overrides.measure ?? (async (_name, run) => await run()),
|
||||
suppressFutureVersionWarning: overrides.suppressFutureVersionWarning ?? false,
|
||||
suppressFutureVersionWarning:
|
||||
overrides.suppressFutureVersionWarning ?? shouldSuppressFutureVersionWarningForEnv(env),
|
||||
observe: overrides.observe ?? true,
|
||||
};
|
||||
}
|
||||
@@ -2544,6 +2554,7 @@ export async function readConfigFileSnapshot(
|
||||
...(options.measure ? { measure: options.measure } : {}),
|
||||
...(options.observe === false ? { observe: false } : {}),
|
||||
...(options.skipPluginValidation ? { pluginValidation: "skip" } : {}),
|
||||
...(options.suppressFutureVersionWarning ? { suppressFutureVersionWarning: true } : {}),
|
||||
...(options.preservedLegacyRootKeys
|
||||
? { preservedLegacyRootKeys: options.preservedLegacyRootKeys }
|
||||
: {}),
|
||||
|
||||
Reference in New Issue
Block a user