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

Files changed (39) hide show
  1. {auto_coder-0.1.363.dist-info → auto_coder-0.1.365.dist-info}/METADATA +2 -2
  2. {auto_coder-0.1.363.dist-info → auto_coder-0.1.365.dist-info}/RECORD +39 -23
  3. autocoder/agent/base_agentic/tools/execute_command_tool_resolver.py +1 -1
  4. autocoder/auto_coder.py +46 -2
  5. autocoder/auto_coder_runner.py +2 -0
  6. autocoder/common/__init__.py +5 -0
  7. autocoder/common/file_checkpoint/__init__.py +21 -0
  8. autocoder/common/file_checkpoint/backup.py +264 -0
  9. autocoder/common/file_checkpoint/conversation_checkpoint.py +182 -0
  10. autocoder/common/file_checkpoint/examples.py +217 -0
  11. autocoder/common/file_checkpoint/manager.py +611 -0
  12. autocoder/common/file_checkpoint/models.py +156 -0
  13. autocoder/common/file_checkpoint/store.py +383 -0
  14. autocoder/common/file_checkpoint/test_backup.py +242 -0
  15. autocoder/common/file_checkpoint/test_manager.py +570 -0
  16. autocoder/common/file_checkpoint/test_models.py +360 -0
  17. autocoder/common/file_checkpoint/test_store.py +327 -0
  18. autocoder/common/file_checkpoint/test_utils.py +297 -0
  19. autocoder/common/file_checkpoint/utils.py +119 -0
  20. autocoder/common/rulefiles/autocoderrules_utils.py +114 -55
  21. autocoder/common/save_formatted_log.py +76 -5
  22. autocoder/common/utils_code_auto_generate.py +2 -1
  23. autocoder/common/v2/agent/agentic_edit.py +545 -225
  24. autocoder/common/v2/agent/agentic_edit_tools/list_files_tool_resolver.py +83 -43
  25. autocoder/common/v2/agent/agentic_edit_tools/read_file_tool_resolver.py +116 -29
  26. autocoder/common/v2/agent/agentic_edit_tools/replace_in_file_tool_resolver.py +179 -48
  27. autocoder/common/v2/agent/agentic_edit_tools/search_files_tool_resolver.py +101 -56
  28. autocoder/common/v2/agent/agentic_edit_tools/test_write_to_file_tool_resolver.py +322 -0
  29. autocoder/common/v2/agent/agentic_edit_tools/write_to_file_tool_resolver.py +173 -132
  30. autocoder/common/v2/agent/agentic_edit_types.py +4 -0
  31. autocoder/compilers/normal_compiler.py +64 -0
  32. autocoder/events/event_manager_singleton.py +133 -4
  33. autocoder/linters/normal_linter.py +373 -0
  34. autocoder/linters/python_linter.py +4 -2
  35. autocoder/version.py +1 -1
  36. {auto_coder-0.1.363.dist-info → auto_coder-0.1.365.dist-info}/LICENSE +0 -0
  37. {auto_coder-0.1.363.dist-info → auto_coder-0.1.365.dist-info}/WHEEL +0 -0
  38. {auto_coder-0.1.363.dist-info → auto_coder-0.1.365.dist-info}/entry_points.txt +0 -0
  39. {auto_coder-0.1.363.dist-info → auto_coder-0.1.365.dist-info}/top_level.txt +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: auto-coder
3
- Version: 0.1.363
3
+ Version: 0.1.365
4
4
  Summary: AutoCoder: AutoCoder
5
5
  Author: allwefantasy
6
6
  Classifier: Programming Language :: Python :: 3.10
@@ -28,7 +28,7 @@ Requires-Dist: prompt-toolkit
28
28
  Requires-Dist: tokenizers
29
29
  Requires-Dist: aiofiles
30
30
  Requires-Dist: readerwriterlock
31
- Requires-Dist: byzerllm[saas] >=0.1.181
31
+ Requires-Dist: byzerllm[saas] >=0.1.182
32
32
  Requires-Dist: patch
33
33
  Requires-Dist: diff-match-patch
34
34
  Requires-Dist: GitPython
@@ -1,10 +1,10 @@
1
1
  autocoder/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
2
- autocoder/auto_coder.py,sha256=dElVs1kOxEArM2T5nfIzDJwT6-_YEq_5Sc3WPTPcBBk,67178
2
+ autocoder/auto_coder.py,sha256=7602L3tG0JErNxh8vkLAmGUgv2c-DGPzPCkmWIQt9bs,69757
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
6
6
  autocoder/auto_coder_rag_mcp.py,sha256=-RrjNwFaS2e5v8XDIrKR-zlUNUE8UBaeOtojffBrvJo,8521
7
- autocoder/auto_coder_runner.py,sha256=SIPsF-hJiGXHYfdApQCEDZc1nn-rf09AC4s1vhSwRsw,112199
7
+ autocoder/auto_coder_runner.py,sha256=VktQIEWjVMmraVjD7W73eZmYtdfm9Ma2w_Ib-cWZYhM,112263
8
8
  autocoder/auto_coder_server.py,sha256=bLORGEclcVdbBVfM140JCI8WtdrU0jbgqdJIVVupiEU,20578
9
9
  autocoder/benchmark.py,sha256=Ypomkdzd1T3GE6dRICY3Hj547dZ6_inqJbBJIp5QMco,4423
10
10
  autocoder/chat_auto_coder.py,sha256=iHy8Kt1so1ZLOPpb5GTfi4BurDe3T1hOPqOw-XIBDpQ,26851
@@ -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=cvMXneYVMewK3wsnehdnyGje5vmWAtTL725STXOPjiE,23
17
+ autocoder/version.py,sha256=IcO5L1bOdV3qLFshmlEIP9ycK_uaklkhdNmRNqLG91g,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
@@ -58,7 +58,7 @@ autocoder/agent/base_agentic/tools/ask_followup_question_tool_resolver.py,sha256
58
58
  autocoder/agent/base_agentic/tools/attempt_completion_tool_resolver.py,sha256=9a_qPihfm45Q22kmxmFwYrZrtNsgtEyBePL8D4SXfes,1487
