UNPKG

@tomisakae/tomibot

Version:

TomiBot - AI Chatbot CLI với Google Genkit. Một chatbot AI thông minh chạy trên command line với giao diện đẹp.

350 lines (346 loc) 13.9 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.TomiBot = void 0; const types_1 = require("./types"); const config_1 = require("./config"); const logger_util_1 = require("../utils/logger.util"); const genkit_service_1 = require("../services/ai/genkit.service"); const chat_service_1 = require("../services/chat/chat.service"); const menu_component_1 = require("../ui/components/menu.component"); const status_component_1 = require("../ui/components/status.component"); const display_util_1 = require("../ui/utils/display.util"); class TomiBot { constructor() { this._isInitialized = false; this._isRunning = false; this._logger = new logger_util_1.Logger('TomiBot'); const aiService = new genkit_service_1.AIServiceImpl(); const chatService = new chat_service_1.ChatServiceImpl(aiService); this._state = { isRunning: false, config: config_1.config.botConfig, services: { ai: aiService, chat: chatService, }, }; this._menuComponent = new menu_component_1.MenuComponent(); this._statusComponent = new status_component_1.StatusComponent(); } async initialize() { if (this._isInitialized) { this._logger.warn('Bot is already initialized'); return; } try { this._logger.info('Initializing TomiBot...'); config_1.config.validateConfiguration(); this._logger.debug('Configuration validated'); await this._state.services.ai.initialize(); this._logger.debug('AI service initialized'); if ('initialize' in this._state.services.chat) { await this._state.services.chat.initialize(); this._logger.debug('Chat service initialized'); } this._isInitialized = true; this._logger.info('TomiBot initialized successfully'); } catch (error) { this._logger.error('Failed to initialize TomiBot:', error); throw new types_1.BotError('Initialization failed', 'INIT_ERROR', { originalError: error, }); } } isInitialized() { return this._isInitialized; } async dispose() { this._logger.info('Disposing TomiBot...'); try { if (this._isRunning) { await this.stop(); } if ('dispose' in this._state.services.ai) { await this._state.services.ai.dispose(); } if ('dispose' in this._state.services.chat) { await this._state.services.chat.dispose(); } this._isInitialized = false; this._logger.info('TomiBot disposed successfully'); } catch (error) { this._logger.error('Error during disposal:', error); throw error; } } async start() { if (!this._isInitialized) { await this.initialize(); } if (this._isRunning) { this._logger.warn('Bot is already running'); return; } try { this._logger.info('Starting TomiBot...'); this._isRunning = true; this._state.isRunning = true; await this.showWelcomeScreen(); await this.checkAndConfigureAPIKey(); await this.showMainMenu(); } catch (error) { this._logger.error('Error starting bot:', error); this._isRunning = false; this._state.isRunning = false; throw error; } } async stop() { if (!this._isRunning) { return; } this._logger.info('Stopping TomiBot...'); try { if (this._state.currentSession) { await this._state.services.chat.endSession(this._state.currentSession.id); delete this._state.currentSession; } this._isRunning = false; this._state.isRunning = false; this._logger.info('TomiBot stopped successfully'); } catch (error) { this._logger.error('Error stopping bot:', error); throw error; } } async showWelcomeScreen() { console.clear(); console.log(await this.createTitle()); console.log(this._statusComponent.renderWelcomeBox(this._state.config)); } async checkAndConfigureAPIKey() { if (!config_1.config.hasValidAPIKey()) { this._logger.warn('API key not configured'); console.log('\n⚠️ GEMINI_API_KEY chưa được cấu hình!'); console.log('💡 Vui lòng cấu hình API key để sử dụng AI chatbot\n'); const shouldConfigure = await this.promptForAPIKeyConfiguration(); if (shouldConfigure) { await this.configureAPIKey(); } else { console.log('⚠️ Chatbot sẽ chạy ở chế độ demo (không có AI)'); } } else { this._logger.info('API key is configured'); console.log('✅ GEMINI_API_KEY đã được cấu hình'); } } async showMainMenu() { while (this._isRunning) { try { const choice = await this._menuComponent.showMainMenu(); await this.handleMenuChoice(choice); } catch (error) { this._logger.error('Error in main menu:', error); console.log('❌ Đã xảy ra lỗi. Vui lòng thử lại.'); } } } async handleMenuChoice(choice) { switch (choice) { case 'chat': await this.startChatSession(); break; case 'status': await this.showSystemStatus(); break; case 'config': await this.showConfigurationMenu(); break; case 'help': await this.showHelp(); break; case 'exit': await this.exitApplication(); break; default: console.log('❌ Lựa chọn không hợp lệ'); } } async createTitle() { return 'TomiBot ASCII Art Title'; } async promptForAPIKeyConfiguration() { return false; } async configureAPIKey() { this._logger.info('API key configuration requested'); console.log('\n' + display_util_1.DisplayUtils.info('🔑 Cấu hình GEMINI_API_KEY')); console.log(display_util_1.DisplayUtils.info('💡 Bạn có thể lấy API key tại: https://aistudio.google.com/app/apikey')); console.log(); const apiKey = await this._menuComponent.promptPassword('Nhập GEMINI_API_KEY của bạn:', (input) => { if (!input.trim()) return 'API key không được để trống'; if (input.length < 10) return 'API key quá ngắn'; return true; }); config_1.config.updateAIConfig({ apiKey }); if ('forceReinitialize' in this._state.services.ai) { this._state.services.ai.forceReinitialize(); } console.log('\n' + display_util_1.DisplayUtils.success('✅ API key đã được cấu hình thành công!')); console.log(display_util_1.DisplayUtils.info('💡 Để lưu vĩnh viễn, hãy thêm vào file .env hoặc system environment')); await this._menuComponent.pauseForUser(); } async runChatLoop() { let isRunning = true; while (isRunning) { try { const message = await this._menuComponent.promptText('\n👤 Bạn:'); if (!message.trim()) continue; const lowerMessage = message.toLowerCase().trim(); if (['exit', 'quit', 'bye', '/exit', '/quit', '/bye'].includes(lowerMessage)) { isRunning = false; break; } console.log('\n🤖 TomiBot đang suy nghĩ...'); const response = await this._state.services.chat.sendMessage(message); if (response.success) { console.log(`\n🤖 TomiBot:\n ${response.content}`); if (response.metadata?.['shouldExit']) { isRunning = false; } } else { console.log('\n' + display_util_1.DisplayUtils.error(`❌ ${response.error || 'Không thể nhận phản hồi từ AI'}`)); } } catch (error) { if (error.name === 'ExitPromptError') { isRunning = false; break; } console.log('\n' + display_util_1.DisplayUtils.error(`❌ Lỗi: ${error.message || error}`)); } } if (this._state.currentSession) { await this._state.services.chat.endSession(this._state.currentSession.id); delete this._state.currentSession; } console.log('\n' + display_util_1.DisplayUtils.success('👋 Đã thoát khỏi phiên chat')); } async startChatSession() { this._logger.info('Chat session requested'); if (!this._state.services.ai.isReady()) { console.log('\n' + display_util_1.DisplayUtils.error('❌ AI service chưa sẵn sàng. Vui lòng kiểm tra API key.')); await this._menuComponent.pauseForUser(); return; } try { const session = await this._state.services.chat.startSession(); this._state.currentSession = session; console.log('\n' + display_util_1.DisplayUtils.success('🚀 Phiên chat đã bắt đầu!')); console.log(display_util_1.DisplayUtils.info('💡 Gõ tin nhắn để trò chuyện với AI')); console.log(display_util_1.DisplayUtils.info('💡 Gõ "/exit" để thoát chat')); console.log(display_util_1.DisplayUtils.separator('─', 60, 'cyan')); await this.runChatLoop(); } catch (error) { this._logger.error('Error starting chat session:', error); console.log('\n' + display_util_1.DisplayUtils.error(`❌ Lỗi khi bắt đầu chat: ${error}`)); } console.log('\n' + display_util_1.DisplayUtils.info('📱 Đã trở về menu chính')); } async showSystemStatus() { console.log(this._statusComponent.renderSystemStatus(this._state)); } async showConfigurationMenu() { this._logger.info('Configuration menu requested'); const choice = await this._menuComponent.showConfigMenu(); switch (choice) { case 'apikey': await this.configureAPIKey(); break; case 'clear': this._state.services.ai.clearHistory(); console.log('\n' + display_util_1.DisplayUtils.success('✅ Đã xóa lịch sử hội thoại!')); await this._menuComponent.pauseForUser(); break; case 'info': console.log('\n' + this._statusComponent.renderConfigurationStatus(this._state.config)); await this._menuComponent.pauseForUser(); break; case 'ui': console.log('\n' + display_util_1.DisplayUtils.info('🎨 Tính năng cài đặt giao diện sẽ được thêm sau')); await this._menuComponent.pauseForUser(); break; case 'back': break; } } async showHelp() { this._logger.info('Help requested'); const helpContent = ` 🤖 TomiBot - AI Chatbot CLI với Google Genkit 📋 Tính năng chính: • Chat với AI sử dụng Google Gemini model • Giao diện CLI đẹp và thân thiện • Lưu lịch sử hội thoại trong phiên • Cấu hình API key dễ dàng • Kiểm tra trạng thái hệ thống 🎯 Cách sử dụng: 1. Cấu hình GEMINI_API_KEY (lấy từ Google AI Studio) 2. Chọn "Bắt đầu Chat với AI" từ menu chính 3. Trò chuyện với TomiBot bằng tiếng Việt 4. Sử dụng các lệnh đặc biệt trong chat: • /exit, /quit, /bye - Thoát chat • /clear - Xóa lịch sử • /history - Xem lịch sử • /status - Xem trạng thái • /help - Trợ giúp 🔗 Liên kết hữu ích: • Google AI Studio: https://aistudio.google.com/app/apikey • Genkit Documentation: https://firebase.google.com/docs/genkit 💡 Mẹo: • Sử dụng Ctrl+C để thoát nhanh • API key chỉ lưu trong phiên hiện tại • Để lưu vĩnh viễn, thêm vào system environment `; console.log('\n' + display_util_1.DisplayUtils.createBox(helpContent.trim(), { title: '❓ Trợ giúp - TomiBot', borderColor: 'yellow', padding: 1, })); await this._menuComponent.pauseForUser(); } async exitApplication() { console.log('\n👋 Cảm ơn bạn đã sử dụng TomiBot!'); console.log('🌟 Hẹn gặp lại bạn lần sau! 🌟\n'); await this.stop(); process.exit(0); } get state() { return { ...this._state }; } get isRunning() { return this._isRunning; } get config() { return config_1.config.botConfig; } } exports.TomiBot = TomiBot; //# sourceMappingURL=bot.js.map