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,14 @@
1
+ """
2
+ Auto-Coder AutoCoderArgs 参数解析模块
3
+
4
+ 提供 AutoCoderArgs 参数的高级解析功能,包括:
5
+ - 支持多种数据类型的统一解析
6
+ - Token 数量单位解析(k, m, g 等)
7
+ - 数学表达式计算
8
+ - 基于模型配置的动态解析
9
+ """
10
+
11
+ from .parser import AutoCoderArgsParser
12
+ from .token_parser import TokenParser
13
+
14
+ __all__ = ["AutoCoderArgsParser", "TokenParser"]
@@ -0,0 +1,184 @@
1
+ from typing import Union, Optional, Dict, Any, Type
2
+ from pydantic import Field
3
+ from ..llms import LLMManager
4
+ from .token_parser import TokenParser
5
+
6
+
7
+ class AutoCoderArgsParser:
8
+ """AutoCoderArgs 参数解析器,提供高级参数解析功能"""
9
+
10
+ def __init__(self, llm_manager: Optional[LLMManager] = None):
11
+ """
12
+ 初始化参数解析器
13
+
14
+ Args:
15
+ llm_manager: LLM 管理器实例
16
+ """
17
+ self.llm_manager = llm_manager or LLMManager()
18
+ self.token_parser = TokenParser(self.llm_manager)
19
+
20
+ def parse_conversation_prune_safe_zone_tokens(self,
21
+ value: Union[str, int, float],
22
+ code_model: Optional[str] = None) -> int:
23
+ """
24
+ 解析 conversation_prune_safe_zone_tokens 参数
25
+
26
+ Args:
27
+ value: 参数值,支持字符串、整数、浮点数
28
+ code_model: 代码模型名称,用于浮点数解析
29
+
30
+ Returns:
31
+ 解析后的 token 数量
32
+
33
+ Examples:
34
+ >>> parser = AutoCoderArgsParser()
35
+ >>> parser.parse_conversation_prune_safe_zone_tokens(51200)
36
+ 51200
37
+ >>> parser.parse_conversation_prune_safe_zone_tokens("50k")
38
+ 51200
39
+ >>> parser.parse_conversation_prune_safe_zone_tokens("50*1024")
40
+ 51200
41
+ >>> parser.parse_conversation_prune_safe_zone_tokens(0.1, "deepseek/v3")
42
+ # 返回 deepseek/v3 context_window 的 10%
43
+ """
44
+ try:
45
+ return self.token_parser.parse_token_value(value, code_model)
46
+ except ValueError as e:
47
+ # 如果解析失败,返回默认值并记录警告
48
+ default_value = 50 * 1024
49
+ print(f"Warning: Failed to parse conversation_prune_safe_zone_tokens '{value}': {e}. Using default value: {default_value}")
50
+ return default_value
51
+
52
+ def parse_context_prune_safe_zone_tokens(self,
53
+ value: Union[str, int, float],
54
+ code_model: Optional[str] = None) -> int:
55
+ """
56
+ 解析 context_prune_safe_zone_tokens 参数
57
+
58
+ Args:
59
+ value: 参数值
60
+ code_model: 代码模型名称
61
+
62
+ Returns:
63
+ 解析后的 token 数量
64
+ """
65
+ try:
66
+ return self.token_parser.parse_token_value(value, code_model)
67
+ except ValueError as e:
68
+ default_value = 24 * 1024
69
+ print(f"Warning: Failed to parse context_prune_safe_zone_tokens '{value}': {e}. Using default value: {default_value}")
70
+ return default_value
71
+
72
+ def parse_token_field(self,
73
+ field_name: str,
74
+ value: Union[str, int, float],
75
+ code_model: Optional[str] = None,
76
+ default_value: Optional[int] = None) -> int:
77
+ """
78
+ 通用的 token 字段解析方法
79
+
80
+ Args:
81
+ field_name: 字段名称
82
+ value: 字段值
83
+ code_model: 代码模型名称
84
+ default_value: 默认值,如果为 None 则使用 50*1024
85
+
86
+ Returns:
87
+ 解析后的 token 数量
88
+ """
89
+ try:
90
+ return self.token_parser.parse_token_value(value, code_model)
91
+ except ValueError as e:
92
+ fallback_value = default_value or 50 * 1024
93
+ print(f"Warning: Failed to parse {field_name} '{value}': {e}. Using default value: {fallback_value}")
94
+ return fallback_value
95
+
96
+ def validate_parsed_args(self, args_dict: Dict[str, Any],
97
+ code_model: Optional[str] = None) -> Dict[str, Any]:
98
+ """
99
+ 验证和解析整个参数字典
100
+
101
+ Args:
102
+ args_dict: 参数字典
103
+ code_model: 代码模型名称
104
+
105
+ Returns:
106
+ 验证和解析后的参数字典
107
+ """
108
+ # 定义需要解析的 token 字段及其默认值
109
+ token_fields = {
110
+ 'conversation_prune_safe_zone_tokens': 50 * 1024,
111
+ 'context_prune_safe_zone_tokens': 24 * 1024,
112
+ 'context_prune_sliding_window_size': 1000,
113
+ 'context_prune_sliding_window_overlap': 100,
114
+ 'rag_params_max_tokens': 500000,
115
+ 'rag_context_window_limit': 120000,
116
+ 'rag_duckdb_vector_dim': 1024,
117
+ 'rag_duckdb_query_top_k': 10000,
118
+ 'rag_emb_dim': 1024,
119
+ 'rag_emb_text_size': 1024,
120
+ 'hybrid_index_max_output_tokens': 1000000,
121
+ 'data_cells_max_num': 2000,
122
+ }
123
+
124
+ parsed_dict = args_dict.copy()
125
+
126
+ for field_name, default_value in token_fields.items():
127
+ if field_name in parsed_dict:
128
+ original_value = parsed_dict[field_name]
129
+ # 如果值不是简单的 int,则进行解析
130
+ if not isinstance(original_value, int):
131
+ parsed_dict[field_name] = self.parse_token_field(
132
+ field_name, original_value, code_model, default_value
133
+ )
134
+
135
+ return parsed_dict
136
+
137
+ def get_parsing_info(self) -> Dict[str, Any]:
138
+ """
139
+ 获取解析器信息和使用示例
140
+
141
+ Returns:
142
+ 包含解析器信息的字典
143
+ """
144
+ return {
145
+ "supported_types": ["int", "float", "str"],
146
+ "string_formats": self.token_parser.get_examples(),
147
+ "supported_units": self.token_parser.get_supported_units(),
148
+ "float_behavior": "Float values (0-1) are treated as percentages of the code_model's context_window",
149
+ "fallback_context_window": 50 * 1024,
150
+ "safety_notes": [
151
+ "Invalid expressions fall back to default values",
152
+ "Negative results are clamped to 0",
153
+ "Division by zero is handled gracefully"
154
+ ]
155
+ }
156
+
157
+ def create_flexible_field(self,
158
+ default_value: Union[str, int, float],
159
+ description: str,
160
+ min_value: Optional[int] = None,
161
+ max_value: Optional[int] = None) -> Field:
162
+ """
163
+ 创建支持灵活解析的 Pydantic 字段
164
+
165
+ Args:
166
+ default_value: 默认值
167
+ description: 字段描述
168
+ min_value: 最小值
169
+ max_value: 最大值
170
+
171
+ Returns:
172
+ Pydantic Field 对象
173
+ """
174
+ field_kwargs = {
175
+ "default": default_value,
176
+ "description": description
177
+ }
178
+
179
+ if min_value is not None:
180
+ field_kwargs["ge"] = min_value
181
+ if max_value is not None:
182
+ field_kwargs["le"] = max_value
183
+
184
+ return Field(**field_kwargs)
@@ -0,0 +1 @@
1
+ # 测试模块初始化文件
@@ -0,0 +1,235 @@
1
+ import pytest
2
+ import tempfile
3
+ from pathlib import Path
4
+ from unittest.mock import Mock
5
+
6
+ from autocoder.common.autocoderargs_parser import AutoCoderArgsParser, TokenParser
7
+ from autocoder.common.llms import LLMManager, LLMModel
8
+
9
+
10
+ @pytest.fixture
11
+ def mock_llm_manager():
12
+ """创建 mock LLM manager fixture"""
13
+ mock_manager = Mock(spec=LLMManager)
14
+
15
+ # 设置默认的模型信息
16
+ mock_model = Mock(spec=LLMModel)
17
+ mock_model.context_window = 32768 # deepseek/v3 的默认值
18
+ mock_manager.get_model.return_value = mock_model
19
+
20
+ return mock_manager
21
+
22
+
23
+ @pytest.fixture
24
+ def args_parser(mock_llm_manager):
25
+ """创建 AutoCoderArgsParser 实例 fixture"""
26
+ return AutoCoderArgsParser(mock_llm_manager)
27
+
28
+
29
+ class TestAutoCoderArgsParser:
30
+ """AutoCoderArgsParser 测试类"""
31
+
32
+ @pytest.mark.parametrize("value,expected", [
33
+ (51200, 51200), # 整数
34
+ ("50k", 51200), # 带单位字符串
35
+ ("50*1024", 51200), # 数学表达式
36
+ (0.1, 3276), # 浮点数比例 (32768 * 0.1)
37
+ ])
38
+ def test_parse_conversation_prune_safe_zone_tokens(self, args_parser, value, expected):
39
+ """测试 conversation_prune_safe_zone_tokens 解析"""
40
+ result = args_parser.parse_conversation_prune_safe_zone_tokens(value, "deepseek/v3")
41
+ assert result == expected
42
+
43
+ def test_parse_conversation_prune_safe_zone_tokens_invalid(self, args_parser, capsys):
44
+ """测试无效值的处理"""
45
+ result = args_parser.parse_conversation_prune_safe_zone_tokens("invalid", "deepseek/v3")
46
+
47
+ # 应该返回默认值
48
+ assert result == 50 * 1024
49
+
50
+ # 应该有警告信息
51
+ captured = capsys.readouterr()
52
+ assert "Warning: Failed to parse conversation_prune_safe_zone_tokens" in captured.out
53
+
54
+ @pytest.mark.parametrize("value,expected", [
55
+ (24576, 24576), # 整数
56
+ ("24k", 24576), # 带单位字符串
57
+ ("24*1024", 24576), # 数学表达式
58
+ (0.05, 1638), # 浮点数比例 (32768 * 0.05)
59
+ ])
60
+ def test_parse_context_prune_safe_zone_tokens(self, args_parser, value, expected):
61
+ """测试 context_prune_safe_zone_tokens 解析"""
62
+ result = args_parser.parse_context_prune_safe_zone_tokens(value, "deepseek/v3")
63
+ assert result == expected
64
+
65
+ def test_parse_context_prune_safe_zone_tokens_invalid(self, args_parser, capsys):
66
+ """测试 context_prune_safe_zone_tokens 无效值处理"""
67
+ result = args_parser.parse_context_prune_safe_zone_tokens("invalid", "deepseek/v3")
68
+
69
+ # 应该返回默认值
70
+ assert result == 24 * 1024
71
+
72
+ # 应该有警告信息
73
+ captured = capsys.readouterr()
74
+ assert "Warning: Failed to parse context_prune_safe_zone_tokens" in captured.out
75
+
76
+ @pytest.mark.parametrize("field_name,value,default_value,expected", [
77
+ ("rag_params_max_tokens", "500k", 500000, 512000),
78
+ ("data_cells_max_num", "2k", 2000, 2048),
79
+ ("context_prune_sliding_window_size", 1000, 1000, 1000),
80
+ ("hybrid_index_max_output_tokens", "1m", 1000000, 1048576),
81
+ ])
82
+ def test_parse_token_field(self, args_parser, field_name, value, default_value, expected):
83
+ """测试通用 token 字段解析"""
84
+ result = args_parser.parse_token_field(field_name, value, "deepseek/v3", default_value)
85
+ assert result == expected
86
+
87
+ def test_parse_token_field_invalid(self, args_parser, capsys):
88
+ """测试通用 token 字段无效值处理"""
89
+ field_name = "test_field"
90
+ result = args_parser.parse_token_field(field_name, "invalid", "deepseek/v3", 1000)
91
+
92
+ # 应该返回提供的默认值
93
+ assert result == 1000
94
+
95
+ # 应该有警告信息
96
+ captured = capsys.readouterr()
97
+ assert f"Warning: Failed to parse {field_name}" in captured.out
98
+
99
+ def test_validate_parsed_args(self, args_parser):
100
+ """测试批量参数验证和解析"""
101
+ args_dict = {
102
+ "conversation_prune_safe_zone_tokens": "50k",
103
+ "context_prune_safe_zone_tokens": "24*1024",
104
+ "rag_params_max_tokens": 0.5, # 比例值
105
+ "data_cells_max_num": "2k",
106
+ "other_field": "not_a_token_field", # 非 token 字段
107
+ "regular_int_field": 12345 # 已经是 int 的字段
108
+ }
109
+
110
+ parsed_dict = args_parser.validate_parsed_args(args_dict, "deepseek/v3")
111
+
112
+ # 检查 token 字段被正确解析
113
+ assert parsed_dict["conversation_prune_safe_zone_tokens"] == 51200
114
+ assert parsed_dict["context_prune_safe_zone_tokens"] == 24576
115
+ assert parsed_dict["rag_params_max_tokens"] == 16384 # 32768 * 0.5
116
+ assert parsed_dict["data_cells_max_num"] == 2048
117
+
118
+ # 检查非 token 字段保持不变
119
+ assert parsed_dict["other_field"] == "not_a_token_field"
120
+ assert parsed_dict["regular_int_field"] == 12345
121
+
122
+ def test_validate_parsed_args_with_non_token_fields_only(self, args_parser):
123
+ """测试只包含非 token 字段的参数字典"""
124
+ args_dict = {
125
+ "model": "deepseek/v3",
126
+ "query": "test query",
127
+ "output": "result.txt",
128
+ "skip_confirm": True
129
+ }
130
+
131
+ parsed_dict = args_parser.validate_parsed_args(args_dict, "deepseek/v3")
132
+
133
+ # 所有字段应该保持不变
134
+ assert parsed_dict == args_dict
135
+
136
+ def test_get_parsing_info(self, args_parser):
137
+ """测试获取解析器信息"""
138
+ info = args_parser.get_parsing_info()
139
+
140
+ # 检查必要的信息字段
141
+ assert "supported_types" in info
142
+ assert "string_formats" in info
143
+ assert "supported_units" in info
144
+ assert "float_behavior" in info
145
+ assert "fallback_context_window" in info
146
+ assert "safety_notes" in info
147
+
148
+ # 检查支持的类型
149
+ assert "int" in info["supported_types"]
150
+ assert "float" in info["supported_types"]
151
+ assert "str" in info["supported_types"]
152
+
153
+ # 检查字符串格式示例
154
+ assert isinstance(info["string_formats"], dict)
155
+ assert "整数" in info["string_formats"]
156
+
157
+ # 检查支持的单位
158
+ assert isinstance(info["supported_units"], dict)
159
+ assert "k" in info["supported_units"]
160
+ assert info["supported_units"]["k"] == 1024
161
+
162
+ def test_float_value_with_zero_context_window(self, args_parser, mock_llm_manager):
163
+ """测试当模型 context_window 为 0 时的回退机制"""
164
+ # Mock 模型的 context_window 为 0
165
+ mock_model = Mock(spec=LLMModel)
166
+ mock_model.context_window = 0
167
+ mock_llm_manager.get_model.return_value = mock_model
168
+
169
+ result = args_parser.parse_conversation_prune_safe_zone_tokens(0.1, "test/model")
170
+ # 应该使用默认值 120*1000
171
+ expected = int((120 * 1000) * 0.1)
172
+ assert result == expected
173
+
174
+ def test_float_value_with_missing_model(self, args_parser, mock_llm_manager):
175
+ """测试当模型不存在时的回退机制"""
176
+ # Mock 获取模型返回 None
177
+ mock_llm_manager.get_model.return_value = None
178
+
179
+ result = args_parser.parse_conversation_prune_safe_zone_tokens(0.1, "nonexistent/model")
180
+ # 应该使用默认值 120*1000
181
+ expected = int((120 * 1000) * 0.1)
182
+ assert result == expected
183
+
184
+ def test_args_parser_uses_token_parser(self, args_parser):
185
+ """测试 AutoCoderArgsParser 正确使用 TokenParser"""
186
+ # 确保 AutoCoderArgsParser 内部使用 TokenParser
187
+ assert hasattr(args_parser, 'token_parser')
188
+ assert isinstance(args_parser.token_parser, TokenParser)
189
+ assert args_parser.token_parser.llm_manager == args_parser.llm_manager
190
+
191
+
192
+ class TestAutoCoderArgsParserIntegration:
193
+ """AutoCoderArgsParser 集成测试"""
194
+
195
+ def test_integration_with_real_llm_manager(self):
196
+ """测试与真实 LLM Manager 的集成"""
197
+ with tempfile.TemporaryDirectory() as temp_dir:
198
+ models_json = Path(temp_dir) / "models.json"
199
+
200
+ # 创建真实的 LLM Manager(使用临时目录)
201
+ from autocoder.common.llms import LLMManager
202
+ llm_manager = LLMManager(str(models_json))
203
+
204
+ # 创建 AutoCoderArgsParser
205
+ parser = AutoCoderArgsParser(llm_manager)
206
+
207
+ # 测试基本功能
208
+ result = parser.parse_conversation_prune_safe_zone_tokens("50k")
209
+ assert result == 51200
210
+
211
+ # 测试浮点数(由于使用默认模型,会使用回退值)
212
+ result = parser.parse_conversation_prune_safe_zone_tokens(0.1)
213
+ expected = int((120 * 1000) * 0.1)
214
+ assert result == expected
215
+
216
+ @pytest.mark.parametrize("field_value", [
217
+ "50k",
218
+ "50*1024",
219
+ 0.1,
220
+ 51200
221
+ ])
222
+ def test_all_supported_formats(self, field_value):
223
+ """测试所有支持的格式都能正常工作"""
224
+ # 使用临时 LLM Manager
225
+ with tempfile.TemporaryDirectory() as temp_dir:
226
+ models_json = Path(temp_dir) / "models.json"
227
+
228
+ from autocoder.common.llms import LLMManager
229
+ llm_manager = LLMManager(str(models_json))
230
+ parser = AutoCoderArgsParser(llm_manager)
231
+
232
+ # 所有格式都应该成功解析,不抛出异常
233
+ result = parser.parse_conversation_prune_safe_zone_tokens(field_value)
234
+ assert isinstance(result, int)
235
+ assert result >= 0
@@ -0,0 +1,195 @@
1
+ import pytest
2
+ import tempfile
3
+ from pathlib import Path
4
+ from unittest.mock import Mock
5
+
6
+ from autocoder.common.autocoderargs_parser.token_parser import TokenParser
7
+ from autocoder.common.llms import LLMManager, LLMModel
8
+
9
+
10
+ @pytest.fixture
11
+ def mock_llm_manager():
12
+ """创建 mock LLM manager fixture"""
13
+ return Mock(spec=LLMManager)
14
+
15
+
16
+ @pytest.fixture
17
+ def token_parser(mock_llm_manager):
18
+ """创建 TokenParser 实例 fixture"""
19
+ return TokenParser(mock_llm_manager)
20
+
21
+
22
+ @pytest.fixture
23
+ def temp_dir():
24
+ """创建临时目录 fixture"""
25
+ with tempfile.TemporaryDirectory() as temp_dir:
26
+ yield temp_dir
27
+
28
+
29
+ class TestTokenParser:
30
+ """TokenParser 测试类"""
31
+
32
+ def test_parse_int_value(self, token_parser):
33
+ """测试整数值解析"""
34
+ result = token_parser.parse_token_value(51200)
35
+ assert result == 51200
36
+
37
+ # 测试负数会被转为 0
38
+ result = token_parser.parse_token_value(-100)
39
+ assert result == 0
40
+
41
+ def test_parse_float_value(self, token_parser, mock_llm_manager):
42
+ """测试浮点数值解析"""
43
+ # Mock 模型信息
44
+ mock_model = Mock(spec=LLMModel)
45
+ mock_model.context_window = 100000
46
+ mock_llm_manager.get_model.return_value = mock_model
47
+
48
+ result = token_parser.parse_token_value(0.1, "test/model")
49
+ assert result == 10000 # 100000 * 0.1
50
+
51
+ # 测试无效的浮点数范围
52
+ with pytest.raises(ValueError):
53
+ token_parser.parse_token_value(1.5, "test/model")
54
+
55
+ with pytest.raises(ValueError):
56
+ token_parser.parse_token_value(-0.1, "test/model")
57
+
58
+ def test_parse_float_value_fallback(self, token_parser, mock_llm_manager):
59
+ """测试浮点数解析的回退机制"""
60
+ # Mock 获取模型失败
61
+ mock_llm_manager.get_model.return_value = None
62
+
63
+ result = token_parser.parse_token_value(0.1)
64
+ expected = int((120 * 1000) * 0.1) # 默认 context_window
65
+ assert result == expected
66
+
67
+ @pytest.mark.parametrize("input_str,expected", [
68
+ ("100k", 100 * 1024),
69
+ ("1m", 1024 * 1024),
70
+ ("2.5k", int(2.5 * 1024)),
71
+ ("1g", 1024 * 1024 * 1024),
72
+ ("50K", 50 * 1024), # 大写
73
+ ("1M", 1024 * 1024), # 大写
74
+ ("100kb", 100 * 1024), # 带 b
75
+ ("2MB", 2 * 1024 * 1024), # 大写带 b
76
+ ])
77
+ def test_parse_unit_strings(self, token_parser, input_str, expected):
78
+ """测试带单位的字符串解析"""
79
+ result = token_parser.parse_token_value(input_str)
80
+ assert result == expected
81
+
82
+ @pytest.mark.parametrize("input_str,expected", [
83
+ ("1024", 1024), # 纯整数字符串
84
+ ("0", 0), # 零
85
+ ("8", 8), # 单个数字
86
+ ("123456", 123456), # 大数字
87
+ ("1024.0", 1024), # 浮点数字符串(整数值)
88
+ ("1024.5", 1024), # 浮点数字符串(小数会被截断)
89
+ ("1024.", 1024), # 末尾有小数点
90
+ (".5", 0), # 纯小数(< 1 的会被转为 0)
91
+ ("0.8", 0), # 小数(< 1 的会被转为 0)
92
+ ("100.99", 100), # 小数截断
93
+ ("-10", 0), # 负数会被转为 0
94
+ ("-100.5", 0), # 负浮点数会被转为 0
95
+ ])
96
+ def test_parse_numeric_strings(self, token_parser, input_str, expected):
97
+ """测试纯数字字符串解析"""
98
+ result = token_parser.parse_token_value(input_str)
99
+ assert result == expected
100
+
101
+ @pytest.mark.parametrize("input_str,expected", [
102
+ ("00123", 123), # 前导零
103
+ ("123.000", 123), # 后续零
104
+ ("0000", 0), # 多个零
105
+ ("1.0000", 1), # 浮点数后续零
106
+ ("0001.5", 1), # 前导零加浮点数
107
+ ])
108
+ def test_parse_numeric_strings_edge_cases(self, token_parser, input_str, expected):
109
+ """测试纯数字字符串解析的边界情况"""
110
+ result = token_parser.parse_token_value(input_str)
111
+ assert result == expected
112
+
113
+ def test_parse_priority_order(self, token_parser):
114
+ """测试解析优先级:纯数字 > 带单位 > 数学表达式"""
115
+ # 确保纯数字不会被误认为是数学表达式
116
+ assert token_parser.parse_token_value("1024") == 1024
117
+ assert token_parser.parse_token_value("1024.0") == 1024
118
+
119
+ # 确保带单位的解析优先于数学表达式(虽然这种情况不太可能发生冲突)
120
+ assert token_parser.parse_token_value("1k") == 1024
121
+ assert token_parser.parse_token_value("1m") == 1024 * 1024
122
+
123
+ # 确保数学表达式正常工作
124
+ assert token_parser.parse_token_value("1+1") == 2
125
+ assert token_parser.parse_token_value("2*2") == 4
126
+
127
+ @pytest.mark.parametrize("expr,expected", [
128
+ ("50*1024", 50 * 1024),
129
+ ("100*1000", 100 * 1000),
130
+ ("2**16", 2**16),
131
+ ("1024+512", 1024 + 512),
132
+ ("2048-512", 2048 - 512),
133
+ ("100*10+50", 100 * 10 + 50),
134
+ ("(100+50)*10", (100 + 50) * 10),
135
+ ("1024//2", 1024 // 2),
136
+ ("1024%100", 1024 % 100),
137
+ ])
138
+ def test_parse_math_expressions(self, token_parser, expr, expected):
139
+ """测试数学表达式解析"""
140
+ result = token_parser.parse_token_value(expr)
141
+ assert result == expected
142
+
143
+ @pytest.mark.parametrize("invalid_expr", [
144
+ "invalid_string",
145
+ "100x", # 无效单位
146
+ "1024 + undefined_var", # 未定义变量
147
+ "1024 / 0", # 除零
148
+ "", # 空字符串
149
+ " ", # 只有空格
150
+ ])
151
+ def test_parse_invalid_expressions(self, token_parser, invalid_expr):
152
+ """测试无效表达式处理"""
153
+ with pytest.raises(ValueError):
154
+ token_parser.parse_token_value(invalid_expr)
155
+
156
+ def test_validate_token_value(self, token_parser):
157
+ """测试值验证功能"""
158
+ # 有效值
159
+ assert token_parser.validate_token_value(1024) is True
160
+ assert token_parser.validate_token_value("50k") is True
161
+ assert token_parser.validate_token_value("50*1024") is True
162
+
163
+ # 范围验证
164
+ assert token_parser.validate_token_value(1024, min_tokens=500, max_tokens=2000) is True
165
+ assert token_parser.validate_token_value(100, min_tokens=500, max_tokens=2000) is False
166
+ assert token_parser.validate_token_value(3000, min_tokens=500, max_tokens=2000) is False
167
+
168
+ # 无效值
169
+ assert token_parser.validate_token_value("invalid") is False
170
+
171
+ def test_get_supported_units(self, token_parser):
172
+ """测试获取支持的单位"""
173
+ units = token_parser.get_supported_units()
174
+ assert 'k' in units
175
+ assert 'm' in units
176
+ assert 'g' in units
177
+ assert units['k'] == 1024
178
+ assert units['m'] == 1024 * 1024
179
+
180
+ def test_get_examples(self, token_parser):
181
+ """测试获取使用示例"""
182
+ examples = token_parser.get_examples()
183
+ assert isinstance(examples, dict)
184
+ assert "整数" in examples
185
+ assert "带单位" in examples
186
+ assert "数学表达式" in examples
187
+
188
+ @pytest.mark.parametrize("invalid_value", [
189
+ [1, 2, 3], # 列表类型不支持
190
+ {"value": 1024}, # 字典类型不支持
191
+ ])
192
+ def test_unsupported_type(self, token_parser, invalid_value):
193
+ """测试不支持的类型"""
194
+ with pytest.raises(ValueError):
195
+ token_parser.parse_token_value(invalid_value)