59
59
  autocoder/agent/base_agentic/tools/base_tool_resolver.py,sha256=Y0PmRPhBLLdZpr2DNV0W5goGfAqylM5m1bHxa3T6vAY,1009
60
60
  autocoder/agent/base_agentic/tools/example_tool_resolver.py,sha256=8WBIqEH_76S0iBHBM3RhLkk14UpJ28lRAw6dNUT-0no,1388
61
- autocoder/agent/base_agentic/tools/execute_command_tool_resolver.py,sha256=XZ9nkSejmLcwrjG187Q7fIEPdVMljQFDYWuUqcP6Yig,3735
61
+ autocoder/agent/base_agentic/tools/execute_command_tool_resolver.py,sha256=FDWheOy2NVG1RDeG2lhMlj0cFjG4UpqCkWPRMEM7Atc,3755
62
62
  autocoder/agent/base_agentic/tools/list_files_tool_resolver.py,sha256=rIKcJ0xVI6Exdmqb2LhUQFL6_GNQFuYazqQSJR0Sf2g,5468
63
63
  autocoder/agent/base_agentic/tools/plan_mode_respond_tool_resolver.py,sha256=hiLdMRknR_Aljd7Ic2bOWZKs11aFHdhkRTKTlP3IIgw,1461
64
64
  autocoder/agent/base_agentic/tools/read_file_tool_resolver.py,sha256=4GV8_hyVlO97MgI2pdUrxur3MFNJutlBT8r9OYfQjps,2857
@@ -78,7 +78,7 @@ autocoder/commands/auto_web.py,sha256=K0Gv7lil5UqmExr_sAJNOcwNxw_q1vhvre1jjQ7tA3
78
78
  autocoder/commands/tools.py,sha256=IX_zx5mWAvQDED7wUHTqNtrCmLNo9ztFV1aZ6AflY4o,34292
79
79
  autocoder/common/JupyterClient.py,sha256=O-wi6pXeAEYhAY24kDa0BINrLYvKS6rKyWe98pDClS0,2816
80
80
  autocoder/common/ShellClient.py,sha256=fM1q8t_XMSbLBl2zkCNC2J9xuyKN3eXzGm6hHhqL2WY,2286
81
- autocoder/common/__init__.py,sha256=uN0sW7jePq-eim95VPLj8LRPGe_XzQQjqJmG0h1T4HU,14681
81
+ autocoder/common/__init__.py,sha256=qZWLTeEjimIGDUvbAq_QV1o5jgMiD1k4TQcoU0-wOo8,14887
82
82
  autocoder/common/action_yml_file_manager.py,sha256=DdF5P1R_B_chCnnqoA2IgogakWLZk_nItiJZUfX0_Wo,17857
83
83
  autocoder/common/anything2images.py,sha256=0ILBbWzY02M-CiWB-vzuomb_J1hVdxRcenAfIrAXq9M,25283
84
84
  autocoder/common/anything2img.py,sha256=iZQmg8srXlD7N5uGl5b_ONKJMBjYoW8kPmokkG6ISF0,10118
@@ -129,7 +129,7 @@ autocoder/common/printer.py,sha256=T4XTAcQp5w1ZWYx5NAUXlIGd-9500Vl0JaG1JJXMdkg,2
129
129
  autocoder/common/recall_validation.py,sha256=Avt9Q9dX3kG6Pf2zsdlOHmsjd-OeSj7U1PFBDp_Cve0,1700
130
130
  autocoder/common/result_manager.py,sha256=tvWtqSDhP7yKGtmB9s1pJAuRnB7nDgjM6eVrXF9n4e0,4169
131
131
  autocoder/common/run_cmd.py,sha256=2VrJpeqooasUoc-WKVrvFfesmRR55kOpPmmYgpQrKVc,8283
132
- autocoder/common/save_formatted_log.py,sha256=_echHX_sCA4oBrUasrmdITGCaP7DbLIhz2yeUYQhDpg,1771
132
+ autocoder/common/save_formatted_log.py,sha256=VXeN3dzA1C0AX1slSwBTFMC1lZHR9GtziSVRqUDEKfU,5395
133
133
  autocoder/common/screenshots.py,sha256=_gA-z1HxGjPShBrtgkdideq58MG6rqFB2qMUJKjrycs,3769
134
134
  autocoder/common/search.py,sha256=245iPFgWhMldoUK3CqCP89ltaxZiNPK73evoG6Fp1h8,16518
135
135
  autocoder/common/search_replace.py,sha256=GphFkc57Hb673CAwmbiocqTbw8vrV7TrZxtOhD0332g,22147
@@ -141,7 +141,7 @@ autocoder/common/test_run_cmd.py,sha256=0piPrNnxTPS8vJRnsVH6-lgB5zeLaXSRY5pPH13H
141
141
  autocoder/common/text.py,sha256=KGRQq314GHBmY4MWG8ossRoQi1_DTotvhxchpn78c-k,1003
142
142
  autocoder/common/token_cost_caculate.py,sha256=MSWJtl7YpQSUt-gFQoqUcJMblyPqHXe2ZioiZOFkV80,10085
143
143
  autocoder/common/types.py,sha256=Cw_4RH-rGmAgQE-Ck69maMAMqlPCDA4Yj37QmuUY0mQ,713
144
- autocoder/common/utils_code_auto_generate.py,sha256=Tvb3Mqxedj0Jhi0faKyWvILuNCty9fZi341fyIs33tA,4550
144
+ autocoder/common/utils_code_auto_generate.py,sha256=zol3E5VQgriGzpR0p51yYnx8unthyurYM83QIudkxeI,4592
145
145
  autocoder/common/conversations/__init__.py,sha256=xGZeOFrDsgg2fkPK1zmvYBDhAyX66FtgOcZaxhYKJXU,1338
146
146
  autocoder/common/conversations/compatibility.py,sha256=WuBXB4-dw5X9LUMsB16VWbihvRZQ1tT99m6zuBwDfqE,9606
