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
@@ -9,6 +9,7 @@ import uuid
9
9
  import logging
10
10
  import difflib
11
11
  import time
12
+ import hashlib
12
13
  from typing import Dict, List, Optional, Tuple, Any
13
14
  from datetime import datetime
14
15
 
@@ -22,6 +23,23 @@ from autocoder.common.file_checkpoint.conversation_checkpoint import Conversatio
22
23
  logger = logging.getLogger(__name__)
23
24
 
24
25
 
26
+ def _generate_checkpoint_id(input_string: str) -> str:
27
+ """
28
+ 根据输入字符串生成安全的checkpoint_id
29
+
30
+ Args:
31
+ input_string: 输入字符串(通常是change_group_id或文件路径)
32
+
33
+ Returns:
34
+ str: MD5哈希生成的checkpoint_id
35
+ """
36
+ if not input_string:
37
+ return str(uuid.uuid4())
38
+
39
+ # 使用MD5生成固定长度的哈希值
40
+ return hashlib.md5(input_string.encode('utf-8')).hexdigest()
41
+
42
+
25
43
  class FileChangeManager:
26
44
  """文件变更管理器,提供高层次的API接口"""
27
45
 
@@ -48,15 +66,14 @@ class FileChangeManager:
48
66
  parent_dir = os.path.dirname(store_dir)
49
67
  conversation_store_dir = os.path.join(parent_dir, "conversation_checkpoints")
50
68
 
51
- try:
52
- self.conversation_store = ConversationCheckpointStore(conversation_store_dir, max_history)
53
- logger.info(f"对话检查点存储初始化成功: {conversation_store_dir}")
54
- except ImportError as e:
55
- logger.warning(f"对话检查点存储初始化失败: {str(e)}")
56
- self.conversation_store = None
69
+ # 让异常直接抛出,确保 conversation_store 始终可用
70
+ self.conversation_store = ConversationCheckpointStore(conversation_store_dir, max_history)
71
+ logger.info(f"对话检查点存储初始化成功: {conversation_store_dir}")
57
72
 
58
73
  def apply_changes_with_conversation(self, changes: Dict[str, FileChange],
59
- conversations: List[Dict[str, Any]],
74
+ conversation_id: str,
75
+ first_message_id: Optional[str] = None,
76
+ last_message_id: Optional[str] = None,
60
77
  change_group_id: Optional[str] = None,
61
78
  metadata: Optional[Dict[str, Any]] = None) -> ApplyResult:
62
79
  """
@@ -64,31 +81,55 @@ class FileChangeManager:
64
81
 
65
82
  Args:
66
83
  changes: 文件变更字典,格式为 {file_path: FileChange}
67
- conversations: 当前对话历史
84
+ conversation_id: 对话会话ID
85
+ first_message_id: 对话消息区间起始ID
86
+ last_message_id: 对话消息区间结束ID
68
87
  change_group_id: 变更组ID,用于将相关变更归为一组
69
88
  metadata: 元数据,可包含额外信息
70
89
 
71
90
  Returns:
72
91
  ApplyResult: 应用结果对象
73
92
  """
93
+ # 记录原始的change_group_id是否为None
94
+ original_group_id_is_none = change_group_id is None
95
+
74
96
  # 应用文件变更
75
97
  result = self.apply_changes(changes, change_group_id)
76
98
 
77
- if result.success and self.conversation_store is not None:
99
+ if result.success:
78
100
  try:
101
+ # 创建并保存对话检查点
102
+ # 生成安全的checkpoint_id(使用MD5哈希)
103
+ if not original_group_id_is_none:
104
+ # 用户提供了group_id,使用MD5哈希
105
+ checkpoint_id = _generate_checkpoint_id(change_group_id)
106
+ else:
107
+ # 用户没有提供group_id,我们需要获取实际使用的group_id
108
+ if result.change_ids:
109
+ # 获取第一个变更的记录来找到实际的group_id
110
+ first_change = self.change_store.get_change(result.change_ids[0])
111
+ if first_change and first_change.group_id:
112
+ checkpoint_id = _generate_checkpoint_id(first_change.group_id)
113
+ else:
114
+ checkpoint_id = result.change_ids[0]
115
+ else:
116
+ checkpoint_id = str(uuid.uuid4())
79
117
 
80
- # 创建并保存对话检查点
81
- checkpoint_id = change_group_id or result.change_ids[0] if result.change_ids else str(uuid.uuid4())
82
118
  checkpoint = ConversationCheckpoint(
83
119
  checkpoint_id=checkpoint_id,
84
120
  timestamp=time.time(),
85
- conversations=conversations,
121
+ conversation_id=conversation_id,
122
+ first_message_id=first_message_id,
123
+ last_message_id=last_message_id,
86
124
  metadata=metadata
87
125
  )
