├── .gitignore ├── .python-version ├── README.md ├── pyproject.toml ├── server.py └── uv.lock /.gitignore: -------------------------------------------------------------------------------- 1 | # Python-generated files 2 | __pycache__/ 3 | *.py[oc] 4 | build/ 5 | dist/ 6 | wheels/ 7 | *.egg-info 8 | 9 | # Virtual environments 10 | .venv 11 | -------------------------------------------------------------------------------- /.python-version: -------------------------------------------------------------------------------- 1 | 3.12 2 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Compiler Explorer MCP 2 | 3 | A Model Context Protocol (MCP) server that connects LLMs to the Compiler Explorer API, enabling them to compile code, explore compiler features, and analyze optimizations across different compilers and languages. 4 | 5 | ## Example Questions 6 | 7 | Here are some interesting questions you can ask your LLM using this MCP: 8 | 9 | ### Compiler Feature Exploration 10 | - "What is the earliest version of GCC that supports the `#embed` directive?" 11 | - "Show me how different versions of Clang handle C++20 modules" 12 | - "What optimization flags are available in Clang 12 that weren't in Clang 11?" 13 | - "Can you demonstrate how MSVC and GCC handle C++20 coroutines differently?" 14 | 15 | ### Optimization Analysis 16 | - "What's the assembly difference between `-O2` and `-O3` for a simple recursive Fibonacci function in GCC 13?" 17 | - "How does Clang's vectorization compare to GCC's for a basic matrix multiplication?" 18 | - "Show me how different optimization levels affect tail-call optimization in this recursive function" 19 | - "What's the impact of `-ffast-math` on this floating-point heavy computation?" 20 | 21 | ### Language Feature Support 22 | - "Which C++20 features are supported in the latest versions of GCC, Clang, and MSVC?" 23 | - "Show me how different compilers implement std::optional's memory layout" 24 | - "Compare how GCC and Clang handle C++20's constexpr virtual functions" 25 | - "Demonstrate the differences in how Intel and GCC compilers auto-vectorize SIMD operations" 26 | 27 | ### Assembly Deep Dives 28 | - "What's the most efficient way to implement a population count in x86 assembly across different CPU architectures?" 29 | - "Show me how different compilers optimize a simple string reverse function at -O3" 30 | - "Compare the assembly output of a virtual function call vs a normal function call" 31 | - "How do different compilers implement std::variant's type switching in assembly?" 32 | 33 | ### Cross-Language Comparison 34 | - "Compare the generated assembly for the same algorithm in C++, Rust, and Go" 35 | - "How do exception handling mechanisms differ between C++ and Rust in terms of generated code?" 36 | - "Show me the overhead of Rust's bounds checking compared to unchecked C++ array access" 37 | - "Compare how C++ and D implement RAII in terms of generated assembly" 38 | 39 | ### Performance Investigation 40 | - "What's the assembly-level difference between using std::sort and a hand-written quicksort?" 41 | - "Show me how different string concatenation methods compare in terms of generated instructions" 42 | - "Compare the efficiency of std::map vs std::unordered_map operations in assembly" 43 | - "How do different smart pointer implementations affect inlining and code size?" 44 | -------------------------------------------------------------------------------- /pyproject.toml: -------------------------------------------------------------------------------- 1 | [project] 2 | name = "compiler-explorer-mcp" 3 | version = "0.1.2" 4 | description = "MCP server allowing LLMs to interact remotely with compilers" 5 | readme = "README.md" 6 | requires-python = ">=3.12" 7 | license = "MIT" 8 | authors = [ 9 | { name = "Anthropic", email = "mcp-support@anthropic.com" } 10 | ] 11 | keywords = ["compiler", "explorer", "mcp", "llm", "claude"] 12 | classifiers = [ 13 | "Development Status :: 4 - Beta", 14 | "Intended Audience :: Developers", 15 | "License :: OSI Approved :: MIT License", 16 | "Programming Language :: Python :: 3", 17 | "Programming Language :: Python :: 3.12", 18 | "Topic :: Software Development :: Compilers", 19 | "Topic :: Software Development :: Libraries :: Python Modules", 20 | ] 21 | dependencies = [ 22 | "fastapi>=0.115.11", 23 | "httpx>=0.28.1", 24 | "mcp[cli]>=1.5.0", 25 | "pydantic>=2.10.6", 26 | "python-dotenv>=1.0.1", 27 | "uvicorn>=0.34.0", 28 | "websockets>=15.0.1", 29 | ] 30 | 31 | [dependency-groups] 32 | dev = [ 33 | "pyright>=1.1.397", 34 | "pytest>=8.3.5", 35 | "ruff>=0.11.2", 36 | ] 37 | 38 | [project.urls] 39 | Homepage = "https://github.com/anthropic/compiler-explorer-mcp" 40 | Repository = "https://github.com/anthropic/compiler-explorer-mcp" 41 | Documentation = "https://github.com/anthropic/compiler-explorer-mcp#readme" 42 | "Bug Tracker" = "https://github.com/anthropic/compiler-explorer-mcp/issues" 43 | 44 | [build-system] 45 | requires = ["hatchling"] 46 | build-backend = "hatchling.build" 47 | 48 | [tool.hatch.build.targets.wheel] 49 | packages = ["server.py"] 50 | 51 | [project.scripts] 52 | compiler-explorer-mcp = "server:mcp.run" 53 | -------------------------------------------------------------------------------- /server.py: -------------------------------------------------------------------------------- 1 | from typing import Any, TypeVar 2 | from pydantic import BaseModel 3 | from mcp.server.fastmcp import FastMCP, Context 4 | import httpx 5 | import json 6 | from fastapi import HTTPException 7 | import re 8 | 9 | T = TypeVar("T") 10 | 11 | 12 | class CompilationFilters(BaseModel): 13 | """Configuration for filtering compiler output. 14 | 15 | Attributes: 16 | binary: Include binary output in the response (default: False) 17 | binary_object: Include binary object output (default: False) 18 | comment_only: Include only comments from the output (default: True) 19 | demangle: Demangle C++ symbols in the output (default: True) 20 | directives: Include compiler directives in the output (default: True) 21 | execute: Include execution results (default: False) 22 | intel: Use Intel syntax for assembly output (default: True) 23 | labels: Include labels in the output (default: True) 24 | library_code: Include library code in the output (default: False) 25 | trim: Trim whitespace from the output (default: False) 26 | """ 27 | 28 | binary: bool = False 29 | binary_object: bool = False 30 | comment_only: bool = True 31 | demangle: bool = True 32 | directives: bool = True 33 | execute: bool = False 34 | intel: bool = True 35 | labels: bool = True 36 | library_code: bool = False 37 | trim: bool = False 38 | 39 | 40 | class Library(BaseModel): 41 | """Represents a library dependency for compilation. 42 | 43 | Attributes: 44 | id: Unique identifier for the library (e.g., 'boost', 'fmt') 45 | version: Version string of the library (e.g., '1.76.0') 46 | """ 47 | 48 | id: str 49 | version: str 50 | 51 | 52 | class CompilerExplorerError(Exception): 53 | def __init__(self, message: str, status_code: int = 500): 54 | self.message = message 55 | self.status_code = status_code 56 | super().__init__(self.message) 57 | 58 | 59 | class CompilerExplorerClient: 60 | """Client for interacting with Compiler Explorer API. 61 | 62 | This client provides methods to interact with the Compiler Explorer API, 63 | handling authentication, request formatting, and error handling. 64 | 65 | Args: 66 | base_url: Base URL for the Compiler Explorer API (default: "https://godbolt.org/api") 67 | """ 68 | 69 | def __init__(self, base_url: str = "https://godbolt.org/api"): 70 | self.base_url = base_url 71 | self.client = httpx.AsyncClient( 72 | headers={"Accept": "application/json", "Content-Type": "application/json"}, 73 | timeout=30.0, 74 | ) 75 | 76 | async def _make_request(self, method: str, url: str, **kwargs) -> Any: 77 | """Make HTTP request with error handling. 78 | 79 | Args: 80 | method: HTTP method to use (GET, POST, etc.) 81 | url: URL to make the request to 82 | **kwargs: Additional arguments to pass to the request 83 | 84 | Returns: 85 | Parsed JSON response from the API 86 | 87 | Raises: 88 | CompilerExplorerError: If the request fails or returns invalid JSON 89 | """ 90 | try: 91 | response = await self.client.request(method, url, **kwargs) 92 | response.raise_for_status() 93 | 94 | # Ensure we have valid JSON response 95 | try: 96 | return response.json() 97 | except json.JSONDecodeError as e: 98 | print(f"Response content: {response.text}") # Debug log 99 | raise CompilerExplorerError(f"Invalid JSON response: {str(e)}") 100 | 101 | except httpx.TimeoutException: 102 | raise CompilerExplorerError("Request timed out") 103 | except httpx.HTTPStatusError as e: 104 | raise CompilerExplorerError( 105 | f"HTTP error occurred: {str(e)}", status_code=e.response.status_code 106 | ) 107 | except Exception as e: 108 | raise CompilerExplorerError(f"Unexpected error: {str(e)}") 109 | 110 | async def list_languages(self) -> list[dict[str, str]]: 111 | """Get list of supported programming languages. 112 | 113 | Returns: 114 | List of dictionaries containing language information, each with keys: 115 | - id: Unique identifier for the language 116 | - name: Display name of the language 117 | - extensions: List of file extensions associated with the language 118 | 119 | Raises: 120 | CompilerExplorerError: If the API request fails 121 | """ 122 | return await self._make_request("GET", f"{self.base_url}/languages") 123 | 124 | async def list_compilers(self, language: str | None = None) -> list[dict[str, str]]: 125 | """Get list of available compilers. 126 | 127 | Args: 128 | language: Optional language filter to get compilers for a specific language 129 | 130 | Returns: 131 | List of dictionaries containing compiler information, each with keys: 132 | - id: Unique identifier for the compiler 133 | - name: Display name of the compiler 134 | - semver: Version string of the compiler 135 | - language: Programming language the compiler supports 136 | 137 | Raises: 138 | CompilerExplorerError: If the API request fails 139 | """ 140 | url = f"{self.base_url}/compilers" 141 | if language: 142 | url += f"/{language}" 143 | return await self._make_request("GET", url) 144 | 145 | async def compile_code( 146 | self, 147 | source: str, 148 | compiler: str, 149 | options: str = "", 150 | filters: CompilationFilters = CompilationFilters(), 151 | libraries: list[Library] = [], 152 | ) -> dict: 153 | """Compile code using specified compiler. 154 | 155 | Args: 156 | source: Source code to compile 157 | compiler: Compiler ID to use (e.g., 'gcc-12.2') 158 | options: Optional compiler flags and options 159 | filters: Optional configuration for filtering compiler output 160 | libraries: Optional list of library dependencies 161 | 162 | Returns: 163 | Dictionary containing compilation results with keys: 164 | - code: Exit code of the compilation 165 | - stdout: Standard output from the compiler 166 | - stderr: Standard error from the compiler 167 | - asm: Generated assembly (if applicable) 168 | 169 | Raises: 170 | CompilerExplorerError: If compilation fails or API request fails 171 | """ 172 | data = { 173 | "source": source, 174 | "options": { 175 | "userArguments": options or "", 176 | "filters": filters.dict() if filters else CompilationFilters().dict(), 177 | "libraries": [lib.dict() for lib in libraries] if libraries else [], 178 | }, 179 | } 180 | return await self._make_request( 181 | "POST", f"{self.base_url}/compiler/{compiler}/compile", json=data 182 | ) 183 | 184 | async def get_opcode_documentation(self, instruction_set: str, opcode: str) -> dict: 185 | """Get documentation for a specific opcode in a given instruction set. 186 | 187 | Args: 188 | instruction_set: Instruction set to search for opcode documentation 189 | opcode: Opcode to search for documentation 190 | """ 191 | return await self._make_request( 192 | "GET", f"{self.base_url}/asm/{instruction_set}/{opcode}" 193 | ) 194 | 195 | 196 | def get_unversioned_compiler_name(compiler_name: str, semver: str) -> str: 197 | """Get the unversioned compiler name from the versioned name. 198 | 199 | Args: 200 | compiler_name: Full compiler name including version 201 | semver: Version string to remove 202 | 203 | Returns: 204 | Cleaned compiler name without version information 205 | 206 | Example: 207 | >>> get_unversioned_compiler_name("gcc-12.2", "12.2") 208 | "gcc" 209 | """ 210 | return ( 211 | compiler_name.replace(semver, "").replace("none", "").replace("()", "").strip() 212 | ) 213 | 214 | 215 | def infer_compiler_id( 216 | compiler_name_or_id: str, compilers: list[dict[str, str]] 217 | ) -> str | None: 218 | """Infer the compiler ID from a name or ID string. 219 | 220 | Args: 221 | compiler_name_or_id: Either a compiler ID or name to match 222 | compilers: List of available compilers from the API 223 | 224 | Returns: 225 | Matching compiler ID if found, None otherwise 226 | 227 | Example: 228 | >>> compilers = [{"id": "gcc-12.2", "name": "GCC 12.2"}] 229 | >>> infer_compiler_id("gcc", compilers) 230 | "gcc-12.2" 231 | """ 232 | if compiler_name_or_id in [c["id"] for c in compilers]: 233 | compiler_id = compiler_name_or_id 234 | else: 235 | # Get the compiler ID from the name 236 | compiler_id = next( 237 | ( 238 | c["id"] 239 | for c in compilers 240 | if c["name"].lower().strip() == compiler_name_or_id.lower().strip() 241 | ), 242 | None, 243 | ) 244 | return compiler_id 245 | 246 | 247 | # Create an MCP server 248 | mcp = FastMCP("Compiler Explorer Bridge") 249 | ce_client = CompilerExplorerClient() 250 | 251 | 252 | @mcp.tool() 253 | async def list_languages() -> list[dict[str, str]]: 254 | """Get a list of supported programming languages. 255 | 256 | Returns: 257 | List of dictionaries containing language information, each with keys: 258 | - id: Unique identifier for the language 259 | - name: Display name of the language 260 | - extensions: List of file extensions associated with the language 261 | 262 | Raises: 263 | HTTPException: If the API request fails 264 | """ 265 | try: 266 | return await ce_client.list_languages() 267 | except CompilerExplorerError as e: 268 | raise HTTPException(status_code=e.status_code, detail=str(e)) 269 | 270 | 271 | # @mcp.tool() 272 | # async def list_compilers() -> List[str]: 273 | # """Get available compilers for a language""" 274 | # try: 275 | # compilers = await ce_client.list_compilers() 276 | # return list( 277 | # {get_unversioned_compiler_name(c["name"], c["semver"]) for c in compilers} 278 | # ) 279 | # except CompilerExplorerError as e: 280 | # raise HTTPException(status_code=e.status_code, detail=str(e)) 281 | 282 | 283 | @mcp.tool() 284 | async def list_compilers_for_language(language: str) -> list[str]: 285 | """Get available compilers for a specific programming language. 286 | 287 | Args: 288 | language: Programming language to get compilers for (e.g., 'cpp', 'rust') 289 | 290 | Returns: 291 | List of unversioned compiler names available for the language 292 | 293 | Raises: 294 | HTTPException: If the API request fails 295 | 296 | Example: 297 | >>> await list_compilers_for_language("cpp") 298 | ["gcc", "clang", "msvc"] 299 | """ 300 | try: 301 | compilers = await ce_client.list_compilers(language) 302 | return list( 303 | {get_unversioned_compiler_name(c["name"], c["semver"]) for c in compilers} 304 | ) 305 | except CompilerExplorerError as e: 306 | raise HTTPException(status_code=e.status_code, detail=str(e)) 307 | 308 | 309 | @mcp.tool() 310 | async def list_compiler_versions(compiler_regex: str) -> list[dict[str, str]]: 311 | """Get available compiler versions matching a compiler name regex. 312 | 313 | NOTE: This may return a lot of results! Choose a specific regex to narrow down the results and not overflow the MCP client. 314 | 315 | Args: 316 | compiler_regex: Regular expression to match compiler names (case-insensitive) 317 | 318 | Returns: 319 | List of dictionaries containing matching compiler information, each with keys: 320 | - id: Unique identifier for the compiler 321 | - name: Display name of the compiler 322 | - semver: Version string of the compiler 323 | 324 | Raises: 325 | HTTPException: If the API request fails 326 | 327 | Example: 328 | >>> await list_compiler_versions("gcc") 329 | [{"id": "gcc-12.2", "name": "GCC 12.2"}, {"id": "gcc-11.3", "name": "GCC 11.3"}] 330 | 331 | >>> await list_compiler_versions("clang.*trunk") 332 | [..., {"id": "irclangtrunk", "name": "clang (trunk)", "lang": "llvm", "compilerType": "", "semver": "(trunk)", "instructionSet": "amd64"}, ...] 333 | """ 334 | compilers = await ce_client.list_compilers() 335 | return [ 336 | c 337 | for c in compilers 338 | if re.search(compiler_regex, c["name"], re.IGNORECASE) 339 | or re.search(compiler_regex, c["id"], re.IGNORECASE) 340 | ] 341 | 342 | 343 | @mcp.tool() 344 | async def compile_code( 345 | source: str, 346 | language: str, 347 | compiler: str, 348 | ctx: Context, 349 | options: str = "", 350 | filters: CompilationFilters = CompilationFilters(), 351 | libraries: list[Library] = [], 352 | ) -> dict: 353 | """Compile source code using specified compiler and options. 354 | 355 | Args: 356 | source: Source code to compile 357 | language: Programming language of the source code 358 | compiler: Compiler name or ID to use 359 | ctx: MCP context for logging and error reporting 360 | options: Compiler flags and options 361 | filters: Configuration for filtering compiler output 362 | libraries: List of library dependencies 363 | 364 | Returns: 365 | Dictionary containing compilation results with keys: 366 | - code: Exit code of the compilation 367 | - stdout: Standard output from the compiler 368 | - stderr: Standard error from the compiler 369 | - asm: Generated assembly (if applicable) 370 | 371 | Raises: 372 | HTTPException: If compilation fails, compiler not found, or API request fails 373 | 374 | Example: 375 | >>> result = await compile_code( 376 | ... source="int main() { return 0; }", 377 | ... language="cpp", 378 | ... compiler="gcc", 379 | ... ctx=ctx 380 | ... ) 381 | """ 382 | try: 383 | compilers = await ce_client.list_compilers(language) 384 | compiler_id = infer_compiler_id(compiler, compilers) 385 | if not compiler_id: 386 | await ctx.error( 387 | message=f"Compiler '{compiler}' not found", 388 | level="error", 389 | ) 390 | raise HTTPException( 391 | status_code=404, detail=f"Compiler '{compiler}' not found" 392 | ) 393 | await ctx.log( 394 | message=f"Inferred compiler {compiler_id} from {compiler}. Compiling...", 395 | level="info", 396 | ) 397 | return await ce_client.compile_code( 398 | source=source, 399 | compiler=compiler_id, 400 | options=options, 401 | filters=filters, 402 | libraries=libraries, 403 | ) 404 | except CompilerExplorerError as e: 405 | raise HTTPException(status_code=e.status_code, detail=str(e)) 406 | 407 | 408 | @mcp.tool() 409 | async def get_opcode_documentation(instruction_set: str, opcode: str) -> dict[str, str]: 410 | """Get documentation for a specific opcode in a given instruction set. 411 | If a user asks about an opcode, but you don't have the instruction set, you can query list_compiler_versions for a specific compiler and it will tell you the instruction set. 412 | You are not an expert on opcodes, so if a user asks about an opcode, you should always use this tool! 413 | 414 | Args: 415 | instruction_set: Instruction set to search for opcode documentation 416 | opcode: Opcode to search for documentation 417 | 418 | Example: 419 | >>> await get_opcode_documentation("amd64", "lea") 420 | 421 | """ 422 | resp = await ce_client.get_opcode_documentation(instruction_set, opcode) 423 | resp.pop("html") 424 | return resp 425 | 426 | 427 | if __name__ == "__main__": 428 | mcp.run() 429 | -------------------------------------------------------------------------------- /uv.lock: -------------------------------------------------------------------------------- 1 | version = 1 2 | revision = 1 3 | requires-python = ">=3.12" 4 | 5 | [[package]] 6 | name = "annotated-types" 7 | version = "0.7.0" 8 | source = { registry = "https://pypi.org/simple" } 9 | sdist = { url = "https://files.pythonhosted.org/packages/ee/67/531ea369ba64dcff5ec9c3402f9f51bf748cec26dde048a2f973a4eea7f5/annotated_types-0.7.0.tar.gz", hash = "sha256:aff07c09a53a08bc8cfccb9c85b05f1aa9a2a6f23728d790723543408344ce89", size = 16081 } 10 | wheels = [ 11 | { url = "https://files.pythonhosted.org/packages/78/b6/6307fbef88d9b5ee7421e68d78a9f162e0da4900bc5f5793f6d3d0e34fb8/annotated_types-0.7.0-py3-none-any.whl", hash = "sha256:1f02e8b43a8fbbc3f3e0d4f0f4bfc8131bcb4eebe8849b8e5c773f3a1c582a53", size = 13643 }, 12 | ] 13 | 14 | [[package]] 15 | name = "anyio" 16 | version = "4.9.0" 17 | source = { registry = "https://pypi.org/simple" } 18 | dependencies = [ 19 | { name = "idna" }, 20 | { name = "sniffio" }, 21 | { name = "typing-extensions", marker = "python_full_version < '3.13'" }, 22 | ] 23 | sdist = { url = "https://files.pythonhosted.org/packages/95/7d/4c1bd541d4dffa1b52bd83fb8527089e097a106fc90b467a7313b105f840/anyio-4.9.0.tar.gz", hash = "sha256:673c0c244e15788651a4ff38710fea9675823028a6f08a5eda409e0c9840a028", size = 190949 } 24 | wheels = [ 25 | { url = "https://files.pythonhosted.org/packages/a1/ee/48ca1a7c89ffec8b6a0c5d02b89c305671d5ffd8d3c94acf8b8c408575bb/anyio-4.9.0-py3-none-any.whl", hash = "sha256:9f76d541cad6e36af7beb62e978876f3b41e3e04f2c1fbf0884604c0a9c4d93c", size = 100916 }, 26 | ] 27 | 28 | [[package]] 29 | name = "certifi" 30 | version = "2025.1.31" 31 | source = { registry = "https://pypi.org/simple" } 32 | sdist = { url = "https://files.pythonhosted.org/packages/1c/ab/c9f1e32b7b1bf505bf26f0ef697775960db7932abeb7b516de930ba2705f/certifi-2025.1.31.tar.gz", hash = "sha256:3d5da6925056f6f18f119200434a4780a94263f10d1c21d032a6f6b2baa20651", size = 167577 } 33 | wheels = [ 34 | { url = "https://files.pythonhosted.org/packages/38/fc/bce832fd4fd99766c04d1ee0eead6b0ec6486fb100ae5e74c1d91292b982/certifi-2025.1.31-py3-none-any.whl", hash = "sha256:ca78db4565a652026a4db2bcdf68f2fb589ea80d0be70e03929ed730746b84fe", size = 166393 }, 35 | ] 36 | 37 | [[package]] 38 | name = "click" 39 | version = "8.1.8" 40 | source = { registry = "https://pypi.org/simple" } 41 | dependencies = [ 42 | { name = "colorama", marker = "sys_platform == 'win32'" }, 43 | ] 44 | sdist = { url = "https://files.pythonhosted.org/packages/b9/2e/0090cbf739cee7d23781ad4b89a9894a41538e4fcf4c31dcdd705b78eb8b/click-8.1.8.tar.gz", hash = "sha256:ed53c9d8990d83c2a27deae68e4ee337473f6330c040a31d4225c9574d16096a", size = 226593 } 45 | wheels = [ 46 | { url = "https://files.pythonhosted.org/packages/7e/d4/7ebdbd03970677812aac39c869717059dbb71a4cfc033ca6e5221787892c/click-8.1.8-py3-none-any.whl", hash = "sha256:63c132bbbed01578a06712a2d1f497bb62d9c1c0d329b7903a866228027263b2", size = 98188 }, 47 | ] 48 | 49 | [[package]] 50 | name = "colorama" 51 | version = "0.4.6" 52 | source = { registry = "https://pypi.org/simple" } 53 | sdist = { url = "https://files.pythonhosted.org/packages/d8/53/6f443c9a4a8358a93a6792e2acffb9d9d5cb0a5cfd8802644b7b1c9a02e4/colorama-0.4.6.tar.gz", hash = "sha256:08695f5cb7ed6e0531a20572697297273c47b8cae5a63ffc6d6ed5c201be6e44", size = 27697 } 54 | wheels = [ 55 | { url = "https://files.pythonhosted.org/packages/d1/d6/3965ed04c63042e047cb6a3e6ed1a63a35087b6a609aa3a15ed8ac56c221/colorama-0.4.6-py2.py3-none-any.whl", hash = "sha256:4f1d9991f5acc0ca119f9d443620b77f9d6b33703e51011c16baf57afb285fc6", size = 25335 }, 56 | ] 57 | 58 | [[package]] 59 | name = "compiler-explorer-mcp" 60 | version = "0.1.1" 61 | source = { editable = "." } 62 | dependencies = [ 63 | { name = "fastapi" }, 64 | { name = "httpx" }, 65 | { name = "mcp", extra = ["cli"] }, 66 | { name = "pydantic" }, 67 | { name = "python-dotenv" }, 68 | { name = "uvicorn" }, 69 | { name = "websockets" }, 70 | ] 71 | 72 | [package.dev-dependencies] 73 | dev = [ 74 | { name = "pyright" }, 75 | { name = "pytest" }, 76 | { name = "ruff" }, 77 | ] 78 | 79 | [package.metadata] 80 | requires-dist = [ 81 | { name = "fastapi", specifier = ">=0.115.11" }, 82 | { name = "httpx", specifier = ">=0.28.1" }, 83 | { name = "mcp", extras = ["cli"], specifier = ">=1.5.0" }, 84 | { name = "pydantic", specifier = ">=2.10.6" }, 85 | { name = "python-dotenv", specifier = ">=1.0.1" }, 86 | { name = "uvicorn", specifier = ">=0.34.0" }, 87 | { name = "websockets", specifier = ">=15.0.1" }, 88 | ] 89 | 90 | [package.metadata.requires-dev] 91 | dev = [ 92 | { name = "pyright", specifier = ">=1.1.397" }, 93 | { name = "pytest", specifier = ">=8.3.5" }, 94 | { name = "ruff", specifier = ">=0.11.2" }, 95 | ] 96 | 97 | [[package]] 98 | name = "fastapi" 99 | version = "0.115.11" 100 | source = { registry = "https://pypi.org/simple" } 101 | dependencies = [ 102 | { name = "pydantic" }, 103 | { name = "starlette" }, 104 | { name = "typing-extensions" }, 105 | ] 106 | sdist = { url = "https://files.pythonhosted.org/packages/b5/28/c5d26e5860df807241909a961a37d45e10533acef95fc368066c7dd186cd/fastapi-0.115.11.tar.gz", hash = "sha256:cc81f03f688678b92600a65a5e618b93592c65005db37157147204d8924bf94f", size = 294441 } 107 | wheels = [ 108 | { url = "https://files.pythonhosted.org/packages/b3/5d/4d8bbb94f0dbc22732350c06965e40740f4a92ca560e90bb566f4f73af41/fastapi-0.115.11-py3-none-any.whl", hash = "sha256:32e1541b7b74602e4ef4a0260ecaf3aadf9d4f19590bba3e1bf2ac4666aa2c64", size = 94926 }, 109 | ] 110 | 111 | [[package]] 112 | name = "h11" 113 | version = "0.14.0" 114 | source = { registry = "https://pypi.org/simple" } 115 | sdist = { url = "https://files.pythonhosted.org/packages/f5/38/3af3d3633a34a3316095b39c8e8fb4853a28a536e55d347bd8d8e9a14b03/h11-0.14.0.tar.gz", hash = "sha256:8f19fbbe99e72420ff35c00b27a34cb9937e902a8b810e2c88300c6f0a3b699d", size = 100418 } 116 | wheels = [ 117 | { url = "https://files.pythonhosted.org/packages/95/04/ff642e65ad6b90db43e668d70ffb6736436c7ce41fcc549f4e9472234127/h11-0.14.0-py3-none-any.whl", hash = "sha256:e3fe4ac4b851c468cc8363d500db52c2ead036020723024a109d37346efaa761", size = 58259 }, 118 | ] 119 | 120 | [[package]] 121 | name = "httpcore" 122 | version = "1.0.7" 123 | source = { registry = "https://pypi.org/simple" } 124 | dependencies = [ 125 | { name = "certifi" }, 126 | { name = "h11" }, 127 | ] 128 | sdist = { url = "https://files.pythonhosted.org/packages/6a/41/d7d0a89eb493922c37d343b607bc1b5da7f5be7e383740b4753ad8943e90/httpcore-1.0.7.tar.gz", hash = "sha256:8551cb62a169ec7162ac7be8d4817d561f60e08eaa485234898414bb5a8a0b4c", size = 85196 } 129 | wheels = [ 130 | { url = "https://files.pythonhosted.org/packages/87/f5/72347bc88306acb359581ac4d52f23c0ef445b57157adedb9aee0cd689d2/httpcore-1.0.7-py3-none-any.whl", hash = "sha256:a3fff8f43dc260d5bd363d9f9cf1830fa3a458b332856f34282de498ed420edd", size = 78551 }, 131 | ] 132 | 133 | [[package]] 134 | name = "httpx" 135 | version = "0.28.1" 136 | source = { registry = "https://pypi.org/simple" } 137 | dependencies = [ 138 | { name = "anyio" }, 139 | { name = "certifi" }, 140 | { name = "httpcore" }, 141 | { name = "idna" }, 142 | ] 143 | sdist = { url = "https://files.pythonhosted.org/packages/b1/df/48c586a5fe32a0f01324ee087459e112ebb7224f646c0b5023f5e79e9956/httpx-0.28.1.tar.gz", hash = "sha256:75e98c5f16b0f35b567856f597f06ff2270a374470a5c2392242528e3e3e42fc", size = 141406 } 144 | wheels = [ 145 | { url = "https://files.pythonhosted.org/packages/2a/39/e50c7c3a983047577ee07d2a9e53faf5a69493943ec3f6a384bdc792deb2/httpx-0.28.1-py3-none-any.whl", hash = "sha256:d909fcccc110f8c7faf814ca82a9a4d816bc5a6dbfea25d6591d6985b8ba59ad", size = 73517 }, 146 | ] 147 | 148 | [[package]] 149 | name = "httpx-sse" 150 | version = "0.4.0" 151 | source = { registry = "https://pypi.org/simple" } 152 | sdist = { url = "https://files.pythonhosted.org/packages/4c/60/8f4281fa9bbf3c8034fd54c0e7412e66edbab6bc74c4996bd616f8d0406e/httpx-sse-0.4.0.tar.gz", hash = "sha256:1e81a3a3070ce322add1d3529ed42eb5f70817f45ed6ec915ab753f961139721", size = 12624 } 153 | wheels = [ 154 | { url = "https://files.pythonhosted.org/packages/e1/9b/a181f281f65d776426002f330c31849b86b31fc9d848db62e16f03ff739f/httpx_sse-0.4.0-py3-none-any.whl", hash = "sha256:f329af6eae57eaa2bdfd962b42524764af68075ea87370a2de920af5341e318f", size = 7819 }, 155 | ] 156 | 157 | [[package]] 158 | name = "idna" 159 | version = "3.10" 160 | source = { registry = "https://pypi.org/simple" } 161 | sdist = { url = "https://files.pythonhosted.org/packages/f1/70/7703c29685631f5a7590aa73f1f1d3fa9a380e654b86af429e0934a32f7d/idna-3.10.tar.gz", hash = "sha256:12f65c9b470abda6dc35cf8e63cc574b1c52b11df2c86030af0ac09b01b13ea9", size = 190490 } 162 | wheels = [ 163 | { url = "https://files.pythonhosted.org/packages/76/c6/c88e154df9c4e1a2a66ccf0005a88dfb2650c1dffb6f5ce603dfbd452ce3/idna-3.10-py3-none-any.whl", hash = "sha256:946d195a0d259cbba61165e88e65941f16e9b36ea6ddb97f00452bae8b1287d3", size = 70442 }, 164 | ] 165 | 166 | [[package]] 167 | name = "iniconfig" 168 | version = "2.1.0" 169 | source = { registry = "https://pypi.org/simple" } 170 | sdist = { url = "https://files.pythonhosted.org/packages/f2/97/ebf4da567aa6827c909642694d71c9fcf53e5b504f2d96afea02718862f3/iniconfig-2.1.0.tar.gz", hash = "sha256:3abbd2e30b36733fee78f9c7f7308f2d0050e88f0087fd25c2645f63c773e1c7", size = 4793 } 171 | wheels = [ 172 | { url = "https://files.pythonhosted.org/packages/2c/e1/e6716421ea10d38022b952c159d5161ca1193197fb744506875fbb87ea7b/iniconfig-2.1.0-py3-none-any.whl", hash = "sha256:9deba5723312380e77435581c6bf4935c94cbfab9b1ed33ef8d238ea168eb760", size = 6050 }, 173 | ] 174 | 175 | [[package]] 176 | name = "markdown-it-py" 177 | version = "3.0.0" 178 | source = { registry = "https://pypi.org/simple" } 179 | dependencies = [ 180 | { name = "mdurl" }, 181 | ] 182 | sdist = { url = "https://files.pythonhosted.org/packages/38/71/3b932df36c1a044d397a1f92d1cf91ee0a503d91e470cbd670aa66b07ed0/markdown-it-py-3.0.0.tar.gz", hash = "sha256:e3f60a94fa066dc52ec76661e37c851cb232d92f9886b15cb560aaada2df8feb", size = 74596 } 183 | wheels = [ 184 | { url = "https://files.pythonhosted.org/packages/42/d7/1ec15b46af6af88f19b8e5ffea08fa375d433c998b8a7639e76935c14f1f/markdown_it_py-3.0.0-py3-none-any.whl", hash = "sha256:355216845c60bd96232cd8d8c40e8f9765cc86f46880e43a8fd22dc1a1a8cab1", size = 87528 }, 185 | ] 186 | 187 | [[package]] 188 | name = "mcp" 189 | version = "1.5.0" 190 | source = { registry = "https://pypi.org/simple" } 191 | dependencies = [ 192 | { name = "anyio" }, 193 | { name = "httpx" }, 194 | { name = "httpx-sse" }, 195 | { name = "pydantic" }, 196 | { name = "pydantic-settings" }, 197 | { name = "sse-starlette" }, 198 | { name = "starlette" }, 199 | { name = "uvicorn" }, 200 | ] 201 | sdist = { url = "https://files.pythonhosted.org/packages/6d/c9/c55764824e893fdebe777ac7223200986a275c3191dba9169f8eb6d7c978/mcp-1.5.0.tar.gz", hash = "sha256:5b2766c05e68e01a2034875e250139839498c61792163a7b221fc170c12f5aa9", size = 159128 } 202 | wheels = [ 203 | { url = "https://files.pythonhosted.org/packages/c1/d1/3ff566ecf322077d861f1a68a1ff025cad337417bd66ad22a7c6f7dfcfaf/mcp-1.5.0-py3-none-any.whl", hash = "sha256:51c3f35ce93cb702f7513c12406bbea9665ef75a08db909200b07da9db641527", size = 73734 }, 204 | ] 205 | 206 | [package.optional-dependencies] 207 | cli = [ 208 | { name = "python-dotenv" }, 209 | { name = "typer" }, 210 | ] 211 | 212 | [[package]] 213 | name = "mdurl" 214 | version = "0.1.2" 215 | source = { registry = "https://pypi.org/simple" } 216 | sdist = { url = "https://files.pythonhosted.org/packages/d6/54/cfe61301667036ec958cb99bd3efefba235e65cdeb9c84d24a8293ba1d90/mdurl-0.1.2.tar.gz", hash = "sha256:bb413d29f5eea38f31dd4754dd7377d4465116fb207585f97bf925588687c1ba", size = 8729 } 217 | wheels = [ 218 | { url = "https://files.pythonhosted.org/packages/b3/38/89ba8ad64ae25be8de66a6d463314cf1eb366222074cfda9ee839c56a4b4/mdurl-0.1.2-py3-none-any.whl", hash = "sha256:84008a41e51615a49fc9966191ff91509e3c40b939176e643fd50a5c2196b8f8", size = 9979 }, 219 | ] 220 | 221 | [[package]] 222 | name = "nodeenv" 223 | version = "1.9.1" 224 | source = { registry = "https://pypi.org/simple" } 225 | sdist = { url = "https://files.pythonhosted.org/packages/43/16/fc88b08840de0e0a72a2f9d8c6bae36be573e475a6326ae854bcc549fc45/nodeenv-1.9.1.tar.gz", hash = "sha256:6ec12890a2dab7946721edbfbcd91f3319c6ccc9aec47be7c7e6b7011ee6645f", size = 47437 } 226 | wheels = [ 227 | { url = "https://files.pythonhosted.org/packages/d2/1d/1b658dbd2b9fa9c4c9f32accbfc0205d532c8c6194dc0f2a4c0428e7128a/nodeenv-1.9.1-py2.py3-none-any.whl", hash = "sha256:ba11c9782d29c27c70ffbdda2d7415098754709be8a7056d79a737cd901155c9", size = 22314 }, 228 | ] 229 | 230 | [[package]] 231 | name = "packaging" 232 | version = "24.2" 233 | source = { registry = "https://pypi.org/simple" } 234 | sdist = { url = "https://files.pythonhosted.org/packages/d0/63/68dbb6eb2de9cb10ee4c9c14a0148804425e13c4fb20d61cce69f53106da/packaging-24.2.tar.gz", hash = "sha256:c228a6dc5e932d346bc5739379109d49e8853dd8223571c7c5b55260edc0b97f", size = 163950 } 235 | wheels = [ 236 | { url = "https://files.pythonhosted.org/packages/88/ef/eb23f262cca3c0c4eb7ab1933c3b1f03d021f2c48f54763065b6f0e321be/packaging-24.2-py3-none-any.whl", hash = "sha256:09abb1bccd265c01f4a3aa3f7a7db064b36514d2cba19a2f694fe6150451a759", size = 65451 }, 237 | ] 238 | 239 | [[package]] 240 | name = "pluggy" 241 | version = "1.5.0" 242 | source = { registry = "https://pypi.org/simple" } 243 | sdist = { url = "https://files.pythonhosted.org/packages/96/2d/02d4312c973c6050a18b314a5ad0b3210edb65a906f868e31c111dede4a6/pluggy-1.5.0.tar.gz", hash = "sha256:2cffa88e94fdc978c4c574f15f9e59b7f4201d439195c3715ca9e2486f1d0cf1", size = 67955 } 244 | wheels = [ 245 | { url = "https://files.pythonhosted.org/packages/88/5f/e351af9a41f866ac3f1fac4ca0613908d9a41741cfcf2228f4ad853b697d/pluggy-1.5.0-py3-none-any.whl", hash = "sha256:44e1ad92c8ca002de6377e165f3e0f1be63266ab4d554740532335b9d75ea669", size = 20556 }, 246 | ] 247 | 248 | [[package]] 249 | name = "pydantic" 250 | version = "2.10.6" 251 | source = { registry = "https://pypi.org/simple" } 252 | dependencies = [ 253 | { name = "annotated-types" }, 254 | { name = "pydantic-core" }, 255 | { name = "typing-extensions" }, 256 | ] 257 | sdist = { url = "https://files.pythonhosted.org/packages/b7/ae/d5220c5c52b158b1de7ca89fc5edb72f304a70a4c540c84c8844bf4008de/pydantic-2.10.6.tar.gz", hash = "sha256:ca5daa827cce33de7a42be142548b0096bf05a7e7b365aebfa5f8eeec7128236", size = 761681 } 258 | wheels = [ 259 | { url = "https://files.pythonhosted.org/packages/f4/3c/8cc1cc84deffa6e25d2d0c688ebb80635dfdbf1dbea3e30c541c8cf4d860/pydantic-2.10.6-py3-none-any.whl", hash = "sha256:427d664bf0b8a2b34ff5dd0f5a18df00591adcee7198fbd71981054cef37b584", size = 431696 }, 260 | ] 261 | 262 | [[package]] 263 | name = "pydantic-core" 264 | version = "2.27.2" 265 | source = { registry = "https://pypi.org/simple" } 266 | dependencies = [ 267 | { name = "typing-extensions" }, 268 | ] 269 | sdist = { url = "https://files.pythonhosted.org/packages/fc/01/f3e5ac5e7c25833db5eb555f7b7ab24cd6f8c322d3a3ad2d67a952dc0abc/pydantic_core-2.27.2.tar.gz", hash = "sha256:eb026e5a4c1fee05726072337ff51d1efb6f59090b7da90d30ea58625b1ffb39", size = 413443 } 270 | wheels = [ 271 | { url = "https://files.pythonhosted.org/packages/d6/74/51c8a5482ca447871c93e142d9d4a92ead74de6c8dc5e66733e22c9bba89/pydantic_core-2.27.2-cp312-cp312-macosx_10_12_x86_64.whl", hash = "sha256:9e0c8cfefa0ef83b4da9588448b6d8d2a2bf1a53c3f1ae5fca39eb3061e2f0b0", size = 1893127 }, 272 | { url = "https://files.pythonhosted.org/packages/d3/f3/c97e80721735868313c58b89d2de85fa80fe8dfeeed84dc51598b92a135e/pydantic_core-2.27.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:83097677b8e3bd7eaa6775720ec8e0405f1575015a463285a92bfdfe254529ef", size = 1811340 }, 273 | { url = "https://files.pythonhosted.org/packages/9e/91/840ec1375e686dbae1bd80a9e46c26a1e0083e1186abc610efa3d9a36180/pydantic_core-2.27.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:172fce187655fece0c90d90a678424b013f8fbb0ca8b036ac266749c09438cb7", size = 1822900 }, 274 | { url = "https://files.pythonhosted.org/packages/f6/31/4240bc96025035500c18adc149aa6ffdf1a0062a4b525c932065ceb4d868/pydantic_core-2.27.2-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:519f29f5213271eeeeb3093f662ba2fd512b91c5f188f3bb7b27bc5973816934", size = 1869177 }, 275 | { url = "https://files.pythonhosted.org/packages/fa/20/02fbaadb7808be578317015c462655c317a77a7c8f0ef274bc016a784c54/pydantic_core-2.27.2-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:05e3a55d124407fffba0dd6b0c0cd056d10e983ceb4e5dbd10dda135c31071d6", size = 2038046 }, 276 | { url = "https://files.pythonhosted.org/packages/06/86/7f306b904e6c9eccf0668248b3f272090e49c275bc488a7b88b0823444a4/pydantic_core-2.27.2-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:9c3ed807c7b91de05e63930188f19e921d1fe90de6b4f5cd43ee7fcc3525cb8c", size = 2685386 }, 277 | { url = "https://files.pythonhosted.org/packages/8d/f0/49129b27c43396581a635d8710dae54a791b17dfc50c70164866bbf865e3/pydantic_core-2.27.2-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6fb4aadc0b9a0c063206846d603b92030eb6f03069151a625667f982887153e2", size = 1997060 }, 278 | { url = "https://files.pythonhosted.org/packages/0d/0f/943b4af7cd416c477fd40b187036c4f89b416a33d3cc0ab7b82708a667aa/pydantic_core-2.27.2-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:28ccb213807e037460326424ceb8b5245acb88f32f3d2777427476e1b32c48c4", size = 2004870 }, 279 | { url = "https://files.pythonhosted.org/packages/35/40/aea70b5b1a63911c53a4c8117c0a828d6790483f858041f47bab0b779f44/pydantic_core-2.27.2-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:de3cd1899e2c279b140adde9357c4495ed9d47131b4a4eaff9052f23398076b3", size = 1999822 }, 280 | { url = "https://files.pythonhosted.org/packages/f2/b3/807b94fd337d58effc5498fd1a7a4d9d59af4133e83e32ae39a96fddec9d/pydantic_core-2.27.2-cp312-cp312-musllinux_1_1_armv7l.whl", hash = "sha256:220f892729375e2d736b97d0e51466252ad84c51857d4d15f5e9692f9ef12be4", size = 2130364 }, 281 | { url = "https://files.pythonhosted.org/packages/fc/df/791c827cd4ee6efd59248dca9369fb35e80a9484462c33c6649a8d02b565/pydantic_core-2.27.2-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:a0fcd29cd6b4e74fe8ddd2c90330fd8edf2e30cb52acda47f06dd615ae72da57", size = 2158303 }, 282 | { url = "https://files.pythonhosted.org/packages/9b/67/4e197c300976af185b7cef4c02203e175fb127e414125916bf1128b639a9/pydantic_core-2.27.2-cp312-cp312-win32.whl", hash = "sha256:1e2cb691ed9834cd6a8be61228471d0a503731abfb42f82458ff27be7b2186fc", size = 1834064 }, 283 | { url = "https://files.pythonhosted.org/packages/1f/ea/cd7209a889163b8dcca139fe32b9687dd05249161a3edda62860430457a5/pydantic_core-2.27.2-cp312-cp312-win_amd64.whl", hash = "sha256:cc3f1a99a4f4f9dd1de4fe0312c114e740b5ddead65bb4102884b384c15d8bc9", size = 1989046 }, 284 | { url = "https://files.pythonhosted.org/packages/bc/49/c54baab2f4658c26ac633d798dab66b4c3a9bbf47cff5284e9c182f4137a/pydantic_core-2.27.2-cp312-cp312-win_arm64.whl", hash = "sha256:3911ac9284cd8a1792d3cb26a2da18f3ca26c6908cc434a18f730dc0db7bfa3b", size = 1885092 }, 285 | { url = "https://files.pythonhosted.org/packages/41/b1/9bc383f48f8002f99104e3acff6cba1231b29ef76cfa45d1506a5cad1f84/pydantic_core-2.27.2-cp313-cp313-macosx_10_12_x86_64.whl", hash = "sha256:7d14bd329640e63852364c306f4d23eb744e0f8193148d4044dd3dacdaacbd8b", size = 1892709 }, 286 | { url = "https://files.pythonhosted.org/packages/10/6c/e62b8657b834f3eb2961b49ec8e301eb99946245e70bf42c8817350cbefc/pydantic_core-2.27.2-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:82f91663004eb8ed30ff478d77c4d1179b3563df6cdb15c0817cd1cdaf34d154", size = 1811273 }, 287 | { url = "https://files.pythonhosted.org/packages/ba/15/52cfe49c8c986e081b863b102d6b859d9defc63446b642ccbbb3742bf371/pydantic_core-2.27.2-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:71b24c7d61131bb83df10cc7e687433609963a944ccf45190cfc21e0887b08c9", size = 1823027 }, 288 | { url = "https://files.pythonhosted.org/packages/b1/1c/b6f402cfc18ec0024120602bdbcebc7bdd5b856528c013bd4d13865ca473/pydantic_core-2.27.2-cp313-cp313-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:fa8e459d4954f608fa26116118bb67f56b93b209c39b008277ace29937453dc9", size = 1868888 }, 289 | { url = "https://files.pythonhosted.org/packages/bd/7b/8cb75b66ac37bc2975a3b7de99f3c6f355fcc4d89820b61dffa8f1e81677/pydantic_core-2.27.2-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ce8918cbebc8da707ba805b7fd0b382816858728ae7fe19a942080c24e5b7cd1", size = 2037738 }, 290 | { url = "https://files.pythonhosted.org/packages/c8/f1/786d8fe78970a06f61df22cba58e365ce304bf9b9f46cc71c8c424e0c334/pydantic_core-2.27.2-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:eda3f5c2a021bbc5d976107bb302e0131351c2ba54343f8a496dc8783d3d3a6a", size = 2685138 }, 291 | { url = "https://files.pythonhosted.org/packages/a6/74/d12b2cd841d8724dc8ffb13fc5cef86566a53ed358103150209ecd5d1999/pydantic_core-2.27.2-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bd8086fa684c4775c27f03f062cbb9eaa6e17f064307e86b21b9e0abc9c0f02e", size = 1997025 }, 292 | { url = "https://files.pythonhosted.org/packages/a0/6e/940bcd631bc4d9a06c9539b51f070b66e8f370ed0933f392db6ff350d873/pydantic_core-2.27.2-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:8d9b3388db186ba0c099a6d20f0604a44eabdeef1777ddd94786cdae158729e4", size = 2004633 }, 293 | { url = "https://files.pythonhosted.org/packages/50/cc/a46b34f1708d82498c227d5d80ce615b2dd502ddcfd8376fc14a36655af1/pydantic_core-2.27.2-cp313-cp313-musllinux_1_1_aarch64.whl", hash = "sha256:7a66efda2387de898c8f38c0cf7f14fca0b51a8ef0b24bfea5849f1b3c95af27", size = 1999404 }, 294 | { url = "https://files.pythonhosted.org/packages/ca/2d/c365cfa930ed23bc58c41463bae347d1005537dc8db79e998af8ba28d35e/pydantic_core-2.27.2-cp313-cp313-musllinux_1_1_armv7l.whl", hash = "sha256:18a101c168e4e092ab40dbc2503bdc0f62010e95d292b27827871dc85450d7ee", size = 2130130 }, 295 | { url = "https://files.pythonhosted.org/packages/f4/d7/eb64d015c350b7cdb371145b54d96c919d4db516817f31cd1c650cae3b21/pydantic_core-2.27.2-cp313-cp313-musllinux_1_1_x86_64.whl", hash = "sha256:ba5dd002f88b78a4215ed2f8ddbdf85e8513382820ba15ad5ad8955ce0ca19a1", size = 2157946 }, 296 | { url = "https://files.pythonhosted.org/packages/a4/99/bddde3ddde76c03b65dfd5a66ab436c4e58ffc42927d4ff1198ffbf96f5f/pydantic_core-2.27.2-cp313-cp313-win32.whl", hash = "sha256:1ebaf1d0481914d004a573394f4be3a7616334be70261007e47c2a6fe7e50130", size = 1834387 }, 297 | { url = "https://files.pythonhosted.org/packages/71/47/82b5e846e01b26ac6f1893d3c5f9f3a2eb6ba79be26eef0b759b4fe72946/pydantic_core-2.27.2-cp313-cp313-win_amd64.whl", hash = "sha256:953101387ecf2f5652883208769a79e48db18c6df442568a0b5ccd8c2723abee", size = 1990453 }, 298 | { url = "https://files.pythonhosted.org/packages/51/b2/b2b50d5ecf21acf870190ae5d093602d95f66c9c31f9d5de6062eb329ad1/pydantic_core-2.27.2-cp313-cp313-win_arm64.whl", hash = "sha256:ac4dbfd1691affb8f48c2c13241a2e3b60ff23247cbcf981759c768b6633cf8b", size = 1885186 }, 299 | ] 300 | 301 | [[package]] 302 | name = "pydantic-settings" 303 | version = "2.8.1" 304 | source = { registry = "https://pypi.org/simple" } 305 | dependencies = [ 306 | { name = "pydantic" }, 307 | { name = "python-dotenv" }, 308 | ] 309 | sdist = { url = "https://files.pythonhosted.org/packages/88/82/c79424d7d8c29b994fb01d277da57b0a9b09cc03c3ff875f9bd8a86b2145/pydantic_settings-2.8.1.tar.gz", hash = "sha256:d5c663dfbe9db9d5e1c646b2e161da12f0d734d422ee56f567d0ea2cee4e8585", size = 83550 } 310 | wheels = [ 311 | { url = "https://files.pythonhosted.org/packages/0b/53/a64f03044927dc47aafe029c42a5b7aabc38dfb813475e0e1bf71c4a59d0/pydantic_settings-2.8.1-py3-none-any.whl", hash = "sha256:81942d5ac3d905f7f3ee1a70df5dfb62d5569c12f51a5a647defc1c3d9ee2e9c", size = 30839 }, 312 | ] 313 | 314 | [[package]] 315 | name = "pygments" 316 | version = "2.19.1" 317 | source = { registry = "https://pypi.org/simple" } 318 | sdist = { url = "https://files.pythonhosted.org/packages/7c/2d/c3338d48ea6cc0feb8446d8e6937e1408088a72a39937982cc6111d17f84/pygments-2.19.1.tar.gz", hash = "sha256:61c16d2a8576dc0649d9f39e089b5f02bcd27fba10d8fb4dcc28173f7a45151f", size = 4968581 } 319 | wheels = [ 320 | { url = "https://files.pythonhosted.org/packages/8a/0b/9fcc47d19c48b59121088dd6da2488a49d5f72dacf8262e2790a1d2c7d15/pygments-2.19.1-py3-none-any.whl", hash = "sha256:9ea1544ad55cecf4b8242fab6dd35a93bbce657034b0611ee383099054ab6d8c", size = 1225293 }, 321 | ] 322 | 323 | [[package]] 324 | name = "pyright" 325 | version = "1.1.397" 326 | source = { registry = "https://pypi.org/simple" } 327 | dependencies = [ 328 | { name = "nodeenv" }, 329 | { name = "typing-extensions" }, 330 | ] 331 | sdist = { url = "https://files.pythonhosted.org/packages/92/23/cefa10c9cb198e0858ed0b9233371d62bca880337f628e58f50dfdfb12f0/pyright-1.1.397.tar.gz", hash = "sha256:07530fd65a449e4b0b28dceef14be0d8e0995a7a5b1bb2f3f897c3e548451ce3", size = 3818998 } 332 | wheels = [ 333 | { url = "https://files.pythonhosted.org/packages/01/b5/98ec41e1e0ad5576ecd42c90ec363560f7b389a441722ea3c7207682dec7/pyright-1.1.397-py3-none-any.whl", hash = "sha256:2e93fba776e714a82b085d68f8345b01f91ba43e1ab9d513e79b70fc85906257", size = 5693631 }, 334 | ] 335 | 336 | [[package]] 337 | name = "pytest" 338 | version = "8.3.5" 339 | source = { registry = "https://pypi.org/simple" } 340 | dependencies = [ 341 | { name = "colorama", marker = "sys_platform == 'win32'" }, 342 | { name = "iniconfig" }, 343 | { name = "packaging" }, 344 | { name = "pluggy" }, 345 | ] 346 | sdist = { url = "https://files.pythonhosted.org/packages/ae/3c/c9d525a414d506893f0cd8a8d0de7706446213181570cdbd766691164e40/pytest-8.3.5.tar.gz", hash = "sha256:f4efe70cc14e511565ac476b57c279e12a855b11f48f212af1080ef2263d3845", size = 1450891 } 347 | wheels = [ 348 | { url = "https://files.pythonhosted.org/packages/30/3d/64ad57c803f1fa1e963a7946b6e0fea4a70df53c1a7fed304586539c2bac/pytest-8.3.5-py3-none-any.whl", hash = "sha256:c69214aa47deac29fad6c2a4f590b9c4a9fdb16a403176fe154b79c0b4d4d820", size = 343634 }, 349 | ] 350 | 351 | [[package]] 352 | name = "python-dotenv" 353 | version = "1.0.1" 354 | source = { registry = "https://pypi.org/simple" } 355 | sdist = { url = "https://files.pythonhosted.org/packages/bc/57/e84d88dfe0aec03b7a2d4327012c1627ab5f03652216c63d49846d7a6c58/python-dotenv-1.0.1.tar.gz", hash = "sha256:e324ee90a023d808f1959c46bcbc04446a10ced277783dc6ee09987c37ec10ca", size = 39115 } 356 | wheels = [ 357 | { url = "https://files.pythonhosted.org/packages/6a/3e/b68c118422ec867fa7ab88444e1274aa40681c606d59ac27de5a5588f082/python_dotenv-1.0.1-py3-none-any.whl", hash = "sha256:f7b63ef50f1b690dddf550d03497b66d609393b40b564ed0d674909a68ebf16a", size = 19863 }, 358 | ] 359 | 360 | [[package]] 361 | name = "rich" 362 | version = "13.9.4" 363 | source = { registry = "https://pypi.org/simple" } 364 | dependencies = [ 365 | { name = "markdown-it-py" }, 366 | { name = "pygments" }, 367 | ] 368 | sdist = { url = "https://files.pythonhosted.org/packages/ab/3a/0316b28d0761c6734d6bc14e770d85506c986c85ffb239e688eeaab2c2bc/rich-13.9.4.tar.gz", hash = "sha256:439594978a49a09530cff7ebc4b5c7103ef57baf48d5ea3184f21d9a2befa098", size = 223149 } 369 | wheels = [ 370 | { url = "https://files.pythonhosted.org/packages/19/71/39c7c0d87f8d4e6c020a393182060eaefeeae6c01dab6a84ec346f2567df/rich-13.9.4-py3-none-any.whl", hash = "sha256:6049d5e6ec054bf2779ab3358186963bac2ea89175919d699e378b99738c2a90", size = 242424 }, 371 | ] 372 | 373 | [[package]] 374 | name = "ruff" 375 | version = "0.11.2" 376 | source = { registry = "https://pypi.org/simple" } 377 | sdist = { url = "https://files.pythonhosted.org/packages/90/61/fb87430f040e4e577e784e325351186976516faef17d6fcd921fe28edfd7/ruff-0.11.2.tar.gz", hash = "sha256:ec47591497d5a1050175bdf4e1a4e6272cddff7da88a2ad595e1e326041d8d94", size = 3857511 } 378 | wheels = [ 379 | { url = "https://files.pythonhosted.org/packages/62/99/102578506f0f5fa29fd7e0df0a273864f79af044757aef73d1cae0afe6ad/ruff-0.11.2-py3-none-linux_armv6l.whl", hash = "sha256:c69e20ea49e973f3afec2c06376eb56045709f0212615c1adb0eda35e8a4e477", size = 10113146 }, 380 | { url = "https://files.pythonhosted.org/packages/74/ad/5cd4ba58ab602a579997a8494b96f10f316e874d7c435bcc1a92e6da1b12/ruff-0.11.2-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:2c5424cc1c4eb1d8ecabe6d4f1b70470b4f24a0c0171356290b1953ad8f0e272", size = 10867092 }, 381 | { url = "https://files.pythonhosted.org/packages/fc/3e/d3f13619e1d152c7b600a38c1a035e833e794c6625c9a6cea6f63dbf3af4/ruff-0.11.2-py3-none-macosx_11_0_arm64.whl", hash = "sha256:ecf20854cc73f42171eedb66f006a43d0a21bfb98a2523a809931cda569552d9", size = 10224082 }, 382 | { url = "https://files.pythonhosted.org/packages/90/06/f77b3d790d24a93f38e3806216f263974909888fd1e826717c3ec956bbcd/ruff-0.11.2-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0c543bf65d5d27240321604cee0633a70c6c25c9a2f2492efa9f6d4b8e4199bb", size = 10394818 }, 383 | { url = "https://files.pythonhosted.org/packages/99/7f/78aa431d3ddebfc2418cd95b786642557ba8b3cb578c075239da9ce97ff9/ruff-0.11.2-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:20967168cc21195db5830b9224be0e964cc9c8ecf3b5a9e3ce19876e8d3a96e3", size = 9952251 }, 384 | { url = "https://files.pythonhosted.org/packages/30/3e/f11186d1ddfaca438c3bbff73c6a2fdb5b60e6450cc466129c694b0ab7a2/ruff-0.11.2-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:955a9ce63483999d9f0b8f0b4a3ad669e53484232853054cc8b9d51ab4c5de74", size = 11563566 }, 385 | { url = "https://files.pythonhosted.org/packages/22/6c/6ca91befbc0a6539ee133d9a9ce60b1a354db12c3c5d11cfdbf77140f851/ruff-0.11.2-py3-none-manylinux_2_17_ppc64.manylinux2014_ppc64.whl", hash = "sha256:86b3a27c38b8fce73bcd262b0de32e9a6801b76d52cdb3ae4c914515f0cef608", size = 12208721 }, 386 | { url = "https://files.pythonhosted.org/packages/19/b0/24516a3b850d55b17c03fc399b681c6a549d06ce665915721dc5d6458a5c/ruff-0.11.2-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:a3b66a03b248c9fcd9d64d445bafdf1589326bee6fc5c8e92d7562e58883e30f", size = 11662274 }, 387 | { url = "https://files.pythonhosted.org/packages/d7/65/76be06d28ecb7c6070280cef2bcb20c98fbf99ff60b1c57d2fb9b8771348/ruff-0.11.2-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:0397c2672db015be5aa3d4dac54c69aa012429097ff219392c018e21f5085147", size = 13792284 }, 388 | { url = "https://files.pythonhosted.org/packages/ce/d2/4ceed7147e05852876f3b5f3fdc23f878ce2b7e0b90dd6e698bda3d20787/ruff-0.11.2-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:869bcf3f9abf6457fbe39b5a37333aa4eecc52a3b99c98827ccc371a8e5b6f1b", size = 11327861 }, 389 | { url = "https://files.pythonhosted.org/packages/c4/78/4935ecba13706fd60ebe0e3dc50371f2bdc3d9bc80e68adc32ff93914534/ruff-0.11.2-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:2a2b50ca35457ba785cd8c93ebbe529467594087b527a08d487cf0ee7b3087e9", size = 10276560 }, 390 | { url = "https://files.pythonhosted.org/packages/81/7f/1b2435c3f5245d410bb5dc80f13ec796454c21fbda12b77d7588d5cf4e29/ruff-0.11.2-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:7c69c74bf53ddcfbc22e6eb2f31211df7f65054bfc1f72288fc71e5f82db3eab", size = 9945091 }, 391 | { url = "https://files.pythonhosted.org/packages/39/c4/692284c07e6bf2b31d82bb8c32f8840f9d0627d92983edaac991a2b66c0a/ruff-0.11.2-py3-none-musllinux_1_2_i686.whl", hash = "sha256:6e8fb75e14560f7cf53b15bbc55baf5ecbe373dd5f3aab96ff7aa7777edd7630", size = 10977133 }, 392 | { url = "https://files.pythonhosted.org/packages/94/cf/8ab81cb7dd7a3b0a3960c2769825038f3adcd75faf46dd6376086df8b128/ruff-0.11.2-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:842a472d7b4d6f5924e9297aa38149e5dcb1e628773b70e6387ae2c97a63c58f", size = 11378514 }, 393 | { url = "https://files.pythonhosted.org/packages/d9/3a/a647fa4f316482dacf2fd68e8a386327a33d6eabd8eb2f9a0c3d291ec549/ruff-0.11.2-py3-none-win32.whl", hash = "sha256:aca01ccd0eb5eb7156b324cfaa088586f06a86d9e5314b0eb330cb48415097cc", size = 10319835 }, 394 | { url = "https://files.pythonhosted.org/packages/86/54/3c12d3af58012a5e2cd7ebdbe9983f4834af3f8cbea0e8a8c74fa1e23b2b/ruff-0.11.2-py3-none-win_amd64.whl", hash = "sha256:3170150172a8f994136c0c66f494edf199a0bbea7a409f649e4bc8f4d7084080", size = 11373713 }, 395 | { url = "https://files.pythonhosted.org/packages/d6/d4/dd813703af8a1e2ac33bf3feb27e8a5ad514c9f219df80c64d69807e7f71/ruff-0.11.2-py3-none-win_arm64.whl", hash = "sha256:52933095158ff328f4c77af3d74f0379e34fd52f175144cefc1b192e7ccd32b4", size = 10441990 }, 396 | ] 397 | 398 | [[package]] 399 | name = "shellingham" 400 | version = "1.5.4" 401 | source = { registry = "https://pypi.org/simple" } 402 | sdist = { url = "https://files.pythonhosted.org/packages/58/15/8b3609fd3830ef7b27b655beb4b4e9c62313a4e8da8c676e142cc210d58e/shellingham-1.5.4.tar.gz", hash = "sha256:8dbca0739d487e5bd35ab3ca4b36e11c4078f3a234bfce294b0a0291363404de", size = 10310 } 403 | wheels = [ 404 | { url = "https://files.pythonhosted.org/packages/e0/f9/0595336914c5619e5f28a1fb793285925a8cd4b432c9da0a987836c7f822/shellingham-1.5.4-py2.py3-none-any.whl", hash = "sha256:7ecfff8f2fd72616f7481040475a65b2bf8af90a56c89140852d1120324e8686", size = 9755 }, 405 | ] 406 | 407 | [[package]] 408 | name = "sniffio" 409 | version = "1.3.1" 410 | source = { registry = "https://pypi.org/simple" } 411 | sdist = { url = "https://files.pythonhosted.org/packages/a2/87/a6771e1546d97e7e041b6ae58d80074f81b7d5121207425c964ddf5cfdbd/sniffio-1.3.1.tar.gz", hash = "sha256:f4324edc670a0f49750a81b895f35c3adb843cca46f0530f79fc1babb23789dc", size = 20372 } 412 | wheels = [ 413 | { url = "https://files.pythonhosted.org/packages/e9/44/75a9c9421471a6c4805dbf2356f7c181a29c1879239abab1ea2cc8f38b40/sniffio-1.3.1-py3-none-any.whl", hash = "sha256:2f6da418d1f1e0fddd844478f41680e794e6051915791a034ff65e5f100525a2", size = 10235 }, 414 | ] 415 | 416 | [[package]] 417 | name = "sse-starlette" 418 | version = "2.2.1" 419 | source = { registry = "https://pypi.org/simple" } 420 | dependencies = [ 421 | { name = "anyio" }, 422 | { name = "starlette" }, 423 | ] 424 | sdist = { url = "https://files.pythonhosted.org/packages/71/a4/80d2a11af59fe75b48230846989e93979c892d3a20016b42bb44edb9e398/sse_starlette-2.2.1.tar.gz", hash = "sha256:54470d5f19274aeed6b2d473430b08b4b379ea851d953b11d7f1c4a2c118b419", size = 17376 } 425 | wheels = [ 426 | { url = "https://files.pythonhosted.org/packages/d9/e0/5b8bd393f27f4a62461c5cf2479c75a2cc2ffa330976f9f00f5f6e4f50eb/sse_starlette-2.2.1-py3-none-any.whl", hash = "sha256:6410a3d3ba0c89e7675d4c273a301d64649c03a5ef1ca101f10b47f895fd0e99", size = 10120 }, 427 | ] 428 | 429 | [[package]] 430 | name = "starlette" 431 | version = "0.46.1" 432 | source = { registry = "https://pypi.org/simple" } 433 | dependencies = [ 434 | { name = "anyio" }, 435 | ] 436 | sdist = { url = "https://files.pythonhosted.org/packages/04/1b/52b27f2e13ceedc79a908e29eac426a63465a1a01248e5f24aa36a62aeb3/starlette-0.46.1.tar.gz", hash = "sha256:3c88d58ee4bd1bb807c0d1acb381838afc7752f9ddaec81bbe4383611d833230", size = 2580102 } 437 | wheels = [ 438 | { url = "https://files.pythonhosted.org/packages/a0/4b/528ccf7a982216885a1ff4908e886b8fb5f19862d1962f56a3fce2435a70/starlette-0.46.1-py3-none-any.whl", hash = "sha256:77c74ed9d2720138b25875133f3a2dae6d854af2ec37dceb56aef370c1d8a227", size = 71995 }, 439 | ] 440 | 441 | [[package]] 442 | name = "typer" 443 | version = "0.15.2" 444 | source = { registry = "https://pypi.org/simple" } 445 | dependencies = [ 446 | { name = "click" }, 447 | { name = "rich" }, 448 | { name = "shellingham" }, 449 | { name = "typing-extensions" }, 450 | ] 451 | sdist = { url = "https://files.pythonhosted.org/packages/8b/6f/3991f0f1c7fcb2df31aef28e0594d8d54b05393a0e4e34c65e475c2a5d41/typer-0.15.2.tar.gz", hash = "sha256:ab2fab47533a813c49fe1f16b1a370fd5819099c00b119e0633df65f22144ba5", size = 100711 } 452 | wheels = [ 453 | { url = "https://files.pythonhosted.org/packages/7f/fc/5b29fea8cee020515ca82cc68e3b8e1e34bb19a3535ad854cac9257b414c/typer-0.15.2-py3-none-any.whl", hash = "sha256:46a499c6107d645a9c13f7ee46c5d5096cae6f5fc57dd11eccbbb9ae3e44ddfc", size = 45061 }, 454 | ] 455 | 456 | [[package]] 457 | name = "typing-extensions" 458 | version = "4.12.2" 459 | source = { registry = "https://pypi.org/simple" } 460 | sdist = { url = "https://files.pythonhosted.org/packages/df/db/f35a00659bc03fec321ba8bce9420de607a1d37f8342eee1863174c69557/typing_extensions-4.12.2.tar.gz", hash = "sha256:1a7ead55c7e559dd4dee8856e3a88b41225abfe1ce8df57b7c13915fe121ffb8", size = 85321 } 461 | wheels = [ 462 | { url = "https://files.pythonhosted.org/packages/26/9f/ad63fc0248c5379346306f8668cda6e2e2e9c95e01216d2b8ffd9ff037d0/typing_extensions-4.12.2-py3-none-any.whl", hash = "sha256:04e5ca0351e0f3f85c6853954072df659d0d13fac324d0072316b67d7794700d", size = 37438 }, 463 | ] 464 | 465 | [[package]] 466 | name = "uvicorn" 467 | version = "0.34.0" 468 | source = { registry = "https://pypi.org/simple" } 469 | dependencies = [ 470 | { name = "click" }, 471 | { name = "h11" }, 472 | ] 473 | sdist = { url = "https://files.pythonhosted.org/packages/4b/4d/938bd85e5bf2edeec766267a5015ad969730bb91e31b44021dfe8b22df6c/uvicorn-0.34.0.tar.gz", hash = "sha256:404051050cd7e905de2c9a7e61790943440b3416f49cb409f965d9dcd0fa73e9", size = 76568 } 474 | wheels = [ 475 | { url = "https://files.pythonhosted.org/packages/61/14/33a3a1352cfa71812a3a21e8c9bfb83f60b0011f5e36f2b1399d51928209/uvicorn-0.34.0-py3-none-any.whl", hash = "sha256:023dc038422502fa28a09c7a30bf2b6991512da7dcdb8fd35fe57cfc154126f4", size = 62315 }, 476 | ] 477 | 478 | [[package]] 479 | name = "websockets" 480 | version = "15.0.1" 481 | source = { registry = "https://pypi.org/simple" } 482 | sdist = { url = "https://files.pythonhosted.org/packages/21/e6/26d09fab466b7ca9c7737474c52be4f76a40301b08362eb2dbc19dcc16c1/websockets-15.0.1.tar.gz", hash = "sha256:82544de02076bafba038ce055ee6412d68da13ab47f0c60cab827346de828dee", size = 177016 } 483 | wheels = [ 484 | { url = "https://files.pythonhosted.org/packages/51/6b/4545a0d843594f5d0771e86463606a3988b5a09ca5123136f8a76580dd63/websockets-15.0.1-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:3e90baa811a5d73f3ca0bcbf32064d663ed81318ab225ee4f427ad4e26e5aff3", size = 175437 }, 485 | { url = "https://files.pythonhosted.org/packages/f4/71/809a0f5f6a06522af902e0f2ea2757f71ead94610010cf570ab5c98e99ed/websockets-15.0.1-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:592f1a9fe869c778694f0aa806ba0374e97648ab57936f092fd9d87f8bc03665", size = 173096 }, 486 | { url = "https://files.pythonhosted.org/packages/3d/69/1a681dd6f02180916f116894181eab8b2e25b31e484c5d0eae637ec01f7c/websockets-15.0.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:0701bc3cfcb9164d04a14b149fd74be7347a530ad3bbf15ab2c678a2cd3dd9a2", size = 173332 }, 487 | { url = "https://files.pythonhosted.org/packages/a6/02/0073b3952f5bce97eafbb35757f8d0d54812b6174ed8dd952aa08429bcc3/websockets-15.0.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e8b56bdcdb4505c8078cb6c7157d9811a85790f2f2b3632c7d1462ab5783d215", size = 183152 }, 488 | { url = "https://files.pythonhosted.org/packages/74/45/c205c8480eafd114b428284840da0b1be9ffd0e4f87338dc95dc6ff961a1/websockets-15.0.1-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:0af68c55afbd5f07986df82831c7bff04846928ea8d1fd7f30052638788bc9b5", size = 182096 }, 489 | { url = "https://files.pythonhosted.org/packages/14/8f/aa61f528fba38578ec553c145857a181384c72b98156f858ca5c8e82d9d3/websockets-15.0.1-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:64dee438fed052b52e4f98f76c5790513235efaa1ef7f3f2192c392cd7c91b65", size = 182523 }, 490 | { url = "https://files.pythonhosted.org/packages/ec/6d/0267396610add5bc0d0d3e77f546d4cd287200804fe02323797de77dbce9/websockets-15.0.1-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:d5f6b181bb38171a8ad1d6aa58a67a6aa9d4b38d0f8c5f496b9e42561dfc62fe", size = 182790 }, 491 | { url = "https://files.pythonhosted.org/packages/02/05/c68c5adbf679cf610ae2f74a9b871ae84564462955d991178f95a1ddb7dd/websockets-15.0.1-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:5d54b09eba2bada6011aea5375542a157637b91029687eb4fdb2dab11059c1b4", size = 182165 }, 492 | { url = "https://files.pythonhosted.org/packages/29/93/bb672df7b2f5faac89761cb5fa34f5cec45a4026c383a4b5761c6cea5c16/websockets-15.0.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:3be571a8b5afed347da347bfcf27ba12b069d9d7f42cb8c7028b5e98bbb12597", size = 182160 }, 493 | { url = "https://files.pythonhosted.org/packages/ff/83/de1f7709376dc3ca9b7eeb4b9a07b4526b14876b6d372a4dc62312bebee0/websockets-15.0.1-cp312-cp312-win32.whl", hash = "sha256:c338ffa0520bdb12fbc527265235639fb76e7bc7faafbb93f6ba80d9c06578a9", size = 176395 }, 494 | { url = "https://files.pythonhosted.org/packages/7d/71/abf2ebc3bbfa40f391ce1428c7168fb20582d0ff57019b69ea20fa698043/websockets-15.0.1-cp312-cp312-win_amd64.whl", hash = "sha256:fcd5cf9e305d7b8338754470cf69cf81f420459dbae8a3b40cee57417f4614a7", size = 176841 }, 495 | { url = "https://files.pythonhosted.org/packages/cb/9f/51f0cf64471a9d2b4d0fc6c534f323b664e7095640c34562f5182e5a7195/websockets-15.0.1-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:ee443ef070bb3b6ed74514f5efaa37a252af57c90eb33b956d35c8e9c10a1931", size = 175440 }, 496 | { url = "https://files.pythonhosted.org/packages/8a/05/aa116ec9943c718905997412c5989f7ed671bc0188ee2ba89520e8765d7b/websockets-15.0.1-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:5a939de6b7b4e18ca683218320fc67ea886038265fd1ed30173f5ce3f8e85675", size = 173098 }, 497 | { url = "https://files.pythonhosted.org/packages/ff/0b/33cef55ff24f2d92924923c99926dcce78e7bd922d649467f0eda8368923/websockets-15.0.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:746ee8dba912cd6fc889a8147168991d50ed70447bf18bcda7039f7d2e3d9151", size = 173329 }, 498 | { url = "https://files.pythonhosted.org/packages/31/1d/063b25dcc01faa8fada1469bdf769de3768b7044eac9d41f734fd7b6ad6d/websockets-15.0.1-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:595b6c3969023ecf9041b2936ac3827e4623bfa3ccf007575f04c5a6aa318c22", size = 183111 }, 499 | { url = "https://files.pythonhosted.org/packages/93/53/9a87ee494a51bf63e4ec9241c1ccc4f7c2f45fff85d5bde2ff74fcb68b9e/websockets-15.0.1-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:3c714d2fc58b5ca3e285461a4cc0c9a66bd0e24c5da9911e30158286c9b5be7f", size = 182054 }, 500 | { url = "https://files.pythonhosted.org/packages/ff/b2/83a6ddf56cdcbad4e3d841fcc55d6ba7d19aeb89c50f24dd7e859ec0805f/websockets-15.0.1-cp313-cp313-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0f3c1e2ab208db911594ae5b4f79addeb3501604a165019dd221c0bdcabe4db8", size = 182496 }, 501 | { url = "https://files.pythonhosted.org/packages/98/41/e7038944ed0abf34c45aa4635ba28136f06052e08fc2168520bb8b25149f/websockets-15.0.1-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:229cf1d3ca6c1804400b0a9790dc66528e08a6a1feec0d5040e8b9eb14422375", size = 182829 }, 502 | { url = "https://files.pythonhosted.org/packages/e0/17/de15b6158680c7623c6ef0db361da965ab25d813ae54fcfeae2e5b9ef910/websockets-15.0.1-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:756c56e867a90fb00177d530dca4b097dd753cde348448a1012ed6c5131f8b7d", size = 182217 }, 503 | { url = "https://files.pythonhosted.org/packages/33/2b/1f168cb6041853eef0362fb9554c3824367c5560cbdaad89ac40f8c2edfc/websockets-15.0.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:558d023b3df0bffe50a04e710bc87742de35060580a293c2a984299ed83bc4e4", size = 182195 }, 504 | { url = "https://files.pythonhosted.org/packages/86/eb/20b6cdf273913d0ad05a6a14aed4b9a85591c18a987a3d47f20fa13dcc47/websockets-15.0.1-cp313-cp313-win32.whl", hash = "sha256:ba9e56e8ceeeedb2e080147ba85ffcd5cd0711b89576b83784d8605a7df455fa", size = 176393 }, 505 | { url = "https://files.pythonhosted.org/packages/1b/6c/c65773d6cab416a64d191d6ee8a8b1c68a09970ea6909d16965d26bfed1e/websockets-15.0.1-cp313-cp313-win_amd64.whl", hash = "sha256:e09473f095a819042ecb2ab9465aee615bd9c2028e4ef7d933600a8401c79561", size = 176837 }, 506 | { url = "https://files.pythonhosted.org/packages/fa/a8/5b41e0da817d64113292ab1f8247140aac61cbf6cfd085d6a0fa77f4984f/websockets-15.0.1-py3-none-any.whl", hash = "sha256:f7a866fbc1e97b5c617ee4116daaa09b722101d4a3c170c787450ba409f9736f", size = 169743 }, 507 | ] 508 | --------------------------------------------------------------------------------