147
147
  autocoder/common/conversations/conversation_manager.py,sha256=ZhuhfSdOTncqgy3nHPoEU7Cg0dCsSl-VPcvLbUlL2Tk,18295
@@ -149,6 +149,19 @@ autocoder/common/conversations/example.py,sha256=Pz_EhO6qneUFMfHZiDmGAClZ6b0V4T1
149
149
  autocoder/common/directory_cache/__init__.py,sha256=AbpHGcgLb-kRsJGnwFEktk7uzpZOCcBY74-YBdrKVGs,1
150
150
  autocoder/common/directory_cache/cache.py,sha256=Jknygb_U6DkF04_SX04IwsOcQdd-2QQ4d6k9Ucc9OZ0,9358
151
151
  autocoder/common/directory_cache/test_cache.py,sha256=0iQkHaZQPhZBwSS6dwK_je93QMLbYGY0BYrTSt45Cao,6610
152
+ autocoder/common/file_checkpoint/__init__.py,sha256=qwoM0tIU-IMr-zGVCMN8yZtmz0NWpRe027l8z8sCjjk,847
153
+ autocoder/common/file_checkpoint/backup.py,sha256=JO26vOG9k7d8b5jgT24PdccSrTuPqKghp1nz5cmjSiE,8813
154
+ autocoder/common/file_checkpoint/conversation_checkpoint.py,sha256=SFSTjA0fF5rsHlYdLQ-Dr9dfDl5JihndhjeqhN3OuMY,6322
155
+ autocoder/common/file_checkpoint/examples.py,sha256=HTik8E0ddvKjEPGwzizWJBHIP9URrWRyRUOKSjYRUG8,6272
156
+ autocoder/common/file_checkpoint/manager.py,sha256=mkEPURbF109qnCwXOikNmJI8INhdfCwBW1v6sRB7ubY,23757
157
+ autocoder/common/file_checkpoint/models.py,sha256=dcZL2QGnklsa_BV_QY81fH-H5hYfhelXrH6GSrubMZo,4730
158
+ autocoder/common/file_checkpoint/store.py,sha256=dgQe-1O_gPJ3QU6tHihGRp0G2jgD2IDxQ-w9zM6Yq54,12920
159
+ autocoder/common/file_checkpoint/test_backup.py,sha256=Z9Y2RyGqxwKPNc7nW-2jtsMAYzqt0qZGzLoq3pn2zCI,8930
160
+ autocoder/common/file_checkpoint/test_manager.py,sha256=jpeHTmuBJ6bgB32VWBF5MxUEutY4qn8m2Q8kZukuuNc,20109
161
+ autocoder/common/file_checkpoint/test_models.py,sha256=BtIF0gYRsLj7EISV8CXNS8PW7OtMd_S2ShWNIBbQDIc,10491
162
+ autocoder/common/file_checkpoint/test_store.py,sha256=SqHT5zExX2mD-OT9ynaayPtjjcp_HZWkd5PovFCUA8U,12038
163
+ autocoder/common/file_checkpoint/test_utils.py,sha256=wN0VZaM5gc2ltu-c3OPKgKDXqOjgSRCPHep_s4Ns0nI,10209
164
+ autocoder/common/file_checkpoint/utils.py,sha256=lWchNqiQNH13sSi5Tn9g9zit8mlWdYSdiiT59nWeFJE,3273
152
165
  autocoder/common/file_monitor/__init__.py,sha256=9reL3IEnyLWU77WjPzeprM8-4lCetlSMZ94Nuxk5KNg,85
153
166
  autocoder/common/file_monitor/monitor.py,sha256=biS9TJyNKga2dE-CeYAi9xfXvA9aMeMl0tBf68G-SBE,16609
154
167
  autocoder/common/ignorefiles/__init__.py,sha256=P0hq7Avu1IeXBYEkPBZLsJhFzhzyktUWTqaRIXiAFLY,75
@@ -158,7 +171,7 @@ autocoder/common/mcp_servers/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NM
158
171
  autocoder/common/mcp_servers/mcp_server_gpt4o_mini_search.py,sha256=TApShxgoozLluobXHOK1-oAE1zm0-9jdRoPLQB1qwMI,5688
159
172
  autocoder/common/mcp_servers/mcp_server_perplexity.py,sha256=CIC26UkfH1lYoVCjfyY5xGGYVx8h0oz0Uj1c7YJ3OPw,5560
160
173
  autocoder/common/rulefiles/__init__.py,sha256=babSbPdFaXk1NvdHtH2zrJLb_tWd7d2ELIyS8NApY_Y,221
161
- autocoder/common/rulefiles/autocoderrules_utils.py,sha256=9AzimGtpmIGtqKZxDGHXMvHnVQb2axByExbFLk5RNgk,17592
174
+ autocoder/common/rulefiles/autocoderrules_utils.py,sha256=TvzKt41wa1uPnYXHkUaJRCuxCJL9IB-Zx6FsEwdSExg,19454
162
175
  autocoder/common/v2/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
163
176
  autocoder/common/v2/code_agentic_editblock_manager.py,sha256=pAh918YMgmLenXmNKXlmDPgKyVJjOuk69901VEEQHm4,34980
164
177
  autocoder/common/v2/code_auto_generate.py,sha256=PAySLU8ZnpdF8GelwSCiEbzv7sBbn-Vhakinf4i6udE,11646
@@ -174,9 +187,9 @@ autocoder/common/v2/code_editblock_manager.py,sha256=DMwJw-FAM6VyaBQV3p4xespHpgZ
174
187
  autocoder/common/v2/code_manager.py,sha256=C403bS-f6urixwitlKHcml-J03hci-UyNwHJOqBiY6Q,9182
175
188
  autocoder/common/v2/code_strict_diff_manager.py,sha256=Bys7tFAq4G03R1zUZuxrszBTvP4QB96jIw2y5BDLyRM,9424
176
189
  autocoder/common/v2/agent/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
