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
|
@@ -8,9 +8,11 @@ from autobyteus.agent.events import (
|
|
|
8
8
|
AgentReadyEvent, # MODIFIED: Renamed from AgentStartedEvent
|
|
9
9
|
AgentStoppedEvent,
|
|
10
10
|
AgentErrorEvent,
|
|
11
|
+
AgentIdleEvent,
|
|
12
|
+
ShutdownRequestedEvent,
|
|
11
13
|
LifecycleEvent
|
|
12
14
|
)
|
|
13
|
-
from autobyteus.agent.
|
|
15
|
+
from autobyteus.agent.status.status_enum import AgentStatus # Import new status enum
|
|
14
16
|
|
|
15
17
|
if TYPE_CHECKING:
|
|
16
18
|
from autobyteus.agent.context import AgentContext
|
|
@@ -20,8 +22,8 @@ logger = logging.getLogger(__name__)
|
|
|
20
22
|
class LifecycleEventLogger(AgentEventHandler):
|
|
21
23
|
"""
|
|
22
24
|
Logs various lifecycle events for an agent.
|
|
23
|
-
This handler does not modify agent state directly;
|
|
24
|
-
|
|
25
|
+
This handler does not modify agent state directly; status changes are projected
|
|
26
|
+
from events.
|
|
25
27
|
"""
|
|
26
28
|
|
|
27
29
|
async def handle(self,
|
|
@@ -32,33 +34,39 @@ class LifecycleEventLogger(AgentEventHandler):
|
|
|
32
34
|
|
|
33
35
|
Args:
|
|
34
36
|
event: The lifecycle event object (AgentReadyEvent, AgentStoppedEvent, etc.).
|
|
35
|
-
context: The composite AgentContext (used for agent_id and current
|
|
37
|
+
context: The composite AgentContext (used for agent_id and current status).
|
|
36
38
|
"""
|
|
37
39
|
|
|
38
40
|
agent_id = context.agent_id
|
|
39
|
-
# MODIFIED: Use
|
|
40
|
-
|
|
41
|
+
# MODIFIED: Use current_status instead of status
|
|
42
|
+
current_status_val = context.current_status.value if context.current_status else "None (Status not set)"
|
|
41
43
|
|
|
42
44
|
if isinstance(event, AgentReadyEvent): # MODIFIED: Check for AgentReadyEvent
|
|
43
|
-
logger.info(f"Agent '{agent_id}' Logged AgentReadyEvent. Current agent
|
|
45
|
+
logger.info(f"Agent '{agent_id}' Logged AgentReadyEvent. Current agent status: {current_status_val}") # MODIFIED log message
|
|
44
46
|
|
|
45
47
|
elif isinstance(event, AgentStoppedEvent):
|
|
46
|
-
logger.info(f"Agent '{agent_id}' Logged AgentStoppedEvent. Current agent
|
|
48
|
+
logger.info(f"Agent '{agent_id}' Logged AgentStoppedEvent. Current agent status: {current_status_val}")
|
|
49
|
+
|
|
50
|
+
elif isinstance(event, AgentIdleEvent):
|
|
51
|
+
logger.info(f"Agent '{agent_id}' Logged AgentIdleEvent. Current agent status: {current_status_val}")
|
|
52
|
+
|
|
53
|
+
elif isinstance(event, ShutdownRequestedEvent):
|
|
54
|
+
logger.info(f"Agent '{agent_id}' Logged ShutdownRequestedEvent. Current agent status: {current_status_val}")
|
|
47
55
|
|
|
48
56
|
elif isinstance(event, AgentErrorEvent):
|
|
49
57
|
logger.error(
|
|
50
58
|
f"Agent '{agent_id}' Logged AgentErrorEvent: {event.error_message}. "
|
|
51
|
-
f"Details: {event.exception_details}. Current agent
|
|
59
|
+
f"Details: {event.exception_details}. Current agent status: {current_status_val}"
|
|
52
60
|
)
|
|
53
61
|
|
|
54
62
|
else: # pragma: no cover
|
|
55
63
|
if isinstance(event, LifecycleEvent):
|
|
56
64
|
logger.warning(
|
|
57
65
|
f"LifecycleEventLogger for agent '{agent_id}' received an unhandled "
|
|
58
|
-
f"specific LifecycleEvent type: {type(event)}. Event: {event}. Current
|
|
66
|
+
f"specific LifecycleEvent type: {type(event)}. Event: {event}. Current status: {current_status_val}"
|
|
59
67
|
)
|
|
60
68
|
else:
|
|
61
69
|
logger.warning(
|
|
62
70
|
f"LifecycleEventLogger for agent '{agent_id}' received an "
|
|
63
|
-
f"unexpected event type: {type(event)}. Event: {event}. Current
|
|
71
|
+
f"unexpected event type: {type(event)}. Event: {event}. Current status: {current_status_val}"
|
|
64
72
|
)
|
|
@@ -6,7 +6,6 @@ from autobyteus.agent.handlers.base_event_handler import AgentEventHandler
|
|
|
6
6
|
from autobyteus.agent.events import LLMCompleteResponseReceivedEvent
|
|
7
7
|
from autobyteus.llm.utils.response_types import CompleteResponse
|
|
8
8
|
from autobyteus.agent.llm_response_processor import BaseLLMResponseProcessor
|
|
9
|
-
from autobyteus.tools.usage.parsers.exceptions import ToolUsageParseException
|
|
10
9
|
|
|
11
10
|
|
|
12
11
|
if TYPE_CHECKING:
|
|
@@ -49,8 +48,8 @@ class LLMCompleteResponseReceivedEventHandler(AgentEventHandler):
|
|
|
49
48
|
any_processor_took_action = False
|
|
50
49
|
|
|
51
50
|
notifier: Optional['AgentExternalEventNotifier'] = None
|
|
52
|
-
if context.
|
|
53
|
-
notifier = context.
|
|
51
|
+
if context.status_manager:
|
|
52
|
+
notifier = context.status_manager.notifier
|
|
54
53
|
|
|
55
54
|
if not notifier: # pragma: no cover
|
|
56
55
|
logger.error(f"Agent '{agent_id}': Notifier not available in LLMCompleteResponseReceivedEventHandler. Cannot emit complete response event.")
|
|
@@ -63,8 +62,15 @@ class LLMCompleteResponseReceivedEventHandler(AgentEventHandler):
|
|
|
63
62
|
f"Proceeding to treat LLM response as output for this leg."
|
|
64
63
|
)
|
|
65
64
|
else:
|
|
65
|
+
valid_processors = []
|
|
66
|
+
for p in processor_instances_to_try:
|
|
67
|
+
if isinstance(p, BaseLLMResponseProcessor):
|
|
68
|
+
valid_processors.append(p)
|
|
69
|
+
else:
|
|
70
|
+
logger.error(f"Agent '{agent_id}': Invalid LLM response processor type in config: {type(p)}. Skipping.")
|
|
71
|
+
|
|
66
72
|
# Sort processors by their order attribute
|
|
67
|
-
sorted_processors = sorted(
|
|
73
|
+
sorted_processors = sorted(valid_processors, key=lambda p: p.get_order())
|
|
68
74
|
processor_names = [p.get_name() for p in sorted_processors]
|
|
69
75
|
logger.debug(f"Agent '{agent_id}': Attempting LLM response processing in order: {processor_names}")
|
|
70
76
|
|
|
@@ -94,17 +100,6 @@ class LLMCompleteResponseReceivedEventHandler(AgentEventHandler):
|
|
|
94
100
|
else:
|
|
95
101
|
logger.debug(f"Agent '{agent_id}': LLMResponseProcessor '{processor_name_for_log}' did not handle the response.")
|
|
96
102
|
|
|
97
|
-
except ToolUsageParseException as e_parse:
|
|
98
|
-
# This is the key change: Catch the specific parsing exception
|
|
99
|
-
logger.warning(f"Agent '{agent_id}': LLMResponseProcessor '{processor_name_for_log}' failed to parse tool usage: {e_parse}")
|
|
100
|
-
if notifier:
|
|
101
|
-
notifier.notify_agent_error_output_generation(
|
|
102
|
-
error_source=f"LLMResponseProcessor.{processor_name_for_log}",
|
|
103
|
-
error_message="The model's response contained a malformed tool call that could not be understood.",
|
|
104
|
-
error_details=str(e_parse)
|
|
105
|
-
)
|
|
106
|
-
# A parsing failure should not prevent other processors from running.
|
|
107
|
-
|
|
108
103
|
except Exception as e: # pragma: no cover
|
|
109
104
|
logger.error(f"Agent '{agent_id}': Error while using LLMResponseProcessor '{processor_name_for_log}': {e}. This processor is skipped.", exc_info=True)
|
|
110
105
|
if notifier:
|
|
@@ -1,13 +1,21 @@
|
|
|
1
1
|
# file: autobyteus/autobyteus/agent/handlers/llm_user_message_ready_event_handler.py
|
|
2
2
|
import logging
|
|
3
3
|
import traceback
|
|
4
|
-
|
|
4
|
+
import uuid
|
|
5
|
+
from typing import TYPE_CHECKING, Optional, List
|
|
5
6
|
|
|
6
7
|
from autobyteus.agent.handlers.base_event_handler import AgentEventHandler
|
|
7
|
-
from autobyteus.agent.events import LLMUserMessageReadyEvent, LLMCompleteResponseReceivedEvent
|
|
8
|
+
from autobyteus.agent.events import LLMUserMessageReadyEvent, LLMCompleteResponseReceivedEvent, PendingToolInvocationEvent
|
|
8
9
|
from autobyteus.llm.user_message import LLMUserMessage
|
|
9
10
|
from autobyteus.llm.utils.response_types import ChunkResponse, CompleteResponse
|
|
10
11
|
from autobyteus.llm.utils.token_usage import TokenUsage
|
|
12
|
+
from autobyteus.agent.streaming.streaming_response_handler import StreamingResponseHandler
|
|
13
|
+
from autobyteus.agent.streaming.streaming_handler_factory import StreamingResponseHandlerFactory
|
|
14
|
+
from autobyteus.agent.streaming.parser.events import SegmentEvent, SegmentType
|
|
15
|
+
from autobyteus.agent.tool_invocation import ToolInvocationTurn
|
|
16
|
+
from autobyteus.agent.llm_request_assembler import LLMRequestAssembler
|
|
17
|
+
from autobyteus.agent.token_budget import apply_compaction_policy, resolve_token_budget
|
|
18
|
+
from autobyteus.llm.prompt_renderers.openai_chat_renderer import OpenAIChatRenderer
|
|
11
19
|
|
|
12
20
|
if TYPE_CHECKING:
|
|
13
21
|
from autobyteus.agent.context import AgentContext
|
|
@@ -18,9 +26,8 @@ logger = logging.getLogger(__name__)
|
|
|
18
26
|
class LLMUserMessageReadyEventHandler(AgentEventHandler):
|
|
19
27
|
"""
|
|
20
28
|
Handles LLMUserMessageReadyEvents by sending the prepared LLMUserMessage
|
|
21
|
-
to the LLM,
|
|
22
|
-
|
|
23
|
-
and then enqueuing an LLMCompleteResponseReceivedEvent with the full aggregated response.
|
|
29
|
+
to the LLM, passing the stream through StreamingResponseHandler for safe parsing,
|
|
30
|
+
emitting filtered chunks via the notifier, and finally enqueuing the complete response.
|
|
24
31
|
"""
|
|
25
32
|
|
|
26
33
|
def __init__(self):
|
|
@@ -37,8 +44,8 @@ class LLMUserMessageReadyEventHandler(AgentEventHandler):
|
|
|
37
44
|
if context.state.llm_instance is None:
|
|
38
45
|
error_msg = f"Agent '{agent_id}' received LLMUserMessageReadyEvent but LLM instance is not yet initialized."
|
|
39
46
|
logger.critical(error_msg)
|
|
40
|
-
if context.
|
|
41
|
-
context.
|
|
47
|
+
if context.status_manager and context.status_manager.notifier:
|
|
48
|
+
context.status_manager.notifier.notify_agent_error_output_generation(
|
|
42
49
|
error_source="LLMUserMessageReadyEventHandler.pre_llm_check",
|
|
43
50
|
error_message=error_msg
|
|
44
51
|
)
|
|
@@ -48,8 +55,13 @@ class LLMUserMessageReadyEventHandler(AgentEventHandler):
|
|
|
48
55
|
logger.info(f"Agent '{agent_id}' handling LLMUserMessageReadyEvent: '{llm_user_message.content}'")
|
|
49
56
|
logger.debug(f"Agent '{agent_id}' preparing to send full message to LLM:\n---\n{llm_user_message.content}\n---")
|
|
50
57
|
|
|
51
|
-
context.state
|
|
58
|
+
memory_manager = getattr(context.state, "memory_manager", None)
|
|
59
|
+
active_turn_id = getattr(context.state, "active_turn_id", None)
|
|
60
|
+
if memory_manager and not active_turn_id:
|
|
61
|
+
active_turn_id = memory_manager.start_turn()
|
|
62
|
+
context.state.active_turn_id = active_turn_id
|
|
52
63
|
|
|
64
|
+
# Initialize aggregators
|
|
53
65
|
complete_response_text = ""
|
|
54
66
|
complete_reasoning_text = ""
|
|
55
67
|
token_usage: Optional[TokenUsage] = None
|
|
@@ -57,66 +69,192 @@ class LLMUserMessageReadyEventHandler(AgentEventHandler):
|
|
|
57
69
|
complete_audio_urls: List[str] = []
|
|
58
70
|
complete_video_urls: List[str] = []
|
|
59
71
|
|
|
72
|
+
# Get notifier for emitting events
|
|
60
73
|
notifier: Optional['AgentExternalEventNotifier'] = None
|
|
61
|
-
if context.
|
|
62
|
-
notifier = context.
|
|
74
|
+
if context.status_manager:
|
|
75
|
+
notifier = context.status_manager.notifier
|
|
63
76
|
|
|
64
77
|
if not notifier: # pragma: no cover
|
|
65
78
|
logger.error(f"Agent '{agent_id}': Notifier not available in LLMUserMessageReadyEventHandler. Cannot emit chunk events.")
|
|
66
79
|
|
|
80
|
+
# Callback for segment events from streaming parser
|
|
81
|
+
def emit_segment_event(event: SegmentEvent):
|
|
82
|
+
if notifier:
|
|
83
|
+
try:
|
|
84
|
+
notifier.notify_agent_segment_event(event.to_dict())
|
|
85
|
+
except Exception as e:
|
|
86
|
+
logger.error(f"Agent '{agent_id}': Error notifying segment event: {e}", exc_info=True)
|
|
87
|
+
|
|
88
|
+
# Collect tool names from agent state/config
|
|
89
|
+
tool_names: List[str] = []
|
|
90
|
+
if context.state.tool_instances:
|
|
91
|
+
tool_names = list(context.state.tool_instances.keys())
|
|
92
|
+
elif context.config.tools:
|
|
93
|
+
for tool in context.config.tools:
|
|
94
|
+
if isinstance(tool, str):
|
|
95
|
+
tool_names.append(tool)
|
|
96
|
+
elif hasattr(tool, "get_name"):
|
|
97
|
+
try:
|
|
98
|
+
tool_names.append(tool.get_name())
|
|
99
|
+
except Exception: # pragma: no cover - defensive
|
|
100
|
+
logger.warning(
|
|
101
|
+
"Agent '%s': Failed to resolve tool name from %s.",
|
|
102
|
+
agent_id,
|
|
103
|
+
type(tool),
|
|
104
|
+
)
|
|
105
|
+
else: # pragma: no cover - defensive
|
|
106
|
+
logger.warning(
|
|
107
|
+
"Agent '%s': Unsupported tool entry in config: %s.",
|
|
108
|
+
agent_id,
|
|
109
|
+
type(tool),
|
|
110
|
+
)
|
|
111
|
+
|
|
112
|
+
# Get provider from LLM instance
|
|
113
|
+
provider = context.state.llm_instance.model.provider if context.state.llm_instance else None
|
|
114
|
+
|
|
115
|
+
# Create streaming handler via factory (all configuration encapsulated)
|
|
116
|
+
handler_result = StreamingResponseHandlerFactory.create(
|
|
117
|
+
tool_names=tool_names,
|
|
118
|
+
provider=provider,
|
|
119
|
+
on_segment_event=emit_segment_event,
|
|
120
|
+
agent_id=agent_id,
|
|
121
|
+
)
|
|
122
|
+
streaming_handler = handler_result.handler
|
|
123
|
+
|
|
124
|
+
logger.info(
|
|
125
|
+
"Agent '%s': Streaming handler selected: %s",
|
|
126
|
+
agent_id,
|
|
127
|
+
streaming_handler.__class__.__name__,
|
|
128
|
+
)
|
|
129
|
+
|
|
130
|
+
# Prepare arguments for stream_user_message
|
|
131
|
+
stream_kwargs = {}
|
|
132
|
+
if handler_result.tool_schemas:
|
|
133
|
+
stream_kwargs["tools"] = handler_result.tool_schemas
|
|
134
|
+
logger.info(
|
|
135
|
+
"Agent '%s': Passing %d tool schemas to LLM API (Provider: %s)",
|
|
136
|
+
agent_id,
|
|
137
|
+
len(handler_result.tool_schemas),
|
|
138
|
+
provider,
|
|
139
|
+
)
|
|
140
|
+
|
|
141
|
+
if not memory_manager:
|
|
142
|
+
raise RuntimeError(f"Agent '{agent_id}' requires a memory manager to assemble LLM requests.")
|
|
143
|
+
|
|
144
|
+
llm_config = getattr(context.state.llm_instance, "config", None)
|
|
145
|
+
llm_model = getattr(context.state.llm_instance, "model", None)
|
|
146
|
+
|
|
147
|
+
renderer = getattr(context.state.llm_instance, "_renderer", None) or OpenAIChatRenderer()
|
|
148
|
+
assembler = LLMRequestAssembler(
|
|
149
|
+
memory_manager=memory_manager,
|
|
150
|
+
renderer=renderer,
|
|
151
|
+
)
|
|
152
|
+
system_prompt = (
|
|
153
|
+
context.state.processed_system_prompt
|
|
154
|
+
or context.state.llm_instance.config.system_message
|
|
155
|
+
)
|
|
156
|
+
request = await assembler.prepare_request(
|
|
157
|
+
processed_user_input=llm_user_message,
|
|
158
|
+
current_turn_id=active_turn_id,
|
|
159
|
+
system_prompt=system_prompt,
|
|
160
|
+
)
|
|
161
|
+
|
|
162
|
+
# State for manual reasoning parts (since they might come from outside the parser)
|
|
163
|
+
segment_id_prefix = f"turn_{uuid.uuid4().hex}:"
|
|
164
|
+
current_reasoning_part_id = None
|
|
165
|
+
|
|
67
166
|
try:
|
|
68
|
-
async for chunk_response in context.state.llm_instance.
|
|
167
|
+
async for chunk_response in context.state.llm_instance.stream_messages(
|
|
168
|
+
request.messages,
|
|
169
|
+
rendered_payload=request.rendered_payload,
|
|
170
|
+
**stream_kwargs,
|
|
171
|
+
):
|
|
69
172
|
if not isinstance(chunk_response, ChunkResponse):
|
|
70
173
|
logger.warning(f"Agent '{agent_id}' received unexpected chunk type: {type(chunk_response)} during LLM stream. Expected ChunkResponse.")
|
|
71
174
|
continue
|
|
72
175
|
|
|
176
|
+
# Aggregate full raw content
|
|
73
177
|
if chunk_response.content:
|
|
74
178
|
complete_response_text += chunk_response.content
|
|
75
179
|
if chunk_response.reasoning:
|
|
76
180
|
complete_reasoning_text += chunk_response.reasoning
|
|
77
181
|
|
|
182
|
+
# Collect usage and media from final chunks
|
|
78
183
|
if chunk_response.is_complete:
|
|
79
184
|
if chunk_response.usage:
|
|
80
185
|
token_usage = chunk_response.usage
|
|
81
186
|
logger.debug(f"Agent '{agent_id}' received final chunk with token usage: {token_usage}")
|
|
82
187
|
if chunk_response.image_urls:
|
|
83
188
|
complete_image_urls.extend(chunk_response.image_urls)
|
|
84
|
-
logger.debug(f"Agent '{agent_id}' received final chunk with {len(chunk_response.image_urls)} image URLs.")
|
|
85
189
|
if chunk_response.audio_urls:
|
|
86
190
|
complete_audio_urls.extend(chunk_response.audio_urls)
|
|
87
|
-
logger.debug(f"Agent '{agent_id}' received final chunk with {len(chunk_response.audio_urls)} audio URLs.")
|
|
88
191
|
if chunk_response.video_urls:
|
|
89
192
|
complete_video_urls.extend(chunk_response.video_urls)
|
|
90
|
-
logger.debug(f"Agent '{agent_id}' received final chunk with {len(chunk_response.video_urls)} video URLs.")
|
|
91
193
|
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
194
|
+
# Handle Reasoning (Manual Segment Management)
|
|
195
|
+
if chunk_response.reasoning:
|
|
196
|
+
if current_reasoning_part_id is None:
|
|
197
|
+
current_reasoning_part_id = f"{segment_id_prefix}reasoning_{uuid.uuid4().hex}"
|
|
198
|
+
# Emit SEGMENT_START for reasoning
|
|
199
|
+
start_event = SegmentEvent.start(
|
|
200
|
+
segment_id=current_reasoning_part_id,
|
|
201
|
+
segment_type=SegmentType.REASONING
|
|
202
|
+
)
|
|
203
|
+
emit_segment_event(start_event)
|
|
204
|
+
|
|
205
|
+
# Emit SEGMENT_CONTENT for reasoning delta
|
|
206
|
+
content_event = SegmentEvent.content(
|
|
207
|
+
segment_id=current_reasoning_part_id,
|
|
208
|
+
delta=chunk_response.reasoning
|
|
209
|
+
)
|
|
210
|
+
emit_segment_event(content_event)
|
|
104
211
|
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
212
|
+
# Handle Content & Tool Calls (Through Handler)
|
|
213
|
+
# Pass the full ChunkResponse object to support both text and tool call streams
|
|
214
|
+
streaming_handler.feed(chunk_response)
|
|
215
|
+
|
|
216
|
+
# End of stream loop
|
|
109
217
|
|
|
218
|
+
# Finalize the stream parser to get any held-back content
|
|
219
|
+
streaming_handler.finalize()
|
|
220
|
+
|
|
221
|
+
# After finalization, enqueue any parsed tool invocations.
|
|
222
|
+
if tool_names:
|
|
223
|
+
tool_invocations = streaming_handler.get_all_invocations()
|
|
224
|
+
if tool_invocations:
|
|
225
|
+
context.state.active_multi_tool_call_turn = ToolInvocationTurn(
|
|
226
|
+
invocations=tool_invocations
|
|
227
|
+
)
|
|
228
|
+
logger.info(
|
|
229
|
+
"Agent '%s': Parsed %d tool invocations from streaming parser.",
|
|
230
|
+
agent_id,
|
|
231
|
+
len(tool_invocations),
|
|
232
|
+
)
|
|
233
|
+
for invocation in tool_invocations:
|
|
234
|
+
if active_turn_id and not invocation.turn_id:
|
|
235
|
+
invocation.turn_id = active_turn_id
|
|
236
|
+
if memory_manager:
|
|
237
|
+
memory_manager.ingest_tool_intent(invocation, turn_id=active_turn_id)
|
|
238
|
+
await context.input_event_queues.enqueue_tool_invocation_request(
|
|
239
|
+
PendingToolInvocationEvent(tool_invocation=invocation)
|
|
240
|
+
)
|
|
241
|
+
|
|
242
|
+
# Close any open reasoning segment
|
|
243
|
+
if current_reasoning_part_id:
|
|
244
|
+
end_event = SegmentEvent.end(segment_id=current_reasoning_part_id)
|
|
245
|
+
emit_segment_event(end_event)
|
|
246
|
+
|
|
247
|
+
logger.debug(f"Agent '{agent_id}' LLM stream completed. Full response length: {len(complete_response_text)}.")
|
|
248
|
+
if complete_reasoning_text:
|
|
249
|
+
logger.debug(f"Agent '{agent_id}' aggregated full LLM reasoning.")
|
|
250
|
+
|
|
110
251
|
except Exception as e:
|
|
111
252
|
logger.error(f"Agent '{agent_id}' error during LLM stream: {e}", exc_info=True)
|
|
112
253
|
error_message_for_output = f"Error processing your request with the LLM: {str(e)}"
|
|
113
254
|
|
|
114
255
|
logger.warning(f"Agent '{agent_id}' LLM stream error. Error message for output: {error_message_for_output}")
|
|
115
|
-
context.state.add_message_to_history({"role": "assistant", "content": error_message_for_output, "is_error": True})
|
|
116
|
-
|
|
117
256
|
if notifier:
|
|
118
257
|
try:
|
|
119
|
-
notifier.notify_agent_data_assistant_chunk_stream_end()
|
|
120
258
|
notifier.notify_agent_error_output_generation(
|
|
121
259
|
error_source="LLMUserMessageReadyEventHandler.stream_user_message",
|
|
122
260
|
error_message=error_message_for_output,
|
|
@@ -131,22 +269,10 @@ class LLMUserMessageReadyEventHandler(AgentEventHandler):
|
|
|
131
269
|
is_error=True
|
|
132
270
|
)
|
|
133
271
|
await context.input_event_queues.enqueue_internal_system_event(llm_complete_event_on_error)
|
|
134
|
-
logger.info(f"Agent '{agent_id}' enqueued LLMCompleteResponseReceivedEvent with error details
|
|
272
|
+
logger.info(f"Agent '{agent_id}' enqueued LLMCompleteResponseReceivedEvent with error details.")
|
|
135
273
|
return
|
|
136
274
|
|
|
137
|
-
#
|
|
138
|
-
history_entry = {"role": "assistant", "content": complete_response_text}
|
|
139
|
-
if complete_reasoning_text:
|
|
140
|
-
history_entry["reasoning"] = complete_reasoning_text
|
|
141
|
-
if complete_image_urls:
|
|
142
|
-
history_entry["image_urls"] = complete_image_urls
|
|
143
|
-
if complete_audio_urls:
|
|
144
|
-
history_entry["audio_urls"] = complete_audio_urls
|
|
145
|
-
if complete_video_urls:
|
|
146
|
-
history_entry["video_urls"] = complete_video_urls
|
|
147
|
-
context.state.add_message_to_history(history_entry)
|
|
148
|
-
|
|
149
|
-
# Create complete response with reasoning and multimodal data
|
|
275
|
+
# Create complete response
|
|
150
276
|
complete_response_obj = CompleteResponse(
|
|
151
277
|
content=complete_response_text,
|
|
152
278
|
reasoning=complete_reasoning_text,
|
|
@@ -155,9 +281,23 @@ class LLMUserMessageReadyEventHandler(AgentEventHandler):
|
|
|
155
281
|
audio_urls=complete_audio_urls,
|
|
156
282
|
video_urls=complete_video_urls
|
|
157
283
|
)
|
|
284
|
+
if memory_manager and active_turn_id:
|
|
285
|
+
memory_manager.ingest_assistant_response(
|
|
286
|
+
complete_response_obj,
|
|
287
|
+
turn_id=active_turn_id,
|
|
288
|
+
source_event="LLMCompleteResponseReceivedEvent",
|
|
289
|
+
)
|
|
290
|
+
if token_usage and llm_config and llm_model:
|
|
291
|
+
budget = resolve_token_budget(llm_model, llm_config, memory_manager.compaction_policy)
|
|
292
|
+
if budget:
|
|
293
|
+
apply_compaction_policy(memory_manager.compaction_policy, budget)
|
|
294
|
+
if memory_manager.compactor and memory_manager.compaction_policy.should_compact(
|
|
295
|
+
token_usage.prompt_tokens,
|
|
296
|
+
budget.input_budget,
|
|
297
|
+
):
|
|
298
|
+
memory_manager.request_compaction()
|
|
158
299
|
llm_complete_event = LLMCompleteResponseReceivedEvent(
|
|
159
300
|
complete_response=complete_response_obj
|
|
160
301
|
)
|
|
161
302
|
await context.input_event_queues.enqueue_internal_system_event(llm_complete_event)
|
|
162
303
|
logger.info(f"Agent '{agent_id}' enqueued LLMCompleteResponseReceivedEvent from LLMUserMessageReadyEventHandler.")
|
|
163
|
-
|
|
@@ -62,16 +62,6 @@ class ToolExecutionApprovalEventHandler(AgentEventHandler):
|
|
|
62
62
|
)
|
|
63
63
|
|
|
64
64
|
denial_reason_str = event.reason or "No specific reason provided."
|
|
65
|
-
denial_content_for_history = f"Tool execution denied by user/system. Reason: {denial_reason_str}"
|
|
66
|
-
|
|
67
|
-
context.state.add_message_to_history({
|
|
68
|
-
"role": "tool",
|
|
69
|
-
"tool_call_id": event.tool_invocation_id,
|
|
70
|
-
"name": retrieved_invocation.name,
|
|
71
|
-
"content": denial_content_for_history,
|
|
72
|
-
})
|
|
73
|
-
logger.debug(f"Agent '{context.agent_id}': Added 'tool' role denial message to history for '{retrieved_invocation.name}' (ID: {event.tool_invocation_id}).")
|
|
74
|
-
|
|
75
65
|
prompt_content_for_llm = (
|
|
76
66
|
f"The request to use the tool '{retrieved_invocation.name}' "
|
|
77
67
|
f"(with arguments: {json.dumps(retrieved_invocation.arguments or {})}) was denied. "
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
# file: autobyteus/autobyteus/agent/handlers/tool_invocation_request_event_handler.py
|
|
2
2
|
import logging
|
|
3
|
-
import json
|
|
4
3
|
import traceback
|
|
5
4
|
from typing import TYPE_CHECKING, Optional
|
|
6
5
|
|
|
7
6
|
from autobyteus.agent.handlers.base_event_handler import AgentEventHandler
|
|
8
7
|
from autobyteus.agent.events import PendingToolInvocationEvent, ToolResultEvent
|
|
9
8
|
from autobyteus.agent.tool_invocation import ToolInvocation
|
|
9
|
+
from autobyteus.utils.llm_output_formatter import format_to_clean_string
|
|
10
10
|
|
|
11
11
|
if TYPE_CHECKING:
|
|
12
12
|
from autobyteus.agent.context import AgentContext
|
|
@@ -46,10 +46,35 @@ class ToolInvocationRequestEventHandler(AgentEventHandler):
|
|
|
46
46
|
except Exception as e_notify:
|
|
47
47
|
logger.error(f"Agent '{agent_id}': Error notifying tool auto-execution: {e_notify}", exc_info=True)
|
|
48
48
|
|
|
49
|
+
# Run tool invocation preprocessors (if any) before execution
|
|
50
|
+
processors = context.config.tool_invocation_preprocessors
|
|
51
|
+
if processors:
|
|
52
|
+
# Filter valid processors first to avoid sorting crashes (checking for get_order attribute)
|
|
53
|
+
valid_processors = [p for p in processors if hasattr(p, 'get_order')]
|
|
54
|
+
sorted_processors = sorted(valid_processors, key=lambda p: p.get_order())
|
|
55
|
+
for processor in sorted_processors:
|
|
56
|
+
try:
|
|
57
|
+
tool_invocation = await processor.process(tool_invocation, context)
|
|
58
|
+
tool_name = tool_invocation.name
|
|
59
|
+
arguments = tool_invocation.arguments
|
|
60
|
+
invocation_id = tool_invocation.id
|
|
61
|
+
except Exception as e:
|
|
62
|
+
error_message = f"Error in tool invocation preprocessor '{processor.get_name()}' for tool '{tool_name}': {e}"
|
|
63
|
+
logger.error(f"Agent '{agent_id}': {error_message}", exc_info=True)
|
|
64
|
+
result_event = ToolResultEvent(
|
|
65
|
+
tool_name=tool_name,
|
|
66
|
+
result=None,
|
|
67
|
+
error=error_message,
|
|
68
|
+
tool_invocation_id=invocation_id,
|
|
69
|
+
turn_id=tool_invocation.turn_id,
|
|
70
|
+
)
|
|
71
|
+
await context.input_event_queues.enqueue_tool_result(result_event)
|
|
72
|
+
return
|
|
73
|
+
|
|
49
74
|
logger.info(f"Agent '{agent_id}' executing tool directly: '{tool_name}' (ID: {invocation_id}) with args: {arguments}")
|
|
50
75
|
|
|
51
76
|
try:
|
|
52
|
-
args_str =
|
|
77
|
+
args_str = format_to_clean_string(arguments)
|
|
53
78
|
except TypeError:
|
|
54
79
|
args_str = str(arguments)
|
|
55
80
|
|
|
@@ -71,13 +96,13 @@ class ToolInvocationRequestEventHandler(AgentEventHandler):
|
|
|
71
96
|
if not tool_instance:
|
|
72
97
|
error_message = f"Tool '{tool_name}' not found or configured for agent '{agent_id}'."
|
|
73
98
|
logger.error(error_message)
|
|
74
|
-
result_event = ToolResultEvent(
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
99
|
+
result_event = ToolResultEvent(
|
|
100
|
+
tool_name=tool_name,
|
|
101
|
+
result=None,
|
|
102
|
+
error=error_message,
|
|
103
|
+
tool_invocation_id=invocation_id,
|
|
104
|
+
turn_id=tool_invocation.turn_id,
|
|
105
|
+
)
|
|
81
106
|
log_msg_error = f"[TOOL_ERROR_DIRECT] {error_message}"
|
|
82
107
|
if notifier:
|
|
83
108
|
try:
|
|
@@ -97,20 +122,19 @@ class ToolInvocationRequestEventHandler(AgentEventHandler):
|
|
|
97
122
|
execution_result = await tool_instance.execute(context=context, **arguments)
|
|
98
123
|
|
|
99
124
|
try:
|
|
100
|
-
result_json_for_log =
|
|
125
|
+
result_json_for_log = format_to_clean_string(execution_result)
|
|
101
126
|
except (TypeError, ValueError):
|
|
102
|
-
result_json_for_log =
|
|
127
|
+
result_json_for_log = format_to_clean_string(str(execution_result))
|
|
103
128
|
|
|
104
129
|
logger.info(f"Tool '{tool_name}' (ID: {invocation_id}) executed by agent '{agent_id}'.")
|
|
105
|
-
result_event = ToolResultEvent(
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
})
|
|
130
|
+
result_event = ToolResultEvent(
|
|
131
|
+
tool_name=tool_name,
|
|
132
|
+
result=execution_result,
|
|
133
|
+
error=None,
|
|
134
|
+
tool_invocation_id=invocation_id,
|
|
135
|
+
tool_args=arguments,
|
|
136
|
+
turn_id=tool_invocation.turn_id,
|
|
137
|
+
)
|
|
114
138
|
log_msg_result = f"[TOOL_RESULT_DIRECT] {result_json_for_log}"
|
|
115
139
|
if notifier:
|
|
116
140
|
try:
|
|
@@ -124,13 +148,13 @@ class ToolInvocationRequestEventHandler(AgentEventHandler):
|
|
|
124
148
|
error_message = f"Error executing tool '{tool_name}' (ID: {invocation_id}): {str(e)}"
|
|
125
149
|
error_details = traceback.format_exc()
|
|
126
150
|
logger.error(f"Agent '{agent_id}' {error_message}", exc_info=True)
|
|
127
|
-
result_event = ToolResultEvent(
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
151
|
+
result_event = ToolResultEvent(
|
|
152
|
+
tool_name=tool_name,
|
|
153
|
+
result=None,
|
|
154
|
+
error=error_message,
|
|
155
|
+
tool_invocation_id=invocation_id,
|
|
156
|
+
turn_id=tool_invocation.turn_id,
|
|
157
|
+
)
|
|
134
158
|
log_msg_exception = f"[TOOL_EXCEPTION_DIRECT] {error_message}\nDetails:\n{error_details}"
|
|
135
159
|
if notifier:
|
|
136
160
|
try:
|
|
@@ -161,8 +185,8 @@ class ToolInvocationRequestEventHandler(AgentEventHandler):
|
|
|
161
185
|
agent_id = context.agent_id
|
|
162
186
|
|
|
163
187
|
notifier: Optional['AgentExternalEventNotifier'] = None
|
|
164
|
-
if context.
|
|
165
|
-
notifier = context.
|
|
188
|
+
if context.status_manager:
|
|
189
|
+
notifier = context.status_manager.notifier
|
|
166
190
|
|
|
167
191
|
if not notifier:
|
|
168
192
|
logger.error(f"Agent '{agent_id}': Notifier not available in ToolInvocationRequestEventHandler. Output events for tool approval/logging will be lost.")
|
|
@@ -175,25 +199,6 @@ class ToolInvocationRequestEventHandler(AgentEventHandler):
|
|
|
175
199
|
|
|
176
200
|
context.store_pending_tool_invocation(tool_invocation)
|
|
177
201
|
|
|
178
|
-
try:
|
|
179
|
-
arguments_json_str = json.dumps(tool_invocation.arguments or {})
|
|
180
|
-
except TypeError:
|
|
181
|
-
logger.warning(f"Could not serialize args for history tool_call for '{tool_invocation.name}'. Using empty dict string.")
|
|
182
|
-
arguments_json_str = "{}"
|
|
183
|
-
|
|
184
|
-
context.add_message_to_history({
|
|
185
|
-
"role": "assistant",
|
|
186
|
-
"content": None,
|
|
187
|
-
"tool_calls": [{
|
|
188
|
-
"id": tool_invocation.id,
|
|
189
|
-
"type": "function",
|
|
190
|
-
"function": {
|
|
191
|
-
"name": tool_invocation.name,
|
|
192
|
-
"arguments": arguments_json_str
|
|
193
|
-
}
|
|
194
|
-
}]
|
|
195
|
-
})
|
|
196
|
-
|
|
197
202
|
approval_data = {
|
|
198
203
|
"invocation_id": tool_invocation.id,
|
|
199
204
|
"tool_name": tool_invocation.name,
|