auto-coder-web 0.1.43__py3-none-any.whl → 0.1.44__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.
@@ -50,7 +50,10 @@ 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()
54
57
 
55
58
  def get_conf_wrapper(self):
56
59
  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
- matched_files = []
43
-
44
- if len(patterns) == 1 and patterns[0] == "":
45
- return active_file_list
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.append(file_path)
51
-
52
- final_exclude_dirs = default_exclude_dirs + \
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
- abs_path = os.path.abspath(file_path)
60
- if not any(
61
- exclude_dir in abs_path.split(os.sep)
62
- for exclude_dir in final_exclude_dirs
63
- ):
64
- matched_files.append(abs_path)
65
- else:
66
- is_added = False
67
- for root, dirs, files in os.walk(project_root, followlinks=True):
68
- dirs[:] = [d for d in dirs if d not in final_exclude_dirs]
69
- if pattern in files:
70
- matched_files.append(os.path.join(root, pattern))
71
- is_added = True
72
- else:
73
- for file in files:
74
- if pattern in os.path.join(root, file):
75
- matched_files.append(os.path.join(root, file))
76
- is_added = True
77
- if not is_added:
78
- matched_files.append(pattern)
79
-
80
- return list(set(matched_files))
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.sep.join(
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
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
@@ -0,0 +1,149 @@
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
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
+ # 组合类型
31
+ IndexStatus = Union[IndexStatusCompleted, IndexStatusError, IndexStatusUnknown]
32
+
33
+ router = APIRouter()
34
+
35
+
36
+ async def get_project_path(request: Request) -> str:
37
+ """
38
+ 从FastAPI请求上下文中获取项目路径
39
+ """
40
+ return request.app.state.project_path
41
+
42
+
43
+ @router.post("/api/index/build")
44
+ async def build_index(project_path: str = Depends(get_project_path)):
45
+ """
46
+ 构建索引
47
+
48
+ 在单独的线程中运行索引构建,避免阻塞主线程
49
+
50
+ Args:
51
+ project_path: 项目路径
52
+
53
+ Returns:
54
+ 构建索引的状态信息
55
+ """
56
+
57
+ # 定义在线程中运行的函数
58
+ def run_index_build_in_thread():
59
+ try:
60
+ # 创建AutoCoderRunnerWrapper实例
61
+ wrapper = AutoCoderRunnerWrapper(project_path)
62
+
63
+ # 调用build_index_wrapper方法构建索引
64
+ result = wrapper.build_index_wrapper()
65
+
66
+ logger.info(f"Index build completed successfully: {result}")
67
+
68
+ # 可以选择将结果保存到文件中,以便前端查询
69
+ status_file = os.path.join(
70
+ project_path, ".auto-coder", "auto-coder.web", "index-status.json")
71
+ os.makedirs(os.path.dirname(status_file), exist_ok=True)
72
+
73
+ # 使用Pydantic模型创建状态数据
74
+ status_data = IndexStatusCompleted(
75
+ result=result,
76
+ timestamp=import_time.time()
77
+ )
78
+
79
+ with open(status_file, 'w') as f:
80
+ f.write(status_data.model_dump_json())
81
+
82
+ except Exception as e:
83
+ logger.error(f"Error building index: {str(e)}")
84
+
85
+ # 保存错误信息
86
+ status_file = os.path.join(
87
+ project_path, ".auto-coder", "auto-coder.web", "index-status.json")
88
+ os.makedirs(os.path.dirname(status_file), exist_ok=True)
89
+
90
+ # 使用Pydantic模型创建错误状态数据
91
+ status_data = IndexStatusError(
92
+ error=str(e),
93
+ timestamp=import_time.time()
94
+ )
95
+
96
+ with open(status_file, 'w') as f:
97
+ f.write(status_data.model_dump_json())
98
+
99
+ try:
100
+ # 创建并启动线程
101
+ thread = Thread(target=run_index_build_in_thread)
102
+ thread.daemon = True # 设置为守护线程,这样当主程序退出时,线程也会退出
103
+ thread.start()
104
+
105
+ logger.info("Started index build in background thread")
106
+ return IndexBuildResponse(
107
+ status="started",
108
+ message="Index build started in background"
109
+ )
110
+ except Exception as e:
111
+ logger.error(f"Error starting index build thread: {str(e)}")
112
+ raise HTTPException(
113
+ status_code=500, detail=f"Failed to start index build: {str(e)}")
114
+
115
+
116
+ @router.get("/api/index/status")
117
+ async def get_index_status(project_path: str = Depends(get_project_path)):
118
+ """
119
+ 获取索引构建状态
120
+
121
+ 从状态文件中读取索引构建的最新状态
122
+
123
+ Args:
124
+ project_path: 项目路径
125
+
126
+ Returns:
127
+ 索引构建的状态信息
128
+ """
129
+ try:
130
+ status_file = os.path.join(
131
+ project_path, ".auto-coder", "auto-coder.web", "index-status.json")
132
+
133
+ if not os.path.exists(status_file):
134
+ return IndexStatusUnknown()
135
+
136
+ with open(status_file, 'r') as f:
137
+ status_data_dict = json.load(f)
138
+
139
+ # 根据状态类型返回相应的Pydantic模型
140
+ if status_data_dict["status"] == "completed":
141
+ return IndexStatusCompleted(**status_data_dict)
142
+ elif status_data_dict["status"] == "error":
143
+ return IndexStatusError(**status_data_dict)
144
+ else:
145
+ return IndexStatusUnknown()
146
+ except Exception as e:
147
+ logger.error(f"Error getting index status: {str(e)}")
148
+ raise HTTPException(
149
+ status_code=500, detail=f"Failed to get index status: {str(e)}")
auto_coder_web/version.py CHANGED
@@ -1 +1 @@
1
- __version__ = "0.1.43"
1
+ __version__ = "0.1.44"
@@ -1,15 +1,15 @@
1
1
  {
2
2
  "files": {
3
- "main.css": "/static/css/main.b7ab91d3.css",
4
- "main.js": "/static/js/main.4d7281bb.js",
3
+ "main.css": "/static/css/main.36162f0a.css",
4
+ "main.js": "/static/js/main.1a6d75ba.js",
5
5
  "static/js/453.d855a71b.chunk.js": "/static/js/453.d855a71b.chunk.js",
6
6
  "index.html": "/index.html",
7
- "main.b7ab91d3.css.map": "/static/css/main.b7ab91d3.css.map",
8
- "main.4d7281bb.js.map": "/static/js/main.4d7281bb.js.map",
7
+ "main.36162f0a.css.map": "/static/css/main.36162f0a.css.map",
8
+ "main.1a6d75ba.js.map": "/static/js/main.1a6d75ba.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.b7ab91d3.css",
13
- "static/js/main.4d7281bb.js"
12
+ "static/css/main.36162f0a.css",
13
+ "static/js/main.1a6d75ba.js"
14
14
  ]
15
15
  }
@@ -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.4d7281bb.js"></script><link href="/static/css/main.b7ab91d3.css" rel="stylesheet"></head><body><noscript>You need to enable JavaScript to run this app.</noscript><div id="root"></div></body></html>
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.1a6d75ba.js"></script><link href="/static/css/main.36162f0a.css" rel="stylesheet"></head><body><noscript>You need to enable JavaScript to run this app.</noscript><div id="root"></div></body></html>