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
|
@@ -1,35 +1,202 @@
|
|
|
1
1
|
import subprocess
|
|
2
2
|
import os
|
|
3
|
+
import time
|
|
4
|
+
import uuid
|
|
3
5
|
from typing import Dict, Any, Optional
|
|
4
6
|
from autocoder.common.run_cmd import run_cmd_subprocess
|
|
7
|
+
from autocoder.common.autocoderargs_parser import AutoCoderArgsParser
|
|
5
8
|
from autocoder.common.v2.agent.agentic_edit_tools.base_tool_resolver import BaseToolResolver
|
|
6
|
-
|
|
9
|
+
# Import ToolResult from types
|
|
10
|
+
from autocoder.common.v2.agent.agentic_edit_types import ExecuteCommandTool, ToolResult
|
|
7
11
|
from autocoder.common.v2.agent.agentic_edit_tools.dangerous_command_checker import DangerousCommandChecker
|
|
8
12
|
from autocoder.common import shells
|
|
9
13
|
from autocoder.common.printer import Printer
|
|
10
14
|
from loguru import logger
|
|
11
|
-
import typing
|
|
12
|
-
from autocoder.common.context_pruner import PruneContext
|
|
13
|
-
from autocoder.
|
|
15
|
+
import typing
|
|
16
|
+
from autocoder.common.pruner.context_pruner import PruneContext
|
|
17
|
+
from autocoder.common.tokens import count_string_tokens as count_tokens
|
|
14
18
|
from autocoder.common import SourceCode
|
|
15
19
|
from autocoder.common import AutoCoderArgs
|
|
16
20
|
from autocoder.events.event_manager_singleton import get_event_manager
|
|
17
21
|
from autocoder.run_context import get_run_context
|
|
22
|
+
from autocoder.common.shell_commands import (
|
|
23
|
+
execute_command,
|
|
24
|
+
execute_command_background,
|
|
25
|
+
execute_commands,
|
|
26
|
+
CommandTimeoutError,
|
|
27
|
+
CommandExecutionError
|
|
28
|
+
)
|
|
29
|
+
from autocoder.common.shell_commands import get_background_process_notifier
|
|
30
|
+
from autocoder.common.wrap_llm_hint.utils import add_hint_to_text
|
|
31
|
+
import shlex
|
|
32
|
+
import json
|
|
33
|
+
import yaml
|
|
34
|
+
from typing import List, Union
|
|
35
|
+
import textwrap
|
|
36
|
+
from pydantic import BaseModel
|
|
37
|
+
from datetime import datetime
|
|
38
|
+
|
|
18
39
|
if typing.TYPE_CHECKING:
|
|
19
40
|
from autocoder.common.v2.agent.agentic_edit import AgenticEdit
|
|
20
41
|
|
|
42
|
+
|
|
43
|
+
class BackgroundCommandInfo(BaseModel):
|
|
44
|
+
"""Information about a background command execution."""
|
|
45
|
+
model_config = {"frozen": True, "extra": "forbid"}
|
|
46
|
+
|
|
47
|
+
pid: int
|
|
48
|
+
process_uniq_id: str
|
|
49
|
+
command: str
|
|
50
|
+
working_directory: str
|
|
51
|
+
background: bool = True
|
|
52
|
+
start_time: Optional[str] = None
|
|
53
|
+
status: str = "running"
|
|
54
|
+
|
|
55
|
+
|
|
56
|
+
class CommandErrorInfo(BaseModel):
|
|
57
|
+
"""Information about a command execution error."""
|
|
58
|
+
model_config = {"frozen": True, "extra": "forbid"}
|
|
59
|
+
|
|
60
|
+
output: str
|
|
61
|
+
returncode: int
|
|
62
|
+
|
|
63
|
+
|
|
64
|
+
class BatchCommandSummary(BaseModel):
|
|
65
|
+
"""Summary information for batch command execution."""
|
|
66
|
+
model_config = {"frozen": True, "extra": "forbid"}
|
|
67
|
+
|
|
68
|
+
total: int
|
|
69
|
+
successful: int
|
|
70
|
+
failed: int
|
|
71
|
+
timed_out: int
|
|
72
|
+
execution_mode: str
|
|
73
|
+
|
|
74
|
+
|
|
75
|
+
class BatchCommandContent(BaseModel):
|
|
76
|
+
"""Content for batch command execution results."""
|
|
77
|
+
model_config = {"frozen": True, "extra": "forbid"}
|
|
78
|
+
|
|
79
|
+
batch_results: List[Dict[str, Any]]
|
|
80
|
+
summary: BatchCommandSummary
|
|
81
|
+
|
|
82
|
+
|
|
83
|
+
class TimeoutErrorInfo(BaseModel):
|
|
84
|
+
"""Information about a command timeout error."""
|
|
85
|
+
model_config = {"frozen": True, "extra": "forbid"}
|
|
86
|
+
|
|
87
|
+
error_type: str = "timeout"
|
|
88
|
+
command: str
|
|
89
|
+
timeout_seconds: int
|
|
90
|
+
working_directory: str
|
|
91
|
+
suggested_timeout: int
|
|
92
|
+
original_error: str
|
|
93
|
+
|
|
94
|
+
|
|
21
95
|
class ExecuteCommandToolResolver(BaseToolResolver):
|
|
22
96
|
def __init__(self, agent: Optional['AgenticEdit'], tool: ExecuteCommandTool, args: AutoCoderArgs):
|
|
23
97
|
super().__init__(agent, tool, args)
|
|
24
|
-
self.tool: ExecuteCommandTool = tool
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
98
|
+
self.tool: ExecuteCommandTool = tool # For type hinting
|
|
99
|
+
|
|
100
|
+
# Initialize AutoCoderArgs parser for flexible parameter parsing
|
|
101
|
+
self.args_parser = AutoCoderArgsParser()
|
|
102
|
+
|
|
103
|
+
# 初始化 context_pruner,使用解析后的 token 值
|
|
104
|
+
max_tokens = self._get_parsed_safe_zone_tokens()
|
|
105
|
+
llm = self.agent.context_prune_llm if self.agent else None
|
|
106
|
+
if llm:
|
|
107
|
+
self.context_pruner = PruneContext(
|
|
108
|
+
max_tokens=max_tokens,
|
|
109
|
+
args=self.args,
|
|
110
|
+
llm=llm
|
|
111
|
+
)
|
|
112
|
+
else:
|
|
113
|
+
self.context_pruner = None
|
|
30
114
|
# 初始化危险命令检查器
|
|
31
115
|
self.danger_checker = DangerousCommandChecker()
|
|
32
116
|
|
|
117
|
+
def _get_parsed_safe_zone_tokens(self) -> int:
|
|
118
|
+
"""
|
|
119
|
+
解析 context_prune_safe_zone_tokens 参数,支持多种格式
|
|
120
|
+
|
|
121
|
+
Returns:
|
|
122
|
+
解析后的 token 数量
|
|
123
|
+
"""
|
|
124
|
+
return self.args_parser.parse_context_prune_safe_zone_tokens(
|
|
125
|
+
self.args.context_prune_safe_zone_tokens,
|
|
126
|
+
self.args.code_model
|
|
127
|
+
)
|
|
128
|
+
|
|
129
|
+
def _prune_command_output_with_file_backup(self, output: str, context_name: str = "command_output") -> str:
|
|
130
|
+
"""
|
|
131
|
+
检查输出是否超过60k tokens,如果超过则裁剪并保存完整输出到文件
|
|
132
|
+
|
|
133
|
+
Args:
|
|
134
|
+
output: 命令输出内容
|
|
135
|
+
context_name: 上下文名称,用于标识输出来源
|
|
136
|
+
|
|
137
|
+
Returns:
|
|
138
|
+
str: 处理后的输出内容
|
|
139
|
+
"""
|
|
140
|
+
if not output:
|
|
141
|
+
return output
|
|
142
|
+
|
|
143
|
+
try:
|
|
144
|
+
# 使用 tokens 模块检查 token 数量
|
|
145
|
+
token_count = count_tokens(output)
|
|
146
|
+
|
|
147
|
+
# 如果不超过 6k tokens,直接返回原输出
|
|
148
|
+
if token_count <= 6000:
|
|
149
|
+
return output
|
|
150
|
+
|
|
151
|
+
# 超过 6k tokens,需要裁剪并保存完整文件
|
|
152
|
+
logger.info(f"Output token count ({token_count}) exceeds 6k, pruning and saving to file")
|
|
153
|
+
|
|
154
|
+
# 创建保存目录
|
|
155
|
+
home_dir = os.path.expanduser("~")
|
|
156
|
+
save_dir = os.path.join(home_dir, ".auto-coder", "tool-result", "execute_command")
|
|
157
|
+
os.makedirs(save_dir, exist_ok=True)
|
|
158
|
+
|
|
159
|
+
# 生成文件名(时间+uuid)
|
|
160
|
+
timestamp = time.strftime("%Y%m%d_%H%M%S")
|
|
161
|
+
file_uuid = str(uuid.uuid4())[:8] # 使用前8位UUID
|
|
162
|
+
filename = f"{timestamp}_{file_uuid}.txt"
|
|
163
|
+
full_file_path = os.path.join(save_dir, filename)
|
|
164
|
+
|
|
165
|
+
# 保存完整输出到文件
|
|
166
|
+
with open(full_file_path, 'w', encoding='utf-8') as f:
|
|
167
|
+
f.write(f"# Command Output - Full Content\n")
|
|
168
|
+
f.write(f"# Generated at: {time.strftime('%Y-%m-%d %H:%M:%S')}\n")
|
|
169
|
+
f.write(f"# Context: {context_name}\n")
|
|
170
|
+
f.write(f"# Token count: {token_count}\n")
|
|
171
|
+
f.write(f"# File size: {len(output)} characters\n")
|
|
172
|
+
f.write(f"{'='*60}\n\n")
|
|
173
|
+
f.write(output)
|
|
174
|
+
|
|
175
|
+
# 获取最后6000个字符
|
|
176
|
+
pruned_output = output[-6000:]
|
|
177
|
+
|
|
178
|
+
# 使用 wrap_llm_hint 模块添加标准化提示信息
|
|
179
|
+
hint_message = f"""⚠️ OUTPUT TRUNCATED - Only showing last 6,000 characters
|
|
180
|
+
|
|
181
|
+
📊 Original output: {token_count:,} tokens, {len(output):,} characters
|
|
182
|
+
💾 Full content saved to: {full_file_path}
|
|
183
|
+
|
|
184
|
+
💡 To read the full output or search within it, use:
|
|
185
|
+
read_file tool with path: {full_file_path}
|
|
186
|
+
|
|
187
|
+
You can also use the query parameter to search for specific content:
|
|
188
|
+
<read_file>
|
|
189
|
+
<path>{full_file_path}</path>
|
|
190
|
+
<query>your search term</query>
|
|
191
|
+
</read_file>"""
|
|
192
|
+
|
|
193
|
+
return add_hint_to_text(pruned_output, hint_message)
|
|
194
|
+
|
|
195
|
+
except Exception as e:
|
|
196
|
+
logger.error(f"Error in _prune_command_output_with_file_backup: {str(e)}")
|
|
197
|
+
# 如果处理失败,回退到原始的剪枝方法
|
|
198
|
+
return self._prune_file_content(output, context_name)
|
|
199
|
+
|
|
33
200
|
def _prune_file_content(self, content: str, file_path: str) -> str:
|
|
34
201
|
"""对文件内容进行剪枝处理"""
|
|
35
202
|
if not self.context_pruner:
|
|
@@ -37,7 +204,8 @@ class ExecuteCommandToolResolver(BaseToolResolver):
|
|
|
37
204
|
|
|
38
205
|
# 计算 token 数量
|
|
39
206
|
tokens = count_tokens(content)
|
|
40
|
-
|
|
207
|
+
safe_zone_tokens = self._get_parsed_safe_zone_tokens()
|
|
208
|
+
if tokens <= safe_zone_tokens:
|
|
41
209
|
return content
|
|
42
210
|
|
|
43
211
|
# 创建 SourceCode 对象
|
|
@@ -48,62 +216,376 @@ class ExecuteCommandToolResolver(BaseToolResolver):
|
|
|
48
216
|
)
|
|
49
217
|
|
|
50
218
|
# 使用 context_pruner 进行剪枝
|
|
219
|
+
strategy = self.args.context_prune_strategy or "extract" # 默认策略
|
|
51
220
|
pruned_sources = self.context_pruner.handle_overflow(
|
|
52
221
|
file_sources=[source_code],
|
|
53
222
|
conversations=self.agent.current_conversations if self.agent else [],
|
|
54
|
-
strategy=
|
|
223
|
+
strategy=strategy
|
|
55
224
|
)
|
|
56
225
|
|
|
57
226
|
if not pruned_sources:
|
|
58
227
|
return content
|
|
59
228
|
|
|
60
|
-
return pruned_sources[0].source_code
|
|
229
|
+
return pruned_sources[0].source_code
|
|
230
|
+
|
|
231
|
+
def _execute_background_command(self, command: str, source_dir: str) -> ToolResult:
|
|
232
|
+
"""执行后台命令并返回PID"""
|
|
233
|
+
try:
|
|
234
|
+
# 使用 shell_commands 模块的后台执行功能
|
|
235
|
+
process_info = execute_command_background(
|
|
236
|
+
command=command,
|
|
237
|
+
cwd=source_dir,
|
|
238
|
+
verbose=False # Use default verbose setting
|
|
239
|
+
)
|
|
240
|
+
|
|
241
|
+
pid = process_info["pid"]
|
|
242
|
+
logger.info(f"Started background command: {command} with PID: {pid}\n. Don't forget to kill the process when you don't need it.")
|
|
243
|
+
|
|
244
|
+
# Register with BackgroundProcessNotifier
|
|
245
|
+
try:
|
|
246
|
+
conversation_id = self.agent.conversation_config.conversation_id if self.agent else None
|
|
247
|
+
if conversation_id:
|
|
248
|
+
notifier = get_background_process_notifier()
|
|
249
|
+
notifier.register_process(
|
|
250
|
+
conversation_id=conversation_id,
|
|
251
|
+
pid=pid,
|
|
252
|
+
tool_name="ExecuteCommandTool",
|
|
253
|
+
command=command,
|
|
254
|
+
cwd=source_dir,
|
|
255
|
+
)
|
|
256
|
+
except Exception as e:
|
|
257
|
+
logger.warning(f"Failed to register background process to notifier: {e}")
|
|
258
|
+
|
|
259
|
+
# 获取 process_uniq_id
|
|
260
|
+
process_uniq_id = process_info.get("process_uniq_id")
|
|
261
|
+
|
|
262
|
+
# 返回成功结果,包含PID和process_uniq_id信息
|
|
263
|
+
background_info = BackgroundCommandInfo(
|
|
264
|
+
pid=pid,
|
|
265
|
+
process_uniq_id=process_uniq_id,
|
|
266
|
+
command=command,
|
|
267
|
+
working_directory=source_dir,
|
|
268
|
+
background=True,
|
|
269
|
+
start_time=process_info.get("start_time"),
|
|
270
|
+
status=process_info.get("status", "running")
|
|
271
|
+
)
|
|
272
|
+
|
|
273
|
+
return ToolResult(
|
|
274
|
+
success=True,
|
|
275
|
+
message=f"Background command started successfully with PID: {pid}, ID: {process_uniq_id}",
|
|
276
|
+
content=background_info.model_dump()
|
|
277
|
+
)
|
|
278
|
+
|
|
279
|
+
except Exception as e:
|
|
280
|
+
logger.error(f"Error starting background command '{command}': {str(e)}")
|
|
281
|
+
return ToolResult(
|
|
282
|
+
success=False,
|
|
283
|
+
message=f"Failed to start background command: {str(e)}"
|
|
284
|
+
)
|
|
285
|
+
|
|
286
|
+
def _parse_batch_commands(self, command_str: str) -> Optional[Union[List[str], Dict[str, Any]]]:
|
|
287
|
+
"""
|
|
288
|
+
解析批量命令,支持 JSON、YAML 和换行分隔格式
|
|
289
|
+
|
|
290
|
+
返回:
|
|
291
|
+
- List[str]: 命令列表
|
|
292
|
+
- Dict: 包含 'mode' 和 'cmds' 的字典
|
|
293
|
+
- None: 如果不是批量命令格式
|
|
294
|
+
"""
|
|
295
|
+
# 去除整体缩进,兼容 <execute_command> 标签内被统一缩进的情况
|
|
296
|
+
command_str = textwrap.dedent(command_str).strip()
|
|
297
|
+
if not command_str:
|
|
298
|
+
return None
|
|
299
|
+
|
|
300
|
+
# 1. 尝试 JSON 解析
|
|
301
|
+
try:
|
|
302
|
+
parsed = json.loads(command_str)
|
|
303
|
+
if isinstance(parsed, list) and all(isinstance(cmd, str) for cmd in parsed):
|
|
304
|
+
return parsed
|
|
305
|
+
elif isinstance(parsed, dict) and ('cmds' in parsed or 'commands' in parsed):
|
|
306
|
+
return parsed
|
|
307
|
+
except (json.JSONDecodeError, ValueError):
|
|
308
|
+
pass
|
|
309
|
+
|
|
310
|
+
# 2. 尝试 YAML 解析
|
|
311
|
+
try:
|
|
312
|
+
parsed = yaml.safe_load(command_str)
|
|
313
|
+
if isinstance(parsed, list) and all(isinstance(cmd, str) for cmd in parsed):
|
|
314
|
+
return parsed
|
|
315
|
+
elif isinstance(parsed, dict):
|
|
316
|
+
# 处理类似 "mode: serial\ncmds:\n - cmd1\n - cmd2" 的格式
|
|
317
|
+
if 'cmds' in parsed:
|
|
318
|
+
return parsed
|
|
319
|
+
# 处理简单的 key-value 对,但不是命令格式
|
|
320
|
+
elif not any(key in parsed for key in ['mode', 'cmds', 'commands']):
|
|
321
|
+
return None
|
|
322
|
+
except (yaml.YAMLError, ValueError):
|
|
323
|
+
pass
|
|
324
|
+
|
|
325
|
+
# 3. 尝试换行分隔
|
|
326
|
+
lines = [line.strip() for line in command_str.splitlines() if line.strip()]
|
|
327
|
+
if len(lines) > 1:
|
|
328
|
+
# 检查是否是 shell 脚本格式(第一行是 shebang 或注释)
|
|
329
|
+
if lines[0].startswith('#'):
|
|
330
|
+
# 如果第一行是 "# serial" 或 "# parallel",提取模式
|
|
331
|
+
if lines[0].lower() in ['# serial', '#serial']:
|
|
332
|
+
return {'mode': 'serial', 'cmds': lines[1:]}
|
|
333
|
+
elif lines[0].lower() in ['# parallel', '#parallel']:
|
|
334
|
+
return {'mode': 'parallel', 'cmds': lines[1:]}
|
|
335
|
+
# 否则当做一个命令,而不是批量命令
|
|
336
|
+
return None
|
|
337
|
+
|
|
338
|
+
# 不是批量命令格式
|
|
339
|
+
return None
|
|
340
|
+
|
|
341
|
+
def _execute_batch_commands(self, commands: Union[List[str], Dict[str, Any]], source_dir: str,
|
|
342
|
+
timeout: Optional[int], requires_approval: bool) -> ToolResult:
|
|
343
|
+
"""执行批量命令"""
|
|
344
|
+
# 解析命令和模式
|
|
345
|
+
if isinstance(commands, dict):
|
|
346
|
+
mode = commands.get('mode', 'parallel').lower()
|
|
347
|
+
cmd_list = commands.get('cmds', commands.get('commands', []))
|
|
348
|
+
parallel = mode != 'serial'
|
|
349
|
+
else:
|
|
350
|
+
cmd_list = commands
|
|
351
|
+
parallel = True # 默认并行
|
|
352
|
+
|
|
353
|
+
# 确保 cmd_list 是字符串列表
|
|
354
|
+
if not isinstance(cmd_list, list):
|
|
355
|
+
return ToolResult(
|
|
356
|
+
success=False,
|
|
357
|
+
message="Invalid command list format"
|
|
358
|
+
)
|
|
359
|
+
|
|
360
|
+
# 类型转换和验证
|
|
361
|
+
validated_cmds: List[str] = []
|
|
362
|
+
for cmd in cmd_list:
|
|
363
|
+
if isinstance(cmd, str):
|
|
364
|
+
validated_cmds.append(cmd)
|
|
365
|
+
else:
|
|
366
|
+
return ToolResult(
|
|
367
|
+
success=False,
|
|
368
|
+
message=f"Invalid command type: expected string, got {type(cmd).__name__}"
|
|
369
|
+
)
|
|
370
|
+
|
|
371
|
+
if not validated_cmds:
|
|
372
|
+
return ToolResult(
|
|
373
|
+
success=False,
|
|
374
|
+
message="No commands found in batch command list"
|
|
375
|
+
)
|
|
376
|
+
|
|
377
|
+
# 危险命令检查
|
|
378
|
+
if self.args.enable_agentic_dangerous_command_check:
|
|
379
|
+
for cmd in validated_cmds:
|
|
380
|
+
is_safe, danger_reason = self.danger_checker.check_command_safety(
|
|
381
|
+
cmd, allow_whitelist_bypass=True)
|
|
382
|
+
if not is_safe:
|
|
383
|
+
recommendations = self.danger_checker.get_safety_recommendations(cmd)
|
|
384
|
+
error_message = f"检测到危险命令: {cmd}\n原因: {danger_reason}"
|
|
385
|
+
if recommendations:
|
|
386
|
+
error_message += f"\n安全建议:\n" + "\n".join(f"- {rec}" for rec in recommendations)
|
|
387
|
+
return ToolResult(success=False, message=error_message)
|
|
388
|
+
|
|
389
|
+
# 批量审批
|
|
390
|
+
if not self.args.enable_agentic_auto_approve and requires_approval:
|
|
391
|
+
approval_message = f"Allow to execute {len(validated_cmds)} commands"
|
|
392
|
+
if not parallel:
|
|
393
|
+
approval_message += " (serial execution)"
|
|
394
|
+
approval_message += "?\n\nCommands:\n" + "\n".join(f" {i+1}. {cmd}" for i, cmd in enumerate(validated_cmds))
|
|
395
|
+
|
|
396
|
+
try:
|
|
397
|
+
if get_run_context().is_web():
|
|
398
|
+
answer = get_event_manager(self.args.event_file).ask_user(
|
|
399
|
+
prompt=approval_message,
|
|
400
|
+
options=["yes", "no"]
|
|
401
|
+
)
|
|
402
|
+
if answer != "yes":
|
|
403
|
+
return ToolResult(
|
|
404
|
+
success=False,
|
|
405
|
+
message=f"Batch command execution denied by user."
|
|
406
|
+
)
|
|
407
|
+
except Exception as e:
|
|
408
|
+
logger.error(f"Error when asking user to approve batch commands: {str(e)}")
|
|
409
|
+
return ToolResult(
|
|
410
|
+
success=False,
|
|
411
|
+
message=f"An unexpected error occurred while asking for approval: {str(e)}"
|
|
412
|
+
)
|
|
413
|
+
|
|
414
|
+
# 执行批量命令
|
|
415
|
+
try:
|
|
416
|
+
logger.info(f"Executing {len(validated_cmds)} commands ({'parallel' if parallel else 'serial'} mode)")
|
|
417
|
+
|
|
418
|
+
# 计算超时参数
|
|
419
|
+
per_command_timeout = None
|
|
420
|
+
if timeout:
|
|
421
|
+
if parallel:
|
|
422
|
+
# 并行模式:每个命令都可以用完整的超时时间
|
|
423
|
+
per_command_timeout = timeout
|
|
424
|
+
else:
|
|
425
|
+
# 串行模式:平分超时时间(至少给每个命令10秒)
|
|
426
|
+
per_command_timeout = max(timeout / len(validated_cmds), 10.0)
|
|
427
|
+
|
|
428
|
+
# 使用 shell_commands 的批量执行功能
|
|
429
|
+
# 创建符合 execute_commands 类型要求的命令列表
|
|
430
|
+
typed_commands: List[Union[str, List[str]]] = validated_cmds # type: ignore
|
|
431
|
+
results = execute_commands(
|
|
432
|
+
commands=typed_commands,
|
|
433
|
+
parallel=parallel,
|
|
434
|
+
per_command_timeout=per_command_timeout,
|
|
435
|
+
timeout=timeout,
|
|
436
|
+
cwd=source_dir,
|
|
437
|
+
verbose=True
|
|
438
|
+
)
|
|
439
|
+
|
|
440
|
+
# 统计结果
|
|
441
|
+
successful = sum(1 for r in results if r['exit_code'] == 0)
|
|
442
|
+
failed = sum(1 for r in results if r['exit_code'] != 0 and not r['timed_out'])
|
|
443
|
+
timed_out = sum(1 for r in results if r['timed_out'])
|
|
444
|
+
|
|
445
|
+
# 构建汇总消息
|
|
446
|
+
summary_parts = []
|
|
447
|
+
if successful > 0:
|
|
448
|
+
summary_parts.append(f"{successful} succeeded")
|
|
449
|
+
if failed > 0:
|
|
450
|
+
summary_parts.append(f"{failed} failed")
|
|
451
|
+
if timed_out > 0:
|
|
452
|
+
summary_parts.append(f"{timed_out} timed out")
|
|
453
|
+
|
|
454
|
+
summary = f"Batch execution completed: {', '.join(summary_parts)}"
|
|
455
|
+
|
|
456
|
+
# 对每个命令的输出进行裁剪
|
|
457
|
+
for result in results:
|
|
458
|
+
if 'output' in result and result['output']:
|
|
459
|
+
result['output'] = self._prune_command_output_with_file_backup(
|
|
460
|
+
result['output'],
|
|
461
|
+
f"command_{result['index']}_output"
|
|
462
|
+
)
|
|
463
|
+
|
|
464
|
+
batch_summary = BatchCommandSummary(
|
|
465
|
+
total=len(results),
|
|
466
|
+
successful=successful,
|
|
467
|
+
failed=failed,
|
|
468
|
+
timed_out=timed_out,
|
|
469
|
+
execution_mode='parallel' if parallel else 'serial'
|
|
470
|
+
)
|
|
471
|
+
|
|
472
|
+
batch_content = BatchCommandContent(
|
|
473
|
+
batch_results=results,
|
|
474
|
+
summary=batch_summary
|
|
475
|
+
)
|
|
476
|
+
|
|
477
|
+
return ToolResult(
|
|
478
|
+
success=all(r['exit_code'] == 0 for r in results),
|
|
479
|
+
message=summary,
|
|
480
|
+
content=batch_content.model_dump()
|
|
481
|
+
)
|
|
482
|
+
|
|
483
|
+
except Exception as e:
|
|
484
|
+
logger.error(f"Error executing batch commands: {str(e)}")
|
|
485
|
+
return ToolResult(
|
|
486
|
+
success=False,
|
|
487
|
+
message=f"An unexpected error occurred while executing batch commands: {str(e)}"
|
|
488
|
+
)
|
|
61
489
|
|
|
62
|
-
def resolve(self) -> ToolResult:
|
|
490
|
+
def resolve(self) -> ToolResult:
|
|
63
491
|
command = self.tool.command
|
|
64
492
|
requires_approval = self.tool.requires_approval
|
|
493
|
+
background = self.tool.background # 获取后台运行选项
|
|
65
494
|
source_dir = self.args.source_dir or "."
|
|
66
495
|
|
|
496
|
+
# 尝试解析批量命令
|
|
497
|
+
batch_commands = self._parse_batch_commands(command)
|
|
498
|
+
if batch_commands is not None:
|
|
499
|
+
# 检查是否是批量命令(多于1个命令)
|
|
500
|
+
if isinstance(batch_commands, list) and len(batch_commands) > 1:
|
|
501
|
+
# 是批量命令列表
|
|
502
|
+
return self._execute_batch_commands(batch_commands, source_dir, self.tool.timeout, requires_approval)
|
|
503
|
+
elif isinstance(batch_commands, dict) and (batch_commands.get('cmds') or batch_commands.get('commands')):
|
|
504
|
+
# 是包含命令列表的字典格式
|
|
505
|
+
return self._execute_batch_commands(batch_commands, source_dir, self.tool.timeout, requires_approval)
|
|
506
|
+
# 如果只有一个命令,继续按单个命令处理
|
|
507
|
+
elif isinstance(batch_commands, list) and len(batch_commands) == 1:
|
|
508
|
+
command = batch_commands[0]
|
|
509
|
+
elif isinstance(batch_commands, dict):
|
|
510
|
+
# 检查是否只有一个命令
|
|
511
|
+
cmd_list = batch_commands.get('cmds', batch_commands.get('commands', []))
|
|
512
|
+
if len(cmd_list) == 1:
|
|
513
|
+
command = cmd_list[0]
|
|
514
|
+
|
|
67
515
|
if self.args.enable_agentic_dangerous_command_check:
|
|
68
516
|
# 使用新的危险命令检查器进行安全检查
|
|
69
|
-
is_safe, danger_reason = self.danger_checker.check_command_safety(
|
|
70
|
-
|
|
517
|
+
is_safe, danger_reason = self.danger_checker.check_command_safety(
|
|
518
|
+
command, allow_whitelist_bypass=True)
|
|
519
|
+
|
|
71
520
|
if not is_safe:
|
|
72
521
|
# 获取安全建议
|
|
73
|
-
recommendations = self.danger_checker.get_safety_recommendations(
|
|
74
|
-
|
|
522
|
+
recommendations = self.danger_checker.get_safety_recommendations(
|
|
523
|
+
command)
|
|
524
|
+
|
|
75
525
|
error_message = f"检测到危险命令: {danger_reason}"
|
|
76
526
|
if recommendations:
|
|
77
|
-
error_message += f"\n安全建议:\n" +
|
|
78
|
-
|
|
527
|
+
error_message += f"\n安全建议:\n" + \
|
|
528
|
+
"\n".join(f"- {rec}" for rec in recommendations)
|
|
529
|
+
|
|
79
530
|
logger.warning(f"阻止执行危险命令: {command}, 原因: {danger_reason}")
|
|
80
531
|
return ToolResult(success=False, message=error_message)
|
|
81
532
|
|
|
82
533
|
# Approval mechanism (simplified)
|
|
83
534
|
if not self.args.enable_agentic_auto_approve and requires_approval:
|
|
84
|
-
logger.info(
|
|
85
|
-
|
|
535
|
+
logger.info(
|
|
536
|
+
f"Executing command: {command} in {os.path.abspath(source_dir)}")
|
|
537
|
+
try:
|
|
86
538
|
# 使用封装的run_cmd方法执行命令
|
|
87
539
|
if get_run_context().is_web():
|
|
88
540
|
answer = get_event_manager(
|
|
89
|
-
self.args.event_file).ask_user(prompt=f"Allow to execute the `{command}`?",options=["yes","no"])
|
|
541
|
+
self.args.event_file).ask_user(prompt=f"Allow to execute the `{command}`?", options=["yes", "no"])
|
|
90
542
|
if answer == "yes":
|
|
91
543
|
pass
|
|
92
544
|
else:
|
|
93
545
|
return ToolResult(success=False, message=f"Command '{command}' execution denied by user.")
|
|
94
546
|
except Exception as e:
|
|
95
|
-
logger.error(
|
|
547
|
+
logger.error(
|
|
548
|
+
f"Error when ask the user to approve the command '{command}': {str(e)}")
|
|
96
549
|
return ToolResult(success=False, message=f"An unexpected error occurred while asking the user to approve the command: {str(e)}")
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
550
|
+
|
|
551
|
+
# 如果是后台运行,使用专门的后台执行方法
|
|
552
|
+
if background:
|
|
553
|
+
return self._execute_background_command(command, source_dir)
|
|
554
|
+
|
|
555
|
+
# 如果不是后台运行,继续使用原来的前台执行逻辑
|
|
556
|
+
try:
|
|
557
|
+
# 根据配置选择使用新的 shell_commands 模块还是旧的 run_cmd 模块
|
|
558
|
+
use_shell_commands = self.args.use_shell_commands
|
|
559
|
+
|
|
560
|
+
# 获取超时参数
|
|
561
|
+
timeout = self.tool.timeout # 使用工具中的超时参数
|
|
562
|
+
|
|
563
|
+
if use_shell_commands:
|
|
564
|
+
# 使用新的 shell_commands 模块
|
|
565
|
+
logger.debug(
|
|
566
|
+
f"Using shell_commands module for command execution (timeout: {timeout}s)")
|
|
567
|
+
try:
|
|
568
|
+
exit_code, output = execute_command(
|
|
569
|
+
command, timeout=timeout, verbose=True, cwd=source_dir)
|
|
570
|
+
except CommandTimeoutError as e:
|
|
571
|
+
logger.error(f"Command timed out: {e}")
|
|
572
|
+
return self._build_timeout_error_result(command, timeout, source_dir, e)
|
|
573
|
+
except CommandExecutionError as e:
|
|
574
|
+
logger.error(f"Command execution failed: {e}")
|
|
575
|
+
return ToolResult(success=False, message=f"Command execution failed: {str(e)}")
|
|
576
|
+
else:
|
|
577
|
+
# 使用旧的 run_cmd 模块(不支持超时)
|
|
578
|
+
logger.debug("Using run_cmd module for command execution (note: timeout not supported)")
|
|
579
|
+
exit_code, output = run_cmd_subprocess(
|
|
580
|
+
command, verbose=True, cwd=source_dir)
|
|
100
581
|
|
|
101
582
|
logger.info(f"Command executed: {command}")
|
|
102
583
|
logger.info(f"Return Code: {exit_code}")
|
|
103
584
|
if output:
|
|
104
|
-
|
|
585
|
+
# Avoid logging potentially huge output directly
|
|
586
|
+
logger.info(f"Original Output (length: {len(output)} chars)")
|
|
105
587
|
|
|
106
|
-
final_output = self.
|
|
588
|
+
final_output = self._prune_command_output_with_file_backup(output, "command_output")
|
|
107
589
|
|
|
108
590
|
if exit_code == 0:
|
|
109
591
|
return ToolResult(success=True, message="Command executed successfully.", content=final_output)
|
|
@@ -111,7 +593,13 @@ class ExecuteCommandToolResolver(BaseToolResolver):
|
|
|
111
593
|
# For the human-readable error message, we might prefer the original full output.
|
|
112
594
|
# For the agent-consumable content, we provide the (potentially pruned) final_output.
|
|
113
595
|
error_message_for_human = f"Command failed with return code {exit_code}.\nOutput:\n{output}"
|
|
114
|
-
|
|
596
|
+
|
|
597
|
+
error_info = CommandErrorInfo(
|
|
598
|
+
output=final_output,
|
|
599
|
+
returncode=exit_code
|
|
600
|
+
)
|
|
601
|
+
|
|
602
|
+
return ToolResult(success=False, message=error_message_for_human, content=error_info.model_dump())
|
|
115
603
|
|
|
116
604
|
except FileNotFoundError:
|
|
117
605
|
return ToolResult(success=False, message=f"Error: The command '{command.split()[0]}' was not found. Please ensure it is installed and in the system's PATH.")
|
|
@@ -120,3 +608,50 @@ class ExecuteCommandToolResolver(BaseToolResolver):
|
|
|
120
608
|
except Exception as e:
|
|
121
609
|
logger.error(f"Error executing command '{command}': {str(e)}")
|
|
122
610
|
return ToolResult(success=False, message=f"An unexpected error occurred while executing the command: {str(e)}")
|
|
611
|
+
|
|
612
|
+
def _build_timeout_error_result(self, command: str, timeout: Optional[int], source_dir: str, error: Exception) -> ToolResult:
|
|
613
|
+
"""构建超时错误结果"""
|
|
614
|
+
# 处理超时值,确保不为 None
|
|
615
|
+
actual_timeout = timeout if timeout is not None else 60
|
|
616
|
+
suggested_timeout = actual_timeout * 2
|
|
617
|
+
|
|
618
|
+
# 构建基本错误信息
|
|
619
|
+
basic_error = f"""COMMAND TIMEOUT ERROR
|
|
620
|
+
|
|
621
|
+
Command: {command}
|
|
622
|
+
Timeout: {actual_timeout} seconds
|
|
623
|
+
Directory: {source_dir}
|
|
624
|
+
|
|
625
|
+
The command failed to complete within the specified timeout period."""
|
|
626
|
+
|
|
627
|
+
# 构建详细的建议信息作为 hint
|
|
628
|
+
suggestions_hint = f"""This usually indicates that:
|
|
629
|
+
1. The command is taking longer than expected to execute
|
|
630
|
+
2. The command may be waiting for user input or hanging
|
|
631
|
+
3. The command is processing large amounts of data
|
|
632
|
+
|
|
633
|
+
Suggestions:
|
|
634
|
+
• Increase the timeout value using: <timeout>{suggested_timeout}</timeout>
|
|
635
|
+
• Check if the command requires user interaction
|
|
636
|
+
• Consider breaking down complex commands into smaller steps
|
|
637
|
+
• Verify the command syntax and parameters are correct
|
|
638
|
+
|
|
639
|
+
Error details: {str(error)}"""
|
|
640
|
+
|
|
641
|
+
# 使用 wrap_llm_hint 模块添加标准化提示信息
|
|
642
|
+
timeout_message = add_hint_to_text(basic_error, suggestions_hint)
|
|
643
|
+
|
|
644
|
+
timeout_info = TimeoutErrorInfo(
|
|
645
|
+
error_type="timeout",
|
|
646
|
+
command=command,
|
|
647
|
+
timeout_seconds=actual_timeout,
|
|
648
|
+
working_directory=source_dir,
|
|
649
|
+
suggested_timeout=suggested_timeout,
|
|
650
|
+
original_error=str(error)
|
|
651
|
+
)
|
|
652
|
+
|
|
653
|
+
return ToolResult(
|
|
654
|
+
success=False,
|
|
655
|
+
message=timeout_message,
|
|
656
|
+
content=timeout_info.model_dump()
|
|
657
|
+
)
|