autobyteus 1.2.1__py3-none-any.whl → 1.2.3__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.
Files changed (466) hide show
  1. autobyteus/agent/agent.py +15 -5
  2. autobyteus/agent/bootstrap_steps/__init__.py +1 -3
  3. autobyteus/agent/bootstrap_steps/agent_bootstrapper.py +3 -59
  4. autobyteus/agent/bootstrap_steps/base_bootstrap_step.py +1 -4
  5. autobyteus/agent/bootstrap_steps/mcp_server_prewarming_step.py +1 -3
  6. autobyteus/agent/bootstrap_steps/system_prompt_processing_step.py +16 -13
  7. autobyteus/agent/bootstrap_steps/workspace_context_initialization_step.py +2 -4
  8. autobyteus/agent/context/agent_config.py +43 -20
  9. autobyteus/agent/context/agent_context.py +23 -18
  10. autobyteus/agent/context/agent_runtime_state.py +19 -19
  11. autobyteus/agent/events/__init__.py +16 -1
  12. autobyteus/agent/events/agent_events.py +43 -3
  13. autobyteus/agent/events/agent_input_event_queue_manager.py +79 -26
  14. autobyteus/agent/events/event_store.py +57 -0
  15. autobyteus/agent/events/notifiers.py +69 -59
  16. autobyteus/agent/events/worker_event_dispatcher.py +21 -64
  17. autobyteus/agent/factory/agent_factory.py +52 -0
  18. autobyteus/agent/handlers/__init__.py +2 -0
  19. autobyteus/agent/handlers/approved_tool_invocation_event_handler.py +51 -34
  20. autobyteus/agent/handlers/bootstrap_event_handler.py +155 -0
  21. autobyteus/agent/handlers/inter_agent_message_event_handler.py +10 -0
  22. autobyteus/agent/handlers/lifecycle_event_logger.py +19 -11
  23. autobyteus/agent/handlers/llm_complete_response_received_event_handler.py +10 -15
  24. autobyteus/agent/handlers/llm_user_message_ready_event_handler.py +188 -48
  25. autobyteus/agent/handlers/tool_execution_approval_event_handler.py +0 -10
  26. autobyteus/agent/handlers/tool_invocation_request_event_handler.py +53 -48
  27. autobyteus/agent/handlers/tool_result_event_handler.py +7 -8
  28. autobyteus/agent/handlers/user_input_message_event_handler.py +10 -3
  29. autobyteus/agent/input_processor/memory_ingest_input_processor.py +40 -0
  30. autobyteus/agent/lifecycle/__init__.py +12 -0
  31. autobyteus/agent/lifecycle/base_processor.py +109 -0
  32. autobyteus/agent/lifecycle/events.py +35 -0
  33. autobyteus/agent/lifecycle/processor_definition.py +36 -0
  34. autobyteus/agent/lifecycle/processor_registry.py +106 -0
  35. autobyteus/agent/llm_request_assembler.py +98 -0
  36. autobyteus/agent/llm_response_processor/__init__.py +1 -8
  37. autobyteus/agent/message/context_file_type.py +1 -1
  38. autobyteus/agent/runtime/agent_runtime.py +29 -21
  39. autobyteus/agent/runtime/agent_worker.py +98 -19
  40. autobyteus/agent/shutdown_steps/__init__.py +2 -0
  41. autobyteus/agent/shutdown_steps/agent_shutdown_orchestrator.py +2 -0
  42. autobyteus/agent/shutdown_steps/tool_cleanup_step.py +58 -0
  43. autobyteus/agent/status/__init__.py +14 -0
  44. autobyteus/agent/status/manager.py +93 -0
  45. autobyteus/agent/status/status_deriver.py +96 -0
  46. autobyteus/agent/{phases/phase_enum.py → status/status_enum.py} +16 -16
  47. autobyteus/agent/status/status_update_utils.py +73 -0
  48. autobyteus/agent/streaming/__init__.py +52 -5
  49. autobyteus/agent/streaming/adapters/__init__.py +18 -0
  50. autobyteus/agent/streaming/adapters/invocation_adapter.py +184 -0
  51. autobyteus/agent/streaming/adapters/tool_call_parsing.py +163 -0
  52. autobyteus/agent/streaming/adapters/tool_syntax_registry.py +67 -0
  53. autobyteus/agent/streaming/agent_event_stream.py +3 -183
  54. autobyteus/agent/streaming/api_tool_call/__init__.py +16 -0
  55. autobyteus/agent/streaming/api_tool_call/file_content_streamer.py +56 -0
  56. autobyteus/agent/streaming/api_tool_call/json_string_field_extractor.py +175 -0
  57. autobyteus/agent/streaming/api_tool_call_streaming_response_handler.py +4 -0
  58. autobyteus/agent/streaming/events/__init__.py +6 -0
  59. autobyteus/agent/streaming/events/stream_event_payloads.py +284 -0
  60. autobyteus/agent/streaming/events/stream_events.py +141 -0
  61. autobyteus/agent/streaming/handlers/__init__.py +15 -0
  62. autobyteus/agent/streaming/handlers/api_tool_call_streaming_response_handler.py +303 -0
  63. autobyteus/agent/streaming/handlers/parsing_streaming_response_handler.py +107 -0
  64. autobyteus/agent/streaming/handlers/pass_through_streaming_response_handler.py +107 -0
  65. autobyteus/agent/streaming/handlers/streaming_handler_factory.py +177 -0
  66. autobyteus/agent/streaming/handlers/streaming_response_handler.py +58 -0
  67. autobyteus/agent/streaming/parser/__init__.py +61 -0
  68. autobyteus/agent/streaming/parser/event_emitter.py +181 -0
  69. autobyteus/agent/streaming/parser/events.py +4 -0
  70. autobyteus/agent/streaming/parser/invocation_adapter.py +4 -0
  71. autobyteus/agent/streaming/parser/json_parsing_strategies/__init__.py +19 -0
  72. autobyteus/agent/streaming/parser/json_parsing_strategies/base.py +32 -0
  73. autobyteus/agent/streaming/parser/json_parsing_strategies/default.py +34 -0
  74. autobyteus/agent/streaming/parser/json_parsing_strategies/gemini.py +31 -0
  75. autobyteus/agent/streaming/parser/json_parsing_strategies/openai.py +64 -0
  76. autobyteus/agent/streaming/parser/json_parsing_strategies/registry.py +75 -0
  77. autobyteus/agent/streaming/parser/parser_context.py +227 -0
  78. autobyteus/agent/streaming/parser/parser_factory.py +132 -0
  79. autobyteus/agent/streaming/parser/sentinel_format.py +7 -0
  80. autobyteus/agent/streaming/parser/state_factory.py +62 -0
  81. autobyteus/agent/streaming/parser/states/__init__.py +1 -0
  82. autobyteus/agent/streaming/parser/states/base_state.py +60 -0
  83. autobyteus/agent/streaming/parser/states/custom_xml_tag_run_bash_parsing_state.py +38 -0
  84. autobyteus/agent/streaming/parser/states/custom_xml_tag_write_file_parsing_state.py +55 -0
  85. autobyteus/agent/streaming/parser/states/delimited_content_state.py +146 -0
  86. autobyteus/agent/streaming/parser/states/json_initialization_state.py +144 -0
  87. autobyteus/agent/streaming/parser/states/json_tool_parsing_state.py +137 -0
  88. autobyteus/agent/streaming/parser/states/sentinel_content_state.py +30 -0
  89. autobyteus/agent/streaming/parser/states/sentinel_initialization_state.py +117 -0
  90. autobyteus/agent/streaming/parser/states/text_state.py +78 -0
  91. autobyteus/agent/streaming/parser/states/xml_patch_file_tool_parsing_state.py +328 -0
  92. autobyteus/agent/streaming/parser/states/xml_run_bash_tool_parsing_state.py +129 -0
  93. autobyteus/agent/streaming/parser/states/xml_tag_initialization_state.py +151 -0
  94. autobyteus/agent/streaming/parser/states/xml_tool_parsing_state.py +63 -0
  95. autobyteus/agent/streaming/parser/states/xml_write_file_tool_parsing_state.py +343 -0
  96. autobyteus/agent/streaming/parser/strategies/__init__.py +17 -0
  97. autobyteus/agent/streaming/parser/strategies/base.py +24 -0
  98. autobyteus/agent/streaming/parser/strategies/json_tool_strategy.py +26 -0
  99. autobyteus/agent/streaming/parser/strategies/registry.py +28 -0
  100. autobyteus/agent/streaming/parser/strategies/sentinel_strategy.py +23 -0
  101. autobyteus/agent/streaming/parser/strategies/xml_tag_strategy.py +21 -0
  102. autobyteus/agent/streaming/parser/stream_scanner.py +167 -0
  103. autobyteus/agent/streaming/parser/streaming_parser.py +212 -0
  104. autobyteus/agent/streaming/parser/tool_call_parsing.py +4 -0
  105. autobyteus/agent/streaming/parser/tool_constants.py +7 -0
  106. autobyteus/agent/streaming/parser/tool_syntax_registry.py +4 -0
  107. autobyteus/agent/streaming/parser/xml_tool_parsing_state_registry.py +55 -0
  108. autobyteus/agent/streaming/parsing_streaming_response_handler.py +4 -0
  109. autobyteus/agent/streaming/pass_through_streaming_response_handler.py +4 -0
  110. autobyteus/agent/streaming/queue_streamer.py +3 -57
  111. autobyteus/agent/streaming/segments/__init__.py +5 -0
  112. autobyteus/agent/streaming/segments/segment_events.py +81 -0
  113. autobyteus/agent/streaming/stream_event_payloads.py +2 -223
  114. autobyteus/agent/streaming/stream_events.py +3 -140
  115. autobyteus/agent/streaming/streaming_handler_factory.py +4 -0
  116. autobyteus/agent/streaming/streaming_response_handler.py +4 -0
  117. autobyteus/agent/streaming/streams/__init__.py +5 -0
  118. autobyteus/agent/streaming/streams/agent_event_stream.py +197 -0
  119. autobyteus/agent/streaming/utils/__init__.py +5 -0
  120. autobyteus/agent/streaming/utils/queue_streamer.py +59 -0
  121. autobyteus/agent/system_prompt_processor/__init__.py +2 -0
  122. autobyteus/agent/system_prompt_processor/available_skills_processor.py +96 -0
  123. autobyteus/agent/system_prompt_processor/base_processor.py +1 -1
  124. autobyteus/agent/system_prompt_processor/processor_meta.py +15 -2
  125. autobyteus/agent/system_prompt_processor/tool_manifest_injector_processor.py +39 -58
  126. autobyteus/agent/token_budget.py +56 -0
  127. autobyteus/agent/tool_execution_result_processor/memory_ingest_tool_result_processor.py +29 -0
  128. autobyteus/agent/tool_invocation.py +16 -40
  129. autobyteus/agent/tool_invocation_preprocessor/__init__.py +9 -0
  130. autobyteus/agent/tool_invocation_preprocessor/base_preprocessor.py +45 -0
  131. autobyteus/agent/tool_invocation_preprocessor/processor_definition.py +15 -0
  132. autobyteus/agent/tool_invocation_preprocessor/processor_meta.py +33 -0
  133. autobyteus/agent/tool_invocation_preprocessor/processor_registry.py +60 -0
  134. autobyteus/agent/utils/wait_for_idle.py +12 -14
  135. autobyteus/agent/workspace/base_workspace.py +6 -27
  136. autobyteus/agent_team/agent_team.py +3 -3
  137. autobyteus/agent_team/agent_team_builder.py +1 -41
  138. autobyteus/agent_team/bootstrap_steps/__init__.py +0 -4
  139. autobyteus/agent_team/bootstrap_steps/agent_configuration_preparation_step.py +8 -18
  140. autobyteus/agent_team/bootstrap_steps/agent_team_bootstrapper.py +4 -16
  141. autobyteus/agent_team/bootstrap_steps/base_agent_team_bootstrap_step.py +1 -2
  142. autobyteus/agent_team/bootstrap_steps/coordinator_initialization_step.py +1 -2
  143. autobyteus/agent_team/bootstrap_steps/task_notifier_initialization_step.py +1 -2
  144. autobyteus/agent_team/bootstrap_steps/team_context_initialization_step.py +4 -4
  145. autobyteus/agent_team/context/agent_team_config.py +6 -3
  146. autobyteus/agent_team/context/agent_team_context.py +25 -3
  147. autobyteus/agent_team/context/agent_team_runtime_state.py +9 -6
  148. autobyteus/agent_team/events/__init__.py +11 -0
  149. autobyteus/agent_team/events/agent_team_event_dispatcher.py +22 -9
  150. autobyteus/agent_team/events/agent_team_events.py +16 -0
  151. autobyteus/agent_team/events/event_store.py +57 -0
  152. autobyteus/agent_team/factory/agent_team_factory.py +8 -0
  153. autobyteus/agent_team/handlers/inter_agent_message_request_event_handler.py +18 -2
  154. autobyteus/agent_team/handlers/lifecycle_agent_team_event_handler.py +21 -5
  155. autobyteus/agent_team/handlers/process_user_message_event_handler.py +17 -8
  156. autobyteus/agent_team/handlers/tool_approval_team_event_handler.py +19 -4
  157. autobyteus/agent_team/runtime/agent_team_runtime.py +41 -10
  158. autobyteus/agent_team/runtime/agent_team_worker.py +69 -5
  159. autobyteus/agent_team/status/__init__.py +14 -0
  160. autobyteus/agent_team/status/agent_team_status.py +18 -0
  161. autobyteus/agent_team/status/agent_team_status_manager.py +33 -0
  162. autobyteus/agent_team/status/status_deriver.py +62 -0
  163. autobyteus/agent_team/status/status_update_utils.py +42 -0
  164. autobyteus/agent_team/streaming/__init__.py +2 -2
  165. autobyteus/agent_team/streaming/agent_team_event_notifier.py +6 -6
  166. autobyteus/agent_team/streaming/agent_team_stream_event_payloads.py +4 -4
  167. autobyteus/agent_team/streaming/agent_team_stream_events.py +3 -3
  168. autobyteus/agent_team/system_prompt_processor/__init__.py +6 -0
  169. autobyteus/agent_team/system_prompt_processor/team_manifest_injector_processor.py +76 -0
  170. autobyteus/agent_team/task_notification/task_notification_mode.py +19 -0
  171. autobyteus/agent_team/utils/wait_for_idle.py +4 -4
  172. autobyteus/cli/agent_cli.py +18 -10
  173. autobyteus/cli/agent_team_tui/app.py +14 -11
  174. autobyteus/cli/agent_team_tui/state.py +13 -15
  175. autobyteus/cli/agent_team_tui/widgets/agent_list_sidebar.py +15 -15
  176. autobyteus/cli/agent_team_tui/widgets/focus_pane.py +143 -36
  177. autobyteus/cli/agent_team_tui/widgets/renderables.py +1 -1
  178. autobyteus/cli/agent_team_tui/widgets/shared.py +25 -25
  179. autobyteus/cli/cli_display.py +193 -44
  180. autobyteus/cli/workflow_tui/app.py +9 -10
  181. autobyteus/cli/workflow_tui/state.py +14 -16
  182. autobyteus/cli/workflow_tui/widgets/agent_list_sidebar.py +15 -15
  183. autobyteus/cli/workflow_tui/widgets/focus_pane.py +137 -35
  184. autobyteus/cli/workflow_tui/widgets/renderables.py +1 -1
  185. autobyteus/cli/workflow_tui/widgets/shared.py +25 -25
  186. autobyteus/clients/autobyteus_client.py +94 -1
  187. autobyteus/events/event_types.py +11 -18
  188. autobyteus/llm/api/autobyteus_llm.py +33 -29
  189. autobyteus/llm/api/claude_llm.py +142 -36
  190. autobyteus/llm/api/gemini_llm.py +163 -59
  191. autobyteus/llm/api/grok_llm.py +1 -1
  192. autobyteus/llm/api/minimax_llm.py +26 -0
  193. autobyteus/llm/api/mistral_llm.py +113 -87
  194. autobyteus/llm/api/ollama_llm.py +9 -42
  195. autobyteus/llm/api/openai_compatible_llm.py +127 -91
  196. autobyteus/llm/api/openai_llm.py +3 -3
  197. autobyteus/llm/api/openai_responses_llm.py +324 -0
  198. autobyteus/llm/api/zhipu_llm.py +21 -2
  199. autobyteus/llm/autobyteus_provider.py +70 -60
  200. autobyteus/llm/base_llm.py +85 -81
  201. autobyteus/llm/converters/__init__.py +14 -0
  202. autobyteus/llm/converters/anthropic_tool_call_converter.py +37 -0
  203. autobyteus/llm/converters/gemini_tool_call_converter.py +57 -0
  204. autobyteus/llm/converters/mistral_tool_call_converter.py +37 -0
  205. autobyteus/llm/converters/openai_tool_call_converter.py +38 -0
  206. autobyteus/llm/extensions/base_extension.py +6 -12
  207. autobyteus/llm/extensions/token_usage_tracking_extension.py +45 -18
  208. autobyteus/llm/llm_factory.py +282 -204
  209. autobyteus/llm/lmstudio_provider.py +60 -49
  210. autobyteus/llm/models.py +35 -2
  211. autobyteus/llm/ollama_provider.py +60 -49
  212. autobyteus/llm/ollama_provider_resolver.py +0 -1
  213. autobyteus/llm/prompt_renderers/__init__.py +19 -0
  214. autobyteus/llm/prompt_renderers/anthropic_prompt_renderer.py +104 -0
  215. autobyteus/llm/prompt_renderers/autobyteus_prompt_renderer.py +19 -0
  216. autobyteus/llm/prompt_renderers/base_prompt_renderer.py +10 -0
  217. autobyteus/llm/prompt_renderers/gemini_prompt_renderer.py +63 -0
  218. autobyteus/llm/prompt_renderers/mistral_prompt_renderer.py +87 -0
  219. autobyteus/llm/prompt_renderers/ollama_prompt_renderer.py +51 -0
  220. autobyteus/llm/prompt_renderers/openai_chat_renderer.py +97 -0
  221. autobyteus/llm/prompt_renderers/openai_responses_renderer.py +101 -0
  222. autobyteus/llm/providers.py +1 -3
  223. autobyteus/llm/token_counter/claude_token_counter.py +56 -25
  224. autobyteus/llm/token_counter/mistral_token_counter.py +12 -8
  225. autobyteus/llm/token_counter/openai_token_counter.py +24 -5
  226. autobyteus/llm/token_counter/token_counter_factory.py +12 -5
  227. autobyteus/llm/utils/llm_config.py +6 -12
  228. autobyteus/llm/utils/media_payload_formatter.py +27 -20
  229. autobyteus/llm/utils/messages.py +55 -3
  230. autobyteus/llm/utils/response_types.py +3 -0
  231. autobyteus/llm/utils/tool_call_delta.py +31 -0
  232. autobyteus/memory/__init__.py +32 -0
  233. autobyteus/memory/active_transcript.py +69 -0
  234. autobyteus/memory/compaction/__init__.py +9 -0
  235. autobyteus/memory/compaction/compaction_result.py +8 -0
  236. autobyteus/memory/compaction/compactor.py +89 -0
  237. autobyteus/memory/compaction/summarizer.py +11 -0
  238. autobyteus/memory/compaction_snapshot_builder.py +84 -0
  239. autobyteus/memory/memory_manager.py +183 -0
  240. autobyteus/memory/models/__init__.py +14 -0
  241. autobyteus/memory/models/episodic_item.py +41 -0
  242. autobyteus/memory/models/memory_types.py +7 -0
  243. autobyteus/memory/models/raw_trace_item.py +79 -0
  244. autobyteus/memory/models/semantic_item.py +41 -0
  245. autobyteus/memory/models/tool_interaction.py +20 -0
  246. autobyteus/memory/policies/__init__.py +5 -0
  247. autobyteus/memory/policies/compaction_policy.py +16 -0
  248. autobyteus/memory/retrieval/__init__.py +7 -0
  249. autobyteus/memory/retrieval/memory_bundle.py +11 -0
  250. autobyteus/memory/retrieval/retriever.py +13 -0
  251. autobyteus/memory/store/__init__.py +7 -0
  252. autobyteus/memory/store/base_store.py +14 -0
  253. autobyteus/memory/store/file_store.py +98 -0
  254. autobyteus/memory/tool_interaction_builder.py +46 -0
  255. autobyteus/memory/turn_tracker.py +9 -0
  256. autobyteus/multimedia/audio/api/autobyteus_audio_client.py +19 -5
  257. autobyteus/multimedia/audio/api/gemini_audio_client.py +108 -16
  258. autobyteus/multimedia/audio/audio_client_factory.py +47 -9
  259. autobyteus/multimedia/audio/audio_model.py +2 -1
  260. autobyteus/multimedia/image/api/autobyteus_image_client.py +19 -5
  261. autobyteus/multimedia/image/api/gemini_image_client.py +38 -17
  262. autobyteus/multimedia/image/api/openai_image_client.py +125 -43
  263. autobyteus/multimedia/image/autobyteus_image_provider.py +2 -1
  264. autobyteus/multimedia/image/image_client_factory.py +47 -15
  265. autobyteus/multimedia/image/image_model.py +5 -2
  266. autobyteus/multimedia/providers.py +3 -2
  267. autobyteus/skills/loader.py +71 -0
  268. autobyteus/skills/model.py +11 -0
  269. autobyteus/skills/registry.py +70 -0
  270. autobyteus/task_management/tools/todo_tools/add_todo.py +2 -2
  271. autobyteus/task_management/tools/todo_tools/create_todo_list.py +2 -2
  272. autobyteus/task_management/tools/todo_tools/update_todo_status.py +2 -2
  273. autobyteus/tools/__init__.py +34 -47
  274. autobyteus/tools/base_tool.py +7 -0
  275. autobyteus/tools/file/__init__.py +2 -6
  276. autobyteus/tools/file/patch_file.py +149 -0
  277. autobyteus/tools/file/read_file.py +36 -5
  278. autobyteus/tools/file/write_file.py +4 -1
  279. autobyteus/tools/functional_tool.py +43 -6
  280. autobyteus/tools/mcp/__init__.py +2 -0
  281. autobyteus/tools/mcp/config_service.py +5 -1
  282. autobyteus/tools/mcp/server/__init__.py +2 -0
  283. autobyteus/tools/mcp/server/http_managed_mcp_server.py +1 -1
  284. autobyteus/tools/mcp/server/websocket_managed_mcp_server.py +141 -0
  285. autobyteus/tools/mcp/server_instance_manager.py +8 -1
  286. autobyteus/tools/mcp/types.py +61 -0
  287. autobyteus/tools/multimedia/audio_tools.py +70 -17
  288. autobyteus/tools/multimedia/download_media_tool.py +18 -4
  289. autobyteus/tools/multimedia/image_tools.py +246 -62
  290. autobyteus/tools/operation_executor/journal_manager.py +107 -0
  291. autobyteus/tools/operation_executor/operation_event_buffer.py +57 -0
  292. autobyteus/tools/operation_executor/operation_event_producer.py +29 -0
  293. autobyteus/tools/operation_executor/operation_executor.py +58 -0
  294. autobyteus/tools/registry/tool_definition.py +43 -2
  295. autobyteus/tools/skill/load_skill.py +50 -0
  296. autobyteus/tools/terminal/__init__.py +45 -0
  297. autobyteus/tools/terminal/ansi_utils.py +32 -0
  298. autobyteus/tools/terminal/background_process_manager.py +233 -0
  299. autobyteus/tools/terminal/output_buffer.py +105 -0
  300. autobyteus/tools/terminal/prompt_detector.py +63 -0
  301. autobyteus/tools/terminal/pty_session.py +241 -0
  302. autobyteus/tools/terminal/session_factory.py +20 -0
  303. autobyteus/tools/terminal/terminal_session_manager.py +226 -0
  304. autobyteus/tools/terminal/tools/__init__.py +13 -0
  305. autobyteus/tools/terminal/tools/get_process_output.py +81 -0
  306. autobyteus/tools/terminal/tools/run_bash.py +109 -0
  307. autobyteus/tools/terminal/tools/start_background_process.py +104 -0
  308. autobyteus/tools/terminal/tools/stop_background_process.py +67 -0
  309. autobyteus/tools/terminal/types.py +54 -0
  310. autobyteus/tools/terminal/wsl_tmux_session.py +221 -0
  311. autobyteus/tools/terminal/wsl_utils.py +156 -0
  312. autobyteus/tools/transaction_management/backup_handler.py +48 -0
  313. autobyteus/tools/transaction_management/operation_lifecycle_manager.py +62 -0
  314. autobyteus/tools/usage/__init__.py +1 -2
  315. autobyteus/tools/usage/formatters/__init__.py +17 -1
  316. autobyteus/tools/usage/formatters/base_formatter.py +8 -0
  317. autobyteus/tools/usage/formatters/default_xml_schema_formatter.py +2 -2
  318. autobyteus/tools/usage/formatters/mistral_json_schema_formatter.py +18 -0
  319. autobyteus/tools/usage/formatters/patch_file_xml_example_formatter.py +64 -0
  320. autobyteus/tools/usage/formatters/patch_file_xml_schema_formatter.py +31 -0
  321. autobyteus/tools/usage/formatters/run_bash_xml_example_formatter.py +32 -0
  322. autobyteus/tools/usage/formatters/run_bash_xml_schema_formatter.py +36 -0
  323. autobyteus/tools/usage/formatters/write_file_xml_example_formatter.py +53 -0
  324. autobyteus/tools/usage/formatters/write_file_xml_schema_formatter.py +31 -0
  325. autobyteus/tools/usage/providers/tool_manifest_provider.py +10 -10
  326. autobyteus/tools/usage/registries/__init__.py +1 -3
  327. autobyteus/tools/usage/registries/tool_formatting_registry.py +115 -8
  328. autobyteus/tools/usage/tool_schema_provider.py +51 -0
  329. autobyteus/tools/web/__init__.py +4 -0
  330. autobyteus/tools/web/read_url_tool.py +80 -0
  331. autobyteus/utils/diff_utils.py +271 -0
  332. autobyteus/utils/download_utils.py +109 -0
  333. autobyteus/utils/file_utils.py +57 -2
  334. autobyteus/utils/gemini_helper.py +56 -0
  335. autobyteus/utils/gemini_model_mapping.py +71 -0
  336. autobyteus/utils/llm_output_formatter.py +75 -0
  337. autobyteus/utils/tool_call_format.py +36 -0
  338. autobyteus/workflow/agentic_workflow.py +3 -3
  339. autobyteus/workflow/bootstrap_steps/agent_tool_injection_step.py +2 -2
  340. autobyteus/workflow/bootstrap_steps/base_workflow_bootstrap_step.py +2 -2
  341. autobyteus/workflow/bootstrap_steps/coordinator_initialization_step.py +2 -2
  342. autobyteus/workflow/bootstrap_steps/coordinator_prompt_preparation_step.py +3 -9
  343. autobyteus/workflow/bootstrap_steps/workflow_bootstrapper.py +6 -6
  344. autobyteus/workflow/bootstrap_steps/workflow_runtime_queue_initialization_step.py +2 -2
  345. autobyteus/workflow/context/workflow_context.py +3 -3
  346. autobyteus/workflow/context/workflow_runtime_state.py +5 -5
  347. autobyteus/workflow/events/workflow_event_dispatcher.py +5 -5
  348. autobyteus/workflow/handlers/lifecycle_workflow_event_handler.py +3 -3
  349. autobyteus/workflow/handlers/process_user_message_event_handler.py +5 -5
  350. autobyteus/workflow/handlers/tool_approval_workflow_event_handler.py +2 -2
  351. autobyteus/workflow/runtime/workflow_runtime.py +8 -8
  352. autobyteus/workflow/runtime/workflow_worker.py +3 -3
  353. autobyteus/workflow/status/__init__.py +11 -0
  354. autobyteus/workflow/status/workflow_status.py +19 -0
  355. autobyteus/workflow/status/workflow_status_manager.py +48 -0
  356. autobyteus/workflow/streaming/__init__.py +2 -2
  357. autobyteus/workflow/streaming/workflow_event_notifier.py +7 -7
  358. autobyteus/workflow/streaming/workflow_stream_event_payloads.py +4 -4
  359. autobyteus/workflow/streaming/workflow_stream_events.py +3 -3
  360. autobyteus/workflow/utils/wait_for_idle.py +4 -4
  361. autobyteus-1.2.3.dist-info/METADATA +293 -0
  362. autobyteus-1.2.3.dist-info/RECORD +600 -0
  363. {autobyteus-1.2.1.dist-info → autobyteus-1.2.3.dist-info}/WHEEL +1 -1
  364. {autobyteus-1.2.1.dist-info → autobyteus-1.2.3.dist-info}/top_level.txt +0 -1
  365. autobyteus/agent/bootstrap_steps/agent_runtime_queue_initialization_step.py +0 -57
  366. autobyteus/agent/hooks/__init__.py +0 -16
  367. autobyteus/agent/hooks/base_phase_hook.py +0 -78
  368. autobyteus/agent/hooks/hook_definition.py +0 -36
  369. autobyteus/agent/hooks/hook_meta.py +0 -37
  370. autobyteus/agent/hooks/hook_registry.py +0 -106
  371. autobyteus/agent/llm_response_processor/provider_aware_tool_usage_processor.py +0 -103
  372. autobyteus/agent/phases/__init__.py +0 -18
  373. autobyteus/agent/phases/discover.py +0 -53
  374. autobyteus/agent/phases/manager.py +0 -265
  375. autobyteus/agent/phases/transition_decorator.py +0 -40
  376. autobyteus/agent/phases/transition_info.py +0 -33
  377. autobyteus/agent/remote_agent.py +0 -244
  378. autobyteus/agent/workspace/workspace_definition.py +0 -36
  379. autobyteus/agent/workspace/workspace_meta.py +0 -37
  380. autobyteus/agent/workspace/workspace_registry.py +0 -72
  381. autobyteus/agent_team/bootstrap_steps/agent_team_runtime_queue_initialization_step.py +0 -25
  382. autobyteus/agent_team/bootstrap_steps/coordinator_prompt_preparation_step.py +0 -85
  383. autobyteus/agent_team/phases/__init__.py +0 -11
  384. autobyteus/agent_team/phases/agent_team_operational_phase.py +0 -19
  385. autobyteus/agent_team/phases/agent_team_phase_manager.py +0 -48
  386. autobyteus/llm/api/bedrock_llm.py +0 -92
  387. autobyteus/llm/api/groq_llm.py +0 -94
  388. autobyteus/llm/api/nvidia_llm.py +0 -108
  389. autobyteus/llm/utils/token_pricing_config.py +0 -87
  390. autobyteus/rpc/__init__.py +0 -73
  391. autobyteus/rpc/client/__init__.py +0 -17
  392. autobyteus/rpc/client/abstract_client_connection.py +0 -124
  393. autobyteus/rpc/client/client_connection_manager.py +0 -153
  394. autobyteus/rpc/client/sse_client_connection.py +0 -306
  395. autobyteus/rpc/client/stdio_client_connection.py +0 -280
  396. autobyteus/rpc/config/__init__.py +0 -13
  397. autobyteus/rpc/config/agent_server_config.py +0 -153
  398. autobyteus/rpc/config/agent_server_registry.py +0 -152
  399. autobyteus/rpc/hosting.py +0 -244
  400. autobyteus/rpc/protocol.py +0 -244
  401. autobyteus/rpc/server/__init__.py +0 -20
  402. autobyteus/rpc/server/agent_server_endpoint.py +0 -181
  403. autobyteus/rpc/server/base_method_handler.py +0 -40
  404. autobyteus/rpc/server/method_handlers.py +0 -259
  405. autobyteus/rpc/server/sse_server_handler.py +0 -182
  406. autobyteus/rpc/server/stdio_server_handler.py +0 -151
  407. autobyteus/rpc/server_main.py +0 -198
  408. autobyteus/rpc/transport_type.py +0 -13
  409. autobyteus/tools/bash/__init__.py +0 -2
  410. autobyteus/tools/bash/bash_executor.py +0 -100
  411. autobyteus/tools/browser/__init__.py +0 -2
  412. autobyteus/tools/browser/session_aware/browser_session_aware_navigate_to.py +0 -75
  413. autobyteus/tools/browser/session_aware/browser_session_aware_tool.py +0 -30
  414. autobyteus/tools/browser/session_aware/browser_session_aware_web_element_trigger.py +0 -154
  415. autobyteus/tools/browser/session_aware/browser_session_aware_webpage_reader.py +0 -89
  416. autobyteus/tools/browser/session_aware/browser_session_aware_webpage_screenshot_taker.py +0 -107
  417. autobyteus/tools/browser/session_aware/factory/browser_session_aware_web_element_trigger_factory.py +0 -14
  418. autobyteus/tools/browser/session_aware/factory/browser_session_aware_webpage_reader_factory.py +0 -26
  419. autobyteus/tools/browser/session_aware/factory/browser_session_aware_webpage_screenshot_taker_factory.py +0 -14
  420. autobyteus/tools/browser/session_aware/shared_browser_session.py +0 -11
  421. autobyteus/tools/browser/session_aware/shared_browser_session_manager.py +0 -25
  422. autobyteus/tools/browser/session_aware/web_element_action.py +0 -20
  423. autobyteus/tools/browser/standalone/__init__.py +0 -6
  424. autobyteus/tools/browser/standalone/factory/__init__.py +0 -0
  425. autobyteus/tools/browser/standalone/factory/webpage_reader_factory.py +0 -25
  426. autobyteus/tools/browser/standalone/factory/webpage_screenshot_taker_factory.py +0 -14
  427. autobyteus/tools/browser/standalone/navigate_to.py +0 -84
  428. autobyteus/tools/browser/standalone/web_page_pdf_generator.py +0 -101
  429. autobyteus/tools/browser/standalone/webpage_image_downloader.py +0 -169
  430. autobyteus/tools/browser/standalone/webpage_reader.py +0 -105
  431. autobyteus/tools/browser/standalone/webpage_screenshot_taker.py +0 -105
  432. autobyteus/tools/file/edit_file.py +0 -200
  433. autobyteus/tools/file/list_directory.py +0 -168
  434. autobyteus/tools/file/search_files.py +0 -188
  435. autobyteus/tools/timer.py +0 -175
  436. autobyteus/tools/usage/parsers/__init__.py +0 -22
  437. autobyteus/tools/usage/parsers/_json_extractor.py +0 -99
  438. autobyteus/tools/usage/parsers/_string_decoders.py +0 -18
  439. autobyteus/tools/usage/parsers/anthropic_xml_tool_usage_parser.py +0 -10
  440. autobyteus/tools/usage/parsers/base_parser.py +0 -41
  441. autobyteus/tools/usage/parsers/default_json_tool_usage_parser.py +0 -83
  442. autobyteus/tools/usage/parsers/default_xml_tool_usage_parser.py +0 -316
  443. autobyteus/tools/usage/parsers/exceptions.py +0 -13
  444. autobyteus/tools/usage/parsers/gemini_json_tool_usage_parser.py +0 -77
  445. autobyteus/tools/usage/parsers/openai_json_tool_usage_parser.py +0 -149
  446. autobyteus/tools/usage/parsers/provider_aware_tool_usage_parser.py +0 -59
  447. autobyteus/tools/usage/registries/tool_usage_parser_registry.py +0 -62
  448. autobyteus/workflow/phases/__init__.py +0 -11
  449. autobyteus/workflow/phases/workflow_operational_phase.py +0 -19
  450. autobyteus/workflow/phases/workflow_phase_manager.py +0 -48
  451. autobyteus-1.2.1.dist-info/METADATA +0 -205
  452. autobyteus-1.2.1.dist-info/RECORD +0 -511
  453. examples/__init__.py +0 -1
  454. examples/agent_team/__init__.py +0 -1
  455. examples/discover_phase_transitions.py +0 -104
  456. examples/run_agentic_software_engineer.py +0 -239
  457. examples/run_browser_agent.py +0 -262
  458. examples/run_google_slides_agent.py +0 -287
  459. examples/run_mcp_browser_client.py +0 -174
  460. examples/run_mcp_google_slides_client.py +0 -270
  461. examples/run_mcp_list_tools.py +0 -189
  462. examples/run_poem_writer.py +0 -284
  463. examples/run_sqlite_agent.py +0 -295
  464. /autobyteus/{tools/browser/session_aware → skills}/__init__.py +0 -0
  465. /autobyteus/tools/{browser/session_aware/factory → skill}/__init__.py +0 -0
  466. {autobyteus-1.2.1.dist-info → autobyteus-1.2.3.dist-info}/licenses/LICENSE +0 -0
