mirror of
https://github.com/openclaw/openclaw.git
synced 2026-04-09 16:21:15 +00:00
fix: stabilize rebased test surfaces
This commit is contained in:
committed by
Peter Steinberger
parent
d75fa152b9
commit
1877a2ea26
@@ -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";
|
||||
|
||||
|
||||
@@ -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>>;
|
||||
|
||||
@@ -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,
|
||||
);
|
||||
});
|
||||
Reference in New Issue
Block a user