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
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
"""
|
|
2
|
+
start_background_process tool - Start long-running processes.
|
|
3
|
+
|
|
4
|
+
Starts processes like servers (yarn dev, uvicorn) in the background
|
|
5
|
+
and returns immediately with a process ID for later reference.
|
|
6
|
+
"""
|
|
7
|
+
|
|
8
|
+
import logging
|
|
9
|
+
from typing import TYPE_CHECKING, Optional
|
|
10
|
+
|
|
11
|
+
from autobyteus.tools import tool
|
|
12
|
+
from autobyteus.tools.tool_category import ToolCategory
|
|
13
|
+
|
|
14
|
+
if TYPE_CHECKING:
|
|
15
|
+
from autobyteus.agent.context import AgentContext
|
|
16
|
+
|
|
17
|
+
logger = logging.getLogger(__name__)
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
def _get_background_manager(context: Optional['AgentContext']):
|
|
21
|
+
"""Get or create the background process manager for this agent.
|
|
22
|
+
|
|
23
|
+
Args:
|
|
24
|
+
context: The agent context.
|
|
25
|
+
|
|
26
|
+
Returns:
|
|
27
|
+
BackgroundProcessManager instance.
|
|
28
|
+
"""
|
|
29
|
+
from autobyteus.tools.terminal.background_process_manager import BackgroundProcessManager
|
|
30
|
+
|
|
31
|
+
if context is None:
|
|
32
|
+
if not hasattr(_get_background_manager, '_default_manager'):
|
|
33
|
+
_get_background_manager._default_manager = BackgroundProcessManager()
|
|
34
|
+
return _get_background_manager._default_manager
|
|
35
|
+
|
|
36
|
+
if not hasattr(context, '_background_process_manager'):
|
|
37
|
+
context._background_process_manager = BackgroundProcessManager()
|
|
38
|
+
|
|
39
|
+
return context._background_process_manager
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
def _get_cwd(context: Optional['AgentContext']) -> str:
|
|
43
|
+
"""Get the working directory for the process.
|
|
44
|
+
|
|
45
|
+
Args:
|
|
46
|
+
context: The agent context.
|
|
47
|
+
|
|
48
|
+
Returns:
|
|
49
|
+
Working directory path.
|
|
50
|
+
"""
|
|
51
|
+
import tempfile
|
|
52
|
+
|
|
53
|
+
if context and hasattr(context, 'workspace') and context.workspace:
|
|
54
|
+
try:
|
|
55
|
+
base_path = context.workspace.get_base_path()
|
|
56
|
+
if base_path and isinstance(base_path, str):
|
|
57
|
+
return base_path
|
|
58
|
+
except Exception:
|
|
59
|
+
pass
|
|
60
|
+
|
|
61
|
+
return tempfile.gettempdir()
|
|
62
|
+
|
|
63
|
+
|
|
64
|
+
@tool(name="start_background_process", category=ToolCategory.SYSTEM)
|
|
65
|
+
async def start_background_process(
|
|
66
|
+
context: Optional['AgentContext'],
|
|
67
|
+
command: str
|
|
68
|
+
) -> dict:
|
|
69
|
+
"""
|
|
70
|
+
Start a long-running process in the background.
|
|
71
|
+
|
|
72
|
+
Use this for servers, watchers, or any process that doesn't
|
|
73
|
+
terminate immediately. The process runs independently and
|
|
74
|
+
you can check its output or stop it later using the returned
|
|
75
|
+
process_id.
|
|
76
|
+
|
|
77
|
+
Args:
|
|
78
|
+
command: The command to run in background.
|
|
79
|
+
Examples: "yarn dev", "uvicorn main:app", "npm start"
|
|
80
|
+
|
|
81
|
+
Returns:
|
|
82
|
+
dict with:
|
|
83
|
+
- process_id: ID to reference this process later
|
|
84
|
+
- status: "started"
|
|
85
|
+
|
|
86
|
+
Examples:
|
|
87
|
+
- start_background_process("yarn dev")
|
|
88
|
+
- start_background_process("uvicorn app:main --reload")
|
|
89
|
+
- start_background_process("python -m http.server 8000")
|
|
90
|
+
|
|
91
|
+
After starting, use:
|
|
92
|
+
- get_process_output(process_id) to check output
|
|
93
|
+
- stop_background_process(process_id) to stop it
|
|
94
|
+
"""
|
|
95
|
+
manager = _get_background_manager(context)
|
|
96
|
+
cwd = _get_cwd(context)
|
|
97
|
+
|
|
98
|
+
logger.info(f"Starting background process: {command}")
|
|
99
|
+
process_id = await manager.start_process(command, cwd)
|
|
100
|
+
|
|
101
|
+
return {
|
|
102
|
+
"process_id": process_id,
|
|
103
|
+
"status": "started"
|
|
104
|
+
}
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
"""
|
|
2
|
+
stop_background_process tool - Stop background processes.
|
|
3
|
+
|
|
4
|
+
Terminates a background process started with start_background_process.
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
import logging
|
|
8
|
+
from typing import TYPE_CHECKING, Optional
|
|
9
|
+
|
|
10
|
+
from autobyteus.tools import tool
|
|
11
|
+
from autobyteus.tools.tool_category import ToolCategory
|
|
12
|
+
|
|
13
|
+
if TYPE_CHECKING:
|
|
14
|
+
from autobyteus.agent.context import AgentContext
|
|
15
|
+
|
|
16
|
+
logger = logging.getLogger(__name__)
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
def _get_background_manager(context: Optional['AgentContext']):
|
|
20
|
+
"""Get the background process manager for this agent."""
|
|
21
|
+
from autobyteus.tools.terminal.background_process_manager import BackgroundProcessManager
|
|
22
|
+
|
|
23
|
+
if context is None:
|
|
24
|
+
if not hasattr(_get_background_manager, '_default_manager'):
|
|
25
|
+
_get_background_manager._default_manager = BackgroundProcessManager()
|
|
26
|
+
return _get_background_manager._default_manager
|
|
27
|
+
|
|
28
|
+
if not hasattr(context, '_background_process_manager'):
|
|
29
|
+
context._background_process_manager = BackgroundProcessManager()
|
|
30
|
+
|
|
31
|
+
return context._background_process_manager
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
@tool(name="stop_background_process", category=ToolCategory.SYSTEM)
|
|
35
|
+
async def stop_background_process(
|
|
36
|
+
context: Optional['AgentContext'],
|
|
37
|
+
process_id: str
|
|
38
|
+
) -> dict:
|
|
39
|
+
"""
|
|
40
|
+
Stop a background process.
|
|
41
|
+
|
|
42
|
+
Terminates a process that was started with start_background_process.
|
|
43
|
+
Sends SIGTERM first for graceful shutdown, then SIGKILL if the
|
|
44
|
+
process doesn't terminate.
|
|
45
|
+
|
|
46
|
+
Args:
|
|
47
|
+
process_id: ID of the process to stop.
|
|
48
|
+
|
|
49
|
+
Returns:
|
|
50
|
+
dict with:
|
|
51
|
+
- status: "stopped" if process was found and stopped,
|
|
52
|
+
"not_found" if process ID doesn't exist
|
|
53
|
+
- process_id: The process identifier
|
|
54
|
+
|
|
55
|
+
Examples:
|
|
56
|
+
- Stop a dev server when done testing
|
|
57
|
+
- Clean up processes before shutting down
|
|
58
|
+
"""
|
|
59
|
+
manager = _get_background_manager(context)
|
|
60
|
+
|
|
61
|
+
logger.info(f"Stopping background process: {process_id}")
|
|
62
|
+
success = await manager.stop_process(process_id)
|
|
63
|
+
|
|
64
|
+
return {
|
|
65
|
+
"status": "stopped" if success else "not_found",
|
|
66
|
+
"process_id": process_id
|
|
67
|
+
}
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Data types for terminal tools.
|
|
3
|
+
|
|
4
|
+
Contains result types returned by terminal operations.
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
from dataclasses import dataclass
|
|
8
|
+
from typing import Optional
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
@dataclass
|
|
12
|
+
class TerminalResult:
|
|
13
|
+
"""Result from run_bash.
|
|
14
|
+
|
|
15
|
+
Attributes:
|
|
16
|
+
stdout: Standard output captured from the command.
|
|
17
|
+
stderr: Standard error captured from the command (may be mixed with stdout in PTY).
|
|
18
|
+
exit_code: Exit code if available, None if not captured.
|
|
19
|
+
timed_out: True if command exceeded timeout.
|
|
20
|
+
"""
|
|
21
|
+
stdout: str
|
|
22
|
+
stderr: str
|
|
23
|
+
exit_code: Optional[int]
|
|
24
|
+
timed_out: bool
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
@dataclass
|
|
28
|
+
class BackgroundProcessOutput:
|
|
29
|
+
"""Result from get_process_output.
|
|
30
|
+
|
|
31
|
+
Attributes:
|
|
32
|
+
output: Recent output lines from the process.
|
|
33
|
+
is_running: True if process is still running.
|
|
34
|
+
process_id: The process identifier.
|
|
35
|
+
"""
|
|
36
|
+
output: str
|
|
37
|
+
is_running: bool
|
|
38
|
+
process_id: str
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
@dataclass
|
|
42
|
+
class ProcessInfo:
|
|
43
|
+
"""Information about a background process.
|
|
44
|
+
|
|
45
|
+
Attributes:
|
|
46
|
+
process_id: Unique identifier for the process.
|
|
47
|
+
command: The command that was executed.
|
|
48
|
+
started_at: Unix timestamp when process started.
|
|
49
|
+
is_running: True if process is still running.
|
|
50
|
+
"""
|
|
51
|
+
process_id: str
|
|
52
|
+
command: str
|
|
53
|
+
started_at: float
|
|
54
|
+
is_running: bool
|
|
@@ -0,0 +1,221 @@
|
|
|
1
|
+
"""
|
|
2
|
+
WSL + tmux backed terminal session implementation for Windows.
|
|
3
|
+
"""
|
|
4
|
+
|
|
5
|
+
from __future__ import annotations
|
|
6
|
+
|
|
7
|
+
import asyncio
|
|
8
|
+
import logging
|
|
9
|
+
import os
|
|
10
|
+
import re
|
|
11
|
+
import subprocess
|
|
12
|
+
from typing import Optional
|
|
13
|
+
|
|
14
|
+
from autobyteus.tools.terminal.wsl_utils import (
|
|
15
|
+
ensure_wsl_available,
|
|
16
|
+
ensure_wsl_distro_available,
|
|
17
|
+
select_wsl_distro,
|
|
18
|
+
windows_path_to_wsl,
|
|
19
|
+
)
|
|
20
|
+
|
|
21
|
+
logger = logging.getLogger(__name__)
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
class WslTmuxSession:
|
|
25
|
+
"""Terminal session backed by WSL + tmux (no pywinpty)."""
|
|
26
|
+
|
|
27
|
+
def __init__(self, session_id: str):
|
|
28
|
+
self._session_id = session_id
|
|
29
|
+
self._closed = False
|
|
30
|
+
self._wsl_exe: Optional[str] = None
|
|
31
|
+
self._distro: Optional[str] = None
|
|
32
|
+
self._session_name: Optional[str] = None
|
|
33
|
+
self._log_path: Optional[str] = None
|
|
34
|
+
self._output_offset = 0
|
|
35
|
+
|
|
36
|
+
@property
|
|
37
|
+
def session_id(self) -> str:
|
|
38
|
+
return self._session_id
|
|
39
|
+
|
|
40
|
+
@property
|
|
41
|
+
def is_alive(self) -> bool:
|
|
42
|
+
return not self._closed
|
|
43
|
+
|
|
44
|
+
async def start(self, cwd: str) -> None:
|
|
45
|
+
if os.name != "nt":
|
|
46
|
+
raise RuntimeError("WslTmuxSession is only supported on Windows.")
|
|
47
|
+
if self._session_name is not None:
|
|
48
|
+
raise RuntimeError("Session already started.")
|
|
49
|
+
|
|
50
|
+
self._wsl_exe = ensure_wsl_available()
|
|
51
|
+
ensure_wsl_distro_available(self._wsl_exe)
|
|
52
|
+
self._distro = select_wsl_distro(self._wsl_exe)
|
|
53
|
+
self._session_name = self._sanitize_session_name(self._session_id)
|
|
54
|
+
|
|
55
|
+
await asyncio.to_thread(self._ensure_tmux_available)
|
|
56
|
+
|
|
57
|
+
wsl_cwd = windows_path_to_wsl(cwd, wsl_exe=self._wsl_exe)
|
|
58
|
+
await asyncio.to_thread(
|
|
59
|
+
self._run_tmux,
|
|
60
|
+
[
|
|
61
|
+
"new-session",
|
|
62
|
+
"-d",
|
|
63
|
+
"-s",
|
|
64
|
+
self._session_name,
|
|
65
|
+
"-c",
|
|
66
|
+
wsl_cwd,
|
|
67
|
+
"-x",
|
|
68
|
+
"120",
|
|
69
|
+
"-y",
|
|
70
|
+
"40",
|
|
71
|
+
"/bin/bash",
|
|
72
|
+
"--noprofile",
|
|
73
|
+
"--norc",
|
|
74
|
+
"-i",
|
|
75
|
+
],
|
|
76
|
+
)
|
|
77
|
+
await asyncio.to_thread(
|
|
78
|
+
self._run_tmux,
|
|
79
|
+
["send-keys", "-t", self._session_name, "export PS1='$ '", "C-m"],
|
|
80
|
+
)
|
|
81
|
+
self._log_path = f"/tmp/autobyteus_tmux_{self._session_name}.log"
|
|
82
|
+
await asyncio.to_thread(self._reset_log)
|
|
83
|
+
await asyncio.to_thread(self._start_pipe)
|
|
84
|
+
|
|
85
|
+
logger.info(
|
|
86
|
+
"Started WSL tmux session %s in %s (distro=%s)",
|
|
87
|
+
self._session_name,
|
|
88
|
+
wsl_cwd,
|
|
89
|
+
self._distro,
|
|
90
|
+
)
|
|
91
|
+
|
|
92
|
+
async def write(self, data: bytes) -> None:
|
|
93
|
+
if self._closed:
|
|
94
|
+
raise RuntimeError("Session is closed")
|
|
95
|
+
if self._session_name is None:
|
|
96
|
+
raise RuntimeError("Session not started")
|
|
97
|
+
|
|
98
|
+
text = data.decode("utf-8", errors="replace")
|
|
99
|
+
text = text.replace("\r\n", "\n").replace("\r", "\n")
|
|
100
|
+
|
|
101
|
+
parts = text.split("\n")
|
|
102
|
+
for idx, part in enumerate(parts):
|
|
103
|
+
if part:
|
|
104
|
+
await asyncio.to_thread(
|
|
105
|
+
self._run_tmux,
|
|
106
|
+
["send-keys", "-t", self._session_name, "-l", part],
|
|
107
|
+
)
|
|
108
|
+
if idx < len(parts) - 1:
|
|
109
|
+
await asyncio.to_thread(
|
|
110
|
+
self._run_tmux,
|
|
111
|
+
["send-keys", "-t", self._session_name, "C-m"],
|
|
112
|
+
)
|
|
113
|
+
|
|
114
|
+
async def read(self, timeout: float = 0.1) -> Optional[bytes]:
|
|
115
|
+
if self._closed or self._session_name is None:
|
|
116
|
+
return None
|
|
117
|
+
data = await asyncio.to_thread(self._read_log_delta)
|
|
118
|
+
if not data:
|
|
119
|
+
if timeout:
|
|
120
|
+
await asyncio.sleep(timeout)
|
|
121
|
+
return None
|
|
122
|
+
return data
|
|
123
|
+
|
|
124
|
+
def resize(self, rows: int, cols: int) -> None:
|
|
125
|
+
if self._closed or self._session_name is None:
|
|
126
|
+
return
|
|
127
|
+
rows = max(1, int(rows))
|
|
128
|
+
cols = max(1, int(cols))
|
|
129
|
+
try:
|
|
130
|
+
self._run_tmux(
|
|
131
|
+
["resize-window", "-t", self._session_name, "-x", str(cols), "-y", str(rows)]
|
|
132
|
+
)
|
|
133
|
+
except Exception as exc:
|
|
134
|
+
logger.debug("Failed to resize tmux session %s: %s", self._session_name, exc)
|
|
135
|
+
|
|
136
|
+
async def close(self) -> None:
|
|
137
|
+
if self._closed:
|
|
138
|
+
return
|
|
139
|
+
self._closed = True
|
|
140
|
+
if self._session_name:
|
|
141
|
+
try:
|
|
142
|
+
await asyncio.to_thread(self._stop_pipe)
|
|
143
|
+
await asyncio.to_thread(
|
|
144
|
+
self._run_tmux, ["kill-session", "-t", self._session_name]
|
|
145
|
+
)
|
|
146
|
+
except Exception:
|
|
147
|
+
pass
|
|
148
|
+
self._session_name = None
|
|
149
|
+
self._log_path = None
|
|
150
|
+
self._output_offset = 0
|
|
151
|
+
logger.info("Closed WSL tmux session %s", self._session_id)
|
|
152
|
+
|
|
153
|
+
def _ensure_tmux_available(self) -> None:
|
|
154
|
+
try:
|
|
155
|
+
self._run_wsl_command(["tmux", "-V"], check=True)
|
|
156
|
+
except RuntimeError as exc:
|
|
157
|
+
raise RuntimeError(
|
|
158
|
+
"tmux is required in the WSL distro. Install with `sudo apt install tmux`."
|
|
159
|
+
) from exc
|
|
160
|
+
|
|
161
|
+
def _run_tmux(self, args: list[str]) -> subprocess.CompletedProcess:
|
|
162
|
+
return self._run_wsl_command(["tmux", *args], check=True)
|
|
163
|
+
|
|
164
|
+
def _reset_log(self) -> None:
|
|
165
|
+
if not self._log_path:
|
|
166
|
+
return
|
|
167
|
+
self._run_wsl_command(["sh", "-c", f"rm -f {self._log_path}; : > {self._log_path}"], check=True)
|
|
168
|
+
self._output_offset = 0
|
|
169
|
+
|
|
170
|
+
def _start_pipe(self) -> None:
|
|
171
|
+
if not self._log_path:
|
|
172
|
+
return
|
|
173
|
+
cmd = f"tmux pipe-pane -o -t {self._session_name}:0.0 'cat >> {self._log_path}'"
|
|
174
|
+
self._run_wsl_command(["sh", "-c", cmd], check=True)
|
|
175
|
+
|
|
176
|
+
def _stop_pipe(self) -> None:
|
|
177
|
+
if not self._session_name:
|
|
178
|
+
return
|
|
179
|
+
self._run_tmux(["pipe-pane", "-t", f"{self._session_name}:0.0"])
|
|
180
|
+
|
|
181
|
+
def _read_log_delta(self) -> bytes:
|
|
182
|
+
if not self._log_path:
|
|
183
|
+
return b""
|
|
184
|
+
cmd = (
|
|
185
|
+
f"if [ -f {self._log_path} ]; then "
|
|
186
|
+
f"dd if={self._log_path} bs=1 skip={self._output_offset} 2>/dev/null; "
|
|
187
|
+
f"fi"
|
|
188
|
+
)
|
|
189
|
+
result = self._run_wsl_command(["sh", "-c", cmd], check=True)
|
|
190
|
+
data = result.stdout or b""
|
|
191
|
+
self._output_offset += len(data)
|
|
192
|
+
return data
|
|
193
|
+
|
|
194
|
+
def _run_wsl_command(self, args: list[str], check: bool) -> subprocess.CompletedProcess:
|
|
195
|
+
if not self._wsl_exe or not self._distro:
|
|
196
|
+
raise RuntimeError("WSL session not initialized.")
|
|
197
|
+
cmd = [self._wsl_exe, "-d", self._distro, "--exec", *args]
|
|
198
|
+
result = subprocess.run(
|
|
199
|
+
cmd,
|
|
200
|
+
capture_output=True,
|
|
201
|
+
text=False,
|
|
202
|
+
check=False,
|
|
203
|
+
timeout=10,
|
|
204
|
+
)
|
|
205
|
+
if check and result.returncode != 0:
|
|
206
|
+
stderr = self._decode_output(result.stderr)
|
|
207
|
+
raise RuntimeError(stderr or "WSL command failed")
|
|
208
|
+
return result
|
|
209
|
+
|
|
210
|
+
@staticmethod
|
|
211
|
+
def _decode_output(raw: bytes) -> str:
|
|
212
|
+
if not raw:
|
|
213
|
+
return ""
|
|
214
|
+
if b"\x00" in raw:
|
|
215
|
+
return raw.decode("utf-16-le", errors="replace")
|
|
216
|
+
return raw.decode("utf-8", errors="replace")
|
|
217
|
+
|
|
218
|
+
@staticmethod
|
|
219
|
+
def _sanitize_session_name(session_id: str) -> str:
|
|
220
|
+
base = re.sub(r"[^a-zA-Z0-9_-]", "_", session_id)
|
|
221
|
+
return f"autobyteus_{base}"
|
|
@@ -0,0 +1,156 @@
|
|
|
1
|
+
"""
|
|
2
|
+
WSL utilities for Windows terminal backend.
|
|
3
|
+
"""
|
|
4
|
+
|
|
5
|
+
from __future__ import annotations
|
|
6
|
+
|
|
7
|
+
import pathlib
|
|
8
|
+
import shutil
|
|
9
|
+
import subprocess
|
|
10
|
+
from typing import List, Optional
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
_WSL_MISSING_MESSAGE = (
|
|
14
|
+
"WSL is not available. Install it with `wsl --install` and reboot, "
|
|
15
|
+
"then ensure a Linux distro is installed."
|
|
16
|
+
)
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
def find_wsl_executable() -> Optional[str]:
|
|
20
|
+
"""Return the path to wsl.exe (preferred) or wsl if available."""
|
|
21
|
+
return shutil.which("wsl.exe") or shutil.which("wsl")
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
def _decode_wsl_bytes(raw: bytes) -> str:
|
|
25
|
+
"""Decode WSL output that may be UTF-16LE on Windows consoles."""
|
|
26
|
+
if not raw:
|
|
27
|
+
return ""
|
|
28
|
+
if b"\x00" in raw:
|
|
29
|
+
return raw.decode("utf-16-le", errors="replace")
|
|
30
|
+
return raw.decode("utf-8", errors="replace")
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
def ensure_wsl_available() -> str:
|
|
34
|
+
"""Return the WSL executable path or raise with guidance."""
|
|
35
|
+
wsl_exe = find_wsl_executable()
|
|
36
|
+
if not wsl_exe:
|
|
37
|
+
raise RuntimeError(_WSL_MISSING_MESSAGE)
|
|
38
|
+
return wsl_exe
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
def list_wsl_distros(wsl_exe: str) -> List[str]:
|
|
42
|
+
"""Return a list of installed WSL distro names."""
|
|
43
|
+
result = subprocess.run(
|
|
44
|
+
[wsl_exe, "-l", "-q"],
|
|
45
|
+
capture_output=True,
|
|
46
|
+
text=False,
|
|
47
|
+
check=False,
|
|
48
|
+
timeout=5,
|
|
49
|
+
)
|
|
50
|
+
if result.returncode != 0:
|
|
51
|
+
return []
|
|
52
|
+
output = _decode_wsl_bytes(result.stdout)
|
|
53
|
+
return [line.strip() for line in output.splitlines() if line.strip()]
|
|
54
|
+
|
|
55
|
+
|
|
56
|
+
def get_default_wsl_distro(wsl_exe: str) -> Optional[str]:
|
|
57
|
+
"""Return the default WSL distro name if available."""
|
|
58
|
+
result = subprocess.run(
|
|
59
|
+
[wsl_exe, "-l", "-v"],
|
|
60
|
+
capture_output=True,
|
|
61
|
+
text=False,
|
|
62
|
+
check=False,
|
|
63
|
+
timeout=5,
|
|
64
|
+
)
|
|
65
|
+
if result.returncode != 0:
|
|
66
|
+
return None
|
|
67
|
+
output = _decode_wsl_bytes(result.stdout)
|
|
68
|
+
for line in output.splitlines():
|
|
69
|
+
stripped = line.strip()
|
|
70
|
+
if stripped.startswith("*"):
|
|
71
|
+
parts = stripped.split()
|
|
72
|
+
if len(parts) >= 2:
|
|
73
|
+
return parts[1]
|
|
74
|
+
return None
|
|
75
|
+
|
|
76
|
+
|
|
77
|
+
def select_wsl_distro(wsl_exe: str) -> str:
|
|
78
|
+
"""Select a usable WSL distro, preferring non-Docker defaults."""
|
|
79
|
+
distros = list_wsl_distros(wsl_exe)
|
|
80
|
+
if not distros:
|
|
81
|
+
raise RuntimeError(
|
|
82
|
+
"No WSL distro is installed. Run `wsl --install` "
|
|
83
|
+
"or install a distro from the Microsoft Store."
|
|
84
|
+
)
|
|
85
|
+
|
|
86
|
+
default = get_default_wsl_distro(wsl_exe)
|
|
87
|
+
excluded = {"docker-desktop", "docker-desktop-data"}
|
|
88
|
+
|
|
89
|
+
if default and default not in excluded:
|
|
90
|
+
return default
|
|
91
|
+
|
|
92
|
+
for distro in distros:
|
|
93
|
+
if distro and distro not in excluded:
|
|
94
|
+
return distro
|
|
95
|
+
|
|
96
|
+
return default or distros[0]
|
|
97
|
+
|
|
98
|
+
|
|
99
|
+
def ensure_wsl_distro_available(wsl_exe: str) -> None:
|
|
100
|
+
"""Raise if no WSL distro is installed."""
|
|
101
|
+
distros = list_wsl_distros(wsl_exe)
|
|
102
|
+
if not distros:
|
|
103
|
+
raise RuntimeError(
|
|
104
|
+
"No WSL distro is installed. Run `wsl --install` "
|
|
105
|
+
"or install a distro from the Microsoft Store."
|
|
106
|
+
)
|
|
107
|
+
|
|
108
|
+
|
|
109
|
+
def _run_wslpath(wsl_exe: str, path: str) -> Optional[str]:
|
|
110
|
+
"""Try to convert a Windows path to WSL path via wslpath."""
|
|
111
|
+
result = subprocess.run(
|
|
112
|
+
[wsl_exe, "wslpath", "-a", "-u", path],
|
|
113
|
+
capture_output=True,
|
|
114
|
+
text=False,
|
|
115
|
+
check=False,
|
|
116
|
+
timeout=5,
|
|
117
|
+
)
|
|
118
|
+
if result.returncode != 0:
|
|
119
|
+
return None
|
|
120
|
+
output = _decode_wsl_bytes(result.stdout).strip()
|
|
121
|
+
return output or None
|
|
122
|
+
|
|
123
|
+
|
|
124
|
+
def _manual_windows_path_to_wsl(path: str) -> str:
|
|
125
|
+
"""Manual conversion for Windows drive paths to /mnt/<drive>/..."""
|
|
126
|
+
windows_path = pathlib.PureWindowsPath(path)
|
|
127
|
+
|
|
128
|
+
if windows_path.drive:
|
|
129
|
+
drive_letter = windows_path.drive.rstrip(":").lower()
|
|
130
|
+
parts = windows_path.parts[1:] # strip drive
|
|
131
|
+
if parts:
|
|
132
|
+
return f"/mnt/{drive_letter}/" + "/".join(parts)
|
|
133
|
+
return f"/mnt/{drive_letter}"
|
|
134
|
+
|
|
135
|
+
raise ValueError(f"Unsupported Windows path format: {path}")
|
|
136
|
+
|
|
137
|
+
|
|
138
|
+
def windows_path_to_wsl(path: str, wsl_exe: Optional[str] = None) -> str:
|
|
139
|
+
"""Convert a Windows path to a WSL path, with wslpath fallback."""
|
|
140
|
+
if not path:
|
|
141
|
+
raise ValueError("Path must be a non-empty string.")
|
|
142
|
+
|
|
143
|
+
if path.startswith("/"):
|
|
144
|
+
return path
|
|
145
|
+
|
|
146
|
+
if path.startswith("\\\\"):
|
|
147
|
+
raise ValueError("UNC paths are not supported for WSL conversion.")
|
|
148
|
+
|
|
149
|
+
if wsl_exe is None:
|
|
150
|
+
wsl_exe = ensure_wsl_available()
|
|
151
|
+
|
|
152
|
+
wslpath = _run_wslpath(wsl_exe, path)
|
|
153
|
+
if wslpath:
|
|
154
|
+
return wslpath
|
|
155
|
+
|
|
156
|
+
return _manual_windows_path_to_wsl(path)
|
autobyteus/tools/tool_meta.py
CHANGED
|
@@ -35,26 +35,8 @@ class ToolMeta(ABCMeta):
|
|
|
35
35
|
logger.error(f"Tool class {name} ({tool_name}) must return a valid string from get_description(). Skipping registration.")
|
|
36
36
|
return
|
|
37
37
|
|
|
38
|
-
|
|
39
|
-
try:
|
|
40
|
-
argument_schema = cls.get_argument_schema()
|
|
41
|
-
if argument_schema is not None and not isinstance(argument_schema, ParameterSchema):
|
|
42
|
-
logger.error(f"Tool class {name} ({tool_name}) get_argument_schema() must return a ParameterSchema or None. Got {type(argument_schema)}. Skipping registration.")
|
|
43
|
-
return
|
|
44
|
-
except Exception as e:
|
|
45
|
-
logger.error(f"Tool class {name} ({tool_name}) failed to provide argument_schema via get_argument_schema(): {e}. Skipping registration.", exc_info=True)
|
|
46
|
-
return
|
|
38
|
+
# Note: We do not call the schema methods here. We pass them as providers.
|
|
47
39
|
|
|
48
|
-
instantiation_config_schema: ParameterSchema = None
|
|
49
|
-
if hasattr(cls, 'get_config_schema'):
|
|
50
|
-
try:
|
|
51
|
-
instantiation_config_schema = cls.get_config_schema()
|
|
52
|
-
if instantiation_config_schema is not None and not isinstance(instantiation_config_schema, ParameterSchema):
|
|
53
|
-
logger.warning(f"Tool class {name} ({tool_name}) get_config_schema() returned non-ParameterSchema type: {type(instantiation_config_schema)}. Treating as no config schema.")
|
|
54
|
-
instantiation_config_schema = None
|
|
55
|
-
except Exception as e:
|
|
56
|
-
logger.warning(f"Tool class {name} ({tool_name}) has get_config_schema() but it failed: {e}. Assuming no instantiation config.")
|
|
57
|
-
|
|
58
40
|
# Get category from class attribute, defaulting to "General"
|
|
59
41
|
category_str = getattr(cls, 'CATEGORY', ToolCategory.GENERAL)
|
|
60
42
|
|
|
@@ -64,16 +46,14 @@ class ToolMeta(ABCMeta):
|
|
|
64
46
|
description=general_description,
|
|
65
47
|
tool_class=cls,
|
|
66
48
|
custom_factory=None,
|
|
67
|
-
|
|
68
|
-
|
|
49
|
+
argument_schema_provider=cls.get_argument_schema,
|
|
50
|
+
config_schema_provider=cls.get_config_schema,
|
|
69
51
|
origin=ToolOrigin.LOCAL,
|
|
70
52
|
category=category_str
|
|
71
53
|
)
|
|
72
54
|
default_tool_registry.register_tool(definition)
|
|
73
55
|
|
|
74
|
-
|
|
75
|
-
config_info = f"inst_config: {len(instantiation_config_schema) if instantiation_config_schema else '0'}"
|
|
76
|
-
logger.info(f"Auto-registered tool: '{tool_name}' from class {name} ({arg_schema_info}, {config_info})")
|
|
56
|
+
logger.info(f"Auto-registered tool: '{tool_name}' from class {name}")
|
|
77
57
|
|
|
78
58
|
except AttributeError as e:
|
|
79
59
|
logger.error(f"Tool class {name} is missing a required method ({e}). Skipping registration.")
|