mistralai 1.10.0__py3-none-any.whl → 1.11.1__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (270) hide show
  1. mistralai/_hooks/tracing.py +28 -3
  2. mistralai/_version.py +3 -3
  3. mistralai/accesses.py +22 -12
  4. mistralai/agents.py +88 -44
  5. mistralai/basesdk.py +6 -0
  6. mistralai/chat.py +96 -40
  7. mistralai/classifiers.py +48 -23
  8. mistralai/conversations.py +186 -64
  9. mistralai/documents.py +72 -26
  10. mistralai/embeddings.py +24 -9
  11. mistralai/extra/README.md +1 -1
  12. mistralai/extra/mcp/auth.py +10 -11
  13. mistralai/extra/mcp/base.py +17 -16
  14. mistralai/extra/mcp/sse.py +13 -15
  15. mistralai/extra/mcp/stdio.py +5 -6
  16. mistralai/extra/observability/otel.py +47 -68
  17. mistralai/extra/run/context.py +33 -43
  18. mistralai/extra/run/result.py +29 -30
  19. mistralai/extra/run/tools.py +8 -9
  20. mistralai/extra/struct_chat.py +15 -8
  21. mistralai/extra/utils/response_format.py +5 -3
  22. mistralai/files.py +58 -24
  23. mistralai/fim.py +20 -12
  24. mistralai/httpclient.py +0 -1
  25. mistralai/jobs.py +65 -26
  26. mistralai/libraries.py +20 -10
  27. mistralai/mistral_agents.py +438 -30
  28. mistralai/mistral_jobs.py +62 -17
  29. mistralai/models/__init__.py +46 -1
  30. mistralai/models/agent.py +1 -1
  31. mistralai/models/agentconversation.py +1 -1
  32. mistralai/models/agenthandoffdoneevent.py +1 -1
  33. mistralai/models/agenthandoffentry.py +3 -2
  34. mistralai/models/agenthandoffstartedevent.py +1 -1
  35. mistralai/models/agents_api_v1_agents_get_versionop.py +21 -0
  36. mistralai/models/agents_api_v1_agents_list_versionsop.py +33 -0
  37. mistralai/models/agents_api_v1_agents_listop.py +5 -1
  38. mistralai/models/agents_api_v1_conversations_listop.py +1 -1
  39. mistralai/models/agentscompletionrequest.py +2 -5
  40. mistralai/models/agentscompletionstreamrequest.py +2 -5
  41. mistralai/models/archiveftmodelout.py +1 -1
  42. mistralai/models/assistantmessage.py +1 -1
  43. mistralai/models/audiochunk.py +1 -1
  44. mistralai/models/audioencoding.py +18 -0
  45. mistralai/models/audioformat.py +17 -0
  46. mistralai/models/basemodelcard.py +1 -1
  47. mistralai/models/batchjobin.py +18 -9
  48. mistralai/models/batchjobout.py +6 -1
  49. mistralai/models/batchjobsout.py +1 -1
  50. mistralai/models/batchrequest.py +48 -0
  51. mistralai/models/chatcompletionchoice.py +10 -5
  52. mistralai/models/chatcompletionrequest.py +2 -5
  53. mistralai/models/chatcompletionstreamrequest.py +2 -5
  54. mistralai/models/classificationrequest.py +37 -3
  55. mistralai/models/classifierdetailedjobout.py +4 -2
  56. mistralai/models/classifierftmodelout.py +3 -2
  57. mistralai/models/classifierjobout.py +4 -2
  58. mistralai/models/codeinterpretertool.py +1 -1
  59. mistralai/models/completiondetailedjobout.py +5 -2
  60. mistralai/models/completionftmodelout.py +3 -2
  61. mistralai/models/completionjobout.py +5 -2
  62. mistralai/models/completionresponsestreamchoice.py +9 -8
  63. mistralai/models/conversationappendrequest.py +4 -1
  64. mistralai/models/conversationappendstreamrequest.py +4 -1
  65. mistralai/models/conversationhistory.py +2 -1
  66. mistralai/models/conversationmessages.py +1 -1
  67. mistralai/models/conversationrequest.py +5 -1
  68. mistralai/models/conversationresponse.py +2 -1
  69. mistralai/models/conversationrestartrequest.py +4 -1
  70. mistralai/models/conversationrestartstreamrequest.py +4 -1
  71. mistralai/models/conversationstreamrequest.py +5 -1
  72. mistralai/models/documentlibrarytool.py +1 -1
  73. mistralai/models/documenturlchunk.py +1 -1
  74. mistralai/models/embeddingdtype.py +7 -1
  75. mistralai/models/embeddingrequest.py +11 -3
  76. mistralai/models/encodingformat.py +4 -1
  77. mistralai/models/entitytype.py +8 -1
  78. mistralai/models/filepurpose.py +8 -1
  79. mistralai/models/files_api_routes_list_filesop.py +4 -11
  80. mistralai/models/files_api_routes_upload_fileop.py +2 -6
  81. mistralai/models/fileschema.py +3 -5
  82. mistralai/models/finetuneablemodeltype.py +4 -1
  83. mistralai/models/ftclassifierlossfunction.py +4 -1
  84. mistralai/models/ftmodelcard.py +1 -1
  85. mistralai/models/functioncallentry.py +3 -2
  86. mistralai/models/functioncallevent.py +1 -1
  87. mistralai/models/functionresultentry.py +3 -2
  88. mistralai/models/functiontool.py +1 -1
  89. mistralai/models/githubrepositoryin.py +1 -1
  90. mistralai/models/githubrepositoryout.py +1 -1
  91. mistralai/models/httpvalidationerror.py +4 -2
  92. mistralai/models/imagegenerationtool.py +1 -1
  93. mistralai/models/imageurlchunk.py +1 -1
  94. mistralai/models/jobs_api_routes_batch_get_batch_jobop.py +40 -3
  95. mistralai/models/jobsout.py +1 -1
  96. mistralai/models/legacyjobmetadataout.py +1 -1
  97. mistralai/models/messageinputentry.py +9 -3
  98. mistralai/models/messageoutputentry.py +6 -3
  99. mistralai/models/messageoutputevent.py +4 -2
  100. mistralai/models/mistralerror.py +11 -7
  101. mistralai/models/mistralpromptmode.py +1 -1
  102. mistralai/models/modelconversation.py +1 -1
  103. mistralai/models/no_response_error.py +5 -1
  104. mistralai/models/ocrrequest.py +11 -1
  105. mistralai/models/ocrtableobject.py +4 -1
  106. mistralai/models/referencechunk.py +1 -1
  107. mistralai/models/requestsource.py +5 -1
  108. mistralai/models/responsedoneevent.py +1 -1
  109. mistralai/models/responseerrorevent.py +1 -1
  110. mistralai/models/responseformats.py +5 -1
  111. mistralai/models/responsestartedevent.py +1 -1
  112. mistralai/models/responsevalidationerror.py +2 -0
  113. mistralai/models/retrievefileout.py +3 -5
  114. mistralai/models/sampletype.py +7 -1
  115. mistralai/models/sdkerror.py +2 -0
  116. mistralai/models/shareenum.py +7 -1
  117. mistralai/models/sharingdelete.py +2 -4
  118. mistralai/models/sharingin.py +3 -5
  119. mistralai/models/source.py +8 -1
  120. mistralai/models/systemmessage.py +1 -1
  121. mistralai/models/textchunk.py +1 -1
  122. mistralai/models/thinkchunk.py +1 -1
  123. mistralai/models/timestampgranularity.py +1 -1
  124. mistralai/models/tool.py +2 -6
  125. mistralai/models/toolcall.py +2 -6
  126. mistralai/models/toolchoice.py +2 -6
  127. mistralai/models/toolchoiceenum.py +6 -1
  128. mistralai/models/toolexecutiondeltaevent.py +2 -1
  129. mistralai/models/toolexecutiondoneevent.py +2 -1
  130. mistralai/models/toolexecutionentry.py +4 -2
  131. mistralai/models/toolexecutionstartedevent.py +2 -1
  132. mistralai/models/toolfilechunk.py +13 -5
  133. mistralai/models/toolmessage.py +1 -1
  134. mistralai/models/toolreferencechunk.py +15 -5
  135. mistralai/models/tooltypes.py +1 -1
  136. mistralai/models/transcriptionsegmentchunk.py +1 -1
  137. mistralai/models/transcriptionstreamdone.py +1 -1
  138. mistralai/models/transcriptionstreamlanguage.py +1 -1
  139. mistralai/models/transcriptionstreamsegmentdelta.py +1 -1
  140. mistralai/models/transcriptionstreamtextdelta.py +1 -1
  141. mistralai/models/unarchiveftmodelout.py +1 -1
  142. mistralai/models/uploadfileout.py +3 -5
  143. mistralai/models/usermessage.py +1 -1
  144. mistralai/models/wandbintegration.py +1 -1
  145. mistralai/models/wandbintegrationout.py +1 -1
  146. mistralai/models/websearchpremiumtool.py +1 -1
  147. mistralai/models/websearchtool.py +1 -1
  148. mistralai/models_.py +24 -12
  149. mistralai/ocr.py +38 -10
  150. mistralai/sdk.py +2 -2
  151. mistralai/transcriptions.py +28 -12
  152. mistralai/types/basemodel.py +41 -3
  153. mistralai/utils/__init__.py +0 -3
  154. mistralai/utils/annotations.py +32 -8
  155. mistralai/utils/enums.py +60 -0
  156. mistralai/utils/forms.py +21 -10
  157. mistralai/utils/queryparams.py +14 -2
  158. mistralai/utils/requestbodies.py +3 -3
  159. mistralai/utils/retries.py +69 -5
  160. mistralai/utils/serializers.py +0 -20
  161. mistralai/utils/unmarshal_json_response.py +15 -1
  162. {mistralai-1.10.0.dist-info → mistralai-1.11.1.dist-info}/METADATA +144 -159
  163. mistralai-1.11.1.dist-info/RECORD +495 -0
  164. {mistralai-1.10.0.dist-info → mistralai-1.11.1.dist-info}/WHEEL +1 -1
  165. mistralai_azure/_version.py +3 -3
  166. mistralai_azure/basesdk.py +21 -5
  167. mistralai_azure/chat.py +82 -109
  168. mistralai_azure/httpclient.py +0 -1
  169. mistralai_azure/models/__init__.py +66 -4
  170. mistralai_azure/models/assistantmessage.py +1 -1
  171. mistralai_azure/models/chatcompletionchoice.py +10 -7
  172. mistralai_azure/models/chatcompletionrequest.py +24 -10
  173. mistralai_azure/models/chatcompletionstreamrequest.py +24 -10
  174. mistralai_azure/models/completionresponsestreamchoice.py +11 -7
  175. mistralai_azure/models/documenturlchunk.py +1 -1
  176. mistralai_azure/models/httpvalidationerror.py +15 -8
  177. mistralai_azure/models/imageurlchunk.py +1 -1
  178. mistralai_azure/models/mistralazureerror.py +30 -0
  179. mistralai_azure/models/mistralpromptmode.py +1 -1
  180. mistralai_azure/models/no_response_error.py +17 -0
  181. mistralai_azure/models/ocrpageobject.py +32 -5
  182. mistralai_azure/models/ocrrequest.py +20 -1
  183. mistralai_azure/models/ocrtableobject.py +34 -0
  184. mistralai_azure/models/prediction.py +4 -0
  185. mistralai_azure/models/referencechunk.py +1 -1
  186. mistralai_azure/models/responseformat.py +4 -2
  187. mistralai_azure/models/responseformats.py +5 -2
  188. mistralai_azure/models/responsevalidationerror.py +27 -0
  189. mistralai_azure/models/sdkerror.py +32 -14
  190. mistralai_azure/models/systemmessage.py +8 -4
  191. mistralai_azure/models/systemmessagecontentchunks.py +21 -0
  192. mistralai_azure/models/textchunk.py +1 -1
  193. mistralai_azure/models/thinkchunk.py +35 -0
  194. mistralai_azure/models/tool.py +2 -6
  195. mistralai_azure/models/toolcall.py +2 -6
  196. mistralai_azure/models/toolchoice.py +2 -6
  197. mistralai_azure/models/toolchoiceenum.py +6 -1
  198. mistralai_azure/models/toolmessage.py +1 -1
  199. mistralai_azure/models/tooltypes.py +1 -1
  200. mistralai_azure/models/usermessage.py +1 -1
  201. mistralai_azure/ocr.py +39 -40
  202. mistralai_azure/types/basemodel.py +41 -3
  203. mistralai_azure/utils/__init__.py +18 -8
  204. mistralai_azure/utils/annotations.py +32 -8
  205. mistralai_azure/utils/enums.py +60 -0
  206. mistralai_azure/utils/eventstreaming.py +10 -0
  207. mistralai_azure/utils/forms.py +21 -10
  208. mistralai_azure/utils/queryparams.py +14 -2
  209. mistralai_azure/utils/requestbodies.py +3 -3
  210. mistralai_azure/utils/retries.py +69 -5
  211. mistralai_azure/utils/serializers.py +3 -22
  212. mistralai_azure/utils/unmarshal_json_response.py +38 -0
  213. mistralai_gcp/_hooks/types.py +7 -0
  214. mistralai_gcp/_version.py +4 -4
  215. mistralai_gcp/basesdk.py +33 -25
  216. mistralai_gcp/chat.py +98 -109
  217. mistralai_gcp/fim.py +62 -85
  218. mistralai_gcp/httpclient.py +6 -17
  219. mistralai_gcp/models/__init__.py +321 -116
  220. mistralai_gcp/models/assistantmessage.py +2 -2
  221. mistralai_gcp/models/chatcompletionchoice.py +10 -7
  222. mistralai_gcp/models/chatcompletionrequest.py +38 -7
  223. mistralai_gcp/models/chatcompletionresponse.py +6 -6
  224. mistralai_gcp/models/chatcompletionstreamrequest.py +38 -7
  225. mistralai_gcp/models/completionresponsestreamchoice.py +12 -8
  226. mistralai_gcp/models/deltamessage.py +1 -1
  227. mistralai_gcp/models/fimcompletionrequest.py +9 -10
  228. mistralai_gcp/models/fimcompletionresponse.py +6 -6
  229. mistralai_gcp/models/fimcompletionstreamrequest.py +9 -10
  230. mistralai_gcp/models/httpvalidationerror.py +15 -8
  231. mistralai_gcp/models/imageurl.py +1 -1
  232. mistralai_gcp/models/imageurlchunk.py +1 -1
  233. mistralai_gcp/models/jsonschema.py +1 -1
  234. mistralai_gcp/models/mistralgcperror.py +30 -0
  235. mistralai_gcp/models/mistralpromptmode.py +8 -0
  236. mistralai_gcp/models/no_response_error.py +17 -0
  237. mistralai_gcp/models/prediction.py +4 -0
  238. mistralai_gcp/models/referencechunk.py +1 -1
  239. mistralai_gcp/models/responseformat.py +5 -3
  240. mistralai_gcp/models/responseformats.py +5 -2
  241. mistralai_gcp/models/responsevalidationerror.py +27 -0
  242. mistralai_gcp/models/sdkerror.py +32 -14
  243. mistralai_gcp/models/systemmessage.py +8 -4
  244. mistralai_gcp/models/systemmessagecontentchunks.py +21 -0
  245. mistralai_gcp/models/textchunk.py +1 -1
  246. mistralai_gcp/models/thinkchunk.py +35 -0
  247. mistralai_gcp/models/tool.py +2 -6
  248. mistralai_gcp/models/toolcall.py +2 -6
  249. mistralai_gcp/models/toolchoice.py +2 -6
  250. mistralai_gcp/models/toolchoiceenum.py +6 -1
  251. mistralai_gcp/models/toolmessage.py +2 -2
  252. mistralai_gcp/models/tooltypes.py +1 -1
  253. mistralai_gcp/models/usageinfo.py +71 -8
  254. mistralai_gcp/models/usermessage.py +2 -2
  255. mistralai_gcp/sdk.py +12 -10
  256. mistralai_gcp/sdkconfiguration.py +0 -7
  257. mistralai_gcp/types/basemodel.py +41 -3
  258. mistralai_gcp/utils/__init__.py +141 -46
  259. mistralai_gcp/utils/annotations.py +32 -8
  260. mistralai_gcp/utils/datetimes.py +23 -0
  261. mistralai_gcp/utils/enums.py +125 -25
  262. mistralai_gcp/utils/eventstreaming.py +10 -0
  263. mistralai_gcp/utils/forms.py +62 -30
  264. mistralai_gcp/utils/queryparams.py +14 -2
  265. mistralai_gcp/utils/requestbodies.py +3 -3
  266. mistralai_gcp/utils/retries.py +69 -5
  267. mistralai_gcp/utils/serializers.py +33 -23
  268. mistralai_gcp/utils/unmarshal_json_response.py +38 -0
  269. mistralai-1.10.0.dist-info/RECORD +0 -475
  270. {mistralai-1.10.0.dist-info → mistralai-1.11.1.dist-info}/licenses/LICENSE +0 -0
