valhalla / backend /src /agents /react.py
Dontcryx_07
final
d660fa9
Raw
History Blame Contribute Delete
2.34 kB
"""react β€” deterministic 0-LLM "keep going or replan?" filter.
Given the agent's current action and fresh observations, returns a
decision: no action -> replan, action finished -> replan, mid-action with
no novelty -> continue. The LLM variant of this decision lives in
brain.decide_tick and fires only on novelty.
Architecture: retained as the cheap reflex layer; the production engine
currently routes decisions through brain.py and WorldEngine phases.
Design: every path has a fixed answer β€” this step must never stall the
simulation on a model call.
"""
from __future__ import annotations
from typing import Any, Dict, List, Optional
from pydantic import BaseModel
from src.core.log import get_logger
from src.core.world_state import CurrentAction
from src.core.perceive import Observation
logger = get_logger(__name__)
class ReactionDecision(BaseModel):
should_replan: bool
reason: str
def decide_reaction(
agent_id: str,
persona: Dict[str, Any],
current_action: Optional[CurrentAction],
observations: List[Observation],
memories: List[str],
tick: int,
) -> ReactionDecision:
"""Cheap heuristic decision: no LLM involved."""
if current_action is None:
return ReactionDecision(should_replan=True, reason="no current action to continue")
if current_action.is_finished(tick):
return ReactionDecision(should_replan=True, reason="current action has finished")
if not observations:
return ReactionDecision(should_replan=False, reason="mid-action, nothing new perceived")
# Mid-action with observations: cheap heuristic β€” always continue.
# The brain's decide_tick (LLM) will handle novel observation decisions.
return ReactionDecision(should_replan=False, reason="mid-action, continuing current action")
# Standalone sanity check (doesn't hit the network)
if __name__ == "__main__":
action = CurrentAction(description="sleeping", start_tick=0, end_tick=60)
r1 = decide_reaction("a", {}, None, [], [], tick=0)
assert r1.should_replan is True
r2 = decide_reaction("a", {}, action, [], [], tick=61)
assert r2.should_replan is True
r3 = decide_reaction("a", {}, action, [], [], tick=30)
assert r3.should_replan is False
print("react.py cheap-path sanity checks passed (LLM branch not exercised here).")