diff --git a/core/embedded_db.py b/core/embedded_db.py index 0c6f3ac..a36c2b5 100644 --- a/core/embedded_db.py +++ b/core/embedded_db.py @@ -292,7 +292,76 @@ class EmbeddedGraphDB: "relations": relations, "message": f"找到 {len(entities)} 个实体, {len(relations)} 条关系" } - + + def get_recent_tasks(self, limit: int = 10, state_filter: str = None) -> Dict: + """ + 获取最近的任务节点 + + Args: + limit: 返回数量 + state_filter: 可选状态过滤(如:进行中、已完成、已暂停、已取消、archived) + + Returns: + {"tasks": [{"task_id": str, "description": str, "state": str, + "info_count": int, "updated_at": str}, ...]} + """ + cursor = self.conn.cursor() + + # 查询所有 TaskNode 实体 + cursor.execute(""" + SELECT e.id, e.name, e.updated_at + FROM entities e + WHERE e.type = 'TaskNode' + ORDER BY e.updated_at DESC + LIMIT ? + """, (limit,)) + rows = cursor.fetchall() + + tasks = [] + for row in rows: + entity_id, name, updated_at = row + + # 查 description + cursor.execute(""" + SELECT r.relation_type, t.name + FROM relations r + JOIN entities t ON r.target_id = t.id + WHERE r.source_id = ? AND r.status = 'active' + AND r.relation_type IN ('has_description', 'HAS_STATE') + """, (entity_id,)) + desc = "" + state = "未知" + for rtype, tname in cursor.fetchall(): + if rtype == 'has_description': + desc = tname + elif rtype == 'HAS_STATE': + state = tname.replace('State_', '') + + # 可选状态过滤 + if state_filter and state != state_filter: + continue + + # 查关联信息节点数量 + cursor.execute(""" + SELECT COUNT(*) + FROM relations + WHERE source_id = ? AND relation_type = 'CONTAINS_INFO' AND status = 'active' + """, (entity_id,)) + info_count = cursor.fetchone()[0] + + tasks.append({ + "task_id": name, + "description": desc, + "state": state, + "info_count": info_count, + "updated_at": updated_at + }) + + return { + "tasks": tasks, + "total": len(tasks) + } + def commit(self, triplets: List[Dict], entity_types: Dict = None, temporal_tag: str = None, session_id: str = None, turn_id: int = None) -> Dict: diff --git a/core/prompts/templates/system_prompt.md b/core/prompts/templates/system_prompt.md index 16f2022..5a062e0 100644 --- a/core/prompts/templates/system_prompt.md +++ b/core/prompts/templates/system_prompt.md @@ -103,6 +103,7 @@ subject, relation, object 每个字段必须是一个**短关键字**(1~5个 ### 任务工具(生命周期管理) | 工具 | 时机 | 说明 | |------|------|------| +| `task_query` | 新对话/需要回顾 | 查询最近任务列表(按更新时间倒序)。**新对话开始时优先调用此工具**,了解现有任务后再决定是继续还是创建新任务 | | `task_create` | 新会话/新主题 | 创建任务节点。**每次新的对话会话应当创建一个独立的「当前轮对话」任务** | | `task_set_state` | 状态变更 | 修改任务状态(active、completed、archived)。**旧会话结束后必须将对应的任务设为 archived** | | `task_delete` | 确需删除的任务 | 彻底删除任务节点 | diff --git a/core/tool_executor.py b/core/tool_executor.py index 807a1c7..8415132 100644 --- a/core/tool_executor.py +++ b/core/tool_executor.py @@ -105,6 +105,11 @@ def execute_tool(graph: Any, tool_name: str, arguments: dict) -> str: result = execute_task_link_info(graph, arguments) return json.dumps(result, ensure_ascii=False, default=str) + elif tool_name == "task_query": + recorder.record("query", tool_name, "") + result = execute_task_query(graph, arguments) + return json.dumps(result, ensure_ascii=False, default=str) + return f"未知工具: {tool_name}" except Exception as e: @@ -352,3 +357,17 @@ def execute_task_link_info(graph: Any, arguments: dict) -> dict: "linked_nodes": info_node_names, "details": result } + +def execute_task_query(graph: Any, arguments: dict) -> dict: + """查询最近的任务列表""" + limit = arguments.get("limit", 10) + state_filter = arguments.get("state_filter") + + result = graph.get_recent_tasks(limit=limit, state_filter=state_filter) + + return { + "status": "success", + "tasks": result["tasks"], + "total": result["total"], + "message": f"找到 {result['total']} 个任务" + } diff --git a/core/tool_limiter.py b/core/tool_limiter.py index ec8516d..2089fa8 100644 --- a/core/tool_limiter.py +++ b/core/tool_limiter.py @@ -45,6 +45,9 @@ class ToolLimiter: if tool_name in ('task_create', 'task_set_state', 'task_delete', 'task_link_info'): return ('task', 'update') + if tool_name == 'task_query': + return ('task', 'query') + if tool_name == 'memory_recall': # 尝试区分工作记忆链查询 vs 一般记忆查询 query = (arguments.get('queryIntent', '') + ' ' + ' '.join( diff --git a/core/tools/memory_tools.py b/core/tools/memory_tools.py index efa0fe0..c3fdce4 100644 --- a/core/tools/memory_tools.py +++ b/core/tools/memory_tools.py @@ -550,6 +550,26 @@ AI操作步骤: "required": ["task_id", "info_node_names"] } } + }, + { + "type": "function", + "function": { + "name": "task_query", + "description": "查询最近的任务列表。按更新时间倒序排列。新对话开始时优先使用此工具获取所有进展中的任务,避免重复创建。", + "parameters": { + "type": "object", + "properties": { + "limit": { + "type": "integer", + "description": "返回的任务数量,默认10" + }, + "state_filter": { + "type": "string", + "description": "按状态筛选:进行中、已完成、已暂停、已取消、archived" + } + } + } + } } ]