/** * ProcessLinker service - Links subagent processes to AI chunks. * * Uses a two-tier linking strategy: * 1. Primary: parentTaskId matching - Links subagents to chunks containing the Task tool call * that spawned them. This is reliable even when the response is still in progress. * 2. Fallback: Timing-based - For orphaned subagents without parentTaskId, falls back to * checking if the subagent's startTime falls within the chunk's time range. */ import { type EnhancedAIChunk, type Process } from '@main/types'; /** * Link processes to a single AI chunk. * * Uses a two-tier linking strategy: * 1. Primary: parentTaskId matching - Links subagents to chunks containing the Task tool call * that spawned them. This is reliable even when the response is still in progress. * 2. Fallback: Timing-based - For orphaned subagents without parentTaskId, falls back to * checking if the subagent's startTime falls within the chunk's time range. */ export function linkProcessesToAIChunk(chunk: EnhancedAIChunk, subagents: Process[]): void { // Build set of Task tool IDs from this chunk's responses const chunkTaskIds = new Set(); for (const response of chunk.responses) { for (const toolCall of response.toolCalls) { if (toolCall.isTask) { chunkTaskIds.add(toolCall.id); } } } // Track which subagents have been linked const linkedSubagentIds = new Set(); // Primary linking: Match subagents to Task calls by parentTaskId for (const subagent of subagents) { if (subagent.parentTaskId && chunkTaskIds.has(subagent.parentTaskId)) { chunk.processes.push(subagent); linkedSubagentIds.add(subagent.id); } } // Fallback linking: For orphaned subagents, use timing-based matching // This handles edge cases where parentTaskId might not be set for (const subagent of subagents) { if (linkedSubagentIds.has(subagent.id)) { continue; // Already linked via parentTaskId } // Only use timing fallback if subagent has no parentTaskId // (If it has parentTaskId but didn't match, it belongs to a different chunk) if (!subagent.parentTaskId) { if (subagent.startTime >= chunk.startTime && subagent.startTime <= chunk.endTime) { chunk.processes.push(subagent); } } } chunk.processes.sort((a, b) => a.startTime.getTime() - b.startTime.getTime()); }