Compare commits

...

12 Commits

Author SHA1 Message Date
copilot-swe-agent[bot]
2ded33f027 fix: bump aiohttp to >=3.14.2 and cryptography to >=50.0.0 to fix pip-audit vulns
Co-authored-by: theCyberTech <84775494+theCyberTech@users.noreply.github.com>
2026-08-04 01:29:40 +00:00
Rip&Tear
034658e46c Merge branch 'main' into fix/native-tool-call-responses-api-shape 2026-08-04 09:22:41 +08:00
copilot-swe-agent[bot]
075829c5fb fix: upgrade nltk to 3.10.0 to resolve path traversal vulnerabilities
Upgrades nltk from 3.9.4 to 3.10.0 which fixes three path traversal
vulnerabilities (GHSA-qvv7-cg9c-w4x3, GHSA-fg7f-2386-8897,
GHSA-xh95-f55m-82fw) that were causing the pip-audit CI job to fail.

Also removes the now-obsolete PYSEC-2026-597 ignore entry from the
vulnerability-scan workflow since the vulnerability is fixed in 3.10.0.
2026-08-03 11:31:36 +00:00
Rip&Tear
f9aef7f93c Merge branch 'main' into fix/native-tool-call-responses-api-shape 2026-08-03 19:18:55 +08:00
copilot-swe-agent[bot]
4267e0ffd3 Resolve merge conflicts with origin/main 2026-07-28 04:16:58 +00:00
Rip&Tear
9e06006f72 style: format Responses API conversion 2026-07-13 08:42:38 +08:00
Rip&Tear
f6640b1cd8 fix: harden Responses API tool call conversion 2026-07-13 08:28:38 +08:00
João Moura
6450d67b9c Merge branch 'main' into fix/native-tool-call-responses-api-shape 2026-07-12 17:57:18 -03:00
theCyberTech
6f62ed826d fix(llms/openai): fix mypy list-item type error in message conversion
_convert_message_to_responses_input_items() was annotated to return
list[dict[str, Any]], but the passthrough branch returns the LLMMessage
argument unchanged. Lists are invariant in mypy, so a bare LLMMessage
(TypedDict) isn't assignable into a list[dict[str, Any]] return - this
was flagged by CI's type-checker job across all Python versions.

Widened the return type (and the local list built in the tool_calls
branch) to list[dict[str, Any] | LLMMessage], matching what the
function actually returns.

