deeme commited on
Commit
c4a0b25
verified
1 Parent(s): 2bc369a

Upload 9 files

Browse files
Files changed (9) hide show
  1. .env +10 -0
  2. Dockerfile +32 -0
  3. README.md +13 -10
  4. server.py +4 -0
  5. src/__init__.py +0 -0
  6. src/app.py +163 -0
  7. src/env.py +17 -0
  8. src/types.py +52 -0
  9. uv.lock +252 -0
.env ADDED
@@ -0,0 +1,10 @@
 
 
 
 
 
 
 
 
 
 
 
1
+ TRAE_APP_ID = "6eefa01c-1036-4c7e-9ca5-d891f63bfcd8"
2
+ TRAE_DEVICE_BRAND = "Modified by dsanke"
3
+ TRAE_DEVICE_CPU = "Intel"
4
+ TRAE_DEVICE_ID = "7472204647139558913"
5
+ TRAE_DEVICE_TYPE = "windows"
6
+ TRAE_IDE_VERSION = ""
7
+ TRAE_IDE_VERSION_CODE = ""
8
+ TRAE_IDE_VERSION_TYPE = ""
9
+ TRAE_MACHINE_ID = "9f569ccf7d06c0c753133b06a0595ae27fabd4ab2d8f8e76fdf32b95b037085c"
10
+ TRAE_OS_VERSION = "Microsoft Windows 10 专业锟斤拷"
Dockerfile ADDED
@@ -0,0 +1,32 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Use a Python image with uv pre-installed
2
+ FROM ghcr.io/astral-sh/uv:python3.13-bookworm-slim
3
+
4
+ # Set working dir to `/trae-api`
5
+ WORKDIR /trae-api
6
+
7
+ # Enable bytecode compilation
8
+ ENV UV_COMPILE_BYTECODE=1
9
+
10
+ # Copy from the cache instead of linking since it's a mounted volume
11
+ ENV UV_LINK_MODE=copy
12
+
13
+ # Install the project's dependencies using the lockfile and settings
14
+ RUN --mount=type=cache,target=/root/.cache/uv \
15
+ --mount=type=bind,source=uv.lock,target=uv.lock \
16
+ --mount=type=bind,source=pyproject.toml,target=pyproject.toml \
17
+ uv sync --frozen --no-install-project --no-dev
18
+
19
+ # Then, add the rest of the project source code and install it
20
+ # Installing separately from its dependencies allows optimal layer caching
21
+ ADD . /trae-api
22
+ RUN --mount=type=cache,target=/root/.cache/uv \
23
+ uv sync --frozen --no-dev
24
+
25
+ # Place executables in the environment at the front of the path
26
+ ENV PATH="/trae-api/.venv/bin:$PATH"
27
+
28
+ # Reset the entrypoint, don't invoke `uv`
29
+ ENTRYPOINT []
30
+
31
+ # Run server.py by default
32
+ CMD ["python", "server.py"]
README.md CHANGED
@@ -1,10 +1,13 @@
1
- ---
2
- title: Trae
3
- emoji: 馃捇
4
- colorFrom: blue
5
- colorTo: purple
6
- sdk: docker
7
- pinned: false
8
- ---
9
-
10
- Check out the configuration reference at https://huggingface.co/docs/hub/spaces-config-reference
 
 
 
 
1
+ ---
2
+ title: trae
3
+ emoji: 馃實
4
+ colorFrom: red
5
+ colorTo: red
6
+ sdk: docker
7
+ pinned: false
8
+ app_port: 8000
9
+ ---
10
+
11
+
12
+
13
+
server.py ADDED
@@ -0,0 +1,4 @@
 
 
 
 
 
