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,89 @@
1
+ """
2
+ Base cache interface for todo caching.
3
+
4
+ This module defines the abstract base class for all cache implementations,
5
+ providing a consistent interface for caching operations.
6
+ """
7
+
8
+ from abc import ABC, abstractmethod
9
+ from typing import Optional, Any, List
10
+
11
+
12
+ class BaseCache(ABC):
13
+ """Abstract base class for cache implementations."""
14
+
15
+ @abstractmethod
16
+ def get(self, key: str) -> Optional[Any]:
17
+ """
18
+ Get a value from the cache.
19
+
20
+ Args:
21
+ key: The cache key
22
+
23
+ Returns:
24
+ The cached value or None if not found/expired
25
+ """
26
+ pass
27
+
28
+ @abstractmethod
29
+ def set(self, key: str, value: Any, ttl: Optional[float] = None) -> None:
30
+ """
31
+ Set a value in the cache.
32
+
33
+ Args:
34
+ key: The cache key
35
+ value: The value to cache
36
+ ttl: Time to live in seconds, None for no expiration
37
+ """
38
+ pass
39
+
40
+ @abstractmethod
41
+ def delete(self, key: str) -> bool:
42
+ """
43
+ Delete a value from the cache.
44
+
45
+ Args:
46
+ key: The cache key
47
+
48
+ Returns:
49
+ True if the key was deleted, False if it didn't exist
50
+ """
51
+ pass
52
+
53
+ @abstractmethod
54
+ def clear(self) -> None:
55
+ """Clear all items from the cache."""
56
+ pass
57
+
58
+ @abstractmethod
59
+ def exists(self, key: str) -> bool:
60
+ """
61
+ Check if a key exists in the cache.
62
+
63
+ Args:
64
+ key: The cache key
65
+
66
+ Returns:
67
+ True if the key exists and is not expired, False otherwise
68
+ """
69
+ pass
70
+
71
+ @abstractmethod
72
+ def size(self) -> int:
73
+ """
74
+ Get the current number of items in the cache.
75
+
76
+ Returns:
77
+ The number of items currently in the cache
78
+ """
79
+ pass
80
+
81
+ @abstractmethod
82
+ def keys(self) -> List[str]:
83
+ """
84
+ Get all keys currently in the cache.
85
+
86
+ Returns:
87
+ List of keys currently in the cache
88
+ """
89
+ pass
@@ -0,0 +1,228 @@
1
+ """
2
+ Cache manager for todo caching.
3
+
4
+ This module provides a high-level interface for managing caches of
5
+ todo lists, with support for cache warming, invalidation,
6
+ and statistics reporting.
7
+ """
8
+
9
+ import logging
10
+ from typing import Optional, List, Dict, Any
11
+
12
+ from .base_cache import BaseCache
13
+ from .memory_cache import MemoryCache
14
+ from ..models import TodoList
15
+
16
+ logger = logging.getLogger(__name__)
17
+
18
+
19
+ class CacheManager:
20
+ """High-level cache manager for todo lists."""
21
+
22
+ def __init__(self, todo_cache: Optional[BaseCache] = None):
23
+ """
24
+ Initialize cache manager.
25
+
26
+ Args:
27
+ todo_cache: Cache instance for todo lists
28
+ """
29
+ self.todo_cache = todo_cache or MemoryCache(
30
+ max_size=50, default_ttl=300.0 # 5 minutes default
31
+ )
32
+
33
+ # Ensure cache implements required interface
34
+ self._validate_cache_interface(self.todo_cache)
35
+
36
+ def _validate_cache_interface(self, cache: BaseCache) -> None:
37
+ """Validate that cache implements required interface."""
38
+ required_methods = ['get', 'set', 'delete', 'clear', 'exists', 'size', 'keys']
39
+ for method in required_methods:
40
+ if not hasattr(cache, method) or not callable(getattr(cache, method)):
41
+ raise TypeError(f"Cache must implement {method} method")
42
+
43
+ def _get_todo_list_key(self, conversation_id: str) -> str:
44
+ """Generate cache key for todo list."""
45
+ return f"todos:{conversation_id}"
46
+
47
+ def cache_todo_list(
48
+ self,
49
+ todo_list: Dict[str, Any],
50
+ ttl: Optional[float] = None
51
+ ) -> None:
52
+ """
53
+ Cache a todo list.
54
+
55
+ Args:
56
+ todo_list: The todo list to cache
57
+ ttl: Time to live in seconds, None for default
58
+ """
59
+ try:
60
+ conversation_id = todo_list.get('conversation_id')
61
+ if not conversation_id:
62
+ logger.error("Cannot cache todo list without conversation_id")
63
+ return
64
+
65
+ key = self._get_todo_list_key(conversation_id)
66
+ self.todo_cache.set(key, todo_list, ttl=ttl)
67
+ logger.debug(f"Cached todo list for conversation {conversation_id}")
68
+ except Exception as e:
69
+ logger.error(f"Failed to cache todo list for conversation {conversation_id}: {e}")
70
+
71
+ def get_todo_list(self, conversation_id: str) -> Optional[Dict[str, Any]]:
72
+ """
73
+ Get a todo list from cache.
74
+
75
+ Args:
76
+ conversation_id: The conversation ID
77
+
78
+ Returns:
79
+ The cached todo list or None if not found
80
+ """
81
+ try:
82
+ key = self._get_todo_list_key(conversation_id)
83
+ todo_list = self.todo_cache.get(key)
84
+ if todo_list:
85
+ logger.debug(f"Cache hit for todo list of conversation {conversation_id}")
86
+ else:
87
+ logger.debug(f"Cache miss for todo list of conversation {conversation_id}")
88
+ return todo_list
89
+ except Exception as e:
90
+ logger.error(f"Failed to get todo list for conversation {conversation_id} from cache: {e}")
91
+ return None
92
+
93
+ def invalidate_todo_list(self, conversation_id: str) -> bool:
94
+ """
95
+ Invalidate cached todo list.
96
+
97
+ Args:
98
+ conversation_id: The conversation ID
99
+
100
+ Returns:
101
+ True if todo list was cached and removed, False otherwise
102
+ """
103
+ try:
104
+ key = self._get_todo_list_key(conversation_id)
105
+ result = self.todo_cache.delete(key)
106
+ if result:
107
+ logger.debug(f"Invalidated todo list for conversation {conversation_id}")
108
+ return result
109
+ except Exception as e:
110
+ logger.error(f"Failed to invalidate todo list for conversation {conversation_id}: {e}")
111
+ return False
112
+
113
+ def cache_todo_lists(
114
+ self,
115
+ todo_lists: List[Dict[str, Any]],
116
+ ttl: Optional[float] = None
117
+ ) -> int:
118
+ """
119
+ Cache multiple todo lists.
120
+
121
+ Args:
122
+ todo_lists: List of todo lists to cache
123
+ ttl: Time to live in seconds, None for default
124
+
125
+ Returns:
126
+ Number of todo lists successfully cached
127
+ """
128
+ count = 0
129
+ for todo_list in todo_lists:
130
+ try:
131
+ self.cache_todo_list(todo_list, ttl=ttl)
132
+ count += 1
133
+ except Exception as e:
134
+ conversation_id = todo_list.get('conversation_id', 'unknown')
135
+ logger.error(f"Failed to cache todo list for conversation {conversation_id}: {e}")
136
+
137
+ return count
138
+
139
+ def invalidate_todo_lists(self, conversation_ids: List[str]) -> Dict[str, bool]:
140
+ """
141
+ Invalidate multiple todo lists.
142
+
143
+ Args:
144
+ conversation_ids: List of conversation IDs to invalidate
145
+
146
+ Returns:
147
+ Dictionary mapping conversation IDs to invalidation results
148
+ """
149
+ results = {}
150
+ for conversation_id in conversation_ids:
151
+ results[conversation_id] = self.invalidate_todo_list(conversation_id)
152
+
153
+ return results
154
+
155
+ def clear_all_caches(self) -> None:
156
+ """Clear all caches."""
157
+ try:
158
+ self.todo_cache.clear()
159
+ logger.info("Cleared all todo caches")
160
+ except Exception as e:
161
+ logger.error(f"Failed to clear caches: {e}")
162
+
163
+ def get_cache_statistics(self) -> Dict[str, Any]:
164
+ """
165
+ Get statistics for all caches.
166
+
167
+ Returns:
168
+ Dictionary with cache statistics
169
+ """
170
+ try:
171
+ stats = {
172
+ "todo_cache": {
173
+ "size": self.todo_cache.size(),
174
+ "max_size": getattr(self.todo_cache, 'max_size', 'unknown')
175
+ }
176
+ }
177
+
178
+ # Add detailed stats if available
179
+ if hasattr(self.todo_cache, 'get_statistics'):
180
+ get_stats_method = getattr(self.todo_cache, 'get_statistics')
181
+ stats["todo_cache"].update(
182
+ get_stats_method()
183
+ )
184
+
185
+ return stats
186
+
187
+ except Exception as e:
188
+ logger.error(f"Failed to get cache statistics: {e}")
189
+ return {
190
+ "todo_cache": {"size": 0, "max_size": "unknown"},
191
+ "error": str(e)
192
+ }
193
+
194
+ def is_todo_list_cached(self, conversation_id: str) -> bool:
195
+ """
196
+ Check if a todo list is cached.
197
+
198
+ Args:
199
+ conversation_id: The conversation ID
200
+
201
+ Returns:
202
+ True if todo list is cached, False otherwise
203
+ """
204
+ try:
205
+ key = self._get_todo_list_key(conversation_id)
206
+ return self.todo_cache.exists(key)
207
+ except Exception as e:
208
+ logger.error(f"Failed to check if todo list for conversation {conversation_id} is cached: {e}")
209
+ return False
210
+
211
+ def get_cached_conversation_ids(self) -> List[str]:
212
+ """
213
+ Get all cached conversation IDs.
214
+
215
+ Returns:
216
+ List of conversation IDs currently cached
217
+ """
218
+ try:
219
+ keys = self.todo_cache.keys()
220
+ # Extract conversation IDs from cache keys
221
+ conversation_ids = []
222
+ for key in keys:
223
+ if key.startswith("todos:"):
224
+ conversation_ids.append(key[6:]) # Remove "todos:" prefix
225
+ return conversation_ids
226
+ except Exception as e:
227
+ logger.error(f"Failed to get cached conversation IDs: {e}")
228
+ return []
@@ -0,0 +1,225 @@
1
+ """
2
+ Memory-based cache implementation with LRU eviction and TTL support.
3
+
4
+ This module provides a thread-safe in-memory cache with configurable
5
+ size limits, TTL expiration, and LRU eviction policies.
6
+ """
7
+
8
+ import time
9
+ import threading
10
+ from collections import OrderedDict
11
+ from typing import Optional, Any, List, Dict
12
+ from dataclasses import dataclass
13
+
14
+ from .base_cache import BaseCache
15
+
16
+ # Sentinel object to distinguish between "no ttl provided" and "ttl=None"
17
+ _TTL_NOT_PROVIDED = object()
18
+
19
+
20
+ @dataclass
21
+ class CacheEntry:
22
+ """Cache entry with value and expiration time."""
23
+ value: Any
24
+ expires_at: Optional[float] = None
25
+
26
+ def is_expired(self) -> bool:
27
+ """Check if this entry has expired."""
28
+ if self.expires_at is None:
29
+ return False
30
+ return time.time() > self.expires_at
31
+
32
+
33
+ class MemoryCache(BaseCache):
34
+ """Thread-safe in-memory cache with LRU eviction and TTL support."""
35
+
36
+ def __init__(self, max_size: int = 50, default_ttl: float = 300.0):
37
+ """
38
+ Initialize memory cache.
39
+
40
+ Args:
41
+ max_size: Maximum number of items to cache
42
+ default_ttl: Default TTL in seconds for cached items
43
+ """
44
+ if max_size <= 0:
45
+ raise ValueError("max_size must be positive")
46
+
47
+ self.max_size = max_size
48
+ self.default_ttl = default_ttl
49
+ self._cache: OrderedDict[str, CacheEntry] = OrderedDict()
50
+ self._lock = threading.RLock()
51
+
52
+ # Optional statistics
53
+ self.hit_count = 0
54
+ self.miss_count = 0
55
+
56
+ def get(self, key: str) -> Optional[Any]:
57
+ """
58
+ Get a value from the cache.
59
+
60
+ Args:
61
+ key: The cache key
62
+
63
+ Returns:
64
+ The cached value or None if not found/expired
65
+ """
66
+ with self._lock:
67
+ entry = self._cache.get(key)
68
+
69
+ if entry is None:
70
+ self.miss_count += 1
71
+ return None
72
+
73
+ if entry.is_expired():
74
+ # Remove expired entry
75
+ del self._cache[key]
76
+ self.miss_count += 1
77
+ return None
78
+
79
+ # Move to end (most recently used)
80
+ self._cache.move_to_end(key)
81
+ self.hit_count += 1
82
+ return entry.value
83
+
84
+ def set(self, key: str, value: Any, ttl = _TTL_NOT_PROVIDED) -> None:
85
+ """
86
+ Set a value in the cache.
87
+
88
+ Args:
89
+ key: The cache key
90
+ value: The value to cache
91
+ ttl: Time to live in seconds, None for no expiration
92
+ """
93
+ with self._lock:
94
+ # Calculate expiration time
95
+ expires_at = None
96
+
97
+ if ttl is _TTL_NOT_PROVIDED:
98
+ # No ttl provided, use default_ttl behavior
99
+ if self.default_ttl > 0:
100
+ expires_at = time.time() + self.default_ttl
101
+ elif ttl is None:
102
+ # Explicit None means permanent caching
103
+ expires_at = None
104
+ elif ttl > 0:
105
+ # Positive ttl value
106
+ expires_at = time.time() + ttl
107
+ # ttl <= 0 means permanent caching (expires_at stays None)
108
+
109
+ # Create cache entry
110
+ entry = CacheEntry(value=value, expires_at=expires_at)
111
+
112
+ # If key already exists, update it
113
+ if key in self._cache:
114
+ self._cache[key] = entry
115
+ self._cache.move_to_end(key)
116
+ else:
117
+ # Add new entry
118
+ self._cache[key] = entry
119
+
120
+ # Evict oldest items if over capacity
121
+ while len(self._cache) > self.max_size:
122
+ oldest_key = next(iter(self._cache))
123
+ del self._cache[oldest_key]
124
+
125
+ def delete(self, key: str) -> bool:
126
+ """
127
+ Delete a value from the cache.
128
+
129
+ Args:
130
+ key: The cache key
131
+
132
+ Returns:
133
+ True if the key was deleted, False if it didn't exist
134
+ """
135
+ with self._lock:
136
+ if key in self._cache:
137
+ del self._cache[key]
138
+ return True
139
+ return False
140
+
141
+ def clear(self) -> None:
142
+ """Clear all items from the cache."""
143
+ with self._lock:
144
+ self._cache.clear()
145
+
146
+ def exists(self, key: str) -> bool:
147
+ """
148
+ Check if a key exists in the cache.
149
+
150
+ Args:
151
+ key: The cache key
152
+
153
+ Returns:
154
+ True if the key exists and is not expired, False otherwise
155
+ """
156
+ with self._lock:
157
+ entry = self._cache.get(key)
158
+
159
+ if entry is None:
160
+ return False
161
+
162
+ if entry.is_expired():
163
+ # Remove expired entry
164
+ del self._cache[key]
165
+ return False
166
+
167
+ return True
168
+
169
+ def size(self) -> int:
170
+ """
171
+ Get the current number of items in the cache.
172
+
173
+ Returns:
174
+ The number of items currently in the cache
175
+ """
176
+ with self._lock:
177
+ # Clean up expired items
178
+ self._cleanup_expired()
179
+ return len(self._cache)
180
+
181
+ def keys(self) -> List[str]:
182
+ """
183
+ Get all keys currently in the cache.
184
+
185
+ Returns:
186
+ List of keys currently in the cache
187
+ """
188
+ with self._lock:
189
+ # Clean up expired items
190
+ self._cleanup_expired()
191
+ return list(self._cache.keys())
192
+
193
+ def _cleanup_expired(self) -> None:
194
+ """Remove all expired entries from the cache."""
195
+ current_time = time.time()
196
+ expired_keys = []
197
+
198
+ for key, entry in self._cache.items():
199
+ if entry.expires_at is not None and current_time > entry.expires_at:
200
+ expired_keys.append(key)
201
+
202
+ for key in expired_keys:
203
+ del self._cache[key]
204
+
205
+ def get_statistics(self) -> Dict[str, Any]:
206
+ """
207
+ Get cache statistics.
208
+
209
+ Returns:
210
+ Dictionary with cache statistics
211
+ """
212
+ with self._lock:
213
+ self._cleanup_expired()
214
+
215
+ total_requests = self.hit_count + self.miss_count
216
+ hit_rate = self.hit_count / total_requests if total_requests > 0 else 0.0
217
+
218
+ return {
219
+ "size": len(self._cache),
220
+ "max_size": self.max_size,
221
+ "hit_count": self.hit_count,
222
+ "miss_count": self.miss_count,
223
+ "hit_rate": hit_rate,
224
+ "default_ttl": self.default_ttl
225
+ }
@@ -0,0 +1,155 @@
1
+ """
2
+ Todo manager configuration class.
3
+ """
4
+
5
+ import os
6
+ import json
7
+ from dataclasses import dataclass
8
+ from typing import Optional, Dict, Any
9
+
10
+
11
+ @dataclass
12
+ class TodoManagerConfig:
13
+ """Configuration class for todo manager"""
14
+
15
+ storage_path: str = "./.auto-coder/todos"
16
+ max_cache_size: int = 50
17
+ cache_ttl: float = 300.0
18
+ enable_compression: bool = False
19
+ log_level: str = "INFO"
20
+
21
+ def __post_init__(self):
22
+ """Validate configuration"""
23
+ self._validate()
24
+
25
+ def _validate(self):
26
+ """Validate configuration data"""
27
+ # Validate storage path
28
+ if not self.storage_path or not isinstance(self.storage_path, str):
29
+ raise ValueError("Storage path cannot be empty")
30
+
31
+ # Validate cache size
32
+ if not isinstance(self.max_cache_size, int) or self.max_cache_size <= 0:
33
+ raise ValueError("Cache size must be a positive integer")
34
+
35
+ # Validate cache TTL
36
+ if not isinstance(self.cache_ttl, (int, float)) or self.cache_ttl <= 0:
37
+ raise ValueError("Cache TTL must be a positive number")
38
+
39
+ # Validate log level
40
+ valid_levels = ["DEBUG", "INFO", "WARNING", "ERROR", "CRITICAL"]
41
+ if self.log_level not in valid_levels:
42
+ raise ValueError(f"Invalid log level: {self.log_level}, valid levels: {valid_levels}")
43
+
44
+ def to_dict(self) -> Dict[str, Any]:
45
+ """Convert to dictionary"""
46
+ return {
47
+ "storage_path": self.storage_path,
48
+ "max_cache_size": self.max_cache_size,
49
+ "cache_ttl": self.cache_ttl,
50
+ "enable_compression": self.enable_compression,
51
+ "log_level": self.log_level
52
+ }
53
+
54
+ @classmethod
55
+ def from_dict(cls, data: Dict[str, Any]) -> "TodoManagerConfig":
56
+ """Create config from dictionary"""
57
+ config = cls()
58
+
59
+ for key, value in data.items():
60
+ if hasattr(config, key):
61
+ setattr(config, key, value)
62
+
63
+ config._validate()
64
+ return config
65
+
66
+ @classmethod
67
+ def from_env(cls, prefix: str = "TODO_") -> "TodoManagerConfig":
68
+ """Create config from environment variables"""
69
+ config = cls()
70
+
71
+ env_mapping = {
72
+ f"{prefix}STORAGE_PATH": "storage_path",
73
+ f"{prefix}MAX_CACHE_SIZE": "max_cache_size",
74
+ f"{prefix}CACHE_TTL": "cache_ttl",
75
+ f"{prefix}ENABLE_COMPRESSION": "enable_compression",
76
+ f"{prefix}LOG_LEVEL": "log_level"
77
+ }
78
+
79
+ for env_key, attr_name in env_mapping.items():
80
+ env_value = os.environ.get(env_key)
81
+ if env_value is not None:
82
+ try:
83
+ if attr_name in ["max_cache_size"]:
84
+ value = int(env_value)
85
+ elif attr_name in ["cache_ttl"]:
86
+ value = float(env_value)
87
+ elif attr_name in ["enable_compression"]:
88
+ value = env_value.lower() in ["true", "1", "yes", "on"]
89
+ else:
90
+ value = env_value
91
+
92
+ setattr(config, attr_name, value)
93
+ except (ValueError, TypeError) as e:
94
+ raise ValueError(f"Environment variable {env_key} has invalid value '{env_value}': {e}")
95
+
96
+ config._validate()
97
+ return config
98
+
99
+ def save_to_file(self, file_path: str):
100
+ """Save config to file"""
101
+ os.makedirs(os.path.dirname(file_path), exist_ok=True)
102
+
103
+ with open(file_path, 'w', encoding='utf-8') as f:
104
+ json.dump(self.to_dict(), f, indent=2, ensure_ascii=False)
105
+
106
+ @classmethod
107
+ def load_from_file(cls, file_path: str) -> "TodoManagerConfig":
108
+ """Load config from file"""
109
+ if not os.path.exists(file_path):
110
+ raise FileNotFoundError(f"Config file not found: {file_path}")
111
+
112
+ try:
113
+ with open(file_path, 'r', encoding='utf-8') as f:
114
+ data = json.load(f)
115
+
116
+ return cls.from_dict(data)
117
+ except json.JSONDecodeError as e:
118
+ raise ValueError(f"Config file format error: {e}")
119
+
120
+ def copy(self) -> "TodoManagerConfig":
121
+ """Create a deep copy of the config"""
122
+ return TodoManagerConfig.from_dict(self.to_dict())
123
+
124
+ def update(self, **kwargs):
125
+ """Update config fields"""
126
+ backup_values = {}
127
+ for key in kwargs.keys():
128
+ if hasattr(self, key):
129
+ backup_values[key] = getattr(self, key)
130
+ else:
131
+ raise AttributeError(f"Config has no attribute: {key}")
132
+
133
+ try:
134
+ for key, value in kwargs.items():
135
+ setattr(self, key, value)
136
+ self._validate()
137
+ except Exception:
138
+ for key, value in backup_values.items():
139
+ setattr(self, key, value)
140
+ raise
141
+
142
+ def __repr__(self) -> str:
143
+ """String representation"""
144
+ return (f"TodoManagerConfig("
145
+ f"storage_path='{self.storage_path}', "
146
+ f"max_cache_size={self.max_cache_size}, "
147
+ f"cache_ttl={self.cache_ttl}, "
148
+ f"log_level='{self.log_level}')")
149
+
150
+ def __eq__(self, other) -> bool:
151
+ """Equality comparison"""
152
+ if not isinstance(other, TodoManagerConfig):
153
+ return False
154
+
155
+ return self.to_dict() == other.to_dict()