


























@@ -389,7 +389,7 @@ describe("resolvePluginTools optional tools", () => {
389389});
390390391391beforeEach(() => {
392-loadOpenClawPluginsMock.mockClear();
392+loadOpenClawPluginsMock.mockReset();
393393resolveRuntimePluginRegistryMock.mockReset();
394394resolveRuntimePluginRegistryMock.mockImplementation((params) =>
395395loadOpenClawPluginsMock(params),
@@ -1185,6 +1185,217 @@ describe("resolvePluginTools optional tools", () => {
11851185expect(loadOpenClawPluginsMock).not.toHaveBeenCalled();
11861186});
118711871188+it("does not let disabled bundled tool owners poison explicit runtime allowlists", () => {
1189+const config = {
1190+plugins: {
1191+enabled: true,
1192+allow: ["memory-core", "memory-lancedb"],
1193+load: { paths: [] },
1194+entries: {
1195+"memory-core": { enabled: true },
1196+"memory-lancedb": { enabled: false },
1197+},
1198+slots: { memory: "memory-core" },
1199+},
1200+};
1201+installToolManifestSnapshots({
1202+ config,
1203+plugins: [
1204+{
1205+id: "memory-core",
1206+origin: "bundled",
1207+enabledByDefault: false,
1208+channels: [],
1209+providers: [],
1210+contracts: {
1211+tools: ["memory_get", "memory_search"],
1212+},
1213+},
1214+{
1215+id: "memory-lancedb",
1216+origin: "bundled",
1217+enabledByDefault: false,
1218+channels: [],
1219+providers: [],
1220+contracts: {
1221+tools: ["memory_recall"],
1222+},
1223+},
1224+],
1225+});
1226+const memorySearchFactory = vi.fn(() => [makeTool("memory_search"), makeTool("memory_get")]);
1227+const activeRegistry = {
1228+plugins: [
1229+{ id: "memory-core", status: "loaded" },
1230+{ id: "memory-lancedb", status: "disabled" },
1231+],
1232+tools: [
1233+{
1234+pluginId: "memory-core",
1235+optional: false,
1236+source: "/tmp/memory-core.js",
1237+names: ["memory_search", "memory_get"],
1238+declaredNames: ["memory_search", "memory_get"],
1239+factory: memorySearchFactory,
1240+},
1241+],
1242+diagnostics: [],
1243+};
1244+setActivePluginRegistry(activeRegistry as never, "gateway-startup", "gateway-bindable", "/tmp");
1245+resolveRuntimePluginRegistryMock.mockReturnValue(undefined);
1246+1247+const tools = resolvePluginTools(
1248+createResolveToolsParams({
1249+context: { ...createContext(), config },
1250+toolAllowlist: ["memory_recall", "memory_search", "memory_get"],
1251+allowGatewaySubagentBinding: true,
1252+}),
1253+);
1254+1255+expectResolvedToolNames(tools, ["memory_search", "memory_get"]);
1256+expect(memorySearchFactory).toHaveBeenCalledTimes(1);
1257+expect(resolveRuntimePluginRegistryMock).not.toHaveBeenCalled();
1258+expect(loadOpenClawPluginsMock).not.toHaveBeenCalled();
1259+});
1260+1261+it("falls back from a loaded channel registry without matching tool entries", () => {
1262+const config = {
1263+plugins: {
1264+enabled: true,
1265+allow: ["memory-core"],
1266+load: { paths: [] },
1267+entries: {
1268+"memory-core": { enabled: true },
1269+},
1270+slots: { memory: "memory-core" },
1271+},
1272+};
1273+installToolManifestSnapshot({
1274+ config,
1275+plugin: {
1276+id: "memory-core",
1277+origin: "bundled",
1278+enabledByDefault: false,
1279+channels: [],
1280+providers: [],
1281+contracts: {
1282+tools: ["memory_get", "memory_search"],
1283+},
1284+},
1285+});
1286+const memorySearchFactory = vi.fn(() => [makeTool("memory_search"), makeTool("memory_get")]);
1287+const activeRegistry = {
1288+plugins: [{ id: "memory-core", status: "loaded" }],
1289+tools: [
1290+{
1291+pluginId: "memory-core",
1292+optional: false,
1293+source: "/tmp/memory-core.js",
1294+names: ["memory_search", "memory_get"],
1295+declaredNames: ["memory_search", "memory_get"],
1296+factory: memorySearchFactory,
1297+},
1298+],
1299+diagnostics: [],
1300+};
1301+setActivePluginRegistry(activeRegistry as never, "gateway-startup", "gateway-bindable", "/tmp");
1302+pinActivePluginChannelRegistry({
1303+plugins: [{ id: "memory-core", status: "loaded" }],
1304+tools: [],
1305+diagnostics: [],
1306+} as never);
1307+resolveRuntimePluginRegistryMock.mockReturnValue(undefined);
1308+1309+const tools = resolvePluginTools(
1310+createResolveToolsParams({
1311+context: { ...createContext(), config },
1312+toolAllowlist: ["memory_search", "memory_get"],
1313+allowGatewaySubagentBinding: true,
1314+}),
1315+);
1316+1317+expectResolvedToolNames(tools, ["memory_search", "memory_get"]);
1318+expect(memorySearchFactory).toHaveBeenCalledTimes(1);
1319+expect(loadOpenClawPluginsMock).not.toHaveBeenCalled();
1320+});
1321+1322+it("loads a standalone registry when cached runtime registries lack matching tool entries", () => {
1323+const config = {
1324+plugins: {
1325+enabled: true,
1326+allow: ["memory-core"],
1327+load: { paths: [] },
1328+entries: {
1329+"memory-core": { enabled: true },
1330+},
1331+slots: { memory: "memory-core" },
1332+},
1333+};
1334+installToolManifestSnapshot({
1335+ config,
1336+plugin: {
1337+id: "memory-core",
1338+origin: "bundled",
1339+enabledByDefault: false,
1340+channels: [],
1341+providers: [],
1342+contracts: {
1343+tools: ["memory_get", "memory_search"],
1344+},
1345+},
1346+});
1347+const memorySearchFactory = vi.fn(() => [makeTool("memory_search"), makeTool("memory_get")]);
1348+const loadedRegistry = {
1349+plugins: [{ id: "memory-core", status: "loaded" }],
1350+tools: [
1351+{
1352+pluginId: "memory-core",
1353+optional: false,
1354+source: "/tmp/memory-core.js",
1355+names: ["memory_search", "memory_get"],
1356+declaredNames: ["memory_search", "memory_get"],
1357+factory: memorySearchFactory,
1358+},
1359+],
1360+diagnostics: [],
1361+};
1362+setActivePluginRegistry(
1363+{
1364+plugins: [{ id: "memory-core", status: "loaded" }],
1365+tools: [],
1366+diagnostics: [],
1367+} as never,
1368+"gateway-startup",
1369+"gateway-bindable",
1370+"/tmp",
1371+);
1372+pinActivePluginChannelRegistry({
1373+plugins: [{ id: "memory-core", status: "loaded" }],
1374+tools: [],
1375+diagnostics: [],
1376+} as never);
1377+resolveRuntimePluginRegistryMock.mockReturnValue(undefined);
1378+loadOpenClawPluginsMock.mockReturnValue(loadedRegistry);
1379+1380+const tools = resolvePluginTools(
1381+createResolveToolsParams({
1382+context: { ...createContext(), config },
1383+toolAllowlist: ["memory_search", "memory_get"],
1384+allowGatewaySubagentBinding: true,
1385+}),
1386+);
1387+1388+expectResolvedToolNames(tools, ["memory_search", "memory_get"]);
1389+expect(memorySearchFactory).toHaveBeenCalledTimes(1);
1390+expect(loadOpenClawPluginsMock).toHaveBeenCalledWith(
1391+expect.objectContaining({
1392+activate: false,
1393+onlyPluginIds: ["memory-core"],
1394+toolDiscovery: true,
1395+}),
1396+);
1397+});
1398+11881399it("adds enabled non-startup tool plugins to the active tool runtime scope", () => {
11891400const activeRegistry = createOptionalDemoActiveRegistry();
11901401setActivePluginRegistry(activeRegistry as never, "gateway-startup", "gateway-bindable", "/tmp");
@@ -1207,7 +1418,18 @@ describe("resolvePluginTools optional tools", () => {
12071418allowGatewaySubagentBinding: true,
12081419});
120914201210-expect(resolveRuntimePluginRegistryMock).not.toHaveBeenCalled();
1421+expect(resolveRuntimePluginRegistryMock).toHaveBeenCalledWith(
1422+expect.objectContaining({
1423+onlyPluginIds: expect.arrayContaining(["tavily"]),
1424+toolDiscovery: true,
1425+}),
1426+);
1427+expect(loadOpenClawPluginsMock).toHaveBeenCalledWith(
1428+expect.objectContaining({
1429+onlyPluginIds: expect.arrayContaining(["tavily"]),
1430+toolDiscovery: true,
1431+}),
1432+);
12111433});
1212143412131435it("reuses the pinned gateway channel registry after provider runtime loads replace active registry", () => {
此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。