@@ -1,22 +1,40 @@
1
1
  """Code generated by Speakeasy (https://speakeasy.com). DO NOT EDIT."""
2
2
 
3
- from dataclasses import dataclass
4
- from typing import Optional
5
3
  import httpx
4
+ from typing import Optional
5
+ from dataclasses import dataclass
6
+
7
+ from mistralai_azure.models import MistralAzureError
8
+
9
+ MAX_MESSAGE_LEN = 10_000
10
+
11
+
12
+ @dataclass(unsafe_hash=True)
13
+ class SDKError(MistralAzureError):
14
+ """The fallback error class if no more specific error class is matched."""
15
+
16
+ def __init__(
17
+ self, message: str, raw_response: httpx.Response, body: Optional[str] = None
18
+ ):
19
+ body_display = body or raw_response.text or '""'
6
20
 
21
+ if message:
22
+ message += ": "
23
+ message += f"Status {raw_response.status_code}"
7
24
 
8
- @dataclass
9
- class SDKError(Exception):
10
- """Represents an error returned by the API."""
25
+ headers = raw_response.headers
26
+ content_type = headers.get("content-type", '""')
27
+ if content_type != "application/json":
28
+ if " " in content_type:
29
+ content_type = f'"{content_type}"'
30
+ message += f" Content-Type {content_type}"
11
31
 
