Raised by Codex on LibreChat-AI#16290: LibreChat-AI#16290 (comment)
useStepHandler buffers message, reasoning, run-step and summarize deltas that arrive before their ON_RUN_STEP, but not ON_RUN_STEP_COMPLETED. A completion for a step the handler has not seen yet logs "No run step or runId found for completed tool call event" and is dropped, so that call's output never reaches the live card (the final message still carries it).
This is the behavior on canary today and LibreChat-AI#16290 keeps it unchanged. The reducer itself (applyToolCallCompleted) already writes a completion into an empty slot correctly, so buffering the completion in the handler alongside the other deltas would be enough.
To settle first: whether any transport can deliver a completion ahead of its run step. If one can, buffer ON_RUN_STEP_COMPLETED in pendingDeltaBuffer and cover the ordering through the hook in useStepHandler.spec.ts.
Raised by Codex on LibreChat-AI#16290: LibreChat-AI#16290 (comment)
useStepHandlerbuffers message, reasoning, run-step and summarize deltas that arrive before theirON_RUN_STEP, but notON_RUN_STEP_COMPLETED. A completion for a step the handler has not seen yet logs "No run step or runId found for completed tool call event" and is dropped, so that call's output never reaches the live card (the final message still carries it).This is the behavior on canary today and LibreChat-AI#16290 keeps it unchanged. The reducer itself (
applyToolCallCompleted) already writes a completion into an empty slot correctly, so buffering the completion in the handler alongside the other deltas would be enough.To settle first: whether any transport can deliver a completion ahead of its run step. If one can, buffer
ON_RUN_STEP_COMPLETEDinpendingDeltaBufferand cover the ordering through the hook inuseStepHandler.spec.ts.