88
- self.conversation_store.save_checkpoint(checkpoint)
126
+
127
+ saved_id = self.conversation_store.save_checkpoint(checkpoint)
89
128
  logger.info(f"已保存对话检查点: {checkpoint_id}")
90
129
  except Exception as e:
91
130
  logger.error(f"保存对话检查点失败: {str(e)}")
131
+ else:
132
+ logger.warning(f"文件变更应用失败,跳过对话检查点保存")
92
133
 
93
134
  return result
94
135
 
@@ -265,16 +306,17 @@ class FileChangeManager:
265
306
 
266
307
  # 获取关联的对话检查点
267
308
  checkpoint = None
268
- checkpoint_id = change_record.group_id or change_id
269
- if self.conversation_store is not None:
270
- try:
271
- checkpoint = self.conversation_store.get_checkpoint(checkpoint_id)
272
- if checkpoint:
273
- logger.info(f"找到关联的对话检查点: {checkpoint_id}")
274
- else:
275
- logger.info(f"未找到关联的对话检查点: {checkpoint_id}")
276
- except Exception as e:
277
- logger.error(f"获取对话检查点失败: {str(e)}")
309
+ # 生成安全的checkpoint_id
310
+ checkpoint_id = _generate_checkpoint_id(change_record.group_id) if change_record.group_id else change_id
311
+
312
+ try:
313
+ checkpoint = self.conversation_store.get_checkpoint(checkpoint_id)
314
+ if checkpoint:
315
+ logger.info(f"找到关联的对话检查点: {checkpoint_id}")
316
+ else:
317
+ logger.debug(f"未找到关联的对话检查点: {checkpoint_id}")
318
+ except Exception as e:
319
+ logger.error(f"获取对话检查点失败: {str(e)}")
278
320
 
279
321
  # 撤销文件变更
280
322
  undo_result = self.undo_change(change_id)
@@ -359,15 +401,16 @@ class FileChangeManager:
359
401
 
360
402
  # 获取关联的对话检查点
361
403
  checkpoint = None
362
- if self.conversation_store is not None:
363
- try:
364
- checkpoint = self.conversation_store.get_checkpoint(group_id)
365
- if checkpoint:
366
- logger.info(f"找到关联的对话检查点: {group_id}")
367
- else:
368
- logger.info(f"未找到关联的对话检查点: {group_id}")
369
- except Exception as e:
370
- logger.error(f"获取对话检查点失败: {str(e)}")
404
+ checkpoint_id = _generate_checkpoint_id(group_id) if group_id else group_id
405
+
406
+ try:
407
+ checkpoint = self.conversation_store.get_checkpoint(checkpoint_id)
408
+ if checkpoint:
409
+ logger.info(f"找到关联的对话检查点: {checkpoint_id}")
410
+ else:
411
+ logger.debug(f"未找到关联的对话检查点: {checkpoint_id}")
412
+ except Exception as e:
413
+ logger.error(f"获取对话检查点失败: {str(e)}")
371
414
 
372
415
  # 撤销文件变更
373
416
  undo_result = self.undo_change_group(group_id)
@@ -422,16 +465,16 @@ class FileChangeManager:
422
465
 
423
466
  # 获取关联的对话检查点
424
467
  checkpoint = None
425
- checkpoint_id = target_change.group_id or version_id
426
- if self.conversation_store is not None:
427
- try:
428
- checkpoint = self.conversation_store.get_checkpoint(checkpoint_id)
429
- if checkpoint:
430
- logger.info(f"找到关联的对话检查点: {checkpoint_id}")
431
- else:
432
- logger.info(f"未找到关联的对话检查点: {checkpoint_id}")
433
- except Exception as e:
434
- logger.error(f"获取对话检查点失败: {str(e)}")
468
+ checkpoint_id = _generate_checkpoint_id(target_change.group_id) if target_change.group_id else version_id
469
+
470
+ try:
471
+ checkpoint = self.conversation_store.get_checkpoint(checkpoint_id)
472
+ if checkpoint:
473
+ logger.info(f"找到关联的对话检查点: {checkpoint_id}")
474
+ else:
475
+ logger.debug(f"未找到关联的对话检查点: {checkpoint_id}")
476
+ except Exception as e:
477
+ logger.error(f"获取对话检查点失败: {str(e)}")
435
478
 
436
479
  # 撤销文件变更
437
480
  undo_result = self.undo_to_version(version_id)
@@ -551,12 +594,11 @@ class FileChangeManager:
551
594
  has_conversation = False
552
595
 
553
596
  # 检查是否有对话检查点
554
- if self.conversation_store is not None:
555
- try:
556
- checkpoint = self.conversation_store.get_checkpoint(group_id)
557
- has_conversation = checkpoint is not None
558
- except Exception as e:
559
- logger.error(f"获取对话检查点失败: {str(e)}")
597
+ try:
598
+ checkpoint = self.conversation_store.get_checkpoint(group_id)
599
+ has_conversation = checkpoint is not None
600
+ except Exception as e:
601
+ logger.error(f"获取对话检查点失败: {str(e)}")
560
602
 
