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
@@ -0,0 +1,364 @@
1
+ import unittest
2
+ import tempfile
3
+ import json
4
+ from pathlib import Path
5
+
6
+ from ..registry import ModelRegistry
7
+ from ..schema import LLMModel
8
+
9
+
10
+ class TestModelRegistry(unittest.TestCase):
11
+ """ModelRegistry 单元测试"""
12
+
13
+ def setUp(self):
14
+ """设置测试环境"""
15
+ self.temp_dir = tempfile.mkdtemp()
16
+ self.models_json = Path(self.temp_dir) / "models.json"
17
+ self.registry = ModelRegistry(str(self.models_json))
18
+
19
+ def tearDown(self):
20
+ """清理测试环境"""
21
+ import shutil
22
+ shutil.rmtree(self.temp_dir, ignore_errors=True)
23
+
24
+ def test_load_default_models(self):
25
+ """测试加载默认模型"""
26
+ # 第一次加载会创建默认配置
27
+ models = self.registry.load()
28
+
29
+ # 验证默认模型已加载
30
+ self.assertGreater(len(models), 0)
31
+
32
+ # 检查一些默认模型
33
+ model_names = [m.name for m in models]
34
+ self.assertIn("deepseek/v3", model_names)
35
+ self.assertIn("deepseek/r1", model_names)
36
+
37
+ # 验证配置文件已创建
38
+ self.assertTrue(self.models_json.exists())
39
+
40
+ def test_save_and_load(self):
41
+ """测试保存和加载"""
42
+ # 创建测试模型
43
+ test_models = [
44
+ LLMModel(
45
+ name="test/save1",
46
+ model_name="test-save-1",
47
+ model_type="saas/openai",
48
+ base_url="https://test.com/v1"
49
+ )
50
+ ]
51
+
52
+ # 保存
53
+ self.registry.save(test_models)
54
+
55
+ # 重新加载
56
+ loaded_models = self.registry.load()
57
+
58
+ # 验证(应该包含默认模型和自定义模型)
59
+ loaded_names = [m.name for m in loaded_models]
60
+ self.assertIn("test/save1", loaded_names)
61
+ # 也应该包含默认模型
62
+ self.assertIn("deepseek/v3", loaded_names)
63
+
64
+ def test_get_model(self):
65
+ """测试获取单个模型"""
66
+ # 获取存在的默认模型
67
+ model = self.registry.get("deepseek/v3")
68
+ self.assertIsNotNone(model)
69
+ if model:
70
+ self.assertEqual(model.name, "deepseek/v3")
71
+
72
+ # 获取不存在的模型
73
+ model = self.registry.get("non/existent")
74
+ self.assertIsNone(model)
75
+
76
+ def test_get_all_models(self):
77
+ """测试获取所有模型"""
78
+ models = self.registry.get_all()
79
+ self.assertIsInstance(models, dict)
80
+ self.assertGreater(len(models), 0)
81
+
82
+ # 应该包含默认模型
83
+ self.assertIn("deepseek/v3", models)
84
+ self.assertIn("deepseek/r1", models)
85
+
86
+ def test_add_or_update(self):
87
+ """测试添加或更新模型"""
88
+ # 添加新模型
89
+ new_model = LLMModel(
90
+ name="test/new",
91
+ model_name="test-new",
92
+ model_type="saas/openai",
93
+ base_url="https://new.com/v1"
94
+ )
95
+ self.registry.add_or_update(new_model)
96
+
97
+ # 验证已添加
98
+ model = self.registry.get("test/new")
99
+ self.assertIsNotNone(model)
100
+ if model:
101
+ self.assertEqual(model.name, "test/new")
102
+
103
+ # 更新模型
104
+ new_model.input_price = 5.0
105
+ self.registry.add_or_update(new_model)
106
+
107
+ # 验证已更新
108
+ model = self.registry.get("test/new")
109
+ self.assertIsNotNone(model)
110
+ if model:
111
+ self.assertEqual(model.input_price, 5.0)
112
+
113
+ def test_save_api_key(self):
114
+ """测试保存 API 密钥"""
115
+ # 保存密钥
116
+ result = self.registry.save_api_key("deepseek/v3", "test-api-key-123")
117
+ self.assertTrue(result)
118
+
119
+ # 获取模型查看其 api_key_path
120
+ model = self.registry.get("deepseek/v3")
121
+ self.assertIsNotNone(model)
122
+ if model:
123
+ expected_key_path = model.api_key_path
124
+ self.assertIsNotNone(expected_key_path)
125
+
126
+ if expected_key_path:
127
+ # 验证密钥文件已创建
128
+ key_file = self.models_json.parent / expected_key_path
129
+ self.assertTrue(key_file.exists())
130
+ self.assertEqual(key_file.read_text().strip(), "test-api-key-123")
131
+
132
+ # 验证模型的 api_key_path 设置正确
133
+ self.assertEqual(model.api_key_path, expected_key_path)
134
+
135
+ def test_save_api_key_nonexistent_model(self):
136
+ """测试为不存在的模型保存 API 密钥"""
137
+ result = self.registry.save_api_key("non/existent", "test-key")
138
+ self.assertFalse(result)
139
+
140
+ def test_backward_compatibility(self):
141
+ """测试向后兼容性"""
142
+ # 创建没有新字段的旧格式数据
143
+ old_format_models = [
144
+ {
145
+ "name": "old/model",
146
+ "model_name": "old-model",
147
+ "model_type": "saas/openai",
148
+ "base_url": "https://old.com/v1",
149
+ "is_reasoning": False,
150
+ "input_price": 1.0,
151
+ "output_price": 2.0
152
+ # 没有 context_window, max_output_tokens, provider
153
+ }
154
+ ]
155
+
156
+ # 写入文件
157
+ with open(self.models_json, 'w') as f:
158
+ json.dump(old_format_models, f)
159
+
160
+ # 加载
161
+ models = self.registry.load()
162
+
163
+ # 验证默认值已添加
164
+ old_model = next((m for m in models if m.name == "old/model"), None)
165
+ self.assertIsNotNone(old_model)
166
+ if old_model:
167
+ self.assertEqual(old_model.context_window, 32768) # 默认值
168
+ self.assertEqual(old_model.max_output_tokens, 8096) # 默认值
169
+ self.assertIsNone(old_model.provider) # 默认值
170
+
171
+ def test_no_cache_behavior(self):
172
+ """测试无缓存行为,每次都重新加载"""
173
+ # 第一次获取模型
174
+ model1 = self.registry.get("deepseek/v3")
175
+ self.assertIsNotNone(model1)
176
+
177
+ # 添加一个新模型
178
+ new_model = LLMModel(
179
+ name="test/nocache",
180
+ model_name="test-nocache",
181
+ model_type="saas/openai",
182
+ base_url="https://test.com/v1"
183
+ )
184
+ self.registry.add_or_update(new_model)
185
+
186
+ # 重新获取,应该能看到新模型
187
+ model2 = self.registry.get("test/nocache")
188
+ self.assertIsNotNone(model2)
189
+ if model2:
190
+ self.assertEqual(model2.name, "test/nocache")
191
+
192
+ # 再次获取所有模型,应该包含新模型
193
+ all_models = self.registry.get_all()
194
+ self.assertIn("test/nocache", all_models)
195
+
196
+ def test_file_corruption_handling(self):
197
+ """测试文件损坏的处理"""
198
+ # 写入无效的 JSON
199
+ with open(self.models_json, 'w') as f:
200
+ f.write("invalid json content")
201
+
202
+ # 应该能正常加载(会重新创建默认配置)
203
+ models = self.registry.load()
204
+ self.assertGreater(len(models), 0)
205
+
206
+ # 验证默认模型存在
207
+ model_names = [m.name for m in models]
208
+ self.assertIn("deepseek/v3", model_names)
209
+
210
+ # 验证文件已被修复
211
+ self.assertTrue(self.models_json.exists())
212
+ with open(self.models_json, 'r') as f:
213
+ data = json.load(f)
214
+ self.assertIsInstance(data, list)
215
+
216
+ def test_remove_model(self):
217
+ """测试删除模型"""
218
+ # 添加一个自定义模型
219
+ custom_model = LLMModel(
220
+ name="test/removable",
221
+ model_name="test-removable",
222
+ model_type="saas/openai",
223
+ base_url="https://test.com/v1"
224
+ )
225
+ self.registry.add_or_update(custom_model)
226
+
227
+ # 验证模型已添加
228
+ self.assertTrue(self.registry.get("test/removable") is not None)
229
+
230
+ # 删除模型
231
+ result = self.registry.remove_model("test/removable")
232
+ self.assertTrue(result)
233
+
234
+ # 验证模型已被删除
235
+ self.assertIsNone(self.registry.get("test/removable"))
236
+
237
+ def test_remove_default_model(self):
238
+ """测试删除默认模型(应该失败)"""
239
+ # 尝试删除默认模型
240
+ result = self.registry.remove_model("deepseek/v3")
241
+ self.assertFalse(result)
242
+
243
+ # 验证默认模型仍然存在
244
+ self.assertIsNotNone(self.registry.get("deepseek/v3"))
245
+
246
+ def test_remove_nonexistent_model(self):
247
+ """测试删除不存在的模型"""
248
+ result = self.registry.remove_model("non/existent")
249
+ self.assertFalse(result)
250
+
251
+ def test_remove_model_with_api_key(self):
252
+ """测试删除带有 API 密钥的模型"""
253
+ # 添加带密钥的模型
254
+ custom_model = LLMModel(
255
+ name="test/with_key",
256
+ model_name="test-with-key",
257
+ model_type="saas/openai",
258
+ base_url="https://test.com/v1",
259
+ api_key="test-key-123"
260
+ )
261
+ self.registry.add_or_update(custom_model)
262
+
263
+ # 保存密钥
264
+ self.registry.save_api_key("test/with_key", "test-key-123")
265
+
266
+ # 获取模型并检查密钥文件是否存在
267
+ model = self.registry.get("test/with_key")
268
+ self.assertIsNotNone(model)
269
+ if model and model.api_key_path:
270
+ key_file = self.models_json.parent / model.api_key_path
271
+ self.assertTrue(key_file.exists())
272
+
273
+ # 删除模型
274
+ result = self.registry.remove_model("test/with_key")
275
+ self.assertTrue(result)
276
+
277
+ # 验证模型已被删除
278
+ self.assertIsNone(self.registry.get("test/with_key"))
279
+
280
+ # 验证密钥文件也被删除(如果可能的话)
281
+ # 注意:这里不强制要求删除,因为可能有权限问题
282
+
283
+ def test_api_key_path_generation(self):
284
+ """测试 API 密钥路径自动生成逻辑"""
285
+ # 创建一个只有 api_key 没有 api_key_path 的模型数据
286
+ model_data = [
287
+ {
288
+ "name": "test/auto_path",
289
+ "model_name": "test-auto-path",
290
+ "model_type": "saas/openai",
291
+ "base_url": "https://test.com/v1",
292
+ "api_key": "test-key-456"
293
+ # 注意:没有 api_key_path
294
+ }
295
+ ]
296
+
297
+ # 写入文件
298
+ with open(self.models_json, 'w') as f:
299
+ json.dump(model_data, f)
300
+
301
+ # 创建密钥文件(按预期的路径)
302
+ expected_key_path = "test_auto_path" # 模拟应该生成的路径
303
+ key_file = self.models_json.parent / expected_key_path
304
+ key_file.write_text("test-key-456")
305
+
306
+ # 加载模型
307
+ models = self.registry.load()
308
+
309
+ # 获取测试模型
310
+ test_model = next((m for m in models if m.name == "test/auto_path"), None)
311
+ self.assertIsNotNone(test_model)
312
+
313
+ if test_model:
314
+ # 验证 api_key_path 已经被自动生成
315
+ self.assertEqual(test_model.api_key_path, expected_key_path)
316
+
317
+ # 验证能够获取到 API 密钥
318
+ self.assertEqual(test_model.get_api_key(), "test-key-456")
319
+
320
+ # 验证 has_api_key 返回 True
321
+ self.assertTrue(test_model.has_api_key)
322
+
323
+ def test_api_key_path_priority(self):
324
+ """测试当 api_key_path 存在时,优先使用它而不是自动生成"""
325
+ # 创建一个既有 api_key 又有 api_key_path 的模型数据
326
+ model_data = [
327
+ {
328
+ "name": "test/priority",
329
+ "model_name": "test-priority",
330
+ "model_type": "saas/openai",
331
+ "base_url": "https://test.com/v1",
332
+ "api_key": "memory-key-789",
333
+ "api_key_path": "custom_key_path"
334
+ }
335
+ ]
336
+
337
+ # 写入文件
338
+ with open(self.models_json, 'w') as f:
339
+ json.dump(model_data, f)
340
+
341
+ # 创建密钥文件(使用自定义路径)
342
+ key_file = self.models_json.parent / "custom_key_path"
343
+ key_file.write_text("file-key-789")
344
+
345
+ # 加载模型
346
+ models = self.registry.load()
347
+
348
+ # 获取测试模型
349
+ test_model = next((m for m in models if m.name == "test/priority"), None)
350
+ self.assertIsNotNone(test_model)
351
+
352
+ if test_model:
353
+ # 验证使用了指定的 api_key_path
354
+ self.assertEqual(test_model.api_key_path, "custom_key_path")
355
+
356
+ # 验证从文件读取的密钥覆盖了内存中的密钥
357
+ self.assertEqual(test_model.get_api_key(), "file-key-789")
358
+
359
+ # 验证 has_api_key 返回 True
360
+ self.assertTrue(test_model.has_api_key)
361
+
362
+
363
+ if __name__ == '__main__':
364
+ unittest.main()
@@ -0,0 +1,62 @@
1
+ """
2
+ MCP Tools Module - A comprehensive Model Context Protocol (MCP) management system
3
+
4
+ This module provides a complete set of tools for managing MCP servers, including
5
+ server connections, tool execution, resource access, and server installation.
6
+ """
7
+
8
+ from .hub import McpHub
9
+ from .server import McpServer, get_mcp_server
10
+ from .executor import McpExecutor, McpToolCall, McpResourceAccess
11
+ from .installer import McpServerInstaller
12
+ from .types import (
13
+ McpRequest, McpInstallRequest, McpRemoveRequest, McpListRequest,
14
+ McpListRunningRequest, McpRefreshRequest, McpServerInfoRequest,
15
+ McpResponse, ServerInfo, InstallResult, RemoveResult, ListResult,
16
+ ListRunningResult, RefreshResult, QueryResult, ErrorResult, ServerConfig,
17
+ StringResult, ExternalServerInfo, McpExternalServer, MarketplaceAddRequest,
18
+ MarketplaceAddResult, MarketplaceUpdateRequest, MarketplaceUpdateResult,
19
+ MarketplaceMCPServerItem
20
+ )
21
+
22
+ __all__ = [
23
+ # Main classes
24
+ 'McpHub',
25
+ 'McpServer',
26
+ 'McpExecutor',
27
+ 'McpServerInstaller',
28
+ 'get_mcp_server',
29
+
30
+ # Tool and resource classes
31
+ 'McpToolCall',
32
+ 'McpResourceAccess',
33
+
34
+ # Request/Response types
35
+ 'McpRequest',
36
+ 'McpInstallRequest',
37
+ 'McpRemoveRequest',
38
+ 'McpListRequest',
39
+ 'McpListRunningRequest',
40
+ 'McpRefreshRequest',
41
+ 'McpServerInfoRequest',
42
+ 'McpResponse',
43
+
44
+ # Result types
45
+ 'ServerInfo',
46
+ 'InstallResult',
47
+ 'RemoveResult',
48
+ 'ListResult',
49
+ 'ListRunningResult',
50
+ 'RefreshResult',
51
+ 'QueryResult',
52
+ 'ErrorResult',
53
+ 'ServerConfig',
54
+ 'StringResult',
55
+ 'ExternalServerInfo',
56
+ 'McpExternalServer',
57
+ 'MarketplaceAddRequest',
58
+ 'MarketplaceAddResult',
59
+ 'MarketplaceUpdateRequest',
60
+ 'MarketplaceUpdateResult',
61
+ 'MarketplaceMCPServerItem',
62
+ ]
@@ -1,56 +1,56 @@
1
+ """
2
+ MCP Tools Executor Module
3
+
4
+ This module provides the McpExecutor class for executing MCP tools and
5
+ managing tool interactions. It handles tool calls, resource access,
6
+ and result formatting.
7
+ """
8
+
1
9
  from typing import Dict, Any, List, Optional, Union
