"""Обработчики режимов: Chat, Skill, Build""" import threading import logging from datetime import datetime from typing import Dict, Any from .state import STATE from .config import API_KEY, API_BASE from .universal_agent import UniversalAgent from .conductor_engine import ConductorEngine from .skill_orchestrator import SkillOrchestrator from .process_manager import PROCESS_MANAGER from .notification_system import NOTIFICATIONS from .helpers import parse_skill_args, build_skill_prompt, parse_build_args from .telegram_utils import send_tg from . import INTERNET_AGENT from .interpreter_config import configure_interpreter_for_model class RateLimiter: def __init__(self): self.user_requests = {} self.max_requests = 5 self.time_window = 10 # seconds self.logger = logging.getLogger(__name__) def check_rate_limit(self, chat_id: str) -> bool: now = datetime.now().timestamp() requests = self.user_requests.get(chat_id, []) # Remove old requests requests = [t for t in requests if now - t < self.time_window] if len(requests) >= self._get_limit(chat_id): self.logger.warning(f"Rate limit exceeded for chat_id {chat_id}") return False requests.append(now) self.user_requests[chat_id] = requests return True def _get_limit(self, chat_id: str) -> int: # Allow higher limits for admin or premium users if needed return self.max_requests rate_limiter = RateLimiter() logger = logging.getLogger(__name__) def configure_interpreter_for_model(model_name: str): """Deprecated: Use from interpreter_config.py instead.""" return configure_interpreter_for_model(model_name, STATE, API_KEY, API_BASE) def run_chat_mode(chat_id: str, text: str, file_context: str = "") -> str: if not rate_limiter.check_rate_limit(chat_id): send_tg(chat_id, "╭───────────────────╮\n │ ⚠️ ʀᴀᴛᴇ ʟɪᴍɪᴛ │\n ├───────────────────┤\n │ Try again later ☕ │\n╰───────────────────╯") return "Rate limited" def chat_task(): STATE.cancel_flag = False STATE.current_mode = "chat" send_tg( chat_id, "╭───────────────────╮\n" " │ 🧠 ᴄᴏɴᴅᴜᴄᴛᴏʀ ᴀᴄᴛɪᴠᴇ │\n" "├───────────────────┤\n" " │ Analyzing request │\n" "╰───────────────────╯" ) try: conductor_engine = ConductorEngine(STATE) result = conductor_engine.orchestrate(text + file_context, chat_id=chat_id) if not STATE.cancel_flag: send_tg(chat_id, result) STATE.add_to_history("chat", "assistant", result) except Exception as e: if not STATE.cancel_flag: send_tg(chat_id, f"▸ ⚠️ ᴄʜᴀᴛ ᴇʀʀᴏʀ\n{str(e)[:500]}") logger.error(f"Chat mode error for {chat_id}: {e}", exc_info=True) t = threading.Thread(target=chat_task) PROCESS_MANAGER.register_thread(t) t.start() return "╭───────────────────╮\n │ ☕ ᴄʜᴀᴛ ᴍᴏᴅᴇ sᴛᴀʀᴛᴇᴅ │\n╰───────────────────╯" def run_skill_mode(chat_id: str, text: str, file_context: str = "") -> str: if not rate_limiter.check_rate_limit(chat_id): send_tg(chat_id, "▸ ⚠️ ʀᴀᴛᴇ ʟɪᴍɪᴛ\nTry again later.") return "Rate limited" params, clean_text = parse_skill_args(text) agents = params.get("agents", []) use_internet = params.get("internet", False) def skill_task(): STATE.cancel_flag = False STATE.current_mode = "skill" send_tg( chat_id, "╭───────────────────╮\n" " │ 🤖 sᴋɪʟʟ ᴍᴏᴅᴇ │\n" "├───────────────────┤\n" " │ Agents activated │\n" "╰───────────────────╯" ) if use_internet: search_results = INTERNET_AGENT.search_web(clean_text[:200]) if search_results: web_context = "\n\n🌐 ɪɴᴛᴇʀɴᴇᴛ ʀᴇsᴜʟᴛs(。◕‿◕。)\n" + "\n".join( f"▹ {r['title'][:50]}... → {r['snippet'][:100]}..." for r in search_results[:3] ) file_context += web_context try: orchestrator = SkillOrchestrator(STATE) result = orchestrator.execute_with_agents(chat_id, clean_text, file_context, agents) if not STATE.cancel_flag: send_tg(chat_id, result) STATE.add_to_history("skill", "assistant", result) except Exception as e: if not STATE.cancel_flag: send_tg(chat_id, f"▸ ⚠️ sᴋɪʟʟ ᴇʀʀᴏʀ\n{str(e)[:500]}") logger.error(f"Skill mode error for {chat_id}: {e}", exc_info=True) t = threading.Thread(target=skill_task) PROCESS_MANAGER.register_thread(t) t.start() return "╭───────────────────╮\n │ 🧩 sᴋɪʟʟ ᴍᴏᴅᴇ sᴛᴀʀᴛᴇᴅ │\n╰───────────────────╯"