auto-coder 1.0.0__py3-none-any.whl → 2.0.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of auto-coder might be problematic. Click here for more details.

Files changed (574) hide show
  1. auto_coder-2.0.0.dist-info/LICENSE +158 -0
  2. auto_coder-2.0.0.dist-info/METADATA +558 -0
  3. auto_coder-2.0.0.dist-info/RECORD +795 -0
  4. {auto_coder-1.0.0.dist-info → auto_coder-2.0.0.dist-info}/WHEEL +1 -1
  5. {auto_coder-1.0.0.dist-info → auto_coder-2.0.0.dist-info}/entry_points.txt +3 -3
  6. autocoder/__init__.py +31 -0
  7. autocoder/agent/auto_filegroup.py +32 -13
  8. autocoder/agent/auto_learn_from_commit.py +9 -1
  9. autocoder/agent/base_agentic/__init__.py +3 -0
  10. autocoder/agent/base_agentic/agent_hub.py +1 -1
  11. autocoder/agent/base_agentic/base_agent.py +235 -136
  12. autocoder/agent/base_agentic/default_tools.py +119 -118
  13. autocoder/agent/base_agentic/test_base_agent.py +1 -1
  14. autocoder/agent/base_agentic/tool_registry.py +32 -20
  15. autocoder/agent/base_agentic/tools/read_file_tool_resolver.py +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 +73 -59
  19. autocoder/auto_coder.py +31 -40
  20. autocoder/auto_coder_rag.py +11 -1084
  21. autocoder/auto_coder_runner.py +970 -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 +401 -0
  112. autocoder/common/file_handler/commit_handler.py +200 -0
  113. autocoder/common/file_handler/lib_handler.py +156 -0
  114. autocoder/common/file_handler/list_files_handler.py +111 -0
  115. autocoder/common/file_handler/mcp_handler.py +268 -0
  116. autocoder/common/file_handler/models_handler.py +493 -0
  117. autocoder/common/file_handler/remove_files_handler.py +172 -0
  118. autocoder/common/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 +288 -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 +349 -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 +1051 -0
  398. autocoder/default_project/__init__.py +501 -0
  399. autocoder/dispacher/__init__.py +4 -12
  400. autocoder/dispacher/actions/action.py +165 -7
  401. autocoder/dispacher/actions/plugins/action_regex_project.py +2 -2
  402. autocoder/index/entry.py +116 -124
  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 +932 -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 +489 -0
  536. autocoder/workflow_agents/loader.py +737 -0
  537. autocoder/workflow_agents/runner.py +267 -0
  538. autocoder/workflow_agents/types.py +172 -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.0.dist-info}/top_level.txt +0 -0
  574. /autocoder/{sdk/example.py → common/agent_query_queue/__init__.py} +0 -0
