import type { Dispatch, MutableRefObject, SetStateAction } from "react"; import type { ClarificationPayload, ModelSwitchInfo, StreamPhase, ThreadIdMap, } from "@/roundtable-planning/api/multi-agent"; import type { Step2ExecutionRefs } from "@/roundtable-planning/hooks/useStep2ExecutionRefs"; import type { ParallelSeatView } from "@/roundtable-planning/hooks/step2-types"; import type { ChainNodeState } from "@/roundtable-planning/lib/job-types"; type EngineExecutionRefName = | "isOrchestratingRef" | "orchestrationCancelRef" | "orchestrationEpochRef" | "selectedAgentsRef" | "agentNameToRoleRef" | "activeAbortersRef" | "pendingInjectFilesRef" | "selectedModelRef" | "agentConfigsRef" | "gatheredDeliveriesRef" | "seatModesRef" | "selectedModeRef" | "seatSkillDirectivesRef" | "orchestrationPlanRef" | "dagExecModeRef" | "dagPlanExecutedRef"; export interface Step2EngineRuntimePort { refs: Pick; resolveSeatThreadId: (ids: ThreadIdMap, agentName: string) => string | undefined; } export interface Step2EngineDialoguePort { appendStreamingDialogue: (card: { sender: string; avatarType: string; initialContent?: string; confidence?: string; agentThreadId?: string; }) => number; appendToDialogue: (id: number, deltaText: string) => void; setDialogueContent: (id: number, fullText: string) => void; appendStepIfNew: ( bubbleId: number, label: string, key: string, args?: Record, ) => void; setDialogueConfidence: (id: number, confidence: string) => void; phaseLabel: ( phase: StreamPhase, agentType: "leader" | "special", toolName?: string, ) => string; finalizeDialogue: (id: number, finalContent: string, confidence?: string) => void; makeModelSwitchHandler: ( bubbleId: number, isParallel: boolean, ) => (info: ModelSwitchInfo) => void; } export interface Step2EngineSpeakerPort { highlightSpeaker: (speakerId: number | null) => void; markSpeakerStreaming: (speakerId: number) => void; markSpeakerIdle: (speakerId: number) => void; markParallelSpeakers: (speakerIds: number[]) => void; clearAllStreamingSpeakers: () => void; } export interface Step2EngineParallelPort { recommendParallelRef: MutableRefObject; parallelStreamRef: MutableRefObject< Map >; ingestParallelDelta: (bubbleId: number, deltaText: string) => void; resetParallelStreams: () => void; setParallelBatch: Dispatch>; setSelectedParallelSeats: Dispatch>; } export interface Step2EngineDagPort { setDagNodeStates: Dispatch< SetStateAction> >; } export interface Step2EngineArtifactPort { handleArtifactToolPhase: ( phase: StreamPhase, toolName: string | undefined, args: Record | undefined, seatThreadId: string | undefined, ) => void; handleUpstreamFrame: (frame: unknown, seatThreadId: string | undefined) => void; ingestSubagentTaskFrame: (frame: unknown, bubbleId: number) => void; } export interface Step2EngineControlPort { setIsOrchestrating: Dispatch>; setPendingClarification: Dispatch>; setClarificationDraft: Dispatch>; setLastLeaderContent: Dispatch>; setConsensusPercentage: Dispatch>; setHasConsensus: Dispatch>; triggerToast: (message: string) => void; } /** * Shared boundary for Step 2 orchestration engines. * Engines depend on grouped capabilities instead of closing over the whole page hook. */ export interface Step2EngineContext { runtime: Step2EngineRuntimePort; dialogue: Step2EngineDialoguePort; speakers: Step2EngineSpeakerPort; parallel: Step2EngineParallelPort; dag: Step2EngineDagPort; artifacts: Step2EngineArtifactPort; control: Step2EngineControlPort; }