Prasham.Jain Claude Opus 4.7 (1M context) commited on
Commit
4c1ad51
·
1 Parent(s): 8be6018

refactor(branch-a): A1 — adopt openenv-core MCPEnvironment + create_app for canonical OpenEnv compliance

Browse files

- Drop wrong PyPI 'openenv' dep (gym-style squat); add 'openenv-core>=0.2.3' (Meta-PyTorch OpenEnv)
- New env/wire.py: CITriageAction / CITriageObservation / CITriageState subclassing OpenEnv's Pydantic Action/Observation/State; carries domain Pydantic schemas as `payload` so frozen Phase 0 schemas stay untouched
- env/server.py: CITriageEnv(MCPEnvironment) with FastMCP server advertising all 11 tools via mcp.tool(); reset/step/_step_impl/state implemented; build_app() uses openenv.core.env_server.http_server.create_app for canonical /reset, /step, /state, /schema, /mcp (POST + WS), /ws, /docs
- Tool execution path stays on /step (CITriageAction kind="tool_call") so episode-level budget/cost bookkeeping is preserved; FastMCP layer handles tools/list discovery
- Tests rewritten against OpenEnv wire format: HTTP for reset shape + error, WebSocket /ws for stateful multi-step flows (canonical EnvClient path), POST /mcp JSON-RPC for tools/list, plus /schema endpoint check; all 12 phase-A1 tests + full schemas suite green (44 passed)
- requirements.txt regenerated

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

pyproject.toml CHANGED
@@ -13,7 +13,7 @@ dependencies = [
13
  "datasets>=2.18",
14
  "huggingface_hub>=0.23",
15
  "jsonschema>=4.21",
16
- "openenv>=0.1.13",
17
  ]
18
 
19
  [project.optional-dependencies]
 
13
  "datasets>=2.18",
14
  "huggingface_hub>=0.23",
15
  "jsonschema>=4.21",
16
+ "openenv-core>=0.2.3",
17
  ]
18
 
19
  [project.optional-dependencies]
requirements.txt CHANGED
@@ -1,4 +1,3 @@
1
- Resolved 131 packages in 2ms
2
  # This file was autogenerated by uv via the following command:
3
  # uv export --no-dev --extra training --format requirements-txt
4
  -e .
@@ -8,6 +7,10 @@ accelerate==1.13.0 \
8
  # via
9
  # ci-triage-env
10
  # trl
 
 
 
 
11
  aiohappyeyeballs==2.6.1 \
12
  --hash=sha256:c3f9d0113123803ccadfdf3f0faa505bc78e6a72d1cc4806cbd719826e943558 \
13
  --hash=sha256:f349ba8f4b75cb25c99c5c2d84e997e485204d2902a9597802b0371f09331fb8
@@ -67,7 +70,12 @@ anyio==4.13.0 \
67
  --hash=sha256:08b310f9e24a9594186fd75b4f73f4a4152069e3853f1ed8bfbf58369f4ad708 \
68
  --hash=sha256:334b70e641fd2221c1505b3890c69882fe4a2df910cba14d97019b90b24439dc
69
  # via
 
70
  # httpx
 
 
 
 
71
  # starlette
72
  # watchfiles
73
  attrs==26.1.0 \
@@ -75,8 +83,60 @@ attrs==26.1.0 \
75
  --hash=sha256:d03ceb89cb322a8fd706d4fb91940737b6642aa36998fe130a9bc96c985eff32
76
  # via
77
  # aiohttp
 
78
  # jsonschema
79
  # referencing
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
80
  certifi==2026.4.22 \
81
  --hash=sha256:3cb2210c8f88ba2318d29b0388d1023c8492ff72ecdde4ebdaddbb13a31b1c4a \
82
  --hash=sha256:8d455352a37b71bf76a79caa83a3d6c25afee4a385d632127b6afb3963f1c580
@@ -85,6 +145,34 @@ certifi==2026.4.22 \
85
  # httpx
86
  # requests
87
  # sentry-sdk
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
88
  charset-normalizer==3.4.7 \
89
  --hash=sha256:08e721811161356f97b4059a9ba7bafb23ea5ee2255402c42881c214e173c6b4 \
90
  --hash=sha256:0f7eb884681e3938906ed0434f20c63046eacd0111c4ba96f27b76084cd679f5 \
@@ -165,6 +253,47 @@ contourpy==1.3.3 \
165
  --hash=sha256:cd5dfcaeb10f7b7f9dc8941717c6c2ade08f587be2226222c12b25f0483ed497 \
166
  --hash=sha256:fd907ae12cd483cd83e414b12941c632a969171bf90fc937d0c9f268a31cafff
167
  # via matplotlib
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
168
  cuda-bindings==13.2.0 ; sys_platform == 'linux' \
169
  --hash=sha256:1eba9504ac70667dd48313395fe05157518fd6371b532790e96fbb31bbb5a5e1 \
170
  --hash=sha256:46d8776a55d6d5da9dd6e9858fba2efcda2abe6743871dee47dd06eb8cb6d955 \
@@ -181,6 +310,10 @@ cycler==0.12.1 \
181
  --hash=sha256:85cef7cff222d8644161529808465972e51340599459b8ac3ccbac5a854e0d30 \
182
  --hash=sha256:88bb128f02ba341da8ef447245a9e138fae777f6a23943da4540077d3601eb1c
183
  # via matplotlib
 
 
 
 
184
  datasets==4.8.4 \
185
  --hash=sha256:a1429ed853275ce7943a01c6d2e25475b4501eb758934362106a280470df3a52 \
186
  --hash=sha256:cdc8bee4698e549d78bf1fed6aea2eebc760b22b084f07e6fc020c6577a6ce6d
@@ -193,10 +326,41 @@ dill==0.4.1 \
193
  # via
194
  # datasets
195
  # multiprocess
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
196
  fastapi==0.136.1 \
197
  --hash=sha256:7af665ad7acfa0a3baf8983d393b6b471b9da10ede59c60045f49fbc89a0fa7f \
198
  --hash=sha256:a6e9d7eeada96c93a4d69cb03836b44fa34e2854accb7244a1ece36cd4781c3f
199
- # via ci-triage-env
 
 
 
 
 
 
 
200
  filelock==3.29.0 \
201
  --hash=sha256:69974355e960702e789734cb4871f884ea6fe50bd8404051a3530bc07809cf90 \
202
  --hash=sha256:96f5f6344709aa1572bbf631c640e4ebeeb519e08da902c39a001882f30ac258
@@ -267,6 +431,7 @@ fsspec==2026.2.0 \
267
  --hash=sha256:98de475b5cb3bd66bedd5c4679e87b4fdfe1a3bf4d707b151b3c07e58c9a2437
268
  # via
269
  # datasets
 
270
  # huggingface-hub
271
  # torch
272
  gitdb==4.0.12 \
@@ -277,12 +442,34 @@ gitpython==3.1.47 \
277
  --hash=sha256:489f590edfd6d20571b2c0e72c6a6ac6915ee8b8cd04572330e3842207a78905 \
278
  --hash=sha256:dba27f922bd2b42cb54c87a8ab3cb6beb6bf07f3d564e21ac848913a05a8a3cd
279
  # via wandb
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
280
  h11==0.16.0 \
281
  --hash=sha256:4e35b956cf45792e4caa5885e69fba00bdbc6ffafbfa020300e549b208ee5ff1 \
282
  --hash=sha256:63cf8bbe7522de3bf65932fda1d9c2772064ffb3dae62d55932da54b31cb6c86
283
  # via
284
  # httpcore
285
  # uvicorn
 
 
 
 
286
  hf-xet==1.4.3 ; platform_machine == 'AMD64' or platform_machine == 'aarch64' or platform_machine == 'amd64' or platform_machine == 'arm64' or platform_machine == 'x86_64' \
287
  --hash=sha256:39f2d2e9654cd9b4319885733993807aab6de9dfbd34c42f0b78338d6617421f \
288
  --hash=sha256:49ad8a8cead2b56051aa84d7fce3e1335efe68df3cf6c058f22a65513885baac \
@@ -321,7 +508,18 @@ httpx==0.28.1 \
321
  # via
322
  # ci-triage-env
323
  # datasets
 
 
 
324
  # huggingface-hub
 
 
 
 
 
 
 
 
325
  huggingface-hub==1.12.0 \
326
  --hash=sha256:7c3fe85e24b652334e5d456d7a812cd9a071e75630fac4365d9165ab5e4a34b6 \
327
  --hash=sha256:d74939969585ee35748bd66de09baf84099d461bda7287cd9043bfb99b0e424d
@@ -329,6 +527,9 @@ huggingface-hub==1.12.0 \
329
  # accelerate
330
  # ci-triage-env
331
  # datasets
 
 
 
332
  # tokenizers
333
  # transformers
334
  idna==3.13 \
@@ -336,23 +537,106 @@ idna==3.13 \
336
  --hash=sha256:892ea0cde124a99ce773decba204c5552b69c3c67ffd5f232eb7696135bc8bb3
337
  # via
338
  # anyio
 
339
  # httpx
340
  # requests
341
  # yarl
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
342
  jinja2==3.1.6 \
343
  --hash=sha256:0137fb05990d35f1275a587e9aee6d56da821fc83491a0fb838183be43f66d6d \
344
  --hash=sha256:85ece4451f492d0c13c5dd7c13a64681a86afae63a5f347908daf103ce6d2f67
345
  # via
 
346
  # torch
347
  # trl
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
348
  jsonschema==4.26.0 \
349
  --hash=sha256:0c26707e2efad8aa1bfc5b7ce170f3fccc2e4918ff85989ba9ffa9facb2be326 \
350
  --hash=sha256:d489f15263b8d200f8387e64b4c3a75f06629559fb73deb8fdfb525f2dab50ce
351
- # via ci-triage-env
 
 
 
 
 
 
352
  jsonschema-specifications==2025.9.1 \
353
  --hash=sha256:98802fee3a11ee76ecaca44429fda8a41bff98b00a0f2838151b113f210cc6fe \
354
  --hash=sha256:b540987f239e745613c7a9176f3edb72b832a4ac465cf02712288397832b5e8d
355
  # via jsonschema
 
 
 
 
356
  kiwisolver==1.5.0 \
357
  --hash=sha256:01808c6d15f4c3e8559595d6d1fe6411c68e4a3822b4b9972b44473b24f4e679 \
358
  --hash=sha256:0df54df7e686afa55e6f21fb86195224a6d9beb71d637e8d7920c95cf0f89aac \
@@ -423,7 +707,9 @@ markupsafe==3.0.3 \
423
  --hash=sha256:d88b440e37a16e651bda4c7c2b930eb586fd15ca7406cb39e211fcff3bf3017d \
424
  --hash=sha256:de8a88e63464af587c950061a5e6a67d3632e36df62b986892331d4620a35c01 \
425
  --hash=sha256:f9e130248f4462aaa8e2552d547f36ddadbeaa573879158d721bbd33dfe4743a
426
- # via jinja2
 
 
427
  matplotlib==3.10.9 \
428
  --hash=sha256:10cc5ce06d10231c36f40e875f3c7e8050362a4ee8f0ee5d29a6b3277d57bb42 \
429
  --hash=sha256:3fc0364dfbe1d07f6d15c5ebd0c5bf89e126916e5a8667dd4a7a6e84c36653d4 \
@@ -446,10 +732,20 @@ matplotlib==3.10.9 \
446
  # via
447
  # ci-triage-env
448
  # seaborn
 
 
 
 
449
  mdurl==0.1.2 \
450
  --hash=sha256:84008a41e51615a49fc9966191ff91509e3c40b939176e643fd50a5c2196b8f8 \
451
  --hash=sha256:bb413d29f5eea38f31dd4754dd7377d4465116fb207585f97bf925588687c1ba
452
  # via markdown-it-py
 
 
 
 
 
 
453
  mpmath==1.3.0 \
454
  --hash=sha256:7a28eb2a9774d00c7bc92411c19a89209d5da7c4c9a9e227be8330a23a25b91f \
455
  --hash=sha256:a0b2b9fe80bbcd81a6647ff13108738cfb482d481d826cc0e02f5b35e5c88d2c
@@ -545,8 +841,8 @@ numpy==2.4.4 \
545
  # accelerate
546
  # contourpy
547
  # datasets
 
548
  # matplotlib
549
- # openenv
550
  # pandas
551
  # seaborn
552
  # transformers
@@ -619,16 +915,64 @@ nvidia-nvtx==13.0.85 ; sys_platform == 'linux' \
619
  --hash=sha256:4936d1d6780fbe68db454f5e72a42ff64d1fd6397df9f363ae786930fd5c1cd4 \
620
  --hash=sha256:cb7780edb6b14107373c835bf8b72e7a178bac7367e23da7acb108f973f157a6
621
  # via cuda-toolkit
622
- openenv==0.1.13 \
623
- --hash=sha256:726971d2289472c1c20261436bcccdf3edfcf0b201d16aec127815bd83bfcb3d \
624
- --hash=sha256:813249d7f526f40c6e8b325f705294761a5bc887b9144c3383fa2bae7baa7726
 
 
 
 
 
 
 
 
625
  # via ci-triage-env
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
626
  packaging==26.2 \
627
  --hash=sha256:5fc45236b9446107ff2415ce77c807cee2862cb6fac22b8a73826d0693b0980e \
628
  --hash=sha256:ff452ff5a3e828ce110190feff1178bb1f2ea2281fa2075aadb987c2fb221661
629
  # via
630
  # accelerate
631
  # datasets
 
 
 
632
  # huggingface-hub
633
  # matplotlib
634
  # transformers
@@ -655,7 +999,12 @@ pandas==3.0.2 \
655
  # via
656
  # ci-triage-env
657
  # datasets
 
658
  # seaborn
 
 
 
 
659
  pillow==12.2.0 \
660
  --hash=sha256:01afa7cf67f74f09523699b4e88c73fb55c13346d212a59a2db1f86b0a63e8c5 \
661
  --hash=sha256:03e7e372d5240cc23e9f07deca4d775c0817bffc641b01e9c3af208dbd300987 \
@@ -687,11 +1036,15 @@ pillow==12.2.0 \
687
  --hash=sha256:f3f40b3c5a968281fd507d519e444c35f0ff171237f4fdde090dd60699458421 \
688
  --hash=sha256:f490f9368b6fc026f021db16d7ec2fbf7d89e2edb42e8ec09d2c60505f5729c7 \
689
  --hash=sha256:fc3d34d4a8fbec3e88a79b92e5465e0f9b842b628675850d860b8bd300b159f5
690
- # via matplotlib
 
 
691
  platformdirs==4.9.6 \
692
  --hash=sha256:3bfa75b0ad0db84096ae777218481852c0ebc6c727b3168c1b9e0118e458cf0a \
693
  --hash=sha256:e61adb1d5e5cb3441b4b7710bea7e4c12250ca49439228cc1021c00dcfac0917
694
- # via wandb
 
 
695
  propcache==0.4.1 \
696
  --hash=sha256:0013cb6f8dde4b2a2f66903b8ba740bdfe378c943c4377a200551ceb27f379e4 \
697
  --hash=sha256:031dce78b9dc099f4c29785d9cf5577a3faf9ebf74ecbd3c856a7b92768c3df3 \
@@ -749,6 +1102,10 @@ psutil==7.2.2 \
749
  --hash=sha256:ed0cace939114f62738d808fdcecd4c869222507e266e574799e9c0faa17d486 \
750
  --hash=sha256:fd04ef36b4a6d599bbdb225dd1d3f51e00105f6d48a28f006da7f9822f2606d8
751
  # via accelerate
 
 
 
 
752
  pyarrow==24.0.0 \
753
  --hash=sha256:0b3537c00fb8d384f15ac1e79b6eb6db04a16514c8c1d22e59a9b95c8ba42868 \
754
  --hash=sha256:14e31a3c9e35f1ab6356c6378f6f72830e6d2d5f1791df3774a7b097d18a6a1e \
@@ -766,12 +1123,23 @@ pyarrow==24.0.0 \
766
  --hash=sha256:b7d9a514e73bc42711e6a35aaccf3587c520024fe0a25d830a1a8a27c15f4f57 \
767
  --hash=sha256:f7616236ec1bc2b15bfdec22a71ab38851c86f8f05ff64f379e1278cf20c634a
768
  # via datasets
 
 
 
 
769
  pydantic==2.13.3 \
770
  --hash=sha256:6db14ac8dfc9a1e57f87ea2c0de670c251240f43cb0c30a5130e9720dc612927 \
771
  --hash=sha256:af09e9d1d09f4e7fe37145c1f577e1d61ceb9a41924bf0094a36506285d0a84d
772
  # via
773
  # ci-triage-env
774
  # fastapi
 
 
 
 
 
 
 
775
  # wandb
776
  pydantic-core==2.46.3 \
777
  --hash=sha256:06d5d8820cbbdb4147578c1fe7ffcd5b83f34508cb9f9ab76e807be7db6ff0a4 \
@@ -822,14 +1190,30 @@ pydantic-core==2.46.3 \
822
  --hash=sha256:fc331a5314ffddd5385b9ee9d0d2fee0b13c27e0e02dad71b1ae5d6561f51eeb \
823
  --hash=sha256:fd35aa21299def8db7ef4fe5c4ff862941a9a158ca7b63d61e66fe67d30416b4
824
  # via pydantic
 
 
 
 
 
 
 
 
825
  pygments==2.20.0 \
826
  --hash=sha256:6757cd03768053ff99f3039c1a36d6c0aa0b263438fcab17520b30a303a82b5f \
827
  --hash=sha256:81a9e26dd42fd28a23a2d169d86d7ac03b46e2f8b59ed4698fb4785f946d0176
828
  # via rich
 
 
 
 
829
  pyparsing==3.3.2 \
830
  --hash=sha256:850ba148bd908d7e2411587e247a1e4f0327839c40e2e5e6d05a007ecc69911d \
831
  --hash=sha256:c777f4d763f140633dcb6d8a3eda953bf7a214dc4eff598413c070bcdc117cbc
832
  # via matplotlib
 
 
 
 
833
  python-dateutil==2.9.0.post0 \
834
  --hash=sha256:37dd54208da7e1cd875388217d5e00ebd4179249f90fb72437e91a35459a0ad3 \
835
  --hash=sha256:a8b2bc7bffae282281c8140a97d3aa9c14da0b136dfe83f850eea9a5f7470427
@@ -839,7 +1223,32 @@ python-dateutil==2.9.0.post0 \
839
  python-dotenv==1.2.2 \
840
  --hash=sha256:1d8214789a24de455a8b8bd8ae6fe3c6b69a5e3d64aa8a8e5d68e694bbcb285a \
841
  --hash=sha256:2c371a91fbd7ba082c2c1dc1f8bf89ca22564a087c2c287cd9b662adde799cf3
842
- # via uvicorn
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
843
  pyyaml==6.0.3 \
844
  --hash=sha256:10892704fc220243f5305762e276552a0395f7beb4dbf9b14ec8fd43b57f126c \
845
  --hash=sha256:1d37d57ad971609cf3c53ba6a7e365e40660e3be0e5175fa9f2365a379d6095a \
@@ -865,7 +1274,11 @@ pyyaml==6.0.3 \
865
  # accelerate
866
  # ci-triage-env
867
  # datasets
 
 
868
  # huggingface-hub
 
 
869
  # transformers
870
  # uvicorn
871
  # wandb
@@ -874,6 +1287,7 @@ referencing==0.37.0 \
874
  --hash=sha256:44aefc3142c5b842538163acb373e24cce6632bd54bdb01b21ad5863489f50d8
875
  # via
876
  # jsonschema
 
877
  # jsonschema-specifications
878
  regex==2026.4.4 \
879
  --hash=sha256:04bb679bc0bde8a7bfb71e991493d47314e7b98380b083df2447cda4b6edb60f \
@@ -915,11 +1329,21 @@ requests==2.33.1 \
915
  --hash=sha256:4e6d1ef462f3626a1f0a0a9c42dd93c63bad33f9f1c1937509b8c5c8718ab56a
916
  # via
917
  # datasets
 
918
  # wandb
919
  rich==15.0.0 \
920
  --hash=sha256:33bd4ef74232fb73fe9279a257718407f169c09b78a87ad3d296f548e27de0bb \
921
  --hash=sha256:edd07a4824c6b40189fb7ac9bc4c52536e9780fbbfbddf6f1e2502c31b068c36
922
- # via typer
 
 
 
 
 
 
 
 
 
923
  rpds-py==0.30.0 \
924
  --hash=sha256:07ae8a593e1c3c6b82ca3292efbe73c30b61332fd612e05abee07c79359f292f \
925
  --hash=sha256:12f90dd7557b6bd57f40abe7747e81e0c0b119bef015ea7726e69fe550e394a4 \
@@ -967,6 +1391,10 @@ rpds-py==0.30.0 \
967
  # via
968
  # jsonschema
969
  # referencing
 
 
 
 
970
  safetensors==0.7.0 \
971
  --hash=sha256:07663963b67e8bd9f0b8ad15bb9163606cd27cc5a1b96235a50d8369803b96b0 \
972
  --hash=sha256:1d060c70284127fa805085d8f10fbd0962792aed71879d00864acda69dbab981 \
@@ -990,6 +1418,14 @@ seaborn==0.13.2 \
990
  --hash=sha256:636f8336facf092165e27924f223d3c62ca560b1f2bb5dff7ab7fad265361987 \
991
  --hash=sha256:93e60a40988f4d65e9f4885df477e2fdaff6b73a9ded434c1ab356dd57eefff7
992
  # via ci-triage-env
 
 
 
 
 
 
 
 
993
  sentry-sdk==2.58.0 \
994
  --hash=sha256:688d1c704ddecf382ea3326f21a67453d4caa95592d722b7c780a36a9d23109e \
995
  --hash=sha256:c1144d947352d54e5b7daa63596d9f848adf684989c06c4f5a659f0c85a18f6f
@@ -1010,10 +1446,22 @@ smmap==5.0.3 \
1010
  --hash=sha256:4d9debb8b99007ae47165abc08670bd74cb74b5227dda7f643eccc4e9eb5642c \
1011
  --hash=sha256:c106e05d5a61449cf6ba9a1e650227ecfb141590d2a98412103ff35d89fc7b2f
1012
  # via gitdb
 
 
 
 
 
 
 
 
1013
  starlette==1.0.0 \
1014
  --hash=sha256:6a4beaf1f81bb472fd19ea9b918b50dc3a77a6f2e190a12954b25e6ed5eea149 \
1015
  --hash=sha256:d3ec55e0bb321692d275455ddfd3df75fff145d009685eb40dc91fc66b03d38b
1016
- # via fastapi
 
 
 
 
1017
  sympy==1.14.0 \
1018
  --hash=sha256:d3d3fe8df1e5a0b42f0e7bdf50541697dbe7d23746e894990c030e2b05e72517 \
1019
  --hash=sha256:e091cc3e99d2141a0ba2847328f5479b05d94a6635cb96148ccb3f34671bd8f5
@@ -1036,6 +1484,36 @@ tokenizers==0.22.2 \
1036
  --hash=sha256:c9ea31edff2968b44a88f97d784c2f16dc0729b8b143ed004699ebca91f05c48 \
1037
  --hash=sha256:df6c4265b289083bf710dff49bc51ef252f9d5be33a45ee2bed151114a56207b
1038
  # via transformers
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1039
  torch==2.11.0 \
1040
  --hash=sha256:0f68f4ac6d95d12e896c3b7a912b5871619542ec54d3649cf48cc1edd4dd2756 \
1041
  --hash=sha256:4b5866312ee6e52ea625cd211dcb97d6a2cdc1131a5f15cc0d87eec948f6dd34 \
@@ -1054,6 +1532,7 @@ tqdm==4.67.3 \
1054
  # via
1055
  # datasets
1056
  # huggingface-hub
 
1057
  # transformers
1058
  transformers==5.6.2 \
1059
  --hash=sha256:e657134c3e5a6bc00a3c35f4e2674bb51adfcd89898495b788a18552bac2b91a \
@@ -1075,7 +1554,10 @@ typer==0.24.2 \
1075
  --hash=sha256:b618bc3d721f9a8d30f3e05565be26416d06e9bcc29d49bc491dc26aba674fa8 \
1076
  --hash=sha256:ec070dcfca1408e85ee203c6365001e818c3b7fffe686fd07ff2d68095ca0480
1077
  # via
 
 
1078
  # huggingface-hub
 
1079
  # transformers
1080
  typing-extensions==4.15.0 \
1081
  --hash=sha256:0cea48d173cc12fa28ecabc3b837ea3cf6f38c6d1136f85cbaaf598984861466 \
@@ -1083,8 +1565,15 @@ typing-extensions==4.15.0 \
1083
  # via
1084
  # aiosignal
1085
  # anyio
 
1086
  # fastapi
 
 
1087
  # huggingface-hub
 
 
 
 
1088
  # pydantic
1089
  # pydantic-core
1090
  # referencing
@@ -1097,11 +1586,17 @@ typing-inspection==0.4.2 \
1097
  --hash=sha256:ba561c48a67c5958007083d386c3295464928b01faa735ab8547c5692e87f464
1098
  # via
1099
  # fastapi
 
1100
  # pydantic
 
1101
  tzdata==2026.2 ; sys_platform == 'emscripten' or sys_platform == 'win32' \
1102
  --hash=sha256:9173fde7d80d9018e02a662e168e5a2d04f87c41ea174b139fbef642eda62d10 \
1103
  --hash=sha256:bbe9af844f658da81a5f95019480da3a89415801f6cc966806612cc7169bffe7
1104
  # via pandas
 
 
 
 
1105
  urllib3==2.6.3 \
1106
  --hash=sha256:1b62b6884944a57dbe321509ab94fd4d3b307075e0c2eae991ac71ee15ad38ed \
1107
  --hash=sha256:bf272323e553dfb2e87d9bfd225ca7b0f467b919d7bbd355436d3fd37cb0acd4
@@ -1111,7 +1606,12 @@ urllib3==2.6.3 \
1111
  uvicorn==0.46.0 \
1112
  --hash=sha256:bbebbcbed972d162afca128605223022bedd345b7bc7855ce66deb31487a9048 \
1113
  --hash=sha256:fb9da0926999cc6cb22dc7cd71a94a632f078e6ae47ff683c5c420750fb7413d
1114
- # via ci-triage-env
 
 
 
 
 
1115
  uvloop==0.22.1 ; platform_python_implementation != 'PyPy' and sys_platform != 'cygwin' and sys_platform != 'win32' \
1116
  --hash=sha256:3b7f102bf3cb1995cfeaee9321105e8f5da76fdb104cdad8986f85461a1b7b77 \
1117
  --hash=sha256:40631b049d5972c6755b06d0bfe8233b1bd9a8a6392d9d1c45c10b6f9e9b2733 \
@@ -1171,7 +1671,9 @@ watchfiles==1.1.1 \
1171
  --hash=sha256:f537afb3276d12814082a2e9b242bdcf416c2e8fd9f799a737990a1dbe906e5b \
1172
  --hash=sha256:f57b396167a2565a4e8b5e56a5a1c537571733992b226f4f1197d79e94cf0ae5 \
1173
  --hash=sha256:f8979280bdafff686ba5e4d8f97840f929a87ed9cdf133cbbd42f7766774d2aa
1174
- # via uvicorn
 
 
1175
  websockets==16.0 \
1176
  --hash=sha256:0298d07ee155e2e9fda5be8a9042200dd2e3bb0b8a38482156576f863a9d457c \
1177
  --hash=sha256:08d7af67b64d29823fed316505a89b86705f2b7981c07848fb5e3ea3020c1abe \
@@ -1198,7 +1700,10 @@ websockets==16.0 \
1198
  --hash=sha256:e0334872c0a37b606418ac52f6ab9cfd17317ac26365f7f65e203e2d0d0d359f \
1199
  --hash=sha256:eaded469f5e5b7294e2bdca0ab06becb6756ea86894a47806456089298813c89 \
1200
  --hash=sha256:f4a32d1bd841d4bcbffdcb3d2ce50c09c3909fbead375ab28d0181af89fd04da
1201
- # via uvicorn
 
 
 
1202
  xxhash==3.7.0 \
1203
  --hash=sha256:03f8ff4474ee61c845758ce00711d7087a770d77efb36f7e74a6e867301000b8 \
1204
  --hash=sha256:073c23900a9fbf3d26616c17c830db28af9803677cd5b33aea3224d824111514 \
@@ -1286,3 +1791,7 @@ yarl==1.23.0 \
1286
  --hash=sha256:f69f57305656a4852f2a7203efc661d8c042e6cc67f7acd97d8667fb448a426e \
1287
  --hash=sha256:fffc45637bcd6538de8b85f51e3df3223e4ad89bccbfca0481c08c7fc8b7ed7d
1288
  # via aiohttp
 
 
 
 
 
 
1
  # This file was autogenerated by uv via the following command:
2
  # uv export --no-dev --extra training --format requirements-txt
3
  -e .
 
7
  # via
8
  # ci-triage-env
9
  # trl
10
+ aiofile==3.9.0 \
11
+ --hash=sha256:ce2f6c1571538cbdfa0143b04e16b208ecb0e9cb4148e528af8a640ed51cc8aa \
12
+ --hash=sha256:e5ad718bb148b265b6df1b3752c4d1d83024b93da9bd599df74b9d9ffcf7919b
13
+ # via py-key-value-aio
14
  aiohappyeyeballs==2.6.1 \
15
  --hash=sha256:c3f9d0113123803ccadfdf3f0faa505bc78e6a72d1cc4806cbd719826e943558 \
16
  --hash=sha256:f349ba8f4b75cb25c99c5c2d84e997e485204d2902a9597802b0371f09331fb8
 
70
  --hash=sha256:08b310f9e24a9594186fd75b4f73f4a4152069e3853f1ed8bfbf58369f4ad708 \
71
  --hash=sha256:334b70e641fd2221c1505b3890c69882fe4a2df910cba14d97019b90b24439dc
72
  # via
73
+ # gradio
74
  # httpx
75
+ # mcp
76
+ # openai
77
+ # py-key-value-aio
78
+ # sse-starlette
79
  # starlette
80
  # watchfiles
81
  attrs==26.1.0 \
 
83
  --hash=sha256:d03ceb89cb322a8fd706d4fb91940737b6642aa36998fe130a9bc96c985eff32
84
  # via
85
  # aiohttp
86
+ # cyclopts
87
  # jsonschema
88
  # referencing
89
+ authlib==1.7.0 \
90
+ --hash=sha256:b3e326c9aa9cc3ea95fe7d89fd880722d3608da4d00e8a27e061e64b48d801d5 \
91
+ --hash=sha256:e36817afb02f6f0b6bf55f150782499ddd6ddf44b402bb055d3263cc65ac9ae0
92
+ # via fastmcp
93
+ backports-tarfile==1.2.0 ; python_full_version < '3.12' \
94
+ --hash=sha256:77e284d754527b01fb1e6fa8a1afe577858ebe4e9dad8919e34c862cb399bc34 \
95
+ --hash=sha256:d75e02c268746e1b8144c278978b6e98e85de6ad16f8e4b0844a154557eca991
96
+ # via jaraco-context
97
+ beartype==0.22.9 \
98
+ --hash=sha256:8f82b54aa723a2848a56008d18875f91c1db02c32ef6a62319a002e3e25a975f \
99
+ --hash=sha256:d16c9bbc61ea14637596c5f6fbff2ee99cbe3573e46a716401734ef50c3060c2
100
+ # via py-key-value-aio
101
+ brotli==1.2.0 \
102
+ --hash=sha256:022426c9e99fd65d9475dce5c195526f04bb8be8907607e27e747893f6ee3e24 \
103
+ --hash=sha256:072e7624b1fc4d601036ab3f4f27942ef772887e876beff0301d261210bca97f \
104
+ --hash=sha256:15b33fe93cedc4caaff8a0bd1eb7e3dab1c61bb22a0bf5bdfdfd97cd7da79744 \
105
+ --hash=sha256:260d3692396e1895c5034f204f0db022c056f9e2ac841593a4cf9426e2a3faca \
106
+ --hash=sha256:2a7f1d03727130fc875448b65b127a9ec5d06d19d0148e7554384229706f9d1b \
107
+ --hash=sha256:2e1ad3fda65ae0d93fec742a128d72e145c9c7a99ee2fcd667785d99eb25a7fe \
108
+ --hash=sha256:350c8348f0e76fff0a0fd6c26755d2653863279d086d3aa2c290a6a7251135dd \
109
+ --hash=sha256:35d382625778834a7f3061b15423919aa03e4f5da34ac8e02c074e4b75ab4f84 \
110
+ --hash=sha256:40d918bce2b427a0c4ba189df7a006ac0c7277c180aee4617d99e9ccaaf59e6a \
111
+ --hash=sha256:7a47ce5c2288702e09dc22a44d0ee6152f2c7eda97b3c8482d826a1f3cfc7da7 \
112
+ --hash=sha256:7a61c06b334bd99bc5ae84f1eeb36bfe01400264b3c352f968c6e30a10f9d08b \
113
+ --hash=sha256:844a8ceb8483fefafc412f85c14f2aae2fb69567bf2a0de53cdb88b73e7c43ae \
114
+ --hash=sha256:898be2be399c221d2671d29eed26b6b2713a02c2119168ed914e7d00ceadb56f \
115
+ --hash=sha256:9c79f57faa25d97900bfb119480806d783fba83cd09ee0b33c17623935b05fa3 \
116
+ --hash=sha256:aa47441fa3026543513139cb8926a92a8e305ee9c71a6209ef7a97d91640ea03 \
117
+ --hash=sha256:acec55bb7c90f1dfc476126f9711a8e81c9af7fb617409a9ee2953115343f08d \
118
+ --hash=sha256:adedc4a67e15327dfdd04884873c6d5a01d3e3b6f61406f99b1ed4865a2f6d28 \
119
+ --hash=sha256:af43b8711a8264bb4e7d6d9a6d004c3a2019c04c01127a868709ec29962b6036 \
120
+ --hash=sha256:b35c13ce241abdd44cb8ca70683f20c0c079728a36a996297adb5334adfc1c44 \
121
+ --hash=sha256:e310f77e41941c13340a95976fe66a8a95b01e783d430eeaf7a2f87e0a57dd0a \
122
+ --hash=sha256:e99befa0b48f3cd293dafeacdd0d191804d105d279e0b387a32054c1180f3161
123
+ # via gradio
124
+ cachetools==7.0.6 \
125
+ --hash=sha256:4e94956cfdd3086f12042cdd29318f5ced3893014f7d0d059bf3ead3f85b7f8b \
126
+ --hash=sha256:e5d524d36d65703a87243a26ff08ad84f73352adbeafb1cde81e207b456aaf24
127
+ # via py-key-value-aio
128
+ caio==0.9.25 \
129
+ --hash=sha256:06c0bb02d6b929119b1cfbe1ca403c768b2013a369e2db46bfa2a5761cf82e40 \
130
+ --hash=sha256:16498e7f81d1d0f5a4c0ad3f2540e65fe25691376e0a5bd367f558067113ed10 \
131
+ --hash=sha256:4fa69eba47e0f041b9d4f336e2ad40740681c43e686b18b191b6c5f4c5544bfb \
132
+ --hash=sha256:6bebf6f079f1341d19f7386db9b8b1f07e8cc15ae13bfdaff573371ba0575d69 \
133
+ --hash=sha256:97084e4e30dfa598449d874c4d8e0c8d5ea17d2f752ef5e48e150ff9d240cd64 \
134
+ --hash=sha256:ae3d62587332bce600f861a8de6256b1014d6485cfd25d68c15caf1611dd1f7c \
135
+ --hash=sha256:bf84bfa039f25ad91f4f52944452a5f6f405e8afab4d445450978cd6241d1478 \
136
+ --hash=sha256:d6956d9e4a27021c8bd6c9677f3a59eb1d820cc32d0343cea7961a03b1371965 \
137
+ --hash=sha256:fb7ff95af4c31ad3f03179149aab61097a71fd85e05f89b4786de0359dffd044 \
138
+ --hash=sha256:fc220b8533dcf0f238a6b1a4a937f92024c71e7b10b5a2dfc1c73604a25709bc
139
+ # via aiofile
140
  certifi==2026.4.22 \
141
  --hash=sha256:3cb2210c8f88ba2318d29b0388d1023c8492ff72ecdde4ebdaddbb13a31b1c4a \
142
  --hash=sha256:8d455352a37b71bf76a79caa83a3d6c25afee4a385d632127b6afb3963f1c580
 
145
  # httpx
146
  # requests
147
  # sentry-sdk
