auto-coder 0.1.359__py3-none-any.whl → 0.1.361__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.359.dist-info → auto_coder-0.1.361.dist-info}/METADATA +1 -1
- {auto_coder-0.1.359.dist-info → auto_coder-0.1.361.dist-info}/RECORD +22 -19
- autocoder/agent/auto_review_commit.py +5 -3
- autocoder/auto_coder.py +3 -3
- autocoder/common/code_auto_generate.py +23 -2
- autocoder/common/code_auto_generate_diff.py +28 -3
- autocoder/common/code_auto_generate_editblock.py +27 -3
- autocoder/common/code_auto_generate_strict_diff.py +28 -2
- autocoder/common/directory_cache/__init__.py +1 -0
- autocoder/common/directory_cache/cache.py +192 -0
- autocoder/common/directory_cache/test_cache.py +190 -0
- autocoder/common/file_monitor/monitor.py +1 -1
- autocoder/common/v2/agent/agentic_edit.py +45 -30
- autocoder/common/v2/code_auto_generate.py +85 -1
- autocoder/common/v2/code_auto_generate_diff.py +8 -6
- autocoder/common/v2/code_auto_generate_editblock.py +26 -3
- autocoder/common/v2/code_auto_generate_strict_diff.py +27 -4
- autocoder/version.py +1 -1
- {auto_coder-0.1.359.dist-info → auto_coder-0.1.361.dist-info}/LICENSE +0 -0
- {auto_coder-0.1.359.dist-info → auto_coder-0.1.361.dist-info}/WHEEL +0 -0
- {auto_coder-0.1.359.dist-info → auto_coder-0.1.361.dist-info}/entry_points.txt +0 -0
- {auto_coder-0.1.359.dist-info → auto_coder-0.1.361.dist-info}/top_level.txt +0 -0
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
autocoder/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
2
|
-
autocoder/auto_coder.py,sha256=
|
|
2
|
+
autocoder/auto_coder.py,sha256=PjMhyZCMm8HFG9BAvj6xwQ4DoMielPRvzOVS3oa1ZTk,67060
|
|
3
3
|
autocoder/auto_coder_lang.py,sha256=Rtupq6N3_HT7JRhDKdgCBcwRaiAnyCOR_Gsp4jUomrI,3229
|
|
4
4
|
autocoder/auto_coder_rag.py,sha256=ru5o86IaKylyVRlVORmnrdf3Q1To2eWi2KLdT9FMW0k,37580
|
|
5
5
|
autocoder/auto_coder_rag_client_mcp.py,sha256=QRxUbjc6A8UmDMQ8lXgZkjgqtq3lgKYeatJbDY6rSo0,6270
|
|
@@ -14,7 +14,7 @@ autocoder/command_parser.py,sha256=fx1g9E6GaM273lGTcJqaFQ-hoksS_Ik2glBMnVltPCE,1
|
|
|
14
14
|
autocoder/lang.py,sha256=PFtATuOhHRnfpqHQkXr6p4C893JvpsgwTMif3l-GEi0,14321
|
|
15
15
|
autocoder/models.py,sha256=Gu50IATQtZtgEir1PpCfwgH6o4ygw6XqqbQRj3lx5dU,13798
|
|
16
16
|
autocoder/run_context.py,sha256=IUfSO6_gp2Wt1blFWAmOpN0b0nDrTTk4LmtCYUBIoro,1643
|
|
17
|
-
autocoder/version.py,sha256
|
|
17
|
+
autocoder/version.py,sha256=-eHH-Zoj_ykjiLWosogiY77V86O55hXvZbTnLHM8u8A,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
|
|
@@ -24,7 +24,7 @@ autocoder/agent/auto_filegroup.py,sha256=pBsAkBcpFTff-9L5OwI8xhf2xPKpl-aZwz-skF2
|
|
|
24
24
|
autocoder/agent/auto_guess_query.py,sha256=rDSdhpPHcOGE5MuDXvIrhCXAPR4ARS1LqpyoLsx2Jhw,11374
|
|
25
25
|
autocoder/agent/auto_learn.py,sha256=uNpfvE_EYGi79KUJEe7g-j5VanbmYOYYnxWf32DaWGE,22359
|
|
26
26
|
autocoder/agent/auto_learn_from_commit.py,sha256=edD4GQJyO2qvVnTKyldeswWoNeKe1Aaua6ieJzlGlFI,10662
|
|
27
|
-
autocoder/agent/auto_review_commit.py,sha256=
|
|
27
|
+
autocoder/agent/auto_review_commit.py,sha256=1z9FOUDPZTWnrPmJ-TwUlXLOTDPmRcAlYqXbUj1pi08,11015
|
|
28
28
|
autocoder/agent/auto_tool.py,sha256=DBzip-P_T6ZtT2eHexPcusmKYD0h7ufzp7TLwXAY10E,11554
|
|
29
29
|
autocoder/agent/coder.py,sha256=x6bdJwDuETGg9ebQnYlUWCxCtQcDGg73LtI6McpWslQ,72034
|
|
30
30
|
autocoder/agent/designer.py,sha256=EpRbzO58Xym3GrnppIT1Z8ZFAlnNfgzHbIzZ3PX-Yv8,27037
|
|
@@ -64,10 +64,10 @@ autocoder/common/buildin_tokenizer.py,sha256=L7d5t39ZFvUd6EoMPXUhYK1toD0FHlRH1jt
|
|
|
64
64
|
autocoder/common/chunk_validation.py,sha256=BrR_ZWavW8IANuueEE7hS8NFAwEvm8TX34WnPx_1hs8,3030
|
|
65
65
|
autocoder/common/cleaner.py,sha256=NU72i8C6o9m0vXExab7nao5bstBUsfJFcj11cXa9l4U,1089
|
|
66
66
|
autocoder/common/code_auto_execute.py,sha256=4KXGmiGObr_B1d6tzV9dwS6MifCSc3Gm4j2d6ildBXQ,6867
|
|
67
|
-
autocoder/common/code_auto_generate.py,sha256=
|
|
68
|
-
autocoder/common/code_auto_generate_diff.py,sha256=
|
|
69
|
-
autocoder/common/code_auto_generate_editblock.py,sha256=
|
|
70
|
-
autocoder/common/code_auto_generate_strict_diff.py,sha256=
|
|
67
|
+
autocoder/common/code_auto_generate.py,sha256=6O7QiJe7514GCGuy4z-udzA2_h7TxEWHaJG7VyoCSSA,12151
|
|
68
|
+
autocoder/common/code_auto_generate_diff.py,sha256=WwMystn0cEFQMUKhIUa5EmNPzvnUMjKiPFpDb1nFb1A,19196
|
|
69
|
+
autocoder/common/code_auto_generate_editblock.py,sha256=JmnHqtt346hFFcLh-vb7_JYzb3PAsNCQZh2Owea9mVI,21906
|
|
70
|
+
autocoder/common/code_auto_generate_strict_diff.py,sha256=NSx1RYtNEQX2qFk1TfJlcTxiUB8Q4-PUxXk9TDV1-ak,18068
|
|
71
71
|
autocoder/common/code_auto_merge.py,sha256=WaU-T-ZVn3QDaA_SrdkHciUPKDcTfVa-IbhHKBYEv5w,9961
|
|
72
72
|
autocoder/common/code_auto_merge_diff.py,sha256=DcljWrtlejq2cb9Gj-jBjvUQzRbCE2uMNGg8SBOhEnk,19271
|
|
73
73
|
autocoder/common/code_auto_merge_editblock.py,sha256=5PLH8Ey4GYsPNMGn36pSy_IgwgZ8-j1QF5FEv-THC-0,18397
|
|
@@ -121,8 +121,11 @@ autocoder/common/conversations/__init__.py,sha256=xGZeOFrDsgg2fkPK1zmvYBDhAyX66F
|
|
|
121
121
|
autocoder/common/conversations/compatibility.py,sha256=WuBXB4-dw5X9LUMsB16VWbihvRZQ1tT99m6zuBwDfqE,9606
|
|
122
122
|
autocoder/common/conversations/conversation_manager.py,sha256=ZhuhfSdOTncqgy3nHPoEU7Cg0dCsSl-VPcvLbUlL2Tk,18295
|
|
123
123
|
autocoder/common/conversations/example.py,sha256=Pz_EhO6qneUFMfHZiDmGAClZ6b0V4T1sbC8tIMxX2RM,5437
|
|
124
|
+
autocoder/common/directory_cache/__init__.py,sha256=AbpHGcgLb-kRsJGnwFEktk7uzpZOCcBY74-YBdrKVGs,1
|
|
125
|
+
autocoder/common/directory_cache/cache.py,sha256=Jknygb_U6DkF04_SX04IwsOcQdd-2QQ4d6k9Ucc9OZ0,9358
|
|
126
|
+
autocoder/common/directory_cache/test_cache.py,sha256=0iQkHaZQPhZBwSS6dwK_je93QMLbYGY0BYrTSt45Cao,6610
|
|
124
127
|
autocoder/common/file_monitor/__init__.py,sha256=9reL3IEnyLWU77WjPzeprM8-4lCetlSMZ94Nuxk5KNg,85
|
|
125
|
-
autocoder/common/file_monitor/monitor.py,sha256=
|
|
128
|
+
autocoder/common/file_monitor/monitor.py,sha256=biS9TJyNKga2dE-CeYAi9xfXvA9aMeMl0tBf68G-SBE,16609
|
|
126
129
|
autocoder/common/ignorefiles/__init__.py,sha256=P0hq7Avu1IeXBYEkPBZLsJhFzhzyktUWTqaRIXiAFLY,75
|
|
127
130
|
autocoder/common/ignorefiles/ignore_file_utils.py,sha256=H1gUjjYLHZ_4GZel9bN5lEgpTlOyfPdIhyNRqd7no4c,3484
|
|
128
131
|
autocoder/common/ignorefiles/test_ignore_file_utils.py,sha256=EydHG6E2iPsnbt-Jt8Go-WvRgFtBW6QkHUQ9nI4cF-w,3111
|
|
@@ -133,10 +136,10 @@ autocoder/common/rulefiles/__init__.py,sha256=babSbPdFaXk1NvdHtH2zrJLb_tWd7d2ELI
|
|
|
133
136
|
autocoder/common/rulefiles/autocoderrules_utils.py,sha256=JsB0BkdyygbTOEBfaAB2WA4RFU6Q3VamaFncmbbiLRE,10011
|
|
134
137
|
autocoder/common/v2/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
135
138
|
autocoder/common/v2/code_agentic_editblock_manager.py,sha256=pAh918YMgmLenXmNKXlmDPgKyVJjOuk69901VEEQHm4,34980
|
|
136
|
-
autocoder/common/v2/code_auto_generate.py,sha256=
|
|
137
|
-
autocoder/common/v2/code_auto_generate_diff.py,sha256=
|
|
138
|
-
autocoder/common/v2/code_auto_generate_editblock.py,sha256=
|
|
139
|
-
autocoder/common/v2/code_auto_generate_strict_diff.py,sha256=
|
|
139
|
+
autocoder/common/v2/code_auto_generate.py,sha256=PAySLU8ZnpdF8GelwSCiEbzv7sBbn-Vhakinf4i6udE,11646
|
|
140
|
+
autocoder/common/v2/code_auto_generate_diff.py,sha256=RWMJHxpQyD86ZOw0yYBFlKJLRsrrAWwRLJwu2rHfNXU,15213
|
|
141
|
+
autocoder/common/v2/code_auto_generate_editblock.py,sha256=qgTPox-0gLeNjzenzBM0B83Z-nzxYtT5BDCvllPLqps,15720
|
|
142
|
+
autocoder/common/v2/code_auto_generate_strict_diff.py,sha256=dbGyjBYWvjl_xT27Zxaq6Cgl7JuPZwYEGngPAyq3j9g,18066
|
|
140
143
|
autocoder/common/v2/code_auto_merge.py,sha256=FZHrIZyFUkFmv4EbproXfIIUfGx_L3EPfvjldsYlplI,9345
|
|
141
144
|
autocoder/common/v2/code_auto_merge_diff.py,sha256=DcljWrtlejq2cb9Gj-jBjvUQzRbCE2uMNGg8SBOhEnk,19271
|
|
142
145
|
autocoder/common/v2/code_auto_merge_editblock.py,sha256=rVohrpjTzgvWEX09GNRAQ0fbjjNjcxeP1bqczhFT8F8,20741
|
|
@@ -146,7 +149,7 @@ autocoder/common/v2/code_editblock_manager.py,sha256=DMwJw-FAM6VyaBQV3p4xespHpgZ
|
|
|
146
149
|
autocoder/common/v2/code_manager.py,sha256=C403bS-f6urixwitlKHcml-J03hci-UyNwHJOqBiY6Q,9182
|
|
147
150
|
autocoder/common/v2/code_strict_diff_manager.py,sha256=Bys7tFAq4G03R1zUZuxrszBTvP4QB96jIw2y5BDLyRM,9424
|
|
148
151
|
autocoder/common/v2/agent/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
149
|
-
autocoder/common/v2/agent/agentic_edit.py,sha256=
|
|
152
|
+
autocoder/common/v2/agent/agentic_edit.py,sha256=qS-wwyzxsCVTZOCyFdX1bGeLKpbT_lkO2O2FOaU2_4s,98891
|
|
150
153
|
autocoder/common/v2/agent/agentic_edit_conversation.py,sha256=pFgWPWHKhZ4J9EcFmIdiGsrSolTZuYcH1qkgKdD8nwk,7726
|
|
151
154
|
autocoder/common/v2/agent/agentic_edit_types.py,sha256=VJMrictg6hJ3mC45VgQGRd43DyDUPDUvPV1Rf3z72NI,4776
|
|
152
155
|
autocoder/common/v2/agent/agentic_tool_display.py,sha256=WKirt-2V346KLnbHgH3NVJiK3xvriD9oaCWj2IdvzLU,7309
|
|
@@ -307,9 +310,9 @@ autocoder/utils/types.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
|
307
310
|
autocoder/utils/auto_coder_utils/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
308
311
|
autocoder/utils/auto_coder_utils/chat_stream_out.py,sha256=t902pKxQ5xM7zgIHiAOsTPLwxhE6VuvXAqPy751S7fg,14096
|
|
309
312
|
autocoder/utils/chat_auto_coder_utils/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
310
|
-
auto_coder-0.1.
|
|
311
|
-
auto_coder-0.1.
|
|
312
|
-
auto_coder-0.1.
|
|
313
|
-
auto_coder-0.1.
|
|
314
|
-
auto_coder-0.1.
|
|
315
|
-
auto_coder-0.1.
|
|
313
|
+
auto_coder-0.1.361.dist-info/LICENSE,sha256=HrhfyXIkWY2tGFK11kg7vPCqhgh5DcxleloqdhrpyMY,11558
|
|
314
|
+
auto_coder-0.1.361.dist-info/METADATA,sha256=HIhJ-9ho4w9uArb53Llorxzoeqn99ge5WW9HItR2t9U,2751
|
|
315
|
+
auto_coder-0.1.361.dist-info/WHEEL,sha256=GV9aMThwP_4oNCtvEC2ec3qUYutgWeAzklro_0m4WJQ,91
|
|
316
|
+
auto_coder-0.1.361.dist-info/entry_points.txt,sha256=0nzHtHH4pNcM7xq4EBA2toS28Qelrvcbrr59GqD_0Ak,350
|
|
317
|
+
auto_coder-0.1.361.dist-info/top_level.txt,sha256=Jqc0_uJSw2GwoFQAa9iJxYns-2mWla-9ok_Y3Gcznjk,10
|
|
318
|
+
auto_coder-0.1.361.dist-info/RECORD,,
|
|
@@ -47,7 +47,7 @@ class AutoReviewCommit:
|
|
|
47
47
|
@byzerllm.prompt()
|
|
48
48
|
def review(self, querie_with_urls_and_changes: List[Tuple[str, List[str], Dict[str, Tuple[str, str]]]], query: str) -> Generator[str,None,None]:
|
|
49
49
|
"""
|
|
50
|
-
|
|
50
|
+
如果前面我们对话提供了文档,请参考上面的文档对提交的代码变更进行审查,提供改进建议,你所有的输出都要以markdown语法输出。
|
|
51
51
|
|
|
52
52
|
下面包含最新一次提交的信息:
|
|
53
53
|
<commit>
|
|
@@ -96,7 +96,7 @@ class AutoReviewCommit:
|
|
|
96
96
|
- 依赖关系:组件耦合是否合理
|
|
97
97
|
- 复用性:是否有重复代码
|
|
98
98
|
|
|
99
|
-
|
|
99
|
+
评审结果包含以下内容
|
|
100
100
|
1. issues: 发现的具体问题列表
|
|
101
101
|
3. severity: 问题的严重程度(low/medium/high),从高到底进行描述。
|
|
102
102
|
4. suggestions: 对应的改进建议列表
|
|
@@ -115,7 +115,9 @@ class AutoReviewCommit:
|
|
|
115
115
|
1. 评审意见应该具体且可操作,而不是泛泛而谈
|
|
116
116
|
2. 对于每个问题都应该提供明确的改进建议
|
|
117
117
|
3. 严重程度的判断要考虑问题对系统的潜在影响
|
|
118
|
-
4. 建议应该符合项目的技术栈和开发规范
|
|
118
|
+
4. 建议应该符合项目的技术栈和开发规范
|
|
119
|
+
|
|
120
|
+
注意,请以「纯 Markdown」输出,不要出现 <markdown>、</markdown> 之类标签。
|
|
119
121
|
"""
|
|
120
122
|
return {}
|
|
121
123
|
|
autocoder/auto_coder.py
CHANGED
|
@@ -52,7 +52,7 @@ from autocoder.common.mcp_server_types import (
|
|
|
52
52
|
McpRequest, McpInstallRequest, McpRemoveRequest, McpListRequest,
|
|
53
53
|
McpListRunningRequest, McpRefreshRequest
|
|
54
54
|
)
|
|
55
|
-
|
|
55
|
+
from autocoder.run_context import get_run_context,RunMode
|
|
56
56
|
console = Console()
|
|
57
57
|
|
|
58
58
|
|
|
@@ -438,7 +438,7 @@ def main(input_args: Optional[List[str]] = None):
|
|
|
438
438
|
llm.setup_sub_client("index_filter_model", index_filter_model)
|
|
439
439
|
|
|
440
440
|
|
|
441
|
-
if args.human_as_model:
|
|
441
|
+
if get_run_context().mode != RunMode.WEB and args.human_as_model:
|
|
442
442
|
|
|
443
443
|
def intercept_callback(
|
|
444
444
|
llm, model: str, input_value: List[Dict[str, Any]]
|
|
@@ -1157,7 +1157,7 @@ def main(input_args: Optional[List[str]] = None):
|
|
|
1157
1157
|
loaded_conversations = pre_conversations + \
|
|
1158
1158
|
chat_history["ask_conversation"]
|
|
1159
1159
|
|
|
1160
|
-
if args.human_as_model:
|
|
1160
|
+
if get_run_context().mode != RunMode.WEB and args.human_as_model:
|
|
1161
1161
|
console = Console()
|
|
1162
1162
|
|
|
1163
1163
|
@byzerllm.prompt()
|
|
@@ -17,7 +17,7 @@ from autocoder.utils import llms as llm_utils
|
|
|
17
17
|
from autocoder.common import SourceCodeList
|
|
18
18
|
from autocoder.privacy.model_filter import ModelPathFilter
|
|
19
19
|
from autocoder.memory.active_context_manager import ActiveContextManager
|
|
20
|
-
|
|
20
|
+
from autocoder.run_context import get_run_context,RunMode
|
|
21
21
|
|
|
22
22
|
class CodeAutoGenerate:
|
|
23
23
|
def __init__(
|
|
@@ -59,16 +59,19 @@ class CodeAutoGenerate:
|
|
|
59
59
|
) -> str:
|
|
60
60
|
"""
|
|
61
61
|
{%- if structure %}
|
|
62
|
+
====
|
|
62
63
|
{{ structure }}
|
|
63
64
|
{%- endif %}
|
|
64
65
|
|
|
65
66
|
{%- if content %}
|
|
67
|
+
====
|
|
66
68
|
下面是一些文件路径以及每个文件对应的源码:
|
|
67
69
|
|
|
68
70
|
{{ content }}
|
|
69
71
|
{%- endif %}
|
|
70
72
|
|
|
71
73
|
{%- if package_context %}
|
|
74
|
+
====
|
|
72
75
|
下面是上面文件的一些信息(包括最近的变更情况):
|
|
73
76
|
<package_context>
|
|
74
77
|
{{ package_context }}
|
|
@@ -76,9 +79,27 @@ class CodeAutoGenerate:
|
|
|
76
79
|
{%- endif %}
|
|
77
80
|
|
|
78
81
|
{%- if context %}
|
|
82
|
+
====
|
|
79
83
|
{{ context }}
|
|
80
84
|
{%- endif %}
|
|
81
85
|
|
|
86
|
+
{%- if extra_docs %}
|
|
87
|
+
====
|
|
88
|
+
|
|
89
|
+
RULES PROVIDED BY USER
|
|
90
|
+
|
|
91
|
+
The following rules are provided by the user, and you must follow them strictly.
|
|
92
|
+
|
|
93
|
+
{% for key, value in extra_docs.items() %}
|
|
94
|
+
<user_rule>
|
|
95
|
+
##File: {{ key }}
|
|
96
|
+
{{ value }}
|
|
97
|
+
</user_rule>
|
|
98
|
+
{% endfor %}
|
|
99
|
+
{% endif %}
|
|
100
|
+
|
|
101
|
+
====
|
|
102
|
+
|
|
82
103
|
下面是用户的需求:
|
|
83
104
|
|
|
84
105
|
{{ instruction }}
|
|
@@ -190,7 +211,7 @@ class CodeAutoGenerate:
|
|
|
190
211
|
generate_mode="wholefile"
|
|
191
212
|
)
|
|
192
213
|
|
|
193
|
-
if not self.args.human_as_model:
|
|
214
|
+
if not self.args.human_as_model or get_run_context().mode == RunMode.WEB:
|
|
194
215
|
with ThreadPoolExecutor(max_workers=len(self.llms) * self.generate_times_same_model) as executor:
|
|
195
216
|
futures = []
|
|
196
217
|
count = 0
|
|
@@ -16,6 +16,8 @@ from autocoder.rag.token_counter import count_tokens
|
|
|
16
16
|
from autocoder.utils import llms as llm_utils
|
|
17
17
|
from autocoder.common import SourceCodeList
|
|
18
18
|
from autocoder.memory.active_context_manager import ActiveContextManager
|
|
19
|
+
from autocoder.common.rulefiles.autocoderrules_utils import get_rules
|
|
20
|
+
from autocoder.run_context import get_run_context,RunMode
|
|
19
21
|
|
|
20
22
|
class CodeAutoGenerateDiff:
|
|
21
23
|
def __init__(
|
|
@@ -135,10 +137,12 @@ class CodeAutoGenerateDiff:
|
|
|
135
137
|
现在让我们开始一个新的任务:
|
|
136
138
|
|
|
137
139
|
{%- if structure %}
|
|
140
|
+
====
|
|
138
141
|
{{ structure }}
|
|
139
142
|
{%- endif %}
|
|
140
143
|
|
|
141
144
|
{%- if content %}
|
|
145
|
+
====
|
|
142
146
|
下面是一些文件路径以及每个文件对应的源码:
|
|
143
147
|
<files>
|
|
144
148
|
{{ content }}
|
|
@@ -146,6 +150,7 @@ class CodeAutoGenerateDiff:
|
|
|
146
150
|
{%- endif %}
|
|
147
151
|
|
|
148
152
|
{%- if package_context %}
|
|
153
|
+
====
|
|
149
154
|
下面是上面文件的一些信息(包括最近的变更情况):
|
|
150
155
|
<package_context>
|
|
151
156
|
{{ package_context }}
|
|
@@ -153,11 +158,29 @@ class CodeAutoGenerateDiff:
|
|
|
153
158
|
{%- endif %}
|
|
154
159
|
|
|
155
160
|
{%- if context %}
|
|
161
|
+
====
|
|
156
162
|
<extra_context>
|
|
157
163
|
{{ context }}
|
|
158
164
|
</extra_context>
|
|
159
165
|
{%- endif %}
|
|
160
166
|
|
|
167
|
+
{%- if extra_docs %}
|
|
168
|
+
====
|
|
169
|
+
|
|
170
|
+
RULES PROVIDED BY USER
|
|
171
|
+
|
|
172
|
+
The following rules are provided by the user, and you must follow them strictly.
|
|
173
|
+
|
|
174
|
+
{% for key, value in extra_docs.items() %}
|
|
175
|
+
<user_rule>
|
|
176
|
+
##File: {{ key }}
|
|
177
|
+
{{ value }}
|
|
178
|
+
</user_rule>
|
|
179
|
+
{% endfor %}
|
|
180
|
+
{% endif %}
|
|
181
|
+
|
|
182
|
+
====
|
|
183
|
+
|
|
161
184
|
下面是用户的需求:
|
|
162
185
|
|
|
163
186
|
{{ instruction }}
|
|
@@ -169,13 +192,15 @@ class CodeAutoGenerateDiff:
|
|
|
169
192
|
return {
|
|
170
193
|
"structure": ""
|
|
171
194
|
}
|
|
172
|
-
|
|
195
|
+
|
|
196
|
+
extra_docs = get_rules()
|
|
173
197
|
return {
|
|
174
198
|
"structure": (
|
|
175
199
|
self.action.pp.get_tree_like_directory_structure()
|
|
176
200
|
if self.action
|
|
177
201
|
else ""
|
|
178
|
-
)
|
|
202
|
+
),
|
|
203
|
+
"extra_docs": extra_docs,
|
|
179
204
|
}
|
|
180
205
|
|
|
181
206
|
@byzerllm.prompt(llm=lambda self: self.llm)
|
|
@@ -380,7 +405,7 @@ class CodeAutoGenerateDiff:
|
|
|
380
405
|
generate_mode="diff"
|
|
381
406
|
)
|
|
382
407
|
|
|
383
|
-
if not self.args.human_as_model:
|
|
408
|
+
if not self.args.human_as_model or get_run_context().mode == RunMode.WEB:
|
|
384
409
|
with ThreadPoolExecutor(max_workers=len(self.llms) * self.generate_times_same_model) as executor:
|
|
385
410
|
futures = []
|
|
386
411
|
count = 0
|
|
@@ -20,8 +20,8 @@ from autocoder.rag.token_counter import count_tokens
|
|
|
20
20
|
from autocoder.utils import llms as llm_utils
|
|
21
21
|
from autocoder.common import SourceCodeList
|
|
22
22
|
from autocoder.memory.active_context_manager import ActiveContextManager
|
|
23
|
-
|
|
24
|
-
|
|
23
|
+
from autocoder.common.rulefiles.autocoderrules_utils import get_rules
|
|
24
|
+
from autocoder.run_context import get_run_context,RunMode
|
|
25
25
|
|
|
26
26
|
class CodeAutoGenerateEditBlock:
|
|
27
27
|
def __init__(
|
|
@@ -188,10 +188,12 @@ class CodeAutoGenerateEditBlock:
|
|
|
188
188
|
现在让我们开始一个新的任务:
|
|
189
189
|
|
|
190
190
|
{%- if structure %}
|
|
191
|
+
====
|
|
191
192
|
{{ structure }}
|
|
192
193
|
{%- endif %}
|
|
193
194
|
|
|
194
195
|
{%- if content %}
|
|
196
|
+
====
|
|
195
197
|
下面是一些文件路径以及每个文件对应的源码:
|
|
196
198
|
<files>
|
|
197
199
|
{{ content }}
|
|
@@ -199,6 +201,7 @@ class CodeAutoGenerateEditBlock:
|
|
|
199
201
|
{%- endif %}
|
|
200
202
|
|
|
201
203
|
{%- if package_context %}
|
|
204
|
+
====
|
|
202
205
|
下面是上面文件的一些信息(包括最近的变更情况):
|
|
203
206
|
<package_context>
|
|
204
207
|
{{ package_context }}
|
|
@@ -206,11 +209,29 @@ class CodeAutoGenerateEditBlock:
|
|
|
206
209
|
{%- endif %}
|
|
207
210
|
|
|
208
211
|
{%- if context %}
|
|
212
|
+
====
|
|
209
213
|
<extra_context>
|
|
210
214
|
{{ context }}
|
|
211
215
|
</extra_context>
|
|
212
216
|
{%- endif %}
|
|
213
217
|
|
|
218
|
+
{%- if extra_docs %}
|
|
219
|
+
====
|
|
220
|
+
|
|
221
|
+
RULES PROVIDED BY USER
|
|
222
|
+
|
|
223
|
+
The following rules are provided by the user, and you must follow them strictly.
|
|
224
|
+
|
|
225
|
+
{% for key, value in extra_docs.items() %}
|
|
226
|
+
<user_rule>
|
|
227
|
+
##File: {{ key }}
|
|
228
|
+
{{ value }}
|
|
229
|
+
</user_rule>
|
|
230
|
+
{% endfor %}
|
|
231
|
+
{% endif %}
|
|
232
|
+
|
|
233
|
+
====
|
|
234
|
+
|
|
214
235
|
下面是用户的需求:
|
|
215
236
|
|
|
216
237
|
{{ instruction }}
|
|
@@ -224,6 +245,8 @@ class CodeAutoGenerateEditBlock:
|
|
|
224
245
|
"fence_0": self.fence_0,
|
|
225
246
|
"fence_1": self.fence_1,
|
|
226
247
|
}
|
|
248
|
+
|
|
249
|
+
extra_docs = get_rules()
|
|
227
250
|
|
|
228
251
|
return {
|
|
229
252
|
"structure": (
|
|
@@ -233,6 +256,7 @@ class CodeAutoGenerateEditBlock:
|
|
|
233
256
|
),
|
|
234
257
|
"fence_0": self.fence_0,
|
|
235
258
|
"fence_1": self.fence_1,
|
|
259
|
+
"extra_docs": extra_docs,
|
|
236
260
|
}
|
|
237
261
|
|
|
238
262
|
@byzerllm.prompt()
|
|
@@ -493,7 +517,7 @@ class CodeAutoGenerateEditBlock:
|
|
|
493
517
|
generate_mode="editblock"
|
|
494
518
|
)
|
|
495
519
|
|
|
496
|
-
if not self.args.human_as_model:
|
|
520
|
+
if not self.args.human_as_model or get_run_context().mode == RunMode.WEB:
|
|
497
521
|
with ThreadPoolExecutor(max_workers=len(self.llms) * self.generate_times_same_model) as executor:
|
|
498
522
|
futures = []
|
|
499
523
|
count = 0
|
|
@@ -16,6 +16,9 @@ from autocoder.utils import llms as llm_utils
|
|
|
16
16
|
from autocoder.common import SourceCodeList
|
|
17
17
|
from autocoder.privacy.model_filter import ModelPathFilter
|
|
18
18
|
from autocoder.memory.active_context_manager import ActiveContextManager
|
|
19
|
+
from autocoder.common.rulefiles.autocoderrules_utils import get_rules
|
|
20
|
+
from autocoder.run_context import get_run_context,RunMode
|
|
21
|
+
|
|
19
22
|
class CodeAutoGenerateStrictDiff:
|
|
20
23
|
def __init__(
|
|
21
24
|
self, llm: byzerllm.ByzerLLM, args: AutoCoderArgs, action=None
|
|
@@ -118,10 +121,12 @@ class CodeAutoGenerateStrictDiff:
|
|
|
118
121
|
现在让我们开始一个新的任务:
|
|
119
122
|
|
|
120
123
|
{%- if structure %}
|
|
124
|
+
====
|
|
121
125
|
{{ structure }}
|
|
122
126
|
{%- endif %}
|
|
123
127
|
|
|
124
128
|
{%- if content %}
|
|
129
|
+
====
|
|
125
130
|
下面是一些文件路径以及每个文件对应的源码:
|
|
126
131
|
<files>
|
|
127
132
|
{{ content }}
|
|
@@ -129,6 +134,7 @@ class CodeAutoGenerateStrictDiff:
|
|
|
129
134
|
{%- endif %}
|
|
130
135
|
|
|
131
136
|
{%- if package_context %}
|
|
137
|
+
====
|
|
132
138
|
下面是上面文件的一些信息(包括最近的变更情况):
|
|
133
139
|
<package_context>
|
|
134
140
|
{{ package_context }}
|
|
@@ -141,6 +147,23 @@ class CodeAutoGenerateStrictDiff:
|
|
|
141
147
|
</extra_context>
|
|
142
148
|
{%- endif %}
|
|
143
149
|
|
|
150
|
+
{%- if extra_docs %}
|
|
151
|
+
====
|
|
152
|
+
|
|
153
|
+
RULES PROVIDED BY USER
|
|
154
|
+
|
|
155
|
+
The following rules are provided by the user, and you must follow them strictly.
|
|
156
|
+
|
|
157
|
+
{% for key, value in extra_docs.items() %}
|
|
158
|
+
<user_rule>
|
|
159
|
+
##File: {{ key }}
|
|
160
|
+
{{ value }}
|
|
161
|
+
</user_rule>
|
|
162
|
+
{% endfor %}
|
|
163
|
+
{% endif %}
|
|
164
|
+
|
|
165
|
+
====
|
|
166
|
+
|
|
144
167
|
下面是用户的需求:
|
|
145
168
|
|
|
146
169
|
{{ instruction }}
|
|
@@ -152,13 +175,16 @@ class CodeAutoGenerateStrictDiff:
|
|
|
152
175
|
return {
|
|
153
176
|
"structure": "",
|
|
154
177
|
}
|
|
178
|
+
|
|
179
|
+
extra_docs = get_rules()
|
|
155
180
|
|
|
156
181
|
return {
|
|
157
182
|
"structure": (
|
|
158
183
|
self.action.pp.get_tree_like_directory_structure()
|
|
159
184
|
if self.action
|
|
160
185
|
else ""
|
|
161
|
-
)
|
|
186
|
+
),
|
|
187
|
+
"extra_docs": extra_docs,
|
|
162
188
|
}
|
|
163
189
|
|
|
164
190
|
@byzerllm.prompt(llm=lambda self: self.llm)
|
|
@@ -354,7 +380,7 @@ class CodeAutoGenerateStrictDiff:
|
|
|
354
380
|
generate_mode="strict_diff"
|
|
355
381
|
)
|
|
356
382
|
|
|
357
|
-
if not self.args.human_as_model:
|
|
383
|
+
if not self.args.human_as_model or get_run_context().mode == RunMode.WEB:
|
|
358
384
|
with ThreadPoolExecutor(max_workers=len(self.llms) * self.generate_times_same_model) as executor:
|
|
359
385
|
futures = []
|
|
360
386
|
count = 0
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
|
|
@@ -0,0 +1,192 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
import os, fnmatch, asyncio
|
|
3
|
+
from watchfiles import Change
|
|
4
|
+
from autocoder.common.ignorefiles.ignore_file_utils import should_ignore
|
|
5
|
+
from autocoder.common.file_monitor.monitor import get_file_monitor
|
|
6
|
+
import logging
|
|
7
|
+
import functools
|
|
8
|
+
|
|
9
|
+
logger = logging.getLogger(__name__)
|
|
10
|
+
|
|
11
|
+
class DirectoryCache:
|
|
12
|
+
_instance: "DirectoryCache|None" = None
|
|
13
|
+
|
|
14
|
+
def __init__(self, root: str):
|
|
15
|
+
self.root = os.path.abspath(root)
|
|
16
|
+
self.files_set: set[str] = set()
|
|
17
|
+
self.lock = asyncio.Lock()
|
|
18
|
+
self._main_loop = asyncio.get_event_loop() # 保存主事件循环引用
|
|
19
|
+
logger.info(f"Initializing DirectoryCache for root: {self.root}")
|
|
20
|
+
|
|
21
|
+
# ---------- 单例获取 ----------
|
|
22
|
+
@classmethod
|
|
23
|
+
def get_instance(cls, root: str | None = None) -> "DirectoryCache":
|
|
24
|
+
if cls._instance is None:
|
|
25
|
+
if root is None:
|
|
26
|
+
raise ValueError("root is required when initializing DirectoryCache for the first time")
|
|
27
|
+
logger.info("Creating new DirectoryCache instance.")
|
|
28
|
+
cls._instance = cls(root)
|
|
29
|
+
cls._instance._build() # 同步首扫
|
|
30
|
+
cls._instance._register_monitor()
|
|
31
|
+
elif root is not None and os.path.abspath(root) != cls._instance.root:
|
|
32
|
+
# 如果请求的 root 与已存在的实例 root 不同,可以选择抛出错误或重新初始化
|
|
33
|
+
logger.warning(f"Requested root {os.path.abspath(root)} differs from existing instance root {cls._instance.root}. Re-initializing cache.")
|
|
34
|
+
cls._instance = cls(root)
|
|
35
|
+
cls._instance._build()
|
|
36
|
+
cls._instance._register_monitor()
|
|
37
|
+
|
|
38
|
+
return cls._instance
|
|
39
|
+
|
|
40
|
+
# ---------- 构建 ----------
|
|
41
|
+
def _build(self) -> None:
|
|
42
|
+
logger.info(f"Building initial file cache for {self.root}...")
|
|
43
|
+
count = 0
|
|
44
|
+
for r, ds, fs in os.walk(self.root, followlinks=True):
|
|
45
|
+
# 过滤掉需要忽略的目录
|
|
46
|
+
ds[:] = [d for d in ds if not should_ignore(os.path.join(r, d))]
|
|
47
|
+
for f in fs:
|
|
48
|
+
fp = os.path.join(r, f)
|
|
49
|
+
abs_fp = os.path.abspath(fp)
|
|
50
|
+
if not should_ignore(abs_fp):
|
|
51
|
+
self.files_set.add(abs_fp)
|
|
52
|
+
count += 1
|
|
53
|
+
logger.info(f"Initial cache build complete. Found {count} files.")
|
|
54
|
+
|
|
55
|
+
|
|
56
|
+
# ---------- 监控回调 ----------
|
|
57
|
+
def _register_monitor(self) -> None:
|
|
58
|
+
try:
|
|
59
|
+
logger.info(f"Registering file monitor for {self.root}")
|
|
60
|
+
mon = get_file_monitor(self.root)
|
|
61
|
+
# 使用 functools.partial 包装异步回调
|
|
62
|
+
async_callback_wrapper = functools.partial(self._on_change_wrapper)
|
|
63
|
+
mon.register("**/*", async_callback_wrapper) # 监听所有文件变化
|
|
64
|
+
if not mon.is_running():
|
|
65
|
+
logger.info("Starting file monitor...")
|
|
66
|
+
mon.start()
|
|
67
|
+
logger.info("File monitor registered and running.")
|
|
68
|
+
except Exception as e:
|
|
69
|
+
logger.error(f"Failed to register or start file monitor: {e}", exc_info=True)
|
|
70
|
+
|
|
71
|
+
# Wrapper to run the async callback in the event loop
|
|
72
|
+
def _on_change_wrapper(self, change: Change, path: str):
|
|
73
|
+
try:
|
|
74
|
+
# 使用run_coroutine_threadsafe在主事件循环中运行协程
|
|
75
|
+
# 注意:主事件循环必须在其他地方运行,如主线程中
|
|
76
|
+
asyncio.run_coroutine_threadsafe(self._on_change(change, path), self._main_loop)
|
|
77
|
+
except Exception as e:
|
|
78
|
+
logger.error(f"Error executing _on_change_wrapper: {e}", exc_info=True)
|
|
79
|
+
# 如果run_coroutine_threadsafe失败,可以考虑一个同步的备用处理方法
|
|
80
|
+
try:
|
|
81
|
+
# 同步备份处理
|
|
82
|
+
ap = os.path.abspath(path)
|
|
83
|
+
if should_ignore(ap):
|
|
84
|
+
return
|
|
85
|
+
|
|
86
|
+
if change is Change.added:
|
|
87
|
+
self.files_set.add(ap)
|
|
88
|
+
elif change is Change.deleted:
|
|
89
|
+
self.files_set.discard(ap)
|
|
90
|
+
# Change.modified不需要更新集合
|
|
91
|
+
except Exception as backup_error:
|
|
92
|
+
logger.error(f"Backup handler also failed: {backup_error}", exc_info=True)
|
|
93
|
+
|
|
94
|
+
|
|
95
|
+
async def _on_change(self, change: Change, path: str) -> None:
|
|
96
|
+
ap = os.path.abspath(path)
|
|
97
|
+
# Check ignore status again, as gitignore might change
|
|
98
|
+
if should_ignore(ap):
|
|
99
|
+
# If a previously tracked file becomes ignored, remove it
|
|
100
|
+
async with self.lock:
|
|
101
|
+
if ap in self.files_set:
|
|
102
|
+
logger.debug(f"File became ignored, removing from cache: {ap}")
|
|
103
|
+
self.files_set.discard(ap)
|
|
104
|
+
return
|
|
105
|
+
|
|
106
|
+
async with self.lock:
|
|
107
|
+
if change is Change.added:
|
|
108
|
+
logger.debug(f"File added, adding to cache: {ap}")
|
|
109
|
+
self.files_set.add(ap)
|
|
110
|
+
elif change is Change.deleted:
|
|
111
|
+
logger.debug(f"File deleted, removing from cache: {ap}")
|
|
112
|
+
self.files_set.discard(ap)
|
|
113
|
+
elif change is Change.modified:
|
|
114
|
+
# Modification doesn't change existence, but we might want to log or handle metadata updates if needed
|
|
115
|
+
logger.debug(f"File modified: {ap} (ignored in cache set)")
|
|
116
|
+
pass # No change needed for the set itself
|
|
117
|
+
|
|
118
|
+
# ---------- 查询 ----------
|
|
119
|
+
async def query(self, patterns: list[str]) -> list[str]:
|
|
120
|
+
logger.debug(f"Querying cache with patterns: {patterns}")
|
|
121
|
+
async with self.lock:
|
|
122
|
+
# Make a copy to avoid issues if the set is modified during iteration (though lock prevents this here)
|
|
123
|
+
current_files = list(self.files_set)
|
|
124
|
+
|
|
125
|
+
if not patterns or patterns == [""] or patterns == ["*"]:
|
|
126
|
+
logger.debug(f"Returning all {len(current_files)} cached files.")
|
|
127
|
+
return current_files
|
|
128
|
+
|
|
129
|
+
out: set[str] = set()
|
|
130
|
+
|
|
131
|
+
for p in patterns:
|
|
132
|
+
pattern_abs = os.path.abspath(os.path.join(self.root, p)) if not os.path.isabs(p) else p
|
|
133
|
+
is_glob = "*" in p or "?" in p or "[" in p # More robust glob check
|
|
134
|
+
|
|
135
|
+
try:
|
|
136
|
+
if is_glob:
|
|
137
|
+
# fnmatch expects relative paths for matching within a root usually,
|
|
138
|
+
# but here we match against absolute paths in files_set.
|
|
139
|
+
# We need a pattern that works with absolute paths.
|
|
140
|
+
# If pattern 'p' is like '*.py', we need to match '/path/to/root/**/*.py'
|
|
141
|
+
# Let's adjust the pattern logic or filtering logic.
|
|
142
|
+
|
|
143
|
+
# Option 1: Match relative paths within the root
|
|
144
|
+
# Convert absolute paths in files_set to relative for matching
|
|
145
|
+
# relative_files = [os.path.relpath(f, self.root) for f in current_files]
|
|
146
|
+
# matched_relative = fnmatch.filter(relative_files, p)
|
|
147
|
+
# out.update(os.path.join(self.root, rel_f) for rel_f in matched_relative)
|
|
148
|
+
|
|
149
|
+
# Option 2: Match absolute paths directly (might need careful pattern construction)
|
|
150
|
+
# If p is relative, make it absolute based on root for matching
|
|
151
|
+
# Example: p = "src/*.py" -> effective_pattern = "/path/to/root/src/*.py"
|
|
152
|
+
# This requires fnmatch to handle absolute paths correctly or custom logic.
|
|
153
|
+
|
|
154
|
+
# Option 3: Simplified wildcard matching on absolute paths
|
|
155
|
+
# Treat '*' as a general wildcard anywhere in the path.
|
|
156
|
+
# fnmatch.filter might work if the pattern is constructed like `*pattern*`
|
|
157
|
+
# Let's stick to the user's original logic first, assuming it worked for their case
|
|
158
|
+
# The original `*{p}*` suggests substring matching with wildcards? Let's refine.
|
|
159
|
+
|
|
160
|
+
# Refined Glob Matching:
|
|
161
|
+
# If p contains wildcards, assume it's a glob pattern relative to root.
|
|
162
|
+
# Convert files_set paths to relative for matching.
|
|
163
|
+
for f_abs in current_files:
|
|
164
|
+
f_rel = os.path.relpath(f_abs, self.root)
|
|
165
|
+
if fnmatch.fnmatch(f_rel, p) or fnmatch.fnmatch(os.path.basename(f_abs), p):
|
|
166
|
+
out.add(f_abs)
|
|
167
|
+
|
|
168
|
+
else:
|
|
169
|
+
# Exact or substring matching for non-glob patterns
|
|
170
|
+
# Match against filename or full path segment
|
|
171
|
+
p_lower = p.lower()
|
|
172
|
+
for f_abs in current_files:
|
|
173
|
+
if p_lower in os.path.basename(f_abs).lower() or p_lower in f_abs.lower():
|
|
174
|
+
out.add(f_abs)
|
|
175
|
+
|
|
176
|
+
except Exception as e:
|
|
177
|
+
logger.error(f"Error during pattern matching for '{p}': {e}", exc_info=True)
|
|
178
|
+
|
|
179
|
+
|
|
180
|
+
result = sorted(list(out)) # Sort for consistent output
|
|
181
|
+
logger.debug(f"Query returned {len(result)} files.")
|
|
182
|
+
return result
|
|
183
|
+
|
|
184
|
+
# Helper function (optional, could be integrated into get_instance)
|
|
185
|
+
def initialize_cache(root_path: str):
|
|
186
|
+
"""Initializes the DirectoryCache singleton."""
|
|
187
|
+
try:
|
|
188
|
+
DirectoryCache.get_instance(root_path)
|
|
189
|
+
logger.info("DirectoryCache initialized successfully.")
|
|
190
|
+
except Exception as e:
|
|
191
|
+
logger.error(f"Failed to initialize DirectoryCache: {e}", exc_info=True)
|
|
192
|
+
|