UNPKG

tlnt

Version:

TLNT - HMS-Powered Multi-Agent Platform with Government Agency Analysis, Deep Research, and Enterprise-Ready Deployment. Self-optimizing multi-domain AI agent with continuous learning and enterprise-grade performance monitoring.

168 lines 5.8 kB
import { readdir, stat } from 'fs/promises'; import { resolve, join } from 'path'; import { pathToFileURL } from 'url'; import { homedir } from 'os'; export class PluginLoader { agentHub; loadedPlugins = new Map(); pluginPaths = []; constructor(agentHub) { this.agentHub = agentHub; this.setupPluginPaths(); } setupPluginPaths() { this.pluginPaths = [ resolve(homedir(), '.tlnt', 'plugins'), resolve(process.cwd(), '.tlnt', 'plugins'), ]; } async loadPlugins() { for (const pluginPath of this.pluginPaths) { try { await this.loadPluginsFromDirectory(pluginPath); } catch (error) { continue; } } await this.loadNpmPlugins(); } async loadPluginsFromDirectory(pluginDir) { try { const entries = await readdir(pluginDir); for (const entry of entries) { const entryPath = join(pluginDir, entry); const stats = await stat(entryPath); if (stats.isDirectory()) { await this.loadPluginFromPath(entryPath); } else if (entry.endsWith('.js') || entry.endsWith('.ts')) { await this.loadPluginFromFile(entryPath); } } } catch (error) { // Directory doesn't exist or can't be read } } async loadPluginFromPath(pluginPath) { const possibleFiles = ['index.js', 'index.ts', 'plugin.js', 'plugin.ts']; for (const file of possibleFiles) { const filePath = join(pluginPath, file); try { await stat(filePath); await this.loadPluginFromFile(filePath); return; } catch { continue; } } } async loadPluginFromFile(filePath) { try { const fileUrl = pathToFileURL(filePath).href; const module = await import(fileUrl); let plugin; if (typeof module.default === 'function') { const pluginId = this.getPluginIdFromPath(filePath); plugin = { id: pluginId, name: pluginId, version: '1.0.0', setup: module.default }; } else if (module.default && typeof module.default.setup === 'function') { plugin = module.default; } else { console.warn(`Plugin at ${filePath} does not export a valid plugin`); return; } await this.loadPlugin(plugin); } catch (error) { console.error(`Failed to load plugin from ${filePath}:`, error); } } async loadNpmPlugins() { try { const nodeModulesPath = resolve(process.cwd(), 'node_modules'); const entries = await readdir(nodeModulesPath); for (const entry of entries) { if (entry.startsWith('tlnt-plugin-')) { await this.loadNpmPlugin(entry); } } } catch (error) { // node_modules doesn't exist or can't be read } } async loadNpmPlugin(packageName) { try { const packageJsonPath = resolve(process.cwd(), 'node_modules', packageName, 'package.json'); const packageJson = JSON.parse(await import('fs').then(fs => fs.readFileSync(packageJsonPath, 'utf-8'))); let pluginPath; if (packageJson.plugin) { pluginPath = resolve(process.cwd(), 'node_modules', packageName, packageJson.plugin); } else if (packageJson.main) { pluginPath = resolve(process.cwd(), 'node_modules', packageName, packageJson.main); } else { pluginPath = resolve(process.cwd(), 'node_modules', packageName, 'index.js'); } await this.loadPluginFromFile(pluginPath); } catch (error) { console.error(`Failed to load npm plugin ${packageName}:`, error); } } async loadPlugin(plugin) { if (this.loadedPlugins.has(plugin.id)) { console.warn(`Plugin ${plugin.id} is already loaded`); return; } try { await plugin.setup(this.agentHub); this.loadedPlugins.set(plugin.id, plugin); console.log(`Loaded plugin: ${plugin.name} v${plugin.version}`); } catch (error) { console.error(`Failed to setup plugin ${plugin.id}:`, error); } } async unloadPlugin(pluginId) { const plugin = this.loadedPlugins.get(pluginId); if (!plugin) { throw new Error(`Plugin ${pluginId} is not loaded`); } if (plugin.teardown) { try { await plugin.teardown(); } catch (error) { console.error(`Error during plugin ${pluginId} teardown:`, error); } } this.loadedPlugins.delete(pluginId); } async reloadPlugin(pluginId) { await this.unloadPlugin(pluginId); await this.loadPlugins(); } listPlugins() { return Array.from(this.loadedPlugins.values()); } getPlugin(pluginId) { return this.loadedPlugins.get(pluginId); } getPluginIdFromPath(filePath) { const parts = filePath.split(/[/\\]/); const fileName = parts[parts.length - 1]; return fileName.replace(/\.(js|ts)$/, ''); } } //# sourceMappingURL=pluginLoader.js.map