auto-coder 0.1.400__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-0.1.400.dist-info → auto_coder-2.0.0.dist-info}/WHEEL +1 -1
- {auto_coder-0.1.400.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 +25 -4
- 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 +1029 -2310
- 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 +1021 -372
- autocoder/chat_auto_coder_lang.py +23 -732
- autocoder/commands/auto_command.py +26 -9
- 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/file_monitor/test_file_monitor.py +307 -0
- autocoder/common/git_utils.py +51 -10
- 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 +746 -0
- autocoder/common/{context_pruner.py → pruner/context_pruner.py} +137 -40
- 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/{conversation_pruner.py → pruner/conversation_pruner.py} +26 -6
- autocoder/common/pruner/test_agentic_conversation_pruner.py +784 -0
- autocoder/common/pruner/test_context_pruner.py +546 -0
- 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/__init__.py +15 -0
- autocoder/common/tokens/counter.py +44 -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 +2729 -2052
- autocoder/common/v2/agent/agentic_edit_change_manager.py +474 -0
- autocoder/common/v2/agent/agentic_edit_tools/__init__.py +43 -2
- autocoder/common/v2/agent/agentic_edit_tools/ac_mod_list_tool_resolver.py +279 -0
- autocoder/common/v2/agent/agentic_edit_tools/ac_mod_read_tool_resolver.py +40 -0
- autocoder/common/v2/agent/agentic_edit_tools/ac_mod_write_tool_resolver.py +52 -0
- autocoder/common/v2/agent/agentic_edit_tools/ask_followup_question_tool_resolver.py +8 -0
- 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 +565 -30
- 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 +244 -51
- 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 +409 -140
- 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 +209 -194
- autocoder/common/v2/agent/agentic_edit_tools/todo_read_tool_resolver.py +135 -0
- autocoder/common/v2/agent/agentic_edit_tools/todo_write_tool_resolver.py +328 -0
- 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 +386 -10
- autocoder/common/v2/agent/runner/__init__.py +31 -0
- autocoder/common/v2/agent/runner/base_runner.py +92 -0
- autocoder/common/v2/agent/runner/file_based_event_runner.py +217 -0
- autocoder/common/v2/agent/runner/sdk_runner.py +182 -0
- autocoder/common/v2/agent/runner/terminal_runner.py +396 -0
- autocoder/common/v2/agent/runner/tool_display.py +589 -0
- 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 +117 -125
- autocoder/{agent → index/filter}/agentic_filter.py +323 -334
- 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 +156 -37
- 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/run_context.py +9 -0
- autocoder/sdk/__init__.py +50 -161
- 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 +158 -170
- autocoder/sdk/cli/options.py +95 -22
- autocoder/sdk/constants.py +139 -51
- autocoder/sdk/core/auto_coder_core.py +484 -267
- autocoder/sdk/core/bridge.py +298 -118
- 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-0.1.400.dist-info/METADATA +0 -396
- auto_coder-0.1.400.dist-info/RECORD +0 -425
- auto_coder-0.1.400.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/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-0.1.400.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/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,
|
|
63
69
|
)
|
|
70
|
+
from autocoder.common.international import (
|
|
71
|
+
get_message as get_i18n_message,
|
|
72
|
+
get_message_with_format,
|
|
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,61 +178,87 @@ 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
|
-
|
|
174
|
-
|
|
175
|
-
|
|
254
|
+
if plugin:
|
|
255
|
+
print(
|
|
256
|
+
f" \033[94m{cmd}\033[0m - \033[92m{desc} ({get_message('plugin_from')} {plugin.plugin_name()})\033[0m"
|
|
257
|
+
)
|
|
258
|
+
else:
|
|
259
|
+
print(
|
|
260
|
+
f" \033[94m{cmd}\033[0m - \033[92m{desc} ({get_message('plugin_from_unknown')})\033[0m"
|
|
261
|
+
)
|
|
176
262
|
print()
|
|
177
263
|
|
|
178
264
|
|
|
@@ -182,6 +268,41 @@ class EnhancedCompleter(Completer):
|
|
|
182
268
|
def __init__(self, base_completer: Completer, plugin_manager: PluginManager):
|
|
183
269
|
self.base_completer: Completer = base_completer
|
|
184
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 []
|
|
185
306
|
|
|
186
307
|
def get_completions(self, document, complete_event):
|
|
187
308
|
# 获取当前输入的文本
|
|
@@ -226,12 +347,25 @@ class EnhancedCompleter(Completer):
|
|
|
226
347
|
)
|
|
227
348
|
return
|
|
228
349
|
# 处理直接命令补全 - 如果输入不包含空格,匹配整个命令
|
|
229
|
-
|
|
350
|
+
# 1. 插件和内置命令
|
|
351
|
+
for command in self.plugin_manager.get_all_commands_with_prefix(
|
|
352
|
+
current_input
|
|
353
|
+
):
|
|
230
354
|
yield Completion(
|
|
231
355
|
command[len(current_input) :],
|
|
232
356
|
start_position=0,
|
|
233
357
|
display=command,
|
|
234
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
|
+
)
|
|
235
369
|
|
|
236
370
|
# 获取并返回基础补全器的补全
|
|
237
371
|
if self.base_completer:
|
|
@@ -264,63 +398,662 @@ class EnhancedCompleter(Completer):
|
|
|
264
398
|
async def get_completions_async(self, document, complete_event):
|
|
265
399
|
"""异步获取补全内容。
|
|
266
400
|
|
|
267
|
-
|
|
268
|
-
|
|
401
|
+
使用 asyncio.run_in_executor 来异步执行耗时的补全操作,
|
|
402
|
+
避免阻塞主线程导致输入卡顿。
|
|
269
403
|
"""
|
|
270
|
-
|
|
271
|
-
|
|
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
|
+
)
|
|
272
527
|
|
|
273
528
|
|
|
274
529
|
ARGS = None
|
|
275
530
|
|
|
276
531
|
|
|
277
|
-
def
|
|
278
|
-
|
|
279
|
-
|
|
532
|
+
def load_builtin_plugins():
|
|
533
|
+
"""加载内置插件"""
|
|
534
|
+
try:
|
|
535
|
+
# 发现所有可用的插件
|
|
536
|
+
discovered_plugins = plugin_manager.discover_plugins()
|
|
280
537
|
|
|
281
|
-
|
|
282
|
-
|
|
538
|
+
# 排除的示例插件列表
|
|
539
|
+
excluded_plugins = {
|
|
540
|
+
"autocoder.plugins.dynamic_completion_example",
|
|
541
|
+
"autocoder.plugins.sample_plugin",
|
|
542
|
+
}
|
|
283
543
|
|
|
284
|
-
|
|
285
|
-
|
|
544
|
+
# 自动加载内置插件(在autocoder.plugins模块中的插件)
|
|
545
|
+
builtin_loaded = 0
|
|
546
|
+
for plugin_class in discovered_plugins:
|
|
547
|
+
module_name = plugin_class.__module__
|
|
548
|
+
if (
|
|
549
|
+
module_name.startswith("autocoder.plugins.")
|
|
550
|
+
and not module_name.endswith(".__init__")
|
|
551
|
+
and module_name not in excluded_plugins
|
|
552
|
+
):
|
|
553
|
+
try:
|
|
554
|
+
if plugin_manager.load_plugin(plugin_class):
|
|
555
|
+
builtin_loaded += 1
|
|
556
|
+
print(f"✓ Loaded builtin plugin: {plugin_class.plugin_name()}")
|
|
557
|
+
except Exception as e:
|
|
558
|
+
print(
|
|
559
|
+
f"✗ Failed to load builtin plugin {plugin_class.plugin_name()}: {e}"
|
|
560
|
+
)
|
|
286
561
|
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
debug=ARGS.debug,
|
|
293
|
-
quick=ARGS.quick,
|
|
294
|
-
lite=ARGS.lite,
|
|
295
|
-
pro=ARGS.pro,
|
|
562
|
+
if builtin_loaded > 0:
|
|
563
|
+
print(
|
|
564
|
+
get_message_with_format_local(
|
|
565
|
+
"loaded_plugins_builtin", count=builtin_loaded
|
|
566
|
+
)
|
|
296
567
|
)
|
|
568
|
+
else:
|
|
569
|
+
print(get_message("no_builtin_plugins_loaded"))
|
|
570
|
+
|
|
571
|
+
except Exception as e:
|
|
572
|
+
print(f"Error loading builtin plugins: {e}")
|
|
573
|
+
|
|
574
|
+
|
|
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
|
|
581
|
+
|
|
582
|
+
# 配置刷新频率(秒)
|
|
583
|
+
TOOLBAR_REFRESH_INTERVAL = 5 # 默认5秒刷新一次
|
|
584
|
+
FAST_REFRESH_INTERVAL = 1 # 有异步任务时1秒刷新一次
|
|
585
|
+
|
|
586
|
+
while not stop_event.is_set():
|
|
587
|
+
try:
|
|
588
|
+
# 检查是否有需要处理的后台任务
|
|
589
|
+
# 这里可以添加系统监控逻辑
|
|
590
|
+
counter += 1
|
|
591
|
+
toolbar_refresh_counter += 1
|
|
592
|
+
|
|
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)}"
|
|
297
948
|
)
|
|
298
|
-
|
|
299
|
-
|
|
949
|
+
if ARGS and ARGS.debug:
|
|
950
|
+
import traceback
|
|
300
951
|
|
|
301
|
-
|
|
302
|
-
# Add default plugin directory into global plugin dirs
|
|
303
|
-
plugin_manager.load_global_plugin_dirs()
|
|
304
|
-
plugin_manager.add_global_plugin_directory(os.path.join(os.path.dirname(__file__), "plugins"))
|
|
952
|
+
traceback.print_exc()
|
|
305
953
|
|
|
306
|
-
# 加载保存的运行时配置
|
|
307
|
-
plugin_manager.load_runtime_cfg()
|
|
308
954
|
|
|
309
|
-
|
|
955
|
+
async def run_app():
|
|
956
|
+
"""运行聊天应用"""
|
|
957
|
+
global ask, coding, chat, design, voice_input, auto_command, run_agentic, active_context, execute_shell_command
|
|
310
958
|
|
|
311
|
-
|
|
959
|
+
# 创建输入队列和忙碌状态
|
|
960
|
+
input_queue = asyncio.Queue()
|
|
961
|
+
busy_event = asyncio.Event()
|
|
962
|
+
busy_event.set() # 初始状态为空闲
|
|
312
963
|
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
"auto_detect": "nature language auto detect",
|
|
316
|
-
"voice_input": "voice input",
|
|
317
|
-
}
|
|
964
|
+
task_event = TaskEvent()
|
|
965
|
+
task_completion_callbacks = []
|
|
318
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
|
+
# 创建键盘绑定
|
|
319
1043
|
kb = KeyBindings()
|
|
320
1044
|
|
|
1045
|
+
# 捕获 Ctrl+C 和 Ctrl+D
|
|
321
1046
|
@kb.add("c-c")
|
|
322
1047
|
def _(event):
|
|
323
|
-
event.app.
|
|
1048
|
+
if event.app.layout.is_searching:
|
|
1049
|
+
event.app.current_buffer.history_search_text = None
|
|
1050
|
+
event.app.current_buffer.reset()
|
|
1051
|
+
# else:
|
|
1052
|
+
# event.app.exit(exception=KeyboardInterrupt)
|
|
1053
|
+
|
|
1054
|
+
@kb.add("c-d")
|
|
1055
|
+
def _(event):
|
|
1056
|
+
event.app.exit(exception=EOFError)
|
|
324
1057
|
|
|
325
1058
|
@kb.add("tab")
|
|
326
1059
|
def _(event):
|
|
@@ -338,38 +1071,31 @@ def main():
|
|
|
338
1071
|
|
|
339
1072
|
@kb.add("c-k")
|
|
340
1073
|
def _(event):
|
|
341
|
-
|
|
342
|
-
memory["mode"] = "auto_detect"
|
|
343
|
-
|
|
344
|
-
current_mode = memory["mode"]
|
|
345
|
-
if current_mode == "normal":
|
|
346
|
-
memory["mode"] = "auto_detect"
|
|
347
|
-
elif current_mode == "auto_detect":
|
|
348
|
-
memory["mode"] = "voice_input"
|
|
349
|
-
else: # voice_input
|
|
350
|
-
memory["mode"] = "normal"
|
|
351
|
-
|
|
352
|
-
save_memory()
|
|
1074
|
+
cycle_mode()
|
|
353
1075
|
event.app.invalidate()
|
|
354
1076
|
|
|
355
1077
|
@kb.add("c-n")
|
|
356
1078
|
def _(event):
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
current_status = memory["conf"]["human_as_model"]
|
|
361
|
-
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"
|
|
362
1081
|
configure(f"human_as_model:{new_status}", skip_print=True)
|
|
363
1082
|
event.app.invalidate()
|
|
364
1083
|
|
|
1084
|
+
# 注册粘贴处理器
|
|
1085
|
+
register_paste_handler(kb)
|
|
1086
|
+
|
|
365
1087
|
# 应用插件的键盘绑定
|
|
366
1088
|
plugin_manager.apply_keybindings(kb)
|
|
367
1089
|
|
|
368
1090
|
def get_bottom_toolbar():
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
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
|
+
}
|
|
373
1099
|
if mode not in MODES:
|
|
374
1100
|
mode = "auto_detect"
|
|
375
1101
|
pwd = os.getcwd()
|
|
@@ -377,330 +1103,253 @@ def main():
|
|
|
377
1103
|
if len(pwd_parts) > 3:
|
|
378
1104
|
pwd = os.sep.join(pwd_parts[-3:])
|
|
379
1105
|
|
|
380
|
-
# Add plugin information to toolbar
|
|
381
1106
|
plugin_info = (
|
|
382
1107
|
f"Plugins: {len(plugin_manager.plugins)}" if plugin_manager.plugins else ""
|
|
383
1108
|
)
|
|
384
|
-
return f"Current Dir: {pwd} \nMode: {MODES[mode]}(ctrl+k) | Human as Model: {human_as_model}(ctrl+n) | {plugin_info}"
|
|
385
1109
|
|
|
386
|
-
|
|
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
|
+
# 创建增强补全器
|
|
387
1133
|
enhanced_completer = EnhancedCompleter(completer, plugin_manager)
|
|
388
1134
|
|
|
389
|
-
#
|
|
390
|
-
history_file_path = os.path.join(
|
|
391
|
-
|
|
1135
|
+
# 定义历史文件路径
|
|
1136
|
+
history_file_path = os.path.join(
|
|
1137
|
+
os.getcwd(), ".auto-coder", "auto-coder.chat", "history", "command_history.txt"
|
|
1138
|
+
)
|
|
392
1139
|
os.makedirs(os.path.dirname(history_file_path), exist_ok=True)
|
|
393
1140
|
|
|
1141
|
+
# 创建会话
|
|
394
1142
|
session = PromptSession(
|
|
395
|
-
history=FileHistory(history_file_path),
|
|
1143
|
+
history=FileHistory(history_file_path),
|
|
396
1144
|
auto_suggest=AutoSuggestFromHistory(),
|
|
397
1145
|
enable_history_search=False,
|
|
398
1146
|
completer=enhanced_completer,
|
|
399
|
-
complete_while_typing=
|
|
1147
|
+
complete_while_typing=False,
|
|
400
1148
|
key_bindings=kb,
|
|
401
1149
|
bottom_toolbar=get_bottom_toolbar,
|
|
402
|
-
|
|
403
|
-
print(
|
|
404
|
-
f"""
|
|
405
|
-
\033[1;32m ____ _ _ _ _ ____ _
|
|
406
|
-
/ ___| |__ __ _| |_ / \ _ _| |_ ___ / ___|___ __| | ___ _ __
|
|
407
|
-
| | | '_ \ / _` | __|____ / _ \| | | | __/ _ \ _____| | / _ \ / _` |/ _ \ '__|
|
|
408
|
-
| |___| | | | (_| | ||_____/ ___ \ |_| | || (_) |_____| |__| (_) | (_| | __/ |
|
|
409
|
-
\____|_| |_|\__,_|\__| /_/ \_\__,_|\__\___/ \____\___/ \__,_|\___|_|
|
|
410
|
-
v{__version__}
|
|
411
|
-
\033[0m"""
|
|
412
|
-
)
|
|
413
|
-
print("\033[1;34mType /help to see available commands.\033[0m\n")
|
|
414
|
-
|
|
415
|
-
# Add plugin information to startup message
|
|
416
|
-
if plugin_manager.plugins:
|
|
417
|
-
print("\033[1;34mLoaded Plugins:\033[0m")
|
|
418
|
-
for name, plugin in plugin_manager.plugins.items():
|
|
419
|
-
print(f" - {name} (v{plugin.version}): {plugin.description}")
|
|
420
|
-
print()
|
|
421
|
-
|
|
422
|
-
show_help()
|
|
423
|
-
|
|
424
|
-
style = Style.from_dict(
|
|
425
|
-
{
|
|
426
|
-
"username": "#884444",
|
|
427
|
-
"at": "#00aa00",
|
|
428
|
-
"colon": "#0000aa",
|
|
429
|
-
"pound": "#00aa00",
|
|
430
|
-
"host": "#00ffff bg:#444400",
|
|
431
|
-
}
|
|
1150
|
+
# 注意:bracketed paste 通过 Keys.BracketedPaste 键绑定处理
|
|
432
1151
|
)
|
|
433
1152
|
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
# Create wrapped versions of functions that plugins want to intercept
|
|
1153
|
+
# 创建 wrapped functions
|
|
437
1154
|
wrapped_functions = {}
|
|
438
1155
|
for func_name, original_func in original_functions.items():
|
|
439
1156
|
wrapped_functions[func_name] = plugin_manager.wrap_function(
|
|
440
1157
|
original_func, func_name
|
|
441
1158
|
)
|
|
442
1159
|
|
|
443
|
-
#
|
|
444
|
-
global ask, coding, chat, design, voice_input, auto_command, execute_shell_command, active_context
|
|
1160
|
+
# 替换原始函数
|
|
445
1161
|
ask = wrapped_functions.get("ask", ask)
|
|
446
1162
|
coding = wrapped_functions.get("coding", coding)
|
|
447
1163
|
chat = wrapped_functions.get("chat", chat)
|
|
448
1164
|
design = wrapped_functions.get("design", design)
|
|
449
1165
|
voice_input = wrapped_functions.get("voice_input", voice_input)
|
|
450
1166
|
auto_command = wrapped_functions.get("auto_command", auto_command)
|
|
1167
|
+
run_agentic = wrapped_functions.get("run_agentic", run_agentic)
|
|
451
1168
|
active_context = wrapped_functions.get("active_context", active_context)
|
|
452
1169
|
execute_shell_command = wrapped_functions.get(
|
|
453
1170
|
"execute_shell_command", execute_shell_command
|
|
454
1171
|
)
|
|
455
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
|
+
# 主交互循环
|
|
456
1219
|
while True:
|
|
1220
|
+
task_state = task_event.get_state()
|
|
457
1221
|
try:
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
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
|
+
]
|
|
466
1236
|
|
|
467
1237
|
if new_prompt:
|
|
468
|
-
user_input = session.
|
|
1238
|
+
user_input = await session.prompt_async(
|
|
469
1239
|
FormattedText(prompt_message), default=new_prompt, style=style
|
|
470
1240
|
)
|
|
1241
|
+
new_prompt = ""
|
|
471
1242
|
else:
|
|
472
|
-
user_input = session.
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
if "mode" not in memory:
|
|
476
|
-
memory["mode"] = "auto_detect"
|
|
477
|
-
|
|
478
|
-
# 处理 user_input 的空格
|
|
479
|
-
if user_input:
|
|
480
|
-
temp_user_input = user_input.lstrip() # 去掉左侧空格
|
|
481
|
-
if temp_user_input.startswith("/"):
|
|
482
|
-
user_input = temp_user_input
|
|
483
|
-
|
|
484
|
-
# Check if this is a plugin command
|
|
485
|
-
if user_input.startswith("/"):
|
|
486
|
-
plugin_result = plugin_manager.process_command(user_input)
|
|
487
|
-
if plugin_result:
|
|
488
|
-
plugin_name, handler, args = plugin_result
|
|
489
|
-
if handler:
|
|
490
|
-
handler(*args)
|
|
491
|
-
continue
|
|
492
|
-
if (
|
|
493
|
-
memory["mode"] == "auto_detect"
|
|
494
|
-
and user_input
|
|
495
|
-
and not user_input.startswith("/")
|
|
496
|
-
):
|
|
497
|
-
event_file, file_id = gengerate_event_file_path()
|
|
498
|
-
configure(f"event_file:{event_file}")
|
|
499
|
-
global_cancel.register_token(event_file)
|
|
500
|
-
auto_command(user_input)
|
|
501
|
-
|
|
502
|
-
elif memory["mode"] == "voice_input" and not user_input.startswith("/"):
|
|
503
|
-
text = voice_input()
|
|
504
|
-
if text: # Check if text is not None
|
|
505
|
-
new_prompt = "/coding " + text
|
|
506
|
-
|
|
507
|
-
elif user_input.startswith("/voice_input"):
|
|
508
|
-
text = voice_input()
|
|
509
|
-
if text: # Check if text is not None
|
|
510
|
-
new_prompt = "/coding " + text
|
|
511
|
-
|
|
512
|
-
elif user_input.startswith("/clear") or user_input.startswith("/cls"):
|
|
513
|
-
print("\033c")
|
|
514
|
-
|
|
515
|
-
elif user_input.startswith("/add_files"):
|
|
516
|
-
args = user_input[len("/add_files") :].strip().split()
|
|
517
|
-
add_files(args)
|
|
518
|
-
elif user_input.startswith("/remove_files"):
|
|
519
|
-
file_names = user_input[len("/remove_files") :].strip().split(",")
|
|
520
|
-
remove_files(file_names)
|
|
521
|
-
elif user_input.startswith("/index/query"):
|
|
522
|
-
query = user_input[len("/index/query") :].strip()
|
|
523
|
-
index_query(query)
|
|
524
|
-
|
|
525
|
-
elif user_input.startswith("/index/build"):
|
|
526
|
-
event_file, file_id = gengerate_event_file_path()
|
|
527
|
-
configure(f"event_file:{event_file}")
|
|
528
|
-
global_cancel.register_token(event_file)
|
|
529
|
-
index_build()
|
|
1243
|
+
user_input = await session.prompt_async(
|
|
1244
|
+
FormattedText(prompt_message), style=style
|
|
1245
|
+
)
|
|
530
1246
|
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
index_export(export_path)
|
|
1247
|
+
if user_input.strip() == "/exit":
|
|
1248
|
+
raise EOFError()
|
|
534
1249
|
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
1250
|
+
# 将输入放入队列,包含完成回调
|
|
1251
|
+
if user_input.strip():
|
|
1252
|
+
await input_queue.put((user_input, set_new_prompt, session))
|
|
1253
|
+
task_event.set_state("pending")
|
|
538
1254
|
|
|
539
|
-
|
|
540
|
-
|
|
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
|
|
541
1268
|
|
|
542
|
-
|
|
543
|
-
query = user_input[len("/models") :].strip()
|
|
544
|
-
handle_models_command(query, get_memory())
|
|
1269
|
+
traceback.print_exc()
|
|
545
1270
|
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
|
|
1271
|
+
exit_msg = get_i18n_message("exit_ctrl_d")
|
|
1272
|
+
print(f"\n\033[93m{exit_msg}\033[0m")
|
|
1273
|
+
|
|
1274
|
+
# 通知后台任务停止
|
|
1275
|
+
stop_ev.set()
|
|
1276
|
+
|
|
1277
|
+
# 取消消费者任务
|
|
1278
|
+
consumer_task.cancel()
|
|
1279
|
+
try:
|
|
1280
|
+
await consumer_task
|
|
1281
|
+
except asyncio.CancelledError:
|
|
1282
|
+
pass
|
|
1283
|
+
|
|
1284
|
+
# 取消后台任务
|
|
1285
|
+
background_task_coro.cancel()
|
|
1286
|
+
try:
|
|
1287
|
+
await background_task_coro
|
|
1288
|
+
except asyncio.CancelledError:
|
|
1289
|
+
pass
|
|
1290
|
+
|
|
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
|
+
)
|
|
582
1307
|
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
exclude_dirs(dir_names)
|
|
1308
|
+
goodbye_msg = get_i18n_message("goodbye")
|
|
1309
|
+
print(f"\n\033[93m{goodbye_msg}\033[0m")
|
|
586
1310
|
|
|
587
|
-
elif user_input.startswith("/exclude_files"):
|
|
588
|
-
query = user_input[len("/exclude_files") :].strip()
|
|
589
|
-
exclude_files(query)
|
|
590
1311
|
|
|
591
|
-
|
|
592
|
-
|
|
1312
|
+
def main():
|
|
1313
|
+
global ARGS
|
|
1314
|
+
load_tokenizer()
|
|
1315
|
+
ARGS = parse_arguments()
|
|
593
1316
|
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
configure(f"event_file:{event_file}")
|
|
597
|
-
global_cancel.register_token(event_file)
|
|
598
|
-
query = user_input[len("/coding") :].strip()
|
|
599
|
-
if not query:
|
|
600
|
-
print("\033[91mPlease enter your request.\033[0m")
|
|
601
|
-
continue
|
|
602
|
-
coding(query)
|
|
603
|
-
elif user_input.startswith("/chat"):
|
|
604
|
-
event_file, file_id = gengerate_event_file_path()
|
|
605
|
-
configure(f"event_file:{event_file}")
|
|
606
|
-
global_cancel.register_token(event_file)
|
|
607
|
-
query = user_input[len("/chat") :].strip()
|
|
608
|
-
if not query:
|
|
609
|
-
print("\033[91mPlease enter your request.\033[0m")
|
|
610
|
-
else:
|
|
611
|
-
chat(query)
|
|
1317
|
+
if ARGS.lite:
|
|
1318
|
+
ARGS.product_mode = "lite"
|
|
612
1319
|
|
|
613
|
-
|
|
614
|
-
|
|
615
|
-
if not query:
|
|
616
|
-
print("\033[91mPlease enter your design request.\033[0m")
|
|
617
|
-
else:
|
|
618
|
-
design(query)
|
|
1320
|
+
if ARGS.pro:
|
|
1321
|
+
ARGS.product_mode = "pro"
|
|
619
1322
|
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
|
|
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,
|
|
1332
|
+
)
|
|
1333
|
+
)
|
|
626
1334
|
|
|
627
|
-
|
|
628
|
-
args = user_input[len("/lib") :].strip().split()
|
|
629
|
-
lib_command(args)
|
|
1335
|
+
start_engine()
|
|
630
1336
|
|
|
631
|
-
|
|
632
|
-
|
|
633
|
-
|
|
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
|
+
)
|
|
634
1342
|
|
|
635
|
-
|
|
636
|
-
|
|
637
|
-
if not query:
|
|
638
|
-
print("Please enter your query.")
|
|
639
|
-
else:
|
|
640
|
-
mcp(query)
|
|
641
|
-
|
|
642
|
-
elif user_input.startswith("/active_context"):
|
|
643
|
-
query = user_input[len("/active_context") :].strip()
|
|
644
|
-
active_context(query)
|
|
645
|
-
|
|
646
|
-
elif user_input.startswith("/auto"):
|
|
647
|
-
query = user_input[len("/auto") :].strip()
|
|
648
|
-
auto_command(query)
|
|
649
|
-
elif user_input.startswith("/debug"):
|
|
650
|
-
code = user_input[len("/debug") :].strip()
|
|
651
|
-
try:
|
|
652
|
-
result = eval(code)
|
|
653
|
-
print(f"Debug result: {result}")
|
|
654
|
-
except Exception as e:
|
|
655
|
-
print(f"Debug error: {str(e)}")
|
|
1343
|
+
# 加载保存的运行时配置
|
|
1344
|
+
plugin_manager.load_runtime_cfg()
|
|
656
1345
|
|
|
657
|
-
|
|
658
|
-
|
|
659
|
-
command = user_input
|
|
660
|
-
if user_input.startswith("/shell"):
|
|
661
|
-
command = user_input[len("/shell") :].strip()
|
|
662
|
-
if not command:
|
|
663
|
-
print("Please enter a shell command to execute.")
|
|
664
|
-
else:
|
|
665
|
-
if command.startswith("/chat"):
|
|
666
|
-
event_file, file_id = gengerate_event_file_path()
|
|
667
|
-
global_cancel.register_token(event_file)
|
|
668
|
-
configure(f"event_file:{event_file}")
|
|
669
|
-
command = command[len("/chat") :].strip()
|
|
670
|
-
gen_and_exec_shell_command(command)
|
|
671
|
-
else:
|
|
672
|
-
execute_shell_command(command)
|
|
673
|
-
else:
|
|
674
|
-
if user_input and user_input.strip():
|
|
675
|
-
auto_command(user_input)
|
|
1346
|
+
# 自动加载内置插件
|
|
1347
|
+
load_builtin_plugins()
|
|
676
1348
|
|
|
677
|
-
|
|
678
|
-
continue
|
|
679
|
-
except EOFError:
|
|
680
|
-
try:
|
|
681
|
-
# Shutdown all plugins before exiting
|
|
682
|
-
plugin_manager.shutdown_all()
|
|
683
|
-
# save_memory()
|
|
684
|
-
try:
|
|
685
|
-
if get_mcp_server():
|
|
686
|
-
get_mcp_server().stop()
|
|
687
|
-
except Exception as e:
|
|
688
|
-
pass
|
|
689
|
-
stop_engine()
|
|
690
|
-
except Exception as e:
|
|
691
|
-
print(
|
|
692
|
-
f"\033[91mAn error occurred while saving memory:\033[0m \033[93m{type(e).__name__}\033[0m - {str(e)}"
|
|
693
|
-
)
|
|
694
|
-
print("\n\033[93mExiting Chat Auto Coder...\033[0m")
|
|
695
|
-
break
|
|
696
|
-
except Exception as e:
|
|
697
|
-
print(
|
|
698
|
-
f"\033[91mAn error occurred:\033[0m \033[93m{type(e).__name__}\033[0m - {str(e)}"
|
|
699
|
-
)
|
|
700
|
-
if ARGS and ARGS.debug:
|
|
701
|
-
import traceback
|
|
1349
|
+
configure(f"product_mode:{ARGS.product_mode}")
|
|
702
1350
|
|
|
703
|
-
|
|
1351
|
+
# 运行应用
|
|
1352
|
+
asyncio.run(run_app())
|
|
704
1353
|
|
|
705
1354
|
|
|
706
1355
|
if __name__ == "__main__":
|