Confirmed with a local mypy run and the full openai/agent_utils test
suites (176 passed).

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-11 19:30:51 +08:00
theCyberTech
37a8267355 fix(llms/openai): convert Chat-Completions tool messages to Responses API input items
_prepare_responses_params() passed non-system messages straight through
as the Responses API "input" array without converting them. That's
fine for plain user/assistant text (matches the API's lenient "easy
input message" shape), but Chat-Completions-style assistant messages
carrying "tool_calls" and "tool"-role messages have no equivalent
shape in the Responses API - it expects standalone "function_call" and
"function_call_output" input items instead. Sending the raw
Chat-Completions shapes gets rejected with a 400 (union-type
validation failure against every Responses API input item variant).

This broke every multi-turn tool-calling conversation over
api="responses" that doesn't rely on auto_chain/previous_response_id
(i.e. the common case: resending full history each turn instead of
referencing server-side state).

Added _convert_message_to_responses_input_items() to translate:
  - assistant + tool_calls -> one function_call item per call
  - tool role               -> function_call_output item
  - everything else         -> passed through unchanged

Verified against a real multi-turn tool-calling run: the agent now
completes the full conversation and returns the actual extracted
answer instead of erroring on the second turn.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-11 18:34:42 +08:00
theCyberTech
cb78402898 test(agent_utils): cover OpenAI Responses API tool-call shape
Regression tests for is_tool_call_list() and extract_tool_call_info()
against the Responses API's flat {"id", "name", "arguments"} dict
shape, alongside existing Chat-Completions and Bedrock/Anthropic
shapes to confirm no regression there.

Confirmed these tests fail against the pre-fix version of
agent_utils.py (3 failures matching exactly the Responses API cases)
and pass against the fix in 37087b7e1.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-11 18:18:07 +08:00
theCyberTech
37087b7e1d fix(agent): recognize OpenAI Responses API tool-call shape in native tool loop
is_tool_call_list() and extract_tool_call_info() only recognized
Chat-Completions-style ({"function": {...}}), Anthropic-style
({"name", "input"}), and Gemini-style tool-call shapes. The Responses
API's function_call output items are flat dicts shaped
{"id", "name", "arguments"} with no nested "function" key and no
"input" key, so they matched none of the checks.

This caused is_tool_call_list() to misclassify a genuine tool call as
a plain text answer, so the native tool loop returned the raw
tool-call list as the agent's final output instead of executing the
tool. Even after recognizing the shape, extract_tool_call_info() would
have passed an empty arguments dict, since it only read "input" for
the dict fallback.

Verified against LLM(api="responses") with tools attached: the agent
now correctly executes the tool with the parsed arguments instead of
returning the unexecuted tool-call JSON as its answer.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-11 18:12:20 +08:00
6 changed files with 284 additions and 57 deletions

View File

@@ -747,7 +747,7 @@ class OpenAICompletion(BaseLLM):
)
@staticmethod
def _to_responses_input(message: LLMMessage) -> list[Any]:
def _to_responses_input(message: LLMMessage) -> list[dict[str, Any] | LLMMessage]:
"""Translate a chat-format message into Responses ``input`` items.
Tool calling is expressed differently by the two APIs. Chat Completions
@@ -765,18 +765,21 @@ class OpenAICompletion(BaseLLM):
role = message.get("role")
if role == "assistant" and message.get("tool_calls"):
items: list[Any] = []
items: list[dict[str, Any] | LLMMessage] = []
content = message.get("content")
if content:
items.append({"role": "assistant", "content": content})
for call in message["tool_calls"]:
function = call.get("function", {})
args = function.get("arguments", "")
items.append(
{
"type": "function_call",
"call_id": call.get("id", ""),
"call_id": call.get("id") or f"call_{id(call)}",
"name": function.get("name", ""),
"arguments": function.get("arguments", "{}"),
"arguments": args
if isinstance(args, str)
else json.dumps(args),
}
)
return items
@@ -807,7 +810,7 @@ class OpenAICompletion(BaseLLM):
- Internally-tagged tool format (flat structure)
"""
instructions: str | None = self.instructions
input_messages: list[LLMMessage] = []
input_messages: list[Any] = []
for message in messages:
if message.get("role") == "system":

View File

