fix: avoid stale provider policy alias cache

This commit is contained in:
Peter Steinberger
2026-05-02 04:24:49 +01:00
parent 1f26a7821f
commit 65404ceabb
2 changed files with 72 additions and 12 deletions

View File

@@ -71,9 +71,13 @@ describe("provider public artifacts", () => {
return { resolveThinkingProfile };
});
vi.doMock("./bundled-dir.js", () => ({
resolveBundledPluginsDir: () => bundledPluginsDir,
}));
vi.doMock("./bundled-dir.js", async (importOriginal) => {
const actual = await importOriginal<typeof import("./bundled-dir.js")>();
return {
...actual,
resolveBundledPluginsDir: () => bundledPluginsDir,
};
});
process.env.OPENCLAW_BUNDLED_PLUGINS_DIR = bundledPluginsDir;
process.env.OPENCLAW_TEST_TRUST_BUNDLED_PLUGINS_DIR = "1";
vi.doMock("./public-surface-loader.js", () => ({
@@ -114,6 +118,71 @@ describe("provider public artifacts", () => {
}
});
it("does not cache manifest-owned provider policy aliases across bundled metadata changes", async () => {
const bundledPluginsDir = fs.mkdtempSync(
path.join(os.tmpdir(), "openclaw-provider-policy-refresh-"),
);
const writePlugin = (pluginId: string, providers: string[], version: number) => {
const pluginDir = path.join(bundledPluginsDir, pluginId);
fs.mkdirSync(pluginDir, { recursive: true });
fs.writeFileSync(
path.join(pluginDir, "openclaw.plugin.json"),
JSON.stringify({
id: pluginId,
name: `${pluginId} ${version}`,
configSchema: { type: "object" },
providers,
}),
);
fs.writeFileSync(
path.join(pluginDir, "index.js"),
"export default { register() {} };\n",
"utf8",
);
};
const loadBundledPluginPublicArtifactModuleSync = vi.fn(({ dirName }: { dirName: string }) => {
if (dirName !== "first" && dirName !== "second") {
throw new Error(`Unable to resolve bundled plugin public surface ${dirName}`);
}
return {
resolveThinkingProfile: () => ({ levels: [{ id: dirName }] }),
};
});
vi.doMock("./public-surface-loader.js", () => ({
loadBundledPluginPublicArtifactModuleSync,
}));
process.env.OPENCLAW_BUNDLED_PLUGINS_DIR = bundledPluginsDir;
process.env.OPENCLAW_TEST_TRUST_BUNDLED_PLUGINS_DIR = "1";
vi.resetModules();
try {
writePlugin("first", ["fixture-provider"], 1);
writePlugin("second", [], 1);
const { resolveBundledProviderPolicySurface: resolvePolicySurface } = await importFreshModule<
typeof import("./provider-public-artifacts.js")
>(import.meta.url, "./provider-public-artifacts.js?scope=provider-alias-refresh");
expect(
resolvePolicySurface("fixture-provider")
?.resolveThinkingProfile?.({ provider: "fixture-provider", modelId: "demo" })
?.levels.map((level) => level.id),
).toEqual(["first"]);
writePlugin("first", [], 2);
writePlugin("second", ["fixture-provider"], 2);
expect(
resolvePolicySurface("fixture-provider")
?.resolveThinkingProfile?.({ provider: "fixture-provider", modelId: "demo" })
?.levels.map((level) => level.id),
).toEqual(["second"]);
} finally {
fs.rmSync(bundledPluginsDir, { force: true, recursive: true });
}
});
it("loads provider policy surfaces without package-manager repair", async () => {
const loadBundledPluginPublicArtifactModuleSync = vi.fn(() => ({
normalizeConfig: (ctx: { providerConfig: ModelProviderConfig }) => ctx.providerConfig,

View File

@@ -15,7 +15,6 @@ import type {
import { loadBundledPluginPublicArtifactModuleSync } from "./public-surface-loader.js";
const PROVIDER_POLICY_ARTIFACT_CANDIDATES = ["provider-policy-api.js"] as const;
const providerPolicyPluginIdsByProviderId = new Map<string, string | null>();
export type BundledProviderPolicySurface = {
normalizeConfig?: (ctx: ProviderNormalizeConfigContext) => ModelProviderConfig | null | undefined;
@@ -70,13 +69,7 @@ function resolveBundledProviderPolicyPluginId(providerId: string): string | null
return null;
}
const bundledPluginsDir = resolveBundledPluginsDir();
const cacheKey = `${bundledPluginsDir ?? "<none>"}::${normalizedProviderId}`;
if (providerPolicyPluginIdsByProviderId.has(cacheKey)) {
return providerPolicyPluginIdsByProviderId.get(cacheKey) ?? null;
}
if (!bundledPluginsDir) {
providerPolicyPluginIdsByProviderId.set(cacheKey, null);
return null;
}
@@ -91,12 +84,10 @@ function resolveBundledProviderPolicyPluginId(providerId: string): string | null
(provider) => normalizeProviderId(provider) === normalizedProviderId,
);
if (ownsProvider) {
providerPolicyPluginIdsByProviderId.set(cacheKey, plugin.id);
return plugin.id;
}
}
providerPolicyPluginIdsByProviderId.set(cacheKey, null);
return null;
}