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,315 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Timeout configuration module for shell command execution.
|
|
3
|
+
|
|
4
|
+
This module provides flexible timeout configuration for different types of commands
|
|
5
|
+
and execution scenarios.
|
|
6
|
+
"""
|
|
7
|
+
|
|
8
|
+
import os
|
|
9
|
+
import re
|
|
10
|
+
from dataclasses import dataclass, field
|
|
11
|
+
from typing import Dict, Optional, Union, List
|
|
12
|
+
|
|
13
|
+
from .exceptions import TimeoutConfigError
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
@dataclass
|
|
17
|
+
class TimeoutConfig:
|
|
18
|
+
"""
|
|
19
|
+
Configuration class for command timeout settings.
|
|
20
|
+
|
|
21
|
+
This class provides comprehensive timeout configuration including:
|
|
22
|
+
- Default timeout for all commands
|
|
23
|
+
- Interactive command timeout
|
|
24
|
+
- Process cleanup timeout
|
|
25
|
+
- Grace period for graceful termination
|
|
26
|
+
- Command-specific timeout overrides
|
|
27
|
+
|
|
28
|
+
Attributes:
|
|
29
|
+
default_timeout: Default timeout for all commands (seconds)
|
|
30
|
+
interactive_timeout: Timeout for interactive commands (seconds)
|
|
31
|
+
cleanup_timeout: Timeout for process cleanup operations (seconds)
|
|
32
|
+
grace_period: Grace period for graceful process termination (seconds)
|
|
33
|
+
command_timeouts: Dictionary mapping command patterns to specific timeouts
|
|
34
|
+
"""
|
|
35
|
+
|
|
36
|
+
default_timeout: Optional[float] = 300.0 # 5 minutes
|
|
37
|
+
interactive_timeout: Optional[float] = 600.0 # 10 minutes
|
|
38
|
+
cleanup_timeout: float = 10.0 # 10 seconds
|
|
39
|
+
grace_period: float = 5.0 # 5 seconds
|
|
40
|
+
|
|
41
|
+
# Command-specific timeout overrides
|
|
42
|
+
command_timeouts: Dict[str, float] = field(default_factory=dict)
|
|
43
|
+
|
|
44
|
+
def __post_init__(self):
|
|
45
|
+
"""Validate configuration after initialization."""
|
|
46
|
+
self._validate_config()
|
|
47
|
+
|
|
48
|
+
def _validate_config(self):
|
|
49
|
+
"""Validate timeout configuration values."""
|
|
50
|
+
|
|
51
|
+
# Validate default_timeout
|
|
52
|
+
if self.default_timeout is not None and self.default_timeout <= 0:
|
|
53
|
+
raise TimeoutConfigError(
|
|
54
|
+
"default_timeout",
|
|
55
|
+
self.default_timeout,
|
|
56
|
+
"must be positive or None"
|
|
57
|
+
)
|
|
58
|
+
|
|
59
|
+
# Validate interactive_timeout
|
|
60
|
+
if self.interactive_timeout is not None and self.interactive_timeout <= 0:
|
|
61
|
+
raise TimeoutConfigError(
|
|
62
|
+
"interactive_timeout",
|
|
63
|
+
self.interactive_timeout,
|
|
64
|
+
"must be positive or None"
|
|
65
|
+
)
|
|
66
|
+
|
|
67
|
+
# Validate cleanup_timeout
|
|
68
|
+
if self.cleanup_timeout <= 0:
|
|
69
|
+
raise TimeoutConfigError(
|
|
70
|
+
"cleanup_timeout",
|
|
71
|
+
self.cleanup_timeout,
|
|
72
|
+
"must be positive"
|
|
73
|
+
)
|
|
74
|
+
|
|
75
|
+
# Validate grace_period
|
|
76
|
+
if self.grace_period <= 0:
|
|
77
|
+
raise TimeoutConfigError(
|
|
78
|
+
"grace_period",
|
|
79
|
+
self.grace_period,
|
|
80
|
+
"must be positive"
|
|
81
|
+
)
|
|
82
|
+
|
|
83
|
+
# Validate command_timeouts
|
|
84
|
+
for command, timeout in self.command_timeouts.items():
|
|
85
|
+
if timeout <= 0:
|
|
86
|
+
raise TimeoutConfigError(
|
|
87
|
+
f"command_timeouts[{command}]",
|
|
88
|
+
timeout,
|
|
89
|
+
"must be positive"
|
|
90
|
+
)
|
|
91
|
+
|
|
92
|
+
def get_timeout_for_command(self, command: Union[str, List[str]]) -> Optional[float]:
|
|
93
|
+
"""
|
|
94
|
+
Get the appropriate timeout for a specific command.
|
|
95
|
+
|
|
96
|
+
This method checks for command-specific timeouts first, then falls back
|
|
97
|
+
to the default timeout.
|
|
98
|
+
|
|
99
|
+
Args:
|
|
100
|
+
command: The command string or list to get timeout for
|
|
101
|
+
|
|
102
|
+
Returns:
|
|
103
|
+
Timeout in seconds, or None for no timeout
|
|
104
|
+
"""
|
|
105
|
+
# Convert command to string if needed
|
|
106
|
+
if isinstance(command, list):
|
|
107
|
+
if not command:
|
|
108
|
+
return self.default_timeout
|
|
109
|
+
command_str = " ".join(str(arg) for arg in command)
|
|
110
|
+
else:
|
|
111
|
+
command_str = command
|
|
112
|
+
|
|
113
|
+
if not command_str:
|
|
114
|
+
return self.default_timeout
|
|
115
|
+
|
|
116
|
+
# Extract the base command (first word)
|
|
117
|
+
base_command = command_str.strip().split()[0] if command_str.strip() else ""
|
|
118
|
+
command_parts = command_str.strip().split()
|
|
119
|
+
is_single_command = len(command_parts) == 1
|
|
120
|
+
|
|
121
|
+
# Check for pattern matches - prioritize patterns that match from the beginning
|
|
122
|
+
# Sort patterns by specificity: exact matches first for single commands, then patterns, then exact for multi-word
|
|
123
|
+
def pattern_priority(item):
|
|
124
|
+
pattern, _ = item
|
|
125
|
+
# For single-word commands, exact matches get highest priority
|
|
126
|
+
# For multi-word commands, patterns get higher priority than base command exact matches
|
|
127
|
+
is_exact = pattern == base_command
|
|
128
|
+
is_pattern = '*' in pattern
|
|
129
|
+
# Patterns starting with text (not *) get higher priority than wildcards
|
|
130
|
+
starts_with_text = not pattern.startswith('*')
|
|
131
|
+
# Longer patterns get higher priority within same category
|
|
132
|
+
length = len(pattern)
|
|
133
|
+
|
|
134
|
+
if is_single_command:
|
|
135
|
+
# Single command: exact > patterns
|
|
136
|
+
return (is_exact, not is_pattern, starts_with_text, length)
|
|
137
|
+
else:
|
|
138
|
+
# Multi-word command: patterns > exact base command
|
|
139
|
+
return (not is_exact or is_pattern, starts_with_text, length)
|
|
140
|
+
|
|
141
|
+
patterns = sorted(self.command_timeouts.items(), key=pattern_priority, reverse=True)
|
|
142
|
+
|
|
143
|
+
for pattern, timeout in patterns:
|
|
144
|
+
# For exact matches, check base command
|
|
145
|
+
if pattern == base_command and ('*' not in pattern):
|
|
146
|
+
# For multi-word commands, only return exact match if no patterns match
|
|
147
|
+
if is_single_command:
|
|
148
|
+
return timeout
|
|
149
|
+
# For multi-word, continue to check patterns first
|
|
150
|
+
# For patterns, check full command string
|
|
151
|
+
if self._matches_pattern(command_str, pattern):
|
|
152
|
+
return timeout
|
|
153
|
+
|
|
154
|
+
# If we get here and it's a multi-word command, check for exact base command match
|
|
155
|
+
if not is_single_command and base_command in self.command_timeouts:
|
|
156
|
+
pattern = base_command
|
|
157
|
+
if '*' not in pattern: # Make sure it's not a pattern
|
|
158
|
+
return self.command_timeouts[base_command]
|
|
159
|
+
|
|
160
|
+
# Fall back to default timeout
|
|
161
|
+
return self.default_timeout
|
|
162
|
+
|
|
163
|
+
def _matches_pattern(self, command: str, pattern: str) -> bool:
|
|
164
|
+
"""
|
|
165
|
+
Check if a command matches a timeout pattern.
|
|
166
|
+
|
|
167
|
+
Args:
|
|
168
|
+
command: The command to check
|
|
169
|
+
pattern: The pattern to match against
|
|
170
|
+
|
|
171
|
+
Returns:
|
|
172
|
+
True if the command matches the pattern
|
|
173
|
+
"""
|
|
174
|
+
# Support simple wildcard patterns
|
|
175
|
+
if '*' in pattern:
|
|
176
|
+
# Convert simple wildcard to regex
|
|
177
|
+
regex_pattern = pattern.replace('*', '.*')
|
|
178
|
+
return bool(re.match(regex_pattern, command))
|
|
179
|
+
|
|
180
|
+
# Support exact substring matching
|
|
181
|
+
return pattern in command
|
|
182
|
+
|
|
183
|
+
def set_command_timeout(self, command_pattern: str, timeout: float):
|
|
184
|
+
"""
|
|
185
|
+
Set timeout for a specific command pattern.
|
|
186
|
+
|
|
187
|
+
Args:
|
|
188
|
+
command_pattern: Command or pattern to set timeout for
|
|
189
|
+
timeout: Timeout value in seconds
|
|
190
|
+
|
|
191
|
+
Raises:
|
|
192
|
+
TimeoutConfigError: If timeout value is invalid
|
|
193
|
+
"""
|
|
194
|
+
if timeout <= 0:
|
|
195
|
+
raise TimeoutConfigError(
|
|
196
|
+
f"command_timeouts[{command_pattern}]",
|
|
197
|
+
timeout,
|
|
198
|
+
"must be positive"
|
|
199
|
+
)
|
|
200
|
+
|
|
201
|
+
self.command_timeouts[command_pattern] = timeout
|
|
202
|
+
|
|
203
|
+
def remove_command_timeout(self, command_pattern: str):
|
|
204
|
+
"""
|
|
205
|
+
Remove timeout override for a command pattern.
|
|
206
|
+
|
|
207
|
+
Args:
|
|
208
|
+
command_pattern: Command pattern to remove
|
|
209
|
+
"""
|
|
210
|
+
self.command_timeouts.pop(command_pattern, None)
|
|
211
|
+
|
|
212
|
+
@classmethod
|
|
213
|
+
def from_env(cls) -> 'TimeoutConfig':
|
|
214
|
+
"""
|
|
215
|
+
Create TimeoutConfig from environment variables.
|
|
216
|
+
|
|
217
|
+
Environment variables:
|
|
218
|
+
AUTOCODER_DEFAULT_TIMEOUT: Default timeout in seconds
|
|
219
|
+
AUTOCODER_INTERACTIVE_TIMEOUT: Interactive timeout in seconds
|
|
220
|
+
AUTOCODER_CLEANUP_TIMEOUT: Cleanup timeout in seconds
|
|
221
|
+
AUTOCODER_GRACE_PERIOD: Grace period in seconds
|
|
222
|
+
|
|
223
|
+
Returns:
|
|
224
|
+
TimeoutConfig instance configured from environment
|
|
225
|
+
"""
|
|
226
|
+
def get_optional_float(env_var: str, default: Optional[float]) -> Optional[float]:
|
|
227
|
+
value = os.getenv(env_var)
|
|
228
|
+
if value is None:
|
|
229
|
+
return default
|
|
230
|
+
if value.lower() in ('none', 'null', ''):
|
|
231
|
+
return None
|
|
232
|
+
try:
|
|
233
|
+
return float(value)
|
|
234
|
+
except ValueError:
|
|
235
|
+
raise TimeoutConfigError(
|
|
236
|
+
env_var,
|
|
237
|
+
value,
|
|
238
|
+
"must be a valid number or 'none'"
|
|
239
|
+
)
|
|
240
|
+
|
|
241
|
+
def get_float(env_var: str, default: float) -> float:
|
|
242
|
+
value = os.getenv(env_var)
|
|
243
|
+
if value is None:
|
|
244
|
+
return default
|
|
245
|
+
try:
|
|
246
|
+
return float(value)
|
|
247
|
+
except ValueError:
|
|
248
|
+
raise TimeoutConfigError(
|
|
249
|
+
env_var,
|
|
250
|
+
value,
|
|
251
|
+
"must be a valid number"
|
|
252
|
+
)
|
|
253
|
+
|
|
254
|
+
return cls(
|
|
255
|
+
default_timeout=get_optional_float('AUTOCODER_DEFAULT_TIMEOUT', 300.0),
|
|
256
|
+
interactive_timeout=get_optional_float('AUTOCODER_INTERACTIVE_TIMEOUT', 600.0),
|
|
257
|
+
cleanup_timeout=get_float('AUTOCODER_CLEANUP_TIMEOUT', 10.0),
|
|
258
|
+
grace_period=get_float('AUTOCODER_GRACE_PERIOD', 5.0),
|
|
259
|
+
)
|
|
260
|
+
|
|
261
|
+
def to_dict(self) -> Dict:
|
|
262
|
+
"""
|
|
263
|
+
Convert configuration to dictionary.
|
|
264
|
+
|
|
265
|
+
Returns:
|
|
266
|
+
Dictionary representation of the configuration
|
|
267
|
+
"""
|
|
268
|
+
return {
|
|
269
|
+
'default_timeout': self.default_timeout,
|
|
270
|
+
'interactive_timeout': self.interactive_timeout,
|
|
271
|
+
'cleanup_timeout': self.cleanup_timeout,
|
|
272
|
+
'grace_period': self.grace_period,
|
|
273
|
+
'command_timeouts': self.command_timeouts.copy(),
|
|
274
|
+
}
|
|
275
|
+
|
|
276
|
+
@classmethod
|
|
277
|
+
def from_dict(cls, config_dict: Dict) -> 'TimeoutConfig':
|
|
278
|
+
"""
|
|
279
|
+
Create TimeoutConfig from dictionary.
|
|
280
|
+
|
|
281
|
+
Args:
|
|
282
|
+
config_dict: Dictionary containing configuration values
|
|
283
|
+
|
|
284
|
+
Returns:
|
|
285
|
+
TimeoutConfig instance
|
|
286
|
+
"""
|
|
287
|
+
return cls(
|
|
288
|
+
default_timeout=config_dict.get('default_timeout', 300.0),
|
|
289
|
+
interactive_timeout=config_dict.get('interactive_timeout', 600.0),
|
|
290
|
+
cleanup_timeout=config_dict.get('cleanup_timeout', 10.0),
|
|
291
|
+
grace_period=config_dict.get('grace_period', 5.0),
|
|
292
|
+
command_timeouts=config_dict.get('command_timeouts', {}),
|
|
293
|
+
)
|
|
294
|
+
|
|
295
|
+
def __str__(self) -> str:
|
|
296
|
+
"""String representation of the configuration."""
|
|
297
|
+
return (
|
|
298
|
+
f"TimeoutConfig("
|
|
299
|
+
f"default={self.default_timeout}, "
|
|
300
|
+
f"interactive={self.interactive_timeout}, "
|
|
301
|
+
f"cleanup={self.cleanup_timeout}, "
|
|
302
|
+
f"grace={self.grace_period}, "
|
|
303
|
+
f"overrides={len(self.command_timeouts)})"
|
|
304
|
+
)
|
|
305
|
+
|
|
306
|
+
def __repr__(self) -> str:
|
|
307
|
+
"""Detailed string representation."""
|
|
308
|
+
return (
|
|
309
|
+
f"TimeoutConfig("
|
|
310
|
+
f"default_timeout={self.default_timeout}, "
|
|
311
|
+
f"interactive_timeout={self.interactive_timeout}, "
|
|
312
|
+
f"cleanup_timeout={self.cleanup_timeout}, "
|
|
313
|
+
f"grace_period={self.grace_period}, "
|
|
314
|
+
f"command_timeouts={self.command_timeouts})"
|
|
315
|
+
)
|
|
@@ -0,0 +1,352 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Timeout manager module for shell command execution.
|
|
3
|
+
|
|
4
|
+
This module provides timeout management functionality including:
|
|
5
|
+
- Starting and canceling timeouts
|
|
6
|
+
- Handling timeout events
|
|
7
|
+
- Managing multiple concurrent timeouts
|
|
8
|
+
- Integration with process cleanup
|
|
9
|
+
"""
|
|
10
|
+
|
|
11
|
+
import subprocess
|
|
12
|
+
import threading
|
|
13
|
+
import time
|
|
14
|
+
from typing import Dict, Optional, Callable
|
|
15
|
+
from loguru import logger
|
|
16
|
+
|
|
17
|
+
from .timeout_config import TimeoutConfig
|
|
18
|
+
from .process_cleanup import cleanup_process_tree
|
|
19
|
+
from .exceptions import CommandTimeoutError
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
class TimeoutManager:
|
|
23
|
+
"""
|
|
24
|
+
Manager for command execution timeouts.
|
|
25
|
+
|
|
26
|
+
This class handles timeout management for command execution, including
|
|
27
|
+
starting timers, canceling them, and handling timeout events with
|
|
28
|
+
proper process cleanup.
|
|
29
|
+
|
|
30
|
+
Attributes:
|
|
31
|
+
config: Timeout configuration
|
|
32
|
+
active_timers: Dictionary of active timeout timers
|
|
33
|
+
timeout_callbacks: Dictionary of timeout callbacks
|
|
34
|
+
"""
|
|
35
|
+
|
|
36
|
+
def __init__(self, config: TimeoutConfig):
|
|
37
|
+
"""
|
|
38
|
+
Initialize timeout manager.
|
|
39
|
+
|
|
40
|
+
Args:
|
|
41
|
+
config: Timeout configuration to use
|
|
42
|
+
"""
|
|
43
|
+
self.config = config
|
|
44
|
+
self.active_timers: Dict[int, threading.Timer] = {}
|
|
45
|
+
self.timeout_callbacks: Dict[int, Callable] = {}
|
|
46
|
+
self._lock = threading.Lock()
|
|
47
|
+
|
|
48
|
+
logger.debug(f"TimeoutManager initialized with config: {config}")
|
|
49
|
+
|
|
50
|
+
def start_timeout(
|
|
51
|
+
self,
|
|
52
|
+
process: subprocess.Popen,
|
|
53
|
+
timeout: float,
|
|
54
|
+
callback: Optional[Callable] = None
|
|
55
|
+
) -> None:
|
|
56
|
+
"""
|
|
57
|
+
Start a timeout for a process.
|
|
58
|
+
|
|
59
|
+
Args:
|
|
60
|
+
process: The subprocess.Popen object to monitor
|
|
61
|
+
timeout: Timeout duration in seconds
|
|
62
|
+
callback: Optional callback to call on timeout (in addition to cleanup)
|
|
63
|
+
"""
|
|
64
|
+
if timeout <= 0:
|
|
65
|
+
logger.warning(f"Invalid timeout value: {timeout}, ignoring")
|
|
66
|
+
return
|
|
67
|
+
|
|
68
|
+
pid = process.pid
|
|
69
|
+
|
|
70
|
+
with self._lock:
|
|
71
|
+
# Cancel any existing timeout for this process (without acquiring lock again)
|
|
72
|
+
existing_timer = self.active_timers.pop(pid, None)
|
|
73
|
+
existing_callback = self.timeout_callbacks.pop(pid, None)
|
|
74
|
+
|
|
75
|
+
if existing_timer:
|
|
76
|
+
existing_timer.cancel()
|
|
77
|
+
logger.debug(f"Canceled existing timeout for PID {pid}")
|
|
78
|
+
|
|
79
|
+
# Create timeout handler
|
|
80
|
+
def timeout_handler():
|
|
81
|
+
self._handle_timeout(process, timeout, callback)
|
|
82
|
+
|
|
83
|
+
# Start timer
|
|
84
|
+
timer = threading.Timer(timeout, timeout_handler)
|
|
85
|
+
timer.daemon = True # Don't prevent program exit
|
|
86
|
+
|
|
87
|
+
try:
|
|
88
|
+
timer.start()
|
|
89
|
+
|
|
90
|
+
# Store timer and callback only if start was successful
|
|
91
|
+
self.active_timers[pid] = timer
|
|
92
|
+
if callback:
|
|
93
|
+
self.timeout_callbacks[pid] = callback
|
|
94
|
+
|
|
95
|
+
logger.debug(f"Started timeout for PID {pid} with {timeout}s timeout")
|
|
96
|
+
|
|
97
|
+
except Exception as e:
|
|
98
|
+
logger.error(f"Failed to start timeout for PID {pid}: {e}")
|
|
99
|
+
# Don't store the timer since it failed to start
|
|
100
|
+
|
|
101
|
+
def cancel_timeout(self, process: subprocess.Popen) -> bool:
|
|
102
|
+
"""
|
|
103
|
+
Cancel timeout for a process.
|
|
104
|
+
|
|
105
|
+
Args:
|
|
106
|
+
process: The subprocess.Popen object
|
|
107
|
+
|
|
108
|
+
Returns:
|
|
109
|
+
True if timeout was canceled, False if no timeout was active
|
|
110
|
+
"""
|
|
111
|
+
pid = process.pid
|
|
112
|
+
|
|
113
|
+
with self._lock:
|
|
114
|
+
timer = self.active_timers.pop(pid, None)
|
|
115
|
+
callback = self.timeout_callbacks.pop(pid, None)
|
|
116
|
+
|
|
117
|
+
if timer:
|
|
118
|
+
timer.cancel()
|
|
119
|
+
logger.debug(f"Canceled timeout for PID {pid}")
|
|
120
|
+
return True
|
|
121
|
+
|
|
122
|
+
return False
|
|
123
|
+
|
|
124
|
+
def is_timeout_active(self, process: subprocess.Popen) -> bool:
|
|
125
|
+
"""
|
|
126
|
+
Check if timeout is active for a process.
|
|
127
|
+
|
|
128
|
+
Args:
|
|
129
|
+
process: The subprocess.Popen object
|
|
130
|
+
|
|
131
|
+
Returns:
|
|
132
|
+
True if timeout is active
|
|
133
|
+
"""
|
|
134
|
+
pid = process.pid
|
|
135
|
+
with self._lock:
|
|
136
|
+
return pid in self.active_timers
|
|
137
|
+
|
|
138
|
+
def get_remaining_timeout(self, process: subprocess.Popen) -> Optional[float]:
|
|
139
|
+
"""
|
|
140
|
+
Get remaining timeout for a process.
|
|
141
|
+
|
|
142
|
+
Args:
|
|
143
|
+
process: The subprocess.Popen object
|
|
144
|
+
|
|
145
|
+
Returns:
|
|
146
|
+
Remaining timeout in seconds, or None if no timeout active
|
|
147
|
+
"""
|
|
148
|
+
pid = process.pid
|
|
149
|
+
with self._lock:
|
|
150
|
+
timer = self.active_timers.get(pid)
|
|
151
|
+
if timer and timer.is_alive():
|
|
152
|
+
# This is an approximation since Timer doesn't expose remaining time
|
|
153
|
+
# In practice, this would need more sophisticated tracking
|
|
154
|
+
return None # Could implement if needed
|
|
155
|
+
return None
|
|
156
|
+
|
|
157
|
+
def _handle_timeout(
|
|
158
|
+
self,
|
|
159
|
+
process: subprocess.Popen,
|
|
160
|
+
timeout: float,
|
|
161
|
+
callback: Optional[Callable] = None
|
|
162
|
+
) -> None:
|
|
163
|
+
"""
|
|
164
|
+
Handle timeout event for a process.
|
|
165
|
+
|
|
166
|
+
Args:
|
|
167
|
+
process: The subprocess.Popen object that timed out
|
|
168
|
+
timeout: The timeout value that was exceeded
|
|
169
|
+
callback: Optional user callback to execute
|
|
170
|
+
"""
|
|
171
|
+
pid = process.pid
|
|
172
|
+
|
|
173
|
+
logger.warning(f"Process {pid} timed out after {timeout} seconds")
|
|
174
|
+
|
|
175
|
+
try:
|
|
176
|
+
# Remove from active timers
|
|
177
|
+
with self._lock:
|
|
178
|
+
self.active_timers.pop(pid, None)
|
|
179
|
+
self.timeout_callbacks.pop(pid, None)
|
|
180
|
+
|
|
181
|
+
# Execute user callback if provided
|
|
182
|
+
if callback:
|
|
183
|
+
try:
|
|
184
|
+
callback(process, timeout)
|
|
185
|
+
except Exception as e:
|
|
186
|
+
logger.error(f"Error in timeout callback for PID {pid}: {e}")
|
|
187
|
+
|
|
188
|
+
# Attempt to cleanup the process tree
|
|
189
|
+
try:
|
|
190
|
+
cleanup_success = cleanup_process_tree(
|
|
191
|
+
pid,
|
|
192
|
+
timeout=self.config.grace_period,
|
|
193
|
+
force_timeout=self.config.cleanup_timeout - self.config.grace_period
|
|
194
|
+
)
|
|
195
|
+
|
|
196
|
+
if cleanup_success:
|
|
197
|
+
logger.debug(f"Successfully cleaned up process tree for PID {pid}")
|
|
198
|
+
else:
|
|
199
|
+
logger.warning(f"Failed to fully cleanup process tree for PID {pid}")
|
|
200
|
+
|
|
201
|
+
except Exception as e:
|
|
202
|
+
logger.error(f"Error during process cleanup for PID {pid}: {e}")
|
|
203
|
+
|
|
204
|
+
except Exception as e:
|
|
205
|
+
logger.error(f"Error handling timeout for PID {pid}: {e}")
|
|
206
|
+
|
|
207
|
+
def cleanup_all_timeouts(self) -> None:
|
|
208
|
+
"""
|
|
209
|
+
Cancel all active timeouts.
|
|
210
|
+
|
|
211
|
+
This method should be called when shutting down to ensure
|
|
212
|
+
all timers are properly canceled.
|
|
213
|
+
"""
|
|
214
|
+
with self._lock:
|
|
215
|
+
for pid, timer in self.active_timers.items():
|
|
216
|
+
try:
|
|
217
|
+
timer.cancel()
|
|
218
|
+
logger.debug(f"Canceled timeout for PID {pid} during cleanup")
|
|
219
|
+
except Exception as e:
|
|
220
|
+
logger.error(f"Error canceling timeout for PID {pid}: {e}")
|
|
221
|
+
|
|
222
|
+
self.active_timers.clear()
|
|
223
|
+
self.timeout_callbacks.clear()
|
|
224
|
+
|
|
225
|
+
logger.debug("All timeouts cleaned up")
|
|
226
|
+
|
|
227
|
+
def get_active_timeouts(self) -> Dict[int, bool]:
|
|
228
|
+
"""
|
|
229
|
+
Get information about active timeouts.
|
|
230
|
+
|
|
231
|
+
Returns:
|
|
232
|
+
Dictionary mapping PID to timer status (alive/dead)
|
|
233
|
+
"""
|
|
234
|
+
with self._lock:
|
|
235
|
+
return {
|
|
236
|
+
pid: timer.is_alive()
|
|
237
|
+
for pid, timer in self.active_timers.items()
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
def __del__(self):
|
|
241
|
+
"""Cleanup when manager is destroyed."""
|
|
242
|
+
try:
|
|
243
|
+
self.cleanup_all_timeouts()
|
|
244
|
+
except Exception:
|
|
245
|
+
pass # Ignore errors during cleanup
|
|
246
|
+
|
|
247
|
+
|
|
248
|
+
class TimeoutContext:
|
|
249
|
+
"""
|
|
250
|
+
Context manager for timeout management.
|
|
251
|
+
|
|
252
|
+
This provides a convenient way to manage timeouts using the 'with' statement.
|
|
253
|
+
The timeout is automatically canceled when exiting the context.
|
|
254
|
+
"""
|
|
255
|
+
|
|
256
|
+
def __init__(
|
|
257
|
+
self,
|
|
258
|
+
manager: TimeoutManager,
|
|
259
|
+
process: subprocess.Popen,
|
|
260
|
+
timeout: float,
|
|
261
|
+
callback: Optional[Callable] = None
|
|
262
|
+
):
|
|
263
|
+
"""
|
|
264
|
+
Initialize timeout context.
|
|
265
|
+
|
|
266
|
+
Args:
|
|
267
|
+
manager: TimeoutManager instance
|
|
268
|
+
process: Process to monitor
|
|
269
|
+
timeout: Timeout duration
|
|
270
|
+
callback: Optional timeout callback
|
|
271
|
+
"""
|
|
272
|
+
self.manager = manager
|
|
273
|
+
self.process = process
|
|
274
|
+
self.timeout = timeout
|
|
275
|
+
self.callback = callback
|
|
276
|
+
|
|
277
|
+
def __enter__(self) -> 'TimeoutContext':
|
|
278
|
+
"""Start timeout when entering context."""
|
|
279
|
+
self.manager.start_timeout(self.process, self.timeout, self.callback)
|
|
280
|
+
return self
|
|
281
|
+
|
|
282
|
+
def __exit__(self, exc_type, exc_val, exc_tb) -> None:
|
|
283
|
+
"""Cancel timeout when exiting context."""
|
|
284
|
+
self.manager.cancel_timeout(self.process)
|
|
285
|
+
|
|
286
|
+
|
|
287
|
+
class GlobalTimeoutManager:
|
|
288
|
+
"""
|
|
289
|
+
Global singleton timeout manager.
|
|
290
|
+
|
|
291
|
+
This provides a convenient way to access a global timeout manager
|
|
292
|
+
throughout the application.
|
|
293
|
+
"""
|
|
294
|
+
|
|
295
|
+
_instance: Optional[TimeoutManager] = None
|
|
296
|
+
_lock = threading.Lock()
|
|
297
|
+
|
|
298
|
+
@classmethod
|
|
299
|
+
def get_instance(cls, config: Optional[TimeoutConfig] = None) -> TimeoutManager:
|
|
300
|
+
"""
|
|
301
|
+
Get or create the global timeout manager instance.
|
|
302
|
+
|
|
303
|
+
Args:
|
|
304
|
+
config: Optional config to use for first initialization
|
|
305
|
+
|
|
306
|
+
Returns:
|
|
307
|
+
Global TimeoutManager instance
|
|
308
|
+
"""
|
|
309
|
+
if cls._instance is None:
|
|
310
|
+
with cls._lock:
|
|
311
|
+
if cls._instance is None:
|
|
312
|
+
if config is None:
|
|
313
|
+
config = TimeoutConfig()
|
|
314
|
+
cls._instance = TimeoutManager(config)
|
|
315
|
+
logger.debug("Created global TimeoutManager instance")
|
|
316
|
+
|
|
317
|
+
return cls._instance
|
|
318
|
+
|
|
319
|
+
@classmethod
|
|
320
|
+
def reset_instance(cls) -> None:
|
|
321
|
+
"""
|
|
322
|
+
Reset the global instance.
|
|
323
|
+
|
|
324
|
+
This is mainly useful for testing.
|
|
325
|
+
"""
|
|
326
|
+
with cls._lock:
|
|
327
|
+
if cls._instance:
|
|
328
|
+
cls._instance.cleanup_all_timeouts()
|
|
329
|
+
cls._instance = None
|
|
330
|
+
logger.debug("Reset global TimeoutManager instance")
|
|
331
|
+
|
|
332
|
+
|
|
333
|
+
def create_timeout_context(
|
|
334
|
+
process: subprocess.Popen,
|
|
335
|
+
timeout: float,
|
|
336
|
+
config: Optional[TimeoutConfig] = None,
|
|
337
|
+
callback: Optional[Callable] = None
|
|
338
|
+
) -> TimeoutContext:
|
|
339
|
+
"""
|
|
340
|
+
Convenience function to create a timeout context.
|
|
341
|
+
|
|
342
|
+
Args:
|
|
343
|
+
process: Process to monitor
|
|
344
|
+
timeout: Timeout duration
|
|
345
|
+
config: Optional timeout configuration
|
|
346
|
+
callback: Optional timeout callback
|
|
347
|
+
|
|
348
|
+
Returns:
|
|
349
|
+
TimeoutContext instance
|
|
350
|
+
"""
|
|
351
|
+
manager = GlobalTimeoutManager.get_instance(config)
|
|
352
|
+
return TimeoutContext(manager, process, timeout, callback)
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
"""Terminal paste handling module for auto-coder.
|
|
2
|
+
|
|
3
|
+
This module provides functionality to intercept terminal paste events,
|
|
4
|
+
save pasted content to files, and resolve placeholders in user input.
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
from .paste_handler import register_paste_handler, resolve_paste_placeholders
|
|
8
|
+
from .paste_manager import PasteManager
|
|
9
|
+
|
|
10
|
+
__all__ = [
|
|
11
|
+
"register_paste_handler",
|
|
12
|
+
"resolve_paste_placeholders",
|
|
13
|
+
"PasteManager"
|
|
14
|
+
]
|