// states/HandleChat.js const path = require('path'); const fs = require('fs'); const { getLastChat, getBot, getDB, setActiveTask, clearActiveTask } = require('../core/context'); const { logChatMessage } = require('../memory/chat'); const { chatWithAI } = require('../lib/ai-helper'); const config = require('../config.json'); module.exports = async function HandleChat() { const bot = getBot(); const db = getDB(); const { username, message } = getLastChat(); const msg = message.toLowerCase(); console.log(`[STATE] HandleChat: ${message}`); logChatMessage(db, username, message); const taskDir = path.join(__dirname, '../bot-tasks'); const availableTasks = fs.readdirSync(taskDir) .filter(f => f.endsWith('.js')) .map(f => f.replace('.js', '')); const matchedTask = availableTasks.find(task => msg.includes(task.replace(/-/g, ' '))); if (matchedTask) { try { const task = require(path.join(taskDir, matchedTask)); setActiveTask(matchedTask); bot.chat(`Okay, I’ll try to ${matchedTask.replace(/-/g, ' ')}.`); await task(bot, db, bot.chat); clearActiveTask(); return; } catch (err) { console.error(`[TASK ERROR] ${matchedTask}:`, err.message); bot.chat(`I couldn't complete the task "${matchedTask}".`); clearActiveTask(); return; } } const prompt = `Player said: "${message}". What task name should I execute (like 'find-flower', 'move-items')? Reply only with the task name or "none".`; const aiResponse = await chatWithAI(prompt, config.ai); const aiTask = aiResponse.trim().toLowerCase().replace(/\s+/g, '-'); if (aiTask !== 'none') { const taskPath = path.join(taskDir, `${aiTask}.js`); if (!fs.existsSync(taskPath)) { bot.chat(`I don’t know how to ${aiTask.replace(/-/g, ' ')} yet, learning now...`); const templatePath = path.join(__dirname, '../bot-tasks/TaskTemplate.js'); if (fs.existsSync(templatePath)) { let template = fs.readFileSync(templatePath, 'utf8'); template = template.replace(/task-template/g, aiTask); fs.writeFileSync(taskPath, template); console.log(`[AI] Task file generated from template: ${taskPath}`); // Ask AI to overwrite it with real logic const taskPrompt = ` You are a Mineflayer bot assistant. Generate a new Node.js module for this task: Task name: "${aiTask}" Use this exact export: module.exports = async function(bot, db, say) { ... } Use valid Mineflayer APIs. Do NOT use bot.inventory.find(). Use bot.inventory.items(). This task should do what the player just asked: "${message}" Only return valid code. No markdown. No explanation. `.trim(); const aiCode = await chatWithAI(taskPrompt, config.ai); if (aiCode.includes('module.exports')) { fs.writeFileSync(taskPath, aiCode.trim()); console.log(`[AI] Task file overwritten with AI code: ${taskPath}`); } else { console.warn(`[AI] Failed to get valid task code from model. Keeping the template.`); } } else { bot.chat(`Template not found. Cannot learn the task.`); return; } } try { const task = require(taskPath); setActiveTask(aiTask); await task(bot, db, bot.chat); clearActiveTask(); return; } catch (err) { console.error(`[TASK ERROR - AI GENERATED] ${aiTask}:`, err.message); bot.chat(`I tried to learn how to ${aiTask.replace(/-/g, ' ')}, but it didn’t work.`); clearActiveTask(); return; } } if (msg.includes(bot.username.toLowerCase())) { const response = await chatWithAI(message, config.ai); bot.chat(response); } };