177
- autocoder/common/v2/agent/agentic_edit.py,sha256=6nLqFwvM79bFmuCcCUO-9i3ZwrDVa-oeyHu-Yc2DbLc,99626
190
+ autocoder/common/v2/agent/agentic_edit.py,sha256=Fx_T6YBWPa4tlTLY8dbecsd1n5a93dGE7b4gygmK56I,115043
178
191
  autocoder/common/v2/agent/agentic_edit_conversation.py,sha256=pFgWPWHKhZ4J9EcFmIdiGsrSolTZuYcH1qkgKdD8nwk,7726
179
- autocoder/common/v2/agent/agentic_edit_types.py,sha256=ftFTXz-KF96GZvhnYRAxiiYOWfotwU_d9Lb8la2I47U,4779
192
+ autocoder/common/v2/agent/agentic_edit_types.py,sha256=nEcZc2MOZ_fQLaJX-YDha_x9Iim22ao4tykYM2iIy4k,4908
180
193
  autocoder/common/v2/agent/agentic_tool_display.py,sha256=-a-JTQLc4q03E_rdIILKMI0B6DHN-5gcGlrqq-mBYK4,7239
181
194
  autocoder/common/v2/agent/ignore_utils.py,sha256=gnUchRzKMLbUm_jvnKL-r-K9MWKPtt-6iiuzijY7Es0,1717
182
195
  autocoder/common/v2/agent/agentic_edit_tools/__init__.py,sha256=RbPZZcZg_VnGssL577GxSyFrYrxQ_LopJ4G_-mY3z_Q,1337
@@ -185,15 +198,16 @@ autocoder/common/v2/agent/agentic_edit_tools/attempt_completion_tool_resolver.py
185
198
  autocoder/common/v2/agent/agentic_edit_tools/base_tool_resolver.py,sha256=Zid2m1uZd-2wVFGc_n_KAViXZyNjbdLSpI5n7ut1RUQ,1036
186
199
  autocoder/common/v2/agent/agentic_edit_tools/execute_command_tool_resolver.py,sha256=sX00xzczfmyW6yPG3nMm0xO8p-WARQTiD4jcoUiTxsg,3844
187
200
  autocoder/common/v2/agent/agentic_edit_tools/list_code_definition_names_tool_resolver.py,sha256=8QoMsADUDWliqiDt_dpguz31403syB8eeW0Pcw-qfb8,3842
188
- autocoder/common/v2/agent/agentic_edit_tools/list_files_tool_resolver.py,sha256=FvpEyBwAfrYvnxcQ_gt7vTmfgoFoR7qr-r1OPx13Xks,5475
201
+ autocoder/common/v2/agent/agentic_edit_tools/list_files_tool_resolver.py,sha256=1tJX9RYRU0zRjKZMzFlZzKm-4R32CzRnZ0UQJj4pxAk,8074
189
202
  autocoder/common/v2/agent/agentic_edit_tools/list_package_info_tool_resolver.py,sha256=dIdV12VuczHpHuHgx2B1j_3BZYc9PL0jfHCuBk9ryk8,2005
190
203
  autocoder/common/v2/agent/agentic_edit_tools/plan_mode_respond_tool_resolver.py,sha256=lGT4_QYJK6Fa9f6HVSGo0cSsGK7qCsDYgJGUowNxPzk,1499
191
- autocoder/common/v2/agent/agentic_edit_tools/read_file_tool_resolver.py,sha256=FWyJ9eJvSvF3DHGRDtSqmLUadEN9fdX7hWv5X3V_Y-U,2907
192
- autocoder/common/v2/agent/agentic_edit_tools/replace_in_file_tool_resolver.py,sha256=Fe_zmKMQAahsYNU4_6BfsW4RHo_9KoIeltPfH7aX4LU,11027
193
- autocoder/common/v2/agent/agentic_edit_tools/search_files_tool_resolver.py,sha256=ACvygitMVOroQ8I-07v9fIvX9Xm9bO1HrIW--Xv9qKw,6894
204
+ autocoder/common/v2/agent/agentic_edit_tools/read_file_tool_resolver.py,sha256=6JhjM3VXV3BGelh1dNcdr-M5FoVPoqLkls1-y8ND8_c,6721
205
+ autocoder/common/v2/agent/agentic_edit_tools/replace_in_file_tool_resolver.py,sha256=J-GOlaLMwEu83v9VuHIstTpRR_vgPMR9wP_AzoK173s,18009
206
+ autocoder/common/v2/agent/agentic_edit_tools/search_files_tool_resolver.py,sha256=VtDRDFJ2qzACy2jpD1ZNhywgCT3_iYUmGoUhHHmMX3o,9581
194
207
  autocoder/common/v2/agent/agentic_edit_tools/test_search_files_tool_resolver.py,sha256=9eBo3WLkrr77iNotwIwVmH1ZL3UY0JQgLpdAIc9wTTM,6127
208
+ autocoder/common/v2/agent/agentic_edit_tools/test_write_to_file_tool_resolver.py,sha256=ZWRPsJny_My4UMzovrB8J2_x5N0rEW-xx3DVI-kDRFI,15870
195
209
  autocoder/common/v2/agent/agentic_edit_tools/use_mcp_tool_resolver.py,sha256=wM2Xy4bcnD0TSLEmcM8rvvyyWenN5_KQnJMO6hJ8lTE,1716
196
- autocoder/common/v2/agent/agentic_edit_tools/write_to_file_tool_resolver.py,sha256=UDUlpVWVRmEMuPHF1v8lkT56Ey22FywnM4l6fUPESU0,9156
210
+ autocoder/common/v2/agent/agentic_edit_tools/write_to_file_tool_resolver.py,sha256=ISJ2jNz0Dfv1W7P2A_mYSM0vPdN0yW1w7Qqt6QjTk98,11170
197
211
  autocoder/compilers/__init__.py,sha256=C0HOms70QA747XD0uZEMmGtRFcIPenohyqECNStv0Bw,1647
