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.
- 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-0.1.400.dist-info → auto_coder-2.0.0.dist-info}/WHEEL +1 -1
- {auto_coder-0.1.400.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 +25 -4
- 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 +1029 -2310
- 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 +1021 -372
- autocoder/chat_auto_coder_lang.py +23 -732
- autocoder/commands/auto_command.py +26 -9
- 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/file_monitor/test_file_monitor.py +307 -0
- autocoder/common/git_utils.py +51 -10
- 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 +746 -0
- autocoder/common/{context_pruner.py → pruner/context_pruner.py} +137 -40
- 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/{conversation_pruner.py → pruner/conversation_pruner.py} +26 -6
- autocoder/common/pruner/test_agentic_conversation_pruner.py +784 -0
- autocoder/common/pruner/test_context_pruner.py +546 -0
- 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/__init__.py +15 -0
- autocoder/common/tokens/counter.py +44 -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 +2729 -2052
- autocoder/common/v2/agent/agentic_edit_change_manager.py +474 -0
- autocoder/common/v2/agent/agentic_edit_tools/__init__.py +43 -2
- autocoder/common/v2/agent/agentic_edit_tools/ac_mod_list_tool_resolver.py +279 -0
- autocoder/common/v2/agent/agentic_edit_tools/ac_mod_read_tool_resolver.py +40 -0
- autocoder/common/v2/agent/agentic_edit_tools/ac_mod_write_tool_resolver.py +52 -0
- autocoder/common/v2/agent/agentic_edit_tools/ask_followup_question_tool_resolver.py +8 -0
- 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 +565 -30
- 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 +244 -51
- 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 +409 -140
- 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 +209 -194
- autocoder/common/v2/agent/agentic_edit_tools/todo_read_tool_resolver.py +135 -0
- autocoder/common/v2/agent/agentic_edit_tools/todo_write_tool_resolver.py +328 -0
- 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 +386 -10
- autocoder/common/v2/agent/runner/__init__.py +31 -0
- autocoder/common/v2/agent/runner/base_runner.py +92 -0
- autocoder/common/v2/agent/runner/file_based_event_runner.py +217 -0
- autocoder/common/v2/agent/runner/sdk_runner.py +182 -0
- autocoder/common/v2/agent/runner/terminal_runner.py +396 -0
- autocoder/common/v2/agent/runner/tool_display.py +589 -0
- 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 +117 -125
- autocoder/{agent → index/filter}/agentic_filter.py +323 -334
- 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 +156 -37
- 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/run_context.py +9 -0
- autocoder/sdk/__init__.py +50 -161
- 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 +158 -170
- autocoder/sdk/cli/options.py +95 -22
- autocoder/sdk/constants.py +139 -51
- autocoder/sdk/core/auto_coder_core.py +484 -267
- autocoder/sdk/core/bridge.py +298 -118
- 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-0.1.400.dist-info/METADATA +0 -396
- auto_coder-0.1.400.dist-info/RECORD +0 -425
- auto_coder-0.1.400.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/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-0.1.400.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,520 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Tests for timeout manager functionality.
|
|
3
|
+
|
|
4
|
+
This module tests the timeout management for shell command execution.
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
import pytest
|
|
8
|
+
import time
|
|
9
|
+
import threading
|
|
10
|
+
from unittest.mock import Mock, patch, MagicMock
|
|
11
|
+
|
|
12
|
+
from autocoder.common.shell_commands.timeout_manager import TimeoutManager
|
|
13
|
+
from autocoder.common.shell_commands.timeout_config import TimeoutConfig
|
|
14
|
+
from autocoder.common.shell_commands.exceptions import CommandTimeoutError
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
class TestTimeoutManager:
|
|
18
|
+
"""Test cases for TimeoutManager class."""
|
|
19
|
+
|
|
20
|
+
def test_initialization(self):
|
|
21
|
+
"""Test timeout manager initialization."""
|
|
22
|
+
config = TimeoutConfig(default_timeout=60.0)
|
|
23
|
+
manager = TimeoutManager(config)
|
|
24
|
+
|
|
25
|
+
assert manager.config == config
|
|
26
|
+
assert len(manager.active_timers) == 0
|
|
27
|
+
|
|
28
|
+
def test_start_timeout_basic(self):
|
|
29
|
+
"""Test starting a basic timeout."""
|
|
30
|
+
config = TimeoutConfig(default_timeout=1.0)
|
|
31
|
+
manager = TimeoutManager(config)
|
|
32
|
+
|
|
33
|
+
# Mock process
|
|
34
|
+
mock_process = Mock()
|
|
35
|
+
mock_process.pid = 123
|
|
36
|
+
mock_process.poll.return_value = None # Still running
|
|
37
|
+
|
|
38
|
+
# Start timeout
|
|
39
|
+
manager.start_timeout(mock_process, 0.1)
|
|
40
|
+
|
|
41
|
+
assert 123 in manager.active_timers
|
|
42
|
+
|
|
43
|
+
# Cleanup
|
|
44
|
+
manager.cancel_timeout(mock_process)
|
|
45
|
+
|
|
46
|
+
def test_start_timeout_with_callback(self):
|
|
47
|
+
"""Test starting timeout with custom callback."""
|
|
48
|
+
config = TimeoutConfig(default_timeout=1.0)
|
|
49
|
+
manager = TimeoutManager(config)
|
|
50
|
+
|
|
51
|
+
mock_process = Mock()
|
|
52
|
+
mock_process.pid = 123
|
|
53
|
+
mock_process.poll.return_value = None
|
|
54
|
+
|
|
55
|
+
callback_called = []
|
|
56
|
+
|
|
57
|
+
def custom_callback(proc, timeout):
|
|
58
|
+
callback_called.append((proc, timeout))
|
|
59
|
+
|
|
60
|
+
# Start timeout with callback
|
|
61
|
+
manager.start_timeout(mock_process, 0.01, custom_callback)
|
|
62
|
+
|
|
63
|
+
# Wait for timeout to trigger
|
|
64
|
+
time.sleep(0.02)
|
|
65
|
+
|
|
66
|
+
# Callback should have been called
|
|
67
|
+
assert len(callback_called) == 1
|
|
68
|
+
assert callback_called[0][0] == mock_process
|
|
69
|
+
assert callback_called[0][1] == 0.01
|
|
70
|
+
|
|
71
|
+
# Cleanup
|
|
72
|
+
manager.cancel_timeout(mock_process)
|
|
73
|
+
|
|
74
|
+
def test_cancel_timeout(self):
|
|
75
|
+
"""Test canceling a timeout."""
|
|
76
|
+
config = TimeoutConfig(default_timeout=1.0)
|
|
77
|
+
manager = TimeoutManager(config)
|
|
78
|
+
|
|
79
|
+
mock_process = Mock()
|
|
80
|
+
mock_process.pid = 123
|
|
81
|
+
mock_process.poll.return_value = None
|
|
82
|
+
|
|
83
|
+
# Start and then cancel timeout
|
|
84
|
+
manager.start_timeout(mock_process, 10.0) # Long timeout
|
|
85
|
+
assert 123 in manager.active_timers
|
|
86
|
+
|
|
87
|
+
cancelled = manager.cancel_timeout(mock_process)
|
|
88
|
+
assert cancelled
|
|
89
|
+
assert 123 not in manager.active_timers
|
|
90
|
+
|
|
91
|
+
def test_cancel_nonexistent_timeout(self):
|
|
92
|
+
"""Test canceling a non-existent timeout."""
|
|
93
|
+
config = TimeoutConfig(default_timeout=1.0)
|
|
94
|
+
manager = TimeoutManager(config)
|
|
95
|
+
|
|
96
|
+
mock_process = Mock()
|
|
97
|
+
mock_process.pid = 999
|
|
98
|
+
|
|
99
|
+
cancelled = manager.cancel_timeout(mock_process)
|
|
100
|
+
assert not cancelled
|
|
101
|
+
|
|
102
|
+
def test_timeout_triggers_callback(self):
|
|
103
|
+
"""Test that timeout triggers the callback function."""
|
|
104
|
+
config = TimeoutConfig(default_timeout=1.0)
|
|
105
|
+
manager = TimeoutManager(config)
|
|
106
|
+
|
|
107
|
+
mock_process = Mock()
|
|
108
|
+
mock_process.pid = 123
|
|
109
|
+
mock_process.poll.return_value = None # Process still running
|
|
110
|
+
|
|
111
|
+
timeout_triggered = []
|
|
112
|
+
|
|
113
|
+
def timeout_callback(proc, timeout):
|
|
114
|
+
timeout_triggered.append(True)
|
|
115
|
+
|
|
116
|
+
# Mock cleanup_process_tree to prevent system calls
|
|
117
|
+
with patch('autocoder.common.shell_commands.timeout_manager.cleanup_process_tree', return_value=True):
|
|
118
|
+
# Start timeout with very short duration
|
|
119
|
+
manager.start_timeout(mock_process, 0.01, timeout_callback)
|
|
120
|
+
|
|
121
|
+
# Wait for timeout to trigger
|
|
122
|
+
time.sleep(0.02)
|
|
123
|
+
|
|
124
|
+
assert len(timeout_triggered) == 1
|
|
125
|
+
|
|
126
|
+
# Cleanup
|
|
127
|
+
manager.cancel_timeout(mock_process)
|
|
128
|
+
|
|
129
|
+
def test_timeout_does_not_trigger_for_completed_process(self):
|
|
130
|
+
"""Test that timeout doesn't trigger for already completed process."""
|
|
131
|
+
config = TimeoutConfig(default_timeout=1.0)
|
|
132
|
+
manager = TimeoutManager(config)
|
|
133
|
+
|
|
134
|
+
mock_process = Mock()
|
|
135
|
+
mock_process.pid = 123
|
|
136
|
+
mock_process.poll.return_value = 0 # Process completed
|
|
137
|
+
|
|
138
|
+
timeout_triggered = []
|
|
139
|
+
|
|
140
|
+
def timeout_callback(proc, timeout):
|
|
141
|
+
timeout_triggered.append(True)
|
|
142
|
+
|
|
143
|
+
# Mock cleanup_process_tree to prevent system calls
|
|
144
|
+
with patch('autocoder.common.shell_commands.timeout_manager.cleanup_process_tree', return_value=True):
|
|
145
|
+
# Start timeout
|
|
146
|
+
manager.start_timeout(mock_process, 0.01, timeout_callback)
|
|
147
|
+
|
|
148
|
+
# Wait for potential timeout
|
|
149
|
+
time.sleep(0.02)
|
|
150
|
+
|
|
151
|
+
# Timeout will still trigger since TimeoutManager doesn't check process.poll()
|
|
152
|
+
# but callback should be called
|
|
153
|
+
assert len(timeout_triggered) == 1
|
|
154
|
+
|
|
155
|
+
# PID should be cleaned up from active timers
|
|
156
|
+
assert 123 not in manager.active_timers
|
|
157
|
+
|
|
158
|
+
def test_get_active_timeouts(self):
|
|
159
|
+
"""Test getting list of active timeouts."""
|
|
160
|
+
config = TimeoutConfig(default_timeout=1.0)
|
|
161
|
+
manager = TimeoutManager(config)
|
|
162
|
+
|
|
163
|
+
mock_process1 = Mock()
|
|
164
|
+
mock_process1.pid = 123
|
|
165
|
+
mock_process1.poll.return_value = None
|
|
166
|
+
|
|
167
|
+
mock_process2 = Mock()
|
|
168
|
+
mock_process2.pid = 456
|
|
169
|
+
mock_process2.poll.return_value = None
|
|
170
|
+
|
|
171
|
+
# Start multiple timeouts
|
|
172
|
+
manager.start_timeout(mock_process1, 10.0)
|
|
173
|
+
manager.start_timeout(mock_process2, 10.0)
|
|
174
|
+
|
|
175
|
+
active = manager.get_active_timeouts()
|
|
176
|
+
assert 123 in active
|
|
177
|
+
assert 456 in active
|
|
178
|
+
assert len(active) == 2
|
|
179
|
+
|
|
180
|
+
# Cleanup
|
|
181
|
+
manager.cancel_timeout(mock_process1)
|
|
182
|
+
manager.cancel_timeout(mock_process2)
|
|
183
|
+
|
|
184
|
+
def test_cleanup_all_timeouts(self):
|
|
185
|
+
"""Test cleaning up all active timeouts."""
|
|
186
|
+
config = TimeoutConfig(default_timeout=1.0)
|
|
187
|
+
manager = TimeoutManager(config)
|
|
188
|
+
|
|
189
|
+
# Start multiple timeouts
|
|
190
|
+
processes = []
|
|
191
|
+
for pid in [123, 456, 789]:
|
|
192
|
+
mock_process = Mock()
|
|
193
|
+
mock_process.pid = pid
|
|
194
|
+
mock_process.poll.return_value = None
|
|
195
|
+
processes.append(mock_process)
|
|
196
|
+
manager.start_timeout(mock_process, 10.0)
|
|
197
|
+
|
|
198
|
+
assert len(manager.active_timers) == 3
|
|
199
|
+
|
|
200
|
+
# Clean up all
|
|
201
|
+
manager.cleanup_all_timeouts()
|
|
202
|
+
|
|
203
|
+
assert len(manager.active_timers) == 0
|
|
204
|
+
|
|
205
|
+
def test_is_timeout_active(self):
|
|
206
|
+
"""Test checking if timeout is active."""
|
|
207
|
+
config = TimeoutConfig(default_timeout=1.0)
|
|
208
|
+
manager = TimeoutManager(config)
|
|
209
|
+
|
|
210
|
+
mock_process = Mock()
|
|
211
|
+
mock_process.pid = 123
|
|
212
|
+
mock_process.poll.return_value = None
|
|
213
|
+
|
|
214
|
+
# Initially no timeout
|
|
215
|
+
assert not manager.is_timeout_active(mock_process)
|
|
216
|
+
|
|
217
|
+
# Start timeout
|
|
218
|
+
manager.start_timeout(mock_process, 10.0)
|
|
219
|
+
assert manager.is_timeout_active(mock_process)
|
|
220
|
+
|
|
221
|
+
# Cancel timeout
|
|
222
|
+
manager.cancel_timeout(mock_process)
|
|
223
|
+
assert not manager.is_timeout_active(mock_process)
|
|
224
|
+
|
|
225
|
+
def test_default_timeout_callback(self):
|
|
226
|
+
"""Test the default timeout callback behavior."""
|
|
227
|
+
config = TimeoutConfig(default_timeout=1.0)
|
|
228
|
+
manager = TimeoutManager(config)
|
|
229
|
+
|
|
230
|
+
mock_process = Mock()
|
|
231
|
+
mock_process.pid = 123
|
|
232
|
+
mock_process.poll.return_value = None
|
|
233
|
+
mock_process.terminate = Mock()
|
|
234
|
+
mock_process.kill = Mock()
|
|
235
|
+
|
|
236
|
+
# Mock cleanup_process_tree to prevent system calls
|
|
237
|
+
with patch('autocoder.common.shell_commands.timeout_manager.cleanup_process_tree', return_value=True):
|
|
238
|
+
# Start timeout without custom callback (uses default)
|
|
239
|
+
manager.start_timeout(mock_process, 0.01)
|
|
240
|
+
|
|
241
|
+
# Wait for timeout to trigger
|
|
242
|
+
time.sleep(0.02)
|
|
243
|
+
|
|
244
|
+
# Process cleanup should have been attempted
|
|
245
|
+
# The actual cleanup is handled by cleanup_process_tree function
|
|
246
|
+
|
|
247
|
+
# Cleanup
|
|
248
|
+
manager.cancel_timeout(mock_process)
|
|
249
|
+
|
|
250
|
+
def test_timeout_with_process_cleanup(self):
|
|
251
|
+
"""Test timeout behavior with process cleanup."""
|
|
252
|
+
config = TimeoutConfig(default_timeout=1.0, grace_period=0.01)
|
|
253
|
+
manager = TimeoutManager(config)
|
|
254
|
+
|
|
255
|
+
mock_process = Mock()
|
|
256
|
+
mock_process.pid = 123
|
|
257
|
+
mock_process.poll.return_value = None
|
|
258
|
+
mock_process.terminate = Mock()
|
|
259
|
+
mock_process.kill = Mock()
|
|
260
|
+
|
|
261
|
+
# Mock cleanup_process_tree to prevent system calls
|
|
262
|
+
with patch('autocoder.common.shell_commands.timeout_manager.cleanup_process_tree', return_value=True):
|
|
263
|
+
# Start timeout
|
|
264
|
+
manager.start_timeout(mock_process, 0.01)
|
|
265
|
+
|
|
266
|
+
# Wait for timeout and grace period
|
|
267
|
+
time.sleep(0.03)
|
|
268
|
+
|
|
269
|
+
# Process cleanup should have been attempted
|
|
270
|
+
# The actual cleanup is handled by cleanup_process_tree function
|
|
271
|
+
|
|
272
|
+
# Cleanup
|
|
273
|
+
manager.cancel_timeout(mock_process)
|
|
274
|
+
|
|
275
|
+
|
|
276
|
+
class TestTimeoutManagerThreadSafety:
|
|
277
|
+
"""Test cases for thread safety of TimeoutManager."""
|
|
278
|
+
|
|
279
|
+
def test_concurrent_timeout_operations(self):
|
|
280
|
+
"""Test concurrent timeout start/cancel operations."""
|
|
281
|
+
config = TimeoutConfig(default_timeout=1.0)
|
|
282
|
+
manager = TimeoutManager(config)
|
|
283
|
+
|
|
284
|
+
results = []
|
|
285
|
+
processes = []
|
|
286
|
+
|
|
287
|
+
def start_timeouts():
|
|
288
|
+
for i in range(10):
|
|
289
|
+
mock_process = Mock()
|
|
290
|
+
mock_process.pid = 1000 + i
|
|
291
|
+
mock_process.poll.return_value = None
|
|
292
|
+
processes.append(mock_process)
|
|
293
|
+
manager.start_timeout(mock_process, 1.0)
|
|
294
|
+
results.append(('start', True))
|
|
295
|
+
|
|
296
|
+
def cancel_timeouts():
|
|
297
|
+
time.sleep(0.01) # Let some timeouts start first
|
|
298
|
+
for i in range(10):
|
|
299
|
+
if i < len(processes):
|
|
300
|
+
cancelled = manager.cancel_timeout(processes[i])
|
|
301
|
+
results.append(('cancel', cancelled))
|
|
302
|
+
|
|
303
|
+
# Run concurrent operations
|
|
304
|
+
thread1 = threading.Thread(target=start_timeouts)
|
|
305
|
+
thread2 = threading.Thread(target=cancel_timeouts)
|
|
306
|
+
|
|
307
|
+
thread1.start()
|
|
308
|
+
thread2.start()
|
|
309
|
+
|
|
310
|
+
thread1.join()
|
|
311
|
+
thread2.join()
|
|
312
|
+
|
|
313
|
+
# Should have handled all operations without crashes
|
|
314
|
+
assert len(results) >= 10 # At least the start operations
|
|
315
|
+
|
|
316
|
+
# Cleanup any remaining timeouts
|
|
317
|
+
manager.cleanup_all_timeouts()
|
|
318
|
+
|
|
319
|
+
|
|
320
|
+
class TestTimeoutManagerErrorCases:
|
|
321
|
+
"""Test cases for error conditions and edge cases."""
|
|
322
|
+
|
|
323
|
+
def test_timeout_with_none_process(self):
|
|
324
|
+
"""Test timeout with None process."""
|
|
325
|
+
config = TimeoutConfig(default_timeout=1.0)
|
|
326
|
+
manager = TimeoutManager(config)
|
|
327
|
+
|
|
328
|
+
# This should raise an AttributeError when trying to access process.pid
|
|
329
|
+
with pytest.raises(AttributeError):
|
|
330
|
+
manager.start_timeout(None, 1.0) # type: ignore
|
|
331
|
+
|
|
332
|
+
def test_timeout_with_invalid_timeout_value(self):
|
|
333
|
+
"""Test timeout with invalid timeout values."""
|
|
334
|
+
config = TimeoutConfig(default_timeout=1.0)
|
|
335
|
+
manager = TimeoutManager(config)
|
|
336
|
+
|
|
337
|
+
mock_process = Mock()
|
|
338
|
+
mock_process.pid = 123
|
|
339
|
+
|
|
340
|
+
# Negative timeout - should be ignored
|
|
341
|
+
manager.start_timeout(mock_process, -1.0)
|
|
342
|
+
assert 123 not in manager.active_timers
|
|
343
|
+
|
|
344
|
+
# Zero timeout - should be ignored
|
|
345
|
+
manager.start_timeout(mock_process, 0.0)
|
|
346
|
+
assert 123 not in manager.active_timers
|
|
347
|
+
|
|
348
|
+
def test_timeout_callback_exception(self):
|
|
349
|
+
"""Test timeout behavior when callback raises exception."""
|
|
350
|
+
config = TimeoutConfig(default_timeout=1.0)
|
|
351
|
+
manager = TimeoutManager(config)
|
|
352
|
+
|
|
353
|
+
mock_process = Mock()
|
|
354
|
+
mock_process.pid = 123
|
|
355
|
+
mock_process.poll.return_value = None
|
|
356
|
+
|
|
357
|
+
def failing_callback(proc, timeout):
|
|
358
|
+
raise RuntimeError("Callback failed")
|
|
359
|
+
|
|
360
|
+
# Mock cleanup_process_tree to prevent system calls
|
|
361
|
+
with patch('autocoder.common.shell_commands.timeout_manager.cleanup_process_tree', return_value=True):
|
|
362
|
+
# Start timeout with failing callback
|
|
363
|
+
manager.start_timeout(mock_process, 0.01, failing_callback)
|
|
364
|
+
|
|
365
|
+
# Wait for timeout to trigger
|
|
366
|
+
time.sleep(0.02)
|
|
367
|
+
|
|
368
|
+
# Manager should still be functional despite callback failure
|
|
369
|
+
# The process should have been cleaned up from active timers
|
|
370
|
+
assert 123 not in manager.active_timers
|
|
371
|
+
|
|
372
|
+
# Cleanup
|
|
373
|
+
manager.cancel_timeout(mock_process)
|
|
374
|
+
|
|
375
|
+
def test_process_poll_exception(self):
|
|
376
|
+
"""Test timeout behavior when process.poll() raises exception."""
|
|
377
|
+
config = TimeoutConfig(default_timeout=1.0)
|
|
378
|
+
manager = TimeoutManager(config)
|
|
379
|
+
|
|
380
|
+
mock_process = Mock()
|
|
381
|
+
mock_process.pid = 123
|
|
382
|
+
mock_process.poll.side_effect = OSError("Process access error")
|
|
383
|
+
|
|
384
|
+
callback_called = []
|
|
385
|
+
|
|
386
|
+
def test_callback(proc, timeout):
|
|
387
|
+
callback_called.append(True)
|
|
388
|
+
|
|
389
|
+
# Mock cleanup_process_tree to prevent system calls
|
|
390
|
+
with patch('autocoder.common.shell_commands.timeout_manager.cleanup_process_tree', return_value=True):
|
|
391
|
+
# Start timeout
|
|
392
|
+
manager.start_timeout(mock_process, 0.01, test_callback)
|
|
393
|
+
|
|
394
|
+
# Wait for timeout
|
|
395
|
+
time.sleep(0.02)
|
|
396
|
+
|
|
397
|
+
# Callback should still be called despite poll() exception
|
|
398
|
+
assert len(callback_called) == 1
|
|
399
|
+
|
|
400
|
+
# Cleanup
|
|
401
|
+
manager.cancel_timeout(mock_process)
|
|
402
|
+
|
|
403
|
+
def test_duplicate_pid_timeout(self):
|
|
404
|
+
"""Test starting timeout for same PID twice."""
|
|
405
|
+
config = TimeoutConfig(default_timeout=1.0)
|
|
406
|
+
manager = TimeoutManager(config)
|
|
407
|
+
|
|
408
|
+
mock_process = Mock()
|
|
409
|
+
mock_process.pid = 123
|
|
410
|
+
mock_process.poll.return_value = None
|
|
411
|
+
|
|
412
|
+
# Start first timeout
|
|
413
|
+
manager.start_timeout(mock_process, 1.0)
|
|
414
|
+
assert 123 in manager.active_timers
|
|
415
|
+
|
|
416
|
+
# Start second timeout for same PID
|
|
417
|
+
manager.start_timeout(mock_process, 1.0)
|
|
418
|
+
|
|
419
|
+
# Should have cancelled the first timeout and started new one
|
|
420
|
+
assert 123 in manager.active_timers
|
|
421
|
+
|
|
422
|
+
# Cleanup
|
|
423
|
+
manager.cancel_timeout(mock_process)
|
|
424
|
+
|
|
425
|
+
def test_timer_cleanup_on_exception(self):
|
|
426
|
+
"""Test that timers are cleaned up even when exceptions occur."""
|
|
427
|
+
config = TimeoutConfig(default_timeout=1.0)
|
|
428
|
+
manager = TimeoutManager(config)
|
|
429
|
+
|
|
430
|
+
mock_process = Mock()
|
|
431
|
+
mock_process.pid = 123
|
|
432
|
+
mock_process.poll.return_value = None
|
|
433
|
+
|
|
434
|
+
# Mock the Timer to raise an exception
|
|
435
|
+
with patch('threading.Timer') as mock_timer_class:
|
|
436
|
+
mock_timer = Mock()
|
|
437
|
+
mock_timer.start.side_effect = RuntimeError("Timer failed")
|
|
438
|
+
mock_timer_class.return_value = mock_timer
|
|
439
|
+
|
|
440
|
+
# Should handle exception gracefully
|
|
441
|
+
manager.start_timeout(mock_process, 1.0)
|
|
442
|
+
|
|
443
|
+
# Timer should not be in active timers due to exception
|
|
444
|
+
assert 123 not in manager.active_timers
|
|
445
|
+
|
|
446
|
+
|
|
447
|
+
class TestTimeoutManagerIntegration:
|
|
448
|
+
"""Integration tests for TimeoutManager."""
|
|
449
|
+
|
|
450
|
+
def test_real_timeout_scenario(self):
|
|
451
|
+
"""Test a realistic timeout scenario."""
|
|
452
|
+
config = TimeoutConfig(default_timeout=0.1, grace_period=0.01)
|
|
453
|
+
manager = TimeoutManager(config)
|
|
454
|
+
|
|
455
|
+
# Create a real subprocess for testing
|
|
456
|
+
import subprocess
|
|
457
|
+
import platform
|
|
458
|
+
|
|
459
|
+
if platform.system() == 'Windows':
|
|
460
|
+
proc = subprocess.Popen(['ping', '127.0.0.1', '-n', '10'])
|
|
461
|
+
else:
|
|
462
|
+
proc = subprocess.Popen(['sleep', '10'])
|
|
463
|
+
|
|
464
|
+
timeout_occurred = []
|
|
465
|
+
|
|
466
|
+
def timeout_callback(process, timeout):
|
|
467
|
+
timeout_occurred.append(True)
|
|
468
|
+
try:
|
|
469
|
+
process.terminate()
|
|
470
|
+
except:
|
|
471
|
+
pass
|
|
472
|
+
|
|
473
|
+
try:
|
|
474
|
+
# Mock cleanup_process_tree to prevent system calls
|
|
475
|
+
with patch('autocoder.common.shell_commands.timeout_manager.cleanup_process_tree', return_value=True):
|
|
476
|
+
# Start timeout
|
|
477
|
+
manager.start_timeout(proc, 0.05, timeout_callback)
|
|
478
|
+
|
|
479
|
+
# Wait for timeout to occur
|
|
480
|
+
time.sleep(0.1)
|
|
481
|
+
|
|
482
|
+
# Timeout should have occurred
|
|
483
|
+
assert len(timeout_occurred) == 1
|
|
484
|
+
|
|
485
|
+
finally:
|
|
486
|
+
# Cleanup
|
|
487
|
+
try:
|
|
488
|
+
proc.terminate()
|
|
489
|
+
proc.wait(timeout=1)
|
|
490
|
+
except:
|
|
491
|
+
pass
|
|
492
|
+
manager.cancel_timeout(proc)
|
|
493
|
+
|
|
494
|
+
def test_timeout_manager_with_command_executor_integration(self):
|
|
495
|
+
"""Test timeout manager integration with command execution."""
|
|
496
|
+
config = TimeoutConfig(default_timeout=0.1)
|
|
497
|
+
manager = TimeoutManager(config)
|
|
498
|
+
|
|
499
|
+
# Simulate process lifecycle
|
|
500
|
+
mock_process = Mock()
|
|
501
|
+
mock_process.pid = 123
|
|
502
|
+
mock_process.poll.return_value = None
|
|
503
|
+
mock_process.terminate = Mock()
|
|
504
|
+
|
|
505
|
+
# Start timeout
|
|
506
|
+
manager.start_timeout(mock_process, 0.05)
|
|
507
|
+
|
|
508
|
+
# Simulate process completing before timeout
|
|
509
|
+
time.sleep(0.02)
|
|
510
|
+
mock_process.poll.return_value = 0 # Process completed
|
|
511
|
+
|
|
512
|
+
# Cancel timeout (process completed)
|
|
513
|
+
cancelled = manager.cancel_timeout(mock_process)
|
|
514
|
+
|
|
515
|
+
# Should have been able to cancel
|
|
516
|
+
assert cancelled or 123 not in manager.active_timers
|
|
517
|
+
|
|
518
|
+
|
|
519
|
+
if __name__ == "__main__":
|
|
520
|
+
pytest.main([__file__, "-v"])
|