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.

Files changed (574) hide show
  1. auto_coder-2.0.1.dist-info/LICENSE +158 -0
  2. auto_coder-2.0.1.dist-info/METADATA +558 -0
  3. auto_coder-2.0.1.dist-info/RECORD +795 -0
  4. {auto_coder-1.0.0.dist-info → auto_coder-2.0.1.dist-info}/WHEEL +1 -1
  5. {auto_coder-1.0.0.dist-info → auto_coder-2.0.1.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 +24 -3
  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 +77 -73
  19. autocoder/auto_coder.py +31 -40
  20. autocoder/auto_coder_rag.py +11 -1084
  21. autocoder/auto_coder_runner.py +962 -2345
  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 +988 -398
  28. autocoder/chat_auto_coder_lang.py +23 -732
  29. autocoder/commands/auto_command.py +25 -8
  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 +409 -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/git_utils.py +44 -8
  119. autocoder/common/global_cancel.py +15 -6
  120. autocoder/common/ignorefiles/test_ignore_file_utils.py +1 -1
  121. autocoder/common/international/__init__.py +31 -0
  122. autocoder/common/international/demo_international.py +92 -0
  123. autocoder/common/international/message_manager.py +157 -0
  124. autocoder/common/international/messages/__init__.py +56 -0
  125. autocoder/common/international/messages/async_command_messages.py +507 -0
  126. autocoder/common/international/messages/auto_coder_messages.py +2208 -0
  127. autocoder/common/international/messages/chat_auto_coder_messages.py +1547 -0
  128. autocoder/common/international/messages/command_help_messages.py +986 -0
  129. autocoder/common/international/messages/conversation_command_messages.py +191 -0
  130. autocoder/common/international/messages/git_helper_plugin_messages.py +159 -0
  131. autocoder/common/international/messages/queue_command_messages.py +751 -0
  132. autocoder/common/international/messages/rules_command_messages.py +77 -0
  133. autocoder/common/international/messages/sdk_messages.py +1707 -0
  134. autocoder/common/international/messages/token_helper_plugin_messages.py +361 -0
  135. autocoder/common/international/messages/tool_display_messages.py +1212 -0
  136. autocoder/common/international/messages/workflow_exception_messages.py +473 -0
  137. autocoder/common/international/test_international.py +612 -0
  138. autocoder/common/linter_core/__init__.py +28 -0
  139. autocoder/common/linter_core/base_linter.py +61 -0
  140. autocoder/common/linter_core/config_loader.py +271 -0
  141. autocoder/common/linter_core/formatters/__init__.py +0 -0
  142. autocoder/common/linter_core/formatters/base_formatter.py +38 -0
  143. autocoder/common/linter_core/formatters/raw_formatter.py +17 -0
  144. autocoder/common/linter_core/linter.py +166 -0
  145. autocoder/common/linter_core/linter_factory.py +216 -0
  146. autocoder/common/linter_core/linter_manager.py +333 -0
  147. autocoder/common/linter_core/linters/__init__.py +9 -0
  148. autocoder/common/linter_core/linters/java_linter.py +342 -0
  149. autocoder/common/linter_core/linters/python_linter.py +115 -0
  150. autocoder/common/linter_core/linters/typescript_linter.py +119 -0
  151. autocoder/common/linter_core/models/__init__.py +7 -0
  152. autocoder/common/linter_core/models/lint_result.py +91 -0
  153. autocoder/common/linter_core/models.py +33 -0
  154. autocoder/common/linter_core/tests/__init__.py +3 -0
  155. autocoder/common/linter_core/tests/test_config_loader.py +323 -0
  156. autocoder/common/linter_core/tests/test_config_loading.py +308 -0
  157. autocoder/common/linter_core/tests/test_factory_manager.py +234 -0
  158. autocoder/common/linter_core/tests/test_formatters.py +147 -0
  159. autocoder/common/linter_core/tests/test_integration.py +317 -0
  160. autocoder/common/linter_core/tests/test_java_linter.py +496 -0
  161. autocoder/common/linter_core/tests/test_linters.py +265 -0
  162. autocoder/common/linter_core/tests/test_models.py +81 -0
  163. autocoder/common/linter_core/tests/verify_config_loading.py +296 -0
  164. autocoder/common/linter_core/tests/verify_fixes.py +183 -0
  165. autocoder/common/llm_friendly_package/__init__.py +31 -0
  166. autocoder/common/llm_friendly_package/base_manager.py +102 -0
  167. autocoder/common/llm_friendly_package/docs_manager.py +121 -0
  168. autocoder/common/llm_friendly_package/library_manager.py +171 -0
  169. autocoder/common/{llm_friendly_package.py → llm_friendly_package/main_manager.py} +204 -231
  170. autocoder/common/llm_friendly_package/models.py +40 -0
  171. autocoder/common/llm_friendly_package/test_llm_friendly_package.py +536 -0
  172. autocoder/common/llms/__init__.py +15 -0
  173. autocoder/common/llms/demo_error_handling.py +85 -0
  174. autocoder/common/llms/factory.py +142 -0
  175. autocoder/common/llms/manager.py +264 -0
  176. autocoder/common/llms/pricing.py +121 -0
  177. autocoder/common/llms/registry.py +316 -0
  178. autocoder/common/llms/schema.py +77 -0
  179. autocoder/common/llms/simple_demo.py +45 -0
  180. autocoder/common/llms/test_quick_model.py +116 -0
  181. autocoder/common/llms/test_remove_functionality.py +182 -0
  182. autocoder/common/llms/tests/__init__.py +1 -0
  183. autocoder/common/llms/tests/test_manager.py +330 -0
  184. autocoder/common/llms/tests/test_registry.py +364 -0
  185. autocoder/common/mcp_tools/__init__.py +62 -0
  186. autocoder/common/{mcp_tools.py → mcp_tools/executor.py} +49 -40
  187. autocoder/common/{mcp_hub.py → mcp_tools/hub.py} +42 -68
  188. autocoder/common/{mcp_server_install.py → mcp_tools/installer.py} +16 -28
  189. autocoder/common/{mcp_server.py → mcp_tools/server.py} +176 -48
  190. autocoder/common/mcp_tools/test_keyboard_interrupt.py +93 -0
  191. autocoder/common/mcp_tools/test_mcp_tools.py +391 -0
  192. autocoder/common/{mcp_server_types.py → mcp_tools/types.py} +121 -48
  193. autocoder/common/mcp_tools/verify_functionality.py +202 -0
  194. autocoder/common/model_speed_tester.py +32 -26
  195. autocoder/common/priority_directory_finder/__init__.py +142 -0
  196. autocoder/common/priority_directory_finder/examples.py +230 -0
  197. autocoder/common/priority_directory_finder/finder.py +283 -0
  198. autocoder/common/priority_directory_finder/models.py +236 -0
  199. autocoder/common/priority_directory_finder/test_priority_directory_finder.py +431 -0
  200. autocoder/common/project_scanner/__init__.py +18 -0
  201. autocoder/common/project_scanner/compat.py +77 -0
  202. autocoder/common/project_scanner/scanner.py +436 -0
  203. autocoder/common/project_tracker/__init__.py +27 -0
  204. autocoder/common/project_tracker/api.py +228 -0
  205. autocoder/common/project_tracker/demo.py +272 -0
  206. autocoder/common/project_tracker/tracker.py +487 -0
  207. autocoder/common/project_tracker/types.py +53 -0
  208. autocoder/common/pruner/__init__.py +67 -0
  209. autocoder/common/pruner/agentic_conversation_pruner.py +651 -102
  210. autocoder/common/pruner/conversation_message_ids_api.py +386 -0
  211. autocoder/common/pruner/conversation_message_ids_manager.py +347 -0
  212. autocoder/common/pruner/conversation_message_ids_pruner.py +473 -0
  213. autocoder/common/pruner/conversation_normalizer.py +347 -0
  214. autocoder/common/pruner/conversation_pruner.py +26 -6
  215. autocoder/common/pruner/test_agentic_conversation_pruner.py +554 -112
  216. autocoder/common/pruner/test_conversation_normalizer.py +502 -0
  217. autocoder/common/pruner/test_tool_content_detector.py +324 -0
  218. autocoder/common/pruner/tool_content_detector.py +227 -0
  219. autocoder/common/pruner/tools/__init__.py +18 -0
  220. autocoder/common/pruner/tools/query_message_ids.py +264 -0
  221. autocoder/common/pruner/tools/test_agentic_pruning_logic.py +432 -0
  222. autocoder/common/pruner/tools/test_message_ids_pruning_only.py +192 -0
  223. autocoder/common/pull_requests/__init__.py +9 -1
  224. autocoder/common/pull_requests/utils.py +122 -1
  225. autocoder/common/rag_manager/rag_manager.py +36 -40
  226. autocoder/common/rulefiles/__init__.py +53 -1
  227. autocoder/common/rulefiles/api.py +250 -0
  228. autocoder/common/rulefiles/core/__init__.py +14 -0
  229. autocoder/common/rulefiles/core/manager.py +241 -0
  230. autocoder/common/rulefiles/core/selector.py +805 -0
  231. autocoder/common/rulefiles/models/__init__.py +20 -0
  232. autocoder/common/rulefiles/models/index.py +16 -0
  233. autocoder/common/rulefiles/models/init_rule.py +18 -0
  234. autocoder/common/rulefiles/models/rule_file.py +18 -0
  235. autocoder/common/rulefiles/models/rule_relevance.py +14 -0
  236. autocoder/common/rulefiles/models/summary.py +16 -0
  237. autocoder/common/rulefiles/test_rulefiles.py +776 -0
  238. autocoder/common/rulefiles/utils/__init__.py +34 -0
  239. autocoder/common/rulefiles/utils/monitor.py +86 -0
  240. autocoder/common/rulefiles/utils/parser.py +230 -0
  241. autocoder/common/save_formatted_log.py +67 -10
  242. autocoder/common/search_replace.py +8 -1
  243. autocoder/common/search_replace_patch/__init__.py +24 -0
  244. autocoder/common/search_replace_patch/base.py +115 -0
  245. autocoder/common/search_replace_patch/manager.py +248 -0
  246. autocoder/common/search_replace_patch/patch_replacer.py +304 -0
  247. autocoder/common/search_replace_patch/similarity_replacer.py +306 -0
  248. autocoder/common/search_replace_patch/string_replacer.py +181 -0
  249. autocoder/common/search_replace_patch/tests/__init__.py +3 -0
  250. autocoder/common/search_replace_patch/tests/run_tests.py +126 -0
  251. autocoder/common/search_replace_patch/tests/test_base.py +188 -0
  252. autocoder/common/search_replace_patch/tests/test_empty_line_insert.py +233 -0
  253. autocoder/common/search_replace_patch/tests/test_integration.py +389 -0
  254. autocoder/common/search_replace_patch/tests/test_manager.py +351 -0
  255. autocoder/common/search_replace_patch/tests/test_patch_replacer.py +316 -0
  256. autocoder/common/search_replace_patch/tests/test_regex_replacer.py +306 -0
  257. autocoder/common/search_replace_patch/tests/test_similarity_replacer.py +384 -0
  258. autocoder/common/shell_commands/__init__.py +197 -0
  259. autocoder/common/shell_commands/background_process_notifier.py +346 -0
  260. autocoder/common/shell_commands/command_executor.py +1127 -0
  261. autocoder/common/shell_commands/error_recovery.py +541 -0
  262. autocoder/common/shell_commands/exceptions.py +120 -0
  263. autocoder/common/shell_commands/interactive_executor.py +476 -0
  264. autocoder/common/shell_commands/interactive_pexpect_process.py +623 -0
  265. autocoder/common/shell_commands/interactive_process.py +744 -0
  266. autocoder/common/shell_commands/interactive_session_manager.py +1014 -0
  267. autocoder/common/shell_commands/monitoring.py +529 -0
  268. autocoder/common/shell_commands/process_cleanup.py +386 -0
  269. autocoder/common/shell_commands/process_manager.py +606 -0
  270. autocoder/common/shell_commands/test_interactive_pexpect_process.py +281 -0
  271. autocoder/common/shell_commands/tests/__init__.py +6 -0
  272. autocoder/common/shell_commands/tests/conftest.py +118 -0
  273. autocoder/common/shell_commands/tests/test_background_process_notifier.py +703 -0
  274. autocoder/common/shell_commands/tests/test_command_executor.py +448 -0
  275. autocoder/common/shell_commands/tests/test_error_recovery.py +305 -0
  276. autocoder/common/shell_commands/tests/test_exceptions.py +299 -0
  277. autocoder/common/shell_commands/tests/test_execute_batch.py +588 -0
  278. autocoder/common/shell_commands/tests/test_indented_batch_commands.py +244 -0
  279. autocoder/common/shell_commands/tests/test_integration.py +664 -0
  280. autocoder/common/shell_commands/tests/test_monitoring.py +546 -0
  281. autocoder/common/shell_commands/tests/test_performance.py +632 -0
  282. autocoder/common/shell_commands/tests/test_process_cleanup.py +397 -0
  283. autocoder/common/shell_commands/tests/test_process_manager.py +606 -0
  284. autocoder/common/shell_commands/tests/test_timeout_config.py +343 -0
  285. autocoder/common/shell_commands/tests/test_timeout_manager.py +520 -0
  286. autocoder/common/shell_commands/timeout_config.py +315 -0
  287. autocoder/common/shell_commands/timeout_manager.py +352 -0
  288. autocoder/common/terminal_paste/__init__.py +14 -0
  289. autocoder/common/terminal_paste/demo.py +145 -0
  290. autocoder/common/terminal_paste/demo_paste_functionality.py +95 -0
  291. autocoder/common/terminal_paste/paste_handler.py +200 -0
  292. autocoder/common/terminal_paste/paste_manager.py +118 -0
  293. autocoder/common/terminal_paste/tests/__init__.py +1 -0
  294. autocoder/common/terminal_paste/tests/test_paste_handler.py +182 -0
  295. autocoder/common/terminal_paste/tests/test_paste_manager.py +126 -0
  296. autocoder/common/terminal_paste/utils.py +163 -0
  297. autocoder/common/test_autocoder_args.py +232 -0
  298. autocoder/common/test_env_manager.py +173 -0
  299. autocoder/common/test_env_manager_integration.py +159 -0
  300. autocoder/common/text_similarity/__init__.py +9 -0
  301. autocoder/common/text_similarity/demo.py +216 -0
  302. autocoder/common/text_similarity/examples.py +266 -0
  303. autocoder/common/text_similarity/test_text_similarity.py +306 -0
  304. autocoder/common/text_similarity/text_similarity.py +194 -0
  305. autocoder/common/text_similarity/utils.py +125 -0
  306. autocoder/common/todos/__init__.py +61 -0
  307. autocoder/common/todos/cache/__init__.py +16 -0
  308. autocoder/common/todos/cache/base_cache.py +89 -0
  309. autocoder/common/todos/cache/cache_manager.py +228 -0
  310. autocoder/common/todos/cache/memory_cache.py +225 -0
  311. autocoder/common/todos/config.py +155 -0
  312. autocoder/common/todos/exceptions.py +35 -0
  313. autocoder/common/todos/get_todo_manager.py +161 -0
  314. autocoder/common/todos/manager.py +537 -0
  315. autocoder/common/todos/models.py +239 -0
  316. autocoder/common/todos/storage/__init__.py +14 -0
  317. autocoder/common/todos/storage/base_storage.py +76 -0
  318. autocoder/common/todos/storage/file_storage.py +278 -0
  319. autocoder/common/tokens/counter.py +24 -2
  320. autocoder/common/tools_manager/__init__.py +17 -0
  321. autocoder/common/tools_manager/examples.py +162 -0
  322. autocoder/common/tools_manager/manager.py +385 -0
  323. autocoder/common/tools_manager/models.py +39 -0
  324. autocoder/common/tools_manager/test_tools_manager.py +303 -0
  325. autocoder/common/tools_manager/utils.py +191 -0
  326. autocoder/common/v2/agent/agentic_callbacks.py +270 -0
  327. autocoder/common/v2/agent/agentic_edit.py +2699 -1856
  328. autocoder/common/v2/agent/agentic_edit_change_manager.py +474 -0
  329. autocoder/common/v2/agent/agentic_edit_tools/__init__.py +35 -1
  330. autocoder/common/v2/agent/agentic_edit_tools/ac_mod_list_tool_resolver.py +279 -0
  331. autocoder/common/v2/agent/agentic_edit_tools/ac_mod_write_tool_resolver.py +10 -1
  332. autocoder/common/v2/agent/agentic_edit_tools/background_task_tool_resolver.py +1167 -0
  333. autocoder/common/v2/agent/agentic_edit_tools/base_tool_resolver.py +2 -2
  334. autocoder/common/v2/agent/agentic_edit_tools/conversation_message_ids_read_tool_resolver.py +214 -0
  335. autocoder/common/v2/agent/agentic_edit_tools/conversation_message_ids_write_tool_resolver.py +299 -0
  336. autocoder/common/v2/agent/agentic_edit_tools/count_tokens_tool_resolver.py +290 -0
  337. autocoder/common/v2/agent/agentic_edit_tools/execute_command_tool_resolver.py +564 -29
  338. autocoder/common/v2/agent/agentic_edit_tools/execute_workflow_tool_resolver.py +485 -0
  339. autocoder/common/v2/agent/agentic_edit_tools/extract_to_text_tool_resolver.py +225 -0
  340. autocoder/common/v2/agent/agentic_edit_tools/lint_report.py +79 -0
  341. autocoder/common/v2/agent/agentic_edit_tools/linter_config_models.py +343 -0
  342. autocoder/common/v2/agent/agentic_edit_tools/linter_enabled_tool_resolver.py +189 -0
  343. autocoder/common/v2/agent/agentic_edit_tools/list_files_tool_resolver.py +169 -101
  344. autocoder/common/v2/agent/agentic_edit_tools/load_extra_document_tool_resolver.py +356 -0
  345. autocoder/common/v2/agent/agentic_edit_tools/read_file_tool_resolver.py +243 -50
  346. autocoder/common/v2/agent/agentic_edit_tools/replace_in_file_tool_resolver.py +667 -147
  347. autocoder/common/v2/agent/agentic_edit_tools/run_named_subagents_tool_resolver.py +691 -0
  348. autocoder/common/v2/agent/agentic_edit_tools/search_files_tool_resolver.py +410 -86
  349. autocoder/common/v2/agent/agentic_edit_tools/session_interactive_tool_resolver.py +115 -0
  350. autocoder/common/v2/agent/agentic_edit_tools/session_start_tool_resolver.py +190 -0
  351. autocoder/common/v2/agent/agentic_edit_tools/session_stop_tool_resolver.py +76 -0
  352. autocoder/common/v2/agent/agentic_edit_tools/test_write_to_file_tool_resolver.py +207 -192
  353. autocoder/common/v2/agent/agentic_edit_tools/todo_read_tool_resolver.py +80 -63
  354. autocoder/common/v2/agent/agentic_edit_tools/todo_write_tool_resolver.py +237 -233
  355. autocoder/common/v2/agent/agentic_edit_tools/use_mcp_tool_resolver.py +2 -2
  356. autocoder/common/v2/agent/agentic_edit_tools/web_crawl_tool_resolver.py +557 -0
  357. autocoder/common/v2/agent/agentic_edit_tools/web_search_tool_resolver.py +600 -0
  358. autocoder/common/v2/agent/agentic_edit_tools/write_to_file_tool_resolver.py +56 -121
  359. autocoder/common/v2/agent/agentic_edit_types.py +343 -9
  360. autocoder/common/v2/agent/runner/__init__.py +3 -3
  361. autocoder/common/v2/agent/runner/base_runner.py +12 -26
  362. autocoder/common/v2/agent/runner/{event_runner.py → file_based_event_runner.py} +3 -2
  363. autocoder/common/v2/agent/runner/sdk_runner.py +150 -8
  364. autocoder/common/v2/agent/runner/terminal_runner.py +170 -57
  365. autocoder/common/v2/agent/runner/tool_display.py +557 -159
  366. autocoder/common/v2/agent/test_agentic_callbacks.py +265 -0
  367. autocoder/common/v2/agent/test_agentic_edit.py +194 -0
  368. autocoder/common/v2/agent/tool_caller/__init__.py +24 -0
  369. autocoder/common/v2/agent/tool_caller/default_tool_resolver_map.py +135 -0
  370. autocoder/common/v2/agent/tool_caller/integration_test.py +172 -0
  371. autocoder/common/v2/agent/tool_caller/plugins/__init__.py +14 -0
  372. autocoder/common/v2/agent/tool_caller/plugins/base_plugin.py +126 -0
  373. autocoder/common/v2/agent/tool_caller/plugins/examples/__init__.py +13 -0
  374. autocoder/common/v2/agent/tool_caller/plugins/examples/logging_plugin.py +164 -0
  375. autocoder/common/v2/agent/tool_caller/plugins/examples/security_filter_plugin.py +198 -0
  376. autocoder/common/v2/agent/tool_caller/plugins/plugin_interface.py +141 -0
  377. autocoder/common/v2/agent/tool_caller/test_tool_caller.py +278 -0
  378. autocoder/common/v2/agent/tool_caller/tool_call_plugin_manager.py +331 -0
  379. autocoder/common/v2/agent/tool_caller/tool_caller.py +337 -0
  380. autocoder/common/v2/agent/tool_caller/usage_example.py +193 -0
  381. autocoder/common/v2/code_agentic_editblock_manager.py +4 -4
  382. autocoder/common/v2/code_auto_generate.py +136 -78
  383. autocoder/common/v2/code_auto_generate_diff.py +135 -79
  384. autocoder/common/v2/code_auto_generate_editblock.py +174 -99
  385. autocoder/common/v2/code_auto_generate_strict_diff.py +151 -71
  386. autocoder/common/v2/code_auto_merge.py +1 -1
  387. autocoder/common/v2/code_auto_merge_editblock.py +13 -1
  388. autocoder/common/v2/code_diff_manager.py +3 -3
  389. autocoder/common/v2/code_editblock_manager.py +4 -14
  390. autocoder/common/v2/code_manager.py +1 -1
  391. autocoder/common/v2/code_strict_diff_manager.py +2 -2
  392. autocoder/common/wrap_llm_hint/__init__.py +10 -0
  393. autocoder/common/wrap_llm_hint/test_wrap_llm_hint.py +1067 -0
  394. autocoder/common/wrap_llm_hint/utils.py +432 -0
  395. autocoder/common/wrap_llm_hint/wrap_llm_hint.py +323 -0
  396. autocoder/completer/__init__.py +8 -0
  397. autocoder/completer/command_completer_v2.py +1094 -0
  398. autocoder/default_project/__init__.py +501 -0
  399. autocoder/dispacher/__init__.py +4 -12
  400. autocoder/dispacher/actions/action.py +400 -129
  401. autocoder/dispacher/actions/plugins/action_regex_project.py +2 -2
  402. autocoder/index/entry.py +117 -125
  403. autocoder/{agent → index/filter}/agentic_filter.py +322 -333
  404. autocoder/index/filter/normal_filter.py +5 -11
  405. autocoder/index/filter/quick_filter.py +1 -1
  406. autocoder/index/index.py +36 -9
  407. autocoder/index/tests/__init__.py +1 -0
  408. autocoder/index/tests/run_tests.py +195 -0
  409. autocoder/index/tests/test_entry.py +303 -0
  410. autocoder/index/tests/test_index_manager.py +314 -0
  411. autocoder/index/tests/test_module_integration.py +300 -0
  412. autocoder/index/tests/test_symbols_utils.py +183 -0
  413. autocoder/inner/__init__.py +4 -0
  414. autocoder/inner/agentic.py +923 -0
  415. autocoder/inner/async_command_handler.py +992 -0
  416. autocoder/inner/conversation_command_handlers.py +623 -0
  417. autocoder/inner/merge_command_handler.py +213 -0
  418. autocoder/inner/queue_command_handler.py +684 -0
  419. autocoder/models.py +95 -266
  420. autocoder/plugins/git_helper_plugin.py +31 -29
  421. autocoder/plugins/token_helper_plugin.py +65 -46
  422. autocoder/pyproject/__init__.py +32 -29
  423. autocoder/rag/agentic_rag.py +215 -75
  424. autocoder/rag/cache/simple_cache.py +1 -2
  425. autocoder/rag/loaders/image_loader.py +1 -1
  426. autocoder/rag/long_context_rag.py +42 -26
  427. autocoder/rag/qa_conversation_strategy.py +1 -1
  428. autocoder/rag/terminal/__init__.py +17 -0
  429. autocoder/rag/terminal/args.py +581 -0
  430. autocoder/rag/terminal/bootstrap.py +61 -0
  431. autocoder/rag/terminal/command_handlers.py +653 -0
  432. autocoder/rag/terminal/formatters/__init__.py +20 -0
  433. autocoder/rag/terminal/formatters/base.py +70 -0
  434. autocoder/rag/terminal/formatters/json_format.py +66 -0
  435. autocoder/rag/terminal/formatters/stream_json.py +95 -0
  436. autocoder/rag/terminal/formatters/text.py +28 -0
  437. autocoder/rag/terminal/init.py +120 -0
  438. autocoder/rag/terminal/utils.py +106 -0
  439. autocoder/rag/test_agentic_rag.py +389 -0
  440. autocoder/rag/test_doc_filter.py +3 -3
  441. autocoder/rag/test_long_context_rag.py +1 -1
  442. autocoder/rag/test_token_limiter.py +517 -10
  443. autocoder/rag/token_counter.py +3 -0
  444. autocoder/rag/token_limiter.py +19 -15
  445. autocoder/rag/tools/__init__.py +26 -2
  446. autocoder/rag/tools/bochaai_example.py +343 -0
  447. autocoder/rag/tools/bochaai_sdk.py +541 -0
  448. autocoder/rag/tools/metaso_example.py +268 -0
  449. autocoder/rag/tools/metaso_sdk.py +417 -0
  450. autocoder/rag/tools/recall_tool.py +28 -7
  451. autocoder/rag/tools/run_integration_tests.py +204 -0
  452. autocoder/rag/tools/test_all_providers.py +318 -0
  453. autocoder/rag/tools/test_bochaai_integration.py +482 -0
  454. autocoder/rag/tools/test_final_integration.py +215 -0
  455. autocoder/rag/tools/test_metaso_integration.py +424 -0
  456. autocoder/rag/tools/test_metaso_real.py +171 -0
  457. autocoder/rag/tools/test_web_crawl_tool.py +639 -0
  458. autocoder/rag/tools/test_web_search_tool.py +509 -0
  459. autocoder/rag/tools/todo_read_tool.py +202 -0
  460. autocoder/rag/tools/todo_write_tool.py +412 -0
  461. autocoder/rag/tools/web_crawl_tool.py +634 -0
  462. autocoder/rag/tools/web_search_tool.py +558 -0
  463. autocoder/rag/tools/web_tools_example.py +119 -0
  464. autocoder/rag/types.py +16 -0
  465. autocoder/rag/variable_holder.py +4 -2
  466. autocoder/rags.py +86 -79
  467. autocoder/regexproject/__init__.py +23 -21
  468. autocoder/sdk/__init__.py +46 -190
  469. autocoder/sdk/api.py +370 -0
  470. autocoder/sdk/async_runner/__init__.py +26 -0
  471. autocoder/sdk/async_runner/async_executor.py +650 -0
  472. autocoder/sdk/async_runner/async_handler.py +356 -0
  473. autocoder/sdk/async_runner/markdown_processor.py +595 -0
  474. autocoder/sdk/async_runner/task_metadata.py +284 -0
  475. autocoder/sdk/async_runner/worktree_manager.py +438 -0
  476. autocoder/sdk/cli/__init__.py +2 -5
  477. autocoder/sdk/cli/formatters.py +28 -204
  478. autocoder/sdk/cli/handlers.py +77 -44
  479. autocoder/sdk/cli/main.py +154 -171
  480. autocoder/sdk/cli/options.py +95 -22
  481. autocoder/sdk/constants.py +139 -51
  482. autocoder/sdk/core/auto_coder_core.py +484 -109
  483. autocoder/sdk/core/bridge.py +297 -115
  484. autocoder/sdk/exceptions.py +18 -12
  485. autocoder/sdk/formatters/__init__.py +19 -0
  486. autocoder/sdk/formatters/input.py +64 -0
  487. autocoder/sdk/formatters/output.py +247 -0
  488. autocoder/sdk/formatters/stream.py +54 -0
  489. autocoder/sdk/models/__init__.py +6 -5
  490. autocoder/sdk/models/options.py +55 -18
  491. autocoder/sdk/utils/formatters.py +27 -195
  492. autocoder/suffixproject/__init__.py +28 -25
  493. autocoder/terminal/__init__.py +14 -0
  494. autocoder/terminal/app.py +454 -0
  495. autocoder/terminal/args.py +32 -0
  496. autocoder/terminal/bootstrap.py +178 -0
  497. autocoder/terminal/command_processor.py +521 -0
  498. autocoder/terminal/command_registry.py +57 -0
  499. autocoder/terminal/help.py +97 -0
  500. autocoder/terminal/tasks/__init__.py +5 -0
  501. autocoder/terminal/tasks/background.py +77 -0
  502. autocoder/terminal/tasks/task_event.py +70 -0
  503. autocoder/terminal/ui/__init__.py +13 -0
  504. autocoder/terminal/ui/completer.py +268 -0
  505. autocoder/terminal/ui/keybindings.py +75 -0
  506. autocoder/terminal/ui/session.py +41 -0
  507. autocoder/terminal/ui/toolbar.py +64 -0
  508. autocoder/terminal/utils/__init__.py +13 -0
  509. autocoder/terminal/utils/errors.py +18 -0
  510. autocoder/terminal/utils/paths.py +19 -0
  511. autocoder/terminal/utils/shell.py +43 -0
  512. autocoder/terminal_v3/__init__.py +10 -0
  513. autocoder/terminal_v3/app.py +201 -0
  514. autocoder/terminal_v3/handlers/__init__.py +5 -0
  515. autocoder/terminal_v3/handlers/command_handler.py +131 -0
  516. autocoder/terminal_v3/models/__init__.py +6 -0
  517. autocoder/terminal_v3/models/conversation_buffer.py +214 -0
  518. autocoder/terminal_v3/models/message.py +50 -0
  519. autocoder/terminal_v3/models/tool_display.py +247 -0
  520. autocoder/terminal_v3/ui/__init__.py +7 -0
  521. autocoder/terminal_v3/ui/keybindings.py +56 -0
  522. autocoder/terminal_v3/ui/layout.py +141 -0
  523. autocoder/terminal_v3/ui/styles.py +43 -0
  524. autocoder/tsproject/__init__.py +23 -23
  525. autocoder/utils/auto_coder_utils/chat_stream_out.py +1 -1
  526. autocoder/utils/llms.py +88 -80
  527. autocoder/utils/math_utils.py +101 -0
  528. autocoder/utils/model_provider_selector.py +16 -4
  529. autocoder/utils/operate_config_api.py +33 -5
  530. autocoder/utils/thread_utils.py +2 -2
  531. autocoder/version.py +4 -2
  532. autocoder/workflow_agents/__init__.py +84 -0
  533. autocoder/workflow_agents/agent.py +143 -0
  534. autocoder/workflow_agents/exceptions.py +573 -0
  535. autocoder/workflow_agents/executor.py +665 -0
  536. autocoder/workflow_agents/loader.py +749 -0
  537. autocoder/workflow_agents/runner.py +267 -0
  538. autocoder/workflow_agents/types.py +173 -0
  539. autocoder/workflow_agents/utils.py +434 -0
  540. autocoder/workflow_agents/workflow_manager.py +211 -0
  541. auto_coder-1.0.0.dist-info/METADATA +0 -396
  542. auto_coder-1.0.0.dist-info/RECORD +0 -442
  543. auto_coder-1.0.0.dist-info/licenses/LICENSE +0 -201
  544. autocoder/auto_coder_server.py +0 -672
  545. autocoder/benchmark.py +0 -138
  546. autocoder/common/ac_style_command_parser/example.py +0 -7
  547. autocoder/common/cleaner.py +0 -31
  548. autocoder/common/command_completer_v2.py +0 -615
  549. autocoder/common/context_pruner.py +0 -477
  550. autocoder/common/conversation_pruner.py +0 -132
  551. autocoder/common/directory_cache/__init__.py +0 -1
  552. autocoder/common/directory_cache/cache.py +0 -192
  553. autocoder/common/directory_cache/test_cache.py +0 -190
  554. autocoder/common/file_checkpoint/examples.py +0 -217
  555. autocoder/common/llm_friendly_package_example.py +0 -138
  556. autocoder/common/llm_friendly_package_test.py +0 -63
  557. autocoder/common/pull_requests/test_module.py +0 -1
  558. autocoder/common/rulefiles/autocoderrules_utils.py +0 -484
  559. autocoder/common/text.py +0 -30
  560. autocoder/common/v2/agent/agentic_edit_tools/list_package_info_tool_resolver.py +0 -42
  561. autocoder/common/v2/agent/agentic_edit_tools/test_execute_command_tool_resolver.py +0 -70
  562. autocoder/common/v2/agent/agentic_edit_tools/test_search_files_tool_resolver.py +0 -163
  563. autocoder/common/v2/agent/agentic_tool_display.py +0 -183
  564. autocoder/plugins/dynamic_completion_example.py +0 -148
  565. autocoder/plugins/sample_plugin.py +0 -160
  566. autocoder/sdk/cli/__main__.py +0 -26
  567. autocoder/sdk/cli/completion_wrapper.py +0 -38
  568. autocoder/sdk/cli/install_completion.py +0 -301
  569. autocoder/sdk/models/messages.py +0 -209
  570. autocoder/sdk/session/__init__.py +0 -32
  571. autocoder/sdk/session/session.py +0 -106
  572. autocoder/sdk/session/session_manager.py +0 -56
  573. {auto_coder-1.0.0.dist-info → auto_coder-2.0.1.dist-info}/top_level.txt +0 -0
  574. /autocoder/{sdk/example.py → common/agent_query_queue/__init__.py} +0 -0
@@ -1,19 +1,27 @@
1
+ """
2
+ MCP Tools Hub Module
3
+
4
+ This module provides the McpHub class for managing MCP server connections
5
+ and interactions. It handles server configuration, connection management,
6
+ and marketplace operations.
7
+ """
8
+
1
9
  import os
2
10
  import json
3
11
  import asyncio
4
- import aiohttp
5
12
  import importlib
6
13
  import pkgutil
7
- import re
8
- import inspect
9
14
  from datetime import datetime, timedelta
10
- from typing import Dict, List, Optional, Any, Set, Optional, Tuple
15
+ from typing import Dict, List, Optional, Any, Set, Tuple
11
16
  from pathlib import Path
12
17
  from pydantic import BaseModel, Field
13
18
  from loguru import logger
14
19
  from contextlib import AsyncExitStack
15
- from datetime import timedelta
16
- from autocoder.common.mcp_server_types import MarketplaceMCPServerItem
20
+
21
+ from .types import (
22
+ McpTool, McpResource, McpResourceTemplate, McpServer,
23
+ MarketplaceMCPServerItem
24
+ )
17
25
 
18
26
  try:
19
27
  from mcp import ClientSession
@@ -27,49 +35,13 @@ except ImportError:
27
35
  ClientSession = None
28
36
  logger.error("mcp is not installed(which requires python>=3.11), please install it by `pip install mcp`")
29
37
 
30
- class McpTool(BaseModel):
31
- """Represents an MCP tool configuration"""
32
-
33
- name: str
34
- description: Optional[str] = None
35
- input_schema: dict = Field(default_factory=dict)
36
-
37
-
38
- class McpResource(BaseModel):
39
- """Represents an MCP resource configuration"""
40
-
41
- uri: str
42
- name: str
43
- description: Optional[str] = None
44
- mime_type: Optional[str] = None
45
-
46
- class McpResourceTemplate(BaseModel):
47
- """Represents an MCP resource template"""
48
-
49
- uri_template: str
50
- name: str
51
- description: Optional[str] = None
52
- mime_type: Optional[str] = None
53
-
54
-
55
- class McpServer(BaseModel):
56
- """Represents an MCP server configuration and status"""
57
-
58
- name: str
59
- config: str # JSON string of server config
60
- status: str = "disconnected" # connected, disconnected, connecting
61
- error: Optional[str] = None
62
- tools: List[McpTool] = Field(default_factory=list)
63
- resources: List[McpResource] = Field(default_factory=list)
64
- resource_templates: List[McpResourceTemplate] = Field(default_factory=list)
65
-
66
38
 
67
39
  class McpConnection:
68
40
  """Represents an active MCP server connection"""
69
41
 
70
- def __init__(self, server: McpServer, session: ClientSession):
42
+ def __init__(self, server: McpServer, session):
71
43
  self.server = server
72
- self.session = session
44
+ self.session = session
73
45
 
74
46
 
75
47
  def _generate_server_configs() -> Tuple[Dict[str, Any], Dict[str, str]]:
@@ -127,7 +99,13 @@ class McpHub:
127
99
 
128
100
  _instance = None
129
101
 
130
- def __new__(cls, settings_path: Optional[str] = None):
102
+ def __new__(cls, settings_path: Optional[str] = None, marketplace_path: Optional[str] = None):
103
+ # For testing purposes, allow multiple instances with custom paths
104
+ if settings_path is not None or marketplace_path is not None:
105
+ instance = super(McpHub, cls).__new__(cls)
106
+ instance._initialized = False
107
+ return instance
108
+
131
109
  if cls._instance is None:
132
110
  cls._instance = super(McpHub, cls).__new__(cls)
133
111
  cls._instance._initialized = False
@@ -178,7 +156,7 @@ class McpHub:
178
156
  def _read_marketplace(self) -> Dict[str, List[Dict[str, Any]]]:
179
157
  """Read marketplace file"""
180
158
  try:
181
- with open(self.marketplace_path,"r", encoding="utf-8") as f:
159
+ with open(self.marketplace_path, "r", encoding="utf-8") as f:
182
160
  return json.load(f)
183
161
  except Exception as e:
184
162
  logger.error(f"Failed to read marketplace: {e}")
@@ -216,7 +194,7 @@ class McpHub:
216
194
 
217
195
  # Add the new item
218
196
  data = self._read_marketplace()
219
- data["mcpServers"].append(item.dict())
197
+ data["mcpServers"].append(item.model_dump())
220
198
 
221
199
  # Write back to file
222
200
  with open(self.marketplace_path, "w", encoding="utf-8") as f:
@@ -341,12 +319,16 @@ class McpHub:
341
319
  logger.error(f"Failed to apply marketplace item: {e}")
342
320
  return False
343
321
 
344
- async def add_server_config(self, name: str, config: Dict[str, Any]) -> None:
322
+ async def add_server_config(self, name: str, config: Dict[str, Any]) -> bool:
345
323
  """
346
324
  Add or update MCP server configuration in settings file.
347
325
 
348
326
  Args:
349
- server_name_or_config: Name of the server or server configuration dictionary
327
+ name: Name of the server
328
+ config: Server configuration dictionary
329
+
330
+ Returns:
331
+ bool: True if successful, False otherwise
350
332
  """
351
333
  settings = self._read_settings()
352
334
  settings["mcpServers"][name] = config
@@ -410,12 +392,16 @@ class McpHub:
410
392
  )