198
212
  autocoder/compilers/base_compiler.py,sha256=dsTzMO4H_RoqWfE-SntIk2B52hWuvSlWVLtkdCbHgGs,3244
199
213
  autocoder/compilers/compiler_config_api.py,sha256=QRSwWm_EX7jSeZ3dtQqM9HI__x5aZ7U0c3fHIW_2N48,13839
@@ -201,6 +215,7 @@ autocoder/compilers/compiler_config_manager.py,sha256=tNwHEk3t2o2L7ZVpHICDEOOIXR
201
215
  autocoder/compilers/compiler_factory.py,sha256=SLUdvBZdqr_pkY-lfArHCuBVjtiMoIs9uxCGztYj6Ro,10950
202
216
  autocoder/compilers/java_compiler.py,sha256=gR-_GB0_A1ZU3cTgRu1H9VPtLPmCWYo2UwBLEZIMvXU,26362
203
217
  autocoder/compilers/models.py,sha256=ZqGQhiF5vfsK71xzLlsCUS_q_Oune3mqokJ8S8ZOPSc,9527
218
+ autocoder/compilers/normal_compiler.py,sha256=3FQO2KK_-pa9lUotXmtCp920lQi9PpcGtdcFpwzjkIQ,1931
204
219
  autocoder/compilers/provided_compiler.py,sha256=gFxMOmFQYzsGCHJ9oPnSPQXboRdB0C4s5evdZMD99js,14667
205
220
  autocoder/compilers/python_compiler.py,sha256=2w2OM_6H0ZWvaquQpDo1x4VciBWczCZkfwmEyJEEpn8,14389
206
221
  autocoder/compilers/reactjs_compiler.py,sha256=h1_9OqiA8ca84-u3DIxQifvtH-2FSsKFWmhwALzNhqM,18159
@@ -220,7 +235,7 @@ autocoder/dispacher/actions/plugins/action_translate.py,sha256=GEn7dZA22jy5WyzIN
220
235
  autocoder/events/__init__.py,sha256=1x_juwr9Ows2RADDa2LyI4QlmPxOVOXZeLO1cht-slM,1443
221
236
  autocoder/events/event_content.py,sha256=eLHf5M1BifSqhzzEBgAWKn3JD5_z_1mWeNdZ53TpMqk,12240
222
237
  autocoder/events/event_manager.py,sha256=ObbvPfNrrhC85w5VvsnLS9oy92oHEwqMN08qGPReNNA,11884
223
- autocoder/events/event_manager_singleton.py,sha256=zIyrkcJ1g5RUh4osQlJRCo4j0GphcVmb0vp7XGbRWEg,8907
238
+ autocoder/events/event_manager_singleton.py,sha256=F2OkC-rSTONZd4KS-ERnBAtBPO74aiEAMwJ9IKYa_b0,14742
224
239
  autocoder/events/event_store.py,sha256=y6tT3P-o3yhDptrKi-UmqI_ZBNg7v21FriI3f7lo_ME,12709
225
240
  autocoder/events/event_types.py,sha256=W_S6PTDIBdufcuPosgz64iITzQy79flL8s3hWB-vZ9o,3638
226
241
  autocoder/helper/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
@@ -243,7 +258,8 @@ autocoder/linters/base_linter.py,sha256=1_0DPESnSyF3ZcQhoFkBYJylT5w-B61Rx-3A9uhu
243
258
  autocoder/linters/code_linter.py,sha256=JylTj-Mj4jl9-XSH3PVlbQ4l55Y6E1FG-glv860CGSs,22462
244
259
  autocoder/linters/linter_factory.py,sha256=rsDzaY0jFnmEsbY8Co_xxpJe9lXgfs07Nnrht8_WWtY,10273
245
260
  autocoder/linters/models.py,sha256=GBdayu_p50KBxoRms4X68zrDK-OsKDEKKjo926FevwE,9838
246
- autocoder/linters/python_linter.py,sha256=4psUpOOvwU8EkSHaHfW_Yd67Qvmuke8bL5_LIaj16wM,22459
261
+ autocoder/linters/normal_linter.py,sha256=5Yavs24XNMOryl0ZDpr1UbVboCZwaIs4x9mFqoC1ZYk,13022
262
+ autocoder/linters/python_linter.py,sha256=CurQa4pYeyPv_e4FxgVBHW-pHOzQTOftARLgY97AKBw,22511
247
263
  autocoder/linters/reactjs_linter.py,sha256=LDCXmAI15LUq8nNPyYko3oryzCc2Su05ob63jEeDdIs,20815
248
264
  autocoder/linters/shadow_linter.py,sha256=SKgRNVnTavNUviFC9osYMz18nGWCVOPOHx9LavEbnmc,15047
249
265
  autocoder/linters/vue_linter.py,sha256=ZyvoxT0kSizFh_UkR7UZYO5DV9edbvDQZaibEF9W95I,20905
@@ -338,9 +354,9 @@ autocoder/utils/types.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
338
354
  autocoder/utils/auto_coder_utils/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
339
355
  autocoder/utils/auto_coder_utils/chat_stream_out.py,sha256=t902pKxQ5xM7zgIHiAOsTPLwxhE6VuvXAqPy751S7fg,14096
340
356
  autocoder/utils/chat_auto_coder_utils/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
