valhalla / backend /src /core /agent_registry.py
Dontcryx_07
final
d660fa9
Raw History Blame Contribute Delete
3.13 kB
"""agent_registry — single source of truth for every agent's runtime state.
Holds one AgentRuntimeState per agent (persona, position, day plan,
wellbeing, conversation state, replan budget) and the AgentRegistry that
the engine, Actions, conversations, and memory all read and write.
Architecture: central state container consumed by every subsystem; the
engine syncs it to WorldState each tick.
Design: consolidates position into one registry to eliminate the
dual-source position drift of earlier versions.
"""
from __future__ import annotations
from typing import Any, Dict, List, Optional
from pydantic import BaseModel
from src.core.world_state import Position
class AgentRuntimeState(BaseModel):
"""Everything the engine needs to know about one agent at runtime."""
agent_id: str
persona: Dict[str, Any]
persona_name: str # display name, e.g. "Parv Singla"
manager: Optional[Any] = None # AgentActionManager instance (set after init)
position: Position
current_action: Optional[Dict[str, Any]] = None # serialised ActionState or None
paused: bool = False # True while in conversation or other blocking state
day_plan: list = [] # current day plan actions
day_archived: bool = False # True when the current sim day has been archived
conversation_start_tick: int = 0 # tick when the active conversation started (0 = not in one)
conversation_count: int = 0 # how many conversations today
replan_count: int = 0 # mid-day full replans today (budget cap)
last_conversation_partner: Optional[str] = None # agent_id of most recent chat partner
active_conversation: Optional[dict] = None # {"partner_name": str, "partner_id": str, "messages": list[dict]}
emotion_state: float = 0.5 # [0, 1], starts neutral
emotion_baseline: float = 0.5 # personality-derived normal mood; used for gentle recovery
energy_level: float = 1.0 # [0, 1], starts full
color: str = "#888888" # frontend color (set by server on init)
class AgentRegistry:
"""Global runtime registry for all agents."""
def __init__(self) -> None:
self._agents: Dict[str, AgentRuntimeState] = {}
def register(self, state: AgentRuntimeState) -> None:
self._agents[state.agent_id] = state
def remove(self, agent_id: str) -> AgentRuntimeState:
"""Remove and return a runtime record for a roster edit while stopped."""
state = self._agents.pop(agent_id, None)
if state is None:
raise KeyError(f"Unknown agent '{agent_id}'")
return state
def get(self, agent_id: str) -> AgentRuntimeState:
state = self._agents.get(agent_id)
if state is None:
raise KeyError(f"Unknown agent '{agent_id}'")
return state
def all_ids(self) -> list[str]:
return list(self._agents.keys())
def all_states(self) -> list[AgentRuntimeState]:
return list(self._agents.values())
def __contains__(self, agent_id: str) -> bool:
return agent_id in self._agents
def __len__(self) -> int:
return len(self._agents)