trimReplayDanglingAssistantToolCalls only collected tool results that
immediately followed the assistant tool-call message. Models such as
gpt-5.3-codex-spark may emit the function_call item before the
explanation text within one response, so history replay order becomes
assistant[tool_call] -> assistant[text] -> tool[result]. The call was
misjudged as dangling and stripped while the tool result survived,
producing a function_call_output without a matching function_call that
the Responses API rejects with 400.
- widen the response collection window to skip interleaved plain
assistant text messages, and drop orphan tool results in the same pass
- synthesize a placeholder function_call (or drop the output when the
tool name is unknown) in normalizeOpenAIResponsesInput so conversations
already persisted with corrupted history can resume