AI Update: روی حالت های تمامی حافظه های موجود پروژه های کاربران رو همر
This commit is contained in:
+131
-36
@@ -1105,19 +1105,26 @@ 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."""
|
||||
def build_memory_menu(chat_id: int, view_type: str = "project", page: int = 0) -> tuple[str, InlineKeyboardMarkup]:
|
||||
"""Builds interactive 3-tier AI Memory manager dashboard with tabs (project, user, global), pagination, and deletion."""
|
||||
from memory_manager import memory_manager
|
||||
session = session_manager.get_or_create(chat_id)
|
||||
curr_proj = session_manager.get_current_project(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"
|
||||
proj_name = curr_proj.name if curr_proj else "default"
|
||||
|
||||
if view_type == "global":
|
||||
memories = memory_manager.get_global_memories(limit=100)
|
||||
else:
|
||||
# Validate view_type
|
||||
if view_type not in ("project", "user", "global"):
|
||||
view_type = "project" if curr_proj else "user"
|
||||
|
||||
if view_type == "project":
|
||||
memories = memory_manager.get_project_memories(user_id=chat_id, project_name=proj_name, limit=100)
|
||||
elif view_type == "user":
|
||||
memories = memory_manager.get_user_memories(user_id=chat_id, limit=100)
|
||||
else: # global
|
||||
memories = memory_manager.get_global_memories(limit=100)
|
||||
|
||||
total_cnt = len(memories)
|
||||
page_size = 5
|
||||
@@ -1125,19 +1132,29 @@ def build_memory_menu(chat_id: int, view_type: str = "private", page: int = 0) -
|
||||
page = max(0, min(page, max_pages - 1))
|
||||
paged_memories = memories[page * page_size : (page + 1) * page_size]
|
||||
|
||||
stats = memory_manager.get_stats()
|
||||
stats = memory_manager.get_stats(user_id=chat_id, project_name=proj_name)
|
||||
|
||||
if is_fa:
|
||||
tab_name = "🌐 خاطرات عمومی (کل سیستم)" if view_type == "global" else "👤 خاطرات خصوصی (اختصاصی شما)"
|
||||
if view_type == "project":
|
||||
tab_name = f"📁 خاطرات اختصاصی پروژه (<code>{escape_html(proj_name)}</code>)"
|
||||
tab_desc = "این خاطرات <b>فقط هنگام فعالیت در همین پروژه</b> به هوش مصنوعی تزریق میشوند."
|
||||
elif view_type == "user":
|
||||
tab_name = "👤 خاطرات شخصی من (سراسری)"
|
||||
tab_desc = "این خاطرات مربوط به شخص شماست و در <b>تمام پروژهها</b> اعمال میگردد."
|
||||
else:
|
||||
tab_name = "🌐 قوانین و خاطرات عمومی (کل سرور و کاربران)"
|
||||
tab_desc = "این قوانین برای <b>همه کاربران</b> تزریق میشوند (ویرایش و حذف فقط توسط مدیر)."
|
||||
|
||||
header = (
|
||||
f"🧠 <b>کنترلپنل حافظه هوشمند هوش مصنوعی (AI Long-Term Memory)</b>\n\n"
|
||||
f"🧠 <b>کنترلپنل حافظه هوشمند ۳ لایه (AI Memory Dashboard)</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"
|
||||
f"• ℹ️ {tab_desc}\n"
|
||||
f"• 📊 <b>آمار:</b> <code>{stats['current_project_memories']}</code> پروژه | <code>{stats['current_user_memories']}</code> کاربر | <code>{stats['global_memories']}</code> عمومی\n\n"
|
||||
)
|
||||
if not memories:
|
||||
body = (
|
||||
f"ℹ️ <i>در این بخش هنوز هیچ خاطرهای ثبت نشده است.</i>\n\n"
|
||||
f"💡 <b>یادگیری خودکار:</b> هوش مصنوعی به صورت خودکار در خلال گفتگوها، عادات، نام و نکات مهم شما را استخراج و ذخیره میکند."
|
||||
f"💡 <b>یادگیری خودکار:</b> هوش مصنوعی در حین گفتگوها نکات مهم مربوط به این بخش را خودکار استخراج و ثبت میکند."
|
||||
)
|
||||
else:
|
||||
body_lines = [f"<b>لیست خاطرات (صفحه {page + 1} از {max_pages}):</b>\n"]
|
||||
@@ -1149,16 +1166,26 @@ def build_memory_menu(chat_id: int, view_type: str = "private", page: int = 0) -
|
||||
)
|
||||
body = "\n\n".join(body_lines)
|
||||
else:
|
||||
tab_name = "🌐 Global System Memory" if view_type == "global" else "👤 Private User Memory"
|
||||
if view_type == "project":
|
||||
tab_name = f"📁 Project Memory (<code>{escape_html(proj_name)}</code>)"
|
||||
tab_desc = "Injected only when working in this project."
|
||||
elif view_type == "user":
|
||||
tab_name = "👤 User Profile Memory"
|
||||
tab_desc = "Applies to you across all your projects."
|
||||
else:
|
||||
tab_name = "🌐 Global System Memory"
|
||||
tab_desc = "Applies to all users (admin-managed)."
|
||||
|
||||
header = (
|
||||
f"🧠 <b>AI Long-Term Memory Dashboard</b>\n\n"
|
||||
f"🧠 <b>3-Tier AI 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"
|
||||
f"• ℹ️ {tab_desc}\n"
|
||||
f"• 📊 <b>Stats:</b> <code>{stats['current_project_memories']}</code> project | <code>{stats['current_user_memories']}</code> user | <code>{stats['global_memories']}</code> global\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>"
|
||||
body = "ℹ️ <i>No memories recorded in this section yet.</i>"
|
||||
else:
|
||||
body_lines = [f"<b>Memories list (Page {page + 1} of {max_pages}):</b>\n"]
|
||||
body_lines = [f"<b>Memories (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(
|
||||
@@ -1172,20 +1199,23 @@ def build_memory_menu(chat_id: int, view_type: str = "private", page: int = 0) -
|
||||
# Build keyboard
|
||||
keyboard = []
|
||||
|
||||
# 1. Tab buttons
|
||||
tab_priv_text = "👤 خاطرات من (خصوصی) ✓" if view_type == "private" else "👤 خاطرات من (خصوصی)"
|
||||
tab_glob_text = "🌐 خاطرات عمومی سیستم ✓" if view_type == "global" else "🌐 خاطرات عمومی سیستم"
|
||||
# 1. 3 Tab buttons
|
||||
t_proj = f"📁 پروژه ({proj_name[:10]}) ✓" if view_type == "project" else f"📁 پروژه ({proj_name[:10]})"
|
||||
t_user = "👤 کاربر (من) ✓" if view_type == "user" else "👤 کاربر (من)"
|
||||
t_glob = "🌐 عمومی ✓" 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"
|
||||
t_proj = f"📁 Project ✓" if view_type == "project" else f"📁 Project"
|
||||
t_user = "👤 User ✓" if view_type == "user" else "👤 User"
|
||||
t_glob = "🌐 Global ✓" if view_type == "global" else "🌐 Global"
|
||||
|
||||
keyboard.append([
|
||||
InlineKeyboardButton(tab_priv_text, callback_data="mem_tab:private:0"),
|
||||
InlineKeyboardButton(tab_glob_text, callback_data="mem_tab:global:0"),
|
||||
InlineKeyboardButton(t_proj, callback_data="mem_tab:project:0"),
|
||||
InlineKeyboardButton(t_user, callback_data="mem_tab:user:0"),
|
||||
InlineKeyboardButton(t_glob, 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)
|
||||
# 2. Item delete buttons
|
||||
can_delete_current = (view_type in ("project", "user")) 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):
|
||||
@@ -1206,7 +1236,7 @@ def build_memory_menu(chat_id: int, view_type: str = "private", page: int = 0) -
|
||||
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)
|
||||
# 4. Clear memory button
|
||||
action_row = []
|
||||
if can_delete_current and total_cnt > 0:
|
||||
clear_label = "🧹 پاکسازی این بخش" if is_fa else "🧹 Clear this section"
|
||||
@@ -3385,39 +3415,96 @@ async def usage_command(update: Update, context: ContextTypes.DEFAULT_TYPE):
|
||||
async def memory_command(update: Update, context: ContextTypes.DEFAULT_TYPE):
|
||||
chat_id = update.effective_chat.id
|
||||
session = session_manager.get_or_create(chat_id)
|
||||
curr_proj = session_manager.get_current_project(chat_id)
|
||||
is_fa = (session.language or "").lower() in ("fa", "farsi", "persian", "🇮🇷 persian / farsi (فارسی)")
|
||||
is_admin_user = settings.is_admin(chat_id)
|
||||
from memory_manager import memory_manager
|
||||
|
||||
if not context.args:
|
||||
text, markup = build_memory_menu(chat_id, view_type="private", page=0)
|
||||
text, markup = build_memory_menu(chat_id, view_type="project" if curr_proj else "user", 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 ("project", "proj", "p"):
|
||||
text, markup = build_memory_menu(chat_id, view_type="project", page=0)
|
||||
await update.message.reply_html(text, reply_markup=markup)
|
||||
return
|
||||
|
||||
if subcmd in ("user", "u", "me", "profile", "private"):
|
||||
text, markup = build_memory_menu(chat_id, view_type="user", page=0)
|
||||
await update.message.reply_html(text, reply_markup=markup)
|
||||
return
|
||||
|
||||
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)
|
||||
# Add memory manually: /memory add <global|user|project> <key> | <content>
|
||||
if subcmd in ("add", "set", "save") and len(context.args) > 2:
|
||||
target_type = context.args[1].lower().strip()
|
||||
if target_type not in ("global", "user", "project"):
|
||||
target_type = "user"
|
||||
rest = " ".join(context.args[1:]).strip()
|
||||
else:
|
||||
rest = " ".join(context.args[2:]).strip()
|
||||
|
||||
if target_type == "global" and not is_admin_user:
|
||||
await update.message.reply_html("🚫 <b>خطای دسترسی: فقط مدیر سیستم میتواند خاطره عمومی ثبت کند.</b>" if is_fa else "🚫 <b>Access Denied.</b>")
|
||||
return
|
||||
|
||||
if "|" in rest:
|
||||
key_part, content_part = rest.split("|", 1)
|
||||
else:
|
||||
parts = rest.split(None, 1)
|
||||
key_part = parts[0]
|
||||
content_part = parts[1] if len(parts) > 1 else ""
|
||||
|
||||
key_clean = key_part.strip().lower()
|
||||
content_clean = content_part.strip()
|
||||
if not key_clean or not content_clean:
|
||||
await update.message.reply_html(
|
||||
"💡 <i>راهنمای افزودن دستی خاطره:</i>\n<code>/memory add [global|user|project] <key> | <محتوا></code>\n\n<b>مثال:</b>\n<code>/memory add global default_php | همیشه از PHP مدرن استفاده شود</code>"
|
||||
if is_fa
|
||||
else "💡 <i>Usage:</i> <code>/memory add [global|user|project] <key> | <content></code>"
|
||||
)
|
||||
return
|
||||
|
||||
p_name = curr_proj.name if (curr_proj and target_type == "project") else "default"
|
||||
item, is_created = memory_manager.save_or_update(
|
||||
type_=target_type,
|
||||
key=key_clean,
|
||||
content=content_clean,
|
||||
user_id=chat_id,
|
||||
project_name=p_name if target_type == "project" else None,
|
||||
category="rule" if target_type == "global" else "preference",
|
||||
importance=5 if target_type == "global" else 3,
|
||||
created_by=chat_id,
|
||||
)
|
||||
msg = f"✅ <b>خاطره با موفقیت ثبت شد:</b>\n• 🏷️ بخش: {item.type}\n• 🔑 کلید: <code>{escape_html(item.key)}</code>\n• 📝 محتوا: {escape_html(item.content)}" if is_fa else f"✅ <b>Memory saved:</b> [{item.type}] {item.key}"
|
||||
text, markup = build_memory_menu(chat_id, view_type=target_type, page=0)
|
||||
await update.message.reply_html(f"{msg}\n\n{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"
|
||||
target_type = context.args[1].lower() if len(context.args) > 1 else "project"
|
||||
if target_type not in ("global", "user", "project"):
|
||||
target_type = "project" if curr_proj else "user"
|
||||
p_name = curr_proj.name if curr_proj else "default"
|
||||
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 "خصوصی"
|
||||
cnt = memory_manager.clear_memories(
|
||||
type_=target_type, user_id=chat_id, project_name=p_name, is_admin=is_admin_user
|
||||
)
|
||||
type_label = f"پروژه {p_name}" if target_type == "project" else ("عمومی" 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)
|
||||
text, markup = build_memory_menu(chat_id, view_type="project" if curr_proj else "user", page=0)
|
||||
await update.message.reply_html(text, reply_markup=markup)
|
||||
|
||||
|
||||
@@ -4078,6 +4165,7 @@ async def callback_handler(update: Update, context: ContextTypes.DEFAULT_TYPE):
|
||||
session = session_manager.get_or_create(chat_id)
|
||||
curr_proj = session_manager.get_current_project(chat_id)
|
||||
is_fa = (session.language or "").lower() in ("fa", "farsi", "persian", "🇮🇷 persian / farsi (فارسی)")
|
||||
is_admin_user = settings.is_admin(chat_id) or settings.is_admin(user_id)
|
||||
data = query.data
|
||||
|
||||
if data == "btn_dashboard":
|
||||
@@ -5190,8 +5278,15 @@ async def callback_handler(update: Update, context: ContextTypes.DEFAULT_TYPE):
|
||||
elif data.startswith("mem_clear_do:"):
|
||||
v_type = data.split(":")[1]
|
||||
from memory_manager import memory_manager
|
||||
curr_p = session_manager.get_current_project(chat_id)
|
||||
p_name = curr_p.name if curr_p else "default"
|
||||
try:
|
||||
cnt = memory_manager.clear_memories(type_=v_type, user_id=chat_id, is_admin=is_admin_user)
|
||||
cnt = memory_manager.clear_memories(
|
||||
type_=v_type,
|
||||
user_id=chat_id,
|
||||
project_name=p_name if v_type == "project" else None,
|
||||
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)
|
||||
|
||||
Reference in New Issue
Block a user