| | const fs = require('fs'); |
| | const path = require('path'); |
| | const { Tool } = require('@langchain/core/tools'); |
| | const { Calculator } = require('@librechat/agents'); |
| | const { logger } = require('@librechat/data-schemas'); |
| | const { zodToJsonSchema } = require('zod-to-json-schema'); |
| | const { Tools, ImageVisionTool } = require('librechat-data-provider'); |
| | const { getToolkitKey, oaiToolkit, ytToolkit } = require('@librechat/api'); |
| | const { toolkits } = require('~/app/clients/tools/manifest'); |
| |
|
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | function loadAndFormatTools({ directory, adminFilter = [], adminIncluded = [] }) { |
| | const filter = new Set([...adminFilter]); |
| | const included = new Set(adminIncluded); |
| | const tools = []; |
| | |
| | const files = fs.readdirSync(directory); |
| |
|
| | if (included.size > 0 && adminFilter.length > 0) { |
| | logger.warn( |
| | 'Both `includedTools` and `filteredTools` are defined; `filteredTools` will be ignored.', |
| | ); |
| | } |
| |
|
| | for (const file of files) { |
| | const filePath = path.join(directory, file); |
| | if (!file.endsWith('.js') || (filter.has(file) && included.size === 0)) { |
| | continue; |
| | } |
| |
|
| | let ToolClass = null; |
| | try { |
| | ToolClass = require(filePath); |
| | } catch (error) { |
| | logger.error(`[loadAndFormatTools] Error loading tool from ${filePath}:`, error); |
| | continue; |
| | } |
| |
|
| | if (!ToolClass || !(ToolClass.prototype instanceof Tool)) { |
| | continue; |
| | } |
| |
|
| | let toolInstance = null; |
| | try { |
| | toolInstance = new ToolClass({ override: true }); |
| | } catch (error) { |
| | logger.error( |
| | `[loadAndFormatTools] Error initializing \`${file}\` tool; if it requires authentication, is the \`override\` field configured?`, |
| | error, |
| | ); |
| | continue; |
| | } |
| |
|
| | if (!toolInstance) { |
| | continue; |
| | } |
| |
|
| | if (filter.has(toolInstance.name) && included.size === 0) { |
| | continue; |
| | } |
| |
|
| | if (included.size > 0 && !included.has(file) && !included.has(toolInstance.name)) { |
| | continue; |
| | } |
| |
|
| | const formattedTool = formatToOpenAIAssistantTool(toolInstance); |
| | tools.push(formattedTool); |
| | } |
| |
|
| | const basicToolInstances = [ |
| | new Calculator(), |
| | ...Object.values(oaiToolkit), |
| | ...Object.values(ytToolkit), |
| | ]; |
| | for (const toolInstance of basicToolInstances) { |
| | const formattedTool = formatToOpenAIAssistantTool(toolInstance); |
| | let toolName = formattedTool[Tools.function].name; |
| | toolName = getToolkitKey({ toolkits, toolName }) ?? toolName; |
| | if (filter.has(toolName) && included.size === 0) { |
| | continue; |
| | } |
| |
|
| | if (included.size > 0 && !included.has(toolName)) { |
| | continue; |
| | } |
| | tools.push(formattedTool); |
| | } |
| |
|
| | tools.push(ImageVisionTool); |
| |
|
| | return tools.reduce((map, tool) => { |
| | map[tool.function.name] = tool; |
| | return map; |
| | }, {}); |
| | } |
| |
|
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | function formatToOpenAIAssistantTool(tool) { |
| | return { |
| | type: Tools.function, |
| | [Tools.function]: { |
| | name: tool.name, |
| | description: tool.description, |
| | parameters: zodToJsonSchema(tool.schema), |
| | }, |
| | }; |
| | } |
| |
|
| | module.exports = { |
| | loadAndFormatTools, |
| | }; |
| |
|