auto-coder 1.0.0__py3-none-any.whl → 2.0.1__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of auto-coder might be problematic. Click here for more details.
- auto_coder-2.0.1.dist-info/LICENSE +158 -0
- auto_coder-2.0.1.dist-info/METADATA +558 -0
- auto_coder-2.0.1.dist-info/RECORD +795 -0
- {auto_coder-1.0.0.dist-info → auto_coder-2.0.1.dist-info}/WHEEL +1 -1
- {auto_coder-1.0.0.dist-info → auto_coder-2.0.1.dist-info}/entry_points.txt +3 -3
- autocoder/__init__.py +31 -0
- autocoder/agent/auto_filegroup.py +32 -13
- autocoder/agent/auto_learn_from_commit.py +9 -1
- autocoder/agent/base_agentic/__init__.py +3 -0
- autocoder/agent/base_agentic/agent_hub.py +1 -1
- autocoder/agent/base_agentic/base_agent.py +235 -136
- autocoder/agent/base_agentic/default_tools.py +119 -118
- autocoder/agent/base_agentic/test_base_agent.py +1 -1
- autocoder/agent/base_agentic/tool_registry.py +32 -20
- autocoder/agent/base_agentic/tools/read_file_tool_resolver.py +24 -3
- autocoder/agent/base_agentic/tools/write_to_file_tool_resolver.py +24 -11
- autocoder/agent/base_agentic/types.py +42 -0
- autocoder/agent/entry_command_agent/chat.py +77 -73
- autocoder/auto_coder.py +31 -40
- autocoder/auto_coder_rag.py +11 -1084
- autocoder/auto_coder_runner.py +962 -2345
- autocoder/auto_coder_terminal.py +26 -0
- autocoder/auto_coder_terminal_v3.py +190 -0
- autocoder/chat/conf_command.py +224 -124
- autocoder/chat/models_command.py +361 -299
- autocoder/chat/rules_command.py +79 -31
- autocoder/chat_auto_coder.py +988 -398
- autocoder/chat_auto_coder_lang.py +23 -732
- autocoder/commands/auto_command.py +25 -8
- autocoder/commands/auto_web.py +1 -1
- autocoder/commands/tools.py +44 -44
- autocoder/common/__init__.py +150 -128
- autocoder/common/ac_style_command_parser/__init__.py +39 -2
- autocoder/common/ac_style_command_parser/config.py +422 -0
- autocoder/common/ac_style_command_parser/parser.py +292 -78
- autocoder/common/ac_style_command_parser/test_parser.py +241 -16
- autocoder/common/ac_style_command_parser/test_typed_parser.py +342 -0
- autocoder/common/ac_style_command_parser/typed_parser.py +653 -0
- autocoder/common/action_yml_file_manager.py +25 -13
- autocoder/common/agent_events/__init__.py +52 -0
- autocoder/common/agent_events/agent_event_emitter.py +193 -0
- autocoder/common/agent_events/event_factory.py +177 -0
- autocoder/common/agent_events/examples.py +307 -0
- autocoder/common/agent_events/types.py +113 -0
- autocoder/common/agent_events/utils.py +68 -0
- autocoder/common/agent_hooks/__init__.py +44 -0
- autocoder/common/agent_hooks/examples.py +582 -0
- autocoder/common/agent_hooks/hook_executor.py +217 -0
- autocoder/common/agent_hooks/hook_manager.py +288 -0
- autocoder/common/agent_hooks/types.py +133 -0
- autocoder/common/agent_hooks/utils.py +99 -0
- autocoder/common/agent_query_queue/queue_executor.py +324 -0
- autocoder/common/agent_query_queue/queue_manager.py +325 -0
- autocoder/common/agents/__init__.py +11 -0
- autocoder/common/agents/agent_manager.py +323 -0
- autocoder/common/agents/agent_parser.py +189 -0
- autocoder/common/agents/example_usage.py +344 -0
- autocoder/common/agents/integration_example.py +330 -0
- autocoder/common/agents/test_agent_parser.py +545 -0
- autocoder/common/async_utils.py +101 -0
- autocoder/common/auto_coder_lang.py +23 -972
- autocoder/common/autocoderargs_parser/__init__.py +14 -0
- autocoder/common/autocoderargs_parser/parser.py +184 -0
- autocoder/common/autocoderargs_parser/tests/__init__.py +1 -0
- autocoder/common/autocoderargs_parser/tests/test_args_parser.py +235 -0
- autocoder/common/autocoderargs_parser/tests/test_token_parser.py +195 -0
- autocoder/common/autocoderargs_parser/token_parser.py +290 -0
- autocoder/common/buildin_tokenizer.py +2 -4
- autocoder/common/code_auto_generate.py +149 -74
- autocoder/common/code_auto_generate_diff.py +163 -70
- autocoder/common/code_auto_generate_editblock.py +179 -89
- autocoder/common/code_auto_generate_strict_diff.py +167 -72
- autocoder/common/code_auto_merge_editblock.py +13 -6
- autocoder/common/code_modification_ranker.py +1 -1
- autocoder/common/command_completer.py +3 -3
- autocoder/common/command_file_manager/manager.py +183 -47
- autocoder/common/command_file_manager/test_command_file_manager.py +507 -0
- autocoder/common/command_templates.py +1 -1
- autocoder/common/conf_utils.py +2 -4
- autocoder/common/conversations/config.py +11 -3
- autocoder/common/conversations/get_conversation_manager.py +100 -2
- autocoder/common/conversations/llm_stats_models.py +264 -0
- autocoder/common/conversations/manager.py +112 -28
- autocoder/common/conversations/models.py +16 -2
- autocoder/common/conversations/storage/index_manager.py +134 -10
- autocoder/common/core_config/__init__.py +63 -0
- autocoder/common/core_config/agentic_mode_manager.py +109 -0
- autocoder/common/core_config/base_manager.py +123 -0
- autocoder/common/core_config/compatibility.py +151 -0
- autocoder/common/core_config/config_manager.py +156 -0
- autocoder/common/core_config/conversation_manager.py +31 -0
- autocoder/common/core_config/exclude_manager.py +72 -0
- autocoder/common/core_config/file_manager.py +177 -0
- autocoder/common/core_config/human_as_model_manager.py +129 -0
- autocoder/common/core_config/lib_manager.py +54 -0
- autocoder/common/core_config/main_manager.py +81 -0
- autocoder/common/core_config/mode_manager.py +126 -0
- autocoder/common/core_config/models.py +70 -0
- autocoder/common/core_config/test_memory_manager.py +1056 -0
- autocoder/common/env_manager.py +282 -0
- autocoder/common/env_manager_usage_example.py +211 -0
- autocoder/common/file_checkpoint/conversation_checkpoint.py +19 -19
- autocoder/common/file_checkpoint/manager.py +264 -48
- autocoder/common/file_checkpoint/test_backup.py +1 -18
- autocoder/common/file_checkpoint/test_manager.py +270 -1
- autocoder/common/file_checkpoint/test_store.py +1 -17
- autocoder/common/file_handler/__init__.py +23 -0
- autocoder/common/file_handler/active_context_handler.py +159 -0
- autocoder/common/file_handler/add_files_handler.py +409 -0
- autocoder/common/file_handler/chat_handler.py +180 -0
- autocoder/common/file_handler/coding_handler.py +409 -0
- autocoder/common/file_handler/commit_handler.py +200 -0
- autocoder/common/file_handler/lib_handler.py +156 -0
- autocoder/common/file_handler/list_files_handler.py +111 -0
- autocoder/common/file_handler/mcp_handler.py +268 -0
- autocoder/common/file_handler/models_handler.py +493 -0
- autocoder/common/file_handler/remove_files_handler.py +172 -0
- autocoder/common/git_utils.py +44 -8
- autocoder/common/global_cancel.py +15 -6
- autocoder/common/ignorefiles/test_ignore_file_utils.py +1 -1
- autocoder/common/international/__init__.py +31 -0
- autocoder/common/international/demo_international.py +92 -0
- autocoder/common/international/message_manager.py +157 -0
- autocoder/common/international/messages/__init__.py +56 -0
- autocoder/common/international/messages/async_command_messages.py +507 -0
- autocoder/common/international/messages/auto_coder_messages.py +2208 -0
- autocoder/common/international/messages/chat_auto_coder_messages.py +1547 -0
- autocoder/common/international/messages/command_help_messages.py +986 -0
- autocoder/common/international/messages/conversation_command_messages.py +191 -0
- autocoder/common/international/messages/git_helper_plugin_messages.py +159 -0
- autocoder/common/international/messages/queue_command_messages.py +751 -0
- autocoder/common/international/messages/rules_command_messages.py +77 -0
- autocoder/common/international/messages/sdk_messages.py +1707 -0
- autocoder/common/international/messages/token_helper_plugin_messages.py +361 -0
- autocoder/common/international/messages/tool_display_messages.py +1212 -0
- autocoder/common/international/messages/workflow_exception_messages.py +473 -0
- autocoder/common/international/test_international.py +612 -0
- autocoder/common/linter_core/__init__.py +28 -0
- autocoder/common/linter_core/base_linter.py +61 -0
- autocoder/common/linter_core/config_loader.py +271 -0
- autocoder/common/linter_core/formatters/__init__.py +0 -0
- autocoder/common/linter_core/formatters/base_formatter.py +38 -0
- autocoder/common/linter_core/formatters/raw_formatter.py +17 -0
- autocoder/common/linter_core/linter.py +166 -0
- autocoder/common/linter_core/linter_factory.py +216 -0
- autocoder/common/linter_core/linter_manager.py +333 -0
- autocoder/common/linter_core/linters/__init__.py +9 -0
- autocoder/common/linter_core/linters/java_linter.py +342 -0
- autocoder/common/linter_core/linters/python_linter.py +115 -0
- autocoder/common/linter_core/linters/typescript_linter.py +119 -0
- autocoder/common/linter_core/models/__init__.py +7 -0
- autocoder/common/linter_core/models/lint_result.py +91 -0
- autocoder/common/linter_core/models.py +33 -0
- autocoder/common/linter_core/tests/__init__.py +3 -0
- autocoder/common/linter_core/tests/test_config_loader.py +323 -0
- autocoder/common/linter_core/tests/test_config_loading.py +308 -0
- autocoder/common/linter_core/tests/test_factory_manager.py +234 -0
- autocoder/common/linter_core/tests/test_formatters.py +147 -0
- autocoder/common/linter_core/tests/test_integration.py +317 -0
- autocoder/common/linter_core/tests/test_java_linter.py +496 -0
- autocoder/common/linter_core/tests/test_linters.py +265 -0
- autocoder/common/linter_core/tests/test_models.py +81 -0
- autocoder/common/linter_core/tests/verify_config_loading.py +296 -0
- autocoder/common/linter_core/tests/verify_fixes.py +183 -0
- autocoder/common/llm_friendly_package/__init__.py +31 -0
- autocoder/common/llm_friendly_package/base_manager.py +102 -0
- autocoder/common/llm_friendly_package/docs_manager.py +121 -0
- autocoder/common/llm_friendly_package/library_manager.py +171 -0
- autocoder/common/{llm_friendly_package.py → llm_friendly_package/main_manager.py} +204 -231
- autocoder/common/llm_friendly_package/models.py +40 -0
- autocoder/common/llm_friendly_package/test_llm_friendly_package.py +536 -0
- autocoder/common/llms/__init__.py +15 -0
- autocoder/common/llms/demo_error_handling.py +85 -0
- autocoder/common/llms/factory.py +142 -0
- autocoder/common/llms/manager.py +264 -0
- autocoder/common/llms/pricing.py +121 -0
- autocoder/common/llms/registry.py +316 -0
- autocoder/common/llms/schema.py +77 -0
- autocoder/common/llms/simple_demo.py +45 -0
- autocoder/common/llms/test_quick_model.py +116 -0
- autocoder/common/llms/test_remove_functionality.py +182 -0
- autocoder/common/llms/tests/__init__.py +1 -0
- autocoder/common/llms/tests/test_manager.py +330 -0
- autocoder/common/llms/tests/test_registry.py +364 -0
- autocoder/common/mcp_tools/__init__.py +62 -0
- autocoder/common/{mcp_tools.py → mcp_tools/executor.py} +49 -40
- autocoder/common/{mcp_hub.py → mcp_tools/hub.py} +42 -68
- autocoder/common/{mcp_server_install.py → mcp_tools/installer.py} +16 -28
- autocoder/common/{mcp_server.py → mcp_tools/server.py} +176 -48
- autocoder/common/mcp_tools/test_keyboard_interrupt.py +93 -0
- autocoder/common/mcp_tools/test_mcp_tools.py +391 -0
- autocoder/common/{mcp_server_types.py → mcp_tools/types.py} +121 -48
- autocoder/common/mcp_tools/verify_functionality.py +202 -0
- autocoder/common/model_speed_tester.py +32 -26
- autocoder/common/priority_directory_finder/__init__.py +142 -0
- autocoder/common/priority_directory_finder/examples.py +230 -0
- autocoder/common/priority_directory_finder/finder.py +283 -0
- autocoder/common/priority_directory_finder/models.py +236 -0
- autocoder/common/priority_directory_finder/test_priority_directory_finder.py +431 -0
- autocoder/common/project_scanner/__init__.py +18 -0
- autocoder/common/project_scanner/compat.py +77 -0
- autocoder/common/project_scanner/scanner.py +436 -0
- autocoder/common/project_tracker/__init__.py +27 -0
- autocoder/common/project_tracker/api.py +228 -0
- autocoder/common/project_tracker/demo.py +272 -0
- autocoder/common/project_tracker/tracker.py +487 -0
- autocoder/common/project_tracker/types.py +53 -0
- autocoder/common/pruner/__init__.py +67 -0
- autocoder/common/pruner/agentic_conversation_pruner.py +651 -102
- autocoder/common/pruner/conversation_message_ids_api.py +386 -0
- autocoder/common/pruner/conversation_message_ids_manager.py +347 -0
- autocoder/common/pruner/conversation_message_ids_pruner.py +473 -0
- autocoder/common/pruner/conversation_normalizer.py +347 -0
- autocoder/common/pruner/conversation_pruner.py +26 -6
- autocoder/common/pruner/test_agentic_conversation_pruner.py +554 -112
- autocoder/common/pruner/test_conversation_normalizer.py +502 -0
- autocoder/common/pruner/test_tool_content_detector.py +324 -0
- autocoder/common/pruner/tool_content_detector.py +227 -0
- autocoder/common/pruner/tools/__init__.py +18 -0
- autocoder/common/pruner/tools/query_message_ids.py +264 -0
- autocoder/common/pruner/tools/test_agentic_pruning_logic.py +432 -0
- autocoder/common/pruner/tools/test_message_ids_pruning_only.py +192 -0
- autocoder/common/pull_requests/__init__.py +9 -1
- autocoder/common/pull_requests/utils.py +122 -1
- autocoder/common/rag_manager/rag_manager.py +36 -40
- autocoder/common/rulefiles/__init__.py +53 -1
- autocoder/common/rulefiles/api.py +250 -0
- autocoder/common/rulefiles/core/__init__.py +14 -0
- autocoder/common/rulefiles/core/manager.py +241 -0
- autocoder/common/rulefiles/core/selector.py +805 -0
- autocoder/common/rulefiles/models/__init__.py +20 -0
- autocoder/common/rulefiles/models/index.py +16 -0
- autocoder/common/rulefiles/models/init_rule.py +18 -0
- autocoder/common/rulefiles/models/rule_file.py +18 -0
- autocoder/common/rulefiles/models/rule_relevance.py +14 -0
- autocoder/common/rulefiles/models/summary.py +16 -0
- autocoder/common/rulefiles/test_rulefiles.py +776 -0
- autocoder/common/rulefiles/utils/__init__.py +34 -0
- autocoder/common/rulefiles/utils/monitor.py +86 -0
- autocoder/common/rulefiles/utils/parser.py +230 -0
- autocoder/common/save_formatted_log.py +67 -10
- autocoder/common/search_replace.py +8 -1
- autocoder/common/search_replace_patch/__init__.py +24 -0
- autocoder/common/search_replace_patch/base.py +115 -0
- autocoder/common/search_replace_patch/manager.py +248 -0
- autocoder/common/search_replace_patch/patch_replacer.py +304 -0
- autocoder/common/search_replace_patch/similarity_replacer.py +306 -0
- autocoder/common/search_replace_patch/string_replacer.py +181 -0
- autocoder/common/search_replace_patch/tests/__init__.py +3 -0
- autocoder/common/search_replace_patch/tests/run_tests.py +126 -0
- autocoder/common/search_replace_patch/tests/test_base.py +188 -0
- autocoder/common/search_replace_patch/tests/test_empty_line_insert.py +233 -0
- autocoder/common/search_replace_patch/tests/test_integration.py +389 -0
- autocoder/common/search_replace_patch/tests/test_manager.py +351 -0
- autocoder/common/search_replace_patch/tests/test_patch_replacer.py +316 -0
- autocoder/common/search_replace_patch/tests/test_regex_replacer.py +306 -0
- autocoder/common/search_replace_patch/tests/test_similarity_replacer.py +384 -0
- autocoder/common/shell_commands/__init__.py +197 -0
- autocoder/common/shell_commands/background_process_notifier.py +346 -0
- autocoder/common/shell_commands/command_executor.py +1127 -0
- autocoder/common/shell_commands/error_recovery.py +541 -0
- autocoder/common/shell_commands/exceptions.py +120 -0
- autocoder/common/shell_commands/interactive_executor.py +476 -0
- autocoder/common/shell_commands/interactive_pexpect_process.py +623 -0
- autocoder/common/shell_commands/interactive_process.py +744 -0
- autocoder/common/shell_commands/interactive_session_manager.py +1014 -0
- autocoder/common/shell_commands/monitoring.py +529 -0
- autocoder/common/shell_commands/process_cleanup.py +386 -0
- autocoder/common/shell_commands/process_manager.py +606 -0
- autocoder/common/shell_commands/test_interactive_pexpect_process.py +281 -0
- autocoder/common/shell_commands/tests/__init__.py +6 -0
- autocoder/common/shell_commands/tests/conftest.py +118 -0
- autocoder/common/shell_commands/tests/test_background_process_notifier.py +703 -0
- autocoder/common/shell_commands/tests/test_command_executor.py +448 -0
- autocoder/common/shell_commands/tests/test_error_recovery.py +305 -0
- autocoder/common/shell_commands/tests/test_exceptions.py +299 -0
- autocoder/common/shell_commands/tests/test_execute_batch.py +588 -0
- autocoder/common/shell_commands/tests/test_indented_batch_commands.py +244 -0
- autocoder/common/shell_commands/tests/test_integration.py +664 -0
- autocoder/common/shell_commands/tests/test_monitoring.py +546 -0
- autocoder/common/shell_commands/tests/test_performance.py +632 -0
- autocoder/common/shell_commands/tests/test_process_cleanup.py +397 -0
- autocoder/common/shell_commands/tests/test_process_manager.py +606 -0
- autocoder/common/shell_commands/tests/test_timeout_config.py +343 -0
- autocoder/common/shell_commands/tests/test_timeout_manager.py +520 -0
- autocoder/common/shell_commands/timeout_config.py +315 -0
- autocoder/common/shell_commands/timeout_manager.py +352 -0
- autocoder/common/terminal_paste/__init__.py +14 -0
- autocoder/common/terminal_paste/demo.py +145 -0
- autocoder/common/terminal_paste/demo_paste_functionality.py +95 -0
- autocoder/common/terminal_paste/paste_handler.py +200 -0
- autocoder/common/terminal_paste/paste_manager.py +118 -0
- autocoder/common/terminal_paste/tests/__init__.py +1 -0
- autocoder/common/terminal_paste/tests/test_paste_handler.py +182 -0
- autocoder/common/terminal_paste/tests/test_paste_manager.py +126 -0
- autocoder/common/terminal_paste/utils.py +163 -0
- autocoder/common/test_autocoder_args.py +232 -0
- autocoder/common/test_env_manager.py +173 -0
- autocoder/common/test_env_manager_integration.py +159 -0
- autocoder/common/text_similarity/__init__.py +9 -0
- autocoder/common/text_similarity/demo.py +216 -0
- autocoder/common/text_similarity/examples.py +266 -0
- autocoder/common/text_similarity/test_text_similarity.py +306 -0
- autocoder/common/text_similarity/text_similarity.py +194 -0
- autocoder/common/text_similarity/utils.py +125 -0
- autocoder/common/todos/__init__.py +61 -0
- autocoder/common/todos/cache/__init__.py +16 -0
- autocoder/common/todos/cache/base_cache.py +89 -0
- autocoder/common/todos/cache/cache_manager.py +228 -0
- autocoder/common/todos/cache/memory_cache.py +225 -0
- autocoder/common/todos/config.py +155 -0
- autocoder/common/todos/exceptions.py +35 -0
- autocoder/common/todos/get_todo_manager.py +161 -0
- autocoder/common/todos/manager.py +537 -0
- autocoder/common/todos/models.py +239 -0
- autocoder/common/todos/storage/__init__.py +14 -0
- autocoder/common/todos/storage/base_storage.py +76 -0
- autocoder/common/todos/storage/file_storage.py +278 -0
- autocoder/common/tokens/counter.py +24 -2
- autocoder/common/tools_manager/__init__.py +17 -0
- autocoder/common/tools_manager/examples.py +162 -0
- autocoder/common/tools_manager/manager.py +385 -0
- autocoder/common/tools_manager/models.py +39 -0
- autocoder/common/tools_manager/test_tools_manager.py +303 -0
- autocoder/common/tools_manager/utils.py +191 -0
- autocoder/common/v2/agent/agentic_callbacks.py +270 -0
- autocoder/common/v2/agent/agentic_edit.py +2699 -1856
- autocoder/common/v2/agent/agentic_edit_change_manager.py +474 -0
- autocoder/common/v2/agent/agentic_edit_tools/__init__.py +35 -1
- autocoder/common/v2/agent/agentic_edit_tools/ac_mod_list_tool_resolver.py +279 -0
- autocoder/common/v2/agent/agentic_edit_tools/ac_mod_write_tool_resolver.py +10 -1
- autocoder/common/v2/agent/agentic_edit_tools/background_task_tool_resolver.py +1167 -0
- autocoder/common/v2/agent/agentic_edit_tools/base_tool_resolver.py +2 -2
- autocoder/common/v2/agent/agentic_edit_tools/conversation_message_ids_read_tool_resolver.py +214 -0
- autocoder/common/v2/agent/agentic_edit_tools/conversation_message_ids_write_tool_resolver.py +299 -0
- autocoder/common/v2/agent/agentic_edit_tools/count_tokens_tool_resolver.py +290 -0
- autocoder/common/v2/agent/agentic_edit_tools/execute_command_tool_resolver.py +564 -29
- autocoder/common/v2/agent/agentic_edit_tools/execute_workflow_tool_resolver.py +485 -0
- autocoder/common/v2/agent/agentic_edit_tools/extract_to_text_tool_resolver.py +225 -0
- autocoder/common/v2/agent/agentic_edit_tools/lint_report.py +79 -0
- autocoder/common/v2/agent/agentic_edit_tools/linter_config_models.py +343 -0
- autocoder/common/v2/agent/agentic_edit_tools/linter_enabled_tool_resolver.py +189 -0
- autocoder/common/v2/agent/agentic_edit_tools/list_files_tool_resolver.py +169 -101
- autocoder/common/v2/agent/agentic_edit_tools/load_extra_document_tool_resolver.py +356 -0
- autocoder/common/v2/agent/agentic_edit_tools/read_file_tool_resolver.py +243 -50
- autocoder/common/v2/agent/agentic_edit_tools/replace_in_file_tool_resolver.py +667 -147
- autocoder/common/v2/agent/agentic_edit_tools/run_named_subagents_tool_resolver.py +691 -0
- autocoder/common/v2/agent/agentic_edit_tools/search_files_tool_resolver.py +410 -86
- autocoder/common/v2/agent/agentic_edit_tools/session_interactive_tool_resolver.py +115 -0
- autocoder/common/v2/agent/agentic_edit_tools/session_start_tool_resolver.py +190 -0
- autocoder/common/v2/agent/agentic_edit_tools/session_stop_tool_resolver.py +76 -0
- autocoder/common/v2/agent/agentic_edit_tools/test_write_to_file_tool_resolver.py +207 -192
- autocoder/common/v2/agent/agentic_edit_tools/todo_read_tool_resolver.py +80 -63
- autocoder/common/v2/agent/agentic_edit_tools/todo_write_tool_resolver.py +237 -233
- autocoder/common/v2/agent/agentic_edit_tools/use_mcp_tool_resolver.py +2 -2
- autocoder/common/v2/agent/agentic_edit_tools/web_crawl_tool_resolver.py +557 -0
- autocoder/common/v2/agent/agentic_edit_tools/web_search_tool_resolver.py +600 -0
- autocoder/common/v2/agent/agentic_edit_tools/write_to_file_tool_resolver.py +56 -121
- autocoder/common/v2/agent/agentic_edit_types.py +343 -9
- autocoder/common/v2/agent/runner/__init__.py +3 -3
- autocoder/common/v2/agent/runner/base_runner.py +12 -26
- autocoder/common/v2/agent/runner/{event_runner.py → file_based_event_runner.py} +3 -2
- autocoder/common/v2/agent/runner/sdk_runner.py +150 -8
- autocoder/common/v2/agent/runner/terminal_runner.py +170 -57
- autocoder/common/v2/agent/runner/tool_display.py +557 -159
- autocoder/common/v2/agent/test_agentic_callbacks.py +265 -0
- autocoder/common/v2/agent/test_agentic_edit.py +194 -0
- autocoder/common/v2/agent/tool_caller/__init__.py +24 -0
- autocoder/common/v2/agent/tool_caller/default_tool_resolver_map.py +135 -0
- autocoder/common/v2/agent/tool_caller/integration_test.py +172 -0
- autocoder/common/v2/agent/tool_caller/plugins/__init__.py +14 -0
- autocoder/common/v2/agent/tool_caller/plugins/base_plugin.py +126 -0
- autocoder/common/v2/agent/tool_caller/plugins/examples/__init__.py +13 -0
- autocoder/common/v2/agent/tool_caller/plugins/examples/logging_plugin.py +164 -0
- autocoder/common/v2/agent/tool_caller/plugins/examples/security_filter_plugin.py +198 -0
- autocoder/common/v2/agent/tool_caller/plugins/plugin_interface.py +141 -0
- autocoder/common/v2/agent/tool_caller/test_tool_caller.py +278 -0
- autocoder/common/v2/agent/tool_caller/tool_call_plugin_manager.py +331 -0
- autocoder/common/v2/agent/tool_caller/tool_caller.py +337 -0
- autocoder/common/v2/agent/tool_caller/usage_example.py +193 -0
- autocoder/common/v2/code_agentic_editblock_manager.py +4 -4
- autocoder/common/v2/code_auto_generate.py +136 -78
- autocoder/common/v2/code_auto_generate_diff.py +135 -79
- autocoder/common/v2/code_auto_generate_editblock.py +174 -99
- autocoder/common/v2/code_auto_generate_strict_diff.py +151 -71
- autocoder/common/v2/code_auto_merge.py +1 -1
- autocoder/common/v2/code_auto_merge_editblock.py +13 -1
- autocoder/common/v2/code_diff_manager.py +3 -3
- autocoder/common/v2/code_editblock_manager.py +4 -14
- autocoder/common/v2/code_manager.py +1 -1
- autocoder/common/v2/code_strict_diff_manager.py +2 -2
- autocoder/common/wrap_llm_hint/__init__.py +10 -0
- autocoder/common/wrap_llm_hint/test_wrap_llm_hint.py +1067 -0
- autocoder/common/wrap_llm_hint/utils.py +432 -0
- autocoder/common/wrap_llm_hint/wrap_llm_hint.py +323 -0
- autocoder/completer/__init__.py +8 -0
- autocoder/completer/command_completer_v2.py +1094 -0
- autocoder/default_project/__init__.py +501 -0
- autocoder/dispacher/__init__.py +4 -12
- autocoder/dispacher/actions/action.py +400 -129
- autocoder/dispacher/actions/plugins/action_regex_project.py +2 -2
- autocoder/index/entry.py +117 -125
- autocoder/{agent → index/filter}/agentic_filter.py +322 -333
- autocoder/index/filter/normal_filter.py +5 -11
- autocoder/index/filter/quick_filter.py +1 -1
- autocoder/index/index.py +36 -9
- autocoder/index/tests/__init__.py +1 -0
- autocoder/index/tests/run_tests.py +195 -0
- autocoder/index/tests/test_entry.py +303 -0
- autocoder/index/tests/test_index_manager.py +314 -0
- autocoder/index/tests/test_module_integration.py +300 -0
- autocoder/index/tests/test_symbols_utils.py +183 -0
- autocoder/inner/__init__.py +4 -0
- autocoder/inner/agentic.py +923 -0
- autocoder/inner/async_command_handler.py +992 -0
- autocoder/inner/conversation_command_handlers.py +623 -0
- autocoder/inner/merge_command_handler.py +213 -0
- autocoder/inner/queue_command_handler.py +684 -0
- autocoder/models.py +95 -266
- autocoder/plugins/git_helper_plugin.py +31 -29
- autocoder/plugins/token_helper_plugin.py +65 -46
- autocoder/pyproject/__init__.py +32 -29
- autocoder/rag/agentic_rag.py +215 -75
- autocoder/rag/cache/simple_cache.py +1 -2
- autocoder/rag/loaders/image_loader.py +1 -1
- autocoder/rag/long_context_rag.py +42 -26
- autocoder/rag/qa_conversation_strategy.py +1 -1
- autocoder/rag/terminal/__init__.py +17 -0
- autocoder/rag/terminal/args.py +581 -0
- autocoder/rag/terminal/bootstrap.py +61 -0
- autocoder/rag/terminal/command_handlers.py +653 -0
- autocoder/rag/terminal/formatters/__init__.py +20 -0
- autocoder/rag/terminal/formatters/base.py +70 -0
- autocoder/rag/terminal/formatters/json_format.py +66 -0
- autocoder/rag/terminal/formatters/stream_json.py +95 -0
- autocoder/rag/terminal/formatters/text.py +28 -0
- autocoder/rag/terminal/init.py +120 -0
- autocoder/rag/terminal/utils.py +106 -0
- autocoder/rag/test_agentic_rag.py +389 -0
- autocoder/rag/test_doc_filter.py +3 -3
- autocoder/rag/test_long_context_rag.py +1 -1
- autocoder/rag/test_token_limiter.py +517 -10
- autocoder/rag/token_counter.py +3 -0
- autocoder/rag/token_limiter.py +19 -15
- autocoder/rag/tools/__init__.py +26 -2
- autocoder/rag/tools/bochaai_example.py +343 -0
- autocoder/rag/tools/bochaai_sdk.py +541 -0
- autocoder/rag/tools/metaso_example.py +268 -0
- autocoder/rag/tools/metaso_sdk.py +417 -0
- autocoder/rag/tools/recall_tool.py +28 -7
- autocoder/rag/tools/run_integration_tests.py +204 -0
- autocoder/rag/tools/test_all_providers.py +318 -0
- autocoder/rag/tools/test_bochaai_integration.py +482 -0
- autocoder/rag/tools/test_final_integration.py +215 -0
- autocoder/rag/tools/test_metaso_integration.py +424 -0
- autocoder/rag/tools/test_metaso_real.py +171 -0
- autocoder/rag/tools/test_web_crawl_tool.py +639 -0
- autocoder/rag/tools/test_web_search_tool.py +509 -0
- autocoder/rag/tools/todo_read_tool.py +202 -0
- autocoder/rag/tools/todo_write_tool.py +412 -0
- autocoder/rag/tools/web_crawl_tool.py +634 -0
- autocoder/rag/tools/web_search_tool.py +558 -0
- autocoder/rag/tools/web_tools_example.py +119 -0
- autocoder/rag/types.py +16 -0
- autocoder/rag/variable_holder.py +4 -2
- autocoder/rags.py +86 -79
- autocoder/regexproject/__init__.py +23 -21
- autocoder/sdk/__init__.py +46 -190
- autocoder/sdk/api.py +370 -0
- autocoder/sdk/async_runner/__init__.py +26 -0
- autocoder/sdk/async_runner/async_executor.py +650 -0
- autocoder/sdk/async_runner/async_handler.py +356 -0
- autocoder/sdk/async_runner/markdown_processor.py +595 -0
- autocoder/sdk/async_runner/task_metadata.py +284 -0
- autocoder/sdk/async_runner/worktree_manager.py +438 -0
- autocoder/sdk/cli/__init__.py +2 -5
- autocoder/sdk/cli/formatters.py +28 -204
- autocoder/sdk/cli/handlers.py +77 -44
- autocoder/sdk/cli/main.py +154 -171
- autocoder/sdk/cli/options.py +95 -22
- autocoder/sdk/constants.py +139 -51
- autocoder/sdk/core/auto_coder_core.py +484 -109
- autocoder/sdk/core/bridge.py +297 -115
- autocoder/sdk/exceptions.py +18 -12
- autocoder/sdk/formatters/__init__.py +19 -0
- autocoder/sdk/formatters/input.py +64 -0
- autocoder/sdk/formatters/output.py +247 -0
- autocoder/sdk/formatters/stream.py +54 -0
- autocoder/sdk/models/__init__.py +6 -5
- autocoder/sdk/models/options.py +55 -18
- autocoder/sdk/utils/formatters.py +27 -195
- autocoder/suffixproject/__init__.py +28 -25
- autocoder/terminal/__init__.py +14 -0
- autocoder/terminal/app.py +454 -0
- autocoder/terminal/args.py +32 -0
- autocoder/terminal/bootstrap.py +178 -0
- autocoder/terminal/command_processor.py +521 -0
- autocoder/terminal/command_registry.py +57 -0
- autocoder/terminal/help.py +97 -0
- autocoder/terminal/tasks/__init__.py +5 -0
- autocoder/terminal/tasks/background.py +77 -0
- autocoder/terminal/tasks/task_event.py +70 -0
- autocoder/terminal/ui/__init__.py +13 -0
- autocoder/terminal/ui/completer.py +268 -0
- autocoder/terminal/ui/keybindings.py +75 -0
- autocoder/terminal/ui/session.py +41 -0
- autocoder/terminal/ui/toolbar.py +64 -0
- autocoder/terminal/utils/__init__.py +13 -0
- autocoder/terminal/utils/errors.py +18 -0
- autocoder/terminal/utils/paths.py +19 -0
- autocoder/terminal/utils/shell.py +43 -0
- autocoder/terminal_v3/__init__.py +10 -0
- autocoder/terminal_v3/app.py +201 -0
- autocoder/terminal_v3/handlers/__init__.py +5 -0
- autocoder/terminal_v3/handlers/command_handler.py +131 -0
- autocoder/terminal_v3/models/__init__.py +6 -0
- autocoder/terminal_v3/models/conversation_buffer.py +214 -0
- autocoder/terminal_v3/models/message.py +50 -0
- autocoder/terminal_v3/models/tool_display.py +247 -0
- autocoder/terminal_v3/ui/__init__.py +7 -0
- autocoder/terminal_v3/ui/keybindings.py +56 -0
- autocoder/terminal_v3/ui/layout.py +141 -0
- autocoder/terminal_v3/ui/styles.py +43 -0
- autocoder/tsproject/__init__.py +23 -23
- autocoder/utils/auto_coder_utils/chat_stream_out.py +1 -1
- autocoder/utils/llms.py +88 -80
- autocoder/utils/math_utils.py +101 -0
- autocoder/utils/model_provider_selector.py +16 -4
- autocoder/utils/operate_config_api.py +33 -5
- autocoder/utils/thread_utils.py +2 -2
- autocoder/version.py +4 -2
- autocoder/workflow_agents/__init__.py +84 -0
- autocoder/workflow_agents/agent.py +143 -0
- autocoder/workflow_agents/exceptions.py +573 -0
- autocoder/workflow_agents/executor.py +665 -0
- autocoder/workflow_agents/loader.py +749 -0
- autocoder/workflow_agents/runner.py +267 -0
- autocoder/workflow_agents/types.py +173 -0
- autocoder/workflow_agents/utils.py +434 -0
- autocoder/workflow_agents/workflow_manager.py +211 -0
- auto_coder-1.0.0.dist-info/METADATA +0 -396
- auto_coder-1.0.0.dist-info/RECORD +0 -442
- auto_coder-1.0.0.dist-info/licenses/LICENSE +0 -201
- autocoder/auto_coder_server.py +0 -672
- autocoder/benchmark.py +0 -138
- autocoder/common/ac_style_command_parser/example.py +0 -7
- autocoder/common/cleaner.py +0 -31
- autocoder/common/command_completer_v2.py +0 -615
- autocoder/common/context_pruner.py +0 -477
- autocoder/common/conversation_pruner.py +0 -132
- autocoder/common/directory_cache/__init__.py +0 -1
- autocoder/common/directory_cache/cache.py +0 -192
- autocoder/common/directory_cache/test_cache.py +0 -190
- autocoder/common/file_checkpoint/examples.py +0 -217
- autocoder/common/llm_friendly_package_example.py +0 -138
- autocoder/common/llm_friendly_package_test.py +0 -63
- autocoder/common/pull_requests/test_module.py +0 -1
- autocoder/common/rulefiles/autocoderrules_utils.py +0 -484
- autocoder/common/text.py +0 -30
- autocoder/common/v2/agent/agentic_edit_tools/list_package_info_tool_resolver.py +0 -42
- autocoder/common/v2/agent/agentic_edit_tools/test_execute_command_tool_resolver.py +0 -70
- autocoder/common/v2/agent/agentic_edit_tools/test_search_files_tool_resolver.py +0 -163
- autocoder/common/v2/agent/agentic_tool_display.py +0 -183
- autocoder/plugins/dynamic_completion_example.py +0 -148
- autocoder/plugins/sample_plugin.py +0 -160
- autocoder/sdk/cli/__main__.py +0 -26
- autocoder/sdk/cli/completion_wrapper.py +0 -38
- autocoder/sdk/cli/install_completion.py +0 -301
- autocoder/sdk/models/messages.py +0 -209
- autocoder/sdk/session/__init__.py +0 -32
- autocoder/sdk/session/session.py +0 -106
- autocoder/sdk/session/session_manager.py +0 -56
- {auto_coder-1.0.0.dist-info → auto_coder-2.0.1.dist-info}/top_level.txt +0 -0
- /autocoder/{sdk/example.py → common/agent_query_queue/__init__.py} +0 -0
|
@@ -0,0 +1,536 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Test suite for LLM Friendly Package Manager
|
|
3
|
+
|
|
4
|
+
This module provides comprehensive tests for all package manager functionality
|
|
5
|
+
including library management, documentation handling, repository operations,
|
|
6
|
+
and integration with core_config.
|
|
7
|
+
"""
|
|
8
|
+
|
|
9
|
+
import os
|
|
10
|
+
import tempfile
|
|
11
|
+
import shutil
|
|
12
|
+
import pytest
|
|
13
|
+
from unittest.mock import Mock, patch, MagicMock
|
|
14
|
+
from pathlib import Path
|
|
15
|
+
|
|
16
|
+
from autocoder.common.llm_friendly_package import (
|
|
17
|
+
LLMFriendlyPackageManager,
|
|
18
|
+
get_package_manager,
|
|
19
|
+
LibraryInfo,
|
|
20
|
+
RepositoryInfo,
|
|
21
|
+
PackageDoc
|
|
22
|
+
)
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
class TestLLMFriendlyPackageManager:
|
|
26
|
+
"""Test suite for LLMFriendlyPackageManager"""
|
|
27
|
+
|
|
28
|
+
@pytest.fixture
|
|
29
|
+
def temp_project_root(self):
|
|
30
|
+
"""Create a temporary project root directory"""
|
|
31
|
+
temp_dir = tempfile.mkdtemp()
|
|
32
|
+
yield temp_dir
|
|
33
|
+
shutil.rmtree(temp_dir, ignore_errors=True)
|
|
34
|
+
|
|
35
|
+
@pytest.fixture
|
|
36
|
+
def mock_memory_manager(self):
|
|
37
|
+
"""Mock memory manager for testing"""
|
|
38
|
+
mock_manager = Mock()
|
|
39
|
+
mock_manager.get_libs.return_value = {}
|
|
40
|
+
mock_manager.get_config.return_value = "https://github.com/allwefantasy/llm_friendly_packages"
|
|
41
|
+
mock_manager.has_lib.return_value = False
|
|
42
|
+
mock_manager.add_lib.return_value = None
|
|
43
|
+
mock_manager.remove_lib.return_value = True
|
|
44
|
+
mock_manager.set_config.return_value = None
|
|
45
|
+
return mock_manager
|
|
46
|
+
|
|
47
|
+
@pytest.fixture
|
|
48
|
+
def manager(self, temp_project_root, mock_memory_manager):
|
|
49
|
+
"""Create a package manager instance for testing"""
|
|
50
|
+
with patch('autocoder.common.llm_friendly_package.main_manager.get_memory_manager') as mock_get_memory:
|
|
51
|
+
mock_get_memory.return_value = mock_memory_manager
|
|
52
|
+
return LLMFriendlyPackageManager(temp_project_root)
|
|
53
|
+
|
|
54
|
+
@pytest.fixture
|
|
55
|
+
def mock_repo_structure(self, manager):
|
|
56
|
+
"""Create a mock repository structure for testing"""
|
|
57
|
+
repo_dir = manager.llm_friendly_packages_dir
|
|
58
|
+
os.makedirs(repo_dir, exist_ok=True)
|
|
59
|
+
|
|
60
|
+
# Create test library structure
|
|
61
|
+
test_lib_path = os.path.join(repo_dir, "github.com", "testuser", "testlib")
|
|
62
|
+
os.makedirs(test_lib_path, exist_ok=True)
|
|
63
|
+
|
|
64
|
+
# Create test markdown file
|
|
65
|
+
readme_path = os.path.join(test_lib_path, "README.md")
|
|
66
|
+
with open(readme_path, "w") as f:
|
|
67
|
+
f.write("# Test Library\n\nThis is a test library for LLM.")
|
|
68
|
+
|
|
69
|
+
# Create another test library
|
|
70
|
+
test_lib2_path = os.path.join(repo_dir, "github.com", "testuser", "testlib2")
|
|
71
|
+
os.makedirs(test_lib2_path, exist_ok=True)
|
|
72
|
+
|
|
73
|
+
docs_path = os.path.join(test_lib2_path, "docs.md")
|
|
74
|
+
with open(docs_path, "w") as f:
|
|
75
|
+
f.write("# Test Library 2 Documentation\n\nDetailed docs here.")
|
|
76
|
+
|
|
77
|
+
return repo_dir
|
|
78
|
+
|
|
79
|
+
def test_manager_initialization(self, temp_project_root, mock_memory_manager):
|
|
80
|
+
"""Test manager initialization"""
|
|
81
|
+
with patch('autocoder.common.llm_friendly_package.main_manager.get_memory_manager') as mock_get_memory:
|
|
82
|
+
mock_get_memory.return_value = mock_memory_manager
|
|
83
|
+
|
|
84
|
+
manager = LLMFriendlyPackageManager(temp_project_root)
|
|
85
|
+
|
|
86
|
+
assert manager.project_root == temp_project_root
|
|
87
|
+
assert manager.memory_manager == mock_memory_manager
|
|
88
|
+
assert manager.lib_dir == os.path.join(temp_project_root, ".auto-coder", "libs")
|
|
89
|
+
assert os.path.exists(manager.lib_dir)
|
|
90
|
+
|
|
91
|
+
def test_get_package_manager_function(self, temp_project_root, mock_memory_manager):
|
|
92
|
+
"""Test the convenience function"""
|
|
93
|
+
with patch('autocoder.common.llm_friendly_package.main_manager.get_memory_manager') as mock_get_memory:
|
|
94
|
+
mock_get_memory.return_value = mock_memory_manager
|
|
95
|
+
|
|
96
|
+
manager = get_package_manager(temp_project_root)
|
|
97
|
+
assert isinstance(manager, LLMFriendlyPackageManager)
|
|
98
|
+
assert manager.project_root == temp_project_root
|
|
99
|
+
|
|
100
|
+
def test_default_proxy_url(self, manager):
|
|
101
|
+
"""Test default proxy URL"""
|
|
102
|
+
assert manager.default_proxy_url == "https://github.com/allwefantasy/llm_friendly_packages"
|
|
103
|
+
|
|
104
|
+
def test_list_added_libraries_empty(self, manager):
|
|
105
|
+
"""Test listing libraries when none are added"""
|
|
106
|
+
libs = manager.list_added_libraries()
|
|
107
|
+
assert libs == []
|
|
108
|
+
|
|
109
|
+
def test_list_added_libraries_with_data(self, manager, mock_memory_manager):
|
|
110
|
+
"""Test listing libraries with data"""
|
|
111
|
+
mock_memory_manager.get_libs.return_value = {"numpy": {}, "pandas": {}}
|
|
112
|
+
|
|
113
|
+
libs = manager.list_added_libraries()
|
|
114
|
+
assert set(libs) == {"numpy", "pandas"}
|
|
115
|
+
|
|
116
|
+
def test_add_library_success(self, manager, mock_memory_manager):
|
|
117
|
+
"""Test successful library addition"""
|
|
118
|
+
mock_memory_manager.has_lib.return_value = False
|
|
119
|
+
|
|
120
|
+
with patch.object(manager, '_clone_repository', return_value=True):
|
|
121
|
+
result = manager.add_library("test-lib")
|
|
122
|
+
|
|
123
|
+
assert result is True
|
|
124
|
+
mock_memory_manager.add_lib.assert_called_once_with("test-lib", {})
|
|
125
|
+
|
|
126
|
+
def test_add_library_already_exists(self, manager, mock_memory_manager):
|
|
127
|
+
"""Test adding library that already exists"""
|
|
128
|
+
mock_memory_manager.has_lib.return_value = True
|
|
129
|
+
|
|
130
|
+
with patch.object(manager, '_clone_repository', return_value=True):
|
|
131
|
+
result = manager.add_library("existing-lib")
|
|
132
|
+
|
|
133
|
+
assert result is False
|
|
134
|
+
mock_memory_manager.add_lib.assert_not_called()
|
|
135
|
+
|
|
136
|
+
def test_add_library_clone_fails(self, manager, mock_memory_manager):
|
|
137
|
+
"""Test library addition when repository clone fails"""
|
|
138
|
+
mock_memory_manager.has_lib.return_value = False
|
|
139
|
+
|
|
140
|
+
with patch.object(manager, '_clone_repository', return_value=False):
|
|
141
|
+
result = manager.add_library("test-lib")
|
|
142
|
+
|
|
143
|
+
assert result is False
|
|
144
|
+
mock_memory_manager.add_lib.assert_not_called()
|
|
145
|
+
|
|
146
|
+
def test_remove_library_success(self, manager, mock_memory_manager):
|
|
147
|
+
"""Test successful library removal"""
|
|
148
|
+
mock_memory_manager.has_lib.return_value = True
|
|
149
|
+
|
|
150
|
+
result = manager.remove_library("test-lib")
|
|
151
|
+
|
|
152
|
+
assert result is True
|
|
153
|
+
mock_memory_manager.remove_lib.assert_called_once_with("test-lib")
|
|
154
|
+
|
|
155
|
+
def test_remove_library_not_found(self, manager, mock_memory_manager):
|
|
156
|
+
"""Test removing library that doesn't exist"""
|
|
157
|
+
mock_memory_manager.has_lib.return_value = False
|
|
158
|
+
|
|
159
|
+
result = manager.remove_library("nonexistent-lib")
|
|
160
|
+
|
|
161
|
+
assert result is False
|
|
162
|
+
mock_memory_manager.remove_lib.assert_not_called()
|
|
163
|
+
|
|
164
|
+
def test_has_library(self, manager, mock_memory_manager):
|
|
165
|
+
"""Test checking if library exists"""
|
|
166
|
+
mock_memory_manager.has_lib.side_effect = lambda name: name == "existing-lib"
|
|
167
|
+
|
|
168
|
+
assert manager.has_library("existing-lib") is True
|
|
169
|
+
assert manager.has_library("nonexistent-lib") is False
|
|
170
|
+
|
|
171
|
+
def test_list_all_available_libraries_no_repo(self, manager):
|
|
172
|
+
"""Test listing available libraries when repository doesn't exist"""
|
|
173
|
+
libs = manager.list_all_available_libraries()
|
|
174
|
+
assert libs == []
|
|
175
|
+
|
|
176
|
+
def test_list_all_available_libraries_with_repo(self, manager, mock_repo_structure, mock_memory_manager):
|
|
177
|
+
"""Test listing available libraries with repository"""
|
|
178
|
+
mock_memory_manager.get_libs.return_value = {"testlib": {}}
|
|
179
|
+
|
|
180
|
+
libs = manager.list_all_available_libraries()
|
|
181
|
+
|
|
182
|
+
assert len(libs) == 2
|
|
183
|
+
|
|
184
|
+
# Check first library
|
|
185
|
+
lib1 = next(lib for lib in libs if lib.lib_name == "testlib")
|
|
186
|
+
assert lib1.domain == "github.com"
|
|
187
|
+
assert lib1.username == "testuser"
|
|
188
|
+
assert lib1.lib_name == "testlib"
|
|
189
|
+
assert lib1.full_path == "testuser/testlib"
|
|
190
|
+
assert lib1.is_added is True
|
|
191
|
+
assert lib1.has_md_files is True
|
|
192
|
+
|
|
193
|
+
# Check second library
|
|
194
|
+
lib2 = next(lib for lib in libs if lib.lib_name == "testlib2")
|
|
195
|
+
assert lib2.is_added is False
|
|
196
|
+
|
|
197
|
+
def test_get_package_path_found(self, manager, mock_repo_structure):
|
|
198
|
+
"""Test getting package path when package exists"""
|
|
199
|
+
path = manager.get_package_path("testlib")
|
|
200
|
+
expected_path = os.path.join(mock_repo_structure, "github.com", "testuser", "testlib")
|
|
201
|
+
assert path == expected_path
|
|
202
|
+
|
|
203
|
+
# Test with full path format
|
|
204
|
+
path2 = manager.get_package_path("testuser/testlib")
|
|
205
|
+
assert path2 == expected_path
|
|
206
|
+
|
|
207
|
+
def test_get_package_path_not_found(self, manager, mock_repo_structure):
|
|
208
|
+
"""Test getting package path when package doesn't exist"""
|
|
209
|
+
path = manager.get_package_path("nonexistent")
|
|
210
|
+
assert path is None
|
|
211
|
+
|
|
212
|
+
def test_get_package_path_no_repo(self, manager):
|
|
213
|
+
"""Test getting package path when repository doesn't exist"""
|
|
214
|
+
path = manager.get_package_path("testlib")
|
|
215
|
+
assert path is None
|
|
216
|
+
|
|
217
|
+
def test_get_docs_no_repo(self, manager):
|
|
218
|
+
"""Test getting docs when repository doesn't exist"""
|
|
219
|
+
docs = manager.get_docs()
|
|
220
|
+
assert docs == []
|
|
221
|
+
|
|
222
|
+
def test_get_docs_content(self, manager, mock_repo_structure, mock_memory_manager):
|
|
223
|
+
"""Test getting documentation content"""
|
|
224
|
+
mock_memory_manager.get_libs.return_value = {"testlib": {}, "testlib2": {}}
|
|
225
|
+
|
|
226
|
+
# Get all docs content
|
|
227
|
+
docs = manager.get_docs(return_paths=False)
|
|
228
|
+
assert len(docs) == 2
|
|
229
|
+
assert "# Test Library" in docs[0]
|
|
230
|
+
assert "# Test Library 2 Documentation" in docs[1]
|
|
231
|
+
|
|
232
|
+
# Get specific package docs
|
|
233
|
+
specific_docs = manager.get_docs("testlib", return_paths=False)
|
|
234
|
+
assert len(specific_docs) == 1
|
|
235
|
+
assert "# Test Library" in specific_docs[0]
|
|
236
|
+
|
|
237
|
+
def test_get_docs_paths(self, manager, mock_repo_structure, mock_memory_manager):
|
|
238
|
+
"""Test getting documentation paths"""
|
|
239
|
+
mock_memory_manager.get_libs.return_value = {"testlib": {}, "testlib2": {}}
|
|
240
|
+
|
|
241
|
+
# Get all docs paths
|
|
242
|
+
paths = manager.get_docs(return_paths=True)
|
|
243
|
+
assert len(paths) == 2
|
|
244
|
+
assert all(path.endswith(".md") for path in paths)
|
|
245
|
+
|
|
246
|
+
# Get specific package paths
|
|
247
|
+
specific_paths = manager.get_docs("testlib", return_paths=True)
|
|
248
|
+
assert len(specific_paths) == 1
|
|
249
|
+
assert specific_paths[0].endswith("README.md")
|
|
250
|
+
|
|
251
|
+
def test_get_library_docs_paths(self, manager, mock_repo_structure, mock_memory_manager):
|
|
252
|
+
"""Test getting library documentation paths"""
|
|
253
|
+
mock_memory_manager.get_libs.return_value = {"testlib": {}}
|
|
254
|
+
|
|
255
|
+
paths = manager.get_library_docs_paths("testlib")
|
|
256
|
+
assert len(paths) == 1
|
|
257
|
+
assert paths[0].endswith("README.md")
|
|
258
|
+
|
|
259
|
+
def test_get_library_docs_content(self, manager, mock_repo_structure, mock_memory_manager):
|
|
260
|
+
"""Test getting library documentation content"""
|
|
261
|
+
mock_memory_manager.get_libs.return_value = {"testlib": {}}
|
|
262
|
+
|
|
263
|
+
content = manager.get_library_docs_content("testlib")
|
|
264
|
+
assert len(content) == 1
|
|
265
|
+
assert "# Test Library" in content[0]
|
|
266
|
+
|
|
267
|
+
@patch('git.Repo')
|
|
268
|
+
def test_clone_repository_success(self, mock_git_repo, manager):
|
|
269
|
+
"""Test successful repository cloning"""
|
|
270
|
+
# Repository doesn't exist
|
|
271
|
+
assert not os.path.exists(manager.llm_friendly_packages_dir)
|
|
272
|
+
|
|
273
|
+
result = manager._clone_repository()
|
|
274
|
+
|
|
275
|
+
assert result is True
|
|
276
|
+
mock_git_repo.clone_from.assert_called_once()
|
|
277
|
+
|
|
278
|
+
@patch('git.Repo')
|
|
279
|
+
def test_clone_repository_already_exists(self, mock_git_repo, manager):
|
|
280
|
+
"""Test cloning when repository already exists"""
|
|
281
|
+
# Create the repository directory
|
|
282
|
+
os.makedirs(manager.llm_friendly_packages_dir)
|
|
283
|
+
|
|
284
|
+
result = manager._clone_repository()
|
|
285
|
+
|
|
286
|
+
assert result is True
|
|
287
|
+
mock_git_repo.clone_from.assert_not_called()
|
|
288
|
+
|
|
289
|
+
@patch('git.Repo')
|
|
290
|
+
def test_clone_repository_failure(self, mock_git_repo, manager):
|
|
291
|
+
"""Test repository cloning failure"""
|
|
292
|
+
from git import GitCommandError
|
|
293
|
+
mock_git_repo.clone_from.side_effect = GitCommandError("clone", "Error")
|
|
294
|
+
|
|
295
|
+
result = manager._clone_repository()
|
|
296
|
+
|
|
297
|
+
assert result is False
|
|
298
|
+
|
|
299
|
+
@patch('git.Repo')
|
|
300
|
+
def test_refresh_repository_success(self, mock_git_repo, manager):
|
|
301
|
+
"""Test successful repository refresh"""
|
|
302
|
+
# Create repository directory
|
|
303
|
+
os.makedirs(manager.llm_friendly_packages_dir)
|
|
304
|
+
|
|
305
|
+
# Mock repository
|
|
306
|
+
mock_repo = Mock()
|
|
307
|
+
mock_origin = Mock()
|
|
308
|
+
mock_origin.url = "https://github.com/allwefantasy/llm_friendly_packages"
|
|
309
|
+
mock_repo.remotes.origin = mock_origin
|
|
310
|
+
mock_git_repo.return_value = mock_repo
|
|
311
|
+
|
|
312
|
+
result = manager.refresh_repository()
|
|
313
|
+
|
|
314
|
+
assert result is True
|
|
315
|
+
mock_origin.pull.assert_called_once()
|
|
316
|
+
|
|
317
|
+
def test_refresh_repository_no_repo(self, manager):
|
|
318
|
+
"""Test refreshing when repository doesn't exist"""
|
|
319
|
+
result = manager.refresh_repository()
|
|
320
|
+
assert result is False
|
|
321
|
+
|
|
322
|
+
@patch('git.Repo')
|
|
323
|
+
def test_refresh_repository_failure(self, mock_git_repo, manager):
|
|
324
|
+
"""Test repository refresh failure"""
|
|
325
|
+
from git import GitCommandError
|
|
326
|
+
|
|
327
|
+
# Create repository directory
|
|
328
|
+
os.makedirs(manager.llm_friendly_packages_dir)
|
|
329
|
+
|
|
330
|
+
mock_repo = Mock()
|
|
331
|
+
mock_origin = Mock()
|
|
332
|
+
mock_origin.pull.side_effect = GitCommandError("pull", "Error")
|
|
333
|
+
mock_repo.remotes.origin = mock_origin
|
|
334
|
+
mock_git_repo.return_value = mock_repo
|
|
335
|
+
|
|
336
|
+
result = manager.refresh_repository()
|
|
337
|
+
assert result is False
|
|
338
|
+
|
|
339
|
+
def test_set_proxy_get_current(self, manager, mock_memory_manager):
|
|
340
|
+
"""Test getting current proxy URL"""
|
|
341
|
+
current_proxy = manager.set_proxy()
|
|
342
|
+
expected_url = "https://github.com/allwefantasy/llm_friendly_packages"
|
|
343
|
+
assert current_proxy == expected_url
|
|
344
|
+
mock_memory_manager.get_config.assert_called_with("lib-proxy", expected_url)
|
|
345
|
+
|
|
346
|
+
def test_set_proxy_new_url(self, manager, mock_memory_manager):
|
|
347
|
+
"""Test setting new proxy URL"""
|
|
348
|
+
new_url = "https://custom-proxy.com/repo"
|
|
349
|
+
result = manager.set_proxy(new_url)
|
|
350
|
+
|
|
351
|
+
assert result == new_url
|
|
352
|
+
mock_memory_manager.set_config.assert_called_once_with("lib-proxy", new_url)
|
|
353
|
+
|
|
354
|
+
def test_get_repository_info_exists(self, manager, mock_repo_structure):
|
|
355
|
+
"""Test getting repository info when it exists"""
|
|
356
|
+
with patch('git.Repo') as mock_git_repo:
|
|
357
|
+
# Mock commit
|
|
358
|
+
mock_commit = Mock()
|
|
359
|
+
mock_commit.committed_datetime.isoformat.return_value = "2023-01-01T12:00:00"
|
|
360
|
+
|
|
361
|
+
mock_repo = Mock()
|
|
362
|
+
mock_repo.head.commit = mock_commit
|
|
363
|
+
mock_git_repo.return_value = mock_repo
|
|
364
|
+
|
|
365
|
+
repo_info = manager.get_repository_info()
|
|
366
|
+
|
|
367
|
+
assert repo_info.exists is True
|
|
368
|
+
assert repo_info.url == "https://github.com/allwefantasy/llm_friendly_packages"
|
|
369
|
+
assert repo_info.last_updated == "2023-01-01T12:00:00"
|
|
370
|
+
|
|
371
|
+
def test_get_repository_info_not_exists(self, manager):
|
|
372
|
+
"""Test getting repository info when it doesn't exist"""
|
|
373
|
+
repo_info = manager.get_repository_info()
|
|
374
|
+
|
|
375
|
+
assert repo_info.exists is False
|
|
376
|
+
assert repo_info.url == "https://github.com/allwefantasy/llm_friendly_packages"
|
|
377
|
+
assert repo_info.last_updated is None
|
|
378
|
+
|
|
379
|
+
def test_display_added_libraries_empty(self, manager, capsys):
|
|
380
|
+
"""Test displaying empty library list"""
|
|
381
|
+
manager.display_added_libraries()
|
|
382
|
+
captured = capsys.readouterr()
|
|
383
|
+
assert "No libraries added yet" in captured.out
|
|
384
|
+
|
|
385
|
+
def test_display_added_libraries_with_data(self, manager, mock_memory_manager, capsys):
|
|
386
|
+
"""Test displaying library list with data"""
|
|
387
|
+
mock_memory_manager.get_libs.return_value = {"numpy": {}, "pandas": {}}
|
|
388
|
+
|
|
389
|
+
manager.display_added_libraries()
|
|
390
|
+
captured = capsys.readouterr()
|
|
391
|
+
# Console output includes library names in the table
|
|
392
|
+
assert "numpy" in captured.out or "pandas" in captured.out
|
|
393
|
+
|
|
394
|
+
def test_display_all_libraries_no_repo(self, manager, capsys):
|
|
395
|
+
"""Test displaying all libraries when repository doesn't exist"""
|
|
396
|
+
manager.display_all_libraries()
|
|
397
|
+
captured = capsys.readouterr()
|
|
398
|
+
assert "repository does not exist" in captured.out
|
|
399
|
+
|
|
400
|
+
def test_display_library_docs_no_docs(self, manager, capsys):
|
|
401
|
+
"""Test displaying library docs when none exist"""
|
|
402
|
+
manager.display_library_docs("nonexistent")
|
|
403
|
+
captured = capsys.readouterr()
|
|
404
|
+
assert "No markdown files found" in captured.out
|
|
405
|
+
|
|
406
|
+
|
|
407
|
+
class TestDataModels:
|
|
408
|
+
"""Test suite for data models"""
|
|
409
|
+
|
|
410
|
+
def test_library_info_creation(self):
|
|
411
|
+
"""Test LibraryInfo creation"""
|
|
412
|
+
lib_info = LibraryInfo(
|
|
413
|
+
domain="github.com",
|
|
414
|
+
username="testuser",
|
|
415
|
+
lib_name="testlib",
|
|
416
|
+
full_path="testuser/testlib",
|
|
417
|
+
is_added=True,
|
|
418
|
+
has_md_files=True
|
|
419
|
+
)
|
|
420
|
+
|
|
421
|
+
assert lib_info.domain == "github.com"
|
|
422
|
+
assert lib_info.username == "testuser"
|
|
423
|
+
assert lib_info.lib_name == "testlib"
|
|
424
|
+
assert lib_info.full_path == "testuser/testlib"
|
|
425
|
+
assert lib_info.is_added is True
|
|
426
|
+
assert lib_info.has_md_files is True
|
|
427
|
+
|
|
428
|
+
def test_library_info_defaults(self):
|
|
429
|
+
"""Test LibraryInfo default values"""
|
|
430
|
+
lib_info = LibraryInfo(
|
|
431
|
+
domain="github.com",
|
|
432
|
+
username="testuser",
|
|
433
|
+
lib_name="testlib",
|
|
434
|
+
full_path="testuser/testlib",
|
|
435
|
+
is_added=False
|
|
436
|
+
)
|
|
437
|
+
|
|
438
|
+
assert lib_info.has_md_files is True # Default value
|
|
439
|
+
|
|
440
|
+
def test_package_doc_creation(self):
|
|
441
|
+
"""Test PackageDoc creation"""
|
|
442
|
+
doc = PackageDoc(
|
|
443
|
+
file_path="/path/to/doc.md",
|
|
444
|
+
content="# Documentation"
|
|
445
|
+
)
|
|
446
|
+
|
|
447
|
+
assert doc.file_path == "/path/to/doc.md"
|
|
448
|
+
assert doc.content == "# Documentation"
|
|
449
|
+
|
|
450
|
+
def test_package_doc_no_content(self):
|
|
451
|
+
"""Test PackageDoc without content"""
|
|
452
|
+
doc = PackageDoc(file_path="/path/to/doc.md")
|
|
453
|
+
|
|
454
|
+
assert doc.file_path == "/path/to/doc.md"
|
|
455
|
+
assert doc.content is None
|
|
456
|
+
|
|
457
|
+
def test_repository_info_creation(self):
|
|
458
|
+
"""Test RepositoryInfo creation"""
|
|
459
|
+
repo_info = RepositoryInfo(
|
|
460
|
+
exists=True,
|
|
461
|
+
url="https://github.com/test/repo",
|
|
462
|
+
last_updated="2023-01-01T12:00:00"
|
|
463
|
+
)
|
|
464
|
+
|
|
465
|
+
assert repo_info.exists is True
|
|
466
|
+
assert repo_info.url == "https://github.com/test/repo"
|
|
467
|
+
assert repo_info.last_updated == "2023-01-01T12:00:00"
|
|
468
|
+
|
|
469
|
+
def test_repository_info_defaults(self):
|
|
470
|
+
"""Test RepositoryInfo default values"""
|
|
471
|
+
repo_info = RepositoryInfo(
|
|
472
|
+
exists=False,
|
|
473
|
+
url="https://github.com/test/repo"
|
|
474
|
+
)
|
|
475
|
+
|
|
476
|
+
assert repo_info.exists is False
|
|
477
|
+
assert repo_info.url == "https://github.com/test/repo"
|
|
478
|
+
assert repo_info.last_updated is None
|
|
479
|
+
|
|
480
|
+
|
|
481
|
+
class TestIntegration:
|
|
482
|
+
"""Integration tests"""
|
|
483
|
+
|
|
484
|
+
@pytest.fixture
|
|
485
|
+
def real_temp_project(self):
|
|
486
|
+
"""Create a real temporary project for integration testing"""
|
|
487
|
+
temp_dir = tempfile.mkdtemp()
|
|
488
|
+
yield temp_dir
|
|
489
|
+
shutil.rmtree(temp_dir, ignore_errors=True)
|
|
490
|
+
|
|
491
|
+
def test_full_workflow_with_mocked_git(self, real_temp_project):
|
|
492
|
+
"""Test a complete workflow with mocked git operations"""
|
|
493
|
+
with patch('git.Repo') as mock_git_repo:
|
|
494
|
+
# Create manager
|
|
495
|
+
manager = LLMFriendlyPackageManager(real_temp_project)
|
|
496
|
+
|
|
497
|
+
# Add a library (this will trigger repository cloning)
|
|
498
|
+
result = manager.add_library("test-library")
|
|
499
|
+
assert result is True
|
|
500
|
+
|
|
501
|
+
# Check that library is added
|
|
502
|
+
assert manager.has_library("test-library")
|
|
503
|
+
libs = manager.list_added_libraries()
|
|
504
|
+
assert "test-library" in libs
|
|
505
|
+
|
|
506
|
+
# Remove the library
|
|
507
|
+
result = manager.remove_library("test-library")
|
|
508
|
+
assert result is True
|
|
509
|
+
assert not manager.has_library("test-library")
|
|
510
|
+
|
|
511
|
+
def test_error_handling_in_docs_reading(self, real_temp_project):
|
|
512
|
+
"""Test error handling when reading documentation files"""
|
|
513
|
+
manager = LLMFriendlyPackageManager(real_temp_project)
|
|
514
|
+
|
|
515
|
+
# Create a corrupted file structure
|
|
516
|
+
repo_dir = manager.llm_friendly_packages_dir
|
|
517
|
+
os.makedirs(repo_dir, exist_ok=True)
|
|
518
|
+
|
|
519
|
+
test_lib_path = os.path.join(repo_dir, "github.com", "testuser", "testlib")
|
|
520
|
+
os.makedirs(test_lib_path, exist_ok=True)
|
|
521
|
+
|
|
522
|
+
# Create a file with permission issues (simulate by creating a directory with same name)
|
|
523
|
+
bad_file_path = os.path.join(test_lib_path, "README.md")
|
|
524
|
+
os.makedirs(bad_file_path, exist_ok=True) # This will cause read error
|
|
525
|
+
|
|
526
|
+
# Add the library
|
|
527
|
+
manager.add_library("testlib")
|
|
528
|
+
|
|
529
|
+
# Try to read docs - should handle the error gracefully
|
|
530
|
+
docs = manager.get_library_docs_content("testlib")
|
|
531
|
+
assert docs == [] # Should return empty list on error
|
|
532
|
+
|
|
533
|
+
|
|
534
|
+
if __name__ == "__main__":
|
|
535
|
+
# Run tests when script is executed directly
|
|
536
|
+
pytest.main([__file__, "-v"])
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
"""
|
|
3
|
+
LLM Error Handling Mechanism Demo Script
|
|
4
|
+
Demonstrates the new detailed error message functionality
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
import tempfile
|
|
8
|
+
from pathlib import Path
|
|
9
|
+
from autocoder.common.llms import LLMManager
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
def demo_error_handling():
|
|
13
|
+
"""Demonstrate detailed error handling mechanism"""
|
|
14
|
+
print("=== LLM Error Handling Mechanism Demo ===\n")
|
|
15
|
+
|
|
16
|
+
# Use temporary directory to avoid affecting user configuration
|
|
17
|
+
with tempfile.TemporaryDirectory() as temp_dir:
|
|
18
|
+
models_json = Path(temp_dir) / "models.json"
|
|
19
|
+
lm = LLMManager(str(models_json))
|
|
20
|
+
|
|
21
|
+
print("1. Attempting to get non-existent model...")
|
|
22
|
+
try:
|
|
23
|
+
llm = lm.get_single_llm("non/existent", "lite")
|
|
24
|
+
print(" ✗ Unexpected success")
|
|
25
|
+
except ValueError as e:
|
|
26
|
+
print(f" ✓ Correctly caught error:")
|
|
27
|
+
print(f" {str(e)}")
|
|
28
|
+
print()
|
|
29
|
+
|
|
30
|
+
print("2. Attempting to get existing model without API key...")
|
|
31
|
+
try:
|
|
32
|
+
llm = lm.get_single_llm("deepseek/v3", "lite")
|
|
33
|
+
print(" ✗ Unexpected success")
|
|
34
|
+
except ValueError as e:
|
|
35
|
+
print(f" ✓ Correctly caught error:")
|
|
36
|
+
print(f" {str(e)}")
|
|
37
|
+
print()
|
|
38
|
+
|
|
39
|
+
print("3. Attempting to get multiple models, all unavailable...")
|
|
40
|
+
try:
|
|
41
|
+
llm = lm.get_single_llm("non/existent1,deepseek/v3,non/existent2", "lite")
|
|
42
|
+
print(" ✗ Unexpected success")
|
|
43
|
+
except ValueError as e:
|
|
44
|
+
print(f" ✓ Correctly caught error:")
|
|
45
|
+
print(f" {str(e)}")
|
|
46
|
+
print()
|
|
47
|
+
|
|
48
|
+
print("4. Adding a model with API key and testing...")
|
|
49
|
+
custom_models = [
|
|
50
|
+
{
|
|
51
|
+
"name": "demo/working",
|
|
52
|
+
"model_name": "demo-working-model",
|
|
53
|
+
"model_type": "saas/openai",
|
|
54
|
+
"base_url": "https://demo.api.com/v1",
|
|
55
|
+
"api_key": "demo-key-123"
|
|
56
|
+
}
|
|
57
|
+
]
|
|
58
|
+
lm.add_models(custom_models)
|
|
59
|
+
|
|
60
|
+
try:
|
|
61
|
+
# This should succeed (although actual deployment would fail, but not due to key issues)
|
|
62
|
+
print(" ✓ Model added successfully with API key configured")
|
|
63
|
+
except Exception as e:
|
|
64
|
+
print(f" ✗ Model addition failed: {e}")
|
|
65
|
+
print()
|
|
66
|
+
|
|
67
|
+
print("5. Demonstrating new error messages vs old error messages...")
|
|
68
|
+
print(" Old error message: 'NoneType' object has no attribute 'stream_chat_oai'")
|
|
69
|
+
print(" New error message: Contains specific model names and failure reasons")
|
|
70
|
+
print()
|
|
71
|
+
|
|
72
|
+
print("=== Demo Complete ===")
|
|
73
|
+
print("Now users can clearly see:")
|
|
74
|
+
print("- Which models don't exist")
|
|
75
|
+
print("- Which models don't have API keys configured")
|
|
76
|
+
print("- Specific error reason for each model")
|
|
77
|
+
|
|
78
|
+
|
|
79
|
+
if __name__ == "__main__":
|
|
80
|
+
try:
|
|
81
|
+
demo_error_handling()
|
|
82
|
+
except Exception as e:
|
|
83
|
+
print(f"Error during demo: {e}")
|
|
84
|
+
import traceback
|
|
85
|
+
traceback.print_exc()
|