@@ -1,16 +1,33 @@
1
1
  import logging
2
- from typing import Optional
2
+ from typing import Optional, Dict, Any
3
3
  from autobyteus.llm.models import LLMModel
4
4
  from autobyteus.llm.utils.llm_config import LLMConfig
5
5
  from autobyteus.llm.api.openai_compatible_llm import OpenAICompatibleLLM
6
6
 
7
7
  logger = logging.getLogger(__name__)
8
8
 
9
+ def _normalize_zhipu_extra_params(extra_params: Dict[str, Any]) -> Dict[str, Any]:
10
+ if not extra_params:
11
+ return {}
12
+
13
+ params = dict(extra_params)
14
+ thinking_type = params.pop("thinking_type", None)
15
+
16
+ if thinking_type is not None:
17
+ thinking = dict(params.get("thinking") or {})
18
+
19
+ if thinking_type is not None:
20
+ thinking["type"] = thinking_type
21
+
22
+ params["thinking"] = thinking
23
+
24
+ return params
25
+
9
26
  class ZhipuLLM(OpenAICompatibleLLM):
10
27
  def __init__(self, model: LLMModel = None, llm_config: LLMConfig = None):
11
28
  # Provide defaults if not specified
12
29
  if model is None:
13
- model = LLMModel['glm-4.6']
30
+ model = LLMModel['glm-4.7']
14
31
  if llm_config is None:
