auto-coder 1.0.0__py3-none-any.whl → 2.0.1__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.1.dist-info/LICENSE +158 -0
- auto_coder-2.0.1.dist-info/METADATA +558 -0
- auto_coder-2.0.1.dist-info/RECORD +795 -0
- {auto_coder-1.0.0.dist-info → auto_coder-2.0.1.dist-info}/WHEEL +1 -1
- {auto_coder-1.0.0.dist-info → auto_coder-2.0.1.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 +77 -73
- autocoder/auto_coder.py +31 -40
- autocoder/auto_coder_rag.py +11 -1084
- autocoder/auto_coder_runner.py +962 -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 +409 -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 +316 -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 +356 -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 +1094 -0
- autocoder/default_project/__init__.py +501 -0
- autocoder/dispacher/__init__.py +4 -12
- autocoder/dispacher/actions/action.py +400 -129
- autocoder/dispacher/actions/plugins/action_regex_project.py +2 -2
- autocoder/index/entry.py +117 -125
- 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 +923 -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 +665 -0
- autocoder/workflow_agents/loader.py +749 -0
- autocoder/workflow_agents/runner.py +267 -0
- autocoder/workflow_agents/types.py +173 -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.1.dist-info}/top_level.txt +0 -0
- /autocoder/{sdk/example.py → common/agent_query_queue/__init__.py} +0 -0
|
@@ -0,0 +1,305 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Tests for error recovery functionality.
|
|
3
|
+
|
|
4
|
+
This module tests the error recovery mechanisms used in shell command execution.
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
import pytest
|
|
8
|
+
import time
|
|
9
|
+
from unittest.mock import Mock, patch
|
|
10
|
+
|
|
11
|
+
from autocoder.common.shell_commands.error_recovery import (
|
|
12
|
+
ErrorRecoveryManager,
|
|
13
|
+
RetryConfig,
|
|
14
|
+
create_default_error_recovery_manager,
|
|
15
|
+
retry_with_backoff
|
|
16
|
+
)
|
|
17
|
+
from autocoder.common.shell_commands.exceptions import (
|
|
18
|
+
CommandExecutionError,
|
|
19
|
+
CommandTimeoutError,
|
|
20
|
+
ErrorRecoveryFailedError
|
|
21
|
+
)
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
class TestRetryConfig:
|
|
25
|
+
"""Test cases for RetryConfig class."""
|
|
26
|
+
|
|
27
|
+
def test_initialization_defaults(self):
|
|
28
|
+
"""Test RetryConfig initialization with default values."""
|
|
29
|
+
config = RetryConfig()
|
|
30
|
+
assert config.max_attempts == 3
|
|
31
|
+
assert config.base_delay == 1.0
|
|
32
|
+
assert config.max_delay == 60.0
|
|
33
|
+
assert config.backoff_factor == 2.0
|
|
34
|
+
assert config.retry_on_timeout is True
|
|
35
|
+
assert config.retry_on_cleanup_error is True
|
|
36
|
+
|
|
37
|
+
def test_initialization_custom(self):
|
|
38
|
+
"""Test RetryConfig initialization with custom values."""
|
|
39
|
+
config = RetryConfig(
|
|
40
|
+
max_attempts=5,
|
|
41
|
+
base_delay=2.0,
|
|
42
|
+
max_delay=120.0,
|
|
43
|
+
backoff_factor=3.0,
|
|
44
|
+
retry_on_timeout=False,
|
|
45
|
+
retry_on_cleanup_error=False
|
|
46
|
+
)
|
|
47
|
+
assert config.max_attempts == 5
|
|
48
|
+
assert config.base_delay == 2.0
|
|
49
|
+
assert config.max_delay == 120.0
|
|
50
|
+
assert config.backoff_factor == 3.0
|
|
51
|
+
assert config.retry_on_timeout is False
|
|
52
|
+
assert config.retry_on_cleanup_error is False
|
|
53
|
+
|
|
54
|
+
def test_get_delay_exponential_backoff(self):
|
|
55
|
+
"""Test exponential backoff delay calculation."""
|
|
56
|
+
config = RetryConfig(base_delay=1.0, backoff_factor=2.0, max_delay=10.0, jitter=False)
|
|
57
|
+
|
|
58
|
+
assert config.get_delay(0) == 1.0 # base_delay * 2^0
|
|
59
|
+
assert config.get_delay(1) == 2.0 # base_delay * 2^1
|
|
60
|
+
assert config.get_delay(2) == 4.0 # base_delay * 2^2
|
|
61
|
+
|
|
62
|
+
def test_get_delay_max_limit(self):
|
|
63
|
+
"""Test that delay calculation respects maximum limit."""
|
|
64
|
+
config = RetryConfig(base_delay=1.0, backoff_factor=2.0, max_delay=5.0, jitter=False)
|
|
65
|
+
|
|
66
|
+
# Even with exponential backoff, delay should not exceed max_delay
|
|
67
|
+
delay_high = config.get_delay(10) # Very high attempt number
|
|
68
|
+
assert delay_high <= 5.0
|
|
69
|
+
|
|
70
|
+
def test_should_retry_timeout_error(self):
|
|
71
|
+
"""Test retry decision for timeout errors."""
|
|
72
|
+
config = RetryConfig(retry_on_timeout=True)
|
|
73
|
+
timeout_error = CommandTimeoutError("test", 5.0, 123)
|
|
74
|
+
assert config.should_retry(timeout_error, 0)
|
|
75
|
+
assert config.should_retry(timeout_error, 1)
|
|
76
|
+
assert config.should_retry(timeout_error, 2)
|
|
77
|
+
assert not config.should_retry(timeout_error, 3) # Max attempts reached
|
|
78
|
+
|
|
79
|
+
def test_should_retry_timeout_disabled(self):
|
|
80
|
+
"""Test retry decision when timeout retry is disabled."""
|
|
81
|
+
config = RetryConfig(retry_on_timeout=False)
|
|
82
|
+
timeout_error = CommandTimeoutError("test", 5.0, 123)
|
|
83
|
+
assert not config.should_retry(timeout_error, 0)
|
|
84
|
+
|
|
85
|
+
def test_should_retry_generic_error(self):
|
|
86
|
+
"""Test retry decision for generic errors."""
|
|
87
|
+
config = RetryConfig()
|
|
88
|
+
generic_error = Exception("Generic error")
|
|
89
|
+
assert not config.should_retry(generic_error, 0)
|
|
90
|
+
|
|
91
|
+
|
|
92
|
+
class TestErrorRecoveryManager:
|
|
93
|
+
"""Test cases for ErrorRecoveryManager class."""
|
|
94
|
+
|
|
95
|
+
def test_initialization_defaults(self):
|
|
96
|
+
"""Test manager initialization with default values."""
|
|
97
|
+
manager = ErrorRecoveryManager()
|
|
98
|
+
assert manager.max_recovery_attempts == 3
|
|
99
|
+
assert len(manager.recovery_strategies) > 0
|
|
100
|
+
|
|
101
|
+
def test_initialization_custom(self):
|
|
102
|
+
"""Test manager initialization with custom values."""
|
|
103
|
+
manager = ErrorRecoveryManager(max_recovery_attempts=5)
|
|
104
|
+
assert manager.max_recovery_attempts == 5
|
|
105
|
+
|
|
106
|
+
def test_register_recovery_strategy(self):
|
|
107
|
+
"""Test registering custom recovery strategies."""
|
|
108
|
+
manager = ErrorRecoveryManager()
|
|
109
|
+
|
|
110
|
+
def custom_strategy(error, context, retry_count):
|
|
111
|
+
return True
|
|
112
|
+
|
|
113
|
+
manager.register_recovery_strategy(ValueError, custom_strategy)
|
|
114
|
+
assert ValueError in manager.recovery_strategies
|
|
115
|
+
|
|
116
|
+
def test_handle_error_success(self):
|
|
117
|
+
"""Test successful error recovery."""
|
|
118
|
+
manager = ErrorRecoveryManager()
|
|
119
|
+
|
|
120
|
+
# Mock a successful recovery
|
|
121
|
+
def mock_strategy(error, context, retry_count):
|
|
122
|
+
return True
|
|
123
|
+
|
|
124
|
+
manager.register_recovery_strategy(ValueError, mock_strategy)
|
|
125
|
+
|
|
126
|
+
error = ValueError("Test error")
|
|
127
|
+
result = manager.handle_error(error)
|
|
128
|
+
assert result is True
|
|
129
|
+
|
|
130
|
+
def test_handle_error_failure(self):
|
|
131
|
+
"""Test failed error recovery."""
|
|
132
|
+
manager = ErrorRecoveryManager(max_recovery_attempts=1)
|
|
133
|
+
|
|
134
|
+
# Mock a failed recovery
|
|
135
|
+
def mock_strategy(error, context, retry_count):
|
|
136
|
+
return False
|
|
137
|
+
|
|
138
|
+
manager.register_recovery_strategy(ValueError, mock_strategy)
|
|
139
|
+
|
|
140
|
+
error = ValueError("Test error")
|
|
141
|
+
with pytest.raises(ErrorRecoveryFailedError):
|
|
142
|
+
manager.handle_error(error)
|
|
143
|
+
|
|
144
|
+
def test_handle_error_no_strategy(self):
|
|
145
|
+
"""Test error handling when no strategy is available."""
|
|
146
|
+
manager = ErrorRecoveryManager()
|
|
147
|
+
|
|
148
|
+
# Use an error type that doesn't have a strategy
|
|
149
|
+
error = KeyError("Test error")
|
|
150
|
+
result = manager.handle_error(error)
|
|
151
|
+
assert result is False
|
|
152
|
+
|
|
153
|
+
|
|
154
|
+
class TestRetryWithBackoff:
|
|
155
|
+
"""Test cases for retry_with_backoff function."""
|
|
156
|
+
|
|
157
|
+
def test_retry_success_on_first_try(self):
|
|
158
|
+
"""Test successful execution on first try."""
|
|
159
|
+
call_count = 0
|
|
160
|
+
|
|
161
|
+
def successful_func():
|
|
162
|
+
nonlocal call_count
|
|
163
|
+
call_count += 1
|
|
164
|
+
return "success"
|
|
165
|
+
|
|
166
|
+
config = RetryConfig()
|
|
167
|
+
result = retry_with_backoff(successful_func, config)
|
|
168
|
+
|
|
169
|
+
assert result == "success"
|
|
170
|
+
assert call_count == 1
|
|
171
|
+
|
|
172
|
+
def test_retry_success_after_failures(self):
|
|
173
|
+
"""Test successful execution after initial failures."""
|
|
174
|
+
call_count = 0
|
|
175
|
+
|
|
176
|
+
def flaky_func():
|
|
177
|
+
nonlocal call_count
|
|
178
|
+
call_count += 1
|
|
179
|
+
if call_count < 3:
|
|
180
|
+
raise CommandTimeoutError("test", 5.0, 123)
|
|
181
|
+
return "success"
|
|
182
|
+
|
|
183
|
+
config = RetryConfig(max_attempts=5, retry_on_timeout=True)
|
|
184
|
+
result = retry_with_backoff(flaky_func, config)
|
|
185
|
+
|
|
186
|
+
assert result == "success"
|
|
187
|
+
assert call_count == 3
|
|
188
|
+
|
|
189
|
+
def test_retry_max_attempts_exceeded(self):
|
|
190
|
+
"""Test behavior when max attempts is exceeded."""
|
|
191
|
+
call_count = 0
|
|
192
|
+
|
|
193
|
+
def always_fail_func():
|
|
194
|
+
nonlocal call_count
|
|
195
|
+
call_count += 1
|
|
196
|
+
raise CommandTimeoutError("test", 5.0, 123)
|
|
197
|
+
|
|
198
|
+
config = RetryConfig(max_attempts=2, retry_on_timeout=True)
|
|
199
|
+
with pytest.raises(CommandTimeoutError):
|
|
200
|
+
retry_with_backoff(always_fail_func, config)
|
|
201
|
+
|
|
202
|
+
assert call_count == 2
|
|
203
|
+
|
|
204
|
+
def test_retry_non_retryable_error(self):
|
|
205
|
+
"""Test behavior with non-retryable errors."""
|
|
206
|
+
call_count = 0
|
|
207
|
+
|
|
208
|
+
def non_retryable_func():
|
|
209
|
+
nonlocal call_count
|
|
210
|
+
call_count += 1
|
|
211
|
+
raise ValueError("Not retryable")
|
|
212
|
+
|
|
213
|
+
config = RetryConfig()
|
|
214
|
+
with pytest.raises(ValueError):
|
|
215
|
+
retry_with_backoff(non_retryable_func, config)
|
|
216
|
+
|
|
217
|
+
assert call_count == 1
|
|
218
|
+
|
|
219
|
+
@patch('time.sleep')
|
|
220
|
+
def test_retry_delay_timing(self, mock_sleep):
|
|
221
|
+
"""Test that delays are applied correctly."""
|
|
222
|
+
call_count = 0
|
|
223
|
+
|
|
224
|
+
def failing_func():
|
|
225
|
+
nonlocal call_count
|
|
226
|
+
call_count += 1
|
|
227
|
+
if call_count < 3:
|
|
228
|
+
raise CommandTimeoutError("test", 5.0, 123)
|
|
229
|
+
return "success"
|
|
230
|
+
|
|
231
|
+
config = RetryConfig(base_delay=1.0, max_attempts=3, retry_on_timeout=True, jitter=False)
|
|
232
|
+
result = retry_with_backoff(failing_func, config)
|
|
233
|
+
|
|
234
|
+
assert result == "success"
|
|
235
|
+
assert mock_sleep.call_count == 2 # Two retries, two delays
|
|
236
|
+
|
|
237
|
+
# Check that delays follow expected pattern
|
|
238
|
+
expected_delays = [1.0, 2.0] # Exponential backoff
|
|
239
|
+
actual_delays = [call.args[0] for call in mock_sleep.call_args_list]
|
|
240
|
+
assert actual_delays == expected_delays
|
|
241
|
+
|
|
242
|
+
|
|
243
|
+
class TestDefaultErrorRecoveryManager:
|
|
244
|
+
"""Test cases for default error recovery manager."""
|
|
245
|
+
|
|
246
|
+
def test_create_default_manager(self):
|
|
247
|
+
"""Test creating default error recovery manager."""
|
|
248
|
+
manager = create_default_error_recovery_manager()
|
|
249
|
+
assert isinstance(manager, ErrorRecoveryManager)
|
|
250
|
+
assert manager.max_recovery_attempts == 3
|
|
251
|
+
assert len(manager.recovery_strategies) > 0
|
|
252
|
+
|
|
253
|
+
def test_default_timeout_error_handling(self):
|
|
254
|
+
"""Test default handling of timeout errors."""
|
|
255
|
+
manager = create_default_error_recovery_manager()
|
|
256
|
+
|
|
257
|
+
timeout_error = CommandTimeoutError("test", 5.0, 123)
|
|
258
|
+
context = {}
|
|
259
|
+
|
|
260
|
+
# Should attempt recovery
|
|
261
|
+
result = manager.handle_error(timeout_error, context)
|
|
262
|
+
assert result is True # Should succeed on first try with increased timeout
|
|
263
|
+
assert 'timeout' in context # Context should be updated with new timeout
|
|
264
|
+
|
|
265
|
+
|
|
266
|
+
class TestErrorRecoveryEdgeCases:
|
|
267
|
+
"""Test cases for edge cases and error conditions."""
|
|
268
|
+
|
|
269
|
+
def test_zero_max_attempts(self):
|
|
270
|
+
"""Test behavior with zero max attempts."""
|
|
271
|
+
config = RetryConfig(max_attempts=0)
|
|
272
|
+
|
|
273
|
+
def failing_func():
|
|
274
|
+
raise CommandTimeoutError("test", 5.0, 123)
|
|
275
|
+
|
|
276
|
+
with pytest.raises(CommandTimeoutError):
|
|
277
|
+
retry_with_backoff(failing_func, config)
|
|
278
|
+
|
|
279
|
+
def test_negative_delay_values(self):
|
|
280
|
+
"""Test behavior with negative delay values."""
|
|
281
|
+
config = RetryConfig(base_delay=-1.0)
|
|
282
|
+
|
|
283
|
+
# Should handle negative delays gracefully
|
|
284
|
+
delay = config.get_delay(1)
|
|
285
|
+
assert delay >= 0 # Should not return negative delays
|
|
286
|
+
|
|
287
|
+
def test_function_with_side_effects(self):
|
|
288
|
+
"""Test retry behavior with functions that have side effects."""
|
|
289
|
+
side_effects = []
|
|
290
|
+
|
|
291
|
+
def side_effect_func():
|
|
292
|
+
side_effects.append("called")
|
|
293
|
+
if len(side_effects) < 2:
|
|
294
|
+
raise CommandTimeoutError("test", 5.0, 123)
|
|
295
|
+
return "success"
|
|
296
|
+
|
|
297
|
+
config = RetryConfig(max_attempts=3, retry_on_timeout=True)
|
|
298
|
+
result = retry_with_backoff(side_effect_func, config)
|
|
299
|
+
|
|
300
|
+
assert result == "success"
|
|
301
|
+
assert len(side_effects) == 2
|
|
302
|
+
|
|
303
|
+
|
|
304
|
+
if __name__ == "__main__":
|
|
305
|
+
pytest.main([__file__, "-v"])
|
|
@@ -0,0 +1,299 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Tests for shell command exceptions.
|
|
3
|
+
|
|
4
|
+
This module tests the custom exception classes used in the shell command system.
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
import pytest
|
|
8
|
+
|
|
9
|
+
from autocoder.common.shell_commands.exceptions import (
|
|
10
|
+
CommandExecutionError,
|
|
11
|
+
CommandTimeoutError,
|
|
12
|
+
ProcessCleanupError,
|
|
13
|
+
ProcessNotFoundError,
|
|
14
|
+
TimeoutConfigError,
|
|
15
|
+
ErrorRecoveryFailedError
|
|
16
|
+
)
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
class TestCommandExecutionError:
|
|
20
|
+
"""Test cases for CommandExecutionError."""
|
|
21
|
+
|
|
22
|
+
def test_basic_creation(self):
|
|
23
|
+
"""Test basic exception creation."""
|
|
24
|
+
error = CommandExecutionError("Test error message")
|
|
25
|
+
assert str(error) == "Test error message"
|
|
26
|
+
assert isinstance(error, Exception)
|
|
27
|
+
|
|
28
|
+
def test_inheritance(self):
|
|
29
|
+
"""Test that CommandExecutionError inherits from Exception."""
|
|
30
|
+
error = CommandExecutionError("Test")
|
|
31
|
+
assert isinstance(error, Exception)
|
|
32
|
+
|
|
33
|
+
def test_empty_message(self):
|
|
34
|
+
"""Test exception with empty message."""
|
|
35
|
+
error = CommandExecutionError("")
|
|
36
|
+
assert str(error) == ""
|
|
37
|
+
assert isinstance(error, Exception)
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
class TestCommandTimeoutError:
|
|
41
|
+
"""Test cases for CommandTimeoutError."""
|
|
42
|
+
|
|
43
|
+
def test_basic_creation(self):
|
|
44
|
+
"""Test basic timeout error creation."""
|
|
45
|
+
error = CommandTimeoutError("sleep 10", 5.0, 12345)
|
|
46
|
+
assert "sleep 10" in str(error)
|
|
47
|
+
assert "5.0" in str(error)
|
|
48
|
+
assert "12345" in str(error)
|
|
49
|
+
|
|
50
|
+
def test_attributes(self):
|
|
51
|
+
"""Test timeout error attributes."""
|
|
52
|
+
error = CommandTimeoutError("test command", 3.0, 999)
|
|
53
|
+
assert error.command == "test command"
|
|
54
|
+
assert error.timeout == 3.0
|
|
55
|
+
assert error.pid == 999
|
|
56
|
+
|
|
57
|
+
def test_without_pid(self):
|
|
58
|
+
"""Test timeout error without PID."""
|
|
59
|
+
error = CommandTimeoutError("echo hello", 2.5)
|
|
60
|
+
assert error.command == "echo hello"
|
|
61
|
+
assert error.timeout == 2.5
|
|
62
|
+
assert error.pid is None
|
|
63
|
+
assert "echo hello" in str(error)
|
|
64
|
+
assert "2.5" in str(error)
|
|
65
|
+
|
|
66
|
+
def test_string_representation(self):
|
|
67
|
+
"""Test string representation of timeout error."""
|
|
68
|
+
error = CommandTimeoutError("echo hello", 2.5, 1234)
|
|
69
|
+
error_str = str(error)
|
|
70
|
+
assert "echo hello" in error_str
|
|
71
|
+
assert "2.5" in error_str
|
|
72
|
+
assert "1234" in error_str
|
|
73
|
+
assert "timed out" in error_str.lower()
|
|
74
|
+
|
|
75
|
+
def test_repr(self):
|
|
76
|
+
"""Test __repr__ method."""
|
|
77
|
+
error = CommandTimeoutError("test", 1.0, 123)
|
|
78
|
+
repr_str = repr(error)
|
|
79
|
+
assert "CommandTimeoutError" in repr_str
|
|
80
|
+
assert "test" in repr_str
|
|
81
|
+
assert "1.0" in repr_str
|
|
82
|
+
assert "123" in repr_str
|
|
83
|
+
|
|
84
|
+
def test_inheritance(self):
|
|
85
|
+
"""Test inheritance from CommandExecutionError."""
|
|
86
|
+
error = CommandTimeoutError("test", 1.0, 123)
|
|
87
|
+
assert isinstance(error, CommandExecutionError)
|
|
88
|
+
assert isinstance(error, Exception)
|
|
89
|
+
|
|
90
|
+
|
|
91
|
+
class TestProcessCleanupError:
|
|
92
|
+
"""Test cases for ProcessCleanupError."""
|
|
93
|
+
|
|
94
|
+
def test_basic_creation(self):
|
|
95
|
+
"""Test basic process cleanup error creation."""
|
|
96
|
+
error = ProcessCleanupError(1234, "Failed to cleanup process")
|
|
97
|
+
assert error.pid == 1234
|
|
98
|
+
assert error.original_message == "Failed to cleanup process"
|
|
99
|
+
assert "1234" in str(error)
|
|
100
|
+
assert "Failed to cleanup process" in str(error)
|
|
101
|
+
|
|
102
|
+
def test_string_representation(self):
|
|
103
|
+
"""Test string representation."""
|
|
104
|
+
error = ProcessCleanupError(5678, "Process is still running")
|
|
105
|
+
error_str = str(error)
|
|
106
|
+
assert "5678" in error_str
|
|
107
|
+
assert "Process is still running" in error_str
|
|
108
|
+
assert "Failed to cleanup process" in error_str
|
|
109
|
+
|
|
110
|
+
def test_repr(self):
|
|
111
|
+
"""Test __repr__ method."""
|
|
112
|
+
error = ProcessCleanupError(999, "Test message")
|
|
113
|
+
repr_str = repr(error)
|
|
114
|
+
assert "ProcessCleanupError" in repr_str
|
|
115
|
+
assert "999" in repr_str
|
|
116
|
+
assert "Test message" in repr_str
|
|
117
|
+
|
|
118
|
+
def test_inheritance(self):
|
|
119
|
+
"""Test inheritance from CommandExecutionError."""
|
|
120
|
+
error = ProcessCleanupError(123, "test")
|
|
121
|
+
assert isinstance(error, CommandExecutionError)
|
|
122
|
+
assert isinstance(error, Exception)
|
|
123
|
+
|
|
124
|
+
|
|
125
|
+
class TestProcessNotFoundError:
|
|
126
|
+
"""Test cases for ProcessNotFoundError."""
|
|
127
|
+
|
|
128
|
+
def test_basic_creation(self):
|
|
129
|
+
"""Test basic process not found error creation."""
|
|
130
|
+
error = ProcessNotFoundError(1234)
|
|
131
|
+
assert error.pid == 1234
|
|
132
|
+
assert "1234" in str(error)
|
|
133
|
+
assert "not found" in str(error).lower()
|
|
134
|
+
|
|
135
|
+
def test_repr(self):
|
|
136
|
+
"""Test __repr__ method."""
|
|
137
|
+
error = ProcessNotFoundError(999)
|
|
138
|
+
repr_str = repr(error)
|
|
139
|
+
assert "ProcessNotFoundError" in repr_str
|
|
140
|
+
assert "999" in repr_str
|
|
141
|
+
|
|
142
|
+
def test_inheritance(self):
|
|
143
|
+
"""Test inheritance from CommandExecutionError."""
|
|
144
|
+
error = ProcessNotFoundError(123)
|
|
145
|
+
assert isinstance(error, CommandExecutionError)
|
|
146
|
+
assert isinstance(error, Exception)
|
|
147
|
+
|
|
148
|
+
|
|
149
|
+
class TestTimeoutConfigError:
|
|
150
|
+
"""Test cases for TimeoutConfigError."""
|
|
151
|
+
|
|
152
|
+
def test_basic_creation(self):
|
|
153
|
+
"""Test basic timeout config error creation."""
|
|
154
|
+
error = TimeoutConfigError("default_timeout", -1, "Timeout must be positive")
|
|
155
|
+
assert error.config_field == "default_timeout"
|
|
156
|
+
assert error.value == -1
|
|
157
|
+
assert error.reason == "Timeout must be positive"
|
|
158
|
+
|
|
159
|
+
def test_string_representation(self):
|
|
160
|
+
"""Test string representation."""
|
|
161
|
+
error = TimeoutConfigError("max_timeout", "invalid", "Must be a number")
|
|
162
|
+
error_str = str(error)
|
|
163
|
+
assert "max_timeout" in error_str
|
|
164
|
+
assert "invalid" in error_str
|
|
165
|
+
assert "Must be a number" in error_str
|
|
166
|
+
|
|
167
|
+
def test_repr(self):
|
|
168
|
+
"""Test __repr__ method."""
|
|
169
|
+
error = TimeoutConfigError("test_field", 123, "test reason")
|
|
170
|
+
repr_str = repr(error)
|
|
171
|
+
assert "TimeoutConfigError" in repr_str
|
|
172
|
+
assert "test_field" in repr_str
|
|
173
|
+
assert "123" in repr_str
|
|
174
|
+
assert "test reason" in repr_str
|
|
175
|
+
|
|
176
|
+
def test_inheritance(self):
|
|
177
|
+
"""Test inheritance from CommandExecutionError."""
|
|
178
|
+
error = TimeoutConfigError("test", 1, "test")
|
|
179
|
+
assert isinstance(error, CommandExecutionError)
|
|
180
|
+
assert isinstance(error, Exception)
|
|
181
|
+
|
|
182
|
+
|
|
183
|
+
class TestErrorRecoveryFailedError:
|
|
184
|
+
"""Test cases for ErrorRecoveryFailedError."""
|
|
185
|
+
|
|
186
|
+
def test_basic_creation(self):
|
|
187
|
+
"""Test basic error recovery failed error creation."""
|
|
188
|
+
original_error = ValueError("Original error")
|
|
189
|
+
error = ErrorRecoveryFailedError(original_error, 3)
|
|
190
|
+
assert error.original_error is original_error
|
|
191
|
+
assert error.recovery_attempts == 3
|
|
192
|
+
assert "3 attempts" in str(error)
|
|
193
|
+
assert "Original error" in str(error)
|
|
194
|
+
|
|
195
|
+
def test_with_different_original_error(self):
|
|
196
|
+
"""Test with different types of original errors."""
|
|
197
|
+
original_error = CommandTimeoutError("test", 1.0, 123)
|
|
198
|
+
error = ErrorRecoveryFailedError(original_error, 5)
|
|
199
|
+
assert error.original_error is original_error
|
|
200
|
+
assert error.recovery_attempts == 5
|
|
201
|
+
assert "5 attempts" in str(error)
|
|
202
|
+
|
|
203
|
+
def test_repr(self):
|
|
204
|
+
"""Test __repr__ method."""
|
|
205
|
+
original_error = RuntimeError("Test error")
|
|
206
|
+
error = ErrorRecoveryFailedError(original_error, 2)
|
|
207
|
+
repr_str = repr(error)
|
|
208
|
+
assert "ErrorRecoveryFailedError" in repr_str
|
|
209
|
+
assert "2" in repr_str
|
|
210
|
+
|
|
211
|
+
def test_inheritance(self):
|
|
212
|
+
"""Test inheritance from CommandExecutionError."""
|
|
213
|
+
original_error = Exception("test")
|
|
214
|
+
error = ErrorRecoveryFailedError(original_error, 1)
|
|
215
|
+
assert isinstance(error, CommandExecutionError)
|
|
216
|
+
assert isinstance(error, Exception)
|
|
217
|
+
|
|
218
|
+
|
|
219
|
+
class TestExceptionInteraction:
|
|
220
|
+
"""Test cases for exception interaction and edge cases."""
|
|
221
|
+
|
|
222
|
+
def test_exception_chaining(self):
|
|
223
|
+
"""Test exception chaining scenarios."""
|
|
224
|
+
try:
|
|
225
|
+
raise CommandExecutionError("Original error")
|
|
226
|
+
except CommandExecutionError as e:
|
|
227
|
+
timeout_error = CommandTimeoutError("test", 1.0, 123)
|
|
228
|
+
timeout_error.__cause__ = e
|
|
229
|
+
assert timeout_error.__cause__ is e
|
|
230
|
+
|
|
231
|
+
def test_multiple_exception_types(self):
|
|
232
|
+
"""Test handling multiple exception types."""
|
|
233
|
+
exec_error = CommandExecutionError("Execution failed")
|
|
234
|
+
timeout_error = CommandTimeoutError("timeout test", 5.0, 456)
|
|
235
|
+
cleanup_error = ProcessCleanupError(789, "Cleanup failed")
|
|
236
|
+
|
|
237
|
+
errors = [exec_error, timeout_error, cleanup_error]
|
|
238
|
+
|
|
239
|
+
for error in errors:
|
|
240
|
+
assert isinstance(error, Exception)
|
|
241
|
+
|
|
242
|
+
# Test that all errors inherit from CommandExecutionError
|
|
243
|
+
for error in errors:
|
|
244
|
+
assert isinstance(error, CommandExecutionError)
|
|
245
|
+
|
|
246
|
+
def test_exception_with_none_values(self):
|
|
247
|
+
"""Test exceptions with None values."""
|
|
248
|
+
# Test CommandTimeoutError with None PID
|
|
249
|
+
error = CommandTimeoutError("test", 5.0, None)
|
|
250
|
+
assert error.command == "test"
|
|
251
|
+
assert error.timeout == 5.0
|
|
252
|
+
assert error.pid is None
|
|
253
|
+
|
|
254
|
+
# Should still be convertible to string
|
|
255
|
+
str_repr = str(error)
|
|
256
|
+
assert isinstance(str_repr, str)
|
|
257
|
+
assert "test" in str_repr
|
|
258
|
+
|
|
259
|
+
def test_exception_pickling(self):
|
|
260
|
+
"""Test that exceptions can be pickled (for multiprocessing)."""
|
|
261
|
+
import pickle
|
|
262
|
+
|
|
263
|
+
# Test basic exception pickling
|
|
264
|
+
error1 = CommandExecutionError("Test execution error")
|
|
265
|
+
pickled1 = pickle.dumps(error1)
|
|
266
|
+
unpickled1 = pickle.loads(pickled1)
|
|
267
|
+
assert str(unpickled1) == str(error1)
|
|
268
|
+
|
|
269
|
+
# Test that custom exceptions at least create proper string representations
|
|
270
|
+
timeout_error = CommandTimeoutError("test", 5.0, 123)
|
|
271
|
+
cleanup_error = ProcessCleanupError(456, "Test cleanup error")
|
|
272
|
+
|
|
273
|
+
# These should at least have proper string representations
|
|
274
|
+
assert str(timeout_error)
|
|
275
|
+
assert str(cleanup_error)
|
|
276
|
+
assert repr(timeout_error)
|
|
277
|
+
assert repr(cleanup_error)
|
|
278
|
+
|
|
279
|
+
# Note: Custom exceptions with complex __init__ may have pickling issues
|
|
280
|
+
# This is acceptable as they're primarily used for immediate error handling
|
|
281
|
+
|
|
282
|
+
def test_all_exceptions_are_command_execution_errors(self):
|
|
283
|
+
"""Test that all custom exceptions inherit from CommandExecutionError."""
|
|
284
|
+
exceptions = [
|
|
285
|
+
CommandExecutionError("test"),
|
|
286
|
+
CommandTimeoutError("test", 1.0, 123),
|
|
287
|
+
ProcessCleanupError(123, "test"),
|
|
288
|
+
ProcessNotFoundError(456),
|
|
289
|
+
TimeoutConfigError("test", "value", "reason"),
|
|
290
|
+
ErrorRecoveryFailedError(Exception("test"), 1)
|
|
291
|
+
]
|
|
292
|
+
|
|
293
|
+
for exc in exceptions:
|
|
294
|
+
assert isinstance(exc, CommandExecutionError)
|
|
295
|
+
assert isinstance(exc, Exception)
|
|
296
|
+
|
|
297
|
+
|
|
298
|
+
if __name__ == "__main__":
|
|
299
|
+
pytest.main([__file__, "-v"])
|