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.
- auto_coder-2.0.0.dist-info/LICENSE +158 -0
- auto_coder-2.0.0.dist-info/METADATA +558 -0
- auto_coder-2.0.0.dist-info/RECORD +795 -0
- {auto_coder-1.0.0.dist-info → auto_coder-2.0.0.dist-info}/WHEEL +1 -1
- {auto_coder-1.0.0.dist-info → auto_coder-2.0.0.dist-info}/entry_points.txt +3 -3
- autocoder/__init__.py +31 -0
- autocoder/agent/auto_filegroup.py +32 -13
- autocoder/agent/auto_learn_from_commit.py +9 -1
- autocoder/agent/base_agentic/__init__.py +3 -0
- autocoder/agent/base_agentic/agent_hub.py +1 -1
- autocoder/agent/base_agentic/base_agent.py +235 -136
- autocoder/agent/base_agentic/default_tools.py +119 -118
- autocoder/agent/base_agentic/test_base_agent.py +1 -1
- autocoder/agent/base_agentic/tool_registry.py +32 -20
- autocoder/agent/base_agentic/tools/read_file_tool_resolver.py +24 -3
- autocoder/agent/base_agentic/tools/write_to_file_tool_resolver.py +24 -11
- autocoder/agent/base_agentic/types.py +42 -0
- autocoder/agent/entry_command_agent/chat.py +73 -59
- autocoder/auto_coder.py +31 -40
- autocoder/auto_coder_rag.py +11 -1084
- autocoder/auto_coder_runner.py +970 -2345
- autocoder/auto_coder_terminal.py +26 -0
- autocoder/auto_coder_terminal_v3.py +190 -0
- autocoder/chat/conf_command.py +224 -124
- autocoder/chat/models_command.py +361 -299
- autocoder/chat/rules_command.py +79 -31
- autocoder/chat_auto_coder.py +988 -398
- autocoder/chat_auto_coder_lang.py +23 -732
- autocoder/commands/auto_command.py +25 -8
- autocoder/commands/auto_web.py +1 -1
- autocoder/commands/tools.py +44 -44
- autocoder/common/__init__.py +150 -128
- autocoder/common/ac_style_command_parser/__init__.py +39 -2
- autocoder/common/ac_style_command_parser/config.py +422 -0
- autocoder/common/ac_style_command_parser/parser.py +292 -78
- autocoder/common/ac_style_command_parser/test_parser.py +241 -16
- autocoder/common/ac_style_command_parser/test_typed_parser.py +342 -0
- autocoder/common/ac_style_command_parser/typed_parser.py +653 -0
- autocoder/common/action_yml_file_manager.py +25 -13
- autocoder/common/agent_events/__init__.py +52 -0
- autocoder/common/agent_events/agent_event_emitter.py +193 -0
- autocoder/common/agent_events/event_factory.py +177 -0
- autocoder/common/agent_events/examples.py +307 -0
- autocoder/common/agent_events/types.py +113 -0
- autocoder/common/agent_events/utils.py +68 -0
- autocoder/common/agent_hooks/__init__.py +44 -0
- autocoder/common/agent_hooks/examples.py +582 -0
- autocoder/common/agent_hooks/hook_executor.py +217 -0
- autocoder/common/agent_hooks/hook_manager.py +288 -0
- autocoder/common/agent_hooks/types.py +133 -0
- autocoder/common/agent_hooks/utils.py +99 -0
- autocoder/common/agent_query_queue/queue_executor.py +324 -0
- autocoder/common/agent_query_queue/queue_manager.py +325 -0
- autocoder/common/agents/__init__.py +11 -0
- autocoder/common/agents/agent_manager.py +323 -0
- autocoder/common/agents/agent_parser.py +189 -0
- autocoder/common/agents/example_usage.py +344 -0
- autocoder/common/agents/integration_example.py +330 -0
- autocoder/common/agents/test_agent_parser.py +545 -0
- autocoder/common/async_utils.py +101 -0
- autocoder/common/auto_coder_lang.py +23 -972
- autocoder/common/autocoderargs_parser/__init__.py +14 -0
- autocoder/common/autocoderargs_parser/parser.py +184 -0
- autocoder/common/autocoderargs_parser/tests/__init__.py +1 -0
- autocoder/common/autocoderargs_parser/tests/test_args_parser.py +235 -0
- autocoder/common/autocoderargs_parser/tests/test_token_parser.py +195 -0
- autocoder/common/autocoderargs_parser/token_parser.py +290 -0
- autocoder/common/buildin_tokenizer.py +2 -4
- autocoder/common/code_auto_generate.py +149 -74
- autocoder/common/code_auto_generate_diff.py +163 -70
- autocoder/common/code_auto_generate_editblock.py +179 -89
- autocoder/common/code_auto_generate_strict_diff.py +167 -72
- autocoder/common/code_auto_merge_editblock.py +13 -6
- autocoder/common/code_modification_ranker.py +1 -1
- autocoder/common/command_completer.py +3 -3
- autocoder/common/command_file_manager/manager.py +183 -47
- autocoder/common/command_file_manager/test_command_file_manager.py +507 -0
- autocoder/common/command_templates.py +1 -1
- autocoder/common/conf_utils.py +2 -4
- autocoder/common/conversations/config.py +11 -3
- autocoder/common/conversations/get_conversation_manager.py +100 -2
- autocoder/common/conversations/llm_stats_models.py +264 -0
- autocoder/common/conversations/manager.py +112 -28
- autocoder/common/conversations/models.py +16 -2
- autocoder/common/conversations/storage/index_manager.py +134 -10
- autocoder/common/core_config/__init__.py +63 -0
- autocoder/common/core_config/agentic_mode_manager.py +109 -0
- autocoder/common/core_config/base_manager.py +123 -0
- autocoder/common/core_config/compatibility.py +151 -0
- autocoder/common/core_config/config_manager.py +156 -0
- autocoder/common/core_config/conversation_manager.py +31 -0
- autocoder/common/core_config/exclude_manager.py +72 -0
- autocoder/common/core_config/file_manager.py +177 -0
- autocoder/common/core_config/human_as_model_manager.py +129 -0
- autocoder/common/core_config/lib_manager.py +54 -0
- autocoder/common/core_config/main_manager.py +81 -0
- autocoder/common/core_config/mode_manager.py +126 -0
- autocoder/common/core_config/models.py +70 -0
- autocoder/common/core_config/test_memory_manager.py +1056 -0
- autocoder/common/env_manager.py +282 -0
- autocoder/common/env_manager_usage_example.py +211 -0
- autocoder/common/file_checkpoint/conversation_checkpoint.py +19 -19
- autocoder/common/file_checkpoint/manager.py +264 -48
- autocoder/common/file_checkpoint/test_backup.py +1 -18
- autocoder/common/file_checkpoint/test_manager.py +270 -1
- autocoder/common/file_checkpoint/test_store.py +1 -17
- autocoder/common/file_handler/__init__.py +23 -0
- autocoder/common/file_handler/active_context_handler.py +159 -0
- autocoder/common/file_handler/add_files_handler.py +409 -0
- autocoder/common/file_handler/chat_handler.py +180 -0
- autocoder/common/file_handler/coding_handler.py +401 -0
- autocoder/common/file_handler/commit_handler.py +200 -0
- autocoder/common/file_handler/lib_handler.py +156 -0
- autocoder/common/file_handler/list_files_handler.py +111 -0
- autocoder/common/file_handler/mcp_handler.py +268 -0
- autocoder/common/file_handler/models_handler.py +493 -0
- autocoder/common/file_handler/remove_files_handler.py +172 -0
- autocoder/common/git_utils.py +44 -8
- autocoder/common/global_cancel.py +15 -6
- autocoder/common/ignorefiles/test_ignore_file_utils.py +1 -1
- autocoder/common/international/__init__.py +31 -0
- autocoder/common/international/demo_international.py +92 -0
- autocoder/common/international/message_manager.py +157 -0
- autocoder/common/international/messages/__init__.py +56 -0
- autocoder/common/international/messages/async_command_messages.py +507 -0
- autocoder/common/international/messages/auto_coder_messages.py +2208 -0
- autocoder/common/international/messages/chat_auto_coder_messages.py +1547 -0
- autocoder/common/international/messages/command_help_messages.py +986 -0
- autocoder/common/international/messages/conversation_command_messages.py +191 -0
- autocoder/common/international/messages/git_helper_plugin_messages.py +159 -0
- autocoder/common/international/messages/queue_command_messages.py +751 -0
- autocoder/common/international/messages/rules_command_messages.py +77 -0
- autocoder/common/international/messages/sdk_messages.py +1707 -0
- autocoder/common/international/messages/token_helper_plugin_messages.py +361 -0
- autocoder/common/international/messages/tool_display_messages.py +1212 -0
- autocoder/common/international/messages/workflow_exception_messages.py +473 -0
- autocoder/common/international/test_international.py +612 -0
- autocoder/common/linter_core/__init__.py +28 -0
- autocoder/common/linter_core/base_linter.py +61 -0
- autocoder/common/linter_core/config_loader.py +271 -0
- autocoder/common/linter_core/formatters/__init__.py +0 -0
- autocoder/common/linter_core/formatters/base_formatter.py +38 -0
- autocoder/common/linter_core/formatters/raw_formatter.py +17 -0
- autocoder/common/linter_core/linter.py +166 -0
- autocoder/common/linter_core/linter_factory.py +216 -0
- autocoder/common/linter_core/linter_manager.py +333 -0
- autocoder/common/linter_core/linters/__init__.py +9 -0
- autocoder/common/linter_core/linters/java_linter.py +342 -0
- autocoder/common/linter_core/linters/python_linter.py +115 -0
- autocoder/common/linter_core/linters/typescript_linter.py +119 -0
- autocoder/common/linter_core/models/__init__.py +7 -0
- autocoder/common/linter_core/models/lint_result.py +91 -0
- autocoder/common/linter_core/models.py +33 -0
- autocoder/common/linter_core/tests/__init__.py +3 -0
- autocoder/common/linter_core/tests/test_config_loader.py +323 -0
- autocoder/common/linter_core/tests/test_config_loading.py +308 -0
- autocoder/common/linter_core/tests/test_factory_manager.py +234 -0
- autocoder/common/linter_core/tests/test_formatters.py +147 -0
- autocoder/common/linter_core/tests/test_integration.py +317 -0
- autocoder/common/linter_core/tests/test_java_linter.py +496 -0
- autocoder/common/linter_core/tests/test_linters.py +265 -0
- autocoder/common/linter_core/tests/test_models.py +81 -0
- autocoder/common/linter_core/tests/verify_config_loading.py +296 -0
- autocoder/common/linter_core/tests/verify_fixes.py +183 -0
- autocoder/common/llm_friendly_package/__init__.py +31 -0
- autocoder/common/llm_friendly_package/base_manager.py +102 -0
- autocoder/common/llm_friendly_package/docs_manager.py +121 -0
- autocoder/common/llm_friendly_package/library_manager.py +171 -0
- autocoder/common/{llm_friendly_package.py → llm_friendly_package/main_manager.py} +204 -231
- autocoder/common/llm_friendly_package/models.py +40 -0
- autocoder/common/llm_friendly_package/test_llm_friendly_package.py +536 -0
- autocoder/common/llms/__init__.py +15 -0
- autocoder/common/llms/demo_error_handling.py +85 -0
- autocoder/common/llms/factory.py +142 -0
- autocoder/common/llms/manager.py +264 -0
- autocoder/common/llms/pricing.py +121 -0
- autocoder/common/llms/registry.py +288 -0
- autocoder/common/llms/schema.py +77 -0
- autocoder/common/llms/simple_demo.py +45 -0
- autocoder/common/llms/test_quick_model.py +116 -0
- autocoder/common/llms/test_remove_functionality.py +182 -0
- autocoder/common/llms/tests/__init__.py +1 -0
- autocoder/common/llms/tests/test_manager.py +330 -0
- autocoder/common/llms/tests/test_registry.py +364 -0
- autocoder/common/mcp_tools/__init__.py +62 -0
- autocoder/common/{mcp_tools.py → mcp_tools/executor.py} +49 -40
- autocoder/common/{mcp_hub.py → mcp_tools/hub.py} +42 -68
- autocoder/common/{mcp_server_install.py → mcp_tools/installer.py} +16 -28
- autocoder/common/{mcp_server.py → mcp_tools/server.py} +176 -48
- autocoder/common/mcp_tools/test_keyboard_interrupt.py +93 -0
- autocoder/common/mcp_tools/test_mcp_tools.py +391 -0
- autocoder/common/{mcp_server_types.py → mcp_tools/types.py} +121 -48
- autocoder/common/mcp_tools/verify_functionality.py +202 -0
- autocoder/common/model_speed_tester.py +32 -26
- autocoder/common/priority_directory_finder/__init__.py +142 -0
- autocoder/common/priority_directory_finder/examples.py +230 -0
- autocoder/common/priority_directory_finder/finder.py +283 -0
- autocoder/common/priority_directory_finder/models.py +236 -0
- autocoder/common/priority_directory_finder/test_priority_directory_finder.py +431 -0
- autocoder/common/project_scanner/__init__.py +18 -0
- autocoder/common/project_scanner/compat.py +77 -0
- autocoder/common/project_scanner/scanner.py +436 -0
- autocoder/common/project_tracker/__init__.py +27 -0
- autocoder/common/project_tracker/api.py +228 -0
- autocoder/common/project_tracker/demo.py +272 -0
- autocoder/common/project_tracker/tracker.py +487 -0
- autocoder/common/project_tracker/types.py +53 -0
- autocoder/common/pruner/__init__.py +67 -0
- autocoder/common/pruner/agentic_conversation_pruner.py +651 -102
- autocoder/common/pruner/conversation_message_ids_api.py +386 -0
- autocoder/common/pruner/conversation_message_ids_manager.py +347 -0
- autocoder/common/pruner/conversation_message_ids_pruner.py +473 -0
- autocoder/common/pruner/conversation_normalizer.py +347 -0
- autocoder/common/pruner/conversation_pruner.py +26 -6
- autocoder/common/pruner/test_agentic_conversation_pruner.py +554 -112
- autocoder/common/pruner/test_conversation_normalizer.py +502 -0
- autocoder/common/pruner/test_tool_content_detector.py +324 -0
- autocoder/common/pruner/tool_content_detector.py +227 -0
- autocoder/common/pruner/tools/__init__.py +18 -0
- autocoder/common/pruner/tools/query_message_ids.py +264 -0
- autocoder/common/pruner/tools/test_agentic_pruning_logic.py +432 -0
- autocoder/common/pruner/tools/test_message_ids_pruning_only.py +192 -0
- autocoder/common/pull_requests/__init__.py +9 -1
- autocoder/common/pull_requests/utils.py +122 -1
- autocoder/common/rag_manager/rag_manager.py +36 -40
- autocoder/common/rulefiles/__init__.py +53 -1
- autocoder/common/rulefiles/api.py +250 -0
- autocoder/common/rulefiles/core/__init__.py +14 -0
- autocoder/common/rulefiles/core/manager.py +241 -0
- autocoder/common/rulefiles/core/selector.py +805 -0
- autocoder/common/rulefiles/models/__init__.py +20 -0
- autocoder/common/rulefiles/models/index.py +16 -0
- autocoder/common/rulefiles/models/init_rule.py +18 -0
- autocoder/common/rulefiles/models/rule_file.py +18 -0
- autocoder/common/rulefiles/models/rule_relevance.py +14 -0
- autocoder/common/rulefiles/models/summary.py +16 -0
- autocoder/common/rulefiles/test_rulefiles.py +776 -0
- autocoder/common/rulefiles/utils/__init__.py +34 -0
- autocoder/common/rulefiles/utils/monitor.py +86 -0
- autocoder/common/rulefiles/utils/parser.py +230 -0
- autocoder/common/save_formatted_log.py +67 -10
- autocoder/common/search_replace.py +8 -1
- autocoder/common/search_replace_patch/__init__.py +24 -0
- autocoder/common/search_replace_patch/base.py +115 -0
- autocoder/common/search_replace_patch/manager.py +248 -0
- autocoder/common/search_replace_patch/patch_replacer.py +304 -0
- autocoder/common/search_replace_patch/similarity_replacer.py +306 -0
- autocoder/common/search_replace_patch/string_replacer.py +181 -0
- autocoder/common/search_replace_patch/tests/__init__.py +3 -0
- autocoder/common/search_replace_patch/tests/run_tests.py +126 -0
- autocoder/common/search_replace_patch/tests/test_base.py +188 -0
- autocoder/common/search_replace_patch/tests/test_empty_line_insert.py +233 -0
- autocoder/common/search_replace_patch/tests/test_integration.py +389 -0
- autocoder/common/search_replace_patch/tests/test_manager.py +351 -0
- autocoder/common/search_replace_patch/tests/test_patch_replacer.py +316 -0
- autocoder/common/search_replace_patch/tests/test_regex_replacer.py +306 -0
- autocoder/common/search_replace_patch/tests/test_similarity_replacer.py +384 -0
- autocoder/common/shell_commands/__init__.py +197 -0
- autocoder/common/shell_commands/background_process_notifier.py +346 -0
- autocoder/common/shell_commands/command_executor.py +1127 -0
- autocoder/common/shell_commands/error_recovery.py +541 -0
- autocoder/common/shell_commands/exceptions.py +120 -0
- autocoder/common/shell_commands/interactive_executor.py +476 -0
- autocoder/common/shell_commands/interactive_pexpect_process.py +623 -0
- autocoder/common/shell_commands/interactive_process.py +744 -0
- autocoder/common/shell_commands/interactive_session_manager.py +1014 -0
- autocoder/common/shell_commands/monitoring.py +529 -0
- autocoder/common/shell_commands/process_cleanup.py +386 -0
- autocoder/common/shell_commands/process_manager.py +606 -0
- autocoder/common/shell_commands/test_interactive_pexpect_process.py +281 -0
- autocoder/common/shell_commands/tests/__init__.py +6 -0
- autocoder/common/shell_commands/tests/conftest.py +118 -0
- autocoder/common/shell_commands/tests/test_background_process_notifier.py +703 -0
- autocoder/common/shell_commands/tests/test_command_executor.py +448 -0
- autocoder/common/shell_commands/tests/test_error_recovery.py +305 -0
- autocoder/common/shell_commands/tests/test_exceptions.py +299 -0
- autocoder/common/shell_commands/tests/test_execute_batch.py +588 -0
- autocoder/common/shell_commands/tests/test_indented_batch_commands.py +244 -0
- autocoder/common/shell_commands/tests/test_integration.py +664 -0
- autocoder/common/shell_commands/tests/test_monitoring.py +546 -0
- autocoder/common/shell_commands/tests/test_performance.py +632 -0
- autocoder/common/shell_commands/tests/test_process_cleanup.py +397 -0
- autocoder/common/shell_commands/tests/test_process_manager.py +606 -0
- autocoder/common/shell_commands/tests/test_timeout_config.py +343 -0
- autocoder/common/shell_commands/tests/test_timeout_manager.py +520 -0
- autocoder/common/shell_commands/timeout_config.py +315 -0
- autocoder/common/shell_commands/timeout_manager.py +352 -0
- autocoder/common/terminal_paste/__init__.py +14 -0
- autocoder/common/terminal_paste/demo.py +145 -0
- autocoder/common/terminal_paste/demo_paste_functionality.py +95 -0
- autocoder/common/terminal_paste/paste_handler.py +200 -0
- autocoder/common/terminal_paste/paste_manager.py +118 -0
- autocoder/common/terminal_paste/tests/__init__.py +1 -0
- autocoder/common/terminal_paste/tests/test_paste_handler.py +182 -0
- autocoder/common/terminal_paste/tests/test_paste_manager.py +126 -0
- autocoder/common/terminal_paste/utils.py +163 -0
- autocoder/common/test_autocoder_args.py +232 -0
- autocoder/common/test_env_manager.py +173 -0
- autocoder/common/test_env_manager_integration.py +159 -0
- autocoder/common/text_similarity/__init__.py +9 -0
- autocoder/common/text_similarity/demo.py +216 -0
- autocoder/common/text_similarity/examples.py +266 -0
- autocoder/common/text_similarity/test_text_similarity.py +306 -0
- autocoder/common/text_similarity/text_similarity.py +194 -0
- autocoder/common/text_similarity/utils.py +125 -0
- autocoder/common/todos/__init__.py +61 -0
- autocoder/common/todos/cache/__init__.py +16 -0
- autocoder/common/todos/cache/base_cache.py +89 -0
- autocoder/common/todos/cache/cache_manager.py +228 -0
- autocoder/common/todos/cache/memory_cache.py +225 -0
- autocoder/common/todos/config.py +155 -0
- autocoder/common/todos/exceptions.py +35 -0
- autocoder/common/todos/get_todo_manager.py +161 -0
- autocoder/common/todos/manager.py +537 -0
- autocoder/common/todos/models.py +239 -0
- autocoder/common/todos/storage/__init__.py +14 -0
- autocoder/common/todos/storage/base_storage.py +76 -0
- autocoder/common/todos/storage/file_storage.py +278 -0
- autocoder/common/tokens/counter.py +24 -2
- autocoder/common/tools_manager/__init__.py +17 -0
- autocoder/common/tools_manager/examples.py +162 -0
- autocoder/common/tools_manager/manager.py +385 -0
- autocoder/common/tools_manager/models.py +39 -0
- autocoder/common/tools_manager/test_tools_manager.py +303 -0
- autocoder/common/tools_manager/utils.py +191 -0
- autocoder/common/v2/agent/agentic_callbacks.py +270 -0
- autocoder/common/v2/agent/agentic_edit.py +2699 -1856
- autocoder/common/v2/agent/agentic_edit_change_manager.py +474 -0
- autocoder/common/v2/agent/agentic_edit_tools/__init__.py +35 -1
- autocoder/common/v2/agent/agentic_edit_tools/ac_mod_list_tool_resolver.py +279 -0
- autocoder/common/v2/agent/agentic_edit_tools/ac_mod_write_tool_resolver.py +10 -1
- autocoder/common/v2/agent/agentic_edit_tools/background_task_tool_resolver.py +1167 -0
- autocoder/common/v2/agent/agentic_edit_tools/base_tool_resolver.py +2 -2
- autocoder/common/v2/agent/agentic_edit_tools/conversation_message_ids_read_tool_resolver.py +214 -0
- autocoder/common/v2/agent/agentic_edit_tools/conversation_message_ids_write_tool_resolver.py +299 -0
- autocoder/common/v2/agent/agentic_edit_tools/count_tokens_tool_resolver.py +290 -0
- autocoder/common/v2/agent/agentic_edit_tools/execute_command_tool_resolver.py +564 -29
- autocoder/common/v2/agent/agentic_edit_tools/execute_workflow_tool_resolver.py +485 -0
- autocoder/common/v2/agent/agentic_edit_tools/extract_to_text_tool_resolver.py +225 -0
- autocoder/common/v2/agent/agentic_edit_tools/lint_report.py +79 -0
- autocoder/common/v2/agent/agentic_edit_tools/linter_config_models.py +343 -0
- autocoder/common/v2/agent/agentic_edit_tools/linter_enabled_tool_resolver.py +189 -0
- autocoder/common/v2/agent/agentic_edit_tools/list_files_tool_resolver.py +169 -101
- autocoder/common/v2/agent/agentic_edit_tools/load_extra_document_tool_resolver.py +349 -0
- autocoder/common/v2/agent/agentic_edit_tools/read_file_tool_resolver.py +243 -50
- autocoder/common/v2/agent/agentic_edit_tools/replace_in_file_tool_resolver.py +667 -147
- autocoder/common/v2/agent/agentic_edit_tools/run_named_subagents_tool_resolver.py +691 -0
- autocoder/common/v2/agent/agentic_edit_tools/search_files_tool_resolver.py +410 -86
- autocoder/common/v2/agent/agentic_edit_tools/session_interactive_tool_resolver.py +115 -0
- autocoder/common/v2/agent/agentic_edit_tools/session_start_tool_resolver.py +190 -0
- autocoder/common/v2/agent/agentic_edit_tools/session_stop_tool_resolver.py +76 -0
- autocoder/common/v2/agent/agentic_edit_tools/test_write_to_file_tool_resolver.py +207 -192
- autocoder/common/v2/agent/agentic_edit_tools/todo_read_tool_resolver.py +80 -63
- autocoder/common/v2/agent/agentic_edit_tools/todo_write_tool_resolver.py +237 -233
- autocoder/common/v2/agent/agentic_edit_tools/use_mcp_tool_resolver.py +2 -2
- autocoder/common/v2/agent/agentic_edit_tools/web_crawl_tool_resolver.py +557 -0
- autocoder/common/v2/agent/agentic_edit_tools/web_search_tool_resolver.py +600 -0
- autocoder/common/v2/agent/agentic_edit_tools/write_to_file_tool_resolver.py +56 -121
- autocoder/common/v2/agent/agentic_edit_types.py +343 -9
- autocoder/common/v2/agent/runner/__init__.py +3 -3
- autocoder/common/v2/agent/runner/base_runner.py +12 -26
- autocoder/common/v2/agent/runner/{event_runner.py → file_based_event_runner.py} +3 -2
- autocoder/common/v2/agent/runner/sdk_runner.py +150 -8
- autocoder/common/v2/agent/runner/terminal_runner.py +170 -57
- autocoder/common/v2/agent/runner/tool_display.py +557 -159
- autocoder/common/v2/agent/test_agentic_callbacks.py +265 -0
- autocoder/common/v2/agent/test_agentic_edit.py +194 -0
- autocoder/common/v2/agent/tool_caller/__init__.py +24 -0
- autocoder/common/v2/agent/tool_caller/default_tool_resolver_map.py +135 -0
- autocoder/common/v2/agent/tool_caller/integration_test.py +172 -0
- autocoder/common/v2/agent/tool_caller/plugins/__init__.py +14 -0
- autocoder/common/v2/agent/tool_caller/plugins/base_plugin.py +126 -0
- autocoder/common/v2/agent/tool_caller/plugins/examples/__init__.py +13 -0
- autocoder/common/v2/agent/tool_caller/plugins/examples/logging_plugin.py +164 -0
- autocoder/common/v2/agent/tool_caller/plugins/examples/security_filter_plugin.py +198 -0
- autocoder/common/v2/agent/tool_caller/plugins/plugin_interface.py +141 -0
- autocoder/common/v2/agent/tool_caller/test_tool_caller.py +278 -0
- autocoder/common/v2/agent/tool_caller/tool_call_plugin_manager.py +331 -0
- autocoder/common/v2/agent/tool_caller/tool_caller.py +337 -0
- autocoder/common/v2/agent/tool_caller/usage_example.py +193 -0
- autocoder/common/v2/code_agentic_editblock_manager.py +4 -4
- autocoder/common/v2/code_auto_generate.py +136 -78
- autocoder/common/v2/code_auto_generate_diff.py +135 -79
- autocoder/common/v2/code_auto_generate_editblock.py +174 -99
- autocoder/common/v2/code_auto_generate_strict_diff.py +151 -71
- autocoder/common/v2/code_auto_merge.py +1 -1
- autocoder/common/v2/code_auto_merge_editblock.py +13 -1
- autocoder/common/v2/code_diff_manager.py +3 -3
- autocoder/common/v2/code_editblock_manager.py +4 -14
- autocoder/common/v2/code_manager.py +1 -1
- autocoder/common/v2/code_strict_diff_manager.py +2 -2
- autocoder/common/wrap_llm_hint/__init__.py +10 -0
- autocoder/common/wrap_llm_hint/test_wrap_llm_hint.py +1067 -0
- autocoder/common/wrap_llm_hint/utils.py +432 -0
- autocoder/common/wrap_llm_hint/wrap_llm_hint.py +323 -0
- autocoder/completer/__init__.py +8 -0
- autocoder/completer/command_completer_v2.py +1051 -0
- autocoder/default_project/__init__.py +501 -0
- autocoder/dispacher/__init__.py +4 -12
- autocoder/dispacher/actions/action.py +165 -7
- autocoder/dispacher/actions/plugins/action_regex_project.py +2 -2
- autocoder/index/entry.py +116 -124
- autocoder/{agent → index/filter}/agentic_filter.py +322 -333
- autocoder/index/filter/normal_filter.py +5 -11
- autocoder/index/filter/quick_filter.py +1 -1
- autocoder/index/index.py +36 -9
- autocoder/index/tests/__init__.py +1 -0
- autocoder/index/tests/run_tests.py +195 -0
- autocoder/index/tests/test_entry.py +303 -0
- autocoder/index/tests/test_index_manager.py +314 -0
- autocoder/index/tests/test_module_integration.py +300 -0
- autocoder/index/tests/test_symbols_utils.py +183 -0
- autocoder/inner/__init__.py +4 -0
- autocoder/inner/agentic.py +932 -0
- autocoder/inner/async_command_handler.py +992 -0
- autocoder/inner/conversation_command_handlers.py +623 -0
- autocoder/inner/merge_command_handler.py +213 -0
- autocoder/inner/queue_command_handler.py +684 -0
- autocoder/models.py +95 -266
- autocoder/plugins/git_helper_plugin.py +31 -29
- autocoder/plugins/token_helper_plugin.py +65 -46
- autocoder/pyproject/__init__.py +32 -29
- autocoder/rag/agentic_rag.py +215 -75
- autocoder/rag/cache/simple_cache.py +1 -2
- autocoder/rag/loaders/image_loader.py +1 -1
- autocoder/rag/long_context_rag.py +42 -26
- autocoder/rag/qa_conversation_strategy.py +1 -1
- autocoder/rag/terminal/__init__.py +17 -0
- autocoder/rag/terminal/args.py +581 -0
- autocoder/rag/terminal/bootstrap.py +61 -0
- autocoder/rag/terminal/command_handlers.py +653 -0
- autocoder/rag/terminal/formatters/__init__.py +20 -0
- autocoder/rag/terminal/formatters/base.py +70 -0
- autocoder/rag/terminal/formatters/json_format.py +66 -0
- autocoder/rag/terminal/formatters/stream_json.py +95 -0
- autocoder/rag/terminal/formatters/text.py +28 -0
- autocoder/rag/terminal/init.py +120 -0
- autocoder/rag/terminal/utils.py +106 -0
- autocoder/rag/test_agentic_rag.py +389 -0
- autocoder/rag/test_doc_filter.py +3 -3
- autocoder/rag/test_long_context_rag.py +1 -1
- autocoder/rag/test_token_limiter.py +517 -10
- autocoder/rag/token_counter.py +3 -0
- autocoder/rag/token_limiter.py +19 -15
- autocoder/rag/tools/__init__.py +26 -2
- autocoder/rag/tools/bochaai_example.py +343 -0
- autocoder/rag/tools/bochaai_sdk.py +541 -0
- autocoder/rag/tools/metaso_example.py +268 -0
- autocoder/rag/tools/metaso_sdk.py +417 -0
- autocoder/rag/tools/recall_tool.py +28 -7
- autocoder/rag/tools/run_integration_tests.py +204 -0
- autocoder/rag/tools/test_all_providers.py +318 -0
- autocoder/rag/tools/test_bochaai_integration.py +482 -0
- autocoder/rag/tools/test_final_integration.py +215 -0
- autocoder/rag/tools/test_metaso_integration.py +424 -0
- autocoder/rag/tools/test_metaso_real.py +171 -0
- autocoder/rag/tools/test_web_crawl_tool.py +639 -0
- autocoder/rag/tools/test_web_search_tool.py +509 -0
- autocoder/rag/tools/todo_read_tool.py +202 -0
- autocoder/rag/tools/todo_write_tool.py +412 -0
- autocoder/rag/tools/web_crawl_tool.py +634 -0
- autocoder/rag/tools/web_search_tool.py +558 -0
- autocoder/rag/tools/web_tools_example.py +119 -0
- autocoder/rag/types.py +16 -0
- autocoder/rag/variable_holder.py +4 -2
- autocoder/rags.py +86 -79
- autocoder/regexproject/__init__.py +23 -21
- autocoder/sdk/__init__.py +46 -190
- autocoder/sdk/api.py +370 -0
- autocoder/sdk/async_runner/__init__.py +26 -0
- autocoder/sdk/async_runner/async_executor.py +650 -0
- autocoder/sdk/async_runner/async_handler.py +356 -0
- autocoder/sdk/async_runner/markdown_processor.py +595 -0
- autocoder/sdk/async_runner/task_metadata.py +284 -0
- autocoder/sdk/async_runner/worktree_manager.py +438 -0
- autocoder/sdk/cli/__init__.py +2 -5
- autocoder/sdk/cli/formatters.py +28 -204
- autocoder/sdk/cli/handlers.py +77 -44
- autocoder/sdk/cli/main.py +154 -171
- autocoder/sdk/cli/options.py +95 -22
- autocoder/sdk/constants.py +139 -51
- autocoder/sdk/core/auto_coder_core.py +484 -109
- autocoder/sdk/core/bridge.py +297 -115
- autocoder/sdk/exceptions.py +18 -12
- autocoder/sdk/formatters/__init__.py +19 -0
- autocoder/sdk/formatters/input.py +64 -0
- autocoder/sdk/formatters/output.py +247 -0
- autocoder/sdk/formatters/stream.py +54 -0
- autocoder/sdk/models/__init__.py +6 -5
- autocoder/sdk/models/options.py +55 -18
- autocoder/sdk/utils/formatters.py +27 -195
- autocoder/suffixproject/__init__.py +28 -25
- autocoder/terminal/__init__.py +14 -0
- autocoder/terminal/app.py +454 -0
- autocoder/terminal/args.py +32 -0
- autocoder/terminal/bootstrap.py +178 -0
- autocoder/terminal/command_processor.py +521 -0
- autocoder/terminal/command_registry.py +57 -0
- autocoder/terminal/help.py +97 -0
- autocoder/terminal/tasks/__init__.py +5 -0
- autocoder/terminal/tasks/background.py +77 -0
- autocoder/terminal/tasks/task_event.py +70 -0
- autocoder/terminal/ui/__init__.py +13 -0
- autocoder/terminal/ui/completer.py +268 -0
- autocoder/terminal/ui/keybindings.py +75 -0
- autocoder/terminal/ui/session.py +41 -0
- autocoder/terminal/ui/toolbar.py +64 -0
- autocoder/terminal/utils/__init__.py +13 -0
- autocoder/terminal/utils/errors.py +18 -0
- autocoder/terminal/utils/paths.py +19 -0
- autocoder/terminal/utils/shell.py +43 -0
- autocoder/terminal_v3/__init__.py +10 -0
- autocoder/terminal_v3/app.py +201 -0
- autocoder/terminal_v3/handlers/__init__.py +5 -0
- autocoder/terminal_v3/handlers/command_handler.py +131 -0
- autocoder/terminal_v3/models/__init__.py +6 -0
- autocoder/terminal_v3/models/conversation_buffer.py +214 -0
- autocoder/terminal_v3/models/message.py +50 -0
- autocoder/terminal_v3/models/tool_display.py +247 -0
- autocoder/terminal_v3/ui/__init__.py +7 -0
- autocoder/terminal_v3/ui/keybindings.py +56 -0
- autocoder/terminal_v3/ui/layout.py +141 -0
- autocoder/terminal_v3/ui/styles.py +43 -0
- autocoder/tsproject/__init__.py +23 -23
- autocoder/utils/auto_coder_utils/chat_stream_out.py +1 -1
- autocoder/utils/llms.py +88 -80
- autocoder/utils/math_utils.py +101 -0
- autocoder/utils/model_provider_selector.py +16 -4
- autocoder/utils/operate_config_api.py +33 -5
- autocoder/utils/thread_utils.py +2 -2
- autocoder/version.py +4 -2
- autocoder/workflow_agents/__init__.py +84 -0
- autocoder/workflow_agents/agent.py +143 -0
- autocoder/workflow_agents/exceptions.py +573 -0
- autocoder/workflow_agents/executor.py +489 -0
- autocoder/workflow_agents/loader.py +737 -0
- autocoder/workflow_agents/runner.py +267 -0
- autocoder/workflow_agents/types.py +172 -0
- autocoder/workflow_agents/utils.py +434 -0
- autocoder/workflow_agents/workflow_manager.py +211 -0
- auto_coder-1.0.0.dist-info/METADATA +0 -396
- auto_coder-1.0.0.dist-info/RECORD +0 -442
- auto_coder-1.0.0.dist-info/licenses/LICENSE +0 -201
- autocoder/auto_coder_server.py +0 -672
- autocoder/benchmark.py +0 -138
- autocoder/common/ac_style_command_parser/example.py +0 -7
- autocoder/common/cleaner.py +0 -31
- autocoder/common/command_completer_v2.py +0 -615
- autocoder/common/context_pruner.py +0 -477
- autocoder/common/conversation_pruner.py +0 -132
- autocoder/common/directory_cache/__init__.py +0 -1
- autocoder/common/directory_cache/cache.py +0 -192
- autocoder/common/directory_cache/test_cache.py +0 -190
- autocoder/common/file_checkpoint/examples.py +0 -217
- autocoder/common/llm_friendly_package_example.py +0 -138
- autocoder/common/llm_friendly_package_test.py +0 -63
- autocoder/common/pull_requests/test_module.py +0 -1
- autocoder/common/rulefiles/autocoderrules_utils.py +0 -484
- autocoder/common/text.py +0 -30
- autocoder/common/v2/agent/agentic_edit_tools/list_package_info_tool_resolver.py +0 -42
- autocoder/common/v2/agent/agentic_edit_tools/test_execute_command_tool_resolver.py +0 -70
- autocoder/common/v2/agent/agentic_edit_tools/test_search_files_tool_resolver.py +0 -163
- autocoder/common/v2/agent/agentic_tool_display.py +0 -183
- autocoder/plugins/dynamic_completion_example.py +0 -148
- autocoder/plugins/sample_plugin.py +0 -160
- autocoder/sdk/cli/__main__.py +0 -26
- autocoder/sdk/cli/completion_wrapper.py +0 -38
- autocoder/sdk/cli/install_completion.py +0 -301
- autocoder/sdk/models/messages.py +0 -209
- autocoder/sdk/session/__init__.py +0 -32
- autocoder/sdk/session/session.py +0 -106
- autocoder/sdk/session/session_manager.py +0 -56
- {auto_coder-1.0.0.dist-info → auto_coder-2.0.0.dist-info}/top_level.txt +0 -0
- /autocoder/{sdk/example.py → common/agent_query_queue/__init__.py} +0 -0
|
@@ -0,0 +1,606 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Test module for ProcessManager functionality.
|
|
3
|
+
|
|
4
|
+
This module tests the process management functionality including:
|
|
5
|
+
- Process creation and configuration
|
|
6
|
+
- Process registration and management
|
|
7
|
+
- Process cleanup and timeout handling
|
|
8
|
+
- Error handling and edge cases
|
|
9
|
+
"""
|
|
10
|
+
|
|
11
|
+
import os
|
|
12
|
+
import time
|
|
13
|
+
import platform
|
|
14
|
+
import threading
|
|
15
|
+
from unittest.mock import Mock, patch, MagicMock
|
|
16
|
+
import subprocess
|
|
17
|
+
import pytest
|
|
18
|
+
|
|
19
|
+
from autocoder.common.shell_commands.process_manager import ProcessManager
|
|
20
|
+
from autocoder.common.shell_commands.timeout_config import TimeoutConfig
|
|
21
|
+
from autocoder.common.shell_commands.exceptions import CommandExecutionError, ProcessCleanupError
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
class TestProcessManager:
|
|
25
|
+
"""Test basic ProcessManager functionality."""
|
|
26
|
+
|
|
27
|
+
def test_initialization(self):
|
|
28
|
+
"""Test ProcessManager initialization."""
|
|
29
|
+
config = TimeoutConfig(default_timeout=60.0)
|
|
30
|
+
manager = ProcessManager(config)
|
|
31
|
+
|
|
32
|
+
assert manager.config == config
|
|
33
|
+
assert manager.timeout_manager is not None
|
|
34
|
+
assert len(manager.active_processes) == 0
|
|
35
|
+
assert len(manager.process_groups) == 0
|
|
36
|
+
|
|
37
|
+
def test_create_process_basic(self):
|
|
38
|
+
"""Test basic process creation."""
|
|
39
|
+
config = TimeoutConfig(default_timeout=60.0)
|
|
40
|
+
manager = ProcessManager(config)
|
|
41
|
+
|
|
42
|
+
if platform.system() == 'Windows':
|
|
43
|
+
command = ['echo', 'test']
|
|
44
|
+
else:
|
|
45
|
+
command = ['echo', 'test']
|
|
46
|
+
|
|
47
|
+
process = manager.create_process(command)
|
|
48
|
+
|
|
49
|
+
try:
|
|
50
|
+
assert process is not None
|
|
51
|
+
assert process.pid > 0
|
|
52
|
+
assert process.pid in manager.active_processes
|
|
53
|
+
|
|
54
|
+
# Wait for process to complete
|
|
55
|
+
exit_code = manager.wait_for_process(process, timeout=5.0)
|
|
56
|
+
assert exit_code == 0
|
|
57
|
+
finally:
|
|
58
|
+
# Cleanup if needed
|
|
59
|
+
if process.pid in manager.active_processes:
|
|
60
|
+
manager.cleanup_process_tree(process)
|
|
61
|
+
|
|
62
|
+
def test_create_process_with_options(self):
|
|
63
|
+
"""Test process creation with various options."""
|
|
64
|
+
config = TimeoutConfig(default_timeout=60.0)
|
|
65
|
+
manager = ProcessManager(config)
|
|
66
|
+
|
|
67
|
+
if platform.system() == 'Windows':
|
|
68
|
+
command = ['echo', 'test']
|
|
69
|
+
else:
|
|
70
|
+
command = ['echo', 'test']
|
|
71
|
+
|
|
72
|
+
process = manager.create_process(
|
|
73
|
+
command,
|
|
74
|
+
timeout=30.0,
|
|
75
|
+
shell=True,
|
|
76
|
+
capture_output=True,
|
|
77
|
+
text=True
|
|
78
|
+
)
|
|
79
|
+
|
|
80
|
+
try:
|
|
81
|
+
assert process is not None
|
|
82
|
+
assert process.pid > 0
|
|
83
|
+
assert process.pid in manager.active_processes
|
|
84
|
+
|
|
85
|
+
# Wait for process to complete
|
|
86
|
+
exit_code = manager.wait_for_process(process, timeout=5.0)
|
|
87
|
+
assert exit_code == 0
|
|
88
|
+
finally:
|
|
89
|
+
# Cleanup if needed
|
|
90
|
+
if process.pid in manager.active_processes:
|
|
91
|
+
manager.cleanup_process_tree(process)
|
|
92
|
+
|
|
93
|
+
def test_create_process_failure(self):
|
|
94
|
+
"""Test process creation failure handling."""
|
|
95
|
+
config = TimeoutConfig(default_timeout=60.0)
|
|
96
|
+
manager = ProcessManager(config)
|
|
97
|
+
|
|
98
|
+
# Try to create process with invalid cwd (this will actually fail)
|
|
99
|
+
with pytest.raises(CommandExecutionError):
|
|
100
|
+
manager.create_process(['echo', 'test'], cwd='/this/path/does/not/exist')
|
|
101
|
+
|
|
102
|
+
def test_register_process(self):
|
|
103
|
+
"""Test manual process registration."""
|
|
104
|
+
config = TimeoutConfig(default_timeout=60.0)
|
|
105
|
+
manager = ProcessManager(config)
|
|
106
|
+
|
|
107
|
+
mock_process = Mock()
|
|
108
|
+
mock_process.pid = 12345
|
|
109
|
+
|
|
110
|
+
manager._register_process(mock_process)
|
|
111
|
+
|
|
112
|
+
assert mock_process.pid in manager.active_processes
|
|
113
|
+
|
|
114
|
+
def test_cleanup_process_success(self):
|
|
115
|
+
"""Test successful process cleanup."""
|
|
116
|
+
config = TimeoutConfig(default_timeout=60.0)
|
|
117
|
+
manager = ProcessManager(config)
|
|
118
|
+
|
|
119
|
+
if platform.system() == 'Windows':
|
|
120
|
+
command = ['ping', '127.0.0.1', '-n', '1']
|
|
121
|
+
else:
|
|
122
|
+
command = ['sleep', '0.1']
|
|
123
|
+
|
|
124
|
+
process = manager.create_process(command)
|
|
125
|
+
|
|
126
|
+
try:
|
|
127
|
+
pid = process.pid
|
|
128
|
+
assert pid in manager.active_processes
|
|
129
|
+
|
|
130
|
+
# Wait a bit for process to complete or be running
|
|
131
|
+
time.sleep(0.05)
|
|
132
|
+
|
|
133
|
+
# Cleanup
|
|
134
|
+
result = manager.cleanup_process_tree(process)
|
|
135
|
+
|
|
136
|
+
assert result is True or result is False # Should return a boolean
|
|
137
|
+
assert pid not in manager.active_processes
|
|
138
|
+
|
|
139
|
+
except Exception as e:
|
|
140
|
+
# Fallback cleanup
|
|
141
|
+
try:
|
|
142
|
+
process.terminate()
|
|
143
|
+
process.wait(timeout=1)
|
|
144
|
+
except:
|
|
145
|
+
pass
|
|
146
|
+
manager.unregister_process(process)
|
|
147
|
+
|
|
148
|
+
def test_cleanup_nonexistent_process(self):
|
|
149
|
+
"""Test cleanup of non-existent process."""
|
|
150
|
+
config = TimeoutConfig(default_timeout=60.0)
|
|
151
|
+
manager = ProcessManager(config)
|
|
152
|
+
|
|
153
|
+
# Create a mock process that doesn't exist
|
|
154
|
+
mock_process = Mock()
|
|
155
|
+
mock_process.pid = 99999
|
|
156
|
+
|
|
157
|
+
result = manager.cleanup_process_tree(mock_process)
|
|
158
|
+
|
|
159
|
+
# Should handle gracefully
|
|
160
|
+
assert result is False or result is True
|
|
161
|
+
|
|
162
|
+
def test_cleanup_all_processes(self):
|
|
163
|
+
"""Test cleanup of all managed processes."""
|
|
164
|
+
config = TimeoutConfig(default_timeout=60.0)
|
|
165
|
+
manager = ProcessManager(config)
|
|
166
|
+
|
|
167
|
+
processes = []
|
|
168
|
+
|
|
169
|
+
# Create multiple processes
|
|
170
|
+
for i in range(3):
|
|
171
|
+
if platform.system() == 'Windows':
|
|
172
|
+
command = ['ping', '127.0.0.1', '-n', '1']
|
|
173
|
+
else:
|
|
174
|
+
command = ['sleep', '0.1']
|
|
175
|
+
|
|
176
|
+
process = manager.create_process(command)
|
|
177
|
+
if process:
|
|
178
|
+
processes.append(process)
|
|
179
|
+
|
|
180
|
+
try:
|
|
181
|
+
assert len(manager.active_processes) >= len(processes)
|
|
182
|
+
|
|
183
|
+
# Cleanup all
|
|
184
|
+
results = manager.cleanup_all_processes()
|
|
185
|
+
|
|
186
|
+
assert len(manager.active_processes) == 0
|
|
187
|
+
assert isinstance(results, list)
|
|
188
|
+
|
|
189
|
+
except Exception:
|
|
190
|
+
# Fallback cleanup
|
|
191
|
+
for process in processes:
|
|
192
|
+
try:
|
|
193
|
+
process.terminate()
|
|
194
|
+
process.wait(timeout=1)
|
|
195
|
+
except:
|
|
196
|
+
pass
|
|
197
|
+
manager.active_processes.clear()
|
|
198
|
+
|
|
199
|
+
def test_get_managed_processes(self):
|
|
200
|
+
"""Test getting list of managed processes."""
|
|
201
|
+
config = TimeoutConfig(default_timeout=60.0)
|
|
202
|
+
manager = ProcessManager(config)
|
|
203
|
+
|
|
204
|
+
initial_count = len(manager.get_all_processes())
|
|
205
|
+
|
|
206
|
+
if platform.system() == 'Windows':
|
|
207
|
+
command = ['echo', 'test']
|
|
208
|
+
else:
|
|
209
|
+
command = ['echo', 'test']
|
|
210
|
+
|
|
211
|
+
process = manager.create_process(command)
|
|
212
|
+
|
|
213
|
+
try:
|
|
214
|
+
current_count = len(manager.get_all_processes())
|
|
215
|
+
assert current_count == initial_count + 1
|
|
216
|
+
|
|
217
|
+
processes = manager.get_all_processes()
|
|
218
|
+
assert process.pid in processes
|
|
219
|
+
assert processes[process.pid] == process
|
|
220
|
+
|
|
221
|
+
finally:
|
|
222
|
+
if process.pid in manager.active_processes:
|
|
223
|
+
manager.cleanup_process_tree(process)
|
|
224
|
+
|
|
225
|
+
def test_is_process_managed(self):
|
|
226
|
+
"""Test checking if process is managed."""
|
|
227
|
+
config = TimeoutConfig(default_timeout=60.0)
|
|
228
|
+
manager = ProcessManager(config)
|
|
229
|
+
|
|
230
|
+
# Non-existent process
|
|
231
|
+
assert 99999 not in manager.active_processes
|
|
232
|
+
|
|
233
|
+
if platform.system() == 'Windows':
|
|
234
|
+
command = ['echo', 'test']
|
|
235
|
+
else:
|
|
236
|
+
command = ['echo', 'test']
|
|
237
|
+
|
|
238
|
+
process = manager.create_process(command)
|
|
239
|
+
|
|
240
|
+
try:
|
|
241
|
+
# Process should be managed
|
|
242
|
+
assert process.pid in manager.active_processes
|
|
243
|
+
|
|
244
|
+
# Wait for process to complete
|
|
245
|
+
exit_code = manager.wait_for_process(process, timeout=5.0)
|
|
246
|
+
|
|
247
|
+
# Process should no longer be managed
|
|
248
|
+
assert process.pid not in manager.active_processes
|
|
249
|
+
|
|
250
|
+
finally:
|
|
251
|
+
if process.pid in manager.active_processes:
|
|
252
|
+
manager.cleanup_process_tree(process)
|
|
253
|
+
|
|
254
|
+
def test_unregister_process(self):
|
|
255
|
+
"""Test process unregistration."""
|
|
256
|
+
config = TimeoutConfig(default_timeout=60.0)
|
|
257
|
+
manager = ProcessManager(config)
|
|
258
|
+
|
|
259
|
+
mock_process = Mock()
|
|
260
|
+
mock_process.pid = 12345
|
|
261
|
+
|
|
262
|
+
# Register then unregister
|
|
263
|
+
manager._register_process(mock_process)
|
|
264
|
+
assert mock_process.pid in manager.active_processes
|
|
265
|
+
|
|
266
|
+
manager.unregister_process(mock_process)
|
|
267
|
+
assert mock_process.pid not in manager.active_processes
|
|
268
|
+
|
|
269
|
+
|
|
270
|
+
class TestProcessManagerWithTimeout:
|
|
271
|
+
"""Test ProcessManager with timeout functionality."""
|
|
272
|
+
|
|
273
|
+
def test_process_with_timeout(self):
|
|
274
|
+
"""Test process creation with timeout."""
|
|
275
|
+
config = TimeoutConfig(default_timeout=1.0)
|
|
276
|
+
manager = ProcessManager(config)
|
|
277
|
+
|
|
278
|
+
if platform.system() == 'Windows':
|
|
279
|
+
# Use a command that will run for a while
|
|
280
|
+
command = ['ping', '127.0.0.1', '-n', '10']
|
|
281
|
+
else:
|
|
282
|
+
command = ['sleep', '10']
|
|
283
|
+
|
|
284
|
+
process = manager.create_process(command, timeout=0.1)
|
|
285
|
+
|
|
286
|
+
try:
|
|
287
|
+
assert process is not None
|
|
288
|
+
|
|
289
|
+
# Process should be killed by timeout
|
|
290
|
+
start_time = time.time()
|
|
291
|
+
try:
|
|
292
|
+
process.wait(timeout=1.0)
|
|
293
|
+
except subprocess.TimeoutExpired:
|
|
294
|
+
# Expected if process is still running
|
|
295
|
+
pass
|
|
296
|
+
duration = time.time() - start_time
|
|
297
|
+
|
|
298
|
+
# Should have been terminated by timeout (allow some margin)
|
|
299
|
+
assert duration < 2.0
|
|
300
|
+
|
|
301
|
+
finally:
|
|
302
|
+
try:
|
|
303
|
+
process.terminate()
|
|
304
|
+
process.wait(timeout=1)
|
|
305
|
+
except:
|
|
306
|
+
pass
|
|
307
|
+
if process.pid in manager.active_processes:
|
|
308
|
+
manager.cleanup_process_tree(process)
|
|
309
|
+
|
|
310
|
+
|
|
311
|
+
class TestProcessManagerErrorHandling:
|
|
312
|
+
"""Test ProcessManager error handling."""
|
|
313
|
+
|
|
314
|
+
def test_cleanup_with_permission_error(self):
|
|
315
|
+
"""Test cleanup when permission is denied."""
|
|
316
|
+
config = TimeoutConfig(default_timeout=60.0)
|
|
317
|
+
manager = ProcessManager(config)
|
|
318
|
+
|
|
319
|
+
# Try to cleanup a system process (should fail with permission error)
|
|
320
|
+
if platform.system() == 'Windows':
|
|
321
|
+
system_pid = 4 # System process
|
|
322
|
+
else:
|
|
323
|
+
system_pid = 1 # Init process
|
|
324
|
+
|
|
325
|
+
# Create a mock process for system PID
|
|
326
|
+
mock_process = Mock()
|
|
327
|
+
mock_process.pid = system_pid
|
|
328
|
+
|
|
329
|
+
result = manager.cleanup_process_tree(mock_process)
|
|
330
|
+
|
|
331
|
+
# Should handle gracefully (might succeed or fail depending on permissions)
|
|
332
|
+
assert result is True or result is False
|
|
333
|
+
|
|
334
|
+
def test_cleanup_with_process_not_found(self):
|
|
335
|
+
"""Test cleanup when process is not found."""
|
|
336
|
+
config = TimeoutConfig(default_timeout=60.0)
|
|
337
|
+
manager = ProcessManager(config)
|
|
338
|
+
|
|
339
|
+
# Create a mock process that doesn't actually exist
|
|
340
|
+
mock_process = Mock()
|
|
341
|
+
mock_process.pid = 99999
|
|
342
|
+
|
|
343
|
+
result = manager.cleanup_process_tree(mock_process)
|
|
344
|
+
|
|
345
|
+
# Should handle gracefully
|
|
346
|
+
assert result is True or result is False
|
|
347
|
+
|
|
348
|
+
def test_process_creation_with_invalid_command(self):
|
|
349
|
+
"""Test process creation with invalid command."""
|
|
350
|
+
config = TimeoutConfig(default_timeout=60.0)
|
|
351
|
+
manager = ProcessManager(config)
|
|
352
|
+
|
|
353
|
+
# Try to create process with invalid cwd (this will actually fail)
|
|
354
|
+
with pytest.raises(CommandExecutionError):
|
|
355
|
+
manager.create_process(['echo', 'test'], cwd='/this/path/does/not/exist')
|
|
356
|
+
|
|
357
|
+
def test_process_creation_with_invalid_cwd(self):
|
|
358
|
+
"""Test process creation with invalid working directory."""
|
|
359
|
+
config = TimeoutConfig(default_timeout=60.0)
|
|
360
|
+
manager = ProcessManager(config)
|
|
361
|
+
|
|
362
|
+
with pytest.raises(CommandExecutionError):
|
|
363
|
+
manager.create_process(
|
|
364
|
+
['echo', 'test'],
|
|
365
|
+
cwd='/this/directory/does/not/exist'
|
|
366
|
+
)
|
|
367
|
+
|
|
368
|
+
@patch('autocoder.common.shell_commands.process_manager.cleanup_process_tree')
|
|
369
|
+
def test_cleanup_with_cleanup_function_failure(self, mock_cleanup):
|
|
370
|
+
"""Test process cleanup when cleanup function fails."""
|
|
371
|
+
config = TimeoutConfig(default_timeout=60.0)
|
|
372
|
+
manager = ProcessManager(config)
|
|
373
|
+
|
|
374
|
+
# Make cleanup function return False (indicating failure)
|
|
375
|
+
mock_cleanup.return_value = False
|
|
376
|
+
|
|
377
|
+
# Create a mock process that appears to be still running
|
|
378
|
+
mock_process = Mock()
|
|
379
|
+
mock_process.pid = 123
|
|
380
|
+
mock_process.poll.return_value = None # Process is still running
|
|
381
|
+
|
|
382
|
+
# Cleanup should handle the failure
|
|
383
|
+
result = manager.cleanup_process_tree(mock_process)
|
|
384
|
+
|
|
385
|
+
# Should return False on failure
|
|
386
|
+
assert result is False
|
|
387
|
+
|
|
388
|
+
|
|
389
|
+
class TestProcessManagerConcurrency:
|
|
390
|
+
"""Test ProcessManager concurrency handling."""
|
|
391
|
+
|
|
392
|
+
def test_concurrent_process_creation(self):
|
|
393
|
+
"""Test concurrent process creation."""
|
|
394
|
+
import threading
|
|
395
|
+
|
|
396
|
+
config = TimeoutConfig(default_timeout=60.0)
|
|
397
|
+
manager = ProcessManager(config)
|
|
398
|
+
|
|
399
|
+
processes = []
|
|
400
|
+
errors = []
|
|
401
|
+
|
|
402
|
+
def create_process():
|
|
403
|
+
try:
|
|
404
|
+
if platform.system() == 'Windows':
|
|
405
|
+
command = ['echo', 'test']
|
|
406
|
+
else:
|
|
407
|
+
command = ['echo', 'test']
|
|
408
|
+
|
|
409
|
+
process = manager.create_process(command)
|
|
410
|
+
if process:
|
|
411
|
+
processes.append(process)
|
|
412
|
+
except Exception as e:
|
|
413
|
+
errors.append(e)
|
|
414
|
+
|
|
415
|
+
# Create multiple threads
|
|
416
|
+
threads = [threading.Thread(target=create_process) for _ in range(5)]
|
|
417
|
+
|
|
418
|
+
# Start all threads
|
|
419
|
+
for thread in threads:
|
|
420
|
+
thread.start()
|
|
421
|
+
|
|
422
|
+
# Wait for all threads
|
|
423
|
+
for thread in threads:
|
|
424
|
+
thread.join()
|
|
425
|
+
|
|
426
|
+
try:
|
|
427
|
+
# Should have created some processes without errors
|
|
428
|
+
assert len(processes) > 0
|
|
429
|
+
assert len(errors) == 0
|
|
430
|
+
|
|
431
|
+
# All processes should be managed
|
|
432
|
+
for process in processes:
|
|
433
|
+
assert process.pid in manager.active_processes
|
|
434
|
+
|
|
435
|
+
finally:
|
|
436
|
+
# Cleanup
|
|
437
|
+
for process in processes:
|
|
438
|
+
try:
|
|
439
|
+
if process.pid in manager.active_processes:
|
|
440
|
+
manager.cleanup_process_tree(process)
|
|
441
|
+
except:
|
|
442
|
+
pass
|
|
443
|
+
|
|
444
|
+
|
|
445
|
+
class TestProcessManagerIntegration:
|
|
446
|
+
"""Test ProcessManager integration scenarios."""
|
|
447
|
+
|
|
448
|
+
def test_full_lifecycle(self):
|
|
449
|
+
"""Test complete process lifecycle."""
|
|
450
|
+
config = TimeoutConfig(default_timeout=60.0)
|
|
451
|
+
manager = ProcessManager(config)
|
|
452
|
+
|
|
453
|
+
if platform.system() == 'Windows':
|
|
454
|
+
command = ['echo', 'Hello World']
|
|
455
|
+
else:
|
|
456
|
+
command = ['echo', 'Hello World']
|
|
457
|
+
|
|
458
|
+
# Create process
|
|
459
|
+
process = manager.create_process(command)
|
|
460
|
+
|
|
461
|
+
try:
|
|
462
|
+
assert process is not None
|
|
463
|
+
assert process.pid in manager.active_processes
|
|
464
|
+
|
|
465
|
+
# Wait for completion
|
|
466
|
+
exit_code = manager.wait_for_process(process, timeout=5.0)
|
|
467
|
+
assert exit_code == 0
|
|
468
|
+
|
|
469
|
+
# Process should be automatically unregistered
|
|
470
|
+
assert process.pid not in manager.active_processes
|
|
471
|
+
|
|
472
|
+
finally:
|
|
473
|
+
if process.pid in manager.active_processes:
|
|
474
|
+
manager.cleanup_process_tree(process)
|
|
475
|
+
|
|
476
|
+
|
|
477
|
+
class TestProcessManagerEdgeCases:
|
|
478
|
+
"""Test ProcessManager edge cases."""
|
|
479
|
+
|
|
480
|
+
def test_empty_command(self):
|
|
481
|
+
"""Test process creation with empty command."""
|
|
482
|
+
config = TimeoutConfig(default_timeout=60.0)
|
|
483
|
+
manager = ProcessManager(config)
|
|
484
|
+
|
|
485
|
+
# Empty command will create a process but it will fail at runtime
|
|
486
|
+
process = manager.create_process([])
|
|
487
|
+
|
|
488
|
+
try:
|
|
489
|
+
assert process is not None
|
|
490
|
+
assert process.pid > 0
|
|
491
|
+
|
|
492
|
+
# Wait for process to fail
|
|
493
|
+
try:
|
|
494
|
+
exit_code = process.wait(timeout=2.0)
|
|
495
|
+
# Process should fail with non-zero exit code
|
|
496
|
+
assert exit_code != 0
|
|
497
|
+
except subprocess.TimeoutExpired:
|
|
498
|
+
# Process might hang, that's also expected behavior
|
|
499
|
+
pass
|
|
500
|
+
finally:
|
|
501
|
+
if process and process.pid in manager.active_processes:
|
|
502
|
+
manager.cleanup_process_tree(process)
|
|
503
|
+
|
|
504
|
+
def test_very_short_timeout(self):
|
|
505
|
+
"""Test process with very short timeout."""
|
|
506
|
+
config = TimeoutConfig(default_timeout=60.0)
|
|
507
|
+
manager = ProcessManager(config)
|
|
508
|
+
|
|
509
|
+
if platform.system() == 'Windows':
|
|
510
|
+
command = ['ping', '127.0.0.1', '-n', '5']
|
|
511
|
+
else:
|
|
512
|
+
command = ['sleep', '1']
|
|
513
|
+
|
|
514
|
+
process = manager.create_process(command, timeout=0.001) # Very short
|
|
515
|
+
|
|
516
|
+
try:
|
|
517
|
+
if process:
|
|
518
|
+
start_time = time.time()
|
|
519
|
+
try:
|
|
520
|
+
process.wait(timeout=0.2)
|
|
521
|
+
except subprocess.TimeoutExpired:
|
|
522
|
+
# Expected if process is still running
|
|
523
|
+
pass
|
|
524
|
+
duration = time.time() - start_time
|
|
525
|
+
|
|
526
|
+
# Should have been killed quickly
|
|
527
|
+
assert duration < 0.5
|
|
528
|
+
finally:
|
|
529
|
+
if process and process.pid in manager.active_processes:
|
|
530
|
+
manager.cleanup_process_tree(process)
|
|
531
|
+
|
|
532
|
+
def test_cleanup_already_cleaned_process(self):
|
|
533
|
+
"""Test cleanup of already cleaned process."""
|
|
534
|
+
config = TimeoutConfig(default_timeout=60.0)
|
|
535
|
+
manager = ProcessManager(config)
|
|
536
|
+
|
|
537
|
+
if platform.system() == 'Windows':
|
|
538
|
+
command = ['echo', 'test']
|
|
539
|
+
else:
|
|
540
|
+
command = ['echo', 'test']
|
|
541
|
+
|
|
542
|
+
process = manager.create_process(command)
|
|
543
|
+
|
|
544
|
+
try:
|
|
545
|
+
pid = process.pid
|
|
546
|
+
|
|
547
|
+
# Wait for process to complete
|
|
548
|
+
process.wait(timeout=5)
|
|
549
|
+
|
|
550
|
+
# Cleanup once
|
|
551
|
+
result1 = manager.cleanup_process_tree(process)
|
|
552
|
+
|
|
553
|
+
# Cleanup again
|
|
554
|
+
result2 = manager.cleanup_process_tree(process)
|
|
555
|
+
|
|
556
|
+
# Both should handle gracefully
|
|
557
|
+
assert result1 is True or result1 is False
|
|
558
|
+
assert result2 is True or result2 is False
|
|
559
|
+
|
|
560
|
+
except Exception:
|
|
561
|
+
if process and process.pid in manager.active_processes:
|
|
562
|
+
manager.cleanup_process_tree(process)
|
|
563
|
+
|
|
564
|
+
def test_manager_state_after_errors(self):
|
|
565
|
+
"""Test manager state consistency after various errors."""
|
|
566
|
+
config = TimeoutConfig(default_timeout=60.0)
|
|
567
|
+
manager = ProcessManager(config)
|
|
568
|
+
|
|
569
|
+
initial_count = len(manager.active_processes)
|
|
570
|
+
|
|
571
|
+
# Try various operations that might fail
|
|
572
|
+
try:
|
|
573
|
+
# This will create a process that fails at runtime
|
|
574
|
+
process1 = manager.create_process(['this_command_does_not_exist'])
|
|
575
|
+
if process1:
|
|
576
|
+
manager.cleanup_process_tree(process1)
|
|
577
|
+
except CommandExecutionError:
|
|
578
|
+
pass
|
|
579
|
+
|
|
580
|
+
try:
|
|
581
|
+
manager.create_process(['echo', 'test'], cwd='/invalid/path')
|
|
582
|
+
except CommandExecutionError:
|
|
583
|
+
pass
|
|
584
|
+
|
|
585
|
+
# Manager state should be consistent (might have processes that were created)
|
|
586
|
+
current_count = len(manager.active_processes)
|
|
587
|
+
|
|
588
|
+
# Should still be able to create valid processes
|
|
589
|
+
if platform.system() == 'Windows':
|
|
590
|
+
command = ['echo', 'test']
|
|
591
|
+
else:
|
|
592
|
+
command = ['echo', 'test']
|
|
593
|
+
|
|
594
|
+
process = manager.create_process(command)
|
|
595
|
+
|
|
596
|
+
try:
|
|
597
|
+
assert process is not None
|
|
598
|
+
assert len(manager.active_processes) >= current_count
|
|
599
|
+
|
|
600
|
+
finally:
|
|
601
|
+
if process and process.pid in manager.active_processes:
|
|
602
|
+
manager.cleanup_process_tree(process)
|
|
603
|
+
|
|
604
|
+
|
|
605
|
+
if __name__ == "__main__":
|
|
606
|
+
pytest.main([__file__, "-v"])
|