AI Update: برو فاز بعدی
This commit is contained in:
Submodule
+1
Submodule projects/8896969833/test added at 4bd584607e
@@ -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
|
||||
|
||||
|
||||
+284
-7
@@ -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"🧠 <b>کنترلپنل حافظه هوشمند هوش مصنوعی (AI Long-Term Memory)</b>\n\n"
|
||||
f"• 📂 <b>بخش فعال:</b> {tab_name}\n"
|
||||
f"• 📊 <b>آمار کل:</b> <code>{stats['total_memories']}</code> خاطره (<code>{stats['global_memories']}</code> عمومی | <code>{stats['private_memories']}</code> خصوصی)\n\n"
|
||||
)
|
||||
if not memories:
|
||||
body = (
|
||||
f"ℹ️ <i>در این بخش هنوز هیچ خاطرهای ثبت نشده است.</i>\n\n"
|
||||
f"💡 <b>یادگیری خودکار:</b> هوش مصنوعی به صورت خودکار در خلال گفتگوها، عادات، نام و نکات مهم شما را استخراج و ذخیره میکند."
|
||||
)
|
||||
else:
|
||||
body_lines = [f"<b>لیست خاطرات (صفحه {page + 1} از {max_pages}):</b>\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"<b>{idx}.</b> 🔑 <code>{escape_html(m.key)}</code> {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"🧠 <b>AI Long-Term Memory Dashboard</b>\n\n"
|
||||
f"• 📂 <b>Active Tab:</b> {tab_name}\n"
|
||||
f"• 📊 <b>Stats:</b> <code>{stats['total_memories']}</code> total (<code>{stats['global_memories']}</code> global | <code>{stats['private_memories']}</code> private)\n\n"
|
||||
)
|
||||
if not memories:
|
||||
body = "ℹ️ <i>No memories recorded in this section yet.</i>\n\n💡 <i>The AI automatically extracts durable facts and preferences during conversations.</i>"
|
||||
else:
|
||||
body_lines = [f"<b>Memories list (Page {page + 1} of {max_pages}):</b>\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"<b>{idx}.</b> 🔑 <code>{escape_html(m.key)}</code> {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"• <code>/model</code> - انتخاب مدل هوش مصنوعی\n"
|
||||
f"• <code>/lang [زبان]</code> - تغییر زبان پاسخدهی (مثلاً <code>/lang fa</code>)\n"
|
||||
f"• <code>/effort [low|med|high]</code> - تنظیم عمق تفکر استدلالی\n"
|
||||
f"• <code>/workspace [مسیر]</code> - تغییر دایرکتوری کاری پروژه فعال\n\n"
|
||||
f"<b>🧠 حافظه بلندمدت هوش مصنوعی (AI Memory):</b>\n"
|
||||
f"• <code>/memory</code> - کنترلپنل تعاملی حافظه هوشمند، مشاهده و پاکسازی خاطرات\n"
|
||||
f"• <code>/memory global</code> - مشاهده قوانین و خاطرات عمومی کل سیستم\n"
|
||||
f"• <code>/memory private</code> - مشاهده خاطرات اختصاصی و شخصی شما\n"
|
||||
f"• <code>/memory clear</code> - پاکسازی خاطرات اختصاصی شما\n"
|
||||
f"• <i>هوش مصنوعی در طول مکالمات، نکات کلیدی و ترجیحات شما را به صورت خودکار به خاطر میسپارد!</i>\n\n"
|
||||
f"<b>👑 مدیریت کاربران و دعوتها (ویژه مدیر):</b>\n"
|
||||
f"• <code>/users</code> - پنل تعاملی مدیریت کاربران و لیست مجاز\n"
|
||||
f"• <code>/invite <user_id></code> - دعوت و اعطای مستقیم دسترسی به کاربر\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"🧹 <b>تعداد {cnt} خاطره {type_label} با موفقیت پاکسازی شد.</b>" if is_fa else f"🧹 <b>{cnt} {target_type} memories cleared.</b>"
|
||||
except PermissionError:
|
||||
msg = "🚫 <b>خطای دسترسی: فقط ادمین مجاز به پاکسازی خاطرات عمومی است.</b>" if is_fa else "🚫 <b>Access denied.</b>"
|
||||
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"🗑️ <b>آیا از حذف این خاطره اطمینان دارید؟</b>\n\n"
|
||||
f"• 🔑 <b>کلید:</b> <code>{escape_html(mem.key)}</code>\n"
|
||||
f"• 📝 <b>محتوا:</b> {escape_html(mem.content)}"
|
||||
if is_fa
|
||||
else
|
||||
f"🗑️ <b>Are you sure you want to delete this memory?</b>\n\n"
|
||||
f"• 🔑 <b>Key:</b> <code>{escape_html(mem.key)}</code>\n"
|
||||
f"• 📝 <b>Content:</b> {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"⚠️ <b>هشدار پاکسازی حافظه</b>\n\n"
|
||||
f"آیا مطمئن هستید که میخواهید تمام خاطرات <b>{type_label}</b> را به صورت کامل پاک کنید؟ این عملیات غیرقابل بازگشت است."
|
||||
if is_fa
|
||||
else
|
||||
f"⚠️ <b>Warning: Clear Memory</b>\n\n"
|
||||
f"Are you sure you want to permanently clear all <b>{v_type}</b> 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))
|
||||
|
||||
@@ -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🧠 <b>خاطره هوش مصنوعی ثبت شد:</b>\n"
|
||||
f"• 🏷️ <b>نوع:</b> {type_label}\n"
|
||||
f"• 🔑 <b>کلید:</b> <code>{escape_html(item.key)}</code>\n"
|
||||
f"• 📂 <b>دسته:</b> <code>{escape_html(item.category)}</code>\n"
|
||||
f"• 📝 <b>محتوا:</b> {escape_html(item.content)}"
|
||||
if is_fa
|
||||
else
|
||||
f"\n\n🧠 <b>AI Memory Saved:</b>\n"
|
||||
f"• 🏷️ <b>Type:</b> {'Global' if item.is_global else 'Private'}\n"
|
||||
f"• 🔑 <b>Key:</b> <code>{escape_html(item.key)}</code>\n"
|
||||
f"• 📂 <b>Category:</b> <code>{escape_html(item.category)}</code>\n"
|
||||
f"• 📝 <b>Content:</b> {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🧠 <b>خاطره هوش مصنوعی بهروزرسانی شد:</b>\n"
|
||||
f"• 🏷️ <b>نوع:</b> {type_label}\n"
|
||||
f"• 🔑 <b>کلید:</b> <code>{escape_html(item.key)}</code>\n"
|
||||
f"• 📝 <b>محتوای جدید:</b> {escape_html(item.content)}"
|
||||
if is_fa
|
||||
else
|
||||
f"\n\n🧠 <b>AI Memory Updated:</b>\n"
|
||||
f"• 🏷️ <b>Type:</b> {'Global' if item.is_global else 'Private'}\n"
|
||||
f"• 🔑 <b>Key:</b> <code>{escape_html(item.key)}</code>\n"
|
||||
f"• 📝 <b>New Content:</b> {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🗑️ <b>خاطره مورد نظر از حافظه هوش مصنوعی حذف گردید.</b>" if is_fa else f"\n\n🗑️ <b>Memory forgotten successfully.</b>"
|
||||
else:
|
||||
badge = f"\n⚠️ خاطرهای با این مشخصات یافت نشد." if is_fa else f"\n⚠️ Memory not found."
|
||||
except PermissionError:
|
||||
badge = "\n🚫 <i>خطای دسترسی: ویرایش یا حذف خاطرات عمومی تنها توسط مدیر سیستم امکانپذیر است.</i>" if is_fa else "\n🚫 <i>Access Denied: Only administrators can modify global memories.</i>"
|
||||
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🧹 <b>حافظه {type_label} پاکسازی شد ({count} مورد حذف گردید).</b>"
|
||||
if is_fa
|
||||
else
|
||||
f"\n\n🧹 <b>{mem_type.capitalize()} memory cleared ({count} items purged).</b>"
|
||||
)
|
||||
except PermissionError:
|
||||
badge = "\n🚫 <i>خطای دسترسی: پاکسازی خاطرات عمومی تنها توسط مدیر امکانپذیر است.</i>" if is_fa else "\n🚫 <i>Access Denied: Only admins can clear global memories.</i>"
|
||||
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<i>[اکشن ناشناخته: {action_name}]</i>" if is_fa else f"\n<i>[Unknown action: {action_name}]</i>", 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=\"<project_optional>\"]]\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=\"<unique_slug>\", category=\"<category>\", content=\"<concise_summary>\"]]\n"
|
||||
" (Saves durable facts/preferences. type defaults to 'private'. Only admin can create 'global').\n"
|
||||
" [[UPDATE_MEMORY: key=\"<slug>\", content=\"<new_content>\"]]\n"
|
||||
" [[DELETE_MEMORY: key=\"<slug>\"]]\n"
|
||||
" [[CLEAR_MEMORY: type=\"private|global\"]]\n\n"
|
||||
"Always explain to the user in a friendly and professional tone what actions have been performed."
|
||||
)
|
||||
|
||||
Binary file not shown.
@@ -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": {}
|
||||
|
||||
File diff suppressed because one or more lines are too long
Reference in New Issue
Block a user