341
- auto_coder-0.1.363.dist-info/LICENSE,sha256=HrhfyXIkWY2tGFK11kg7vPCqhgh5DcxleloqdhrpyMY,11558
342
- auto_coder-0.1.363.dist-info/METADATA,sha256=KehY_HMpGLKM6rmOq3jp4fJwGpmz8D_OhZjswgqhuYg,2775
343
- auto_coder-0.1.363.dist-info/WHEEL,sha256=GV9aMThwP_4oNCtvEC2ec3qUYutgWeAzklro_0m4WJQ,91
344
- auto_coder-0.1.363.dist-info/entry_points.txt,sha256=0nzHtHH4pNcM7xq4EBA2toS28Qelrvcbrr59GqD_0Ak,350
345
- auto_coder-0.1.363.dist-info/top_level.txt,sha256=Jqc0_uJSw2GwoFQAa9iJxYns-2mWla-9ok_Y3Gcznjk,10
346
- auto_coder-0.1.363.dist-info/RECORD,,
357
+ auto_coder-0.1.365.dist-info/LICENSE,sha256=HrhfyXIkWY2tGFK11kg7vPCqhgh5DcxleloqdhrpyMY,11558
358
+ auto_coder-0.1.365.dist-info/METADATA,sha256=vo07pJAu6M2IMTWjRq9caGUXRwr88NMs05TIHDGUJKs,2775
359
+ auto_coder-0.1.365.dist-info/WHEEL,sha256=GV9aMThwP_4oNCtvEC2ec3qUYutgWeAzklro_0m4WJQ,91
360
+ auto_coder-0.1.365.dist-info/entry_points.txt,sha256=0nzHtHH4pNcM7xq4EBA2toS28Qelrvcbrr59GqD_0Ak,350
361
+ auto_coder-0.1.365.dist-info/top_level.txt,sha256=Jqc0_uJSw2GwoFQAa9iJxYns-2mWla-9ok_Y3Gcznjk,10
362
+ auto_coder-0.1.365.dist-info/RECORD,,
@@ -3,13 +3,13 @@ import subprocess
3
3
  from typing import Dict, Any, Optional
4
4
  from autocoder.agent.base_agentic.tools.base_tool_resolver import BaseToolResolver
5
5
  from autocoder.agent.base_agentic.types import ExecuteCommandTool, ToolResult # Import ToolResult from types
6
- from autocoder.common import shells
7
6
  from autocoder.common.printer import Printer
8
7
  from loguru import logger
9
8
  import typing
10
9
  from autocoder.common import AutoCoderArgs
11
10
  from autocoder.events.event_manager_singleton import get_event_manager
12
11
  from autocoder.run_context import get_run_context
12
+ from autocoder.common.run_cmd import run_cmd_subprocess
13
13
  if typing.TYPE_CHECKING:
14
14
  from ..base_agent import BaseAgent
15
15
 
autocoder/auto_coder.py CHANGED
@@ -376,8 +376,8 @@ def main(input_args: Optional[List[str]] = None):
376
376
  llm.setup_sub_client("inference_model", inference_model)
377
377
 
378
378
  if args.index_filter_model:
379
- model_info = models_module.get_model_by_name(args.index_filter_model)
380
- model_name = args.index_filter_model
379
+ model_name = args.index_filter_model.strip()
380
+ model_info = models_module.get_model_by_name(model_name)
381
381
  index_filter_model = byzerllm.SimpleByzerLLM(default_model_name=model_name)
382
382
  index_filter_model.deploy(
383
383
  model_path="",
@@ -393,6 +393,41 @@ def main(input_args: Optional[List[str]] = None):
393
393
  )
394
394
  llm.setup_sub_client("index_filter_model", index_filter_model)
395
395
 
396
+ if args.context_prune_model:
397
+ model_name = args.context_prune_model.strip()
398
+ model_info = models_module.get_model_by_name(model_name)
399
+ context_prune_model = byzerllm.SimpleByzerLLM(default_model_name=model_name)
400
+ context_prune_model.deploy(
401
+ model_path="",
402
+ pretrained_model_type=model_info["model_type"],
403
+ udf_name=model_name,
404
+ infer_params={
405
+ "saas.base_url": model_info["base_url"],
406
+ "saas.api_key": model_info["api_key"],
407
+ "saas.model": model_info["model_name"],
408
+ "saas.is_reasoning": model_info["is_reasoning"],
409
+ "saas.max_output_tokens": model_info.get("max_output_tokens", 8096)
410
+ }
411
+ )
412
+ llm.setup_sub_client("context_prune_model", context_prune_model)
413
+
414
+ if args.conversation_prune_model:
415
+ model_name = args.conversation_prune_model.strip()
416
+ model_info = models_module.get_model_by_name(model_name)
417
+ conversation_prune_model = byzerllm.SimpleByzerLLM(default_model_name=model_name)
418
+ conversation_prune_model.deploy(
419
+ model_path="",
420
+ pretrained_model_type=model_info["model_type"],
421
+ udf_name=model_name,
422
+ infer_params={
423
+ "saas.base_url": model_info["base_url"],
424
+ "saas.api_key": model_info["api_key"],
425
+ "saas.model": model_info["model_name"],
426
+ "saas.is_reasoning": model_info["is_reasoning"],
427
+ "saas.max_output_tokens": model_info.get("max_output_tokens", 8096)
428
+ }
429
+ )
430
+ llm.setup_sub_client("conversation_prune_model", conversation_prune_model)
396
431
 
397
432
  if args.product_mode == "pro":
398
433
  if args.code_model:
@@ -437,6 +472,15 @@ def main(input_args: Optional[List[str]] = None):
437
472
  index_filter_model.setup_default_model_name(args.index_filter_model)
438
473
  llm.setup_sub_client("index_filter_model", index_filter_model)
439
474
 
475
+ if args.context_prune_model:
476
+ context_prune_model = byzerllm.ByzerLLM()
477
+ context_prune_model.setup_default_model_name(args.context_prune_model)
478
+ llm.setup_sub_client("context_prune_model", context_prune_model)
479
+
480
+ if args.conversation_prune_model:
481
+ conversation_prune_model = byzerllm.ByzerLLM()
482
+ conversation_prune_model.setup_default_model_name(args.conversation_prune_model)
483
+ llm.setup_sub_client("conversation_prune_model", conversation_prune_model)
440
484
 
441
485
  if get_run_context().mode != RunMode.WEB and args.human_as_model:
442
486
 
@@ -2850,6 +2850,7 @@ def auto_command(query: str,extra_args: Dict[str,Any]={}):
2850
2850
  else:
2851
2851
  agent.run_in_terminal(AgenticEditRequest(user_input=query))
2852
2852
 
2853
+ completer.refresh_files()
2853
2854
  return
2854
2855
 
