Lines 34-74javascript
34 const pluginDirs = dirs ?? PLUGIN_DIRS;
35 const signature = pluginSignature(pluginDirs);
36 if (cachedPlugins && cachedPlugins.signature === signature) {
37 pluginReadOnlyIds = cachedPlugins.readOnlyIds;
38 return cachedPlugins.tools;
40 const tools = await loadPluginToolsUncached(pluginDirs);
41 cachedPlugins = { signature, tools, readOnlyIds: pluginReadOnlyIds };
44async function loadPluginToolsUncached(pluginDirs) {
46 const readOnlyIds = new Set();
47 for (const dir of pluginDirs) {
50 const files = readdirSync(dir).filter((f) => f.endsWith(".ts") || f.endsWith(".js") || f.endsWith(".mjs"));
51 for (const file of files) {
52 const filePath = path.join(dir, file);
53 const namespace = path.basename(file, path.extname(file));
55 const mod = await import(pathToFileURL(filePath).href);
56 for (const [exportName, def] of Object.entries(mod)) {
MediumDynamic Require
Package source references dynamic require/import behavior.
dist/plugins.jsView on unpkg · L54 57 if (!isPluginTool(def))
59 const toolId = exportName === "default" ? namespace : `${namespace}_${exportName}`;
61 console.warn(`\x1b[33m ⚠ Plugin tool "${toolId}" from ${filePath} conflicts with an existing tool; skipping\x1b[0m`);
64 const properties = {};
66 for (const [key, param] of Object.entries(def.parameters)) {
67 const type = narrowJsonType(param.type);
68 properties[key] = { type, ...(param.description ? { description: param.description } : {}) };
71 if (def.readOnly === true)
72 readOnlyIds.add(toolId);
73 tools[toolId] = tool({
74 description: def.description,