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,325 @@
1
+
2
+ import os
3
+ import json
4
+ import uuid
5
+ import threading
6
+ from typing import Dict, List, Optional, Any
7
+ from datetime import datetime
8
+ from pathlib import Path
9
+ from dataclasses import dataclass, asdict
10
+ from enum import Enum
11
+ from loguru import logger as global_logger
12
+
13
+
14
+ class QueueTaskStatus(Enum):
15
+ """队列任务状态枚举"""
16
+ PENDING = "pending"
17
+ RUNNING = "running"
18
+ COMPLETED = "completed"
19
+ FAILED = "failed"
20
+ CANCELLED = "cancelled"
21
+
22
+
23
+ @dataclass
24
+ class QueueTask:
25
+ """队列任务数据结构"""
26
+ task_id: str
27
+ user_query: str # 用户需求而非命令
28
+ model: str # 使用的模型
29
+ status: QueueTaskStatus
30
+ created_at: datetime
31
+ started_at: Optional[datetime] = None
32
+ completed_at: Optional[datetime] = None
33
+ result: Optional[str] = None
34
+ error_message: Optional[str] = None
35
+ priority: int = 0 # 优先级,数字越大优先级越高
36
+ worktree_name: Optional[str] = None # worktree 名称
37
+ # 兼容旧版本
38
+ command: Optional[str] = None # 保留以兼容旧数据
39
+
40
+ def to_dict(self) -> Dict[str, Any]:
41
+ """转换为字典格式"""
42
+ data = asdict(self)
43
+ # 处理datetime和enum类型
44
+ data['status'] = self.status.value
45
+ data['created_at'] = self.created_at.isoformat() if self.created_at else None
46
+ data['started_at'] = self.started_at.isoformat() if self.started_at else None
47
+ data['completed_at'] = self.completed_at.isoformat() if self.completed_at else None
48
+ return data
49
+
50
+ @classmethod
51
+ def from_dict(cls, data: Dict[str, Any]) -> 'QueueTask':
52
+ """从字典创建任务对象"""
53
+ # 处理datetime和enum类型
54
+ data['status'] = QueueTaskStatus(data['status'])
55
+ data['created_at'] = datetime.fromisoformat(data['created_at']) if data.get('created_at') else None
56
+ data['started_at'] = datetime.fromisoformat(data['started_at']) if data.get('started_at') else None
57
+ data['completed_at'] = datetime.fromisoformat(data['completed_at']) if data.get('completed_at') else None
58
+
59
+ # 兼容旧版本数据
60
+ if 'command' in data and 'user_query' not in data:
61
+ data['user_query'] = data['command']
62
+ if 'model' not in data:
63
+ data['model'] = 'auto'
64
+
65
+ # 只传递存在的字段
66
+ valid_fields = {'task_id', 'user_query', 'model', 'status', 'created_at',
67
+ 'started_at', 'completed_at', 'result', 'error_message',
68
+ 'priority', 'worktree_name', 'command'}
69
+ filtered_data = {k: v for k, v in data.items() if k in valid_fields}
70
+
71
+ return cls(**filtered_data)
72
+
73
+
74
+ class QueueManager:
75
+ """队列管理器"""
76
+
77
+ def __init__(self, queue_dir: Optional[str] = None):
78
+ """
79
+ 初始化队列管理器
80
+
81
+ Args:
82
+ queue_dir: 队列数据存储目录,默认为 ~/.auto-coder/queue
83
+ """
84
+ if queue_dir is None:
85
+ self.queue_dir = Path.home() / ".auto-coder" / "queue"
86
+ else:
87
+ self.queue_dir = Path(queue_dir)
88
+
89
+ self.queue_dir.mkdir(parents=True, exist_ok=True)
90
+ self.queue_file = self.queue_dir / "tasks.json"
91
+ self._lock = threading.Lock()
92
+
93
+ # 初始化队列文件
94
+ if not self.queue_file.exists():
95
+ self._save_tasks([])
96
+
97
+ def _load_tasks(self) -> List[QueueTask]:
98
+ """加载所有任务"""
99
+ try:
100
+ with open(self.queue_file, 'r', encoding='utf-8') as f:
101
+ tasks_data = json.load(f)
102
+ return [QueueTask.from_dict(task_data) for task_data in tasks_data]
103
+ except (FileNotFoundError, json.JSONDecodeError) as e:
104
+ global_logger.warning(f"Failed to load tasks: {e}")
105
+ return []
106
+
107
+ def _save_tasks(self, tasks: List[QueueTask]) -> None:
108
+ """保存所有任务"""
109
+ try:
110
+ tasks_data = [task.to_dict() for task in tasks]
111
+ with open(self.queue_file, 'w', encoding='utf-8') as f:
112
+ json.dump(tasks_data, f, indent=2, ensure_ascii=False)
113
+ except Exception as e:
114
+ global_logger.error(f"Failed to save tasks: {e}")
115
+ raise
116
+
117
+ def add_task(self, user_query: str = None, model: str = "auto", priority: int = 0, command: str = None, worktree_name: str = None) -> str:
118
+ """
119
+ 添加新任务到队列
120
+
121
+ Args:
122
+ user_query: 用户需求
123
+ model: 使用的模型
124
+ priority: 任务优先级,数字越大优先级越高
125
+ command: 旧版本兼容参数
126
+ worktree_name: 自定义 worktree 名称
127
+
128
+ Returns:
129
+ str: 任务ID
130
+ """
131
+ with self._lock:
132
+ task_id = str(uuid.uuid4())[:8] # 使用8位UUID作为任务ID
133
+
134
+ # 兼容旧版本
135
+ if command and not user_query:
136
+ user_query = command
137
+
138
+ task = QueueTask(
139
+ task_id=task_id,
140
+ user_query=user_query,
141
+ model=model,
142
+ status=QueueTaskStatus.PENDING,
143
+ created_at=datetime.now(),
144
+ priority=priority,
145
+ worktree_name=worktree_name,
146
+ command=command # 兼容字段
147
+ )
148
+
149
+ tasks = self._load_tasks()
150
+ tasks.append(task)
151
+
152
+ # 按优先级和创建时间排序(优先级高的在前,同优先级按创建时间排序)
153
+ tasks.sort(key=lambda t: (-t.priority, t.created_at))
154
+
155
+ self._save_tasks(tasks)
156
+ global_logger.info(f"Added task {task_id}: {user_query[:100]}..." if len(user_query) > 100 else f"Added task {task_id}: {user_query}")
157
+ return task_id
158
+
159
+ def get_task(self, task_id: str) -> Optional[QueueTask]:
160
+ """
161
+ 获取指定任务
162
+
163
+ Args:
164
+ task_id: 任务ID
165
+
166
+ Returns:
167
+ QueueTask: 任务对象,如果不存在返回None
168
+ """
169
+ tasks = self._load_tasks()
170
+ for task in tasks:
171
+ if task.task_id == task_id:
172
+ return task
173
+ return None
174
+
175
+ def list_tasks(self, status_filter: Optional[QueueTaskStatus] = None) -> List[QueueTask]:
176
+ """
177
+ 列出所有任务
178
+
179
+ Args:
180
+ status_filter: 状态过滤器,只返回指定状态的任务
181
+
182
+ Returns:
183
+ List[QueueTask]: 任务列表
184
+ """
185
+ tasks = self._load_tasks()
186
+ if status_filter:
187
+ tasks = [task for task in tasks if task.status == status_filter]
188
+ return tasks
189
+
190
+ def remove_task(self, task_id: str) -> bool:
191
+ """
192
+ 移除指定任务
193
+
194
+ Args:
195
+ task_id: 任务ID
196
+
197
+ Returns:
198
+ bool: 是否成功移除
199
+ """
200
+ with self._lock:
201
+ tasks = self._load_tasks()
202
+ original_count = len(tasks)
203
+
204
+ # 只允许移除非运行状态的任务
205
+ tasks = [task for task in tasks if not (
206
+ task.task_id == task_id and task.status != QueueTaskStatus.RUNNING
207
+ )]
208
+
209
+ if len(tasks) < original_count:
210
+ self._save_tasks(tasks)
211
+ global_logger.info(f"Removed task {task_id}")
212
+ return True
213
+ else:
214
+ global_logger.warning(f"Task {task_id} not found or is running")
215
+ return False
216
+
217
+ def update_task_status(self, task_id: str, status: QueueTaskStatus,
218
+ result: Optional[str] = None,
219
+ error_message: Optional[str] = None) -> bool:
220
+ """
221
+ 更新任务状态
222
+
223
+ Args:
224
+ task_id: 任务ID
225
+ status: 新状态
226
+ result: 执行结果
227
+ error_message: 错误信息
228
+
229
+ Returns:
230
+ bool: 是否更新成功
231
+ """
232
+ with self._lock:
233
+ tasks = self._load_tasks()
234
+ for task in tasks:
235
+ if task.task_id == task_id:
236
+ task.status = status
237
+
238
+ if status == QueueTaskStatus.RUNNING and task.started_at is None:
239
+ task.started_at = datetime.now()
240
+ elif status in [QueueTaskStatus.COMPLETED, QueueTaskStatus.FAILED, QueueTaskStatus.CANCELLED]:
241
+ task.completed_at = datetime.now()
242
+
243
+ if result is not None:
244
+ task.result = result
245
+ if error_message is not None:
246
+ task.error_message = error_message
247
+
248
+ self._save_tasks(tasks)
249
+ global_logger.info(f"Updated task {task_id} status to {status.value}")
250
+ return True
251
+
252
+ global_logger.warning(f"Task {task_id} not found")
253
+ return False
254
+
255
+ def get_next_pending_task(self) -> Optional[QueueTask]:
256
+ """
257
+ 获取下一个待执行的任务(优先级最高的pending任务)
258
+
259
+ Returns:
260
+ QueueTask: 下一个待执行的任务,如果没有返回None
261
+ """
262
+ tasks = self._load_tasks()
263
+ pending_tasks = [task for task in tasks if task.status == QueueTaskStatus.PENDING]
264
+
265
+ if not pending_tasks:
266
+ return None
267
+
268
+ # 返回优先级最高的任务(已经按优先级排序)
269
+ return pending_tasks[0]
270
+
271
+ def get_running_tasks(self) -> List[QueueTask]:
272
+ """
273
+ 获取所有正在运行的任务
274
+
275
+ Returns:
276
+ List[QueueTask]: 正在运行的任务列表
277
+ """
278
+ return self.list_tasks(QueueTaskStatus.RUNNING)
279
+
280
+ def clear_completed_tasks(self) -> int:
281
+ """
282
+ 清理已完成的任务
283
+
284
+ Returns:
285
+ int: 清理的任务数量
286
+ """
287
+ with self._lock:
288
+ tasks = self._load_tasks()
289
+ original_count = len(tasks)
290
+
291
+ # 保留未完成的任务
292
+ tasks = [task for task in tasks if task.status not in [
293
+ QueueTaskStatus.COMPLETED,
294
+ QueueTaskStatus.FAILED,
295
+ QueueTaskStatus.CANCELLED
296
+ ]]
297
+
298
+ removed_count = original_count - len(tasks)
299
+ if removed_count > 0:
300
+ self._save_tasks(tasks)
301
+ global_logger.info(f"Cleared {removed_count} completed tasks")
302
+
303
+ return removed_count
304
+
305
+ def get_queue_statistics(self) -> Dict[str, int]:
306
+ """
307
+ 获取队列统计信息
308
+
309
+ Returns:
310
+ Dict[str, int]: 统计信息
311
+ """
312
+ tasks = self._load_tasks()
313
+ stats = {
314
+ 'total': len(tasks),
315
+ 'pending': 0,
316
+ 'running': 0,
317
+ 'completed': 0,
318
+ 'failed': 0,
319
+ 'cancelled': 0
320
+ }
321
+
322
+ for task in tasks:
323
+ stats[task.status.value] += 1
324
+
325
+ return stats
@@ -0,0 +1,11 @@
1
+ """
2
+ AutoCoder Agents Module
3
+
4
+ This module provides functionality to read and parse agent definitions from .md files
5
+ in the .autocoderagents directory.
6
+ """
7
+
8
+ from .agent_manager import AgentManager
9
+ from .agent_parser import AgentParser, Agent
10
+
11
+ __all__ = ['AgentManager', 'AgentParser', 'Agent']
@@ -0,0 +1,323 @@
1
+ import shlex
2
+ import os
3
+ from pathlib import Path
4
+ from typing import List, Optional, Dict, Any
5
+ from loguru import logger
6
+ import byzerllm
7
+
8
+ from .agent_parser import AgentParser, Agent
9
+
10
+ # 导入优先级目录查找器
11
+ from autocoder.common.priority_directory_finder import (
12
+ PriorityDirectoryFinder, FinderConfig, SearchStrategy,
13
+ ValidationMode, create_file_filter
14
+ )
15
+
16
+
17
+ class AgentManager:
18
+ """Manager for loading and accessing agent definitions with multi-directory support."""
19
+
20
+ def __init__(self, project_root: str):
21
+ """
22
+ Initialize AgentManager.
23
+
24
+ Args:
25
+ project_root: Root directory of the project
26
+ """
27
+ self.project_root = Path(project_root)
28
+ self.agents: Dict[str, Agent] = {}
29
+ self.agents_directories: List[str] = []
30
+ self._load_agents()
31
+
32
+ def _get_agents_search_paths(self) -> List[Path]:
33
+ """
34
+ Get the list of directories to search for agents, in priority order.
35
+
36
+ Returns:
37
+ List of Path objects in priority order:
38
+ 1. Project directory/.autocoderagents
39
+ 2. Project directory/.auto-coder/.autocoderagents
40
+ 3. ~/.auto-coder/.autocoderagents
41
+ """
42
+ search_paths = []
43
+
44
+ # 1. Project directory/.autocoderagents (highest priority)
45
+ project_agents_dir = self.project_root / ".autocoderagents"
46
+ search_paths.append(project_agents_dir)
47
+
48
+ # 2. Project directory/.auto-coder/.autocoderagents
49
+ project_autocoder_dir = self.project_root / ".auto-coder" / ".autocoderagents"
50
+ search_paths.append(project_autocoder_dir)
51
+
52
+ # 3. ~/.auto-coder/.autocoderagents (lowest priority)
53
+ home_autocoder_dir = Path.home() / ".auto-coder" / ".autocoderagents"
54
+ search_paths.append(home_autocoder_dir)
55
+
56
+ return search_paths
57
+
58
+ def _load_agents(self) -> None:
59
+ """
60
+ 使用优先级目录查找器加载 agent 定义。
61
+ 采用 MERGE_ALL 策略,合并所有目录中的 agent 定义,支持优先级覆盖和repos功能。
62
+ """
63
+ try:
64
+ # 创建文件过滤器,只查找.md文件
65
+ md_filter = create_file_filter(extensions=[".md"], recursive=False)
66
+
67
+ # 创建查找器配置,使用MERGE_ALL策略合并所有目录
68
+ config = FinderConfig(strategy=SearchStrategy.MERGE_ALL)
69
+
70
+ # 获取项目名用于repos目录
71
+ project_name = self.project_root.name
72
+
73
+ # 按优先级添加目录配置
74
+ config.add_directory(
75
+ path=str(self.project_root / ".autocoderagents"),
76
+ priority=1,
77
+ validation_mode=ValidationMode.HAS_SPECIFIC_FILES,
78
+ file_filter=md_filter,
79
+ description="项目级agent目录"
80
+ )
81
+ config.add_directory(
82
+ path=str(self.project_root / ".auto-coder" / ".autocoderagents"),
83
+ priority=2,
84
+ validation_mode=ValidationMode.HAS_SPECIFIC_FILES,
85
+ file_filter=md_filter,
86
+ description="项目.auto-coder agent目录"
87
+ )
88
+ config.add_directory(
89
+ path="~/.auto-coder/.autocoderagents",
90
+ priority=3,
91
+ validation_mode=ValidationMode.HAS_SPECIFIC_FILES,
92
+ file_filter=md_filter,
93
+ description="全局agent目录"
94
+ )
95
+ # 添加repos目录支持
96
+ repos_dir = f"~/.auto-coder/.autocoderagents/repos/{project_name}"
97
+ config.add_directory(
98
+ path=repos_dir,
99
+ priority=4,
100
+ validation_mode=ValidationMode.HAS_SPECIFIC_FILES,
101
+ file_filter=md_filter,
102
+ description=f"项目特定repos agent目录: {project_name}"
103
+ )
104
+
105
+ # 执行查找
106
+ finder = PriorityDirectoryFinder(config)
107
+ result = finder.find_directories()
108
+
109
+ if result.success and result.selected_directories:
110
+ logger.info(f"使用优先级查找器找到 {len(result.selected_directories)} 个agent目录")
111
+ self.agents_directories = result.selected_directories
112
+
113
+ # 按优先级顺序加载agents,高优先级覆盖低优先级
114
+ for agents_dir in self.agents_directories:
115
+ logger.info(f"加载agent目录: {agents_dir}")
116
+ self._load_agents_from_directory(Path(agents_dir))
117
+ else:
118
+ logger.info("优先级查找器未找到包含agent文件的目录")
119
+ self.agents_directories = []
120
+
121
+ except Exception as e:
122
+ logger.error(f"使用优先级查找器加载agents时出错: {e}")
123
+ # 回退到传统方法
124
+ self._load_agents_fallback()
125
+
126
+ def _load_agents_from_directory(self, agents_dir: Path) -> None:
127
+ """Load agents from a specific directory with priority-based override logic."""
128
+ if not agents_dir.exists():
129
+ logger.debug(f"Agents directory not found: {agents_dir}")
130
+ return
131
+
132
+ if not agents_dir.is_dir():
133
+ logger.warning(f"Expected directory but found file: {agents_dir}")
134
+ return
135
+
136
+ # Find all .md files in the agents directory
137
+ md_files = list(agents_dir.glob("*.md"))
138
+
139
+ if md_files:
140
+ logger.debug(f"Found {len(md_files)} agent files in {agents_dir}")
141
+
142
+ for md_file in md_files:
143
+ try:
144
+ agent = AgentParser.parse_agent_file(md_file)
145
+
146
+ # Validate agent
147
+ errors = AgentParser.validate_agent(agent)
148
+ if errors:
149
+ logger.error(f"Validation errors for {md_file.name}: {'; '.join(errors)}")
150
+ continue
151
+
152
+ # 检查是否已有同名agent,实现优先级覆盖逻辑
153
+ if agent.name in self.agents:
154
+ old_agent_path = self.agents[agent.name].file_path
155
+ # 由于我们按优先级顺序加载,后加载的优先级更低,所以跳过
156
+ logger.debug(f"跳过agent '{agent.name}' from {md_file} (已存在优先级更高的版本: {old_agent_path})")
157
+ continue
158
+
159
+ self.agents[agent.name] = agent
160
+ logger.debug(f"Loaded agent '{agent.name}' from {md_file}")
161
+
162
+ except Exception as e:
163
+ logger.error(f"Failed to parse agent file {md_file.name}: {e}")
164
+
165
+ def _load_agents_fallback(self) -> None:
166
+ """回退到传统的agent加载方法"""
167
+ logger.info("回退到传统的agent目录查找方法")
168
+ search_paths = self._get_agents_search_paths()
169
+
170
+ # Load agents from all directories, with higher priority directories loaded last
171
+ # This way higher priority agents will overwrite lower priority ones
172
+ for agents_dir in reversed(search_paths): # Start with lowest priority
173
+ self._load_agents_from_directory(agents_dir)
174
+
175
+ def get_agent(self, name: str) -> Optional[Agent]:
176
+ """
177
+ Get an agent by name.
178
+
179
+ Args:
180
+ name: Name of the agent
181
+
182
+ Returns:
183
+ Agent object if found, None otherwise
184
+ """
185
+ return self.agents.get(name)
186
+
187
+ def list_agents(self) -> List[Agent]:
188
+ """
189
+ Get a list of all loaded agents.
190
+
191
+ Returns:
192
+ List of Agent objects
193
+ """
194
+ return list(self.agents.values())
195
+
196
+ def get_agent_names(self) -> List[str]:
197
+ """
198
+ Get a list of all agent names.
199
+
200
+ Returns:
201
+ List of agent names
202
+ """
203
+ return list(self.agents.keys())
204
+
205
+ @byzerllm.prompt()
206
+ def render_sub_agents_section(self, current_model: Optional[str] = None) -> str:
207
+ """
208
+ {% if not agents_available %}
209
+ {% else %}
210
+ ## Available Named Sub Agents
211
+
212
+ The following specialized agents are available for delegation:
213
+
214
+ {% for agent in sorted_agents %}
215
+ ### {{ agent.name }}
216
+ **Description**: {{ agent.description }}
217
+ {% if agent.tools %}
218
+ **Available Tools**: {{ agent.tools | join(', ') }}
219
+ {% endif %}
220
+
221
+ {% endfor %}
222
+ ## How to Use
223
+
224
+ Use the `run_named_subagents` tool to run multiple agent commands:
225
+
226
+ ### Example: Parallel Execution
227
+
228
+ <run_named_subagents>
229
+ <subagents>
230
+ mode: parallel
231
+ subagents:
232
+ {% for agent in example_agents %}
233
+ - name: {{ agent.name }}
234
+ task: {{ agent.example_task }}
235
+ {% endfor %}
236
+ </subagents>
237
+ </run_named_subagents>
238
+
239
+
240
+ ### Example: Serial Execution
241
+
242
+ <run_named_subagents>
243
+ <subagents>
244
+ mode: serial
245
+ subagents:
246
+ - name: agent_name
247
+ task: your task description here
248
+ </subagents>
249
+ </run_named_subagents>
250
+
251
+ {% endif %}
252
+ """
253
+ if not self.agents:
254
+ return {
255
+ "agents_available": False
256
+ }
257
+
258
+ # Sort agents by name for consistent output
259
+ sorted_agents = sorted(self.agents.values(), key=lambda a: a.name)
260
+
261
+ # Prepare agent data for template
262
+ agents_data = []
263
+ for agent in sorted_agents:
264
+ model_to_use = agent.model or current_model
265
+ if not model_to_use:
266
+ raise ValueError(f"Agent {agent.name} has no model specified and no current model provided")
267
+
268
+ # Use shlex.quote for safe shell escaping
269
+ safe_task = shlex.quote("YOUR_TASK_HERE")
270
+ safe_model = shlex.quote(model_to_use)
271
+ safe_prompt = shlex.quote(agent.content)
272
+ command = f'echo {safe_task} | auto-coder.run --model {safe_model} --system-prompt {safe_prompt}'
273
+
274
+ agents_data.append({
275
+ "name": agent.name,
276
+ "description": agent.description,
277
+ "tools": agent.tools if agent.tools else None,
278
+ "command": command
279
+ })
280
+
281
+ # Prepare example agents data
282
+ example_agents_data = []
283
+ example_agents = sorted_agents[:2] if len(sorted_agents) >= 2 else sorted_agents
284
+ for agent in example_agents:
285
+ example_agents_data.append({
286
+ "name": agent.name,
287
+ "example_task": f"Task for {agent.name}"
288
+ })
289
+
290
+ return {
291
+ "agents_available": True,
292
+ "sorted_agents": agents_data,
293
+ "example_agents": example_agents_data
294
+ } # type: ignore
295
+
296
+ def reload_agents(self) -> None:
297
+ """Reload all agents from the directory."""
298
+ self.agents.clear()
299
+ self._load_agents()
300
+
301
+ def get_all_agents_directories(self) -> List[str]:
302
+ """
303
+ 获取所有agent目录路径
304
+
305
+ Returns:
306
+ List[str]: 所有agent目录路径列表,按优先级排序
307
+ """
308
+ return self.agents_directories.copy()
309
+
310
+ def to_dict(self) -> Dict[str, Any]:
311
+ """
312
+ Convert the agent manager state to a dictionary.
313
+
314
+ Returns:
315
+ Dictionary representation of all agents
316
+ """
317
+ search_paths = self._get_agents_search_paths()
318
+ return {
319
+ 'project_root': str(self.project_root),
320
+ 'search_paths': [str(path) for path in search_paths],
321
+ 'agents_directories': self.agents_directories,
322
+ 'agents': {name: agent.to_dict() for name, agent in self.agents.items()}
323
+ }