148
+ cffi==2.0.0 ; platform_python_implementation != 'PyPy' \
149
+ --hash=sha256:1e3a615586f05fc4065a8b22b8152f0c1b00cdbc60596d187c2a74f9e3036e4e \
150
+ --hash=sha256:21d1152871b019407d8ac3985f6775c079416c282e431a4da6afe7aefd2bccbe \
151
+ --hash=sha256:2c8f814d84194c9ea681642fd164267891702542f028a15fc97d4674b6206187 \
152
+ --hash=sha256:2de9a304e27f7596cd03d16f1b7c72219bd944e99cc52b84d0145aefb07cbd3c \
153
+ --hash=sha256:3925dd22fa2b7699ed2617149842d2e6adde22b262fcbfada50e3d195e4b3a94 \
154
+ --hash=sha256:3e17ed538242334bf70832644a32a7aae3d83b57567f9fd60a26257e992b79ba \
155
+ --hash=sha256:44d1b5909021139fe36001ae048dbdde8214afa20200eda0f64c068cac5d5529 \
156
+ --hash=sha256:4671d9dd5ec934cb9a73e7ee9676f9362aba54f7f34910956b84d727b0d73fb6 \
157
+ --hash=sha256:5fed36fccc0612a53f1d4d9a816b50a36702c28a2aa880cb8a122b3466638743 \
158
+ --hash=sha256:66f011380d0e49ed280c789fbd08ff0d40968ee7b665575489afa95c98196ab5 \
159
+ --hash=sha256:6824f87845e3396029f3820c206e459ccc91760e8fa24422f8b0c3d1731cbec5 \
160
+ --hash=sha256:6d02d6655b0e54f54c4ef0b94eb6be0607b70853c45ce98bd278dc7de718be5d \
161
+ --hash=sha256:730cacb21e1bdff3ce90babf007d0a0917cc3e6492f336c2f0134101e0944f93 \
162
+ --hash=sha256:81afed14892743bbe14dacb9e36d9e0e504cd204e0b165062c488942b9718037 \
163
+ --hash=sha256:8941aaadaf67246224cee8c3803777eed332a19d909b47e29c9842ef1e79ac26 \
164
+ --hash=sha256:8eca2a813c1cb7ad4fb74d368c2ffbbb4789d377ee5bb8df98373c2cc0dee76c \
165
+ --hash=sha256:94698a9c5f91f9d138526b48fe26a199609544591f859c870d477351dc7b2414 \
166
+ --hash=sha256:9de40a7b0323d889cf8d23d1ef214f565ab154443c42737dfe52ff82cf857664 \
167
+ --hash=sha256:a05d0c237b3349096d3981b727493e22147f934b20f6f125a3eba8f994bec4a9 \
168
+ --hash=sha256:b21e08af67b8a103c71a250401c78d5e0893beff75e28c53c98f4de42f774062 \
169
+ --hash=sha256:b4c854ef3adc177950a8dfc81a86f5115d2abd545751a304c5bcf2c2c7283cfe \
170
+ --hash=sha256:baf5215e0ab74c16e2dd324e8ec067ef59e41125d3eade2b863d294fd5035c92 \
171
+ --hash=sha256:c649e3a33450ec82378822b3dad03cc228b8f5963c0c12fc3b1e0ab940f768a5 \
172
+ --hash=sha256:c6638687455baf640e37344fe26d37c404db8b80d037c3d29f58fe8d1c3b194d \
173
+ --hash=sha256:da68248800ad6320861f129cd9c1bf96ca849a2771a59e0344e88681905916f5 \
174
+ --hash=sha256:da902562c3e9c550df360bfa53c035b2f241fed6d9aef119048073680ace4a18
175
+ # via cryptography
176
  charset-normalizer==3.4.7 \
177
  --hash=sha256:08e721811161356f97b4059a9ba7bafb23ea5ee2255402c42881c214e173c6b4 \
178
  --hash=sha256:0f7eb884681e3938906ed0434f20c63046eacd0111c4ba96f27b76084cd679f5 \
 
253
  --hash=sha256:cd5dfcaeb10f7b7f9dc8941717c6c2ade08f587be2226222c12b25f0483ed497 \
254
  --hash=sha256:fd907ae12cd483cd83e414b12941c632a969171bf90fc937d0c9f268a31cafff
255
  # via matplotlib
256
+ cryptography==47.0.0 \
257
+ --hash=sha256:0024b87d47ae2399165a6bfb20d24888881eeab83ae2566d62467c5ff0030ce7 \
258
+ --hash=sha256:07efe86201817e7d3c18781ca9770bc0db04e1e48c994be384e4602bc38f8f27 \
259
+ --hash=sha256:11dbb9f50a0f1bb9757b3d8c27c1101780efb8f0bdecfb12439c22a74d64c001 \
260
+ --hash=sha256:14432c8a9bcb37009784f9594a62fae211a2ae9543e96c92b2a8e4c3cd5cd0c4 \
261
+ --hash=sha256:1581aef4219f7ca2849d0250edaa3866212fb74bf5667284f46aa92f9e65c1ca \
262
+ --hash=sha256:160ad728f128972d362e714054f6ba0067cab7fb350c5202a9ae8ae4ce3ef1a0 \
263
+ --hash=sha256:1a405c08857258c11016777e11c02bacbe7ef596faf259305d282272a3a05cbe \
264
+ --hash=sha256:1e47422b5557bb82d3fff997e8d92cff4e28b9789576984f08c248d2b3535d93 \
265
+ --hash=sha256:20fdbe3e38fb67c385d233c89371fa27f9909f6ebca1cecc20c13518dae65475 \
266
+ --hash=sha256:2207a498b03275d0051589e326b79d4cf59985c99031b05bb292ac52631c37fe \
267
+ --hash=sha256:256d07c78a04d6b276f5df935a9923275f53bd1522f214447fdf365494e2d515 \
268
+ --hash=sha256:2b45761c6ec22b7c726d6a829558777e32d0f1c8be7c3f3480f9c912d5ee8a10 \
269
+ --hash=sha256:34b4358b925a5ea3e14384ca781a2c0ef7ac219b57bb9eacc4457078e2b19f92 \
270
+ --hash=sha256:4e1de79e047e25d6e9f8cea71c86b4a53aced64134f0f003bbcbf3655fd172c8 \
271
+ --hash=sha256:5d0e362ff51041b0c0d219cc7d6924d7b8996f57ce5712bdcef71eb3c65a59cc \
272
+ --hash=sha256:6f29f36582e6151d9686235e586dd35bb67491f024767d10b842e520dc6a07ac \
273
+ --hash=sha256:7a02675e2fabd0c0fc04c868b8781863cbf1967691543c22f5470500ff840b31 \
274
+ --hash=sha256:7f1207974a904e005f762869996cf620e9bf79ecb4622f148550bb48e0eb35a7 \
275
+ --hash=sha256:7fda2f02c9015db3f42bb8a22324a454516ed10a8c29ca6ece6cdbb5efe2a203 \
276
+ --hash=sha256:80887c5cbd1774683cb126f0ab4184567f080071d5acf62205acb354b4b753b7 \
277
+ --hash=sha256:835d2d7f47cdc53b3224e90810fb1d36ca94ea29cc1801fb4c1bc43876735769 \
278
+ --hash=sha256:9af828c0d5a65c70ec729cd7495a4bf1a67ecb66417b8f02ff125ab8a6326a74 \
279
+ --hash=sha256:9c59ab0e0fa3a180a5a9c59f3a5abe3ef90d474bc56d7fadfbe80359491b615b \
280
+ --hash=sha256:9f8e55fe4e63613a5e1cc5819030f27b97742d720203a087802ce4ce9ceb52bb \
281
+ --hash=sha256:9fe6b7c64926c765f9dff301f9c1b867febcda5768868ca084e18589113732ab \
282
+ --hash=sha256:a49a3eb5341b9503fa3000a9a0db033161db90d47285291f53c2a9d2cd1b7f76 \
283
+ --hash=sha256:a9b761f012a943b7de0e828843c5688d0de94a0578d44d6c85a1bae32f87791f \
284
+ --hash=sha256:b9a8943e359b7615db1a3ba587994618e094ff3d6fa5a390c73d079ce18b3973 \
285
+ --hash=sha256:cffbba3392df0fa8629bb7f43454ee2925059ee158e23c54620b9063912b86c8 \
286
+ --hash=sha256:ed67ea4e0cfb5faa5bc7ecb6e2b8838f3807a03758eec239d6c21c8769355310 \
287
+ --hash=sha256:edd4da498015da5b9f26d38d3bfc2e90257bfa9cbed1f6767c282a0025ae649b \
288
+ --hash=sha256:ef6b3634087f18d2155b1e8ce264e5345a753da2c5fa9815e7d41315c90f8318 \
289
+ --hash=sha256:f5c15764f261394b22aef6b00252f5195f46f2ca300bec57149474e2538b31f8 \
290
+ --hash=sha256:f5c3296dab66202f1b18a91fa266be93d6aa0c2806ea3d67762c69f60adc71aa \
291
+ --hash=sha256:f7db373287273d8af1414cf95dc4118b13ffdc62be521997b0f2b270771fef50
292
+ # via
293
+ # authlib
294
+ # joserfc
295
+ # pyjwt
296
+ # secretstorage
297
  cuda-bindings==13.2.0 ; sys_platform == 'linux' \
298
  --hash=sha256:1eba9504ac70667dd48313395fe05157518fd6371b532790e96fbb31bbb5a5e1 \
299
  --hash=sha256:46d8776a55d6d5da9dd6e9858fba2efcda2abe6743871dee47dd06eb8cb6d955 \
 
310
  --hash=sha256:85cef7cff222d8644161529808465972e51340599459b8ac3ccbac5a854e0d30 \
311
  --hash=sha256:88bb128f02ba341da8ef447245a9e138fae777f6a23943da4540077d3601eb1c
312
  # via matplotlib
313
+ cyclopts==4.11.0 \
314
+ --hash=sha256:1ffcb9990dbd56b90da19980d31596de9e99019980a215a5d76cf88fe452e94d \
315
+ --hash=sha256:34318e3823b44b5baa754a5e37ec70a5c17dc81c65e4295ed70e17bc1aeae50d
316
+ # via fastmcp
317
  datasets==4.8.4 \
318
  --hash=sha256:a1429ed853275ce7943a01c6d2e25475b4501eb758934362106a280470df3a52 \
319
  --hash=sha256:cdc8bee4698e549d78bf1fed6aea2eebc760b22b084f07e6fc020c6577a6ce6d
 
326
  # via
327
  # datasets
328
  # multiprocess
329
+ distro==1.9.0 \
330
+ --hash=sha256:2fa77c6fd8940f116ee1d6b94a2f90b13b5ea8d019b98bc8bafdcabcdd9bdbed \
331
+ --hash=sha256:7bffd925d65168f85027d8da9af6bddab658135b840670a223589bc0c8ef02b2
332
+ # via openai
333
+ dnspython==2.8.0 \
334
+ --hash=sha256:01d9bbc4a2d76bf0db7c1f729812ded6d912bd318d3b1cf81d30c0f845dbf3af \
335
+ --hash=sha256:181d3c6996452cb1189c4046c61599b84a5a86e099562ffde77d26984ff26d0f
336
+ # via email-validator
337
+ docstring-parser==0.18.0 \
338
+ --hash=sha256:292510982205c12b1248696f44959db3cdd1740237a968ea1e2e7a900eeb2015 \
339
+ --hash=sha256:b3fcbed555c47d8479be0796ef7e19c2670d428d72e96da63f3a40122860374b
340
+ # via cyclopts
341
+ docutils==0.22.4 \
342
+ --hash=sha256:4db53b1fde9abecbb74d91230d32ab626d94f6badfc575d6db9194a49df29968 \
343
+ --hash=sha256:d0013f540772d1420576855455d050a2180186c91c15779301ac2ccb3eeb68de
344
+ # via rich-rst
345
+ email-validator==2.3.0 \
346
+ --hash=sha256:80f13f623413e6b197ae73bb10bf4eb0908faf509ad8362c5edeb0be7fd450b4 \
347
+ --hash=sha256:9fc05c37f2f6cf439ff414f8fc46d917929974a82244c20eb10231ba60c54426
348
+ # via pydantic
349
+ exceptiongroup==1.3.1 \
350
+ --hash=sha256:8b412432c6055b0b7d14c310000ae93352ed6754f70fa8f7c34141f91c4e3219 \
351
+ --hash=sha256:a7a39a3bd276781e98394987d3a5701d0c4edffb633bb7a5144577f82c773598
352
+ # via fastmcp
353
  fastapi==0.136.1 \
354
  --hash=sha256:7af665ad7acfa0a3baf8983d393b6b471b9da10ede59c60045f49fbc89a0fa7f \
355
  --hash=sha256:a6e9d7eeada96c93a4d69cb03836b44fa34e2854accb7244a1ece36cd4781c3f
356
+ # via
357
+ # ci-triage-env
358
+ # gradio
359
+ # openenv-core
360
+ fastmcp==3.2.4 \
361
+ --hash=sha256:083ecb75b44a4169e7fc0f632f94b781bdb0ff877c6b35b9877cbb566fd4d4d1 \
362
+ --hash=sha256:e6c9c429171041455e47ab94bb3f83c4657622a0ec28922f6940053959bd58a9
363
+ # via openenv-core
364
  filelock==3.29.0 \
365
  --hash=sha256:69974355e960702e789734cb4871f884ea6fe50bd8404051a3530bc07809cf90 \
366
  --hash=sha256:96f5f6344709aa1572bbf631c640e4ebeeb519e08da902c39a001882f30ac258
 
431
  --hash=sha256:98de475b5cb3bd66bedd5c4679e87b4fdfe1a3bf4d707b151b3c07e58c9a2437
432
  # via
433
  # datasets
434
+ # gradio-client
435
  # huggingface-hub
436
  # torch
437
  gitdb==4.0.12 \
 
442
  --hash=sha256:489f590edfd6d20571b2c0e72c6a6ac6915ee8b8cd04572330e3842207a78905 \
443
  --hash=sha256:dba27f922bd2b42cb54c87a8ab3cb6beb6bf07f3d564e21ac848913a05a8a3cd
444
  # via wandb
445
+ gradio==6.13.0 \
446
+ --hash=sha256:23457dde02202d97f636a5c170967a846297e20f40c3152b41aa4c3460245e3b \
447
+ --hash=sha256:46953f88aad36db9bc369ad2d1d6c4f200274da28f232b54842b2d4942a24f8f
448
+ # via openenv-core
449
+ gradio-client==2.5.0 \
450
+ --hash=sha256:4cde99bad62149595c30c90876ca2e405e3a13687ecf895474f3412cb476673d \
451
+ --hash=sha256:d43e2179c29076292a76485ad7ed2e6eaa19d14ac58283bd7f5beabfe4ca958c
452
+ # via
453
+ # gradio
454
+ # hf-gradio
455
+ griffelib==2.0.2 \
456
+ --hash=sha256:3cf20b3bc470e83763ffbf236e0076b1211bac1bc67de13daf494640f2de707e \
457
+ --hash=sha256:925c857658fb1ba40c0772c37acbc2ab650bd794d9c1b9726922e36ea4117ea1
458
+ # via fastmcp
459
+ groovy==0.1.2 \
460
+ --hash=sha256:25c1dc09b3f9d7e292458aa762c6beb96ea037071bf5e917fc81fb78d2231083 \
461
+ --hash=sha256:7f7975bab18c729a257a8b1ae9dcd70b7cafb1720481beae47719af57c35fa64
462
+ # via gradio
463
  h11==0.16.0 \
464
  --hash=sha256:4e35b956cf45792e4caa5885e69fba00bdbc6ffafbfa020300e549b208ee5ff1 \
465
  --hash=sha256:63cf8bbe7522de3bf65932fda1d9c2772064ffb3dae62d55932da54b31cb6c86
466
  # via
467
  # httpcore
468
  # uvicorn
469
+ hf-gradio==0.4.1 \
470
+ --hash=sha256:76b8cb8be6abe62d74c1ad2d35b42f0629db89aa9e1a8d033cecfe7c856eeab3 \
471
+ --hash=sha256:a017d942618f0d495a58ee4563047fa04bef614c00e0cb789a9a6d0633cffa7b
472
+ # via gradio
473
  hf-xet==1.4.3 ; platform_machine == 'AMD64' or platform_machine == 'aarch64' or platform_machine == 'amd64' or platform_machine == 'arm64' or platform_machine == 'x86_64' \
474
  --hash=sha256:39f2d2e9654cd9b4319885733993807aab6de9dfbd34c42f0b78338d6617421f \
475
  --hash=sha256:49ad8a8cead2b56051aa84d7fce3e1335efe68df3cf6c058f22a65513885baac \
 
508
  # via
509
  # ci-triage-env
510
  # datasets
511
+ # fastmcp
512
+ # gradio
513
+ # gradio-client
514
  # huggingface-hub
515
+ # mcp
516
+ # openai
517
+ # openenv-core
518
+ # safehttpx
519
+ httpx-sse==0.4.3 \
520
+ --hash=sha256:0ac1c9fe3c0afad2e0ebb25a934a59f4c7823b60792691f779fad2c5568830fc \
521
+ --hash=sha256:9b1ed0127459a66014aec3c56bebd93da3c1bc8bb6618c8082039a44889a755d
522
+ # via mcp
523
  huggingface-hub==1.12.0 \
524
  --hash=sha256:7c3fe85e24b652334e5d456d7a812cd9a071e75630fac4365d9165ab5e4a34b6 \
525
  --hash=sha256:d74939969585ee35748bd66de09baf84099d461bda7287cd9043bfb99b0e424d
 
527
  # accelerate
528
  # ci-triage-env
529
  # datasets
530
+ # gradio
531
+ # gradio-client
532
+ # openenv-core
533
  # tokenizers
534
  # transformers
535
  idna==3.13 \
 
537
  --hash=sha256:892ea0cde124a99ce773decba204c5552b69c3c67ffd5f232eb7696135bc8bb3
538
  # via
539
  # anyio
540
+ # email-validator
541
  # httpx
542
  # requests
543
  # yarl
544
+ importlib-metadata==8.7.1 \
545
+ --hash=sha256:49fef1ae6440c182052f407c8d34a68f72efc36db9ca90dc0113398f2fdde8bb \
546
+ --hash=sha256:5a1f80bf1daa489495071efbb095d75a634cf28a8bc299581244063b53176151
547
+ # via
548
+ # keyring
549
+ # opentelemetry-api
550
+ jaraco-classes==3.4.0 \
551
+ --hash=sha256:47a024b51d0239c0dd8c8540c6c7f484be3b8fcf0b2d85c13825780d3b3f3acd \
552
+ --hash=sha256:f662826b6bed8cace05e7ff873ce0f9283b5c924470fe664fff1c2f00f581790
553
+ # via keyring
554
+ jaraco-context==6.1.2 \
555
+ --hash=sha256:bf8150b79a2d5d91ae48629d8b427a8f7ba0e1097dd6202a9059f29a36379535 \
556
+ --hash=sha256:f1a6c9d391e661cc5b8d39861ff077a7dc24dc23833ccee564b234b81c82dfe3
557
+ # via keyring
558
+ jaraco-functools==4.4.0 \
559
+ --hash=sha256:9eec1e36f45c818d9bf307c8948eb03b2b56cd44087b3cdc989abca1f20b9176 \
560
+ --hash=sha256:da21933b0417b89515562656547a77b4931f98176eb173644c0d35032a33d6bb
561
+ # via keyring
562
+ jeepney==0.9.0 ; sys_platform == 'linux' \
563
+ --hash=sha256:97e5714520c16fc0a45695e5365a2e11b81ea79bba796e26f9f1d178cb182683 \
564
+ --hash=sha256:cf0e9e845622b81e4a28df94c40345400256ec608d0e55bb8a3feaa9163f5732
565
+ # via
566
+ # keyring
567
+ # secretstorage
568
  jinja2==3.1.6 \
569
  --hash=sha256:0137fb05990d35f1275a587e9aee6d56da821fc83491a0fb838183be43f66d6d \
570
  --hash=sha256:85ece4451f492d0c13c5dd7c13a64681a86afae63a5f347908daf103ce6d2f67
571
  # via
572
+ # gradio
573
  # torch
574
  # trl
575
+ jiter==0.14.0 \
576
+ --hash=sha256:02c4a7ab56f746014874f2c525584c0daca1dec37f66fd707ecef3b7e5c2228c \
577
+ --hash=sha256:0ac9cbaa86c10996b92bd12c91659b60f939f8e28fcfa6bc11a0e90a774ce95b \
578
+ --hash=sha256:23ad2a7a9da1935575c820428dd8d2490ce4d23189691ce33da1fc0a58e14e1c \
579
+ --hash=sha256:2fb2ce3a7bc331256dfb14cefc34832366bb28a9aca81deaf43bbf2a5659e607 \
580
+ --hash=sha256:33a20d838b91ef376b3a56896d5b04e725c7df5bc4864cc6569cf046a8d73b6d \
581
+ --hash=sha256:351bf6eda4e3a7ceb876377840c702e9a3e4ecc4624dbfb2d6463c67ae52637d \
582
+ --hash=sha256:376e9dafff914253bb9d46cdc5f7965607fbe7feb0a491c34e35f92b2770702e \
583
+ --hash=sha256:42d6ed359ac49eb922fdd565f209c57340aa06d589c84c8413e42a0f9ae1b842 \
584
+ --hash=sha256:432c4db5255d86a259efde91e55cb4c8d18c0521d844c9e2e7efcce3899fb016 \
585
+ --hash=sha256:4927d09b3e572787cc5e0a5318601448e1ab9391bcef95677f5840c2d00eaa6d \
586
+ --hash=sha256:4e9178be60e229b1b2b0710f61b9e24d1f4f8556985a83ff4c4f95920eea7314 \
587
+ --hash=sha256:5252a7ca23785cef5d02d4ece6077a1b556a410c591b379f82091c3001e14844 \
588
+ --hash=sha256:54b3ddf5786bc7732d293bba3411ac637ecfa200a39983166d1df86a59a43c9f \
589
+ --hash=sha256:5c001d5a646c2a50dc055dd526dad5d5245969e8234d2b1131d0451e81f3a373 \
590
+ --hash=sha256:5dec7c0a3e98d2a3f8a2e67382d0d7c3ac60c69103a4b271da889b4e8bb1e129 \
591
+ --hash=sha256:67f00d94b281174144d6532a04b66a12cb866cbdc47c3af3bfe2973677f9861a \
592
+ --hash=sha256:69539d936fb5d55caf6ecd33e2e884de083ff0ea28579780d56c4403094bb8d9 \
593
+ --hash=sha256:6dd689f5f4a5a33747b28686e051095beb214fe28cfda5e9fe58a295a788f593 \
594
+ --hash=sha256:71527ce13fd5a0c4e40ad37331f8c547177dbb2dd0a93e5278b6a5eecf748804 \
595
+ --hash=sha256:7d9d51eb96c82a9652933bd769fe6de66877d6eb2b2440e281f2938c51b5643e \
596
+ --hash=sha256:7e791e247b8044512e070bd1f3633dc08350d32776d2d6e7473309d0edf256a2 \
597
+ --hash=sha256:7ede4331a1899d604463369c730dbb961ffdc5312bc7f16c41c2896415b1304a \
598
+ --hash=sha256:834bb5bdabca2e91592a03d373838a8d0a1b8bbde7077ae6913fd2fc51812d00 \
599
+ --hash=sha256:844e73b6c56b505e9e169234ea3bdea2ea43f769f847f47ac559ba1d2361ebea \
600
+ --hash=sha256:92cd8b6025981a041f5310430310b55b25ca593972c16407af8837d3d7d2ca01 \
601
+ --hash=sha256:a25ffa2dbbdf8721855612f6dca15c108224b12d0c4024d0ac3d7902132b4211 \
602
+ --hash=sha256:a7e4ccff04ec03614e62c613e976a3a5860dc9714ce8266f44328bdc8b1cab2c \
603
+ --hash=sha256:ae039aaef8de3f8157ecc1fdd4d85043ac4f57538c245a0afaecb8321ec951c3 \
604
+ --hash=sha256:c1dcfbeb93d9ecd9ca128bbf8910120367777973fa193fb9a39c31237d8df165 \
605
+ --hash=sha256:c409578cbd77c338975670ada777add4efd53379667edf0aceea730cabede6fb \
606
+ --hash=sha256:d824ca4148b705970bf4e120924a212fdfca9859a73e42bd7889a63a4ea6bb98 \
607
+ --hash=sha256:e52c076f187405fc21523c746c04399c9af8ece566077ed147b2126f2bcba577 \
608
+ --hash=sha256:e8a39e66dac7153cf3f964a12aad515afa8d74938ec5cc0018adcdae5367c79e \
609
+ --hash=sha256:ee4a72f12847ef29b072aee9ad5474041ab2924106bdca9fcf5d7d965853e057 \
610
+ --hash=sha256:fbd9e482663ca9d005d051330e4d2d8150bb208a209409c10f7e7dfdf7c49da9 \
611
+ --hash=sha256:fc7e37b4b8bc7e80a63ad6cfa5fc11fab27dbfea4cc4ae644b1ab3f273dc348f \
612
+ --hash=sha256:ff3a6465b3a0f54b1a430f45c3c0ba7d61ceb45cbc3e33f9e1a7f638d690baf3
613
+ # via openai
614
+ joserfc==1.6.4 \
615
+ --hash=sha256:34ce5f499bfcc5e9ad4cc75077f9278ab3227b71da9aaf28f9ab705f8a560d3c \
616
+ --hash=sha256:3e4a22b509b41908989237a045e25c8308d5fd47ab96bdae2dd8057c6451003a
617
+ # via authlib
618
+ jsonref==1.1.0 \
619
+ --hash=sha256:32fe8e1d85af0fdefbebce950af85590b22b60f9e95443176adbde4e1ecea552 \
620
+ --hash=sha256:590dc7773df6c21cbf948b5dac07a72a251db28b0238ceecce0a2abfa8ec30a9
621
+ # via fastmcp
622
  jsonschema==4.26.0 \
623
  --hash=sha256:0c26707e2efad8aa1bfc5b7ce170f3fccc2e4918ff85989ba9ffa9facb2be326 \
624
  --hash=sha256:d489f15263b8d200f8387e64b4c3a75f06629559fb73deb8fdfb525f2dab50ce
625
+ # via
626
+ # ci-triage-env
627
+ # mcp
628
+ jsonschema-path==0.4.5 \
629
+ --hash=sha256:7d77a2c3f3ec569a40efe5c5f942c44c1af2a6f96fe0866794c9ef5b8f87fd65 \
630
+ --hash=sha256:c6cd7d577ae290c7defd4f4029e86fdb248ca1bd41a07557795b3c95e5144918
631
+ # via fastmcp
632
  jsonschema-specifications==2025.9.1 \
633
  --hash=sha256:98802fee3a11ee76ecaca44429fda8a41bff98b00a0f2838151b113f210cc6fe \
634
  --hash=sha256:b540987f239e745613c7a9176f3edb72b832a4ac465cf02712288397832b5e8d
635
  # via jsonschema
636
+ keyring==25.7.0 \
637
+ --hash=sha256:be4a0b195f149690c166e850609a477c532ddbfbaed96a404d4e43f8d5e2689f \
638
+ --hash=sha256:fe01bd85eb3f8fb3dd0405defdeac9a5b4f6f0439edbb3149577f244a2e8245b
639
+ # via py-key-value-aio
640
  kiwisolver==1.5.0 \
641
  --hash=sha256:01808c6d15f4c3e8559595d6d1fe6411c68e4a3822b4b9972b44473b24f4e679 \
642
  --hash=sha256:0df54df7e686afa55e6f21fb86195224a6d9beb71d637e8d7920c95cf0f89aac \
 
707
  --hash=sha256:d88b440e37a16e651bda4c7c2b930eb586fd15ca7406cb39e211fcff3bf3017d \
708
  --hash=sha256:de8a88e63464af587c950061a5e6a67d3632e36df62b986892331d4620a35c01 \
709
  --hash=sha256:f9e130248f4462aaa8e2552d547f36ddadbeaa573879158d721bbd33dfe4743a
710
+ # via
711
+ # gradio
712
+ # jinja2
713
  matplotlib==3.10.9 \
714
  --hash=sha256:10cc5ce06d10231c36f40e875f3c7e8050362a4ee8f0ee5d29a6b3277d57bb42 \
715
  --hash=sha256:3fc0364dfbe1d07f6d15c5ebd0c5bf89e126916e5a8667dd4a7a6e84c36653d4 \
 
732
  # via
733
  # ci-triage-env
734
  # seaborn
735
+ mcp==1.27.0 \
736
+ --hash=sha256:5ce1fa81614958e267b21fb2aa34e0aea8e2c6ede60d52aba45fd47246b4d741 \
737
+ --hash=sha256:d3dc35a7eec0d458c1da4976a48f982097ddaab87e278c5511d5a4a56e852b83
738
+ # via fastmcp
739
  mdurl==0.1.2 \
740
  --hash=sha256:84008a41e51615a49fc9966191ff91509e3c40b939176e643fd50a5c2196b8f8 \
741
  --hash=sha256:bb413d29f5eea38f31dd4754dd7377d4465116fb207585f97bf925588687c1ba
742
  # via markdown-it-py
743
+ more-itertools==11.0.2 \
744
+ --hash=sha256:392a9e1e362cbc106a2457d37cabf9b36e5e12efd4ebff1654630e76597df804 \
745
+ --hash=sha256:6e35b35f818b01f691643c6c611bc0902f2e92b46c18fffa77ae1e7c46e912e4
746
+ # via
747
+ # jaraco-classes
748
+ # jaraco-functools
749
  mpmath==1.3.0 \
750
  --hash=sha256:7a28eb2a9774d00c7bc92411c19a89209d5da7c4c9a9e227be8330a23a25b91f \
751
  --hash=sha256:a0b2b9fe80bbcd81a6647ff13108738cfb482d481d826cc0e02f5b35e5c88d2c
 
841
  # accelerate
842
  # contourpy
843
  # datasets
844
+ # gradio
845
  # matplotlib
 
846
  # pandas
847
  # seaborn
848
  # transformers
 
915
  --hash=sha256:4936d1d6780fbe68db454f5e72a42ff64d1fd6397df9f363ae786930fd5c1cd4 \
916
  --hash=sha256:cb7780edb6b14107373c835bf8b72e7a178bac7367e23da7acb108f973f157a6
917
  # via cuda-toolkit
918
+ openai==2.32.0 \
919
+ --hash=sha256:4dcc9badeb4bf54ad0d187453742f290226d30150890b7890711bda4f32f192f \
920
+ --hash=sha256:c54b27a9e4cb8d51f0dd94972ffd1a04437efeb259a9e60d8922b8bd26fe55e0
921
+ # via openenv-core
922
+ openapi-pydantic==0.5.1 \
923
+ --hash=sha256:a3a09ef4586f5bd760a8df7f43028b60cafb6d9f61de2acba9574766255ab146 \
924
+ --hash=sha256:ff6835af6bde7a459fb93eb93bb92b8749b754fc6e51b2f1590a19dc3005ee0d
925
+ # via fastmcp
926
+ openenv-core==0.2.3 \
927
+ --hash=sha256:48aefd774474556297ce012b80f2ceb271db51253d7fd0838e6e2dcc329db0c3 \
928
+ --hash=sha256:f75a20c94452057a5f53a86e6d71a9f6a461524c3d6a865aa9344d257a92b795
929
  # via ci-triage-env
930
+ opentelemetry-api==1.41.1 \
931
+ --hash=sha256:0ad1814d73b875f84494387dae86ce0b12c68556331ce6ce8fe789197c949621 \
932
+ --hash=sha256:a22df900e75c76dc08440710e51f52f1aa6b451b429298896023e60db5b3139f
933
+ # via fastmcp
934
+ orjson==3.11.8 \
935
+ --hash=sha256:0022bb50f90da04b009ce32c512dc1885910daa7cb10b7b0cba4505b16db82a8 \
936
+ --hash=sha256:003646067cc48b7fcab2ae0c562491c9b5d2cbd43f1e5f16d98fd118c5522d34 \
937
+ --hash=sha256:093d489fa039ddade2db541097dbb484999fcc65fc2b0ff9819141e2ab364f25 \
938
+ --hash=sha256:0e32f7154299f42ae66f13488963269e5eccb8d588a65bc839ed986919fc9fac \
939
+ --hash=sha256:14778ffd0f6896aa613951a7fbf4690229aa7a543cb2bfbe9f358e08aafa9546 \
940
+ --hash=sha256:1cd0b77e77c95758f8e1100139844e99f3ccc87e71e6fc8e1c027e55807c549f \
941
+ --hash=sha256:25e0c672a2e32348d2eb33057b41e754091f2835f87222e4675b796b92264f06 \
942
+ --hash=sha256:3cf17c141617b88ced4536b2135c552490f07799f6ad565948ea07bef0dcb9a6 \
943
+ --hash=sha256:3f262401086a3960586af06c054609365e98407151f5ea24a62893a40d80dbbb \
944
+ --hash=sha256:469ac2125611b7c5741a0b3798cd9e5786cbad6345f9f400c77212be89563bec \
945
+ --hash=sha256:48854463b0572cc87dac7d981aa72ed8bf6deedc0511853dc76b8bbd5482d36d \
946
+ --hash=sha256:53a0f57e59a530d18a142f4d4ba6dfc708dc5fdedce45e98ff06b44930a2a48f \
947
+ --hash=sha256:54153d21520a71a4c82a0dbb4523e468941d549d221dc173de0f019678cf3813 \
948
+ --hash=sha256:58a4a208a6fbfdb7a7327b8f201c6014f189f721fd55d047cafc4157af1bc62a \
949
+ --hash=sha256:5d8b5231de76c528a46b57010bbd83fb51e056aa0220a372fd5065e978406f1c \
950
+ --hash=sha256:5f8952d6d2505c003e8f0224ff7858d341fa4e33fef82b91c4ff0ef070f2393c \
951
+ --hash=sha256:6a3d159d5ffa0e3961f353c4b036540996bf8b9697ccc38261c0eac1fd3347a6 \
952
+ --hash=sha256:6dbe9a97bdb4d8d9d5367b52a7c32549bba70b2739c58ef74a6964a6d05ae054 \
953
+ --hash=sha256:6eda5b8b6be91d3f26efb7dc6e5e68ee805bc5617f65a328587b35255f138bf4 \
954
+ --hash=sha256:76070a76e9c5ae661e2d9848f216980d8d533e0f8143e6ed462807b242e3c5e8 \
955
+ --hash=sha256:8e8c6218b614badf8e229b697865df4301afa74b791b6c9ade01d19a9953a942 \
956
+ --hash=sha256:9185589c1f2a944c17e26c9925dcdbc2df061cc4a145395c57f0c51f9b5dbfcd \
957
+ --hash=sha256:96163d9cdc5a202703e9ad1b9ae757d5f0ca62f4fa0cc93d1f27b0e180cc404e \
958
+ --hash=sha256:9b48e274f8824567d74e2158199e269597edf00823a1b12b63d48462bbf5123e \
959
+ --hash=sha256:a5c370674ebabe16c6ccac33ff80c62bf8a6e59439f5e9d40c1f5ab8fd2215b7 \
960
+ --hash=sha256:e0950ed1bcb9893f4293fd5c5a7ee10934fbf82c4101c70be360db23ce24b7d2 \
961
+ --hash=sha256:ea56a955056a6d6c550cf18b3348656a9d9a4f02e2d0c02cabf3c73f1055d506 \
962
+ --hash=sha256:ed193ce51d77a3830cad399a529cd4ef029968761f43ddc549e1bc62b40d88f8 \
963
+ --hash=sha256:ee8db7bfb6fe03581bbab54d7c4124a6dd6a7f4273a38f7267197890f094675f \
964
+ --hash=sha256:f30491bc4f862aa15744b9738517454f1e46e56c972a2be87d70d727d5b2a8f8 \
965
+ --hash=sha256:ff51f9d657d1afb6f410cb435792ce4e1fe427aab23d2fcd727a2876e21d4cb6
966
+ # via gradio
967
  packaging==26.2 \
968
  --hash=sha256:5fc45236b9446107ff2415ce77c807cee2862cb6fac22b8a73826d0693b0980e \
969
  --hash=sha256:ff452ff5a3e828ce110190feff1178bb1f2ea2281fa2075aadb987c2fb221661
970
  # via
971
  # accelerate
972
  # datasets
973
+ # fastmcp
974
+ # gradio
975
+ # gradio-client
976
  # huggingface-hub
977
  # matplotlib
978
  # transformers
 
999
  # via
1000
  # ci-triage-env
1001
  # datasets
1002
+ # gradio
1003
  # seaborn
1004
+ pathable==0.5.0 \
1005
+ --hash=sha256:646e3d09491a6351a0c82632a09c02cdf70a252e73196b36d8a15ba0a114f0a6 \
1006
+ --hash=sha256:d81938348a1cacb525e7c75166270644782c0fb9c8cecc16be033e71427e0ef1
1007
+ # via jsonschema-path
1008
  pillow==12.2.0 \
1009
  --hash=sha256:01afa7cf67f74f09523699b4e88c73fb55c13346d212a59a2db1f86b0a63e8c5 \
