autobyteus 1.2.0__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 (512) 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 +23 -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 +74 -60
  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/message/send_message_to.py +5 -4
  39. autobyteus/agent/runtime/agent_runtime.py +29 -21
  40. autobyteus/agent/runtime/agent_worker.py +98 -19
  41. autobyteus/agent/shutdown_steps/__init__.py +2 -0
  42. autobyteus/agent/shutdown_steps/agent_shutdown_orchestrator.py +2 -0
  43. autobyteus/agent/shutdown_steps/tool_cleanup_step.py +58 -0
  44. autobyteus/agent/status/__init__.py +14 -0
  45. autobyteus/agent/status/manager.py +93 -0
  46. autobyteus/agent/status/status_deriver.py +96 -0
  47. autobyteus/agent/{phases/phase_enum.py → status/status_enum.py} +16 -16
  48. autobyteus/agent/status/status_update_utils.py +73 -0
  49. autobyteus/agent/streaming/__init__.py +52 -5
  50. autobyteus/agent/streaming/adapters/__init__.py +18 -0
  51. autobyteus/agent/streaming/adapters/invocation_adapter.py +184 -0
  52. autobyteus/agent/streaming/adapters/tool_call_parsing.py +163 -0
  53. autobyteus/agent/streaming/adapters/tool_syntax_registry.py +67 -0
  54. autobyteus/agent/streaming/agent_event_stream.py +3 -178
  55. autobyteus/agent/streaming/api_tool_call/__init__.py +16 -0
  56. autobyteus/agent/streaming/api_tool_call/file_content_streamer.py +56 -0
  57. autobyteus/agent/streaming/api_tool_call/json_string_field_extractor.py +175 -0
  58. autobyteus/agent/streaming/api_tool_call_streaming_response_handler.py +4 -0
  59. autobyteus/agent/streaming/events/__init__.py +6 -0
  60. autobyteus/agent/streaming/events/stream_event_payloads.py +284 -0
  61. autobyteus/agent/streaming/events/stream_events.py +141 -0
  62. autobyteus/agent/streaming/handlers/__init__.py +15 -0
  63. autobyteus/agent/streaming/handlers/api_tool_call_streaming_response_handler.py +303 -0
  64. autobyteus/agent/streaming/handlers/parsing_streaming_response_handler.py +107 -0
  65. autobyteus/agent/streaming/handlers/pass_through_streaming_response_handler.py +107 -0
  66. autobyteus/agent/streaming/handlers/streaming_handler_factory.py +177 -0
  67. autobyteus/agent/streaming/handlers/streaming_response_handler.py +58 -0
  68. autobyteus/agent/streaming/parser/__init__.py +61 -0
  69. autobyteus/agent/streaming/parser/event_emitter.py +181 -0
  70. autobyteus/agent/streaming/parser/events.py +4 -0
  71. autobyteus/agent/streaming/parser/invocation_adapter.py +4 -0
  72. autobyteus/agent/streaming/parser/json_parsing_strategies/__init__.py +19 -0
  73. autobyteus/agent/streaming/parser/json_parsing_strategies/base.py +32 -0
  74. autobyteus/agent/streaming/parser/json_parsing_strategies/default.py +34 -0
  75. autobyteus/agent/streaming/parser/json_parsing_strategies/gemini.py +31 -0
  76. autobyteus/agent/streaming/parser/json_parsing_strategies/openai.py +64 -0
  77. autobyteus/agent/streaming/parser/json_parsing_strategies/registry.py +75 -0
  78. autobyteus/agent/streaming/parser/parser_context.py +227 -0
  79. autobyteus/agent/streaming/parser/parser_factory.py +132 -0
  80. autobyteus/agent/streaming/parser/sentinel_format.py +7 -0
  81. autobyteus/agent/streaming/parser/state_factory.py +62 -0
  82. autobyteus/agent/streaming/parser/states/__init__.py +1 -0
  83. autobyteus/agent/streaming/parser/states/base_state.py +60 -0
  84. autobyteus/agent/streaming/parser/states/custom_xml_tag_run_bash_parsing_state.py +38 -0
  85. autobyteus/agent/streaming/parser/states/custom_xml_tag_write_file_parsing_state.py +55 -0
  86. autobyteus/agent/streaming/parser/states/delimited_content_state.py +146 -0
  87. autobyteus/agent/streaming/parser/states/json_initialization_state.py +144 -0
  88. autobyteus/agent/streaming/parser/states/json_tool_parsing_state.py +137 -0
  89. autobyteus/agent/streaming/parser/states/sentinel_content_state.py +30 -0
  90. autobyteus/agent/streaming/parser/states/sentinel_initialization_state.py +117 -0
  91. autobyteus/agent/streaming/parser/states/text_state.py +78 -0
  92. autobyteus/agent/streaming/parser/states/xml_patch_file_tool_parsing_state.py +328 -0
  93. autobyteus/agent/streaming/parser/states/xml_run_bash_tool_parsing_state.py +129 -0
  94. autobyteus/agent/streaming/parser/states/xml_tag_initialization_state.py +151 -0
  95. autobyteus/agent/streaming/parser/states/xml_tool_parsing_state.py +63 -0
  96. autobyteus/agent/streaming/parser/states/xml_write_file_tool_parsing_state.py +343 -0
  97. autobyteus/agent/streaming/parser/strategies/__init__.py +17 -0
  98. autobyteus/agent/streaming/parser/strategies/base.py +24 -0
  99. autobyteus/agent/streaming/parser/strategies/json_tool_strategy.py +26 -0
  100. autobyteus/agent/streaming/parser/strategies/registry.py +28 -0
  101. autobyteus/agent/streaming/parser/strategies/sentinel_strategy.py +23 -0
  102. autobyteus/agent/streaming/parser/strategies/xml_tag_strategy.py +21 -0
  103. autobyteus/agent/streaming/parser/stream_scanner.py +167 -0
  104. autobyteus/agent/streaming/parser/streaming_parser.py +212 -0
  105. autobyteus/agent/streaming/parser/tool_call_parsing.py +4 -0
  106. autobyteus/agent/streaming/parser/tool_constants.py +7 -0
  107. autobyteus/agent/streaming/parser/tool_syntax_registry.py +4 -0
  108. autobyteus/agent/streaming/parser/xml_tool_parsing_state_registry.py +55 -0
  109. autobyteus/agent/streaming/parsing_streaming_response_handler.py +4 -0
  110. autobyteus/agent/streaming/pass_through_streaming_response_handler.py +4 -0
  111. autobyteus/agent/streaming/queue_streamer.py +3 -57
  112. autobyteus/agent/streaming/segments/__init__.py +5 -0
  113. autobyteus/agent/streaming/segments/segment_events.py +81 -0
  114. autobyteus/agent/streaming/stream_event_payloads.py +2 -198
  115. autobyteus/agent/streaming/stream_events.py +3 -128
  116. autobyteus/agent/streaming/streaming_handler_factory.py +4 -0
  117. autobyteus/agent/streaming/streaming_response_handler.py +4 -0
  118. autobyteus/agent/streaming/streams/__init__.py +5 -0
  119. autobyteus/agent/streaming/streams/agent_event_stream.py +197 -0
  120. autobyteus/agent/streaming/utils/__init__.py +5 -0
  121. autobyteus/agent/streaming/utils/queue_streamer.py +59 -0
  122. autobyteus/agent/system_prompt_processor/__init__.py +2 -0
  123. autobyteus/agent/system_prompt_processor/available_skills_processor.py +96 -0
  124. autobyteus/agent/system_prompt_processor/base_processor.py +1 -1
  125. autobyteus/agent/system_prompt_processor/processor_meta.py +15 -2
  126. autobyteus/agent/system_prompt_processor/tool_manifest_injector_processor.py +39 -58
  127. autobyteus/agent/token_budget.py +56 -0
  128. autobyteus/agent/tool_execution_result_processor/memory_ingest_tool_result_processor.py +29 -0
  129. autobyteus/agent/tool_invocation.py +16 -40
  130. autobyteus/agent/tool_invocation_preprocessor/__init__.py +9 -0
  131. autobyteus/agent/tool_invocation_preprocessor/base_preprocessor.py +45 -0
  132. autobyteus/agent/tool_invocation_preprocessor/processor_definition.py +15 -0
  133. autobyteus/agent/tool_invocation_preprocessor/processor_meta.py +33 -0
  134. autobyteus/agent/tool_invocation_preprocessor/processor_registry.py +60 -0
  135. autobyteus/agent/utils/wait_for_idle.py +12 -14
  136. autobyteus/agent/workspace/base_workspace.py +6 -27
  137. autobyteus/agent_team/agent_team.py +3 -3
  138. autobyteus/agent_team/agent_team_builder.py +1 -41
  139. autobyteus/agent_team/bootstrap_steps/__init__.py +0 -4
  140. autobyteus/agent_team/bootstrap_steps/agent_configuration_preparation_step.py +8 -18
  141. autobyteus/agent_team/bootstrap_steps/agent_team_bootstrapper.py +4 -16
  142. autobyteus/agent_team/bootstrap_steps/base_agent_team_bootstrap_step.py +1 -2
  143. autobyteus/agent_team/bootstrap_steps/coordinator_initialization_step.py +1 -2
  144. autobyteus/agent_team/bootstrap_steps/task_notifier_initialization_step.py +5 -6
  145. autobyteus/agent_team/bootstrap_steps/team_context_initialization_step.py +15 -15
  146. autobyteus/agent_team/context/agent_team_config.py +6 -3
  147. autobyteus/agent_team/context/agent_team_context.py +25 -3
  148. autobyteus/agent_team/context/agent_team_runtime_state.py +11 -8
  149. autobyteus/agent_team/events/__init__.py +11 -0
  150. autobyteus/agent_team/events/agent_team_event_dispatcher.py +22 -9
  151. autobyteus/agent_team/events/agent_team_events.py +16 -0
  152. autobyteus/agent_team/events/event_store.py +57 -0
  153. autobyteus/agent_team/factory/agent_team_factory.py +8 -0
  154. autobyteus/agent_team/handlers/inter_agent_message_request_event_handler.py +18 -2
  155. autobyteus/agent_team/handlers/lifecycle_agent_team_event_handler.py +21 -5
  156. autobyteus/agent_team/handlers/process_user_message_event_handler.py +17 -8
  157. autobyteus/agent_team/handlers/tool_approval_team_event_handler.py +19 -4
  158. autobyteus/agent_team/runtime/agent_team_runtime.py +41 -10
  159. autobyteus/agent_team/runtime/agent_team_worker.py +69 -5
  160. autobyteus/agent_team/status/__init__.py +14 -0
  161. autobyteus/agent_team/status/agent_team_status.py +18 -0
  162. autobyteus/agent_team/status/agent_team_status_manager.py +33 -0
  163. autobyteus/agent_team/status/status_deriver.py +62 -0
  164. autobyteus/agent_team/status/status_update_utils.py +42 -0
  165. autobyteus/agent_team/streaming/__init__.py +2 -2
  166. autobyteus/agent_team/streaming/agent_team_event_notifier.py +10 -10
  167. autobyteus/agent_team/streaming/agent_team_stream_event_payloads.py +7 -7
  168. autobyteus/agent_team/streaming/agent_team_stream_events.py +11 -11
  169. autobyteus/agent_team/system_prompt_processor/__init__.py +6 -0
  170. autobyteus/agent_team/system_prompt_processor/team_manifest_injector_processor.py +76 -0
  171. autobyteus/agent_team/task_notification/activation_policy.py +1 -1
  172. autobyteus/agent_team/task_notification/system_event_driven_agent_task_notifier.py +22 -22
  173. autobyteus/agent_team/task_notification/task_notification_mode.py +20 -1
  174. autobyteus/agent_team/utils/wait_for_idle.py +4 -4
  175. autobyteus/cli/agent_cli.py +18 -10
  176. autobyteus/cli/agent_team_tui/app.py +18 -15
  177. autobyteus/cli/agent_team_tui/state.py +21 -23
  178. autobyteus/cli/agent_team_tui/widgets/agent_list_sidebar.py +15 -15
  179. autobyteus/cli/agent_team_tui/widgets/focus_pane.py +146 -39
  180. autobyteus/cli/agent_team_tui/widgets/renderables.py +1 -1
  181. autobyteus/cli/agent_team_tui/widgets/shared.py +26 -26
  182. autobyteus/cli/agent_team_tui/widgets/{task_board_panel.py → task_plan_panel.py} +5 -5
  183. autobyteus/cli/cli_display.py +193 -44
  184. autobyteus/cli/workflow_tui/app.py +9 -10
  185. autobyteus/cli/workflow_tui/state.py +14 -16
  186. autobyteus/cli/workflow_tui/widgets/agent_list_sidebar.py +15 -15
  187. autobyteus/cli/workflow_tui/widgets/focus_pane.py +137 -35
  188. autobyteus/cli/workflow_tui/widgets/renderables.py +1 -1
  189. autobyteus/cli/workflow_tui/widgets/shared.py +25 -25
  190. autobyteus/clients/autobyteus_client.py +94 -1
  191. autobyteus/events/event_types.py +15 -21
  192. autobyteus/llm/api/autobyteus_llm.py +33 -29
  193. autobyteus/llm/api/claude_llm.py +142 -36
  194. autobyteus/llm/api/gemini_llm.py +163 -59
  195. autobyteus/llm/api/grok_llm.py +1 -1
  196. autobyteus/llm/api/minimax_llm.py +26 -0
  197. autobyteus/llm/api/mistral_llm.py +113 -87
  198. autobyteus/llm/api/ollama_llm.py +9 -42
  199. autobyteus/llm/api/openai_compatible_llm.py +127 -91
  200. autobyteus/llm/api/openai_llm.py +3 -3
  201. autobyteus/llm/api/openai_responses_llm.py +324 -0
  202. autobyteus/llm/api/zhipu_llm.py +21 -2
  203. autobyteus/llm/autobyteus_provider.py +70 -60
  204. autobyteus/llm/base_llm.py +85 -81
  205. autobyteus/llm/converters/__init__.py +14 -0
  206. autobyteus/llm/converters/anthropic_tool_call_converter.py +37 -0
  207. autobyteus/llm/converters/gemini_tool_call_converter.py +57 -0
  208. autobyteus/llm/converters/mistral_tool_call_converter.py +37 -0
  209. autobyteus/llm/converters/openai_tool_call_converter.py +38 -0
  210. autobyteus/llm/extensions/base_extension.py +6 -12
  211. autobyteus/llm/extensions/token_usage_tracking_extension.py +45 -18
  212. autobyteus/llm/llm_factory.py +282 -204
  213. autobyteus/llm/lmstudio_provider.py +60 -49
  214. autobyteus/llm/models.py +35 -2
  215. autobyteus/llm/ollama_provider.py +60 -49
  216. autobyteus/llm/ollama_provider_resolver.py +0 -1
  217. autobyteus/llm/prompt_renderers/__init__.py +19 -0
  218. autobyteus/llm/prompt_renderers/anthropic_prompt_renderer.py +104 -0
  219. autobyteus/llm/prompt_renderers/autobyteus_prompt_renderer.py +19 -0
  220. autobyteus/llm/prompt_renderers/base_prompt_renderer.py +10 -0
  221. autobyteus/llm/prompt_renderers/gemini_prompt_renderer.py +63 -0
  222. autobyteus/llm/prompt_renderers/mistral_prompt_renderer.py +87 -0
  223. autobyteus/llm/prompt_renderers/ollama_prompt_renderer.py +51 -0
  224. autobyteus/llm/prompt_renderers/openai_chat_renderer.py +97 -0
  225. autobyteus/llm/prompt_renderers/openai_responses_renderer.py +101 -0
  226. autobyteus/llm/providers.py +1 -3
  227. autobyteus/llm/token_counter/claude_token_counter.py +56 -25
  228. autobyteus/llm/token_counter/mistral_token_counter.py +12 -8
  229. autobyteus/llm/token_counter/openai_token_counter.py +24 -5
  230. autobyteus/llm/token_counter/token_counter_factory.py +12 -5
  231. autobyteus/llm/utils/llm_config.py +6 -12
  232. autobyteus/llm/utils/media_payload_formatter.py +27 -20
  233. autobyteus/llm/utils/messages.py +55 -3
  234. autobyteus/llm/utils/response_types.py +3 -0
  235. autobyteus/llm/utils/tool_call_delta.py +31 -0
  236. autobyteus/memory/__init__.py +32 -0
  237. autobyteus/memory/active_transcript.py +69 -0
  238. autobyteus/memory/compaction/__init__.py +9 -0
  239. autobyteus/memory/compaction/compaction_result.py +8 -0
  240. autobyteus/memory/compaction/compactor.py +89 -0
  241. autobyteus/memory/compaction/summarizer.py +11 -0
  242. autobyteus/memory/compaction_snapshot_builder.py +84 -0
  243. autobyteus/memory/memory_manager.py +183 -0
  244. autobyteus/memory/models/__init__.py +14 -0
  245. autobyteus/memory/models/episodic_item.py +41 -0
  246. autobyteus/memory/models/memory_types.py +7 -0
  247. autobyteus/memory/models/raw_trace_item.py +79 -0
  248. autobyteus/memory/models/semantic_item.py +41 -0
  249. autobyteus/memory/models/tool_interaction.py +20 -0
  250. autobyteus/memory/policies/__init__.py +5 -0
  251. autobyteus/memory/policies/compaction_policy.py +16 -0
  252. autobyteus/memory/retrieval/__init__.py +7 -0
  253. autobyteus/memory/retrieval/memory_bundle.py +11 -0
  254. autobyteus/memory/retrieval/retriever.py +13 -0
  255. autobyteus/memory/store/__init__.py +7 -0
  256. autobyteus/memory/store/base_store.py +14 -0
  257. autobyteus/memory/store/file_store.py +98 -0
  258. autobyteus/memory/tool_interaction_builder.py +46 -0
  259. autobyteus/memory/turn_tracker.py +9 -0
  260. autobyteus/multimedia/audio/api/__init__.py +3 -2
  261. autobyteus/multimedia/audio/api/autobyteus_audio_client.py +19 -5
  262. autobyteus/multimedia/audio/api/gemini_audio_client.py +108 -16
  263. autobyteus/multimedia/audio/api/openai_audio_client.py +112 -0
  264. autobyteus/multimedia/audio/audio_client_factory.py +84 -9
  265. autobyteus/multimedia/audio/audio_model.py +2 -1
  266. autobyteus/multimedia/image/api/autobyteus_image_client.py +19 -5
  267. autobyteus/multimedia/image/api/gemini_image_client.py +38 -17
  268. autobyteus/multimedia/image/api/openai_image_client.py +125 -43
  269. autobyteus/multimedia/image/autobyteus_image_provider.py +2 -1
  270. autobyteus/multimedia/image/image_client_factory.py +47 -15
  271. autobyteus/multimedia/image/image_model.py +5 -2
  272. autobyteus/multimedia/providers.py +3 -2
  273. autobyteus/skills/loader.py +71 -0
  274. autobyteus/skills/model.py +11 -0
  275. autobyteus/skills/registry.py +70 -0
  276. autobyteus/task_management/__init__.py +43 -20
  277. autobyteus/task_management/{base_task_board.py → base_task_plan.py} +16 -13
  278. autobyteus/task_management/converters/__init__.py +2 -2
  279. autobyteus/task_management/converters/{task_board_converter.py → task_plan_converter.py} +13 -13
  280. autobyteus/task_management/events.py +7 -7
  281. autobyteus/task_management/{in_memory_task_board.py → in_memory_task_plan.py} +34 -22
  282. autobyteus/task_management/schemas/__init__.py +3 -0
  283. autobyteus/task_management/schemas/task_status_report.py +2 -2
  284. autobyteus/task_management/schemas/todo_definition.py +15 -0
  285. autobyteus/task_management/todo.py +29 -0
  286. autobyteus/task_management/todo_list.py +75 -0
  287. autobyteus/task_management/tools/__init__.py +24 -8
  288. autobyteus/task_management/tools/task_tools/__init__.py +19 -0
  289. autobyteus/task_management/tools/{assign_task_to.py → task_tools/assign_task_to.py} +18 -18
  290. autobyteus/task_management/tools/{publish_task.py → task_tools/create_task.py} +16 -18
  291. autobyteus/task_management/tools/{publish_tasks.py → task_tools/create_tasks.py} +19 -19
  292. autobyteus/task_management/tools/{get_my_tasks.py → task_tools/get_my_tasks.py} +15 -15
  293. autobyteus/task_management/tools/{get_task_board_status.py → task_tools/get_task_plan_status.py} +16 -16
  294. autobyteus/task_management/tools/{update_task_status.py → task_tools/update_task_status.py} +16 -16
  295. autobyteus/task_management/tools/todo_tools/__init__.py +18 -0
  296. autobyteus/task_management/tools/todo_tools/add_todo.py +78 -0
  297. autobyteus/task_management/tools/todo_tools/create_todo_list.py +79 -0
  298. autobyteus/task_management/tools/todo_tools/get_todo_list.py +55 -0
  299. autobyteus/task_management/tools/todo_tools/update_todo_status.py +85 -0
  300. autobyteus/tools/__init__.py +43 -52
  301. autobyteus/tools/base_tool.py +7 -0
  302. autobyteus/tools/file/__init__.py +9 -0
  303. autobyteus/tools/file/patch_file.py +149 -0
  304. autobyteus/tools/file/{file_reader.py → read_file.py} +38 -7
  305. autobyteus/tools/file/{file_writer.py → write_file.py} +7 -4
  306. autobyteus/tools/functional_tool.py +53 -14
  307. autobyteus/tools/mcp/__init__.py +2 -0
  308. autobyteus/tools/mcp/config_service.py +5 -1
  309. autobyteus/tools/mcp/server/__init__.py +2 -0
  310. autobyteus/tools/mcp/server/http_managed_mcp_server.py +1 -1
  311. autobyteus/tools/mcp/server/websocket_managed_mcp_server.py +141 -0
  312. autobyteus/tools/mcp/server_instance_manager.py +8 -1
  313. autobyteus/tools/mcp/tool.py +3 -3
  314. autobyteus/tools/mcp/tool_registrar.py +5 -2
  315. autobyteus/tools/mcp/types.py +61 -0
  316. autobyteus/tools/multimedia/__init__.py +2 -1
  317. autobyteus/tools/multimedia/audio_tools.py +72 -19
  318. autobyteus/tools/{download_media_tool.py → multimedia/download_media_tool.py} +21 -7
  319. autobyteus/tools/multimedia/image_tools.py +248 -64
  320. autobyteus/tools/multimedia/media_reader_tool.py +1 -1
  321. autobyteus/tools/operation_executor/journal_manager.py +107 -0
  322. autobyteus/tools/operation_executor/operation_event_buffer.py +57 -0
  323. autobyteus/tools/operation_executor/operation_event_producer.py +29 -0
  324. autobyteus/tools/operation_executor/operation_executor.py +58 -0
  325. autobyteus/tools/registry/tool_definition.py +108 -14
  326. autobyteus/tools/registry/tool_registry.py +29 -0
  327. autobyteus/tools/search/__init__.py +17 -0
  328. autobyteus/tools/search/base_strategy.py +35 -0
  329. autobyteus/tools/search/client.py +24 -0
  330. autobyteus/tools/search/factory.py +81 -0
  331. autobyteus/tools/search/google_cse_strategy.py +68 -0
  332. autobyteus/tools/search/providers.py +10 -0
  333. autobyteus/tools/search/serpapi_strategy.py +65 -0
  334. autobyteus/tools/search/serper_strategy.py +87 -0
  335. autobyteus/tools/search_tool.py +83 -0
  336. autobyteus/tools/skill/load_skill.py +50 -0
  337. autobyteus/tools/terminal/__init__.py +45 -0
  338. autobyteus/tools/terminal/ansi_utils.py +32 -0
  339. autobyteus/tools/terminal/background_process_manager.py +233 -0
  340. autobyteus/tools/terminal/output_buffer.py +105 -0
  341. autobyteus/tools/terminal/prompt_detector.py +63 -0
  342. autobyteus/tools/terminal/pty_session.py +241 -0
  343. autobyteus/tools/terminal/session_factory.py +20 -0
  344. autobyteus/tools/terminal/terminal_session_manager.py +226 -0
  345. autobyteus/tools/terminal/tools/__init__.py +13 -0
  346. autobyteus/tools/terminal/tools/get_process_output.py +81 -0
  347. autobyteus/tools/terminal/tools/run_bash.py +109 -0
  348. autobyteus/tools/terminal/tools/start_background_process.py +104 -0
  349. autobyteus/tools/terminal/tools/stop_background_process.py +67 -0
  350. autobyteus/tools/terminal/types.py +54 -0
  351. autobyteus/tools/terminal/wsl_tmux_session.py +221 -0
  352. autobyteus/tools/terminal/wsl_utils.py +156 -0
  353. autobyteus/tools/tool_meta.py +4 -24
  354. autobyteus/tools/transaction_management/backup_handler.py +48 -0
  355. autobyteus/tools/transaction_management/operation_lifecycle_manager.py +62 -0
  356. autobyteus/tools/usage/__init__.py +1 -2
  357. autobyteus/tools/usage/formatters/__init__.py +17 -1
  358. autobyteus/tools/usage/formatters/base_formatter.py +8 -0
  359. autobyteus/tools/usage/formatters/default_xml_schema_formatter.py +2 -2
  360. autobyteus/tools/usage/formatters/mistral_json_schema_formatter.py +18 -0
  361. autobyteus/tools/usage/formatters/patch_file_xml_example_formatter.py +64 -0
  362. autobyteus/tools/usage/formatters/patch_file_xml_schema_formatter.py +31 -0
  363. autobyteus/tools/usage/formatters/run_bash_xml_example_formatter.py +32 -0
  364. autobyteus/tools/usage/formatters/run_bash_xml_schema_formatter.py +36 -0
  365. autobyteus/tools/usage/formatters/write_file_xml_example_formatter.py +53 -0
  366. autobyteus/tools/usage/formatters/write_file_xml_schema_formatter.py +31 -0
  367. autobyteus/tools/usage/providers/tool_manifest_provider.py +10 -10
  368. autobyteus/tools/usage/registries/__init__.py +1 -3
  369. autobyteus/tools/usage/registries/tool_formatting_registry.py +115 -8
  370. autobyteus/tools/usage/tool_schema_provider.py +51 -0
  371. autobyteus/tools/web/__init__.py +4 -0
  372. autobyteus/tools/web/read_url_tool.py +80 -0
  373. autobyteus/utils/diff_utils.py +271 -0
  374. autobyteus/utils/download_utils.py +109 -0
  375. autobyteus/utils/file_utils.py +57 -2
  376. autobyteus/utils/gemini_helper.py +56 -0
  377. autobyteus/utils/gemini_model_mapping.py +71 -0
  378. autobyteus/utils/llm_output_formatter.py +75 -0
  379. autobyteus/utils/tool_call_format.py +36 -0
  380. autobyteus/workflow/agentic_workflow.py +3 -3
  381. autobyteus/workflow/bootstrap_steps/agent_tool_injection_step.py +2 -2
  382. autobyteus/workflow/bootstrap_steps/base_workflow_bootstrap_step.py +2 -2
  383. autobyteus/workflow/bootstrap_steps/coordinator_initialization_step.py +2 -2
  384. autobyteus/workflow/bootstrap_steps/coordinator_prompt_preparation_step.py +4 -11
  385. autobyteus/workflow/bootstrap_steps/workflow_bootstrapper.py +6 -6
  386. autobyteus/workflow/bootstrap_steps/workflow_runtime_queue_initialization_step.py +2 -2
  387. autobyteus/workflow/context/workflow_context.py +3 -3
  388. autobyteus/workflow/context/workflow_runtime_state.py +5 -5
  389. autobyteus/workflow/events/workflow_event_dispatcher.py +5 -5
  390. autobyteus/workflow/handlers/lifecycle_workflow_event_handler.py +3 -3
  391. autobyteus/workflow/handlers/process_user_message_event_handler.py +5 -5
  392. autobyteus/workflow/handlers/tool_approval_workflow_event_handler.py +2 -2
  393. autobyteus/workflow/runtime/workflow_runtime.py +8 -8
  394. autobyteus/workflow/runtime/workflow_worker.py +3 -3
  395. autobyteus/workflow/status/__init__.py +11 -0
  396. autobyteus/workflow/status/workflow_status.py +19 -0
  397. autobyteus/workflow/status/workflow_status_manager.py +48 -0
  398. autobyteus/workflow/streaming/__init__.py +2 -2
  399. autobyteus/workflow/streaming/workflow_event_notifier.py +7 -7
  400. autobyteus/workflow/streaming/workflow_stream_event_payloads.py +4 -4
  401. autobyteus/workflow/streaming/workflow_stream_events.py +3 -3
  402. autobyteus/workflow/utils/wait_for_idle.py +4 -4
  403. autobyteus-1.2.3.dist-info/METADATA +293 -0
  404. autobyteus-1.2.3.dist-info/RECORD +600 -0
  405. {autobyteus-1.2.0.dist-info → autobyteus-1.2.3.dist-info}/WHEEL +1 -1
  406. {autobyteus-1.2.0.dist-info → autobyteus-1.2.3.dist-info}/top_level.txt +0 -1
  407. autobyteus/agent/bootstrap_steps/agent_runtime_queue_initialization_step.py +0 -57
  408. autobyteus/agent/hooks/__init__.py +0 -16
  409. autobyteus/agent/hooks/base_phase_hook.py +0 -78
  410. autobyteus/agent/hooks/hook_definition.py +0 -36
  411. autobyteus/agent/hooks/hook_meta.py +0 -37
  412. autobyteus/agent/hooks/hook_registry.py +0 -106
  413. autobyteus/agent/llm_response_processor/provider_aware_tool_usage_processor.py +0 -103
  414. autobyteus/agent/phases/__init__.py +0 -18
  415. autobyteus/agent/phases/discover.py +0 -53
  416. autobyteus/agent/phases/manager.py +0 -265
  417. autobyteus/agent/phases/transition_decorator.py +0 -40
  418. autobyteus/agent/phases/transition_info.py +0 -33
  419. autobyteus/agent/remote_agent.py +0 -244
  420. autobyteus/agent/workspace/workspace_definition.py +0 -36
  421. autobyteus/agent/workspace/workspace_meta.py +0 -37
  422. autobyteus/agent/workspace/workspace_registry.py +0 -72
  423. autobyteus/agent_team/bootstrap_steps/agent_team_runtime_queue_initialization_step.py +0 -25
  424. autobyteus/agent_team/bootstrap_steps/coordinator_prompt_preparation_step.py +0 -85
  425. autobyteus/agent_team/phases/__init__.py +0 -11
  426. autobyteus/agent_team/phases/agent_team_operational_phase.py +0 -19
  427. autobyteus/agent_team/phases/agent_team_phase_manager.py +0 -48
  428. autobyteus/llm/api/bedrock_llm.py +0 -92
  429. autobyteus/llm/api/groq_llm.py +0 -94
  430. autobyteus/llm/api/nvidia_llm.py +0 -108
  431. autobyteus/llm/utils/token_pricing_config.py +0 -87
  432. autobyteus/person/examples/sample_persons.py +0 -14
  433. autobyteus/person/examples/sample_roles.py +0 -14
  434. autobyteus/person/person.py +0 -29
  435. autobyteus/person/role.py +0 -14
  436. autobyteus/rpc/__init__.py +0 -73
  437. autobyteus/rpc/client/__init__.py +0 -17
  438. autobyteus/rpc/client/abstract_client_connection.py +0 -124
  439. autobyteus/rpc/client/client_connection_manager.py +0 -153
  440. autobyteus/rpc/client/sse_client_connection.py +0 -306
  441. autobyteus/rpc/client/stdio_client_connection.py +0 -280
  442. autobyteus/rpc/config/__init__.py +0 -13
  443. autobyteus/rpc/config/agent_server_config.py +0 -153
  444. autobyteus/rpc/config/agent_server_registry.py +0 -152
  445. autobyteus/rpc/hosting.py +0 -244
  446. autobyteus/rpc/protocol.py +0 -244
  447. autobyteus/rpc/server/__init__.py +0 -20
  448. autobyteus/rpc/server/agent_server_endpoint.py +0 -181
  449. autobyteus/rpc/server/base_method_handler.py +0 -40
  450. autobyteus/rpc/server/method_handlers.py +0 -259
  451. autobyteus/rpc/server/sse_server_handler.py +0 -182
  452. autobyteus/rpc/server/stdio_server_handler.py +0 -151
  453. autobyteus/rpc/server_main.py +0 -198
  454. autobyteus/rpc/transport_type.py +0 -13
  455. autobyteus/tools/bash/__init__.py +0 -2
  456. autobyteus/tools/bash/bash_executor.py +0 -100
  457. autobyteus/tools/browser/__init__.py +0 -2
  458. autobyteus/tools/browser/session_aware/__init__.py +0 -0
  459. autobyteus/tools/browser/session_aware/browser_session_aware_navigate_to.py +0 -75
  460. autobyteus/tools/browser/session_aware/browser_session_aware_tool.py +0 -30
  461. autobyteus/tools/browser/session_aware/browser_session_aware_web_element_trigger.py +0 -154
  462. autobyteus/tools/browser/session_aware/browser_session_aware_webpage_reader.py +0 -89
  463. autobyteus/tools/browser/session_aware/browser_session_aware_webpage_screenshot_taker.py +0 -107
  464. autobyteus/tools/browser/session_aware/factory/__init__.py +0 -0
  465. autobyteus/tools/browser/session_aware/factory/browser_session_aware_web_element_trigger_factory.py +0 -14
  466. autobyteus/tools/browser/session_aware/factory/browser_session_aware_webpage_reader_factory.py +0 -26
  467. autobyteus/tools/browser/session_aware/factory/browser_session_aware_webpage_screenshot_taker_factory.py +0 -14
  468. autobyteus/tools/browser/session_aware/shared_browser_session.py +0 -11
  469. autobyteus/tools/browser/session_aware/shared_browser_session_manager.py +0 -25
  470. autobyteus/tools/browser/session_aware/web_element_action.py +0 -20
  471. autobyteus/tools/browser/standalone/__init__.py +0 -6
  472. autobyteus/tools/browser/standalone/factory/__init__.py +0 -0
  473. autobyteus/tools/browser/standalone/factory/webpage_reader_factory.py +0 -25
  474. autobyteus/tools/browser/standalone/factory/webpage_screenshot_taker_factory.py +0 -14
  475. autobyteus/tools/browser/standalone/navigate_to.py +0 -80
  476. autobyteus/tools/browser/standalone/web_page_pdf_generator.py +0 -97
  477. autobyteus/tools/browser/standalone/webpage_image_downloader.py +0 -165
  478. autobyteus/tools/browser/standalone/webpage_reader.py +0 -101
  479. autobyteus/tools/browser/standalone/webpage_screenshot_taker.py +0 -101
  480. autobyteus/tools/file/file_editor.py +0 -200
  481. autobyteus/tools/google_search.py +0 -149
  482. autobyteus/tools/timer.py +0 -171
  483. autobyteus/tools/usage/parsers/__init__.py +0 -22
  484. autobyteus/tools/usage/parsers/_json_extractor.py +0 -99
  485. autobyteus/tools/usage/parsers/_string_decoders.py +0 -18
  486. autobyteus/tools/usage/parsers/anthropic_xml_tool_usage_parser.py +0 -10
  487. autobyteus/tools/usage/parsers/base_parser.py +0 -41
  488. autobyteus/tools/usage/parsers/default_json_tool_usage_parser.py +0 -83
  489. autobyteus/tools/usage/parsers/default_xml_tool_usage_parser.py +0 -316
  490. autobyteus/tools/usage/parsers/exceptions.py +0 -13
  491. autobyteus/tools/usage/parsers/gemini_json_tool_usage_parser.py +0 -77
  492. autobyteus/tools/usage/parsers/openai_json_tool_usage_parser.py +0 -149
  493. autobyteus/tools/usage/parsers/provider_aware_tool_usage_parser.py +0 -59
  494. autobyteus/tools/usage/registries/tool_usage_parser_registry.py +0 -62
  495. autobyteus/workflow/phases/__init__.py +0 -11
  496. autobyteus/workflow/phases/workflow_operational_phase.py +0 -19
  497. autobyteus/workflow/phases/workflow_phase_manager.py +0 -48
  498. autobyteus-1.2.0.dist-info/METADATA +0 -205
  499. autobyteus-1.2.0.dist-info/RECORD +0 -496
  500. examples/__init__.py +0 -1
  501. examples/agent_team/__init__.py +0 -1
  502. examples/discover_phase_transitions.py +0 -104
  503. examples/run_browser_agent.py +0 -262
  504. examples/run_google_slides_agent.py +0 -287
  505. examples/run_mcp_browser_client.py +0 -174
  506. examples/run_mcp_google_slides_client.py +0 -270
  507. examples/run_mcp_list_tools.py +0 -189
  508. examples/run_poem_writer.py +0 -284
  509. examples/run_sqlite_agent.py +0 -295
  510. /autobyteus/{person → skills}/__init__.py +0 -0
  511. /autobyteus/{person/examples → tools/skill}/__init__.py +0 -0
  512. {autobyteus-1.2.0.dist-info → autobyteus-1.2.3.dist-info}/licenses/LICENSE +0 -0
