auto-coder 0.1.326__py3-none-any.whl → 0.1.328__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.326.dist-info → auto_coder-0.1.328.dist-info}/METADATA +1 -1
- {auto_coder-0.1.326.dist-info → auto_coder-0.1.328.dist-info}/RECORD +28 -16
- autocoder/common/__init__.py +5 -0
- autocoder/common/auto_coder_lang.py +16 -0
- autocoder/common/stream_out_type.py +6 -0
- autocoder/common/v2/code_editblock_manager.py +92 -8
- autocoder/compilers/__init__.py +51 -0
- autocoder/compilers/base_compiler.py +107 -0
- autocoder/compilers/compiler_config_api.py +365 -0
- autocoder/compilers/compiler_config_manager.py +305 -0
- autocoder/compilers/compiler_factory.py +271 -0
- autocoder/compilers/java_compiler.py +680 -0
- autocoder/compilers/models.py +210 -0
- autocoder/compilers/provided_compiler.py +343 -0
- autocoder/compilers/python_compiler.py +413 -0
- autocoder/compilers/reactjs_compiler.py +491 -0
- autocoder/compilers/shadow_compiler.py +42 -0
- autocoder/compilers/vue_compiler.py +548 -0
- autocoder/events/event_content.py +29 -0
- autocoder/index/index.py +43 -9
- autocoder/memory/active_context_manager.py +3 -3
- autocoder/memory/active_package.py +2 -2
- autocoder/shadows/shadow_manager.py +251 -4
- autocoder/version.py +1 -1
- {auto_coder-0.1.326.dist-info → auto_coder-0.1.328.dist-info}/LICENSE +0 -0
- {auto_coder-0.1.326.dist-info → auto_coder-0.1.328.dist-info}/WHEEL +0 -0
- {auto_coder-0.1.326.dist-info → auto_coder-0.1.328.dist-info}/entry_points.txt +0 -0
- {auto_coder-0.1.326.dist-info → auto_coder-0.1.328.dist-info}/top_level.txt +0 -0
|
@@ -108,7 +108,7 @@ class ActiveContextManager:
|
|
|
108
108
|
global_logger.configure(
|
|
109
109
|
handlers=[
|
|
110
110
|
# 移除控制台输出,只保留文件输出
|
|
111
|
-
# 文件 Handler
|
|
111
|
+
# 文件 Handler
|
|
112
112
|
{
|
|
113
113
|
"sink": log_file,
|
|
114
114
|
"level": "INFO",
|
|
@@ -117,12 +117,12 @@ class ActiveContextManager:
|
|
|
117
117
|
"format": "{time:YYYY-MM-DD HH:mm:ss} | {level} | {name} | {message}",
|
|
118
118
|
"filter": lambda record: record["extra"].get("name") in ["DirectoryMapper", "ActiveContextManager","ActivePackage","AsyncProcessor"]
|
|
119
119
|
},
|
|
120
|
-
# 控制台 Handler
|
|
120
|
+
# 控制台 Handler
|
|
121
121
|
{
|
|
122
122
|
"sink": sys.stdout,
|
|
123
123
|
"level": "INFO",
|
|
124
124
|
"format": "{time:YYYY-MM-DD HH:mm:ss} | {name} | {message}",
|
|
125
|
-
"filter": lambda record: record["extra"].get("name") not in ["ActiveContextManager"]
|
|
125
|
+
"filter": lambda record: record["extra"].get("name") not in ["DirectoryMapper", "ActiveContextManager","ActivePackage","AsyncProcessor","TokenCostCalculator"]
|
|
126
126
|
}
|
|
127
127
|
]
|
|
128
128
|
)
|
|
@@ -192,7 +192,7 @@ class ActivePackage:
|
|
|
192
192
|
end_time_current_change = time.monotonic()
|
|
193
193
|
|
|
194
194
|
# 使用TokenCostCalculator跟踪token使用情况
|
|
195
|
-
token_calculator = TokenCostCalculator(logger_name="ActivePackage
|
|
195
|
+
token_calculator = TokenCostCalculator(logger_name="ActivePackage",args=args)
|
|
196
196
|
current_change_stats: TokenUsageStats = token_calculator.track_token_usage(
|
|
197
197
|
llm=self.llm,
|
|
198
198
|
meta_holder=meta_holder_current_change,
|
|
@@ -316,7 +316,7 @@ class ActivePackage:
|
|
|
316
316
|
end_time_current_change = time.monotonic()
|
|
317
317
|
|
|
318
318
|
# 使用TokenCostCalculator跟踪token使用情况
|
|
319
|
-
token_calculator = TokenCostCalculator(logger_name="ActivePackage
|
|
319
|
+
token_calculator = TokenCostCalculator(logger_name="ActivePackage",args=args)
|
|
320
320
|
update_current_change_stats: TokenUsageStats = token_calculator.track_token_usage(
|
|
321
321
|
llm=self.llm,
|
|
322
322
|
meta_holder=meta_holder_current_change,
|
|
@@ -10,16 +10,18 @@ class ShadowManager:
|
|
|
10
10
|
如果提供了event_file_id,则影子文件存储在<source_dir>/.auto-coder/shadows/<event_file_id>/中。
|
|
11
11
|
"""
|
|
12
12
|
|
|
13
|
-
def __init__(self, source_dir, event_file_id=None):
|
|
13
|
+
def __init__(self, source_dir, event_file_id=None, ignore_clean_shadows=False):
|
|
14
14
|
"""
|
|
15
15
|
使用项目根目录初始化。
|
|
16
16
|
|
|
17
17
|
参数:
|
|
18
18
|
source_dir (str): 项目根目录的绝对路径。
|
|
19
19
|
event_file_id (str, optional): 事件文件ID,用于创建特定的影子目录。
|
|
20
|
+
ignore_clean_shadows (bool, optional): 是否忽略清理影子目录。
|
|
20
21
|
"""
|
|
21
22
|
self.source_dir = os.path.abspath(source_dir)
|
|
22
|
-
|
|
23
|
+
self.ignore_clean_shadows = ignore_clean_shadows
|
|
24
|
+
self.event_file_id = None
|
|
23
25
|
# # 根据是否提供了event_file_id来确定shadows_dir的路径
|
|
24
26
|
# if event_file_id:
|
|
25
27
|
# print("======" + event_file_id)
|
|
@@ -28,12 +30,25 @@ class ShadowManager:
|
|
|
28
30
|
|
|
29
31
|
if event_file_id:
|
|
30
32
|
event_file_id = self.get_event_file_id_from_path(event_file_id)
|
|
33
|
+
self.event_file_id = event_file_id
|
|
31
34
|
self.shadows_dir = os.path.join(self.source_dir, '.auto-coder', 'shadows', event_file_id)
|
|
32
35
|
else:
|
|
33
36
|
self.shadows_dir = os.path.join(self.source_dir, '.auto-coder', 'shadows')
|
|
34
|
-
|
|
37
|
+
|
|
35
38
|
# 确保影子目录存在
|
|
36
39
|
os.makedirs(self.shadows_dir, exist_ok=True)
|
|
40
|
+
|
|
41
|
+
# 确保链接项目目录存在
|
|
42
|
+
link_projects_dir = os.path.join(self.source_dir, '.auto-coder', 'shadows', 'link_projects')
|
|
43
|
+
source_basename = os.path.basename(self.source_dir)
|
|
44
|
+
os.makedirs(link_projects_dir, exist_ok=True)
|
|
45
|
+
if self.event_file_id:
|
|
46
|
+
self.link_projects_dir = os.path.join(link_projects_dir, self.event_file_id, source_basename)
|
|
47
|
+
else:
|
|
48
|
+
self.link_projects_dir = os.path.join(link_projects_dir, source_basename)
|
|
49
|
+
|
|
50
|
+
os.makedirs(self.link_projects_dir, exist_ok=True)
|
|
51
|
+
|
|
37
52
|
|
|
38
53
|
def get_event_file_id_from_path(self, path):
|
|
39
54
|
"""
|
|
@@ -222,6 +237,9 @@ class ShadowManager:
|
|
|
222
237
|
返回:
|
|
223
238
|
bool: 操作成功则为True,否则为False
|
|
224
239
|
"""
|
|
240
|
+
if self.ignore_clean_shadows:
|
|
241
|
+
return True
|
|
242
|
+
|
|
225
243
|
if not os.path.exists(self.shadows_dir):
|
|
226
244
|
return True
|
|
227
245
|
|
|
@@ -237,4 +255,233 @@ class ShadowManager:
|
|
|
237
255
|
return True
|
|
238
256
|
except Exception as e:
|
|
239
257
|
print(f"清理影子目录时出错: {str(e)}")
|
|
240
|
-
return False
|
|
258
|
+
return False
|
|
259
|
+
|
|
260
|
+
def create_link_project(self):
|
|
261
|
+
"""
|
|
262
|
+
创建链接项目,该项目是源目录的一个特殊副本,
|
|
263
|
+
其中优先使用影子目录中的文件,如果影子目录中不存在则使用源目录中的文件。
|
|
264
|
+
|
|
265
|
+
返回:
|
|
266
|
+
str: 链接项目的路径
|
|
267
|
+
"""
|
|
268
|
+
# 清理链接项目目录
|
|
269
|
+
self._clean_link_project_dir()
|
|
270
|
+
# 创建链接项目
|
|
271
|
+
self._create_links(self.source_dir, self.link_projects_dir)
|
|
272
|
+
return self.link_projects_dir
|
|
273
|
+
|
|
274
|
+
def _clean_link_project_dir(self):
|
|
275
|
+
"""
|
|
276
|
+
清理链接项目目录中的所有内容,但保留目录本身。
|
|
277
|
+
|
|
278
|
+
返回:
|
|
279
|
+
bool: 操作成功则为True,否则为False
|
|
280
|
+
"""
|
|
281
|
+
if not os.path.exists(self.link_projects_dir):
|
|
282
|
+
return True
|
|
283
|
+
|
|
284
|
+
try:
|
|
285
|
+
# 删除链接项目目录中的所有内容
|
|
286
|
+
for item in os.listdir(self.link_projects_dir):
|
|
287
|
+
item_path = os.path.join(self.link_projects_dir, item)
|
|
288
|
+
if os.path.isfile(item_path):
|
|
289
|
+
os.unlink(item_path)
|
|
290
|
+
elif os.path.isdir(item_path):
|
|
291
|
+
shutil.rmtree(item_path)
|
|
292
|
+
|
|
293
|
+
return True
|
|
294
|
+
except Exception as e:
|
|
295
|
+
print(f"清理链接项目目录时出错: {str(e)}")
|
|
296
|
+
return False
|
|
297
|
+
|
|
298
|
+
def _create_links(self, source_path, link_path, rel_path=''):
|
|
299
|
+
"""
|
|
300
|
+
递归创建从源目录到链接项目目录的链接
|
|
301
|
+
|
|
302
|
+
参数:
|
|
303
|
+
source_path: 当前处理的源目录路径
|
|
304
|
+
link_path: 对应的链接项目目录路径
|
|
305
|
+
rel_path: 相对于根源目录的相对路径
|
|
306
|
+
"""
|
|
307
|
+
# 获取源目录中的所有项目
|
|
308
|
+
for item in os.listdir(source_path):
|
|
309
|
+
# 跳过.auto-coder目录
|
|
310
|
+
if item in ['.auto-coder', '.git']:
|
|
311
|
+
continue
|
|
312
|
+
|
|
313
|
+
source_item_path = os.path.join(source_path, item)
|
|
314
|
+
link_item_path = os.path.join(link_path, item)
|
|
315
|
+
current_rel_path = os.path.join(rel_path, item) if rel_path else item
|
|
316
|
+
|
|
317
|
+
# 我们相当于遍历了所有目录,遇到 shadow_dir 和 source_dir 同时存在:
|
|
318
|
+
# 则创建目录,遍历里面的文件,如果文件出现在shadow_dir里,则软链到shadow_dir,否则软链到source_dir里。
|
|
319
|
+
# 如果目录不同时存在,则直接创建到 source_dir的软链。这样就能确保 link_project 和 source_dir 的结构完全一致。
|
|
320
|
+
if os.path.isdir(source_item_path):
|
|
321
|
+
# 构建在shadows_dir中可能存在的对应路径
|
|
322
|
+
shadow_dir_path = os.path.join(self.shadows_dir, current_rel_path)
|
|
323
|
+
|
|
324
|
+
# 2.1 如果目录在shadows_dir中存在
|
|
325
|
+
if os.path.exists(shadow_dir_path) and os.path.isdir(shadow_dir_path):
|
|
326
|
+
# 创建对应的目录结构
|
|
327
|
+
os.makedirs(link_item_path, exist_ok=True)
|
|
328
|
+
|
|
329
|
+
# 遍历源目录中的文件
|
|
330
|
+
for file_item in os.listdir(source_item_path):
|
|
331
|
+
source_file_path = os.path.join(source_item_path, file_item)
|
|
332
|
+
link_file_path = os.path.join(link_item_path, file_item)
|
|
333
|
+
shadow_file_path = os.path.join(shadow_dir_path, file_item)
|
|
334
|
+
|
|
335
|
+
# 只处理文件,不处理子目录
|
|
336
|
+
if os.path.isfile(source_file_path):
|
|
337
|
+
# 检查链接文件是否已存在,如果存在则删除
|
|
338
|
+
if os.path.exists(link_file_path):
|
|
339
|
+
os.remove(link_file_path)
|
|
340
|
+
|
|
341
|
+
# 如果文件在shadows_dir中存在,链接到shadows_dir中的文件
|
|
342
|
+
if os.path.exists(shadow_file_path) and os.path.isfile(shadow_file_path):
|
|
343
|
+
os.symlink(shadow_file_path, link_file_path)
|
|
344
|
+
# 否则链接到源目录中的文件
|
|
345
|
+
else:
|
|
346
|
+
os.symlink(source_file_path, link_file_path)
|
|
347
|
+
|
|
348
|
+
# 递归处理子目录
|
|
349
|
+
self._create_links(source_item_path, link_item_path, current_rel_path)
|
|
350
|
+
|
|
351
|
+
# 2.2 如果目录在shadows_dir中不存在,直接创建软链接
|
|
352
|
+
else:
|
|
353
|
+
# 检查链接是否已存在,如果存在则删除
|
|
354
|
+
if os.path.exists(link_item_path):
|
|
355
|
+
if os.path.islink(link_item_path):
|
|
356
|
+
os.unlink(link_item_path)
|
|
357
|
+
elif os.path.isdir(link_item_path):
|
|
358
|
+
shutil.rmtree(link_item_path)
|
|
359
|
+
else:
|
|
360
|
+
os.remove(link_item_path)
|
|
361
|
+
|
|
362
|
+
os.symlink(source_item_path, link_item_path)
|
|
363
|
+
|
|
364
|
+
# 处理第一层级文件
|
|
365
|
+
elif os.path.isfile(source_item_path):
|
|
366
|
+
# 构建在shadows_dir中可能存在的对应文件路径
|
|
367
|
+
shadow_file_path = os.path.join(self.shadows_dir, current_rel_path)
|
|
368
|
+
|
|
369
|
+
# 检查链接文件是否已存在,如果存在则删除
|
|
370
|
+
if os.path.exists(link_item_path):
|
|
371
|
+
os.remove(link_item_path)
|
|
372
|
+
|
|
373
|
+
# 如果文件在shadows_dir中存在,链接到shadows_dir中的文件
|
|
374
|
+
if os.path.exists(shadow_file_path) and os.path.isfile(shadow_file_path):
|
|
375
|
+
os.symlink(shadow_file_path, link_item_path)
|
|
376
|
+
# 否则链接到源目录中的文件
|
|
377
|
+
else:
|
|
378
|
+
os.symlink(source_item_path, link_item_path)
|
|
379
|
+
|
|
380
|
+
def compare_directories(self):
|
|
381
|
+
"""
|
|
382
|
+
比较源目录和链接项目目录之间的差异,并打印出来。
|
|
383
|
+
|
|
384
|
+
返回:
|
|
385
|
+
tuple: (源目录独有的文件/目录列表, 链接项目独有的文件/目录列表, 同时存在但类型不同的项目列表)
|
|
386
|
+
"""
|
|
387
|
+
# 确保链接项目目录存在
|
|
388
|
+
if not os.path.exists(self.link_projects_dir):
|
|
389
|
+
print(f"链接项目目录不存在: {self.link_projects_dir}")
|
|
390
|
+
return [], [], []
|
|
391
|
+
|
|
392
|
+
source_only = [] # 只在源目录存在的文件/目录
|
|
393
|
+
link_only = [] # 只在链接项目存在的文件/目录
|
|
394
|
+
type_diff = [] # 类型不同的文件/目录
|
|
395
|
+
|
|
396
|
+
# 递归比较目录结构
|
|
397
|
+
self._compare_dir_recursive(self.source_dir, self.link_projects_dir, "", source_only, link_only, type_diff)
|
|
398
|
+
|
|
399
|
+
# 打印差异结果
|
|
400
|
+
print("\n目录结构比较结果:")
|
|
401
|
+
|
|
402
|
+
if not (source_only or link_only or type_diff):
|
|
403
|
+
print("✅ 目录结构完全一致")
|
|
404
|
+
return source_only, link_only, type_diff
|
|
405
|
+
|
|
406
|
+
if source_only:
|
|
407
|
+
print("\n🔍 仅在源目录中存在:")
|
|
408
|
+
for item in source_only:
|
|
409
|
+
print(f" - {item}")
|
|
410
|
+
|
|
411
|
+
if link_only:
|
|
412
|
+
print("\n🔍 仅在链接项目中存在:")
|
|
413
|
+
for item in link_only:
|
|
414
|
+
print(f" - {item}")
|
|
415
|
+
|
|
416
|
+
if type_diff:
|
|
417
|
+
print("\n🔍 同名但类型不同的项目:")
|
|
418
|
+
for item in type_diff:
|
|
419
|
+
print(f" - {item}")
|
|
420
|
+
|
|
421
|
+
return source_only, link_only, type_diff
|
|
422
|
+
|
|
423
|
+
def _compare_dir_recursive(self, source_path, link_path, rel_path, source_only, link_only, type_diff):
|
|
424
|
+
"""
|
|
425
|
+
递归比较两个目录的差异
|
|
426
|
+
|
|
427
|
+
参数:
|
|
428
|
+
source_path: 源目录路径
|
|
429
|
+
link_path: 链接项目目录路径
|
|
430
|
+
rel_path: 当前处理的相对路径
|
|
431
|
+
source_only: 仅在源目录存在的项目列表
|
|
432
|
+
link_only: 仅在链接项目存在的项目列表
|
|
433
|
+
type_diff: 同名但类型不同的项目列表
|
|
434
|
+
"""
|
|
435
|
+
# 获取源目录和链接项目目录中的所有项目
|
|
436
|
+
try:
|
|
437
|
+
source_items = set(os.listdir(source_path))
|
|
438
|
+
except (FileNotFoundError, PermissionError):
|
|
439
|
+
source_items = set()
|
|
440
|
+
|
|
441
|
+
try:
|
|
442
|
+
link_items = set(os.listdir(link_path))
|
|
443
|
+
except (FileNotFoundError, PermissionError):
|
|
444
|
+
link_items = set()
|
|
445
|
+
|
|
446
|
+
# 忽略特定目录
|
|
447
|
+
ignored_dirs = ['.auto-coder', '.git']
|
|
448
|
+
source_items = {item for item in source_items if item not in ignored_dirs}
|
|
449
|
+
link_items = {item for item in link_items if item not in ignored_dirs}
|
|
450
|
+
|
|
451
|
+
# 找出仅在源目录中存在的项目
|
|
452
|
+
for item in source_items - link_items:
|
|
453
|
+
item_rel_path = os.path.join(rel_path, item) if rel_path else item
|
|
454
|
+
source_only.append(item_rel_path)
|
|
455
|
+
|
|
456
|
+
# 找出仅在链接项目中存在的项目
|
|
457
|
+
for item in link_items - source_items:
|
|
458
|
+
item_rel_path = os.path.join(rel_path, item) if rel_path else item
|
|
459
|
+
link_only.append(item_rel_path)
|
|
460
|
+
|
|
461
|
+
# 比较同时存在的项目
|
|
462
|
+
for item in source_items.intersection(link_items):
|
|
463
|
+
# 跳过忽略的目录
|
|
464
|
+
if item in ignored_dirs:
|
|
465
|
+
continue
|
|
466
|
+
|
|
467
|
+
source_item_path = os.path.join(source_path, item)
|
|
468
|
+
link_item_path = os.path.join(link_path, item)
|
|
469
|
+
item_rel_path = os.path.join(rel_path, item) if rel_path else item
|
|
470
|
+
|
|
471
|
+
# 如果类型不同(一个是文件,一个是目录)
|
|
472
|
+
source_is_dir = os.path.isdir(source_item_path)
|
|
473
|
+
link_is_dir = os.path.isdir(link_item_path)
|
|
474
|
+
|
|
475
|
+
if source_is_dir != link_is_dir:
|
|
476
|
+
type_description = f"{item_rel_path} (源: {'目录' if source_is_dir else '文件'}, 链接: {'目录' if link_is_dir else '文件'})"
|
|
477
|
+
type_diff.append(type_description)
|
|
478
|
+
elif source_is_dir and link_is_dir:
|
|
479
|
+
# 如果都是目录,递归比较
|
|
480
|
+
self._compare_dir_recursive(
|
|
481
|
+
source_item_path,
|
|
482
|
+
link_item_path,
|
|
483
|
+
item_rel_path,
|
|
484
|
+
source_only,
|
|
485
|
+
link_only,
|
|
486
|
+
type_diff
|
|
487
|
+
)
|
autocoder/version.py
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
__version__ = "0.1.
|
|
1
|
+
__version__ = "0.1.328"
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|