autobyteus 1.2.1__py3-none-any.whl → 1.3.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- autobyteus/agent/agent.py +15 -5
- autobyteus/agent/bootstrap_steps/__init__.py +3 -3
- autobyteus/agent/bootstrap_steps/agent_bootstrapper.py +5 -59
- autobyteus/agent/bootstrap_steps/base_bootstrap_step.py +1 -4
- autobyteus/agent/bootstrap_steps/mcp_server_prewarming_step.py +1 -3
- autobyteus/agent/bootstrap_steps/system_prompt_processing_step.py +16 -13
- autobyteus/agent/bootstrap_steps/working_context_snapshot_restore_step.py +38 -0
- autobyteus/agent/bootstrap_steps/workspace_context_initialization_step.py +2 -4
- autobyteus/agent/context/agent_config.py +47 -20
- autobyteus/agent/context/agent_context.py +23 -18
- autobyteus/agent/context/agent_runtime_state.py +21 -19
- autobyteus/agent/events/__init__.py +16 -1
- autobyteus/agent/events/agent_events.py +43 -3
- autobyteus/agent/events/agent_input_event_queue_manager.py +79 -26
- autobyteus/agent/events/event_store.py +57 -0
- autobyteus/agent/events/notifiers.py +69 -59
- autobyteus/agent/events/worker_event_dispatcher.py +21 -64
- autobyteus/agent/factory/agent_factory.py +83 -6
- autobyteus/agent/handlers/__init__.py +2 -0
- autobyteus/agent/handlers/approved_tool_invocation_event_handler.py +51 -34
- autobyteus/agent/handlers/bootstrap_event_handler.py +155 -0
- autobyteus/agent/handlers/inter_agent_message_event_handler.py +10 -0
- autobyteus/agent/handlers/lifecycle_event_logger.py +19 -11
- autobyteus/agent/handlers/llm_complete_response_received_event_handler.py +10 -15
- autobyteus/agent/handlers/llm_user_message_ready_event_handler.py +188 -48
- autobyteus/agent/handlers/tool_execution_approval_event_handler.py +0 -10
- autobyteus/agent/handlers/tool_invocation_request_event_handler.py +53 -48
- autobyteus/agent/handlers/tool_result_event_handler.py +7 -8
- autobyteus/agent/handlers/user_input_message_event_handler.py +10 -3
- autobyteus/agent/input_processor/memory_ingest_input_processor.py +44 -0
- autobyteus/agent/lifecycle/__init__.py +12 -0
- autobyteus/agent/lifecycle/base_processor.py +109 -0
- autobyteus/agent/lifecycle/events.py +35 -0
- autobyteus/agent/lifecycle/processor_definition.py +36 -0
- autobyteus/agent/lifecycle/processor_registry.py +106 -0
- autobyteus/agent/llm_request_assembler.py +98 -0
- autobyteus/agent/llm_response_processor/__init__.py +1 -8
- autobyteus/agent/message/context_file_type.py +1 -1
- autobyteus/agent/runtime/agent_runtime.py +29 -21
- autobyteus/agent/runtime/agent_worker.py +98 -19
- autobyteus/agent/shutdown_steps/__init__.py +2 -0
- autobyteus/agent/shutdown_steps/agent_shutdown_orchestrator.py +2 -0
- autobyteus/agent/shutdown_steps/tool_cleanup_step.py +58 -0
- autobyteus/agent/status/__init__.py +14 -0
- autobyteus/agent/status/manager.py +93 -0
- autobyteus/agent/status/status_deriver.py +96 -0
- autobyteus/agent/{phases/phase_enum.py → status/status_enum.py} +16 -16
- autobyteus/agent/status/status_update_utils.py +73 -0
- autobyteus/agent/streaming/__init__.py +52 -5
- autobyteus/agent/streaming/adapters/__init__.py +18 -0
- autobyteus/agent/streaming/adapters/invocation_adapter.py +184 -0
- autobyteus/agent/streaming/adapters/tool_call_parsing.py +163 -0
- autobyteus/agent/streaming/adapters/tool_syntax_registry.py +67 -0
- autobyteus/agent/streaming/agent_event_stream.py +3 -183
- autobyteus/agent/streaming/api_tool_call/__init__.py +16 -0
- autobyteus/agent/streaming/api_tool_call/file_content_streamer.py +56 -0
- autobyteus/agent/streaming/api_tool_call/json_string_field_extractor.py +175 -0
- autobyteus/agent/streaming/api_tool_call_streaming_response_handler.py +4 -0
- autobyteus/agent/streaming/events/__init__.py +6 -0
- autobyteus/agent/streaming/events/stream_event_payloads.py +284 -0
- autobyteus/agent/streaming/events/stream_events.py +141 -0
- autobyteus/agent/streaming/handlers/__init__.py +15 -0
- autobyteus/agent/streaming/handlers/api_tool_call_streaming_response_handler.py +303 -0
- autobyteus/agent/streaming/handlers/parsing_streaming_response_handler.py +107 -0
- autobyteus/agent/streaming/handlers/pass_through_streaming_response_handler.py +107 -0
- autobyteus/agent/streaming/handlers/streaming_handler_factory.py +177 -0
- autobyteus/agent/streaming/handlers/streaming_response_handler.py +58 -0
- autobyteus/agent/streaming/parser/__init__.py +61 -0
- autobyteus/agent/streaming/parser/event_emitter.py +181 -0
- autobyteus/agent/streaming/parser/events.py +4 -0
- autobyteus/agent/streaming/parser/invocation_adapter.py +4 -0
- autobyteus/agent/streaming/parser/json_parsing_strategies/__init__.py +19 -0
- autobyteus/agent/streaming/parser/json_parsing_strategies/base.py +32 -0
- autobyteus/agent/streaming/parser/json_parsing_strategies/default.py +34 -0
- autobyteus/agent/streaming/parser/json_parsing_strategies/gemini.py +31 -0
- autobyteus/agent/streaming/parser/json_parsing_strategies/openai.py +64 -0
- autobyteus/agent/streaming/parser/json_parsing_strategies/registry.py +75 -0
- autobyteus/agent/streaming/parser/parser_context.py +227 -0
- autobyteus/agent/streaming/parser/parser_factory.py +132 -0
- autobyteus/agent/streaming/parser/sentinel_format.py +7 -0
- autobyteus/agent/streaming/parser/state_factory.py +62 -0
- autobyteus/agent/streaming/parser/states/__init__.py +1 -0
- autobyteus/agent/streaming/parser/states/base_state.py +60 -0
- autobyteus/agent/streaming/parser/states/custom_xml_tag_run_bash_parsing_state.py +38 -0
- autobyteus/agent/streaming/parser/states/custom_xml_tag_write_file_parsing_state.py +55 -0
- autobyteus/agent/streaming/parser/states/delimited_content_state.py +146 -0
- autobyteus/agent/streaming/parser/states/json_initialization_state.py +144 -0
- autobyteus/agent/streaming/parser/states/json_tool_parsing_state.py +137 -0
- autobyteus/agent/streaming/parser/states/sentinel_content_state.py +30 -0
- autobyteus/agent/streaming/parser/states/sentinel_initialization_state.py +117 -0
- autobyteus/agent/streaming/parser/states/text_state.py +78 -0
- autobyteus/agent/streaming/parser/states/xml_patch_file_tool_parsing_state.py +328 -0
- autobyteus/agent/streaming/parser/states/xml_run_bash_tool_parsing_state.py +129 -0
- autobyteus/agent/streaming/parser/states/xml_tag_initialization_state.py +151 -0
- autobyteus/agent/streaming/parser/states/xml_tool_parsing_state.py +63 -0
- autobyteus/agent/streaming/parser/states/xml_write_file_tool_parsing_state.py +343 -0
- autobyteus/agent/streaming/parser/strategies/__init__.py +17 -0
- autobyteus/agent/streaming/parser/strategies/base.py +24 -0
- autobyteus/agent/streaming/parser/strategies/json_tool_strategy.py +26 -0
- autobyteus/agent/streaming/parser/strategies/registry.py +28 -0
- autobyteus/agent/streaming/parser/strategies/sentinel_strategy.py +23 -0
- autobyteus/agent/streaming/parser/strategies/xml_tag_strategy.py +21 -0
- autobyteus/agent/streaming/parser/stream_scanner.py +167 -0
- autobyteus/agent/streaming/parser/streaming_parser.py +212 -0
- autobyteus/agent/streaming/parser/tool_call_parsing.py +4 -0
- autobyteus/agent/streaming/parser/tool_constants.py +7 -0
- autobyteus/agent/streaming/parser/tool_syntax_registry.py +4 -0
- autobyteus/agent/streaming/parser/xml_tool_parsing_state_registry.py +55 -0
- autobyteus/agent/streaming/parsing_streaming_response_handler.py +4 -0
- autobyteus/agent/streaming/pass_through_streaming_response_handler.py +4 -0
- autobyteus/agent/streaming/queue_streamer.py +3 -57
- autobyteus/agent/streaming/segments/__init__.py +5 -0
- autobyteus/agent/streaming/segments/segment_events.py +82 -0
- autobyteus/agent/streaming/stream_event_payloads.py +2 -223
- autobyteus/agent/streaming/stream_events.py +3 -140
- autobyteus/agent/streaming/streaming_handler_factory.py +4 -0
- autobyteus/agent/streaming/streaming_response_handler.py +4 -0
- autobyteus/agent/streaming/streams/__init__.py +5 -0
- autobyteus/agent/streaming/streams/agent_event_stream.py +197 -0
- autobyteus/agent/streaming/utils/__init__.py +5 -0
- autobyteus/agent/streaming/utils/queue_streamer.py +59 -0
- autobyteus/agent/system_prompt_processor/__init__.py +2 -0
- autobyteus/agent/system_prompt_processor/available_skills_processor.py +96 -0
- autobyteus/agent/system_prompt_processor/base_processor.py +1 -1
- autobyteus/agent/system_prompt_processor/processor_meta.py +15 -2
- autobyteus/agent/system_prompt_processor/tool_manifest_injector_processor.py +39 -58
- autobyteus/agent/token_budget.py +56 -0
- autobyteus/agent/tool_execution_result_processor/memory_ingest_tool_result_processor.py +29 -0
- autobyteus/agent/tool_invocation.py +16 -40
- autobyteus/agent/tool_invocation_preprocessor/__init__.py +9 -0
- autobyteus/agent/tool_invocation_preprocessor/base_preprocessor.py +45 -0
- autobyteus/agent/tool_invocation_preprocessor/processor_definition.py +15 -0
- autobyteus/agent/tool_invocation_preprocessor/processor_meta.py +33 -0
- autobyteus/agent/tool_invocation_preprocessor/processor_registry.py +60 -0
- autobyteus/agent/utils/wait_for_idle.py +12 -14
- autobyteus/agent/workspace/base_workspace.py +6 -27
- autobyteus/agent_team/agent_team.py +3 -3
- autobyteus/agent_team/agent_team_builder.py +1 -41
- autobyteus/agent_team/bootstrap_steps/__init__.py +0 -4
- autobyteus/agent_team/bootstrap_steps/agent_configuration_preparation_step.py +8 -18
- autobyteus/agent_team/bootstrap_steps/agent_team_bootstrapper.py +4 -16
- autobyteus/agent_team/bootstrap_steps/base_agent_team_bootstrap_step.py +1 -2
- autobyteus/agent_team/bootstrap_steps/coordinator_initialization_step.py +1 -2
- autobyteus/agent_team/bootstrap_steps/task_notifier_initialization_step.py +1 -2
- autobyteus/agent_team/bootstrap_steps/team_context_initialization_step.py +4 -4
- autobyteus/agent_team/context/agent_team_config.py +6 -3
- autobyteus/agent_team/context/agent_team_context.py +25 -3
- autobyteus/agent_team/context/agent_team_runtime_state.py +9 -6
- autobyteus/agent_team/events/__init__.py +11 -0
- autobyteus/agent_team/events/agent_team_event_dispatcher.py +22 -9
- autobyteus/agent_team/events/agent_team_events.py +16 -0
- autobyteus/agent_team/events/event_store.py +57 -0
- autobyteus/agent_team/factory/agent_team_factory.py +8 -0
- autobyteus/agent_team/handlers/inter_agent_message_request_event_handler.py +18 -2
- autobyteus/agent_team/handlers/lifecycle_agent_team_event_handler.py +21 -5
- autobyteus/agent_team/handlers/process_user_message_event_handler.py +17 -8
- autobyteus/agent_team/handlers/tool_approval_team_event_handler.py +19 -4
- autobyteus/agent_team/runtime/agent_team_runtime.py +41 -10
- autobyteus/agent_team/runtime/agent_team_worker.py +69 -5
- autobyteus/agent_team/status/__init__.py +14 -0
- autobyteus/agent_team/status/agent_team_status.py +18 -0
- autobyteus/agent_team/status/agent_team_status_manager.py +33 -0
- autobyteus/agent_team/status/status_deriver.py +62 -0
- autobyteus/agent_team/status/status_update_utils.py +42 -0
- autobyteus/agent_team/streaming/__init__.py +2 -2
- autobyteus/agent_team/streaming/agent_team_event_notifier.py +6 -6
- autobyteus/agent_team/streaming/agent_team_stream_event_payloads.py +4 -4
- autobyteus/agent_team/streaming/agent_team_stream_events.py +3 -3
- autobyteus/agent_team/system_prompt_processor/__init__.py +6 -0
- autobyteus/agent_team/system_prompt_processor/team_manifest_injector_processor.py +76 -0
- autobyteus/agent_team/task_notification/task_notification_mode.py +19 -0
- autobyteus/agent_team/utils/wait_for_idle.py +4 -4
- autobyteus/cli/agent_cli.py +18 -10
- autobyteus/cli/agent_team_tui/app.py +14 -11
- autobyteus/cli/agent_team_tui/state.py +13 -15
- autobyteus/cli/agent_team_tui/widgets/agent_list_sidebar.py +15 -15
- autobyteus/cli/agent_team_tui/widgets/focus_pane.py +143 -36
- autobyteus/cli/agent_team_tui/widgets/renderables.py +1 -1
- autobyteus/cli/agent_team_tui/widgets/shared.py +25 -25
- autobyteus/cli/cli_display.py +193 -44
- autobyteus/cli/workflow_tui/app.py +9 -10
- autobyteus/cli/workflow_tui/state.py +14 -16
- autobyteus/cli/workflow_tui/widgets/agent_list_sidebar.py +15 -15
- autobyteus/cli/workflow_tui/widgets/focus_pane.py +137 -35
- autobyteus/cli/workflow_tui/widgets/renderables.py +1 -1
- autobyteus/cli/workflow_tui/widgets/shared.py +25 -25
- autobyteus/clients/autobyteus_client.py +94 -1
- autobyteus/events/event_types.py +11 -18
- autobyteus/llm/api/autobyteus_llm.py +33 -29
- autobyteus/llm/api/claude_llm.py +142 -36
- autobyteus/llm/api/gemini_llm.py +163 -59
- autobyteus/llm/api/grok_llm.py +1 -1
- autobyteus/llm/api/minimax_llm.py +26 -0
- autobyteus/llm/api/mistral_llm.py +113 -87
- autobyteus/llm/api/ollama_llm.py +9 -42
- autobyteus/llm/api/openai_compatible_llm.py +127 -91
- autobyteus/llm/api/openai_llm.py +3 -3
- autobyteus/llm/api/openai_responses_llm.py +324 -0
- autobyteus/llm/api/zhipu_llm.py +21 -2
- autobyteus/llm/autobyteus_provider.py +70 -60
- autobyteus/llm/base_llm.py +85 -81
- autobyteus/llm/converters/__init__.py +14 -0
- autobyteus/llm/converters/anthropic_tool_call_converter.py +37 -0
- autobyteus/llm/converters/gemini_tool_call_converter.py +57 -0
- autobyteus/llm/converters/mistral_tool_call_converter.py +37 -0
- autobyteus/llm/converters/openai_tool_call_converter.py +38 -0
- autobyteus/llm/extensions/base_extension.py +6 -12
- autobyteus/llm/extensions/token_usage_tracking_extension.py +45 -18
- autobyteus/llm/llm_factory.py +282 -204
- autobyteus/llm/lmstudio_provider.py +60 -49
- autobyteus/llm/models.py +35 -2
- autobyteus/llm/ollama_provider.py +60 -49
- autobyteus/llm/ollama_provider_resolver.py +0 -1
- autobyteus/llm/prompt_renderers/__init__.py +19 -0
- autobyteus/llm/prompt_renderers/anthropic_prompt_renderer.py +104 -0
- autobyteus/llm/prompt_renderers/autobyteus_prompt_renderer.py +19 -0
- autobyteus/llm/prompt_renderers/base_prompt_renderer.py +10 -0
- autobyteus/llm/prompt_renderers/gemini_prompt_renderer.py +63 -0
- autobyteus/llm/prompt_renderers/mistral_prompt_renderer.py +87 -0
- autobyteus/llm/prompt_renderers/ollama_prompt_renderer.py +51 -0
- autobyteus/llm/prompt_renderers/openai_chat_renderer.py +97 -0
- autobyteus/llm/prompt_renderers/openai_responses_renderer.py +101 -0
- autobyteus/llm/providers.py +1 -3
- autobyteus/llm/token_counter/claude_token_counter.py +56 -25
- autobyteus/llm/token_counter/mistral_token_counter.py +12 -8
- autobyteus/llm/token_counter/openai_token_counter.py +24 -5
- autobyteus/llm/token_counter/token_counter_factory.py +12 -5
- autobyteus/llm/utils/llm_config.py +6 -12
- autobyteus/llm/utils/media_payload_formatter.py +27 -20
- autobyteus/llm/utils/messages.py +55 -3
- autobyteus/llm/utils/response_types.py +3 -0
- autobyteus/llm/utils/tool_call_delta.py +31 -0
- autobyteus/memory/__init__.py +35 -0
- autobyteus/memory/compaction/__init__.py +9 -0
- autobyteus/memory/compaction/compaction_result.py +8 -0
- autobyteus/memory/compaction/compactor.py +89 -0
- autobyteus/memory/compaction/summarizer.py +11 -0
- autobyteus/memory/compaction_snapshot_builder.py +84 -0
- autobyteus/memory/memory_manager.py +205 -0
- autobyteus/memory/models/__init__.py +14 -0
- autobyteus/memory/models/episodic_item.py +41 -0
- autobyteus/memory/models/memory_types.py +7 -0
- autobyteus/memory/models/raw_trace_item.py +79 -0
- autobyteus/memory/models/semantic_item.py +41 -0
- autobyteus/memory/models/tool_interaction.py +20 -0
- autobyteus/memory/path_resolver.py +27 -0
- autobyteus/memory/policies/__init__.py +5 -0
- autobyteus/memory/policies/compaction_policy.py +16 -0
- autobyteus/memory/restore/__init__.py +1 -0
- autobyteus/memory/restore/working_context_snapshot_bootstrapper.py +61 -0
- autobyteus/memory/retrieval/__init__.py +7 -0
- autobyteus/memory/retrieval/memory_bundle.py +11 -0
- autobyteus/memory/retrieval/retriever.py +13 -0
- autobyteus/memory/store/__init__.py +9 -0
- autobyteus/memory/store/base_store.py +14 -0
- autobyteus/memory/store/file_store.py +98 -0
- autobyteus/memory/store/working_context_snapshot_store.py +28 -0
- autobyteus/memory/tool_interaction_builder.py +46 -0
- autobyteus/memory/turn_tracker.py +9 -0
- autobyteus/memory/working_context_snapshot.py +69 -0
- autobyteus/memory/working_context_snapshot_serializer.py +135 -0
- autobyteus/multimedia/audio/api/autobyteus_audio_client.py +19 -5
- autobyteus/multimedia/audio/api/gemini_audio_client.py +109 -16
- autobyteus/multimedia/audio/audio_client_factory.py +47 -9
- autobyteus/multimedia/audio/audio_model.py +2 -1
- autobyteus/multimedia/image/api/autobyteus_image_client.py +19 -5
- autobyteus/multimedia/image/api/gemini_image_client.py +39 -17
- autobyteus/multimedia/image/api/openai_image_client.py +125 -43
- autobyteus/multimedia/image/autobyteus_image_provider.py +2 -1
- autobyteus/multimedia/image/image_client_factory.py +47 -15
- autobyteus/multimedia/image/image_model.py +5 -2
- autobyteus/multimedia/providers.py +3 -2
- autobyteus/skills/loader.py +71 -0
- autobyteus/skills/model.py +11 -0
- autobyteus/skills/registry.py +70 -0
- autobyteus/task_management/tools/todo_tools/add_todo.py +2 -2
- autobyteus/task_management/tools/todo_tools/create_todo_list.py +2 -2
- autobyteus/task_management/tools/todo_tools/update_todo_status.py +2 -2
- autobyteus/tools/__init__.py +34 -47
- autobyteus/tools/base_tool.py +7 -0
- autobyteus/tools/file/__init__.py +2 -6
- autobyteus/tools/file/patch_file.py +149 -0
- autobyteus/tools/file/read_file.py +36 -5
- autobyteus/tools/file/write_file.py +4 -1
- autobyteus/tools/functional_tool.py +43 -6
- autobyteus/tools/mcp/__init__.py +2 -0
- autobyteus/tools/mcp/config_service.py +5 -1
- autobyteus/tools/mcp/server/__init__.py +2 -0
- autobyteus/tools/mcp/server/http_managed_mcp_server.py +1 -1
- autobyteus/tools/mcp/server/websocket_managed_mcp_server.py +141 -0
- autobyteus/tools/mcp/server_instance_manager.py +8 -1
- autobyteus/tools/mcp/types.py +61 -0
- autobyteus/tools/multimedia/audio_tools.py +70 -17
- autobyteus/tools/multimedia/download_media_tool.py +18 -4
- autobyteus/tools/multimedia/image_tools.py +246 -62
- autobyteus/tools/operation_executor/journal_manager.py +107 -0
- autobyteus/tools/operation_executor/operation_event_buffer.py +57 -0
- autobyteus/tools/operation_executor/operation_event_producer.py +29 -0
- autobyteus/tools/operation_executor/operation_executor.py +58 -0
- autobyteus/tools/registry/tool_definition.py +43 -2
- autobyteus/tools/skill/load_skill.py +50 -0
- autobyteus/tools/terminal/__init__.py +45 -0
- autobyteus/tools/terminal/ansi_utils.py +32 -0
- autobyteus/tools/terminal/background_process_manager.py +233 -0
- autobyteus/tools/terminal/output_buffer.py +105 -0
- autobyteus/tools/terminal/prompt_detector.py +63 -0
- autobyteus/tools/terminal/pty_session.py +241 -0
- autobyteus/tools/terminal/session_factory.py +20 -0
- autobyteus/tools/terminal/terminal_session_manager.py +226 -0
- autobyteus/tools/terminal/tools/__init__.py +13 -0
- autobyteus/tools/terminal/tools/get_process_output.py +81 -0
- autobyteus/tools/terminal/tools/run_bash.py +109 -0
- autobyteus/tools/terminal/tools/start_background_process.py +104 -0
- autobyteus/tools/terminal/tools/stop_background_process.py +67 -0
- autobyteus/tools/terminal/types.py +54 -0
- autobyteus/tools/terminal/wsl_tmux_session.py +221 -0
- autobyteus/tools/terminal/wsl_utils.py +156 -0
- autobyteus/tools/transaction_management/backup_handler.py +48 -0
- autobyteus/tools/transaction_management/operation_lifecycle_manager.py +62 -0
- autobyteus/tools/usage/__init__.py +1 -2
- autobyteus/tools/usage/formatters/__init__.py +17 -1
- autobyteus/tools/usage/formatters/base_formatter.py +8 -0
- autobyteus/tools/usage/formatters/default_xml_schema_formatter.py +2 -2
- autobyteus/tools/usage/formatters/mistral_json_schema_formatter.py +18 -0
- autobyteus/tools/usage/formatters/patch_file_xml_example_formatter.py +64 -0
- autobyteus/tools/usage/formatters/patch_file_xml_schema_formatter.py +31 -0
- autobyteus/tools/usage/formatters/run_bash_xml_example_formatter.py +32 -0
- autobyteus/tools/usage/formatters/run_bash_xml_schema_formatter.py +36 -0
- autobyteus/tools/usage/formatters/write_file_xml_example_formatter.py +53 -0
- autobyteus/tools/usage/formatters/write_file_xml_schema_formatter.py +31 -0
- autobyteus/tools/usage/providers/tool_manifest_provider.py +10 -10
- autobyteus/tools/usage/registries/__init__.py +1 -3
- autobyteus/tools/usage/registries/tool_formatting_registry.py +115 -8
- autobyteus/tools/usage/tool_schema_provider.py +51 -0
- autobyteus/tools/web/__init__.py +4 -0
- autobyteus/tools/web/read_url_tool.py +80 -0
- autobyteus/utils/diff_utils.py +271 -0
- autobyteus/utils/download_utils.py +109 -0
- autobyteus/utils/file_utils.py +57 -2
- autobyteus/utils/gemini_helper.py +64 -0
- autobyteus/utils/gemini_model_mapping.py +71 -0
- autobyteus/utils/llm_output_formatter.py +75 -0
- autobyteus/utils/tool_call_format.py +36 -0
- autobyteus/workflow/agentic_workflow.py +3 -3
- autobyteus/workflow/bootstrap_steps/agent_tool_injection_step.py +2 -2
- autobyteus/workflow/bootstrap_steps/base_workflow_bootstrap_step.py +2 -2
- autobyteus/workflow/bootstrap_steps/coordinator_initialization_step.py +2 -2
- autobyteus/workflow/bootstrap_steps/coordinator_prompt_preparation_step.py +3 -9
- autobyteus/workflow/bootstrap_steps/workflow_bootstrapper.py +6 -6
- autobyteus/workflow/bootstrap_steps/workflow_runtime_queue_initialization_step.py +2 -2
- autobyteus/workflow/context/workflow_context.py +3 -3
- autobyteus/workflow/context/workflow_runtime_state.py +5 -5
- autobyteus/workflow/events/workflow_event_dispatcher.py +5 -5
- autobyteus/workflow/handlers/lifecycle_workflow_event_handler.py +3 -3
- autobyteus/workflow/handlers/process_user_message_event_handler.py +5 -5
- autobyteus/workflow/handlers/tool_approval_workflow_event_handler.py +2 -2
- autobyteus/workflow/runtime/workflow_runtime.py +8 -8
- autobyteus/workflow/runtime/workflow_worker.py +3 -3
- autobyteus/workflow/status/__init__.py +11 -0
- autobyteus/workflow/status/workflow_status.py +19 -0
- autobyteus/workflow/status/workflow_status_manager.py +48 -0
- autobyteus/workflow/streaming/__init__.py +2 -2
- autobyteus/workflow/streaming/workflow_event_notifier.py +7 -7
- autobyteus/workflow/streaming/workflow_stream_event_payloads.py +4 -4
- autobyteus/workflow/streaming/workflow_stream_events.py +3 -3
- autobyteus/workflow/utils/wait_for_idle.py +4 -4
- autobyteus-1.3.0.dist-info/METADATA +293 -0
- autobyteus-1.3.0.dist-info/RECORD +606 -0
- {autobyteus-1.2.1.dist-info → autobyteus-1.3.0.dist-info}/WHEEL +1 -1
- {autobyteus-1.2.1.dist-info → autobyteus-1.3.0.dist-info}/top_level.txt +0 -1
- autobyteus/agent/bootstrap_steps/agent_runtime_queue_initialization_step.py +0 -57
- autobyteus/agent/hooks/__init__.py +0 -16
- autobyteus/agent/hooks/base_phase_hook.py +0 -78
- autobyteus/agent/hooks/hook_definition.py +0 -36
- autobyteus/agent/hooks/hook_meta.py +0 -37
- autobyteus/agent/hooks/hook_registry.py +0 -106
- autobyteus/agent/llm_response_processor/provider_aware_tool_usage_processor.py +0 -103
- autobyteus/agent/phases/__init__.py +0 -18
- autobyteus/agent/phases/discover.py +0 -53
- autobyteus/agent/phases/manager.py +0 -265
- autobyteus/agent/phases/transition_decorator.py +0 -40
- autobyteus/agent/phases/transition_info.py +0 -33
- autobyteus/agent/remote_agent.py +0 -244
- autobyteus/agent/workspace/workspace_definition.py +0 -36
- autobyteus/agent/workspace/workspace_meta.py +0 -37
- autobyteus/agent/workspace/workspace_registry.py +0 -72
- autobyteus/agent_team/bootstrap_steps/agent_team_runtime_queue_initialization_step.py +0 -25
- autobyteus/agent_team/bootstrap_steps/coordinator_prompt_preparation_step.py +0 -85
- autobyteus/agent_team/phases/__init__.py +0 -11
- autobyteus/agent_team/phases/agent_team_operational_phase.py +0 -19
- autobyteus/agent_team/phases/agent_team_phase_manager.py +0 -48
- autobyteus/llm/api/bedrock_llm.py +0 -92
- autobyteus/llm/api/groq_llm.py +0 -94
- autobyteus/llm/api/nvidia_llm.py +0 -108
- autobyteus/llm/utils/token_pricing_config.py +0 -87
- autobyteus/rpc/__init__.py +0 -73
- autobyteus/rpc/client/__init__.py +0 -17
- autobyteus/rpc/client/abstract_client_connection.py +0 -124
- autobyteus/rpc/client/client_connection_manager.py +0 -153
- autobyteus/rpc/client/sse_client_connection.py +0 -306
- autobyteus/rpc/client/stdio_client_connection.py +0 -280
- autobyteus/rpc/config/__init__.py +0 -13
- autobyteus/rpc/config/agent_server_config.py +0 -153
- autobyteus/rpc/config/agent_server_registry.py +0 -152
- autobyteus/rpc/hosting.py +0 -244
- autobyteus/rpc/protocol.py +0 -244
- autobyteus/rpc/server/__init__.py +0 -20
- autobyteus/rpc/server/agent_server_endpoint.py +0 -181
- autobyteus/rpc/server/base_method_handler.py +0 -40
- autobyteus/rpc/server/method_handlers.py +0 -259
- autobyteus/rpc/server/sse_server_handler.py +0 -182
- autobyteus/rpc/server/stdio_server_handler.py +0 -151
- autobyteus/rpc/server_main.py +0 -198
- autobyteus/rpc/transport_type.py +0 -13
- autobyteus/tools/bash/__init__.py +0 -2
- autobyteus/tools/bash/bash_executor.py +0 -100
- autobyteus/tools/browser/__init__.py +0 -2
- autobyteus/tools/browser/session_aware/browser_session_aware_navigate_to.py +0 -75
- autobyteus/tools/browser/session_aware/browser_session_aware_tool.py +0 -30
- autobyteus/tools/browser/session_aware/browser_session_aware_web_element_trigger.py +0 -154
- autobyteus/tools/browser/session_aware/browser_session_aware_webpage_reader.py +0 -89
- autobyteus/tools/browser/session_aware/browser_session_aware_webpage_screenshot_taker.py +0 -107
- autobyteus/tools/browser/session_aware/factory/browser_session_aware_web_element_trigger_factory.py +0 -14
- autobyteus/tools/browser/session_aware/factory/browser_session_aware_webpage_reader_factory.py +0 -26
- autobyteus/tools/browser/session_aware/factory/browser_session_aware_webpage_screenshot_taker_factory.py +0 -14
- autobyteus/tools/browser/session_aware/shared_browser_session.py +0 -11
- autobyteus/tools/browser/session_aware/shared_browser_session_manager.py +0 -25
- autobyteus/tools/browser/session_aware/web_element_action.py +0 -20
- autobyteus/tools/browser/standalone/__init__.py +0 -6
- autobyteus/tools/browser/standalone/factory/__init__.py +0 -0
- autobyteus/tools/browser/standalone/factory/webpage_reader_factory.py +0 -25
- autobyteus/tools/browser/standalone/factory/webpage_screenshot_taker_factory.py +0 -14
- autobyteus/tools/browser/standalone/navigate_to.py +0 -84
- autobyteus/tools/browser/standalone/web_page_pdf_generator.py +0 -101
- autobyteus/tools/browser/standalone/webpage_image_downloader.py +0 -169
- autobyteus/tools/browser/standalone/webpage_reader.py +0 -105
- autobyteus/tools/browser/standalone/webpage_screenshot_taker.py +0 -105
- autobyteus/tools/file/edit_file.py +0 -200
- autobyteus/tools/file/list_directory.py +0 -168
- autobyteus/tools/file/search_files.py +0 -188
- autobyteus/tools/timer.py +0 -175
- autobyteus/tools/usage/parsers/__init__.py +0 -22
- autobyteus/tools/usage/parsers/_json_extractor.py +0 -99
- autobyteus/tools/usage/parsers/_string_decoders.py +0 -18
- autobyteus/tools/usage/parsers/anthropic_xml_tool_usage_parser.py +0 -10
- autobyteus/tools/usage/parsers/base_parser.py +0 -41
- autobyteus/tools/usage/parsers/default_json_tool_usage_parser.py +0 -83
- autobyteus/tools/usage/parsers/default_xml_tool_usage_parser.py +0 -316
- autobyteus/tools/usage/parsers/exceptions.py +0 -13
- autobyteus/tools/usage/parsers/gemini_json_tool_usage_parser.py +0 -77
- autobyteus/tools/usage/parsers/openai_json_tool_usage_parser.py +0 -149
- autobyteus/tools/usage/parsers/provider_aware_tool_usage_parser.py +0 -59
- autobyteus/tools/usage/registries/tool_usage_parser_registry.py +0 -62
- autobyteus/workflow/phases/__init__.py +0 -11
- autobyteus/workflow/phases/workflow_operational_phase.py +0 -19
- autobyteus/workflow/phases/workflow_phase_manager.py +0 -48
- autobyteus-1.2.1.dist-info/METADATA +0 -205
- autobyteus-1.2.1.dist-info/RECORD +0 -511
- examples/__init__.py +0 -1
- examples/agent_team/__init__.py +0 -1
- examples/discover_phase_transitions.py +0 -104
- examples/run_agentic_software_engineer.py +0 -239
- examples/run_browser_agent.py +0 -262
- examples/run_google_slides_agent.py +0 -287
- examples/run_mcp_browser_client.py +0 -174
- examples/run_mcp_google_slides_client.py +0 -270
- examples/run_mcp_list_tools.py +0 -189
- examples/run_poem_writer.py +0 -284
- examples/run_sqlite_agent.py +0 -295
- /autobyteus/{tools/browser/session_aware → skills}/__init__.py +0 -0
- /autobyteus/tools/{browser/session_aware/factory → skill}/__init__.py +0 -0
- {autobyteus-1.2.1.dist-info → autobyteus-1.3.0.dist-info}/licenses/LICENSE +0 -0
autobyteus/tools/__init__.py
CHANGED
|
@@ -15,17 +15,28 @@ from .tool_config import ToolConfig # Configuration data object, primarily for c
|
|
|
15
15
|
from .tool_origin import ToolOrigin
|
|
16
16
|
from .tool_category import ToolCategory
|
|
17
17
|
|
|
18
|
+
# Tool Formatting Registration Support
|
|
19
|
+
# Tool Formatting Registration Support
|
|
20
|
+
from autobyteus.tools.usage.registries.tool_formatting_registry import ToolFormattingRegistry, register_tool_formatter
|
|
21
|
+
from autobyteus.tools.usage.registries.tool_formatter_pair import ToolFormatterPair
|
|
22
|
+
from autobyteus.tools.usage.formatters.base_formatter import BaseSchemaFormatter, BaseExampleFormatter
|
|
23
|
+
|
|
24
|
+
|
|
18
25
|
logger = logging.getLogger(__name__)
|
|
19
26
|
|
|
20
27
|
# --- Re-export specific tools for easier access ---
|
|
21
28
|
|
|
22
29
|
# Functional tools (decorated functions are now instances)
|
|
23
|
-
from .bash.bash_executor import bash_executor
|
|
24
30
|
from .file.read_file import read_file
|
|
25
31
|
from .file.write_file import write_file
|
|
26
|
-
from .file.
|
|
27
|
-
from .
|
|
28
|
-
|
|
32
|
+
from .file.patch_file import patch_file
|
|
33
|
+
from .skill.load_skill import load_skill
|
|
34
|
+
|
|
35
|
+
# Terminal tools (PTY-based stateful terminal)
|
|
36
|
+
from .terminal.tools.run_bash import run_bash
|
|
37
|
+
from .terminal.tools.start_background_process import start_background_process
|
|
38
|
+
from .terminal.tools.get_process_output import get_process_output
|
|
39
|
+
from .terminal.tools.stop_background_process import stop_background_process
|
|
29
40
|
|
|
30
41
|
# General Class-based tools
|
|
31
42
|
try:
|
|
@@ -33,7 +44,6 @@ try:
|
|
|
33
44
|
except ModuleNotFoundError as import_err:
|
|
34
45
|
logger.warning("Search tool not available: %s", import_err)
|
|
35
46
|
Search = None
|
|
36
|
-
from .timer import Timer
|
|
37
47
|
try:
|
|
38
48
|
from .multimedia.image_tools import GenerateImageTool, EditImageTool
|
|
39
49
|
except ModuleNotFoundError as import_err:
|
|
@@ -51,33 +61,14 @@ except ModuleNotFoundError as import_err:
|
|
|
51
61
|
logger.warning("Download media tool not available: %s", import_err)
|
|
52
62
|
DownloadMediaTool = None
|
|
53
63
|
|
|
54
|
-
#
|
|
55
|
-
try:
|
|
56
|
-
from .browser.standalone.navigate_to import NavigateTo as StandaloneNavigateTo # Alias to avoid name clash
|
|
57
|
-
from .browser.standalone.webpage_reader import WebPageReader as StandaloneWebPageReader # Alias
|
|
58
|
-
from .browser.standalone.webpage_screenshot_taker import WebPageScreenshotTaker as StandaloneWebPageScreenshotTaker # Alias
|
|
59
|
-
from .browser.standalone.webpage_image_downloader import WebPageImageDownloader
|
|
60
|
-
from .browser.standalone.web_page_pdf_generator import WebPagePDFGenerator
|
|
61
|
-
except ModuleNotFoundError as import_err:
|
|
62
|
-
logger.warning('Standalone browser tools not available: %s', import_err)
|
|
63
|
-
StandaloneNavigateTo = None
|
|
64
|
-
StandaloneWebPageReader = None
|
|
65
|
-
StandaloneWebPageScreenshotTaker = None
|
|
66
|
-
WebPageImageDownloader = None
|
|
67
|
-
WebPagePDFGenerator = None
|
|
68
|
-
|
|
69
|
-
# Session-Aware Browser tools
|
|
64
|
+
# Web tools
|
|
70
65
|
try:
|
|
71
|
-
from .
|
|
72
|
-
from .browser.session_aware.browser_session_aware_web_element_trigger import BrowserSessionAwareWebElementTrigger
|
|
73
|
-
from .browser.session_aware.browser_session_aware_webpage_reader import BrowserSessionAwareWebPageReader
|
|
74
|
-
from .browser.session_aware.browser_session_aware_webpage_screenshot_taker import BrowserSessionAwareWebPageScreenshotTaker
|
|
66
|
+
from .web.read_url_tool import ReadUrl
|
|
75
67
|
except ModuleNotFoundError as import_err:
|
|
76
|
-
logger.warning(
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
BrowserSessionAwareWebPageScreenshotTaker = None
|
|
68
|
+
logger.warning("ReadUrl tool not available: %s", import_err)
|
|
69
|
+
ReadUrl = None
|
|
70
|
+
|
|
71
|
+
|
|
81
72
|
|
|
82
73
|
|
|
83
74
|
__all__ = [
|
|
@@ -92,31 +83,27 @@ __all__ = [
|
|
|
92
83
|
"ToolCategory",
|
|
93
84
|
|
|
94
85
|
# Re-exported functional tool instances
|
|
95
|
-
"
|
|
86
|
+
"run_bash",
|
|
87
|
+
"start_background_process",
|
|
88
|
+
"get_process_output",
|
|
89
|
+
"stop_background_process",
|
|
96
90
|
"read_file",
|
|
97
91
|
"write_file",
|
|
98
|
-
"
|
|
99
|
-
"
|
|
100
|
-
"list_directory",
|
|
92
|
+
"patch_file",
|
|
93
|
+
"load_skill",
|
|
101
94
|
|
|
102
95
|
# Re-exported general class-based tools
|
|
103
96
|
"Search",
|
|
104
|
-
"Timer",
|
|
105
97
|
"GenerateImageTool",
|
|
106
98
|
"EditImageTool",
|
|
107
99
|
"ReadMediaFile",
|
|
108
100
|
"DownloadMediaTool",
|
|
109
101
|
|
|
110
|
-
# Re-exported
|
|
111
|
-
"
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
"
|
|
115
|
-
"
|
|
116
|
-
|
|
117
|
-
# Re-exported Session-Aware Browser tools
|
|
118
|
-
"BrowserSessionAwareNavigateTo",
|
|
119
|
-
"BrowserSessionAwareWebElementTrigger",
|
|
120
|
-
"BrowserSessionAwareWebPageReader",
|
|
121
|
-
"BrowserSessionAwareWebPageScreenshotTaker",
|
|
102
|
+
# Re-exported Web tools
|
|
103
|
+
"ReadUrl",
|
|
104
|
+
|
|
105
|
+
# Tool Formatting
|
|
106
|
+
"register_tool_formatter",
|
|
107
|
+
"BaseSchemaFormatter",
|
|
108
|
+
"BaseExampleFormatter",
|
|
122
109
|
]
|
autobyteus/tools/base_tool.py
CHANGED
|
@@ -174,6 +174,13 @@ class BaseTool(ABC, EventEmitter, metaclass=ToolMeta):
|
|
|
174
174
|
async def _execute(self, context: 'AgentContext', **kwargs) -> Any:
|
|
175
175
|
raise NotImplementedError("Subclasses must implement the '_execute' method.")
|
|
176
176
|
|
|
177
|
+
async def cleanup(self) -> None:
|
|
178
|
+
"""
|
|
179
|
+
Lifecycle hook invoked during agent shutdown to release resources held by the tool.
|
|
180
|
+
Default implementation is a no-op.
|
|
181
|
+
"""
|
|
182
|
+
return None
|
|
183
|
+
|
|
177
184
|
@classmethod
|
|
178
185
|
def tool_usage(cls) -> str:
|
|
179
186
|
logger.warning("BaseTool.tool_usage() is deprecated. Tool usage is now generated by formatters.")
|
|
@@ -1,13 +1,9 @@
|
|
|
1
|
-
from .
|
|
1
|
+
from .patch_file import patch_file
|
|
2
2
|
from .read_file import read_file
|
|
3
3
|
from .write_file import write_file
|
|
4
|
-
from .search_files import search_files
|
|
5
|
-
from .list_directory import list_directory
|
|
6
4
|
|
|
7
5
|
__all__ = [
|
|
8
|
-
"
|
|
6
|
+
"patch_file",
|
|
9
7
|
"read_file",
|
|
10
8
|
"write_file",
|
|
11
|
-
"search_files",
|
|
12
|
-
"list_directory",
|
|
13
9
|
]
|
|
@@ -0,0 +1,149 @@
|
|
|
1
|
+
import os
|
|
2
|
+
import logging
|
|
3
|
+
from typing import TYPE_CHECKING, List
|
|
4
|
+
|
|
5
|
+
from pydantic import Field
|
|
6
|
+
|
|
7
|
+
from autobyteus.tools.functional_tool import tool
|
|
8
|
+
from autobyteus.tools.tool_category import ToolCategory
|
|
9
|
+
from autobyteus.utils.diff_utils import apply_unified_diff, PatchApplicationError
|
|
10
|
+
|
|
11
|
+
if TYPE_CHECKING:
|
|
12
|
+
from autobyteus.agent.context import AgentContext
|
|
13
|
+
|
|
14
|
+
logger = logging.getLogger(__name__)
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
def _resolve_file_path(context: 'AgentContext', path: str) -> str:
|
|
18
|
+
"""Resolves an absolute path for the given input, using the agent workspace when needed."""
|
|
19
|
+
if os.path.isabs(path):
|
|
20
|
+
final_path = path
|
|
21
|
+
logger.debug("patch_file: provided path '%s' is absolute.", path)
|
|
22
|
+
else:
|
|
23
|
+
if not context.workspace:
|
|
24
|
+
error_msg = ("Relative path '%s' provided, but no workspace is configured for agent '%s'. "
|
|
25
|
+
"A workspace is required to resolve relative paths.")
|
|
26
|
+
logger.error(error_msg, path, context.agent_id)
|
|
27
|
+
raise ValueError(error_msg % (path, context.agent_id))
|
|
28
|
+
base_path = context.workspace.get_base_path()
|
|
29
|
+
if not base_path or not isinstance(base_path, str):
|
|
30
|
+
error_msg = ("Agent '%s' has a configured workspace, but it provided an invalid base path ('%s'). "
|
|
31
|
+
"Cannot resolve relative path '%s'.")
|
|
32
|
+
logger.error(error_msg, context.agent_id, base_path, path)
|
|
33
|
+
raise ValueError(error_msg % (context.agent_id, base_path, path))
|
|
34
|
+
final_path = os.path.join(base_path, path)
|
|
35
|
+
logger.debug("patch_file: resolved relative path '%s' against workspace base '%s' to '%s'.", path, base_path, final_path)
|
|
36
|
+
|
|
37
|
+
normalized_path = os.path.normpath(final_path)
|
|
38
|
+
logger.debug("patch_file: normalized path to '%s'.", normalized_path)
|
|
39
|
+
return normalized_path
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
@tool(name="patch_file", category=ToolCategory.FILE_SYSTEM)
|
|
43
|
+
async def patch_file(
|
|
44
|
+
context: 'AgentContext',
|
|
45
|
+
path: str = Field(..., description="Path to the target file."),
|
|
46
|
+
patch: str = Field(
|
|
47
|
+
...,
|
|
48
|
+
description=(
|
|
49
|
+
"Unified diff hunks describing edits to apply. "
|
|
50
|
+
"Example:\n"
|
|
51
|
+
"--- a/sample.txt\n"
|
|
52
|
+
"+++ b/sample.txt\n"
|
|
53
|
+
"@@ -1,2 +1,2 @@\n"
|
|
54
|
+
"-old line\n"
|
|
55
|
+
"+new line\n"
|
|
56
|
+
" unchanged line"
|
|
57
|
+
),
|
|
58
|
+
),
|
|
59
|
+
) -> str:
|
|
60
|
+
"""Applies a unified diff patch to update a text file without overwriting unrelated content.
|
|
61
|
+
|
|
62
|
+
Args:
|
|
63
|
+
path: Path to the target file. Relative paths are resolved against the agent workspace when available.
|
|
64
|
+
patch: Unified diff patch describing the edits to apply.
|
|
65
|
+
|
|
66
|
+
Raises:
|
|
67
|
+
FileNotFoundError: If the file does not exist.
|
|
68
|
+
PatchApplicationError: If the patch content cannot be applied cleanly.
|
|
69
|
+
IOError: If file reading or writing fails.
|
|
70
|
+
"""
|
|
71
|
+
logger.debug("patch_file: requested patch for agent '%s' on path '%s'.", context.agent_id, path)
|
|
72
|
+
return_path = os.path.normpath(path)
|
|
73
|
+
|
|
74
|
+
# Detailed logging for debugging patch content
|
|
75
|
+
logger.info("patch_file: ===== PATCH ARGUMENT DEBUG START =====")
|
|
76
|
+
logger.info("patch_file: raw patch repr: %r", patch)
|
|
77
|
+
logger.info("patch_file: patch length: %d chars", len(patch) if patch else 0)
|
|
78
|
+
patch_lines = patch.splitlines(keepends=True) if patch else []
|
|
79
|
+
for i, line in enumerate(patch_lines, 1):
|
|
80
|
+
prefix = line[0] if line else '<empty>'
|
|
81
|
+
logger.info("patch_file: line %d: prefix=%r content=%r", i, prefix, line)
|
|
82
|
+
logger.info("patch_file: ===== PATCH ARGUMENT DEBUG END =====")
|
|
83
|
+
|
|
84
|
+
final_path = _resolve_file_path(context, path)
|
|
85
|
+
|
|
86
|
+
file_exists = os.path.exists(final_path)
|
|
87
|
+
if not file_exists:
|
|
88
|
+
raise FileNotFoundError(f"The file at resolved path {final_path} does not exist.")
|
|
89
|
+
|
|
90
|
+
try:
|
|
91
|
+
original_lines: List[str]
|
|
92
|
+
if file_exists:
|
|
93
|
+
with open(final_path, 'r', encoding='utf-8') as source:
|
|
94
|
+
original_lines = source.read().splitlines(keepends=True)
|
|
95
|
+
else:
|
|
96
|
+
original_lines = []
|
|
97
|
+
|
|
98
|
+
# Log original file content for comparison
|
|
99
|
+
logger.info("patch_file: ===== ORIGINAL FILE DEBUG START =====")
|
|
100
|
+
for i, line in enumerate(original_lines, 1):
|
|
101
|
+
logger.info("patch_file: original line %d: %r", i, line)
|
|
102
|
+
logger.info("patch_file: ===== ORIGINAL FILE DEBUG END =====")
|
|
103
|
+
|
|
104
|
+
patched_lines = None
|
|
105
|
+
patch_error = None
|
|
106
|
+
retry_strategies = [
|
|
107
|
+
(0, False),
|
|
108
|
+
(1, False),
|
|
109
|
+
(1, True),
|
|
110
|
+
(2, True),
|
|
111
|
+
]
|
|
112
|
+
for fuzz_factor, ignore_whitespace in retry_strategies:
|
|
113
|
+
try:
|
|
114
|
+
patched_lines = apply_unified_diff(
|
|
115
|
+
original_lines,
|
|
116
|
+
patch,
|
|
117
|
+
fuzz_factor=fuzz_factor,
|
|
118
|
+
ignore_whitespace=ignore_whitespace,
|
|
119
|
+
)
|
|
120
|
+
if (fuzz_factor, ignore_whitespace) != (0, False):
|
|
121
|
+
logger.info(
|
|
122
|
+
"patch_file: applied with fuzz=%d ignore_whitespace=%s.",
|
|
123
|
+
fuzz_factor,
|
|
124
|
+
ignore_whitespace,
|
|
125
|
+
)
|
|
126
|
+
break
|
|
127
|
+
except PatchApplicationError as patch_err:
|
|
128
|
+
patch_error = patch_err
|
|
129
|
+
logger.warning(
|
|
130
|
+
"patch_file: patch failed with fuzz=%d ignore_whitespace=%s: %s",
|
|
131
|
+
fuzz_factor,
|
|
132
|
+
ignore_whitespace,
|
|
133
|
+
patch_err,
|
|
134
|
+
)
|
|
135
|
+
continue
|
|
136
|
+
if patched_lines is None:
|
|
137
|
+
raise patch_error or PatchApplicationError("Patch could not be applied.")
|
|
138
|
+
|
|
139
|
+
with open(final_path, 'w', encoding='utf-8') as destination:
|
|
140
|
+
destination.writelines(patched_lines)
|
|
141
|
+
|
|
142
|
+
logger.info("patch_file: successfully applied patch to '%s'.", final_path)
|
|
143
|
+
return f"File patched successfully at {return_path}"
|
|
144
|
+
except PatchApplicationError as patch_err:
|
|
145
|
+
logger.error("patch_file: failed to apply patch to '%s': %s", final_path, patch_err, exc_info=True)
|
|
146
|
+
raise patch_err
|
|
147
|
+
except Exception as exc: # pragma: no cover - general safeguard
|
|
148
|
+
logger.error("patch_file: unexpected error while patching '%s': %s", final_path, exc, exc_info=True)
|
|
149
|
+
raise IOError(f"Could not patch file at '{final_path}': {exc}")
|
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
import os
|
|
2
2
|
import logging
|
|
3
|
-
from typing import TYPE_CHECKING
|
|
3
|
+
from typing import TYPE_CHECKING, Optional
|
|
4
|
+
|
|
5
|
+
from pydantic import Field
|
|
4
6
|
|
|
5
7
|
from autobyteus.tools import tool
|
|
6
8
|
from autobyteus.tools.tool_category import ToolCategory
|
|
@@ -11,15 +13,32 @@ if TYPE_CHECKING:
|
|
|
11
13
|
logger = logging.getLogger(__name__)
|
|
12
14
|
|
|
13
15
|
@tool(name="read_file", category=ToolCategory.FILE_SYSTEM)
|
|
14
|
-
async def read_file(
|
|
16
|
+
async def read_file(
|
|
17
|
+
context: 'AgentContext',
|
|
18
|
+
path: str,
|
|
19
|
+
start_line: Optional[int] = None,
|
|
20
|
+
end_line: Optional[int] = None,
|
|
21
|
+
include_line_numbers: bool = Field(
|
|
22
|
+
True,
|
|
23
|
+
description="If true, prefix each returned line with its line number (default).",
|
|
24
|
+
),
|
|
25
|
+
) -> str:
|
|
15
26
|
"""
|
|
16
|
-
Reads content from a specified file.
|
|
27
|
+
Reads content from a specified file. Supports optional 1-based inclusive line ranges via start_line/end_line.
|
|
28
|
+
Each returned line is prefixed with its line number when include_line_numbers is true.
|
|
17
29
|
'path' is the path to the file. If relative, it must be resolved against a configured agent workspace.
|
|
18
|
-
Raises ValueError if a relative path is given without a valid workspace.
|
|
30
|
+
Raises ValueError if a relative path is given without a valid workspace or if line range arguments are invalid.
|
|
19
31
|
Raises FileNotFoundError if the file does not exist.
|
|
20
32
|
Raises IOError if file reading fails for other reasons.
|
|
21
33
|
"""
|
|
22
34
|
logger.debug(f"Functional read_file tool for agent {context.agent_id}, initial path: {path}")
|
|
35
|
+
|
|
36
|
+
if start_line is not None and start_line < 1:
|
|
37
|
+
raise ValueError(f"start_line must be >= 1 when provided; got {start_line}.")
|
|
38
|
+
if end_line is not None and end_line < 1:
|
|
39
|
+
raise ValueError(f"end_line must be >= 1 when provided; got {end_line}.")
|
|
40
|
+
if start_line is not None and end_line is not None and end_line < start_line:
|
|
41
|
+
raise ValueError(f"end_line ({end_line}) must be >= start_line ({start_line}).")
|
|
23
42
|
|
|
24
43
|
final_path: str
|
|
25
44
|
if os.path.isabs(path):
|
|
@@ -48,7 +67,19 @@ async def read_file(context: 'AgentContext', path: str) -> str:
|
|
|
48
67
|
|
|
49
68
|
try:
|
|
50
69
|
with open(final_path, 'r', encoding='utf-8') as file:
|
|
51
|
-
|
|
70
|
+
selected_lines = []
|
|
71
|
+
for line_no, line in enumerate(file, start=1):
|
|
72
|
+
if start_line is not None and line_no < start_line:
|
|
73
|
+
continue
|
|
74
|
+
if end_line is not None and line_no > end_line:
|
|
75
|
+
break
|
|
76
|
+
if include_line_numbers:
|
|
77
|
+
line_text = line.rstrip('\n')
|
|
78
|
+
line_suffix = '\n' if line.endswith('\n') else ''
|
|
79
|
+
selected_lines.append(f"{line_no}: {line_text}{line_suffix}")
|
|
80
|
+
else:
|
|
81
|
+
selected_lines.append(line)
|
|
82
|
+
content = ''.join(selected_lines)
|
|
52
83
|
logger.info(f"File successfully read from '{final_path}' for agent '{context.agent_id}'.")
|
|
53
84
|
return content
|
|
54
85
|
except Exception as e:
|
|
@@ -23,8 +23,10 @@ async def write_file(context: 'AgentContext', path: str, content: str) -> str:
|
|
|
23
23
|
logger.debug(f"Functional write_file tool for agent {context.agent_id}, initial path: {path}")
|
|
24
24
|
|
|
25
25
|
final_path: str
|
|
26
|
+
return_path: str
|
|
26
27
|
if os.path.isabs(path):
|
|
27
28
|
final_path = path
|
|
29
|
+
return_path = final_path
|
|
28
30
|
logger.debug(f"Path '{path}' is absolute. Using it directly.")
|
|
29
31
|
else:
|
|
30
32
|
if not context.workspace:
|
|
@@ -39,6 +41,7 @@ async def write_file(context: 'AgentContext', path: str, content: str) -> str:
|
|
|
39
41
|
raise ValueError(error_msg)
|
|
40
42
|
|
|
41
43
|
final_path = os.path.join(base_path, path)
|
|
44
|
+
return_path = os.path.normpath(path)
|
|
42
45
|
logger.debug(f"Path '{path}' is relative. Resolved to '{final_path}' using workspace base path '{base_path}'.")
|
|
43
46
|
|
|
44
47
|
try:
|
|
@@ -53,7 +56,7 @@ async def write_file(context: 'AgentContext', path: str, content: str) -> str:
|
|
|
53
56
|
file.write(content)
|
|
54
57
|
|
|
55
58
|
logger.info(f"File successfully written to '{final_path}' for agent '{context.agent_id}'.")
|
|
56
|
-
return f"File created/updated at {
|
|
59
|
+
return f"File created/updated at {return_path}"
|
|
57
60
|
except Exception as e:
|
|
58
61
|
logger.error(f"Error writing file to final path '{final_path}' for agent {context.agent_id}: {e}", exc_info=True)
|
|
59
62
|
raise IOError(f"Could not write file at '{final_path}': {str(e)}")
|
|
@@ -155,6 +155,12 @@ def _get_parameter_type_from_hint(py_type: Any, param_name: str) -> Tuple[Parame
|
|
|
155
155
|
logger.warning(f"Unmapped type hint {py_type} (actual_type: {actual_type}) for param '{param_name}'. Defaulting to ParameterType.STRING.")
|
|
156
156
|
return ParameterType.STRING, None
|
|
157
157
|
|
|
158
|
+
|
|
159
|
+
try:
|
|
160
|
+
from pydantic.fields import FieldInfo
|
|
161
|
+
except ImportError:
|
|
162
|
+
FieldInfo = None # type: ignore
|
|
163
|
+
|
|
158
164
|
def _parse_signature(sig: inspect.Signature, tool_name: str) -> Tuple[TypingList[str], bool, bool, ParameterSchema]:
|
|
159
165
|
func_param_names = []
|
|
160
166
|
expects_context = False
|
|
@@ -175,26 +181,51 @@ def _parse_signature(sig: inspect.Signature, tool_name: str) -> Tuple[TypingList
|
|
|
175
181
|
param_type_enum, item_schema = _get_parameter_type_from_hint(param_type_hint, param_name)
|
|
176
182
|
|
|
177
183
|
is_required = param_obj.default == inspect.Parameter.empty
|
|
178
|
-
if
|
|
179
|
-
|
|
180
|
-
|
|
184
|
+
default_val = param_obj.default if param_obj.default != inspect.Parameter.empty else None
|
|
185
|
+
|
|
186
|
+
# --- Pydantic Field Extraction Logic ---
|
|
181
187
|
param_desc = f"Parameter '{param_name}' for tool '{tool_name}'."
|
|
182
188
|
param_name_lower = param_name.lower()
|
|
183
189
|
if "path" in param_name_lower or "file" in param_name_lower or "dir" in param_name_lower or "folder" in param_name_lower:
|
|
184
|
-
|
|
190
|
+
param_desc += " This is expected to be a path."
|
|
191
|
+
|
|
192
|
+
if FieldInfo and isinstance(param_obj.default, FieldInfo):
|
|
193
|
+
field_info = param_obj.default
|
|
194
|
+
|
|
195
|
+
# 1. Description
|
|
196
|
+
if field_info.description:
|
|
197
|
+
param_desc = field_info.description
|
|
185
198
|
|
|
199
|
+
# 2. Default Value & Requiredness
|
|
200
|
+
# If PydanticUndefined (or similar sentinel), it means required.
|
|
201
|
+
# Otherwise, use the default value from Field.
|
|
202
|
+
# Note: Pydantic v1 uses Undefined, v2 uses PydanticUndefined.
|
|
203
|
+
# We check if it is the special undefined value via representation or direct check.
|
|
204
|
+
|
|
205
|
+
# Simple heuristic for "Undefined" without importing the specific sentinel
|
|
206
|
+
if str(field_info.default) == "PydanticUndefined" or field_info.default == ...:
|
|
207
|
+
is_required = True
|
|
208
|
+
default_val = None
|
|
209
|
+
else:
|
|
210
|
+
is_required = False
|
|
211
|
+
default_val = field_info.default
|
|
212
|
+
|
|
213
|
+
if get_origin(param_type_hint) is Union and type(None) in get_args(param_type_hint):
|
|
214
|
+
is_required = False
|
|
215
|
+
|
|
186
216
|
schema_param = ParameterDefinition(
|
|
187
217
|
name=param_name,
|
|
188
218
|
param_type=param_type_enum,
|
|
189
219
|
description=param_desc,
|
|
190
220
|
required=is_required,
|
|
191
|
-
default_value=
|
|
221
|
+
default_value=default_val,
|
|
192
222
|
array_item_schema=item_schema
|
|
193
223
|
)
|
|
194
224
|
generated_arg_schema.add_parameter(schema_param)
|
|
195
225
|
|
|
196
226
|
return func_param_names, expects_context, expects_tool_state, generated_arg_schema
|
|
197
227
|
|
|
228
|
+
|
|
198
229
|
# --- The refactored @tool decorator ---
|
|
199
230
|
|
|
200
231
|
def tool(
|
|
@@ -217,6 +248,11 @@ def tool(
|
|
|
217
248
|
|
|
218
249
|
final_arg_schema = argument_schema if argument_schema is not None else gen_arg_schema
|
|
219
250
|
|
|
251
|
+
def _current_description() -> str:
|
|
252
|
+
"""Recompute the description from the latest docstring/override."""
|
|
253
|
+
latest_doc = inspect.getdoc(func)
|
|
254
|
+
return description or (latest_doc.split('\n\n')[0] if latest_doc else f"Functional tool: {tool_name}")
|
|
255
|
+
|
|
220
256
|
def factory(inst_config: Optional[ToolConfig] = None) -> FunctionalTool:
|
|
221
257
|
return FunctionalTool(
|
|
222
258
|
original_func=func,
|
|
@@ -239,7 +275,8 @@ def tool(
|
|
|
239
275
|
custom_factory=factory,
|
|
240
276
|
tool_class=None,
|
|
241
277
|
origin=ToolOrigin.LOCAL,
|
|
242
|
-
category=category
|
|
278
|
+
category=category,
|
|
279
|
+
description_provider=_current_description
|
|
243
280
|
)
|
|
244
281
|
default_tool_registry.register_tool(tool_def)
|
|
245
282
|
|
autobyteus/tools/mcp/__init__.py
CHANGED
|
@@ -19,6 +19,7 @@ from .types import (
|
|
|
19
19
|
BaseMcpConfig,
|
|
20
20
|
StdioMcpServerConfig,
|
|
21
21
|
StreamableHttpMcpServerConfig,
|
|
22
|
+
WebsocketMcpServerConfig,
|
|
22
23
|
McpTransportType,
|
|
23
24
|
McpServerInstanceKey,
|
|
24
25
|
)
|
|
@@ -37,6 +38,7 @@ __all__ = [
|
|
|
37
38
|
"BaseMcpConfig",
|
|
38
39
|
"StdioMcpServerConfig",
|
|
39
40
|
"StreamableHttpMcpServerConfig",
|
|
41
|
+
"WebsocketMcpServerConfig",
|
|
40
42
|
"McpTransportType",
|
|
41
43
|
"McpServerInstanceKey",
|
|
42
44
|
# Services and Managers
|
|
@@ -9,6 +9,7 @@ from .types import (
|
|
|
9
9
|
BaseMcpConfig,
|
|
10
10
|
StdioMcpServerConfig,
|
|
11
11
|
StreamableHttpMcpServerConfig,
|
|
12
|
+
WebsocketMcpServerConfig,
|
|
12
13
|
McpTransportType
|
|
13
14
|
)
|
|
14
15
|
from autobyteus.utils.singleton import SingletonMeta
|
|
@@ -49,7 +50,8 @@ class McpConfigService(metaclass=SingletonMeta):
|
|
|
49
50
|
|
|
50
51
|
transport_specific_params_key_map = {
|
|
51
52
|
McpTransportType.STDIO: "stdio_params",
|
|
52
|
-
McpTransportType.STREAMABLE_HTTP: "streamable_http_params"
|
|
53
|
+
McpTransportType.STREAMABLE_HTTP: "streamable_http_params",
|
|
54
|
+
McpTransportType.WEBSOCKET: "websocket_params",
|
|
53
55
|
}
|
|
54
56
|
|
|
55
57
|
if transport_type in transport_specific_params_key_map:
|
|
@@ -74,6 +76,8 @@ class McpConfigService(metaclass=SingletonMeta):
|
|
|
74
76
|
return StdioMcpServerConfig(**constructor_params)
|
|
75
77
|
elif transport_type == McpTransportType.STREAMABLE_HTTP:
|
|
76
78
|
return StreamableHttpMcpServerConfig(**constructor_params)
|
|
79
|
+
elif transport_type == McpTransportType.WEBSOCKET:
|
|
80
|
+
return WebsocketMcpServerConfig(**constructor_params)
|
|
77
81
|
else:
|
|
78
82
|
raise ValueError(f"Unsupported McpTransportType '{transport_type}' for server '{server_id}'.")
|
|
79
83
|
except TypeError as e:
|
|
@@ -5,6 +5,7 @@ This package contains the core abstractions for managing connections to remote M
|
|
|
5
5
|
from .base_managed_mcp_server import BaseManagedMcpServer, ServerState
|
|
6
6
|
from .stdio_managed_mcp_server import StdioManagedMcpServer
|
|
7
7
|
from .http_managed_mcp_server import HttpManagedMcpServer
|
|
8
|
+
from .websocket_managed_mcp_server import WebsocketManagedMcpServer
|
|
8
9
|
from .proxy import McpServerProxy
|
|
9
10
|
|
|
10
11
|
__all__ = [
|
|
@@ -12,5 +13,6 @@ __all__ = [
|
|
|
12
13
|
"ServerState",
|
|
13
14
|
"StdioManagedMcpServer",
|
|
14
15
|
"HttpManagedMcpServer",
|
|
16
|
+
"WebsocketManagedMcpServer",
|
|
15
17
|
"McpServerProxy",
|
|
16
18
|
]
|
|
@@ -23,7 +23,7 @@ class HttpManagedMcpServer(BaseManagedMcpServer):
|
|
|
23
23
|
config = cast(StreamableHttpMcpServerConfig, self._config)
|
|
24
24
|
|
|
25
25
|
logger.debug(f"Establishing HTTP connection for server '{self.server_id}' to URL: {config.url}")
|
|
26
|
-
read_stream, write_stream = await self._exit_stack.enter_async_context(
|
|
26
|
+
read_stream, write_stream, _ = await self._exit_stack.enter_async_context(
|
|
27
27
|
streamablehttp_client(config.url, headers=config.headers)
|
|
28
28
|
)
|
|
29
29
|
session = await self._exit_stack.enter_async_context(ClientSession(read_stream, write_stream))
|