From 3e9fb5c9fcb61853d300daac0ff8e648153df154 Mon Sep 17 00:00:00 2001 From: Antigravity Bot Date: Sun, 30 Aug 2026 09:28:18 +0330 Subject: [PATCH] =?UTF-8?q?AI=20Update:=20=D9=BE=D8=B3=20=D9=81=D8=A7?= =?UTF-8?q?=D8=B2=20=D8=A7=D9=88=D9=84=20=D8=B1=D9=88=20=D9=BE=DB=8C=D8=A7?= =?UTF-8?q?=D8=AF=D9=87=20=DA=A9=D9=86?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- telegram-agy-bot/data/memory.db | Bin 0 -> 28672 bytes telegram-agy-bot/memory_manager.py | 408 +++++++++++++++++++++++++++++ telegram-agy-bot/sessions.json | 16 +- 3 files changed, 416 insertions(+), 8 deletions(-) create mode 100644 telegram-agy-bot/data/memory.db create mode 100644 telegram-agy-bot/memory_manager.py diff --git a/telegram-agy-bot/data/memory.db b/telegram-agy-bot/data/memory.db new file mode 100644 index 0000000000000000000000000000000000000000..9225492c08e77184582513d3c88f9d96189890bc GIT binary patch literal 28672 zcmeI)&u`mg7zgmzj#F#>F^|I(qEYD`2qjjdNvJ{yp$W3i&}doOWyx4iQQEvK7D=4C z4y;3)h{V=T>V+EzZXk{AQp%4T;_tA#+cpX92oe&43y+h${TZ)tLLJ{%aqPtJ`#g_7 zb|TsNarsi-_5{D?xQ(jEC)o+6s_Y%k8DlCKX$X_F$&;v9GKmY;|fB*y_009X6CjuW2>4`VSl}^fT*2HzYcD>RN4ac>` za%G|FiABd2Xy2=N3<->eHn<;P^BQ1lPx8i!@O-ej@FmZcXxD{`u zCFH1~=*-)F4^JIN%<%32yJmJ?)%3(!D&Xe90$Q&95p8_sL$ST_@qP*ALhe#|puw&| z|FV`0r$i=yf7&WqJgkzR<*9zSR3{nJ6K_$SiwEmmtUL47`tCBdL(AM5^G~ZBP+Tua zYE~UeOiUuE>&3;OKs6y*#9urFRYY3m$&%7zUgMQAu=@5{H(6%iScpe z?nF1HJOJce-4jJV%hLl7yYNV~Yjn7ltoN)UpDpGtW{Y$Df;Gpp<~-5;a2OZXGCzCo@jb|14MVX8!gB6sIyzI1X+hLJkcZCty(ww{t*NBu^FD5tH=LjMxE}^AOHafKmY;|fB*y_009U< z00PgQKuaBAr?gj2w-u)A{cBCyx5<}9&GsC((sISMa1w5KEobY#f6w3azwtLYEquqX zT%K}jB3%C7e-LzNz7eeQ;P%7yN1v{5-4E{g8)stKt*?Lma?)|+yz_!G%96}H*|EZ$ zy$dI;4_e(^y*zHaE`rrCj{gG%3={hI9 Dict[str, Any]: + return asdict(self) + + @property + def is_global(self) -> bool: + return self.type == "global" + + @property + def is_private(self) -> bool: + return self.type == "private" + + +class MemoryManager: + def __init__(self, db_path: Path = DB_PATH): + self.db_path = db_path + self._init_db() + + def _get_connection(self) -> sqlite3.Connection: + self.db_path.parent.mkdir(parents=True, exist_ok=True) + conn = sqlite3.connect(str(self.db_path), timeout=15.0) + conn.row_factory = sqlite3.Row + conn.execute("PRAGMA journal_mode=WAL;") + conn.execute("PRAGMA synchronous=NORMAL;") + return conn + + def _init_db(self): + """Initializes tables and indexes if they do not exist.""" + try: + with self._get_connection() as conn: + conn.execute(""" + CREATE TABLE IF NOT EXISTS memories ( + id INTEGER PRIMARY KEY AUTOINCREMENT, + type TEXT NOT NULL CHECK(type IN ('global', 'private')), + user_id INTEGER, + key TEXT NOT NULL, + category TEXT NOT NULL DEFAULT 'general', + content TEXT NOT NULL, + importance INTEGER NOT NULL DEFAULT 1, + created_by INTEGER, + created_at REAL NOT NULL, + updated_at REAL NOT NULL + ); + """) + # Partial unique indexes to properly handle NULL user_id for global memories + conn.execute(""" + CREATE UNIQUE INDEX IF NOT EXISTS idx_memories_global_key + ON memories(type, key) WHERE type = 'global'; + """) + conn.execute(""" + CREATE UNIQUE INDEX IF NOT EXISTS idx_memories_private_key + ON memories(type, user_id, key) WHERE type = 'private'; + """) + conn.execute(""" + CREATE INDEX IF NOT EXISTS idx_memories_user_type + ON memories(type, user_id); + """) + conn.execute(""" + CREATE INDEX IF NOT EXISTS idx_memories_category + ON memories(category); + """) + logger.info("Memory database initialized successfully at %s", self.db_path) + except Exception as e: + logger.error("Failed to initialize memory database: %s", e) + raise + + def save_or_update( + self, + type_: str, + key: str, + content: str, + user_id: Optional[int] = None, + category: str = "general", + importance: int = 1, + created_by: Optional[int] = None, + ) -> Tuple[MemoryItem, bool]: + """ + Saves or updates a memory. + Returns: (MemoryItem, is_created: bool) + """ + type_ = type_.lower().strip() + if type_ not in ("global", "private"): + raise ValueError("Memory type must be 'global' or 'private'") + + if type_ == "global": + user_id = None + elif user_id is None: + raise ValueError("Private memory requires a valid user_id") + + key = key.strip().lower() + if not key: + raise ValueError("Memory key cannot be empty") + + content = content.strip() + if not content: + raise ValueError("Memory content cannot be empty") + + category = category.strip().lower() or "general" + importance = max(1, min(5, int(importance))) + now = time.time() + + with self._get_connection() as conn: + # Check if exists + if type_ == "global": + cur = conn.execute( + "SELECT id, created_at, created_by FROM memories WHERE type = 'global' AND key = ?", + (key,), + ) + else: + cur = conn.execute( + "SELECT id, created_at, created_by FROM memories WHERE type = 'private' AND user_id = ? AND key = ?", + (user_id, key), + ) + row = cur.fetchone() + + if row: + mem_id = row["id"] + orig_created_at = row["created_at"] + orig_created_by = row["created_by"] or created_by + conn.execute( + """ + UPDATE memories + SET category = ?, content = ?, importance = ?, updated_at = ? + WHERE id = ? + """, + (category, content, importance, now, mem_id), + ) + is_created = False + created_at = orig_created_at + creator = orig_created_by + else: + cur = conn.execute( + """ + INSERT INTO memories (type, user_id, key, category, content, importance, created_by, created_at, updated_at) + VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?) + """, + (type_, user_id, key, category, content, importance, created_by, now, now), + ) + mem_id = cur.lastrowid + is_created = True + created_at = now + creator = created_by + + item = MemoryItem( + id=mem_id, + type=type_, + user_id=user_id, + key=key, + category=category, + content=content, + importance=importance, + created_by=creator, + created_at=created_at, + updated_at=now, + ) + logger.info( + "%s memory [id=%d, key=%s, type=%s, user=%s]", + "Created" if is_created else "Updated", + mem_id, + key, + type_, + user_id, + ) + return item, is_created + + def get_by_id(self, memory_id: int) -> Optional[MemoryItem]: + with self._get_connection() as conn: + cur = conn.execute("SELECT * FROM memories WHERE id = ?", (memory_id,)) + row = cur.fetchone() + if row: + return MemoryItem(**dict(row)) + return None + + def get_by_key(self, type_: str, key: str, user_id: Optional[int] = None) -> Optional[MemoryItem]: + type_ = type_.lower().strip() + key = key.lower().strip() + with self._get_connection() as conn: + if type_ == "global": + cur = conn.execute("SELECT * FROM memories WHERE type = 'global' AND key = ?", (key,)) + else: + cur = conn.execute( + "SELECT * FROM memories WHERE type = 'private' AND user_id = ? AND key = ?", + (user_id, key), + ) + row = cur.fetchone() + if row: + return MemoryItem(**dict(row)) + return None + + def get_global_memories(self, category: Optional[str] = None, limit: int = 100) -> List[MemoryItem]: + with self._get_connection() as conn: + if category: + cur = conn.execute( + "SELECT * FROM memories WHERE type = 'global' AND category = ? ORDER BY importance DESC, updated_at DESC LIMIT ?", + (category.lower().strip(), limit), + ) + else: + cur = conn.execute( + "SELECT * FROM memories WHERE type = 'global' ORDER BY importance DESC, updated_at DESC LIMIT ?", + (limit,), + ) + return [MemoryItem(**dict(r)) for r in cur.fetchall()] + + def get_user_memories( + self, user_id: int, category: Optional[str] = None, limit: int = 100 + ) -> List[MemoryItem]: + with self._get_connection() as conn: + if category: + cur = conn.execute( + "SELECT * FROM memories WHERE type = 'private' AND user_id = ? AND category = ? ORDER BY importance DESC, updated_at DESC LIMIT ?", + (user_id, category.lower().strip(), limit), + ) + else: + cur = conn.execute( + "SELECT * FROM memories WHERE type = 'private' AND user_id = ? ORDER BY importance DESC, updated_at DESC LIMIT ?", + (user_id, limit), + ) + return [MemoryItem(**dict(r)) for r in cur.fetchall()] + + def delete_by_id(self, memory_id: int, user_id: Optional[int] = None, is_admin: bool = False) -> bool: + with self._get_connection() as conn: + cur = conn.execute("SELECT * FROM memories WHERE id = ?", (memory_id,)) + row = cur.fetchone() + if not row: + return False + mem = MemoryItem(**dict(row)) + if mem.type == "global" and not is_admin: + raise PermissionError("Only administrators can delete global memories") + if mem.type == "private" and mem.user_id != user_id and not is_admin: + raise PermissionError("Cannot delete another user's private memory") + + conn.execute("DELETE FROM memories WHERE id = ?", (memory_id,)) + logger.info("Deleted memory [id=%d, key=%s, type=%s]", memory_id, mem.key, mem.type) + return True + + def delete_by_key( + self, type_: str, key: str, user_id: Optional[int] = None, is_admin: bool = False + ) -> bool: + type_ = type_.lower().strip() + key = key.lower().strip() + with self._get_connection() as conn: + if type_ == "global": + if not is_admin: + raise PermissionError("Only administrators can delete global memories") + cur = conn.execute("DELETE FROM memories WHERE type = 'global' AND key = ?", (key,)) + else: + if user_id is None: + return False + cur = conn.execute( + "DELETE FROM memories WHERE type = 'private' AND user_id = ? AND key = ?", + (user_id, key), + ) + deleted = cur.rowcount > 0 + if deleted: + logger.info("Deleted memory by key [key=%s, type=%s, user=%s]", key, type_, user_id) + return deleted + + def clear_memories(self, type_: str, user_id: Optional[int] = None, is_admin: bool = False) -> int: + type_ = type_.lower().strip() + with self._get_connection() as conn: + if type_ == "global": + if not is_admin: + raise PermissionError("Only administrators can clear global memories") + cur = conn.execute("DELETE FROM memories WHERE type = 'global'") + else: + if user_id is None: + return 0 + cur = conn.execute("DELETE FROM memories WHERE type = 'private' AND user_id = ?", (user_id,)) + count = cur.rowcount + logger.info("Cleared %d %s memories for user %s", count, type_, user_id) + return count + + def search_memories( + self, query: str, user_id: Optional[int] = None, type_: Optional[str] = None, limit: int = 50 + ) -> List[MemoryItem]: + q = f"%{query.strip().lower()}%" + with self._get_connection() as conn: + if type_ == "global": + cur = conn.execute( + """ + SELECT * FROM memories + WHERE type = 'global' AND (key LIKE ? OR content LIKE ? OR category LIKE ?) + ORDER BY importance DESC, updated_at DESC LIMIT ? + """, + (q, q, q, limit), + ) + elif type_ == "private" and user_id is not None: + cur = conn.execute( + """ + SELECT * FROM memories + WHERE type = 'private' AND user_id = ? AND (key LIKE ? OR content LIKE ? OR category LIKE ?) + ORDER BY importance DESC, updated_at DESC LIMIT ? + """, + (user_id, q, q, q, limit), + ) + elif user_id is not None: + cur = conn.execute( + """ + SELECT * FROM memories + WHERE (type = 'global' OR (type = 'private' AND user_id = ?)) + AND (key LIKE ? OR content LIKE ? OR category LIKE ?) + ORDER BY type DESC, importance DESC, updated_at DESC LIMIT ? + """, + (user_id, q, q, q, limit), + ) + else: + cur = conn.execute( + """ + SELECT * FROM memories + WHERE type = 'global' AND (key LIKE ? OR content LIKE ? OR category LIKE ?) + ORDER BY importance DESC, updated_at DESC LIMIT ? + """, + (q, q, q, limit), + ) + return [MemoryItem(**dict(r)) for r in cur.fetchall()] + + def format_memories_for_prompt(self, user_id: Optional[int] = None) -> Optional[str]: + """ + Formats all applicable memories (Global + User's Private) into a concise, token-efficient + system instruction block for the AI model. + Returns None if no memories are found. + """ + globals_list = self.get_global_memories(limit=50) + privates_list = self.get_user_memories(user_id=user_id, limit=50) if user_id else [] + + if not globals_list and not privates_list: + return None + + lines = [ + "[SYSTEM INSTRUCTION: AI PERSISTENT MEMORY & CONTINUOUS LEARNING]", + "You have access to persistent long-term memory containing verified system rules and user context.", + "Use this knowledge to maintain continuity and customize all your responses accordingly.\n" + ] + + if globals_list: + lines.append("🌐 GLOBAL SYSTEM MEMORY (قوانین و اطلاعات عمومی سیستم):") + for m in globals_list: + cat = f"[{m.category}]" if m.category and m.category != "general" else "" + lines.append(f"• [key: {m.key}] {cat} {m.content}") + lines.append("") + + if privates_list: + lines.append(f"👤 USER PRIVATE MEMORY (خاطرات و ترجیحات اختصاصی این کاربر):") + for m in privates_list: + cat = f"[{m.category}]" if m.category and m.category != "general" else "" + lines.append(f"• [key: {m.key}] {cat} {m.content}") + lines.append("") + + lines.extend([ + "🧠 AUTONOMOUS MEMORY MANAGEMENT RULES:", + "1. When the user shares important facts, personal preferences, coding conventions, or rules that should persist, output the action tag:", + ' [[SAVE_MEMORY: type="private|global", key="", category="preference|rule|tech_stack|fact", content=""]]', + "2. Note: Non-admin users can ONLY save 'private' memories. Only system administrators can set 'global' memories.", + "3. If a past memory is superseded or changed, update it with the same key or use [[UPDATE_MEMORY: key=\"\", content=\"\"]].", + "4. If the user explicitly asks to forget something, use [[DELETE_MEMORY: key=\"\"]].", + "5. Do NOT store temporary or trivial small-talk. Only store enduring and valuable knowledge." + ]) + + return "\n".join(lines) + + def get_stats(self) -> Dict[str, Any]: + with self._get_connection() as conn: + cur = conn.execute("SELECT COUNT(*) as cnt FROM memories WHERE type = 'global'") + global_count = cur.fetchone()["cnt"] + + cur = conn.execute("SELECT COUNT(*) as cnt FROM memories WHERE type = 'private'") + private_count = cur.fetchone()["cnt"] + + cur = conn.execute("SELECT COUNT(DISTINCT user_id) as cnt FROM memories WHERE type = 'private'") + user_count = cur.fetchone()["cnt"] + + return { + "total_memories": global_count + private_count, + "global_memories": global_count, + "private_memories": private_count, + "users_with_memory": user_count, + } + + +memory_manager = MemoryManager() diff --git a/telegram-agy-bot/sessions.json b/telegram-agy-bot/sessions.json index 94d1acb..7d5fa84 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": 17956, - "last_total_tokens": 217340, - "last_response": "\u0639\u0644\u062a \u0646\u0645\u0627\u06cc\u0634 \u0639\u0628\u0627\u0631\u062a **`[\u0627\u06a9\u0634\u0646 \u0646\u0627\u0634\u0646\u0627\u062e\u062a\u0647: SAVE_MEMORY]`** \u0627\u06cc\u0646 \u0627\u0633\u062a:\n\n### \ud83d\udd0d \u0686\u0631\u0627 \u0627\u06cc\u0646 \u0627\u062a\u0641\u0627\u0642 \u0627\u0641\u062a\u0627\u062f\u061f\n\u0631\u0628\u0627\u062a \u062a\u0644\u06af\u0631\u0627\u0645 \u06cc\u06a9 \u0633\u06cc\u0633\u062a\u0645 \u0645\u0641\u0633\u0631 \u062f\u0627\u062e\u0644\u06cc (Parser) \u062f\u0627\u0631\u062f \u06a9\u0647 \u0645\u062a\u0646 \u062e\u0631\u0648\u062c\u06cc \u0647\u0648\u0634 \u0645\u0635\u0646\u0648\u0639\u06cc \u0631\u0627 \u0627\u0633\u06a9\u0646 \u0645\u06cc\u200c\u06a9\u0646\u062f. \u0647\u0631 \u0632\u0645\u0627\u0646 \u062f\u0631 \u0645\u062a\u0646 \u0627\u0644\u06af\u0648\u06cc\u06cc \u0634\u0628\u06cc\u0647 `[[\u0646\u0627\u0645_\u062f\u0633\u062a\u0648\u0631: \u067e\u0627\u0631\u0627\u0645\u062a\u0631\u0647\u0627]]` \u067e\u06cc\u062f\u0627 \u06a9\u0646\u062f\u060c \u062a\u0644\u0627\u0634 \u0645\u06cc\u200c\u06a9\u0646\u062f \u0622\u0646 \u0631\u0627 \u0628\u0647 \u0639\u0646\u0648\u0627\u0646 \u06cc\u06a9 **\u0641\u0631\u0645\u0627\u0646 \u0627\u062c\u0631\u0627\u06cc\u06cc \u062f\u0631 \u0633\u0631\u0648\u0631 \u06cc\u0627 \u0631\u0628\u0627\u062a** (\u0645\u0627\u0646\u0646\u062f \u062a\u063a\u06cc\u06cc\u0631 \u0645\u062f\u0644\u060c \u062a\u0646\u0638\u06cc\u0645 \u0633\u0627\u0628\u062f\u0627\u0645\u06cc\u0646\u060c \u0633\u0627\u062e\u062a \u067e\u0631\u0648\u0698\u0647 \u0648 ...) \u0627\u062c\u0631\u0627 \u06a9\u0646\u062f.\n\n\u0627\u0632 \u0622\u0646\u062c\u0627 \u06a9\u0647 \u062f\u0631 \u067e\u06cc\u0627\u0645 \u0642\u0628\u0644\u06cc \u0645\u0646 \u0633\u0627\u062e\u062a\u0627\u0631 \u062a\u06af\u200c\u0647\u0627\u06cc \u067e\u06cc\u0634\u0646\u0647\u0627\u062f\u06cc \u0631\u0627 \u0628\u0631\u0627\u06cc \u0645\u0639\u0631\u0641\u06cc \u067e\u0631\u0648\u062a\u06a9\u0644 \u0630\u06a9\u0631 \u06a9\u0631\u062f\u0645\u060c \u0631\u0628\u0627\u062a \u062a\u0635\u0648\u0631 \u06a9\u0631\u062f \u0627\u06cc\u0646\u200c\u0647\u0627 \u06cc\u06a9 \u0641\u0631\u0645\u0627\u0646 \u0639\u0645\u0644\u06cc\u0627\u062a\u06cc \u0647\u0633\u062a\u0646\u062f\u061b \u0648 \u0686\u0648\u0646 **\u0647\u0646\u0648\u0632 \u0645\u0627\u0698\u0648\u0644 \u062d\u0627\u0641\u0638\u0647 \u0631\u0627 \u062f\u0631 \u06a9\u062f \u0631\u0628\u0627\u062a \u067e\u06cc\u0627\u062f\u0647\u200c\u0633\u0627\u0632\u06cc \u0648 \u0631\u062c\u06cc\u0633\u062a\u0631 \u0646\u06a9\u0631\u062f\u0647\u200c\u0627\u06cc\u0645**\u060c \u0631\u0628\u0627\u062a \u0627\u06cc\u0646 \u062a\u06af \u0631\u0627 \u0628\u0647 \u0639\u0646\u0648\u0627\u0646 \u06cc\u06a9 \u062f\u0633\u062a\u0648\u0631 \u062a\u0639\u0631\u06cc\u0641\u200c\u0646\u0634\u062f\u0647 \u0634\u0646\u0627\u0633\u0627\u06cc\u06cc \u06a9\u0631\u062f\u0647 \u0648 \u0628\u0647 \u0635\u0648\u0631\u062a \u062e\u0648\u062f\u06a9\u0627\u0631 \u067e\u06cc\u0627\u0645 `[\u0627\u06a9\u0634\u0646 \u0646\u0627\u0634\u0646\u0627\u062e\u062a\u0647: SAVE_MEMORY]` \u0631\u0627 \u062c\u0627\u06cc\u06af\u0632\u06cc\u0646 \u0622\u0646 \u06a9\u0631\u062f.\n\n---\n\n### \ud83d\udee0\ufe0f \u067e\u0633 \u0627\u0632 \u067e\u06cc\u0627\u062f\u0647\u200c\u0633\u0627\u0632\u06cc \u0633\u06cc\u0633\u062a\u0645 \u0686\u0647 \u062a\u063a\u06cc\u06cc\u0631\u06cc \u0631\u062e \u0645\u06cc\u200c\u062f\u0647\u062f\u061f\n1. **\u062b\u0628\u062a \u0631\u0633\u0645\u06cc \u0627\u06a9\u0634\u0646\u200c\u0647\u0627:** \u0627\u06cc\u0646 \u06f4 \u062a\u06af \u0628\u0647 \u0644\u06cc\u0633\u062a \u0627\u06a9\u0634\u0646\u200c\u0647\u0627\u06cc \u0631\u0633\u0645\u06cc \u0631\u0628\u0627\u062a \u0627\u0636\u0627\u0641\u0647 \u0645\u06cc\u200c\u0634\u0648\u0646\u062f.\n2. **\u0627\u062c\u0631\u0627\u06cc \u062f\u0631 \u067e\u0633\u200c\u0632\u0645\u06cc\u0646\u0647 (Silent Execution):** \u0648\u0642\u062a\u06cc \u0647\u0648\u0634 \u0645\u0635\u0646\u0648\u0639\u06cc \u0627\u06cc\u0646 \u062a\u06af\u200c\u0647\u0627 \u0631\u0627 \u062f\u0631 \u067e\u0627\u0633\u062e\u0634 \u0635\u0627\u062f\u0631 \u06a9\u0646\u062f\u060c \u0631\u0628\u0627\u062a \u062f\u0631 \u0647\u0645\u0627\u0646 \u0644\u062d\u0638\u0647 \u0627\u0637\u0644\u0627\u0639\u0627\u062a \u0631\u0627 \u062f\u0631 \u062f\u06cc\u062a\u0627\u0628\u06cc\u0633 \u062d\u0627\u0641\u0638\u0647 (`memory.db`) \u0630\u062e\u06cc\u0631\u0647/\u0648\u06cc\u0631\u0627\u06cc\u0634 \u0645\u06cc\u200c\u06a9\u0646\u062f.\n3. **\u0639\u062f\u0645 \u0646\u0645\u0627\u06cc\u0634 \u0628\u0647 \u06a9\u0627\u0631\u0628\u0631:** \u0627\u06cc\u0646 \u062a\u06af\u200c\u0647\u0627 \u0628\u0647 \u0635\u0648\u0631\u062a \u062e\u0648\u062f\u06a9\u0627\u0631 \u0627\u0632 \u062e\u0631\u0648\u062c\u06cc \u0646\u0647\u0627\u06cc\u06cc \u062d\u0630\u0641 \u0645\u06cc\u200c\u0634\u0648\u0646\u062f \u062a\u0627 \u0645\u062a\u0646 \u06a9\u0627\u0631\u0628\u0631 \u06a9\u0627\u0645\u0644\u0627\u064b \u062a\u0645\u06cc\u0632\u060c \u0627\u0646\u0633\u0627\u0646\u06cc \u0648 \u0628\u062f\u0648\u0646 \u06a9\u062f\u0647\u0627\u06cc \u0633\u06cc\u0633\u062a\u0645\u06cc \u0646\u0645\u0627\u06cc\u0634 \u062f\u0627\u062f\u0647 \u0634\u0648\u062f.\n\n---\n\n\u0622\u0645\u0627\u062f\u0647\u200c\u0627\u0645 \u06a9\u0647 \u067e\u06cc\u0627\u062f\u0647\u200c\u0633\u0627\u0632\u06cc **\u0641\u0627\u0632 \u06f1 (\u0645\u0627\u0698\u0648\u0644 \u062f\u06cc\u062a\u0627\u0628\u06cc\u0633 \u062d\u0627\u0641\u0638\u0647 `memory_manager.py`)** \u0648 \u0633\u067e\u0633 \u0631\u062c\u06cc\u0633\u062a\u0631 \u06a9\u0631\u062f\u0646 \u0627\u06cc\u0646 \u0627\u06a9\u0634\u0646\u200c\u0647\u0627 \u0631\u0627 \u0634\u0631\u0648\u0639 \u06a9\u0646\u0645. \u0622\u06cc\u0627 \u0645\u0648\u0627\u0641\u0642\u06cc\u062f\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": 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", "created_at": 1787995349.975879, "description": "" }, @@ -71,19 +71,19 @@ } }, "turn_in_progress": false, - "last_prompt": "\u062a\u063a\u06cc\u06cc\u0631\u0627\u062a\n\u0627\u06cc\u0646 \u067e\u0631\u0648\u062a\u0648\u06a9\u0648\u0644 \u0627\u06a9\u0634\u0646 \u062a\u06af\u0647\u0627\u06cc\u062a\n1. \u0630\u062e\u06cc\u0631\u0647 \u062e\u0627\u0637\u0631\u0647 \u062c\u062f\u06cc\u062f:\n\n[\u0627\u06a9\u0634\u0646 \u0646\u0627\u0634\u0646\u0627\u062e\u062a\u0647: SAVE_MEMORY]\n\n2. \u0648\u06cc\u0631\u0627\u06cc\u0634 \u06cc\u0627 \u0628\u0647\u200c\u0631\u0648\u0632\u0631\u0633\u0627\u0646\u06cc \u062e\u0627\u0637\u0631\u0647 \u0645\u0648\u062c\u0648\u062f:\n\n[\u0627\u06a9\u0634\u0646 \u0646\u0627\u0634\u0646\u0627\u062e\u062a\u0647: UPDATE_MEMORY]\n\n3. \u062d\u0630\u0641 \u06cc\u06a9 \u062e\u0627\u0637\u0631\u0647 \u062e\u0627\u0635:\n\n[\u0627\u06a9\u0634\u0646 \u0646\u0627\u0634\u0646\u0627\u062e\u062a\u0647: DELETE_MEMORY]\n\n4. \u067e\u0627\u06a9\u200c\u0633\u0627\u0632\u06cc \u06a9\u0627\u0645\u0644 \u062d\u0627\u0641\u0638\u0647:\n\n[\u0627\u06a9\u0634\u0646 \u0646\u0627\u0634\u0646\u0627\u062e\u062a\u0647: CLEAR_MEMORY]\n\n\n\u0627\u06a9\u0634\u0646 \u0646\u0627\u0634\u0646\u0627\u062e\u062a\u0647 \u0686\u06cc\u0633\u062a\u061f", - "last_response": "\u0639\u0644\u062a \u0646\u0645\u0627\u06cc\u0634 \u0639\u0628\u0627\u0631\u062a **`[\u0627\u06a9\u0634\u0646 \u0646\u0627\u0634\u0646\u0627\u062e\u062a\u0647: SAVE_MEMORY]`** \u0627\u06cc\u0646 \u0627\u0633\u062a:\n\n### \ud83d\udd0d \u0686\u0631\u0627 \u0627\u06cc\u0646 \u0627\u062a\u0641\u0627\u0642 \u0627\u0641\u062a\u0627\u062f\u061f\n\u0631\u0628\u0627\u062a \u062a\u0644\u06af\u0631\u0627\u0645 \u06cc\u06a9 \u0633\u06cc\u0633\u062a\u0645 \u0645\u0641\u0633\u0631 \u062f\u0627\u062e\u0644\u06cc (Parser) \u062f\u0627\u0631\u062f \u06a9\u0647 \u0645\u062a\u0646 \u062e\u0631\u0648\u062c\u06cc \u0647\u0648\u0634 \u0645\u0635\u0646\u0648\u0639\u06cc \u0631\u0627 \u0627\u0633\u06a9\u0646 \u0645\u06cc\u200c\u06a9\u0646\u062f. \u0647\u0631 \u0632\u0645\u0627\u0646 \u062f\u0631 \u0645\u062a\u0646 \u0627\u0644\u06af\u0648\u06cc\u06cc \u0634\u0628\u06cc\u0647 `[[\u0646\u0627\u0645_\u062f\u0633\u062a\u0648\u0631: \u067e\u0627\u0631\u0627\u0645\u062a\u0631\u0647\u0627]]` \u067e\u06cc\u062f\u0627 \u06a9\u0646\u062f\u060c \u062a\u0644\u0627\u0634 \u0645\u06cc\u200c\u06a9\u0646\u062f \u0622\u0646 \u0631\u0627 \u0628\u0647 \u0639\u0646\u0648\u0627\u0646 \u06cc\u06a9 **\u0641\u0631\u0645\u0627\u0646 \u0627\u062c\u0631\u0627\u06cc\u06cc \u062f\u0631 \u0633\u0631\u0648\u0631 \u06cc\u0627 \u0631\u0628\u0627\u062a** (\u0645\u0627\u0646\u0646\u062f \u062a\u063a\u06cc\u06cc\u0631 \u0645\u062f\u0644\u060c \u062a\u0646\u0638\u06cc\u0645 \u0633\u0627\u0628\u062f\u0627\u0645\u06cc\u0646\u060c \u0633\u0627\u062e\u062a \u067e\u0631\u0648\u0698\u0647 \u0648 ...) \u0627\u062c\u0631\u0627 \u06a9\u0646\u062f.\n\n\u0627\u0632 \u0622\u0646\u062c\u0627 \u06a9\u0647 \u062f\u0631 \u067e\u06cc\u0627\u0645 \u0642\u0628\u0644\u06cc \u0645\u0646 \u0633\u0627\u062e\u062a\u0627\u0631 \u062a\u06af\u200c\u0647\u0627\u06cc \u067e\u06cc\u0634\u0646\u0647\u0627\u062f\u06cc \u0631\u0627 \u0628\u0631\u0627\u06cc \u0645\u0639\u0631\u0641\u06cc \u067e\u0631\u0648\u062a\u06a9\u0644 \u0630\u06a9\u0631 \u06a9\u0631\u062f\u0645\u060c \u0631\u0628\u0627\u062a \u062a\u0635\u0648\u0631 \u06a9\u0631\u062f \u0627\u06cc\u0646\u200c\u0647\u0627 \u06cc\u06a9 \u0641\u0631\u0645\u0627\u0646 \u0639\u0645\u0644\u06cc\u0627\u062a\u06cc \u0647\u0633\u062a\u0646\u062f\u061b \u0648 \u0686\u0648\u0646 **\u0647\u0646\u0648\u0632 \u0645\u0627\u0698\u0648\u0644 \u062d\u0627\u0641\u0638\u0647 \u0631\u0627 \u062f\u0631 \u06a9\u062f \u0631\u0628\u0627\u062a \u067e\u06cc\u0627\u062f\u0647\u200c\u0633\u0627\u0632\u06cc \u0648 \u0631\u062c\u06cc\u0633\u062a\u0631 \u0646\u06a9\u0631\u062f\u0647\u200c\u0627\u06cc\u0645**\u060c \u0631\u0628\u0627\u062a \u0627\u06cc\u0646 \u062a\u06af \u0631\u0627 \u0628\u0647 \u0639\u0646\u0648\u0627\u0646 \u06cc\u06a9 \u062f\u0633\u062a\u0648\u0631 \u062a\u0639\u0631\u06cc\u0641\u200c\u0646\u0634\u062f\u0647 \u0634\u0646\u0627\u0633\u0627\u06cc\u06cc \u06a9\u0631\u062f\u0647 \u0648 \u0628\u0647 \u0635\u0648\u0631\u062a \u062e\u0648\u062f\u06a9\u0627\u0631 \u067e\u06cc\u0627\u0645 `[\u0627\u06a9\u0634\u0646 \u0646\u0627\u0634\u0646\u0627\u062e\u062a\u0647: SAVE_MEMORY]` \u0631\u0627 \u062c\u0627\u06cc\u06af\u0632\u06cc\u0646 \u0622\u0646 \u06a9\u0631\u062f.\n\n---\n\n### \ud83d\udee0\ufe0f \u067e\u0633 \u0627\u0632 \u067e\u06cc\u0627\u062f\u0647\u200c\u0633\u0627\u0632\u06cc \u0633\u06cc\u0633\u062a\u0645 \u0686\u0647 \u062a\u063a\u06cc\u06cc\u0631\u06cc \u0631\u062e \u0645\u06cc\u200c\u062f\u0647\u062f\u061f\n1. **\u062b\u0628\u062a \u0631\u0633\u0645\u06cc \u0627\u06a9\u0634\u0646\u200c\u0647\u0627:** \u0627\u06cc\u0646 \u06f4 \u062a\u06af \u0628\u0647 \u0644\u06cc\u0633\u062a \u0627\u06a9\u0634\u0646\u200c\u0647\u0627\u06cc \u0631\u0633\u0645\u06cc \u0631\u0628\u0627\u062a \u0627\u0636\u0627\u0641\u0647 \u0645\u06cc\u200c\u0634\u0648\u0646\u062f.\n2. **\u0627\u062c\u0631\u0627\u06cc \u062f\u0631 \u067e\u0633\u200c\u0632\u0645\u06cc\u0646\u0647 (Silent Execution):** \u0648\u0642\u062a\u06cc \u0647\u0648\u0634 \u0645\u0635\u0646\u0648\u0639\u06cc \u0627\u06cc\u0646 \u062a\u06af\u200c\u0647\u0627 \u0631\u0627 \u062f\u0631 \u067e\u0627\u0633\u062e\u0634 \u0635\u0627\u062f\u0631 \u06a9\u0646\u062f\u060c \u0631\u0628\u0627\u062a \u062f\u0631 \u0647\u0645\u0627\u0646 \u0644\u062d\u0638\u0647 \u0627\u0637\u0644\u0627\u0639\u0627\u062a \u0631\u0627 \u062f\u0631 \u062f\u06cc\u062a\u0627\u0628\u06cc\u0633 \u062d\u0627\u0641\u0638\u0647 (`memory.db`) \u0630\u062e\u06cc\u0631\u0647/\u0648\u06cc\u0631\u0627\u06cc\u0634 \u0645\u06cc\u200c\u06a9\u0646\u062f.\n3. **\u0639\u062f\u0645 \u0646\u0645\u0627\u06cc\u0634 \u0628\u0647 \u06a9\u0627\u0631\u0628\u0631:** \u0627\u06cc\u0646 \u062a\u06af\u200c\u0647\u0627 \u0628\u0647 \u0635\u0648\u0631\u062a \u062e\u0648\u062f\u06a9\u0627\u0631 \u0627\u0632 \u062e\u0631\u0648\u062c\u06cc \u0646\u0647\u0627\u06cc\u06cc \u062d\u0630\u0641 \u0645\u06cc\u200c\u0634\u0648\u0646\u062f \u062a\u0627 \u0645\u062a\u0646 \u06a9\u0627\u0631\u0628\u0631 \u06a9\u0627\u0645\u0644\u0627\u064b \u062a\u0645\u06cc\u0632\u060c \u0627\u0646\u0633\u0627\u0646\u06cc \u0648 \u0628\u062f\u0648\u0646 \u06a9\u062f\u0647\u0627\u06cc \u0633\u06cc\u0633\u062a\u0645\u06cc \u0646\u0645\u0627\u06cc\u0634 \u062f\u0627\u062f\u0647 \u0634\u0648\u062f.\n\n---\n\n\u0622\u0645\u0627\u062f\u0647\u200c\u0627\u0645 \u06a9\u0647 \u067e\u06cc\u0627\u062f\u0647\u200c\u0633\u0627\u0632\u06cc **\u0641\u0627\u0632 \u06f1 (\u0645\u0627\u0698\u0648\u0644 \u062f\u06cc\u062a\u0627\u0628\u06cc\u0633 \u062d\u0627\u0641\u0638\u0647 `memory_manager.py`)** \u0648 \u0633\u067e\u0633 \u0631\u062c\u06cc\u0633\u062a\u0631 \u06a9\u0631\u062f\u0646 \u0627\u06cc\u0646 \u0627\u06a9\u0634\u0646\u200c\u0647\u0627 \u0631\u0627 \u0634\u0631\u0648\u0639 \u06a9\u0646\u0645. \u0622\u06cc\u0627 \u0645\u0648\u0627\u0641\u0642\u06cc\u062f\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": "\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_status_msg_id": null, "restart_pending": false, "last_delivered": true, - "last_update_time": 1788069412.7671723, + "last_update_time": 1788069497.0166173, "workspace": "/root", "conversation_id": "d54c0c8d-6424-40a4-84f4-7a9de60eac7b", "model": "gemini-3.7-flash-auto", "effort": "high", "language": "fa", - "last_context_length": 17956, - "last_total_tokens": 217340 + "last_context_length": 21661, + "last_total_tokens": 265643 }, "232801087": { "chat_id": 232801087,