UNPKG

langcode

Version:

A Plugin-Based Framework for Managing and Using LangChain

181 lines (162 loc) 5.2 kB
import { LogLevel, logLevels, Plugin, plugins, PluginTypeMap } from "../types"; import { Logger } from "./Logger"; import { EventEmitter } from "events"; interface HistoryItem { timestamp?: string; level: LogLevel; phase: "init" | "run" | "expose"; pluginName?: string; message: string; data?: any; elapsedMs?: number; } export class PluginRunner extends EventEmitter { private activePlugins = new Map<string, Plugin>(); private logger: Logger; private strict?: boolean; private tag = "langcode"; private histories: HistoryItem[] = []; private historyLimit = 1_000; constructor(debug = false, logFile: string | null = null, strict?: boolean) { super(); this.logger = new Logger({ debug: debug, filePath: logFile, tag: this.tag, }); this.strict = strict; logLevels.forEach((level: LogLevel) => { const loggerEvent = `${this.tag}:${level}`; this.logger.on(loggerEvent, (payload) => { this.emit(loggerEvent, payload); this.emit(this.tag, payload); }); }); } private pushHistory(item: HistoryItem) { const itema = {...item,timestamp: new Date().toISOString()} if (this.histories.length >= this.historyLimit) this.histories.shift(); this.histories.push(itema); // this.logger[item.level](`🔌 history added: ${JSON.stringify(itema,null,2)}`); } public history() { return [...this.histories]; } async initialize( configList: { pluginName: plugins; config: Record<string, any> }[] ) { for (const { pluginName, config } of configList) { try { const pluginModule = await import(`../plugins/${pluginName}/${pluginName}Plugin`); const pluginInstance: Plugin = new pluginModule.default(); this.logger.info(`🔌 Başlatılıyor: ${pluginName}`); this.pushHistory({ level: "info", phase: "init", pluginName, message:`🔌 Başlatılıyor: ${pluginName}`, }); await pluginInstance.init(config); this.activePlugins.set(pluginName, pluginInstance); this.logger.success(`✅ Aktif: ${pluginName}`); this.pushHistory({ level: "success", phase: "init", pluginName, message:`✅ Aktif: ${pluginName}`, }); } catch (err) { this.logger.error(`❌ Plugin '${pluginName}' yüklenemedi:`, err); this.pushHistory({ level:"error", phase: "init", pluginName, message:`❌ Plugin '${pluginName}' yüklenemedi:`, data:err }); if (this.strict) { throw {error:err,history:this.histories}; } } } } async run<T extends keyof PluginTypeMap>( pluginName: T, args: PluginTypeMap[T]["runArgs"] ): Promise<PluginTypeMap[T]["return"]> { const plugin = this.activePlugins.get(pluginName); if (!plugin) { this.logger.error(`Plugin '${pluginName}' aktif değil.`); this.pushHistory({ level: "error", phase: "run", pluginName, message:`Plugin '${pluginName}' aktif değil.` }); if (this.strict) { throw {error:`Plugin '${pluginName}' aktif değil.`,history:this.histories}; } } this.logger.info(`⏳ Çalıştırılıyor: ${pluginName}`, args); this.pushHistory({ level: "info", phase: "run", pluginName, data:args, message:`⏳ Çalıştırılıyor: ${pluginName}` }); const start = Date.now(); const result = await plugin?.run(args); this.logger.success( `✅ Tamamlandı (${pluginName}) - ${Date.now() - start}ms` ); this.logger.debug("📤 Cevap:", result); this.pushHistory({ level: "success", phase: "run", pluginName, data:result, message: `✅ Tamamlandı (${pluginName}) - ${Date.now() - start}ms` }); return result; } async getExpose<T extends keyof PluginTypeMap>( pluginName: T ): Promise<PluginTypeMap[T]["expose"] | undefined> { const plugin = this.activePlugins.get(pluginName); if (!plugin) { this.logger.error(`Plugin '${pluginName}' aktif değil.`); this.pushHistory({ level: "error", phase: "expose", pluginName, message: `Plugin '${pluginName}' aktif değil.` }); if (this.strict) { throw {error:`Plugin '${pluginName}' aktif değil.`,history:this.histories}; } } if (typeof plugin?.expose === "function") { this.pushHistory({ level: "success", phase: "expose", pluginName, message: `Expose başarılı` }); return plugin.expose() as PluginTypeMap[T]["expose"]; } this.logger.error(`Plugin '${pluginName}' expose() sağlamıyor.`); this.pushHistory({ level: "error", phase: "expose", pluginName, message: `Plugin '${pluginName}' expose() sağlamıyor.` }); if (this.strict) { throw {error:`Plugin '${pluginName}' expose() sağlamıyor.`,history:this.histories}; } } } function capitalize(str: string) { return str.charAt(0).toUpperCase() + str.slice(1); }