1010
  --hash=sha256:03e7e372d5240cc23e9f07deca4d775c0817bffc641b01e9c3af208dbd300987 \
 
1036
  --hash=sha256:f3f40b3c5a968281fd507d519e444c35f0ff171237f4fdde090dd60699458421 \
1037
  --hash=sha256:f490f9368b6fc026f021db16d7ec2fbf7d89e2edb42e8ec09d2c60505f5729c7 \
1038
  --hash=sha256:fc3d34d4a8fbec3e88a79b92e5465e0f9b842b628675850d860b8bd300b159f5
1039
+ # via
1040
+ # gradio
1041
+ # matplotlib
1042
  platformdirs==4.9.6 \
1043
  --hash=sha256:3bfa75b0ad0db84096ae777218481852c0ebc6c727b3168c1b9e0118e458cf0a \
1044
  --hash=sha256:e61adb1d5e5cb3441b4b7710bea7e4c12250ca49439228cc1021c00dcfac0917
1045
+ # via
1046
+ # fastmcp
1047
+ # wandb
1048
  propcache==0.4.1 \
1049
  --hash=sha256:0013cb6f8dde4b2a2f66903b8ba740bdfe378c943c4377a200551ceb27f379e4 \
1050
  --hash=sha256:031dce78b9dc099f4c29785d9cf5577a3faf9ebf74ecbd3c856a7b92768c3df3 \
 
1102
  --hash=sha256:ed0cace939114f62738d808fdcecd4c869222507e266e574799e9c0faa17d486 \
1103
  --hash=sha256:fd04ef36b4a6d599bbdb225dd1d3f51e00105f6d48a28f006da7f9822f2606d8
1104
  # via accelerate
1105
+ py-key-value-aio==0.4.4 \
1106
+ --hash=sha256:18e17564ecae61b987f909fc2cd41ee2012c84b4b1dcb8c055cf8b4bc1bf3f5d \
1107
+ --hash=sha256:e3012e6243ed7cc09bb05457bd4d03b1ba5c2b1ca8700096b3927db79ffbbe55
1108
+ # via fastmcp
1109
  pyarrow==24.0.0 \
1110
  --hash=sha256:0b3537c00fb8d384f15ac1e79b6eb6db04a16514c8c1d22e59a9b95c8ba42868 \
1111
  --hash=sha256:14e31a3c9e35f1ab6356c6378f6f72830e6d2d5f1791df3774a7b097d18a6a1e \
 
1123
  --hash=sha256:b7d9a514e73bc42711e6a35aaccf3587c520024fe0a25d830a1a8a27c15f4f57 \
1124
  --hash=sha256:f7616236ec1bc2b15bfdec22a71ab38851c86f8f05ff64f379e1278cf20c634a
1125
  # via datasets
1126
+ pycparser==3.0 ; implementation_name != 'PyPy' and platform_python_implementation != 'PyPy' \
1127
+ --hash=sha256:600f49d217304a5902ac3c37e1281c9fe94e4d0489de643a9504c5cdfdfc6b29 \
1128
+ --hash=sha256:b727414169a36b7d524c1c3e31839a521725078d7b2ff038656844266160a992
1129
+ # via cffi
1130
  pydantic==2.13.3 \
1131
  --hash=sha256:6db14ac8dfc9a1e57f87ea2c0de670c251240f43cb0c30a5130e9720dc612927 \
1132
  --hash=sha256:af09e9d1d09f4e7fe37145c1f577e1d61ceb9a41924bf0094a36506285d0a84d
1133
  # via
1134
  # ci-triage-env
1135
  # fastapi
1136
+ # fastmcp
1137
+ # gradio
1138
+ # mcp
1139
+ # openai
1140
+ # openapi-pydantic
1141
+ # openenv-core
1142
+ # pydantic-settings
1143
  # wandb
1144
  pydantic-core==2.46.3 \
1145
  --hash=sha256:06d5d8820cbbdb4147578c1fe7ffcd5b83f34508cb9f9ab76e807be7db6ff0a4 \
 
1190
  --hash=sha256:fc331a5314ffddd5385b9ee9d0d2fee0b13c27e0e02dad71b1ae5d6561f51eeb \
1191
  --hash=sha256:fd35aa21299def8db7ef4fe5c4ff862941a9a158ca7b63d61e66fe67d30416b4
1192
  # via pydantic
1193
+ pydantic-settings==2.14.0 \
1194
+ --hash=sha256:24285fd4b0e0c06507dd9fdfd331ee23794305352aaec8fc4eb92d4047aeb67d \
1195
+ --hash=sha256:fc8d5d692eb7092e43c8647c1c35a3ecd00e040fcf02ed86f4cb5458ca62182e
1196
+ # via mcp
1197
+ pydub==0.25.1 \
1198
+ --hash=sha256:65617e33033874b59d87db603aa1ed450633288aefead953b30bded59cb599a6 \
1199
+ --hash=sha256:980a33ce9949cab2a569606b65674d748ecbca4f0796887fd6f46173a7b0d30f
1200
+ # via gradio
1201
  pygments==2.20.0 \
1202
  --hash=sha256:6757cd03768053ff99f3039c1a36d6c0aa0b263438fcab17520b30a303a82b5f \
1203
  --hash=sha256:81a9e26dd42fd28a23a2d169d86d7ac03b46e2f8b59ed4698fb4785f946d0176
1204
  # via rich
1205
+ pyjwt==2.12.1 \
1206
+ --hash=sha256:28ca37c070cad8ba8cd9790cd940535d40274d22f80ab87f3ac6a713e6e8454c \
1207
+ --hash=sha256:c74a7a2adf861c04d002db713dd85f84beb242228e671280bf709d765b03672b
1208
+ # via mcp
1209
  pyparsing==3.3.2 \
1210
  --hash=sha256:850ba148bd908d7e2411587e247a1e4f0327839c40e2e5e6d05a007ecc69911d \
1211
  --hash=sha256:c777f4d763f140633dcb6d8a3eda953bf7a214dc4eff598413c070bcdc117cbc
1212
  # via matplotlib
1213
+ pyperclip==1.11.0 \
1214
+ --hash=sha256:244035963e4428530d9e3a6101a1ef97209c6825edab1567beac148ccc1db1b6 \
1215
+ --hash=sha256:299403e9ff44581cb9ba2ffeed69c7aa96a008622ad0c46cb575ca75b5b84273
1216
+ # via fastmcp
1217
  python-dateutil==2.9.0.post0 \
1218
  --hash=sha256:37dd54208da7e1cd875388217d5e00ebd4179249f90fb72437e91a35459a0ad3 \
1219
  --hash=sha256:a8b2bc7bffae282281c8140a97d3aa9c14da0b136dfe83f850eea9a5f7470427
 
1223
  python-dotenv==1.2.2 \
1224
  --hash=sha256:1d8214789a24de455a8b8bd8ae6fe3c6b69a5e3d64aa8a8e5d68e694bbcb285a \
1225
  --hash=sha256:2c371a91fbd7ba082c2c1dc1f8bf89ca22564a087c2c287cd9b662adde799cf3
1226
+ # via
1227
+ # fastmcp
1228
+ # pydantic-settings
1229
+ # uvicorn
1230
+ python-multipart==0.0.26 \
1231
+ --hash=sha256:08fadc45918cd615e26846437f50c5d6d23304da32c341f289a617127b081f17 \
1232
+ --hash=sha256:c0b169f8c4484c13b0dcf2ef0ec3a4adb255c4b7d18d8e420477d2b1dd03f185
1233
+ # via
1234
+ # gradio
1235
+ # mcp
1236
+ pytz==2026.1.post1 \
1237
+ --hash=sha256:3378dde6a0c3d26719182142c56e60c7f9af7e968076f31aae569d72a0358ee1 \
1238
+ --hash=sha256:f2fd16142fda348286a75e1a524be810bb05d444e5a081f37f7affc635035f7a
1239
+ # via gradio
1240
+ pywin32==311 ; sys_platform == 'win32' \
1241
+ --hash=sha256:184eb5e436dea364dcd3d2316d577d625c0351bf237c4e9a5fabbcfa5a58b151 \
1242
+ --hash=sha256:3ce80b34b22b17ccbd937a6e78e7225d80c52f5ab9940fe0506a1a16f3dab503 \
1243
+ --hash=sha256:750ec6e621af2b948540032557b10a2d43b0cee2ae9758c54154d711cc852d31 \
1244
+ --hash=sha256:a733f1388e1a842abb67ffa8e7aad0e70ac519e09b0f6a784e65a136ec7cefd2 \
1245
+ --hash=sha256:b8c095edad5c211ff31c05223658e71bf7116daa0ecf3ad85f3201ea3190d067 \
1246
+ --hash=sha256:e286f46a9a39c4a18b319c28f59b61de793654af2f395c102b4f819e584b5852
1247
+ # via mcp
1248
+ pywin32-ctypes==0.2.3 ; sys_platform == 'win32' \
1249
+ --hash=sha256:8a1513379d709975552d202d942d9837758905c8d01eb82b8bcc30918929e7b8 \
1250
+ --hash=sha256:d162dc04946d704503b2edc4d55f3dba5c1d539ead017afa00142c38b9885755
1251
+ # via keyring
1252
  pyyaml==6.0.3 \
1253
  --hash=sha256:10892704fc220243f5305762e276552a0395f7beb4dbf9b14ec8fd43b57f126c \
1254
  --hash=sha256:1d37d57ad971609cf3c53ba6a7e365e40660e3be0e5175fa9f2365a379d6095a \
 
1274
  # accelerate
1275
  # ci-triage-env
1276
  # datasets
1277
+ # fastmcp
1278
+ # gradio
1279
  # huggingface-hub
1280
+ # jsonschema-path
1281
+ # openenv-core
1282
  # transformers
1283
  # uvicorn
1284
  # wandb
 
1287
  --hash=sha256:44aefc3142c5b842538163acb373e24cce6632bd54bdb01b21ad5863489f50d8
1288
  # via
1289
  # jsonschema
1290
+ # jsonschema-path
1291
  # jsonschema-specifications
1292
  regex==2026.4.4 \
1293
  --hash=sha256:04bb679bc0bde8a7bfb71e991493d47314e7b98380b083df2447cda4b6edb60f \
 
1329
  --hash=sha256:4e6d1ef462f3626a1f0a0a9c42dd93c63bad33f9f1c1937509b8c5c8718ab56a
1330
  # via
1331
  # datasets
1332
+ # openenv-core
1333
  # wandb
1334
  rich==15.0.0 \
1335
  --hash=sha256:33bd4ef74232fb73fe9279a257718407f169c09b78a87ad3d296f548e27de0bb \
1336
  --hash=sha256:edd07a4824c6b40189fb7ac9bc4c52536e9780fbbfbddf6f1e2502c31b068c36
1337
+ # via
1338
+ # cyclopts
1339
+ # fastmcp
1340
+ # openenv-core
1341
+ # rich-rst
1342
+ # typer
1343
+ rich-rst==1.3.2 \
1344
+ --hash=sha256:a1196fdddf1e364b02ec68a05e8ff8f6914fee10fbca2e6b6735f166bb0da8d4 \
1345
+ --hash=sha256:a99b4907cbe118cf9d18b0b44de272efa61f15117c61e39ebdc431baf5df722a
1346
+ # via cyclopts
1347
  rpds-py==0.30.0 \
1348
  --hash=sha256:07ae8a593e1c3c6b82ca3292efbe73c30b61332fd612e05abee07c79359f292f \
1349
  --hash=sha256:12f90dd7557b6bd57f40abe7747e81e0c0b119bef015ea7726e69fe550e394a4 \
 
1391
  # via
1392
  # jsonschema
1393
  # referencing
1394
+ safehttpx==0.1.7 \
1395
+ --hash=sha256:c4f4a162db6993464d7ca3d7cc4af0ffc6515a606dfd220b9f82c6945d869cde \
1396
+ --hash=sha256:db201c0978c41eddb8bb480f3eee59dd67304fdd91646035e9d9a720049a9d23
1397
+ # via gradio
1398
  safetensors==0.7.0 \
1399
  --hash=sha256:07663963b67e8bd9f0b8ad15bb9163606cd27cc5a1b96235a50d8369803b96b0 \
1400
  --hash=sha256:1d060c70284127fa805085d8f10fbd0962792aed71879d00864acda69dbab981 \
 
1418
  --hash=sha256:636f8336facf092165e27924f223d3c62ca560b1f2bb5dff7ab7fad265361987 \
1419
  --hash=sha256:93e60a40988f4d65e9f4885df477e2fdaff6b73a9ded434c1ab356dd57eefff7
1420
  # via ci-triage-env
1421
+ secretstorage==3.5.0 ; sys_platform == 'linux' \
1422
+ --hash=sha256:0ce65888c0725fcb2c5bc0fdb8e5438eece02c523557ea40ce0703c266248137 \
1423
+ --hash=sha256:f04b8e4689cbce351744d5537bf6b1329c6fc68f91fa666f60a380edddcd11be
1424
+ # via keyring
1425
+ semantic-version==2.10.0 \
1426
+ --hash=sha256:bdabb6d336998cbb378d4b9db3a4b56a1e3235701dc05ea2690d9a997ed5041c \
1427
+ --hash=sha256:de78a3b8e0feda74cabc54aab2da702113e33ac9d9eb9d2389bcf1f58b7d9177
1428
+ # via gradio
1429
  sentry-sdk==2.58.0 \
1430
  --hash=sha256:688d1c704ddecf382ea3326f21a67453d4caa95592d722b7c780a36a9d23109e \
1431
  --hash=sha256:c1144d947352d54e5b7daa63596d9f848adf684989c06c4f5a659f0c85a18f6f
 
1446
  --hash=sha256:4d9debb8b99007ae47165abc08670bd74cb74b5227dda7f643eccc4e9eb5642c \
1447
  --hash=sha256:c106e05d5a61449cf6ba9a1e650227ecfb141590d2a98412103ff35d89fc7b2f
1448
  # via gitdb
1449
+ sniffio==1.3.1 \
1450
+ --hash=sha256:2f6da418d1f1e0fddd844478f41680e794e6051915791a034ff65e5f100525a2 \
1451
+ --hash=sha256:f4324edc670a0f49750a81b895f35c3adb843cca46f0530f79fc1babb23789dc
1452
+ # via openai
1453
+ sse-starlette==3.3.4 \
1454
+ --hash=sha256:84bb06e58939a8b38d8341f1bc9792f06c2b53f48c608dd207582b664fc8f3c1 \
1455
+ --hash=sha256:aaf92fc067af8a5427192895ac028e947b484ac01edbc3caf00e7e7137c7bef1
1456
+ # via mcp
1457
  starlette==1.0.0 \
1458
  --hash=sha256:6a4beaf1f81bb472fd19ea9b918b50dc3a77a6f2e190a12954b25e6ed5eea149 \
1459
  --hash=sha256:d3ec55e0bb321692d275455ddfd3df75fff145d009685eb40dc91fc66b03d38b
1460
+ # via
1461
+ # fastapi
1462
+ # gradio
1463
+ # mcp
1464
+ # sse-starlette
1465
  sympy==1.14.0 \
1466
  --hash=sha256:d3d3fe8df1e5a0b42f0e7bdf50541697dbe7d23746e894990c030e2b05e72517 \
1467
  --hash=sha256:e091cc3e99d2141a0ba2847328f5479b05d94a6635cb96148ccb3f34671bd8f5
 
1484
  --hash=sha256:c9ea31edff2968b44a88f97d784c2f16dc0729b8b143ed004699ebca91f05c48 \
1485
  --hash=sha256:df6c4265b289083bf710dff49bc51ef252f9d5be33a45ee2bed151114a56207b
1486
  # via transformers
1487
+ tomli==2.4.1 \
1488
+ --hash=sha256:0d85819802132122da43cb86656f8d1f8c6587d54ae7dcaf30e90533028b49fe \
1489
+ --hash=sha256:136443dbd7e1dee43c68ac2694fde36b2849865fa258d39bf822c10e8068eac5 \
1490
+ --hash=sha256:47149d5bd38761ac8be13a84864bf0b7b70bc051806bc3669ab1cbc56216b23c \
1491
+ --hash=sha256:4ab97e64ccda8756376892c53a72bd1f964e519c77236368527f758fbc36a53a \
1492
+ --hash=sha256:52c8ef851d9a240f11a88c003eacb03c31fc1c9c4ec64a99a0f922b93874fda9 \
1493
+ --hash=sha256:5a881ab208c0baf688221f8cecc5401bd291d67e38a1ac884d6736cbcd8247e9 \
1494
+ --hash=sha256:5cb41aa38891e073ee49d55fbc7839cfdb2bc0e600add13874d048c94aadddd1 \
1495
+ --hash=sha256:5e262d41726bc187e69af7825504c933b6794dc3fbd5945e41a79bb14c31f585 \
1496
+ --hash=sha256:5ee18d9ebdb417e384b58fe414e8d6af9f4e7a0ae761519fb50f721de398dd4e \
1497
+ --hash=sha256:7c7e1a961a0b2f2472c1ac5b69affa0ae1132c39adcb67aba98568702b9cc23f \
1498
+ --hash=sha256:7f86fd587c4ed9dd76f318225e7d9b29cfc5a9d43de44e5754db8d1128487085 \
1499
+ --hash=sha256:96481a5786729fd470164b47cdb3e0e58062a496f455ee41b4403be77cb5a076 \
1500
+ --hash=sha256:c2541745709bad0264b7d4705ad453b76ccd191e64aa6f0fc66b69a293a45ece \
1501
+ --hash=sha256:c742f741d58a28940ce01d58f0ab2ea3ced8b12402f162f4d534dfe18ba1cd6a \
1502
+ --hash=sha256:da25dc3563bff5965356133435b757a795a17b17d01dbc0f42fb32447ddfd917 \
1503
+ --hash=sha256:ec9bfaf3ad2df51ace80688143a6a4ebc09a248f6ff781a9945e51937008fcbc \
1504
+ --hash=sha256:f758f1b9299d059cc3f6546ae2af89670cb1c4d48ea29c3cacc4fe7de3058257 \
1505
+ --hash=sha256:f8f0fc26ec2cc2b965b7a3b87cd19c5c6b8c5e5f436b984e85f486d652285c30 \
1506
+ --hash=sha256:ff18e6a727ee0ab0388507b89d1bc6a22b138d1e2fa56d1ad494586d61d2eae9 \
1507
+ --hash=sha256:ff2983983d34813c1aeb0fa89091e76c3a22889ee83ab27c5eeb45100560c049
1508
+ # via openenv-core
1509
+ tomli-w==1.2.0 \
1510
+ --hash=sha256:188306098d013b691fcadc011abd66727d3c414c571bb01b1a174ba8c983cf90 \
1511
+ --hash=sha256:2dd14fac5a47c27be9cd4c976af5a12d87fb1f0b4512f81d69cce3b35ae25021
1512
+ # via openenv-core
1513
+ tomlkit==0.14.0 \
1514
+ --hash=sha256:592064ed85b40fa213469f81ac584f67a4f2992509a7c3ea2d632208623a3680 \
1515
+ --hash=sha256:cf00efca415dbd57575befb1f6634c4f42d2d87dbba376128adb42c121b87064
1516
+ # via gradio
1517
  torch==2.11.0 \
1518
  --hash=sha256:0f68f4ac6d95d12e896c3b7a912b5871619542ec54d3649cf48cc1edd4dd2756 \
1519
  --hash=sha256:4b5866312ee6e52ea625cd211dcb97d6a2cdc1131a5f15cc0d87eec948f6dd34 \
 
1532
  # via
1533
  # datasets
1534
  # huggingface-hub
1535
+ # openai
1536
  # transformers
1537
  transformers==5.6.2 \
1538
  --hash=sha256:e657134c3e5a6bc00a3c35f4e2674bb51adfcd89898495b788a18552bac2b91a \
 
1554
  --hash=sha256:b618bc3d721f9a8d30f3e05565be26416d06e9bcc29d49bc491dc26aba674fa8 \
1555
  --hash=sha256:ec070dcfca1408e85ee203c6365001e818c3b7fffe686fd07ff2d68095ca0480
1556
  # via
1557
+ # gradio
1558
+ # hf-gradio
1559
  # huggingface-hub
1560
+ # openenv-core
1561
  # transformers
1562
  typing-extensions==4.15.0 \
1563
  --hash=sha256:0cea48d173cc12fa28ecabc3b837ea3cf6f38c6d1136f85cbaaf598984861466 \
 
1565
  # via
1566
  # aiosignal
1567
  # anyio
1568
+ # exceptiongroup
1569
  # fastapi
1570
+ # gradio
1571
+ # gradio-client
1572
  # huggingface-hub
1573
+ # mcp
1574
+ # openai
1575
+ # opentelemetry-api
1576
+ # py-key-value-aio
1577
  # pydantic
1578
  # pydantic-core
1579
  # referencing
 
1586
  --hash=sha256:ba561c48a67c5958007083d386c3295464928b01faa735ab8547c5692e87f464
1587
  # via
1588
  # fastapi
1589
+ # mcp
1590
  # pydantic
1591
+ # pydantic-settings
1592
  tzdata==2026.2 ; sys_platform == 'emscripten' or sys_platform == 'win32' \
1593
  --hash=sha256:9173fde7d80d9018e02a662e168e5a2d04f87c41ea174b139fbef642eda62d10 \
1594
  --hash=sha256:bbe9af844f658da81a5f95019480da3a89415801f6cc966806612cc7169bffe7
1595
  # via pandas
1596
+ uncalled-for==0.3.1 \
1597
+ --hash=sha256:074cdc92da8356278f93d0ded6f2a66dd883dbecaf9bc89437646ee2289cc200 \
1598
+ --hash=sha256:5e412ac6708f04b56bef5867b5dcf6690ebce4eb7316058d9c50787492bb4bca
1599
+ # via fastmcp
1600
  urllib3==2.6.3 \
1601
  --hash=sha256:1b62b6884944a57dbe321509ab94fd4d3b307075e0c2eae991ac71ee15ad38ed \
1602
  --hash=sha256:bf272323e553dfb2e87d9bfd225ca7b0f467b919d7bbd355436d3fd37cb0acd4
 
1606
  uvicorn==0.46.0 \
1607
  --hash=sha256:bbebbcbed972d162afca128605223022bedd345b7bc7855ce66deb31487a9048 \
1608
  --hash=sha256:fb9da0926999cc6cb22dc7cd71a94a632f078e6ae47ff683c5c420750fb7413d
1609
+ # via
1610
+ # ci-triage-env
1611
+ # fastmcp
1612
+ # gradio
1613
+ # mcp
1614
+ # openenv-core
1615
  uvloop==0.22.1 ; platform_python_implementation != 'PyPy' and sys_platform != 'cygwin' and sys_platform != 'win32' \
1616
  --hash=sha256:3b7f102bf3cb1995cfeaee9321105e8f5da76fdb104cdad8986f85461a1b7b77 \
1617
  --hash=sha256:40631b049d5972c6755b06d0bfe8233b1bd9a8a6392d9d1c45c10b6f9e9b2733 \
 
1671
  --hash=sha256:f537afb3276d12814082a2e9b242bdcf416c2e8fd9f799a737990a1dbe906e5b \
1672
  --hash=sha256:f57b396167a2565a4e8b5e56a5a1c537571733992b226f4f1197d79e94cf0ae5 \
1673
  --hash=sha256:f8979280bdafff686ba5e4d8f97840f929a87ed9cdf133cbbd42f7766774d2aa
1674
+ # via
1675
+ # fastmcp
1676
+ # uvicorn
1677
  websockets==16.0 \
1678
  --hash=sha256:0298d07ee155e2e9fda5be8a9042200dd2e3bb0b8a38482156576f863a9d457c \
1679
  --hash=sha256:08d7af67b64d29823fed316505a89b86705f2b7981c07848fb5e3ea3020c1abe \
 
1700
  --hash=sha256:e0334872c0a37b606418ac52f6ab9cfd17317ac26365f7f65e203e2d0d0d359f \
1701
  --hash=sha256:eaded469f5e5b7294e2bdca0ab06becb6756ea86894a47806456089298813c89 \
1702
  --hash=sha256:f4a32d1bd841d4bcbffdcb3d2ce50c09c3909fbead375ab28d0181af89fd04da
1703
+ # via
1704
+ # fastmcp
1705
+ # openenv-core
1706
+ # uvicorn
1707
  xxhash==3.7.0 \
1708
  --hash=sha256:03f8ff4474ee61c845758ce00711d7087a770d77efb36f7e74a6e867301000b8 \
1709
  --hash=sha256:073c23900a9fbf3d26616c17c830db28af9803677cd5b33aea3224d824111514 \
 
1791
  --hash=sha256:f69f57305656a4852f2a7203efc661d8c042e6cc67f7acd97d8667fb448a426e \
1792
  --hash=sha256:fffc45637bcd6538de8b85f51e3df3223e4ad89bccbfca0481c08c7fc8b7ed7d
1793
  # via aiohttp
1794
+ zipp==3.23.1 \
1795
+ --hash=sha256:0b3596c50a5c700c9cb40ba8d86d9f2cc4807e9bedb06bcdf7fac85633e444dc \
1796
+ --hash=sha256:32120e378d32cd9714ad503c1d024619063ec28aad2248dc6672ad13edfa5110
1797
+ # via importlib-metadata
src/ci_triage_env/env/server.py CHANGED
@@ -1,172 +1,238 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
  import logging
2
  import os
3
- import random
4
- import threading
5
  import uuid
 
6
 
7
- from fastapi import FastAPI, HTTPException
8
- from pydantic import BaseModel
 
9
 
10
  from ci_triage_env.env.episode import EpisodeManager
11
  from ci_triage_env.env.scenario_loader import load_scenarios
12
  from ci_triage_env.env.tools import ALL_TOOL_HANDLERS, ToolHandler
13
- from ci_triage_env.schemas.action import TerminalAction, ToolCall
14
- from ci_triage_env.schemas.episode import EpisodeState
15
- from ci_triage_env.schemas.observation import Observation
16
- from ci_triage_env.schemas.scenario import Scenario
17
- from ci_triage_env.schemas.tools import ALL_TOOLS, MCPToolDef
18
 
19
  logger = logging.getLogger(__name__)
20
 
21
 
22
- class CITriageEnv:
23
- """OpenEnv-style CI triage environment.
24
 
25
- Public surface: 11 MCP tools + reset/step/state lifecycle. The PyPI ``openenv``
26
- package does not actually expose ``MCPEnvironment`` (its name collides with an
27
- unrelated gym-style library); per phase-a1.md "If the path differs, update", we
28
- implement the MCP listing endpoint directly on FastAPI rather than inheriting.
 
29
  """
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
30
 
31
  def __init__(
32
  self,
33
  scenario_source: str | None = None,
34
  scenarios: dict[str, Scenario] | None = None,
35
- ):
36
- self._episodes: dict[str, EpisodeManager] = {}
37
- self._lock = threading.Lock()
38
  if scenarios is not None:
39
- self._scenarios = dict(scenarios)
40
  else:
41
- self._scenarios = load_scenarios(scenario_source)
 
42
  if not self._scenarios:
43
  raise RuntimeError(
44
  "no scenarios found; populate data_artifacts/scenarios/*.json or set "
45
  "CI_TRIAGE_SCENARIO_SOURCE"
46
  )
47
- self._tools: dict[str, ToolHandler] = {h.name: h for h in ALL_TOOL_HANDLERS}
48
- self._tool_defs: dict[str, MCPToolDef] = {t.name: t for t in ALL_TOOLS}
 
 
 
49
 
50
  @property
51
  def scenarios(self) -> dict[str, Scenario]:
52
  return self._scenarios
53
 
54
- @property
55
- def tool_defs(self) -> list[MCPToolDef]:
56
- return list(self._tool_defs.values())
57
-
58
- def _new_episode_id(self) -> str:
59
- return str(uuid.uuid4())
60
-
61
  def _seed_for(self, scenario: Scenario, episode_id: str, override: int | None) -> int:
62
  if override is not None:
63
  return override
64
  return hash((scenario.seed, episode_id)) & 0xFFFFFFFF
65
 
 
 
 
 
 
 
 
 
66
  def reset(
67
  self,
 
 
68
  scenario_id: str | None = None,
69
- seed_override: int | None = None,
70
- ) -> Observation:
71
  if scenario_id is None:
72
- scenario_id = random.choice(list(self._scenarios.keys()))
73
  scenario = self._scenarios.get(scenario_id)
74
  if scenario is None:
75
- raise KeyError(scenario_id)
76
- episode_id = self._new_episode_id()
77
- seed = self._seed_for(scenario, episode_id, seed_override)
78
- manager = EpisodeManager(scenario=scenario, episode_id=episode_id, seed=seed)
79
- with self._lock:
80
- self._episodes[episode_id] = manager
81
- return manager.initial_observation()
82
-
83
- def step(self, episode_id: str, action: dict) -> Observation:
84
- with self._lock:
85
- manager = self._episodes.get(episode_id)
86
- if manager is None:
87
- raise KeyError(episode_id)
88
- if manager.is_terminated:
89
- raise RuntimeError("episode already terminated")
90
-
91
- if action.get("action_type") == "submit_diagnosis":
92
- terminal = TerminalAction.model_validate(action)
93
- return manager.apply_terminal(terminal)
94
-
95
- if "tool_name" in action:
96
- tool_call = ToolCall.model_validate(action)
97
- handler = self._tools.get(tool_call.tool_name)
98
- if handler is None:
99
- raise KeyError(f"unknown tool: {tool_call.tool_name}")
100
- output = handler.call(tool_call.args, manager.scenario, manager.history)
101
- return manager.apply_tool_call(tool_call, output)
102
-
103
- raise ValueError(
104
- "action must be a ToolCall (with tool_name) or a TerminalAction "
105
- "(with action_type='submit_diagnosis')"
106
  )
 
107
 
108
- def state(self, episode_id: str) -> EpisodeState:
109
- with self._lock:
110
- manager = self._episodes.get(episode_id)
111
- if manager is None:
112
- raise KeyError(episode_id)
113
- return manager.to_state()
114
-
115
-
116
- class ResetRequest(BaseModel):
117
- scenario_id: str | None = None
118
- seed_override: int | None = None
119
-
120
-
121
- class StepRequest(BaseModel):
122
- episode_id: str
123
- action: dict
 
 
 
 
 
124
 
 
 
 
 
 
 
 
 
 
 
 
 
125
 
126
- def create_app(env: CITriageEnv) -> FastAPI:
127
- app = FastAPI(title="CI Triage Env")
 
 
128
 
129
- @app.post("/reset")
130
- def reset(req: ResetRequest) -> Observation:
131
- try:
132
- return env.reset(scenario_id=req.scenario_id, seed_override=req.seed_override)
133
- except KeyError as exc:
134
- raise HTTPException(status_code=404, detail=f"unknown scenario_id: {exc.args[0]}") from exc
135
 
136
- @app.post("/step")
137
- def step(req: StepRequest) -> Observation:
138
- try:
139
- return env.step(req.episode_id, req.action)
140
- except KeyError as exc:
141
- raise HTTPException(status_code=404, detail=f"unknown id: {exc.args[0]}") from exc
142
- except RuntimeError as exc:
143
- raise HTTPException(status_code=400, detail=str(exc)) from exc
144
- except (ValueError, Exception) as exc:
145
- if isinstance(exc, HTTPException):
146
- raise
147
- raise HTTPException(status_code=400, detail=str(exc)) from exc
 
 
148
 
149
- @app.get("/state/{episode_id}")
150
- def state(episode_id: str) -> EpisodeState:
151
- try:
152
- return env.state(episode_id)
153
- except KeyError as exc:
154
- raise HTTPException(status_code=404, detail=f"unknown episode_id: {exc.args[0]}") from exc
155
 
156
- @app.get("/mcp/tools")
157
- def list_mcp_tools() -> list[MCPToolDef]:
158
- return env.tool_defs
159
 
160
- return app
 
 
 
161
 
 
 
162
 
163
- def _bootstrap() -> FastAPI:
164
- source = os.environ.get("CI_TRIAGE_SCENARIO_SOURCE")
165
- env = CITriageEnv(scenario_source=source)
166
- return create_app(env)
 
 
 
 
 
 
 
 
 
 
167
 
168
 
169
  if __name__ == "__main__":
170
  import uvicorn
171
 
172
- uvicorn.run(_bootstrap(), host="0.0.0.0", port=8000)
 
1
+ """OpenEnv-compliant CI triage environment.
2
+
3
+ Public surface (registered automatically by ``openenv.core.env_server.http_server.create_app``):
4
+
5
+ - ``POST /reset`` → ``ResetResponse`` with the initial domain Observation
6
+ - ``POST /step`` → ``StepResponse`` for ``CITriageAction``
7
+ - ``GET /state`` → ``CITriageState`` (current EpisodeState)
8
+ - ``GET /schema`` → action / observation / state JSON Schemas
9
+ - ``POST /mcp`` → JSON-RPC ``tools/list`` and ``tools/call``
10
+ - ``WS /mcp`` → MCP over WebSocket
11
+ - ``WS /ws`` → persistent OpenEnv session (canonical ``EnvClient`` path)
12
+ - ``GET /docs`` → Swagger UI
13
+
14
+ Tools are registered with a ``FastMCP`` server so MCP clients can discover them
15
+ via ``tools/list``. Step-level tool calls go through ``CITriageAction``
16
+ (``kind="tool_call"``) so budget/cost bookkeeping stays inside the env.
17
+ """
18
+
19
+ from __future__ import annotations
20
+
21
  import logging
22
  import os
 
 
23
  import uuid
24
+ from typing import Any
25
 
26
+ from fastmcp import FastMCP
27
+ from openenv.core.env_server.http_server import create_app as openenv_create_app
28
+ from openenv.core.env_server.mcp_environment import MCPEnvironment
29
 
30
  from ci_triage_env.env.episode import EpisodeManager
31
  from ci_triage_env.env.scenario_loader import load_scenarios
32
  from ci_triage_env.env.tools import ALL_TOOL_HANDLERS, ToolHandler
33
+ from ci_triage_env.env.wire import CITriageAction, CITriageObservation, CITriageState
34
+ from ci_triage_env.schemas.observation import Observation as DomainObservation
35
+ from ci_triage_env.schemas.scenario import Scenario, ToolOutput
36
+ from ci_triage_env.schemas.tools import ALL_TOOLS
 
37
 
38
  logger = logging.getLogger(__name__)
39
 
40
 
41
+ def _build_mcp_server(handlers: list[ToolHandler]) -> FastMCP:
42
+ """Build a FastMCP server advertising the 11 tools.
43
 
44
+ The function bodies are stubs in Phase A1: they validate args against the
45
+ schema and return placeholder payloads. Real routing into scenario-specific
46
+ tool outputs lands in A2. Cost / budget bookkeeping happens on the env's
47
+ ``/step`` path via ``CITriageAction(kind="tool_call")``, not here, so that
48
+ one canonical path owns episode state.
49
  """
50
+ mcp = FastMCP(name="ci-triage")
51
+ handler_map = {h.name: h for h in handlers}
52
+ tool_defs = {t.name: t for t in ALL_TOOLS}
53
+
54
+ for tool_def in ALL_TOOLS:
55
+ handler = handler_map[tool_def.name]
56
+
57
+ def _make_fn(name: str, h: ToolHandler) -> Any:
58
+ def _fn(arguments: dict | None = None) -> dict:
59
+ args = arguments or {}
60
+ h.validate_args(args)
61
+ placeholder = ToolOutput(
62
+ tool_name=name,
63
+ payload={"stub": True, "tool": name},
64
+ cost_units=h.cost_unit,
65
+ )
66
+ return {"payload": placeholder.payload, "cost_units": placeholder.cost_units}
67
+
68
+ _fn.__name__ = name
69
+ return _fn
70
+
71
+ mcp.tool(
72
+ name=tool_def.name,
73
+ description=tool_def.description,
74
+ )(_make_fn(tool_def.name, handler))
75
+
76
+ # Sanity: ALL_TOOLS already excludes reserved names; the MCPEnvironment will
77
+ # re-validate in __init__ but assert here too for fast feedback.
78
+ reserved = {"reset", "step", "state", "close"}
79
+ assert not (set(tool_defs) & reserved)
80
+ return mcp
81
+
82
+
83
+ class CITriageEnv(MCPEnvironment):
84
+ """CI triage env exposing 11 MCP tools and a structured terminal action."""
85
+
86
+ SUPPORTS_CONCURRENT_SESSIONS: bool = True
87
 
88
  def __init__(
89
  self,
90
  scenario_source: str | None = None,
91
  scenarios: dict[str, Scenario] | None = None,
92
+ ) -> None:
 
 
93
  if scenarios is not None:
94
+ self._scenarios: dict[str, Scenario] = dict(scenarios)
95
  else:
96
+ source = scenario_source or os.environ.get("CI_TRIAGE_SCENARIO_SOURCE")
97
+ self._scenarios = load_scenarios(source)
98
  if not self._scenarios:
99
  raise RuntimeError(
100
  "no scenarios found; populate data_artifacts/scenarios/*.json or set "
101
  "CI_TRIAGE_SCENARIO_SOURCE"
102
  )
103
+
104
+ self._handlers: dict[str, ToolHandler] = {h.name: h for h in ALL_TOOL_HANDLERS}
105
+ super().__init__(mcp_server=_build_mcp_server(ALL_TOOL_HANDLERS))
106
+
107
+ self._episode: EpisodeManager | None = None
108
 
109
  @property
110
  def scenarios(self) -> dict[str, Scenario]:
111
  return self._scenarios
112
 
 
 
 
 
 
 
 
113
  def _seed_for(self, scenario: Scenario, episode_id: str, override: int | None) -> int:
114
  if override is not None:
115
  return override
116
  return hash((scenario.seed, episode_id)) & 0xFFFFFFFF
117
 
118
+ def _wrap(self, domain_obs: DomainObservation) -> CITriageObservation:
119
+ return CITriageObservation(
120
+ done=domain_obs.is_terminal,
121
+ reward=None,
122
+ metadata={},
123
+ payload=domain_obs,
124
+ )
125
+
126
  def reset(
127
  self,
128
+ seed: int | None = None,
129
+ episode_id: str | None = None,
130
  scenario_id: str | None = None,
131
+ **kwargs: Any,
132
+ ) -> CITriageObservation:
133
  if scenario_id is None:
134
+ scenario_id = next(iter(self._scenarios))
135
  scenario = self._scenarios.get(scenario_id)
136
  if scenario is None:
137
+ raise KeyError(f"unknown scenario_id: {scenario_id}")
138
+ if episode_id is None:
139
+ episode_id = str(uuid.uuid4())
140
+ self._episode = EpisodeManager(
141
+ scenario=scenario,
142
+ episode_id=episode_id,
143
+ seed=self._seed_for(scenario, episode_id, seed),
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
144
  )
145
+ return self._wrap(self._episode.initial_observation())
146
 
147
+ def step(
148
+ self,
149
+ action: CITriageAction,
150
+ timeout_s: float | None = None,
151
+ **kwargs: Any,
152
+ ) -> CITriageObservation:
153
+ # Override MCPEnvironment.step so /step always lands here for our typed
154
+ # action. ListToolsAction / CallToolAction still flow through MCP via
155
+ # the /mcp endpoint; clients hitting /step always send CITriageAction.
156
+ return self._step_impl(action, timeout_s=timeout_s, **kwargs)
157
+
158
+ def _step_impl(
159
+ self,
160
+ action: CITriageAction,
161
+ timeout_s: float | None = None,
162
+ **kwargs: Any,
163
+ ) -> CITriageObservation:
164
+ if self._episode is None:
165
+ raise RuntimeError("env has no active episode; call reset first")
166
+ if self._episode.is_terminated:
167
+ raise RuntimeError("episode already terminated")
168
 
169
+ if action.kind == "tool_call":
170
+ if action.tool_call is None:
171
+ raise ValueError("kind='tool_call' requires a tool_call payload")
172
+ handler = self._handlers.get(action.tool_call.tool_name)
173
+ if handler is None:
174
+ raise KeyError(f"unknown tool: {action.tool_call.tool_name}")
175
+ output = handler.call(
176
+ action.tool_call.args,
177
+ self._episode.scenario,
178
+ self._episode.history,
179
+ )
180
+ return self._wrap(self._episode.apply_tool_call(action.tool_call, output))
181
 
182
+ if action.kind == "submit_diagnosis":
183
+ if action.terminal is None:
184
+ raise ValueError("kind='submit_diagnosis' requires a terminal payload")
185
+ return self._wrap(self._episode.apply_terminal(action.terminal))
186
 
187
+ raise ValueError(f"unknown action kind: {action.kind}")
 
 
 
 
 
188
 
189
+ @property
190
+ def state(self) -> CITriageState:
191
+ if self._episode is None:
192
+ return CITriageState(
193
+ episode_id=None,
194
+ step_count=0,
195
+ payload=None,
196
+ )
197
+ domain_state = self._episode.to_state()
198
+ return CITriageState(
199
+ episode_id=domain_state.episode_id,
200
+ step_count=domain_state.step,
201
+ payload=domain_state,
202
+ )
203
 
204
+ def close(self) -> None:
205
+ # Inherit MCPEnvironment.close behavior (clears mcp client/server). We
206
+ # also drop the episode reference so a stale env can't be re-used.
207
+ self._episode = None
208
+ super().close()
 
209
 
 
 
 
210
 
211
+ # ---------------------------------------------------------------------------
212
+ # Module-level FastAPI app for `python -m ci_triage_env.env.server` / uvicorn.
213
+ # Use ``build_app()`` from tests to inject scenarios.
214
+ # ---------------------------------------------------------------------------
215
 
216
+ def build_app(env_factory=None):
217
+ """Build the OpenEnv-canonical FastAPI app.
218
 
219
+ Args:
220
+ env_factory: Callable returning a fresh ``CITriageEnv`` per HTTP request
221
+ (OpenEnv's stateless HTTP semantics) and per WebSocket session.
222
+ Defaults to ``CITriageEnv`` (loads scenarios from
223
+ ``CI_TRIAGE_SCENARIO_SOURCE`` or ``data_artifacts/scenarios``).
224
+ """
225
+ factory = env_factory or CITriageEnv
226
+ return openenv_create_app(
227
+ env=factory,
228
+ action_cls=CITriageAction,
229
+ observation_cls=CITriageObservation,
230
+ env_name="ci-triage",
231
+ max_concurrent_envs=4,
232
+ )
233
 
234
 
235
  if __name__ == "__main__":
236
  import uvicorn
237
 
238
+ uvicorn.run(build_app(), host="0.0.0.0", port=8000)
src/ci_triage_env/env/wire.py ADDED
@@ -0,0 +1,77 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """OpenEnv-compliant wire types for the CI triage env.
2
+
3
+ These wrap our frozen domain Pydantic schemas into OpenEnv's Action / Observation /
4
+ State envelope so the env is consumable by the canonical ``EnvClient``,
5
+ ``serialize_observation`` / ``deserialize_action`` helpers, and HF Spaces' OpenEnv
6
+ runner. The domain schemas in ``ci_triage_env.schemas`` are unchanged.
7
+ """
8
+
9
+ from typing import Literal
10
+
11
+ from openenv.core.env_server.types import Action, Observation, State
12
+ from pydantic import ConfigDict, Field
13
+
14
+ from ci_triage_env.schemas.action import SecondaryAction, TerminalAction, ToolCall
15
+ from ci_triage_env.schemas.diagnosis import DiagnosisLabel
16
+ from ci_triage_env.schemas.episode import EpisodeState
17
+ from ci_triage_env.schemas.observation import Observation as DomainObservation
18
+
19
+
20
+ class CITriageAction(Action):
21
+ """Wire action: discriminated on ``kind``.
22
+
23
+ - ``kind="tool_call"`` carries ``tool_call`` (a domain ``ToolCall``).
24
+ - ``kind="submit_diagnosis"`` carries ``terminal`` (a domain ``TerminalAction``).
25
+
26
+ A separate envelope (rather than directly subclassing OpenEnv's MCP
27
+ ``CallToolAction``) keeps tool-call cost/budget bookkeeping inside our env
28
+ rather than at the FastMCP layer, while still letting agents discover tools
29
+ via the standard MCP ``tools/list`` route.
30
+ """
31
+
32
+ model_config = ConfigDict(extra="forbid", validate_assignment=True)
33
+
34
+ kind: Literal["tool_call", "submit_diagnosis"]
35
+ tool_call: ToolCall | None = None
36
+ terminal: TerminalAction | None = None
37
+
38
+ @classmethod
39
+ def from_tool_call(cls, tool_name: str, args: dict | None = None) -> "CITriageAction":
40
+ return cls(kind="tool_call", tool_call=ToolCall(tool_name=tool_name, args=args or {}))
41
+
42
+ @classmethod
43
+ def from_terminal(
44
+ cls,
45
+ diagnosis: DiagnosisLabel,
46
+ confidence: float,
47
+ secondary_actions: list[SecondaryAction] | None = None,
48
+ ) -> "CITriageAction":
49
+ return cls(
50
+ kind="submit_diagnosis",
51
+ terminal=TerminalAction(
52
+ diagnosis=diagnosis,
53
+ confidence=confidence,
54
+ secondary_actions=secondary_actions or [],
55
+ ),
56
+ )
57
+
58
+
59
+ class CITriageObservation(Observation):
60
+ """Wire observation: OpenEnv envelope (``done``, ``reward``, ``metadata``) plus
61
+ the full domain ``Observation`` as ``payload`` for clients that need scenario,
62
+ budget, tool response, etc."""
63
+
64
+ model_config = ConfigDict(extra="forbid", validate_assignment=True)
65
+
66
+ payload: DomainObservation = Field(description="Domain-level observation")
67
+
68
+
69
+ class CITriageState(State):
70
+ """Wire state: OpenEnv envelope plus the full domain ``EpisodeState``."""
71
+
72
+ model_config = ConfigDict(extra="allow", validate_assignment=True)
73
+
74
+ payload: EpisodeState | None = Field(
75
+ default=None,
76
+ description="Full domain episode state; None before the first reset.",
77
+ )
tests/env/conftest.py CHANGED
@@ -1,27 +1,49 @@
1
  import pytest
2
  from fastapi.testclient import TestClient
3
 
4
- from ci_triage_env.env.server import CITriageEnv, create_app
5
  from ci_triage_env.mock.scenario import make_mock_scenario
6
 
7
 
8
- @pytest.fixture
9
- def env() -> CITriageEnv:
10
- scenarios = {
11
  s.scenario_id: s
12
  for s in [
13
  make_mock_scenario("race_flake", seed=42),
14
  make_mock_scenario("real_bug", seed=7),
15
  ]
16
  }
17
- return CITriageEnv(scenarios=scenarios)
18
 
19
 
20
  @pytest.fixture
21
- def client(env: CITriageEnv) -> TestClient:
22
- return TestClient(create_app(env))
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
23
 
24
 
25
  @pytest.fixture
26
- def known_scenario_id(env: CITriageEnv) -> str:
27
- return next(iter(env.scenarios))
 
1
  import pytest
2
  from fastapi.testclient import TestClient
3
 
4
+ from ci_triage_env.env.server import CITriageEnv, build_app
5
  from ci_triage_env.mock.scenario import make_mock_scenario
6
 
7
 
8
+ def _make_scenarios() -> dict:
9
+ return {
 
10
  s.scenario_id: s
11
  for s in [
12
  make_mock_scenario("race_flake", seed=42),
13
  make_mock_scenario("real_bug", seed=7),
14
  ]
15
  }
 
16
 
17
 
18
  @pytest.fixture
19
+ def scenarios() -> dict:
20
+ return _make_scenarios()
21
+
22
+
23
+ @pytest.fixture
24
+ def env_factory(scenarios):
25
+ """Factory returning a fresh CITriageEnv per request, bound to fixed scenarios.
26
+
27
+ Matches OpenEnv's per-session env model: each WebSocket session and each
28
+ stateless /reset+/step request gets its own instance.
29
+ """
30
+
31
+ def _factory():
32
+ return CITriageEnv(scenarios=scenarios)
33
+
34
+ return _factory
35
+
36
+
37
+ @pytest.fixture
38
+ def app(env_factory):
39
+ return build_app(env_factory=env_factory)
40
+
41
+
42
+ @pytest.fixture
43
+ def client(app) -> TestClient:
44
+ return TestClient(app)
45
 
46
 
47
  @pytest.fixture
48
+ def known_scenario_id(scenarios) -> str:
49
+ return next(iter(scenarios))
tests/env/test_server.py CHANGED
@@ -1,155 +1,216 @@
1
- from concurrent.futures import ThreadPoolExecutor
2
 
3
- from fastapi.testclient import TestClient
 
 
 
 
 
4
 
5
- from ci_triage_env.env.server import CITriageEnv, create_app
6
- from ci_triage_env.mock.scenario import make_mock_scenario
7
- from ci_triage_env.schemas.action import TerminalAction, ToolCall
8
- from ci_triage_env.schemas.diagnosis import DiagnosisLabel
9
- from ci_triage_env.schemas.episode import EpisodeState
10
- from ci_triage_env.schemas.observation import Observation
11
 
 
12
 
13
- def test_server_boots():
14
- env = CITriageEnv(scenarios={make_mock_scenario().scenario_id: make_mock_scenario()})
15
- app = create_app(env)
16
- assert app.title == "CI Triage Env"
17
 
18
 
19
- def test_reset_returns_valid_observation(client: TestClient):
20
- resp = client.post("/reset", json={})
21
- assert resp.status_code == 200
22
- obs = Observation.model_validate(resp.json())
23
- assert obs.failure_summary is not None
24
- assert obs.step == 0
25
- assert obs.is_terminal is False
26
 
27
 
28
- def test_reset_with_specific_scenario_id(client: TestClient, known_scenario_id: str):
29
- resp = client.post("/reset", json={"scenario_id": known_scenario_id})
30
- assert resp.status_code == 200
31
- obs = Observation.model_validate(resp.json())
32
- assert obs.episode_id
33
 
 
 
 
34
 
35
- def test_reset_with_unknown_scenario_id_404(client: TestClient):
36
- resp = client.post("/reset", json={"scenario_id": "does-not-exist"})
37
- assert resp.status_code == 404
38
 
 
 
 
39
 
40
- def test_step_with_tool_call_returns_observation(client: TestClient, known_scenario_id: str):
41
- reset = client.post("/reset", json={"scenario_id": known_scenario_id}).json()
42
- episode_id = reset["episode_id"]
43
- call = ToolCall(tool_name="read_logs", args={"scope": "test"})
44
- resp = client.post("/step", json={"episode_id": episode_id, "action": call.model_dump()})
45
- assert resp.status_code == 200, resp.text
46
- obs = Observation.model_validate(resp.json())
47
- assert obs.tool_response is not None
48
- assert obs.tool_response.tool_name == "read_logs"
49
- assert obs.is_terminal is False
50
-
51
-
52
- def test_step_with_terminal_action_marks_done(client: TestClient, known_scenario_id: str):
53
- reset = client.post("/reset", json={"scenario_id": known_scenario_id}).json()
54
- episode_id = reset["episode_id"]
55
- terminal = TerminalAction(
56
- action_type="submit_diagnosis",
57
- diagnosis=DiagnosisLabel.RACE_FLAKE,
58
- confidence=0.8,
59
- )
60
- resp = client.post("/step", json={"episode_id": episode_id, "action": terminal.model_dump()})
61
  assert resp.status_code == 200, resp.text
62
- obs = Observation.model_validate(resp.json())
63
- assert obs.is_terminal is True
64
-
65
- state_resp = client.get(f"/state/{episode_id}")
66
- state = EpisodeState.model_validate(state_resp.json())
67
- assert state.is_terminated is True
68
- assert state.final_action is not None
69
-
70
-
71
- def test_step_after_terminal_returns_400(client: TestClient, known_scenario_id: str):
72
- reset = client.post("/reset", json={"scenario_id": known_scenario_id}).json()
73
- episode_id = reset["episode_id"]
74
- terminal = TerminalAction(
75
- action_type="submit_diagnosis",
76
- diagnosis=DiagnosisLabel.RACE_FLAKE,
77
- confidence=0.8,
78
- )
79
- client.post("/step", json={"episode_id": episode_id, "action": terminal.model_dump()})
80
- again = client.post("/step", json={"episode_id": episode_id, "action": terminal.model_dump()})
81
- assert again.status_code == 400
82
-
83
-
84
- def test_state_endpoint_returns_episode_state(client: TestClient, known_scenario_id: str):
85
- reset = client.post("/reset", json={"scenario_id": known_scenario_id}).json()
86
- episode_id = reset["episode_id"]
87
- resp = client.get(f"/state/{episode_id}")
88
- assert resp.status_code == 200
89
- state = EpisodeState.model_validate(resp.json())
90
- assert state.episode_id == episode_id
91
- assert state.scenario_id == known_scenario_id
92
- assert state.step == 0
93
- assert state.is_terminated is False
94
-
95
-
96
- def test_state_unknown_episode_404(client: TestClient):
97
- resp = client.get("/state/not-a-real-episode-id")
98
- assert resp.status_code == 404
99
 
100
 
101
- def test_concurrent_resets_get_distinct_episode_ids(client: TestClient, known_scenario_id: str):
102
- def do_reset() -> str:
103
- return client.post("/reset", json={"scenario_id": known_scenario_id}).json()["episode_id"]
104
-
105
- with ThreadPoolExecutor(max_workers=8) as pool:
106
- ids = list(pool.map(lambda _: do_reset(), range(8)))
107
-
108
- assert len(set(ids)) == len(ids)
109
-
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
110
 
111
- def test_mcp_endpoint_lists_all_11_tools(client: TestClient):
112
- resp = client.get("/mcp/tools")
113
- assert resp.status_code == 200
114
- tools = resp.json()
 
 
 
 
 
115
  names = {t["name"] for t in tools}
116
- assert names == {
117
- "read_logs",
118
- "inspect_test_code",
119
- "run_diagnostic",
120
- "cluster_metrics",
121
- "query_flake_history",
122
- "recent_commits",
123
- "check_owner",
124
- "rerun_test",
125
- "quarantine_test",
126
- "file_bug",
127
- "ping_owner",
128
- }
129
  assert len(tools) == 11
130
 
131
 
132
- def test_episode_seeding_deterministic(client: TestClient, known_scenario_id: str):
133
- def run_one() -> EpisodeState:
134
- reset = client.post(
135
- "/reset",
136
- json={"scenario_id": known_scenario_id, "seed_override": 12345},
137
- ).json()
138
- episode_id = reset["episode_id"]
139
- call = ToolCall(tool_name="read_logs", args={"scope": "test"})
140
- client.post("/step", json={"episode_id": episode_id, "action": call.model_dump()})
141
- terminal = TerminalAction(
142
- action_type="submit_diagnosis",
143
- diagnosis=DiagnosisLabel.RACE_FLAKE,
144
- confidence=0.6,
145
- )
146
- client.post("/step", json={"episode_id": episode_id, "action": terminal.model_dump()})
147
- return EpisodeState.model_validate(client.get(f"/state/{episode_id}").json())
 
 
 
148
 
149
  a = run_one()
150
  b = run_one()
151
- assert a.seed == b.seed == 12345
152
- assert a.step == b.step
153
- assert a.is_terminated and b.is_terminated
154
- assert [r.action for r in a.history] == [r.action for r in b.history]
155
- assert [r.cost_charged for r in a.history] == [r.cost_charged for r in b.history]
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """Phase A1 server tests against the OpenEnv-canonical wire format.
2
 
3
+ OpenEnv's HTTP ``/reset`` and ``/step`` endpoints are stateless (a fresh env
4
+ instance is constructed per request). State-preserving multi-step flows go
5
+ over the WebSocket ``/ws`` endpoint, which is the canonical OpenEnv session
6
+ path used by ``EnvClient``. Stateful behavior is therefore validated over
7
+ ``/ws``; HTTP endpoints are validated for shape and error handling.
8
+ """
9
 
10
+ from __future__ import annotations
 
 
 
 
 
11
 
12
+ import json
13
 
14
+ from ci_triage_env.env.server import build_app
15
+ from ci_triage_env.env.wire import CITriageAction
16
+ from ci_triage_env.schemas.diagnosis import DiagnosisLabel
 
17
 
18
 
19
+ def _assert_observation_envelope(payload: dict) -> None:
20
+ assert "observation" in payload
21
+ assert "reward" in payload
22
+ assert "done" in payload
 
 
 
23
 
24
 
25
+ # ---------------------------------------------------------------------------
26
+ # A1.1 Server boot
27
+ # ---------------------------------------------------------------------------
 
 
28
 
29
+ def test_server_boots(env_factory):
30
+ app = build_app(env_factory=env_factory)
31
+ assert app.title # FastAPI app instantiated
32
 
 
 
 
33
 
34
+ # ---------------------------------------------------------------------------
35
+ # A1.2 / A1.3 HTTP /reset shape
36
+ # ---------------------------------------------------------------------------
37
 
38
+ def test_reset_returns_valid_observation(client):
39
+ resp = client.post("/reset", json={})
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
40
  assert resp.status_code == 200, resp.text
41
+ body = resp.json()
42
+ _assert_observation_envelope(body)
43
+ assert body["done"] is False
44
+ obs_payload = body["observation"]["payload"]
45
+ assert obs_payload["failure_summary"] is not None
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
46
 
47
 
48
+ def test_reset_with_specific_scenario_id(client, known_scenario_id):
49
+ resp = client.post("/reset", json={"scenario_id": known_scenario_id})
50
+ assert resp.status_code == 200, resp.text
51
+ body = resp.json()
52
+ obs_payload = body["observation"]["payload"]
53
+ assert obs_payload["episode_id"]
54
+
55
+
56
+ # ---------------------------------------------------------------------------
57
+ # A1.4 Unknown scenario surfaces as a server error
58
+ # ---------------------------------------------------------------------------
59
+
60
+ def test_reset_with_unknown_scenario_id_errors(app):
61
+ from fastapi.testclient import TestClient
62
+
63
+ nonraising = TestClient(app, raise_server_exceptions=False)
64
+ resp = nonraising.post("/reset", json={"scenario_id": "does-not-exist"})
65
+ assert resp.status_code >= 400
66
+
67
+
68
+ # ---------------------------------------------------------------------------
69
+ # A1.5–A1.8: Stateful flows over WebSocket /ws
70
+ # ---------------------------------------------------------------------------
71
+
72
+ def _ws_send_recv(ws, message: dict) -> dict:
73
+ ws.send_text(json.dumps(message))
74
+ return json.loads(ws.receive_text())
75
+
76
+
77
+ def test_step_with_tool_call_returns_observation(client, known_scenario_id):
78
+ with client.websocket_connect("/ws") as ws:
79
+ _ws_send_recv(ws, {"type": "reset", "data": {"scenario_id": known_scenario_id}})
80
+ action = CITriageAction.from_tool_call("read_logs", {"scope": "test"})
81
+ resp = _ws_send_recv(ws, {"type": "step", "data": action.model_dump()})
82
+ assert resp["type"] == "observation"
83
+ payload = resp["data"]["observation"]["payload"]
84
+ assert payload["tool_response"] is not None
85
+ assert payload["tool_response"]["tool_name"] == "read_logs"
86
+ assert resp["data"]["done"] is False
87
+
88
+
89
+ def test_step_with_terminal_action_marks_done(client, known_scenario_id):
90
+ with client.websocket_connect("/ws") as ws:
91
+ _ws_send_recv(ws, {"type": "reset", "data": {"scenario_id": known_scenario_id}})
92
+ terminal = CITriageAction.from_terminal(DiagnosisLabel.RACE_FLAKE, confidence=0.8)
93
+ step = _ws_send_recv(ws, {"type": "step", "data": terminal.model_dump()})
94
+ assert step["data"]["done"] is True
95
+ assert step["data"]["observation"]["payload"]["is_terminal"] is True
96
+
97
+ state = _ws_send_recv(ws, {"type": "state"})
98
+ assert state["type"] == "state"
99
+ assert state["data"]["payload"]["is_terminated"] is True
100
+ assert state["data"]["payload"]["final_action"] is not None
101
+
102
+
103
+ def test_step_after_terminal_returns_error(client, known_scenario_id):
104
+ with client.websocket_connect("/ws") as ws:
105
+ _ws_send_recv(ws, {"type": "reset", "data": {"scenario_id": known_scenario_id}})
106
+ terminal = CITriageAction.from_terminal(DiagnosisLabel.RACE_FLAKE, confidence=0.8)
107
+ _ws_send_recv(ws, {"type": "step", "data": terminal.model_dump()})
108
+ again = _ws_send_recv(ws, {"type": "step", "data": terminal.model_dump()})
109
+ assert again["type"] == "error"
110
+
111
+
112
+ def test_state_endpoint_returns_episode_state(client, known_scenario_id):
113
+ with client.websocket_connect("/ws") as ws:
114
+ _ws_send_recv(ws, {"type": "reset", "data": {"scenario_id": known_scenario_id}})
115
+ state = _ws_send_recv(ws, {"type": "state"})
116
+ assert state["type"] == "state"
117
+ payload = state["data"]["payload"]
118
+ assert payload is not None
119
+ assert payload["scenario_id"] == known_scenario_id
120
+ assert payload["is_terminated"] is False
121
+
122
+
123
+ # ---------------------------------------------------------------------------
124
+ # A1.9 Distinct episode_ids across concurrent sessions
125
+ # ---------------------------------------------------------------------------
126
+
127
+ def test_concurrent_ws_sessions_get_distinct_episode_ids(client, known_scenario_id):
128
+ episode_ids: list[str] = []
129
+ with client.websocket_connect("/ws") as ws_a, client.websocket_connect("/ws") as ws_b:
130
+ for ws in (ws_a, ws_b):
131
+ obs = _ws_send_recv(ws, {"type": "reset", "data": {"scenario_id": known_scenario_id}})
132
+ episode_ids.append(obs["data"]["observation"]["payload"]["episode_id"])
133
+ assert episode_ids[0] != episode_ids[1]
134
+
135
+
136
+ # ---------------------------------------------------------------------------
137
+ # A1.10 MCP /mcp tools/list — canonical OpenEnv MCP discovery
138
+ # ---------------------------------------------------------------------------
139
+
140
+ EXPECTED_TOOL_NAMES = {
141
+ "read_logs",
142
+ "inspect_test_code",
143
+ "run_diagnostic",
144
+ "cluster_metrics",
145
+ "query_flake_history",
146
+ "recent_commits",
147
+ "check_owner",
148
+ "rerun_test",
149
+ "quarantine_test",
150
+ "file_bug",
151
+ "ping_owner",
152
+ }
153
+
154
+
155
+ def test_mcp_endpoint_lists_all_11_tools(client):
156
+ # Establish an MCP session first so subsequent tools/list shares it.
157
+ create = client.post(
158
+ "/mcp",
159
+ json={"jsonrpc": "2.0", "id": "1", "method": "openenv/session/create", "params": {}},
160
+ )
161
+ assert create.status_code == 200, create.text
162
+ session_id = create.json()["result"]["session_id"]
163
 
164
+ resp = client.post(
165
+ "/mcp",
166
+ json={"jsonrpc": "2.0", "id": "2", "method": "tools/list", "params": {}},
167
+ headers={"X-OpenEnv-Session-Id": session_id},
168
+ )
169
+ assert resp.status_code == 200, resp.text
170
+ body = resp.json()
171
+ assert "result" in body, body
172
+ tools = body["result"]["tools"]
173
  names = {t["name"] for t in tools}
174
+ assert names == EXPECTED_TOOL_NAMES
 
 
 
 
 
 
 
 
 
 
 
 
175
  assert len(tools) == 11
176
 
177
 
178
+ # ---------------------------------------------------------------------------
179
+ # A1.11 Deterministic seeding
180
+ # ---------------------------------------------------------------------------
181
+
182
+ def test_episode_seeding_deterministic(client, known_scenario_id):
183
+ def run_one() -> dict:
184
+ with client.websocket_connect("/ws") as ws:
185
+ _ws_send_recv(
186
+ ws,
187
+ {
188
+ "type": "reset",
189
+ "data": {"scenario_id": known_scenario_id, "seed": 12345},
190
+ },
191
+ )
192
+ action = CITriageAction.from_tool_call("read_logs", {"scope": "test"})
193
+ _ws_send_recv(ws, {"type": "step", "data": action.model_dump()})
194
+ terminal = CITriageAction.from_terminal(DiagnosisLabel.RACE_FLAKE, confidence=0.6)
195
+ _ws_send_recv(ws, {"type": "step", "data": terminal.model_dump()})
196
+ return _ws_send_recv(ws, {"type": "state"})["data"]["payload"]
197
 
198
  a = run_one()
199
  b = run_one()
200
+ assert a["seed"] == b["seed"] == 12345
201
+ assert a["step"] == b["step"]
202
+ assert a["is_terminated"] and b["is_terminated"]
203
+ assert [r["action"] for r in a["history"]] == [r["action"] for r in b["history"]]
204
+ assert [r["cost_charged"] for r in a["history"]] == [r["cost_charged"] for r in b["history"]]
205
+
206
+
207
+ # ---------------------------------------------------------------------------
208
+ # A1.12 /schema is exposed (OpenEnv standard surface)
209
+ # ---------------------------------------------------------------------------
210
+
211
+ def test_schema_endpoint_returns_action_observation_state(client):
212
+ resp = client.get("/schema")
213
+ assert resp.status_code == 200, resp.text
214
+ body = resp.json()
215
+ assert "action" in body
216
+ assert "observation" in body
uv.lock CHANGED
@@ -25,6 +25,18 @@ wheels = [
25
  { url = "https://files.pythonhosted.org/packages/7e/46/02ac5e262d4af18054b3e922b2baedbb2a03289ee792162de60a865defc5/accelerate-1.13.0-py3-none-any.whl", hash = "sha256:cf1a3efb96c18f7b152eb0fa7490f3710b19c3f395699358f08decca2b8b62e0", size = 383744, upload-time = "2026-03-04T19:34:10.313Z" },
26
  ]
27
 
 
 
 
 
 
 
 
 
 
 
 
 
28
  [[package]]
29
  name = "aiohappyeyeballs"
30
  version = "2.6.1"
@@ -138,6 +150,91 @@ wheels = [
138
  { url = "https://files.pythonhosted.org/packages/64/b4/17d4b0b2a2dc85a6df63d1157e028ed19f90d4cd97c36717afef2bc2f395/attrs-26.1.0-py3-none-any.whl", hash = "sha256:c647aa4a12dfbad9333ca4e71fe62ddc36f4e63b2d260a37a8b83d2f043ac309", size = 67548, upload-time = "2026-03-19T14:22:23.645Z" },
139
  ]
140
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
141
  [[package]]
142
  name = "certifi"
143
  version = "2026.4.22"
@@ -147,6 +244,42 @@ wheels = [
147
  { url = "https://files.pythonhosted.org/packages/22/30/7cd8fdcdfbc5b869528b079bfb76dcdf6056b1a2097a662e5e8c04f42965/certifi-2026.4.22-py3-none-any.whl", hash = "sha256:3cb2210c8f88ba2318d29b0388d1023c8492ff72ecdde4ebdaddbb13a31b1c4a", size = 135707, upload-time = "2026-04-22T11:26:09.372Z" },
148
  ]
149
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
150
  [[package]]
151
  name = "charset-normalizer"
152
  version = "3.4.7"
