auto-coder 1.0.0__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 (574) 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-1.0.0.dist-info → auto_coder-2.0.0.dist-info}/WHEEL +1 -1
  5. {auto_coder-1.0.0.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 +24 -3
  16. autocoder/agent/base_agentic/tools/write_to_file_tool_resolver.py +24 -11
  17. autocoder/agent/base_agentic/types.py +42 -0
  18. autocoder/agent/entry_command_agent/chat.py +73 -59
  19. autocoder/auto_coder.py +31 -40
  20. autocoder/auto_coder_rag.py +11 -1084
  21. autocoder/auto_coder_runner.py +970 -2345
  22. autocoder/auto_coder_terminal.py +26 -0
  23. autocoder/auto_coder_terminal_v3.py +190 -0
  24. autocoder/chat/conf_command.py +224 -124
  25. autocoder/chat/models_command.py +361 -299
  26. autocoder/chat/rules_command.py +79 -31
  27. autocoder/chat_auto_coder.py +988 -398
  28. autocoder/chat_auto_coder_lang.py +23 -732
  29. autocoder/commands/auto_command.py +25 -8
  30. autocoder/commands/auto_web.py +1 -1
  31. autocoder/commands/tools.py +44 -44
  32. autocoder/common/__init__.py +150 -128
  33. autocoder/common/ac_style_command_parser/__init__.py +39 -2
  34. autocoder/common/ac_style_command_parser/config.py +422 -0
  35. autocoder/common/ac_style_command_parser/parser.py +292 -78
  36. autocoder/common/ac_style_command_parser/test_parser.py +241 -16
  37. autocoder/common/ac_style_command_parser/test_typed_parser.py +342 -0
  38. autocoder/common/ac_style_command_parser/typed_parser.py +653 -0
  39. autocoder/common/action_yml_file_manager.py +25 -13
  40. autocoder/common/agent_events/__init__.py +52 -0
  41. autocoder/common/agent_events/agent_event_emitter.py +193 -0
  42. autocoder/common/agent_events/event_factory.py +177 -0
  43. autocoder/common/agent_events/examples.py +307 -0
  44. autocoder/common/agent_events/types.py +113 -0
  45. autocoder/common/agent_events/utils.py +68 -0
  46. autocoder/common/agent_hooks/__init__.py +44 -0
  47. autocoder/common/agent_hooks/examples.py +582 -0
  48. autocoder/common/agent_hooks/hook_executor.py +217 -0
  49. autocoder/common/agent_hooks/hook_manager.py +288 -0
  50. autocoder/common/agent_hooks/types.py +133 -0
  51. autocoder/common/agent_hooks/utils.py +99 -0
  52. autocoder/common/agent_query_queue/queue_executor.py +324 -0
  53. autocoder/common/agent_query_queue/queue_manager.py +325 -0
  54. autocoder/common/agents/__init__.py +11 -0
  55. autocoder/common/agents/agent_manager.py +323 -0
  56. autocoder/common/agents/agent_parser.py +189 -0
  57. autocoder/common/agents/example_usage.py +344 -0
  58. autocoder/common/agents/integration_example.py +330 -0
  59. autocoder/common/agents/test_agent_parser.py +545 -0
  60. autocoder/common/async_utils.py +101 -0
  61. autocoder/common/auto_coder_lang.py +23 -972
  62. autocoder/common/autocoderargs_parser/__init__.py +14 -0
  63. autocoder/common/autocoderargs_parser/parser.py +184 -0
  64. autocoder/common/autocoderargs_parser/tests/__init__.py +1 -0
  65. autocoder/common/autocoderargs_parser/tests/test_args_parser.py +235 -0
  66. autocoder/common/autocoderargs_parser/tests/test_token_parser.py +195 -0
  67. autocoder/common/autocoderargs_parser/token_parser.py +290 -0
  68. autocoder/common/buildin_tokenizer.py +2 -4
  69. autocoder/common/code_auto_generate.py +149 -74
  70. autocoder/common/code_auto_generate_diff.py +163 -70
  71. autocoder/common/code_auto_generate_editblock.py +179 -89
  72. autocoder/common/code_auto_generate_strict_diff.py +167 -72
  73. autocoder/common/code_auto_merge_editblock.py +13 -6
  74. autocoder/common/code_modification_ranker.py +1 -1
  75. autocoder/common/command_completer.py +3 -3
  76. autocoder/common/command_file_manager/manager.py +183 -47
  77. autocoder/common/command_file_manager/test_command_file_manager.py +507 -0
  78. autocoder/common/command_templates.py +1 -1
  79. autocoder/common/conf_utils.py +2 -4
  80. autocoder/common/conversations/config.py +11 -3
  81. autocoder/common/conversations/get_conversation_manager.py +100 -2
  82. autocoder/common/conversations/llm_stats_models.py +264 -0
  83. autocoder/common/conversations/manager.py +112 -28
  84. autocoder/common/conversations/models.py +16 -2
  85. autocoder/common/conversations/storage/index_manager.py +134 -10
  86. autocoder/common/core_config/__init__.py +63 -0
  87. autocoder/common/core_config/agentic_mode_manager.py +109 -0
  88. autocoder/common/core_config/base_manager.py +123 -0
  89. autocoder/common/core_config/compatibility.py +151 -0
  90. autocoder/common/core_config/config_manager.py +156 -0
  91. autocoder/common/core_config/conversation_manager.py +31 -0
  92. autocoder/common/core_config/exclude_manager.py +72 -0
  93. autocoder/common/core_config/file_manager.py +177 -0
  94. autocoder/common/core_config/human_as_model_manager.py +129 -0
  95. autocoder/common/core_config/lib_manager.py +54 -0
  96. autocoder/common/core_config/main_manager.py +81 -0
  97. autocoder/common/core_config/mode_manager.py +126 -0
  98. autocoder/common/core_config/models.py +70 -0
  99. autocoder/common/core_config/test_memory_manager.py +1056 -0
  100. autocoder/common/env_manager.py +282 -0
  101. autocoder/common/env_manager_usage_example.py +211 -0
  102. autocoder/common/file_checkpoint/conversation_checkpoint.py +19 -19
  103. autocoder/common/file_checkpoint/manager.py +264 -48
  104. autocoder/common/file_checkpoint/test_backup.py +1 -18
  105. autocoder/common/file_checkpoint/test_manager.py +270 -1
  106. autocoder/common/file_checkpoint/test_store.py +1 -17
  107. autocoder/common/file_handler/__init__.py +23 -0
  108. autocoder/common/file_handler/active_context_handler.py +159 -0
  109. autocoder/common/file_handler/add_files_handler.py +409 -0
  110. autocoder/common/file_handler/chat_handler.py +180 -0
  111. autocoder/common/file_handler/coding_handler.py +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/git_utils.py +44 -8
  119. autocoder/common/global_cancel.py +15 -6
  120. autocoder/common/ignorefiles/test_ignore_file_utils.py +1 -1
  121. autocoder/common/international/__init__.py +31 -0
  122. autocoder/common/international/demo_international.py +92 -0
  123. autocoder/common/international/message_manager.py +157 -0
  124. autocoder/common/international/messages/__init__.py +56 -0
  125. autocoder/common/international/messages/async_command_messages.py +507 -0
  126. autocoder/common/international/messages/auto_coder_messages.py +2208 -0
  127. autocoder/common/international/messages/chat_auto_coder_messages.py +1547 -0
  128. autocoder/common/international/messages/command_help_messages.py +986 -0
  129. autocoder/common/international/messages/conversation_command_messages.py +191 -0
  130. autocoder/common/international/messages/git_helper_plugin_messages.py +159 -0
  131. autocoder/common/international/messages/queue_command_messages.py +751 -0
  132. autocoder/common/international/messages/rules_command_messages.py +77 -0
  133. autocoder/common/international/messages/sdk_messages.py +1707 -0
  134. autocoder/common/international/messages/token_helper_plugin_messages.py +361 -0
  135. autocoder/common/international/messages/tool_display_messages.py +1212 -0
  136. autocoder/common/international/messages/workflow_exception_messages.py +473 -0
  137. autocoder/common/international/test_international.py +612 -0
  138. autocoder/common/linter_core/__init__.py +28 -0
  139. autocoder/common/linter_core/base_linter.py +61 -0
  140. autocoder/common/linter_core/config_loader.py +271 -0
  141. autocoder/common/linter_core/formatters/__init__.py +0 -0
  142. autocoder/common/linter_core/formatters/base_formatter.py +38 -0
  143. autocoder/common/linter_core/formatters/raw_formatter.py +17 -0
  144. autocoder/common/linter_core/linter.py +166 -0
  145. autocoder/common/linter_core/linter_factory.py +216 -0
  146. autocoder/common/linter_core/linter_manager.py +333 -0
  147. autocoder/common/linter_core/linters/__init__.py +9 -0
  148. autocoder/common/linter_core/linters/java_linter.py +342 -0
  149. autocoder/common/linter_core/linters/python_linter.py +115 -0
  150. autocoder/common/linter_core/linters/typescript_linter.py +119 -0
  151. autocoder/common/linter_core/models/__init__.py +7 -0
  152. autocoder/common/linter_core/models/lint_result.py +91 -0
  153. autocoder/common/linter_core/models.py +33 -0
  154. autocoder/common/linter_core/tests/__init__.py +3 -0
  155. autocoder/common/linter_core/tests/test_config_loader.py +323 -0
  156. autocoder/common/linter_core/tests/test_config_loading.py +308 -0
  157. autocoder/common/linter_core/tests/test_factory_manager.py +234 -0
  158. autocoder/common/linter_core/tests/test_formatters.py +147 -0
  159. autocoder/common/linter_core/tests/test_integration.py +317 -0
  160. autocoder/common/linter_core/tests/test_java_linter.py +496 -0
  161. autocoder/common/linter_core/tests/test_linters.py +265 -0
  162. autocoder/common/linter_core/tests/test_models.py +81 -0
  163. autocoder/common/linter_core/tests/verify_config_loading.py +296 -0
  164. autocoder/common/linter_core/tests/verify_fixes.py +183 -0
  165. autocoder/common/llm_friendly_package/__init__.py +31 -0
  166. autocoder/common/llm_friendly_package/base_manager.py +102 -0
  167. autocoder/common/llm_friendly_package/docs_manager.py +121 -0
  168. autocoder/common/llm_friendly_package/library_manager.py +171 -0
  169. autocoder/common/{llm_friendly_package.py → llm_friendly_package/main_manager.py} +204 -231
  170. autocoder/common/llm_friendly_package/models.py +40 -0
  171. autocoder/common/llm_friendly_package/test_llm_friendly_package.py +536 -0
  172. autocoder/common/llms/__init__.py +15 -0
  173. autocoder/common/llms/demo_error_handling.py +85 -0
  174. autocoder/common/llms/factory.py +142 -0
  175. autocoder/common/llms/manager.py +264 -0
  176. autocoder/common/llms/pricing.py +121 -0
  177. autocoder/common/llms/registry.py +288 -0
  178. autocoder/common/llms/schema.py +77 -0
  179. autocoder/common/llms/simple_demo.py +45 -0
  180. autocoder/common/llms/test_quick_model.py +116 -0
  181. autocoder/common/llms/test_remove_functionality.py +182 -0
  182. autocoder/common/llms/tests/__init__.py +1 -0
  183. autocoder/common/llms/tests/test_manager.py +330 -0
  184. autocoder/common/llms/tests/test_registry.py +364 -0
  185. autocoder/common/mcp_tools/__init__.py +62 -0
  186. autocoder/common/{mcp_tools.py → mcp_tools/executor.py} +49 -40
  187. autocoder/common/{mcp_hub.py → mcp_tools/hub.py} +42 -68
  188. autocoder/common/{mcp_server_install.py → mcp_tools/installer.py} +16 -28
  189. autocoder/common/{mcp_server.py → mcp_tools/server.py} +176 -48
  190. autocoder/common/mcp_tools/test_keyboard_interrupt.py +93 -0
  191. autocoder/common/mcp_tools/test_mcp_tools.py +391 -0
  192. autocoder/common/{mcp_server_types.py → mcp_tools/types.py} +121 -48
  193. autocoder/common/mcp_tools/verify_functionality.py +202 -0
  194. autocoder/common/model_speed_tester.py +32 -26
  195. autocoder/common/priority_directory_finder/__init__.py +142 -0
  196. autocoder/common/priority_directory_finder/examples.py +230 -0
  197. autocoder/common/priority_directory_finder/finder.py +283 -0
  198. autocoder/common/priority_directory_finder/models.py +236 -0
  199. autocoder/common/priority_directory_finder/test_priority_directory_finder.py +431 -0
  200. autocoder/common/project_scanner/__init__.py +18 -0
  201. autocoder/common/project_scanner/compat.py +77 -0
  202. autocoder/common/project_scanner/scanner.py +436 -0
  203. autocoder/common/project_tracker/__init__.py +27 -0
  204. autocoder/common/project_tracker/api.py +228 -0
  205. autocoder/common/project_tracker/demo.py +272 -0
  206. autocoder/common/project_tracker/tracker.py +487 -0
  207. autocoder/common/project_tracker/types.py +53 -0
  208. autocoder/common/pruner/__init__.py +67 -0
  209. autocoder/common/pruner/agentic_conversation_pruner.py +651 -102
  210. autocoder/common/pruner/conversation_message_ids_api.py +386 -0
  211. autocoder/common/pruner/conversation_message_ids_manager.py +347 -0
  212. autocoder/common/pruner/conversation_message_ids_pruner.py +473 -0
  213. autocoder/common/pruner/conversation_normalizer.py +347 -0
  214. autocoder/common/pruner/conversation_pruner.py +26 -6
  215. autocoder/common/pruner/test_agentic_conversation_pruner.py +554 -112
  216. autocoder/common/pruner/test_conversation_normalizer.py +502 -0
  217. autocoder/common/pruner/test_tool_content_detector.py +324 -0
  218. autocoder/common/pruner/tool_content_detector.py +227 -0
  219. autocoder/common/pruner/tools/__init__.py +18 -0
  220. autocoder/common/pruner/tools/query_message_ids.py +264 -0
  221. autocoder/common/pruner/tools/test_agentic_pruning_logic.py +432 -0
  222. autocoder/common/pruner/tools/test_message_ids_pruning_only.py +192 -0
  223. autocoder/common/pull_requests/__init__.py +9 -1
  224. autocoder/common/pull_requests/utils.py +122 -1
  225. autocoder/common/rag_manager/rag_manager.py +36 -40
  226. autocoder/common/rulefiles/__init__.py +53 -1
  227. autocoder/common/rulefiles/api.py +250 -0
  228. autocoder/common/rulefiles/core/__init__.py +14 -0
  229. autocoder/common/rulefiles/core/manager.py +241 -0
  230. autocoder/common/rulefiles/core/selector.py +805 -0
  231. autocoder/common/rulefiles/models/__init__.py +20 -0
  232. autocoder/common/rulefiles/models/index.py +16 -0
  233. autocoder/common/rulefiles/models/init_rule.py +18 -0
  234. autocoder/common/rulefiles/models/rule_file.py +18 -0
  235. autocoder/common/rulefiles/models/rule_relevance.py +14 -0
  236. autocoder/common/rulefiles/models/summary.py +16 -0
  237. autocoder/common/rulefiles/test_rulefiles.py +776 -0
  238. autocoder/common/rulefiles/utils/__init__.py +34 -0
  239. autocoder/common/rulefiles/utils/monitor.py +86 -0
  240. autocoder/common/rulefiles/utils/parser.py +230 -0
  241. autocoder/common/save_formatted_log.py +67 -10
  242. autocoder/common/search_replace.py +8 -1
  243. autocoder/common/search_replace_patch/__init__.py +24 -0
  244. autocoder/common/search_replace_patch/base.py +115 -0
  245. autocoder/common/search_replace_patch/manager.py +248 -0
  246. autocoder/common/search_replace_patch/patch_replacer.py +304 -0
  247. autocoder/common/search_replace_patch/similarity_replacer.py +306 -0
  248. autocoder/common/search_replace_patch/string_replacer.py +181 -0
  249. autocoder/common/search_replace_patch/tests/__init__.py +3 -0
  250. autocoder/common/search_replace_patch/tests/run_tests.py +126 -0
  251. autocoder/common/search_replace_patch/tests/test_base.py +188 -0
  252. autocoder/common/search_replace_patch/tests/test_empty_line_insert.py +233 -0
  253. autocoder/common/search_replace_patch/tests/test_integration.py +389 -0
  254. autocoder/common/search_replace_patch/tests/test_manager.py +351 -0
  255. autocoder/common/search_replace_patch/tests/test_patch_replacer.py +316 -0
  256. autocoder/common/search_replace_patch/tests/test_regex_replacer.py +306 -0
  257. autocoder/common/search_replace_patch/tests/test_similarity_replacer.py +384 -0
  258. autocoder/common/shell_commands/__init__.py +197 -0
  259. autocoder/common/shell_commands/background_process_notifier.py +346 -0
  260. autocoder/common/shell_commands/command_executor.py +1127 -0
  261. autocoder/common/shell_commands/error_recovery.py +541 -0
  262. autocoder/common/shell_commands/exceptions.py +120 -0
  263. autocoder/common/shell_commands/interactive_executor.py +476 -0
  264. autocoder/common/shell_commands/interactive_pexpect_process.py +623 -0
  265. autocoder/common/shell_commands/interactive_process.py +744 -0
  266. autocoder/common/shell_commands/interactive_session_manager.py +1014 -0
  267. autocoder/common/shell_commands/monitoring.py +529 -0
  268. autocoder/common/shell_commands/process_cleanup.py +386 -0
  269. autocoder/common/shell_commands/process_manager.py +606 -0
  270. autocoder/common/shell_commands/test_interactive_pexpect_process.py +281 -0
  271. autocoder/common/shell_commands/tests/__init__.py +6 -0
  272. autocoder/common/shell_commands/tests/conftest.py +118 -0
  273. autocoder/common/shell_commands/tests/test_background_process_notifier.py +703 -0
  274. autocoder/common/shell_commands/tests/test_command_executor.py +448 -0
  275. autocoder/common/shell_commands/tests/test_error_recovery.py +305 -0
  276. autocoder/common/shell_commands/tests/test_exceptions.py +299 -0
  277. autocoder/common/shell_commands/tests/test_execute_batch.py +588 -0
  278. autocoder/common/shell_commands/tests/test_indented_batch_commands.py +244 -0
  279. autocoder/common/shell_commands/tests/test_integration.py +664 -0
  280. autocoder/common/shell_commands/tests/test_monitoring.py +546 -0
  281. autocoder/common/shell_commands/tests/test_performance.py +632 -0
  282. autocoder/common/shell_commands/tests/test_process_cleanup.py +397 -0
  283. autocoder/common/shell_commands/tests/test_process_manager.py +606 -0
  284. autocoder/common/shell_commands/tests/test_timeout_config.py +343 -0
  285. autocoder/common/shell_commands/tests/test_timeout_manager.py +520 -0
  286. autocoder/common/shell_commands/timeout_config.py +315 -0
  287. autocoder/common/shell_commands/timeout_manager.py +352 -0
  288. autocoder/common/terminal_paste/__init__.py +14 -0
  289. autocoder/common/terminal_paste/demo.py +145 -0
  290. autocoder/common/terminal_paste/demo_paste_functionality.py +95 -0
  291. autocoder/common/terminal_paste/paste_handler.py +200 -0
  292. autocoder/common/terminal_paste/paste_manager.py +118 -0
  293. autocoder/common/terminal_paste/tests/__init__.py +1 -0
  294. autocoder/common/terminal_paste/tests/test_paste_handler.py +182 -0
  295. autocoder/common/terminal_paste/tests/test_paste_manager.py +126 -0
  296. autocoder/common/terminal_paste/utils.py +163 -0
  297. autocoder/common/test_autocoder_args.py +232 -0
  298. autocoder/common/test_env_manager.py +173 -0
  299. autocoder/common/test_env_manager_integration.py +159 -0
  300. autocoder/common/text_similarity/__init__.py +9 -0
  301. autocoder/common/text_similarity/demo.py +216 -0
  302. autocoder/common/text_similarity/examples.py +266 -0
  303. autocoder/common/text_similarity/test_text_similarity.py +306 -0
  304. autocoder/common/text_similarity/text_similarity.py +194 -0
  305. autocoder/common/text_similarity/utils.py +125 -0
  306. autocoder/common/todos/__init__.py +61 -0
  307. autocoder/common/todos/cache/__init__.py +16 -0
  308. autocoder/common/todos/cache/base_cache.py +89 -0
  309. autocoder/common/todos/cache/cache_manager.py +228 -0
  310. autocoder/common/todos/cache/memory_cache.py +225 -0
  311. autocoder/common/todos/config.py +155 -0
  312. autocoder/common/todos/exceptions.py +35 -0
  313. autocoder/common/todos/get_todo_manager.py +161 -0
  314. autocoder/common/todos/manager.py +537 -0
  315. autocoder/common/todos/models.py +239 -0
  316. autocoder/common/todos/storage/__init__.py +14 -0
  317. autocoder/common/todos/storage/base_storage.py +76 -0
  318. autocoder/common/todos/storage/file_storage.py +278 -0
  319. autocoder/common/tokens/counter.py +24 -2
  320. autocoder/common/tools_manager/__init__.py +17 -0
  321. autocoder/common/tools_manager/examples.py +162 -0
  322. autocoder/common/tools_manager/manager.py +385 -0
  323. autocoder/common/tools_manager/models.py +39 -0
  324. autocoder/common/tools_manager/test_tools_manager.py +303 -0
  325. autocoder/common/tools_manager/utils.py +191 -0
  326. autocoder/common/v2/agent/agentic_callbacks.py +270 -0
  327. autocoder/common/v2/agent/agentic_edit.py +2699 -1856
  328. autocoder/common/v2/agent/agentic_edit_change_manager.py +474 -0
  329. autocoder/common/v2/agent/agentic_edit_tools/__init__.py +35 -1
  330. autocoder/common/v2/agent/agentic_edit_tools/ac_mod_list_tool_resolver.py +279 -0
  331. autocoder/common/v2/agent/agentic_edit_tools/ac_mod_write_tool_resolver.py +10 -1
  332. autocoder/common/v2/agent/agentic_edit_tools/background_task_tool_resolver.py +1167 -0
  333. autocoder/common/v2/agent/agentic_edit_tools/base_tool_resolver.py +2 -2
  334. autocoder/common/v2/agent/agentic_edit_tools/conversation_message_ids_read_tool_resolver.py +214 -0
  335. autocoder/common/v2/agent/agentic_edit_tools/conversation_message_ids_write_tool_resolver.py +299 -0
  336. autocoder/common/v2/agent/agentic_edit_tools/count_tokens_tool_resolver.py +290 -0
  337. autocoder/common/v2/agent/agentic_edit_tools/execute_command_tool_resolver.py +564 -29
  338. autocoder/common/v2/agent/agentic_edit_tools/execute_workflow_tool_resolver.py +485 -0
  339. autocoder/common/v2/agent/agentic_edit_tools/extract_to_text_tool_resolver.py +225 -0
  340. autocoder/common/v2/agent/agentic_edit_tools/lint_report.py +79 -0
  341. autocoder/common/v2/agent/agentic_edit_tools/linter_config_models.py +343 -0
  342. autocoder/common/v2/agent/agentic_edit_tools/linter_enabled_tool_resolver.py +189 -0
  343. autocoder/common/v2/agent/agentic_edit_tools/list_files_tool_resolver.py +169 -101
  344. autocoder/common/v2/agent/agentic_edit_tools/load_extra_document_tool_resolver.py +349 -0
  345. autocoder/common/v2/agent/agentic_edit_tools/read_file_tool_resolver.py +243 -50
  346. autocoder/common/v2/agent/agentic_edit_tools/replace_in_file_tool_resolver.py +667 -147
  347. autocoder/common/v2/agent/agentic_edit_tools/run_named_subagents_tool_resolver.py +691 -0
  348. autocoder/common/v2/agent/agentic_edit_tools/search_files_tool_resolver.py +410 -86
  349. autocoder/common/v2/agent/agentic_edit_tools/session_interactive_tool_resolver.py +115 -0
  350. autocoder/common/v2/agent/agentic_edit_tools/session_start_tool_resolver.py +190 -0
  351. autocoder/common/v2/agent/agentic_edit_tools/session_stop_tool_resolver.py +76 -0
  352. autocoder/common/v2/agent/agentic_edit_tools/test_write_to_file_tool_resolver.py +207 -192
  353. autocoder/common/v2/agent/agentic_edit_tools/todo_read_tool_resolver.py +80 -63
  354. autocoder/common/v2/agent/agentic_edit_tools/todo_write_tool_resolver.py +237 -233
  355. autocoder/common/v2/agent/agentic_edit_tools/use_mcp_tool_resolver.py +2 -2
  356. autocoder/common/v2/agent/agentic_edit_tools/web_crawl_tool_resolver.py +557 -0
  357. autocoder/common/v2/agent/agentic_edit_tools/web_search_tool_resolver.py +600 -0
  358. autocoder/common/v2/agent/agentic_edit_tools/write_to_file_tool_resolver.py +56 -121
  359. autocoder/common/v2/agent/agentic_edit_types.py +343 -9
  360. autocoder/common/v2/agent/runner/__init__.py +3 -3
  361. autocoder/common/v2/agent/runner/base_runner.py +12 -26
  362. autocoder/common/v2/agent/runner/{event_runner.py → file_based_event_runner.py} +3 -2
  363. autocoder/common/v2/agent/runner/sdk_runner.py +150 -8
  364. autocoder/common/v2/agent/runner/terminal_runner.py +170 -57
  365. autocoder/common/v2/agent/runner/tool_display.py +557 -159
  366. autocoder/common/v2/agent/test_agentic_callbacks.py +265 -0
  367. autocoder/common/v2/agent/test_agentic_edit.py +194 -0
  368. autocoder/common/v2/agent/tool_caller/__init__.py +24 -0
  369. autocoder/common/v2/agent/tool_caller/default_tool_resolver_map.py +135 -0
  370. autocoder/common/v2/agent/tool_caller/integration_test.py +172 -0
  371. autocoder/common/v2/agent/tool_caller/plugins/__init__.py +14 -0
  372. autocoder/common/v2/agent/tool_caller/plugins/base_plugin.py +126 -0
  373. autocoder/common/v2/agent/tool_caller/plugins/examples/__init__.py +13 -0
  374. autocoder/common/v2/agent/tool_caller/plugins/examples/logging_plugin.py +164 -0
  375. autocoder/common/v2/agent/tool_caller/plugins/examples/security_filter_plugin.py +198 -0
  376. autocoder/common/v2/agent/tool_caller/plugins/plugin_interface.py +141 -0
  377. autocoder/common/v2/agent/tool_caller/test_tool_caller.py +278 -0
  378. autocoder/common/v2/agent/tool_caller/tool_call_plugin_manager.py +331 -0
  379. autocoder/common/v2/agent/tool_caller/tool_caller.py +337 -0
  380. autocoder/common/v2/agent/tool_caller/usage_example.py +193 -0
  381. autocoder/common/v2/code_agentic_editblock_manager.py +4 -4
  382. autocoder/common/v2/code_auto_generate.py +136 -78
  383. autocoder/common/v2/code_auto_generate_diff.py +135 -79
  384. autocoder/common/v2/code_auto_generate_editblock.py +174 -99
  385. autocoder/common/v2/code_auto_generate_strict_diff.py +151 -71
  386. autocoder/common/v2/code_auto_merge.py +1 -1
  387. autocoder/common/v2/code_auto_merge_editblock.py +13 -1
  388. autocoder/common/v2/code_diff_manager.py +3 -3
  389. autocoder/common/v2/code_editblock_manager.py +4 -14
  390. autocoder/common/v2/code_manager.py +1 -1
  391. autocoder/common/v2/code_strict_diff_manager.py +2 -2
  392. autocoder/common/wrap_llm_hint/__init__.py +10 -0
  393. autocoder/common/wrap_llm_hint/test_wrap_llm_hint.py +1067 -0
  394. autocoder/common/wrap_llm_hint/utils.py +432 -0
  395. autocoder/common/wrap_llm_hint/wrap_llm_hint.py +323 -0
  396. autocoder/completer/__init__.py +8 -0
  397. autocoder/completer/command_completer_v2.py +1051 -0
  398. autocoder/default_project/__init__.py +501 -0
  399. autocoder/dispacher/__init__.py +4 -12
  400. autocoder/dispacher/actions/action.py +165 -7
  401. autocoder/dispacher/actions/plugins/action_regex_project.py +2 -2
  402. autocoder/index/entry.py +116 -124
  403. autocoder/{agent → index/filter}/agentic_filter.py +322 -333
  404. autocoder/index/filter/normal_filter.py +5 -11
  405. autocoder/index/filter/quick_filter.py +1 -1
  406. autocoder/index/index.py +36 -9
  407. autocoder/index/tests/__init__.py +1 -0
  408. autocoder/index/tests/run_tests.py +195 -0
  409. autocoder/index/tests/test_entry.py +303 -0
  410. autocoder/index/tests/test_index_manager.py +314 -0
  411. autocoder/index/tests/test_module_integration.py +300 -0
  412. autocoder/index/tests/test_symbols_utils.py +183 -0
  413. autocoder/inner/__init__.py +4 -0
  414. autocoder/inner/agentic.py +932 -0
  415. autocoder/inner/async_command_handler.py +992 -0
  416. autocoder/inner/conversation_command_handlers.py +623 -0
  417. autocoder/inner/merge_command_handler.py +213 -0
  418. autocoder/inner/queue_command_handler.py +684 -0
  419. autocoder/models.py +95 -266
  420. autocoder/plugins/git_helper_plugin.py +31 -29
  421. autocoder/plugins/token_helper_plugin.py +65 -46
  422. autocoder/pyproject/__init__.py +32 -29
  423. autocoder/rag/agentic_rag.py +215 -75
  424. autocoder/rag/cache/simple_cache.py +1 -2
  425. autocoder/rag/loaders/image_loader.py +1 -1
  426. autocoder/rag/long_context_rag.py +42 -26
  427. autocoder/rag/qa_conversation_strategy.py +1 -1
  428. autocoder/rag/terminal/__init__.py +17 -0
  429. autocoder/rag/terminal/args.py +581 -0
  430. autocoder/rag/terminal/bootstrap.py +61 -0
  431. autocoder/rag/terminal/command_handlers.py +653 -0
  432. autocoder/rag/terminal/formatters/__init__.py +20 -0
  433. autocoder/rag/terminal/formatters/base.py +70 -0
  434. autocoder/rag/terminal/formatters/json_format.py +66 -0
  435. autocoder/rag/terminal/formatters/stream_json.py +95 -0
  436. autocoder/rag/terminal/formatters/text.py +28 -0
  437. autocoder/rag/terminal/init.py +120 -0
  438. autocoder/rag/terminal/utils.py +106 -0
  439. autocoder/rag/test_agentic_rag.py +389 -0
  440. autocoder/rag/test_doc_filter.py +3 -3
  441. autocoder/rag/test_long_context_rag.py +1 -1
  442. autocoder/rag/test_token_limiter.py +517 -10
  443. autocoder/rag/token_counter.py +3 -0
  444. autocoder/rag/token_limiter.py +19 -15
  445. autocoder/rag/tools/__init__.py +26 -2
  446. autocoder/rag/tools/bochaai_example.py +343 -0
  447. autocoder/rag/tools/bochaai_sdk.py +541 -0
  448. autocoder/rag/tools/metaso_example.py +268 -0
  449. autocoder/rag/tools/metaso_sdk.py +417 -0
  450. autocoder/rag/tools/recall_tool.py +28 -7
  451. autocoder/rag/tools/run_integration_tests.py +204 -0
  452. autocoder/rag/tools/test_all_providers.py +318 -0
  453. autocoder/rag/tools/test_bochaai_integration.py +482 -0
  454. autocoder/rag/tools/test_final_integration.py +215 -0
  455. autocoder/rag/tools/test_metaso_integration.py +424 -0
  456. autocoder/rag/tools/test_metaso_real.py +171 -0
  457. autocoder/rag/tools/test_web_crawl_tool.py +639 -0
  458. autocoder/rag/tools/test_web_search_tool.py +509 -0
  459. autocoder/rag/tools/todo_read_tool.py +202 -0
  460. autocoder/rag/tools/todo_write_tool.py +412 -0
  461. autocoder/rag/tools/web_crawl_tool.py +634 -0
  462. autocoder/rag/tools/web_search_tool.py +558 -0
  463. autocoder/rag/tools/web_tools_example.py +119 -0
  464. autocoder/rag/types.py +16 -0
  465. autocoder/rag/variable_holder.py +4 -2
  466. autocoder/rags.py +86 -79
  467. autocoder/regexproject/__init__.py +23 -21
  468. autocoder/sdk/__init__.py +46 -190
  469. autocoder/sdk/api.py +370 -0
  470. autocoder/sdk/async_runner/__init__.py +26 -0
  471. autocoder/sdk/async_runner/async_executor.py +650 -0
  472. autocoder/sdk/async_runner/async_handler.py +356 -0
  473. autocoder/sdk/async_runner/markdown_processor.py +595 -0
  474. autocoder/sdk/async_runner/task_metadata.py +284 -0
  475. autocoder/sdk/async_runner/worktree_manager.py +438 -0
  476. autocoder/sdk/cli/__init__.py +2 -5
  477. autocoder/sdk/cli/formatters.py +28 -204
  478. autocoder/sdk/cli/handlers.py +77 -44
  479. autocoder/sdk/cli/main.py +154 -171
  480. autocoder/sdk/cli/options.py +95 -22
  481. autocoder/sdk/constants.py +139 -51
  482. autocoder/sdk/core/auto_coder_core.py +484 -109
  483. autocoder/sdk/core/bridge.py +297 -115
  484. autocoder/sdk/exceptions.py +18 -12
  485. autocoder/sdk/formatters/__init__.py +19 -0
  486. autocoder/sdk/formatters/input.py +64 -0
  487. autocoder/sdk/formatters/output.py +247 -0
  488. autocoder/sdk/formatters/stream.py +54 -0
  489. autocoder/sdk/models/__init__.py +6 -5
  490. autocoder/sdk/models/options.py +55 -18
  491. autocoder/sdk/utils/formatters.py +27 -195
  492. autocoder/suffixproject/__init__.py +28 -25
  493. autocoder/terminal/__init__.py +14 -0
  494. autocoder/terminal/app.py +454 -0
  495. autocoder/terminal/args.py +32 -0
  496. autocoder/terminal/bootstrap.py +178 -0
  497. autocoder/terminal/command_processor.py +521 -0
  498. autocoder/terminal/command_registry.py +57 -0
  499. autocoder/terminal/help.py +97 -0
  500. autocoder/terminal/tasks/__init__.py +5 -0
  501. autocoder/terminal/tasks/background.py +77 -0
  502. autocoder/terminal/tasks/task_event.py +70 -0
  503. autocoder/terminal/ui/__init__.py +13 -0
  504. autocoder/terminal/ui/completer.py +268 -0
  505. autocoder/terminal/ui/keybindings.py +75 -0
  506. autocoder/terminal/ui/session.py +41 -0
  507. autocoder/terminal/ui/toolbar.py +64 -0
  508. autocoder/terminal/utils/__init__.py +13 -0
  509. autocoder/terminal/utils/errors.py +18 -0
  510. autocoder/terminal/utils/paths.py +19 -0
  511. autocoder/terminal/utils/shell.py +43 -0
  512. autocoder/terminal_v3/__init__.py +10 -0
  513. autocoder/terminal_v3/app.py +201 -0
  514. autocoder/terminal_v3/handlers/__init__.py +5 -0
  515. autocoder/terminal_v3/handlers/command_handler.py +131 -0
  516. autocoder/terminal_v3/models/__init__.py +6 -0
  517. autocoder/terminal_v3/models/conversation_buffer.py +214 -0
  518. autocoder/terminal_v3/models/message.py +50 -0
  519. autocoder/terminal_v3/models/tool_display.py +247 -0
  520. autocoder/terminal_v3/ui/__init__.py +7 -0
  521. autocoder/terminal_v3/ui/keybindings.py +56 -0
  522. autocoder/terminal_v3/ui/layout.py +141 -0
  523. autocoder/terminal_v3/ui/styles.py +43 -0
  524. autocoder/tsproject/__init__.py +23 -23
  525. autocoder/utils/auto_coder_utils/chat_stream_out.py +1 -1
  526. autocoder/utils/llms.py +88 -80
  527. autocoder/utils/math_utils.py +101 -0
  528. autocoder/utils/model_provider_selector.py +16 -4
  529. autocoder/utils/operate_config_api.py +33 -5
  530. autocoder/utils/thread_utils.py +2 -2
  531. autocoder/version.py +4 -2
  532. autocoder/workflow_agents/__init__.py +84 -0
  533. autocoder/workflow_agents/agent.py +143 -0
  534. autocoder/workflow_agents/exceptions.py +573 -0
  535. autocoder/workflow_agents/executor.py +489 -0
  536. autocoder/workflow_agents/loader.py +737 -0
  537. autocoder/workflow_agents/runner.py +267 -0
  538. autocoder/workflow_agents/types.py +172 -0
  539. autocoder/workflow_agents/utils.py +434 -0
  540. autocoder/workflow_agents/workflow_manager.py +211 -0
  541. auto_coder-1.0.0.dist-info/METADATA +0 -396
  542. auto_coder-1.0.0.dist-info/RECORD +0 -442
  543. auto_coder-1.0.0.dist-info/licenses/LICENSE +0 -201
  544. autocoder/auto_coder_server.py +0 -672
  545. autocoder/benchmark.py +0 -138
  546. autocoder/common/ac_style_command_parser/example.py +0 -7
  547. autocoder/common/cleaner.py +0 -31
  548. autocoder/common/command_completer_v2.py +0 -615
  549. autocoder/common/context_pruner.py +0 -477
  550. autocoder/common/conversation_pruner.py +0 -132
  551. autocoder/common/directory_cache/__init__.py +0 -1
  552. autocoder/common/directory_cache/cache.py +0 -192
  553. autocoder/common/directory_cache/test_cache.py +0 -190
  554. autocoder/common/file_checkpoint/examples.py +0 -217
  555. autocoder/common/llm_friendly_package_example.py +0 -138
  556. autocoder/common/llm_friendly_package_test.py +0 -63
  557. autocoder/common/pull_requests/test_module.py +0 -1
  558. autocoder/common/rulefiles/autocoderrules_utils.py +0 -484
  559. autocoder/common/text.py +0 -30
  560. autocoder/common/v2/agent/agentic_edit_tools/list_package_info_tool_resolver.py +0 -42
  561. autocoder/common/v2/agent/agentic_edit_tools/test_execute_command_tool_resolver.py +0 -70
  562. autocoder/common/v2/agent/agentic_edit_tools/test_search_files_tool_resolver.py +0 -163
  563. autocoder/common/v2/agent/agentic_tool_display.py +0 -183
  564. autocoder/plugins/dynamic_completion_example.py +0 -148
  565. autocoder/plugins/sample_plugin.py +0 -160
  566. autocoder/sdk/cli/__main__.py +0 -26
  567. autocoder/sdk/cli/completion_wrapper.py +0 -38
  568. autocoder/sdk/cli/install_completion.py +0 -301
  569. autocoder/sdk/models/messages.py +0 -209
  570. autocoder/sdk/session/__init__.py +0 -32
  571. autocoder/sdk/session/session.py +0 -106
  572. autocoder/sdk/session/session_manager.py +0 -56
  573. {auto_coder-1.0.0.dist-info → auto_coder-2.0.0.dist-info}/top_level.txt +0 -0
  574. /autocoder/{sdk/example.py → common/agent_query_queue/__init__.py} +0 -0
@@ -0,0 +1,664 @@
1
+ """
2
+ Integration tests for Shell Commands module.
3
+
4
+ This module provides comprehensive integration tests that verify
5
+ the interaction between different components of the shell commands
6
+ system including command execution, process management, timeout
7
+ handling, background processing, and interactive sessions.
8
+ """
9
+
10
+ import unittest
11
+ import pytest
12
+ import time
13
+ import tempfile
14
+ import os
15
+ import platform
16
+ import threading
17
+ from unittest.mock import patch
18
+ from typing import List, Dict, Any
19
+
20
+ from autocoder.common.shell_commands import (
21
+ CommandExecutor,
22
+ TimeoutConfig,
23
+ execute_command,
24
+ execute_command_background,
25
+ execute_commands,
26
+ get_background_processes,
27
+ get_background_process_info,
28
+ cleanup_background_process,
29
+ InteractiveCommandExecutor,
30
+ execute_interactive,
31
+ create_interactive_shell,
32
+ get_session_manager,
33
+ get_background_process_notifier,
34
+ CommandTimeoutError,
35
+ CommandExecutionError
36
+ )
37
+
38
+
39
+ class TestBasicIntegration(unittest.TestCase):
40
+ """Test basic integration between core components."""
41
+
42
+ def setUp(self):
43
+ """Set up integration test environment."""
44
+ self.temp_dir = tempfile.mkdtemp()
45
+
46
+ def tearDown(self):
47
+ """Clean up integration test environment."""
48
+ import shutil
49
+ try:
50
+ shutil.rmtree(self.temp_dir)
51
+ except:
52
+ pass
53
+
54
+ def test_command_executor_with_timeout_config(self):
55
+ """Test CommandExecutor integration with TimeoutConfig."""
56
+ # Create custom timeout configuration
57
+ config = TimeoutConfig(
58
+ default_timeout=5.0,
59
+ cleanup_timeout=2.0,
60
+ grace_period=1.0
61
+ )
62
+ config.set_command_timeout("echo*", 10.0)
63
+
64
+ # Create executor with custom config
65
+ executor = CommandExecutor(config=config, verbose=True)
66
+
67
+ try:
68
+ # Test normal command execution
69
+ exit_code, output = executor.execute("echo 'Hello Integration'")
70
+ self.assertEqual(exit_code, 0)
71
+ self.assertIn("Hello Integration", output)
72
+
73
+ # Test command with specific timeout
74
+ start_time = time.time()
75
+ exit_code, output = executor.execute("echo 'Specific timeout'")
76
+ duration = time.time() - start_time
77
+
78
+ self.assertEqual(exit_code, 0)
79
+ self.assertLess(duration, 10.0) # Should complete quickly
80
+
81
+ finally:
82
+ executor.cleanup()
83
+
84
+ def test_command_executor_with_working_directory(self):
85
+ """Test CommandExecutor with custom working directory."""
86
+ config = TimeoutConfig(default_timeout=10.0)
87
+ executor = CommandExecutor(config=config)
88
+
89
+ try:
90
+ # Test command in custom directory
91
+ if platform.system() == "Windows":
92
+ exit_code, output = executor.execute("dir", cwd=self.temp_dir)
93
+ else:
94
+ exit_code, output = executor.execute("pwd", cwd=self.temp_dir)
95
+
96
+ self.assertEqual(exit_code, 0)
97
+ if platform.system() != "Windows":
98
+ self.assertIn(self.temp_dir, output)
99
+
100
+ finally:
101
+ executor.cleanup()
102
+
103
+ def test_timeout_integration(self):
104
+ """Test timeout integration across components."""
105
+ config = TimeoutConfig(default_timeout=2.0)
106
+ executor = CommandExecutor(config=config)
107
+
108
+ try:
109
+ # Test timeout with cleanup
110
+ with self.assertRaises(CommandTimeoutError):
111
+ executor.execute("sleep 5") # Should timeout after 2 seconds
112
+
113
+ finally:
114
+ executor.cleanup()
115
+
116
+
117
+ class TestBackgroundProcessIntegration(unittest.TestCase):
118
+ """Test background process integration."""
119
+
120
+ def setUp(self):
121
+ """Set up background process tests."""
122
+ self.temp_dir = tempfile.mkdtemp()
123
+
124
+ def tearDown(self):
125
+ """Clean up background process tests."""
126
+ # Clean up any remaining background processes
127
+ try:
128
+ bg_processes = get_background_processes()
129
+ for pid in bg_processes.keys():
130
+ cleanup_background_process(pid)
131
+ except:
132
+ pass
133
+
134
+ import shutil
135
+ try:
136
+ shutil.rmtree(self.temp_dir)
137
+ except:
138
+ pass
139
+
140
+ @pytest.mark.integration
141
+ def test_background_execution_lifecycle(self):
142
+ """Test complete background execution lifecycle."""
143
+ # Start background process
144
+ info = execute_command_background(
145
+ "python -c \"import time; print('start'); time.sleep(1); print('end')\"",
146
+ cwd=self.temp_dir
147
+ )
148
+
149
+ try:
150
+ self.assertIn("pid", info)
151
+ self.assertIn("command", info)
152
+ pid = info["pid"]
153
+
154
+ # Verify process is tracked
155
+ bg_processes = get_background_processes()
156
+ self.assertIn(pid, bg_processes)
157
+
158
+ # Get process info
159
+ process_info = get_background_process_info(pid)
160
+ self.assertIsNotNone(process_info)
161
+ self.assertEqual(process_info["command"], info["command"])
162
+
163
+ # Wait for completion
164
+ start_time = time.time()
165
+ while time.time() - start_time < 10: # 10 second timeout
166
+ process_info = get_background_process_info(pid)
167
+ if process_info and process_info.get("status") == "completed":
168
+ break
169
+ time.sleep(0.1)
170
+
171
+ # Verify completion
172
+ final_info = get_background_process_info(pid)
173
+ self.assertEqual(final_info["status"], "completed")
174
+ self.assertEqual(final_info["exit_code"], 0)
175
+
176
+ finally:
177
+ # Clean up
178
+ cleanup_background_process(pid)
179
+
180
+ @pytest.mark.integration
181
+ def test_background_process_with_notifier(self):
182
+ """Test background process integration with notifier."""
183
+ import uuid
184
+
185
+ conv_id = f"test-{uuid.uuid4()}"
186
+ notifier = get_background_process_notifier()
187
+
188
+ try:
189
+ # Start background process
190
+ info = execute_command_background(
191
+ "python -c \"print('notification test')\"",
192
+ cwd=self.temp_dir
193
+ )
194
+
195
+ # Register with notifier
196
+ task_id = notifier.register_process(
197
+ conversation_id=conv_id,
198
+ pid=info["pid"],
199
+ tool_name="test_tool",
200
+ command=info["command"],
201
+ cwd=self.temp_dir
202
+ )
203
+
204
+ # Wait for completion notification
205
+ deadline = time.time() + 10.0
206
+ while time.time() < deadline:
207
+ if notifier.has_messages(conv_id):
208
+ break
209
+ time.sleep(0.1)
210
+
211
+ # Check for messages
212
+ messages = notifier.poll_messages(conv_id)
213
+ self.assertGreater(len(messages), 0)
214
+
215
+ message = messages[0]
216
+ self.assertEqual(message.task_id, task_id)
217
+ self.assertEqual(message.conversation_id, conv_id)
218
+ self.assertIn(message.status, ["completed", "failed"])
219
+
220
+ finally:
221
+ # Clean up
222
+ if 'info' in locals():
223
+ cleanup_background_process(info["pid"])
224
+
225
+ @pytest.mark.integration
226
+ def test_concurrent_background_processes(self):
227
+ """Test multiple concurrent background processes."""
228
+ processes = []
229
+
230
+ try:
231
+ # Start multiple background processes
232
+ for i in range(3):
233
+ info = execute_command_background(
234
+ f"python -c \"import time; print('process {i}'); time.sleep(0.5)\"",
235
+ cwd=self.temp_dir
236
+ )
237
+ processes.append(info)
238
+
239
+ # Verify all processes are tracked
240
+ bg_processes = get_background_processes()
241
+ for info in processes:
242
+ self.assertIn(info["pid"], bg_processes)
243
+
244
+ # Wait for all to complete
245
+ deadline = time.time() + 15.0
246
+ while time.time() < deadline:
247
+ all_completed = True
248
+ for info in processes:
249
+ process_info = get_background_process_info(info["pid"])
250
+ if not process_info or process_info.get("status") != "completed":
251
+ all_completed = False
252
+ break
253
+
254
+ if all_completed:
255
+ break
256
+ time.sleep(0.1)
257
+
258
+ # Verify all completed successfully
259
+ for info in processes:
260
+ process_info = get_background_process_info(info["pid"])
261
+ self.assertEqual(process_info["status"], "completed")
262
+ self.assertEqual(process_info["exit_code"], 0)
263
+
264
+ finally:
265
+ # Clean up all processes
266
+ for info in processes:
267
+ cleanup_background_process(info["pid"])
268
+
269
+
270
+ class TestInteractiveSessionIntegration(unittest.TestCase):
271
+ """Test interactive session integration."""
272
+
273
+ def setUp(self):
274
+ """Set up interactive session tests."""
275
+ self.temp_dir = tempfile.mkdtemp()
276
+
277
+ def tearDown(self):
278
+ """Clean up interactive session tests."""
279
+ # Clean up any remaining sessions
280
+ try:
281
+ manager = get_session_manager()
282
+ manager.cleanup_all()
283
+ except:
284
+ pass
285
+
286
+ import shutil
287
+ try:
288
+ shutil.rmtree(self.temp_dir)
289
+ except:
290
+ pass
291
+
292
+ @pytest.mark.integration
293
+ def test_interactive_session_creation_and_communication(self):
294
+ """Test creating interactive session and communication."""
295
+ manager = get_session_manager()
296
+
297
+ # Create session
298
+ result = manager.create_session(
299
+ "python -c \"import sys; print('Ready'); sys.stdout.flush(); exec(input())\"",
300
+ cwd=self.temp_dir,
301
+ timeout=30,
302
+ use_pexpect=False
303
+ )
304
+
305
+ try:
306
+ self.assertTrue(result.success, f"Session creation failed: {result.message}")
307
+ session_id = result.content["session_id"]
308
+
309
+ # Send input
310
+ input_result = manager.send_input(session_id, "print('Hello from session')\n")
311
+ self.assertTrue(input_result.success)
312
+
313
+ # Read output
314
+ time.sleep(0.5) # Give time for command to execute
315
+ output_result = manager.read_output(session_id)
316
+ # Output reading might not always succeed depending on timing
317
+ if not output_result.success:
318
+ print(f"Output read failed: {output_result.message}")
319
+ # Don't assert success as it may depend on timing
320
+
321
+ finally:
322
+ if result.success:
323
+ manager.terminate_session(result.content["session_id"])
324
+
325
+ @pytest.mark.integration
326
+ @pytest.mark.skipif(platform.system() == "Windows", reason="Shell behavior different on Windows")
327
+ def test_interactive_shell_integration(self):
328
+ """Test interactive shell integration."""
329
+ session = create_interactive_shell(timeout=30)
330
+
331
+ try:
332
+ self.assertIsNotNone(session)
333
+ self.assertTrue(session.process.is_alive())
334
+
335
+ # Send command
336
+ session.process.write("echo 'shell test'\n")
337
+
338
+ # Read output
339
+ time.sleep(0.5)
340
+ output = session.process.read_output(timeout=2.0)
341
+
342
+ # Output might contain shell control characters
343
+ if output:
344
+ # Clean the output and check for our test string
345
+ clean_output = output.replace('\x1b', '').replace('\r', '').replace('%', '')
346
+ if "shell test" not in clean_output:
347
+ print(f"Unexpected output: {repr(output)}")
348
+ # Don't fail the test as shell output can vary
349
+
350
+ finally:
351
+ session.terminate()
352
+
353
+ @pytest.mark.integration
354
+ def test_multiple_interactive_sessions(self):
355
+ """Test managing multiple interactive sessions."""
356
+ executor = InteractiveCommandExecutor()
357
+ sessions = []
358
+
359
+ try:
360
+ # Create multiple sessions
361
+ for i in range(3):
362
+ session = executor.execute_interactive(
363
+ f"python -c \"print('session {i}'); import time; time.sleep(1)\"",
364
+ timeout=10
365
+ )
366
+ sessions.append(session)
367
+
368
+ # Verify all sessions are active
369
+ session_list = executor.list_sessions()
370
+ self.assertEqual(len(session_list), 3)
371
+
372
+ # Verify each session has unique ID
373
+ session_ids = [s["session_id"] for s in session_list]
374
+ self.assertEqual(len(session_ids), len(set(session_ids)))
375
+
376
+ finally:
377
+ # Clean up all sessions
378
+ executor.cleanup()
379
+
380
+
381
+ class TestBatchExecutionIntegration(unittest.TestCase):
382
+ """Test batch execution integration."""
383
+
384
+ def setUp(self):
385
+ """Set up batch execution tests."""
386
+ self.temp_dir = tempfile.mkdtemp()
387
+
388
+ def tearDown(self):
389
+ """Clean up batch execution tests."""
390
+ import shutil
391
+ try:
392
+ shutil.rmtree(self.temp_dir)
393
+ except:
394
+ pass
395
+
396
+ @pytest.mark.integration
397
+ def test_batch_parallel_execution(self):
398
+ """Test parallel batch execution."""
399
+ commands = [
400
+ "echo 'Task 1'",
401
+ "echo 'Task 2'",
402
+ "echo 'Task 3'"
403
+ ]
404
+
405
+ start_time = time.time()
406
+ results = execute_commands(commands, parallel=True, timeout=10.0)
407
+ duration = time.time() - start_time
408
+
409
+ # Verify results
410
+ self.assertEqual(len(results), 3)
411
+
412
+ for i, result in enumerate(results):
413
+ self.assertEqual(result["index"], i)
414
+ self.assertEqual(result["exit_code"], 0)
415
+ self.assertIn(f"Task {i+1}", result["output"])
416
+ self.assertFalse(result["timed_out"])
417
+
418
+ # Parallel execution should be faster than serial
419
+ self.assertLess(duration, 5.0)
420
+
421
+ @pytest.mark.integration
422
+ def test_batch_serial_execution(self):
423
+ """Test serial batch execution."""
424
+ commands = [
425
+ "echo 'Step 1'",
426
+ "echo 'Step 2'",
427
+ "echo 'Step 3'"
428
+ ]
429
+
430
+ results = execute_commands(commands, parallel=False, timeout=10.0)
431
+
432
+ # Verify results are in order
433
+ self.assertEqual(len(results), 3)
434
+
435
+ for i, result in enumerate(results):
436
+ self.assertEqual(result["index"], i)
437
+ self.assertEqual(result["exit_code"], 0)
438
+ self.assertIn(f"Step {i+1}", result["output"])
439
+
440
+ @pytest.mark.integration
441
+ def test_batch_with_failures(self):
442
+ """Test batch execution with some failures."""
443
+ commands = [
444
+ "echo 'Success'",
445
+ "python -c \"import sys; sys.exit(1)\"", # This will fail
446
+ "echo 'Another success'"
447
+ ]
448
+
449
+ results = execute_commands(commands, parallel=True, timeout=10.0)
450
+
451
+ # Verify mixed results
452
+ self.assertEqual(len(results), 3)
453
+ self.assertEqual(results[0]["exit_code"], 0) # Success
454
+ self.assertEqual(results[1]["exit_code"], 1) # Failure
455
+ self.assertEqual(results[2]["exit_code"], 0) # Success
456
+
457
+ @pytest.mark.integration
458
+ def test_batch_with_timeout(self):
459
+ """Test batch execution with timeouts."""
460
+ commands = [
461
+ "echo 'Quick task'",
462
+ "python -c \"import time; time.sleep(5)\"", # This will timeout
463
+ "echo 'Another quick task'"
464
+ ]
465
+
466
+ results = execute_commands(
467
+ commands,
468
+ parallel=True,
469
+ per_command_timeout=1.0, # Short timeout
470
+ timeout=10.0
471
+ )
472
+
473
+ # Verify timeout behavior
474
+ self.assertEqual(len(results), 3)
475
+ self.assertEqual(results[0]["exit_code"], 0) # Should succeed
476
+ self.assertTrue(results[1]["timed_out"]) # Should timeout
477
+ self.assertEqual(results[2]["exit_code"], 0) # Should succeed
478
+
479
+
480
+ class TestErrorHandlingIntegration(unittest.TestCase):
481
+ """Test error handling integration across components."""
482
+
483
+ def setUp(self):
484
+ """Set up error handling tests."""
485
+ self.temp_dir = tempfile.mkdtemp()
486
+
487
+ def tearDown(self):
488
+ """Clean up error handling tests."""
489
+ import shutil
490
+ try:
491
+ shutil.rmtree(self.temp_dir)
492
+ except:
493
+ pass
494
+
495
+ def test_timeout_error_propagation(self):
496
+ """Test timeout error propagation through components."""
497
+ config = TimeoutConfig(default_timeout=1.0)
498
+ executor = CommandExecutor(config=config)
499
+
500
+ try:
501
+ with self.assertRaises(CommandTimeoutError) as cm:
502
+ executor.execute("python -c \"import time; time.sleep(5)\"")
503
+
504
+ # Verify error details
505
+ error = cm.exception
506
+ self.assertIn("python", error.command)
507
+ self.assertEqual(error.timeout, 1.0)
508
+ self.assertIsNotNone(error.pid)
509
+
510
+ finally:
511
+ executor.cleanup()
512
+
513
+ def test_invalid_command_error_handling(self):
514
+ """Test handling of invalid commands."""
515
+ executor = CommandExecutor()
516
+
517
+ try:
518
+ # On macOS, invalid commands may not always raise exceptions
519
+ # They might return with exit code 127 instead
520
+ exit_code, output = executor.execute("/nonexistent/command/that/does/not/exist")
521
+ # If no exception is raised, check that exit code indicates failure
522
+ self.assertNotEqual(exit_code, 0, "Invalid command should not succeed")
523
+
524
+ finally:
525
+ executor.cleanup()
526
+
527
+ def test_background_process_error_handling(self):
528
+ """Test error handling in background processes."""
529
+ # Start a background process that will fail
530
+ info = execute_command_background(
531
+ "python -c \"import sys; sys.exit(42)\"", # Exit with code 42
532
+ cwd=self.temp_dir
533
+ )
534
+
535
+ try:
536
+ pid = info["pid"]
537
+
538
+ # Wait for completion
539
+ deadline = time.time() + 10.0
540
+ while time.time() < deadline:
541
+ process_info = get_background_process_info(pid)
542
+ if process_info and process_info.get("status") == "completed":
543
+ break
544
+ time.sleep(0.1)
545
+
546
+ # Verify error is captured
547
+ final_info = get_background_process_info(pid)
548
+ self.assertEqual(final_info["status"], "completed")
549
+ self.assertEqual(final_info["exit_code"], 42)
550
+
551
+ finally:
552
+ cleanup_background_process(pid)
553
+
554
+
555
+ class TestConcurrencyIntegration(unittest.TestCase):
556
+ """Test concurrency integration across components."""
557
+
558
+ def setUp(self):
559
+ """Set up concurrency tests."""
560
+ self.temp_dir = tempfile.mkdtemp()
561
+
562
+ def tearDown(self):
563
+ """Clean up concurrency tests."""
564
+ import shutil
565
+ try:
566
+ shutil.rmtree(self.temp_dir)
567
+ except:
568
+ pass
569
+
570
+ @pytest.mark.integration
571
+ def test_concurrent_command_execution(self):
572
+ """Test concurrent command execution."""
573
+ config = TimeoutConfig(default_timeout=10.0)
574
+ results = []
575
+ threads = []
576
+
577
+ def execute_command_thread(index):
578
+ try:
579
+ executor = CommandExecutor(config=config)
580
+ exit_code, output = executor.execute(f"echo 'Thread {index}'")
581
+ results.append((index, exit_code, output))
582
+ executor.cleanup()
583
+ except Exception as e:
584
+ results.append((index, -1, str(e)))
585
+
586
+ # Start multiple concurrent executions
587
+ for i in range(5):
588
+ thread = threading.Thread(target=execute_command_thread, args=(i,))
589
+ threads.append(thread)
590
+ thread.start()
591
+
592
+ # Wait for all threads
593
+ for thread in threads:
594
+ thread.join(timeout=15.0)
595
+
596
+ # Verify all completed successfully
597
+ self.assertEqual(len(results), 5)
598
+ for index, exit_code, output in results:
599
+ self.assertEqual(exit_code, 0)
600
+ self.assertIn(f"Thread {index}", output)
601
+
602
+ @pytest.mark.integration
603
+ def test_concurrent_background_processes(self):
604
+ """Test concurrent background process management."""
605
+ processes = []
606
+ threads = []
607
+
608
+ def start_background_process(index):
609
+ try:
610
+ info = execute_command_background(
611
+ f"python -c \"import time; print('BG {index}'); time.sleep(0.5)\"",
612
+ cwd=self.temp_dir
613
+ )
614
+ processes.append(info)
615
+ except Exception as e:
616
+ processes.append({"error": str(e), "index": index})
617
+
618
+ # Start multiple background processes concurrently
619
+ for i in range(3):
620
+ thread = threading.Thread(target=start_background_process, args=(i,))
621
+ threads.append(thread)
622
+ thread.start()
623
+
624
+ # Wait for all threads
625
+ for thread in threads:
626
+ thread.join(timeout=10.0)
627
+
628
+ try:
629
+ # Verify all processes started
630
+ self.assertEqual(len(processes), 3)
631
+ for info in processes:
632
+ self.assertNotIn("error", info)
633
+ self.assertIn("pid", info)
634
+
635
+ # Wait for all to complete
636
+ deadline = time.time() + 15.0
637
+ while time.time() < deadline:
638
+ all_completed = True
639
+ for info in processes:
640
+ if "pid" in info:
641
+ process_info = get_background_process_info(info["pid"])
642
+ if not process_info or process_info.get("status") != "completed":
643
+ all_completed = False
644
+ break
645
+
646
+ if all_completed:
647
+ break
648
+ time.sleep(0.1)
649
+
650
+ # Verify all completed
651
+ for info in processes:
652
+ if "pid" in info:
653
+ process_info = get_background_process_info(info["pid"])
654
+ self.assertEqual(process_info["status"], "completed")
655
+
656
+ finally:
657
+ # Clean up
658
+ for info in processes:
659
+ if "pid" in info:
660
+ cleanup_background_process(info["pid"])
661
+
662
+
663
+ if __name__ == "__main__":
664
+ unittest.main()