15
32
  llm_config = LLMConfig()
16
33
 
@@ -20,6 +37,8 @@ class ZhipuLLM(OpenAICompatibleLLM):
20
37
  api_key_env_var="ZHIPU_API_KEY",
21
38
  base_url="https://open.bigmodel.cn/api/paas/v4/"
22
39
  )
40
+ if self.config and isinstance(self.config.extra_params, dict):
41
+ self.config.extra_params = _normalize_zhipu_extra_params(self.config.extra_params)
23
42
  logger.info(f"ZhipuLLM initialized with model: {self.model}")
24
43
 
25
44
  async def cleanup(self):
@@ -32,76 +32,86 @@ class AutobyteusModelProvider:
32
32
 
33
33
  return []
34
34
 
35
+ @staticmethod
36
+ def get_models() -> List[LLMModel]:
37
+ """
38
+ Fetches models from all configured Autobyteus hosts and returns them as LLMModel objects.
39
+ """
40
+ hosts = AutobyteusModelProvider._get_hosts()
41
+ if not hosts:
42
+ logger.info("No Autobyteus LLM server hosts configured. Skipping Autobyteus LLM model discovery.")
43
+ return []
44
+
45
+ all_models = []
46
+
47
+ for host_url in hosts:
48
+ if not AutobyteusModelProvider.is_valid_url(host_url):
49
+ logger.error(f"Invalid Autobyteus host URL: {host_url}, skipping.")
50
+ continue
51
+
52
+ logger.info(f"Discovering Autobyteus models from host: {host_url}")
53
+ client = None
54
+ try:
55
+ # Instantiate client for this specific host
56
+ client = AutobyteusClient(server_url=host_url)
57
+ response = client.get_available_llm_models_sync()
58
+ except Exception as e:
59
+ logger.warning(f"Could not connect or fetch models from Autobyteus server at {host_url}: {e}")
60
+ continue
61
+ finally:
62
+ if client:
63
+ client.sync_client.close()
64
+
65
+ if not AutobyteusModelProvider._validate_server_response(response):
66
+ continue
67
+
68
+ models = response.get('models', [])
69
+ for model_info in models:
70
+ try:
71
+ validation_result = AutobyteusModelProvider._validate_model_info(model_info)
72
+ if not validation_result["valid"]:
73
+ logger.warning(validation_result["message"])
74
+ continue
75
+
76
+ llm_config = AutobyteusModelProvider._parse_llm_config(model_info["config"])
77
+ if not llm_config:
78
+ continue
79
+
80
+ llm_model = LLMModel(
81
+ name=model_info["name"],
82
+ value=model_info["value"],
83
+ provider=LLMProvider(model_info["provider"]),
84
+ llm_class=AutobyteusLLM,
85
+ canonical_name=model_info["canonical_name"],
86
+ runtime=LLMRuntime.AUTOBYTEUS,
87
+ host_url=host_url,
88
+ default_config=llm_config
89
+ )
90
+ all_models.append(llm_model)
91
+
92
+ except Exception as e:
93
+ logger.error(f"Failed to create LLMModel for '{model_info.get('name')}' from {host_url}: {e}")
94
+
95
+ return all_models
96
+
35
97
  @staticmethod
