auto-coder 0.1.400__py3-none-any.whl → 2.0.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of auto-coder might be problematic. Click here for more details.

Files changed (579) hide show
  1. auto_coder-2.0.0.dist-info/LICENSE +158 -0
  2. auto_coder-2.0.0.dist-info/METADATA +558 -0
  3. auto_coder-2.0.0.dist-info/RECORD +795 -0
  4. {auto_coder-0.1.400.dist-info → auto_coder-2.0.0.dist-info}/WHEEL +1 -1
  5. {auto_coder-0.1.400.dist-info → auto_coder-2.0.0.dist-info}/entry_points.txt +3 -3
  6. autocoder/__init__.py +31 -0
  7. autocoder/agent/auto_filegroup.py +32 -13
  8. autocoder/agent/auto_learn_from_commit.py +9 -1
  9. autocoder/agent/base_agentic/__init__.py +3 -0
  10. autocoder/agent/base_agentic/agent_hub.py +1 -1
  11. autocoder/agent/base_agentic/base_agent.py +235 -136
  12. autocoder/agent/base_agentic/default_tools.py +119 -118
  13. autocoder/agent/base_agentic/test_base_agent.py +1 -1
  14. autocoder/agent/base_agentic/tool_registry.py +32 -20
  15. autocoder/agent/base_agentic/tools/read_file_tool_resolver.py +25 -4
  16. autocoder/agent/base_agentic/tools/write_to_file_tool_resolver.py +24 -11
  17. autocoder/agent/base_agentic/types.py +42 -0
  18. autocoder/agent/entry_command_agent/chat.py +73 -59
  19. autocoder/auto_coder.py +31 -40
  20. autocoder/auto_coder_rag.py +11 -1084
  21. autocoder/auto_coder_runner.py +1029 -2310
  22. autocoder/auto_coder_terminal.py +26 -0
  23. autocoder/auto_coder_terminal_v3.py +190 -0
  24. autocoder/chat/conf_command.py +224 -124
  25. autocoder/chat/models_command.py +361 -299
  26. autocoder/chat/rules_command.py +79 -31
  27. autocoder/chat_auto_coder.py +1021 -372
  28. autocoder/chat_auto_coder_lang.py +23 -732
  29. autocoder/commands/auto_command.py +26 -9
  30. autocoder/commands/auto_web.py +1 -1
  31. autocoder/commands/tools.py +44 -44
  32. autocoder/common/__init__.py +150 -128
  33. autocoder/common/ac_style_command_parser/__init__.py +39 -2
  34. autocoder/common/ac_style_command_parser/config.py +422 -0
  35. autocoder/common/ac_style_command_parser/parser.py +292 -78
  36. autocoder/common/ac_style_command_parser/test_parser.py +241 -16
  37. autocoder/common/ac_style_command_parser/test_typed_parser.py +342 -0
  38. autocoder/common/ac_style_command_parser/typed_parser.py +653 -0
  39. autocoder/common/action_yml_file_manager.py +25 -13
  40. autocoder/common/agent_events/__init__.py +52 -0
  41. autocoder/common/agent_events/agent_event_emitter.py +193 -0
  42. autocoder/common/agent_events/event_factory.py +177 -0
  43. autocoder/common/agent_events/examples.py +307 -0
  44. autocoder/common/agent_events/types.py +113 -0
  45. autocoder/common/agent_events/utils.py +68 -0
  46. autocoder/common/agent_hooks/__init__.py +44 -0
  47. autocoder/common/agent_hooks/examples.py +582 -0
  48. autocoder/common/agent_hooks/hook_executor.py +217 -0
  49. autocoder/common/agent_hooks/hook_manager.py +288 -0
  50. autocoder/common/agent_hooks/types.py +133 -0
  51. autocoder/common/agent_hooks/utils.py +99 -0
  52. autocoder/common/agent_query_queue/queue_executor.py +324 -0
  53. autocoder/common/agent_query_queue/queue_manager.py +325 -0
  54. autocoder/common/agents/__init__.py +11 -0
  55. autocoder/common/agents/agent_manager.py +323 -0
  56. autocoder/common/agents/agent_parser.py +189 -0
  57. autocoder/common/agents/example_usage.py +344 -0
  58. autocoder/common/agents/integration_example.py +330 -0
  59. autocoder/common/agents/test_agent_parser.py +545 -0
  60. autocoder/common/async_utils.py +101 -0
  61. autocoder/common/auto_coder_lang.py +23 -972
  62. autocoder/common/autocoderargs_parser/__init__.py +14 -0
  63. autocoder/common/autocoderargs_parser/parser.py +184 -0
  64. autocoder/common/autocoderargs_parser/tests/__init__.py +1 -0
  65. autocoder/common/autocoderargs_parser/tests/test_args_parser.py +235 -0
  66. autocoder/common/autocoderargs_parser/tests/test_token_parser.py +195 -0
  67. autocoder/common/autocoderargs_parser/token_parser.py +290 -0
  68. autocoder/common/buildin_tokenizer.py +2 -4
  69. autocoder/common/code_auto_generate.py +149 -74
  70. autocoder/common/code_auto_generate_diff.py +163 -70
  71. autocoder/common/code_auto_generate_editblock.py +179 -89
  72. autocoder/common/code_auto_generate_strict_diff.py +167 -72
  73. autocoder/common/code_auto_merge_editblock.py +13 -6
  74. autocoder/common/code_modification_ranker.py +1 -1
  75. autocoder/common/command_completer.py +3 -3
  76. autocoder/common/command_file_manager/manager.py +183 -47
  77. autocoder/common/command_file_manager/test_command_file_manager.py +507 -0
  78. autocoder/common/command_templates.py +1 -1
  79. autocoder/common/conf_utils.py +2 -4
  80. autocoder/common/conversations/config.py +11 -3
  81. autocoder/common/conversations/get_conversation_manager.py +100 -2
  82. autocoder/common/conversations/llm_stats_models.py +264 -0
  83. autocoder/common/conversations/manager.py +112 -28
  84. autocoder/common/conversations/models.py +16 -2
  85. autocoder/common/conversations/storage/index_manager.py +134 -10
  86. autocoder/common/core_config/__init__.py +63 -0
  87. autocoder/common/core_config/agentic_mode_manager.py +109 -0
  88. autocoder/common/core_config/base_manager.py +123 -0
  89. autocoder/common/core_config/compatibility.py +151 -0
  90. autocoder/common/core_config/config_manager.py +156 -0
  91. autocoder/common/core_config/conversation_manager.py +31 -0
  92. autocoder/common/core_config/exclude_manager.py +72 -0
  93. autocoder/common/core_config/file_manager.py +177 -0
  94. autocoder/common/core_config/human_as_model_manager.py +129 -0
  95. autocoder/common/core_config/lib_manager.py +54 -0
  96. autocoder/common/core_config/main_manager.py +81 -0
  97. autocoder/common/core_config/mode_manager.py +126 -0
  98. autocoder/common/core_config/models.py +70 -0
  99. autocoder/common/core_config/test_memory_manager.py +1056 -0
  100. autocoder/common/env_manager.py +282 -0
  101. autocoder/common/env_manager_usage_example.py +211 -0
  102. autocoder/common/file_checkpoint/conversation_checkpoint.py +19 -19
  103. autocoder/common/file_checkpoint/manager.py +264 -48
  104. autocoder/common/file_checkpoint/test_backup.py +1 -18
  105. autocoder/common/file_checkpoint/test_manager.py +270 -1
  106. autocoder/common/file_checkpoint/test_store.py +1 -17
  107. autocoder/common/file_handler/__init__.py +23 -0
  108. autocoder/common/file_handler/active_context_handler.py +159 -0
  109. autocoder/common/file_handler/add_files_handler.py +409 -0
  110. autocoder/common/file_handler/chat_handler.py +180 -0
  111. autocoder/common/file_handler/coding_handler.py +401 -0
  112. autocoder/common/file_handler/commit_handler.py +200 -0
  113. autocoder/common/file_handler/lib_handler.py +156 -0
  114. autocoder/common/file_handler/list_files_handler.py +111 -0
  115. autocoder/common/file_handler/mcp_handler.py +268 -0
  116. autocoder/common/file_handler/models_handler.py +493 -0
  117. autocoder/common/file_handler/remove_files_handler.py +172 -0
  118. autocoder/common/file_monitor/test_file_monitor.py +307 -0
  119. autocoder/common/git_utils.py +51 -10
  120. autocoder/common/global_cancel.py +15 -6
  121. autocoder/common/ignorefiles/test_ignore_file_utils.py +1 -1
  122. autocoder/common/international/__init__.py +31 -0
  123. autocoder/common/international/demo_international.py +92 -0
  124. autocoder/common/international/message_manager.py +157 -0
  125. autocoder/common/international/messages/__init__.py +56 -0
  126. autocoder/common/international/messages/async_command_messages.py +507 -0
  127. autocoder/common/international/messages/auto_coder_messages.py +2208 -0
  128. autocoder/common/international/messages/chat_auto_coder_messages.py +1547 -0
  129. autocoder/common/international/messages/command_help_messages.py +986 -0
  130. autocoder/common/international/messages/conversation_command_messages.py +191 -0
  131. autocoder/common/international/messages/git_helper_plugin_messages.py +159 -0
  132. autocoder/common/international/messages/queue_command_messages.py +751 -0
  133. autocoder/common/international/messages/rules_command_messages.py +77 -0
  134. autocoder/common/international/messages/sdk_messages.py +1707 -0
  135. autocoder/common/international/messages/token_helper_plugin_messages.py +361 -0
  136. autocoder/common/international/messages/tool_display_messages.py +1212 -0
  137. autocoder/common/international/messages/workflow_exception_messages.py +473 -0
  138. autocoder/common/international/test_international.py +612 -0
  139. autocoder/common/linter_core/__init__.py +28 -0
  140. autocoder/common/linter_core/base_linter.py +61 -0
  141. autocoder/common/linter_core/config_loader.py +271 -0
  142. autocoder/common/linter_core/formatters/__init__.py +0 -0
  143. autocoder/common/linter_core/formatters/base_formatter.py +38 -0
  144. autocoder/common/linter_core/formatters/raw_formatter.py +17 -0
  145. autocoder/common/linter_core/linter.py +166 -0
  146. autocoder/common/linter_core/linter_factory.py +216 -0
  147. autocoder/common/linter_core/linter_manager.py +333 -0
  148. autocoder/common/linter_core/linters/__init__.py +9 -0
  149. autocoder/common/linter_core/linters/java_linter.py +342 -0
  150. autocoder/common/linter_core/linters/python_linter.py +115 -0
  151. autocoder/common/linter_core/linters/typescript_linter.py +119 -0
  152. autocoder/common/linter_core/models/__init__.py +7 -0
  153. autocoder/common/linter_core/models/lint_result.py +91 -0
  154. autocoder/common/linter_core/models.py +33 -0
  155. autocoder/common/linter_core/tests/__init__.py +3 -0
  156. autocoder/common/linter_core/tests/test_config_loader.py +323 -0
  157. autocoder/common/linter_core/tests/test_config_loading.py +308 -0
  158. autocoder/common/linter_core/tests/test_factory_manager.py +234 -0
  159. autocoder/common/linter_core/tests/test_formatters.py +147 -0
  160. autocoder/common/linter_core/tests/test_integration.py +317 -0
  161. autocoder/common/linter_core/tests/test_java_linter.py +496 -0
  162. autocoder/common/linter_core/tests/test_linters.py +265 -0
  163. autocoder/common/linter_core/tests/test_models.py +81 -0
  164. autocoder/common/linter_core/tests/verify_config_loading.py +296 -0
  165. autocoder/common/linter_core/tests/verify_fixes.py +183 -0
  166. autocoder/common/llm_friendly_package/__init__.py +31 -0
  167. autocoder/common/llm_friendly_package/base_manager.py +102 -0
  168. autocoder/common/llm_friendly_package/docs_manager.py +121 -0
  169. autocoder/common/llm_friendly_package/library_manager.py +171 -0
  170. autocoder/common/{llm_friendly_package.py → llm_friendly_package/main_manager.py} +204 -231
  171. autocoder/common/llm_friendly_package/models.py +40 -0
  172. autocoder/common/llm_friendly_package/test_llm_friendly_package.py +536 -0
  173. autocoder/common/llms/__init__.py +15 -0
  174. autocoder/common/llms/demo_error_handling.py +85 -0
  175. autocoder/common/llms/factory.py +142 -0
  176. autocoder/common/llms/manager.py +264 -0
  177. autocoder/common/llms/pricing.py +121 -0
  178. autocoder/common/llms/registry.py +288 -0
  179. autocoder/common/llms/schema.py +77 -0
  180. autocoder/common/llms/simple_demo.py +45 -0
  181. autocoder/common/llms/test_quick_model.py +116 -0
  182. autocoder/common/llms/test_remove_functionality.py +182 -0
  183. autocoder/common/llms/tests/__init__.py +1 -0
  184. autocoder/common/llms/tests/test_manager.py +330 -0
  185. autocoder/common/llms/tests/test_registry.py +364 -0
  186. autocoder/common/mcp_tools/__init__.py +62 -0
  187. autocoder/common/{mcp_tools.py → mcp_tools/executor.py} +49 -40
  188. autocoder/common/{mcp_hub.py → mcp_tools/hub.py} +42 -68
  189. autocoder/common/{mcp_server_install.py → mcp_tools/installer.py} +16 -28
  190. autocoder/common/{mcp_server.py → mcp_tools/server.py} +176 -48
  191. autocoder/common/mcp_tools/test_keyboard_interrupt.py +93 -0
  192. autocoder/common/mcp_tools/test_mcp_tools.py +391 -0
  193. autocoder/common/{mcp_server_types.py → mcp_tools/types.py} +121 -48
  194. autocoder/common/mcp_tools/verify_functionality.py +202 -0
  195. autocoder/common/model_speed_tester.py +32 -26
  196. autocoder/common/priority_directory_finder/__init__.py +142 -0
  197. autocoder/common/priority_directory_finder/examples.py +230 -0
  198. autocoder/common/priority_directory_finder/finder.py +283 -0
  199. autocoder/common/priority_directory_finder/models.py +236 -0
  200. autocoder/common/priority_directory_finder/test_priority_directory_finder.py +431 -0
  201. autocoder/common/project_scanner/__init__.py +18 -0
  202. autocoder/common/project_scanner/compat.py +77 -0
  203. autocoder/common/project_scanner/scanner.py +436 -0
  204. autocoder/common/project_tracker/__init__.py +27 -0
  205. autocoder/common/project_tracker/api.py +228 -0
  206. autocoder/common/project_tracker/demo.py +272 -0
  207. autocoder/common/project_tracker/tracker.py +487 -0
  208. autocoder/common/project_tracker/types.py +53 -0
  209. autocoder/common/pruner/__init__.py +67 -0
  210. autocoder/common/pruner/agentic_conversation_pruner.py +746 -0
  211. autocoder/common/{context_pruner.py → pruner/context_pruner.py} +137 -40
  212. autocoder/common/pruner/conversation_message_ids_api.py +386 -0
  213. autocoder/common/pruner/conversation_message_ids_manager.py +347 -0
  214. autocoder/common/pruner/conversation_message_ids_pruner.py +473 -0
  215. autocoder/common/pruner/conversation_normalizer.py +347 -0
  216. autocoder/common/{conversation_pruner.py → pruner/conversation_pruner.py} +26 -6
  217. autocoder/common/pruner/test_agentic_conversation_pruner.py +784 -0
  218. autocoder/common/pruner/test_context_pruner.py +546 -0
  219. autocoder/common/pruner/test_conversation_normalizer.py +502 -0
  220. autocoder/common/pruner/test_tool_content_detector.py +324 -0
  221. autocoder/common/pruner/tool_content_detector.py +227 -0
  222. autocoder/common/pruner/tools/__init__.py +18 -0
  223. autocoder/common/pruner/tools/query_message_ids.py +264 -0
  224. autocoder/common/pruner/tools/test_agentic_pruning_logic.py +432 -0
  225. autocoder/common/pruner/tools/test_message_ids_pruning_only.py +192 -0
  226. autocoder/common/pull_requests/__init__.py +9 -1
  227. autocoder/common/pull_requests/utils.py +122 -1
  228. autocoder/common/rag_manager/rag_manager.py +36 -40
  229. autocoder/common/rulefiles/__init__.py +53 -1
  230. autocoder/common/rulefiles/api.py +250 -0
  231. autocoder/common/rulefiles/core/__init__.py +14 -0
  232. autocoder/common/rulefiles/core/manager.py +241 -0
  233. autocoder/common/rulefiles/core/selector.py +805 -0
  234. autocoder/common/rulefiles/models/__init__.py +20 -0
  235. autocoder/common/rulefiles/models/index.py +16 -0
  236. autocoder/common/rulefiles/models/init_rule.py +18 -0
  237. autocoder/common/rulefiles/models/rule_file.py +18 -0
  238. autocoder/common/rulefiles/models/rule_relevance.py +14 -0
  239. autocoder/common/rulefiles/models/summary.py +16 -0
  240. autocoder/common/rulefiles/test_rulefiles.py +776 -0
  241. autocoder/common/rulefiles/utils/__init__.py +34 -0
  242. autocoder/common/rulefiles/utils/monitor.py +86 -0
  243. autocoder/common/rulefiles/utils/parser.py +230 -0
  244. autocoder/common/save_formatted_log.py +67 -10
  245. autocoder/common/search_replace.py +8 -1
  246. autocoder/common/search_replace_patch/__init__.py +24 -0
  247. autocoder/common/search_replace_patch/base.py +115 -0
  248. autocoder/common/search_replace_patch/manager.py +248 -0
  249. autocoder/common/search_replace_patch/patch_replacer.py +304 -0
  250. autocoder/common/search_replace_patch/similarity_replacer.py +306 -0
  251. autocoder/common/search_replace_patch/string_replacer.py +181 -0
  252. autocoder/common/search_replace_patch/tests/__init__.py +3 -0
  253. autocoder/common/search_replace_patch/tests/run_tests.py +126 -0
  254. autocoder/common/search_replace_patch/tests/test_base.py +188 -0
  255. autocoder/common/search_replace_patch/tests/test_empty_line_insert.py +233 -0
  256. autocoder/common/search_replace_patch/tests/test_integration.py +389 -0
  257. autocoder/common/search_replace_patch/tests/test_manager.py +351 -0
  258. autocoder/common/search_replace_patch/tests/test_patch_replacer.py +316 -0
  259. autocoder/common/search_replace_patch/tests/test_regex_replacer.py +306 -0
  260. autocoder/common/search_replace_patch/tests/test_similarity_replacer.py +384 -0
  261. autocoder/common/shell_commands/__init__.py +197 -0
  262. autocoder/common/shell_commands/background_process_notifier.py +346 -0
  263. autocoder/common/shell_commands/command_executor.py +1127 -0
  264. autocoder/common/shell_commands/error_recovery.py +541 -0
  265. autocoder/common/shell_commands/exceptions.py +120 -0
  266. autocoder/common/shell_commands/interactive_executor.py +476 -0
  267. autocoder/common/shell_commands/interactive_pexpect_process.py +623 -0
  268. autocoder/common/shell_commands/interactive_process.py +744 -0
  269. autocoder/common/shell_commands/interactive_session_manager.py +1014 -0
  270. autocoder/common/shell_commands/monitoring.py +529 -0
  271. autocoder/common/shell_commands/process_cleanup.py +386 -0
  272. autocoder/common/shell_commands/process_manager.py +606 -0
  273. autocoder/common/shell_commands/test_interactive_pexpect_process.py +281 -0
  274. autocoder/common/shell_commands/tests/__init__.py +6 -0
  275. autocoder/common/shell_commands/tests/conftest.py +118 -0
  276. autocoder/common/shell_commands/tests/test_background_process_notifier.py +703 -0
  277. autocoder/common/shell_commands/tests/test_command_executor.py +448 -0
  278. autocoder/common/shell_commands/tests/test_error_recovery.py +305 -0
  279. autocoder/common/shell_commands/tests/test_exceptions.py +299 -0
  280. autocoder/common/shell_commands/tests/test_execute_batch.py +588 -0
  281. autocoder/common/shell_commands/tests/test_indented_batch_commands.py +244 -0
  282. autocoder/common/shell_commands/tests/test_integration.py +664 -0
  283. autocoder/common/shell_commands/tests/test_monitoring.py +546 -0
  284. autocoder/common/shell_commands/tests/test_performance.py +632 -0
  285. autocoder/common/shell_commands/tests/test_process_cleanup.py +397 -0
  286. autocoder/common/shell_commands/tests/test_process_manager.py +606 -0
  287. autocoder/common/shell_commands/tests/test_timeout_config.py +343 -0
  288. autocoder/common/shell_commands/tests/test_timeout_manager.py +520 -0
  289. autocoder/common/shell_commands/timeout_config.py +315 -0
  290. autocoder/common/shell_commands/timeout_manager.py +352 -0
  291. autocoder/common/terminal_paste/__init__.py +14 -0
  292. autocoder/common/terminal_paste/demo.py +145 -0
  293. autocoder/common/terminal_paste/demo_paste_functionality.py +95 -0
  294. autocoder/common/terminal_paste/paste_handler.py +200 -0
  295. autocoder/common/terminal_paste/paste_manager.py +118 -0
  296. autocoder/common/terminal_paste/tests/__init__.py +1 -0
  297. autocoder/common/terminal_paste/tests/test_paste_handler.py +182 -0
  298. autocoder/common/terminal_paste/tests/test_paste_manager.py +126 -0
  299. autocoder/common/terminal_paste/utils.py +163 -0
  300. autocoder/common/test_autocoder_args.py +232 -0
  301. autocoder/common/test_env_manager.py +173 -0
  302. autocoder/common/test_env_manager_integration.py +159 -0
  303. autocoder/common/text_similarity/__init__.py +9 -0
  304. autocoder/common/text_similarity/demo.py +216 -0
  305. autocoder/common/text_similarity/examples.py +266 -0
  306. autocoder/common/text_similarity/test_text_similarity.py +306 -0
  307. autocoder/common/text_similarity/text_similarity.py +194 -0
  308. autocoder/common/text_similarity/utils.py +125 -0
  309. autocoder/common/todos/__init__.py +61 -0
  310. autocoder/common/todos/cache/__init__.py +16 -0
  311. autocoder/common/todos/cache/base_cache.py +89 -0
  312. autocoder/common/todos/cache/cache_manager.py +228 -0
  313. autocoder/common/todos/cache/memory_cache.py +225 -0
  314. autocoder/common/todos/config.py +155 -0
  315. autocoder/common/todos/exceptions.py +35 -0
  316. autocoder/common/todos/get_todo_manager.py +161 -0
  317. autocoder/common/todos/manager.py +537 -0
  318. autocoder/common/todos/models.py +239 -0
  319. autocoder/common/todos/storage/__init__.py +14 -0
  320. autocoder/common/todos/storage/base_storage.py +76 -0
  321. autocoder/common/todos/storage/file_storage.py +278 -0
  322. autocoder/common/tokens/__init__.py +15 -0
  323. autocoder/common/tokens/counter.py +44 -2
  324. autocoder/common/tools_manager/__init__.py +17 -0
  325. autocoder/common/tools_manager/examples.py +162 -0
  326. autocoder/common/tools_manager/manager.py +385 -0
  327. autocoder/common/tools_manager/models.py +39 -0
  328. autocoder/common/tools_manager/test_tools_manager.py +303 -0
  329. autocoder/common/tools_manager/utils.py +191 -0
  330. autocoder/common/v2/agent/agentic_callbacks.py +270 -0
  331. autocoder/common/v2/agent/agentic_edit.py +2729 -2052
  332. autocoder/common/v2/agent/agentic_edit_change_manager.py +474 -0
  333. autocoder/common/v2/agent/agentic_edit_tools/__init__.py +43 -2
  334. autocoder/common/v2/agent/agentic_edit_tools/ac_mod_list_tool_resolver.py +279 -0
  335. autocoder/common/v2/agent/agentic_edit_tools/ac_mod_read_tool_resolver.py +40 -0
  336. autocoder/common/v2/agent/agentic_edit_tools/ac_mod_write_tool_resolver.py +52 -0
  337. autocoder/common/v2/agent/agentic_edit_tools/ask_followup_question_tool_resolver.py +8 -0
  338. autocoder/common/v2/agent/agentic_edit_tools/background_task_tool_resolver.py +1167 -0
  339. autocoder/common/v2/agent/agentic_edit_tools/base_tool_resolver.py +2 -2
  340. autocoder/common/v2/agent/agentic_edit_tools/conversation_message_ids_read_tool_resolver.py +214 -0
  341. autocoder/common/v2/agent/agentic_edit_tools/conversation_message_ids_write_tool_resolver.py +299 -0
  342. autocoder/common/v2/agent/agentic_edit_tools/count_tokens_tool_resolver.py +290 -0
  343. autocoder/common/v2/agent/agentic_edit_tools/execute_command_tool_resolver.py +565 -30
  344. autocoder/common/v2/agent/agentic_edit_tools/execute_workflow_tool_resolver.py +485 -0
  345. autocoder/common/v2/agent/agentic_edit_tools/extract_to_text_tool_resolver.py +225 -0
  346. autocoder/common/v2/agent/agentic_edit_tools/lint_report.py +79 -0
  347. autocoder/common/v2/agent/agentic_edit_tools/linter_config_models.py +343 -0
  348. autocoder/common/v2/agent/agentic_edit_tools/linter_enabled_tool_resolver.py +189 -0
  349. autocoder/common/v2/agent/agentic_edit_tools/list_files_tool_resolver.py +169 -101
  350. autocoder/common/v2/agent/agentic_edit_tools/load_extra_document_tool_resolver.py +349 -0
  351. autocoder/common/v2/agent/agentic_edit_tools/read_file_tool_resolver.py +244 -51
  352. autocoder/common/v2/agent/agentic_edit_tools/replace_in_file_tool_resolver.py +667 -147
  353. autocoder/common/v2/agent/agentic_edit_tools/run_named_subagents_tool_resolver.py +691 -0
  354. autocoder/common/v2/agent/agentic_edit_tools/search_files_tool_resolver.py +409 -140
  355. autocoder/common/v2/agent/agentic_edit_tools/session_interactive_tool_resolver.py +115 -0
  356. autocoder/common/v2/agent/agentic_edit_tools/session_start_tool_resolver.py +190 -0
  357. autocoder/common/v2/agent/agentic_edit_tools/session_stop_tool_resolver.py +76 -0
  358. autocoder/common/v2/agent/agentic_edit_tools/test_write_to_file_tool_resolver.py +209 -194
  359. autocoder/common/v2/agent/agentic_edit_tools/todo_read_tool_resolver.py +135 -0
  360. autocoder/common/v2/agent/agentic_edit_tools/todo_write_tool_resolver.py +328 -0
  361. autocoder/common/v2/agent/agentic_edit_tools/use_mcp_tool_resolver.py +2 -2
  362. autocoder/common/v2/agent/agentic_edit_tools/web_crawl_tool_resolver.py +557 -0
  363. autocoder/common/v2/agent/agentic_edit_tools/web_search_tool_resolver.py +600 -0
  364. autocoder/common/v2/agent/agentic_edit_tools/write_to_file_tool_resolver.py +56 -121
  365. autocoder/common/v2/agent/agentic_edit_types.py +386 -10
  366. autocoder/common/v2/agent/runner/__init__.py +31 -0
  367. autocoder/common/v2/agent/runner/base_runner.py +92 -0
  368. autocoder/common/v2/agent/runner/file_based_event_runner.py +217 -0
  369. autocoder/common/v2/agent/runner/sdk_runner.py +182 -0
  370. autocoder/common/v2/agent/runner/terminal_runner.py +396 -0
  371. autocoder/common/v2/agent/runner/tool_display.py +589 -0
  372. autocoder/common/v2/agent/test_agentic_callbacks.py +265 -0
  373. autocoder/common/v2/agent/test_agentic_edit.py +194 -0
  374. autocoder/common/v2/agent/tool_caller/__init__.py +24 -0
  375. autocoder/common/v2/agent/tool_caller/default_tool_resolver_map.py +135 -0
  376. autocoder/common/v2/agent/tool_caller/integration_test.py +172 -0
  377. autocoder/common/v2/agent/tool_caller/plugins/__init__.py +14 -0
  378. autocoder/common/v2/agent/tool_caller/plugins/base_plugin.py +126 -0
  379. autocoder/common/v2/agent/tool_caller/plugins/examples/__init__.py +13 -0
  380. autocoder/common/v2/agent/tool_caller/plugins/examples/logging_plugin.py +164 -0
  381. autocoder/common/v2/agent/tool_caller/plugins/examples/security_filter_plugin.py +198 -0
  382. autocoder/common/v2/agent/tool_caller/plugins/plugin_interface.py +141 -0
  383. autocoder/common/v2/agent/tool_caller/test_tool_caller.py +278 -0
  384. autocoder/common/v2/agent/tool_caller/tool_call_plugin_manager.py +331 -0
  385. autocoder/common/v2/agent/tool_caller/tool_caller.py +337 -0
  386. autocoder/common/v2/agent/tool_caller/usage_example.py +193 -0
  387. autocoder/common/v2/code_agentic_editblock_manager.py +4 -4
  388. autocoder/common/v2/code_auto_generate.py +136 -78
  389. autocoder/common/v2/code_auto_generate_diff.py +135 -79
  390. autocoder/common/v2/code_auto_generate_editblock.py +174 -99
  391. autocoder/common/v2/code_auto_generate_strict_diff.py +151 -71
  392. autocoder/common/v2/code_auto_merge.py +1 -1
  393. autocoder/common/v2/code_auto_merge_editblock.py +13 -1
  394. autocoder/common/v2/code_diff_manager.py +3 -3
  395. autocoder/common/v2/code_editblock_manager.py +4 -14
  396. autocoder/common/v2/code_manager.py +1 -1
  397. autocoder/common/v2/code_strict_diff_manager.py +2 -2
  398. autocoder/common/wrap_llm_hint/__init__.py +10 -0
  399. autocoder/common/wrap_llm_hint/test_wrap_llm_hint.py +1067 -0
  400. autocoder/common/wrap_llm_hint/utils.py +432 -0
  401. autocoder/common/wrap_llm_hint/wrap_llm_hint.py +323 -0
  402. autocoder/completer/__init__.py +8 -0
  403. autocoder/completer/command_completer_v2.py +1051 -0
  404. autocoder/default_project/__init__.py +501 -0
  405. autocoder/dispacher/__init__.py +4 -12
  406. autocoder/dispacher/actions/action.py +165 -7
  407. autocoder/dispacher/actions/plugins/action_regex_project.py +2 -2
  408. autocoder/index/entry.py +117 -125
  409. autocoder/{agent → index/filter}/agentic_filter.py +323 -334
  410. autocoder/index/filter/normal_filter.py +5 -11
  411. autocoder/index/filter/quick_filter.py +1 -1
  412. autocoder/index/index.py +36 -9
  413. autocoder/index/tests/__init__.py +1 -0
  414. autocoder/index/tests/run_tests.py +195 -0
  415. autocoder/index/tests/test_entry.py +303 -0
  416. autocoder/index/tests/test_index_manager.py +314 -0
  417. autocoder/index/tests/test_module_integration.py +300 -0
  418. autocoder/index/tests/test_symbols_utils.py +183 -0
  419. autocoder/inner/__init__.py +4 -0
  420. autocoder/inner/agentic.py +932 -0
  421. autocoder/inner/async_command_handler.py +992 -0
  422. autocoder/inner/conversation_command_handlers.py +623 -0
  423. autocoder/inner/merge_command_handler.py +213 -0
  424. autocoder/inner/queue_command_handler.py +684 -0
  425. autocoder/models.py +95 -266
  426. autocoder/plugins/git_helper_plugin.py +31 -29
  427. autocoder/plugins/token_helper_plugin.py +156 -37
  428. autocoder/pyproject/__init__.py +32 -29
  429. autocoder/rag/agentic_rag.py +215 -75
  430. autocoder/rag/cache/simple_cache.py +1 -2
  431. autocoder/rag/loaders/image_loader.py +1 -1
  432. autocoder/rag/long_context_rag.py +42 -26
  433. autocoder/rag/qa_conversation_strategy.py +1 -1
  434. autocoder/rag/terminal/__init__.py +17 -0
  435. autocoder/rag/terminal/args.py +581 -0
  436. autocoder/rag/terminal/bootstrap.py +61 -0
  437. autocoder/rag/terminal/command_handlers.py +653 -0
  438. autocoder/rag/terminal/formatters/__init__.py +20 -0
  439. autocoder/rag/terminal/formatters/base.py +70 -0
  440. autocoder/rag/terminal/formatters/json_format.py +66 -0
  441. autocoder/rag/terminal/formatters/stream_json.py +95 -0
  442. autocoder/rag/terminal/formatters/text.py +28 -0
  443. autocoder/rag/terminal/init.py +120 -0
  444. autocoder/rag/terminal/utils.py +106 -0
  445. autocoder/rag/test_agentic_rag.py +389 -0
  446. autocoder/rag/test_doc_filter.py +3 -3
  447. autocoder/rag/test_long_context_rag.py +1 -1
  448. autocoder/rag/test_token_limiter.py +517 -10
  449. autocoder/rag/token_counter.py +3 -0
  450. autocoder/rag/token_limiter.py +19 -15
  451. autocoder/rag/tools/__init__.py +26 -2
  452. autocoder/rag/tools/bochaai_example.py +343 -0
  453. autocoder/rag/tools/bochaai_sdk.py +541 -0
  454. autocoder/rag/tools/metaso_example.py +268 -0
  455. autocoder/rag/tools/metaso_sdk.py +417 -0
  456. autocoder/rag/tools/recall_tool.py +28 -7
  457. autocoder/rag/tools/run_integration_tests.py +204 -0
  458. autocoder/rag/tools/test_all_providers.py +318 -0
  459. autocoder/rag/tools/test_bochaai_integration.py +482 -0
  460. autocoder/rag/tools/test_final_integration.py +215 -0
  461. autocoder/rag/tools/test_metaso_integration.py +424 -0
  462. autocoder/rag/tools/test_metaso_real.py +171 -0
  463. autocoder/rag/tools/test_web_crawl_tool.py +639 -0
  464. autocoder/rag/tools/test_web_search_tool.py +509 -0
  465. autocoder/rag/tools/todo_read_tool.py +202 -0
  466. autocoder/rag/tools/todo_write_tool.py +412 -0
  467. autocoder/rag/tools/web_crawl_tool.py +634 -0
  468. autocoder/rag/tools/web_search_tool.py +558 -0
  469. autocoder/rag/tools/web_tools_example.py +119 -0
  470. autocoder/rag/types.py +16 -0
  471. autocoder/rag/variable_holder.py +4 -2
  472. autocoder/rags.py +86 -79
  473. autocoder/regexproject/__init__.py +23 -21
  474. autocoder/run_context.py +9 -0
  475. autocoder/sdk/__init__.py +50 -161
  476. autocoder/sdk/api.py +370 -0
  477. autocoder/sdk/async_runner/__init__.py +26 -0
  478. autocoder/sdk/async_runner/async_executor.py +650 -0
  479. autocoder/sdk/async_runner/async_handler.py +356 -0
  480. autocoder/sdk/async_runner/markdown_processor.py +595 -0
  481. autocoder/sdk/async_runner/task_metadata.py +284 -0
  482. autocoder/sdk/async_runner/worktree_manager.py +438 -0
  483. autocoder/sdk/cli/__init__.py +2 -5
  484. autocoder/sdk/cli/formatters.py +28 -204
  485. autocoder/sdk/cli/handlers.py +77 -44
  486. autocoder/sdk/cli/main.py +158 -170
  487. autocoder/sdk/cli/options.py +95 -22
  488. autocoder/sdk/constants.py +139 -51
  489. autocoder/sdk/core/auto_coder_core.py +484 -267
  490. autocoder/sdk/core/bridge.py +298 -118
  491. autocoder/sdk/exceptions.py +18 -12
  492. autocoder/sdk/formatters/__init__.py +19 -0
  493. autocoder/sdk/formatters/input.py +64 -0
  494. autocoder/sdk/formatters/output.py +247 -0
  495. autocoder/sdk/formatters/stream.py +54 -0
  496. autocoder/sdk/models/__init__.py +6 -5
  497. autocoder/sdk/models/options.py +55 -18
  498. autocoder/sdk/utils/formatters.py +27 -195
  499. autocoder/suffixproject/__init__.py +28 -25
  500. autocoder/terminal/__init__.py +14 -0
  501. autocoder/terminal/app.py +454 -0
  502. autocoder/terminal/args.py +32 -0
  503. autocoder/terminal/bootstrap.py +178 -0
  504. autocoder/terminal/command_processor.py +521 -0
  505. autocoder/terminal/command_registry.py +57 -0
  506. autocoder/terminal/help.py +97 -0
  507. autocoder/terminal/tasks/__init__.py +5 -0
  508. autocoder/terminal/tasks/background.py +77 -0
  509. autocoder/terminal/tasks/task_event.py +70 -0
  510. autocoder/terminal/ui/__init__.py +13 -0
  511. autocoder/terminal/ui/completer.py +268 -0
  512. autocoder/terminal/ui/keybindings.py +75 -0
  513. autocoder/terminal/ui/session.py +41 -0
  514. autocoder/terminal/ui/toolbar.py +64 -0
  515. autocoder/terminal/utils/__init__.py +13 -0
  516. autocoder/terminal/utils/errors.py +18 -0
  517. autocoder/terminal/utils/paths.py +19 -0
  518. autocoder/terminal/utils/shell.py +43 -0
  519. autocoder/terminal_v3/__init__.py +10 -0
  520. autocoder/terminal_v3/app.py +201 -0
  521. autocoder/terminal_v3/handlers/__init__.py +5 -0
  522. autocoder/terminal_v3/handlers/command_handler.py +131 -0
  523. autocoder/terminal_v3/models/__init__.py +6 -0
  524. autocoder/terminal_v3/models/conversation_buffer.py +214 -0
  525. autocoder/terminal_v3/models/message.py +50 -0
  526. autocoder/terminal_v3/models/tool_display.py +247 -0
  527. autocoder/terminal_v3/ui/__init__.py +7 -0
  528. autocoder/terminal_v3/ui/keybindings.py +56 -0
  529. autocoder/terminal_v3/ui/layout.py +141 -0
  530. autocoder/terminal_v3/ui/styles.py +43 -0
  531. autocoder/tsproject/__init__.py +23 -23
  532. autocoder/utils/auto_coder_utils/chat_stream_out.py +1 -1
  533. autocoder/utils/llms.py +88 -80
  534. autocoder/utils/math_utils.py +101 -0
  535. autocoder/utils/model_provider_selector.py +16 -4
  536. autocoder/utils/operate_config_api.py +33 -5
  537. autocoder/utils/thread_utils.py +2 -2
  538. autocoder/version.py +4 -2
  539. autocoder/workflow_agents/__init__.py +84 -0
  540. autocoder/workflow_agents/agent.py +143 -0
  541. autocoder/workflow_agents/exceptions.py +573 -0
  542. autocoder/workflow_agents/executor.py +489 -0
  543. autocoder/workflow_agents/loader.py +737 -0
  544. autocoder/workflow_agents/runner.py +267 -0
  545. autocoder/workflow_agents/types.py +172 -0
  546. autocoder/workflow_agents/utils.py +434 -0
  547. autocoder/workflow_agents/workflow_manager.py +211 -0
  548. auto_coder-0.1.400.dist-info/METADATA +0 -396
  549. auto_coder-0.1.400.dist-info/RECORD +0 -425
  550. auto_coder-0.1.400.dist-info/licenses/LICENSE +0 -201
  551. autocoder/auto_coder_server.py +0 -672
  552. autocoder/benchmark.py +0 -138
  553. autocoder/common/ac_style_command_parser/example.py +0 -7
  554. autocoder/common/cleaner.py +0 -31
  555. autocoder/common/command_completer_v2.py +0 -615
  556. autocoder/common/directory_cache/__init__.py +0 -1
  557. autocoder/common/directory_cache/cache.py +0 -192
  558. autocoder/common/directory_cache/test_cache.py +0 -190
  559. autocoder/common/file_checkpoint/examples.py +0 -217
  560. autocoder/common/llm_friendly_package_example.py +0 -138
  561. autocoder/common/llm_friendly_package_test.py +0 -63
  562. autocoder/common/pull_requests/test_module.py +0 -1
  563. autocoder/common/rulefiles/autocoderrules_utils.py +0 -484
  564. autocoder/common/text.py +0 -30
  565. autocoder/common/v2/agent/agentic_edit_tools/list_package_info_tool_resolver.py +0 -42
  566. autocoder/common/v2/agent/agentic_edit_tools/test_execute_command_tool_resolver.py +0 -70
  567. autocoder/common/v2/agent/agentic_edit_tools/test_search_files_tool_resolver.py +0 -163
  568. autocoder/common/v2/agent/agentic_tool_display.py +0 -183
  569. autocoder/plugins/dynamic_completion_example.py +0 -148
  570. autocoder/plugins/sample_plugin.py +0 -160
  571. autocoder/sdk/cli/__main__.py +0 -26
  572. autocoder/sdk/cli/completion_wrapper.py +0 -38
  573. autocoder/sdk/cli/install_completion.py +0 -301
  574. autocoder/sdk/models/messages.py +0 -209
  575. autocoder/sdk/session/__init__.py +0 -32
  576. autocoder/sdk/session/session.py +0 -106
  577. autocoder/sdk/session/session_manager.py +0 -56
  578. {auto_coder-0.1.400.dist-info → auto_coder-2.0.0.dist-info}/top_level.txt +0 -0
  579. /autocoder/{sdk/example.py → common/agent_query_queue/__init__.py} +0 -0
