(event: MessageEvent)
| 197 | console.debug('[useTerminalStream] SSE connected successfully', { runId, nodeId, stream }); |
| 198 | |
| 199 | const handleTerminal = (event: MessageEvent) => { |
| 200 | try { |
| 201 | const payload = JSON.parse(event.data) as Awaited< |
| 202 | ReturnType<typeof api.executions.getTerminalChunks> |
| 203 | >; |
| 204 | console.debug('[useTerminalStream] terminal SSE event received', { |
| 205 | totalChunks: payload.chunks?.length, |
| 206 | nodeId, |
| 207 | stream, |
| 208 | cursor: payload.cursor, |
| 209 | }); |
| 210 | if (!payload.chunks?.length) { |
| 211 | console.debug('[useTerminalStream] no chunks in payload'); |
| 212 | return; |
| 213 | } |
| 214 | const relevant = payload.chunks.filter( |
| 215 | (chunk) => chunk.nodeRef === nodeId && chunk.stream === stream, |
| 216 | ); |
| 217 | console.debug('[useTerminalStream] filtered chunks', { |
| 218 | relevantCount: relevant.length, |
| 219 | totalCount: payload.chunks.length, |
| 220 | nodeRefs: payload.chunks.map((c) => c.nodeRef), |
| 221 | streams: payload.chunks.map((c) => c.stream), |
| 222 | }); |
| 223 | if (relevant.length === 0) { |
| 224 | console.debug('[useTerminalStream] no relevant chunks for nodeId/stream'); |
| 225 | return; |
| 226 | } |
| 227 | cursorRef.current = payload.cursor ?? cursorRef.current; |
| 228 | setChunks((prev) => { |
| 229 | const merged = mergeTerminalChunks(prev, relevant); |
| 230 | console.debug('[useTerminalStream] updating chunks', { |
| 231 | prevCount: prev.length, |
| 232 | newCount: relevant.length, |
| 233 | mergedCount: merged.length, |
| 234 | lastChunkIndex: merged[merged.length - 1]?.chunkIndex, |
| 235 | }); |
| 236 | return merged; |
| 237 | }); |
| 238 | setMode('live'); |
| 239 | } catch (err) { |
| 240 | console.error('[useTerminalStream] failed to parse terminal SSE', err); |
| 241 | } |
| 242 | }; |
| 243 | |
| 244 | const handleComplete = () => { |
| 245 | setIsStreaming(false); |
nothing calls this directly
no test coverage detected