@@ -198,7 +331,7 @@ dependencies = [
198
  { name = "httpx" },
199
  { name = "huggingface-hub" },
200
  { name = "jsonschema" },
201
- { name = "openenv" },
202
  { name = "pydantic" },
203
  { name = "pyyaml" },
204
  { name = "uvicorn", extra = ["standard"] },
@@ -240,7 +373,7 @@ requires-dist = [
240
  { name = "matplotlib", marker = "extra == 'training'", specifier = ">=3.8" },
241
  { name = "mypy", marker = "extra == 'dev'", specifier = ">=1.10" },
242
  { name = "openai", marker = "extra == 'data'", specifier = ">=1.40" },
243
- { name = "openenv", specifier = ">=0.1.13" },
244
  { name = "pandas", marker = "extra == 'training'", specifier = ">=2.2" },
245
  { name = "pydantic", specifier = ">=2.7,<3.0" },
246
  { name = "pytest", marker = "extra == 'dev'", specifier = ">=8" },
@@ -363,6 +496,51 @@ toml = [
363
  { name = "tomli", marker = "python_full_version <= '3.11'" },
364
  ]
365
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
366
  [[package]]
367
  name = "cuda-bindings"
368
  version = "13.2.0"
@@ -437,6 +615,21 @@ wheels = [
437
  { url = "https://files.pythonhosted.org/packages/e7/05/c19819d5e3d95294a6f5947fb9b9629efb316b96de511b418c53d245aae6/cycler-0.12.1-py3-none-any.whl", hash = "sha256:85cef7cff222d8644161529808465972e51340599459b8ac3ccbac5a854e0d30", size = 8321, upload-time = "2023-10-07T05:32:16.783Z" },
438
  ]
439
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
440
  [[package]]
441
  name = "datasets"
442
  version = "4.8.4"
@@ -480,6 +673,58 @@ wheels = [
480
  { url = "https://files.pythonhosted.org/packages/12/b3/231ffd4ab1fc9d679809f356cebee130ac7daa00d6d6f3206dd4fd137e9e/distro-1.9.0-py3-none-any.whl", hash = "sha256:7bffd925d65168f85027d8da9af6bddab658135b840670a223589bc0c8ef02b2", size = 20277, upload-time = "2023-12-24T09:54:30.421Z" },
481
  ]
482
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
483
  [[package]]
484
  name = "fastapi"
485
  version = "0.136.1"
@@ -496,6 +741,39 @@ wheels = [
496
  { url = "https://files.pythonhosted.org/packages/5a/ff/2e4eca3ade2c22fe1dea7043b8ee9dabe47753349eb1b56a202de8af6349/fastapi-0.136.1-py3-none-any.whl", hash = "sha256:a6e9d7eeada96c93a4d69cb03836b44fa34e2854accb7244a1ece36cd4781c3f", size = 117683, upload-time = "2026-04-23T16:49:42.437Z" },
497
  ]
498
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
499
  [[package]]
500
  name = "filelock"
501
  version = "3.29.0"
@@ -609,6 +887,78 @@ wheels = [
609
  { url = "https://files.pythonhosted.org/packages/f2/c5/a1bc0996af85757903cf2bf444a7824e68e0035ce63fb41d6f76f9def68b/gitpython-3.1.47-py3-none-any.whl", hash = "sha256:489f590edfd6d20571b2c0e72c6a6ac6915ee8b8cd04572330e3842207a78905", size = 209547, upload-time = "2026-04-22T02:44:41.271Z" },
610
  ]
611
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
612
  [[package]]
613
  name = "h11"
614
  version = "0.16.0"
@@ -618,6 +968,19 @@ wheels = [
618
  { url = "https://files.pythonhosted.org/packages/04/4b/29cac41a4d98d144bf5f6d33995617b185d14b22401f75ca86f384e87ff1/h11-0.16.0-py3-none-any.whl", hash = "sha256:63cf8bbe7522de3bf65932fda1d9c2772064ffb3dae62d55932da54b31cb6c86", size = 37515, upload-time = "2025-04-24T03:35:24.344Z" },
619
  ]
620
 
 
 
 
 
 
 
 
 
 
 
 
 
 
621
  [[package]]
622
  name = "hf-xet"
623
  version = "1.4.3"
@@ -684,6 +1047,15 @@ wheels = [
684
  { url = "https://files.pythonhosted.org/packages/2a/39/e50c7c3a983047577ee07d2a9e53faf5a69493943ec3f6a384bdc792deb2/httpx-0.28.1-py3-none-any.whl", hash = "sha256:d909fcccc110f8c7faf814ca82a9a4d816bc5a6dbfea25d6591d6985b8ba59ad", size = 73517, upload-time = "2024-12-06T15:37:21.509Z" },
685
  ]
686
 
 
 
 
 
 
 
 
 
 
687
  [[package]]
688
  name = "huggingface-hub"
689
  version = "1.12.0"
@@ -713,6 +1085,18 @@ wheels = [
713
  { url = "https://files.pythonhosted.org/packages/5d/13/ad7d7ca3808a898b4612b6fe93cde56b53f3034dcde235acb1f0e1df24c6/idna-3.13-py3-none-any.whl", hash = "sha256:892ea0cde124a99ce773decba204c5552b69c3c67ffd5f232eb7696135bc8bb3", size = 68629, upload-time = "2026-04-22T16:42:40.909Z" },
714
  ]
715
 
 
 
 
 
 
 
 
 
 
 
 
 
716
  [[package]]
717
  name = "iniconfig"
718
  version = "2.3.0"
@@ -722,6 +1106,51 @@ wheels = [
722
  { url = "https://files.pythonhosted.org/packages/cb/b1/3846dd7f199d53cb17f49cba7e651e9ce294d8497c8c150530ed11865bb8/iniconfig-2.3.0-py3-none-any.whl", hash = "sha256:f631c04d2c48c52b84d0d0549c99ff3859c98df65b3101406327ecc7d53fbf12", size = 7484, upload-time = "2025-10-18T21:55:41.639Z" },
723
  ]
724
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
725
  [[package]]
726
  name = "jinja2"
727
  version = "3.1.6"
@@ -787,6 +1216,27 @@ wheels = [
787
  { url = "https://files.pythonhosted.org/packages/7b/91/984aca2ec129e2757d1e4e3c81c3fcda9d0f85b74670a094cc443d9ee949/joblib-1.5.3-py3-none-any.whl", hash = "sha256:5fc3c5039fc5ca8c0276333a188bbd59d6b7ab37fe6632daa76bc7f9ec18e713", size = 309071, upload-time = "2025-12-15T08:41:44.973Z" },
788
  ]
789
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
790
  [[package]]
791
  name = "jsonschema"
792
  version = "4.26.0"
@@ -802,6 +1252,20 @@ wheels = [
802
  { url = "https://files.pythonhosted.org/packages/69/90/f63fb5873511e014207a475e2bb4e8b2e570d655b00ac19a9a0ca0a385ee/jsonschema-4.26.0-py3-none-any.whl", hash = "sha256:d489f15263b8d200f8387e64b4c3a75f06629559fb73deb8fdfb525f2dab50ce", size = 90630, upload-time = "2026-01-07T13:41:05.306Z" },
803
  ]
804
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
805
  [[package]]
806
  name = "jsonschema-specifications"
807
  version = "2025.9.1"
@@ -814,6 +1278,24 @@ wheels = [
814
  { url = "https://files.pythonhosted.org/packages/41/45/1a4ed80516f02155c51f51e8cedb3c1902296743db0bbc66608a0db2814f/jsonschema_specifications-2025.9.1-py3-none-any.whl", hash = "sha256:98802fee3a11ee76ecaca44429fda8a41bff98b00a0f2838151b113f210cc6fe", size = 18437, upload-time = "2025-09-08T01:34:57.871Z" },
815
  ]
816
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
817
  [[package]]
818
  name = "kiwisolver"
819
  version = "1.5.0"
@@ -973,6 +1455,31 @@ wheels = [
973
  { url = "https://files.pythonhosted.org/packages/6f/87/afead29192170917537934c6aff4b008c805fff7b1ccea0c79120d96beda/matplotlib-3.10.9-pp311-pypy311_pp73-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:3fc0364dfbe1d07f6d15c5ebd0c5bf89e126916e5a8667dd4a7a6e84c36653d4", size = 8774002, upload-time = "2026-04-24T00:14:09.816Z" },
974
  ]
975
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
976
  [[package]]
977
  name = "mdurl"
978
  version = "0.1.2"
@@ -982,6 +1489,15 @@ wheels = [
982
  { url = "https://files.pythonhosted.org/packages/b3/38/89ba8ad64ae25be8de66a6d463314cf1eb366222074cfda9ee839c56a4b4/mdurl-0.1.2-py3-none-any.whl", hash = "sha256:84008a41e51615a49fc9966191ff91509e3c40b939176e643fd50a5c2196b8f8", size = 9979, upload-time = "2022-08-14T12:40:09.779Z" },
983
  ]
984
 
 
 
 
 
 
 
 
 
 
985
  [[package]]
986
  name = "mpmath"
987
  version = "1.3.0"
@@ -1307,15 +1823,92 @@ wheels = [
1307
  ]
1308
 
1309
  [[package]]
1310
- name = "openenv"
1311
- version = "0.1.13"
1312
  source = { registry = "https://pypi.org/simple" }
1313
  dependencies = [
1314
- { name = "numpy" },
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1315
  ]
1316
- sdist = { url = "https://files.pythonhosted.org/packages/35/94/c47e8f7303452793a3519c8cbc1b31dfffdedd13aaed821958ab3f152927/openenv-0.1.13.tar.gz", hash = "sha256:726971d2289472c1c20261436bcccdf3edfcf0b201d16aec127815bd83bfcb3d", size = 5112, upload-time = "2020-12-16T11:49:39.777Z" }
1317
  wheels = [
1318
- { url = "https://files.pythonhosted.org/packages/33/7f/e6f4467528161b8f0eb2ec784f4bbcd1fa9ea7acad13c0fb18597013e83b/openenv-0.1.13-py3-none-any.whl", hash = "sha256:813249d7f526f40c6e8b325f705294761a5bc887b9144c3383fa2bae7baa7726", size = 12080, upload-time = "2020-12-16T11:49:38.816Z" },
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1319
  ]
1320
 
1321
  [[package]]
@@ -1356,6 +1949,15 @@ wheels = [
1356
  { url = "https://files.pythonhosted.org/packages/d5/18/7f0bd34ae27b28159aa80f2a6799f47fda34f7fb938a76e20c7b7fe3b200/pandas-3.0.2-cp312-cp312-win_arm64.whl", hash = "sha256:08504503f7101300107ecdc8df73658e4347586db5cfdadabc1592e9d7e7a0fd", size = 9056118, upload-time = "2026-03-31T06:46:54.548Z" },
1357
  ]
1358
 
 
 
 
 
 
 
 
 
 
1359
  [[package]]
1360
  name = "pathspec"
1361
  version = "1.1.0"
@@ -1490,6 +2092,31 @@ wheels = [
1490
  { url = "https://files.pythonhosted.org/packages/8c/c7/7bb2e321574b10df20cbde462a94e2b71d05f9bbda251ef27d104668306a/psutil-7.2.2-cp37-abi3-win_arm64.whl", hash = "sha256:8c233660f575a5a89e6d4cb65d9f938126312bca76d8fe087b947b3a1aaac9ee", size = 134617, upload-time = "2026-01-28T18:15:36.514Z" },
1491
  ]
1492
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1493
  [[package]]
1494
  name = "pyarrow"
1495
  version = "24.0.0"
@@ -1512,6 +2139,15 @@ wheels = [
1512
  { url = "https://files.pythonhosted.org/packages/66/1c/e3e72c8014ad2743ca64a701652c733cc5cbcee15c0463a32a8c55518d9e/pyarrow-24.0.0-cp312-cp312-win_amd64.whl", hash = "sha256:295f0a7f2e242dabd513737cf076007dc5b2d59237e3eca37b05c0c6446f3826", size = 27355660, upload-time = "2026-04-21T10:48:01.718Z" },
1513
  ]
1514
 
 
 
 
 
 
 
 
 
 
1515
  [[package]]
1516
  name = "pydantic"
1517
  version = "2.13.3"
@@ -1527,6 +2163,11 @@ wheels = [
1527
  { url = "https://files.pythonhosted.org/packages/f3/0a/fd7d723f8f8153418fb40cf9c940e82004fce7e987026b08a68a36dd3fe7/pydantic-2.13.3-py3-none-any.whl", hash = "sha256:6db14ac8dfc9a1e57f87ea2c0de670c251240f43cb0c30a5130e9720dc612927", size = 471981, upload-time = "2026-04-20T14:46:41.402Z" },
1528
  ]
1529
 
 
 
 
 
 
1530
  [[package]]
1531
  name = "pydantic-core"
1532
  version = "2.46.3"
@@ -1584,6 +2225,29 @@ wheels = [
1584
  { url = "https://files.pythonhosted.org/packages/07/0f/1c34a74c8d07136f0d729ffe5e1fdab04fbdaa7684f61a92f92511a84a15/pydantic_core-2.46.3-pp311-pypy311_pp73-win_amd64.whl", hash = "sha256:b00b76f7142fc60c762ce579bd29c8fa44aaa56592dd3c54fab3928d0d4ca6ff", size = 2184144, upload-time = "2026-04-20T14:42:57Z" },
1585
  ]
1586
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1587
  [[package]]
1588
  name = "pygments"
1589
  version = "2.20.0"
@@ -1593,6 +2257,20 @@ wheels = [
1593
  { url = "https://files.pythonhosted.org/packages/f4/7e/a72dd26f3b0f4f2bf1dd8923c85f7ceb43172af56d63c7383eb62b332364/pygments-2.20.0-py3-none-any.whl", hash = "sha256:81a9e26dd42fd28a23a2d169d86d7ac03b46e2f8b59ed4698fb4785f946d0176", size = 1231151, upload-time = "2026-03-29T13:29:30.038Z" },
1594
  ]
1595
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1596
  [[package]]
1597
  name = "pyparsing"
1598
  version = "3.3.2"
@@ -1602,6 +2280,15 @@ wheels = [
1602
  { url = "https://files.pythonhosted.org/packages/10/bd/c038d7cc38edc1aa5bf91ab8068b63d4308c66c4c8bb3cbba7dfbc049f9c/pyparsing-3.3.2-py3-none-any.whl", hash = "sha256:850ba148bd908d7e2411587e247a1e4f0327839c40e2e5e6d05a007ecc69911d", size = 122781, upload-time = "2026-01-21T03:57:55.912Z" },
1603
  ]
1604
 
 
 
 
 
 
 
 
 
 
1605
  [[package]]
1606
  name = "pytest"
1607
  version = "9.0.3"
@@ -1665,6 +2352,46 @@ wheels = [
1665
  { url = "https://files.pythonhosted.org/packages/0b/d7/1959b9648791274998a9c3526f6d0ec8fd2233e4d4acce81bbae76b44b2a/python_dotenv-1.2.2-py3-none-any.whl", hash = "sha256:1d8214789a24de455a8b8bd8ae6fe3c6b69a5e3d64aa8a8e5d68e694bbcb285a", size = 22101, upload-time = "2026-03-01T16:00:25.09Z" },
1666
  ]
1667
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1668
  [[package]]
1669
  name = "pyyaml"
1670
  version = "6.0.3"
@@ -1774,6 +2501,19 @@ wheels = [
1774
  { url = "https://files.pythonhosted.org/packages/82/3b/64d4899d73f91ba49a8c18a8ff3f0ea8f1c1d75481760df8c68ef5235bf5/rich-15.0.0-py3-none-any.whl", hash = "sha256:33bd4ef74232fb73fe9279a257718407f169c09b78a87ad3d296f548e27de0bb", size = 310654, upload-time = "2026-04-12T08:24:02.83Z" },
1775
  ]
1776
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1777
  [[package]]
1778
  name = "rpds-py"
1779
  version = "0.30.0"
@@ -1849,6 +2589,18 @@ wheels = [
1849
  { url = "https://files.pythonhosted.org/packages/c0/98/6beb4b351e472e5f4c4613f7c35a5290b8be2497e183825310c4c3a3984b/ruff-0.15.12-py3-none-win_arm64.whl", hash = "sha256:a538f7a82d061cee7be55542aca1d86d1393d55d81d4fcc314370f4340930d4f", size = 11120821, upload-time = "2026-04-24T18:16:57.979Z" },
1850
  ]
1851
 
 
 
 
 
 
 
 
 
 
 
 
 
1852
  [[package]]
1853
  name = "safetensors"
1854
  version = "0.7.0"
@@ -1942,6 +2694,28 @@ wheels = [
1942
  { url = "https://files.pythonhosted.org/packages/83/11/00d3c3dfc25ad54e731d91449895a79e4bf2384dc3ac01809010ba88f6d5/seaborn-0.13.2-py3-none-any.whl", hash = "sha256:636f8336facf092165e27924f223d3c62ca560b1f2bb5dff7ab7fad265361987", size = 294914, upload-time = "2024-01-25T13:21:49.598Z" },
1943
  ]
1944
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1945
  [[package]]
1946
  name = "sentry-sdk"
1947
  version = "2.58.0"
@@ -2000,6 +2774,19 @@ wheels = [
2000
  { url = "https://files.pythonhosted.org/packages/e9/44/75a9c9421471a6c4805dbf2356f7c181a29c1879239abab1ea2cc8f38b40/sniffio-1.3.1-py3-none-any.whl", hash = "sha256:2f6da418d1f1e0fddd844478f41680e794e6051915791a034ff65e5f100525a2", size = 10235, upload-time = "2024-02-25T23:20:01.196Z" },
2001
  ]
2002
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2003
  [[package]]
2004
  name = "starlette"
2005
  version = "1.0.0"
@@ -2096,6 +2883,24 @@ wheels = [
2096
  { url = "https://files.pythonhosted.org/packages/7b/61/cceae43728b7de99d9b847560c262873a1f6c98202171fd5ed62640b494b/tomli-2.4.1-py3-none-any.whl", hash = "sha256:0d85819802132122da43cb86656f8d1f8c6587d54ae7dcaf30e90533028b49fe", size = 14583, upload-time = "2026-03-25T20:22:03.012Z" },
2097
  ]
2098
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2099
  [[package]]
2100
  name = "torch"
2101
  version = "2.11.0"
@@ -2231,6 +3036,15 @@ wheels = [
2231
  { url = "https://files.pythonhosted.org/packages/ce/e4/dccd7f47c4b64213ac01ef921a1337ee6e30e8c6466046018326977efd95/tzdata-2026.2-py2.py3-none-any.whl", hash = "sha256:bbe9af844f658da81a5f95019480da3a89415801f6cc966806612cc7169bffe7", size = 349321, upload-time = "2026-04-24T15:22:05.876Z" },
2232
  ]
2233
 
 
 
 
 
 
 
 
 
 
2234
  [[package]]
2235
  name = "urllib3"
2236
  version = "2.6.3"
@@ -2487,3 +3301,12 @@ wheels = [
2487
  { url = "https://files.pythonhosted.org/packages/d2/35/aeab955d6c425b227d5b7247eafb24f2653fedc32f95373a001af5dfeb9e/yarl-1.23.0-cp312-cp312-win_arm64.whl", hash = "sha256:6e87a6e8735b44816e7db0b2fbc9686932df473c826b0d9743148432e10bb9b9", size = 81879, upload-time = "2026-03-01T22:05:40.006Z" },
2488
  { url = "https://files.pythonhosted.org/packages/69/68/c8739671f5699c7dc470580a4f821ef37c32c4cb0b047ce223a7f115757f/yarl-1.23.0-py3-none-any.whl", hash = "sha256:a2df6afe50dea8ae15fa34c9f824a3ee958d785fd5d089063d960bae1daa0a3f", size = 48288, upload-time = "2026-03-01T22:07:51.388Z" },
2489
  ]
 
 
 
 
 
 
 
 
 
 
25
  { url = "https://files.pythonhosted.org/packages/7e/46/02ac5e262d4af18054b3e922b2baedbb2a03289ee792162de60a865defc5/accelerate-1.13.0-py3-none-any.whl", hash = "sha256:cf1a3efb96c18f7b152eb0fa7490f3710b19c3f395699358f08decca2b8b62e0", size = 383744, upload-time = "2026-03-04T19:34:10.313Z" },
26
  ]
27
 
28
+ [[package]]
29
+ name = "aiofile"
30
+ version = "3.9.0"
31
+ source = { registry = "https://pypi.org/simple" }
32
+ dependencies = [
33
+ { name = "caio" },
34
+ ]
35
+ sdist = { url = "https://files.pythonhosted.org/packages/67/e2/d7cb819de8df6b5c1968a2756c3cb4122d4fa2b8fc768b53b7c9e5edb646/aiofile-3.9.0.tar.gz", hash = "sha256:e5ad718bb148b265b6df1b3752c4d1d83024b93da9bd599df74b9d9ffcf7919b", size = 17943, upload-time = "2024-10-08T10:39:35.846Z" }
36
+ wheels = [
37
+ { url = "https://files.pythonhosted.org/packages/50/25/da1f0b4dd970e52bf5a36c204c107e11a0c6d3ed195eba0bfbc664c312b2/aiofile-3.9.0-py3-none-any.whl", hash = "sha256:ce2f6c1571538cbdfa0143b04e16b208ecb0e9cb4148e528af8a640ed51cc8aa", size = 19539, upload-time = "2024-10-08T10:39:32.955Z" },
38
+ ]
39
+
40
  [[package]]
41
  name = "aiohappyeyeballs"
42
  version = "2.6.1"
 
150
  { url = "https://files.pythonhosted.org/packages/64/b4/17d4b0b2a2dc85a6df63d1157e028ed19f90d4cd97c36717afef2bc2f395/attrs-26.1.0-py3-none-any.whl", hash = "sha256:c647aa4a12dfbad9333ca4e71fe62ddc36f4e63b2d260a37a8b83d2f043ac309", size = 67548, upload-time = "2026-03-19T14:22:23.645Z" },
151
  ]
152
 
153
+ [[package]]
154
+ name = "authlib"
155
+ version = "1.7.0"
156
+ source = { registry = "https://pypi.org/simple" }
157
+ dependencies = [
158
+ { name = "cryptography" },
159
+ { name = "joserfc" },
160
+ ]
161
+ sdist = { url = "https://files.pythonhosted.org/packages/d9/82/4d0603f30c1b4629b1f091bb266b0d7986434891d6940a8c87f8098db24e/authlib-1.7.0.tar.gz", hash = "sha256:b3e326c9aa9cc3ea95fe7d89fd880722d3608da4d00e8a27e061e64b48d801d5", size = 175890, upload-time = "2026-04-18T11:00:28.559Z" }
162
+ wheels = [
163
+ { url = "https://files.pythonhosted.org/packages/ca/48/c954218b2a250e23f178f10167c4173fecb5a75d2c206f0a67ba58006c26/authlib-1.7.0-py2.py3-none-any.whl", hash = "sha256:e36817afb02f6f0b6bf55f150782499ddd6ddf44b402bb055d3263cc65ac9ae0", size = 258779, upload-time = "2026-04-18T11:00:26.64Z" },
164
+ ]
165
+
166
+ [[package]]
167
+ name = "backports-tarfile"
168
+ version = "1.2.0"
169
+ source = { registry = "https://pypi.org/simple" }
170
+ sdist = { url = "https://files.pythonhosted.org/packages/86/72/cd9b395f25e290e633655a100af28cb253e4393396264a98bd5f5951d50f/backports_tarfile-1.2.0.tar.gz", hash = "sha256:d75e02c268746e1b8144c278978b6e98e85de6ad16f8e4b0844a154557eca991", size = 86406, upload-time = "2024-05-28T17:01:54.731Z" }
171
+ wheels = [
172
+ { url = "https://files.pythonhosted.org/packages/b9/fa/123043af240e49752f1c4bd24da5053b6bd00cad78c2be53c0d1e8b975bc/backports.tarfile-1.2.0-py3-none-any.whl", hash = "sha256:77e284d754527b01fb1e6fa8a1afe577858ebe4e9dad8919e34c862cb399bc34", size = 30181, upload-time = "2024-05-28T17:01:53.112Z" },
173
+ ]
174
+
175
+ [[package]]
176
+ name = "beartype"
177
+ version = "0.22.9"
178
+ source = { registry = "https://pypi.org/simple" }
179
+ sdist = { url = "https://files.pythonhosted.org/packages/c7/94/1009e248bbfbab11397abca7193bea6626806be9a327d399810d523a07cb/beartype-0.22.9.tar.gz", hash = "sha256:8f82b54aa723a2848a56008d18875f91c1db02c32ef6a62319a002e3e25a975f", size = 1608866, upload-time = "2025-12-13T06:50:30.72Z" }
180
+ wheels = [
181
+ { url = "https://files.pythonhosted.org/packages/71/cc/18245721fa7747065ab478316c7fea7c74777d07f37ae60db2e84f8172e8/beartype-0.22.9-py3-none-any.whl", hash = "sha256:d16c9bbc61ea14637596c5f6fbff2ee99cbe3573e46a716401734ef50c3060c2", size = 1333658, upload-time = "2025-12-13T06:50:28.266Z" },
182
+ ]
183
+
184
+ [[package]]
185
+ name = "brotli"
186
+ version = "1.2.0"
187
+ source = { registry = "https://pypi.org/simple" }
188
+ sdist = { url = "https://files.pythonhosted.org/packages/f7/16/c92ca344d646e71a43b8bb353f0a6490d7f6e06210f8554c8f874e454285/brotli-1.2.0.tar.gz", hash = "sha256:e310f77e41941c13340a95976fe66a8a95b01e783d430eeaf7a2f87e0a57dd0a", size = 7388632, upload-time = "2025-11-05T18:39:42.86Z" }
189
+ wheels = [
190
+ { url = "https://files.pythonhosted.org/packages/7a/ef/f285668811a9e1ddb47a18cb0b437d5fc2760d537a2fe8a57875ad6f8448/brotli-1.2.0-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:15b33fe93cedc4caaff8a0bd1eb7e3dab1c61bb22a0bf5bdfdfd97cd7da79744", size = 863110, upload-time = "2025-11-05T18:38:12.978Z" },
191
+ { url = "https://files.pythonhosted.org/packages/50/62/a3b77593587010c789a9d6eaa527c79e0848b7b860402cc64bc0bc28a86c/brotli-1.2.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:898be2be399c221d2671d29eed26b6b2713a02c2119168ed914e7d00ceadb56f", size = 445438, upload-time = "2025-11-05T18:38:14.208Z" },
192
+ { url = "https://files.pythonhosted.org/packages/cd/e1/7fadd47f40ce5549dc44493877db40292277db373da5053aff181656e16e/brotli-1.2.0-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:350c8348f0e76fff0a0fd6c26755d2653863279d086d3aa2c290a6a7251135dd", size = 1534420, upload-time = "2025-11-05T18:38:15.111Z" },
193
+ { url = "https://files.pythonhosted.org/packages/12/8b/1ed2f64054a5a008a4ccd2f271dbba7a5fb1a3067a99f5ceadedd4c1d5a7/brotli-1.2.0-cp311-cp311-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:2e1ad3fda65ae0d93fec742a128d72e145c9c7a99ee2fcd667785d99eb25a7fe", size = 1632619, upload-time = "2025-11-05T18:38:16.094Z" },
194
+ { url = "https://files.pythonhosted.org/packages/89/5a/7071a621eb2d052d64efd5da2ef55ecdac7c3b0c6e4f9d519e9c66d987ef/brotli-1.2.0-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:40d918bce2b427a0c4ba189df7a006ac0c7277c180aee4617d99e9ccaaf59e6a", size = 1426014, upload-time = "2025-11-05T18:38:17.177Z" },
195
+ { url = "https://files.pythonhosted.org/packages/26/6d/0971a8ea435af5156acaaccec1a505f981c9c80227633851f2810abd252a/brotli-1.2.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:2a7f1d03727130fc875448b65b127a9ec5d06d19d0148e7554384229706f9d1b", size = 1489661, upload-time = "2025-11-05T18:38:18.41Z" },
196
+ { url = "https://files.pythonhosted.org/packages/f3/75/c1baca8b4ec6c96a03ef8230fab2a785e35297632f402ebb1e78a1e39116/brotli-1.2.0-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:9c79f57faa25d97900bfb119480806d783fba83cd09ee0b33c17623935b05fa3", size = 1599150, upload-time = "2025-11-05T18:38:19.792Z" },
197
+ { url = "https://files.pythonhosted.org/packages/0d/1a/23fcfee1c324fd48a63d7ebf4bac3a4115bdb1b00e600f80f727d850b1ae/brotli-1.2.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:844a8ceb8483fefafc412f85c14f2aae2fb69567bf2a0de53cdb88b73e7c43ae", size = 1493505, upload-time = "2025-11-05T18:38:20.913Z" },
198
+ { url = "https://files.pythonhosted.org/packages/36/e5/12904bbd36afeef53d45a84881a4810ae8810ad7e328a971ebbfd760a0b3/brotli-1.2.0-cp311-cp311-win32.whl", hash = "sha256:aa47441fa3026543513139cb8926a92a8e305ee9c71a6209ef7a97d91640ea03", size = 334451, upload-time = "2025-11-05T18:38:21.94Z" },
199
+ { url = "https://files.pythonhosted.org/packages/02/8b/ecb5761b989629a4758c394b9301607a5880de61ee2ee5fe104b87149ebc/brotli-1.2.0-cp311-cp311-win_amd64.whl", hash = "sha256:022426c9e99fd65d9475dce5c195526f04bb8be8907607e27e747893f6ee3e24", size = 369035, upload-time = "2025-11-05T18:38:22.941Z" },
200
+ { url = "https://files.pythonhosted.org/packages/11/ee/b0a11ab2315c69bb9b45a2aaed022499c9c24a205c3a49c3513b541a7967/brotli-1.2.0-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:35d382625778834a7f3061b15423919aa03e4f5da34ac8e02c074e4b75ab4f84", size = 861543, upload-time = "2025-11-05T18:38:24.183Z" },
201
+ { url = "https://files.pythonhosted.org/packages/e1/2f/29c1459513cd35828e25531ebfcbf3e92a5e49f560b1777a9af7203eb46e/brotli-1.2.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:7a61c06b334bd99bc5ae84f1eeb36bfe01400264b3c352f968c6e30a10f9d08b", size = 444288, upload-time = "2025-11-05T18:38:25.139Z" },
202
+ { url = "https://files.pythonhosted.org/packages/3d/6f/feba03130d5fceadfa3a1bb102cb14650798c848b1df2a808356f939bb16/brotli-1.2.0-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:acec55bb7c90f1dfc476126f9711a8e81c9af7fb617409a9ee2953115343f08d", size = 1528071, upload-time = "2025-11-05T18:38:26.081Z" },
203
+ { url = "https://files.pythonhosted.org/packages/2b/38/f3abb554eee089bd15471057ba85f47e53a44a462cfce265d9bf7088eb09/brotli-1.2.0-cp312-cp312-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:260d3692396e1895c5034f204f0db022c056f9e2ac841593a4cf9426e2a3faca", size = 1626913, upload-time = "2025-11-05T18:38:27.284Z" },
204
+ { url = "https://files.pythonhosted.org/packages/03/a7/03aa61fbc3c5cbf99b44d158665f9b0dd3d8059be16c460208d9e385c837/brotli-1.2.0-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:072e7624b1fc4d601036ab3f4f27942ef772887e876beff0301d261210bca97f", size = 1419762, upload-time = "2025-11-05T18:38:28.295Z" },
205
+ { url = "https://files.pythonhosted.org/packages/21/1b/0374a89ee27d152a5069c356c96b93afd1b94eae83f1e004b57eb6ce2f10/brotli-1.2.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:adedc4a67e15327dfdd04884873c6d5a01d3e3b6f61406f99b1ed4865a2f6d28", size = 1484494, upload-time = "2025-11-05T18:38:29.29Z" },
206
+ { url = "https://files.pythonhosted.org/packages/cf/57/69d4fe84a67aef4f524dcd075c6eee868d7850e85bf01d778a857d8dbe0a/brotli-1.2.0-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:7a47ce5c2288702e09dc22a44d0ee6152f2c7eda97b3c8482d826a1f3cfc7da7", size = 1593302, upload-time = "2025-11-05T18:38:30.639Z" },
207
+ { url = "https://files.pythonhosted.org/packages/d5/3b/39e13ce78a8e9a621c5df3aeb5fd181fcc8caba8c48a194cd629771f6828/brotli-1.2.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:af43b8711a8264bb4e7d6d9a6d004c3a2019c04c01127a868709ec29962b6036", size = 1487913, upload-time = "2025-11-05T18:38:31.618Z" },
208
+ { url = "https://files.pythonhosted.org/packages/62/28/4d00cb9bd76a6357a66fcd54b4b6d70288385584063f4b07884c1e7286ac/brotli-1.2.0-cp312-cp312-win32.whl", hash = "sha256:e99befa0b48f3cd293dafeacdd0d191804d105d279e0b387a32054c1180f3161", size = 334362, upload-time = "2025-11-05T18:38:32.939Z" },
209
+ { url = "https://files.pythonhosted.org/packages/1c/4e/bc1dcac9498859d5e353c9b153627a3752868a9d5f05ce8dedd81a2354ab/brotli-1.2.0-cp312-cp312-win_amd64.whl", hash = "sha256:b35c13ce241abdd44cb8ca70683f20c0c079728a36a996297adb5334adfc1c44", size = 369115, upload-time = "2025-11-05T18:38:33.765Z" },
210
+ ]
211
+
212
+ [[package]]
213
+ name = "cachetools"
214
+ version = "7.0.6"
215
+ source = { registry = "https://pypi.org/simple" }
216
+ sdist = { url = "https://files.pythonhosted.org/packages/76/7b/1755ed2c6bfabd1d98b37ae73152f8dcf94aa40fee119d163c19ed484704/cachetools-7.0.6.tar.gz", hash = "sha256:e5d524d36d65703a87243a26ff08ad84f73352adbeafb1cde81e207b456aaf24", size = 37526, upload-time = "2026-04-20T19:02:23.289Z" }
217
+ wheels = [
218
+ { url = "https://files.pythonhosted.org/packages/fe/c4/cf76242a5da1410917107ff14551764aa405a5fd10cd10cf9a5ca8fa77f4/cachetools-7.0.6-py3-none-any.whl", hash = "sha256:4e94956cfdd3086f12042cdd29318f5ced3893014f7d0d059bf3ead3f85b7f8b", size = 13976, upload-time = "2026-04-20T19:02:21.187Z" },
219
+ ]
220
+
221
+ [[package]]
222
+ name = "caio"
223
+ version = "0.9.25"
224
+ source = { registry = "https://pypi.org/simple" }
225
+ sdist = { url = "https://files.pythonhosted.org/packages/92/88/b8527e1b00c1811db339a1df8bd1ae49d146fcea9d6a5c40e3a80aaeb38d/caio-0.9.25.tar.gz", hash = "sha256:16498e7f81d1d0f5a4c0ad3f2540e65fe25691376e0a5bd367f558067113ed10", size = 26781, upload-time = "2025-12-26T15:21:36.501Z" }
226
+ wheels = [
227
+ { url = "https://files.pythonhosted.org/packages/ec/90/543f556fcfcfa270713eef906b6352ab048e1e557afec12925c991dc93c2/caio-0.9.25-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:d6956d9e4a27021c8bd6c9677f3a59eb1d820cc32d0343cea7961a03b1371965", size = 36839, upload-time = "2025-12-26T15:21:40.267Z" },
228
+ { url = "https://files.pythonhosted.org/packages/51/3b/36f3e8ec38dafe8de4831decd2e44c69303d2a3892d16ceda42afed44e1b/caio-0.9.25-cp311-cp311-manylinux2010_x86_64.manylinux2014_x86_64.manylinux_2_12_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:bf84bfa039f25ad91f4f52944452a5f6f405e8afab4d445450978cd6241d1478", size = 80255, upload-time = "2025-12-26T15:22:20.271Z" },
229
+ { url = "https://files.pythonhosted.org/packages/df/ce/65e64867d928e6aff1b4f0e12dba0ef6d5bf412c240dc1df9d421ac10573/caio-0.9.25-cp311-cp311-manylinux_2_34_aarch64.whl", hash = "sha256:ae3d62587332bce600f861a8de6256b1014d6485cfd25d68c15caf1611dd1f7c", size = 80052, upload-time = "2026-03-04T22:08:20.402Z" },
230
+ { url = "https://files.pythonhosted.org/packages/46/90/e278863c47e14ec58309aa2e38a45882fbe67b4cc29ec9bc8f65852d3e45/caio-0.9.25-cp311-cp311-manylinux_2_34_x86_64.whl", hash = "sha256:fc220b8533dcf0f238a6b1a4a937f92024c71e7b10b5a2dfc1c73604a25709bc", size = 78273, upload-time = "2026-03-04T22:08:21.368Z" },
231
+ { url = "https://files.pythonhosted.org/packages/d3/25/79c98ebe12df31548ba4eaf44db11b7cad6b3e7b4203718335620939083c/caio-0.9.25-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:fb7ff95af4c31ad3f03179149aab61097a71fd85e05f89b4786de0359dffd044", size = 36983, upload-time = "2025-12-26T15:21:36.075Z" },
232
+ { url = "https://files.pythonhosted.org/packages/a3/2b/21288691f16d479945968a0a4f2856818c1c5be56881d51d4dac9b255d26/caio-0.9.25-cp312-cp312-manylinux2010_x86_64.manylinux2014_x86_64.manylinux_2_12_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:97084e4e30dfa598449d874c4d8e0c8d5ea17d2f752ef5e48e150ff9d240cd64", size = 82012, upload-time = "2025-12-26T15:22:20.983Z" },
233
+ { url = "https://files.pythonhosted.org/packages/03/c4/8a1b580875303500a9c12b9e0af58cb82e47f5bcf888c2457742a138273c/caio-0.9.25-cp312-cp312-manylinux_2_34_aarch64.whl", hash = "sha256:4fa69eba47e0f041b9d4f336e2ad40740681c43e686b18b191b6c5f4c5544bfb", size = 81502, upload-time = "2026-03-04T22:08:22.381Z" },
234
+ { url = "https://files.pythonhosted.org/packages/d1/1c/0fe770b8ffc8362c48134d1592d653a81a3d8748d764bec33864db36319d/caio-0.9.25-cp312-cp312-manylinux_2_34_x86_64.whl", hash = "sha256:6bebf6f079f1341d19f7386db9b8b1f07e8cc15ae13bfdaff573371ba0575d69", size = 80200, upload-time = "2026-03-04T22:08:23.382Z" },
235
+ { url = "https://files.pythonhosted.org/packages/86/93/1f76c8d1bafe3b0614e06b2195784a3765bbf7b0a067661af9e2dd47fc33/caio-0.9.25-py3-none-any.whl", hash = "sha256:06c0bb02d6b929119b1cfbe1ca403c768b2013a369e2db46bfa2a5761cf82e40", size = 19087, upload-time = "2025-12-26T15:22:00.221Z" },
236
+ ]
237
+
238
  [[package]]
239
  name = "certifi"
240
  version = "2026.4.22"
 
244
  { url = "https://files.pythonhosted.org/packages/22/30/7cd8fdcdfbc5b869528b079bfb76dcdf6056b1a2097a662e5e8c04f42965/certifi-2026.4.22-py3-none-any.whl", hash = "sha256:3cb2210c8f88ba2318d29b0388d1023c8492ff72ecdde4ebdaddbb13a31b1c4a", size = 135707, upload-time = "2026-04-22T11:26:09.372Z" },
245
  ]
246
 
