auto-coder 0.1.305__py3-none-any.whl → 0.1.307__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.305.dist-info → auto_coder-0.1.307.dist-info}/METADATA +1 -1
- {auto_coder-0.1.305.dist-info → auto_coder-0.1.307.dist-info}/RECORD +43 -38
- autocoder/agent/auto_demand_organizer.py +13 -20
- autocoder/agent/auto_filegroup.py +10 -16
- autocoder/agent/auto_learn_from_commit.py +25 -33
- autocoder/agent/auto_review_commit.py +15 -64
- autocoder/auto_coder.py +6 -8
- autocoder/auto_coder_runner.py +153 -8
- autocoder/chat_auto_coder.py +9 -1
- autocoder/chat_auto_coder_lang.py +552 -278
- autocoder/commands/auto_command.py +31 -7
- autocoder/common/__init__.py +6 -0
- autocoder/common/action_yml_file_manager.py +75 -37
- autocoder/common/auto_coder_lang.py +737 -401
- autocoder/common/code_auto_generate.py +104 -16
- autocoder/common/code_auto_generate_diff.py +101 -10
- autocoder/common/code_auto_generate_editblock.py +103 -9
- autocoder/common/code_auto_generate_strict_diff.py +99 -9
- autocoder/common/code_auto_merge.py +8 -0
- autocoder/common/code_auto_merge_diff.py +8 -0
- autocoder/common/code_auto_merge_editblock.py +7 -0
- autocoder/common/code_auto_merge_strict_diff.py +5 -0
- autocoder/common/code_modification_ranker.py +9 -3
- autocoder/common/command_completer.py +12 -0
- autocoder/common/command_generator.py +5 -4
- autocoder/common/git_utils.py +86 -63
- autocoder/common/stream_out_type.py +8 -1
- autocoder/common/utils_code_auto_generate.py +29 -3
- autocoder/dispacher/__init__.py +18 -19
- autocoder/dispacher/actions/action.py +0 -132
- autocoder/index/filter/quick_filter.py +6 -3
- autocoder/memory/__init__.py +7 -0
- autocoder/memory/active_context_manager.py +649 -0
- autocoder/memory/active_package.py +469 -0
- autocoder/memory/async_processor.py +161 -0
- autocoder/memory/directory_mapper.py +67 -0
- autocoder/utils/auto_coder_utils/chat_stream_out.py +5 -0
- autocoder/utils/project_structure.py +35 -1
- autocoder/version.py +1 -1
- {auto_coder-0.1.305.dist-info → auto_coder-0.1.307.dist-info}/LICENSE +0 -0
- {auto_coder-0.1.305.dist-info → auto_coder-0.1.307.dist-info}/WHEEL +0 -0
- {auto_coder-0.1.305.dist-info → auto_coder-0.1.307.dist-info}/entry_points.txt +0 -0
- {auto_coder-0.1.305.dist-info → auto_coder-0.1.307.dist-info}/top_level.txt +0 -0
|
@@ -213,6 +213,8 @@ class CommandAutoTuner:
|
|
|
213
213
|
@byzerllm.prompt()
|
|
214
214
|
def _analyze(self, request: AutoCommandRequest) -> str:
|
|
215
215
|
"""
|
|
216
|
+
你是 auto-coder.chat 软件,帮助用户完成编程方面的需求。我们的目标是根据用户输入和当前上下文,组合多个函数来完成用户的需求。
|
|
217
|
+
|
|
216
218
|
## 当前用户环境信息如下:
|
|
217
219
|
<os_info>
|
|
218
220
|
操作系统: {{ env_info.os_name }} {{ env_info.os_version }}
|
|
@@ -234,10 +236,11 @@ class CommandAutoTuner:
|
|
|
234
236
|
{%- endif %}
|
|
235
237
|
</os_info>
|
|
236
238
|
|
|
237
|
-
|
|
238
|
-
|
|
239
|
+
当前项目根目录:
|
|
240
|
+
{{ current_project }}
|
|
241
|
+
|
|
239
242
|
{% if current_files %}
|
|
240
|
-
##
|
|
243
|
+
## 当前用户手动添加关注的文件列表:
|
|
241
244
|
<current_files>
|
|
242
245
|
{% for file in current_files %}
|
|
243
246
|
- {{ file }}
|
|
@@ -246,7 +249,7 @@ class CommandAutoTuner:
|
|
|
246
249
|
{% endif %}
|
|
247
250
|
|
|
248
251
|
|
|
249
|
-
##
|
|
252
|
+
## 这是用户对你的配置
|
|
250
253
|
<current_conf>
|
|
251
254
|
{{ current_conf }}
|
|
252
255
|
</current_conf>
|
|
@@ -260,6 +263,24 @@ class CommandAutoTuner:
|
|
|
260
263
|
## 函数组合说明:
|
|
261
264
|
{{ command_combination_readme }}
|
|
262
265
|
|
|
266
|
+
## active-context 项目追踪文档系统
|
|
267
|
+
|
|
268
|
+
在 {{ current_project }}/.auto-coder/active-context 下,我们提供了对该项目每个文件目录的追踪。
|
|
269
|
+
具体逻辑为:假设我们在当前项目有 ./src/package1/py1.py, 那么相应的在 .auto-coder/active-context 会有一个 ./src/package1 目录,
|
|
270
|
+
该目录下可能会有一个 active-context.md 文件,该文件记录了该目录下所有文件相关信息,可以帮你更好的理解这个目录下的文档,你可以通过 read_files 函数来读取
|
|
271
|
+
这个文件。注意,这个文件不一定存在。如果读取失败也是正常的。
|
|
272
|
+
|
|
273
|
+
## 变更记录文档系统
|
|
274
|
+
|
|
275
|
+
在 {{ current_project }}/actions 目录下,会有格式类似 000000001201_chat_action.yml 的文件,该文件记录了最近10次对话,
|
|
276
|
+
你可以通过 read_files 函数来读取这些文件,从而更好的理解用户的需求。
|
|
277
|
+
|
|
278
|
+
下面是一些字段的简单介绍
|
|
279
|
+
- query: 用户需求
|
|
280
|
+
- urls: 用户提供的上下文文件列表
|
|
281
|
+
- dynamic_urls: auto-coder.chat 自动感知的一些文件列表
|
|
282
|
+
- add_updated_urls: 这次需求发生变更的文件列表
|
|
283
|
+
|
|
263
284
|
{% if conversation_history %}
|
|
264
285
|
## 历史对话:
|
|
265
286
|
<conversation_history>
|
|
@@ -314,7 +335,8 @@ class CommandAutoTuner:
|
|
|
314
335
|
"conversation_safe_zone_tokens": self.args.conversation_prune_safe_zone_tokens,
|
|
315
336
|
"os_distribution": shells.get_os_distribution(),
|
|
316
337
|
"current_user": shells.get_current_username(),
|
|
317
|
-
"command_combination_readme": self._command_combination_readme.prompt()
|
|
338
|
+
"command_combination_readme": self._command_combination_readme.prompt(),
|
|
339
|
+
"current_project": os.path.abspath(self.args.source_dir)
|
|
318
340
|
}
|
|
319
341
|
|
|
320
342
|
@byzerllm.prompt()
|
|
@@ -337,8 +359,10 @@ class CommandAutoTuner:
|
|
|
337
359
|
尽可通过了解项目后,多用 @文件和@@符号,这样 chat 函数可以更清晰的理解你关注的代码,文档和意图。
|
|
338
360
|
|
|
339
361
|
### 调用 coding 函数应该注意的事项
|
|
340
|
-
调用 coding
|
|
341
|
-
|
|
362
|
+
调用 coding 函数的之前,你需要尽可能先了解用户需求,了解项目状态,包括读取 active_context 文件来了解项目。
|
|
363
|
+
然后清晰的描述自己的需求,完整的实现步骤,以及尽可能对@文件和@@符号需要参考以及修改的文件和符号。
|
|
364
|
+
对于比较复杂的需求,你还可以使用 chat 函数来进行讨论,从而获取一些有用的信息。
|
|
365
|
+
如果成功执行了 coding 函数, 最好再调用一次 chat("/review /commit"),方便总结这次代码变更。
|
|
342
366
|
注意,review 完后,需要询问用户是否要做啥调整不,如果用户说不用,那么就停止。否则根据意图进行后续操作。
|
|
343
367
|
|
|
344
368
|
### 关于对话大小的问题
|
autocoder/common/__init__.py
CHANGED
|
@@ -412,6 +412,12 @@ class AutoCoderArgs(pydantic.BaseModel):
|
|
|
412
412
|
|
|
413
413
|
event_file: Optional[str] = None
|
|
414
414
|
|
|
415
|
+
enable_active_context: Optional[bool] = False
|
|
416
|
+
|
|
417
|
+
generate_max_rounds: Optional[int] = 5
|
|
418
|
+
|
|
419
|
+
revert_commit_id: Optional[str] = None
|
|
420
|
+
|
|
415
421
|
class Config:
|
|
416
422
|
protected_namespaces = ()
|
|
417
423
|
|
|
@@ -4,8 +4,10 @@ import hashlib
|
|
|
4
4
|
import git
|
|
5
5
|
from typing import List, Dict, Tuple, Optional, Union, Any
|
|
6
6
|
from loguru import logger
|
|
7
|
+
from autocoder.common.git_utils import get_repo
|
|
7
8
|
from autocoder.common.printer import Printer
|
|
8
9
|
import byzerllm
|
|
10
|
+
from autocoder.common import git_utils
|
|
9
11
|
|
|
10
12
|
class ActionYmlFileManager:
|
|
11
13
|
"""
|
|
@@ -44,7 +46,7 @@ class ActionYmlFileManager:
|
|
|
44
46
|
except Exception as e:
|
|
45
47
|
logger.error(f"Failed to create actions directory: {e}")
|
|
46
48
|
return False
|
|
47
|
-
return True
|
|
49
|
+
return True
|
|
48
50
|
|
|
49
51
|
def get_action_files(self, filter_prefix: Optional[str] = None) -> List[str]:
|
|
50
52
|
"""
|
|
@@ -183,16 +185,21 @@ class ActionYmlFileManager:
|
|
|
183
185
|
Returns:
|
|
184
186
|
Dict: YAML 内容,如果加载失败返回空字典
|
|
185
187
|
"""
|
|
186
|
-
yaml_path = os.path.join(self.actions_dir, file_name)
|
|
187
|
-
|
|
188
|
+
yaml_path = os.path.join(self.actions_dir, file_name)
|
|
188
189
|
try:
|
|
189
190
|
with open(yaml_path, 'r', encoding='utf-8') as f:
|
|
190
191
|
content = yaml.safe_load(f) or {}
|
|
191
192
|
return content
|
|
192
|
-
except Exception as e:
|
|
193
|
+
except Exception as e:
|
|
193
194
|
self.printer.print_in_terminal("yaml_load_error", style="red",
|
|
194
195
|
yaml_file=yaml_path, error=str(e))
|
|
195
196
|
return {}
|
|
197
|
+
|
|
198
|
+
def get_full_path_by_file_name(self, file_name: str) -> str:
|
|
199
|
+
"""
|
|
200
|
+
根据文件名获取完整路径
|
|
201
|
+
"""
|
|
202
|
+
return os.path.join(self.actions_dir, file_name)
|
|
196
203
|
|
|
197
204
|
def save_yaml_content(self, file_name: str, content: Dict) -> bool:
|
|
198
205
|
"""
|
|
@@ -232,6 +239,26 @@ class ActionYmlFileManager:
|
|
|
232
239
|
yaml_content = self.load_yaml_content(file_name)
|
|
233
240
|
yaml_content[field] = value
|
|
234
241
|
return self.save_yaml_content(file_name, yaml_content)
|
|
242
|
+
|
|
243
|
+
def get_all_commit_id_from_file(self,file_name:str):
|
|
244
|
+
'''
|
|
245
|
+
会包含 revert 信息
|
|
246
|
+
'''
|
|
247
|
+
repo = get_repo(self.source_dir)
|
|
248
|
+
if repo is None:
|
|
249
|
+
logger.error("Repository is not initialized.")
|
|
250
|
+
return []
|
|
251
|
+
|
|
252
|
+
commit_hashes = []
|
|
253
|
+
for commit in repo.iter_commits():
|
|
254
|
+
lines = commit.message.strip().split('\n')
|
|
255
|
+
last_line = lines[-1]
|
|
256
|
+
if file_name in last_line or (commit.message.startswith("<revert>") and file_name in commit.message):
|
|
257
|
+
commit_hash = commit.hexsha
|
|
258
|
+
commit_hashes.append(commit_hash)
|
|
259
|
+
|
|
260
|
+
return commit_hashes
|
|
261
|
+
|
|
235
262
|
|
|
236
263
|
def get_commit_id_from_file(self, file_name: str) -> Optional[str]:
|
|
237
264
|
"""
|
|
@@ -243,16 +270,19 @@ class ActionYmlFileManager:
|
|
|
243
270
|
Returns:
|
|
244
271
|
Optional[str]: commit ID,如果计算失败返回 None
|
|
245
272
|
"""
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
with open(yaml_path, 'r', encoding='utf-8') as f:
|
|
250
|
-
yaml_content = f.read()
|
|
251
|
-
file_md5 = hashlib.md5(yaml_content.encode("utf-8")).hexdigest()
|
|
252
|
-
return f"auto_coder_{file_name}"
|
|
253
|
-
except Exception as e:
|
|
254
|
-
logger.error(f"Failed to calculate commit ID: {e}")
|
|
273
|
+
repo = get_repo(self.source_dir)
|
|
274
|
+
if repo is None:
|
|
275
|
+
logger.error("Repository is not initialized.")
|
|
255
276
|
return None
|
|
277
|
+
|
|
278
|
+
commit_hash = None
|
|
279
|
+
# 这里遍历从最新的commit 开始遍历
|
|
280
|
+
for commit in repo.iter_commits():
|
|
281
|
+
last_line = commit.message.strip().split('\n')[-1]
|
|
282
|
+
if file_name in last_line and not commit.message.startswith("<revert>"):
|
|
283
|
+
commit_hash = commit.hexsha
|
|
284
|
+
break
|
|
285
|
+
return commit_hash
|
|
256
286
|
|
|
257
287
|
def get_file_name_from_commit_id(self, commit_id: str) -> Optional[str]:
|
|
258
288
|
"""
|
|
@@ -298,7 +328,7 @@ class ActionYmlFileManager:
|
|
|
298
328
|
return self.get_file_name_from_commit_id(last_line)
|
|
299
329
|
except Exception as e:
|
|
300
330
|
logger.error(f"Failed to extract file name from commit message: {e}")
|
|
301
|
-
return None
|
|
331
|
+
return None
|
|
302
332
|
|
|
303
333
|
def get_commit_changes(self, file_name: Optional[str] = None) -> List[Tuple[str, List[str], Dict[str, Tuple[str, str]]]]:
|
|
304
334
|
"""
|
|
@@ -327,31 +357,30 @@ class ActionYmlFileManager:
|
|
|
327
357
|
changes = {}
|
|
328
358
|
try:
|
|
329
359
|
repo = git.Repo(self.source_dir)
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
pass # 文件可能是新增的
|
|
360
|
+
commit =repo.commit(commit_id)
|
|
361
|
+
if commit.parents:
|
|
362
|
+
parent = commit.parents[0]
|
|
363
|
+
# 获取所有文件的前后内容
|
|
364
|
+
for diff_item in parent.diff(commit):
|
|
365
|
+
file_path = diff_item.a_path if diff_item.a_path else diff_item.b_path
|
|
366
|
+
|
|
367
|
+
# 获取变更前内容
|
|
368
|
+
before_content = None
|
|
369
|
+
try:
|
|
370
|
+
if diff_item.a_blob:
|
|
371
|
+
before_content = repo.git.show(f"{parent.hexsha}:{file_path}")
|
|
372
|
+
except git.exc.GitCommandError:
|
|
373
|
+
pass # 文件可能是新增的
|
|
345
374
|
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
375
|
+
# 获取变更后内容
|
|
376
|
+
after_content = None
|
|
377
|
+
try:
|
|
378
|
+
if diff_item.b_blob:
|
|
379
|
+
after_content = repo.git.show(f"{commit.hexsha}:{file_path}")
|
|
380
|
+
except git.exc.GitCommandError:
|
|
381
|
+
pass # 文件可能被删除
|
|
353
382
|
|
|
354
|
-
|
|
383
|
+
changes[file_path] = (before_content, after_content)
|
|
355
384
|
break
|
|
356
385
|
except git.exc.GitCommandError as e:
|
|
357
386
|
self.printer.print_in_terminal("git_command_error", style="red", error=str(e))
|
|
@@ -360,6 +389,15 @@ class ActionYmlFileManager:
|
|
|
360
389
|
|
|
361
390
|
return [(query, urls, changes)]
|
|
362
391
|
|
|
392
|
+
def revert_file(self, file_name: str) -> bool:
|
|
393
|
+
revert_result = git_utils.revert_changes(
|
|
394
|
+
self.source_dir, f"auto_coder_{file_name}"
|
|
395
|
+
)
|
|
396
|
+
if revert_result:
|
|
397
|
+
self.update_yaml_field(file_name, "revert_commit_id", revert_result.get("new_commit_hash"))
|
|
398
|
+
return True
|
|
399
|
+
return False
|
|
400
|
+
|
|
363
401
|
def parse_history_tasks(self, limit: int = 5) -> List[Dict]:
|
|
364
402
|
"""
|
|
365
403
|
解析历史任务信息
|