"""Agent command transport coordination and result validation.""" import re from app.agent_commands.exceptions import ( AgentCommandConflict, AgentCommandNotFound, ) from app.agent_commands.models import ( AgentCommand, AgentCommandResultRequest, ) from app.agent_commands.repository import AgentCommandRepository from app.agent_commands.policy import rejection_reason class AgentCommandService: def __init__(self, repository: AgentCommandRepository): self.repository = repository def claim(self, agent_id: str) -> list[AgentCommand]: return [ AgentCommand.model_validate(row) for row in self.repository.claim_pending(agent_id) if rejection_reason(row["command_type"]) is None ] @staticmethod def _legacy_error(value: str | None) -> str | None: if not value: return None sanitized = re.sub(r"\b(?:\d{1,3}\.){3}\d{1,3}\b", "[address]", value) return sanitized[:255] def submit_result( self, agent_id: str, request: AgentCommandResultRequest ) -> None: command = self.repository.get_command(request.command_id) if not command: raise AgentCommandNotFound("Agent command not found") if command["agent_id"] != agent_id: raise AgentCommandConflict("Agent command belongs to another Agent") reason = rejection_reason(command["command_type"]) if reason: # Repository repeats this check under a row lock and records the # cancellation atomically; never accept an old physical result. self.repository.finish_command( request.command_id, agent_id, "cancelled", {}, reason ) raise AgentCommandConflict(reason) if command["command_status"] != "claimed": raise AgentCommandConflict( f"Agent command is {command['command_status']}, not claimed" ) result_payload = request.result_payload error_message = self._legacy_error(request.error_message) self.repository.finish_command( request.command_id, agent_id, request.status, result_payload, error_message, )