auto-coder 0.1.336__py3-none-any.whl → 0.1.337__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.

@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: auto-coder
3
- Version: 0.1.336
3
+ Version: 0.1.337
4
4
  Summary: AutoCoder: AutoCoder
5
5
  Author: allwefantasy
6
6
  Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
@@ -4,21 +4,21 @@ autocoder/auto_coder_lang.py,sha256=Rtupq6N3_HT7JRhDKdgCBcwRaiAnyCOR_Gsp4jUomrI,
4
4
  autocoder/auto_coder_rag.py,sha256=NesRm7sIJrRQL1xxm_lbMtM7gi-KrYv9f26RfBuloZE,35386
5
5
  autocoder/auto_coder_rag_client_mcp.py,sha256=QRxUbjc6A8UmDMQ8lXgZkjgqtq3lgKYeatJbDY6rSo0,6270
6
6
  autocoder/auto_coder_rag_mcp.py,sha256=-RrjNwFaS2e5v8XDIrKR-zlUNUE8UBaeOtojffBrvJo,8521
7
- autocoder/auto_coder_runner.py,sha256=W08NHr_I-9ldhXUhatnKrUCBL33_mQpF7KFqzp0zMEI,109203
7
+ autocoder/auto_coder_runner.py,sha256=MMppqdwfT1a-NoIxqbQGNS2z2Wi0CWY6X3AK8morCsE,111424
8
8
  autocoder/auto_coder_server.py,sha256=bLORGEclcVdbBVfM140JCI8WtdrU0jbgqdJIVVupiEU,20578
9
9
  autocoder/benchmark.py,sha256=Ypomkdzd1T3GE6dRICY3Hj547dZ6_inqJbBJIp5QMco,4423
10
- autocoder/chat_auto_coder.py,sha256=SzH6fdoH8kJgARYXBu0CTB8J9PY8Q2T9CrIB844PXtM,25841
10
+ autocoder/chat_auto_coder.py,sha256=CthuvdjVjTQOVv-zREsl8OCsZHPSP9OQcIgHULrW2Ro,25842
11
11
  autocoder/chat_auto_coder_lang.py,sha256=RxkYAMWUB5ayX0x03yBOcEkjTcWG_EBsLXBC_bh--cc,22265
12
12
  autocoder/command_args.py,sha256=HxflngkYtTrV17Vfgk6lyUyiG68jP2ftSc7FYr9AXwY,30585
13
13
  autocoder/command_parser.py,sha256=fx1g9E6GaM273lGTcJqaFQ-hoksS_Ik2glBMnVltPCE,10013
14
14
  autocoder/lang.py,sha256=PFtATuOhHRnfpqHQkXr6p4C893JvpsgwTMif3l-GEi0,14321
15
15
  autocoder/models.py,sha256=_SCar82QIeBFTZZBdM2jPS6atKVhHnvE0gX3V0CsxD4,11590
16
16
  autocoder/run_context.py,sha256=IUfSO6_gp2Wt1blFWAmOpN0b0nDrTTk4LmtCYUBIoro,1643
17
- autocoder/version.py,sha256=znLFQLSAKbCRErJEcoRffYh44RYOI_DI4IWhNI0JIy0,23
17
+ autocoder/version.py,sha256=_LNwUtBnPaBerh9KZiByo60wMmCJ6961eqCjdcRR4Zk,23
18
18
  autocoder/agent/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
19
19
  autocoder/agent/agentic_edit.py,sha256=XsfePZ-t6M-uBSdG1VLZXk1goqXk2HPeJ_A8IYyBuWQ,58896
20
20
  autocoder/agent/agentic_edit_types.py,sha256=oFcDd_cxJ2yH9Ed1uTpD3BipudgoIEWDMPb5pAkq4gI,3288
21
- autocoder/agent/agentic_filter.py,sha256=yL7ufHJWIJpwmsd5Z5IAdnLopYN89JgB8DlC7NhTYFU,38780
21
+ autocoder/agent/agentic_filter.py,sha256=9Miqj9lVOkKrKRXK9MZDouhkp2n1s_RakpRwdmLfFtY,39516
22
22
  autocoder/agent/auto_demand_organizer.py,sha256=URAq0gSEiHeV_W4zwhOI_83kHz0Ryfj1gcfh5jwCv_w,6501
23
23
  autocoder/agent/auto_filegroup.py,sha256=pBsAkBcpFTff-9L5OwI8xhf2xPKpl-aZwz-skF2B6dc,6296
24
24
  autocoder/agent/auto_guess_query.py,sha256=rDSdhpPHcOGE5MuDXvIrhCXAPR4ARS1LqpyoLsx2Jhw,11374
@@ -54,7 +54,7 @@ autocoder/common/action_yml_file_manager.py,sha256=DdF5P1R_B_chCnnqoA2IgogakWLZk
54
54
  autocoder/common/anything2images.py,sha256=0ILBbWzY02M-CiWB-vzuomb_J1hVdxRcenAfIrAXq9M,25283