411
393
  transport_config = config.get("transport", {
412
394
  "type": "stdio",
413
- "endpoint":""
395
+ "endpoint": ""
414
396
  })
415
397
 
416
398
  if transport_config["type"] not in ["stdio", "sse"]:
417
399
  raise ValueError(f"Invalid transport type: {transport_config['type']}")
418
400
 
401
+ # Check if MCP is available
402
+ if stdio_client is None or sse_client is None or ClientSession is None:
403
+ raise RuntimeError("MCP is not installed or not available")
404
+
419
405
  if transport_config["type"] == "stdio":
420
406
  # Setup transport parameters
421
407
  server_params = StdioServerParameters(
@@ -432,7 +418,6 @@ class McpHub:
432
418
  url = transport_config["endpoint"]
433
419
  transport = await exit_stack.enter_async_context(sse_client(url))
434
420
 
435
-
436
421
  try:
437
422
  stdio, write = transport
438
423
  session = await exit_stack.enter_async_context(
@@ -455,11 +440,6 @@ class McpHub:
455
440
  self.connections[name].server.error = error_msg
456
441
  return server
457
442
 
458
-
459
-
460
-
461
-
462
-
463
443
  async def delete_connection(self, name: str) -> None:
464
444
  """
465
445
  Close and remove a server connection with proper cleanup
@@ -477,7 +457,6 @@ class McpHub:
477
457
  del self.exit_stacks[name]
478
458
  except Exception as e:
479
459
  logger.error(f"Error cleaning up to {name}: {e}")
480
-
481
460
 
482
461
  async def refresh_server_connection(self, name: str) -> None:
483
462
  """
@@ -577,14 +556,9 @@ class McpHub:
577
556
  if not connection:
578
557
  return []
579
558
 
580
- # return await self.send_request(
581
- # types.ClientRequest(
582
- # types.PingRequest(
583
- # method="ping",
584
- # )
585
- # ),
586
- # types.EmptyResult,
587
- # )
559
+ if mcp_types is None:
560
+ logger.warning("MCP types not available")
561
+ return []
588
562
 
589
563
  response = await connection.session.send_request(
590
564
  mcp_types.ClientRequest(mcp_types.ListResourceTemplatesRequest(
@@ -617,7 +591,7 @@ class McpHub:
617
591
 
618
592
  async def call_tool(
619
593
  self, server_name: str, tool_name: str, tool_arguments: Optional[Dict] = None
620
- ) -> mcp_types.CallToolResult:
594
+ ):
621
595
  """
622
596
  Call an MCP tool with arguments
623
597
  """
@@ -627,7 +601,7 @@ class McpHub:
627
601
 
628
602
  return await connection.session.call_tool(tool_name, tool_arguments or {})
629
603
 
630
- async def read_resource(self, server_name: str, uri: str) -> mcp_types.ReadResourceResult:
604
+ async def read_resource(self, server_name: str, uri: str):
631
605
  """
632
606
  Read an MCP resource
633
607
  """
@@ -649,4 +623,4 @@ class McpHub:
649
623
  """
650
624
  Get all available server templates as JSON strings
651
625
  """
652
- return MCP_SERVER_TEMPLATES
626
+ return MCP_SERVER_TEMPLATES
@@ -1,13 +1,22 @@
1
+ """
2
+ MCP Tools Installer Module
3
+
4
+ This module provides the McpServerInstaller class for installing and
5
+ configuring MCP servers. It handles both built-in and external servers.
6
+ """
7
+
1
8
  import json
2
9
  import sys
3
10
  import os
4
11
  import time
5
12
  from typing import Dict, Any, Tuple, List
6
13
  from loguru import logger
7
- import asyncio
8
14
 
9
- from autocoder.common.mcp_hub import McpHub, MCP_BUILD_IN_SERVERS
10
- from autocoder.common.mcp_server_types import McpResponse, McpInstallRequest, InstallResult, ServerConfig, McpExternalServer
15
+ from .hub import McpHub, MCP_BUILD_IN_SERVERS
16
+ from .types import (
17
+ McpResponse, McpInstallRequest, InstallResult, ServerConfig,
18
+ McpExternalServer, MarketplaceMCPServerItem
19
+ )
11
20
  from autocoder.chat_auto_coder_lang import get_message_with_format
12
21
 
13
22
 
@@ -130,7 +139,6 @@ class McpServerInstaller:
130
139
  for s in external_servers:
131
140
  if s.name == name:
132
141
  if s.runtime == "python":
133
- # self.install_python_package(name)
134
142
  template_config = {
135
143
  "command": "python",
136
144
  "args": [
@@ -138,7 +146,6 @@ class McpServerInstaller:
138
146
  ],
139
147
  }
140
148
  elif s.runtime == "node":
141
- # self.install_node_package(name)
142
149
  template_config = {
143
150
  "command": "npx",
144
151
  "args": [
@@ -155,14 +162,6 @@ class McpServerInstaller:
155
162
  if not config.get("args") and (name.startswith("@") or config.get("command") in ["npx", "npm"]):
156
163
  config["args"] = ["-y", "-g", name]
157
164
 
158
- ## 如果有模板,则无需再次安装,处理模板的时候会自动安装
159
- # if not template_config:
160
- # # Install package if needed
161
- # if name.startswith("@") or config.get("command") in ["npx", "npm"]:
162
- # self.install_node_package(name)
163
- # else:
164
- # self.install_python_package(name)
165
-
166
165
  return name, config
167
166
 
168
167
  def parse_json_config(self, server_name_or_config: str) -> Tuple[str, Dict[str, Any]]:
@@ -175,16 +174,10 @@ class McpServerInstaller:
175
174
  # 取第一个server 配置
176
175
  config = list(raw_config.values())[0]
177
176
  name = list(raw_config.keys())[0]
178
- # if name.startswith("@") or config["command"] in ["npx", "npm"]:
179
- # for item in config["args"]:
180
- # if name in item:
181
- # self.install_node_package(item)
182
- # else:
183
- # self.install_python_package(name)
184
177
 
185
178
  return name, config
186
179
 
187
- def process_market_install_item(self, market_item) -> Tuple[str, Dict[str, Any]]:
180
+ def process_market_install_item(self, market_item: MarketplaceMCPServerItem) -> Tuple[str, Dict[str, Any]]:
188
181
  """Process a MarketplaceMCPServerItem into name and config"""
189
182
  name = market_item.name
190
183
  config = {
@@ -192,14 +185,6 @@ class McpServerInstaller:
192
185
  "args": market_item.args,
193
186
  "env": market_item.env
194
187
  }
195
-
196
- # Install package if needed
197
- # if name.startswith("@") or market_item.command in ["npx", "npm"]:
198
- # for item in market_item.args:
199
- # if name in item:
200
- # self.install_node_package(item)
201
- # elif market_item.command not in ["python", "node"]:
202
- # self.install_python_package(name)
203
188
 
204
189
  return name, config
205
190
 
@@ -215,6 +200,9 @@ class McpServerInstaller:
215
200
  display_result = request.market_install_item.name
216
201
  else:
217
202
  server_name_or_config = request.server_name_or_config
203
+ if server_name_or_config is None:
204
+ raise ValueError("server_name_or_config is required")
205
+
218
206
  display_result = server_name_or_config
219
207
 
220
208
  # Try different parsing methods
@@ -1,64 +1,145 @@
1
+ """
2
+ MCP Tools Server Module
3
+
4
+ This module provides the McpServer class for handling MCP server operations
5
+ in a thread-safe manner. It manages requests and responses through async queues.
6
+ """
7
+
1
8
  import asyncio
2
9
  from asyncio import Queue as AsyncQueue
3
10
  import threading
4
- from typing import List
5
- import os
6
- import time
11
+ import signal
12
+ import atexit
13
+ from typing import Union
7
14
  from loguru import logger
8
- import json
9
15
 
10
- from autocoder.common.mcp_hub import McpHub, MCP_BUILD_IN_SERVERS, MarketplaceMCPServerItem
11
- from autocoder.common.mcp_tools import McpExecutor
16
+ from .hub import McpHub, MCP_BUILD_IN_SERVERS
17
+ from .executor import McpExecutor
18
+ from .installer import McpServerInstaller
19
+ from .types import (
20
+ McpRequest, McpInstallRequest, McpRemoveRequest, McpListRequest,
21
+ McpListRunningRequest, McpRefreshRequest, McpServerInfoRequest,
22
+ McpResponse, ServerInfo, InstallResult, RemoveResult, ListResult,
23
+ ListRunningResult, RefreshResult, QueryResult, ErrorResult,
24
+ StringResult, MarketplaceAddRequest, MarketplaceAddResult,
25
+ MarketplaceUpdateRequest, MarketplaceUpdateResult, MarketplaceMCPServerItem
26
+ )
12
27
  from autocoder.utils.llms import get_single_llm
13
28
  from autocoder.chat_auto_coder_lang import get_message_with_format
14
- from autocoder.common.mcp_server_types import (
15
- McpRequest, McpInstallRequest, McpRemoveRequest, McpListRequest,
16
- McpListRunningRequest, McpRefreshRequest, McpServerInfoRequest,
17
- McpResponse, ServerInfo, InstallResult, RemoveResult, ListResult,
18
- ListRunningResult, RefreshResult, QueryResult, ErrorResult, ServerConfig,StringResult,
19
- ExternalServerInfo, McpExternalServer, MarketplaceAddRequest, MarketplaceAddResult,
20
- MarketplaceUpdateRequest, MarketplaceUpdateResult
21
- )
22
- from autocoder.common.mcp_server_install import McpServerInstaller
29
+
23
30
 
24
31
  class McpServer:
32
+ """
33
+ MCP Server handling class that manages MCP operations in a thread-safe manner.
34
+
35
+ This class provides an async interface for MCP operations while maintaining
36
+ thread safety through proper queue management.
37
+ """
38
+
25
39
  def __init__(self):
26
40
  self._request_queue = AsyncQueue()
27
41
  self._response_queue = AsyncQueue()
28
42
  self._running = False
29
43
  self._task = None
30
44
  self._loop = None
45
+ self._thread = None
31
46
  self._installer = McpServerInstaller()
47
+ self._shutdown_event = threading.Event()
32
48
 
33
49
  def start(self):
50
+ """Start the MCP server in a separate thread"""
34
51
  if self._running:
35
52
  return
36
53
 
37
54
  self._running = True
55
+ self._shutdown_event.clear()
38
56
  self._loop = asyncio.new_event_loop()
39
- threading.Thread(target=self._run_event_loop, daemon=True).start()
57
+ self._thread = threading.Thread(target=self._run_event_loop, daemon=True)
58
+ self._thread.start()
40
59
 
41
60
  def stop(self):
42
- if self._running:
43
- self._running = False
44
- if self._loop:
45
- self._loop.stop()
46
- self._loop.close()
61
+ """Stop the MCP server"""
62
+ if not self._running:
63
+ return
64
+
65
+ self._running = False
66
+ self._shutdown_event.set()
67
+
68
+ if self._loop and self._loop.is_running():
69
+ # Cancel the task gracefully
70
+ if self._task and not self._task.done():
71
+ self._loop.call_soon_threadsafe(self._task.cancel)
72
+
73
+ # Send None to break the request processing loop
74
+ try:
75
+ future = asyncio.run_coroutine_threadsafe(
76
+ self._request_queue.put(None), self._loop
77
+ )
78
+ future.result(timeout=1.0)
79
+ except Exception:
80
+ pass
81
+
82
+ # Stop the event loop
83
+ self._loop.call_soon_threadsafe(self._loop.stop)
84
+
85
+ # Wait for thread to finish
86
+ if self._thread and self._thread.is_alive():
87
+ self._thread.join(timeout=2.0)
88
+ if self._thread.is_alive():
89
+ logger.warning("MCP server thread did not stop gracefully")
47
90
 
48
91
  def _run_event_loop(self):
92
+ """Run the event loop in the dedicated thread"""
93
+ if self._loop is None:
94
+ return
95
+
49
96
  asyncio.set_event_loop(self._loop)
50
- self._task = self._loop.create_task(self._process_request())
51
- self._loop.run_forever()
97
+
98
+ try:
99
+ self._task = self._loop.create_task(self._process_request())
100
+ self._loop.run_forever()
101
+ except KeyboardInterrupt:
102
+ logger.info("KeyboardInterrupt received in MCP server event loop")
103
+ except Exception as e:
104
+ logger.error(f"Error in MCP server event loop: {e}")
105
+ finally:
106
+ # Clean up
107
+ if self._task and not self._task.done():
108
+ self._task.cancel()
109
+ try:
110
+ self._loop.run_until_complete(self._task)
111
+ except asyncio.CancelledError:
112
+ pass
113
+
114
+ # Close the loop
115
+ try:
116
+ self._loop.close()
117
+ except Exception as e:
118
+ logger.error(f"Error closing event loop: {e}")
52
119
 
53
120
  async def _process_request(self):
54
- hub = McpHub()
55
-
56
- ## 可能会阻塞,当mcp settings.json 里有异常内容时
57
- await hub.initialize()
121
+ """
122
+ Process incoming requests and generate responses
123
+ """
124
+ hub = McpHub()
125
+
126
+ try:
127
+ # May block if there are abnormal contents in mcp settings.json
128
+ await hub.initialize()
129
+ except Exception as e:
130
+ logger.error(f"Failed to initialize MCP hub: {e}")
131
+ return
58
132
 
59
133
  while self._running:
60
- try:
61
- request = await self._request_queue.get()
134
+ try:
135
+ # Use timeout to allow checking _running flag
136
+ try:
137
+ request = await asyncio.wait_for(
138
+ self._request_queue.get(), timeout=1.0
139
+ )
140
+ except asyncio.TimeoutError:
141
+ continue
142
+
62
143
  if request is None:
63
144
  break
64
145
 
@@ -89,14 +170,14 @@ class McpServer:
89
170
 
90
171
  elif isinstance(request, McpListRequest):
91
172
  try:
92
- # Get built-in servers
173
+ # Get built-in servers
93
174
  builtin_servers = []
94
175
  for name, config in MCP_BUILD_IN_SERVERS.items():
95
176
  marketplace_item = MarketplaceMCPServerItem(
96
177
  name=name,
97
178
  description=f"Built-in: {name}",
98
179
  mcp_type="command",
99
- command=config.get("command", ""),
180
+ command=config.get("command") or "",
100
181
  args=config.get("args", []),
101
182
  env=config.get("env", {})
102
183
  )
@@ -156,10 +237,15 @@ class McpServer:
156
237
 
157
238
  elif isinstance(request, McpServerInfoRequest):
158
239
  try:
159
- llm = get_single_llm(request.model, product_mode=request.product_mode)
240
+ llm = get_single_llm(request.model, product_mode=request.product_mode or "lite")
241
+ if llm is None:
242
+ raise ValueError("Failed to get LLM instance")
160
243
  mcp_executor = McpExecutor(hub, llm)
161
244
  result = mcp_executor.get_connected_servers_info()
162
- await self._response_queue.put(McpResponse(result=result, raw_result=StringResult(result=result)))
245
+ await self._response_queue.put(McpResponse(
246
+ result=result,
247
+ raw_result=StringResult(result=result)
248
+ ))
163
249
  except Exception as e:
164
250
  import traceback
165
251
  traceback.print_exc()
@@ -172,8 +258,7 @@ class McpServer:
172
258
  elif isinstance(request, McpListRunningRequest):
173
259
  try:
174
260
  servers = hub.get_servers()
175
- running_servers = "\n".join(
176
- [f"- {server.name}" for server in servers])
261
+ running_servers = "\n".join([f"- {server.name}" for server in servers])
177
262
  result = running_servers if running_servers else ""
178
263
  await self._response_queue.put(McpResponse(
179
264
  result=result,
@@ -219,7 +304,7 @@ class McpServer:
219
304
  name=request.name,
220
305
  description=request.description,
221
306
  mcp_type=request.mcp_type,
222
- command=request.command,
307
+ command=request.command or "",
223
308
  args=request.args or [],
224
309
  env=request.env or {},
225
310
  url=request.url or ""
@@ -264,7 +349,7 @@ class McpServer:
264
349
  name=request.name,
265
350
  description=request.description,
266
351
  mcp_type=request.mcp_type,
267
- command=request.command,
352
+ command=request.command or "",
268
353
  args=request.args or [],
269
354
  env=request.env or {},
270
355
  url=request.url or ""
@@ -303,6 +388,7 @@ class McpServer:
303
388
  ))
304
389
 
305
390
  else:
391
+ # Handle general MCP requests
306
392
  if not request.query.strip():
307
393
  await self._response_queue.put(McpResponse(
308
394
  result="",
@@ -316,8 +402,7 @@ class McpServer:
316
402
 
317
403
  llm = get_single_llm(request.model, product_mode=request.product_mode)
318
404
  mcp_executor = McpExecutor(hub, llm)
319
- conversations = [
320
- {"role": "user", "content": request.query}]
405
+ conversations = [{"role": "user", "content": request.query}]
321
406
  _, results = await mcp_executor.run(conversations)
322
407
 
323
408
  if not results:
@@ -339,20 +424,53 @@ class McpServer:
339
424
  results=results
340
425
  )
341
426
  ))
427
+ except asyncio.CancelledError:
428
+ logger.info("MCP request processing was cancelled")
429
+ break
342
430
  except Exception as e:
343
- await self._response_queue.put(McpResponse(
344
- result="",
345
- error=get_message_with_format("mcp_error_title") + ": " + str(e),
346
- raw_result=ErrorResult(error=str(e))
347
- ))
431
+ logger.error(f"Error in MCP request processing: {e}")
432
+ try:
433
+ await self._response_queue.put(McpResponse(
434
+ result="",
435
+ error=get_message_with_format("mcp_error_title") + ": " + str(e),
436
+ raw_result=ErrorResult(error=str(e))
437
+ ))
438
+ except Exception:
439
+ pass
440
+
441
+ # Clean up hub connections
442
+ try:
443
+ await hub.shutdown()
444
+ except Exception as e:
445
+ logger.error(f"Error shutting down MCP hub: {e}")
348
446
 
349
- def send_request(self, request: McpRequest) -> McpResponse:
447
+ def send_request(self, request: Union[McpRequest, McpServerInfoRequest]) -> McpResponse:
448
+ """
449
+ Send a request to the MCP server and wait for response
450
+
451
+ Args:
452
+ request: The request to send
453
+
454
+ Returns:
455
+ McpResponse: The response from the server
456
+ """
457
+ if not self._running:
458
+ self.start()
459
+
350
460
  async def _send():
351
461
  await self._request_queue.put(request)
352
462
  return await self._response_queue.get()
353
-
354
- future = asyncio.run_coroutine_threadsafe(_send(), self._loop)
355
- return future.result()
463
+
464
+ if self._loop is None:
465
+ return McpResponse(result="", error="Event loop not available")
466
+
467
+ try:
468
+ future = asyncio.run_coroutine_threadsafe(_send(), self._loop)
469
+ return future.result(timeout=30.0) # Add timeout to prevent hanging
470
+ except asyncio.TimeoutError:
471
+ return McpResponse(result="", error="Request timeout")
472
+ except Exception as e:
473
+ return McpResponse(result="", error=f"Request failed: {str(e)}")
356
474
 
357
475
 
358
476
  # Global MCP server instance
@@ -360,10 +478,20 @@ _mcp_server = None
360
478
 
361
479
 
362
480
  def get_mcp_server():
481
+ """Get the global MCP server instance"""
363
482
  global _mcp_server
364
483
  if _mcp_server is None:
365
484
  _mcp_server = McpServer()
366
485
  _mcp_server.start()
486
+ # Register cleanup function
487
+ atexit.register(_cleanup_mcp_server)
367
488
  return _mcp_server
368
489
 
369
490
 
491
+ def _cleanup_mcp_server():
492
+ """Clean up the global MCP server instance"""
493
+ global _mcp_server
494
+ if _mcp_server is not None:
495
+ logger.info("Cleaning up MCP server...")
496
+ _mcp_server.stop()
497
+ _mcp_server = None