autobyteus 1.2.1__py3-none-any.whl → 1.3.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- autobyteus/agent/agent.py +15 -5
- autobyteus/agent/bootstrap_steps/__init__.py +3 -3
- autobyteus/agent/bootstrap_steps/agent_bootstrapper.py +5 -59
- autobyteus/agent/bootstrap_steps/base_bootstrap_step.py +1 -4
- autobyteus/agent/bootstrap_steps/mcp_server_prewarming_step.py +1 -3
- autobyteus/agent/bootstrap_steps/system_prompt_processing_step.py +16 -13
- autobyteus/agent/bootstrap_steps/working_context_snapshot_restore_step.py +38 -0
- autobyteus/agent/bootstrap_steps/workspace_context_initialization_step.py +2 -4
- autobyteus/agent/context/agent_config.py +47 -20
- autobyteus/agent/context/agent_context.py +23 -18
- autobyteus/agent/context/agent_runtime_state.py +21 -19
- autobyteus/agent/events/__init__.py +16 -1
- autobyteus/agent/events/agent_events.py +43 -3
- autobyteus/agent/events/agent_input_event_queue_manager.py +79 -26
- autobyteus/agent/events/event_store.py +57 -0
- autobyteus/agent/events/notifiers.py +69 -59
- autobyteus/agent/events/worker_event_dispatcher.py +21 -64
- autobyteus/agent/factory/agent_factory.py +83 -6
- autobyteus/agent/handlers/__init__.py +2 -0
- autobyteus/agent/handlers/approved_tool_invocation_event_handler.py +51 -34
- autobyteus/agent/handlers/bootstrap_event_handler.py +155 -0
- autobyteus/agent/handlers/inter_agent_message_event_handler.py +10 -0
- autobyteus/agent/handlers/lifecycle_event_logger.py +19 -11
- autobyteus/agent/handlers/llm_complete_response_received_event_handler.py +10 -15
- autobyteus/agent/handlers/llm_user_message_ready_event_handler.py +188 -48
- autobyteus/agent/handlers/tool_execution_approval_event_handler.py +0 -10
- autobyteus/agent/handlers/tool_invocation_request_event_handler.py +53 -48
- autobyteus/agent/handlers/tool_result_event_handler.py +7 -8
- autobyteus/agent/handlers/user_input_message_event_handler.py +10 -3
- autobyteus/agent/input_processor/memory_ingest_input_processor.py +44 -0
- autobyteus/agent/lifecycle/__init__.py +12 -0
- autobyteus/agent/lifecycle/base_processor.py +109 -0
- autobyteus/agent/lifecycle/events.py +35 -0
- autobyteus/agent/lifecycle/processor_definition.py +36 -0
- autobyteus/agent/lifecycle/processor_registry.py +106 -0
- autobyteus/agent/llm_request_assembler.py +98 -0
- autobyteus/agent/llm_response_processor/__init__.py +1 -8
- autobyteus/agent/message/context_file_type.py +1 -1
- autobyteus/agent/runtime/agent_runtime.py +29 -21
- autobyteus/agent/runtime/agent_worker.py +98 -19
- autobyteus/agent/shutdown_steps/__init__.py +2 -0
- autobyteus/agent/shutdown_steps/agent_shutdown_orchestrator.py +2 -0
- autobyteus/agent/shutdown_steps/tool_cleanup_step.py +58 -0
- autobyteus/agent/status/__init__.py +14 -0
- autobyteus/agent/status/manager.py +93 -0
- autobyteus/agent/status/status_deriver.py +96 -0
- autobyteus/agent/{phases/phase_enum.py → status/status_enum.py} +16 -16
- autobyteus/agent/status/status_update_utils.py +73 -0
- autobyteus/agent/streaming/__init__.py +52 -5
- autobyteus/agent/streaming/adapters/__init__.py +18 -0
- autobyteus/agent/streaming/adapters/invocation_adapter.py +184 -0
- autobyteus/agent/streaming/adapters/tool_call_parsing.py +163 -0
- autobyteus/agent/streaming/adapters/tool_syntax_registry.py +67 -0
- autobyteus/agent/streaming/agent_event_stream.py +3 -183
- autobyteus/agent/streaming/api_tool_call/__init__.py +16 -0
- autobyteus/agent/streaming/api_tool_call/file_content_streamer.py +56 -0
- autobyteus/agent/streaming/api_tool_call/json_string_field_extractor.py +175 -0
- autobyteus/agent/streaming/api_tool_call_streaming_response_handler.py +4 -0
- autobyteus/agent/streaming/events/__init__.py +6 -0
- autobyteus/agent/streaming/events/stream_event_payloads.py +284 -0
- autobyteus/agent/streaming/events/stream_events.py +141 -0
- autobyteus/agent/streaming/handlers/__init__.py +15 -0
- autobyteus/agent/streaming/handlers/api_tool_call_streaming_response_handler.py +303 -0
- autobyteus/agent/streaming/handlers/parsing_streaming_response_handler.py +107 -0
- autobyteus/agent/streaming/handlers/pass_through_streaming_response_handler.py +107 -0
- autobyteus/agent/streaming/handlers/streaming_handler_factory.py +177 -0
- autobyteus/agent/streaming/handlers/streaming_response_handler.py +58 -0
- autobyteus/agent/streaming/parser/__init__.py +61 -0
- autobyteus/agent/streaming/parser/event_emitter.py +181 -0
- autobyteus/agent/streaming/parser/events.py +4 -0
- autobyteus/agent/streaming/parser/invocation_adapter.py +4 -0
- autobyteus/agent/streaming/parser/json_parsing_strategies/__init__.py +19 -0
- autobyteus/agent/streaming/parser/json_parsing_strategies/base.py +32 -0
- autobyteus/agent/streaming/parser/json_parsing_strategies/default.py +34 -0
- autobyteus/agent/streaming/parser/json_parsing_strategies/gemini.py +31 -0
- autobyteus/agent/streaming/parser/json_parsing_strategies/openai.py +64 -0
- autobyteus/agent/streaming/parser/json_parsing_strategies/registry.py +75 -0
- autobyteus/agent/streaming/parser/parser_context.py +227 -0
- autobyteus/agent/streaming/parser/parser_factory.py +132 -0
- autobyteus/agent/streaming/parser/sentinel_format.py +7 -0
- autobyteus/agent/streaming/parser/state_factory.py +62 -0
- autobyteus/agent/streaming/parser/states/__init__.py +1 -0
- autobyteus/agent/streaming/parser/states/base_state.py +60 -0
- autobyteus/agent/streaming/parser/states/custom_xml_tag_run_bash_parsing_state.py +38 -0
- autobyteus/agent/streaming/parser/states/custom_xml_tag_write_file_parsing_state.py +55 -0
- autobyteus/agent/streaming/parser/states/delimited_content_state.py +146 -0
- autobyteus/agent/streaming/parser/states/json_initialization_state.py +144 -0
- autobyteus/agent/streaming/parser/states/json_tool_parsing_state.py +137 -0
- autobyteus/agent/streaming/parser/states/sentinel_content_state.py +30 -0
- autobyteus/agent/streaming/parser/states/sentinel_initialization_state.py +117 -0
- autobyteus/agent/streaming/parser/states/text_state.py +78 -0
- autobyteus/agent/streaming/parser/states/xml_patch_file_tool_parsing_state.py +328 -0
- autobyteus/agent/streaming/parser/states/xml_run_bash_tool_parsing_state.py +129 -0
- autobyteus/agent/streaming/parser/states/xml_tag_initialization_state.py +151 -0
- autobyteus/agent/streaming/parser/states/xml_tool_parsing_state.py +63 -0
- autobyteus/agent/streaming/parser/states/xml_write_file_tool_parsing_state.py +343 -0
- autobyteus/agent/streaming/parser/strategies/__init__.py +17 -0
- autobyteus/agent/streaming/parser/strategies/base.py +24 -0
- autobyteus/agent/streaming/parser/strategies/json_tool_strategy.py +26 -0
- autobyteus/agent/streaming/parser/strategies/registry.py +28 -0
- autobyteus/agent/streaming/parser/strategies/sentinel_strategy.py +23 -0
- autobyteus/agent/streaming/parser/strategies/xml_tag_strategy.py +21 -0
- autobyteus/agent/streaming/parser/stream_scanner.py +167 -0
- autobyteus/agent/streaming/parser/streaming_parser.py +212 -0
- autobyteus/agent/streaming/parser/tool_call_parsing.py +4 -0
- autobyteus/agent/streaming/parser/tool_constants.py +7 -0
- autobyteus/agent/streaming/parser/tool_syntax_registry.py +4 -0
- autobyteus/agent/streaming/parser/xml_tool_parsing_state_registry.py +55 -0
- autobyteus/agent/streaming/parsing_streaming_response_handler.py +4 -0
- autobyteus/agent/streaming/pass_through_streaming_response_handler.py +4 -0
- autobyteus/agent/streaming/queue_streamer.py +3 -57
- autobyteus/agent/streaming/segments/__init__.py +5 -0
- autobyteus/agent/streaming/segments/segment_events.py +82 -0
- autobyteus/agent/streaming/stream_event_payloads.py +2 -223
- autobyteus/agent/streaming/stream_events.py +3 -140
- autobyteus/agent/streaming/streaming_handler_factory.py +4 -0
- autobyteus/agent/streaming/streaming_response_handler.py +4 -0
- autobyteus/agent/streaming/streams/__init__.py +5 -0
- autobyteus/agent/streaming/streams/agent_event_stream.py +197 -0
- autobyteus/agent/streaming/utils/__init__.py +5 -0
- autobyteus/agent/streaming/utils/queue_streamer.py +59 -0
- autobyteus/agent/system_prompt_processor/__init__.py +2 -0
- autobyteus/agent/system_prompt_processor/available_skills_processor.py +96 -0
- autobyteus/agent/system_prompt_processor/base_processor.py +1 -1
- autobyteus/agent/system_prompt_processor/processor_meta.py +15 -2
- autobyteus/agent/system_prompt_processor/tool_manifest_injector_processor.py +39 -58
- autobyteus/agent/token_budget.py +56 -0
- autobyteus/agent/tool_execution_result_processor/memory_ingest_tool_result_processor.py +29 -0
- autobyteus/agent/tool_invocation.py +16 -40
- autobyteus/agent/tool_invocation_preprocessor/__init__.py +9 -0
- autobyteus/agent/tool_invocation_preprocessor/base_preprocessor.py +45 -0
- autobyteus/agent/tool_invocation_preprocessor/processor_definition.py +15 -0
- autobyteus/agent/tool_invocation_preprocessor/processor_meta.py +33 -0
- autobyteus/agent/tool_invocation_preprocessor/processor_registry.py +60 -0
- autobyteus/agent/utils/wait_for_idle.py +12 -14
- autobyteus/agent/workspace/base_workspace.py +6 -27
- autobyteus/agent_team/agent_team.py +3 -3
- autobyteus/agent_team/agent_team_builder.py +1 -41
- autobyteus/agent_team/bootstrap_steps/__init__.py +0 -4
- autobyteus/agent_team/bootstrap_steps/agent_configuration_preparation_step.py +8 -18
- autobyteus/agent_team/bootstrap_steps/agent_team_bootstrapper.py +4 -16
- autobyteus/agent_team/bootstrap_steps/base_agent_team_bootstrap_step.py +1 -2
- autobyteus/agent_team/bootstrap_steps/coordinator_initialization_step.py +1 -2
- autobyteus/agent_team/bootstrap_steps/task_notifier_initialization_step.py +1 -2
- autobyteus/agent_team/bootstrap_steps/team_context_initialization_step.py +4 -4
- autobyteus/agent_team/context/agent_team_config.py +6 -3
- autobyteus/agent_team/context/agent_team_context.py +25 -3
- autobyteus/agent_team/context/agent_team_runtime_state.py +9 -6
- autobyteus/agent_team/events/__init__.py +11 -0
- autobyteus/agent_team/events/agent_team_event_dispatcher.py +22 -9
- autobyteus/agent_team/events/agent_team_events.py +16 -0
- autobyteus/agent_team/events/event_store.py +57 -0
- autobyteus/agent_team/factory/agent_team_factory.py +8 -0
- autobyteus/agent_team/handlers/inter_agent_message_request_event_handler.py +18 -2
- autobyteus/agent_team/handlers/lifecycle_agent_team_event_handler.py +21 -5
- autobyteus/agent_team/handlers/process_user_message_event_handler.py +17 -8
- autobyteus/agent_team/handlers/tool_approval_team_event_handler.py +19 -4
- autobyteus/agent_team/runtime/agent_team_runtime.py +41 -10
- autobyteus/agent_team/runtime/agent_team_worker.py +69 -5
- autobyteus/agent_team/status/__init__.py +14 -0
- autobyteus/agent_team/status/agent_team_status.py +18 -0
- autobyteus/agent_team/status/agent_team_status_manager.py +33 -0
- autobyteus/agent_team/status/status_deriver.py +62 -0
- autobyteus/agent_team/status/status_update_utils.py +42 -0
- autobyteus/agent_team/streaming/__init__.py +2 -2
- autobyteus/agent_team/streaming/agent_team_event_notifier.py +6 -6
- autobyteus/agent_team/streaming/agent_team_stream_event_payloads.py +4 -4
- autobyteus/agent_team/streaming/agent_team_stream_events.py +3 -3
- autobyteus/agent_team/system_prompt_processor/__init__.py +6 -0
- autobyteus/agent_team/system_prompt_processor/team_manifest_injector_processor.py +76 -0
- autobyteus/agent_team/task_notification/task_notification_mode.py +19 -0
- autobyteus/agent_team/utils/wait_for_idle.py +4 -4
- autobyteus/cli/agent_cli.py +18 -10
- autobyteus/cli/agent_team_tui/app.py +14 -11
- autobyteus/cli/agent_team_tui/state.py +13 -15
- autobyteus/cli/agent_team_tui/widgets/agent_list_sidebar.py +15 -15
- autobyteus/cli/agent_team_tui/widgets/focus_pane.py +143 -36
- autobyteus/cli/agent_team_tui/widgets/renderables.py +1 -1
- autobyteus/cli/agent_team_tui/widgets/shared.py +25 -25
- autobyteus/cli/cli_display.py +193 -44
- autobyteus/cli/workflow_tui/app.py +9 -10
- autobyteus/cli/workflow_tui/state.py +14 -16
- autobyteus/cli/workflow_tui/widgets/agent_list_sidebar.py +15 -15
- autobyteus/cli/workflow_tui/widgets/focus_pane.py +137 -35
- autobyteus/cli/workflow_tui/widgets/renderables.py +1 -1
- autobyteus/cli/workflow_tui/widgets/shared.py +25 -25
- autobyteus/clients/autobyteus_client.py +94 -1
- autobyteus/events/event_types.py +11 -18
- autobyteus/llm/api/autobyteus_llm.py +33 -29
- autobyteus/llm/api/claude_llm.py +142 -36
- autobyteus/llm/api/gemini_llm.py +163 -59
- autobyteus/llm/api/grok_llm.py +1 -1
- autobyteus/llm/api/minimax_llm.py +26 -0
- autobyteus/llm/api/mistral_llm.py +113 -87
- autobyteus/llm/api/ollama_llm.py +9 -42
- autobyteus/llm/api/openai_compatible_llm.py +127 -91
- autobyteus/llm/api/openai_llm.py +3 -3
- autobyteus/llm/api/openai_responses_llm.py +324 -0
- autobyteus/llm/api/zhipu_llm.py +21 -2
- autobyteus/llm/autobyteus_provider.py +70 -60
- autobyteus/llm/base_llm.py +85 -81
- autobyteus/llm/converters/__init__.py +14 -0
- autobyteus/llm/converters/anthropic_tool_call_converter.py +37 -0
- autobyteus/llm/converters/gemini_tool_call_converter.py +57 -0
- autobyteus/llm/converters/mistral_tool_call_converter.py +37 -0
- autobyteus/llm/converters/openai_tool_call_converter.py +38 -0
- autobyteus/llm/extensions/base_extension.py +6 -12
- autobyteus/llm/extensions/token_usage_tracking_extension.py +45 -18
- autobyteus/llm/llm_factory.py +282 -204
- autobyteus/llm/lmstudio_provider.py +60 -49
- autobyteus/llm/models.py +35 -2
- autobyteus/llm/ollama_provider.py +60 -49
- autobyteus/llm/ollama_provider_resolver.py +0 -1
- autobyteus/llm/prompt_renderers/__init__.py +19 -0
- autobyteus/llm/prompt_renderers/anthropic_prompt_renderer.py +104 -0
- autobyteus/llm/prompt_renderers/autobyteus_prompt_renderer.py +19 -0
- autobyteus/llm/prompt_renderers/base_prompt_renderer.py +10 -0
- autobyteus/llm/prompt_renderers/gemini_prompt_renderer.py +63 -0
- autobyteus/llm/prompt_renderers/mistral_prompt_renderer.py +87 -0
- autobyteus/llm/prompt_renderers/ollama_prompt_renderer.py +51 -0
- autobyteus/llm/prompt_renderers/openai_chat_renderer.py +97 -0
- autobyteus/llm/prompt_renderers/openai_responses_renderer.py +101 -0
- autobyteus/llm/providers.py +1 -3
- autobyteus/llm/token_counter/claude_token_counter.py +56 -25
- autobyteus/llm/token_counter/mistral_token_counter.py +12 -8
- autobyteus/llm/token_counter/openai_token_counter.py +24 -5
- autobyteus/llm/token_counter/token_counter_factory.py +12 -5
- autobyteus/llm/utils/llm_config.py +6 -12
- autobyteus/llm/utils/media_payload_formatter.py +27 -20
- autobyteus/llm/utils/messages.py +55 -3
- autobyteus/llm/utils/response_types.py +3 -0
- autobyteus/llm/utils/tool_call_delta.py +31 -0
- autobyteus/memory/__init__.py +35 -0
- autobyteus/memory/compaction/__init__.py +9 -0
- autobyteus/memory/compaction/compaction_result.py +8 -0
- autobyteus/memory/compaction/compactor.py +89 -0
- autobyteus/memory/compaction/summarizer.py +11 -0
- autobyteus/memory/compaction_snapshot_builder.py +84 -0
- autobyteus/memory/memory_manager.py +205 -0
- autobyteus/memory/models/__init__.py +14 -0
- autobyteus/memory/models/episodic_item.py +41 -0
- autobyteus/memory/models/memory_types.py +7 -0
- autobyteus/memory/models/raw_trace_item.py +79 -0
- autobyteus/memory/models/semantic_item.py +41 -0
- autobyteus/memory/models/tool_interaction.py +20 -0
- autobyteus/memory/path_resolver.py +27 -0
- autobyteus/memory/policies/__init__.py +5 -0
- autobyteus/memory/policies/compaction_policy.py +16 -0
- autobyteus/memory/restore/__init__.py +1 -0
- autobyteus/memory/restore/working_context_snapshot_bootstrapper.py +61 -0
- autobyteus/memory/retrieval/__init__.py +7 -0
- autobyteus/memory/retrieval/memory_bundle.py +11 -0
- autobyteus/memory/retrieval/retriever.py +13 -0
- autobyteus/memory/store/__init__.py +9 -0
- autobyteus/memory/store/base_store.py +14 -0
- autobyteus/memory/store/file_store.py +98 -0
- autobyteus/memory/store/working_context_snapshot_store.py +28 -0
- autobyteus/memory/tool_interaction_builder.py +46 -0
- autobyteus/memory/turn_tracker.py +9 -0
- autobyteus/memory/working_context_snapshot.py +69 -0
- autobyteus/memory/working_context_snapshot_serializer.py +135 -0
- autobyteus/multimedia/audio/api/autobyteus_audio_client.py +19 -5
- autobyteus/multimedia/audio/api/gemini_audio_client.py +109 -16
- autobyteus/multimedia/audio/audio_client_factory.py +47 -9
- autobyteus/multimedia/audio/audio_model.py +2 -1
- autobyteus/multimedia/image/api/autobyteus_image_client.py +19 -5
- autobyteus/multimedia/image/api/gemini_image_client.py +39 -17
- autobyteus/multimedia/image/api/openai_image_client.py +125 -43
- autobyteus/multimedia/image/autobyteus_image_provider.py +2 -1
- autobyteus/multimedia/image/image_client_factory.py +47 -15
- autobyteus/multimedia/image/image_model.py +5 -2
- autobyteus/multimedia/providers.py +3 -2
- autobyteus/skills/loader.py +71 -0
- autobyteus/skills/model.py +11 -0
- autobyteus/skills/registry.py +70 -0
- autobyteus/task_management/tools/todo_tools/add_todo.py +2 -2
- autobyteus/task_management/tools/todo_tools/create_todo_list.py +2 -2
- autobyteus/task_management/tools/todo_tools/update_todo_status.py +2 -2
- autobyteus/tools/__init__.py +34 -47
- autobyteus/tools/base_tool.py +7 -0
- autobyteus/tools/file/__init__.py +2 -6
- autobyteus/tools/file/patch_file.py +149 -0
- autobyteus/tools/file/read_file.py +36 -5
- autobyteus/tools/file/write_file.py +4 -1
- autobyteus/tools/functional_tool.py +43 -6
- autobyteus/tools/mcp/__init__.py +2 -0
- autobyteus/tools/mcp/config_service.py +5 -1
- autobyteus/tools/mcp/server/__init__.py +2 -0
- autobyteus/tools/mcp/server/http_managed_mcp_server.py +1 -1
- autobyteus/tools/mcp/server/websocket_managed_mcp_server.py +141 -0
- autobyteus/tools/mcp/server_instance_manager.py +8 -1
- autobyteus/tools/mcp/types.py +61 -0
- autobyteus/tools/multimedia/audio_tools.py +70 -17
- autobyteus/tools/multimedia/download_media_tool.py +18 -4
- autobyteus/tools/multimedia/image_tools.py +246 -62
- autobyteus/tools/operation_executor/journal_manager.py +107 -0
- autobyteus/tools/operation_executor/operation_event_buffer.py +57 -0
- autobyteus/tools/operation_executor/operation_event_producer.py +29 -0
- autobyteus/tools/operation_executor/operation_executor.py +58 -0
- autobyteus/tools/registry/tool_definition.py +43 -2
- autobyteus/tools/skill/load_skill.py +50 -0
- autobyteus/tools/terminal/__init__.py +45 -0
- autobyteus/tools/terminal/ansi_utils.py +32 -0
- autobyteus/tools/terminal/background_process_manager.py +233 -0
- autobyteus/tools/terminal/output_buffer.py +105 -0
- autobyteus/tools/terminal/prompt_detector.py +63 -0
- autobyteus/tools/terminal/pty_session.py +241 -0
- autobyteus/tools/terminal/session_factory.py +20 -0
- autobyteus/tools/terminal/terminal_session_manager.py +226 -0
- autobyteus/tools/terminal/tools/__init__.py +13 -0
- autobyteus/tools/terminal/tools/get_process_output.py +81 -0
- autobyteus/tools/terminal/tools/run_bash.py +109 -0
- autobyteus/tools/terminal/tools/start_background_process.py +104 -0
- autobyteus/tools/terminal/tools/stop_background_process.py +67 -0
- autobyteus/tools/terminal/types.py +54 -0
- autobyteus/tools/terminal/wsl_tmux_session.py +221 -0
- autobyteus/tools/terminal/wsl_utils.py +156 -0
- autobyteus/tools/transaction_management/backup_handler.py +48 -0
- autobyteus/tools/transaction_management/operation_lifecycle_manager.py +62 -0
- autobyteus/tools/usage/__init__.py +1 -2
- autobyteus/tools/usage/formatters/__init__.py +17 -1
- autobyteus/tools/usage/formatters/base_formatter.py +8 -0
- autobyteus/tools/usage/formatters/default_xml_schema_formatter.py +2 -2
- autobyteus/tools/usage/formatters/mistral_json_schema_formatter.py +18 -0
- autobyteus/tools/usage/formatters/patch_file_xml_example_formatter.py +64 -0
- autobyteus/tools/usage/formatters/patch_file_xml_schema_formatter.py +31 -0
- autobyteus/tools/usage/formatters/run_bash_xml_example_formatter.py +32 -0
- autobyteus/tools/usage/formatters/run_bash_xml_schema_formatter.py +36 -0
- autobyteus/tools/usage/formatters/write_file_xml_example_formatter.py +53 -0
- autobyteus/tools/usage/formatters/write_file_xml_schema_formatter.py +31 -0
- autobyteus/tools/usage/providers/tool_manifest_provider.py +10 -10
- autobyteus/tools/usage/registries/__init__.py +1 -3
- autobyteus/tools/usage/registries/tool_formatting_registry.py +115 -8
- autobyteus/tools/usage/tool_schema_provider.py +51 -0
- autobyteus/tools/web/__init__.py +4 -0
- autobyteus/tools/web/read_url_tool.py +80 -0
- autobyteus/utils/diff_utils.py +271 -0
- autobyteus/utils/download_utils.py +109 -0
- autobyteus/utils/file_utils.py +57 -2
- autobyteus/utils/gemini_helper.py +64 -0
- autobyteus/utils/gemini_model_mapping.py +71 -0
- autobyteus/utils/llm_output_formatter.py +75 -0
- autobyteus/utils/tool_call_format.py +36 -0
- autobyteus/workflow/agentic_workflow.py +3 -3
- autobyteus/workflow/bootstrap_steps/agent_tool_injection_step.py +2 -2
- autobyteus/workflow/bootstrap_steps/base_workflow_bootstrap_step.py +2 -2
- autobyteus/workflow/bootstrap_steps/coordinator_initialization_step.py +2 -2
- autobyteus/workflow/bootstrap_steps/coordinator_prompt_preparation_step.py +3 -9
- autobyteus/workflow/bootstrap_steps/workflow_bootstrapper.py +6 -6
- autobyteus/workflow/bootstrap_steps/workflow_runtime_queue_initialization_step.py +2 -2
- autobyteus/workflow/context/workflow_context.py +3 -3
- autobyteus/workflow/context/workflow_runtime_state.py +5 -5
- autobyteus/workflow/events/workflow_event_dispatcher.py +5 -5
- autobyteus/workflow/handlers/lifecycle_workflow_event_handler.py +3 -3
- autobyteus/workflow/handlers/process_user_message_event_handler.py +5 -5
- autobyteus/workflow/handlers/tool_approval_workflow_event_handler.py +2 -2
- autobyteus/workflow/runtime/workflow_runtime.py +8 -8
- autobyteus/workflow/runtime/workflow_worker.py +3 -3
- autobyteus/workflow/status/__init__.py +11 -0
- autobyteus/workflow/status/workflow_status.py +19 -0
- autobyteus/workflow/status/workflow_status_manager.py +48 -0
- autobyteus/workflow/streaming/__init__.py +2 -2
- autobyteus/workflow/streaming/workflow_event_notifier.py +7 -7
- autobyteus/workflow/streaming/workflow_stream_event_payloads.py +4 -4
- autobyteus/workflow/streaming/workflow_stream_events.py +3 -3
- autobyteus/workflow/utils/wait_for_idle.py +4 -4
- autobyteus-1.3.0.dist-info/METADATA +293 -0
- autobyteus-1.3.0.dist-info/RECORD +606 -0
- {autobyteus-1.2.1.dist-info → autobyteus-1.3.0.dist-info}/WHEEL +1 -1
- {autobyteus-1.2.1.dist-info → autobyteus-1.3.0.dist-info}/top_level.txt +0 -1
- autobyteus/agent/bootstrap_steps/agent_runtime_queue_initialization_step.py +0 -57
- autobyteus/agent/hooks/__init__.py +0 -16
- autobyteus/agent/hooks/base_phase_hook.py +0 -78
- autobyteus/agent/hooks/hook_definition.py +0 -36
- autobyteus/agent/hooks/hook_meta.py +0 -37
- autobyteus/agent/hooks/hook_registry.py +0 -106
- autobyteus/agent/llm_response_processor/provider_aware_tool_usage_processor.py +0 -103
- autobyteus/agent/phases/__init__.py +0 -18
- autobyteus/agent/phases/discover.py +0 -53
- autobyteus/agent/phases/manager.py +0 -265
- autobyteus/agent/phases/transition_decorator.py +0 -40
- autobyteus/agent/phases/transition_info.py +0 -33
- autobyteus/agent/remote_agent.py +0 -244
- autobyteus/agent/workspace/workspace_definition.py +0 -36
- autobyteus/agent/workspace/workspace_meta.py +0 -37
- autobyteus/agent/workspace/workspace_registry.py +0 -72
- autobyteus/agent_team/bootstrap_steps/agent_team_runtime_queue_initialization_step.py +0 -25
- autobyteus/agent_team/bootstrap_steps/coordinator_prompt_preparation_step.py +0 -85
- autobyteus/agent_team/phases/__init__.py +0 -11
- autobyteus/agent_team/phases/agent_team_operational_phase.py +0 -19
- autobyteus/agent_team/phases/agent_team_phase_manager.py +0 -48
- autobyteus/llm/api/bedrock_llm.py +0 -92
- autobyteus/llm/api/groq_llm.py +0 -94
- autobyteus/llm/api/nvidia_llm.py +0 -108
- autobyteus/llm/utils/token_pricing_config.py +0 -87
- autobyteus/rpc/__init__.py +0 -73
- autobyteus/rpc/client/__init__.py +0 -17
- autobyteus/rpc/client/abstract_client_connection.py +0 -124
- autobyteus/rpc/client/client_connection_manager.py +0 -153
- autobyteus/rpc/client/sse_client_connection.py +0 -306
- autobyteus/rpc/client/stdio_client_connection.py +0 -280
- autobyteus/rpc/config/__init__.py +0 -13
- autobyteus/rpc/config/agent_server_config.py +0 -153
- autobyteus/rpc/config/agent_server_registry.py +0 -152
- autobyteus/rpc/hosting.py +0 -244
- autobyteus/rpc/protocol.py +0 -244
- autobyteus/rpc/server/__init__.py +0 -20
- autobyteus/rpc/server/agent_server_endpoint.py +0 -181
- autobyteus/rpc/server/base_method_handler.py +0 -40
- autobyteus/rpc/server/method_handlers.py +0 -259
- autobyteus/rpc/server/sse_server_handler.py +0 -182
- autobyteus/rpc/server/stdio_server_handler.py +0 -151
- autobyteus/rpc/server_main.py +0 -198
- autobyteus/rpc/transport_type.py +0 -13
- autobyteus/tools/bash/__init__.py +0 -2
- autobyteus/tools/bash/bash_executor.py +0 -100
- autobyteus/tools/browser/__init__.py +0 -2
- autobyteus/tools/browser/session_aware/browser_session_aware_navigate_to.py +0 -75
- autobyteus/tools/browser/session_aware/browser_session_aware_tool.py +0 -30
- autobyteus/tools/browser/session_aware/browser_session_aware_web_element_trigger.py +0 -154
- autobyteus/tools/browser/session_aware/browser_session_aware_webpage_reader.py +0 -89
- autobyteus/tools/browser/session_aware/browser_session_aware_webpage_screenshot_taker.py +0 -107
- autobyteus/tools/browser/session_aware/factory/browser_session_aware_web_element_trigger_factory.py +0 -14
- autobyteus/tools/browser/session_aware/factory/browser_session_aware_webpage_reader_factory.py +0 -26
- autobyteus/tools/browser/session_aware/factory/browser_session_aware_webpage_screenshot_taker_factory.py +0 -14
- autobyteus/tools/browser/session_aware/shared_browser_session.py +0 -11
- autobyteus/tools/browser/session_aware/shared_browser_session_manager.py +0 -25
- autobyteus/tools/browser/session_aware/web_element_action.py +0 -20
- autobyteus/tools/browser/standalone/__init__.py +0 -6
- autobyteus/tools/browser/standalone/factory/__init__.py +0 -0
- autobyteus/tools/browser/standalone/factory/webpage_reader_factory.py +0 -25
- autobyteus/tools/browser/standalone/factory/webpage_screenshot_taker_factory.py +0 -14
- autobyteus/tools/browser/standalone/navigate_to.py +0 -84
- autobyteus/tools/browser/standalone/web_page_pdf_generator.py +0 -101
- autobyteus/tools/browser/standalone/webpage_image_downloader.py +0 -169
- autobyteus/tools/browser/standalone/webpage_reader.py +0 -105
- autobyteus/tools/browser/standalone/webpage_screenshot_taker.py +0 -105
- autobyteus/tools/file/edit_file.py +0 -200
- autobyteus/tools/file/list_directory.py +0 -168
- autobyteus/tools/file/search_files.py +0 -188
- autobyteus/tools/timer.py +0 -175
- autobyteus/tools/usage/parsers/__init__.py +0 -22
- autobyteus/tools/usage/parsers/_json_extractor.py +0 -99
- autobyteus/tools/usage/parsers/_string_decoders.py +0 -18
- autobyteus/tools/usage/parsers/anthropic_xml_tool_usage_parser.py +0 -10
- autobyteus/tools/usage/parsers/base_parser.py +0 -41
- autobyteus/tools/usage/parsers/default_json_tool_usage_parser.py +0 -83
- autobyteus/tools/usage/parsers/default_xml_tool_usage_parser.py +0 -316
- autobyteus/tools/usage/parsers/exceptions.py +0 -13
- autobyteus/tools/usage/parsers/gemini_json_tool_usage_parser.py +0 -77
- autobyteus/tools/usage/parsers/openai_json_tool_usage_parser.py +0 -149
- autobyteus/tools/usage/parsers/provider_aware_tool_usage_parser.py +0 -59
- autobyteus/tools/usage/registries/tool_usage_parser_registry.py +0 -62
- autobyteus/workflow/phases/__init__.py +0 -11
- autobyteus/workflow/phases/workflow_operational_phase.py +0 -19
- autobyteus/workflow/phases/workflow_phase_manager.py +0 -48
- autobyteus-1.2.1.dist-info/METADATA +0 -205
- autobyteus-1.2.1.dist-info/RECORD +0 -511
- examples/__init__.py +0 -1
- examples/agent_team/__init__.py +0 -1
- examples/discover_phase_transitions.py +0 -104
- examples/run_agentic_software_engineer.py +0 -239
- examples/run_browser_agent.py +0 -262
- examples/run_google_slides_agent.py +0 -287
- examples/run_mcp_browser_client.py +0 -174
- examples/run_mcp_google_slides_client.py +0 -270
- examples/run_mcp_list_tools.py +0 -189
- examples/run_poem_writer.py +0 -284
- examples/run_sqlite_agent.py +0 -295
- /autobyteus/{tools/browser/session_aware → skills}/__init__.py +0 -0
- /autobyteus/tools/{browser/session_aware/factory → skill}/__init__.py +0 -0
- {autobyteus-1.2.1.dist-info → autobyteus-1.3.0.dist-info}/licenses/LICENSE +0 -0
|
@@ -0,0 +1,212 @@
|
|
|
1
|
+
"""
|
|
2
|
+
StreamingParser: Main driver class for the streaming response parser.
|
|
3
|
+
|
|
4
|
+
This is the primary entry point for parsing LLM responses in real-time.
|
|
5
|
+
It manages the state machine and provides a clean API for feeding chunks
|
|
6
|
+
and collecting parsed segment events.
|
|
7
|
+
"""
|
|
8
|
+
from typing import List, Optional, Iterator
|
|
9
|
+
import logging
|
|
10
|
+
|
|
11
|
+
from .parser_context import ParserContext, ParserConfig
|
|
12
|
+
from .states.text_state import TextState
|
|
13
|
+
from .events import SegmentEvent, SegmentType, SegmentEventType
|
|
14
|
+
|
|
15
|
+
logger = logging.getLogger(__name__)
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
class StreamingParser:
|
|
19
|
+
"""
|
|
20
|
+
Main driver for streaming LLM response parsing.
|
|
21
|
+
|
|
22
|
+
This class provides a simple API for:
|
|
23
|
+
1. Feeding chunks of text from an LLM stream
|
|
24
|
+
2. Collecting structured SegmentEvents
|
|
25
|
+
3. Finalizing the stream when complete
|
|
26
|
+
|
|
27
|
+
Example usage:
|
|
28
|
+
parser = StreamingParser()
|
|
29
|
+
|
|
30
|
+
# As chunks arrive from LLM
|
|
31
|
+
for chunk in llm_stream:
|
|
32
|
+
events = parser.feed(chunk)
|
|
33
|
+
for event in events:
|
|
34
|
+
# Send to WebSocket, update UI, etc.
|
|
35
|
+
handle_event(event)
|
|
36
|
+
|
|
37
|
+
# When stream ends
|
|
38
|
+
final_events = parser.finalize()
|
|
39
|
+
"""
|
|
40
|
+
|
|
41
|
+
def __init__(self, config: Optional[ParserConfig] = None):
|
|
42
|
+
"""
|
|
43
|
+
Initialize the streaming parser.
|
|
44
|
+
|
|
45
|
+
Args:
|
|
46
|
+
config: Optional parser configuration. Defaults to parsing
|
|
47
|
+
XML tool calls.
|
|
48
|
+
"""
|
|
49
|
+
self._context = ParserContext(config)
|
|
50
|
+
self._context.current_state = TextState(self._context)
|
|
51
|
+
self._is_finalized = False
|
|
52
|
+
logger.debug("StreamingParser initialized")
|
|
53
|
+
|
|
54
|
+
@property
|
|
55
|
+
def config(self) -> ParserConfig:
|
|
56
|
+
"""Get the parser configuration."""
|
|
57
|
+
return self._context.config
|
|
58
|
+
|
|
59
|
+
def feed(self, chunk: str) -> List[SegmentEvent]:
|
|
60
|
+
"""
|
|
61
|
+
Feed a chunk of text from the LLM stream.
|
|
62
|
+
|
|
63
|
+
This method:
|
|
64
|
+
1. Appends the chunk to the internal buffer
|
|
65
|
+
2. Runs the state machine until the buffer is exhausted
|
|
66
|
+
3. Returns any events that were emitted
|
|
67
|
+
|
|
68
|
+
Args:
|
|
69
|
+
chunk: A string chunk from the LLM response stream.
|
|
70
|
+
|
|
71
|
+
Returns:
|
|
72
|
+
List of SegmentEvents emitted while processing this chunk.
|
|
73
|
+
|
|
74
|
+
Raises:
|
|
75
|
+
RuntimeError: If called after finalize().
|
|
76
|
+
"""
|
|
77
|
+
if self._is_finalized:
|
|
78
|
+
raise RuntimeError("Cannot feed chunks after finalize() has been called")
|
|
79
|
+
|
|
80
|
+
if not chunk:
|
|
81
|
+
return []
|
|
82
|
+
|
|
83
|
+
self._context.append(chunk)
|
|
84
|
+
|
|
85
|
+
# Run the state machine until buffer is exhausted
|
|
86
|
+
while self._context.has_more_chars():
|
|
87
|
+
self._context.current_state.run()
|
|
88
|
+
|
|
89
|
+
# Drop consumed buffer data to avoid unbounded growth
|
|
90
|
+
self._context.compact()
|
|
91
|
+
|
|
92
|
+
# Return all events emitted during processing
|
|
93
|
+
return self._context.get_and_clear_events()
|
|
94
|
+
|
|
95
|
+
def finalize(self) -> List[SegmentEvent]:
|
|
96
|
+
"""
|
|
97
|
+
Signal that the LLM stream has ended.
|
|
98
|
+
|
|
99
|
+
This method:
|
|
100
|
+
1. Calls finalize() on the current state to flush any buffers
|
|
101
|
+
2. Returns any final events
|
|
102
|
+
3. Marks the parser as finalized
|
|
103
|
+
|
|
104
|
+
Returns:
|
|
105
|
+
List of any remaining SegmentEvents.
|
|
106
|
+
|
|
107
|
+
Raises:
|
|
108
|
+
RuntimeError: If called more than once.
|
|
109
|
+
"""
|
|
110
|
+
if self._is_finalized:
|
|
111
|
+
raise RuntimeError("finalize() has already been called")
|
|
112
|
+
|
|
113
|
+
self._is_finalized = True
|
|
114
|
+
|
|
115
|
+
# Finalize the current state
|
|
116
|
+
self._context.current_state.finalize()
|
|
117
|
+
|
|
118
|
+
# Close any open text segment to complete the lifecycle.
|
|
119
|
+
if self._context.get_current_segment_type() == SegmentType.TEXT:
|
|
120
|
+
self._context.emit_segment_end()
|
|
121
|
+
|
|
122
|
+
# Clear any remaining buffer data
|
|
123
|
+
self._context.compact()
|
|
124
|
+
|
|
125
|
+
# Return any remaining events
|
|
126
|
+
return self._context.get_and_clear_events()
|
|
127
|
+
|
|
128
|
+
def feed_and_finalize(self, text: str) -> List[SegmentEvent]:
|
|
129
|
+
"""
|
|
130
|
+
Convenience method to parse a complete response in one call.
|
|
131
|
+
|
|
132
|
+
Args:
|
|
133
|
+
text: The complete LLM response text.
|
|
134
|
+
|
|
135
|
+
Returns:
|
|
136
|
+
All SegmentEvents from parsing the complete response.
|
|
137
|
+
"""
|
|
138
|
+
events = self.feed(text)
|
|
139
|
+
events.extend(self.finalize())
|
|
140
|
+
return events
|
|
141
|
+
|
|
142
|
+
@property
|
|
143
|
+
def is_finalized(self) -> bool:
|
|
144
|
+
"""Check if the parser has been finalized."""
|
|
145
|
+
return self._is_finalized
|
|
146
|
+
|
|
147
|
+
def get_current_segment_id(self) -> Optional[str]:
|
|
148
|
+
"""Get the ID of the currently active segment, if any."""
|
|
149
|
+
return self._context.get_current_segment_id()
|
|
150
|
+
|
|
151
|
+
def get_current_segment_type(self) -> Optional[SegmentType]:
|
|
152
|
+
"""Get the type of the currently active segment, if any."""
|
|
153
|
+
return self._context.get_current_segment_type()
|
|
154
|
+
|
|
155
|
+
|
|
156
|
+
def parse_complete_response(
|
|
157
|
+
text: str,
|
|
158
|
+
config: Optional[ParserConfig] = None
|
|
159
|
+
) -> List[SegmentEvent]:
|
|
160
|
+
"""
|
|
161
|
+
Convenience function to parse a complete LLM response.
|
|
162
|
+
|
|
163
|
+
Args:
|
|
164
|
+
text: The complete LLM response text.
|
|
165
|
+
config: Optional parser configuration.
|
|
166
|
+
|
|
167
|
+
Returns:
|
|
168
|
+
List of all SegmentEvents from parsing.
|
|
169
|
+
"""
|
|
170
|
+
parser = StreamingParser(config)
|
|
171
|
+
return parser.feed_and_finalize(text)
|
|
172
|
+
|
|
173
|
+
|
|
174
|
+
def extract_segments(events: List[SegmentEvent]) -> List[dict]:
|
|
175
|
+
"""
|
|
176
|
+
Extract segment summaries from a list of events.
|
|
177
|
+
|
|
178
|
+
This is a utility function that converts the event stream into
|
|
179
|
+
a list of segment dictionaries with accumulated content.
|
|
180
|
+
|
|
181
|
+
Args:
|
|
182
|
+
events: List of SegmentEvents.
|
|
183
|
+
|
|
184
|
+
Returns:
|
|
185
|
+
List of segment dictionaries with 'id', 'type', 'content', 'metadata'.
|
|
186
|
+
"""
|
|
187
|
+
segments = []
|
|
188
|
+
current_segment = None
|
|
189
|
+
|
|
190
|
+
for event in events:
|
|
191
|
+
if event.event_type == SegmentEventType.START:
|
|
192
|
+
current_segment = {
|
|
193
|
+
"id": event.segment_id,
|
|
194
|
+
"type": event.segment_type.value if event.segment_type else "unknown",
|
|
195
|
+
"content": "",
|
|
196
|
+
"metadata": event.payload.get("metadata", {})
|
|
197
|
+
}
|
|
198
|
+
elif event.event_type == SegmentEventType.CONTENT:
|
|
199
|
+
if current_segment:
|
|
200
|
+
delta = event.payload.get("delta", "")
|
|
201
|
+
if isinstance(delta, str):
|
|
202
|
+
current_segment["content"] += delta
|
|
203
|
+
elif event.event_type == SegmentEventType.END:
|
|
204
|
+
if current_segment:
|
|
205
|
+
segments.append(current_segment)
|
|
206
|
+
current_segment = None
|
|
207
|
+
|
|
208
|
+
# Handle unclosed segment
|
|
209
|
+
if current_segment:
|
|
210
|
+
segments.append(current_segment)
|
|
211
|
+
|
|
212
|
+
return segments
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
"""
|
|
2
|
+
XmlToolParsingStateRegistry: Central registry for mapping tool names to their parsing states.
|
|
3
|
+
|
|
4
|
+
This singleton allows:
|
|
5
|
+
1. Core defaults (write_file, patch_file, run_bash) to be registered.
|
|
6
|
+
2. External consumers (users, plugins) to register custom states for new tools (e.g., patch_prompt).
|
|
7
|
+
3. The main XmlTagInitializationState to perform dynamic lookups instead of hardcoded if/else.
|
|
8
|
+
"""
|
|
9
|
+
from typing import Dict, Optional, Type, TYPE_CHECKING
|
|
10
|
+
from autobyteus.utils.singleton import SingletonMeta
|
|
11
|
+
|
|
12
|
+
if TYPE_CHECKING:
|
|
13
|
+
from .states.base_state import BaseState
|
|
14
|
+
|
|
15
|
+
class XmlToolParsingStateRegistry(metaclass=SingletonMeta):
|
|
16
|
+
"""
|
|
17
|
+
Registry for dispatching <tool name="..."> tags to specific Parser State classes.
|
|
18
|
+
"""
|
|
19
|
+
|
|
20
|
+
def __init__(self):
|
|
21
|
+
# Maps tool_name -> State Class
|
|
22
|
+
self._tool_states: Dict[str, Type["BaseState"]] = {}
|
|
23
|
+
|
|
24
|
+
# Register Core Defaults
|
|
25
|
+
# We perform local imports to avoid top-level circular dependencies
|
|
26
|
+
from .states.xml_write_file_tool_parsing_state import XmlWriteFileToolParsingState
|
|
27
|
+
from .states.xml_patch_file_tool_parsing_state import XmlPatchFileToolParsingState
|
|
28
|
+
from .states.xml_run_bash_tool_parsing_state import XmlRunBashToolParsingState
|
|
29
|
+
from .tool_constants import TOOL_NAME_WRITE_FILE, TOOL_NAME_PATCH_FILE, TOOL_NAME_RUN_BASH
|
|
30
|
+
|
|
31
|
+
self.register_tool_state(TOOL_NAME_WRITE_FILE, XmlWriteFileToolParsingState)
|
|
32
|
+
self.register_tool_state(TOOL_NAME_PATCH_FILE, XmlPatchFileToolParsingState)
|
|
33
|
+
self.register_tool_state(TOOL_NAME_RUN_BASH, XmlRunBashToolParsingState)
|
|
34
|
+
|
|
35
|
+
def register_tool_state(self, tool_name: str, state_class: Type["BaseState"]) -> None:
|
|
36
|
+
"""
|
|
37
|
+
Register a custom parsing state for a specific tool.
|
|
38
|
+
|
|
39
|
+
Args:
|
|
40
|
+
tool_name: The name of the tool (e.g., 'write_file', 'patch_prompt').
|
|
41
|
+
state_class: The class handling the parsing (must inherit from BaseState).
|
|
42
|
+
"""
|
|
43
|
+
self._tool_states[tool_name] = state_class
|
|
44
|
+
|
|
45
|
+
def get_state_for_tool(self, tool_name: str) -> Optional[Type["BaseState"]]:
|
|
46
|
+
"""
|
|
47
|
+
Retrieve the parsing state class for a given tool.
|
|
48
|
+
|
|
49
|
+
Args:
|
|
50
|
+
tool_name: The tool name found in the XML tag.
|
|
51
|
+
|
|
52
|
+
Returns:
|
|
53
|
+
The registered state class, or None if not found.
|
|
54
|
+
"""
|
|
55
|
+
return self._tool_states.get(tool_name)
|
|
@@ -1,58 +1,4 @@
|
|
|
1
|
-
|
|
2
|
-
import
|
|
3
|
-
import logging
|
|
4
|
-
from typing import TypeVar, AsyncIterator, Union, Any
|
|
5
|
-
import queue as standard_queue
|
|
1
|
+
"""Compatibility shim for stream_queue_items."""
|
|
2
|
+
from .utils.queue_streamer import stream_queue_items
|
|
6
3
|
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
T = TypeVar('T')
|
|
10
|
-
|
|
11
|
-
async def stream_queue_items(
|
|
12
|
-
queue: standard_queue.Queue[Union[T, object]],
|
|
13
|
-
sentinel: object,
|
|
14
|
-
source_name: str = "unspecified_queue"
|
|
15
|
-
) -> AsyncIterator[T]:
|
|
16
|
-
"""
|
|
17
|
-
Asynchronously iterates over a standard `queue.Queue`, yielding items of type T
|
|
18
|
-
until a specific sentinel object is encountered. This is designed to be used
|
|
19
|
-
from an async context to consume from a queue populated by a synchronous/threaded context.
|
|
20
|
-
|
|
21
|
-
Args:
|
|
22
|
-
queue: The standard `queue.Queue` to stream items from.
|
|
23
|
-
sentinel: The unique object used to signal the end of data in the queue.
|
|
24
|
-
source_name: An optional identifier for the queue source, used in logging.
|
|
25
|
-
|
|
26
|
-
Yields:
|
|
27
|
-
Items of type T from the queue.
|
|
28
|
-
|
|
29
|
-
Raises:
|
|
30
|
-
TypeError: If queue is not a `queue.Queue`.
|
|
31
|
-
ValueError: If sentinel is None.
|
|
32
|
-
asyncio.CancelledError: If the generator is cancelled.
|
|
33
|
-
Exception: Propagates exceptions encountered during queue.get().
|
|
34
|
-
"""
|
|
35
|
-
if not isinstance(queue, standard_queue.Queue):
|
|
36
|
-
raise TypeError(f"queue must be an instance of queue.Queue for source '{source_name}'.")
|
|
37
|
-
if sentinel is None:
|
|
38
|
-
raise ValueError(f"sentinel object cannot be None for source '{source_name}'.")
|
|
39
|
-
|
|
40
|
-
logger.debug(f"Starting to stream items from queue '{source_name}'.")
|
|
41
|
-
loop = asyncio.get_running_loop()
|
|
42
|
-
try:
|
|
43
|
-
while True:
|
|
44
|
-
# Use run_in_executor to wait for the blocking get() call without blocking the event loop.
|
|
45
|
-
item: Any = await loop.run_in_executor(None, queue.get)
|
|
46
|
-
if item is sentinel:
|
|
47
|
-
logger.debug(f"Sentinel {sentinel!r} received from queue '{source_name}'. Ending stream.")
|
|
48
|
-
break
|
|
49
|
-
|
|
50
|
-
yield item # type: ignore
|
|
51
|
-
except asyncio.CancelledError:
|
|
52
|
-
logger.info(f"Stream from queue '{source_name}' was cancelled.")
|
|
53
|
-
raise
|
|
54
|
-
except Exception as e:
|
|
55
|
-
logger.error(f"Error streaming from queue '{source_name}': {e}", exc_info=True)
|
|
56
|
-
raise
|
|
57
|
-
finally:
|
|
58
|
-
logger.debug(f"Exiting stream_queue_items for queue '{source_name}'.")
|
|
4
|
+
__all__ = ["stream_queue_items"]
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Segment Event definitions for the Streaming Parser.
|
|
3
|
+
|
|
4
|
+
These dataclasses define the structured events that the parser emits
|
|
5
|
+
as it incrementally parses LLM response chunks.
|
|
6
|
+
"""
|
|
7
|
+
from dataclasses import dataclass, field
|
|
8
|
+
from typing import Dict, Any, Optional
|
|
9
|
+
from enum import Enum
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
class SegmentType(str, Enum):
|
|
13
|
+
"""Types of content segments that can be parsed from LLM responses."""
|
|
14
|
+
TEXT = "text"
|
|
15
|
+
TOOL_CALL = "tool_call"
|
|
16
|
+
WRITE_FILE = "write_file"
|
|
17
|
+
PATCH_FILE = "patch_file"
|
|
18
|
+
RUN_BASH = "run_bash"
|
|
19
|
+
REASONING = "reasoning"
|
|
20
|
+
MEDIA = "media"
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
class SegmentEventType(str, Enum):
|
|
24
|
+
"""Types of segment lifecycle events."""
|
|
25
|
+
START = "SEGMENT_START"
|
|
26
|
+
CONTENT = "SEGMENT_CONTENT"
|
|
27
|
+
END = "SEGMENT_END"
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
@dataclass
|
|
31
|
+
class SegmentEvent:
|
|
32
|
+
"""
|
|
33
|
+
A structured event emitted by the streaming parser.
|
|
34
|
+
|
|
35
|
+
Attributes:
|
|
36
|
+
event_type: The lifecycle stage of this event (START, CONTENT, END).
|
|
37
|
+
segment_id: Unique identifier for the segment this event belongs to.
|
|
38
|
+
segment_type: The type of content segment (only present in START events).
|
|
39
|
+
payload: Additional data for the event (e.g., delta content, metadata).
|
|
40
|
+
"""
|
|
41
|
+
event_type: SegmentEventType
|
|
42
|
+
segment_id: str
|
|
43
|
+
segment_type: Optional[SegmentType] = None
|
|
44
|
+
payload: Dict[str, Any] = field(default_factory=dict)
|
|
45
|
+
|
|
46
|
+
def to_dict(self) -> Dict[str, Any]:
|
|
47
|
+
"""Serialize the event to a dictionary for JSON transmission."""
|
|
48
|
+
result = {
|
|
49
|
+
"type": self.event_type.value,
|
|
50
|
+
"segment_id": self.segment_id,
|
|
51
|
+
"payload": self.payload
|
|
52
|
+
}
|
|
53
|
+
if self.segment_type is not None:
|
|
54
|
+
result["segment_type"] = self.segment_type.value
|
|
55
|
+
return result
|
|
56
|
+
|
|
57
|
+
@classmethod
|
|
58
|
+
def start(cls, segment_id: str, segment_type: SegmentType, **metadata) -> "SegmentEvent":
|
|
59
|
+
"""Factory method to create a SEGMENT_START event."""
|
|
60
|
+
return cls(
|
|
61
|
+
event_type=SegmentEventType.START,
|
|
62
|
+
segment_id=segment_id,
|
|
63
|
+
segment_type=segment_type,
|
|
64
|
+
payload={"metadata": metadata} if metadata else {}
|
|
65
|
+
)
|
|
66
|
+
|
|
67
|
+
@classmethod
|
|
68
|
+
def content(cls, segment_id: str, delta: Any) -> "SegmentEvent":
|
|
69
|
+
"""Factory method to create a SEGMENT_CONTENT event."""
|
|
70
|
+
return cls(
|
|
71
|
+
event_type=SegmentEventType.CONTENT,
|
|
72
|
+
segment_id=segment_id,
|
|
73
|
+
payload={"delta": delta}
|
|
74
|
+
)
|
|
75
|
+
|
|
76
|
+
@classmethod
|
|
77
|
+
def end(cls, segment_id: str) -> "SegmentEvent":
|
|
78
|
+
"""Factory method to create a SEGMENT_END event."""
|
|
79
|
+
return cls(
|
|
80
|
+
event_type=SegmentEventType.END,
|
|
81
|
+
segment_id=segment_id
|
|
82
|
+
)
|
|
@@ -1,223 +1,2 @@
|
|
|
1
|
-
|
|
2
|
-
import
|
|
3
|
-
from typing import Dict, Any, Optional, List, Union
|
|
4
|
-
from pydantic import BaseModel, Field
|
|
5
|
-
|
|
6
|
-
from autobyteus.llm.utils.token_usage import TokenUsage
|
|
7
|
-
from autobyteus.agent.phases import AgentOperationalPhase
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
logger = logging.getLogger(__name__)
|
|
11
|
-
|
|
12
|
-
# --- Base Payload Model (Optional, for common fields if any) ---
|
|
13
|
-
class BaseStreamPayload(BaseModel):
|
|
14
|
-
pass
|
|
15
|
-
|
|
16
|
-
# --- Specific Payload Models for each StreamEventType ---
|
|
17
|
-
|
|
18
|
-
class AssistantChunkData(BaseStreamPayload):
|
|
19
|
-
content: str
|
|
20
|
-
reasoning: Optional[str] = None
|
|
21
|
-
is_complete: bool
|
|
22
|
-
usage: Optional[TokenUsage] = None
|
|
23
|
-
image_urls: Optional[List[str]] = None
|
|
24
|
-
audio_urls: Optional[List[str]] = None
|
|
25
|
-
video_urls: Optional[List[str]] = None
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
class AssistantCompleteResponseData(BaseStreamPayload):
|
|
29
|
-
content: str
|
|
30
|
-
reasoning: Optional[str] = None
|
|
31
|
-
usage: Optional[TokenUsage] = None
|
|
32
|
-
image_urls: Optional[List[str]] = None
|
|
33
|
-
audio_urls: Optional[List[str]] = None
|
|
34
|
-
video_urls: Optional[List[str]] = None
|
|
35
|
-
|
|
36
|
-
class ToolInteractionLogEntryData(BaseStreamPayload):
|
|
37
|
-
log_entry: str
|
|
38
|
-
tool_invocation_id: str
|
|
39
|
-
tool_name: str
|
|
40
|
-
|
|
41
|
-
class AgentOperationalPhaseTransitionData(BaseStreamPayload):
|
|
42
|
-
new_phase: AgentOperationalPhase
|
|
43
|
-
old_phase: Optional[AgentOperationalPhase] = None
|
|
44
|
-
trigger: Optional[str] = None
|
|
45
|
-
tool_name: Optional[str] = None
|
|
46
|
-
error_message: Optional[str] = None
|
|
47
|
-
error_details: Optional[str] = None
|
|
48
|
-
|
|
49
|
-
class ErrorEventData(BaseStreamPayload):
|
|
50
|
-
source: str
|
|
51
|
-
message: str
|
|
52
|
-
details: Optional[str] = None
|
|
53
|
-
|
|
54
|
-
class ToolInvocationApprovalRequestedData(BaseStreamPayload):
|
|
55
|
-
invocation_id: str
|
|
56
|
-
tool_name: str
|
|
57
|
-
arguments: Dict[str, Any]
|
|
58
|
-
|
|
59
|
-
class ToolInvocationAutoExecutingData(BaseStreamPayload):
|
|
60
|
-
invocation_id: str
|
|
61
|
-
tool_name: str
|
|
62
|
-
arguments: Dict[str, Any]
|
|
63
|
-
|
|
64
|
-
# NEW PAYLOAD
|
|
65
|
-
class SystemTaskNotificationData(BaseStreamPayload):
|
|
66
|
-
sender_id: str
|
|
67
|
-
content: str
|
|
68
|
-
|
|
69
|
-
class ToDoItemData(BaseStreamPayload):
|
|
70
|
-
description: str
|
|
71
|
-
todo_id: str
|
|
72
|
-
status: str
|
|
73
|
-
|
|
74
|
-
class ToDoListUpdateData(BaseStreamPayload):
|
|
75
|
-
todos: List[ToDoItemData]
|
|
76
|
-
|
|
77
|
-
class EmptyData(BaseStreamPayload):
|
|
78
|
-
pass
|
|
79
|
-
|
|
80
|
-
# Union of all possible data payload types
|
|
81
|
-
StreamDataPayload = Union[
|
|
82
|
-
AssistantChunkData,
|
|
83
|
-
AssistantCompleteResponseData,
|
|
84
|
-
ToolInteractionLogEntryData,
|
|
85
|
-
AgentOperationalPhaseTransitionData,
|
|
86
|
-
ErrorEventData,
|
|
87
|
-
ToolInvocationApprovalRequestedData,
|
|
88
|
-
ToolInvocationAutoExecutingData,
|
|
89
|
-
SystemTaskNotificationData, # NEW
|
|
90
|
-
ToDoListUpdateData,
|
|
91
|
-
EmptyData
|
|
92
|
-
]
|
|
93
|
-
|
|
94
|
-
# Factory functions to create payload models from various inputs
|
|
95
|
-
|
|
96
|
-
def create_assistant_chunk_data(chunk_obj: Any) -> AssistantChunkData:
|
|
97
|
-
usage_data = None
|
|
98
|
-
if hasattr(chunk_obj, 'usage'):
|
|
99
|
-
usage_data = getattr(chunk_obj, 'usage')
|
|
100
|
-
elif isinstance(chunk_obj, dict) and 'usage' in chunk_obj:
|
|
101
|
-
usage_data = chunk_obj.get('usage')
|
|
102
|
-
|
|
103
|
-
parsed_usage = None
|
|
104
|
-
if usage_data:
|
|
105
|
-
if isinstance(usage_data, TokenUsage):
|
|
106
|
-
parsed_usage = usage_data
|
|
107
|
-
elif isinstance(usage_data, dict):
|
|
108
|
-
try:
|
|
109
|
-
parsed_usage = TokenUsage(**usage_data)
|
|
110
|
-
except Exception as e:
|
|
111
|
-
logger.warning(f"Could not parse usage dict into TokenUsage for AssistantChunkData: {e}. Usage dict: {usage_data}")
|
|
112
|
-
else:
|
|
113
|
-
logger.warning(f"Unsupported usage type {type(usage_data)} for AssistantChunkData.")
|
|
114
|
-
|
|
115
|
-
if hasattr(chunk_obj, 'content') and hasattr(chunk_obj, 'is_complete'):
|
|
116
|
-
return AssistantChunkData(
|
|
117
|
-
content=str(getattr(chunk_obj, 'content', '')),
|
|
118
|
-
reasoning=getattr(chunk_obj, 'reasoning', None),
|
|
119
|
-
is_complete=bool(getattr(chunk_obj, 'is_complete', False)),
|
|
120
|
-
usage=parsed_usage,
|
|
121
|
-
image_urls=getattr(chunk_obj, 'image_urls', None),
|
|
122
|
-
audio_urls=getattr(chunk_obj, 'audio_urls', None),
|
|
123
|
-
video_urls=getattr(chunk_obj, 'video_urls', None)
|
|
124
|
-
)
|
|
125
|
-
elif isinstance(chunk_obj, dict):
|
|
126
|
-
return AssistantChunkData(
|
|
127
|
-
content=str(chunk_obj.get('content', '')),
|
|
128
|
-
reasoning=chunk_obj.get('reasoning', None),
|
|
129
|
-
is_complete=bool(chunk_obj.get('is_complete', False)),
|
|
130
|
-
usage=parsed_usage,
|
|
131
|
-
image_urls=chunk_obj.get('image_urls', None),
|
|
132
|
-
audio_urls=chunk_obj.get('audio_urls', None),
|
|
133
|
-
video_urls=chunk_obj.get('video_urls', None)
|
|
134
|
-
)
|
|
135
|
-
raise ValueError(f"Cannot create AssistantChunkData from {type(chunk_obj)}")
|
|
136
|
-
|
|
137
|
-
def create_assistant_complete_response_data(complete_resp_obj: Any) -> AssistantCompleteResponseData:
|
|
138
|
-
usage_data = None
|
|
139
|
-
if hasattr(complete_resp_obj, 'usage'):
|
|
140
|
-
usage_data = getattr(complete_resp_obj, 'usage')
|
|
141
|
-
elif isinstance(complete_resp_obj, dict) and 'usage' in complete_resp_obj:
|
|
142
|
-
usage_data = complete_resp_obj.get('usage')
|
|
143
|
-
|
|
144
|
-
parsed_usage = None
|
|
145
|
-
if usage_data:
|
|
146
|
-
if isinstance(usage_data, TokenUsage):
|
|
147
|
-
parsed_usage = usage_data
|
|
148
|
-
elif isinstance(usage_data, dict):
|
|
149
|
-
try:
|
|
150
|
-
parsed_usage = TokenUsage(**usage_data)
|
|
151
|
-
except Exception as e: # pragma: no cover
|
|
152
|
-
logger.warning(f"Could not parse usage dict into TokenUsage for AssistantCompleteResponseData: {e}. Usage dict: {usage_data}")
|
|
153
|
-
else: # pragma: no cover
|
|
154
|
-
logger.warning(f"Unsupported usage type {type(usage_data)} for AssistantCompleteResponseData.")
|
|
155
|
-
|
|
156
|
-
if hasattr(complete_resp_obj, 'content'):
|
|
157
|
-
return AssistantCompleteResponseData(
|
|
158
|
-
content=str(getattr(complete_resp_obj, 'content', '')),
|
|
159
|
-
reasoning=getattr(complete_resp_obj, 'reasoning', None),
|
|
160
|
-
usage=parsed_usage,
|
|
161
|
-
image_urls=getattr(complete_resp_obj, 'image_urls', None),
|
|
162
|
-
audio_urls=getattr(complete_resp_obj, 'audio_urls', None),
|
|
163
|
-
video_urls=getattr(complete_resp_obj, 'video_urls', None)
|
|
164
|
-
)
|
|
165
|
-
elif isinstance(complete_resp_obj, dict):
|
|
166
|
-
return AssistantCompleteResponseData(
|
|
167
|
-
content=str(complete_resp_obj.get('content', '')),
|
|
168
|
-
reasoning=complete_resp_obj.get('reasoning', None),
|
|
169
|
-
usage=parsed_usage,
|
|
170
|
-
image_urls=complete_resp_obj.get('image_urls', None),
|
|
171
|
-
audio_urls=complete_resp_obj.get('audio_urls', None),
|
|
172
|
-
video_urls=complete_resp_obj.get('video_urls', None)
|
|
173
|
-
)
|
|
174
|
-
raise ValueError(f"Cannot create AssistantCompleteResponseData from {type(complete_resp_obj)}")
|
|
175
|
-
|
|
176
|
-
def create_tool_interaction_log_entry_data(log_data: Any) -> ToolInteractionLogEntryData:
|
|
177
|
-
if isinstance(log_data, dict):
|
|
178
|
-
if all(k in log_data for k in ['log_entry', 'tool_invocation_id', 'tool_name']):
|
|
179
|
-
return ToolInteractionLogEntryData(**log_data)
|
|
180
|
-
raise ValueError(f"Cannot create ToolInteractionLogEntryData from {type(log_data)}. Expected dict with 'log_entry', 'tool_invocation_id', and 'tool_name' keys.")
|
|
181
|
-
|
|
182
|
-
def create_agent_operational_phase_transition_data(phase_data_dict: Any) -> AgentOperationalPhaseTransitionData:
|
|
183
|
-
if isinstance(phase_data_dict, dict):
|
|
184
|
-
return AgentOperationalPhaseTransitionData(**phase_data_dict)
|
|
185
|
-
raise ValueError(f"Cannot create AgentOperationalPhaseTransitionData from {type(phase_data_dict)}")
|
|
186
|
-
|
|
187
|
-
def create_error_event_data(error_data_dict: Any) -> ErrorEventData:
|
|
188
|
-
if isinstance(error_data_dict, dict):
|
|
189
|
-
return ErrorEventData(**error_data_dict)
|
|
190
|
-
raise ValueError(f"Cannot create ErrorEventData from {type(error_data_dict)}")
|
|
191
|
-
|
|
192
|
-
def create_tool_invocation_approval_requested_data(approval_data_dict: Any) -> ToolInvocationApprovalRequestedData:
|
|
193
|
-
if isinstance(approval_data_dict, dict):
|
|
194
|
-
return ToolInvocationApprovalRequestedData(**approval_data_dict)
|
|
195
|
-
raise ValueError(f"Cannot create ToolInvocationApprovalRequestedData from {type(approval_data_dict)}")
|
|
196
|
-
|
|
197
|
-
def create_tool_invocation_auto_executing_data(auto_exec_data_dict: Any) -> ToolInvocationAutoExecutingData:
|
|
198
|
-
if isinstance(auto_exec_data_dict, dict):
|
|
199
|
-
return ToolInvocationAutoExecutingData(**auto_exec_data_dict)
|
|
200
|
-
raise ValueError(f"Cannot create ToolInvocationAutoExecutingData from {type(auto_exec_data_dict)}")
|
|
201
|
-
|
|
202
|
-
# NEW FACTORY FUNCTION
|
|
203
|
-
def create_system_task_notification_data(notification_data_dict: Any) -> SystemTaskNotificationData:
|
|
204
|
-
if isinstance(notification_data_dict, dict):
|
|
205
|
-
return SystemTaskNotificationData(**notification_data_dict)
|
|
206
|
-
raise ValueError(f"Cannot create SystemTaskNotificationData from {type(notification_data_dict)}")
|
|
207
|
-
|
|
208
|
-
def create_todo_list_update_data(todo_data_dict: Any) -> ToDoListUpdateData:
|
|
209
|
-
if isinstance(todo_data_dict, dict):
|
|
210
|
-
todos_payload = todo_data_dict.get('todos', [])
|
|
211
|
-
if not isinstance(todos_payload, list):
|
|
212
|
-
raise ValueError("Expected 'todos' to be a list when creating ToDoListUpdateData.")
|
|
213
|
-
todo_items = []
|
|
214
|
-
for todo_entry in todos_payload:
|
|
215
|
-
if not isinstance(todo_entry, dict):
|
|
216
|
-
logger.warning(f"Skipping non-dict todo entry when creating ToDoListUpdateData: {todo_entry!r}")
|
|
217
|
-
continue
|
|
218
|
-
try:
|
|
219
|
-
todo_items.append(ToDoItemData(**todo_entry))
|
|
220
|
-
except Exception as exc:
|
|
221
|
-
logger.warning(f"Failed to parse todo entry into ToDoItemData: {todo_entry!r}; error: {exc}")
|
|
222
|
-
return ToDoListUpdateData(todos=todo_items)
|
|
223
|
-
raise ValueError(f"Cannot create ToDoListUpdateData from {type(todo_data_dict)}")
|
|
1
|
+
"""Compatibility shim for stream event payloads."""
|
|
2
|
+
from .events.stream_event_payloads import *
|