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

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

Potentially problematic release.


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

Files changed (579) hide show
  1. auto_coder-2.0.0.dist-info/LICENSE +158 -0
  2. auto_coder-2.0.0.dist-info/METADATA +558 -0
  3. auto_coder-2.0.0.dist-info/RECORD +795 -0
  4. {auto_coder-0.1.400.dist-info → auto_coder-2.0.0.dist-info}/WHEEL +1 -1
  5. {auto_coder-0.1.400.dist-info → auto_coder-2.0.0.dist-info}/entry_points.txt +3 -3
  6. autocoder/__init__.py +31 -0
  7. autocoder/agent/auto_filegroup.py +32 -13
  8. autocoder/agent/auto_learn_from_commit.py +9 -1
  9. autocoder/agent/base_agentic/__init__.py +3 -0
  10. autocoder/agent/base_agentic/agent_hub.py +1 -1
  11. autocoder/agent/base_agentic/base_agent.py +235 -136
  12. autocoder/agent/base_agentic/default_tools.py +119 -118
  13. autocoder/agent/base_agentic/test_base_agent.py +1 -1
  14. autocoder/agent/base_agentic/tool_registry.py +32 -20
  15. autocoder/agent/base_agentic/tools/read_file_tool_resolver.py +25 -4
  16. autocoder/agent/base_agentic/tools/write_to_file_tool_resolver.py +24 -11
  17. autocoder/agent/base_agentic/types.py +42 -0
  18. autocoder/agent/entry_command_agent/chat.py +73 -59
  19. autocoder/auto_coder.py +31 -40
  20. autocoder/auto_coder_rag.py +11 -1084
  21. autocoder/auto_coder_runner.py +1029 -2310
  22. autocoder/auto_coder_terminal.py +26 -0
  23. autocoder/auto_coder_terminal_v3.py +190 -0
  24. autocoder/chat/conf_command.py +224 -124
  25. autocoder/chat/models_command.py +361 -299
  26. autocoder/chat/rules_command.py +79 -31
  27. autocoder/chat_auto_coder.py +1021 -372
  28. autocoder/chat_auto_coder_lang.py +23 -732
  29. autocoder/commands/auto_command.py +26 -9
  30. autocoder/commands/auto_web.py +1 -1
  31. autocoder/commands/tools.py +44 -44
  32. autocoder/common/__init__.py +150 -128
  33. autocoder/common/ac_style_command_parser/__init__.py +39 -2
  34. autocoder/common/ac_style_command_parser/config.py +422 -0
  35. autocoder/common/ac_style_command_parser/parser.py +292 -78
  36. autocoder/common/ac_style_command_parser/test_parser.py +241 -16
  37. autocoder/common/ac_style_command_parser/test_typed_parser.py +342 -0
  38. autocoder/common/ac_style_command_parser/typed_parser.py +653 -0
  39. autocoder/common/action_yml_file_manager.py +25 -13
  40. autocoder/common/agent_events/__init__.py +52 -0
  41. autocoder/common/agent_events/agent_event_emitter.py +193 -0
  42. autocoder/common/agent_events/event_factory.py +177 -0
  43. autocoder/common/agent_events/examples.py +307 -0
  44. autocoder/common/agent_events/types.py +113 -0
  45. autocoder/common/agent_events/utils.py +68 -0
  46. autocoder/common/agent_hooks/__init__.py +44 -0
  47. autocoder/common/agent_hooks/examples.py +582 -0
  48. autocoder/common/agent_hooks/hook_executor.py +217 -0
  49. autocoder/common/agent_hooks/hook_manager.py +288 -0
  50. autocoder/common/agent_hooks/types.py +133 -0
  51. autocoder/common/agent_hooks/utils.py +99 -0
  52. autocoder/common/agent_query_queue/queue_executor.py +324 -0
  53. autocoder/common/agent_query_queue/queue_manager.py +325 -0
  54. autocoder/common/agents/__init__.py +11 -0
  55. autocoder/common/agents/agent_manager.py +323 -0
  56. autocoder/common/agents/agent_parser.py +189 -0
  57. autocoder/common/agents/example_usage.py +344 -0
  58. autocoder/common/agents/integration_example.py +330 -0
  59. autocoder/common/agents/test_agent_parser.py +545 -0
  60. autocoder/common/async_utils.py +101 -0
  61. autocoder/common/auto_coder_lang.py +23 -972
  62. autocoder/common/autocoderargs_parser/__init__.py +14 -0
  63. autocoder/common/autocoderargs_parser/parser.py +184 -0
  64. autocoder/common/autocoderargs_parser/tests/__init__.py +1 -0
  65. autocoder/common/autocoderargs_parser/tests/test_args_parser.py +235 -0
  66. autocoder/common/autocoderargs_parser/tests/test_token_parser.py +195 -0
  67. autocoder/common/autocoderargs_parser/token_parser.py +290 -0
  68. autocoder/common/buildin_tokenizer.py +2 -4
  69. autocoder/common/code_auto_generate.py +149 -74
  70. autocoder/common/code_auto_generate_diff.py +163 -70
  71. autocoder/common/code_auto_generate_editblock.py +179 -89
  72. autocoder/common/code_auto_generate_strict_diff.py +167 -72
  73. autocoder/common/code_auto_merge_editblock.py +13 -6
  74. autocoder/common/code_modification_ranker.py +1 -1
  75. autocoder/common/command_completer.py +3 -3
  76. autocoder/common/command_file_manager/manager.py +183 -47
  77. autocoder/common/command_file_manager/test_command_file_manager.py +507 -0
  78. autocoder/common/command_templates.py +1 -1
  79. autocoder/common/conf_utils.py +2 -4
  80. autocoder/common/conversations/config.py +11 -3
  81. autocoder/common/conversations/get_conversation_manager.py +100 -2
  82. autocoder/common/conversations/llm_stats_models.py +264 -0
  83. autocoder/common/conversations/manager.py +112 -28
  84. autocoder/common/conversations/models.py +16 -2
  85. autocoder/common/conversations/storage/index_manager.py +134 -10
  86. autocoder/common/core_config/__init__.py +63 -0
  87. autocoder/common/core_config/agentic_mode_manager.py +109 -0
  88. autocoder/common/core_config/base_manager.py +123 -0
  89. autocoder/common/core_config/compatibility.py +151 -0
  90. autocoder/common/core_config/config_manager.py +156 -0
  91. autocoder/common/core_config/conversation_manager.py +31 -0
  92. autocoder/common/core_config/exclude_manager.py +72 -0
  93. autocoder/common/core_config/file_manager.py +177 -0
  94. autocoder/common/core_config/human_as_model_manager.py +129 -0
  95. autocoder/common/core_config/lib_manager.py +54 -0
  96. autocoder/common/core_config/main_manager.py +81 -0
  97. autocoder/common/core_config/mode_manager.py +126 -0
  98. autocoder/common/core_config/models.py +70 -0
  99. autocoder/common/core_config/test_memory_manager.py +1056 -0
  100. autocoder/common/env_manager.py +282 -0
  101. autocoder/common/env_manager_usage_example.py +211 -0
  102. autocoder/common/file_checkpoint/conversation_checkpoint.py +19 -19
  103. autocoder/common/file_checkpoint/manager.py +264 -48
  104. autocoder/common/file_checkpoint/test_backup.py +1 -18
  105. autocoder/common/file_checkpoint/test_manager.py +270 -1
  106. autocoder/common/file_checkpoint/test_store.py +1 -17
  107. autocoder/common/file_handler/__init__.py +23 -0
  108. autocoder/common/file_handler/active_context_handler.py +159 -0
  109. autocoder/common/file_handler/add_files_handler.py +409 -0
  110. autocoder/common/file_handler/chat_handler.py +180 -0
  111. autocoder/common/file_handler/coding_handler.py +401 -0
  112. autocoder/common/file_handler/commit_handler.py +200 -0
  113. autocoder/common/file_handler/lib_handler.py +156 -0
  114. autocoder/common/file_handler/list_files_handler.py +111 -0
  115. autocoder/common/file_handler/mcp_handler.py +268 -0
  116. autocoder/common/file_handler/models_handler.py +493 -0
  117. autocoder/common/file_handler/remove_files_handler.py +172 -0
  118. autocoder/common/file_monitor/test_file_monitor.py +307 -0
  119. autocoder/common/git_utils.py +51 -10
  120. autocoder/common/global_cancel.py +15 -6
  121. autocoder/common/ignorefiles/test_ignore_file_utils.py +1 -1
  122. autocoder/common/international/__init__.py +31 -0
  123. autocoder/common/international/demo_international.py +92 -0
  124. autocoder/common/international/message_manager.py +157 -0
  125. autocoder/common/international/messages/__init__.py +56 -0
  126. autocoder/common/international/messages/async_command_messages.py +507 -0
  127. autocoder/common/international/messages/auto_coder_messages.py +2208 -0
  128. autocoder/common/international/messages/chat_auto_coder_messages.py +1547 -0
  129. autocoder/common/international/messages/command_help_messages.py +986 -0
  130. autocoder/common/international/messages/conversation_command_messages.py +191 -0
  131. autocoder/common/international/messages/git_helper_plugin_messages.py +159 -0
  132. autocoder/common/international/messages/queue_command_messages.py +751 -0
  133. autocoder/common/international/messages/rules_command_messages.py +77 -0
  134. autocoder/common/international/messages/sdk_messages.py +1707 -0
  135. autocoder/common/international/messages/token_helper_plugin_messages.py +361 -0
  136. autocoder/common/international/messages/tool_display_messages.py +1212 -0
  137. autocoder/common/international/messages/workflow_exception_messages.py +473 -0
  138. autocoder/common/international/test_international.py +612 -0
  139. autocoder/common/linter_core/__init__.py +28 -0
  140. autocoder/common/linter_core/base_linter.py +61 -0
  141. autocoder/common/linter_core/config_loader.py +271 -0
  142. autocoder/common/linter_core/formatters/__init__.py +0 -0
  143. autocoder/common/linter_core/formatters/base_formatter.py +38 -0
  144. autocoder/common/linter_core/formatters/raw_formatter.py +17 -0
  145. autocoder/common/linter_core/linter.py +166 -0
  146. autocoder/common/linter_core/linter_factory.py +216 -0
  147. autocoder/common/linter_core/linter_manager.py +333 -0
  148. autocoder/common/linter_core/linters/__init__.py +9 -0
  149. autocoder/common/linter_core/linters/java_linter.py +342 -0
  150. autocoder/common/linter_core/linters/python_linter.py +115 -0
  151. autocoder/common/linter_core/linters/typescript_linter.py +119 -0
  152. autocoder/common/linter_core/models/__init__.py +7 -0
  153. autocoder/common/linter_core/models/lint_result.py +91 -0
  154. autocoder/common/linter_core/models.py +33 -0
  155. autocoder/common/linter_core/tests/__init__.py +3 -0
  156. autocoder/common/linter_core/tests/test_config_loader.py +323 -0
  157. autocoder/common/linter_core/tests/test_config_loading.py +308 -0
  158. autocoder/common/linter_core/tests/test_factory_manager.py +234 -0
  159. autocoder/common/linter_core/tests/test_formatters.py +147 -0
  160. autocoder/common/linter_core/tests/test_integration.py +317 -0
  161. autocoder/common/linter_core/tests/test_java_linter.py +496 -0
  162. autocoder/common/linter_core/tests/test_linters.py +265 -0
  163. autocoder/common/linter_core/tests/test_models.py +81 -0
  164. autocoder/common/linter_core/tests/verify_config_loading.py +296 -0
  165. autocoder/common/linter_core/tests/verify_fixes.py +183 -0
  166. autocoder/common/llm_friendly_package/__init__.py +31 -0
  167. autocoder/common/llm_friendly_package/base_manager.py +102 -0
  168. autocoder/common/llm_friendly_package/docs_manager.py +121 -0
  169. autocoder/common/llm_friendly_package/library_manager.py +171 -0
  170. autocoder/common/{llm_friendly_package.py → llm_friendly_package/main_manager.py} +204 -231
  171. autocoder/common/llm_friendly_package/models.py +40 -0
  172. autocoder/common/llm_friendly_package/test_llm_friendly_package.py +536 -0
  173. autocoder/common/llms/__init__.py +15 -0
  174. autocoder/common/llms/demo_error_handling.py +85 -0
  175. autocoder/common/llms/factory.py +142 -0
  176. autocoder/common/llms/manager.py +264 -0
  177. autocoder/common/llms/pricing.py +121 -0
  178. autocoder/common/llms/registry.py +288 -0
  179. autocoder/common/llms/schema.py +77 -0
  180. autocoder/common/llms/simple_demo.py +45 -0
  181. autocoder/common/llms/test_quick_model.py +116 -0
  182. autocoder/common/llms/test_remove_functionality.py +182 -0
  183. autocoder/common/llms/tests/__init__.py +1 -0
  184. autocoder/common/llms/tests/test_manager.py +330 -0
  185. autocoder/common/llms/tests/test_registry.py +364 -0
  186. autocoder/common/mcp_tools/__init__.py +62 -0
  187. autocoder/common/{mcp_tools.py → mcp_tools/executor.py} +49 -40
  188. autocoder/common/{mcp_hub.py → mcp_tools/hub.py} +42 -68
  189. autocoder/common/{mcp_server_install.py → mcp_tools/installer.py} +16 -28
  190. autocoder/common/{mcp_server.py → mcp_tools/server.py} +176 -48
  191. autocoder/common/mcp_tools/test_keyboard_interrupt.py +93 -0
  192. autocoder/common/mcp_tools/test_mcp_tools.py +391 -0
  193. autocoder/common/{mcp_server_types.py → mcp_tools/types.py} +121 -48
  194. autocoder/common/mcp_tools/verify_functionality.py +202 -0
  195. autocoder/common/model_speed_tester.py +32 -26
  196. autocoder/common/priority_directory_finder/__init__.py +142 -0
  197. autocoder/common/priority_directory_finder/examples.py +230 -0
  198. autocoder/common/priority_directory_finder/finder.py +283 -0
  199. autocoder/common/priority_directory_finder/models.py +236 -0
  200. autocoder/common/priority_directory_finder/test_priority_directory_finder.py +431 -0
  201. autocoder/common/project_scanner/__init__.py +18 -0
  202. autocoder/common/project_scanner/compat.py +77 -0
  203. autocoder/common/project_scanner/scanner.py +436 -0
  204. autocoder/common/project_tracker/__init__.py +27 -0
  205. autocoder/common/project_tracker/api.py +228 -0
  206. autocoder/common/project_tracker/demo.py +272 -0
  207. autocoder/common/project_tracker/tracker.py +487 -0
  208. autocoder/common/project_tracker/types.py +53 -0
  209. autocoder/common/pruner/__init__.py +67 -0
  210. autocoder/common/pruner/agentic_conversation_pruner.py +746 -0
  211. autocoder/common/{context_pruner.py → pruner/context_pruner.py} +137 -40
  212. autocoder/common/pruner/conversation_message_ids_api.py +386 -0
  213. autocoder/common/pruner/conversation_message_ids_manager.py +347 -0
  214. autocoder/common/pruner/conversation_message_ids_pruner.py +473 -0
  215. autocoder/common/pruner/conversation_normalizer.py +347 -0
  216. autocoder/common/{conversation_pruner.py → pruner/conversation_pruner.py} +26 -6
  217. autocoder/common/pruner/test_agentic_conversation_pruner.py +784 -0
  218. autocoder/common/pruner/test_context_pruner.py +546 -0
  219. autocoder/common/pruner/test_conversation_normalizer.py +502 -0
  220. autocoder/common/pruner/test_tool_content_detector.py +324 -0
  221. autocoder/common/pruner/tool_content_detector.py +227 -0
  222. autocoder/common/pruner/tools/__init__.py +18 -0
  223. autocoder/common/pruner/tools/query_message_ids.py +264 -0
  224. autocoder/common/pruner/tools/test_agentic_pruning_logic.py +432 -0
  225. autocoder/common/pruner/tools/test_message_ids_pruning_only.py +192 -0
  226. autocoder/common/pull_requests/__init__.py +9 -1
  227. autocoder/common/pull_requests/utils.py +122 -1
  228. autocoder/common/rag_manager/rag_manager.py +36 -40
  229. autocoder/common/rulefiles/__init__.py +53 -1
  230. autocoder/common/rulefiles/api.py +250 -0
  231. autocoder/common/rulefiles/core/__init__.py +14 -0
  232. autocoder/common/rulefiles/core/manager.py +241 -0
  233. autocoder/common/rulefiles/core/selector.py +805 -0
  234. autocoder/common/rulefiles/models/__init__.py +20 -0
  235. autocoder/common/rulefiles/models/index.py +16 -0
  236. autocoder/common/rulefiles/models/init_rule.py +18 -0
  237. autocoder/common/rulefiles/models/rule_file.py +18 -0
  238. autocoder/common/rulefiles/models/rule_relevance.py +14 -0
  239. autocoder/common/rulefiles/models/summary.py +16 -0
  240. autocoder/common/rulefiles/test_rulefiles.py +776 -0
  241. autocoder/common/rulefiles/utils/__init__.py +34 -0
  242. autocoder/common/rulefiles/utils/monitor.py +86 -0
  243. autocoder/common/rulefiles/utils/parser.py +230 -0
  244. autocoder/common/save_formatted_log.py +67 -10
  245. autocoder/common/search_replace.py +8 -1
  246. autocoder/common/search_replace_patch/__init__.py +24 -0
  247. autocoder/common/search_replace_patch/base.py +115 -0
  248. autocoder/common/search_replace_patch/manager.py +248 -0
  249. autocoder/common/search_replace_patch/patch_replacer.py +304 -0
  250. autocoder/common/search_replace_patch/similarity_replacer.py +306 -0
  251. autocoder/common/search_replace_patch/string_replacer.py +181 -0
  252. autocoder/common/search_replace_patch/tests/__init__.py +3 -0
  253. autocoder/common/search_replace_patch/tests/run_tests.py +126 -0
  254. autocoder/common/search_replace_patch/tests/test_base.py +188 -0
  255. autocoder/common/search_replace_patch/tests/test_empty_line_insert.py +233 -0
  256. autocoder/common/search_replace_patch/tests/test_integration.py +389 -0
  257. autocoder/common/search_replace_patch/tests/test_manager.py +351 -0
  258. autocoder/common/search_replace_patch/tests/test_patch_replacer.py +316 -0
  259. autocoder/common/search_replace_patch/tests/test_regex_replacer.py +306 -0
  260. autocoder/common/search_replace_patch/tests/test_similarity_replacer.py +384 -0
  261. autocoder/common/shell_commands/__init__.py +197 -0
  262. autocoder/common/shell_commands/background_process_notifier.py +346 -0
  263. autocoder/common/shell_commands/command_executor.py +1127 -0
  264. autocoder/common/shell_commands/error_recovery.py +541 -0
  265. autocoder/common/shell_commands/exceptions.py +120 -0
  266. autocoder/common/shell_commands/interactive_executor.py +476 -0
  267. autocoder/common/shell_commands/interactive_pexpect_process.py +623 -0
  268. autocoder/common/shell_commands/interactive_process.py +744 -0
  269. autocoder/common/shell_commands/interactive_session_manager.py +1014 -0
  270. autocoder/common/shell_commands/monitoring.py +529 -0
  271. autocoder/common/shell_commands/process_cleanup.py +386 -0
  272. autocoder/common/shell_commands/process_manager.py +606 -0
  273. autocoder/common/shell_commands/test_interactive_pexpect_process.py +281 -0
  274. autocoder/common/shell_commands/tests/__init__.py +6 -0
  275. autocoder/common/shell_commands/tests/conftest.py +118 -0
  276. autocoder/common/shell_commands/tests/test_background_process_notifier.py +703 -0
  277. autocoder/common/shell_commands/tests/test_command_executor.py +448 -0
  278. autocoder/common/shell_commands/tests/test_error_recovery.py +305 -0
  279. autocoder/common/shell_commands/tests/test_exceptions.py +299 -0
  280. autocoder/common/shell_commands/tests/test_execute_batch.py +588 -0
  281. autocoder/common/shell_commands/tests/test_indented_batch_commands.py +244 -0
  282. autocoder/common/shell_commands/tests/test_integration.py +664 -0
  283. autocoder/common/shell_commands/tests/test_monitoring.py +546 -0
  284. autocoder/common/shell_commands/tests/test_performance.py +632 -0
  285. autocoder/common/shell_commands/tests/test_process_cleanup.py +397 -0
  286. autocoder/common/shell_commands/tests/test_process_manager.py +606 -0
  287. autocoder/common/shell_commands/tests/test_timeout_config.py +343 -0
  288. autocoder/common/shell_commands/tests/test_timeout_manager.py +520 -0
  289. autocoder/common/shell_commands/timeout_config.py +315 -0
  290. autocoder/common/shell_commands/timeout_manager.py +352 -0
  291. autocoder/common/terminal_paste/__init__.py +14 -0
  292. autocoder/common/terminal_paste/demo.py +145 -0
  293. autocoder/common/terminal_paste/demo_paste_functionality.py +95 -0
  294. autocoder/common/terminal_paste/paste_handler.py +200 -0
  295. autocoder/common/terminal_paste/paste_manager.py +118 -0
  296. autocoder/common/terminal_paste/tests/__init__.py +1 -0
  297. autocoder/common/terminal_paste/tests/test_paste_handler.py +182 -0
  298. autocoder/common/terminal_paste/tests/test_paste_manager.py +126 -0
  299. autocoder/common/terminal_paste/utils.py +163 -0
  300. autocoder/common/test_autocoder_args.py +232 -0
  301. autocoder/common/test_env_manager.py +173 -0
  302. autocoder/common/test_env_manager_integration.py +159 -0
  303. autocoder/common/text_similarity/__init__.py +9 -0
  304. autocoder/common/text_similarity/demo.py +216 -0
  305. autocoder/common/text_similarity/examples.py +266 -0
  306. autocoder/common/text_similarity/test_text_similarity.py +306 -0
  307. autocoder/common/text_similarity/text_similarity.py +194 -0
  308. autocoder/common/text_similarity/utils.py +125 -0
  309. autocoder/common/todos/__init__.py +61 -0
  310. autocoder/common/todos/cache/__init__.py +16 -0
  311. autocoder/common/todos/cache/base_cache.py +89 -0
  312. autocoder/common/todos/cache/cache_manager.py +228 -0
  313. autocoder/common/todos/cache/memory_cache.py +225 -0
  314. autocoder/common/todos/config.py +155 -0
  315. autocoder/common/todos/exceptions.py +35 -0
  316. autocoder/common/todos/get_todo_manager.py +161 -0
  317. autocoder/common/todos/manager.py +537 -0
  318. autocoder/common/todos/models.py +239 -0
  319. autocoder/common/todos/storage/__init__.py +14 -0
  320. autocoder/common/todos/storage/base_storage.py +76 -0
  321. autocoder/common/todos/storage/file_storage.py +278 -0
  322. autocoder/common/tokens/__init__.py +15 -0
  323. autocoder/common/tokens/counter.py +44 -2
  324. autocoder/common/tools_manager/__init__.py +17 -0
  325. autocoder/common/tools_manager/examples.py +162 -0
  326. autocoder/common/tools_manager/manager.py +385 -0
  327. autocoder/common/tools_manager/models.py +39 -0
  328. autocoder/common/tools_manager/test_tools_manager.py +303 -0
  329. autocoder/common/tools_manager/utils.py +191 -0
  330. autocoder/common/v2/agent/agentic_callbacks.py +270 -0
  331. autocoder/common/v2/agent/agentic_edit.py +2729 -2052
  332. autocoder/common/v2/agent/agentic_edit_change_manager.py +474 -0
  333. autocoder/common/v2/agent/agentic_edit_tools/__init__.py +43 -2
  334. autocoder/common/v2/agent/agentic_edit_tools/ac_mod_list_tool_resolver.py +279 -0
  335. autocoder/common/v2/agent/agentic_edit_tools/ac_mod_read_tool_resolver.py +40 -0
  336. autocoder/common/v2/agent/agentic_edit_tools/ac_mod_write_tool_resolver.py +52 -0
  337. autocoder/common/v2/agent/agentic_edit_tools/ask_followup_question_tool_resolver.py +8 -0
  338. autocoder/common/v2/agent/agentic_edit_tools/background_task_tool_resolver.py +1167 -0
  339. autocoder/common/v2/agent/agentic_edit_tools/base_tool_resolver.py +2 -2
  340. autocoder/common/v2/agent/agentic_edit_tools/conversation_message_ids_read_tool_resolver.py +214 -0
  341. autocoder/common/v2/agent/agentic_edit_tools/conversation_message_ids_write_tool_resolver.py +299 -0
  342. autocoder/common/v2/agent/agentic_edit_tools/count_tokens_tool_resolver.py +290 -0
  343. autocoder/common/v2/agent/agentic_edit_tools/execute_command_tool_resolver.py +565 -30
  344. autocoder/common/v2/agent/agentic_edit_tools/execute_workflow_tool_resolver.py +485 -0
  345. autocoder/common/v2/agent/agentic_edit_tools/extract_to_text_tool_resolver.py +225 -0
  346. autocoder/common/v2/agent/agentic_edit_tools/lint_report.py +79 -0
  347. autocoder/common/v2/agent/agentic_edit_tools/linter_config_models.py +343 -0
  348. autocoder/common/v2/agent/agentic_edit_tools/linter_enabled_tool_resolver.py +189 -0
  349. autocoder/common/v2/agent/agentic_edit_tools/list_files_tool_resolver.py +169 -101
  350. autocoder/common/v2/agent/agentic_edit_tools/load_extra_document_tool_resolver.py +349 -0
  351. autocoder/common/v2/agent/agentic_edit_tools/read_file_tool_resolver.py +244 -51
  352. autocoder/common/v2/agent/agentic_edit_tools/replace_in_file_tool_resolver.py +667 -147
  353. autocoder/common/v2/agent/agentic_edit_tools/run_named_subagents_tool_resolver.py +691 -0
  354. autocoder/common/v2/agent/agentic_edit_tools/search_files_tool_resolver.py +409 -140
  355. autocoder/common/v2/agent/agentic_edit_tools/session_interactive_tool_resolver.py +115 -0
  356. autocoder/common/v2/agent/agentic_edit_tools/session_start_tool_resolver.py +190 -0
  357. autocoder/common/v2/agent/agentic_edit_tools/session_stop_tool_resolver.py +76 -0
  358. autocoder/common/v2/agent/agentic_edit_tools/test_write_to_file_tool_resolver.py +209 -194
  359. autocoder/common/v2/agent/agentic_edit_tools/todo_read_tool_resolver.py +135 -0
  360. autocoder/common/v2/agent/agentic_edit_tools/todo_write_tool_resolver.py +328 -0
  361. autocoder/common/v2/agent/agentic_edit_tools/use_mcp_tool_resolver.py +2 -2
  362. autocoder/common/v2/agent/agentic_edit_tools/web_crawl_tool_resolver.py +557 -0
  363. autocoder/common/v2/agent/agentic_edit_tools/web_search_tool_resolver.py +600 -0
  364. autocoder/common/v2/agent/agentic_edit_tools/write_to_file_tool_resolver.py +56 -121
  365. autocoder/common/v2/agent/agentic_edit_types.py +386 -10
  366. autocoder/common/v2/agent/runner/__init__.py +31 -0
  367. autocoder/common/v2/agent/runner/base_runner.py +92 -0
  368. autocoder/common/v2/agent/runner/file_based_event_runner.py +217 -0
  369. autocoder/common/v2/agent/runner/sdk_runner.py +182 -0
  370. autocoder/common/v2/agent/runner/terminal_runner.py +396 -0
  371. autocoder/common/v2/agent/runner/tool_display.py +589 -0
  372. autocoder/common/v2/agent/test_agentic_callbacks.py +265 -0
  373. autocoder/common/v2/agent/test_agentic_edit.py +194 -0
  374. autocoder/common/v2/agent/tool_caller/__init__.py +24 -0
  375. autocoder/common/v2/agent/tool_caller/default_tool_resolver_map.py +135 -0
  376. autocoder/common/v2/agent/tool_caller/integration_test.py +172 -0
  377. autocoder/common/v2/agent/tool_caller/plugins/__init__.py +14 -0
  378. autocoder/common/v2/agent/tool_caller/plugins/base_plugin.py +126 -0
  379. autocoder/common/v2/agent/tool_caller/plugins/examples/__init__.py +13 -0
  380. autocoder/common/v2/agent/tool_caller/plugins/examples/logging_plugin.py +164 -0
  381. autocoder/common/v2/agent/tool_caller/plugins/examples/security_filter_plugin.py +198 -0
  382. autocoder/common/v2/agent/tool_caller/plugins/plugin_interface.py +141 -0
  383. autocoder/common/v2/agent/tool_caller/test_tool_caller.py +278 -0
  384. autocoder/common/v2/agent/tool_caller/tool_call_plugin_manager.py +331 -0
  385. autocoder/common/v2/agent/tool_caller/tool_caller.py +337 -0
  386. autocoder/common/v2/agent/tool_caller/usage_example.py +193 -0
  387. autocoder/common/v2/code_agentic_editblock_manager.py +4 -4
  388. autocoder/common/v2/code_auto_generate.py +136 -78
  389. autocoder/common/v2/code_auto_generate_diff.py +135 -79
  390. autocoder/common/v2/code_auto_generate_editblock.py +174 -99
  391. autocoder/common/v2/code_auto_generate_strict_diff.py +151 -71
  392. autocoder/common/v2/code_auto_merge.py +1 -1
  393. autocoder/common/v2/code_auto_merge_editblock.py +13 -1
  394. autocoder/common/v2/code_diff_manager.py +3 -3
  395. autocoder/common/v2/code_editblock_manager.py +4 -14
  396. autocoder/common/v2/code_manager.py +1 -1
  397. autocoder/common/v2/code_strict_diff_manager.py +2 -2
  398. autocoder/common/wrap_llm_hint/__init__.py +10 -0
  399. autocoder/common/wrap_llm_hint/test_wrap_llm_hint.py +1067 -0
  400. autocoder/common/wrap_llm_hint/utils.py +432 -0
  401. autocoder/common/wrap_llm_hint/wrap_llm_hint.py +323 -0
  402. autocoder/completer/__init__.py +8 -0
  403. autocoder/completer/command_completer_v2.py +1051 -0
  404. autocoder/default_project/__init__.py +501 -0
  405. autocoder/dispacher/__init__.py +4 -12
  406. autocoder/dispacher/actions/action.py +165 -7
  407. autocoder/dispacher/actions/plugins/action_regex_project.py +2 -2
  408. autocoder/index/entry.py +117 -125
  409. autocoder/{agent → index/filter}/agentic_filter.py +323 -334
  410. autocoder/index/filter/normal_filter.py +5 -11
  411. autocoder/index/filter/quick_filter.py +1 -1
  412. autocoder/index/index.py +36 -9
  413. autocoder/index/tests/__init__.py +1 -0
  414. autocoder/index/tests/run_tests.py +195 -0
  415. autocoder/index/tests/test_entry.py +303 -0
  416. autocoder/index/tests/test_index_manager.py +314 -0
  417. autocoder/index/tests/test_module_integration.py +300 -0
  418. autocoder/index/tests/test_symbols_utils.py +183 -0
  419. autocoder/inner/__init__.py +4 -0
  420. autocoder/inner/agentic.py +932 -0
  421. autocoder/inner/async_command_handler.py +992 -0
  422. autocoder/inner/conversation_command_handlers.py +623 -0
  423. autocoder/inner/merge_command_handler.py +213 -0
  424. autocoder/inner/queue_command_handler.py +684 -0
  425. autocoder/models.py +95 -266
  426. autocoder/plugins/git_helper_plugin.py +31 -29
  427. autocoder/plugins/token_helper_plugin.py +156 -37
  428. autocoder/pyproject/__init__.py +32 -29
  429. autocoder/rag/agentic_rag.py +215 -75
  430. autocoder/rag/cache/simple_cache.py +1 -2
  431. autocoder/rag/loaders/image_loader.py +1 -1
  432. autocoder/rag/long_context_rag.py +42 -26
  433. autocoder/rag/qa_conversation_strategy.py +1 -1
  434. autocoder/rag/terminal/__init__.py +17 -0
  435. autocoder/rag/terminal/args.py +581 -0
  436. autocoder/rag/terminal/bootstrap.py +61 -0
  437. autocoder/rag/terminal/command_handlers.py +653 -0
  438. autocoder/rag/terminal/formatters/__init__.py +20 -0
  439. autocoder/rag/terminal/formatters/base.py +70 -0
  440. autocoder/rag/terminal/formatters/json_format.py +66 -0
  441. autocoder/rag/terminal/formatters/stream_json.py +95 -0
  442. autocoder/rag/terminal/formatters/text.py +28 -0
  443. autocoder/rag/terminal/init.py +120 -0
  444. autocoder/rag/terminal/utils.py +106 -0
  445. autocoder/rag/test_agentic_rag.py +389 -0
  446. autocoder/rag/test_doc_filter.py +3 -3
  447. autocoder/rag/test_long_context_rag.py +1 -1
  448. autocoder/rag/test_token_limiter.py +517 -10
  449. autocoder/rag/token_counter.py +3 -0
  450. autocoder/rag/token_limiter.py +19 -15
  451. autocoder/rag/tools/__init__.py +26 -2
  452. autocoder/rag/tools/bochaai_example.py +343 -0
  453. autocoder/rag/tools/bochaai_sdk.py +541 -0
  454. autocoder/rag/tools/metaso_example.py +268 -0
  455. autocoder/rag/tools/metaso_sdk.py +417 -0
  456. autocoder/rag/tools/recall_tool.py +28 -7
  457. autocoder/rag/tools/run_integration_tests.py +204 -0
  458. autocoder/rag/tools/test_all_providers.py +318 -0
  459. autocoder/rag/tools/test_bochaai_integration.py +482 -0
  460. autocoder/rag/tools/test_final_integration.py +215 -0
  461. autocoder/rag/tools/test_metaso_integration.py +424 -0
  462. autocoder/rag/tools/test_metaso_real.py +171 -0
  463. autocoder/rag/tools/test_web_crawl_tool.py +639 -0
  464. autocoder/rag/tools/test_web_search_tool.py +509 -0
  465. autocoder/rag/tools/todo_read_tool.py +202 -0
  466. autocoder/rag/tools/todo_write_tool.py +412 -0
  467. autocoder/rag/tools/web_crawl_tool.py +634 -0
  468. autocoder/rag/tools/web_search_tool.py +558 -0
  469. autocoder/rag/tools/web_tools_example.py +119 -0
  470. autocoder/rag/types.py +16 -0
  471. autocoder/rag/variable_holder.py +4 -2
  472. autocoder/rags.py +86 -79
  473. autocoder/regexproject/__init__.py +23 -21
  474. autocoder/run_context.py +9 -0
  475. autocoder/sdk/__init__.py +50 -161
  476. autocoder/sdk/api.py +370 -0
  477. autocoder/sdk/async_runner/__init__.py +26 -0
  478. autocoder/sdk/async_runner/async_executor.py +650 -0
  479. autocoder/sdk/async_runner/async_handler.py +356 -0
  480. autocoder/sdk/async_runner/markdown_processor.py +595 -0
  481. autocoder/sdk/async_runner/task_metadata.py +284 -0
  482. autocoder/sdk/async_runner/worktree_manager.py +438 -0
  483. autocoder/sdk/cli/__init__.py +2 -5
  484. autocoder/sdk/cli/formatters.py +28 -204
  485. autocoder/sdk/cli/handlers.py +77 -44
  486. autocoder/sdk/cli/main.py +158 -170
  487. autocoder/sdk/cli/options.py +95 -22
  488. autocoder/sdk/constants.py +139 -51
  489. autocoder/sdk/core/auto_coder_core.py +484 -267
  490. autocoder/sdk/core/bridge.py +298 -118
  491. autocoder/sdk/exceptions.py +18 -12
  492. autocoder/sdk/formatters/__init__.py +19 -0
  493. autocoder/sdk/formatters/input.py +64 -0
  494. autocoder/sdk/formatters/output.py +247 -0
  495. autocoder/sdk/formatters/stream.py +54 -0
  496. autocoder/sdk/models/__init__.py +6 -5
  497. autocoder/sdk/models/options.py +55 -18
  498. autocoder/sdk/utils/formatters.py +27 -195
  499. autocoder/suffixproject/__init__.py +28 -25
  500. autocoder/terminal/__init__.py +14 -0
  501. autocoder/terminal/app.py +454 -0
  502. autocoder/terminal/args.py +32 -0
  503. autocoder/terminal/bootstrap.py +178 -0
  504. autocoder/terminal/command_processor.py +521 -0
  505. autocoder/terminal/command_registry.py +57 -0
  506. autocoder/terminal/help.py +97 -0
  507. autocoder/terminal/tasks/__init__.py +5 -0
  508. autocoder/terminal/tasks/background.py +77 -0
  509. autocoder/terminal/tasks/task_event.py +70 -0
  510. autocoder/terminal/ui/__init__.py +13 -0
  511. autocoder/terminal/ui/completer.py +268 -0
  512. autocoder/terminal/ui/keybindings.py +75 -0
  513. autocoder/terminal/ui/session.py +41 -0
  514. autocoder/terminal/ui/toolbar.py +64 -0
  515. autocoder/terminal/utils/__init__.py +13 -0
  516. autocoder/terminal/utils/errors.py +18 -0
  517. autocoder/terminal/utils/paths.py +19 -0
  518. autocoder/terminal/utils/shell.py +43 -0
  519. autocoder/terminal_v3/__init__.py +10 -0
  520. autocoder/terminal_v3/app.py +201 -0
  521. autocoder/terminal_v3/handlers/__init__.py +5 -0
  522. autocoder/terminal_v3/handlers/command_handler.py +131 -0
  523. autocoder/terminal_v3/models/__init__.py +6 -0
  524. autocoder/terminal_v3/models/conversation_buffer.py +214 -0
  525. autocoder/terminal_v3/models/message.py +50 -0
  526. autocoder/terminal_v3/models/tool_display.py +247 -0
  527. autocoder/terminal_v3/ui/__init__.py +7 -0
  528. autocoder/terminal_v3/ui/keybindings.py +56 -0
  529. autocoder/terminal_v3/ui/layout.py +141 -0
  530. autocoder/terminal_v3/ui/styles.py +43 -0
  531. autocoder/tsproject/__init__.py +23 -23
  532. autocoder/utils/auto_coder_utils/chat_stream_out.py +1 -1
  533. autocoder/utils/llms.py +88 -80
  534. autocoder/utils/math_utils.py +101 -0
  535. autocoder/utils/model_provider_selector.py +16 -4
  536. autocoder/utils/operate_config_api.py +33 -5
  537. autocoder/utils/thread_utils.py +2 -2
  538. autocoder/version.py +4 -2
  539. autocoder/workflow_agents/__init__.py +84 -0
  540. autocoder/workflow_agents/agent.py +143 -0
  541. autocoder/workflow_agents/exceptions.py +573 -0
  542. autocoder/workflow_agents/executor.py +489 -0
  543. autocoder/workflow_agents/loader.py +737 -0
  544. autocoder/workflow_agents/runner.py +267 -0
  545. autocoder/workflow_agents/types.py +172 -0
  546. autocoder/workflow_agents/utils.py +434 -0
  547. autocoder/workflow_agents/workflow_manager.py +211 -0
  548. auto_coder-0.1.400.dist-info/METADATA +0 -396
  549. auto_coder-0.1.400.dist-info/RECORD +0 -425
  550. auto_coder-0.1.400.dist-info/licenses/LICENSE +0 -201
  551. autocoder/auto_coder_server.py +0 -672
  552. autocoder/benchmark.py +0 -138
  553. autocoder/common/ac_style_command_parser/example.py +0 -7
  554. autocoder/common/cleaner.py +0 -31
  555. autocoder/common/command_completer_v2.py +0 -615
  556. autocoder/common/directory_cache/__init__.py +0 -1
  557. autocoder/common/directory_cache/cache.py +0 -192
  558. autocoder/common/directory_cache/test_cache.py +0 -190
  559. autocoder/common/file_checkpoint/examples.py +0 -217
  560. autocoder/common/llm_friendly_package_example.py +0 -138
  561. autocoder/common/llm_friendly_package_test.py +0 -63
  562. autocoder/common/pull_requests/test_module.py +0 -1
  563. autocoder/common/rulefiles/autocoderrules_utils.py +0 -484
  564. autocoder/common/text.py +0 -30
  565. autocoder/common/v2/agent/agentic_edit_tools/list_package_info_tool_resolver.py +0 -42
  566. autocoder/common/v2/agent/agentic_edit_tools/test_execute_command_tool_resolver.py +0 -70
  567. autocoder/common/v2/agent/agentic_edit_tools/test_search_files_tool_resolver.py +0 -163
  568. autocoder/common/v2/agent/agentic_tool_display.py +0 -183
  569. autocoder/plugins/dynamic_completion_example.py +0 -148
  570. autocoder/plugins/sample_plugin.py +0 -160
  571. autocoder/sdk/cli/__main__.py +0 -26
  572. autocoder/sdk/cli/completion_wrapper.py +0 -38
  573. autocoder/sdk/cli/install_completion.py +0 -301
  574. autocoder/sdk/models/messages.py +0 -209
  575. autocoder/sdk/session/__init__.py +0 -32
  576. autocoder/sdk/session/session.py +0 -106
  577. autocoder/sdk/session/session_manager.py +0 -56
  578. {auto_coder-0.1.400.dist-info → auto_coder-2.0.0.dist-info}/top_level.txt +0 -0
  579. /autocoder/{sdk/example.py → common/agent_query_queue/__init__.py} +0 -0
