feat(main/cli/script):新增codex配置cli和健康检查接口
This commit is contained in:
+2
-1
@@ -27,9 +27,10 @@ debug_request_body.txt
|
|||||||
|
|
||||||
# Docker (避免层级嵌套)
|
# Docker (避免层级嵌套)
|
||||||
docker/
|
docker/
|
||||||
|
scripts/
|
||||||
Dockerfile
|
Dockerfile
|
||||||
docker-compose*.yml
|
docker-compose*.yml
|
||||||
|
cli.py
|
||||||
# Build / Dist
|
# Build / Dist
|
||||||
dist/
|
dist/
|
||||||
build/
|
build/
|
||||||
|
|||||||
@@ -4,8 +4,6 @@ OpenAI Responses API ↔ DeepSeek Chat API 流式转发代理。
|
|||||||
|
|
||||||
将 OpenAI Codex 等客户端发出的 Responses API 请求,实时转换为 DeepSeek Chat Completions 格式,实现 SSE 流式透传。
|
将 OpenAI Codex 等客户端发出的 Responses API 请求,实时转换为 DeepSeek Chat Completions 格式,实现 SSE 流式透传。
|
||||||
|
|
||||||
本项目配合 `CC Switch`使用,可实现 Codex IDE/CLI 与 DeepSeek Chat 的对接中转。
|
|
||||||
|
|
||||||
> 妈的,使用Codex,想用DeepSeek接入,找了半天工具,就没发现什么非常好用的工具,协议都不匹配,找到 [Nigel211/codex_deepseek_proxy](https://github.com/Nigel211/codex_deepseek_proxy.git) 但是单文件模式不习惯,使用flask框架也不喜欢,同时在使用中发现模型的对应问题,很头大,没工夫去慢慢研究了,所以重构了fastAPI的版本,后续有空的话会增加其他各路国产模型的适配。
|
> 妈的,使用Codex,想用DeepSeek接入,找了半天工具,就没发现什么非常好用的工具,协议都不匹配,找到 [Nigel211/codex_deepseek_proxy](https://github.com/Nigel211/codex_deepseek_proxy.git) 但是单文件模式不习惯,使用flask框架也不喜欢,同时在使用中发现模型的对应问题,很头大,没工夫去慢慢研究了,所以重构了fastAPI的版本,后续有空的话会增加其他各路国产模型的适配。
|
||||||
|
|
||||||
|
|
||||||
@@ -206,9 +204,16 @@ docker run -d \
|
|||||||
|
|
||||||
## 用法
|
## 用法
|
||||||
|
|
||||||
### API Endpoints
|
### API Endpoints 1
|
||||||
|
|
||||||
本项目无法直接实现codex的对接,需要配合CCSwitch等工具实现对接。
|
本项目提供了一个简易的命令行接口,用于将配置Codex 的桌面端请求代理到本中转服务
|
||||||
|
```
|
||||||
|
uv run cli.py -u http://<你的ip>:12345 -k <你设置的MY_API_KEY>
|
||||||
|
```
|
||||||
|
|
||||||
|
### API Endpoints 2
|
||||||
|
|
||||||
|
如果要使用第三方工具,请使用下面的API Endpoints
|
||||||
|
|
||||||
打开ccswitch,点击添加新供应商,选择自定义,填写代理地址和端口即可。
|
打开ccswitch,点击添加新供应商,选择自定义,填写代理地址和端口即可。
|
||||||
|
|
||||||
@@ -224,7 +229,6 @@ API 请求地址:http://127.0.0.1:12345(本地跑这个服务就本地,远程
|
|||||||
|
|
||||||

|

|
||||||
|
|
||||||
|
|
||||||
## 模型映射
|
## 模型映射
|
||||||
|
|
||||||
通过环境变量为每个 Codex 模型名指定对应的 DeepSeek 模型:
|
通过环境变量为每个 Codex 模型名指定对应的 DeepSeek 模型:
|
||||||
|
|||||||
@@ -0,0 +1,53 @@
|
|||||||
|
from script.tools import get_config, get_auth
|
||||||
|
import requests
|
||||||
|
|
||||||
|
def healthcheck(base_url:str, api_key:str):
|
||||||
|
try:
|
||||||
|
url = f'{base_url}/health'
|
||||||
|
headers = {'Authorization': f'Bearer {api_key}'}
|
||||||
|
response = requests.get(url, headers=headers)
|
||||||
|
if response.status_code == 200:
|
||||||
|
data = response.json()
|
||||||
|
if 'status' in data and data['status'] == 'ok':
|
||||||
|
return True
|
||||||
|
return False
|
||||||
|
except Exception as e:
|
||||||
|
print(f"Error occurred while checking health: {e}")
|
||||||
|
return False
|
||||||
|
|
||||||
|
def init(base_url:str, api_key:str):
|
||||||
|
if healthcheck(base_url, api_key):
|
||||||
|
try:
|
||||||
|
config = get_config()
|
||||||
|
auth = get_auth()
|
||||||
|
|
||||||
|
# 先设置config
|
||||||
|
config.set("model_provider", "custom")
|
||||||
|
config.set("model", "gpt-4.4")
|
||||||
|
config.set("model_reasoning_effort", "high")
|
||||||
|
config.set("disable_response_storage", True)
|
||||||
|
|
||||||
|
config.set("model_providers.custom.name", "codex2deepseek")
|
||||||
|
config.set("model_providers.custom.wire_api", "responses")
|
||||||
|
config.set("model_providers.custom.requires_openai_auth", True)
|
||||||
|
config.set("model_providers.custom.base_url", base_url)
|
||||||
|
|
||||||
|
# 设置auth
|
||||||
|
auth.set("auth_mode", "apikey")
|
||||||
|
auth.set("OPENAI_API_KEY", api_key)
|
||||||
|
return True,"初始化成功,请重启Codex以应用新配置."
|
||||||
|
except Exception as e:
|
||||||
|
return False, f"初始化失败: {str(e)}"
|
||||||
|
else:
|
||||||
|
return False, "自定义模型提供者不可用,请检查基本URL和API密钥."
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
# 运行参数cli:python -u <base_url> -k <api_key>
|
||||||
|
import argparse
|
||||||
|
parser = argparse.ArgumentParser(description="初始化自定义模型提供者配置。")
|
||||||
|
parser.add_argument("-u", "--base_url", type=str, required=True, help="自定义模型提供者的基本URL。")
|
||||||
|
parser.add_argument("-k", "--api_key", type=str, required=True, help="用于身份验证的API密钥。")
|
||||||
|
args = parser.parse_args()
|
||||||
|
success, message = init(args.base_url, args.api_key)
|
||||||
|
print(message)
|
||||||
@@ -49,6 +49,11 @@ app = FastAPI(
|
|||||||
lifespan=create_lifespan,
|
lifespan=create_lifespan,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@app.get("/health")
|
||||||
|
async def health_check():
|
||||||
|
"""健康检查端点"""
|
||||||
|
return {"status": "ok"}
|
||||||
|
|
||||||
# 配置中间件
|
# 配置中间件
|
||||||
setup_middleware(app)
|
setup_middleware(app)
|
||||||
|
|
||||||
|
|||||||
@@ -8,4 +8,5 @@ dependencies = [
|
|||||||
"fastapi>=0.136.0",
|
"fastapi>=0.136.0",
|
||||||
"uvicorn>=0.44.0",
|
"uvicorn>=0.44.0",
|
||||||
"requests>=2.28",
|
"requests>=2.28",
|
||||||
|
"rtoml>=0.13.0",
|
||||||
]
|
]
|
||||||
|
|||||||
+177
@@ -0,0 +1,177 @@
|
|||||||
|
import rtoml
|
||||||
|
import json
|
||||||
|
from pathlib import Path
|
||||||
|
from typing import Any, Dict
|
||||||
|
import os
|
||||||
|
|
||||||
|
# ==================== 安全嵌套读取 ====================
|
||||||
|
class _SafeNested:
|
||||||
|
def __init__(self, data):
|
||||||
|
self._data = data
|
||||||
|
|
||||||
|
def __getattr__(self, key):
|
||||||
|
if isinstance(self._data, dict) and key in self._data:
|
||||||
|
return _SafeNested(self._data[key])
|
||||||
|
return _SafeNested(None)
|
||||||
|
|
||||||
|
def __str__(self):
|
||||||
|
return str(self._data) if self._data is not None else "None"
|
||||||
|
|
||||||
|
def __repr__(self):
|
||||||
|
return str(self)
|
||||||
|
|
||||||
|
def __bool__(self):
|
||||||
|
return self._data is not None
|
||||||
|
|
||||||
|
# ==================== 核心配置类 ====================
|
||||||
|
class TomlConfig:
|
||||||
|
def __init__(self, file_path: str | Path):
|
||||||
|
self._path = Path(file_path)
|
||||||
|
self._data: Dict[str, Any] = self._load_file()
|
||||||
|
|
||||||
|
def _load_file(self) -> Dict[str, Any]:
|
||||||
|
if not self._path.exists():
|
||||||
|
return {}
|
||||||
|
with open(self._path, "r", encoding="utf-8") as f:
|
||||||
|
return rtoml.load(f)
|
||||||
|
|
||||||
|
def save(self) -> None:
|
||||||
|
""" ✅ 终极:保留所有格式、空章节、原样输出 """
|
||||||
|
with open(self._path, "w", encoding="utf-8") as f:
|
||||||
|
rtoml.dump(self._data, f, pretty=True)
|
||||||
|
|
||||||
|
def all(self) -> Dict[str, Any]:
|
||||||
|
return self._data.copy()
|
||||||
|
|
||||||
|
def keys(self) -> list:
|
||||||
|
return list(self._data.keys())
|
||||||
|
|
||||||
|
def get(self, path: str, default: Any = None) -> Any:
|
||||||
|
keys = path.split(".")
|
||||||
|
current = self._data
|
||||||
|
try:
|
||||||
|
for k in keys:
|
||||||
|
current = current[k]
|
||||||
|
return current
|
||||||
|
except (KeyError, TypeError):
|
||||||
|
return default
|
||||||
|
|
||||||
|
def set(self, path: str, value: Any, auto_save: bool = True) -> None:
|
||||||
|
keys = path.split(".")
|
||||||
|
current = self._data
|
||||||
|
for k in keys[:-1]:
|
||||||
|
current = current.setdefault(k, {})
|
||||||
|
current[keys[-1]] = value
|
||||||
|
if auto_save:
|
||||||
|
self.save()
|
||||||
|
|
||||||
|
# 点访问(只读)
|
||||||
|
def __getattr__(self, key):
|
||||||
|
return _SafeNested(self._data.get(key))
|
||||||
|
|
||||||
|
def __getitem__(self, key):
|
||||||
|
return self.__getattr__(key)
|
||||||
|
|
||||||
|
# ==================== JSON 认证/配置工具类====================
|
||||||
|
class JsonAuth:
|
||||||
|
def __init__(self, file_path: str | Path):
|
||||||
|
self._path = Path(file_path)
|
||||||
|
self._data: Dict[str, Any] = self._load_file()
|
||||||
|
|
||||||
|
def _load_file(self) -> Dict[str, Any]:
|
||||||
|
"""加载 JSON 文件,不存在返回空字典"""
|
||||||
|
if not self._path.exists():
|
||||||
|
return {}
|
||||||
|
try:
|
||||||
|
with open(self._path, "r", encoding="utf-8") as f:
|
||||||
|
return json.load(f)
|
||||||
|
except:
|
||||||
|
return {}
|
||||||
|
|
||||||
|
def save(self) -> None:
|
||||||
|
"""保存(格式化输出、中文不乱码、结构完全保留)"""
|
||||||
|
with open(self._path, "w", encoding="utf-8") as f:
|
||||||
|
json.dump(
|
||||||
|
self._data,
|
||||||
|
f,
|
||||||
|
ensure_ascii=False,
|
||||||
|
indent=4
|
||||||
|
)
|
||||||
|
|
||||||
|
def all(self) -> Dict[str, Any]:
|
||||||
|
"""获取全部数据"""
|
||||||
|
return self._data.copy()
|
||||||
|
|
||||||
|
def keys(self) -> list:
|
||||||
|
"""获取顶层键"""
|
||||||
|
return list(self._data.keys())
|
||||||
|
|
||||||
|
def get(self, path: str, default: Any = None) -> Any:
|
||||||
|
"""支持 a.b.c 格式安全获取"""
|
||||||
|
keys = path.split(".")
|
||||||
|
current = self._data
|
||||||
|
try:
|
||||||
|
for k in keys:
|
||||||
|
current = current[k]
|
||||||
|
return current
|
||||||
|
except (KeyError, TypeError):
|
||||||
|
return default
|
||||||
|
|
||||||
|
def set(self, path: str, value: Any, auto_save: bool = True) -> None:
|
||||||
|
"""支持 a.b.c 格式设置,自动创建层级"""
|
||||||
|
keys = path.split(".")
|
||||||
|
current = self._data
|
||||||
|
for k in keys[:-1]:
|
||||||
|
current = current.setdefault(k, {})
|
||||||
|
current[keys[-1]] = value
|
||||||
|
if auto_save:
|
||||||
|
self.save()
|
||||||
|
|
||||||
|
# ==================== 点访问(只读,永不报错)====================
|
||||||
|
def __getattr__(self, key):
|
||||||
|
return _SafeNested(self._data.get(key))
|
||||||
|
|
||||||
|
def __getitem__(self, key):
|
||||||
|
return self.__getattr__(key)
|
||||||
|
|
||||||
|
# ==================== 工具函数 ====================
|
||||||
|
def get_user_home():
|
||||||
|
return os.path.expanduser("~")
|
||||||
|
|
||||||
|
def check_codex_dir():
|
||||||
|
codex_dir = Path(get_user_home()) / ".codex"
|
||||||
|
if not codex_dir.exists():
|
||||||
|
raise FileNotFoundError(f"{codex_dir} 不存在")
|
||||||
|
return codex_dir
|
||||||
|
|
||||||
|
def get_config():
|
||||||
|
codex_dir = check_codex_dir()
|
||||||
|
config_path = codex_dir / "config.toml"
|
||||||
|
if not config_path.exists():
|
||||||
|
raise FileNotFoundError(f"{config_path} 不存在")
|
||||||
|
return TomlConfig(config_path)
|
||||||
|
|
||||||
|
def get_auth():
|
||||||
|
codex_dir = check_codex_dir()
|
||||||
|
auth_path = codex_dir / "auth.json"
|
||||||
|
if not auth_path.exists():
|
||||||
|
raise FileNotFoundError(f"{auth_path} 不存在")
|
||||||
|
return JsonAuth(auth_path)
|
||||||
|
|
||||||
|
# ==================== 测试 ====================
|
||||||
|
if __name__ == "__main__":
|
||||||
|
cfg = get_config()
|
||||||
|
|
||||||
|
print("不存在的键:", cfg.a.b.c)
|
||||||
|
print("model =", cfg.get("model"))
|
||||||
|
print("mcp_servers =", cfg.mcp_servers)
|
||||||
|
|
||||||
|
print("\n\n")
|
||||||
|
|
||||||
|
auth = get_auth()
|
||||||
|
|
||||||
|
print("不存在的键:", auth.a.b.c)
|
||||||
|
print("auth_mode =", auth.get("auth_mode"))
|
||||||
|
print("OPENAI_API_KEY =", auth.OPENAI_API_KEY)
|
||||||
|
|
||||||
|
auth.set("auth_mode", "apikey")
|
||||||
@@ -134,6 +134,7 @@ source = { virtual = "." }
|
|||||||
dependencies = [
|
dependencies = [
|
||||||
{ name = "fastapi" },
|
{ name = "fastapi" },
|
||||||
{ name = "requests" },
|
{ name = "requests" },
|
||||||
|
{ name = "rtoml" },
|
||||||
{ name = "uvicorn" },
|
{ name = "uvicorn" },
|
||||||
]
|
]
|
||||||
|
|
||||||
@@ -141,6 +142,7 @@ dependencies = [
|
|||||||
requires-dist = [
|
requires-dist = [
|
||||||
{ name = "fastapi", specifier = ">=0.136.0" },
|
{ name = "fastapi", specifier = ">=0.136.0" },
|
||||||
{ name = "requests", specifier = ">=2.28" },
|
{ name = "requests", specifier = ">=2.28" },
|
||||||
|
{ name = "rtoml", specifier = ">=0.13.0" },
|
||||||
{ name = "uvicorn", specifier = ">=0.44.0" },
|
{ name = "uvicorn", specifier = ">=0.44.0" },
|
||||||
]
|
]
|
||||||
|
|
||||||
@@ -292,6 +294,53 @@ wheels = [
|
|||||||
{ url = "https://files.pythonhosted.org/packages/a0/f4/c67b0b3f1b9245e8d266f0f112c500d50e5b4e83cb6f3b71b6528104182a/requests-2.34.2-py3-none-any.whl", hash = "sha256:2a0d60c172f83ac6ab31e4554906c0f3b3588d37b5cb939b1c061f4907e278e0", size = 73075, upload-time = "2026-05-14T19:25:26.443Z" },
|
{ url = "https://files.pythonhosted.org/packages/a0/f4/c67b0b3f1b9245e8d266f0f112c500d50e5b4e83cb6f3b71b6528104182a/requests-2.34.2-py3-none-any.whl", hash = "sha256:2a0d60c172f83ac6ab31e4554906c0f3b3588d37b5cb939b1c061f4907e278e0", size = 73075, upload-time = "2026-05-14T19:25:26.443Z" },
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "rtoml"
|
||||||
|
version = "0.13.0"
|
||||||
|
source = { registry = "https://pypi.org/simple" }
|
||||||
|
sdist = { url = "https://files.pythonhosted.org/packages/e9/11/2655729f675411fc82588d6cf598758a2339d56c5a2fa6eb89f3302ec484/rtoml-0.13.0.tar.gz", hash = "sha256:974522c887b47abc0bb62ee8ae9e44d3a0c2cdac9d60ba0ed01c5a40df0ea424", size = 43171, upload-time = "2025-10-19T04:59:00.262Z" }
|
||||||
|
wheels = [
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/5f/1e/835105f9953ff5a04f1332ff651a185d7c9fa5b333ca6557789621f0bce6/rtoml-0.13.0-cp312-cp312-macosx_10_12_x86_64.whl", hash = "sha256:e94c60ee00b6625c1e0f42d411edc8aa1c4fcf09c183347eb362a7b87e36f199", size = 329825, upload-time = "2025-10-19T04:58:21.722Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/7a/da/7bd910e8c9a4a8f8d3da8ad7e8c5c63b3227ad9704a04c765b1947c16982/rtoml-0.13.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:1e15f554e62b3b1661bd2ee5972f0a2d3dca925753481c6022b3f31d05634bb4", size = 312637, upload-time = "2025-10-19T04:58:22.578Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/c8/da/3529447a6b68c0df993845a82f6c64c0755dfa4ea8fc36873845df9b2217/rtoml-0.13.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f8a2d9c8234d245334765a89f65b0d934f403629423f70f30a688fc8194e8ed1", size = 338019, upload-time = "2025-10-19T04:58:23.414Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/88/8a/9b85639084b018b012c821c5a530b5c025347dcadb7e5794b9b14bd9adc2/rtoml-0.13.0-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:7fb0c9f266136a2072d082bc781e49c27422e740505788573ad9cdc58015f58e", size = 366171, upload-time = "2025-10-19T04:58:24.31Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/27/dd/2d9348f6c77a9ec65449696bfd50a539e793b5b5595bd2e4036b6f0cf1fa/rtoml-0.13.0-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:2fe4a2443246b56e1fb25f298acb7f3d93da0623d52ef76dbfb2abeb0cfbdfaf", size = 382874, upload-time = "2025-10-19T04:58:25.185Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/63/8a/f350209d8b316a64a734d379cf62927222d58341d2b1665d1854a6bb2933/rtoml-0.13.0-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:f4a8896475cfb4ef68fd2dda2ad3aacecb6d9c40696e85f47ad8b18b8f003b42", size = 406552, upload-time = "2025-10-19T04:58:26.057Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/68/b4/c1c51adca7b4cf364e80ba9f4c42be3fa95f3ddef6c022b97688addb441e/rtoml-0.13.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5a0939d03ce3dc5340645e0cb191e82d248dff5a77d6646139c5f9ac8531799d", size = 346034, upload-time = "2025-10-19T04:58:27.298Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/c7/4f/3ce38a91e253bb671452ba3b1e11f74197e35318457e638aa3b4d59e06da/rtoml-0.13.0-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:763f8b86db927e1bb6e6d65c676a03c6431f1de1037ae896c3a0984353573547", size = 372957, upload-time = "2025-10-19T04:58:28.244Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/19/58/c4a1ddcc2402fe3b773ee55c03e002682b797297f1dcf5ea362d6ab0ae3e/rtoml-0.13.0-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:ff2f38ffbd3c8bfdc60513ef8efdc732fa205bd53a45226559df5605cb1431d5", size = 519510, upload-time = "2025-10-19T04:58:29.226Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/4a/03/1232dc261e35521a73000bf48e9c04451248d1ff9e668949e06549bb87c8/rtoml-0.13.0-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:ba2fbc1f1fa7bff8d722fd2539dc9962064b6193b90424625b2d4fe87726f945", size = 518664, upload-time = "2025-10-19T04:58:30.257Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/5b/46/5c853e1deab5cbc98564f43cde565e47793889d9c72ca24cf45fb1f637e6/rtoml-0.13.0-cp312-cp312-win32.whl", hash = "sha256:ed5120b56e568df8f297e7a8228b2f2c258daaee3af8b690584cbc0dce1d7f05", size = 217896, upload-time = "2025-10-19T04:58:31.125Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/e8/ec/31ce0a96a0800c060bfbb61d243029f44baf1eb45c1469d70b1768f5b820/rtoml-0.13.0-cp312-cp312-win_amd64.whl", hash = "sha256:1af5785c1f0119d523c77461de8c910e87f6254d3786f9768a8e16ec8250d42d", size = 222748, upload-time = "2025-10-19T04:58:32.016Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/04/15/b92baaf70147932b66a451b07a4cdd36e6d68a59cd6a47bce9c532acba11/rtoml-0.13.0-cp312-cp312-win_arm64.whl", hash = "sha256:564903f2ea90191ac172f89a47a3d6b7d633ff7e2ac92b82590924ad6e1452ba", size = 212862, upload-time = "2025-10-19T04:58:32.942Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/cd/28/b186d539286bc52a4910e9b4202f6736dbf17188fbcf944f2710e188e759/rtoml-0.13.0-cp313-cp313-macosx_10_12_x86_64.whl", hash = "sha256:ad9988a3a4bd11e45d8cc2064c16397dfe6686cef18f2cfdeb7e93bdb2ca9775", size = 329464, upload-time = "2025-10-19T04:58:33.796Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/ec/a7/29d73c982280ad01f1fea647db551a1eebd5e62c05c000babee6bed9a546/rtoml-0.13.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:44ef5f5deb6eb735b93074dd56e7039c3c4929055e91feb83e2032e4c2bd1665", size = 312357, upload-time = "2025-10-19T04:58:34.798Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/c8/51/8cf01d5e4a712cc61550abace74c5f5275a7a186c2b90f3437f6c2006dc0/rtoml-0.13.0-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:020fe78f7e53b9fef1762cd3734374baa506b225dd72ee7603242b11f33602c3", size = 337631, upload-time = "2025-10-19T04:58:35.814Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/2e/96/c2ace9dfe6e874db1de8f35cdb1926dd0a724e1569ffdba424252c0fb4f5/rtoml-0.13.0-cp313-cp313-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:1f4ceacdeab625f9585006976961f65165318d494f13f2cd114880576996f8ab", size = 365633, upload-time = "2025-10-19T04:58:36.71Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/8f/f0/5ee0f7d0ebad5d0c332871807c0dc5b06b0ffd601582299e9fdb1be7bb8b/rtoml-0.13.0-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:2823c41a3d0d019f3a0724e3a7c95439d6e034acc5251ed5c8129a5c8edcfb0a", size = 382393, upload-time = "2025-10-19T04:58:37.952Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/f6/2b/e028f2ba5942ed31a950d4e485328be49599e487a3773940dcd835bd1064/rtoml-0.13.0-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:e289dc70d1ad0a81266b0f85ffbbc2a0e3ab58c1aedbd2bd5f46cfd8d3da5afe", size = 406156, upload-time = "2025-10-19T04:58:38.881Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/a1/4e/8e133c2fc6c758bcc067ed474c5c2d744c6a8f390b593b8cc1324f7a4cb7/rtoml-0.13.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0e904779134a2d9658edbdc58392a84f7a531620afdd2ded67a6bb792b2cfb86", size = 345467, upload-time = "2025-10-19T04:58:39.77Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/98/ca/855bbb4d1ade53dca2098a9dc434527bfad5045e7595c3107ed2d14b7163/rtoml-0.13.0-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:956fcce8ec80ea59e32f85e8897cfaabd63a2a945aad1d9e439274ee71b9a6f6", size = 372463, upload-time = "2025-10-19T04:58:40.675Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/ed/99/3ebed5dd770526632c6d1ff4817b615a904c11ecb06093b65e6da5800d46/rtoml-0.13.0-cp313-cp313-musllinux_1_1_aarch64.whl", hash = "sha256:b756dc66682b89f3fa2dea3dc17d2acf7ca2af416ba7a36f19e97340f2b3ffa4", size = 519179, upload-time = "2025-10-19T04:58:41.629Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/2e/e2/515ed4000d5707893ec869c10783f0102ff1ec6e8c15b6fc94be804eb6eb/rtoml-0.13.0-cp313-cp313-musllinux_1_1_x86_64.whl", hash = "sha256:9fb0792ce87a49bb7ba8e9332854ca0b178c6f86462ae1142813b2b780875633", size = 518145, upload-time = "2025-10-19T04:58:42.618Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/dd/8b/7848a5293b25975171d5b5b809f373150f10c3dae8311359a37948f34da2/rtoml-0.13.0-cp313-cp313-win32.whl", hash = "sha256:ad2e3e3accec89d112a431fa0991c9dd2f1ca5282e385a75f6697b5de6910ef9", size = 217473, upload-time = "2025-10-19T04:58:43.821Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/24/45/24391d1f58982494b898322ab230c5e7fc1020400ba303244fd5cc8eeb10/rtoml-0.13.0-cp313-cp313-win_amd64.whl", hash = "sha256:d7435f2b11384216461e2355a2795e67dc812d701f66890bd43680b6a8e365ce", size = 222228, upload-time = "2025-10-19T04:58:44.68Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/67/5e/aec326eec687af0849ebc646d47b6adc5f575c6e1998d4cbd6f69d49935e/rtoml-0.13.0-cp313-cp313-win_arm64.whl", hash = "sha256:0434e3d196375b82cfa5dc155cad6c78fd96c2cc6692e1d887505e1d99900986", size = 212406, upload-time = "2025-10-19T04:58:45.923Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/28/51/07a144e0fd7fa0f2273a8a65e7ede19aa59ffac13b15c8344c462eaa0689/rtoml-0.13.0-cp314-cp314-macosx_10_12_x86_64.whl", hash = "sha256:566f8f8e6dc2e965972b0d8f7c856e4920c443815e9d29a895ae04d588d9b48f", size = 329514, upload-time = "2025-10-19T04:58:46.796Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/b4/b1/0205f688f83051457c1553fc152dc0617fe39acb2377cb0a657ff467a825/rtoml-0.13.0-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:e5634d2079c8912958791973e0a4cfed311660286bfb6b14698294735ede7b7d", size = 312328, upload-time = "2025-10-19T04:58:47.857Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/d8/11/1b5205c03e7644b39112231a905691c9c24caab8bbeb08507e8e43a064c5/rtoml-0.13.0-cp314-cp314-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:18a141e0ea5ec8e0be88726d768956affe4a937b109421567cbd4dfdc5016d0c", size = 338687, upload-time = "2025-10-19T04:58:49.028Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/38/56/5709af9938727211b5883ad66b03a86b19b3d6544388115e4e39d506afc8/rtoml-0.13.0-cp314-cp314-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:55b003f31a87f49dd941d02aac84b7c4d8cfbd1dfcc80d7a6a71835c72ddd74f", size = 365670, upload-time = "2025-10-19T04:58:49.988Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/0d/a6/99fa1618beca99f62b5a156874eb5752fe51eb78e3f0363c9533d34fd9dc/rtoml-0.13.0-cp314-cp314-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:9c7ade406218833fbbc97ceca92050c02f4d724045770eb9020be1b3d97df455", size = 382240, upload-time = "2025-10-19T04:58:50.954Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/88/0e/23f7719656bdabeee1731b46443ea1d3aaecdde702142bcd7757a4ab75b2/rtoml-0.13.0-cp314-cp314-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:c84d8b77cd0dbb5cf1da33846d5c5fd02536c06ab5ab560e90e4ca2920942b58", size = 406158, upload-time = "2025-10-19T04:58:51.925Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/60/66/07df2e5f99f17696a46fd6cbc5c9d279422b1652f0d130a122418ee077ea/rtoml-0.13.0-cp314-cp314-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:95a229595254449cbf0b2e396f1b444ed8a0c259f78bab505326bb2a1e4239ff", size = 345644, upload-time = "2025-10-19T04:58:52.839Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/83/fc/32efd575a5b1f6674675dd8ed181c7cca81fa315b8411df23f91251b2fd6/rtoml-0.13.0-cp314-cp314-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:a3bf2a94df8bb22642fbd263b17aa6b7822384a756204c1da9ae05c4c5c749f9", size = 372629, upload-time = "2025-10-19T04:58:53.846Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/77/ca/e70ee8457ea07885b885848e07ac07590f9e70e8a57b564e2cb23583dcca/rtoml-0.13.0-cp314-cp314-musllinux_1_1_aarch64.whl", hash = "sha256:8377affbcf36c4fc8360778015c82972b4d0134faacee426ec37e8e7afcf3855", size = 519169, upload-time = "2025-10-19T04:58:54.754Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/fa/20/2eb6fab37a545902fe634318e33c1d2199ae4f3be3b522da1dc5f7563a74/rtoml-0.13.0-cp314-cp314-musllinux_1_1_x86_64.whl", hash = "sha256:b844b95939cc4f7b88d99fc874a191957d218ecf057bdc381745ad58e953361b", size = 518186, upload-time = "2025-10-19T04:58:55.705Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/f2/1c/f1251b42591aaab0feb2d9a4ab8c9c6f49511f2bae6fea175d7db4111f13/rtoml-0.13.0-cp314-cp314-win32.whl", hash = "sha256:cadb00e9a4d09832d2842ae18638d27103c992ccfbc5a702eb14b6b40e4e0ed9", size = 217475, upload-time = "2025-10-19T04:58:57.211Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/fc/e5/db02ccd1aea7b17645b785b55c605c655959655f320f4fadfa1d293c914e/rtoml-0.13.0-cp314-cp314-win_amd64.whl", hash = "sha256:4f1c6fa1c31f2baabc1436e8b87997da2b960e61a5a4dac52f7f4e4ef7b6810c", size = 221608, upload-time = "2025-10-19T04:58:58.07Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/7a/63/48fd3207eb8f50566d871d86ea25cd86e4f2de2459229907e271272f58ac/rtoml-0.13.0-cp314-cp314-win_arm64.whl", hash = "sha256:f513e54f6788038bb6473564544b27cecd48dc2666fc066eb09f3759df4e3b42", size = 211938, upload-time = "2025-10-19T04:58:58.963Z" },
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "starlette"
|
name = "starlette"
|
||||||
version = "1.1.0"
|
version = "1.1.0"
|
||||||
|
|||||||
Reference in New Issue
Block a user