auto-coder-web 0.1.109__py3-none-any.whl → 0.1.111__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- auto_coder_web/auto_coder_runner_wrapper.py +7 -3
- auto_coder_web/common_router/lib_router.py +325 -0
- auto_coder_web/common_router/model_router.py +16 -0
- auto_coder_web/proxy.py +5 -1
- auto_coder_web/version.py +1 -1
- auto_coder_web/web/assets/{main-BtXMe4GC.css → main-DruTAIag.css} +2 -2
- auto_coder_web/web/assets/main.js +373 -373
- auto_coder_web/web/index.html +1 -1
- {auto_coder_web-0.1.109.dist-info → auto_coder_web-0.1.111.dist-info}/METADATA +2 -2
- {auto_coder_web-0.1.109.dist-info → auto_coder_web-0.1.111.dist-info}/RECORD +13 -12
- {auto_coder_web-0.1.109.dist-info → auto_coder_web-0.1.111.dist-info}/WHEEL +0 -0
- {auto_coder_web-0.1.109.dist-info → auto_coder_web-0.1.111.dist-info}/entry_points.txt +0 -0
- {auto_coder_web-0.1.109.dist-info → auto_coder_web-0.1.111.dist-info}/top_level.txt +0 -0
@@ -61,12 +61,16 @@ class AutoCoderRunnerWrapper:
|
|
61
61
|
memory = get_memory()
|
62
62
|
return memory["conf"]
|
63
63
|
|
64
|
+
def get_memory_wrapper(self):
|
65
|
+
return get_memory()
|
64
66
|
|
65
67
|
def coding_wapper(self,query):
|
66
68
|
return coding(query)
|
67
69
|
|
68
70
|
def chat_wrapper(self,query):
|
69
|
-
return chat(query)
|
70
|
-
|
71
|
-
|
71
|
+
return chat(query)
|
72
|
+
|
73
|
+
def lib_wrapper(self,query):
|
74
|
+
return lib_command(query)
|
75
|
+
|
72
76
|
|
@@ -0,0 +1,325 @@
|
|
1
|
+
from fastapi import APIRouter, Depends, Request, HTTPException, Body
|
2
|
+
from pydantic import BaseModel
|
3
|
+
from typing import Dict, List, Optional
|
4
|
+
import os
|
5
|
+
import git
|
6
|
+
import json
|
7
|
+
from pathlib import Path
|
8
|
+
from autocoder.auto_coder_runner import get_memory, save_memory_with_new_memory
|
9
|
+
|
10
|
+
router = APIRouter()
|
11
|
+
|
12
|
+
# 定义依赖项函数
|
13
|
+
async def get_project_path(request: Request) -> str:
|
14
|
+
"""获取项目路径作为依赖"""
|
15
|
+
return request.app.state.project_path
|
16
|
+
|
17
|
+
|
18
|
+
# 模型定义
|
19
|
+
class LibAddRequest(BaseModel):
|
20
|
+
lib_name: str
|
21
|
+
|
22
|
+
class LibRemoveRequest(BaseModel):
|
23
|
+
lib_name: str
|
24
|
+
|
25
|
+
class LibProxyRequest(BaseModel):
|
26
|
+
proxy_url: Optional[str] = None
|
27
|
+
|
28
|
+
class LibGetRequest(BaseModel):
|
29
|
+
package_name: str
|
30
|
+
|
31
|
+
class LibResponse(BaseModel):
|
32
|
+
success: bool
|
33
|
+
message: str
|
34
|
+
data: Optional[Dict] = None
|
35
|
+
|
36
|
+
class LibItem(BaseModel):
|
37
|
+
domain: str
|
38
|
+
username: str
|
39
|
+
lib_name: str
|
40
|
+
full_path: str
|
41
|
+
is_added: bool
|
42
|
+
|
43
|
+
@router.get("/api/lib/list", response_model=LibResponse)
|
44
|
+
async def list_libs(
|
45
|
+
request: Request,
|
46
|
+
memory: Dict = Depends(get_memory)
|
47
|
+
):
|
48
|
+
"""列出所有已添加的库"""
|
49
|
+
libs = memory.get("libs", {})
|
50
|
+
|
51
|
+
return LibResponse(
|
52
|
+
success=True,
|
53
|
+
message="Libraries retrieved successfully",
|
54
|
+
data={"libraries": list(libs.keys())}
|
55
|
+
)
|
56
|
+
|
57
|
+
@router.post("/api/lib/add", response_model=LibResponse)
|
58
|
+
async def add_lib(
|
59
|
+
request: Request,
|
60
|
+
lib_request: LibAddRequest,
|
61
|
+
memory: Dict = Depends(get_memory),
|
62
|
+
project_path: str = Depends(get_project_path)
|
63
|
+
):
|
64
|
+
"""添加一个库"""
|
65
|
+
lib_name = lib_request.lib_name.strip()
|
66
|
+
|
67
|
+
# 初始化目录
|
68
|
+
lib_dir = os.path.join(project_path, ".auto-coder", "libs")
|
69
|
+
llm_friendly_packages_dir = os.path.join(lib_dir, "llm_friendly_packages")
|
70
|
+
|
71
|
+
if not os.path.exists(lib_dir):
|
72
|
+
os.makedirs(lib_dir, exist_ok=True)
|
73
|
+
|
74
|
+
if "libs" not in memory:
|
75
|
+
memory["libs"] = {}
|
76
|
+
|
77
|
+
# 已存在的库直接返回
|
78
|
+
if lib_name in memory["libs"]:
|
79
|
+
return LibResponse(
|
80
|
+
success=True,
|
81
|
+
message=f"Library {lib_name} is already added"
|
82
|
+
)
|
83
|
+
|
84
|
+
# 克隆仓库(如果不存在)
|
85
|
+
if not os.path.exists(llm_friendly_packages_dir):
|
86
|
+
try:
|
87
|
+
proxy_url = memory.get(
|
88
|
+
"lib-proxy", "https://github.com/allwefantasy/llm_friendly_packages"
|
89
|
+
)
|
90
|
+
git.Repo.clone_from(
|
91
|
+
proxy_url,
|
92
|
+
llm_friendly_packages_dir,
|
93
|
+
)
|
94
|
+
except git.exc.GitCommandError as e:
|
95
|
+
return LibResponse(
|
96
|
+
success=False,
|
97
|
+
message=f"Error cloning repository: {str(e)}"
|
98
|
+
)
|
99
|
+
|
100
|
+
# 添加库到内存
|
101
|
+
memory["libs"][lib_name] = {}
|
102
|
+
await save_memory_with_new_memory(memory)
|
103
|
+
|
104
|
+
return LibResponse(
|
105
|
+
success=True,
|
106
|
+
message=f"Added library: {lib_name}"
|
107
|
+
)
|
108
|
+
|
109
|
+
@router.post("/api/lib/remove", response_model=LibResponse)
|
110
|
+
async def remove_lib(
|
111
|
+
request: Request,
|
112
|
+
lib_request: LibRemoveRequest,
|
113
|
+
memory: Dict = Depends(get_memory)
|
114
|
+
):
|
115
|
+
"""移除一个库"""
|
116
|
+
lib_name = lib_request.lib_name.strip()
|
117
|
+
|
118
|
+
if "libs" not in memory:
|
119
|
+
memory["libs"] = {}
|
120
|
+
|
121
|
+
if lib_name in memory["libs"]:
|
122
|
+
del memory["libs"][lib_name]
|
123
|
+
await save_memory_with_new_memory(memory)
|
124
|
+
return LibResponse(
|
125
|
+
success=True,
|
126
|
+
message=f"Removed library: {lib_name}"
|
127
|
+
)
|
128
|
+
else:
|
129
|
+
return LibResponse(
|
130
|
+
success=False,
|
131
|
+
message=f"Library {lib_name} is not in the list"
|
132
|
+
)
|
133
|
+
|
134
|
+
@router.post("/api/lib/set-proxy", response_model=LibResponse)
|
135
|
+
async def set_proxy(
|
136
|
+
request: Request,
|
137
|
+
proxy_request: LibProxyRequest = Body(None),
|
138
|
+
memory: Dict = Depends(get_memory)
|
139
|
+
):
|
140
|
+
"""设置代理URL"""
|
141
|
+
if proxy_request is None or proxy_request.proxy_url is None:
|
142
|
+
# 获取当前代理
|
143
|
+
current_proxy = memory.get("lib-proxy", "No proxy set")
|
144
|
+
return LibResponse(
|
145
|
+
success=True,
|
146
|
+
message=f"Current proxy: {current_proxy}",
|
147
|
+
data={"proxy": current_proxy}
|
148
|
+
)
|
149
|
+
else:
|
150
|
+
# 设置代理
|
151
|
+
memory["lib-proxy"] = proxy_request.proxy_url
|
152
|
+
await save_memory_with_new_memory(memory)
|
153
|
+
return LibResponse(
|
154
|
+
success=True,
|
155
|
+
message=f"Set proxy to: {proxy_request.proxy_url}"
|
156
|
+
)
|
157
|
+
|
158
|
+
@router.post("/api/lib/refresh", response_model=LibResponse)
|
159
|
+
async def refresh_lib(
|
160
|
+
request: Request,
|
161
|
+
memory: Dict = Depends(get_memory),
|
162
|
+
project_path: str = Depends(get_project_path)
|
163
|
+
):
|
164
|
+
"""刷新llm_friendly_packages仓库"""
|
165
|
+
llm_friendly_packages_dir = os.path.join(project_path, ".auto-coder", "libs", "llm_friendly_packages")
|
166
|
+
|
167
|
+
if not os.path.exists(llm_friendly_packages_dir):
|
168
|
+
return LibResponse(
|
169
|
+
success=False,
|
170
|
+
message="llm_friendly_packages repository does not exist. Please add a library first to clone it."
|
171
|
+
)
|
172
|
+
|
173
|
+
try:
|
174
|
+
repo = git.Repo(llm_friendly_packages_dir)
|
175
|
+
origin = repo.remotes.origin
|
176
|
+
proxy_url = memory.get("lib-proxy")
|
177
|
+
|
178
|
+
current_url = origin.url
|
179
|
+
|
180
|
+
if proxy_url and proxy_url != current_url:
|
181
|
+
new_url = proxy_url
|
182
|
+
origin.set_url(new_url)
|
183
|
+
|
184
|
+
origin.pull()
|
185
|
+
return LibResponse(
|
186
|
+
success=True,
|
187
|
+
message="Successfully updated llm_friendly_packages repository"
|
188
|
+
)
|
189
|
+
except git.exc.GitCommandError as e:
|
190
|
+
return LibResponse(
|
191
|
+
success=False,
|
192
|
+
message=f"Error updating repository: {str(e)}"
|
193
|
+
)
|
194
|
+
|
195
|
+
@router.post("/api/lib/get", response_model=LibResponse)
|
196
|
+
async def get_lib_docs(
|
197
|
+
request: Request,
|
198
|
+
get_request: LibGetRequest,
|
199
|
+
project_path: str = Depends(get_project_path),
|
200
|
+
memory: Dict = Depends(get_memory)
|
201
|
+
):
|
202
|
+
"""获取特定包的文档"""
|
203
|
+
package_name = get_request.package_name.strip()
|
204
|
+
|
205
|
+
# 使用与auto_coder_runner中相似的逻辑
|
206
|
+
lib_dir = os.path.join(project_path, ".auto-coder", "libs")
|
207
|
+
llm_friendly_packages_dir = os.path.join(lib_dir, "llm_friendly_packages")
|
208
|
+
docs = []
|
209
|
+
|
210
|
+
if not os.path.exists(llm_friendly_packages_dir):
|
211
|
+
return LibResponse(
|
212
|
+
success=False,
|
213
|
+
message="llm_friendly_packages repository does not exist"
|
214
|
+
)
|
215
|
+
|
216
|
+
libs = list(memory.get("libs", {}).keys())
|
217
|
+
|
218
|
+
for domain in os.listdir(llm_friendly_packages_dir):
|
219
|
+
domain_path = os.path.join(llm_friendly_packages_dir, domain)
|
220
|
+
if os.path.isdir(domain_path):
|
221
|
+
for username in os.listdir(domain_path):
|
222
|
+
username_path = os.path.join(domain_path, username)
|
223
|
+
if os.path.isdir(username_path):
|
224
|
+
for lib_name in os.listdir(username_path):
|
225
|
+
lib_path = os.path.join(username_path, lib_name)
|
226
|
+
if (
|
227
|
+
os.path.isdir(lib_path)
|
228
|
+
and (
|
229
|
+
package_name is None
|
230
|
+
or lib_name == package_name
|
231
|
+
or package_name == os.path.join(username, lib_name)
|
232
|
+
)
|
233
|
+
and lib_name in libs
|
234
|
+
):
|
235
|
+
for root, _, files in os.walk(lib_path):
|
236
|
+
for file in files:
|
237
|
+
if file.endswith(".md"):
|
238
|
+
file_path = os.path.join(root, file)
|
239
|
+
docs.append(str(Path(file_path).relative_to(project_path)))
|
240
|
+
|
241
|
+
if docs:
|
242
|
+
return LibResponse(
|
243
|
+
success=True,
|
244
|
+
message=f"Found {len(docs)} markdown files for package: {package_name}",
|
245
|
+
data={"docs": docs}
|
246
|
+
)
|
247
|
+
else:
|
248
|
+
return LibResponse(
|
249
|
+
success=False,
|
250
|
+
message=f"No markdown files found for package: {package_name}"
|
251
|
+
)
|
252
|
+
|
253
|
+
@router.get("/api/lib/list-all", response_model=LibResponse)
|
254
|
+
async def list_all_libs(
|
255
|
+
request: Request,
|
256
|
+
memory: Dict = Depends(get_memory),
|
257
|
+
project_path: str = Depends(get_project_path)
|
258
|
+
):
|
259
|
+
"""列出所有可用的库,包括未添加的库"""
|
260
|
+
lib_dir = os.path.join(project_path, ".auto-coder", "libs")
|
261
|
+
llm_friendly_packages_dir = os.path.join(lib_dir, "llm_friendly_packages")
|
262
|
+
available_libs = []
|
263
|
+
|
264
|
+
# 如果仓库不存在,自动下载
|
265
|
+
if not os.path.exists(llm_friendly_packages_dir):
|
266
|
+
if not os.path.exists(lib_dir):
|
267
|
+
os.makedirs(lib_dir, exist_ok=True)
|
268
|
+
|
269
|
+
try:
|
270
|
+
# 获取代理URL(如果已设置)
|
271
|
+
proxy_url = memory.get(
|
272
|
+
"lib-proxy", "https://github.com/allwefantasy/llm_friendly_packages"
|
273
|
+
)
|
274
|
+
# 克隆仓库
|
275
|
+
git.Repo.clone_from(
|
276
|
+
proxy_url,
|
277
|
+
llm_friendly_packages_dir,
|
278
|
+
)
|
279
|
+
except git.exc.GitCommandError as e:
|
280
|
+
return LibResponse(
|
281
|
+
success=False,
|
282
|
+
message=f"Error cloning repository: {str(e)}",
|
283
|
+
data={"libraries": []}
|
284
|
+
)
|
285
|
+
|
286
|
+
# 获取已添加的库列表
|
287
|
+
added_libs = set(memory.get("libs", {}).keys())
|
288
|
+
|
289
|
+
# 遍历所有domain目录
|
290
|
+
for domain in os.listdir(llm_friendly_packages_dir):
|
291
|
+
domain_path = os.path.join(llm_friendly_packages_dir, domain)
|
292
|
+
if os.path.isdir(domain_path):
|
293
|
+
# 遍历所有username目录
|
294
|
+
for username in os.listdir(domain_path):
|
295
|
+
username_path = os.path.join(domain_path, username)
|
296
|
+
if os.path.isdir(username_path):
|
297
|
+
# 遍历所有lib_name目录
|
298
|
+
for lib_name in os.listdir(username_path):
|
299
|
+
lib_path = os.path.join(username_path, lib_name)
|
300
|
+
if os.path.isdir(lib_path):
|
301
|
+
# 检查是否有Markdown文件
|
302
|
+
has_md_files = False
|
303
|
+
for root, _, files in os.walk(lib_path):
|
304
|
+
if any(file.endswith('.md') for file in files):
|
305
|
+
has_md_files = True
|
306
|
+
break
|
307
|
+
|
308
|
+
if has_md_files:
|
309
|
+
lib_item = LibItem(
|
310
|
+
domain=domain,
|
311
|
+
username=username,
|
312
|
+
lib_name=lib_name,
|
313
|
+
full_path=f"{username}/{lib_name}",
|
314
|
+
is_added=lib_name in added_libs
|
315
|
+
)
|
316
|
+
available_libs.append(lib_item.dict())
|
317
|
+
|
318
|
+
# 按domain和username分组排序
|
319
|
+
available_libs.sort(key=lambda x: (x["domain"], x["username"], x["lib_name"]))
|
320
|
+
|
321
|
+
return LibResponse(
|
322
|
+
success=True,
|
323
|
+
message=f"Found {len(available_libs)} available libraries",
|
324
|
+
data={"libraries": available_libs}
|
325
|
+
)
|
@@ -264,6 +264,22 @@ def load_providers() -> List[Dict]:
|
|
264
264
|
"output_price": 0.0,
|
265
265
|
"is_reasoning": False,
|
266
266
|
"max_output_tokens": 8096*2
|
267
|
+
},
|
268
|
+
{
|
269
|
+
"id": "anthropic/claude-sonnet-4",
|
270
|
+
"name": "claude-sonnet-4",
|
271
|
+
"input_price": 22.0,
|
272
|
+
"output_price": 111.0,
|
273
|
+
"is_reasoning": False,
|
274
|
+
"max_output_tokens": 8096*4
|
275
|
+
},
|
276
|
+
{
|
277
|
+
"id": "anthropic/claude-opus-4",
|
278
|
+
"name": "claude-opus-4",
|
279
|
+
"input_price": 111.0,
|
280
|
+
"output_price": 555.0,
|
281
|
+
"is_reasoning": False,
|
282
|
+
"max_output_tokens": 8096*4
|
267
283
|
}
|
268
284
|
]
|
269
285
|
},
|
auto_coder_web/proxy.py
CHANGED
@@ -21,7 +21,7 @@ from autocoder.common import AutoCoderArgs
|
|
21
21
|
from auto_coder_web.auto_coder_runner_wrapper import AutoCoderRunnerWrapper
|
22
22
|
from auto_coder_web.routers import todo_router, settings_router, auto_router, commit_router, chat_router, coding_router, index_router, config_router, upload_router, rag_router, editable_preview_router, mcp_router, direct_chat_router, rules_router, chat_panels_router, code_editor_tabs_router, file_command_router
|
23
23
|
from auto_coder_web.expert_routers import history_router
|
24
|
-
from auto_coder_web.common_router import completions_router, file_router, auto_coder_conf_router, chat_list_router, file_group_router, model_router, compiler_router
|
24
|
+
from auto_coder_web.common_router import completions_router, file_router, auto_coder_conf_router, chat_list_router, file_group_router, model_router, compiler_router, lib_router
|
25
25
|
from auto_coder_web.common_router import active_context_router
|
26
26
|
from rich.console import Console
|
27
27
|
from loguru import logger
|
@@ -86,6 +86,9 @@ class ProxyServer:
|
|
86
86
|
# self.app.state.file_cacher = FileCacher(self.project_path)
|
87
87
|
# Store initialization status
|
88
88
|
self.app.state.is_initialized = self.is_initialized
|
89
|
+
# Store memory for lib_router
|
90
|
+
if self.auto_coder_runner:
|
91
|
+
self.app.state.memory = self.auto_coder_runner.get_memory_wrapper()
|
89
92
|
|
90
93
|
self.app.include_router(todo_router.router)
|
91
94
|
self.app.include_router(settings_router.router)
|
@@ -113,6 +116,7 @@ class ProxyServer:
|
|
113
116
|
self.app.include_router(chat_panels_router.router)
|
114
117
|
self.app.include_router(code_editor_tabs_router.router)
|
115
118
|
self.app.include_router(file_command_router.router)
|
119
|
+
self.app.include_router(lib_router.router)
|
116
120
|
|
117
121
|
@self.app.on_event("shutdown")
|
118
122
|
async def shutdown_event():
|
auto_coder_web/version.py
CHANGED
@@ -1 +1 @@
|
|
1
|
-
__version__ = "0.1.
|
1
|
+
__version__ = "0.1.111"
|