55
55
  autocoder/common/anything2img.py,sha256=iZQmg8srXlD7N5uGl5b_ONKJMBjYoW8kPmokkG6ISF0,10118
56
56
  autocoder/common/audio.py,sha256=Kn9nWKQddWnUrAz0a_ZUgjcu4VUU_IcZBigT7n3N3qc,7439
57
- autocoder/common/auto_coder_lang.py,sha256=34SU-Q_JDjioH_i7jc3JsZkX6SjgueBMC54_P8Xwf5U,40478
57
+ autocoder/common/auto_coder_lang.py,sha256=cNwzXknWDDFUoG68D0xhp1KgTC25bS8pbObeL-1pRpA,40656
58
58
  autocoder/common/auto_configure.py,sha256=D4N-fl9v8bKM5-Ds-uhkC2uGDmHH_ZjLJ759F8KXMKs,13129
59
59
  autocoder/common/buildin_tokenizer.py,sha256=L7d5t39ZFvUd6EoMPXUhYK1toD0FHlRH1jtjKRGokWU,1236
60
60
  autocoder/common/chunk_validation.py,sha256=BrR_ZWavW8IANuueEE7hS8NFAwEvm8TX34WnPx_1hs8,3030
@@ -126,9 +126,10 @@ autocoder/common/v2/code_editblock_manager.py,sha256=G0CIuV9Ki0FqMLnpA8nBT4pnkCN
126
126
  autocoder/common/v2/code_manager.py,sha256=C403bS-f6urixwitlKHcml-J03hci-UyNwHJOqBiY6Q,9182
127
127
  autocoder/common/v2/code_strict_diff_manager.py,sha256=v-J1kDyLg7tLGg_6_lbO9S4fNkx7M_L8Xr2G7fPptiU,9347
128
128
  autocoder/common/v2/agent/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
129
- autocoder/common/v2/agent/agentic_edit.py,sha256=Vv5e_lgzfd9PZS10bJR0yvFzP4MLAVCZB45s02RWXkU,83440
129
+ autocoder/common/v2/agent/agentic_edit.py,sha256=iFr2Umr1qXYGH0enzn2KJS8H2nqfuKkyBidbUKq38Bc,87031
130
+ autocoder/common/v2/agent/agentic_edit_conversation.py,sha256=XtN0D1stP80gKnGiVxFMZL1DbIU56AISyDkS52RMaac,4434
130
131
  autocoder/common/v2/agent/agentic_edit_types.py,sha256=ZCgIu0Dj4xPP9s-lWtzh1-wBvoXrSkgu3pan_Oo_Ng0,4433
131
- autocoder/common/v2/agent/agentic_tool_display.py,sha256=O-H7vV5G-Jlkrul_GWmfUEsJZdeUbwtbBlfONlYD7bY,7382
132
+ autocoder/common/v2/agent/agentic_tool_display.py,sha256=5KshKQX0YFcGobfbJIwylwkalAEuZVUO68hSrIlPM64,7341
132
133
  autocoder/common/v2/agent/agentic_edit_tools/__init__.py,sha256=wGICCc1dYh07osB21j62zOQ9Ws0PyyOQ12UYRHmHrtI,1229
133
134
  autocoder/common/v2/agent/agentic_edit_tools/ask_followup_question_tool_resolver.py,sha256=pjrukXjWXMIfUAUzoHzr7j2Onf1L7bxmjsUR1gGaFoA,2809
134
135
  autocoder/common/v2/agent/agentic_edit_tools/attempt_completion_tool_resolver.py,sha256=82ZGKeRBSDKeead_XVBW4FxpiE-5dS7tBOk_3RZ6B5s,1511
@@ -139,7 +140,7 @@ autocoder/common/v2/agent/agentic_edit_tools/list_files_tool_resolver.py,sha256=
139
140
  autocoder/common/v2/agent/agentic_edit_tools/plan_mode_respond_tool_resolver.py,sha256=SZwFUxK6d2BaKWqQXi_c3IVe2iffviF6VUXJA9T9sx0,1492
140
141
  autocoder/common/v2/agent/agentic_edit_tools/read_file_tool_resolver.py,sha256=9Bh0KVbL0qiIqwChlb77biiBiETQ3zekxGe5Fj7hXAg,2800
141
142
  autocoder/common/v2/agent/agentic_edit_tools/replace_in_file_tool_resolver.py,sha256=tTQpCIGIzh1XO_MZm6wefMvUm_h6cKoa--oPIm-VwXM,7342
142
- autocoder/common/v2/agent/agentic_edit_tools/search_files_tool_resolver.py,sha256=Q5U5CMS-06vwXlI0DZImtGZRpi-WXTb5GNDeIpjIdxQ,5571
143
+ autocoder/common/v2/agent/agentic_edit_tools/search_files_tool_resolver.py,sha256=K-TcqY0z7nDupMkTRDAJdqW3z2Y_RUM_wUb-pOEVQRI,6044
143
144
  autocoder/common/v2/agent/agentic_edit_tools/use_mcp_tool_resolver.py,sha256=wM2Xy4bcnD0TSLEmcM8rvvyyWenN5_KQnJMO6hJ8lTE,1716
