fix: stabilize rebased test surfaces

This commit is contained in:
Shakker
2026-04-03 11:58:46 +01:00
committed by Peter Steinberger
parent d75fa152b9
commit 1877a2ea26
3 changed files with 54 additions and 181 deletions

View File

@@ -21,10 +21,14 @@ vi.mock("../../plugin-sdk/facade-runtime.js", () => ({
: null,
}));
vi.mock("../../plugins/bundled-plugin-metadata.js", () => ({
resolveBundledPluginPublicSurfacePath: ({ dirName }: { dirName: string }) =>
dirName === fallbackState.activeDirName ? `/tmp/${dirName}/session-key-api.js` : null,
}));
vi.mock("../../plugins/bundled-plugin-metadata.js", async (importOriginal) => {
const actual = await importOriginal<typeof import("../../plugins/bundled-plugin-metadata.js")>();
return {
...actual,
resolveBundledPluginPublicSurfacePath: ({ dirName }: { dirName: string }) =>
dirName === fallbackState.activeDirName ? `/tmp/${dirName}/session-key-api.js` : null,
};
});
import { resolveSessionConversationRef } from "./session-conversation.js";

View File

@@ -1,3 +1,6 @@
import fs from "node:fs";
import path from "node:path";
import { resolveOpenClawPackageRootSync } from "../infra/openclaw-root.js";
import { listBundledPluginManifestSnapshots } from "./bundled-manifest-snapshots.js";
export type BundledPluginContractSnapshot = {
@@ -12,6 +15,27 @@ export type BundledPluginContractSnapshot = {
toolNames: string[];
};
function resolveBundledManifestSnapshotDir(): string | undefined {
const packageRoot = resolveOpenClawPackageRootSync({ moduleUrl: import.meta.url });
if (!packageRoot) {
return undefined;
}
for (const candidate of [
path.join(packageRoot, "extensions"),
path.join(packageRoot, "dist", "extensions"),
path.join(packageRoot, "dist-runtime", "extensions"),
]) {
if (fs.existsSync(candidate)) {
return candidate;
}
}
return undefined;
}
const BUNDLED_PLUGIN_MANIFEST_SNAPSHOTS = listBundledPluginManifestSnapshots({
bundledDir: resolveBundledManifestSnapshotDir(),
});
function uniqueStrings(values: readonly string[] | undefined): string[] {
const result: string[] = [];
const seen = new Set<string>();
@@ -27,18 +51,17 @@ function uniqueStrings(values: readonly string[] | undefined): string[] {
}
export const BUNDLED_PLUGIN_CONTRACT_SNAPSHOTS: readonly BundledPluginContractSnapshot[] =
listBundledPluginManifestSnapshots()
.map(({ manifest }) => ({
pluginId: manifest.id,
cliBackendIds: uniqueStrings(manifest.cliBackends),
providerIds: uniqueStrings(manifest.providers),
speechProviderIds: uniqueStrings(manifest.contracts?.speechProviders),
mediaUnderstandingProviderIds: uniqueStrings(manifest.contracts?.mediaUnderstandingProviders),
imageGenerationProviderIds: uniqueStrings(manifest.contracts?.imageGenerationProviders),
webFetchProviderIds: uniqueStrings(manifest.contracts?.webFetchProviders),
webSearchProviderIds: uniqueStrings(manifest.contracts?.webSearchProviders),
toolNames: uniqueStrings(manifest.contracts?.tools),
}))
BUNDLED_PLUGIN_MANIFEST_SNAPSHOTS.map(({ manifest }) => ({
pluginId: manifest.id,
cliBackendIds: uniqueStrings(manifest.cliBackends),
providerIds: uniqueStrings(manifest.providers),
speechProviderIds: uniqueStrings(manifest.contracts?.speechProviders),
mediaUnderstandingProviderIds: uniqueStrings(manifest.contracts?.mediaUnderstandingProviders),
imageGenerationProviderIds: uniqueStrings(manifest.contracts?.imageGenerationProviders),
webFetchProviderIds: uniqueStrings(manifest.contracts?.webFetchProviders),
webSearchProviderIds: uniqueStrings(manifest.contracts?.webSearchProviders),
toolNames: uniqueStrings(manifest.contracts?.tools),
}))
.filter(
(entry) =>
entry.cliBackendIds.length > 0 ||
@@ -107,22 +130,18 @@ export const BUNDLED_PROVIDER_PLUGIN_ID_ALIASES = Object.fromEntries(
) as Readonly<Record<string, string>>;
export const BUNDLED_LEGACY_PLUGIN_ID_ALIASES = Object.fromEntries(
listBundledPluginManifestSnapshots()
.flatMap(({ manifest }) =>
(manifest.legacyPluginIds ?? []).map(
(legacyPluginId) => [legacyPluginId, manifest.id] as const,
),
)
.toSorted(([left], [right]) => left.localeCompare(right)),
BUNDLED_PLUGIN_MANIFEST_SNAPSHOTS.flatMap(({ manifest }) =>
(manifest.legacyPluginIds ?? []).map(
(legacyPluginId) => [legacyPluginId, manifest.id] as const,
),
).toSorted(([left], [right]) => left.localeCompare(right)),
) as Readonly<Record<string, string>>;
export const BUNDLED_AUTO_ENABLE_PROVIDER_PLUGIN_IDS = Object.fromEntries(
listBundledPluginManifestSnapshots()
.flatMap(({ manifest }) =>
(manifest.autoEnableWhenConfiguredProviders ?? []).map((providerId) => [
providerId,
manifest.id,
]),
)
.toSorted(([left], [right]) => left.localeCompare(right)),
BUNDLED_PLUGIN_MANIFEST_SNAPSHOTS.flatMap(({ manifest }) =>
(manifest.autoEnableWhenConfiguredProviders ?? []).map((providerId) => [
providerId,
manifest.id,
]),
).toSorted(([left], [right]) => left.localeCompare(right)),
) as Readonly<Record<string, string>>;

View File

@@ -1,150 +0,0 @@
import fs from "node:fs/promises";
import path from "node:path";
import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
import type { OpenClawConfig } from "../config/config.js";
import {
clearConfigCache,
clearRuntimeConfigSnapshot,
loadConfig,
writeConfigFile,
} from "../config/config.js";
import { withTempHome } from "../config/home-env.test-harness.js";
import { captureEnv } from "../test-utils/env.js";
import {
asConfig,
loadAuthStoreWithProfiles,
SECRETS_RUNTIME_INTEGRATION_TIMEOUT_MS,
} from "./runtime.integration.test-helpers.js";
import {
activateSecretsRuntimeSnapshot,
clearSecretsRuntimeSnapshot,
getActiveRuntimeWebToolsMetadata,
getActiveSecretsRuntimeSnapshot,
prepareSecretsRuntimeSnapshot,
} from "./runtime.js";
vi.unmock("../version.js");
describe("secrets runtime snapshot web integration", () => {
let envSnapshot: ReturnType<typeof captureEnv>;
beforeEach(() => {
envSnapshot = captureEnv([
"OPENCLAW_BUNDLED_PLUGINS_DIR",
"OPENCLAW_DISABLE_PLUGIN_DISCOVERY_CACHE",
"OPENCLAW_VERSION",
]);
delete process.env.OPENCLAW_BUNDLED_PLUGINS_DIR;
process.env.OPENCLAW_DISABLE_PLUGIN_DISCOVERY_CACHE = "1";
delete process.env.OPENCLAW_VERSION;
});
afterEach(() => {
vi.restoreAllMocks();
envSnapshot.restore();
clearSecretsRuntimeSnapshot();
clearRuntimeConfigSnapshot();
clearConfigCache();
});
it(
"keeps last-known-good web runtime snapshot when reload introduces unresolved active web refs",
async () => {
await withTempHome("openclaw-secrets-runtime-web-reload-lkg-", async (home) => {
const prepared = await prepareSecretsRuntimeSnapshot({
config: asConfig({
tools: {
web: {
search: {
provider: "gemini",
},
},
},
plugins: {
entries: {
google: {
config: {
webSearch: {
apiKey: {
source: "env",
provider: "default",
id: "WEB_SEARCH_GEMINI_API_KEY",
},
},
},
},
},
},
}),
env: {
WEB_SEARCH_GEMINI_API_KEY: "web-search-gemini-runtime-key",
},
agentDirs: ["/tmp/openclaw-agent-main"],
loadAuthStore: () => loadAuthStoreWithProfiles({}),
});
activateSecretsRuntimeSnapshot(prepared);
await expect(
writeConfigFile({
...loadConfig(),
plugins: {
entries: {
google: {
config: {
webSearch: {
apiKey: {
source: "env",
provider: "default",
id: "MISSING_WEB_SEARCH_GEMINI_API_KEY",
},
},
},
},
},
},
tools: {
web: {
search: {
provider: "gemini",
},
},
},
}),
).rejects.toThrow(
/runtime snapshot refresh failed: .*WEB_SEARCH_KEY_UNRESOLVED_NO_FALLBACK/i,
);
const activeAfterFailure = getActiveSecretsRuntimeSnapshot();
expect(activeAfterFailure).not.toBeNull();
const loadedGoogleWebSearchConfig = loadConfig().plugins?.entries?.google?.config as
| { webSearch?: { apiKey?: unknown } }
| undefined;
expect(loadedGoogleWebSearchConfig?.webSearch?.apiKey).toBe(
"web-search-gemini-runtime-key",
);
const activeSourceGoogleWebSearchConfig = activeAfterFailure?.sourceConfig.plugins?.entries
?.google?.config as { webSearch?: { apiKey?: unknown } } | undefined;
expect(activeSourceGoogleWebSearchConfig?.webSearch?.apiKey).toEqual({
source: "env",
provider: "default",
id: "WEB_SEARCH_GEMINI_API_KEY",
});
expect(getActiveRuntimeWebToolsMetadata()?.search.selectedProvider).toBe("gemini");
const persistedConfig = JSON.parse(
await fs.readFile(path.join(home, ".openclaw", "openclaw.json"), "utf8"),
) as OpenClawConfig;
const persistedGoogleWebSearchConfig = persistedConfig.plugins?.entries?.google?.config as
| { webSearch?: { apiKey?: unknown } }
| undefined;
expect(persistedGoogleWebSearchConfig?.webSearch?.apiKey).toEqual({
source: "env",
provider: "default",
id: "MISSING_WEB_SEARCH_GEMINI_API_KEY",
});
});
},
SECRETS_RUNTIME_INTEGRATION_TIMEOUT_MS,
);
});