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
|
@@ -0,0 +1,805 @@
|
|
|
1
|
+
# -*- coding: utf-8 -*-
|
|
2
|
+
"""
|
|
3
|
+
RuleSelector
|
|
4
|
+
|
|
5
|
+
基于 LLM 的智能规则选择器,支持规则摘要生成和索引创建。
|
|
6
|
+
"""
|
|
7
|
+
|
|
8
|
+
import os
|
|
9
|
+
import subprocess
|
|
10
|
+
import tempfile
|
|
11
|
+
import concurrent.futures
|
|
12
|
+
from typing import Dict, List, Optional, Union
|
|
13
|
+
from loguru import logger
|
|
14
|
+
|
|
15
|
+
# 导入第三方依赖
|
|
16
|
+
import byzerllm
|
|
17
|
+
from autocoder.common import AutoCoderArgs
|
|
18
|
+
|
|
19
|
+
# 导入数据模型
|
|
20
|
+
from ..models.rule_file import RuleFile
|
|
21
|
+
from ..models.rule_relevance import RuleRelevance
|
|
22
|
+
from ..models.summary import AlwaysApplyRuleSummary
|
|
23
|
+
from ..models.index import ConditionalRulesIndex
|
|
24
|
+
from ..models.init_rule import InitRule
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
class RuleSelector:
|
|
30
|
+
"""
|
|
31
|
+
根据LLM的判断和规则元数据选择适用的规则。
|
|
32
|
+
"""
|
|
33
|
+
def __init__(self, llm: Optional[Union[byzerllm.ByzerLLM, byzerllm.SimpleByzerLLM]], args: Optional[AutoCoderArgs] = None):
|
|
34
|
+
"""
|
|
35
|
+
初始化RuleSelector。
|
|
36
|
+
|
|
37
|
+
Args:
|
|
38
|
+
llm: ByzerLLM 实例,用于判断规则是否适用。如果为 None,则只选择 always_apply=True 的规则。
|
|
39
|
+
args: 传递给 Agent 的参数,可能包含用于规则选择的上下文信息。
|
|
40
|
+
"""
|
|
41
|
+
self.llm = llm
|
|
42
|
+
self.args = args
|
|
43
|
+
|
|
44
|
+
|
|
45
|
+
|
|
46
|
+
@byzerllm.prompt()
|
|
47
|
+
def _build_selection_prompt(self, rule: RuleFile, context: str = "") -> str:
|
|
48
|
+
"""
|
|
49
|
+
判断规则是否适用于当前任务。
|
|
50
|
+
|
|
51
|
+
规则描述:
|
|
52
|
+
{{ rule.description }}
|
|
53
|
+
|
|
54
|
+
规则内容摘要 (前200字符):
|
|
55
|
+
{{ rule.content[:200] }}
|
|
56
|
+
|
|
57
|
+
{% if context %}
|
|
58
|
+
任务上下文:
|
|
59
|
+
{{ context }}
|
|
60
|
+
{% endif %}
|
|
61
|
+
|
|
62
|
+
基于以上信息,判断这条规则 (路径: {{ rule.file_path }}) 是否与当前任务相关并应该被应用?
|
|
63
|
+
|
|
64
|
+
请以JSON格式返回结果:
|
|
65
|
+
```json
|
|
66
|
+
{
|
|
67
|
+
"is_relevant": true或false,
|
|
68
|
+
"reason": "判断理由"
|
|
69
|
+
}
|
|
70
|
+
```
|
|
71
|
+
"""
|
|
72
|
+
# 注意:确保 rule 对象和 context 字典能够被 Jinja2 正确访问。
|
|
73
|
+
# Pydantic模型可以直接在Jinja2中使用其属性。
|
|
74
|
+
return {
|
|
75
|
+
"rule": rule,
|
|
76
|
+
"context": context
|
|
77
|
+
} # type: ignore
|
|
78
|
+
|
|
79
|
+
def _evaluate_rule(self, rule: RuleFile, context: str) -> tuple[RuleFile, bool, Optional[str]]:
|
|
80
|
+
"""
|
|
81
|
+
评估单个规则是否适用于当前上下文。
|
|
82
|
+
|
|
83
|
+
Args:
|
|
84
|
+
rule: 要评估的规则
|
|
85
|
+
context: 上下文信息
|
|
86
|
+
|
|
87
|
+
Returns:
|
|
88
|
+
tuple: (规则, 是否选中, 理由)
|
|
89
|
+
"""
|
|
90
|
+
# 如果规则设置为总是应用,直接返回选中
|
|
91
|
+
if rule.always_apply:
|
|
92
|
+
return (rule, True, "规则设置为总是应用")
|
|
93
|
+
|
|
94
|
+
# 如果没有LLM,无法评估non-always规则
|
|
95
|
+
if self.llm is None:
|
|
96
|
+
return (rule, False, "未提供LLM,无法评估non-always规则")
|
|
97
|
+
|
|
98
|
+
try:
|
|
99
|
+
prompt = self._build_selection_prompt.prompt(rule=rule, context=context)
|
|
100
|
+
logger.debug(f"为规则 '{os.path.basename(rule.file_path)}' 生成的判断 Prompt (片段): {prompt[:200]}...")
|
|
101
|
+
|
|
102
|
+
result = None
|
|
103
|
+
try:
|
|
104
|
+
# 使用with_return_type方法获取结构化结果
|
|
105
|
+
result = self._build_selection_prompt.with_llm(self.llm).with_return_type(RuleRelevance).run(rule=rule, context=context)
|
|
106
|
+
if result and result.is_relevant:
|
|
107
|
+
return (rule, True, result.reason)
|
|
108
|
+
else:
|
|
109
|
+
return (rule, False, result.reason if result else "未提供理由")
|
|
110
|
+
except Exception as e:
|
|
111
|
+
logger.warning(f"LLM 未能为规则 '{os.path.basename(rule.file_path)}' 提供有效响应: {e}")
|
|
112
|
+
return (rule, False, f"LLM评估出错: {str(e)}")
|
|
113
|
+
|
|
114
|
+
except Exception as e:
|
|
115
|
+
logger.error(f"评估规则 '{os.path.basename(rule.file_path)}' 时出错: {e}", exc_info=True)
|
|
116
|
+
return (rule, False, f"评估过程出错: {str(e)}")
|
|
117
|
+
|
|
118
|
+
def select_rules(self, context: str) -> List[RuleFile]:
|
|
119
|
+
"""
|
|
120
|
+
选择适用于当前上下文的规则。使用线程池并发评估规则。
|
|
121
|
+
|
|
122
|
+
Args:
|
|
123
|
+
context: 包含用于规则选择的上下文信息 (例如,用户指令、目标文件等)。
|
|
124
|
+
|
|
125
|
+
Returns:
|
|
126
|
+
List[RuleFile]: 选定的规则列表。
|
|
127
|
+
"""
|
|
128
|
+
# 导入函数以避免循环依赖
|
|
129
|
+
from ..api import get_parsed_rules
|
|
130
|
+
|
|
131
|
+
rules = get_parsed_rules()
|
|
132
|
+
selected_rules: List[RuleFile] = []
|
|
133
|
+
logger.info(f"开始选择规则,总规则数: {len(rules)}")
|
|
134
|
+
|
|
135
|
+
# 预先分类处理always_apply规则
|
|
136
|
+
always_apply_rules = []
|
|
137
|
+
need_llm_rules = []
|
|
138
|
+
|
|
139
|
+
for rule in rules:
|
|
140
|
+
if rule.always_apply:
|
|
141
|
+
always_apply_rules.append(rule)
|
|
142
|
+
elif self.llm is not None:
|
|
143
|
+
need_llm_rules.append(rule)
|
|
144
|
+
|
|
145
|
+
# 添加always_apply规则
|
|
146
|
+
for rule in always_apply_rules:
|
|
147
|
+
selected_rules.append(rule)
|
|
148
|
+
logger.debug(f"规则 '{os.path.basename(rule.file_path)}' (AlwaysApply=True) 已自动选择。")
|
|
149
|
+
|
|
150
|
+
# 如果没有需要LLM评估的规则,直接返回结果
|
|
151
|
+
if not need_llm_rules:
|
|
152
|
+
logger.info(f"规则选择完成,选中规则数: {len(selected_rules)}")
|
|
153
|
+
return selected_rules
|
|
154
|
+
|
|
155
|
+
# 使用线程池并发评估规则
|
|
156
|
+
with concurrent.futures.ThreadPoolExecutor() as executor:
|
|
157
|
+
# 提交所有评估任务
|
|
158
|
+
future_to_rule = {
|
|
159
|
+
executor.submit(self._evaluate_rule, rule, context): rule
|
|
160
|
+
for rule in need_llm_rules
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
# 收集评估结果
|
|
164
|
+
for future in concurrent.futures.as_completed(future_to_rule):
|
|
165
|
+
rule, is_selected, reason = future.result()
|
|
166
|
+
if is_selected:
|
|
167
|
+
selected_rules.append(rule)
|
|
168
|
+
logger.info(f"规则 '{os.path.basename(rule.file_path)}' (AlwaysApply=False) 已被 LLM 选择,原因: {reason}")
|
|
169
|
+
else:
|
|
170
|
+
logger.debug(f"规则 '{os.path.basename(rule.file_path)}' (AlwaysApply=False) 未被 LLM 选择,原因: {reason}")
|
|
171
|
+
|
|
172
|
+
logger.info(f"规则选择完成,选中规则数: {len(selected_rules)}")
|
|
173
|
+
return selected_rules
|
|
174
|
+
|
|
175
|
+
def get_selected_rules_content(self, context: str) -> Dict[str, str]:
|
|
176
|
+
"""
|
|
177
|
+
获取选定规则的文件路径和内容字典。
|
|
178
|
+
|
|
179
|
+
Args:
|
|
180
|
+
context: 传递给 select_rules 的上下文。
|
|
181
|
+
|
|
182
|
+
Returns:
|
|
183
|
+
Dict[str, str]: 选定规则的 {file_path: content} 字典。
|
|
184
|
+
"""
|
|
185
|
+
selected_rules = self.select_rules(context=context)
|
|
186
|
+
# 使用 os.path.basename 获取文件名作为 key,如果需要的话
|
|
187
|
+
# return {os.path.basename(rule.file_path): rule.content for rule in selected_rules}
|
|
188
|
+
# 保持 file_path 作为 key
|
|
189
|
+
return {rule.file_path: rule.content for rule in selected_rules}
|
|
190
|
+
|
|
191
|
+
@byzerllm.prompt()
|
|
192
|
+
def _build_always_apply_summary_prompt(self, rules: List[RuleFile]) -> str:
|
|
193
|
+
"""
|
|
194
|
+
Merge all always-apply rules into a unified rule description.
|
|
195
|
+
|
|
196
|
+
Below is the list of all always-apply rules ({{ rules|length }} rules in total):
|
|
197
|
+
|
|
198
|
+
{% for rule in rules %}
|
|
199
|
+
## Rule {{ loop.index }}: {{ rule.file_path }}
|
|
200
|
+
{% if rule.description %}
|
|
201
|
+
**Description**: {{ rule.description }}
|
|
202
|
+
{% endif %}
|
|
203
|
+
{% if rule.globs %}
|
|
204
|
+
**Applicable Files**: {{ rule.globs|join(', ') }}
|
|
205
|
+
{% endif %}
|
|
206
|
+
|
|
207
|
+
**Content**:
|
|
208
|
+
{{ rule.content }}
|
|
209
|
+
|
|
210
|
+
---
|
|
211
|
+
{% endfor %}
|
|
212
|
+
|
|
213
|
+
Please merge all the above rules into a unified and concise rule description. Requirements:
|
|
214
|
+
1. Keep all important rule points
|
|
215
|
+
2. Remove duplicate content while preserving complementary information
|
|
216
|
+
3. Organize content by logical grouping
|
|
217
|
+
4. Generate a unified rule document that is easy to understand and follow
|
|
218
|
+
|
|
219
|
+
***Do not include any extraneous content, please start outputting the rule content directly.***
|
|
220
|
+
```
|
|
221
|
+
"""
|
|
222
|
+
return {"rules": rules} # type: ignore
|
|
223
|
+
|
|
224
|
+
@byzerllm.prompt()
|
|
225
|
+
def _build_conditional_rules_index_prompt(self, rules: List[RuleFile]) -> str:
|
|
226
|
+
"""
|
|
227
|
+
Generate an index directory for all conditional rules.
|
|
228
|
+
|
|
229
|
+
Below is the list of all conditional rules ({{ rules|length }} rules in total):
|
|
230
|
+
|
|
231
|
+
{% for rule in rules %}
|
|
232
|
+
## Rule {{ loop.index }}: {{ rule.file_path }}
|
|
233
|
+
{% if rule.description %}
|
|
234
|
+
**Description**: {{ rule.description }}
|
|
235
|
+
{% endif %}
|
|
236
|
+
{% if rule.globs %}
|
|
237
|
+
**Applicable Files**: {{ rule.globs|join(', ') }}
|
|
238
|
+
{% endif %}
|
|
239
|
+
|
|
240
|
+
**Content**:
|
|
241
|
+
{{ rule.content }}
|
|
242
|
+
|
|
243
|
+
---
|
|
244
|
+
{% endfor %}
|
|
245
|
+
|
|
246
|
+
Please generate a detailed index directory for all the above conditional rules. Requirements:
|
|
247
|
+
1. Provide concise descriptions and usage explanations for each rule to help users understand the purpose of the rules
|
|
248
|
+
2. Explain when these rules should be selected and used
|
|
249
|
+
3. Generate an easy-to-navigate and searchable directory structure that must include file paths
|
|
250
|
+
|
|
251
|
+
***Do not include any extraneous content, please start outputting the rule content directly.***
|
|
252
|
+
"""
|
|
253
|
+
return {"rules": rules} # type: ignore
|
|
254
|
+
|
|
255
|
+
def generate_always_apply_summary(self) -> Optional[AlwaysApplyRuleSummary]:
|
|
256
|
+
"""
|
|
257
|
+
生成所有必须应用规则的合并摘要。
|
|
258
|
+
|
|
259
|
+
Returns:
|
|
260
|
+
AlwaysApplyRuleSummary: 合并后的规则摘要,如果没有 LLM 则返回 None
|
|
261
|
+
"""
|
|
262
|
+
if self.llm is None:
|
|
263
|
+
logger.warning("未提供 LLM,无法生成必须应用规则摘要")
|
|
264
|
+
return None
|
|
265
|
+
|
|
266
|
+
# 导入函数以避免循环依赖
|
|
267
|
+
from ..api import get_parsed_rules
|
|
268
|
+
|
|
269
|
+
# 获取所有解析后的规则
|
|
270
|
+
all_rules = get_parsed_rules()
|
|
271
|
+
always_apply_rules = [rule for rule in all_rules if rule.always_apply]
|
|
272
|
+
|
|
273
|
+
if not always_apply_rules:
|
|
274
|
+
logger.info("未找到必须应用的规则")
|
|
275
|
+
return AlwaysApplyRuleSummary(
|
|
276
|
+
summary="未找到必须应用的规则。",
|
|
277
|
+
rule_count=0,
|
|
278
|
+
covered_areas=[]
|
|
279
|
+
)
|
|
280
|
+
|
|
281
|
+
|
|
282
|
+
|
|
283
|
+
logger.info(f"开始生成必须应用规则摘要,规则数量: {len(always_apply_rules)}")
|
|
284
|
+
|
|
285
|
+
try:
|
|
286
|
+
# 由于 prompt 现在不返回 JSON,我们需要直接获取字符串结果
|
|
287
|
+
result_str = self._build_always_apply_summary_prompt.with_llm(self.llm).run(rules=always_apply_rules)
|
|
288
|
+
if result_str:
|
|
289
|
+
# 创建摘要对象
|
|
290
|
+
result = AlwaysApplyRuleSummary(
|
|
291
|
+
summary=result_str,
|
|
292
|
+
rule_count=len(always_apply_rules),
|
|
293
|
+
covered_areas=[] # 暂时为空,可以后续通过 LLM 分析生成
|
|
294
|
+
)
|
|
295
|
+
|
|
296
|
+
|
|
297
|
+
|
|
298
|
+
logger.info(f"成功生成必须应用规则摘要")
|
|
299
|
+
return result
|
|
300
|
+
else:
|
|
301
|
+
logger.warning("LLM 未能生成有效的规则摘要")
|
|
302
|
+
return None
|
|
303
|
+
except Exception as e:
|
|
304
|
+
logger.error(f"生成必须应用规则摘要时出错: {e}", exc_info=True)
|
|
305
|
+
return None
|
|
306
|
+
|
|
307
|
+
def generate_conditional_rules_index(self) -> Optional[ConditionalRulesIndex]:
|
|
308
|
+
"""
|
|
309
|
+
生成所有条件规则的索引目录。
|
|
310
|
+
|
|
311
|
+
Returns:
|
|
312
|
+
ConditionalRulesIndex: 条件规则索引,如果没有 LLM 则返回 None
|
|
313
|
+
"""
|
|
314
|
+
if self.llm is None:
|
|
315
|
+
logger.warning("未提供 LLM,无法生成条件规则索引")
|
|
316
|
+
return None
|
|
317
|
+
|
|
318
|
+
# 导入函数以避免循环依赖
|
|
319
|
+
from ..api import get_parsed_rules
|
|
320
|
+
|
|
321
|
+
# 获取所有解析后的规则
|
|
322
|
+
all_rules = get_parsed_rules()
|
|
323
|
+
conditional_rules = [rule for rule in all_rules if not rule.always_apply]
|
|
324
|
+
|
|
325
|
+
if not conditional_rules:
|
|
326
|
+
logger.info("未找到条件规则")
|
|
327
|
+
return ConditionalRulesIndex(
|
|
328
|
+
index_content="未找到条件规则。",
|
|
329
|
+
rule_count=0,
|
|
330
|
+
categories=[]
|
|
331
|
+
)
|
|
332
|
+
|
|
333
|
+
|
|
334
|
+
|
|
335
|
+
logger.info(f"开始生成条件规则索引,规则数量: {len(conditional_rules)}")
|
|
336
|
+
|
|
337
|
+
try:
|
|
338
|
+
# 由于 prompt 现在不返回 JSON,我们需要直接获取字符串结果
|
|
339
|
+
result_str = self._build_conditional_rules_index_prompt.with_llm(self.llm).run(rules=conditional_rules)
|
|
340
|
+
if result_str:
|
|
341
|
+
# 创建索引对象
|
|
342
|
+
result = ConditionalRulesIndex(
|
|
343
|
+
index_content=result_str,
|
|
344
|
+
rule_count=len(conditional_rules),
|
|
345
|
+
categories=[] # 暂时为空,可以后续通过 LLM 分析生成
|
|
346
|
+
)
|
|
347
|
+
|
|
348
|
+
|
|
349
|
+
|
|
350
|
+
logger.info(f"成功生成条件规则索引")
|
|
351
|
+
return result
|
|
352
|
+
else:
|
|
353
|
+
logger.warning("LLM 未能生成有效的规则索引")
|
|
354
|
+
return None
|
|
355
|
+
except Exception as e:
|
|
356
|
+
logger.error(f"生成条件规则索引时出错: {e}", exc_info=True)
|
|
357
|
+
return None
|
|
358
|
+
|
|
359
|
+
|
|
360
|
+
|
|
361
|
+
def generate_init_rule(self, project_root: Optional[str] = None) -> Optional[InitRule]:
|
|
362
|
+
"""
|
|
363
|
+
使用 subagent 机制探索项目结构并生成初始化规则。
|
|
364
|
+
|
|
365
|
+
Args:
|
|
366
|
+
project_root: 项目根目录路径,如果为 None 则使用当前目录
|
|
367
|
+
|
|
368
|
+
Returns:
|
|
369
|
+
InitRule: 生成的初始化规则,如果失败则返回 None
|
|
370
|
+
"""
|
|
371
|
+
if project_root is None:
|
|
372
|
+
project_root = os.getcwd()
|
|
373
|
+
|
|
374
|
+
logger.info(f"使用 subagent 机制开始生成初始化规则: {project_root}")
|
|
375
|
+
|
|
376
|
+
try:
|
|
377
|
+
# 探索项目结构
|
|
378
|
+
project_info = self._explore_project_structure(project_root)
|
|
379
|
+
logger.info(f"项目探索完成,检测到技术栈: {project_info['technologies']}")
|
|
380
|
+
|
|
381
|
+
# 获取模型名称
|
|
382
|
+
model_name = self._get_model_name()
|
|
383
|
+
if not model_name:
|
|
384
|
+
logger.error("无法获取模型名称,无法使用 subagent 机制")
|
|
385
|
+
return None
|
|
386
|
+
|
|
387
|
+
# 使用 subagent 机制生成规则
|
|
388
|
+
success = self._generate_init_rule_with_subagent(project_info, model_name, project_root)
|
|
389
|
+
|
|
390
|
+
if not success:
|
|
391
|
+
logger.error("subagent 执行失败")
|
|
392
|
+
return None
|
|
393
|
+
|
|
394
|
+
# 检查生成的文件并读取内容
|
|
395
|
+
rules_dir = self._find_rules_directory(project_root)
|
|
396
|
+
if not rules_dir:
|
|
397
|
+
logger.error("未找到 .autocoderrules 目录")
|
|
398
|
+
return None
|
|
399
|
+
|
|
400
|
+
init_file_path = os.path.join(rules_dir, "init.md")
|
|
401
|
+
if not os.path.exists(init_file_path):
|
|
402
|
+
logger.error(f"未找到生成的 init.md 文件: {init_file_path}")
|
|
403
|
+
return None
|
|
404
|
+
|
|
405
|
+
# 读取生成的内容
|
|
406
|
+
with open(init_file_path, 'r', encoding='utf-8') as f:
|
|
407
|
+
content = f.read()
|
|
408
|
+
|
|
409
|
+
if not content.strip():
|
|
410
|
+
logger.error("生成的 init.md 文件为空")
|
|
411
|
+
return None
|
|
412
|
+
|
|
413
|
+
# 确定项目类型
|
|
414
|
+
project_type = self._determine_project_type(project_info['technologies'])
|
|
415
|
+
|
|
416
|
+
# 提取命令列表
|
|
417
|
+
commands = self._extract_commands_from_content(content)
|
|
418
|
+
|
|
419
|
+
# 创建 InitRule 对象
|
|
420
|
+
result = InitRule(
|
|
421
|
+
content=content,
|
|
422
|
+
project_type=project_type,
|
|
423
|
+
commands=commands,
|
|
424
|
+
technologies=project_info['technologies'],
|
|
425
|
+
file_path=init_file_path
|
|
426
|
+
)
|
|
427
|
+
|
|
428
|
+
logger.info(f"成功使用 subagent 生成初始化规则,项目类型: {project_type}")
|
|
429
|
+
return result
|
|
430
|
+
|
|
431
|
+
except Exception as e:
|
|
432
|
+
logger.error(f"使用 subagent 生成初始化规则时出错: {e}", exc_info=True)
|
|
433
|
+
return None
|
|
434
|
+
|
|
435
|
+
def _explore_project_structure(self, project_root: str) -> Dict:
|
|
436
|
+
"""探索项目结构,检测技术栈和配置文件"""
|
|
437
|
+
project_info = {
|
|
438
|
+
'root_files': [],
|
|
439
|
+
'main_directories': [],
|
|
440
|
+
'technologies': [],
|
|
441
|
+
'package_json': None,
|
|
442
|
+
'setup_py': None,
|
|
443
|
+
'requirements_txt': None,
|
|
444
|
+
'go_mod': None,
|
|
445
|
+
'pyproject_toml': None,
|
|
446
|
+
'tsconfig_json': None,
|
|
447
|
+
}
|
|
448
|
+
|
|
449
|
+
try:
|
|
450
|
+
# 获取根目录文件
|
|
451
|
+
if os.path.exists(project_root):
|
|
452
|
+
root_items = os.listdir(project_root)
|
|
453
|
+
|
|
454
|
+
# 分离文件和目录
|
|
455
|
+
for item in root_items:
|
|
456
|
+
item_path = os.path.join(project_root, item)
|
|
457
|
+
if os.path.isfile(item_path):
|
|
458
|
+
project_info['root_files'].append(item)
|
|
459
|
+
elif os.path.isdir(item_path) and not item.startswith('.'):
|
|
460
|
+
project_info['main_directories'].append(item)
|
|
461
|
+
|
|
462
|
+
# 检测配置文件并读取内容
|
|
463
|
+
config_files = {
|
|
464
|
+
'package.json': 'package_json',
|
|
465
|
+
'setup.py': 'setup_py',
|
|
466
|
+
'requirements.txt': 'requirements_txt',
|
|
467
|
+
'go.mod': 'go_mod',
|
|
468
|
+
'pyproject.toml': 'pyproject_toml',
|
|
469
|
+
'tsconfig.json': 'tsconfig_json',
|
|
470
|
+
}
|
|
471
|
+
|
|
472
|
+
for filename, key in config_files.items():
|
|
473
|
+
file_path = os.path.join(project_root, filename)
|
|
474
|
+
if os.path.exists(file_path):
|
|
475
|
+
try:
|
|
476
|
+
with open(file_path, 'r', encoding='utf-8') as f:
|
|
477
|
+
content = f.read()
|
|
478
|
+
project_info[key] = content[:1000] # 限制内容长度
|
|
479
|
+
except Exception as e:
|
|
480
|
+
logger.warning(f"读取 {filename} 时出错: {e}")
|
|
481
|
+
|
|
482
|
+
# 检测技术栈
|
|
483
|
+
project_info['technologies'] = self._detect_technologies(project_info)
|
|
484
|
+
|
|
485
|
+
except Exception as e:
|
|
486
|
+
logger.error(f"探索项目结构时出错: {e}")
|
|
487
|
+
|
|
488
|
+
return project_info
|
|
489
|
+
|
|
490
|
+
def _detect_technologies(self, project_info: Dict) -> List[str]:
|
|
491
|
+
"""根据配置文件检测技术栈"""
|
|
492
|
+
technologies = []
|
|
493
|
+
|
|
494
|
+
# Python
|
|
495
|
+
if project_info['setup_py'] or project_info['requirements_txt'] or project_info['pyproject_toml']:
|
|
496
|
+
technologies.append('Python')
|
|
497
|
+
|
|
498
|
+
# JavaScript/TypeScript
|
|
499
|
+
if project_info['package_json']:
|
|
500
|
+
technologies.append('JavaScript')
|
|
501
|
+
try:
|
|
502
|
+
import json
|
|
503
|
+
package_data = json.loads(project_info['package_json'])
|
|
504
|
+
dependencies = {
|
|
505
|
+
**package_data.get('dependencies', {}),
|
|
506
|
+
**package_data.get('devDependencies', {})
|
|
507
|
+
}
|
|
508
|
+
|
|
509
|
+
if 'typescript' in dependencies or project_info['tsconfig_json']:
|
|
510
|
+
technologies.append('TypeScript')
|
|
511
|
+
|
|
512
|
+
if 'react' in dependencies:
|
|
513
|
+
technologies.append('React')
|
|
514
|
+
|
|
515
|
+
if 'vue' in dependencies:
|
|
516
|
+
technologies.append('Vue')
|
|
517
|
+
|
|
518
|
+
if 'express' in dependencies:
|
|
519
|
+
technologies.append('Node.js')
|
|
520
|
+
|
|
521
|
+
except Exception as e:
|
|
522
|
+
logger.warning(f"解析 package.json 时出错: {e}")
|
|
523
|
+
|
|
524
|
+
# Go
|
|
525
|
+
if project_info['go_mod']:
|
|
526
|
+
technologies.append('Go')
|
|
527
|
+
|
|
528
|
+
# 其他检测
|
|
529
|
+
if 'src' in project_info['main_directories']:
|
|
530
|
+
if not technologies: # 如果还没检测到技术栈,根据目录结构猜测
|
|
531
|
+
technologies.append('General')
|
|
532
|
+
|
|
533
|
+
return technologies if technologies else ['Unknown']
|
|
534
|
+
|
|
535
|
+
def _determine_project_type(self, technologies: List[str]) -> str:
|
|
536
|
+
"""根据技术栈确定项目类型"""
|
|
537
|
+
if 'React' in technologies:
|
|
538
|
+
return 'React Application'
|
|
539
|
+
elif 'Vue' in technologies:
|
|
540
|
+
return 'Vue Application'
|
|
541
|
+
elif 'TypeScript' in technologies:
|
|
542
|
+
return 'TypeScript Project'
|
|
543
|
+
elif 'JavaScript' in technologies:
|
|
544
|
+
return 'JavaScript Project'
|
|
545
|
+
elif 'Python' in technologies:
|
|
546
|
+
return 'Python Project'
|
|
547
|
+
elif 'Go' in technologies:
|
|
548
|
+
return 'Go Project'
|
|
549
|
+
else:
|
|
550
|
+
return 'General Project'
|
|
551
|
+
|
|
552
|
+
def _extract_commands_from_content(self, content: str) -> List[str]:
|
|
553
|
+
"""从生成的内容中提取命令列表"""
|
|
554
|
+
commands = []
|
|
555
|
+
lines = content.split('\n')
|
|
556
|
+
in_commands_section = False
|
|
557
|
+
|
|
558
|
+
for line in lines:
|
|
559
|
+
line = line.strip()
|
|
560
|
+
if line.lower().startswith('# bash commands'):
|
|
561
|
+
in_commands_section = True
|
|
562
|
+
continue
|
|
563
|
+
elif line.startswith('#') and in_commands_section:
|
|
564
|
+
in_commands_section = False
|
|
565
|
+
elif in_commands_section and line.startswith('-'):
|
|
566
|
+
# 提取命令名称
|
|
567
|
+
command_part = line[1:].strip()
|
|
568
|
+
if ':' in command_part:
|
|
569
|
+
command_name = command_part.split(':')[0].strip()
|
|
570
|
+
commands.append(command_name)
|
|
571
|
+
|
|
572
|
+
return commands
|
|
573
|
+
|
|
574
|
+
def _get_model_name(self) -> Optional[str]:
|
|
575
|
+
"""
|
|
576
|
+
获取当前可用的模型名称
|
|
577
|
+
|
|
578
|
+
Returns:
|
|
579
|
+
当前模型名称,如果没有则返回 None
|
|
580
|
+
"""
|
|
581
|
+
try:
|
|
582
|
+
# 尝试从 args 中获取模型信息
|
|
583
|
+
if self.args and hasattr(self.args, 'model') and self.args.model:
|
|
584
|
+
return self.args.model
|
|
585
|
+
|
|
586
|
+
# 尝试从 llm 实例获取模型名称
|
|
587
|
+
if self.llm:
|
|
588
|
+
if hasattr(self.llm, 'default_model_name') and self.llm.default_model_name:
|
|
589
|
+
return self.llm.default_model_name
|
|
590
|
+
elif hasattr(self.llm, 'model_name') and self.llm.model_name:
|
|
591
|
+
return self.llm.model_name
|
|
592
|
+
elif hasattr(self.llm, 'model') and self.llm.model:
|
|
593
|
+
return self.llm.model
|
|
594
|
+
|
|
595
|
+
# 尝试从环境变量获取
|
|
596
|
+
env_model = os.getenv('AUTO_CODER_MODEL')
|
|
597
|
+
if env_model:
|
|
598
|
+
return env_model
|
|
599
|
+
|
|
600
|
+
# 默认模型
|
|
601
|
+
return "v3_chat"
|
|
602
|
+
|
|
603
|
+
except Exception as e:
|
|
604
|
+
logger.warning(f"获取模型名称时出错: {str(e)}")
|
|
605
|
+
return "v3_chat"
|
|
606
|
+
|
|
607
|
+
def _generate_init_rule_with_subagent(self, project_info: Dict, model_name: str, project_root: str) -> bool:
|
|
608
|
+
"""
|
|
609
|
+
使用 subagent 机制生成初始化规则
|
|
610
|
+
|
|
611
|
+
Args:
|
|
612
|
+
project_info: 项目信息
|
|
613
|
+
model_name: 模型名称
|
|
614
|
+
project_root: 项目根目录
|
|
615
|
+
|
|
616
|
+
Returns:
|
|
617
|
+
是否成功
|
|
618
|
+
"""
|
|
619
|
+
try:
|
|
620
|
+
# 创建临时文件
|
|
621
|
+
with tempfile.NamedTemporaryFile(mode='w', suffix='.md', delete=False, encoding='utf-8') as temp_file:
|
|
622
|
+
temp_file_path = temp_file.name
|
|
623
|
+
|
|
624
|
+
# 构建指令内容
|
|
625
|
+
instruction_content = self._build_subagent_instruction(project_info, project_root)
|
|
626
|
+
temp_file.write(instruction_content)
|
|
627
|
+
|
|
628
|
+
logger.info(f"创建临时指令文件: {temp_file_path}")
|
|
629
|
+
|
|
630
|
+
try:
|
|
631
|
+
# 切换到项目根目录执行命令
|
|
632
|
+
original_cwd = os.getcwd()
|
|
633
|
+
os.chdir(project_root)
|
|
634
|
+
|
|
635
|
+
# 构建并执行 auto-coder.run 命令
|
|
636
|
+
command = f"cat {temp_file_path} | auto-coder.run --model {model_name}"
|
|
637
|
+
logger.info(f"执行 subagent 命令: {command}")
|
|
638
|
+
|
|
639
|
+
# 执行命令
|
|
640
|
+
result = subprocess.run(
|
|
641
|
+
command,
|
|
642
|
+
shell=True,
|
|
643
|
+
capture_output=True,
|
|
644
|
+
text=True,
|
|
645
|
+
timeout=300 # 5分钟超时
|
|
646
|
+
)
|
|
647
|
+
|
|
648
|
+
if result.returncode == 0:
|
|
649
|
+
logger.info("subagent 命令执行成功")
|
|
650
|
+
if result.stdout:
|
|
651
|
+
logger.info(f"命令输出: {result.stdout}")
|
|
652
|
+
return True
|
|
653
|
+
else:
|
|
654
|
+
logger.error(f"subagent 命令执行失败,返回码: {result.returncode}")
|
|
655
|
+
if result.stderr:
|
|
656
|
+
logger.error(f"错误输出: {result.stderr}")
|
|
657
|
+
if result.stdout:
|
|
658
|
+
logger.error(f"标准输出: {result.stdout}")
|
|
659
|
+
return False
|
|
660
|
+
|
|
661
|
+
finally:
|
|
662
|
+
# 恢复原始工作目录
|
|
663
|
+
os.chdir(original_cwd)
|
|
664
|
+
|
|
665
|
+
# 清理临时文件
|
|
666
|
+
try:
|
|
667
|
+
os.unlink(temp_file_path)
|
|
668
|
+
logger.info(f"已清理临时文件: {temp_file_path}")
|
|
669
|
+
except Exception as e:
|
|
670
|
+
logger.warning(f"清理临时文件时出错: {e}")
|
|
671
|
+
|
|
672
|
+
except subprocess.TimeoutExpired:
|
|
673
|
+
logger.error("subagent 命令执行超时")
|
|
674
|
+
return False
|
|
675
|
+
except Exception as e:
|
|
676
|
+
logger.error(f"执行 subagent 命令时出错: {e}", exc_info=True)
|
|
677
|
+
return False
|
|
678
|
+
|
|
679
|
+
def _build_subagent_instruction(self, project_info: Dict, project_root: str) -> str:
|
|
680
|
+
"""
|
|
681
|
+
构建 subagent 的指令内容
|
|
682
|
+
|
|
683
|
+
Args:
|
|
684
|
+
project_info: 项目信息
|
|
685
|
+
project_root: 项目根目录
|
|
686
|
+
|
|
687
|
+
Returns:
|
|
688
|
+
指令内容
|
|
689
|
+
"""
|
|
690
|
+
# 构建项目信息描述
|
|
691
|
+
project_description = ""
|
|
692
|
+
|
|
693
|
+
if project_info.get('package_json'):
|
|
694
|
+
project_description += f"\n**发现 package.json 文件**:\n```json\n{project_info['package_json'][:500]}...\n```\n"
|
|
695
|
+
|
|
696
|
+
if project_info.get('setup_py'):
|
|
697
|
+
project_description += f"\n**发现 setup.py 文件**:\n```python\n{project_info['setup_py'][:500]}...\n```\n"
|
|
698
|
+
|
|
699
|
+
if project_info.get('requirements_txt'):
|
|
700
|
+
project_description += f"\n**发现 requirements.txt 文件**:\n```\n{project_info['requirements_txt'][:300]}...\n```\n"
|
|
701
|
+
|
|
702
|
+
if project_info.get('go_mod'):
|
|
703
|
+
project_description += f"\n**发现 go.mod 文件**:\n```\n{project_info['go_mod'][:300]}...\n```\n"
|
|
704
|
+
|
|
705
|
+
if project_info.get('pyproject_toml'):
|
|
706
|
+
project_description += f"\n**发现 pyproject.toml 文件**:\n```toml\n{project_info['pyproject_toml'][:500]}...\n```\n"
|
|
707
|
+
|
|
708
|
+
if project_info.get('tsconfig_json'):
|
|
709
|
+
project_description += f"\n**发现 tsconfig.json 文件**:\n```json\n{project_info['tsconfig_json'][:300]}...\n```\n"
|
|
710
|
+
|
|
711
|
+
root_files = ', '.join(project_info.get('root_files', [])[:10])
|
|
712
|
+
main_directories = ', '.join(project_info.get('main_directories', [])[:10])
|
|
713
|
+
technologies = ', '.join(project_info.get('technologies', []))
|
|
714
|
+
|
|
715
|
+
instruction = f"""请分析当前项目结构并在 .autocoderrules 目录下生成一个 init.md 文件,包含项目的开发规则和指导。
|
|
716
|
+
|
|
717
|
+
## 项目信息
|
|
718
|
+
|
|
719
|
+
**项目根目录**: {project_root}
|
|
720
|
+
**根目录文件**: {root_files}
|
|
721
|
+
**主要目录**: {main_directories}
|
|
722
|
+
**检测到的技术栈**: {technologies}
|
|
723
|
+
|
|
724
|
+
{project_description}
|
|
725
|
+
|
|
726
|
+
## 任务要求
|
|
727
|
+
|
|
728
|
+
请根据上述项目信息,在 `.autocoderrules` 目录下创建一个 `init.md` 文件,内容应该包括:
|
|
729
|
+
|
|
730
|
+
### 1. Bash commands
|
|
731
|
+
列出常用的构建、测试、运行命令,格式如下:
|
|
732
|
+
```
|
|
733
|
+
# Bash commands
|
|
734
|
+
- command_name: 命令描述
|
|
735
|
+
- another_command: 另一个命令描述
|
|
736
|
+
```
|
|
737
|
+
|
|
738
|
+
### 2. Code style
|
|
739
|
+
根据检测到的技术栈,提供相应的编码规范,例如:
|
|
740
|
+
```
|
|
741
|
+
# Code style
|
|
742
|
+
- 使用一致的代码格式化规则
|
|
743
|
+
- 遵循对应语言的最佳实践
|
|
744
|
+
```
|
|
745
|
+
|
|
746
|
+
### 3. Workflow
|
|
747
|
+
提供开发工作流建议:
|
|
748
|
+
```
|
|
749
|
+
# Workflow
|
|
750
|
+
- 开发流程建议
|
|
751
|
+
- 测试和部署流程
|
|
752
|
+
```
|
|
753
|
+
|
|
754
|
+
### 4. Technology-specific rules
|
|
755
|
+
针对具体技术栈的特殊规则:
|
|
756
|
+
```
|
|
757
|
+
# Technology-specific rules
|
|
758
|
+
- 技术栈特定的规则
|
|
759
|
+
- 框架相关的最佳实践
|
|
760
|
+
```
|
|
761
|
+
|
|
762
|
+
## 注意事项
|
|
763
|
+
|
|
764
|
+
1. 如果 `.autocoderrules` 目录不存在,请先创建该目录
|
|
765
|
+
2. 根据实际检测到的技术栈生成相应的规则
|
|
766
|
+
3. 确保生成的规则实用且具体
|
|
767
|
+
4. 命令应该是项目中实际可能用到的
|
|
768
|
+
5. 规则应该帮助开发者快速上手项目开发
|
|
769
|
+
|
|
770
|
+
请立即开始分析项目并生成 init.md 文件。
|
|
771
|
+
"""
|
|
772
|
+
|
|
773
|
+
return instruction
|
|
774
|
+
|
|
775
|
+
def _find_rules_directory(self, project_root: str) -> Optional[str]:
|
|
776
|
+
"""
|
|
777
|
+
查找现有的 .autocoderrules 目录
|
|
778
|
+
|
|
779
|
+
Args:
|
|
780
|
+
project_root: 项目根目录
|
|
781
|
+
|
|
782
|
+
Returns:
|
|
783
|
+
找到的规则目录路径,如果没找到则返回 None
|
|
784
|
+
"""
|
|
785
|
+
try:
|
|
786
|
+
# 按优先级顺序查找
|
|
787
|
+
possible_dirs = [
|
|
788
|
+
os.path.join(project_root, ".autocoderrules"),
|
|
789
|
+
os.path.join(project_root, ".auto-coder", ".autocoderrules"),
|
|
790
|
+
os.path.join(project_root, ".auto-coder", "autocoderrules"),
|
|
791
|
+
]
|
|
792
|
+
|
|
793
|
+
for rules_dir in possible_dirs:
|
|
794
|
+
if os.path.exists(rules_dir) and os.path.isdir(rules_dir):
|
|
795
|
+
logger.info(f"找到现有的规则目录: {rules_dir}")
|
|
796
|
+
return rules_dir
|
|
797
|
+
|
|
798
|
+
# 如果没有找到现有目录,返回默认的第一个位置
|
|
799
|
+
default_dir = possible_dirs[0]
|
|
800
|
+
logger.info(f"未找到现有规则目录,返回默认位置: {default_dir}")
|
|
801
|
+
return default_dir
|
|
802
|
+
|
|
803
|
+
except Exception as e:
|
|
804
|
+
logger.error(f"查找规则目录时出错: {e}")
|
|
805
|
+
return None
|