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.

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