diff --git a/src/system-agent/agent-turn.test.ts b/src/system-agent/agent-turn.test.ts index ba7dead65223..0b54db6c445d 100644 --- a/src/system-agent/agent-turn.test.ts +++ b/src/system-agent/agent-turn.test.ts @@ -1,7 +1,7 @@ import fs from "node:fs"; import os from "node:os"; import path from "node:path"; -import { afterEach, beforeEach, describe, expect, it, vi } from "vitest"; +import { afterAll, afterEach, beforeAll, beforeEach, describe, expect, it, vi } from "vitest"; import { listAgentEntries } from "../agents/agent-scope-config.js"; import { testing as cliBackendsTesting } from "../agents/cli-backends.test-support.js"; import { fingerprintResolvedProviderAuth } from "../agents/execution-auth-binding.js"; @@ -14,7 +14,11 @@ import { import { runSystemAgentTurnWithDeps, type SystemAgentTurnDeps } from "./agent-turn.test-support.js"; import { SystemAgentInferenceUnavailableError } from "./inference-error.js"; import { resolveSystemAgentConfiguredRouteFromConfig } from "./inference-route.js"; -import { createSystemAgentVerifiedInferenceTestFixture } from "./system-agent.test-helpers.js"; +import { + createSystemAgentVerifiedInferenceTestFixture, + installSystemAgentPluginMetadataTestSnapshot, + type SystemAgentPluginMetadataTestSnapshot, +} from "./system-agent.test-helpers.js"; import { createSystemAgentVerifiedInferenceBinding } from "./verified-inference.js"; vi.mock("../plugins/providers.js", async (importOriginal) => ({ @@ -58,11 +62,13 @@ vi.mock("../config/config.js", async (importOriginal) => ({ })); const tempDirs: string[] = []; +let pluginMetadataSnapshot: SystemAgentPluginMetadataTestSnapshot | undefined; function useTempStateDir(): string { const stateDir = fs.mkdtempSync(path.join(os.tmpdir(), "openclaw-turn-")); tempDirs.push(stateDir); vi.stubEnv("OPENCLAW_STATE_DIR", stateDir); + pluginMetadataSnapshot?.rebindForCurrentEnv(); return stateDir; } @@ -94,6 +100,14 @@ async function createVerifiedSession(config: OpenClawConfig) { }; } +beforeAll(() => { + pluginMetadataSnapshot = installSystemAgentPluginMetadataTestSnapshot(); +}); + +afterAll(() => { + pluginMetadataSnapshot?.restore(); +}); + beforeEach(() => { // Core tests install a contract-level selectable backend instead of loading // a plugin's generated setup artifact from dist/. @@ -126,6 +140,7 @@ beforeEach(() => { afterEach(() => { cliBackendsTesting.resetDepsForTest(); vi.unstubAllEnvs(); + pluginMetadataSnapshot?.rebindForCurrentEnv(); vi.clearAllMocks(); for (const dir of tempDirs.splice(0)) { fs.rmSync(dir, { recursive: true, force: true }); diff --git a/src/system-agent/chat-engine.test.ts b/src/system-agent/chat-engine.test.ts index e86da12b4945..5c96b4a2e91b 100644 --- a/src/system-agent/chat-engine.test.ts +++ b/src/system-agent/chat-engine.test.ts @@ -3,7 +3,7 @@ import fs from "node:fs"; import os from "node:os"; import path from "node:path"; import { expectDefined } from "@openclaw/normalization-core"; -import { afterEach, beforeAll, describe, expect, it, vi } from "vitest"; +import { afterAll, afterEach, beforeAll, describe, expect, it, vi } from "vitest"; import { fingerprintAuthProfileCredential, fingerprintOpaqueRuntimeOwner, @@ -25,7 +25,11 @@ import { type SystemAgentConfiguredRoute, } from "./inference-route.js"; import { verifyConfigAfterSystemAgentWrite } from "./post-write-verification.js"; -import { createSystemAgentVerifiedInferenceTestFixture } from "./system-agent.test-helpers.js"; +import { + createSystemAgentVerifiedInferenceTestFixture, + installSystemAgentPluginMetadataTestSnapshot, + type SystemAgentPluginMetadataTestSnapshot, +} from "./system-agent.test-helpers.js"; import { createSystemAgentVerifiedInferenceBinding, type SystemAgentVerifiedInferenceBinding, @@ -117,11 +121,13 @@ const sharedVerifiedInferenceConfig = { let sharedVerifiedInference: SystemAgentVerifiedInferenceBinding | undefined; let sharedVerifiedInferenceDeps: SystemAgentVerifiedInferenceDeps | undefined; +let pluginMetadataSnapshot: SystemAgentPluginMetadataTestSnapshot | undefined; function useTempStateDir(): string { const dir = fs.mkdtempSync(path.join(os.tmpdir(), "openclaw-engine-")); tempDirs.push(dir); vi.stubEnv("OPENCLAW_STATE_DIR", dir); + pluginMetadataSnapshot?.rebindForCurrentEnv(); return dir; } @@ -298,6 +304,9 @@ async function advanceGatewayWizardToToken(engine: SystemAgentChatEngine) { } beforeAll(async () => { + pluginMetadataSnapshot = installSystemAgentPluginMetadataTestSnapshot( + sharedVerifiedInferenceConfig, + ); const fixture = await createSystemAgentVerifiedInferenceTestFixture( sharedVerifiedInferenceConfig, ); @@ -308,8 +317,13 @@ beforeAll(async () => { ); }); +afterAll(() => { + pluginMetadataSnapshot?.restore(); +}); + afterEach(() => { vi.unstubAllEnvs(); + pluginMetadataSnapshot?.rebindForCurrentEnv(); vi.clearAllMocks(); mocks.readConfigFileSnapshot.mockResolvedValue( configSnapshot(structuredClone(sharedVerifiedInferenceConfig)) as never, diff --git a/src/system-agent/setup-inference.test.ts b/src/system-agent/setup-inference.test.ts index 4d6e492dbefb..0d0f20be154e 100644 --- a/src/system-agent/setup-inference.test.ts +++ b/src/system-agent/setup-inference.test.ts @@ -52,6 +52,10 @@ import { verifySetupInference as verifySetupInferenceImpl, verifySetupInferenceConfig as verifySetupInferenceConfigImpl, } from "./setup-inference.js"; +import { + installSystemAgentPluginMetadataTestSnapshot, + type SystemAgentPluginMetadataTestSnapshot, +} from "./system-agent.test-helpers.js"; import { createSystemAgentVerifiedInferenceBinding, type SystemAgentVerifiedInferenceBinding, @@ -126,13 +130,25 @@ const testCodexRuntimeArtifact = { const suiteTempRootTracker = createSuiteTempRootTracker({ prefix: "setup-inference-test-", }); +let pluginMetadataSnapshot: SystemAgentPluginMetadataTestSnapshot | undefined; beforeAll(async () => { + pluginMetadataSnapshot = installSystemAgentPluginMetadataTestSnapshot( + materializedMainRuntimeConfig, + ); await suiteTempRootTracker.setup(); }); afterAll(async () => { - await suiteTempRootTracker.cleanup(); + try { + await suiteTempRootTracker.cleanup(); + } finally { + pluginMetadataSnapshot?.restore(); + } +}); + +beforeEach(() => { + pluginMetadataSnapshot?.rebindForCurrentEnv(); }); async function makeTempDir(): Promise { diff --git a/src/system-agent/system-agent.test-helpers.ts b/src/system-agent/system-agent.test-helpers.ts index f6aa2824391a..21a440eb4e33 100644 --- a/src/system-agent/system-agent.test-helpers.ts +++ b/src/system-agent/system-agent.test-helpers.ts @@ -11,6 +11,12 @@ import { import { resolveCliRuntimeExecutionProvider } from "../agents/model-runtime-aliases.js"; import { resolveSimpleCompletionSelectionForAgent } from "../agents/simple-completion-runtime.js"; import type { OpenClawConfig } from "../config/types.openclaw.js"; +import { + captureCurrentPluginMetadataSnapshotState, + restoreCurrentPluginMetadataSnapshotState, + setCurrentPluginMetadataSnapshot, +} from "../plugins/current-plugin-metadata-snapshot.js"; +import { resolvePluginMetadataSnapshot } from "../plugins/plugin-metadata-snapshot.js"; import type { RuntimeEnv } from "../runtime.js"; import { listSystemAgentAuditEntriesForTests } from "./audit.test-support.js"; import { resolveSystemAgentConfiguredRouteFromConfig } from "./inference-route.js"; @@ -25,6 +31,28 @@ type SystemAgentVerifiedInferenceTestFixture = { deps: SystemAgentVerifiedInferenceDeps; }; +export type SystemAgentPluginMetadataTestSnapshot = { + /** Rebind after a test redirects to another empty state root with the same plugin inventory. */ + rebindForCurrentEnv: () => void; + restore: () => void; +}; + +/** Install the process-stable plugin metadata snapshot that the real Gateway owns. */ +export function installSystemAgentPluginMetadataTestSnapshot( + config: OpenClawConfig = {}, +): SystemAgentPluginMetadataTestSnapshot { + const previous = captureCurrentPluginMetadataSnapshotState(); + const snapshot = resolvePluginMetadataSnapshot({ config, env: process.env }); + const rebindForCurrentEnv = () => { + setCurrentPluginMetadataSnapshot(snapshot, { config, env: process.env }); + }; + rebindForCurrentEnv(); + return { + rebindForCurrentEnv, + restore: () => restoreCurrentPluginMetadataSnapshotState(previous), + }; +} + export function readLastSystemAgentAuditEntry(): unknown { return listSystemAgentAuditEntriesForTests().at(-1)?.value; } diff --git a/src/system-agent/verified-inference.test.ts b/src/system-agent/verified-inference.test.ts index 189aa7aaf6d8..50f9b7223424 100644 --- a/src/system-agent/verified-inference.test.ts +++ b/src/system-agent/verified-inference.test.ts @@ -1,7 +1,7 @@ import fs from "node:fs"; import os from "node:os"; import path from "node:path"; -import { beforeEach, describe, expect, it, vi } from "vitest"; +import { afterAll, beforeAll, beforeEach, describe, expect, it, vi } from "vitest"; import { fingerprintAuthProfileCredential, fingerprintAwsSdkRuntimeOwner, @@ -13,6 +13,10 @@ import type { OpenClawConfig } from "../config/types.openclaw.js"; import type { PluginOrigin } from "../plugins/types.js"; import { resolveSystemAgentConfiguredRouteFromConfig } from "./inference-route.js"; import { resolvePersistentApplyInference } from "./setup-inference.js"; +import { + installSystemAgentPluginMetadataTestSnapshot, + type SystemAgentPluginMetadataTestSnapshot, +} from "./system-agent.test-helpers.js"; import { createSystemAgentVerifiedInferenceBinding, resolveSystemAgentVerifiedInferenceRoute, @@ -76,6 +80,15 @@ const profile = { }; const runtime = { log: () => {}, error: () => {}, exit: () => {} } as never; +let pluginMetadataSnapshot: SystemAgentPluginMetadataTestSnapshot | undefined; + +beforeAll(() => { + pluginMetadataSnapshot = installSystemAgentPluginMetadataTestSnapshot(config()); +}); + +afterAll(() => { + pluginMetadataSnapshot?.restore(); +}); type TestPluginRecord = { pluginId: string; @@ -111,6 +124,7 @@ function pluginRecord( } beforeEach(() => { + pluginMetadataSnapshot?.rebindForCurrentEnv(); pluginRegistryState.providerOwnerIds = ["provider-owner"]; pluginRegistryState.records = [pluginRecord("provider-owner"), pluginRecord("codex")]; harnessRuntimeArtifactState.id = "codex-app-server";