Skip to content
Merged
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
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

* Fixed structured data extraction with `ChatAnthropic()` failing for Pydantic models containing nested types (e.g., `list[NestedModel]`). The issue was that `$defs` (containing nested type definitions) was incorrectly placed inside the schema, breaking JSON `$ref` pointer references. (#100)
* Fixed MCP tools failing with OpenAI providers due to strict mode schema validation. OpenAI's strict mode rejects standard JSON Schema features like `format: "uri"` and requires all properties in the `required` array. MCP tools now set `strict=false` to use standard JSON Schema conventions. (#255)
* Fixed MCP tools not working with `ChatGoogle()`. (#257)
* Tool functions parameters that are `typing.Annotated` with a `pydantic.Field` (e.g., `def add(x: Annotated[int, Field(description="First number")])`) are now handled correctly. (#251)

## [0.14.0] - 2025-12-09
Expand Down
35 changes: 32 additions & 3 deletions chatlas/_provider_google.py
Original file line number Diff line number Diff line change
Expand Up @@ -299,6 +299,7 @@ def _chat_perform_args(
from google.genai.types import (
FunctionDeclaration,
GenerateContentConfig,
Schema,
ToolListUnion,
)
from google.genai.types import Tool as GoogleTool
Expand Down Expand Up @@ -336,11 +337,18 @@ def _chat_perform_args(
gtool = GoogleTool.model_validate(tool.definition)
google_tools.append(gtool)
else:
func = tool.schema["function"]
params = func.get("parameters")
gtool = GoogleTool(
function_declarations=[
FunctionDeclaration.from_callable(
client=self._client._api_client,
callable=tool.func,
FunctionDeclaration(
name=func["name"],
description=func.get("description"),
parameters=Schema.model_validate(
_strip_additional_properties(params)
)
if params
else None,
)
]
)
Expand Down Expand Up @@ -726,3 +734,24 @@ def ChatVertex(
),
system_prompt=system_prompt,
)


def _strip_additional_properties(params: dict[str, Any]) -> dict[str, Any]:
"""
Recursively remove additionalProperties from JSON schema.

Google's API doesn't accept additionalProperties in tool schemas,
so we strip it before passing to Schema.model_validate().
"""
result = {k: v for k, v in params.items() if k != "additionalProperties"}

if "properties" in result and isinstance(result["properties"], dict):
result["properties"] = {
k: _strip_additional_properties(v) if isinstance(v, dict) else v
for k, v in result["properties"].items()
}

if "items" in result and isinstance(result["items"], dict):
result["items"] = _strip_additional_properties(result["items"])

return result
20 changes: 10 additions & 10 deletions tests/_vcr/test_provider_google/test_tools_parallel.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -21,20 +21,20 @@ interactions:
Host:
- generativelanguage.googleapis.com
x-goog-api-client:
- google-genai-sdk/1.56.0 gl-python/3.11.13
- google-genai-sdk/1.56.0 gl-python/3.12.11
method: POST
uri: https://generativelanguage.googleapis.com/v1beta/models/gemini-2.5-flash:streamGenerateContent?alt=sse
response:
body:
string: "data: {\"candidates\": [{\"content\": {\"parts\": [{\"functionCall\":
{\"name\": \"favorite_color\",\"args\": {\"_person\": \"Joe\"}},\"thoughtSignature\":
\"CiQBcsjafEcxf/2DYJh2KLN0ZyvZXL8qb4eVwpfO1vMCbc+FiI4KdQFyyNp83WPKtw1VCcGDQEHMo5P3ZwwuQVnRgXLHuVpY6pIuISKWq2ahOuhS+R5bmNhTgWLnQZVizSzuoHQvYB+UKBpzHivSACk+/3ev+DdTh/yX3bDryuehMGmfRobrHcHgF14KX9WuMstDN2U8jDu667vWxwrLAQFyyNp8DHJkkPOE6BNUMI5kKtPnOrgc2WbCgjNj4NtwnieDVCXEWRhs8UvvI4bs6T20AHzhyvbVM/iZVcJ3pOWUxTy4vQlrVWQXXpkhMPdHUGNheP3AGhdqQWa7vF8AeR48TUhztTYntyMOwI4ZIkB0C5iqukbIOjGFwM820OpQoy/jfIgGpN0lWzEAek4i/mRiU2xyks5hnaq8OZ1Hb81rIPMFMrkhNp+ubM5H1ba6vpRv7TH3Lt53HsNJDLIqqvFvLxq+JtnjUGLT\"},{\"functionCall\":
\"CiQBcsjafMjxiJn3cWg1h7gi5wrPZplGeMGBGKbMKSrgBmOQ3ToKdQFyyNp8iRQFDsoj4U/xFCCuVdfsNoSR6oJhg9BkrMdgX3fMpRFugrAETa9LVnXWl/Nquk9tpc0s36K4w4enJeGRlWHXCj2xA0irMk3076hl1+cVvPB+AXzl1v+wkkCEKx2DmnmQWqMlEdCri/yhx4fbZB5PiQrLAQFyyNp883zKACGlUvM4xF23wAAyCGnBSfNIKbUa0KjfsoiPDhObJdVrtY1f2Y/eQsOx+Cwgg/Iwr4LyC+JpjYn/bhHDkgVQqHOKB8gpt9CSKQ9d5INULjjX7Ugx3wgg40sJXHDelBzi28F1UN+Fx5aVh7TTd1cMnoFqW7Hxsy4+7N+nabYJZY2pWO+z7WKv7p3YvETy7XdXm3FpNs3VUrBArs1oD+g+2fxOWR47loS9VOpVto5ChqbwSBCqks3B0SyhGuVBZp9E7Rqy\"},{\"functionCall\":
{\"name\": \"favorite_color\",\"args\": {\"_person\": \"Hadley\"}}}],\"role\":
\"model\"},\"finishReason\": \"STOP\",\"index\": 0,\"finishMessage\": \"Model
generated function call(s).\"}],\"usageMetadata\": {\"promptTokenCount\":
80,\"candidatesTokenCount\": 31,\"totalTokenCount\": 170,\"promptTokensDetails\":
[{\"modality\": \"TEXT\",\"tokenCount\": 80}],\"thoughtsTokenCount\": 59},\"modelVersion\":
\"gemini-2.5-flash\",\"responseId\": \"cLBVabe2A8vO_uMP5cWO6As\"}\r\n\r\n"
\"gemini-2.5-flash\",\"responseId\": \"_nBYaYTfOKOi_uMPi9GGwQ8\"}\r\n\r\n"
headers:
Alt-Svc:
- h3=":443"; ma=2592000,h3-29=":443"; ma=2592000
Expand All @@ -43,11 +43,11 @@ interactions:
Content-Type:
- text/event-stream
Date:
- Wed, 31 Dec 2025 23:23:28 GMT
- Sat, 03 Jan 2026 01:29:35 GMT
Server:
- scaffolding on HTTPServer2
Server-Timing:
- gfet4t7; dur=692
- gfet4t7; dur=676
Transfer-Encoding:
- chunked
Vary:
Expand Down Expand Up @@ -90,17 +90,17 @@ interactions:
Host:
- generativelanguage.googleapis.com
x-goog-api-client:
- google-genai-sdk/1.56.0 gl-python/3.11.13
- google-genai-sdk/1.56.0 gl-python/3.12.11
method: POST
uri: https://generativelanguage.googleapis.com/v1beta/models/gemini-2.5-flash:streamGenerateContent?alt=sse
response:
body:
string: "data: {\"candidates\": [{\"content\": {\"parts\": [{\"text\": \"Joe:
sage green, Hadley: red\",\"thoughtSignature\": \"CikBcsjafCFKwPhN+Wb7TRnVQm+ElR/oCeo2mzKEHS8+Td1xBPeskYdN9wp4AXLI2nxAYZCYcFksv72VZHK353YTaGKoZfPlEVRaIl7KUdIqjX5Fqp+roMh19jtTWOB9d3xXMjUas0i/gsWY2ViciwJa7btqli/mgp+Zq3Ew71pE9rJTjbI8R0lmZUhlVdNmh/c0WHOZ4Y6iJD1Zh3vJUq18D8M/CsoBAXLI2nwURNZLgw9xpPFG1JpY3HguQ6cf3vxQl+iwZ9bfJi7uCeXwIDUqRx3w7IDyl+Aa/arTIXU92vjedDK+ZstyokFtJ7pmVFaxPdq1LWTR9+/zFRB3sAUuthVUIal2LqILasEavLiWAS7cTKEHhccQ6kbqAi+L+RncuxWROgu2WHiE4ztR8PRIot8L/QWihzpVVrlV1W9iNKvx7hbT+533O8QvGQLYKQw1gpx/iGR6ZFquBIoivI74TROvLjv8PYfNoIcjeSbDZAqWAQFyyNp83amdQAwXMpsoAZYNgIdKqQTPe+mfG9h5uO0r37dTdcP1ThRHiX2Y1zjOHMm+Bmp24DuR07bzqVDjEaA7odnSQ1M8w3tkI3kvdzIMLNlFBZS52eeXiMzX43Z3CyY25K1UE+oYa4/dliVLvE7onCloSzNCN1Tqwvxueh9GiAhNb6H8dP/vKo4uLR7iEItQmFOxOw==\"}],\"role\":
sage green, Hadley: red\",\"thoughtSignature\": \"CikBcsjafEQ5li0668U/qtbZwgJcrUKj0K26qG5trR41aCc2n6OAg8RrCgp4AXLI2nxxfIx0rsAaGp0+hi9VwK3/OhGcod1MDqpE7u9TbArCnl1Tr6XHv6x4AdMFOj5eruifbd3Fp6RKTEsdWBLODM34IwgRcpd+PUv2OtfnZQpFogUi4j51ecgcAKU3BhEjWaAowhudur1P5a3kHOy32cm24XbPCsoBAXLI2nzPG4G4G9Zvjlvy6lVEFR3hFgK45p6TMcbTAQ6V4iUpHO4q7btbSV8nr3Pm52JZKPvbsq29uknE7qAbINQWD7nxW9lBGzSPzbwv0lrEbcNZgv7whdPnjD7cbL1wIVmTyHJVFlMXa0qGgz6ppeymdcjzj7af1pde3fllw+Mp4xyCzGyn22sP5alyPTbPvIAeXPjqSaj+NLYBXrWx6yQFVCi53XnS81DxHK3FzzN0433mj2wAfjMxMBmnNYlyXuVOUKfg40EKXgqWAQFyyNp8qdHQ5FJi7SgLe3qEIo0rY281iv9w2NB5t6iEvIsK/2htK3Zz0rr6g8lqGjcvN7tyXs0RDIwSzJQsjXvGk8KSEiUGxOIjnim2YG0eZkffJ1KImOf58eSwPaz6eK6f7ZtifJtb5yl1vHJJzmqE3zw5RCdQIZmSPwFRM+ArhjW38O1Robnap/CK+mragHe8r+b4Ug==\"}],\"role\":
\"model\"},\"finishReason\": \"STOP\",\"index\": 0}],\"usageMetadata\": {\"promptTokenCount\":
140,\"candidatesTokenCount\": 8,\"totalTokenCount\": 254,\"promptTokensDetails\":
[{\"modality\": \"TEXT\",\"tokenCount\": 140}],\"thoughtsTokenCount\": 106},\"modelVersion\":
\"gemini-2.5-flash\",\"responseId\": \"cbBVafhco-H-4w_Uvp2JDA\"}\r\n\r\n"
\"gemini-2.5-flash\",\"responseId\": \"_3BYae7dONql_uMPt9e6qAw\"}\r\n\r\n"
headers:
Alt-Svc:
- h3=":443"; ma=2592000,h3-29=":443"; ma=2592000
Expand All @@ -109,11 +109,11 @@ interactions:
Content-Type:
- text/event-stream
Date:
- Wed, 31 Dec 2025 23:23:29 GMT
- Sat, 03 Jan 2026 01:29:36 GMT
Server:
- scaffolding on HTTPServer2
Server-Timing:
- gfet4t7; dur=806
- gfet4t7; dur=813
Transfer-Encoding:
- chunked
Vary:
Expand Down
30 changes: 15 additions & 15 deletions tests/_vcr/test_provider_google/test_tools_sequential.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -25,19 +25,19 @@ interactions:
Host:
- generativelanguage.googleapis.com
x-goog-api-client:
- google-genai-sdk/1.56.0 gl-python/3.11.13
- google-genai-sdk/1.56.0 gl-python/3.12.11
method: POST
uri: https://generativelanguage.googleapis.com/v1beta/models/gemini-2.5-flash:streamGenerateContent?alt=sse
response:
body:
string: "data: {\"candidates\": [{\"content\": {\"parts\": [{\"functionCall\":
{\"name\": \"weather_forecast\",\"args\": {\"city\": \"New York\"}},\"thoughtSignature\":
\"CiQBcsjafLhyUDj0UNUR/Cle08w8Gwk26TZE39p3vyKt16OwRUkKeQFyyNp8KBHPrbClayUb6w5qB/Vr5z4YB6hR1eVzthcXhg+nexjB+21eNjT3QXlDXIzZeEK5rHvh4L+PvoszJLCqsSCufU1ttqY2kV6oBfoRncFHrGXXDqdULOfaFUO7mZLlSWbH2+o2+bKv/XQYchOcVJojiD/iVQcKjAIBcsjafDNI0ijQGMe/V/Z7Gc8stGncDaoRPehWfgBWbr07kpSS2mYD6/S0x1dbcWFOUIiymmK9faP1iPyJAuh326GxuE3XlDDNcNjPkz8RzfvJq3VqKDU2bDqwQOYLdSxmc+/EUyhRF7gB9TI4UTi5uf5hlxsJESjUd7eVRzSxAZfPziu4+9XvKFcmoWSRcEc/mWtymikz2+vYsFmI8Hwxn+1nLBgX5RIOIz99TRCOtSXrWfu12r92oywUWQEq8jiAc3UzdRLUEh3U+v+U+fJhVKAZ0Jf1PM+vcrUZsG6tfnrZfZyO6J4/3m+KkGPkW9KTQHHMA6UR0pA55fVUN6Od1YBX/lrZ7uaUfhtCCl8BcsjafBkxjGNoR7pmBJraAR391rBQqiNlVuXKGKXe/4iRBx4Gd3gXMt6qWVsfebU5aOnPKxnFJOgRT22ER7usCEax7TPQnVh0vWon4VAUdX7DVtlX90tT0NLrCtTSag==\"}],\"role\":
\"CiQBcsjafACpV7G9rvFg/YUqr5jwsRi6YjR7sTD//u+elmtbYfgKbwFyyNp80DDvuelFbpI07IdJJg6JXLe8HyyCT3JxStjPiQ6P5zPGi85/67m0EHDE6+ynjzMGTkiwiUHe01H8Kj+FtopqVp+zMfE9IbuVBH/m0zYejdyEyo97gsgMnMWZGxM7vrCTNl/4KKRkVoNN5Qr9AQFyyNp8UZoxx1q/Fm3u67QEFP6lLXbyiFpDokV6Drcbwh74alJhpU14jqqiAO2/iuMdr+470VrEUpbyyeUS8/3UnahOKmdsfLUf2TNeYa9dncg5QuSe6nFwf5GCs2vTcC2Wmy6Yi9tvd63BEnEdMhJYGkk/62gKKIzGHofZW/Q93mUAIpjEFU9WTAcP4CZfMov91pNHBsJb9OGyzWc1dZKB6OhpIlAVAXmY4wpGzpXtx1wxxPGU7LSvYNNyHwmeI03IPdjUbiLFb96vZGZlb5b4qcffddrT6zHC/benaxpVLOW/gbV3OxQn8OMcjAzL46zI7KrFRbLnDYiQb6AKSgFyyNp8EizpyAaDFRQaEC2Iun1ljFL7UbERZwi4J338Abg5xkFWUZfZIAHfFwkBfQDj+fCGnwt1dCIUzCF0+1b5HUsVSMMWBg58\"}],\"role\":
\"model\"},\"finishReason\": \"STOP\",\"index\": 0,\"finishMessage\": \"Model
generated function call(s).\"}],\"usageMetadata\": {\"promptTokenCount\":
133,\"candidatesTokenCount\": 16,\"totalTokenCount\": 232,\"promptTokensDetails\":
[{\"modality\": \"TEXT\",\"tokenCount\": 133}],\"thoughtsTokenCount\": 83},\"modelVersion\":
\"gemini-2.5-flash\",\"responseId\": \"crBVab6fBe6p_uMPycCNyAg\"}\r\n\r\n"
133,\"candidatesTokenCount\": 16,\"totalTokenCount\": 226,\"promptTokensDetails\":
[{\"modality\": \"TEXT\",\"tokenCount\": 133}],\"thoughtsTokenCount\": 77},\"modelVersion\":
\"gemini-2.5-flash\",\"responseId\": \"AXFYaf3jA7qj_uMPuYjYCQ\"}\r\n\r\n"
headers:
Alt-Svc:
- h3=":443"; ma=2592000,h3-29=":443"; ma=2592000
Expand All @@ -46,11 +46,11 @@ interactions:
Content-Type:
- text/event-stream
Date:
- Wed, 31 Dec 2025 23:23:30 GMT
- Sat, 03 Jan 2026 01:29:37 GMT
Server:
- scaffolding on HTTPServer2
Server-Timing:
- gfet4t7; dur=781
- gfet4t7; dur=741
Transfer-Encoding:
- chunked
Vary:
Expand Down Expand Up @@ -94,7 +94,7 @@ interactions:
Host:
- generativelanguage.googleapis.com
x-goog-api-client:
- google-genai-sdk/1.56.0 gl-python/3.11.13
- google-genai-sdk/1.56.0 gl-python/3.12.11
method: POST
uri: https://generativelanguage.googleapis.com/v1beta/models/gemini-2.5-flash:streamGenerateContent?alt=sse
response:
Expand All @@ -104,7 +104,7 @@ interactions:
\"STOP\",\"index\": 0,\"finishMessage\": \"Model generated function call(s).\"}],\"usageMetadata\":
{\"promptTokenCount\": 165,\"candidatesTokenCount\": 14,\"totalTokenCount\":
179,\"promptTokensDetails\": [{\"modality\": \"TEXT\",\"tokenCount\": 165}]},\"modelVersion\":
\"gemini-2.5-flash\",\"responseId\": \"dLBVaZqVHs2n_uMPx4K9wAw\"}\r\n\r\n"
\"gemini-2.5-flash\",\"responseId\": \"AnFYab6FA-6p_uMPycCNyAg\"}\r\n\r\n"
headers:
Alt-Svc:
- h3=":443"; ma=2592000,h3-29=":443"; ma=2592000
Expand All @@ -113,11 +113,11 @@ interactions:
Content-Type:
- text/event-stream
Date:
- Wed, 31 Dec 2025 23:23:32 GMT
- Sat, 03 Jan 2026 01:29:38 GMT
Server:
- scaffolding on HTTPServer2
Server-Timing:
- gfet4t7; dur=1731
- gfet4t7; dur=443
Transfer-Encoding:
- chunked
Vary:
Expand Down Expand Up @@ -164,7 +164,7 @@ interactions:
Host:
- generativelanguage.googleapis.com
x-goog-api-client:
- google-genai-sdk/1.56.0 gl-python/3.11.13
- google-genai-sdk/1.56.0 gl-python/3.12.11
method: POST
uri: https://generativelanguage.googleapis.com/v1beta/models/gemini-2.5-flash:streamGenerateContent?alt=sse
response:
Expand All @@ -173,7 +173,7 @@ interactions:
\"model\"},\"finishReason\": \"STOP\",\"index\": 0}],\"usageMetadata\": {\"promptTokenCount\":
192,\"candidatesTokenCount\": 1,\"totalTokenCount\": 193,\"promptTokensDetails\":
[{\"modality\": \"TEXT\",\"tokenCount\": 192}]},\"modelVersion\": \"gemini-2.5-flash\",\"responseId\":
\"dbBVaY62Au6p_uMPycCNyAg\"}\r\n\r\n"
\"AnFYaZCxLt63_uMP172v6Q0\"}\r\n\r\n"
headers:
Alt-Svc:
- h3=":443"; ma=2592000,h3-29=":443"; ma=2592000
Expand All @@ -182,11 +182,11 @@ interactions:
Content-Type:
- text/event-stream
Date:
- Wed, 31 Dec 2025 23:23:33 GMT
- Sat, 03 Jan 2026 01:29:38 GMT
Server:
- scaffolding on HTTPServer2
Server-Timing:
- gfet4t7; dur=242
- gfet4t7; dur=413
Transfer-Encoding:
- chunked
Vary:
Expand Down
Loading