144
145
  autocoder/common/v2/agent/agentic_edit_tools/write_to_file_tool_resolver.py,sha256=UO4SrkDek3WDlRdlHH022W1roSNMdMcipJqDxRBlheM,3044
145
146
  autocoder/compilers/__init__.py,sha256=C0HOms70QA747XD0uZEMmGtRFcIPenohyqECNStv0Bw,1647
@@ -275,9 +276,9 @@ autocoder/utils/types.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
275
276
  autocoder/utils/auto_coder_utils/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
276
277
  autocoder/utils/auto_coder_utils/chat_stream_out.py,sha256=KW0mlmcHlStXi8-_6fXZ2-ifeJ5mgP0OV7DQFzCtIsw,14008
277
278
  autocoder/utils/chat_auto_coder_utils/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
278
- auto_coder-0.1.336.dist-info/LICENSE,sha256=HrhfyXIkWY2tGFK11kg7vPCqhgh5DcxleloqdhrpyMY,11558
279
- auto_coder-0.1.336.dist-info/METADATA,sha256=jFmhNbFpLI9K9ggO4_IYJ7FdnWg2P8j2VSZYQQZJwao,2747
280
- auto_coder-0.1.336.dist-info/WHEEL,sha256=GV9aMThwP_4oNCtvEC2ec3qUYutgWeAzklro_0m4WJQ,91
281
- auto_coder-0.1.336.dist-info/entry_points.txt,sha256=0nzHtHH4pNcM7xq4EBA2toS28Qelrvcbrr59GqD_0Ak,350
282
- auto_coder-0.1.336.dist-info/top_level.txt,sha256=Jqc0_uJSw2GwoFQAa9iJxYns-2mWla-9ok_Y3Gcznjk,10
283
- auto_coder-0.1.336.dist-info/RECORD,,
279
+ auto_coder-0.1.337.dist-info/LICENSE,sha256=HrhfyXIkWY2tGFK11kg7vPCqhgh5DcxleloqdhrpyMY,11558
280
+ auto_coder-0.1.337.dist-info/METADATA,sha256=GH7LgmlLQFdtYtvXWvRcDzUoY5toRt_Bmf0XX8Mcghg,2747
281
+ auto_coder-0.1.337.dist-info/WHEEL,sha256=GV9aMThwP_4oNCtvEC2ec3qUYutgWeAzklro_0m4WJQ,91
282
+ auto_coder-0.1.337.dist-info/entry_points.txt,sha256=0nzHtHH4pNcM7xq4EBA2toS28Qelrvcbrr59GqD_0Ak,350
283
+ auto_coder-0.1.337.dist-info/top_level.txt,sha256=Jqc0_uJSw2GwoFQAa9iJxYns-2mWla-9ok_Y3Gcznjk,10
284
+ auto_coder-0.1.337.dist-info/RECORD,,
@@ -259,8 +259,8 @@ class AgenticFilter:
259
259
  3. **深入分析**:
260
260
  * 使用 `read_files` 读取关键文件的内容进行确认。如果文件过大,使用 `line_ranges` 参数分段读取。
261
261
  * 如有必要,使用 `run_python` 或 `execute_shell_command` 执行代码或命令进行更复杂的分析。
262
- 4. **迭代决策**: 根据工具的返回结果,你可能需要多次调用不同的工具来逐步缩小范围或获取更多信息。
263
- 5. **最终响应**: 当你确定了所有需要参考和修改的文件后,**必须**调用 `output_result` 工具,并提供符合其要求格式的JSON字符串作为其 `response` 参数。
262
+ 4. **迭代决策**: 根据工具的返回结果,你可能需要多次调用不同的工具来逐步缩小范围或获取更多信息。
263
+ 6. **最终响应**: 当你确定了所有需要参考和修改的文件后,**必须**调用 `output_result` 工具,并提供符合其要求格式的JSON字符串作为其 `response` 参数。
264
264
  该json格式要求为:
265
265
  ```json
266
266
  {
@@ -273,9 +273,17 @@ class AgenticFilter:
273
273
  "reasoning": "详细说明你是如何通过分析和使用工具得出这个文件列表的。"
274
274
  }
275
275
  ```
276
-
277
-
278
- """
276
+
277
+ {% if enable_active_context %}
278
+ ** 非常非常重要的提示 **
279
+ 每一个目录都有一个描述信息,比如 {{ project_path }}/src/abc/bbc 的目录描述信息会放在 {{ project_path }}/.auto-coder/active-context/src/abc/bbc/active.md 文件中。
280
+ 你可以使用 read_files 函数读取,从而帮助你更好的挑选要详细阅读哪个文件。值得注意的是,active.md 并不会包含该目录下所有的文件信息,只保存最近发生变更的文件的信息。
281
+ {% endif %}
282
+ """
283
+ return {
284
+ "project_path": os.path.abspath(self.args.source_dir),
285
+ "enable_active_context": self.args.enable_active_context,
286
+ }
279
287
 