36
98
  def discover_and_register():
37
99
  """Discover and register Autobyteus models from all configured hosts."""
38
100
  try:
39
101
  from autobyteus.llm.llm_factory import LLMFactory
40
102
 
41
- hosts = AutobyteusModelProvider._get_hosts()
42
- if not hosts:
43
- logger.info("No Autobyteus LLM server hosts configured. Skipping Autobyteus LLM model discovery.")
44
- return
103
+ discovered_models = AutobyteusModelProvider.get_models()
104
+ registered_count = 0
45
105
 
46
- total_registered_count = 0
47
-
48
- for host_url in hosts:
49
- if not AutobyteusModelProvider.is_valid_url(host_url):
50
- logger.error(f"Invalid Autobyteus host URL: {host_url}, skipping.")
51
- continue
52
-
53
- logger.info(f"Discovering Autobyteus models from host: {host_url}")
54
- client = None
106
+ for model in discovered_models:
55
107
  try:
56
- # Instantiate client for this specific host
57
- client = AutobyteusClient(server_url=host_url)
58
- response = client.get_available_llm_models_sync()
108
+ LLMFactory.register_model(model)
109
+ registered_count += 1
59
110
  except Exception as e:
60
- logger.warning(f"Could not connect or fetch models from Autobyteus server at {host_url}: {e}")
61
- continue
62
- finally:
63
- if client:
64
- client.sync_client.close()
65
-
66
- if not AutobyteusModelProvider._validate_server_response(response):
67
- continue
68
-
69
- models = response.get('models', [])
70
- host_registered_count = 0
71
- for model_info in models:
72
- try:
73
- validation_result = AutobyteusModelProvider._validate_model_info(model_info)
74
- if not validation_result["valid"]:
75
- logger.warning(validation_result["message"])
76
- continue
77
-
78
- llm_config = AutobyteusModelProvider._parse_llm_config(model_info["config"])
79
- if not llm_config:
80
- continue
81
-
82
- llm_model = LLMModel(
83
- name=model_info["name"],
84
- value=model_info["value"],
85
- provider=LLMProvider(model_info["provider"]),
86
- llm_class=AutobyteusLLM,
87
- canonical_name=model_info["canonical_name"],
88
- runtime=LLMRuntime.AUTOBYTEUS,
89
- host_url=host_url,
90
- default_config=llm_config
91
- )
92
-
93
- LLMFactory.register_model(llm_model)
94
- host_registered_count += 1
95
-
96
- except Exception as e:
97
- logger.error(f"Failed to register Autobyteus model '{model_info.get('name')}' from {host_url}: {e}")
98
-
99
- if host_registered_count > 0:
100
- logger.info(f"Registered {host_registered_count} models from Autobyteus host {host_url}")
101
- total_registered_count += host_registered_count
111
+ logger.warning(f"Failed to register Autobyteus model '{model.name}': {e}")
102
112
 
