feat(v2): T-M2 采纳 pi branch-summarization——折叠摘要携带文件清单 + rollup 行带产物锚点

- AgentService._history_from_session:从全部轮次的 write_file/edit_file
  工具调用提取已读写文件清单(去重/单路径裁 120 字符/封顶 20 个),以摘要轮
  注入对话上下文——轮次滑出窗口后事实清单仍在(丢上下文不丢事实)
- Workspace.rollup:done 折叠行追加(产出: <artifact 锚点>),上下文折叠后
  产物事实在 a:// 锚点体系内仍可寻址;既有子串断言全部兼容
- 新增 tests/test_branch_manifest.py 4 项
This commit is contained in:
tzt
2026-09-19 09:32:33 +08:00
parent f7e8273434
commit 184c11199a
3 changed files with 102 additions and 2 deletions
+23 -1
View File
@@ -71,6 +71,9 @@ _REVIEW_SCHEMA_HINT = {
DEFAULT_MAX_HANDOFFS = 2 # 规划者<->执行者交接轮数上限
# 会写文件的工具名(T-M2 折叠摘要的文件清单来源)
_FILE_TOOLS = {"write_file", "edit_file"}
def _parse_json_loose(content: str) -> Dict[str, Any]:
"""宽松解析规划者的 JSON 输出(剥围栏/取首个对象);失败返回 {}"""
@@ -445,12 +448,31 @@ class AgentService:
def _history_from_session(session: Optional["AgentSession"],
max_turns: int = 6,
max_chars: int = 1500) -> List[Dict[str, Any]]:
"""把会话既往轮次折叠成对话上下文(不含工具细节)。"""
"""把会话既往轮次折叠成对话上下文(不含工具细节)。
T-M2(采纳 pi branch-summarization 思想):折叠摘要携带本会话
已写入/编辑的文件清单——轮次滑出窗口后,事实清单仍随首条摘要
进入对话,丢上下文不丢事实。
"""
if session is None:
return []
turns = [t for t in session.data.get("turns", [])
if t.get("state") == STATE_DONE and t.get("response")]
files = sorted({
str((a.get("arguments") or {}).get("path") or "").strip()
for t in session.data.get("turns", [])
for a in (t.get("tool_calls") or [])
if isinstance(a, dict)
and str(a.get("name") or "") in _FILE_TOOLS
and (a.get("arguments") or {}).get("path")
})
out: List[Dict[str, Any]] = []
if files:
shown = "".join(f[:120] for f in files[:20])
more = f"(等共 {len(files)} 个)" if len(files) > 20 else ""
out.append({"role": "user",
"content": f"(上下文摘要)本会话此前已写入/编辑的文件:{shown}{more}"})
out.append({"role": "assistant", "content": "已了解上述文件背景,将继续任务。"})
for t in turns[-max_turns:]:
out.append({"role": "user", "content": str(t["task"])[:max_chars]})
out.append({"role": "assistant", "content": str(t["response"])[:max_chars]})