'use strict'; const conf = require('../conf'); const {sleep} = require('../utils'); const { ProviderFactory } = require('./ai/providers'); class Ai{ constructor(args){ this.bot = args.bot; this.promptName = args.promptName; this.prompCustom = args.prompCustom || ''; this.intervalLength = args.intervalLength || 30; this.intervalStop; this.messageListener; this.provider = null; // Bot-specific AI config (overrides global config) this.botConfig = args.botConfig || {}; } // Get merged config: bot-specific settings override global settings __getConfig() { return { ...conf.ai, // Global defaults ...this.botConfig, // Bot-specific overrides }; } async init(){ this.bot.on('onReady', async (argument)=>{ try{ await this.start(); let messages = ['']; this.messageListener = this.bot.on('message', (message, type)=>{ if(type === 'game_info') return; if(message.toString().startsWith('<') && message.toString().split('>')[0].includes(this.bot.bot.entity.username)){ console.log('message blocked from message array') return; } console.log(`Message ${type}: ${message.toString()}`) messages.push('>', message.toString()); }); this.intervalStop = setInterval(async ()=>{ let result; try{ result = await this.chat(JSON.stringify({ messages, currentTime:Date.now()+1} )); }catch(error){ console.log('error AI API', error, result); messages = []; return ; } try{ messages = ['']; if(!this.provider.getResponse(result)) return; for(let message of JSON.parse(this.provider.getResponse(result))){ console.log('toSay', message.delay, message.text); if(message.text === '___') return; setTimeout(async (message)=>{ await this.bot.sayAiSafe(message.text); }, message.delay*1000, message); } }catch(error){ console.log('Error in AI message loop', error, result); try { if(result && this.provider.getResponse(result)){ console.log(this.provider.getResponse(result)) } } catch(e) { // Ignore } } }, this.intervalLength*1000); }catch(error){ console.log('error in onReady', error); } }); } async unload(){ if(this.intervalStop){ clearInterval(this.intervalStop); this.intervalStop = undefined; } if(this.messageListener){ this.messageListener(); } if(this.provider){ await this.provider.close(); } return true; } async start(history){ const config = this.__getConfig(); let bulbaItems = {}; console.log(`${this.bot.name} AI config:`, { provider: config.provider, model: config.model, promptName: this.promptName, baseUrl: config.baseUrl, }); const prompt = conf.ai.prompts[this.promptName]( this.bot.bot.entity.username, config.interval, Object.values(this.bot.getPlayers()).map(player=>`<[${player.lvl}] ${player.username}>`).join('\n'), bulbaItems, this.prompCustom, ); // Create the provider instance with merged config and prompt this.provider = ProviderFactory.create({ ...config, prompt: prompt, }); await this.provider.start(history); console.log(`${this.bot.name} AI ${config.provider} provider started (model: ${config.model})`); } async chat(message, retryCount=0){ console.log(`chat ${this.bot.name}`, retryCount) try{ let result = await this.provider.chat(message); return result }catch(error){ console.log('AI chat error', error) throw error; } } } module.exports = Ai;