103
- if total_registered_count > 0:
104
- logger.info(f"Finished Autobyteus discovery. Total models registered: {total_registered_count}")
113
+ if registered_count > 0:
114
+ logger.info(f"Finished Autobyteus discovery. Total models registered: {registered_count}")
105
115
 
106
116
  except Exception as e:
107
117
  logger.error(f"An unexpected error occurred during Autobyteus model discovery: {e}", exc_info=True)
@@ -26,12 +26,13 @@ class BaseLLM(ABC):
26
26
 
27
27
  self._token_usage_extension: TokenUsageTrackingExtension = self.register_extension(TokenUsageTrackingExtension)
28
28
 
29
- self.messages: List[Message] = []
30
29
  self.system_message = self.config.system_message or self.DEFAULT_SYSTEM_MESSAGE
31
- self.add_system_message(self.system_message)
32
30
 
33
31
  @property
34
32
  def latest_token_usage(self):
33
+ """Get latest token usage. Returns None if token tracking is disabled."""
34
+ if not self._token_usage_extension.is_enabled:
35
+ return None
35
36
  return self._token_usage_extension.latest_token_usage
36
37
 
37
38
  def register_extension(self, extension_class: Type[LLMExtension]) -> LLMExtension:
@@ -45,42 +46,19 @@ class BaseLLM(ABC):
45
46
  def get_extension(self, extension_class: Type[LLMExtension]) -> Optional[LLMExtension]:
46
47
  return self._extension_registry.get(extension_class)
47
48
 
48
- def add_system_message(self, message: str):
49
- self.messages.append(Message(MessageRole.SYSTEM, content=message))
50
-
51
- def add_user_message(self, user_message: LLMUserMessage):
52
- """
53
- Adds a user message to history, converting from LLMUserMessage to Message.
54
- """
55
- msg = Message(
49
+ def _build_user_message(self, user_message: LLMUserMessage) -> Message:
50
+ return Message(
56
51
  role=MessageRole.USER,
57
52
  content=user_message.content,
58
53
  image_urls=user_message.image_urls,
59
54
  audio_urls=user_message.audio_urls,
60
- video_urls=user_message.video_urls
61
- )
62
- self.messages.append(msg)
63
- self._trigger_on_user_message_added(msg)
64
-
65
- def add_assistant_message(self,
66
- content: Optional[str],
67
- reasoning_content: Optional[str] = None,
68
- image_urls: Optional[List[str]] = None,
69
- audio_urls: Optional[List[str]] = None,
70
- video_urls: Optional[List[str]] = None):
71
- """
72
- Adds a multimodal assistant message to the conversation history.
73
- """
74
- msg = Message(
75
- role=MessageRole.ASSISTANT,
76
- content=content,
77
- reasoning_content=reasoning_content,
78
- image_urls=image_urls,
79
- audio_urls=audio_urls,
80
- video_urls=video_urls
55
+ video_urls=user_message.video_urls,
81
56
  )
82
- self.messages.append(msg)
83
- self._trigger_on_assistant_message_added(msg)
57
+
58
+ def _build_system_message(self) -> Optional[Message]:
59
+ if not self.system_message:
60
+ return None
61
+ return Message(MessageRole.SYSTEM, content=self.system_message)
84
62
 
85
63
  def configure_system_prompt(self, new_system_prompt: str):
86
64
  if not new_system_prompt or not isinstance(new_system_prompt, str):
@@ -89,51 +67,40 @@ class BaseLLM(ABC):
89
67
 
90
68
  self.system_message = new_system_prompt
91
69
  self.config.system_message = new_system_prompt
92
-
93
- system_message_found = False
94
- for i, msg in enumerate(self.messages):
95
- if msg.role == MessageRole.SYSTEM:
96
- self.messages[i] = Message(MessageRole.SYSTEM, new_system_prompt)
97
- system_message_found = True
98
- logging.debug(f"Replaced existing system message at index {i}.")
99
- break
100
-
101
- if not system_message_found:
102
- self.messages.insert(0, Message(MessageRole.SYSTEM, new_system_prompt))
103
- logging.debug("No existing system message found, inserted new one at the beginning.")
104
-
105
70
  logging.info(f"LLM instance system prompt updated. New prompt length: {len(new_system_prompt)}")
106
71
 
107
- def _trigger_on_user_message_added(self, message: Message):
72
+ async def _execute_before_hooks(self, messages: List[Message], rendered_payload: Optional[dict] = None, **kwargs) -> None:
108
73
  for extension in self._extension_registry.get_all():
109
- extension.on_user_message_added(message)
74
+ await extension.before_invoke(messages, rendered_payload, **kwargs)
110
75
 
111
- def _trigger_on_assistant_message_added(self, message: Message):
76
+ async def _execute_after_hooks(self, messages: List[Message], response: CompleteResponse = None, **kwargs) -> None:
112
77
  for extension in self._extension_registry.get_all():
113
- extension.on_assistant_message_added(message)
114
-
115
- async def _execute_before_hooks(self, user_message: LLMUserMessage, **kwargs) -> None:
116
- for extension in self._extension_registry.get_all():
117
- await extension.before_invoke(user_message, **kwargs)
118
-
119
- async def _execute_after_hooks(self, user_message: LLMUserMessage, response: CompleteResponse = None, **kwargs) -> None:
120
- for extension in self._extension_registry.get_all():
121
- await extension.after_invoke(user_message, response, **kwargs)
122
-
123
- async def send_user_message(self, user_message: LLMUserMessage, **kwargs) -> CompleteResponse:
124
- await self._execute_before_hooks(user_message, **kwargs)
125
- response = await self._send_user_message_to_llm(user_message, **kwargs)
126
- await self._execute_after_hooks(user_message, response, **kwargs)
78
+ await extension.after_invoke(messages, response, **kwargs)
79
+
80
+ async def send_messages(
81
+ self,
82
+ messages: List[Message],
83
+ rendered_payload: Optional[dict] = None,
84
+ **kwargs,
85
+ ) -> CompleteResponse:
86
+ await self._execute_before_hooks(messages, rendered_payload, **kwargs)
87
+ response = await self._send_messages_to_llm(messages, **kwargs)
88
+ await self._execute_after_hooks(messages, response, **kwargs)
127
89
  return response
128
90
 
129
- async def stream_user_message(self, user_message: LLMUserMessage, **kwargs) -> AsyncGenerator[ChunkResponse, None]:
130
- await self._execute_before_hooks(user_message, **kwargs)
91
+ async def stream_messages(
92
+ self,
93
+ messages: List[Message],
94
+ rendered_payload: Optional[dict] = None,
95
+ **kwargs,
96
+ ) -> AsyncGenerator[ChunkResponse, None]:
97
+ await self._execute_before_hooks(messages, rendered_payload, **kwargs)
131
98
 
132
99
  accumulated_content = ""
133
100
  accumulated_reasoning = ""
134
101
  final_chunk = None
135
-
136
- async for chunk in self._stream_user_message_to_llm(user_message, **kwargs):
102
+
103
+ async for chunk in self._stream_messages_to_llm(messages, **kwargs):
137
104
  if chunk.content:
138
105
  accumulated_content += chunk.content
139
106
  if chunk.reasoning:
@@ -146,34 +113,72 @@ class BaseLLM(ABC):
146
113
  complete_response = CompleteResponse(
147
114
  content=accumulated_content,
148
115
  reasoning=accumulated_reasoning if accumulated_reasoning else None,
149
- usage=final_chunk.usage if final_chunk else None
116
+ usage=final_chunk.usage if final_chunk else None,
150
117
  )
151
-
152
- await self._execute_after_hooks(user_message, complete_response, **kwargs)
153
118
 
154
- @abstractmethod
119
+ await self._execute_after_hooks(messages, complete_response, **kwargs)
120
+
121
+ async def send_user_message(self, user_message: LLMUserMessage, **kwargs) -> CompleteResponse:
122
+ messages: List[Message] = []
123
+ system_message = self._build_system_message()
124
+ if system_message:
125
+ messages.append(system_message)
126
+ messages.append(self._build_user_message(user_message))
127
+ return await self.send_messages(messages, **kwargs)
128
+
129
+ async def stream_user_message(
130
+ self, user_message: LLMUserMessage, **kwargs
131
+ ) -> AsyncGenerator[ChunkResponse, None]:
132
+ messages: List[Message] = []
133
+ system_message = self._build_system_message()
134
+ if system_message:
135
+ messages.append(system_message)
136
+ messages.append(self._build_user_message(user_message))
137
+ async for chunk in self.stream_messages(messages, **kwargs):
138
+ yield chunk
139
+
155
140
  async def _send_user_message_to_llm(self, user_message: LLMUserMessage, **kwargs) -> CompleteResponse:
141
+ messages: List[Message] = []
142
+ system_message = self._build_system_message()
143
+ if system_message:
144
+ messages.append(system_message)
145
+ messages.append(self._build_user_message(user_message))
146
+ return await self._send_messages_to_llm(messages, **kwargs)
147
+
148
+ async def _stream_user_message_to_llm(
149
+ self, user_message: LLMUserMessage, **kwargs
150
+ ) -> AsyncGenerator[ChunkResponse, None]:
151
+ messages: List[Message] = []
152
+ system_message = self._build_system_message()
153
+ if system_message:
154
+ messages.append(system_message)
155
+ messages.append(self._build_user_message(user_message))
156
+ async for chunk in self._stream_messages_to_llm(messages, **kwargs):
157
+ yield chunk
158
+
159
+ @abstractmethod
160
+ async def _send_messages_to_llm(self, messages: List[Message], **kwargs) -> CompleteResponse:
156
161
  """
157
- Abstract method for sending a user message to an LLM. Must be implemented by subclasses.
158
-
162
+ Abstract method for sending a list of messages to an LLM. Must be implemented by subclasses.
163
+
159
164
  Args:
160
- user_message (LLMUserMessage): The user message object.
165
+ messages (List[Message]): The message list to send.
161
166
  **kwargs: Additional arguments for LLM-specific usage.
162
-
167
+
163
168
  Returns:
164
169
  CompleteResponse: The complete response from the LLM.
165
170
  """
166
171
  pass
167
172
 
168
173
  @abstractmethod
169
- async def _stream_user_message_to_llm(self, user_message: LLMUserMessage, **kwargs) -> AsyncGenerator[ChunkResponse, None]:
174
+ async def _stream_messages_to_llm(self, messages: List[Message], **kwargs) -> AsyncGenerator[ChunkResponse, None]:
170
175
  """
171
- Abstract method for streaming a user message response from the LLM. Must be implemented by subclasses.
172
-
176
+ Abstract method for streaming a response from an LLM. Must be implemented by subclasses.
177
+
173
178
  Args:
174
- user_message (LLMUserMessage): The user message object.
179
+ messages (List[Message]): The message list to send.
175
180
  **kwargs: Additional arguments for LLM-specific usage.
176
-
181
+
177
182
  Yields:
178
183
  AsyncGenerator[ChunkResponse, None]: Streaming chunks from the LLM response.
179
184
  """
@@ -183,4 +188,3 @@ class BaseLLM(ABC):
183
188
  for extension in self._extension_registry.get_all():
184
189
  await extension.cleanup()
185
190
  self._extension_registry.clear()
186
- self.messages = []
@@ -0,0 +1,14 @@
1
+ # file: autobyteus/autobyteus/llm/converters/__init__.py
2
+ """
3
+ LLM provider-specific converters.
4
+
5
+ These converters transform provider-specific data formats into
6
+ normalized internal representations.
7
+ """
8
+
9
+ from .openai_tool_call_converter import convert_openai_tool_calls
10
+ from .gemini_tool_call_converter import convert_gemini_tool_calls
11
+ from .anthropic_tool_call_converter import convert_anthropic_tool_call
12
+ from .mistral_tool_call_converter import convert_mistral_tool_calls
13
+
14
+ __all__ = ["convert_openai_tool_calls", "convert_gemini_tool_calls", "convert_anthropic_tool_call", "convert_mistral_tool_calls"]
@@ -0,0 +1,37 @@
1
+ from typing import List, Optional, Any
2
+ from autobyteus.llm.utils.tool_call_delta import ToolCallDelta
3
+
4
+ # Anthropic event types are typically simple objects or dicts from the SDK stream
5
+ # The SDK yields `MessageStreamEvent` objects.
6
+
7
+ def convert_anthropic_tool_call(event: Any) -> Optional[List[ToolCallDelta]]:
8
+ """
9
+ Convert an Anthropic stream event into ToolCallDelta objects.
10
+
11
+ Handles:
12
+ - ContentBlockStartEvent (type='content_block_start') -> Tool Name + ID
13
+ - ContentBlockDeltaEvent (type='content_block_delta') -> Arguments Delta
14
+ """
15
+
16
+ # Handle ContentBlockStartEvent (Start of tool use)
17
+ # event.content_block.type == 'tool_use'
18
+ if event.type == "content_block_start":
19
+ if event.content_block.type == "tool_use":
20
+ return [ToolCallDelta(
21
+ index=event.index, # Anthropic provides index
22
+ call_id=event.content_block.id,
23
+ name=event.content_block.name,
24
+ arguments_delta=None # No args yet
25
+ )]
26
+
27
+ # Handle ContentBlockDeltaEvent (JSON args update)
28
+ elif event.type == "content_block_delta":
29
+ if event.delta.type == "input_json_delta":
30
+ return [ToolCallDelta(
31
+ index=event.index, # Anthropic provides index matching the start event
32
+ call_id=None,
33
+ name=None,
34
+ arguments_delta=event.delta.partial_json
35
+ )]
36
+
37
+ return None
@@ -0,0 +1,57 @@
1
+ from typing import List, Optional, Any
2
+ from autobyteus.llm.utils.tool_call_delta import ToolCallDelta
3
+ from google.genai import types as genai_types
4
+ import json
5
+
6
+ def convert_gemini_tool_calls(part: Any) -> Optional[List[ToolCallDelta]]:
7
+ """
8
+ Convert a Gemini stream part (which might be a functionCall) into ToolCallDelta objects.
9
+
10
+ Gemini 'functionCall' usually comes as a complete object in the parts list,
11
+ but we treat it as a delta to fit the unified streaming model.
12
+ """
13
+ # Check if the part has a function_call
14
+ # The SDK structure for part usually has a 'function_call' attribute
15
+
16
+ # Note: genai_types.Part might have function_call (FunctionCall)
17
+
18
+ # Safety check for attribute existence
19
+ if not hasattr(part, "function_call") or not part.function_call:
20
+ return None
21
+
22
+ fc = part.function_call
23
+
24
+ # Gemini provides the full arguments as a dict in the 'args' attribute
25
+ # We serialize this back to JSON string for the delta, because our unified
26
+ # ToolCallDelta expects string deltas for arguments.
27
+ # Since we get the full args at once, this is a "complete" delta.
28
+
29
+ # Note: 'args' is a dictionary.
30
+ arguments_json = json.dumps(fc.args) if fc.args else "{}"
31
+
32
+ # We use a fixed index 0 because Gemini typically emits one function call per candidate part?
33
+ # Actually Gemini can return multiple function calls in parallel tool use?
34
+ # But usually they are in separate parts or candidates.
35
+ # For now, we assume implicit index 0 for the part itself.
36
+ # If parallel tool calling is supported via multiple parts, the caller loop needs to handle indexing
37
+ # if it's not provided by the SDK.
38
+ # However, ToolCallDelta requires an index. We'll default to 0.
39
+ # If the caller iterates parts, it might need to assign indices.
40
+ # But wait, ToolCallDelta logic merges by index. If we always return index 0 for distinct parts, they merge.
41
+ # We might need to generate a unique index or rely on the caller to offset it.
42
+ # BUT, Gemini streaming chunks usually contain ONE part at a time.
43
+ # If we treat each function_call part as a NEW tool call, we need a way to distinguish parallel ones?
44
+ # Or maybe we just generate a unique call_id if one isn't present.
45
+ # Gemini function calls don't always have IDs in the stream?
46
+ # Let's check `fc.name` and `fc.args`.
47
+
48
+ # For simplicity, if we get a full function call, we return one delta that has EVERYTHING.
49
+ # The unified handler will assume it's a new call if index is new... or if it's the first time
50
+ # seeing this index.
51
+
52
+ return [ToolCallDelta(
53
+ index=0, # Assuming single tool call per part context for now
54
+ call_id=None, # Gemini doesn't always provide call ID in stream? We'll rely on handler to generate one.
55
+ name=fc.name,
56
+ arguments_delta=arguments_json
57
+ )]
@@ -0,0 +1,37 @@
1
+ from typing import List, Optional, Any
2
+ from autobyteus.llm.utils.tool_call_delta import ToolCallDelta
3
+ import logging
4
+
5
+ logger = logging.getLogger(__name__)
6
+
7
+ def convert_mistral_tool_calls(tool_calls: List[Any]) -> Optional[List[ToolCallDelta]]:
8
+ """
9
+ Convert Mistral streaming tool calls (similar to OpenAI) into ToolCallDelta objects.
10
+ """
11
+ if not tool_calls:
12
+ return None
13
+
14
+ deltas = []
15
+ for tool_call in tool_calls:
16
+ # Mistral SDK 'ToolCall' or dict in delta
17
+ # Usually has: index, id, function (name, arguments)
18
+
19
+ index = tool_call.get('index', 0) if isinstance(tool_call, dict) else getattr(tool_call, 'index', 0)
20
+ call_id = tool_call.get('id', None) if isinstance(tool_call, dict) else getattr(tool_call, 'id', None)
21
+
22
+ function = tool_call.get('function', None) if isinstance(tool_call, dict) else getattr(tool_call, 'function', None)
23
+ name = None
24
+ arguments = None
25
+
26
+ if function:
27
+ name = function.get('name', None) if isinstance(function, dict) else getattr(function, 'name', None)
28
+ arguments = function.get('arguments', None) if isinstance(function, dict) else getattr(function, 'arguments', None)
29
+
30
+ deltas.append(ToolCallDelta(
31
+ index=index,
32
+ call_id=call_id,
33
+ name=name,
34
+ arguments_delta=arguments
35
+ ))
36
+
37
+ return deltas
@@ -0,0 +1,38 @@
1
+ # file: autobyteus/autobyteus/llm/converters/openai_tool_call_converter.py
2
+ """
3
+ Converter for OpenAI SDK tool call deltas to normalized ToolCallDelta format.
4
+ """
5
+
6
+ from typing import List, Optional
7
+ from autobyteus.llm.utils.tool_call_delta import ToolCallDelta
8
+
9
+ # Type checking import for OpenAI SDK types
10
+ try:
11
+ from openai.types.chat.chat_completion_chunk import ChoiceDeltaToolCall
12
+ except ImportError:
13
+ ChoiceDeltaToolCall = None # type: ignore
14
+
15
+
16
+ def convert_openai_tool_calls(delta_tool_calls: Optional[List]) -> Optional[List[ToolCallDelta]]:
17
+ """
18
+ Convert OpenAI SDK tool call deltas to normalized ToolCallDelta objects.
19
+
20
+ Args:
21
+ delta_tool_calls: List of ChoiceDeltaToolCall from OpenAI SDK, or None.
22
+
23
+ Returns:
24
+ List of normalized ToolCallDelta objects, or None if input is None/empty.
25
+ """
26
+ if not delta_tool_calls:
27
+ return None
28
+
29
+ result = []
30
+ for tc in delta_tool_calls:
31
+ # Extract fields from OpenAI's ChoiceDeltaToolCall
32
+ result.append(ToolCallDelta(
33
+ index=tc.index,
34
+ call_id=tc.id if tc.id else None,
35
+ name=tc.function.name if tc.function and tc.function.name else None,
36
+ arguments_delta=tc.function.arguments if tc.function and tc.function.arguments else None,
37
+ ))
38
+ return result
@@ -1,8 +1,8 @@
1
1
  from abc import ABC, abstractmethod
2
- from typing import List, Optional, TYPE_CHECKING
2
+ from typing import List, Optional, TYPE_CHECKING, Any
3
+
3
4
  from autobyteus.llm.utils.messages import Message
4
5
  from autobyteus.llm.utils.response_types import CompleteResponse
5
- from autobyteus.llm.user_message import LLMUserMessage
6
6
 
7
7
  if TYPE_CHECKING:
8
8
  from autobyteus.llm.base_llm import BaseLLM
@@ -13,32 +13,26 @@ class LLMExtension(ABC):
13
13
 
14
14
  @abstractmethod
15
15
  async def before_invoke(
16
- self, user_message: LLMUserMessage, **kwargs
16
+ self, messages: List[Message], rendered_payload: Optional[Any] = None, **kwargs
17
17
  ) -> None:
18
18
  """
19
- Called before invoking the LLM with a user message.
19
+ Called before invoking the LLM with explicit messages.
20
20
  """
21
21
  pass
22
22
 
23
23
  @abstractmethod
24
24
  async def after_invoke(
25
- self, user_message: LLMUserMessage, response: CompleteResponse = None, **kwargs
25
+ self, messages: List[Message], response: CompleteResponse = None, **kwargs
26
26
  ) -> None:
27
27
  """
28
28
  Called after receiving the response from the LLM.
29
29
 
30
30
  Args:
31
- user_message: The original user message object.
31
+ messages: The explicit prompt messages used for invocation.
32
32
  response: Complete response including content and usage information.
33
33
  kwargs: Additional arguments.
34
34
  """
35
35
  pass
36
36
 
37
- def on_user_message_added(self, message: Message):
38
- pass
39
-
40
- def on_assistant_message_added(self, message: Message):
41
- pass
42
-
43
37
  async def cleanup(self) -> None:
44
38
  pass