from typing import Any from app.memory.service import MemoryService from app.tools._dispatch import NOT_HANDLED, ToolContext TOOL_NAMES = frozenset({ "remember_fact", "recall_memories", "forget_memory", "update_profile", "update_session_summary", }) TOOL_DEFINITIONS: list[dict[str, Any]] = [ { "type": "function", "function": { "name": "remember_fact", "description": ( "Сохранить факт в долгосрочную память. " "Когда пользователь просит «запомни», или сообщает устойчивое предпочтение/факт." ), "parameters": { "type": "object", "properties": { "content": {"type": "string", "description": "Что запомнить"}, "category": { "type": "string", "description": "preference, person, habit, project, fact", }, "importance": {"type": "integer", "description": "1-5, по умолчанию 3"}, }, "required": ["content"], }, }, }, { "type": "function", "function": { "name": "recall_memories", "description": ( "Поиск в долгосрочной памяти. " "Когда спрашивают «что ты помнишь», «что я говорил про X»." ), "parameters": { "type": "object", "properties": { "query": {"type": "string", "description": "Подстрока для поиска"}, "category": {"type": "string"}, "limit": {"type": "integer"}, }, "required": [], }, }, }, { "type": "function", "function": { "name": "forget_memory", "description": "Удалить (деактивировать) факт по id из recall_memories или снимка памяти.", "parameters": { "type": "object", "properties": { "memory_id": {"type": "integer"}, }, "required": ["memory_id"], }, }, }, { "type": "function", "function": { "name": "update_profile", "description": ( "Обновить профиль пользователя: name, timezone, language, notes. " "Передавай только изменившиеся поля." ), "parameters": { "type": "object", "properties": { "name": {"type": "string"}, "age": {"type": "string", "description": "Возраст пользователя"}, "timezone": {"type": "string"}, "language": {"type": "string"}, "notes": {"type": "string"}, }, "required": [], }, }, }, { "type": "function", "function": { "name": "update_session_summary", "description": ( "Сохранить краткую сводку темы текущего чата " "(когда диалог длинный или пользователь просит «сожми контекст»)." ), "parameters": { "type": "object", "properties": { "summary": {"type": "string", "description": "2-5 предложений о теме чата"}, "session_id": {"type": "integer"}, }, "required": ["summary", "session_id"], }, }, }, ] async def execute(name: str, arguments: dict[str, Any], ctx: ToolContext) -> Any: if name not in TOOL_NAMES: return NOT_HANDLED memory = MemoryService(ctx.db, ctx.user_id) if name == "remember_fact": return memory.remember_fact( arguments.get("content", ""), category=arguments.get("category", "fact"), importance=arguments.get("importance", 3), session_id=ctx.session_id, source="tool", ) if name == "recall_memories": return memory.recall_memories( query=arguments.get("query"), category=arguments.get("category"), limit=arguments.get("limit", 20), ) if name == "forget_memory": return memory.forget_memory(int(arguments["memory_id"])) if name == "update_profile": updates = { k: arguments[k] for k in ("name", "age", "timezone", "language", "notes") if k in arguments and arguments[k] is not None } return memory.update_profile(updates) if name == "update_session_summary": return memory.update_session_summary( int(arguments["session_id"]), arguments.get("summary", ""), ) return NOT_HANDLED