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

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

Potentially problematic release.


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

Files changed (579) hide show
  1. auto_coder-2.0.0.dist-info/LICENSE +158 -0
  2. auto_coder-2.0.0.dist-info/METADATA +558 -0
  3. auto_coder-2.0.0.dist-info/RECORD +795 -0
  4. {auto_coder-0.1.400.dist-info → auto_coder-2.0.0.dist-info}/WHEEL +1 -1
  5. {auto_coder-0.1.400.dist-info → auto_coder-2.0.0.dist-info}/entry_points.txt +3 -3
  6. autocoder/__init__.py +31 -0
  7. autocoder/agent/auto_filegroup.py +32 -13
  8. autocoder/agent/auto_learn_from_commit.py +9 -1
  9. autocoder/agent/base_agentic/__init__.py +3 -0
  10. autocoder/agent/base_agentic/agent_hub.py +1 -1
  11. autocoder/agent/base_agentic/base_agent.py +235 -136
  12. autocoder/agent/base_agentic/default_tools.py +119 -118
  13. autocoder/agent/base_agentic/test_base_agent.py +1 -1
  14. autocoder/agent/base_agentic/tool_registry.py +32 -20
  15. autocoder/agent/base_agentic/tools/read_file_tool_resolver.py +25 -4
  16. autocoder/agent/base_agentic/tools/write_to_file_tool_resolver.py +24 -11
  17. autocoder/agent/base_agentic/types.py +42 -0
  18. autocoder/agent/entry_command_agent/chat.py +73 -59
  19. autocoder/auto_coder.py +31 -40
  20. autocoder/auto_coder_rag.py +11 -1084
  21. autocoder/auto_coder_runner.py +1029 -2310
  22. autocoder/auto_coder_terminal.py +26 -0
  23. autocoder/auto_coder_terminal_v3.py +190 -0
  24. autocoder/chat/conf_command.py +224 -124
  25. autocoder/chat/models_command.py +361 -299
  26. autocoder/chat/rules_command.py +79 -31
  27. autocoder/chat_auto_coder.py +1021 -372
  28. autocoder/chat_auto_coder_lang.py +23 -732
  29. autocoder/commands/auto_command.py +26 -9
  30. autocoder/commands/auto_web.py +1 -1
  31. autocoder/commands/tools.py +44 -44
  32. autocoder/common/__init__.py +150 -128
  33. autocoder/common/ac_style_command_parser/__init__.py +39 -2
  34. autocoder/common/ac_style_command_parser/config.py +422 -0
  35. autocoder/common/ac_style_command_parser/parser.py +292 -78
  36. autocoder/common/ac_style_command_parser/test_parser.py +241 -16
  37. autocoder/common/ac_style_command_parser/test_typed_parser.py +342 -0
  38. autocoder/common/ac_style_command_parser/typed_parser.py +653 -0
  39. autocoder/common/action_yml_file_manager.py +25 -13
  40. autocoder/common/agent_events/__init__.py +52 -0
  41. autocoder/common/agent_events/agent_event_emitter.py +193 -0
  42. autocoder/common/agent_events/event_factory.py +177 -0
  43. autocoder/common/agent_events/examples.py +307 -0
  44. autocoder/common/agent_events/types.py +113 -0
  45. autocoder/common/agent_events/utils.py +68 -0
  46. autocoder/common/agent_hooks/__init__.py +44 -0
  47. autocoder/common/agent_hooks/examples.py +582 -0
  48. autocoder/common/agent_hooks/hook_executor.py +217 -0
  49. autocoder/common/agent_hooks/hook_manager.py +288 -0
  50. autocoder/common/agent_hooks/types.py +133 -0
  51. autocoder/common/agent_hooks/utils.py +99 -0
  52. autocoder/common/agent_query_queue/queue_executor.py +324 -0
  53. autocoder/common/agent_query_queue/queue_manager.py +325 -0
  54. autocoder/common/agents/__init__.py +11 -0
  55. autocoder/common/agents/agent_manager.py +323 -0
  56. autocoder/common/agents/agent_parser.py +189 -0
  57. autocoder/common/agents/example_usage.py +344 -0
  58. autocoder/common/agents/integration_example.py +330 -0
  59. autocoder/common/agents/test_agent_parser.py +545 -0
  60. autocoder/common/async_utils.py +101 -0
  61. autocoder/common/auto_coder_lang.py +23 -972
  62. autocoder/common/autocoderargs_parser/__init__.py +14 -0
  63. autocoder/common/autocoderargs_parser/parser.py +184 -0
  64. autocoder/common/autocoderargs_parser/tests/__init__.py +1 -0
  65. autocoder/common/autocoderargs_parser/tests/test_args_parser.py +235 -0
  66. autocoder/common/autocoderargs_parser/tests/test_token_parser.py +195 -0
  67. autocoder/common/autocoderargs_parser/token_parser.py +290 -0
  68. autocoder/common/buildin_tokenizer.py +2 -4
  69. autocoder/common/code_auto_generate.py +149 -74
  70. autocoder/common/code_auto_generate_diff.py +163 -70
  71. autocoder/common/code_auto_generate_editblock.py +179 -89
  72. autocoder/common/code_auto_generate_strict_diff.py +167 -72
  73. autocoder/common/code_auto_merge_editblock.py +13 -6
  74. autocoder/common/code_modification_ranker.py +1 -1
  75. autocoder/common/command_completer.py +3 -3
  76. autocoder/common/command_file_manager/manager.py +183 -47
  77. autocoder/common/command_file_manager/test_command_file_manager.py +507 -0
  78. autocoder/common/command_templates.py +1 -1
  79. autocoder/common/conf_utils.py +2 -4
  80. autocoder/common/conversations/config.py +11 -3
  81. autocoder/common/conversations/get_conversation_manager.py +100 -2
  82. autocoder/common/conversations/llm_stats_models.py +264 -0
  83. autocoder/common/conversations/manager.py +112 -28
  84. autocoder/common/conversations/models.py +16 -2
  85. autocoder/common/conversations/storage/index_manager.py +134 -10
  86. autocoder/common/core_config/__init__.py +63 -0
  87. autocoder/common/core_config/agentic_mode_manager.py +109 -0
  88. autocoder/common/core_config/base_manager.py +123 -0
  89. autocoder/common/core_config/compatibility.py +151 -0
  90. autocoder/common/core_config/config_manager.py +156 -0
  91. autocoder/common/core_config/conversation_manager.py +31 -0
  92. autocoder/common/core_config/exclude_manager.py +72 -0
  93. autocoder/common/core_config/file_manager.py +177 -0
  94. autocoder/common/core_config/human_as_model_manager.py +129 -0
  95. autocoder/common/core_config/lib_manager.py +54 -0
  96. autocoder/common/core_config/main_manager.py +81 -0
  97. autocoder/common/core_config/mode_manager.py +126 -0
  98. autocoder/common/core_config/models.py +70 -0
  99. autocoder/common/core_config/test_memory_manager.py +1056 -0
  100. autocoder/common/env_manager.py +282 -0
  101. autocoder/common/env_manager_usage_example.py +211 -0
  102. autocoder/common/file_checkpoint/conversation_checkpoint.py +19 -19
  103. autocoder/common/file_checkpoint/manager.py +264 -48
  104. autocoder/common/file_checkpoint/test_backup.py +1 -18
  105. autocoder/common/file_checkpoint/test_manager.py +270 -1
  106. autocoder/common/file_checkpoint/test_store.py +1 -17
  107. autocoder/common/file_handler/__init__.py +23 -0
  108. autocoder/common/file_handler/active_context_handler.py +159 -0
  109. autocoder/common/file_handler/add_files_handler.py +409 -0
  110. autocoder/common/file_handler/chat_handler.py +180 -0
  111. autocoder/common/file_handler/coding_handler.py +401 -0
  112. autocoder/common/file_handler/commit_handler.py +200 -0
  113. autocoder/common/file_handler/lib_handler.py +156 -0
  114. autocoder/common/file_handler/list_files_handler.py +111 -0
  115. autocoder/common/file_handler/mcp_handler.py +268 -0
  116. autocoder/common/file_handler/models_handler.py +493 -0
  117. autocoder/common/file_handler/remove_files_handler.py +172 -0
  118. autocoder/common/file_monitor/test_file_monitor.py +307 -0
  119. autocoder/common/git_utils.py +51 -10
  120. autocoder/common/global_cancel.py +15 -6
  121. autocoder/common/ignorefiles/test_ignore_file_utils.py +1 -1
  122. autocoder/common/international/__init__.py +31 -0
  123. autocoder/common/international/demo_international.py +92 -0
  124. autocoder/common/international/message_manager.py +157 -0
  125. autocoder/common/international/messages/__init__.py +56 -0
  126. autocoder/common/international/messages/async_command_messages.py +507 -0
  127. autocoder/common/international/messages/auto_coder_messages.py +2208 -0
  128. autocoder/common/international/messages/chat_auto_coder_messages.py +1547 -0
  129. autocoder/common/international/messages/command_help_messages.py +986 -0
  130. autocoder/common/international/messages/conversation_command_messages.py +191 -0
  131. autocoder/common/international/messages/git_helper_plugin_messages.py +159 -0
  132. autocoder/common/international/messages/queue_command_messages.py +751 -0
  133. autocoder/common/international/messages/rules_command_messages.py +77 -0
  134. autocoder/common/international/messages/sdk_messages.py +1707 -0
  135. autocoder/common/international/messages/token_helper_plugin_messages.py +361 -0
  136. autocoder/common/international/messages/tool_display_messages.py +1212 -0
  137. autocoder/common/international/messages/workflow_exception_messages.py +473 -0
  138. autocoder/common/international/test_international.py +612 -0
  139. autocoder/common/linter_core/__init__.py +28 -0
  140. autocoder/common/linter_core/base_linter.py +61 -0
  141. autocoder/common/linter_core/config_loader.py +271 -0
  142. autocoder/common/linter_core/formatters/__init__.py +0 -0
  143. autocoder/common/linter_core/formatters/base_formatter.py +38 -0
  144. autocoder/common/linter_core/formatters/raw_formatter.py +17 -0
  145. autocoder/common/linter_core/linter.py +166 -0
  146. autocoder/common/linter_core/linter_factory.py +216 -0
  147. autocoder/common/linter_core/linter_manager.py +333 -0
  148. autocoder/common/linter_core/linters/__init__.py +9 -0
  149. autocoder/common/linter_core/linters/java_linter.py +342 -0
  150. autocoder/common/linter_core/linters/python_linter.py +115 -0
  151. autocoder/common/linter_core/linters/typescript_linter.py +119 -0
  152. autocoder/common/linter_core/models/__init__.py +7 -0
  153. autocoder/common/linter_core/models/lint_result.py +91 -0
  154. autocoder/common/linter_core/models.py +33 -0
  155. autocoder/common/linter_core/tests/__init__.py +3 -0
  156. autocoder/common/linter_core/tests/test_config_loader.py +323 -0
  157. autocoder/common/linter_core/tests/test_config_loading.py +308 -0
  158. autocoder/common/linter_core/tests/test_factory_manager.py +234 -0
  159. autocoder/common/linter_core/tests/test_formatters.py +147 -0
  160. autocoder/common/linter_core/tests/test_integration.py +317 -0
  161. autocoder/common/linter_core/tests/test_java_linter.py +496 -0
  162. autocoder/common/linter_core/tests/test_linters.py +265 -0
  163. autocoder/common/linter_core/tests/test_models.py +81 -0
  164. autocoder/common/linter_core/tests/verify_config_loading.py +296 -0
  165. autocoder/common/linter_core/tests/verify_fixes.py +183 -0
  166. autocoder/common/llm_friendly_package/__init__.py +31 -0
  167. autocoder/common/llm_friendly_package/base_manager.py +102 -0
  168. autocoder/common/llm_friendly_package/docs_manager.py +121 -0
  169. autocoder/common/llm_friendly_package/library_manager.py +171 -0
  170. autocoder/common/{llm_friendly_package.py → llm_friendly_package/main_manager.py} +204 -231
  171. autocoder/common/llm_friendly_package/models.py +40 -0
  172. autocoder/common/llm_friendly_package/test_llm_friendly_package.py +536 -0
  173. autocoder/common/llms/__init__.py +15 -0
  174. autocoder/common/llms/demo_error_handling.py +85 -0
  175. autocoder/common/llms/factory.py +142 -0
  176. autocoder/common/llms/manager.py +264 -0
  177. autocoder/common/llms/pricing.py +121 -0
  178. autocoder/common/llms/registry.py +288 -0
  179. autocoder/common/llms/schema.py +77 -0
  180. autocoder/common/llms/simple_demo.py +45 -0
  181. autocoder/common/llms/test_quick_model.py +116 -0
  182. autocoder/common/llms/test_remove_functionality.py +182 -0
  183. autocoder/common/llms/tests/__init__.py +1 -0
  184. autocoder/common/llms/tests/test_manager.py +330 -0
  185. autocoder/common/llms/tests/test_registry.py +364 -0
  186. autocoder/common/mcp_tools/__init__.py +62 -0
  187. autocoder/common/{mcp_tools.py → mcp_tools/executor.py} +49 -40
  188. autocoder/common/{mcp_hub.py → mcp_tools/hub.py} +42 -68
  189. autocoder/common/{mcp_server_install.py → mcp_tools/installer.py} +16 -28
  190. autocoder/common/{mcp_server.py → mcp_tools/server.py} +176 -48
  191. autocoder/common/mcp_tools/test_keyboard_interrupt.py +93 -0
  192. autocoder/common/mcp_tools/test_mcp_tools.py +391 -0
  193. autocoder/common/{mcp_server_types.py → mcp_tools/types.py} +121 -48
  194. autocoder/common/mcp_tools/verify_functionality.py +202 -0
  195. autocoder/common/model_speed_tester.py +32 -26
  196. autocoder/common/priority_directory_finder/__init__.py +142 -0
  197. autocoder/common/priority_directory_finder/examples.py +230 -0
  198. autocoder/common/priority_directory_finder/finder.py +283 -0
  199. autocoder/common/priority_directory_finder/models.py +236 -0
  200. autocoder/common/priority_directory_finder/test_priority_directory_finder.py +431 -0
  201. autocoder/common/project_scanner/__init__.py +18 -0
  202. autocoder/common/project_scanner/compat.py +77 -0
  203. autocoder/common/project_scanner/scanner.py +436 -0
  204. autocoder/common/project_tracker/__init__.py +27 -0
  205. autocoder/common/project_tracker/api.py +228 -0
  206. autocoder/common/project_tracker/demo.py +272 -0
  207. autocoder/common/project_tracker/tracker.py +487 -0
  208. autocoder/common/project_tracker/types.py +53 -0
  209. autocoder/common/pruner/__init__.py +67 -0
  210. autocoder/common/pruner/agentic_conversation_pruner.py +746 -0
  211. autocoder/common/{context_pruner.py → pruner/context_pruner.py} +137 -40
  212. autocoder/common/pruner/conversation_message_ids_api.py +386 -0
  213. autocoder/common/pruner/conversation_message_ids_manager.py +347 -0
  214. autocoder/common/pruner/conversation_message_ids_pruner.py +473 -0
  215. autocoder/common/pruner/conversation_normalizer.py +347 -0
  216. autocoder/common/{conversation_pruner.py → pruner/conversation_pruner.py} +26 -6
  217. autocoder/common/pruner/test_agentic_conversation_pruner.py +784 -0
  218. autocoder/common/pruner/test_context_pruner.py +546 -0
  219. autocoder/common/pruner/test_conversation_normalizer.py +502 -0
  220. autocoder/common/pruner/test_tool_content_detector.py +324 -0
  221. autocoder/common/pruner/tool_content_detector.py +227 -0
  222. autocoder/common/pruner/tools/__init__.py +18 -0
  223. autocoder/common/pruner/tools/query_message_ids.py +264 -0
  224. autocoder/common/pruner/tools/test_agentic_pruning_logic.py +432 -0
  225. autocoder/common/pruner/tools/test_message_ids_pruning_only.py +192 -0
  226. autocoder/common/pull_requests/__init__.py +9 -1
  227. autocoder/common/pull_requests/utils.py +122 -1
  228. autocoder/common/rag_manager/rag_manager.py +36 -40
  229. autocoder/common/rulefiles/__init__.py +53 -1
  230. autocoder/common/rulefiles/api.py +250 -0
  231. autocoder/common/rulefiles/core/__init__.py +14 -0
  232. autocoder/common/rulefiles/core/manager.py +241 -0
  233. autocoder/common/rulefiles/core/selector.py +805 -0
  234. autocoder/common/rulefiles/models/__init__.py +20 -0
  235. autocoder/common/rulefiles/models/index.py +16 -0
  236. autocoder/common/rulefiles/models/init_rule.py +18 -0
  237. autocoder/common/rulefiles/models/rule_file.py +18 -0
  238. autocoder/common/rulefiles/models/rule_relevance.py +14 -0
  239. autocoder/common/rulefiles/models/summary.py +16 -0
  240. autocoder/common/rulefiles/test_rulefiles.py +776 -0
  241. autocoder/common/rulefiles/utils/__init__.py +34 -0
  242. autocoder/common/rulefiles/utils/monitor.py +86 -0
  243. autocoder/common/rulefiles/utils/parser.py +230 -0
  244. autocoder/common/save_formatted_log.py +67 -10
  245. autocoder/common/search_replace.py +8 -1
  246. autocoder/common/search_replace_patch/__init__.py +24 -0
  247. autocoder/common/search_replace_patch/base.py +115 -0
  248. autocoder/common/search_replace_patch/manager.py +248 -0
  249. autocoder/common/search_replace_patch/patch_replacer.py +304 -0
  250. autocoder/common/search_replace_patch/similarity_replacer.py +306 -0
  251. autocoder/common/search_replace_patch/string_replacer.py +181 -0
  252. autocoder/common/search_replace_patch/tests/__init__.py +3 -0
  253. autocoder/common/search_replace_patch/tests/run_tests.py +126 -0
  254. autocoder/common/search_replace_patch/tests/test_base.py +188 -0
  255. autocoder/common/search_replace_patch/tests/test_empty_line_insert.py +233 -0
  256. autocoder/common/search_replace_patch/tests/test_integration.py +389 -0
  257. autocoder/common/search_replace_patch/tests/test_manager.py +351 -0
  258. autocoder/common/search_replace_patch/tests/test_patch_replacer.py +316 -0
  259. autocoder/common/search_replace_patch/tests/test_regex_replacer.py +306 -0
  260. autocoder/common/search_replace_patch/tests/test_similarity_replacer.py +384 -0
  261. autocoder/common/shell_commands/__init__.py +197 -0
  262. autocoder/common/shell_commands/background_process_notifier.py +346 -0
  263. autocoder/common/shell_commands/command_executor.py +1127 -0
  264. autocoder/common/shell_commands/error_recovery.py +541 -0
  265. autocoder/common/shell_commands/exceptions.py +120 -0
  266. autocoder/common/shell_commands/interactive_executor.py +476 -0
  267. autocoder/common/shell_commands/interactive_pexpect_process.py +623 -0
  268. autocoder/common/shell_commands/interactive_process.py +744 -0
  269. autocoder/common/shell_commands/interactive_session_manager.py +1014 -0
  270. autocoder/common/shell_commands/monitoring.py +529 -0
  271. autocoder/common/shell_commands/process_cleanup.py +386 -0
  272. autocoder/common/shell_commands/process_manager.py +606 -0
  273. autocoder/common/shell_commands/test_interactive_pexpect_process.py +281 -0
  274. autocoder/common/shell_commands/tests/__init__.py +6 -0
  275. autocoder/common/shell_commands/tests/conftest.py +118 -0
  276. autocoder/common/shell_commands/tests/test_background_process_notifier.py +703 -0
  277. autocoder/common/shell_commands/tests/test_command_executor.py +448 -0
  278. autocoder/common/shell_commands/tests/test_error_recovery.py +305 -0
  279. autocoder/common/shell_commands/tests/test_exceptions.py +299 -0
  280. autocoder/common/shell_commands/tests/test_execute_batch.py +588 -0
  281. autocoder/common/shell_commands/tests/test_indented_batch_commands.py +244 -0
  282. autocoder/common/shell_commands/tests/test_integration.py +664 -0
  283. autocoder/common/shell_commands/tests/test_monitoring.py +546 -0
  284. autocoder/common/shell_commands/tests/test_performance.py +632 -0
  285. autocoder/common/shell_commands/tests/test_process_cleanup.py +397 -0
  286. autocoder/common/shell_commands/tests/test_process_manager.py +606 -0
  287. autocoder/common/shell_commands/tests/test_timeout_config.py +343 -0
  288. autocoder/common/shell_commands/tests/test_timeout_manager.py +520 -0
  289. autocoder/common/shell_commands/timeout_config.py +315 -0
  290. autocoder/common/shell_commands/timeout_manager.py +352 -0
  291. autocoder/common/terminal_paste/__init__.py +14 -0
  292. autocoder/common/terminal_paste/demo.py +145 -0
  293. autocoder/common/terminal_paste/demo_paste_functionality.py +95 -0
  294. autocoder/common/terminal_paste/paste_handler.py +200 -0
  295. autocoder/common/terminal_paste/paste_manager.py +118 -0
  296. autocoder/common/terminal_paste/tests/__init__.py +1 -0
  297. autocoder/common/terminal_paste/tests/test_paste_handler.py +182 -0
  298. autocoder/common/terminal_paste/tests/test_paste_manager.py +126 -0
  299. autocoder/common/terminal_paste/utils.py +163 -0
  300. autocoder/common/test_autocoder_args.py +232 -0
  301. autocoder/common/test_env_manager.py +173 -0
  302. autocoder/common/test_env_manager_integration.py +159 -0
  303. autocoder/common/text_similarity/__init__.py +9 -0
  304. autocoder/common/text_similarity/demo.py +216 -0
  305. autocoder/common/text_similarity/examples.py +266 -0
  306. autocoder/common/text_similarity/test_text_similarity.py +306 -0
  307. autocoder/common/text_similarity/text_similarity.py +194 -0
  308. autocoder/common/text_similarity/utils.py +125 -0
  309. autocoder/common/todos/__init__.py +61 -0
  310. autocoder/common/todos/cache/__init__.py +16 -0
  311. autocoder/common/todos/cache/base_cache.py +89 -0
  312. autocoder/common/todos/cache/cache_manager.py +228 -0
  313. autocoder/common/todos/cache/memory_cache.py +225 -0
  314. autocoder/common/todos/config.py +155 -0
  315. autocoder/common/todos/exceptions.py +35 -0
  316. autocoder/common/todos/get_todo_manager.py +161 -0
  317. autocoder/common/todos/manager.py +537 -0
  318. autocoder/common/todos/models.py +239 -0
  319. autocoder/common/todos/storage/__init__.py +14 -0
  320. autocoder/common/todos/storage/base_storage.py +76 -0
  321. autocoder/common/todos/storage/file_storage.py +278 -0
  322. autocoder/common/tokens/__init__.py +15 -0
  323. autocoder/common/tokens/counter.py +44 -2
  324. autocoder/common/tools_manager/__init__.py +17 -0
  325. autocoder/common/tools_manager/examples.py +162 -0
  326. autocoder/common/tools_manager/manager.py +385 -0
  327. autocoder/common/tools_manager/models.py +39 -0
  328. autocoder/common/tools_manager/test_tools_manager.py +303 -0
  329. autocoder/common/tools_manager/utils.py +191 -0
  330. autocoder/common/v2/agent/agentic_callbacks.py +270 -0
  331. autocoder/common/v2/agent/agentic_edit.py +2729 -2052
  332. autocoder/common/v2/agent/agentic_edit_change_manager.py +474 -0
  333. autocoder/common/v2/agent/agentic_edit_tools/__init__.py +43 -2
  334. autocoder/common/v2/agent/agentic_edit_tools/ac_mod_list_tool_resolver.py +279 -0
  335. autocoder/common/v2/agent/agentic_edit_tools/ac_mod_read_tool_resolver.py +40 -0
  336. autocoder/common/v2/agent/agentic_edit_tools/ac_mod_write_tool_resolver.py +52 -0
  337. autocoder/common/v2/agent/agentic_edit_tools/ask_followup_question_tool_resolver.py +8 -0
  338. autocoder/common/v2/agent/agentic_edit_tools/background_task_tool_resolver.py +1167 -0
  339. autocoder/common/v2/agent/agentic_edit_tools/base_tool_resolver.py +2 -2
  340. autocoder/common/v2/agent/agentic_edit_tools/conversation_message_ids_read_tool_resolver.py +214 -0
  341. autocoder/common/v2/agent/agentic_edit_tools/conversation_message_ids_write_tool_resolver.py +299 -0
  342. autocoder/common/v2/agent/agentic_edit_tools/count_tokens_tool_resolver.py +290 -0
  343. autocoder/common/v2/agent/agentic_edit_tools/execute_command_tool_resolver.py +565 -30
  344. autocoder/common/v2/agent/agentic_edit_tools/execute_workflow_tool_resolver.py +485 -0
  345. autocoder/common/v2/agent/agentic_edit_tools/extract_to_text_tool_resolver.py +225 -0
  346. autocoder/common/v2/agent/agentic_edit_tools/lint_report.py +79 -0
  347. autocoder/common/v2/agent/agentic_edit_tools/linter_config_models.py +343 -0
  348. autocoder/common/v2/agent/agentic_edit_tools/linter_enabled_tool_resolver.py +189 -0
  349. autocoder/common/v2/agent/agentic_edit_tools/list_files_tool_resolver.py +169 -101
  350. autocoder/common/v2/agent/agentic_edit_tools/load_extra_document_tool_resolver.py +349 -0
  351. autocoder/common/v2/agent/agentic_edit_tools/read_file_tool_resolver.py +244 -51
  352. autocoder/common/v2/agent/agentic_edit_tools/replace_in_file_tool_resolver.py +667 -147
  353. autocoder/common/v2/agent/agentic_edit_tools/run_named_subagents_tool_resolver.py +691 -0
  354. autocoder/common/v2/agent/agentic_edit_tools/search_files_tool_resolver.py +409 -140
  355. autocoder/common/v2/agent/agentic_edit_tools/session_interactive_tool_resolver.py +115 -0
  356. autocoder/common/v2/agent/agentic_edit_tools/session_start_tool_resolver.py +190 -0
  357. autocoder/common/v2/agent/agentic_edit_tools/session_stop_tool_resolver.py +76 -0
  358. autocoder/common/v2/agent/agentic_edit_tools/test_write_to_file_tool_resolver.py +209 -194
  359. autocoder/common/v2/agent/agentic_edit_tools/todo_read_tool_resolver.py +135 -0
  360. autocoder/common/v2/agent/agentic_edit_tools/todo_write_tool_resolver.py +328 -0
  361. autocoder/common/v2/agent/agentic_edit_tools/use_mcp_tool_resolver.py +2 -2
  362. autocoder/common/v2/agent/agentic_edit_tools/web_crawl_tool_resolver.py +557 -0
  363. autocoder/common/v2/agent/agentic_edit_tools/web_search_tool_resolver.py +600 -0
  364. autocoder/common/v2/agent/agentic_edit_tools/write_to_file_tool_resolver.py +56 -121
  365. autocoder/common/v2/agent/agentic_edit_types.py +386 -10
  366. autocoder/common/v2/agent/runner/__init__.py +31 -0
  367. autocoder/common/v2/agent/runner/base_runner.py +92 -0
  368. autocoder/common/v2/agent/runner/file_based_event_runner.py +217 -0
  369. autocoder/common/v2/agent/runner/sdk_runner.py +182 -0
  370. autocoder/common/v2/agent/runner/terminal_runner.py +396 -0
  371. autocoder/common/v2/agent/runner/tool_display.py +589 -0
  372. autocoder/common/v2/agent/test_agentic_callbacks.py +265 -0
  373. autocoder/common/v2/agent/test_agentic_edit.py +194 -0
  374. autocoder/common/v2/agent/tool_caller/__init__.py +24 -0
  375. autocoder/common/v2/agent/tool_caller/default_tool_resolver_map.py +135 -0
  376. autocoder/common/v2/agent/tool_caller/integration_test.py +172 -0
  377. autocoder/common/v2/agent/tool_caller/plugins/__init__.py +14 -0
  378. autocoder/common/v2/agent/tool_caller/plugins/base_plugin.py +126 -0
  379. autocoder/common/v2/agent/tool_caller/plugins/examples/__init__.py +13 -0
  380. autocoder/common/v2/agent/tool_caller/plugins/examples/logging_plugin.py +164 -0
  381. autocoder/common/v2/agent/tool_caller/plugins/examples/security_filter_plugin.py +198 -0
  382. autocoder/common/v2/agent/tool_caller/plugins/plugin_interface.py +141 -0
  383. autocoder/common/v2/agent/tool_caller/test_tool_caller.py +278 -0
  384. autocoder/common/v2/agent/tool_caller/tool_call_plugin_manager.py +331 -0
  385. autocoder/common/v2/agent/tool_caller/tool_caller.py +337 -0
  386. autocoder/common/v2/agent/tool_caller/usage_example.py +193 -0
  387. autocoder/common/v2/code_agentic_editblock_manager.py +4 -4
  388. autocoder/common/v2/code_auto_generate.py +136 -78
  389. autocoder/common/v2/code_auto_generate_diff.py +135 -79
  390. autocoder/common/v2/code_auto_generate_editblock.py +174 -99
  391. autocoder/common/v2/code_auto_generate_strict_diff.py +151 -71
  392. autocoder/common/v2/code_auto_merge.py +1 -1
  393. autocoder/common/v2/code_auto_merge_editblock.py +13 -1
  394. autocoder/common/v2/code_diff_manager.py +3 -3
  395. autocoder/common/v2/code_editblock_manager.py +4 -14
  396. autocoder/common/v2/code_manager.py +1 -1
  397. autocoder/common/v2/code_strict_diff_manager.py +2 -2
  398. autocoder/common/wrap_llm_hint/__init__.py +10 -0
  399. autocoder/common/wrap_llm_hint/test_wrap_llm_hint.py +1067 -0
  400. autocoder/common/wrap_llm_hint/utils.py +432 -0
  401. autocoder/common/wrap_llm_hint/wrap_llm_hint.py +323 -0
  402. autocoder/completer/__init__.py +8 -0
  403. autocoder/completer/command_completer_v2.py +1051 -0
  404. autocoder/default_project/__init__.py +501 -0
  405. autocoder/dispacher/__init__.py +4 -12
  406. autocoder/dispacher/actions/action.py +165 -7
  407. autocoder/dispacher/actions/plugins/action_regex_project.py +2 -2
  408. autocoder/index/entry.py +117 -125
  409. autocoder/{agent → index/filter}/agentic_filter.py +323 -334
  410. autocoder/index/filter/normal_filter.py +5 -11
  411. autocoder/index/filter/quick_filter.py +1 -1
  412. autocoder/index/index.py +36 -9
  413. autocoder/index/tests/__init__.py +1 -0
  414. autocoder/index/tests/run_tests.py +195 -0
  415. autocoder/index/tests/test_entry.py +303 -0
  416. autocoder/index/tests/test_index_manager.py +314 -0
  417. autocoder/index/tests/test_module_integration.py +300 -0
  418. autocoder/index/tests/test_symbols_utils.py +183 -0
  419. autocoder/inner/__init__.py +4 -0
  420. autocoder/inner/agentic.py +932 -0
  421. autocoder/inner/async_command_handler.py +992 -0
  422. autocoder/inner/conversation_command_handlers.py +623 -0
  423. autocoder/inner/merge_command_handler.py +213 -0
  424. autocoder/inner/queue_command_handler.py +684 -0
  425. autocoder/models.py +95 -266
  426. autocoder/plugins/git_helper_plugin.py +31 -29
  427. autocoder/plugins/token_helper_plugin.py +156 -37
  428. autocoder/pyproject/__init__.py +32 -29
  429. autocoder/rag/agentic_rag.py +215 -75
  430. autocoder/rag/cache/simple_cache.py +1 -2
  431. autocoder/rag/loaders/image_loader.py +1 -1
  432. autocoder/rag/long_context_rag.py +42 -26
  433. autocoder/rag/qa_conversation_strategy.py +1 -1
  434. autocoder/rag/terminal/__init__.py +17 -0
  435. autocoder/rag/terminal/args.py +581 -0
  436. autocoder/rag/terminal/bootstrap.py +61 -0
  437. autocoder/rag/terminal/command_handlers.py +653 -0
  438. autocoder/rag/terminal/formatters/__init__.py +20 -0
  439. autocoder/rag/terminal/formatters/base.py +70 -0
  440. autocoder/rag/terminal/formatters/json_format.py +66 -0
  441. autocoder/rag/terminal/formatters/stream_json.py +95 -0
  442. autocoder/rag/terminal/formatters/text.py +28 -0
  443. autocoder/rag/terminal/init.py +120 -0
  444. autocoder/rag/terminal/utils.py +106 -0
  445. autocoder/rag/test_agentic_rag.py +389 -0
  446. autocoder/rag/test_doc_filter.py +3 -3
  447. autocoder/rag/test_long_context_rag.py +1 -1
  448. autocoder/rag/test_token_limiter.py +517 -10
  449. autocoder/rag/token_counter.py +3 -0
  450. autocoder/rag/token_limiter.py +19 -15
  451. autocoder/rag/tools/__init__.py +26 -2
  452. autocoder/rag/tools/bochaai_example.py +343 -0
  453. autocoder/rag/tools/bochaai_sdk.py +541 -0
  454. autocoder/rag/tools/metaso_example.py +268 -0
  455. autocoder/rag/tools/metaso_sdk.py +417 -0
  456. autocoder/rag/tools/recall_tool.py +28 -7
  457. autocoder/rag/tools/run_integration_tests.py +204 -0
  458. autocoder/rag/tools/test_all_providers.py +318 -0
  459. autocoder/rag/tools/test_bochaai_integration.py +482 -0
  460. autocoder/rag/tools/test_final_integration.py +215 -0
  461. autocoder/rag/tools/test_metaso_integration.py +424 -0
  462. autocoder/rag/tools/test_metaso_real.py +171 -0
  463. autocoder/rag/tools/test_web_crawl_tool.py +639 -0
  464. autocoder/rag/tools/test_web_search_tool.py +509 -0
  465. autocoder/rag/tools/todo_read_tool.py +202 -0
  466. autocoder/rag/tools/todo_write_tool.py +412 -0
  467. autocoder/rag/tools/web_crawl_tool.py +634 -0
  468. autocoder/rag/tools/web_search_tool.py +558 -0
  469. autocoder/rag/tools/web_tools_example.py +119 -0
  470. autocoder/rag/types.py +16 -0
  471. autocoder/rag/variable_holder.py +4 -2
  472. autocoder/rags.py +86 -79
  473. autocoder/regexproject/__init__.py +23 -21
  474. autocoder/run_context.py +9 -0
  475. autocoder/sdk/__init__.py +50 -161
  476. autocoder/sdk/api.py +370 -0
  477. autocoder/sdk/async_runner/__init__.py +26 -0
  478. autocoder/sdk/async_runner/async_executor.py +650 -0
  479. autocoder/sdk/async_runner/async_handler.py +356 -0
  480. autocoder/sdk/async_runner/markdown_processor.py +595 -0
  481. autocoder/sdk/async_runner/task_metadata.py +284 -0
  482. autocoder/sdk/async_runner/worktree_manager.py +438 -0
  483. autocoder/sdk/cli/__init__.py +2 -5
  484. autocoder/sdk/cli/formatters.py +28 -204
  485. autocoder/sdk/cli/handlers.py +77 -44
  486. autocoder/sdk/cli/main.py +158 -170
  487. autocoder/sdk/cli/options.py +95 -22
  488. autocoder/sdk/constants.py +139 -51
  489. autocoder/sdk/core/auto_coder_core.py +484 -267
  490. autocoder/sdk/core/bridge.py +298 -118
  491. autocoder/sdk/exceptions.py +18 -12
  492. autocoder/sdk/formatters/__init__.py +19 -0
  493. autocoder/sdk/formatters/input.py +64 -0
  494. autocoder/sdk/formatters/output.py +247 -0
  495. autocoder/sdk/formatters/stream.py +54 -0
  496. autocoder/sdk/models/__init__.py +6 -5
  497. autocoder/sdk/models/options.py +55 -18
  498. autocoder/sdk/utils/formatters.py +27 -195
  499. autocoder/suffixproject/__init__.py +28 -25
  500. autocoder/terminal/__init__.py +14 -0
  501. autocoder/terminal/app.py +454 -0
  502. autocoder/terminal/args.py +32 -0
  503. autocoder/terminal/bootstrap.py +178 -0
  504. autocoder/terminal/command_processor.py +521 -0
  505. autocoder/terminal/command_registry.py +57 -0
  506. autocoder/terminal/help.py +97 -0
  507. autocoder/terminal/tasks/__init__.py +5 -0
  508. autocoder/terminal/tasks/background.py +77 -0
  509. autocoder/terminal/tasks/task_event.py +70 -0
  510. autocoder/terminal/ui/__init__.py +13 -0
  511. autocoder/terminal/ui/completer.py +268 -0
  512. autocoder/terminal/ui/keybindings.py +75 -0
  513. autocoder/terminal/ui/session.py +41 -0
  514. autocoder/terminal/ui/toolbar.py +64 -0
  515. autocoder/terminal/utils/__init__.py +13 -0
  516. autocoder/terminal/utils/errors.py +18 -0
  517. autocoder/terminal/utils/paths.py +19 -0
  518. autocoder/terminal/utils/shell.py +43 -0
  519. autocoder/terminal_v3/__init__.py +10 -0
  520. autocoder/terminal_v3/app.py +201 -0
  521. autocoder/terminal_v3/handlers/__init__.py +5 -0
  522. autocoder/terminal_v3/handlers/command_handler.py +131 -0
  523. autocoder/terminal_v3/models/__init__.py +6 -0
  524. autocoder/terminal_v3/models/conversation_buffer.py +214 -0
  525. autocoder/terminal_v3/models/message.py +50 -0
  526. autocoder/terminal_v3/models/tool_display.py +247 -0
  527. autocoder/terminal_v3/ui/__init__.py +7 -0
  528. autocoder/terminal_v3/ui/keybindings.py +56 -0
  529. autocoder/terminal_v3/ui/layout.py +141 -0
  530. autocoder/terminal_v3/ui/styles.py +43 -0
  531. autocoder/tsproject/__init__.py +23 -23
  532. autocoder/utils/auto_coder_utils/chat_stream_out.py +1 -1
  533. autocoder/utils/llms.py +88 -80
  534. autocoder/utils/math_utils.py +101 -0
  535. autocoder/utils/model_provider_selector.py +16 -4
  536. autocoder/utils/operate_config_api.py +33 -5
  537. autocoder/utils/thread_utils.py +2 -2
  538. autocoder/version.py +4 -2
  539. autocoder/workflow_agents/__init__.py +84 -0
  540. autocoder/workflow_agents/agent.py +143 -0
  541. autocoder/workflow_agents/exceptions.py +573 -0
  542. autocoder/workflow_agents/executor.py +489 -0
  543. autocoder/workflow_agents/loader.py +737 -0
  544. autocoder/workflow_agents/runner.py +267 -0
  545. autocoder/workflow_agents/types.py +172 -0
  546. autocoder/workflow_agents/utils.py +434 -0
  547. autocoder/workflow_agents/workflow_manager.py +211 -0
  548. auto_coder-0.1.400.dist-info/METADATA +0 -396
  549. auto_coder-0.1.400.dist-info/RECORD +0 -425
  550. auto_coder-0.1.400.dist-info/licenses/LICENSE +0 -201
  551. autocoder/auto_coder_server.py +0 -672
  552. autocoder/benchmark.py +0 -138
  553. autocoder/common/ac_style_command_parser/example.py +0 -7
  554. autocoder/common/cleaner.py +0 -31
  555. autocoder/common/command_completer_v2.py +0 -615
  556. autocoder/common/directory_cache/__init__.py +0 -1
  557. autocoder/common/directory_cache/cache.py +0 -192
  558. autocoder/common/directory_cache/test_cache.py +0 -190
  559. autocoder/common/file_checkpoint/examples.py +0 -217
  560. autocoder/common/llm_friendly_package_example.py +0 -138
  561. autocoder/common/llm_friendly_package_test.py +0 -63
  562. autocoder/common/pull_requests/test_module.py +0 -1
  563. autocoder/common/rulefiles/autocoderrules_utils.py +0 -484
  564. autocoder/common/text.py +0 -30
  565. autocoder/common/v2/agent/agentic_edit_tools/list_package_info_tool_resolver.py +0 -42
  566. autocoder/common/v2/agent/agentic_edit_tools/test_execute_command_tool_resolver.py +0 -70
  567. autocoder/common/v2/agent/agentic_edit_tools/test_search_files_tool_resolver.py +0 -163
  568. autocoder/common/v2/agent/agentic_tool_display.py +0 -183
  569. autocoder/plugins/dynamic_completion_example.py +0 -148
  570. autocoder/plugins/sample_plugin.py +0 -160
  571. autocoder/sdk/cli/__main__.py +0 -26
  572. autocoder/sdk/cli/completion_wrapper.py +0 -38
  573. autocoder/sdk/cli/install_completion.py +0 -301
  574. autocoder/sdk/models/messages.py +0 -209
  575. autocoder/sdk/session/__init__.py +0 -32
  576. autocoder/sdk/session/session.py +0 -106
  577. autocoder/sdk/session/session_manager.py +0 -56
  578. {auto_coder-0.1.400.dist-info → auto_coder-2.0.0.dist-info}/top_level.txt +0 -0
  579. /autocoder/{sdk/example.py → common/agent_query_queue/__init__.py} +0 -0
