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,18 @@
|
|
|
1
|
+
"""Shared adapters for streaming output."""
|
|
2
|
+
|
|
3
|
+
from .invocation_adapter import ToolInvocationAdapter
|
|
4
|
+
from .tool_syntax_registry import (
|
|
5
|
+
ToolSyntaxSpec,
|
|
6
|
+
get_tool_syntax_spec,
|
|
7
|
+
tool_syntax_registry_items,
|
|
8
|
+
)
|
|
9
|
+
from .tool_call_parsing import parse_json_tool_call, parse_xml_arguments
|
|
10
|
+
|
|
11
|
+
__all__ = [
|
|
12
|
+
"ToolInvocationAdapter",
|
|
13
|
+
"ToolSyntaxSpec",
|
|
14
|
+
"get_tool_syntax_spec",
|
|
15
|
+
"tool_syntax_registry_items",
|
|
16
|
+
"parse_json_tool_call",
|
|
17
|
+
"parse_xml_arguments",
|
|
18
|
+
]
|
|
@@ -0,0 +1,184 @@
|
|
|
1
|
+
"""
|
|
2
|
+
ToolInvocation Adapter: Converts tool SegmentEvents into ToolInvocation objects.
|
|
3
|
+
|
|
4
|
+
This adapter serves as the bridge between the streaming parser (which emits SegmentEvents)
|
|
5
|
+
and the agent's tool execution system (which expects ToolInvocation objects).
|
|
6
|
+
|
|
7
|
+
Key Design: The segment_id from the parser becomes the invocationId, ensuring
|
|
8
|
+
consistent ID tracking from parse time through approval and execution.
|
|
9
|
+
"""
|
|
10
|
+
from typing import Optional, List, Dict, Any, TYPE_CHECKING
|
|
11
|
+
import logging
|
|
12
|
+
|
|
13
|
+
from ..segments.segment_events import SegmentEvent, SegmentType, SegmentEventType
|
|
14
|
+
from .tool_syntax_registry import get_tool_syntax_spec
|
|
15
|
+
from .tool_call_parsing import parse_json_tool_call, parse_xml_arguments
|
|
16
|
+
from autobyteus.agent.tool_invocation import ToolInvocation
|
|
17
|
+
|
|
18
|
+
logger = logging.getLogger(__name__)
|
|
19
|
+
|
|
20
|
+
if TYPE_CHECKING:
|
|
21
|
+
from ..parser.json_parsing_strategies.base import JsonToolParsingStrategy
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
class ToolInvocationAdapter:
|
|
25
|
+
"""
|
|
26
|
+
Converts tool call SegmentEvents into ToolInvocation objects.
|
|
27
|
+
|
|
28
|
+
Usage:
|
|
29
|
+
adapter = ToolInvocationAdapter()
|
|
30
|
+
|
|
31
|
+
for event in parser.feed(chunk):
|
|
32
|
+
result = adapter.process_event(event)
|
|
33
|
+
if result:
|
|
34
|
+
# Got a complete ToolInvocation
|
|
35
|
+
enqueue_tool_invocation(result)
|
|
36
|
+
"""
|
|
37
|
+
|
|
38
|
+
def __init__(self, json_tool_parser: Optional["JsonToolParsingStrategy"] = None):
|
|
39
|
+
# Track active tool segments: segment_id -> accumulated data
|
|
40
|
+
self._active_segments: Dict[str, Dict[str, Any]] = {}
|
|
41
|
+
self._json_tool_parser = json_tool_parser
|
|
42
|
+
|
|
43
|
+
def process_event(self, event: SegmentEvent) -> Optional[ToolInvocation]:
|
|
44
|
+
"""
|
|
45
|
+
Process a SegmentEvent and return a ToolInvocation if complete.
|
|
46
|
+
|
|
47
|
+
Args:
|
|
48
|
+
event: A SegmentEvent from the streaming parser.
|
|
49
|
+
|
|
50
|
+
Returns:
|
|
51
|
+
ToolInvocation if a tool segment just completed, None otherwise.
|
|
52
|
+
"""
|
|
53
|
+
if event.event_type == SegmentEventType.START:
|
|
54
|
+
return self._handle_start(event)
|
|
55
|
+
elif event.event_type == SegmentEventType.CONTENT:
|
|
56
|
+
return self._handle_content(event)
|
|
57
|
+
elif event.event_type == SegmentEventType.END:
|
|
58
|
+
return self._handle_end(event)
|
|
59
|
+
return None
|
|
60
|
+
|
|
61
|
+
def _handle_start(self, event: SegmentEvent) -> None:
|
|
62
|
+
"""Handle SEGMENT_START events."""
|
|
63
|
+
if event.segment_type != SegmentType.TOOL_CALL and get_tool_syntax_spec(event.segment_type) is None:
|
|
64
|
+
return None
|
|
65
|
+
|
|
66
|
+
# Initialize tracking for this tool segment
|
|
67
|
+
metadata = event.payload.get("metadata", {})
|
|
68
|
+
tool_name = metadata.get("tool_name")
|
|
69
|
+
syntax_spec = get_tool_syntax_spec(event.segment_type)
|
|
70
|
+
if syntax_spec:
|
|
71
|
+
tool_name = syntax_spec.tool_name
|
|
72
|
+
|
|
73
|
+
self._active_segments[event.segment_id] = {
|
|
74
|
+
"segment_type": event.segment_type,
|
|
75
|
+
"tool_name": tool_name,
|
|
76
|
+
"content_buffer": "",
|
|
77
|
+
"arguments": {},
|
|
78
|
+
"syntax_spec": syntax_spec,
|
|
79
|
+
"metadata": metadata,
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
logger.debug(f"ToolInvocationAdapter: Started tracking segment {event.segment_id}")
|
|
83
|
+
return None
|
|
84
|
+
|
|
85
|
+
def _handle_content(self, event: SegmentEvent) -> None:
|
|
86
|
+
"""Handle SEGMENT_CONTENT events."""
|
|
87
|
+
if event.segment_id not in self._active_segments:
|
|
88
|
+
return None
|
|
89
|
+
|
|
90
|
+
# Accumulate content (for display purposes)
|
|
91
|
+
delta = event.payload.get("delta", "")
|
|
92
|
+
self._active_segments[event.segment_id]["content_buffer"] += delta
|
|
93
|
+
return None
|
|
94
|
+
|
|
95
|
+
def _handle_end(self, event: SegmentEvent) -> Optional[ToolInvocation]:
|
|
96
|
+
"""
|
|
97
|
+
Handle SEGMENT_END events.
|
|
98
|
+
|
|
99
|
+
When a tool segment ends, create and return a ToolInvocation.
|
|
100
|
+
"""
|
|
101
|
+
if event.segment_id not in self._active_segments:
|
|
102
|
+
return None
|
|
103
|
+
|
|
104
|
+
segment_data = self._active_segments.pop(event.segment_id)
|
|
105
|
+
|
|
106
|
+
# Extract metadata from END event (display metadata only)
|
|
107
|
+
metadata = event.payload.get("metadata", {})
|
|
108
|
+
segment_type = segment_data.get("segment_type")
|
|
109
|
+
tool_name = metadata.get("tool_name") or segment_data.get("tool_name")
|
|
110
|
+
arguments: Dict[str, Any] = segment_data.get("arguments", {})
|
|
111
|
+
content_buffer = segment_data.get("content_buffer", "")
|
|
112
|
+
start_metadata = segment_data.get("metadata", {})
|
|
113
|
+
syntax_spec = segment_data.get("syntax_spec")
|
|
114
|
+
|
|
115
|
+
if syntax_spec:
|
|
116
|
+
tool_name = syntax_spec.tool_name
|
|
117
|
+
args = syntax_spec.build_arguments(
|
|
118
|
+
{**start_metadata, **metadata},
|
|
119
|
+
content_buffer,
|
|
120
|
+
)
|
|
121
|
+
if args is None:
|
|
122
|
+
logger.warning(
|
|
123
|
+
f"Tool segment {event.segment_id} ended without required arguments for {tool_name}"
|
|
124
|
+
)
|
|
125
|
+
return None
|
|
126
|
+
arguments = args
|
|
127
|
+
elif segment_type == SegmentType.TOOL_CALL:
|
|
128
|
+
content = content_buffer
|
|
129
|
+
stripped = content.lstrip()
|
|
130
|
+
parsed_call = None
|
|
131
|
+
|
|
132
|
+
# Check if arguments were provided in metadata (e.g. Sentinel parser)
|
|
133
|
+
# First check start_metadata, then end metadata
|
|
134
|
+
if start_metadata.get("arguments"):
|
|
135
|
+
arguments = start_metadata["arguments"]
|
|
136
|
+
elif metadata.get("arguments"):
|
|
137
|
+
arguments = metadata["arguments"]
|
|
138
|
+
elif stripped.startswith("{") or stripped.startswith("["):
|
|
139
|
+
parsed_call = parse_json_tool_call(stripped, self._json_tool_parser)
|
|
140
|
+
else:
|
|
141
|
+
arguments = parse_xml_arguments(content)
|
|
142
|
+
|
|
143
|
+
if parsed_call:
|
|
144
|
+
tool_name = tool_name or parsed_call.get("name")
|
|
145
|
+
arguments = parsed_call.get("arguments") or {}
|
|
146
|
+
|
|
147
|
+
if not tool_name:
|
|
148
|
+
logger.warning(f"Tool segment {event.segment_id} ended without tool_name")
|
|
149
|
+
return None
|
|
150
|
+
|
|
151
|
+
# Create ToolInvocation with segment_id as the invocation id
|
|
152
|
+
invocation = ToolInvocation(
|
|
153
|
+
name=tool_name,
|
|
154
|
+
arguments=arguments,
|
|
155
|
+
id=event.segment_id # Key: segment_id becomes invocationId
|
|
156
|
+
)
|
|
157
|
+
|
|
158
|
+
logger.info(f"ToolInvocationAdapter: Created invocation {invocation.id} for tool {tool_name}")
|
|
159
|
+
return invocation
|
|
160
|
+
|
|
161
|
+
def process_events(self, events: List[SegmentEvent]) -> List[ToolInvocation]:
|
|
162
|
+
"""
|
|
163
|
+
Process multiple events and return all completed ToolInvocations.
|
|
164
|
+
|
|
165
|
+
Args:
|
|
166
|
+
events: List of SegmentEvents from the parser.
|
|
167
|
+
|
|
168
|
+
Returns:
|
|
169
|
+
List of ToolInvocations for any completed tool segments.
|
|
170
|
+
"""
|
|
171
|
+
invocations = []
|
|
172
|
+
for event in events:
|
|
173
|
+
result = self.process_event(event)
|
|
174
|
+
if result:
|
|
175
|
+
invocations.append(result)
|
|
176
|
+
return invocations
|
|
177
|
+
|
|
178
|
+
def reset(self) -> None:
|
|
179
|
+
"""Clear all tracking state."""
|
|
180
|
+
self._active_segments.clear()
|
|
181
|
+
|
|
182
|
+
def get_active_segment_ids(self) -> List[str]:
|
|
183
|
+
"""Get IDs of currently tracked tool segments."""
|
|
184
|
+
return list(self._active_segments.keys())
|
|
@@ -0,0 +1,163 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Utility parsers for tool call argument extraction.
|
|
3
|
+
|
|
4
|
+
These functions are intentionally decoupled from streaming states so the
|
|
5
|
+
ToolInvocationAdapter can be the single source of truth for arguments.
|
|
6
|
+
"""
|
|
7
|
+
from __future__ import annotations
|
|
8
|
+
|
|
9
|
+
import json
|
|
10
|
+
import re
|
|
11
|
+
import xml.etree.ElementTree as ET
|
|
12
|
+
from typing import Any, Dict, Optional
|
|
13
|
+
|
|
14
|
+
from ..parser.json_parsing_strategies.base import JsonToolParsingStrategy
|
|
15
|
+
|
|
16
|
+
_ARGS_OPEN = "<arguments>"
|
|
17
|
+
_ARGS_CLOSE = "</arguments>"
|
|
18
|
+
_TAG_SPLIT_PATTERN = re.compile(r"(<[A-Za-z!/][^>]*>)")
|
|
19
|
+
_ENTITY_PATTERN = re.compile(r"&(?!(?:amp|lt|gt|quot|apos|#\d+|#x[0-9a-fA-F]+);)")
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
def parse_xml_arguments(content: str) -> Dict[str, Any]:
|
|
23
|
+
"""
|
|
24
|
+
Parse XML tool arguments from a tool-call content body.
|
|
25
|
+
|
|
26
|
+
Supports:
|
|
27
|
+
1) <arguments><arg name="x">...</arg></arguments>
|
|
28
|
+
2) <arguments><path>...</path></arguments>
|
|
29
|
+
3) Direct content without <arguments> wrapper
|
|
30
|
+
"""
|
|
31
|
+
args_match = re.search(
|
|
32
|
+
rf"{_ARGS_OPEN}(.*?){_ARGS_CLOSE}",
|
|
33
|
+
content,
|
|
34
|
+
re.IGNORECASE | re.DOTALL,
|
|
35
|
+
)
|
|
36
|
+
if args_match:
|
|
37
|
+
args_content = args_match.group(1)
|
|
38
|
+
else:
|
|
39
|
+
args_content = content.strip()
|
|
40
|
+
|
|
41
|
+
if not args_content:
|
|
42
|
+
return {}
|
|
43
|
+
|
|
44
|
+
try:
|
|
45
|
+
root = ET.fromstring(f"<root>{args_content}</root>")
|
|
46
|
+
return _parse_xml_children(root)
|
|
47
|
+
except ET.ParseError:
|
|
48
|
+
sanitized = _sanitize_xml_fragment(args_content)
|
|
49
|
+
try:
|
|
50
|
+
root = ET.fromstring(f"<root>{sanitized}</root>")
|
|
51
|
+
return _parse_xml_children(root)
|
|
52
|
+
except ET.ParseError:
|
|
53
|
+
return _parse_legacy_arguments(args_content)
|
|
54
|
+
|
|
55
|
+
|
|
56
|
+
def parse_json_tool_call(
|
|
57
|
+
json_str: str,
|
|
58
|
+
parser: Optional[JsonToolParsingStrategy] = None,
|
|
59
|
+
) -> Optional[Dict[str, Any]]:
|
|
60
|
+
"""
|
|
61
|
+
Parse a JSON string into tool call info.
|
|
62
|
+
|
|
63
|
+
Returns dict with 'name' and 'arguments', or None if invalid.
|
|
64
|
+
"""
|
|
65
|
+
if parser is not None:
|
|
66
|
+
parsed_calls = parser.parse(json_str)
|
|
67
|
+
if parsed_calls:
|
|
68
|
+
return parsed_calls[0]
|
|
69
|
+
return None
|
|
70
|
+
|
|
71
|
+
try:
|
|
72
|
+
data = json.loads(json_str)
|
|
73
|
+
|
|
74
|
+
if isinstance(data, list) and data:
|
|
75
|
+
data = data[0]
|
|
76
|
+
|
|
77
|
+
if isinstance(data, dict):
|
|
78
|
+
name = (
|
|
79
|
+
data.get("name")
|
|
80
|
+
or data.get("tool")
|
|
81
|
+
or data.get("function", {}).get("name")
|
|
82
|
+
or "unknown"
|
|
83
|
+
)
|
|
84
|
+
arguments = (
|
|
85
|
+
data.get("arguments")
|
|
86
|
+
or data.get("parameters")
|
|
87
|
+
or data.get("function", {}).get("arguments")
|
|
88
|
+
or {}
|
|
89
|
+
)
|
|
90
|
+
if isinstance(arguments, str):
|
|
91
|
+
try:
|
|
92
|
+
arguments = json.loads(arguments)
|
|
93
|
+
except json.JSONDecodeError:
|
|
94
|
+
pass
|
|
95
|
+
return {"name": name, "arguments": arguments}
|
|
96
|
+
except json.JSONDecodeError:
|
|
97
|
+
return None
|
|
98
|
+
|
|
99
|
+
return None
|
|
100
|
+
|
|
101
|
+
|
|
102
|
+
def _parse_xml_children(element: ET.Element) -> Dict[str, Any]:
|
|
103
|
+
arguments: Dict[str, Any] = {}
|
|
104
|
+
for child in element:
|
|
105
|
+
name = child.attrib.get("name") or child.tag
|
|
106
|
+
if not name:
|
|
107
|
+
continue
|
|
108
|
+
arguments[name] = _parse_xml_value(child)
|
|
109
|
+
return arguments
|
|
110
|
+
|
|
111
|
+
|
|
112
|
+
def _parse_xml_value(element: ET.Element) -> Any:
|
|
113
|
+
items = [child for child in element if child.tag == "item"]
|
|
114
|
+
if items:
|
|
115
|
+
return [_parse_item_value(item) for item in items]
|
|
116
|
+
|
|
117
|
+
arg_children = [child for child in element if child.tag == "arg"]
|
|
118
|
+
if arg_children:
|
|
119
|
+
return _parse_xml_children(element)
|
|
120
|
+
|
|
121
|
+
other_children = [child for child in element if child.tag not in {"arg", "item"}]
|
|
122
|
+
if other_children:
|
|
123
|
+
return _parse_xml_children(element)
|
|
124
|
+
|
|
125
|
+
text = element.text or ""
|
|
126
|
+
return text.strip()
|
|
127
|
+
|
|
128
|
+
|
|
129
|
+
def _parse_item_value(element: ET.Element) -> Any:
|
|
130
|
+
arg_children = [child for child in element if child.tag == "arg"]
|
|
131
|
+
if arg_children:
|
|
132
|
+
return _parse_xml_children(element)
|
|
133
|
+
other_children = [child for child in element if child.tag not in {"arg", "item"}]
|
|
134
|
+
if other_children:
|
|
135
|
+
return _parse_xml_children(element)
|
|
136
|
+
text = element.text or ""
|
|
137
|
+
return text.strip()
|
|
138
|
+
|
|
139
|
+
|
|
140
|
+
def _parse_legacy_arguments(args_content: str) -> Dict[str, Any]:
|
|
141
|
+
arguments: Dict[str, Any] = {}
|
|
142
|
+
arg_pattern = re.compile(r"<(\\w+)>(.*?)</\\1>", re.DOTALL)
|
|
143
|
+
for match in arg_pattern.finditer(args_content):
|
|
144
|
+
arg_name = match.group(1)
|
|
145
|
+
arg_value = match.group(2).strip()
|
|
146
|
+
arguments[arg_name] = arg_value
|
|
147
|
+
return arguments
|
|
148
|
+
|
|
149
|
+
|
|
150
|
+
def _sanitize_xml_fragment(fragment: str) -> str:
|
|
151
|
+
"""Escape raw text to make fragment XML-safe without touching tags."""
|
|
152
|
+
parts = _TAG_SPLIT_PATTERN.split(fragment)
|
|
153
|
+
sanitized_parts = []
|
|
154
|
+
for part in parts:
|
|
155
|
+
if not part:
|
|
156
|
+
continue
|
|
157
|
+
if part.startswith("<") and part.endswith(">"):
|
|
158
|
+
sanitized_parts.append(part)
|
|
159
|
+
continue
|
|
160
|
+
escaped = _ENTITY_PATTERN.sub("&", part)
|
|
161
|
+
escaped = escaped.replace("<", "<")
|
|
162
|
+
sanitized_parts.append(escaped)
|
|
163
|
+
return "".join(sanitized_parts)
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Registry for mapping segment syntaxes to tool invocations.
|
|
3
|
+
"""
|
|
4
|
+
from __future__ import annotations
|
|
5
|
+
|
|
6
|
+
from dataclasses import dataclass
|
|
7
|
+
from typing import Callable, Dict, Optional, Tuple
|
|
8
|
+
|
|
9
|
+
from ..segments.segment_events import SegmentType
|
|
10
|
+
|
|
11
|
+
ToolArgsBuilder = Callable[[dict, str], Optional[dict]]
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
@dataclass(frozen=True)
|
|
15
|
+
class ToolSyntaxSpec:
|
|
16
|
+
"""Defines how a segment type maps to a tool invocation."""
|
|
17
|
+
|
|
18
|
+
tool_name: str
|
|
19
|
+
build_arguments: ToolArgsBuilder
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
def _build_write_file_args(metadata: dict, content: str) -> Optional[dict]:
|
|
23
|
+
path = metadata.get("path")
|
|
24
|
+
if not path:
|
|
25
|
+
return None
|
|
26
|
+
return {"path": path, "content": content}
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
def _build_run_bash_args(metadata: dict, content: str) -> Optional[dict]:
|
|
30
|
+
command = content or metadata.get("cmd") or ""
|
|
31
|
+
if not command:
|
|
32
|
+
return None
|
|
33
|
+
return {"command": command}
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
def _build_patch_file_args(metadata: dict, content: str) -> Optional[dict]:
|
|
37
|
+
path = metadata.get("path")
|
|
38
|
+
if not path:
|
|
39
|
+
return None
|
|
40
|
+
# 'content' here is the accumulated patch delta from the stream
|
|
41
|
+
return {"path": path, "patch": content}
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
_TOOL_SYNTAX_REGISTRY: Dict[SegmentType, ToolSyntaxSpec] = {
|
|
45
|
+
SegmentType.WRITE_FILE: ToolSyntaxSpec(
|
|
46
|
+
tool_name="write_file",
|
|
47
|
+
build_arguments=_build_write_file_args,
|
|
48
|
+
),
|
|
49
|
+
SegmentType.RUN_BASH: ToolSyntaxSpec(
|
|
50
|
+
tool_name="run_bash",
|
|
51
|
+
build_arguments=_build_run_bash_args,
|
|
52
|
+
),
|
|
53
|
+
SegmentType.PATCH_FILE: ToolSyntaxSpec(
|
|
54
|
+
tool_name="patch_file",
|
|
55
|
+
build_arguments=_build_patch_file_args,
|
|
56
|
+
),
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
|
|
60
|
+
def get_tool_syntax_spec(segment_type: SegmentType) -> Optional[ToolSyntaxSpec]:
|
|
61
|
+
"""Return tool syntax spec for a segment type if registered."""
|
|
62
|
+
return _TOOL_SYNTAX_REGISTRY.get(segment_type)
|
|
63
|
+
|
|
64
|
+
|
|
65
|
+
def tool_syntax_registry_items() -> Tuple[Tuple[SegmentType, ToolSyntaxSpec], ...]:
|
|
66
|
+
"""Expose registry items for inspection/testing."""
|
|
67
|
+
return tuple(_TOOL_SYNTAX_REGISTRY.items())
|
|
@@ -1,184 +1,4 @@
|
|
|
1
|
-
|
|
2
|
-
import
|
|
3
|
-
import logging
|
|
4
|
-
import traceback
|
|
5
|
-
import functools
|
|
6
|
-
import queue as standard_queue
|
|
7
|
-
from typing import AsyncIterator, Dict, Any, TYPE_CHECKING, List, Optional, Callable, Union
|
|
1
|
+
"""Compatibility shim for AgentEventStream."""
|
|
2
|
+
from .streams.agent_event_stream import AgentEventStream
|
|
8
3
|
|
|
9
|
-
|
|
10
|
-
from autobyteus.agent.streaming.stream_events import StreamEvent, StreamEventType
|
|
11
|
-
from autobyteus.agent.streaming.stream_event_payloads import (
|
|
12
|
-
create_assistant_chunk_data,
|
|
13
|
-
create_assistant_complete_response_data,
|
|
14
|
-
create_tool_interaction_log_entry_data,
|
|
15
|
-
create_agent_operational_phase_transition_data,
|
|
16
|
-
create_error_event_data,
|
|
17
|
-
create_tool_invocation_approval_requested_data,
|
|
18
|
-
create_tool_invocation_auto_executing_data,
|
|
19
|
-
create_system_task_notification_data, # NEW
|
|
20
|
-
create_todo_list_update_data,
|
|
21
|
-
AssistantChunkData,
|
|
22
|
-
AssistantCompleteResponseData,
|
|
23
|
-
ToolInteractionLogEntryData,
|
|
24
|
-
AgentOperationalPhaseTransitionData,
|
|
25
|
-
ToolInvocationApprovalRequestedData,
|
|
26
|
-
ToolInvocationAutoExecutingData,
|
|
27
|
-
ErrorEventData,
|
|
28
|
-
SystemTaskNotificationData, # NEW
|
|
29
|
-
ToDoListUpdateData,
|
|
30
|
-
EmptyData,
|
|
31
|
-
StreamDataPayload,
|
|
32
|
-
)
|
|
33
|
-
from .queue_streamer import stream_queue_items
|
|
34
|
-
from autobyteus.events.event_types import EventType
|
|
35
|
-
from autobyteus.events.event_emitter import EventEmitter
|
|
36
|
-
|
|
37
|
-
if TYPE_CHECKING:
|
|
38
|
-
from autobyteus.agent.agent import Agent
|
|
39
|
-
from autobyteus.agent.events.notifiers import AgentExternalEventNotifier
|
|
40
|
-
|
|
41
|
-
logger = logging.getLogger(__name__)
|
|
42
|
-
|
|
43
|
-
_AES_INTERNAL_SENTINEL = object()
|
|
44
|
-
|
|
45
|
-
class AgentEventStream(EventEmitter):
|
|
46
|
-
def __init__(self, agent: 'Agent'):
|
|
47
|
-
super().__init__()
|
|
48
|
-
|
|
49
|
-
from autobyteus.agent.agent import Agent as ConcreteAgent
|
|
50
|
-
if not isinstance(agent, ConcreteAgent):
|
|
51
|
-
raise TypeError(f"AgentEventStream requires an Agent instance, got {type(agent).__name__}.")
|
|
52
|
-
|
|
53
|
-
self.agent_id: str = agent.agent_id
|
|
54
|
-
|
|
55
|
-
self._loop = asyncio.get_event_loop()
|
|
56
|
-
self._generic_stream_event_internal_q: standard_queue.Queue[Union[StreamEvent, object]] = standard_queue.Queue()
|
|
57
|
-
|
|
58
|
-
self._notifier: Optional['AgentExternalEventNotifier'] = None
|
|
59
|
-
if agent.context and agent.context.phase_manager:
|
|
60
|
-
self._notifier = agent.context.phase_manager.notifier
|
|
61
|
-
|
|
62
|
-
if not self._notifier:
|
|
63
|
-
logger.error(f"AgentEventStream for '{self.agent_id}': Notifier not available. No events will be streamed.")
|
|
64
|
-
return
|
|
65
|
-
|
|
66
|
-
self._register_listeners()
|
|
67
|
-
|
|
68
|
-
logger.info(f"AgentEventStream (ID: {self.object_id}) initialized for agent_id '{self.agent_id}'. Subscribed to notifier.")
|
|
69
|
-
|
|
70
|
-
def _register_listeners(self):
|
|
71
|
-
"""Subscribes this instance's handler to all relevant events from the notifier."""
|
|
72
|
-
all_agent_event_types = [et for et in EventType if et.name.startswith("AGENT_")]
|
|
73
|
-
|
|
74
|
-
for event_type in all_agent_event_types:
|
|
75
|
-
self.subscribe_from(self._notifier, event_type, self._handle_notifier_event_sync)
|
|
76
|
-
|
|
77
|
-
def _handle_notifier_event_sync(self, event_type: EventType, payload: Optional[Any] = None, object_id: Optional[str] = None, **kwargs):
|
|
78
|
-
event_agent_id = kwargs.get("agent_id", self.agent_id)
|
|
79
|
-
|
|
80
|
-
typed_payload_for_stream_event: Optional[StreamDataPayload] = None
|
|
81
|
-
stream_event_type_for_generic_stream: Optional[StreamEventType] = None
|
|
82
|
-
|
|
83
|
-
try:
|
|
84
|
-
if event_type == EventType.AGENT_PHASE_IDLE_ENTERED:
|
|
85
|
-
typed_payload_for_stream_event = create_agent_operational_phase_transition_data(payload)
|
|
86
|
-
stream_event_type_for_generic_stream = StreamEventType.AGENT_IDLE
|
|
87
|
-
elif event_type.name.startswith("AGENT_PHASE_"):
|
|
88
|
-
typed_payload_for_stream_event = create_agent_operational_phase_transition_data(payload)
|
|
89
|
-
stream_event_type_for_generic_stream = StreamEventType.AGENT_OPERATIONAL_PHASE_TRANSITION
|
|
90
|
-
elif event_type == EventType.AGENT_DATA_ASSISTANT_CHUNK:
|
|
91
|
-
typed_payload_for_stream_event = create_assistant_chunk_data(payload)
|
|
92
|
-
stream_event_type_for_generic_stream = StreamEventType.ASSISTANT_CHUNK
|
|
93
|
-
elif event_type == EventType.AGENT_DATA_ASSISTANT_COMPLETE_RESPONSE:
|
|
94
|
-
typed_payload_for_stream_event = create_assistant_complete_response_data(payload)
|
|
95
|
-
stream_event_type_for_generic_stream = StreamEventType.ASSISTANT_COMPLETE_RESPONSE
|
|
96
|
-
elif event_type == EventType.AGENT_DATA_TOOL_LOG:
|
|
97
|
-
typed_payload_for_stream_event = create_tool_interaction_log_entry_data(payload)
|
|
98
|
-
stream_event_type_for_generic_stream = StreamEventType.TOOL_INTERACTION_LOG_ENTRY
|
|
99
|
-
elif event_type == EventType.AGENT_REQUEST_TOOL_INVOCATION_APPROVAL:
|
|
100
|
-
typed_payload_for_stream_event = create_tool_invocation_approval_requested_data(payload)
|
|
101
|
-
stream_event_type_for_generic_stream = StreamEventType.TOOL_INVOCATION_APPROVAL_REQUESTED
|
|
102
|
-
elif event_type == EventType.AGENT_TOOL_INVOCATION_AUTO_EXECUTING:
|
|
103
|
-
typed_payload_for_stream_event = create_tool_invocation_auto_executing_data(payload)
|
|
104
|
-
stream_event_type_for_generic_stream = StreamEventType.TOOL_INVOCATION_AUTO_EXECUTING
|
|
105
|
-
elif event_type == EventType.AGENT_ERROR_OUTPUT_GENERATION:
|
|
106
|
-
typed_payload_for_stream_event = create_error_event_data(payload)
|
|
107
|
-
stream_event_type_for_generic_stream = StreamEventType.ERROR_EVENT
|
|
108
|
-
# NEW MAPPING
|
|
109
|
-
elif event_type == EventType.AGENT_DATA_SYSTEM_TASK_NOTIFICATION_RECEIVED:
|
|
110
|
-
typed_payload_for_stream_event = create_system_task_notification_data(payload)
|
|
111
|
-
stream_event_type_for_generic_stream = StreamEventType.SYSTEM_TASK_NOTIFICATION
|
|
112
|
-
elif event_type == EventType.AGENT_DATA_TODO_LIST_UPDATED:
|
|
113
|
-
typed_payload_for_stream_event = create_todo_list_update_data(payload)
|
|
114
|
-
stream_event_type_for_generic_stream = StreamEventType.AGENT_TODO_LIST_UPDATE
|
|
115
|
-
|
|
116
|
-
elif event_type in [EventType.AGENT_DATA_ASSISTANT_CHUNK_STREAM_END, EventType.AGENT_DATA_TOOL_LOG_STREAM_END]:
|
|
117
|
-
pass
|
|
118
|
-
else:
|
|
119
|
-
logger.debug(f"AgentEventStream received internal event '{event_type.name}' with no direct stream mapping.")
|
|
120
|
-
|
|
121
|
-
except Exception as e:
|
|
122
|
-
logger.error(f"AgentEventStream error processing payload for event '{event_type.name}': {e}", exc_info=True)
|
|
123
|
-
|
|
124
|
-
if typed_payload_for_stream_event and stream_event_type_for_generic_stream:
|
|
125
|
-
stream_event = StreamEvent(
|
|
126
|
-
agent_id=event_agent_id,
|
|
127
|
-
event_type=stream_event_type_for_generic_stream,
|
|
128
|
-
data=typed_payload_for_stream_event
|
|
129
|
-
)
|
|
130
|
-
self._generic_stream_event_internal_q.put(stream_event)
|
|
131
|
-
|
|
132
|
-
async def close(self):
|
|
133
|
-
logger.info(f"AgentEventStream (ID: {self.object_id}) for '{self.agent_id}': close() called. Unsubscribing all listeners and signaling.")
|
|
134
|
-
self.unsubscribe_all_listeners()
|
|
135
|
-
await self._loop.run_in_executor(None, self._generic_stream_event_internal_q.put, _AES_INTERNAL_SENTINEL)
|
|
136
|
-
|
|
137
|
-
async def all_events(self) -> AsyncIterator[StreamEvent]:
|
|
138
|
-
"""The primary method to consume all structured events from the agent."""
|
|
139
|
-
async for event in stream_queue_items(self._generic_stream_event_internal_q, _AES_INTERNAL_SENTINEL, f"agent_{self.agent_id}_all_events"):
|
|
140
|
-
yield event
|
|
141
|
-
|
|
142
|
-
# --- Convenience Stream Methods ---
|
|
143
|
-
|
|
144
|
-
async def stream_assistant_chunks(self) -> AsyncIterator[AssistantChunkData]:
|
|
145
|
-
"""A convenience async generator that yields only assistant content/reasoning chunks."""
|
|
146
|
-
async for event in self.all_events():
|
|
147
|
-
if event.event_type == StreamEventType.ASSISTANT_CHUNK and isinstance(event.data, AssistantChunkData):
|
|
148
|
-
yield event.data
|
|
149
|
-
|
|
150
|
-
async def stream_assistant_final_response(self) -> AsyncIterator[AssistantCompleteResponseData]:
|
|
151
|
-
"""A convenience async generator that yields only the final, complete assistant responses."""
|
|
152
|
-
async for event in self.all_events():
|
|
153
|
-
if event.event_type == StreamEventType.ASSISTANT_COMPLETE_RESPONSE and isinstance(event.data, AssistantCompleteResponseData):
|
|
154
|
-
yield event.data
|
|
155
|
-
|
|
156
|
-
async def stream_tool_logs(self) -> AsyncIterator[ToolInteractionLogEntryData]:
|
|
157
|
-
"""A convenience async generator that yields only tool interaction log entries."""
|
|
158
|
-
async for event in self.all_events():
|
|
159
|
-
if event.event_type == StreamEventType.TOOL_INTERACTION_LOG_ENTRY and isinstance(event.data, ToolInteractionLogEntryData):
|
|
160
|
-
yield event.data
|
|
161
|
-
|
|
162
|
-
async def stream_phase_transitions(self) -> AsyncIterator[AgentOperationalPhaseTransitionData]:
|
|
163
|
-
"""A convenience async generator that yields only agent phase transition data."""
|
|
164
|
-
async for event in self.all_events():
|
|
165
|
-
if event.event_type == StreamEventType.AGENT_OPERATIONAL_PHASE_TRANSITION and isinstance(event.data, AgentOperationalPhaseTransitionData):
|
|
166
|
-
yield event.data
|
|
167
|
-
|
|
168
|
-
async def stream_tool_approval_requests(self) -> AsyncIterator[ToolInvocationApprovalRequestedData]:
|
|
169
|
-
"""A convenience async generator that yields only requests for tool invocation approval."""
|
|
170
|
-
async for event in self.all_events():
|
|
171
|
-
if event.event_type == StreamEventType.TOOL_INVOCATION_APPROVAL_REQUESTED and isinstance(event.data, ToolInvocationApprovalRequestedData):
|
|
172
|
-
yield event.data
|
|
173
|
-
|
|
174
|
-
async def stream_tool_auto_executing(self) -> AsyncIterator[ToolInvocationAutoExecutingData]:
|
|
175
|
-
"""A convenience async generator that yields only events for tools being auto-executed."""
|
|
176
|
-
async for event in self.all_events():
|
|
177
|
-
if event.event_type == StreamEventType.TOOL_INVOCATION_AUTO_EXECUTING and isinstance(event.data, ToolInvocationAutoExecutingData):
|
|
178
|
-
yield event.data
|
|
179
|
-
|
|
180
|
-
async def stream_errors(self) -> AsyncIterator[ErrorEventData]:
|
|
181
|
-
"""A convenience async generator that yields only error events."""
|
|
182
|
-
async for event in self.all_events():
|
|
183
|
-
if event.event_type == StreamEventType.ERROR_EVENT and isinstance(event.data, ErrorEventData):
|
|
184
|
-
yield event.data
|
|
4
|
+
__all__ = ["AgentEventStream"]
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
"""API tool call streaming helpers."""
|
|
2
|
+
|
|
3
|
+
from .json_string_field_extractor import JsonStringFieldExtractor, FieldExtractionResult
|
|
4
|
+
from .file_content_streamer import (
|
|
5
|
+
FileContentStreamUpdate,
|
|
6
|
+
WriteFileContentStreamer,
|
|
7
|
+
PatchFileContentStreamer,
|
|
8
|
+
)
|
|
9
|
+
|
|
10
|
+
__all__ = [
|
|
11
|
+
"JsonStringFieldExtractor",
|
|
12
|
+
"FieldExtractionResult",
|
|
13
|
+
"FileContentStreamUpdate",
|
|
14
|
+
"WriteFileContentStreamer",
|
|
15
|
+
"PatchFileContentStreamer",
|
|
16
|
+
]
|