2
- from byzerllm import prompt
3
10
  import json
4
- import byzerllm
5
11
  import re
6
- from pydantic import BaseModel, Field
7
12
  from loguru import logger
8
- import os
9
- import time
13
+ from byzerllm import prompt
14
+ import byzerllm
15
+
16
+ from .types import McpToolCall, McpResourceAccess
17
+ from .hub import McpHub
18
+
10
19
  try:
11
20
  import mcp.types as mcp_types
12
21
  except ImportError:
13
22
  mcp_types = None
14
23
  logger.error("mcp is not installed(which requires python>=3.11), please install it by `pip install mcp`")
15
- from autocoder.common.mcp_hub import McpHub
16
-
17
-
18
- class McpToolCall(BaseModel):
19
- server_name: str = Field(..., description="The name of the MCP server")
20
- tool_name: str = Field(..., description="The name of the tool to call")
21
- arguments: Dict[str, Any] = Field(
22
- default_factory=dict, description="The arguments to pass to the tool")
23
-
24
-
25
- class McpResourceAccess(BaseModel):
26
- server_name: str = Field(..., description="The name of the MCP server")
27
- uri: str = Field(..., description="The URI of the resource to access")
28
24
 
29
25
 
30
26
  class McpExecutor:
27
+ """
28
+ Executes MCP tools and manages tool interactions.
29
+
30
+ This class provides a high-level interface for executing MCP tools,
31
+ accessing resources, and formatting results.
32
+ """
33
+
31
34
  def __init__(self, mcp_hub: McpHub, llm: byzerllm.ByzerLLM):
