Spaces:
Configuration error
Configuration error
| import type { AnyAgentTool } from "../agents/tools/common.js"; | |
| import { normalizeToolName } from "../agents/tool-policy.js"; | |
| import { createSubsystemLogger } from "../logging/subsystem.js"; | |
| import { loadMoltbotPlugins } from "./loader.js"; | |
| import type { MoltbotPluginToolContext } from "./types.js"; | |
| const log = createSubsystemLogger("plugins"); | |
| type PluginToolMeta = { | |
| pluginId: string; | |
| optional: boolean; | |
| }; | |
| const pluginToolMeta = new WeakMap<AnyAgentTool, PluginToolMeta>(); | |
| export function getPluginToolMeta(tool: AnyAgentTool): PluginToolMeta | undefined { | |
| return pluginToolMeta.get(tool); | |
| } | |
| function normalizeAllowlist(list?: string[]) { | |
| return new Set((list ?? []).map(normalizeToolName).filter(Boolean)); | |
| } | |
| function isOptionalToolAllowed(params: { | |
| toolName: string; | |
| pluginId: string; | |
| allowlist: Set<string>; | |
| }): boolean { | |
| if (params.allowlist.size === 0) return false; | |
| const toolName = normalizeToolName(params.toolName); | |
| if (params.allowlist.has(toolName)) return true; | |
| const pluginKey = normalizeToolName(params.pluginId); | |
| if (params.allowlist.has(pluginKey)) return true; | |
| return params.allowlist.has("group:plugins"); | |
| } | |
| export function resolvePluginTools(params: { | |
| context: MoltbotPluginToolContext; | |
| existingToolNames?: Set<string>; | |
| toolAllowlist?: string[]; | |
| }): AnyAgentTool[] { | |
| const registry = loadMoltbotPlugins({ | |
| config: params.context.config, | |
| workspaceDir: params.context.workspaceDir, | |
| logger: { | |
| info: (msg) => log.info(msg), | |
| warn: (msg) => log.warn(msg), | |
| error: (msg) => log.error(msg), | |
| debug: (msg) => log.debug(msg), | |
| }, | |
| }); | |
| const tools: AnyAgentTool[] = []; | |
| const existing = params.existingToolNames ?? new Set<string>(); | |
| const existingNormalized = new Set(Array.from(existing, (tool) => normalizeToolName(tool))); | |
| const allowlist = normalizeAllowlist(params.toolAllowlist); | |
| const blockedPlugins = new Set<string>(); | |
| for (const entry of registry.tools) { | |
| if (blockedPlugins.has(entry.pluginId)) continue; | |
| const pluginIdKey = normalizeToolName(entry.pluginId); | |
| if (existingNormalized.has(pluginIdKey)) { | |
| const message = `plugin id conflicts with core tool name (${entry.pluginId})`; | |
| log.error(message); | |
| registry.diagnostics.push({ | |
| level: "error", | |
| pluginId: entry.pluginId, | |
| source: entry.source, | |
| message, | |
| }); | |
| blockedPlugins.add(entry.pluginId); | |
| continue; | |
| } | |
| let resolved: AnyAgentTool | AnyAgentTool[] | null | undefined = null; | |
| try { | |
| resolved = entry.factory(params.context); | |
| } catch (err) { | |
| log.error(`plugin tool failed (${entry.pluginId}): ${String(err)}`); | |
| continue; | |
| } | |
| if (!resolved) continue; | |
| const listRaw = Array.isArray(resolved) ? resolved : [resolved]; | |
| const list = entry.optional | |
| ? listRaw.filter((tool) => | |
| isOptionalToolAllowed({ | |
| toolName: tool.name, | |
| pluginId: entry.pluginId, | |
| allowlist, | |
| }), | |
| ) | |
| : listRaw; | |
| if (list.length === 0) continue; | |
| const nameSet = new Set<string>(); | |
| for (const tool of list) { | |
| if (nameSet.has(tool.name) || existing.has(tool.name)) { | |
| const message = `plugin tool name conflict (${entry.pluginId}): ${tool.name}`; | |
| log.error(message); | |
| registry.diagnostics.push({ | |
| level: "error", | |
| pluginId: entry.pluginId, | |
| source: entry.source, | |
| message, | |
| }); | |
| continue; | |
| } | |
| nameSet.add(tool.name); | |
| existing.add(tool.name); | |
| pluginToolMeta.set(tool, { | |
| pluginId: entry.pluginId, | |
| optional: entry.optional, | |
| }); | |
| tools.push(tool); | |
| } | |
| } | |
| return tools; | |
| } | |