From 166758cb0f2f079157671f79362e34c6b2eecceb Mon Sep 17 00:00:00 2001 From: rayhan Date: Wed, 5 Aug 2026 02:52:30 +0100 Subject: [PATCH] fix: migrate mistralai to 2.x and remediate CVE-2025-67221 (orjson) (#17810) ## Summary Migrates `mistralai` from `==0.4.2` to `>=2.7.2,<3.0.0` to unblock the orjson CVE fix. The old SDK pinned `orjson>=3.9.10,<3.11`, preventing upgrade to the patched version. | CVE | Severity | Package | Installed | Fixed in | |---|---|---|---|---| | CVE-2025-67221 | HIGH | orjson | 3.10.18 | 3.11.6 | `mistralai` 2.x (the current maintained version) drops the orjson dependency entirely. Added `orjson>=3.11.6` to `constraint-dependencies` to pin the floor for remaining parent packages (`langgraph-sdk`, `langsmith`, `ranx`). --- pyproject.toml | 6 +- rag/llm/chat_model.py | 16 +++-- rag/llm/embedding_model.py | 8 +-- .../unit_test/rag/llm/test_embedding_model.py | 8 +-- uv.lock | 68 +++++++++++++------ 5 files changed, 68 insertions(+), 38 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index 5badfc8cbf..d9f0e1e214 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -69,7 +69,7 @@ dependencies = [ "mcp>=1.28.1,<2.0.0", "mini-racer>=0.12.4,<0.13.0", "minio==7.2.4", - "mistralai==0.4.2", + "mistralai>=2.7.2,<3.0.0", "mysql-connector-python>=9.0.0,<10.0.0", "moodlepy>=0.23.0", "mypy-boto3-s3==1.40.26", @@ -236,6 +236,10 @@ constraint-dependencies = [ # CVE-2026-59939: httplib2 < 0.32.0 vulnerable; pulled in transitively via # google-api-python-client, google-auth-httplib2 "httplib2>=0.32.0", + # CVE-2025-67221: orjson < 3.11.6 vulnerable; pulled in transitively via + # langgraph-sdk, langsmith, ranx. Previously blocked by mistralai==0.4.2 + # pinning orjson<3.11 + "orjson>=3.11.6", ] exclude-dependencies = [ # crawl4ai>=0.8.6 depends on unclecode-litellm, which installs the same diff --git a/rag/llm/chat_model.py b/rag/llm/chat_model.py index 9a4d972782..69e431d68a 100644 --- a/rag/llm/chat_model.py +++ b/rag/llm/chat_model.py @@ -27,7 +27,6 @@ from urllib.parse import urljoin import json_repair from json.decoder import JSONDecodeError import litellm -import openai from openai import AsyncOpenAI, OpenAI from enum import StrEnum @@ -994,9 +993,9 @@ class MistralChat(Base): def __init__(self, key, model_name, base_url=None, **kwargs): super().__init__(key, model_name, base_url=base_url, **kwargs) - from mistralai.client import MistralClient + from mistralai.client import Mistral - self.client = MistralClient(api_key=key) + self.client = Mistral(api_key=key) self.model_name = model_name def _clean_conf(self, gen_conf): @@ -1008,7 +1007,7 @@ class MistralChat(Base): def _chat(self, history, gen_conf=None, **kwargs): gen_conf = dict(gen_conf or {}) gen_conf = self._clean_conf(gen_conf) - response = self.client.chat(model=self.model_name, messages=history, **gen_conf) + response = self.client.chat.complete(model=self.model_name, messages=history, **gen_conf) if not response.choices: raise ValueError("LLM returned empty response") # pact: guard empty choices list ans = response.choices[0].message.content @@ -1020,6 +1019,8 @@ class MistralChat(Base): return ans, total_token_count_from_response(response) def chat_streamly(self, system, history, gen_conf=None, **kwargs): + from mistralai.client.errors import MistralError + gen_conf = dict(gen_conf or {}) if system and history and history[0].get("role") != "system": history.insert(0, {"role": "system", "content": system}) @@ -1027,8 +1028,9 @@ class MistralChat(Base): ans = "" total_tokens = 0 try: - response = self.client.chat_stream(model=self.model_name, messages=history, **gen_conf, **kwargs) - for resp in response: + response = self.client.chat.stream(model=self.model_name, messages=history, **gen_conf, **kwargs) + for event in response: + resp = event.data if not resp.choices or not resp.choices[0].delta.content: continue ans = resp.choices[0].delta.content @@ -1040,7 +1042,7 @@ class MistralChat(Base): ans += LENGTH_NOTIFICATION_EN yield ans - except openai.APIError as e: + except MistralError as e: yield ans + "\n**ERROR**: " + str(e) yield total_tokens diff --git a/rag/llm/embedding_model.py b/rag/llm/embedding_model.py index a1c137dfe8..e4790e0222 100644 --- a/rag/llm/embedding_model.py +++ b/rag/llm/embedding_model.py @@ -611,9 +611,9 @@ class MistralEmbed(Base): _FACTORY_NAME = "Mistral" def __init__(self, key, model_name="mistral-embed", base_url=None): - from mistralai.client import MistralClient + from mistralai.client import Mistral - self.client = MistralClient(api_key=key) + self.client = Mistral(api_key=key) self.model_name = model_name def encode(self, texts: list): @@ -628,7 +628,7 @@ class MistralEmbed(Base): retry_max = 5 while retry_max > 0: try: - res = self.client.embeddings(input=texts[i : i + batch_size], model=self.model_name) + res = self.client.embeddings.create(inputs=texts[i : i + batch_size], model=self.model_name) ress.extend([d.embedding for d in res.data]) token_count += total_token_count_from_response(res) break @@ -648,7 +648,7 @@ class MistralEmbed(Base): retry_max = 5 while retry_max > 0: try: - res = self.client.embeddings(input=[truncate(text, DEFAULT_MAX_TOKENS)], model=self.model_name) + res = self.client.embeddings.create(inputs=[truncate(text, DEFAULT_MAX_TOKENS)], model=self.model_name) return np.array(res.data[0].embedding), total_token_count_from_response(res) except Exception as _e: if retry_max == 1: diff --git a/test/unit_test/rag/llm/test_embedding_model.py b/test/unit_test/rag/llm/test_embedding_model.py index cbd0d0d7ee..b548c82422 100644 --- a/test/unit_test/rag/llm/test_embedding_model.py +++ b/test/unit_test/rag/llm/test_embedding_model.py @@ -223,15 +223,15 @@ class TestTruncationBoundary: embed.model_name = "mistral-embed" captured = {} - def _embeddings(input, model): - captured["input"] = input + def _embeddings_create(inputs, model): + captured["inputs"] = inputs return _OpenAIResp([[0.0, 0.0]], total_tokens=1) embed.client = MagicMock() - embed.client.embeddings = MagicMock(side_effect=_embeddings) + embed.client.embeddings.create = MagicMock(side_effect=_embeddings_create) huge = "word " * 12000 embed.encode([huge]) - assert num_tokens_from_string(captured["input"][0]) <= DEFAULT_MAX_TOKENS + assert num_tokens_from_string(captured["inputs"][0]) <= DEFAULT_MAX_TOKENS # --------------------------------------------------------------------------- # diff --git a/uv.lock b/uv.lock index 4309f06d37..2b73825311 100644 --- a/uv.lock +++ b/uv.lock @@ -14,6 +14,7 @@ constraints = [ { name = "lxml", specifier = ">=6.1.1" }, { name = "lxml-html-clean", specifier = ">=0.4.5" }, { name = "nltk", specifier = ">=3.10.0" }, + { name = "orjson", specifier = ">=3.11.6" }, { name = "protobuf", specifier = ">=5.29.6" }, { name = "pyasn1", specifier = ">=0.6.4" }, { name = "trio", specifier = ">=0.26.0", index = "https://pypi.org/simple" }, @@ -1880,6 +1881,15 @@ wheels = [ { url = "https://mirrors.aliyun.com/pypi/packages/c1/8b/5fe2cc11fee489817272089c4203e679c63b570a5aaeb18d852ae3cbba6a/et_xmlfile-2.0.0-py3-none-any.whl", hash = "sha256:7a91720bc756843502c3b7504c77b8fe44217c85c537d85037f0f536151b2caa" }, ] +[[package]] +name = "eval-type-backport" +version = "0.4.0" +source = { registry = "https://mirrors.aliyun.com/pypi/simple" } +sdist = { url = "https://mirrors.aliyun.com/pypi/packages/1c/15/273a4baf8248d6d76220723c3caf039d283774b31a7c46ba686120145b76/eval_type_backport-0.4.0.tar.gz", hash = "sha256:8397d25e6524c2e67b9576bb0636be27dea2192017711220c534ec2de921e9b0" } +wheels = [ + { url = "https://mirrors.aliyun.com/pypi/packages/50/a7/bb99bf5e6f78736ddb53480f2c3ff3702ffe2196a7c5e1661c03081d398e/eval_type_backport-0.4.0-py3-none-any.whl", hash = "sha256:ad5e2a8db71b6696a56eafb938b0f5a337d3217f256b8e158b469422b4772b20" }, +] + [[package]] name = "events" version = "0.5" @@ -3138,6 +3148,15 @@ version = "0.82.2" source = { registry = "https://mirrors.aliyun.com/pypi/simple" } sdist = { url = "https://mirrors.aliyun.com/pypi/packages/cf/a1/693351acd0a9edca4de9153372a65e75398898ea7f8a5c722ab00f464929/jsonpath-0.82.2.tar.gz", hash = "sha256:d87ef2bcbcded68ee96bc34c1809b69457ecec9b0c4dd471658a12bd391002d1" } +[[package]] +name = "jsonpath-python" +version = "1.1.6" +source = { registry = "https://mirrors.aliyun.com/pypi/simple" } +sdist = { url = "https://mirrors.aliyun.com/pypi/packages/98/18/4ca8742534a5993ff383f7602e325ce2d5d7cc93d72ac5e1cdedbea8a458/jsonpath_python-1.1.6.tar.gz", hash = "sha256:dded9932b4ec41fb8726e09c83afa4e6be618f938c2db287cc2a81723c639671" } +wheels = [ + { url = "https://mirrors.aliyun.com/pypi/packages/55/8a/1270a6803bd821cbfcdda387eaa13cb41a7b1f7b9bd145979b3bfb9d6cb7/jsonpath_python-1.1.6-py3-none-any.whl", hash = "sha256:a1c50afd8d3fbbaf47a4873bc890dcb3c15da96f5c020327977d844d8731a2d4" }, +] + [[package]] name = "jsonpointer" version = "3.1.1" @@ -3678,16 +3697,21 @@ wheels = [ [[package]] name = "mistralai" -version = "0.4.2" +version = "2.8.0" source = { registry = "https://mirrors.aliyun.com/pypi/simple" } dependencies = [ + { name = "eval-type-backport" }, { name = "httpx" }, - { name = "orjson" }, + { name = "jsonpath-python" }, + { name = "opentelemetry-api" }, + { name = "opentelemetry-semantic-conventions" }, { name = "pydantic" }, + { name = "python-dateutil" }, + { name = "typing-inspection" }, ] -sdist = { url = "https://mirrors.aliyun.com/pypi/packages/fa/20/4204f461588310b3a7ffbbbb7fa573493dc1c8185d376ee72516c04575bf/mistralai-0.4.2.tar.gz", hash = "sha256:5eb656710517168ae053f9847b0bb7f617eda07f1f93f946ad6c91a4d407fd93" } +sdist = { url = "https://mirrors.aliyun.com/pypi/packages/38/1b/29b202ea8f0ff72fcc1b8049dbd3c54d3ca719dff7f4fb0a9ac5d727612f/mistralai-2.8.0.tar.gz", hash = "sha256:fea2d131850bbe010133494e9eb065624afe752dd032a7260ba507ab5a36953a" } wheels = [ - { url = "https://mirrors.aliyun.com/pypi/packages/4f/fe/79dad76b8d94b62d9e2aab8446183190e1dc384c617d06c3c93307850e11/mistralai-0.4.2-py3-none-any.whl", hash = "sha256:63c98eea139585f0a3b2c4c6c09c453738bac3958055e6f2362d3866e96b0168" }, + { url = "https://mirrors.aliyun.com/pypi/packages/0e/75/ccfcf875de1265a0d1b5b523877b3a03e427f22de94d8bea3ce252640ac9/mistralai-2.8.0-py3-none-any.whl", hash = "sha256:1514a776946f2a7fa04281a11bcccb218397a2bf0fdc892979c8900b422e13df" }, ] [[package]] @@ -4261,25 +4285,25 @@ wheels = [ [[package]] name = "orjson" -version = "3.10.18" +version = "3.11.9" source = { registry = "https://mirrors.aliyun.com/pypi/simple" } -sdist = { url = "https://mirrors.aliyun.com/pypi/packages/81/0b/fea456a3ffe74e70ba30e01ec183a9b26bec4d497f61dcfce1b601059c60/orjson-3.10.18.tar.gz", hash = "sha256:e8da3947d92123eda795b68228cafe2724815621fe35e8e320a9e9593a4bcd53" } +sdist = { url = "https://mirrors.aliyun.com/pypi/packages/7e/0c/964746fcafbd16f8ff53219ad9f6b412b34f345c75f384ad434ceaadb538/orjson-3.11.9.tar.gz", hash = "sha256:4fef17e1f8722c11587a6ef18e35902450221da0028e65dbaaa543619e68e48f" } wheels = [ - { url = "https://mirrors.aliyun.com/pypi/packages/04/f0/8aedb6574b68096f3be8f74c0b56d36fd94bcf47e6c7ed47a7bd1474aaa8/orjson-3.10.18-cp313-cp313-macosx_10_15_x86_64.macosx_11_0_arm64.macosx_10_15_universal2.whl", hash = "sha256:69c34b9441b863175cc6a01f2935de994025e773f814412030f269da4f7be147" }, - { url = "https://mirrors.aliyun.com/pypi/packages/bc/f7/7118f965541aeac6844fcb18d6988e111ac0d349c9b80cda53583e758908/orjson-3.10.18-cp313-cp313-macosx_15_0_arm64.whl", hash = "sha256:1ebeda919725f9dbdb269f59bc94f861afbe2a27dce5608cdba2d92772364d1c" }, - { url = "https://mirrors.aliyun.com/pypi/packages/fb/d9/839637cc06eaf528dd8127b36004247bf56e064501f68df9ee6fd56a88ee/orjson-3.10.18-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5adf5f4eed520a4959d29ea80192fa626ab9a20b2ea13f8f6dc58644f6927103" }, - { url = "https://mirrors.aliyun.com/pypi/packages/2b/6d/f226ecfef31a1f0e7d6bf9a31a0bbaf384c7cbe3fce49cc9c2acc51f902a/orjson-3.10.18-cp313-cp313-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:7592bb48a214e18cd670974f289520f12b7aed1fa0b2e2616b8ed9e069e08595" }, - { url = "https://mirrors.aliyun.com/pypi/packages/73/2d/371513d04143c85b681cf8f3bce743656eb5b640cb1f461dad750ac4b4d4/orjson-3.10.18-cp313-cp313-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f872bef9f042734110642b7a11937440797ace8c87527de25e0c53558b579ccc" }, - { url = "https://mirrors.aliyun.com/pypi/packages/69/cb/a4d37a30507b7a59bdc484e4a3253c8141bf756d4e13fcc1da760a0b00cb/orjson-3.10.18-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:0315317601149c244cb3ecef246ef5861a64824ccbcb8018d32c66a60a84ffbc" }, - { url = "https://mirrors.aliyun.com/pypi/packages/1e/ae/cd10883c48d912d216d541eb3db8b2433415fde67f620afe6f311f5cd2ca/orjson-3.10.18-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:e0da26957e77e9e55a6c2ce2e7182a36a6f6b180ab7189315cb0995ec362e049" }, - { url = "https://mirrors.aliyun.com/pypi/packages/6d/4c/2bda09855c6b5f2c055034c9eda1529967b042ff8d81a05005115c4e6772/orjson-3.10.18-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bb70d489bc79b7519e5803e2cc4c72343c9dc1154258adf2f8925d0b60da7c58" }, - { url = "https://mirrors.aliyun.com/pypi/packages/13/4a/35971fd809a8896731930a80dfff0b8ff48eeb5d8b57bb4d0d525160017f/orjson-3.10.18-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:e9e86a6af31b92299b00736c89caf63816f70a4001e750bda179e15564d7a034" }, - { url = "https://mirrors.aliyun.com/pypi/packages/99/70/0fa9e6310cda98365629182486ff37a1c6578e34c33992df271a476ea1cd/orjson-3.10.18-cp313-cp313-musllinux_1_2_armv7l.whl", hash = "sha256:c382a5c0b5931a5fc5405053d36c1ce3fd561694738626c77ae0b1dfc0242ca1" }, - { url = "https://mirrors.aliyun.com/pypi/packages/32/cb/990a0e88498babddb74fb97855ae4fbd22a82960e9b06eab5775cac435da/orjson-3.10.18-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:8e4b2ae732431127171b875cb2668f883e1234711d3c147ffd69fe5be51a8012" }, - { url = "https://mirrors.aliyun.com/pypi/packages/92/44/473248c3305bf782a384ed50dd8bc2d3cde1543d107138fd99b707480ca1/orjson-3.10.18-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:2d808e34ddb24fc29a4d4041dcfafbae13e129c93509b847b14432717d94b44f" }, - { url = "https://mirrors.aliyun.com/pypi/packages/ad/fd/7f1d3edd4ffcd944a6a40e9f88af2197b619c931ac4d3cfba4798d4d3815/orjson-3.10.18-cp313-cp313-win32.whl", hash = "sha256:ad8eacbb5d904d5591f27dee4031e2c1db43d559edb8f91778efd642d70e6bea" }, - { url = "https://mirrors.aliyun.com/pypi/packages/4b/03/c75c6ad46be41c16f4cfe0352a2d1450546f3c09ad2c9d341110cd87b025/orjson-3.10.18-cp313-cp313-win_amd64.whl", hash = "sha256:aed411bcb68bf62e85588f2a7e03a6082cc42e5a2796e06e72a962d7c6310b52" }, - { url = "https://mirrors.aliyun.com/pypi/packages/c2/28/f53038a5a72cc4fd0b56c1eafb4ef64aec9685460d5ac34de98ca78b6e29/orjson-3.10.18-cp313-cp313-win_arm64.whl", hash = "sha256:f54c1385a0e6aba2f15a40d703b858bedad36ded0491e55d35d905b2c34a4cc3" }, + { url = "https://mirrors.aliyun.com/pypi/packages/32/33/93fcc25907235c344ae73122f8a4e01d2d393ef062b4af7d2e2487a32c37/orjson-3.11.9-cp313-cp313-macosx_10_15_x86_64.macosx_11_0_arm64.macosx_10_15_universal2.whl", hash = "sha256:4bab1b2d6141fe7b32ae71dac905666ece4f94936efbfb13d55bb7739a3a6021" }, + { url = "https://mirrors.aliyun.com/pypi/packages/8f/27/b1e6dadb3c080313c03fdd8067b85e6a0460c7d8d6a1c3984ef77b904e4d/orjson-3.11.9-cp313-cp313-macosx_15_0_arm64.whl", hash = "sha256:844417969855fc7a41be124aafe83dc424592a7f77cd4501900c67307122b92c" }, + { url = "https://mirrors.aliyun.com/pypi/packages/21/0f/c9ede0bf052f6b4051e64a7d4fa91b725cccf8321a6a786e86eb03519f00/orjson-3.11.9-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ffe02797b5e9f3a9d8292ddcd289b474ad13e81ad83cd1891a240811f1d2cb81" }, + { url = "https://mirrors.aliyun.com/pypi/packages/fd/26/d398e28048dc18205bbe812f2c88cb9b40313db2470778e25964796458fe/orjson-3.11.9-cp313-cp313-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:0e4eed3b200023042814d2fc8a5d2e880f13b52e1ed2485e83da4f3962f7dc1a" }, + { url = "https://mirrors.aliyun.com/pypi/packages/66/60/52b0054c4c700d5aa7fc5b7ca96917400d8f061307778578e67a10e25852/orjson-3.11.9-cp313-cp313-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:8aff7da9952a5ad1cef8e68017724d96c7b9a66e99e91d6252e1b133d67a7b10" }, + { url = "https://mirrors.aliyun.com/pypi/packages/d5/97/1e3dc2b2a28b7b2528f403d2fc1d79ec5f39af3bc143ab65d3ec26426385/orjson-3.11.9-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:4d4e98d6f3b8afed8bc8cd9718ec0cdf46661826beefb53fe8eafb37f2bf0362" }, + { url = "https://mirrors.aliyun.com/pypi/packages/fc/39/31fbfe7850f2de32dee7e7e5c09f26d403ab01e440ac96001c6b01ad3c99/orjson-3.11.9-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:3a81d52442a7c99b3662333235b3adf96a1715864658b35bb797212be7bddb97" }, + { url = "https://mirrors.aliyun.com/pypi/packages/a1/08/dca0082dd2a194acb93e5457e73455388e2e2ca464a2672449a9ddbb679d/orjson-3.11.9-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4e39364e726a8fff737309aff059ff67d8a8c8d5b677be7bb49a8b3e84b7e218" }, + { url = "https://mirrors.aliyun.com/pypi/packages/11/d4/5bdb0626801230139987385554c5d4c42255218ac906525bf4347f22cd95/orjson-3.11.9-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:4fd66214623f1b17501df9f0543bef0b833979ab5b6ded1e1d123222866aa8c9" }, + { url = "https://mirrors.aliyun.com/pypi/packages/fa/88/a21fb53b3ede6703aede6dce4710ed4111e5b201cfa6bbff5e544f9d47d7/orjson-3.11.9-cp313-cp313-musllinux_1_2_armv7l.whl", hash = "sha256:8ecc30f10465fa1e0ce13fd01d9e22c316e5053a719a8d915d4545a09a5ff677" }, + { url = "https://mirrors.aliyun.com/pypi/packages/3d/57/1b30daf70f0d8180e9a73cefbfbdd99e4bf19eb020466502b01fba7e0e50/orjson-3.11.9-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:97db4c94a7db398a5bd636273324f0b3fd58b350bbbac8bb380ceb825a9b40f4" }, + { url = "https://mirrors.aliyun.com/pypi/packages/04/83/45fbb6d962e260807f99441db9613cee868ceda4baceda59b3720a563f97/orjson-3.11.9-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:9f78cf8fec5bd627f4082b8dfeac7871b43d7f3274904492a43dab39f18a19a0" }, + { url = "https://mirrors.aliyun.com/pypi/packages/5f/cc/2d10025f9056d376e4127ec05a5808b218d46f035fdc08178a5411b34250/orjson-3.11.9-cp313-cp313-win32.whl", hash = "sha256:d4087e5c0209a0a8efe4de3303c234b9c44d1174161dcd851e8eea07c7560b32" }, + { url = "https://mirrors.aliyun.com/pypi/packages/67/bd/2775ff28bfe883b9aa1ff348300542eb2ef1ee18d8ae0e3a49846817a865/orjson-3.11.9-cp313-cp313-win_amd64.whl", hash = "sha256:051b102c93b4f634e89f3866b07b9a9a98915ada541f4ec30f177067b2694979" }, + { url = "https://mirrors.aliyun.com/pypi/packages/91/2b/d26799e580939e32a7da9a39531bc9e58e15ca32ffaa6a8cb3e9bb0d22cd/orjson-3.11.9-cp313-cp313-win_arm64.whl", hash = "sha256:cce9127885941bd28f080cecf1f1d288336b7e0d812c345b08be88b572796254" }, ] [[package]] @@ -8239,7 +8263,7 @@ requires-dist = [ { name = "mcp", specifier = ">=1.28.1,<2.0.0" }, { name = "mini-racer", specifier = ">=0.12.4,<0.13.0" }, { name = "minio", specifier = "==7.2.4" }, - { name = "mistralai", specifier = "==0.4.2" }, + { name = "mistralai", specifier = ">=2.7.2,<3.0.0" }, { name = "moodlepy", specifier = ">=0.23.0" }, { name = "mypy-boto3-s3", specifier = "==1.40.26" }, { name = "mysql-connector-python", specifier = ">=9.0.0,<10.0.0" },