12
- message: str
13
- status_code: int = -1
14
- body: str = ""
15
- raw_response: Optional[httpx.Response] = None
32
+ if len(body_display) > MAX_MESSAGE_LEN:
33
+ truncated = body_display[:MAX_MESSAGE_LEN]
34
+ remaining = len(body_display) - MAX_MESSAGE_LEN
35
+ body_display = f"{truncated}...and {remaining} more chars"
16
36
 
17
- def __str__(self):
18
- body = ""
19
- if len(self.body) > 0:
20
- body = f"\n{self.body}"
37
+ message += f". Body: {body_display}"
38
+ message = message.strip()
21
39
 
22
- return f"{self.message}: Status {self.status_code}{body}"
40
+ super().__init__(message, raw_response, body)
@@ -1,23 +1,27 @@
1
1
  """Code generated by Speakeasy (https://speakeasy.com). DO NOT EDIT."""
2
2
 
3
3
  from __future__ import annotations
4
- from .textchunk import TextChunk, TextChunkTypedDict
4
+ from .systemmessagecontentchunks import (
5
+ SystemMessageContentChunks,
6
+ SystemMessageContentChunksTypedDict,
7
+ )
5
8
  from mistralai_azure.types import BaseModel
6
9
  from typing import List, Literal, Optional, Union