@@ -0,0 +1,189 @@
1
+ """
2
+ Linter-enabled tool resolver that extends BaseToolResolver with linting capabilities.
3
+ """
4
+
5
+ from typing import Optional, List
6
+ from autocoder.common.v2.agent.agentic_edit_types import BaseTool, ToolResult
7
+ from autocoder.common.v2.agent.agentic_edit_tools.base_tool_resolver import BaseToolResolver
8
+ from autocoder.common.v2.agent.agentic_edit_tools.linter_config_models import LinterConfig
9
+ from autocoder.common import AutoCoderArgs
10
+ from autocoder.common.linter_core.config_loader import load_linter_config
11
+ import typing
12
+ import os
13
+ import json
14
+ from loguru import logger
15
+
16
+ if typing.TYPE_CHECKING:
17
+ from autocoder.common.v2.agent.agentic_edit import AgenticEdit
18
+ from autocoder.common.linter_core.linter_manager import LinterManager
19
+ from autocoder.common.v2.agent.agentic_edit_tools.lint_report import LintReport
20
+
21
+
22
+ class LinterEnabledToolResolver(BaseToolResolver):
23
+ """
24
+ Tool resolver with integrated linter support.
25
+
26
+ This class extends BaseToolResolver to provide linting capabilities
27
+ for tools that modify files.
28
+ """
29
+
30
+ def __init__(self, agent: Optional['AgenticEdit'], tool: BaseTool, args: AutoCoderArgs):
31
+ """
32
+ Initializes the resolver with linter support.
33
+
34
+ Args:
35
+ agent: The AutoCoder agent instance.
36
+ tool: The Pydantic model instance representing the tool call.
37
+ args: Additional arguments needed for execution (e.g., source_dir).
38
+ """
39
+ super().__init__(agent, tool, args)
40
+
41
+ # Initialize linter
42
+ self.linter_manager: Optional['LinterManager'] = None
43
+ self.linter_config: Optional[LinterConfig] = None
44
+ self._init_linter()
45
+
46
+ def _init_linter(self):
47
+ """初始化 Linter 管理器"""
48
+ try:
49
+ # Load and validate linter configuration using the centralized loader
50
+ source_dir = getattr(self.args, 'source_dir', None)
51
+ linter_config_path = getattr(self.args, 'linter_config_path', None)
52
+
53
+ raw_config = load_linter_config(
54
+ config_path=linter_config_path,
55
+ source_dir=source_dir
56
+ )
57
+
58
+ self.linter_config = LinterConfig.from_dict(raw_config)
59
+
60
+ # Check if linter is enabled
61
+ if not self.linter_config.enabled:
62
+ logger.debug("Linter is disabled in configuration")
63
+ return
64
+
65
+ # Import and initialize LinterManager
66
+ from autocoder.common.linter_core.linter_manager import LinterManager
67
+
68
+ # Convert to manager-compatible config
69
+ manager_config = self.linter_config.to_manager_config()
70
+
71
+ self.linter_manager = LinterManager(manager_config, source_dir=source_dir)
72
+ logger.info("Linter manager initialized successfully with validated configuration")
73
+
74
+ except ImportError as e:
75
+ logger.warning(f"Linter module not available: {e}")
76
+ except ValueError as e:
77
+ logger.error(f"Invalid linter configuration: {e}")
78
+ # Use default disabled config on validation error
79
+ self.linter_config = LinterConfig(enabled=False)
80
+ except Exception as e:
81
+ logger.error(f"Failed to initialize linter: {e}")
82
+ # Use default disabled config on error
83
+ self.linter_config = LinterConfig(enabled=False)
84
+
85
+
86
+ def should_lint(self, file_path: str) -> bool:
87
+ """判断文件是否需要 lint 检查"""
88
+ if not self.linter_manager or not self.linter_config:
89
+ return False
90
+
91
+ # Use the Pydantic model's method
92
+ should_lint = self.linter_config.should_lint_file(file_path)
93
+
94
+ if not should_lint:
95
+ logger.debug(f"File {file_path} excluded from linting")
96
+
97
+ return should_lint
98
+
99
+ def lint_files(self, file_paths: List[str]) -> Optional['LintReport']:
100
+ """对文件运行 linter 检查"""
101
+ if not self.linter_manager:
102
+ return None
103
+
104
+ try:
105
+ from autocoder.common.v2.agent.agentic_edit_tools.lint_report import LintReport
106
+
107
+ # Convert relative paths to absolute paths
108
+ abs_file_paths = []
109
+ source_dir = self.args.source_dir or "."
110
+ for file_path in file_paths:
111
+ if not os.path.isabs(file_path):
112
+ abs_path = os.path.abspath(os.path.join(source_dir, file_path))
113
+ else:
114
+ abs_path = file_path
115
+ abs_file_paths.append(abs_path)
116
+
117
+ # Run linter
118
+ results = self.linter_manager.lint_files(abs_file_paths, parallel=False)
119
+
120
+ # Create report
121
+ report = LintReport.from_linter_results(results, self.linter_manager)
122
+
123
+ return report
124
+
125
+ except Exception as e:
126
+ logger.error(f"Error running linter: {e}")
127
+ return None
128
+
129
+ def handle_lint_results(self, original_result: ToolResult, lint_report: Optional['LintReport']) -> ToolResult:
130
+ """处理 lint 结果并更新 ToolResult"""
131
+ if not lint_report or not self.linter_config:
132
+ return original_result
133
+
134
+ # Get configuration from Pydantic model
135
+ mode = self.linter_config.mode
136
+ report_format = self.linter_config.report.format
137
+ include_in_result = self.linter_config.report.include_in_result
138
+
139
+ # Generate report text based on format
140
+ if report_format == 'detailed':
141
+ report_text = lint_report.to_markdown()
142
+ elif report_format == 'json':
143
+ report_text = json.dumps(lint_report.to_json(), indent=2)
144
+ else: # simple
145
+ report_text = lint_report.to_simple_text()
146
+
147
+ # Handle based on mode
148
+ if mode == 'blocking' and lint_report.has_issues():
149
+ # Blocking mode - fail the operation
150
+ return ToolResult(
151
+ success=False,
152
+ message=f"Operation blocked due to lint issues:\n{report_text}",
153
+ content={'lint_report': lint_report.to_json()} if include_in_result else None
154
+ )
155
+ elif mode == 'silent':
156
+ # Silent mode - don't modify the result
157
+ if include_in_result and original_result.content:
158
+ if isinstance(original_result.content, dict):
159
+ original_result.content['lint_report'] = lint_report.to_json()
160
+ return original_result
161
+ else: # warning mode (default)
162
+ # Warning mode - append lint results to message
163
+ if lint_report.has_issues():
164
+ new_message = f"{original_result.message}\n\n{report_text}"
165
+ else:
166
+ new_message = f"{original_result.message}\n✅ Lint check passed - No issues found"
167
+
168
+ # Create new result with updated message and content
169
+ new_content = original_result.content or {}
170
+ if include_in_result:
171
+ if isinstance(new_content, dict):
172
+ new_content['lint_report'] = lint_report.to_json()
173
+ else:
174
+ new_content = {'lint_report': lint_report.to_json()}
175
+
176
+ return ToolResult(
177
+ success=original_result.success,
178
+ message=new_message,
179
+ content=new_content if new_content else None
180
+ )
181
+
182
+ def resolve(self) -> ToolResult:
183
+ """
184
+ Must be implemented by subclasses.
185
+
186
+ Returns:
187
+ A ToolResult object indicating success or failure and a message.
188
+ """
189
+ raise NotImplementedError("Subclasses must implement the resolve method")
@@ -1,5 +1,7 @@
1
1
  import os