247
+ [[package]]
248
+ name = "cffi"
249
+ version = "2.0.0"
250
+ source = { registry = "https://pypi.org/simple" }
251
+ dependencies = [
252
+ { name = "pycparser", marker = "implementation_name != 'PyPy'" },
253
+ ]
254
+ sdist = { url = "https://files.pythonhosted.org/packages/eb/56/b1ba7935a17738ae8453301356628e8147c79dbb825bcbc73dc7401f9846/cffi-2.0.0.tar.gz", hash = "sha256:44d1b5909021139fe36001ae048dbdde8214afa20200eda0f64c068cac5d5529", size = 523588, upload-time = "2025-09-08T23:24:04.541Z" }
255
+ wheels = [
256
+ { url = "https://files.pythonhosted.org/packages/12/4a/3dfd5f7850cbf0d06dc84ba9aa00db766b52ca38d8b86e3a38314d52498c/cffi-2.0.0-cp311-cp311-macosx_10_13_x86_64.whl", hash = "sha256:b4c854ef3adc177950a8dfc81a86f5115d2abd545751a304c5bcf2c2c7283cfe", size = 184344, upload-time = "2025-09-08T23:22:26.456Z" },
257
+ { url = "https://files.pythonhosted.org/packages/4f/8b/f0e4c441227ba756aafbe78f117485b25bb26b1c059d01f137fa6d14896b/cffi-2.0.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:2de9a304e27f7596cd03d16f1b7c72219bd944e99cc52b84d0145aefb07cbd3c", size = 180560, upload-time = "2025-09-08T23:22:28.197Z" },
258
+ { url = "https://files.pythonhosted.org/packages/b1/b7/1200d354378ef52ec227395d95c2576330fd22a869f7a70e88e1447eb234/cffi-2.0.0-cp311-cp311-manylinux1_i686.manylinux2014_i686.manylinux_2_17_i686.manylinux_2_5_i686.whl", hash = "sha256:baf5215e0ab74c16e2dd324e8ec067ef59e41125d3eade2b863d294fd5035c92", size = 209613, upload-time = "2025-09-08T23:22:29.475Z" },
259
+ { url = "https://files.pythonhosted.org/packages/b8/56/6033f5e86e8cc9bb629f0077ba71679508bdf54a9a5e112a3c0b91870332/cffi-2.0.0-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:730cacb21e1bdff3ce90babf007d0a0917cc3e6492f336c2f0134101e0944f93", size = 216476, upload-time = "2025-09-08T23:22:31.063Z" },
260
+ { url = "https://files.pythonhosted.org/packages/dc/7f/55fecd70f7ece178db2f26128ec41430d8720f2d12ca97bf8f0a628207d5/cffi-2.0.0-cp311-cp311-manylinux2014_ppc64le.manylinux_2_17_ppc64le.whl", hash = "sha256:6824f87845e3396029f3820c206e459ccc91760e8fa24422f8b0c3d1731cbec5", size = 203374, upload-time = "2025-09-08T23:22:32.507Z" },
261
+ { url = "https://files.pythonhosted.org/packages/84/ef/a7b77c8bdc0f77adc3b46888f1ad54be8f3b7821697a7b89126e829e676a/cffi-2.0.0-cp311-cp311-manylinux2014_s390x.manylinux_2_17_s390x.whl", hash = "sha256:9de40a7b0323d889cf8d23d1ef214f565ab154443c42737dfe52ff82cf857664", size = 202597, upload-time = "2025-09-08T23:22:34.132Z" },
262
+ { url = "https://files.pythonhosted.org/packages/d7/91/500d892b2bf36529a75b77958edfcd5ad8e2ce4064ce2ecfeab2125d72d1/cffi-2.0.0-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:8941aaadaf67246224cee8c3803777eed332a19d909b47e29c9842ef1e79ac26", size = 215574, upload-time = "2025-09-08T23:22:35.443Z" },
263
+ { url = "https://files.pythonhosted.org/packages/44/64/58f6255b62b101093d5df22dcb752596066c7e89dd725e0afaed242a61be/cffi-2.0.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:a05d0c237b3349096d3981b727493e22147f934b20f6f125a3eba8f994bec4a9", size = 218971, upload-time = "2025-09-08T23:22:36.805Z" },
264
+ { url = "https://files.pythonhosted.org/packages/ab/49/fa72cebe2fd8a55fbe14956f9970fe8eb1ac59e5df042f603ef7c8ba0adc/cffi-2.0.0-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:94698a9c5f91f9d138526b48fe26a199609544591f859c870d477351dc7b2414", size = 211972, upload-time = "2025-09-08T23:22:38.436Z" },
265
+ { url = "https://files.pythonhosted.org/packages/0b/28/dd0967a76aab36731b6ebfe64dec4e981aff7e0608f60c2d46b46982607d/cffi-2.0.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:5fed36fccc0612a53f1d4d9a816b50a36702c28a2aa880cb8a122b3466638743", size = 217078, upload-time = "2025-09-08T23:22:39.776Z" },
266
+ { url = "https://files.pythonhosted.org/packages/2b/c0/015b25184413d7ab0a410775fdb4a50fca20f5589b5dab1dbbfa3baad8ce/cffi-2.0.0-cp311-cp311-win32.whl", hash = "sha256:c649e3a33450ec82378822b3dad03cc228b8f5963c0c12fc3b1e0ab940f768a5", size = 172076, upload-time = "2025-09-08T23:22:40.95Z" },
267
+ { url = "https://files.pythonhosted.org/packages/ae/8f/dc5531155e7070361eb1b7e4c1a9d896d0cb21c49f807a6c03fd63fc877e/cffi-2.0.0-cp311-cp311-win_amd64.whl", hash = "sha256:66f011380d0e49ed280c789fbd08ff0d40968ee7b665575489afa95c98196ab5", size = 182820, upload-time = "2025-09-08T23:22:42.463Z" },
268
+ { url = "https://files.pythonhosted.org/packages/95/5c/1b493356429f9aecfd56bc171285a4c4ac8697f76e9bbbbb105e537853a1/cffi-2.0.0-cp311-cp311-win_arm64.whl", hash = "sha256:c6638687455baf640e37344fe26d37c404db8b80d037c3d29f58fe8d1c3b194d", size = 177635, upload-time = "2025-09-08T23:22:43.623Z" },
269
+ { url = "https://files.pythonhosted.org/packages/ea/47/4f61023ea636104d4f16ab488e268b93008c3d0bb76893b1b31db1f96802/cffi-2.0.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:6d02d6655b0e54f54c4ef0b94eb6be0607b70853c45ce98bd278dc7de718be5d", size = 185271, upload-time = "2025-09-08T23:22:44.795Z" },
270
+ { url = "https://files.pythonhosted.org/packages/df/a2/781b623f57358e360d62cdd7a8c681f074a71d445418a776eef0aadb4ab4/cffi-2.0.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:8eca2a813c1cb7ad4fb74d368c2ffbbb4789d377ee5bb8df98373c2cc0dee76c", size = 181048, upload-time = "2025-09-08T23:22:45.938Z" },
271
+ { url = "https://files.pythonhosted.org/packages/ff/df/a4f0fbd47331ceeba3d37c2e51e9dfc9722498becbeec2bd8bc856c9538a/cffi-2.0.0-cp312-cp312-manylinux1_i686.manylinux2014_i686.manylinux_2_17_i686.manylinux_2_5_i686.whl", hash = "sha256:21d1152871b019407d8ac3985f6775c079416c282e431a4da6afe7aefd2bccbe", size = 212529, upload-time = "2025-09-08T23:22:47.349Z" },
272
+ { url = "https://files.pythonhosted.org/packages/d5/72/12b5f8d3865bf0f87cf1404d8c374e7487dcf097a1c91c436e72e6badd83/cffi-2.0.0-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:b21e08af67b8a103c71a250401c78d5e0893beff75e28c53c98f4de42f774062", size = 220097, upload-time = "2025-09-08T23:22:48.677Z" },
273
+ { url = "https://files.pythonhosted.org/packages/c2/95/7a135d52a50dfa7c882ab0ac17e8dc11cec9d55d2c18dda414c051c5e69e/cffi-2.0.0-cp312-cp312-manylinux2014_ppc64le.manylinux_2_17_ppc64le.whl", hash = "sha256:1e3a615586f05fc4065a8b22b8152f0c1b00cdbc60596d187c2a74f9e3036e4e", size = 207983, upload-time = "2025-09-08T23:22:50.06Z" },
274
+ { url = "https://files.pythonhosted.org/packages/3a/c8/15cb9ada8895957ea171c62dc78ff3e99159ee7adb13c0123c001a2546c1/cffi-2.0.0-cp312-cp312-manylinux2014_s390x.manylinux_2_17_s390x.whl", hash = "sha256:81afed14892743bbe14dacb9e36d9e0e504cd204e0b165062c488942b9718037", size = 206519, upload-time = "2025-09-08T23:22:51.364Z" },
275
+ { url = "https://files.pythonhosted.org/packages/78/2d/7fa73dfa841b5ac06c7b8855cfc18622132e365f5b81d02230333ff26e9e/cffi-2.0.0-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:3e17ed538242334bf70832644a32a7aae3d83b57567f9fd60a26257e992b79ba", size = 219572, upload-time = "2025-09-08T23:22:52.902Z" },
276
+ { url = "https://files.pythonhosted.org/packages/07/e0/267e57e387b4ca276b90f0434ff88b2c2241ad72b16d31836adddfd6031b/cffi-2.0.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:3925dd22fa2b7699ed2617149842d2e6adde22b262fcbfada50e3d195e4b3a94", size = 222963, upload-time = "2025-09-08T23:22:54.518Z" },
277
+ { url = "https://files.pythonhosted.org/packages/b6/75/1f2747525e06f53efbd878f4d03bac5b859cbc11c633d0fb81432d98a795/cffi-2.0.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:2c8f814d84194c9ea681642fd164267891702542f028a15fc97d4674b6206187", size = 221361, upload-time = "2025-09-08T23:22:55.867Z" },
278
+ { url = "https://files.pythonhosted.org/packages/7b/2b/2b6435f76bfeb6bbf055596976da087377ede68df465419d192acf00c437/cffi-2.0.0-cp312-cp312-win32.whl", hash = "sha256:da902562c3e9c550df360bfa53c035b2f241fed6d9aef119048073680ace4a18", size = 172932, upload-time = "2025-09-08T23:22:57.188Z" },
279
+ { url = "https://files.pythonhosted.org/packages/f8/ed/13bd4418627013bec4ed6e54283b1959cf6db888048c7cf4b4c3b5b36002/cffi-2.0.0-cp312-cp312-win_amd64.whl", hash = "sha256:da68248800ad6320861f129cd9c1bf96ca849a2771a59e0344e88681905916f5", size = 183557, upload-time = "2025-09-08T23:22:58.351Z" },
280
+ { url = "https://files.pythonhosted.org/packages/95/31/9f7f93ad2f8eff1dbc1c3656d7ca5bfd8fb52c9d786b4dcf19b2d02217fa/cffi-2.0.0-cp312-cp312-win_arm64.whl", hash = "sha256:4671d9dd5ec934cb9a73e7ee9676f9362aba54f7f34910956b84d727b0d73fb6", size = 177762, upload-time = "2025-09-08T23:22:59.668Z" },
281
+ ]
282
+
283
  [[package]]
284
  name = "charset-normalizer"
285
  version = "3.4.7"
 
331
  { name = "httpx" },
332
  { name = "huggingface-hub" },
333
  { name = "jsonschema" },
334
+ { name = "openenv-core" },
335
  { name = "pydantic" },
336
  { name = "pyyaml" },
337
  { name = "uvicorn", extra = ["standard"] },
 
373
  { name = "matplotlib", marker = "extra == 'training'", specifier = ">=3.8" },
374
  { name = "mypy", marker = "extra == 'dev'", specifier = ">=1.10" },
375
  { name = "openai", marker = "extra == 'data'", specifier = ">=1.40" },
376
+ { name = "openenv-core", specifier = ">=0.2.3" },
377
  { name = "pandas", marker = "extra == 'training'", specifier = ">=2.2" },
378
  { name = "pydantic", specifier = ">=2.7,<3.0" },
379
  { name = "pytest", marker = "extra == 'dev'", specifier = ">=8" },
 
496
  { name = "tomli", marker = "python_full_version <= '3.11'" },
497
  ]
498
 
499
+ [[package]]
500
+ name = "cryptography"
501
+ version = "47.0.0"
502
+ source = { registry = "https://pypi.org/simple" }
503
+ dependencies = [
504
+ { name = "cffi", marker = "platform_python_implementation != 'PyPy'" },
505
+ ]
506
+ sdist = { url = "https://files.pythonhosted.org/packages/ef/b2/7ffa7fe8207a8c42147ffe70c3e360b228160c1d85dc3faff16aaa3244c0/cryptography-47.0.0.tar.gz", hash = "sha256:9f8e55fe4e63613a5e1cc5819030f27b97742d720203a087802ce4ce9ceb52bb", size = 830863, upload-time = "2026-04-24T19:54:57.056Z" }
507
+ wheels = [
508
+ { url = "https://files.pythonhosted.org/packages/a4/98/40dfe932134bdcae4f6ab5927c87488754bf9eb79297d7e0070b78dd58e9/cryptography-47.0.0-cp311-abi3-macosx_10_9_universal2.whl", hash = "sha256:160ad728f128972d362e714054f6ba0067cab7fb350c5202a9ae8ae4ce3ef1a0", size = 7912214, upload-time = "2026-04-24T19:53:03.864Z" },
509
+ { url = "https://files.pythonhosted.org/packages/34/c6/2733531243fba725f58611b918056b277692f1033373dcc8bd01af1c05d4/cryptography-47.0.0-cp311-abi3-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:b9a8943e359b7615db1a3ba587994618e094ff3d6fa5a390c73d079ce18b3973", size = 4644617, upload-time = "2026-04-24T19:53:06.909Z" },
510
+ { url = "https://files.pythonhosted.org/packages/00/e3/b27be1a670a9b87f855d211cf0e1174a5d721216b7616bd52d8581d912ed/cryptography-47.0.0-cp311-abi3-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:f5c15764f261394b22aef6b00252f5195f46f2ca300bec57149474e2538b31f8", size = 4668186, upload-time = "2026-04-24T19:53:09.053Z" },
511
+ { url = "https://files.pythonhosted.org/packages/81/b9/8443cfe5d17d482d348cee7048acf502bb89a51b6382f06240fd290d4ca3/cryptography-47.0.0-cp311-abi3-manylinux_2_28_aarch64.whl", hash = "sha256:9c59ab0e0fa3a180a5a9c59f3a5abe3ef90d474bc56d7fadfbe80359491b615b", size = 4651244, upload-time = "2026-04-24T19:53:11.217Z" },
512
+ { url = "https://files.pythonhosted.org/packages/5d/5e/13ed0cdd0eb88ba159d6dd5ebfece8cb901dbcf1ae5ac4072e28b55d3153/cryptography-47.0.0-cp311-abi3-manylinux_2_28_ppc64le.whl", hash = "sha256:34b4358b925a5ea3e14384ca781a2c0ef7ac219b57bb9eacc4457078e2b19f92", size = 5252906, upload-time = "2026-04-24T19:53:13.532Z" },
513
+ { url = "https://files.pythonhosted.org/packages/64/16/ed058e1df0f33d440217cd120d41d5dda9dd215a80b8187f68483185af82/cryptography-47.0.0-cp311-abi3-manylinux_2_28_x86_64.whl", hash = "sha256:0024b87d47ae2399165a6bfb20d24888881eeab83ae2566d62467c5ff0030ce7", size = 4701842, upload-time = "2026-04-24T19:53:15.618Z" },
514
+ { url = "https://files.pythonhosted.org/packages/02/e0/3d30986b30fdbd9e969abbdf8ba00ed0618615144341faeb57f395a084fe/cryptography-47.0.0-cp311-abi3-manylinux_2_31_armv7l.whl", hash = "sha256:1e47422b5557bb82d3fff997e8d92cff4e28b9789576984f08c248d2b3535d93", size = 4289313, upload-time = "2026-04-24T19:53:17.755Z" },
515
+ { url = "https://files.pythonhosted.org/packages/df/fd/32db38e3ad0cb331f0691cb4c7a8a6f176f679124dee746b3af6633db4d9/cryptography-47.0.0-cp311-abi3-manylinux_2_34_aarch64.whl", hash = "sha256:6f29f36582e6151d9686235e586dd35bb67491f024767d10b842e520dc6a07ac", size = 4650964, upload-time = "2026-04-24T19:53:20.062Z" },
516
+ { url = "https://files.pythonhosted.org/packages/86/53/5395d944dfd48cb1f67917f533c609c34347185ef15eb4308024c876f274/cryptography-47.0.0-cp311-abi3-manylinux_2_34_ppc64le.whl", hash = "sha256:a9b761f012a943b7de0e828843c5688d0de94a0578d44d6c85a1bae32f87791f", size = 5207817, upload-time = "2026-04-24T19:53:22.498Z" },
517
+ { url = "https://files.pythonhosted.org/packages/34/4f/e5711b28e1901f7d480a2b1b688b645aa4c77c73f10731ed17e7f7db3f0d/cryptography-47.0.0-cp311-abi3-manylinux_2_34_x86_64.whl", hash = "sha256:4e1de79e047e25d6e9f8cea71c86b4a53aced64134f0f003bbcbf3655fd172c8", size = 4701544, upload-time = "2026-04-24T19:53:24.356Z" },
518
+ { url = "https://files.pythonhosted.org/packages/22/22/c8ddc25de3010fc8da447648f5a092c40e7a8fadf01dd6d255d9c0b9373d/cryptography-47.0.0-cp311-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:ef6b3634087f18d2155b1e8ce264e5345a753da2c5fa9815e7d41315c90f8318", size = 4783536, upload-time = "2026-04-24T19:53:26.665Z" },
519
+ { url = "https://files.pythonhosted.org/packages/66/b6/d4a68f4ea999c6d89e8498579cba1c5fcba4276284de7773b17e4fa69293/cryptography-47.0.0-cp311-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:11dbb9f50a0f1bb9757b3d8c27c1101780efb8f0bdecfb12439c22a74d64c001", size = 4926106, upload-time = "2026-04-24T19:53:28.686Z" },
520
+ { url = "https://files.pythonhosted.org/packages/54/ed/5f524db1fade9c013aa618e1c99c6ed05e8ffc9ceee6cda22fed22dda3f4/cryptography-47.0.0-cp311-abi3-win32.whl", hash = "sha256:7fda2f02c9015db3f42bb8a22324a454516ed10a8c29ca6ece6cdbb5efe2a203", size = 3258581, upload-time = "2026-04-24T19:53:31.058Z" },
521
+ { url = "https://files.pythonhosted.org/packages/b2/dc/1b901990b174786569029f67542b3edf72ac068b6c3c8683c17e6a2f5363/cryptography-47.0.0-cp311-abi3-win_amd64.whl", hash = "sha256:f5c3296dab66202f1b18a91fa266be93d6aa0c2806ea3d67762c69f60adc71aa", size = 3775309, upload-time = "2026-04-24T19:53:33.054Z" },
522
+ { url = "https://files.pythonhosted.org/packages/e0/34/a4fae8ae7c3bc227460c9ae43f56abf1b911da0ec29e0ebac53bb0a4b6b7/cryptography-47.0.0-cp38-abi3-macosx_10_9_universal2.whl", hash = "sha256:14432c8a9bcb37009784f9594a62fae211a2ae9543e96c92b2a8e4c3cd5cd0c4", size = 7904072, upload-time = "2026-04-24T19:54:06.411Z" },
523
+ { url = "https://files.pythonhosted.org/packages/01/64/d7b1e54fdb69f22d24a64bb3e88dc718b31c7fb10ef0b9691a3cf7eeea6e/cryptography-47.0.0-cp38-abi3-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:07efe86201817e7d3c18781ca9770bc0db04e1e48c994be384e4602bc38f8f27", size = 4635767, upload-time = "2026-04-24T19:54:08.519Z" },
524
+ { url = "https://files.pythonhosted.org/packages/8b/7b/cca826391fb2a94efdcdfe4631eb69306ee1cff0b22f664a412c90713877/cryptography-47.0.0-cp38-abi3-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:2b45761c6ec22b7c726d6a829558777e32d0f1c8be7c3f3480f9c912d5ee8a10", size = 4654350, upload-time = "2026-04-24T19:54:10.795Z" },
525
+ { url = "https://files.pythonhosted.org/packages/4c/65/4b57bcc823f42a991627c51c2f68c9fd6eb1393c1756aac876cba2accae2/cryptography-47.0.0-cp38-abi3-manylinux_2_28_aarch64.whl", hash = "sha256:edd4da498015da5b9f26d38d3bfc2e90257bfa9cbed1f6767c282a0025ae649b", size = 4643394, upload-time = "2026-04-24T19:54:13.275Z" },
526
+ { url = "https://files.pythonhosted.org/packages/f4/c4/2c5fbeea70adbbca2bbae865e1d605d6a4a7f8dbd9d33eaf69645087f06c/cryptography-47.0.0-cp38-abi3-manylinux_2_28_ppc64le.whl", hash = "sha256:9af828c0d5a65c70ec729cd7495a4bf1a67ecb66417b8f02ff125ab8a6326a74", size = 5225777, upload-time = "2026-04-24T19:54:15.18Z" },
527
+ { url = "https://files.pythonhosted.org/packages/7e/b8/ac57107ef32749d2b244e36069bb688792a363aaaa3acc9e3cf84c130315/cryptography-47.0.0-cp38-abi3-manylinux_2_28_x86_64.whl", hash = "sha256:256d07c78a04d6b276f5df935a9923275f53bd1522f214447fdf365494e2d515", size = 4688771, upload-time = "2026-04-24T19:54:17.835Z" },
528
+ { url = "https://files.pythonhosted.org/packages/56/fc/9f1de22ff8be99d991f240a46863c52d475404c408886c5a38d2b5c3bb26/cryptography-47.0.0-cp38-abi3-manylinux_2_31_armv7l.whl", hash = "sha256:5d0e362ff51041b0c0d219cc7d6924d7b8996f57ce5712bdcef71eb3c65a59cc", size = 4270753, upload-time = "2026-04-24T19:54:19.963Z" },
529
+ { url = "https://files.pythonhosted.org/packages/00/68/d70c852797aa68e8e48d12e5a87170c43f67bb4a59403627259dd57d15de/cryptography-47.0.0-cp38-abi3-manylinux_2_34_aarch64.whl", hash = "sha256:1581aef4219f7ca2849d0250edaa3866212fb74bf5667284f46aa92f9e65c1ca", size = 4642911, upload-time = "2026-04-24T19:54:21.818Z" },
530
+ { url = "https://files.pythonhosted.org/packages/a5/51/661cbee74f594c5d97ff82d34f10d5551c085ca4668645f4606ebd22bd5d/cryptography-47.0.0-cp38-abi3-manylinux_2_34_ppc64le.whl", hash = "sha256:a49a3eb5341b9503fa3000a9a0db033161db90d47285291f53c2a9d2cd1b7f76", size = 5181411, upload-time = "2026-04-24T19:54:24.376Z" },
531
+ { url = "https://files.pythonhosted.org/packages/94/87/f2b6c374a82cf076cfa1416992ac8e8ec94d79facc37aec87c1a5cb72352/cryptography-47.0.0-cp38-abi3-manylinux_2_34_x86_64.whl", hash = "sha256:2207a498b03275d0051589e326b79d4cf59985c99031b05bb292ac52631c37fe", size = 4688262, upload-time = "2026-04-24T19:54:26.946Z" },
532
+ { url = "https://files.pythonhosted.org/packages/14/e2/8b7462f4acf21ec509616f0245018bb197194ab0b65c2ea21a0bdd53c0eb/cryptography-47.0.0-cp38-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:7a02675e2fabd0c0fc04c868b8781863cbf1967691543c22f5470500ff840b31", size = 4775506, upload-time = "2026-04-24T19:54:28.926Z" },
533
+ { url = "https://files.pythonhosted.org/packages/70/75/158e494e4c08dc05e039da5bb48553826bd26c23930cf8d3cd5f21fa8921/cryptography-47.0.0-cp38-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:80887c5cbd1774683cb126f0ab4184567f080071d5acf62205acb354b4b753b7", size = 4912060, upload-time = "2026-04-24T19:54:30.869Z" },
534
+ { url = "https://files.pythonhosted.org/packages/06/bd/0a9d3edbf5eadbac926d7b9b3cd0c4be584eeeae4a003d24d9eda4affbbd/cryptography-47.0.0-cp38-abi3-win32.whl", hash = "sha256:ed67ea4e0cfb5faa5bc7ecb6e2b8838f3807a03758eec239d6c21c8769355310", size = 3248487, upload-time = "2026-04-24T19:54:33.494Z" },
535
+ { url = "https://files.pythonhosted.org/packages/60/80/5681af756d0da3a599b7bdb586fac5a1540f1bcefd2717a20e611ddade45/cryptography-47.0.0-cp38-abi3-win_amd64.whl", hash = "sha256:835d2d7f47cdc53b3224e90810fb1d36ca94ea29cc1801fb4c1bc43876735769", size = 3755737, upload-time = "2026-04-24T19:54:35.408Z" },
536
+ { url = "https://files.pythonhosted.org/packages/1b/a0/928c9ce0d120a40a81aa99e3ba383e87337b9ac9ef9f6db02e4d7822424d/cryptography-47.0.0-pp311-pypy311_pp73-macosx_11_0_arm64.whl", hash = "sha256:7f1207974a904e005f762869996cf620e9bf79ecb4622f148550bb48e0eb35a7", size = 3909893, upload-time = "2026-04-24T19:54:38.334Z" },
537
+ { url = "https://files.pythonhosted.org/packages/81/75/d691e284750df5d9569f2b1ce4a00a71e1d79566da83b2b3e5549c84917f/cryptography-47.0.0-pp311-pypy311_pp73-manylinux_2_28_aarch64.whl", hash = "sha256:1a405c08857258c11016777e11c02bacbe7ef596faf259305d282272a3a05cbe", size = 4587867, upload-time = "2026-04-24T19:54:40.619Z" },
538
+ { url = "https://files.pythonhosted.org/packages/07/d6/1b90f1a4e453009730b4545286f0b39bb348d805c11181fc31544e4f9a65/cryptography-47.0.0-pp311-pypy311_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:20fdbe3e38fb67c385d233c89371fa27f9909f6ebca1cecc20c13518dae65475", size = 4627192, upload-time = "2026-04-24T19:54:42.849Z" },
539
+ { url = "https://files.pythonhosted.org/packages/dc/53/cb358a80e9e359529f496870dd08c102aa8a4b5b9f9064f00f0d6ed5b527/cryptography-47.0.0-pp311-pypy311_pp73-manylinux_2_34_aarch64.whl", hash = "sha256:f7db373287273d8af1414cf95dc4118b13ffdc62be521997b0f2b270771fef50", size = 4587486, upload-time = "2026-04-24T19:54:44.908Z" },
540
+ { url = "https://files.pythonhosted.org/packages/8b/57/aaa3d53876467a226f9a7a82fd14dd48058ad2de1948493442dfa16e2ffd/cryptography-47.0.0-pp311-pypy311_pp73-manylinux_2_34_x86_64.whl", hash = "sha256:9fe6b7c64926c765f9dff301f9c1b867febcda5768868ca084e18589113732ab", size = 4626327, upload-time = "2026-04-24T19:54:47.813Z" },
541
+ { url = "https://files.pythonhosted.org/packages/ab/9c/51f28c3550276bcf35660703ba0ab829a90b88be8cd98a71ef23c2413913/cryptography-47.0.0-pp311-pypy311_pp73-win_amd64.whl", hash = "sha256:cffbba3392df0fa8629bb7f43454ee2925059ee158e23c54620b9063912b86c8", size = 3698916, upload-time = "2026-04-24T19:54:49.782Z" },
542
+ ]
543
+
544
  [[package]]
545
  name = "cuda-bindings"
546
  version = "13.2.0"
 
615
  { url = "https://files.pythonhosted.org/packages/e7/05/c19819d5e3d95294a6f5947fb9b9629efb316b96de511b418c53d245aae6/cycler-0.12.1-py3-none-any.whl", hash = "sha256:85cef7cff222d8644161529808465972e51340599459b8ac3ccbac5a854e0d30", size = 8321, upload-time = "2023-10-07T05:32:16.783Z" },
616
  ]
617
 
618
+ [[package]]
619
+ name = "cyclopts"
620
+ version = "4.11.0"
621
+ source = { registry = "https://pypi.org/simple" }
622
+ dependencies = [
623
+ { name = "attrs" },
624
+ { name = "docstring-parser" },
625
+ { name = "rich" },
626
+ { name = "rich-rst" },
627
+ ]
628
+ sdist = { url = "https://files.pythonhosted.org/packages/f9/fa/eff8f1abae783bade9b5e9bafafd0040d4dbf51988f9384bfdc0326ba1fc/cyclopts-4.11.0.tar.gz", hash = "sha256:1ffcb9990dbd56b90da19980d31596de9e99019980a215a5d76cf88fe452e94d", size = 170690, upload-time = "2026-04-23T00:23:36.858Z" }
629
+ wheels = [
630
+ { url = "https://files.pythonhosted.org/packages/7c/37/197db187c260d24d4be1f09d427f59f3fb9a89bcf1354e23865c7bff7607/cyclopts-4.11.0-py3-none-any.whl", hash = "sha256:34318e3823b44b5baa754a5e37ec70a5c17dc81c65e4295ed70e17bc1aeae50d", size = 208494, upload-time = "2026-04-23T00:23:34.948Z" },
631
+ ]
632
+
633
  [[package]]
634
  name = "datasets"
635
  version = "4.8.4"
 
673
  { url = "https://files.pythonhosted.org/packages/12/b3/231ffd4ab1fc9d679809f356cebee130ac7daa00d6d6f3206dd4fd137e9e/distro-1.9.0-py3-none-any.whl", hash = "sha256:7bffd925d65168f85027d8da9af6bddab658135b840670a223589bc0c8ef02b2", size = 20277, upload-time = "2023-12-24T09:54:30.421Z" },
674
  ]
675
 
676
+ [[package]]
677
+ name = "dnspython"
678
+ version = "2.8.0"
679
+ source = { registry = "https://pypi.org/simple" }
680
+ sdist = { url = "https://files.pythonhosted.org/packages/8c/8b/57666417c0f90f08bcafa776861060426765fdb422eb10212086fb811d26/dnspython-2.8.0.tar.gz", hash = "sha256:181d3c6996452cb1189c4046c61599b84a5a86e099562ffde77d26984ff26d0f", size = 368251, upload-time = "2025-09-07T18:58:00.022Z" }
681
+ wheels = [
682
+ { url = "https://files.pythonhosted.org/packages/ba/5a/18ad964b0086c6e62e2e7500f7edc89e3faa45033c71c1893d34eed2b2de/dnspython-2.8.0-py3-none-any.whl", hash = "sha256:01d9bbc4a2d76bf0db7c1f729812ded6d912bd318d3b1cf81d30c0f845dbf3af", size = 331094, upload-time = "2025-09-07T18:57:58.071Z" },
683
+ ]
684
+
685
+ [[package]]
686
+ name = "docstring-parser"
687
+ version = "0.18.0"
688
+ source = { registry = "https://pypi.org/simple" }
689
+ sdist = { url = "https://files.pythonhosted.org/packages/e0/4d/f332313098c1de1b2d2ff91cf2674415cc7cddab2ca1b01ae29774bd5fdf/docstring_parser-0.18.0.tar.gz", hash = "sha256:292510982205c12b1248696f44959db3cdd1740237a968ea1e2e7a900eeb2015", size = 29341, upload-time = "2026-04-14T04:09:19.867Z" }
690
+ wheels = [
691
+ { url = "https://files.pythonhosted.org/packages/a7/5f/ed01f9a3cdffbd5a008556fc7b2a08ddb1cc6ace7effa7340604b1d16699/docstring_parser-0.18.0-py3-none-any.whl", hash = "sha256:b3fcbed555c47d8479be0796ef7e19c2670d428d72e96da63f3a40122860374b", size = 22484, upload-time = "2026-04-14T04:09:18.638Z" },
692
+ ]
693
+
694
+ [[package]]
695
+ name = "docutils"
696
+ version = "0.22.4"
697
+ source = { registry = "https://pypi.org/simple" }
698
+ sdist = { url = "https://files.pythonhosted.org/packages/ae/b6/03bb70946330e88ffec97aefd3ea75ba575cb2e762061e0e62a213befee8/docutils-0.22.4.tar.gz", hash = "sha256:4db53b1fde9abecbb74d91230d32ab626d94f6badfc575d6db9194a49df29968", size = 2291750, upload-time = "2025-12-18T19:00:26.443Z" }
699
+ wheels = [
700
+ { url = "https://files.pythonhosted.org/packages/02/10/5da547df7a391dcde17f59520a231527b8571e6f46fc8efb02ccb370ab12/docutils-0.22.4-py3-none-any.whl", hash = "sha256:d0013f540772d1420576855455d050a2180186c91c15779301ac2ccb3eeb68de", size = 633196, upload-time = "2025-12-18T19:00:18.077Z" },
701
+ ]
702
+
703
+ [[package]]
704
+ name = "email-validator"
705
+ version = "2.3.0"
706
+ source = { registry = "https://pypi.org/simple" }
707
+ dependencies = [
708
+ { name = "dnspython" },
709
+ { name = "idna" },
710
+ ]
711
+ sdist = { url = "https://files.pythonhosted.org/packages/f5/22/900cb125c76b7aaa450ce02fd727f452243f2e91a61af068b40adba60ea9/email_validator-2.3.0.tar.gz", hash = "sha256:9fc05c37f2f6cf439ff414f8fc46d917929974a82244c20eb10231ba60c54426", size = 51238, upload-time = "2025-08-26T13:09:06.831Z" }
712
+ wheels = [
713
+ { url = "https://files.pythonhosted.org/packages/de/15/545e2b6cf2e3be84bc1ed85613edd75b8aea69807a71c26f4ca6a9258e82/email_validator-2.3.0-py3-none-any.whl", hash = "sha256:80f13f623413e6b197ae73bb10bf4eb0908faf509ad8362c5edeb0be7fd450b4", size = 35604, upload-time = "2025-08-26T13:09:05.858Z" },
714
+ ]
715
+
716
+ [[package]]
717
+ name = "exceptiongroup"
718
+ version = "1.3.1"
719
+ source = { registry = "https://pypi.org/simple" }
720
+ dependencies = [
721
+ { name = "typing-extensions" },
722
+ ]
723
+ 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" }
724
+ wheels = [
725
+ { url = "https://files.pythonhosted.org/packages/8a/0e/97c33bf5009bdbac74fd2beace167cab3f978feb69cc36f1ef79360d6c4e/exceptiongroup-1.3.1-py3-none-any.whl", hash = "sha256:a7a39a3bd276781e98394987d3a5701d0c4edffb633bb7a5144577f82c773598", size = 16740, upload-time = "2025-11-21T23:01:53.443Z" },
726
+ ]
727
+
728
  [[package]]
729
  name = "fastapi"
730
  version = "0.136.1"
 
741
  { url = "https://files.pythonhosted.org/packages/5a/ff/2e4eca3ade2c22fe1dea7043b8ee9dabe47753349eb1b56a202de8af6349/fastapi-0.136.1-py3-none-any.whl", hash = "sha256:a6e9d7eeada96c93a4d69cb03836b44fa34e2854accb7244a1ece36cd4781c3f", size = 117683, upload-time = "2026-04-23T16:49:42.437Z" },
742
  ]
743
 
744
+ [[package]]
745
+ name = "fastmcp"
746
+ version = "3.2.4"
747
+ source = { registry = "https://pypi.org/simple" }
748
+ dependencies = [
749
+ { name = "authlib" },
750
+ { name = "cyclopts" },
751
+ { name = "exceptiongroup" },
752
+ { name = "griffelib" },
753
+ { name = "httpx" },
754
+ { name = "jsonref" },
755
+ { name = "jsonschema-path" },
756
+ { name = "mcp" },
757
+ { name = "openapi-pydantic" },
758
+ { name = "opentelemetry-api" },
759
+ { name = "packaging" },
760
+ { name = "platformdirs" },
761
+ { name = "py-key-value-aio", extra = ["filetree", "keyring", "memory"] },
762
+ { name = "pydantic", extra = ["email"] },
763
+ { name = "pyperclip" },
764
+ { name = "python-dotenv" },
765
+ { name = "pyyaml" },
766
+ { name = "rich" },
767
+ { name = "uncalled-for" },
768
+ { name = "uvicorn" },
769
+ { name = "watchfiles" },
770
+ { name = "websockets" },
771
+ ]
772
+ sdist = { url = "https://files.pythonhosted.org/packages/9c/13/29544fbc6dfe45ea38046af0067311e0bad7acc7d1f2ad38bb08f2409fe2/fastmcp-3.2.4.tar.gz", hash = "sha256:083ecb75b44a4169e7fc0f632f94b781bdb0ff877c6b35b9877cbb566fd4d4d1", size = 28746127, upload-time = "2026-04-14T01:42:24.174Z" }
773
+ wheels = [
774
+ { url = "https://files.pythonhosted.org/packages/cf/76/b310d52fa0e30d39bd937eb58ec2c1f1ea1b5f519f0575e9dd9612f01deb/fastmcp-3.2.4-py3-none-any.whl", hash = "sha256:e6c9c429171041455e47ab94bb3f83c4657622a0ec28922f6940053959bd58a9", size = 728599, upload-time = "2026-04-14T01:42:26.85Z" },
775
+ ]
776
+
777
  [[package]]
778
  name = "filelock"
779
  version = "3.29.0"
 
887
  { url = "https://files.pythonhosted.org/packages/f2/c5/a1bc0996af85757903cf2bf444a7824e68e0035ce63fb41d6f76f9def68b/gitpython-3.1.47-py3-none-any.whl", hash = "sha256:489f590edfd6d20571b2c0e72c6a6ac6915ee8b8cd04572330e3842207a78905", size = 209547, upload-time = "2026-04-22T02:44:41.271Z" },
888
  ]
889
 
