(params: {
runState: RunState
actualCredits: number | undefined
agentMode: AgentMode
timerController: SendMessageTimerController
updater: BatchedMessageUpdater
aiMessageId: string
wasAbortedByUser: boolean
setStreamStatus: (status: StreamStatus) => void
setCanProcessQueue: (can: boolean) => void
updateChainInProgress: (value: boolean) => void
setHasReceivedPlanResponse: (value: boolean) => void
resumeQueue?: () => void
isProcessingQueueRef?: MutableRefObject<boolean>
isQueuePausedRef?: MutableRefObject<boolean>
})
| 330 | } |
| 331 | |
| 332 | export const handleRunCompletion = (params: { |
| 333 | runState: RunState |
| 334 | actualCredits: number | undefined |
| 335 | agentMode: AgentMode |
| 336 | timerController: SendMessageTimerController |
| 337 | updater: BatchedMessageUpdater |
| 338 | aiMessageId: string |
| 339 | wasAbortedByUser: boolean |
| 340 | setStreamStatus: (status: StreamStatus) => void |
| 341 | setCanProcessQueue: (can: boolean) => void |
| 342 | updateChainInProgress: (value: boolean) => void |
| 343 | setHasReceivedPlanResponse: (value: boolean) => void |
| 344 | resumeQueue?: () => void |
| 345 | isProcessingQueueRef?: MutableRefObject<boolean> |
| 346 | isQueuePausedRef?: MutableRefObject<boolean> |
| 347 | }) => { |
| 348 | const { |
| 349 | runState, |
| 350 | actualCredits, |
| 351 | agentMode, |
| 352 | timerController, |
| 353 | updater, |
| 354 | wasAbortedByUser, |
| 355 | setStreamStatus, |
| 356 | setCanProcessQueue, |
| 357 | updateChainInProgress, |
| 358 | setHasReceivedPlanResponse, |
| 359 | resumeQueue, |
| 360 | isProcessingQueueRef, |
| 361 | isQueuePausedRef, |
| 362 | } = params |
| 363 | |
| 364 | // If user aborted, the abort handler already handled UI updates and released the |
| 365 | // chain lock. Don't finalize queue state again to avoid interfering with any new |
| 366 | // run that may have started after the abort. Uses per-run abort signal (not shared |
| 367 | // streamRefs) so a newer run's reset() can't clear this flag. |
| 368 | if (wasAbortedByUser) { |
| 369 | return |
| 370 | } |
| 371 | |
| 372 | const output = runState.output |
| 373 | const finalizeAfterError = () => { |
| 374 | finalizeQueueState({ |
| 375 | setStreamStatus, |
| 376 | setCanProcessQueue, |
| 377 | updateChainInProgress, |
| 378 | isProcessingQueueRef, |
| 379 | isQueuePausedRef, |
| 380 | }) |
| 381 | timerController.stop('error') |
| 382 | } |
| 383 | |
| 384 | if (!output) { |
| 385 | if (!wasAbortedByUser) { |
| 386 | updater.setError(DEFAULT_RUN_OUTPUT_ERROR_MESSAGE) |
| 387 | finalizeAfterError() |
| 388 | } |
| 389 | return |
no test coverage detected