Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
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
2 changes: 1 addition & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ typecheck-both: typecheck-pyright typecheck-mypy
.PHONY: test
test: ## Run tests and collect coverage data
@# To test using a specific version of python, run 'make install-all-python' then set environment variable PYTEST_PYTHON=3.10 or similar
COLUMNS=150 $(if $(PYTEST_PYTHON),UV_PROJECT_ENVIRONMENT=.venv$(subst .,,$(PYTEST_PYTHON))) uv run $(if $(PYTEST_PYTHON),--python $(PYTEST_PYTHON)) coverage run -m pytest -n auto --dist=loadgroup --durations=20
COLUMNS=150 $(if $(PYTEST_PYTHON),UV_PROJECT_ENVIRONMENT=.venv$(subst .,,$(PYTEST_PYTHON))) uv run $(if $(PYTEST_PYTHON),--python $(PYTEST_PYTHON)) coverage run -m pytest -n auto --dist=loadgroup --durations=100
@uv run coverage combine
@uv run coverage report

Expand Down
Binary file added tests/assets/kiwi.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file removed tests/assets/kiwi.png
Binary file not shown.
6 changes: 3 additions & 3 deletions tests/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -334,8 +334,8 @@ def audio_content(assets_path: Path) -> BinaryContent:

@pytest.fixture(scope='session')
def image_content(assets_path: Path) -> BinaryContent:
image_bytes = assets_path.joinpath('kiwi.png').read_bytes()
return BinaryContent(data=image_bytes, media_type='image/png')
image_bytes = assets_path.joinpath('kiwi.jpg').read_bytes()
return BinaryContent(data=image_bytes, media_type='image/jpeg')


@pytest.fixture(scope='session')
Expand Down Expand Up @@ -369,7 +369,7 @@ def openai_api_key() -> str:

@pytest.fixture(scope='session')
def gemini_api_key() -> str:
return os.getenv('GEMINI_API_KEY', 'mock-api-key')
return os.getenv('GEMINI_API_KEY', os.getenv('GOOGLE_API_KEY', 'mock-api-key'))


@pytest.fixture(scope='session')
Expand Down
18 changes: 9 additions & 9 deletions tests/mcp_server.py
Original file line number Diff line number Diff line change
Expand Up @@ -49,13 +49,13 @@ async def get_weather_forecast(location: str) -> str:

@mcp.tool()
async def get_image_resource() -> EmbeddedResource:
data = Path(__file__).parent.joinpath('assets/kiwi.png').read_bytes()
data = Path(__file__).parent.joinpath('assets/kiwi.jpg').read_bytes()
return EmbeddedResource(
type='resource',
resource=BlobResourceContents(
uri=AnyUrl('resource://kiwi.png'),
uri=AnyUrl('resource://kiwi.jpg'),
blob=base64.b64encode(data).decode('utf-8'),
mimeType='image/png',
mimeType='image/jpeg',
),
)

Expand All @@ -64,14 +64,14 @@ async def get_image_resource() -> EmbeddedResource:
async def get_image_resource_link() -> ResourceLink:
return ResourceLink(
type='resource_link',
uri=AnyUrl('resource://kiwi.png'),
name='kiwi.png',
uri=AnyUrl('resource://kiwi.jpg'),
name='kiwi.jpg',
)


@mcp.resource('resource://kiwi.png', mime_type='image/png')
@mcp.resource('resource://kiwi.jpg', mime_type='image/jpg')
async def kiwi_resource() -> bytes:
return Path(__file__).parent.joinpath('assets/kiwi.png').read_bytes()
return Path(__file__).parent.joinpath('assets/kiwi.jpg').read_bytes()


@mcp.tool()
Expand Down Expand Up @@ -138,8 +138,8 @@ async def greeting_resource_template(name: str) -> str:

@mcp.tool()
async def get_image() -> Image:
data = Path(__file__).parent.joinpath('assets/kiwi.png').read_bytes()
return Image(data=data, format='png')
data = Path(__file__).parent.joinpath('assets/kiwi.jpg').read_bytes()
return Image(data=data, format='jpg')


@mcp.tool()
Expand Down

Large diffs are not rendered by default.

Large diffs are not rendered by default.

Large diffs are not rendered by default.

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ interactions:
response:
headers:
content-length:
- '1080'
- '922'
content-security-policy:
- default-src 'none'; frame-ancestors 'none'
content-type:
Expand All @@ -25,12 +25,6 @@ interactions:
strict-transport-security:
- max-age=63072000
parsed_body:
- model_id: amazon-rerank-1-0
regions:
- eu
- us
type:
- text-to-text
- model_id: claude-3-5-haiku
regions:
- us
Expand Down Expand Up @@ -76,12 +70,6 @@ interactions:
- us
type:
- text-to-embedding
- model_id: cohere-rerank-3-5
regions:
- eu
- us
type:
- text-to-text
- model_id: gpt-oss-120b
regions:
- eu
Expand Down Expand Up @@ -124,7 +112,7 @@ interactions:
alt-svc:
- h3=":443"; ma=86400
content-length:
- '570'
- '479'
content-type:
- application/json
referrer-policy:
Expand All @@ -133,10 +121,6 @@ interactions:
- max-age=3600; includeSubDomains
parsed_body:
data:
- created: 0
id: qwen-3-235b-a22b-thinking-2507
object: model
owned_by: Cerebras
- created: 0
id: llama-3.3-70b
object: model
Expand Down

