/** * Swarm Reconnection Module * * Handles initialization of swarm context for teammates. * - Fresh spawns: Initialize from CLI args (set in main.tsx via dynamicTeamContext) * - Resumed sessions: Initialize from teamName/agentName stored in the transcript */ import type { AppState } from '../../state/AppState.js' import { logForDebugging } from '../debug.js' import { logError } from '../log.js' import { getDynamicTeamContext } from '../teammate.js' import { getTeamFilePath, readTeamFile } from './teamHelpers.js' /** * Computes the initial teamContext for AppState. * * This is called synchronously in main.tsx to compute the teamContext * BEFORE the first render, eliminating the need for useEffect workarounds. * * @returns The teamContext object to include in initialState, or undefined if not a teammate */ export function computeInitialTeamContext(): | AppState['teamContext'] | undefined { // dynamicTeamContext is set in main.tsx from CLI args const context = getDynamicTeamContext() if (!context?.teamName || !context?.agentName) { logForDebugging( '[Reconnection] computeInitialTeamContext: No teammate context set (not a teammate)', ) return undefined } const { teamName, agentId, agentName } = context // Read team file to get lead agent ID const teamFile = readTeamFile(teamName) if (!teamFile) { logError( new Error( `[computeInitialTeamContext] Could not read team file for ${teamName}`, ), ) return undefined } const teamFilePath = getTeamFilePath(teamName) const isLeader = !agentId logForDebugging( `[Reconnection] Computed initial team context for ${isLeader ? 'leader' : `teammate ${agentName}`} in team ${teamName}`, ) return { teamName, teamFilePath, leadAgentId: teamFile.leadAgentId, selfAgentId: agentId, selfAgentName: agentName, isLeader, teammates: {}, } } /** * Initialize teammate context from a resumed session. * * This is called when resuming a session that has teamName/agentName stored * in the transcript. It sets up teamContext in AppState so that heartbeat * and other swarm features work correctly. */ export function initializeTeammateContextFromSession( setAppState: (updater: (prev: AppState) => AppState) => void, teamName: string, agentName: string, ): void { // Read team file to get lead agent ID const teamFile = readTeamFile(teamName) if (!teamFile) { logError( new Error( `[initializeTeammateContextFromSession] Could not read team file for ${teamName} (agent: ${agentName})`, ), ) return } // Find the member in the team file to get their agentId const member = teamFile.members.find(m => m.name === agentName) if (!member) { logForDebugging( `[Reconnection] Member ${agentName} not found in team ${teamName} - may have been removed`, ) } const agentId = member?.agentId const teamFilePath = getTeamFilePath(teamName) // Set teamContext in AppState setAppState(prev => ({ ...prev, teamContext: { teamName, teamFilePath, leadAgentId: teamFile.leadAgentId, selfAgentId: agentId, selfAgentName: agentName, isLeader: false, teammates: {}, }, })) logForDebugging( `[Reconnection] Initialized agent context from session for ${agentName} in team ${teamName}`, ) }