1
+ from contextlib import nullcontext
1
2
import os
2
3
from typing import Any
3
4
4
5
import openai
5
- import pytest
6
6
from openai .types .chat .chat_completion import ChatCompletion , Choice
7
7
from openai .types .chat .chat_completion_message import ChatCompletionMessage
8
8
from openai .types .responses import ResponseCompletedEvent
9
+ import pytest
9
10
11
+ from agents import __version__
10
12
from agents import (
11
13
ModelSettings ,
12
14
ModelTracing ,
@@ -78,8 +80,10 @@ def test_set_default_openai_api():
78
80
79
81
@pytest .mark .allow_call_model_methods
80
82
@pytest .mark .asyncio
81
- async def test_user_agent_override_responses ():
83
+ @pytest .mark .parametrize ("override_ua" , [None , "test_user_agent" ])
84
+ async def test_user_agent_header_responses (override_ua ):
82
85
called_kwargs = {}
86
+ expected_ua = override_ua or f"Agents/Python { __version__ } "
83
87
84
88
class DummyStream :
85
89
def __aiter__ (self ):
@@ -98,13 +102,14 @@ async def create(self, **kwargs):
98
102
called_kwargs = kwargs
99
103
return DummyStream ()
100
104
101
- class DummyClient :
105
+ class DummyResponsesClient :
102
106
def __init__ (self ):
103
107
self .responses = DummyResponses ()
104
108
105
- model = OpenAIResponsesModel (model = "gpt-4" , openai_client = DummyClient ()) # type: ignore
109
+ model = OpenAIResponsesModel (model = "gpt-4" , openai_client = DummyResponsesClient ()) # type: ignore
106
110
107
- with user_agent_override ("test_user_agent" ):
111
+ cm = user_agent_override (override_ua ) if override_ua else nullcontext ()
112
+ with cm :
108
113
stream = model .stream_response (
109
114
system_instructions = None ,
110
115
input = "hi" ,
@@ -114,24 +119,24 @@ def __init__(self):
114
119
handoffs = [],
115
120
tracing = ModelTracing .DISABLED ,
116
121
)
117
-
118
122
async for _ in stream :
119
123
pass
120
124
121
125
assert "extra_headers" in called_kwargs
122
- assert called_kwargs ["extra_headers" ]["User-Agent" ] == "test_user_agent"
126
+ assert called_kwargs ["extra_headers" ]["User-Agent" ] == expected_ua
123
127
124
128
125
129
@pytest .mark .allow_call_model_methods
126
130
@pytest .mark .asyncio
127
- async def test_user_agent_override_chat_completions ():
131
+ @pytest .mark .parametrize ("override_ua" , [None , "test_user_agent" ])
132
+ async def test_user_agent_header_chat_completions (override_ua ):
128
133
called_kwargs = {}
134
+ expected_ua = override_ua or f"Agents/Python { __version__ } "
129
135
130
136
class DummyCompletions :
131
137
async def create (self , ** kwargs ):
132
138
nonlocal called_kwargs
133
139
called_kwargs = kwargs
134
-
135
140
msg = ChatCompletionMessage (role = "assistant" , content = "Hello" )
136
141
choice = Choice (index = 0 , finish_reason = "stop" , message = msg )
137
142
return ChatCompletion (
@@ -143,14 +148,15 @@ async def create(self, **kwargs):
143
148
usage = None ,
144
149
)
145
150
146
- class DummyClient :
151
+ class DummyChatClient :
147
152
def __init__ (self ):
148
153
self .chat = type ("_Chat" , (), {"completions" : DummyCompletions ()})()
149
154
self .base_url = "https://api.openai.com"
150
155
151
- model = OpenAIChatCompletionsModel (model = "gpt-4" , openai_client = DummyClient ()) # type: ignore
156
+ model = OpenAIChatCompletionsModel (model = "gpt-4" , openai_client = DummyChatClient ()) # type: ignore
152
157
153
- with user_agent_override ("test_user_agent" ):
158
+ cm = user_agent_override (override_ua ) if override_ua else nullcontext ()
159
+ with cm :
154
160
await model .get_response (
155
161
system_instructions = None ,
156
162
input = "hi" ,
@@ -164,19 +170,20 @@ def __init__(self):
164
170
)
165
171
166
172
assert "extra_headers" in called_kwargs
167
- assert called_kwargs ["extra_headers" ]["User-Agent" ] == "test_user_agent"
173
+ assert called_kwargs ["extra_headers" ]["User-Agent" ] == expected_ua
168
174
169
175
170
176
@pytest .mark .allow_call_model_methods
171
177
@pytest .mark .asyncio
172
- async def test_user_agent_override_litellm (monkeypatch ):
178
+ @pytest .mark .parametrize ("override_ua" , [None , "test_user_agent" ])
179
+ async def test_user_agent_header_litellm (override_ua , monkeypatch ):
180
+ called_kwargs = {}
181
+ expected_ua = override_ua or f"Agents/Python { __version__ } "
182
+
173
183
import importlib
174
184
import sys
175
185
import types as pytypes
176
186
177
- called_kwargs = {}
178
-
179
- # Create a fake litellm module so we don't need the real dependency
180
187
litellm_fake : Any = pytypes .ModuleType ("litellm" )
181
188
182
189
class DummyMessage :
@@ -196,7 +203,6 @@ def __init__(self):
196
203
197
204
class DummyModelResponse :
198
205
def __init__ (self ):
199
- # Minimal shape expected by get_response()
200
206
self .choices = [Choices ()]
201
207
202
208
async def acompletion (** kwargs ):
@@ -217,14 +223,14 @@ async def acompletion(**kwargs):
217
223
218
224
monkeypatch .setitem (sys .modules , "litellm" , litellm_fake )
219
225
220
- # Import after injecting fake module and patch the module's symbol directly
221
226
litellm_mod = importlib .import_module ("agents.extensions.models.litellm_model" )
222
227
monkeypatch .setattr (litellm_mod , "litellm" , litellm_fake , raising = True )
223
228
LitellmModel = litellm_mod .LitellmModel
224
229
225
230
model = LitellmModel (model = "gpt-4" )
226
231
227
- with user_agent_override ("test_user_agent" ):
232
+ cm = user_agent_override (override_ua ) if override_ua else nullcontext ()
233
+ with cm :
228
234
await model .get_response (
229
235
system_instructions = None ,
230
236
input = "hi" ,
@@ -239,4 +245,7 @@ async def acompletion(**kwargs):
239
245
)
240
246
241
247
assert "extra_headers" in called_kwargs
242
- assert called_kwargs ["extra_headers" ]["User-Agent" ] == "test_user_agent"
248
+ assert called_kwargs ["extra_headers" ]["User-Agent" ] == expected_ua
249
+
250
+
251
+ # (Replaced by test_user_agent_header_parametrized)
0 commit comments