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 9225492..02e10dd 100644 Binary files a/telegram-agy-bot/data/memory.db and b/telegram-agy-bot/data/memory.db differ diff --git a/telegram-agy-bot/invites.json b/telegram-agy-bot/invites.json index b77adf2..ad3e0dd 100644 --- a/telegram-agy-bot/invites.json +++ b/telegram-agy-bot/invites.json @@ -25,6 +25,19 @@ "expires_at": null, "is_active": false, "note": "" + }, + "inv_ba36af3e": { + "code": "inv_ba36af3e", + "creator_id": 78649634, + "created_at": 1788069516.5607157, + "max_uses": 1, + "uses_count": 1, + "used_by": [ + 8896969833 + ], + "expires_at": null, + "is_active": false, + "note": "" } }, "pending_requests": {} diff --git a/telegram-agy-bot/sessions.json b/telegram-agy-bot/sessions.json index 7d5fa84..96e4722 100644 --- a/telegram-agy-bot/sessions.json +++ b/telegram-agy-bot/sessions.json @@ -42,9 +42,9 @@ "model": "gemini-3.7-flash-auto", "effort": "high", "language": "fa", - "last_context_length": 21661, - "last_total_tokens": 265643, - "last_response": "\u2705 **\u0641\u0627\u0632 \u0627\u0648\u0644 \u0628\u0627 \u0645\u0648\u0641\u0642\u06cc\u062a \u067e\u06cc\u0627\u062f\u0647\u200c\u0633\u0627\u0632\u06cc \u0648 \u062a\u0633\u062a \u0634\u062f!**\n\n---\n\n### \ud83d\udce6 \u0627\u0642\u062f\u0627\u0645\u0627\u062a \u0627\u0646\u062c\u0627\u0645\u200c\u0634\u062f\u0647 \u062f\u0631 \u0641\u0627\u0632 \u06f1:\n\n1. **\u0637\u0631\u0627\u062d\u06cc \u0645\u0627\u0698\u0648\u0644 \u0645\u0648\u062a\u0648\u0631 \u062d\u0627\u0641\u0638\u0647 (`memory_manager.py`):**\n - \u0627\u06cc\u062c\u0627\u062f \u06a9\u0644\u0627\u0633\u200c\u0647\u0627\u06cc `MemoryItem` \u0648 `MemoryManager`.\n - \u0631\u0627\u0647\u200c\u0627\u0646\u062f\u0627\u0632\u06cc \u067e\u0627\u06cc\u06af\u0627\u0647 \u062f\u0627\u062f\u0647 \u067e\u0631\u0633\u0631\u0639\u062a SQLite \u062f\u0631 \u0645\u0633\u06cc\u0631 `/root/telegram-agy-bot/data/memory.db`.\n - \u0641\u0639\u0627\u0644\u200c\u0633\u0627\u0632\u06cc \u062d\u0627\u0644\u062a **WAL (Write-Ahead Logging)** \u0628\u0631\u0627\u06cc \u0647\u0645\u0632\u0645\u0627\u0646\u06cc \u0628\u0627\u0644\u0627 \u0648 \u067e\u0627\u06cc\u062f\u0627\u0631\u06cc \u06a9\u0627\u0645\u0644 \u062f\u0631 \u062f\u0631\u062e\u0648\u0627\u0633\u062a\u200c\u0647\u0627\u06cc \u0686\u0646\u062f\u06a9\u0627\u0631\u0628\u0631\u0647.\n\n2. **\u0637\u0631\u0627\u062d\u06cc \u0627\u0633\u06a9\u06cc\u0645\u0627 \u0648 \u0627\u06cc\u0646\u062f\u06a9\u0633\u200c\u0647\u0627:**\n - \u062c\u062f\u0648\u0644 `memories` \u0628\u0627 \u0641\u06cc\u0644\u062f\u0647\u0627\u06cc:\n - `id`: \u0634\u0646\u0627\u0633\u0647 \u06cc\u06a9\u062a\u0627\u06cc \u0639\u062f\u062f\u06cc\n - `type`: \u0646\u0648\u0639 \u062e\u0627\u0637\u0631\u0647 (`global` \u0628\u0631\u0627\u06cc \u0647\u0645\u0647 \u06a9\u0627\u0631\u0628\u0631\u0627\u0646 / `private` \u0627\u062e\u062a\u0635\u0627\u0635\u06cc \u0647\u0631 \u06a9\u0627\u0631\u0628\u0631)\n - `user_id`: \u0634\u0646\u0627\u0633\u0647 \u062a\u0644\u06af\u0631\u0627\u0645 \u06a9\u0627\u0631\u0628\u0631 (\u0628\u0631\u0627\u06cc \u0639\u0645\u0648\u0645\u06cc \u0645\u0642\u062f\u0627\u0631 `NULL`)\n - `key`: \u06a9\u0644\u06cc\u062f \u0645\u062a\u0646\u06cc \u06cc\u06a9\u062a\u0627 (\u062c\u0647\u062a \u0628\u0647\u200c\u0631\u0648\u0632\u0631\u0633\u0627\u0646\u06cc \u062e\u0648\u062f\u06a9\u0627\u0631 \u0648 \u062c\u0644\u0648\u06af\u06cc\u0631\u06cc \u0627\u0632 \u062b\u0628\u062a \u0645\u0648\u0627\u0631\u062f \u062a\u06a9\u0631\u0627\u0631\u06cc)\n - `category`: \u062f\u0633\u062a\u0647\u200c\u0628\u0646\u062f\u06cc \u0645\u0648\u0636\u0648\u0639\u06cc (`rule`, `preference`, `tech_stack`, `fact`, `workflow`, `general`)\n - `content`: \u0645\u062a\u0646 \u062e\u0644\u0627\u0635\u0647\u200c\u0634\u062f\u0647 \u0648 \u0645\u0641\u06cc\u062f \u062e\u0627\u0637\u0631\u0647\n - `importance`: \u0631\u062a\u0628\u0647 \u0627\u0647\u0645\u06cc\u062a (\u06f1 \u062a\u0627 \u06f5)\n - `created_at` \u0648 `updated_at`: \u062b\u0628\u062a \u0632\u0645\u0627\u0646 \u062f\u0642\u06cc\u0642\n - \u0633\u0627\u062e\u062a \u0627\u06cc\u0646\u062f\u06a9\u0633\u200c\u0647\u0627\u06cc \u06cc\u06a9\u062a\u0627 \u0648 \u0633\u0631\u06cc\u0639 \u0628\u0631 \u0631\u0648\u06cc `(type, key)` \u0648 `(type, user_id, key)`.\n\n3. **\u067e\u06cc\u0627\u062f\u0647\u200c\u0633\u0627\u0632\u06cc \u0645\u062a\u062f\u0647\u0627\u06cc \u06a9\u0627\u0631\u0628\u0631\u062f\u06cc (CRUD & Analytics):**\n - `save_or_update()`: \u0627\u06cc\u062c\u0627\u062f \u06cc\u0627 \u0628\u0647\u200c\u0631\u0648\u0632\u0631\u0633\u0627\u0646\u06cc \u062e\u0648\u062f\u06a9\u0627\u0631 \u0628\u0631 \u0627\u0633\u0627\u0633 \u06a9\u0644\u06cc\u062f.\n - `get_global_memories()`: \u062f\u0631\u06cc\u0627\u0641\u062a \u062a\u0645\u0627\u0645\u06cc \u0642\u0648\u0627\u0646\u06cc\u0646 \u0648 \u062e\u0627\u0637\u0631\u0627\u062a \u0639\u0645\u0648\u0645\u06cc \u0633\u06cc\u0633\u062a\u0645.\n - `get_user_memories()`: \u0648\u0627\u06a9\u0634\u06cc \u0627\u062e\u062a\u0635\u0627\u0635\u06cc \u062e\u0627\u0637\u0631\u0627\u062a \u0647\u0631 \u06a9\u0627\u0631\u0628\u0631 \u0628\u0627 \u0627\u06cc\u0632\u0648\u0644\u0627\u0633\u06cc\u0648\u0646 \u06a9\u0627\u0645\u0644.\n - `delete_by_id()` / `delete_by_key()`: \u062d\u0630\u0641 \u0628\u0627 \u06a9\u0646\u062a\u0631\u0644 \u062f\u0642\u06cc\u0642 \u062f\u0633\u062a\u0631\u0633\u06cc (\u0641\u0642\u0637 \u0627\u062f\u0645\u06cc\u0646 \u0628\u0631\u0627\u06cc \u0639\u0645\u0648\u0645\u06cc).\n - `clear_memories()`: \u067e\u0627\u06a9\u200c\u0633\u0627\u0632\u06cc \u06a9\u0627\u0645\u0644 \u062d\u0627\u0641\u0638\u0647 \u062e\u0635\u0648\u0635\u06cc \u06cc\u0627 \u0639\u0645\u0648\u0645\u06cc.\n - `format_memories_for_prompt()`: \u0641\u0631\u0645\u062a\u200c\u0628\u0646\u062f\u06cc \u0627\u0633\u062a\u0627\u0646\u062f\u0627\u0631\u062f \u0648 \u0628\u0647\u06cc\u0646\u0647\u200c\u0633\u0627\u0632\u06cc\u200c\u0634\u062f\u0647 \u0628\u0631\u0627\u06cc \u062a\u0632\u0631\u06cc\u0642 \u0628\u0647 \u0647\u0648\u0634 \u0645\u0635\u0646\u0648\u0639\u06cc.\n - `get_stats()`: \u06af\u0632\u0627\u0631\u0634\u200c\u06af\u06cc\u0631\u06cc \u0627\u0632 \u062a\u0639\u062f\u0627\u062f \u062e\u0627\u0637\u0631\u0627\u062a \u0639\u0645\u0648\u0645\u06cc\u060c \u062e\u0635\u0648\u0635\u06cc \u0648 \u06a9\u0627\u0631\u0628\u0631\u0627\u0646 \u062f\u0627\u0631\u0627\u06cc \u062d\u0627\u0641\u0638\u0647.\n\n4. **\u062a\u0633\u062a \u0648 \u0627\u0639\u062a\u0628\u0627\u0631\u0633\u0646\u062c\u06cc:**\n - \u062a\u0633\u062a \u0630\u062e\u06cc\u0631\u0647\u200c\u0633\u0627\u0632\u06cc\u060c \u0628\u0627\u0632\u06cc\u0627\u0628\u06cc \u0648 \u0642\u0627\u0644\u0628\u200c\u0628\u0646\u062f\u06cc \u067e\u0631\u0627\u0645\u067e\u062a \u0628\u0627 \u0645\u0648\u0641\u0642\u06cc\u062a \u0627\u0646\u062c\u0627\u0645 \u0634\u062f.\n - \u0642\u0627\u0646\u0648\u0646 \u0639\u0645\u0648\u0645\u06cc \u0633\u06cc\u0633\u062a\u0645 (`php_preference`) \u0646\u06cc\u0632 \u0628\u0647 \u0639\u0646\u0648\u0627\u0646 \u0627\u0648\u0644\u06cc\u0646 \u062e\u0627\u0637\u0631\u0647 \u0639\u0645\u0648\u0645\u06cc \u062f\u0631 \u062f\u06cc\u062a\u0627\u0628\u06cc\u0633 \u062b\u0628\u062a \u0634\u062f.\n\n---\n\n### \ud83d\ude80 \u06af\u0627\u0645 \u0628\u0639\u062f\u06cc:\n\u0622\u0645\u0627\u062f\u0647 \u0648\u0631\u0648\u062f \u0628\u0647 **\u0641\u0627\u0632 \u06f2 (\u0627\u062a\u0635\u0627\u0644 \u0645\u0648\u062a\u0648\u0631 \u062d\u0627\u0641\u0638\u0647 \u0628\u0647 \u067e\u0627\u06cc\u067e\u200c\u0644\u0627\u06cc\u0646 \u0647\u0648\u0634 \u0645\u0635\u0646\u0648\u0639\u06cc \u062f\u0631 `agy_engine.py`)** \u0648 **\u0641\u0627\u0632 \u06f3 (\u067e\u0631\u062f\u0627\u0632\u0634 \u062a\u06af\u200c\u0647\u0627\u06cc \u0627\u06a9\u0634\u0646 \u0647\u0648\u0634 \u0645\u0635\u0646\u0648\u0639\u06cc \u062f\u0631 `bot_actions.py`)** \u0647\u0633\u062a\u06cc\u0645. \n\n\u0622\u06cc\u0627 \u0645\u0627\u06cc\u0644\u06cc\u062f \u0641\u0627\u0632 \u06f2 \u0648 \u06f3 \u0631\u0627 \u0627\u062f\u0627\u0645\u0647 \u062f\u0647\u06cc\u0645\u061f\n\n---\n\u2022 \u0646\u0627\u0645 \u067e\u0631\u0648\u0698\u0647: default\n\u2022 \u0622\u062f\u0631\u0633 \u0645\u062e\u0632\u0646: https://git.msa.artacloud.ir/root/default\n", + "last_context_length": 59015, + "last_total_tokens": 559030, + "last_response": "\u0641\u0631\u0622\u06cc\u0646\u062f \u062a\u0633\u062a \u0627\u062c\u0631\u0627\u06cc \u0627\u06a9\u0634\u0646\u200c\u062a\u06af\u200c\u0647\u0627\u06cc \u062d\u0627\u0641\u0638\u0647 \u0622\u063a\u0627\u0632 \u0634\u062f \u0648 \u0645\u0646\u062a\u0638\u0631 \u0646\u062a\u06cc\u062c\u0647 \u0627\u062c\u0631\u0627\u06cc \u0622\u0646 \u0647\u0633\u062a\u06cc\u0645.\n\u062f\u0631 \u062d\u0627\u0644 \u06a9\u0627\u0645\u067e\u0627\u06cc\u0644 \u0648 \u0627\u0639\u062a\u0628\u0627\u0631\u0633\u0646\u062c\u06cc \u0633\u06cc\u0646\u062a\u06a9\u0633 \u062a\u0645\u0627\u0645 \u0641\u0627\u06cc\u0644\u200c\u0647\u0627\u06cc \u067e\u0627\u06cc\u062a\u0648\u0646 \u067e\u0631\u0648\u0698\u0647 \u0647\u0633\u062a\u06cc\u0645.\n\u062a\u0633\u062a \u062c\u0627\u0645\u0639 \u06cc\u06a9\u067e\u0627\u0631\u0686\u0647\u200c\u0633\u0627\u0632\u06cc \u0648 \u0631\u0627\u0628\u0637 \u06a9\u0627\u0631\u0628\u0631\u06cc \u062d\u0627\u0641\u0638\u0647 \u0622\u063a\u0627\u0632 \u0634\u062f.\n\ud83c\udf89 **\u062a\u0645\u0627\u0645\u06cc \u0641\u0627\u0632\u0647\u0627\u06cc \u0633\u06cc\u0633\u062a\u0645 \u062d\u0627\u0641\u0638\u0647 \u0647\u0648\u0634 \u0645\u0635\u0646\u0648\u0639\u06cc \u06a9\u0627\u0631\u0628\u0631\u0627\u0646 \u0628\u0627 \u0645\u0648\u0641\u0642\u06cc\u062a \u067e\u06cc\u0627\u062f\u0647\u200c\u0633\u0627\u0632\u06cc\u060c \u06cc\u06a9\u067e\u0627\u0631\u0686\u0647\u200c\u0633\u0627\u0632\u06cc \u0648 \u062a\u0633\u062a \u0634\u062f!**\n\n---\n\n### \ud83d\udcca \u062e\u0644\u0627\u0635\u0647 \u062a\u063a\u06cc\u06cc\u0631\u0627\u062a \u0648 \u0642\u0627\u0628\u0644\u06cc\u062a\u200c\u0647\u0627\u06cc \u067e\u06cc\u0627\u062f\u0647\u200c\u0633\u0627\u0632\u06cc\u200c\u0634\u062f\u0647:\n\n#### \u06f1. \u0645\u0627\u0698\u0648\u0644 \u067e\u0627\u06cc\u06af\u0627\u0647 \u062f\u0627\u062f\u0647 \u0648 \u0645\u0648\u062a\u0648\u0631 \u0630\u062e\u06cc\u0631\u0647\u200c\u0633\u0627\u0632\u06cc (`memory_manager.py`)\n- \u0627\u06cc\u062c\u0627\u062f \u067e\u0627\u06cc\u06af\u0627\u0647 \u062f\u0627\u062f\u0647 \u0645\u0633\u062a\u0642\u0644 \u0648 \u067e\u0631\u0633\u0631\u0639\u062a SQLite \u062f\u0631 \u0645\u0633\u06cc\u0631 `/root/telegram-agy-bot/data/memory.db` \u0628\u0627 \u062d\u0627\u0644\u062a \u0647\u0645\u0632\u0645\u0627\u0646\u06cc **WAL**.\n- \u062a\u0641\u06a9\u06cc\u06a9 \u06a9\u0627\u0645\u0644 \u0648 \u0627\u06cc\u0632\u0648\u0644\u0647 \u062e\u0627\u0637\u0631\u0627\u062a \u0628\u0647 \u062f\u0648 \u0628\u062e\u0634:\n - **\ud83c\udf10 \u062e\u0627\u0637\u0631\u0627\u062a \u0639\u0645\u0648\u0645\u06cc (Global Memory):** \u0627\u0639\u0645\u0627\u0644\u200c\u0634\u062f\u0647 \u0628\u0631 \u062a\u0645\u0627\u0645 \u06a9\u0627\u0631\u0628\u0631\u0627\u0646 \u0648 \u0633\u0634\u0646\u200c\u0647\u0627 (\u0641\u0642\u0637 \u0628\u0627 \u062f\u0633\u062a\u0631\u0633\u06cc \u0645\u062f\u06cc\u0631 \u0633\u06cc\u0633\u062a\u0645).\n - **\ud83d\udc64 \u062e\u0627\u0637\u0631\u0627\u062a \u062e\u0635\u0648\u0635\u06cc (Private Memory):** \u0627\u06cc\u0632\u0648\u0644\u0647 \u0648 \u0627\u062e\u062a\u0635\u0627\u0635\u06cc \u0628\u0631\u0627\u06cc \u0647\u0631 \u06a9\u0627\u0631\u0628\u0631 \u0628\u0631 \u0627\u0633\u0627\u0633 \u0634\u0646\u0627\u0633\u0647 \u062a\u0644\u06af\u0631\u0627\u0645.\n- \u062c\u0644\u0648\u06af\u06cc\u0631\u06cc \u062e\u0648\u062f\u06a9\u0627\u0631 \u0627\u0632 \u062b\u0628\u062a \u0645\u0648\u0627\u0631\u062f \u062a\u06a9\u0631\u0627\u0631\u06cc \u0628\u0627 \u0645\u06a9\u0627\u0646\u06cc\u0633\u0645 \u06a9\u0644\u06cc\u062f \u06cc\u06a9\u062a\u0627 (`key-based deduplication`).\n\n#### \u06f2. \u062a\u0632\u0631\u06cc\u0642 \u0647\u0648\u0634\u0645\u0646\u062f \u062d\u0627\u0641\u0638\u0647 \u0628\u0647 \u067e\u0627\u06cc\u067e\u200c\u0644\u0627\u06cc\u0646 \u0647\u0648\u0634 \u0645\u0635\u0646\u0648\u0639\u06cc (`agy_engine.py`)\n- \u062f\u0631 \u0647\u0631 \u067e\u06cc\u0627\u0645 \u0627\u0631\u0633\u0627\u0644\u06cc\u060c \u0631\u0628\u0627\u062a \u0628\u0647 \u0635\u0648\u0631\u062a \u062e\u0648\u062f\u06a9\u0627\u0631 \u062e\u0627\u0637\u0631\u0627\u062a \u0639\u0645\u0648\u0645\u06cc \u0648 \u062e\u0627\u0637\u0631\u0627\u062a \u062e\u0635\u0648\u0635\u06cc \u0647\u0645\u0627\u0646 \u06a9\u0627\u0631\u0628\u0631 \u0631\u0627 \u0627\u0633\u062a\u062e\u0631\u0627\u062c \u0648 \u062f\u0631 \u0642\u0627\u0644\u0628 \u0628\u0644\u0648\u06a9 \u0627\u0633\u062a\u0627\u0646\u062f\u0627\u0631\u062f `[SYSTEM INSTRUCTION: AI PERSISTENT MEMORY]` \u0628\u0627 \u062d\u062f\u0627\u0642\u0644 \u0645\u0635\u0631\u0641 \u062a\u0648\u06a9\u0646 \u0628\u0647 \u0645\u062f\u0644 \u062a\u0632\u0631\u06cc\u0642 \u0645\u06cc\u200c\u06a9\u0646\u062f.\n\n#### \u06f3. \u0627\u06a9\u0634\u0646\u200c\u062a\u06af\u200c\u0647\u0627\u06cc \u067e\u0631\u062f\u0627\u0632\u0634 \u0648 \u06cc\u0627\u062f\u06af\u06cc\u0631\u06cc \u062e\u0648\u062f\u06a9\u0627\u0631 (`bot_actions.py`)\n- \u062b\u0628\u062a \u0648 \u062a\u0639\u0631\u06cc\u0641 \u0627\u06a9\u0634\u0646\u200c\u0647\u0627\u06cc \u0632\u06cc\u0631 \u062f\u0631 \u0645\u0641\u0633\u0631 \u0631\u0628\u0627\u062a:\n - `SAVE_MEMORY`: \u0630\u062e\u06cc\u0631\u0647\u200c\u0633\u0627\u0632\u06cc \u062e\u0627\u0637\u0631\u0647 \u06cc\u0627 \u062a\u0631\u062c\u06cc\u062d \u062c\u062f\u06cc\u062f \u0628\u0627 \u062f\u0633\u062a\u0647\u200c\u0628\u0646\u062f\u06cc \u0648 \u0627\u0647\u0645\u06cc\u062a\n - `UPDATE_MEMORY`: \u0648\u06cc\u0631\u0627\u06cc\u0634 \u0648 \u0628\u0647\u200c\u0631\u0648\u0632\u0631\u0633\u0627\u0646\u06cc \u062e\u0627\u0637\u0631\u0647 \u0645\u0648\u062c\u0648\u062f\n - `DELETE_MEMORY`: \u062d\u0630\u0641 \u06cc\u06a9 \u062e\u0627\u0637\u0631\u0647 \u0645\u0634\u062e\u0635\n - `CLEAR_MEMORY`: \u067e\u0627\u06a9\u200c\u0633\u0627\u0632\u06cc \u06a9\u0627\u0645\u0644 \u062e\u0627\u0637\u0631\u0627\u062a \u062e\u0635\u0648\u0635\u06cc \u06cc\u0627 \u0639\u0645\u0648\u0645\u06cc\n- **\u06af\u06cc\u062a \u0627\u0645\u0646\u06cc\u062a\u06cc:** \u0627\u0639\u062a\u0628\u0627\u0631\u0633\u0646\u062c\u06cc \u0633\u0637\u062d \u062f\u0633\u062a\u0631\u0633\u06cc \u0627\u062f\u0645\u06cc\u0646 \u062c\u0647\u062a \u062c\u0644\u0648\u06af\u06cc\u0631\u06cc \u0627\u0632 \u0648\u06cc\u0631\u0627\u06cc\u0634 \u06cc\u0627 \u0633\u0627\u062e\u062a \u062e\u0627\u0637\u0631\u0627\u062a \u0639\u0645\u0648\u0645\u06cc \u062a\u0648\u0633\u0637 \u06a9\u0627\u0631\u0628\u0631\u0627\u0646 \u0639\u0627\u062f\u06cc.\n\n#### \u06f4. \u067e\u0646\u0644 \u062a\u0639\u0627\u0645\u0644\u06cc \u0648 \u062f\u0633\u062a\u0648\u0631\u0627\u062a \u062a\u0644\u06af\u0631\u0627\u0645 (`bot.py`)\n- \u0627\u0641\u0632\u0648\u062f\u0646 \u062f\u0633\u062a\u0648\u0631 `/memory` (\u0648 \u0646\u0627\u0645\u200c\u0647\u0627\u06cc \u0645\u0633\u062a\u0639\u0627\u0631 `/memories` \u0648 `/hafeze`)\n- \u0627\u0641\u0632\u0648\u062f\u0646 \u062f\u06a9\u0645\u0647 \u0634\u06cc\u0634\u0647\u200c\u0627\u06cc **\u00ab\ud83e\udde0 \u062d\u0627\u0641\u0638\u0647 \u0647\u0648\u0634 \u0645\u0635\u0646\u0648\u0639\u06cc\u00bb** \u0628\u0647 \u0645\u0646\u0648\u06cc \u0627\u0635\u0644\u06cc \u062f\u0627\u0634\u0628\u0648\u0631\u062f \u0648 \u0645\u0646\u0648\u06cc \u062a\u0646\u0638\u06cc\u0645\u0627\u062a\n- \u0627\u0645\u06a9\u0627\u0646 \u0645\u0634\u0627\u0647\u062f\u0647 \u0644\u06cc\u0633\u062a \u062e\u0627\u0637\u0631\u0627\u062a \u0628\u0627 \u0635\u0641\u062d\u0647\u200c\u0628\u0646\u062f\u06cc (Pagination)\u060c \u0633\u0648\u0626\u06cc\u0686 \u062a\u0628 \u0628\u06cc\u0646 \u062e\u0627\u0637\u0631\u0627\u062a \u0645\u0646 \u0648 \u0639\u0645\u0648\u0645\u06cc\u060c \u062d\u0630\u0641 \u062a\u06a9\u06cc \u0647\u0631 \u062e\u0627\u0637\u0631\u0647\u060c \u0648 \u067e\u0627\u06a9\u200c\u0633\u0627\u0632\u06cc \u06a9\u0627\u0645\u0644\n- \u0628\u0647\u200c\u0631\u0648\u0632\u0631\u0633\u0627\u0646\u06cc \u0645\u0646\u0648\u06cc \u0631\u0627\u0647\u0646\u0645\u0627 (`/help`) \u0648 \u0644\u06cc\u0633\u062a \u062f\u0633\u062a\u0648\u0631\u0627\u062a \u0631\u0628\u0627\u062a (`BotCommand`)\n\n---\n\n[[RESTART_BOT]]\n\n\u2022 \u0646\u0627\u0645 \u067e\u0631\u0648\u0698\u0647: default\n\u2022 \u0622\u062f\u0631\u0633 \u0645\u062e\u0632\u0646: https://git.msa.artacloud.ir/root/default\n", "created_at": 1787995349.975879, "description": "" }, @@ -71,19 +71,19 @@ } }, "turn_in_progress": false, - "last_prompt": "\u067e\u0633 \u0641\u0627\u0632 \u0627\u0648\u0644 \u0631\u0648 \u067e\u06cc\u0627\u062f\u0647 \u06a9\u0646", - "last_response": "\u2705 **\u0641\u0627\u0632 \u0627\u0648\u0644 \u0628\u0627 \u0645\u0648\u0641\u0642\u06cc\u062a \u067e\u06cc\u0627\u062f\u0647\u200c\u0633\u0627\u0632\u06cc \u0648 \u062a\u0633\u062a \u0634\u062f!**\n\n---\n\n### \ud83d\udce6 \u0627\u0642\u062f\u0627\u0645\u0627\u062a \u0627\u0646\u062c\u0627\u0645\u200c\u0634\u062f\u0647 \u062f\u0631 \u0641\u0627\u0632 \u06f1:\n\n1. **\u0637\u0631\u0627\u062d\u06cc \u0645\u0627\u0698\u0648\u0644 \u0645\u0648\u062a\u0648\u0631 \u062d\u0627\u0641\u0638\u0647 (`memory_manager.py`):**\n - \u0627\u06cc\u062c\u0627\u062f \u06a9\u0644\u0627\u0633\u200c\u0647\u0627\u06cc `MemoryItem` \u0648 `MemoryManager`.\n - \u0631\u0627\u0647\u200c\u0627\u0646\u062f\u0627\u0632\u06cc \u067e\u0627\u06cc\u06af\u0627\u0647 \u062f\u0627\u062f\u0647 \u067e\u0631\u0633\u0631\u0639\u062a SQLite \u062f\u0631 \u0645\u0633\u06cc\u0631 `/root/telegram-agy-bot/data/memory.db`.\n - \u0641\u0639\u0627\u0644\u200c\u0633\u0627\u0632\u06cc \u062d\u0627\u0644\u062a **WAL (Write-Ahead Logging)** \u0628\u0631\u0627\u06cc \u0647\u0645\u0632\u0645\u0627\u0646\u06cc \u0628\u0627\u0644\u0627 \u0648 \u067e\u0627\u06cc\u062f\u0627\u0631\u06cc \u06a9\u0627\u0645\u0644 \u062f\u0631 \u062f\u0631\u062e\u0648\u0627\u0633\u062a\u200c\u0647\u0627\u06cc \u0686\u0646\u062f\u06a9\u0627\u0631\u0628\u0631\u0647.\n\n2. **\u0637\u0631\u0627\u062d\u06cc \u0627\u0633\u06a9\u06cc\u0645\u0627 \u0648 \u0627\u06cc\u0646\u062f\u06a9\u0633\u200c\u0647\u0627:**\n - \u062c\u062f\u0648\u0644 `memories` \u0628\u0627 \u0641\u06cc\u0644\u062f\u0647\u0627\u06cc:\n - `id`: \u0634\u0646\u0627\u0633\u0647 \u06cc\u06a9\u062a\u0627\u06cc \u0639\u062f\u062f\u06cc\n - `type`: \u0646\u0648\u0639 \u062e\u0627\u0637\u0631\u0647 (`global` \u0628\u0631\u0627\u06cc \u0647\u0645\u0647 \u06a9\u0627\u0631\u0628\u0631\u0627\u0646 / `private` \u0627\u062e\u062a\u0635\u0627\u0635\u06cc \u0647\u0631 \u06a9\u0627\u0631\u0628\u0631)\n - `user_id`: \u0634\u0646\u0627\u0633\u0647 \u062a\u0644\u06af\u0631\u0627\u0645 \u06a9\u0627\u0631\u0628\u0631 (\u0628\u0631\u0627\u06cc \u0639\u0645\u0648\u0645\u06cc \u0645\u0642\u062f\u0627\u0631 `NULL`)\n - `key`: \u06a9\u0644\u06cc\u062f \u0645\u062a\u0646\u06cc \u06cc\u06a9\u062a\u0627 (\u062c\u0647\u062a \u0628\u0647\u200c\u0631\u0648\u0632\u0631\u0633\u0627\u0646\u06cc \u062e\u0648\u062f\u06a9\u0627\u0631 \u0648 \u062c\u0644\u0648\u06af\u06cc\u0631\u06cc \u0627\u0632 \u062b\u0628\u062a \u0645\u0648\u0627\u0631\u062f \u062a\u06a9\u0631\u0627\u0631\u06cc)\n - `category`: \u062f\u0633\u062a\u0647\u200c\u0628\u0646\u062f\u06cc \u0645\u0648\u0636\u0648\u0639\u06cc (`rule`, `preference`, `tech_stack`, `fact`, `workflow`, `general`)\n - `content`: \u0645\u062a\u0646 \u062e\u0644\u0627\u0635\u0647\u200c\u0634\u062f\u0647 \u0648 \u0645\u0641\u06cc\u062f \u062e\u0627\u0637\u0631\u0647\n - `importance`: \u0631\u062a\u0628\u0647 \u0627\u0647\u0645\u06cc\u062a (\u06f1 \u062a\u0627 \u06f5)\n - `created_at` \u0648 `updated_at`: \u062b\u0628\u062a \u0632\u0645\u0627\u0646 \u062f\u0642\u06cc\u0642\n - \u0633\u0627\u062e\u062a \u0627\u06cc\u0646\u062f\u06a9\u0633\u200c\u0647\u0627\u06cc \u06cc\u06a9\u062a\u0627 \u0648 \u0633\u0631\u06cc\u0639 \u0628\u0631 \u0631\u0648\u06cc `(type, key)` \u0648 `(type, user_id, key)`.\n\n3. **\u067e\u06cc\u0627\u062f\u0647\u200c\u0633\u0627\u0632\u06cc \u0645\u062a\u062f\u0647\u0627\u06cc \u06a9\u0627\u0631\u0628\u0631\u062f\u06cc (CRUD & Analytics):**\n - `save_or_update()`: \u0627\u06cc\u062c\u0627\u062f \u06cc\u0627 \u0628\u0647\u200c\u0631\u0648\u0632\u0631\u0633\u0627\u0646\u06cc \u062e\u0648\u062f\u06a9\u0627\u0631 \u0628\u0631 \u0627\u0633\u0627\u0633 \u06a9\u0644\u06cc\u062f.\n - `get_global_memories()`: \u062f\u0631\u06cc\u0627\u0641\u062a \u062a\u0645\u0627\u0645\u06cc \u0642\u0648\u0627\u0646\u06cc\u0646 \u0648 \u062e\u0627\u0637\u0631\u0627\u062a \u0639\u0645\u0648\u0645\u06cc \u0633\u06cc\u0633\u062a\u0645.\n - `get_user_memories()`: \u0648\u0627\u06a9\u0634\u06cc \u0627\u062e\u062a\u0635\u0627\u0635\u06cc \u062e\u0627\u0637\u0631\u0627\u062a \u0647\u0631 \u06a9\u0627\u0631\u0628\u0631 \u0628\u0627 \u0627\u06cc\u0632\u0648\u0644\u0627\u0633\u06cc\u0648\u0646 \u06a9\u0627\u0645\u0644.\n - `delete_by_id()` / `delete_by_key()`: \u062d\u0630\u0641 \u0628\u0627 \u06a9\u0646\u062a\u0631\u0644 \u062f\u0642\u06cc\u0642 \u062f\u0633\u062a\u0631\u0633\u06cc (\u0641\u0642\u0637 \u0627\u062f\u0645\u06cc\u0646 \u0628\u0631\u0627\u06cc \u0639\u0645\u0648\u0645\u06cc).\n - `clear_memories()`: \u067e\u0627\u06a9\u200c\u0633\u0627\u0632\u06cc \u06a9\u0627\u0645\u0644 \u062d\u0627\u0641\u0638\u0647 \u062e\u0635\u0648\u0635\u06cc \u06cc\u0627 \u0639\u0645\u0648\u0645\u06cc.\n - `format_memories_for_prompt()`: \u0641\u0631\u0645\u062a\u200c\u0628\u0646\u062f\u06cc \u0627\u0633\u062a\u0627\u0646\u062f\u0627\u0631\u062f \u0648 \u0628\u0647\u06cc\u0646\u0647\u200c\u0633\u0627\u0632\u06cc\u200c\u0634\u062f\u0647 \u0628\u0631\u0627\u06cc \u062a\u0632\u0631\u06cc\u0642 \u0628\u0647 \u0647\u0648\u0634 \u0645\u0635\u0646\u0648\u0639\u06cc.\n - `get_stats()`: \u06af\u0632\u0627\u0631\u0634\u200c\u06af\u06cc\u0631\u06cc \u0627\u0632 \u062a\u0639\u062f\u0627\u062f \u062e\u0627\u0637\u0631\u0627\u062a \u0639\u0645\u0648\u0645\u06cc\u060c \u062e\u0635\u0648\u0635\u06cc \u0648 \u06a9\u0627\u0631\u0628\u0631\u0627\u0646 \u062f\u0627\u0631\u0627\u06cc \u062d\u0627\u0641\u0638\u0647.\n\n4. **\u062a\u0633\u062a \u0648 \u0627\u0639\u062a\u0628\u0627\u0631\u0633\u0646\u062c\u06cc:**\n - \u062a\u0633\u062a \u0630\u062e\u06cc\u0631\u0647\u200c\u0633\u0627\u0632\u06cc\u060c \u0628\u0627\u0632\u06cc\u0627\u0628\u06cc \u0648 \u0642\u0627\u0644\u0628\u200c\u0628\u0646\u062f\u06cc \u067e\u0631\u0627\u0645\u067e\u062a \u0628\u0627 \u0645\u0648\u0641\u0642\u06cc\u062a \u0627\u0646\u062c\u0627\u0645 \u0634\u062f.\n - \u0642\u0627\u0646\u0648\u0646 \u0639\u0645\u0648\u0645\u06cc \u0633\u06cc\u0633\u062a\u0645 (`php_preference`) \u0646\u06cc\u0632 \u0628\u0647 \u0639\u0646\u0648\u0627\u0646 \u0627\u0648\u0644\u06cc\u0646 \u062e\u0627\u0637\u0631\u0647 \u0639\u0645\u0648\u0645\u06cc \u062f\u0631 \u062f\u06cc\u062a\u0627\u0628\u06cc\u0633 \u062b\u0628\u062a \u0634\u062f.\n\n---\n\n### \ud83d\ude80 \u06af\u0627\u0645 \u0628\u0639\u062f\u06cc:\n\u0622\u0645\u0627\u062f\u0647 \u0648\u0631\u0648\u062f \u0628\u0647 **\u0641\u0627\u0632 \u06f2 (\u0627\u062a\u0635\u0627\u0644 \u0645\u0648\u062a\u0648\u0631 \u062d\u0627\u0641\u0638\u0647 \u0628\u0647 \u067e\u0627\u06cc\u067e\u200c\u0644\u0627\u06cc\u0646 \u0647\u0648\u0634 \u0645\u0635\u0646\u0648\u0639\u06cc \u062f\u0631 `agy_engine.py`)** \u0648 **\u0641\u0627\u0632 \u06f3 (\u067e\u0631\u062f\u0627\u0632\u0634 \u062a\u06af\u200c\u0647\u0627\u06cc \u0627\u06a9\u0634\u0646 \u0647\u0648\u0634 \u0645\u0635\u0646\u0648\u0639\u06cc \u062f\u0631 `bot_actions.py`)** \u0647\u0633\u062a\u06cc\u0645. \n\n\u0622\u06cc\u0627 \u0645\u0627\u06cc\u0644\u06cc\u062f \u0641\u0627\u0632 \u06f2 \u0648 \u06f3 \u0631\u0627 \u0627\u062f\u0627\u0645\u0647 \u062f\u0647\u06cc\u0645\u061f\n\n---\n\u2022 \u0646\u0627\u0645 \u067e\u0631\u0648\u0698\u0647: default\n\u2022 \u0622\u062f\u0631\u0633 \u0645\u062e\u0632\u0646: https://git.msa.artacloud.ir/root/default\n", + "last_prompt": "\u0628\u0631\u0648 \u0641\u0627\u0632 \u0628\u0639\u062f\u06cc", + "last_response": "\u0641\u0631\u0622\u06cc\u0646\u062f \u062a\u0633\u062a \u0627\u062c\u0631\u0627\u06cc \u0627\u06a9\u0634\u0646\u200c\u062a\u06af\u200c\u0647\u0627\u06cc \u062d\u0627\u0641\u0638\u0647 \u0622\u063a\u0627\u0632 \u0634\u062f \u0648 \u0645\u0646\u062a\u0638\u0631 \u0646\u062a\u06cc\u062c\u0647 \u0627\u062c\u0631\u0627\u06cc \u0622\u0646 \u0647\u0633\u062a\u06cc\u0645.\n\u062f\u0631 \u062d\u0627\u0644 \u06a9\u0627\u0645\u067e\u0627\u06cc\u0644 \u0648 \u0627\u0639\u062a\u0628\u0627\u0631\u0633\u0646\u062c\u06cc \u0633\u06cc\u0646\u062a\u06a9\u0633 \u062a\u0645\u0627\u0645 \u0641\u0627\u06cc\u0644\u200c\u0647\u0627\u06cc \u067e\u0627\u06cc\u062a\u0648\u0646 \u067e\u0631\u0648\u0698\u0647 \u0647\u0633\u062a\u06cc\u0645.\n\u062a\u0633\u062a \u062c\u0627\u0645\u0639 \u06cc\u06a9\u067e\u0627\u0631\u0686\u0647\u200c\u0633\u0627\u0632\u06cc \u0648 \u0631\u0627\u0628\u0637 \u06a9\u0627\u0631\u0628\u0631\u06cc \u062d\u0627\u0641\u0638\u0647 \u0622\u063a\u0627\u0632 \u0634\u062f.\n\ud83c\udf89 **\u062a\u0645\u0627\u0645\u06cc \u0641\u0627\u0632\u0647\u0627\u06cc \u0633\u06cc\u0633\u062a\u0645 \u062d\u0627\u0641\u0638\u0647 \u0647\u0648\u0634 \u0645\u0635\u0646\u0648\u0639\u06cc \u06a9\u0627\u0631\u0628\u0631\u0627\u0646 \u0628\u0627 \u0645\u0648\u0641\u0642\u06cc\u062a \u067e\u06cc\u0627\u062f\u0647\u200c\u0633\u0627\u0632\u06cc\u060c \u06cc\u06a9\u067e\u0627\u0631\u0686\u0647\u200c\u0633\u0627\u0632\u06cc \u0648 \u062a\u0633\u062a \u0634\u062f!**\n\n---\n\n### \ud83d\udcca \u062e\u0644\u0627\u0635\u0647 \u062a\u063a\u06cc\u06cc\u0631\u0627\u062a \u0648 \u0642\u0627\u0628\u0644\u06cc\u062a\u200c\u0647\u0627\u06cc \u067e\u06cc\u0627\u062f\u0647\u200c\u0633\u0627\u0632\u06cc\u200c\u0634\u062f\u0647:\n\n#### \u06f1. \u0645\u0627\u0698\u0648\u0644 \u067e\u0627\u06cc\u06af\u0627\u0647 \u062f\u0627\u062f\u0647 \u0648 \u0645\u0648\u062a\u0648\u0631 \u0630\u062e\u06cc\u0631\u0647\u200c\u0633\u0627\u0632\u06cc (`memory_manager.py`)\n- \u0627\u06cc\u062c\u0627\u062f \u067e\u0627\u06cc\u06af\u0627\u0647 \u062f\u0627\u062f\u0647 \u0645\u0633\u062a\u0642\u0644 \u0648 \u067e\u0631\u0633\u0631\u0639\u062a SQLite \u062f\u0631 \u0645\u0633\u06cc\u0631 `/root/telegram-agy-bot/data/memory.db` \u0628\u0627 \u062d\u0627\u0644\u062a \u0647\u0645\u0632\u0645\u0627\u0646\u06cc **WAL**.\n- \u062a\u0641\u06a9\u06cc\u06a9 \u06a9\u0627\u0645\u0644 \u0648 \u0627\u06cc\u0632\u0648\u0644\u0647 \u062e\u0627\u0637\u0631\u0627\u062a \u0628\u0647 \u062f\u0648 \u0628\u062e\u0634:\n - **\ud83c\udf10 \u062e\u0627\u0637\u0631\u0627\u062a \u0639\u0645\u0648\u0645\u06cc (Global Memory):** \u0627\u0639\u0645\u0627\u0644\u200c\u0634\u062f\u0647 \u0628\u0631 \u062a\u0645\u0627\u0645 \u06a9\u0627\u0631\u0628\u0631\u0627\u0646 \u0648 \u0633\u0634\u0646\u200c\u0647\u0627 (\u0641\u0642\u0637 \u0628\u0627 \u062f\u0633\u062a\u0631\u0633\u06cc \u0645\u062f\u06cc\u0631 \u0633\u06cc\u0633\u062a\u0645).\n - **\ud83d\udc64 \u062e\u0627\u0637\u0631\u0627\u062a \u062e\u0635\u0648\u0635\u06cc (Private Memory):** \u0627\u06cc\u0632\u0648\u0644\u0647 \u0648 \u0627\u062e\u062a\u0635\u0627\u0635\u06cc \u0628\u0631\u0627\u06cc \u0647\u0631 \u06a9\u0627\u0631\u0628\u0631 \u0628\u0631 \u0627\u0633\u0627\u0633 \u0634\u0646\u0627\u0633\u0647 \u062a\u0644\u06af\u0631\u0627\u0645.\n- \u062c\u0644\u0648\u06af\u06cc\u0631\u06cc \u062e\u0648\u062f\u06a9\u0627\u0631 \u0627\u0632 \u062b\u0628\u062a \u0645\u0648\u0627\u0631\u062f \u062a\u06a9\u0631\u0627\u0631\u06cc \u0628\u0627 \u0645\u06a9\u0627\u0646\u06cc\u0633\u0645 \u06a9\u0644\u06cc\u062f \u06cc\u06a9\u062a\u0627 (`key-based deduplication`).\n\n#### \u06f2. \u062a\u0632\u0631\u06cc\u0642 \u0647\u0648\u0634\u0645\u0646\u062f \u062d\u0627\u0641\u0638\u0647 \u0628\u0647 \u067e\u0627\u06cc\u067e\u200c\u0644\u0627\u06cc\u0646 \u0647\u0648\u0634 \u0645\u0635\u0646\u0648\u0639\u06cc (`agy_engine.py`)\n- \u062f\u0631 \u0647\u0631 \u067e\u06cc\u0627\u0645 \u0627\u0631\u0633\u0627\u0644\u06cc\u060c \u0631\u0628\u0627\u062a \u0628\u0647 \u0635\u0648\u0631\u062a \u062e\u0648\u062f\u06a9\u0627\u0631 \u062e\u0627\u0637\u0631\u0627\u062a \u0639\u0645\u0648\u0645\u06cc \u0648 \u062e\u0627\u0637\u0631\u0627\u062a \u062e\u0635\u0648\u0635\u06cc \u0647\u0645\u0627\u0646 \u06a9\u0627\u0631\u0628\u0631 \u0631\u0627 \u0627\u0633\u062a\u062e\u0631\u0627\u062c \u0648 \u062f\u0631 \u0642\u0627\u0644\u0628 \u0628\u0644\u0648\u06a9 \u0627\u0633\u062a\u0627\u0646\u062f\u0627\u0631\u062f `[SYSTEM INSTRUCTION: AI PERSISTENT MEMORY]` \u0628\u0627 \u062d\u062f\u0627\u0642\u0644 \u0645\u0635\u0631\u0641 \u062a\u0648\u06a9\u0646 \u0628\u0647 \u0645\u062f\u0644 \u062a\u0632\u0631\u06cc\u0642 \u0645\u06cc\u200c\u06a9\u0646\u062f.\n\n#### \u06f3. \u0627\u06a9\u0634\u0646\u200c\u062a\u06af\u200c\u0647\u0627\u06cc \u067e\u0631\u062f\u0627\u0632\u0634 \u0648 \u06cc\u0627\u062f\u06af\u06cc\u0631\u06cc \u062e\u0648\u062f\u06a9\u0627\u0631 (`bot_actions.py`)\n- \u062b\u0628\u062a \u0648 \u062a\u0639\u0631\u06cc\u0641 \u0627\u06a9\u0634\u0646\u200c\u0647\u0627\u06cc \u0632\u06cc\u0631 \u062f\u0631 \u0645\u0641\u0633\u0631 \u0631\u0628\u0627\u062a:\n - `SAVE_MEMORY`: \u0630\u062e\u06cc\u0631\u0647\u200c\u0633\u0627\u0632\u06cc \u062e\u0627\u0637\u0631\u0647 \u06cc\u0627 \u062a\u0631\u062c\u06cc\u062d \u062c\u062f\u06cc\u062f \u0628\u0627 \u062f\u0633\u062a\u0647\u200c\u0628\u0646\u062f\u06cc \u0648 \u0627\u0647\u0645\u06cc\u062a\n - `UPDATE_MEMORY`: \u0648\u06cc\u0631\u0627\u06cc\u0634 \u0648 \u0628\u0647\u200c\u0631\u0648\u0632\u0631\u0633\u0627\u0646\u06cc \u062e\u0627\u0637\u0631\u0647 \u0645\u0648\u062c\u0648\u062f\n - `DELETE_MEMORY`: \u062d\u0630\u0641 \u06cc\u06a9 \u062e\u0627\u0637\u0631\u0647 \u0645\u0634\u062e\u0635\n - `CLEAR_MEMORY`: \u067e\u0627\u06a9\u200c\u0633\u0627\u0632\u06cc \u06a9\u0627\u0645\u0644 \u062e\u0627\u0637\u0631\u0627\u062a \u062e\u0635\u0648\u0635\u06cc \u06cc\u0627 \u0639\u0645\u0648\u0645\u06cc\n- **\u06af\u06cc\u062a \u0627\u0645\u0646\u06cc\u062a\u06cc:** \u0627\u0639\u062a\u0628\u0627\u0631\u0633\u0646\u062c\u06cc \u0633\u0637\u062d \u062f\u0633\u062a\u0631\u0633\u06cc \u0627\u062f\u0645\u06cc\u0646 \u062c\u0647\u062a \u062c\u0644\u0648\u06af\u06cc\u0631\u06cc \u0627\u0632 \u0648\u06cc\u0631\u0627\u06cc\u0634 \u06cc\u0627 \u0633\u0627\u062e\u062a \u062e\u0627\u0637\u0631\u0627\u062a \u0639\u0645\u0648\u0645\u06cc \u062a\u0648\u0633\u0637 \u06a9\u0627\u0631\u0628\u0631\u0627\u0646 \u0639\u0627\u062f\u06cc.\n\n#### \u06f4. \u067e\u0646\u0644 \u062a\u0639\u0627\u0645\u0644\u06cc \u0648 \u062f\u0633\u062a\u0648\u0631\u0627\u062a \u062a\u0644\u06af\u0631\u0627\u0645 (`bot.py`)\n- \u0627\u0641\u0632\u0648\u062f\u0646 \u062f\u0633\u062a\u0648\u0631 `/memory` (\u0648 \u0646\u0627\u0645\u200c\u0647\u0627\u06cc \u0645\u0633\u062a\u0639\u0627\u0631 `/memories` \u0648 `/hafeze`)\n- \u0627\u0641\u0632\u0648\u062f\u0646 \u062f\u06a9\u0645\u0647 \u0634\u06cc\u0634\u0647\u200c\u0627\u06cc **\u00ab\ud83e\udde0 \u062d\u0627\u0641\u0638\u0647 \u0647\u0648\u0634 \u0645\u0635\u0646\u0648\u0639\u06cc\u00bb** \u0628\u0647 \u0645\u0646\u0648\u06cc \u0627\u0635\u0644\u06cc \u062f\u0627\u0634\u0628\u0648\u0631\u062f \u0648 \u0645\u0646\u0648\u06cc \u062a\u0646\u0638\u06cc\u0645\u0627\u062a\n- \u0627\u0645\u06a9\u0627\u0646 \u0645\u0634\u0627\u0647\u062f\u0647 \u0644\u06cc\u0633\u062a \u062e\u0627\u0637\u0631\u0627\u062a \u0628\u0627 \u0635\u0641\u062d\u0647\u200c\u0628\u0646\u062f\u06cc (Pagination)\u060c \u0633\u0648\u0626\u06cc\u0686 \u062a\u0628 \u0628\u06cc\u0646 \u062e\u0627\u0637\u0631\u0627\u062a \u0645\u0646 \u0648 \u0639\u0645\u0648\u0645\u06cc\u060c \u062d\u0630\u0641 \u062a\u06a9\u06cc \u0647\u0631 \u062e\u0627\u0637\u0631\u0647\u060c \u0648 \u067e\u0627\u06a9\u200c\u0633\u0627\u0632\u06cc \u06a9\u0627\u0645\u0644\n- \u0628\u0647\u200c\u0631\u0648\u0632\u0631\u0633\u0627\u0646\u06cc \u0645\u0646\u0648\u06cc \u0631\u0627\u0647\u0646\u0645\u0627 (`/help`) \u0648 \u0644\u06cc\u0633\u062a \u062f\u0633\u062a\u0648\u0631\u0627\u062a \u0631\u0628\u0627\u062a (`BotCommand`)\n\n---\n\n[[RESTART_BOT]]\n\n\u2022 \u0646\u0627\u0645 \u067e\u0631\u0648\u0698\u0647: default\n\u2022 \u0622\u062f\u0631\u0633 \u0645\u062e\u0632\u0646: https://git.msa.artacloud.ir/root/default\n", "last_status_msg_id": null, "restart_pending": false, "last_delivered": true, - "last_update_time": 1788069497.0166173, + "last_update_time": 1788069822.8331306, "workspace": "/root", "conversation_id": "d54c0c8d-6424-40a4-84f4-7a9de60eac7b", "model": "gemini-3.7-flash-auto", "effort": "high", "language": "fa", - "last_context_length": 21661, - "last_total_tokens": 265643 + "last_context_length": 59015, + "last_total_tokens": 559030 }, "232801087": { "chat_id": 232801087, @@ -154,5 +154,43 @@ "language": "fa", "last_context_length": null, "last_total_tokens": null + }, + "8896969833": { + "chat_id": 8896969833, + "active_project": "test", + "projects": { + "test": { + "name": "test", + "workspace": "/root/projects/8896969833/test", + "owner_id": 8896969833, + "shared_with": [], + "conversation_id": "3f7359a9-d339-46f5-bb36-efc7cd6b6db7", + "conversation_history": [ + "3f7359a9-d339-46f5-bb36-efc7cd6b6db7" + ], + "model": "gemini-3.7-flash", + "effort": "high", + "language": "fa", + "last_context_length": 4426, + "last_total_tokens": 46918, + "last_response": "\u06a9\u062f \u0645\u0646\u0628\u0639 \u0648 \u062a\u0645\u0627\u0645\u06cc \u0645\u0627\u0698\u0648\u0644\u200c\u0647\u0627\u06cc \u0631\u0628\u0627\u062a \u062a\u0644\u06af\u0631\u0627\u0645 \u062f\u0631 \u0645\u0633\u06cc\u0631 `/root/telegram-agy-bot` \u062f\u0631 \u062f\u0633\u062a\u0631\u0633 \u0648 \u0622\u0645\u0627\u062f\u0647 \u0648\u06cc\u0631\u0627\u06cc\u0634 \u0647\u0633\u062a\u0646\u062f.\n\n### \ud83d\udcc2 \u0633\u0627\u062e\u062a\u0627\u0631 \u0645\u0627\u0698\u0648\u0644\u200c\u0647\u0627\u06cc \u0627\u0635\u0644\u06cc \u0631\u0628\u0627\u062a:\n- **`bot.py`**: \u0647\u0633\u062a\u0647 \u0627\u0635\u0644\u06cc \u0631\u0628\u0627\u062a\u060c \u0645\u062f\u06cc\u0631\u06cc\u062a \u062f\u0633\u062a\u0648\u0631\u0627\u062a (`/start`, `/model`, `/projects`, `/tasks` \u0648...) \u0648 \u0647\u0646\u062f\u0644\u0631\u0647\u0627\u06cc \u062a\u0644\u06af\u0631\u0627\u0645.\n- **`bot_actions.py`**: \u0633\u06cc\u0633\u062a\u0645 \u062a\u062d\u0644\u06cc\u0644 \u0648 \u0627\u062c\u0631\u0627\u06cc \u062e\u0648\u062f\u06a9\u0627\u0631 \u062f\u0633\u062a\u0648\u0631\u0627\u062a \u0647\u0648\u0634 \u0645\u0635\u0646\u0648\u0639\u06cc (\u0645\u062f\u06cc\u0631\u06cc\u062a \u067e\u0631\u0648\u0698\u0647\u200c\u0647\u0627\u060c \u0632\u0645\u0627\u0646\u200c\u0628\u0646\u062f\u06cc \u062a\u0633\u06a9\u200c\u0647\u0627\u060c \u0633\u0627\u0628\u200c\u062f\u0627\u0645\u06cc\u0646\u200c\u0647\u0627\u06cc Caddy\u060c \u062a\u063a\u06cc\u06cc\u0631 \u0645\u062f\u0644 \u0648...).\n- **`agy_engine.py`**: \u0645\u0648\u062a\u0648\u0631 \u067e\u0631\u062f\u0627\u0632\u0634 \u0648 \u0627\u0633\u062a\u0631\u06cc\u0645 \u0632\u0646\u062f\u0647 \u067e\u0627\u0633\u062e\u200c\u0647\u0627\u06cc \u0647\u0648\u0634 \u0645\u0635\u0646\u0648\u0639\u06cc \u0648 \u0627\u062c\u0631\u0627\u06cc \u062a\u0633\u06a9\u200c\u0647\u0627.\n- **`formatters.py`**: \u0642\u0627\u0644\u0628\u200c\u0628\u0646\u062f\u06cc \u062e\u0631\u0648\u062c\u06cc\u200c\u0647\u0627\u060c \u067e\u06cc\u0627\u0645\u200c\u0647\u0627\u06cc \u062a\u0644\u06af\u0631\u0627\u0645 (HTML)\u060c \u062a\u0641\u06a9\u06cc\u06a9 \u0628\u0644\u0627\u06a9\u200c\u0647\u0627\u06cc \u0641\u06a9\u0631\u06a9\u0631\u062f\u0646 \u0648 \u06a9\u062f\u0647\u0627.\n- **`scheduler.py`**: \u0633\u06cc\u0633\u062a\u0645 \u0632\u0645\u0627\u0646\u200c\u0628\u0646\u062f\u06cc \u067e\u06cc\u0634\u0631\u0641\u062a\u0647 (Cron Jobs\u060c \u062a\u0633\u06a9\u200c\u0647\u0627\u06cc \u062f\u0648\u0631\u0647\u200c\u0627\u06cc \u0648 \u06cc\u0627\u062f\u0622\u0648\u0631\u0647\u0627).\n- **`git_manager.py`**: \u0645\u062f\u06cc\u0631\u06cc\u062a \u06af\u06cc\u062a \u0648 \u0627\u062a\u0635\u0627\u0644 \u0628\u0647 Gitea.\n- **`memory_manager.py` / `sessions.json`**: \u0645\u062f\u06cc\u0631\u06cc\u062a \u0646\u0634\u0633\u062a\u200c\u0647\u0627\u060c \u062a\u0627\u0631\u06cc\u062e\u0686\u0647 \u0648 \u0627\u0637\u0644\u0627\u0639\u0627\u062a \u06a9\u0627\u0631\u0628\u0631\u0627\u0646.\n- **`sys_monitor.py` / `usage_monitor.py`**: \u0645\u0627\u0646\u06cc\u062a\u0648\u0631\u06cc\u0646\u06af \u0645\u0646\u0627\u0628\u0639 \u0633\u0631\u0648\u0631 \u0648 \u0645\u0635\u0631\u0641 \u0633\u0647\u0645\u06cc\u0647\u200c\u0647\u0627.\n- **`voice_transcriber.py` / `web_uploader.py`**: \u0645\u0627\u0698\u0648\u0644 \u062a\u0628\u062f\u06cc\u0644 \u0635\u0648\u062a \u0648 \u067e\u0646\u0644 \u0648\u0628 \u0622\u067e\u0644\u0648\u062f \u0641\u0627\u06cc\u0644\u200c\u0647\u0627.\n\n---\n\n**\u062f\u0642\u06cc\u0642\u0627\u064b \u0686\u0647 \u062a\u063a\u06cc\u06cc\u0631\u0627\u062a\u06cc \u0645\u062f \u0646\u0638\u0631\u062a\u0627\u0646 \u0627\u0633\u062a\u061f**\n(\u0628\u0631\u0627\u06cc \u0645\u062b\u0627\u0644: \u0627\u0641\u0632\u0648\u062f\u0646 \u0642\u0627\u0628\u0644\u06cc\u062a \u06cc\u0627 \u062f\u0633\u062a\u0648\u0631 \u062c\u062f\u06cc\u062f\u060c \u062a\u063a\u06cc\u06cc\u0631 \u0646\u062d\u0648\u0647 \u067e\u0627\u0633\u062e\u200c\u062f\u0647\u06cc \u0648 \u0645\u0646\u0648\u0647\u0627\u060c \u0627\u0635\u0644\u0627\u062d \u0645\u0646\u0637\u0642 \u06cc\u06a9 \u0645\u0627\u0698\u0648\u0644\u060c \u06cc\u0627 \u0634\u062e\u0635\u06cc\u200c\u0633\u0627\u0632\u06cc \u0641\u0631\u0622\u06cc\u0646\u062f\u0647\u0627)\n\n\u0644\u0637\u0641\u0627\u064b \u0628\u0641\u0631\u0645\u0627\u06cc\u06cc\u062f \u062a\u0627 \u062a\u063a\u06cc\u06cc\u0631\u0627\u062a \u0631\u0627 \u0627\u0639\u0645\u0627\u0644 \u06a9\u0646\u0645 \u0648 \u062f\u0631 \u0635\u0648\u0631\u062a \u0646\u06cc\u0627\u0632 \u0628\u0627 `[[RESTART_BOT]]` \u0631\u0628\u0627\u062a \u0631\u0627 \u0645\u062c\u062f\u062f\u0627\u064b \u0631\u0627\u0647\u200c\u0627\u0646\u062f\u0627\u0632\u06cc \u06a9\u0646\u06cc\u0645.\n", + "created_at": 1788069553.9717174, + "description": "" + } + }, + "turn_in_progress": false, + "last_prompt": "\u0645\u06cc\u062e\u0648\u0627\u0645 \u062e\u0648\u062f \u0631\u0628\u0627\u062a \u06a9\u0646\u062a\u0631\u0644 \u06af\u0631 \u0647\u0648\u0634 \u0645\u0635\u0646\u0648\u0639\u06cc \u0631\u0627 \u0648\u06cc\u0631\u0627\u06cc\u0634 \u06a9\u0646\u0645", + "last_response": "\u06a9\u062f \u0645\u0646\u0628\u0639 \u0648 \u062a\u0645\u0627\u0645\u06cc \u0645\u0627\u0698\u0648\u0644\u200c\u0647\u0627\u06cc \u0631\u0628\u0627\u062a \u062a\u0644\u06af\u0631\u0627\u0645 \u062f\u0631 \u0645\u0633\u06cc\u0631 `/root/telegram-agy-bot` \u062f\u0631 \u062f\u0633\u062a\u0631\u0633 \u0648 \u0622\u0645\u0627\u062f\u0647 \u0648\u06cc\u0631\u0627\u06cc\u0634 \u0647\u0633\u062a\u0646\u062f.\n\n### \ud83d\udcc2 \u0633\u0627\u062e\u062a\u0627\u0631 \u0645\u0627\u0698\u0648\u0644\u200c\u0647\u0627\u06cc \u0627\u0635\u0644\u06cc \u0631\u0628\u0627\u062a:\n- **`bot.py`**: \u0647\u0633\u062a\u0647 \u0627\u0635\u0644\u06cc \u0631\u0628\u0627\u062a\u060c \u0645\u062f\u06cc\u0631\u06cc\u062a \u062f\u0633\u062a\u0648\u0631\u0627\u062a (`/start`, `/model`, `/projects`, `/tasks` \u0648...) \u0648 \u0647\u0646\u062f\u0644\u0631\u0647\u0627\u06cc \u062a\u0644\u06af\u0631\u0627\u0645.\n- **`bot_actions.py`**: \u0633\u06cc\u0633\u062a\u0645 \u062a\u062d\u0644\u06cc\u0644 \u0648 \u0627\u062c\u0631\u0627\u06cc \u062e\u0648\u062f\u06a9\u0627\u0631 \u062f\u0633\u062a\u0648\u0631\u0627\u062a \u0647\u0648\u0634 \u0645\u0635\u0646\u0648\u0639\u06cc (\u0645\u062f\u06cc\u0631\u06cc\u062a \u067e\u0631\u0648\u0698\u0647\u200c\u0647\u0627\u060c \u0632\u0645\u0627\u0646\u200c\u0628\u0646\u062f\u06cc \u062a\u0633\u06a9\u200c\u0647\u0627\u060c \u0633\u0627\u0628\u200c\u062f\u0627\u0645\u06cc\u0646\u200c\u0647\u0627\u06cc Caddy\u060c \u062a\u063a\u06cc\u06cc\u0631 \u0645\u062f\u0644 \u0648...).\n- **`agy_engine.py`**: \u0645\u0648\u062a\u0648\u0631 \u067e\u0631\u062f\u0627\u0632\u0634 \u0648 \u0627\u0633\u062a\u0631\u06cc\u0645 \u0632\u0646\u062f\u0647 \u067e\u0627\u0633\u062e\u200c\u0647\u0627\u06cc \u0647\u0648\u0634 \u0645\u0635\u0646\u0648\u0639\u06cc \u0648 \u0627\u062c\u0631\u0627\u06cc \u062a\u0633\u06a9\u200c\u0647\u0627.\n- **`formatters.py`**: \u0642\u0627\u0644\u0628\u200c\u0628\u0646\u062f\u06cc \u062e\u0631\u0648\u062c\u06cc\u200c\u0647\u0627\u060c \u067e\u06cc\u0627\u0645\u200c\u0647\u0627\u06cc \u062a\u0644\u06af\u0631\u0627\u0645 (HTML)\u060c \u062a\u0641\u06a9\u06cc\u06a9 \u0628\u0644\u0627\u06a9\u200c\u0647\u0627\u06cc \u0641\u06a9\u0631\u06a9\u0631\u062f\u0646 \u0648 \u06a9\u062f\u0647\u0627.\n- **`scheduler.py`**: \u0633\u06cc\u0633\u062a\u0645 \u0632\u0645\u0627\u0646\u200c\u0628\u0646\u062f\u06cc \u067e\u06cc\u0634\u0631\u0641\u062a\u0647 (Cron Jobs\u060c \u062a\u0633\u06a9\u200c\u0647\u0627\u06cc \u062f\u0648\u0631\u0647\u200c\u0627\u06cc \u0648 \u06cc\u0627\u062f\u0622\u0648\u0631\u0647\u0627).\n- **`git_manager.py`**: \u0645\u062f\u06cc\u0631\u06cc\u062a \u06af\u06cc\u062a \u0648 \u0627\u062a\u0635\u0627\u0644 \u0628\u0647 Gitea.\n- **`memory_manager.py` / `sessions.json`**: \u0645\u062f\u06cc\u0631\u06cc\u062a \u0646\u0634\u0633\u062a\u200c\u0647\u0627\u060c \u062a\u0627\u0631\u06cc\u062e\u0686\u0647 \u0648 \u0627\u0637\u0644\u0627\u0639\u0627\u062a \u06a9\u0627\u0631\u0628\u0631\u0627\u0646.\n- **`sys_monitor.py` / `usage_monitor.py`**: \u0645\u0627\u0646\u06cc\u062a\u0648\u0631\u06cc\u0646\u06af \u0645\u0646\u0627\u0628\u0639 \u0633\u0631\u0648\u0631 \u0648 \u0645\u0635\u0631\u0641 \u0633\u0647\u0645\u06cc\u0647\u200c\u0647\u0627.\n- **`voice_transcriber.py` / `web_uploader.py`**: \u0645\u0627\u0698\u0648\u0644 \u062a\u0628\u062f\u06cc\u0644 \u0635\u0648\u062a \u0648 \u067e\u0646\u0644 \u0648\u0628 \u0622\u067e\u0644\u0648\u062f \u0641\u0627\u06cc\u0644\u200c\u0647\u0627.\n\n---\n\n**\u062f\u0642\u06cc\u0642\u0627\u064b \u0686\u0647 \u062a\u063a\u06cc\u06cc\u0631\u0627\u062a\u06cc \u0645\u062f \u0646\u0638\u0631\u062a\u0627\u0646 \u0627\u0633\u062a\u061f**\n(\u0628\u0631\u0627\u06cc \u0645\u062b\u0627\u0644: \u0627\u0641\u0632\u0648\u062f\u0646 \u0642\u0627\u0628\u0644\u06cc\u062a \u06cc\u0627 \u062f\u0633\u062a\u0648\u0631 \u062c\u062f\u06cc\u062f\u060c \u062a\u063a\u06cc\u06cc\u0631 \u0646\u062d\u0648\u0647 \u067e\u0627\u0633\u062e\u200c\u062f\u0647\u06cc \u0648 \u0645\u0646\u0648\u0647\u0627\u060c \u0627\u0635\u0644\u0627\u062d \u0645\u0646\u0637\u0642 \u06cc\u06a9 \u0645\u0627\u0698\u0648\u0644\u060c \u06cc\u0627 \u0634\u062e\u0635\u06cc\u200c\u0633\u0627\u0632\u06cc \u0641\u0631\u0622\u06cc\u0646\u062f\u0647\u0627)\n\n\u0644\u0637\u0641\u0627\u064b \u0628\u0641\u0631\u0645\u0627\u06cc\u06cc\u062f \u062a\u0627 \u062a\u063a\u06cc\u06cc\u0631\u0627\u062a \u0631\u0627 \u0627\u0639\u0645\u0627\u0644 \u06a9\u0646\u0645 \u0648 \u062f\u0631 \u0635\u0648\u0631\u062a \u0646\u06cc\u0627\u0632 \u0628\u0627 `[[RESTART_BOT]]` \u0631\u0628\u0627\u062a \u0631\u0627 \u0645\u062c\u062f\u062f\u0627\u064b \u0631\u0627\u0647\u200c\u0627\u0646\u062f\u0627\u0632\u06cc \u06a9\u0646\u06cc\u0645.\n", + "last_status_msg_id": null, + "restart_pending": false, + "last_delivered": true, + "last_update_time": 1788069702.2900536, + "workspace": "/root/projects/8896969833/test", + "conversation_id": "3f7359a9-d339-46f5-bb36-efc7cd6b6db7", + "model": "gemini-3.7-flash", + "effort": "high", + "language": "fa", + "last_context_length": 4426, + "last_total_tokens": 46918 } } \ No newline at end of file