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
@@ -0,0 +1,239 @@
1
+ """
2
+ Todo manager data models.
3
+ """
4
+
5
+ import time
6
+ import uuid
7
+ from typing import Union, Dict, List, Optional, Any
8
+ from dataclasses import dataclass, field
9
+
10
+
11
+ @dataclass
12
+ class Todo:
13
+ """Todo item data model"""
14
+
15
+ content: str
16
+ todo_id: str = field(default_factory=lambda: str(uuid.uuid4())[:8])
17
+ status: str = "pending"
18
+ priority: str = "medium"
19
+ created_at: float = field(default_factory=time.time)
20
+ updated_at: float = field(default_factory=time.time)
21
+ notes: Optional[str] = None
22
+ dependencies: Optional[List[str]] = None
23
+
24
+ def __post_init__(self):
25
+ """Data validation"""
26
+ self._validate()
27
+
28
+ def _validate(self):
29
+ """Validate todo data"""
30
+ # Validate content
31
+ if not self.content or (isinstance(self.content, str) and len(self.content.strip()) == 0):
32
+ raise ValueError("Todo content cannot be empty")
33
+
34
+ # Validate status
35
+ valid_statuses = ["pending", "in_progress", "completed", "cancelled"]
36
+ if self.status not in valid_statuses:
37
+ raise ValueError(f"Invalid status: {self.status}, valid statuses: {valid_statuses}")
38
+
39
+ # Validate priority
40
+ valid_priorities = ["low", "medium", "high"]
41
+ if self.priority not in valid_priorities:
42
+ raise ValueError(f"Invalid priority: {self.priority}, valid priorities: {valid_priorities}")
43
+
44
+ # Validate timestamps
45
+ if not isinstance(self.created_at, (int, float)) or self.created_at <= 0:
46
+ raise ValueError("Invalid created_at timestamp")
47
+
48
+ if not isinstance(self.updated_at, (int, float)) or self.updated_at < self.created_at:
49
+ raise ValueError("Invalid updated_at timestamp")
50
+
51
+ # Validate todo ID
52
+ if not isinstance(self.todo_id, str) or len(self.todo_id) == 0:
53
+ raise ValueError("Todo ID cannot be empty")
54
+
55
+ def update_status(self, status: str):
56
+ """Update todo status"""
57
+ valid_statuses = ["pending", "in_progress", "completed", "cancelled"]
58
+ if status not in valid_statuses:
59
+ raise ValueError(f"Invalid status: {status}")
60
+
61
+ self.status = status
62
+ self.updated_at = time.time()
63
+
64
+ def update_content(self, content: str):
65
+ """Update todo content"""
66
+ if not content or len(content.strip()) == 0:
67
+ raise ValueError("Todo content cannot be empty")
68
+
69
+ self.content = content
70
+ self.updated_at = time.time()
71
+
72
+ def update_priority(self, priority: str):
73
+ """Update todo priority"""
74
+ valid_priorities = ["low", "medium", "high"]
75
+ if priority not in valid_priorities:
76
+ raise ValueError(f"Invalid priority: {priority}")
77
+
78
+ self.priority = priority
79
+ self.updated_at = time.time()
80
+
81
+ def add_notes(self, notes: str):
82
+ """Add or update notes"""
83
+ self.notes = notes
84
+ self.updated_at = time.time()
85
+
86
+ def add_dependency(self, todo_id: str):
87
+ """Add a dependency to another todo"""
88
+ if self.dependencies is None:
89
+ self.dependencies = []
90
+
91
+ if todo_id not in self.dependencies:
92
+ self.dependencies.append(todo_id)
93
+ self.updated_at = time.time()
94
+
95
+ def remove_dependency(self, todo_id: str):
96
+ """Remove a dependency"""
97
+ if self.dependencies and todo_id in self.dependencies:
98
+ self.dependencies.remove(todo_id)
99
+ self.updated_at = time.time()
100
+
101
+ def to_dict(self) -> Dict[str, Any]:
102
+ """Serialize to dictionary"""
103
+ return {
104
+ "todo_id": self.todo_id,
105
+ "content": self.content,
106
+ "status": self.status,
107
+ "priority": self.priority,
108
+ "created_at": self.created_at,
109
+ "updated_at": self.updated_at,
110
+ "notes": self.notes,
111
+ "dependencies": self.dependencies
112
+ }
113
+
114
+ @classmethod
115
+ def from_dict(cls, data: Dict[str, Any]) -> "Todo":
116
+ """Deserialize from dictionary"""
117
+ return cls(
118
+ todo_id=data["todo_id"],
119
+ content=data["content"],
120
+ status=data.get("status", "pending"),
121
+ priority=data.get("priority", "medium"),
122
+ created_at=data["created_at"],
123
+ updated_at=data["updated_at"],
124
+ notes=data.get("notes"),
125
+ dependencies=data.get("dependencies")
126
+ )
127
+
128
+
129
+ @dataclass
130
+ class TodoList:
131
+ """Todo list data model for a conversation"""
132
+
133
+ conversation_id: str
134
+ todos: List[Dict[str, Any]] = field(default_factory=list)
135
+ created_at: float = field(default_factory=time.time)
136
+ updated_at: float = field(default_factory=time.time)
137
+ metadata: Optional[Dict[str, Any]] = None
138
+
139
+ def __post_init__(self):
140
+ """Data validation"""
141
+ self._validate()
142
+
143
+ def _validate(self):
144
+ """Validate todo list data"""
145
+ # Validate conversation ID
146
+ if not isinstance(self.conversation_id, str) or len(self.conversation_id) == 0:
147
+ raise ValueError("Conversation ID cannot be empty")
148
+
149
+ # Validate timestamps
150
+ if not isinstance(self.created_at, (int, float)) or self.created_at <= 0:
151
+ raise ValueError("Invalid created_at timestamp")
152
+
153
+ if not isinstance(self.updated_at, (int, float)) or self.updated_at < self.created_at:
154
+ raise ValueError("Invalid updated_at timestamp")
155
+
156
+ # Validate todos list
157
+ if not isinstance(self.todos, list):
158
+ raise ValueError("Todos must be a list")
159
+
160
+ def add_todo(self, todo: Todo):
161
+ """Add a todo to the list"""
162
+ self.todos.append(todo.to_dict())
163
+ self.updated_at = time.time()
164
+
165
+ def remove_todo(self, todo_id: str) -> bool:
166
+ """Remove a todo from the list"""
167
+ for i, todo_data in enumerate(self.todos):
168
+ if todo_data.get("todo_id") == todo_id:
169
+ del self.todos[i]
170
+ self.updated_at = time.time()
171
+ return True
172
+ return False
173
+
174
+ def get_todo(self, todo_id: str) -> Optional[Dict[str, Any]]:
175
+ """Get a todo from the list"""
176
+ for todo_data in self.todos:
177
+ if todo_data.get("todo_id") == todo_id:
178
+ return todo_data
179
+ return None
180
+
181
+ def update_todo(self, todo_id: str, **kwargs) -> bool:
182
+ """Update a todo in the list"""
183
+ for todo_data in self.todos:
184
+ if todo_data.get("todo_id") == todo_id:
185
+ # Update fields
186
+ for key, value in kwargs.items():
187
+ if key in ["content", "status", "priority", "notes", "dependencies"]:
188
+ todo_data[key] = value
189
+
190
+ todo_data["updated_at"] = time.time()
191
+ self.updated_at = time.time()
192
+ return True
193
+ return False
194
+
195
+ def get_todos_by_status(self, status: str) -> List[Dict[str, Any]]:
196
+ """Get todos by status"""
197
+ return [todo for todo in self.todos if todo.get("status") == status]
198
+
199
+ def get_todos_by_priority(self, priority: str) -> List[Dict[str, Any]]:
200
+ """Get todos by priority"""
201
+ return [todo for todo in self.todos if todo.get("priority") == priority]
202
+
203
+ def get_statistics(self) -> Dict[str, int]:
204
+ """Get todo statistics"""
205
+ stats = {
206
+ "total": len(self.todos),
207
+ "pending": 0,
208
+ "in_progress": 0,
209
+ "completed": 0,
210
+ "cancelled": 0
211
+ }
212
+
213
+ for todo in self.todos:
214
+ status = todo.get("status", "pending")
215
+ if status in stats:
216
+ stats[status] += 1
217
+
218
+ return stats
219
+
220
+ def to_dict(self) -> Dict[str, Any]:
221
+ """Serialize to dictionary"""
222
+ return {
223
+ "conversation_id": self.conversation_id,
224
+ "todos": self.todos,
225
+ "created_at": self.created_at,
226
+ "updated_at": self.updated_at,
227
+ "metadata": self.metadata
228
+ }
229
+
230
+ @classmethod
231
+ def from_dict(cls, data: Dict[str, Any]) -> "TodoList":
232
+ """Deserialize from dictionary"""
233
+ return cls(
234
+ conversation_id=data["conversation_id"],
235
+ todos=data.get("todos", []),
236
+ created_at=data["created_at"],
237
+ updated_at=data["updated_at"],
238
+ metadata=data.get("metadata")
239
+ )
@@ -0,0 +1,14 @@
1
+ """
2
+ Storage module for todo management.
3
+
4
+ This module provides storage functionality for todos and todo lists,
5
+ with support for file-based storage and extensible storage backends.
6
+ """
7
+
8
+ from .base_storage import BaseStorage
9
+ from .file_storage import FileStorage
10
+
11
+ __all__ = [
12
+ 'BaseStorage',
13
+ 'FileStorage'
14
+ ]
@@ -0,0 +1,76 @@
1
+ """
2
+ Base storage interface for todo management.
3
+
4
+ This module defines the abstract base class for all storage implementations,
5
+ providing a consistent interface for todo and todo list operations.
6
+ """
7
+
8
+ from abc import ABC, abstractmethod
9
+ from typing import Optional, Dict, Any, List
10
+
11
+
12
+ class BaseStorage(ABC):
13
+ """Abstract base class for todo storage implementations."""
14
+
15
+ @abstractmethod
16
+ def save_todo_list(self, conversation_id: str, todo_list_data: Dict[str, Any]) -> bool:
17
+ """
18
+ Save a todo list to storage.
19
+
20
+ Args:
21
+ conversation_id: The conversation ID
22
+ todo_list_data: The todo list data to save
23
+
24
+ Returns:
25
+ True if save was successful, False otherwise
26
+ """
27
+ pass
28
+
29
+ @abstractmethod
30
+ def load_todo_list(self, conversation_id: str) -> Optional[Dict[str, Any]]:
31
+ """
32
+ Load a todo list from storage.
33
+
34
+ Args:
35
+ conversation_id: The conversation ID
36
+
37
+ Returns:
38
+ Todo list data or None if not found
39
+ """
40
+ pass
41
+
42
+ @abstractmethod
43
+ def delete_todo_list(self, conversation_id: str) -> bool:
44
+ """
45
+ Delete a todo list from storage.
46
+
47
+ Args:
48
+ conversation_id: The conversation ID
49
+
50
+ Returns:
51
+ True if deletion was successful, False otherwise
52
+ """
53
+ pass
54
+
55
+ @abstractmethod
56
+ def todo_list_exists(self, conversation_id: str) -> bool:
57
+ """
58
+ Check if a todo list exists in storage.
59
+
60
+ Args:
61
+ conversation_id: The conversation ID
62
+
63
+ Returns:
64
+ True if todo list exists, False otherwise
65
+ """
66
+ pass
67
+
68
+ @abstractmethod
69
+ def list_conversation_ids(self) -> List[str]:
70
+ """
71
+ List all conversation IDs that have todo lists.
72
+
73
+ Returns:
74
+ List of conversation IDs
75
+ """
76
+ pass
@@ -0,0 +1,278 @@
1
+ """
2
+ File-based storage implementation for todo lists.
3
+
4
+ This module provides a file system storage implementation for todo lists,
5
+ storing each conversation's todos as a separate JSON file.
6
+ """
7
+
8
+ import os
9
+ import json
10
+ import tempfile
11
+ from pathlib import Path
12
+ from typing import Optional, Dict, Any, List
13
+ from loguru import logger
14
+
15
+ from .base_storage import BaseStorage
16
+
17
+
18
+ class FileStorage(BaseStorage):
19
+ """File-based storage implementation for todo lists."""
20
+
21
+ def __init__(self, storage_path: str):
22
+ """
23
+ Initialize file storage.
24
+
25
+ Args:
26
+ storage_path: Base path for todo storage
27
+ """
28
+ self.storage_path = Path(storage_path)
29
+ self._ensure_storage_directory()
30
+
31
+ def _ensure_storage_directory(self):
32
+ """Ensure storage directory exists."""
33
+ self.storage_path.mkdir(parents=True, exist_ok=True)
34
+
35
+ def _get_todo_list_file_path(self, conversation_id: str) -> Path:
36
+ """
37
+ Get file path for a conversation's todo list.
38
+
39
+ Args:
40
+ conversation_id: The conversation ID
41
+
42
+ Returns:
43
+ Path to the todo list file
44
+ """
45
+ # Sanitize conversation ID for file system
46
+ safe_id = self._sanitize_filename(conversation_id)
47
+ return self.storage_path / f"{safe_id}.json"
48
+
49
+ def _sanitize_filename(self, filename: str) -> str:
50
+ """
51
+ Sanitize filename to be safe for file system.
52
+
53
+ Args:
54
+ filename: Original filename
55
+
56
+ Returns:
57
+ Sanitized filename
58
+ """
59
+ # Replace unsafe characters with underscores
60
+ unsafe_chars = '<>:"/\\|?*'
61
+ safe_name = filename
62
+ for char in unsafe_chars:
63
+ safe_name = safe_name.replace(char, '_')
64
+
65
+ # Limit length
66
+ if len(safe_name) > 200:
67
+ safe_name = safe_name[:200]
68
+
69
+ return safe_name
70
+
71
+ def _validate_todo_list_data(self, todo_list_data: Dict[str, Any]) -> bool:
72
+ """
73
+ Validate todo list data structure.
74
+
75
+ Args:
76
+ todo_list_data: Todo list data to validate
77
+
78
+ Returns:
79
+ True if valid, False otherwise
80
+ """
81
+ required_fields = ['conversation_id', 'todos', 'created_at', 'updated_at']
82
+
83
+ for field in required_fields:
84
+ if field not in todo_list_data:
85
+ logger.error(f"Todo list validation failed: missing field '{field}'")
86
+ return False
87
+
88
+ if not isinstance(todo_list_data['todos'], list):
89
+ logger.error("Todo list validation failed: 'todos' must be a list")
90
+ return False
91
+
92
+ return True
93
+
94
+ def _atomic_write_file(self, file_path: Path, data: Dict[str, Any]) -> bool:
95
+ """
96
+ Atomically write data to file.
97
+
98
+ Args:
99
+ file_path: Target file path
100
+ data: Data to write
101
+
102
+ Returns:
103
+ True if write was successful, False otherwise
104
+ """
105
+ try:
106
+ # Write to temporary file first
107
+ temp_fd, temp_path = tempfile.mkstemp(
108
+ suffix='.tmp',
109
+ dir=file_path.parent,
110
+ prefix=f'{file_path.stem}_'
111
+ )
112
+
113
+ try:
114
+ with os.fdopen(temp_fd, 'w', encoding='utf-8') as f:
115
+ json.dump(data, f, indent=2, ensure_ascii=False)
116
+
117
+ # Atomic move
118
+ Path(temp_path).replace(file_path)
119
+ return True
120
+
121
+ except Exception:
122
+ # Clean up temp file on error
123
+ try:
124
+ os.unlink(temp_path)
125
+ except:
126
+ pass
127
+ raise
128
+
129
+ except Exception as e:
130
+ logger.error(f"Failed to write file atomically {file_path}: {e}")
131
+ return False
132
+
133
+ def save_todo_list(self, conversation_id: str, todo_list_data: Dict[str, Any]) -> bool:
134
+ """
135
+ Save a todo list to storage.
136
+
137
+ Args:
138
+ conversation_id: The conversation ID
139
+ todo_list_data: The todo list data to save
140
+
141
+ Returns:
142
+ True if save was successful, False otherwise
143
+ """
144
+ try:
145
+ # Validate data
146
+ if not self._validate_todo_list_data(todo_list_data):
147
+ return False
148
+
149
+ # Get file path
150
+ file_path = self._get_todo_list_file_path(conversation_id)
151
+
152
+ # Atomic write
153
+ success = self._atomic_write_file(file_path, todo_list_data)
154
+
155
+ if success:
156
+ logger.debug(f"Successfully saved todo list for conversation {conversation_id}")
157
+ else:
158
+ logger.error(f"Failed to save todo list for conversation {conversation_id}")
159
+
160
+ return success
161
+
162
+ except Exception as e:
163
+ logger.error(f"Error saving todo list for conversation {conversation_id}: {e}")
164
+ return False
165
+
166
+ def load_todo_list(self, conversation_id: str) -> Optional[Dict[str, Any]]:
167
+ """
168
+ Load a todo list from storage.
169
+
170
+ Args:
171
+ conversation_id: The conversation ID
172
+
173
+ Returns:
174
+ Todo list data or None if not found
175
+ """
176
+ try:
177
+ file_path = self._get_todo_list_file_path(conversation_id)
178
+
179
+ if not file_path.exists():
180
+ logger.debug(f"Todo list file not found for conversation {conversation_id}")
181
+ return None
182
+
183
+ with open(file_path, 'r', encoding='utf-8') as f:
184
+ data = json.load(f)
185
+
186
+ # Validate loaded data
187
+ if not self._validate_todo_list_data(data):
188
+ logger.error(f"Invalid todo list data for conversation {conversation_id}")
189
+ return None
190
+
191
+ logger.debug(f"Successfully loaded todo list for conversation {conversation_id}")
192
+ return data
193
+
194
+ except json.JSONDecodeError as e:
195
+ logger.error(f"Invalid JSON in todo list file for conversation {conversation_id}: {e}")
196
+ return None
197
+ except Exception as e:
198
+ logger.error(f"Error loading todo list for conversation {conversation_id}: {e}")
199
+ return None
200
+
201
+ def delete_todo_list(self, conversation_id: str) -> bool:
202
+ """
203
+ Delete a todo list from storage.
204
+
205
+ Args:
206
+ conversation_id: The conversation ID
207
+
208
+ Returns:
209
+ True if deletion was successful, False otherwise
210
+ """
211
+ try:
212
+ file_path = self._get_todo_list_file_path(conversation_id)
213
+
214
+ if file_path.exists():
215
+ file_path.unlink()
216
+ logger.debug(f"Successfully deleted todo list for conversation {conversation_id}")
217
+ return True
218
+ else:
219
+ logger.debug(f"Todo list file not found for conversation {conversation_id} (already deleted)")
220
+ return True
221
+
222
+ except Exception as e:
223
+ logger.error(f"Error deleting todo list for conversation {conversation_id}: {e}")
224
+ return False
225
+
226
+ def todo_list_exists(self, conversation_id: str) -> bool:
227
+ """
228
+ Check if a todo list exists in storage.
229
+
230
+ Args:
231
+ conversation_id: The conversation ID
232
+
233
+ Returns:
234
+ True if todo list exists, False otherwise
235
+ """
236
+ try:
237
+ file_path = self._get_todo_list_file_path(conversation_id)
238
+ return file_path.exists()
239
+ except Exception as e:
240
+ logger.error(f"Error checking todo list existence for conversation {conversation_id}: {e}")
241
+ return False
242
+
243
+ def list_conversation_ids(self) -> List[str]:
244
+ """
245
+ List all conversation IDs that have todo lists.
246
+
247
+ Returns:
248
+ List of conversation IDs
249
+ """
250
+ try:
251
+ conversation_ids = []
252
+
253
+ if not self.storage_path.exists():
254
+ return conversation_ids
255
+
256
+ for file_path in self.storage_path.glob("*.json"):
257
+ # Extract conversation ID from filename
258
+ conversation_id = file_path.stem
259
+
260
+ # Try to load and validate the file
261
+ try:
262
+ with open(file_path, 'r', encoding='utf-8') as f:
263
+ data = json.load(f)
264
+
265
+ if self._validate_todo_list_data(data):
266
+ # Use the conversation ID from the file content
267
+ actual_id = data.get('conversation_id', conversation_id)
268
+ conversation_ids.append(actual_id)
269
+
270
+ except Exception as e:
271
+ logger.warning(f"Skipping invalid todo list file {file_path}: {e}")
272
+ continue
273
+
274
+ return conversation_ids
275
+
276
+ except Exception as e:
277
+ logger.error(f"Error listing conversation IDs: {e}")
278
+ return []
@@ -51,6 +51,20 @@ def count_directory_tokens(
51
51
  )