7
10
  from typing_extensions import NotRequired, TypeAliasType, TypedDict
8
11
 
9
12
 
10
13
  SystemMessageContentTypedDict = TypeAliasType(
11
- "SystemMessageContentTypedDict", Union[str, List[TextChunkTypedDict]]
14
+ "SystemMessageContentTypedDict",
15
+ Union[str, List[SystemMessageContentChunksTypedDict]],
12
16
  )
13
17
 
14
18
 
15
19
  SystemMessageContent = TypeAliasType(
16
- "SystemMessageContent", Union[str, List[TextChunk]]
20
+ "SystemMessageContent", Union[str, List[SystemMessageContentChunks]]
17
21
  )
18
22
 
19
23
 
20
- Role = Literal["system"]
24
+ Role = Literal["system",]
21
25
 
22
26
 
23
27
  class SystemMessageTypedDict(TypedDict):
@@ -0,0 +1,21 @@
1
+ """Code generated by Speakeasy (https://speakeasy.com). DO NOT EDIT."""
2
+
3
+ from __future__ import annotations
4
+ from .textchunk import TextChunk, TextChunkTypedDict
5
+ from .thinkchunk import ThinkChunk, ThinkChunkTypedDict
6
+ from mistralai_azure.utils import get_discriminator
7
+ from pydantic import Discriminator, Tag
8
+ from typing import Union
9
+ from typing_extensions import Annotated, TypeAliasType
10
+
11
+
12
+ SystemMessageContentChunksTypedDict = TypeAliasType(
13
+ "SystemMessageContentChunksTypedDict",
14
+ Union[TextChunkTypedDict, ThinkChunkTypedDict],
15
+ )
16
+
17
+
18
+ SystemMessageContentChunks = Annotated[
19
+ Union[Annotated[TextChunk, Tag("text")], Annotated[ThinkChunk, Tag("thinking")]],
20
+ Discriminator(lambda m: get_discriminator(m, "type", "type")),
21
+ ]
@@ -6,7 +6,7 @@ from typing import Literal, Optional
6
6
  from typing_extensions import NotRequired, TypedDict
7
7
 
8
8
 
9
- Type = Literal["text"]
9
+ Type = Literal["text",]
10
10
 
11
11
 
12
12
  class TextChunkTypedDict(TypedDict):
