mirror of
https://github.com/openclaw/openclaw.git
synced 2026-05-06 06:20:43 +00:00
fix: honor wildcard tool denylists in factory planning (#76773) (thanks @dorukardahan)
This commit is contained in:
@@ -10,7 +10,7 @@ Docs: https://docs.openclaw.ai
|
||||
|
||||
### Changes
|
||||
|
||||
- Agents/tools: skip optional media and PDF tool factories when the effective tool denylist already blocks them, avoiding unnecessary hot-path setup for tools that will be filtered out before model use.
|
||||
- Agents/tools: skip optional media and PDF tool factories when the effective tool denylist already blocks them, avoiding unnecessary hot-path setup for tools that will be filtered out before model use. (#76773) Thanks @dorukardahan.
|
||||
- Gateway/performance: lazy-load early runtime discovery and shutdown-hook helpers, defer maintenance timers until after readiness, and trim duplicate plugin auto-enable work during Gateway startup.
|
||||
- QA/Mantis: add a `pnpm openclaw qa mantis discord-smoke` runner and manual GitHub workflow that verify the Mantis Discord bot can see the configured guild/channel, post a smoke message, add a reaction, and upload artifacts.
|
||||
- Gateway/performance: lazy-load the heavy cron runtime after the rest of Gateway startup, defer restart-sentinel refresh after readiness, and let the Gateway startup benchmark write per-run V8 CPU profiles with `--cpu-prof-dir`.
|
||||
|
||||
@@ -276,6 +276,45 @@ describe("optional media tool factory planning", () => {
|
||||
});
|
||||
});
|
||||
|
||||
it("applies wildcard deny patterns to optional factory planning", () => {
|
||||
const config: OpenClawConfig = {};
|
||||
installSnapshot(config, [
|
||||
createPlugin({
|
||||
id: "image-owner",
|
||||
contracts: { imageGenerationProviders: ["image-owner"] },
|
||||
setupProviders: [{ id: "image-owner", envVars: ["IMAGE_OWNER_API_KEY"] }],
|
||||
}),
|
||||
createPlugin({
|
||||
id: "video-owner",
|
||||
contracts: { videoGenerationProviders: ["video-owner"] },
|
||||
setupProviders: [{ id: "video-owner", envVars: ["VIDEO_OWNER_API_KEY"] }],
|
||||
}),
|
||||
createPlugin({
|
||||
id: "music-owner",
|
||||
contracts: { musicGenerationProviders: ["music-owner"] },
|
||||
setupProviders: [{ id: "music-owner", envVars: ["MUSIC_OWNER_API_KEY"] }],
|
||||
}),
|
||||
createPlugin({
|
||||
id: "media-owner",
|
||||
contracts: { mediaUnderstandingProviders: ["anthropic"] },
|
||||
setupProviders: [{ id: "anthropic", envVars: ["ANTHROPIC_API_KEY"] }],
|
||||
}),
|
||||
]);
|
||||
|
||||
expect(
|
||||
__testing.resolveOptionalMediaToolFactoryPlan({
|
||||
config,
|
||||
authStore: createAuthStore(["image-owner", "video-owner", "music-owner", "anthropic"]),
|
||||
toolDenylist: ["*_generate", "p*"],
|
||||
}),
|
||||
).toEqual({
|
||||
imageGenerate: false,
|
||||
videoGenerate: false,
|
||||
musicGenerate: false,
|
||||
pdf: false,
|
||||
});
|
||||
});
|
||||
|
||||
it("keeps auth-backed providers on the factory path", () => {
|
||||
const config: OpenClawConfig = {};
|
||||
installSnapshot(config, [
|
||||
|
||||
@@ -22,7 +22,7 @@ import {
|
||||
import type { SandboxFsBridge } from "./sandbox/fs-bridge.js";
|
||||
import type { SpawnedToolContext } from "./spawned-context.js";
|
||||
import type { ToolFsPolicy } from "./tool-fs-policy.js";
|
||||
import { expandToolGroups, normalizeToolName } from "./tool-policy.js";
|
||||
import { isToolAllowedByPolicyName } from "./tool-policy-match.js";
|
||||
import { createAgentsListTool } from "./tools/agents-list-tool.js";
|
||||
import { createCanvasTool } from "./tools/canvas-tool.js";
|
||||
import type { AnyAgentTool } from "./tools/common.js";
|
||||
@@ -83,31 +83,15 @@ function hasExplicitImageModelConfig(config: OpenClawConfig | undefined): boolea
|
||||
return hasToolModelConfig(coerceImageModelConfig(config));
|
||||
}
|
||||
|
||||
function isToolAllowedByFactoryAllowlist(toolName: string, allowlist?: string[]): boolean {
|
||||
if (!allowlist || allowlist.length === 0) {
|
||||
return true;
|
||||
}
|
||||
const expanded = new Set(expandToolGroups(allowlist));
|
||||
return expanded.has("*") || expanded.has(normalizeToolName(toolName));
|
||||
}
|
||||
|
||||
function isToolDeniedByFactoryDenylist(toolName: string, denylist?: string[]): boolean {
|
||||
if (!denylist || denylist.length === 0) {
|
||||
return false;
|
||||
}
|
||||
const expanded = new Set(expandToolGroups(denylist));
|
||||
return expanded.has("*") || expanded.has(normalizeToolName(toolName));
|
||||
}
|
||||
|
||||
function isToolAllowedByFactoryPolicy(params: {
|
||||
toolName: string;
|
||||
allowlist?: string[];
|
||||
denylist?: string[];
|
||||
}): boolean {
|
||||
if (isToolDeniedByFactoryDenylist(params.toolName, params.denylist)) {
|
||||
return false;
|
||||
}
|
||||
return isToolAllowedByFactoryAllowlist(params.toolName, params.allowlist);
|
||||
return isToolAllowedByPolicyName(params.toolName, {
|
||||
allow: params.allowlist,
|
||||
deny: params.denylist,
|
||||
});
|
||||
}
|
||||
|
||||
function resolveImageToolFactoryAvailable(params: {
|
||||
|
||||
Reference in New Issue
Block a user