@@ -1,7 +1,6 @@
1
1
  import os
2
2
  import yaml
3
3
  import hashlib
4
- import git
5
4
  from typing import List, Dict, Tuple, Optional, Union, Any
6
5
  from loguru import logger
7
6
  from autocoder.common.git_utils import get_repo
@@ -9,6 +8,16 @@ from autocoder.common.printer import Printer
9
8
  import byzerllm
10
9
  from autocoder.common import git_utils
11
10
 
11
+ # 延迟导入git模块,避免启动时的导入错误
12
+ def _get_git_module():
13
+ """延迟导入git模块"""
14
+ try:
15
+ import git
16
+ return git, True
17
+ except ImportError as e:
18
+ logger.warning(f"Git module not available: {e}. Some git features will be disabled.")
19
+ return None, False
20
+
12
21
  class ActionYmlFileManager:
13
22
  """
14
23
  Actions 目录文件操作工具类,用于抽象和管理 actions 目录下的 YAML 文件操作。
@@ -226,12 +235,9 @@ class ActionYmlFileManager:
226
235
 
227
236
  try:
228
237
  with open(yaml_path, 'w', encoding='utf-8') as f:
229
- yaml.dump(content, f, allow_unicode=True, default_flow_style=False)
230
- self.printer.print_in_terminal("yaml_update_success", style="green", yaml_file=yaml_path)
238
+ yaml.dump(content, f, allow_unicode=True, default_flow_style=False)
231
239
  return True
232
- except Exception as e:
233
- self.printer.print_in_terminal("yaml_save_error", style="red",
234
- yaml_file=yaml_path, error=str(e))
240
+ except Exception as e:
235
241
  return False
236
242
 
237
243
  def update_yaml_field(self, file_name: str, field: str, value: Any) -> bool:
@@ -365,9 +371,14 @@ class ActionYmlFileManager:
365
371
  return [(query, urls, {})]
366
372
 
367
373
  changes = {}
374
+ git_module, git_available = _get_git_module()
375
+ if not git_available:
376
+ self.printer.print_in_terminal("git_not_available", style="yellow")
377
+ return [(query, urls, {})]
378
+
368
379
  try:
369
- repo = git.Repo(self.source_dir)
370
- commit =repo.commit(commit_id)
380
+ repo = git_module.Repo(self.source_dir)
381
+ commit = repo.commit(commit_id)
371
382
  if commit.parents:
372
383
  parent = commit.parents[0]
373
384
  # 获取所有文件的前后内容
@@ -379,7 +390,7 @@ class ActionYmlFileManager:
379
390
  try:
380
391
  if diff_item.a_blob:
381
392
  before_content = repo.git.show(f"{parent.hexsha}:{file_path}")
382
- except git.exc.GitCommandError:
393
+ except git_module.exc.GitCommandError:
383
394
  pass # 文件可能是新增的
384
395
 
385
396
  # 获取变更后内容
@@ -387,15 +398,16 @@ class ActionYmlFileManager:
387
398
  try:
388
399
  if diff_item.b_blob:
389
400
  after_content = repo.git.show(f"{commit.hexsha}:{file_path}")
390
- except git.exc.GitCommandError:
401
+ except git_module.exc.GitCommandError:
391
402
  pass # 文件可能被删除
392
403
 
393
404
  changes[file_path] = (before_content, after_content)
394
405
  break
395
- except git.exc.GitCommandError as e:
396
- self.printer.print_in_terminal("git_command_error", style="red", error=str(e))
397
406
  except Exception as e:
398
- self.printer.print_in_terminal("get_commit_changes_error", style="red", error=str(e))
407
+ if git_module and hasattr(git_module.exc, 'GitCommandError') and isinstance(e, git_module.exc.GitCommandError):
408
+ self.printer.print_in_terminal("git_command_error", style="red", error=str(e))
409
+ else:
410
+ self.printer.print_in_terminal("get_commit_changes_error", style="red", error=str(e))
399
411
 
400
412
  return [(query, urls, changes)]
401
413
 
@@ -0,0 +1,52 @@
1
+ """
2
+ Agent Events Module
3
+
4
+ A comprehensive event handling system for auto-coder agents with support for
5
+ event emission, subscription, filtering, and processing.
6
+ """
7
+
8
+ from .types import (
9
+ EventType,
10
+ EventMessage,
11
+ EventHandler,
12
+ EventListener,
13
+ EventMetrics,
14
+ EventEmitterConfig,
15
+ EventContext
16
+ )
17
+
18
+ from .event_factory import EventFactory
19
+ from .agent_event_emitter import AgentEventEmitter
20
+ from .utils import (
21
+ create_event_system,
22
+ create_pre_tool_use_event,
23
+ create_post_tool_use_event,
24
+ create_error_occurred_event,
25
+ create_conversation_start_event,
26
+ create_conversation_end_event,
27
+ create_custom_event
28
+ )
29
+
30
+ __all__ = [
31
+ # Types
32
+ 'EventType',
33
+ 'EventMessage',
34
+ 'EventHandler',
35
+ 'EventListener',
36
+ 'EventMetrics',
37
+ 'EventEmitterConfig',
38
+ 'EventContext',
39
+
40
+ # Core classes
41
+ 'EventFactory',
42
+ 'AgentEventEmitter',
43
+
44
+ # Utility functions
45
+ 'create_event_system',
46
+ 'create_pre_tool_use_event',
47
+ 'create_post_tool_use_event',
48
+ 'create_error_occurred_event',
49
+ 'create_conversation_start_event',
50
+ 'create_conversation_end_event',
51
+ 'create_custom_event'
52
+ ]
@@ -0,0 +1,193 @@
1
+ """
2
+ Core event emitter for agent events with support for filtering, metrics, and error handling.
3
+ """
4
+
5
+ import asyncio
6
+ import time
7
+ from collections import defaultdict
8
+ from typing import Dict, List, Optional, Set, Callable
9
+ from loguru import logger
10
+
11
+ from autocoder.common.async_utils import AsyncSyncMixin, run_async_in_sync
12
+ from .types import (
13
+ EventMessage, EventType, EventHandler, EventListener,
14
+ EventMetrics, EventEmitterConfig, EventFilter
15
+ )
16
+
17
+
18
+ class AgentEventEmitter(AsyncSyncMixin):
19
+ """
20
+ Core event emitter for agent events.
21
+
22
+ Provides both async and sync methods for all operations.
23
+ Sync methods are automatically generated with a '_sync' suffix.
24
+ """
25
+
26
+ def __init__(self, config: Optional[EventEmitterConfig] = None):
27
+ """Initialize the event emitter."""
28
+ self.config = config or EventEmitterConfig()
29
+ self._listeners: Dict[EventType, List[EventListener]] = defaultdict(list)
30
+ self._metrics = EventMetrics()
31
+ self._lock = asyncio.Lock()
32
+
33
+ def on(self, event_type: EventType, handler: EventHandler) -> None:
34
+ """Register an event handler for the specified event type."""
35
+ self.add_listener(event_type, handler)
36
+
37
+ def once(self, event_type: EventType, handler: EventHandler) -> None:
38
+ """Register a one-time event handler."""
39
+ self.add_listener(event_type, handler, once=True)
40
+
41
+ def off(self, event_type: EventType, handler: EventHandler) -> bool:
42
+ """Remove an event handler."""
43
+ listeners = self._listeners.get(event_type, [])
44
+ for i, listener in enumerate(listeners):
45
+ if listener.handler == handler:
46
+ del listeners[i]
47
+ self._metrics.total_handlers -= 1
48
+ return True
49
+ return False
50
+
51
+ def add_listener(self, event_type: EventType, handler: EventHandler,
52
+ filter: Optional[EventFilter] = None, once: bool = False) -> None:
53
+ """Add an event listener with advanced options."""
54
+ if len(self._listeners[event_type]) >= self.config.max_listeners:
55
+ logger.warning(f"Max listeners ({self.config.max_listeners}) reached for {event_type}")
56
+ return
57
+
58
+ listener = EventListener(handler=handler, filter=filter, once=once)
59
+ self._listeners[event_type].append(listener)
60
+ self._metrics.total_handlers += 1
61
+
62
+ if self.config.enable_logging:
63
+ logger.info(f"Added listener for {event_type} (once={once}, filtered={filter is not None})")
64
+
65
+ def remove_listener(self, event_type: EventType, handler: EventHandler) -> bool:
66
+ """Remove a specific event listener."""
67
+ return self.off(event_type, handler)
68
+
69
+ def remove_all_listeners(self, event_type: Optional[EventType] = None) -> None:
70
+ """Remove all listeners for a specific event type or all events."""
71
+ if event_type:
72
+ count = len(self._listeners.get(event_type, []))
73
+ self._listeners[event_type] = []
74
+ self._metrics.total_handlers -= count
75
+ else:
76
+ total_removed = sum(len(listeners) for listeners in self._listeners.values())
77
+ self._listeners.clear()
78
+ self._metrics.total_handlers -= total_removed
79
+
80
+ if self.config.enable_logging:
81
+ logger.info(f"Removed all listeners for {event_type or 'all events'}")
82
+
83
+ def listener_count(self, event_type: EventType) -> int:
84
+ """Get the number of listeners for an event type."""
85
+ return len(self._listeners.get(event_type, []))
86
+
87
+ async def emit(self, event_message: EventMessage) -> None:
88
+ """Emit an event to all registered handlers."""
89
+ start_time = time.time()
90
+ event_type = event_message.event_type
91
+
92
+ if self.config.enable_logging:
93
+ logger.info(f"Emitting event: {event_type} ({event_message.event_id})")
94
+
95
+ # Get listeners for this event type (copy to avoid modification during iteration)
96
+ listeners = self._listeners.get(event_type, []).copy()
97
+
98
+ # Track listeners to remove (once handlers)
99
+ to_remove = []
100
+
101
+ # Process each listener
102
+ for listener in listeners:
103
+ try:
104
+ # Apply filter if present
105
+ if listener.filter and not listener.filter(event_message):
106
+ continue
107
+
108
+ # Execute handler
109
+ await listener.handler(event_message)
110
+
111
+ # Mark once handlers for removal
112
+ if listener.once:
113
+ to_remove.append((event_type, listener))
114
+
115
+ except Exception as e:
116
+ self._metrics.error_count += 1
117
+ error_msg = f"Error in event handler for {event_type}: {e}"
118
+ logger.error(error_msg)
119
+
120
+ if self.config.error_handler:
121
+ try:
122
+ self.config.error_handler(e, event_type)
123
+ except Exception as handler_error:
124
+ logger.error(f"Error in error handler: {handler_error}")
125
+
126
+ # Remove once handlers
127
+ async with self._lock:
128
+ for event_type_remove, listener_remove in to_remove:
129
+ try:
130
+ self._listeners[event_type_remove].remove(listener_remove)
131
+ self._metrics.total_handlers -= 1
132
+ except ValueError:
133
+ pass # Already removed
134
+
135
+ # Process with hook manager if available
136
+ if self.config.hook_manager:
137
+ try:
138
+ # Hook manager process_event is always async, so we await it
139
+ await self.config.hook_manager.process_event(event_message)
140
+ except Exception as e:
141
+ logger.error(f"Error in hook manager: {e}")
142
+
143
+ # Update metrics
144
+ processing_time = time.time() - start_time
145
+ self._metrics.total_events += 1
146
+ self._metrics.total_processing_time += processing_time
147
+
148
+ # Update handler count metrics
149
+ event_type_str = event_type.value
150
+ self._metrics.handler_counts[event_type_str] = self._metrics.handler_counts.get(event_type_str, 0) + len(listeners)
151
+
152
+ if self.config.enable_logging:
153
+ logger.info(f"Event {event_type} processed in {processing_time:.3f}s")
154
+
155
+ # The emit_sync method is automatically provided by AsyncSyncMixin
156
+
157
+ async def wait_for_event(self, event_type: EventType, timeout: Optional[float] = None,
158
+ filter: Optional[EventFilter] = None) -> Optional[EventMessage]:
159
+ """Wait for a specific event to be emitted."""
160
+ future = asyncio.Future()
161
+
162
+ async def handler(event_message: EventMessage):
163
+ if not future.done():
164
+ future.set_result(event_message)
165
+
166
+ # Add temporary listener
167
+ self.add_listener(event_type, handler, filter=filter, once=True)
168
+
169
+ try:
170
+ if timeout:
171
+ return await asyncio.wait_for(future, timeout=timeout)
172
+ else:
173
+ return await future
174
+ except asyncio.TimeoutError:
175
+ # Remove the listener if timeout occurs
176
+ self.off(event_type, handler)
177
+ return None
178
+
179
+ def get_metrics(self) -> EventMetrics:
180
+ """Get event processing metrics."""
181
+ return self._metrics
182
+
183
+ def reset_metrics(self) -> None:
184
+ """Reset event processing metrics."""
185
+ self._metrics = EventMetrics()
186
+
187
+ def list_event_types(self) -> List[EventType]:
188
+ """Get all event types that have listeners."""
189
+ return list(self._listeners.keys())
190
+
191
+ def get_listeners(self, event_type: EventType) -> List[EventListener]:
192
+ """Get all listeners for a specific event type."""
193
+ return self._listeners.get(event_type, []).copy()
@@ -0,0 +1,177 @@
1
+ """
2
+ Event Factory for creating typed events with proper context management.
3
+ """
4
+
5
+ import time
6
+ from typing import Dict, Any, Optional
7
+ from .types import EventMessage, EventType, EventContext
8
+
9
+ class EventFactory:
10
+ """Factory for creating typed events with context management."""
11
+
12
+ def __init__(self, default_context: Optional[EventContext] = None):
13
+ """Initialize factory with optional default context."""
14
+ self.default_context = default_context
15
+
16
+ @classmethod
17
+ def create_with_context(cls, context: EventContext) -> 'EventFactory':
18
+ """Create a factory with default context."""
19
+ return cls(default_context=context)
20
+
21
+ def set_default_context(self, context: EventContext) -> None:
22
+ """Set default context for all events created by this factory."""
23
+ self.default_context = context
24
+
25
+ def _create_event(self, event_type: EventType, content: Dict[str, Any],
26
+ context: Optional[EventContext] = None) -> EventMessage:
27
+ """Create an event with proper context inheritance."""
28
+ # Merge contexts - specific context overrides default
29
+ final_context = self.default_context
30
+ if context:
31
+ if final_context:
32
+ # Merge contexts
33
+ final_context = EventContext(
34
+ agent_id=context.agent_id or final_context.agent_id,
35
+ conversation_id=context.conversation_id or final_context.conversation_id,
36
+ metadata={**(final_context.metadata or {}), **(context.metadata or {})}
37
+ )
38
+ else:
39
+ final_context = context
40
+
41
+ return EventMessage(
42
+ event_type=event_type,
43
+ content=content,
44
+ context=final_context
45
+ )
46
+
47
+ def create_pre_tool_use_event(self, tool_name: str, tool_input: Dict[str, Any],
48
+ context: Optional[EventContext] = None) -> EventMessage:
49
+ """Create a PreToolUse event."""
50
+ content = {
51
+ 'tool_name': tool_name,
52
+ 'tool_input': tool_input,
53
+ 'timestamp': time.time()
54
+ }
55
+ return self._create_event(EventType.PRE_TOOL_USE, content, context)
56
+
57
+ def create_post_tool_use_event(self, tool_name: str, tool_input: Dict[str, Any],
58
+ tool_output: Any, success: bool,
59
+ execution_time_ms: Optional[float] = None,
60
+ context: Optional[EventContext] = None) -> EventMessage:
61
+ """Create a PostToolUse event."""
62
+ content = {
63
+ 'tool_name': tool_name,
64
+ 'tool_input': tool_input,
65
+ 'tool_output': tool_output,
66
+ 'success': success,
67
+ 'timestamp': time.time()
68
+ }
69
+ if execution_time_ms is not None:
70
+ content['execution_time_ms'] = execution_time_ms
71
+
72
+ return self._create_event(EventType.POST_TOOL_USE, content, context)
73
+
74
+ def create_error_occurred_event(self, error_type: str, error_message: str,
75
+ tool_name: Optional[str] = None,
76
+ stack_trace: Optional[str] = None,
77
+ context: Optional[EventContext] = None) -> EventMessage:
78
+ """Create an ErrorOccurred event."""
79
+ content = {
80
+ 'error_type': error_type,
81
+ 'error_message': error_message,
82
+ 'timestamp': time.time()
83
+ }
84
+ if tool_name:
85
+ content['tool_name'] = tool_name
86
+ if stack_trace:
87
+ content['stack_trace'] = stack_trace
88
+
89
+ return self._create_event(EventType.ERROR_OCCURRED, content, context)
90
+
91
+ def create_conversation_start_event(self, message_count: int = 0,
92
+ conversation_id: Optional[str] = None,
93
+ context: Optional[EventContext] = None) -> EventMessage:
94
+ """Create a ConversationStart event."""
95
+ content = {
96
+ 'message_count': message_count,
97
+ 'timestamp': time.time()
98
+ }
99
+ if conversation_id:
100
+ content['conversation_id'] = conversation_id
101
+
102
+ return self._create_event(EventType.CONVERSATION_START, content, context)
103
+
104
+ def create_conversation_end_event(self, did_complete_task: bool,
105
+ iteration_count: int = 0,
106
+ conversation_id: Optional[str] = None,
107
+ context: Optional[EventContext] = None) -> EventMessage:
108
+ """Create a ConversationEnd event."""
109
+ content = {
110
+ 'did_complete_task': did_complete_task,
111
+ 'iteration_count': iteration_count,
112
+ 'timestamp': time.time()
113
+ }
114
+ if conversation_id:
115
+ content['conversation_id'] = conversation_id
116
+
117
+ return self._create_event(EventType.CONVERSATION_END, content, context)
118
+
119
+ def create_tool_execution_event(self, tool_name: str, progress: float = 0.0,
120
+ status: str = "running",
121
+ context: Optional[EventContext] = None) -> EventMessage:
122
+ """Create a ToolExecution event."""
123
+ content = {
124
+ 'tool_name': tool_name,
125
+ 'progress': progress,
126
+ 'status': status,
127
+ 'timestamp': time.time()
128
+ }
129
+ return self._create_event(EventType.TOOL_EXECUTION, content, context)
130
+
131
+ def create_tool_request_approval_event(self, tool_name: str,
132
+ tool_input: Dict[str, Any],
133
+ reason: str = "",
134
+ context: Optional[EventContext] = None) -> EventMessage:
135
+ """Create a ToolRequestApproval event."""
136
+ content = {
137
+ 'tool_name': tool_name,
138
+ 'tool_input': tool_input,
139
+ 'reason': reason,
140
+ 'timestamp': time.time()
141
+ }
142
+ return self._create_event(EventType.TOOL_REQUEST_APPROVAL, content, context)
143
+
144
+ def create_mode_change_event(self, old_mode: str, new_mode: str,
145
+ context: Optional[EventContext] = None) -> EventMessage:
146
+ """Create a ModeChange event."""
147
+ content = {
148
+ 'old_mode': old_mode,
149
+ 'new_mode': new_mode,
150
+ 'timestamp': time.time()
151
+ }
152
+ return self._create_event(EventType.MODE_CHANGE, content, context)
153
+
154
+ def create_token_count_info_event(self, input_tokens: int, output_tokens: int,
155
+ total_tokens: int, model: Optional[str] = None,
156
+ context: Optional[EventContext] = None) -> EventMessage:
157
+ """Create a TokenCountInfo event."""
158
+ content = {
159
+ 'input_tokens': input_tokens,
160
+ 'output_tokens': output_tokens,
161
+ 'total_tokens': total_tokens,
162
+ 'timestamp': time.time()
163
+ }
164
+ if model:
165
+ content['model'] = model
166
+
167
+ return self._create_event(EventType.TOKEN_COUNT_INFO, content, context)
168
+
169
+ def create_custom_event(self, event_name: str, data: Dict[str, Any],
170
+ context: Optional[EventContext] = None) -> EventMessage:
171
+ """Create a custom event."""
172
+ content = {
173
+ 'event_name': event_name,
174
+ 'data': data,
175
+ 'timestamp': time.time()
176
+ }
177
+ return self._create_event(EventType.CUSTOM_EVENT, content, context)