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
autocoder/chat_auto_coder.py
CHANGED
|
@@ -1,34 +1,21 @@
|
|
|
1
|
-
from
|
|
1
|
+
from loguru import logger
|
|
2
|
+
|
|
3
|
+
logger.remove() # 把默认 sink 去掉,彻底静音
|
|
4
|
+
from autocoder.run_context import get_run_context, RunMode
|
|
2
5
|
|
|
3
6
|
# 设置运行模式为终端模式
|
|
4
7
|
get_run_context().set_mode(RunMode.TERMINAL)
|
|
5
8
|
|
|
6
|
-
import
|
|
7
|
-
import
|
|
8
|
-
from
|
|
9
|
-
from prompt_toolkit.key_binding import KeyBindings
|
|
10
|
-
from prompt_toolkit.history import FileHistory
|
|
11
|
-
from prompt_toolkit.auto_suggest import AutoSuggestFromHistory
|
|
12
|
-
from prompt_toolkit.styles import Style
|
|
13
|
-
from autocoder.version import __version__
|
|
14
|
-
from autocoder.chat_auto_coder_lang import get_message
|
|
15
|
-
from prompt_toolkit.formatted_text import FormattedText
|
|
16
|
-
from prompt_toolkit.completion import Completer, Completion
|
|
17
|
-
from autocoder.plugins import PluginManager
|
|
18
|
-
from autocoder.events.event_manager_singleton import gengerate_event_file_path
|
|
19
|
-
from autocoder.common.global_cancel import global_cancel
|
|
20
|
-
from autocoder.chat.models_command import handle_models_command
|
|
21
|
-
from autocoder.common.conversations.get_conversation_manager import (
|
|
22
|
-
get_conversation_manager,
|
|
23
|
-
get_conversation_manager_config,
|
|
24
|
-
reset_conversation_manager
|
|
25
|
-
)
|
|
9
|
+
import sys
|
|
10
|
+
import asyncio
|
|
11
|
+
from autocoder.chat.conf_command import handle_conf_command
|
|
26
12
|
from autocoder.auto_coder_runner import (
|
|
27
|
-
auto_command,
|
|
28
|
-
|
|
13
|
+
auto_command,
|
|
14
|
+
run_agentic,
|
|
15
|
+
# Keep configure if it's used elsewhere or by handle_conf_command internally (though we adapted handle_conf_command not to)
|
|
16
|
+
configure,
|
|
29
17
|
# manage_models, # Removed
|
|
30
18
|
# print_conf, # Removed
|
|
31
|
-
save_memory,
|
|
32
19
|
exclude_dirs,
|
|
33
20
|
exclude_files,
|
|
34
21
|
ask,
|
|
@@ -55,14 +42,86 @@ from autocoder.auto_coder_runner import (
|
|
|
55
42
|
get_mcp_server,
|
|
56
43
|
completer,
|
|
57
44
|
summon,
|
|
58
|
-
get_memory,
|
|
59
45
|
active_context,
|
|
60
46
|
rules,
|
|
61
47
|
start as start_engine,
|
|
62
|
-
stop as stop_engine
|
|
48
|
+
stop as stop_engine,
|
|
49
|
+
)
|
|
50
|
+
|
|
51
|
+
# Import memory and mode management from core_config module
|
|
52
|
+
from autocoder.common.core_config import (
|
|
53
|
+
cycle_mode,
|
|
54
|
+
get_mode,
|
|
55
|
+
set_mode,
|
|
56
|
+
toggle_human_as_model,
|
|
57
|
+
get_human_as_model_string,
|
|
58
|
+
get_memory_manager,
|
|
59
|
+
)
|
|
60
|
+
from autocoder.chat.models_command import handle_models_command
|
|
61
|
+
from autocoder.common.global_cancel import global_cancel, CancelRequestedException
|
|
62
|
+
from autocoder.events.event_manager_singleton import gengerate_event_file_path
|
|
63
|
+
from autocoder.plugins import PluginManager
|
|
64
|
+
from prompt_toolkit.completion import Completer, Completion
|
|
65
|
+
from prompt_toolkit.formatted_text import FormattedText
|
|
66
|
+
from autocoder.chat_auto_coder_lang import (
|
|
67
|
+
get_message,
|
|
68
|
+
get_message_with_format as get_message_with_format_local,
|
|
69
|
+
)
|
|
70
|
+
from autocoder.common.international import (
|
|
71
|
+
get_message as get_i18n_message,
|
|
72
|
+
get_message_with_format,
|
|
63
73
|
)
|
|
74
|
+
from autocoder.version import __version__
|
|
75
|
+
from prompt_toolkit.styles import Style
|
|
76
|
+
from prompt_toolkit.auto_suggest import AutoSuggestFromHistory
|
|
77
|
+
from prompt_toolkit.history import FileHistory
|
|
78
|
+
from prompt_toolkit.key_binding import KeyBindings
|
|
79
|
+
from prompt_toolkit import PromptSession
|
|
80
|
+
from autocoder.common.terminal_paste import (
|
|
81
|
+
register_paste_handler,
|
|
82
|
+
resolve_paste_placeholders,
|
|
83
|
+
)
|
|
84
|
+
import os
|
|
85
|
+
import argparse
|
|
86
|
+
import time
|
|
87
|
+
|
|
88
|
+
|
|
89
|
+
class TaskEvent:
|
|
90
|
+
def __init__(self):
|
|
91
|
+
self.state = "idle" # idle, pending, started, running, completed
|
|
92
|
+
self._event = asyncio.Event()
|
|
93
|
+
self._event.set() # 初始状态为可用
|
|
94
|
+
|
|
95
|
+
def set_state(self, state):
|
|
96
|
+
"""设置任务状态"""
|
|
97
|
+
self.state = state
|
|
98
|
+
if state == "completed":
|
|
99
|
+
self._event.set()
|
|
100
|
+
else:
|
|
101
|
+
self._event.clear()
|
|
102
|
+
|
|
103
|
+
def get_state(self):
|
|
104
|
+
"""获取当前状态"""
|
|
105
|
+
return self.state
|
|
106
|
+
|
|
107
|
+
def is_completed(self):
|
|
108
|
+
"""检查是否完成"""
|
|
109
|
+
return self.state == "completed"
|
|
110
|
+
|
|
111
|
+
def is_running(self):
|
|
112
|
+
"""检查是否正在运行"""
|
|
113
|
+
return self.state in ["started", "running"]
|
|
114
|
+
|
|
115
|
+
async def wait(self):
|
|
116
|
+
"""等待任务完成"""
|
|
117
|
+
await self._event.wait()
|
|
118
|
+
|
|
119
|
+
def clear(self):
|
|
120
|
+
"""清除完成状态,重置为pending"""
|
|
121
|
+
self.set_state("idle")
|
|
122
|
+
|
|
123
|
+
|
|
64
124
|
# Ensure the correct import is present
|
|
65
|
-
from autocoder.chat.conf_command import handle_conf_command
|
|
66
125
|
|
|
67
126
|
# Create a global plugin manager
|
|
68
127
|
plugin_manager = PluginManager()
|
|
@@ -75,6 +134,7 @@ original_functions = {
|
|
|
75
134
|
"design": design,
|
|
76
135
|
"voice_input": voice_input,
|
|
77
136
|
"auto_command": auto_command,
|
|
137
|
+
"run_agentic": run_agentic,
|
|
78
138
|
"execute_shell_command": execute_shell_command,
|
|
79
139
|
"active_context": active_context,
|
|
80
140
|
}
|
|
@@ -118,65 +178,86 @@ def show_help():
|
|
|
118
178
|
f" \033[94m{get_message('commands')}\033[0m - \033[93m{get_message('description')}\033[0m"
|
|
119
179
|
)
|
|
120
180
|
print(
|
|
121
|
-
f" \033[94m/
|
|
181
|
+
f" \033[94m/auto\033[0m \033[93m<query>\033[0m - \033[92m{get_message('auto_desc')}\033[0m"
|
|
122
182
|
)
|
|
123
183
|
print(
|
|
124
|
-
f"
|
|
184
|
+
f" \033[94m/auto /new\033[0m \033[93m<query>\033[0m - \033[92m{get_message('auto_new_desc')}\033[0m"
|
|
125
185
|
)
|
|
126
186
|
print(
|
|
127
|
-
f"
|
|
187
|
+
f" \033[94m/auto /resume\033[0m \033[93m<id> <query>\033[0m - \033[92m{get_message('auto_resume_desc')}\033[0m"
|
|
128
188
|
)
|
|
129
189
|
print(
|
|
130
|
-
f"
|
|
131
|
-
)
|
|
190
|
+
f" \033[94m/auto /list\033[0m - \033[92m{get_message('auto_list_desc')}\033[0m"
|
|
191
|
+
)
|
|
132
192
|
print(
|
|
133
|
-
f"
|
|
193
|
+
f" \033[94m/auto /command\033[0m \033[93m<file>\033[0m - \033[92m{get_message('auto_command_desc')}\033[0m"
|
|
134
194
|
)
|
|
135
|
-
|
|
195
|
+
|
|
136
196
|
print(f" \033[94m/commit\033[0m - \033[92m{get_message('commit_desc')}\033[0m")
|
|
197
|
+
|
|
137
198
|
print(
|
|
138
199
|
f" \033[94m/conf\033[0m \033[93m<key>:<value>\033[0m - \033[92m{get_message('conf_desc')}\033[0m"
|
|
139
200
|
)
|
|
201
|
+
|
|
140
202
|
print(
|
|
141
|
-
f" \033[94m/
|
|
203
|
+
f" \033[94m/shell\033[0m \033[93m<command>\033[0m - \033[92m{get_message('shell_desc')}\033[0m"
|
|
142
204
|
)
|
|
143
205
|
print(
|
|
144
|
-
f" \033[94m/
|
|
206
|
+
f" \033[94m/shell\033[0m - \033[92m{get_message('shell_interactive_desc')}\033[0m"
|
|
145
207
|
)
|
|
146
208
|
print(
|
|
147
|
-
f" \033[94m
|
|
209
|
+
f" \033[94m!\033[0m\033[93m<command>\033[0m - \033[92m{get_message('shell_single_command_desc')}\033[0m"
|
|
148
210
|
)
|
|
149
|
-
|
|
211
|
+
|
|
150
212
|
print(
|
|
151
|
-
f" \033[94m/
|
|
213
|
+
f" \033[94m/add_files\033[0m \033[93m<file1> <file2> ...\033[0m - \033[92m{get_message('add_files_desc')}\033[0m"
|
|
152
214
|
)
|
|
153
215
|
print(
|
|
154
|
-
f" \033[94m/
|
|
216
|
+
f" \033[94m/remove_files\033[0m \033[93m<file1>,<file2> ...\033[0m - \033[92m{get_message('remove_files_desc')}\033[0m"
|
|
217
|
+
)
|
|
218
|
+
print(
|
|
219
|
+
f" \033[94m/chat\033[0m \033[93m<query>\033[0m - \033[92m{get_message('chat_desc')}\033[0m"
|
|
220
|
+
)
|
|
221
|
+
print(
|
|
222
|
+
f" \033[94m/coding\033[0m \033[93m<query>\033[0m - \033[92m{get_message('coding_desc')}\033[0m"
|
|
223
|
+
)
|
|
224
|
+
|
|
225
|
+
print(f" \033[94m/revert\033[0m - \033[92m{get_message('revert_desc')}\033[0m")
|
|
226
|
+
print(
|
|
227
|
+
f" \033[94m/index/query\033[0m \033[93m<args>\033[0m - \033[92m{get_message('index_query_desc')}\033[0m"
|
|
228
|
+
)
|
|
229
|
+
print(
|
|
230
|
+
f" \033[94m/index/build\033[0m - \033[92m{get_message('index_build_desc')}\033[0m"
|
|
155
231
|
)
|
|
156
232
|
print(
|
|
157
|
-
f" \033[94m/
|
|
233
|
+
f" \033[94m/list_files\033[0m - \033[92m{get_message('list_files_desc')}\033[0m"
|
|
158
234
|
)
|
|
235
|
+
print(f" \033[94m/help\033[0m - \033[92m{get_message('help_desc')}\033[0m")
|
|
159
236
|
print(f" \033[94m/mode\033[0m - \033[92m{get_message('mode_desc')}\033[0m")
|
|
160
237
|
print(f" \033[94m/lib\033[0m - \033[92m{get_message('lib_desc')}\033[0m")
|
|
161
238
|
print(f" \033[94m/models\033[0m - \033[92m{get_message('models_desc')}\033[0m")
|
|
162
239
|
print(f" \033[94m/plugins\033[0m - \033[92m{get_message('plugins_desc')}\033[0m")
|
|
163
|
-
print(
|
|
240
|
+
print(
|
|
241
|
+
f" \033[94m/active_context\033[0m - \033[92m{get_message('active_context_desc')}\033[0m"
|
|
242
|
+
)
|
|
164
243
|
print(f" \033[94m/exit\033[0m - \033[92m{get_message('exit_desc')}\033[0m")
|
|
165
244
|
print()
|
|
166
245
|
|
|
167
246
|
# 显示插件命令
|
|
168
247
|
if plugin_manager.command_handlers:
|
|
169
|
-
print("\033[
|
|
170
|
-
print(
|
|
248
|
+
print(f"\033[1m{get_message('plugin_commands_title')}\033[0m")
|
|
249
|
+
print(
|
|
250
|
+
f" \033[94m{get_message('plugin_command_header')}\033[0m - \033[93m{get_message('plugin_description_header')}\033[0m"
|
|
251
|
+
)
|
|
171
252
|
for cmd, (_, desc, plugin_id) in plugin_manager.command_handlers.items():
|
|
172
253
|
plugin = plugin_manager.get_plugin(plugin_id)
|
|
173
254
|
if plugin:
|
|
174
255
|
print(
|
|
175
|
-
f" \033[94m{cmd}\033[0m - \033[92m{desc} (
|
|
256
|
+
f" \033[94m{cmd}\033[0m - \033[92m{desc} ({get_message('plugin_from')} {plugin.plugin_name()})\033[0m"
|
|
176
257
|
)
|
|
177
258
|
else:
|
|
178
259
|
print(
|
|
179
|
-
f" \033[94m{cmd}\033[0m - \033[92m{desc} (
|
|
260
|
+
f" \033[94m{cmd}\033[0m - \033[92m{desc} ({get_message('plugin_from_unknown')})\033[0m"
|
|
180
261
|
)
|
|
181
262
|
print()
|
|
182
263
|
|
|
@@ -187,6 +268,41 @@ class EnhancedCompleter(Completer):
|
|
|
187
268
|
def __init__(self, base_completer: Completer, plugin_manager: PluginManager):
|
|
188
269
|
self.base_completer: Completer = base_completer
|
|
189
270
|
self.plugin_manager: PluginManager = plugin_manager
|
|
271
|
+
self._custom_commands_cache = set()
|
|
272
|
+
self._cache_valid = False
|
|
273
|
+
|
|
274
|
+
def _get_custom_commands(self):
|
|
275
|
+
"""获取自定义命令列表(从 .autocodercommands 目录)"""
|
|
276
|
+
if self._cache_valid and self._custom_commands_cache:
|
|
277
|
+
return sorted(list(self._custom_commands_cache))
|
|
278
|
+
|
|
279
|
+
try:
|
|
280
|
+
from autocoder.common.command_file_manager.manager import CommandManager
|
|
281
|
+
|
|
282
|
+
# 创建命令管理器
|
|
283
|
+
command_manager = CommandManager()
|
|
284
|
+
|
|
285
|
+
# 列出所有命令文件
|
|
286
|
+
result = command_manager.list_command_files(recursive=True)
|
|
287
|
+
|
|
288
|
+
if result.success:
|
|
289
|
+
commands = set()
|
|
290
|
+
for file_name in result.command_files:
|
|
291
|
+
# 去掉 .md 后缀和路径前缀,只保留命令名
|
|
292
|
+
command_name = os.path.basename(file_name)
|
|
293
|
+
if command_name.endswith('.md'):
|
|
294
|
+
command_name = command_name[:-3]
|
|
295
|
+
# 添加 / 前缀形成完整命令
|
|
296
|
+
commands.add(f"/{command_name}")
|
|
297
|
+
|
|
298
|
+
self._custom_commands_cache = commands
|
|
299
|
+
self._cache_valid = True
|
|
300
|
+
return sorted(list(commands))
|
|
301
|
+
except Exception:
|
|
302
|
+
# 静默处理异常,返回空列表
|
|
303
|
+
pass
|
|
304
|
+
|
|
305
|
+
return []
|
|
190
306
|
|
|
191
307
|
def get_completions(self, document, complete_event):
|
|
192
308
|
# 获取当前输入的文本
|
|
@@ -231,12 +347,25 @@ class EnhancedCompleter(Completer):
|
|
|
231
347
|
)
|
|
232
348
|
return
|
|
233
349
|
# 处理直接命令补全 - 如果输入不包含空格,匹配整个命令
|
|
234
|
-
|
|
350
|
+
# 1. 插件和内置命令
|
|
351
|
+
for command in self.plugin_manager.get_all_commands_with_prefix(
|
|
352
|
+
current_input
|
|
353
|
+
):
|
|
235
354
|
yield Completion(
|
|
236
355
|
command[len(current_input) :],
|
|
237
356
|
start_position=0,
|
|
238
357
|
display=command,
|
|
239
358
|
)
|
|
359
|
+
|
|
360
|
+
# 2. 自定义命令(从 .autocodercommands 目录)
|
|
361
|
+
custom_commands = self._get_custom_commands()
|
|
362
|
+
for command in custom_commands:
|
|
363
|
+
if command.startswith(current_input):
|
|
364
|
+
yield Completion(
|
|
365
|
+
command[len(current_input) :],
|
|
366
|
+
start_position=0,
|
|
367
|
+
display=command,
|
|
368
|
+
)
|
|
240
369
|
|
|
241
370
|
# 获取并返回基础补全器的补全
|
|
242
371
|
if self.base_completer:
|
|
@@ -269,11 +398,132 @@ class EnhancedCompleter(Completer):
|
|
|
269
398
|
async def get_completions_async(self, document, complete_event):
|
|
270
399
|
"""异步获取补全内容。
|
|
271
400
|
|
|
272
|
-
|
|
273
|
-
|
|
401
|
+
使用 asyncio.run_in_executor 来异步执行耗时的补全操作,
|
|
402
|
+
避免阻塞主线程导致输入卡顿。
|
|
274
403
|
"""
|
|
275
|
-
|
|
276
|
-
|
|
404
|
+
import asyncio
|
|
405
|
+
from concurrent.futures import ThreadPoolExecutor
|
|
406
|
+
|
|
407
|
+
# 获取当前输入的文本
|
|
408
|
+
text_before_cursor = document.text_before_cursor.lstrip()
|
|
409
|
+
|
|
410
|
+
# 只有当我们需要处理命令补全时才进行处理
|
|
411
|
+
if text_before_cursor.startswith("/"):
|
|
412
|
+
# 获取当前输入的命令前缀
|
|
413
|
+
current_input = text_before_cursor
|
|
414
|
+
|
|
415
|
+
# 使用线程池执行器来异步执行耗时操作
|
|
416
|
+
loop = asyncio.get_event_loop()
|
|
417
|
+
executor = ThreadPoolExecutor(max_workers=1)
|
|
418
|
+
|
|
419
|
+
try:
|
|
420
|
+
# 检查是否需要动态补全
|
|
421
|
+
if " " in current_input:
|
|
422
|
+
# 将连续的空格替换为单个空格
|
|
423
|
+
_input_one_space = " ".join(current_input.split())
|
|
424
|
+
|
|
425
|
+
# 异步获取动态命令列表
|
|
426
|
+
dynamic_cmds = await loop.run_in_executor(
|
|
427
|
+
executor, self.plugin_manager.get_dynamic_cmds
|
|
428
|
+
)
|
|
429
|
+
|
|
430
|
+
for dynamic_cmd in dynamic_cmds:
|
|
431
|
+
if _input_one_space.startswith(dynamic_cmd):
|
|
432
|
+
# 异步处理动态补全
|
|
433
|
+
completions = await loop.run_in_executor(
|
|
434
|
+
executor,
|
|
435
|
+
self.plugin_manager.process_dynamic_completions,
|
|
436
|
+
dynamic_cmd,
|
|
437
|
+
current_input,
|
|
438
|
+
)
|
|
439
|
+
for completion_text, display_text in completions:
|
|
440
|
+
yield Completion(
|
|
441
|
+
completion_text,
|
|
442
|
+
start_position=0,
|
|
443
|
+
display=display_text,
|
|
444
|
+
)
|
|
445
|
+
return
|
|
446
|
+
|
|
447
|
+
# 如果不是特定命令,检查一般命令 + 空格的情况
|
|
448
|
+
cmd_parts = current_input.split(maxsplit=1)
|
|
449
|
+
base_cmd = cmd_parts[0]
|
|
450
|
+
|
|
451
|
+
# 异步获取插件命令补全
|
|
452
|
+
plugin_completions_dict = await loop.run_in_executor(
|
|
453
|
+
executor, self.plugin_manager.get_plugin_completions
|
|
454
|
+
)
|
|
455
|
+
|
|
456
|
+
# 如果命令存在于补全字典中,进行处理
|
|
457
|
+
if base_cmd in plugin_completions_dict:
|
|
458
|
+
# 异步处理命令补全
|
|
459
|
+
completions_list = await loop.run_in_executor(
|
|
460
|
+
executor,
|
|
461
|
+
self._get_command_completions_list,
|
|
462
|
+
base_cmd,
|
|
463
|
+
current_input,
|
|
464
|
+
plugin_completions_dict[base_cmd],
|
|
465
|
+
)
|
|
466
|
+
for completion in completions_list:
|
|
467
|
+
yield completion
|
|
468
|
+
return
|
|
469
|
+
else:
|
|
470
|
+
# 处理直接命令补全 - 异步获取所有匹配的命令
|
|
471
|
+
# 1. 插件和内置命令
|
|
472
|
+
commands = await loop.run_in_executor(
|
|
473
|
+
executor,
|
|
474
|
+
self.plugin_manager.get_all_commands_with_prefix,
|
|
475
|
+
current_input,
|
|
476
|
+
)
|
|
477
|
+
for command in commands:
|
|
478
|
+
yield Completion(
|
|
479
|
+
command[len(current_input) :],
|
|
480
|
+
start_position=0,
|
|
481
|
+
display=command,
|
|
482
|
+
)
|
|
483
|
+
|
|
484
|
+
# 2. 自定义命令(从 .autocodercommands 目录)
|
|
485
|
+
custom_commands = await loop.run_in_executor(
|
|
486
|
+
executor,
|
|
487
|
+
self._get_custom_commands,
|
|
488
|
+
)
|
|
489
|
+
for command in custom_commands:
|
|
490
|
+
if command.startswith(current_input):
|
|
491
|
+
yield Completion(
|
|
492
|
+
command[len(current_input) :],
|
|
493
|
+
start_position=0,
|
|
494
|
+
display=command,
|
|
495
|
+
)
|
|
496
|
+
finally:
|
|
497
|
+
executor.shutdown(wait=False)
|
|
498
|
+
|
|
499
|
+
# 异步获取基础补全器的补全
|
|
500
|
+
if self.base_completer:
|
|
501
|
+
# 如果基础补全器支持异步方法,优先使用
|
|
502
|
+
if hasattr(self.base_completer, "get_completions_async"):
|
|
503
|
+
async for completion in self.base_completer.get_completions_async(
|
|
504
|
+
document, complete_event
|
|
505
|
+
):
|
|
506
|
+
yield completion
|
|
507
|
+
else:
|
|
508
|
+
# 否则在线程池中运行同步方法
|
|
509
|
+
loop = asyncio.get_event_loop()
|
|
510
|
+
executor = ThreadPoolExecutor(max_workers=1)
|
|
511
|
+
try:
|
|
512
|
+
completions = await loop.run_in_executor(
|
|
513
|
+
executor,
|
|
514
|
+
list,
|
|
515
|
+
self.base_completer.get_completions(document, complete_event),
|
|
516
|
+
)
|
|
517
|
+
for completion in completions:
|
|
518
|
+
yield completion
|
|
519
|
+
finally:
|
|
520
|
+
executor.shutdown(wait=False)
|
|
521
|
+
|
|
522
|
+
def _get_command_completions_list(self, command, current_input, completions):
|
|
523
|
+
"""获取命令补全列表(用于异步执行)"""
|
|
524
|
+
return list(
|
|
525
|
+
self._process_command_completions(command, current_input, completions)
|
|
526
|
+
)
|
|
277
527
|
|
|
278
528
|
|
|
279
529
|
ARGS = None
|
|
@@ -284,92 +534,526 @@ def load_builtin_plugins():
|
|
|
284
534
|
try:
|
|
285
535
|
# 发现所有可用的插件
|
|
286
536
|
discovered_plugins = plugin_manager.discover_plugins()
|
|
287
|
-
|
|
537
|
+
|
|
288
538
|
# 排除的示例插件列表
|
|
289
539
|
excluded_plugins = {
|
|
290
540
|
"autocoder.plugins.dynamic_completion_example",
|
|
291
|
-
"autocoder.plugins.sample_plugin"
|
|
541
|
+
"autocoder.plugins.sample_plugin",
|
|
292
542
|
}
|
|
293
|
-
|
|
543
|
+
|
|
294
544
|
# 自动加载内置插件(在autocoder.plugins模块中的插件)
|
|
295
545
|
builtin_loaded = 0
|
|
296
546
|
for plugin_class in discovered_plugins:
|
|
297
547
|
module_name = plugin_class.__module__
|
|
298
|
-
if (
|
|
548
|
+
if (
|
|
549
|
+
module_name.startswith("autocoder.plugins.")
|
|
299
550
|
and not module_name.endswith(".__init__")
|
|
300
|
-
and module_name not in excluded_plugins
|
|
551
|
+
and module_name not in excluded_plugins
|
|
552
|
+
):
|
|
301
553
|
try:
|
|
302
554
|
if plugin_manager.load_plugin(plugin_class):
|
|
303
555
|
builtin_loaded += 1
|
|
304
556
|
print(f"✓ Loaded builtin plugin: {plugin_class.plugin_name()}")
|
|
305
557
|
except Exception as e:
|
|
306
|
-
print(
|
|
307
|
-
|
|
558
|
+
print(
|
|
559
|
+
f"✗ Failed to load builtin plugin {plugin_class.plugin_name()}: {e}"
|
|
560
|
+
)
|
|
561
|
+
|
|
308
562
|
if builtin_loaded > 0:
|
|
309
|
-
print(
|
|
563
|
+
print(
|
|
564
|
+
get_message_with_format_local(
|
|
565
|
+
"loaded_plugins_builtin", count=builtin_loaded
|
|
566
|
+
)
|
|
567
|
+
)
|
|
310
568
|
else:
|
|
311
|
-
print("
|
|
312
|
-
|
|
569
|
+
print(get_message("no_builtin_plugins_loaded"))
|
|
570
|
+
|
|
313
571
|
except Exception as e:
|
|
314
572
|
print(f"Error loading builtin plugins: {e}")
|
|
315
573
|
|
|
316
574
|
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
575
|
+
# 后台任务:监控全局状态或执行其他后台逻辑
|
|
576
|
+
async def background_task(stop_event: asyncio.Event, session=None):
|
|
577
|
+
"""后台任务:可以用于监控系统状态、清理任务等"""
|
|
578
|
+
counter = 0
|
|
579
|
+
toolbar_refresh_counter = 0
|
|
580
|
+
last_async_task_count = 0
|
|
320
581
|
|
|
321
|
-
|
|
322
|
-
|
|
582
|
+
# 配置刷新频率(秒)
|
|
583
|
+
TOOLBAR_REFRESH_INTERVAL = 5 # 默认5秒刷新一次
|
|
584
|
+
FAST_REFRESH_INTERVAL = 1 # 有异步任务时1秒刷新一次
|
|
323
585
|
|
|
324
|
-
|
|
325
|
-
|
|
586
|
+
while not stop_event.is_set():
|
|
587
|
+
try:
|
|
588
|
+
# 检查是否有需要处理的后台任务
|
|
589
|
+
# 这里可以添加系统监控逻辑
|
|
590
|
+
counter += 1
|
|
591
|
+
toolbar_refresh_counter += 1
|
|
326
592
|
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
593
|
+
# 检查当前异步任务状态,决定刷新频率
|
|
594
|
+
current_async_task_count = 0
|
|
595
|
+
try:
|
|
596
|
+
from pathlib import Path
|
|
597
|
+
from autocoder.sdk.async_runner.task_metadata import TaskMetadataManager
|
|
598
|
+
|
|
599
|
+
async_agent_dir = Path.home() / ".auto-coder" / "async_agent"
|
|
600
|
+
meta_dir = async_agent_dir / "meta"
|
|
601
|
+
|
|
602
|
+
if meta_dir.exists():
|
|
603
|
+
metadata_manager = TaskMetadataManager(str(meta_dir))
|
|
604
|
+
summary = metadata_manager.get_task_summary()
|
|
605
|
+
current_async_task_count = summary.get("running", 0)
|
|
606
|
+
except Exception:
|
|
607
|
+
# 静默处理异常
|
|
608
|
+
pass
|
|
609
|
+
|
|
610
|
+
# 智能刷新:有异步任务时更频繁刷新,无任务时降低刷新频率
|
|
611
|
+
should_refresh = False
|
|
612
|
+
if current_async_task_count > 0:
|
|
613
|
+
# 有异步任务时,每秒刷新
|
|
614
|
+
should_refresh = toolbar_refresh_counter >= FAST_REFRESH_INTERVAL
|
|
615
|
+
else:
|
|
616
|
+
# 无异步任务时,每5秒刷新
|
|
617
|
+
should_refresh = toolbar_refresh_counter >= TOOLBAR_REFRESH_INTERVAL
|
|
618
|
+
|
|
619
|
+
# 任务数量变化时立即刷新
|
|
620
|
+
if current_async_task_count != last_async_task_count:
|
|
621
|
+
should_refresh = True
|
|
622
|
+
last_async_task_count = current_async_task_count
|
|
623
|
+
|
|
624
|
+
# 执行工具栏刷新
|
|
625
|
+
if should_refresh and session and hasattr(session, "app"):
|
|
626
|
+
try:
|
|
627
|
+
session.app.invalidate()
|
|
628
|
+
toolbar_refresh_counter = 0
|
|
629
|
+
except Exception:
|
|
630
|
+
# 静默处理刷新异常,不影响后台任务运行
|
|
631
|
+
pass
|
|
632
|
+
|
|
633
|
+
# 每60秒执行一次清理
|
|
634
|
+
if counter % 60 == 0:
|
|
635
|
+
# 执行一些后台清理任务
|
|
636
|
+
pass
|
|
637
|
+
|
|
638
|
+
await asyncio.sleep(1)
|
|
639
|
+
except asyncio.CancelledError:
|
|
640
|
+
break
|
|
641
|
+
except Exception as e:
|
|
642
|
+
# 后台任务出错时,不要让整个应用崩溃
|
|
643
|
+
if ARGS and ARGS.debug:
|
|
644
|
+
print(f"Background task error: {e}")
|
|
645
|
+
await asyncio.sleep(5) # 出错后等待5秒再继续
|
|
646
|
+
|
|
647
|
+
|
|
648
|
+
async def process_user_input(user_input: str, new_prompt_callback, session=None):
|
|
649
|
+
"""处理用户输入的异步函数"""
|
|
650
|
+
try:
|
|
651
|
+
# 首先解析粘贴占位符
|
|
652
|
+
user_input = resolve_paste_placeholders(user_input)
|
|
653
|
+
|
|
654
|
+
# 处理 user_input 的空格
|
|
655
|
+
if user_input:
|
|
656
|
+
temp_user_input = user_input.lstrip() # 去掉左侧空格
|
|
657
|
+
if temp_user_input.startswith("/"):
|
|
658
|
+
user_input = temp_user_input
|
|
659
|
+
|
|
660
|
+
# 获取当前shell类型
|
|
661
|
+
import platform
|
|
662
|
+
|
|
663
|
+
shell = "/bin/bash" if platform.system() != "Windows" else "cmd.exe"
|
|
664
|
+
|
|
665
|
+
# 1. 如果用户输入 /shell,启动一个子 shell
|
|
666
|
+
if user_input == "/shell":
|
|
667
|
+
if session and hasattr(session, "app"):
|
|
668
|
+
try:
|
|
669
|
+
# 正确地等待异步方法
|
|
670
|
+
await session.app.run_system_command(shell, wait_for_enter=False)
|
|
671
|
+
except Exception:
|
|
672
|
+
# 如果异步调用失败,回退到同步方式
|
|
673
|
+
import subprocess
|
|
674
|
+
|
|
675
|
+
subprocess.call([shell])
|
|
676
|
+
else:
|
|
677
|
+
import subprocess
|
|
678
|
+
|
|
679
|
+
subprocess.call([shell])
|
|
680
|
+
return
|
|
681
|
+
|
|
682
|
+
# 2. 如果以 ! 开头,当作单行 shell 命令执行
|
|
683
|
+
if user_input.startswith("!"):
|
|
684
|
+
command = user_input[1:] # 去掉 ! 前缀
|
|
685
|
+
if session and hasattr(session, "app"):
|
|
686
|
+
try:
|
|
687
|
+
# 正确地等待异步方法
|
|
688
|
+
await session.app.run_system_command(command, wait_for_enter=False)
|
|
689
|
+
except Exception:
|
|
690
|
+
# 如果异步调用失败,回退到同步方式
|
|
691
|
+
import subprocess
|
|
692
|
+
|
|
693
|
+
subprocess.call([shell, "-c", command])
|
|
694
|
+
else:
|
|
695
|
+
import subprocess
|
|
696
|
+
|
|
697
|
+
subprocess.call([shell, "-c", command])
|
|
698
|
+
return
|
|
699
|
+
|
|
700
|
+
# 修复插件命令处理逻辑
|
|
701
|
+
plugin_handled = False
|
|
702
|
+
if user_input.startswith("/"):
|
|
703
|
+
plugin_result = plugin_manager.process_command(user_input)
|
|
704
|
+
if plugin_result:
|
|
705
|
+
plugin_name, handler, args = plugin_result
|
|
706
|
+
if handler:
|
|
707
|
+
handler(*args)
|
|
708
|
+
plugin_handled = True
|
|
709
|
+
|
|
710
|
+
# 如果插件已处理命令,直接返回
|
|
711
|
+
if plugin_handled:
|
|
712
|
+
return
|
|
713
|
+
|
|
714
|
+
# 如果插件未处理,继续处理内置命令
|
|
715
|
+
memory_manager = get_memory_manager()
|
|
716
|
+
|
|
717
|
+
# Shell 模式处理 - 优先级最高
|
|
718
|
+
if (
|
|
719
|
+
memory_manager.is_shell_mode()
|
|
720
|
+
and user_input
|
|
721
|
+
and not user_input.startswith("/")
|
|
722
|
+
):
|
|
723
|
+
if session and hasattr(session, "app"):
|
|
724
|
+
try:
|
|
725
|
+
# 正确地等待异步方法
|
|
726
|
+
await session.app.run_system_command(
|
|
727
|
+
user_input, wait_for_enter=False
|
|
728
|
+
)
|
|
729
|
+
except Exception:
|
|
730
|
+
# 如果异步调用失败,回退到同步方式
|
|
731
|
+
import subprocess
|
|
732
|
+
|
|
733
|
+
subprocess.call([shell, "-c", user_input])
|
|
734
|
+
else:
|
|
735
|
+
output = execute_shell_command(user_input)
|
|
736
|
+
if output:
|
|
737
|
+
print(output)
|
|
738
|
+
return
|
|
739
|
+
|
|
740
|
+
if (
|
|
741
|
+
memory_manager.is_auto_detect_mode()
|
|
742
|
+
and user_input
|
|
743
|
+
and not user_input.startswith("/")
|
|
744
|
+
):
|
|
745
|
+
event_file, file_id = gengerate_event_file_path()
|
|
746
|
+
configure(f"event_file:{event_file}")
|
|
747
|
+
global_cancel.register_token(event_file)
|
|
748
|
+
run_agentic(user_input, cancel_token=event_file)
|
|
749
|
+
|
|
750
|
+
elif memory_manager.is_voice_input_mode() and not user_input.startswith("/"):
|
|
751
|
+
text = voice_input()
|
|
752
|
+
if text: # Check if text is not None
|
|
753
|
+
new_prompt_callback("/coding " + text)
|
|
754
|
+
|
|
755
|
+
elif user_input.startswith("/voice_input"):
|
|
756
|
+
text = voice_input()
|
|
757
|
+
if text: # Check if text is not None
|
|
758
|
+
new_prompt_callback("/coding " + text)
|
|
759
|
+
|
|
760
|
+
elif user_input.startswith("/clear") or user_input.startswith("/cls"):
|
|
761
|
+
print("\033c")
|
|
762
|
+
|
|
763
|
+
elif user_input.startswith("/add_files"):
|
|
764
|
+
args = user_input[len("/add_files") :].strip().split()
|
|
765
|
+
add_files(args)
|
|
766
|
+
elif user_input.startswith("/remove_files"):
|
|
767
|
+
file_names = user_input[len("/remove_files") :].strip().split(",")
|
|
768
|
+
remove_files(file_names)
|
|
769
|
+
elif user_input.startswith("/index/query"):
|
|
770
|
+
query = user_input[len("/index/query") :].strip()
|
|
771
|
+
index_query(query)
|
|
772
|
+
|
|
773
|
+
elif user_input.startswith("/index/build"):
|
|
774
|
+
event_file, file_id = gengerate_event_file_path()
|
|
775
|
+
configure(f"event_file:{event_file}")
|
|
776
|
+
global_cancel.register_token(event_file)
|
|
777
|
+
index_build()
|
|
778
|
+
|
|
779
|
+
elif user_input.startswith("/index/export"):
|
|
780
|
+
export_path = user_input[len("/index/export") :].strip()
|
|
781
|
+
index_export(export_path)
|
|
782
|
+
|
|
783
|
+
elif user_input.startswith("/index/import"):
|
|
784
|
+
import_path = user_input[len("/index/import") :].strip()
|
|
785
|
+
index_import(import_path)
|
|
786
|
+
|
|
787
|
+
elif user_input.startswith("/list_files"):
|
|
788
|
+
list_files()
|
|
789
|
+
|
|
790
|
+
elif user_input.startswith("/models"):
|
|
791
|
+
query = user_input[len("/models") :].strip()
|
|
792
|
+
handle_models_command(query)
|
|
793
|
+
|
|
794
|
+
elif user_input.startswith("/mode"):
|
|
795
|
+
conf = user_input[len("/mode") :].strip()
|
|
796
|
+
if not conf:
|
|
797
|
+
print(get_mode())
|
|
798
|
+
else:
|
|
799
|
+
set_mode(conf)
|
|
800
|
+
|
|
801
|
+
elif user_input.startswith("/conf/export"):
|
|
802
|
+
from autocoder.common.conf_import_export import export_conf
|
|
803
|
+
|
|
804
|
+
export_conf(os.getcwd(), user_input[len("/conf/export") :].strip() or ".")
|
|
805
|
+
|
|
806
|
+
elif user_input.startswith("/plugins"):
|
|
807
|
+
# 提取命令参数并交由 plugin_manager 处理
|
|
808
|
+
args = user_input[len("/plugins") :].strip().split()
|
|
809
|
+
result = plugin_manager.handle_plugins_command(args)
|
|
810
|
+
print(result, end="")
|
|
811
|
+
|
|
812
|
+
# Handle /conf and its subcommands like /conf /export, /conf /import
|
|
813
|
+
elif user_input.startswith("/conf"):
|
|
814
|
+
# Extract everything after "/conf"
|
|
815
|
+
command_args = user_input[len("/conf") :].strip()
|
|
816
|
+
# Call the handler from conf_command.py and print its string result
|
|
817
|
+
result_message = handle_conf_command(command_args)
|
|
818
|
+
print(result_message)
|
|
819
|
+
elif user_input.startswith("/revert"):
|
|
820
|
+
revert()
|
|
821
|
+
elif user_input.startswith("/commit"):
|
|
822
|
+
query = user_input[len("/commit") :].strip()
|
|
823
|
+
commit(query)
|
|
824
|
+
elif user_input.startswith("/help"):
|
|
825
|
+
query = user_input[len("/help") :].strip()
|
|
826
|
+
if not query:
|
|
827
|
+
show_help()
|
|
828
|
+
else:
|
|
829
|
+
from autocoder.auto_coder_runner import help
|
|
830
|
+
|
|
831
|
+
help(query)
|
|
832
|
+
|
|
833
|
+
elif user_input.startswith("/exclude_dirs"):
|
|
834
|
+
dir_names = user_input[len("/exclude_dirs") :].strip().split(",")
|
|
835
|
+
exclude_dirs(dir_names)
|
|
836
|
+
|
|
837
|
+
elif user_input.startswith("/exclude_files"):
|
|
838
|
+
query = user_input[len("/exclude_files") :].strip()
|
|
839
|
+
exclude_files(query)
|
|
840
|
+
|
|
841
|
+
elif user_input.startswith("/exit"):
|
|
842
|
+
# 退出应用
|
|
843
|
+
raise EOFError()
|
|
844
|
+
|
|
845
|
+
elif user_input.startswith("/coding"):
|
|
846
|
+
event_file, file_id = gengerate_event_file_path()
|
|
847
|
+
configure(f"event_file:{event_file}")
|
|
848
|
+
global_cancel.register_token(event_file)
|
|
849
|
+
query = user_input[len("/coding") :].strip()
|
|
850
|
+
if not query:
|
|
851
|
+
print(f"\033[91m{get_message('please_enter_request')}\033[0m")
|
|
852
|
+
return
|
|
853
|
+
coding(query, cancel_token=event_file)
|
|
854
|
+
elif user_input.startswith("/chat"):
|
|
855
|
+
event_file, file_id = gengerate_event_file_path()
|
|
856
|
+
configure(f"event_file:{event_file}")
|
|
857
|
+
global_cancel.register_token(event_file)
|
|
858
|
+
query = user_input[len("/chat") :].strip()
|
|
859
|
+
if not query:
|
|
860
|
+
print(f"\033[91m{get_message('please_enter_request')}\033[0m")
|
|
861
|
+
else:
|
|
862
|
+
chat(query)
|
|
863
|
+
|
|
864
|
+
elif user_input.startswith("/design"):
|
|
865
|
+
query = user_input[len("/design") :].strip()
|
|
866
|
+
if not query:
|
|
867
|
+
print(f"\033[91m{get_message('please_enter_design_request')}\033[0m")
|
|
868
|
+
else:
|
|
869
|
+
design(query)
|
|
870
|
+
|
|
871
|
+
elif user_input.startswith("/summon"):
|
|
872
|
+
query = user_input[len("/summon") :].strip()
|
|
873
|
+
if not query:
|
|
874
|
+
print(f"\033[91m{get_message('please_enter_request')}\033[0m")
|
|
875
|
+
else:
|
|
876
|
+
summon(query)
|
|
877
|
+
|
|
878
|
+
elif user_input.startswith("/lib"):
|
|
879
|
+
args = user_input[len("/lib") :].strip().split()
|
|
880
|
+
lib_command(args)
|
|
881
|
+
|
|
882
|
+
elif user_input.startswith("/rules"):
|
|
883
|
+
query = user_input[len("/rules") :].strip()
|
|
884
|
+
rules(query)
|
|
885
|
+
|
|
886
|
+
elif user_input.startswith("/mcp"):
|
|
887
|
+
query = user_input[len("/mcp") :].strip()
|
|
888
|
+
if not query:
|
|
889
|
+
print(get_message("please_enter_query"))
|
|
890
|
+
else:
|
|
891
|
+
mcp(query)
|
|
892
|
+
|
|
893
|
+
elif user_input.startswith("/active_context"):
|
|
894
|
+
query = user_input[len("/active_context") :].strip()
|
|
895
|
+
active_context(query)
|
|
896
|
+
|
|
897
|
+
elif user_input.startswith("/auto"):
|
|
898
|
+
query = user_input[len("/auto") :].strip()
|
|
899
|
+
event_file, _ = gengerate_event_file_path()
|
|
900
|
+
global_cancel.register_token(event_file)
|
|
901
|
+
configure(f"event_file:{event_file}")
|
|
902
|
+
run_agentic(query, cancel_token=event_file)
|
|
903
|
+
elif user_input.startswith("/debug"):
|
|
904
|
+
code = user_input[len("/debug") :].strip()
|
|
905
|
+
try:
|
|
906
|
+
result = eval(code)
|
|
907
|
+
print(f"Debug result: {result}")
|
|
908
|
+
except Exception as e:
|
|
909
|
+
print(f"Debug error: {str(e)}")
|
|
910
|
+
|
|
911
|
+
elif user_input.startswith("/shell"):
|
|
912
|
+
command = user_input[len("/shell") :].strip()
|
|
913
|
+
if not command:
|
|
914
|
+
# 如果没有命令参数,切换到 shell 模式
|
|
915
|
+
memory_manager.set_mode("shell")
|
|
916
|
+
print(get_message("switched_to_shell_mode"))
|
|
917
|
+
else:
|
|
918
|
+
if command.startswith("/chat"):
|
|
919
|
+
event_file, file_id = gengerate_event_file_path()
|
|
920
|
+
global_cancel.register_token(event_file)
|
|
921
|
+
configure(f"event_file:{event_file}")
|
|
922
|
+
command = command[len("/chat") :].strip()
|
|
923
|
+
gen_and_exec_shell_command(command)
|
|
924
|
+
else:
|
|
925
|
+
execute_shell_command(command)
|
|
926
|
+
else:
|
|
927
|
+
# 对于未识别的命令,显示提示信息而不是执行auto_command
|
|
928
|
+
if user_input and user_input.strip():
|
|
929
|
+
if user_input.startswith("/"):
|
|
930
|
+
command = user_input.split(" ")[0][1:]
|
|
931
|
+
query = user_input[len(command) + 1:].strip()
|
|
932
|
+
user_input = f"/command {command}.md {query}"
|
|
933
|
+
|
|
934
|
+
# 只有非命令输入才执行auto_command
|
|
935
|
+
event_file, _ = gengerate_event_file_path()
|
|
936
|
+
global_cancel.register_token(event_file)
|
|
937
|
+
configure(f"event_file:{event_file}")
|
|
938
|
+
run_agentic(user_input, cancel_token=event_file)
|
|
939
|
+
|
|
940
|
+
except EOFError:
|
|
941
|
+
# 重新抛出这些异常,让主循环处理
|
|
942
|
+
raise
|
|
943
|
+
except (CancelRequestedException, KeyboardInterrupt):
|
|
944
|
+
pass
|
|
945
|
+
except Exception as e:
|
|
946
|
+
print(
|
|
947
|
+
f"\033[91m 1. An error occurred:\033[0m \033[93m{type(e).__name__}\033[0m - {str(e)}"
|
|
337
948
|
)
|
|
338
|
-
|
|
339
|
-
|
|
949
|
+
if ARGS and ARGS.debug:
|
|
950
|
+
import traceback
|
|
340
951
|
|
|
341
|
-
|
|
342
|
-
# Add default plugin directory into global plugin dirs
|
|
343
|
-
plugin_manager.load_global_plugin_dirs()
|
|
344
|
-
plugin_manager.add_global_plugin_directory(os.path.join(os.path.dirname(__file__), "plugins"))
|
|
952
|
+
traceback.print_exc()
|
|
345
953
|
|
|
346
|
-
# 加载保存的运行时配置
|
|
347
|
-
plugin_manager.load_runtime_cfg()
|
|
348
|
-
|
|
349
|
-
# 自动加载内置插件(如果还没有被配置文件加载)
|
|
350
|
-
load_builtin_plugins()
|
|
351
954
|
|
|
352
|
-
|
|
955
|
+
async def run_app():
|
|
956
|
+
"""运行聊天应用"""
|
|
957
|
+
global ask, coding, chat, design, voice_input, auto_command, run_agentic, active_context, execute_shell_command
|
|
353
958
|
|
|
354
|
-
|
|
959
|
+
# 创建输入队列和忙碌状态
|
|
960
|
+
input_queue = asyncio.Queue()
|
|
961
|
+
busy_event = asyncio.Event()
|
|
962
|
+
busy_event.set() # 初始状态为空闲
|
|
355
963
|
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
"auto_detect": "nature language auto detect",
|
|
359
|
-
"voice_input": "voice input",
|
|
360
|
-
}
|
|
964
|
+
task_event = TaskEvent()
|
|
965
|
+
task_completion_callbacks = []
|
|
361
966
|
|
|
967
|
+
# 触发所有任务完成回调
|
|
968
|
+
async def trigger_task_completion_callbacks():
|
|
969
|
+
"""触发所有注册的任务完成回调"""
|
|
970
|
+
for callback in task_completion_callbacks:
|
|
971
|
+
try:
|
|
972
|
+
if asyncio.iscoroutinefunction(callback):
|
|
973
|
+
await callback()
|
|
974
|
+
else:
|
|
975
|
+
callback()
|
|
976
|
+
except Exception as e:
|
|
977
|
+
print(
|
|
978
|
+
f"\033[91mError in task completion callback:\033[0m {type(e).__name__} - {str(e)}"
|
|
979
|
+
)
|
|
980
|
+
if ARGS and ARGS.debug:
|
|
981
|
+
import traceback
|
|
982
|
+
|
|
983
|
+
traceback.print_exc()
|
|
984
|
+
task_completion_callbacks.clear()
|
|
985
|
+
|
|
986
|
+
# 创建后台消费者协程
|
|
987
|
+
async def consumer_loop():
|
|
988
|
+
"""后台处理用户输入的消费者协程"""
|
|
989
|
+
nonlocal session
|
|
990
|
+
while True:
|
|
991
|
+
is_queue_geted = False
|
|
992
|
+
try:
|
|
993
|
+
# 给队列获取操作添加超时,让消费者有机会响应取消请求
|
|
994
|
+
try:
|
|
995
|
+
user_input, new_prompt_callback, session = await asyncio.wait_for(
|
|
996
|
+
input_queue.get(), timeout=1.0
|
|
997
|
+
)
|
|
998
|
+
is_queue_geted = True
|
|
999
|
+
except asyncio.TimeoutError:
|
|
1000
|
+
# 超时后短暂休眠,然后继续循环等待
|
|
1001
|
+
await asyncio.sleep(0.1)
|
|
1002
|
+
continue
|
|
1003
|
+
|
|
1004
|
+
# 设置任务状态为已开始
|
|
1005
|
+
task_event.set_state("started")
|
|
1006
|
+
busy_event.clear() # 标记为忙碌
|
|
1007
|
+
|
|
1008
|
+
# 设置任务状态为运行中
|
|
1009
|
+
task_event.set_state("running")
|
|
1010
|
+
|
|
1011
|
+
# 直接调用异步的 process_user_input 函数
|
|
1012
|
+
await process_user_input(user_input, new_prompt_callback, session)
|
|
1013
|
+
|
|
1014
|
+
await trigger_task_completion_callbacks()
|
|
1015
|
+
|
|
1016
|
+
# 设置任务状态为已完成
|
|
1017
|
+
task_event.set_state("completed")
|
|
1018
|
+
|
|
1019
|
+
except KeyboardInterrupt:
|
|
1020
|
+
global_cancel.set_active_tokens()
|
|
1021
|
+
task_event.set_state("completed")
|
|
1022
|
+
continue
|
|
1023
|
+
except asyncio.CancelledError:
|
|
1024
|
+
break
|
|
1025
|
+
except Exception as e:
|
|
1026
|
+
if ARGS and ARGS.debug:
|
|
1027
|
+
import traceback
|
|
1028
|
+
|
|
1029
|
+
traceback.print_exc()
|
|
1030
|
+
continue
|
|
1031
|
+
finally:
|
|
1032
|
+
busy_event.set() # 标记为空闲
|
|
1033
|
+
if is_queue_geted:
|
|
1034
|
+
input_queue.task_done()
|
|
1035
|
+
# 确保任务状态最终被重置
|
|
1036
|
+
if task_event.get_state() != "completed":
|
|
1037
|
+
task_event.set_state("completed")
|
|
1038
|
+
|
|
1039
|
+
# 启动消费者协程
|
|
1040
|
+
consumer_task = asyncio.create_task(consumer_loop())
|
|
1041
|
+
|
|
1042
|
+
# 创建键盘绑定
|
|
362
1043
|
kb = KeyBindings()
|
|
363
1044
|
|
|
1045
|
+
# 捕获 Ctrl+C 和 Ctrl+D
|
|
364
1046
|
@kb.add("c-c")
|
|
365
1047
|
def _(event):
|
|
366
|
-
# 如果在历史搜索模式中
|
|
367
1048
|
if event.app.layout.is_searching:
|
|
368
1049
|
event.app.current_buffer.history_search_text = None
|
|
369
|
-
# 清除当前缓冲区
|
|
370
1050
|
event.app.current_buffer.reset()
|
|
371
|
-
else:
|
|
372
|
-
|
|
1051
|
+
# else:
|
|
1052
|
+
# event.app.exit(exception=KeyboardInterrupt)
|
|
1053
|
+
|
|
1054
|
+
@kb.add("c-d")
|
|
1055
|
+
def _(event):
|
|
1056
|
+
event.app.exit(exception=EOFError)
|
|
373
1057
|
|
|
374
1058
|
@kb.add("tab")
|
|
375
1059
|
def _(event):
|
|
@@ -387,38 +1071,31 @@ def main():
|
|
|
387
1071
|
|
|
388
1072
|
@kb.add("c-k")
|
|
389
1073
|
def _(event):
|
|
390
|
-
|
|
391
|
-
memory["mode"] = "auto_detect"
|
|
392
|
-
|
|
393
|
-
current_mode = memory["mode"]
|
|
394
|
-
if current_mode == "normal":
|
|
395
|
-
memory["mode"] = "auto_detect"
|
|
396
|
-
elif current_mode == "auto_detect":
|
|
397
|
-
memory["mode"] = "voice_input"
|
|
398
|
-
else: # voice_input
|
|
399
|
-
memory["mode"] = "normal"
|
|
400
|
-
|
|
401
|
-
save_memory()
|
|
1074
|
+
cycle_mode()
|
|
402
1075
|
event.app.invalidate()
|
|
403
1076
|
|
|
404
1077
|
@kb.add("c-n")
|
|
405
1078
|
def _(event):
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
current_status = memory["conf"]["human_as_model"]
|
|
410
|
-
new_status = "true" if current_status == "false" else "false"
|
|
1079
|
+
new_status_bool = toggle_human_as_model()
|
|
1080
|
+
new_status = "true" if new_status_bool else "false"
|
|
411
1081
|
configure(f"human_as_model:{new_status}", skip_print=True)
|
|
412
1082
|
event.app.invalidate()
|
|
413
1083
|
|
|
1084
|
+
# 注册粘贴处理器
|
|
1085
|
+
register_paste_handler(kb)
|
|
1086
|
+
|
|
414
1087
|
# 应用插件的键盘绑定
|
|
415
1088
|
plugin_manager.apply_keybindings(kb)
|
|
416
1089
|
|
|
417
1090
|
def get_bottom_toolbar():
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
1091
|
+
mode = get_mode()
|
|
1092
|
+
human_as_model = get_human_as_model_string()
|
|
1093
|
+
MODES = {
|
|
1094
|
+
"normal": "normal",
|
|
1095
|
+
"auto_detect": "nature language auto detect",
|
|
1096
|
+
"voice_input": "voice input",
|
|
1097
|
+
"shell": "shell",
|
|
1098
|
+
}
|
|
422
1099
|
if mode not in MODES:
|
|
423
1100
|
mode = "auto_detect"
|
|
424
1101
|
pwd = os.getcwd()
|
|
@@ -426,340 +1103,253 @@ def main():
|
|
|
426
1103
|
if len(pwd_parts) > 3:
|
|
427
1104
|
pwd = os.sep.join(pwd_parts[-3:])
|
|
428
1105
|
|
|
429
|
-
# Add plugin information to toolbar
|
|
430
1106
|
plugin_info = (
|
|
431
1107
|
f"Plugins: {len(plugin_manager.plugins)}" if plugin_manager.plugins else ""
|
|
432
1108
|
)
|
|
433
|
-
return f"Current Dir: {pwd} \nMode: {MODES[mode]}(ctrl+k) | Human as Model: {human_as_model}(ctrl+n) | {plugin_info}"
|
|
434
1109
|
|
|
435
|
-
|
|
1110
|
+
# 获取正在运行的 async 任务数量
|
|
1111
|
+
async_tasks_info = ""
|
|
1112
|
+
try:
|
|
1113
|
+
from pathlib import Path
|
|
1114
|
+
from autocoder.sdk.async_runner.task_metadata import TaskMetadataManager
|
|
1115
|
+
|
|
1116
|
+
async_agent_dir = Path.home() / ".auto-coder" / "async_agent"
|
|
1117
|
+
meta_dir = os.path.join(async_agent_dir, "meta")
|
|
1118
|
+
|
|
1119
|
+
if os.path.exists(meta_dir):
|
|
1120
|
+
metadata_manager = TaskMetadataManager(meta_dir)
|
|
1121
|
+
summary = metadata_manager.get_task_summary()
|
|
1122
|
+
running_count = summary.get("running", 0)
|
|
1123
|
+
|
|
1124
|
+
if running_count > 0:
|
|
1125
|
+
async_tasks_info = f" | Async Tasks: 🔄 {running_count}"
|
|
1126
|
+
except Exception:
|
|
1127
|
+
# 静默处理异常,不影响底部工具栏的显示
|
|
1128
|
+
pass
|
|
1129
|
+
|
|
1130
|
+
return f"Current Dir: {pwd} \nMode: {MODES[mode]}(ctrl+k) | Human as Model: {human_as_model}(ctrl+n) | {plugin_info}{async_tasks_info}"
|
|
1131
|
+
|
|
1132
|
+
# 创建增强补全器
|
|
436
1133
|
enhanced_completer = EnhancedCompleter(completer, plugin_manager)
|
|
437
1134
|
|
|
438
|
-
#
|
|
439
|
-
history_file_path = os.path.join(
|
|
440
|
-
|
|
1135
|
+
# 定义历史文件路径
|
|
1136
|
+
history_file_path = os.path.join(
|
|
1137
|
+
os.getcwd(), ".auto-coder", "auto-coder.chat", "history", "command_history.txt"
|
|
1138
|
+
)
|
|
441
1139
|
os.makedirs(os.path.dirname(history_file_path), exist_ok=True)
|
|
442
1140
|
|
|
1141
|
+
# 创建会话
|
|
443
1142
|
session = PromptSession(
|
|
444
|
-
history=FileHistory(history_file_path),
|
|
1143
|
+
history=FileHistory(history_file_path),
|
|
445
1144
|
auto_suggest=AutoSuggestFromHistory(),
|
|
446
1145
|
enable_history_search=False,
|
|
447
1146
|
completer=enhanced_completer,
|
|
448
|
-
complete_while_typing=
|
|
1147
|
+
complete_while_typing=False,
|
|
449
1148
|
key_bindings=kb,
|
|
450
1149
|
bottom_toolbar=get_bottom_toolbar,
|
|
1150
|
+
# 注意:bracketed paste 通过 Keys.BracketedPaste 键绑定处理
|
|
451
1151
|
)
|
|
452
|
-
print(
|
|
453
|
-
f"""
|
|
454
|
-
\033[1;32m ____ _ _ _ _ ____ _
|
|
455
|
-
/ ___| |__ __ _| |_ / \ _ _| |_ ___ / ___|___ __| | ___ _ __
|
|
456
|
-
| | | '_ \ / _` | __|____ / _ \| | | | __/ _ \ _____| | / _ \ / _` |/ _ \ '__|
|
|
457
|
-
| |___| | | | (_| | ||_____/ ___ \ |_| | || (_) |_____| |__| (_) | (_| | __/ |
|
|
458
|
-
\____|_| |_|\__,_|\__| /_/ \_\__,_|\__\___/ \____\___/ \__,_|\___|_|
|
|
459
|
-
v{__version__}
|
|
460
|
-
\033[0m"""
|
|
461
|
-
)
|
|
462
|
-
print("\033[1;34mType /help to see available commands.\033[0m\n")
|
|
463
|
-
|
|
464
|
-
# Add plugin information to startup message
|
|
465
|
-
if plugin_manager.plugins:
|
|
466
|
-
print("\033[1;34mLoaded Plugins:\033[0m")
|
|
467
|
-
for name, plugin in plugin_manager.plugins.items():
|
|
468
|
-
print(f" - {name} (v{plugin.version}): {plugin.description}")
|
|
469
|
-
print()
|
|
470
|
-
|
|
471
|
-
show_help()
|
|
472
|
-
|
|
473
|
-
style = Style.from_dict(
|
|
474
|
-
{
|
|
475
|
-
"username": "#884444",
|
|
476
|
-
"at": "#00aa00",
|
|
477
|
-
"colon": "#0000aa",
|
|
478
|
-
"pound": "#00aa00",
|
|
479
|
-
"host": "#00ffff bg:#444400",
|
|
480
|
-
}
|
|
481
|
-
)
|
|
482
|
-
|
|
483
|
-
new_prompt = ""
|
|
484
1152
|
|
|
485
|
-
#
|
|
1153
|
+
# 创建 wrapped functions
|
|
486
1154
|
wrapped_functions = {}
|
|
487
1155
|
for func_name, original_func in original_functions.items():
|
|
488
1156
|
wrapped_functions[func_name] = plugin_manager.wrap_function(
|
|
489
1157
|
original_func, func_name
|
|
490
1158
|
)
|
|
491
1159
|
|
|
492
|
-
#
|
|
493
|
-
global ask, coding, chat, design, voice_input, auto_command, execute_shell_command, active_context
|
|
1160
|
+
# 替换原始函数
|
|
494
1161
|
ask = wrapped_functions.get("ask", ask)
|
|
495
1162
|
coding = wrapped_functions.get("coding", coding)
|
|
496
1163
|
chat = wrapped_functions.get("chat", chat)
|
|
497
1164
|
design = wrapped_functions.get("design", design)
|
|
498
1165
|
voice_input = wrapped_functions.get("voice_input", voice_input)
|
|
499
1166
|
auto_command = wrapped_functions.get("auto_command", auto_command)
|
|
1167
|
+
run_agentic = wrapped_functions.get("run_agentic", run_agentic)
|
|
500
1168
|
active_context = wrapped_functions.get("active_context", active_context)
|
|
501
1169
|
execute_shell_command = wrapped_functions.get(
|
|
502
1170
|
"execute_shell_command", execute_shell_command
|
|
503
1171
|
)
|
|
504
1172
|
|
|
1173
|
+
stop_ev = asyncio.Event()
|
|
1174
|
+
new_prompt = ""
|
|
1175
|
+
|
|
1176
|
+
# 用于设置新提示的回调函数
|
|
1177
|
+
def set_new_prompt(prompt):
|
|
1178
|
+
nonlocal new_prompt
|
|
1179
|
+
new_prompt = prompt
|
|
1180
|
+
|
|
1181
|
+
# 样式定义
|
|
1182
|
+
style = Style.from_dict(
|
|
1183
|
+
{
|
|
1184
|
+
"username": "#884444",
|
|
1185
|
+
"at": "#00aa00",
|
|
1186
|
+
"colon": "#0000aa",
|
|
1187
|
+
"pound": "#00aa00",
|
|
1188
|
+
"host": "#00ffff bg:#444400",
|
|
1189
|
+
"busy": "#ff6600 italic",
|
|
1190
|
+
}
|
|
1191
|
+
)
|
|
1192
|
+
|
|
1193
|
+
# 显示启动信息
|
|
1194
|
+
print(
|
|
1195
|
+
f"""
|
|
1196
|
+
\033[1;32m ____ _ _ _ _ ____ _
|
|
1197
|
+
/ ___| |__ __ _| |_ / \\ _ _| |_ ___ / ___|___ __| | ___ _ __
|
|
1198
|
+
| | | '_ \\ / _` | __|____ / _ \\| | | | __/ _ \\ _____| | / _ \\ / _` |/ _ \\ '__|
|
|
1199
|
+
| |___| | | | (_| | ||_____/ ___ \\ |_| | || (_) |_____| |__| (_) | (_| | __/ |
|
|
1200
|
+
\\____|_| |_|\\__,_|\\__| /_/ \\_\\__,_|\\__\\___/ \\____\\___/ \\__,_|\\___|_|
|
|
1201
|
+
v{__version__}
|
|
1202
|
+
\033[0m"""
|
|
1203
|
+
)
|
|
1204
|
+
print(f"\033[1;34m{get_message('type_help_to_see_commands')}\033[0m\n")
|
|
1205
|
+
|
|
1206
|
+
# 显示插件信息
|
|
1207
|
+
if plugin_manager.plugins:
|
|
1208
|
+
print(f"\033[1;34m{get_message('loaded_plugins_title')}\033[0m")
|
|
1209
|
+
for name, plugin in plugin_manager.plugins.items():
|
|
1210
|
+
print(f" - {name} (v{plugin.version}): {plugin.description}")
|
|
1211
|
+
print()
|
|
1212
|
+
|
|
1213
|
+
show_help()
|
|
1214
|
+
|
|
1215
|
+
# 启动后台任务(传递 session 对象以便刷新工具栏)
|
|
1216
|
+
background_task_coro = asyncio.create_task(background_task(stop_ev, session))
|
|
1217
|
+
|
|
1218
|
+
# 主交互循环
|
|
505
1219
|
while True:
|
|
1220
|
+
task_state = task_event.get_state()
|
|
506
1221
|
try:
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
1222
|
+
# 根据任务状态控制是否渲染prompt
|
|
1223
|
+
if task_state in ["started", "running", "pending"]:
|
|
1224
|
+
# 任务运行中,不显示prompt,跳过此次循环
|
|
1225
|
+
await asyncio.sleep(0.1)
|
|
1226
|
+
continue
|
|
1227
|
+
else:
|
|
1228
|
+
prompt_message = [
|
|
1229
|
+
("class:username", "coding"),
|
|
1230
|
+
("class:at", "@"),
|
|
1231
|
+
("class:host", "auto-coder.chat"),
|
|
1232
|
+
("class:colon", ":"),
|
|
1233
|
+
("class:path", "~"),
|
|
1234
|
+
("class:dollar", "$ "),
|
|
1235
|
+
]
|
|
515
1236
|
|
|
516
1237
|
if new_prompt:
|
|
517
|
-
user_input = session.
|
|
1238
|
+
user_input = await session.prompt_async(
|
|
518
1239
|
FormattedText(prompt_message), default=new_prompt, style=style
|
|
519
1240
|
)
|
|
1241
|
+
new_prompt = ""
|
|
520
1242
|
else:
|
|
521
|
-
user_input = session.
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
if "mode" not in memory:
|
|
525
|
-
memory["mode"] = "auto_detect"
|
|
526
|
-
|
|
527
|
-
# 处理 user_input 的空格
|
|
528
|
-
if user_input:
|
|
529
|
-
temp_user_input = user_input.lstrip() # 去掉左侧空格
|
|
530
|
-
if temp_user_input.startswith("/"):
|
|
531
|
-
user_input = temp_user_input
|
|
532
|
-
|
|
533
|
-
# 修复插件命令处理逻辑
|
|
534
|
-
plugin_handled = False
|
|
535
|
-
if user_input.startswith("/"):
|
|
536
|
-
plugin_result = plugin_manager.process_command(user_input)
|
|
537
|
-
if plugin_result:
|
|
538
|
-
plugin_name, handler, args = plugin_result
|
|
539
|
-
if handler:
|
|
540
|
-
handler(*args)
|
|
541
|
-
plugin_handled = True
|
|
542
|
-
|
|
543
|
-
# 如果插件已处理命令,直接继续下一轮循环
|
|
544
|
-
if plugin_handled:
|
|
545
|
-
continue
|
|
546
|
-
|
|
547
|
-
# 如果插件未处理,继续处理内置命令
|
|
548
|
-
if (
|
|
549
|
-
memory["mode"] == "auto_detect"
|
|
550
|
-
and user_input
|
|
551
|
-
and not user_input.startswith("/")
|
|
552
|
-
):
|
|
553
|
-
event_file, file_id = gengerate_event_file_path()
|
|
554
|
-
configure(f"event_file:{event_file}")
|
|
555
|
-
global_cancel.register_token(event_file)
|
|
556
|
-
auto_command(user_input)
|
|
557
|
-
|
|
558
|
-
elif memory["mode"] == "voice_input" and not user_input.startswith("/"):
|
|
559
|
-
text = voice_input()
|
|
560
|
-
if text: # Check if text is not None
|
|
561
|
-
new_prompt = "/coding " + text
|
|
562
|
-
|
|
563
|
-
elif user_input.startswith("/voice_input"):
|
|
564
|
-
text = voice_input()
|
|
565
|
-
if text: # Check if text is not None
|
|
566
|
-
new_prompt = "/coding " + text
|
|
567
|
-
|
|
568
|
-
elif user_input.startswith("/clear") or user_input.startswith("/cls"):
|
|
569
|
-
print("\033c")
|
|
570
|
-
|
|
571
|
-
elif user_input.startswith("/add_files"):
|
|
572
|
-
args = user_input[len("/add_files") :].strip().split()
|
|
573
|
-
add_files(args)
|
|
574
|
-
elif user_input.startswith("/remove_files"):
|
|
575
|
-
file_names = user_input[len("/remove_files") :].strip().split(",")
|
|
576
|
-
remove_files(file_names)
|
|
577
|
-
elif user_input.startswith("/index/query"):
|
|
578
|
-
query = user_input[len("/index/query") :].strip()
|
|
579
|
-
index_query(query)
|
|
580
|
-
|
|
581
|
-
elif user_input.startswith("/index/build"):
|
|
582
|
-
event_file, file_id = gengerate_event_file_path()
|
|
583
|
-
configure(f"event_file:{event_file}")
|
|
584
|
-
global_cancel.register_token(event_file)
|
|
585
|
-
index_build()
|
|
1243
|
+
user_input = await session.prompt_async(
|
|
1244
|
+
FormattedText(prompt_message), style=style
|
|
1245
|
+
)
|
|
586
1246
|
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
index_export(export_path)
|
|
1247
|
+
if user_input.strip() == "/exit":
|
|
1248
|
+
raise EOFError()
|
|
590
1249
|
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
|
|
1250
|
+
# 将输入放入队列,包含完成回调
|
|
1251
|
+
if user_input.strip():
|
|
1252
|
+
await input_queue.put((user_input, set_new_prompt, session))
|
|
1253
|
+
task_event.set_state("pending")
|
|
594
1254
|
|
|
595
|
-
|
|
596
|
-
|
|
1255
|
+
except (KeyboardInterrupt, asyncio.CancelledError):
|
|
1256
|
+
global_cancel.set_active_tokens()
|
|
1257
|
+
continue
|
|
1258
|
+
except CancelRequestedException:
|
|
1259
|
+
continue
|
|
1260
|
+
except EOFError:
|
|
1261
|
+
break
|
|
1262
|
+
except Exception as e:
|
|
1263
|
+
print(
|
|
1264
|
+
f"\033[91m 2. An error occurred:\033[0m \033[93m{type(e).__name__}\033[0m - {str(e)}"
|
|
1265
|
+
)
|
|
1266
|
+
if ARGS and ARGS.debug:
|
|
1267
|
+
import traceback
|
|
597
1268
|
|
|
598
|
-
|
|
599
|
-
query = user_input[len("/models") :].strip()
|
|
600
|
-
handle_models_command(query, get_memory())
|
|
1269
|
+
traceback.print_exc()
|
|
601
1270
|
|
|
602
|
-
|
|
603
|
-
|
|
604
|
-
if not conf:
|
|
605
|
-
print(memory["mode"])
|
|
606
|
-
else:
|
|
607
|
-
memory["mode"] = conf
|
|
608
|
-
save_memory()
|
|
609
|
-
|
|
610
|
-
elif user_input.startswith("/conf/export"):
|
|
611
|
-
from autocoder.common.conf_import_export import export_conf
|
|
612
|
-
export_conf(os.getcwd(), user_input[len("/conf/export") :].strip() or ".")
|
|
613
|
-
|
|
614
|
-
elif user_input.startswith("/plugins"):
|
|
615
|
-
# 提取命令参数并交由 plugin_manager 处理
|
|
616
|
-
args = user_input[len("/plugins") :].strip().split()
|
|
617
|
-
result = plugin_manager.handle_plugins_command(args)
|
|
618
|
-
print(result, end="")
|
|
619
|
-
|
|
620
|
-
# Handle /conf and its subcommands like /conf /export, /conf /import
|
|
621
|
-
elif user_input.startswith("/conf"):
|
|
622
|
-
# Extract everything after "/conf"
|
|
623
|
-
command_args = user_input[len("/conf"):].strip()
|
|
624
|
-
# Call the handler from conf_command.py and print its string result
|
|
625
|
-
result_message = handle_conf_command(command_args, memory)
|
|
626
|
-
print(result_message)
|
|
627
|
-
elif user_input.startswith("/revert"):
|
|
628
|
-
revert()
|
|
629
|
-
elif user_input.startswith("/commit"):
|
|
630
|
-
query = user_input[len("/commit") :].strip()
|
|
631
|
-
commit(query)
|
|
632
|
-
elif user_input.startswith("/help"):
|
|
633
|
-
query = user_input[len("/help") :].strip()
|
|
634
|
-
if not query:
|
|
635
|
-
show_help()
|
|
636
|
-
else:
|
|
637
|
-
help(query)
|
|
1271
|
+
exit_msg = get_i18n_message("exit_ctrl_d")
|
|
1272
|
+
print(f"\n\033[93m{exit_msg}\033[0m")
|
|
638
1273
|
|
|
639
|
-
|
|
640
|
-
|
|
641
|
-
exclude_dirs(dir_names)
|
|
1274
|
+
# 通知后台任务停止
|
|
1275
|
+
stop_ev.set()
|
|
642
1276
|
|
|
643
|
-
|
|
644
|
-
|
|
645
|
-
|
|
1277
|
+
# 取消消费者任务
|
|
1278
|
+
consumer_task.cancel()
|
|
1279
|
+
try:
|
|
1280
|
+
await consumer_task
|
|
1281
|
+
except asyncio.CancelledError:
|
|
1282
|
+
pass
|
|
646
1283
|
|
|
647
|
-
|
|
648
|
-
|
|
1284
|
+
# 取消后台任务
|
|
1285
|
+
background_task_coro.cancel()
|
|
1286
|
+
try:
|
|
1287
|
+
await background_task_coro
|
|
1288
|
+
except asyncio.CancelledError:
|
|
1289
|
+
pass
|
|
649
1290
|
|
|
650
|
-
|
|
651
|
-
|
|
652
|
-
|
|
653
|
-
|
|
654
|
-
|
|
655
|
-
|
|
656
|
-
|
|
657
|
-
|
|
658
|
-
|
|
659
|
-
|
|
660
|
-
|
|
661
|
-
|
|
662
|
-
|
|
663
|
-
|
|
664
|
-
|
|
665
|
-
|
|
666
|
-
else:
|
|
667
|
-
chat(query)
|
|
1291
|
+
# 清理资源
|
|
1292
|
+
try:
|
|
1293
|
+
# 关闭所有插件
|
|
1294
|
+
plugin_manager.shutdown_all()
|
|
1295
|
+
# 停止 MCP 服务器
|
|
1296
|
+
try:
|
|
1297
|
+
if get_mcp_server():
|
|
1298
|
+
get_mcp_server().stop()
|
|
1299
|
+
except Exception as e:
|
|
1300
|
+
pass
|
|
1301
|
+
# 停止引擎
|
|
1302
|
+
stop_engine()
|
|
1303
|
+
except Exception as e:
|
|
1304
|
+
print(
|
|
1305
|
+
f"\033[91m 3. An error occurred while cleaning up:\033[0m \033[93m{type(e).__name__}\033[0m - {str(e)}"
|
|
1306
|
+
)
|
|
668
1307
|
|
|
669
|
-
|
|
670
|
-
|
|
671
|
-
if not query:
|
|
672
|
-
print("\033[91mPlease enter your design request.\033[0m")
|
|
673
|
-
else:
|
|
674
|
-
design(query)
|
|
1308
|
+
goodbye_msg = get_i18n_message("goodbye")
|
|
1309
|
+
print(f"\n\033[93m{goodbye_msg}\033[0m")
|
|
675
1310
|
|
|
676
|
-
elif user_input.startswith("/summon"):
|
|
677
|
-
query = user_input[len("/summon") :].strip()
|
|
678
|
-
if not query:
|
|
679
|
-
print("\033[91mPlease enter your request.\033[0m")
|
|
680
|
-
else:
|
|
681
|
-
summon(query)
|
|
682
1311
|
|
|
683
|
-
|
|
684
|
-
|
|
685
|
-
|
|
1312
|
+
def main():
|
|
1313
|
+
global ARGS
|
|
1314
|
+
load_tokenizer()
|
|
1315
|
+
ARGS = parse_arguments()
|
|
686
1316
|
|
|
687
|
-
|
|
688
|
-
|
|
689
|
-
rules(query)
|
|
1317
|
+
if ARGS.lite:
|
|
1318
|
+
ARGS.product_mode = "lite"
|
|
690
1319
|
|
|
691
|
-
|
|
692
|
-
|
|
693
|
-
if not query:
|
|
694
|
-
print("Please enter your query.")
|
|
695
|
-
else:
|
|
696
|
-
mcp(query)
|
|
697
|
-
|
|
698
|
-
elif user_input.startswith("/active_context"):
|
|
699
|
-
query = user_input[len("/active_context") :].strip()
|
|
700
|
-
active_context(query)
|
|
701
|
-
|
|
702
|
-
elif user_input.startswith("/auto"):
|
|
703
|
-
query = user_input[len("/auto") :].strip()
|
|
704
|
-
auto_command(query)
|
|
705
|
-
elif user_input.startswith("/debug"):
|
|
706
|
-
code = user_input[len("/debug") :].strip()
|
|
707
|
-
try:
|
|
708
|
-
result = eval(code)
|
|
709
|
-
print(f"Debug result: {result}")
|
|
710
|
-
except Exception as e:
|
|
711
|
-
print(f"Debug error: {str(e)}")
|
|
1320
|
+
if ARGS.pro:
|
|
1321
|
+
ARGS.product_mode = "pro"
|
|
712
1322
|
|
|
713
|
-
|
|
714
|
-
|
|
715
|
-
|
|
716
|
-
|
|
717
|
-
|
|
718
|
-
|
|
719
|
-
|
|
720
|
-
|
|
721
|
-
|
|
722
|
-
command = command[len("/chat") :].strip()
|
|
723
|
-
gen_and_exec_shell_command(command)
|
|
724
|
-
else:
|
|
725
|
-
execute_shell_command(command)
|
|
726
|
-
else:
|
|
727
|
-
# 对于未识别的命令,显示提示信息而不是执行auto_command
|
|
728
|
-
if user_input and user_input.strip():
|
|
729
|
-
if user_input.startswith("/"):
|
|
730
|
-
print(f"\033[91mUnknown command: {user_input}\033[0m")
|
|
731
|
-
print("Type /help to see available commands.")
|
|
732
|
-
else:
|
|
733
|
-
# 只有非命令输入才执行auto_command
|
|
734
|
-
auto_command(user_input)
|
|
735
|
-
|
|
736
|
-
except KeyboardInterrupt:
|
|
737
|
-
continue
|
|
738
|
-
except EOFError:
|
|
739
|
-
try:
|
|
740
|
-
# Shutdown all plugins before exiting
|
|
741
|
-
plugin_manager.shutdown_all()
|
|
742
|
-
# save_memory()
|
|
743
|
-
try:
|
|
744
|
-
if get_mcp_server():
|
|
745
|
-
get_mcp_server().stop()
|
|
746
|
-
except Exception as e:
|
|
747
|
-
pass
|
|
748
|
-
stop_engine()
|
|
749
|
-
except Exception as e:
|
|
750
|
-
print(
|
|
751
|
-
f"\033[91mAn error occurred while saving memory:\033[0m \033[93m{type(e).__name__}\033[0m - {str(e)}"
|
|
752
|
-
)
|
|
753
|
-
print("\n\033[93mExiting Chat Auto Coder...\033[0m")
|
|
754
|
-
break
|
|
755
|
-
except Exception as e:
|
|
756
|
-
print(
|
|
757
|
-
f"\033[91mAn error occurred:\033[0m \033[93m{type(e).__name__}\033[0m - {str(e)}"
|
|
1323
|
+
if not ARGS.quick:
|
|
1324
|
+
initialize_system(
|
|
1325
|
+
InitializeSystemRequest(
|
|
1326
|
+
product_mode=ARGS.product_mode,
|
|
1327
|
+
skip_provider_selection=ARGS.skip_provider_selection,
|
|
1328
|
+
debug=ARGS.debug,
|
|
1329
|
+
quick=ARGS.quick,
|
|
1330
|
+
lite=ARGS.lite,
|
|
1331
|
+
pro=ARGS.pro,
|
|
758
1332
|
)
|
|
759
|
-
|
|
760
|
-
import traceback
|
|
1333
|
+
)
|
|
761
1334
|
|
|
762
|
-
|
|
1335
|
+
start_engine()
|
|
1336
|
+
|
|
1337
|
+
# 初始化插件系统
|
|
1338
|
+
plugin_manager.load_global_plugin_dirs()
|
|
1339
|
+
plugin_manager.add_global_plugin_directory(
|
|
1340
|
+
os.path.join(os.path.dirname(__file__), "plugins")
|
|
1341
|
+
)
|
|
1342
|
+
|
|
1343
|
+
# 加载保存的运行时配置
|
|
1344
|
+
plugin_manager.load_runtime_cfg()
|
|
1345
|
+
|
|
1346
|
+
# 自动加载内置插件
|
|
1347
|
+
load_builtin_plugins()
|
|
1348
|
+
|
|
1349
|
+
configure(f"product_mode:{ARGS.product_mode}")
|
|
1350
|
+
|
|
1351
|
+
# 运行应用
|
|
1352
|
+
asyncio.run(run_app())
|
|
763
1353
|
|
|
764
1354
|
|
|
765
1355
|
if __name__ == "__main__":
|