diff --git a/src/agents/tool-policy.ts b/src/agents/tool-policy.ts index bd029643a..188a9c336 100644 --- a/src/agents/tool-policy.ts +++ b/src/agents/tool-policy.ts @@ -1,4 +1,19 @@ +import { + expandToolGroups, + normalizeToolList, + normalizeToolName, + resolveToolProfilePolicy, + TOOL_GROUPS, +} from "./tool-policy-shared.js"; import type { AnyAgentTool } from "./tools/common.js"; +export { + expandToolGroups, + normalizeToolList, + normalizeToolName, + resolveToolProfilePolicy, + TOOL_GROUPS, +} from "./tool-policy-shared.js"; +export type { ToolProfileId } from "./tool-policy-shared.js"; // Keep tool-policy browser-safe: do not import tools/common at runtime. function wrapOwnerOnlyToolExecution(tool: AnyAgentTool, senderIsOwner: boolean): AnyAgentTool { @@ -13,92 +28,8 @@ function wrapOwnerOnlyToolExecution(tool: AnyAgentTool, senderIsOwner: boolean): }; } -export type ToolProfileId = "minimal" | "coding" | "messaging" | "full"; - -type ToolProfilePolicy = { - allow?: string[]; - deny?: string[]; -}; - -const TOOL_NAME_ALIASES: Record = { - bash: "exec", - "apply-patch": "apply_patch", -}; - -export const TOOL_GROUPS: Record = { - // NOTE: Keep canonical (lowercase) tool names here. - "group:memory": ["memory_search", "memory_get"], - "group:web": ["web_search", "web_fetch"], - // Basic workspace/file tools - "group:fs": ["read", "write", "edit", "apply_patch"], - // Host/runtime execution tools - "group:runtime": ["exec", "process"], - // Session management tools - "group:sessions": [ - "sessions_list", - "sessions_history", - "sessions_send", - "sessions_spawn", - "subagents", - "session_status", - ], - // UI helpers - "group:ui": ["browser", "canvas"], - // Automation + infra - "group:automation": ["cron", "gateway"], - // Messaging surface - "group:messaging": ["message"], - // Nodes + device tools - "group:nodes": ["nodes"], - // All OpenClaw native tools (excludes provider plugins). - "group:openclaw": [ - "browser", - "canvas", - "nodes", - "cron", - "message", - "gateway", - "agents_list", - "sessions_list", - "sessions_history", - "sessions_send", - "sessions_spawn", - "subagents", - "session_status", - "memory_search", - "memory_get", - "web_search", - "web_fetch", - "image", - ], -}; - const OWNER_ONLY_TOOL_NAME_FALLBACKS = new Set(["whatsapp_login", "cron", "gateway"]); -const TOOL_PROFILES: Record = { - minimal: { - allow: ["session_status"], - }, - coding: { - allow: ["group:fs", "group:runtime", "group:sessions", "group:memory", "image"], - }, - messaging: { - allow: [ - "group:messaging", - "sessions_list", - "sessions_history", - "sessions_send", - "session_status", - ], - }, - full: {}, -}; - -export function normalizeToolName(name: string) { - const normalized = name.trim().toLowerCase(); - return TOOL_NAME_ALIASES[normalized] ?? normalized; -} - export function isOwnerOnlyToolName(name: string) { return OWNER_ONLY_TOOL_NAME_FALLBACKS.has(normalizeToolName(name)); } @@ -120,13 +51,6 @@ export function applyOwnerOnlyToolPolicy(tools: AnyAgentTool[], senderIsOwner: b return withGuard.filter((tool) => !isOwnerOnlyTool(tool)); } -export function normalizeToolList(list?: string[]) { - if (!list) { - return []; - } - return list.map(normalizeToolName).filter(Boolean); -} - export type ToolPolicyLike = { allow?: string[]; deny?: string[]; @@ -143,20 +67,6 @@ export type AllowlistResolution = { strippedAllowlist: boolean; }; -export function expandToolGroups(list?: string[]) { - const normalized = normalizeToolList(list); - const expanded: string[] = []; - for (const value of normalized) { - const group = TOOL_GROUPS[value]; - if (group) { - expanded.push(...group); - continue; - } - expanded.push(value); - } - return Array.from(new Set(expanded)); -} - export function collectExplicitAllowlist(policies: Array): string[] { const entries: string[] = []; for (const policy of policies) { @@ -284,23 +194,6 @@ export function stripPluginOnlyAllowlist( }; } -export function resolveToolProfilePolicy(profile?: string): ToolProfilePolicy | undefined { - if (!profile) { - return undefined; - } - const resolved = TOOL_PROFILES[profile as ToolProfileId]; - if (!resolved) { - return undefined; - } - if (!resolved.allow && !resolved.deny) { - return undefined; - } - return { - allow: resolved.allow ? [...resolved.allow] : undefined, - deny: resolved.deny ? [...resolved.deny] : undefined, - }; -} - export function mergeAlsoAllowPolicy( policy: TPolicy | undefined, alsoAllow?: string[],