@@ -0,0 +1,35 @@
1
+ """Code generated by Speakeasy (https://speakeasy.com). DO NOT EDIT."""
2
+
3
+ from __future__ import annotations
4
+ from .referencechunk import ReferenceChunk, ReferenceChunkTypedDict
5
+ from .textchunk import TextChunk, TextChunkTypedDict
6
+ from mistralai_azure.types import BaseModel
7
+ from typing import List, Literal, Optional, Union
8
+ from typing_extensions import NotRequired, TypeAliasType, TypedDict
9
+
10
+
11
+ ThinkingTypedDict = TypeAliasType(
12
+ "ThinkingTypedDict", Union[ReferenceChunkTypedDict, TextChunkTypedDict]
13
+ )
14
+
15
+
16
+ Thinking = TypeAliasType("Thinking", Union[ReferenceChunk, TextChunk])
17
+
18
+
19
+ ThinkChunkType = Literal["thinking",]
20
+
21
+
22
+ class ThinkChunkTypedDict(TypedDict):
23
+ thinking: List[ThinkingTypedDict]
24
+ closed: NotRequired[bool]
25
+ r"""Whether the thinking chunk is closed or not. Currently only used for prefixing."""
26
+ type: NotRequired[ThinkChunkType]
27
+
28
+
29
+ class ThinkChunk(BaseModel):
30
+ thinking: List[Thinking]
31
+
32
+ closed: Optional[bool] = None
33
+ r"""Whether the thinking chunk is closed or not. Currently only used for prefixing."""
34
+
35
+ type: Optional[ThinkChunkType] = "thinking"
@@ -4,10 +4,8 @@ from __future__ import annotations
4
4
  from .function import Function, FunctionTypedDict
5
5
  from .tooltypes import ToolTypes
6
6
  from mistralai_azure.types import BaseModel
7
- from mistralai_azure.utils import validate_open_enum
8
- from pydantic.functional_validators import PlainValidator
9
7
  from typing import Optional
10
- from typing_extensions import Annotated, NotRequired, TypedDict
8
+ from typing_extensions import NotRequired, TypedDict
11
9
 
12
10
 
13
11
  class ToolTypedDict(TypedDict):
@@ -18,6 +16,4 @@ class ToolTypedDict(TypedDict):
18
16
  class Tool(BaseModel):
19
17
  function: Function
20
18
 
21
- type: Annotated[Optional[ToolTypes], PlainValidator(validate_open_enum(False))] = (
22
- None
23
- )
19
+ type: Optional[ToolTypes] = None
@@ -4,10 +4,8 @@ from __future__ import annotations
4
4
  from .functioncall import FunctionCall, FunctionCallTypedDict
5
5
  from .tooltypes import ToolTypes
6
6
  from mistralai_azure.types import BaseModel
7
- from mistralai_azure.utils import validate_open_enum
8
- from pydantic.functional_validators import PlainValidator
9
7
  from typing import Optional
10
- from typing_extensions import Annotated, NotRequired, TypedDict
8
+ from typing_extensions import NotRequired, TypedDict
11
9
 
12
10
 
13
11
  class ToolCallTypedDict(TypedDict):
@@ -22,8 +20,6 @@ class ToolCall(BaseModel):
22
20
 
23
21
  id: Optional[str] = "null"
24
22
 
25
- type: Annotated[Optional[ToolTypes], PlainValidator(validate_open_enum(False))] = (
26
- None
27
- )
23
+ type: Optional[ToolTypes] = None
28
24
 
29
25
  index: Optional[int] = 0
@@ -4,10 +4,8 @@ from __future__ import annotations
4
4
  from .functionname import FunctionName, FunctionNameTypedDict
5
5
  from .tooltypes import ToolTypes
6
6
  from mistralai_azure.types import BaseModel
7
- from mistralai_azure.utils import validate_open_enum
8
- from pydantic.functional_validators import PlainValidator
9
7
  from typing import Optional
10
- from typing_extensions import Annotated, NotRequired, TypedDict
8
+ from typing_extensions import NotRequired, TypedDict
11
9
 
12
10
 
13
11
  class ToolChoiceTypedDict(TypedDict):
@@ -24,6 +22,4 @@ class ToolChoice(BaseModel):
24
22
  function: FunctionName
25
23
  r"""this restriction of `Function` is used to select a specific function to call"""
26
24
 
27
- type: Annotated[Optional[ToolTypes], PlainValidator(validate_open_enum(False))] = (
28
- None
29
- )
25
+ type: Optional[ToolTypes] = None
@@ -4,4 +4,9 @@ from __future__ import annotations
4
4
  from typing import Literal
5
5
 
6
6
 
