/** * Deterministic Agent ID System * * This module provides helper functions for formatting and parsing deterministic * agent IDs used in the swarm/teammate system. * * ## ID Formats * * **Agent IDs**: `agentName@teamName` * - Example: `team-lead@my-project`, `researcher@my-project` * - The @ symbol acts as a separator between agent name and team name * * **Request IDs**: `{requestType}-{timestamp}@{agentId}` * - Example: `shutdown-1702500000000@researcher@my-project` * - Used for shutdown requests, plan approvals, etc. * * ## Why Deterministic IDs? * * Deterministic IDs provide several benefits: * * 1. **Reproducibility**: The same agent spawned with the same name in the same team * always gets the same ID, enabling reconnection after crashes/restarts. * * 2. **Human-readable**: IDs are meaningful and debuggable (e.g., `tester@my-project`). * * 3. **Predictable**: Team leads can compute a teammate's ID without looking it up, * simplifying message routing and task assignment. * * ## Constraints * * - Agent names must NOT contain `@` (it's used as the separator) * - Use `sanitizeAgentName()` from TeammateTool.ts to strip @ from names */ /** * Formats an agent ID in the format `agentName@teamName`. */ export function formatAgentId(agentName: string, teamName: string): string { return `${agentName}@${teamName}` } /** * Parses an agent ID into its components. * Returns null if the ID doesn't contain the @ separator. */ export function parseAgentId( agentId: string, ): { agentName: string; teamName: string } | null { const atIndex = agentId.indexOf('@') if (atIndex === -1) { return null } return { agentName: agentId.slice(0, atIndex), teamName: agentId.slice(atIndex + 1), } } /** * Formats a request ID in the format `{requestType}-{timestamp}@{agentId}`. */ export function generateRequestId( requestType: string, agentId: string, ): string { const timestamp = Date.now() return `${requestType}-${timestamp}@${agentId}` } /** * Parses a request ID into its components. * Returns null if the request ID doesn't match the expected format. */ export function parseRequestId( requestId: string, ): { requestType: string; timestamp: number; agentId: string } | null { const atIndex = requestId.indexOf('@') if (atIndex === -1) { return null } const prefix = requestId.slice(0, atIndex) const agentId = requestId.slice(atIndex + 1) const lastDashIndex = prefix.lastIndexOf('-') if (lastDashIndex === -1) { return null } const requestType = prefix.slice(0, lastDashIndex) const timestampStr = prefix.slice(lastDashIndex + 1) const timestamp = parseInt(timestampStr, 10) if (isNaN(timestamp)) { return null } return { requestType, timestamp, agentId } }