@@ -1404,9 +1404,9 @@ def is_tool_call_list(response: list[Any]) -> bool:
if isinstance(first_item, dict) and "name" in first_item and "input" in first_item:
return True
# OpenAI Responses API style: {"id", "name", "arguments"}, with no nested
# "function" object and no "input". Without this the list isn't recognized as
# tool calls, so the executor hands it back verbatim and the agent returns raw
# tool-call JSON instead of running the tool and producing a final answer.
# "function" object and no "input". This intentionally accepts the same broad
# shape as the Bedrock check above; only provider paths that return lists reach
# this classifier.
if (
isinstance(first_item, dict)
and "name" in first_item

View File

@@ -970,6 +970,140 @@ def test_openai_responses_api_with_system_message_extraction():
assert result.isupper() or "HELLO" in result.upper()
def test_openai_responses_api_converts_assistant_tool_calls_message():
"""Regression: assistant messages carrying tool_calls (Chat-Completions
shape) must become standalone function_call input items, since the
Responses API has no message shape for an assistant tool-call turn.
"""
llm = OpenAICompletion(model="gpt-4o-mini", api="responses")
messages = [
{"role": "user", "content": "Fetch https://example.com"},
{
"role": "assistant",
"content": None,
"tool_calls": [
{
"id": "call_abc123",
"type": "function",
"function": {
"name": "fetch_page",
"arguments": '{"url": "https://example.com"}',
},
}
],
},
]
params = llm._prepare_responses_params(messages)
assert params["input"][0] == {"role": "user", "content": "Fetch https://example.com"}
assert params["input"][1] == {
"type": "function_call",
"call_id": "call_abc123",
"name": "fetch_page",
"arguments": '{"url": "https://example.com"}',
}
def test_openai_responses_api_preserves_assistant_content_with_tool_calls():
"""Assistant text must be retained when it accompanies tool calls."""
llm = OpenAICompletion(model="gpt-4o-mini", api="responses")
messages = [
{
"role": "assistant",
"content": "I'll fetch that page now.",
"tool_calls": [
{
"type": "function",
"function": {
"name": "fetch_page",
"arguments": {"url": "https://example.com"},
},
}
],
}
]
params = llm._prepare_responses_params(messages)
assert params["input"][0] == {
"role": "assistant",
"content": "I'll fetch that page now.",
}
assert params["input"][1]["type"] == "function_call"
assert params["input"][1]["call_id"].startswith("call_")
assert params["input"][1]["arguments"] == '{"url": "https://example.com"}'
def test_openai_responses_api_converts_tool_result_message():
"""Regression: tool-role messages (Chat-Completions shape) must become
function_call_output input items for the Responses API.
"""
llm = OpenAICompletion(model="gpt-4o-mini", api="responses")
messages = [
{
"role": "tool",
"tool_call_id": "call_abc123",
"name": "fetch_page",
"content": "<html>page text</html>",
},
]
params = llm._prepare_responses_params(messages)
assert params["input"] == [
{
"type": "function_call_output",
"call_id": "call_abc123",
"output": "<html>page text</html>",
}
]
def test_openai_responses_api_multi_turn_tool_conversation_shape():
"""Regression: a full multi-turn tool-calling conversation (user ->
assistant tool_calls -> tool result) must convert entirely into valid
Responses API input items, with no leftover Chat-Completions-only keys
("tool_calls", "tool_call_id") that the Responses API would reject.
"""
llm = OpenAICompletion(model="gpt-4o-mini", api="responses")
messages = [
{"role": "user", "content": "Fetch https://example.com"},
{
"role": "assistant",
"content": None,
"tool_calls": [
{
"id": "call_abc123",
"type": "function",
"function": {
"name": "fetch_page",
"arguments": '{"url": "https://example.com"}',
},
}
],
},
{
"role": "tool",
"tool_call_id": "call_abc123",
"name": "fetch_page",
"content": "<html>page text</html>",
},
]
params = llm._prepare_responses_params(messages)
for item in params["input"]:
assert "tool_calls" not in item
assert "tool_call_id" not in item
assert params["input"][1]["type"] == "function_call"
assert params["input"][2]["type"] == "function_call_output"
@pytest.mark.vcr()
def test_openai_responses_api_streaming():
"""Test Responses API with streaming enabled."""

View File

@@ -25,6 +25,8 @@ from crewai.utilities.agent_utils import (
_split_messages_into_chunks,
convert_tools_to_openai_schema,
execute_single_native_tool_call,
extract_tool_call_info,
is_tool_call_list,
NativeToolCallResult,
parse_tool_call_args,
summarize_messages,
@@ -981,6 +983,88 @@ class TestParallelSummarizationVCR:
assert "report.pdf" in summary_msg["files"]
class TestIsToolCallListResponsesApiShape:
"""Regression tests: OpenAI Responses API tool-call dicts must be recognized.
Responses API function_call output items are flat dicts shaped
{"id", "name", "arguments"} - no nested "function" key, and "arguments"
instead of Anthropic/Bedrock-style "input".
"""
def test_responses_api_dict_is_recognized_as_tool_call(self) -> None:
response = [
{
"id": "call_abc123",
"name": "fetch_page",
"arguments": '{"url": "https://example.com"}',
}
]
assert is_tool_call_list(response) is True
def test_plain_text_answer_not_misclassified(self) -> None:
assert is_tool_call_list(["just a string, not a tool call"]) is False
def test_empty_list_returns_false(self) -> None:
assert is_tool_call_list([]) is False
def test_chat_completions_style_still_recognized(self) -> None:
response = [{"function": {"name": "fetch_page", "arguments": "{}"}}]
assert is_tool_call_list(response) is True
def test_bedrock_anthropic_style_still_recognized(self) -> None:
response = [{"name": "fetch_page", "input": {"url": "https://example.com"}}]
assert is_tool_call_list(response) is True
class TestExtractToolCallInfoResponsesApiShape:
"""Regression tests: extract_tool_call_info must parse Responses API dicts."""
def test_responses_api_dict_extracts_real_arguments(self) -> None:
tool_call = {
"id": "call_abc123",
"name": "fetch_page",
"arguments": '{"url": "https://example.com"}',
}
result = extract_tool_call_info(tool_call)
assert result is not None
call_id, func_name, func_args = result
assert call_id == "call_abc123"
assert func_name == "fetch_page"
assert func_args == '{"url": "https://example.com"}'
def test_responses_api_dict_does_not_return_empty_args(self) -> None:
tool_call = {
"id": "call_xyz",
"name": "fetch_page",
"arguments": '{"url": "https://example.com"}',
}
_, _, func_args = extract_tool_call_info(tool_call)
assert func_args != {}
def test_bedrock_anthropic_style_still_uses_input(self) -> None:
tool_call = {"name": "fetch_page", "input": {"url": "https://example.com"}}
_, func_name, func_args = extract_tool_call_info(tool_call)
assert func_name == "fetch_page"
assert func_args == {"url": "https://example.com"}
def test_chat_completions_style_still_uses_nested_function(self) -> None:
tool_call = {
"id": "call_1",
"function": {"name": "fetch_page", "arguments": "{}"},
}
_, func_name, func_args = extract_tool_call_info(tool_call)
assert func_name == "fetch_page"
assert func_args == "{}"
def test_non_dict_unrecognized_shape_returns_none(self) -> None:
assert extract_tool_call_info("just a string") is None
def test_unrecognized_dict_shape_returns_empty_name_and_args(self) -> None:
call_id, func_name, func_args = extract_tool_call_info({"unrelated": "data"})
assert func_name == ""
assert func_args == {}
class TestParseToolCallArgs:
"""Unit tests for parse_tool_call_args."""

View File

@@ -182,6 +182,10 @@ exclude-newer-package = { pypdf = "2026-06-24T00:00:00Z", msgpack = "2026-06-20T
# langchain-text-splitters <1.1.2 has GHSA-fv5p-p927-qmxr (SSRF bypass in split_text_from_url).
# transformers 4.57.6 has CVE-2026-1839; force 5.4+ (docling 2.84 allows huggingface-hub>=1).
# cryptography 46.0.6 has CVE-2026-39892; force 46.0.7+.
# cryptography <50.0.0 has GHSA-m2h6-j472-rp4c (wildcard DNS name acceptance bypass),
# GHSA-g6cj-pr64-35w5 (Bleichenbacher oracle in PKCS#7 EnvelopedData decryption),
# GHSA-jwv3-5hgf-82ww (exponential path-building via duplicate self-signed intermediates);
# all fixed in 50.0.0; force 50.0.0+.
# pypdf <6.10.2 has GHSA-4pxv-j86v-mhcw, GHSA-7gw9-cf7v-778f, GHSA-x284-j5p8-9c5p.
# pypdf <6.14.2 has GHSA-jm82-fx9c-mx94 and GHSA-5qjq-93h5-hrgp/GHSA-55h5-xmcq-c37v/GHSA-g867-7843-wf8q/GHSA-5xf7-4p34-54qr; force 6.14.2+.
# uv <0.11.15 has GHSA-4gg8-gxpx-9rph (and earlier GHSA-pjjw-68hj-v9mw); force 0.11.15+.
@@ -200,6 +204,8 @@ exclude-newer-package = { pypdf = "2026-06-24T00:00:00Z", msgpack = "2026-06-20T
# authlib <1.6.12 has GHSA-jj8c-mmj3-mmgv (CSRF bypass in cache-based state storage) and PYSEC-2026-188.
# pip 26.1.1 has PYSEC-2026-196; force 26.1.2+.
# aiohttp <=3.13.x has GHSA-jg22-mg44-37j8, GHSA-hg6j-4rv6-33pg; fixed in 3.14.0; force 3.14.0+.
# aiohttp <3.14.2 has GHSA-mq44-7p77-q5h7 (WebSocket client accepts deflate frames without negotiation),
# GHSA-mfx4-hv73-q22v, GHSA-cq5v-8q36-5273; all fixed in 3.14.2; force 3.14.2+.
# docling-core 2.74.0 has GHSA-j5xp-7m2f-49jv, GHSA-jmmv-h3mp-59v8; force 2.74.1+.
# pip <26.1.1 has GHSA-58qw-9mgm-455v (archive handling); OSV considers 26.1.1 unaffected.
# paramiko <5.0.0 has GHSA-r374-rxx8-8654 (SHA-1 in rsakey.py); OSV considers 5.0.0 unaffected. Transitive via composio-core.
@@ -223,7 +229,7 @@ override-dependencies = [
"langchain-text-splitters>=1.1.2,<2",
"urllib3>=2.7.0",
"transformers>=5.4.0; python_version >= '3.10'",
"cryptography>=46.0.7",
"cryptography>=50.0.0",
"pypdf>=6.14.2,<7",
"uv>=0.11.15,<1",
"python-multipart>=0.0.27,<1",
@@ -232,7 +238,7 @@ override-dependencies = [
"langsmith>=0.8.18,<1",
"authlib>=1.6.12",
"pip>=26.1.2",
"aiohttp>=3.14.0",
"aiohttp>=3.14.2",
# [chunking] carried here because override-dependencies replace the whole
# requirement; without it the docling extra's chunking deps get stripped.
"docling-core[chunking]>=2.74.1",

94
uv.lock generated
View File

@@ -1056,7 +1056,7 @@ name = "coloredlogs"
version = "15.0.1"
source = { registry = "https://pypi.org/simple" }
dependencies = [
{ name = "humanfriendly", marker = "python_full_version < '3.11'" },
{ name = "humanfriendly" },
]
sdist = { url = "https://files.pythonhosted.org/packages/cc/c7/eed8f27100517e8c0e6b923d5f0845d0cb99763da6fdee00478f91db7325/coloredlogs-15.0.1.tar.gz", hash = "sha256:7c991aa71a4577af2f82600d8f8f3a89f936baeaf9b50a9c197da014e5bf16b0", size = 278520, upload-time = "2021-06-11T10:22:45.202Z" }
wheels = [
@@ -1154,7 +1154,7 @@ resolution-markers = [
"python_full_version < '3.11' and platform_machine == 's390x'",
]
dependencies = [
{ name = "numpy", version = "2.2.6", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.11'" },
{ name = "numpy", version = "2.2.6", source = { registry = "https://pypi.org/simple" } },
]
sdist = { url = "https://files.pythonhosted.org/packages/66/54/eb9bfc647b19f2009dd5c7f5ec51c4e6ca831725f1aea7a993034f483147/contourpy-1.3.2.tar.gz", hash = "sha256:b6945942715a034c671b7fc54f9588126b0b8bf23db2696e3ca8328f3ff0ab54", size = 13466130, upload-time = "2025-04-15T17:47:53.79Z" }
wheels = [
@@ -1229,7 +1229,7 @@ resolution-markers = [
"python_full_version == '3.11.*' and platform_machine == 's390x'",
]
dependencies = [
{ name = "numpy", version = "2.4.6", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.11'" },
{ name = "numpy", version = "2.4.6", source = { registry = "https://pypi.org/simple" } },
]
sdist = { url = "https://files.pythonhosted.org/packages/58/01/1253e6698a07380cd31a736d248a3f2a50a7c88779a1813da27503cadc2a/contourpy-1.3.3.tar.gz", hash = "sha256:083e12155b210502d0bca491432bb04d56dc3432f95a979b429f2848c3dbe880", size = 13466174, upload-time = "2025-07-26T12:03:12.549Z" }
wheels = [
@@ -1883,34 +1883,34 @@ wheels = [
[package.optional-dependencies]
cudart = [
{ name = "nvidia-cuda-runtime", marker = "sys_platform == 'linux' or sys_platform == 'win32'" },
{ name = "nvidia-cuda-runtime" },
]
cufft = [
{ name = "nvidia-cufft", marker = "sys_platform == 'linux' or sys_platform == 'win32'" },
{ name = "nvidia-cufft" },
]
cufile = [
{ name = "nvidia-cufile", marker = "sys_platform == 'linux'" },
{ name = "nvidia-cufile" },
]
cupti = [
{ name = "nvidia-cuda-cupti", marker = "sys_platform == 'linux' or sys_platform == 'win32'" },
{ name = "nvidia-cuda-cupti" },
]
curand = [
{ name = "nvidia-curand", marker = "sys_platform == 'linux' or sys_platform == 'win32'" },
{ name = "nvidia-curand" },
]
cusolver = [
{ name = "nvidia-cusolver", marker = "sys_platform == 'linux' or sys_platform == 'win32'" },
{ name = "nvidia-cusolver" },
]
cusparse = [
{ name = "nvidia-cusparse", marker = "sys_platform == 'linux' or sys_platform == 'win32'" },
{ name = "nvidia-cusparse" },
]
nvjitlink = [
{ name = "nvidia-nvjitlink", marker = "sys_platform == 'linux' or sys_platform == 'win32'" },
{ name = "nvidia-nvjitlink" },
]
nvrtc = [
{ name = "nvidia-cuda-nvrtc", marker = "sys_platform == 'linux' or sys_platform == 'win32'" },
{ name = "nvidia-cuda-nvrtc" },
]
nvtx = [
{ name = "nvidia-nvtx", marker = "sys_platform == 'linux' or sys_platform == 'win32'" },
{ name = "nvidia-nvtx" },
]
[[package]]
@@ -2435,7 +2435,7 @@ name = "exceptiongroup"
version = "1.3.1"
source = { registry = "https://pypi.org/simple" }
dependencies = [
{ name = "typing-extensions", marker = "python_full_version < '3.11'" },
{ name = "typing-extensions" },
]
sdist = { url = "https://files.pythonhosted.org/packages/50/79/66800aadf48771f6b62f7eb014e352e5d06856655206165d775e675a02c9/exceptiongroup-1.3.1.tar.gz", hash = "sha256:8b412432c6055b0b7d14c310000ae93352ed6754f70fa8f7c34141f91c4e3219", size = 30371, upload-time = "2025-11-21T23:01:54.787Z" }
wheels = [
@@ -3024,8 +3024,8 @@ name = "grpcio-health-checking"
version = "1.71.2"
source = { registry = "https://pypi.org/simple" }
dependencies = [
{ name = "grpcio", marker = "python_full_version < '3.11' or (python_full_version >= '3.13' and platform_machine != 's390x')" },
{ name = "protobuf", marker = "python_full_version < '3.11' or (python_full_version >= '3.13' and platform_machine != 's390x')" },
{ name = "grpcio" },
{ name = "protobuf" },
]
sdist = { url = "https://files.pythonhosted.org/packages/53/86/20994347ef36b7626fb74539f13128100dd8b7eaac67efc063264e6cdc80/grpcio_health_checking-1.71.2.tar.gz", hash = "sha256:1c21ece88c641932f432b573ef504b20603bdf030ad4e1ec35dd7fdb4ea02637", size = 16770, upload-time = "2025-06-28T04:24:08.768Z" }
wheels = [
@@ -3229,7 +3229,7 @@ name = "humanfriendly"
version = "10.0"
source = { registry = "https://pypi.org/simple" }
dependencies = [
{ name = "pyreadline3", marker = "python_full_version < '3.11' and sys_platform == 'win32'" },
{ name = "pyreadline3", marker = "sys_platform == 'win32'" },
]
sdist = { url = "https://files.pythonhosted.org/packages/cc/3f/2c29224acb2e2df4d2046e4c73ee2662023c58ff5b113c4c1adac0886c43/humanfriendly-10.0.tar.gz", hash = "sha256:6b0b831ce8f15f7300721aa49829fc4e83921a9a301cc7f606be6686a2288ddc", size = 360702, upload-time = "2021-09-17T21:40:43.31Z" }
wheels = [
@@ -4466,10 +4466,10 @@ resolution-markers = [
"python_full_version < '3.11' and platform_machine == 's390x'",
]
dependencies = [
{ name = "jsonref", marker = "python_full_version < '3.12'" },
{ name = "mcp", extra = ["ws"], marker = "python_full_version < '3.12'" },
{ name = "pydantic", marker = "python_full_version < '3.12'" },
{ name = "python-dotenv", marker = "python_full_version < '3.12'" },
{ name = "jsonref" },
{ name = "mcp", extra = ["ws"] },
{ name = "pydantic" },
{ name = "python-dotenv" },
]
sdist = { url = "https://files.pythonhosted.org/packages/d0/28/64fc666fa5d86bb1b048c167975d4ea19210f9f8571b64b26563739774ac/mcpadapt-0.1.19.tar.gz", hash = "sha256:dfab84fc75cc84a49a40bd61079773b1faf840227b74b82c71a7755b9c1957c5", size = 4227721, upload-time = "2025-10-16T07:11:56.736Z" }
wheels = [
@@ -4487,10 +4487,10 @@ resolution-markers = [
"python_full_version == '3.12.*' and platform_machine == 's390x'",
]
dependencies = [
{ name = "jsonref", marker = "python_full_version >= '3.12'" },
{ name = "mcp", extra = ["ws"], marker = "python_full_version >= '3.12'" },
{ name = "pydantic", marker = "python_full_version >= '3.12'" },
{ name = "python-dotenv", marker = "python_full_version >= '3.12'" },
{ name = "jsonref" },
{ name = "mcp", extra = ["ws"] },
{ name = "pydantic" },
{ name = "python-dotenv" },
]
sdist = { url = "https://files.pythonhosted.org/packages/e3/71/1bbbe157e55d30ab4a74fa878f6942cc0586e9820f03e03451a3d2297e9b/mcpadapt-0.1.20.tar.gz", hash = "sha256:4047c0da61e481dd0673a48936a427da9e6547c6cf0d580ff4e4761dcf058ed1", size = 4203656, upload-time = "2025-10-24T15:35:02.135Z" }
wheels = [
@@ -5506,12 +5506,12 @@ name = "onnxruntime"
version = "1.23.2"
source = { registry = "https://pypi.org/simple" }
dependencies = [
{ name = "coloredlogs", marker = "python_full_version < '3.11'" },
{ name = "flatbuffers", marker = "python_full_version < '3.11'" },
{ name = "numpy", version = "2.2.6", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.11'" },
{ name = "packaging", marker = "python_full_version < '3.11'" },
{ name = "protobuf", marker = "python_full_version < '3.11'" },
{ name = "sympy", marker = "python_full_version < '3.11'" },
{ name = "coloredlogs" },
{ name = "flatbuffers" },
{ name = "numpy", version = "2.2.6", source = { registry = "https://pypi.org/simple" } },
{ name = "packaging" },
{ name = "protobuf" },
{ name = "sympy" },
]
wheels = [
{ url = "https://files.pythonhosted.org/packages/35/d6/311b1afea060015b56c742f3531168c1644650767f27ef40062569960587/onnxruntime-1.23.2-cp310-cp310-macosx_13_0_arm64.whl", hash = "sha256:a7730122afe186a784660f6ec5807138bf9d792fa1df76556b27307ea9ebcbe3", size = 17195934, upload-time = "2025-10-27T23:06:14.143Z" },
@@ -8159,7 +8159,7 @@ resolution-markers = [
"python_full_version < '3.11' and platform_machine == 's390x'",
]
dependencies = [
{ name = "numpy", version = "2.2.6", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.11'" },
{ name = "numpy", version = "2.2.6", source = { registry = "https://pypi.org/simple" } },
]
sdist = { url = "https://files.pythonhosted.org/packages/0f/37/6964b830433e654ec7485e45a00fc9a27cf868d622838f6b6d9c5ec0d532/scipy-1.15.3.tar.gz", hash = "sha256:eae3cf522bc7df64b42cad3925c876e1b0b6c35c1337c93e12c0f366f55b0eaf", size = 59419214, upload-time = "2025-05-08T16:13:05.955Z" }
wheels = [
@@ -8223,7 +8223,7 @@ resolution-markers = [
"python_full_version == '3.11.*' and platform_machine == 's390x'",
]
dependencies = [
{ name = "numpy", version = "2.4.6", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.11'" },
{ name = "numpy", version = "2.4.6", source = { registry = "https://pypi.org/simple" } },
]
sdist = { url = "https://files.pythonhosted.org/packages/7a/97/5a3609c4f8d58b039179648e62dd220f89864f56f7357f5d4f45c29eb2cc/scipy-1.17.1.tar.gz", hash = "sha256:95d8e012d8cb8816c226aef832200b1d45109ed4464303e997c5b13122b297c0", size = 30573822, upload-time = "2026-02-23T00:26:24.851Z" }
wheels = [
@@ -9854,13 +9854,13 @@ resolution-markers = [
"python_full_version < '3.11' and platform_machine == 's390x'",
]
dependencies = [
{ name = "authlib", marker = "python_full_version < '3.11' or (python_full_version >= '3.13' and platform_machine != 's390x')" },
{ name = "deprecation", marker = "python_full_version < '3.11' or (python_full_version >= '3.13' and platform_machine != 's390x')" },
{ name = "grpcio", marker = "python_full_version < '3.11' or (python_full_version >= '3.13' and platform_machine != 's390x')" },
{ name = "grpcio-health-checking", marker = "python_full_version < '3.11' or (python_full_version >= '3.13' and platform_machine != 's390x')" },
{ name = "httpx", marker = "python_full_version < '3.11' or (python_full_version >= '3.13' and platform_machine != 's390x')" },
{ name = "pydantic", marker = "python_full_version < '3.11' or (python_full_version >= '3.13' and platform_machine != 's390x')" },
{ name = "validators", marker = "python_full_version < '3.11' or (python_full_version >= '3.13' and platform_machine != 's390x')" },
{ name = "authlib" },
{ name = "deprecation" },
{ name = "grpcio" },
{ name = "grpcio-health-checking" },
{ name = "httpx" },
{ name = "pydantic" },
{ name = "validators" },
]
sdist = { url = "https://files.pythonhosted.org/packages/a7/b9/7b9e05cf923743aa1479afcd85c48ebca82d031c3c3a5d02b1b3fcb52eb9/weaviate_client-4.16.2.tar.gz", hash = "sha256:eb7107a3221a5ad68d604cafc65195bd925a9709512ea0b6fe0dd212b0678fab", size = 681321, upload-time = "2025-07-22T09:10:48.79Z" }
wheels = [
@@ -9879,13 +9879,13 @@ resolution-markers = [
"python_full_version == '3.11.*' and platform_machine == 's390x'",
]
dependencies = [
{ name = "authlib", marker = "(python_full_version >= '3.11' and python_full_version < '3.13') or (python_full_version >= '3.11' and platform_machine == 's390x')" },
{ name = "grpcio", marker = "(python_full_version >= '3.11' and python_full_version < '3.13') or (python_full_version >= '3.11' and platform_machine == 's390x')" },
{ name = "httpx", marker = "(python_full_version >= '3.11' and python_full_version < '3.13') or (python_full_version >= '3.11' and platform_machine == 's390x')" },
{ name = "packaging", marker = "(python_full_version >= '3.11' and python_full_version < '3.13') or (python_full_version >= '3.11' and platform_machine == 's390x')" },
{ name = "protobuf", marker = "(python_full_version >= '3.11' and python_full_version < '3.13') or (python_full_version >= '3.11' and platform_machine == 's390x')" },
{ name = "pydantic", marker = "(python_full_version >= '3.11' and python_full_version < '3.13') or (python_full_version >= '3.11' and platform_machine == 's390x')" },
{ name = "validators", marker = "(python_full_version >= '3.11' and python_full_version < '3.13') or (python_full_version >= '3.11' and platform_machine == 's390x')" },
{ name = "authlib" },
{ name = "grpcio" },
{ name = "httpx" },
{ name = "packaging" },
{ name = "protobuf" },
{ name = "pydantic" },
{ name = "validators" },
]
sdist = { url = "https://files.pythonhosted.org/packages/2b/b8/103f3aaa246d4e932f4cfeb846e51436966f2aeedf60c2665a3fc51a975a/weaviate_client-4.21.3.tar.gz", hash = "sha256:d7b1f2b0cecbc747e9427f4e3b9463cdfee090746bfbbd40e59cfa25ea2afd4a", size = 847895, upload-time = "2026-06-02T13:03:51.598Z" }
wheels = [