280
288
  @byzerllm.prompt()
281
289
  def _execute_command_result(self, result: str) -> str:
@@ -590,8 +598,7 @@ class AgenticFilter:
590
598
  - 如果未找到匹配项,会返回提示信息
591
599
 
592
600
  </usage>
593
- </command>
594
-
601
+ </command>
595
602
  <command>
596
603
  <n>execute_mcp_server</n>
597
604
  <description>执行MCP服务器</description>
@@ -22,6 +22,8 @@ from autocoder.common.result_manager import ResultManager
22
22
  from autocoder.version import __version__
23
23
  from autocoder.auto_coder import main as auto_coder_main
24
24
  from autocoder.utils import get_last_yaml_file
25
+ from autocoder.commands.auto_command import CommandAutoTuner, AutoCommandRequest, CommandConfig, MemoryConfig
26
+ from autocoder.common.v2.agent.agentic_edit import AgenticEdit,AgenticEditRequest
25
27
  from autocoder.index.symbols_utils import (
26
28
  extract_symbols,
27
29
  SymbolType,
@@ -60,7 +62,7 @@ from autocoder.common.conf_validator import ConfigValidator
60
62
  from autocoder import command_parser as CommandParser
61
63
  from loguru import logger as global_logger
62
64
  from autocoder.utils.project_structure import EnhancedFileAnalyzer
63
- from autocoder.common import SourceCodeList
65
+ from autocoder.common import SourceCodeList,SourceCode
64
66
 
65
67
 
66
68
  ## 对外API,用于第三方集成 auto-coder 使用。
@@ -2777,22 +2779,67 @@ def conf_import(path: str):
2777
2779
  from autocoder.common.conf_import_export import import_conf
2778
2780
  import_conf(os.getcwd(), path)
2779
2781
 
2782
+ def generate_new_yaml(query: str):
2783
+ memory = get_memory()
2784
+ conf = memory.get("conf",{})
2785
+ current_files = memory.get("current_files",{}).get("files",[])
2786
+ auto_coder_main(["next", "chat_action"])
2787
+ latest_yaml_file = get_last_yaml_file("actions")
2788
+ if latest_yaml_file:
2789
+ yaml_config = {
2790
+ "include_file": ["./base/base.yml"],
2791
+ "auto_merge": conf.get("auto_merge", "editblock"),
2792
+ "human_as_model": conf.get("human_as_model", "false") == "true",
2793
+ "skip_build_index": conf.get("skip_build_index", "true") == "true",
2794
+ "skip_confirm": conf.get("skip_confirm", "true") == "true",
2795
+ "silence": conf.get("silence", "true") == "true",
2796
+ "include_project_structure": conf.get("include_project_structure", "true")
2797
+ == "true",
2798
+ "exclude_files": memory.get("exclude_files", []),
2799
+ }
2800
+ yaml_config["context"] = ""
2801
+ for key, value in conf.items():
2802
+ converted_value = convert_config_value(key, value)
2803
+ if converted_value is not None:
2804
+ yaml_config[key] = converted_value
2805
+
2806
+ yaml_config["urls"] = current_files + get_llm_friendly_package_docs(
2807
+ return_paths=True
2808
+ )
2809
+ # handle image
2810
+ v = Image.convert_image_paths_from(query)
2811
+ yaml_config["query"] = v
2812
+
2813
+ yaml_content = convert_yaml_config_to_str(yaml_config=yaml_config)
2814
+
2815
+ execute_file = os.path.join("actions", latest_yaml_file)
2816
+ with open(os.path.join(execute_file), "w",encoding="utf-8") as f:
2817
+ f.write(yaml_content)
2818
+ return execute_file,convert_yaml_to_config(execute_file)
2819
+
2780
2820
  @run_in_raw_thread()
2781
2821
  def auto_command(query: str,extra_args: Dict[str,Any]={}):
2782
- """处理/auto指令"""
2783
- from autocoder.commands.auto_command import CommandAutoTuner, AutoCommandRequest, CommandConfig, MemoryConfig
2784
- args = get_final_config()
2785
-
2822
+ """处理/auto指令"""
2823
+ args = get_final_config()
2824
+ memory = get_memory()
2786
2825
  if args.enable_agentic_edit:
2787
- from autocoder.common.v2.agent.agentic_edit import AgenticEdit,AgenticEditRequest
2788
- llm = get_single_llm(args.code_model or args.model,product_mode=args.product_mode)
2789
- agent = AgenticEdit(llm=llm,args=args,files=SourceCodeList(sources=[]),
2790
- conversation_history=[],
2791
- memory_config=MemoryConfig(memory=memory,
2792
- save_memory_func=save_memory), command_config=CommandConfig)
2793
- agent.run_in_terminal(AgenticEditRequest(user_input=query))
2794
- return
2795
-
2826
+ execute_file,args = generate_new_yaml(query)
2827
+ args.file = execute_file
2828
+ current_files = memory.get("current_files",{}).get("files",[])
2829
+ sources = []
2830
+ for file in current_files:
2831
+ with open(file,"r",encoding="utf-8") as f:
2832
+ sources.append(SourceCode(module_name=file,source_code=f.read()))
2833
+
2834
+ llm = get_single_llm(args.code_model or args.model,product_mode=args.product_mode)
2835
+ agent = AgenticEdit(llm=llm,args=args,files=SourceCodeList(sources=sources),
2836
+ conversation_history=[],
2837
+ memory_config=MemoryConfig(memory=memory,
2838
+ save_memory_func=save_memory), command_config=CommandConfig)
2839
+ agent.run_in_terminal(AgenticEditRequest(user_input=query))
2840
+ return
2841
+
2842
+ args = get_final_config()
2796
2843
  # 准备请求参数
2797
2844
  request = AutoCommandRequest(
2798
2845
  user_input=query
@@ -668,8 +668,7 @@ def main():
668
668
  try:
669
669
  # Shutdown all plugins before exiting
670
670
  plugin_manager.shutdown_all()
671
-
672
- save_memory()
671
+ # save_memory()
673
672
  try:
674
673
  if get_mcp_server():
675
674
  get_mcp_server().stop()
@@ -825,6 +825,14 @@ MESSAGES = {
825
825
  "/compile/check/end": {
826
826
  "en": "Finished compile error checking process.",
827
827
  "zh": "结束编译错误检查过程."
828
+ },
829
+ "/agent/edit/objective":{
830
+ "en":"Objective",
831
+ "zh":"目标"
832
+ },
833
+ "/agent/edit/user_query":{
834
+ "en":"User Query",
835
+ "zh":"用户查询"
828
836
  }
829
837
  }
830
838
 
@@ -12,7 +12,8 @@ from rich.panel import Panel
12
12
  from pydantic import SkipValidation
13
13
 
14
14
  # Removed ResultManager, stream_out, git_utils, AutoCommandTools, count_tokens, global_cancel, ActionYmlFileManager, get_event_manager, EventContentCreator, get_run_context, AgenticFilterStreamOutType
15
- from autocoder.auto_coder import AutoCoderArgs
15
+ from autocoder.common import AutoCoderArgs, git_utils, SourceCodeList, SourceCode
16
+ from autocoder.common.global_cancel import global_cancel
16
17
  from autocoder.common import detect_env
17
18
  from autocoder.common import shells
18
19
  from loguru import logger
@@ -34,10 +35,13 @@ from rich.syntax import Syntax # Added
34
35
  from rich.markdown import Markdown # Added
35
36
  from autocoder.events.event_manager_singleton import get_event_manager
36
37
  from autocoder.events.event_types import Event, EventType, EventMetadata
38
+ from autocoder.memory.active_context_manager import ActiveContextManager
37
39
  from autocoder.events import event_content as EventContentCreator
38
40
  from autocoder.shadows.shadow_manager import ShadowManager
39
41
  from autocoder.linters.shadow_linter import ShadowLinter
40
42
  from autocoder.compilers.shadow_compiler import ShadowCompiler
43
+ from autocoder.common.action_yml_file_manager import ActionYmlFileManager
44
+ from autocoder.common.auto_coder_lang import get_message
41
45
  # Import the new display function
42
46
  from autocoder.common.v2.agent.agentic_tool_display import get_tool_display_message
43
47
  from autocoder.common.v2.agent.agentic_edit_types import FileChangeEntry
@@ -655,6 +659,13 @@ class AgenticEdit:
655
659
  3. Remember, you have extensive capabilities with access to a wide range of tools that can be used in powerful and clever ways as necessary to accomplish each goal. Before calling a tool, do some analysis within <thinking></thinking> tags. First, analyze the file structure provided in environment_details to gain context and insights for proceeding effectively. Then, think about which of the provided tools is the most relevant tool to accomplish the user's task. Next, go through each of the required parameters of the relevant tool and determine if the user has directly provided or given enough information to infer a value. When deciding if the parameter can be inferred, carefully consider all the context to see if it supports a specific value. If all of the required parameters are present or can be reasonably inferred, close the thinking tag and proceed with the tool use. BUT, if one of the values for a required parameter is missing, DO NOT invoke the tool (not even with fillers for the missing params) and instead, ask the user to provide the missing parameters using the ask_followup_question tool. DO NOT ask for more information on optional parameters if it is not provided.
656
660
  4. Once you've completed the user's task, you must use the attempt_completion tool to present the result of the task to the user. You may also provide a CLI command to showcase the result of your task; this can be particularly useful for web development tasks, where you can run e.g. \`open index.html\` to show the website you've built.
657
661
  5. The user may provide feedback, which you can use to make improvements and try again. But DO NOT continue in pointless back and forth conversations, i.e. don't end your responses with questions or offers for further assistance.
662
+
663
+ {{ enable_active_context }}
664
+ **Very Important Notice**
665
+ Each directory has a description file stored separately. For example, the description for the directory `{{ current_project }}/src/abc/bbc` can be found in the file `{{ current_project }}/.auto-coder/active-context/src/abc/bbc/active.md`.
666
+ You can use the tool `read_file` to read these description files, which helps you decide exactly which files need detailed attention. Note that the `active.md` file does not contain information about all files within the directory—it only includes information
667
+ about the files that were recently changed.
668
+ {{ enable_active_context }}
658
669
  """
659
670
  env_info = detect_env()
660
671
  shell_type = "bash"
@@ -674,6 +685,7 @@ class AgenticEdit:
674
685
  "home_dir": os.path.expanduser("~"),
675
686
  "files": self.files.to_str(),
676
687
  "mcp_server_info": self.mcp_server_info,
688
+ "enable_active_context": self.args.enable_active_context,
677
689
  }
678
690
 
679
691
  # Removed _execute_command_result and execute_auto_command methods
@@ -732,11 +744,12 @@ class AgenticEdit:
732
744
  f"Initial conversation history size: {len(conversations)}")
733
745
 
734
746
  while True:
747
+ global_cancel.check_and_raise()
735
748
  logger.info(
736
749
  f"Starting LLM interaction cycle. History size: {len(conversations)}")
737
750
  tool_executed = False
738
751
  assistant_buffer = ""
739
-
752
+
740
753
  llm_response_gen = stream_chat_with_continue(
741
754
  llm=self.llm,
742
755
  conversations=conversations,
@@ -749,6 +762,7 @@ class AgenticEdit:
749
762
  llm_response_gen,meta_holder)
750
763
 
751
764
  for event in parsed_events:
765
+ global_cancel.check_and_raise()
752
766
  if isinstance(event, (LLMOutputEvent, LLMThinkingEvent)):
753
767
  assistant_buffer += event.text
754
768
  yield event # Yield text/thinking immediately for display
@@ -929,6 +943,8 @@ class AgenticEdit:
929
943
  return None
930
944
 
931
945
  for content_chunk, metadata in generator:
946
+ global_cancel.check_and_raise()
947
+
932
948
  meta_holder.meta = metadata
933
949
  if not content_chunk:
934
950
  continue
@@ -1160,17 +1176,51 @@ class AgenticEdit:
1160
1176
  )
1161
1177
  event_manager.write_error(content=error_content.to_dict(), metadata=metadata.to_dict())
1162
1178
  # Re-raise the exception if needed, or handle appropriately
1163
- # raise e
1179
+ raise e
1164
1180
 
1165
1181
  def apply_changes(self):
1166
1182
  """
1167
1183
  Apply all tracked file changes to the original project directory.
1168
- """
1169
- for change in self.get_all_file_changes():
1170
- file_path = change['file_path']
1171
- content = change['content']
1184
+ """
1185
+ for (file_path,change) in self.get_all_file_changes().items():
1172
1186
  with open(file_path, 'w', encoding='utf-8') as f:
1173
- f.write(content)
1187
+ f.write(change.content)
1188
+
1189
+ if len(self.get_all_file_changes()) > 0:
1190
+ if not self.args.skip_commit:
1191
+ try:
1192
+ file_name = os.path.basename(self.args.file)
1193
+ commit_result = git_utils.commit_changes(
1194
+ self.args.source_dir,
1195
+ f"{self.args.query}\nauto_coder_{file_name}",
1196
+ )
1197
+
1198
+ action_yml_file_manager = ActionYmlFileManager(self.args.source_dir)
1199
+ action_file_name = os.path.basename(self.args.file)
1200
+ add_updated_urls = []
1201
+ commit_result.changed_files
1202
+ for file in commit_result.changed_files:
1203
+ add_updated_urls.append(os.path.join(self.args.source_dir, file))
1204
+
1205
+ self.args.add_updated_urls = add_updated_urls
1206
+ update_yaml_success = action_yml_file_manager.update_yaml_field(action_file_name, "add_updated_urls", add_updated_urls)
1207
+ if not update_yaml_success:
1208
+ self.printer.print_in_terminal("yaml_save_error", style="red", yaml_file=action_file_name)
1209
+
1210
+ if self.args.enable_active_context:
1211
+ active_context_manager = ActiveContextManager(self.llm, self.args.source_dir)
1212
+ task_id = active_context_manager.process_changes(self.args)
1213
+ self.printer.print_in_terminal("active_context_background_task",
1214
+ style="blue",
1215
+ task_id=task_id)
1216
+ git_utils.print_commit_info(commit_result=commit_result)
1217
+ except Exception as e:
1218
+ self.printer.print_str_in_terminal(
1219
+ self.git_require_msg(source_dir=self.args.source_dir, error=str(e)),
1220
+ style="red"
1221
+ )
1222
+ else:
1223
+ self.printer.print_in_terminal("no_changes_made")
1174
1224
 
1175
1225
  def run_in_terminal(self, request: AgenticEditRequest):
1176
1226
  """
@@ -1181,7 +1231,7 @@ class AgenticEdit:
1181
1231
  project_name = os.path.basename(os.path.abspath(self.args.source_dir))
1182
1232
  console.rule(f"[bold cyan]Starting Agentic Edit: {project_name}[/]")
1183
1233
  console.print(Panel(
1184
- f"[bold]User Query:[/bold]\n{request.user_input}", title="Objective", border_style="blue"))
1234
+ f"[bold]{get_message('/agent/edit/user_query')}:[/bold]\n{request.user_input}", title=get_message("/agent/edit/objective"), border_style="blue"))
1185
1235
 
1186
1236
  try:
1187
1237
  event_stream = self.analyze(request)
@@ -1214,12 +1264,17 @@ class AgenticEdit:
1214
1264
  base_content = f"[bold]Status:[/bold] {'Success' if result.success else 'Failure'}\n"
1215
1265
  base_content += f"[bold]Message:[/bold] {result.message}\n"
1216
1266
 
1267
+ def _format_content(content):
1268
+ if len(content) > 200:
1269
+ return f"{content[:100]}\n...\n{content[-100:]}"
1270
+ else:
1271
+ return content
1272
+
1217
1273
  # Prepare panel for base info first
1218
1274
  panel_content = [base_content]
1219
1275
  syntax_content = None
1220
1276
 
1221
- if result.content is not None:
1222
- panel_content.append("[bold]Content:[/bold]\n")
1277
+ if result.content is not None:
1223
1278
  content_str = ""
1224
1279
  try:
1225
1280
  if isinstance(result.content, (dict, list)):
@@ -1257,16 +1312,16 @@ class AgenticEdit:
1257
1312
  lexer = "text"
1258
1313
 
1259
1314
  syntax_content = Syntax(
1260
- result.content[0:100], lexer, theme="default", line_numbers=True)
1315
+ _format_content(result.content), lexer, theme="default", line_numbers=True)
1261
1316
  else:
1262
1317
  content_str = str(result.content)
1263
1318
  # Append simple string content directly
1264
- panel_content.append(content_str[0:100])
1319
+ panel_content.append(_format_content(content_str))
1265
1320
  except Exception as e:
1266
1321
  logger.warning(
1267
1322
  f"Error formatting tool result content: {e}")
1268
1323
  panel_content.append(
1269
- str(result.content)) # Fallback
1324
+ _format_content(str(result.content))) # Fallback
1270
1325
 
1271
1326
  # Print the base info panel
1272
1327
  console.print(Panel("\n".join(
@@ -1298,5 +1353,6 @@ class AgenticEdit:
1298
1353
  "An unexpected error occurred during agent execution:")
1299
1354
  console.print(Panel(
1300
1355
  f"[bold red]FATAL ERROR:[/bold red]\n{str(e)}", title="🔥 System Error", border_style="red"))
1356
+ raise e
1301
1357
  finally:
1302
1358
  console.rule("[bold cyan]Agentic Edit Finished[/]")
@@ -0,0 +1,113 @@
1
+ # src/autocoder/common/v2/agent/agentic_edit_conversation.py
2
+ import os
3
+ import json
4
+ from typing import List, Dict, Any, Optional
5
+ from autocoder.common import AutoCoderArgs
6
+
7
+ # Define a type alias for a message dictionary
8
+ MessageType = Dict[str, Any]
9
+
10
+ class AgenticConversation:
11
+ """
12
+ Manages the conversation history for an agentic editing process.
13
+
14
+ Handles adding messages (user, assistant, tool calls, tool results)
15
+ and retrieving the history.
16
+ """
17
+
18
+ def __init__(self, args: AutoCoderArgs, initial_history: Optional[List[MessageType]] = None):
19
+ """
20
+ Initializes the conversation history.
21
+
22
+ Args:
23
+ initial_history: An optional list of messages to start with.
24
+ """
25
+ self.project_path = args.source_dir
26
+ self._history: List[MessageType] = initial_history if initial_history is not None else []
27
+ self.memory_file_path = os.path.join(self.project_path, ".auto-coder", "memory", "agentic_edit_memory.json")
28
+ self._load_memory()
29
+
30
+ def add_message(self, role: str, content: Any, **kwargs):
31
+ """
32
+ Adds a message to the conversation history.
33
+
34
+ Args:
35
+ role: The role of the message sender (e.g., "user", "assistant", "tool").
36
+ content: The content of the message. Can be None for messages like tool calls.
37
+ **kwargs: Additional key-value pairs to include in the message dictionary (e.g., tool_calls, tool_call_id).
38
+ """
39
+ message: MessageType = {"role": role}
40
+ if content is not None:
41
+ message["content"] = content
42
+ message.update(kwargs)
43
+ self._history.append(message)
44
+ self._save_memory()
45
+
46
+ def add_user_message(self, content: str):
47
+ """Adds a user message."""
48
+ self.add_message(role="user", content=content)
49
+
50
+ def add_assistant_message(self, content: str):
51
+ """Adds an assistant message (potentially containing text response)."""
52
+ self.add_message(role="assistant", content=content)
53
+
54
+ def add_assistant_tool_call_message(self, tool_calls: List[Dict[str, Any]], content: Optional[str] = None):
55
+ """
56
+ Adds a message representing one or more tool calls from the assistant.
57
+ Optionally includes assistant's textual reasoning/content alongside the calls.
58
+ """
59
+ self.add_message(role="assistant", content=content, tool_calls=tool_calls)
60
+
61
+
62
+ def add_tool_result_message(self, tool_call_id: str, content: Any):
63
+ """Adds a message representing the result of a specific tool call."""
64
+ # The content here is typically the output/result from the tool execution.
65
+ self.add_message(role="tool", content=content, tool_call_id=tool_call_id)
66
+
67
+
68
+ def get_history(self) -> List[MessageType]:
69
+ """
70
+ Returns the current conversation history.
71
+
72
+ Returns:
73
+ A list of message dictionaries.
74
+ """
75
+ # Return a deep copy might be safer if messages contain mutable objects,
76
+ # but a shallow copy is usually sufficient for typical message structures.
77
+ return self._history.copy()
78
+
79
+ def clear_history(self):
80
+ """Clears the conversation history."""
81
+ self._history = []
82
+
83
+ def __len__(self) -> int:
84
+ """Returns the number of messages in the history."""
85
+ return len(self._history)
86
+
87
+ def __str__(self) -> str:
88
+ """Returns a string representation of the conversation history."""
89
+ # Consider a more readable format if needed for debugging
90
+ return str(self._history)
91
+
92
+ # Potential future enhancements:
93
+ # - Method to limit history size (by tokens or message count)
94
+ # - Method to format history specifically for different LLM APIs
95
+ # - Serialization/deserialization methods
96
+
97
+ def _save_memory(self):
98
+ try:
99
+ os.makedirs(os.path.dirname(self.memory_file_path), exist_ok=True)
100
+ with open(self.memory_file_path, "w", encoding="utf-8") as f:
101
+ json.dump(self._history, f, ensure_ascii=False, indent=2)
102
+ except Exception as e:
103
+ # Optionally log or ignore
104
+ pass
105
+
106
+ def _load_memory(self):
107
+ try:
108
+ if os.path.exists(self.memory_file_path):
109
+ with open(self.memory_file_path, "r", encoding="utf-8") as f:
110
+ self._history = json.load(f)
111
+ except Exception as e:
112
+ # Ignore loading errors, start fresh
113
+ pass
@@ -54,9 +54,14 @@ class SearchFilesToolResolver(BaseToolResolver):
54
54
  compiled_regex = re.compile(regex_pattern)
55
55
  search_glob_pattern = os.path.join(search_base_path, "**", file_pattern)
56
56
 
57
- logger.info(f"Searching for regex '{regex_pattern}' in files matching '{file_pattern}' under '{search_base_path}' (shadow: {shadow_exists})")
57
+ ignored_dirs = ['.git', 'node_modules', '.mvn', '.idea', '__pycache__', '.venv', 'venv', 'dist', 'build', '.gradle']
58
+ logger.info(f"Searching for regex '{regex_pattern}' in files matching '{file_pattern}' under '{search_base_path}' (shadow: {shadow_exists}), ignoring directories: {ignored_dirs}")
58
59
 
59
60
  for filepath in glob.glob(search_glob_pattern, recursive=True):
61
+ normalized_path = filepath.replace("\\", "/") # Normalize for Windows paths
62
+ if any(f"/{ignored_dir}/" in normalized_path or normalized_path.endswith(f"/{ignored_dir}") or f"/{ignored_dir}/" in normalized_path for ignored_dir in ignored_dirs):
63
+ continue
64
+
60
65
  if os.path.isfile(filepath):
61
66
  try:
62
67
  with open(filepath, 'r', encoding='utf-8', errors='replace') as f:
@@ -129,11 +129,11 @@ def get_tool_display_message(tool: BaseTool) -> str:
129
129
  "ellipsis": '...' if len(tool.content) > 150 else ''
130
130
  }
131
131
  elif isinstance(tool, ReplaceInFileTool):
132
- snippet = tool.diff[:200]
132
+ snippet = tool.diff
133
133
  context = {
134
134
  "path": tool.path,
135
135
  "diff_snippet": snippet,
136
- "ellipsis": '...' if len(tool.diff) > 200 else ''
136
+ "ellipsis": ''
137
137
  }
138
138
  elif isinstance(tool, ExecuteCommandTool):
139
139
  context = {"command": tool.command, "requires_approval": tool.requires_approval}
autocoder/version.py CHANGED
@@ -1 +1 @@
1
- __version__ = "0.1.336"
1
+ __version__ = "0.1.337"