auto-coder 0.1.392__py3-none-any.whl → 0.1.395__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.
Potentially problematic release.
This version of auto-coder might be problematic. Click here for more details.
- {auto_coder-0.1.392.dist-info → auto_coder-0.1.395.dist-info}/METADATA +1 -1
- {auto_coder-0.1.392.dist-info → auto_coder-0.1.395.dist-info}/RECORD +17 -13
- autocoder/agent/base_agentic/tools/execute_command_tool_resolver.py +1 -9
- autocoder/auto_coder_rag.py +67 -20
- autocoder/common/llm_friendly_package.py +36 -3
- autocoder/common/rag_manager/__init__.py +4 -0
- autocoder/common/rag_manager/rag_manager.py +144 -0
- autocoder/common/v2/agent/agentic_edit.py +349 -16
- autocoder/common/v2/agent/agentic_edit_tools/__init__.py +2 -0
- autocoder/common/v2/agent/agentic_edit_tools/use_rag_tool_resolver.py +91 -0
- autocoder/common/v2/agent/agentic_edit_types.py +5 -0
- autocoder/rags.py +348 -0
- autocoder/version.py +1 -1
- {auto_coder-0.1.392.dist-info → auto_coder-0.1.395.dist-info}/LICENSE +0 -0
- {auto_coder-0.1.392.dist-info → auto_coder-0.1.395.dist-info}/WHEEL +0 -0
- {auto_coder-0.1.392.dist-info → auto_coder-0.1.395.dist-info}/entry_points.txt +0 -0
- {auto_coder-0.1.392.dist-info → auto_coder-0.1.395.dist-info}/top_level.txt +0 -0
autocoder/rags.py
ADDED
|
@@ -0,0 +1,348 @@
|
|
|
1
|
+
import os
|
|
2
|
+
import json
|
|
3
|
+
import fcntl
|
|
4
|
+
import platform
|
|
5
|
+
import time
|
|
6
|
+
from typing import Dict, Optional, Any, List
|
|
7
|
+
from pathlib import Path
|
|
8
|
+
from contextlib import contextmanager
|
|
9
|
+
from datetime import datetime
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
RAGS_JSON = os.path.expanduser("~/.auto-coder/keys/rags.json")
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
class RAGConfigManager:
|
|
16
|
+
"""RAG配置管理器,支持并发安全的增删改查操作"""
|
|
17
|
+
|
|
18
|
+
def __init__(self, config_path: str = RAGS_JSON):
|
|
19
|
+
self.config_path = config_path
|
|
20
|
+
self._ensure_config_dir()
|
|
21
|
+
|
|
22
|
+
def _ensure_config_dir(self):
|
|
23
|
+
"""确保配置目录存在"""
|
|
24
|
+
config_dir = os.path.dirname(self.config_path)
|
|
25
|
+
if not os.path.exists(config_dir):
|
|
26
|
+
os.makedirs(config_dir, exist_ok=True)
|
|
27
|
+
|
|
28
|
+
@contextmanager
|
|
29
|
+
def _file_lock(self, mode='r'):
|
|
30
|
+
"""
|
|
31
|
+
文件锁上下文管理器,确保并发安全
|
|
32
|
+
"""
|
|
33
|
+
# 确保文件存在
|
|
34
|
+
if not os.path.exists(self.config_path):
|
|
35
|
+
with open(self.config_path, 'w') as f:
|
|
36
|
+
json.dump({}, f)
|
|
37
|
+
|
|
38
|
+
file_handle = open(self.config_path, mode)
|
|
39
|
+
try:
|
|
40
|
+
if platform.system() != "Windows":
|
|
41
|
+
# Unix系统使用fcntl
|
|
42
|
+
if 'w' in mode or 'a' in mode or '+' in mode:
|
|
43
|
+
fcntl.flock(file_handle.fileno(), fcntl.LOCK_EX) # 独占锁
|
|
44
|
+
else:
|
|
45
|
+
fcntl.flock(file_handle.fileno(), fcntl.LOCK_SH) # 共享锁
|
|
46
|
+
else:
|
|
47
|
+
# Windows系统的文件锁实现
|
|
48
|
+
try:
|
|
49
|
+
import msvcrt
|
|
50
|
+
if 'w' in mode or 'a' in mode or '+' in mode:
|
|
51
|
+
msvcrt.locking(file_handle.fileno(), msvcrt.LK_LOCK, 1)
|
|
52
|
+
else:
|
|
53
|
+
msvcrt.locking(file_handle.fileno(), msvcrt.LK_LOCK, 1)
|
|
54
|
+
except ImportError:
|
|
55
|
+
# 如果msvcrt不可用,退化到无锁模式(不推荐)
|
|
56
|
+
pass
|
|
57
|
+
|
|
58
|
+
yield file_handle
|
|
59
|
+
finally:
|
|
60
|
+
if platform.system() != "Windows":
|
|
61
|
+
fcntl.flock(file_handle.fileno(), fcntl.LOCK_UN) # 释放锁
|
|
62
|
+
else:
|
|
63
|
+
try:
|
|
64
|
+
import msvcrt
|
|
65
|
+
msvcrt.locking(file_handle.fileno(), msvcrt.LK_UNLCK, 1)
|
|
66
|
+
except ImportError:
|
|
67
|
+
pass
|
|
68
|
+
file_handle.close()
|
|
69
|
+
|
|
70
|
+
def _load_config(self) -> Dict[str, Any]:
|
|
71
|
+
"""
|
|
72
|
+
加载配置文件
|
|
73
|
+
"""
|
|
74
|
+
try:
|
|
75
|
+
with self._file_lock('r') as f:
|
|
76
|
+
content = f.read().strip()
|
|
77
|
+
if not content:
|
|
78
|
+
return {}
|
|
79
|
+
return json.loads(content)
|
|
80
|
+
except (FileNotFoundError, json.JSONDecodeError):
|
|
81
|
+
return {}
|
|
82
|
+
|
|
83
|
+
def _save_config(self, config: Dict[str, Any]):
|
|
84
|
+
"""
|
|
85
|
+
保存配置文件
|
|
86
|
+
"""
|
|
87
|
+
with self._file_lock('w') as f:
|
|
88
|
+
json.dump(config, f, indent=2, ensure_ascii=False)
|
|
89
|
+
|
|
90
|
+
def create(self, name: str, config: Dict[str, Any]) -> bool:
|
|
91
|
+
"""
|
|
92
|
+
创建新的RAG服务配置
|
|
93
|
+
|
|
94
|
+
Args:
|
|
95
|
+
name: RAG服务名称
|
|
96
|
+
config: 配置字典
|
|
97
|
+
|
|
98
|
+
Returns:
|
|
99
|
+
bool: 创建成功返回True,如果名称已存在返回False
|
|
100
|
+
"""
|
|
101
|
+
all_configs = self._load_config()
|
|
102
|
+
|
|
103
|
+
if name in all_configs:
|
|
104
|
+
return False
|
|
105
|
+
|
|
106
|
+
# 确保配置包含必要的字段
|
|
107
|
+
config['name'] = name
|
|
108
|
+
if 'status' not in config:
|
|
109
|
+
config['status'] = 'stopped'
|
|
110
|
+
if 'created_at' not in config:
|
|
111
|
+
config['created_at'] = datetime.now().isoformat()
|
|
112
|
+
config['updated_at'] = datetime.now().isoformat()
|
|
113
|
+
|
|
114
|
+
all_configs[name] = config
|
|
115
|
+
self._save_config(all_configs)
|
|
116
|
+
return True
|
|
117
|
+
|
|
118
|
+
def read(self, name: Optional[str] = None) -> Optional[Dict[str, Any]]:
|
|
119
|
+
"""
|
|
120
|
+
读取RAG服务配置
|
|
121
|
+
|
|
122
|
+
Args:
|
|
123
|
+
name: RAG服务名称,如果为None则返回所有配置
|
|
124
|
+
|
|
125
|
+
Returns:
|
|
126
|
+
Dict: 配置字典,如果name不存在或为None且无配置则返回None
|
|
127
|
+
"""
|
|
128
|
+
all_configs = self._load_config()
|
|
129
|
+
|
|
130
|
+
if name is None:
|
|
131
|
+
return all_configs if all_configs else None
|
|
132
|
+
|
|
133
|
+
return all_configs.get(name)
|
|
134
|
+
|
|
135
|
+
def update(self, name: str, config: Dict[str, Any]) -> bool:
|
|
136
|
+
"""
|
|
137
|
+
更新RAG服务配置
|
|
138
|
+
|
|
139
|
+
Args:
|
|
140
|
+
name: RAG服务名称
|
|
141
|
+
config: 新的配置字典(会与现有配置合并)
|
|
142
|
+
|
|
143
|
+
Returns:
|
|
144
|
+
bool: 更新成功返回True,如果名称不存在返回False
|
|
145
|
+
"""
|
|
146
|
+
all_configs = self._load_config()
|
|
147
|
+
|
|
148
|
+
if name not in all_configs:
|
|
149
|
+
return False
|
|
150
|
+
|
|
151
|
+
# 合并配置
|
|
152
|
+
existing_config = all_configs[name]
|
|
153
|
+
existing_config.update(config)
|
|
154
|
+
existing_config['name'] = name # 确保名称不被覆盖
|
|
155
|
+
existing_config['updated_at'] = datetime.now().isoformat()
|
|
156
|
+
|
|
157
|
+
all_configs[name] = existing_config
|
|
158
|
+
self._save_config(all_configs)
|
|
159
|
+
return True
|
|
160
|
+
|
|
161
|
+
def delete(self, name: str) -> bool:
|
|
162
|
+
"""
|
|
163
|
+
删除RAG服务配置
|
|
164
|
+
|
|
165
|
+
Args:
|
|
166
|
+
name: RAG服务名称
|
|
167
|
+
|
|
168
|
+
Returns:
|
|
169
|
+
bool: 删除成功返回True,如果名称不存在返回False
|
|
170
|
+
"""
|
|
171
|
+
all_configs = self._load_config()
|
|
172
|
+
|
|
173
|
+
if name not in all_configs:
|
|
174
|
+
return False
|
|
175
|
+
|
|
176
|
+
del all_configs[name]
|
|
177
|
+
self._save_config(all_configs)
|
|
178
|
+
return True
|
|
179
|
+
|
|
180
|
+
def list_names(self) -> List[str]:
|
|
181
|
+
"""
|
|
182
|
+
获取所有RAG服务名称列表
|
|
183
|
+
|
|
184
|
+
Returns:
|
|
185
|
+
List[str]: 服务名称列表
|
|
186
|
+
"""
|
|
187
|
+
all_configs = self._load_config()
|
|
188
|
+
return list(all_configs.keys())
|
|
189
|
+
|
|
190
|
+
def exists(self, name: str) -> bool:
|
|
191
|
+
"""
|
|
192
|
+
检查RAG服务是否存在
|
|
193
|
+
|
|
194
|
+
Args:
|
|
195
|
+
name: RAG服务名称
|
|
196
|
+
|
|
197
|
+
Returns:
|
|
198
|
+
bool: 存在返回True,否则返回False
|
|
199
|
+
"""
|
|
200
|
+
all_configs = self._load_config()
|
|
201
|
+
return name in all_configs
|
|
202
|
+
|
|
203
|
+
def get_by_port(self, port: int) -> Optional[Dict[str, Any]]:
|
|
204
|
+
"""
|
|
205
|
+
根据端口号查找RAG服务配置
|
|
206
|
+
|
|
207
|
+
Args:
|
|
208
|
+
port: 端口号
|
|
209
|
+
|
|
210
|
+
Returns:
|
|
211
|
+
Dict: 配置字典,如果未找到返回None
|
|
212
|
+
"""
|
|
213
|
+
all_configs = self._load_config()
|
|
214
|
+
|
|
215
|
+
for name, config in all_configs.items():
|
|
216
|
+
if config.get('port') == port:
|
|
217
|
+
return config
|
|
218
|
+
|
|
219
|
+
return None
|
|
220
|
+
|
|
221
|
+
def get_running_services(self) -> Dict[str, Any]:
|
|
222
|
+
"""
|
|
223
|
+
获取所有运行中的RAG服务
|
|
224
|
+
|
|
225
|
+
Returns:
|
|
226
|
+
Dict: 运行中的服务配置字典
|
|
227
|
+
"""
|
|
228
|
+
all_configs = self._load_config()
|
|
229
|
+
running_services = {}
|
|
230
|
+
|
|
231
|
+
for name, config in all_configs.items():
|
|
232
|
+
if config.get('status') == 'running':
|
|
233
|
+
running_services[name] = config
|
|
234
|
+
|
|
235
|
+
return running_services
|
|
236
|
+
|
|
237
|
+
def update_status(self, name: str, status: str, **kwargs) -> bool:
|
|
238
|
+
"""
|
|
239
|
+
更新RAG服务状态
|
|
240
|
+
|
|
241
|
+
Args:
|
|
242
|
+
name: RAG服务名称
|
|
243
|
+
status: 新状态 ('running', 'stopped', 'error', etc.)
|
|
244
|
+
**kwargs: 其他要更新的状态信息(如process_id, stdout_fd等)
|
|
245
|
+
|
|
246
|
+
Returns:
|
|
247
|
+
bool: 更新成功返回True,如果名称不存在返回False
|
|
248
|
+
"""
|
|
249
|
+
update_data = {'status': status, **kwargs}
|
|
250
|
+
return self.update(name, update_data)
|
|
251
|
+
|
|
252
|
+
def cleanup_stopped_services(self):
|
|
253
|
+
"""
|
|
254
|
+
清理已停止服务的临时状态信息(如process_id, stdout_fd等)
|
|
255
|
+
"""
|
|
256
|
+
all_configs = self._load_config()
|
|
257
|
+
modified = False
|
|
258
|
+
|
|
259
|
+
for name, config in all_configs.items():
|
|
260
|
+
if config.get('status') == 'stopped':
|
|
261
|
+
# 清理临时状态字段
|
|
262
|
+
temp_fields = ['process_id', 'stdout_fd', 'stderr_fd', 'cache_build_task_id']
|
|
263
|
+
for field in temp_fields:
|
|
264
|
+
if field in config:
|
|
265
|
+
del config[field]
|
|
266
|
+
modified = True
|
|
267
|
+
|
|
268
|
+
if modified:
|
|
269
|
+
self._save_config(all_configs)
|
|
270
|
+
|
|
271
|
+
|
|
272
|
+
# 创建全局实例
|
|
273
|
+
rag_manager = RAGConfigManager()
|
|
274
|
+
|
|
275
|
+
|
|
276
|
+
# 便捷函数
|
|
277
|
+
def create_rag_config(name: str, config: Dict[str, Any]) -> bool:
|
|
278
|
+
"""创建RAG配置的便捷函数"""
|
|
279
|
+
return rag_manager.create(name, config)
|
|
280
|
+
|
|
281
|
+
|
|
282
|
+
def get_rag_config(name: Optional[str] = None) -> Optional[Dict[str, Any]]:
|
|
283
|
+
"""获取RAG配置的便捷函数"""
|
|
284
|
+
return rag_manager.read(name)
|
|
285
|
+
|
|
286
|
+
|
|
287
|
+
def update_rag_config(name: str, config: Dict[str, Any]) -> bool:
|
|
288
|
+
"""更新RAG配置的便捷函数"""
|
|
289
|
+
return rag_manager.update(name, config)
|
|
290
|
+
|
|
291
|
+
|
|
292
|
+
def delete_rag_config(name: str) -> bool:
|
|
293
|
+
"""删除RAG配置的便捷函数"""
|
|
294
|
+
return rag_manager.delete(name)
|
|
295
|
+
|
|
296
|
+
|
|
297
|
+
def list_rag_names() -> List[str]:
|
|
298
|
+
"""获取所有RAG服务名称的便捷函数"""
|
|
299
|
+
return rag_manager.list_names()
|
|
300
|
+
|
|
301
|
+
|
|
302
|
+
def rag_exists(name: str) -> bool:
|
|
303
|
+
"""检查RAG服务是否存在的便捷函数"""
|
|
304
|
+
return rag_manager.exists(name)
|
|
305
|
+
|
|
306
|
+
|
|
307
|
+
def get_rag_by_port(port: int) -> Optional[Dict[str, Any]]:
|
|
308
|
+
"""根据端口获取RAG配置的便捷函数"""
|
|
309
|
+
return rag_manager.get_by_port(port)
|
|
310
|
+
|
|
311
|
+
|
|
312
|
+
def get_running_rags() -> Dict[str, Any]:
|
|
313
|
+
"""获取运行中RAG服务的便捷函数"""
|
|
314
|
+
return rag_manager.get_running_services()
|
|
315
|
+
|
|
316
|
+
|
|
317
|
+
def update_rag_status(name: str, status: str, **kwargs) -> bool:
|
|
318
|
+
"""更新RAG服务状态的便捷函数"""
|
|
319
|
+
return rag_manager.update_status(name, status, **kwargs)
|
|
320
|
+
|
|
321
|
+
|
|
322
|
+
# 使用示例
|
|
323
|
+
if __name__ == "__main__":
|
|
324
|
+
# 创建配置
|
|
325
|
+
config = {
|
|
326
|
+
"model": "deepseek_chat",
|
|
327
|
+
"tokenizer_path": "/Users/allwefantasy/Downloads/tokenizer.json",
|
|
328
|
+
"doc_dir": "/path/to/docs",
|
|
329
|
+
"rag_doc_filter_relevance": 2.0,
|
|
330
|
+
"host": "0.0.0.0",
|
|
331
|
+
"port": 8000,
|
|
332
|
+
"enable_hybrid_index": False,
|
|
333
|
+
"required_exts": ".md,.rst",
|
|
334
|
+
"disable_inference_enhance": True
|
|
335
|
+
}
|
|
336
|
+
|
|
337
|
+
# 创建
|
|
338
|
+
create_rag_config("test_rag", config)
|
|
339
|
+
|
|
340
|
+
# 读取
|
|
341
|
+
all_configs = get_rag_config()
|
|
342
|
+
specific_config = get_rag_config("test_rag")
|
|
343
|
+
|
|
344
|
+
# 更新
|
|
345
|
+
update_rag_config("test_rag", {"status": "running", "port": 8001})
|
|
346
|
+
|
|
347
|
+
# 删除
|
|
348
|
+
delete_rag_config("test_rag")
|
autocoder/version.py
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
__version__ = "0.1.
|
|
1
|
+
__version__ = "0.1.395"
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|