561
603
  checkpoints.append({
562
604
  "id": group_id,
@@ -567,6 +609,180 @@ class FileChangeManager:
567
609
 
568
610
  return checkpoints
569
611
 
612
+ def get_checkpointed_message_ids(self, conversation_id: str) -> List[str]:
613
+ """
614
+ 获取所有有checkpoint的message_id(只返回last_message_id)
615
+
616
+ Args:
617
+ conversation_id: 对话ID
618
+
619
+ Returns:
620
+ List[str]: 有checkpoint关联的last_message_id列表
621
+ """
622
+ checkpointed_message_ids = []
623
+
624
+ try:
625
+ # 获取所有变更组
626
+ change_groups = self.get_change_groups(limit=1000) # 获取更多的记录
627
+
628
+ # 遍历每个变更组,查找对应的checkpoint
629
+ for group_id, _, _ in change_groups:
630
+ # 生成安全的checkpoint_id
631
+ checkpoint_id = _generate_checkpoint_id(group_id) if group_id else group_id
632
+
633
+ try:
634
+ checkpoint = self.conversation_store.get_checkpoint(checkpoint_id)
635
+ if checkpoint and checkpoint.conversation_id == conversation_id:
636
+ # 只收集last_message_id
637
+ if checkpoint.last_message_id and checkpoint.last_message_id not in checkpointed_message_ids:
638
+ checkpointed_message_ids.append(checkpoint.last_message_id)
639
+ except Exception as e:
640
+ logger.debug(f"获取checkpoint {checkpoint_id} 失败: {str(e)}")
641
+ continue
642
+
643
+ # 也检查没有group_id的单独变更
644
+ latest_changes = self.change_store.get_latest_changes(limit=100)
645
+ for change in latest_changes:
646
+ if not change.group_id: # 单独的变更
647
+ checkpoint_id = change.change_id
648
+ try:
649
+ checkpoint = self.conversation_store.get_checkpoint(checkpoint_id)
650
+ if checkpoint and checkpoint.conversation_id == conversation_id:
651
+ if checkpoint.last_message_id and checkpoint.last_message_id not in checkpointed_message_ids:
652
+ checkpointed_message_ids.append(checkpoint.last_message_id)
653
+ except Exception:
654
+ continue
655
+
656
+ logger.info(f"找到 {len(checkpointed_message_ids)} 个有checkpoint的last_message_id")
657
+ return checkpointed_message_ids
658
+
659
+ except Exception as e:
660
+ logger.error(f"获取checkpointed message_ids失败: {str(e)}")
661
+ return checkpointed_message_ids
662
+
663
+ def rollback_to_message(self, message_id: str, conversation_id: Optional[str] = None) -> Tuple[UndoResult, Optional[ConversationCheckpoint]]:
664
+ """
665
+ 回滚到指定message_id所在的checkpoint
666
+
667
+ Args:
668
+ message_id: 目标消息ID
669
+ conversation_id: 可选的对话ID,用于过滤checkpoint
670
+
671
+ Returns:
672
+ Tuple[UndoResult, Optional[ConversationCheckpoint]]: 回滚结果和找到的对话检查点
673
+ """
674
+ try:
675
+ # 查找包含该message_id的checkpoint
676
+ found_checkpoint = None
677
+ found_group_id = None
678
+ found_change_id = None
679
+
680
+ # 先检查有group_id的变更
681
+ change_groups = self.get_change_groups(limit=1000)
682
+ for group_id, _, _ in change_groups:
683
+ checkpoint_id = _generate_checkpoint_id(group_id) if group_id else group_id
684
+
685
+ try:
686
+ checkpoint = self.conversation_store.get_checkpoint(checkpoint_id)
687
+ if checkpoint:
688
+ # 检查message_id是否在这个checkpoint的范围内
689
+ is_in_range = False
690
+
691
+ # 检查是否匹配conversation_id(如果提供了)
692
+ if conversation_id and checkpoint.conversation_id != conversation_id:
693
+ continue
694
+
695
+ if checkpoint.first_message_id == message_id or checkpoint.last_message_id == message_id:
696
+ is_in_range = True
697
+ elif checkpoint.first_message_id and checkpoint.last_message_id:
698
+ # 简化版本:如果message_id在checkpoint的范围内,我们假设它匹配
699
+ # 注意:这里无法准确判断message_id是否在范围内,除非有完整的消息列表
700
+ # 但如果first或last匹配,我们已经在上面处理了
701
+ pass
702
+
703
+ if is_in_range:
704
+ found_checkpoint = checkpoint
705
+ found_group_id = group_id
706
+ logger.info(f"找到包含message_id {message_id} 的checkpoint (group: {group_id})")
707
+ break
708
+
709
+ except Exception as e:
710
+ logger.debug(f"检查checkpoint {checkpoint_id} 时出错: {str(e)}")
711
+ continue
712
+
713
+ # 如果没找到,检查单独的变更
714
+ if not found_checkpoint:
715
+ latest_changes = self.change_store.get_latest_changes(limit=100)
716
+ for change in latest_changes:
717
+ if not change.group_id:
718
+ checkpoint_id = change.change_id
719
+ try:
720
+ checkpoint = self.conversation_store.get_checkpoint(checkpoint_id)
721
+ if checkpoint:
722
+ if (checkpoint.first_message_id == message_id or
723
+ checkpoint.last_message_id == message_id):
724
+ found_checkpoint = checkpoint
725
+ found_change_id = change.change_id
726
+ logger.info(f"找到包含message_id {message_id} 的checkpoint (change: {change.change_id})")
727
+ break
728
+ except Exception:
729
+ continue
730
+
731
+ if not found_checkpoint:
732
+ logger.warning(f"未找到包含message_id {message_id} 的checkpoint")
733
+ return UndoResult(success=False, errors={"general": f"未找到包含message_id {message_id} 的checkpoint"}), None
734
+
735
+ # 执行回滚
736
+ logger.info(f"开始回滚到message_id {message_id} 对应的checkpoint")
737
+
738
+ # 获取当前所有的变更记录
739
+ all_changes = self.change_store.get_latest_changes(limit=1000)
740
+
741
+ # 找到目标checkpoint对应的变更记录
742
+ target_timestamp = None
743
+ if found_group_id:
744
+ # 找到该组最后一个变更的时间戳
745
+ group_changes = self.change_store.get_changes_by_group(found_group_id)
746
+ if group_changes:
747
+ target_timestamp = max(change.timestamp for change in group_changes)
748
+ elif found_change_id:
749
+ # 找到该变更的时间戳
750
+ for change in all_changes:
751
+ if change.change_id == found_change_id:
752
+ target_timestamp = change.timestamp
753
+ break
754
+
755
+ if not target_timestamp:
756
+ return UndoResult(success=False, errors={"general": "无法确定回滚目标时间点"}), found_checkpoint
757
+
758
+ # 撤销所有在目标时间戳之后的变更
759
+ result = UndoResult(success=True)
760
+ changes_to_undo = []
761
+
762
+ for change in all_changes:
763
+ if change.timestamp > target_timestamp:
764
+ changes_to_undo.append(change)
765
+
766
+ # 按时间戳降序排序,确保按照相反的顺序撤销
767
+ changes_to_undo.sort(key=lambda x: x.timestamp, reverse=True)
768
+
769
+ logger.info(f"需要撤销 {len(changes_to_undo)} 个变更")
770
+
771
+ # 逐个撤销变更
772
+ for change in changes_to_undo:
773
+ change_result = self.undo_change(change.change_id)
774
+ result.success = result.success and change_result.success
775
+ result.restored_files.extend(change_result.restored_files)
776
+ result.errors.update(change_result.errors)
777
+
778
+ logger.info(f"回滚到message_id {message_id} 完成,恢复了 {len(result.restored_files)} 个文件")
779
+
780
+ return result, found_checkpoint
781
+
782
+ except Exception as e:
783
+ logger.error(f"回滚到message_id {message_id} 失败: {str(e)}")
784
+ return UndoResult(success=False, errors={"general": str(e)}), None
785
+
570
786
  def get_diff_text(self, old_content: str, new_content: str) -> str:
571
787
  """
572
788
  获取两个文本内容的差异文本
@@ -40,24 +40,7 @@ class TestFileBackupManager:
40
40
  assert manager.backup_dir == temp_backup_dir
41
41
  assert os.path.exists(temp_backup_dir)
42
42
 
43
- def test_init_with_default_dir(self, monkeypatch):
44
- """测试使用默认目录初始化"""
45
- # 创建一个临时主目录
46
- temp_home = tempfile.mkdtemp()
47
- try:
48
- # 模拟用户主目录
49
- monkeypatch.setattr(os.path, 'expanduser', lambda path: temp_home)
50
-
51
- manager = FileBackupManager()
52
-
53
- expected_dir = os.path.join(temp_home, ".autocoder", "backups")
54
- assert manager.backup_dir == expected_dir
55
- assert os.path.exists(expected_dir)
56
- finally:
57
- # 清理临时目录
58
- if os.path.exists(temp_home):
59
- shutil.rmtree(temp_home)
60
-
43
+
61
44
  def test_backup_file(self, temp_backup_dir, sample_file):
62
45
  """测试备份文件功能"""
63
46
  manager = FileBackupManager(backup_dir=temp_backup_dir)