32
35
  self.mcp_hub = mcp_hub
33
36
  self.llm = llm
34
37
 
35
- def get_server_names(self) -> List[str]:
38
+ def get_server_names(self) -> str:
36
39
  """
37
40
  Get the names of all connected MCP servers.
38
41
 
39
42
  Returns:
40
- List of server names
41
-
43
+ Comma-separated string of server names or "(None running currently)"
42
44
  """
43
45
  server_names = [server.name for server in self.mcp_hub.get_servers()]
44
46
  return ",".join(server_names) or "(None running currently)"
45
47
 
46
48
  def get_connected_servers_info(self) -> str:
47
- """Generate formatted information about connected MCP servers
48
-
49
- Args:
50
- mcp_hub: McpHub instance to get server information from
49
+ """
50
+ Generate formatted information about connected MCP servers
51
51
 
52
52
  Returns:
53
- Formatted string with server details
53
+ Formatted string with server details including tools, resources, and templates
54
54
  """
55
55
  servers = self.mcp_hub.get_servers()
56
56
  if not servers:
@@ -108,11 +108,9 @@ class McpExecutor:
108
108
  info.append(server_info)
109
109
 
110
110
  return "\n\n".join(info)
111
-
112
-
113
111
 
114
112
  @byzerllm.prompt()
115
- def mcp_prompt(self,query:str) -> str:
113
+ def mcp_prompt(self, query: str) -> str:
116
114
  """