2
2
  from typing import Dict, Any, Optional, List, Set, Union
3
+
4
+ from pydantic import BaseModel, Field
3
5
  from autocoder.common.v2.agent.agentic_edit_tools.base_tool_resolver import BaseToolResolver
4
6
  from autocoder.common.v2.agent.agentic_edit_types import ListFilesTool, ToolResult # Import ToolResult from types
5
7
  from loguru import logger
@@ -12,97 +14,148 @@ if typing.TYPE_CHECKING:
12
14
  from autocoder.common.v2.agent.agentic_edit import AgenticEdit
13
15
 
14
16
 
17
+ class ListErrorInfo(BaseModel):
18
+ """Information about errors encountered during list operations."""
19
+ file_path: str = Field(..., description="Path to the file/directory that caused the error")
20
+ error_type: str = Field(..., description="Type of error (e.g., 'PermissionError', 'FileNotFoundError')")
21
+ error_message: str = Field(..., description="Detailed error message")
22
+
23
+ class Config:
24
+ """Pydantic configuration."""
25
+ frozen = True
26
+ extra = "forbid"
27
+
28
+
29
+ class ListResultContent(BaseModel):
30
+ """Content structure for list operation results."""
31
+ files: List[str] = Field(..., description="List of files and directories found")
32
+ errors: List[ListErrorInfo] = Field(..., description="List of errors encountered during listing")
33
+
34
+ class Config:
35
+ """Pydantic configuration."""
36
+ frozen = True
37
+ extra = "forbid"
38
+
39
+
15
40
  class ListFilesToolResolver(BaseToolResolver):