7
- ToolChoiceEnum = Literal["auto", "none", "any", "required"]
7
+ ToolChoiceEnum = Literal[
8
+ "auto",
9
+ "none",
10
+ "any",
11
+ "required",
12
+ ]
@@ -22,7 +22,7 @@ ToolMessageContentTypedDict = TypeAliasType(
22
22
  ToolMessageContent = TypeAliasType("ToolMessageContent", Union[str, List[ContentChunk]])
23
23
 
24
24
 
25
- ToolMessageRole = Literal["tool"]
25
+ ToolMessageRole = Literal["tool",]
26
26
 
27
27
 
28
28
  class ToolMessageTypedDict(TypedDict):
@@ -5,4 +5,4 @@ from mistralai_azure.types import UnrecognizedStr
5
5
  from typing import Literal, Union
6
6
 
7
7
 
8
- ToolTypes = Union[Literal["function"], UnrecognizedStr]
8
+ ToolTypes = Union[Literal["function",], UnrecognizedStr]
@@ -16,7 +16,7 @@ UserMessageContentTypedDict = TypeAliasType(
16
16
  UserMessageContent = TypeAliasType("UserMessageContent", Union[str, List[ContentChunk]])
17
17
 
18
18
 
19
- UserMessageRole = Literal["user"]
19
+ UserMessageRole = Literal["user",]
20
20
 
21
21
 
22
22
  class UserMessageTypedDict(TypedDict):
mistralai_azure/ocr.py CHANGED
@@ -4,6 +4,7 @@ from .basesdk import BaseSDK
4
4
  from mistralai_azure import models, utils
5
5
  from mistralai_azure._hooks import HookContext
6
6
  from mistralai_azure.types import Nullable, OptionalNullable, UNSET
7
+ from mistralai_azure.utils.unmarshal_json_response import unmarshal_json_response
7
8
  from typing import Any, List, Mapping, Optional, Union
8
9
 
9
10
 
@@ -24,11 +25,14 @@ class Ocr(BaseSDK):
24
25
  document_annotation_format: OptionalNullable[
25
26
  Union[models.ResponseFormat, models.ResponseFormatTypedDict]
26
27
  ] = UNSET,
28
+ table_format: OptionalNullable[models.TableFormat] = UNSET,
29
+ extract_header: Optional[bool] = None,
30
+ extract_footer: Optional[bool] = None,
27
31
  retries: OptionalNullable[utils.RetryConfig] = UNSET,
28
32
  server_url: Optional[str] = None,
29
33
  timeout_ms: Optional[int] = None,
30
34
  http_headers: Optional[Mapping[str, str]] = None,
31
- ) -> Optional[models.OCRResponse]:
35
+ ) -> models.OCRResponse:
32
36
  r"""OCR
33
37
 
34
38
  :param model:
@@ -40,6 +44,9 @@ class Ocr(BaseSDK):
40
44
  :param image_min_size: Minimum height and width of image to extract
41
45
  :param bbox_annotation_format: Structured output class for extracting useful information from each extracted bounding box / image from document. Only json_schema is valid for this field
42
46
  :param document_annotation_format: Structured output class for extracting useful information from the entire document. Only json_schema is valid for this field
47
+ :param table_format:
48
+ :param extract_header:
49
+ :param extract_footer:
43
50
  :param retries: Override the default retry configuration for this method
44
51
  :param server_url: Override the default server URL for this method
45
52
  :param timeout_ms: Override the default request timeout configuration for this method in milliseconds
@@ -69,6 +76,9 @@ class Ocr(BaseSDK):
69
76
  document_annotation_format=utils.get_pydantic_model(
70
77
  document_annotation_format, OptionalNullable[models.ResponseFormat]
71
78
  ),
79
+ table_format=table_format,
80
+ extract_header=extract_header,
81
+ extract_footer=extract_footer,
72
82
  )
73
83
 
74
84
  req = self._build_request(
@@ -87,6 +97,7 @@ class Ocr(BaseSDK):
87
97
  get_serialized_body=lambda: utils.serialize_request_body(
88
98
  request, False, False, "json", models.OCRRequest
89
99
  ),
100
+ allow_empty_value=None,
90
101
  timeout_ms=timeout_ms,
91
102
  )
92
103
 
@@ -103,7 +114,7 @@ class Ocr(BaseSDK):
103
114
  config=self.sdk_configuration,
104
115
  base_url=base_url or "",
105
116
  operation_id="ocr_v1_ocr_post",
106
- oauth2_scopes=[],
117
+ oauth2_scopes=None,
107
118
  security_source=self.sdk_configuration.security,
108
119
  ),
109
120
  request=req,
@@ -113,31 +124,20 @@ class Ocr(BaseSDK):
113
124
 
114
125
  response_data: Any = None
115
126
  if utils.match_response(http_res, "200", "application/json"):
116
- return utils.unmarshal_json(http_res.text, Optional[models.OCRResponse])
127
+ return unmarshal_json_response(models.OCRResponse, http_res)
117
128
  if utils.match_response(http_res, "422", "application/json"):
118
- response_data = utils.unmarshal_json(
119
- http_res.text, models.HTTPValidationErrorData
129
+ response_data = unmarshal_json_response(
130
+ models.HTTPValidationErrorData, http_res
120
131
  )
121
- raise models.HTTPValidationError(data=response_data)
132
+ raise models.HTTPValidationError(response_data, http_res)
122
133
  if utils.match_response(http_res, "4XX", "*"):
123
134
  http_res_text = utils.stream_to_text(http_res)
124
- raise models.SDKError(
125
- "API error occurred", http_res.status_code, http_res_text, http_res
126
- )
135
+ raise models.SDKError("API error occurred", http_res, http_res_text)
127
136
  if utils.match_response(http_res, "5XX", "*"):
128
137
  http_res_text = utils.stream_to_text(http_res)
129
- raise models.SDKError(
130
- "API error occurred", http_res.status_code, http_res_text, http_res
131
- )
138
+ raise models.SDKError("API error occurred", http_res, http_res_text)
132
139
 
133
- content_type = http_res.headers.get("Content-Type")
134
- http_res_text = utils.stream_to_text(http_res)
135
- raise models.SDKError(
136
- f"Unexpected response received (code: {http_res.status_code}, type: {content_type})",
137
- http_res.status_code,
138
- http_res_text,
139
- http_res,
140
- )
140
+ raise models.SDKError("Unexpected response received", http_res)
141
141
 
142
142
  async def process_async(
143
143
  self,
@@ -155,11 +155,14 @@ class Ocr(BaseSDK):
155
155
  document_annotation_format: OptionalNullable[
156
156
  Union[models.ResponseFormat, models.ResponseFormatTypedDict]
157
157
  ] = UNSET,
158
+ table_format: OptionalNullable[models.TableFormat] = UNSET,
159
+ extract_header: Optional[bool] = None,
160
+ extract_footer: Optional[bool] = None,
158
161
  retries: OptionalNullable[utils.RetryConfig] = UNSET,
159
162
  server_url: Optional[str] = None,
160
163
  timeout_ms: Optional[int] = None,
161
164
  http_headers: Optional[Mapping[str, str]] = None,
162
- ) -> Optional[models.OCRResponse]:
165
+ ) -> models.OCRResponse:
163
166
  r"""OCR
164
167
 
165
168
  :param model:
@@ -171,6 +174,9 @@ class Ocr(BaseSDK):
171
174
  :param image_min_size: Minimum height and width of image to extract
172
175
  :param bbox_annotation_format: Structured output class for extracting useful information from each extracted bounding box / image from document. Only json_schema is valid for this field
