From af262198a6af037e7ecc675a59bfe9152fbc3abb Mon Sep 17 00:00:00 2001 From: Antigravity Bot Date: Sun, 30 Aug 2026 09:33:46 +0330 Subject: [PATCH] =?UTF-8?q?AI=20Update:=20=D8=A8=D8=B1=D9=88=20=D9=81?= =?UTF-8?q?=D8=A7=D8=B2=20=D8=A8=D8=B9=D8=AF=DB=8C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- projects/8896969833/test | 1 + telegram-agy-bot/agy_engine.py | 10 ++ telegram-agy-bot/bot.py | 291 +++++++++++++++++++++++++++++++- telegram-agy-bot/bot_actions.py | 170 +++++++++++++++++++ telegram-agy-bot/data/memory.db | Bin 28672 -> 28672 bytes telegram-agy-bot/invites.json | 13 ++ telegram-agy-bot/sessions.json | 54 +++++- 7 files changed, 524 insertions(+), 15 deletions(-) create mode 160000 projects/8896969833/test diff --git a/projects/8896969833/test b/projects/8896969833/test new file mode 160000 index 0000000..4bd5846 --- /dev/null +++ b/projects/8896969833/test @@ -0,0 +1 @@ +Subproject commit 4bd584607e1ad981673c64812ca8bcd8837543ca diff --git a/telegram-agy-bot/agy_engine.py b/telegram-agy-bot/agy_engine.py index f4d2ff4..adf51b6 100644 --- a/telegram-agy-bot/agy_engine.py +++ b/telegram-agy-bot/agy_engine.py @@ -1326,6 +1326,16 @@ class AGYEngine: except Exception as ex: logger.warning(f"Failed to load bot actions instruction: {ex}") + # AI Long-Term Persistent Memory Instruction (Global + User Private) + try: + from memory_manager import memory_manager + memory_instruction = memory_manager.format_memories_for_prompt(user_id=session.chat_id) + if memory_instruction: + system_instructions.append(memory_instruction) + except Exception as mex: + logger.warning(f"Failed to load memory instructions for chat {session.chat_id}: {mex}") + + if system_instructions: effective_prompt = "\n\n".join(system_instructions) + "\n\n" + prompt diff --git a/telegram-agy-bot/bot.py b/telegram-agy-bot/bot.py index 19017ab..6a0309f 100644 --- a/telegram-agy-bot/bot.py +++ b/telegram-agy-bot/bot.py @@ -228,15 +228,18 @@ def build_main_dashboard(chat_id: int) -> tuple[str, InlineKeyboardMarkup]: InlineKeyboardButton("⏰ زمان‌بندی", callback_data="btn_tasks_menu"), ], [ + InlineKeyboardButton("🧠 حافظه هوش مصنوعی", callback_data="btn_memory_menu"), InlineKeyboardButton("📈 سهمیه مصرف (AGY)", callback_data="btn_usage_menu"), + ], + [ InlineKeyboardButton("🖥 سخت‌افزار سرور", callback_data="btn_hw_menu"), - ], - [ InlineKeyboardButton("🐙 گیت (Gitea)", callback_data="btn_git_menu"), - InlineKeyboardButton("⚙️ تنظیمات و مدل", callback_data="btn_settings_menu"), ], [ + InlineKeyboardButton("⚙️ تنظیمات و مدل", callback_data="btn_settings_menu"), InlineKeyboardButton("🔄 گفتگوی جدید", callback_data="btn_restart"), + ], + [ InlineKeyboardButton("📖 راهنما", callback_data="btn_help_menu"), ], ] @@ -264,15 +267,18 @@ def build_main_dashboard(chat_id: int) -> tuple[str, InlineKeyboardMarkup]: InlineKeyboardButton("⏰ Schedule", callback_data="btn_tasks_menu"), ], [ + InlineKeyboardButton("🧠 AI Memory", callback_data="btn_memory_menu"), InlineKeyboardButton("📈 Quota & Usage", callback_data="btn_usage_menu"), + ], + [ InlineKeyboardButton("🖥 Server Hardware", callback_data="btn_hw_menu"), - ], - [ InlineKeyboardButton("🐙 Git (Gitea)", callback_data="btn_git_menu"), - InlineKeyboardButton("⚙️ Settings & Model", callback_data="btn_settings_menu"), ], [ + InlineKeyboardButton("⚙️ Settings & Model", callback_data="btn_settings_menu"), InlineKeyboardButton("🔄 New Chat", callback_data="btn_restart"), + ], + [ InlineKeyboardButton("📖 Bot Guide", callback_data="btn_help_menu"), ], ] @@ -764,6 +770,9 @@ def build_settings_menu(chat_id: int) -> tuple[str, InlineKeyboardMarkup]: [ InlineKeyboardButton("⚡ سطح تفکر / استدلال (Effort)", callback_data="btn_effort_menu"), ], + [ + InlineKeyboardButton("🧠 مدیریت حافظه هوش مصنوعی", callback_data="btn_memory_menu"), + ], [ InlineKeyboardButton("🌐 زبان پاسخ‌دهی", callback_data="btn_lang_menu"), InlineKeyboardButton("📊 وضعیت و کانتکست", callback_data="btn_status_menu"), @@ -793,6 +802,9 @@ def build_settings_menu(chat_id: int) -> tuple[str, InlineKeyboardMarkup]: [ InlineKeyboardButton("⚡ Reasoning Effort", callback_data="btn_effort_menu"), ], + [ + InlineKeyboardButton("🧠 AI Memory Management", callback_data="btn_memory_menu"), + ], [ InlineKeyboardButton("🌐 Response Language", callback_data="btn_lang_menu"), InlineKeyboardButton("📊 Status & Tokens", callback_data="btn_status_menu"), @@ -1093,6 +1105,126 @@ def process_ai_schedule_actions(raw_text: str, chat_id: int, project_name: str, return processed_text, created_tasks +def build_memory_menu(chat_id: int, view_type: str = "private", page: int = 0) -> tuple[str, InlineKeyboardMarkup]: + """Builds interactive AI Long-Term Memory manager dashboard with tabs (private vs global), pagination, and deletion.""" + from memory_manager import memory_manager + session = session_manager.get_or_create(chat_id) + is_fa = (session.language or "").lower() in ("fa", "farsi", "persian", "🇮🇷 persian / farsi (فارسی)") + is_admin_user = settings.is_admin(chat_id) + + view_type = "global" if view_type == "global" else "private" + + if view_type == "global": + memories = memory_manager.get_global_memories(limit=100) + else: + memories = memory_manager.get_user_memories(user_id=chat_id, limit=100) + + total_cnt = len(memories) + page_size = 5 + max_pages = max(1, (total_cnt + page_size - 1) // page_size) if total_cnt > 0 else 1 + page = max(0, min(page, max_pages - 1)) + paged_memories = memories[page * page_size : (page + 1) * page_size] + + stats = memory_manager.get_stats() + + if is_fa: + tab_name = "🌐 خاطرات عمومی (کل سیستم)" if view_type == "global" else "👤 خاطرات خصوصی (اختصاصی شما)" + header = ( + f"🧠 کنترل‌پنل حافظه هوشمند هوش مصنوعی (AI Long-Term Memory)\n\n" + f"• 📂 بخش فعال: {tab_name}\n" + f"• 📊 آمار کل: {stats['total_memories']} خاطره ({stats['global_memories']} عمومی | {stats['private_memories']} خصوصی)\n\n" + ) + if not memories: + body = ( + f"ℹ️ در این بخش هنوز هیچ خاطره‌ای ثبت نشده است.\n\n" + f"💡 یادگیری خودکار: هوش مصنوعی به صورت خودکار در خلال گفتگوها، عادات، نام و نکات مهم شما را استخراج و ذخیره می‌کند." + ) + else: + body_lines = [f"لیست خاطرات (صفحه {page + 1} از {max_pages}):\n"] + for idx, m in enumerate(paged_memories, start=page * page_size + 1): + cat_badge = f"[{m.category}]" if m.category and m.category != "general" else "" + body_lines.append( + f"{idx}. 🔑 {escape_html(m.key)} {cat_badge}\n" + f" 📝 {escape_html(m.content)}" + ) + body = "\n\n".join(body_lines) + else: + tab_name = "🌐 Global System Memory" if view_type == "global" else "👤 Private User Memory" + header = ( + f"🧠 AI Long-Term Memory Dashboard\n\n" + f"• 📂 Active Tab: {tab_name}\n" + f"• 📊 Stats: {stats['total_memories']} total ({stats['global_memories']} global | {stats['private_memories']} private)\n\n" + ) + if not memories: + body = "ℹ️ No memories recorded in this section yet.\n\n💡 The AI automatically extracts durable facts and preferences during conversations." + else: + body_lines = [f"Memories list (Page {page + 1} of {max_pages}):\n"] + for idx, m in enumerate(paged_memories, start=page * page_size + 1): + cat_badge = f"[{m.category}]" if m.category and m.category != "general" else "" + body_lines.append( + f"{idx}. 🔑 {escape_html(m.key)} {cat_badge}\n" + f" 📝 {escape_html(m.content)}" + ) + body = "\n\n".join(body_lines) + + text = f"{header}{body}" + + # Build keyboard + keyboard = [] + + # 1. Tab buttons + tab_priv_text = "👤 خاطرات من (خصوصی) ✓" if view_type == "private" else "👤 خاطرات من (خصوصی)" + tab_glob_text = "🌐 خاطرات عمومی سیستم ✓" if view_type == "global" else "🌐 خاطرات عمومی سیستم" + if not is_fa: + tab_priv_text = "👤 My Memory ✓" if view_type == "private" else "👤 My Memory" + tab_glob_text = "🌐 Global Memory ✓" if view_type == "global" else "🌐 Global Memory" + + keyboard.append([ + InlineKeyboardButton(tab_priv_text, callback_data="mem_tab:private:0"), + InlineKeyboardButton(tab_glob_text, callback_data="mem_tab:global:0"), + ]) + + # 2. Item delete buttons (for paged memories) + can_delete_current = (view_type == "private") or (view_type == "global" and is_admin_user) + if can_delete_current and paged_memories: + del_row = [] + for idx, m in enumerate(paged_memories, start=page * page_size + 1): + del_row.append(InlineKeyboardButton(f"🗑️ #{idx}", callback_data=f"mem_del_conf:{m.id}:{view_type}:{page}")) + if len(del_row) == 5: + keyboard.append(del_row) + del_row = [] + if del_row: + keyboard.append(del_row) + + # 3. Pagination row + if max_pages > 1: + pag_row = [] + if page > 0: + pag_row.append(InlineKeyboardButton("⬅️ قبلی" if is_fa else "⬅️ Prev", callback_data=f"mem_tab:{view_type}:{page - 1}")) + pag_row.append(InlineKeyboardButton(f"📄 {page + 1}/{max_pages}", callback_data="noop")) + if page < max_pages - 1: + pag_row.append(InlineKeyboardButton("بعدی ➡️" if is_fa else "Next ➡️", callback_data=f"mem_tab:{view_type}:{page + 1}")) + keyboard.append(pag_row) + + # 4. Clear memory button (if applicable) + action_row = [] + if can_delete_current and total_cnt > 0: + clear_label = "🧹 پاکسازی این بخش" if is_fa else "🧹 Clear this section" + action_row.append(InlineKeyboardButton(clear_label, callback_data=f"mem_clear_conf:{view_type}")) + + action_row.append(InlineKeyboardButton("🔄 تازه‌سازی" if is_fa else "🔄 Refresh", callback_data=f"mem_tab:{view_type}:{page}")) + if action_row: + keyboard.append(action_row) + + # 5. Main menu button + keyboard.append([ + InlineKeyboardButton("🏠 منوی اصلی" if is_fa else "🏠 Main Dashboard", callback_data="btn_dashboard"), + InlineKeyboardButton("⚙️ تنظیمات" if is_fa else "⚙️ Settings", callback_data="btn_settings_menu"), + ]) + + return text, InlineKeyboardMarkup(keyboard) + + def build_tasks_menu(chat_id: int, page: int = 0) -> tuple[str, InlineKeyboardMarkup]: """Builds interactive Scheduled Tasks manager dashboard with pagination and status buttons.""" session = session_manager.get_or_create(chat_id) @@ -1715,7 +1847,12 @@ async def help_command(update: Update, context: ContextTypes.DEFAULT_TYPE): f"• /model - انتخاب مدل هوش مصنوعی\n" f"• /lang [زبان] - تغییر زبان پاسخ‌دهی (مثلاً /lang fa)\n" f"• /effort [low|med|high] - تنظیم عمق تفکر استدلالی\n" - f"• /workspace [مسیر] - تغییر دایرکتوری کاری پروژه فعال\n\n" + f"🧠 حافظه بلندمدت هوش مصنوعی (AI Memory):\n" + f"• /memory - کنترل‌پنل تعاملی حافظه هوشمند، مشاهده و پاک‌سازی خاطرات\n" + f"• /memory global - مشاهده قوانین و خاطرات عمومی کل سیستم\n" + f"• /memory private - مشاهده خاطرات اختصاصی و شخصی شما\n" + f"• /memory clear - پاک‌سازی خاطرات اختصاصی شما\n" + f"• هوش مصنوعی در طول مکالمات، نکات کلیدی و ترجیحات شما را به صورت خودکار به خاطر می‌سپارد!\n\n" f"👑 مدیریت کاربران و دعوت‌ها (ویژه مدیر):\n" f"• /users - پنل تعاملی مدیریت کاربران و لیست مجاز\n" f"• /invite <user_id> - دعوت و اعطای مستقیم دسترسی به کاربر\n" @@ -3240,6 +3377,47 @@ async def usage_command(update: Update, context: ContextTypes.DEFAULT_TYPE): text, markup = await build_usage_report(chat_id) await status_msg.edit_text(text, parse_mode=constants.ParseMode.HTML, reply_markup=markup) +# Command: /memory or /memories +@check_auth +async def memory_command(update: Update, context: ContextTypes.DEFAULT_TYPE): + chat_id = update.effective_chat.id + session = session_manager.get_or_create(chat_id) + is_fa = (session.language or "").lower() in ("fa", "farsi", "persian", "🇮🇷 persian / farsi (فارسی)") + is_admin_user = settings.is_admin(chat_id) + + if not context.args: + text, markup = build_memory_menu(chat_id, view_type="private", page=0) + await update.message.reply_html(text, reply_markup=markup) + return + + subcmd = context.args[0].lower().strip() + from memory_manager import memory_manager + + if subcmd in ("global", "g", "public", "system"): + text, markup = build_memory_menu(chat_id, view_type="global", page=0) + await update.message.reply_html(text, reply_markup=markup) + return + + if subcmd in ("private", "p", "my", "user"): + text, markup = build_memory_menu(chat_id, view_type="private", page=0) + await update.message.reply_html(text, reply_markup=markup) + return + + if subcmd in ("clear", "clean", "purge"): + target_type = "global" if len(context.args) > 1 and context.args[1].lower() in ("global", "g") else "private" + try: + cnt = memory_manager.clear_memories(type_=target_type, user_id=chat_id, is_admin=is_admin_user) + type_label = "عمومی" if target_type == "global" else "خصوصی" + msg = f"🧹 تعداد {cnt} خاطره {type_label} با موفقیت پاک‌سازی شد." if is_fa else f"🧹 {cnt} {target_type} memories cleared." + except PermissionError: + msg = "🚫 خطای دسترسی: فقط ادمین مجاز به پاک‌سازی خاطرات عمومی است." if is_fa else "🚫 Access denied." + await update.message.reply_html(msg) + return + + text, markup = build_memory_menu(chat_id, view_type="private", page=0) + await update.message.reply_html(text, reply_markup=markup) + + # Command: /context or /tokens @check_auth async def context_command(update: Update, context: ContextTypes.DEFAULT_TYPE): @@ -4926,6 +5104,103 @@ async def callback_handler(update: Update, context: ContextTypes.DEFAULT_TYPE): reply_markup=InlineKeyboardMarkup(keyboard), ) + elif data == "btn_memory_menu" or data.startswith("mem_tab:"): + parts = data.split(":") + v_type = parts[1] if len(parts) > 1 else "private" + page_num = int(parts[2]) if len(parts) > 2 and parts[2].isdigit() else 0 + text, markup = build_memory_menu(chat_id, view_type=v_type, page=page_num) + try: + await query.edit_message_text(text, parse_mode=constants.ParseMode.HTML, reply_markup=markup) + except Exception: + await query.message.reply_html(text, reply_markup=markup) + + elif data.startswith("mem_del_conf:"): + _, m_id_str, v_type, page_str = data.split(":") + m_id = int(m_id_str) + p_num = int(page_str) + from memory_manager import memory_manager + mem = memory_manager.get_by_id(m_id) + if not mem: + await query.answer("❌ خاطره یافت نشد." if is_fa else "❌ Memory not found.", show_alert=True) + text, markup = build_memory_menu(chat_id, view_type=v_type, page=p_num) + await query.edit_message_text(text, parse_mode=constants.ParseMode.HTML, reply_markup=markup) + else: + confirm_text = ( + f"🗑️ آیا از حذف این خاطره اطمینان دارید؟\n\n" + f"• 🔑 کلید: {escape_html(mem.key)}\n" + f"• 📝 محتوا: {escape_html(mem.content)}" + if is_fa + else + f"🗑️ Are you sure you want to delete this memory?\n\n" + f"• 🔑 Key: {escape_html(mem.key)}\n" + f"• 📝 Content: {escape_html(mem.content)}" + ) + keyboard = [ + [ + InlineKeyboardButton("✅ بله، حذف شود" if is_fa else "✅ Yes, Delete", callback_data=f"mem_del_do:{m_id}:{v_type}:{p_num}"), + InlineKeyboardButton("❌ انصراف" if is_fa else "❌ Cancel", callback_data=f"mem_tab:{v_type}:{p_num}"), + ] + ] + await query.edit_message_text(confirm_text, parse_mode=constants.ParseMode.HTML, reply_markup=InlineKeyboardMarkup(keyboard)) + + elif data.startswith("mem_del_do:"): + _, m_id_str, v_type, page_str = data.split(":") + m_id = int(m_id_str) + p_num = int(page_str) + from memory_manager import memory_manager + try: + ok = memory_manager.delete_by_id(m_id, user_id=chat_id, is_admin=is_admin_user) + if ok: + await query.answer("🗑️ خاطره با موفقیت حذف شد." if is_fa else "🗑️ Memory deleted successfully.") + else: + await query.answer("❌ خاطره یافت نشد." if is_fa else "❌ Memory not found.", show_alert=True) + except PermissionError: + await query.answer("🚫 دسترسی غیرمجاز!" if is_fa else "🚫 Permission denied!", show_alert=True) + except Exception as e: + await query.answer(f"⚠️ خطا: {e}", show_alert=True) + + text, markup = build_memory_menu(chat_id, view_type=v_type, page=p_num) + try: + await query.edit_message_text(text, parse_mode=constants.ParseMode.HTML, reply_markup=markup) + except Exception: + await query.message.reply_html(text, reply_markup=markup) + + elif data.startswith("mem_clear_conf:"): + v_type = data.split(":")[1] + type_label = "عمومی سیستم" if v_type == "global" else "اختصاصی خودتان" + confirm_text = ( + f"⚠️ هشدار پاک‌سازی حافظه\n\n" + f"آیا مطمئن هستید که می‌خواهید تمام خاطرات {type_label} را به صورت کامل پاک کنید؟ این عملیات غیرقابل بازگشت است." + if is_fa + else + f"⚠️ Warning: Clear Memory\n\n" + f"Are you sure you want to permanently clear all {v_type} memories?" + ) + keyboard = [ + [ + InlineKeyboardButton("💥 بله، همه را پاک کن" if is_fa else "💥 Yes, Clear All", callback_data=f"mem_clear_do:{v_type}"), + InlineKeyboardButton("❌ انصراف" if is_fa else "❌ Cancel", callback_data=f"mem_tab:{v_type}:0"), + ] + ] + await query.edit_message_text(confirm_text, parse_mode=constants.ParseMode.HTML, reply_markup=InlineKeyboardMarkup(keyboard)) + + elif data.startswith("mem_clear_do:"): + v_type = data.split(":")[1] + from memory_manager import memory_manager + try: + cnt = memory_manager.clear_memories(type_=v_type, user_id=chat_id, is_admin=is_admin_user) + await query.answer(f"🧹 تعداد {cnt} خاطره پاک شد." if is_fa else f"🧹 Cleared {cnt} memories.") + except PermissionError: + await query.answer("🚫 دسترسی غیرمجاز!" if is_fa else "🚫 Permission denied!", show_alert=True) + except Exception as e: + await query.answer(f"⚠️ خطا: {e}", show_alert=True) + + text, markup = build_memory_menu(chat_id, view_type=v_type, page=0) + try: + await query.edit_message_text(text, parse_mode=constants.ParseMode.HTML, reply_markup=markup) + except Exception: + await query.message.reply_html(text, reply_markup=markup) + elif data == "btn_tasks_menu": text, markup = build_tasks_menu(chat_id, page=0) try: @@ -5811,6 +6086,7 @@ async def on_startup(app: Application): try: commands = [ BotCommand("start", "کنترل‌پنل اصلی / Main dashboard"), + BotCommand("memory", "حافظه هوش مصنوعی / AI Memory"), BotCommand("projects", "مدیریت پروژه‌ها / Manage projects"), BotCommand("newproject", "ساخت پروژه جدید / Create project"), BotCommand("switch", "سوییچ پروژه / Switch project"), @@ -5947,6 +6223,7 @@ def main(): # General & Control Panel Handlers application.add_handler(CommandHandler(["start", "menu", "dashboard", "panel"], start_command)) + application.add_handler(CommandHandler(["memory", "memories", "hafeze"], memory_command)) application.add_handler(CommandHandler("help", help_command)) application.add_handler(CommandHandler(["usage", "quota", "credits"], usage_command)) application.add_handler(CommandHandler(["new", "reset"], new_command)) diff --git a/telegram-agy-bot/bot_actions.py b/telegram-agy-bot/bot_actions.py index 02cda2f..6b6bb38 100644 --- a/telegram-agy-bot/bot_actions.py +++ b/telegram-agy-bot/bot_actions.py @@ -1081,6 +1081,169 @@ async def execute_action( badge = f"\n⚠️ خطا در بازگردانی گیت: {escape_html(msg)}" return badge, side_effects, created_task + # ------------------------------------------------------------- + # 30. SAVE_MEMORY / STORE_MEMORY / SET_MEMORY + # ------------------------------------------------------------- + elif act in ("SAVE_MEMORY", "STORE_MEMORY", "SET_MEMORY", "ADD_MEMORY"): + from memory_manager import memory_manager + + mem_type = (attrs.get("type") or "private").lower().strip() + key = attrs.get("key") or attrs.get("slug") or attrs.get("name") + content = attrs.get("content") or attrs.get("text") or attrs.get("value") or attrs.get("_default") + category = (attrs.get("category") or "general").lower().strip() + importance_raw = attrs.get("importance") or "1" + try: + importance = int(importance_raw) + except Exception: + importance = 1 + + if not key or not content: + return ( + "\n⚠️ خطا در ذخیره خاطره: کلید (key) و محتوا (content) الزامی هستند." + if is_fa + else "\n⚠️ Memory save error: 'key' and 'content' are required.", + side_effects, + created_task, + ) + + # Security check: Non-admins cannot create global memories + if mem_type == "global" and not is_admin: + logger.warning("Non-admin user %s attempted to create global memory %s; downgraded to private.", chat_id, key) + mem_type = "private" + + try: + item, is_created = memory_manager.save_or_update( + type_=mem_type, + key=key, + content=content, + user_id=chat_id, + category=category, + importance=importance, + created_by=chat_id, + ) + type_label = "🌐 عمومی (سیستم)" if item.is_global else "👤 خصوصی (شما)" + badge = ( + f"\n\n🧠 خاطره هوش مصنوعی ثبت شد:\n" + f"• 🏷️ نوع: {type_label}\n" + f"• 🔑 کلید: {escape_html(item.key)}\n" + f"• 📂 دسته: {escape_html(item.category)}\n" + f"• 📝 محتوا: {escape_html(item.content)}" + if is_fa + else + f"\n\n🧠 AI Memory Saved:\n" + f"• 🏷️ Type: {'Global' if item.is_global else 'Private'}\n" + f"• 🔑 Key: {escape_html(item.key)}\n" + f"• 📂 Category: {escape_html(item.category)}\n" + f"• 📝 Content: {escape_html(item.content)}" + ) + except Exception as e: + badge = f"\n⚠️ خطا در ذخیره خاطره: {escape_html(str(e))}" + return badge, side_effects, created_task + + # ------------------------------------------------------------- + # 31. UPDATE_MEMORY + # ------------------------------------------------------------- + elif act in ("UPDATE_MEMORY", "EDIT_MEMORY"): + from memory_manager import memory_manager + + mem_type = (attrs.get("type") or "private").lower().strip() + key = attrs.get("key") or attrs.get("slug") + content = attrs.get("content") or attrs.get("text") or attrs.get("_default") + category = attrs.get("category") + importance_raw = attrs.get("importance") + + if not key or not content: + return ( + "\n⚠️ خطا در به‌روزرسانی خاطره: مشخص کردن key و content الزامی است." + if is_fa + else "\n⚠️ Memory update error: 'key' and 'content' required.", + side_effects, + created_task, + ) + + if mem_type == "global" and not is_admin: + mem_type = "private" + + try: + existing = memory_manager.get_by_key(type_=mem_type, key=key, user_id=chat_id) + cat = category or (existing.category if existing else "general") + imp = int(importance_raw) if importance_raw and importance_raw.isdigit() else (existing.importance if existing else 1) + item, is_created = memory_manager.save_or_update( + type_=mem_type, + key=key, + content=content, + user_id=chat_id, + category=cat, + importance=imp, + created_by=chat_id, + ) + type_label = "🌐 عمومی (سیستم)" if item.is_global else "👤 خصوصی (شما)" + badge = ( + f"\n\n🧠 خاطره هوش مصنوعی به‌روزرسانی شد:\n" + f"• 🏷️ نوع: {type_label}\n" + f"• 🔑 کلید: {escape_html(item.key)}\n" + f"• 📝 محتوای جدید: {escape_html(item.content)}" + if is_fa + else + f"\n\n🧠 AI Memory Updated:\n" + f"• 🏷️ Type: {'Global' if item.is_global else 'Private'}\n" + f"• 🔑 Key: {escape_html(item.key)}\n" + f"• 📝 New Content: {escape_html(item.content)}" + ) + except Exception as e: + badge = f"\n⚠️ خطا در ویرایش خاطره: {escape_html(str(e))}" + return badge, side_effects, created_task + + # ------------------------------------------------------------- + # 32. DELETE_MEMORY / FORGET_MEMORY / REMOVE_MEMORY + # ------------------------------------------------------------- + elif act in ("DELETE_MEMORY", "FORGET_MEMORY", "REMOVE_MEMORY"): + from memory_manager import memory_manager + + mem_id_raw = attrs.get("id") + key = attrs.get("key") or attrs.get("slug") or attrs.get("_default") + mem_type = (attrs.get("type") or "private").lower().strip() + + try: + if mem_id_raw and mem_id_raw.isdigit(): + ok = memory_manager.delete_by_id(int(mem_id_raw), user_id=chat_id, is_admin=is_admin) + elif key: + ok = memory_manager.delete_by_key(type_=mem_type, key=key, user_id=chat_id, is_admin=is_admin) + else: + return "\n⚠️ لطفاً شناسه یا کلید خاطره جهت حذف را مشخص کنید." if is_fa else "\n⚠️ Please specify memory id or key to delete.", side_effects, created_task + + if ok: + badge = f"\n\n🗑️ خاطره مورد نظر از حافظه هوش مصنوعی حذف گردید." if is_fa else f"\n\n🗑️ Memory forgotten successfully." + else: + badge = f"\n⚠️ خاطره‌ای با این مشخصات یافت نشد." if is_fa else f"\n⚠️ Memory not found." + except PermissionError: + badge = "\n🚫 خطای دسترسی: ویرایش یا حذف خاطرات عمومی تنها توسط مدیر سیستم امکان‌پذیر است." if is_fa else "\n🚫 Access Denied: Only administrators can modify global memories." + except Exception as e: + badge = f"\n⚠️ خطا در حذف خاطره: {escape_html(str(e))}" + return badge, side_effects, created_task + + # ------------------------------------------------------------- + # 33. CLEAR_MEMORY / PURGE_MEMORY + # ------------------------------------------------------------- + elif act in ("CLEAR_MEMORY", "PURGE_MEMORY", "RESET_MEMORY"): + from memory_manager import memory_manager + + mem_type = (attrs.get("type") or "private").lower().strip() + try: + count = memory_manager.clear_memories(type_=mem_type, user_id=chat_id, is_admin=is_admin) + type_label = "عمومی" if mem_type == "global" else "خصوصی" + badge = ( + f"\n\n🧹 حافظه {type_label} پاک‌سازی شد ({count} مورد حذف گردید)." + if is_fa + else + f"\n\n🧹 {mem_type.capitalize()} memory cleared ({count} items purged)." + ) + except PermissionError: + badge = "\n🚫 خطای دسترسی: پاک‌سازی خاطرات عمومی تنها توسط مدیر امکان‌پذیر است." if is_fa else "\n🚫 Access Denied: Only admins can clear global memories." + except Exception as e: + badge = f"\n⚠️ خطا در پاک‌سازی حافظه: {escape_html(str(e))}" + return badge, side_effects, created_task + # ------------------------------------------------------------- # Auto-effort internal tag # ------------------------------------------------------------- @@ -1091,6 +1254,7 @@ async def execute_action( return f"\n[اکشن ناشناخته: {action_name}]" if is_fa else f"\n[Unknown action: {action_name}]", side_effects, created_task + # ===================================================================== # Main AI Response Processor # ===================================================================== @@ -1228,5 +1392,11 @@ def get_ai_bot_actions_instruction(lang: str = "fa") -> str: " [[GIT_INIT: project=\"\"]]\n\n" "17. Restart Telegram Bot Service:\n" " [[RESTART_BOT]]\n\n" + "18. Long-Term AI Memory Management:\n" + " [[SAVE_MEMORY: type=\"private|global\", key=\"\", category=\"\", content=\"\"]]\n" + " (Saves durable facts/preferences. type defaults to 'private'. Only admin can create 'global').\n" + " [[UPDATE_MEMORY: key=\"\", content=\"\"]]\n" + " [[DELETE_MEMORY: key=\"\"]]\n" + " [[CLEAR_MEMORY: type=\"private|global\"]]\n\n" "Always explain to the user in a friendly and professional tone what actions have been performed." ) diff --git a/telegram-agy-bot/data/memory.db b/telegram-agy-bot/data/memory.db index 9225492c08e77184582513d3c88f9d96189890bc..02e10dddf70200490d34264579aa18da6791b57c 100644 GIT binary patch delta 312 zcmZp8z}WDBaRZA07c*ZB1Ah+RFTR+~f&zYg^^MZZJPgt-vWktKoGk3@1x1-ifdUFQTW{urwru_-$12Fkyvcw?fP;zuBm@6r{*#*p754H=NwNZ6 z&4|Ul%#$DcD{?XOUuNL{%KwD_GEn(Z{>e|`1sIuuqykXp76boF{#*P%fHG(JC%??+ XlVIj!Rs@;_^C%NLvnXd#X-+Bt*#Cme delta 96 zcmZp8z}WDBaRZA02NT~f2L2qrUz-IL-tlezCC4hr$h66TMSzWw|1ksqW1#R&{>hL1 y6*-vrpD^%$<$nScxxqjANxTA3