auto-coder 0.1.400__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 (579) 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-0.1.400.dist-info → auto_coder-2.0.0.dist-info}/WHEEL +1 -1
  5. {auto_coder-0.1.400.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 +25 -4
  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 +1029 -2310
  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 +1021 -372
  28. autocoder/chat_auto_coder_lang.py +23 -732
  29. autocoder/commands/auto_command.py +26 -9
  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/file_monitor/test_file_monitor.py +307 -0
  119. autocoder/common/git_utils.py +51 -10
  120. autocoder/common/global_cancel.py +15 -6
  121. autocoder/common/ignorefiles/test_ignore_file_utils.py +1 -1
  122. autocoder/common/international/__init__.py +31 -0
  123. autocoder/common/international/demo_international.py +92 -0
  124. autocoder/common/international/message_manager.py +157 -0
  125. autocoder/common/international/messages/__init__.py +56 -0
  126. autocoder/common/international/messages/async_command_messages.py +507 -0
  127. autocoder/common/international/messages/auto_coder_messages.py +2208 -0
  128. autocoder/common/international/messages/chat_auto_coder_messages.py +1547 -0
  129. autocoder/common/international/messages/command_help_messages.py +986 -0
  130. autocoder/common/international/messages/conversation_command_messages.py +191 -0
  131. autocoder/common/international/messages/git_helper_plugin_messages.py +159 -0
  132. autocoder/common/international/messages/queue_command_messages.py +751 -0
  133. autocoder/common/international/messages/rules_command_messages.py +77 -0
  134. autocoder/common/international/messages/sdk_messages.py +1707 -0
  135. autocoder/common/international/messages/token_helper_plugin_messages.py +361 -0
  136. autocoder/common/international/messages/tool_display_messages.py +1212 -0
  137. autocoder/common/international/messages/workflow_exception_messages.py +473 -0
  138. autocoder/common/international/test_international.py +612 -0
  139. autocoder/common/linter_core/__init__.py +28 -0
  140. autocoder/common/linter_core/base_linter.py +61 -0
  141. autocoder/common/linter_core/config_loader.py +271 -0
  142. autocoder/common/linter_core/formatters/__init__.py +0 -0
  143. autocoder/common/linter_core/formatters/base_formatter.py +38 -0
  144. autocoder/common/linter_core/formatters/raw_formatter.py +17 -0
  145. autocoder/common/linter_core/linter.py +166 -0
  146. autocoder/common/linter_core/linter_factory.py +216 -0
  147. autocoder/common/linter_core/linter_manager.py +333 -0
  148. autocoder/common/linter_core/linters/__init__.py +9 -0
  149. autocoder/common/linter_core/linters/java_linter.py +342 -0
  150. autocoder/common/linter_core/linters/python_linter.py +115 -0
  151. autocoder/common/linter_core/linters/typescript_linter.py +119 -0
  152. autocoder/common/linter_core/models/__init__.py +7 -0
  153. autocoder/common/linter_core/models/lint_result.py +91 -0
  154. autocoder/common/linter_core/models.py +33 -0
  155. autocoder/common/linter_core/tests/__init__.py +3 -0
  156. autocoder/common/linter_core/tests/test_config_loader.py +323 -0
  157. autocoder/common/linter_core/tests/test_config_loading.py +308 -0
  158. autocoder/common/linter_core/tests/test_factory_manager.py +234 -0
  159. autocoder/common/linter_core/tests/test_formatters.py +147 -0
  160. autocoder/common/linter_core/tests/test_integration.py +317 -0
  161. autocoder/common/linter_core/tests/test_java_linter.py +496 -0
  162. autocoder/common/linter_core/tests/test_linters.py +265 -0
  163. autocoder/common/linter_core/tests/test_models.py +81 -0
  164. autocoder/common/linter_core/tests/verify_config_loading.py +296 -0
  165. autocoder/common/linter_core/tests/verify_fixes.py +183 -0
  166. autocoder/common/llm_friendly_package/__init__.py +31 -0
  167. autocoder/common/llm_friendly_package/base_manager.py +102 -0
  168. autocoder/common/llm_friendly_package/docs_manager.py +121 -0
  169. autocoder/common/llm_friendly_package/library_manager.py +171 -0
  170. autocoder/common/{llm_friendly_package.py → llm_friendly_package/main_manager.py} +204 -231
  171. autocoder/common/llm_friendly_package/models.py +40 -0
  172. autocoder/common/llm_friendly_package/test_llm_friendly_package.py +536 -0
  173. autocoder/common/llms/__init__.py +15 -0
  174. autocoder/common/llms/demo_error_handling.py +85 -0
  175. autocoder/common/llms/factory.py +142 -0
  176. autocoder/common/llms/manager.py +264 -0
  177. autocoder/common/llms/pricing.py +121 -0
  178. autocoder/common/llms/registry.py +288 -0
  179. autocoder/common/llms/schema.py +77 -0
  180. autocoder/common/llms/simple_demo.py +45 -0
  181. autocoder/common/llms/test_quick_model.py +116 -0
  182. autocoder/common/llms/test_remove_functionality.py +182 -0
  183. autocoder/common/llms/tests/__init__.py +1 -0
  184. autocoder/common/llms/tests/test_manager.py +330 -0
  185. autocoder/common/llms/tests/test_registry.py +364 -0
  186. autocoder/common/mcp_tools/__init__.py +62 -0
  187. autocoder/common/{mcp_tools.py → mcp_tools/executor.py} +49 -40
  188. autocoder/common/{mcp_hub.py → mcp_tools/hub.py} +42 -68
  189. autocoder/common/{mcp_server_install.py → mcp_tools/installer.py} +16 -28
  190. autocoder/common/{mcp_server.py → mcp_tools/server.py} +176 -48
  191. autocoder/common/mcp_tools/test_keyboard_interrupt.py +93 -0
  192. autocoder/common/mcp_tools/test_mcp_tools.py +391 -0
  193. autocoder/common/{mcp_server_types.py → mcp_tools/types.py} +121 -48
  194. autocoder/common/mcp_tools/verify_functionality.py +202 -0
  195. autocoder/common/model_speed_tester.py +32 -26
  196. autocoder/common/priority_directory_finder/__init__.py +142 -0
  197. autocoder/common/priority_directory_finder/examples.py +230 -0
  198. autocoder/common/priority_directory_finder/finder.py +283 -0
  199. autocoder/common/priority_directory_finder/models.py +236 -0
  200. autocoder/common/priority_directory_finder/test_priority_directory_finder.py +431 -0
  201. autocoder/common/project_scanner/__init__.py +18 -0
  202. autocoder/common/project_scanner/compat.py +77 -0
  203. autocoder/common/project_scanner/scanner.py +436 -0
  204. autocoder/common/project_tracker/__init__.py +27 -0
  205. autocoder/common/project_tracker/api.py +228 -0
  206. autocoder/common/project_tracker/demo.py +272 -0
  207. autocoder/common/project_tracker/tracker.py +487 -0
  208. autocoder/common/project_tracker/types.py +53 -0
  209. autocoder/common/pruner/__init__.py +67 -0
  210. autocoder/common/pruner/agentic_conversation_pruner.py +746 -0
  211. autocoder/common/{context_pruner.py → pruner/context_pruner.py} +137 -40
  212. autocoder/common/pruner/conversation_message_ids_api.py +386 -0
  213. autocoder/common/pruner/conversation_message_ids_manager.py +347 -0
  214. autocoder/common/pruner/conversation_message_ids_pruner.py +473 -0
  215. autocoder/common/pruner/conversation_normalizer.py +347 -0
  216. autocoder/common/{conversation_pruner.py → pruner/conversation_pruner.py} +26 -6
  217. autocoder/common/pruner/test_agentic_conversation_pruner.py +784 -0
  218. autocoder/common/pruner/test_context_pruner.py +546 -0
  219. autocoder/common/pruner/test_conversation_normalizer.py +502 -0
  220. autocoder/common/pruner/test_tool_content_detector.py +324 -0
  221. autocoder/common/pruner/tool_content_detector.py +227 -0
  222. autocoder/common/pruner/tools/__init__.py +18 -0
  223. autocoder/common/pruner/tools/query_message_ids.py +264 -0
  224. autocoder/common/pruner/tools/test_agentic_pruning_logic.py +432 -0
  225. autocoder/common/pruner/tools/test_message_ids_pruning_only.py +192 -0
  226. autocoder/common/pull_requests/__init__.py +9 -1
  227. autocoder/common/pull_requests/utils.py +122 -1
  228. autocoder/common/rag_manager/rag_manager.py +36 -40
  229. autocoder/common/rulefiles/__init__.py +53 -1
  230. autocoder/common/rulefiles/api.py +250 -0
  231. autocoder/common/rulefiles/core/__init__.py +14 -0
  232. autocoder/common/rulefiles/core/manager.py +241 -0
  233. autocoder/common/rulefiles/core/selector.py +805 -0
  234. autocoder/common/rulefiles/models/__init__.py +20 -0
  235. autocoder/common/rulefiles/models/index.py +16 -0
  236. autocoder/common/rulefiles/models/init_rule.py +18 -0
  237. autocoder/common/rulefiles/models/rule_file.py +18 -0
  238. autocoder/common/rulefiles/models/rule_relevance.py +14 -0
  239. autocoder/common/rulefiles/models/summary.py +16 -0
  240. autocoder/common/rulefiles/test_rulefiles.py +776 -0
  241. autocoder/common/rulefiles/utils/__init__.py +34 -0
  242. autocoder/common/rulefiles/utils/monitor.py +86 -0
  243. autocoder/common/rulefiles/utils/parser.py +230 -0
  244. autocoder/common/save_formatted_log.py +67 -10
  245. autocoder/common/search_replace.py +8 -1
  246. autocoder/common/search_replace_patch/__init__.py +24 -0
  247. autocoder/common/search_replace_patch/base.py +115 -0
  248. autocoder/common/search_replace_patch/manager.py +248 -0
  249. autocoder/common/search_replace_patch/patch_replacer.py +304 -0
  250. autocoder/common/search_replace_patch/similarity_replacer.py +306 -0
  251. autocoder/common/search_replace_patch/string_replacer.py +181 -0
  252. autocoder/common/search_replace_patch/tests/__init__.py +3 -0
  253. autocoder/common/search_replace_patch/tests/run_tests.py +126 -0
  254. autocoder/common/search_replace_patch/tests/test_base.py +188 -0
  255. autocoder/common/search_replace_patch/tests/test_empty_line_insert.py +233 -0
  256. autocoder/common/search_replace_patch/tests/test_integration.py +389 -0
  257. autocoder/common/search_replace_patch/tests/test_manager.py +351 -0
  258. autocoder/common/search_replace_patch/tests/test_patch_replacer.py +316 -0
  259. autocoder/common/search_replace_patch/tests/test_regex_replacer.py +306 -0
  260. autocoder/common/search_replace_patch/tests/test_similarity_replacer.py +384 -0
  261. autocoder/common/shell_commands/__init__.py +197 -0
  262. autocoder/common/shell_commands/background_process_notifier.py +346 -0
  263. autocoder/common/shell_commands/command_executor.py +1127 -0
  264. autocoder/common/shell_commands/error_recovery.py +541 -0
  265. autocoder/common/shell_commands/exceptions.py +120 -0
  266. autocoder/common/shell_commands/interactive_executor.py +476 -0
  267. autocoder/common/shell_commands/interactive_pexpect_process.py +623 -0
  268. autocoder/common/shell_commands/interactive_process.py +744 -0
  269. autocoder/common/shell_commands/interactive_session_manager.py +1014 -0
  270. autocoder/common/shell_commands/monitoring.py +529 -0
  271. autocoder/common/shell_commands/process_cleanup.py +386 -0
  272. autocoder/common/shell_commands/process_manager.py +606 -0
  273. autocoder/common/shell_commands/test_interactive_pexpect_process.py +281 -0
  274. autocoder/common/shell_commands/tests/__init__.py +6 -0
  275. autocoder/common/shell_commands/tests/conftest.py +118 -0
  276. autocoder/common/shell_commands/tests/test_background_process_notifier.py +703 -0
  277. autocoder/common/shell_commands/tests/test_command_executor.py +448 -0
  278. autocoder/common/shell_commands/tests/test_error_recovery.py +305 -0
  279. autocoder/common/shell_commands/tests/test_exceptions.py +299 -0
  280. autocoder/common/shell_commands/tests/test_execute_batch.py +588 -0
  281. autocoder/common/shell_commands/tests/test_indented_batch_commands.py +244 -0
  282. autocoder/common/shell_commands/tests/test_integration.py +664 -0
  283. autocoder/common/shell_commands/tests/test_monitoring.py +546 -0
  284. autocoder/common/shell_commands/tests/test_performance.py +632 -0
  285. autocoder/common/shell_commands/tests/test_process_cleanup.py +397 -0
  286. autocoder/common/shell_commands/tests/test_process_manager.py +606 -0
  287. autocoder/common/shell_commands/tests/test_timeout_config.py +343 -0
  288. autocoder/common/shell_commands/tests/test_timeout_manager.py +520 -0
  289. autocoder/common/shell_commands/timeout_config.py +315 -0
  290. autocoder/common/shell_commands/timeout_manager.py +352 -0
  291. autocoder/common/terminal_paste/__init__.py +14 -0
  292. autocoder/common/terminal_paste/demo.py +145 -0
  293. autocoder/common/terminal_paste/demo_paste_functionality.py +95 -0
  294. autocoder/common/terminal_paste/paste_handler.py +200 -0
  295. autocoder/common/terminal_paste/paste_manager.py +118 -0
  296. autocoder/common/terminal_paste/tests/__init__.py +1 -0
  297. autocoder/common/terminal_paste/tests/test_paste_handler.py +182 -0
  298. autocoder/common/terminal_paste/tests/test_paste_manager.py +126 -0
  299. autocoder/common/terminal_paste/utils.py +163 -0
  300. autocoder/common/test_autocoder_args.py +232 -0
  301. autocoder/common/test_env_manager.py +173 -0
  302. autocoder/common/test_env_manager_integration.py +159 -0
  303. autocoder/common/text_similarity/__init__.py +9 -0
  304. autocoder/common/text_similarity/demo.py +216 -0
  305. autocoder/common/text_similarity/examples.py +266 -0
  306. autocoder/common/text_similarity/test_text_similarity.py +306 -0
  307. autocoder/common/text_similarity/text_similarity.py +194 -0
  308. autocoder/common/text_similarity/utils.py +125 -0
  309. autocoder/common/todos/__init__.py +61 -0
  310. autocoder/common/todos/cache/__init__.py +16 -0
  311. autocoder/common/todos/cache/base_cache.py +89 -0
  312. autocoder/common/todos/cache/cache_manager.py +228 -0
  313. autocoder/common/todos/cache/memory_cache.py +225 -0
  314. autocoder/common/todos/config.py +155 -0
  315. autocoder/common/todos/exceptions.py +35 -0
  316. autocoder/common/todos/get_todo_manager.py +161 -0
  317. autocoder/common/todos/manager.py +537 -0
  318. autocoder/common/todos/models.py +239 -0
  319. autocoder/common/todos/storage/__init__.py +14 -0
  320. autocoder/common/todos/storage/base_storage.py +76 -0
  321. autocoder/common/todos/storage/file_storage.py +278 -0
  322. autocoder/common/tokens/__init__.py +15 -0
  323. autocoder/common/tokens/counter.py +44 -2
  324. autocoder/common/tools_manager/__init__.py +17 -0
  325. autocoder/common/tools_manager/examples.py +162 -0
  326. autocoder/common/tools_manager/manager.py +385 -0
  327. autocoder/common/tools_manager/models.py +39 -0
  328. autocoder/common/tools_manager/test_tools_manager.py +303 -0
  329. autocoder/common/tools_manager/utils.py +191 -0
  330. autocoder/common/v2/agent/agentic_callbacks.py +270 -0
  331. autocoder/common/v2/agent/agentic_edit.py +2729 -2052
  332. autocoder/common/v2/agent/agentic_edit_change_manager.py +474 -0
  333. autocoder/common/v2/agent/agentic_edit_tools/__init__.py +43 -2
  334. autocoder/common/v2/agent/agentic_edit_tools/ac_mod_list_tool_resolver.py +279 -0
  335. autocoder/common/v2/agent/agentic_edit_tools/ac_mod_read_tool_resolver.py +40 -0
  336. autocoder/common/v2/agent/agentic_edit_tools/ac_mod_write_tool_resolver.py +52 -0
  337. autocoder/common/v2/agent/agentic_edit_tools/ask_followup_question_tool_resolver.py +8 -0
  338. autocoder/common/v2/agent/agentic_edit_tools/background_task_tool_resolver.py +1167 -0
  339. autocoder/common/v2/agent/agentic_edit_tools/base_tool_resolver.py +2 -2
  340. autocoder/common/v2/agent/agentic_edit_tools/conversation_message_ids_read_tool_resolver.py +214 -0
  341. autocoder/common/v2/agent/agentic_edit_tools/conversation_message_ids_write_tool_resolver.py +299 -0
  342. autocoder/common/v2/agent/agentic_edit_tools/count_tokens_tool_resolver.py +290 -0
  343. autocoder/common/v2/agent/agentic_edit_tools/execute_command_tool_resolver.py +565 -30
  344. autocoder/common/v2/agent/agentic_edit_tools/execute_workflow_tool_resolver.py +485 -0
  345. autocoder/common/v2/agent/agentic_edit_tools/extract_to_text_tool_resolver.py +225 -0
  346. autocoder/common/v2/agent/agentic_edit_tools/lint_report.py +79 -0
  347. autocoder/common/v2/agent/agentic_edit_tools/linter_config_models.py +343 -0
  348. autocoder/common/v2/agent/agentic_edit_tools/linter_enabled_tool_resolver.py +189 -0
  349. autocoder/common/v2/agent/agentic_edit_tools/list_files_tool_resolver.py +169 -101
  350. autocoder/common/v2/agent/agentic_edit_tools/load_extra_document_tool_resolver.py +349 -0
  351. autocoder/common/v2/agent/agentic_edit_tools/read_file_tool_resolver.py +244 -51
  352. autocoder/common/v2/agent/agentic_edit_tools/replace_in_file_tool_resolver.py +667 -147
  353. autocoder/common/v2/agent/agentic_edit_tools/run_named_subagents_tool_resolver.py +691 -0
  354. autocoder/common/v2/agent/agentic_edit_tools/search_files_tool_resolver.py +409 -140
  355. autocoder/common/v2/agent/agentic_edit_tools/session_interactive_tool_resolver.py +115 -0
  356. autocoder/common/v2/agent/agentic_edit_tools/session_start_tool_resolver.py +190 -0
  357. autocoder/common/v2/agent/agentic_edit_tools/session_stop_tool_resolver.py +76 -0
  358. autocoder/common/v2/agent/agentic_edit_tools/test_write_to_file_tool_resolver.py +209 -194
  359. autocoder/common/v2/agent/agentic_edit_tools/todo_read_tool_resolver.py +135 -0
  360. autocoder/common/v2/agent/agentic_edit_tools/todo_write_tool_resolver.py +328 -0
  361. autocoder/common/v2/agent/agentic_edit_tools/use_mcp_tool_resolver.py +2 -2
  362. autocoder/common/v2/agent/agentic_edit_tools/web_crawl_tool_resolver.py +557 -0
  363. autocoder/common/v2/agent/agentic_edit_tools/web_search_tool_resolver.py +600 -0
  364. autocoder/common/v2/agent/agentic_edit_tools/write_to_file_tool_resolver.py +56 -121
  365. autocoder/common/v2/agent/agentic_edit_types.py +386 -10
  366. autocoder/common/v2/agent/runner/__init__.py +31 -0
  367. autocoder/common/v2/agent/runner/base_runner.py +92 -0
  368. autocoder/common/v2/agent/runner/file_based_event_runner.py +217 -0
  369. autocoder/common/v2/agent/runner/sdk_runner.py +182 -0
  370. autocoder/common/v2/agent/runner/terminal_runner.py +396 -0
  371. autocoder/common/v2/agent/runner/tool_display.py +589 -0
  372. autocoder/common/v2/agent/test_agentic_callbacks.py +265 -0
  373. autocoder/common/v2/agent/test_agentic_edit.py +194 -0
  374. autocoder/common/v2/agent/tool_caller/__init__.py +24 -0
  375. autocoder/common/v2/agent/tool_caller/default_tool_resolver_map.py +135 -0
  376. autocoder/common/v2/agent/tool_caller/integration_test.py +172 -0
  377. autocoder/common/v2/agent/tool_caller/plugins/__init__.py +14 -0
  378. autocoder/common/v2/agent/tool_caller/plugins/base_plugin.py +126 -0
  379. autocoder/common/v2/agent/tool_caller/plugins/examples/__init__.py +13 -0
  380. autocoder/common/v2/agent/tool_caller/plugins/examples/logging_plugin.py +164 -0
  381. autocoder/common/v2/agent/tool_caller/plugins/examples/security_filter_plugin.py +198 -0
  382. autocoder/common/v2/agent/tool_caller/plugins/plugin_interface.py +141 -0
  383. autocoder/common/v2/agent/tool_caller/test_tool_caller.py +278 -0
  384. autocoder/common/v2/agent/tool_caller/tool_call_plugin_manager.py +331 -0
  385. autocoder/common/v2/agent/tool_caller/tool_caller.py +337 -0
  386. autocoder/common/v2/agent/tool_caller/usage_example.py +193 -0
  387. autocoder/common/v2/code_agentic_editblock_manager.py +4 -4
  388. autocoder/common/v2/code_auto_generate.py +136 -78
  389. autocoder/common/v2/code_auto_generate_diff.py +135 -79
  390. autocoder/common/v2/code_auto_generate_editblock.py +174 -99
  391. autocoder/common/v2/code_auto_generate_strict_diff.py +151 -71
  392. autocoder/common/v2/code_auto_merge.py +1 -1
  393. autocoder/common/v2/code_auto_merge_editblock.py +13 -1
  394. autocoder/common/v2/code_diff_manager.py +3 -3
  395. autocoder/common/v2/code_editblock_manager.py +4 -14
  396. autocoder/common/v2/code_manager.py +1 -1
  397. autocoder/common/v2/code_strict_diff_manager.py +2 -2
  398. autocoder/common/wrap_llm_hint/__init__.py +10 -0
  399. autocoder/common/wrap_llm_hint/test_wrap_llm_hint.py +1067 -0
  400. autocoder/common/wrap_llm_hint/utils.py +432 -0
  401. autocoder/common/wrap_llm_hint/wrap_llm_hint.py +323 -0
  402. autocoder/completer/__init__.py +8 -0
  403. autocoder/completer/command_completer_v2.py +1051 -0
  404. autocoder/default_project/__init__.py +501 -0
  405. autocoder/dispacher/__init__.py +4 -12
  406. autocoder/dispacher/actions/action.py +165 -7
  407. autocoder/dispacher/actions/plugins/action_regex_project.py +2 -2
  408. autocoder/index/entry.py +117 -125
  409. autocoder/{agent → index/filter}/agentic_filter.py +323 -334
  410. autocoder/index/filter/normal_filter.py +5 -11
  411. autocoder/index/filter/quick_filter.py +1 -1
  412. autocoder/index/index.py +36 -9
  413. autocoder/index/tests/__init__.py +1 -0
  414. autocoder/index/tests/run_tests.py +195 -0
  415. autocoder/index/tests/test_entry.py +303 -0
  416. autocoder/index/tests/test_index_manager.py +314 -0
  417. autocoder/index/tests/test_module_integration.py +300 -0
  418. autocoder/index/tests/test_symbols_utils.py +183 -0
  419. autocoder/inner/__init__.py +4 -0
  420. autocoder/inner/agentic.py +932 -0
  421. autocoder/inner/async_command_handler.py +992 -0
  422. autocoder/inner/conversation_command_handlers.py +623 -0
  423. autocoder/inner/merge_command_handler.py +213 -0
  424. autocoder/inner/queue_command_handler.py +684 -0
  425. autocoder/models.py +95 -266
  426. autocoder/plugins/git_helper_plugin.py +31 -29
  427. autocoder/plugins/token_helper_plugin.py +156 -37
  428. autocoder/pyproject/__init__.py +32 -29
  429. autocoder/rag/agentic_rag.py +215 -75
  430. autocoder/rag/cache/simple_cache.py +1 -2
  431. autocoder/rag/loaders/image_loader.py +1 -1
  432. autocoder/rag/long_context_rag.py +42 -26
  433. autocoder/rag/qa_conversation_strategy.py +1 -1
  434. autocoder/rag/terminal/__init__.py +17 -0
  435. autocoder/rag/terminal/args.py +581 -0
  436. autocoder/rag/terminal/bootstrap.py +61 -0
  437. autocoder/rag/terminal/command_handlers.py +653 -0
  438. autocoder/rag/terminal/formatters/__init__.py +20 -0
  439. autocoder/rag/terminal/formatters/base.py +70 -0
  440. autocoder/rag/terminal/formatters/json_format.py +66 -0
  441. autocoder/rag/terminal/formatters/stream_json.py +95 -0
  442. autocoder/rag/terminal/formatters/text.py +28 -0
  443. autocoder/rag/terminal/init.py +120 -0
  444. autocoder/rag/terminal/utils.py +106 -0
  445. autocoder/rag/test_agentic_rag.py +389 -0
  446. autocoder/rag/test_doc_filter.py +3 -3
  447. autocoder/rag/test_long_context_rag.py +1 -1
  448. autocoder/rag/test_token_limiter.py +517 -10
  449. autocoder/rag/token_counter.py +3 -0
  450. autocoder/rag/token_limiter.py +19 -15
  451. autocoder/rag/tools/__init__.py +26 -2
  452. autocoder/rag/tools/bochaai_example.py +343 -0
  453. autocoder/rag/tools/bochaai_sdk.py +541 -0
  454. autocoder/rag/tools/metaso_example.py +268 -0
  455. autocoder/rag/tools/metaso_sdk.py +417 -0
  456. autocoder/rag/tools/recall_tool.py +28 -7
  457. autocoder/rag/tools/run_integration_tests.py +204 -0
  458. autocoder/rag/tools/test_all_providers.py +318 -0
  459. autocoder/rag/tools/test_bochaai_integration.py +482 -0
  460. autocoder/rag/tools/test_final_integration.py +215 -0
  461. autocoder/rag/tools/test_metaso_integration.py +424 -0
  462. autocoder/rag/tools/test_metaso_real.py +171 -0
  463. autocoder/rag/tools/test_web_crawl_tool.py +639 -0
  464. autocoder/rag/tools/test_web_search_tool.py +509 -0
  465. autocoder/rag/tools/todo_read_tool.py +202 -0
  466. autocoder/rag/tools/todo_write_tool.py +412 -0
  467. autocoder/rag/tools/web_crawl_tool.py +634 -0
  468. autocoder/rag/tools/web_search_tool.py +558 -0
  469. autocoder/rag/tools/web_tools_example.py +119 -0
  470. autocoder/rag/types.py +16 -0
  471. autocoder/rag/variable_holder.py +4 -2
  472. autocoder/rags.py +86 -79
  473. autocoder/regexproject/__init__.py +23 -21
  474. autocoder/run_context.py +9 -0
  475. autocoder/sdk/__init__.py +50 -161
  476. autocoder/sdk/api.py +370 -0
  477. autocoder/sdk/async_runner/__init__.py +26 -0
  478. autocoder/sdk/async_runner/async_executor.py +650 -0
  479. autocoder/sdk/async_runner/async_handler.py +356 -0
  480. autocoder/sdk/async_runner/markdown_processor.py +595 -0
  481. autocoder/sdk/async_runner/task_metadata.py +284 -0
  482. autocoder/sdk/async_runner/worktree_manager.py +438 -0
  483. autocoder/sdk/cli/__init__.py +2 -5
  484. autocoder/sdk/cli/formatters.py +28 -204
  485. autocoder/sdk/cli/handlers.py +77 -44
  486. autocoder/sdk/cli/main.py +158 -170
  487. autocoder/sdk/cli/options.py +95 -22
  488. autocoder/sdk/constants.py +139 -51
  489. autocoder/sdk/core/auto_coder_core.py +484 -267
  490. autocoder/sdk/core/bridge.py +298 -118
  491. autocoder/sdk/exceptions.py +18 -12
  492. autocoder/sdk/formatters/__init__.py +19 -0
  493. autocoder/sdk/formatters/input.py +64 -0
  494. autocoder/sdk/formatters/output.py +247 -0
  495. autocoder/sdk/formatters/stream.py +54 -0
  496. autocoder/sdk/models/__init__.py +6 -5
  497. autocoder/sdk/models/options.py +55 -18
  498. autocoder/sdk/utils/formatters.py +27 -195
  499. autocoder/suffixproject/__init__.py +28 -25
  500. autocoder/terminal/__init__.py +14 -0
  501. autocoder/terminal/app.py +454 -0
  502. autocoder/terminal/args.py +32 -0
  503. autocoder/terminal/bootstrap.py +178 -0
  504. autocoder/terminal/command_processor.py +521 -0
  505. autocoder/terminal/command_registry.py +57 -0
  506. autocoder/terminal/help.py +97 -0
  507. autocoder/terminal/tasks/__init__.py +5 -0
  508. autocoder/terminal/tasks/background.py +77 -0
  509. autocoder/terminal/tasks/task_event.py +70 -0
  510. autocoder/terminal/ui/__init__.py +13 -0
  511. autocoder/terminal/ui/completer.py +268 -0
  512. autocoder/terminal/ui/keybindings.py +75 -0
  513. autocoder/terminal/ui/session.py +41 -0
  514. autocoder/terminal/ui/toolbar.py +64 -0
  515. autocoder/terminal/utils/__init__.py +13 -0
  516. autocoder/terminal/utils/errors.py +18 -0
  517. autocoder/terminal/utils/paths.py +19 -0
  518. autocoder/terminal/utils/shell.py +43 -0
  519. autocoder/terminal_v3/__init__.py +10 -0
  520. autocoder/terminal_v3/app.py +201 -0
  521. autocoder/terminal_v3/handlers/__init__.py +5 -0
  522. autocoder/terminal_v3/handlers/command_handler.py +131 -0
  523. autocoder/terminal_v3/models/__init__.py +6 -0
  524. autocoder/terminal_v3/models/conversation_buffer.py +214 -0
  525. autocoder/terminal_v3/models/message.py +50 -0
  526. autocoder/terminal_v3/models/tool_display.py +247 -0
  527. autocoder/terminal_v3/ui/__init__.py +7 -0
  528. autocoder/terminal_v3/ui/keybindings.py +56 -0
  529. autocoder/terminal_v3/ui/layout.py +141 -0
  530. autocoder/terminal_v3/ui/styles.py +43 -0
  531. autocoder/tsproject/__init__.py +23 -23
  532. autocoder/utils/auto_coder_utils/chat_stream_out.py +1 -1
  533. autocoder/utils/llms.py +88 -80
  534. autocoder/utils/math_utils.py +101 -0
  535. autocoder/utils/model_provider_selector.py +16 -4
  536. autocoder/utils/operate_config_api.py +33 -5
  537. autocoder/utils/thread_utils.py +2 -2
  538. autocoder/version.py +4 -2
  539. autocoder/workflow_agents/__init__.py +84 -0
  540. autocoder/workflow_agents/agent.py +143 -0
  541. autocoder/workflow_agents/exceptions.py +573 -0
  542. autocoder/workflow_agents/executor.py +489 -0
  543. autocoder/workflow_agents/loader.py +737 -0
  544. autocoder/workflow_agents/runner.py +267 -0
  545. autocoder/workflow_agents/types.py +172 -0
  546. autocoder/workflow_agents/utils.py +434 -0
  547. autocoder/workflow_agents/workflow_manager.py +211 -0
  548. auto_coder-0.1.400.dist-info/METADATA +0 -396
  549. auto_coder-0.1.400.dist-info/RECORD +0 -425
  550. auto_coder-0.1.400.dist-info/licenses/LICENSE +0 -201
  551. autocoder/auto_coder_server.py +0 -672
  552. autocoder/benchmark.py +0 -138
  553. autocoder/common/ac_style_command_parser/example.py +0 -7
  554. autocoder/common/cleaner.py +0 -31
  555. autocoder/common/command_completer_v2.py +0 -615
  556. autocoder/common/directory_cache/__init__.py +0 -1
  557. autocoder/common/directory_cache/cache.py +0 -192
  558. autocoder/common/directory_cache/test_cache.py +0 -190
  559. autocoder/common/file_checkpoint/examples.py +0 -217
  560. autocoder/common/llm_friendly_package_example.py +0 -138
  561. autocoder/common/llm_friendly_package_test.py +0 -63
  562. autocoder/common/pull_requests/test_module.py +0 -1
  563. autocoder/common/rulefiles/autocoderrules_utils.py +0 -484
  564. autocoder/common/text.py +0 -30
  565. autocoder/common/v2/agent/agentic_edit_tools/list_package_info_tool_resolver.py +0 -42
  566. autocoder/common/v2/agent/agentic_edit_tools/test_execute_command_tool_resolver.py +0 -70
  567. autocoder/common/v2/agent/agentic_edit_tools/test_search_files_tool_resolver.py +0 -163
  568. autocoder/common/v2/agent/agentic_tool_display.py +0 -183
  569. autocoder/plugins/dynamic_completion_example.py +0 -148
  570. autocoder/plugins/sample_plugin.py +0 -160
  571. autocoder/sdk/cli/__main__.py +0 -26
  572. autocoder/sdk/cli/completion_wrapper.py +0 -38
  573. autocoder/sdk/cli/install_completion.py +0 -301
  574. autocoder/sdk/models/messages.py +0 -209
  575. autocoder/sdk/session/__init__.py +0 -32
  576. autocoder/sdk/session/session.py +0 -106
  577. autocoder/sdk/session/session_manager.py +0 -56
  578. {auto_coder-0.1.400.dist-info → auto_coder-2.0.0.dist-info}/top_level.txt +0 -0
  579. /autocoder/{sdk/example.py → common/agent_query_queue/__init__.py} +0 -0
@@ -3,7 +3,7 @@ from typing import Tuple
3
3
  from pathlib import Path
4
4
  import json
5
5
  from loguru import logger
6
- from autocoder.rag.token_counter import count_tokens
6
+ from autocoder.common.tokens import count_string_tokens as count_tokens
7
7
  from autocoder.common import AutoCoderArgs, SourceCode
8
8
  from byzerllm.utils.client.code_utils import extract_code
9
9
  from autocoder.index.types import VerifyFileRelevance
@@ -15,11 +15,12 @@ from autocoder.common.auto_coder_lang import get_message_with_format
15
15
 
16
16
 
17
17
  class PruneContext:
18
- def __init__(self, max_tokens: int, args: AutoCoderArgs, llm: Union[byzerllm.ByzerLLM, byzerllm.SimpleByzerLLM]):
18
+ def __init__(self, max_tokens: int, args: AutoCoderArgs, llm: Union[byzerllm.ByzerLLM, byzerllm.SimpleByzerLLM], verbose: bool = False):
19
19
  self.max_tokens = max_tokens
20
20
  self.args = args
21
21
  self.llm = llm
22
22
  self.printer = Printer()
23
+ self.verbose = verbose
23
24
 
24
25
  def _split_content_with_sliding_window(self, content: str, window_size=100, overlap=20) -> List[Tuple[int, int, str]]:
25
26
  """使用滑动窗口分割大文件内容,返回包含行号信息的文本块
@@ -95,6 +96,11 @@ class PruneContext:
95
96
  token_count = 0
96
97
  selected_files = []
97
98
  full_file_tokens = int(self.max_tokens * 0.8)
99
+
100
+ if self.verbose:
101
+ total_input_tokens = sum(f.tokens for f in file_sources)
102
+ self.printer.print_str_in_terminal(f"🚀 开始代码片段抽取处理,共 {len(file_sources)} 个文件,总token数: {total_input_tokens}")
103
+ self.printer.print_str_in_terminal(f"📋 处理策略: 完整文件优先阈值={full_file_tokens}, 最大token限制={self.max_tokens}")
98
104
 
99
105
  @byzerllm.prompt()
100
106
  def extract_code_snippets(conversations: List[Dict[str, str]], content: str, is_partial_content: bool = False) -> str:
@@ -206,6 +212,8 @@ class PruneContext:
206
212
  selected_files.append(SourceCode(
207
213
  module_name=file_source.module_name, source_code=file_source.source_code, tokens=tokens))
208
214
  token_count += tokens
215
+ if self.verbose:
216
+ self.printer.print_str_in_terminal(f"✅ 文件 {file_source.module_name} 完整保留 (token数: {tokens},当前总token数: {token_count})")
209
217
  continue
210
218
 
211
219
  # 如果单个文件太大,那么先按滑动窗口分割,然后对窗口抽取代码片段
@@ -216,8 +224,16 @@ class PruneContext:
216
224
  chunks = self._split_content_with_sliding_window(file_source.source_code,
217
225
  self.args.context_prune_sliding_window_size,
218
226
  self.args.context_prune_sliding_window_overlap)
227
+
228
+ if self.verbose:
229
+ self.printer.print_str_in_terminal(f"📊 文件 {file_source.module_name} 通过滑动窗口分割为 {len(chunks)} 个chunks")
230
+
219
231
  all_snippets = []
220
- for chunk_start, chunk_end, chunk_content in chunks:
232
+ chunk_with_results = 0
233
+ for chunk_idx, (chunk_start, chunk_end, chunk_content) in enumerate(chunks):
234
+ if self.verbose:
235
+ self.printer.print_str_in_terminal(f" 🔍 处理chunk {chunk_idx + 1}/{len(chunks)} (行号: {chunk_start}-{chunk_end})")
236
+
221
237
  extracted = extract_code_snippets.with_llm(self.llm).run(
222
238
  conversations=conversations,
223
239
  content=chunk_content,
@@ -227,29 +243,61 @@ class PruneContext:
227
243
  json_str = extract_code(extracted)[0][1]
228
244
  snippets = json.loads(json_str)
229
245
 
230
- # 获取到的本来就是在原始文件里的绝对行号
231
- # 后续在构建代码片段内容时,会为了适配数组操作修改行号,这里无需处理
232
- adjusted_snippets = [{
233
- "start_line": snippet["start_line"],
234
- "end_line": snippet["end_line"]
235
- } for snippet in snippets]
236
- all_snippets.extend(adjusted_snippets)
237
- merged_snippets = self._merge_overlapping_snippets(
238
- all_snippets)
239
- content_snippets = self._build_snippet_content(
240
- file_source.module_name, file_source.source_code, merged_snippets)
241
- snippet_tokens = count_tokens(content_snippets)
242
- if token_count + snippet_tokens <= self.max_tokens:
243
- selected_files.append(SourceCode(
244
- module_name=file_source.module_name, source_code=content_snippets, tokens=snippet_tokens))
245
- token_count += snippet_tokens
246
- self.printer.print_in_terminal("file_snippet_procesed", file_path=file_source.module_name,
247
- total_tokens=token_count,
248
- tokens=tokens,
249
- snippet_tokens=snippet_tokens)
250
- continue
246
+ if snippets: # 有抽取结果
247
+ chunk_with_results += 1
248
+ if self.verbose:
249
+ self.printer.print_str_in_terminal(f" chunk {chunk_idx + 1} 抽取到 {len(snippets)} 个代码片段: {snippets}")
250
+
251
+ # 获取到的本来就是在原始文件里的绝对行号
252
+ # 后续在构建代码片段内容时,会为了适配数组操作修改行号,这里无需处理
253
+ adjusted_snippets = [{
254
+ "start_line": snippet["start_line"],
255
+ "end_line": snippet["end_line"]
256
+ } for snippet in snippets]
257
+ all_snippets.extend(adjusted_snippets)
258
+ else:
259
+ if self.verbose:
260
+ self.printer.print_str_in_terminal(f" ❌ chunk {chunk_idx + 1} 未抽取到相关代码片段")
261
+ else:
262
+ if self.verbose:
263
+ self.printer.print_str_in_terminal(f" ❌ chunk {chunk_idx + 1} 抽取失败,未返回结果")
264
+
265
+ if self.verbose:
266
+ self.printer.print_str_in_terminal(f"📈 滑动窗口处理完成: {chunk_with_results}/{len(chunks)} 个chunks有抽取结果,共收集到 {len(all_snippets)} 个代码片段")
267
+
268
+ merged_snippets = self._merge_overlapping_snippets(all_snippets)
269
+
270
+ if self.verbose:
271
+ self.printer.print_str_in_terminal(f"🔄 合并重叠片段: {len(all_snippets)} -> {len(merged_snippets)} 个片段")
272
+ if merged_snippets:
273
+ self.printer.print_str_in_terminal(f" 合并后的片段: {merged_snippets}")
274
+
275
+ # 只有当有代码片段时才处理
276
+ if merged_snippets:
277
+ content_snippets = self._build_snippet_content(
278
+ file_source.module_name, file_source.source_code, merged_snippets)
279
+ snippet_tokens = count_tokens(content_snippets)
280
+
281
+ if token_count + snippet_tokens <= self.max_tokens:
282
+ selected_files.append(SourceCode(
283
+ module_name=file_source.module_name, source_code=content_snippets, tokens=snippet_tokens))
284
+ token_count += snippet_tokens
285
+ self.printer.print_in_terminal("file_snippet_procesed", file_path=file_source.module_name,
286
+ total_tokens=token_count,
287
+ tokens=tokens,
288
+ snippet_tokens=snippet_tokens)
289
+ if self.verbose:
290
+ self.printer.print_str_in_terminal(f"✅ 文件 {file_source.module_name} 滑动窗口处理成功,最终抽取到结果")
291
+ continue
292
+ else:
293
+ if self.verbose:
294
+ self.printer.print_str_in_terminal(f"❌ 文件 {file_source.module_name} 滑动窗口处理后token数超限 ({token_count + snippet_tokens} > {self.max_tokens}),停止处理")
295
+ break
251
296
  else:
252
- break
297
+ # 滑动窗口处理后没有相关代码片段,跳过这个文件
298
+ if self.verbose:
299
+ self.printer.print_str_in_terminal(f"⏭️ 文件 {file_source.module_name} 滑动窗口处理后无相关代码片段,跳过处理")
300
+ continue
253
301
 
254
302
  # 抽取关键片段
255
303
  lines = file_source.source_code.splitlines()
@@ -262,6 +310,10 @@ class PruneContext:
262
310
  # 抽取代码片段
263
311
  self.printer.print_in_terminal(
264
312
  "file_snippet_processing", file_path=file_source.module_name)
313
+
314
+ if self.verbose:
315
+ self.printer.print_str_in_terminal(f"🔍 开始对文件 {file_source.module_name} 进行整体代码片段抽取 (共 {len(lines)} 行)")
316
+
265
317
  extracted = extract_code_snippets.with_llm(self.llm).run(
266
318
  conversations=conversations,
267
319
  content=new_content
@@ -271,25 +323,70 @@ class PruneContext:
271
323
  if extracted:
272
324
  json_str = extract_code(extracted)[0][1]
273
325
  snippets = json.loads(json_str)
274
- content_snippets = self._build_snippet_content(
275
- file_source.module_name, file_source.source_code, snippets)
276
-
277
- snippet_tokens = count_tokens(content_snippets)
278
- if token_count + snippet_tokens <= self.max_tokens:
279
- selected_files.append(SourceCode(module_name=file_source.module_name,
280
- source_code=content_snippets,
281
- tokens=snippet_tokens))
282
- token_count += snippet_tokens
283
- self.printer.print_in_terminal("file_snippet_procesed", file_path=file_source.module_name,
284
- total_tokens=token_count,
285
- tokens=tokens,
286
- snippet_tokens=snippet_tokens)
326
+
327
+ if self.verbose:
328
+ if snippets:
329
+ self.printer.print_str_in_terminal(f" ✅ 抽取到 {len(snippets)} 个代码片段: {snippets}")
330
+ else:
331
+ self.printer.print_str_in_terminal(f" ❌ 未抽取到相关代码片段")
332
+
333
+ # 只有当有代码片段时才处理
334
+ if snippets:
335
+ content_snippets = self._build_snippet_content(
336
+ file_source.module_name, file_source.source_code, snippets)
337
+
338
+ snippet_tokens = count_tokens(content_snippets)
339
+ if token_count + snippet_tokens <= self.max_tokens:
340
+ selected_files.append(SourceCode(module_name=file_source.module_name,
341
+ source_code=content_snippets,
342
+ tokens=snippet_tokens))
343
+ token_count += snippet_tokens
344
+ self.printer.print_in_terminal("file_snippet_procesed", file_path=file_source.module_name,
345
+ total_tokens=token_count,
346
+ tokens=tokens,
347
+ snippet_tokens=snippet_tokens)
348
+ if self.verbose:
349
+ self.printer.print_str_in_terminal(f"✅ 文件 {file_source.module_name} 整体抽取成功,最终抽取到结果")
350
+ else:
351
+ if self.verbose:
352
+ self.printer.print_str_in_terminal(f"❌ 文件 {file_source.module_name} 整体抽取后token数超限 ({token_count + snippet_tokens} > {self.max_tokens}),停止处理")
353
+ break
287
354
  else:
288
- break
355
+ # 没有相关代码片段,跳过这个文件
356
+ if self.verbose:
357
+ self.printer.print_str_in_terminal(f"⏭️ 文件 {file_source.module_name} 无相关代码片段,跳过处理")
358
+ else:
359
+ if self.verbose:
360
+ self.printer.print_str_in_terminal(f"❌ 文件 {file_source.module_name} 整体抽取失败,未返回结果")
289
361
  except Exception as e:
290
362
  logger.error(f"Failed to process {file_source.module_name}: {e}")
363
+ if self.verbose:
364
+ self.printer.print_str_in_terminal(f"❌ 文件 {file_source.module_name} 处理异常: {e}")
291
365
  continue
292
366
 
367
+ if self.verbose:
368
+ total_input_tokens = sum(f.tokens for f in file_sources)
369
+ final_tokens = sum(f.tokens for f in selected_files)
370
+ self.printer.print_str_in_terminal(f"🎯 代码片段抽取处理完成")
371
+ self.printer.print_str_in_terminal(f"📊 处理结果统计:")
372
+ self.printer.print_str_in_terminal(f" • 输入文件数: {len(file_sources)} 个,输入token数: {total_input_tokens}")
373
+ self.printer.print_str_in_terminal(f" • 输出文件数: {len(selected_files)} 个,输出token数: {final_tokens}")
374
+ self.printer.print_str_in_terminal(f" • Token压缩率: {((total_input_tokens - final_tokens) / total_input_tokens * 100):.1f}%")
375
+
376
+ # 统计各种处理方式的文件数量
377
+ complete_files = 0
378
+ snippet_files = 0
379
+ for i, file_source in enumerate(file_sources):
380
+ if i < len(selected_files):
381
+ if selected_files[i].source_code == file_source.source_code:
382
+ complete_files += 1
383
+ else:
384
+ snippet_files += 1
385
+
386
+ self.printer.print_str_in_terminal(f" • 完整保留文件: {complete_files} 个")
387
+ self.printer.print_str_in_terminal(f" • 片段抽取文件: {snippet_files} 个")
388
+ self.printer.print_str_in_terminal(f" • 跳过处理文件: {len(file_sources) - len(selected_files)} 个")
389
+
293
390
  return selected_files
294
391
 
295
392
  def _merge_overlapping_snippets(self, snippets: List[dict]) -> List[dict]:
@@ -373,7 +470,7 @@ class PruneContext:
373
470
  else:
374
471
  raise ValueError(f"无效策略: {strategy}. 可选值: delete/extract/score")
375
472
 
376
- def _count_tokens(self, file_sources: List[SourceCode]) -> int:
473
+ def _count_tokens(self, file_sources: List[SourceCode]) -> Tuple[int, List[SourceCode]]:
377
474
  """计算文件总token数"""
378
475
  total_tokens = 0
379
476
  sources = []
@@ -0,0 +1,386 @@
1
+ """
2
+ 会话消息ID管理API
3
+ 提供高级的会话消息ID管理接口,包括验证、错误处理和便捷方法
4
+ """
5
+
6
+ import re
7
+ from typing import List, Optional, Dict, Any, Union
8
+ from dataclasses import dataclass
9
+ from loguru import logger
10
+
11
+ from .conversation_message_ids_manager import (
12
+ ConversationMessageIdsManager,
13
+ ConversationMessageIds,
14
+ get_conversation_message_ids_manager
15
+ )
16
+
17
+
18
+ @dataclass
19
+ class MessageIdsValidationResult:
20
+ """消息ID验证结果"""
21
+ is_valid: bool
22
+ error_message: str = ""
23
+ warnings: Optional[List[str]] = None
24
+ normalized_message_ids: Optional[List[str]] = None
25
+
26
+ def __post_init__(self):
27
+ if self.warnings is None:
28
+ self.warnings = []
29
+ if self.normalized_message_ids is None:
30
+ self.normalized_message_ids = []
31
+
32
+
33
+ @dataclass
34
+ class MessageIdsParseResult:
35
+ """消息ID解析结果"""
36
+ success: bool
37
+ message_ids: Optional[List[str]] = None
38
+ error_message: str = ""
39
+
40
+ def __post_init__(self):
41
+ if self.message_ids is None:
42
+ self.message_ids = []
43
+
44
+
45
+ class ConversationMessageIdsAPI:
46
+ """会话消息ID管理API - 高级接口"""
47
+
48
+ def __init__(self, storage_dir: Optional[str] = None):
49
+ """初始化API
50
+
51
+ Args:
52
+ storage_dir: 存储目录,如果为None则使用默认目录
53
+ """
54
+ self.manager = get_conversation_message_ids_manager(storage_dir)
55
+
56
+ def save_conversation_message_ids(
57
+ self,
58
+ conversation_id: str,
59
+ message_ids: Union[List[str], str],
60
+ description: str = "",
61
+ preserve_pairs: bool = True,
62
+ conversation_message_ids: Optional[List[str]] = None
63
+ ) -> tuple[bool, str, Optional[ConversationMessageIds]]:
64
+ """保存或更新会话消息ID
65
+
66
+ Args:
67
+ conversation_id: 会话ID
68
+ message_ids: 消息ID列表或消息ID字符串 (如 "9226b3a4,204e1cd8")
69
+ description: 描述信息
70
+ preserve_pairs: 是否保证user/assistant成对裁剪
71
+ conversation_message_ids: 对话中所有消息的ID列表(用于验证)
72
+
73
+ Returns:
74
+ (是否成功, 错误信息, ConversationMessageIds对象)
75
+ """
76
+ try:
77
+ # 解析消息ID
78
+ if isinstance(message_ids, str):
79
+ parse_result = self.parse_message_ids_string(message_ids)
80
+ if not parse_result.success:
81
+ return False, parse_result.error_message, None
82
+ message_ids_list = parse_result.message_ids or []
83
+ else:
84
+ message_ids_list = message_ids
85
+
86
+ # 验证消息ID
87
+ if conversation_message_ids is not None:
88
+ validation_result = self.validate_message_ids(message_ids_list, conversation_message_ids)
89
+ if not validation_result.is_valid:
90
+ return False, validation_result.error_message, None
91
+ if validation_result.normalized_message_ids:
92
+ message_ids_list = validation_result.normalized_message_ids
93
+
94
+ # 保存消息ID
95
+ message_ids_obj = self.manager.save_message_ids(
96
+ conversation_id=conversation_id,
97
+ message_ids=message_ids_list,
98
+ description=description,
99
+ preserve_pairs=preserve_pairs
100
+ )
101
+
102
+ logger.info(f"Successfully saved message IDs for conversation {conversation_id}: {message_ids_list}")
103
+ return True, "", message_ids_obj
104
+
105
+ except Exception as e:
106
+ error_msg = f"Failed to save conversation message IDs: {str(e)}"
107
+ logger.error(error_msg)
108
+ return False, error_msg, None
109
+
110
+ def get_conversation_message_ids(self, conversation_id: str) -> Optional[ConversationMessageIds]:
111
+ """获取会话消息ID
112
+
113
+ Args:
114
+ conversation_id: 会话ID
115
+
116
+ Returns:
117
+ ConversationMessageIds对象或None
118
+ """
119
+ return self.manager.get_message_ids(conversation_id)
120
+
121
+ def delete_conversation_message_ids(self, conversation_id: str) -> tuple[bool, str]:
122
+ """删除会话消息ID
123
+
124
+ Args:
125
+ conversation_id: 会话ID
126
+
127
+ Returns:
128
+ (是否成功, 错误信息)
129
+ """
130
+ try:
131
+ success = self.manager.delete_message_ids(conversation_id)
132
+ if success:
133
+ logger.info(f"Successfully deleted message IDs for conversation {conversation_id}")
134
+ return True, ""
135
+ else:
136
+ return False, f"No message IDs found for conversation {conversation_id}"
137
+ except Exception as e:
138
+ error_msg = f"Failed to delete conversation message IDs: {str(e)}"
139
+ logger.error(error_msg)
140
+ return False, error_msg
141
+
142
+ def list_all_message_ids(self) -> List[ConversationMessageIds]:
143
+ """列出所有会话消息ID
144
+
145
+ Returns:
146
+ 会话消息ID列表
147
+ """
148
+ return self.manager.get_all_message_ids()
149
+
150
+ def list_conversation_ids(self) -> List[str]:
151
+ """列出所有已配置消息ID的会话ID
152
+
153
+ Returns:
154
+ 会话ID列表
155
+ """
156
+ return self.manager.list_conversation_ids()
157
+
158
+ def validate_message_ids(
159
+ self,
160
+ message_ids: List[str],
161
+ conversation_message_ids: List[str],
162
+ auto_fix: bool = True,
163
+ allow_missing: bool = True
164
+ ) -> MessageIdsValidationResult:
165
+ """验证消息ID有效性
166
+
167
+ Args:
168
+ message_ids: 要删除的消息ID列表
169
+ conversation_message_ids: 对话中所有消息的ID列表
170
+ auto_fix: 是否自动修复一些问题
171
+ allow_missing: 是否允许某些消息ID不存在(用于部分对话场景)
172
+
173
+ Returns:
174
+ 验证结果
175
+ """
176
+ result = MessageIdsValidationResult(is_valid=True)
177
+
178
+ if not message_ids:
179
+ result.is_valid = False
180
+ result.error_message = "消息ID列表不能为空"
181
+ return result
182
+
183
+ normalized_ids = []
184
+ warnings = []
185
+
186
+ # 创建有效ID集合 (取前8个字符)
187
+ valid_ids = {msg_id[:8] for msg_id in conversation_message_ids}
188
+
189
+ for i, msg_id in enumerate(message_ids):
190
+ # 类型检查
191
+ if not isinstance(msg_id, str):
192
+ result.is_valid = False
193
+ result.error_message = f"消息ID {i+1}: ID必须是字符串"
194
+ return result
195
+
196
+ # 长度检查和自动修复
197
+ if len(msg_id) < 8:
198
+ result.is_valid = False
199
+ result.error_message = f"消息ID {i+1}: ID长度必须至少8个字符"
200
+ return result
201
+ elif len(msg_id) > 8:
202
+ if auto_fix:
203
+ msg_id = msg_id[:8]
204
+ warnings.append(f"消息ID {i+1}: 自动截取前8个字符")
205
+ else:
206
+ result.is_valid = False
207
+ result.error_message = f"消息ID {i+1}: ID长度超过8个字符"
208
+ return result
209
+
210
+ # 有效性检查
211
+ if msg_id not in valid_ids:
212
+ if allow_missing:
213
+ # 允许缺失模式:跳过不存在的消息ID,给出警告
214
+ warnings.append(f"消息ID {i+1}: '{msg_id}' 在对话中不存在,已跳过")
215
+ continue
216
+ else:
217
+ # 严格模式:任何不存在的消息ID都导致验证失败
218
+ result.is_valid = False
219
+ result.error_message = f"消息ID {i+1}: '{msg_id}' 在对话中不存在"
220
+ return result
221
+
222
+ normalized_ids.append(msg_id)
223
+
224
+ # 移除重复ID
225
+ if auto_fix:
226
+ seen = set()
227
+ unique_ids = []
228
+ for msg_id in normalized_ids:
229
+ if msg_id not in seen:
230
+ seen.add(msg_id)
231
+ unique_ids.append(msg_id)
232
+
233
+ if len(unique_ids) < len(normalized_ids):
234
+ warnings.append(f"自动移除重复的消息ID: {len(normalized_ids)} -> {len(unique_ids)}")
235
+ normalized_ids = unique_ids
236
+
237
+ result.warnings = warnings
238
+ result.normalized_message_ids = normalized_ids
239
+ return result
240
+
241
+ def parse_message_ids_string(self, message_ids_string: str) -> MessageIdsParseResult:
242
+ """解析消息ID字符串
243
+
244
+ Args:
245
+ message_ids_string: 消息ID字符串,如 "9226b3a4,204e1cd8,1f3a5b7c"
246
+
247
+ Returns:
248
+ 解析结果
249
+ """
250
+ try:
251
+ message_ids = []
252
+
253
+ # 去除空白字符
254
+ message_ids_string = message_ids_string.strip()
255
+
256
+ if not message_ids_string:
257
+ return MessageIdsParseResult(
258
+ success=False,
259
+ error_message="消息ID字符串不能为空"
260
+ )
261
+
262
+ # 分割多个消息ID (支持逗号和分号分隔)
263
+ id_parts = re.split(r'[,;]', message_ids_string)
264
+
265
+ for i, part in enumerate(id_parts):
266
+ part = part.strip()
267
+ if not part:
268
+ continue
269
+ message_ids.append(part.lower()) # 统一转为小写
270
+
271
+ return MessageIdsParseResult(
272
+ success=True,
273
+ message_ids=message_ids
274
+ )
275
+
276
+ except Exception as e:
277
+ return MessageIdsParseResult(
278
+ success=False,
279
+ error_message=f"解析消息ID字符串失败: {str(e)}"
280
+ )
281
+
282
+ def format_message_ids_to_string(self, message_ids: List[str]) -> str:
283
+ """将消息ID列表格式化为字符串
284
+
285
+ Args:
286
+ message_ids: 消息ID列表
287
+
288
+ Returns:
289
+ 格式化后的字符串
290
+ """
291
+ return ",".join(message_ids)
292
+
293
+ def get_message_ids_statistics(self, conversation_id: str) -> Optional[Dict[str, Any]]:
294
+ """获取消息ID统计信息
295
+
296
+ Args:
297
+ conversation_id: 会话ID
298
+
299
+ Returns:
300
+ 统计信息字典或None
301
+ """
302
+ message_ids_obj = self.get_conversation_message_ids(conversation_id)
303
+ if not message_ids_obj:
304
+ return None
305
+
306
+ total_count = message_ids_obj.get_total_message_count()
307
+
308
+ return {
309
+ "conversation_id": conversation_id,
310
+ "total_message_ids": len(message_ids_obj.message_ids),
311
+ "unique_message_ids": total_count,
312
+ "message_ids": message_ids_obj.message_ids,
313
+ "preserve_pairs": message_ids_obj.preserve_pairs,
314
+ "description": message_ids_obj.description,
315
+ "created_at": message_ids_obj.created_at,
316
+ "updated_at": message_ids_obj.updated_at
317
+ }
318
+
319
+ def export_message_ids_to_dict(self) -> Dict[str, Any]:
320
+ """导出所有消息ID为字典格式
321
+
322
+ Returns:
323
+ 包含所有消息ID的字典
324
+ """
325
+ all_message_ids = self.list_all_message_ids()
326
+ return {
327
+ "version": "1.0",
328
+ "total_configs": len(all_message_ids),
329
+ "message_configs": [config.to_dict() for config in all_message_ids]
330
+ }
331
+
332
+ def import_message_ids_from_dict(self, data: Dict[str, Any]) -> tuple[bool, str, int]:
333
+ """从字典导入消息ID配置
334
+
335
+ Args:
336
+ data: 包含消息ID数据的字典
337
+
338
+ Returns:
339
+ (是否成功, 错误信息, 成功导入的数量)
340
+ """
341
+ try:
342
+ if "message_configs" not in data:
343
+ return False, "数据格式错误: 缺少 'message_configs' 字段", 0
344
+
345
+ success_count = 0
346
+
347
+ for config_data in data["message_configs"]:
348
+ try:
349
+ message_ids_obj = ConversationMessageIds.from_dict(config_data)
350
+ self.manager.save_message_ids(
351
+ conversation_id=message_ids_obj.conversation_id,
352
+ message_ids=message_ids_obj.message_ids,
353
+ description=message_ids_obj.description,
354
+ preserve_pairs=message_ids_obj.preserve_pairs
355
+ )
356
+ success_count += 1
357
+ except Exception as e:
358
+ logger.warning(f"Failed to import message IDs for conversation {config_data.get('conversation_id', 'unknown')}: {e}")
359
+
360
+ return True, f"成功导入 {success_count} 个消息ID配置", success_count
361
+
362
+ except Exception as e:
363
+ error_msg = f"导入消息ID配置失败: {str(e)}"
364
+ logger.error(error_msg)
365
+ return False, error_msg, 0
366
+
367
+
368
+ # 全局API实例
369
+ _conversation_message_ids_api = None
370
+
371
+
372
+ def get_conversation_message_ids_api(storage_dir: Optional[str] = None) -> ConversationMessageIdsAPI:
373
+ """获取全局会话消息ID API实例
374
+
375
+ Args:
376
+ storage_dir: 存储目录
377
+
378
+ Returns:
379
+ ConversationMessageIdsAPI实例
380
+ """
381
+ global _conversation_message_ids_api
382
+
383
+ if _conversation_message_ids_api is None:
384
+ _conversation_message_ids_api = ConversationMessageIdsAPI(storage_dir)
385
+
386
+ return _conversation_message_ids_api