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

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

Potentially problematic release.


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

Files changed (574) hide show
  1. auto_coder-2.0.0.dist-info/LICENSE +158 -0
  2. auto_coder-2.0.0.dist-info/METADATA +558 -0
  3. auto_coder-2.0.0.dist-info/RECORD +795 -0
  4. {auto_coder-1.0.0.dist-info → auto_coder-2.0.0.dist-info}/WHEEL +1 -1
  5. {auto_coder-1.0.0.dist-info → auto_coder-2.0.0.dist-info}/entry_points.txt +3 -3
  6. autocoder/__init__.py +31 -0
  7. autocoder/agent/auto_filegroup.py +32 -13
  8. autocoder/agent/auto_learn_from_commit.py +9 -1
  9. autocoder/agent/base_agentic/__init__.py +3 -0
  10. autocoder/agent/base_agentic/agent_hub.py +1 -1
  11. autocoder/agent/base_agentic/base_agent.py +235 -136
  12. autocoder/agent/base_agentic/default_tools.py +119 -118
  13. autocoder/agent/base_agentic/test_base_agent.py +1 -1
  14. autocoder/agent/base_agentic/tool_registry.py +32 -20
  15. autocoder/agent/base_agentic/tools/read_file_tool_resolver.py +24 -3
  16. autocoder/agent/base_agentic/tools/write_to_file_tool_resolver.py +24 -11
  17. autocoder/agent/base_agentic/types.py +42 -0
  18. autocoder/agent/entry_command_agent/chat.py +73 -59
  19. autocoder/auto_coder.py +31 -40
  20. autocoder/auto_coder_rag.py +11 -1084
  21. autocoder/auto_coder_runner.py +970 -2345
  22. autocoder/auto_coder_terminal.py +26 -0
  23. autocoder/auto_coder_terminal_v3.py +190 -0
  24. autocoder/chat/conf_command.py +224 -124
  25. autocoder/chat/models_command.py +361 -299
  26. autocoder/chat/rules_command.py +79 -31
  27. autocoder/chat_auto_coder.py +988 -398
  28. autocoder/chat_auto_coder_lang.py +23 -732
  29. autocoder/commands/auto_command.py +25 -8
  30. autocoder/commands/auto_web.py +1 -1
  31. autocoder/commands/tools.py +44 -44
  32. autocoder/common/__init__.py +150 -128
  33. autocoder/common/ac_style_command_parser/__init__.py +39 -2
  34. autocoder/common/ac_style_command_parser/config.py +422 -0
  35. autocoder/common/ac_style_command_parser/parser.py +292 -78
  36. autocoder/common/ac_style_command_parser/test_parser.py +241 -16
  37. autocoder/common/ac_style_command_parser/test_typed_parser.py +342 -0
  38. autocoder/common/ac_style_command_parser/typed_parser.py +653 -0
  39. autocoder/common/action_yml_file_manager.py +25 -13
  40. autocoder/common/agent_events/__init__.py +52 -0
  41. autocoder/common/agent_events/agent_event_emitter.py +193 -0
  42. autocoder/common/agent_events/event_factory.py +177 -0
  43. autocoder/common/agent_events/examples.py +307 -0
  44. autocoder/common/agent_events/types.py +113 -0
  45. autocoder/common/agent_events/utils.py +68 -0
  46. autocoder/common/agent_hooks/__init__.py +44 -0
  47. autocoder/common/agent_hooks/examples.py +582 -0
  48. autocoder/common/agent_hooks/hook_executor.py +217 -0
  49. autocoder/common/agent_hooks/hook_manager.py +288 -0
  50. autocoder/common/agent_hooks/types.py +133 -0
  51. autocoder/common/agent_hooks/utils.py +99 -0
  52. autocoder/common/agent_query_queue/queue_executor.py +324 -0
  53. autocoder/common/agent_query_queue/queue_manager.py +325 -0
  54. autocoder/common/agents/__init__.py +11 -0
  55. autocoder/common/agents/agent_manager.py +323 -0
  56. autocoder/common/agents/agent_parser.py +189 -0
  57. autocoder/common/agents/example_usage.py +344 -0
  58. autocoder/common/agents/integration_example.py +330 -0
  59. autocoder/common/agents/test_agent_parser.py +545 -0
  60. autocoder/common/async_utils.py +101 -0
  61. autocoder/common/auto_coder_lang.py +23 -972
  62. autocoder/common/autocoderargs_parser/__init__.py +14 -0
  63. autocoder/common/autocoderargs_parser/parser.py +184 -0
  64. autocoder/common/autocoderargs_parser/tests/__init__.py +1 -0
  65. autocoder/common/autocoderargs_parser/tests/test_args_parser.py +235 -0
  66. autocoder/common/autocoderargs_parser/tests/test_token_parser.py +195 -0
  67. autocoder/common/autocoderargs_parser/token_parser.py +290 -0
  68. autocoder/common/buildin_tokenizer.py +2 -4
  69. autocoder/common/code_auto_generate.py +149 -74
  70. autocoder/common/code_auto_generate_diff.py +163 -70
  71. autocoder/common/code_auto_generate_editblock.py +179 -89
  72. autocoder/common/code_auto_generate_strict_diff.py +167 -72
  73. autocoder/common/code_auto_merge_editblock.py +13 -6
  74. autocoder/common/code_modification_ranker.py +1 -1
  75. autocoder/common/command_completer.py +3 -3
  76. autocoder/common/command_file_manager/manager.py +183 -47
  77. autocoder/common/command_file_manager/test_command_file_manager.py +507 -0
  78. autocoder/common/command_templates.py +1 -1
  79. autocoder/common/conf_utils.py +2 -4
  80. autocoder/common/conversations/config.py +11 -3
  81. autocoder/common/conversations/get_conversation_manager.py +100 -2
  82. autocoder/common/conversations/llm_stats_models.py +264 -0
  83. autocoder/common/conversations/manager.py +112 -28
  84. autocoder/common/conversations/models.py +16 -2
  85. autocoder/common/conversations/storage/index_manager.py +134 -10
  86. autocoder/common/core_config/__init__.py +63 -0
  87. autocoder/common/core_config/agentic_mode_manager.py +109 -0
  88. autocoder/common/core_config/base_manager.py +123 -0
  89. autocoder/common/core_config/compatibility.py +151 -0
  90. autocoder/common/core_config/config_manager.py +156 -0
  91. autocoder/common/core_config/conversation_manager.py +31 -0
  92. autocoder/common/core_config/exclude_manager.py +72 -0
  93. autocoder/common/core_config/file_manager.py +177 -0
  94. autocoder/common/core_config/human_as_model_manager.py +129 -0
  95. autocoder/common/core_config/lib_manager.py +54 -0
  96. autocoder/common/core_config/main_manager.py +81 -0
  97. autocoder/common/core_config/mode_manager.py +126 -0
  98. autocoder/common/core_config/models.py +70 -0
  99. autocoder/common/core_config/test_memory_manager.py +1056 -0
  100. autocoder/common/env_manager.py +282 -0
  101. autocoder/common/env_manager_usage_example.py +211 -0
  102. autocoder/common/file_checkpoint/conversation_checkpoint.py +19 -19
  103. autocoder/common/file_checkpoint/manager.py +264 -48
  104. autocoder/common/file_checkpoint/test_backup.py +1 -18
  105. autocoder/common/file_checkpoint/test_manager.py +270 -1
  106. autocoder/common/file_checkpoint/test_store.py +1 -17
  107. autocoder/common/file_handler/__init__.py +23 -0
  108. autocoder/common/file_handler/active_context_handler.py +159 -0
  109. autocoder/common/file_handler/add_files_handler.py +409 -0
  110. autocoder/common/file_handler/chat_handler.py +180 -0
  111. autocoder/common/file_handler/coding_handler.py +401 -0
  112. autocoder/common/file_handler/commit_handler.py +200 -0
  113. autocoder/common/file_handler/lib_handler.py +156 -0
  114. autocoder/common/file_handler/list_files_handler.py +111 -0
  115. autocoder/common/file_handler/mcp_handler.py +268 -0
  116. autocoder/common/file_handler/models_handler.py +493 -0
  117. autocoder/common/file_handler/remove_files_handler.py +172 -0
  118. autocoder/common/git_utils.py +44 -8
  119. autocoder/common/global_cancel.py +15 -6
  120. autocoder/common/ignorefiles/test_ignore_file_utils.py +1 -1
  121. autocoder/common/international/__init__.py +31 -0
  122. autocoder/common/international/demo_international.py +92 -0
  123. autocoder/common/international/message_manager.py +157 -0
  124. autocoder/common/international/messages/__init__.py +56 -0
  125. autocoder/common/international/messages/async_command_messages.py +507 -0
  126. autocoder/common/international/messages/auto_coder_messages.py +2208 -0
  127. autocoder/common/international/messages/chat_auto_coder_messages.py +1547 -0
  128. autocoder/common/international/messages/command_help_messages.py +986 -0
  129. autocoder/common/international/messages/conversation_command_messages.py +191 -0
  130. autocoder/common/international/messages/git_helper_plugin_messages.py +159 -0
  131. autocoder/common/international/messages/queue_command_messages.py +751 -0
  132. autocoder/common/international/messages/rules_command_messages.py +77 -0
  133. autocoder/common/international/messages/sdk_messages.py +1707 -0
  134. autocoder/common/international/messages/token_helper_plugin_messages.py +361 -0
  135. autocoder/common/international/messages/tool_display_messages.py +1212 -0
  136. autocoder/common/international/messages/workflow_exception_messages.py +473 -0
  137. autocoder/common/international/test_international.py +612 -0
  138. autocoder/common/linter_core/__init__.py +28 -0
  139. autocoder/common/linter_core/base_linter.py +61 -0
  140. autocoder/common/linter_core/config_loader.py +271 -0
  141. autocoder/common/linter_core/formatters/__init__.py +0 -0
  142. autocoder/common/linter_core/formatters/base_formatter.py +38 -0
  143. autocoder/common/linter_core/formatters/raw_formatter.py +17 -0
  144. autocoder/common/linter_core/linter.py +166 -0
  145. autocoder/common/linter_core/linter_factory.py +216 -0
  146. autocoder/common/linter_core/linter_manager.py +333 -0
  147. autocoder/common/linter_core/linters/__init__.py +9 -0
  148. autocoder/common/linter_core/linters/java_linter.py +342 -0
  149. autocoder/common/linter_core/linters/python_linter.py +115 -0
  150. autocoder/common/linter_core/linters/typescript_linter.py +119 -0
  151. autocoder/common/linter_core/models/__init__.py +7 -0
  152. autocoder/common/linter_core/models/lint_result.py +91 -0
  153. autocoder/common/linter_core/models.py +33 -0
  154. autocoder/common/linter_core/tests/__init__.py +3 -0
  155. autocoder/common/linter_core/tests/test_config_loader.py +323 -0
  156. autocoder/common/linter_core/tests/test_config_loading.py +308 -0
  157. autocoder/common/linter_core/tests/test_factory_manager.py +234 -0
  158. autocoder/common/linter_core/tests/test_formatters.py +147 -0
  159. autocoder/common/linter_core/tests/test_integration.py +317 -0
  160. autocoder/common/linter_core/tests/test_java_linter.py +496 -0
  161. autocoder/common/linter_core/tests/test_linters.py +265 -0
  162. autocoder/common/linter_core/tests/test_models.py +81 -0
  163. autocoder/common/linter_core/tests/verify_config_loading.py +296 -0
  164. autocoder/common/linter_core/tests/verify_fixes.py +183 -0
  165. autocoder/common/llm_friendly_package/__init__.py +31 -0
  166. autocoder/common/llm_friendly_package/base_manager.py +102 -0
  167. autocoder/common/llm_friendly_package/docs_manager.py +121 -0
  168. autocoder/common/llm_friendly_package/library_manager.py +171 -0
  169. autocoder/common/{llm_friendly_package.py → llm_friendly_package/main_manager.py} +204 -231
  170. autocoder/common/llm_friendly_package/models.py +40 -0
  171. autocoder/common/llm_friendly_package/test_llm_friendly_package.py +536 -0
  172. autocoder/common/llms/__init__.py +15 -0
  173. autocoder/common/llms/demo_error_handling.py +85 -0
  174. autocoder/common/llms/factory.py +142 -0
  175. autocoder/common/llms/manager.py +264 -0
  176. autocoder/common/llms/pricing.py +121 -0
  177. autocoder/common/llms/registry.py +288 -0
  178. autocoder/common/llms/schema.py +77 -0
  179. autocoder/common/llms/simple_demo.py +45 -0
  180. autocoder/common/llms/test_quick_model.py +116 -0
  181. autocoder/common/llms/test_remove_functionality.py +182 -0
  182. autocoder/common/llms/tests/__init__.py +1 -0
  183. autocoder/common/llms/tests/test_manager.py +330 -0
  184. autocoder/common/llms/tests/test_registry.py +364 -0
  185. autocoder/common/mcp_tools/__init__.py +62 -0
  186. autocoder/common/{mcp_tools.py → mcp_tools/executor.py} +49 -40
  187. autocoder/common/{mcp_hub.py → mcp_tools/hub.py} +42 -68
  188. autocoder/common/{mcp_server_install.py → mcp_tools/installer.py} +16 -28
  189. autocoder/common/{mcp_server.py → mcp_tools/server.py} +176 -48
  190. autocoder/common/mcp_tools/test_keyboard_interrupt.py +93 -0
  191. autocoder/common/mcp_tools/test_mcp_tools.py +391 -0
  192. autocoder/common/{mcp_server_types.py → mcp_tools/types.py} +121 -48
  193. autocoder/common/mcp_tools/verify_functionality.py +202 -0
  194. autocoder/common/model_speed_tester.py +32 -26
  195. autocoder/common/priority_directory_finder/__init__.py +142 -0
  196. autocoder/common/priority_directory_finder/examples.py +230 -0
  197. autocoder/common/priority_directory_finder/finder.py +283 -0
  198. autocoder/common/priority_directory_finder/models.py +236 -0
  199. autocoder/common/priority_directory_finder/test_priority_directory_finder.py +431 -0
  200. autocoder/common/project_scanner/__init__.py +18 -0
  201. autocoder/common/project_scanner/compat.py +77 -0
  202. autocoder/common/project_scanner/scanner.py +436 -0
  203. autocoder/common/project_tracker/__init__.py +27 -0
  204. autocoder/common/project_tracker/api.py +228 -0
  205. autocoder/common/project_tracker/demo.py +272 -0
  206. autocoder/common/project_tracker/tracker.py +487 -0
  207. autocoder/common/project_tracker/types.py +53 -0
  208. autocoder/common/pruner/__init__.py +67 -0
  209. autocoder/common/pruner/agentic_conversation_pruner.py +651 -102
  210. autocoder/common/pruner/conversation_message_ids_api.py +386 -0
  211. autocoder/common/pruner/conversation_message_ids_manager.py +347 -0
  212. autocoder/common/pruner/conversation_message_ids_pruner.py +473 -0
  213. autocoder/common/pruner/conversation_normalizer.py +347 -0
  214. autocoder/common/pruner/conversation_pruner.py +26 -6
  215. autocoder/common/pruner/test_agentic_conversation_pruner.py +554 -112
  216. autocoder/common/pruner/test_conversation_normalizer.py +502 -0
  217. autocoder/common/pruner/test_tool_content_detector.py +324 -0
  218. autocoder/common/pruner/tool_content_detector.py +227 -0
  219. autocoder/common/pruner/tools/__init__.py +18 -0
  220. autocoder/common/pruner/tools/query_message_ids.py +264 -0
  221. autocoder/common/pruner/tools/test_agentic_pruning_logic.py +432 -0
  222. autocoder/common/pruner/tools/test_message_ids_pruning_only.py +192 -0
  223. autocoder/common/pull_requests/__init__.py +9 -1
  224. autocoder/common/pull_requests/utils.py +122 -1
  225. autocoder/common/rag_manager/rag_manager.py +36 -40
  226. autocoder/common/rulefiles/__init__.py +53 -1
  227. autocoder/common/rulefiles/api.py +250 -0
  228. autocoder/common/rulefiles/core/__init__.py +14 -0
  229. autocoder/common/rulefiles/core/manager.py +241 -0
  230. autocoder/common/rulefiles/core/selector.py +805 -0
  231. autocoder/common/rulefiles/models/__init__.py +20 -0
  232. autocoder/common/rulefiles/models/index.py +16 -0
  233. autocoder/common/rulefiles/models/init_rule.py +18 -0
  234. autocoder/common/rulefiles/models/rule_file.py +18 -0
  235. autocoder/common/rulefiles/models/rule_relevance.py +14 -0
  236. autocoder/common/rulefiles/models/summary.py +16 -0
  237. autocoder/common/rulefiles/test_rulefiles.py +776 -0
  238. autocoder/common/rulefiles/utils/__init__.py +34 -0
  239. autocoder/common/rulefiles/utils/monitor.py +86 -0
  240. autocoder/common/rulefiles/utils/parser.py +230 -0
  241. autocoder/common/save_formatted_log.py +67 -10
  242. autocoder/common/search_replace.py +8 -1
  243. autocoder/common/search_replace_patch/__init__.py +24 -0
  244. autocoder/common/search_replace_patch/base.py +115 -0
  245. autocoder/common/search_replace_patch/manager.py +248 -0
  246. autocoder/common/search_replace_patch/patch_replacer.py +304 -0
  247. autocoder/common/search_replace_patch/similarity_replacer.py +306 -0
  248. autocoder/common/search_replace_patch/string_replacer.py +181 -0
  249. autocoder/common/search_replace_patch/tests/__init__.py +3 -0
  250. autocoder/common/search_replace_patch/tests/run_tests.py +126 -0
  251. autocoder/common/search_replace_patch/tests/test_base.py +188 -0
  252. autocoder/common/search_replace_patch/tests/test_empty_line_insert.py +233 -0
  253. autocoder/common/search_replace_patch/tests/test_integration.py +389 -0
  254. autocoder/common/search_replace_patch/tests/test_manager.py +351 -0
  255. autocoder/common/search_replace_patch/tests/test_patch_replacer.py +316 -0
  256. autocoder/common/search_replace_patch/tests/test_regex_replacer.py +306 -0
  257. autocoder/common/search_replace_patch/tests/test_similarity_replacer.py +384 -0
  258. autocoder/common/shell_commands/__init__.py +197 -0
  259. autocoder/common/shell_commands/background_process_notifier.py +346 -0
  260. autocoder/common/shell_commands/command_executor.py +1127 -0
  261. autocoder/common/shell_commands/error_recovery.py +541 -0
  262. autocoder/common/shell_commands/exceptions.py +120 -0
  263. autocoder/common/shell_commands/interactive_executor.py +476 -0
  264. autocoder/common/shell_commands/interactive_pexpect_process.py +623 -0
  265. autocoder/common/shell_commands/interactive_process.py +744 -0
  266. autocoder/common/shell_commands/interactive_session_manager.py +1014 -0
  267. autocoder/common/shell_commands/monitoring.py +529 -0
  268. autocoder/common/shell_commands/process_cleanup.py +386 -0
  269. autocoder/common/shell_commands/process_manager.py +606 -0
  270. autocoder/common/shell_commands/test_interactive_pexpect_process.py +281 -0
  271. autocoder/common/shell_commands/tests/__init__.py +6 -0
  272. autocoder/common/shell_commands/tests/conftest.py +118 -0
  273. autocoder/common/shell_commands/tests/test_background_process_notifier.py +703 -0
  274. autocoder/common/shell_commands/tests/test_command_executor.py +448 -0
  275. autocoder/common/shell_commands/tests/test_error_recovery.py +305 -0
  276. autocoder/common/shell_commands/tests/test_exceptions.py +299 -0
  277. autocoder/common/shell_commands/tests/test_execute_batch.py +588 -0
  278. autocoder/common/shell_commands/tests/test_indented_batch_commands.py +244 -0
  279. autocoder/common/shell_commands/tests/test_integration.py +664 -0
  280. autocoder/common/shell_commands/tests/test_monitoring.py +546 -0
  281. autocoder/common/shell_commands/tests/test_performance.py +632 -0
  282. autocoder/common/shell_commands/tests/test_process_cleanup.py +397 -0
  283. autocoder/common/shell_commands/tests/test_process_manager.py +606 -0
  284. autocoder/common/shell_commands/tests/test_timeout_config.py +343 -0
  285. autocoder/common/shell_commands/tests/test_timeout_manager.py +520 -0
  286. autocoder/common/shell_commands/timeout_config.py +315 -0
  287. autocoder/common/shell_commands/timeout_manager.py +352 -0
  288. autocoder/common/terminal_paste/__init__.py +14 -0
  289. autocoder/common/terminal_paste/demo.py +145 -0
  290. autocoder/common/terminal_paste/demo_paste_functionality.py +95 -0
  291. autocoder/common/terminal_paste/paste_handler.py +200 -0
  292. autocoder/common/terminal_paste/paste_manager.py +118 -0
  293. autocoder/common/terminal_paste/tests/__init__.py +1 -0
  294. autocoder/common/terminal_paste/tests/test_paste_handler.py +182 -0
  295. autocoder/common/terminal_paste/tests/test_paste_manager.py +126 -0
  296. autocoder/common/terminal_paste/utils.py +163 -0
  297. autocoder/common/test_autocoder_args.py +232 -0
  298. autocoder/common/test_env_manager.py +173 -0
  299. autocoder/common/test_env_manager_integration.py +159 -0
  300. autocoder/common/text_similarity/__init__.py +9 -0
  301. autocoder/common/text_similarity/demo.py +216 -0
  302. autocoder/common/text_similarity/examples.py +266 -0
  303. autocoder/common/text_similarity/test_text_similarity.py +306 -0
  304. autocoder/common/text_similarity/text_similarity.py +194 -0
  305. autocoder/common/text_similarity/utils.py +125 -0
  306. autocoder/common/todos/__init__.py +61 -0
  307. autocoder/common/todos/cache/__init__.py +16 -0
  308. autocoder/common/todos/cache/base_cache.py +89 -0
  309. autocoder/common/todos/cache/cache_manager.py +228 -0
  310. autocoder/common/todos/cache/memory_cache.py +225 -0
  311. autocoder/common/todos/config.py +155 -0
  312. autocoder/common/todos/exceptions.py +35 -0
  313. autocoder/common/todos/get_todo_manager.py +161 -0
  314. autocoder/common/todos/manager.py +537 -0
  315. autocoder/common/todos/models.py +239 -0
  316. autocoder/common/todos/storage/__init__.py +14 -0
  317. autocoder/common/todos/storage/base_storage.py +76 -0
  318. autocoder/common/todos/storage/file_storage.py +278 -0
  319. autocoder/common/tokens/counter.py +24 -2
  320. autocoder/common/tools_manager/__init__.py +17 -0
  321. autocoder/common/tools_manager/examples.py +162 -0
  322. autocoder/common/tools_manager/manager.py +385 -0
  323. autocoder/common/tools_manager/models.py +39 -0
  324. autocoder/common/tools_manager/test_tools_manager.py +303 -0
  325. autocoder/common/tools_manager/utils.py +191 -0
  326. autocoder/common/v2/agent/agentic_callbacks.py +270 -0
  327. autocoder/common/v2/agent/agentic_edit.py +2699 -1856
  328. autocoder/common/v2/agent/agentic_edit_change_manager.py +474 -0
  329. autocoder/common/v2/agent/agentic_edit_tools/__init__.py +35 -1
  330. autocoder/common/v2/agent/agentic_edit_tools/ac_mod_list_tool_resolver.py +279 -0
  331. autocoder/common/v2/agent/agentic_edit_tools/ac_mod_write_tool_resolver.py +10 -1
  332. autocoder/common/v2/agent/agentic_edit_tools/background_task_tool_resolver.py +1167 -0
  333. autocoder/common/v2/agent/agentic_edit_tools/base_tool_resolver.py +2 -2
  334. autocoder/common/v2/agent/agentic_edit_tools/conversation_message_ids_read_tool_resolver.py +214 -0
  335. autocoder/common/v2/agent/agentic_edit_tools/conversation_message_ids_write_tool_resolver.py +299 -0
  336. autocoder/common/v2/agent/agentic_edit_tools/count_tokens_tool_resolver.py +290 -0
  337. autocoder/common/v2/agent/agentic_edit_tools/execute_command_tool_resolver.py +564 -29
  338. autocoder/common/v2/agent/agentic_edit_tools/execute_workflow_tool_resolver.py +485 -0
  339. autocoder/common/v2/agent/agentic_edit_tools/extract_to_text_tool_resolver.py +225 -0
  340. autocoder/common/v2/agent/agentic_edit_tools/lint_report.py +79 -0
  341. autocoder/common/v2/agent/agentic_edit_tools/linter_config_models.py +343 -0
  342. autocoder/common/v2/agent/agentic_edit_tools/linter_enabled_tool_resolver.py +189 -0
  343. autocoder/common/v2/agent/agentic_edit_tools/list_files_tool_resolver.py +169 -101
  344. autocoder/common/v2/agent/agentic_edit_tools/load_extra_document_tool_resolver.py +349 -0
  345. autocoder/common/v2/agent/agentic_edit_tools/read_file_tool_resolver.py +243 -50
  346. autocoder/common/v2/agent/agentic_edit_tools/replace_in_file_tool_resolver.py +667 -147
  347. autocoder/common/v2/agent/agentic_edit_tools/run_named_subagents_tool_resolver.py +691 -0
  348. autocoder/common/v2/agent/agentic_edit_tools/search_files_tool_resolver.py +410 -86
  349. autocoder/common/v2/agent/agentic_edit_tools/session_interactive_tool_resolver.py +115 -0
  350. autocoder/common/v2/agent/agentic_edit_tools/session_start_tool_resolver.py +190 -0
  351. autocoder/common/v2/agent/agentic_edit_tools/session_stop_tool_resolver.py +76 -0
  352. autocoder/common/v2/agent/agentic_edit_tools/test_write_to_file_tool_resolver.py +207 -192
  353. autocoder/common/v2/agent/agentic_edit_tools/todo_read_tool_resolver.py +80 -63
  354. autocoder/common/v2/agent/agentic_edit_tools/todo_write_tool_resolver.py +237 -233
  355. autocoder/common/v2/agent/agentic_edit_tools/use_mcp_tool_resolver.py +2 -2
  356. autocoder/common/v2/agent/agentic_edit_tools/web_crawl_tool_resolver.py +557 -0
  357. autocoder/common/v2/agent/agentic_edit_tools/web_search_tool_resolver.py +600 -0
  358. autocoder/common/v2/agent/agentic_edit_tools/write_to_file_tool_resolver.py +56 -121
  359. autocoder/common/v2/agent/agentic_edit_types.py +343 -9
  360. autocoder/common/v2/agent/runner/__init__.py +3 -3
  361. autocoder/common/v2/agent/runner/base_runner.py +12 -26
  362. autocoder/common/v2/agent/runner/{event_runner.py → file_based_event_runner.py} +3 -2
  363. autocoder/common/v2/agent/runner/sdk_runner.py +150 -8
  364. autocoder/common/v2/agent/runner/terminal_runner.py +170 -57
  365. autocoder/common/v2/agent/runner/tool_display.py +557 -159
  366. autocoder/common/v2/agent/test_agentic_callbacks.py +265 -0
  367. autocoder/common/v2/agent/test_agentic_edit.py +194 -0
  368. autocoder/common/v2/agent/tool_caller/__init__.py +24 -0
  369. autocoder/common/v2/agent/tool_caller/default_tool_resolver_map.py +135 -0
  370. autocoder/common/v2/agent/tool_caller/integration_test.py +172 -0
  371. autocoder/common/v2/agent/tool_caller/plugins/__init__.py +14 -0
  372. autocoder/common/v2/agent/tool_caller/plugins/base_plugin.py +126 -0
  373. autocoder/common/v2/agent/tool_caller/plugins/examples/__init__.py +13 -0
  374. autocoder/common/v2/agent/tool_caller/plugins/examples/logging_plugin.py +164 -0
  375. autocoder/common/v2/agent/tool_caller/plugins/examples/security_filter_plugin.py +198 -0
  376. autocoder/common/v2/agent/tool_caller/plugins/plugin_interface.py +141 -0
  377. autocoder/common/v2/agent/tool_caller/test_tool_caller.py +278 -0
  378. autocoder/common/v2/agent/tool_caller/tool_call_plugin_manager.py +331 -0
  379. autocoder/common/v2/agent/tool_caller/tool_caller.py +337 -0
  380. autocoder/common/v2/agent/tool_caller/usage_example.py +193 -0
  381. autocoder/common/v2/code_agentic_editblock_manager.py +4 -4
  382. autocoder/common/v2/code_auto_generate.py +136 -78
  383. autocoder/common/v2/code_auto_generate_diff.py +135 -79
  384. autocoder/common/v2/code_auto_generate_editblock.py +174 -99
  385. autocoder/common/v2/code_auto_generate_strict_diff.py +151 -71
  386. autocoder/common/v2/code_auto_merge.py +1 -1
  387. autocoder/common/v2/code_auto_merge_editblock.py +13 -1
  388. autocoder/common/v2/code_diff_manager.py +3 -3
  389. autocoder/common/v2/code_editblock_manager.py +4 -14
  390. autocoder/common/v2/code_manager.py +1 -1
  391. autocoder/common/v2/code_strict_diff_manager.py +2 -2
  392. autocoder/common/wrap_llm_hint/__init__.py +10 -0
  393. autocoder/common/wrap_llm_hint/test_wrap_llm_hint.py +1067 -0
  394. autocoder/common/wrap_llm_hint/utils.py +432 -0
  395. autocoder/common/wrap_llm_hint/wrap_llm_hint.py +323 -0
  396. autocoder/completer/__init__.py +8 -0
  397. autocoder/completer/command_completer_v2.py +1051 -0
  398. autocoder/default_project/__init__.py +501 -0
  399. autocoder/dispacher/__init__.py +4 -12
  400. autocoder/dispacher/actions/action.py +165 -7
  401. autocoder/dispacher/actions/plugins/action_regex_project.py +2 -2
  402. autocoder/index/entry.py +116 -124
  403. autocoder/{agent → index/filter}/agentic_filter.py +322 -333
  404. autocoder/index/filter/normal_filter.py +5 -11
  405. autocoder/index/filter/quick_filter.py +1 -1
  406. autocoder/index/index.py +36 -9
  407. autocoder/index/tests/__init__.py +1 -0
  408. autocoder/index/tests/run_tests.py +195 -0
  409. autocoder/index/tests/test_entry.py +303 -0
  410. autocoder/index/tests/test_index_manager.py +314 -0
  411. autocoder/index/tests/test_module_integration.py +300 -0
  412. autocoder/index/tests/test_symbols_utils.py +183 -0
  413. autocoder/inner/__init__.py +4 -0
  414. autocoder/inner/agentic.py +932 -0
  415. autocoder/inner/async_command_handler.py +992 -0
  416. autocoder/inner/conversation_command_handlers.py +623 -0
  417. autocoder/inner/merge_command_handler.py +213 -0
  418. autocoder/inner/queue_command_handler.py +684 -0
  419. autocoder/models.py +95 -266
  420. autocoder/plugins/git_helper_plugin.py +31 -29
  421. autocoder/plugins/token_helper_plugin.py +65 -46
  422. autocoder/pyproject/__init__.py +32 -29
  423. autocoder/rag/agentic_rag.py +215 -75
  424. autocoder/rag/cache/simple_cache.py +1 -2
  425. autocoder/rag/loaders/image_loader.py +1 -1
  426. autocoder/rag/long_context_rag.py +42 -26
  427. autocoder/rag/qa_conversation_strategy.py +1 -1
  428. autocoder/rag/terminal/__init__.py +17 -0
  429. autocoder/rag/terminal/args.py +581 -0
  430. autocoder/rag/terminal/bootstrap.py +61 -0
  431. autocoder/rag/terminal/command_handlers.py +653 -0
  432. autocoder/rag/terminal/formatters/__init__.py +20 -0
  433. autocoder/rag/terminal/formatters/base.py +70 -0
  434. autocoder/rag/terminal/formatters/json_format.py +66 -0
  435. autocoder/rag/terminal/formatters/stream_json.py +95 -0
  436. autocoder/rag/terminal/formatters/text.py +28 -0
  437. autocoder/rag/terminal/init.py +120 -0
  438. autocoder/rag/terminal/utils.py +106 -0
  439. autocoder/rag/test_agentic_rag.py +389 -0
  440. autocoder/rag/test_doc_filter.py +3 -3
  441. autocoder/rag/test_long_context_rag.py +1 -1
  442. autocoder/rag/test_token_limiter.py +517 -10
  443. autocoder/rag/token_counter.py +3 -0
  444. autocoder/rag/token_limiter.py +19 -15
  445. autocoder/rag/tools/__init__.py +26 -2
  446. autocoder/rag/tools/bochaai_example.py +343 -0
  447. autocoder/rag/tools/bochaai_sdk.py +541 -0
  448. autocoder/rag/tools/metaso_example.py +268 -0
  449. autocoder/rag/tools/metaso_sdk.py +417 -0
  450. autocoder/rag/tools/recall_tool.py +28 -7
  451. autocoder/rag/tools/run_integration_tests.py +204 -0
  452. autocoder/rag/tools/test_all_providers.py +318 -0
  453. autocoder/rag/tools/test_bochaai_integration.py +482 -0
  454. autocoder/rag/tools/test_final_integration.py +215 -0
  455. autocoder/rag/tools/test_metaso_integration.py +424 -0
  456. autocoder/rag/tools/test_metaso_real.py +171 -0
  457. autocoder/rag/tools/test_web_crawl_tool.py +639 -0
  458. autocoder/rag/tools/test_web_search_tool.py +509 -0
  459. autocoder/rag/tools/todo_read_tool.py +202 -0
  460. autocoder/rag/tools/todo_write_tool.py +412 -0
  461. autocoder/rag/tools/web_crawl_tool.py +634 -0
  462. autocoder/rag/tools/web_search_tool.py +558 -0
  463. autocoder/rag/tools/web_tools_example.py +119 -0
  464. autocoder/rag/types.py +16 -0
  465. autocoder/rag/variable_holder.py +4 -2
  466. autocoder/rags.py +86 -79
  467. autocoder/regexproject/__init__.py +23 -21
  468. autocoder/sdk/__init__.py +46 -190
  469. autocoder/sdk/api.py +370 -0
  470. autocoder/sdk/async_runner/__init__.py +26 -0
  471. autocoder/sdk/async_runner/async_executor.py +650 -0
  472. autocoder/sdk/async_runner/async_handler.py +356 -0
  473. autocoder/sdk/async_runner/markdown_processor.py +595 -0
  474. autocoder/sdk/async_runner/task_metadata.py +284 -0
  475. autocoder/sdk/async_runner/worktree_manager.py +438 -0
  476. autocoder/sdk/cli/__init__.py +2 -5
  477. autocoder/sdk/cli/formatters.py +28 -204
  478. autocoder/sdk/cli/handlers.py +77 -44
  479. autocoder/sdk/cli/main.py +154 -171
  480. autocoder/sdk/cli/options.py +95 -22
  481. autocoder/sdk/constants.py +139 -51
  482. autocoder/sdk/core/auto_coder_core.py +484 -109
  483. autocoder/sdk/core/bridge.py +297 -115
  484. autocoder/sdk/exceptions.py +18 -12
  485. autocoder/sdk/formatters/__init__.py +19 -0
  486. autocoder/sdk/formatters/input.py +64 -0
  487. autocoder/sdk/formatters/output.py +247 -0
  488. autocoder/sdk/formatters/stream.py +54 -0
  489. autocoder/sdk/models/__init__.py +6 -5
  490. autocoder/sdk/models/options.py +55 -18
  491. autocoder/sdk/utils/formatters.py +27 -195
  492. autocoder/suffixproject/__init__.py +28 -25
  493. autocoder/terminal/__init__.py +14 -0
  494. autocoder/terminal/app.py +454 -0
  495. autocoder/terminal/args.py +32 -0
  496. autocoder/terminal/bootstrap.py +178 -0
  497. autocoder/terminal/command_processor.py +521 -0
  498. autocoder/terminal/command_registry.py +57 -0
  499. autocoder/terminal/help.py +97 -0
  500. autocoder/terminal/tasks/__init__.py +5 -0
  501. autocoder/terminal/tasks/background.py +77 -0
  502. autocoder/terminal/tasks/task_event.py +70 -0
  503. autocoder/terminal/ui/__init__.py +13 -0
  504. autocoder/terminal/ui/completer.py +268 -0
  505. autocoder/terminal/ui/keybindings.py +75 -0
  506. autocoder/terminal/ui/session.py +41 -0
  507. autocoder/terminal/ui/toolbar.py +64 -0
  508. autocoder/terminal/utils/__init__.py +13 -0
  509. autocoder/terminal/utils/errors.py +18 -0
  510. autocoder/terminal/utils/paths.py +19 -0
  511. autocoder/terminal/utils/shell.py +43 -0
  512. autocoder/terminal_v3/__init__.py +10 -0
  513. autocoder/terminal_v3/app.py +201 -0
  514. autocoder/terminal_v3/handlers/__init__.py +5 -0
  515. autocoder/terminal_v3/handlers/command_handler.py +131 -0
  516. autocoder/terminal_v3/models/__init__.py +6 -0
  517. autocoder/terminal_v3/models/conversation_buffer.py +214 -0
  518. autocoder/terminal_v3/models/message.py +50 -0
  519. autocoder/terminal_v3/models/tool_display.py +247 -0
  520. autocoder/terminal_v3/ui/__init__.py +7 -0
  521. autocoder/terminal_v3/ui/keybindings.py +56 -0
  522. autocoder/terminal_v3/ui/layout.py +141 -0
  523. autocoder/terminal_v3/ui/styles.py +43 -0
  524. autocoder/tsproject/__init__.py +23 -23
  525. autocoder/utils/auto_coder_utils/chat_stream_out.py +1 -1
  526. autocoder/utils/llms.py +88 -80
  527. autocoder/utils/math_utils.py +101 -0
  528. autocoder/utils/model_provider_selector.py +16 -4
  529. autocoder/utils/operate_config_api.py +33 -5
  530. autocoder/utils/thread_utils.py +2 -2
  531. autocoder/version.py +4 -2
  532. autocoder/workflow_agents/__init__.py +84 -0
  533. autocoder/workflow_agents/agent.py +143 -0
  534. autocoder/workflow_agents/exceptions.py +573 -0
  535. autocoder/workflow_agents/executor.py +489 -0
  536. autocoder/workflow_agents/loader.py +737 -0
  537. autocoder/workflow_agents/runner.py +267 -0
  538. autocoder/workflow_agents/types.py +172 -0
  539. autocoder/workflow_agents/utils.py +434 -0
  540. autocoder/workflow_agents/workflow_manager.py +211 -0
  541. auto_coder-1.0.0.dist-info/METADATA +0 -396
  542. auto_coder-1.0.0.dist-info/RECORD +0 -442
  543. auto_coder-1.0.0.dist-info/licenses/LICENSE +0 -201
  544. autocoder/auto_coder_server.py +0 -672
  545. autocoder/benchmark.py +0 -138
  546. autocoder/common/ac_style_command_parser/example.py +0 -7
  547. autocoder/common/cleaner.py +0 -31
  548. autocoder/common/command_completer_v2.py +0 -615
  549. autocoder/common/context_pruner.py +0 -477
  550. autocoder/common/conversation_pruner.py +0 -132
  551. autocoder/common/directory_cache/__init__.py +0 -1
  552. autocoder/common/directory_cache/cache.py +0 -192
  553. autocoder/common/directory_cache/test_cache.py +0 -190
  554. autocoder/common/file_checkpoint/examples.py +0 -217
  555. autocoder/common/llm_friendly_package_example.py +0 -138
  556. autocoder/common/llm_friendly_package_test.py +0 -63
  557. autocoder/common/pull_requests/test_module.py +0 -1
  558. autocoder/common/rulefiles/autocoderrules_utils.py +0 -484
  559. autocoder/common/text.py +0 -30
  560. autocoder/common/v2/agent/agentic_edit_tools/list_package_info_tool_resolver.py +0 -42
  561. autocoder/common/v2/agent/agentic_edit_tools/test_execute_command_tool_resolver.py +0 -70
  562. autocoder/common/v2/agent/agentic_edit_tools/test_search_files_tool_resolver.py +0 -163
  563. autocoder/common/v2/agent/agentic_tool_display.py +0 -183
  564. autocoder/plugins/dynamic_completion_example.py +0 -148
  565. autocoder/plugins/sample_plugin.py +0 -160
  566. autocoder/sdk/cli/__main__.py +0 -26
  567. autocoder/sdk/cli/completion_wrapper.py +0 -38
  568. autocoder/sdk/cli/install_completion.py +0 -301
  569. autocoder/sdk/models/messages.py +0 -209
  570. autocoder/sdk/session/__init__.py +0 -32
  571. autocoder/sdk/session/session.py +0 -106
  572. autocoder/sdk/session/session_manager.py +0 -56
  573. {auto_coder-1.0.0.dist-info → auto_coder-2.0.0.dist-info}/top_level.txt +0 -0
  574. /autocoder/{sdk/example.py → common/agent_query_queue/__init__.py} +0 -0
@@ -0,0 +1,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 []
@@ -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
  """
@@ -0,0 +1,17 @@
1
+ """
2
+ Tools Manager Module
3
+
4
+ 动态加载和管理 .autocodertools 目录中的工具命令文件的模块。
5
+ """
6
+
7
+ from .manager import ToolsManager
8
+ from .models import ToolCommand, ToolsLoadResult
9
+ from .utils import extract_tool_help, is_tool_command_file
10
+
11
+ __all__ = [
12
+ "ToolsManager",
13
+ "ToolCommand",
14
+ "ToolsLoadResult",
15
+ "extract_tool_help",
16
+ "is_tool_command_file"
17
+ ]