




























@@ -3,22 +3,43 @@ import type { OpenClawConfig } from "../../config/types.openclaw.js";
3344const mocks = vi.hoisted(() => ({
55ensurePluginRegistryLoaded: vi.fn(),
6+resolveActivatableProviderOwnerPluginIds: vi.fn(),
7+resolveBundledProviderCompatPluginIds: vi.fn(),
8+resolveOwningPluginIdsForProvider: vi.fn(),
69}));
710811vi.mock("../../plugins/runtime/runtime-registry-loader.js", () => ({
912ensurePluginRegistryLoaded: mocks.ensurePluginRegistryLoaded,
1013}));
111415+vi.mock("../../plugins/providers.js", () => ({
16+resolveActivatableProviderOwnerPluginIds: mocks.resolveActivatableProviderOwnerPluginIds,
17+resolveBundledProviderCompatPluginIds: mocks.resolveBundledProviderCompatPluginIds,
18+resolveOwningPluginIdsForProvider: mocks.resolveOwningPluginIdsForProvider,
19+}));
20+1221describe("ensureSelectedAgentHarnessPlugin", () => {
1322let ensureSelectedAgentHarnessPlugin: typeof import("./runtime-plugin.js").ensureSelectedAgentHarnessPlugin;
14231524beforeEach(async () => {
1625mocks.ensurePluginRegistryLoaded.mockReset();
26+mocks.resolveActivatableProviderOwnerPluginIds.mockReset();
27+mocks.resolveBundledProviderCompatPluginIds.mockReset();
28+mocks.resolveOwningPluginIdsForProvider.mockReset();
29+mocks.resolveOwningPluginIdsForProvider.mockImplementation(
30+({ provider }: { provider: string }) =>
31+provider === "openai" || provider === "openai-codex" ? ["openai"] : undefined,
32+);
33+mocks.resolveBundledProviderCompatPluginIds.mockImplementation(
34+({ onlyPluginIds }: { onlyPluginIds?: readonly string[] }) =>
35+(onlyPluginIds ?? []).filter((pluginId) => pluginId === "openai"),
36+);
37+mocks.resolveActivatableProviderOwnerPluginIds.mockReturnValue([]);
1738vi.resetModules();
1839({ ensureSelectedAgentHarnessPlugin } = await import("./runtime-plugin.js"));
1940});
204121-it("loads Codex when an explicit runtime override forces the Codex harness", async () => {
42+it("loads Codex and the provider owner when an explicit runtime override forces the Codex harness", async () => {
2243await ensureSelectedAgentHarnessPlugin({
2344provider: "openai",
2445modelId: "gpt-5.5",
@@ -40,12 +61,12 @@ describe("ensureSelectedAgentHarnessPlugin", () => {
4061expect.objectContaining({
4162scope: "all",
4263workspaceDir: "/tmp/workspace",
43-onlyPluginIds: ["codex"],
64+onlyPluginIds: ["codex", "openai"],
4465}),
4566);
4667});
476848-it("tries to load Codex for the implicit official OpenAI runtime before selection", async () => {
69+it("loads Codex and the provider owner for the implicit official OpenAI runtime before selection", async () => {
4970await ensureSelectedAgentHarnessPlugin({
5071provider: "openai",
5172modelId: "gpt-5.5",
@@ -62,6 +83,174 @@ describe("ensureSelectedAgentHarnessPlugin", () => {
6283workspaceDir: "/tmp/workspace",
6384});
648586+expect(mocks.ensurePluginRegistryLoaded).toHaveBeenCalledWith(
87+expect.objectContaining({
88+scope: "all",
89+workspaceDir: "/tmp/workspace",
90+onlyPluginIds: ["codex", "openai"],
91+}),
92+);
93+});
94+95+it("widens a scoped harness allowlist with the provider owner for openai-codex models", async () => {
96+await ensureSelectedAgentHarnessPlugin({
97+provider: "openai-codex",
98+modelId: "gpt-5.5-pro",
99+config: {
100+plugins: {
101+allow: ["codex"],
102+entries: {
103+codex: { enabled: true },
104+},
105+},
106+} as OpenClawConfig,
107+workspaceDir: "/tmp/workspace",
108+});
109+110+expect(mocks.ensurePluginRegistryLoaded).toHaveBeenCalledWith(
111+expect.objectContaining({
112+scope: "all",
113+workspaceDir: "/tmp/workspace",
114+onlyPluginIds: ["codex", "openai"],
115+config: expect.objectContaining({
116+plugins: expect.objectContaining({
117+allow: ["codex", "openai"],
118+entries: expect.objectContaining({
119+codex: expect.objectContaining({ enabled: true }),
120+openai: expect.objectContaining({ enabled: true }),
121+}),
122+}),
123+}),
124+}),
125+);
126+});
127+128+it("does not auto-activate untrusted provider owners for Codex harness loads", async () => {
129+mocks.resolveOwningPluginIdsForProvider.mockReturnValueOnce(["openai", "workspace-openai"]);
130+mocks.resolveBundledProviderCompatPluginIds.mockReturnValueOnce(["openai"]);
131+mocks.resolveActivatableProviderOwnerPluginIds.mockReturnValueOnce([]);
132+133+await ensureSelectedAgentHarnessPlugin({
134+provider: "openai-codex",
135+modelId: "gpt-5.5-pro",
136+config: {
137+plugins: {
138+allow: ["codex"],
139+entries: {
140+codex: { enabled: true },
141+},
142+},
143+} as OpenClawConfig,
144+workspaceDir: "/tmp/workspace",
145+});
146+147+expect(mocks.resolveBundledProviderCompatPluginIds).toHaveBeenCalledWith({
148+config: expect.any(Object),
149+workspaceDir: "/tmp/workspace",
150+onlyPluginIds: ["openai", "workspace-openai"],
151+});
152+expect(mocks.resolveActivatableProviderOwnerPluginIds).toHaveBeenCalledWith({
153+pluginIds: ["openai", "workspace-openai"],
154+config: expect.any(Object),
155+workspaceDir: "/tmp/workspace",
156+});
157+expect(mocks.ensurePluginRegistryLoaded).toHaveBeenCalledWith(
158+expect.objectContaining({
159+scope: "all",
160+workspaceDir: "/tmp/workspace",
161+onlyPluginIds: ["codex", "openai"],
162+}),
163+);
164+});
165+166+it("does not bypass a restrictive allowlist that omits the Codex harness", async () => {
167+await ensureSelectedAgentHarnessPlugin({
168+provider: "openai-codex",
169+modelId: "gpt-5.5-pro",
170+config: {
171+plugins: {
172+allow: ["telegram"],
173+entries: {
174+telegram: { enabled: true },
175+},
176+},
177+} as OpenClawConfig,
178+workspaceDir: "/tmp/workspace",
179+});
180+181+expect(mocks.resolveOwningPluginIdsForProvider).not.toHaveBeenCalled();
182+expect(mocks.resolveBundledProviderCompatPluginIds).not.toHaveBeenCalled();
183+expect(mocks.resolveActivatableProviderOwnerPluginIds).not.toHaveBeenCalled();
184+expect(mocks.ensurePluginRegistryLoaded).toHaveBeenCalledWith(
185+expect.objectContaining({
186+scope: "all",
187+workspaceDir: "/tmp/workspace",
188+onlyPluginIds: ["codex"],
189+config: expect.objectContaining({
190+plugins: expect.objectContaining({
191+allow: ["telegram"],
192+entries: expect.not.objectContaining({
193+codex: expect.anything(),
194+openai: expect.anything(),
195+}),
196+}),
197+}),
198+}),
199+);
200+});
201+202+it("honors bundled discovery compat when a legacy allowlist omits the Codex harness", async () => {
203+await ensureSelectedAgentHarnessPlugin({
204+provider: "openai-codex",
205+modelId: "gpt-5.5-pro",
206+config: {
207+plugins: {
208+allow: ["telegram"],
209+bundledDiscovery: "compat",
210+entries: {
211+telegram: { enabled: true },
212+},
213+},
214+} as OpenClawConfig,
215+workspaceDir: "/tmp/workspace",
216+});
217+218+expect(mocks.resolveOwningPluginIdsForProvider).toHaveBeenCalledWith({
219+provider: "openai-codex",
220+config: expect.any(Object),
221+workspaceDir: "/tmp/workspace",
222+});
223+expect(mocks.ensurePluginRegistryLoaded).toHaveBeenCalledWith(
224+expect.objectContaining({
225+scope: "all",
226+workspaceDir: "/tmp/workspace",
227+onlyPluginIds: ["codex", "openai"],
228+config: expect.objectContaining({
229+plugins: expect.objectContaining({
230+allow: ["telegram", "codex", "openai"],
231+entries: expect.objectContaining({
232+codex: expect.objectContaining({ enabled: true }),
233+openai: expect.objectContaining({ enabled: true }),
234+telegram: expect.objectContaining({ enabled: true }),
235+}),
236+}),
237+}),
238+}),
239+);
240+});
241+242+it("keeps a Codex scoped load narrow when the provider has no owner plugin", async () => {
243+mocks.resolveOwningPluginIdsForProvider.mockReturnValueOnce(undefined);
244+245+await ensureSelectedAgentHarnessPlugin({
246+provider: "custom-provider",
247+modelId: "gpt-5.5",
248+agentHarnessRuntimeOverride: "codex",
249+workspaceDir: "/tmp/workspace",
250+});
251+252+expect(mocks.resolveBundledProviderCompatPluginIds).not.toHaveBeenCalled();
253+expect(mocks.resolveActivatableProviderOwnerPluginIds).not.toHaveBeenCalled();
65254expect(mocks.ensurePluginRegistryLoaded).toHaveBeenCalledWith(
66255expect.objectContaining({
67256scope: "all",
@@ -89,5 +278,6 @@ describe("ensureSelectedAgentHarnessPlugin", () => {
89278});
9027991280expect(mocks.ensurePluginRegistryLoaded).not.toHaveBeenCalled();
281+expect(mocks.resolveOwningPluginIdsForProvider).not.toHaveBeenCalled();
92282});
93283});
此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。