File size: 2,535 Bytes
0e3d4b8
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
"""Reviewer Agent — reviews work, validates quality, finds issues.

Reviews the output of other agents. Can approve or reject work,
and suggest improvements. Runs after each step is completed.
"""

from __future__ import annotations

import logging
from typing import Any

from .agent_base import BaseAgent
from ..memory.goal_memory import Goal

logger = logging.getLogger(__name__)


class ReviewerAgent(BaseAgent):
    """Reviews work done by other agents and validates quality."""

    def __init__(self, goal_memory, persistent_memory=None, generate_fn=None):
        super().__init__(
            name="reviewer",
            role="Quality Reviewer",
            description="Reviews work, validates quality, and finds issues",
            goal_memory=goal_memory,
            persistent_memory=persistent_memory,
            generate_fn=generate_fn,
            poll_interval_s=4.0,
        )

    def _can_handle(self, goal: Goal) -> bool:
        """Reviewer handles goals in reviewing status."""
        return goal.status == "reviewing"

    def process_goal(self, goal: Goal) -> dict[str, Any]:
        """Review the most recent step output."""
        if goal.current_step == 0 and not goal.steps:
            return {"success": True, "output": "Nothing to review"}

        # Review the last completed step
        review_idx = max(0, goal.current_step - 1)
        if review_idx >= len(goal.steps):
            return {"success": True, "output": "No steps to review"}

        step = goal.steps[review_idx]
        if step.get("status") != "completed":
            return {"success": True, "output": "Step not completed yet"}

        prompt = (
            f"You are a quality reviewer. Review this work:\n"
            f"Goal: {goal.title}\n"
            f"Step: {step['title']}\n"
            f"Result: {step.get('result', '')[:500]}\n\n"
            f"Evaluate: Is this correct and complete? Reply APPROVED or NEEDS_WORK with reason.\n"
        )

        response = self._generate(prompt)

        approved = "APPROVED" in response.upper()

        if self.persistent_memory:
            self.persistent_memory.add_episodic(
                "review", f"Review of '{step['title']}': {'approved' if approved else 'needs work'}",
                importance=0.6, tags=["review", goal.title[:20]]
            )

        if approved:
            return {"success": True, "output": f"Approved: {response[:100]}"}
        else:
            return {"success": False, "output": "", "error": f"Needs work: {response[:100]}"}