auto-coder 0.1.400__py3-none-any.whl → 2.0.0__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 (579) hide show
  1. auto_coder-2.0.0.dist-info/LICENSE +158 -0
  2. auto_coder-2.0.0.dist-info/METADATA +558 -0
  3. auto_coder-2.0.0.dist-info/RECORD +795 -0
  4. {auto_coder-0.1.400.dist-info → auto_coder-2.0.0.dist-info}/WHEEL +1 -1
  5. {auto_coder-0.1.400.dist-info → auto_coder-2.0.0.dist-info}/entry_points.txt +3 -3
  6. autocoder/__init__.py +31 -0
  7. autocoder/agent/auto_filegroup.py +32 -13
  8. autocoder/agent/auto_learn_from_commit.py +9 -1
  9. autocoder/agent/base_agentic/__init__.py +3 -0
  10. autocoder/agent/base_agentic/agent_hub.py +1 -1
  11. autocoder/agent/base_agentic/base_agent.py +235 -136
  12. autocoder/agent/base_agentic/default_tools.py +119 -118
  13. autocoder/agent/base_agentic/test_base_agent.py +1 -1
  14. autocoder/agent/base_agentic/tool_registry.py +32 -20
  15. autocoder/agent/base_agentic/tools/read_file_tool_resolver.py +25 -4
  16. autocoder/agent/base_agentic/tools/write_to_file_tool_resolver.py +24 -11
  17. autocoder/agent/base_agentic/types.py +42 -0
  18. autocoder/agent/entry_command_agent/chat.py +73 -59
  19. autocoder/auto_coder.py +31 -40
  20. autocoder/auto_coder_rag.py +11 -1084
  21. autocoder/auto_coder_runner.py +1029 -2310
  22. autocoder/auto_coder_terminal.py +26 -0
  23. autocoder/auto_coder_terminal_v3.py +190 -0
  24. autocoder/chat/conf_command.py +224 -124
  25. autocoder/chat/models_command.py +361 -299
  26. autocoder/chat/rules_command.py +79 -31
  27. autocoder/chat_auto_coder.py +1021 -372
  28. autocoder/chat_auto_coder_lang.py +23 -732
  29. autocoder/commands/auto_command.py +26 -9
  30. autocoder/commands/auto_web.py +1 -1
  31. autocoder/commands/tools.py +44 -44
  32. autocoder/common/__init__.py +150 -128
  33. autocoder/common/ac_style_command_parser/__init__.py +39 -2
  34. autocoder/common/ac_style_command_parser/config.py +422 -0
  35. autocoder/common/ac_style_command_parser/parser.py +292 -78
  36. autocoder/common/ac_style_command_parser/test_parser.py +241 -16
  37. autocoder/common/ac_style_command_parser/test_typed_parser.py +342 -0
  38. autocoder/common/ac_style_command_parser/typed_parser.py +653 -0
  39. autocoder/common/action_yml_file_manager.py +25 -13
  40. autocoder/common/agent_events/__init__.py +52 -0
  41. autocoder/common/agent_events/agent_event_emitter.py +193 -0
  42. autocoder/common/agent_events/event_factory.py +177 -0
  43. autocoder/common/agent_events/examples.py +307 -0
  44. autocoder/common/agent_events/types.py +113 -0
  45. autocoder/common/agent_events/utils.py +68 -0
  46. autocoder/common/agent_hooks/__init__.py +44 -0
  47. autocoder/common/agent_hooks/examples.py +582 -0
  48. autocoder/common/agent_hooks/hook_executor.py +217 -0
  49. autocoder/common/agent_hooks/hook_manager.py +288 -0
  50. autocoder/common/agent_hooks/types.py +133 -0
  51. autocoder/common/agent_hooks/utils.py +99 -0
  52. autocoder/common/agent_query_queue/queue_executor.py +324 -0
  53. autocoder/common/agent_query_queue/queue_manager.py +325 -0
  54. autocoder/common/agents/__init__.py +11 -0
  55. autocoder/common/agents/agent_manager.py +323 -0
  56. autocoder/common/agents/agent_parser.py +189 -0
  57. autocoder/common/agents/example_usage.py +344 -0
  58. autocoder/common/agents/integration_example.py +330 -0
  59. autocoder/common/agents/test_agent_parser.py +545 -0
  60. autocoder/common/async_utils.py +101 -0
  61. autocoder/common/auto_coder_lang.py +23 -972
  62. autocoder/common/autocoderargs_parser/__init__.py +14 -0
  63. autocoder/common/autocoderargs_parser/parser.py +184 -0
  64. autocoder/common/autocoderargs_parser/tests/__init__.py +1 -0
  65. autocoder/common/autocoderargs_parser/tests/test_args_parser.py +235 -0
  66. autocoder/common/autocoderargs_parser/tests/test_token_parser.py +195 -0
  67. autocoder/common/autocoderargs_parser/token_parser.py +290 -0
  68. autocoder/common/buildin_tokenizer.py +2 -4
  69. autocoder/common/code_auto_generate.py +149 -74
  70. autocoder/common/code_auto_generate_diff.py +163 -70
  71. autocoder/common/code_auto_generate_editblock.py +179 -89
  72. autocoder/common/code_auto_generate_strict_diff.py +167 -72
  73. autocoder/common/code_auto_merge_editblock.py +13 -6
  74. autocoder/common/code_modification_ranker.py +1 -1
  75. autocoder/common/command_completer.py +3 -3
  76. autocoder/common/command_file_manager/manager.py +183 -47
  77. autocoder/common/command_file_manager/test_command_file_manager.py +507 -0
  78. autocoder/common/command_templates.py +1 -1
  79. autocoder/common/conf_utils.py +2 -4
  80. autocoder/common/conversations/config.py +11 -3
  81. autocoder/common/conversations/get_conversation_manager.py +100 -2
  82. autocoder/common/conversations/llm_stats_models.py +264 -0
  83. autocoder/common/conversations/manager.py +112 -28
  84. autocoder/common/conversations/models.py +16 -2
  85. autocoder/common/conversations/storage/index_manager.py +134 -10
  86. autocoder/common/core_config/__init__.py +63 -0
  87. autocoder/common/core_config/agentic_mode_manager.py +109 -0
  88. autocoder/common/core_config/base_manager.py +123 -0
  89. autocoder/common/core_config/compatibility.py +151 -0
  90. autocoder/common/core_config/config_manager.py +156 -0
  91. autocoder/common/core_config/conversation_manager.py +31 -0
  92. autocoder/common/core_config/exclude_manager.py +72 -0
  93. autocoder/common/core_config/file_manager.py +177 -0
  94. autocoder/common/core_config/human_as_model_manager.py +129 -0
  95. autocoder/common/core_config/lib_manager.py +54 -0
  96. autocoder/common/core_config/main_manager.py +81 -0
  97. autocoder/common/core_config/mode_manager.py +126 -0
  98. autocoder/common/core_config/models.py +70 -0
  99. autocoder/common/core_config/test_memory_manager.py +1056 -0
  100. autocoder/common/env_manager.py +282 -0
  101. autocoder/common/env_manager_usage_example.py +211 -0
  102. autocoder/common/file_checkpoint/conversation_checkpoint.py +19 -19
  103. autocoder/common/file_checkpoint/manager.py +264 -48
  104. autocoder/common/file_checkpoint/test_backup.py +1 -18
  105. autocoder/common/file_checkpoint/test_manager.py +270 -1
  106. autocoder/common/file_checkpoint/test_store.py +1 -17
  107. autocoder/common/file_handler/__init__.py +23 -0
  108. autocoder/common/file_handler/active_context_handler.py +159 -0
  109. autocoder/common/file_handler/add_files_handler.py +409 -0
  110. autocoder/common/file_handler/chat_handler.py +180 -0
  111. autocoder/common/file_handler/coding_handler.py +401 -0
  112. autocoder/common/file_handler/commit_handler.py +200 -0
  113. autocoder/common/file_handler/lib_handler.py +156 -0
  114. autocoder/common/file_handler/list_files_handler.py +111 -0
  115. autocoder/common/file_handler/mcp_handler.py +268 -0
  116. autocoder/common/file_handler/models_handler.py +493 -0
  117. autocoder/common/file_handler/remove_files_handler.py +172 -0
  118. autocoder/common/file_monitor/test_file_monitor.py +307 -0
  119. autocoder/common/git_utils.py +51 -10
  120. autocoder/common/global_cancel.py +15 -6
  121. autocoder/common/ignorefiles/test_ignore_file_utils.py +1 -1
  122. autocoder/common/international/__init__.py +31 -0
  123. autocoder/common/international/demo_international.py +92 -0
  124. autocoder/common/international/message_manager.py +157 -0
  125. autocoder/common/international/messages/__init__.py +56 -0
  126. autocoder/common/international/messages/async_command_messages.py +507 -0
  127. autocoder/common/international/messages/auto_coder_messages.py +2208 -0
  128. autocoder/common/international/messages/chat_auto_coder_messages.py +1547 -0
  129. autocoder/common/international/messages/command_help_messages.py +986 -0
  130. autocoder/common/international/messages/conversation_command_messages.py +191 -0
  131. autocoder/common/international/messages/git_helper_plugin_messages.py +159 -0
  132. autocoder/common/international/messages/queue_command_messages.py +751 -0
  133. autocoder/common/international/messages/rules_command_messages.py +77 -0
  134. autocoder/common/international/messages/sdk_messages.py +1707 -0
  135. autocoder/common/international/messages/token_helper_plugin_messages.py +361 -0
  136. autocoder/common/international/messages/tool_display_messages.py +1212 -0
  137. autocoder/common/international/messages/workflow_exception_messages.py +473 -0
  138. autocoder/common/international/test_international.py +612 -0
  139. autocoder/common/linter_core/__init__.py +28 -0
  140. autocoder/common/linter_core/base_linter.py +61 -0
  141. autocoder/common/linter_core/config_loader.py +271 -0
  142. autocoder/common/linter_core/formatters/__init__.py +0 -0
  143. autocoder/common/linter_core/formatters/base_formatter.py +38 -0
  144. autocoder/common/linter_core/formatters/raw_formatter.py +17 -0
  145. autocoder/common/linter_core/linter.py +166 -0
  146. autocoder/common/linter_core/linter_factory.py +216 -0
  147. autocoder/common/linter_core/linter_manager.py +333 -0
  148. autocoder/common/linter_core/linters/__init__.py +9 -0
  149. autocoder/common/linter_core/linters/java_linter.py +342 -0
  150. autocoder/common/linter_core/linters/python_linter.py +115 -0
  151. autocoder/common/linter_core/linters/typescript_linter.py +119 -0
  152. autocoder/common/linter_core/models/__init__.py +7 -0
  153. autocoder/common/linter_core/models/lint_result.py +91 -0
  154. autocoder/common/linter_core/models.py +33 -0
  155. autocoder/common/linter_core/tests/__init__.py +3 -0
  156. autocoder/common/linter_core/tests/test_config_loader.py +323 -0
  157. autocoder/common/linter_core/tests/test_config_loading.py +308 -0
  158. autocoder/common/linter_core/tests/test_factory_manager.py +234 -0
  159. autocoder/common/linter_core/tests/test_formatters.py +147 -0
  160. autocoder/common/linter_core/tests/test_integration.py +317 -0
  161. autocoder/common/linter_core/tests/test_java_linter.py +496 -0
  162. autocoder/common/linter_core/tests/test_linters.py +265 -0
  163. autocoder/common/linter_core/tests/test_models.py +81 -0
  164. autocoder/common/linter_core/tests/verify_config_loading.py +296 -0
  165. autocoder/common/linter_core/tests/verify_fixes.py +183 -0
  166. autocoder/common/llm_friendly_package/__init__.py +31 -0
  167. autocoder/common/llm_friendly_package/base_manager.py +102 -0
  168. autocoder/common/llm_friendly_package/docs_manager.py +121 -0
  169. autocoder/common/llm_friendly_package/library_manager.py +171 -0
  170. autocoder/common/{llm_friendly_package.py → llm_friendly_package/main_manager.py} +204 -231
  171. autocoder/common/llm_friendly_package/models.py +40 -0
  172. autocoder/common/llm_friendly_package/test_llm_friendly_package.py +536 -0
  173. autocoder/common/llms/__init__.py +15 -0
  174. autocoder/common/llms/demo_error_handling.py +85 -0
  175. autocoder/common/llms/factory.py +142 -0
  176. autocoder/common/llms/manager.py +264 -0
  177. autocoder/common/llms/pricing.py +121 -0
  178. autocoder/common/llms/registry.py +288 -0
  179. autocoder/common/llms/schema.py +77 -0
  180. autocoder/common/llms/simple_demo.py +45 -0
  181. autocoder/common/llms/test_quick_model.py +116 -0
  182. autocoder/common/llms/test_remove_functionality.py +182 -0
  183. autocoder/common/llms/tests/__init__.py +1 -0
  184. autocoder/common/llms/tests/test_manager.py +330 -0
  185. autocoder/common/llms/tests/test_registry.py +364 -0
  186. autocoder/common/mcp_tools/__init__.py +62 -0
  187. autocoder/common/{mcp_tools.py → mcp_tools/executor.py} +49 -40
  188. autocoder/common/{mcp_hub.py → mcp_tools/hub.py} +42 -68
  189. autocoder/common/{mcp_server_install.py → mcp_tools/installer.py} +16 -28
  190. autocoder/common/{mcp_server.py → mcp_tools/server.py} +176 -48
  191. autocoder/common/mcp_tools/test_keyboard_interrupt.py +93 -0
  192. autocoder/common/mcp_tools/test_mcp_tools.py +391 -0
  193. autocoder/common/{mcp_server_types.py → mcp_tools/types.py} +121 -48
  194. autocoder/common/mcp_tools/verify_functionality.py +202 -0
  195. autocoder/common/model_speed_tester.py +32 -26
  196. autocoder/common/priority_directory_finder/__init__.py +142 -0
  197. autocoder/common/priority_directory_finder/examples.py +230 -0
  198. autocoder/common/priority_directory_finder/finder.py +283 -0
  199. autocoder/common/priority_directory_finder/models.py +236 -0
  200. autocoder/common/priority_directory_finder/test_priority_directory_finder.py +431 -0
  201. autocoder/common/project_scanner/__init__.py +18 -0
  202. autocoder/common/project_scanner/compat.py +77 -0
  203. autocoder/common/project_scanner/scanner.py +436 -0
  204. autocoder/common/project_tracker/__init__.py +27 -0
  205. autocoder/common/project_tracker/api.py +228 -0
  206. autocoder/common/project_tracker/demo.py +272 -0
  207. autocoder/common/project_tracker/tracker.py +487 -0
  208. autocoder/common/project_tracker/types.py +53 -0
  209. autocoder/common/pruner/__init__.py +67 -0
  210. autocoder/common/pruner/agentic_conversation_pruner.py +746 -0
  211. autocoder/common/{context_pruner.py → pruner/context_pruner.py} +137 -40
  212. autocoder/common/pruner/conversation_message_ids_api.py +386 -0
  213. autocoder/common/pruner/conversation_message_ids_manager.py +347 -0
  214. autocoder/common/pruner/conversation_message_ids_pruner.py +473 -0
  215. autocoder/common/pruner/conversation_normalizer.py +347 -0
  216. autocoder/common/{conversation_pruner.py → pruner/conversation_pruner.py} +26 -6
  217. autocoder/common/pruner/test_agentic_conversation_pruner.py +784 -0
  218. autocoder/common/pruner/test_context_pruner.py +546 -0
  219. autocoder/common/pruner/test_conversation_normalizer.py +502 -0
  220. autocoder/common/pruner/test_tool_content_detector.py +324 -0
  221. autocoder/common/pruner/tool_content_detector.py +227 -0
  222. autocoder/common/pruner/tools/__init__.py +18 -0
  223. autocoder/common/pruner/tools/query_message_ids.py +264 -0
  224. autocoder/common/pruner/tools/test_agentic_pruning_logic.py +432 -0
  225. autocoder/common/pruner/tools/test_message_ids_pruning_only.py +192 -0
  226. autocoder/common/pull_requests/__init__.py +9 -1
  227. autocoder/common/pull_requests/utils.py +122 -1
  228. autocoder/common/rag_manager/rag_manager.py +36 -40
  229. autocoder/common/rulefiles/__init__.py +53 -1
  230. autocoder/common/rulefiles/api.py +250 -0
  231. autocoder/common/rulefiles/core/__init__.py +14 -0
  232. autocoder/common/rulefiles/core/manager.py +241 -0
  233. autocoder/common/rulefiles/core/selector.py +805 -0
  234. autocoder/common/rulefiles/models/__init__.py +20 -0
  235. autocoder/common/rulefiles/models/index.py +16 -0
  236. autocoder/common/rulefiles/models/init_rule.py +18 -0
  237. autocoder/common/rulefiles/models/rule_file.py +18 -0
  238. autocoder/common/rulefiles/models/rule_relevance.py +14 -0
  239. autocoder/common/rulefiles/models/summary.py +16 -0
  240. autocoder/common/rulefiles/test_rulefiles.py +776 -0
  241. autocoder/common/rulefiles/utils/__init__.py +34 -0
  242. autocoder/common/rulefiles/utils/monitor.py +86 -0
  243. autocoder/common/rulefiles/utils/parser.py +230 -0
  244. autocoder/common/save_formatted_log.py +67 -10
  245. autocoder/common/search_replace.py +8 -1
  246. autocoder/common/search_replace_patch/__init__.py +24 -0
  247. autocoder/common/search_replace_patch/base.py +115 -0
  248. autocoder/common/search_replace_patch/manager.py +248 -0
  249. autocoder/common/search_replace_patch/patch_replacer.py +304 -0
  250. autocoder/common/search_replace_patch/similarity_replacer.py +306 -0
  251. autocoder/common/search_replace_patch/string_replacer.py +181 -0
  252. autocoder/common/search_replace_patch/tests/__init__.py +3 -0
  253. autocoder/common/search_replace_patch/tests/run_tests.py +126 -0
  254. autocoder/common/search_replace_patch/tests/test_base.py +188 -0
  255. autocoder/common/search_replace_patch/tests/test_empty_line_insert.py +233 -0
  256. autocoder/common/search_replace_patch/tests/test_integration.py +389 -0
  257. autocoder/common/search_replace_patch/tests/test_manager.py +351 -0
  258. autocoder/common/search_replace_patch/tests/test_patch_replacer.py +316 -0
  259. autocoder/common/search_replace_patch/tests/test_regex_replacer.py +306 -0
  260. autocoder/common/search_replace_patch/tests/test_similarity_replacer.py +384 -0
  261. autocoder/common/shell_commands/__init__.py +197 -0
  262. autocoder/common/shell_commands/background_process_notifier.py +346 -0
  263. autocoder/common/shell_commands/command_executor.py +1127 -0
  264. autocoder/common/shell_commands/error_recovery.py +541 -0
  265. autocoder/common/shell_commands/exceptions.py +120 -0
  266. autocoder/common/shell_commands/interactive_executor.py +476 -0
  267. autocoder/common/shell_commands/interactive_pexpect_process.py +623 -0
  268. autocoder/common/shell_commands/interactive_process.py +744 -0
  269. autocoder/common/shell_commands/interactive_session_manager.py +1014 -0
  270. autocoder/common/shell_commands/monitoring.py +529 -0
  271. autocoder/common/shell_commands/process_cleanup.py +386 -0
  272. autocoder/common/shell_commands/process_manager.py +606 -0
  273. autocoder/common/shell_commands/test_interactive_pexpect_process.py +281 -0
  274. autocoder/common/shell_commands/tests/__init__.py +6 -0
  275. autocoder/common/shell_commands/tests/conftest.py +118 -0
  276. autocoder/common/shell_commands/tests/test_background_process_notifier.py +703 -0
  277. autocoder/common/shell_commands/tests/test_command_executor.py +448 -0
  278. autocoder/common/shell_commands/tests/test_error_recovery.py +305 -0
  279. autocoder/common/shell_commands/tests/test_exceptions.py +299 -0
  280. autocoder/common/shell_commands/tests/test_execute_batch.py +588 -0
  281. autocoder/common/shell_commands/tests/test_indented_batch_commands.py +244 -0
  282. autocoder/common/shell_commands/tests/test_integration.py +664 -0
  283. autocoder/common/shell_commands/tests/test_monitoring.py +546 -0
  284. autocoder/common/shell_commands/tests/test_performance.py +632 -0
  285. autocoder/common/shell_commands/tests/test_process_cleanup.py +397 -0
  286. autocoder/common/shell_commands/tests/test_process_manager.py +606 -0
  287. autocoder/common/shell_commands/tests/test_timeout_config.py +343 -0
  288. autocoder/common/shell_commands/tests/test_timeout_manager.py +520 -0
  289. autocoder/common/shell_commands/timeout_config.py +315 -0
  290. autocoder/common/shell_commands/timeout_manager.py +352 -0
  291. autocoder/common/terminal_paste/__init__.py +14 -0
  292. autocoder/common/terminal_paste/demo.py +145 -0
  293. autocoder/common/terminal_paste/demo_paste_functionality.py +95 -0
  294. autocoder/common/terminal_paste/paste_handler.py +200 -0
  295. autocoder/common/terminal_paste/paste_manager.py +118 -0
  296. autocoder/common/terminal_paste/tests/__init__.py +1 -0
  297. autocoder/common/terminal_paste/tests/test_paste_handler.py +182 -0
  298. autocoder/common/terminal_paste/tests/test_paste_manager.py +126 -0
  299. autocoder/common/terminal_paste/utils.py +163 -0
  300. autocoder/common/test_autocoder_args.py +232 -0
  301. autocoder/common/test_env_manager.py +173 -0
  302. autocoder/common/test_env_manager_integration.py +159 -0
  303. autocoder/common/text_similarity/__init__.py +9 -0
  304. autocoder/common/text_similarity/demo.py +216 -0
  305. autocoder/common/text_similarity/examples.py +266 -0
  306. autocoder/common/text_similarity/test_text_similarity.py +306 -0
  307. autocoder/common/text_similarity/text_similarity.py +194 -0
  308. autocoder/common/text_similarity/utils.py +125 -0
  309. autocoder/common/todos/__init__.py +61 -0
  310. autocoder/common/todos/cache/__init__.py +16 -0
  311. autocoder/common/todos/cache/base_cache.py +89 -0
  312. autocoder/common/todos/cache/cache_manager.py +228 -0
  313. autocoder/common/todos/cache/memory_cache.py +225 -0
  314. autocoder/common/todos/config.py +155 -0
  315. autocoder/common/todos/exceptions.py +35 -0
  316. autocoder/common/todos/get_todo_manager.py +161 -0
  317. autocoder/common/todos/manager.py +537 -0
  318. autocoder/common/todos/models.py +239 -0
  319. autocoder/common/todos/storage/__init__.py +14 -0
  320. autocoder/common/todos/storage/base_storage.py +76 -0
  321. autocoder/common/todos/storage/file_storage.py +278 -0
  322. autocoder/common/tokens/__init__.py +15 -0
  323. autocoder/common/tokens/counter.py +44 -2
  324. autocoder/common/tools_manager/__init__.py +17 -0
  325. autocoder/common/tools_manager/examples.py +162 -0
  326. autocoder/common/tools_manager/manager.py +385 -0
  327. autocoder/common/tools_manager/models.py +39 -0
  328. autocoder/common/tools_manager/test_tools_manager.py +303 -0
  329. autocoder/common/tools_manager/utils.py +191 -0
  330. autocoder/common/v2/agent/agentic_callbacks.py +270 -0
  331. autocoder/common/v2/agent/agentic_edit.py +2729 -2052
  332. autocoder/common/v2/agent/agentic_edit_change_manager.py +474 -0
  333. autocoder/common/v2/agent/agentic_edit_tools/__init__.py +43 -2
  334. autocoder/common/v2/agent/agentic_edit_tools/ac_mod_list_tool_resolver.py +279 -0
  335. autocoder/common/v2/agent/agentic_edit_tools/ac_mod_read_tool_resolver.py +40 -0
  336. autocoder/common/v2/agent/agentic_edit_tools/ac_mod_write_tool_resolver.py +52 -0
  337. autocoder/common/v2/agent/agentic_edit_tools/ask_followup_question_tool_resolver.py +8 -0
  338. autocoder/common/v2/agent/agentic_edit_tools/background_task_tool_resolver.py +1167 -0
  339. autocoder/common/v2/agent/agentic_edit_tools/base_tool_resolver.py +2 -2
  340. autocoder/common/v2/agent/agentic_edit_tools/conversation_message_ids_read_tool_resolver.py +214 -0
  341. autocoder/common/v2/agent/agentic_edit_tools/conversation_message_ids_write_tool_resolver.py +299 -0
  342. autocoder/common/v2/agent/agentic_edit_tools/count_tokens_tool_resolver.py +290 -0
  343. autocoder/common/v2/agent/agentic_edit_tools/execute_command_tool_resolver.py +565 -30
  344. autocoder/common/v2/agent/agentic_edit_tools/execute_workflow_tool_resolver.py +485 -0
  345. autocoder/common/v2/agent/agentic_edit_tools/extract_to_text_tool_resolver.py +225 -0
  346. autocoder/common/v2/agent/agentic_edit_tools/lint_report.py +79 -0
  347. autocoder/common/v2/agent/agentic_edit_tools/linter_config_models.py +343 -0
  348. autocoder/common/v2/agent/agentic_edit_tools/linter_enabled_tool_resolver.py +189 -0
  349. autocoder/common/v2/agent/agentic_edit_tools/list_files_tool_resolver.py +169 -101
  350. autocoder/common/v2/agent/agentic_edit_tools/load_extra_document_tool_resolver.py +349 -0
  351. autocoder/common/v2/agent/agentic_edit_tools/read_file_tool_resolver.py +244 -51
  352. autocoder/common/v2/agent/agentic_edit_tools/replace_in_file_tool_resolver.py +667 -147
  353. autocoder/common/v2/agent/agentic_edit_tools/run_named_subagents_tool_resolver.py +691 -0
  354. autocoder/common/v2/agent/agentic_edit_tools/search_files_tool_resolver.py +409 -140
  355. autocoder/common/v2/agent/agentic_edit_tools/session_interactive_tool_resolver.py +115 -0
  356. autocoder/common/v2/agent/agentic_edit_tools/session_start_tool_resolver.py +190 -0
  357. autocoder/common/v2/agent/agentic_edit_tools/session_stop_tool_resolver.py +76 -0
  358. autocoder/common/v2/agent/agentic_edit_tools/test_write_to_file_tool_resolver.py +209 -194
  359. autocoder/common/v2/agent/agentic_edit_tools/todo_read_tool_resolver.py +135 -0
  360. autocoder/common/v2/agent/agentic_edit_tools/todo_write_tool_resolver.py +328 -0
  361. autocoder/common/v2/agent/agentic_edit_tools/use_mcp_tool_resolver.py +2 -2
  362. autocoder/common/v2/agent/agentic_edit_tools/web_crawl_tool_resolver.py +557 -0
  363. autocoder/common/v2/agent/agentic_edit_tools/web_search_tool_resolver.py +600 -0
  364. autocoder/common/v2/agent/agentic_edit_tools/write_to_file_tool_resolver.py +56 -121
  365. autocoder/common/v2/agent/agentic_edit_types.py +386 -10
  366. autocoder/common/v2/agent/runner/__init__.py +31 -0
  367. autocoder/common/v2/agent/runner/base_runner.py +92 -0
  368. autocoder/common/v2/agent/runner/file_based_event_runner.py +217 -0
  369. autocoder/common/v2/agent/runner/sdk_runner.py +182 -0
  370. autocoder/common/v2/agent/runner/terminal_runner.py +396 -0
  371. autocoder/common/v2/agent/runner/tool_display.py +589 -0
  372. autocoder/common/v2/agent/test_agentic_callbacks.py +265 -0
  373. autocoder/common/v2/agent/test_agentic_edit.py +194 -0
  374. autocoder/common/v2/agent/tool_caller/__init__.py +24 -0
  375. autocoder/common/v2/agent/tool_caller/default_tool_resolver_map.py +135 -0
  376. autocoder/common/v2/agent/tool_caller/integration_test.py +172 -0
  377. autocoder/common/v2/agent/tool_caller/plugins/__init__.py +14 -0
  378. autocoder/common/v2/agent/tool_caller/plugins/base_plugin.py +126 -0
  379. autocoder/common/v2/agent/tool_caller/plugins/examples/__init__.py +13 -0
  380. autocoder/common/v2/agent/tool_caller/plugins/examples/logging_plugin.py +164 -0
  381. autocoder/common/v2/agent/tool_caller/plugins/examples/security_filter_plugin.py +198 -0
  382. autocoder/common/v2/agent/tool_caller/plugins/plugin_interface.py +141 -0
  383. autocoder/common/v2/agent/tool_caller/test_tool_caller.py +278 -0
  384. autocoder/common/v2/agent/tool_caller/tool_call_plugin_manager.py +331 -0
  385. autocoder/common/v2/agent/tool_caller/tool_caller.py +337 -0
  386. autocoder/common/v2/agent/tool_caller/usage_example.py +193 -0
  387. autocoder/common/v2/code_agentic_editblock_manager.py +4 -4
  388. autocoder/common/v2/code_auto_generate.py +136 -78
  389. autocoder/common/v2/code_auto_generate_diff.py +135 -79
  390. autocoder/common/v2/code_auto_generate_editblock.py +174 -99
  391. autocoder/common/v2/code_auto_generate_strict_diff.py +151 -71
  392. autocoder/common/v2/code_auto_merge.py +1 -1
  393. autocoder/common/v2/code_auto_merge_editblock.py +13 -1
  394. autocoder/common/v2/code_diff_manager.py +3 -3
  395. autocoder/common/v2/code_editblock_manager.py +4 -14
  396. autocoder/common/v2/code_manager.py +1 -1
  397. autocoder/common/v2/code_strict_diff_manager.py +2 -2
  398. autocoder/common/wrap_llm_hint/__init__.py +10 -0
  399. autocoder/common/wrap_llm_hint/test_wrap_llm_hint.py +1067 -0
  400. autocoder/common/wrap_llm_hint/utils.py +432 -0
  401. autocoder/common/wrap_llm_hint/wrap_llm_hint.py +323 -0
  402. autocoder/completer/__init__.py +8 -0
  403. autocoder/completer/command_completer_v2.py +1051 -0
  404. autocoder/default_project/__init__.py +501 -0
  405. autocoder/dispacher/__init__.py +4 -12
  406. autocoder/dispacher/actions/action.py +165 -7
  407. autocoder/dispacher/actions/plugins/action_regex_project.py +2 -2
  408. autocoder/index/entry.py +117 -125
  409. autocoder/{agent → index/filter}/agentic_filter.py +323 -334
  410. autocoder/index/filter/normal_filter.py +5 -11
  411. autocoder/index/filter/quick_filter.py +1 -1
  412. autocoder/index/index.py +36 -9
  413. autocoder/index/tests/__init__.py +1 -0
  414. autocoder/index/tests/run_tests.py +195 -0
  415. autocoder/index/tests/test_entry.py +303 -0
  416. autocoder/index/tests/test_index_manager.py +314 -0
  417. autocoder/index/tests/test_module_integration.py +300 -0
  418. autocoder/index/tests/test_symbols_utils.py +183 -0
  419. autocoder/inner/__init__.py +4 -0
  420. autocoder/inner/agentic.py +932 -0
  421. autocoder/inner/async_command_handler.py +992 -0
  422. autocoder/inner/conversation_command_handlers.py +623 -0
  423. autocoder/inner/merge_command_handler.py +213 -0
  424. autocoder/inner/queue_command_handler.py +684 -0
  425. autocoder/models.py +95 -266
  426. autocoder/plugins/git_helper_plugin.py +31 -29
  427. autocoder/plugins/token_helper_plugin.py +156 -37
  428. autocoder/pyproject/__init__.py +32 -29
  429. autocoder/rag/agentic_rag.py +215 -75
  430. autocoder/rag/cache/simple_cache.py +1 -2
  431. autocoder/rag/loaders/image_loader.py +1 -1
  432. autocoder/rag/long_context_rag.py +42 -26
  433. autocoder/rag/qa_conversation_strategy.py +1 -1
  434. autocoder/rag/terminal/__init__.py +17 -0
  435. autocoder/rag/terminal/args.py +581 -0
  436. autocoder/rag/terminal/bootstrap.py +61 -0
  437. autocoder/rag/terminal/command_handlers.py +653 -0
  438. autocoder/rag/terminal/formatters/__init__.py +20 -0
  439. autocoder/rag/terminal/formatters/base.py +70 -0
  440. autocoder/rag/terminal/formatters/json_format.py +66 -0
  441. autocoder/rag/terminal/formatters/stream_json.py +95 -0
  442. autocoder/rag/terminal/formatters/text.py +28 -0
  443. autocoder/rag/terminal/init.py +120 -0
  444. autocoder/rag/terminal/utils.py +106 -0
  445. autocoder/rag/test_agentic_rag.py +389 -0
  446. autocoder/rag/test_doc_filter.py +3 -3
  447. autocoder/rag/test_long_context_rag.py +1 -1
  448. autocoder/rag/test_token_limiter.py +517 -10
  449. autocoder/rag/token_counter.py +3 -0
  450. autocoder/rag/token_limiter.py +19 -15
  451. autocoder/rag/tools/__init__.py +26 -2
  452. autocoder/rag/tools/bochaai_example.py +343 -0
  453. autocoder/rag/tools/bochaai_sdk.py +541 -0
  454. autocoder/rag/tools/metaso_example.py +268 -0
  455. autocoder/rag/tools/metaso_sdk.py +417 -0
  456. autocoder/rag/tools/recall_tool.py +28 -7
  457. autocoder/rag/tools/run_integration_tests.py +204 -0
  458. autocoder/rag/tools/test_all_providers.py +318 -0
  459. autocoder/rag/tools/test_bochaai_integration.py +482 -0
  460. autocoder/rag/tools/test_final_integration.py +215 -0
  461. autocoder/rag/tools/test_metaso_integration.py +424 -0
  462. autocoder/rag/tools/test_metaso_real.py +171 -0
  463. autocoder/rag/tools/test_web_crawl_tool.py +639 -0
  464. autocoder/rag/tools/test_web_search_tool.py +509 -0
  465. autocoder/rag/tools/todo_read_tool.py +202 -0
  466. autocoder/rag/tools/todo_write_tool.py +412 -0
  467. autocoder/rag/tools/web_crawl_tool.py +634 -0
  468. autocoder/rag/tools/web_search_tool.py +558 -0
  469. autocoder/rag/tools/web_tools_example.py +119 -0
  470. autocoder/rag/types.py +16 -0
  471. autocoder/rag/variable_holder.py +4 -2
  472. autocoder/rags.py +86 -79
  473. autocoder/regexproject/__init__.py +23 -21
  474. autocoder/run_context.py +9 -0
  475. autocoder/sdk/__init__.py +50 -161
  476. autocoder/sdk/api.py +370 -0
  477. autocoder/sdk/async_runner/__init__.py +26 -0
  478. autocoder/sdk/async_runner/async_executor.py +650 -0
  479. autocoder/sdk/async_runner/async_handler.py +356 -0
  480. autocoder/sdk/async_runner/markdown_processor.py +595 -0
  481. autocoder/sdk/async_runner/task_metadata.py +284 -0
  482. autocoder/sdk/async_runner/worktree_manager.py +438 -0
  483. autocoder/sdk/cli/__init__.py +2 -5
  484. autocoder/sdk/cli/formatters.py +28 -204
  485. autocoder/sdk/cli/handlers.py +77 -44
  486. autocoder/sdk/cli/main.py +158 -170
  487. autocoder/sdk/cli/options.py +95 -22
  488. autocoder/sdk/constants.py +139 -51
  489. autocoder/sdk/core/auto_coder_core.py +484 -267
  490. autocoder/sdk/core/bridge.py +298 -118
  491. autocoder/sdk/exceptions.py +18 -12
  492. autocoder/sdk/formatters/__init__.py +19 -0
  493. autocoder/sdk/formatters/input.py +64 -0
  494. autocoder/sdk/formatters/output.py +247 -0
  495. autocoder/sdk/formatters/stream.py +54 -0
  496. autocoder/sdk/models/__init__.py +6 -5
  497. autocoder/sdk/models/options.py +55 -18
  498. autocoder/sdk/utils/formatters.py +27 -195
  499. autocoder/suffixproject/__init__.py +28 -25
  500. autocoder/terminal/__init__.py +14 -0
  501. autocoder/terminal/app.py +454 -0
  502. autocoder/terminal/args.py +32 -0
  503. autocoder/terminal/bootstrap.py +178 -0
  504. autocoder/terminal/command_processor.py +521 -0
  505. autocoder/terminal/command_registry.py +57 -0
  506. autocoder/terminal/help.py +97 -0
  507. autocoder/terminal/tasks/__init__.py +5 -0
  508. autocoder/terminal/tasks/background.py +77 -0
  509. autocoder/terminal/tasks/task_event.py +70 -0
  510. autocoder/terminal/ui/__init__.py +13 -0
  511. autocoder/terminal/ui/completer.py +268 -0
  512. autocoder/terminal/ui/keybindings.py +75 -0
  513. autocoder/terminal/ui/session.py +41 -0
  514. autocoder/terminal/ui/toolbar.py +64 -0
  515. autocoder/terminal/utils/__init__.py +13 -0
  516. autocoder/terminal/utils/errors.py +18 -0
  517. autocoder/terminal/utils/paths.py +19 -0
  518. autocoder/terminal/utils/shell.py +43 -0
  519. autocoder/terminal_v3/__init__.py +10 -0
  520. autocoder/terminal_v3/app.py +201 -0
  521. autocoder/terminal_v3/handlers/__init__.py +5 -0
  522. autocoder/terminal_v3/handlers/command_handler.py +131 -0
  523. autocoder/terminal_v3/models/__init__.py +6 -0
  524. autocoder/terminal_v3/models/conversation_buffer.py +214 -0
  525. autocoder/terminal_v3/models/message.py +50 -0
  526. autocoder/terminal_v3/models/tool_display.py +247 -0
  527. autocoder/terminal_v3/ui/__init__.py +7 -0
  528. autocoder/terminal_v3/ui/keybindings.py +56 -0
  529. autocoder/terminal_v3/ui/layout.py +141 -0
  530. autocoder/terminal_v3/ui/styles.py +43 -0
  531. autocoder/tsproject/__init__.py +23 -23
  532. autocoder/utils/auto_coder_utils/chat_stream_out.py +1 -1
  533. autocoder/utils/llms.py +88 -80
  534. autocoder/utils/math_utils.py +101 -0
  535. autocoder/utils/model_provider_selector.py +16 -4
  536. autocoder/utils/operate_config_api.py +33 -5
  537. autocoder/utils/thread_utils.py +2 -2
  538. autocoder/version.py +4 -2
  539. autocoder/workflow_agents/__init__.py +84 -0
  540. autocoder/workflow_agents/agent.py +143 -0
  541. autocoder/workflow_agents/exceptions.py +573 -0
  542. autocoder/workflow_agents/executor.py +489 -0
  543. autocoder/workflow_agents/loader.py +737 -0
  544. autocoder/workflow_agents/runner.py +267 -0
  545. autocoder/workflow_agents/types.py +172 -0
  546. autocoder/workflow_agents/utils.py +434 -0
  547. autocoder/workflow_agents/workflow_manager.py +211 -0
  548. auto_coder-0.1.400.dist-info/METADATA +0 -396
  549. auto_coder-0.1.400.dist-info/RECORD +0 -425
  550. auto_coder-0.1.400.dist-info/licenses/LICENSE +0 -201
  551. autocoder/auto_coder_server.py +0 -672
  552. autocoder/benchmark.py +0 -138
  553. autocoder/common/ac_style_command_parser/example.py +0 -7
  554. autocoder/common/cleaner.py +0 -31
  555. autocoder/common/command_completer_v2.py +0 -615
  556. autocoder/common/directory_cache/__init__.py +0 -1
  557. autocoder/common/directory_cache/cache.py +0 -192
  558. autocoder/common/directory_cache/test_cache.py +0 -190
  559. autocoder/common/file_checkpoint/examples.py +0 -217
  560. autocoder/common/llm_friendly_package_example.py +0 -138
  561. autocoder/common/llm_friendly_package_test.py +0 -63
  562. autocoder/common/pull_requests/test_module.py +0 -1
  563. autocoder/common/rulefiles/autocoderrules_utils.py +0 -484
  564. autocoder/common/text.py +0 -30
  565. autocoder/common/v2/agent/agentic_edit_tools/list_package_info_tool_resolver.py +0 -42
  566. autocoder/common/v2/agent/agentic_edit_tools/test_execute_command_tool_resolver.py +0 -70
  567. autocoder/common/v2/agent/agentic_edit_tools/test_search_files_tool_resolver.py +0 -163
  568. autocoder/common/v2/agent/agentic_tool_display.py +0 -183
  569. autocoder/plugins/dynamic_completion_example.py +0 -148
  570. autocoder/plugins/sample_plugin.py +0 -160
  571. autocoder/sdk/cli/__main__.py +0 -26
  572. autocoder/sdk/cli/completion_wrapper.py +0 -38
  573. autocoder/sdk/cli/install_completion.py +0 -301
  574. autocoder/sdk/models/messages.py +0 -209
  575. autocoder/sdk/session/__init__.py +0 -32
  576. autocoder/sdk/session/session.py +0 -106
  577. autocoder/sdk/session/session_manager.py +0 -56
  578. {auto_coder-0.1.400.dist-info → auto_coder-2.0.0.dist-info}/top_level.txt +0 -0
  579. /autocoder/{sdk/example.py → common/agent_query_queue/__init__.py} +0 -0