16
41
  def __init__(self, agent: Optional['AgenticEdit'], tool: ListFilesTool, args: AutoCoderArgs):
17
42
  super().__init__(agent, tool, args)
18
43
  self.tool: ListFilesTool = tool # For type hinting
19
- self.shadow_manager = self.agent.shadow_manager
20
44
 
21
- def list_files_in_dir(self, base_dir: str, recursive: bool, source_dir: str, is_outside_source: bool) -> Set[str]:
22
- """Helper function to list files in a directory"""
45
+ def list_files_in_dir(self, base_dir: str, recursive: bool, source_dir: str, is_outside_source: bool) -> tuple[Set[str], List[ListErrorInfo]]:
46
+ """Helper function to list files in a directory with error collection.
47
+
48
+ Returns:
49
+ Tuple of (file set, error information list)
50
+ """
23
51
  result = set()
52
+ errors = []
53
+
24
54
  try:
25
55
  if recursive:
26
56
  for root, dirs, files in os.walk(base_dir):
27
- # Modify dirs in-place to skip ignored dirs early
28
- dirs[:] = [d for d in dirs if not should_ignore(os.path.join(root, d))]
29
- for name in files:
30
- full_path = os.path.join(root, name)
57
+ try:
58
+ # Modify dirs in-place to skip ignored dirs early
59
+ accessible_dirs = []
60
+ for d in dirs:
61
+ dir_path = os.path.join(root, d)
62
+ if should_ignore(dir_path):
63
+ continue
64
+ try:
65
+ # Test if we can access the directory
66
+ os.listdir(dir_path)
67
+ accessible_dirs.append(d)
68
+ except (PermissionError, OSError) as e:
69
+ error_info = ListErrorInfo(
70
+ file_path=dir_path,
71
+ error_type=type(e).__name__,
72
+ error_message=f"Cannot access directory: {str(e)}"
73
+ )
74
+ errors.append(error_info)
75
+ logger.warning(f"Cannot access directory {dir_path}: {e}")
76
+ dirs[:] = accessible_dirs
77
+
78
+ # Process files in current directory
79
+ for name in files:
80
+ full_path = os.path.join(root, name)
81
+ if should_ignore(full_path):
82
+ continue
83
+ try:
84
+ # Test if we can access the file
85
+ os.stat(full_path)
86
+ display_path = os.path.relpath(full_path, source_dir) if not is_outside_source else full_path
87
+ result.add(display_path)
88
+ except (PermissionError, OSError) as e:
89
+ error_info = ListErrorInfo(
90
+ file_path=full_path,
91
+ error_type=type(e).__name__,
92
+ error_message=f"Cannot access file: {str(e)}"
93
+ )
94
+ errors.append(error_info)
95
+ logger.warning(f"Cannot access file {full_path}: {e}")
96
+
97
+ # Add accessible directories to result
98
+ for d in dirs:
99
+ full_path = os.path.join(root, d)
100
+ display_path = os.path.relpath(full_path, source_dir) if not is_outside_source else full_path
101
+ result.add(display_path + "/")
102
+
103
+ except (PermissionError, OSError) as e:
104
+ error_info = ListErrorInfo(
105
+ file_path=root,
106
+ error_type=type(e).__name__,
107
+ error_message=f"Cannot access directory during walk: {str(e)}"
108
+ )
109
+ errors.append(error_info)
110
+ logger.warning(f"Cannot access directory {root} during walk: {e}")
111
+ break # Stop walking this branch
112
+ else:
113
+ try:
114
+ items = os.listdir(base_dir)
115
+ for item in items:
116
+ full_path = os.path.join(base_dir, item)
31
117
  if should_ignore(full_path):
