resumen de artifacts
This commit is contained in:
@@ -84,11 +84,15 @@ class ContextEngine:
|
||||
if kb_section:
|
||||
sections.append(kb_section)
|
||||
|
||||
# 4. Task state
|
||||
# 4. Task history — compact summaries of past tasks in this session
|
||||
if "task_state" in allowed and session.task_history:
|
||||
sections.append(self._build_task_history(session))
|
||||
|
||||
# 5. Task state — current task
|
||||
if "task_state" in allowed and session.current_task:
|
||||
sections.append(self._build_task_state(session.current_task))
|
||||
|
||||
# 5. Artifact memory — summarised, never raw
|
||||
# 6. Artifact memory — summarised, never raw (only current task's)
|
||||
if "artifact_memory" in allowed and artifacts:
|
||||
sections.append(self._build_artifact_memory(artifacts))
|
||||
|
||||
@@ -379,6 +383,42 @@ class ContextEngine:
|
||||
parts.extend(session.current_task.facts_extracted[-5:])
|
||||
return " ".join(parts)
|
||||
|
||||
def _build_task_history(self, session: SessionState) -> ContextSection:
|
||||
"""Build a compact summary of past tasks in this session.
|
||||
|
||||
Each completed task is ~50 tokens instead of hundreds.
|
||||
The agent retains awareness of what was done before.
|
||||
"""
|
||||
lines = [
|
||||
"# Session History",
|
||||
f"_{len(session.task_history)} previous task(s) in this session_",
|
||||
"",
|
||||
]
|
||||
|
||||
for i, entry in enumerate(session.task_history):
|
||||
status = entry.get("status", "?")
|
||||
objective = entry.get("objective", "")[:100]
|
||||
summary = entry.get("summary", "")[:150]
|
||||
facts = entry.get("facts", [])
|
||||
|
||||
lines.append(f"**Task {i + 1}** [{status}]: {objective}")
|
||||
if summary:
|
||||
lines.append(f" Result: {summary}")
|
||||
if facts:
|
||||
lines.append(f" Facts: {'; '.join(facts[:5])}")
|
||||
review = entry.get("review", "")
|
||||
if review:
|
||||
lines.append(f" Review: {review[:100]}")
|
||||
lines.append("")
|
||||
|
||||
content = "\n".join(lines)
|
||||
return ContextSection(
|
||||
section_type=ContextSectionType.TASK_STATE,
|
||||
content=content,
|
||||
priority=55, # Below knowledge (60), above artifacts (50)
|
||||
token_estimate=estimate_tokens(content),
|
||||
)
|
||||
|
||||
def _build_task_state(self, task: TaskState) -> ContextSection:
|
||||
lines = [
|
||||
"# Current Task",
|
||||
|
||||
@@ -85,6 +85,7 @@ class SessionState(BaseModel):
|
||||
immutable_rules: list[str] = Field(default_factory=list)
|
||||
current_task: TaskState | None = None
|
||||
completed_tasks: list[str] = Field(default_factory=list)
|
||||
task_history: list[dict[str, Any]] = Field(default_factory=list) # Compact summaries of past tasks
|
||||
turn_count: int = 0
|
||||
created_at: datetime = Field(default_factory=lambda: datetime.now(timezone.utc))
|
||||
updated_at: datetime = Field(default_factory=lambda: datetime.now(timezone.utc))
|
||||
|
||||
@@ -209,7 +209,10 @@ class OrchestratorEngine:
|
||||
logger.error("Review failed: %s", e)
|
||||
review_result = {"content": f"Review skipped due to error: {e}"}
|
||||
|
||||
# 5. Complete — session ALWAYS returns to idle
|
||||
# 5. Compact task into history before completing
|
||||
await self._compact_task_to_history(session, task, results, review_result)
|
||||
|
||||
# 6. Complete — session ALWAYS returns to idle
|
||||
session.complete_task()
|
||||
|
||||
final_content = self._assemble_response(results, review_result)
|
||||
@@ -258,6 +261,68 @@ class OrchestratorEngine:
|
||||
# Internals
|
||||
# ------------------------------------------------------------------
|
||||
|
||||
async def _compact_task_to_history(
|
||||
self,
|
||||
session: SessionState,
|
||||
task: TaskState,
|
||||
results: list[dict[str, Any]],
|
||||
review_result: dict[str, Any],
|
||||
) -> None:
|
||||
"""Compact a completed task into a minimal history entry.
|
||||
|
||||
This is critical for long sessions: instead of keeping all
|
||||
artifacts and facts from every task, we compress each completed
|
||||
task into a ~200 token summary that preserves:
|
||||
- What was done (objective)
|
||||
- What was produced (file changes, modules created)
|
||||
- Key facts learned
|
||||
- Issues found by reviewer
|
||||
"""
|
||||
# Collect all artifact summaries from this task
|
||||
artifacts = await self.memory.list_artifacts(session.session_id)
|
||||
task_artifacts = [a for a in artifacts if a.task_id == task.task_id]
|
||||
|
||||
# Build compact summary
|
||||
step_summaries = []
|
||||
for step in task.plan:
|
||||
if step.result_summary:
|
||||
step_summaries.append(f"{step.agent_role}: {step.result_summary[:100]}")
|
||||
|
||||
tools_used = set()
|
||||
for step in task.plan:
|
||||
tools_used.update(step.tools_used)
|
||||
|
||||
history_entry = {
|
||||
"task_id": task.task_id,
|
||||
"objective": task.objective,
|
||||
"status": task.status.value,
|
||||
"steps": len(task.plan),
|
||||
"facts": task.facts_extracted[-10:],
|
||||
"tools_used": list(tools_used)[:10],
|
||||
"artifacts_count": len(task_artifacts),
|
||||
"summary": "; ".join(step_summaries)[:300],
|
||||
"review": (review_result.get("content", ""))[:200],
|
||||
}
|
||||
|
||||
# Keep max 20 task histories (trim oldest)
|
||||
session.task_history.append(history_entry)
|
||||
if len(session.task_history) > 20:
|
||||
session.task_history = session.task_history[-20:]
|
||||
|
||||
# Clean up old artifacts from Redis to free memory
|
||||
# Keep only artifacts from the last 2 tasks
|
||||
recent_task_ids = {t["task_id"] for t in session.task_history[-2:]}
|
||||
for artifact in artifacts:
|
||||
if artifact.task_id not in recent_task_ids:
|
||||
# Remove old artifact from Redis hash
|
||||
key = f"{self.memory._prefix}:session:{session.session_id}:artifacts"
|
||||
await self.memory._r.hdel(key, artifact.artifact_id)
|
||||
|
||||
logger.info(
|
||||
"Compacted task %s into history (%d facts, %d tools, %d artifacts → summary)",
|
||||
task.task_id, len(task.facts_extracted), len(tools_used), len(task_artifacts),
|
||||
)
|
||||
|
||||
def _create_agent(self, role: AgentRole) -> PlannerAgent | CoderAgent | CollectorAgent | ReviewerAgent:
|
||||
"""Instantiate a subagent for the given role."""
|
||||
profile = self._profiles[role]
|
||||
|
||||
Reference in New Issue
Block a user