Fix OpenAI streaming tool calls being split into two entries - #10352
Fix OpenAI streaming tool calls being split into two entries#10352dpage wants to merge 1 commit into
Conversation
_read_responses_stream() keyed its tool_calls_data dict by call_id, but response.function_call_arguments.delta events carry item_id, not call_id, so the delta accumulation always missed the entry seeded by the preceding response.output_item.added event and created a second, empty-name entry instead. Correlate on item_id, keeping the real call_id alongside it so the emitted ToolCall.id is still correct. Closes pgadmin-org#10348
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: Path: .coderabbit.yaml Review profile: CHILL Plan: Pro Plus Run ID: 📒 Files selected for processing (2)
Included review availability: Your plan provides up to 8 included reviews per hour; 6 remain after this review. WalkthroughThe Responses API stream parser now correlates function-call argument deltas by ChangesResponses tool-call correlation
Estimated code review effort: 2 (Simple) | ~10 minutes Merge Risk: ⚪ Minimal · up to This localized fix corrects streamed tool-call assembly and adds regression coverage for single and parallel calls; no actionable merge-blocking risk remains beyond normal checks and review. 🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
Full details: Linked Issues checkExplanation The changes satisfy issue
✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
Summary
OpenAIClient._read_responses_stream()accumulated Responses API (/v1/responses) streamed function-call arguments in atool_calls_datadict keyed bycall_id. But per OpenAI's Responses API streaming event reference,response.function_call_arguments.deltaevents carryitem_id,output_index,deltaandsequence_number— there is nocall_idon that event.data.get('call_id', '')always evaluated to'', so every delta missed the entry seeded by the precedingresponse.output_item.addedevent and accumulated into a second, empty-name entry instead — one tool call came back as two separateToolCalls (name with no arguments, and arguments with no name).item_id(matchingitem.idfromresponse.output_item.added) instead, while still carrying the realcall_idthrough so the emittedToolCall.id(used later to reference the call, e.g.'call_id': tc.idwhen replaying tool calls back to the API) is correct.Test plan
web/pgadmin/llm/tests/test_openai_stream.pycovering a single streamed tool call and two parallel tool calls, using fake Responses API SSE events.call_id-keyed logic and pass with the fix.pycodestyleclean on the changed/added files.Closes #10348
Summary by CodeRabbit
Bug Fixes
Tests