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
|
@@ -39,6 +39,57 @@ class LMStudioModelProvider:
|
|
|
39
39
|
except Exception:
|
|
40
40
|
return False
|
|
41
41
|
|
|
42
|
+
@staticmethod
|
|
43
|
+
def get_models() -> List[LLMModel]:
|
|
44
|
+
"""
|
|
45
|
+
Fetches models from all configured LM Studio instances and returns them as LLMModel objects.
|
|
46
|
+
"""
|
|
47
|
+
hosts = LMStudioModelProvider._get_hosts()
|
|
48
|
+
all_models = []
|
|
49
|
+
|
|
50
|
+
for host_url in hosts:
|
|
51
|
+
if not LMStudioModelProvider.is_valid_url(host_url):
|
|
52
|
+
logger.error(f"Invalid LM Studio host URL: {host_url}, skipping.")
|
|
53
|
+
continue
|
|
54
|
+
|
|
55
|
+
logger.info(f"Discovering LM Studio models from host: {host_url}")
|
|
56
|
+
base_url = f"{host_url}/v1"
|
|
57
|
+
client = OpenAI(base_url=base_url, api_key="lm-studio") # Dummy key
|
|
58
|
+
|
|
59
|
+
try:
|
|
60
|
+
response = client.models.list()
|
|
61
|
+
models = response.data
|
|
62
|
+
except APIConnectionError:
|
|
63
|
+
logger.warning(f"Could not connect to LM Studio at {host_url}. Please ensure the server is running.")
|
|
64
|
+
continue
|
|
65
|
+
except OpenAIError as e:
|
|
66
|
+
logger.error(f"An error occurred fetching models from LM Studio at {host_url}: {e}")
|
|
67
|
+
continue
|
|
68
|
+
|
|
69
|
+
for model_info in models:
|
|
70
|
+
model_id = model_info.id
|
|
71
|
+
if not model_id:
|
|
72
|
+
continue
|
|
73
|
+
|
|
74
|
+
try:
|
|
75
|
+
llm_model = LLMModel(
|
|
76
|
+
name=model_id,
|
|
77
|
+
value=model_id,
|
|
78
|
+
provider=LLMProvider.LMSTUDIO, # LMStudio is both provider and runtime
|
|
79
|
+
llm_class=LMStudioLLM,
|
|
80
|
+
canonical_name=model_id,
|
|
81
|
+
runtime=LLMRuntime.LMSTUDIO,
|
|
82
|
+
host_url=host_url,
|
|
83
|
+
default_config=LLMConfig(
|
|
84
|
+
pricing_config=TokenPricingConfig(0.0, 0.0) # Local models are free
|
|
85
|
+
)
|
|
86
|
+
)
|
|
87
|
+
all_models.append(llm_model)
|
|
88
|
+
except Exception as e:
|
|
89
|
+
logger.warning(f"Failed to create LLMModel for '{model_id}' from {host_url}: {e}")
|
|
90
|
+
|
|
91
|
+
return all_models
|
|
92
|
+
|
|
42
93
|
@staticmethod
|
|
43
94
|
def discover_and_register():
|
|
44
95
|
"""
|
|
@@ -47,58 +98,18 @@ class LMStudioModelProvider:
|
|
|
47
98
|
try:
|
|
48
99
|
from autobyteus.llm.llm_factory import LLMFactory
|
|
49
100
|
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
for host_url in hosts:
|
|
54
|
-
if not LMStudioModelProvider.is_valid_url(host_url):
|
|
55
|
-
logger.error(f"Invalid LM Studio host URL: {host_url}, skipping.")
|
|
56
|
-
continue
|
|
57
|
-
|
|
58
|
-
logger.info(f"Discovering LM Studio models from host: {host_url}")
|
|
59
|
-
base_url = f"{host_url}/v1"
|
|
60
|
-
client = OpenAI(base_url=base_url, api_key="lm-studio") # Dummy key
|
|
101
|
+
discovered_models = LMStudioModelProvider.get_models()
|
|
102
|
+
registered_count = 0
|
|
61
103
|
|
|
104
|
+
for model in discovered_models:
|
|
62
105
|
try:
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
except
|
|
66
|
-
logger.warning(f"
|
|
67
|
-
continue
|
|
68
|
-
except OpenAIError as e:
|
|
69
|
-
logger.error(f"An error occurred fetching models from LM Studio at {host_url}: {e}")
|
|
70
|
-
continue
|
|
71
|
-
|
|
72
|
-
host_registered_count = 0
|
|
73
|
-
for model_info in models:
|
|
74
|
-
model_id = model_info.id
|
|
75
|
-
if not model_id:
|
|
76
|
-
continue
|
|
77
|
-
|
|
78
|
-
try:
|
|
79
|
-
llm_model = LLMModel(
|
|
80
|
-
name=model_id,
|
|
81
|
-
value=model_id,
|
|
82
|
-
provider=LLMProvider.LMSTUDIO, # LMStudio is both provider and runtime
|
|
83
|
-
llm_class=LMStudioLLM,
|
|
84
|
-
canonical_name=model_id,
|
|
85
|
-
runtime=LLMRuntime.LMSTUDIO,
|
|
86
|
-
host_url=host_url,
|
|
87
|
-
default_config=LLMConfig(
|
|
88
|
-
pricing_config=TokenPricingConfig(0.0, 0.0) # Local models are free
|
|
89
|
-
)
|
|
90
|
-
)
|
|
91
|
-
LLMFactory.register_model(llm_model)
|
|
92
|
-
host_registered_count += 1
|
|
93
|
-
except Exception as e:
|
|
94
|
-
logger.warning(f"Failed to register LM Studio model '{model_id}' from {host_url}: {e}")
|
|
95
|
-
|
|
96
|
-
if host_registered_count > 0:
|
|
97
|
-
logger.info(f"Registered {host_registered_count} models from LM Studio host {host_url}")
|
|
98
|
-
total_registered_count += host_registered_count
|
|
106
|
+
LLMFactory.register_model(model)
|
|
107
|
+
registered_count += 1
|
|
108
|
+
except Exception as e:
|
|
109
|
+
logger.warning(f"Failed to register LM Studio model '{model.name}': {e}")
|
|
99
110
|
|
|
100
|
-
if
|
|
101
|
-
logger.info(f"Finished LM Studio discovery. Total models registered: {
|
|
111
|
+
if registered_count > 0:
|
|
112
|
+
logger.info(f"Finished LM Studio discovery. Total models registered: {registered_count}")
|
|
102
113
|
|
|
103
114
|
except Exception as e:
|
|
104
115
|
logger.error(f"An unexpected error occurred during LM Studio model discovery: {e}")
|
autobyteus/llm/models.py
CHANGED
|
@@ -1,17 +1,19 @@
|
|
|
1
1
|
import logging
|
|
2
|
-
from typing import TYPE_CHECKING, Type, Optional, List, Iterator
|
|
2
|
+
from typing import TYPE_CHECKING, Type, Optional, List, Iterator, Dict, Any
|
|
3
3
|
from dataclasses import dataclass
|
|
4
4
|
from urllib.parse import urlparse
|
|
5
5
|
|
|
6
6
|
from autobyteus.llm.providers import LLMProvider
|
|
7
7
|
from autobyteus.llm.runtimes import LLMRuntime
|
|
8
8
|
from autobyteus.llm.utils.llm_config import LLMConfig
|
|
9
|
+
from autobyteus.utils.parameter_schema import ParameterSchema
|
|
9
10
|
|
|
10
11
|
if TYPE_CHECKING:
|
|
11
12
|
from autobyteus.llm.base_llm import BaseLLM
|
|
12
13
|
from autobyteus.llm.llm_factory import LLMFactory
|
|
13
14
|
|
|
14
15
|
logger = logging.getLogger(__name__)
|
|
16
|
+
DEFAULT_MAX_CONTEXT_TOKENS = 200000
|
|
15
17
|
|
|
16
18
|
@dataclass
|
|
17
19
|
class ModelInfo:
|
|
@@ -23,6 +25,7 @@ class ModelInfo:
|
|
|
23
25
|
provider: str
|
|
24
26
|
runtime: str
|
|
25
27
|
host_url: Optional[str] = None
|
|
28
|
+
config_schema: Optional[Dict[str, Any]] = None # Serialized ParameterSchema
|
|
26
29
|
|
|
27
30
|
@dataclass
|
|
28
31
|
class ProviderModelGroup:
|
|
@@ -101,7 +104,11 @@ class LLMModel(metaclass=LLMModelMeta):
|
|
|
101
104
|
canonical_name: str,
|
|
102
105
|
default_config: Optional[LLMConfig] = None,
|
|
103
106
|
runtime: LLMRuntime = LLMRuntime.API,
|
|
104
|
-
host_url: Optional[str] = None
|
|
107
|
+
host_url: Optional[str] = None,
|
|
108
|
+
config_schema: Optional[ParameterSchema] = None,
|
|
109
|
+
max_context_tokens: Optional[int] = None,
|
|
110
|
+
default_compaction_ratio: float = 0.8,
|
|
111
|
+
default_safety_margin_tokens: int = 256,
|
|
105
112
|
):
|
|
106
113
|
self._name = name
|
|
107
114
|
self._value = value
|
|
@@ -109,8 +116,18 @@ class LLMModel(metaclass=LLMModelMeta):
|
|
|
109
116
|
self.provider = provider
|
|
110
117
|
self.llm_class = llm_class
|
|
111
118
|
self.default_config = default_config if default_config else LLMConfig()
|
|
119
|
+
if max_context_tokens is None:
|
|
120
|
+
max_context_tokens = (
|
|
121
|
+
self.default_config.token_limit
|
|
122
|
+
if self.default_config.token_limit is not None
|
|
123
|
+
else DEFAULT_MAX_CONTEXT_TOKENS
|
|
124
|
+
)
|
|
125
|
+
self.max_context_tokens = max_context_tokens
|
|
126
|
+
self.default_compaction_ratio = default_compaction_ratio
|
|
127
|
+
self.default_safety_margin_tokens = default_safety_margin_tokens
|
|
112
128
|
self.runtime = runtime
|
|
113
129
|
self.host_url = host_url
|
|
130
|
+
self.config_schema = config_schema
|
|
114
131
|
self._model_identifier = self._generate_identifier()
|
|
115
132
|
|
|
116
133
|
def _generate_identifier(self) -> str:
|
|
@@ -183,6 +200,22 @@ class LLMModel(metaclass=LLMModelMeta):
|
|
|
183
200
|
|
|
184
201
|
return self.llm_class(model=self, llm_config=config_to_use)
|
|
185
202
|
|
|
203
|
+
def to_model_info(self) -> ModelInfo:
|
|
204
|
+
"""
|
|
205
|
+
Converts this LLMModel to a ModelInfo data structure for API responses.
|
|
206
|
+
Serializes the config_schema if present.
|
|
207
|
+
"""
|
|
208
|
+
return ModelInfo(
|
|
209
|
+
model_identifier=self.model_identifier,
|
|
210
|
+
display_name=self.name,
|
|
211
|
+
value=self.value,
|
|
212
|
+
canonical_name=self.canonical_name,
|
|
213
|
+
provider=self.provider.value,
|
|
214
|
+
runtime=self.runtime.value,
|
|
215
|
+
host_url=self.host_url,
|
|
216
|
+
config_schema=self.config_schema.to_dict() if self.config_schema else None
|
|
217
|
+
)
|
|
218
|
+
|
|
186
219
|
def __repr__(self):
|
|
187
220
|
return (
|
|
188
221
|
f"LLMModel(identifier='{self.model_identifier}', name='{self.name}', "
|
|
@@ -44,6 +44,58 @@ class OllamaModelProvider:
|
|
|
44
44
|
except Exception:
|
|
45
45
|
return False
|
|
46
46
|
|
|
47
|
+
@staticmethod
|
|
48
|
+
def get_models() -> List[LLMModel]:
|
|
49
|
+
"""
|
|
50
|
+
Fetches models from all configured Ollama hosts and returns them as LLMModel objects.
|
|
51
|
+
"""
|
|
52
|
+
hosts = OllamaModelProvider._get_hosts()
|
|
53
|
+
all_models = []
|
|
54
|
+
|
|
55
|
+
for host_url in hosts:
|
|
56
|
+
if not OllamaModelProvider.is_valid_url(host_url):
|
|
57
|
+
logger.error(f"Invalid Ollama host URL provided: '{host_url}', skipping.")
|
|
58
|
+
continue
|
|
59
|
+
|
|
60
|
+
logger.info(f"Discovering Ollama models from host: {host_url}")
|
|
61
|
+
client = Client(host=host_url)
|
|
62
|
+
|
|
63
|
+
try:
|
|
64
|
+
response = client.list()
|
|
65
|
+
models = response.get('models', [])
|
|
66
|
+
except httpx.ConnectError:
|
|
67
|
+
logger.warning(f"Could not connect to Ollama server at {host_url}. Please ensure it's running.")
|
|
68
|
+
continue
|
|
69
|
+
except Exception as e:
|
|
70
|
+
logger.error(f"Failed to fetch models from {host_url}: {e}")
|
|
71
|
+
continue
|
|
72
|
+
|
|
73
|
+
for model_info in models:
|
|
74
|
+
model_name = model_info.get('model')
|
|
75
|
+
if not model_name:
|
|
76
|
+
continue
|
|
77
|
+
|
|
78
|
+
try:
|
|
79
|
+
provider = OllamaProviderResolver.resolve(model_name)
|
|
80
|
+
|
|
81
|
+
llm_model = LLMModel(
|
|
82
|
+
name=model_name,
|
|
83
|
+
value=model_name,
|
|
84
|
+
provider=provider,
|
|
85
|
+
llm_class=OllamaLLM,
|
|
86
|
+
canonical_name=model_name,
|
|
87
|
+
runtime=LLMRuntime.OLLAMA,
|
|
88
|
+
host_url=host_url,
|
|
89
|
+
default_config=LLMConfig(
|
|
90
|
+
pricing_config=TokenPricingConfig(0.0, 0.0) # Local models are free
|
|
91
|
+
)
|
|
92
|
+
)
|
|
93
|
+
all_models.append(llm_model)
|
|
94
|
+
except Exception as e:
|
|
95
|
+
logger.warning(f"Failed to create LLMModel for '{model_name}' from host {host_url}: {e}")
|
|
96
|
+
|
|
97
|
+
return all_models
|
|
98
|
+
|
|
47
99
|
@staticmethod
|
|
48
100
|
def discover_and_register():
|
|
49
101
|
"""
|
|
@@ -52,59 +104,18 @@ class OllamaModelProvider:
|
|
|
52
104
|
try:
|
|
53
105
|
from autobyteus.llm.llm_factory import LLMFactory
|
|
54
106
|
|
|
55
|
-
|
|
56
|
-
|
|
107
|
+
discovered_models = OllamaModelProvider.get_models()
|
|
108
|
+
registered_count = 0
|
|
57
109
|
|
|
58
|
-
for
|
|
59
|
-
if not OllamaModelProvider.is_valid_url(host_url):
|
|
60
|
-
logger.error(f"Invalid Ollama host URL provided: '{host_url}', skipping.")
|
|
61
|
-
continue
|
|
62
|
-
|
|
63
|
-
logger.info(f"Discovering Ollama models from host: {host_url}")
|
|
64
|
-
client = Client(host=host_url)
|
|
65
|
-
|
|
110
|
+
for model in discovered_models:
|
|
66
111
|
try:
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
except httpx.ConnectError:
|
|
70
|
-
logger.warning(f"Could not connect to Ollama server at {host_url}. Please ensure it's running.")
|
|
71
|
-
continue
|
|
112
|
+
LLMFactory.register_model(model)
|
|
113
|
+
registered_count += 1
|
|
72
114
|
except Exception as e:
|
|
73
|
-
logger.
|
|
74
|
-
continue
|
|
75
|
-
|
|
76
|
-
host_registered_count = 0
|
|
77
|
-
for model_info in models:
|
|
78
|
-
model_name = model_info.get('model')
|
|
79
|
-
if not model_name:
|
|
80
|
-
continue
|
|
81
|
-
|
|
82
|
-
try:
|
|
83
|
-
provider = OllamaProviderResolver.resolve(model_name)
|
|
84
|
-
|
|
85
|
-
llm_model = LLMModel(
|
|
86
|
-
name=model_name,
|
|
87
|
-
value=model_name,
|
|
88
|
-
provider=provider,
|
|
89
|
-
llm_class=OllamaLLM,
|
|
90
|
-
canonical_name=model_name,
|
|
91
|
-
runtime=LLMRuntime.OLLAMA,
|
|
92
|
-
host_url=host_url,
|
|
93
|
-
default_config=LLMConfig(
|
|
94
|
-
pricing_config=TokenPricingConfig(0.0, 0.0) # Local models are free
|
|
95
|
-
)
|
|
96
|
-
)
|
|
97
|
-
LLMFactory.register_model(llm_model)
|
|
98
|
-
host_registered_count += 1
|
|
99
|
-
except Exception as e:
|
|
100
|
-
logger.warning(f"Failed to register model '{model_name}' from host {host_url}: {e}")
|
|
101
|
-
|
|
102
|
-
if host_registered_count > 0:
|
|
103
|
-
logger.info(f"Registered {host_registered_count} models from Ollama host {host_url}")
|
|
104
|
-
total_registered_count += host_registered_count
|
|
115
|
+
logger.warning(f"Failed to register Ollama model '{model.name}': {e}")
|
|
105
116
|
|
|
106
|
-
if
|
|
107
|
-
logger.info(f"Finished Ollama discovery. Total models registered: {
|
|
117
|
+
if registered_count > 0:
|
|
118
|
+
logger.info(f"Finished Ollama discovery. Total models registered: {registered_count}")
|
|
108
119
|
|
|
109
120
|
except Exception as e:
|
|
110
121
|
logger.error(f"An unexpected error occurred during Ollama model discovery: {e}")
|
|
@@ -15,7 +15,6 @@ class OllamaProviderResolver:
|
|
|
15
15
|
KEYWORD_PROVIDER_MAP = [
|
|
16
16
|
(['gpt'], LLMProvider.OPENAI),
|
|
17
17
|
(['gemma', 'gemini'], LLMProvider.GEMINI),
|
|
18
|
-
(['llama'], LLMProvider.GROQ),
|
|
19
18
|
(['mistral'], LLMProvider.MISTRAL),
|
|
20
19
|
(['deepseek'], LLMProvider.DEEPSEEK),
|
|
21
20
|
(['qwen'], LLMProvider.QWEN),
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
from autobyteus.llm.prompt_renderers.base_prompt_renderer import BasePromptRenderer
|
|
2
|
+
from autobyteus.llm.prompt_renderers.openai_responses_renderer import OpenAIResponsesRenderer
|
|
3
|
+
from autobyteus.llm.prompt_renderers.openai_chat_renderer import OpenAIChatRenderer
|
|
4
|
+
from autobyteus.llm.prompt_renderers.anthropic_prompt_renderer import AnthropicPromptRenderer
|
|
5
|
+
from autobyteus.llm.prompt_renderers.gemini_prompt_renderer import GeminiPromptRenderer
|
|
6
|
+
from autobyteus.llm.prompt_renderers.mistral_prompt_renderer import MistralPromptRenderer
|
|
7
|
+
from autobyteus.llm.prompt_renderers.ollama_prompt_renderer import OllamaPromptRenderer
|
|
8
|
+
from autobyteus.llm.prompt_renderers.autobyteus_prompt_renderer import AutobyteusPromptRenderer
|
|
9
|
+
|
|
10
|
+
__all__ = [
|
|
11
|
+
"BasePromptRenderer",
|
|
12
|
+
"OpenAIResponsesRenderer",
|
|
13
|
+
"OpenAIChatRenderer",
|
|
14
|
+
"AnthropicPromptRenderer",
|
|
15
|
+
"GeminiPromptRenderer",
|
|
16
|
+
"MistralPromptRenderer",
|
|
17
|
+
"OllamaPromptRenderer",
|
|
18
|
+
"AutobyteusPromptRenderer",
|
|
19
|
+
]
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
import asyncio
|
|
2
|
+
import json
|
|
3
|
+
import logging
|
|
4
|
+
from typing import List, Dict, Any
|
|
5
|
+
|
|
6
|
+
from autobyteus.llm.prompt_renderers.base_prompt_renderer import BasePromptRenderer
|
|
7
|
+
from autobyteus.llm.utils.media_payload_formatter import (
|
|
8
|
+
media_source_to_base64,
|
|
9
|
+
get_mime_type,
|
|
10
|
+
is_valid_media_path,
|
|
11
|
+
)
|
|
12
|
+
from autobyteus.llm.utils.messages import Message, MessageRole, ToolCallPayload, ToolResultPayload
|
|
13
|
+
|
|
14
|
+
logger = logging.getLogger(__name__)
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
class AnthropicPromptRenderer(BasePromptRenderer):
|
|
18
|
+
async def render(self, messages: List[Message]) -> List[Dict[str, Any]]:
|
|
19
|
+
formatted_messages: List[Dict[str, Any]] = []
|
|
20
|
+
valid_image_mimes = {"image/jpeg", "image/png", "image/gif", "image/webp"}
|
|
21
|
+
|
|
22
|
+
for msg in messages:
|
|
23
|
+
role = msg.role.value
|
|
24
|
+
if msg.tool_payload or msg.role == MessageRole.TOOL:
|
|
25
|
+
payload_text = _format_tool_payload(msg)
|
|
26
|
+
role = (
|
|
27
|
+
MessageRole.USER.value
|
|
28
|
+
if msg.role == MessageRole.TOOL
|
|
29
|
+
else MessageRole.ASSISTANT.value
|
|
30
|
+
)
|
|
31
|
+
msg = Message(
|
|
32
|
+
role=MessageRole.USER
|
|
33
|
+
if role == MessageRole.USER.value
|
|
34
|
+
else MessageRole.ASSISTANT,
|
|
35
|
+
content=payload_text or "",
|
|
36
|
+
)
|
|
37
|
+
|
|
38
|
+
if msg.image_urls:
|
|
39
|
+
content_blocks: List[Dict[str, Any]] = []
|
|
40
|
+
|
|
41
|
+
image_tasks = [media_source_to_base64(url) for url in msg.image_urls]
|
|
42
|
+
try:
|
|
43
|
+
base64_images = await asyncio.gather(*image_tasks)
|
|
44
|
+
|
|
45
|
+
for i, b64_data in enumerate(base64_images):
|
|
46
|
+
original_url = msg.image_urls[i]
|
|
47
|
+
mime_type = get_mime_type(original_url)
|
|
48
|
+
|
|
49
|
+
if mime_type not in valid_image_mimes:
|
|
50
|
+
logger.warning(
|
|
51
|
+
"Unsupported image MIME type '%s' for %s. "
|
|
52
|
+
"Anthropic supports: %s. Defaulting to image/jpeg.",
|
|
53
|
+
mime_type,
|
|
54
|
+
original_url,
|
|
55
|
+
valid_image_mimes,
|
|
56
|
+
)
|
|
57
|
+
mime_type = "image/jpeg"
|
|
58
|
+
|
|
59
|
+
content_blocks.append(
|
|
60
|
+
{
|
|
61
|
+
"type": "image",
|
|
62
|
+
"source": {
|
|
63
|
+
"type": "base64",
|
|
64
|
+
"media_type": mime_type,
|
|
65
|
+
"data": b64_data,
|
|
66
|
+
},
|
|
67
|
+
}
|
|
68
|
+
)
|
|
69
|
+
except Exception as e:
|
|
70
|
+
logger.error("Error processing images for Claude: %s", e)
|
|
71
|
+
|
|
72
|
+
if msg.content:
|
|
73
|
+
content_blocks.append({"type": "text", "text": msg.content})
|
|
74
|
+
|
|
75
|
+
formatted_messages.append({"role": role, "content": content_blocks})
|
|
76
|
+
else:
|
|
77
|
+
formatted_messages.append(
|
|
78
|
+
{
|
|
79
|
+
"role": role,
|
|
80
|
+
"content": msg.content or "",
|
|
81
|
+
}
|
|
82
|
+
)
|
|
83
|
+
|
|
84
|
+
return formatted_messages
|
|
85
|
+
|
|
86
|
+
|
|
87
|
+
def _format_tool_payload(message: Message) -> str:
|
|
88
|
+
payload = message.tool_payload
|
|
89
|
+
if isinstance(payload, ToolCallPayload):
|
|
90
|
+
lines = []
|
|
91
|
+
for call in payload.tool_calls:
|
|
92
|
+
args = call.arguments
|
|
93
|
+
if isinstance(args, (dict, list)):
|
|
94
|
+
args = json.dumps(args, ensure_ascii=True)
|
|
95
|
+
lines.append(f"[TOOL_CALL] {call.name} {args}")
|
|
96
|
+
return "\n".join(lines)
|
|
97
|
+
if isinstance(payload, ToolResultPayload):
|
|
98
|
+
if payload.tool_error:
|
|
99
|
+
return f"[TOOL_ERROR] {payload.tool_name} {payload.tool_error}"
|
|
100
|
+
result = payload.tool_result
|
|
101
|
+
if isinstance(result, (dict, list)):
|
|
102
|
+
result = json.dumps(result, ensure_ascii=True)
|
|
103
|
+
return f"[TOOL_RESULT] {payload.tool_name} {result}"
|
|
104
|
+
return message.content or ""
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
from typing import List, Dict, Any
|
|
2
|
+
|
|
3
|
+
from autobyteus.llm.prompt_renderers.base_prompt_renderer import BasePromptRenderer
|
|
4
|
+
from autobyteus.llm.utils.messages import Message, MessageRole
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
class AutobyteusPromptRenderer(BasePromptRenderer):
|
|
8
|
+
async def render(self, messages: List[Message]) -> List[Dict[str, Any]]:
|
|
9
|
+
for msg in reversed(messages):
|
|
10
|
+
if msg.role == MessageRole.USER:
|
|
11
|
+
return [
|
|
12
|
+
{
|
|
13
|
+
"content": msg.content or "",
|
|
14
|
+
"image_urls": list(msg.image_urls),
|
|
15
|
+
"audio_urls": list(msg.audio_urls),
|
|
16
|
+
"video_urls": list(msg.video_urls),
|
|
17
|
+
}
|
|
18
|
+
]
|
|
19
|
+
raise ValueError("AutobyteusPromptRenderer requires at least one user message.")
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
from abc import ABC, abstractmethod
|
|
2
|
+
from typing import List, Dict, Any
|
|
3
|
+
|
|
4
|
+
from autobyteus.llm.utils.messages import Message
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
class BasePromptRenderer(ABC):
|
|
8
|
+
@abstractmethod
|
|
9
|
+
async def render(self, messages: List[Message]) -> List[Dict[str, Any]]:
|
|
10
|
+
raise NotImplementedError
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
import base64
|
|
2
|
+
import mimetypes
|
|
3
|
+
import logging
|
|
4
|
+
from typing import Dict, List, Any, Optional
|
|
5
|
+
|
|
6
|
+
from google.genai import types as genai_types
|
|
7
|
+
|
|
8
|
+
from autobyteus.llm.prompt_renderers.base_prompt_renderer import BasePromptRenderer
|
|
9
|
+
from autobyteus.llm.utils.messages import Message, MessageRole, ToolCallPayload, ToolResultPayload
|
|
10
|
+
from autobyteus.llm.utils.media_payload_formatter import media_source_to_base64, get_mime_type
|
|
11
|
+
|
|
12
|
+
logger = logging.getLogger(__name__)
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
class GeminiPromptRenderer(BasePromptRenderer):
|
|
16
|
+
async def render(self, messages: List[Message]) -> List[Dict[str, Any]]:
|
|
17
|
+
history: List[Dict[str, Any]] = []
|
|
18
|
+
for msg in messages:
|
|
19
|
+
role = None
|
|
20
|
+
content_text = msg.content
|
|
21
|
+
if msg.tool_payload or msg.role == MessageRole.TOOL:
|
|
22
|
+
content_text = _format_tool_payload(msg)
|
|
23
|
+
role = "model" if msg.role == MessageRole.ASSISTANT else "user"
|
|
24
|
+
elif msg.role in (MessageRole.USER, MessageRole.ASSISTANT):
|
|
25
|
+
role = "model" if msg.role == MessageRole.ASSISTANT else "user"
|
|
26
|
+
else:
|
|
27
|
+
continue
|
|
28
|
+
|
|
29
|
+
if role is None:
|
|
30
|
+
continue
|
|
31
|
+
|
|
32
|
+
parts: List[Any] = []
|
|
33
|
+
if content_text:
|
|
34
|
+
parts.append({"text": content_text})
|
|
35
|
+
|
|
36
|
+
media_urls = msg.image_urls + msg.audio_urls + msg.video_urls
|
|
37
|
+
for url in media_urls:
|
|
38
|
+
try:
|
|
39
|
+
b64_data = await media_source_to_base64(url)
|
|
40
|
+
data_bytes = base64.b64decode(b64_data)
|
|
41
|
+
mime_type, _ = mimetypes.guess_type(url)
|
|
42
|
+
if not mime_type:
|
|
43
|
+
mime_type = get_mime_type(url)
|
|
44
|
+
parts.append(genai_types.Part.from_bytes(data=data_bytes, mime_type=mime_type))
|
|
45
|
+
except Exception as exc:
|
|
46
|
+
logger.error("Failed to process media content %s: %s", url, exc)
|
|
47
|
+
|
|
48
|
+
if parts:
|
|
49
|
+
history.append({"role": role, "parts": parts})
|
|
50
|
+
|
|
51
|
+
return history
|
|
52
|
+
|
|
53
|
+
|
|
54
|
+
def _format_tool_payload(message: Message) -> Optional[str]:
|
|
55
|
+
payload = message.tool_payload
|
|
56
|
+
if isinstance(payload, ToolCallPayload):
|
|
57
|
+
lines = [f"[TOOL_CALL] {call.name} {call.arguments}" for call in payload.tool_calls]
|
|
58
|
+
return "\n".join(lines)
|
|
59
|
+
if isinstance(payload, ToolResultPayload):
|
|
60
|
+
if payload.tool_error:
|
|
61
|
+
return f"[TOOL_ERROR] {payload.tool_name} {payload.tool_error}"
|
|
62
|
+
return f"[TOOL_RESULT] {payload.tool_name} {payload.tool_result}"
|
|
63
|
+
return None
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
import asyncio
|
|
2
|
+
import logging
|
|
3
|
+
from typing import Dict, List, Any, Optional, Union
|
|
4
|
+
|
|
5
|
+
from autobyteus.llm.prompt_renderers.base_prompt_renderer import BasePromptRenderer
|
|
6
|
+
from autobyteus.llm.utils.messages import Message, MessageRole, ToolCallPayload, ToolResultPayload
|
|
7
|
+
from autobyteus.llm.utils.media_payload_formatter import (
|
|
8
|
+
media_source_to_base64,
|
|
9
|
+
get_mime_type,
|
|
10
|
+
is_valid_media_path,
|
|
11
|
+
)
|
|
12
|
+
|
|
13
|
+
logger = logging.getLogger(__name__)
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
class MistralPromptRenderer(BasePromptRenderer):
|
|
17
|
+
async def render(self, messages: List[Message]) -> List[Dict[str, Any]]:
|
|
18
|
+
mistral_messages: List[Dict[str, Any]] = []
|
|
19
|
+
for msg in messages:
|
|
20
|
+
role = msg.role.value
|
|
21
|
+
if msg.tool_payload or msg.role == MessageRole.TOOL:
|
|
22
|
+
content_text = _format_tool_payload(msg) or ""
|
|
23
|
+
role = (
|
|
24
|
+
MessageRole.USER.value
|
|
25
|
+
if msg.role == MessageRole.TOOL
|
|
26
|
+
else MessageRole.ASSISTANT.value
|
|
27
|
+
)
|
|
28
|
+
msg = Message(
|
|
29
|
+
role=MessageRole.USER
|
|
30
|
+
if role == MessageRole.USER.value
|
|
31
|
+
else MessageRole.ASSISTANT,
|
|
32
|
+
content=content_text,
|
|
33
|
+
)
|
|
34
|
+
|
|
35
|
+
if not msg.content and not msg.image_urls and msg.role != MessageRole.SYSTEM:
|
|
36
|
+
continue
|
|
37
|
+
|
|
38
|
+
content: Union[str, List[Dict[str, Any]]]
|
|
39
|
+
if msg.image_urls:
|
|
40
|
+
content_parts: List[Dict[str, Any]] = []
|
|
41
|
+
if msg.content:
|
|
42
|
+
content_parts.append({"type": "text", "text": msg.content})
|
|
43
|
+
|
|
44
|
+
image_tasks = [media_source_to_base64(url) for url in msg.image_urls]
|
|
45
|
+
try:
|
|
46
|
+
base64_images = await asyncio.gather(*image_tasks)
|
|
47
|
+
for i, b64_image in enumerate(base64_images):
|
|
48
|
+
original_url = msg.image_urls[i]
|
|
49
|
+
mime_type = (
|
|
50
|
+
get_mime_type(original_url)
|
|
51
|
+
if is_valid_media_path(original_url)
|
|
52
|
+
else "image/jpeg"
|
|
53
|
+
)
|
|
54
|
+
data_uri = f"data:{mime_type};base64,{b64_image}"
|
|
55
|
+
content_parts.append(
|
|
56
|
+
{
|
|
57
|
+
"type": "image_url",
|
|
58
|
+
"image_url": {"url": data_uri},
|
|
59
|
+
}
|
|
60
|
+
)
|
|
61
|
+
except Exception as exc:
|
|
62
|
+
logger.error("Error processing images for Mistral: %s", exc)
|
|
63
|
+
|
|
64
|
+
if msg.audio_urls:
|
|
65
|
+
logger.warning("MistralLLM does not yet support audio; skipping.")
|
|
66
|
+
if msg.video_urls:
|
|
67
|
+
logger.warning("MistralLLM does not yet support video; skipping.")
|
|
68
|
+
|
|
69
|
+
content = content_parts
|
|
70
|
+
else:
|
|
71
|
+
content = msg.content or ""
|
|
72
|
+
|
|
73
|
+
mistral_messages.append({"role": role, "content": content})
|
|
74
|
+
|
|
75
|
+
return mistral_messages
|
|
76
|
+
|
|
77
|
+
|
|
78
|
+
def _format_tool_payload(message: Message) -> Optional[str]:
|
|
79
|
+
payload = message.tool_payload
|
|
80
|
+
if isinstance(payload, ToolCallPayload):
|
|
81
|
+
lines = [f"[TOOL_CALL] {call.name} {call.arguments}" for call in payload.tool_calls]
|
|
82
|
+
return "\n".join(lines)
|
|
83
|
+
if isinstance(payload, ToolResultPayload):
|
|
84
|
+
if payload.tool_error:
|
|
85
|
+
return f"[TOOL_ERROR] {payload.tool_name} {payload.tool_error}"
|
|
86
|
+
return f"[TOOL_RESULT] {payload.tool_name} {payload.tool_result}"
|
|
87
|
+
return None
|