32
118
  continue
33
- display_path = os.path.relpath(full_path, source_dir) if not is_outside_source else full_path
34
- result.add(display_path)
35
- for d in dirs:
36
- full_path = os.path.join(root, d)
37
- display_path = os.path.relpath(full_path, source_dir) if not is_outside_source else full_path
38
- result.add(display_path + "/")
39
- else:
40
- for item in os.listdir(base_dir):
41
- full_path = os.path.join(base_dir, item)
42
- if should_ignore(full_path):
43
- continue
44
- display_path = os.path.relpath(full_path, source_dir) if not is_outside_source else full_path
45
- if os.path.isdir(full_path):
46
- result.add(display_path + "/")
47
- else:
48
- result.add(display_path)
119
+ try:
120
+ display_path = os.path.relpath(full_path, source_dir) if not is_outside_source else full_path
121
+ if os.path.isdir(full_path):
122
+ result.add(display_path + "/")
123
+ else:
124
+ result.add(display_path)
125
+ except (PermissionError, OSError) as e:
126
+ error_info = ListErrorInfo(
127
+ file_path=full_path,
128
+ error_type=type(e).__name__,
129
+ error_message=f"Cannot access item: {str(e)}"
130
+ )
131
+ errors.append(error_info)
132
+ logger.warning(f"Cannot access item {full_path}: {e}")
133
+ except (PermissionError, OSError) as e:
134
+ error_info = ListErrorInfo(
135
+ file_path=base_dir,
136
+ error_type=type(e).__name__,
137
+ error_message=f"Cannot list directory: {str(e)}"
138
+ )
139
+ errors.append(error_info)
140
+ logger.warning(f"Cannot list directory {base_dir}: {e}")
49
141
  except Exception as e:
