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,632 @@
1
+ """
2
+ Performance tests for Shell Commands module.
3
+
4
+ This module provides performance tests to verify that the shell commands
5
+ system performs well under various load conditions including high
6
+ throughput, concurrent operations, memory usage, and stress scenarios.
7
+ """
8
+
9
+ import unittest
10
+ import pytest
11
+ import time
12
+ import threading
13
+ import tempfile
14
+ import os
15
+ import psutil
16
+ import statistics
17
+ from typing import List, Dict, Any, Tuple
18
+ from concurrent.futures import ThreadPoolExecutor, as_completed
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
+ cleanup_background_process,
28
+ InteractiveCommandExecutor,
29
+ get_session_manager,
30
+ get_background_process_notifier
31
+ )
32
+
33
+
34
+ class PerformanceTestCase(unittest.TestCase):
35
+ """Base class for performance tests with common utilities."""
36
+
37
+ def setUp(self):
38
+ """Set up performance test environment."""
39
+ self.temp_dir = tempfile.mkdtemp()
40
+ self.start_memory = self._get_memory_usage()
41
+ self.performance_data = {}
42
+
43
+ def tearDown(self):
44
+ """Clean up performance test environment."""
45
+ # Clean up any remaining processes
46
+ try:
47
+ bg_processes = get_background_processes()
48
+ for pid in bg_processes.keys():
49
+ cleanup_background_process(pid)
50
+ except:
51
+ pass
52
+
53
+ # Clean up sessions
54
+ try:
55
+ manager = get_session_manager()
56
+ manager.cleanup_all()
57
+ except:
58
+ pass
59
+
60
+ import shutil
61
+ try:
62
+ shutil.rmtree(self.temp_dir)
63
+ except:
64
+ pass
65
+
66
+ # Report memory usage
67
+ end_memory = self._get_memory_usage()
68
+ memory_diff = end_memory - self.start_memory
69
+ if memory_diff > 50 * 1024 * 1024: # 50MB threshold
70
+ print(f"Warning: Memory usage increased by {memory_diff / 1024 / 1024:.1f}MB")
71
+
72
+ def _get_memory_usage(self) -> int:
73
+ """Get current process memory usage in bytes."""
74
+ try:
75
+ process = psutil.Process()
76
+ return process.memory_info().rss
77
+ except:
78
+ return 0
79
+
80
+ def _measure_time(self, func, *args, **kwargs):
81
+ """Measure execution time of a function."""
82
+ start_time = time.time()
83
+ result = func(*args, **kwargs)
84
+ end_time = time.time()
85
+ return result, end_time - start_time
86
+
87
+ def _measure_throughput(self, func, iterations: int, *args, **kwargs) -> Tuple[List[Any], float]:
88
+ """Measure throughput of a function over multiple iterations."""
89
+ results = []
90
+ start_time = time.time()
91
+
92
+ for _ in range(iterations):
93
+ result = func(*args, **kwargs)
94
+ results.append(result)
95
+
96
+ end_time = time.time()
97
+ total_time = end_time - start_time
98
+ throughput = iterations / total_time if total_time > 0 else 0
99
+
100
+ return results, throughput
101
+
102
+
103
+ @pytest.mark.performance
104
+ class TestCommandExecutionPerformance(PerformanceTestCase):
105
+ """Test command execution performance."""
106
+
107
+ def test_single_command_performance(self):
108
+ """Test performance of single command execution."""
109
+ config = TimeoutConfig(default_timeout=30.0)
110
+ executor = CommandExecutor(config=config)
111
+
112
+ try:
113
+ # Measure simple command execution
114
+ _, duration = self._measure_time(
115
+ executor.execute, "echo 'performance test'"
116
+ )
117
+
118
+ # Should complete quickly
119
+ self.assertLess(duration, 1.0, "Simple command should complete in under 1 second")
120
+
121
+ # Measure multiple executions for consistency
122
+ durations = []
123
+ for _ in range(10):
124
+ _, duration = self._measure_time(
125
+ executor.execute, "echo 'test'"
126
+ )
127
+ durations.append(duration)
128
+
129
+ avg_duration = statistics.mean(durations)
130
+ std_deviation = statistics.stdev(durations) if len(durations) > 1 else 0
131
+
132
+ self.assertLess(avg_duration, 0.5, "Average execution time should be reasonable")
133
+ self.assertLess(std_deviation, 0.2, "Execution time should be consistent")
134
+
135
+ finally:
136
+ executor.cleanup()
137
+
138
+ def test_concurrent_command_execution_performance(self):
139
+ """Test performance under concurrent command execution."""
140
+ num_threads = 10
141
+ commands_per_thread = 5
142
+
143
+ def execute_commands_worker():
144
+ config = TimeoutConfig(default_timeout=10.0)
145
+ executor = CommandExecutor(config=config)
146
+ durations = []
147
+
148
+ try:
149
+ for i in range(commands_per_thread):
150
+ _, duration = self._measure_time(
151
+ executor.execute, f"echo 'worker command {i}'"
152
+ )
153
+ durations.append(duration)
154
+ return durations
155
+ finally:
156
+ executor.cleanup()
157
+
158
+ # Execute commands concurrently
159
+ start_time = time.time()
160
+ with ThreadPoolExecutor(max_workers=num_threads) as executor:
161
+ futures = [executor.submit(execute_commands_worker) for _ in range(num_threads)]
162
+ results = [future.result() for future in as_completed(futures)]
163
+
164
+ total_time = time.time() - start_time
165
+
166
+ # Calculate statistics
167
+ all_durations = [duration for worker_durations in results for duration in worker_durations]
168
+ total_commands = num_threads * commands_per_thread
169
+ avg_duration = statistics.mean(all_durations)
170
+ throughput = total_commands / total_time
171
+
172
+ # Performance assertions
173
+ self.assertGreater(throughput, 10, "Should achieve reasonable throughput")
174
+ self.assertLess(avg_duration, 2.0, "Average command duration should be reasonable")
175
+ self.assertLess(total_time, 30.0, "Total execution time should be reasonable")
176
+
177
+ print(f"Concurrent execution: {total_commands} commands in {total_time:.2f}s "
178
+ f"(throughput: {throughput:.1f} cmd/s, avg: {avg_duration:.3f}s)")
179
+
180
+ def test_batch_execution_performance(self):
181
+ """Test batch execution performance."""
182
+ # Test parallel batch execution
183
+ commands = [f"echo 'batch command {i}'" for i in range(20)]
184
+
185
+ # Measure parallel execution
186
+ parallel_results, parallel_time = self._measure_time(
187
+ execute_commands, commands, parallel=True, timeout=30.0
188
+ )
189
+
190
+ # Measure serial execution
191
+ serial_results, serial_time = self._measure_time(
192
+ execute_commands, commands, parallel=False, timeout=60.0
193
+ )
194
+
195
+ # Verify all commands succeeded
196
+ self.assertEqual(len(parallel_results), 20)
197
+ self.assertEqual(len(serial_results), 20)
198
+
199
+ for result in parallel_results + serial_results:
200
+ self.assertEqual(result["exit_code"], 0)
201
+
202
+ # Parallel should be significantly faster for I/O bound tasks
203
+ speedup_ratio = serial_time / parallel_time if parallel_time > 0 else 1
204
+
205
+ print(f"Batch execution: Parallel {parallel_time:.2f}s vs Serial {serial_time:.2f}s "
206
+ f"(speedup: {speedup_ratio:.1f}x)")
207
+
208
+ # Allow for some overhead, but parallel should still be faster
209
+ self.assertLess(parallel_time, serial_time * 0.8,
210
+ "Parallel execution should be significantly faster")
211
+
212
+
213
+ @pytest.mark.performance
214
+ class TestBackgroundProcessPerformance(PerformanceTestCase):
215
+ """Test background process performance."""
216
+
217
+ def test_background_process_creation_performance(self):
218
+ """Test performance of background process creation."""
219
+ num_processes = 20
220
+ processes = []
221
+
222
+ try:
223
+ # Measure batch creation
224
+ creation_durations = []
225
+ for i in range(num_processes):
226
+ _, duration = self._measure_time(
227
+ execute_command_background,
228
+ f"python -c \"import time; print('bg {i}'); time.sleep(0.1)\"",
229
+ cwd=self.temp_dir
230
+ )
231
+ creation_durations.append(duration)
232
+ # Track for cleanup
233
+ processes.append(_)
234
+
235
+ avg_creation_time = statistics.mean(creation_durations)
236
+ max_creation_time = max(creation_durations)
237
+
238
+ # Performance assertions
239
+ self.assertLess(avg_creation_time, 0.5, "Background process creation should be fast")
240
+ self.assertLess(max_creation_time, 2.0, "No single creation should be too slow")
241
+
242
+ print(f"Background process creation: avg {avg_creation_time:.3f}s, "
243
+ f"max {max_creation_time:.3f}s for {num_processes} processes")
244
+
245
+ # Verify all processes are tracked
246
+ bg_processes = get_background_processes()
247
+ active_count = len([p for p in bg_processes.values() if p.get("status") == "running"])
248
+ self.assertGreaterEqual(active_count, num_processes * 0.5) # At least half should still be running
249
+
250
+ finally:
251
+ # Clean up all processes
252
+ for info in processes:
253
+ if isinstance(info, dict) and "pid" in info:
254
+ cleanup_background_process(info["pid"])
255
+
256
+ def test_background_process_monitoring_performance(self):
257
+ """Test performance of background process monitoring."""
258
+ num_processes = 10
259
+ processes = []
260
+
261
+ try:
262
+ # Start background processes
263
+ for i in range(num_processes):
264
+ info = execute_command_background(
265
+ f"python -c \"import time; time.sleep(2); print('done {i}')\"",
266
+ cwd=self.temp_dir
267
+ )
268
+ processes.append(info)
269
+
270
+ # Measure monitoring performance
271
+ monitoring_durations = []
272
+ for _ in range(20): # Multiple monitoring cycles
273
+ _, duration = self._measure_time(get_background_processes)
274
+ monitoring_durations.append(duration)
275
+ time.sleep(0.1)
276
+
277
+ avg_monitoring_time = statistics.mean(monitoring_durations)
278
+ max_monitoring_time = max(monitoring_durations)
279
+
280
+ # Performance assertions
281
+ self.assertLess(avg_monitoring_time, 0.1, "Process monitoring should be fast")
282
+ self.assertLess(max_monitoring_time, 0.5, "No monitoring call should be too slow")
283
+
284
+ print(f"Background process monitoring: avg {avg_monitoring_time:.3f}s, "
285
+ f"max {max_monitoring_time:.3f}s per call")
286
+
287
+ finally:
288
+ # Clean up
289
+ for info in processes:
290
+ cleanup_background_process(info["pid"])
291
+
292
+ def test_background_process_notifier_performance(self):
293
+ """Test background process notifier performance."""
294
+ import uuid
295
+
296
+ conv_id = f"perf-test-{uuid.uuid4()}"
297
+ notifier = get_background_process_notifier()
298
+ num_processes = 15
299
+ processes = []
300
+
301
+ try:
302
+ # Start multiple background processes and register them
303
+ registration_durations = []
304
+ for i in range(num_processes):
305
+ info = execute_command_background(
306
+ f"python -c \"import time; time.sleep(0.5); print('notifier test {i}')\"",
307
+ cwd=self.temp_dir
308
+ )
309
+ processes.append(info)
310
+
311
+ # Measure registration time
312
+ _, duration = self._measure_time(
313
+ notifier.register_process,
314
+ conversation_id=conv_id,
315
+ pid=info["pid"],
316
+ tool_name="perf_test",
317
+ command=info["command"],
318
+ cwd=self.temp_dir
319
+ )
320
+ registration_durations.append(duration)
321
+
322
+ avg_registration_time = statistics.mean(registration_durations)
323
+
324
+ # Test message polling performance
325
+ polling_durations = []
326
+ total_messages = 0
327
+
328
+ # Poll for completion messages
329
+ deadline = time.time() + 30.0
330
+ while time.time() < deadline:
331
+ _, duration = self._measure_time(
332
+ notifier.poll_messages, conv_id, 10
333
+ )
334
+ polling_durations.append(duration)
335
+
336
+ messages = notifier.poll_messages(conv_id, 10)
337
+ total_messages += len(messages)
338
+
339
+ if total_messages >= num_processes:
340
+ break
341
+
342
+ time.sleep(0.1)
343
+
344
+ if polling_durations:
345
+ avg_polling_time = statistics.mean(polling_durations)
346
+ max_polling_time = max(polling_durations)
347
+
348
+ # Performance assertions
349
+ self.assertLess(avg_registration_time, 0.1, "Process registration should be fast")
350
+ self.assertLess(avg_polling_time, 0.05, "Message polling should be very fast")
351
+ self.assertLess(max_polling_time, 0.2, "No polling should be too slow")
352
+
353
+ print(f"Notifier performance: registration avg {avg_registration_time:.3f}s, "
354
+ f"polling avg {avg_polling_time:.3f}s")
355
+
356
+ finally:
357
+ # Clean up
358
+ for info in processes:
359
+ cleanup_background_process(info["pid"])
360
+
361
+
362
+ @pytest.mark.performance
363
+ class TestInteractiveSessionPerformance(PerformanceTestCase):
364
+ """Test interactive session performance."""
365
+
366
+ def test_session_creation_performance(self):
367
+ """Test performance of interactive session creation."""
368
+ manager = get_session_manager()
369
+ num_sessions = 10
370
+ session_ids = []
371
+
372
+ try:
373
+ # Measure session creation
374
+ creation_durations = []
375
+ for i in range(num_sessions):
376
+ _, duration = self._measure_time(
377
+ manager.create_session,
378
+ f"python -c \"print('session {i}'); import time; time.sleep(0.5)\"",
379
+ timeout=30,
380
+ use_pexpect=False
381
+ )
382
+ creation_durations.append(duration)
383
+
384
+ if _.success:
385
+ session_ids.append(_.content["session_id"])
386
+
387
+ avg_creation_time = statistics.mean(creation_durations)
388
+ successful_sessions = len(session_ids)
389
+
390
+ # Performance assertions
391
+ self.assertLess(avg_creation_time, 2.0, "Session creation should be reasonably fast")
392
+ self.assertGreaterEqual(successful_sessions, num_sessions * 0.8, "Most sessions should be created successfully")
393
+
394
+ print(f"Session creation: avg {avg_creation_time:.3f}s for {successful_sessions}/{num_sessions} sessions")
395
+
396
+ finally:
397
+ # Clean up sessions
398
+ for session_id in session_ids:
399
+ try:
400
+ manager.terminate_session(session_id)
401
+ except:
402
+ pass
403
+
404
+ def test_session_communication_performance(self):
405
+ """Test performance of session communication."""
406
+ manager = get_session_manager()
407
+
408
+ # Create a session
409
+ result = manager.create_session(
410
+ "python -c \"import sys; [print(input()) for _ in range(100)]\"",
411
+ timeout=60,
412
+ use_pexpect=False
413
+ )
414
+
415
+ if not result.success:
416
+ self.skipTest("Could not create session for performance test")
417
+
418
+ session_id = result.content["session_id"]
419
+
420
+ try:
421
+ # Measure input/output performance
422
+ communication_durations = []
423
+ for i in range(20):
424
+ # Measure sending input
425
+ _, send_duration = self._measure_time(
426
+ manager.send_input, session_id, f"Message {i}\n"
427
+ )
428
+
429
+ # Small delay to let command process
430
+ time.sleep(0.05)
431
+
432
+ # Measure reading output
433
+ _, read_duration = self._measure_time(
434
+ manager.read_output, session_id
435
+ )
436
+
437
+ total_duration = send_duration + read_duration
438
+ communication_durations.append(total_duration)
439
+
440
+ avg_communication_time = statistics.mean(communication_durations)
441
+ max_communication_time = max(communication_durations)
442
+
443
+ # Performance assertions
444
+ self.assertLess(avg_communication_time, 0.5, "Session communication should be fast")
445
+ self.assertLess(max_communication_time, 2.0, "No single communication should be too slow")
446
+
447
+ print(f"Session communication: avg {avg_communication_time:.3f}s, "
448
+ f"max {max_communication_time:.3f}s per round-trip")
449
+
450
+ finally:
451
+ manager.terminate_session(session_id)
452
+
453
+ def test_concurrent_session_performance(self):
454
+ """Test performance with multiple concurrent sessions."""
455
+ manager = get_session_manager()
456
+ num_sessions = 8 # Reasonable number for concurrent testing
457
+
458
+ def session_worker(session_index):
459
+ """Worker function for concurrent session testing."""
460
+ timings = []
461
+ session_id = None
462
+
463
+ try:
464
+ # Create session
465
+ start_time = time.time()
466
+ result = manager.create_session(
467
+ f"python -c \"import time; print('session {session_index} ready'); "
468
+ f"[print(input()) for _ in range(5)]\"",
469
+ timeout=30,
470
+ use_pexpect=False
471
+ )
472
+ creation_time = time.time() - start_time
473
+
474
+ if not result.success:
475
+ return {"error": f"Failed to create session {session_index}"}
476
+
477
+ session_id = result.content["session_id"]
478
+ timings.append(("creation", creation_time))
479
+
480
+ # Perform some communication
481
+ for i in range(5):
482
+ start_time = time.time()
483
+ manager.send_input(session_id, f"Message {i} from session {session_index}\n")
484
+ time.sleep(0.02) # Small delay
485
+ manager.read_output(session_id)
486
+ comm_time = time.time() - start_time
487
+ timings.append(("communication", comm_time))
488
+
489
+ return {"session_index": session_index, "timings": timings}
490
+
491
+ except Exception as e:
492
+ return {"error": f"Session {session_index} error: {str(e)}"}
493
+ finally:
494
+ if session_id:
495
+ try:
496
+ manager.terminate_session(session_id)
497
+ except:
498
+ pass
499
+
500
+ # Execute concurrent sessions
501
+ start_time = time.time()
502
+ with ThreadPoolExecutor(max_workers=num_sessions) as executor:
503
+ futures = [executor.submit(session_worker, i) for i in range(num_sessions)]
504
+ results = [future.result() for future in as_completed(futures)]
505
+ total_time = time.time() - start_time
506
+
507
+ # Analyze results
508
+ successful_sessions = [r for r in results if "error" not in r]
509
+ failed_sessions = [r for r in results if "error" in r]
510
+
511
+ if failed_sessions:
512
+ print(f"Failed sessions: {len(failed_sessions)}")
513
+ for failure in failed_sessions:
514
+ print(f" {failure['error']}")
515
+
516
+ self.assertGreater(len(successful_sessions), num_sessions * 0.7,
517
+ "Most concurrent sessions should succeed")
518
+
519
+ if successful_sessions:
520
+ all_timings = []
521
+ for session_result in successful_sessions:
522
+ all_timings.extend(session_result["timings"])
523
+
524
+ creation_times = [t[1] for t in all_timings if t[0] == "creation"]
525
+ communication_times = [t[1] for t in all_timings if t[0] == "communication"]
526
+
527
+ if creation_times:
528
+ avg_creation = statistics.mean(creation_times)
529
+ print(f"Concurrent sessions: {len(successful_sessions)} sessions, "
530
+ f"avg creation {avg_creation:.3f}s, total time {total_time:.2f}s")
531
+
532
+ self.assertLess(avg_creation, 5.0, "Concurrent session creation should be reasonable")
533
+
534
+
535
+ @pytest.mark.performance
536
+ class TestMemoryPerformance(PerformanceTestCase):
537
+ """Test memory usage performance."""
538
+
539
+ def test_memory_usage_under_load(self):
540
+ """Test memory usage under high load."""
541
+ initial_memory = self._get_memory_usage()
542
+
543
+ # Create multiple executors and run commands
544
+ executors = []
545
+ try:
546
+ for i in range(10):
547
+ config = TimeoutConfig(default_timeout=30.0)
548
+ executor = CommandExecutor(config=config)
549
+ executors.append(executor)
550
+
551
+ # Execute some commands
552
+ for j in range(5):
553
+ executor.execute(f"echo 'executor {i} command {j}'")
554
+
555
+ # Check memory usage after load
556
+ peak_memory = self._get_memory_usage()
557
+ memory_increase = peak_memory - initial_memory
558
+
559
+ print(f"Memory usage: initial {initial_memory // 1024 // 1024}MB, "
560
+ f"peak {peak_memory // 1024 // 1024}MB, "
561
+ f"increase {memory_increase // 1024 // 1024}MB")
562
+
563
+ # Memory increase should be reasonable (less than 100MB for this test)
564
+ self.assertLess(memory_increase, 100 * 1024 * 1024,
565
+ "Memory usage should not increase excessively")
566
+
567
+ finally:
568
+ # Clean up executors
569
+ for executor in executors:
570
+ executor.cleanup()
571
+
572
+ # Force garbage collection
573
+ import gc
574
+ gc.collect()
575
+
576
+ # Check memory after cleanup
577
+ final_memory = self._get_memory_usage()
578
+ memory_after_cleanup = final_memory - initial_memory
579
+
580
+ print(f"Memory after cleanup: {final_memory // 1024 // 1024}MB, "
581
+ f"net increase {memory_after_cleanup // 1024 // 1024}MB")
582
+
583
+ def test_background_process_memory_scaling(self):
584
+ """Test memory usage with many background processes."""
585
+ initial_memory = self._get_memory_usage()
586
+ processes = []
587
+
588
+ try:
589
+ # Start many short-lived background processes
590
+ for i in range(50):
591
+ info = execute_command_background(
592
+ f"python -c \"import time; time.sleep(0.2); print('done {i}')\"",
593
+ cwd=self.temp_dir
594
+ )
595
+ processes.append(info)
596
+
597
+ # Check memory periodically
598
+ if i % 10 == 0:
599
+ current_memory = self._get_memory_usage()
600
+ memory_per_process = (current_memory - initial_memory) // (i + 1) if i > 0 else 0
601
+ print(f"After {i+1} processes: {memory_per_process // 1024}KB per process")
602
+
603
+ # Wait for processes to complete
604
+ deadline = time.time() + 30.0
605
+ while time.time() < deadline:
606
+ bg_processes = get_background_processes()
607
+ active_count = len([p for p in bg_processes.values() if p.get("status") == "running"])
608
+ if active_count == 0:
609
+ break
610
+ time.sleep(0.5)
611
+
612
+ peak_memory = self._get_memory_usage()
613
+ total_increase = peak_memory - initial_memory
614
+ memory_per_process = total_increase // len(processes)
615
+
616
+ print(f"Memory scaling: {len(processes)} processes, "
617
+ f"total increase {total_increase // 1024 // 1024}MB, "
618
+ f"~{memory_per_process // 1024}KB per process")
619
+
620
+ # Each process shouldn't use excessive memory
621
+ self.assertLess(memory_per_process, 5 * 1024 * 1024, # 5MB per process
622
+ "Memory per process should be reasonable")
623
+
624
+ finally:
625
+ # Clean up
626
+ for info in processes:
627
+ cleanup_background_process(info["pid"])
628
+
629
+
630
+ if __name__ == "__main__":
631
+ # Run performance tests with verbose output
632
+ unittest.main(verbosity=2)