fix(openai): merge ThinkingBlock and tool reasoning details instead of overwriting - #2914
fix(openai): merge ThinkingBlock and tool reasoning details instead of overwriting#2914chaucerj wants to merge 12 commits into
Conversation
…-trips Gemini 3 requires thought signatures to be replayed with function calls. They are stored as byte[] in ToolUseBlock metadata, but a JSON persistence round-trip (session save/load) restores them as a Base64 String, so the converters' instanceof checks silently dropped them and the next request failed with 400 INVALID_ARGUMENT from the server. - GeminiMessageConverter: decode Base64 String signatures back to byte[] - OpenAIMessageConverter: normalize byte[] signatures to Base64 String (covers the in-memory cross-provider path) and restore reasoning detail metadata that comes back from persistence as a LinkedHashMap Verified against the live gemini-3-flash-preview API: replaying a function call without its signature returns 400 "Function call is missing a thought_signature in functionCall parts"; replaying it with the signature returns 200. Co-Authored-By: Claude Code <noreply@anthropic.com>
HarnessAgentDynamicHookBuilderTest failed once in agentscope-harness (own surefire JVM, unrelated to this change; another PR hit the same 1-error-in-844 flake on a different harness test the same day). No code change. Co-Authored-By: Claude Code <noreply@anthropic.com>
Adds a no-metadata ToolUseBlock case to both converter test classes, exercising the null-metadata guards left as partial branches by the previous coverage pass. Patch coverage is now 100% of changed lines. Co-Authored-By: Claude Code <noreply@anthropic.com>
ToolUseBlock normalizes null metadata to an empty map, so the null-side of the metadata guards is unreachable and cannot be covered. The actual partial branches were: - GeminiMessageConverter: a signature value that is neither byte[] nor String (now covered by a non-string signature test) - OpenAIMessageConverter: a ThinkingBlock details list whose entries cannot be restored (now covered), and a dead !candidate.isEmpty() check in the fallback-signature scan - toSignatureString never returns an empty string, so the check is dropped. Co-Authored-By: Claude Code <noreply@anthropic.com>
…f overwriting convertAssistantMessage called builder.reasoningDetails(...) twice — once for details restored from ThinkingBlock metadata and once for tool-call details. The second call silently replaced the first, so assistant messages carrying both a thinking block and tool calls dropped the thinking-side reasoning details (issue agentscope-ai#2913). Collect both sources into one list and set reasoningDetails once, after the tool-call section. Co-Authored-By: Claude Code <noreply@anthropic.com>
The ubuntu build failed in agentscope-harness JsonSessionDefaultLocationTest @tempdir cleanup (DirectoryNotEmptyException during teardown, assertions all passed) - unrelated to this change; re-triggering. Co-Authored-By: Claude Code <noreply@anthropic.com>
|
The two red ubuntu runs are both unrelated to this change:
This branch only touches |
…-persistence Sync with latest main (f96cdc7), including the openai-java 4.52.0 bump. No code changes; merge was conflict-free. Co-Authored-By: Claude Code <noreply@anthropic.com>
…easoning-details-overwrite Pull in the main sync merge; keeps this branch stacked on the updated fix/thought-signature-persistence. No code changes. Co-Authored-By: Claude Code <noreply@anthropic.com>
…-persistence Sync with main (b436110): picks up the rag-simple apiKey ambiguity fix (agentscope-ai#2912) so CI can go green again. No code changes of our own. Co-Authored-By: Claude Code <noreply@anthropic.com>
…easoning-details-overwrite Pull the main sync (b436110, includes rag-simple CI fix agentscope-ai#2912) into this stack. No code changes of our own. Co-Authored-By: Claude Code <noreply@anthropic.com>
HarnessAgentDynamicHookBuilderTest failed on windows-latest with a suppressed DirectoryNotEmptyException in @tempdir teardown (assertions passed). Unrelated to this change; re-running. Co-Authored-By: Claude Code <noreply@anthropic.com>
Third occurrence of the same harness flake class: async session writer leaves subdirs behind and @tempdir teardown throws (suppressed DirectoryNotEmptyException; assertions pass, 0 failures). Not related to this change. Co-Authored-By: Claude Code <noreply@anthropic.com>
|
The latest failures on this PR are all the same flaky-test class in the harness module, unrelated to this change (which only touches
In every case: assertions pass ( Evidence it's not this PR: the sibling PR #2910 (identical tree except this PR's 17-line converter change, which no harness test routes through) passed the same suite green on both OSes in run 33356276237. I lack admin rights to re-run failed jobs, so I re-triggered via empty commits twice; the flake hit a third time. Maintainers with admin should be able to get it green with a simple "Re-run failed jobs". Longer term it may be worth making the session writer await termination before test teardown. |
oss-maintainer
left a comment
There was a problem hiding this comment.
LGTM. fix(openai): merge ThinkingBlock and tool reasoning details instead of overwriting — change looks correct and clean.
Automated review by github-manager-bot
Fixes #2913
What
OpenAIMessageConverter.convertAssistantMessagecalledbuilder.reasoningDetails(...)twice: once for details restored from theThinkingBlockmetadata, once for details collected from tool use metadata. The second call silently overwrote the first, so an assistant message containing both a thinking block and tool calls lost the thinking-side reasoning details.Change
Collect both sources into a single list and set
reasoningDetailsexactly once, after the tool-call section:List<OpenAIReasoningDetail> reasoningDetailsabove the ThinkingBlock handlingbuilder.reasoningDetails(reasoningDetails)after tool calls, covering the no-tool-calls case tooTest
testThinkingDetailsMergedWithToolDetailsasserts a message with both aThinkingBlock(METADATA_REASONING_DETAILS) and a tool call (reasoningDetailmetadata) yields both details ([thinking-detail, tool-detail]); before the fix it returned only[tool-detail]. Existing thinking-only / tool-only tests unchanged and green.Note
Stacked on #2910 (same file, adjacent code). Merge #2910 first; this PR's own commit is the last one.
🤖 Generated with Claude Code