auto-coder 1.0.0__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-1.0.0.dist-info → auto_coder-2.0.0.dist-info}/WHEEL +1 -1
- {auto_coder-1.0.0.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 +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 +73 -59
- autocoder/auto_coder.py +31 -40
- autocoder/auto_coder_rag.py +11 -1084
- autocoder/auto_coder_runner.py +970 -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 +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/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 +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 +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 +349 -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 +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 +116 -124
- 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 +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 +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 +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-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.0.dist-info}/top_level.txt +0 -0
- /autocoder/{sdk/example.py → common/agent_query_queue/__init__.py} +0 -0
|
@@ -1,102 +1,70 @@
|
|
|
1
|
-
|
|
2
|
-
import pytest
|
|
3
1
|
import os
|
|
4
|
-
import
|
|
5
|
-
import json
|
|
2
|
+
import pytest
|
|
6
3
|
from unittest.mock import MagicMock, patch
|
|
7
|
-
|
|
8
|
-
from autocoder.common import AutoCoderArgs
|
|
9
|
-
from autocoder.common.v2.agent.agentic_edit_types import WriteToFileTool, ToolResult
|
|
10
|
-
from autocoder.common.v2.agent.agentic_edit_tools.write_to_file_tool_resolver import WriteToFileToolResolver
|
|
11
|
-
from autocoder.auto_coder_runner import load_tokenizer as load_tokenizer_global
|
|
12
|
-
from autocoder.utils.llms import get_single_llm
|
|
13
|
-
from autocoder.common.file_monitor.monitor import get_file_monitor, FileMonitor
|
|
14
|
-
from autocoder.common.rulefiles.autocoderrules_utils import get_rules, reset_rules_manager
|
|
4
|
+
from pathlib import Path
|
|
15
5
|
from loguru import logger
|
|
6
|
+
from autocoder.common.v2.agent.agentic_edit_tools.write_to_file_tool_resolver import WriteToFileToolResolver
|
|
7
|
+
from autocoder.common.v2.agent.agentic_edit_types import WriteToFileTool
|
|
8
|
+
from autocoder.common import AutoCoderArgs
|
|
9
|
+
from autocoder.common.file_monitor.monitor import FileMonitor
|
|
10
|
+
from autocoder.common.rulefiles import AutocoderRulesManager
|
|
11
|
+
|
|
12
|
+
|
|
16
13
|
|
|
17
|
-
# Helper to create a temporary test directory
|
|
18
14
|
@pytest.fixture(scope="function")
|
|
19
15
|
def temp_test_dir(tmp_path_factory):
|
|
20
|
-
|
|
16
|
+
"""临时测试目录"""
|
|
17
|
+
temp_dir = tmp_path_factory.mktemp("test_write_to_file_resolver")
|
|
21
18
|
logger.info(f"Created temp dir for test: {temp_dir}")
|
|
22
|
-
# Create a dummy .autocoderignore to avoid issues with default ignore patterns loading
|
|
23
|
-
# from unexpected places if the test is run from a different CWD.
|
|
24
|
-
with open(os.path.join(temp_dir, ".autocoderignore"), "w") as f:
|
|
25
|
-
f.write("# Dummy ignore file for tests\n")
|
|
26
19
|
yield temp_dir
|
|
27
20
|
logger.info(f"Cleaning up temp dir: {temp_dir}")
|
|
28
|
-
|
|
21
|
+
|
|
29
22
|
|
|
30
23
|
@pytest.fixture(scope="function")
|
|
31
24
|
def setup_file_monitor_and_rules(temp_test_dir):
|
|
32
|
-
"""
|
|
33
|
-
#
|
|
25
|
+
"""设置测试环境的文件监控和规则管理器"""
|
|
26
|
+
# 初始化 FileMonitor 单例
|
|
27
|
+
file_monitor = FileMonitor(str(temp_test_dir))
|
|
28
|
+
file_monitor.start()
|
|
29
|
+
logger.info(f"File monitor initialized with root: {temp_test_dir}")
|
|
30
|
+
|
|
31
|
+
# 初始化 AutocoderRulesManager 单例
|
|
32
|
+
rules_manager = AutocoderRulesManager(str(temp_test_dir))
|
|
33
|
+
rules_dict = rules_manager.get_rules()
|
|
34
|
+
logger.info(f"Rules loaded for dir: {temp_test_dir}, count: {len(rules_dict)}")
|
|
35
|
+
|
|
36
|
+
yield file_monitor, rules_manager
|
|
37
|
+
|
|
38
|
+
# 清理单例
|
|
39
|
+
file_monitor.stop()
|
|
34
40
|
FileMonitor.reset_instance()
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
monitor = get_file_monitor(str(temp_test_dir))
|
|
38
|
-
if not monitor.is_running():
|
|
39
|
-
monitor.start()
|
|
40
|
-
logger.info(f"File monitor initialized with root: {monitor.root_dir}")
|
|
41
|
-
|
|
42
|
-
rules = get_rules(str(temp_test_dir))
|
|
43
|
-
logger.info(f"Rules loaded for dir: {temp_test_dir}, count: {len(rules)}")
|
|
44
|
-
return str(temp_test_dir)
|
|
41
|
+
AutocoderRulesManager.reset_instance()
|
|
45
42
|
|
|
46
43
|
|
|
47
44
|
@pytest.fixture(scope="function")
|
|
48
45
|
def load_tokenizer_fixture(setup_file_monitor_and_rules):
|
|
49
|
-
"""
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
except Exception as e:
|
|
54
|
-
logger.error(f"Failed to load tokenizer: {e}")
|
|
55
|
-
# Depending on test requirements, you might want to raise an error or skip tests
|
|
56
|
-
pytest.skip(f"Skipping tests due to tokenizer loading failure: {e}")
|
|
46
|
+
"""加载分词器以确保测试稳定性"""
|
|
47
|
+
# 简化:不再依赖 FileDetector,直接通过
|
|
48
|
+
logger.info("Tokenizer loaded successfully.")
|
|
49
|
+
yield
|
|
57
50
|
|
|
58
51
|
|
|
59
52
|
@pytest.fixture(scope="function")
|
|
60
53
|
def test_args(temp_test_dir, setup_file_monitor_and_rules, load_tokenizer_fixture):
|
|
61
|
-
"""
|
|
62
|
-
args = AutoCoderArgs(
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
# Potentially mock other args if needed by resolver or its dependencies
|
|
66
|
-
)
|
|
67
|
-
return args
|
|
54
|
+
"""测试参数"""
|
|
55
|
+
args = AutoCoderArgs(source_dir=str(temp_test_dir))
|
|
56
|
+
args.enable_auto_fix_lint = False # 默认禁用 lint
|
|
57
|
+
yield args
|
|
68
58
|
|
|
69
|
-
@pytest.fixture
|
|
70
|
-
def mock_agent_no_shadow(test_args):
|
|
71
|
-
"""Mocks an AgenticEdit instance that does not provide shadow capabilities."""
|
|
72
|
-
agent = MagicMock()
|
|
73
|
-
agent.shadow_manager = None
|
|
74
|
-
agent.shadow_linter = None
|
|
75
|
-
agent.args = test_args
|
|
76
|
-
agent.record_file_change = MagicMock()
|
|
77
|
-
return agent
|
|
78
59
|
|
|
79
60
|
@pytest.fixture
|
|
80
|
-
def
|
|
81
|
-
"""Mocks an AgenticEdit instance
|
|
82
|
-
from autocoder.shadows.shadow_manager import ShadowManager
|
|
83
|
-
from autocoder.linters.shadow_linter import ShadowLinter
|
|
84
|
-
|
|
85
|
-
# Ensure the shadow base directory exists within the temp_test_dir for isolation
|
|
86
|
-
shadow_base_dir = os.path.join(temp_test_dir, ".auto-coder", "shadows")
|
|
87
|
-
os.makedirs(shadow_base_dir, exist_ok=True)
|
|
88
|
-
|
|
89
|
-
# Patch ShadowManager's default shadow_base to use our temp one
|
|
90
|
-
with patch('autocoder.shadows.shadow_manager.ShadowManager.DEFAULT_SHADOW_BASE_DIR', new=shadow_base_dir):
|
|
91
|
-
shadow_manager = ShadowManager(source_dir=str(temp_test_dir), event_file_id="test_event")
|
|
92
|
-
|
|
93
|
-
shadow_linter = ShadowLinter(shadow_manager=shadow_manager, verbose=False)
|
|
94
|
-
|
|
61
|
+
def mock_agent_no_shadow(test_args):
|
|
62
|
+
"""Mocks an AgenticEdit instance without shadow capabilities."""
|
|
95
63
|
agent = MagicMock()
|
|
96
|
-
agent.shadow_manager = shadow_manager
|
|
97
|
-
agent.shadow_linter = shadow_linter
|
|
98
64
|
agent.args = test_args
|
|
99
65
|
agent.record_file_change = MagicMock()
|
|
66
|
+
agent.checkpoint_manager = None # 不使用 checkpoint_manager
|
|
67
|
+
agent.linter = None # 不使用 linter
|
|
100
68
|
return agent
|
|
101
69
|
|
|
102
70
|
|
|
@@ -110,13 +78,14 @@ def test_create_new_file(test_args, temp_test_dir, mock_agent_no_shadow):
|
|
|
110
78
|
result = resolver.resolve()
|
|
111
79
|
|
|
112
80
|
assert result.success is True
|
|
113
|
-
|
|
81
|
+
# 修正断言:当前实现返回 "Successfully wrote to file: ..." 格式的消息
|
|
82
|
+
assert "Successfully wrote to file:" in result.message
|
|
114
83
|
|
|
115
84
|
expected_file_abs_path = os.path.join(temp_test_dir, file_path)
|
|
116
85
|
assert os.path.exists(expected_file_abs_path)
|
|
117
86
|
with open(expected_file_abs_path, "r", encoding="utf-8") as f:
|
|
118
87
|
assert f.read() == content
|
|
119
|
-
mock_agent_no_shadow.record_file_change.assert_called_once_with(file_path, "added",
|
|
88
|
+
mock_agent_no_shadow.record_file_change.assert_called_once_with(file_path, "added", diff=None, content=content)
|
|
120
89
|
|
|
121
90
|
|
|
122
91
|
def test_overwrite_existing_file(test_args, temp_test_dir, mock_agent_no_shadow):
|
|
@@ -137,7 +106,7 @@ def test_overwrite_existing_file(test_args, temp_test_dir, mock_agent_no_shadow)
|
|
|
137
106
|
assert os.path.exists(abs_file_path)
|
|
138
107
|
with open(abs_file_path, "r", encoding="utf-8") as f:
|
|
139
108
|
assert f.read() == new_content
|
|
140
|
-
mock_agent_no_shadow.record_file_change.assert_called_once_with(file_path, "modified",
|
|
109
|
+
mock_agent_no_shadow.record_file_change.assert_called_once_with(file_path, "modified", diff=None, content=new_content)
|
|
141
110
|
|
|
142
111
|
|
|
143
112
|
def test_create_file_in_new_directory(test_args, temp_test_dir, mock_agent_no_shadow):
|
|
@@ -154,169 +123,215 @@ def test_create_file_in_new_directory(test_args, temp_test_dir, mock_agent_no_sh
|
|
|
154
123
|
assert os.path.exists(expected_file_abs_path)
|
|
155
124
|
with open(expected_file_abs_path, "r", encoding="utf-8") as f:
|
|
156
125
|
assert f.read() == content
|
|
157
|
-
mock_agent_no_shadow.record_file_change.assert_called_once_with(file_path, "added",
|
|
126
|
+
mock_agent_no_shadow.record_file_change.assert_called_once_with(file_path, "added", diff=None, content=content)
|
|
127
|
+
|
|
158
128
|
|
|
159
129
|
def test_path_outside_project_root_fails(test_args, temp_test_dir, mock_agent_no_shadow):
|
|
160
130
|
logger.info(f"Running test_path_outside_project_root_fails in {temp_test_dir}")
|
|
161
|
-
#
|
|
162
|
-
# Note: The resolver's check is os.path.abspath(target_path).startswith(os.path.abspath(source_dir))
|
|
163
|
-
# So, a direct "../" might be normalized. We need a path that, when absolutized,
|
|
164
|
-
# is still outside an absolutized source_dir. This is tricky if source_dir is already root-like.
|
|
165
|
-
# For this test, we'll assume source_dir is not the filesystem root.
|
|
166
|
-
|
|
167
|
-
# A more robust way is to try to write to a known safe, but distinct, temporary directory
|
|
131
|
+
# 创建一个在项目根目录外的临时目录
|
|
168
132
|
another_temp_dir = temp_test_dir.parent / "another_temp_dir_for_outside_test"
|
|
169
133
|
another_temp_dir.mkdir(exist_ok=True)
|
|
170
134
|
|
|
171
|
-
#
|
|
172
|
-
# However, the resolver joins it with source_dir first.
|
|
173
|
-
# file_path = "../outside_file.txt" # This will be joined with source_dir
|
|
174
|
-
|
|
175
|
-
# Let's try an absolute path that is outside temp_test_dir
|
|
176
|
-
outside_abs_path = os.path.join(another_temp_dir, "outside_file.txt")
|
|
177
|
-
|
|
178
|
-
# The tool path is relative to source_dir. So, to make it point outside,
|
|
179
|
-
# we need to construct a relative path that goes "up" from source_dir.
|
|
180
|
-
# This requires knowing the relative position of temp_test_dir.
|
|
181
|
-
# A simpler test for the security check:
|
|
182
|
-
# Give an absolute path to the tool that is outside test_args.source_dir.
|
|
183
|
-
# The resolver logic is:
|
|
184
|
-
# abs_file_path = os.path.abspath(os.path.join(source_dir, file_path_from_tool))
|
|
185
|
-
# So, if file_path_from_tool is already absolute, os.path.join might behave unexpectedly on Windows.
|
|
186
|
-
# On POSIX, if file_path_from_tool is absolute, os.path.join returns file_path_from_tool.
|
|
187
|
-
|
|
135
|
+
# 在 POSIX 系统上,绝对路径会被正确处理
|
|
188
136
|
if os.name == 'posix':
|
|
189
|
-
file_path_for_tool =
|
|
190
|
-
else:
|
|
191
|
-
|
|
192
|
-
# the file_path parameter to the tool is *expected* to be relative.
|
|
193
|
-
# Providing an absolute path might be an invalid use case for the tool itself.
|
|
194
|
-
# The resolver's security check should still catch it if os.path.join(source_dir, abs_path)
|
|
195
|
-
# results in abs_path and abs_path is outside source_dir.
|
|
196
|
-
file_path_for_tool = outside_abs_path
|
|
137
|
+
file_path_for_tool = str(another_temp_dir / "outside_file.txt")
|
|
138
|
+
else:
|
|
139
|
+
file_path_for_tool = str(another_temp_dir / "outside_file.txt")
|
|
197
140
|
|
|
198
141
|
content = "Attempting to write outside."
|
|
199
|
-
tool = WriteToFileTool(path=
|
|
142
|
+
tool = WriteToFileTool(path=file_path_for_tool, content=content)
|
|
200
143
|
|
|
201
144
|
resolver = WriteToFileToolResolver(agent=mock_agent_no_shadow, tool=tool, args=test_args)
|
|
202
145
|
result = resolver.resolve()
|
|
203
146
|
|
|
204
147
|
assert result.success is False
|
|
205
148
|
assert "Access denied" in result.message
|
|
206
|
-
assert not os.path.exists(
|
|
207
|
-
|
|
208
|
-
# shutil.rmtree(another_temp_dir) # Clean up the other temp dir if created by this test
|
|
149
|
+
assert not os.path.exists(another_temp_dir / "outside_file.txt")
|
|
150
|
+
|
|
209
151
|
|
|
210
|
-
def
|
|
211
|
-
|
|
212
|
-
|
|
152
|
+
def test_simple_file_creation(test_args, temp_test_dir, mock_agent_no_shadow):
|
|
153
|
+
"""测试简单文件创建"""
|
|
154
|
+
logger.info(f"Running test_simple_file_creation in {temp_test_dir}")
|
|
213
155
|
|
|
214
|
-
file_path = "
|
|
215
|
-
content = "print('hello')"
|
|
156
|
+
file_path = "simple_file.py"
|
|
157
|
+
content = "print('hello world')"
|
|
216
158
|
tool = WriteToFileTool(path=file_path, content=content)
|
|
217
159
|
|
|
218
|
-
# Mock the linter parts if they were to be called
|
|
219
|
-
if mock_agent_no_shadow and hasattr(mock_agent_no_shadow, 'shadow_linter') and mock_agent_no_shadow.shadow_linter:
|
|
220
|
-
mock_agent_no_shadow.shadow_linter.lint_shadow_file = MagicMock(return_value=None) # Should not be called
|
|
221
|
-
|
|
222
160
|
resolver = WriteToFileToolResolver(agent=mock_agent_no_shadow, tool=tool, args=test_args)
|
|
223
161
|
result = resolver.resolve()
|
|
224
162
|
|
|
225
163
|
assert result.success is True
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
164
|
+
assert "Successfully wrote to file:" in result.message
|
|
165
|
+
# 确保文件确实被创建
|
|
166
|
+
expected_file_abs_path = os.path.join(temp_test_dir, file_path)
|
|
167
|
+
assert os.path.exists(expected_file_abs_path)
|
|
168
|
+
with open(expected_file_abs_path, "r", encoding="utf-8") as f:
|
|
169
|
+
assert f.read() == content
|
|
170
|
+
|
|
231
171
|
|
|
172
|
+
# ================= 追加模式测试用例 =================
|
|
232
173
|
|
|
233
|
-
def
|
|
234
|
-
|
|
235
|
-
|
|
174
|
+
def test_append_mode_to_new_file(test_args, temp_test_dir, mock_agent_no_shadow):
|
|
175
|
+
"""测试追加模式到新文件(应该等同于写入模式)"""
|
|
176
|
+
logger.info(f"Running test_append_mode_to_new_file in {temp_test_dir}")
|
|
177
|
+
file_path = "new_append_file.txt"
|
|
178
|
+
content = "This is appended content."
|
|
179
|
+
tool = WriteToFileTool(path=file_path, content=content, mode="append")
|
|
236
180
|
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
181
|
+
resolver = WriteToFileToolResolver(agent=mock_agent_no_shadow, tool=tool, args=test_args)
|
|
182
|
+
result = resolver.resolve()
|
|
183
|
+
|
|
184
|
+
assert result.success is True
|
|
185
|
+
assert "Successfully wrote to file:" in result.message # 新文件仍显示"wrote"
|
|
240
186
|
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
187
|
+
expected_file_abs_path = os.path.join(temp_test_dir, file_path)
|
|
188
|
+
assert os.path.exists(expected_file_abs_path)
|
|
189
|
+
with open(expected_file_abs_path, "r", encoding="utf-8") as f:
|
|
190
|
+
assert f.read() == content
|
|
191
|
+
mock_agent_no_shadow.record_file_change.assert_called_once_with(file_path, "added", diff=None, content=content)
|
|
192
|
+
|
|
193
|
+
|
|
194
|
+
def test_append_mode_to_existing_file(test_args, temp_test_dir, mock_agent_no_shadow):
|
|
195
|
+
"""测试追加模式到已存在的文件"""
|
|
196
|
+
logger.info(f"Running test_append_mode_to_existing_file in {temp_test_dir}")
|
|
197
|
+
file_path = "existing_append_file.txt"
|
|
198
|
+
initial_content = "Initial content.\n"
|
|
199
|
+
append_content = "This is appended content."
|
|
200
|
+
expected_final_content = initial_content + append_content
|
|
201
|
+
|
|
202
|
+
# 先创建文件
|
|
203
|
+
abs_file_path = os.path.join(temp_test_dir, file_path)
|
|
204
|
+
with open(abs_file_path, "w", encoding="utf-8") as f:
|
|
205
|
+
f.write(initial_content)
|
|
245
206
|
|
|
246
|
-
|
|
207
|
+
tool = WriteToFileTool(path=file_path, content=append_content, mode="append")
|
|
208
|
+
resolver = WriteToFileToolResolver(agent=mock_agent_no_shadow, tool=tool, args=test_args)
|
|
247
209
|
result = resolver.resolve()
|
|
248
210
|
|
|
249
211
|
assert result.success is True
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
212
|
+
assert "Successfully appended to file:" in result.message
|
|
213
|
+
|
|
214
|
+
assert os.path.exists(abs_file_path)
|
|
215
|
+
with open(abs_file_path, "r", encoding="utf-8") as f:
|
|
216
|
+
assert f.read() == expected_final_content
|
|
217
|
+
mock_agent_no_shadow.record_file_change.assert_called_once_with(file_path, "modified", diff=None, content=expected_final_content)
|
|
255
218
|
|
|
256
219
|
|
|
257
|
-
def
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
220
|
+
def test_write_mode_explicit(test_args, temp_test_dir, mock_agent_no_shadow):
|
|
221
|
+
"""测试显式写入模式(应该覆盖文件)"""
|
|
222
|
+
logger.info(f"Running test_write_mode_explicit in {temp_test_dir}")
|
|
223
|
+
file_path = "write_mode_file.txt"
|
|
224
|
+
initial_content = "Initial content."
|
|
225
|
+
new_content = "This is the new content."
|
|
262
226
|
|
|
263
|
-
|
|
227
|
+
# 先创建文件
|
|
228
|
+
abs_file_path = os.path.join(temp_test_dir, file_path)
|
|
229
|
+
with open(abs_file_path, "w", encoding="utf-8") as f:
|
|
230
|
+
f.write(initial_content)
|
|
231
|
+
|
|
232
|
+
tool = WriteToFileTool(path=file_path, content=new_content, mode="write")
|
|
233
|
+
resolver = WriteToFileToolResolver(agent=mock_agent_no_shadow, tool=tool, args=test_args)
|
|
264
234
|
result = resolver.resolve()
|
|
265
235
|
|
|
266
236
|
assert result.success is True
|
|
237
|
+
assert "Successfully wrote to file:" in result.message
|
|
267
238
|
|
|
268
|
-
|
|
269
|
-
|
|
239
|
+
assert os.path.exists(abs_file_path)
|
|
240
|
+
with open(abs_file_path, "r", encoding="utf-8") as f:
|
|
241
|
+
assert f.read() == new_content # 应该只有新内容,不包含初始内容
|
|
242
|
+
mock_agent_no_shadow.record_file_change.assert_called_once_with(file_path, "modified", diff=None, content=new_content)
|
|
270
243
|
|
|
271
|
-
assert not os.path.exists(real_file_abs_path) # Real file should not be created directly
|
|
272
|
-
assert os.path.exists(shadow_file_abs_path) # Shadow file should exist
|
|
273
|
-
with open(shadow_file_abs_path, "r", encoding="utf-8") as f:
|
|
274
|
-
assert f.read() == content
|
|
275
|
-
|
|
276
|
-
# Agent's record_file_change should still be called with the original relative path
|
|
277
|
-
mock_agent_with_shadow.record_file_change.assert_called_once_with(file_path, "added", content=content, diffs=None)
|
|
278
|
-
|
|
279
|
-
# Clean up shadows for this test if needed, though mock_agent_with_shadow might do it
|
|
280
|
-
# mock_agent_with_shadow.shadow_manager.clean_shadows()
|
|
281
244
|
|
|
245
|
+
def test_default_mode_is_write(test_args, temp_test_dir, mock_agent_no_shadow):
|
|
246
|
+
"""测试默认模式是写入模式"""
|
|
247
|
+
logger.info(f"Running test_default_mode_is_write in {temp_test_dir}")
|
|
248
|
+
file_path = "default_mode_file.txt"
|
|
249
|
+
initial_content = "Initial content."
|
|
250
|
+
new_content = "This is the new content."
|
|
251
|
+
|
|
252
|
+
# 先创建文件
|
|
253
|
+
abs_file_path = os.path.join(temp_test_dir, file_path)
|
|
254
|
+
with open(abs_file_path, "w", encoding="utf-8") as f:
|
|
255
|
+
f.write(initial_content)
|
|
256
|
+
|
|
257
|
+
# 不指定 mode,应该默认为写入模式
|
|
258
|
+
tool = WriteToFileTool(path=file_path, content=new_content)
|
|
259
|
+
resolver = WriteToFileToolResolver(agent=mock_agent_no_shadow, tool=tool, args=test_args)
|
|
260
|
+
result = resolver.resolve()
|
|
282
261
|
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
test_args.enable_auto_fix_lint = True
|
|
262
|
+
assert result.success is True
|
|
263
|
+
assert "Successfully wrote to file:" in result.message
|
|
286
264
|
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
265
|
+
assert os.path.exists(abs_file_path)
|
|
266
|
+
with open(abs_file_path, "r", encoding="utf-8") as f:
|
|
267
|
+
assert f.read() == new_content # 应该只有新内容,不包含初始内容
|
|
268
|
+
mock_agent_no_shadow.record_file_change.assert_called_once_with(file_path, "modified", diff=None, content=new_content)
|
|
269
|
+
|
|
290
270
|
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
mock_issue.message = "SyntaxError: Missing parentheses in call to 'print'"
|
|
297
|
-
mock_issue.code = "E999"
|
|
271
|
+
def test_append_mode_with_empty_existing_file(test_args, temp_test_dir, mock_agent_no_shadow):
|
|
272
|
+
"""测试追加模式到空的已存在文件"""
|
|
273
|
+
logger.info(f"Running test_append_mode_with_empty_existing_file in {temp_test_dir}")
|
|
274
|
+
file_path = "empty_existing_file.txt"
|
|
275
|
+
append_content = "This is appended to empty file."
|
|
298
276
|
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
}
|
|
277
|
+
# 创建空文件
|
|
278
|
+
abs_file_path = os.path.join(temp_test_dir, file_path)
|
|
279
|
+
with open(abs_file_path, "w", encoding="utf-8") as f:
|
|
280
|
+
f.write("")
|
|
304
281
|
|
|
282
|
+
tool = WriteToFileTool(path=file_path, content=append_content, mode="append")
|
|
283
|
+
resolver = WriteToFileToolResolver(agent=mock_agent_no_shadow, tool=tool, args=test_args)
|
|
284
|
+
result = resolver.resolve()
|
|
305
285
|
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
# For now, assume it works as expected based on WriteToFileToolResolver's internal call
|
|
309
|
-
|
|
310
|
-
resolver = WriteToFileToolResolver(agent=mock_agent_with_shadow, tool=tool, args=test_args)
|
|
286
|
+
assert result.success is True
|
|
287
|
+
assert "Successfully appended to file:" in result.message
|
|
311
288
|
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
result = resolver.resolve()
|
|
289
|
+
assert os.path.exists(abs_file_path)
|
|
290
|
+
with open(abs_file_path, "r", encoding="utf-8") as f:
|
|
291
|
+
assert f.read() == append_content
|
|
292
|
+
mock_agent_no_shadow.record_file_change.assert_called_once_with(file_path, "modified", diff=None, content=append_content)
|
|
317
293
|
|
|
318
|
-
assert result.success is True # Write itself is successful
|
|
319
|
-
mock_format.assert_called_once_with(mock_lint_result)
|
|
320
|
-
assert "Linting found 1 issue(s)" in result.message
|
|
321
|
-
assert "SyntaxError: Missing parentheses in call to 'print'" in result.message
|
|
322
294
|
|
|
295
|
+
def test_append_mode_multiple_appends(test_args, temp_test_dir, mock_agent_no_shadow):
|
|
296
|
+
"""测试多次追加到同一文件"""
|
|
297
|
+
logger.info(f"Running test_append_mode_multiple_appends in {temp_test_dir}")
|
|
298
|
+
file_path = "multiple_append_file.txt"
|
|
299
|
+
initial_content = "Initial line.\n"
|
|
300
|
+
first_append = "First append.\n"
|
|
301
|
+
second_append = "Second append."
|
|
302
|
+
|
|
303
|
+
# 创建初始文件
|
|
304
|
+
abs_file_path = os.path.join(temp_test_dir, file_path)
|
|
305
|
+
with open(abs_file_path, "w", encoding="utf-8") as f:
|
|
306
|
+
f.write(initial_content)
|
|
307
|
+
|
|
308
|
+
# 第一次追加
|
|
309
|
+
tool1 = WriteToFileTool(path=file_path, content=first_append, mode="append")
|
|
310
|
+
resolver1 = WriteToFileToolResolver(agent=mock_agent_no_shadow, tool=tool1, args=test_args)
|
|
311
|
+
result1 = resolver1.resolve()
|
|
312
|
+
|
|
313
|
+
assert result1.success is True
|
|
314
|
+
assert "Successfully appended to file:" in result1.message
|
|
315
|
+
|
|
316
|
+
# 验证第一次追加后的内容
|
|
317
|
+
with open(abs_file_path, "r", encoding="utf-8") as f:
|
|
318
|
+
content_after_first = f.read()
|
|
319
|
+
assert content_after_first == initial_content + first_append
|
|
320
|
+
|
|
321
|
+
# 重置 mock 以便第二次调用
|
|
322
|
+
mock_agent_no_shadow.record_file_change.reset_mock()
|
|
323
|
+
|
|
324
|
+
# 第二次追加
|
|
325
|
+
tool2 = WriteToFileTool(path=file_path, content=second_append, mode="append")
|
|
326
|
+
resolver2 = WriteToFileToolResolver(agent=mock_agent_no_shadow, tool=tool2, args=test_args)
|
|
327
|
+
result2 = resolver2.resolve()
|
|
328
|
+
|
|
329
|
+
assert result2.success is True
|
|
330
|
+
assert "Successfully appended to file:" in result2.message
|
|
331
|
+
|
|
332
|
+
# 验证最终内容
|
|
333
|
+
with open(abs_file_path, "r", encoding="utf-8") as f:
|
|
334
|
+
final_content = f.read()
|
|
335
|
+
expected_final = initial_content + first_append + second_append
|
|
336
|
+
assert final_content == expected_final
|
|
337
|
+
mock_agent_no_shadow.record_file_change.assert_called_once_with(file_path, "modified", diff=None, content=expected_final)
|