2855
2856
  args = get_final_config()
@@ -2902,3 +2903,4 @@ def auto_command(query: str,extra_args: Dict[str,Any]={}):
2902
2903
  border_style="blue",
2903
2904
  padding=(1, 2)
2904
2905
  ))
2906
+ completer.refresh_files()
@@ -254,6 +254,8 @@ class AutoCoderArgs(pydantic.BaseModel):
254
254
  emb_model: Optional[str] = ""
255
255
  code_model: Optional[str] = ""
256
256
  generate_rerank_model: Optional[str] = ""
257
+ context_prune_model: Optional[str] = ""
258
+ conversation_prune_model: Optional[str] = ""
257
259
  inference_model: Optional[str] = ""
258
260
  system_prompt: Optional[str] = ""
259
261
  planner_model: Optional[str] = ""
@@ -399,6 +401,7 @@ class AutoCoderArgs(pydantic.BaseModel):
399
401
 
400
402
  context_prune_strategy: Optional[str] = "extract"
401
403
  context_prune: Optional[bool] = True
404
+ context_prune_safe_zone_tokens: Optional[int] = 32*1024
402
405
  context_prune_sliding_window_size: Optional[int] = 1000
403
406
  context_prune_sliding_window_overlap: Optional[int] = 100
404
407
 
@@ -432,6 +435,8 @@ class AutoCoderArgs(pydantic.BaseModel):
432
435
  auto_fix_lint_max_attempts: Optional[int] = 5
433
436
  auto_fix_compile_max_attempts: Optional[int] = 5
434
437
  auto_fix_merge_max_attempts: Optional[int] = 5
438
+
439
+ enable_auto_select_rules: Optional[bool] = True
435
440
 
436
441
  ignore_clean_shadows: Optional[bool] = False
437
442
 
