Skip to content
Open
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions src/openai/lib/streaming/responses/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
ResponseTextDoneEvent as ResponseTextDoneEvent,
ResponseTextDeltaEvent as ResponseTextDeltaEvent,
ResponseFunctionCallArgumentsDeltaEvent as ResponseFunctionCallArgumentsDeltaEvent,
ResponseFunctionCallArgumentsDoneEvent as ResponseFunctionCallArgumentsDoneEvent,
)
from ._responses import (
ResponseStream as ResponseStream,
Expand Down
27 changes: 26 additions & 1 deletion src/openai/lib/streaming/responses/_responses.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,13 +12,14 @@
ResponseCompletedEvent,
ResponseTextDeltaEvent,
ResponseFunctionCallArgumentsDeltaEvent,
ResponseFunctionCallArgumentsDoneEvent,
)
from ...._types import Omit, omit
from ...._utils import is_given, consume_sync_iterator, consume_async_iterator
from ...._models import build, construct_type_unchecked
from ...._streaming import Stream, AsyncStream
from ....types.responses import ParsedResponse, ResponseStreamEvent as RawResponseStreamEvent
from ..._parsing._responses import TextFormatT, parse_text, parse_response
from ..._parsing._responses import TextFormatT, parse_text, parse_response, parse_function_tool_arguments
from ....types.responses.tool_param import ToolParam
from ....types.responses.parsed_response import (
ParsedContent,
Expand Down Expand Up @@ -305,6 +306,30 @@ def handle_event(self, event: RawResponseStreamEvent) -> List[ResponseStreamEven
)
)

elif event.type == "response.function_call_arguments.done":
output = snapshot.output[event.output_index]
assert output.type == "function_call"

# Parse arguments using input_tools
parsed_arguments = parse_function_tool_arguments(
input_tools=self._input_tools,
function_call=output
)
output.parsed_arguments = parsed_arguments

# Emit event with name from accumulated snapshot
events.append(
build(
ResponseFunctionCallArgumentsDoneEvent,
arguments=output.arguments,
item_id=event.item_id,
name=output.name, # FROM SNAPSHOT, not raw event
output_index=event.output_index,
sequence_number=event.sequence_number,
type="response.function_call_arguments.done",
Comment on lines 309 to 329

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Preserve arguments when only a done event is emitted

The new handler builds ResponseFunctionCallArgumentsDoneEvent using output.arguments, which is only populated by prior response.function_call_arguments.delta events. If the server delivers the full arguments payload only in the response.function_call_arguments.done event (and never emits deltas), output.arguments remains empty and callers now see blank arguments even though the raw event contained them. Previously the raw event was forwarded untouched so the arguments were available. Consider sourcing the field from event.arguments (or falling back to it) to avoid dropping data in backends that do not emit delta updates.

Useful? React with 👍 / 👎.

)
)

elif event.type == "response.completed":
response = self._completed_response
assert response is not None
Expand Down