1
+ import uvicorn
2
+
3
+ if __name__ == "__main__":
4
+ uvicorn.run("src.app:app", host="0.0.0.0", port=8000)
src/__init__.py ADDED
File without changes
src/app.py ADDED
@@ -0,0 +1,163 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import json
2
+ import time
3
+ import uuid
4
+ from datetime import datetime
5
+
6
+ import httpx_sse
7
+ from fastapi import FastAPI, Header
8
+ from fastapi.responses import JSONResponse, StreamingResponse
9
+ from httpx import AsyncClient
10
+
11
+ from .env import (
12
+ TRAE_APP_ID,
13
+ TRAE_DEVICE_BRAND,
14
+ TRAE_DEVICE_CPU,
15
+ TRAE_DEVICE_ID,
16
+ TRAE_DEVICE_TYPE,
17
+ TRAE_IDE_TOKEN,
18
+ TRAE_IDE_VERSION,
19
+ TRAE_IDE_VERSION_CODE,
20
+ TRAE_IDE_VERSION_TYPE,
21
+ TRAE_MACHINE_ID,
22
+ TRAE_OS_VERSION,
23
+ )
24
+ from .types import (
25
+ ChatCompletionChunk,
26
+ ChatCompletionChunkChoice,
27
+ ChatCompletionRequest,
28
+ Model,
29
+ )
30
+
31
+ app = FastAPI(
32
+ title="Trae2OpenAI Proxy",
33
+ description="A api proxy to make trae's builtin models openai compatible",
34
+ version="0.1.0",
35
+ )
36
+
37
+
38
+ @app.get("/v1/models")
39
+ async def list_models(ide_token: str = Header(TRAE_IDE_TOKEN, alias="Authorization")) -> JSONResponse:
40
+ ide_token = ide_token.removeprefix("Bearer ")
41
+ async with AsyncClient() as client:
42
+ response = await client.get(
43
+ "https://trae-api-us.mchost.guru/api/ide/v1/model_list",
44
+ params={"type": "llm_raw_chat"},
45
+ headers={
46
+ "x-app-id": TRAE_APP_ID,
47
+ "x-device-brand": TRAE_DEVICE_BRAND,
48
+ "x-device-cpu": TRAE_DEVICE_CPU,
49
+ "x-device-id": TRAE_DEVICE_ID,
50
+ "x-device-type": TRAE_DEVICE_TYPE,
51
+ "x-ide-token": ide_token,
52
+ "x-ide-version": TRAE_IDE_VERSION,
53
+ "x-ide-version-code": TRAE_IDE_VERSION_CODE,
54
+ "x-ide-version-type": TRAE_IDE_VERSION_TYPE,
55
+ "x-machine-id": TRAE_MACHINE_ID,
56
+ "x-os-version": TRAE_OS_VERSION,
57
+ },
58
+ )
59
+ return JSONResponse(
60
+ {
61
+ "object": "list",
62
+ "data": [Model(created=0, id=model["name"]).model_dump() for model in response.json()["model_configs"]],
63
+ }
64
+ )
65
+
66
+
67
+ @app.post("/v1/chat/completions")
68
+ async def create_chat_completions(
69
+ request: ChatCompletionRequest, ide_token: str = Header(TRAE_IDE_TOKEN, alias="Authorization")
70
+ ) -> StreamingResponse:
71
+ ide_token = ide_token.removeprefix("Bearer ")
72
+ current_turn = sum(1 for msg in request.messages[:-1] if msg.role == "user")
73
+ last_assistant_message = next(filter(lambda msg: msg.role == "assistant", reversed(request.messages)), None)
74
+
75
+ async def stream_response():
76
+ async with AsyncClient() as client:
77
+ async with httpx_sse.aconnect_sse(
78
+ client,
79
+ "POST",
80
+ "https://trae-api-us.mchost.guru/api/ide/v1/chat",
81
+ headers={
82
+ "x-app-id": TRAE_APP_ID,
83
+ "x-device-brand": TRAE_DEVICE_BRAND,
84
+ "x-device-cpu": TRAE_DEVICE_CPU,
85
+ "x-device-id": TRAE_DEVICE_ID,
86
+ "x-device-type": TRAE_DEVICE_TYPE,
87
+ "x-ide-token": ide_token,
88
+ "x-ide-version": TRAE_IDE_VERSION,
89
+ "x-ide-version-code": TRAE_IDE_VERSION_CODE,
90
+ "x-ide-version-type": TRAE_IDE_VERSION_TYPE,
91
+ "x-machine-id": TRAE_MACHINE_ID,
92
+ "x-os-version": TRAE_OS_VERSION,
93
+ },
94
+ json={
95
+ "chat_history": [
96
+ {
97
+ **msg.model_dump(),
98
+ "status": "success",
99
+ "locale": "zh-cn",
100
+ }
101
+ for msg in request.messages[:-1]
102
+ ],
103
+ "context_resolvers": [],
104
+ "conversation_id": str(uuid.uuid4()),
105
+ "current_turn": current_turn,
106
+ "generate_suggested_questions": False,
107
+ "intent_name": "general_qa_intent",
108
+ "is_preset": True,
109
+ "last_llm_response_info": (
110
+ {"turn": current_turn - 1, "is_error": False, "response": last_assistant_message.content}
111
+ if last_assistant_message
112
+ else {}
113
+ ),
114
+ "model_name": request.model,
115
+ "multi_media": [],
116
+ "provider": "",
117
+ "session_id": str(uuid.uuid4()),
118
+ "user_input": request.messages[-1].content,
119
+ "valid_turns": list(range(current_turn)),
120
+ "variables": json.dumps(
121
+ {"locale": "zh-cn", "current_time": datetime.now().strftime("%Y%m%d %H:%M:%S %A")}
122
+ ),
123
+ },
124
+ ) as response:
125
+ chunk = ChatCompletionChunk(
126
+ choices=[],
127
+ created=int(time.time()),
128
+ id="",
129
+ model=request.model,
130
+ )
131
+ async for sse in response.aiter_sse():
132
+ sse_data = sse.json()
133
+ if sse.event == "metadata":
134
+ chunk.id = str(sse_data["prompt_completion_id"])
135
+ elif sse.event == "output":
136
+ content = sse_data["response"]
137
+ reasoning_content = sse_data["reasoning_content"]
138
+ chunk.choices = [
139
+ ChatCompletionChunkChoice(
140
+ delta={"role": "assistant", "content": content, "reasoning_content": reasoning_content}
141
+ )
142
+ ]
143
+ yield f"data: {chunk.model_dump_json()}\n\n"
144
+ elif sse.event == "token_usage":
145
+ chunk.choices = []
146
+ chunk.usage = {
147
+ "completion_tokens": sse_data["completion_tokens"],
148
+ "prompt_tokens": sse_data["prompt_tokens"],
149
+ "total_tokens": sse_data["total_tokens"],
150
+ }
151
+ yield f"data: {chunk.model_dump_json()}\n\n"
152
+ elif sse.event == "done":
153
+ chunk.choices = [ChatCompletionChunkChoice(delta={}, finish_reason="stop")]
154
+ yield f"data: {chunk.model_dump_json()}\n\ndata: [DONE]\n\n"
155
+ elif sse.event == "error":
156
+ chunk.choices = [
157
+ ChatCompletionChunkChoice(
158
+ delta={"role": "assistant", "content": sse.data}, finish_reason="error"
159
+ )
160
+ ]
161
+ yield f"data: {chunk.model_dump_json()}\n\ndata: [DONE]\n\n"
162
+
163
+ return StreamingResponse(stream_response(), media_type="text/event-stream")
src/env.py ADDED
@@ -0,0 +1,17 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import os
2
+
3
+ from dotenv import load_dotenv
4
+
5
+ load_dotenv()
6
+
7
+ TRAE_APP_ID = str(os.getenv("TRAE_APP_ID"))
8
+ TRAE_DEVICE_BRAND = str(os.getenv("TRAE_DEVICE_BRAND"))
9
+ TRAE_DEVICE_CPU = str(os.getenv("TRAE_DEVICE_CPU"))
10
+ TRAE_DEVICE_ID = str(os.getenv("TRAE_DEVICE_ID"))
11
+ TRAE_DEVICE_TYPE = str(os.getenv("TRAE_DEVICE_TYPE"))
12
+ TRAE_IDE_TOKEN = str(os.getenv("TRAE_IDE_TOKEN"))
13
+ TRAE_IDE_VERSION = str(os.getenv("TRAE_IDE_VERSION"))
14
+ TRAE_IDE_VERSION_CODE = str(os.getenv("TRAE_IDE_VERSION_CODE"))
15
+ TRAE_IDE_VERSION_TYPE = str(os.getenv("TRAE_IDE_VERSION_TYPE"))
16
+ TRAE_MACHINE_ID = str(os.getenv("TRAE_MACHINE_ID"))
17
+ TRAE_OS_VERSION = str(os.getenv("TRAE_OS_VERSION"))
src/types.py ADDED
@@ -0,0 +1,52 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from typing import Any, Literal
2
+
3
+ from pydantic import BaseModel
4
+
5
+
6
+ class ChatMessage(BaseModel):
7
+ content: str | list[dict[str, Any]]
8
+ name: str | None = None
9
+ role: Literal["system", "user", "assistant", "tool", "function"]
10
+
11
+
12
+ class ChatCompletionRequest(BaseModel):
13
+ model: str
14
+ messages: list[ChatMessage]
15
+ max_completion_tokens: int | None = None
16
+ modalities: list[str] | None = None
17
+ response_format: dict[str, Any] | None = None
18
+ seed: int | None = None
19
+ stop: str | list[str] | None = None
20
+ stream: bool | None = False
21
+ stream_options: dict[str, Any] | None = None
22
+ temperature: float | None = 1
23
+ tool_choice: Literal["none", "auto", "required"] | dict[str, Any] | None = None
24
+ tools: list[dict[str, Any]] | None = None
25
+ top_k: int | None = 20
26
+ top_p: float | None = 1
27
+ web_search_options: dict[str, Any] | None = None
28
+
29
+
30
+ class ChatCompletionChunkChoice(BaseModel):
31
+ delta: dict[str, Any]
32
+ finish_reason: str | None = None
33
+ index: int = 0
34
+ logprobs: dict[str, Any] | None = None
35
+
36
+
37
+ class ChatCompletionChunk(BaseModel):
38
+ choices: list[ChatCompletionChunkChoice]
39
+ created: int
40
+ id: str
41
+ model: str
42
+ object: str = "chat.completion.chunk"
43
+ service_tier: str | None = None
44
+ system_fingerprint: str = ""
45
+ usage: dict[str, Any] | None = None
46
+
47
+
48
+ class Model(BaseModel):
49
+ created: int
50
+ id: str
51
+ object: str = "model"
52
+ owned_by: str = "trae"
uv.lock ADDED
@@ -0,0 +1,252 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ version = 1
2
+ revision = 1
3
+ requires-python = ">=3.13.2"
4
+
5
+ [[package]]
6
+ name = "annotated-types"
7
+ version = "0.7.0"
8
+ source = { registry = "https://pypi.tuna.tsinghua.edu.cn/simple" }
9
+ sdist = { url = "https://pypi.tuna.tsinghua.edu.cn/packages/ee/67/531ea369ba64dcff5ec9c3402f9f51bf748cec26dde048a2f973a4eea7f5/annotated_types-0.7.0.tar.gz", hash = "sha256:aff07c09a53a08bc8cfccb9c85b05f1aa9a2a6f23728d790723543408344ce89", size = 16081 }
10
+ wheels = [
11
+ { url = "https://pypi.tuna.tsinghua.edu.cn/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.tuna.tsinghua.edu.cn/simple" }
18
+ dependencies = [
19
+ { name = "idna" },
20
+ { name = "sniffio" },
21
+ ]
22
+ sdist = { url = "https://pypi.tuna.tsinghua.edu.cn/packages/95/7d/4c1bd541d4dffa1b52bd83fb8527089e097a106fc90b467a7313b105f840/anyio-4.9.0.tar.gz", hash = "sha256:673c0c244e15788651a4ff38710fea9675823028a6f08a5eda409e0c9840a028", size = 190949 }
23
+ wheels = [
24
+ { url = "https://pypi.tuna.tsinghua.edu.cn/packages/a1/ee/48ca1a7c89ffec8b6a0c5d02b89c305671d5ffd8d3c94acf8b8c408575bb/anyio-4.9.0-py3-none-any.whl", hash = "sha256:9f76d541cad6e36af7beb62e978876f3b41e3e04f2c1fbf0884604c0a9c4d93c", size = 100916 },
25
+ ]
26
+
27
+ [[package]]
28
+ name = "certifi"
29
+ version = "2025.1.31"
30
+ source = { registry = "https://pypi.tuna.tsinghua.edu.cn/simple" }
31
+ sdist = { url = "https://pypi.tuna.tsinghua.edu.cn/packages/1c/ab/c9f1e32b7b1bf505bf26f0ef697775960db7932abeb7b516de930ba2705f/certifi-2025.1.31.tar.gz", hash = "sha256:3d5da6925056f6f18f119200434a4780a94263f10d1c21d032a6f6b2baa20651", size = 167577 }
32
+ wheels = [
33
+ { url = "https://pypi.tuna.tsinghua.edu.cn/packages/38/fc/bce832fd4fd99766c04d1ee0eead6b0ec6486fb100ae5e74c1d91292b982/certifi-2025.1.31-py3-none-any.whl", hash = "sha256:ca78db4565a652026a4db2bcdf68f2fb589ea80d0be70e03929ed730746b84fe", size = 166393 },
34
+ ]
35
+
36
+ [[package]]
37
+ name = "click"
38
+ version = "8.1.8"
39
+ source = { registry = "https://pypi.tuna.tsinghua.edu.cn/simple" }
40
+ dependencies = [
41
+ { name = "colorama", marker = "sys_platform == 'win32'" },
42
+ ]
43
+ sdist = { url = "https://pypi.tuna.tsinghua.edu.cn/packages/b9/2e/0090cbf739cee7d23781ad4b89a9894a41538e4fcf4c31dcdd705b78eb8b/click-8.1.8.tar.gz", hash = "sha256:ed53c9d8990d83c2a27deae68e4ee337473f6330c040a31d4225c9574d16096a", size = 226593 }
44
+ wheels = [
45
+ { url = "https://pypi.tuna.tsinghua.edu.cn/packages/7e/d4/7ebdbd03970677812aac39c869717059dbb71a4cfc033ca6e5221787892c/click-8.1.8-py3-none-any.whl", hash = "sha256:63c132bbbed01578a06712a2d1f497bb62d9c1c0d329b7903a866228027263b2", size = 98188 },
46
+ ]
47
+
48
+ [[package]]
49
+ name = "colorama"
50
+ version = "0.4.6"
51
+ source = { registry = "https://pypi.tuna.tsinghua.edu.cn/simple" }
52
+ sdist = { url = "https://pypi.tuna.tsinghua.edu.cn/packages/d8/53/6f443c9a4a8358a93a6792e2acffb9d9d5cb0a5cfd8802644b7b1c9a02e4/colorama-0.4.6.tar.gz", hash = "sha256:08695f5cb7ed6e0531a20572697297273c47b8cae5a63ffc6d6ed5c201be6e44", size = 27697 }
53
+ wheels = [
54
+ { url = "https://pypi.tuna.tsinghua.edu.cn/packages/d1/d6/3965ed04c63042e047cb6a3e6ed1a63a35087b6a609aa3a15ed8ac56c221/colorama-0.4.6-py2.py3-none-any.whl", hash = "sha256:4f1d9991f5acc0ca119f9d443620b77f9d6b33703e51011c16baf57afb285fc6", size = 25335 },
55
+ ]
56
+
57
+ [[package]]
58
+ name = "fastapi"
59
+ version = "0.115.12"
60
+ source = { registry = "https://pypi.tuna.tsinghua.edu.cn/simple" }
61
+ dependencies = [
62
+ { name = "pydantic" },
63
+ { name = "starlette" },
64
+ { name = "typing-extensions" },
65
+ ]
66
+ sdist = { url = "https://pypi.tuna.tsinghua.edu.cn/packages/f4/55/ae499352d82338331ca1e28c7f4a63bfd09479b16395dce38cf50a39e2c2/fastapi-0.115.12.tar.gz", hash = "sha256:1e2c2a2646905f9e83d32f04a3f86aff4a286669c6c950ca95b5fd68c2602681", size = 295236 }
67
+ wheels = [
68
+ { url = "https://pypi.tuna.tsinghua.edu.cn/packages/50/b3/b51f09c2ba432a576fe63758bddc81f78f0c6309d9e5c10d194313bf021e/fastapi-0.115.12-py3-none-any.whl", hash = "sha256:e94613d6c05e27be7ffebdd6ea5f388112e5e430c8f7d6494a9d1d88d43e814d", size = 95164 },
69
+ ]
70
+
71
+ [[package]]
72
+ name = "h11"
73
+ version = "0.14.0"
74
+ source = { registry = "https://pypi.tuna.tsinghua.edu.cn/simple" }
75
+ sdist = { url = "https://pypi.tuna.tsinghua.edu.cn/packages/f5/38/3af3d3633a34a3316095b39c8e8fb4853a28a536e55d347bd8d8e9a14b03/h11-0.14.0.tar.gz", hash = "sha256:8f19fbbe99e72420ff35c00b27a34cb9937e902a8b810e2c88300c6f0a3b699d", size = 100418 }
76
+ wheels = [
77
+ { url = "https://pypi.tuna.tsinghua.edu.cn/packages/95/04/ff642e65ad6b90db43e668d70ffb6736436c7ce41fcc549f4e9472234127/h11-0.14.0-py3-none-any.whl", hash = "sha256:e3fe4ac4b851c468cc8363d500db52c2ead036020723024a109d37346efaa761", size = 58259 },
78
+ ]
79
+
80
+ [[package]]
81
+ name = "httpcore"
82
+ version = "1.0.7"
83
+ source = { registry = "https://pypi.tuna.tsinghua.edu.cn/simple" }
84
+ dependencies = [
85
+ { name = "certifi" },
86
+ { name = "h11" },
87
+ ]
88
+ sdist = { url = "https://pypi.tuna.tsinghua.edu.cn/packages/6a/41/d7d0a89eb493922c37d343b607bc1b5da7f5be7e383740b4753ad8943e90/httpcore-1.0.7.tar.gz", hash = "sha256:8551cb62a169ec7162ac7be8d4817d561f60e08eaa485234898414bb5a8a0b4c", size = 85196 }
89
+ wheels = [
90
+ { url = "https://pypi.tuna.tsinghua.edu.cn/packages/87/f5/72347bc88306acb359581ac4d52f23c0ef445b57157adedb9aee0cd689d2/httpcore-1.0.7-py3-none-any.whl", hash = "sha256:a3fff8f43dc260d5bd363d9f9cf1830fa3a458b332856f34282de498ed420edd", size = 78551 },
91
+ ]
92
+
93
+ [[package]]
94
+ name = "httpx"
95
+ version = "0.28.1"
96
+ source = { registry = "https://pypi.tuna.tsinghua.edu.cn/simple" }
97
+ dependencies = [
98
+ { name = "anyio" },
99
+ { name = "certifi" },
100
+ { name = "httpcore" },
101
+ { name = "idna" },
102
+ ]
103
+ sdist = { url = "https://pypi.tuna.tsinghua.edu.cn/packages/b1/df/48c586a5fe32a0f01324ee087459e112ebb7224f646c0b5023f5e79e9956/httpx-0.28.1.tar.gz", hash = "sha256:75e98c5f16b0f35b567856f597f06ff2270a374470a5c2392242528e3e3e42fc", size = 141406 }
104
+ wheels = [
105
+ { url = "https://pypi.tuna.tsinghua.edu.cn/packages/2a/39/e50c7c3a983047577ee07d2a9e53faf5a69493943ec3f6a384bdc792deb2/httpx-0.28.1-py3-none-any.whl", hash = "sha256:d909fcccc110f8c7faf814ca82a9a4d816bc5a6dbfea25d6591d6985b8ba59ad", size = 73517 },
106
+ ]
107
+
108
+ [[package]]
109
+ name = "httpx-sse"
110
+ version = "0.4.0"
111
+ source = { registry = "https://pypi.tuna.tsinghua.edu.cn/simple" }
112
+ sdist = { url = "https://pypi.tuna.tsinghua.edu.cn/packages/4c/60/8f4281fa9bbf3c8034fd54c0e7412e66edbab6bc74c4996bd616f8d0406e/httpx-sse-0.4.0.tar.gz", hash = "sha256:1e81a3a3070ce322add1d3529ed42eb5f70817f45ed6ec915ab753f961139721", size = 12624 }
113
+ wheels = [
114
+ { url = "https://pypi.tuna.tsinghua.edu.cn/packages/e1/9b/a181f281f65d776426002f330c31849b86b31fc9d848db62e16f03ff739f/httpx_sse-0.4.0-py3-none-any.whl", hash = "sha256:f329af6eae57eaa2bdfd962b42524764af68075ea87370a2de920af5341e318f", size = 7819 },
115
+ ]
116
+
117
+ [[package]]
118
+ name = "idna"
119
+ version = "3.10"
120
+ source = { registry = "https://pypi.tuna.tsinghua.edu.cn/simple" }
121
+ sdist = { url = "https://pypi.tuna.tsinghua.edu.cn/packages/f1/70/7703c29685631f5a7590aa73f1f1d3fa9a380e654b86af429e0934a32f7d/idna-3.10.tar.gz", hash = "sha256:12f65c9b470abda6dc35cf8e63cc574b1c52b11df2c86030af0ac09b01b13ea9", size = 190490 }
122
+ wheels = [
123
+ { url = "https://pypi.tuna.tsinghua.edu.cn/packages/76/c6/c88e154df9c4e1a2a66ccf0005a88dfb2650c1dffb6f5ce603dfbd452ce3/idna-3.10-py3-none-any.whl", hash = "sha256:946d195a0d259cbba61165e88e65941f16e9b36ea6ddb97f00452bae8b1287d3", size = 70442 },
124
+ ]
125
+
126
+ [[package]]
127
+ name = "pydantic"
128
+ version = "2.11.2"
129
+ source = { registry = "https://pypi.tuna.tsinghua.edu.cn/simple" }
130
+ dependencies = [
131
+ { name = "annotated-types" },
132
+ { name = "pydantic-core" },
133
+ { name = "typing-extensions" },
134
+ { name = "typing-inspection" },
135
+ ]
136
+ sdist = { url = "https://pypi.tuna.tsinghua.edu.cn/packages/b0/41/832125a41fe098b58d1fdd04ae819b4dc6b34d6b09ed78304fd93d4bc051/pydantic-2.11.2.tar.gz", hash = "sha256:2138628e050bd7a1e70b91d4bf4a91167f4ad76fdb83209b107c8d84b854917e", size = 784742 }
137
+ wheels = [
138
+ { url = "https://pypi.tuna.tsinghua.edu.cn/packages/bf/c2/0f3baea344d0b15e35cb3e04ad5b953fa05106b76efbf4c782a3f47f22f5/pydantic-2.11.2-py3-none-any.whl", hash = "sha256:7f17d25846bcdf89b670a86cdfe7b29a9f1c9ca23dee154221c9aa81845cfca7", size = 443295 },
139
+ ]
140
+
141
+ [[package]]
142
+ name = "pydantic-core"
143
+ version = "2.33.1"
144
+ source = { registry = "https://pypi.tuna.tsinghua.edu.cn/simple" }
145
+ dependencies = [
146
+ { name = "typing-extensions" },
147
+ ]
148
+ sdist = { url = "https://pypi.tuna.tsinghua.edu.cn/packages/17/19/ed6a078a5287aea7922de6841ef4c06157931622c89c2a47940837b5eecd/pydantic_core-2.33.1.tar.gz", hash = "sha256:bcc9c6fdb0ced789245b02b7d6603e17d1563064ddcfc36f046b61c0c05dd9df", size = 434395 }
149
+ wheels = [
150
+ { url = "https://pypi.tuna.tsinghua.edu.cn/packages/7a/24/eed3466a4308d79155f1cdd5c7432c80ddcc4530ba8623b79d5ced021641/pydantic_core-2.33.1-cp313-cp313-macosx_10_12_x86_64.whl", hash = "sha256:70af6a21237b53d1fe7b9325b20e65cbf2f0a848cf77bed492b029139701e66a", size = 2033551 },
151
+ { url = "https://pypi.tuna.tsinghua.edu.cn/packages/ab/14/df54b1a0bc9b6ded9b758b73139d2c11b4e8eb43e8ab9c5847c0a2913ada/pydantic_core-2.33.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:282b3fe1bbbe5ae35224a0dbd05aed9ccabccd241e8e6b60370484234b456266", size = 1852785 },
152
+ { url = "https://pypi.tuna.tsinghua.edu.cn/packages/fa/96/e275f15ff3d34bb04b0125d9bc8848bf69f25d784d92a63676112451bfb9/pydantic_core-2.33.1-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4b315e596282bbb5822d0c7ee9d255595bd7506d1cb20c2911a4da0b970187d3", size = 1897758 },
153
+ { url = "https://pypi.tuna.tsinghua.edu.cn/packages/b7/d8/96bc536e975b69e3a924b507d2a19aedbf50b24e08c80fb00e35f9baaed8/pydantic_core-2.33.1-cp313-cp313-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:1dfae24cf9921875ca0ca6a8ecb4bb2f13c855794ed0d468d6abbec6e6dcd44a", size = 1986109 },
154
+ { url = "https://pypi.tuna.tsinghua.edu.cn/packages/90/72/ab58e43ce7e900b88cb571ed057b2fcd0e95b708a2e0bed475b10130393e/pydantic_core-2.33.1-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:6dd8ecfde08d8bfadaea669e83c63939af76f4cf5538a72597016edfa3fad516", size = 2129159 },
155
+ { url = "https://pypi.tuna.tsinghua.edu.cn/packages/dc/3f/52d85781406886c6870ac995ec0ba7ccc028b530b0798c9080531b409fdb/pydantic_core-2.33.1-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:2f593494876eae852dc98c43c6f260f45abdbfeec9e4324e31a481d948214764", size = 2680222 },
156
+ { url = "https://pypi.tuna.tsinghua.edu.cn/packages/f4/56/6e2ef42f363a0eec0fd92f74a91e0ac48cd2e49b695aac1509ad81eee86a/pydantic_core-2.33.1-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:948b73114f47fd7016088e5186d13faf5e1b2fe83f5e320e371f035557fd264d", size = 2006980 },
157
+ { url = "https://pypi.tuna.tsinghua.edu.cn/packages/4c/c0/604536c4379cc78359f9ee0aa319f4aedf6b652ec2854953f5a14fc38c5a/pydantic_core-2.33.1-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:e11f3864eb516af21b01e25fac915a82e9ddad3bb0fb9e95a246067398b435a4", size = 2120840 },
158
+ { url = "https://pypi.tuna.tsinghua.edu.cn/packages/1f/46/9eb764814f508f0edfb291a0f75d10854d78113fa13900ce13729aaec3ae/pydantic_core-2.33.1-cp313-cp313-musllinux_1_1_aarch64.whl", hash = "sha256:549150be302428b56fdad0c23c2741dcdb5572413776826c965619a25d9c6bde", size = 2072518 },
159
+ { url = "https://pypi.tuna.tsinghua.edu.cn/packages/42/e3/fb6b2a732b82d1666fa6bf53e3627867ea3131c5f39f98ce92141e3e3dc1/pydantic_core-2.33.1-cp313-cp313-musllinux_1_1_armv7l.whl", hash = "sha256:495bc156026efafd9ef2d82372bd38afce78ddd82bf28ef5276c469e57c0c83e", size = 2248025 },
160
+ { url = "https://pypi.tuna.tsinghua.edu.cn/packages/5c/9d/fbe8fe9d1aa4dac88723f10a921bc7418bd3378a567cb5e21193a3c48b43/pydantic_core-2.33.1-cp313-cp313-musllinux_1_1_x86_64.whl", hash = "sha256:ec79de2a8680b1a67a07490bddf9636d5c2fab609ba8c57597e855fa5fa4dacd", size = 2254991 },
161
+ { url = "https://pypi.tuna.tsinghua.edu.cn/packages/aa/99/07e2237b8a66438d9b26482332cda99a9acccb58d284af7bc7c946a42fd3/pydantic_core-2.33.1-cp313-cp313-win32.whl", hash = "sha256:ee12a7be1742f81b8a65b36c6921022301d466b82d80315d215c4c691724986f", size = 1915262 },
162
+ { url = "https://pypi.tuna.tsinghua.edu.cn/packages/8a/f4/e457a7849beeed1e5defbcf5051c6f7b3c91a0624dd31543a64fc9adcf52/pydantic_core-2.33.1-cp313-cp313-win_amd64.whl", hash = "sha256:ede9b407e39949d2afc46385ce6bd6e11588660c26f80576c11c958e6647bc40", size = 1956626 },
163
+ { url = "https://pypi.tuna.tsinghua.edu.cn/packages/20/d0/e8d567a7cff7b04e017ae164d98011f1e1894269fe8e90ea187a3cbfb562/pydantic_core-2.33.1-cp313-cp313-win_arm64.whl", hash = "sha256:aa687a23d4b7871a00e03ca96a09cad0f28f443690d300500603bd0adba4b523", size = 1909590 },
164
+ { url = "https://pypi.tuna.tsinghua.edu.cn/packages/ef/fd/24ea4302d7a527d672c5be06e17df16aabfb4e9fdc6e0b345c21580f3d2a/pydantic_core-2.33.1-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:401d7b76e1000d0dd5538e6381d28febdcacb097c8d340dde7d7fc6e13e9f95d", size = 1812963 },
165
+ { url = "https://pypi.tuna.tsinghua.edu.cn/packages/5f/95/4fbc2ecdeb5c1c53f1175a32d870250194eb2fdf6291b795ab08c8646d5d/pydantic_core-2.33.1-cp313-cp313t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7aeb055a42d734c0255c9e489ac67e75397d59c6fbe60d155851e9782f276a9c", size = 1986896 },
166
+ { url = "https://pypi.tuna.tsinghua.edu.cn/packages/71/ae/fe31e7f4a62431222d8f65a3bd02e3fa7e6026d154a00818e6d30520ea77/pydantic_core-2.33.1-cp313-cp313t-win_amd64.whl", hash = "sha256:338ea9b73e6e109f15ab439e62cb3b78aa752c7fd9536794112e14bee02c8d18", size = 1931810 },
167
+ ]
168
+
169
+ [[package]]
170
+ name = "python-dotenv"
171
+ version = "1.1.0"
172
+ source = { registry = "https://pypi.tuna.tsinghua.edu.cn/simple" }
173
+ sdist = { url = "https://pypi.tuna.tsinghua.edu.cn/packages/88/2c/7bb1416c5620485aa793f2de31d3df393d3686aa8a8506d11e10e13c5baf/python_dotenv-1.1.0.tar.gz", hash = "sha256:41f90bc6f5f177fb41f53e87666db362025010eb28f60a01c9143bfa33a2b2d5", size = 39920 }
174
+ wheels = [
175
+ { url = "https://pypi.tuna.tsinghua.edu.cn/packages/1e/18/98a99ad95133c6a6e2005fe89faedf294a748bd5dc803008059409ac9b1e/python_dotenv-1.1.0-py3-none-any.whl", hash = "sha256:d7c01d9e2293916c18baf562d95698754b0dbbb5e74d457c45d4f6561fb9d55d", size = 20256 },
176
+ ]
177
+
178
+ [[package]]
179
+ name = "sniffio"
180
+ version = "1.3.1"
181
+ source = { registry = "https://pypi.tuna.tsinghua.edu.cn/simple" }
182
+ sdist = { url = "https://pypi.tuna.tsinghua.edu.cn/packages/a2/87/a6771e1546d97e7e041b6ae58d80074f81b7d5121207425c964ddf5cfdbd/sniffio-1.3.1.tar.gz", hash = "sha256:f4324edc670a0f49750a81b895f35c3adb843cca46f0530f79fc1babb23789dc", size = 20372 }
183
+ wheels = [
184
+ { url = "https://pypi.tuna.tsinghua.edu.cn/packages/e9/44/75a9c9421471a6c4805dbf2356f7c181a29c1879239abab1ea2cc8f38b40/sniffio-1.3.1-py3-none-any.whl", hash = "sha256:2f6da418d1f1e0fddd844478f41680e794e6051915791a034ff65e5f100525a2", size = 10235 },
185
+ ]
186
+
187
+ [[package]]
188
+ name = "starlette"
189
+ version = "0.46.1"
190
+ source = { registry = "https://pypi.tuna.tsinghua.edu.cn/simple" }
191
+ dependencies = [
192
+ { name = "anyio" },
193
+ ]
194
+ sdist = { url = "https://pypi.tuna.tsinghua.edu.cn/packages/04/1b/52b27f2e13ceedc79a908e29eac426a63465a1a01248e5f24aa36a62aeb3/starlette-0.46.1.tar.gz", hash = "sha256:3c88d58ee4bd1bb807c0d1acb381838afc7752f9ddaec81bbe4383611d833230", size = 2580102 }
195
+ wheels = [
196
+ { url = "https://pypi.tuna.tsinghua.edu.cn/packages/a0/4b/528ccf7a982216885a1ff4908e886b8fb5f19862d1962f56a3fce2435a70/starlette-0.46.1-py3-none-any.whl", hash = "sha256:77c74ed9d2720138b25875133f3a2dae6d854af2ec37dceb56aef370c1d8a227", size = 71995 },
197
+ ]
198
+
199
+ [[package]]
200
+ name = "trae-api"
201
+ version = "0.1.0"
202
+ source = { virtual = "." }
203
+ dependencies = [
204
+ { name = "fastapi" },
205
+ { name = "httpx" },
206
+ { name = "httpx-sse" },
207
+ { name = "python-dotenv" },
208
+ { name = "uvicorn" },
209
+ ]
210
+
211
+ [package.metadata]
212
+ requires-dist = [
213
+ { name = "fastapi", specifier = ">=0.115.12" },
214
+ { name = "httpx", specifier = ">=0.28.1" },
215
+ { name = "httpx-sse", specifier = ">=0.4.0" },
216
+ { name = "python-dotenv", specifier = ">=1.1.0" },
217
+ { name = "uvicorn", specifier = ">=0.34.0" },
218
+ ]
219
+
220
+ [[package]]
221
+ name = "typing-extensions"
222
+ version = "4.13.1"
223
+ source = { registry = "https://pypi.tuna.tsinghua.edu.cn/simple" }
224
+ sdist = { url = "https://pypi.tuna.tsinghua.edu.cn/packages/76/ad/cd3e3465232ec2416ae9b983f27b9e94dc8171d56ac99b345319a9475967/typing_extensions-4.13.1.tar.gz", hash = "sha256:98795af00fb9640edec5b8e31fc647597b4691f099ad75f469a2616be1a76dff", size = 106633 }
225
+ wheels = [
226
+ { url = "https://pypi.tuna.tsinghua.edu.cn/packages/df/c5/e7a0b0f5ed69f94c8ab7379c599e6036886bffcde609969a5325f47f1332/typing_extensions-4.13.1-py3-none-any.whl", hash = "sha256:4b6cf02909eb5495cfbc3f6e8fd49217e6cc7944e145cdda8caa3734777f9e69", size = 45739 },
227
+ ]
228
+
229
+ [[package]]
230
+ name = "typing-inspection"
231
+ version = "0.4.0"
232
+ source = { registry = "https://pypi.tuna.tsinghua.edu.cn/simple" }
233
+ dependencies = [
234
+ { name = "typing-extensions" },
235
+ ]
236
+ sdist = { url = "https://pypi.tuna.tsinghua.edu.cn/packages/82/5c/e6082df02e215b846b4b8c0b887a64d7d08ffaba30605502639d44c06b82/typing_inspection-0.4.0.tar.gz", hash = "sha256:9765c87de36671694a67904bf2c96e395be9c6439bb6c87b5142569dcdd65122", size = 76222 }
237
+ wheels = [
238
+ { url = "https://pypi.tuna.tsinghua.edu.cn/packages/31/08/aa4fdfb71f7de5176385bd9e90852eaf6b5d622735020ad600f2bab54385/typing_inspection-0.4.0-py3-none-any.whl", hash = "sha256:50e72559fcd2a6367a19f7a7e610e6afcb9fac940c650290eed893d61386832f", size = 14125 },
239
+ ]
240
+
241
+ [[package]]
242
+ name = "uvicorn"
243
+ version = "0.34.0"
244
+ source = { registry = "https://pypi.tuna.tsinghua.edu.cn/simple" }
245
+ dependencies = [
246
+ { name = "click" },
247
+ { name = "h11" },
248
+ ]
249
+ sdist = { url = "https://pypi.tuna.tsinghua.edu.cn/packages/4b/4d/938bd85e5bf2edeec766267a5015ad969730bb91e31b44021dfe8b22df6c/uvicorn-0.34.0.tar.gz", hash = "sha256:404051050cd7e905de2c9a7e61790943440b3416f49cb409f965d9dcd0fa73e9", size = 76568 }
250
+ wheels = [
251
+ { url = "https://pypi.tuna.tsinghua.edu.cn/packages/61/14/33a3a1352cfa71812a3a21e8c9bfb83f60b0011f5e36f2b1399d51928209/uvicorn-0.34.0-py3-none-any.whl", hash = "sha256:023dc038422502fa28a09c7a30bf2b6991512da7dcdb8fd35fe57cfc154126f4", size = 62315 },
252
+ ]