mirror of
https://github.com/openclaw/openclaw.git
synced 2026-06-02 18:17:14 +00:00
refactor: centralize message-provider tool filtering
This commit is contained in:
@@ -319,19 +319,6 @@ describe("createOpenClawCodingTools", () => {
|
|||||||
expect(names.has("telegram")).toBe(false);
|
expect(names.has("telegram")).toBe(false);
|
||||||
expect(names.has("whatsapp")).toBe(false);
|
expect(names.has("whatsapp")).toBe(false);
|
||||||
});
|
});
|
||||||
it.each(["voice", "VOICE", " Voice "])(
|
|
||||||
"does not expose tts tool for normalized voice message provider: %s",
|
|
||||||
(messageProvider) => {
|
|
||||||
const tools = createOpenClawCodingTools({ messageProvider });
|
|
||||||
const names = new Set(tools.map((tool) => tool.name));
|
|
||||||
expect(names.has("tts")).toBe(false);
|
|
||||||
},
|
|
||||||
);
|
|
||||||
it("keeps tts tool for non-voice providers", () => {
|
|
||||||
const tools = createOpenClawCodingTools({ messageProvider: "discord" });
|
|
||||||
const names = new Set(tools.map((tool) => tool.name));
|
|
||||||
expect(names.has("tts")).toBe(true);
|
|
||||||
});
|
|
||||||
it("filters session tools for sub-agent sessions by default", () => {
|
it("filters session tools for sub-agent sessions by default", () => {
|
||||||
const tools = createOpenClawCodingTools({
|
const tools = createOpenClawCodingTools({
|
||||||
sessionKey: "agent:main:subagent:test",
|
sessionKey: "agent:main:subagent:test",
|
||||||
|
|||||||
19
src/agents/pi-tools.message-provider-policy.test.ts
Normal file
19
src/agents/pi-tools.message-provider-policy.test.ts
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
import { describe, expect, it } from "vitest";
|
||||||
|
import { createOpenClawCodingTools } from "./pi-tools.js";
|
||||||
|
|
||||||
|
describe("createOpenClawCodingTools message provider policy", () => {
|
||||||
|
it.each(["voice", "VOICE", " Voice "])(
|
||||||
|
"does not expose tts tool for normalized voice provider: %s",
|
||||||
|
(messageProvider) => {
|
||||||
|
const tools = createOpenClawCodingTools({ messageProvider });
|
||||||
|
const names = new Set(tools.map((tool) => tool.name));
|
||||||
|
expect(names.has("tts")).toBe(false);
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
|
it("keeps tts tool for non-voice providers", () => {
|
||||||
|
const tools = createOpenClawCodingTools({ messageProvider: "discord" });
|
||||||
|
const names = new Set(tools.map((tool) => tool.name));
|
||||||
|
expect(names.has("tts")).toBe(true);
|
||||||
|
});
|
||||||
|
});
|
||||||
@@ -67,6 +67,31 @@ function isOpenAIProvider(provider?: string) {
|
|||||||
return normalized === "openai" || normalized === "openai-codex";
|
return normalized === "openai" || normalized === "openai-codex";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const TOOL_DENY_BY_MESSAGE_PROVIDER: Readonly<Record<string, readonly string[]>> = {
|
||||||
|
voice: ["tts"],
|
||||||
|
};
|
||||||
|
|
||||||
|
function normalizeMessageProvider(messageProvider?: string): string | undefined {
|
||||||
|
const normalized = messageProvider?.trim().toLowerCase();
|
||||||
|
return normalized && normalized.length > 0 ? normalized : undefined;
|
||||||
|
}
|
||||||
|
|
||||||
|
function applyMessageProviderToolPolicy(
|
||||||
|
tools: AnyAgentTool[],
|
||||||
|
messageProvider?: string,
|
||||||
|
): AnyAgentTool[] {
|
||||||
|
const normalizedProvider = normalizeMessageProvider(messageProvider);
|
||||||
|
if (!normalizedProvider) {
|
||||||
|
return tools;
|
||||||
|
}
|
||||||
|
const deniedTools = TOOL_DENY_BY_MESSAGE_PROVIDER[normalizedProvider];
|
||||||
|
if (!deniedTools || deniedTools.length === 0) {
|
||||||
|
return tools;
|
||||||
|
}
|
||||||
|
const deniedSet = new Set(deniedTools);
|
||||||
|
return tools.filter((tool) => !deniedSet.has(tool.name));
|
||||||
|
}
|
||||||
|
|
||||||
function isApplyPatchAllowedForModel(params: {
|
function isApplyPatchAllowedForModel(params: {
|
||||||
modelProvider?: string;
|
modelProvider?: string;
|
||||||
modelId?: string;
|
modelId?: string;
|
||||||
@@ -217,8 +242,6 @@ export function createOpenClawCodingTools(options?: {
|
|||||||
/** Whether the sender is an owner (required for owner-only tools). */
|
/** Whether the sender is an owner (required for owner-only tools). */
|
||||||
senderIsOwner?: boolean;
|
senderIsOwner?: boolean;
|
||||||
}): AnyAgentTool[] {
|
}): AnyAgentTool[] {
|
||||||
const rawMessageProvider = options?.messageProvider?.trim().toLowerCase();
|
|
||||||
const isVoiceMessageProvider = rawMessageProvider === "voice";
|
|
||||||
const execToolName = "exec";
|
const execToolName = "exec";
|
||||||
const sandbox = options?.sandbox?.enabled ? options.sandbox : undefined;
|
const sandbox = options?.sandbox?.enabled ? options.sandbox : undefined;
|
||||||
const {
|
const {
|
||||||
@@ -482,9 +505,7 @@ export function createOpenClawCodingTools(options?: {
|
|||||||
senderIsOwner: options?.senderIsOwner,
|
senderIsOwner: options?.senderIsOwner,
|
||||||
}),
|
}),
|
||||||
];
|
];
|
||||||
const toolsForMessageProvider = isVoiceMessageProvider
|
const toolsForMessageProvider = applyMessageProviderToolPolicy(tools, options?.messageProvider);
|
||||||
? tools.filter((tool) => tool.name !== "tts")
|
|
||||||
: tools;
|
|
||||||
// Security: treat unknown/undefined as unauthorized (opt-in, not opt-out)
|
// Security: treat unknown/undefined as unauthorized (opt-in, not opt-out)
|
||||||
const senderIsOwner = options?.senderIsOwner === true;
|
const senderIsOwner = options?.senderIsOwner === true;
|
||||||
const toolsByAuthorization = applyOwnerOnlyToolPolicy(toolsForMessageProvider, senderIsOwner);
|
const toolsByAuthorization = applyOwnerOnlyToolPolicy(toolsForMessageProvider, senderIsOwner);
|
||||||
|
|||||||
Reference in New Issue
Block a user