Large diffs are not rendered by default.

Large diffs are not rendered by default.

28 changes: 14 additions & 14 deletions tests/models/test_anthropic.py
Original file line number Diff line number Diff line change
Expand Up @@ -1108,38 +1108,38 @@ async def get_image() -> BinaryContent:
),
ModelResponse(
parts=[
TextPart(content='Let me get the image and check what fruit is shown.'),
ToolCallPart(tool_name='get_image', args={}, tool_call_id='toolu_01WALUz3dC75yywrmL6dF3Bc'),
TextPart(content="I'll get the image and identify the fruit in it."),
ToolCallPart(tool_name='get_image', args={}, tool_call_id='toolu_01PHxLXXMf3zJCjPVT9kPuFQ'),
],
usage=RequestUsage(
input_tokens=372,
input_tokens=555,
output_tokens=49,
details={
'cache_creation_input_tokens': 0,
'cache_read_input_tokens': 0,
'input_tokens': 372,
'input_tokens': 555,
'output_tokens': 49,
},
),
model_name='claude-sonnet-4-5-20250929',
timestamp=IsDatetime(),
provider_name='anthropic',
provider_details={'finish_reason': 'tool_use'},
provider_response_id='msg_01Kwjzggomz7bv9og51qGFuH',
provider_response_id='msg_01T327ZyP7axwsPFDzwiYTMB',
finish_reason='tool_call',
run_id=IsStr(),
),
ModelRequest(
parts=[
ToolReturnPart(
tool_name='get_image',
content='See file 1c8566',
tool_call_id='toolu_01WALUz3dC75yywrmL6dF3Bc',
content='See file 241a70',
tool_call_id='toolu_01PHxLXXMf3zJCjPVT9kPuFQ',
timestamp=IsDatetime(),
),
UserPromptPart(
content=[
'This is file 1c8566:',
'This is file 241a70:',
image_content,
],
timestamp=IsDatetime(),
Expand All @@ -1150,24 +1150,24 @@ async def get_image() -> BinaryContent:
ModelResponse(
parts=[
TextPart(
content="The image shows a kiwi fruit that has been cut in half, displaying its characteristic bright green flesh with small black seeds arranged in a circular pattern around a white center core. The kiwi's flesh has the typical fuzzy brown skin visible around the edges. The image is a clean, well-lit close-up shot of the kiwi slice against a white background."
content='The fruit in the image is a **kiwi** (also called kiwifruit). The image shows a cross-section of a kiwi, displaying its characteristic bright green flesh, small black seeds arranged in a circular pattern around a pale center, and the fuzzy brown skin around the edges.'
)
],
usage=RequestUsage(
input_tokens=2025,
output_tokens=81,
input_tokens=1100,
output_tokens=66,
details={
'cache_creation_input_tokens': 0,
'cache_read_input_tokens': 0,
'input_tokens': 2025,
'output_tokens': 81,
'input_tokens': 1100,
'output_tokens': 66,
},
),
model_name='claude-sonnet-4-5-20250929',
timestamp=IsDatetime(),
provider_name='anthropic',
provider_details={'finish_reason': 'end_turn'},
provider_response_id='msg_015btMBYLTuDnMP7zAeuHQGi',
provider_response_id='msg_01SZqj5KLnCWURYDQeaPo7mJ',
finish_reason='stop',
run_id=IsStr(),
),
Expand Down
6 changes: 3 additions & 3 deletions tests/models/test_gemini.py
Original file line number Diff line number Diff line change
Expand Up @@ -1177,7 +1177,7 @@ def handler(request: httpx.Request) -> httpx.Response:
async def test_image_as_binary_content_tool_response(
allow_model_requests: None, gemini_api_key: str, image_content: BinaryContent
) -> None:
m = GeminiModel('gemini-2.5-pro-preview-03-25', provider=GoogleGLAProvider(api_key=gemini_api_key))
m = GeminiModel('gemini-3-pro-preview', provider=GoogleGLAProvider(api_key=gemini_api_key))
agent = Agent(m)

@agent.tool_plain
Expand Down Expand Up @@ -1218,13 +1218,13 @@ async def get_image() -> BinaryContent:
parts=[
ToolReturnPart(
tool_name='get_image',
content='See file 1c8566',
content='See file 241a70',
tool_call_id=IsStr(),
timestamp=IsDatetime(),
),
UserPromptPart(
content=[
'This is file 1c8566:',
'This is file 241a70:',
image_content,
],
timestamp=IsDatetime(),
Expand Down
22 changes: 11 additions & 11 deletions tests/models/test_groq.py
Original file line number Diff line number Diff line change
Expand Up @@ -585,7 +585,7 @@ async def test_image_url_input(allow_model_requests: None, groq_api_key: str):
async def test_image_as_binary_content_tool_response(
allow_model_requests: None, groq_api_key: str, image_content: BinaryContent
):
m = GroqModel('meta-llama/llama-4-scout-17b-16e-instruct', provider=GroqProvider(api_key=groq_api_key))
m = GroqModel('meta-llama/llama-4-maverick-17b-128e-instruct', provider=GroqProvider(api_key=groq_api_key))
agent = Agent(m)

@agent.tool_plain
Expand All @@ -609,27 +609,27 @@ async def get_image() -> BinaryContent:
run_id=IsStr(),
),
ModelResponse(
parts=[ToolCallPart(tool_name='get_image', args='{}', tool_call_id='call_wkpd')],
usage=RequestUsage(input_tokens=192, output_tokens=8),
model_name='meta-llama/llama-4-scout-17b-16e-instruct',
parts=[ToolCallPart(tool_name='get_image', args='{}', tool_call_id='6weyx5dr0')],
usage=RequestUsage(input_tokens=712, output_tokens=20),
model_name='meta-llama/llama-4-maverick-17b-128e-instruct',
timestamp=IsDatetime(),
provider_name='groq',
provider_details={'finish_reason': 'tool_calls'},
provider_response_id='chatcmpl-3c327c89-e9f5-4aac-a5d5-190e6f6f25c9',
provider_response_id='chatcmpl-b8f663a4-3fd5-45fd-8350-f76e3ad82fd2',
finish_reason='tool_call',
run_id=IsStr(),
),
ModelRequest(
parts=[
ToolReturnPart(
tool_name='get_image',
content='See file 1c8566',
tool_call_id='call_wkpd',
content='See file 241a70',
tool_call_id='6weyx5dr0',
timestamp=IsDatetime(),
),
UserPromptPart(
content=[
'This is file 1c8566:',
'This is file 241a70:',
image_content,
],
timestamp=IsDatetime(),
Expand All @@ -639,12 +639,12 @@ async def get_image() -> BinaryContent:
),
ModelResponse(
parts=[TextPart(content='The fruit in the image is a kiwi.')],
usage=RequestUsage(input_tokens=2552, output_tokens=11),
model_name='meta-llama/llama-4-scout-17b-16e-instruct',
usage=RequestUsage(input_tokens=1501, output_tokens=11),
model_name='meta-llama/llama-4-maverick-17b-128e-instruct',
timestamp=IsDatetime(),
provider_name='groq',
provider_details={'finish_reason': 'stop'},
provider_response_id='chatcmpl-82dfad42-6a28-4089-82c3-c8633f626c0d',
provider_response_id='chatcmpl-3e3c87b6-4bba-410b-97a1-7e0c112f704f',
finish_reason='stop',
run_id=IsStr(),
),
Expand Down
16 changes: 8 additions & 8 deletions tests/models/test_mistral.py
Original file line number Diff line number Diff line change
Expand Up @@ -1901,27 +1901,27 @@ async def get_image() -> BinaryContent:
run_id=IsStr(),
),
ModelResponse(
parts=[ToolCallPart(tool_name='get_image', args='{}', tool_call_id='utZJMAZN4')],
parts=[ToolCallPart(tool_name='get_image', args='{}', tool_call_id='9v45XkLNV')],
usage=RequestUsage(input_tokens=65, output_tokens=16),
model_name='pixtral-12b-latest',
timestamp=IsDatetime(),
provider_name='mistral',
provider_details={'finish_reason': 'tool_calls'},
provider_response_id='fce6d16a4e5940edb24ae16dd0369947',
provider_response_id='b3b0e536e2784e489cbd42eb0a62fc0b',
finish_reason='tool_call',
run_id=IsStr(),
),
ModelRequest(
parts=[
ToolReturnPart(
tool_name='get_image',
content='See file 1c8566',
tool_call_id='utZJMAZN4',
content='See file 241a70',
tool_call_id='9v45XkLNV',
timestamp=IsDatetime(),
),
UserPromptPart(
content=[
'This is file 1c8566:',
'This is file 241a70:',
image_content,
],
timestamp=IsDatetime(),
Expand All @@ -1932,15 +1932,15 @@ async def get_image() -> BinaryContent:
ModelResponse(
parts=[
TextPart(
content='The image you\'re referring to, labeled as "file 1c8566," shows a kiwi. Kiwis are small, brown, oval-shaped fruits with a bright green flesh inside that is dotted with tiny black seeds. They have a sweet and tangy flavor and are known for being rich in vitamin C and fiber.'
content='The image shows a kiwi fruit that has been cut in half. Kiwis are known for their bright green flesh with tiny black seeds and a unique texture. They have a sweet and tangy flavor.'
)
],
usage=RequestUsage(input_tokens=2931, output_tokens=70),
usage=RequestUsage(input_tokens=1542, output_tokens=43),
model_name='pixtral-12b-latest',
timestamp=IsDatetime(),
provider_name='mistral',
provider_details={'finish_reason': 'stop'},
provider_response_id='26e7de193646460e8904f8e604a60dc1',
provider_response_id='c01b0e4a6a7a44f2ae0eb5a16af91f28',
finish_reason='stop',
run_id=IsStr(),
),
Expand Down
Loading
Loading