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
autocoder/common/text.py
DELETED
|
@@ -1,30 +0,0 @@
|
|
|
1
|
-
from difflib import SequenceMatcher
|
|
2
|
-
|
|
3
|
-
class TextSimilarity:
|
|
4
|
-
def __init__(self, text_a, text_b):
|
|
5
|
-
self.text_a = text_a
|
|
6
|
-
self.text_b = text_b
|
|
7
|
-
self.lines_a = self._split_into_lines(text_a)
|
|
8
|
-
self.lines_b = self._split_into_lines(text_b)
|
|
9
|
-
self.m = len(self.lines_a)
|
|
10
|
-
self.n = len(self.lines_b)
|
|
11
|
-
|
|
12
|
-
def _split_into_lines(self, text):
|
|
13
|
-
return text.splitlines()
|
|
14
|
-
|
|
15
|
-
def _levenshtein_ratio(self, s1, s2):
|
|
16
|
-
return SequenceMatcher(None, s1, s2).ratio()
|
|
17
|
-
|
|
18
|
-
def get_best_matching_window(self):
|
|
19
|
-
best_similarity = 0
|
|
20
|
-
best_window = []
|
|
21
|
-
|
|
22
|
-
for i in range(self.n - self.m + 1): # 滑动窗口
|
|
23
|
-
window_b = self.lines_b[i:i + self.m]
|
|
24
|
-
similarity = self._levenshtein_ratio("\n".join(self.lines_a), "\n".join(window_b))
|
|
25
|
-
|
|
26
|
-
if similarity > best_similarity:
|
|
27
|
-
best_similarity = similarity
|
|
28
|
-
best_window = window_b
|
|
29
|
-
|
|
30
|
-
return best_similarity, "\n".join(best_window)
|
|
@@ -1,42 +0,0 @@
|
|
|
1
|
-
|
|
2
|
-
import os
|
|
3
|
-
from typing import Optional
|
|
4
|
-
from autocoder.common.v2.agent.agentic_edit_tools.base_tool_resolver import BaseToolResolver
|
|
5
|
-
from autocoder.common.v2.agent.agentic_edit_types import ListPackageInfoTool, ToolResult
|
|
6
|
-
from loguru import logger
|
|
7
|
-
import typing
|
|
8
|
-
|
|
9
|
-
if typing.TYPE_CHECKING:
|
|
10
|
-
from autocoder.common.v2.agent.agentic_edit import AgenticEdit
|
|
11
|
-
|
|
12
|
-
class ListPackageInfoToolResolver(BaseToolResolver):
|
|
13
|
-
def __init__(self, agent: Optional['AgenticEdit'], tool: ListPackageInfoTool, args):
|
|
14
|
-
super().__init__(agent, tool, args)
|
|
15
|
-
self.tool: ListPackageInfoTool = tool
|
|
16
|
-
|
|
17
|
-
def resolve(self) -> ToolResult:
|
|
18
|
-
source_dir = self.args.source_dir or "."
|
|
19
|
-
abs_source_dir = os.path.abspath(source_dir)
|
|
20
|
-
|
|
21
|
-
input_path = self.tool.path.strip()
|
|
22
|
-
abs_input_path = os.path.abspath(os.path.join(source_dir, input_path)) if not os.path.isabs(input_path) else input_path
|
|
23
|
-
|
|
24
|
-
# 校验输入目录是否在项目目录内
|
|
25
|
-
if not abs_input_path.startswith(abs_source_dir):
|
|
26
|
-
return ToolResult(success=False, message=f"Error: Access denied. Path outside project: {self.tool.path}")
|
|
27
|
-
|
|
28
|
-
rel_package_path = os.path.relpath(abs_input_path, abs_source_dir)
|
|
29
|
-
active_md_path = os.path.join(abs_source_dir, ".auto-coder", "active-context", rel_package_path, "active.md")
|
|
30
|
-
|
|
31
|
-
logger.info(f"Looking for package info at: {active_md_path}")
|
|
32
|
-
|
|
33
|
-
if not os.path.exists(active_md_path):
|
|
34
|
-
return ToolResult(success=True, message="No package info found for this path.", content="没有相关包信息。")
|
|
35
|
-
|
|
36
|
-
try:
|
|
37
|
-
with open(active_md_path, 'r', encoding='utf-8', errors='replace') as f:
|
|
38
|
-
content = f.read()
|
|
39
|
-
return ToolResult(success=True, message="Successfully retrieved package info.", content=content)
|
|
40
|
-
except Exception as e:
|
|
41
|
-
logger.error(f"Error reading package info file: {e}")
|
|
42
|
-
return ToolResult(success=False, message=f"Error reading package info file: {e}")
|
|
@@ -1,70 +0,0 @@
|
|
|
1
|
-
import pytest
|
|
2
|
-
from unittest.mock import MagicMock, patch
|
|
3
|
-
from autocoder.common.v2.agent.agentic_edit_tools \
|
|
4
|
-
.execute_command_tool_resolver import ExecuteCommandToolResolver
|
|
5
|
-
from autocoder.common.v2.agent.agentic_edit_types import ExecuteCommandTool
|
|
6
|
-
from autocoder.common import AutoCoderArgs
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
class TestExecuteCommandToolResolver:
|
|
10
|
-
@pytest.fixture
|
|
11
|
-
def mock_agent(self):
|
|
12
|
-
agent = MagicMock()
|
|
13
|
-
agent.args = AutoCoderArgs()
|
|
14
|
-
agent.args.context_prune_safe_zone_tokens = 1000
|
|
15
|
-
agent.context_prune_llm = None
|
|
16
|
-
agent.current_conversations = []
|
|
17
|
-
return agent
|
|
18
|
-
|
|
19
|
-
@pytest.fixture
|
|
20
|
-
def mock_tool(self):
|
|
21
|
-
return ExecuteCommandTool(
|
|
22
|
-
command="echo 'test output'",
|
|
23
|
-
requires_approval=False
|
|
24
|
-
)
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
def test_command_execution_with_token_count(self, mock_agent, mock_tool):
|
|
28
|
-
"""测试命令执行并验证token统计功能"""
|
|
29
|
-
resolver = ExecuteCommandToolResolver(mock_agent, mock_tool, mock_agent.args)
|
|
30
|
-
|
|
31
|
-
# 模拟命令执行返回大量输出
|
|
32
|
-
with patch("autocoder.common.run_cmd.run_cmd_subprocess") as mock_run_cmd:
|
|
33
|
-
mock_run_cmd.return_value = (0, "test output " * 500) # 生成大量输出
|
|
34
|
-
|
|
35
|
-
result = resolver.resolve()
|
|
36
|
-
|
|
37
|
-
assert result.success
|
|
38
|
-
assert "test output" in result.content
|
|
39
|
-
|
|
40
|
-
# 验证token统计功能
|
|
41
|
-
# 这里需要修改ExecuteCommandToolResolver来添加token统计功能
|
|
42
|
-
# 测试将失败,符合TDD的红色阶段
|
|
43
|
-
|
|
44
|
-
def test_output_pruning_when_exceeds_token_limit(self, mock_agent, mock_tool):
|
|
45
|
-
"""测试当输出超过token限制时的裁剪功能"""
|
|
46
|
-
resolver = ExecuteCommandToolResolver(mock_agent, mock_tool, mock_agent.args)
|
|
47
|
-
|
|
48
|
-
# 模拟命令执行返回大量输出
|
|
49
|
-
with patch("autocoder.common.run_cmd.run_cmd_subprocess") as mock_run_cmd:
|
|
50
|
-
mock_run_cmd.return_value = (0, "test output " * 500) # 生成大量输出
|
|
51
|
-
|
|
52
|
-
result = resolver.resolve()
|
|
53
|
-
|
|
54
|
-
assert result.success
|
|
55
|
-
# 验证输出是否被裁剪
|
|
56
|
-
# 这里需要修改ExecuteCommandToolResolver来添加裁剪功能
|
|
57
|
-
# 测试将失败,符合TDD的红色阶段
|
|
58
|
-
|
|
59
|
-
def test_command_execution_failure(self, mock_agent, mock_tool):
|
|
60
|
-
"""测试命令执行失败的情况"""
|
|
61
|
-
resolver = ExecuteCommandToolResolver(mock_agent, mock_tool, mock_agent.args)
|
|
62
|
-
|
|
63
|
-
# 模拟命令执行失败
|
|
64
|
-
with patch("autocoder.common.run_cmd.run_cmd_subprocess") as mock_run_cmd:
|
|
65
|
-
mock_run_cmd.return_value = (1, "command failed")
|
|
66
|
-
|
|
67
|
-
result = resolver.resolve()
|
|
68
|
-
|
|
69
|
-
assert not result.success
|
|
70
|
-
assert "command failed" in result.message
|
|
@@ -1,163 +0,0 @@
|
|
|
1
|
-
import pytest
|
|
2
|
-
import os
|
|
3
|
-
import tempfile
|
|
4
|
-
import shutil
|
|
5
|
-
from unittest.mock import patch, MagicMock
|
|
6
|
-
|
|
7
|
-
from autocoder.common.v2.agent.agentic_edit_tools.search_files_tool_resolver import SearchFilesToolResolver
|
|
8
|
-
from autocoder.common.v2.agent.agentic_edit_types import SearchFilesTool, ToolResult
|
|
9
|
-
from autocoder.common import AutoCoderArgs
|
|
10
|
-
|
|
11
|
-
# Helper function to create a directory structure with files for testing
|
|
12
|
-
def create_test_files(base_dir, structure):
|
|
13
|
-
"""
|
|
14
|
-
Creates a directory structure with files based on the provided dictionary.
|
|
15
|
-
Keys are filenames (relative to base_dir), values are file contents.
|
|
16
|
-
Directories are created automatically.
|
|
17
|
-
"""
|
|
18
|
-
for path, content in structure.items():
|
|
19
|
-
full_path = os.path.join(base_dir, path)
|
|
20
|
-
os.makedirs(os.path.dirname(full_path), exist_ok=True)
|
|
21
|
-
with open(full_path, 'w') as f:
|
|
22
|
-
f.write(content)
|
|
23
|
-
|
|
24
|
-
@pytest.fixture
|
|
25
|
-
def search_tool_resolver(temp_search_dir):
|
|
26
|
-
"""Fixture to provide an instance of SearchFilesToolResolver."""
|
|
27
|
-
# Create AutoCoderArgs with the temp directory as source_dir to allow the security check to pass
|
|
28
|
-
args = AutoCoderArgs()
|
|
29
|
-
args.source_dir = temp_search_dir # Set the source_dir to our temp directory
|
|
30
|
-
return SearchFilesToolResolver(None, SearchFilesTool(path="", regex=""), args)
|
|
31
|
-
|
|
32
|
-
@pytest.fixture(scope="function")
|
|
33
|
-
def temp_search_dir():
|
|
34
|
-
"""Fixture to create a temporary directory with test files for searching."""
|
|
35
|
-
temp_dir = tempfile.mkdtemp()
|
|
36
|
-
test_structure = {
|
|
37
|
-
"file1.txt": "Hello world\nThis is a test file.",
|
|
38
|
-
"subdir/file2.py": "import sys\n\ndef main():\n print('Python script')\n",
|
|
39
|
-
"subdir/another.txt": "Another text file with world.",
|
|
40
|
-
".hiddenfile": "This should be ignored by default",
|
|
41
|
-
"no_match.md": "Markdown file."
|
|
42
|
-
}
|
|
43
|
-
create_test_files(temp_dir, test_structure)
|
|
44
|
-
yield temp_dir # Provide the path to the test function
|
|
45
|
-
shutil.rmtree(temp_dir) # Cleanup after test
|
|
46
|
-
|
|
47
|
-
# --- Test Cases ---
|
|
48
|
-
|
|
49
|
-
def test_resolve_finds_matches(search_tool_resolver, temp_search_dir):
|
|
50
|
-
"""Test that resolve finds matches correctly."""
|
|
51
|
-
# Set up the tool with the pattern we want to search for
|
|
52
|
-
tool = SearchFilesTool(
|
|
53
|
-
path="", # Use empty path to search in the source_dir itself
|
|
54
|
-
regex="world",
|
|
55
|
-
file_pattern="*.txt"
|
|
56
|
-
)
|
|
57
|
-
search_tool_resolver.tool = tool
|
|
58
|
-
|
|
59
|
-
# Call the resolve method directly
|
|
60
|
-
response = search_tool_resolver.resolve()
|
|
61
|
-
|
|
62
|
-
# Check the response
|
|
63
|
-
assert isinstance(response, ToolResult)
|
|
64
|
-
assert response.success
|
|
65
|
-
assert "Search completed. Found 2 matches" in response.message
|
|
66
|
-
|
|
67
|
-
# Check that the correct files were found
|
|
68
|
-
assert len(response.content) == 2
|
|
69
|
-
paths = [result["path"] for result in response.content]
|
|
70
|
-
assert any("file1.txt" in path for path in paths)
|
|
71
|
-
assert any("another.txt" in path for path in paths)
|
|
72
|
-
|
|
73
|
-
# Check that the match lines contain our search pattern
|
|
74
|
-
for result in response.content:
|
|
75
|
-
assert "world" in result["match_line"]
|
|
76
|
-
|
|
77
|
-
def test_resolve_no_matches(search_tool_resolver, temp_search_dir):
|
|
78
|
-
"""Test that resolve handles no matches correctly."""
|
|
79
|
-
tool = SearchFilesTool(
|
|
80
|
-
path="", # Use empty path to search in the source_dir itself
|
|
81
|
-
regex="nonexistent_pattern",
|
|
82
|
-
file_pattern="*"
|
|
83
|
-
)
|
|
84
|
-
search_tool_resolver.tool = tool
|
|
85
|
-
|
|
86
|
-
response = search_tool_resolver.resolve()
|
|
87
|
-
|
|
88
|
-
assert isinstance(response, ToolResult)
|
|
89
|
-
assert response.success # Still success, just no results
|
|
90
|
-
assert "Search completed. Found 0 matches" in response.message
|
|
91
|
-
assert len(response.content) == 0
|
|
92
|
-
|
|
93
|
-
def test_resolve_file_pattern(search_tool_resolver, temp_search_dir):
|
|
94
|
-
"""Test that the file_pattern is correctly applied."""
|
|
95
|
-
# Test .txt pattern
|
|
96
|
-
tool_txt = SearchFilesTool(
|
|
97
|
-
path="", # Use empty path to search in the source_dir itself
|
|
98
|
-
regex="world",
|
|
99
|
-
file_pattern="*.txt" # Only search .txt files
|
|
100
|
-
)
|
|
101
|
-
search_tool_resolver.tool = tool_txt
|
|
102
|
-
|
|
103
|
-
response_txt = search_tool_resolver.resolve()
|
|
104
|
-
|
|
105
|
-
assert isinstance(response_txt, ToolResult)
|
|
106
|
-
assert response_txt.success
|
|
107
|
-
assert "Search completed. Found 2 matches" in response_txt.message
|
|
108
|
-
# Ensure only .txt files were matched
|
|
109
|
-
for result in response_txt.content:
|
|
110
|
-
assert result["path"].endswith(".txt")
|
|
111
|
-
|
|
112
|
-
# Test .py pattern
|
|
113
|
-
tool_py = SearchFilesTool(
|
|
114
|
-
path="", # Use empty path to search in the source_dir itself
|
|
115
|
-
regex="print",
|
|
116
|
-
file_pattern="*.py" # Only search .py files
|
|
117
|
-
)
|
|
118
|
-
search_tool_resolver.tool = tool_py
|
|
119
|
-
|
|
120
|
-
response_py = search_tool_resolver.resolve()
|
|
121
|
-
|
|
122
|
-
assert isinstance(response_py, ToolResult)
|
|
123
|
-
assert response_py.success
|
|
124
|
-
assert "Search completed. Found 1 matches" in response_py.message
|
|
125
|
-
# Ensure only .py files were matched
|
|
126
|
-
for result in response_py.content:
|
|
127
|
-
assert result["path"].endswith(".py")
|
|
128
|
-
|
|
129
|
-
def test_invalid_regex(search_tool_resolver, temp_search_dir):
|
|
130
|
-
"""Test that an invalid regex pattern is properly handled."""
|
|
131
|
-
tool = SearchFilesTool(
|
|
132
|
-
path="", # Use empty path to search in the source_dir itself
|
|
133
|
-
regex="[invalid regex", # Invalid regex pattern
|
|
134
|
-
file_pattern="*"
|
|
135
|
-
)
|
|
136
|
-
search_tool_resolver.tool = tool
|
|
137
|
-
|
|
138
|
-
response = search_tool_resolver.resolve()
|
|
139
|
-
|
|
140
|
-
assert isinstance(response, ToolResult)
|
|
141
|
-
assert not response.success
|
|
142
|
-
assert "Invalid regex pattern" in response.message
|
|
143
|
-
|
|
144
|
-
def test_nonexistent_path(search_tool_resolver, temp_search_dir):
|
|
145
|
-
"""Test that a nonexistent path is properly handled."""
|
|
146
|
-
# Create a path that we know doesn't exist under temp_search_dir
|
|
147
|
-
nonexistent_path = "nonexistent_subdirectory"
|
|
148
|
-
|
|
149
|
-
tool = SearchFilesTool(
|
|
150
|
-
path=nonexistent_path, # This path doesn't exist in our temp directory
|
|
151
|
-
regex="pattern",
|
|
152
|
-
file_pattern="*"
|
|
153
|
-
)
|
|
154
|
-
search_tool_resolver.tool = tool
|
|
155
|
-
|
|
156
|
-
response = search_tool_resolver.resolve()
|
|
157
|
-
|
|
158
|
-
assert isinstance(response, ToolResult)
|
|
159
|
-
assert not response.success
|
|
160
|
-
assert "Error: Search path not found" in response.message
|
|
161
|
-
|
|
162
|
-
# Add more tests as needed
|
|
163
|
-
|
|
@@ -1,183 +0,0 @@
|
|
|
1
|
-
import json
|
|
2
|
-
from typing import Dict, Callable, Type
|
|
3
|
-
from autocoder.common.auto_coder_lang import get_system_language, format_str_jinja2
|
|
4
|
-
from autocoder.common.v2.agent.agentic_edit_types import (
|
|
5
|
-
BaseTool,
|
|
6
|
-
ReadFileTool, WriteToFileTool, ReplaceInFileTool, ExecuteCommandTool,
|
|
7
|
-
ListFilesTool, SearchFilesTool, ListCodeDefinitionNamesTool,
|
|
8
|
-
AskFollowupQuestionTool, UseMcpTool, AttemptCompletionTool
|
|
9
|
-
)
|
|
10
|
-
|
|
11
|
-
# Define message templates for each tool in English and Chinese
|
|
12
|
-
TOOL_DISPLAY_MESSAGES: Dict[Type[BaseTool], Dict[str, str]] = {
|
|
13
|
-
ReadFileTool: {
|
|
14
|
-
"en": "AutoCoder wants to read this file:\n[bold cyan]{{ path }}[/]",
|
|
15
|
-
"zh": "AutoCoder 想要读取此文件:\n[bold cyan]{{ path }}[/]"
|
|
16
|
-
},
|
|
17
|
-
WriteToFileTool: {
|
|
18
|
-
"en": (
|
|
19
|
-
"AutoCoder wants to write to this file:\n[bold cyan]{{ path }}[/]\n\n"
|
|
20
|
-
"[dim]Content Snippet:[/dim]\n{{ content_snippet }}{{ ellipsis }}"
|
|
21
|
-
),
|
|
22
|
-
"zh": (
|
|
23
|
-
"AutoCoder 想要写入此文件:\n[bold cyan]{{ path }}[/]\n\n"
|
|
24
|
-
"[dim]内容片段:[/dim]\n{{ content_snippet }}{{ ellipsis }}"
|
|
25
|
-
)
|
|
26
|
-
},
|
|
27
|
-
ReplaceInFileTool: {
|
|
28
|
-
"en": (
|
|
29
|
-
"AutoCoder wants to replace content in this file:\n[bold cyan]{{ path }}[/]\n\n"
|
|
30
|
-
"[dim]Diff Snippet:[/dim]\n{{ diff_snippet }}{{ ellipsis }}"
|
|
31
|
-
),
|
|
32
|
-
"zh": (
|
|
33
|
-
"AutoCoder 想要替换此文件中的内容:\n[bold cyan]{{ path }}[/]\n\n"
|
|
34
|
-
"[dim]差异片段:[/dim]\n{{ diff_snippet }}{{ ellipsis }}"
|
|
35
|
-
)
|
|
36
|
-
},
|
|
37
|
-
ExecuteCommandTool: {
|
|
38
|
-
"en": (
|
|
39
|
-
"AutoCoder wants to execute this command:\n[bold yellow]{{ command }}[/]\n"
|
|
40
|
-
"[dim](Requires Approval: {{ requires_approval }})[/]"
|
|
41
|
-
),
|
|
42
|
-
"zh": (
|
|
43
|
-
"AutoCoder 想要执行此命令:\n[bold yellow]{{ command }}[/]\n"
|
|
44
|
-
"[dim](需要批准:{{ requires_approval }})[/]"
|
|
45
|
-
)
|
|
46
|
-
},
|
|
47
|
-
ListFilesTool: {
|
|
48
|
-
"en": (
|
|
49
|
-
"AutoCoder wants to list files in:\n[bold green]{{ path }}[/] "
|
|
50
|
-
"{{ recursive_text }}"
|
|
51
|
-
),
|
|
52
|
-
"zh": (
|
|
53
|
-
"AutoCoder 想要列出此目录中的文件:\n[bold green]{{ path }}[/] "
|
|
54
|
-
"{{ recursive_text }}"
|
|
55
|
-
)
|
|
56
|
-
},
|
|
57
|
-
SearchFilesTool: {
|
|
58
|
-
"en": (
|
|
59
|
-
"AutoCoder wants to search files in:\n[bold green]{{ path }}[/]\n"
|
|
60
|
-
"[dim]File Pattern:[/dim] [yellow]{{ file_pattern }}[/]\n"
|
|
61
|
-
"[dim]Regex:[/dim] [yellow]{{ regex }}[/]"
|
|
62
|
-
),
|
|
63
|
-
"zh": (
|
|
64
|
-
"AutoCoder 想要在此目录中搜索文件:\n[bold green]{{ path }}[/]\n"
|
|
65
|
-
"[dim]文件模式:[/dim] [yellow]{{ file_pattern }}[/]\n"
|
|
66
|
-
"[dim]正则表达式:[/dim] [yellow]{{ regex }}[/]"
|
|
67
|
-
)
|
|
68
|
-
},
|
|
69
|
-
ListCodeDefinitionNamesTool: {
|
|
70
|
-
"en": "AutoCoder wants to list definitions in:\n[bold green]{{ path }}[/]",
|
|
71
|
-
"zh": "AutoCoder 想要列出此路径中的定义:\n[bold green]{{ path }}[/]"
|
|
72
|
-
},
|
|
73
|
-
AskFollowupQuestionTool: {
|
|
74
|
-
"en": (
|
|
75
|
-
"AutoCoder is asking a question:\n[bold magenta]{{ question }}[/]\n"
|
|
76
|
-
"{{ options_text }}"
|
|
77
|
-
),
|
|
78
|
-
"zh": (
|
|
79
|
-
"AutoCoder 正在提问:\n[bold magenta]{{ question }}[/]\n"
|
|
80
|
-
"{{ options_text }}"
|
|
81
|
-
)
|
|
82
|
-
},
|
|
83
|
-
UseMcpTool: {
|
|
84
|
-
"en": (
|
|
85
|
-
"AutoCoder wants to use an MCP tool:\n"
|
|
86
|
-
"[dim]Server:[/dim] [blue]{{ server_name }}[/]\n"
|
|
87
|
-
"[dim]Tool:[/dim] [blue]{{ tool_name }}[/]\n"
|
|
88
|
-
"[dim]Args:[/dim] {{ arguments_snippet }}{{ ellipsis }}"
|
|
89
|
-
),
|
|
90
|
-
"zh": (
|
|
91
|
-
"AutoCoder 想要使用 MCP 工具:\n"
|
|
92
|
-
"[dim]服务器:[/dim] [blue]{{ server_name }}[/]\n"
|
|
93
|
-
"[dim]工具:[/dim] [blue]{{ tool_name }}[/]\n"
|
|
94
|
-
"[dim]参数:[/dim] {{ arguments_snippet }}{{ ellipsis }}"
|
|
95
|
-
)
|
|
96
|
-
}
|
|
97
|
-
}
|
|
98
|
-
|
|
99
|
-
def get_tool_display_message(tool: BaseTool) -> str:
|
|
100
|
-
"""
|
|
101
|
-
Generates a user-friendly, internationalized string representation for a tool call.
|
|
102
|
-
|
|
103
|
-
Args:
|
|
104
|
-
tool: The tool instance (Pydantic model).
|
|
105
|
-
|
|
106
|
-
Returns:
|
|
107
|
-
A formatted string for display in the terminal.
|
|
108
|
-
"""
|
|
109
|
-
lang = get_system_language()
|
|
110
|
-
tool_type = type(tool)
|
|
111
|
-
|
|
112
|
-
if tool_type not in TOOL_DISPLAY_MESSAGES:
|
|
113
|
-
# Fallback for unknown tools
|
|
114
|
-
return f"Unknown tool type: {tool_type.__name__}\nData: {tool.model_dump_json(indent=2)}"
|
|
115
|
-
|
|
116
|
-
templates = TOOL_DISPLAY_MESSAGES[tool_type]
|
|
117
|
-
template = templates.get(lang, templates.get("en", "Tool display template not found")) # Fallback to English
|
|
118
|
-
|
|
119
|
-
# Prepare context specific to each tool type
|
|
120
|
-
context = {}
|
|
121
|
-
if isinstance(tool, ReadFileTool):
|
|
122
|
-
context = {"path": tool.path}
|
|
123
|
-
elif isinstance(tool, WriteToFileTool):
|
|
124
|
-
snippet = tool.content[:150]
|
|
125
|
-
context = {
|
|
126
|
-
"path": tool.path,
|
|
127
|
-
"content_snippet": snippet,
|
|
128
|
-
"ellipsis": '...' if len(tool.content) > 150 else ''
|
|
129
|
-
}
|
|
130
|
-
elif isinstance(tool, ReplaceInFileTool):
|
|
131
|
-
snippet = tool.diff
|
|
132
|
-
context = {
|
|
133
|
-
"path": tool.path,
|
|
134
|
-
"diff_snippet": snippet,
|
|
135
|
-
"ellipsis": ''
|
|
136
|
-
}
|
|
137
|
-
elif isinstance(tool, ExecuteCommandTool):
|
|
138
|
-
context = {"command": tool.command, "requires_approval": tool.requires_approval}
|
|
139
|
-
elif isinstance(tool, ListFilesTool):
|
|
140
|
-
rec_text_en = '(Recursively)' if tool.recursive else '(Top Level)'
|
|
141
|
-
rec_text_zh = '(递归)' if tool.recursive else '(顶层)'
|
|
142
|
-
context = {
|
|
143
|
-
"path": tool.path,
|
|
144
|
-
"recursive_text": rec_text_zh if lang == 'zh' else rec_text_en
|
|
145
|
-
}
|
|
146
|
-
elif isinstance(tool, SearchFilesTool):
|
|
147
|
-
context = {
|
|
148
|
-
"path": tool.path,
|
|
149
|
-
"file_pattern": tool.file_pattern or '*',
|
|
150
|
-
"regex": tool.regex
|
|
151
|
-
}
|
|
152
|
-
elif isinstance(tool, ListCodeDefinitionNamesTool):
|
|
153
|
-
context = {"path": tool.path}
|
|
154
|
-
elif isinstance(tool, AskFollowupQuestionTool):
|
|
155
|
-
options_text_en = ""
|
|
156
|
-
options_text_zh = ""
|
|
157
|
-
if tool.options:
|
|
158
|
-
options_list_en = "\n".join([f"- {opt}" for opt in tool.options])
|
|
159
|
-
options_list_zh = "\n".join([f"- {opt}" for opt in tool.options]) # Assuming options are simple enough not to need translation
|
|
160
|
-
options_text_en = f"[dim]Options:[/dim]\n{options_list_en}"
|
|
161
|
-
options_text_zh = f"[dim]选项:[/dim]\n{options_list_zh}"
|
|
162
|
-
context = {
|
|
163
|
-
"question": tool.question,
|
|
164
|
-
"options_text": options_text_zh if lang == 'zh' else options_text_en
|
|
165
|
-
}
|
|
166
|
-
elif isinstance(tool, UseMcpTool):
|
|
167
|
-
args_str = tool.query
|
|
168
|
-
snippet = args_str[:100]
|
|
169
|
-
context = {
|
|
170
|
-
"server_name": tool.server_name,
|
|
171
|
-
"tool_name": tool.tool_name,
|
|
172
|
-
"arguments_snippet": snippet,
|
|
173
|
-
"ellipsis": '...' if len(args_str) > 100 else ''
|
|
174
|
-
}
|
|
175
|
-
else:
|
|
176
|
-
# Generic context for tools not specifically handled above
|
|
177
|
-
context = tool.model_dump()
|
|
178
|
-
|
|
179
|
-
try:
|
|
180
|
-
return format_str_jinja2(template, **context)
|
|
181
|
-
except Exception as e:
|
|
182
|
-
# Fallback in case of formatting errors
|
|
183
|
-
return f"Error formatting display for {tool_type.__name__}: {e}\nTemplate: {template}\nContext: {context}"
|
|
@@ -1,148 +0,0 @@
|
|
|
1
|
-
"""
|
|
2
|
-
Dynamic Completion Example Plugin for Chat Auto Coder.
|
|
3
|
-
"""
|
|
4
|
-
|
|
5
|
-
from typing import Any, Callable, Dict, List, Optional, Tuple, Type, Union
|
|
6
|
-
from autocoder.plugins import Plugin, PluginManager
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
class DynamicCompletionExamplePlugin(Plugin):
|
|
10
|
-
"""A sample plugin demonstrating dynamic completion functionality."""
|
|
11
|
-
|
|
12
|
-
name = "dynamic_completion_example"
|
|
13
|
-
description = "Demonstrates the dynamic completion feature"
|
|
14
|
-
version = "0.1.0"
|
|
15
|
-
|
|
16
|
-
def __init__(self, manager: PluginManager, config: Optional[Dict[str, Any]] = None, config_path: Optional[str] = None):
|
|
17
|
-
"""Initialize the plugin.
|
|
18
|
-
|
|
19
|
-
Args:
|
|
20
|
-
manager: The plugin manager instance
|
|
21
|
-
config: Optional configuration dictionary for the plugin
|
|
22
|
-
config_path: Optional path to the configuration file
|
|
23
|
-
"""
|
|
24
|
-
super().__init__(manager, config, config_path)
|
|
25
|
-
self.items = ["item1", "item2", "item3", "custom_item"]
|
|
26
|
-
|
|
27
|
-
def initialize(self) -> bool:
|
|
28
|
-
"""Initialize the plugin.
|
|
29
|
-
|
|
30
|
-
Returns:
|
|
31
|
-
True if initialization was successful, False otherwise
|
|
32
|
-
"""
|
|
33
|
-
# Register for function interception if needed
|
|
34
|
-
# self.manager.register_function_interception(self.name, "ask")
|
|
35
|
-
|
|
36
|
-
# Register as a dynamic completion provider
|
|
37
|
-
self.manager.register_dynamic_completion_provider(self.name, ["/example"])
|
|
38
|
-
|
|
39
|
-
return True
|
|
40
|
-
|
|
41
|
-
def get_commands(self) -> Dict[str, Tuple[Callable, str]]:
|
|
42
|
-
"""Get commands provided by this plugin.
|
|
43
|
-
|
|
44
|
-
Returns:
|
|
45
|
-
A dictionary of command name to handler and description
|
|
46
|
-
"""
|
|
47
|
-
return {
|
|
48
|
-
"example": (
|
|
49
|
-
self.example_command,
|
|
50
|
-
"Example command with dynamic completion",
|
|
51
|
-
),
|
|
52
|
-
"example/add": (self.add_item, "Add a new item to the example list"),
|
|
53
|
-
"example/list": (self.list_items, "List all available items"),
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
def get_completions(self) -> Dict[str, List[str]]:
|
|
57
|
-
"""Get completions provided by this plugin.
|
|
58
|
-
|
|
59
|
-
Returns:
|
|
60
|
-
A dictionary mapping command prefixes to completion options
|
|
61
|
-
"""
|
|
62
|
-
# 基本的静态补全选项
|
|
63
|
-
return {
|
|
64
|
-
"/example": ["add", "list", "select"],
|
|
65
|
-
}
|
|
66
|
-
|
|
67
|
-
def get_dynamic_completions(
|
|
68
|
-
self, command: str, current_input: str
|
|
69
|
-
) -> List[Tuple[str, str]]:
|
|
70
|
-
"""Get dynamic completions based on the current command context.
|
|
71
|
-
|
|
72
|
-
Args:
|
|
73
|
-
command: The base command (e.g., "/example select")
|
|
74
|
-
current_input: The full current input including the command
|
|
75
|
-
|
|
76
|
-
Returns:
|
|
77
|
-
A list of tuples containing (completion_text, display_text)
|
|
78
|
-
"""
|
|
79
|
-
# 如果是 /example select 命令,提供动态项目列表
|
|
80
|
-
if current_input.startswith("/example select"):
|
|
81
|
-
# 提取已输入的部分项目名
|
|
82
|
-
parts = current_input.split(maxsplit=2)
|
|
83
|
-
item_prefix = ""
|
|
84
|
-
if len(parts) > 2:
|
|
85
|
-
item_prefix = parts[2]
|
|
86
|
-
|
|
87
|
-
# 返回匹配的项目
|
|
88
|
-
return [
|
|
89
|
-
(item, f"{item} (example item)")
|
|
90
|
-
for item in self.items
|
|
91
|
-
if item.startswith(item_prefix)
|
|
92
|
-
]
|
|
93
|
-
|
|
94
|
-
return []
|
|
95
|
-
|
|
96
|
-
def example_command(self, args: str) -> None:
|
|
97
|
-
"""Handle the example command.
|
|
98
|
-
|
|
99
|
-
Args:
|
|
100
|
-
args: Command arguments
|
|
101
|
-
"""
|
|
102
|
-
if not args:
|
|
103
|
-
print("Usage: /example [add|list|select]")
|
|
104
|
-
return
|
|
105
|
-
|
|
106
|
-
parts = args.split(maxsplit=1)
|
|
107
|
-
subcommand = parts[0]
|
|
108
|
-
|
|
109
|
-
if subcommand == "select" and len(parts) > 1:
|
|
110
|
-
item = parts[1]
|
|
111
|
-
if item in self.items:
|
|
112
|
-
print(f"Selected item: {item}")
|
|
113
|
-
else:
|
|
114
|
-
print(
|
|
115
|
-
f"Item '{item}' not found. Use /example list to see available items."
|
|
116
|
-
)
|
|
117
|
-
else:
|
|
118
|
-
print(f"Unknown subcommand: {subcommand}. Use add, list, or select.")
|
|
119
|
-
|
|
120
|
-
def add_item(self, args: str) -> None:
|
|
121
|
-
"""Add a new item to the list.
|
|
122
|
-
|
|
123
|
-
Args:
|
|
124
|
-
args: The item name to add
|
|
125
|
-
"""
|
|
126
|
-
if not args:
|
|
127
|
-
print("Please specify an item name to add.")
|
|
128
|
-
return
|
|
129
|
-
|
|
130
|
-
if args in self.items:
|
|
131
|
-
print(f"Item '{args}' already exists.")
|
|
132
|
-
else:
|
|
133
|
-
self.items.append(args)
|
|
134
|
-
print(f"Added item: {args}")
|
|
135
|
-
|
|
136
|
-
def list_items(self, args: str) -> None:
|
|
137
|
-
"""List all available items.
|
|
138
|
-
|
|
139
|
-
Args:
|
|
140
|
-
args: Ignored
|
|
141
|
-
"""
|
|
142
|
-
print("Available items:")
|
|
143
|
-
for item in self.items:
|
|
144
|
-
print(f" - {item}")
|
|
145
|
-
|
|
146
|
-
def shutdown(self) -> None:
|
|
147
|
-
"""Shutdown the plugin."""
|
|
148
|
-
pass
|