auto-coder 1.0.0__py3-none-any.whl → 2.0.1__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 (574) hide show
  1. auto_coder-2.0.1.dist-info/LICENSE +158 -0
  2. auto_coder-2.0.1.dist-info/METADATA +558 -0
  3. auto_coder-2.0.1.dist-info/RECORD +795 -0
  4. {auto_coder-1.0.0.dist-info → auto_coder-2.0.1.dist-info}/WHEEL +1 -1
  5. {auto_coder-1.0.0.dist-info → auto_coder-2.0.1.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 +24 -3
  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 +77 -73
  19. autocoder/auto_coder.py +31 -40
  20. autocoder/auto_coder_rag.py +11 -1084
  21. autocoder/auto_coder_runner.py +962 -2345
  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 +988 -398
  28. autocoder/chat_auto_coder_lang.py +23 -732
  29. autocoder/commands/auto_command.py +25 -8
  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 +409 -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/git_utils.py +44 -8
  119. autocoder/common/global_cancel.py +15 -6
  120. autocoder/common/ignorefiles/test_ignore_file_utils.py +1 -1
  121. autocoder/common/international/__init__.py +31 -0
  122. autocoder/common/international/demo_international.py +92 -0
  123. autocoder/common/international/message_manager.py +157 -0
  124. autocoder/common/international/messages/__init__.py +56 -0
  125. autocoder/common/international/messages/async_command_messages.py +507 -0
  126. autocoder/common/international/messages/auto_coder_messages.py +2208 -0
  127. autocoder/common/international/messages/chat_auto_coder_messages.py +1547 -0
  128. autocoder/common/international/messages/command_help_messages.py +986 -0
  129. autocoder/common/international/messages/conversation_command_messages.py +191 -0
  130. autocoder/common/international/messages/git_helper_plugin_messages.py +159 -0
  131. autocoder/common/international/messages/queue_command_messages.py +751 -0
  132. autocoder/common/international/messages/rules_command_messages.py +77 -0
  133. autocoder/common/international/messages/sdk_messages.py +1707 -0
  134. autocoder/common/international/messages/token_helper_plugin_messages.py +361 -0
  135. autocoder/common/international/messages/tool_display_messages.py +1212 -0
  136. autocoder/common/international/messages/workflow_exception_messages.py +473 -0
  137. autocoder/common/international/test_international.py +612 -0
  138. autocoder/common/linter_core/__init__.py +28 -0
  139. autocoder/common/linter_core/base_linter.py +61 -0
  140. autocoder/common/linter_core/config_loader.py +271 -0
  141. autocoder/common/linter_core/formatters/__init__.py +0 -0
  142. autocoder/common/linter_core/formatters/base_formatter.py +38 -0
  143. autocoder/common/linter_core/formatters/raw_formatter.py +17 -0
  144. autocoder/common/linter_core/linter.py +166 -0
  145. autocoder/common/linter_core/linter_factory.py +216 -0
  146. autocoder/common/linter_core/linter_manager.py +333 -0
  147. autocoder/common/linter_core/linters/__init__.py +9 -0
  148. autocoder/common/linter_core/linters/java_linter.py +342 -0
  149. autocoder/common/linter_core/linters/python_linter.py +115 -0
  150. autocoder/common/linter_core/linters/typescript_linter.py +119 -0
  151. autocoder/common/linter_core/models/__init__.py +7 -0
  152. autocoder/common/linter_core/models/lint_result.py +91 -0
  153. autocoder/common/linter_core/models.py +33 -0
  154. autocoder/common/linter_core/tests/__init__.py +3 -0
  155. autocoder/common/linter_core/tests/test_config_loader.py +323 -0
  156. autocoder/common/linter_core/tests/test_config_loading.py +308 -0
  157. autocoder/common/linter_core/tests/test_factory_manager.py +234 -0
  158. autocoder/common/linter_core/tests/test_formatters.py +147 -0
  159. autocoder/common/linter_core/tests/test_integration.py +317 -0
  160. autocoder/common/linter_core/tests/test_java_linter.py +496 -0
  161. autocoder/common/linter_core/tests/test_linters.py +265 -0
  162. autocoder/common/linter_core/tests/test_models.py +81 -0
  163. autocoder/common/linter_core/tests/verify_config_loading.py +296 -0
  164. autocoder/common/linter_core/tests/verify_fixes.py +183 -0
  165. autocoder/common/llm_friendly_package/__init__.py +31 -0
  166. autocoder/common/llm_friendly_package/base_manager.py +102 -0
  167. autocoder/common/llm_friendly_package/docs_manager.py +121 -0
  168. autocoder/common/llm_friendly_package/library_manager.py +171 -0
  169. autocoder/common/{llm_friendly_package.py → llm_friendly_package/main_manager.py} +204 -231
  170. autocoder/common/llm_friendly_package/models.py +40 -0
  171. autocoder/common/llm_friendly_package/test_llm_friendly_package.py +536 -0
  172. autocoder/common/llms/__init__.py +15 -0
  173. autocoder/common/llms/demo_error_handling.py +85 -0
  174. autocoder/common/llms/factory.py +142 -0
  175. autocoder/common/llms/manager.py +264 -0
  176. autocoder/common/llms/pricing.py +121 -0
  177. autocoder/common/llms/registry.py +316 -0
  178. autocoder/common/llms/schema.py +77 -0
  179. autocoder/common/llms/simple_demo.py +45 -0
  180. autocoder/common/llms/test_quick_model.py +116 -0
  181. autocoder/common/llms/test_remove_functionality.py +182 -0
  182. autocoder/common/llms/tests/__init__.py +1 -0
  183. autocoder/common/llms/tests/test_manager.py +330 -0
  184. autocoder/common/llms/tests/test_registry.py +364 -0
  185. autocoder/common/mcp_tools/__init__.py +62 -0
  186. autocoder/common/{mcp_tools.py → mcp_tools/executor.py} +49 -40
  187. autocoder/common/{mcp_hub.py → mcp_tools/hub.py} +42 -68
  188. autocoder/common/{mcp_server_install.py → mcp_tools/installer.py} +16 -28
  189. autocoder/common/{mcp_server.py → mcp_tools/server.py} +176 -48
  190. autocoder/common/mcp_tools/test_keyboard_interrupt.py +93 -0
  191. autocoder/common/mcp_tools/test_mcp_tools.py +391 -0
  192. autocoder/common/{mcp_server_types.py → mcp_tools/types.py} +121 -48
  193. autocoder/common/mcp_tools/verify_functionality.py +202 -0
  194. autocoder/common/model_speed_tester.py +32 -26
  195. autocoder/common/priority_directory_finder/__init__.py +142 -0
  196. autocoder/common/priority_directory_finder/examples.py +230 -0
  197. autocoder/common/priority_directory_finder/finder.py +283 -0
  198. autocoder/common/priority_directory_finder/models.py +236 -0
  199. autocoder/common/priority_directory_finder/test_priority_directory_finder.py +431 -0
  200. autocoder/common/project_scanner/__init__.py +18 -0
  201. autocoder/common/project_scanner/compat.py +77 -0
  202. autocoder/common/project_scanner/scanner.py +436 -0
  203. autocoder/common/project_tracker/__init__.py +27 -0
  204. autocoder/common/project_tracker/api.py +228 -0
  205. autocoder/common/project_tracker/demo.py +272 -0
  206. autocoder/common/project_tracker/tracker.py +487 -0
  207. autocoder/common/project_tracker/types.py +53 -0
  208. autocoder/common/pruner/__init__.py +67 -0
  209. autocoder/common/pruner/agentic_conversation_pruner.py +651 -102
  210. autocoder/common/pruner/conversation_message_ids_api.py +386 -0
  211. autocoder/common/pruner/conversation_message_ids_manager.py +347 -0
  212. autocoder/common/pruner/conversation_message_ids_pruner.py +473 -0
  213. autocoder/common/pruner/conversation_normalizer.py +347 -0
  214. autocoder/common/pruner/conversation_pruner.py +26 -6
  215. autocoder/common/pruner/test_agentic_conversation_pruner.py +554 -112
  216. autocoder/common/pruner/test_conversation_normalizer.py +502 -0
  217. autocoder/common/pruner/test_tool_content_detector.py +324 -0
  218. autocoder/common/pruner/tool_content_detector.py +227 -0
  219. autocoder/common/pruner/tools/__init__.py +18 -0
  220. autocoder/common/pruner/tools/query_message_ids.py +264 -0
  221. autocoder/common/pruner/tools/test_agentic_pruning_logic.py +432 -0
  222. autocoder/common/pruner/tools/test_message_ids_pruning_only.py +192 -0
  223. autocoder/common/pull_requests/__init__.py +9 -1
  224. autocoder/common/pull_requests/utils.py +122 -1
  225. autocoder/common/rag_manager/rag_manager.py +36 -40
  226. autocoder/common/rulefiles/__init__.py +53 -1
  227. autocoder/common/rulefiles/api.py +250 -0
  228. autocoder/common/rulefiles/core/__init__.py +14 -0
  229. autocoder/common/rulefiles/core/manager.py +241 -0
  230. autocoder/common/rulefiles/core/selector.py +805 -0
  231. autocoder/common/rulefiles/models/__init__.py +20 -0
  232. autocoder/common/rulefiles/models/index.py +16 -0
  233. autocoder/common/rulefiles/models/init_rule.py +18 -0
  234. autocoder/common/rulefiles/models/rule_file.py +18 -0
  235. autocoder/common/rulefiles/models/rule_relevance.py +14 -0
  236. autocoder/common/rulefiles/models/summary.py +16 -0
  237. autocoder/common/rulefiles/test_rulefiles.py +776 -0
  238. autocoder/common/rulefiles/utils/__init__.py +34 -0
  239. autocoder/common/rulefiles/utils/monitor.py +86 -0
  240. autocoder/common/rulefiles/utils/parser.py +230 -0
  241. autocoder/common/save_formatted_log.py +67 -10
  242. autocoder/common/search_replace.py +8 -1
  243. autocoder/common/search_replace_patch/__init__.py +24 -0
  244. autocoder/common/search_replace_patch/base.py +115 -0
  245. autocoder/common/search_replace_patch/manager.py +248 -0
  246. autocoder/common/search_replace_patch/patch_replacer.py +304 -0
  247. autocoder/common/search_replace_patch/similarity_replacer.py +306 -0
  248. autocoder/common/search_replace_patch/string_replacer.py +181 -0
  249. autocoder/common/search_replace_patch/tests/__init__.py +3 -0
  250. autocoder/common/search_replace_patch/tests/run_tests.py +126 -0
  251. autocoder/common/search_replace_patch/tests/test_base.py +188 -0
  252. autocoder/common/search_replace_patch/tests/test_empty_line_insert.py +233 -0
  253. autocoder/common/search_replace_patch/tests/test_integration.py +389 -0
  254. autocoder/common/search_replace_patch/tests/test_manager.py +351 -0
  255. autocoder/common/search_replace_patch/tests/test_patch_replacer.py +316 -0
  256. autocoder/common/search_replace_patch/tests/test_regex_replacer.py +306 -0
  257. autocoder/common/search_replace_patch/tests/test_similarity_replacer.py +384 -0
  258. autocoder/common/shell_commands/__init__.py +197 -0
  259. autocoder/common/shell_commands/background_process_notifier.py +346 -0
  260. autocoder/common/shell_commands/command_executor.py +1127 -0
  261. autocoder/common/shell_commands/error_recovery.py +541 -0
  262. autocoder/common/shell_commands/exceptions.py +120 -0
  263. autocoder/common/shell_commands/interactive_executor.py +476 -0
  264. autocoder/common/shell_commands/interactive_pexpect_process.py +623 -0
  265. autocoder/common/shell_commands/interactive_process.py +744 -0
  266. autocoder/common/shell_commands/interactive_session_manager.py +1014 -0
  267. autocoder/common/shell_commands/monitoring.py +529 -0
  268. autocoder/common/shell_commands/process_cleanup.py +386 -0
  269. autocoder/common/shell_commands/process_manager.py +606 -0
  270. autocoder/common/shell_commands/test_interactive_pexpect_process.py +281 -0
  271. autocoder/common/shell_commands/tests/__init__.py +6 -0
  272. autocoder/common/shell_commands/tests/conftest.py +118 -0
  273. autocoder/common/shell_commands/tests/test_background_process_notifier.py +703 -0
  274. autocoder/common/shell_commands/tests/test_command_executor.py +448 -0
  275. autocoder/common/shell_commands/tests/test_error_recovery.py +305 -0
  276. autocoder/common/shell_commands/tests/test_exceptions.py +299 -0
  277. autocoder/common/shell_commands/tests/test_execute_batch.py +588 -0
  278. autocoder/common/shell_commands/tests/test_indented_batch_commands.py +244 -0
  279. autocoder/common/shell_commands/tests/test_integration.py +664 -0
  280. autocoder/common/shell_commands/tests/test_monitoring.py +546 -0
  281. autocoder/common/shell_commands/tests/test_performance.py +632 -0
  282. autocoder/common/shell_commands/tests/test_process_cleanup.py +397 -0
  283. autocoder/common/shell_commands/tests/test_process_manager.py +606 -0
  284. autocoder/common/shell_commands/tests/test_timeout_config.py +343 -0
  285. autocoder/common/shell_commands/tests/test_timeout_manager.py +520 -0
  286. autocoder/common/shell_commands/timeout_config.py +315 -0
  287. autocoder/common/shell_commands/timeout_manager.py +352 -0
  288. autocoder/common/terminal_paste/__init__.py +14 -0
  289. autocoder/common/terminal_paste/demo.py +145 -0
  290. autocoder/common/terminal_paste/demo_paste_functionality.py +95 -0
  291. autocoder/common/terminal_paste/paste_handler.py +200 -0
  292. autocoder/common/terminal_paste/paste_manager.py +118 -0
  293. autocoder/common/terminal_paste/tests/__init__.py +1 -0
  294. autocoder/common/terminal_paste/tests/test_paste_handler.py +182 -0
  295. autocoder/common/terminal_paste/tests/test_paste_manager.py +126 -0
  296. autocoder/common/terminal_paste/utils.py +163 -0
  297. autocoder/common/test_autocoder_args.py +232 -0
  298. autocoder/common/test_env_manager.py +173 -0
  299. autocoder/common/test_env_manager_integration.py +159 -0
  300. autocoder/common/text_similarity/__init__.py +9 -0
  301. autocoder/common/text_similarity/demo.py +216 -0
  302. autocoder/common/text_similarity/examples.py +266 -0
  303. autocoder/common/text_similarity/test_text_similarity.py +306 -0
  304. autocoder/common/text_similarity/text_similarity.py +194 -0
  305. autocoder/common/text_similarity/utils.py +125 -0
  306. autocoder/common/todos/__init__.py +61 -0
  307. autocoder/common/todos/cache/__init__.py +16 -0
  308. autocoder/common/todos/cache/base_cache.py +89 -0
  309. autocoder/common/todos/cache/cache_manager.py +228 -0
  310. autocoder/common/todos/cache/memory_cache.py +225 -0
  311. autocoder/common/todos/config.py +155 -0
  312. autocoder/common/todos/exceptions.py +35 -0
  313. autocoder/common/todos/get_todo_manager.py +161 -0
  314. autocoder/common/todos/manager.py +537 -0
  315. autocoder/common/todos/models.py +239 -0
  316. autocoder/common/todos/storage/__init__.py +14 -0
  317. autocoder/common/todos/storage/base_storage.py +76 -0
  318. autocoder/common/todos/storage/file_storage.py +278 -0
  319. autocoder/common/tokens/counter.py +24 -2
  320. autocoder/common/tools_manager/__init__.py +17 -0
  321. autocoder/common/tools_manager/examples.py +162 -0
  322. autocoder/common/tools_manager/manager.py +385 -0
  323. autocoder/common/tools_manager/models.py +39 -0
  324. autocoder/common/tools_manager/test_tools_manager.py +303 -0
  325. autocoder/common/tools_manager/utils.py +191 -0
  326. autocoder/common/v2/agent/agentic_callbacks.py +270 -0
  327. autocoder/common/v2/agent/agentic_edit.py +2699 -1856
  328. autocoder/common/v2/agent/agentic_edit_change_manager.py +474 -0
  329. autocoder/common/v2/agent/agentic_edit_tools/__init__.py +35 -1
  330. autocoder/common/v2/agent/agentic_edit_tools/ac_mod_list_tool_resolver.py +279 -0
  331. autocoder/common/v2/agent/agentic_edit_tools/ac_mod_write_tool_resolver.py +10 -1
  332. autocoder/common/v2/agent/agentic_edit_tools/background_task_tool_resolver.py +1167 -0
  333. autocoder/common/v2/agent/agentic_edit_tools/base_tool_resolver.py +2 -2
  334. autocoder/common/v2/agent/agentic_edit_tools/conversation_message_ids_read_tool_resolver.py +214 -0
  335. autocoder/common/v2/agent/agentic_edit_tools/conversation_message_ids_write_tool_resolver.py +299 -0
  336. autocoder/common/v2/agent/agentic_edit_tools/count_tokens_tool_resolver.py +290 -0
  337. autocoder/common/v2/agent/agentic_edit_tools/execute_command_tool_resolver.py +564 -29
  338. autocoder/common/v2/agent/agentic_edit_tools/execute_workflow_tool_resolver.py +485 -0
  339. autocoder/common/v2/agent/agentic_edit_tools/extract_to_text_tool_resolver.py +225 -0
  340. autocoder/common/v2/agent/agentic_edit_tools/lint_report.py +79 -0
  341. autocoder/common/v2/agent/agentic_edit_tools/linter_config_models.py +343 -0
  342. autocoder/common/v2/agent/agentic_edit_tools/linter_enabled_tool_resolver.py +189 -0
  343. autocoder/common/v2/agent/agentic_edit_tools/list_files_tool_resolver.py +169 -101
  344. autocoder/common/v2/agent/agentic_edit_tools/load_extra_document_tool_resolver.py +356 -0
  345. autocoder/common/v2/agent/agentic_edit_tools/read_file_tool_resolver.py +243 -50
  346. autocoder/common/v2/agent/agentic_edit_tools/replace_in_file_tool_resolver.py +667 -147
  347. autocoder/common/v2/agent/agentic_edit_tools/run_named_subagents_tool_resolver.py +691 -0
  348. autocoder/common/v2/agent/agentic_edit_tools/search_files_tool_resolver.py +410 -86
  349. autocoder/common/v2/agent/agentic_edit_tools/session_interactive_tool_resolver.py +115 -0
  350. autocoder/common/v2/agent/agentic_edit_tools/session_start_tool_resolver.py +190 -0
  351. autocoder/common/v2/agent/agentic_edit_tools/session_stop_tool_resolver.py +76 -0
  352. autocoder/common/v2/agent/agentic_edit_tools/test_write_to_file_tool_resolver.py +207 -192
  353. autocoder/common/v2/agent/agentic_edit_tools/todo_read_tool_resolver.py +80 -63
  354. autocoder/common/v2/agent/agentic_edit_tools/todo_write_tool_resolver.py +237 -233
  355. autocoder/common/v2/agent/agentic_edit_tools/use_mcp_tool_resolver.py +2 -2
  356. autocoder/common/v2/agent/agentic_edit_tools/web_crawl_tool_resolver.py +557 -0
  357. autocoder/common/v2/agent/agentic_edit_tools/web_search_tool_resolver.py +600 -0
  358. autocoder/common/v2/agent/agentic_edit_tools/write_to_file_tool_resolver.py +56 -121
  359. autocoder/common/v2/agent/agentic_edit_types.py +343 -9
  360. autocoder/common/v2/agent/runner/__init__.py +3 -3
  361. autocoder/common/v2/agent/runner/base_runner.py +12 -26
  362. autocoder/common/v2/agent/runner/{event_runner.py → file_based_event_runner.py} +3 -2
  363. autocoder/common/v2/agent/runner/sdk_runner.py +150 -8
  364. autocoder/common/v2/agent/runner/terminal_runner.py +170 -57
  365. autocoder/common/v2/agent/runner/tool_display.py +557 -159
  366. autocoder/common/v2/agent/test_agentic_callbacks.py +265 -0
  367. autocoder/common/v2/agent/test_agentic_edit.py +194 -0
  368. autocoder/common/v2/agent/tool_caller/__init__.py +24 -0
  369. autocoder/common/v2/agent/tool_caller/default_tool_resolver_map.py +135 -0
  370. autocoder/common/v2/agent/tool_caller/integration_test.py +172 -0
  371. autocoder/common/v2/agent/tool_caller/plugins/__init__.py +14 -0
  372. autocoder/common/v2/agent/tool_caller/plugins/base_plugin.py +126 -0
  373. autocoder/common/v2/agent/tool_caller/plugins/examples/__init__.py +13 -0
  374. autocoder/common/v2/agent/tool_caller/plugins/examples/logging_plugin.py +164 -0
  375. autocoder/common/v2/agent/tool_caller/plugins/examples/security_filter_plugin.py +198 -0
  376. autocoder/common/v2/agent/tool_caller/plugins/plugin_interface.py +141 -0
  377. autocoder/common/v2/agent/tool_caller/test_tool_caller.py +278 -0
  378. autocoder/common/v2/agent/tool_caller/tool_call_plugin_manager.py +331 -0
  379. autocoder/common/v2/agent/tool_caller/tool_caller.py +337 -0
  380. autocoder/common/v2/agent/tool_caller/usage_example.py +193 -0
  381. autocoder/common/v2/code_agentic_editblock_manager.py +4 -4
  382. autocoder/common/v2/code_auto_generate.py +136 -78
  383. autocoder/common/v2/code_auto_generate_diff.py +135 -79
  384. autocoder/common/v2/code_auto_generate_editblock.py +174 -99
  385. autocoder/common/v2/code_auto_generate_strict_diff.py +151 -71
  386. autocoder/common/v2/code_auto_merge.py +1 -1
  387. autocoder/common/v2/code_auto_merge_editblock.py +13 -1
  388. autocoder/common/v2/code_diff_manager.py +3 -3
  389. autocoder/common/v2/code_editblock_manager.py +4 -14
  390. autocoder/common/v2/code_manager.py +1 -1
  391. autocoder/common/v2/code_strict_diff_manager.py +2 -2
  392. autocoder/common/wrap_llm_hint/__init__.py +10 -0
  393. autocoder/common/wrap_llm_hint/test_wrap_llm_hint.py +1067 -0
  394. autocoder/common/wrap_llm_hint/utils.py +432 -0
  395. autocoder/common/wrap_llm_hint/wrap_llm_hint.py +323 -0
  396. autocoder/completer/__init__.py +8 -0
  397. autocoder/completer/command_completer_v2.py +1094 -0
  398. autocoder/default_project/__init__.py +501 -0
  399. autocoder/dispacher/__init__.py +4 -12
  400. autocoder/dispacher/actions/action.py +400 -129
  401. autocoder/dispacher/actions/plugins/action_regex_project.py +2 -2
  402. autocoder/index/entry.py +117 -125
  403. autocoder/{agent → index/filter}/agentic_filter.py +322 -333
  404. autocoder/index/filter/normal_filter.py +5 -11
  405. autocoder/index/filter/quick_filter.py +1 -1
  406. autocoder/index/index.py +36 -9
  407. autocoder/index/tests/__init__.py +1 -0
  408. autocoder/index/tests/run_tests.py +195 -0
  409. autocoder/index/tests/test_entry.py +303 -0
  410. autocoder/index/tests/test_index_manager.py +314 -0
  411. autocoder/index/tests/test_module_integration.py +300 -0
  412. autocoder/index/tests/test_symbols_utils.py +183 -0
  413. autocoder/inner/__init__.py +4 -0
  414. autocoder/inner/agentic.py +923 -0
  415. autocoder/inner/async_command_handler.py +992 -0
  416. autocoder/inner/conversation_command_handlers.py +623 -0
  417. autocoder/inner/merge_command_handler.py +213 -0
  418. autocoder/inner/queue_command_handler.py +684 -0
  419. autocoder/models.py +95 -266
  420. autocoder/plugins/git_helper_plugin.py +31 -29
  421. autocoder/plugins/token_helper_plugin.py +65 -46
  422. autocoder/pyproject/__init__.py +32 -29
  423. autocoder/rag/agentic_rag.py +215 -75
  424. autocoder/rag/cache/simple_cache.py +1 -2
  425. autocoder/rag/loaders/image_loader.py +1 -1
  426. autocoder/rag/long_context_rag.py +42 -26
  427. autocoder/rag/qa_conversation_strategy.py +1 -1
  428. autocoder/rag/terminal/__init__.py +17 -0
  429. autocoder/rag/terminal/args.py +581 -0
  430. autocoder/rag/terminal/bootstrap.py +61 -0
  431. autocoder/rag/terminal/command_handlers.py +653 -0
  432. autocoder/rag/terminal/formatters/__init__.py +20 -0
  433. autocoder/rag/terminal/formatters/base.py +70 -0
  434. autocoder/rag/terminal/formatters/json_format.py +66 -0
  435. autocoder/rag/terminal/formatters/stream_json.py +95 -0
  436. autocoder/rag/terminal/formatters/text.py +28 -0
  437. autocoder/rag/terminal/init.py +120 -0
  438. autocoder/rag/terminal/utils.py +106 -0
  439. autocoder/rag/test_agentic_rag.py +389 -0
  440. autocoder/rag/test_doc_filter.py +3 -3
  441. autocoder/rag/test_long_context_rag.py +1 -1
  442. autocoder/rag/test_token_limiter.py +517 -10
  443. autocoder/rag/token_counter.py +3 -0
  444. autocoder/rag/token_limiter.py +19 -15
  445. autocoder/rag/tools/__init__.py +26 -2
  446. autocoder/rag/tools/bochaai_example.py +343 -0
  447. autocoder/rag/tools/bochaai_sdk.py +541 -0
  448. autocoder/rag/tools/metaso_example.py +268 -0
  449. autocoder/rag/tools/metaso_sdk.py +417 -0
  450. autocoder/rag/tools/recall_tool.py +28 -7
  451. autocoder/rag/tools/run_integration_tests.py +204 -0
  452. autocoder/rag/tools/test_all_providers.py +318 -0
  453. autocoder/rag/tools/test_bochaai_integration.py +482 -0
  454. autocoder/rag/tools/test_final_integration.py +215 -0
  455. autocoder/rag/tools/test_metaso_integration.py +424 -0
  456. autocoder/rag/tools/test_metaso_real.py +171 -0
  457. autocoder/rag/tools/test_web_crawl_tool.py +639 -0
  458. autocoder/rag/tools/test_web_search_tool.py +509 -0
  459. autocoder/rag/tools/todo_read_tool.py +202 -0
  460. autocoder/rag/tools/todo_write_tool.py +412 -0
  461. autocoder/rag/tools/web_crawl_tool.py +634 -0
  462. autocoder/rag/tools/web_search_tool.py +558 -0
  463. autocoder/rag/tools/web_tools_example.py +119 -0
  464. autocoder/rag/types.py +16 -0
  465. autocoder/rag/variable_holder.py +4 -2
  466. autocoder/rags.py +86 -79
  467. autocoder/regexproject/__init__.py +23 -21
  468. autocoder/sdk/__init__.py +46 -190
  469. autocoder/sdk/api.py +370 -0
  470. autocoder/sdk/async_runner/__init__.py +26 -0
  471. autocoder/sdk/async_runner/async_executor.py +650 -0
  472. autocoder/sdk/async_runner/async_handler.py +356 -0
  473. autocoder/sdk/async_runner/markdown_processor.py +595 -0
  474. autocoder/sdk/async_runner/task_metadata.py +284 -0
  475. autocoder/sdk/async_runner/worktree_manager.py +438 -0
  476. autocoder/sdk/cli/__init__.py +2 -5
  477. autocoder/sdk/cli/formatters.py +28 -204
  478. autocoder/sdk/cli/handlers.py +77 -44
  479. autocoder/sdk/cli/main.py +154 -171
  480. autocoder/sdk/cli/options.py +95 -22
  481. autocoder/sdk/constants.py +139 -51
  482. autocoder/sdk/core/auto_coder_core.py +484 -109
  483. autocoder/sdk/core/bridge.py +297 -115
  484. autocoder/sdk/exceptions.py +18 -12
  485. autocoder/sdk/formatters/__init__.py +19 -0
  486. autocoder/sdk/formatters/input.py +64 -0
  487. autocoder/sdk/formatters/output.py +247 -0
  488. autocoder/sdk/formatters/stream.py +54 -0
  489. autocoder/sdk/models/__init__.py +6 -5
  490. autocoder/sdk/models/options.py +55 -18
  491. autocoder/sdk/utils/formatters.py +27 -195
  492. autocoder/suffixproject/__init__.py +28 -25
  493. autocoder/terminal/__init__.py +14 -0
  494. autocoder/terminal/app.py +454 -0
  495. autocoder/terminal/args.py +32 -0
  496. autocoder/terminal/bootstrap.py +178 -0
  497. autocoder/terminal/command_processor.py +521 -0
  498. autocoder/terminal/command_registry.py +57 -0
  499. autocoder/terminal/help.py +97 -0
  500. autocoder/terminal/tasks/__init__.py +5 -0
  501. autocoder/terminal/tasks/background.py +77 -0
  502. autocoder/terminal/tasks/task_event.py +70 -0
  503. autocoder/terminal/ui/__init__.py +13 -0
  504. autocoder/terminal/ui/completer.py +268 -0
  505. autocoder/terminal/ui/keybindings.py +75 -0
  506. autocoder/terminal/ui/session.py +41 -0
  507. autocoder/terminal/ui/toolbar.py +64 -0
  508. autocoder/terminal/utils/__init__.py +13 -0
  509. autocoder/terminal/utils/errors.py +18 -0
  510. autocoder/terminal/utils/paths.py +19 -0
  511. autocoder/terminal/utils/shell.py +43 -0
  512. autocoder/terminal_v3/__init__.py +10 -0
  513. autocoder/terminal_v3/app.py +201 -0
  514. autocoder/terminal_v3/handlers/__init__.py +5 -0
  515. autocoder/terminal_v3/handlers/command_handler.py +131 -0
  516. autocoder/terminal_v3/models/__init__.py +6 -0
  517. autocoder/terminal_v3/models/conversation_buffer.py +214 -0
  518. autocoder/terminal_v3/models/message.py +50 -0
  519. autocoder/terminal_v3/models/tool_display.py +247 -0
  520. autocoder/terminal_v3/ui/__init__.py +7 -0
  521. autocoder/terminal_v3/ui/keybindings.py +56 -0
  522. autocoder/terminal_v3/ui/layout.py +141 -0
  523. autocoder/terminal_v3/ui/styles.py +43 -0
  524. autocoder/tsproject/__init__.py +23 -23
  525. autocoder/utils/auto_coder_utils/chat_stream_out.py +1 -1
  526. autocoder/utils/llms.py +88 -80
  527. autocoder/utils/math_utils.py +101 -0
  528. autocoder/utils/model_provider_selector.py +16 -4
  529. autocoder/utils/operate_config_api.py +33 -5
  530. autocoder/utils/thread_utils.py +2 -2
  531. autocoder/version.py +4 -2
  532. autocoder/workflow_agents/__init__.py +84 -0
  533. autocoder/workflow_agents/agent.py +143 -0
  534. autocoder/workflow_agents/exceptions.py +573 -0
  535. autocoder/workflow_agents/executor.py +665 -0
  536. autocoder/workflow_agents/loader.py +749 -0
  537. autocoder/workflow_agents/runner.py +267 -0
  538. autocoder/workflow_agents/types.py +173 -0
  539. autocoder/workflow_agents/utils.py +434 -0
  540. autocoder/workflow_agents/workflow_manager.py +211 -0
  541. auto_coder-1.0.0.dist-info/METADATA +0 -396
  542. auto_coder-1.0.0.dist-info/RECORD +0 -442
  543. auto_coder-1.0.0.dist-info/licenses/LICENSE +0 -201
  544. autocoder/auto_coder_server.py +0 -672
  545. autocoder/benchmark.py +0 -138
  546. autocoder/common/ac_style_command_parser/example.py +0 -7
  547. autocoder/common/cleaner.py +0 -31
  548. autocoder/common/command_completer_v2.py +0 -615
  549. autocoder/common/context_pruner.py +0 -477
  550. autocoder/common/conversation_pruner.py +0 -132
  551. autocoder/common/directory_cache/__init__.py +0 -1
  552. autocoder/common/directory_cache/cache.py +0 -192
  553. autocoder/common/directory_cache/test_cache.py +0 -190
  554. autocoder/common/file_checkpoint/examples.py +0 -217
  555. autocoder/common/llm_friendly_package_example.py +0 -138
  556. autocoder/common/llm_friendly_package_test.py +0 -63
  557. autocoder/common/pull_requests/test_module.py +0 -1
  558. autocoder/common/rulefiles/autocoderrules_utils.py +0 -484
  559. autocoder/common/text.py +0 -30
  560. autocoder/common/v2/agent/agentic_edit_tools/list_package_info_tool_resolver.py +0 -42
  561. autocoder/common/v2/agent/agentic_edit_tools/test_execute_command_tool_resolver.py +0 -70
  562. autocoder/common/v2/agent/agentic_edit_tools/test_search_files_tool_resolver.py +0 -163
  563. autocoder/common/v2/agent/agentic_tool_display.py +0 -183
  564. autocoder/plugins/dynamic_completion_example.py +0 -148
  565. autocoder/plugins/sample_plugin.py +0 -160
  566. autocoder/sdk/cli/__main__.py +0 -26
  567. autocoder/sdk/cli/completion_wrapper.py +0 -38
  568. autocoder/sdk/cli/install_completion.py +0 -301
  569. autocoder/sdk/models/messages.py +0 -209
  570. autocoder/sdk/session/__init__.py +0 -32
  571. autocoder/sdk/session/session.py +0 -106
  572. autocoder/sdk/session/session_manager.py +0 -56
  573. {auto_coder-1.0.0.dist-info → auto_coder-2.0.1.dist-info}/top_level.txt +0 -0
  574. /autocoder/{sdk/example.py → common/agent_query_queue/__init__.py} +0 -0
@@ -0,0 +1,805 @@
1
+ # -*- coding: utf-8 -*-
2
+ """
3
+ RuleSelector
4
+
5
+ 基于 LLM 的智能规则选择器,支持规则摘要生成和索引创建。
6
+ """
7
+
8
+ import os
9
+ import subprocess
10
+ import tempfile
11
+ import concurrent.futures
12
+ from typing import Dict, List, Optional, Union
13
+ from loguru import logger
14
+
15
+ # 导入第三方依赖
16
+ import byzerllm
17
+ from autocoder.common import AutoCoderArgs
18
+
19
+ # 导入数据模型
20
+ from ..models.rule_file import RuleFile
21
+ from ..models.rule_relevance import RuleRelevance
22
+ from ..models.summary import AlwaysApplyRuleSummary
23
+ from ..models.index import ConditionalRulesIndex
24
+ from ..models.init_rule import InitRule
25
+
26
+
27
+
28
+
29
+ class RuleSelector:
30
+ """
31
+ 根据LLM的判断和规则元数据选择适用的规则。
32
+ """
33
+ def __init__(self, llm: Optional[Union[byzerllm.ByzerLLM, byzerllm.SimpleByzerLLM]], args: Optional[AutoCoderArgs] = None):
34
+ """
35
+ 初始化RuleSelector。
36
+
37
+ Args:
38
+ llm: ByzerLLM 实例,用于判断规则是否适用。如果为 None,则只选择 always_apply=True 的规则。
39
+ args: 传递给 Agent 的参数,可能包含用于规则选择的上下文信息。
40
+ """
41
+ self.llm = llm
42
+ self.args = args
43
+
44
+
45
+
46
+ @byzerllm.prompt()
47
+ def _build_selection_prompt(self, rule: RuleFile, context: str = "") -> str:
48
+ """
49
+ 判断规则是否适用于当前任务。
50
+
51
+ 规则描述:
52
+ {{ rule.description }}
53
+
54
+ 规则内容摘要 (前200字符):
55
+ {{ rule.content[:200] }}
56
+
57
+ {% if context %}
58
+ 任务上下文:
59
+ {{ context }}
60
+ {% endif %}
61
+
62
+ 基于以上信息,判断这条规则 (路径: {{ rule.file_path }}) 是否与当前任务相关并应该被应用?
63
+
64
+ 请以JSON格式返回结果:
65
+ ```json
66
+ {
67
+ "is_relevant": true或false,
68
+ "reason": "判断理由"
69
+ }
70
+ ```
71
+ """
72
+ # 注意:确保 rule 对象和 context 字典能够被 Jinja2 正确访问。
73
+ # Pydantic模型可以直接在Jinja2中使用其属性。
74
+ return {
75
+ "rule": rule,
76
+ "context": context
77
+ } # type: ignore
78
+
79
+ def _evaluate_rule(self, rule: RuleFile, context: str) -> tuple[RuleFile, bool, Optional[str]]:
80
+ """
81
+ 评估单个规则是否适用于当前上下文。
82
+
83
+ Args:
84
+ rule: 要评估的规则
85
+ context: 上下文信息
86
+
87
+ Returns:
88
+ tuple: (规则, 是否选中, 理由)
89
+ """
90
+ # 如果规则设置为总是应用,直接返回选中
91
+ if rule.always_apply:
92
+ return (rule, True, "规则设置为总是应用")
93
+
94
+ # 如果没有LLM,无法评估non-always规则
95
+ if self.llm is None:
96
+ return (rule, False, "未提供LLM,无法评估non-always规则")
97
+
98
+ try:
99
+ prompt = self._build_selection_prompt.prompt(rule=rule, context=context)
100
+ logger.debug(f"为规则 '{os.path.basename(rule.file_path)}' 生成的判断 Prompt (片段): {prompt[:200]}...")
101
+
102
+ result = None
103
+ try:
104
+ # 使用with_return_type方法获取结构化结果
105
+ result = self._build_selection_prompt.with_llm(self.llm).with_return_type(RuleRelevance).run(rule=rule, context=context)
106
+ if result and result.is_relevant:
107
+ return (rule, True, result.reason)
108
+ else:
109
+ return (rule, False, result.reason if result else "未提供理由")
110
+ except Exception as e:
111
+ logger.warning(f"LLM 未能为规则 '{os.path.basename(rule.file_path)}' 提供有效响应: {e}")
112
+ return (rule, False, f"LLM评估出错: {str(e)}")
113
+
114
+ except Exception as e:
115
+ logger.error(f"评估规则 '{os.path.basename(rule.file_path)}' 时出错: {e}", exc_info=True)
116
+ return (rule, False, f"评估过程出错: {str(e)}")
117
+
118
+ def select_rules(self, context: str) -> List[RuleFile]:
119
+ """
120
+ 选择适用于当前上下文的规则。使用线程池并发评估规则。
121
+
122
+ Args:
123
+ context: 包含用于规则选择的上下文信息 (例如,用户指令、目标文件等)。
124
+
125
+ Returns:
126
+ List[RuleFile]: 选定的规则列表。
127
+ """
128
+ # 导入函数以避免循环依赖
129
+ from ..api import get_parsed_rules
130
+
131
+ rules = get_parsed_rules()
132
+ selected_rules: List[RuleFile] = []
133
+ logger.info(f"开始选择规则,总规则数: {len(rules)}")
134
+
135
+ # 预先分类处理always_apply规则
136
+ always_apply_rules = []
137
+ need_llm_rules = []
138
+
139
+ for rule in rules:
140
+ if rule.always_apply:
141
+ always_apply_rules.append(rule)
142
+ elif self.llm is not None:
143
+ need_llm_rules.append(rule)
144
+
145
+ # 添加always_apply规则
146
+ for rule in always_apply_rules:
147
+ selected_rules.append(rule)
148
+ logger.debug(f"规则 '{os.path.basename(rule.file_path)}' (AlwaysApply=True) 已自动选择。")
149
+
150
+ # 如果没有需要LLM评估的规则,直接返回结果
151
+ if not need_llm_rules:
152
+ logger.info(f"规则选择完成,选中规则数: {len(selected_rules)}")
153
+ return selected_rules
154
+
155
+ # 使用线程池并发评估规则
156
+ with concurrent.futures.ThreadPoolExecutor() as executor:
157
+ # 提交所有评估任务
158
+ future_to_rule = {
159
+ executor.submit(self._evaluate_rule, rule, context): rule
160
+ for rule in need_llm_rules
161
+ }
162
+
163
+ # 收集评估结果
164
+ for future in concurrent.futures.as_completed(future_to_rule):
165
+ rule, is_selected, reason = future.result()
166
+ if is_selected:
167
+ selected_rules.append(rule)
168
+ logger.info(f"规则 '{os.path.basename(rule.file_path)}' (AlwaysApply=False) 已被 LLM 选择,原因: {reason}")
169
+ else:
170
+ logger.debug(f"规则 '{os.path.basename(rule.file_path)}' (AlwaysApply=False) 未被 LLM 选择,原因: {reason}")
171
+
172
+ logger.info(f"规则选择完成,选中规则数: {len(selected_rules)}")
173
+ return selected_rules
174
+
175
+ def get_selected_rules_content(self, context: str) -> Dict[str, str]:
176
+ """
177
+ 获取选定规则的文件路径和内容字典。
178
+
179
+ Args:
180
+ context: 传递给 select_rules 的上下文。
181
+
182
+ Returns:
183
+ Dict[str, str]: 选定规则的 {file_path: content} 字典。
184
+ """
185
+ selected_rules = self.select_rules(context=context)
186
+ # 使用 os.path.basename 获取文件名作为 key,如果需要的话
187
+ # return {os.path.basename(rule.file_path): rule.content for rule in selected_rules}
188
+ # 保持 file_path 作为 key
189
+ return {rule.file_path: rule.content for rule in selected_rules}
190
+
191
+ @byzerllm.prompt()
192
+ def _build_always_apply_summary_prompt(self, rules: List[RuleFile]) -> str:
193
+ """
194
+ Merge all always-apply rules into a unified rule description.
195
+
196
+ Below is the list of all always-apply rules ({{ rules|length }} rules in total):
197
+
198
+ {% for rule in rules %}
199
+ ## Rule {{ loop.index }}: {{ rule.file_path }}
200
+ {% if rule.description %}
201
+ **Description**: {{ rule.description }}
202
+ {% endif %}
203
+ {% if rule.globs %}
204
+ **Applicable Files**: {{ rule.globs|join(', ') }}
205
+ {% endif %}
206
+
207
+ **Content**:
208
+ {{ rule.content }}
209
+
210
+ ---
211
+ {% endfor %}
212
+
213
+ Please merge all the above rules into a unified and concise rule description. Requirements:
214
+ 1. Keep all important rule points
215
+ 2. Remove duplicate content while preserving complementary information
216
+ 3. Organize content by logical grouping
217
+ 4. Generate a unified rule document that is easy to understand and follow
218
+
219
+ ***Do not include any extraneous content, please start outputting the rule content directly.***
220
+ ```
221
+ """
222
+ return {"rules": rules} # type: ignore
223
+
224
+ @byzerllm.prompt()
225
+ def _build_conditional_rules_index_prompt(self, rules: List[RuleFile]) -> str:
226
+ """
227
+ Generate an index directory for all conditional rules.
228
+
229
+ Below is the list of all conditional rules ({{ rules|length }} rules in total):
230
+
231
+ {% for rule in rules %}
232
+ ## Rule {{ loop.index }}: {{ rule.file_path }}
233
+ {% if rule.description %}
234
+ **Description**: {{ rule.description }}
235
+ {% endif %}
236
+ {% if rule.globs %}
237
+ **Applicable Files**: {{ rule.globs|join(', ') }}
238
+ {% endif %}
239
+
240
+ **Content**:
241
+ {{ rule.content }}
242
+
243
+ ---
244
+ {% endfor %}
245
+
246
+ Please generate a detailed index directory for all the above conditional rules. Requirements:
247
+ 1. Provide concise descriptions and usage explanations for each rule to help users understand the purpose of the rules
248
+ 2. Explain when these rules should be selected and used
249
+ 3. Generate an easy-to-navigate and searchable directory structure that must include file paths
250
+
251
+ ***Do not include any extraneous content, please start outputting the rule content directly.***
252
+ """
253
+ return {"rules": rules} # type: ignore
254
+
255
+ def generate_always_apply_summary(self) -> Optional[AlwaysApplyRuleSummary]:
256
+ """
257
+ 生成所有必须应用规则的合并摘要。
258
+
259
+ Returns:
260
+ AlwaysApplyRuleSummary: 合并后的规则摘要,如果没有 LLM 则返回 None
261
+ """
262
+ if self.llm is None:
263
+ logger.warning("未提供 LLM,无法生成必须应用规则摘要")
264
+ return None
265
+
266
+ # 导入函数以避免循环依赖
267
+ from ..api import get_parsed_rules
268
+
269
+ # 获取所有解析后的规则
270
+ all_rules = get_parsed_rules()
271
+ always_apply_rules = [rule for rule in all_rules if rule.always_apply]
272
+
273
+ if not always_apply_rules:
274
+ logger.info("未找到必须应用的规则")
275
+ return AlwaysApplyRuleSummary(
276
+ summary="未找到必须应用的规则。",
277
+ rule_count=0,
278
+ covered_areas=[]
279
+ )
280
+
281
+
282
+
283
+ logger.info(f"开始生成必须应用规则摘要,规则数量: {len(always_apply_rules)}")
284
+
285
+ try:
286
+ # 由于 prompt 现在不返回 JSON,我们需要直接获取字符串结果
287
+ result_str = self._build_always_apply_summary_prompt.with_llm(self.llm).run(rules=always_apply_rules)
288
+ if result_str:
289
+ # 创建摘要对象
290
+ result = AlwaysApplyRuleSummary(
291
+ summary=result_str,
292
+ rule_count=len(always_apply_rules),
293
+ covered_areas=[] # 暂时为空,可以后续通过 LLM 分析生成
294
+ )
295
+
296
+
297
+
298
+ logger.info(f"成功生成必须应用规则摘要")
299
+ return result
300
+ else:
301
+ logger.warning("LLM 未能生成有效的规则摘要")
302
+ return None
303
+ except Exception as e:
304
+ logger.error(f"生成必须应用规则摘要时出错: {e}", exc_info=True)
305
+ return None
306
+
307
+ def generate_conditional_rules_index(self) -> Optional[ConditionalRulesIndex]:
308
+ """
309
+ 生成所有条件规则的索引目录。
310
+
311
+ Returns:
312
+ ConditionalRulesIndex: 条件规则索引,如果没有 LLM 则返回 None
313
+ """
314
+ if self.llm is None:
315
+ logger.warning("未提供 LLM,无法生成条件规则索引")
316
+ return None
317
+
318
+ # 导入函数以避免循环依赖
319
+ from ..api import get_parsed_rules
320
+
321
+ # 获取所有解析后的规则
322
+ all_rules = get_parsed_rules()
323
+ conditional_rules = [rule for rule in all_rules if not rule.always_apply]
324
+
325
+ if not conditional_rules:
326
+ logger.info("未找到条件规则")
327
+ return ConditionalRulesIndex(
328
+ index_content="未找到条件规则。",
329
+ rule_count=0,
330
+ categories=[]
331
+ )
332
+
333
+
334
+
335
+ logger.info(f"开始生成条件规则索引,规则数量: {len(conditional_rules)}")
336
+
337
+ try:
338
+ # 由于 prompt 现在不返回 JSON,我们需要直接获取字符串结果
339
+ result_str = self._build_conditional_rules_index_prompt.with_llm(self.llm).run(rules=conditional_rules)
340
+ if result_str:
341
+ # 创建索引对象
342
+ result = ConditionalRulesIndex(
343
+ index_content=result_str,
344
+ rule_count=len(conditional_rules),
345
+ categories=[] # 暂时为空,可以后续通过 LLM 分析生成
346
+ )
347
+
348
+
349
+
350
+ logger.info(f"成功生成条件规则索引")
351
+ return result
352
+ else:
353
+ logger.warning("LLM 未能生成有效的规则索引")
354
+ return None
355
+ except Exception as e:
356
+ logger.error(f"生成条件规则索引时出错: {e}", exc_info=True)
357
+ return None
358
+
359
+
360
+
361
+ def generate_init_rule(self, project_root: Optional[str] = None) -> Optional[InitRule]:
362
+ """
363
+ 使用 subagent 机制探索项目结构并生成初始化规则。
364
+
365
+ Args:
366
+ project_root: 项目根目录路径,如果为 None 则使用当前目录
367
+
368
+ Returns:
369
+ InitRule: 生成的初始化规则,如果失败则返回 None
370
+ """
371
+ if project_root is None:
372
+ project_root = os.getcwd()
373
+
374
+ logger.info(f"使用 subagent 机制开始生成初始化规则: {project_root}")
375
+
376
+ try:
377
+ # 探索项目结构
378
+ project_info = self._explore_project_structure(project_root)
379
+ logger.info(f"项目探索完成,检测到技术栈: {project_info['technologies']}")
380
+
381
+ # 获取模型名称
382
+ model_name = self._get_model_name()
383
+ if not model_name:
384
+ logger.error("无法获取模型名称,无法使用 subagent 机制")
385
+ return None
386
+
387
+ # 使用 subagent 机制生成规则
388
+ success = self._generate_init_rule_with_subagent(project_info, model_name, project_root)
389
+
390
+ if not success:
391
+ logger.error("subagent 执行失败")
392
+ return None
393
+
394
+ # 检查生成的文件并读取内容
395
+ rules_dir = self._find_rules_directory(project_root)
396
+ if not rules_dir:
397
+ logger.error("未找到 .autocoderrules 目录")
398
+ return None
399
+
400
+ init_file_path = os.path.join(rules_dir, "init.md")
401
+ if not os.path.exists(init_file_path):
402
+ logger.error(f"未找到生成的 init.md 文件: {init_file_path}")
403
+ return None
404
+
405
+ # 读取生成的内容
406
+ with open(init_file_path, 'r', encoding='utf-8') as f:
407
+ content = f.read()
408
+
409
+ if not content.strip():
410
+ logger.error("生成的 init.md 文件为空")
411
+ return None
412
+
413
+ # 确定项目类型
414
+ project_type = self._determine_project_type(project_info['technologies'])
415
+
416
+ # 提取命令列表
417
+ commands = self._extract_commands_from_content(content)
418
+
419
+ # 创建 InitRule 对象
420
+ result = InitRule(
421
+ content=content,
422
+ project_type=project_type,
423
+ commands=commands,
424
+ technologies=project_info['technologies'],
425
+ file_path=init_file_path
426
+ )
427
+
428
+ logger.info(f"成功使用 subagent 生成初始化规则,项目类型: {project_type}")
429
+ return result
430
+
431
+ except Exception as e:
432
+ logger.error(f"使用 subagent 生成初始化规则时出错: {e}", exc_info=True)
433
+ return None
434
+
435
+ def _explore_project_structure(self, project_root: str) -> Dict:
436
+ """探索项目结构,检测技术栈和配置文件"""
437
+ project_info = {
438
+ 'root_files': [],
439
+ 'main_directories': [],
440
+ 'technologies': [],
441
+ 'package_json': None,
442
+ 'setup_py': None,
443
+ 'requirements_txt': None,
444
+ 'go_mod': None,
445
+ 'pyproject_toml': None,
446
+ 'tsconfig_json': None,
447
+ }
448
+
449
+ try:
450
+ # 获取根目录文件
451
+ if os.path.exists(project_root):
452
+ root_items = os.listdir(project_root)
453
+
454
+ # 分离文件和目录
455
+ for item in root_items:
456
+ item_path = os.path.join(project_root, item)
457
+ if os.path.isfile(item_path):
458
+ project_info['root_files'].append(item)
459
+ elif os.path.isdir(item_path) and not item.startswith('.'):
460
+ project_info['main_directories'].append(item)
461
+
462
+ # 检测配置文件并读取内容
463
+ config_files = {
464
+ 'package.json': 'package_json',
465
+ 'setup.py': 'setup_py',
466
+ 'requirements.txt': 'requirements_txt',
467
+ 'go.mod': 'go_mod',
468
+ 'pyproject.toml': 'pyproject_toml',
469
+ 'tsconfig.json': 'tsconfig_json',
470
+ }
471
+
472
+ for filename, key in config_files.items():
473
+ file_path = os.path.join(project_root, filename)
474
+ if os.path.exists(file_path):
475
+ try:
476
+ with open(file_path, 'r', encoding='utf-8') as f:
477
+ content = f.read()
478
+ project_info[key] = content[:1000] # 限制内容长度
479
+ except Exception as e:
480
+ logger.warning(f"读取 {filename} 时出错: {e}")
481
+
482
+ # 检测技术栈
483
+ project_info['technologies'] = self._detect_technologies(project_info)
484
+
485
+ except Exception as e:
486
+ logger.error(f"探索项目结构时出错: {e}")
487
+
488
+ return project_info
489
+
490
+ def _detect_technologies(self, project_info: Dict) -> List[str]:
491
+ """根据配置文件检测技术栈"""
492
+ technologies = []
493
+
494
+ # Python
495
+ if project_info['setup_py'] or project_info['requirements_txt'] or project_info['pyproject_toml']:
496
+ technologies.append('Python')
497
+
498
+ # JavaScript/TypeScript
499
+ if project_info['package_json']:
500
+ technologies.append('JavaScript')
501
+ try:
502
+ import json
503
+ package_data = json.loads(project_info['package_json'])
504
+ dependencies = {
505
+ **package_data.get('dependencies', {}),
506
+ **package_data.get('devDependencies', {})
507
+ }
508
+
509
+ if 'typescript' in dependencies or project_info['tsconfig_json']:
510
+ technologies.append('TypeScript')
511
+
512
+ if 'react' in dependencies:
513
+ technologies.append('React')
514
+
515
+ if 'vue' in dependencies:
516
+ technologies.append('Vue')
517
+
518
+ if 'express' in dependencies:
519
+ technologies.append('Node.js')
520
+
521
+ except Exception as e:
522
+ logger.warning(f"解析 package.json 时出错: {e}")
523
+
524
+ # Go
525
+ if project_info['go_mod']:
526
+ technologies.append('Go')
527
+
528
+ # 其他检测
529
+ if 'src' in project_info['main_directories']:
530
+ if not technologies: # 如果还没检测到技术栈,根据目录结构猜测
531
+ technologies.append('General')
532
+
533
+ return technologies if technologies else ['Unknown']
534
+
535
+ def _determine_project_type(self, technologies: List[str]) -> str:
536
+ """根据技术栈确定项目类型"""
537
+ if 'React' in technologies:
538
+ return 'React Application'
539
+ elif 'Vue' in technologies:
540
+ return 'Vue Application'
541
+ elif 'TypeScript' in technologies:
542
+ return 'TypeScript Project'
543
+ elif 'JavaScript' in technologies:
544
+ return 'JavaScript Project'
545
+ elif 'Python' in technologies:
546
+ return 'Python Project'
547
+ elif 'Go' in technologies:
548
+ return 'Go Project'
549
+ else:
550
+ return 'General Project'
551
+
552
+ def _extract_commands_from_content(self, content: str) -> List[str]:
553
+ """从生成的内容中提取命令列表"""
554
+ commands = []
555
+ lines = content.split('\n')
556
+ in_commands_section = False
557
+
558
+ for line in lines:
559
+ line = line.strip()
560
+ if line.lower().startswith('# bash commands'):
561
+ in_commands_section = True
562
+ continue
563
+ elif line.startswith('#') and in_commands_section:
564
+ in_commands_section = False
565
+ elif in_commands_section and line.startswith('-'):
566
+ # 提取命令名称
567
+ command_part = line[1:].strip()
568
+ if ':' in command_part:
569
+ command_name = command_part.split(':')[0].strip()
570
+ commands.append(command_name)
571
+
572
+ return commands
573
+
574
+ def _get_model_name(self) -> Optional[str]:
575
+ """
576
+ 获取当前可用的模型名称
577
+
578
+ Returns:
579
+ 当前模型名称,如果没有则返回 None
580
+ """
581
+ try:
582
+ # 尝试从 args 中获取模型信息
583
+ if self.args and hasattr(self.args, 'model') and self.args.model:
584
+ return self.args.model
585
+
586
+ # 尝试从 llm 实例获取模型名称
587
+ if self.llm:
588
+ if hasattr(self.llm, 'default_model_name') and self.llm.default_model_name:
589
+ return self.llm.default_model_name
590
+ elif hasattr(self.llm, 'model_name') and self.llm.model_name:
591
+ return self.llm.model_name
592
+ elif hasattr(self.llm, 'model') and self.llm.model:
593
+ return self.llm.model
594
+
595
+ # 尝试从环境变量获取
596
+ env_model = os.getenv('AUTO_CODER_MODEL')
597
+ if env_model:
598
+ return env_model
599
+
600
+ # 默认模型
601
+ return "v3_chat"
602
+
603
+ except Exception as e:
604
+ logger.warning(f"获取模型名称时出错: {str(e)}")
605
+ return "v3_chat"
606
+
607
+ def _generate_init_rule_with_subagent(self, project_info: Dict, model_name: str, project_root: str) -> bool:
608
+ """
609
+ 使用 subagent 机制生成初始化规则
610
+
611
+ Args:
612
+ project_info: 项目信息
613
+ model_name: 模型名称
614
+ project_root: 项目根目录
615
+
616
+ Returns:
617
+ 是否成功
618
+ """
619
+ try:
620
+ # 创建临时文件
621
+ with tempfile.NamedTemporaryFile(mode='w', suffix='.md', delete=False, encoding='utf-8') as temp_file:
622
+ temp_file_path = temp_file.name
623
+
624
+ # 构建指令内容
625
+ instruction_content = self._build_subagent_instruction(project_info, project_root)
626
+ temp_file.write(instruction_content)
627
+
628
+ logger.info(f"创建临时指令文件: {temp_file_path}")
629
+
630
+ try:
631
+ # 切换到项目根目录执行命令
632
+ original_cwd = os.getcwd()
633
+ os.chdir(project_root)
634
+
635
+ # 构建并执行 auto-coder.run 命令
636
+ command = f"cat {temp_file_path} | auto-coder.run --model {model_name}"
637
+ logger.info(f"执行 subagent 命令: {command}")
638
+
639
+ # 执行命令
640
+ result = subprocess.run(
641
+ command,
642
+ shell=True,
643
+ capture_output=True,
644
+ text=True,
645
+ timeout=300 # 5分钟超时
646
+ )
647
+
648
+ if result.returncode == 0:
649
+ logger.info("subagent 命令执行成功")
650
+ if result.stdout:
651
+ logger.info(f"命令输出: {result.stdout}")
652
+ return True
653
+ else:
654
+ logger.error(f"subagent 命令执行失败,返回码: {result.returncode}")
655
+ if result.stderr:
656
+ logger.error(f"错误输出: {result.stderr}")
657
+ if result.stdout:
658
+ logger.error(f"标准输出: {result.stdout}")
659
+ return False
660
+
661
+ finally:
662
+ # 恢复原始工作目录
663
+ os.chdir(original_cwd)
664
+
665
+ # 清理临时文件
666
+ try:
667
+ os.unlink(temp_file_path)
668
+ logger.info(f"已清理临时文件: {temp_file_path}")
669
+ except Exception as e:
670
+ logger.warning(f"清理临时文件时出错: {e}")
671
+
672
+ except subprocess.TimeoutExpired:
673
+ logger.error("subagent 命令执行超时")
674
+ return False
675
+ except Exception as e:
676
+ logger.error(f"执行 subagent 命令时出错: {e}", exc_info=True)
677
+ return False
678
+
679
+ def _build_subagent_instruction(self, project_info: Dict, project_root: str) -> str:
680
+ """
681
+ 构建 subagent 的指令内容
682
+
683
+ Args:
684
+ project_info: 项目信息
685
+ project_root: 项目根目录
686
+
687
+ Returns:
688
+ 指令内容
689
+ """
690
+ # 构建项目信息描述
691
+ project_description = ""
692
+
693
+ if project_info.get('package_json'):
694
+ project_description += f"\n**发现 package.json 文件**:\n```json\n{project_info['package_json'][:500]}...\n```\n"
695
+
696
+ if project_info.get('setup_py'):
697
+ project_description += f"\n**发现 setup.py 文件**:\n```python\n{project_info['setup_py'][:500]}...\n```\n"
698
+
699
+ if project_info.get('requirements_txt'):
700
+ project_description += f"\n**发现 requirements.txt 文件**:\n```\n{project_info['requirements_txt'][:300]}...\n```\n"
701
+
702
+ if project_info.get('go_mod'):
703
+ project_description += f"\n**发现 go.mod 文件**:\n```\n{project_info['go_mod'][:300]}...\n```\n"
704
+
705
+ if project_info.get('pyproject_toml'):
706
+ project_description += f"\n**发现 pyproject.toml 文件**:\n```toml\n{project_info['pyproject_toml'][:500]}...\n```\n"
707
+
708
+ if project_info.get('tsconfig_json'):
709
+ project_description += f"\n**发现 tsconfig.json 文件**:\n```json\n{project_info['tsconfig_json'][:300]}...\n```\n"
710
+
711
+ root_files = ', '.join(project_info.get('root_files', [])[:10])
712
+ main_directories = ', '.join(project_info.get('main_directories', [])[:10])
713
+ technologies = ', '.join(project_info.get('technologies', []))
714
+
715
+ instruction = f"""请分析当前项目结构并在 .autocoderrules 目录下生成一个 init.md 文件,包含项目的开发规则和指导。
716
+
717
+ ## 项目信息
718
+
719
+ **项目根目录**: {project_root}
720
+ **根目录文件**: {root_files}
721
+ **主要目录**: {main_directories}
722
+ **检测到的技术栈**: {technologies}
723
+
724
+ {project_description}
725
+
726
+ ## 任务要求
727
+
728
+ 请根据上述项目信息,在 `.autocoderrules` 目录下创建一个 `init.md` 文件,内容应该包括:
729
+
730
+ ### 1. Bash commands
731
+ 列出常用的构建、测试、运行命令,格式如下:
732
+ ```
733
+ # Bash commands
734
+ - command_name: 命令描述
735
+ - another_command: 另一个命令描述
736
+ ```
737
+
738
+ ### 2. Code style
739
+ 根据检测到的技术栈,提供相应的编码规范,例如:
740
+ ```
741
+ # Code style
742
+ - 使用一致的代码格式化规则
743
+ - 遵循对应语言的最佳实践
744
+ ```
745
+
746
+ ### 3. Workflow
747
+ 提供开发工作流建议:
748
+ ```
749
+ # Workflow
750
+ - 开发流程建议
751
+ - 测试和部署流程
752
+ ```
753
+
754
+ ### 4. Technology-specific rules
755
+ 针对具体技术栈的特殊规则:
756
+ ```
757
+ # Technology-specific rules
758
+ - 技术栈特定的规则
759
+ - 框架相关的最佳实践
760
+ ```
761
+
762
+ ## 注意事项
763
+
764
+ 1. 如果 `.autocoderrules` 目录不存在,请先创建该目录
765
+ 2. 根据实际检测到的技术栈生成相应的规则
766
+ 3. 确保生成的规则实用且具体
767
+ 4. 命令应该是项目中实际可能用到的
768
+ 5. 规则应该帮助开发者快速上手项目开发
769
+
770
+ 请立即开始分析项目并生成 init.md 文件。
771
+ """
772
+
773
+ return instruction
774
+
775
+ def _find_rules_directory(self, project_root: str) -> Optional[str]:
776
+ """
777
+ 查找现有的 .autocoderrules 目录
778
+
779
+ Args:
780
+ project_root: 项目根目录
781
+
782
+ Returns:
783
+ 找到的规则目录路径,如果没找到则返回 None
784
+ """
785
+ try:
786
+ # 按优先级顺序查找
787
+ possible_dirs = [
788
+ os.path.join(project_root, ".autocoderrules"),
789
+ os.path.join(project_root, ".auto-coder", ".autocoderrules"),
790
+ os.path.join(project_root, ".auto-coder", "autocoderrules"),
791
+ ]
792
+
793
+ for rules_dir in possible_dirs:
794
+ if os.path.exists(rules_dir) and os.path.isdir(rules_dir):
795
+ logger.info(f"找到现有的规则目录: {rules_dir}")
796
+ return rules_dir
797
+
798
+ # 如果没有找到现有目录,返回默认的第一个位置
799
+ default_dir = possible_dirs[0]
800
+ logger.info(f"未找到现有规则目录,返回默认位置: {default_dir}")
801
+ return default_dir
802
+
803
+ except Exception as e:
804
+ logger.error(f"查找规则目录时出错: {e}")
805
+ return None