173
176
  :param document_annotation_format: Structured output class for extracting useful information from the entire document. Only json_schema is valid for this field
177
+ :param table_format:
178
+ :param extract_header:
179
+ :param extract_footer:
174
180
  :param retries: Override the default retry configuration for this method
175
181
  :param server_url: Override the default server URL for this method
176
182
  :param timeout_ms: Override the default request timeout configuration for this method in milliseconds
@@ -200,6 +206,9 @@ class Ocr(BaseSDK):
200
206
  document_annotation_format=utils.get_pydantic_model(
201
207
  document_annotation_format, OptionalNullable[models.ResponseFormat]
202
208
  ),
209
+ table_format=table_format,
210
+ extract_header=extract_header,
211
+ extract_footer=extract_footer,
203
212
  )
204
213
 
205
214
  req = self._build_request_async(
@@ -218,6 +227,7 @@ class Ocr(BaseSDK):
218
227
  get_serialized_body=lambda: utils.serialize_request_body(
219
228
  request, False, False, "json", models.OCRRequest
220
229
  ),
230
+ allow_empty_value=None,
221
231
  timeout_ms=timeout_ms,
222
232
  )
223
233
 
@@ -234,7 +244,7 @@ class Ocr(BaseSDK):
234
244
  config=self.sdk_configuration,
235
245
  base_url=base_url or "",
236
246
  operation_id="ocr_v1_ocr_post",
237
- oauth2_scopes=[],
247
+ oauth2_scopes=None,
238
248
  security_source=self.sdk_configuration.security,
239
249
  ),
240
250
  request=req,
@@ -244,28 +254,17 @@ class Ocr(BaseSDK):
244
254
 
245
255
  response_data: Any = None
246
256
  if utils.match_response(http_res, "200", "application/json"):
247
- return utils.unmarshal_json(http_res.text, Optional[models.OCRResponse])
257
+ return unmarshal_json_response(models.OCRResponse, http_res)
248
258
  if utils.match_response(http_res, "422", "application/json"):
249
- response_data = utils.unmarshal_json(
250
- http_res.text, models.HTTPValidationErrorData
259
+ response_data = unmarshal_json_response(
260
+ models.HTTPValidationErrorData, http_res
251
261
  )
252
- raise models.HTTPValidationError(data=response_data)
262
+ raise models.HTTPValidationError(response_data, http_res)
253
263
  if utils.match_response(http_res, "4XX", "*"):
254
264
  http_res_text = await utils.stream_to_text_async(http_res)
255
- raise models.SDKError(
256
- "API error occurred", http_res.status_code, http_res_text, http_res
257
- )
265
+ raise models.SDKError("API error occurred", http_res, http_res_text)
258
266
  if utils.match_response(http_res, "5XX", "*"):
259
267
  http_res_text = await utils.stream_to_text_async(http_res)
260
- raise models.SDKError(
261
- "API error occurred", http_res.status_code, http_res_text, http_res
262
- )
268
+ raise models.SDKError("API error occurred", http_res, http_res_text)
263
269
 
264
- content_type = http_res.headers.get("Content-Type")
265
- http_res_text = await utils.stream_to_text_async(http_res)
266
- raise models.SDKError(
267
- f"Unexpected response received (code: {http_res.status_code}, type: {content_type})",
268
- http_res.status_code,
269
- http_res_text,
270
- http_res,
271
- )
270
+ raise models.SDKError("Unexpected response received", http_res)
@@ -2,7 +2,8 @@
2
2
 
3
3
  from pydantic import ConfigDict, model_serializer
4
4
  from pydantic import BaseModel as PydanticBaseModel
5
- from typing import TYPE_CHECKING, Literal, Optional, TypeVar, Union
5
+ from pydantic_core import core_schema
6
+ from typing import TYPE_CHECKING, Any, Literal, Optional, TypeVar, Union
6
7
  from typing_extensions import TypeAliasType, TypeAlias
7
8
 
8
9
 
@@ -35,5 +36,42 @@ else:
35
36
  "OptionalNullable", Union[Optional[Nullable[T]], Unset], type_params=(T,)
36
37
  )
37
38
 
38
- UnrecognizedInt: TypeAlias = int
39
- UnrecognizedStr: TypeAlias = str
39
+
40
+ class UnrecognizedStr(str):
41
+ @classmethod
42
+ def __get_pydantic_core_schema__(cls, _source_type: Any, _handler: Any) -> core_schema.CoreSchema:
43
+ # Make UnrecognizedStr only work in lax mode, not strict mode
44
+ # This makes it a "fallback" option when more specific types (like Literals) don't match
45
+ def validate_lax(v: Any) -> 'UnrecognizedStr':
46
+ if isinstance(v, cls):
47
+ return v
48
+ return cls(str(v))
49
+
50
+ # Use lax_or_strict_schema where strict always fails
51
+ # This forces Pydantic to prefer other union members in strict mode
52
+ # and only fall back to UnrecognizedStr in lax mode
53
+ return core_schema.lax_or_strict_schema(
54
+ lax_schema=core_schema.chain_schema([
55
+ core_schema.str_schema(),
56
+ core_schema.no_info_plain_validator_function(validate_lax)
57
+ ]),
58
+ strict_schema=core_schema.none_schema(), # Always fails in strict mode
59
+ )
60
+
61
+
62
+ class UnrecognizedInt(int):
63
+ @classmethod
64
+ def __get_pydantic_core_schema__(cls, _source_type: Any, _handler: Any) -> core_schema.CoreSchema:
65
+ # Make UnrecognizedInt only work in lax mode, not strict mode
66
+ # This makes it a "fallback" option when more specific types (like Literals) don't match
67
+ def validate_lax(v: Any) -> 'UnrecognizedInt':
68
+ if isinstance(v, cls):
69
+ return v
70
+ return cls(int(v))
71
+ return core_schema.lax_or_strict_schema(
72
+ lax_schema=core_schema.chain_schema([
73
+ core_schema.int_schema(),
74
+ core_schema.no_info_plain_validator_function(validate_lax)
75
+ ]),
76
+ strict_schema=core_schema.none_schema(), # Always fails in strict mode
77
+ )
@@ -2,6 +2,8 @@
2
2
 
