From 2af02a305fc3ec8d9728b3d0264d5d4105c635be Mon Sep 17 00:00:00 2001 From: Copilot Date: Tue, 21 Apr 2026 03:41:00 +0000 Subject: [PATCH 1/2] Fix streaming response losing created_at from response.completed event (#5347) The streaming path in _parse_chunk_from_openai did not extract created_at from the response.completed event, unlike the non-streaming path in _parse_responses_response. This caused durabletask persistence warnings when created_at was None. Extract created_at in the response.completed case and pass it to the returned ChatResponseUpdate. Also fix pre-existing pyright errors for optional orjson import in sample files. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- .../agent_framework_openai/_chat_client.py | 5 ++++ .../tests/openai/test_openai_chat_client.py | 24 +++++++++++++++++++ .../conversations/file_history_provider.py | 2 +- ...story_provider_conversation_persistence.py | 2 +- 4 files changed, 31 insertions(+), 2 deletions(-) diff --git a/python/packages/openai/agent_framework_openai/_chat_client.py b/python/packages/openai/agent_framework_openai/_chat_client.py index 5b7584dc6d..c8a41a204f 100644 --- a/python/packages/openai/agent_framework_openai/_chat_client.py +++ b/python/packages/openai/agent_framework_openai/_chat_client.py @@ -2028,6 +2028,7 @@ def _parse_chunk_from_openai( local_shell_tool_name = self._get_local_shell_tool_name(options.get("tools")) conversation_id: str | None = None response_id: str | None = None + created_at: str | None = None continuation_token: OpenAIContinuationToken | None = None model = self.model match event.type: @@ -2209,6 +2210,9 @@ def _parse_chunk_from_openai( response_id = event.response.id conversation_id = self._get_conversation_id(event.response, options.get("store")) model = event.response.model + created_at = datetime.fromtimestamp(event.response.created_at, tz=timezone.utc).strftime( + "%Y-%m-%dT%H:%M:%S.%fZ" + ) if event.response.usage: usage = self._parse_usage_from_openai(event.response.usage) if usage: @@ -2589,6 +2593,7 @@ def _get_ann_value(key: str) -> Any: response_id=response_id, role="assistant", model=model, + created_at=created_at, continuation_token=continuation_token, additional_properties=metadata, raw_representation=event, diff --git a/python/packages/openai/tests/openai/test_openai_chat_client.py b/python/packages/openai/tests/openai/test_openai_chat_client.py index 8c956a6339..7624f30b65 100644 --- a/python/packages/openai/tests/openai/test_openai_chat_client.py +++ b/python/packages/openai/tests/openai/test_openai_chat_client.py @@ -2192,6 +2192,7 @@ def test_streaming_chunk_with_usage_only() -> None: mock_event.response.id = "resp_usage" mock_event.response.model = "test-model" mock_event.response.conversation = None + mock_event.response.created_at = 1000000000.0 mock_event.response.usage = MagicMock() mock_event.response.usage.input_tokens = 50 mock_event.response.usage.output_tokens = 25 @@ -4438,6 +4439,7 @@ def test_streaming_response_completed_no_continuation_token() -> None: mock_event.response.conversation = MagicMock() mock_event.response.conversation.id = "conv_done" mock_event.response.model = "test-model" + mock_event.response.created_at = 1000000000.0 mock_event.response.usage = None update = client._parse_chunk_from_openai(mock_event, chat_options, function_call_ids) @@ -4445,6 +4447,28 @@ def test_streaming_response_completed_no_continuation_token() -> None: assert update.continuation_token is None +def test_streaming_response_completed_sets_created_at() -> None: + """Test that response.completed sets created_at on the ChatResponseUpdate.""" + client = OpenAIChatClient(model="test-model", api_key="test-key") + chat_options: dict[str, Any] = {} + function_call_ids: dict[int, tuple[str, str]] = {} + + mock_event = MagicMock() + mock_event.type = "response.completed" + mock_event.response = MagicMock() + mock_event.response.id = "resp_created" + mock_event.response.conversation = MagicMock() + mock_event.response.conversation.id = "conv_created" + mock_event.response.model = "test-model" + mock_event.response.created_at = 1000000000.0 + mock_event.response.usage = None + + update = client._parse_chunk_from_openai(mock_event, chat_options, function_call_ids) + + assert update.created_at is not None + assert update.created_at == "2001-09-09T01:46:40.000000Z" + + def test_map_chat_to_agent_update_preserves_continuation_token() -> None: """Test that map_chat_to_agent_update propagates continuation_token.""" from agent_framework._types import map_chat_to_agent_update diff --git a/python/samples/02-agents/conversations/file_history_provider.py b/python/samples/02-agents/conversations/file_history_provider.py index 04a87f8224..9781334c0b 100644 --- a/python/samples/02-agents/conversations/file_history_provider.py +++ b/python/samples/02-agents/conversations/file_history_provider.py @@ -21,7 +21,7 @@ from pydantic import Field try: - import orjson + import orjson # type: ignore[import-not-found] except ImportError: orjson = None diff --git a/python/samples/02-agents/conversations/file_history_provider_conversation_persistence.py b/python/samples/02-agents/conversations/file_history_provider_conversation_persistence.py index 70c5d7e8e8..9f135936ca 100644 --- a/python/samples/02-agents/conversations/file_history_provider_conversation_persistence.py +++ b/python/samples/02-agents/conversations/file_history_provider_conversation_persistence.py @@ -22,7 +22,7 @@ from pydantic import Field try: - import orjson + import orjson # type: ignore[import-not-found] except ImportError: orjson = None From b8d039a38f03af3c584e9ec5ecc13aa0d19a1e3c Mon Sep 17 00:00:00 2001 From: Copilot Date: Tue, 21 Apr 2026 03:53:32 +0000 Subject: [PATCH 2/2] Fix orjson import suppression to use pyright instead of mypy (#5347) Replace `# type: ignore[import-not-found]` with `# pyright: ignore[reportMissingImports]` on optional orjson imports in conversation sample files, matching the repo's Pyright strict configuration. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- python/samples/02-agents/conversations/file_history_provider.py | 2 +- .../file_history_provider_conversation_persistence.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/python/samples/02-agents/conversations/file_history_provider.py b/python/samples/02-agents/conversations/file_history_provider.py index 9781334c0b..20735ffd17 100644 --- a/python/samples/02-agents/conversations/file_history_provider.py +++ b/python/samples/02-agents/conversations/file_history_provider.py @@ -21,7 +21,7 @@ from pydantic import Field try: - import orjson # type: ignore[import-not-found] + import orjson # pyright: ignore[reportMissingImports] except ImportError: orjson = None diff --git a/python/samples/02-agents/conversations/file_history_provider_conversation_persistence.py b/python/samples/02-agents/conversations/file_history_provider_conversation_persistence.py index 9f135936ca..693501b0f9 100644 --- a/python/samples/02-agents/conversations/file_history_provider_conversation_persistence.py +++ b/python/samples/02-agents/conversations/file_history_provider_conversation_persistence.py @@ -22,7 +22,7 @@ from pydantic import Field try: - import orjson # type: ignore[import-not-found] + import orjson # pyright: ignore[reportMissingImports] except ImportError: orjson = None