890
+ [[package]]
891
+ name = "gradio"
892
+ version = "6.13.0"
893
+ source = { registry = "https://pypi.org/simple" }
894
+ dependencies = [
895
+ { name = "anyio" },
896
+ { name = "brotli" },
897
+ { name = "fastapi" },
898
+ { name = "gradio-client" },
899
+ { name = "groovy" },
900
+ { name = "hf-gradio" },
901
+ { name = "httpx" },
902
+ { name = "huggingface-hub" },
903
+ { name = "jinja2" },
904
+ { name = "markupsafe" },
905
+ { name = "numpy" },
906
+ { name = "orjson" },
907
+ { name = "packaging" },
908
+ { name = "pandas" },
909
+ { name = "pillow" },
910
+ { name = "pydantic" },
911
+ { name = "pydub" },
912
+ { name = "python-multipart" },
913
+ { name = "pytz" },
914
+ { name = "pyyaml" },
915
+ { name = "safehttpx" },
916
+ { name = "semantic-version" },
917
+ { name = "starlette" },
918
+ { name = "tomlkit" },
919
+ { name = "typer" },
920
+ { name = "typing-extensions" },
921
+ { name = "uvicorn" },
922
+ ]
923
+ sdist = { url = "https://files.pythonhosted.org/packages/7d/93/022b6cae8b566424683a80c21ca04c364f9b88120f08a9ba2b93c6b7c8e3/gradio-6.13.0.tar.gz", hash = "sha256:23457dde02202d97f636a5c170967a846297e20f40c3152b41aa4c3460245e3b", size = 36016802, upload-time = "2026-04-20T23:16:10.057Z" }
924
+ wheels = [
925
+ { url = "https://files.pythonhosted.org/packages/3f/95/0ad40fb92ba3e6fe36182f722f81d69842a1e93cab1d9c6171256ef55418/gradio-6.13.0-py3-none-any.whl", hash = "sha256:46953f88aad36db9bc369ad2d1d6c4f200274da28f232b54842b2d4942a24f8f", size = 19684382, upload-time = "2026-04-20T23:16:06.298Z" },
926
+ ]
927
+
928
+ [[package]]
929
+ name = "gradio-client"
930
+ version = "2.5.0"
931
+ source = { registry = "https://pypi.org/simple" }
932
+ dependencies = [
933
+ { name = "fsspec" },
934
+ { name = "httpx" },
935
+ { name = "huggingface-hub" },
936
+ { name = "packaging" },
937
+ { name = "typing-extensions" },
938
+ ]
939
+ sdist = { url = "https://files.pythonhosted.org/packages/e8/e6/6b6029f5fe2ad7f1211105d530e34d991014c2cae463f9223033031cfc4f/gradio_client-2.5.0.tar.gz", hash = "sha256:4cde99bad62149595c30c90876ca2e405e3a13687ecf895474f3412cb476673d", size = 59013, upload-time = "2026-04-20T23:16:21.518Z" }
940
+ wheels = [
941
+ { url = "https://files.pythonhosted.org/packages/78/81/0a861b8e1ff42960139c6cd4c7dd591292fa09ea1ae2d87677441cba4c00/gradio_client-2.5.0-py3-none-any.whl", hash = "sha256:d43e2179c29076292a76485ad7ed2e6eaa19d14ac58283bd7f5beabfe4ca958c", size = 59952, upload-time = "2026-04-20T23:16:20.186Z" },
942
+ ]
943
+
944
+ [[package]]
945
+ name = "griffelib"
946
+ version = "2.0.2"
947
+ source = { registry = "https://pypi.org/simple" }
948
+ sdist = { url = "https://files.pythonhosted.org/packages/9d/82/74f4a3310cdabfbb10da554c3a672847f1ed33c6f61dd472681ce7f1fe67/griffelib-2.0.2.tar.gz", hash = "sha256:3cf20b3bc470e83763ffbf236e0076b1211bac1bc67de13daf494640f2de707e", size = 166461, upload-time = "2026-03-27T11:34:51.091Z" }
949
+ wheels = [
950
+ { url = "https://files.pythonhosted.org/packages/11/8c/c9138d881c79aa0ea9ed83cbd58d5ca75624378b38cee225dcf5c42cc91f/griffelib-2.0.2-py3-none-any.whl", hash = "sha256:925c857658fb1ba40c0772c37acbc2ab650bd794d9c1b9726922e36ea4117ea1", size = 142357, upload-time = "2026-03-27T11:34:46.275Z" },
951
+ ]
952
+
953
+ [[package]]
954
+ name = "groovy"
955
+ version = "0.1.2"
956
+ source = { registry = "https://pypi.org/simple" }
957
+ sdist = { url = "https://files.pythonhosted.org/packages/52/36/bbdede67400277bef33d3ec0e6a31750da972c469f75966b4930c753218f/groovy-0.1.2.tar.gz", hash = "sha256:25c1dc09b3f9d7e292458aa762c6beb96ea037071bf5e917fc81fb78d2231083", size = 17325, upload-time = "2025-02-28T20:24:56.068Z" }
958
+ wheels = [
959
+ { url = "https://files.pythonhosted.org/packages/28/27/3d6dcadc8a3214d8522c1e7f6a19554e33659be44546d44a2f7572ac7d2a/groovy-0.1.2-py3-none-any.whl", hash = "sha256:7f7975bab18c729a257a8b1ae9dcd70b7cafb1720481beae47719af57c35fa64", size = 14090, upload-time = "2025-02-28T20:24:55.152Z" },
960
+ ]
961
+
962
  [[package]]
963
  name = "h11"
964
  version = "0.16.0"
 
968
  { url = "https://files.pythonhosted.org/packages/04/4b/29cac41a4d98d144bf5f6d33995617b185d14b22401f75ca86f384e87ff1/h11-0.16.0-py3-none-any.whl", hash = "sha256:63cf8bbe7522de3bf65932fda1d9c2772064ffb3dae62d55932da54b31cb6c86", size = 37515, upload-time = "2025-04-24T03:35:24.344Z" },
969
  ]
970
 
971
+ [[package]]
972
+ name = "hf-gradio"
973
+ version = "0.4.1"
974
+ source = { registry = "https://pypi.org/simple" }
975
+ dependencies = [
976
+ { name = "gradio-client" },
977
+ { name = "typer" },
978
+ ]
979
+ sdist = { url = "https://files.pythonhosted.org/packages/ce/86/c9694b7cfada5780e75769e60dc161a161f4dd7fc91b61db5e3a3338bef9/hf_gradio-0.4.1.tar.gz", hash = "sha256:a017d942618f0d495a58ee4563047fa04bef614c00e0cb789a9a6d0633cffa7b", size = 6560, upload-time = "2026-04-22T14:01:32.334Z" }
980
+ wheels = [
981
+ { url = "https://files.pythonhosted.org/packages/30/2d/afff2ee87e75d8eb85c92bb8cf0e15b05c23c2ebd8fd8dec781d8601ed7f/hf_gradio-0.4.1-py3-none-any.whl", hash = "sha256:76b8cb8be6abe62d74c1ad2d35b42f0629db89aa9e1a8d033cecfe7c856eeab3", size = 4482, upload-time = "2026-04-17T19:53:31.827Z" },
982
+ ]
983
+
984
  [[package]]
985
  name = "hf-xet"
986
  version = "1.4.3"
 
1047
  { url = "https://files.pythonhosted.org/packages/2a/39/e50c7c3a983047577ee07d2a9e53faf5a69493943ec3f6a384bdc792deb2/httpx-0.28.1-py3-none-any.whl", hash = "sha256:d909fcccc110f8c7faf814ca82a9a4d816bc5a6dbfea25d6591d6985b8ba59ad", size = 73517, upload-time = "2024-12-06T15:37:21.509Z" },
1048
  ]
1049
 
1050
+ [[package]]
1051
+ name = "httpx-sse"
1052
+ version = "0.4.3"
1053
+ source = { registry = "https://pypi.org/simple" }
1054
+ sdist = { url = "https://files.pythonhosted.org/packages/0f/4c/751061ffa58615a32c31b2d82e8482be8dd4a89154f003147acee90f2be9/httpx_sse-0.4.3.tar.gz", hash = "sha256:9b1ed0127459a66014aec3c56bebd93da3c1bc8bb6618c8082039a44889a755d", size = 15943, upload-time = "2025-10-10T21:48:22.271Z" }
1055
+ wheels = [
1056
+ { url = "https://files.pythonhosted.org/packages/d2/fd/6668e5aec43ab844de6fc74927e155a3b37bf40d7c3790e49fc0406b6578/httpx_sse-0.4.3-py3-none-any.whl", hash = "sha256:0ac1c9fe3c0afad2e0ebb25a934a59f4c7823b60792691f779fad2c5568830fc", size = 8960, upload-time = "2025-10-10T21:48:21.158Z" },
1057
+ ]
1058
+
1059
  [[package]]
1060
  name = "huggingface-hub"
1061
  version = "1.12.0"
 
1085
  { url = "https://files.pythonhosted.org/packages/5d/13/ad7d7ca3808a898b4612b6fe93cde56b53f3034dcde235acb1f0e1df24c6/idna-3.13-py3-none-any.whl", hash = "sha256:892ea0cde124a99ce773decba204c5552b69c3c67ffd5f232eb7696135bc8bb3", size = 68629, upload-time = "2026-04-22T16:42:40.909Z" },
1086
  ]
1087
 
1088
+ [[package]]
1089
+ name = "importlib-metadata"
1090
+ version = "8.7.1"
1091
+ source = { registry = "https://pypi.org/simple" }
1092
+ dependencies = [
1093
+ { name = "zipp" },
1094
+ ]
1095
+ sdist = { url = "https://files.pythonhosted.org/packages/f3/49/3b30cad09e7771a4982d9975a8cbf64f00d4a1ececb53297f1d9a7be1b10/importlib_metadata-8.7.1.tar.gz", hash = "sha256:49fef1ae6440c182052f407c8d34a68f72efc36db9ca90dc0113398f2fdde8bb", size = 57107, upload-time = "2025-12-21T10:00:19.278Z" }
1096
+ wheels = [
1097
+ { url = "https://files.pythonhosted.org/packages/fa/5e/f8e9a1d23b9c20a551a8a02ea3637b4642e22c2626e3a13a9a29cdea99eb/importlib_metadata-8.7.1-py3-none-any.whl", hash = "sha256:5a1f80bf1daa489495071efbb095d75a634cf28a8bc299581244063b53176151", size = 27865, upload-time = "2025-12-21T10:00:18.329Z" },
1098
+ ]
1099
+
1100
  [[package]]
1101
  name = "iniconfig"
1102
  version = "2.3.0"
 
1106
  { url = "https://files.pythonhosted.org/packages/cb/b1/3846dd7f199d53cb17f49cba7e651e9ce294d8497c8c150530ed11865bb8/iniconfig-2.3.0-py3-none-any.whl", hash = "sha256:f631c04d2c48c52b84d0d0549c99ff3859c98df65b3101406327ecc7d53fbf12", size = 7484, upload-time = "2025-10-18T21:55:41.639Z" },
1107
  ]
1108
 
1109
+ [[package]]
1110
+ name = "jaraco-classes"
1111
+ version = "3.4.0"
1112
+ source = { registry = "https://pypi.org/simple" }
1113
+ dependencies = [
1114
+ { name = "more-itertools" },
1115
+ ]
1116
+ sdist = { url = "https://files.pythonhosted.org/packages/06/c0/ed4a27bc5571b99e3cff68f8a9fa5b56ff7df1c2251cc715a652ddd26402/jaraco.classes-3.4.0.tar.gz", hash = "sha256:47a024b51d0239c0dd8c8540c6c7f484be3b8fcf0b2d85c13825780d3b3f3acd", size = 11780, upload-time = "2024-03-31T07:27:36.643Z" }
1117
+ wheels = [
1118
+ { url = "https://files.pythonhosted.org/packages/7f/66/b15ce62552d84bbfcec9a4873ab79d993a1dd4edb922cbfccae192bd5b5f/jaraco.classes-3.4.0-py3-none-any.whl", hash = "sha256:f662826b6bed8cace05e7ff873ce0f9283b5c924470fe664fff1c2f00f581790", size = 6777, upload-time = "2024-03-31T07:27:34.792Z" },
1119
+ ]
1120
+
1121
+ [[package]]
1122
+ name = "jaraco-context"
1123
+ version = "6.1.2"
1124
+ source = { registry = "https://pypi.org/simple" }
1125
+ dependencies = [
1126
+ { name = "backports-tarfile", marker = "python_full_version < '3.12'" },
1127
+ ]
1128
+ sdist = { url = "https://files.pythonhosted.org/packages/af/50/4763cd07e722bb6285316d390a164bc7e479db9d90daa769f22578f698b4/jaraco_context-6.1.2.tar.gz", hash = "sha256:f1a6c9d391e661cc5b8d39861ff077a7dc24dc23833ccee564b234b81c82dfe3", size = 16801, upload-time = "2026-03-20T22:13:33.922Z" }
1129
+ wheels = [
1130
+ { url = "https://files.pythonhosted.org/packages/f2/58/bc8954bda5fcda97bd7c19be11b85f91973d67a706ed4a3aec33e7de22db/jaraco_context-6.1.2-py3-none-any.whl", hash = "sha256:bf8150b79a2d5d91ae48629d8b427a8f7ba0e1097dd6202a9059f29a36379535", size = 7871, upload-time = "2026-03-20T22:13:32.808Z" },
1131
+ ]
1132
+
1133
+ [[package]]
1134
+ name = "jaraco-functools"
1135
+ version = "4.4.0"
1136
+ source = { registry = "https://pypi.org/simple" }
1137
+ dependencies = [
1138
+ { name = "more-itertools" },
1139
+ ]
1140
+ sdist = { url = "https://files.pythonhosted.org/packages/0f/27/056e0638a86749374d6f57d0b0db39f29509cce9313cf91bdc0ac4d91084/jaraco_functools-4.4.0.tar.gz", hash = "sha256:da21933b0417b89515562656547a77b4931f98176eb173644c0d35032a33d6bb", size = 19943, upload-time = "2025-12-21T09:29:43.6Z" }
1141
+ wheels = [
1142
+ { url = "https://files.pythonhosted.org/packages/fd/c4/813bb09f0985cb21e959f21f2464169eca882656849adf727ac7bb7e1767/jaraco_functools-4.4.0-py3-none-any.whl", hash = "sha256:9eec1e36f45c818d9bf307c8948eb03b2b56cd44087b3cdc989abca1f20b9176", size = 10481, upload-time = "2025-12-21T09:29:42.27Z" },
1143
+ ]
1144
+
1145
+ [[package]]
1146
+ name = "jeepney"
1147
+ version = "0.9.0"
1148
+ source = { registry = "https://pypi.org/simple" }
1149
+ sdist = { url = "https://files.pythonhosted.org/packages/7b/6f/357efd7602486741aa73ffc0617fb310a29b588ed0fd69c2399acbb85b0c/jeepney-0.9.0.tar.gz", hash = "sha256:cf0e9e845622b81e4a28df94c40345400256ec608d0e55bb8a3feaa9163f5732", size = 106758, upload-time = "2025-02-27T18:51:01.684Z" }
1150
+ wheels = [
1151
+ { url = "https://files.pythonhosted.org/packages/b2/a3/e137168c9c44d18eff0376253da9f1e9234d0239e0ee230d2fee6cea8e55/jeepney-0.9.0-py3-none-any.whl", hash = "sha256:97e5714520c16fc0a45695e5365a2e11b81ea79bba796e26f9f1d178cb182683", size = 49010, upload-time = "2025-02-27T18:51:00.104Z" },
1152
+ ]
1153
+
1154
  [[package]]
1155
  name = "jinja2"
1156
  version = "3.1.6"
 
1216
  { url = "https://files.pythonhosted.org/packages/7b/91/984aca2ec129e2757d1e4e3c81c3fcda9d0f85b74670a094cc443d9ee949/joblib-1.5.3-py3-none-any.whl", hash = "sha256:5fc3c5039fc5ca8c0276333a188bbd59d6b7ab37fe6632daa76bc7f9ec18e713", size = 309071, upload-time = "2025-12-15T08:41:44.973Z" },
1217
  ]
1218
 
1219
+ [[package]]
1220
+ name = "joserfc"
1221
+ version = "1.6.4"
1222
+ source = { registry = "https://pypi.org/simple" }
1223
+ dependencies = [
1224
+ { name = "cryptography" },
1225
+ ]
1226
+ sdist = { url = "https://files.pythonhosted.org/packages/de/c6/de8fdbdfa75c8ca04fead38a82d573df8a82906e984c349d58665f459558/joserfc-1.6.4.tar.gz", hash = "sha256:34ce5f499bfcc5e9ad4cc75077f9278ab3227b71da9aaf28f9ab705f8a560d3c", size = 231866, upload-time = "2026-04-13T13:15:40.632Z" }
1227
+ wheels = [
1228
+ { url = "https://files.pythonhosted.org/packages/b6/f7/210b27752e972edb36d239315b08d3eb6b14824cc4a590da2337d195260b/joserfc-1.6.4-py3-none-any.whl", hash = "sha256:3e4a22b509b41908989237a045e25c8308d5fd47ab96bdae2dd8057c6451003a", size = 70464, upload-time = "2026-04-13T13:15:39.259Z" },
1229
+ ]
1230
+
1231
+ [[package]]
1232
+ name = "jsonref"
1233
+ version = "1.1.0"
1234
+ source = { registry = "https://pypi.org/simple" }
1235
+ sdist = { url = "https://files.pythonhosted.org/packages/aa/0d/c1f3277e90ccdb50d33ed5ba1ec5b3f0a242ed8c1b1a85d3afeb68464dca/jsonref-1.1.0.tar.gz", hash = "sha256:32fe8e1d85af0fdefbebce950af85590b22b60f9e95443176adbde4e1ecea552", size = 8814, upload-time = "2023-01-16T16:10:04.455Z" }
1236
+ wheels = [
1237
+ { url = "https://files.pythonhosted.org/packages/0c/ec/e1db9922bceb168197a558a2b8c03a7963f1afe93517ddd3cf99f202f996/jsonref-1.1.0-py3-none-any.whl", hash = "sha256:590dc7773df6c21cbf948b5dac07a72a251db28b0238ceecce0a2abfa8ec30a9", size = 9425, upload-time = "2023-01-16T16:10:02.255Z" },
1238
+ ]
1239
+
1240
  [[package]]
1241
  name = "jsonschema"
1242
  version = "4.26.0"
 
1252
  { url = "https://files.pythonhosted.org/packages/69/90/f63fb5873511e014207a475e2bb4e8b2e570d655b00ac19a9a0ca0a385ee/jsonschema-4.26.0-py3-none-any.whl", hash = "sha256:d489f15263b8d200f8387e64b4c3a75f06629559fb73deb8fdfb525f2dab50ce", size = 90630, upload-time = "2026-01-07T13:41:05.306Z" },
1253
  ]
1254
 
1255
+ [[package]]
1256
+ name = "jsonschema-path"
1257
+ version = "0.4.5"
1258
+ source = { registry = "https://pypi.org/simple" }
1259
+ dependencies = [
1260
+ { name = "pathable" },
1261
+ { name = "pyyaml" },
1262
+ { name = "referencing" },
1263
+ ]
1264
+ sdist = { url = "https://files.pythonhosted.org/packages/5b/8a/7e6102f2b8bdc6705a9eb5294f8f6f9ccd3a8420e8e8e19671d1dd773251/jsonschema_path-0.4.5.tar.gz", hash = "sha256:c6cd7d577ae290c7defd4f4029e86fdb248ca1bd41a07557795b3c95e5144918", size = 15113, upload-time = "2026-03-03T09:56:46.87Z" }
1265
+ wheels = [
1266
+ { url = "https://files.pythonhosted.org/packages/04/d5/4e96c44f6c1ea3d812cf5391d81a4f5abaa540abf8d04ecd7f66e0ed11df/jsonschema_path-0.4.5-py3-none-any.whl", hash = "sha256:7d77a2c3f3ec569a40efe5c5f942c44c1af2a6f96fe0866794c9ef5b8f87fd65", size = 19368, upload-time = "2026-03-03T09:56:45.39Z" },
1267
+ ]
1268
+
1269
  [[package]]
1270
  name = "jsonschema-specifications"
1271
  version = "2025.9.1"
 
1278
  { url = "https://files.pythonhosted.org/packages/41/45/1a4ed80516f02155c51f51e8cedb3c1902296743db0bbc66608a0db2814f/jsonschema_specifications-2025.9.1-py3-none-any.whl", hash = "sha256:98802fee3a11ee76ecaca44429fda8a41bff98b00a0f2838151b113f210cc6fe", size = 18437, upload-time = "2025-09-08T01:34:57.871Z" },
1279
  ]
1280
 
1281
+ [[package]]
1282
+ name = "keyring"
1283
+ version = "25.7.0"
1284
+ source = { registry = "https://pypi.org/simple" }
1285
+ dependencies = [
1286
+ { name = "importlib-metadata", marker = "python_full_version < '3.12'" },
1287
+ { name = "jaraco-classes" },
1288
+ { name = "jaraco-context" },
1289
+ { name = "jaraco-functools" },
1290
+ { name = "jeepney", marker = "sys_platform == 'linux'" },
1291
+ { name = "pywin32-ctypes", marker = "sys_platform == 'win32'" },
1292
+ { name = "secretstorage", marker = "sys_platform == 'linux'" },
1293
+ ]
1294
+ sdist = { url = "https://files.pythonhosted.org/packages/43/4b/674af6ef2f97d56f0ab5153bf0bfa28ccb6c3ed4d1babf4305449668807b/keyring-25.7.0.tar.gz", hash = "sha256:fe01bd85eb3f8fb3dd0405defdeac9a5b4f6f0439edbb3149577f244a2e8245b", size = 63516, upload-time = "2025-11-16T16:26:09.482Z" }
1295
+ wheels = [
1296
+ { url = "https://files.pythonhosted.org/packages/81/db/e655086b7f3a705df045bf0933bdd9c2f79bb3c97bfef1384598bb79a217/keyring-25.7.0-py3-none-any.whl", hash = "sha256:be4a0b195f149690c166e850609a477c532ddbfbaed96a404d4e43f8d5e2689f", size = 39160, upload-time = "2025-11-16T16:26:08.402Z" },
1297
+ ]
1298
+
1299
  [[package]]
1300
  name = "kiwisolver"
1301
  version = "1.5.0"
 
1455
  { url = "https://files.pythonhosted.org/packages/6f/87/afead29192170917537934c6aff4b008c805fff7b1ccea0c79120d96beda/matplotlib-3.10.9-pp311-pypy311_pp73-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:3fc0364dfbe1d07f6d15c5ebd0c5bf89e126916e5a8667dd4a7a6e84c36653d4", size = 8774002, upload-time = "2026-04-24T00:14:09.816Z" },
1456
  ]
1457
 
1458
+ [[package]]
1459
+ name = "mcp"
1460
+ version = "1.27.0"
1461
+ source = { registry = "https://pypi.org/simple" }
1462
+ dependencies = [
1463
+ { name = "anyio" },
1464
+ { name = "httpx" },
1465
+ { name = "httpx-sse" },
1466
+ { name = "jsonschema" },
1467
+ { name = "pydantic" },
1468
+ { name = "pydantic-settings" },
1469
+ { name = "pyjwt", extra = ["crypto"] },
1470
+ { name = "python-multipart" },
1471
+ { name = "pywin32", marker = "sys_platform == 'win32'" },
1472
+ { name = "sse-starlette" },
1473
+ { name = "starlette" },
1474
+ { name = "typing-extensions" },
1475
+ { name = "typing-inspection" },
1476
+ { name = "uvicorn", marker = "sys_platform != 'emscripten'" },
1477
+ ]
1478
+ sdist = { url = "https://files.pythonhosted.org/packages/8b/eb/c0cfc62075dc6e1ec1c64d352ae09ac051d9334311ed226f1f425312848a/mcp-1.27.0.tar.gz", hash = "sha256:d3dc35a7eec0d458c1da4976a48f982097ddaab87e278c5511d5a4a56e852b83", size = 607509, upload-time = "2026-04-02T14:48:08.88Z" }
1479
+ wheels = [
1480
+ { url = "https://files.pythonhosted.org/packages/9c/46/f6b4ad632c67ef35209a66127e4bddc95759649dd595f71f13fba11bdf9a/mcp-1.27.0-py3-none-any.whl", hash = "sha256:5ce1fa81614958e267b21fb2aa34e0aea8e2c6ede60d52aba45fd47246b4d741", size = 215967, upload-time = "2026-04-02T14:48:07.24Z" },
1481
+ ]
1482
+
1483
  [[package]]
1484
  name = "mdurl"
1485
  version = "0.1.2"
 
1489
  { url = "https://files.pythonhosted.org/packages/b3/38/89ba8ad64ae25be8de66a6d463314cf1eb366222074cfda9ee839c56a4b4/mdurl-0.1.2-py3-none-any.whl", hash = "sha256:84008a41e51615a49fc9966191ff91509e3c40b939176e643fd50a5c2196b8f8", size = 9979, upload-time = "2022-08-14T12:40:09.779Z" },
1490
  ]
1491
 
1492
+ [[package]]
1493
+ name = "more-itertools"
1494
+ version = "11.0.2"
1495
+ source = { registry = "https://pypi.org/simple" }
1496
+ sdist = { url = "https://files.pythonhosted.org/packages/a2/f7/139d22fef48ac78127d18e01d80cf1be40236ae489769d17f35c3d425293/more_itertools-11.0.2.tar.gz", hash = "sha256:392a9e1e362cbc106a2457d37cabf9b36e5e12efd4ebff1654630e76597df804", size = 144659, upload-time = "2026-04-09T15:01:33.297Z" }
1497
+ wheels = [
1498
+ { url = "https://files.pythonhosted.org/packages/cb/98/6af411189d9413534c3eb691182bff1f5c6d44ed2f93f2edfe52a1bbceb8/more_itertools-11.0.2-py3-none-any.whl", hash = "sha256:6e35b35f818b01f691643c6c611bc0902f2e92b46c18fffa77ae1e7c46e912e4", size = 71939, upload-time = "2026-04-09T15:01:32.21Z" },
1499
+ ]
1500
+
1501
  [[package]]
1502
  name = "mpmath"
1503
  version = "1.3.0"
 
1823
  ]
1824
 
1825
  [[package]]
1826
+ name = "openapi-pydantic"
1827
+ version = "0.5.1"
1828
  source = { registry = "https://pypi.org/simple" }
1829
  dependencies = [
1830
+ { name = "pydantic" },
1831
+ ]
1832
+ sdist = { url = "https://files.pythonhosted.org/packages/02/2e/58d83848dd1a79cb92ed8e63f6ba901ca282c5f09d04af9423ec26c56fd7/openapi_pydantic-0.5.1.tar.gz", hash = "sha256:ff6835af6bde7a459fb93eb93bb92b8749b754fc6e51b2f1590a19dc3005ee0d", size = 60892, upload-time = "2025-01-08T19:29:27.083Z" }
1833
+ wheels = [
1834
+ { url = "https://files.pythonhosted.org/packages/12/cf/03675d8bd8ecbf4445504d8071adab19f5f993676795708e36402ab38263/openapi_pydantic-0.5.1-py3-none-any.whl", hash = "sha256:a3a09ef4586f5bd760a8df7f43028b60cafb6d9f61de2acba9574766255ab146", size = 96381, upload-time = "2025-01-08T19:29:25.275Z" },
1835
+ ]
1836
+
1837
+ [[package]]
1838
+ name = "openenv-core"
1839
+ version = "0.2.3"
1840
+ source = { registry = "https://pypi.org/simple" }
1841
+ dependencies = [
1842
+ { name = "fastapi" },
1843
+ { name = "fastmcp" },
1844
+ { name = "gradio" },
1845
+ { name = "httpx" },
1846
+ { name = "huggingface-hub" },
1847
+ { name = "openai" },
1848
+ { name = "pydantic" },
1849
+ { name = "pyyaml" },
1850
+ { name = "requests" },
1851
+ { name = "rich" },
1852
+ { name = "tomli" },
1853
+ { name = "tomli-w" },
1854
+ { name = "typer" },
1855
+ { name = "uvicorn" },
1856
+ { name = "websockets" },
1857
  ]
1858
+ sdist = { url = "https://files.pythonhosted.org/packages/93/f3/41a5ed932a2507438c985e9d959dcaa1a6c46f293995c064348c0e52dd40/openenv_core-0.2.3.tar.gz", hash = "sha256:48aefd774474556297ce012b80f2ceb271db51253d7fd0838e6e2dcc329db0c3", size = 146944, upload-time = "2026-03-28T18:56:28.415Z" }
1859
  wheels = [
1860
+ { url = "https://files.pythonhosted.org/packages/2f/22/38c339e370d198008f2c17ebdda1ae8f23bb4e1509dc7ae8eab6dc9b9cbe/openenv_core-0.2.3-py3-none-any.whl", hash = "sha256:f75a20c94452057a5f53a86e6d71a9f6a461524c3d6a865aa9344d257a92b795", size = 174557, upload-time = "2026-03-28T18:56:26.874Z" },
1861
+ ]
1862
+
1863
+ [[package]]
1864
+ name = "opentelemetry-api"
1865
+ version = "1.41.1"
1866
+ source = { registry = "https://pypi.org/simple" }
1867
+ dependencies = [
1868
+ { name = "importlib-metadata" },
1869
+ { name = "typing-extensions" },
1870
+ ]
1871
+ sdist = { url = "https://files.pythonhosted.org/packages/fa/fc/b7564cbef36601aef0d6c9bc01f7badb64be8e862c2e1c3c5c3b43b53e4f/opentelemetry_api-1.41.1.tar.gz", hash = "sha256:0ad1814d73b875f84494387dae86ce0b12c68556331ce6ce8fe789197c949621", size = 71416, upload-time = "2026-04-24T13:15:38.262Z" }
1872
+ wheels = [
1873
+ { url = "https://files.pythonhosted.org/packages/29/59/3e7118ed140f76b0982ba4321bdaed1997a0473f9720de2d10788a577033/opentelemetry_api-1.41.1-py3-none-any.whl", hash = "sha256:a22df900e75c76dc08440710e51f52f1aa6b451b429298896023e60db5b3139f", size = 69007, upload-time = "2026-04-24T13:15:15.662Z" },
1874
+ ]
1875
+
1876
+ [[package]]
1877
+ name = "orjson"
1878
+ version = "3.11.8"
1879
+ source = { registry = "https://pypi.org/simple" }
1880
+ sdist = { url = "https://files.pythonhosted.org/packages/9d/1b/2024d06792d0779f9dbc51531b61c24f76c75b9f4ce05e6f3377a1814cea/orjson-3.11.8.tar.gz", hash = "sha256:96163d9cdc5a202703e9ad1b9ae757d5f0ca62f4fa0cc93d1f27b0e180cc404e", size = 5603832, upload-time = "2026-03-31T16:16:27.878Z" }
1881
+ wheels = [
1882
+ { url = "https://files.pythonhosted.org/packages/67/41/5aa7fa3b0f4dc6b47dcafc3cea909299c37e40e9972feabc8b6a74e2730d/orjson-3.11.8-cp311-cp311-macosx_10_15_x86_64.macosx_11_0_arm64.macosx_10_15_universal2.whl", hash = "sha256:003646067cc48b7fcab2ae0c562491c9b5d2cbd43f1e5f16d98fd118c5522d34", size = 229229, upload-time = "2026-03-31T16:14:50.424Z" },
1883
+ { url = "https://files.pythonhosted.org/packages/0a/d7/57e7f2458e0a2c41694f39fc830030a13053a84f837a5b73423dca1f0938/orjson-3.11.8-cp311-cp311-macosx_15_0_arm64.whl", hash = "sha256:ed193ce51d77a3830cad399a529cd4ef029968761f43ddc549e1bc62b40d88f8", size = 128871, upload-time = "2026-03-31T16:14:51.888Z" },
1884
+ { url = "https://files.pythonhosted.org/packages/53/4a/e0fdb9430983e6c46e0299559275025075568aad5d21dd606faee3703924/orjson-3.11.8-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f30491bc4f862aa15744b9738517454f1e46e56c972a2be87d70d727d5b2a8f8", size = 132104, upload-time = "2026-03-31T16:14:53.142Z" },
1885
+ { url = "https://files.pythonhosted.org/packages/08/4a/2025a60ff3f5c8522060cda46612d9b1efa653de66ed2908591d8d82f22d/orjson-3.11.8-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:6eda5b8b6be91d3f26efb7dc6e5e68ee805bc5617f65a328587b35255f138bf4", size = 130483, upload-time = "2026-03-31T16:14:54.605Z" },
1886
+ { url = "https://files.pythonhosted.org/packages/2d/3c/b9cde05bdc7b2385c66014e0620627da638d3d04e4954416ab48c31196c5/orjson-3.11.8-cp311-cp311-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ee8db7bfb6fe03581bbab54d7c4124a6dd6a7f4273a38f7267197890f094675f", size = 135481, upload-time = "2026-03-31T16:14:55.901Z" },
1887
+ { url = "https://files.pythonhosted.org/packages/ff/f2/a8238e7734de7cb589fed319857a8025d509c89dc52fdcc88f39c6d03d5a/orjson-3.11.8-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:5d8b5231de76c528a46b57010bbd83fb51e056aa0220a372fd5065e978406f1c", size = 146819, upload-time = "2026-03-31T16:14:57.548Z" },
1888
+ { url = "https://files.pythonhosted.org/packages/db/10/dbf1e2a3cafea673b1b4350e371877b759060d6018a998643b7040e5de48/orjson-3.11.8-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:58a4a208a6fbfdb7a7327b8f201c6014f189f721fd55d047cafc4157af1bc62a", size = 132846, upload-time = "2026-03-31T16:14:58.91Z" },
1889
+ { url = "https://files.pythonhosted.org/packages/f8/fc/55e667ec9c85694038fcff00573d221b085d50777368ee3d77f38668bf3c/orjson-3.11.8-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5f8952d6d2505c003e8f0224ff7858d341fa4e33fef82b91c4ff0ef070f2393c", size = 133580, upload-time = "2026-03-31T16:15:00.519Z" },
1890
+ { url = "https://files.pythonhosted.org/packages/7e/a6/c08c589a9aad0cb46c4831d17de212a2b6901f9d976814321ff8e69e8785/orjson-3.11.8-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:0022bb50f90da04b009ce32c512dc1885910daa7cb10b7b0cba4505b16db82a8", size = 142042, upload-time = "2026-03-31T16:15:01.906Z" },
1891
+ { url = "https://files.pythonhosted.org/packages/5c/cc/2f78ea241d52b717d2efc38878615fe80425bf2beb6e68c984dde257a766/orjson-3.11.8-cp311-cp311-musllinux_1_2_armv7l.whl", hash = "sha256:ff51f9d657d1afb6f410cb435792ce4e1fe427aab23d2fcd727a2876e21d4cb6", size = 423845, upload-time = "2026-03-31T16:15:03.703Z" },
1892
+ { url = "https://files.pythonhosted.org/packages/70/07/c17dcf05dd8045457538428a983bf1f1127928df5bf328cb24d2b7cddacb/orjson-3.11.8-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:6dbe9a97bdb4d8d9d5367b52a7c32549bba70b2739c58ef74a6964a6d05ae054", size = 147729, upload-time = "2026-03-31T16:15:05.203Z" },
1893
+ { url = "https://files.pythonhosted.org/packages/90/6c/0fb6e8a24e682e0958d71711ae6f39110e4b9cd8cab1357e2a89cb8e1951/orjson-3.11.8-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:a5c370674ebabe16c6ccac33ff80c62bf8a6e59439f5e9d40c1f5ab8fd2215b7", size = 136425, upload-time = "2026-03-31T16:15:07.052Z" },
1894
+ { url = "https://files.pythonhosted.org/packages/b2/35/4d3cc3a3d616035beb51b24a09bb872942dc452cf2df0c1d11ab35046d9f/orjson-3.11.8-cp311-cp311-win32.whl", hash = "sha256:0e32f7154299f42ae66f13488963269e5eccb8d588a65bc839ed986919fc9fac", size = 131870, upload-time = "2026-03-31T16:15:08.678Z" },
1895
+ { url = "https://files.pythonhosted.org/packages/13/26/9fe70f81d16b702f8c3a775e8731b50ad91d22dacd14c7599b60a0941cd1/orjson-3.11.8-cp311-cp311-win_amd64.whl", hash = "sha256:25e0c672a2e32348d2eb33057b41e754091f2835f87222e4675b796b92264f06", size = 127440, upload-time = "2026-03-31T16:15:09.994Z" },
1896
+ { url = "https://files.pythonhosted.org/packages/e8/c6/b038339f4145efd2859c1ca53097a52c0bb9cbdd24f947ebe146da1ad067/orjson-3.11.8-cp311-cp311-win_arm64.whl", hash = "sha256:9185589c1f2a944c17e26c9925dcdbc2df061cc4a145395c57f0c51f9b5dbfcd", size = 127399, upload-time = "2026-03-31T16:15:11.412Z" },
1897
+ { url = "https://files.pythonhosted.org/packages/01/f6/8d58b32ab32d9215973a1688aebd098252ee8af1766c0e4e36e7831f0295/orjson-3.11.8-cp312-cp312-macosx_10_15_x86_64.macosx_11_0_arm64.macosx_10_15_universal2.whl", hash = "sha256:1cd0b77e77c95758f8e1100139844e99f3ccc87e71e6fc8e1c027e55807c549f", size = 229233, upload-time = "2026-03-31T16:15:12.762Z" },
1898
+ { url = "https://files.pythonhosted.org/packages/a9/8b/2ffe35e71f6b92622e8ea4607bf33ecf7dfb51b3619dcfabfd36cbe2d0a5/orjson-3.11.8-cp312-cp312-macosx_15_0_arm64.whl", hash = "sha256:6a3d159d5ffa0e3961f353c4b036540996bf8b9697ccc38261c0eac1fd3347a6", size = 128772, upload-time = "2026-03-31T16:15:14.237Z" },
1899
+ { url = "https://files.pythonhosted.org/packages/27/d2/1f8682ae50d5c6897a563cb96bc106da8c9cb5b7b6e81a52e4cc086679b9/orjson-3.11.8-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:76070a76e9c5ae661e2d9848f216980d8d533e0f8143e6ed462807b242e3c5e8", size = 131946, upload-time = "2026-03-31T16:15:15.607Z" },
1900
+ { url = "https://files.pythonhosted.org/packages/52/4b/5500f76f0eece84226e0689cb48dcde081104c2fa6e2483d17ca13685ffb/orjson-3.11.8-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:54153d21520a71a4c82a0dbb4523e468941d549d221dc173de0f019678cf3813", size = 130368, upload-time = "2026-03-31T16:15:17.066Z" },
1901
+ { url = "https://files.pythonhosted.org/packages/da/4e/58b927e08fbe9840e6c920d9e299b051ea667463b1f39a56e668669f8508/orjson-3.11.8-cp312-cp312-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:469ac2125611b7c5741a0b3798cd9e5786cbad6345f9f400c77212be89563bec", size = 135540, upload-time = "2026-03-31T16:15:18.404Z" },
1902
+ { url = "https://files.pythonhosted.org/packages/56/7c/ba7cb871cba1bcd5cd02ee34f98d894c6cea96353ad87466e5aef2429c60/orjson-3.11.8-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:14778ffd0f6896aa613951a7fbf4690229aa7a543cb2bfbe9f358e08aafa9546", size = 146877, upload-time = "2026-03-31T16:15:19.833Z" },
1903
+ { url = "https://files.pythonhosted.org/packages/0b/5d/eb9c25fc1386696c6a342cd361c306452c75e0b55e86ad602dd4827a7fd7/orjson-3.11.8-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:ea56a955056a6d6c550cf18b3348656a9d9a4f02e2d0c02cabf3c73f1055d506", size = 132837, upload-time = "2026-03-31T16:15:21.282Z" },
1904
+ { url = "https://files.pythonhosted.org/packages/37/87/5ddeb7fc1fbd9004aeccab08426f34c81a5b4c25c7061281862b015fce2b/orjson-3.11.8-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:53a0f57e59a530d18a142f4d4ba6dfc708dc5fdedce45e98ff06b44930a2a48f", size = 133624, upload-time = "2026-03-31T16:15:22.641Z" },
1905
+ { url = "https://files.pythonhosted.org/packages/22/09/90048793db94ee4b2fcec4ac8e5ddb077367637d6650be896b3494b79bb7/orjson-3.11.8-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:9b48e274f8824567d74e2158199e269597edf00823a1b12b63d48462bbf5123e", size = 141904, upload-time = "2026-03-31T16:15:24.435Z" },
1906
+ { url = "https://files.pythonhosted.org/packages/c0/cf/eb284847487821a5d415e54149a6449ba9bfc5872ce63ab7be41b8ec401c/orjson-3.11.8-cp312-cp312-musllinux_1_2_armv7l.whl", hash = "sha256:3f262401086a3960586af06c054609365e98407151f5ea24a62893a40d80dbbb", size = 423742, upload-time = "2026-03-31T16:15:26.155Z" },
1907
+ { url = "https://files.pythonhosted.org/packages/44/09/e12423d327071c851c13e76936f144a96adacfc037394dec35ac3fc8d1e8/orjson-3.11.8-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:8e8c6218b614badf8e229b697865df4301afa74b791b6c9ade01d19a9953a942", size = 147806, upload-time = "2026-03-31T16:15:27.909Z" },
1908
+ { url = "https://files.pythonhosted.org/packages/b3/6d/37c2589ba864e582ffe7611643314785c6afb1f83c701654ef05daa8fcc7/orjson-3.11.8-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:093d489fa039ddade2db541097dbb484999fcc65fc2b0ff9819141e2ab364f25", size = 136485, upload-time = "2026-03-31T16:15:29.749Z" },
1909
+ { url = "https://files.pythonhosted.org/packages/be/c9/135194a02ab76b04ed9a10f68624b7ebd238bbe55548878b11ff15a0f352/orjson-3.11.8-cp312-cp312-win32.whl", hash = "sha256:e0950ed1bcb9893f4293fd5c5a7ee10934fbf82c4101c70be360db23ce24b7d2", size = 131966, upload-time = "2026-03-31T16:15:31.687Z" },
1910
+ { url = "https://files.pythonhosted.org/packages/ed/9a/9796f8fbe3cf30ce9cb696748dbb535e5c87be4bf4fe2e9ca498ef1fa8cf/orjson-3.11.8-cp312-cp312-win_amd64.whl", hash = "sha256:3cf17c141617b88ced4536b2135c552490f07799f6ad565948ea07bef0dcb9a6", size = 127441, upload-time = "2026-03-31T16:15:33.333Z" },
1911
+ { url = "https://files.pythonhosted.org/packages/cc/47/5aaf54524a7a4a0dd09dd778f3fa65dd2108290615b652e23d944152bc8e/orjson-3.11.8-cp312-cp312-win_arm64.whl", hash = "sha256:48854463b0572cc87dac7d981aa72ed8bf6deedc0511853dc76b8bbd5482d36d", size = 127364, upload-time = "2026-03-31T16:15:34.748Z" },
1912
  ]