@@ -0,0 +1,248 @@
1
+ """
2
+ Search Replace Manager - unified interface for different replacement strategies
3
+ """
4
+
5
+ from typing import List, Tuple, Optional, Dict, Any
6
+ from loguru import logger
7
+
8
+ from .base import BaseReplacer, ReplaceResult, ReplaceStrategy
9
+ from .string_replacer import StringReplacer
10
+ from .patch_replacer import PatchReplacer
11
+ from .similarity_replacer import SimilarityReplacer
12
+
13
+
14
+ class SearchReplaceManager:
15
+ """搜索替换管理器 - 统一管理多种替换策略"""
16
+
17
+ def __init__(self, default_strategy: ReplaceStrategy = ReplaceStrategy.STRING):
18
+ """
19
+ 初始化搜索替换管理器
20
+
21
+ Args:
22
+ default_strategy: 默认的替换策略
23
+ """
24
+ self.default_strategy = default_strategy
25
+ self.replacers: Dict[ReplaceStrategy, BaseReplacer] = {}
26
+ self._initialize_replacers()
27
+
28
+ def _initialize_replacers(self):
29
+ """初始化所有替换器"""
30
+ try:
31
+ # 初始化字符串替换器
32
+ self.replacers[ReplaceStrategy.STRING] = StringReplacer(lenient_mode=True)
33
+ logger.info("Initialized StringReplacer")
34
+ except Exception as e:
35
+ logger.error(f"Failed to initialize StringReplacer: {e}")
36
+
37
+ try:
38
+ # 初始化补丁替换器
39
+ self.replacers[ReplaceStrategy.PATCH] = PatchReplacer(use_patch_ng=True)
40
+ logger.info("Initialized PatchReplacer")
41
+ except Exception as e:
42
+ logger.error(f"Failed to initialize PatchReplacer: {e}")
43
+
44
+ try:
45
+ # 初始化相似度替换器
46
+ self.replacers[ReplaceStrategy.SIMILARITY] = SimilarityReplacer(similarity_threshold=0.99)
47
+ logger.info("Initialized SimilarityReplacer")
48
+ except Exception as e:
49
+ logger.error(f"Failed to initialize SimilarityReplacer: {e}")
50
+
51
+ def get_replacer(self, strategy: ReplaceStrategy) -> Optional[BaseReplacer]:
52
+ """
53
+ 获取指定策略的替换器
54
+
55
+ Args:
56
+ strategy: 替换策略
57
+
58
+ Returns:
59
+ 对应的替换器实例,如果不存在则返回 None
60
+ """
61
+ return self.replacers.get(strategy)
62
+
63
+ def replace(self, content: str, search_blocks: List[Tuple[str, str]],
64
+ strategy: Optional[ReplaceStrategy] = None) -> ReplaceResult:
65
+ """
66
+ 执行文本替换
67
+
68
+ Args:
69
+ content: 原始文件内容
70
+ search_blocks: 搜索替换块列表
71
+ strategy: 指定的替换策略,如果为None则使用默认策略
72
+
73
+ Returns:
74
+ ReplaceResult: 替换结果
75
+ """
76
+ if strategy is None:
77
+ strategy = self.default_strategy
78
+
79
+ replacer = self.get_replacer(strategy)
80
+ if not replacer:
81
+ return ReplaceResult(
82
+ success=False,
83
+ message=f"Replacer for strategy '{strategy.value}' not available",
84
+ total_count=len(search_blocks)
85
+ )
86
+
87
+ logger.info(f"Using {strategy.value} strategy for replacement")
88
+ return replacer.replace(content, search_blocks)
89
+
90
+ def replace_with_fallback(self, content: str, search_blocks: List[Tuple[str, str]],
91
+ fallback_strategies: Optional[List[ReplaceStrategy]] = None) -> ReplaceResult:
92
+ """
93
+ 使用回退策略进行文本替换
94
+
95
+ Args:
96
+ content: 原始文件内容
97
+ search_blocks: 搜索替换块列表
98
+ fallback_strategies: 回退策略列表,默认为 [STRING, SIMILARITY, PATCH]
99
+
100
+ Returns:
101
+ ReplaceResult: 替换结果
102
+ """
103
+ if fallback_strategies is None:
104
+ fallback_strategies = [
105
+ ReplaceStrategy.STRING,
106
+ ReplaceStrategy.SIMILARITY,
107
+ ReplaceStrategy.PATCH,
108
+ ]
109
+
110
+ last_result = None
111
+
112
+ for strategy in fallback_strategies:
113
+ replacer = self.get_replacer(strategy)
114
+ if not replacer:
115
+ logger.warning(f"Replacer for strategy '{strategy.value}' not available, skipping")
116
+ continue
117
+
118
+ if not replacer.can_handle(content, search_blocks):
119
+ logger.warning(f"Replacer '{strategy.value}' cannot handle the given content, skipping")
120
+ continue
121
+
122
+ logger.info(f"Trying {strategy.value} strategy for replacement")
123
+ result = replacer.replace(content, search_blocks)
124
+
125
+ if result.success:
126
+ logger.info(f"Successfully replaced using {strategy.value} strategy")
127
+ result.metadata['used_strategy'] = strategy.value
128
+ result.metadata['fallback_used'] = len(fallback_strategies) > 1
129
+ return result
130
+ else:
131
+ logger.warning(f"Failed to replace using {strategy.value} strategy: {result.message}")
132
+ last_result = result
133
+
134
+ # 如果所有策略都失败了,返回最后一个结果
135
+ if last_result:
136
+ last_result.metadata['all_strategies_failed'] = True
137
+ last_result.metadata['tried_strategies'] = [s.value for s in fallback_strategies]
138
+ return last_result
139
+
140
+ return ReplaceResult(
141
+ success=False,
142
+ message="No suitable replacer found for the given content",
143
+ total_count=len(search_blocks)
144
+ )
145
+
146
+ def get_available_strategies(self) -> List[ReplaceStrategy]:
147
+ """
148
+ 获取所有可用的替换策略
149
+
150
+ Returns:
151
+ 可用的替换策略列表
152
+ """
153
+ return list(self.replacers.keys())
154
+
155
+ def set_default_strategy(self, strategy: ReplaceStrategy):
156
+ """
157
+ 设置默认替换策略
158
+
159
+ Args:
160
+ strategy: 新的默认策略
161
+ """
162
+ if strategy in self.replacers:
163
+ self.default_strategy = strategy
164
+ logger.info(f"Default strategy set to {strategy.value}")
165
+ else:
166
+ logger.warning(f"Strategy {strategy.value} not available, default strategy unchanged")
167
+
168
+ def configure_replacer(self, strategy: ReplaceStrategy, **kwargs):
169
+ """
170
+ 配置指定替换器的参数
171
+
172
+ Args:
173
+ strategy: 替换策略
174
+ **kwargs: 配置参数
175
+ """
176
+ replacer = self.get_replacer(strategy)
177
+ if not replacer:
178
+ logger.warning(f"Replacer for strategy '{strategy.value}' not available")
179
+ return
180
+
181
+ try:
182
+ if strategy == ReplaceStrategy.STRING and isinstance(replacer, StringReplacer):
183
+ if 'lenient_mode' in kwargs:
184
+ replacer.lenient_mode = kwargs['lenient_mode']
185
+ logger.info(f"StringReplacer lenient_mode set to {kwargs['lenient_mode']}")
186
+
187
+ elif strategy == ReplaceStrategy.PATCH and isinstance(replacer, PatchReplacer):
188
+ if 'use_patch_ng' in kwargs:
189
+ replacer.use_patch_ng = kwargs['use_patch_ng']
190
+ replacer._load_patch_module()
191
+ logger.info(f"PatchReplacer use_patch_ng set to {kwargs['use_patch_ng']}")
192
+
193
+ elif strategy == ReplaceStrategy.SIMILARITY and isinstance(replacer, SimilarityReplacer):
194
+ if 'similarity_threshold' in kwargs:
195
+ replacer.set_similarity_threshold(kwargs['similarity_threshold'])
196
+
197
+ except Exception as e:
198
+ logger.error(f"Failed to configure {strategy.value} replacer: {e}")
199
+
200
+ def get_replacer_info(self, strategy: ReplaceStrategy) -> Dict[str, Any]:
201
+ """
202
+ 获取替换器信息
203
+
204
+ Args:
205
+ strategy: 替换策略
206
+
207
+ Returns:
208
+ 替换器信息字典
209
+ """
210
+ replacer = self.get_replacer(strategy)
211
+ if not replacer:
212
+ return {'available': False, 'strategy': strategy.value}
213
+
214
+ info = {
215
+ 'available': True,
216
+ 'strategy': strategy.value,
217
+ 'class_name': replacer.__class__.__name__
218
+ }
219
+
220
+ # 添加特定替换器的信息
221
+ try:
222
+ if strategy == ReplaceStrategy.STRING and isinstance(replacer, StringReplacer):
223
+ info['lenient_mode'] = replacer.lenient_mode
224
+ elif strategy == ReplaceStrategy.PATCH and isinstance(replacer, PatchReplacer):
225
+ info['use_patch_ng'] = replacer.use_patch_ng
226
+ info['patch_module_available'] = replacer._patch_module is not None
227
+ elif strategy == ReplaceStrategy.SIMILARITY and isinstance(replacer, SimilarityReplacer):
228
+ info['similarity_threshold'] = replacer.similarity_threshold
229
+ except Exception as e:
230
+ logger.warning(f"Failed to get detailed info for {strategy.value}: {e}")
231
+
232
+ return info
233
+
234
+ def get_status(self) -> Dict[str, Any]:
235
+ """
236
+ 获取管理器状态
237
+
238
+ Returns:
239
+ 状态信息字典
240
+ """
241
+ return {
242
+ 'default_strategy': self.default_strategy.value,
243
+ 'available_strategies': [s.value for s in self.get_available_strategies()],
244
+ 'replacer_info': {
245
+ strategy.value: self.get_replacer_info(strategy)
246
+ for strategy in ReplaceStrategy
247
+ }
248
+ }
@@ -0,0 +1,304 @@
1
+ """
2
+ Patch-based text replacer implementation
3
+ """
4
+
5
+ import tempfile
6
+ import os
7
+ from typing import List, Tuple, Optional
8
+ from loguru import logger
9
+
10
+ from .base import BaseReplacer, ReplaceResult, ReplaceStrategy
11
+
12
+
13
+ class PatchReplacer(BaseReplacer):
14
+ """基于补丁库的文本替换器"""
15
+
16
+ def __init__(self, use_patch_ng: bool = True):
17
+ """
18
+ 初始化补丁替换器
19
+
20
+ Args:
21
+ use_patch_ng: 是否使用 patch-ng 库(True)还是 unidiff 库(False)
22
+ """
23
+ super().__init__(ReplaceStrategy.PATCH)
24
+ self.use_patch_ng = use_patch_ng
25
+ self._patch_module = None
26
+ self._load_patch_module()
27
+
28
+ def _load_patch_module(self):
29
+ """加载补丁模块"""
30
+ try:
31
+ if self.use_patch_ng:
32
+ try:
33
+ import patch_ng
34
+ self._patch_module = patch_ng
35
+ logger.info("Loaded patch-ng module")
36
+ except ImportError:
37
+ logger.warning("patch-ng not available, falling back to unidiff")
38
+ self.use_patch_ng = False
39
+
40
+ if not self.use_patch_ng:
41
+ try:
42
+ import unidiff
43
+ self._patch_module = unidiff
44
+ logger.info("Loaded unidiff module")
45
+ except ImportError:
46
+ logger.error("Neither patch-ng nor unidiff is available")
47
+ self._patch_module = None
48
+
49
+ except Exception as e:
50
+ logger.error(f"Failed to load patch module: {e}")
51
+ self._patch_module = None
52
+
53
+ def _search_blocks_to_unified_diff(self, search_blocks: List[Tuple[str, str]],
54
+ filename: str = "file.txt") -> str:
55
+ """
56
+ 将搜索替换块转换为统一差异格式
57
+
58
+ Args:
59
+ search_blocks: 搜索替换块列表
60
+ filename: 文件名(用于生成diff头)
61
+
62
+ Returns:
63
+ 统一差异格式的字符串
64
+ """
65
+ # 为了简化,我们假设每个搜索块都是完整的替换
66
+ # 实际应用中可能需要更复杂的逻辑来生成正确的unified diff
67
+
68
+ diff_lines = []
69
+ diff_lines.append(f"--- a/{filename}")
70
+ diff_lines.append(f"+++ b/{filename}")
71
+
72
+ for i, (search_text, replace_text) in enumerate(search_blocks):
73
+ search_lines = search_text.splitlines()
74
+ replace_lines = replace_text.splitlines()
75
+
76
+ # 生成hunk头
77
+ diff_lines.append(f"@@ -{i+1},{len(search_lines)} +{i+1},{len(replace_lines)} @@")
78
+
79
+ # 添加删除行
80
+ for line in search_lines:
81
+ diff_lines.append(f"-{line}")
82
+
83
+ # 添加添加行
84
+ for line in replace_lines:
85
+ diff_lines.append(f"+{line}")
86
+
87
+ return "\n".join(diff_lines) + "\n"
88
+
89
+ def _apply_patch_ng(self, content: str, diff_content: str, filename: str) -> Optional[str]:
90
+ """
91
+ 使用 patch-ng 应用补丁
92
+
93
+ Args:
94
+ content: 原始内容
95
+ diff_content: 差异内容
96
+ filename: 文件名
97
+
98
+ Returns:
99
+ 应用补丁后的内容,失败时返回 None
100
+ """
101
+ try:
102
+ patchset = self._patch_module.PatchSet.from_string(diff_content)
103
+
104
+ # 创建临时文件
105
+ with tempfile.NamedTemporaryFile(mode='w', delete=False, suffix='.txt') as f:
106
+ f.write(content)
107
+ temp_file = f.name
108
+
109
+ try:
110
+ # 应用补丁
111
+ if patchset.apply(root=os.path.dirname(temp_file)):
112
+ with open(temp_file, 'r', encoding='utf-8') as f:
113
+ return f.read()
114
+ else:
115
+ logger.error("Failed to apply patch using patch-ng")
116
+ return None
117
+ finally:
118
+ # 清理临时文件
119
+ if os.path.exists(temp_file):
120
+ os.unlink(temp_file)
121
+
122
+ except Exception as e:
123
+ logger.error(f"Error applying patch with patch-ng: {e}")
124
+ return None
125
+
126
+ def _apply_unidiff(self, content: str, diff_content: str, filename: str) -> Optional[str]:
127
+ """
128
+ 使用 unidiff 应用补丁
129
+
130
+ Args:
131
+ content: 原始内容
132
+ diff_content: 差异内容
133
+ filename: 文件名
134
+
135
+ Returns:
136
+ 应用补丁后的内容,失败时返回 None
137
+ """
138
+ try:
139
+ patchset = self._patch_module.PatchSet(diff_content)
140
+
141
+ if not patchset:
142
+ logger.error("No patches found in diff content")
143
+ return None
144
+
145
+ # 取第一个补丁文件
146
+ patch_file = patchset[0]
147
+
148
+ # 将内容分割为行
149
+ lines = content.splitlines(keepends=True)
150
+
151
+ # 应用补丁
152
+ try:
153
+ new_lines = self._apply_patch_to_lines(lines, patch_file)
154
+ return ''.join(new_lines)
155
+ except Exception as e:
156
+ logger.error(f"Error applying patch to lines: {e}")
157
+ return None
158
+
159
+ except Exception as e:
160
+ logger.error(f"Error applying patch with unidiff: {e}")
161
+ return None
162
+
163
+ def _apply_patch_to_lines(self, lines: List[str], patch_file) -> List[str]:
164
+ """
165
+ 将补丁应用到行列表
166
+
167
+ Args:
168
+ lines: 原始行列表
169
+ patch_file: 补丁文件对象
170
+
171
+ Returns:
172
+ 应用补丁后的行列表
173
+ """
174
+ new_lines = lines.copy()
175
+
176
+ # 按照行号倒序处理hunks,避免行号偏移问题
177
+ for hunk in reversed(patch_file):
178
+ target_line = hunk.target_start - 1 # 转换为0索引
179
+
180
+ # 删除旧行
181
+ lines_to_remove = [line for line in hunk if line.is_removed]
182
+ for _ in lines_to_remove:
183
+ if target_line < len(new_lines):
184
+ new_lines.pop(target_line)
185
+
186
+ # 添加新行
187
+ lines_to_add = [line.value for line in hunk if line.is_added]
188
+ for i, line_value in enumerate(lines_to_add):
189
+ new_lines.insert(target_line + i, line_value)
190
+
191
+ return new_lines
192
+
193
+ def replace(self, content: str, search_blocks: List[Tuple[str, str]]) -> ReplaceResult:
194
+ """
195
+ 执行基于补丁的替换
196
+
197
+ Args:
198
+ content: 原始文件内容
199
+ search_blocks: 搜索替换块列表
200
+
201
+ Returns:
202
+ ReplaceResult: 替换结果
203
+ """
204
+ if not self._patch_module:
205
+ return ReplaceResult(
206
+ success=False,
207
+ message="No patch module available. Please install patch-ng or unidiff",
208
+ total_count=len(search_blocks)
209
+ )
210
+
211
+ if not self.validate_search_blocks(search_blocks):
212
+ return ReplaceResult(
213
+ success=False,
214
+ message="Invalid search blocks provided",
215
+ total_count=len(search_blocks)
216
+ )
217
+
218
+ try:
219
+ # 检查是否有插入操作
220
+ insert_blocks = [(i, replace_text) for i, (search_text, replace_text) in enumerate(search_blocks) if search_text == ""]
221
+ regular_blocks = [(search_text, replace_text) for search_text, replace_text in search_blocks if search_text != ""]
222
+
223
+ current_content = content
224
+ applied_count = 0
225
+
226
+ # 先处理插入操作
227
+ for i, insert_text in insert_blocks:
228
+ # 插入到文件开头
229
+ if not insert_text.endswith(("\n", "\r\n")):
230
+ insert_text += "\n"
231
+
232
+ current_content = insert_text + current_content
233
+ applied_count += 1
234
+ logger.info(f"Patch replacer inserted block {i+1}/{len(search_blocks)} at file head")
235
+
236
+ # 如果没有常规替换块,直接返回插入结果
237
+ if not regular_blocks:
238
+ return ReplaceResult(
239
+ success=True,
240
+ message=f"Successfully inserted {applied_count} blocks at file head",
241
+ new_content=current_content,
242
+ applied_count=applied_count,
243
+ total_count=len(search_blocks),
244
+ metadata={
245
+ 'strategy': self.get_strategy_name(),
246
+ 'patch_module': 'patch-ng' if self.use_patch_ng else 'unidiff'
247
+ }
248
+ )
249
+
250
+ # 处理常规替换块
251
+ # 将搜索替换块转换为统一差异格式
252
+ diff_content = self._search_blocks_to_unified_diff(regular_blocks)
253
+ logger.debug(f"Generated diff content:\n{diff_content}")
254
+
255
+ # 应用补丁
256
+ if self.use_patch_ng:
257
+ new_content = self._apply_patch_ng(current_content, diff_content, "file.txt")
258
+ else:
259
+ new_content = self._apply_unidiff(current_content, diff_content, "file.txt")
260
+
261
+ if new_content is not None:
262
+ return ReplaceResult(
263
+ success=True,
264
+ message=f"Successfully applied patch with {len(regular_blocks)} blocks and {len(insert_blocks)} inserts",
265
+ new_content=new_content,
266
+ applied_count=applied_count + len(regular_blocks),
267
+ total_count=len(search_blocks),
268
+ metadata={
269
+ 'strategy': self.get_strategy_name(),
270
+ 'patch_module': 'patch-ng' if self.use_patch_ng else 'unidiff'
271
+ }
272
+ )
273
+ else:
274
+ return ReplaceResult(
275
+ success=applied_count > 0,
276
+ message=f"Failed to apply patch for regular blocks, but {applied_count} inserts succeeded",
277
+ new_content=current_content if applied_count > 0 else None,
278
+ applied_count=applied_count,
279
+ total_count=len(search_blocks),
280
+ errors=["Patch application failed for regular blocks"]
281
+ )
282
+
283
+ except Exception as e:
284
+ logger.error(f"Error in patch replacement: {e}")
285
+ return ReplaceResult(
286
+ success=False,
287
+ message=f"Error in patch replacement: {str(e)}",
288
+ total_count=len(search_blocks),
289
+ errors=[str(e)]
290
+ )
291
+
292
+ def can_handle(self, content: str, search_blocks: List[Tuple[str, str]]) -> bool:
293
+ """
294
+ 检查是否能处理给定的内容和搜索块
295
+
296
+ Args:
297
+ content: 原始文件内容
298
+ search_blocks: 搜索替换块列表
299
+
300
+ Returns:
301
+ bool: 是否能处理
302
+ """
303
+ return (self._patch_module is not None and
304
+ self.validate_search_blocks(search_blocks))