#[cfg(test)]
mod agent_navigation_tests;
use std::collections::{HashMap, HashSet};
pub(crate) use tau_proto::AgentNavigationMode as AgentNavigationState;
pub(crate) fn is_navigation_eligible(
mode: tau_proto::AgentNavigationMode,
runtime_state: tau_proto::AgentRuntimeState,
) -> bool {
match mode {
tau_proto::AgentNavigationMode::Active => true,
tau_proto::AgentNavigationMode::ActiveAuto => {
runtime_state == tau_proto::AgentRuntimeState::Running
}
tau_proto::AgentNavigationMode::Suspended => false,
}
}
#[derive(Clone, Debug, Default)]
pub(crate) struct AgentNavigation {
live_agents: HashSet<tau_proto::AgentId>,
modes: HashMap<tau_proto::AgentId, tau_proto::AgentNavigationMode>,
runtime_states: HashMap<tau_proto::AgentId, tau_proto::AgentRuntimeState>,
}
impl AgentNavigation {
pub(crate) fn mark_live(&mut self, agent_id: tau_proto::AgentId) {
self.live_agents.insert(agent_id);
}
pub(crate) fn apply_stats(
&mut self,
agent_id: &tau_proto::AgentId,
navigation_mode: tau_proto::AgentNavigationMode,
runtime_state: tau_proto::AgentRuntimeState,
) {
if self.live_agents.contains(agent_id) {
self.modes.insert(agent_id.clone(), navigation_mode);
self.runtime_states.insert(agent_id.clone(), runtime_state);
}
}
pub(crate) fn unload(&mut self, agent_id: &tau_proto::AgentId) {
self.live_agents.remove(agent_id);
self.modes.remove(agent_id);
self.runtime_states.remove(agent_id);
}
pub(crate) fn mode(&self, agent_id: &tau_proto::AgentId) -> tau_proto::AgentNavigationMode {
self.modes.get(agent_id).copied().unwrap_or_default()
}
pub(crate) fn is_active(&self, agent_id: &tau_proto::AgentId) -> bool {
self.live_agents.contains(agent_id)
&& self.modes.get(agent_id).is_some_and(|mode| {
self.runtime_states
.get(agent_id)
.is_some_and(|runtime| is_navigation_eligible(*mode, *runtime))
})
}
pub(crate) fn active_agents(&self) -> HashSet<tau_proto::AgentId> {
self.live_agents
.iter()
.filter(|agent_id| self.is_active(agent_id))
.cloned()
.collect()
}
pub(crate) fn active_count(&self) -> usize {
self.live_agents
.iter()
.filter(|agent_id| self.is_active(agent_id))
.count()
}
pub(crate) fn is_live(&self, agent_id: &tau_proto::AgentId) -> bool {
self.live_agents.contains(agent_id)
}
pub(crate) fn live_agents(&self) -> HashSet<tau_proto::AgentId> {
self.live_agents.clone()
}
}