@@ -0,0 +1,588 @@
1
+ """
2
+ Tests for batch command execution functionality.
3
+
4
+ This module tests the execute_commands and execute_batch functions
5
+ for both parallel and serial execution modes.
6
+ """
7
+
8
+ import pytest
9
+ import time
10
+ import platform
11
+ from typing import List, Dict, Any
12
+ import json
13
+
14
+ from ..command_executor import CommandExecutor, execute_commands
15
+ from ..timeout_config import TimeoutConfig
16
+ from ..exceptions import CommandTimeoutError, CommandExecutionError
17
+
18
+
19
+ class TestExecuteBatch:
20
+ """Test cases for execute_batch method."""
21
+
22
+ def setup_method(self):
23
+ """Set up test fixtures."""
24
+ self.config = TimeoutConfig(default_timeout=10.0)
25
+ self.executor = CommandExecutor(self.config, verbose=False)
26
+
27
+ def teardown_method(self):
28
+ """Clean up after tests."""
29
+ self.executor.cleanup()
30
+
31
+ def test_empty_commands_list(self):
32
+ """Test execution with empty commands list."""
33
+ results = self.executor.execute_batch([])
34
+ assert results == []
35
+
36
+ def test_single_command_serial(self):
37
+ """Test executing a single command serially."""
38
+ if platform.system() == "Windows":
39
+ commands = ["echo Hello"]
40
+ else:
41
+ commands = ["echo 'Hello'"]
42
+
43
+ results = self.executor.execute_batch(commands, parallel=False)
44
+
45
+ assert len(results) == 1
46
+ assert results[0]["index"] == 0
47
+ assert results[0]["exit_code"] == 0
48
+ assert "Hello" in results[0]["output"]
49
+ assert results[0]["timed_out"] is False
50
+
51
+ def test_multiple_commands_serial(self):
52
+ """Test executing multiple commands serially."""
53
+ if platform.system() == "Windows":
54
+ commands = ["echo One", "echo Two", "echo Three"]
55
+ else:
56
+ commands = ["echo 'One'", "echo 'Two'", "echo 'Three'"]
57
+
58
+ start_time = time.time()
59
+ results = self.executor.execute_batch(commands, parallel=False)
60
+ duration = time.time() - start_time
61
+
62
+ assert len(results) == 3
63
+ for i, result in enumerate(results):
64
+ assert result["index"] == i
65
+ assert result["exit_code"] == 0
66
+ assert result["timed_out"] is False
67
+
68
+ assert "One" in results[0]["output"]
69
+ assert "Two" in results[1]["output"]
70
+ assert "Three" in results[2]["output"]
71
+
72
+ def test_multiple_commands_parallel(self):
73
+ """Test executing multiple commands in parallel."""
74
+ if platform.system() == "Windows":
75
+ commands = ["echo Alpha", "echo Beta", "echo Gamma"]
76
+ else:
77
+ commands = ["echo 'Alpha'", "echo 'Beta'", "echo 'Gamma'"]
78
+
79
+ start_time = time.time()
80
+ results = self.executor.execute_batch(commands, parallel=True)
81
+ duration = time.time() - start_time
82
+
83
+ assert len(results) == 3
84
+
85
+ # Results should maintain order even when executed in parallel
86
+ assert results[0]["index"] == 0
87
+ assert results[1]["index"] == 1
88
+ assert results[2]["index"] == 2
89
+
90
+ assert "Alpha" in results[0]["output"]
91
+ assert "Beta" in results[1]["output"]
92
+ assert "Gamma" in results[2]["output"]
93
+
94
+ def test_command_failure_serial(self):
95
+ """Test handling of failed commands in serial execution."""
96
+ if platform.system() == "Windows":
97
+ commands = ["echo Success", "exit 1", "echo After"]
98
+ else:
99
+ commands = ["echo Success", "false", "echo After"]
100
+
101
+ results = self.executor.execute_batch(commands, parallel=False)
102
+
103
+ assert len(results) == 3
104
+ assert results[0]["exit_code"] == 0
105
+ assert results[1]["exit_code"] != 0
106
+ assert results[2]["exit_code"] == 0 # Should continue after failure
107
+
108
+ def test_command_failure_parallel(self):
109
+ """Test handling of failed commands in parallel execution."""
110
+ if platform.system() == "Windows":
111
+ commands = ["echo OK1", "exit 1", "echo OK2"]
112
+ else:
113
+ commands = ["echo OK1", "false", "echo OK2"]
114
+
115
+ results = self.executor.execute_batch(commands, parallel=True)
116
+
117
+ assert len(results) == 3
118
+ assert results[0]["exit_code"] == 0
119
+ assert results[1]["exit_code"] != 0
120
+ assert results[2]["exit_code"] == 0
121
+
122
+ def test_per_command_timeout(self):
123
+ """Test per-command timeout in serial execution."""
124
+ if platform.system() == "Windows":
125
+ commands = ["echo Quick", "ping -n 10 127.0.0.1", "echo Done"]
126
+ else:
127
+ commands = ["echo Quick", "sleep 10", "echo Done"]
128
+
129
+ results = self.executor.execute_batch(
130
+ commands,
131
+ per_command_timeout=0.5,
132
+ parallel=False
133
+ )
134
+
135
+ assert len(results) == 3
136
+ assert results[0]["exit_code"] == 0
137
+ assert results[0]["timed_out"] is False
138
+
139
+ assert results[1]["exit_code"] == -1
140
+ assert results[1]["timed_out"] is True
141
+ assert "timed out" in results[1]["error"].lower()
142
+
143
+ # Should continue after timeout
144
+ assert results[2]["exit_code"] == 0
145
+ assert results[2]["timed_out"] is False
146
+
147
+ def test_overall_timeout_serial(self):
148
+ """Test overall timeout in serial execution."""
149
+ if platform.system() == "Windows":
150
+ commands = ["ping -n 2 127.0.0.1"] * 5
151
+ else:
152
+ commands = ["sleep 1"] * 5
153
+
154
+ start_time = time.time()
155
+ results = self.executor.execute_batch(
156
+ commands,
157
+ timeout=2.0, # Overall timeout shorter than total execution
158
+ parallel=False
159
+ )
160
+ duration = time.time() - start_time
161
+
162
+ assert duration < 3.0 # Should timeout before all complete
163
+
164
+ # Some commands should have executed
165
+ executed_count = sum(1 for r in results if not r["timed_out"])
166
+ timed_out_count = sum(1 for r in results if r["timed_out"])
167
+
168
+ assert executed_count > 0
169
+ assert timed_out_count > 0
170
+ assert len(results) == 5
171
+
172
+ def test_overall_timeout_parallel(self):
173
+ """Test overall timeout in parallel execution."""
174
+ if platform.system() == "Windows":
175
+ commands = ["ping -n 5 127.0.0.1"] * 4
176
+ else:
177
+ commands = ["sleep 3"] * 4
178
+
179
+ start_time = time.time()
180
+ results = self.executor.execute_batch(
181
+ commands,
182
+ timeout=1.0, # Overall timeout
183
+ parallel=True
184
+ )
185
+ duration = time.time() - start_time
186
+
187
+ assert duration < 3.0 # Should timeout quickly (allowing for cleanup time)
188
+ assert len(results) == 4
189
+
190
+ # All should timeout since they're running in parallel
191
+ for result in results:
192
+ assert result["timed_out"] is True
193
+
194
+ def test_mixed_success_and_failure(self):
195
+ """Test batch with mix of successful and failing commands."""
196
+ if platform.system() == "Windows":
197
+ commands = [
198
+ "echo Start",
199
+ "exit 0",
200
+ "exit 1",
201
+ "ping -n 10 127.0.0.1", # Will timeout
202
+ "echo End"
203
+ ]
204
+ else:
205
+ commands = [
206
+ "echo Start",
207
+ "true",
208
+ "false",
209
+ "sleep 10", # Will timeout
210
+ "echo End"
211
+ ]
212
+
213
+ results = self.executor.execute_batch(
214
+ commands,
215
+ per_command_timeout=0.5,
216
+ parallel=False
217
+ )
218
+
219
+ assert len(results) == 5
220
+ assert results[0]["exit_code"] == 0 # echo Start
221
+ assert results[1]["exit_code"] == 0 # exit 0 / true
222
+ assert results[2]["exit_code"] != 0 # exit 1 / false
223
+ assert results[3]["timed_out"] is True # timeout
224
+ assert results[4]["exit_code"] == 0 # echo End
225
+
226
+ def test_result_structure(self):
227
+ """Test that results have the expected structure."""
228
+ commands = ["echo Test"]
229
+ results = self.executor.execute_batch(commands)
230
+
231
+ assert len(results) == 1
232
+ result = results[0]
233
+
234
+ # Check all expected fields
235
+ assert "command" in result
236
+ assert "index" in result
237
+ assert "exit_code" in result
238
+ assert "output" in result
239
+ assert "error" in result
240
+ assert "timed_out" in result
241
+ assert "duration" in result
242
+ assert "start_time" in result
243
+ assert "end_time" in result
244
+
245
+ # Check types
246
+ assert isinstance(result["command"], str)
247
+ assert isinstance(result["index"], int)
248
+ assert isinstance(result["exit_code"], int)
249
+ assert isinstance(result["output"], str)
250
+ assert result["error"] is None or isinstance(result["error"], str)
251
+ assert isinstance(result["timed_out"], bool)
252
+ assert isinstance(result["duration"], float)
253
+ assert isinstance(result["start_time"], float)
254
+ assert isinstance(result["end_time"], float)
255
+
256
+ def test_command_ordering_preserved(self):
257
+ """Test that command order is preserved in results."""
258
+ commands = [f"echo 'Command {i}'" for i in range(10)]
259
+
260
+ # Test both serial and parallel
261
+ for parallel in [False, True]:
262
+ results = self.executor.execute_batch(commands, parallel=parallel)
263
+
264
+ assert len(results) == 10
265
+ for i, result in enumerate(results):
266
+ assert result["index"] == i
267
+ assert f"Command {i}" in result["output"]
268
+
269
+
270
+ class TestExecuteCommands:
271
+ """Test cases for the convenience execute_commands function."""
272
+
273
+ def test_basic_parallel_execution(self):
274
+ """Test basic parallel execution with convenience function."""
275
+ if platform.system() == "Windows":
276
+ commands = ["echo A", "echo B", "echo C"]
277
+ else:
278
+ commands = ["echo A", "echo B", "echo C"]
279
+
280
+ results = execute_commands(commands, parallel=True)
281
+
282
+ assert len(results) == 3
283
+ assert all(r["exit_code"] == 0 for r in results)
284
+ assert "A" in results[0]["output"]
285
+ assert "B" in results[1]["output"]
286
+ assert "C" in results[2]["output"]
287
+
288
+ def test_basic_serial_execution(self):
289
+ """Test basic serial execution with convenience function."""
290
+ commands = ["echo 1", "echo 2", "echo 3"]
291
+
292
+ results = execute_commands(commands, parallel=False)
293
+
294
+ assert len(results) == 3
295
+ assert all(r["exit_code"] == 0 for r in results)
296
+
297
+ def test_with_timeout_options(self):
298
+ """Test convenience function with timeout options."""
299
+ if platform.system() == "Windows":
300
+ commands = ["echo Fast", "ping -n 5 127.0.0.1"]
301
+ else:
302
+ commands = ["echo Fast", "sleep 3"]
303
+
304
+ results = execute_commands(
305
+ commands,
306
+ per_command_timeout=1.0,
307
+ parallel=False
308
+ )
309
+
310
+ assert results[0]["timed_out"] is False
311
+ assert results[1]["timed_out"] is True
312
+
313
+ def test_with_working_directory(self):
314
+ """Test execution with custom working directory."""
315
+ import tempfile
316
+ import os
317
+
318
+ with tempfile.TemporaryDirectory() as temp_dir:
319
+ # Create a test file in temp directory
320
+ test_file = os.path.join(temp_dir, "test.txt")
321
+ with open(test_file, "w") as f:
322
+ f.write("test content")
323
+
324
+ if platform.system() == "Windows":
325
+ commands = ["dir", "type test.txt"]
326
+ else:
327
+ commands = ["ls", "cat test.txt"]
328
+
329
+ results = execute_commands(commands, cwd=temp_dir, parallel=False)
330
+
331
+ assert all(r["exit_code"] == 0 for r in results)
332
+ assert "test.txt" in results[0]["output"]
333
+ assert "test content" in results[1]["output"]
334
+
335
+ def test_empty_commands(self):
336
+ """Test with empty command list."""
337
+ results = execute_commands([])
338
+ assert results == []
339
+
340
+ def test_verbose_mode(self):
341
+ """Test verbose mode doesn't break functionality."""
342
+ commands = ["echo Verbose"]
343
+ results = execute_commands(commands, verbose=True)
344
+
345
+ assert len(results) == 1
346
+ assert results[0]["exit_code"] == 0
347
+
348
+
349
+ class TestBatchExecutionEdgeCases:
350
+ """Test edge cases for batch execution."""
351
+
352
+ def test_very_large_batch(self):
353
+ """Test execution of a large number of commands."""
354
+ # Create 50 simple commands
355
+ commands = [f"echo 'Item {i}'" for i in range(50)]
356
+
357
+ results = execute_commands(commands, parallel=True)
358
+
359
+ assert len(results) == 50
360
+ assert all(r["exit_code"] == 0 for r in results)
361
+
362
+ def test_invalid_commands(self):
363
+ """Test batch with invalid commands."""
364
+ commands = [
365
+ "echo Valid",
366
+ "this_command_does_not_exist_12345",
367
+ "echo Also Valid"
368
+ ]
369
+
370
+ results = execute_commands(commands, parallel=False)
371
+
372
+ assert len(results) == 3
373
+ assert results[0]["exit_code"] == 0
374
+ assert results[1]["exit_code"] != 0
375
+ assert results[2]["exit_code"] == 0
376
+
377
+ def test_mixed_command_types(self):
378
+ """Test batch with different command formats."""
379
+ commands = [
380
+ "echo String command",
381
+ ["echo", "List", "command"],
382
+ "echo Another string"
383
+ ]
384
+
385
+ results = execute_commands(commands, parallel=False)
386
+
387
+ assert len(results) == 3
388
+ assert all(r["exit_code"] == 0 for r in results)
389
+ assert "String command" in results[0]["output"]
390
+ assert "List command" in results[1]["output"]
391
+ assert "Another string" in results[2]["output"]
392
+
393
+
394
+ class TestExecuteBatchViaResolver:
395
+ """Test cases for batch execution via ExecuteCommandToolResolver."""
396
+
397
+ def test_json_array_batch(self):
398
+ """Test batch execution using JSON array format."""
399
+ from autocoder.common.v2.agent.agentic_edit_types import ExecuteCommandTool
400
+ from autocoder.common.v2.agent.agentic_edit_tools.execute_command_tool_resolver import ExecuteCommandToolResolver
401
+ from autocoder.common import AutoCoderArgs
402
+
403
+ # Create tool with JSON array
404
+ tool = ExecuteCommandTool(
405
+ command='["echo Hello", "echo World", "echo Done"]',
406
+ requires_approval=False,
407
+ timeout=30
408
+ )
409
+
410
+ args = AutoCoderArgs(
411
+ source_dir=".",
412
+ enable_agentic_dangerous_command_check=False,
413
+ enable_agentic_auto_approve=True,
414
+ use_shell_commands=True
415
+ )
416
+
417
+ resolver = ExecuteCommandToolResolver(None, tool, args)
418
+ result = resolver.resolve()
419
+
420
+ assert result.success is True
421
+ assert 'batch_results' in result.content
422
+ assert len(result.content['batch_results']) == 3
423
+ assert all(r['exit_code'] == 0 for r in result.content['batch_results'])
424
+
425
+ def test_yaml_serial_mode(self):
426
+ """Test batch execution using YAML format with serial mode."""
427
+ from autocoder.common.v2.agent.agentic_edit_types import ExecuteCommandTool
428
+ from autocoder.common.v2.agent.agentic_edit_tools.execute_command_tool_resolver import ExecuteCommandToolResolver
429
+ from autocoder.common import AutoCoderArgs
430
+
431
+ yaml_command = """mode: serial
432
+ cmds:
433
+ - echo "Step 1"
434
+ - echo "Step 2"
435
+ - echo "Step 3"
436
+ """
437
+
438
+ tool = ExecuteCommandTool(
439
+ command=yaml_command,
440
+ requires_approval=False,
441
+ timeout=30
442
+ )
443
+
444
+ args = AutoCoderArgs(
445
+ source_dir=".",
446
+ enable_agentic_dangerous_command_check=False,
447
+ enable_agentic_auto_approve=True,
448
+ use_shell_commands=True
449
+ )
450
+
451
+ resolver = ExecuteCommandToolResolver(None, tool, args)
452
+ result = resolver.resolve()
453
+
454
+ assert result.success is True
455
+ assert result.content['summary']['execution_mode'] == 'serial'
456
+ assert result.content['summary']['total'] == 3
457
+
458
+ def test_newline_separated_batch(self):
459
+ """Test batch execution using newline-separated format."""
460
+ from autocoder.common.v2.agent.agentic_edit_types import ExecuteCommandTool
461
+ from autocoder.common.v2.agent.agentic_edit_tools.execute_command_tool_resolver import ExecuteCommandToolResolver
462
+ from autocoder.common import AutoCoderArgs
463
+
464
+ commands = """echo "Line 1"
465
+ echo "Line 2"
466
+ echo "Line 3"
467
+ """
468
+
469
+ tool = ExecuteCommandTool(
470
+ command=commands,
471
+ requires_approval=False,
472
+ timeout=30
473
+ )
474
+
475
+ args = AutoCoderArgs(
476
+ source_dir=".",
477
+ enable_agentic_dangerous_command_check=False,
478
+ enable_agentic_auto_approve=True,
479
+ use_shell_commands=True
480
+ )
481
+
482
+ resolver = ExecuteCommandToolResolver(None, tool, args)
483
+ result = resolver.resolve()
484
+
485
+ assert result.success is True
486
+ # In newline separated mode, it's treated as single command output
487
+ if isinstance(result.content, str):
488
+ # Single command output
489
+ assert "Line 1" in result.content
490
+ assert "Line 2" in result.content
491
+ assert "Line 3" in result.content
492
+ else:
493
+ # Batch mode
494
+ assert 'batch_results' in result.content
495
+ assert len(result.content['batch_results']) == 3
496
+
497
+ def test_single_command_fallback(self):
498
+ """Test that single commands still work normally."""
499
+ from autocoder.common.v2.agent.agentic_edit_types import ExecuteCommandTool
500
+ from autocoder.common.v2.agent.agentic_edit_tools.execute_command_tool_resolver import ExecuteCommandToolResolver
501
+ from autocoder.common import AutoCoderArgs
502
+
503
+ tool = ExecuteCommandTool(
504
+ command='echo "Single command"',
505
+ requires_approval=False,
506
+ timeout=30
507
+ )
508
+
509
+ args = AutoCoderArgs(
510
+ source_dir=".",
511
+ enable_agentic_dangerous_command_check=False,
512
+ enable_agentic_auto_approve=True,
513
+ use_shell_commands=True
514
+ )
515
+
516
+ resolver = ExecuteCommandToolResolver(None, tool, args)
517
+ result = resolver.resolve()
518
+
519
+ assert result.success is True
520
+ # Single command should not have batch_results
521
+ assert 'batch_results' not in result.content or result.content is None or isinstance(result.content, str)
522
+
523
+ def test_serial_with_comment(self):
524
+ """Test serial execution with comment prefix."""
525
+ from autocoder.common.v2.agent.agentic_edit_types import ExecuteCommandTool
526
+ from autocoder.common.v2.agent.agentic_edit_tools.execute_command_tool_resolver import ExecuteCommandToolResolver
527
+ from autocoder.common import AutoCoderArgs
528
+
529
+ commands = """# serial
530
+ echo "First"
531
+ echo "Second"
532
+ echo "Third"
533
+ """
534
+
535
+ tool = ExecuteCommandTool(
536
+ command=commands,
537
+ requires_approval=False,
538
+ timeout=30
539
+ )
540
+
541
+ args = AutoCoderArgs(
542
+ source_dir=".",
543
+ enable_agentic_dangerous_command_check=False,
544
+ enable_agentic_auto_approve=True,
545
+ use_shell_commands=True
546
+ )
547
+
548
+ resolver = ExecuteCommandToolResolver(None, tool, args)
549
+ result = resolver.resolve()
550
+
551
+ assert result.success is True
552
+ assert result.content['summary']['execution_mode'] == 'serial'
553
+
554
+ def test_batch_with_failure(self):
555
+ """Test batch execution with some commands failing."""
556
+ from autocoder.common.v2.agent.agentic_edit_types import ExecuteCommandTool
557
+ from autocoder.common.v2.agent.agentic_edit_tools.execute_command_tool_resolver import ExecuteCommandToolResolver
558
+ from autocoder.common import AutoCoderArgs
559
+
560
+ if platform.system() == "Windows":
561
+ commands = ['echo "Success"', 'exit 1', 'echo "After failure"']
562
+ else:
563
+ commands = ['echo "Success"', 'false', 'echo "After failure"']
564
+
565
+ tool = ExecuteCommandTool(
566
+ command=json.dumps(commands),
567
+ requires_approval=False,
568
+ timeout=30
569
+ )
570
+
571
+ args = AutoCoderArgs(
572
+ source_dir=".",
573
+ enable_agentic_dangerous_command_check=False,
574
+ enable_agentic_auto_approve=True,
575
+ use_shell_commands=True
576
+ )
577
+
578
+ resolver = ExecuteCommandToolResolver(None, tool, args)
579
+ result = resolver.resolve()
580
+
581
+ # Overall result should be False due to failure
582
+ assert result.success is False
583
+ assert result.content['summary']['failed'] == 1
584
+ assert result.content['summary']['successful'] == 2
585
+
586
+
587
+ if __name__ == "__main__":
588
+ pytest.main([__file__, "-v"])