50
- logger.warning(f"Error listing files in {base_dir}: {e}")
51
- return result
52
-
53
- def list_files_with_shadow(self, list_path_str: str, recursive: bool, source_dir: str, absolute_source_dir: str, absolute_list_path: str) -> Union[ToolResult, List[str]]:
54
- """List files using shadow manager for path translation"""
55
- # Security check: Allow listing outside source_dir IF the original path is outside?
56
- is_outside_source = not absolute_list_path.startswith(absolute_source_dir)
57
- if is_outside_source:
58
- logger.warning(f"Listing path is outside the project source directory: {list_path_str}")
59
-
60
- # Check if shadow directory exists for this path
61
- shadow_exists = False
62
- shadow_dir_path = None
63
- if self.shadow_manager:
64
- try:
65
- shadow_dir_path = self.shadow_manager.to_shadow_path(absolute_list_path)
66
- if os.path.exists(shadow_dir_path) and os.path.isdir(shadow_dir_path):
67
- shadow_exists = True
68
- except Exception as e:
69
- logger.warning(f"Error checking shadow path for {absolute_list_path}: {e}")
70
-
71
- # Validate that at least one of the directories exists
72
- if not os.path.exists(absolute_list_path) and not shadow_exists:
73
- return ToolResult(success=False, message=f"Error: Path not found: {list_path_str}")
74
- if os.path.exists(absolute_list_path) and not os.path.isdir(absolute_list_path):
75
- return ToolResult(success=False, message=f"Error: Path is not a directory: {list_path_str}")
76
- if shadow_exists and not os.path.isdir(shadow_dir_path):
77
- return ToolResult(success=False, message=f"Error: Shadow path is not a directory: {shadow_dir_path}")
78
-
79
- # Collect files from shadow and/or source directory
80
- shadow_files_set = set()
81
- if shadow_exists:
82
- shadow_files_set = self.list_files_in_dir(shadow_dir_path, recursive, source_dir, is_outside_source)
83
-
84
- source_files_set = set()
85
- if os.path.exists(absolute_list_path) and os.path.isdir(absolute_list_path):
86
- source_files_set = self.list_files_in_dir(absolute_list_path, recursive, source_dir, is_outside_source)
87
-
88
- # Merge results, prioritizing shadow files if exist
89
- if shadow_exists:
90
- merged_files = shadow_files_set.union(
91
- {f for f in source_files_set if f not in shadow_files_set}
142
+ error_info = ListErrorInfo(
143
+ file_path=base_dir,
144
+ error_type=type(e).__name__,
145
+ error_message=f"Unexpected error: {str(e)}"
92
146
  )
93
- else:
94
- merged_files = source_files_set
95
-
96
- try:
97
- message = f"Successfully listed contents of '{list_path_str}' (Recursive: {recursive}). Found {len(merged_files)} items."
98
- logger.info(message)
99
- return sorted(merged_files)
100
- except Exception as e:
101
- logger.error(f"Error listing files in '{list_path_str}': {str(e)}")
102
- return ToolResult(success=False, message=f"An unexpected error occurred while listing files: {str(e)}")
147
+ errors.append(error_info)
148
+ logger.warning(f"Unexpected error listing files in {base_dir}: {e}")
149
+
150
+ return result, errors
151
+
103
152
 
104
- def list_files_normal(self, list_path_str: str, recursive: bool, source_dir: str, absolute_source_dir: str, absolute_list_path: str) -> Union[ToolResult, List[str]]:
105
- """List files directly without using shadow manager"""
153
+ def list_files_normal(self, list_path_str: str, recursive: bool, source_dir: str, absolute_source_dir: str, absolute_list_path: str) -> Union[ToolResult, tuple[List[str], List[ListErrorInfo]]]:
154
+ """List files directly without using shadow manager with error collection.
155
+
156
+ Returns:
157
+ ToolResult on error, or tuple of (file list, error information) on success
158
+ """
106
159
  # Security check: Allow listing outside source_dir IF the original path is outside?
107
160
  is_outside_source = not absolute_list_path.startswith(absolute_source_dir)
108
161
  if is_outside_source:
@@ -115,14 +168,13 @@ class ListFilesToolResolver(BaseToolResolver):
115
168
  return ToolResult(success=False, message=f"Error: Path is not a directory: {list_path_str}")
116
169
 
117
170
  # Collect files from the directory
118
- files_set = self.list_files_in_dir(absolute_list_path, recursive, source_dir, is_outside_source)
171
+ files_set, errors = self.list_files_in_dir(absolute_list_path, recursive, source_dir, is_outside_source)
119
172
 
120
173
  try:
121
- message = f"Successfully listed contents of '{list_path_str}' (Recursive: {recursive}). Found {len(files_set)} items."
122
- logger.info(message)
123
- return sorted(files_set)
174
+ sorted_files = sorted(files_set)
175
+ return sorted_files, errors
124
176
  except Exception as e:
125
- logger.error(f"Error listing files in '{list_path_str}': {str(e)}")
177
+ logger.error(f"Error sorting files in '{list_path_str}': {str(e)}")
126
178
  return ToolResult(success=False, message=f"An unexpected error occurred while listing files: {str(e)}")
127
179
 
128
180
  def resolve(self) -> ToolResult:
@@ -133,23 +185,39 @@ class ListFilesToolResolver(BaseToolResolver):
133
185
  absolute_source_dir = os.path.abspath(source_dir)
134
186
  absolute_list_path = os.path.abspath(os.path.join(source_dir, list_path_str))
135
187
 
136
- # Choose the appropriate implementation based on whether shadow_manager is available
137
- if self.shadow_manager:
138
- result = self.list_files_with_shadow(list_path_str, recursive, source_dir, absolute_source_dir, absolute_list_path)
139
- else:
140
- result = self.list_files_normal(list_path_str, recursive, source_dir, absolute_source_dir, absolute_list_path)
141
-
142
- # Handle the case where the implementation returns a sorted list instead of a ToolResult
143
- if isinstance(result, list):
144
- total_items = len(result)
145
- # Limit results to 200 if needed
146
- if total_items > 200:
147
- truncated_result = result[:200]
148
- message = f"Successfully listed contents of '{list_path_str}' (Recursive: {recursive}). Found {total_items} items, showing only the first 200."
149
- logger.info(message)
150
- return ToolResult(success=True, message=message, content=truncated_result)
151
- else:
152
- message = f"Successfully listed contents of '{list_path_str}' (Recursive: {recursive}). Found {total_items} items."
153
- return ToolResult(success=True, message=message, content=result)
154
- else:
188
+ # Use the normal implementation since shadow_manager is no longer available
189
+ result = self.list_files_normal(list_path_str, recursive, source_dir, absolute_source_dir, absolute_list_path)
190
+
191
+ # Handle the case where the implementation returns a ToolResult (error case)
192
+ if isinstance(result, ToolResult):
155
193
  return result
194
+
195
+ # Handle successful results (tuple of files and errors)
196
+ files_list, errors = result
197
+ total_items = len(files_list)
198
+ total_errors = len(errors)
199
+
200
+ # Prepare error summary for message
201
+ error_summary = ""
202
+ if total_errors > 0:
203
+ error_types = {}
204
+ for error in errors:
205
+ error_types[error.error_type] = error_types.get(error.error_type, 0) + 1
206
+ error_summary = f" Encountered {total_errors} errors: " + ", ".join([f"{count} {error_type}" for error_type, count in error_types.items()])
207
+
208
+ # Prepare content with both results and errors using Pydantic model
209
+ truncated_files = files_list[:200] if total_items > 200 else files_list
210
+ content_model = ListResultContent(
211
+ files=truncated_files,
212
+ errors=errors
213
+ )
214
+ content = content_model.model_dump()
215
+
216
+ # Limit results to 200 if needed
217
+ if total_items > 200:
218
+ message = f"Successfully listed contents of '{list_path_str}' (Recursive: {recursive}). Found {total_items} items, showing only the first 200.{error_summary}"
219
+ logger.info(message)
220
+ return ToolResult(success=True, message=message, content=content)
221
+ else:
222
+ message = f"Successfully listed contents of '{list_path_str}' (Recursive: {recursive}). Found {total_items} items.{error_summary}"
223
+ return ToolResult(success=True, message=message, content=content)