52
52
 
53
53
 
54
+ def count_string_tokens(text: str) -> int:
55
+ """
56
+ 统计字符串的 token 数量
57
+
58
+ Args:
59
+ text: 要统计的字符串内容
60
+
61
+ Returns:
62
+ int: token 数量
63
+ """
64
+ counter = TokenCounter()
65
+ return counter.count_string_tokens(text)
66
+
67
+
54
68
  __all__ = [
55
69
  'TokenResult',
56
70
  'DirectoryTokenResult',
@@ -59,4 +73,5 @@ __all__ = [
59
73
  'FileFilter',
60
74
  'count_file_tokens',
61
75
  'count_directory_tokens',
76
+ 'count_string_tokens',
62
77
  ]
@@ -4,6 +4,7 @@ from typing import List, Dict, Optional, Union, Callable
4
4
  from pathlib import Path
5
5
  import time
6
6
  import re
7
+ import importlib.resources as resources
7
8
 
8
9
  from autocoder.rag.variable_holder import VariableHolder
9
10
  from .models import TokenResult, DirectoryTokenResult
@@ -30,9 +31,30 @@ class TokenCounter:
30
31
  self.parallel = parallel
31
32
  self.max_workers = max_workers
32
33
 
33
- # 确保 tokenizer 已经加载
34
+ # 确保 tokenizer 已经加载,如果没有则自动初始化
35
+ self._ensure_tokenizer_initialized()
36
+
37
+ def _ensure_tokenizer_initialized(self):
38
+ """
39
+ 确保 tokenizer 已经初始化,如果没有则自动初始化
40
+ """
34
41
  if VariableHolder.TOKENIZER_MODEL is None:
35
- raise RuntimeError("Tokenizer model not initialized. Please call load_tokenizer() first.")
42
+ self._initialize_tokenizer()
43
+
44
+ def _initialize_tokenizer(self):
45
+ """
46
+ 初始化 tokenizer,参考 auto_coder_runner.py 中的 load_tokenizer 实现
47
+ """
48
+ try:
49
+ from tokenizers import Tokenizer
50
+ tokenizer_path = str(resources.files("autocoder") / "data" / "tokenizer.json")
51
+ VariableHolder.TOKENIZER_PATH = tokenizer_path
52
+ VariableHolder.TOKENIZER_MODEL = Tokenizer.from_file(tokenizer_path)
53
+ except (FileNotFoundError, ImportError) as e:
54
+ raise RuntimeError(
55
+ f"Failed to initialize tokenizer: {str(e)}. "
56
+ f"Make sure tokenizer.json exists in the autocoder package data directory."
57
+ )
36
58
 
37
59
  def count_file(self, file_path: str) -> TokenResult:
38
60
  """
@@ -200,6 +222,26 @@ class TokenCounter:
200
222
  errors=errors
201
223
  )
202
224
 
225
+ def count_string_tokens(self, text: str) -> int:
226
+ """
227
+ 统计字符串的 token 数量
228
+
229
+ Args:
230
+ text: 要统计的字符串内容
231
+
232
+ Returns:
233
+ int: token 数量
234
+ """
235
+ try:
236
+ if not isinstance(text, str):
237
+ raise ValueError("Input must be a string")
238
+
239
+ # 使用 tokenizer 编码字符串并统计 token 数量
240
+ tokens = VariableHolder.TOKENIZER_MODEL.encode(text)
241
+ return len(tokens)
242
+ except Exception as e:
243
+ raise RuntimeError(f"Failed to count tokens: {str(e)}")
244
+
203
245
  def set_tokenizer(self, tokenizer_name: str) -> None:
204
246
  """
205
247
  更改 tokenizer(目前不支持,仅为接口预留)