-
职责混乱:
MemoryFormatter既格式化 memory 信息,又格式化 artifacts(diff, errors, test results)Prompt Template也有占位符显示 artifacts({CURRENT_DIFF}, {RECENT_ERROR}, {TEST_RESULTS})- 导致同一信息在两个地方显示
-
数据流不清晰:
State.memory → MemoryFormatter → Memory Context (包含 Current State with diff) State.artifacts → ContextPack → Prompt Template ({CURRENT_DIFF}, {RECENT_ERROR})两者重叠,导致重复
-
违反单一数据源原则:
- Diff 在 Memory Current State 中显示(最多2000字符)
- Diff 在 Prompt Template 的 {CURRENT_DIFF} 中显示(完整)
- 重复浪费 token
-
职责分离:
- Memory Formatter:只负责格式化 memory 相关的信息(plan, context, activity, tool results, file content)
- Artifacts Formatter:负责格式化 artifacts(diff, errors, test results)
- Prompt Template:只负责结构化和占位符替换
-
单一数据源:
- 每个信息只在一个地方显示
- Memory Context 不包含 artifacts 的完整内容
- Artifacts 通过 Prompt Template 的占位符显示
-
清晰的边界:
- Memory = 历史状态、计划、上下文、活动记录
- Artifacts = 当前状态(diff, errors, test results)
┌─────────────────────────────────────────────────────────┐
│ AgentState │
│ ┌──────────────┐ ┌──────────────┐ │
│ │ Memory │ │ Artifacts │ │
│ │ - plan │ │ - current_diff│ │
│ │ - context │ │ - last_error │ │
│ │ - activity │ │ - test_results│ │
│ │ - tool_results│ └──────────────┘ │
│ └──────────────┘ │
└─────────────────────────────────────────────────────────┘
│ │
│ │
▼ ▼
┌──────────────────┐ ┌──────────────────┐
│ MemoryFormatter │ │ ContextPackBuilder│
│ │ │ │
│ 只格式化 Memory │ │ 只格式化 Artifacts│
│ - Critical Warnings│ │ - Current Diff │
│ - Task Overview │ │ - Recent Error │
│ - Execution Plan │ │ - Test Results │
│ - Context │ └──────────────────┘
│ - Activity │ │
│ - Tool Results │ │
│ - File Content │ │
│ - State Summary │ │
│ (不含完整diff) │ │
└──────────────────┘ │
│ │
│ │
└──────────┬─────────────┘
│
▼
┌──────────────────┐
│ Prompt Template │
│ │
│ {STATE_SUMMARY} │ ← Memory Context
│ {CURRENT_DIFF} │ ← Artifacts
│ {RECENT_ERROR} │ ← Artifacts
│ {TEST_RESULTS} │ ← Artifacts
└──────────────────┘
Current State 应该只包含状态摘要,不包含完整内容:
def _format_current_state(self, state: "AgentState") -> str:
"""格式化当前状态摘要
注意:Current State 只包含状态摘要,完整内容在 Prompt Template 的占位符中显示。
这样可以避免重复,并保持职责清晰。
"""
parts = ["### ⚠️ Current State"]
# Last Error - 只显示摘要
if state.last_error.summary:
# 只显示错误类型和关键信息,不显示完整堆栈
error_summary = state.last_error.summary.split('\n')[0] # 第一行
if len(state.last_error.summary) > 200:
error_summary += " (see Recent Errors section below for details)"
parts.append(f"**Last Error**: {error_summary}")
else:
parts.append("**Last Error**: None")
# Current Diff - 只显示统计信息
if state.artifacts.current_diff:
diff_lines = state.artifacts.current_diff.count('\n')
diff_size = len(state.artifacts.current_diff)
# 提取修改的文件
files_changed = self._extract_files_from_diff(state.artifacts.current_diff)
if files_changed:
files_summary = ', '.join(files_changed[:3])
if len(files_changed) > 3:
files_summary += f" (+{len(files_changed) - 3} more)"
parts.append(f"**Current Diff**: {diff_lines} lines in {len(files_changed)} file(s): {files_summary} (see Current Diff section below)")
else:
parts.append(f"**Current Diff**: {diff_lines} lines changed (see Current Diff section below)")
else:
parts.append("**Current Diff**: No changes")
# Test Results - 只显示状态
if state.artifacts.test_results:
# 只显示通过/失败状态,不显示完整结果
if "passed" in state.artifacts.test_results.lower() or "✓" in state.artifacts.test_results:
parts.append("**Test Results**: ✓ Passed (see Test Results section below for details)")
elif "failed" in state.artifacts.test_results.lower() or "❌" in state.artifacts.test_results:
parts.append("**Test Results**: ❌ Failed (see Test Results section below for details)")
else:
parts.append("**Test Results**: ⚠️ Unknown (see Test Results section below for details)")
else:
parts.append("**Test Results**: No verification command available")
return "\n".join(parts)Memory Context 应该包含:
- ✅ Critical Warnings
- ✅ Task Overview
- ✅ Execution Plan
- ✅ Important Context
- ✅ Recent Activity
- ✅ Tool Execution Results
- ✅ Modified Files Content
- ✅ Current State (摘要,不含完整内容)
- ✅ Next Steps Guidance
Artifacts (通过 Prompt Template 占位符显示):
- ✅ Current Diff (完整内容)
- ✅ Recent Error (完整内容)
- ✅ Test Results (完整内容)
在 Prompt Template 中明确说明:
{STATE_SUMMARY}包含 memory 信息,Current State 部分只包含摘要{CURRENT_DIFF},{RECENT_ERROR},{TEST_RESULTS}包含完整内容
def _extract_files_from_diff(self, diff: str) -> List[str]:
"""从 diff 中提取修改的文件列表"""
files = []
for line in diff.split('\n')[:50]: # 只检查前50行
if line.startswith('+++ ') or line.startswith('--- '):
file_path = line[4:].strip()
if file_path and file_path not in files:
files.append(file_path)
return files- 修改
_format_current_state()只显示摘要 - 添加
_extract_files_from_diff()辅助方法 - 更新文档说明职责边界
- 运行现有测试确保不破坏功能
- 验证 diff 不再重复
- 检查 token 使用量是否减少
- 检查 Recent Error 是否也需要类似处理
- 检查 Test Results 是否也需要类似处理
- 统一所有 artifacts 的处理方式
- Token 节省:消除 diff 重复,节省数千 token
- 职责清晰:Memory 和 Artifacts 职责明确
- 易于维护:单一数据源,修改更容易
- 可扩展性:未来添加新的 artifact 类型更容易
- 低风险:只是改变显示方式,不改变数据源
- 向后兼容:Prompt Template 结构不变,只是内容来源更清晰
- 测试覆盖:现有测试应该能覆盖大部分场景