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,61 @@
1
+ """
2
+ Simple base class for language-specific linters.
3
+ """
4
+
5
+ from abc import ABC, abstractmethod
6
+ from typing import List, Optional, Dict, Any, Union
7
+ from pathlib import Path
8
+
9
+ from .models.lint_result import LintResult
10
+
11
+
12
+ class BaseLinter(ABC):
13
+ """Base class for all language linters."""
14
+
15
+ def __init__(self, config: Optional[Dict[str, Any]] = None):
16
+ """Initialize with optional configuration."""
17
+ self.config = config or {}
18
+
19
+ @property
20
+ def name(self) -> str:
21
+ """Name of the linter."""
22
+ return self.__class__.__name__
23
+
24
+ @property
25
+ @abstractmethod
26
+ def supported_extensions(self) -> List[str]:
27
+ """Supported file extensions (e.g., ['.py', '.pyi'])."""
28
+ pass
29
+
30
+ @property
31
+ @abstractmethod
32
+ def language_name(self) -> str:
33
+ """Human-readable language name."""
34
+ pass
35
+
36
+ @abstractmethod
37
+ def is_available(self) -> bool:
38
+ """Check if the linter tools are available."""
39
+ pass
40
+
41
+ @abstractmethod
42
+ def lint_file(self, file_path: Union[str, Path]) -> LintResult:
43
+ """
44
+ Lint a single file and return the result.
45
+
46
+ Args:
47
+ file_path: Path to the file to lint
48
+
49
+ Returns:
50
+ LintResult with the linting output
51
+ """
52
+ pass
53
+
54
+ def can_lint_file(self, file_path: Union[str, Path]) -> bool:
55
+ """Check if this linter can handle the given file."""
56
+ path = Path(file_path)
57
+ return path.suffix.lower() in self.supported_extensions
58
+
59
+ def get_config_value(self, key: str, default: Any = None) -> Any:
60
+ """Get a configuration value."""
61
+ return self.config.get(key, default)
@@ -0,0 +1,271 @@
1
+ """
2
+ Centralized configuration loader for the linter core module.
3
+
4
+ This module provides comprehensive configuration loading from multiple sources
5
+ with proper priority handling and format support.
6
+ """
7
+
8
+ import os
9
+ import json
10
+ from typing import Dict, Any, Optional, List
11
+ from pathlib import Path
12
+ from loguru import logger
13
+
14
+
15
+ class LinterConfigLoader:
16
+ """
17
+ Centralized configuration loader for linter configurations.
18
+
19
+ Loads configuration from multiple sources in priority order:
20
+ 1. Explicit config path (if provided)
21
+ 2. Environment variable AUTOCODER_LINTER_CONFIG
22
+ 3. Project config file (.autocoderlinters/)
23
+ 4. Global user config file (~/.auto-coder/.autocoderlinters/)
24
+ 5. Default configuration
25
+ """
26
+
27
+ DEFAULT_CONFIG = {
28
+ 'enabled': False, # Disabled by default for safety
29
+ 'mode': 'warning',
30
+ 'check_after_modification': True,
31
+ 'report': {
32
+ 'format': 'simple',
33
+ 'include_in_result': True
34
+ }
35
+ }
36
+
37
+ def __init__(self, source_dir: Optional[str] = None):
38
+ """
39
+ Initialize the config loader.
40
+
41
+ Args:
42
+ source_dir: Base directory for relative path resolution
43
+ """
44
+ self.source_dir = source_dir or "."
45
+
46
+ def load_config(self,
47
+ config_path: Optional[str] = None,
48
+ config_key: str = 'linter') -> Dict[str, Any]:
49
+ """
50
+ Load configuration from multiple sources in priority order.
51
+
52
+ Args:
53
+ config_path: Explicit path to configuration file
54
+ config_key: Key to extract from configuration files (for nested configs)
55
+
56
+ Returns:
57
+ Dictionary containing the loaded configuration
58
+ """
59
+ # 1. Check explicit config path
60
+ if config_path:
61
+ config = self._load_from_file(config_path, config_key)
62
+ if config is not None:
63
+ logger.info(f"Loaded linter config from explicit path: {config_path}")
64
+ return config
65
+
66
+ # 2. Check environment variable
67
+ config = self._load_from_environment()
68
+ if config is not None:
69
+ return config
70
+
71
+ # 3. Check project config file
72
+ config = self._load_from_project_config(config_key)
73
+ if config is not None:
74
+ return config
75
+
76
+ # 4. Check global user config file
77
+ config = self._load_from_global_config(config_key)
78
+ if config is not None:
79
+ return config
80
+
81
+ # 5. Return default configuration
82
+ logger.debug("Using default linter configuration")
83
+ return self.DEFAULT_CONFIG.copy()
84
+
85
+ def _load_from_file(self, file_path: str, config_key: str = 'linter') -> Optional[Dict[str, Any]]:
86
+ """Load configuration from a specific file."""
87
+ try:
88
+ path = Path(file_path)
89
+ if not path.exists():
90
+ logger.debug(f"Config file not found: {file_path}")
91
+ return None
92
+
93
+ with open(path, 'r', encoding='utf-8') as f:
94
+ if path.suffix.lower() == '.json':
95
+ data = json.load(f)
96
+ else:
97
+ # Try YAML if available
98
+ try:
99
+ import yaml
100
+ data = yaml.safe_load(f)
101
+ except ImportError:
102
+ logger.warning(f"YAML support not available, treating {file_path} as JSON")
103
+ f.seek(0) # Reset file pointer
104
+ data = json.load(f)
105
+
106
+ # Extract the specified section if present, otherwise use the whole config
107
+ config = data.get(config_key, data) if isinstance(data, dict) else data
108
+
109
+ logger.info(f"Successfully loaded config from: {file_path}")
110
+ return config
111
+
112
+ except Exception as e:
113
+ logger.error(f"Failed to load config from {file_path}: {e}")
114
+ return None
115
+
116
+ def _load_from_environment(self) -> Optional[Dict[str, Any]]:
117
+ """Load configuration from environment variable."""
118
+ env_config = os.environ.get('AUTOCODER_LINTER_CONFIG')
119
+ if not env_config:
120
+ return None
121
+
122
+ try:
123
+ config = json.loads(env_config)
124
+ logger.info("Loaded linter config from environment variable")
125
+ return config
126
+ except json.JSONDecodeError as e:
127
+ logger.error(f"Failed to parse AUTOCODER_LINTER_CONFIG: {e}")
128
+ return None
129
+
130
+ def _load_from_project_config(self, config_key: str = 'linter') -> Optional[Dict[str, Any]]:
131
+ """Load configuration from project config directory."""
132
+ project_config_dir = Path(self.source_dir) / '.autocoderlinters'
133
+
134
+ # Try different config file formats in order of preference
135
+ config_files = [
136
+ project_config_dir / 'config.json',
137
+ project_config_dir / 'config.yaml',
138
+ project_config_dir / 'config.yml',
139
+ project_config_dir / 'linter.json',
140
+ project_config_dir / 'linter.yaml',
141
+ project_config_dir / 'linter.yml',
142
+ ]
143
+
144
+ for config_file in config_files:
145
+ if config_file.exists():
146
+ config = self._load_from_file(str(config_file), config_key)
147
+ if config is not None:
148
+ logger.info(f"Loaded linter config from project: {config_file}")
149
+ return config
150
+
151
+ logger.debug(f"No project config found in: {project_config_dir}")
152
+ return None
153
+
154
+ def _load_from_global_config(self, config_key: str = 'linter') -> Optional[Dict[str, Any]]:
155
+ """Load configuration from global user config directory."""
156
+ try:
157
+ # Use os.path.expanduser to handle ~ on all platforms
158
+ global_config_dir = Path(os.path.expanduser('~')) / '.auto-coder' / '.autocoderlinters'
159
+
160
+ # Try different config file formats in order of preference
161
+ config_files = [
162
+ global_config_dir / 'config.json',
163
+ global_config_dir / 'config.yaml',
164
+ global_config_dir / 'config.yml',
165
+ global_config_dir / 'linter.json',
166
+ global_config_dir / 'linter.yaml',
167
+ global_config_dir / 'linter.yml',
168
+ ]
169
+
170
+ for config_file in config_files:
171
+ if config_file.exists():
172
+ config = self._load_from_file(str(config_file), config_key)
173
+ if config is not None:
174
+ logger.info(f"Loaded linter config from global user config: {config_file}")
175
+ return config
176
+
177
+ except Exception as e:
178
+ logger.debug(f"Error checking global user config: {e}")
179
+
180
+ logger.debug("No global user config found")
181
+ return None
182
+
183
+ def validate_config(self, config: Dict[str, Any]) -> Dict[str, Any]:
184
+ """
185
+ Validate and normalize configuration.
186
+
187
+ Args:
188
+ config: Raw configuration dictionary
189
+
190
+ Returns:
191
+ Validated and normalized configuration
192
+ """
193
+ # Ensure all required keys exist with defaults
194
+ validated = self.DEFAULT_CONFIG.copy()
195
+
196
+ if isinstance(config, dict):
197
+ # Update with provided config
198
+ validated.update(config)
199
+
200
+ # Validate specific fields
201
+ if 'mode' in config and config['mode'] not in ['blocking', 'warning', 'silent']:
202
+ logger.warning(f"Invalid linter mode '{config['mode']}', using 'warning'")
203
+ validated['mode'] = 'warning'
204
+
205
+ if 'report' in config and isinstance(config['report'], dict):
206
+ report_config = validated['report']
207
+ report_config.update(config['report'])
208
+
209
+ if 'format' in config['report'] and config['report']['format'] not in ['simple', 'detailed', 'json']:
210
+ logger.warning(f"Invalid report format '{config['report']['format']}', using 'simple'")
211
+ report_config['format'] = 'simple'
212
+
213
+ return validated
214
+
215
+ @classmethod
216
+ def load_manager_config(cls, config_path: Optional[str] = None,
217
+ source_dir: Optional[str] = None) -> Dict[str, Any]:
218
+ """
219
+ Load configuration specifically for LinterManager.
220
+
221
+ This is a convenience method that loads the full configuration
222
+ (not just the linter section) for use by LinterManager.
223
+
224
+ Args:
225
+ config_path: Explicit path to configuration file
226
+ source_dir: Base directory for relative path resolution
227
+
228
+ Returns:
229
+ Full configuration dictionary for LinterManager
230
+ """
231
+ loader = cls(source_dir)
232
+
233
+ # Try to load full config (without extracting just 'linter' section)
234
+ if config_path:
235
+ config = loader._load_from_file(config_path, config_key=None)
236
+ if config is not None:
237
+ return config
238
+
239
+ # Check environment variable for full config
240
+ env_config = os.environ.get('AUTOCODER_LINTER_CONFIG')
241
+ if env_config:
242
+ try:
243
+ return json.loads(env_config)
244
+ except json.JSONDecodeError:
245
+ pass
246
+
247
+ # Check project and global config files
248
+ for config_source in [loader._load_from_project_config, loader._load_from_global_config]:
249
+ config = config_source(config_key=None) # Load full config
250
+ if config is not None:
251
+ return config
252
+
253
+ # Return empty config if nothing found
254
+ return {}
255
+
256
+
257
+ def load_linter_config(config_path: Optional[str] = None,
258
+ source_dir: Optional[str] = None) -> Dict[str, Any]:
259
+ """
260
+ Convenience function to load and validate linter configuration.
261
+
262
+ Args:
263
+ config_path: Explicit path to configuration file
264
+ source_dir: Base directory for relative path resolution
265
+
266
+ Returns:
267
+ Validated linter configuration dictionary
268
+ """
269
+ loader = LinterConfigLoader(source_dir)
270
+ raw_config = loader.load_config(config_path)
271
+ return loader.validate_config(raw_config)
File without changes
@@ -0,0 +1,38 @@
1
+ """
2
+ Base classes for formatting linter results.
3
+
4
+ This layer allows each linter to define how its results are presented
5
+ without changing the linting logic. By default, a raw formatter returns
6
+ results unchanged (as dictionaries), and consumers may subclass to
7
+ produce pretty text, tables, or other formats.
8
+ """
9
+
10
+ from __future__ import annotations
11
+
12
+ from abc import ABC, abstractmethod
13
+ from typing import Any, Dict
14
+
15
+ from ..models.lint_result import LintResult
16
+
17
+
18
+ class BaseLintOutputFormatter(ABC):
19
+ """Abstract formatter for lint results.
20
+
21
+ Subclasses implement presentation logic for a single result and a
22
+ collection of results. The return type is intentionally flexible to
23
+ support dicts, strings, or other serializable structures.
24
+ """
25
+
26
+ @abstractmethod
27
+ def format_result(self, result: LintResult) -> Any:
28
+ """Format a single `LintResult` for presentation."""
29
+ raise NotImplementedError
30
+
31
+ def format_results(self, results: Dict[str, LintResult]) -> Dict[str, Any]:
32
+ """Format multiple results.
33
+
34
+ Default implementation maps input keys to formatted entries using
35
+ `format_result`. Subclasses may override when a different aggregated
36
+ structure is desired (e.g., a single text blob, table, or summary).
37
+ """
38
+ return {path: self.format_result(result) for path, result in results.items()}
@@ -0,0 +1,17 @@
1
+ """
2
+ Default raw formatter that returns lint results as dictionaries, unchanged.
3
+ """
4
+
5
+ from __future__ import annotations
6
+
7
+ from typing import Any
8
+
9
+ from ..models.lint_result import LintResult
10
+ from .base_formatter import BaseLintOutputFormatter
11
+
12
+
13
+ class RawLintOutputFormatter(BaseLintOutputFormatter):
14
+ """Return lint results as plain dictionaries with embedded summary."""
15
+
16
+ def format_result(self, result: LintResult) -> Any:
17
+ return result.to_dict()
@@ -0,0 +1,166 @@
1
+ """
2
+ Main Linter class that provides a simple interface for code checking.
3
+ """
4
+
5
+ import concurrent.futures
6
+ from typing import Dict, List, Optional, Union, Any
7
+ from pathlib import Path
8
+
9
+ from .base_linter import BaseLinter
10
+ from .models.lint_result import LintResult
11
+ from .linters import PythonLinter, TypeScriptLinter
12
+
13
+
14
+ class Linter:
15
+ """Simple interface for linting files across multiple languages."""
16
+
17
+ def __init__(self, config: Optional[Dict[str, Any]] = None):
18
+ """
19
+ Initialize the linter.
20
+
21
+ Args:
22
+ config: Optional configuration with keys:
23
+ - max_workers: Maximum parallel workers (default: 4)
24
+ - python: Python linter config
25
+ - typescript: TypeScript linter config
26
+ """
27
+ self.config = config or {}
28
+ self.max_workers = self.config.get('max_workers', 4)
29
+
30
+ # Initialize available linters
31
+ self._linters: Dict[str, BaseLinter] = {}
32
+ self._init_linters()
33
+
34
+ def _init_linters(self) -> None:
35
+ """Initialize all available linters."""
36
+ # Python linter
37
+ python_config = self.config.get('python', {})
38
+ python_linter = PythonLinter(python_config)
39
+ if python_linter.is_available():
40
+ self._linters['python'] = python_linter
41
+
42
+ # TypeScript linter
43
+ ts_config = self.config.get('typescript', {})
44
+ ts_linter = TypeScriptLinter(ts_config)
45
+ if ts_linter.is_available():
46
+ self._linters['typescript'] = ts_linter
47
+
48
+ def check_file(self, file_path: Union[str, Path]) -> Optional[LintResult]:
49
+ """
50
+ Check a single file.
51
+
52
+ Args:
53
+ file_path: Path to the file to check
54
+
55
+ Returns:
56
+ LintResult if the file can be checked, None otherwise
57
+ """
58
+ path = Path(file_path)
59
+
60
+ if not path.exists():
61
+ return LintResult(
62
+ file_path=str(path),
63
+ success=False,
64
+ error=f"File not found: {path}"
65
+ )
66
+
67
+ # Find appropriate linter
68
+ for linter in self._linters.values():
69
+ if linter.can_check(path):
70
+ return linter.check_file(path)
71
+
72
+ return None # No linter available for this file type
73
+
74
+ def check_files(self, file_paths: List[Union[str, Path]],
75
+ parallel: bool = True) -> Dict[str, LintResult]:
76
+ """
77
+ Check multiple files.
78
+
79
+ Args:
80
+ file_paths: List of file paths to check
81
+ parallel: Whether to use parallel processing
82
+
83
+ Returns:
84
+ Dictionary mapping file paths to their results
85
+ """
86
+ results = {}
87
+
88
+ if parallel and len(file_paths) > 1:
89
+ with concurrent.futures.ThreadPoolExecutor(max_workers=self.max_workers) as executor:
90
+ future_to_file = {
91
+ executor.submit(self.check_file, fp): str(fp)
92
+ for fp in file_paths
93
+ }
94
+
95
+ for future in concurrent.futures.as_completed(future_to_file):
96
+ file_path = future_to_file[future]
97
+ try:
98
+ result = future.result()
99
+ if result:
100
+ results[file_path] = result
101
+ except Exception as e:
102
+ results[file_path] = LintResult(
103
+ file_path=file_path,
104
+ success=False,
105
+ error=str(e)
106
+ )
107
+ else:
108
+ for file_path in file_paths:
109
+ result = self.check_file(file_path)
110
+ if result:
111
+ results[str(file_path)] = result
112
+
113
+ return results
114
+
115
+ def check_directory(self, directory: Union[str, Path],
116
+ recursive: bool = True,
117
+ extensions: Optional[List[str]] = None) -> Dict[str, LintResult]:
118
+ """
119
+ Check all supported files in a directory.
120
+
121
+ Args:
122
+ directory: Directory to check
123
+ recursive: Whether to check subdirectories
124
+ extensions: Specific extensions to check (None = all supported)
125
+
126
+ Returns:
127
+ Dictionary mapping file paths to their results
128
+ """
129
+ path = Path(directory)
130
+ if not path.exists():
131
+ return {
132
+ str(path): LintResult(
133
+ file_path=str(path),
134
+ success=False,
135
+ error=f"Directory not found: {path}"
136
+ )
137
+ }
138
+
139
+ # Get all supported extensions if not specified
140
+ if extensions is None:
141
+ extensions = []
142
+ for linter in self._linters.values():
143
+ extensions.extend(linter.extensions)
144
+
145
+ # Find files
146
+ files = []
147
+ pattern = "**/*" if recursive else "*"
148
+ for ext in set(extensions):
149
+ files.extend(path.glob(f"{pattern}{ext}"))
150
+
151
+ return self.check_files(files)
152
+
153
+ def get_supported_languages(self) -> List[str]:
154
+ """Get list of supported languages."""
155
+ return list(self._linters.keys())
156
+
157
+ def get_supported_extensions(self) -> List[str]:
158
+ """Get list of all supported file extensions."""
159
+ extensions = []
160
+ for linter in self._linters.values():
161
+ extensions.extend(linter.extensions)
162
+ return list(set(extensions))
163
+
164
+ def is_available(self, language: str) -> bool:
165
+ """Check if a specific language linter is available."""
166
+ return language in self._linters