auto-coder 1.0.0__py3-none-any.whl → 2.0.1__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of auto-coder might be problematic. Click here for more details.
- auto_coder-2.0.1.dist-info/LICENSE +158 -0
- auto_coder-2.0.1.dist-info/METADATA +558 -0
- auto_coder-2.0.1.dist-info/RECORD +795 -0
- {auto_coder-1.0.0.dist-info → auto_coder-2.0.1.dist-info}/WHEEL +1 -1
- {auto_coder-1.0.0.dist-info → auto_coder-2.0.1.dist-info}/entry_points.txt +3 -3
- autocoder/__init__.py +31 -0
- autocoder/agent/auto_filegroup.py +32 -13
- autocoder/agent/auto_learn_from_commit.py +9 -1
- autocoder/agent/base_agentic/__init__.py +3 -0
- autocoder/agent/base_agentic/agent_hub.py +1 -1
- autocoder/agent/base_agentic/base_agent.py +235 -136
- autocoder/agent/base_agentic/default_tools.py +119 -118
- autocoder/agent/base_agentic/test_base_agent.py +1 -1
- autocoder/agent/base_agentic/tool_registry.py +32 -20
- autocoder/agent/base_agentic/tools/read_file_tool_resolver.py +24 -3
- autocoder/agent/base_agentic/tools/write_to_file_tool_resolver.py +24 -11
- autocoder/agent/base_agentic/types.py +42 -0
- autocoder/agent/entry_command_agent/chat.py +77 -73
- autocoder/auto_coder.py +31 -40
- autocoder/auto_coder_rag.py +11 -1084
- autocoder/auto_coder_runner.py +962 -2345
- autocoder/auto_coder_terminal.py +26 -0
- autocoder/auto_coder_terminal_v3.py +190 -0
- autocoder/chat/conf_command.py +224 -124
- autocoder/chat/models_command.py +361 -299
- autocoder/chat/rules_command.py +79 -31
- autocoder/chat_auto_coder.py +988 -398
- autocoder/chat_auto_coder_lang.py +23 -732
- autocoder/commands/auto_command.py +25 -8
- autocoder/commands/auto_web.py +1 -1
- autocoder/commands/tools.py +44 -44
- autocoder/common/__init__.py +150 -128
- autocoder/common/ac_style_command_parser/__init__.py +39 -2
- autocoder/common/ac_style_command_parser/config.py +422 -0
- autocoder/common/ac_style_command_parser/parser.py +292 -78
- autocoder/common/ac_style_command_parser/test_parser.py +241 -16
- autocoder/common/ac_style_command_parser/test_typed_parser.py +342 -0
- autocoder/common/ac_style_command_parser/typed_parser.py +653 -0
- autocoder/common/action_yml_file_manager.py +25 -13
- autocoder/common/agent_events/__init__.py +52 -0
- autocoder/common/agent_events/agent_event_emitter.py +193 -0
- autocoder/common/agent_events/event_factory.py +177 -0
- autocoder/common/agent_events/examples.py +307 -0
- autocoder/common/agent_events/types.py +113 -0
- autocoder/common/agent_events/utils.py +68 -0
- autocoder/common/agent_hooks/__init__.py +44 -0
- autocoder/common/agent_hooks/examples.py +582 -0
- autocoder/common/agent_hooks/hook_executor.py +217 -0
- autocoder/common/agent_hooks/hook_manager.py +288 -0
- autocoder/common/agent_hooks/types.py +133 -0
- autocoder/common/agent_hooks/utils.py +99 -0
- autocoder/common/agent_query_queue/queue_executor.py +324 -0
- autocoder/common/agent_query_queue/queue_manager.py +325 -0
- autocoder/common/agents/__init__.py +11 -0
- autocoder/common/agents/agent_manager.py +323 -0
- autocoder/common/agents/agent_parser.py +189 -0
- autocoder/common/agents/example_usage.py +344 -0
- autocoder/common/agents/integration_example.py +330 -0
- autocoder/common/agents/test_agent_parser.py +545 -0
- autocoder/common/async_utils.py +101 -0
- autocoder/common/auto_coder_lang.py +23 -972
- autocoder/common/autocoderargs_parser/__init__.py +14 -0
- autocoder/common/autocoderargs_parser/parser.py +184 -0
- autocoder/common/autocoderargs_parser/tests/__init__.py +1 -0
- autocoder/common/autocoderargs_parser/tests/test_args_parser.py +235 -0
- autocoder/common/autocoderargs_parser/tests/test_token_parser.py +195 -0
- autocoder/common/autocoderargs_parser/token_parser.py +290 -0
- autocoder/common/buildin_tokenizer.py +2 -4
- autocoder/common/code_auto_generate.py +149 -74
- autocoder/common/code_auto_generate_diff.py +163 -70
- autocoder/common/code_auto_generate_editblock.py +179 -89
- autocoder/common/code_auto_generate_strict_diff.py +167 -72
- autocoder/common/code_auto_merge_editblock.py +13 -6
- autocoder/common/code_modification_ranker.py +1 -1
- autocoder/common/command_completer.py +3 -3
- autocoder/common/command_file_manager/manager.py +183 -47
- autocoder/common/command_file_manager/test_command_file_manager.py +507 -0
- autocoder/common/command_templates.py +1 -1
- autocoder/common/conf_utils.py +2 -4
- autocoder/common/conversations/config.py +11 -3
- autocoder/common/conversations/get_conversation_manager.py +100 -2
- autocoder/common/conversations/llm_stats_models.py +264 -0
- autocoder/common/conversations/manager.py +112 -28
- autocoder/common/conversations/models.py +16 -2
- autocoder/common/conversations/storage/index_manager.py +134 -10
- autocoder/common/core_config/__init__.py +63 -0
- autocoder/common/core_config/agentic_mode_manager.py +109 -0
- autocoder/common/core_config/base_manager.py +123 -0
- autocoder/common/core_config/compatibility.py +151 -0
- autocoder/common/core_config/config_manager.py +156 -0
- autocoder/common/core_config/conversation_manager.py +31 -0
- autocoder/common/core_config/exclude_manager.py +72 -0
- autocoder/common/core_config/file_manager.py +177 -0
- autocoder/common/core_config/human_as_model_manager.py +129 -0
- autocoder/common/core_config/lib_manager.py +54 -0
- autocoder/common/core_config/main_manager.py +81 -0
- autocoder/common/core_config/mode_manager.py +126 -0
- autocoder/common/core_config/models.py +70 -0
- autocoder/common/core_config/test_memory_manager.py +1056 -0
- autocoder/common/env_manager.py +282 -0
- autocoder/common/env_manager_usage_example.py +211 -0
- autocoder/common/file_checkpoint/conversation_checkpoint.py +19 -19
- autocoder/common/file_checkpoint/manager.py +264 -48
- autocoder/common/file_checkpoint/test_backup.py +1 -18
- autocoder/common/file_checkpoint/test_manager.py +270 -1
- autocoder/common/file_checkpoint/test_store.py +1 -17
- autocoder/common/file_handler/__init__.py +23 -0
- autocoder/common/file_handler/active_context_handler.py +159 -0
- autocoder/common/file_handler/add_files_handler.py +409 -0
- autocoder/common/file_handler/chat_handler.py +180 -0
- autocoder/common/file_handler/coding_handler.py +409 -0
- autocoder/common/file_handler/commit_handler.py +200 -0
- autocoder/common/file_handler/lib_handler.py +156 -0
- autocoder/common/file_handler/list_files_handler.py +111 -0
- autocoder/common/file_handler/mcp_handler.py +268 -0
- autocoder/common/file_handler/models_handler.py +493 -0
- autocoder/common/file_handler/remove_files_handler.py +172 -0
- autocoder/common/git_utils.py +44 -8
- autocoder/common/global_cancel.py +15 -6
- autocoder/common/ignorefiles/test_ignore_file_utils.py +1 -1
- autocoder/common/international/__init__.py +31 -0
- autocoder/common/international/demo_international.py +92 -0
- autocoder/common/international/message_manager.py +157 -0
- autocoder/common/international/messages/__init__.py +56 -0
- autocoder/common/international/messages/async_command_messages.py +507 -0
- autocoder/common/international/messages/auto_coder_messages.py +2208 -0
- autocoder/common/international/messages/chat_auto_coder_messages.py +1547 -0
- autocoder/common/international/messages/command_help_messages.py +986 -0
- autocoder/common/international/messages/conversation_command_messages.py +191 -0
- autocoder/common/international/messages/git_helper_plugin_messages.py +159 -0
- autocoder/common/international/messages/queue_command_messages.py +751 -0
- autocoder/common/international/messages/rules_command_messages.py +77 -0
- autocoder/common/international/messages/sdk_messages.py +1707 -0
- autocoder/common/international/messages/token_helper_plugin_messages.py +361 -0
- autocoder/common/international/messages/tool_display_messages.py +1212 -0
- autocoder/common/international/messages/workflow_exception_messages.py +473 -0
- autocoder/common/international/test_international.py +612 -0
- autocoder/common/linter_core/__init__.py +28 -0
- autocoder/common/linter_core/base_linter.py +61 -0
- autocoder/common/linter_core/config_loader.py +271 -0
- autocoder/common/linter_core/formatters/__init__.py +0 -0
- autocoder/common/linter_core/formatters/base_formatter.py +38 -0
- autocoder/common/linter_core/formatters/raw_formatter.py +17 -0
- autocoder/common/linter_core/linter.py +166 -0
- autocoder/common/linter_core/linter_factory.py +216 -0
- autocoder/common/linter_core/linter_manager.py +333 -0
- autocoder/common/linter_core/linters/__init__.py +9 -0
- autocoder/common/linter_core/linters/java_linter.py +342 -0
- autocoder/common/linter_core/linters/python_linter.py +115 -0
- autocoder/common/linter_core/linters/typescript_linter.py +119 -0
- autocoder/common/linter_core/models/__init__.py +7 -0
- autocoder/common/linter_core/models/lint_result.py +91 -0
- autocoder/common/linter_core/models.py +33 -0
- autocoder/common/linter_core/tests/__init__.py +3 -0
- autocoder/common/linter_core/tests/test_config_loader.py +323 -0
- autocoder/common/linter_core/tests/test_config_loading.py +308 -0
- autocoder/common/linter_core/tests/test_factory_manager.py +234 -0
- autocoder/common/linter_core/tests/test_formatters.py +147 -0
- autocoder/common/linter_core/tests/test_integration.py +317 -0
- autocoder/common/linter_core/tests/test_java_linter.py +496 -0
- autocoder/common/linter_core/tests/test_linters.py +265 -0
- autocoder/common/linter_core/tests/test_models.py +81 -0
- autocoder/common/linter_core/tests/verify_config_loading.py +296 -0
- autocoder/common/linter_core/tests/verify_fixes.py +183 -0
- autocoder/common/llm_friendly_package/__init__.py +31 -0
- autocoder/common/llm_friendly_package/base_manager.py +102 -0
- autocoder/common/llm_friendly_package/docs_manager.py +121 -0
- autocoder/common/llm_friendly_package/library_manager.py +171 -0
- autocoder/common/{llm_friendly_package.py → llm_friendly_package/main_manager.py} +204 -231
- autocoder/common/llm_friendly_package/models.py +40 -0
- autocoder/common/llm_friendly_package/test_llm_friendly_package.py +536 -0
- autocoder/common/llms/__init__.py +15 -0
- autocoder/common/llms/demo_error_handling.py +85 -0
- autocoder/common/llms/factory.py +142 -0
- autocoder/common/llms/manager.py +264 -0
- autocoder/common/llms/pricing.py +121 -0
- autocoder/common/llms/registry.py +316 -0
- autocoder/common/llms/schema.py +77 -0
- autocoder/common/llms/simple_demo.py +45 -0
- autocoder/common/llms/test_quick_model.py +116 -0
- autocoder/common/llms/test_remove_functionality.py +182 -0
- autocoder/common/llms/tests/__init__.py +1 -0
- autocoder/common/llms/tests/test_manager.py +330 -0
- autocoder/common/llms/tests/test_registry.py +364 -0
- autocoder/common/mcp_tools/__init__.py +62 -0
- autocoder/common/{mcp_tools.py → mcp_tools/executor.py} +49 -40
- autocoder/common/{mcp_hub.py → mcp_tools/hub.py} +42 -68
- autocoder/common/{mcp_server_install.py → mcp_tools/installer.py} +16 -28
- autocoder/common/{mcp_server.py → mcp_tools/server.py} +176 -48
- autocoder/common/mcp_tools/test_keyboard_interrupt.py +93 -0
- autocoder/common/mcp_tools/test_mcp_tools.py +391 -0
- autocoder/common/{mcp_server_types.py → mcp_tools/types.py} +121 -48
- autocoder/common/mcp_tools/verify_functionality.py +202 -0
- autocoder/common/model_speed_tester.py +32 -26
- autocoder/common/priority_directory_finder/__init__.py +142 -0
- autocoder/common/priority_directory_finder/examples.py +230 -0
- autocoder/common/priority_directory_finder/finder.py +283 -0
- autocoder/common/priority_directory_finder/models.py +236 -0
- autocoder/common/priority_directory_finder/test_priority_directory_finder.py +431 -0
- autocoder/common/project_scanner/__init__.py +18 -0
- autocoder/common/project_scanner/compat.py +77 -0
- autocoder/common/project_scanner/scanner.py +436 -0
- autocoder/common/project_tracker/__init__.py +27 -0
- autocoder/common/project_tracker/api.py +228 -0
- autocoder/common/project_tracker/demo.py +272 -0
- autocoder/common/project_tracker/tracker.py +487 -0
- autocoder/common/project_tracker/types.py +53 -0
- autocoder/common/pruner/__init__.py +67 -0
- autocoder/common/pruner/agentic_conversation_pruner.py +651 -102
- autocoder/common/pruner/conversation_message_ids_api.py +386 -0
- autocoder/common/pruner/conversation_message_ids_manager.py +347 -0
- autocoder/common/pruner/conversation_message_ids_pruner.py +473 -0
- autocoder/common/pruner/conversation_normalizer.py +347 -0
- autocoder/common/pruner/conversation_pruner.py +26 -6
- autocoder/common/pruner/test_agentic_conversation_pruner.py +554 -112
- autocoder/common/pruner/test_conversation_normalizer.py +502 -0
- autocoder/common/pruner/test_tool_content_detector.py +324 -0
- autocoder/common/pruner/tool_content_detector.py +227 -0
- autocoder/common/pruner/tools/__init__.py +18 -0
- autocoder/common/pruner/tools/query_message_ids.py +264 -0
- autocoder/common/pruner/tools/test_agentic_pruning_logic.py +432 -0
- autocoder/common/pruner/tools/test_message_ids_pruning_only.py +192 -0
- autocoder/common/pull_requests/__init__.py +9 -1
- autocoder/common/pull_requests/utils.py +122 -1
- autocoder/common/rag_manager/rag_manager.py +36 -40
- autocoder/common/rulefiles/__init__.py +53 -1
- autocoder/common/rulefiles/api.py +250 -0
- autocoder/common/rulefiles/core/__init__.py +14 -0
- autocoder/common/rulefiles/core/manager.py +241 -0
- autocoder/common/rulefiles/core/selector.py +805 -0
- autocoder/common/rulefiles/models/__init__.py +20 -0
- autocoder/common/rulefiles/models/index.py +16 -0
- autocoder/common/rulefiles/models/init_rule.py +18 -0
- autocoder/common/rulefiles/models/rule_file.py +18 -0
- autocoder/common/rulefiles/models/rule_relevance.py +14 -0
- autocoder/common/rulefiles/models/summary.py +16 -0
- autocoder/common/rulefiles/test_rulefiles.py +776 -0
- autocoder/common/rulefiles/utils/__init__.py +34 -0
- autocoder/common/rulefiles/utils/monitor.py +86 -0
- autocoder/common/rulefiles/utils/parser.py +230 -0
- autocoder/common/save_formatted_log.py +67 -10
- autocoder/common/search_replace.py +8 -1
- autocoder/common/search_replace_patch/__init__.py +24 -0
- autocoder/common/search_replace_patch/base.py +115 -0
- autocoder/common/search_replace_patch/manager.py +248 -0
- autocoder/common/search_replace_patch/patch_replacer.py +304 -0
- autocoder/common/search_replace_patch/similarity_replacer.py +306 -0
- autocoder/common/search_replace_patch/string_replacer.py +181 -0
- autocoder/common/search_replace_patch/tests/__init__.py +3 -0
- autocoder/common/search_replace_patch/tests/run_tests.py +126 -0
- autocoder/common/search_replace_patch/tests/test_base.py +188 -0
- autocoder/common/search_replace_patch/tests/test_empty_line_insert.py +233 -0
- autocoder/common/search_replace_patch/tests/test_integration.py +389 -0
- autocoder/common/search_replace_patch/tests/test_manager.py +351 -0
- autocoder/common/search_replace_patch/tests/test_patch_replacer.py +316 -0
- autocoder/common/search_replace_patch/tests/test_regex_replacer.py +306 -0
- autocoder/common/search_replace_patch/tests/test_similarity_replacer.py +384 -0
- autocoder/common/shell_commands/__init__.py +197 -0
- autocoder/common/shell_commands/background_process_notifier.py +346 -0
- autocoder/common/shell_commands/command_executor.py +1127 -0
- autocoder/common/shell_commands/error_recovery.py +541 -0
- autocoder/common/shell_commands/exceptions.py +120 -0
- autocoder/common/shell_commands/interactive_executor.py +476 -0
- autocoder/common/shell_commands/interactive_pexpect_process.py +623 -0
- autocoder/common/shell_commands/interactive_process.py +744 -0
- autocoder/common/shell_commands/interactive_session_manager.py +1014 -0
- autocoder/common/shell_commands/monitoring.py +529 -0
- autocoder/common/shell_commands/process_cleanup.py +386 -0
- autocoder/common/shell_commands/process_manager.py +606 -0
- autocoder/common/shell_commands/test_interactive_pexpect_process.py +281 -0
- autocoder/common/shell_commands/tests/__init__.py +6 -0
- autocoder/common/shell_commands/tests/conftest.py +118 -0
- autocoder/common/shell_commands/tests/test_background_process_notifier.py +703 -0
- autocoder/common/shell_commands/tests/test_command_executor.py +448 -0
- autocoder/common/shell_commands/tests/test_error_recovery.py +305 -0
- autocoder/common/shell_commands/tests/test_exceptions.py +299 -0
- autocoder/common/shell_commands/tests/test_execute_batch.py +588 -0
- autocoder/common/shell_commands/tests/test_indented_batch_commands.py +244 -0
- autocoder/common/shell_commands/tests/test_integration.py +664 -0
- autocoder/common/shell_commands/tests/test_monitoring.py +546 -0
- autocoder/common/shell_commands/tests/test_performance.py +632 -0
- autocoder/common/shell_commands/tests/test_process_cleanup.py +397 -0
- autocoder/common/shell_commands/tests/test_process_manager.py +606 -0
- autocoder/common/shell_commands/tests/test_timeout_config.py +343 -0
- autocoder/common/shell_commands/tests/test_timeout_manager.py +520 -0
- autocoder/common/shell_commands/timeout_config.py +315 -0
- autocoder/common/shell_commands/timeout_manager.py +352 -0
- autocoder/common/terminal_paste/__init__.py +14 -0
- autocoder/common/terminal_paste/demo.py +145 -0
- autocoder/common/terminal_paste/demo_paste_functionality.py +95 -0
- autocoder/common/terminal_paste/paste_handler.py +200 -0
- autocoder/common/terminal_paste/paste_manager.py +118 -0
- autocoder/common/terminal_paste/tests/__init__.py +1 -0
- autocoder/common/terminal_paste/tests/test_paste_handler.py +182 -0
- autocoder/common/terminal_paste/tests/test_paste_manager.py +126 -0
- autocoder/common/terminal_paste/utils.py +163 -0
- autocoder/common/test_autocoder_args.py +232 -0
- autocoder/common/test_env_manager.py +173 -0
- autocoder/common/test_env_manager_integration.py +159 -0
- autocoder/common/text_similarity/__init__.py +9 -0
- autocoder/common/text_similarity/demo.py +216 -0
- autocoder/common/text_similarity/examples.py +266 -0
- autocoder/common/text_similarity/test_text_similarity.py +306 -0
- autocoder/common/text_similarity/text_similarity.py +194 -0
- autocoder/common/text_similarity/utils.py +125 -0
- autocoder/common/todos/__init__.py +61 -0
- autocoder/common/todos/cache/__init__.py +16 -0
- autocoder/common/todos/cache/base_cache.py +89 -0
- autocoder/common/todos/cache/cache_manager.py +228 -0
- autocoder/common/todos/cache/memory_cache.py +225 -0
- autocoder/common/todos/config.py +155 -0
- autocoder/common/todos/exceptions.py +35 -0
- autocoder/common/todos/get_todo_manager.py +161 -0
- autocoder/common/todos/manager.py +537 -0
- autocoder/common/todos/models.py +239 -0
- autocoder/common/todos/storage/__init__.py +14 -0
- autocoder/common/todos/storage/base_storage.py +76 -0
- autocoder/common/todos/storage/file_storage.py +278 -0
- autocoder/common/tokens/counter.py +24 -2
- autocoder/common/tools_manager/__init__.py +17 -0
- autocoder/common/tools_manager/examples.py +162 -0
- autocoder/common/tools_manager/manager.py +385 -0
- autocoder/common/tools_manager/models.py +39 -0
- autocoder/common/tools_manager/test_tools_manager.py +303 -0
- autocoder/common/tools_manager/utils.py +191 -0
- autocoder/common/v2/agent/agentic_callbacks.py +270 -0
- autocoder/common/v2/agent/agentic_edit.py +2699 -1856
- autocoder/common/v2/agent/agentic_edit_change_manager.py +474 -0
- autocoder/common/v2/agent/agentic_edit_tools/__init__.py +35 -1
- autocoder/common/v2/agent/agentic_edit_tools/ac_mod_list_tool_resolver.py +279 -0
- autocoder/common/v2/agent/agentic_edit_tools/ac_mod_write_tool_resolver.py +10 -1
- autocoder/common/v2/agent/agentic_edit_tools/background_task_tool_resolver.py +1167 -0
- autocoder/common/v2/agent/agentic_edit_tools/base_tool_resolver.py +2 -2
- autocoder/common/v2/agent/agentic_edit_tools/conversation_message_ids_read_tool_resolver.py +214 -0
- autocoder/common/v2/agent/agentic_edit_tools/conversation_message_ids_write_tool_resolver.py +299 -0
- autocoder/common/v2/agent/agentic_edit_tools/count_tokens_tool_resolver.py +290 -0
- autocoder/common/v2/agent/agentic_edit_tools/execute_command_tool_resolver.py +564 -29
- autocoder/common/v2/agent/agentic_edit_tools/execute_workflow_tool_resolver.py +485 -0
- autocoder/common/v2/agent/agentic_edit_tools/extract_to_text_tool_resolver.py +225 -0
- autocoder/common/v2/agent/agentic_edit_tools/lint_report.py +79 -0
- autocoder/common/v2/agent/agentic_edit_tools/linter_config_models.py +343 -0
- autocoder/common/v2/agent/agentic_edit_tools/linter_enabled_tool_resolver.py +189 -0
- autocoder/common/v2/agent/agentic_edit_tools/list_files_tool_resolver.py +169 -101
- autocoder/common/v2/agent/agentic_edit_tools/load_extra_document_tool_resolver.py +356 -0
- autocoder/common/v2/agent/agentic_edit_tools/read_file_tool_resolver.py +243 -50
- autocoder/common/v2/agent/agentic_edit_tools/replace_in_file_tool_resolver.py +667 -147
- autocoder/common/v2/agent/agentic_edit_tools/run_named_subagents_tool_resolver.py +691 -0
- autocoder/common/v2/agent/agentic_edit_tools/search_files_tool_resolver.py +410 -86
- autocoder/common/v2/agent/agentic_edit_tools/session_interactive_tool_resolver.py +115 -0
- autocoder/common/v2/agent/agentic_edit_tools/session_start_tool_resolver.py +190 -0
- autocoder/common/v2/agent/agentic_edit_tools/session_stop_tool_resolver.py +76 -0
- autocoder/common/v2/agent/agentic_edit_tools/test_write_to_file_tool_resolver.py +207 -192
- autocoder/common/v2/agent/agentic_edit_tools/todo_read_tool_resolver.py +80 -63
- autocoder/common/v2/agent/agentic_edit_tools/todo_write_tool_resolver.py +237 -233
- autocoder/common/v2/agent/agentic_edit_tools/use_mcp_tool_resolver.py +2 -2
- autocoder/common/v2/agent/agentic_edit_tools/web_crawl_tool_resolver.py +557 -0
- autocoder/common/v2/agent/agentic_edit_tools/web_search_tool_resolver.py +600 -0
- autocoder/common/v2/agent/agentic_edit_tools/write_to_file_tool_resolver.py +56 -121
- autocoder/common/v2/agent/agentic_edit_types.py +343 -9
- autocoder/common/v2/agent/runner/__init__.py +3 -3
- autocoder/common/v2/agent/runner/base_runner.py +12 -26
- autocoder/common/v2/agent/runner/{event_runner.py → file_based_event_runner.py} +3 -2
- autocoder/common/v2/agent/runner/sdk_runner.py +150 -8
- autocoder/common/v2/agent/runner/terminal_runner.py +170 -57
- autocoder/common/v2/agent/runner/tool_display.py +557 -159
- autocoder/common/v2/agent/test_agentic_callbacks.py +265 -0
- autocoder/common/v2/agent/test_agentic_edit.py +194 -0
- autocoder/common/v2/agent/tool_caller/__init__.py +24 -0
- autocoder/common/v2/agent/tool_caller/default_tool_resolver_map.py +135 -0
- autocoder/common/v2/agent/tool_caller/integration_test.py +172 -0
- autocoder/common/v2/agent/tool_caller/plugins/__init__.py +14 -0
- autocoder/common/v2/agent/tool_caller/plugins/base_plugin.py +126 -0
- autocoder/common/v2/agent/tool_caller/plugins/examples/__init__.py +13 -0
- autocoder/common/v2/agent/tool_caller/plugins/examples/logging_plugin.py +164 -0
- autocoder/common/v2/agent/tool_caller/plugins/examples/security_filter_plugin.py +198 -0
- autocoder/common/v2/agent/tool_caller/plugins/plugin_interface.py +141 -0
- autocoder/common/v2/agent/tool_caller/test_tool_caller.py +278 -0
- autocoder/common/v2/agent/tool_caller/tool_call_plugin_manager.py +331 -0
- autocoder/common/v2/agent/tool_caller/tool_caller.py +337 -0
- autocoder/common/v2/agent/tool_caller/usage_example.py +193 -0
- autocoder/common/v2/code_agentic_editblock_manager.py +4 -4
- autocoder/common/v2/code_auto_generate.py +136 -78
- autocoder/common/v2/code_auto_generate_diff.py +135 -79
- autocoder/common/v2/code_auto_generate_editblock.py +174 -99
- autocoder/common/v2/code_auto_generate_strict_diff.py +151 -71
- autocoder/common/v2/code_auto_merge.py +1 -1
- autocoder/common/v2/code_auto_merge_editblock.py +13 -1
- autocoder/common/v2/code_diff_manager.py +3 -3
- autocoder/common/v2/code_editblock_manager.py +4 -14
- autocoder/common/v2/code_manager.py +1 -1
- autocoder/common/v2/code_strict_diff_manager.py +2 -2
- autocoder/common/wrap_llm_hint/__init__.py +10 -0
- autocoder/common/wrap_llm_hint/test_wrap_llm_hint.py +1067 -0
- autocoder/common/wrap_llm_hint/utils.py +432 -0
- autocoder/common/wrap_llm_hint/wrap_llm_hint.py +323 -0
- autocoder/completer/__init__.py +8 -0
- autocoder/completer/command_completer_v2.py +1094 -0
- autocoder/default_project/__init__.py +501 -0
- autocoder/dispacher/__init__.py +4 -12
- autocoder/dispacher/actions/action.py +400 -129
- autocoder/dispacher/actions/plugins/action_regex_project.py +2 -2
- autocoder/index/entry.py +117 -125
- autocoder/{agent → index/filter}/agentic_filter.py +322 -333
- autocoder/index/filter/normal_filter.py +5 -11
- autocoder/index/filter/quick_filter.py +1 -1
- autocoder/index/index.py +36 -9
- autocoder/index/tests/__init__.py +1 -0
- autocoder/index/tests/run_tests.py +195 -0
- autocoder/index/tests/test_entry.py +303 -0
- autocoder/index/tests/test_index_manager.py +314 -0
- autocoder/index/tests/test_module_integration.py +300 -0
- autocoder/index/tests/test_symbols_utils.py +183 -0
- autocoder/inner/__init__.py +4 -0
- autocoder/inner/agentic.py +923 -0
- autocoder/inner/async_command_handler.py +992 -0
- autocoder/inner/conversation_command_handlers.py +623 -0
- autocoder/inner/merge_command_handler.py +213 -0
- autocoder/inner/queue_command_handler.py +684 -0
- autocoder/models.py +95 -266
- autocoder/plugins/git_helper_plugin.py +31 -29
- autocoder/plugins/token_helper_plugin.py +65 -46
- autocoder/pyproject/__init__.py +32 -29
- autocoder/rag/agentic_rag.py +215 -75
- autocoder/rag/cache/simple_cache.py +1 -2
- autocoder/rag/loaders/image_loader.py +1 -1
- autocoder/rag/long_context_rag.py +42 -26
- autocoder/rag/qa_conversation_strategy.py +1 -1
- autocoder/rag/terminal/__init__.py +17 -0
- autocoder/rag/terminal/args.py +581 -0
- autocoder/rag/terminal/bootstrap.py +61 -0
- autocoder/rag/terminal/command_handlers.py +653 -0
- autocoder/rag/terminal/formatters/__init__.py +20 -0
- autocoder/rag/terminal/formatters/base.py +70 -0
- autocoder/rag/terminal/formatters/json_format.py +66 -0
- autocoder/rag/terminal/formatters/stream_json.py +95 -0
- autocoder/rag/terminal/formatters/text.py +28 -0
- autocoder/rag/terminal/init.py +120 -0
- autocoder/rag/terminal/utils.py +106 -0
- autocoder/rag/test_agentic_rag.py +389 -0
- autocoder/rag/test_doc_filter.py +3 -3
- autocoder/rag/test_long_context_rag.py +1 -1
- autocoder/rag/test_token_limiter.py +517 -10
- autocoder/rag/token_counter.py +3 -0
- autocoder/rag/token_limiter.py +19 -15
- autocoder/rag/tools/__init__.py +26 -2
- autocoder/rag/tools/bochaai_example.py +343 -0
- autocoder/rag/tools/bochaai_sdk.py +541 -0
- autocoder/rag/tools/metaso_example.py +268 -0
- autocoder/rag/tools/metaso_sdk.py +417 -0
- autocoder/rag/tools/recall_tool.py +28 -7
- autocoder/rag/tools/run_integration_tests.py +204 -0
- autocoder/rag/tools/test_all_providers.py +318 -0
- autocoder/rag/tools/test_bochaai_integration.py +482 -0
- autocoder/rag/tools/test_final_integration.py +215 -0
- autocoder/rag/tools/test_metaso_integration.py +424 -0
- autocoder/rag/tools/test_metaso_real.py +171 -0
- autocoder/rag/tools/test_web_crawl_tool.py +639 -0
- autocoder/rag/tools/test_web_search_tool.py +509 -0
- autocoder/rag/tools/todo_read_tool.py +202 -0
- autocoder/rag/tools/todo_write_tool.py +412 -0
- autocoder/rag/tools/web_crawl_tool.py +634 -0
- autocoder/rag/tools/web_search_tool.py +558 -0
- autocoder/rag/tools/web_tools_example.py +119 -0
- autocoder/rag/types.py +16 -0
- autocoder/rag/variable_holder.py +4 -2
- autocoder/rags.py +86 -79
- autocoder/regexproject/__init__.py +23 -21
- autocoder/sdk/__init__.py +46 -190
- autocoder/sdk/api.py +370 -0
- autocoder/sdk/async_runner/__init__.py +26 -0
- autocoder/sdk/async_runner/async_executor.py +650 -0
- autocoder/sdk/async_runner/async_handler.py +356 -0
- autocoder/sdk/async_runner/markdown_processor.py +595 -0
- autocoder/sdk/async_runner/task_metadata.py +284 -0
- autocoder/sdk/async_runner/worktree_manager.py +438 -0
- autocoder/sdk/cli/__init__.py +2 -5
- autocoder/sdk/cli/formatters.py +28 -204
- autocoder/sdk/cli/handlers.py +77 -44
- autocoder/sdk/cli/main.py +154 -171
- autocoder/sdk/cli/options.py +95 -22
- autocoder/sdk/constants.py +139 -51
- autocoder/sdk/core/auto_coder_core.py +484 -109
- autocoder/sdk/core/bridge.py +297 -115
- autocoder/sdk/exceptions.py +18 -12
- autocoder/sdk/formatters/__init__.py +19 -0
- autocoder/sdk/formatters/input.py +64 -0
- autocoder/sdk/formatters/output.py +247 -0
- autocoder/sdk/formatters/stream.py +54 -0
- autocoder/sdk/models/__init__.py +6 -5
- autocoder/sdk/models/options.py +55 -18
- autocoder/sdk/utils/formatters.py +27 -195
- autocoder/suffixproject/__init__.py +28 -25
- autocoder/terminal/__init__.py +14 -0
- autocoder/terminal/app.py +454 -0
- autocoder/terminal/args.py +32 -0
- autocoder/terminal/bootstrap.py +178 -0
- autocoder/terminal/command_processor.py +521 -0
- autocoder/terminal/command_registry.py +57 -0
- autocoder/terminal/help.py +97 -0
- autocoder/terminal/tasks/__init__.py +5 -0
- autocoder/terminal/tasks/background.py +77 -0
- autocoder/terminal/tasks/task_event.py +70 -0
- autocoder/terminal/ui/__init__.py +13 -0
- autocoder/terminal/ui/completer.py +268 -0
- autocoder/terminal/ui/keybindings.py +75 -0
- autocoder/terminal/ui/session.py +41 -0
- autocoder/terminal/ui/toolbar.py +64 -0
- autocoder/terminal/utils/__init__.py +13 -0
- autocoder/terminal/utils/errors.py +18 -0
- autocoder/terminal/utils/paths.py +19 -0
- autocoder/terminal/utils/shell.py +43 -0
- autocoder/terminal_v3/__init__.py +10 -0
- autocoder/terminal_v3/app.py +201 -0
- autocoder/terminal_v3/handlers/__init__.py +5 -0
- autocoder/terminal_v3/handlers/command_handler.py +131 -0
- autocoder/terminal_v3/models/__init__.py +6 -0
- autocoder/terminal_v3/models/conversation_buffer.py +214 -0
- autocoder/terminal_v3/models/message.py +50 -0
- autocoder/terminal_v3/models/tool_display.py +247 -0
- autocoder/terminal_v3/ui/__init__.py +7 -0
- autocoder/terminal_v3/ui/keybindings.py +56 -0
- autocoder/terminal_v3/ui/layout.py +141 -0
- autocoder/terminal_v3/ui/styles.py +43 -0
- autocoder/tsproject/__init__.py +23 -23
- autocoder/utils/auto_coder_utils/chat_stream_out.py +1 -1
- autocoder/utils/llms.py +88 -80
- autocoder/utils/math_utils.py +101 -0
- autocoder/utils/model_provider_selector.py +16 -4
- autocoder/utils/operate_config_api.py +33 -5
- autocoder/utils/thread_utils.py +2 -2
- autocoder/version.py +4 -2
- autocoder/workflow_agents/__init__.py +84 -0
- autocoder/workflow_agents/agent.py +143 -0
- autocoder/workflow_agents/exceptions.py +573 -0
- autocoder/workflow_agents/executor.py +665 -0
- autocoder/workflow_agents/loader.py +749 -0
- autocoder/workflow_agents/runner.py +267 -0
- autocoder/workflow_agents/types.py +173 -0
- autocoder/workflow_agents/utils.py +434 -0
- autocoder/workflow_agents/workflow_manager.py +211 -0
- auto_coder-1.0.0.dist-info/METADATA +0 -396
- auto_coder-1.0.0.dist-info/RECORD +0 -442
- auto_coder-1.0.0.dist-info/licenses/LICENSE +0 -201
- autocoder/auto_coder_server.py +0 -672
- autocoder/benchmark.py +0 -138
- autocoder/common/ac_style_command_parser/example.py +0 -7
- autocoder/common/cleaner.py +0 -31
- autocoder/common/command_completer_v2.py +0 -615
- autocoder/common/context_pruner.py +0 -477
- autocoder/common/conversation_pruner.py +0 -132
- autocoder/common/directory_cache/__init__.py +0 -1
- autocoder/common/directory_cache/cache.py +0 -192
- autocoder/common/directory_cache/test_cache.py +0 -190
- autocoder/common/file_checkpoint/examples.py +0 -217
- autocoder/common/llm_friendly_package_example.py +0 -138
- autocoder/common/llm_friendly_package_test.py +0 -63
- autocoder/common/pull_requests/test_module.py +0 -1
- autocoder/common/rulefiles/autocoderrules_utils.py +0 -484
- autocoder/common/text.py +0 -30
- autocoder/common/v2/agent/agentic_edit_tools/list_package_info_tool_resolver.py +0 -42
- autocoder/common/v2/agent/agentic_edit_tools/test_execute_command_tool_resolver.py +0 -70
- autocoder/common/v2/agent/agentic_edit_tools/test_search_files_tool_resolver.py +0 -163
- autocoder/common/v2/agent/agentic_tool_display.py +0 -183
- autocoder/plugins/dynamic_completion_example.py +0 -148
- autocoder/plugins/sample_plugin.py +0 -160
- autocoder/sdk/cli/__main__.py +0 -26
- autocoder/sdk/cli/completion_wrapper.py +0 -38
- autocoder/sdk/cli/install_completion.py +0 -301
- autocoder/sdk/models/messages.py +0 -209
- autocoder/sdk/session/__init__.py +0 -32
- autocoder/sdk/session/session.py +0 -106
- autocoder/sdk/session/session_manager.py +0 -56
- {auto_coder-1.0.0.dist-info → auto_coder-2.0.1.dist-info}/top_level.txt +0 -0
- /autocoder/{sdk/example.py → common/agent_query_queue/__init__.py} +0 -0
|
@@ -2,131 +2,455 @@ import os
|
|
|
2
2
|
import re
|
|
3
3
|
import glob
|
|
4
4
|
from typing import Dict, Any, Optional, List, Union
|
|
5
|
+
|
|
6
|
+
from pydantic import BaseModel, Field
|
|
5
7
|
from autocoder.common.v2.agent.agentic_edit_tools.base_tool_resolver import BaseToolResolver
|
|
6
|
-
# Import ToolResult from types
|
|
7
8
|
from autocoder.common.v2.agent.agentic_edit_types import SearchFilesTool, ToolResult
|
|
8
|
-
from loguru import logger
|
|
9
9
|
from autocoder.common import AutoCoderArgs
|
|
10
|
+
from autocoder.common.ignorefiles.ignore_file_utils import should_ignore
|
|
11
|
+
from loguru import logger
|
|
10
12
|
import typing
|
|
13
|
+
import json
|
|
11
14
|
|
|
12
|
-
|
|
15
|
+
# Import token counter and wrap_llm_hint modules
|
|
16
|
+
from autocoder.common.tokens import count_string_tokens
|
|
17
|
+
from autocoder.common.wrap_llm_hint.utils import add_hint_to_text
|
|
13
18
|
|
|
14
19
|
if typing.TYPE_CHECKING:
|
|
15
20
|
from autocoder.common.v2.agent.agentic_edit import AgenticEdit
|
|
16
21
|
|
|
17
22
|
|
|
23
|
+
class SearchParameters(BaseModel):
|
|
24
|
+
"""Strongly typed search parameters for file searching operations.
|
|
25
|
+
|
|
26
|
+
This class ensures type safety and validation for all search-related parameters.
|
|
27
|
+
"""
|
|
28
|
+
search_path_str: str = Field(..., description="Original search path string for error messages")
|
|
29
|
+
regex_pattern: str = Field(..., description="Regular expression pattern to search for")
|
|
30
|
+
file_pattern: str = Field(..., description="Glob pattern for file filtering (e.g., '*.py')")
|
|
31
|
+
source_dir: str = Field(..., description="Source directory path")
|
|
32
|
+
absolute_source_dir: str = Field(..., description="Absolute path to source directory")
|
|
33
|
+
absolute_search_path: str = Field(..., description="Absolute path to search directory")
|
|
34
|
+
|
|
35
|
+
class Config:
|
|
36
|
+
"""Pydantic configuration."""
|
|
37
|
+
frozen = True # Make the class immutable
|
|
38
|
+
extra = "forbid" # Prevent extra fields
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
class SearchErrorInfo(BaseModel):
|
|
42
|
+
"""Information about errors encountered during search operations."""
|
|
43
|
+
file_path: str = Field(..., description="Path to the file/directory that caused the error")
|
|
44
|
+
error_type: str = Field(..., description="Type of error (e.g., 'PermissionError', 'FileNotFoundError')")
|
|
45
|
+
error_message: str = Field(..., description="Detailed error message")
|
|
46
|
+
|
|
47
|
+
class Config:
|
|
48
|
+
"""Pydantic configuration."""
|
|
49
|
+
frozen = True
|
|
50
|
+
extra = "forbid"
|
|
51
|
+
|
|
52
|
+
|
|
53
|
+
class SearchMatchInfo(BaseModel):
|
|
54
|
+
"""Information about a single search match."""
|
|
55
|
+
path: str = Field(..., description="Relative path to the file containing the match")
|
|
56
|
+
line_number: int = Field(..., description="Line number where the match was found (1-indexed)")
|
|
57
|
+
match_line: str = Field(..., description="The line content that matched the pattern")
|
|
58
|
+
context: str = Field(..., description="Context lines around the match")
|
|
59
|
+
|
|
60
|
+
class Config:
|
|
61
|
+
"""Pydantic configuration."""
|
|
62
|
+
frozen = True
|
|
63
|
+
extra = "forbid"
|
|
64
|
+
|
|
65
|
+
|
|
66
|
+
class SearchResultContent(BaseModel):
|
|
67
|
+
"""Content structure for search operation results."""
|
|
68
|
+
matches: List[SearchMatchInfo] = Field(..., description="List of search matches found")
|
|
69
|
+
errors: List[SearchErrorInfo] = Field(..., description="List of errors encountered during search")
|
|
70
|
+
|
|
71
|
+
class Config:
|
|
72
|
+
"""Pydantic configuration."""
|
|
73
|
+
frozen = True
|
|
74
|
+
extra = "forbid"
|
|
75
|
+
|
|
76
|
+
|
|
18
77
|
class SearchFilesToolResolver(BaseToolResolver):
|
|
78
|
+
"""Resolver for searching files with regex patterns.
|
|
79
|
+
|
|
80
|
+
This class provides functionality to search for text patterns within files
|
|
81
|
+
using regular expressions, with support for file pattern filtering and
|
|
82
|
+
security checks to prevent access outside the project directory.
|
|
83
|
+
"""
|
|
84
|
+
|
|
85
|
+
# Constants for search configuration
|
|
86
|
+
MAX_SEARCH_RESULTS = 200
|
|
87
|
+
CONTEXT_LINES_BEFORE = 2
|
|
88
|
+
CONTEXT_LINES_AFTER = 3
|
|
89
|
+
DEFAULT_FILE_PATTERN = "*"
|
|
90
|
+
DEFAULT_SOURCE_DIR = "."
|
|
91
|
+
|
|
19
92
|
def __init__(self, agent: Optional['AgenticEdit'], tool: SearchFilesTool, args: AutoCoderArgs):
|
|
93
|
+
"""Initialize the search files tool resolver.
|
|
94
|
+
|
|
95
|
+
Args:
|
|
96
|
+
agent: Optional AgenticEdit instance
|
|
97
|
+
tool: SearchFilesTool configuration
|
|
98
|
+
args: AutoCoder arguments containing source directory
|
|
99
|
+
"""
|
|
20
100
|
super().__init__(agent, tool, args)
|
|
21
101
|
self.tool: SearchFilesTool = tool
|
|
22
|
-
self.shadow_manager = self.agent.shadow_manager if self.agent else None
|
|
23
102
|
|
|
24
|
-
def search_in_dir(self, base_dir: str, regex_pattern: str, file_pattern: str,
|
|
25
|
-
|
|
103
|
+
def search_in_dir(self, base_dir: str, regex_pattern: str, file_pattern: str,
|
|
104
|
+
source_dir: str, is_shadow: bool = False,
|
|
105
|
+
compiled_regex: Optional[re.Pattern] = None) -> tuple[List[SearchMatchInfo], List[SearchErrorInfo]]:
|
|
106
|
+
"""Search for regex patterns in files within a directory.
|
|
107
|
+
|
|
108
|
+
Args:
|
|
109
|
+
base_dir: Directory to search in
|
|
110
|
+
regex_pattern: Regular expression pattern to search for
|
|
111
|
+
file_pattern: Glob pattern for file filtering (e.g., '*.py')
|
|
112
|
+
source_dir: Source directory for calculating relative paths
|
|
113
|
+
is_shadow: Whether this is a shadow directory search (legacy parameter)
|
|
114
|
+
compiled_regex: Pre-compiled regex pattern for efficiency
|
|
115
|
+
|
|
116
|
+
Returns:
|
|
117
|
+
Tuple of (search match objects, error information list)
|
|
118
|
+
"""
|
|
26
119
|
search_results = []
|
|
120
|
+
errors = []
|
|
27
121
|
search_glob_pattern = os.path.join(base_dir, "**", file_pattern)
|
|
28
122
|
|
|
29
123
|
logger.info(
|
|
30
|
-
f"Searching for regex '{regex_pattern}' in files matching '{file_pattern}'
|
|
124
|
+
f"Searching for regex '{regex_pattern}' in files matching '{file_pattern}' "
|
|
125
|
+
f"under '{base_dir}' (shadow: {is_shadow}) with ignore rules applied."
|
|
126
|
+
)
|
|
31
127
|
|
|
32
128
|
if compiled_regex is None:
|
|
33
129
|
compiled_regex = re.compile(regex_pattern)
|
|
34
130
|
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
131
|
+
try:
|
|
132
|
+
matching_files = glob.glob(search_glob_pattern, recursive=True)
|
|
133
|
+
except (PermissionError, OSError) as e:
|
|
134
|
+
error_info = SearchErrorInfo(
|
|
135
|
+
file_path=base_dir,
|
|
136
|
+
error_type=type(e).__name__,
|
|
137
|
+
error_message=f"Cannot access directory for glob search: {str(e)}"
|
|
138
|
+
)
|
|
139
|
+
errors.append(error_info)
|
|
140
|
+
logger.warning(f"Cannot access directory {base_dir}: {e}")
|
|
141
|
+
return search_results, errors
|
|
142
|
+
|
|
143
|
+
for filepath in matching_files:
|
|
144
|
+
if not self._should_process_file(filepath):
|
|
38
145
|
continue
|
|
146
|
+
|
|
147
|
+
file_matches, file_errors = self._search_in_file_with_errors(filepath, compiled_regex, source_dir)
|
|
148
|
+
search_results.extend(file_matches)
|
|
149
|
+
errors.extend(file_errors)
|
|
39
150
|
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
151
|
+
return search_results, errors
|
|
152
|
+
|
|
153
|
+
def _should_process_file(self, filepath: str) -> bool:
|
|
154
|
+
"""Check if a file should be processed for searching.
|
|
155
|
+
|
|
156
|
+
Args:
|
|
157
|
+
filepath: Path to the file to check
|
|
158
|
+
|
|
159
|
+
Returns:
|
|
160
|
+
True if the file should be processed, False otherwise
|
|
161
|
+
"""
|
|
162
|
+
abs_path = os.path.abspath(filepath)
|
|
163
|
+
return os.path.isfile(filepath) and not should_ignore(abs_path)
|
|
164
|
+
|
|
165
|
+
def _search_in_file(self, filepath: str, compiled_regex: re.Pattern,
|
|
166
|
+
source_dir: str) -> List[SearchMatchInfo]:
|
|
167
|
+
"""Search for regex matches within a single file.
|
|
168
|
+
|
|
169
|
+
Args:
|
|
170
|
+
filepath: Path to the file to search
|
|
171
|
+
compiled_regex: Compiled regular expression pattern
|
|
172
|
+
source_dir: Source directory for calculating relative paths
|
|
173
|
+
|
|
174
|
+
Returns:
|
|
175
|
+
List of SearchMatchInfo objects for this file
|
|
176
|
+
"""
|
|
177
|
+
file_matches, _ = self._search_in_file_with_errors(filepath, compiled_regex, source_dir)
|
|
178
|
+
return file_matches
|
|
179
|
+
|
|
180
|
+
def _search_in_file_with_errors(self, filepath: str, compiled_regex: re.Pattern,
|
|
181
|
+
source_dir: str) -> tuple[List[SearchMatchInfo], List[SearchErrorInfo]]:
|
|
182
|
+
"""Search for regex matches within a single file, collecting errors.
|
|
183
|
+
|
|
184
|
+
Args:
|
|
185
|
+
filepath: Path to the file to search
|
|
186
|
+
compiled_regex: Compiled regular expression pattern
|
|
187
|
+
source_dir: Source directory for calculating relative paths
|
|
188
|
+
|
|
189
|
+
Returns:
|
|
190
|
+
Tuple of (SearchMatchInfo objects, error information list)
|
|
191
|
+
"""
|
|
192
|
+
file_matches = []
|
|
193
|
+
errors = []
|
|
194
|
+
|
|
195
|
+
try:
|
|
196
|
+
with open(filepath, 'r', encoding='utf-8', errors='replace') as f:
|
|
197
|
+
lines = f.readlines()
|
|
198
|
+
|
|
199
|
+
for line_index, line in enumerate(lines):
|
|
200
|
+
if compiled_regex.search(line):
|
|
201
|
+
match_info = self._create_match_info(
|
|
202
|
+
filepath, line_index, line, lines, source_dir
|
|
203
|
+
)
|
|
204
|
+
file_matches.append(match_info)
|
|
205
|
+
|
|
206
|
+
except (PermissionError, OSError, UnicodeDecodeError) as e:
|
|
207
|
+
error_info = SearchErrorInfo(
|
|
208
|
+
file_path=filepath,
|
|
209
|
+
error_type=type(e).__name__,
|
|
210
|
+
error_message=f"Cannot read file: {str(e)}"
|
|
211
|
+
)
|
|
212
|
+
errors.append(error_info)
|
|
213
|
+
logger.warning(f"Could not read or process file {filepath}: {e}")
|
|
214
|
+
except Exception as e:
|
|
215
|
+
error_info = SearchErrorInfo(
|
|
216
|
+
file_path=filepath,
|
|
217
|
+
error_type=type(e).__name__,
|
|
218
|
+
error_message=f"Unexpected error: {str(e)}"
|
|
219
|
+
)
|
|
220
|
+
errors.append(error_info)
|
|
221
|
+
logger.warning(f"Unexpected error processing file {filepath}: {e}")
|
|
222
|
+
|
|
223
|
+
return file_matches, errors
|
|
224
|
+
|
|
225
|
+
def _create_match_info(self, filepath: str, line_index: int, line: str,
|
|
226
|
+
all_lines: List[str], source_dir: str) -> SearchMatchInfo:
|
|
227
|
+
"""Create a match information object.
|
|
228
|
+
|
|
229
|
+
Args:
|
|
230
|
+
filepath: Path to the file containing the match
|
|
231
|
+
line_index: Zero-based index of the matching line
|
|
232
|
+
line: The matching line content
|
|
233
|
+
all_lines: All lines in the file for context
|
|
234
|
+
source_dir: Source directory for calculating relative paths
|
|
235
|
+
|
|
236
|
+
Returns:
|
|
237
|
+
SearchMatchInfo object containing match information
|
|
238
|
+
"""
|
|
239
|
+
context_start = max(0, line_index - self.CONTEXT_LINES_BEFORE)
|
|
240
|
+
context_end = min(len(all_lines), line_index + self.CONTEXT_LINES_AFTER)
|
|
241
|
+
|
|
242
|
+
context_lines = [
|
|
243
|
+
f"{j + 1}: {all_lines[j]}"
|
|
244
|
+
for j in range(context_start, context_end)
|
|
245
|
+
]
|
|
246
|
+
context = "".join(context_lines)
|
|
247
|
+
|
|
248
|
+
relative_path = os.path.relpath(filepath, source_dir)
|
|
249
|
+
|
|
250
|
+
return SearchMatchInfo(
|
|
251
|
+
path=relative_path,
|
|
252
|
+
line_number=line_index + 1,
|
|
253
|
+
match_line=line.strip(),
|
|
254
|
+
context=context.strip()
|
|
255
|
+
)
|
|
82
256
|
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
257
|
+
def search_files_normal(self, search_path_str: str, regex_pattern: str,
|
|
258
|
+
file_pattern: str, source_dir: str,
|
|
259
|
+
absolute_source_dir: str, absolute_search_path: str) -> Union[ToolResult, tuple[List[SearchMatchInfo], List[SearchErrorInfo]]]:
|
|
260
|
+
"""Search files directly in the specified directory or file.
|
|
261
|
+
|
|
262
|
+
Args:
|
|
263
|
+
search_path_str: Original search path string (for error messages)
|
|
264
|
+
regex_pattern: Regular expression pattern to search for
|
|
265
|
+
file_pattern: Glob pattern for file filtering
|
|
266
|
+
source_dir: Source directory path
|
|
267
|
+
absolute_source_dir: Absolute path to source directory
|
|
268
|
+
absolute_search_path: Absolute path to search directory or file
|
|
269
|
+
|
|
270
|
+
Returns:
|
|
271
|
+
ToolResult on error, or tuple of (SearchMatchInfo objects, error information) on success
|
|
272
|
+
"""
|
|
273
|
+
# Perform security and validation checks
|
|
274
|
+
validation_result = self._validate_search_path(
|
|
275
|
+
search_path_str, absolute_source_dir, absolute_search_path
|
|
276
|
+
)
|
|
277
|
+
if validation_result:
|
|
278
|
+
return validation_result
|
|
88
279
|
|
|
89
280
|
try:
|
|
90
281
|
compiled_regex = re.compile(regex_pattern)
|
|
91
|
-
|
|
92
|
-
#
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
282
|
+
|
|
283
|
+
# Check if the path is a file or directory
|
|
284
|
+
if os.path.isfile(absolute_search_path):
|
|
285
|
+
# Search in single file
|
|
286
|
+
logger.info(f"Searching for regex '{regex_pattern}' in file '{absolute_search_path}'")
|
|
287
|
+
if not self._should_process_file(absolute_search_path):
|
|
288
|
+
return [], []
|
|
289
|
+
search_results, errors = self._search_in_file_with_errors(absolute_search_path, compiled_regex, source_dir)
|
|
290
|
+
else:
|
|
291
|
+
# Search in directory
|
|
292
|
+
search_results, errors = self.search_in_dir(
|
|
293
|
+
absolute_search_path, regex_pattern, file_pattern,
|
|
294
|
+
source_dir, is_shadow=False, compiled_regex=compiled_regex
|
|
295
|
+
)
|
|
296
|
+
|
|
297
|
+
return search_results, errors
|
|
97
298
|
|
|
98
299
|
except re.error as e:
|
|
300
|
+
error_msg = f"Invalid regex pattern: {e}"
|
|
99
301
|
logger.error(f"Invalid regex pattern '{regex_pattern}': {e}")
|
|
100
|
-
return ToolResult(success=False, message=
|
|
302
|
+
return ToolResult(success=False, message=error_msg)
|
|
303
|
+
|
|
101
304
|
except Exception as e:
|
|
305
|
+
error_msg = f"An unexpected error occurred during search: {str(e)}"
|
|
102
306
|
logger.error(f"Error during file search: {str(e)}")
|
|
103
|
-
return ToolResult(success=False, message=
|
|
307
|
+
return ToolResult(success=False, message=error_msg)
|
|
308
|
+
|
|
309
|
+
def _validate_search_path(self, search_path_str: str, absolute_source_dir: str,
|
|
310
|
+
absolute_search_path: str) -> Optional[ToolResult]:
|
|
311
|
+
"""Validate the search path for security and existence.
|
|
312
|
+
|
|
313
|
+
Args:
|
|
314
|
+
search_path_str: Original search path string (for error messages)
|
|
315
|
+
absolute_source_dir: Absolute path to source directory
|
|
316
|
+
absolute_search_path: Absolute path to search directory or file
|
|
317
|
+
|
|
318
|
+
Returns:
|
|
319
|
+
ToolResult with error if validation fails, None if validation passes
|
|
320
|
+
"""
|
|
321
|
+
# Security check: prevent access outside project directory
|
|
322
|
+
if not absolute_search_path.startswith(absolute_source_dir):
|
|
323
|
+
return ToolResult(
|
|
324
|
+
success=False,
|
|
325
|
+
message=f"Error: Access denied. Attempted to search outside the project directory: {search_path_str}"
|
|
326
|
+
)
|
|
327
|
+
|
|
328
|
+
# Check if path exists
|
|
329
|
+
if not os.path.exists(absolute_search_path):
|
|
330
|
+
return ToolResult(
|
|
331
|
+
success=False,
|
|
332
|
+
message=f"Error: Search path not found: {search_path_str}"
|
|
333
|
+
)
|
|
334
|
+
|
|
335
|
+
return None
|
|
104
336
|
|
|
105
337
|
def resolve(self) -> ToolResult:
|
|
106
|
-
"""Resolve the search files tool by
|
|
338
|
+
"""Resolve the search files tool by executing the search operation.
|
|
339
|
+
|
|
340
|
+
Returns:
|
|
341
|
+
ToolResult containing search results or error information
|
|
342
|
+
"""
|
|
343
|
+
search_params = self._extract_search_parameters()
|
|
344
|
+
|
|
345
|
+
result = self.search_files_normal(
|
|
346
|
+
search_params.search_path_str,
|
|
347
|
+
search_params.regex_pattern,
|
|
348
|
+
search_params.file_pattern,
|
|
349
|
+
search_params.source_dir,
|
|
350
|
+
search_params.absolute_source_dir,
|
|
351
|
+
search_params.absolute_search_path
|
|
352
|
+
)
|
|
353
|
+
|
|
354
|
+
return self._format_search_result(result)
|
|
355
|
+
|
|
356
|
+
def _extract_search_parameters(self) -> SearchParameters:
|
|
357
|
+
"""Extract and prepare search parameters from tool configuration.
|
|
358
|
+
|
|
359
|
+
Returns:
|
|
360
|
+
SearchParameters instance with strongly typed parameters
|
|
361
|
+
"""
|
|
107
362
|
search_path_str = self.tool.path
|
|
108
363
|
regex_pattern = self.tool.regex
|
|
109
|
-
file_pattern = self.tool.file_pattern or
|
|
110
|
-
source_dir = self.args.source_dir or
|
|
364
|
+
file_pattern = self.tool.file_pattern or self.DEFAULT_FILE_PATTERN
|
|
365
|
+
source_dir = self.args.source_dir or self.DEFAULT_SOURCE_DIR
|
|
111
366
|
absolute_source_dir = os.path.abspath(source_dir)
|
|
112
367
|
absolute_search_path = os.path.abspath(
|
|
113
|
-
os.path.join(source_dir, search_path_str)
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
368
|
+
os.path.join(source_dir, search_path_str)
|
|
369
|
+
)
|
|
370
|
+
|
|
371
|
+
return SearchParameters(
|
|
372
|
+
search_path_str=search_path_str,
|
|
373
|
+
regex_pattern=regex_pattern,
|
|
374
|
+
file_pattern=file_pattern,
|
|
375
|
+
source_dir=source_dir,
|
|
376
|
+
absolute_source_dir=absolute_source_dir,
|
|
377
|
+
absolute_search_path=absolute_search_path
|
|
378
|
+
)
|
|
379
|
+
|
|
380
|
+
def _format_search_result(self, result: Union[ToolResult, tuple[List[SearchMatchInfo], List[SearchErrorInfo]]]) -> ToolResult:
|
|
381
|
+
"""Format the search result into a standardized ToolResult.
|
|
382
|
+
|
|
383
|
+
Args:
|
|
384
|
+
result: Raw search result (either ToolResult or tuple of SearchMatchInfo objects and errors)
|
|
385
|
+
|
|
386
|
+
Returns:
|
|
387
|
+
Formatted ToolResult
|
|
388
|
+
"""
|
|
389
|
+
# If result is already a ToolResult (error case), return it directly
|
|
390
|
+
if isinstance(result, ToolResult):
|
|
391
|
+
return result
|
|
392
|
+
|
|
393
|
+
# Handle successful search results (tuple of matches and errors)
|
|
394
|
+
search_results, errors = result
|
|
395
|
+
total_results = len(search_results)
|
|
396
|
+
total_errors = len(errors)
|
|
397
|
+
|
|
398
|
+
# Prepare error summary for message
|
|
399
|
+
error_summary = ""
|
|
400
|
+
if total_errors > 0:
|
|
401
|
+
error_types = {}
|
|
402
|
+
for error in errors:
|
|
403
|
+
error_types[error.error_type] = error_types.get(error.error_type, 0) + 1
|
|
404
|
+
error_summary = f" Encountered {total_errors} errors: " + ", ".join([f"{count} {error_type}" for error_type, count in error_types.items()])
|
|
405
|
+
|
|
406
|
+
# Prepare content with both results and errors using Pydantic model
|
|
407
|
+
truncated_matches = search_results[:self.MAX_SEARCH_RESULTS] if total_results > self.MAX_SEARCH_RESULTS else search_results
|
|
408
|
+
content_model = SearchResultContent(
|
|
409
|
+
matches=truncated_matches,
|
|
410
|
+
errors=errors
|
|
411
|
+
)
|
|
412
|
+
content = content_model.model_dump()
|
|
413
|
+
|
|
414
|
+
# Convert content to JSON string to count tokens
|
|
415
|
+
content_str = json.dumps(content, ensure_ascii=False, indent=2)
|
|
416
|
+
token_count = count_string_tokens(content_str)
|
|
417
|
+
|
|
418
|
+
# Check if content exceeds 5k tokens
|
|
419
|
+
MAX_TOKENS = 5000
|
|
420
|
+
if token_count > MAX_TOKENS:
|
|
421
|
+
# Truncate to first 1000 characters
|
|
422
|
+
truncated_content_str = content_str[:1000]
|
|
423
|
+
|
|
424
|
+
# Add hint about truncation
|
|
425
|
+
hint_message = "Search results truncated due to exceeding 5k tokens. Try narrowing your search by using more specific regex patterns or file patterns to reduce output."
|
|
426
|
+
truncated_content_str = add_hint_to_text(truncated_content_str, hint_message)
|
|
427
|
+
|
|
428
|
+
# Log the truncation
|
|
429
|
+
logger.warning(f"Search results truncated from {token_count} tokens to first 1000 characters")
|
|
430
|
+
|
|
431
|
+
# Create truncation message
|
|
432
|
+
if total_results > self.MAX_SEARCH_RESULTS:
|
|
433
|
+
message = (
|
|
434
|
+
f"Search completed. Found {total_results} matches (showing first {self.MAX_SEARCH_RESULTS}), "
|
|
435
|
+
f"but results were truncated due to size (original: {token_count} tokens).{error_summary}"
|
|
436
|
+
)
|
|
127
437
|
else:
|
|
128
|
-
message =
|
|
129
|
-
|
|
130
|
-
|
|
438
|
+
message = (
|
|
439
|
+
f"Search completed. Found {total_results} matches, "
|
|
440
|
+
f"but results were truncated due to size (original: {token_count} tokens).{error_summary}"
|
|
441
|
+
)
|
|
442
|
+
|
|
443
|
+
return ToolResult(success=True, message=message, content=truncated_content_str)
|
|
444
|
+
|
|
445
|
+
# Normal case - content within token limit
|
|
446
|
+
if total_results > self.MAX_SEARCH_RESULTS:
|
|
447
|
+
message = (
|
|
448
|
+
f"Search completed. Found {total_results} matches, "
|
|
449
|
+
f"showing only the first {self.MAX_SEARCH_RESULTS}.{error_summary}"
|
|
450
|
+
)
|
|
451
|
+
logger.info(message)
|
|
452
|
+
return ToolResult(success=True, message=message, content=content)
|
|
131
453
|
else:
|
|
132
|
-
|
|
454
|
+
message = f"Search completed. Found {total_results} matches.{error_summary}"
|
|
455
|
+
logger.info(message)
|
|
456
|
+
return ToolResult(success=True, message=message, content=content)
|
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Session interactive tool resolver for interacting with active sessions.
|
|
3
|
+
"""
|
|
4
|
+
|
|
5
|
+
from typing import Optional
|
|
6
|
+
from loguru import logger
|
|
7
|
+
|
|
8
|
+
from autocoder.common.v2.agent.agentic_edit_tools.base_tool_resolver import BaseToolResolver
|
|
9
|
+
from autocoder.common.v2.agent.agentic_edit_types import SessionInteractiveTool, ToolResult
|
|
10
|
+
from autocoder.common.shell_commands import get_session_manager
|
|
11
|
+
from autocoder.common import AutoCoderArgs
|
|
12
|
+
|
|
13
|
+
import typing
|
|
14
|
+
if typing.TYPE_CHECKING:
|
|
15
|
+
from autocoder.common.v2.agent.agentic_edit import AgenticEdit
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
class SessionInteractiveToolResolver(BaseToolResolver):
|
|
19
|
+
"""Resolver for interacting with active command sessions."""
|
|
20
|
+
|
|
21
|
+
def __init__(self, agent: Optional['AgenticEdit'], tool: SessionInteractiveTool, args: AutoCoderArgs):
|
|
22
|
+
super().__init__(agent, tool, args)
|
|
23
|
+
self.tool: SessionInteractiveTool = tool
|
|
24
|
+
self.session_manager = get_session_manager()
|
|
25
|
+
|
|
26
|
+
def resolve(self) -> ToolResult:
|
|
27
|
+
"""
|
|
28
|
+
Send input to a session and read output.
|
|
29
|
+
|
|
30
|
+
Returns:
|
|
31
|
+
ToolResult with session output
|
|
32
|
+
"""
|
|
33
|
+
session_id = self.tool.session_id
|
|
34
|
+
input_text = self.tool.input
|
|
35
|
+
read_timeout = self.tool.read_timeout
|
|
36
|
+
max_bytes = self.tool.max_bytes
|
|
37
|
+
expect_prompt = self.tool.expect_prompt
|
|
38
|
+
prompt_regex = self.tool.prompt_regex
|
|
39
|
+
|
|
40
|
+
logger.debug(
|
|
41
|
+
f"Sending input to session {session_id}: {input_text[:50]}...")
|
|
42
|
+
|
|
43
|
+
# Send input to session
|
|
44
|
+
result = self.session_manager.send_input(
|
|
45
|
+
session_id=session_id,
|
|
46
|
+
input_text=input_text,
|
|
47
|
+
read_timeout=read_timeout,
|
|
48
|
+
max_bytes=max_bytes,
|
|
49
|
+
expect_prompt=expect_prompt,
|
|
50
|
+
prompt_regex=prompt_regex
|
|
51
|
+
)
|
|
52
|
+
|
|
53
|
+
if result.success:
|
|
54
|
+
# Handle both dict and string content
|
|
55
|
+
output = ''
|
|
56
|
+
raw_output = ''
|
|
57
|
+
cleaned_length = 0
|
|
58
|
+
|
|
59
|
+
if isinstance(result.content, dict):
|
|
60
|
+
output = result.content.get('output', '')
|
|
61
|
+
raw_output = result.content.get('raw_output', '')
|
|
62
|
+
cleaned_length = result.content.get('cleaned_length', 0)
|
|
63
|
+
elif isinstance(result.content, str):
|
|
64
|
+
output = result.content
|
|
65
|
+
raw_output = result.content
|
|
66
|
+
cleaned_length = len(result.content)
|
|
67
|
+
|
|
68
|
+
logger.debug(
|
|
69
|
+
f"Session {session_id} output: {len(output)} characters")
|
|
70
|
+
|
|
71
|
+
# Format content as readable text
|
|
72
|
+
if output.strip():
|
|
73
|
+
lines = output.strip().split('\n')
|
|
74
|
+
line_count = len(lines)
|
|
75
|
+
|
|
76
|
+
# Create formatted text output
|
|
77
|
+
formatted_content = f"""Session ID: {session_id}
|
|
78
|
+
Input: {input_text}
|
|
79
|
+
Output ({line_count} lines):
|
|
80
|
+
{'-' * 50}
|
|
81
|
+
{output}
|
|
82
|
+
{'-' * 50}
|
|
83
|
+
Status: Success - Received {line_count} lines of output"""
|
|
84
|
+
|
|
85
|
+
return ToolResult(
|
|
86
|
+
success=True,
|
|
87
|
+
message=f"Input sent successfully. Received {line_count} lines of output",
|
|
88
|
+
content=formatted_content
|
|
89
|
+
)
|
|
90
|
+
else:
|
|
91
|
+
# No output case
|
|
92
|
+
formatted_content = f"""Session ID: {session_id}
|
|
93
|
+
Input: {input_text}
|
|
94
|
+
Output: (no output)
|
|
95
|
+
Status: Success - No output received"""
|
|
96
|
+
|
|
97
|
+
return ToolResult(
|
|
98
|
+
success=True,
|
|
99
|
+
message="Input sent successfully. No output received.",
|
|
100
|
+
content=formatted_content
|
|
101
|
+
)
|
|
102
|
+
else:
|
|
103
|
+
# Error case - format as text as well
|
|
104
|
+
formatted_content = f"""Session ID: {session_id}
|
|
105
|
+
Input: {input_text}
|
|
106
|
+
Status: Error - {result.message}"""
|
|
107
|
+
|
|
108
|
+
logger.error(
|
|
109
|
+
f"Failed to interact with session {session_id}: {result.message}")
|
|
110
|
+
|
|
111
|
+
return ToolResult(
|
|
112
|
+
success=False,
|
|
113
|
+
message=result.message,
|
|
114
|
+
content=formatted_content
|
|
115
|
+
)
|