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:
|
except Exception as ex:
|
||||||
logger.warning(f"Failed to load bot actions instruction: {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:
|
if system_instructions:
|
||||||
effective_prompt = "\n\n".join(system_instructions) + "\n\n" + prompt
|
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_tasks_menu"),
|
||||||
],
|
],
|
||||||
[
|
[
|
||||||
|
InlineKeyboardButton("🧠 حافظه هوش مصنوعی", callback_data="btn_memory_menu"),
|
||||||
InlineKeyboardButton("📈 سهمیه مصرف (AGY)", callback_data="btn_usage_menu"),
|
InlineKeyboardButton("📈 سهمیه مصرف (AGY)", callback_data="btn_usage_menu"),
|
||||||
|
],
|
||||||
|
[
|
||||||
InlineKeyboardButton("🖥 سختافزار سرور", callback_data="btn_hw_menu"),
|
InlineKeyboardButton("🖥 سختافزار سرور", callback_data="btn_hw_menu"),
|
||||||
],
|
|
||||||
[
|
|
||||||
InlineKeyboardButton("🐙 گیت (Gitea)", callback_data="btn_git_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_restart"),
|
||||||
|
],
|
||||||
|
[
|
||||||
InlineKeyboardButton("📖 راهنما", callback_data="btn_help_menu"),
|
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("⏰ Schedule", callback_data="btn_tasks_menu"),
|
||||||
],
|
],
|
||||||
[
|
[
|
||||||
|
InlineKeyboardButton("🧠 AI Memory", callback_data="btn_memory_menu"),
|
||||||
InlineKeyboardButton("📈 Quota & Usage", callback_data="btn_usage_menu"),
|
InlineKeyboardButton("📈 Quota & Usage", callback_data="btn_usage_menu"),
|
||||||
|
],
|
||||||
|
[
|
||||||
InlineKeyboardButton("🖥 Server Hardware", callback_data="btn_hw_menu"),
|
InlineKeyboardButton("🖥 Server Hardware", callback_data="btn_hw_menu"),
|
||||||
],
|
|
||||||
[
|
|
||||||
InlineKeyboardButton("🐙 Git (Gitea)", callback_data="btn_git_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("🔄 New Chat", callback_data="btn_restart"),
|
||||||
|
],
|
||||||
|
[
|
||||||
InlineKeyboardButton("📖 Bot Guide", callback_data="btn_help_menu"),
|
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("⚡ سطح تفکر / استدلال (Effort)", callback_data="btn_effort_menu"),
|
||||||
],
|
],
|
||||||
|
[
|
||||||
|
InlineKeyboardButton("🧠 مدیریت حافظه هوش مصنوعی", callback_data="btn_memory_menu"),
|
||||||
|
],
|
||||||
[
|
[
|
||||||
InlineKeyboardButton("🌐 زبان پاسخدهی", callback_data="btn_lang_menu"),
|
InlineKeyboardButton("🌐 زبان پاسخدهی", callback_data="btn_lang_menu"),
|
||||||
InlineKeyboardButton("📊 وضعیت و کانتکست", callback_data="btn_status_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("⚡ 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("🌐 Response Language", callback_data="btn_lang_menu"),
|
||||||
InlineKeyboardButton("📊 Status & Tokens", callback_data="btn_status_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
|
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]:
|
def build_tasks_menu(chat_id: int, page: int = 0) -> tuple[str, InlineKeyboardMarkup]:
|
||||||
"""Builds interactive Scheduled Tasks manager dashboard with pagination and status buttons."""
|
"""Builds interactive Scheduled Tasks manager dashboard with pagination and status buttons."""
|
||||||
session = session_manager.get_or_create(chat_id)
|
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>/model</code> - انتخاب مدل هوش مصنوعی\n"
|
||||||
f"• <code>/lang [زبان]</code> - تغییر زبان پاسخدهی (مثلاً <code>/lang fa</code>)\n"
|
f"• <code>/lang [زبان]</code> - تغییر زبان پاسخدهی (مثلاً <code>/lang fa</code>)\n"
|
||||||
f"• <code>/effort [low|med|high]</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"<b>👑 مدیریت کاربران و دعوتها (ویژه مدیر):</b>\n"
|
||||||
f"• <code>/users</code> - پنل تعاملی مدیریت کاربران و لیست مجاز\n"
|
f"• <code>/users</code> - پنل تعاملی مدیریت کاربران و لیست مجاز\n"
|
||||||
f"• <code>/invite <user_id></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)
|
text, markup = await build_usage_report(chat_id)
|
||||||
await status_msg.edit_text(text, parse_mode=constants.ParseMode.HTML, reply_markup=markup)
|
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
|
# Command: /context or /tokens
|
||||||
@check_auth
|
@check_auth
|
||||||
async def context_command(update: Update, context: ContextTypes.DEFAULT_TYPE):
|
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),
|
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":
|
elif data == "btn_tasks_menu":
|
||||||
text, markup = build_tasks_menu(chat_id, page=0)
|
text, markup = build_tasks_menu(chat_id, page=0)
|
||||||
try:
|
try:
|
||||||
@@ -5811,6 +6086,7 @@ async def on_startup(app: Application):
|
|||||||
try:
|
try:
|
||||||
commands = [
|
commands = [
|
||||||
BotCommand("start", "کنترلپنل اصلی / Main dashboard"),
|
BotCommand("start", "کنترلپنل اصلی / Main dashboard"),
|
||||||
|
BotCommand("memory", "حافظه هوش مصنوعی / AI Memory"),
|
||||||
BotCommand("projects", "مدیریت پروژهها / Manage projects"),
|
BotCommand("projects", "مدیریت پروژهها / Manage projects"),
|
||||||
BotCommand("newproject", "ساخت پروژه جدید / Create project"),
|
BotCommand("newproject", "ساخت پروژه جدید / Create project"),
|
||||||
BotCommand("switch", "سوییچ پروژه / Switch project"),
|
BotCommand("switch", "سوییچ پروژه / Switch project"),
|
||||||
@@ -5947,6 +6223,7 @@ def main():
|
|||||||
|
|
||||||
# General & Control Panel Handlers
|
# General & Control Panel Handlers
|
||||||
application.add_handler(CommandHandler(["start", "menu", "dashboard", "panel"], start_command))
|
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("help", help_command))
|
||||||
application.add_handler(CommandHandler(["usage", "quota", "credits"], usage_command))
|
application.add_handler(CommandHandler(["usage", "quota", "credits"], usage_command))
|
||||||
application.add_handler(CommandHandler(["new", "reset"], new_command))
|
application.add_handler(CommandHandler(["new", "reset"], new_command))
|
||||||
|
|||||||
@@ -1081,6 +1081,169 @@ async def execute_action(
|
|||||||
badge = f"\n⚠️ خطا در بازگردانی گیت: {escape_html(msg)}"
|
badge = f"\n⚠️ خطا در بازگردانی گیت: {escape_html(msg)}"
|
||||||
return badge, side_effects, created_task
|
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
|
# 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
|
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
|
# 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"
|
" [[GIT_INIT: project=\"<project_optional>\"]]\n\n"
|
||||||
"17. Restart Telegram Bot Service:\n"
|
"17. Restart Telegram Bot Service:\n"
|
||||||
" [[RESTART_BOT]]\n\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."
|
"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,
|
"expires_at": null,
|
||||||
"is_active": false,
|
"is_active": false,
|
||||||
"note": ""
|
"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": {}
|
"pending_requests": {}
|
||||||
|
|||||||
File diff suppressed because one or more lines are too long
Reference in New Issue
Block a user