source dump of claude code
at main 99 lines 2.8 kB view raw
1/** 2 * Deterministic Agent ID System 3 * 4 * This module provides helper functions for formatting and parsing deterministic 5 * agent IDs used in the swarm/teammate system. 6 * 7 * ## ID Formats 8 * 9 * **Agent IDs**: `agentName@teamName` 10 * - Example: `team-lead@my-project`, `researcher@my-project` 11 * - The @ symbol acts as a separator between agent name and team name 12 * 13 * **Request IDs**: `{requestType}-{timestamp}@{agentId}` 14 * - Example: `shutdown-1702500000000@researcher@my-project` 15 * - Used for shutdown requests, plan approvals, etc. 16 * 17 * ## Why Deterministic IDs? 18 * 19 * Deterministic IDs provide several benefits: 20 * 21 * 1. **Reproducibility**: The same agent spawned with the same name in the same team 22 * always gets the same ID, enabling reconnection after crashes/restarts. 23 * 24 * 2. **Human-readable**: IDs are meaningful and debuggable (e.g., `tester@my-project`). 25 * 26 * 3. **Predictable**: Team leads can compute a teammate's ID without looking it up, 27 * simplifying message routing and task assignment. 28 * 29 * ## Constraints 30 * 31 * - Agent names must NOT contain `@` (it's used as the separator) 32 * - Use `sanitizeAgentName()` from TeammateTool.ts to strip @ from names 33 */ 34 35/** 36 * Formats an agent ID in the format `agentName@teamName`. 37 */ 38export function formatAgentId(agentName: string, teamName: string): string { 39 return `${agentName}@${teamName}` 40} 41 42/** 43 * Parses an agent ID into its components. 44 * Returns null if the ID doesn't contain the @ separator. 45 */ 46export function parseAgentId( 47 agentId: string, 48): { agentName: string; teamName: string } | null { 49 const atIndex = agentId.indexOf('@') 50 if (atIndex === -1) { 51 return null 52 } 53 return { 54 agentName: agentId.slice(0, atIndex), 55 teamName: agentId.slice(atIndex + 1), 56 } 57} 58 59/** 60 * Formats a request ID in the format `{requestType}-{timestamp}@{agentId}`. 61 */ 62export function generateRequestId( 63 requestType: string, 64 agentId: string, 65): string { 66 const timestamp = Date.now() 67 return `${requestType}-${timestamp}@${agentId}` 68} 69 70/** 71 * Parses a request ID into its components. 72 * Returns null if the request ID doesn't match the expected format. 73 */ 74export function parseRequestId( 75 requestId: string, 76): { requestType: string; timestamp: number; agentId: string } | null { 77 const atIndex = requestId.indexOf('@') 78 if (atIndex === -1) { 79 return null 80 } 81 82 const prefix = requestId.slice(0, atIndex) 83 const agentId = requestId.slice(atIndex + 1) 84 85 const lastDashIndex = prefix.lastIndexOf('-') 86 if (lastDashIndex === -1) { 87 return null 88 } 89 90 const requestType = prefix.slice(0, lastDashIndex) 91 const timestampStr = prefix.slice(lastDashIndex + 1) 92 const timestamp = parseInt(timestampStr, 10) 93 94 if (isNaN(timestamp)) { 95 return null 96 } 97 98 return { requestType, timestamp, agentId } 99}