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,315 @@
1
+ """
2
+ Timeout configuration module for shell command execution.
3
+
4
+ This module provides flexible timeout configuration for different types of commands
5
+ and execution scenarios.
6
+ """
7
+
8
+ import os
9
+ import re
10
+ from dataclasses import dataclass, field
11
+ from typing import Dict, Optional, Union, List
12
+
13
+ from .exceptions import TimeoutConfigError
14
+
15
+
16
+ @dataclass
17
+ class TimeoutConfig:
18
+ """
19
+ Configuration class for command timeout settings.
20
+
21
+ This class provides comprehensive timeout configuration including:
22
+ - Default timeout for all commands
23
+ - Interactive command timeout
24
+ - Process cleanup timeout
25
+ - Grace period for graceful termination
26
+ - Command-specific timeout overrides
27
+
28
+ Attributes:
29
+ default_timeout: Default timeout for all commands (seconds)
30
+ interactive_timeout: Timeout for interactive commands (seconds)
31
+ cleanup_timeout: Timeout for process cleanup operations (seconds)
32
+ grace_period: Grace period for graceful process termination (seconds)
33
+ command_timeouts: Dictionary mapping command patterns to specific timeouts
34
+ """
35
+
36
+ default_timeout: Optional[float] = 300.0 # 5 minutes
37
+ interactive_timeout: Optional[float] = 600.0 # 10 minutes
38
+ cleanup_timeout: float = 10.0 # 10 seconds
39
+ grace_period: float = 5.0 # 5 seconds
40
+
41
+ # Command-specific timeout overrides
42
+ command_timeouts: Dict[str, float] = field(default_factory=dict)
43
+
44
+ def __post_init__(self):
45
+ """Validate configuration after initialization."""
46
+ self._validate_config()
47
+
48
+ def _validate_config(self):
49
+ """Validate timeout configuration values."""
50
+
51
+ # Validate default_timeout
52
+ if self.default_timeout is not None and self.default_timeout <= 0:
53
+ raise TimeoutConfigError(
54
+ "default_timeout",
55
+ self.default_timeout,
56
+ "must be positive or None"
57
+ )
58
+
59
+ # Validate interactive_timeout
60
+ if self.interactive_timeout is not None and self.interactive_timeout <= 0:
61
+ raise TimeoutConfigError(
62
+ "interactive_timeout",
63
+ self.interactive_timeout,
64
+ "must be positive or None"
65
+ )
66
+
67
+ # Validate cleanup_timeout
68
+ if self.cleanup_timeout <= 0:
69
+ raise TimeoutConfigError(
70
+ "cleanup_timeout",
71
+ self.cleanup_timeout,
72
+ "must be positive"
73
+ )
74
+
75
+ # Validate grace_period
76
+ if self.grace_period <= 0:
77
+ raise TimeoutConfigError(
78
+ "grace_period",
79
+ self.grace_period,
80
+ "must be positive"
81
+ )
82
+
83
+ # Validate command_timeouts
84
+ for command, timeout in self.command_timeouts.items():
85
+ if timeout <= 0:
86
+ raise TimeoutConfigError(
87
+ f"command_timeouts[{command}]",
88
+ timeout,
89
+ "must be positive"
90
+ )
91
+
92
+ def get_timeout_for_command(self, command: Union[str, List[str]]) -> Optional[float]:
93
+ """
94
+ Get the appropriate timeout for a specific command.
95
+
96
+ This method checks for command-specific timeouts first, then falls back
97
+ to the default timeout.
98
+
99
+ Args:
100
+ command: The command string or list to get timeout for
101
+
102
+ Returns:
103
+ Timeout in seconds, or None for no timeout
104
+ """
105
+ # Convert command to string if needed
106
+ if isinstance(command, list):
107
+ if not command:
108
+ return self.default_timeout
109
+ command_str = " ".join(str(arg) for arg in command)
110
+ else:
111
+ command_str = command
112
+
113
+ if not command_str:
114
+ return self.default_timeout
115
+
116
+ # Extract the base command (first word)
117
+ base_command = command_str.strip().split()[0] if command_str.strip() else ""
118
+ command_parts = command_str.strip().split()
119
+ is_single_command = len(command_parts) == 1
120
+
121
+ # Check for pattern matches - prioritize patterns that match from the beginning
122
+ # Sort patterns by specificity: exact matches first for single commands, then patterns, then exact for multi-word
123
+ def pattern_priority(item):
124
+ pattern, _ = item
125
+ # For single-word commands, exact matches get highest priority
126
+ # For multi-word commands, patterns get higher priority than base command exact matches
127
+ is_exact = pattern == base_command
128
+ is_pattern = '*' in pattern
129
+ # Patterns starting with text (not *) get higher priority than wildcards
130
+ starts_with_text = not pattern.startswith('*')
131
+ # Longer patterns get higher priority within same category
132
+ length = len(pattern)
133
+
134
+ if is_single_command:
135
+ # Single command: exact > patterns
136
+ return (is_exact, not is_pattern, starts_with_text, length)
137
+ else:
138
+ # Multi-word command: patterns > exact base command
139
+ return (not is_exact or is_pattern, starts_with_text, length)
140
+
141
+ patterns = sorted(self.command_timeouts.items(), key=pattern_priority, reverse=True)
142
+
143
+ for pattern, timeout in patterns:
144
+ # For exact matches, check base command
145
+ if pattern == base_command and ('*' not in pattern):
146
+ # For multi-word commands, only return exact match if no patterns match
147
+ if is_single_command:
148
+ return timeout
149
+ # For multi-word, continue to check patterns first
150
+ # For patterns, check full command string
151
+ if self._matches_pattern(command_str, pattern):
152
+ return timeout
153
+
154
+ # If we get here and it's a multi-word command, check for exact base command match
155
+ if not is_single_command and base_command in self.command_timeouts:
156
+ pattern = base_command
157
+ if '*' not in pattern: # Make sure it's not a pattern
158
+ return self.command_timeouts[base_command]
159
+
160
+ # Fall back to default timeout
161
+ return self.default_timeout
162
+
163
+ def _matches_pattern(self, command: str, pattern: str) -> bool:
164
+ """
165
+ Check if a command matches a timeout pattern.
166
+
167
+ Args:
168
+ command: The command to check
169
+ pattern: The pattern to match against
170
+
171
+ Returns:
172
+ True if the command matches the pattern
173
+ """
174
+ # Support simple wildcard patterns
175
+ if '*' in pattern:
176
+ # Convert simple wildcard to regex
177
+ regex_pattern = pattern.replace('*', '.*')
178
+ return bool(re.match(regex_pattern, command))
179
+
180
+ # Support exact substring matching
181
+ return pattern in command
182
+
183
+ def set_command_timeout(self, command_pattern: str, timeout: float):
184
+ """
185
+ Set timeout for a specific command pattern.
186
+
187
+ Args:
188
+ command_pattern: Command or pattern to set timeout for
189
+ timeout: Timeout value in seconds
190
+
191
+ Raises:
192
+ TimeoutConfigError: If timeout value is invalid
193
+ """
194
+ if timeout <= 0:
195
+ raise TimeoutConfigError(
196
+ f"command_timeouts[{command_pattern}]",
197
+ timeout,
198
+ "must be positive"
199
+ )
200
+
201
+ self.command_timeouts[command_pattern] = timeout
202
+
203
+ def remove_command_timeout(self, command_pattern: str):
204
+ """
205
+ Remove timeout override for a command pattern.
206
+
207
+ Args:
208
+ command_pattern: Command pattern to remove
209
+ """
210
+ self.command_timeouts.pop(command_pattern, None)
211
+
212
+ @classmethod
213
+ def from_env(cls) -> 'TimeoutConfig':
214
+ """
215
+ Create TimeoutConfig from environment variables.
216
+
217
+ Environment variables:
218
+ AUTOCODER_DEFAULT_TIMEOUT: Default timeout in seconds
219
+ AUTOCODER_INTERACTIVE_TIMEOUT: Interactive timeout in seconds
220
+ AUTOCODER_CLEANUP_TIMEOUT: Cleanup timeout in seconds
221
+ AUTOCODER_GRACE_PERIOD: Grace period in seconds
222
+
223
+ Returns:
224
+ TimeoutConfig instance configured from environment
225
+ """
226
+ def get_optional_float(env_var: str, default: Optional[float]) -> Optional[float]:
227
+ value = os.getenv(env_var)
228
+ if value is None:
229
+ return default
230
+ if value.lower() in ('none', 'null', ''):
231
+ return None
232
+ try:
233
+ return float(value)
234
+ except ValueError:
235
+ raise TimeoutConfigError(
236
+ env_var,
237
+ value,
238
+ "must be a valid number or 'none'"
239
+ )
240
+
241
+ def get_float(env_var: str, default: float) -> float:
242
+ value = os.getenv(env_var)
243
+ if value is None:
244
+ return default
245
+ try:
246
+ return float(value)
247
+ except ValueError:
248
+ raise TimeoutConfigError(
249
+ env_var,
250
+ value,
251
+ "must be a valid number"
252
+ )
253
+
254
+ return cls(
255
+ default_timeout=get_optional_float('AUTOCODER_DEFAULT_TIMEOUT', 300.0),
256
+ interactive_timeout=get_optional_float('AUTOCODER_INTERACTIVE_TIMEOUT', 600.0),
257
+ cleanup_timeout=get_float('AUTOCODER_CLEANUP_TIMEOUT', 10.0),
258
+ grace_period=get_float('AUTOCODER_GRACE_PERIOD', 5.0),
259
+ )
260
+
261
+ def to_dict(self) -> Dict:
262
+ """
263
+ Convert configuration to dictionary.
264
+
265
+ Returns:
266
+ Dictionary representation of the configuration
267
+ """
268
+ return {
269
+ 'default_timeout': self.default_timeout,
270
+ 'interactive_timeout': self.interactive_timeout,
271
+ 'cleanup_timeout': self.cleanup_timeout,
272
+ 'grace_period': self.grace_period,
273
+ 'command_timeouts': self.command_timeouts.copy(),
274
+ }
275
+
276
+ @classmethod
277
+ def from_dict(cls, config_dict: Dict) -> 'TimeoutConfig':
278
+ """
279
+ Create TimeoutConfig from dictionary.
280
+
281
+ Args:
282
+ config_dict: Dictionary containing configuration values
283
+
284
+ Returns:
285
+ TimeoutConfig instance
286
+ """
287
+ return cls(
288
+ default_timeout=config_dict.get('default_timeout', 300.0),
289
+ interactive_timeout=config_dict.get('interactive_timeout', 600.0),
290
+ cleanup_timeout=config_dict.get('cleanup_timeout', 10.0),
291
+ grace_period=config_dict.get('grace_period', 5.0),
292
+ command_timeouts=config_dict.get('command_timeouts', {}),
293
+ )
294
+
295
+ def __str__(self) -> str:
296
+ """String representation of the configuration."""
297
+ return (
298
+ f"TimeoutConfig("
299
+ f"default={self.default_timeout}, "
300
+ f"interactive={self.interactive_timeout}, "
301
+ f"cleanup={self.cleanup_timeout}, "
302
+ f"grace={self.grace_period}, "
303
+ f"overrides={len(self.command_timeouts)})"
304
+ )
305
+
306
+ def __repr__(self) -> str:
307
+ """Detailed string representation."""
308
+ return (
309
+ f"TimeoutConfig("
310
+ f"default_timeout={self.default_timeout}, "
311
+ f"interactive_timeout={self.interactive_timeout}, "
312
+ f"cleanup_timeout={self.cleanup_timeout}, "
313
+ f"grace_period={self.grace_period}, "
314
+ f"command_timeouts={self.command_timeouts})"
315
+ )
@@ -0,0 +1,352 @@
1
+ """
2
+ Timeout manager module for shell command execution.
3
+
4
+ This module provides timeout management functionality including:
5
+ - Starting and canceling timeouts
6
+ - Handling timeout events
7
+ - Managing multiple concurrent timeouts
8
+ - Integration with process cleanup
9
+ """
10
+
11
+ import subprocess
12
+ import threading
13
+ import time
14
+ from typing import Dict, Optional, Callable
15
+ from loguru import logger
16
+
17
+ from .timeout_config import TimeoutConfig
18
+ from .process_cleanup import cleanup_process_tree
19
+ from .exceptions import CommandTimeoutError
20
+
21
+
22
+ class TimeoutManager:
23
+ """
24
+ Manager for command execution timeouts.
25
+
26
+ This class handles timeout management for command execution, including
27
+ starting timers, canceling them, and handling timeout events with
28
+ proper process cleanup.
29
+
30
+ Attributes:
31
+ config: Timeout configuration
32
+ active_timers: Dictionary of active timeout timers
33
+ timeout_callbacks: Dictionary of timeout callbacks
34
+ """
35
+
36
+ def __init__(self, config: TimeoutConfig):
37
+ """
38
+ Initialize timeout manager.
39
+
40
+ Args:
41
+ config: Timeout configuration to use
42
+ """
43
+ self.config = config
44
+ self.active_timers: Dict[int, threading.Timer] = {}
45
+ self.timeout_callbacks: Dict[int, Callable] = {}
46
+ self._lock = threading.Lock()
47
+
48
+ logger.debug(f"TimeoutManager initialized with config: {config}")
49
+
50
+ def start_timeout(
51
+ self,
52
+ process: subprocess.Popen,
53
+ timeout: float,
54
+ callback: Optional[Callable] = None
55
+ ) -> None:
56
+ """
57
+ Start a timeout for a process.
58
+
59
+ Args:
60
+ process: The subprocess.Popen object to monitor
61
+ timeout: Timeout duration in seconds
62
+ callback: Optional callback to call on timeout (in addition to cleanup)
63
+ """
64
+ if timeout <= 0:
65
+ logger.warning(f"Invalid timeout value: {timeout}, ignoring")
66
+ return
67
+
68
+ pid = process.pid
69
+
70
+ with self._lock:
71
+ # Cancel any existing timeout for this process (without acquiring lock again)
72
+ existing_timer = self.active_timers.pop(pid, None)
73
+ existing_callback = self.timeout_callbacks.pop(pid, None)
74
+
75
+ if existing_timer:
76
+ existing_timer.cancel()
77
+ logger.debug(f"Canceled existing timeout for PID {pid}")
78
+
79
+ # Create timeout handler
80
+ def timeout_handler():
81
+ self._handle_timeout(process, timeout, callback)
82
+
83
+ # Start timer
84
+ timer = threading.Timer(timeout, timeout_handler)
85
+ timer.daemon = True # Don't prevent program exit
86
+
87
+ try:
88
+ timer.start()
89
+
90
+ # Store timer and callback only if start was successful
91
+ self.active_timers[pid] = timer
92
+ if callback:
93
+ self.timeout_callbacks[pid] = callback
94
+
95
+ logger.debug(f"Started timeout for PID {pid} with {timeout}s timeout")
96
+
97
+ except Exception as e:
98
+ logger.error(f"Failed to start timeout for PID {pid}: {e}")
99
+ # Don't store the timer since it failed to start
100
+
101
+ def cancel_timeout(self, process: subprocess.Popen) -> bool:
102
+ """
103
+ Cancel timeout for a process.
104
+
105
+ Args:
106
+ process: The subprocess.Popen object
107
+
108
+ Returns:
109
+ True if timeout was canceled, False if no timeout was active
110
+ """
111
+ pid = process.pid
112
+
113
+ with self._lock:
114
+ timer = self.active_timers.pop(pid, None)
115
+ callback = self.timeout_callbacks.pop(pid, None)
116
+
117
+ if timer:
118
+ timer.cancel()
119
+ logger.debug(f"Canceled timeout for PID {pid}")
120
+ return True
121
+
122
+ return False
123
+
124
+ def is_timeout_active(self, process: subprocess.Popen) -> bool:
125
+ """
126
+ Check if timeout is active for a process.
127
+
128
+ Args:
129
+ process: The subprocess.Popen object
130
+
131
+ Returns:
132
+ True if timeout is active
133
+ """
134
+ pid = process.pid
135
+ with self._lock:
136
+ return pid in self.active_timers
137
+
138
+ def get_remaining_timeout(self, process: subprocess.Popen) -> Optional[float]:
139
+ """
140
+ Get remaining timeout for a process.
141
+
142
+ Args:
143
+ process: The subprocess.Popen object
144
+
145
+ Returns:
146
+ Remaining timeout in seconds, or None if no timeout active
147
+ """
148
+ pid = process.pid
149
+ with self._lock:
150
+ timer = self.active_timers.get(pid)
151
+ if timer and timer.is_alive():
152
+ # This is an approximation since Timer doesn't expose remaining time
153
+ # In practice, this would need more sophisticated tracking
154
+ return None # Could implement if needed
155
+ return None
156
+
157
+ def _handle_timeout(
158
+ self,
159
+ process: subprocess.Popen,
160
+ timeout: float,
161
+ callback: Optional[Callable] = None
162
+ ) -> None:
163
+ """
164
+ Handle timeout event for a process.
165
+
166
+ Args:
167
+ process: The subprocess.Popen object that timed out
168
+ timeout: The timeout value that was exceeded
169
+ callback: Optional user callback to execute
170
+ """
171
+ pid = process.pid
172
+
173
+ logger.warning(f"Process {pid} timed out after {timeout} seconds")
174
+
175
+ try:
176
+ # Remove from active timers
177
+ with self._lock:
178
+ self.active_timers.pop(pid, None)
179
+ self.timeout_callbacks.pop(pid, None)
180
+
181
+ # Execute user callback if provided
182
+ if callback:
183
+ try:
184
+ callback(process, timeout)
185
+ except Exception as e:
186
+ logger.error(f"Error in timeout callback for PID {pid}: {e}")
187
+
188
+ # Attempt to cleanup the process tree
189
+ try:
190
+ cleanup_success = cleanup_process_tree(
191
+ pid,
192
+ timeout=self.config.grace_period,
193
+ force_timeout=self.config.cleanup_timeout - self.config.grace_period
194
+ )
195
+
196
+ if cleanup_success:
197
+ logger.debug(f"Successfully cleaned up process tree for PID {pid}")
198
+ else:
199
+ logger.warning(f"Failed to fully cleanup process tree for PID {pid}")
200
+
201
+ except Exception as e:
202
+ logger.error(f"Error during process cleanup for PID {pid}: {e}")
203
+
204
+ except Exception as e:
205
+ logger.error(f"Error handling timeout for PID {pid}: {e}")
206
+
207
+ def cleanup_all_timeouts(self) -> None:
208
+ """
209
+ Cancel all active timeouts.
210
+
211
+ This method should be called when shutting down to ensure
212
+ all timers are properly canceled.
213
+ """
214
+ with self._lock:
215
+ for pid, timer in self.active_timers.items():
216
+ try:
217
+ timer.cancel()
218
+ logger.debug(f"Canceled timeout for PID {pid} during cleanup")
219
+ except Exception as e:
220
+ logger.error(f"Error canceling timeout for PID {pid}: {e}")
221
+
222
+ self.active_timers.clear()
223
+ self.timeout_callbacks.clear()
224
+
225
+ logger.debug("All timeouts cleaned up")
226
+
227
+ def get_active_timeouts(self) -> Dict[int, bool]:
228
+ """
229
+ Get information about active timeouts.
230
+
231
+ Returns:
232
+ Dictionary mapping PID to timer status (alive/dead)
233
+ """
234
+ with self._lock:
235
+ return {
236
+ pid: timer.is_alive()
237
+ for pid, timer in self.active_timers.items()
238
+ }
239
+
240
+ def __del__(self):
241
+ """Cleanup when manager is destroyed."""
242
+ try:
243
+ self.cleanup_all_timeouts()
244
+ except Exception:
245
+ pass # Ignore errors during cleanup
246
+
247
+
248
+ class TimeoutContext:
249
+ """
250
+ Context manager for timeout management.
251
+
252
+ This provides a convenient way to manage timeouts using the 'with' statement.
253
+ The timeout is automatically canceled when exiting the context.
254
+ """
255
+
256
+ def __init__(
257
+ self,
258
+ manager: TimeoutManager,
259
+ process: subprocess.Popen,
260
+ timeout: float,
261
+ callback: Optional[Callable] = None
262
+ ):
263
+ """
264
+ Initialize timeout context.
265
+
266
+ Args:
267
+ manager: TimeoutManager instance
268
+ process: Process to monitor
269
+ timeout: Timeout duration
270
+ callback: Optional timeout callback
271
+ """
272
+ self.manager = manager
273
+ self.process = process
274
+ self.timeout = timeout
275
+ self.callback = callback
276
+
277
+ def __enter__(self) -> 'TimeoutContext':
278
+ """Start timeout when entering context."""
279
+ self.manager.start_timeout(self.process, self.timeout, self.callback)
280
+ return self
281
+
282
+ def __exit__(self, exc_type, exc_val, exc_tb) -> None:
283
+ """Cancel timeout when exiting context."""
284
+ self.manager.cancel_timeout(self.process)
285
+
286
+
287
+ class GlobalTimeoutManager:
288
+ """
289
+ Global singleton timeout manager.
290
+
291
+ This provides a convenient way to access a global timeout manager
292
+ throughout the application.
293
+ """
294
+
295
+ _instance: Optional[TimeoutManager] = None
296
+ _lock = threading.Lock()
297
+
298
+ @classmethod
299
+ def get_instance(cls, config: Optional[TimeoutConfig] = None) -> TimeoutManager:
300
+ """
301
+ Get or create the global timeout manager instance.
302
+
303
+ Args:
304
+ config: Optional config to use for first initialization
305
+
306
+ Returns:
307
+ Global TimeoutManager instance
308
+ """
309
+ if cls._instance is None:
310
+ with cls._lock:
311
+ if cls._instance is None:
312
+ if config is None:
313
+ config = TimeoutConfig()
314
+ cls._instance = TimeoutManager(config)
315
+ logger.debug("Created global TimeoutManager instance")
316
+
317
+ return cls._instance
318
+
319
+ @classmethod
320
+ def reset_instance(cls) -> None:
321
+ """
322
+ Reset the global instance.
323
+
324
+ This is mainly useful for testing.
325
+ """
326
+ with cls._lock:
327
+ if cls._instance:
328
+ cls._instance.cleanup_all_timeouts()
329
+ cls._instance = None
330
+ logger.debug("Reset global TimeoutManager instance")
331
+
332
+
333
+ def create_timeout_context(
334
+ process: subprocess.Popen,
335
+ timeout: float,
336
+ config: Optional[TimeoutConfig] = None,
337
+ callback: Optional[Callable] = None
338
+ ) -> TimeoutContext:
339
+ """
340
+ Convenience function to create a timeout context.
341
+
342
+ Args:
343
+ process: Process to monitor
344
+ timeout: Timeout duration
345
+ config: Optional timeout configuration
346
+ callback: Optional timeout callback
347
+
348
+ Returns:
349
+ TimeoutContext instance
350
+ """
351
+ manager = GlobalTimeoutManager.get_instance(config)
352
+ return TimeoutContext(manager, process, timeout, callback)
@@ -0,0 +1,14 @@
1
+ """Terminal paste handling module for auto-coder.
2
+
3
+ This module provides functionality to intercept terminal paste events,
4
+ save pasted content to files, and resolve placeholders in user input.
5
+ """
6
+
7
+ from .paste_handler import register_paste_handler, resolve_paste_placeholders
8
+ from .paste_manager import PasteManager
9
+
10
+ __all__ = [
11
+ "register_paste_handler",
12
+ "resolve_paste_placeholders",
13
+ "PasteManager"
14
+ ]