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,606 @@
1
+ """
2
+ Test module for ProcessManager functionality.
3
+
4
+ This module tests the process management functionality including:
5
+ - Process creation and configuration
6
+ - Process registration and management
7
+ - Process cleanup and timeout handling
8
+ - Error handling and edge cases
9
+ """
10
+
11
+ import os
12
+ import time
13
+ import platform
14
+ import threading
15
+ from unittest.mock import Mock, patch, MagicMock
16
+ import subprocess
17
+ import pytest
18
+
19
+ from autocoder.common.shell_commands.process_manager import ProcessManager
20
+ from autocoder.common.shell_commands.timeout_config import TimeoutConfig
21
+ from autocoder.common.shell_commands.exceptions import CommandExecutionError, ProcessCleanupError
22
+
23
+
24
+ class TestProcessManager:
25
+ """Test basic ProcessManager functionality."""
26
+
27
+ def test_initialization(self):
28
+ """Test ProcessManager initialization."""
29
+ config = TimeoutConfig(default_timeout=60.0)
30
+ manager = ProcessManager(config)
31
+
32
+ assert manager.config == config
33
+ assert manager.timeout_manager is not None
34
+ assert len(manager.active_processes) == 0
35
+ assert len(manager.process_groups) == 0
36
+
37
+ def test_create_process_basic(self):
38
+ """Test basic process creation."""
39
+ config = TimeoutConfig(default_timeout=60.0)
40
+ manager = ProcessManager(config)
41
+
42
+ if platform.system() == 'Windows':
43
+ command = ['echo', 'test']
44
+ else:
45
+ command = ['echo', 'test']
46
+
47
+ process = manager.create_process(command)
48
+
49
+ try:
50
+ assert process is not None
51
+ assert process.pid > 0
52
+ assert process.pid in manager.active_processes
53
+
54
+ # Wait for process to complete
55
+ exit_code = manager.wait_for_process(process, timeout=5.0)
56
+ assert exit_code == 0
57
+ finally:
58
+ # Cleanup if needed
59
+ if process.pid in manager.active_processes:
60
+ manager.cleanup_process_tree(process)
61
+
62
+ def test_create_process_with_options(self):
63
+ """Test process creation with various options."""
64
+ config = TimeoutConfig(default_timeout=60.0)
65
+ manager = ProcessManager(config)
66
+
67
+ if platform.system() == 'Windows':
68
+ command = ['echo', 'test']
69
+ else:
70
+ command = ['echo', 'test']
71
+
72
+ process = manager.create_process(
73
+ command,
74
+ timeout=30.0,
75
+ shell=True,
76
+ capture_output=True,
77
+ text=True
78
+ )
79
+
80
+ try:
81
+ assert process is not None
82
+ assert process.pid > 0
83
+ assert process.pid in manager.active_processes
84
+
85
+ # Wait for process to complete
86
+ exit_code = manager.wait_for_process(process, timeout=5.0)
87
+ assert exit_code == 0
88
+ finally:
89
+ # Cleanup if needed
90
+ if process.pid in manager.active_processes:
91
+ manager.cleanup_process_tree(process)
92
+
93
+ def test_create_process_failure(self):
94
+ """Test process creation failure handling."""
95
+ config = TimeoutConfig(default_timeout=60.0)
96
+ manager = ProcessManager(config)
97
+
98
+ # Try to create process with invalid cwd (this will actually fail)
99
+ with pytest.raises(CommandExecutionError):
100
+ manager.create_process(['echo', 'test'], cwd='/this/path/does/not/exist')
101
+
102
+ def test_register_process(self):
103
+ """Test manual process registration."""
104
+ config = TimeoutConfig(default_timeout=60.0)
105
+ manager = ProcessManager(config)
106
+
107
+ mock_process = Mock()
108
+ mock_process.pid = 12345
109
+
110
+ manager._register_process(mock_process)
111
+
112
+ assert mock_process.pid in manager.active_processes
113
+
114
+ def test_cleanup_process_success(self):
115
+ """Test successful process cleanup."""
116
+ config = TimeoutConfig(default_timeout=60.0)
117
+ manager = ProcessManager(config)
118
+
119
+ if platform.system() == 'Windows':
120
+ command = ['ping', '127.0.0.1', '-n', '1']
121
+ else:
122
+ command = ['sleep', '0.1']
123
+
124
+ process = manager.create_process(command)
125
+
126
+ try:
127
+ pid = process.pid
128
+ assert pid in manager.active_processes
129
+
130
+ # Wait a bit for process to complete or be running
131
+ time.sleep(0.05)
132
+
133
+ # Cleanup
134
+ result = manager.cleanup_process_tree(process)
135
+
136
+ assert result is True or result is False # Should return a boolean
137
+ assert pid not in manager.active_processes
138
+
139
+ except Exception as e:
140
+ # Fallback cleanup
141
+ try:
142
+ process.terminate()
143
+ process.wait(timeout=1)
144
+ except:
145
+ pass
146
+ manager.unregister_process(process)
147
+
148
+ def test_cleanup_nonexistent_process(self):
149
+ """Test cleanup of non-existent process."""
150
+ config = TimeoutConfig(default_timeout=60.0)
151
+ manager = ProcessManager(config)
152
+
153
+ # Create a mock process that doesn't exist
154
+ mock_process = Mock()
155
+ mock_process.pid = 99999
156
+
157
+ result = manager.cleanup_process_tree(mock_process)
158
+
159
+ # Should handle gracefully
160
+ assert result is False or result is True
161
+
162
+ def test_cleanup_all_processes(self):
163
+ """Test cleanup of all managed processes."""
164
+ config = TimeoutConfig(default_timeout=60.0)
165
+ manager = ProcessManager(config)
166
+
167
+ processes = []
168
+
169
+ # Create multiple processes
170
+ for i in range(3):
171
+ if platform.system() == 'Windows':
172
+ command = ['ping', '127.0.0.1', '-n', '1']
173
+ else:
174
+ command = ['sleep', '0.1']
175
+
176
+ process = manager.create_process(command)
177
+ if process:
178
+ processes.append(process)
179
+
180
+ try:
181
+ assert len(manager.active_processes) >= len(processes)
182
+
183
+ # Cleanup all
184
+ results = manager.cleanup_all_processes()
185
+
186
+ assert len(manager.active_processes) == 0
187
+ assert isinstance(results, list)
188
+
189
+ except Exception:
190
+ # Fallback cleanup
191
+ for process in processes:
192
+ try:
193
+ process.terminate()
194
+ process.wait(timeout=1)
195
+ except:
196
+ pass
197
+ manager.active_processes.clear()
198
+
199
+ def test_get_managed_processes(self):
200
+ """Test getting list of managed processes."""
201
+ config = TimeoutConfig(default_timeout=60.0)
202
+ manager = ProcessManager(config)
203
+
204
+ initial_count = len(manager.get_all_processes())
205
+
206
+ if platform.system() == 'Windows':
207
+ command = ['echo', 'test']
208
+ else:
209
+ command = ['echo', 'test']
210
+
211
+ process = manager.create_process(command)
212
+
213
+ try:
214
+ current_count = len(manager.get_all_processes())
215
+ assert current_count == initial_count + 1
216
+
217
+ processes = manager.get_all_processes()
218
+ assert process.pid in processes
219
+ assert processes[process.pid] == process
220
+
221
+ finally:
222
+ if process.pid in manager.active_processes:
223
+ manager.cleanup_process_tree(process)
224
+
225
+ def test_is_process_managed(self):
226
+ """Test checking if process is managed."""
227
+ config = TimeoutConfig(default_timeout=60.0)
228
+ manager = ProcessManager(config)
229
+
230
+ # Non-existent process
231
+ assert 99999 not in manager.active_processes
232
+
233
+ if platform.system() == 'Windows':
234
+ command = ['echo', 'test']
235
+ else:
236
+ command = ['echo', 'test']
237
+
238
+ process = manager.create_process(command)
239
+
240
+ try:
241
+ # Process should be managed
242
+ assert process.pid in manager.active_processes
243
+
244
+ # Wait for process to complete
245
+ exit_code = manager.wait_for_process(process, timeout=5.0)
246
+
247
+ # Process should no longer be managed
248
+ assert process.pid not in manager.active_processes
249
+
250
+ finally:
251
+ if process.pid in manager.active_processes:
252
+ manager.cleanup_process_tree(process)
253
+
254
+ def test_unregister_process(self):
255
+ """Test process unregistration."""
256
+ config = TimeoutConfig(default_timeout=60.0)
257
+ manager = ProcessManager(config)
258
+
259
+ mock_process = Mock()
260
+ mock_process.pid = 12345
261
+
262
+ # Register then unregister
263
+ manager._register_process(mock_process)
264
+ assert mock_process.pid in manager.active_processes
265
+
266
+ manager.unregister_process(mock_process)
267
+ assert mock_process.pid not in manager.active_processes
268
+
269
+
270
+ class TestProcessManagerWithTimeout:
271
+ """Test ProcessManager with timeout functionality."""
272
+
273
+ def test_process_with_timeout(self):
274
+ """Test process creation with timeout."""
275
+ config = TimeoutConfig(default_timeout=1.0)
276
+ manager = ProcessManager(config)
277
+
278
+ if platform.system() == 'Windows':
279
+ # Use a command that will run for a while
280
+ command = ['ping', '127.0.0.1', '-n', '10']
281
+ else:
282
+ command = ['sleep', '10']
283
+
284
+ process = manager.create_process(command, timeout=0.1)
285
+
286
+ try:
287
+ assert process is not None
288
+
289
+ # Process should be killed by timeout
290
+ start_time = time.time()
291
+ try:
292
+ process.wait(timeout=1.0)
293
+ except subprocess.TimeoutExpired:
294
+ # Expected if process is still running
295
+ pass
296
+ duration = time.time() - start_time
297
+
298
+ # Should have been terminated by timeout (allow some margin)
299
+ assert duration < 2.0
300
+
301
+ finally:
302
+ try:
303
+ process.terminate()
304
+ process.wait(timeout=1)
305
+ except:
306
+ pass
307
+ if process.pid in manager.active_processes:
308
+ manager.cleanup_process_tree(process)
309
+
310
+
311
+ class TestProcessManagerErrorHandling:
312
+ """Test ProcessManager error handling."""
313
+
314
+ def test_cleanup_with_permission_error(self):
315
+ """Test cleanup when permission is denied."""
316
+ config = TimeoutConfig(default_timeout=60.0)
317
+ manager = ProcessManager(config)
318
+
319
+ # Try to cleanup a system process (should fail with permission error)
320
+ if platform.system() == 'Windows':
321
+ system_pid = 4 # System process
322
+ else:
323
+ system_pid = 1 # Init process
324
+
325
+ # Create a mock process for system PID
326
+ mock_process = Mock()
327
+ mock_process.pid = system_pid
328
+
329
+ result = manager.cleanup_process_tree(mock_process)
330
+
331
+ # Should handle gracefully (might succeed or fail depending on permissions)
332
+ assert result is True or result is False
333
+
334
+ def test_cleanup_with_process_not_found(self):
335
+ """Test cleanup when process is not found."""
336
+ config = TimeoutConfig(default_timeout=60.0)
337
+ manager = ProcessManager(config)
338
+
339
+ # Create a mock process that doesn't actually exist
340
+ mock_process = Mock()
341
+ mock_process.pid = 99999
342
+
343
+ result = manager.cleanup_process_tree(mock_process)
344
+
345
+ # Should handle gracefully
346
+ assert result is True or result is False
347
+
348
+ def test_process_creation_with_invalid_command(self):
349
+ """Test process creation with invalid command."""
350
+ config = TimeoutConfig(default_timeout=60.0)
351
+ manager = ProcessManager(config)
352
+
353
+ # Try to create process with invalid cwd (this will actually fail)
354
+ with pytest.raises(CommandExecutionError):
355
+ manager.create_process(['echo', 'test'], cwd='/this/path/does/not/exist')
356
+
357
+ def test_process_creation_with_invalid_cwd(self):
358
+ """Test process creation with invalid working directory."""
359
+ config = TimeoutConfig(default_timeout=60.0)
360
+ manager = ProcessManager(config)
361
+
362
+ with pytest.raises(CommandExecutionError):
363
+ manager.create_process(
364
+ ['echo', 'test'],
365
+ cwd='/this/directory/does/not/exist'
366
+ )
367
+
368
+ @patch('autocoder.common.shell_commands.process_manager.cleanup_process_tree')
369
+ def test_cleanup_with_cleanup_function_failure(self, mock_cleanup):
370
+ """Test process cleanup when cleanup function fails."""
371
+ config = TimeoutConfig(default_timeout=60.0)
372
+ manager = ProcessManager(config)
373
+
374
+ # Make cleanup function return False (indicating failure)
375
+ mock_cleanup.return_value = False
376
+
377
+ # Create a mock process that appears to be still running
378
+ mock_process = Mock()
379
+ mock_process.pid = 123
380
+ mock_process.poll.return_value = None # Process is still running
381
+
382
+ # Cleanup should handle the failure
383
+ result = manager.cleanup_process_tree(mock_process)
384
+
385
+ # Should return False on failure
386
+ assert result is False
387
+
388
+
389
+ class TestProcessManagerConcurrency:
390
+ """Test ProcessManager concurrency handling."""
391
+
392
+ def test_concurrent_process_creation(self):
393
+ """Test concurrent process creation."""
394
+ import threading
395
+
396
+ config = TimeoutConfig(default_timeout=60.0)
397
+ manager = ProcessManager(config)
398
+
399
+ processes = []
400
+ errors = []
401
+
402
+ def create_process():
403
+ try:
404
+ if platform.system() == 'Windows':
405
+ command = ['echo', 'test']
406
+ else:
407
+ command = ['echo', 'test']
408
+
409
+ process = manager.create_process(command)
410
+ if process:
411
+ processes.append(process)
412
+ except Exception as e:
413
+ errors.append(e)
414
+
415
+ # Create multiple threads
416
+ threads = [threading.Thread(target=create_process) for _ in range(5)]
417
+
418
+ # Start all threads
419
+ for thread in threads:
420
+ thread.start()
421
+
422
+ # Wait for all threads
423
+ for thread in threads:
424
+ thread.join()
425
+
426
+ try:
427
+ # Should have created some processes without errors
428
+ assert len(processes) > 0
429
+ assert len(errors) == 0
430
+
431
+ # All processes should be managed
432
+ for process in processes:
433
+ assert process.pid in manager.active_processes
434
+
435
+ finally:
436
+ # Cleanup
437
+ for process in processes:
438
+ try:
439
+ if process.pid in manager.active_processes:
440
+ manager.cleanup_process_tree(process)
441
+ except:
442
+ pass
443
+
444
+
445
+ class TestProcessManagerIntegration:
446
+ """Test ProcessManager integration scenarios."""
447
+
448
+ def test_full_lifecycle(self):
449
+ """Test complete process lifecycle."""
450
+ config = TimeoutConfig(default_timeout=60.0)
451
+ manager = ProcessManager(config)
452
+
453
+ if platform.system() == 'Windows':
454
+ command = ['echo', 'Hello World']
455
+ else:
456
+ command = ['echo', 'Hello World']
457
+
458
+ # Create process
459
+ process = manager.create_process(command)
460
+
461
+ try:
462
+ assert process is not None
463
+ assert process.pid in manager.active_processes
464
+
465
+ # Wait for completion
466
+ exit_code = manager.wait_for_process(process, timeout=5.0)
467
+ assert exit_code == 0
468
+
469
+ # Process should be automatically unregistered
470
+ assert process.pid not in manager.active_processes
471
+
472
+ finally:
473
+ if process.pid in manager.active_processes:
474
+ manager.cleanup_process_tree(process)
475
+
476
+
477
+ class TestProcessManagerEdgeCases:
478
+ """Test ProcessManager edge cases."""
479
+
480
+ def test_empty_command(self):
481
+ """Test process creation with empty command."""
482
+ config = TimeoutConfig(default_timeout=60.0)
483
+ manager = ProcessManager(config)
484
+
485
+ # Empty command will create a process but it will fail at runtime
486
+ process = manager.create_process([])
487
+
488
+ try:
489
+ assert process is not None
490
+ assert process.pid > 0
491
+
492
+ # Wait for process to fail
493
+ try:
494
+ exit_code = process.wait(timeout=2.0)
495
+ # Process should fail with non-zero exit code
496
+ assert exit_code != 0
497
+ except subprocess.TimeoutExpired:
498
+ # Process might hang, that's also expected behavior
499
+ pass
500
+ finally:
501
+ if process and process.pid in manager.active_processes:
502
+ manager.cleanup_process_tree(process)
503
+
504
+ def test_very_short_timeout(self):
505
+ """Test process with very short timeout."""
506
+ config = TimeoutConfig(default_timeout=60.0)
507
+ manager = ProcessManager(config)
508
+
509
+ if platform.system() == 'Windows':
510
+ command = ['ping', '127.0.0.1', '-n', '5']
511
+ else:
512
+ command = ['sleep', '1']
513
+
514
+ process = manager.create_process(command, timeout=0.001) # Very short
515
+
516
+ try:
517
+ if process:
518
+ start_time = time.time()
519
+ try:
520
+ process.wait(timeout=0.2)
521
+ except subprocess.TimeoutExpired:
522
+ # Expected if process is still running
523
+ pass
524
+ duration = time.time() - start_time
525
+
526
+ # Should have been killed quickly
527
+ assert duration < 0.5
528
+ finally:
529
+ if process and process.pid in manager.active_processes:
530
+ manager.cleanup_process_tree(process)
531
+
532
+ def test_cleanup_already_cleaned_process(self):
533
+ """Test cleanup of already cleaned process."""
534
+ config = TimeoutConfig(default_timeout=60.0)
535
+ manager = ProcessManager(config)
536
+
537
+ if platform.system() == 'Windows':
538
+ command = ['echo', 'test']
539
+ else:
540
+ command = ['echo', 'test']
541
+
542
+ process = manager.create_process(command)
543
+
544
+ try:
545
+ pid = process.pid
546
+
547
+ # Wait for process to complete
548
+ process.wait(timeout=5)
549
+
550
+ # Cleanup once
551
+ result1 = manager.cleanup_process_tree(process)
552
+
553
+ # Cleanup again
554
+ result2 = manager.cleanup_process_tree(process)
555
+
556
+ # Both should handle gracefully
557
+ assert result1 is True or result1 is False
558
+ assert result2 is True or result2 is False
559
+
560
+ except Exception:
561
+ if process and process.pid in manager.active_processes:
562
+ manager.cleanup_process_tree(process)
563
+
564
+ def test_manager_state_after_errors(self):
565
+ """Test manager state consistency after various errors."""
566
+ config = TimeoutConfig(default_timeout=60.0)
567
+ manager = ProcessManager(config)
568
+
569
+ initial_count = len(manager.active_processes)
570
+
571
+ # Try various operations that might fail
572
+ try:
573
+ # This will create a process that fails at runtime
574
+ process1 = manager.create_process(['this_command_does_not_exist'])
575
+ if process1:
576
+ manager.cleanup_process_tree(process1)
577
+ except CommandExecutionError:
578
+ pass
579
+
580
+ try:
581
+ manager.create_process(['echo', 'test'], cwd='/invalid/path')
582
+ except CommandExecutionError:
583
+ pass
584
+
585
+ # Manager state should be consistent (might have processes that were created)
586
+ current_count = len(manager.active_processes)
587
+
588
+ # Should still be able to create valid processes
589
+ if platform.system() == 'Windows':
590
+ command = ['echo', 'test']
591
+ else:
592
+ command = ['echo', 'test']
593
+
594
+ process = manager.create_process(command)
595
+
596
+ try:
597
+ assert process is not None
598
+ assert len(manager.active_processes) >= current_count
599
+
600
+ finally:
601
+ if process and process.pid in manager.active_processes:
602
+ manager.cleanup_process_tree(process)
603
+
604
+
605
+ if __name__ == "__main__":
606
+ pytest.main([__file__, "-v"])