117
115
  TOOL USE
118
116
 
@@ -221,7 +219,7 @@ class McpExecutor:
221
219
  "server_names": self.get_server_names()
222
220
  }
223
221
 
224
- async def extract_mcp_calls(self,content: str) -> List[Union[McpToolCall, McpResourceAccess]]:
222
+ async def extract_mcp_calls(self, content: str) -> List[Union[McpToolCall, McpResourceAccess]]:
225
223
  """
226
224
  Extract MCP tool calls and resource accesses from content.
227
225
 
@@ -269,17 +267,26 @@ class McpExecutor:
269
267
 
270
268
  return results
271
269
 
272
- async def run(self, conversations: List[Dict[str, Any]]):
270
+ async def run(self, conversations: List[Dict[str, Any]]):
271
+ """
272
+ Run MCP tool execution based on conversations.
273
+
274
+ Args:
275
+ conversations: List of conversation messages
276
+
277
+ Returns:
278
+ Tuple of (new_conversations, tool_results)
279
+ """
273
280
  all_tool_results = []
274
281
 
275
282
  query = conversations[-1]["content"]
276
- new_conversations = conversations[0:-1]+[{
283
+ new_conversations = conversations[0:-1] + [{
277
284
  "role": "user",
278
285
  "content": self.mcp_prompt.prompt(query=query)
279
286
  }]
280
287
 
281
288
  v = self.llm.chat_oai(conversations=new_conversations)
282
- content = v[0].output
289
+ content = str(v[0].output)
283
290
 
284
291
  tools = await self.extract_mcp_calls(content)
285
292
 
@@ -287,7 +294,7 @@ class McpExecutor:
287
294
  results = await self.execute_mcp_tools(tools)
288
295
  all_tool_results += results
289
296
 
290
- return new_conversations,all_tool_results
297
+ return new_conversations, all_tool_results
291
298
 
292
299
  def format_mcp_result(self, result: Any) -> str:
293
300
  """
