import type { Config } from '../config/index.js'; import type { Lifecycle } from './lifecycle.js'; import type { AudioTranscriptionConfig } from '../models/media.js'; import { HookEngine } from '../hooks/index.js'; import { ToolRegistry, ToolExecutor, ToolPolicy, allBuiltinTools, createWebSearchTools, createProcessTools, ProcessManager, BrowserManager, createBrowserTools, createAudioTranscribeTool } from '../tools/index.js'; export interface ToolsDeps { config: Config; lifecycle: Lifecycle; hookEngine: HookEngine; } export interface ToolsResult { toolRegistry: ToolRegistry; toolExecutor: ToolExecutor; browserManager?: BrowserManager; } export function initTools(deps: ToolsDeps): ToolsResult { const { config, lifecycle, hookEngine } = deps; // Initialize tool registry and register all builtin tools const toolRegistry = new ToolRegistry(); for (const tool of allBuiltinTools) { toolRegistry.register(tool); } // Register web search tool if configured with credentials if (config.web_search.api_key || config.web_search.endpoint) { for (const tool of createWebSearchTools({ provider: config.web_search.provider, apiKey: config.web_search.api_key, endpoint: config.web_search.endpoint, maxResults: config.web_search.max_results, })) { toolRegistry.register(tool); } } // Initialize process manager and register process tools const processManager = new ProcessManager({ maxConcurrent: config.process.max_concurrent, maxRuntimeMinutes: config.process.max_runtime_minutes, bufferSize: config.process.buffer_size, }); for (const tool of createProcessTools(processManager)) { toolRegistry.register(tool); } lifecycle.onShutdown(async () => { await processManager.shutdown(); console.log('Process manager stopped'); }); // Register audio transcription tool if configured if (config.audio?.enabled && config.audio.provider) { const audioConfig: AudioTranscriptionConfig = { endpoint: config.audio.provider.endpoint, apiKey: config.audio.provider.api_key, model: config.audio.provider.model, }; const audioTool = createAudioTranscribeTool(audioConfig); toolRegistry.register(audioTool); console.log(`Audio transcription enabled (type=${config.audio.provider.type}, endpoint=${audioConfig.endpoint})`); } // Initialize browser manager and register browser tools (if enabled) const browserToolNames = ['browser.navigate', 'browser.screenshot', 'browser.click', 'browser.type', 'browser.content', 'browser.eval', 'browser.evaluate']; let browserManager: BrowserManager | undefined; if (config.browser?.enabled) { const manager = new BrowserManager({ executablePath: config.browser.executable_path, wsEndpoint: config.browser.ws_endpoint, headless: config.browser.headless, maxPages: config.browser.max_pages, defaultTimeout: config.browser.default_timeout, }); browserManager = manager; for (const tool of createBrowserTools(manager)) { toolRegistry.register(tool); } console.log(`Browser tools enabled (headless=${config.browser.headless})`); lifecycle.onShutdown(async () => { await manager.shutdown(); console.log('Browser manager stopped'); }); } else { console.log('Browser tools disabled (set browser.enabled=true to register browser.* tools)'); } const toolExecutor = new ToolExecutor(toolRegistry, hookEngine, { sensitiveMode: config.agents.sensitive_mode, immutableDenylist: config.agents.immutable_denylist.map((rule) => ({ tool: rule.tool, argsPattern: rule.args_pattern, reason: rule.reason, })), }); // Initialize tool policy from config const toolPolicy = new ToolPolicy(config.tools); toolRegistry.setPolicy(toolPolicy); const effectiveProfile = toolPolicy.getEffectiveProfile(); if (effectiveProfile !== 'full') { console.log(`Tool policy: profile=${effectiveProfile}, deny=[${config.tools.deny.join(', ')}]`); } if (config.browser?.enabled) { const allNames = toolRegistry.list().map((tool) => tool.name); const allowed = toolPolicy.resolveAllowedNames(allNames); const availableBrowserTools = browserToolNames.filter((name) => allowed.has(name)); if (availableBrowserTools.length === 0) { console.log('Browser tools are registered but blocked by tool policy (use tools.profile=coding/full or tools.allow).'); } else { console.log(`Browser tools available after policy: ${availableBrowserTools.join(', ')}`); } } return { toolRegistry, toolExecutor, browserManager }; }