@@ -0,0 +1,21 @@
1
+ """
2
+ 文件变更管理模块
3
+
4
+ 该模块提供了一种可靠的机制来应用、记录和撤销对项目文件的修改。
5
+ 主要功能包括:
6
+ 1. 将影子系统中的文件变更安全地应用到用户的实际项目中
7
+ 2. 记录每次变更的历史,支持多版本撤销功能
8
+ 3. 提供简单直观的API,便于集成到现有的编辑流程中
9
+ """
10
+
11
+ from autocoder.common.file_checkpoint.models import (
12
+ FileChange, ChangeRecord, ApplyResult, UndoResult, DiffResult
13
+ )
14
+ from autocoder.common.file_checkpoint.manager import FileChangeManager
15
+ from autocoder.common.file_checkpoint.store import FileChangeStore
16
+ from autocoder.common.file_checkpoint.backup import FileBackupManager
17
+
18
+ __all__ = [
19
+ 'FileChange', 'ChangeRecord', 'ApplyResult', 'UndoResult', 'DiffResult',
20
+ 'FileChangeManager', 'FileChangeStore', 'FileBackupManager'
21
+ ]
@@ -0,0 +1,264 @@
1
+ """
2
+ 文件备份管理器
3
+
4
+ 负责文件的备份和恢复操作,支持多版本文件备份。
5
+ """
6
+
7
+ import os
8
+ import uuid
9
+ import shutil
10
+ import logging
11
+ from typing import Optional, Dict, List, Tuple
12
+ from datetime import datetime
13
+ import json
14
+ import threading
15
+
16
+ logger = logging.getLogger(__name__)
17
+
18
+
19
+ class FileBackupManager:
20
+ """负责文件的备份和恢复操作"""
21
+
22
+ def __init__(self, backup_dir: Optional[str] = None):
23
+ """
24
+ 初始化备份管理器
25
+
26
+ Args:
27
+ backup_dir: 备份文件存储目录,如果为None则使用默认目录
28
+ """
29
+ if backup_dir is None:
30
+ # 默认备份目录为项目根目录下的.auto-coder/checkpoint
31
+ backup_dir = os.path.join(os.getcwd(), ".auto-coder", "checkpoint")
32
+
33
+ self.backup_dir = backup_dir
34
+ self.metadata_file = os.path.join(backup_dir, "backup_metadata.json")
35
+ self.lock = threading.RLock()
36
+
37
+ # 确保备份目录存在
38
+ os.makedirs(backup_dir, exist_ok=True)
39
+
40
+ # 加载备份元数据
41
+ self.metadata = self._load_metadata()
42
+
43
+ def backup_file(self, file_path: str) -> Optional[str]:
44
+ """
45
+ 备份指定文件
46
+
47
+ Args:
48
+ file_path: 文件路径
49
+
50
+ Returns:
51
+ str: 备份文件ID,如果文件不存在则返回None
52
+ """
53
+ if not os.path.exists(file_path):
54
+ return None
55
+
56
+ with self.lock:
57
+ # 生成唯一的备份ID
58
+ backup_id = str(uuid.uuid4())
59
+
60
+ # 构建备份文件路径
61
+ backup_file_path = os.path.join(self.backup_dir, backup_id)
62
+
63
+ try:
64
+ # 复制文件到备份目录
65
+ shutil.copy2(file_path, backup_file_path)
66
+
67
+ # 更新元数据
68
+ self.metadata[backup_id] = {
69
+ "original_path": file_path,
70
+ "timestamp": datetime.now().timestamp(),
71
+ "size": os.path.getsize(file_path)
72
+ }
73
+
74
+ # 保存元数据
75
+ self._save_metadata()
76
+
77
+ logger.debug(f"已备份文件 {file_path} 到 {backup_file_path}")
78
+ return backup_id
79
+
80
+ except Exception as e:
81
+ logger.error(f"备份文件 {file_path} 失败: {str(e)}")
82
+ # 清理可能部分创建的备份文件
83
+ if os.path.exists(backup_file_path):
84
+ os.remove(backup_file_path)
85
+ return None
86
+
87
+ def restore_file(self, file_path: str, backup_id: str) -> bool:
88
+ """
89
+ 从备份恢复文件
90
+
91
+ Args:
92
+ file_path: 目标文件路径
93
+ backup_id: 备份文件ID
94
+
95
+ Returns:
96
+ bool: 恢复是否成功
97
+ """
98
+ with self.lock:
99
+ # 检查备份ID是否存在
100
+ if backup_id not in self.metadata:
101
+ logger.error(f"备份ID {backup_id} 不存在")
102
+ return False
103
+
104
+ # 构建备份文件路径
105
+ backup_file_path = os.path.join(self.backup_dir, backup_id)
106
+
107
+ # 检查备份文件是否存在
108
+ if not os.path.exists(backup_file_path):
109
+ logger.error(f"备份文件 {backup_file_path} 不存在")
110
+ return False
111
+
112
+ try:
113
+ # 确保目标目录存在
114
+ os.makedirs(os.path.dirname(file_path), exist_ok=True)
115
+
116
+ # 复制备份文件到目标路径
117
+ shutil.copy2(backup_file_path, file_path)
118
+
119
+ logger.debug(f"已从 {backup_file_path} 恢复文件到 {file_path}")
120
+ return True
121
+
122
+ except Exception as e:
123
+ logger.error(f"恢复文件 {file_path} 失败: {str(e)}")
124
+ return False
125
+
126
+ def get_backup_content(self, backup_id: str) -> Optional[str]:
127
+ """
128
+ 获取备份文件的内容
129
+
130
+ Args:
131
+ backup_id: 备份文件ID
132
+
133
+ Returns:
134
+ str: 备份文件内容,如果备份不存在则返回None
135
+ """
136
+ with self.lock:
137
+ # 检查备份ID是否存在
138
+ if backup_id not in self.metadata:
139
+ logger.error(f"备份ID {backup_id} 不存在")
140
+ return None
141
+
142
+ # 构建备份文件路径
143
+ backup_file_path = os.path.join(self.backup_dir, backup_id)
144
+
145
+ # 检查备份文件是否存在
146
+ if not os.path.exists(backup_file_path):
147
+ logger.error(f"备份文件 {backup_file_path} 不存在")
148
+ return None
149
+
150
+ try:
151
+ # 读取备份文件内容
152
+ with open(backup_file_path, 'r', encoding='utf-8') as f:
153
+ return f.read()
154
+
155
+ except Exception as e:
156
+ logger.error(f"读取备份文件 {backup_file_path} 失败: {str(e)}")
157
+ return None
158
+
159
+ def delete_backup(self, backup_id: str) -> bool:
160
+ """
161
+ 删除指定的备份文件
162
+
163
+ Args:
164
+ backup_id: 备份文件ID
165
+
166
+ Returns:
167
+ bool: 删除是否成功
168
+ """
169
+ with self.lock:
170
+ # 检查备份ID是否存在
171
+ if backup_id not in self.metadata:
172
+ logger.error(f"备份ID {backup_id} 不存在")
173
+ return False
174
+
175
+ # 构建备份文件路径
176
+ backup_file_path = os.path.join(self.backup_dir, backup_id)
177
+
178
+ try:
179
+ # 删除备份文件
180
+ if os.path.exists(backup_file_path):
181
+ os.remove(backup_file_path)
182
+
183
+ # 更新元数据
184
+ del self.metadata[backup_id]
185
+
186
+ # 保存元数据
187
+ self._save_metadata()
188
+
189
+ logger.debug(f"已删除备份 {backup_id}")
190
+ return True
191
+
192
+ except Exception as e:
193
+ logger.error(f"删除备份 {backup_id} 失败: {str(e)}")
194
+ return False
195
+
196
+ def clean_old_backups(self, max_age_days: int = 30) -> int:
197
+ """
198
+ 清理过旧的备份文件
199
+
200
+ Args:
201
+ max_age_days: 最大保留天数
202
+
203
+ Returns:
204
+ int: 清理的备份文件数量
205
+ """
206
+ with self.lock:
207
+ now = datetime.now().timestamp()
208
+ max_age_seconds = max_age_days * 24 * 60 * 60
209
+
210
+ backup_ids_to_delete = []
211
+
212
+ # 找出过旧的备份
213
+ for backup_id, metadata in self.metadata.items():
214
+ if now - metadata["timestamp"] > max_age_seconds:
215
+ backup_ids_to_delete.append(backup_id)
216
+
217
+ # 删除过旧的备份
218
+ deleted_count = 0
219
+ for backup_id in backup_ids_to_delete:
220
+ if self.delete_backup(backup_id):
221
+ deleted_count += 1
222
+
223
+ return deleted_count
224
+
225
+ def get_backups_for_file(self, file_path: str) -> List[Tuple[str, float]]:
226
+ """
227
+ 获取指定文件的所有备份
228
+
229
+ Args:
230
+ file_path: 文件路径
231
+
232
+ Returns:
233
+ List[Tuple[str, float]]: 备份ID和时间戳的列表,按时间戳降序排序
234
+ """
235
+ with self.lock:
236
+ backups = []
237
+
238
+ for backup_id, metadata in self.metadata.items():
239
+ if metadata["original_path"] == file_path:
240
+ backups.append((backup_id, metadata["timestamp"]))
241
+
242
+ # 按时间戳降序排序
243
+ backups.sort(key=lambda x: x[1], reverse=True)
244
+
245
+ return backups
246
+
247
+ def _load_metadata(self) -> Dict:
248
+ """加载备份元数据"""
249
+ if os.path.exists(self.metadata_file):
250
+ try:
251
+ with open(self.metadata_file, 'r', encoding='utf-8') as f:
252
+ return json.load(f)
253
+ except Exception as e:
254
+ logger.error(f"加载备份元数据失败: {str(e)}")
255
+
256
+ return {}
257
+
258
+ def _save_metadata(self) -> None:
259
+ """保存备份元数据"""
260
+ try:
261
+ with open(self.metadata_file, 'w', encoding='utf-8') as f:
262
+ json.dump(self.metadata, f, indent=2)
263
+ except Exception as e:
264
+ logger.error(f"保存备份元数据失败: {str(e)}")