1913
 
1914
  [[package]]
 
1949
  { url = "https://files.pythonhosted.org/packages/d5/18/7f0bd34ae27b28159aa80f2a6799f47fda34f7fb938a76e20c7b7fe3b200/pandas-3.0.2-cp312-cp312-win_arm64.whl", hash = "sha256:08504503f7101300107ecdc8df73658e4347586db5cfdadabc1592e9d7e7a0fd", size = 9056118, upload-time = "2026-03-31T06:46:54.548Z" },
1950
  ]
1951
 
1952
+ [[package]]
1953
+ name = "pathable"
1954
+ version = "0.5.0"
1955
+ source = { registry = "https://pypi.org/simple" }
1956
+ sdist = { url = "https://files.pythonhosted.org/packages/72/55/b748445cb4ea6b125626f15379be7c96d1035d4fa3e8fee362fa92298abf/pathable-0.5.0.tar.gz", hash = "sha256:d81938348a1cacb525e7c75166270644782c0fb9c8cecc16be033e71427e0ef1", size = 16655, upload-time = "2026-02-20T08:47:00.748Z" }
1957
+ wheels = [
1958
+ { url = "https://files.pythonhosted.org/packages/52/96/5a770e5c461462575474468e5af931cff9de036e7c2b4fea23c1c58d2cbe/pathable-0.5.0-py3-none-any.whl", hash = "sha256:646e3d09491a6351a0c82632a09c02cdf70a252e73196b36d8a15ba0a114f0a6", size = 16867, upload-time = "2026-02-20T08:46:59.536Z" },
1959
+ ]
1960
+
1961
  [[package]]
1962
  name = "pathspec"
1963
  version = "1.1.0"
 
2092
  { url = "https://files.pythonhosted.org/packages/8c/c7/7bb2e321574b10df20cbde462a94e2b71d05f9bbda251ef27d104668306a/psutil-7.2.2-cp37-abi3-win_arm64.whl", hash = "sha256:8c233660f575a5a89e6d4cb65d9f938126312bca76d8fe087b947b3a1aaac9ee", size = 134617, upload-time = "2026-01-28T18:15:36.514Z" },
2093
  ]
2094
 
2095
+ [[package]]
2096
+ name = "py-key-value-aio"
2097
+ version = "0.4.4"
2098
+ source = { registry = "https://pypi.org/simple" }
2099
+ dependencies = [
2100
+ { name = "beartype" },
2101
+ { name = "typing-extensions" },
2102
+ ]
2103
+ sdist = { url = "https://files.pythonhosted.org/packages/04/3c/0397c072a38d4bc580994b42e0c90c5f44f679303489e4376289534735e5/py_key_value_aio-0.4.4.tar.gz", hash = "sha256:e3012e6243ed7cc09bb05457bd4d03b1ba5c2b1ca8700096b3927db79ffbbe55", size = 92300, upload-time = "2026-02-16T21:21:43.245Z" }
2104
+ wheels = [
2105
+ { url = "https://files.pythonhosted.org/packages/32/69/f1b537ee70b7def42d63124a539ed3026a11a3ffc3086947a1ca6e861868/py_key_value_aio-0.4.4-py3-none-any.whl", hash = "sha256:18e17564ecae61b987f909fc2cd41ee2012c84b4b1dcb8c055cf8b4bc1bf3f5d", size = 152291, upload-time = "2026-02-16T21:21:44.241Z" },
2106
+ ]
2107
+
2108
+ [package.optional-dependencies]
2109
+ filetree = [
2110
+ { name = "aiofile" },
2111
+ { name = "anyio" },
2112
+ ]
2113
+ keyring = [
2114
+ { name = "keyring" },
2115
+ ]
2116
+ memory = [
2117
+ { name = "cachetools" },
2118
+ ]
2119
+
2120
  [[package]]
2121
  name = "pyarrow"
2122
  version = "24.0.0"
 
2139
  { url = "https://files.pythonhosted.org/packages/66/1c/e3e72c8014ad2743ca64a701652c733cc5cbcee15c0463a32a8c55518d9e/pyarrow-24.0.0-cp312-cp312-win_amd64.whl", hash = "sha256:295f0a7f2e242dabd513737cf076007dc5b2d59237e3eca37b05c0c6446f3826", size = 27355660, upload-time = "2026-04-21T10:48:01.718Z" },
2140
  ]
2141
 
2142
+ [[package]]
2143
+ name = "pycparser"
2144
+ version = "3.0"
2145
+ source = { registry = "https://pypi.org/simple" }
2146
+ sdist = { url = "https://files.pythonhosted.org/packages/1b/7d/92392ff7815c21062bea51aa7b87d45576f649f16458d78b7cf94b9ab2e6/pycparser-3.0.tar.gz", hash = "sha256:600f49d217304a5902ac3c37e1281c9fe94e4d0489de643a9504c5cdfdfc6b29", size = 103492, upload-time = "2026-01-21T14:26:51.89Z" }
2147
+ wheels = [
2148
+ { url = "https://files.pythonhosted.org/packages/0c/c3/44f3fbbfa403ea2a7c779186dc20772604442dde72947e7d01069cbe98e3/pycparser-3.0-py3-none-any.whl", hash = "sha256:b727414169a36b7d524c1c3e31839a521725078d7b2ff038656844266160a992", size = 48172, upload-time = "2026-01-21T14:26:50.693Z" },
2149
+ ]
2150
+
2151
  [[package]]
2152
  name = "pydantic"
2153
  version = "2.13.3"
 
2163
  { url = "https://files.pythonhosted.org/packages/f3/0a/fd7d723f8f8153418fb40cf9c940e82004fce7e987026b08a68a36dd3fe7/pydantic-2.13.3-py3-none-any.whl", hash = "sha256:6db14ac8dfc9a1e57f87ea2c0de670c251240f43cb0c30a5130e9720dc612927", size = 471981, upload-time = "2026-04-20T14:46:41.402Z" },
2164
  ]
2165
 
2166
+ [package.optional-dependencies]
2167
+ email = [
2168
+ { name = "email-validator" },
2169
+ ]
2170
+
2171
  [[package]]
2172
  name = "pydantic-core"
2173
  version = "2.46.3"
 
2225
  { url = "https://files.pythonhosted.org/packages/07/0f/1c34a74c8d07136f0d729ffe5e1fdab04fbdaa7684f61a92f92511a84a15/pydantic_core-2.46.3-pp311-pypy311_pp73-win_amd64.whl", hash = "sha256:b00b76f7142fc60c762ce579bd29c8fa44aaa56592dd3c54fab3928d0d4ca6ff", size = 2184144, upload-time = "2026-04-20T14:42:57Z" },
2226
  ]
2227
 
2228
+ [[package]]
2229
+ name = "pydantic-settings"
2230
+ version = "2.14.0"
2231
+ source = { registry = "https://pypi.org/simple" }
2232
+ dependencies = [
2233
+ { name = "pydantic" },
2234
+ { name = "python-dotenv" },
2235
+ { name = "typing-inspection" },
2236
+ ]
2237
+ sdist = { url = "https://files.pythonhosted.org/packages/42/98/c8345dccdc31de4228c039a98f6467a941e39558da41c1744fbe29fa5666/pydantic_settings-2.14.0.tar.gz", hash = "sha256:24285fd4b0e0c06507dd9fdfd331ee23794305352aaec8fc4eb92d4047aeb67d", size = 235709, upload-time = "2026-04-20T13:37:40.293Z" }
2238
+ wheels = [
2239
+ { url = "https://files.pythonhosted.org/packages/01/dd/bebff3040138f00ae8a102d426b27349b9a49acc310fcae7f92112d867e3/pydantic_settings-2.14.0-py3-none-any.whl", hash = "sha256:fc8d5d692eb7092e43c8647c1c35a3ecd00e040fcf02ed86f4cb5458ca62182e", size = 60940, upload-time = "2026-04-20T13:37:38.586Z" },
2240
+ ]
2241
+
2242
+ [[package]]
2243
+ name = "pydub"
2244
+ version = "0.25.1"
2245
+ source = { registry = "https://pypi.org/simple" }
2246
+ sdist = { url = "https://files.pythonhosted.org/packages/fe/9a/e6bca0eed82db26562c73b5076539a4a08d3cffd19c3cc5913a3e61145fd/pydub-0.25.1.tar.gz", hash = "sha256:980a33ce9949cab2a569606b65674d748ecbca4f0796887fd6f46173a7b0d30f", size = 38326, upload-time = "2021-03-10T02:09:54.659Z" }
2247
+ wheels = [
2248
+ { url = "https://files.pythonhosted.org/packages/a6/53/d78dc063216e62fc55f6b2eebb447f6a4b0a59f55c8406376f76bf959b08/pydub-0.25.1-py2.py3-none-any.whl", hash = "sha256:65617e33033874b59d87db603aa1ed450633288aefead953b30bded59cb599a6", size = 32327, upload-time = "2021-03-10T02:09:53.503Z" },
2249
+ ]
2250
+
2251
  [[package]]
2252
  name = "pygments"
2253
  version = "2.20.0"
 
2257
  { url = "https://files.pythonhosted.org/packages/f4/7e/a72dd26f3b0f4f2bf1dd8923c85f7ceb43172af56d63c7383eb62b332364/pygments-2.20.0-py3-none-any.whl", hash = "sha256:81a9e26dd42fd28a23a2d169d86d7ac03b46e2f8b59ed4698fb4785f946d0176", size = 1231151, upload-time = "2026-03-29T13:29:30.038Z" },
2258
  ]
2259
 
2260
+ [[package]]
2261
+ name = "pyjwt"
2262
+ version = "2.12.1"
2263
+ source = { registry = "https://pypi.org/simple" }
2264
+ sdist = { url = "https://files.pythonhosted.org/packages/c2/27/a3b6e5bf6ff856d2509292e95c8f57f0df7017cf5394921fc4e4ef40308a/pyjwt-2.12.1.tar.gz", hash = "sha256:c74a7a2adf861c04d002db713dd85f84beb242228e671280bf709d765b03672b", size = 102564, upload-time = "2026-03-13T19:27:37.25Z" }
2265
+ wheels = [
2266
+ { url = "https://files.pythonhosted.org/packages/e5/7a/8dd906bd22e79e47397a61742927f6747fe93242ef86645ee9092e610244/pyjwt-2.12.1-py3-none-any.whl", hash = "sha256:28ca37c070cad8ba8cd9790cd940535d40274d22f80ab87f3ac6a713e6e8454c", size = 29726, upload-time = "2026-03-13T19:27:35.677Z" },
2267
+ ]
2268
+
2269
+ [package.optional-dependencies]
2270
+ crypto = [
2271
+ { name = "cryptography" },
2272
+ ]
2273
+
2274
  [[package]]
2275
  name = "pyparsing"
2276
  version = "3.3.2"
 
2280
  { url = "https://files.pythonhosted.org/packages/10/bd/c038d7cc38edc1aa5bf91ab8068b63d4308c66c4c8bb3cbba7dfbc049f9c/pyparsing-3.3.2-py3-none-any.whl", hash = "sha256:850ba148bd908d7e2411587e247a1e4f0327839c40e2e5e6d05a007ecc69911d", size = 122781, upload-time = "2026-01-21T03:57:55.912Z" },
2281
  ]
2282
 
2283
+ [[package]]
2284
+ name = "pyperclip"
2285
+ version = "1.11.0"
2286
+ source = { registry = "https://pypi.org/simple" }
2287
+ sdist = { url = "https://files.pythonhosted.org/packages/e8/52/d87eba7cb129b81563019d1679026e7a112ef76855d6159d24754dbd2a51/pyperclip-1.11.0.tar.gz", hash = "sha256:244035963e4428530d9e3a6101a1ef97209c6825edab1567beac148ccc1db1b6", size = 12185, upload-time = "2025-09-26T14:40:37.245Z" }
2288
+ wheels = [
2289
+ { url = "https://files.pythonhosted.org/packages/df/80/fc9d01d5ed37ba4c42ca2b55b4339ae6e200b456be3a1aaddf4a9fa99b8c/pyperclip-1.11.0-py3-none-any.whl", hash = "sha256:299403e9ff44581cb9ba2ffeed69c7aa96a008622ad0c46cb575ca75b5b84273", size = 11063, upload-time = "2025-09-26T14:40:36.069Z" },
2290
+ ]
2291
+
2292
  [[package]]
2293
  name = "pytest"
2294
  version = "9.0.3"
 
2352
  { url = "https://files.pythonhosted.org/packages/0b/d7/1959b9648791274998a9c3526f6d0ec8fd2233e4d4acce81bbae76b44b2a/python_dotenv-1.2.2-py3-none-any.whl", hash = "sha256:1d8214789a24de455a8b8bd8ae6fe3c6b69a5e3d64aa8a8e5d68e694bbcb285a", size = 22101, upload-time = "2026-03-01T16:00:25.09Z" },
2353
  ]
2354
 
2355
+ [[package]]
2356
+ name = "python-multipart"
2357
+ version = "0.0.26"
2358
+ source = { registry = "https://pypi.org/simple" }
2359
+ sdist = { url = "https://files.pythonhosted.org/packages/88/71/b145a380824a960ebd60e1014256dbb7d2253f2316ff2d73dfd8928ec2c3/python_multipart-0.0.26.tar.gz", hash = "sha256:08fadc45918cd615e26846437f50c5d6d23304da32c341f289a617127b081f17", size = 43501, upload-time = "2026-04-10T14:09:59.473Z" }
2360
+ wheels = [
2361
+ { url = "https://files.pythonhosted.org/packages/9a/22/f1925cdda983ab66fc8ec6ec8014b959262747e58bdca26a4e3d1da29d56/python_multipart-0.0.26-py3-none-any.whl", hash = "sha256:c0b169f8c4484c13b0dcf2ef0ec3a4adb255c4b7d18d8e420477d2b1dd03f185", size = 28847, upload-time = "2026-04-10T14:09:58.131Z" },
2362
+ ]
2363
+
2364
+ [[package]]
2365
+ name = "pytz"
2366
+ version = "2026.1.post1"
2367
+ source = { registry = "https://pypi.org/simple" }
2368
+ sdist = { url = "https://files.pythonhosted.org/packages/56/db/b8721d71d945e6a8ac63c0fc900b2067181dbb50805958d4d4661cf7d277/pytz-2026.1.post1.tar.gz", hash = "sha256:3378dde6a0c3d26719182142c56e60c7f9af7e968076f31aae569d72a0358ee1", size = 321088, upload-time = "2026-03-03T07:47:50.683Z" }
2369
+ wheels = [
2370
+ { url = "https://files.pythonhosted.org/packages/10/99/781fe0c827be2742bcc775efefccb3b048a3a9c6ce9aec0cbf4a101677e5/pytz-2026.1.post1-py2.py3-none-any.whl", hash = "sha256:f2fd16142fda348286a75e1a524be810bb05d444e5a081f37f7affc635035f7a", size = 510489, upload-time = "2026-03-03T07:47:49.167Z" },
2371
+ ]
2372
+
2373
+ [[package]]
2374
+ name = "pywin32"
2375
+ version = "311"
2376
+ source = { registry = "https://pypi.org/simple" }
2377
+ wheels = [
2378
+ { url = "https://files.pythonhosted.org/packages/7c/af/449a6a91e5d6db51420875c54f6aff7c97a86a3b13a0b4f1a5c13b988de3/pywin32-311-cp311-cp311-win32.whl", hash = "sha256:184eb5e436dea364dcd3d2316d577d625c0351bf237c4e9a5fabbcfa5a58b151", size = 8697031, upload-time = "2025-07-14T20:13:13.266Z" },
2379
+ { url = "https://files.pythonhosted.org/packages/51/8f/9bb81dd5bb77d22243d33c8397f09377056d5c687aa6d4042bea7fbf8364/pywin32-311-cp311-cp311-win_amd64.whl", hash = "sha256:3ce80b34b22b17ccbd937a6e78e7225d80c52f5ab9940fe0506a1a16f3dab503", size = 9508308, upload-time = "2025-07-14T20:13:15.147Z" },
2380
+ { url = "https://files.pythonhosted.org/packages/44/7b/9c2ab54f74a138c491aba1b1cd0795ba61f144c711daea84a88b63dc0f6c/pywin32-311-cp311-cp311-win_arm64.whl", hash = "sha256:a733f1388e1a842abb67ffa8e7aad0e70ac519e09b0f6a784e65a136ec7cefd2", size = 8703930, upload-time = "2025-07-14T20:13:16.945Z" },
2381
+ { url = "https://files.pythonhosted.org/packages/e7/ab/01ea1943d4eba0f850c3c61e78e8dd59757ff815ff3ccd0a84de5f541f42/pywin32-311-cp312-cp312-win32.whl", hash = "sha256:750ec6e621af2b948540032557b10a2d43b0cee2ae9758c54154d711cc852d31", size = 8706543, upload-time = "2025-07-14T20:13:20.765Z" },
2382
+ { url = "https://files.pythonhosted.org/packages/d1/a8/a0e8d07d4d051ec7502cd58b291ec98dcc0c3fff027caad0470b72cfcc2f/pywin32-311-cp312-cp312-win_amd64.whl", hash = "sha256:b8c095edad5c211ff31c05223658e71bf7116daa0ecf3ad85f3201ea3190d067", size = 9495040, upload-time = "2025-07-14T20:13:22.543Z" },
2383
+ { url = "https://files.pythonhosted.org/packages/ba/3a/2ae996277b4b50f17d61f0603efd8253cb2d79cc7ae159468007b586396d/pywin32-311-cp312-cp312-win_arm64.whl", hash = "sha256:e286f46a9a39c4a18b319c28f59b61de793654af2f395c102b4f819e584b5852", size = 8710102, upload-time = "2025-07-14T20:13:24.682Z" },
2384
+ ]
2385
+
2386
+ [[package]]
2387
+ name = "pywin32-ctypes"
2388
+ version = "0.2.3"
2389
+ source = { registry = "https://pypi.org/simple" }
2390
+ sdist = { url = "https://files.pythonhosted.org/packages/85/9f/01a1a99704853cb63f253eea009390c88e7131c67e66a0a02099a8c917cb/pywin32-ctypes-0.2.3.tar.gz", hash = "sha256:d162dc04946d704503b2edc4d55f3dba5c1d539ead017afa00142c38b9885755", size = 29471, upload-time = "2024-08-14T10:15:34.626Z" }
2391
+ wheels = [
2392
+ { url = "https://files.pythonhosted.org/packages/de/3d/8161f7711c017e01ac9f008dfddd9410dff3674334c233bde66e7ba65bbf/pywin32_ctypes-0.2.3-py3-none-any.whl", hash = "sha256:8a1513379d709975552d202d942d9837758905c8d01eb82b8bcc30918929e7b8", size = 30756, upload-time = "2024-08-14T10:15:33.187Z" },
2393
+ ]
2394
+
2395
  [[package]]
2396
  name = "pyyaml"
2397
  version = "6.0.3"
 
2501
  { url = "https://files.pythonhosted.org/packages/82/3b/64d4899d73f91ba49a8c18a8ff3f0ea8f1c1d75481760df8c68ef5235bf5/rich-15.0.0-py3-none-any.whl", hash = "sha256:33bd4ef74232fb73fe9279a257718407f169c09b78a87ad3d296f548e27de0bb", size = 310654, upload-time = "2026-04-12T08:24:02.83Z" },
2502
  ]
2503
 
2504
+ [[package]]
2505
+ name = "rich-rst"
2506
+ version = "1.3.2"
2507
+ source = { registry = "https://pypi.org/simple" }
2508
+ dependencies = [
2509
+ { name = "docutils" },
2510
+ { name = "rich" },
2511
+ ]
2512
+ sdist = { url = "https://files.pythonhosted.org/packages/bc/6d/a506aaa4a9eaa945ed8ab2b7347859f53593864289853c5d6d62b77246e0/rich_rst-1.3.2.tar.gz", hash = "sha256:a1196fdddf1e364b02ec68a05e8ff8f6914fee10fbca2e6b6735f166bb0da8d4", size = 14936, upload-time = "2025-10-14T16:49:45.332Z" }
2513
+ wheels = [
2514
+ { url = "https://files.pythonhosted.org/packages/13/2f/b4530fbf948867702d0a3f27de4a6aab1d156f406d72852ab902c4d04de9/rich_rst-1.3.2-py3-none-any.whl", hash = "sha256:a99b4907cbe118cf9d18b0b44de272efa61f15117c61e39ebdc431baf5df722a", size = 12567, upload-time = "2025-10-14T16:49:42.953Z" },
2515
+ ]
2516
+
2517
  [[package]]
2518
  name = "rpds-py"
2519
  version = "0.30.0"
 
2589
  { url = "https://files.pythonhosted.org/packages/c0/98/6beb4b351e472e5f4c4613f7c35a5290b8be2497e183825310c4c3a3984b/ruff-0.15.12-py3-none-win_arm64.whl", hash = "sha256:a538f7a82d061cee7be55542aca1d86d1393d55d81d4fcc314370f4340930d4f", size = 11120821, upload-time = "2026-04-24T18:16:57.979Z" },
2590
  ]
2591
 
2592
+ [[package]]
2593
+ name = "safehttpx"
2594
+ version = "0.1.7"
2595
+ source = { registry = "https://pypi.org/simple" }
2596
+ dependencies = [
2597
+ { name = "httpx" },
2598
+ ]
2599
+ sdist = { url = "https://files.pythonhosted.org/packages/89/d1/4282284d9cf1ee873607a46442da977fc3c985059315ab23610be31d5885/safehttpx-0.1.7.tar.gz", hash = "sha256:db201c0978c41eddb8bb480f3eee59dd67304fdd91646035e9d9a720049a9d23", size = 10385, upload-time = "2025-10-24T18:30:09.783Z" }
2600
+ wheels = [
2601
+ { url = "https://files.pythonhosted.org/packages/2e/a3/0f0b7d78e2f1eb9e8e1afbff1d2bff8d60144aee17aca51c065b516743dd/safehttpx-0.1.7-py3-none-any.whl", hash = "sha256:c4f4a162db6993464d7ca3d7cc4af0ffc6515a606dfd220b9f82c6945d869cde", size = 8959, upload-time = "2025-10-24T18:30:08.733Z" },
2602
+ ]
2603
+
2604
  [[package]]
2605
  name = "safetensors"
2606
  version = "0.7.0"
 
2694
  { url = "https://files.pythonhosted.org/packages/83/11/00d3c3dfc25ad54e731d91449895a79e4bf2384dc3ac01809010ba88f6d5/seaborn-0.13.2-py3-none-any.whl", hash = "sha256:636f8336facf092165e27924f223d3c62ca560b1f2bb5dff7ab7fad265361987", size = 294914, upload-time = "2024-01-25T13:21:49.598Z" },
2695
  ]
2696
 
2697
+ [[package]]
2698
+ name = "secretstorage"
2699
+ version = "3.5.0"
2700
+ source = { registry = "https://pypi.org/simple" }
2701
+ dependencies = [
2702
+ { name = "cryptography", marker = "sys_platform != 'emscripten' and sys_platform != 'win32'" },
2703
+ { name = "jeepney", marker = "sys_platform != 'emscripten' and sys_platform != 'win32'" },
2704
+ ]
2705
+ sdist = { url = "https://files.pythonhosted.org/packages/1c/03/e834bcd866f2f8a49a85eaff47340affa3bfa391ee9912a952a1faa68c7b/secretstorage-3.5.0.tar.gz", hash = "sha256:f04b8e4689cbce351744d5537bf6b1329c6fc68f91fa666f60a380edddcd11be", size = 19884, upload-time = "2025-11-23T19:02:53.191Z" }
2706
+ wheels = [
2707
+ { url = "https://files.pythonhosted.org/packages/b7/46/f5af3402b579fd5e11573ce652019a67074317e18c1935cc0b4ba9b35552/secretstorage-3.5.0-py3-none-any.whl", hash = "sha256:0ce65888c0725fcb2c5bc0fdb8e5438eece02c523557ea40ce0703c266248137", size = 15554, upload-time = "2025-11-23T19:02:51.545Z" },
2708
+ ]
2709
+
2710
+ [[package]]
2711
+ name = "semantic-version"
2712
+ version = "2.10.0"
2713
+ source = { registry = "https://pypi.org/simple" }
2714
+ sdist = { url = "https://files.pythonhosted.org/packages/7d/31/f2289ce78b9b473d582568c234e104d2a342fd658cc288a7553d83bb8595/semantic_version-2.10.0.tar.gz", hash = "sha256:bdabb6d336998cbb378d4b9db3a4b56a1e3235701dc05ea2690d9a997ed5041c", size = 52289, upload-time = "2022-05-26T13:35:23.454Z" }
2715
+ wheels = [
2716
+ { url = "https://files.pythonhosted.org/packages/6a/23/8146aad7d88f4fcb3a6218f41a60f6c2d4e3a72de72da1825dc7c8f7877c/semantic_version-2.10.0-py2.py3-none-any.whl", hash = "sha256:de78a3b8e0feda74cabc54aab2da702113e33ac9d9eb9d2389bcf1f58b7d9177", size = 15552, upload-time = "2022-05-26T13:35:21.206Z" },
2717
+ ]
2718
+
2719
  [[package]]
2720
  name = "sentry-sdk"
2721
  version = "2.58.0"
 
2774
  { url = "https://files.pythonhosted.org/packages/e9/44/75a9c9421471a6c4805dbf2356f7c181a29c1879239abab1ea2cc8f38b40/sniffio-1.3.1-py3-none-any.whl", hash = "sha256:2f6da418d1f1e0fddd844478f41680e794e6051915791a034ff65e5f100525a2", size = 10235, upload-time = "2024-02-25T23:20:01.196Z" },
2775
  ]
2776
 
2777
+ [[package]]
2778
+ name = "sse-starlette"
2779
+ version = "3.3.4"
2780
+ source = { registry = "https://pypi.org/simple" }
2781
+ dependencies = [
2782
+ { name = "anyio" },
2783
+ { name = "starlette" },
2784
+ ]
2785
+ sdist = { url = "https://files.pythonhosted.org/packages/26/8c/f9290339ef6d79badbc010f067cd769d6601ec11a57d78569c683fb4dd87/sse_starlette-3.3.4.tar.gz", hash = "sha256:aaf92fc067af8a5427192895ac028e947b484ac01edbc3caf00e7e7137c7bef1", size = 32427, upload-time = "2026-03-29T09:00:23.307Z" }
2786
+ wheels = [
2787
+ { url = "https://files.pythonhosted.org/packages/f8/7f/3de5402f39890ac5660b86bcf5c03f9d855dad5c4ed764866d7b592b46fd/sse_starlette-3.3.4-py3-none-any.whl", hash = "sha256:84bb06e58939a8b38d8341f1bc9792f06c2b53f48c608dd207582b664fc8f3c1", size = 14330, upload-time = "2026-03-29T09:00:21.846Z" },
2788
+ ]
2789
+
2790
  [[package]]
2791
  name = "starlette"
2792
  version = "1.0.0"
 
2883
  { url = "https://files.pythonhosted.org/packages/7b/61/cceae43728b7de99d9b847560c262873a1f6c98202171fd5ed62640b494b/tomli-2.4.1-py3-none-any.whl", hash = "sha256:0d85819802132122da43cb86656f8d1f8c6587d54ae7dcaf30e90533028b49fe", size = 14583, upload-time = "2026-03-25T20:22:03.012Z" },
2884
  ]
2885
 
2886
+ [[package]]
2887
+ name = "tomli-w"
2888
+ version = "1.2.0"
2889
+ source = { registry = "https://pypi.org/simple" }
2890
+ sdist = { url = "https://files.pythonhosted.org/packages/19/75/241269d1da26b624c0d5e110e8149093c759b7a286138f4efd61a60e75fe/tomli_w-1.2.0.tar.gz", hash = "sha256:2dd14fac5a47c27be9cd4c976af5a12d87fb1f0b4512f81d69cce3b35ae25021", size = 7184, upload-time = "2025-01-15T12:07:24.262Z" }
2891
+ wheels = [
2892
+ { url = "https://files.pythonhosted.org/packages/c7/18/c86eb8e0202e32dd3df50d43d7ff9854f8e0603945ff398974c1d91ac1ef/tomli_w-1.2.0-py3-none-any.whl", hash = "sha256:188306098d013b691fcadc011abd66727d3c414c571bb01b1a174ba8c983cf90", size = 6675, upload-time = "2025-01-15T12:07:22.074Z" },
2893
+ ]
2894
+
2895
+ [[package]]
2896
+ name = "tomlkit"
2897
+ version = "0.14.0"
2898
+ source = { registry = "https://pypi.org/simple" }
2899
+ sdist = { url = "https://files.pythonhosted.org/packages/c3/af/14b24e41977adb296d6bd1fb59402cf7d60ce364f90c890bd2ec65c43b5a/tomlkit-0.14.0.tar.gz", hash = "sha256:cf00efca415dbd57575befb1f6634c4f42d2d87dbba376128adb42c121b87064", size = 187167, upload-time = "2026-01-13T01:14:53.304Z" }
2900
+ wheels = [
2901
+ { url = "https://files.pythonhosted.org/packages/b5/11/87d6d29fb5d237229d67973a6c9e06e048f01cf4994dee194ab0ea841814/tomlkit-0.14.0-py3-none-any.whl", hash = "sha256:592064ed85b40fa213469f81ac584f67a4f2992509a7c3ea2d632208623a3680", size = 39310, upload-time = "2026-01-13T01:14:51.965Z" },
2902
+ ]
2903
+
2904
  [[package]]
2905
  name = "torch"
2906
  version = "2.11.0"
 
3036
  { url = "https://files.pythonhosted.org/packages/ce/e4/dccd7f47c4b64213ac01ef921a1337ee6e30e8c6466046018326977efd95/tzdata-2026.2-py2.py3-none-any.whl", hash = "sha256:bbe9af844f658da81a5f95019480da3a89415801f6cc966806612cc7169bffe7", size = 349321, upload-time = "2026-04-24T15:22:05.876Z" },
3037
  ]
3038
 
3039
+ [[package]]
3040
+ name = "uncalled-for"
3041
+ version = "0.3.1"
3042
+ source = { registry = "https://pypi.org/simple" }
3043
+ sdist = { url = "https://files.pythonhosted.org/packages/e1/68/35c1d87e608940badbcfeb630347aa0509897284684f61fab6423d02b253/uncalled_for-0.3.1.tar.gz", hash = "sha256:5e412ac6708f04b56bef5867b5dcf6690ebce4eb7316058d9c50787492bb4bca", size = 49693, upload-time = "2026-04-07T13:05:06.462Z" }
3044
+ wheels = [
3045
+ { url = "https://files.pythonhosted.org/packages/11/e1/7ec67882ad8fc9f86384bef6421fa252c9cbe5744f8df6ce77afc9eca1f5/uncalled_for-0.3.1-py3-none-any.whl", hash = "sha256:074cdc92da8356278f93d0ded6f2a66dd883dbecaf9bc89437646ee2289cc200", size = 11361, upload-time = "2026-04-07T13:05:05.341Z" },
3046
+ ]
3047
+
3048
  [[package]]
3049
  name = "urllib3"
3050
  version = "2.6.3"
 
3301
  { url = "https://files.pythonhosted.org/packages/d2/35/aeab955d6c425b227d5b7247eafb24f2653fedc32f95373a001af5dfeb9e/yarl-1.23.0-cp312-cp312-win_arm64.whl", hash = "sha256:6e87a6e8735b44816e7db0b2fbc9686932df473c826b0d9743148432e10bb9b9", size = 81879, upload-time = "2026-03-01T22:05:40.006Z" },
3302
  { url = "https://files.pythonhosted.org/packages/69/68/c8739671f5699c7dc470580a4f821ef37c32c4cb0b047ce223a7f115757f/yarl-1.23.0-py3-none-any.whl", hash = "sha256:a2df6afe50dea8ae15fa34c9f824a3ee958d785fd5d089063d960bae1daa0a3f", size = 48288, upload-time = "2026-03-01T22:07:51.388Z" },
3303
  ]
3304
+
3305
+ [[package]]
3306
+ name = "zipp"
3307
+ version = "3.23.1"
3308
+ source = { registry = "https://pypi.org/simple" }
3309
+ sdist = { url = "https://files.pythonhosted.org/packages/30/21/093488dfc7cc8964ded15ab726fad40f25fd3d788fd741cc1c5a17d78ee8/zipp-3.23.1.tar.gz", hash = "sha256:32120e378d32cd9714ad503c1d024619063ec28aad2248dc6672ad13edfa5110", size = 25965, upload-time = "2026-04-13T23:21:46.6Z" }
3310
+ wheels = [
3311
+ { url = "https://files.pythonhosted.org/packages/08/8a/0861bec20485572fbddf3dfba2910e38fe249796cb73ecdeb74e07eeb8d3/zipp-3.23.1-py3-none-any.whl", hash = "sha256:0b3596c50a5c700c9cb40ba8d86d9f2cc4807e9bedb06bcdf7fac85633e444dc", size = 10378, upload-time = "2026-04-13T23:21:45.386Z" },
3312
+ ]