























1-import { beforeEach, describe, expect, it, vi } from "vitest";
1+import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
2233const mocks = vi.hoisted(() => ({
44buildManifestBuiltInModelSuppressionResolver: vi.fn(),
5-resolveManifestBuiltInModelSuppression: vi.fn(),
65}));
7687vi.mock("../plugins/manifest-model-suppression.js", () => ({
98buildManifestBuiltInModelSuppressionResolver: mocks.buildManifestBuiltInModelSuppressionResolver,
10-resolveManifestBuiltInModelSuppression: mocks.resolveManifestBuiltInModelSuppression,
119}));
121011+import {
12+clearCurrentPluginMetadataSnapshotState,
13+setCurrentPluginMetadataSnapshotState,
14+} from "../plugins/current-plugin-metadata-state.js";
1315import {
1416buildShouldSuppressBuiltInModel,
17+clearModelSuppressionResolverCacheForTest,
1518shouldSuppressBuiltInModel,
1619} from "./model-suppression.js";
172021+const originalBundledPluginsDir = process.env.OPENCLAW_BUNDLED_PLUGINS_DIR;
22+1823describe("model suppression", () => {
1924beforeEach(() => {
25+clearCurrentPluginMetadataSnapshotState();
26+clearModelSuppressionResolverCacheForTest();
2027mocks.buildManifestBuiltInModelSuppressionResolver.mockReset();
21-mocks.resolveManifestBuiltInModelSuppression.mockReset();
28+});
29+30+afterEach(() => {
31+if (originalBundledPluginsDir === undefined) {
32+delete process.env.OPENCLAW_BUNDLED_PLUGINS_DIR;
33+} else {
34+process.env.OPENCLAW_BUNDLED_PLUGINS_DIR = originalBundledPluginsDir;
35+}
2236});
23372438it("uses manifest suppression", () => {
25-mocks.resolveManifestBuiltInModelSuppression.mockReturnValueOnce({
39+const resolver = vi.fn().mockReturnValueOnce({
2640suppress: true,
2741errorMessage: "manifest suppression",
2842});
43+const config = {};
44+mocks.buildManifestBuiltInModelSuppressionResolver.mockReturnValueOnce(resolver);
29453046expect(
3147shouldSuppressBuiltInModel({
3248provider: "openai",
3349id: "gpt-5.3-codex-spark",
34-config: {},
50+ config,
3551}),
3652).toBe(true);
375338-expect(mocks.resolveManifestBuiltInModelSuppression).toHaveBeenCalledOnce();
54+expect(mocks.buildManifestBuiltInModelSuppressionResolver).toHaveBeenCalledOnce();
55+expect(mocks.buildManifestBuiltInModelSuppressionResolver).toHaveBeenCalledWith({
56+ config,
57+env: process.env,
58+});
59+expect(resolver).toHaveBeenCalledWith({
60+provider: "openai",
61+id: "gpt-5.3-codex-spark",
62+});
3963});
40644165it("does not run deprecated runtime suppression hooks", () => {
66+const resolver = vi.fn().mockReturnValueOnce(undefined);
67+mocks.buildManifestBuiltInModelSuppressionResolver.mockReturnValueOnce(resolver);
68+4269expect(
4370shouldSuppressBuiltInModel({
4471provider: "openai",
@@ -47,7 +74,77 @@ describe("model suppression", () => {
4774}),
4875).toBe(false);
497650-expect(mocks.resolveManifestBuiltInModelSuppression).toHaveBeenCalledOnce();
77+expect(mocks.buildManifestBuiltInModelSuppressionResolver).toHaveBeenCalledOnce();
78+});
79+80+it("reuses manifest suppression resolver for repeated checks with the same scope", () => {
81+const resolver = vi.fn().mockReturnValue(undefined);
82+const config = {};
83+mocks.buildManifestBuiltInModelSuppressionResolver.mockReturnValueOnce(resolver);
84+85+expect(shouldSuppressBuiltInModel({ provider: "openai", id: "gpt-5.3", config })).toBe(false);
86+expect(shouldSuppressBuiltInModel({ provider: "anthropic", id: "claude-4", config })).toBe(
87+false,
88+);
89+90+expect(mocks.buildManifestBuiltInModelSuppressionResolver).toHaveBeenCalledOnce();
91+expect(resolver).toHaveBeenCalledTimes(2);
92+});
93+94+it("refreshes manifest suppression resolver when the current metadata snapshot changes", () => {
95+const firstResolver = vi.fn().mockReturnValue(undefined);
96+const secondResolver = vi.fn().mockReturnValue(undefined);
97+const config = {};
98+mocks.buildManifestBuiltInModelSuppressionResolver
99+.mockReturnValueOnce(firstResolver)
100+.mockReturnValueOnce(secondResolver);
101+102+setCurrentPluginMetadataSnapshotState({ id: "first" }, undefined);
103+expect(shouldSuppressBuiltInModel({ provider: "openai", id: "gpt-5.3", config })).toBe(false);
104+105+setCurrentPluginMetadataSnapshotState({ id: "second" }, undefined);
106+expect(shouldSuppressBuiltInModel({ provider: "openai", id: "gpt-5.3", config })).toBe(false);
107+108+expect(mocks.buildManifestBuiltInModelSuppressionResolver).toHaveBeenCalledTimes(2);
109+expect(firstResolver).toHaveBeenCalledOnce();
110+expect(secondResolver).toHaveBeenCalledOnce();
111+});
112+113+it("refreshes manifest suppression resolver when process env plugin metadata inputs change", () => {
114+const firstResolver = vi.fn().mockReturnValue(undefined);
115+const secondResolver = vi.fn().mockReturnValue(undefined);
116+const config = {};
117+mocks.buildManifestBuiltInModelSuppressionResolver
118+.mockReturnValueOnce(firstResolver)
119+.mockReturnValueOnce(secondResolver);
120+121+process.env.OPENCLAW_BUNDLED_PLUGINS_DIR = "/tmp/openclaw-bundled-a";
122+expect(shouldSuppressBuiltInModel({ provider: "openai", id: "gpt-5.3", config })).toBe(false);
123+124+process.env.OPENCLAW_BUNDLED_PLUGINS_DIR = "/tmp/openclaw-bundled-b";
125+expect(shouldSuppressBuiltInModel({ provider: "openai", id: "gpt-5.3", config })).toBe(false);
126+127+expect(mocks.buildManifestBuiltInModelSuppressionResolver).toHaveBeenCalledTimes(2);
128+expect(firstResolver).toHaveBeenCalledOnce();
129+expect(secondResolver).toHaveBeenCalledOnce();
130+});
131+132+it("refreshes manifest suppression resolver when config plugin inputs mutate in place", () => {
133+const firstResolver = vi.fn().mockReturnValue(undefined);
134+const secondResolver = vi.fn().mockReturnValue(undefined);
135+const config = { plugins: { load: { paths: ["/tmp/openclaw-plugin-a"] } } };
136+mocks.buildManifestBuiltInModelSuppressionResolver
137+.mockReturnValueOnce(firstResolver)
138+.mockReturnValueOnce(secondResolver);
139+140+expect(shouldSuppressBuiltInModel({ provider: "openai", id: "gpt-5.3", config })).toBe(false);
141+142+config.plugins.load.paths = ["/tmp/openclaw-plugin-b"];
143+expect(shouldSuppressBuiltInModel({ provider: "openai", id: "gpt-5.3", config })).toBe(false);
144+145+expect(mocks.buildManifestBuiltInModelSuppressionResolver).toHaveBeenCalledTimes(2);
146+expect(firstResolver).toHaveBeenCalledOnce();
147+expect(secondResolver).toHaveBeenCalledOnce();
51148});
5214953150describe("buildShouldSuppressBuiltInModel", () => {
此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。