autobyteus 1.2.0__py3-none-any.whl → 1.2.3__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- autobyteus/agent/agent.py +15 -5
- autobyteus/agent/bootstrap_steps/__init__.py +1 -3
- autobyteus/agent/bootstrap_steps/agent_bootstrapper.py +3 -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/workspace_context_initialization_step.py +2 -4
- autobyteus/agent/context/agent_config.py +43 -20
- autobyteus/agent/context/agent_context.py +23 -18
- autobyteus/agent/context/agent_runtime_state.py +23 -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 +74 -60
- autobyteus/agent/events/worker_event_dispatcher.py +21 -64
- autobyteus/agent/factory/agent_factory.py +52 -0
- 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 +40 -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/message/send_message_to.py +5 -4
- 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 -178
- 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 +81 -0
- autobyteus/agent/streaming/stream_event_payloads.py +2 -198
- autobyteus/agent/streaming/stream_events.py +3 -128
- 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 +5 -6
- autobyteus/agent_team/bootstrap_steps/team_context_initialization_step.py +15 -15
- 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 +11 -8
- 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 +10 -10
- autobyteus/agent_team/streaming/agent_team_stream_event_payloads.py +7 -7
- autobyteus/agent_team/streaming/agent_team_stream_events.py +11 -11
- 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/activation_policy.py +1 -1
- autobyteus/agent_team/task_notification/system_event_driven_agent_task_notifier.py +22 -22
- autobyteus/agent_team/task_notification/task_notification_mode.py +20 -1
- autobyteus/agent_team/utils/wait_for_idle.py +4 -4
- autobyteus/cli/agent_cli.py +18 -10
- autobyteus/cli/agent_team_tui/app.py +18 -15
- autobyteus/cli/agent_team_tui/state.py +21 -23
- autobyteus/cli/agent_team_tui/widgets/agent_list_sidebar.py +15 -15
- autobyteus/cli/agent_team_tui/widgets/focus_pane.py +146 -39
- autobyteus/cli/agent_team_tui/widgets/renderables.py +1 -1
- autobyteus/cli/agent_team_tui/widgets/shared.py +26 -26
- autobyteus/cli/agent_team_tui/widgets/{task_board_panel.py → task_plan_panel.py} +5 -5
- 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 +15 -21
- 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 +32 -0
- autobyteus/memory/active_transcript.py +69 -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 +183 -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/policies/__init__.py +5 -0
- autobyteus/memory/policies/compaction_policy.py +16 -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 +7 -0
- autobyteus/memory/store/base_store.py +14 -0
- autobyteus/memory/store/file_store.py +98 -0
- autobyteus/memory/tool_interaction_builder.py +46 -0
- autobyteus/memory/turn_tracker.py +9 -0
- autobyteus/multimedia/audio/api/__init__.py +3 -2
- autobyteus/multimedia/audio/api/autobyteus_audio_client.py +19 -5
- autobyteus/multimedia/audio/api/gemini_audio_client.py +108 -16
- autobyteus/multimedia/audio/api/openai_audio_client.py +112 -0
- autobyteus/multimedia/audio/audio_client_factory.py +84 -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 +38 -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/__init__.py +43 -20
- autobyteus/task_management/{base_task_board.py → base_task_plan.py} +16 -13
- autobyteus/task_management/converters/__init__.py +2 -2
- autobyteus/task_management/converters/{task_board_converter.py → task_plan_converter.py} +13 -13
- autobyteus/task_management/events.py +7 -7
- autobyteus/task_management/{in_memory_task_board.py → in_memory_task_plan.py} +34 -22
- autobyteus/task_management/schemas/__init__.py +3 -0
- autobyteus/task_management/schemas/task_status_report.py +2 -2
- autobyteus/task_management/schemas/todo_definition.py +15 -0
- autobyteus/task_management/todo.py +29 -0
- autobyteus/task_management/todo_list.py +75 -0
- autobyteus/task_management/tools/__init__.py +24 -8
- autobyteus/task_management/tools/task_tools/__init__.py +19 -0
- autobyteus/task_management/tools/{assign_task_to.py → task_tools/assign_task_to.py} +18 -18
- autobyteus/task_management/tools/{publish_task.py → task_tools/create_task.py} +16 -18
- autobyteus/task_management/tools/{publish_tasks.py → task_tools/create_tasks.py} +19 -19
- autobyteus/task_management/tools/{get_my_tasks.py → task_tools/get_my_tasks.py} +15 -15
- autobyteus/task_management/tools/{get_task_board_status.py → task_tools/get_task_plan_status.py} +16 -16
- autobyteus/task_management/tools/{update_task_status.py → task_tools/update_task_status.py} +16 -16
- autobyteus/task_management/tools/todo_tools/__init__.py +18 -0
- autobyteus/task_management/tools/todo_tools/add_todo.py +78 -0
- autobyteus/task_management/tools/todo_tools/create_todo_list.py +79 -0
- autobyteus/task_management/tools/todo_tools/get_todo_list.py +55 -0
- autobyteus/task_management/tools/todo_tools/update_todo_status.py +85 -0
- autobyteus/tools/__init__.py +43 -52
- autobyteus/tools/base_tool.py +7 -0
- autobyteus/tools/file/__init__.py +9 -0
- autobyteus/tools/file/patch_file.py +149 -0
- autobyteus/tools/file/{file_reader.py → read_file.py} +38 -7
- autobyteus/tools/file/{file_writer.py → write_file.py} +7 -4
- autobyteus/tools/functional_tool.py +53 -14
- 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/tool.py +3 -3
- autobyteus/tools/mcp/tool_registrar.py +5 -2
- autobyteus/tools/mcp/types.py +61 -0
- autobyteus/tools/multimedia/__init__.py +2 -1
- autobyteus/tools/multimedia/audio_tools.py +72 -19
- autobyteus/tools/{download_media_tool.py → multimedia/download_media_tool.py} +21 -7
- autobyteus/tools/multimedia/image_tools.py +248 -64
- autobyteus/tools/multimedia/media_reader_tool.py +1 -1
- 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 +108 -14
- autobyteus/tools/registry/tool_registry.py +29 -0
- autobyteus/tools/search/__init__.py +17 -0
- autobyteus/tools/search/base_strategy.py +35 -0
- autobyteus/tools/search/client.py +24 -0
- autobyteus/tools/search/factory.py +81 -0
- autobyteus/tools/search/google_cse_strategy.py +68 -0
- autobyteus/tools/search/providers.py +10 -0
- autobyteus/tools/search/serpapi_strategy.py +65 -0
- autobyteus/tools/search/serper_strategy.py +87 -0
- autobyteus/tools/search_tool.py +83 -0
- 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/tool_meta.py +4 -24
- 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 +56 -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 +4 -11
- 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.2.3.dist-info/METADATA +293 -0
- autobyteus-1.2.3.dist-info/RECORD +600 -0
- {autobyteus-1.2.0.dist-info → autobyteus-1.2.3.dist-info}/WHEEL +1 -1
- {autobyteus-1.2.0.dist-info → autobyteus-1.2.3.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/person/examples/sample_persons.py +0 -14
- autobyteus/person/examples/sample_roles.py +0 -14
- autobyteus/person/person.py +0 -29
- autobyteus/person/role.py +0 -14
- 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/__init__.py +0 -0
- 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/__init__.py +0 -0
- 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 -80
- autobyteus/tools/browser/standalone/web_page_pdf_generator.py +0 -97
- autobyteus/tools/browser/standalone/webpage_image_downloader.py +0 -165
- autobyteus/tools/browser/standalone/webpage_reader.py +0 -101
- autobyteus/tools/browser/standalone/webpage_screenshot_taker.py +0 -101
- autobyteus/tools/file/file_editor.py +0 -200
- autobyteus/tools/google_search.py +0 -149
- autobyteus/tools/timer.py +0 -171
- 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.0.dist-info/METADATA +0 -205
- autobyteus-1.2.0.dist-info/RECORD +0 -496
- examples/__init__.py +0 -1
- examples/agent_team/__init__.py +0 -1
- examples/discover_phase_transitions.py +0 -104
- 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/{person → skills}/__init__.py +0 -0
- /autobyteus/{person/examples → tools/skill}/__init__.py +0 -0
- {autobyteus-1.2.0.dist-info → autobyteus-1.2.3.dist-info}/licenses/LICENSE +0 -0
|
@@ -4,8 +4,9 @@ from autobyteus.llm.models import LLMModel
|
|
|
4
4
|
from autobyteus.llm.utils.llm_config import LLMConfig
|
|
5
5
|
from autobyteus.llm.utils.token_usage import TokenUsage
|
|
6
6
|
from autobyteus.llm.utils.response_types import CompleteResponse, ChunkResponse
|
|
7
|
-
from autobyteus.llm.
|
|
7
|
+
from autobyteus.llm.utils.messages import Message
|
|
8
8
|
from autobyteus.clients import AutobyteusClient
|
|
9
|
+
from autobyteus.llm.prompt_renderers.autobyteus_prompt_renderer import AutobyteusPromptRenderer
|
|
9
10
|
import logging
|
|
10
11
|
import uuid
|
|
11
12
|
|
|
@@ -20,26 +21,34 @@ class AutobyteusLLM(BaseLLM):
|
|
|
20
21
|
|
|
21
22
|
self.client = AutobyteusClient(server_url=self.model.host_url)
|
|
22
23
|
self.conversation_id = str(uuid.uuid4())
|
|
24
|
+
self._renderer = AutobyteusPromptRenderer()
|
|
23
25
|
logger.info(f"AutobyteusLLM initialized for model '{self.model.model_identifier}' with conversation ID: {self.conversation_id}")
|
|
24
26
|
|
|
25
|
-
async def
|
|
27
|
+
async def _send_messages_to_llm(
|
|
26
28
|
self,
|
|
27
|
-
|
|
29
|
+
messages: List[Message],
|
|
28
30
|
**kwargs
|
|
29
31
|
) -> CompleteResponse:
|
|
30
|
-
self.
|
|
32
|
+
rendered = await self._renderer.render(messages)
|
|
33
|
+
if not rendered:
|
|
34
|
+
raise ValueError("AutobyteusLLM requires at least one user message.")
|
|
35
|
+
payload = rendered[0]
|
|
31
36
|
try:
|
|
32
37
|
response = await self.client.send_message(
|
|
33
38
|
conversation_id=self.conversation_id,
|
|
34
39
|
model_name=self.model.name,
|
|
35
|
-
user_message=
|
|
36
|
-
image_urls=
|
|
37
|
-
audio_urls=
|
|
38
|
-
video_urls=
|
|
40
|
+
user_message=payload.get("content", ""),
|
|
41
|
+
image_urls=payload.get("image_urls", []),
|
|
42
|
+
audio_urls=payload.get("audio_urls", []),
|
|
43
|
+
video_urls=payload.get("video_urls", []),
|
|
39
44
|
)
|
|
40
45
|
|
|
41
|
-
assistant_message =
|
|
42
|
-
|
|
46
|
+
assistant_message = (
|
|
47
|
+
response.get("response")
|
|
48
|
+
or response.get("content")
|
|
49
|
+
or response.get("message")
|
|
50
|
+
or ""
|
|
51
|
+
)
|
|
43
52
|
|
|
44
53
|
token_usage_data = response.get('token_usage') or {}
|
|
45
54
|
token_usage = TokenUsage(
|
|
@@ -54,25 +63,27 @@ class AutobyteusLLM(BaseLLM):
|
|
|
54
63
|
)
|
|
55
64
|
except Exception as e:
|
|
56
65
|
logger.error(f"Error processing message: {str(e)}")
|
|
57
|
-
await self._handle_error_cleanup()
|
|
58
66
|
raise
|
|
59
67
|
|
|
60
|
-
async def
|
|
68
|
+
async def _stream_messages_to_llm(
|
|
61
69
|
self,
|
|
62
|
-
|
|
70
|
+
messages: List[Message],
|
|
63
71
|
**kwargs
|
|
64
72
|
) -> AsyncGenerator[ChunkResponse, None]:
|
|
65
|
-
self.
|
|
73
|
+
rendered = await self._renderer.render(messages)
|
|
74
|
+
if not rendered:
|
|
75
|
+
raise ValueError("AutobyteusLLM requires at least one user message.")
|
|
76
|
+
payload = rendered[0]
|
|
66
77
|
complete_response = ""
|
|
67
78
|
|
|
68
79
|
try:
|
|
69
80
|
async for chunk in self.client.stream_message(
|
|
70
81
|
conversation_id=self.conversation_id,
|
|
71
82
|
model_name=self.model.name,
|
|
72
|
-
user_message=
|
|
73
|
-
image_urls=
|
|
74
|
-
audio_urls=
|
|
75
|
-
video_urls=
|
|
83
|
+
user_message=payload.get("content", ""),
|
|
84
|
+
image_urls=payload.get("image_urls", []),
|
|
85
|
+
audio_urls=payload.get("audio_urls", []),
|
|
86
|
+
video_urls=payload.get("video_urls", []),
|
|
76
87
|
):
|
|
77
88
|
if 'error' in chunk:
|
|
78
89
|
raise RuntimeError(chunk['error'])
|
|
@@ -100,24 +111,17 @@ class AutobyteusLLM(BaseLLM):
|
|
|
100
111
|
video_urls=chunk.get('video_urls', []),
|
|
101
112
|
usage=token_usage
|
|
102
113
|
)
|
|
103
|
-
|
|
104
|
-
self.add_assistant_message(complete_response)
|
|
105
114
|
except Exception as e:
|
|
106
115
|
logger.error(f"Error streaming message: {str(e)}")
|
|
107
|
-
await self._handle_error_cleanup()
|
|
108
116
|
raise
|
|
109
117
|
|
|
110
118
|
async def cleanup(self):
|
|
119
|
+
"""
|
|
120
|
+
Clean up the remote conversation. The owning agent controls the HTTP
|
|
121
|
+
client lifecycle.
|
|
122
|
+
"""
|
|
111
123
|
try:
|
|
112
124
|
await self.client.cleanup(self.conversation_id)
|
|
113
125
|
await super().cleanup()
|
|
114
126
|
except Exception as e:
|
|
115
127
|
logger.error(f"Error during cleanup: {str(e)}")
|
|
116
|
-
finally:
|
|
117
|
-
await self.client.close()
|
|
118
|
-
|
|
119
|
-
async def _handle_error_cleanup(self):
|
|
120
|
-
try:
|
|
121
|
-
await self.cleanup()
|
|
122
|
-
except Exception as cleanup_error:
|
|
123
|
-
logger.error(f"Error during error cleanup: {str(cleanup_error)}")
|
autobyteus/llm/api/claude_llm.py
CHANGED
|
@@ -1,27 +1,84 @@
|
|
|
1
|
-
from typing import Dict, Optional, List, AsyncGenerator, Tuple
|
|
2
1
|
import anthropic
|
|
3
2
|
import os
|
|
4
3
|
import logging
|
|
4
|
+
from typing import Dict, Optional, List, AsyncGenerator, Tuple
|
|
5
|
+
|
|
5
6
|
from autobyteus.llm.models import LLMModel
|
|
6
7
|
from autobyteus.llm.base_llm import BaseLLM
|
|
7
8
|
from autobyteus.llm.utils.llm_config import LLMConfig
|
|
8
9
|
from autobyteus.llm.utils.messages import MessageRole, Message
|
|
9
10
|
from autobyteus.llm.utils.token_usage import TokenUsage
|
|
10
11
|
from autobyteus.llm.utils.response_types import CompleteResponse, ChunkResponse
|
|
11
|
-
from autobyteus.llm.
|
|
12
|
+
from autobyteus.llm.converters import convert_anthropic_tool_call
|
|
13
|
+
from autobyteus.llm.prompt_renderers.anthropic_prompt_renderer import AnthropicPromptRenderer
|
|
12
14
|
|
|
13
15
|
logger = logging.getLogger(__name__)
|
|
14
16
|
|
|
17
|
+
def _build_thinking_param(extra_params: Dict) -> Optional[Dict]:
|
|
18
|
+
enabled = extra_params.get("thinking_enabled", False)
|
|
19
|
+
if not isinstance(enabled, bool) or not enabled:
|
|
20
|
+
return None
|
|
21
|
+
|
|
22
|
+
budget = extra_params.get("thinking_budget_tokens", 1024)
|
|
23
|
+
try:
|
|
24
|
+
budget_int = int(budget)
|
|
25
|
+
except (TypeError, ValueError):
|
|
26
|
+
budget_int = 1024
|
|
27
|
+
|
|
28
|
+
return {"type": "enabled", "budget_tokens": budget_int}
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
def _split_claude_content_blocks(blocks: List) -> Tuple[str, str]:
|
|
32
|
+
"""Split Claude content blocks into visible text and thinking summaries."""
|
|
33
|
+
content_segments: List[str] = []
|
|
34
|
+
thinking_segments: List[str] = []
|
|
35
|
+
|
|
36
|
+
for block in blocks or []:
|
|
37
|
+
block_type = getattr(block, "type", None)
|
|
38
|
+
if block_type is None and isinstance(block, dict):
|
|
39
|
+
block_type = block.get("type")
|
|
40
|
+
|
|
41
|
+
if block_type == "text":
|
|
42
|
+
text = getattr(block, "text", None)
|
|
43
|
+
if text is None and isinstance(block, dict):
|
|
44
|
+
text = block.get("text")
|
|
45
|
+
if text:
|
|
46
|
+
content_segments.append(text)
|
|
47
|
+
elif block_type == "thinking":
|
|
48
|
+
thinking = getattr(block, "thinking", None)
|
|
49
|
+
if thinking is None and isinstance(block, dict):
|
|
50
|
+
thinking = block.get("thinking")
|
|
51
|
+
if thinking:
|
|
52
|
+
thinking_segments.append(thinking)
|
|
53
|
+
elif block_type == "redacted_thinking":
|
|
54
|
+
redacted = getattr(block, "redacted_thinking", None)
|
|
55
|
+
if redacted is None and isinstance(block, dict):
|
|
56
|
+
redacted = block.get("redacted_thinking")
|
|
57
|
+
if redacted:
|
|
58
|
+
thinking_segments.append(redacted)
|
|
59
|
+
|
|
60
|
+
return "".join(content_segments), "".join(thinking_segments)
|
|
61
|
+
|
|
62
|
+
|
|
63
|
+
def _split_system_message(messages: List[Message]) -> Tuple[Optional[str], List[Message]]:
|
|
64
|
+
system_parts = [msg.content for msg in messages if msg.role == MessageRole.SYSTEM and msg.content]
|
|
65
|
+
system_prompt = "\n".join(system_parts) if system_parts else None
|
|
66
|
+
remaining = [msg for msg in messages if msg.role != MessageRole.SYSTEM]
|
|
67
|
+
return system_prompt, remaining
|
|
68
|
+
|
|
69
|
+
|
|
15
70
|
class ClaudeLLM(BaseLLM):
|
|
16
71
|
def __init__(self, model: LLMModel = None, llm_config: LLMConfig = None):
|
|
17
72
|
if model is None:
|
|
18
|
-
model = LLMModel['claude-4-sonnet']
|
|
73
|
+
model = LLMModel['claude-4.5-sonnet']
|
|
19
74
|
if llm_config is None:
|
|
20
75
|
llm_config = LLMConfig()
|
|
21
76
|
|
|
22
77
|
super().__init__(model=model, llm_config=llm_config)
|
|
23
78
|
self.client = self.initialize()
|
|
24
|
-
self.
|
|
79
|
+
self._renderer = AnthropicPromptRenderer()
|
|
80
|
+
# Claude Sonnet 4.5 currently allows up to ~8k output tokens; let config override.
|
|
81
|
+
self.max_tokens = llm_config.max_tokens if llm_config.max_tokens is not None else 8192
|
|
25
82
|
|
|
26
83
|
@classmethod
|
|
27
84
|
def initialize(cls):
|
|
@@ -36,10 +93,6 @@ class ClaudeLLM(BaseLLM):
|
|
|
36
93
|
except Exception as e:
|
|
37
94
|
raise ValueError(f"Failed to initialize Anthropic client: {str(e)}")
|
|
38
95
|
|
|
39
|
-
def _get_non_system_messages(self) -> List[Dict]:
|
|
40
|
-
# NOTE: This will need to be updated to handle multimodal messages for Claude
|
|
41
|
-
return [msg.to_dict() for msg in self.messages if msg.role != MessageRole.SYSTEM]
|
|
42
|
-
|
|
43
96
|
def _create_token_usage(self, input_tokens: int, output_tokens: int) -> TokenUsage:
|
|
44
97
|
return TokenUsage(
|
|
45
98
|
prompt_tokens=input_tokens,
|
|
@@ -47,23 +100,37 @@ class ClaudeLLM(BaseLLM):
|
|
|
47
100
|
total_tokens=input_tokens + output_tokens
|
|
48
101
|
)
|
|
49
102
|
|
|
50
|
-
async def
|
|
51
|
-
|
|
103
|
+
async def _send_messages_to_llm(self, messages: List[Message], **kwargs) -> CompleteResponse:
|
|
104
|
+
try:
|
|
105
|
+
system_prompt, non_system = _split_system_message(messages)
|
|
106
|
+
formatted_messages = await self._renderer.render(non_system)
|
|
107
|
+
thinking_param = _build_thinking_param(self.config.extra_params)
|
|
52
108
|
|
|
53
|
-
|
|
54
|
-
|
|
109
|
+
request_kwargs = {
|
|
110
|
+
"model": self.model.value,
|
|
111
|
+
"max_tokens": self.max_tokens,
|
|
112
|
+
"messages": formatted_messages,
|
|
113
|
+
}
|
|
114
|
+
if system_prompt:
|
|
115
|
+
request_kwargs["system"] = system_prompt
|
|
116
|
+
if thinking_param:
|
|
117
|
+
# Extended thinking is not compatible with temperature modifications
|
|
118
|
+
request_kwargs["thinking"] = thinking_param
|
|
119
|
+
else:
|
|
120
|
+
request_kwargs["temperature"] = 0
|
|
55
121
|
|
|
56
|
-
try:
|
|
57
122
|
response = self.client.messages.create(
|
|
58
|
-
|
|
59
|
-
max_tokens=self.max_tokens,
|
|
60
|
-
temperature=0,
|
|
61
|
-
system=self.system_message,
|
|
62
|
-
messages=self._get_non_system_messages()
|
|
123
|
+
**request_kwargs
|
|
63
124
|
)
|
|
64
125
|
|
|
65
|
-
assistant_message = response
|
|
66
|
-
|
|
126
|
+
assistant_message = getattr(response, "text", "") or ""
|
|
127
|
+
reasoning_summary = None
|
|
128
|
+
if response.content:
|
|
129
|
+
parsed_text, parsed_thinking = _split_claude_content_blocks(response.content)
|
|
130
|
+
if parsed_text:
|
|
131
|
+
assistant_message = parsed_text
|
|
132
|
+
if parsed_thinking:
|
|
133
|
+
reasoning_summary = parsed_thinking
|
|
67
134
|
|
|
68
135
|
token_usage = self._create_token_usage(
|
|
69
136
|
response.usage.input_tokens,
|
|
@@ -74,35 +141,72 @@ class ClaudeLLM(BaseLLM):
|
|
|
74
141
|
|
|
75
142
|
return CompleteResponse(
|
|
76
143
|
content=assistant_message,
|
|
144
|
+
reasoning=reasoning_summary,
|
|
77
145
|
usage=token_usage
|
|
78
146
|
)
|
|
79
147
|
except anthropic.APIError as e:
|
|
80
148
|
logger.error(f"Error in Claude API call: {str(e)}")
|
|
81
149
|
raise ValueError(f"Error in Claude API call: {str(e)}")
|
|
82
150
|
|
|
83
|
-
async def
|
|
84
|
-
self,
|
|
151
|
+
async def _stream_messages_to_llm(
|
|
152
|
+
self, messages: List[Message], **kwargs
|
|
85
153
|
) -> AsyncGenerator[ChunkResponse, None]:
|
|
86
|
-
self.add_user_message(user_message)
|
|
87
154
|
complete_response = ""
|
|
155
|
+
complete_reasoning = ""
|
|
88
156
|
final_message = None
|
|
89
157
|
|
|
90
|
-
#
|
|
91
|
-
|
|
158
|
+
# Extract tools if provided
|
|
159
|
+
tools = kwargs.get("tools")
|
|
92
160
|
|
|
93
161
|
try:
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
162
|
+
# Prepare arguments for stream
|
|
163
|
+
system_prompt, non_system = _split_system_message(messages)
|
|
164
|
+
formatted_messages = await self._renderer.render(non_system)
|
|
165
|
+
thinking_param = _build_thinking_param(self.config.extra_params)
|
|
166
|
+
stream_kwargs = {
|
|
167
|
+
"model": self.model.value,
|
|
168
|
+
"max_tokens": self.max_tokens,
|
|
169
|
+
"messages": formatted_messages,
|
|
170
|
+
}
|
|
171
|
+
if system_prompt:
|
|
172
|
+
stream_kwargs["system"] = system_prompt
|
|
173
|
+
if thinking_param:
|
|
174
|
+
# Extended thinking is not compatible with temperature modifications
|
|
175
|
+
stream_kwargs["thinking"] = thinking_param
|
|
176
|
+
else:
|
|
177
|
+
stream_kwargs["temperature"] = 0
|
|
178
|
+
|
|
179
|
+
if tools:
|
|
180
|
+
stream_kwargs["tools"] = tools
|
|
181
|
+
|
|
182
|
+
with self.client.messages.stream(**stream_kwargs) as stream:
|
|
101
183
|
for event in stream:
|
|
102
|
-
|
|
103
|
-
|
|
184
|
+
|
|
185
|
+
# Handle text content
|
|
186
|
+
if event.type == "content_block_delta":
|
|
187
|
+
delta_type = getattr(event.delta, "type", None)
|
|
188
|
+
if delta_type == "text_delta":
|
|
189
|
+
complete_response += event.delta.text
|
|
190
|
+
yield ChunkResponse(
|
|
191
|
+
content=event.delta.text,
|
|
192
|
+
is_complete=False
|
|
193
|
+
)
|
|
194
|
+
elif delta_type == "thinking_delta":
|
|
195
|
+
thinking_delta = getattr(event.delta, "thinking", None)
|
|
196
|
+
if thinking_delta:
|
|
197
|
+
complete_reasoning += thinking_delta
|
|
198
|
+
yield ChunkResponse(
|
|
199
|
+
content="",
|
|
200
|
+
reasoning=thinking_delta,
|
|
201
|
+
is_complete=False
|
|
202
|
+
)
|
|
203
|
+
|
|
204
|
+
# Handle tool calls using common converter
|
|
205
|
+
tool_calls = convert_anthropic_tool_call(event)
|
|
206
|
+
if tool_calls:
|
|
104
207
|
yield ChunkResponse(
|
|
105
|
-
content=
|
|
208
|
+
content="",
|
|
209
|
+
tool_calls=tool_calls,
|
|
106
210
|
is_complete=False
|
|
107
211
|
)
|
|
108
212
|
|
|
@@ -120,7 +224,9 @@ class ClaudeLLM(BaseLLM):
|
|
|
120
224
|
usage=token_usage
|
|
121
225
|
)
|
|
122
226
|
|
|
123
|
-
|
|
227
|
+
# Only add assistant message if there's actual content.
|
|
228
|
+
# Tool-call-only responses should not add empty messages, as Claude API
|
|
229
|
+
# rejects subsequent requests with "all messages must have non-empty content".
|
|
124
230
|
except anthropic.APIError as e:
|
|
125
231
|
logger.error(f"Error in Claude API streaming: {str(e)}")
|
|
126
232
|
raise ValueError(f"Error in Claude API streaming: {str(e)}")
|
autobyteus/llm/api/gemini_llm.py
CHANGED
|
@@ -1,29 +1,41 @@
|
|
|
1
1
|
import logging
|
|
2
|
-
|
|
3
|
-
from
|
|
2
|
+
import asyncio
|
|
3
|
+
from typing import Dict, List, AsyncGenerator, Any, Optional
|
|
4
4
|
from google.genai import types as genai_types
|
|
5
|
-
import os
|
|
6
5
|
from autobyteus.llm.models import LLMModel
|
|
7
6
|
from autobyteus.llm.base_llm import BaseLLM
|
|
8
7
|
from autobyteus.llm.utils.llm_config import LLMConfig
|
|
9
8
|
from autobyteus.llm.utils.messages import MessageRole, Message
|
|
10
9
|
from autobyteus.llm.utils.token_usage import TokenUsage
|
|
11
10
|
from autobyteus.llm.utils.response_types import CompleteResponse, ChunkResponse
|
|
12
|
-
from autobyteus.
|
|
11
|
+
from autobyteus.utils.gemini_helper import initialize_gemini_client_with_runtime
|
|
12
|
+
from autobyteus.utils.gemini_model_mapping import resolve_model_for_runtime
|
|
13
|
+
from autobyteus.llm.converters import convert_gemini_tool_calls
|
|
14
|
+
from autobyteus.llm.prompt_renderers.gemini_prompt_renderer import GeminiPromptRenderer
|
|
13
15
|
|
|
14
16
|
logger = logging.getLogger(__name__)
|
|
15
17
|
|
|
16
|
-
def
|
|
17
|
-
"""
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
for
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
18
|
+
def _split_gemini_parts(parts: List[Any]) -> tuple[str, str]:
|
|
19
|
+
"""Split Gemini content parts into visible text and thought summaries."""
|
|
20
|
+
content_segments: List[str] = []
|
|
21
|
+
thought_segments: List[str] = []
|
|
22
|
+
for part in parts or []:
|
|
23
|
+
text = getattr(part, "text", None)
|
|
24
|
+
if not text:
|
|
25
|
+
continue
|
|
26
|
+
if getattr(part, "thought", False):
|
|
27
|
+
thought_segments.append(text)
|
|
28
|
+
else:
|
|
29
|
+
content_segments.append(text)
|
|
30
|
+
return "".join(content_segments), "".join(thought_segments)
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
def _split_system_message(messages: List[Message]) -> tuple[Optional[str], List[Message]]:
|
|
34
|
+
system_parts = [msg.content for msg in messages if msg.role == MessageRole.SYSTEM and msg.content]
|
|
35
|
+
system_prompt = "\n".join(system_parts) if system_parts else None
|
|
36
|
+
remaining = [msg for msg in messages if msg.role != MessageRole.SYSTEM]
|
|
37
|
+
return system_prompt, remaining
|
|
38
|
+
|
|
27
39
|
|
|
28
40
|
class GeminiLLM(BaseLLM):
|
|
29
41
|
def __init__(self, model: LLMModel = None, llm_config: LLMConfig = None):
|
|
@@ -32,59 +44,84 @@ class GeminiLLM(BaseLLM):
|
|
|
32
44
|
}
|
|
33
45
|
|
|
34
46
|
if model is None:
|
|
35
|
-
|
|
47
|
+
# Default to the latest low-latency Gemini LLM.
|
|
48
|
+
model = LLMModel['gemini-3-flash-preview']
|
|
36
49
|
if llm_config is None:
|
|
37
50
|
llm_config = LLMConfig()
|
|
38
51
|
|
|
39
52
|
super().__init__(model=model, llm_config=llm_config)
|
|
40
|
-
|
|
41
|
-
self.async_client = self.client.aio
|
|
42
|
-
|
|
43
|
-
@classmethod
|
|
44
|
-
def initialize(cls) -> genai.client.Client:
|
|
45
|
-
api_key = os.environ.get("GEMINI_API_KEY")
|
|
46
|
-
if not api_key:
|
|
47
|
-
logger.error("GEMINI_API_KEY environment variable is not set.")
|
|
48
|
-
raise ValueError("GEMINI_API_KEY environment variable is not set.")
|
|
53
|
+
|
|
49
54
|
try:
|
|
50
|
-
|
|
55
|
+
self.client, self.runtime_info = initialize_gemini_client_with_runtime()
|
|
56
|
+
self.async_client = self.client.aio
|
|
57
|
+
self._renderer = GeminiPromptRenderer()
|
|
51
58
|
except Exception as e:
|
|
52
|
-
|
|
53
|
-
|
|
59
|
+
# Re-raise or handle initialization errors specifically for the LLM context if needed
|
|
60
|
+
logger.error(f"Failed to initialize Gemini LLM: {str(e)}")
|
|
61
|
+
raise
|
|
54
62
|
|
|
55
|
-
def _get_generation_config(self) -> genai_types.GenerateContentConfig:
|
|
63
|
+
def _get_generation_config(self, system_prompt: Optional[str] = None) -> genai_types.GenerateContentConfig:
|
|
56
64
|
"""Builds the generation config, handling special cases like 'thinking'."""
|
|
57
65
|
config = self.generation_config_dict.copy()
|
|
58
66
|
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
67
|
+
# Map thinking_level to token budget
|
|
68
|
+
# Values based on Gemini 3 API recommendations
|
|
69
|
+
THINKING_LEVEL_BUDGETS = {
|
|
70
|
+
"minimal": 0,
|
|
71
|
+
"low": 1024,
|
|
72
|
+
"medium": 4096,
|
|
73
|
+
"high": 16384,
|
|
74
|
+
}
|
|
62
75
|
|
|
63
|
-
#
|
|
64
|
-
|
|
76
|
+
# Read thinking_level from extra_params (set by user config)
|
|
77
|
+
# Default to "minimal" (0 tokens) for backward compatibility
|
|
78
|
+
thinking_level = self.config.extra_params.get("thinking_level", "minimal")
|
|
79
|
+
thinking_budget = THINKING_LEVEL_BUDGETS.get(thinking_level, 0)
|
|
65
80
|
|
|
81
|
+
include_thoughts = self.config.extra_params.get("include_thoughts", False)
|
|
82
|
+
if not isinstance(include_thoughts, bool):
|
|
83
|
+
include_thoughts = False
|
|
84
|
+
thinking_config = genai_types.ThinkingConfig(
|
|
85
|
+
thinking_budget=thinking_budget,
|
|
86
|
+
include_thoughts=include_thoughts
|
|
87
|
+
)
|
|
88
|
+
|
|
89
|
+
# System instruction is now part of the config
|
|
90
|
+
system_instruction = system_prompt if system_prompt is not None else self.system_message
|
|
91
|
+
|
|
66
92
|
return genai_types.GenerateContentConfig(
|
|
67
93
|
**config,
|
|
68
94
|
thinking_config=thinking_config,
|
|
69
95
|
system_instruction=system_instruction
|
|
70
96
|
)
|
|
71
97
|
|
|
72
|
-
async def
|
|
73
|
-
self.add_user_message(user_message)
|
|
74
|
-
|
|
98
|
+
async def _send_messages_to_llm(self, messages: List[Message], **kwargs) -> CompleteResponse:
|
|
75
99
|
try:
|
|
76
|
-
|
|
77
|
-
|
|
100
|
+
system_prompt, non_system = _split_system_message(messages)
|
|
101
|
+
history = await self._renderer.render(non_system)
|
|
102
|
+
generation_config = self._get_generation_config(system_prompt=system_prompt)
|
|
78
103
|
|
|
104
|
+
# FIX: Removed 'models/' prefix to support Vertex AI
|
|
105
|
+
runtime_adjusted_model = resolve_model_for_runtime(
|
|
106
|
+
self.model.value,
|
|
107
|
+
modality="llm",
|
|
108
|
+
runtime=getattr(self, "runtime_info", None) and self.runtime_info.runtime,
|
|
109
|
+
)
|
|
79
110
|
response = await self.async_client.models.generate_content(
|
|
80
|
-
model=
|
|
111
|
+
model=runtime_adjusted_model,
|
|
81
112
|
contents=history,
|
|
82
113
|
config=generation_config,
|
|
83
114
|
)
|
|
84
115
|
|
|
85
|
-
assistant_message = response.text
|
|
86
|
-
|
|
87
|
-
|
|
116
|
+
assistant_message = response.text or ""
|
|
117
|
+
reasoning_summary = None
|
|
118
|
+
if response.candidates and response.candidates[0].content and response.candidates[0].content.parts:
|
|
119
|
+
parsed_text, parsed_thoughts = _split_gemini_parts(response.candidates[0].content.parts)
|
|
120
|
+
if parsed_text:
|
|
121
|
+
assistant_message = parsed_text
|
|
122
|
+
if parsed_thoughts:
|
|
123
|
+
reasoning_summary = parsed_thoughts
|
|
124
|
+
|
|
88
125
|
token_usage = TokenUsage(
|
|
89
126
|
prompt_tokens=0,
|
|
90
127
|
completion_tokens=0,
|
|
@@ -93,35 +130,102 @@ class GeminiLLM(BaseLLM):
|
|
|
93
130
|
|
|
94
131
|
return CompleteResponse(
|
|
95
132
|
content=assistant_message,
|
|
133
|
+
reasoning=reasoning_summary,
|
|
96
134
|
usage=token_usage
|
|
97
135
|
)
|
|
98
136
|
except Exception as e:
|
|
99
137
|
logger.error(f"Error in Gemini API call: {str(e)}")
|
|
100
138
|
raise ValueError(f"Error in Gemini API call: {str(e)}")
|
|
101
139
|
|
|
102
|
-
async def
|
|
103
|
-
self.add_user_message(user_message)
|
|
140
|
+
async def _stream_messages_to_llm(self, messages: List[Message], **kwargs) -> AsyncGenerator[ChunkResponse, None]:
|
|
104
141
|
complete_response = ""
|
|
142
|
+
complete_reasoning = ""
|
|
143
|
+
|
|
144
|
+
# Extract tools if provided
|
|
145
|
+
tools = kwargs.get("tools")
|
|
105
146
|
|
|
106
147
|
try:
|
|
107
|
-
|
|
108
|
-
|
|
148
|
+
system_prompt, non_system = _split_system_message(messages)
|
|
149
|
+
history = await self._renderer.render(non_system)
|
|
150
|
+
generation_config = self._get_generation_config(system_prompt=system_prompt)
|
|
151
|
+
|
|
152
|
+
# Add tools to config if present
|
|
153
|
+
# Note: In google.genai, tools can be passed in config
|
|
154
|
+
if tools:
|
|
155
|
+
# Auto-wrap tools if they appear to be raw function declarations
|
|
156
|
+
if isinstance(tools, list) and len(tools) > 0:
|
|
157
|
+
first_tool = tools[0]
|
|
158
|
+
# Check if it's a raw declaration (dict with name/description) but NOT a wrapper (dict with function_declarations)
|
|
159
|
+
if isinstance(first_tool, dict):
|
|
160
|
+
is_declaration = "name" in first_tool and "description" in first_tool
|
|
161
|
+
is_wrapper = "function_declarations" in first_tool
|
|
162
|
+
|
|
163
|
+
if is_declaration and not is_wrapper:
|
|
164
|
+
# Wrap the list of declarations into a single Tool structure
|
|
165
|
+
tools = [{"function_declarations": tools}]
|
|
109
166
|
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
167
|
+
try:
|
|
168
|
+
generation_config.tools = tools
|
|
169
|
+
except Exception:
|
|
170
|
+
# Fallback or strict strict typing issues
|
|
171
|
+
pass
|
|
172
|
+
|
|
173
|
+
# FIX: Removed 'models/' prefix to support Vertex AI
|
|
174
|
+
runtime_adjusted_model = resolve_model_for_runtime(
|
|
175
|
+
self.model.value,
|
|
176
|
+
modality="llm",
|
|
177
|
+
runtime=getattr(self, "runtime_info", None) and self.runtime_info.runtime,
|
|
114
178
|
)
|
|
179
|
+
|
|
180
|
+
# Prepare call args
|
|
181
|
+
call_kwargs = {
|
|
182
|
+
"model": runtime_adjusted_model,
|
|
183
|
+
"contents": history,
|
|
184
|
+
"config": generation_config,
|
|
185
|
+
}
|
|
186
|
+
# If explicit tools argument is needed and not supported in config for this SDK version:
|
|
187
|
+
# call_kwargs['tools'] = tools
|
|
188
|
+
# But usually config holds it.
|
|
189
|
+
|
|
190
|
+
response_stream = await self.async_client.models.generate_content_stream(**call_kwargs)
|
|
115
191
|
|
|
116
192
|
async for chunk in response_stream:
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
content
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
193
|
+
handled_parts = False
|
|
194
|
+
if chunk.candidates and chunk.candidates[0].content and chunk.candidates[0].content.parts:
|
|
195
|
+
handled_parts = True
|
|
196
|
+
for part in chunk.candidates[0].content.parts:
|
|
197
|
+
part_text = getattr(part, "text", None)
|
|
198
|
+
if part_text:
|
|
199
|
+
if getattr(part, "thought", False):
|
|
200
|
+
complete_reasoning += part_text
|
|
201
|
+
yield ChunkResponse(
|
|
202
|
+
content="",
|
|
203
|
+
reasoning=part_text,
|
|
204
|
+
is_complete=False
|
|
205
|
+
)
|
|
206
|
+
else:
|
|
207
|
+
complete_response += part_text
|
|
208
|
+
yield ChunkResponse(
|
|
209
|
+
content=part_text,
|
|
210
|
+
is_complete=False
|
|
211
|
+
)
|
|
212
|
+
|
|
213
|
+
tool_calls = convert_gemini_tool_calls(part)
|
|
214
|
+
if tool_calls:
|
|
215
|
+
yield ChunkResponse(
|
|
216
|
+
content="",
|
|
217
|
+
tool_calls=tool_calls,
|
|
218
|
+
is_complete=False
|
|
219
|
+
)
|
|
220
|
+
|
|
221
|
+
if not handled_parts:
|
|
222
|
+
chunk_text = chunk.text
|
|
223
|
+
if chunk_text:
|
|
224
|
+
complete_response += chunk_text
|
|
225
|
+
yield ChunkResponse(
|
|
226
|
+
content=chunk_text,
|
|
227
|
+
is_complete=False
|
|
228
|
+
)
|
|
125
229
|
|
|
126
230
|
token_usage = TokenUsage(
|
|
127
231
|
prompt_tokens=0,
|
autobyteus/llm/api/grok_llm.py
CHANGED
|
@@ -10,7 +10,7 @@ class GrokLLM(OpenAICompatibleLLM):
|
|
|
10
10
|
def __init__(self, model: LLMModel = None, llm_config: LLMConfig = None):
|
|
11
11
|
# Provide defaults if not specified
|
|
12
12
|
if model is None:
|
|
13
|
-
model = LLMModel['grok-
|
|
13
|
+
model = LLMModel['grok-4-1-fast-reasoning']
|
|
14
14
|
if llm_config is None:
|
|
15
15
|
llm_config = LLMConfig()
|
|
16
16
|
|