auto-coder 1.0.0__py3-none-any.whl → 2.0.1__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of auto-coder might be problematic. Click here for more details.
- auto_coder-2.0.1.dist-info/LICENSE +158 -0
- auto_coder-2.0.1.dist-info/METADATA +558 -0
- auto_coder-2.0.1.dist-info/RECORD +795 -0
- {auto_coder-1.0.0.dist-info → auto_coder-2.0.1.dist-info}/WHEEL +1 -1
- {auto_coder-1.0.0.dist-info → auto_coder-2.0.1.dist-info}/entry_points.txt +3 -3
- autocoder/__init__.py +31 -0
- autocoder/agent/auto_filegroup.py +32 -13
- autocoder/agent/auto_learn_from_commit.py +9 -1
- autocoder/agent/base_agentic/__init__.py +3 -0
- autocoder/agent/base_agentic/agent_hub.py +1 -1
- autocoder/agent/base_agentic/base_agent.py +235 -136
- autocoder/agent/base_agentic/default_tools.py +119 -118
- autocoder/agent/base_agentic/test_base_agent.py +1 -1
- autocoder/agent/base_agentic/tool_registry.py +32 -20
- autocoder/agent/base_agentic/tools/read_file_tool_resolver.py +24 -3
- autocoder/agent/base_agentic/tools/write_to_file_tool_resolver.py +24 -11
- autocoder/agent/base_agentic/types.py +42 -0
- autocoder/agent/entry_command_agent/chat.py +77 -73
- autocoder/auto_coder.py +31 -40
- autocoder/auto_coder_rag.py +11 -1084
- autocoder/auto_coder_runner.py +962 -2345
- autocoder/auto_coder_terminal.py +26 -0
- autocoder/auto_coder_terminal_v3.py +190 -0
- autocoder/chat/conf_command.py +224 -124
- autocoder/chat/models_command.py +361 -299
- autocoder/chat/rules_command.py +79 -31
- autocoder/chat_auto_coder.py +988 -398
- autocoder/chat_auto_coder_lang.py +23 -732
- autocoder/commands/auto_command.py +25 -8
- autocoder/commands/auto_web.py +1 -1
- autocoder/commands/tools.py +44 -44
- autocoder/common/__init__.py +150 -128
- autocoder/common/ac_style_command_parser/__init__.py +39 -2
- autocoder/common/ac_style_command_parser/config.py +422 -0
- autocoder/common/ac_style_command_parser/parser.py +292 -78
- autocoder/common/ac_style_command_parser/test_parser.py +241 -16
- autocoder/common/ac_style_command_parser/test_typed_parser.py +342 -0
- autocoder/common/ac_style_command_parser/typed_parser.py +653 -0
- autocoder/common/action_yml_file_manager.py +25 -13
- autocoder/common/agent_events/__init__.py +52 -0
- autocoder/common/agent_events/agent_event_emitter.py +193 -0
- autocoder/common/agent_events/event_factory.py +177 -0
- autocoder/common/agent_events/examples.py +307 -0
- autocoder/common/agent_events/types.py +113 -0
- autocoder/common/agent_events/utils.py +68 -0
- autocoder/common/agent_hooks/__init__.py +44 -0
- autocoder/common/agent_hooks/examples.py +582 -0
- autocoder/common/agent_hooks/hook_executor.py +217 -0
- autocoder/common/agent_hooks/hook_manager.py +288 -0
- autocoder/common/agent_hooks/types.py +133 -0
- autocoder/common/agent_hooks/utils.py +99 -0
- autocoder/common/agent_query_queue/queue_executor.py +324 -0
- autocoder/common/agent_query_queue/queue_manager.py +325 -0
- autocoder/common/agents/__init__.py +11 -0
- autocoder/common/agents/agent_manager.py +323 -0
- autocoder/common/agents/agent_parser.py +189 -0
- autocoder/common/agents/example_usage.py +344 -0
- autocoder/common/agents/integration_example.py +330 -0
- autocoder/common/agents/test_agent_parser.py +545 -0
- autocoder/common/async_utils.py +101 -0
- autocoder/common/auto_coder_lang.py +23 -972
- autocoder/common/autocoderargs_parser/__init__.py +14 -0
- autocoder/common/autocoderargs_parser/parser.py +184 -0
- autocoder/common/autocoderargs_parser/tests/__init__.py +1 -0
- autocoder/common/autocoderargs_parser/tests/test_args_parser.py +235 -0
- autocoder/common/autocoderargs_parser/tests/test_token_parser.py +195 -0
- autocoder/common/autocoderargs_parser/token_parser.py +290 -0
- autocoder/common/buildin_tokenizer.py +2 -4
- autocoder/common/code_auto_generate.py +149 -74
- autocoder/common/code_auto_generate_diff.py +163 -70
- autocoder/common/code_auto_generate_editblock.py +179 -89
- autocoder/common/code_auto_generate_strict_diff.py +167 -72
- autocoder/common/code_auto_merge_editblock.py +13 -6
- autocoder/common/code_modification_ranker.py +1 -1
- autocoder/common/command_completer.py +3 -3
- autocoder/common/command_file_manager/manager.py +183 -47
- autocoder/common/command_file_manager/test_command_file_manager.py +507 -0
- autocoder/common/command_templates.py +1 -1
- autocoder/common/conf_utils.py +2 -4
- autocoder/common/conversations/config.py +11 -3
- autocoder/common/conversations/get_conversation_manager.py +100 -2
- autocoder/common/conversations/llm_stats_models.py +264 -0
- autocoder/common/conversations/manager.py +112 -28
- autocoder/common/conversations/models.py +16 -2
- autocoder/common/conversations/storage/index_manager.py +134 -10
- autocoder/common/core_config/__init__.py +63 -0
- autocoder/common/core_config/agentic_mode_manager.py +109 -0
- autocoder/common/core_config/base_manager.py +123 -0
- autocoder/common/core_config/compatibility.py +151 -0
- autocoder/common/core_config/config_manager.py +156 -0
- autocoder/common/core_config/conversation_manager.py +31 -0
- autocoder/common/core_config/exclude_manager.py +72 -0
- autocoder/common/core_config/file_manager.py +177 -0
- autocoder/common/core_config/human_as_model_manager.py +129 -0
- autocoder/common/core_config/lib_manager.py +54 -0
- autocoder/common/core_config/main_manager.py +81 -0
- autocoder/common/core_config/mode_manager.py +126 -0
- autocoder/common/core_config/models.py +70 -0
- autocoder/common/core_config/test_memory_manager.py +1056 -0
- autocoder/common/env_manager.py +282 -0
- autocoder/common/env_manager_usage_example.py +211 -0
- autocoder/common/file_checkpoint/conversation_checkpoint.py +19 -19
- autocoder/common/file_checkpoint/manager.py +264 -48
- autocoder/common/file_checkpoint/test_backup.py +1 -18
- autocoder/common/file_checkpoint/test_manager.py +270 -1
- autocoder/common/file_checkpoint/test_store.py +1 -17
- autocoder/common/file_handler/__init__.py +23 -0
- autocoder/common/file_handler/active_context_handler.py +159 -0
- autocoder/common/file_handler/add_files_handler.py +409 -0
- autocoder/common/file_handler/chat_handler.py +180 -0
- autocoder/common/file_handler/coding_handler.py +409 -0
- autocoder/common/file_handler/commit_handler.py +200 -0
- autocoder/common/file_handler/lib_handler.py +156 -0
- autocoder/common/file_handler/list_files_handler.py +111 -0
- autocoder/common/file_handler/mcp_handler.py +268 -0
- autocoder/common/file_handler/models_handler.py +493 -0
- autocoder/common/file_handler/remove_files_handler.py +172 -0
- autocoder/common/git_utils.py +44 -8
- autocoder/common/global_cancel.py +15 -6
- autocoder/common/ignorefiles/test_ignore_file_utils.py +1 -1
- autocoder/common/international/__init__.py +31 -0
- autocoder/common/international/demo_international.py +92 -0
- autocoder/common/international/message_manager.py +157 -0
- autocoder/common/international/messages/__init__.py +56 -0
- autocoder/common/international/messages/async_command_messages.py +507 -0
- autocoder/common/international/messages/auto_coder_messages.py +2208 -0
- autocoder/common/international/messages/chat_auto_coder_messages.py +1547 -0
- autocoder/common/international/messages/command_help_messages.py +986 -0
- autocoder/common/international/messages/conversation_command_messages.py +191 -0
- autocoder/common/international/messages/git_helper_plugin_messages.py +159 -0
- autocoder/common/international/messages/queue_command_messages.py +751 -0
- autocoder/common/international/messages/rules_command_messages.py +77 -0
- autocoder/common/international/messages/sdk_messages.py +1707 -0
- autocoder/common/international/messages/token_helper_plugin_messages.py +361 -0
- autocoder/common/international/messages/tool_display_messages.py +1212 -0
- autocoder/common/international/messages/workflow_exception_messages.py +473 -0
- autocoder/common/international/test_international.py +612 -0
- autocoder/common/linter_core/__init__.py +28 -0
- autocoder/common/linter_core/base_linter.py +61 -0
- autocoder/common/linter_core/config_loader.py +271 -0
- autocoder/common/linter_core/formatters/__init__.py +0 -0
- autocoder/common/linter_core/formatters/base_formatter.py +38 -0
- autocoder/common/linter_core/formatters/raw_formatter.py +17 -0
- autocoder/common/linter_core/linter.py +166 -0
- autocoder/common/linter_core/linter_factory.py +216 -0
- autocoder/common/linter_core/linter_manager.py +333 -0
- autocoder/common/linter_core/linters/__init__.py +9 -0
- autocoder/common/linter_core/linters/java_linter.py +342 -0
- autocoder/common/linter_core/linters/python_linter.py +115 -0
- autocoder/common/linter_core/linters/typescript_linter.py +119 -0
- autocoder/common/linter_core/models/__init__.py +7 -0
- autocoder/common/linter_core/models/lint_result.py +91 -0
- autocoder/common/linter_core/models.py +33 -0
- autocoder/common/linter_core/tests/__init__.py +3 -0
- autocoder/common/linter_core/tests/test_config_loader.py +323 -0
- autocoder/common/linter_core/tests/test_config_loading.py +308 -0
- autocoder/common/linter_core/tests/test_factory_manager.py +234 -0
- autocoder/common/linter_core/tests/test_formatters.py +147 -0
- autocoder/common/linter_core/tests/test_integration.py +317 -0
- autocoder/common/linter_core/tests/test_java_linter.py +496 -0
- autocoder/common/linter_core/tests/test_linters.py +265 -0
- autocoder/common/linter_core/tests/test_models.py +81 -0
- autocoder/common/linter_core/tests/verify_config_loading.py +296 -0
- autocoder/common/linter_core/tests/verify_fixes.py +183 -0
- autocoder/common/llm_friendly_package/__init__.py +31 -0
- autocoder/common/llm_friendly_package/base_manager.py +102 -0
- autocoder/common/llm_friendly_package/docs_manager.py +121 -0
- autocoder/common/llm_friendly_package/library_manager.py +171 -0
- autocoder/common/{llm_friendly_package.py → llm_friendly_package/main_manager.py} +204 -231
- autocoder/common/llm_friendly_package/models.py +40 -0
- autocoder/common/llm_friendly_package/test_llm_friendly_package.py +536 -0
- autocoder/common/llms/__init__.py +15 -0
- autocoder/common/llms/demo_error_handling.py +85 -0
- autocoder/common/llms/factory.py +142 -0
- autocoder/common/llms/manager.py +264 -0
- autocoder/common/llms/pricing.py +121 -0
- autocoder/common/llms/registry.py +316 -0
- autocoder/common/llms/schema.py +77 -0
- autocoder/common/llms/simple_demo.py +45 -0
- autocoder/common/llms/test_quick_model.py +116 -0
- autocoder/common/llms/test_remove_functionality.py +182 -0
- autocoder/common/llms/tests/__init__.py +1 -0
- autocoder/common/llms/tests/test_manager.py +330 -0
- autocoder/common/llms/tests/test_registry.py +364 -0
- autocoder/common/mcp_tools/__init__.py +62 -0
- autocoder/common/{mcp_tools.py → mcp_tools/executor.py} +49 -40
- autocoder/common/{mcp_hub.py → mcp_tools/hub.py} +42 -68
- autocoder/common/{mcp_server_install.py → mcp_tools/installer.py} +16 -28
- autocoder/common/{mcp_server.py → mcp_tools/server.py} +176 -48
- autocoder/common/mcp_tools/test_keyboard_interrupt.py +93 -0
- autocoder/common/mcp_tools/test_mcp_tools.py +391 -0
- autocoder/common/{mcp_server_types.py → mcp_tools/types.py} +121 -48
- autocoder/common/mcp_tools/verify_functionality.py +202 -0
- autocoder/common/model_speed_tester.py +32 -26
- autocoder/common/priority_directory_finder/__init__.py +142 -0
- autocoder/common/priority_directory_finder/examples.py +230 -0
- autocoder/common/priority_directory_finder/finder.py +283 -0
- autocoder/common/priority_directory_finder/models.py +236 -0
- autocoder/common/priority_directory_finder/test_priority_directory_finder.py +431 -0
- autocoder/common/project_scanner/__init__.py +18 -0
- autocoder/common/project_scanner/compat.py +77 -0
- autocoder/common/project_scanner/scanner.py +436 -0
- autocoder/common/project_tracker/__init__.py +27 -0
- autocoder/common/project_tracker/api.py +228 -0
- autocoder/common/project_tracker/demo.py +272 -0
- autocoder/common/project_tracker/tracker.py +487 -0
- autocoder/common/project_tracker/types.py +53 -0
- autocoder/common/pruner/__init__.py +67 -0
- autocoder/common/pruner/agentic_conversation_pruner.py +651 -102
- autocoder/common/pruner/conversation_message_ids_api.py +386 -0
- autocoder/common/pruner/conversation_message_ids_manager.py +347 -0
- autocoder/common/pruner/conversation_message_ids_pruner.py +473 -0
- autocoder/common/pruner/conversation_normalizer.py +347 -0
- autocoder/common/pruner/conversation_pruner.py +26 -6
- autocoder/common/pruner/test_agentic_conversation_pruner.py +554 -112
- autocoder/common/pruner/test_conversation_normalizer.py +502 -0
- autocoder/common/pruner/test_tool_content_detector.py +324 -0
- autocoder/common/pruner/tool_content_detector.py +227 -0
- autocoder/common/pruner/tools/__init__.py +18 -0
- autocoder/common/pruner/tools/query_message_ids.py +264 -0
- autocoder/common/pruner/tools/test_agentic_pruning_logic.py +432 -0
- autocoder/common/pruner/tools/test_message_ids_pruning_only.py +192 -0
- autocoder/common/pull_requests/__init__.py +9 -1
- autocoder/common/pull_requests/utils.py +122 -1
- autocoder/common/rag_manager/rag_manager.py +36 -40
- autocoder/common/rulefiles/__init__.py +53 -1
- autocoder/common/rulefiles/api.py +250 -0
- autocoder/common/rulefiles/core/__init__.py +14 -0
- autocoder/common/rulefiles/core/manager.py +241 -0
- autocoder/common/rulefiles/core/selector.py +805 -0
- autocoder/common/rulefiles/models/__init__.py +20 -0
- autocoder/common/rulefiles/models/index.py +16 -0
- autocoder/common/rulefiles/models/init_rule.py +18 -0
- autocoder/common/rulefiles/models/rule_file.py +18 -0
- autocoder/common/rulefiles/models/rule_relevance.py +14 -0
- autocoder/common/rulefiles/models/summary.py +16 -0
- autocoder/common/rulefiles/test_rulefiles.py +776 -0
- autocoder/common/rulefiles/utils/__init__.py +34 -0
- autocoder/common/rulefiles/utils/monitor.py +86 -0
- autocoder/common/rulefiles/utils/parser.py +230 -0
- autocoder/common/save_formatted_log.py +67 -10
- autocoder/common/search_replace.py +8 -1
- autocoder/common/search_replace_patch/__init__.py +24 -0
- autocoder/common/search_replace_patch/base.py +115 -0
- autocoder/common/search_replace_patch/manager.py +248 -0
- autocoder/common/search_replace_patch/patch_replacer.py +304 -0
- autocoder/common/search_replace_patch/similarity_replacer.py +306 -0
- autocoder/common/search_replace_patch/string_replacer.py +181 -0
- autocoder/common/search_replace_patch/tests/__init__.py +3 -0
- autocoder/common/search_replace_patch/tests/run_tests.py +126 -0
- autocoder/common/search_replace_patch/tests/test_base.py +188 -0
- autocoder/common/search_replace_patch/tests/test_empty_line_insert.py +233 -0
- autocoder/common/search_replace_patch/tests/test_integration.py +389 -0
- autocoder/common/search_replace_patch/tests/test_manager.py +351 -0
- autocoder/common/search_replace_patch/tests/test_patch_replacer.py +316 -0
- autocoder/common/search_replace_patch/tests/test_regex_replacer.py +306 -0
- autocoder/common/search_replace_patch/tests/test_similarity_replacer.py +384 -0
- autocoder/common/shell_commands/__init__.py +197 -0
- autocoder/common/shell_commands/background_process_notifier.py +346 -0
- autocoder/common/shell_commands/command_executor.py +1127 -0
- autocoder/common/shell_commands/error_recovery.py +541 -0
- autocoder/common/shell_commands/exceptions.py +120 -0
- autocoder/common/shell_commands/interactive_executor.py +476 -0
- autocoder/common/shell_commands/interactive_pexpect_process.py +623 -0
- autocoder/common/shell_commands/interactive_process.py +744 -0
- autocoder/common/shell_commands/interactive_session_manager.py +1014 -0
- autocoder/common/shell_commands/monitoring.py +529 -0
- autocoder/common/shell_commands/process_cleanup.py +386 -0
- autocoder/common/shell_commands/process_manager.py +606 -0
- autocoder/common/shell_commands/test_interactive_pexpect_process.py +281 -0
- autocoder/common/shell_commands/tests/__init__.py +6 -0
- autocoder/common/shell_commands/tests/conftest.py +118 -0
- autocoder/common/shell_commands/tests/test_background_process_notifier.py +703 -0
- autocoder/common/shell_commands/tests/test_command_executor.py +448 -0
- autocoder/common/shell_commands/tests/test_error_recovery.py +305 -0
- autocoder/common/shell_commands/tests/test_exceptions.py +299 -0
- autocoder/common/shell_commands/tests/test_execute_batch.py +588 -0
- autocoder/common/shell_commands/tests/test_indented_batch_commands.py +244 -0
- autocoder/common/shell_commands/tests/test_integration.py +664 -0
- autocoder/common/shell_commands/tests/test_monitoring.py +546 -0
- autocoder/common/shell_commands/tests/test_performance.py +632 -0
- autocoder/common/shell_commands/tests/test_process_cleanup.py +397 -0
- autocoder/common/shell_commands/tests/test_process_manager.py +606 -0
- autocoder/common/shell_commands/tests/test_timeout_config.py +343 -0
- autocoder/common/shell_commands/tests/test_timeout_manager.py +520 -0
- autocoder/common/shell_commands/timeout_config.py +315 -0
- autocoder/common/shell_commands/timeout_manager.py +352 -0
- autocoder/common/terminal_paste/__init__.py +14 -0
- autocoder/common/terminal_paste/demo.py +145 -0
- autocoder/common/terminal_paste/demo_paste_functionality.py +95 -0
- autocoder/common/terminal_paste/paste_handler.py +200 -0
- autocoder/common/terminal_paste/paste_manager.py +118 -0
- autocoder/common/terminal_paste/tests/__init__.py +1 -0
- autocoder/common/terminal_paste/tests/test_paste_handler.py +182 -0
- autocoder/common/terminal_paste/tests/test_paste_manager.py +126 -0
- autocoder/common/terminal_paste/utils.py +163 -0
- autocoder/common/test_autocoder_args.py +232 -0
- autocoder/common/test_env_manager.py +173 -0
- autocoder/common/test_env_manager_integration.py +159 -0
- autocoder/common/text_similarity/__init__.py +9 -0
- autocoder/common/text_similarity/demo.py +216 -0
- autocoder/common/text_similarity/examples.py +266 -0
- autocoder/common/text_similarity/test_text_similarity.py +306 -0
- autocoder/common/text_similarity/text_similarity.py +194 -0
- autocoder/common/text_similarity/utils.py +125 -0
- autocoder/common/todos/__init__.py +61 -0
- autocoder/common/todos/cache/__init__.py +16 -0
- autocoder/common/todos/cache/base_cache.py +89 -0
- autocoder/common/todos/cache/cache_manager.py +228 -0
- autocoder/common/todos/cache/memory_cache.py +225 -0
- autocoder/common/todos/config.py +155 -0
- autocoder/common/todos/exceptions.py +35 -0
- autocoder/common/todos/get_todo_manager.py +161 -0
- autocoder/common/todos/manager.py +537 -0
- autocoder/common/todos/models.py +239 -0
- autocoder/common/todos/storage/__init__.py +14 -0
- autocoder/common/todos/storage/base_storage.py +76 -0
- autocoder/common/todos/storage/file_storage.py +278 -0
- autocoder/common/tokens/counter.py +24 -2
- autocoder/common/tools_manager/__init__.py +17 -0
- autocoder/common/tools_manager/examples.py +162 -0
- autocoder/common/tools_manager/manager.py +385 -0
- autocoder/common/tools_manager/models.py +39 -0
- autocoder/common/tools_manager/test_tools_manager.py +303 -0
- autocoder/common/tools_manager/utils.py +191 -0
- autocoder/common/v2/agent/agentic_callbacks.py +270 -0
- autocoder/common/v2/agent/agentic_edit.py +2699 -1856
- autocoder/common/v2/agent/agentic_edit_change_manager.py +474 -0
- autocoder/common/v2/agent/agentic_edit_tools/__init__.py +35 -1
- autocoder/common/v2/agent/agentic_edit_tools/ac_mod_list_tool_resolver.py +279 -0
- autocoder/common/v2/agent/agentic_edit_tools/ac_mod_write_tool_resolver.py +10 -1
- autocoder/common/v2/agent/agentic_edit_tools/background_task_tool_resolver.py +1167 -0
- autocoder/common/v2/agent/agentic_edit_tools/base_tool_resolver.py +2 -2
- autocoder/common/v2/agent/agentic_edit_tools/conversation_message_ids_read_tool_resolver.py +214 -0
- autocoder/common/v2/agent/agentic_edit_tools/conversation_message_ids_write_tool_resolver.py +299 -0
- autocoder/common/v2/agent/agentic_edit_tools/count_tokens_tool_resolver.py +290 -0
- autocoder/common/v2/agent/agentic_edit_tools/execute_command_tool_resolver.py +564 -29
- autocoder/common/v2/agent/agentic_edit_tools/execute_workflow_tool_resolver.py +485 -0
- autocoder/common/v2/agent/agentic_edit_tools/extract_to_text_tool_resolver.py +225 -0
- autocoder/common/v2/agent/agentic_edit_tools/lint_report.py +79 -0
- autocoder/common/v2/agent/agentic_edit_tools/linter_config_models.py +343 -0
- autocoder/common/v2/agent/agentic_edit_tools/linter_enabled_tool_resolver.py +189 -0
- autocoder/common/v2/agent/agentic_edit_tools/list_files_tool_resolver.py +169 -101
- autocoder/common/v2/agent/agentic_edit_tools/load_extra_document_tool_resolver.py +356 -0
- autocoder/common/v2/agent/agentic_edit_tools/read_file_tool_resolver.py +243 -50
- autocoder/common/v2/agent/agentic_edit_tools/replace_in_file_tool_resolver.py +667 -147
- autocoder/common/v2/agent/agentic_edit_tools/run_named_subagents_tool_resolver.py +691 -0
- autocoder/common/v2/agent/agentic_edit_tools/search_files_tool_resolver.py +410 -86
- autocoder/common/v2/agent/agentic_edit_tools/session_interactive_tool_resolver.py +115 -0
- autocoder/common/v2/agent/agentic_edit_tools/session_start_tool_resolver.py +190 -0
- autocoder/common/v2/agent/agentic_edit_tools/session_stop_tool_resolver.py +76 -0
- autocoder/common/v2/agent/agentic_edit_tools/test_write_to_file_tool_resolver.py +207 -192
- autocoder/common/v2/agent/agentic_edit_tools/todo_read_tool_resolver.py +80 -63
- autocoder/common/v2/agent/agentic_edit_tools/todo_write_tool_resolver.py +237 -233
- autocoder/common/v2/agent/agentic_edit_tools/use_mcp_tool_resolver.py +2 -2
- autocoder/common/v2/agent/agentic_edit_tools/web_crawl_tool_resolver.py +557 -0
- autocoder/common/v2/agent/agentic_edit_tools/web_search_tool_resolver.py +600 -0
- autocoder/common/v2/agent/agentic_edit_tools/write_to_file_tool_resolver.py +56 -121
- autocoder/common/v2/agent/agentic_edit_types.py +343 -9
- autocoder/common/v2/agent/runner/__init__.py +3 -3
- autocoder/common/v2/agent/runner/base_runner.py +12 -26
- autocoder/common/v2/agent/runner/{event_runner.py → file_based_event_runner.py} +3 -2
- autocoder/common/v2/agent/runner/sdk_runner.py +150 -8
- autocoder/common/v2/agent/runner/terminal_runner.py +170 -57
- autocoder/common/v2/agent/runner/tool_display.py +557 -159
- autocoder/common/v2/agent/test_agentic_callbacks.py +265 -0
- autocoder/common/v2/agent/test_agentic_edit.py +194 -0
- autocoder/common/v2/agent/tool_caller/__init__.py +24 -0
- autocoder/common/v2/agent/tool_caller/default_tool_resolver_map.py +135 -0
- autocoder/common/v2/agent/tool_caller/integration_test.py +172 -0
- autocoder/common/v2/agent/tool_caller/plugins/__init__.py +14 -0
- autocoder/common/v2/agent/tool_caller/plugins/base_plugin.py +126 -0
- autocoder/common/v2/agent/tool_caller/plugins/examples/__init__.py +13 -0
- autocoder/common/v2/agent/tool_caller/plugins/examples/logging_plugin.py +164 -0
- autocoder/common/v2/agent/tool_caller/plugins/examples/security_filter_plugin.py +198 -0
- autocoder/common/v2/agent/tool_caller/plugins/plugin_interface.py +141 -0
- autocoder/common/v2/agent/tool_caller/test_tool_caller.py +278 -0
- autocoder/common/v2/agent/tool_caller/tool_call_plugin_manager.py +331 -0
- autocoder/common/v2/agent/tool_caller/tool_caller.py +337 -0
- autocoder/common/v2/agent/tool_caller/usage_example.py +193 -0
- autocoder/common/v2/code_agentic_editblock_manager.py +4 -4
- autocoder/common/v2/code_auto_generate.py +136 -78
- autocoder/common/v2/code_auto_generate_diff.py +135 -79
- autocoder/common/v2/code_auto_generate_editblock.py +174 -99
- autocoder/common/v2/code_auto_generate_strict_diff.py +151 -71
- autocoder/common/v2/code_auto_merge.py +1 -1
- autocoder/common/v2/code_auto_merge_editblock.py +13 -1
- autocoder/common/v2/code_diff_manager.py +3 -3
- autocoder/common/v2/code_editblock_manager.py +4 -14
- autocoder/common/v2/code_manager.py +1 -1
- autocoder/common/v2/code_strict_diff_manager.py +2 -2
- autocoder/common/wrap_llm_hint/__init__.py +10 -0
- autocoder/common/wrap_llm_hint/test_wrap_llm_hint.py +1067 -0
- autocoder/common/wrap_llm_hint/utils.py +432 -0
- autocoder/common/wrap_llm_hint/wrap_llm_hint.py +323 -0
- autocoder/completer/__init__.py +8 -0
- autocoder/completer/command_completer_v2.py +1094 -0
- autocoder/default_project/__init__.py +501 -0
- autocoder/dispacher/__init__.py +4 -12
- autocoder/dispacher/actions/action.py +400 -129
- autocoder/dispacher/actions/plugins/action_regex_project.py +2 -2
- autocoder/index/entry.py +117 -125
- autocoder/{agent → index/filter}/agentic_filter.py +322 -333
- autocoder/index/filter/normal_filter.py +5 -11
- autocoder/index/filter/quick_filter.py +1 -1
- autocoder/index/index.py +36 -9
- autocoder/index/tests/__init__.py +1 -0
- autocoder/index/tests/run_tests.py +195 -0
- autocoder/index/tests/test_entry.py +303 -0
- autocoder/index/tests/test_index_manager.py +314 -0
- autocoder/index/tests/test_module_integration.py +300 -0
- autocoder/index/tests/test_symbols_utils.py +183 -0
- autocoder/inner/__init__.py +4 -0
- autocoder/inner/agentic.py +923 -0
- autocoder/inner/async_command_handler.py +992 -0
- autocoder/inner/conversation_command_handlers.py +623 -0
- autocoder/inner/merge_command_handler.py +213 -0
- autocoder/inner/queue_command_handler.py +684 -0
- autocoder/models.py +95 -266
- autocoder/plugins/git_helper_plugin.py +31 -29
- autocoder/plugins/token_helper_plugin.py +65 -46
- autocoder/pyproject/__init__.py +32 -29
- autocoder/rag/agentic_rag.py +215 -75
- autocoder/rag/cache/simple_cache.py +1 -2
- autocoder/rag/loaders/image_loader.py +1 -1
- autocoder/rag/long_context_rag.py +42 -26
- autocoder/rag/qa_conversation_strategy.py +1 -1
- autocoder/rag/terminal/__init__.py +17 -0
- autocoder/rag/terminal/args.py +581 -0
- autocoder/rag/terminal/bootstrap.py +61 -0
- autocoder/rag/terminal/command_handlers.py +653 -0
- autocoder/rag/terminal/formatters/__init__.py +20 -0
- autocoder/rag/terminal/formatters/base.py +70 -0
- autocoder/rag/terminal/formatters/json_format.py +66 -0
- autocoder/rag/terminal/formatters/stream_json.py +95 -0
- autocoder/rag/terminal/formatters/text.py +28 -0
- autocoder/rag/terminal/init.py +120 -0
- autocoder/rag/terminal/utils.py +106 -0
- autocoder/rag/test_agentic_rag.py +389 -0
- autocoder/rag/test_doc_filter.py +3 -3
- autocoder/rag/test_long_context_rag.py +1 -1
- autocoder/rag/test_token_limiter.py +517 -10
- autocoder/rag/token_counter.py +3 -0
- autocoder/rag/token_limiter.py +19 -15
- autocoder/rag/tools/__init__.py +26 -2
- autocoder/rag/tools/bochaai_example.py +343 -0
- autocoder/rag/tools/bochaai_sdk.py +541 -0
- autocoder/rag/tools/metaso_example.py +268 -0
- autocoder/rag/tools/metaso_sdk.py +417 -0
- autocoder/rag/tools/recall_tool.py +28 -7
- autocoder/rag/tools/run_integration_tests.py +204 -0
- autocoder/rag/tools/test_all_providers.py +318 -0
- autocoder/rag/tools/test_bochaai_integration.py +482 -0
- autocoder/rag/tools/test_final_integration.py +215 -0
- autocoder/rag/tools/test_metaso_integration.py +424 -0
- autocoder/rag/tools/test_metaso_real.py +171 -0
- autocoder/rag/tools/test_web_crawl_tool.py +639 -0
- autocoder/rag/tools/test_web_search_tool.py +509 -0
- autocoder/rag/tools/todo_read_tool.py +202 -0
- autocoder/rag/tools/todo_write_tool.py +412 -0
- autocoder/rag/tools/web_crawl_tool.py +634 -0
- autocoder/rag/tools/web_search_tool.py +558 -0
- autocoder/rag/tools/web_tools_example.py +119 -0
- autocoder/rag/types.py +16 -0
- autocoder/rag/variable_holder.py +4 -2
- autocoder/rags.py +86 -79
- autocoder/regexproject/__init__.py +23 -21
- autocoder/sdk/__init__.py +46 -190
- autocoder/sdk/api.py +370 -0
- autocoder/sdk/async_runner/__init__.py +26 -0
- autocoder/sdk/async_runner/async_executor.py +650 -0
- autocoder/sdk/async_runner/async_handler.py +356 -0
- autocoder/sdk/async_runner/markdown_processor.py +595 -0
- autocoder/sdk/async_runner/task_metadata.py +284 -0
- autocoder/sdk/async_runner/worktree_manager.py +438 -0
- autocoder/sdk/cli/__init__.py +2 -5
- autocoder/sdk/cli/formatters.py +28 -204
- autocoder/sdk/cli/handlers.py +77 -44
- autocoder/sdk/cli/main.py +154 -171
- autocoder/sdk/cli/options.py +95 -22
- autocoder/sdk/constants.py +139 -51
- autocoder/sdk/core/auto_coder_core.py +484 -109
- autocoder/sdk/core/bridge.py +297 -115
- autocoder/sdk/exceptions.py +18 -12
- autocoder/sdk/formatters/__init__.py +19 -0
- autocoder/sdk/formatters/input.py +64 -0
- autocoder/sdk/formatters/output.py +247 -0
- autocoder/sdk/formatters/stream.py +54 -0
- autocoder/sdk/models/__init__.py +6 -5
- autocoder/sdk/models/options.py +55 -18
- autocoder/sdk/utils/formatters.py +27 -195
- autocoder/suffixproject/__init__.py +28 -25
- autocoder/terminal/__init__.py +14 -0
- autocoder/terminal/app.py +454 -0
- autocoder/terminal/args.py +32 -0
- autocoder/terminal/bootstrap.py +178 -0
- autocoder/terminal/command_processor.py +521 -0
- autocoder/terminal/command_registry.py +57 -0
- autocoder/terminal/help.py +97 -0
- autocoder/terminal/tasks/__init__.py +5 -0
- autocoder/terminal/tasks/background.py +77 -0
- autocoder/terminal/tasks/task_event.py +70 -0
- autocoder/terminal/ui/__init__.py +13 -0
- autocoder/terminal/ui/completer.py +268 -0
- autocoder/terminal/ui/keybindings.py +75 -0
- autocoder/terminal/ui/session.py +41 -0
- autocoder/terminal/ui/toolbar.py +64 -0
- autocoder/terminal/utils/__init__.py +13 -0
- autocoder/terminal/utils/errors.py +18 -0
- autocoder/terminal/utils/paths.py +19 -0
- autocoder/terminal/utils/shell.py +43 -0
- autocoder/terminal_v3/__init__.py +10 -0
- autocoder/terminal_v3/app.py +201 -0
- autocoder/terminal_v3/handlers/__init__.py +5 -0
- autocoder/terminal_v3/handlers/command_handler.py +131 -0
- autocoder/terminal_v3/models/__init__.py +6 -0
- autocoder/terminal_v3/models/conversation_buffer.py +214 -0
- autocoder/terminal_v3/models/message.py +50 -0
- autocoder/terminal_v3/models/tool_display.py +247 -0
- autocoder/terminal_v3/ui/__init__.py +7 -0
- autocoder/terminal_v3/ui/keybindings.py +56 -0
- autocoder/terminal_v3/ui/layout.py +141 -0
- autocoder/terminal_v3/ui/styles.py +43 -0
- autocoder/tsproject/__init__.py +23 -23
- autocoder/utils/auto_coder_utils/chat_stream_out.py +1 -1
- autocoder/utils/llms.py +88 -80
- autocoder/utils/math_utils.py +101 -0
- autocoder/utils/model_provider_selector.py +16 -4
- autocoder/utils/operate_config_api.py +33 -5
- autocoder/utils/thread_utils.py +2 -2
- autocoder/version.py +4 -2
- autocoder/workflow_agents/__init__.py +84 -0
- autocoder/workflow_agents/agent.py +143 -0
- autocoder/workflow_agents/exceptions.py +573 -0
- autocoder/workflow_agents/executor.py +665 -0
- autocoder/workflow_agents/loader.py +749 -0
- autocoder/workflow_agents/runner.py +267 -0
- autocoder/workflow_agents/types.py +173 -0
- autocoder/workflow_agents/utils.py +434 -0
- autocoder/workflow_agents/workflow_manager.py +211 -0
- auto_coder-1.0.0.dist-info/METADATA +0 -396
- auto_coder-1.0.0.dist-info/RECORD +0 -442
- auto_coder-1.0.0.dist-info/licenses/LICENSE +0 -201
- autocoder/auto_coder_server.py +0 -672
- autocoder/benchmark.py +0 -138
- autocoder/common/ac_style_command_parser/example.py +0 -7
- autocoder/common/cleaner.py +0 -31
- autocoder/common/command_completer_v2.py +0 -615
- autocoder/common/context_pruner.py +0 -477
- autocoder/common/conversation_pruner.py +0 -132
- autocoder/common/directory_cache/__init__.py +0 -1
- autocoder/common/directory_cache/cache.py +0 -192
- autocoder/common/directory_cache/test_cache.py +0 -190
- autocoder/common/file_checkpoint/examples.py +0 -217
- autocoder/common/llm_friendly_package_example.py +0 -138
- autocoder/common/llm_friendly_package_test.py +0 -63
- autocoder/common/pull_requests/test_module.py +0 -1
- autocoder/common/rulefiles/autocoderrules_utils.py +0 -484
- autocoder/common/text.py +0 -30
- autocoder/common/v2/agent/agentic_edit_tools/list_package_info_tool_resolver.py +0 -42
- autocoder/common/v2/agent/agentic_edit_tools/test_execute_command_tool_resolver.py +0 -70
- autocoder/common/v2/agent/agentic_edit_tools/test_search_files_tool_resolver.py +0 -163
- autocoder/common/v2/agent/agentic_tool_display.py +0 -183
- autocoder/plugins/dynamic_completion_example.py +0 -148
- autocoder/plugins/sample_plugin.py +0 -160
- autocoder/sdk/cli/__main__.py +0 -26
- autocoder/sdk/cli/completion_wrapper.py +0 -38
- autocoder/sdk/cli/install_completion.py +0 -301
- autocoder/sdk/models/messages.py +0 -209
- autocoder/sdk/session/__init__.py +0 -32
- autocoder/sdk/session/session.py +0 -106
- autocoder/sdk/session/session_manager.py +0 -56
- {auto_coder-1.0.0.dist-info → auto_coder-2.0.1.dist-info}/top_level.txt +0 -0
- /autocoder/{sdk/example.py → common/agent_query_queue/__init__.py} +0 -0
|
@@ -0,0 +1,145 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
"""Demo script for terminal_paste module functionality.
|
|
3
|
+
|
|
4
|
+
This script demonstrates how the terminal_paste module works:
|
|
5
|
+
1. Simulates paste events by saving content to files
|
|
6
|
+
2. Shows placeholder resolution
|
|
7
|
+
3. Demonstrates cleanup functionality
|
|
8
|
+
"""
|
|
9
|
+
|
|
10
|
+
import os
|
|
11
|
+
import sys
|
|
12
|
+
from autocoder.common.terminal_paste import (
|
|
13
|
+
PasteManager,
|
|
14
|
+
resolve_paste_placeholders
|
|
15
|
+
)
|
|
16
|
+
from autocoder.common.terminal_paste.paste_handler import (
|
|
17
|
+
cleanup_old_pastes,
|
|
18
|
+
list_paste_files
|
|
19
|
+
)
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
def demo_basic_functionality():
|
|
23
|
+
"""Demonstrate basic paste functionality."""
|
|
24
|
+
print("=== Terminal Paste Module Demo ===\n")
|
|
25
|
+
|
|
26
|
+
# Initialize paste manager
|
|
27
|
+
pm = PasteManager()
|
|
28
|
+
print(f"Paste directory: {pm.paste_dir}")
|
|
29
|
+
|
|
30
|
+
# Simulate saving some paste content
|
|
31
|
+
print("\n1. Saving paste content...")
|
|
32
|
+
content1 = """def hello_world():
|
|
33
|
+
print("Hello, World!")
|
|
34
|
+
return "success"
|
|
35
|
+
"""
|
|
36
|
+
|
|
37
|
+
content2 = """# This is a markdown example
|
|
38
|
+
## Features
|
|
39
|
+
- Feature 1
|
|
40
|
+
- Feature 2
|
|
41
|
+
- Feature 3
|
|
42
|
+
"""
|
|
43
|
+
|
|
44
|
+
file_id1 = pm.save_paste(content1)
|
|
45
|
+
file_id2 = pm.save_paste(content2)
|
|
46
|
+
|
|
47
|
+
print(f" Saved Python code as: {file_id1}")
|
|
48
|
+
print(f" Saved Markdown as: {file_id2}")
|
|
49
|
+
|
|
50
|
+
# Show placeholder resolution
|
|
51
|
+
print("\n2. Demonstrating placeholder resolution...")
|
|
52
|
+
test_command = f"/coding Please review this code: [{file_id1}] and update the documentation: [{file_id2}]"
|
|
53
|
+
print(f" Original command: {test_command}")
|
|
54
|
+
|
|
55
|
+
resolved_command = resolve_paste_placeholders(test_command)
|
|
56
|
+
print(f" Resolved command: {resolved_command}")
|
|
57
|
+
|
|
58
|
+
# List all paste files
|
|
59
|
+
print("\n3. Listing all paste files...")
|
|
60
|
+
paste_files = list_paste_files()
|
|
61
|
+
for i, paste_file in enumerate(paste_files, 1):
|
|
62
|
+
print(f" {i}. {paste_file}")
|
|
63
|
+
|
|
64
|
+
# Read back content
|
|
65
|
+
print("\n4. Reading back content...")
|
|
66
|
+
read_content1 = pm.read_paste(file_id1)
|
|
67
|
+
print(f" Content from {file_id1}:")
|
|
68
|
+
if read_content1:
|
|
69
|
+
print(f" {repr(read_content1[:50])}...")
|
|
70
|
+
else:
|
|
71
|
+
print(" Content not found")
|
|
72
|
+
|
|
73
|
+
# Cleanup demonstration
|
|
74
|
+
print("\n5. Cleanup demonstration...")
|
|
75
|
+
print(f" Files before cleanup: {len(paste_files)}")
|
|
76
|
+
cleaned_count = cleanup_old_pastes(max_age_hours=0) # Clean all files
|
|
77
|
+
print(f" Files cleaned: {cleaned_count}")
|
|
78
|
+
|
|
79
|
+
remaining_files = list_paste_files()
|
|
80
|
+
print(f" Files after cleanup: {len(remaining_files)}")
|
|
81
|
+
|
|
82
|
+
|
|
83
|
+
def demo_error_handling():
|
|
84
|
+
"""Demonstrate error handling."""
|
|
85
|
+
print("\n=== Error Handling Demo ===\n")
|
|
86
|
+
|
|
87
|
+
pm = PasteManager()
|
|
88
|
+
|
|
89
|
+
# Try to read non-existent file
|
|
90
|
+
print("1. Reading non-existent file...")
|
|
91
|
+
non_existent = pm.read_paste("pasted-nonexistent12345")
|
|
92
|
+
print(f" Result: {non_existent}")
|
|
93
|
+
|
|
94
|
+
# Try to resolve invalid placeholder
|
|
95
|
+
print("\n2. Resolving invalid placeholder...")
|
|
96
|
+
invalid_text = "Command with [pasted-invalidid] placeholder"
|
|
97
|
+
resolved = resolve_paste_placeholders(invalid_text)
|
|
98
|
+
print(f" Original: {invalid_text}")
|
|
99
|
+
print(f" Resolved: {resolved}")
|
|
100
|
+
|
|
101
|
+
|
|
102
|
+
def demo_integration_example():
|
|
103
|
+
"""Show how this would integrate with chat_auto_coder.py."""
|
|
104
|
+
print("\n=== Integration Example ===\n")
|
|
105
|
+
|
|
106
|
+
# Simulate what happens in chat_auto_coder.py
|
|
107
|
+
pm = PasteManager()
|
|
108
|
+
|
|
109
|
+
# User pastes some content (simulated)
|
|
110
|
+
pasted_content = """SELECT users.name, COUNT(orders.id) as order_count
|
|
111
|
+
FROM users
|
|
112
|
+
LEFT JOIN orders ON users.id = orders.user_id
|
|
113
|
+
WHERE users.created_at > '2023-01-01'
|
|
114
|
+
GROUP BY users.id, users.name
|
|
115
|
+
ORDER BY order_count DESC;"""
|
|
116
|
+
|
|
117
|
+
# Save the paste (this would happen in the paste handler)
|
|
118
|
+
file_id = pm.save_paste(pasted_content)
|
|
119
|
+
print(f"User pastes SQL query, saved as: {file_id}")
|
|
120
|
+
|
|
121
|
+
# User types command with placeholder (what they see in terminal)
|
|
122
|
+
user_input = f"/coding Please optimize this SQL query: [{file_id}]"
|
|
123
|
+
print(f"User types: {user_input}")
|
|
124
|
+
|
|
125
|
+
# Before processing, resolve placeholders (happens in main loop)
|
|
126
|
+
resolved_input = resolve_paste_placeholders(user_input)
|
|
127
|
+
print(f"System processes: {resolved_input}")
|
|
128
|
+
|
|
129
|
+
print("\nThis way, the user sees a clean command line, but the system gets the full content!")
|
|
130
|
+
|
|
131
|
+
|
|
132
|
+
if __name__ == "__main__":
|
|
133
|
+
try:
|
|
134
|
+
demo_basic_functionality()
|
|
135
|
+
demo_error_handling()
|
|
136
|
+
demo_integration_example()
|
|
137
|
+
print("\n=== Demo Complete ===")
|
|
138
|
+
except KeyboardInterrupt:
|
|
139
|
+
print("\n\nDemo interrupted by user.")
|
|
140
|
+
sys.exit(0)
|
|
141
|
+
except Exception as e:
|
|
142
|
+
print(f"\nDemo failed with error: {e}")
|
|
143
|
+
import traceback
|
|
144
|
+
traceback.print_exc()
|
|
145
|
+
sys.exit(1)
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
"""
|
|
3
|
+
演示新的粘贴功能
|
|
4
|
+
|
|
5
|
+
这个脚本展示了如何使用新的粘贴处理功能:
|
|
6
|
+
1. Ctrl+P 粘贴多行内容并自动保存为文件
|
|
7
|
+
2. 占位符自动解析为实际内容
|
|
8
|
+
"""
|
|
9
|
+
|
|
10
|
+
import os
|
|
11
|
+
import tempfile
|
|
12
|
+
from prompt_toolkit import PromptSession
|
|
13
|
+
from prompt_toolkit.key_binding import KeyBindings
|
|
14
|
+
from prompt_toolkit.clipboard import ClipboardData
|
|
15
|
+
from autocoder.common.terminal_paste import register_paste_handler, resolve_paste_placeholders
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
def demo_paste_functionality():
|
|
19
|
+
"""演示粘贴功能的完整流程"""
|
|
20
|
+
print("🎯 Terminal Paste 功能演示")
|
|
21
|
+
print("=" * 50)
|
|
22
|
+
|
|
23
|
+
# 创建键绑定
|
|
24
|
+
kb = KeyBindings()
|
|
25
|
+
register_paste_handler(kb)
|
|
26
|
+
|
|
27
|
+
print("✅ 粘贴处理器已注册")
|
|
28
|
+
print("📋 使用说明:")
|
|
29
|
+
print(" - 复制多行文本到剪贴板")
|
|
30
|
+
print(" - 按 Ctrl+P 粘贴 (多行内容会保存为文件)")
|
|
31
|
+
print(" - 按 Ctrl+V 正常粘贴 (单行内容)")
|
|
32
|
+
print(" - 输入 'quit' 退出演示")
|
|
33
|
+
print()
|
|
34
|
+
|
|
35
|
+
# 创建 PromptSession
|
|
36
|
+
session = PromptSession(
|
|
37
|
+
key_bindings=kb
|
|
38
|
+
# 注意:bracketed paste 通过 Keys.BracketedPaste 绑定处理
|
|
39
|
+
)
|
|
40
|
+
|
|
41
|
+
while True:
|
|
42
|
+
try:
|
|
43
|
+
# 获取用户输入
|
|
44
|
+
user_input = session.prompt("📝 请输入命令 (或按 Ctrl+P 粘贴): ")
|
|
45
|
+
|
|
46
|
+
if user_input.lower() in ['quit', 'exit', 'q']:
|
|
47
|
+
print("👋 演示结束")
|
|
48
|
+
break
|
|
49
|
+
|
|
50
|
+
# 解析占位符
|
|
51
|
+
resolved_input = resolve_paste_placeholders(user_input)
|
|
52
|
+
|
|
53
|
+
# 显示结果
|
|
54
|
+
if resolved_input != user_input:
|
|
55
|
+
print("🔄 占位符已解析:")
|
|
56
|
+
print(f" 原始输入: {user_input}")
|
|
57
|
+
print(f" 解析后: {resolved_input}")
|
|
58
|
+
else:
|
|
59
|
+
print(f"📤 您输入了: {resolved_input}")
|
|
60
|
+
|
|
61
|
+
print()
|
|
62
|
+
|
|
63
|
+
except KeyboardInterrupt:
|
|
64
|
+
print("\n👋 演示结束")
|
|
65
|
+
break
|
|
66
|
+
except Exception as e:
|
|
67
|
+
print(f"❌ 错误: {e}")
|
|
68
|
+
|
|
69
|
+
|
|
70
|
+
def create_sample_clipboard_content():
|
|
71
|
+
"""创建示例剪贴板内容用于测试"""
|
|
72
|
+
sample_content = """def hello_world():
|
|
73
|
+
print("Hello, World!")
|
|
74
|
+
return "success"
|
|
75
|
+
|
|
76
|
+
if __name__ == "__main__":
|
|
77
|
+
result = hello_world()
|
|
78
|
+
print(f"Result: {result}")"""
|
|
79
|
+
|
|
80
|
+
print("📋 示例多行内容:")
|
|
81
|
+
print(sample_content)
|
|
82
|
+
print()
|
|
83
|
+
print("💡 提示: 复制上面的代码,然后在演示中按 Ctrl+P 粘贴")
|
|
84
|
+
print()
|
|
85
|
+
|
|
86
|
+
|
|
87
|
+
if __name__ == "__main__":
|
|
88
|
+
print("🚀 开始 Terminal Paste 功能演示")
|
|
89
|
+
print()
|
|
90
|
+
|
|
91
|
+
# 显示示例内容
|
|
92
|
+
create_sample_clipboard_content()
|
|
93
|
+
|
|
94
|
+
# 运行演示
|
|
95
|
+
demo_paste_functionality()
|
|
@@ -0,0 +1,200 @@
|
|
|
1
|
+
"""Terminal paste event handler and placeholder resolver."""
|
|
2
|
+
|
|
3
|
+
import re
|
|
4
|
+
from typing import Optional, Callable
|
|
5
|
+
from prompt_toolkit.key_binding import KeyBindings
|
|
6
|
+
from prompt_toolkit.application import get_app
|
|
7
|
+
from prompt_toolkit.clipboard import ClipboardData
|
|
8
|
+
from prompt_toolkit.keys import Keys
|
|
9
|
+
from .paste_manager import PasteManager
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
# Global paste manager instance
|
|
13
|
+
_paste_manager: Optional[PasteManager] = None
|
|
14
|
+
|
|
15
|
+
# 占位符正则表达式,匹配 [pasted-<uuid>] 格式(32位十六进制,无连字符)
|
|
16
|
+
PLACEHOLDER_PATTERN = re.compile(r"\[pasted-([0-9a-f]{32})\]")
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
def get_paste_manager() -> PasteManager:
|
|
20
|
+
"""Get or create global paste manager instance."""
|
|
21
|
+
global _paste_manager
|
|
22
|
+
if _paste_manager is None:
|
|
23
|
+
_paste_manager = PasteManager()
|
|
24
|
+
return _paste_manager
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
def register_paste_handler(kb: KeyBindings) -> None:
|
|
28
|
+
"""Register paste handler with prompt_toolkit key bindings.
|
|
29
|
+
|
|
30
|
+
Args:
|
|
31
|
+
kb: KeyBindings instance to register with
|
|
32
|
+
|
|
33
|
+
Note:
|
|
34
|
+
This function sets up a custom paste handler that intercepts multi-line
|
|
35
|
+
paste operations and saves them to files with placeholder replacement.
|
|
36
|
+
|
|
37
|
+
Supports multiple paste methods:
|
|
38
|
+
- Bracketed paste (automatic detection of pasted content)
|
|
39
|
+
- Ctrl+V (standard paste shortcut)
|
|
40
|
+
- Ctrl+P (legacy binding)
|
|
41
|
+
- Cmd+V (Mac paste shortcut, mapped as Meta+V)
|
|
42
|
+
"""
|
|
43
|
+
|
|
44
|
+
def paste_handler_impl(event):
|
|
45
|
+
"""Handle paste operations with file saving for multi-line content."""
|
|
46
|
+
try:
|
|
47
|
+
# Get the current application
|
|
48
|
+
app = event.app
|
|
49
|
+
|
|
50
|
+
# Get clipboard content
|
|
51
|
+
clipboard_data = app.clipboard.get_data()
|
|
52
|
+
if not clipboard_data:
|
|
53
|
+
return
|
|
54
|
+
|
|
55
|
+
text = clipboard_data.text
|
|
56
|
+
if not text:
|
|
57
|
+
return
|
|
58
|
+
|
|
59
|
+
# Check if it's multi-line content (more than 1 line)
|
|
60
|
+
lines = text.splitlines()
|
|
61
|
+
if len(lines) > 1:
|
|
62
|
+
# Save multi-line content to file and insert placeholder
|
|
63
|
+
paste_manager = get_paste_manager()
|
|
64
|
+
file_id = paste_manager.save_paste(text)
|
|
65
|
+
|
|
66
|
+
# Create placeholder - file_id already contains "pasted-" prefix
|
|
67
|
+
placeholder = f"[{file_id}]"
|
|
68
|
+
|
|
69
|
+
# Insert placeholder instead of actual content
|
|
70
|
+
event.current_buffer.insert_text(placeholder)
|
|
71
|
+
else:
|
|
72
|
+
# For single-line content, just paste normally
|
|
73
|
+
event.current_buffer.insert_text(text)
|
|
74
|
+
|
|
75
|
+
except Exception as e:
|
|
76
|
+
print(f"\033[91m✗ Error in paste handler: {e}\033[0m")
|
|
77
|
+
# Fall back to normal paste behavior
|
|
78
|
+
try:
|
|
79
|
+
clipboard_data = event.app.clipboard.get_data()
|
|
80
|
+
if clipboard_data and clipboard_data.text:
|
|
81
|
+
event.current_buffer.insert_text(clipboard_data.text)
|
|
82
|
+
except:
|
|
83
|
+
pass
|
|
84
|
+
|
|
85
|
+
# Bind to bracketed paste event (most reliable for all paste operations)
|
|
86
|
+
@kb.add(Keys.BracketedPaste)
|
|
87
|
+
def bracketed_paste_handler(event):
|
|
88
|
+
"""Handle bracketed paste events (automatic paste detection)."""
|
|
89
|
+
try:
|
|
90
|
+
# For bracketed paste, the pasted text is directly available in event.data
|
|
91
|
+
text = event.data
|
|
92
|
+
if not text:
|
|
93
|
+
return
|
|
94
|
+
|
|
95
|
+
# Check if it's multi-line content (more than 1 line)
|
|
96
|
+
lines = text.splitlines()
|
|
97
|
+
if len(lines) > 1:
|
|
98
|
+
# Save multi-line content to file and insert placeholder
|
|
99
|
+
paste_manager = get_paste_manager()
|
|
100
|
+
file_id = paste_manager.save_paste(text)
|
|
101
|
+
|
|
102
|
+
# Create placeholder - file_id already contains "pasted-" prefix
|
|
103
|
+
placeholder = f"[{file_id}]"
|
|
104
|
+
|
|
105
|
+
# Insert placeholder instead of actual content
|
|
106
|
+
event.current_buffer.insert_text(placeholder)
|
|
107
|
+
else:
|
|
108
|
+
# For single-line content, just paste normally
|
|
109
|
+
event.current_buffer.insert_text(text)
|
|
110
|
+
|
|
111
|
+
except Exception as e:
|
|
112
|
+
print(f"\033[91m✗ Error in bracketed paste handler: {e}\033[0m")
|
|
113
|
+
# Fall back to inserting the text directly
|
|
114
|
+
try:
|
|
115
|
+
if hasattr(event, 'data') and event.data:
|
|
116
|
+
event.current_buffer.insert_text(event.data)
|
|
117
|
+
except:
|
|
118
|
+
pass
|
|
119
|
+
|
|
120
|
+
# Bind to standard paste shortcuts as backup
|
|
121
|
+
@kb.add('c-v') # Ctrl+V (standard paste)
|
|
122
|
+
def ctrl_v_paste_handler(event):
|
|
123
|
+
"""Handle Ctrl+V paste events."""
|
|
124
|
+
paste_handler_impl(event)
|
|
125
|
+
|
|
126
|
+
@kb.add('c-p') # Ctrl+P (legacy binding)
|
|
127
|
+
def ctrl_p_paste_handler(event):
|
|
128
|
+
"""Handle Ctrl+P paste events (legacy)."""
|
|
129
|
+
paste_handler_impl(event)
|
|
130
|
+
|
|
131
|
+
# For Mac users: Cmd+V is often mapped as Meta+V in terminals
|
|
132
|
+
@kb.add('escape', 'v') # Meta+V (often mapped from Cmd+V on Mac)
|
|
133
|
+
def meta_v_paste_handler(event):
|
|
134
|
+
"""Handle Meta+V paste events (Mac Cmd+V equivalent)."""
|
|
135
|
+
paste_handler_impl(event)
|
|
136
|
+
|
|
137
|
+
|
|
138
|
+
def resolve_paste_placeholders(text: str) -> str:
|
|
139
|
+
"""Resolve paste placeholders in text to actual content.
|
|
140
|
+
|
|
141
|
+
Args:
|
|
142
|
+
text: Input text that may contain placeholders
|
|
143
|
+
|
|
144
|
+
Returns:
|
|
145
|
+
Text with placeholders replaced by actual content
|
|
146
|
+
"""
|
|
147
|
+
if not text or "[pasted-" not in text:
|
|
148
|
+
return text
|
|
149
|
+
|
|
150
|
+
paste_manager = get_paste_manager()
|
|
151
|
+
|
|
152
|
+
def replace_placeholder(match) -> str:
|
|
153
|
+
"""Replace a single placeholder with its content."""
|
|
154
|
+
uuid_part = match.group(1) # Extract UUID from [pasted-<uuid>]
|
|
155
|
+
file_id = f"pasted-{uuid_part}" # Reconstruct full file_id
|
|
156
|
+
|
|
157
|
+
try:
|
|
158
|
+
content = paste_manager.read_paste(file_id)
|
|
159
|
+
if content is not None:
|
|
160
|
+
return content
|
|
161
|
+
else:
|
|
162
|
+
# File not found, keep placeholder for debugging
|
|
163
|
+
print(f"\033[93m⚠ Paste file not found: {file_id}\033[0m")
|
|
164
|
+
return match.group(0)
|
|
165
|
+
except Exception as e:
|
|
166
|
+
print(f"\033[91m✗ Error reading paste file: {e}\033[0m")
|
|
167
|
+
return match.group(0)
|
|
168
|
+
|
|
169
|
+
# Replace all placeholders in the text
|
|
170
|
+
resolved_text = PLACEHOLDER_PATTERN.sub(replace_placeholder, text)
|
|
171
|
+
|
|
172
|
+
# Show user if any replacements were made
|
|
173
|
+
if resolved_text != text:
|
|
174
|
+
placeholder_count = len(PLACEHOLDER_PATTERN.findall(text))
|
|
175
|
+
print(f"\033[92m✓ Resolved {placeholder_count} paste placeholder(s)\033[0m")
|
|
176
|
+
|
|
177
|
+
return resolved_text
|
|
178
|
+
|
|
179
|
+
|
|
180
|
+
def cleanup_old_pastes(max_age_hours: int = 24) -> int:
|
|
181
|
+
"""Clean up old paste files.
|
|
182
|
+
|
|
183
|
+
Args:
|
|
184
|
+
max_age_hours: Maximum age in hours for paste files
|
|
185
|
+
|
|
186
|
+
Returns:
|
|
187
|
+
Number of files cleaned up
|
|
188
|
+
"""
|
|
189
|
+
paste_manager = get_paste_manager()
|
|
190
|
+
return paste_manager.cleanup_old_pastes(max_age_hours)
|
|
191
|
+
|
|
192
|
+
|
|
193
|
+
def list_paste_files() -> list[str]:
|
|
194
|
+
"""List all paste file IDs.
|
|
195
|
+
|
|
196
|
+
Returns:
|
|
197
|
+
List of paste file IDs
|
|
198
|
+
"""
|
|
199
|
+
paste_manager = get_paste_manager()
|
|
200
|
+
return paste_manager.list_pastes()
|
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
"""Paste manager for handling paste file operations."""
|
|
2
|
+
|
|
3
|
+
import os
|
|
4
|
+
import uuid
|
|
5
|
+
from typing import Optional
|
|
6
|
+
from pathlib import Path
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
class PasteManager:
|
|
10
|
+
"""Manager for handling paste file operations."""
|
|
11
|
+
|
|
12
|
+
def __init__(self, base_dir: Optional[str] = None):
|
|
13
|
+
"""Initialize paste manager.
|
|
14
|
+
|
|
15
|
+
Args:
|
|
16
|
+
base_dir: Base directory for paste files. If None, uses current working directory.
|
|
17
|
+
"""
|
|
18
|
+
self.base_dir = base_dir or os.getcwd()
|
|
19
|
+
self.paste_dir = os.path.join(self.base_dir, ".auto-coder", "pastes")
|
|
20
|
+
self._ensure_paste_dir()
|
|
21
|
+
|
|
22
|
+
def _ensure_paste_dir(self) -> None:
|
|
23
|
+
"""Ensure paste directory exists."""
|
|
24
|
+
os.makedirs(self.paste_dir, exist_ok=True)
|
|
25
|
+
|
|
26
|
+
def save_paste(self, content: str) -> str:
|
|
27
|
+
"""Save paste content to file and return file ID.
|
|
28
|
+
|
|
29
|
+
Args:
|
|
30
|
+
content: Content to save
|
|
31
|
+
|
|
32
|
+
Returns:
|
|
33
|
+
File ID (without path)
|
|
34
|
+
"""
|
|
35
|
+
file_id = f"pasted-{uuid.uuid4().hex}"
|
|
36
|
+
file_path = os.path.join(self.paste_dir, file_id)
|
|
37
|
+
|
|
38
|
+
try:
|
|
39
|
+
with open(file_path, "w", encoding="utf-8") as f:
|
|
40
|
+
f.write(content)
|
|
41
|
+
return file_id
|
|
42
|
+
except Exception as e:
|
|
43
|
+
raise RuntimeError(f"Failed to save paste content: {e}")
|
|
44
|
+
|
|
45
|
+
def read_paste(self, file_id: str) -> Optional[str]:
|
|
46
|
+
"""Read paste content from file.
|
|
47
|
+
|
|
48
|
+
Args:
|
|
49
|
+
file_id: File ID to read
|
|
50
|
+
|
|
51
|
+
Returns:
|
|
52
|
+
File content or None if file not found
|
|
53
|
+
"""
|
|
54
|
+
# Handle both "pasted-<uuid>" and just "<uuid>" formats
|
|
55
|
+
if not file_id.startswith("pasted-"):
|
|
56
|
+
file_id = f"pasted-{file_id}"
|
|
57
|
+
|
|
58
|
+
file_path = os.path.join(self.paste_dir, file_id)
|
|
59
|
+
|
|
60
|
+
try:
|
|
61
|
+
with open(file_path, "r", encoding="utf-8") as f:
|
|
62
|
+
return f.read()
|
|
63
|
+
except FileNotFoundError:
|
|
64
|
+
return None
|
|
65
|
+
except Exception as e:
|
|
66
|
+
raise RuntimeError(f"Failed to read paste file {file_id}: {e}")
|
|
67
|
+
|
|
68
|
+
def cleanup_old_pastes(self, max_age_hours: int = 24) -> int:
|
|
69
|
+
"""Clean up old paste files.
|
|
70
|
+
|
|
71
|
+
Args:
|
|
72
|
+
max_age_hours: Maximum age in hours for paste files
|
|
73
|
+
|
|
74
|
+
Returns:
|
|
75
|
+
Number of files cleaned up
|
|
76
|
+
"""
|
|
77
|
+
import time
|
|
78
|
+
|
|
79
|
+
if not os.path.exists(self.paste_dir):
|
|
80
|
+
return 0
|
|
81
|
+
|
|
82
|
+
current_time = time.time()
|
|
83
|
+
max_age_seconds = max_age_hours * 3600
|
|
84
|
+
cleaned_count = 0
|
|
85
|
+
|
|
86
|
+
try:
|
|
87
|
+
for filename in os.listdir(self.paste_dir):
|
|
88
|
+
if filename.startswith("pasted-"):
|
|
89
|
+
file_path = os.path.join(self.paste_dir, filename)
|
|
90
|
+
if os.path.isfile(file_path):
|
|
91
|
+
file_age = current_time - os.path.getmtime(file_path)
|
|
92
|
+
if file_age > max_age_seconds:
|
|
93
|
+
os.remove(file_path)
|
|
94
|
+
cleaned_count += 1
|
|
95
|
+
except Exception as e:
|
|
96
|
+
raise RuntimeError(f"Failed to cleanup old pastes: {e}")
|
|
97
|
+
|
|
98
|
+
return cleaned_count
|
|
99
|
+
|
|
100
|
+
def list_pastes(self) -> list[str]:
|
|
101
|
+
"""List all paste file IDs.
|
|
102
|
+
|
|
103
|
+
Returns:
|
|
104
|
+
List of paste file IDs
|
|
105
|
+
"""
|
|
106
|
+
if not os.path.exists(self.paste_dir):
|
|
107
|
+
return []
|
|
108
|
+
|
|
109
|
+
try:
|
|
110
|
+
files = []
|
|
111
|
+
for filename in os.listdir(self.paste_dir):
|
|
112
|
+
if filename.startswith("pasted-") and os.path.isfile(
|
|
113
|
+
os.path.join(self.paste_dir, filename)
|
|
114
|
+
):
|
|
115
|
+
files.append(filename)
|
|
116
|
+
return sorted(files)
|
|
117
|
+
except Exception as e:
|
|
118
|
+
raise RuntimeError(f"Failed to list paste files: {e}")
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
"""Test module for terminal_paste."""
|