@@ -0,0 +1,146 @@
1
+ """
2
+ DelimitedContentState: Base state for content blocks terminated by a closing tag.
3
+
4
+ Provides streaming-safe emission with a holdback tail to prevent partial
5
+ closing tags from being emitted.
6
+ """
7
+ from typing import TYPE_CHECKING, Optional, Dict
8
+
9
+ from .base_state import BaseState
10
+ from ..events import SegmentType
11
+
12
+ if TYPE_CHECKING:
13
+ from ..parser_context import ParserContext
14
+
15
+
16
+ class DelimitedContentState(BaseState):
17
+ """
18
+ Base class for parsing delimited content blocks.
19
+
20
+ Subclasses must define:
21
+ - CLOSING_TAG: The closing tag string (e.g., "</file>")
22
+ - SEGMENT_TYPE: SegmentType for emitted segments
23
+ """
24
+
25
+ CLOSING_TAG = ""
26
+ SEGMENT_TYPE: Optional[SegmentType] = None
27
+
28
+ def __init__(
29
+ self,
30
+ context: "ParserContext",
31
+ opening_tag: str,
32
+ closing_tag_override: Optional[str] = None,
33
+ ):
34
+ super().__init__(context)
35
+ self._opening_tag = opening_tag
36
+ self._segment_started = False
37
+ self._tail = ""
38
+ self._closing_tag = closing_tag_override if closing_tag_override is not None else self.CLOSING_TAG
39
+ self._closing_tag_lower = self._closing_tag.lower()
40
+ self._holdback_len = max(len(self._closing_tag) - 1, 0)
41
+
42
+ def _can_start_segment(self) -> bool:
43
+ """Return False to emit opening tag as text and abort."""
44
+ return True
45
+
46
+ def _get_start_metadata(self) -> Dict[str, str]:
47
+ """Metadata to include on segment start."""
48
+ return {}
49
+
50
+ def _opening_content(self) -> Optional[str]:
51
+ """Optional content to emit immediately after segment start."""
52
+ return None
53
+
54
+ def _on_segment_complete(self) -> None:
55
+ """Hook invoked just before segment end is emitted."""
56
+ return None
57
+
58
+ def _should_emit_closing_tag(self) -> bool:
59
+ """Whether to emit the closing tag as content."""
60
+ return False
61
+
62
+ def run(self) -> None:
63
+ from .text_state import TextState
64
+
65
+ if not self._segment_started:
66
+ if not self._can_start_segment():
67
+ self.context.append_text_segment(self._opening_tag)
68
+ self.context.transition_to(TextState(self.context))
69
+ return
70
+
71
+ if self.SEGMENT_TYPE is None:
72
+ raise RuntimeError("SEGMENT_TYPE is not defined for DelimitedContentState.")
73
+
74
+ self.context.emit_segment_start(self.SEGMENT_TYPE, **self._get_start_metadata())
75
+ self._segment_started = True
76
+
77
+ opening_content = self._opening_content()
78
+ if opening_content:
79
+ self.context.emit_segment_content(opening_content)
80
+
81
+ if not self.context.has_more_chars():
82
+ return
83
+
84
+ available = self.context.consume_remaining()
85
+ combined = self._tail + available
86
+
87
+ if combined:
88
+ idx = combined.lower().find(self._closing_tag_lower)
89
+ else:
90
+ idx = -1
91
+
92
+ if idx != -1:
93
+ content_before = combined[:idx]
94
+ if content_before:
95
+ self.context.emit_segment_content(content_before)
96
+
97
+ if self._should_emit_closing_tag() and self._closing_tag:
98
+ self.context.emit_segment_content(self._closing_tag)
99
+
100
+ tail_len = len(self._tail)
101
+ closing_len = len(self._closing_tag)
102
+ if idx < tail_len:
103
+ consumed_from_available = idx + closing_len - tail_len
104
+ else:
105
+ consumed_from_available = (idx - tail_len) + closing_len
106
+
107
+ extra = len(available) - consumed_from_available
108
+ if extra > 0:
109
+ self.context.rewind_by(extra)
110
+
111
+ self._tail = ""
112
+ self._on_segment_complete()
113
+ self.context.emit_segment_end()
114
+ self.context.transition_to(TextState(self.context))
115
+ return
116
+
117
+ if self._holdback_len == 0:
118
+ if combined:
119
+ self.context.emit_segment_content(combined)
120
+ self._tail = ""
121
+ return
122
+
123
+ if len(combined) > self._holdback_len:
124
+ safe = combined[:-self._holdback_len]
125
+ if safe:
126
+ self.context.emit_segment_content(safe)
127
+ self._tail = combined[-self._holdback_len:]
128
+ else:
129
+ self._tail = combined
130
+
131
+ def finalize(self) -> None:
132
+ from .text_state import TextState
133
+
134
+ remaining = self.context.consume_remaining() if self.context.has_more_chars() else ""
135
+
136
+ if not self._segment_started:
137
+ text = self._opening_tag + self._tail + remaining
138
+ if text:
139
+ self.context.append_text_segment(text)
140
+ else:
141
+ if self._tail or remaining:
142
+ self.context.emit_segment_content(self._tail + remaining)
143
+ self._tail = ""
144
+ self.context.emit_segment_end()
145
+
146
+ self.context.transition_to(TextState(self.context))
@@ -0,0 +1,144 @@
1
+ """
2
+ JsonInitializationState: Analyzes potential JSON tool calls after a '{' or '[' is detected.
3
+
4
+ This state buffers characters to determine if a JSON structure is a tool call
5
+ based on a signature check strategy. Used for providers like OpenAI that use
6
+ JSON format instead of XML.
7
+ """
8
+ from typing import TYPE_CHECKING, Optional, List
9
+
10
+ from .base_state import BaseState
11
+ from ..events import SegmentType
12
+
13
+ if TYPE_CHECKING:
14
+ from ..parser_context import ParserContext
15
+
16
+
17
+ class JsonToolSignatureChecker:
18
+ """
19
+ Checks if a JSON buffer matches known tool call signatures.
20
+
21
+ Common JSON tool call formats:
22
+ - OpenAI: {"name": "tool_name", "arguments": {...}}
23
+ - Anthropic: Similar structure
24
+
25
+ Returns:
26
+ - 'match': Buffer matches a tool signature
27
+ - 'partial': Buffer could still match (keep buffering)
28
+ - 'no_match': Buffer definitely not a tool call
29
+ """
30
+
31
+ def __init__(self, patterns: Optional[List[str]] = None):
32
+ """
33
+ Initialize with custom patterns or defaults.
34
+
35
+ Args:
36
+ patterns: List of JSON prefixes that indicate tool calls.
37
+ Uses defaults if not provided.
38
+ """
39
+ from ..parser_context import ParserConfig
40
+ self._patterns = patterns or ParserConfig.DEFAULT_JSON_PATTERNS
41
+
42
+ def check_signature(self, buffer: str) -> str:
43
+ """
44
+ Check if the buffer matches a tool call signature.
45
+
46
+ Returns 'match', 'partial', or 'no_match'.
47
+ """
48
+ # Normalize whitespace for checking
49
+ normalized = buffer.replace(" ", "").replace("\n", "").replace("\t", "")
50
+
51
+ for pattern in self._patterns:
52
+ normalized_pattern = pattern.replace(" ", "")
53
+
54
+ # Exact prefix match - it's a tool call
55
+ if normalized.startswith(normalized_pattern):
56
+ return 'match'
57
+
58
+ # Could still become this pattern
59
+ if normalized_pattern.startswith(normalized):
60
+ return 'partial'
61
+
62
+ # Check if we're still in the opening portion
63
+ # Allow for whitespace variations like { "name" or {\n"name"
64
+ if len(normalized) < 8: # Short buffer, still checking
65
+ if normalized in ['', '{', '[', '{"', '[{', '{"n', '{"na', '{"nam']:
66
+ return 'partial'
67
+
68
+ return 'no_match'
69
+
70
+
71
+ class JsonInitializationState(BaseState):
72
+ """
73
+ Analyzes a potential JSON tool call to determine if it's a known format.
74
+
75
+ This state is entered when a '{' or '[' is detected and JSON parsing is enabled.
76
+ It buffers characters to check for tool call signatures.
77
+ """
78
+
79
+ def __init__(self, context: "ParserContext"):
80
+ super().__init__(context)
81
+ # Consume the trigger character that caused this transition
82
+ trigger = self.context.peek_char()
83
+ self.context.advance()
84
+ self._signature_buffer = trigger if trigger else ""
85
+ # Use patterns from config
86
+ self._checker = JsonToolSignatureChecker(context.json_tool_patterns)
87
+
88
+ def run(self) -> None:
89
+ """
90
+ Buffer characters and check for tool call signatures.
91
+
92
+ If a match is found, transitions to XmlToolParsingState (JSON mode).
93
+ If no match, reverts the buffer to text.
94
+ """
95
+ from .text_state import TextState
96
+ from .json_tool_parsing_state import JsonToolParsingState
97
+
98
+ while self.context.has_more_chars():
99
+ char = self.context.peek_char()
100
+ self._signature_buffer += char
101
+ self.context.advance()
102
+
103
+ match = self._checker.check_signature(self._signature_buffer)
104
+
105
+ if match == 'match':
106
+ # Found a tool signature
107
+ if self.context.parse_tool_calls:
108
+ if self.context.get_current_segment_type() == SegmentType.TEXT:
109
+ self.context.emit_segment_end()
110
+ # Signature buffer already consumed by this state; pass it along.
111
+ self.context.transition_to(
112
+ JsonToolParsingState(
113
+ self.context,
114
+ self._signature_buffer,
115
+ signature_consumed=True,
116
+ )
117
+ )
118
+ else:
119
+ # Tool parsing disabled - emit as text
120
+ self.context.append_text_segment(self._signature_buffer)
121
+ self.context.transition_to(TextState(self.context))
122
+ return
123
+
124
+ if match == 'no_match':
125
+ # Not a tool call - emit as text
126
+ self.context.append_text_segment(self._signature_buffer)
127
+ self.context.transition_to(TextState(self.context))
128
+ return
129
+
130
+ # 'partial' - continue buffering
131
+
132
+ def finalize(self) -> None:
133
+ """
134
+ Called when stream ends while checking JSON signature.
135
+
136
+ Emit buffered content as text.
137
+ """
138
+ from .text_state import TextState
139
+
140
+ if self._signature_buffer:
141
+ self.context.append_text_segment(self._signature_buffer)
142
+ self._signature_buffer = ""
143
+
144
+ self.context.transition_to(TextState(self.context))
@@ -0,0 +1,137 @@
1
+ """
2
+ JsonToolParsingState: Streams JSON tool call content.
3
+
4
+ This state identifies JSON tool-call boundaries and streams raw JSON content.
5
+ Tool arguments are parsed later by the ToolInvocationAdapter.
6
+ """
7
+ from typing import TYPE_CHECKING, List
8
+
9
+ from .base_state import BaseState
10
+ from ..events import SegmentType
11
+
12
+ if TYPE_CHECKING:
13
+ from ..parser_context import ParserContext
14
+
15
+
16
+ class JsonToolParsingState(BaseState):
17
+ """
18
+ Streams JSON tool call content.
19
+
20
+ Expected formats:
21
+ - {"name": "tool_name", "arguments": {...}}
22
+ - [{"name": "tool_name", "arguments": {...}}]
23
+
24
+ Handles nested braces and proper JSON boundary detection.
25
+ """
26
+
27
+ def __init__(
28
+ self,
29
+ context: "ParserContext",
30
+ signature_buffer: str,
31
+ signature_consumed: bool = False,
32
+ ):
33
+ super().__init__(context)
34
+ self._signature_buffer = signature_buffer
35
+ self._signature_consumed = signature_consumed
36
+ self._brace_count = 0
37
+ self._bracket_count = 0
38
+ self._in_string = False
39
+ self._escape_next = False
40
+ self._segment_started = False
41
+ self._initialized = False
42
+ self._is_array = signature_buffer.startswith('[')
43
+
44
+ def run(self) -> None:
45
+ """
46
+ Parse JSON tool content, tracking nested braces.
47
+ """
48
+ from .text_state import TextState
49
+
50
+ if not self._segment_started:
51
+ self.context.emit_segment_start(SegmentType.TOOL_CALL)
52
+ self._segment_started = True
53
+
54
+ consumed: List[str] = []
55
+
56
+ if not self._initialized:
57
+ if self._signature_consumed:
58
+ consumed.append(self._signature_buffer)
59
+ for char in self._signature_buffer:
60
+ self._update_brace_count(char)
61
+ else:
62
+ signature = self.context.consume(len(self._signature_buffer))
63
+ if signature:
64
+ consumed.append(signature)
65
+ for char in signature:
66
+ self._update_brace_count(char)
67
+ self._initialized = True
68
+
69
+ while self.context.has_more_chars():
70
+ char = self.context.peek_char()
71
+ self.context.advance()
72
+ consumed.append(char)
73
+ self._update_brace_count(char)
74
+
75
+ if self._is_json_complete():
76
+ if consumed:
77
+ self.context.emit_segment_content("".join(consumed))
78
+
79
+ self.context.emit_segment_end()
80
+ self.context.transition_to(TextState(self.context))
81
+ return
82
+
83
+ if consumed:
84
+ self.context.emit_segment_content("".join(consumed))
85
+
86
+ def _update_brace_count(self, char: str) -> None:
87
+ """Update brace/bracket count, handling strings."""
88
+ if self._escape_next:
89
+ self._escape_next = False
90
+ return
91
+
92
+ if char == '\\' and self._in_string:
93
+ self._escape_next = True
94
+ return
95
+
96
+ if char == '"' and not self._escape_next:
97
+ self._in_string = not self._in_string
98
+ return
99
+
100
+ if self._in_string:
101
+ return
102
+
103
+ if char == '{':
104
+ self._brace_count += 1
105
+ elif char == '}':
106
+ self._brace_count -= 1
107
+ elif char == '[':
108
+ self._bracket_count += 1
109
+ elif char == ']':
110
+ self._bracket_count -= 1
111
+
112
+ def _is_json_complete(self) -> bool:
113
+ """Check if we have a complete JSON structure."""
114
+ if self._in_string:
115
+ return False
116
+
117
+ if self._is_array:
118
+ return self._bracket_count == 0 and self._brace_count == 0
119
+ else:
120
+ return self._brace_count == 0
121
+
122
+ def finalize(self) -> None:
123
+ """
124
+ Called when stream ends while parsing JSON.
125
+
126
+ Emit any remaining content and close the segment.
127
+ """
128
+ from .text_state import TextState
129
+
130
+ if self.context.has_more_chars():
131
+ remaining = self.context.consume_remaining()
132
+ if remaining:
133
+ self.context.emit_segment_content(remaining)
134
+
135
+ if self._segment_started:
136
+ self.context.emit_segment_end()
137
+ self.context.transition_to(TextState(self.context))
@@ -0,0 +1,30 @@
1
+ """
2
+ SentinelContentState: Parses sentinel-delimited content blocks.
3
+ """
4
+ from typing import TYPE_CHECKING, Dict
5
+
6
+ from .delimited_content_state import DelimitedContentState
7
+ from ..sentinel_format import END_MARKER
8
+ from ..events import SegmentType
9
+
10
+ if TYPE_CHECKING:
11
+ from ..parser_context import ParserContext
12
+
13
+
14
+ class SentinelContentState(DelimitedContentState):
15
+ """
16
+ Parses content for a sentinel block until the matching end marker.
17
+ """
18
+
19
+ def __init__(
20
+ self,
21
+ context: "ParserContext",
22
+ segment_type: SegmentType,
23
+ metadata: Dict[str, object],
24
+ ):
25
+ self.SEGMENT_TYPE = segment_type
26
+ self._metadata = metadata
27
+ super().__init__(context, opening_tag="", closing_tag_override=END_MARKER)
28
+
29
+ def _get_start_metadata(self) -> dict:
30
+ return self._metadata
@@ -0,0 +1,117 @@
1
+ """
2
+ SentinelInitializationState: Parses sentinel start headers.
3
+ """
4
+ import json
5
+ from typing import TYPE_CHECKING, Dict, Optional
6
+
7
+ from .base_state import BaseState
8
+ from ..events import SegmentType
9
+ from ..sentinel_format import START_MARKER, MARKER_END
10
+
11
+ if TYPE_CHECKING:
12
+ from ..parser_context import ParserContext
13
+
14
+
15
+ class SentinelInitializationState(BaseState):
16
+ """
17
+ Parses the sentinel start header and transitions to content state.
18
+ """
19
+
20
+ def __init__(self, context: "ParserContext"):
21
+ super().__init__(context)
22
+ self._header_buffer = ""
23
+
24
+ def run(self) -> None:
25
+ from .text_state import TextState
26
+ from .sentinel_content_state import SentinelContentState
27
+
28
+ if not self.context.has_more_chars():
29
+ return
30
+
31
+ start_pos = self.context.get_position()
32
+ end_idx = self.context.find(MARKER_END, start_pos)
33
+
34
+ if end_idx == -1:
35
+ self._header_buffer += self.context.consume_remaining()
36
+ if not self._is_possible_prefix(self._header_buffer):
37
+ self.context.append_text_segment(self._header_buffer)
38
+ self.context.transition_to(TextState(self.context))
39
+ return
40
+
41
+ self._header_buffer += self.context.consume(end_idx - start_pos + len(MARKER_END))
42
+
43
+ if not self._header_buffer.startswith(START_MARKER):
44
+ self.context.append_text_segment(self._header_buffer)
45
+ self.context.transition_to(TextState(self.context))
46
+ return
47
+
48
+ header_json = self._header_buffer[len(START_MARKER):]
49
+ if header_json.endswith(MARKER_END):
50
+ header_json = header_json[:-len(MARKER_END)]
51
+ header_json = header_json.strip()
52
+
53
+ if not header_json:
54
+ self.context.append_text_segment(self._header_buffer)
55
+ self.context.transition_to(TextState(self.context))
56
+ return
57
+
58
+ data = self._parse_header_json(header_json)
59
+ if not data:
60
+ self.context.append_text_segment(self._header_buffer)
61
+ self.context.transition_to(TextState(self.context))
62
+ return
63
+
64
+ type_str = data.get("type")
65
+ segment_type = self._map_segment_type(type_str)
66
+
67
+ if segment_type is None:
68
+ self.context.append_text_segment(self._header_buffer)
69
+ self.context.transition_to(TextState(self.context))
70
+ return
71
+
72
+ metadata = dict(data)
73
+ metadata.pop("type", None)
74
+
75
+ if self.context.get_current_segment_type() == SegmentType.TEXT:
76
+ self.context.emit_segment_end()
77
+
78
+ self.context.transition_to(
79
+ SentinelContentState(
80
+ self.context,
81
+ segment_type=segment_type,
82
+ metadata=metadata,
83
+ )
84
+ )
85
+
86
+ def finalize(self) -> None:
87
+ from .text_state import TextState
88
+
89
+ if self.context.has_more_chars():
90
+ self._header_buffer += self.context.consume_remaining()
91
+
92
+ if self._header_buffer:
93
+ self.context.append_text_segment(self._header_buffer)
94
+ self.context.transition_to(TextState(self.context))
95
+
96
+ def _is_possible_prefix(self, buffer: str) -> bool:
97
+ return START_MARKER.startswith(buffer) or buffer.startswith(START_MARKER)
98
+
99
+ def _parse_header_json(self, header_json: str) -> Optional[Dict[str, object]]:
100
+ try:
101
+ data = json.loads(header_json)
102
+ return data if isinstance(data, dict) else None
103
+ except json.JSONDecodeError:
104
+ return None
105
+
106
+ def _map_segment_type(self, type_str: Optional[str]) -> Optional[SegmentType]:
107
+ if not type_str:
108
+ return None
109
+ value = type_str.strip().lower()
110
+ mapping = {
111
+ "text": SegmentType.TEXT,
112
+ "tool": SegmentType.TOOL_CALL,
113
+ "tool_call": SegmentType.TOOL_CALL,
114
+ "write_file": SegmentType.WRITE_FILE,
115
+ "run_bash": SegmentType.RUN_BASH,
116
+ }
117
+ return mapping.get(value)
@@ -0,0 +1,78 @@
1
+ """
2
+ TextState: Default state for parsing plain text.
3
+
4
+ This state consumes characters as text content and detects triggers
5
+ for transitioning to specialized parsing states (XML tags, JSON).
6
+ """
7
+ from typing import TYPE_CHECKING
8
+
9
+ from .base_state import BaseState
10
+ if TYPE_CHECKING:
11
+ from ..parser_context import ParserContext
12
+
13
+
14
+ class TextState(BaseState):
15
+ """
16
+ Default state for parsing plain text content.
17
+
18
+ This state:
19
+ - Accumulates text characters
20
+ - Detects '<' for potential XML tag transitions
21
+ - Detects '{' or '[' for potential JSON transitions (if enabled)
22
+ - Emits text segments when transitioning or at end of buffer
23
+ """
24
+
25
+ def __init__(self, context: "ParserContext"):
26
+ super().__init__(context)
27
+
28
+ def run(self) -> None:
29
+ """
30
+ Process characters as text until a trigger is found or buffer is exhausted.
31
+ """
32
+ # Import here to avoid circular dependency
33
+ from .xml_tag_initialization_state import XmlTagInitializationState
34
+
35
+ start_pos = self.context.get_position()
36
+
37
+ if not self.context.has_more_chars():
38
+ return
39
+
40
+ strategies = self.context.detection_strategies
41
+
42
+ best_idx = -1
43
+ best_strategy = None
44
+ for strategy in strategies:
45
+ idx = strategy.next_marker(self.context, start_pos)
46
+ if idx == -1:
47
+ continue
48
+ if best_idx == -1 or idx < best_idx:
49
+ best_idx = idx
50
+ best_strategy = strategy
51
+
52
+ if best_idx == -1:
53
+ text = self.context.substring(start_pos)
54
+ if text:
55
+ self.context.append_text_segment(text)
56
+ self.context.set_position(self.context.get_buffer_length())
57
+ return
58
+
59
+ if best_idx > start_pos:
60
+ text = self.context.substring(start_pos, best_idx)
61
+ if text:
62
+ self.context.append_text_segment(text)
63
+
64
+ self.context.set_position(best_idx)
65
+
66
+ if best_strategy is None:
67
+ self.context.transition_to(XmlTagInitializationState(self.context))
68
+ else:
69
+ self.context.transition_to(best_strategy.create_state(self.context))
70
+
71
+ def finalize(self) -> None:
72
+ """
73
+ Called when stream ends while in TextState.
74
+
75
+ Nothing special to do here since run() already emits text
76
+ when buffer is exhausted.
77
+ """
78
+ pass