@@ -0,0 +1,653 @@
1
+ from collections import OrderedDict
2
+ from typing import Dict, List, Tuple, Any, Optional, Union
3
+ from dataclasses import dataclass, field
4
+ import re
5
+
6
+ from .parser import CommandParser
7
+ from .config import (
8
+ ParserConfig,
9
+ CommandConfig,
10
+ ArgumentConfig,
11
+ ArgType,
12
+ ParamConstraint,
13
+ )
14
+
15
+
16
+ @dataclass
17
+ class ParsedCommand:
18
+ """解析后的命令结果"""
19
+
20
+ name: str
21
+ args: List[Any] = field(default_factory=list) # 转换后的类型
22
+ kwargs: Dict[str, Any] = field(default_factory=dict) # 转换后的类型
23
+ raw_args: List[str] = field(default_factory=list) # 原始字符串
24
+ raw_kwargs: Dict[str, str] = field(default_factory=dict) # 原始字符串
25
+ remainder: Optional[str] = None # 剩余参数
26
+ errors: List[str] = field(default_factory=list) # 解析错误
27
+
28
+ @property
29
+ def is_valid(self) -> bool:
30
+ """是否有效(无错误)"""
31
+ return len(self.errors) == 0
32
+
33
+
34
+ class TypedCommandParser(CommandParser):
35
+ """
36
+ 支持类型和配置的命令解析器
37
+
38
+ Example:
39
+ >>> from autocoder.common.ac_style_command_parser import create_config
40
+ >>>
41
+ >>> # 创建配置
42
+ >>> config = (create_config()
43
+ ... .command("model")
44
+ ... .positional("name", required=True, choices=["gpt-4", "gpt-3.5"])
45
+ ... .max_args(1)
46
+ ... .command("config")
47
+ ... .keyword("temperature", type=float, default=0.7)
48
+ ... .keyword("max_tokens", type=int)
49
+ ... .command("task-prefix")
50
+ ... .positional("prefix", required=True)
51
+ ... .collect_remainder("query")
52
+ ... .build()
53
+ ... )
54
+ >>>
55
+ >>> # 创建解析器
56
+ >>> parser = TypedCommandParser(config)
57
+ >>>
58
+ >>> # 解析命令
59
+ >>> result = parser.parse_typed("/model gpt-4 /config temperature=0.8")
60
+ >>> print(result["model"].args) # ['gpt-4'] - 已验证
61
+ >>> print(result["config"].kwargs) # {'temperature': 0.8} - 已转换为float
62
+ """
63
+
64
+ def __init__(self, config: Optional[ParserConfig] = None):
65
+ """
66
+ 初始化类型化命令解析器
67
+
68
+ Args:
69
+ config: 解析器配置,如果为None则使用默认配置
70
+ """
71
+ super().__init__()
72
+ self.config = config or ParserConfig()
73
+
74
+ def parse_typed(self, query: str) -> OrderedDict[str, ParsedCommand]:
75
+ """
76
+ 解析命令并进行类型转换和验证
77
+
78
+ Args:
79
+ query: 命令行格式的查询字符串
80
+
81
+ Returns:
82
+ OrderedDict[str, ParsedCommand]: 解析和验证后的命令字典
83
+ """
84
+ # 使用基础解析器解析
85
+ raw_commands = self.parse(query)
86
+
87
+ # 如果配置了全局 collect_remainder,需要调整参数分配
88
+ remainder_text = ""
89
+ if self.config.collect_remainder and raw_commands:
90
+ raw_commands, remainder_text = self._redistribute_args_for_global_remainder(
91
+ raw_commands
92
+ )
93
+
94
+ # 处理每个命令
95
+ typed_commands = OrderedDict()
96
+
97
+ for cmd_name, cmd_info in raw_commands.items():
98
+ raw_args = cmd_info["args"]
99
+ raw_kwargs = cmd_info["kwargs"]
100
+
101
+ # 获取命令配置
102
+ cmd_config = self.config.get_command_config(cmd_name)
103
+
104
+ if cmd_config:
105
+ # 有配置,进行验证和转换
106
+ parsed_cmd = self._process_configured_command(
107
+ cmd_name, cmd_config, raw_args, raw_kwargs
108
+ )
109
+ else:
110
+ # 无配置
111
+ if self.config.strict_mode:
112
+ # 严格模式下,未配置的命令是错误
113
+ parsed_cmd = ParsedCommand(
114
+ name=cmd_name,
115
+ raw_args=raw_args,
116
+ raw_kwargs=raw_kwargs,
117
+ errors=[f"Unknown command: {cmd_name}"],
118
+ )
119
+ else:
120
+ # 非严格模式,保持原样
121
+ parsed_cmd = ParsedCommand(
122
+ name=cmd_name,
123
+ args=raw_args,
124
+ kwargs=raw_kwargs,
125
+ raw_args=raw_args,
126
+ raw_kwargs=raw_kwargs,
127
+ )
128
+
129
+ typed_commands[cmd_name] = parsed_cmd
130
+
131
+ # 如果有剩余文本,添加到特殊的 remainder 命令中
132
+ if remainder_text:
133
+ remainder_cmd = ParsedCommand(
134
+ name=self.config.remainder_name,
135
+ args=[remainder_text],
136
+ kwargs={},
137
+ raw_args=[remainder_text],
138
+ raw_kwargs={},
139
+ remainder=remainder_text,
140
+ )
141
+ typed_commands[self.config.remainder_name] = remainder_cmd
142
+
143
+ return typed_commands
144
+
145
+ def _process_configured_command(
146
+ self,
147
+ cmd_name: str,
148
+ config: CommandConfig,
149
+ raw_args: List[str],
150
+ raw_kwargs: Dict[str, str],
151
+ ) -> ParsedCommand:
152
+ """
153
+ 处理有配置的命令
154
+
155
+ Args:
156
+ cmd_name: 命令名
157
+ config: 命令配置
158
+ raw_args: 原始位置参数
159
+ raw_kwargs: 原始键值对参数
160
+
161
+ Returns:
162
+ ParsedCommand: 处理后的命令
163
+ """
164
+ parsed_cmd = ParsedCommand(
165
+ name=cmd_name, raw_args=raw_args, raw_kwargs=raw_kwargs
166
+ )
167
+
168
+ # 验证参数
169
+ valid, errors = config.validate_args(raw_args, raw_kwargs)
170
+ if not valid:
171
+ parsed_cmd.errors.extend(errors)
172
+
173
+ # 处理位置参数
174
+ converted_args = []
175
+ remainder_args = []
176
+
177
+ for i, arg_value in enumerate(raw_args):
178
+ if i < len(config.positional_args):
179
+ # 有对应的配置
180
+ arg_config = config.positional_args[i]
181
+ converted_value = self._convert_value(arg_value, arg_config.type)
182
+ converted_args.append(converted_value)
183
+ else:
184
+ # 超出配置的参数
185
+ if config.collect_remainder:
186
+ remainder_args.append(arg_value)
187
+ else:
188
+ converted_args.append(arg_value)
189
+
190
+ # 添加默认值
191
+ for i in range(len(raw_args), len(config.positional_args)):
192
+ arg_config = config.positional_args[i]
193
+ if arg_config.default is not None:
194
+ converted_args.append(arg_config.default)
195
+ elif arg_config.constraint != ParamConstraint.REQUIRED:
196
+ # 可选参数,不添加
197
+ break
198
+
199
+ parsed_cmd.args = converted_args
200
+
201
+ # 处理剩余参数
202
+ if config.collect_remainder and remainder_args:
203
+ parsed_cmd.remainder = " ".join(remainder_args)
204
+
205
+ # 处理键值对参数
206
+ converted_kwargs = {}
207
+
208
+ for key, value in raw_kwargs.items():
209
+ if key in config.keyword_args:
210
+ arg_config = config.keyword_args[key]
211
+ converted_value = self._convert_value(value, arg_config.type)
212
+ converted_kwargs[key] = converted_value
213
+ else:
214
+ # 未配置的键值对
215
+ if not config.collect_remainder:
216
+ converted_kwargs[key] = value
217
+
218
+ # 添加默认值
219
+ for key, arg_config in config.keyword_args.items():
220
+ if key not in converted_kwargs and arg_config.default is not None:
221
+ converted_kwargs[key] = arg_config.default
222
+
223
+ parsed_cmd.kwargs = converted_kwargs
224
+
225
+ return parsed_cmd
226
+
227
+ def _extract_remainder(self, raw_commands: OrderedDict, query: str) -> str:
228
+ """
229
+ 提取剩余参数文本
230
+
231
+ Args:
232
+ raw_commands: 解析出的原始命令
233
+ query: 原始查询字符串
234
+
235
+ Returns:
236
+ 剩余参数文本
237
+ """
238
+ if not raw_commands:
239
+ return ""
240
+
241
+ # 获取最后一个命令
242
+ last_cmd_name = list(raw_commands.keys())[-1]
243
+ last_cmd_info = raw_commands[last_cmd_name]
244
+ last_cmd_config = self.config.get_command_config(last_cmd_name)
245
+
246
+ if not last_cmd_config:
247
+ # 如果最后一个命令没有配置,将其所有参数作为剩余参数
248
+ return " ".join(last_cmd_info["args"])
249
+
250
+ # 根据最后一个命令的配置决定如何处理剩余参数
251
+ raw_args = last_cmd_info["args"]
252
+ raw_kwargs = last_cmd_info["kwargs"]
253
+
254
+ remainder_args = []
255
+
256
+ if last_cmd_config.arg_type in [ArgType.POSITIONAL, ArgType.MIXED]:
257
+ # 如果有位置参数配置
258
+ if last_cmd_config.positional_args:
259
+ # 跳过已配置的位置参数数量
260
+ configured_count = len(last_cmd_config.positional_args)
261
+ if len(raw_args) > configured_count:
262
+ remainder_args = raw_args[configured_count:]
263
+ elif len(raw_args) == configured_count and not raw_kwargs:
264
+ # 如果位置参数刚好匹配且没有键值对参数,检查是否还有未解析的文本
265
+ # 这种情况需要从原始查询中重新提取
266
+ return self._extract_text_after_last_command(query, raw_commands)
267
+ else:
268
+ # 没有位置参数配置,所有位置参数都是剩余参数
269
+ remainder_args = raw_args
270
+
271
+ if last_cmd_config.arg_type in [ArgType.KEYWORD, ArgType.MIXED]:
272
+ # 如果是键值对类型,且没有位置参数配置,所有位置参数都是剩余参数
273
+ if not last_cmd_config.positional_args:
274
+ remainder_args = raw_args
275
+
276
+ return " ".join(remainder_args)
277
+
278
+ def _redistribute_args_for_global_remainder(
279
+ self, raw_commands: OrderedDict
280
+ ) -> Tuple[OrderedDict, str]:
281
+ """
282
+ 为全局 collect_remainder 重新分配参数
283
+
284
+ 根据每个命令的配置限制其参数数量,收集多余的参数作为全局 remainder
285
+
286
+ Args:
287
+ raw_commands: 原始解析的命令
288
+
289
+ Returns:
290
+ Tuple[OrderedDict, str]: 调整后的命令字典和剩余参数文本
291
+ """
292
+ adjusted_commands = OrderedDict()
293
+ all_remainder_args = []
294
+
295
+ for cmd_name, cmd_info in raw_commands.items():
296
+ raw_args = cmd_info["args"]
297
+ raw_kwargs = cmd_info["kwargs"]
298
+ cmd_config = self.config.get_command_config(cmd_name)
299
+
300
+ if cmd_config:
301
+ # 确定该命令应该接受的最大参数数量
302
+ max_args = None
303
+
304
+ if cmd_config.max_positional is not None:
305
+ # 明确设置了 max_positional
306
+ max_args = cmd_config.max_positional
307
+ elif cmd_config.positional_args:
308
+ # 根据位置参数配置推断
309
+ max_args = len(cmd_config.positional_args)
310
+ elif cmd_config.arg_type == ArgType.KEYWORD:
311
+ # 纯键值对命令,不接受位置参数
312
+ max_args = 0
313
+
314
+ if max_args is not None and len(raw_args) > max_args:
315
+ # 保留前 max_args 个参数,其余的加入 remainder
316
+ kept_args = raw_args[:max_args]
317
+ remainder_args = raw_args[max_args:]
318
+ all_remainder_args.extend(remainder_args)
319
+
320
+ adjusted_commands[cmd_name] = {
321
+ "args": kept_args,
322
+ "kwargs": raw_kwargs,
323
+ }
324
+ else:
325
+ # 参数数量在限制范围内,保持原样
326
+ adjusted_commands[cmd_name] = cmd_info
327
+ else:
328
+ # 没有配置,保持原样
329
+ adjusted_commands[cmd_name] = cmd_info
330
+
331
+ remainder_text = " ".join(all_remainder_args)
332
+ return adjusted_commands, remainder_text
333
+
334
+ def _extract_text_after_last_command(
335
+ self, query: str, raw_commands: OrderedDict
336
+ ) -> str:
337
+ """
338
+ 从原始查询中提取最后一个命令之后的文本
339
+
340
+ Args:
341
+ query: 原始查询字符串
342
+ raw_commands: 解析出的原始命令
343
+
344
+ Returns:
345
+ 最后一个命令之后的剩余文本
346
+ """
347
+ if not raw_commands:
348
+ return ""
349
+
350
+ # 找到最后一个命令在查询字符串中的位置
351
+ last_cmd_name = list(raw_commands.keys())[-1]
352
+ last_cmd_pattern = rf"/{re.escape(last_cmd_name)}\b"
353
+
354
+ # 找到最后一个命令的位置
355
+ matches = list(re.finditer(last_cmd_pattern, query))
356
+ if not matches:
357
+ return ""
358
+
359
+ last_match = matches[-1]
360
+ cmd_end_pos = last_match.end()
361
+
362
+ # 获取最后一个命令的参数
363
+ last_cmd_info = raw_commands[last_cmd_name]
364
+ remaining_text = query[cmd_end_pos:].strip()
365
+
366
+ # 移除已经解析的参数
367
+ for arg in last_cmd_info["args"]:
368
+ # 简单的文本替换,可能需要更精确的处理
369
+ arg_pattern = re.escape(arg)
370
+ remaining_text = re.sub(
371
+ rf"\b{arg_pattern}\b", "", remaining_text, 1
372
+ ).strip()
373
+
374
+ for key, value in last_cmd_info["kwargs"].items():
375
+ kv_pattern = rf"\b{re.escape(key)}={re.escape(value)}\b"
376
+ remaining_text = re.sub(kv_pattern, "", remaining_text).strip()
377
+
378
+ return remaining_text.strip()
379
+
380
+ def _convert_value(self, value: str, target_type: type) -> Any:
381
+ """
382
+ 转换值的类型
383
+
384
+ Args:
385
+ value: 字符串值
386
+ target_type: 目标类型
387
+
388
+ Returns:
389
+ 转换后的值
390
+ """
391
+ if target_type == str:
392
+ return value
393
+
394
+ if target_type == bool:
395
+ # 特殊处理布尔值
396
+ if value.lower() in ("true", "1", "yes", "on"):
397
+ return True
398
+ elif value.lower() in ("false", "0", "no", "off"):
399
+ return False
400
+ else:
401
+ return bool(value)
402
+
403
+ try:
404
+ return target_type(value)
405
+ except (ValueError, TypeError):
406
+ # 转换失败,返回原值
407
+ return value
408
+
409
+ def parse_with_config(
410
+ self, query: str, config: ParserConfig
411
+ ) -> OrderedDict[str, ParsedCommand]:
412
+ """
413
+ 使用指定配置解析命令
414
+
415
+ Args:
416
+ query: 命令行格式的查询字符串
417
+ config: 解析器配置
418
+
419
+ Returns:
420
+ OrderedDict[str, ParsedCommand]: 解析后的命令字典
421
+ """
422
+ old_config = self.config
423
+ self.config = config
424
+ try:
425
+ return self.parse_typed(query)
426
+ finally:
427
+ self.config = old_config
428
+
429
+
430
+ class CommandWrapper:
431
+ """
432
+ 命令包装器,提供对命令参数的便捷访问
433
+ """
434
+
435
+ def __init__(
436
+ self, parsed_cmd: ParsedCommand, config: Optional[ParserConfig] = None
437
+ ):
438
+ self._parsed_cmd = parsed_cmd
439
+ self._config = config
440
+
441
+ def __getattr__(self, name: str) -> Any:
442
+ """通过属性访问命令参数"""
443
+ if name.startswith("_"):
444
+ raise AttributeError(
445
+ f"'{self.__class__.__name__}' object has no attribute '{name}'"
446
+ )
447
+
448
+ # 查找位置参数配置
449
+ cmd_config = None
450
+ if self._config:
451
+ cmd_config = self._config.get_command_config(self._parsed_cmd.name)
452
+
453
+ if cmd_config:
454
+ # 如果有剩余参数且参数名匹配命令配置的 remainder_name
455
+ if self._parsed_cmd.remainder and name == cmd_config.remainder_name:
456
+ return self._parsed_cmd.remainder
457
+
458
+ # 查找位置参数
459
+ for i, arg_config in enumerate(cmd_config.positional_args):
460
+ if arg_config.name == name and i < len(self._parsed_cmd.args):
461
+ return self._parsed_cmd.args[i]
462
+
463
+ # 查找键值对参数
464
+ if name in self._parsed_cmd.kwargs:
465
+ return self._parsed_cmd.kwargs[name]
466
+
467
+ # 如果键值对参数在配置中但不在 kwargs 中(用户没有提供),检查默认值
468
+ if name in cmd_config.keyword_args:
469
+ arg_config = cmd_config.keyword_args[name]
470
+ # 如果有默认值,返回默认值;否则返回 None(因为它是可选的)
471
+ return arg_config.default if arg_config.default is not None else None
472
+
473
+ # 如果没有配置,尝试通过索引访问
474
+ if name == "remainder" and self._parsed_cmd.remainder:
475
+ return self._parsed_cmd.remainder
476
+
477
+ # 回退到原始行为(用于没有配置的命令)
478
+ if self._parsed_cmd.kwargs and name in self._parsed_cmd.kwargs:
479
+ return self._parsed_cmd.kwargs[name]
480
+
481
+ # 只有在没有任何配置的情况下,才使用单参数回退
482
+ # 如果有配置但没有匹配到,应该抛出 AttributeError
483
+ if not cmd_config:
484
+ # 如果是简单的单参数情况,直接返回第一个参数
485
+ if len(self._parsed_cmd.args) == 1 and not self._parsed_cmd.kwargs:
486
+ return self._parsed_cmd.args[0]
487
+
488
+ raise AttributeError(
489
+ f"'{self.__class__.__name__}' object has no attribute '{name}'"
490
+ )
491
+
492
+ def __repr__(self) -> str:
493
+ return f"CommandWrapper({self._parsed_cmd.name})"
494
+
495
+
496
+ @dataclass
497
+ class TypedQueryCommand:
498
+ """
499
+ 类型化的查询命令结果,提供便捷的属性访问
500
+
501
+ 与 QueryCommand 类似,但支持类型转换和验证
502
+ """
503
+
504
+ _commands: OrderedDict[str, ParsedCommand] = field(default_factory=OrderedDict)
505
+ _config: Optional[ParserConfig] = None
506
+ _query: str = ""
507
+
508
+ def __getattr__(self, name: str) -> Any:
509
+ """通过属性访问命令参数"""
510
+ if name.startswith("_"):
511
+ raise AttributeError(
512
+ f"'{self.__class__.__name__}' object has no attribute '{name}'"
513
+ )
514
+
515
+ # 特殊处理 query 属性 - 优先从配置的 remainder_name 获取
516
+ if name == "query":
517
+ if self._config and self._config.collect_remainder:
518
+ remainder_name = self._config.remainder_name
519
+ if remainder_name in self._commands:
520
+ remainder_cmd = self._commands[remainder_name]
521
+ return remainder_cmd.remainder or ""
522
+ return self._query
523
+
524
+ # 查找命令
525
+ parsed_cmd = self._get_command(name)
526
+ if parsed_cmd:
527
+ # 获取命令配置
528
+ cmd_config = None
529
+ if self._config:
530
+ cmd_config = self._config.get_command_config(parsed_cmd.name)
531
+
532
+ # 如果有配置(位置参数或键值对参数),检查是否需要 CommandWrapper
533
+ if cmd_config and (cmd_config.positional_args or cmd_config.keyword_args):
534
+ # 特殊处理:如果只有一个位置参数且参数名为 "value",且没有剩余参数和键值对参数,直接返回值
535
+ if (
536
+ len(cmd_config.positional_args) == 1
537
+ and cmd_config.positional_args[0].name == "value"
538
+ and len(parsed_cmd.args) == 1
539
+ and not parsed_cmd.remainder
540
+ and not parsed_cmd.kwargs
541
+ ):
542
+ return parsed_cmd.args[0]
543
+ # 其他情况返回 CommandWrapper 以支持嵌套访问
544
+ return CommandWrapper(parsed_cmd, self._config)
545
+
546
+ # 如果有剩余参数但没有位置参数配置,直接返回剩余参数
547
+ if parsed_cmd.remainder:
548
+ return parsed_cmd.remainder
549
+
550
+ # 如果有键值对参数但没有配置,返回字典
551
+ if parsed_cmd.kwargs:
552
+ return parsed_cmd.kwargs
553
+
554
+ # 如果有位置参数
555
+ if parsed_cmd.args:
556
+ return (
557
+ parsed_cmd.args[0] if len(parsed_cmd.args) == 1 else parsed_cmd.args
558
+ )
559
+
560
+ # 命令存在但没有参数
561
+ return ""
562
+
563
+ return None
564
+
565
+ def _get_command(self, name: str) -> Optional[ParsedCommand]:
566
+ """获取命令(支持连字符转换)"""
567
+ # 直接查找
568
+ if name in self._commands:
569
+ return self._commands[name]
570
+
571
+ # 尝试连字符转换
572
+ hyphen_name = name.replace("_", "-")
573
+ if hyphen_name in self._commands:
574
+ return self._commands[hyphen_name]
575
+
576
+ return None
577
+
578
+ def has_command(self, command: str) -> bool:
579
+ """检查是否包含指定命令"""
580
+ return self._get_command(command) is not None
581
+
582
+ def get_command(self, command: str) -> Optional[ParsedCommand]:
583
+ """获取解析后的命令对象"""
584
+ return self._get_command(command)
585
+
586
+ def get_errors(self) -> Dict[str, List[str]]:
587
+ """获取所有命令的错误"""
588
+ errors = {}
589
+ for cmd_name, parsed_cmd in self._commands.items():
590
+ if parsed_cmd.errors:
591
+ errors[cmd_name] = parsed_cmd.errors
592
+ return errors
593
+
594
+ def is_valid(self) -> bool:
595
+ """检查是否所有命令都有效"""
596
+ return all(cmd.is_valid for cmd in self._commands.values())
597
+
598
+ def __repr__(self) -> str:
599
+ """返回对象的字符串表示"""
600
+ commands_str = ", ".join(self._commands.keys())
601
+ valid_str = "valid" if self.is_valid() else "has errors"
602
+ return f"TypedQueryCommand(commands=[{commands_str}], {valid_str})"
603
+
604
+
605
+ def parse_typed_query(
606
+ query: str, config: Optional[ParserConfig] = None
607
+ ) -> TypedQueryCommand:
608
+ """
609
+ 解析类型化的查询命令
610
+
611
+ Args:
612
+ query: 命令行格式的查询字符串
613
+ config: 解析器配置
614
+
615
+ Returns:
616
+ TypedQueryCommand: 类型化的查询命令对象
617
+
618
+ Example:
619
+ >>> from autocoder.common.ac_style_command_parser import create_config
620
+ >>>
621
+ >>> config = (create_config()
622
+ ... .command("model")
623
+ ... .positional("name", required=True)
624
+ ... .command("temperature")
625
+ ... .positional("value", type=float)
626
+ ... .build()
627
+ ... )
628
+ >>>
629
+ >>> result = parse_typed_query("/model gpt-4 /temperature 0.8", config)
630
+ >>> print(result.model) # "gpt-4"
631
+ >>> print(result.temperature) # 0.8 (float类型)
632
+ >>> print(result.is_valid()) # True
633
+ """
634
+ parser = TypedCommandParser(config)
635
+ parsed_commands = parser.parse_typed(query)
636
+
637
+ result = TypedQueryCommand()
638
+ result._commands = parsed_commands
639
+ result._config = config
640
+
641
+ # 如果配置了全局 collect_remainder,query 会从特殊的 remainder 命令中获取
642
+ # 否则,从第一个有剩余参数的命令中获取
643
+ if config and config.collect_remainder:
644
+ # query 会通过 __getattr__ 自动从 remainder_name 命令中获取
645
+ pass
646
+ else:
647
+ # 兼容旧的行为:从第一个有剩余参数的命令中获取
648
+ for cmd_name, parsed_cmd in parsed_commands.items():
649
+ if parsed_cmd.remainder:
650
+ result._query = parsed_cmd.remainder
651
+ break
652
+
653
+ return result