auto-coder-web 0.1.43__py3-none-any.whl → 0.1.45__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 -1
- auto_coder_web/common_router/completions_router.py +58 -40
- auto_coder_web/proxy.py +6 -5
- auto_coder_web/routers/index_router.py +201 -0
- auto_coder_web/version.py +1 -1
- auto_coder_web/web/asset-manifest.json +6 -6
- auto_coder_web/web/index.html +1 -1
- auto_coder_web/web/static/css/{main.b7ab91d3.css → main.f34d9cfc.css} +2 -2
- auto_coder_web/web/static/css/main.f34d9cfc.css.map +1 -0
- auto_coder_web/web/static/js/{main.4d7281bb.js → main.bb3658c2.js} +3 -3
- auto_coder_web/web/static/js/{main.4d7281bb.js.LICENSE.txt → main.bb3658c2.js.LICENSE.txt} +2 -0
- auto_coder_web/web/static/js/{main.4d7281bb.js.map → main.bb3658c2.js.map} +1 -1
- {auto_coder_web-0.1.43.dist-info → auto_coder_web-0.1.45.dist-info}/METADATA +2 -2
- {auto_coder_web-0.1.43.dist-info → auto_coder_web-0.1.45.dist-info}/RECORD +17 -16
- auto_coder_web/web/static/css/main.b7ab91d3.css.map +0 -1
- {auto_coder_web-0.1.43.dist-info → auto_coder_web-0.1.45.dist-info}/WHEEL +0 -0
- {auto_coder_web-0.1.43.dist-info → auto_coder_web-0.1.45.dist-info}/entry_points.txt +0 -0
- {auto_coder_web-0.1.43.dist-info → auto_coder_web-0.1.45.dist-info}/top_level.txt +0 -0
@@ -50,7 +50,13 @@ class AutoCoderRunnerWrapper:
|
|
50
50
|
return auto_command(command,params)
|
51
51
|
|
52
52
|
def configure_wrapper(self,conf: str, skip_print=False ):
|
53
|
-
return configure(conf, skip_print)
|
53
|
+
return configure(conf, skip_print)
|
54
|
+
|
55
|
+
def build_index_wrapper(self):
|
56
|
+
return index_build()
|
57
|
+
|
58
|
+
def query_index_wrapper(self,query: str):
|
59
|
+
return index_query(query)
|
54
60
|
|
55
61
|
def get_conf_wrapper(self):
|
56
62
|
memory = get_memory()
|
@@ -35,49 +35,68 @@ async def get_project_path(request: Request):
|
|
35
35
|
|
36
36
|
def find_files_in_project(patterns: List[str], project_path: str) -> List[str]:
|
37
37
|
memory = get_memory()
|
38
|
-
default_exclude_dirs = [".git", "node_modules", "dist", "build", "__pycache__",".venv"]
|
38
|
+
default_exclude_dirs = [".git", "node_modules", "dist", "build", "__pycache__", ".venv", ".auto-coder"]
|
39
39
|
active_file_list = memory["current_files"]["files"]
|
40
|
-
|
40
|
+
final_exclude_dirs = default_exclude_dirs + memory.get("exclude_dirs", [])
|
41
41
|
project_root = project_path
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
42
|
+
|
43
|
+
def should_exclude_path(path: str) -> bool:
|
44
|
+
"""检查路径是否应该被排除(路径中包含排除目录或以.开头的目录/文件)"""
|
45
|
+
# 处理相对/绝对路径
|
46
|
+
rel_path = path
|
47
|
+
if os.path.isabs(path):
|
48
|
+
try:
|
49
|
+
rel_path = os.path.relpath(path, project_root)
|
50
|
+
except ValueError:
|
51
|
+
rel_path = path
|
52
|
+
|
53
|
+
# 检查文件或目录本身是否以.开头
|
54
|
+
if os.path.basename(rel_path).startswith('.'):
|
55
|
+
return True
|
56
|
+
|
57
|
+
# 检查路径中是否包含排除目录
|
58
|
+
path_parts = rel_path.split(os.sep)
|
59
|
+
return any(part in final_exclude_dirs or part.startswith('.') for part in path_parts)
|
60
|
+
|
61
|
+
# 如果没有提供有效模式,返回过滤后的活动文件列表
|
62
|
+
if not patterns or (len(patterns) == 1 and patterns[0] == ""):
|
63
|
+
return [f for f in active_file_list if not should_exclude_path(f)]
|
64
|
+
|
65
|
+
matched_files = set() # 使用集合避免重复
|
46
66
|
|
47
67
|
for pattern in patterns:
|
68
|
+
# 1. 从活动文件列表中匹配
|
48
69
|
for file_path in active_file_list:
|
49
|
-
if pattern in os.path.basename(file_path):
|
50
|
-
matched_files.
|
51
|
-
|
52
|
-
|
53
|
-
memory.get("exclude_dirs", [])
|
54
|
-
|
55
|
-
for pattern in patterns:
|
70
|
+
if not should_exclude_path(file_path) and pattern in os.path.basename(file_path):
|
71
|
+
matched_files.add(file_path)
|
72
|
+
|
73
|
+
# 2. 如果是通配符模式,使用glob
|
56
74
|
if "*" in pattern or "?" in pattern:
|
57
75
|
for file_path in glob.glob(pattern, recursive=True):
|
58
|
-
if os.path.isfile(file_path):
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
76
|
+
if os.path.isfile(file_path) and not should_exclude_path(file_path):
|
77
|
+
matched_files.add(os.path.abspath(file_path))
|
78
|
+
continue
|
79
|
+
|
80
|
+
# 3. 使用os.walk在文件系统中查找
|
81
|
+
for root, dirs, files in os.walk(project_root, followlinks=True):
|
82
|
+
# 过滤不需要遍历的目录
|
83
|
+
dirs[:] = [d for d in dirs if d not in final_exclude_dirs and not d.startswith('.')]
|
84
|
+
|
85
|
+
if should_exclude_path(root):
|
86
|
+
continue
|
87
|
+
|
88
|
+
# 查找匹配文件
|
89
|
+
for file in files:
|
90
|
+
if pattern in file:
|
91
|
+
file_path = os.path.join(root, file)
|
92
|
+
if not should_exclude_path(file_path):
|
93
|
+
matched_files.add(file_path)
|
94
|
+
|
95
|
+
# 4. 如果pattern本身是文件路径
|
96
|
+
if os.path.exists(pattern) and os.path.isfile(pattern) and not should_exclude_path(pattern):
|
97
|
+
matched_files.add(os.path.abspath(pattern))
|
98
|
+
|
99
|
+
return list(matched_files)
|
81
100
|
|
82
101
|
def get_symbol_list(project_path: str) -> List[SymbolItem]:
|
83
102
|
list_of_symbols = []
|
@@ -131,10 +150,9 @@ async def get_file_completions(
|
|
131
150
|
completions = []
|
132
151
|
project_root = project_path
|
133
152
|
for file_name in matches:
|
134
|
-
path_parts = file_name.split(os.sep)
|
153
|
+
# path_parts = file_name.split(os.sep)
|
135
154
|
# 只显示最后三层路径,让显示更简洁
|
136
|
-
display_name = os.
|
137
|
-
path_parts[-3:]) if len(path_parts) > 3 else file_name
|
155
|
+
display_name = os.path.basename(file_name)
|
138
156
|
relative_path = os.path.relpath(file_name, project_root)
|
139
157
|
|
140
158
|
completions.append(CompletionItem(
|
@@ -163,4 +181,4 @@ async def get_symbol_completions(
|
|
163
181
|
path=relative_path,
|
164
182
|
display=f"{symbol.symbol_name}(location: {relative_path})"
|
165
183
|
))
|
166
|
-
return CompletionResponse(completions=matches)
|
184
|
+
return CompletionResponse(completions=matches)
|
auto_coder_web/proxy.py
CHANGED
@@ -16,12 +16,12 @@ import argparse
|
|
16
16
|
import aiofiles
|
17
17
|
import pkg_resources
|
18
18
|
import sys
|
19
|
-
from .terminal import terminal_manager
|
19
|
+
from auto_coder_web.terminal import terminal_manager
|
20
20
|
from autocoder.common import AutoCoderArgs
|
21
21
|
from auto_coder_web.auto_coder_runner_wrapper import AutoCoderRunnerWrapper
|
22
|
-
from .routers import todo_router, settings_router, auto_router, commit_router, chat_router, coding_router
|
23
|
-
from .expert_routers import history_router
|
24
|
-
from .common_router import completions_router, file_router, auto_coder_conf_router, chat_list_router, file_group_router, model_router
|
22
|
+
from auto_coder_web.routers import todo_router, settings_router, auto_router, commit_router, chat_router, coding_router,index_router
|
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
|
25
25
|
from rich.console import Console
|
26
26
|
from loguru import logger
|
27
27
|
from auto_coder_web.lang import get_message
|
@@ -94,7 +94,8 @@ class ProxyServer:
|
|
94
94
|
self.app.include_router(auto_coder_conf_router.router)
|
95
95
|
self.app.include_router(chat_list_router.router)
|
96
96
|
self.app.include_router(file_group_router.router)
|
97
|
-
self.app.include_router(model_router.router)
|
97
|
+
self.app.include_router(model_router.router)
|
98
|
+
self.app.include_router(index_router.router)
|
98
99
|
|
99
100
|
@self.app.on_event("shutdown")
|
100
101
|
async def shutdown_event():
|
@@ -0,0 +1,201 @@
|
|
1
|
+
import os
|
2
|
+
import json
|
3
|
+
from threading import Thread
|
4
|
+
import time as import_time
|
5
|
+
from fastapi import APIRouter, HTTPException, Request, Depends
|
6
|
+
from pydantic import BaseModel
|
7
|
+
from typing import Optional, Any, Dict, Union, List
|
8
|
+
from auto_coder_web.auto_coder_runner_wrapper import AutoCoderRunnerWrapper
|
9
|
+
from loguru import logger
|
10
|
+
|
11
|
+
# 定义Pydantic模型
|
12
|
+
class IndexBuildResponse(BaseModel):
|
13
|
+
status: str
|
14
|
+
message: Optional[str] = None
|
15
|
+
|
16
|
+
class IndexStatusCompleted(BaseModel):
|
17
|
+
status: str = "completed"
|
18
|
+
result: Any
|
19
|
+
timestamp: float
|
20
|
+
|
21
|
+
class IndexStatusError(BaseModel):
|
22
|
+
status: str = "error"
|
23
|
+
error: str
|
24
|
+
timestamp: float
|
25
|
+
|
26
|
+
class IndexStatusUnknown(BaseModel):
|
27
|
+
status: str = "unknown"
|
28
|
+
message: str = "No index build status available"
|
29
|
+
|
30
|
+
class SourceCode(BaseModel):
|
31
|
+
module_name: str
|
32
|
+
source_code: str
|
33
|
+
tag: str = ""
|
34
|
+
tokens: int = -1
|
35
|
+
metadata: Dict[str, Any] = {}
|
36
|
+
|
37
|
+
class SourceCodeListResponse(BaseModel):
|
38
|
+
sources: List[SourceCode]
|
39
|
+
|
40
|
+
# 组合类型
|
41
|
+
IndexStatus = Union[IndexStatusCompleted, IndexStatusError, IndexStatusUnknown]
|
42
|
+
|
43
|
+
router = APIRouter()
|
44
|
+
|
45
|
+
|
46
|
+
async def get_project_path(request: Request) -> str:
|
47
|
+
"""
|
48
|
+
从FastAPI请求上下文中获取项目路径
|
49
|
+
"""
|
50
|
+
return request.app.state.project_path
|
51
|
+
|
52
|
+
|
53
|
+
@router.post("/api/index/build")
|
54
|
+
async def build_index(project_path: str = Depends(get_project_path)):
|
55
|
+
"""
|
56
|
+
构建索引
|
57
|
+
|
58
|
+
在单独的线程中运行索引构建,避免阻塞主线程
|
59
|
+
|
60
|
+
Args:
|
61
|
+
project_path: 项目路径
|
62
|
+
|
63
|
+
Returns:
|
64
|
+
构建索引的状态信息
|
65
|
+
"""
|
66
|
+
|
67
|
+
# 定义在线程中运行的函数
|
68
|
+
def run_index_build_in_thread():
|
69
|
+
try:
|
70
|
+
# 创建AutoCoderRunnerWrapper实例
|
71
|
+
wrapper = AutoCoderRunnerWrapper(project_path)
|
72
|
+
|
73
|
+
# 调用build_index_wrapper方法构建索引
|
74
|
+
result = wrapper.build_index_wrapper()
|
75
|
+
|
76
|
+
logger.info(f"Index build completed successfully: {result}")
|
77
|
+
|
78
|
+
# 可以选择将结果保存到文件中,以便前端查询
|
79
|
+
status_file = os.path.join(
|
80
|
+
project_path, ".auto-coder", "auto-coder.web", "index-status.json")
|
81
|
+
os.makedirs(os.path.dirname(status_file), exist_ok=True)
|
82
|
+
|
83
|
+
# 使用Pydantic模型创建状态数据
|
84
|
+
status_data = IndexStatusCompleted(
|
85
|
+
result=result,
|
86
|
+
timestamp=import_time.time()
|
87
|
+
)
|
88
|
+
|
89
|
+
with open(status_file, 'w') as f:
|
90
|
+
f.write(status_data.model_dump_json())
|
91
|
+
|
92
|
+
except Exception as e:
|
93
|
+
logger.error(f"Error building index: {str(e)}")
|
94
|
+
|
95
|
+
# 保存错误信息
|
96
|
+
status_file = os.path.join(
|
97
|
+
project_path, ".auto-coder", "auto-coder.web", "index-status.json")
|
98
|
+
os.makedirs(os.path.dirname(status_file), exist_ok=True)
|
99
|
+
|
100
|
+
# 使用Pydantic模型创建错误状态数据
|
101
|
+
status_data = IndexStatusError(
|
102
|
+
error=str(e),
|
103
|
+
timestamp=import_time.time()
|
104
|
+
)
|
105
|
+
|
106
|
+
with open(status_file, 'w') as f:
|
107
|
+
f.write(status_data.model_dump_json())
|
108
|
+
|
109
|
+
try:
|
110
|
+
# 创建并启动线程
|
111
|
+
thread = Thread(target=run_index_build_in_thread)
|
112
|
+
thread.daemon = True # 设置为守护线程,这样当主程序退出时,线程也会退出
|
113
|
+
thread.start()
|
114
|
+
|
115
|
+
logger.info("Started index build in background thread")
|
116
|
+
return IndexBuildResponse(
|
117
|
+
status="started",
|
118
|
+
message="Index build started in background"
|
119
|
+
)
|
120
|
+
except Exception as e:
|
121
|
+
logger.error(f"Error starting index build thread: {str(e)}")
|
122
|
+
raise HTTPException(
|
123
|
+
status_code=500, detail=f"Failed to start index build: {str(e)}")
|
124
|
+
|
125
|
+
|
126
|
+
@router.get("/api/index/status")
|
127
|
+
async def get_index_status(project_path: str = Depends(get_project_path)):
|
128
|
+
"""
|
129
|
+
获取索引构建状态
|
130
|
+
|
131
|
+
从状态文件中读取索引构建的最新状态
|
132
|
+
|
133
|
+
Args:
|
134
|
+
project_path: 项目路径
|
135
|
+
|
136
|
+
Returns:
|
137
|
+
索引构建的状态信息
|
138
|
+
"""
|
139
|
+
try:
|
140
|
+
status_file = os.path.join(
|
141
|
+
project_path, ".auto-coder", "auto-coder.web", "index-status.json")
|
142
|
+
|
143
|
+
if not os.path.exists(status_file):
|
144
|
+
return IndexStatusUnknown()
|
145
|
+
|
146
|
+
with open(status_file, 'r') as f:
|
147
|
+
status_data_dict = json.load(f)
|
148
|
+
|
149
|
+
# 根据状态类型返回相应的Pydantic模型
|
150
|
+
if status_data_dict["status"] == "completed":
|
151
|
+
return IndexStatusCompleted(**status_data_dict)
|
152
|
+
elif status_data_dict["status"] == "error":
|
153
|
+
return IndexStatusError(**status_data_dict)
|
154
|
+
else:
|
155
|
+
return IndexStatusUnknown()
|
156
|
+
except Exception as e:
|
157
|
+
logger.error(f"Error getting index status: {str(e)}")
|
158
|
+
raise HTTPException(
|
159
|
+
status_code=500, detail=f"Failed to get index status: {str(e)}")
|
160
|
+
|
161
|
+
|
162
|
+
@router.get("/api/index/query", response_model=SourceCodeListResponse)
|
163
|
+
async def query_index(query: str, project_path: str = Depends(get_project_path)):
|
164
|
+
"""
|
165
|
+
智能搜索项目文件
|
166
|
+
|
167
|
+
使用索引查询相关文件
|
168
|
+
|
169
|
+
Args:
|
170
|
+
query: 搜索查询
|
171
|
+
project_path: 项目路径
|
172
|
+
|
173
|
+
Returns:
|
174
|
+
匹配的源代码文件列表
|
175
|
+
"""
|
176
|
+
try:
|
177
|
+
wrapper = AutoCoderRunnerWrapper(project_path)
|
178
|
+
result = wrapper.query_index_wrapper(query)
|
179
|
+
|
180
|
+
# 将结果转换为SourceCodeListResponse格式
|
181
|
+
if hasattr(result, 'sources'):
|
182
|
+
sources = [
|
183
|
+
SourceCode(
|
184
|
+
module_name=os.path.relpath(source.module_name, project_path),
|
185
|
+
source_code="",
|
186
|
+
tag=source.tag if hasattr(source, 'tag') else "",
|
187
|
+
tokens=source.tokens if hasattr(source, 'tokens') else -1,
|
188
|
+
metadata=source.metadata if hasattr(source, 'metadata') else {}
|
189
|
+
)
|
190
|
+
for source in result.sources
|
191
|
+
]
|
192
|
+
return SourceCodeListResponse(sources=sources)
|
193
|
+
else:
|
194
|
+
# 如果结果不是预期的格式,返回空列表
|
195
|
+
logger.warning(f"Unexpected result format from query_index_wrapper: {type(result)}")
|
196
|
+
return SourceCodeListResponse(sources=[])
|
197
|
+
|
198
|
+
except Exception as e:
|
199
|
+
logger.error(f"Error querying index: {str(e)}")
|
200
|
+
raise HTTPException(
|
201
|
+
status_code=500, detail=f"Failed to query index: {str(e)}")
|
auto_coder_web/version.py
CHANGED
@@ -1 +1 @@
|
|
1
|
-
__version__ = "0.1.
|
1
|
+
__version__ = "0.1.45"
|
@@ -1,15 +1,15 @@
|
|
1
1
|
{
|
2
2
|
"files": {
|
3
|
-
"main.css": "/static/css/main.
|
4
|
-
"main.js": "/static/js/main.
|
3
|
+
"main.css": "/static/css/main.f34d9cfc.css",
|
4
|
+
"main.js": "/static/js/main.bb3658c2.js",
|
5
5
|
"static/js/453.d855a71b.chunk.js": "/static/js/453.d855a71b.chunk.js",
|
6
6
|
"index.html": "/index.html",
|
7
|
-
"main.
|
8
|
-
"main.
|
7
|
+
"main.f34d9cfc.css.map": "/static/css/main.f34d9cfc.css.map",
|
8
|
+
"main.bb3658c2.js.map": "/static/js/main.bb3658c2.js.map",
|
9
9
|
"453.d855a71b.chunk.js.map": "/static/js/453.d855a71b.chunk.js.map"
|
10
10
|
},
|
11
11
|
"entrypoints": [
|
12
|
-
"static/css/main.
|
13
|
-
"static/js/main.
|
12
|
+
"static/css/main.f34d9cfc.css",
|
13
|
+
"static/js/main.bb3658c2.js"
|
14
14
|
]
|
15
15
|
}
|
auto_coder_web/web/index.html
CHANGED
@@ -1 +1 @@
|
|
1
|
-
<!doctype html><html lang="en"><head><meta charset="utf-8"/><link rel="icon" href="/favicon.ico"/><meta name="viewport" content="width=device-width,initial-scale=1"/><meta name="theme-color" content="#000000"/><meta name="description" content="Web site created using create-react-app"/><link rel="apple-touch-icon" href="/logo192.png"/><link rel="manifest" href="/manifest.json"/><title>React App</title><script defer="defer" src="/static/js/main.
|
1
|
+
<!doctype html><html lang="en"><head><meta charset="utf-8"/><link rel="icon" href="/favicon.ico"/><meta name="viewport" content="width=device-width,initial-scale=1"/><meta name="theme-color" content="#000000"/><meta name="description" content="Web site created using create-react-app"/><link rel="apple-touch-icon" href="/logo192.png"/><link rel="manifest" href="/manifest.json"/><title>React App</title><script defer="defer" src="/static/js/main.bb3658c2.js"></script><link href="/static/css/main.f34d9cfc.css" rel="stylesheet"></head><body><noscript>You need to enable JavaScript to run this app.</noscript><div id="root"></div></body></html>
|