@@ -301,18 +308,20 @@ class McpExecutor:
301
308
  """
302
309
  if result is None:
303
310
  return "(No result)"
304
- if isinstance(result, mcp_types.CallToolResult):
305
- if len(result.content) ==1:
306
- return result.content[0].text
311
+
312
+ if mcp_types and isinstance(result, mcp_types.CallToolResult):
313
+ if len(result.content) == 1:
314
+ content_item = result.content[0]
315
+ if hasattr(content_item, 'text'):
316
+ return content_item.text
307
317
 
308
- return json.dumps(result.model_dump(), indent=2, ensure_ascii=False)
318
+ return json.dumps(result.model_dump() if hasattr(result, 'model_dump') else result, indent=2, ensure_ascii=False)
309
319
 
310
320
  async def execute_mcp_tools(self, tools: List[Union[McpToolCall, McpResourceAccess]]) -> List[Any]:
311
321
  """
312
322
  Execute MCP tools and return results in order.
313
323
 
314
324
  Args:
315
- mcp_hub: McpHub instance to execute tools
316
325
  tools: List of McpToolCall and McpResourceAccess objects
317
326
 
318
327
  Returns:
@@ -332,4 +341,4 @@ class McpExecutor:
332
341
  except Exception as e:
333
342
  logger.error(f"Failed to execute MCP tool {tool}: {e}")
334
343
  results.append(None)
335
- return results
344
+ return results