3
3
  from typing import TYPE_CHECKING
4
4
  from importlib import import_module
5
+ import builtins
6
+ import sys
5
7
 
6
8
  if TYPE_CHECKING:
7
9
  from .annotations import get_discriminator
@@ -39,7 +41,6 @@ if TYPE_CHECKING:
39
41
  validate_decimal,
40
42
  validate_float,
41
43
  validate_int,
42
- validate_open_enum,
43
44
  )
44
45
  from .url import generate_url, template_url, remove_suffix
45
46
  from .values import (
@@ -100,7 +101,6 @@ __all__ = [
100
101
  "validate_const",
101
102
  "validate_float",
102
103
  "validate_int",
103
- "validate_open_enum",
104
104
  "cast_partial",
105
105
  ]
106
106
 
@@ -153,11 +153,22 @@ _dynamic_imports: dict[str, str] = {
153
153
  "validate_const": ".serializers",
154
154
  "validate_float": ".serializers",
155
155
  "validate_int": ".serializers",
156
- "validate_open_enum": ".serializers",
157
156
  "cast_partial": ".values",
158
157
  }
159
158
 
160
159
 
160
+ def dynamic_import(modname, retries=3):
161
+ for attempt in range(retries):
162
+ try:
163
+ return import_module(modname, __package__)
164
+ except KeyError:
165
+ # Clear any half-initialized module and retry
166
+ sys.modules.pop(modname, None)
167
+ if attempt == retries - 1:
168
+ break
169
+ raise KeyError(f"Failed to import module '{modname}' after {retries} attempts")
170
+
171
+
161
172
  def __getattr__(attr_name: str) -> object:
162
173
  module_name = _dynamic_imports.get(attr_name)
163
174
  if module_name is None:
@@ -166,9 +177,8 @@ def __getattr__(attr_name: str) -> object:
166
177
  )
167
178
 
168
179
  try:
169
- module = import_module(module_name, __package__)
170
- result = getattr(module, attr_name)
171
- return result
180
+ module = dynamic_import(module_name)
181
+ return getattr(module, attr_name)
172
182
  except ImportError as e:
173
183
  raise ImportError(
174
184
  f"Failed to import {attr_name} from {module_name}: {e}"
@@ -180,5 +190,5 @@ def __getattr__(attr_name: str) -> object:
180
190
 
181
191
 
182
192
  def __dir__():
183
- lazy_attrs = list(_dynamic_imports.keys())
184
- return sorted(lazy_attrs)
193
+ lazy_attrs = builtins.list(_dynamic_imports.keys())
194
+ return builtins.sorted(lazy_attrs)
@@ -3,6 +3,7 @@
3
3
  from enum import Enum
4
4
  from typing import Any, Optional
5
5
 
6
+
6
7
  def get_discriminator(model: Any, fieldname: str, key: str) -> str:
7
8
  """
8
9
  Recursively search for the discriminator attribute in a model.
@@ -25,31 +26,54 @@ def get_discriminator(model: Any, fieldname: str, key: str) -> str:
25
26
 
26
27
  if isinstance(field, dict):
27
28
  if key in field:
28
- return f'{field[key]}'
29
+ return f"{field[key]}"
29
30
 
30
31
  if hasattr(field, fieldname):
31
32
  attr = getattr(field, fieldname)
32
33
  if isinstance(attr, Enum):
33
- return f'{attr.value}'
34
- return f'{attr}'
34
+ return f"{attr.value}"
35
+ return f"{attr}"
35
36
 
36
37
  if hasattr(field, upper_fieldname):
37
38
  attr = getattr(field, upper_fieldname)
38
39
  if isinstance(attr, Enum):
39
- return f'{attr.value}'
40
- return f'{attr}'
40
+ return f"{attr.value}"
41
+ return f"{attr}"
41
42
 
42
43
  return None
43
44
 
45
+ def search_nested_discriminator(obj: Any) -> Optional[str]:
46
+ """Recursively search for discriminator in nested structures."""
47
+ # First try direct field lookup
48
+ discriminator = get_field_discriminator(obj)
49
+ if discriminator is not None:
50
+ return discriminator
51
+
52
+ # If it's a dict, search in nested values
53
+ if isinstance(obj, dict):
54
+ for value in obj.values():
55
+ if isinstance(value, list):
56
+ # Search in list items
57
+ for item in value:
58
+ nested_discriminator = search_nested_discriminator(item)
59
+ if nested_discriminator is not None:
60
+ return nested_discriminator
61
+ elif isinstance(value, dict):
62
+ # Search in nested dict
63
+ nested_discriminator = search_nested_discriminator(value)
64
+ if nested_discriminator is not None:
65
+ return nested_discriminator
66
+
67
+ return None
44
68
 
45
69
  if isinstance(model, list):
46
70
  for field in model:
47
- discriminator = get_field_discriminator(field)
71
+ discriminator = search_nested_discriminator(field)
48
72
  if discriminator is not None:
49
73
  return discriminator
50
74
 
51
- discriminator = get_field_discriminator(model)
75
+ discriminator = search_nested_discriminator(model)
52
76
  if discriminator is not None:
53
77
  return discriminator
54
78
 
55
- raise ValueError(f'Could not find discriminator field {fieldname} in {model}')
79
+ raise ValueError(f"Could not find discriminator field {fieldname} in {model}")