Talegorithm 4 часов назад
Родитель
Сommit
242f514a33
3 измененных файлов с 101 добавлено и 28 удалено
  1. 37 28
      agent/core/runner.py
  2. 3 0
      agent/tools/builtin/__init__.py
  3. 61 0
      agent/tools/builtin/context.py

+ 37 - 28
agent/core/runner.py

@@ -157,6 +157,7 @@ BUILTIN_TOOLS = [
     "goal",
     "agent",
     "evaluate",
+    "get_current_context",
 
     # 搜索工具
     "search_posts",
@@ -887,13 +888,14 @@ class AgentRunner:
             return history, start_head_seq, sequence
 
         # 创建 summary 消息
+        from agent.core.prompts import build_summary_header
         summary_msg = Message.create(
             trace_id=trace_id,
             role="user",
             sequence=sequence,
             parent_sequence=start_head_seq,
             branch_type=None,  # 主路径
-            content=f"[压缩总结 - Fallback]\n{summary_text}",
+            content=build_summary_header(summary_text),
         )
 
         if self.trace_store:
@@ -1086,31 +1088,6 @@ class AgentRunner:
                 config.enable_prompt_caching
             )
 
-            # 周期性注入 GoalTree + Collaborators(动态内容追加在缓存点之后)
-            # 仅在主路径执行
-            if not side_branch_ctx and iteration % CONTEXT_INJECTION_INTERVAL == 0:
-                context_injection = self._build_context_injection(trace, goal_tree)
-                if context_injection:
-                    system_msg = {"role": "system", "content": context_injection}
-                    llm_messages.append(system_msg)
-
-                    # 持久化上下文注入消息
-                    if self.trace_store:
-                        current_goal_id = goal_tree.current_id if (goal_tree and goal_tree.current_id) else None
-                        system_message = Message.create(
-                            trace_id=trace_id,
-                            role="system",
-                            sequence=sequence,
-                            goal_id=current_goal_id,
-                            parent_sequence=head_seq if head_seq > 0 else None,
-                            content=f"[上下文注入]\n{context_injection}",
-                        )
-                        await self.trace_store.add_message(system_message)
-                        history.append(system_msg)
-                        head_seq = sequence
-                        sequence += 1
-
-
             # 调用 LLM(等待完成后再检查 cancel 信号,不中断正在进行的调用)
             result = await self.llm_call(
                 messages=llm_messages,
@@ -1129,6 +1106,30 @@ class AgentRunner:
             cache_creation_tokens = result.get("cache_creation_tokens")
             cache_read_tokens = result.get("cache_read_tokens")
 
+            # 周期性自动注入上下文(仅主路径)
+            if not side_branch_ctx and iteration % CONTEXT_INJECTION_INTERVAL == 0:
+                # 检查是否已经调用了 get_current_context
+                if tool_calls:
+                    has_context_call = any(
+                        tc.get("function", {}).get("name") == "get_current_context"
+                        for tc in tool_calls
+                    )
+                else:
+                    has_context_call = False
+                    tool_calls = []
+
+                if not has_context_call:
+                    # 手动添加 get_current_context 工具调用
+                    import uuid
+                    context_call_id = f"call_context_{uuid.uuid4().hex[:8]}"
+                    tool_calls.append({
+                        "id": context_call_id,
+                        "type": "function",
+                        "function": {"name": "get_current_context", "arguments": "{}"}
+                    })
+                    logger.info(f"[周期性注入] 自动添加 get_current_context 工具调用 (iteration={iteration})")
+
+
             # 按需自动创建 root goal(仅主路径)
             if not side_branch_ctx and goal_tree and not goal_tree.goals and tool_calls:
                 has_goal_call = any(
@@ -1286,14 +1287,22 @@ class AgentRunner:
                             logger.warning("侧分支未生成有效 summary,使用默认")
                             summary_text = "压缩完成"
 
-                        # 创建主路径的 summary 消息
+                        # 创建主路径的 summary 消息(末尾追加详细 GoalTree)
+                        from agent.core.prompts import build_summary_header
+                        summary_content = build_summary_header(summary_text)
+
+                        # 追加详细 GoalTree(压缩后立即注入)
+                        if goal_tree and goal_tree.goals:
+                            goal_tree_detail = goal_tree.to_prompt(include_summary=True)
+                            summary_content += f"\n\n## Current Plan\n\n{goal_tree_detail}"
+
                         summary_msg = Message.create(
                             trace_id=trace_id,
                             role="user",
                             sequence=sequence,
                             parent_sequence=side_branch_ctx.start_head_seq,
                             branch_type=None,  # 回到主路径
-                            content=f"[压缩总结]\n{summary_text}",
+                            content=summary_content,
                         )
 
                         if self.trace_store:

+ 3 - 0
agent/tools/builtin/__init__.py

@@ -19,6 +19,7 @@ from agent.tools.builtin.search import search_posts, get_search_suggestions
 from agent.tools.builtin.sandbox import (sandbox_create_environment, sandbox_run_shell,
                                          sandbox_rebuild_with_ports,sandbox_destroy_environment)
 from agent.tools.builtin.knowledge import(knowledge_search,knowledge_save,knowledge_list,knowledge_update,knowledge_batch_update,knowledge_slim)
+from agent.tools.builtin.context import get_current_context
 from agent.trace.goal_tool import goal
 # 导入浏览器工具以触发注册
 import agent.tools.builtin.browser  # noqa: F401
@@ -50,6 +51,8 @@ __all__ = [
     "sandbox_run_shell",
     "sandbox_rebuild_with_ports",
     "sandbox_destroy_environment",
+    # 上下文工具
+    "get_current_context",
     # Goal 管理
     "goal",
 ]

+ 61 - 0
agent/tools/builtin/context.py

@@ -0,0 +1,61 @@
+"""
+上下文工具 - 获取当前执行上下文
+
+提供 get_current_context 工具,让 Agent 可以主动获取:
+- 当前计划(GoalTree)
+- 焦点提醒
+- 协作者状态
+
+框架也会在特定轮次自动调用此工具进行周期性上下文刷新。
+"""
+
+from agent.tools import tool, ToolResult, ToolContext
+
+
+@tool(
+    description="获取当前执行上下文,包括计划状态、焦点提醒、协作者信息等。当你感到困惑或需要回顾当前任务状态时调用。",
+    hidden_params=["context"]
+)
+async def get_current_context(
+    context: ToolContext,
+) -> ToolResult:
+    """
+    获取当前执行上下文
+
+    Returns:
+        ToolResult: 包含 GoalTree、焦点提醒、协作者状态等信息
+    """
+    runner = context.get("runner")
+    goal_tree = context.get("goal_tree")
+    trace_id = context.get("trace_id")
+
+    if not runner:
+        return ToolResult(
+            title="❌ 无法获取上下文",
+            output="Runner 未初始化",
+            error="Runner not available"
+        )
+
+    # 获取 trace 对象
+    trace = None
+    if runner.trace_store and trace_id:
+        trace = await runner.trace_store.get_trace(trace_id)
+
+    # 构建上下文内容(复用 runner 的 _build_context_injection 方法)
+    if hasattr(runner, '_build_context_injection'):
+        context_content = runner._build_context_injection(trace, goal_tree)
+    else:
+        # Fallback:只返回 GoalTree
+        if goal_tree and goal_tree.goals:
+            context_content = f"## Current Plan\n\n{goal_tree.to_prompt()}"
+        else:
+            context_content = "暂无计划信息"
+
+    if not context_content:
+        context_content = "当前无需要刷新的上下文信息"
+
+    return ToolResult(
+        title="📋 当前执行上下文",
+        output=context_content,
+        long_term_memory="已刷新执行上下文",
+    )