






















@@ -0,0 +1,148 @@
1+import { beforeEach, describe, expect, it, vi } from "vitest";
2+import type { OpenClawConfig } from "../config/types.openclaw.js";
3+import type { PluginMetadataSnapshot } from "./plugin-metadata-snapshot.js";
4+5+const mocks = vi.hoisted(() => ({
6+applyPluginAutoEnable:
7+vi.fn<typeof import("../config/plugin-auto-enable.js").applyPluginAutoEnable>(),
8+listExplicitlyDisabledChannelIdsForConfig: vi.fn(),
9+listPotentialConfiguredChannelIds: vi.fn(),
10+listExplicitConfiguredChannelIdsForConfig: vi.fn(),
11+loadGatewayStartupPluginPlan:
12+vi.fn<typeof import("./channel-plugin-ids.js").loadGatewayStartupPluginPlan>(),
13+resolveConfiguredChannelPluginIds:
14+vi.fn<typeof import("./channel-plugin-ids.js").resolveConfiguredChannelPluginIds>(),
15+loadManifestMetadataSnapshot:
16+vi.fn<typeof import("./manifest-contract-eligibility.js").loadManifestMetadataSnapshot>(),
17+passesManifestOwnerBasePolicy:
18+vi.fn<typeof import("./manifest-owner-policy.js").passesManifestOwnerBasePolicy>(),
19+}));
20+21+vi.mock("../config/plugin-auto-enable.js", () => ({
22+applyPluginAutoEnable: (...args: Parameters<typeof mocks.applyPluginAutoEnable>) =>
23+mocks.applyPluginAutoEnable(...args),
24+}));
25+26+vi.mock("../channels/config-presence.js", () => ({
27+listExplicitlyDisabledChannelIdsForConfig: (
28+ ...args: Parameters<typeof mocks.listExplicitlyDisabledChannelIdsForConfig>
29+) => mocks.listExplicitlyDisabledChannelIdsForConfig(...args),
30+listPotentialConfiguredChannelIds: (
31+ ...args: Parameters<typeof mocks.listPotentialConfiguredChannelIds>
32+) => mocks.listPotentialConfiguredChannelIds(...args),
33+}));
34+35+vi.mock("./channel-plugin-ids.js", () => ({
36+listExplicitConfiguredChannelIdsForConfig: (
37+ ...args: Parameters<typeof mocks.listExplicitConfiguredChannelIdsForConfig>
38+) => mocks.listExplicitConfiguredChannelIdsForConfig(...args),
39+loadGatewayStartupPluginPlan: (...args: Parameters<typeof mocks.loadGatewayStartupPluginPlan>) =>
40+mocks.loadGatewayStartupPluginPlan(...args),
41+resolveConfiguredChannelPluginIds: (
42+ ...args: Parameters<typeof mocks.resolveConfiguredChannelPluginIds>
43+) => mocks.resolveConfiguredChannelPluginIds(...args),
44+}));
45+46+vi.mock("./manifest-contract-eligibility.js", () => ({
47+loadManifestMetadataSnapshot: (...args: Parameters<typeof mocks.loadManifestMetadataSnapshot>) =>
48+mocks.loadManifestMetadataSnapshot(...args),
49+}));
50+51+vi.mock("./manifest-owner-policy.js", () => ({
52+passesManifestOwnerBasePolicy: (
53+ ...args: Parameters<typeof mocks.passesManifestOwnerBasePolicy>
54+) => mocks.passesManifestOwnerBasePolicy(...args),
55+}));
56+57+import { resolveEffectivePluginIds } from "./effective-plugin-ids.js";
58+59+function resolve(config: OpenClawConfig): string[] {
60+return resolveEffectivePluginIds({
61+ config,
62+env: {},
63+workspaceDir: "/workspace",
64+});
65+}
66+67+describe("resolveEffectivePluginIds", () => {
68+beforeEach(() => {
69+mocks.applyPluginAutoEnable.mockReset();
70+mocks.listExplicitlyDisabledChannelIdsForConfig.mockReset();
71+mocks.listPotentialConfiguredChannelIds.mockReset();
72+mocks.listExplicitConfiguredChannelIdsForConfig.mockReset();
73+mocks.loadGatewayStartupPluginPlan.mockReset();
74+mocks.resolveConfiguredChannelPluginIds.mockReset();
75+mocks.loadManifestMetadataSnapshot.mockReset();
76+mocks.passesManifestOwnerBasePolicy.mockReset();
77+78+mocks.applyPluginAutoEnable.mockImplementation((params) => ({
79+config: params.config ?? {},
80+changes: [],
81+autoEnabledReasons: {},
82+}));
83+mocks.listExplicitlyDisabledChannelIdsForConfig.mockReturnValue([]);
84+mocks.listPotentialConfiguredChannelIds.mockReturnValue([]);
85+mocks.listExplicitConfiguredChannelIdsForConfig.mockReturnValue([]);
86+mocks.loadGatewayStartupPluginPlan.mockReturnValue({
87+channelPluginIds: [],
88+configuredDeferredChannelPluginIds: [],
89+pluginIds: [],
90+});
91+mocks.resolveConfiguredChannelPluginIds.mockReturnValue([]);
92+mocks.loadManifestMetadataSnapshot.mockReturnValue({
93+plugins: [],
94+} as unknown as PluginMetadataSnapshot);
95+mocks.passesManifestOwnerBasePolicy.mockReturnValue(true);
96+});
97+98+it("includes a selected context-engine slot even when omitted from explicit allow and entries", () => {
99+expect(
100+resolve({
101+plugins: {
102+slots: { contextEngine: "lossless-claw" },
103+},
104+}),
105+).toEqual(["lossless-claw"]);
106+});
107+108+it("keeps the built-in legacy context engine out of plugin preload ids", () => {
109+expect(
110+resolve({
111+plugins: {
112+slots: { contextEngine: "legacy" },
113+},
114+}),
115+).toEqual([]);
116+});
117+118+it.each([
119+{
120+name: "plugins disabled",
121+plugins: {
122+enabled: false,
123+slots: { contextEngine: "lossless-claw" },
124+},
125+},
126+{
127+name: "denylisted",
128+plugins: {
129+deny: ["lossless-claw"],
130+slots: { contextEngine: "lossless-claw" },
131+},
132+},
133+{
134+name: "entry disabled",
135+plugins: {
136+entries: {
137+"lossless-claw": { enabled: false },
138+},
139+slots: { contextEngine: "lossless-claw" },
140+},
141+},
142+] satisfies Array<{ name: string; plugins: NonNullable<OpenClawConfig["plugins"]> }>)(
143+"does not preload a selected context-engine slot when $name",
144+({ plugins }) => {
145+expect(resolve({ plugins })).toEqual([]);
146+},
147+);
148+});
此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。