autobyteus 1.1.3__py3-none-any.whl → 1.1.5__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 +1 -1
- autobyteus/agent/bootstrap_steps/system_prompt_processing_step.py +4 -2
- autobyteus/agent/context/__init__.py +4 -2
- autobyteus/agent/context/agent_config.py +35 -8
- autobyteus/agent/context/agent_context_registry.py +73 -0
- autobyteus/agent/events/notifiers.py +4 -0
- autobyteus/agent/events/worker_event_dispatcher.py +1 -2
- autobyteus/agent/handlers/inter_agent_message_event_handler.py +8 -3
- autobyteus/agent/handlers/llm_complete_response_received_event_handler.py +19 -19
- autobyteus/agent/handlers/llm_user_message_ready_event_handler.py +2 -2
- autobyteus/agent/handlers/tool_result_event_handler.py +48 -20
- autobyteus/agent/handlers/user_input_message_event_handler.py +16 -1
- autobyteus/agent/input_processor/__init__.py +1 -7
- autobyteus/agent/message/context_file_type.py +6 -0
- autobyteus/agent/message/send_message_to.py +74 -99
- autobyteus/agent/phases/discover.py +2 -1
- autobyteus/agent/runtime/agent_runtime.py +10 -2
- autobyteus/agent/runtime/agent_worker.py +1 -0
- autobyteus/agent/sender_type.py +15 -0
- autobyteus/agent/streaming/agent_event_stream.py +6 -0
- autobyteus/agent/streaming/stream_event_payloads.py +12 -0
- autobyteus/agent/streaming/stream_events.py +3 -0
- autobyteus/agent/system_prompt_processor/tool_manifest_injector_processor.py +7 -4
- autobyteus/agent/tool_execution_result_processor/__init__.py +9 -0
- autobyteus/agent/tool_execution_result_processor/base_processor.py +46 -0
- autobyteus/agent/tool_execution_result_processor/processor_definition.py +36 -0
- autobyteus/agent/tool_execution_result_processor/processor_meta.py +36 -0
- autobyteus/agent/tool_execution_result_processor/processor_registry.py +70 -0
- autobyteus/agent/workspace/base_workspace.py +17 -2
- autobyteus/agent_team/__init__.py +1 -0
- autobyteus/agent_team/agent_team.py +93 -0
- autobyteus/agent_team/agent_team_builder.py +184 -0
- autobyteus/agent_team/base_agent_team.py +86 -0
- autobyteus/agent_team/bootstrap_steps/__init__.py +24 -0
- autobyteus/agent_team/bootstrap_steps/agent_configuration_preparation_step.py +73 -0
- autobyteus/agent_team/bootstrap_steps/agent_team_bootstrapper.py +54 -0
- autobyteus/agent_team/bootstrap_steps/agent_team_runtime_queue_initialization_step.py +25 -0
- autobyteus/agent_team/bootstrap_steps/base_agent_team_bootstrap_step.py +23 -0
- autobyteus/agent_team/bootstrap_steps/coordinator_initialization_step.py +41 -0
- autobyteus/agent_team/bootstrap_steps/coordinator_prompt_preparation_step.py +85 -0
- autobyteus/agent_team/bootstrap_steps/task_notifier_initialization_step.py +51 -0
- autobyteus/agent_team/bootstrap_steps/team_context_initialization_step.py +45 -0
- autobyteus/agent_team/context/__init__.py +17 -0
- autobyteus/agent_team/context/agent_team_config.py +33 -0
- autobyteus/agent_team/context/agent_team_context.py +61 -0
- autobyteus/agent_team/context/agent_team_runtime_state.py +56 -0
- autobyteus/agent_team/context/team_manager.py +147 -0
- autobyteus/agent_team/context/team_node_config.py +76 -0
- autobyteus/agent_team/events/__init__.py +29 -0
- autobyteus/agent_team/events/agent_team_event_dispatcher.py +39 -0
- autobyteus/agent_team/events/agent_team_events.py +53 -0
- autobyteus/agent_team/events/agent_team_input_event_queue_manager.py +21 -0
- autobyteus/agent_team/exceptions.py +8 -0
- autobyteus/agent_team/factory/__init__.py +9 -0
- autobyteus/agent_team/factory/agent_team_factory.py +99 -0
- autobyteus/agent_team/handlers/__init__.py +19 -0
- autobyteus/agent_team/handlers/agent_team_event_handler_registry.py +23 -0
- autobyteus/agent_team/handlers/base_agent_team_event_handler.py +16 -0
- autobyteus/agent_team/handlers/inter_agent_message_request_event_handler.py +61 -0
- autobyteus/agent_team/handlers/lifecycle_agent_team_event_handler.py +27 -0
- autobyteus/agent_team/handlers/process_user_message_event_handler.py +46 -0
- autobyteus/agent_team/handlers/tool_approval_team_event_handler.py +48 -0
- autobyteus/agent_team/phases/__init__.py +11 -0
- autobyteus/agent_team/phases/agent_team_operational_phase.py +19 -0
- autobyteus/agent_team/phases/agent_team_phase_manager.py +48 -0
- autobyteus/agent_team/runtime/__init__.py +13 -0
- autobyteus/agent_team/runtime/agent_team_runtime.py +82 -0
- autobyteus/agent_team/runtime/agent_team_worker.py +117 -0
- autobyteus/agent_team/shutdown_steps/__init__.py +17 -0
- autobyteus/agent_team/shutdown_steps/agent_team_shutdown_orchestrator.py +35 -0
- autobyteus/agent_team/shutdown_steps/agent_team_shutdown_step.py +42 -0
- autobyteus/agent_team/shutdown_steps/base_agent_team_shutdown_step.py +16 -0
- autobyteus/agent_team/shutdown_steps/bridge_cleanup_step.py +28 -0
- autobyteus/agent_team/shutdown_steps/sub_team_shutdown_step.py +41 -0
- autobyteus/agent_team/streaming/__init__.py +26 -0
- autobyteus/agent_team/streaming/agent_event_bridge.py +48 -0
- autobyteus/agent_team/streaming/agent_event_multiplexer.py +70 -0
- autobyteus/agent_team/streaming/agent_team_event_notifier.py +64 -0
- autobyteus/agent_team/streaming/agent_team_event_stream.py +33 -0
- autobyteus/agent_team/streaming/agent_team_stream_event_payloads.py +32 -0
- autobyteus/agent_team/streaming/agent_team_stream_events.py +56 -0
- autobyteus/agent_team/streaming/team_event_bridge.py +50 -0
- autobyteus/agent_team/task_notification/__init__.py +11 -0
- autobyteus/agent_team/task_notification/system_event_driven_agent_task_notifier.py +164 -0
- autobyteus/agent_team/task_notification/task_notification_mode.py +24 -0
- autobyteus/agent_team/utils/__init__.py +9 -0
- autobyteus/agent_team/utils/wait_for_idle.py +46 -0
- autobyteus/cli/__init__.py +1 -1
- autobyteus/cli/agent_team_tui/__init__.py +4 -0
- autobyteus/cli/agent_team_tui/app.py +210 -0
- autobyteus/cli/agent_team_tui/state.py +180 -0
- autobyteus/cli/agent_team_tui/widgets/__init__.py +6 -0
- autobyteus/cli/agent_team_tui/widgets/agent_list_sidebar.py +149 -0
- autobyteus/cli/agent_team_tui/widgets/focus_pane.py +320 -0
- autobyteus/cli/agent_team_tui/widgets/logo.py +20 -0
- autobyteus/cli/agent_team_tui/widgets/renderables.py +77 -0
- autobyteus/cli/agent_team_tui/widgets/shared.py +60 -0
- autobyteus/cli/agent_team_tui/widgets/status_bar.py +14 -0
- autobyteus/cli/agent_team_tui/widgets/task_board_panel.py +82 -0
- autobyteus/cli/cli_display.py +1 -1
- autobyteus/cli/workflow_tui/__init__.py +4 -0
- autobyteus/cli/workflow_tui/app.py +210 -0
- autobyteus/cli/workflow_tui/state.py +189 -0
- autobyteus/cli/workflow_tui/widgets/__init__.py +6 -0
- autobyteus/cli/workflow_tui/widgets/agent_list_sidebar.py +149 -0
- autobyteus/cli/workflow_tui/widgets/focus_pane.py +335 -0
- autobyteus/cli/workflow_tui/widgets/logo.py +27 -0
- autobyteus/cli/workflow_tui/widgets/renderables.py +70 -0
- autobyteus/cli/workflow_tui/widgets/shared.py +51 -0
- autobyteus/cli/workflow_tui/widgets/status_bar.py +14 -0
- autobyteus/events/event_types.py +8 -0
- autobyteus/llm/api/autobyteus_llm.py +11 -12
- autobyteus/llm/api/lmstudio_llm.py +34 -0
- autobyteus/llm/api/ollama_llm.py +8 -13
- autobyteus/llm/api/openai_compatible_llm.py +20 -3
- autobyteus/llm/autobyteus_provider.py +73 -46
- autobyteus/llm/llm_factory.py +103 -139
- autobyteus/llm/lmstudio_provider.py +104 -0
- autobyteus/llm/models.py +83 -53
- autobyteus/llm/ollama_provider.py +69 -61
- autobyteus/llm/ollama_provider_resolver.py +1 -0
- autobyteus/llm/providers.py +13 -12
- autobyteus/llm/runtimes.py +11 -0
- autobyteus/llm/token_counter/token_counter_factory.py +2 -0
- autobyteus/task_management/__init__.py +43 -0
- autobyteus/task_management/base_task_board.py +68 -0
- autobyteus/task_management/converters/__init__.py +11 -0
- autobyteus/task_management/converters/task_board_converter.py +64 -0
- autobyteus/task_management/converters/task_plan_converter.py +48 -0
- autobyteus/task_management/deliverable.py +16 -0
- autobyteus/task_management/deliverables/__init__.py +8 -0
- autobyteus/task_management/deliverables/file_deliverable.py +15 -0
- autobyteus/task_management/events.py +27 -0
- autobyteus/task_management/in_memory_task_board.py +126 -0
- autobyteus/task_management/schemas/__init__.py +15 -0
- autobyteus/task_management/schemas/deliverable_schema.py +13 -0
- autobyteus/task_management/schemas/plan_definition.py +35 -0
- autobyteus/task_management/schemas/task_status_report.py +27 -0
- autobyteus/task_management/task_plan.py +110 -0
- autobyteus/task_management/tools/__init__.py +14 -0
- autobyteus/task_management/tools/get_task_board_status.py +68 -0
- autobyteus/task_management/tools/publish_task_plan.py +113 -0
- autobyteus/task_management/tools/update_task_status.py +135 -0
- autobyteus/tools/__init__.py +2 -0
- autobyteus/tools/ask_user_input.py +2 -1
- autobyteus/tools/bash/bash_executor.py +61 -15
- autobyteus/tools/browser/session_aware/browser_session_aware_navigate_to.py +2 -0
- autobyteus/tools/browser/session_aware/browser_session_aware_web_element_trigger.py +3 -0
- autobyteus/tools/browser/session_aware/browser_session_aware_webpage_reader.py +3 -0
- autobyteus/tools/browser/session_aware/browser_session_aware_webpage_screenshot_taker.py +3 -0
- autobyteus/tools/browser/standalone/google_search_ui.py +2 -0
- autobyteus/tools/browser/standalone/navigate_to.py +2 -0
- autobyteus/tools/browser/standalone/web_page_pdf_generator.py +3 -0
- autobyteus/tools/browser/standalone/webpage_image_downloader.py +3 -0
- autobyteus/tools/browser/standalone/webpage_reader.py +2 -0
- autobyteus/tools/browser/standalone/webpage_screenshot_taker.py +3 -0
- autobyteus/tools/file/file_reader.py +36 -9
- autobyteus/tools/file/file_writer.py +37 -9
- autobyteus/tools/functional_tool.py +5 -4
- autobyteus/tools/image_downloader.py +2 -0
- autobyteus/tools/mcp/config_service.py +63 -58
- autobyteus/tools/mcp/server/http_managed_mcp_server.py +14 -2
- autobyteus/tools/mcp/server/stdio_managed_mcp_server.py +14 -2
- autobyteus/tools/mcp/server_instance_manager.py +30 -4
- autobyteus/tools/mcp/tool_registrar.py +106 -51
- autobyteus/tools/parameter_schema.py +17 -11
- autobyteus/tools/pdf_downloader.py +2 -1
- autobyteus/tools/registry/tool_definition.py +36 -37
- autobyteus/tools/registry/tool_registry.py +50 -2
- autobyteus/tools/timer.py +2 -0
- autobyteus/tools/tool_category.py +15 -4
- autobyteus/tools/tool_meta.py +6 -1
- autobyteus/tools/tool_origin.py +10 -0
- autobyteus/tools/usage/formatters/default_json_example_formatter.py +78 -3
- autobyteus/tools/usage/formatters/default_xml_example_formatter.py +23 -3
- autobyteus/tools/usage/formatters/gemini_json_example_formatter.py +6 -0
- autobyteus/tools/usage/formatters/google_json_example_formatter.py +7 -0
- autobyteus/tools/usage/formatters/openai_json_example_formatter.py +6 -4
- autobyteus/tools/usage/parsers/gemini_json_tool_usage_parser.py +23 -7
- autobyteus/tools/usage/parsers/provider_aware_tool_usage_parser.py +14 -25
- autobyteus/tools/usage/providers/__init__.py +2 -12
- autobyteus/tools/usage/providers/tool_manifest_provider.py +36 -29
- autobyteus/tools/usage/registries/__init__.py +7 -12
- autobyteus/tools/usage/registries/tool_formatter_pair.py +15 -0
- autobyteus/tools/usage/registries/tool_formatting_registry.py +58 -0
- autobyteus/tools/usage/registries/tool_usage_parser_registry.py +55 -0
- autobyteus/workflow/agentic_workflow.py +93 -0
- autobyteus/{agent/workflow → workflow}/base_agentic_workflow.py +19 -27
- autobyteus/workflow/bootstrap_steps/__init__.py +20 -0
- autobyteus/workflow/bootstrap_steps/agent_tool_injection_step.py +34 -0
- autobyteus/workflow/bootstrap_steps/base_workflow_bootstrap_step.py +23 -0
- autobyteus/workflow/bootstrap_steps/coordinator_initialization_step.py +41 -0
- autobyteus/workflow/bootstrap_steps/coordinator_prompt_preparation_step.py +108 -0
- autobyteus/workflow/bootstrap_steps/workflow_bootstrapper.py +50 -0
- autobyteus/workflow/bootstrap_steps/workflow_runtime_queue_initialization_step.py +25 -0
- autobyteus/workflow/context/__init__.py +17 -0
- autobyteus/workflow/context/team_manager.py +147 -0
- autobyteus/workflow/context/workflow_config.py +30 -0
- autobyteus/workflow/context/workflow_context.py +61 -0
- autobyteus/workflow/context/workflow_node_config.py +76 -0
- autobyteus/workflow/context/workflow_runtime_state.py +53 -0
- autobyteus/workflow/events/__init__.py +29 -0
- autobyteus/workflow/events/workflow_event_dispatcher.py +39 -0
- autobyteus/workflow/events/workflow_events.py +53 -0
- autobyteus/workflow/events/workflow_input_event_queue_manager.py +21 -0
- autobyteus/workflow/exceptions.py +8 -0
- autobyteus/workflow/factory/__init__.py +9 -0
- autobyteus/workflow/factory/workflow_factory.py +99 -0
- autobyteus/workflow/handlers/__init__.py +19 -0
- autobyteus/workflow/handlers/base_workflow_event_handler.py +16 -0
- autobyteus/workflow/handlers/inter_agent_message_request_event_handler.py +61 -0
- autobyteus/workflow/handlers/lifecycle_workflow_event_handler.py +27 -0
- autobyteus/workflow/handlers/process_user_message_event_handler.py +46 -0
- autobyteus/workflow/handlers/tool_approval_workflow_event_handler.py +39 -0
- autobyteus/workflow/handlers/workflow_event_handler_registry.py +23 -0
- autobyteus/workflow/phases/__init__.py +11 -0
- autobyteus/workflow/phases/workflow_operational_phase.py +19 -0
- autobyteus/workflow/phases/workflow_phase_manager.py +48 -0
- autobyteus/workflow/runtime/__init__.py +13 -0
- autobyteus/workflow/runtime/workflow_runtime.py +82 -0
- autobyteus/workflow/runtime/workflow_worker.py +117 -0
- autobyteus/workflow/shutdown_steps/__init__.py +17 -0
- autobyteus/workflow/shutdown_steps/agent_team_shutdown_step.py +42 -0
- autobyteus/workflow/shutdown_steps/base_workflow_shutdown_step.py +16 -0
- autobyteus/workflow/shutdown_steps/bridge_cleanup_step.py +28 -0
- autobyteus/workflow/shutdown_steps/sub_workflow_shutdown_step.py +41 -0
- autobyteus/workflow/shutdown_steps/workflow_shutdown_orchestrator.py +35 -0
- autobyteus/workflow/streaming/__init__.py +26 -0
- autobyteus/workflow/streaming/agent_event_bridge.py +48 -0
- autobyteus/workflow/streaming/agent_event_multiplexer.py +70 -0
- autobyteus/workflow/streaming/workflow_event_bridge.py +50 -0
- autobyteus/workflow/streaming/workflow_event_notifier.py +83 -0
- autobyteus/workflow/streaming/workflow_event_stream.py +33 -0
- autobyteus/workflow/streaming/workflow_stream_event_payloads.py +28 -0
- autobyteus/workflow/streaming/workflow_stream_events.py +45 -0
- autobyteus/workflow/utils/__init__.py +9 -0
- autobyteus/workflow/utils/wait_for_idle.py +46 -0
- autobyteus/workflow/workflow_builder.py +151 -0
- {autobyteus-1.1.3.dist-info → autobyteus-1.1.5.dist-info}/METADATA +16 -14
- autobyteus-1.1.5.dist-info/RECORD +455 -0
- {autobyteus-1.1.3.dist-info → autobyteus-1.1.5.dist-info}/top_level.txt +1 -0
- examples/__init__.py +1 -0
- examples/agent_team/__init__.py +1 -0
- examples/discover_phase_transitions.py +104 -0
- examples/run_browser_agent.py +262 -0
- examples/run_google_slides_agent.py +287 -0
- examples/run_mcp_browser_client.py +174 -0
- examples/run_mcp_google_slides_client.py +270 -0
- examples/run_mcp_list_tools.py +189 -0
- examples/run_poem_writer.py +284 -0
- examples/run_sqlite_agent.py +295 -0
- autobyteus/agent/context/agent_phase_manager.py +0 -264
- autobyteus/agent/context/phases.py +0 -49
- autobyteus/agent/group/__init__.py +0 -0
- autobyteus/agent/group/agent_group.py +0 -164
- autobyteus/agent/group/agent_group_context.py +0 -81
- autobyteus/agent/input_processor/content_prefixing_input_processor.py +0 -41
- autobyteus/agent/input_processor/metadata_appending_input_processor.py +0 -34
- autobyteus/agent/input_processor/passthrough_input_processor.py +0 -33
- autobyteus/agent/workflow/__init__.py +0 -11
- autobyteus/agent/workflow/agentic_workflow.py +0 -89
- autobyteus/tools/mcp/call_handlers/__init__.py +0 -16
- autobyteus/tools/mcp/call_handlers/base_handler.py +0 -40
- autobyteus/tools/mcp/call_handlers/stdio_handler.py +0 -76
- autobyteus/tools/mcp/call_handlers/streamable_http_handler.py +0 -55
- autobyteus/tools/mcp/registrar.py +0 -202
- autobyteus/tools/usage/providers/json_example_provider.py +0 -32
- autobyteus/tools/usage/providers/json_schema_provider.py +0 -35
- autobyteus/tools/usage/providers/json_tool_usage_parser_provider.py +0 -28
- autobyteus/tools/usage/providers/xml_example_provider.py +0 -28
- autobyteus/tools/usage/providers/xml_schema_provider.py +0 -29
- autobyteus/tools/usage/providers/xml_tool_usage_parser_provider.py +0 -26
- autobyteus/tools/usage/registries/json_example_formatter_registry.py +0 -51
- autobyteus/tools/usage/registries/json_schema_formatter_registry.py +0 -51
- autobyteus/tools/usage/registries/json_tool_usage_parser_registry.py +0 -42
- autobyteus/tools/usage/registries/xml_example_formatter_registry.py +0 -30
- autobyteus/tools/usage/registries/xml_schema_formatter_registry.py +0 -33
- autobyteus/tools/usage/registries/xml_tool_usage_parser_registry.py +0 -30
- autobyteus/workflow/simple_task.py +0 -98
- autobyteus/workflow/task.py +0 -147
- autobyteus/workflow/workflow.py +0 -49
- autobyteus-1.1.3.dist-info/RECORD +0 -312
- {autobyteus-1.1.3.dist-info → autobyteus-1.1.5.dist-info}/WHEEL +0 -0
- {autobyteus-1.1.3.dist-info → autobyteus-1.1.5.dist-info}/licenses/LICENSE +0 -0
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
# file: autobyteus/autobyteus/task_management/tools/publish_task_plan.py
|
|
2
|
+
import json
|
|
3
|
+
import logging
|
|
4
|
+
from typing import TYPE_CHECKING, Optional, Dict, Any
|
|
5
|
+
|
|
6
|
+
from pydantic import ValidationError
|
|
7
|
+
# No longer need GenerateJsonSchema from pydantic.json_schema
|
|
8
|
+
# from pydantic.json_schema import GenerateJsonSchema
|
|
9
|
+
|
|
10
|
+
from autobyteus.tools.base_tool import BaseTool
|
|
11
|
+
from autobyteus.tools.tool_category import ToolCategory
|
|
12
|
+
from autobyteus.tools.parameter_schema import ParameterSchema, ParameterDefinition, ParameterType
|
|
13
|
+
from autobyteus.task_management.schemas import TaskPlanDefinitionSchema
|
|
14
|
+
from autobyteus.task_management.converters import TaskPlanConverter, TaskBoardConverter
|
|
15
|
+
|
|
16
|
+
if TYPE_CHECKING:
|
|
17
|
+
from autobyteus.agent.context import AgentContext
|
|
18
|
+
from autobyteus.agent_team.context import AgentTeamContext
|
|
19
|
+
|
|
20
|
+
logger = logging.getLogger(__name__)
|
|
21
|
+
|
|
22
|
+
class PublishTaskPlan(BaseTool):
|
|
23
|
+
"""A tool for the coordinator to parse and load a generated plan into the TaskBoard."""
|
|
24
|
+
|
|
25
|
+
CATEGORY = ToolCategory.TASK_MANAGEMENT
|
|
26
|
+
|
|
27
|
+
# The failing custom InlineSchemaGenerator has been removed.
|
|
28
|
+
|
|
29
|
+
@classmethod
|
|
30
|
+
def get_name(cls) -> str:
|
|
31
|
+
return "PublishTaskPlan"
|
|
32
|
+
|
|
33
|
+
@classmethod
|
|
34
|
+
def get_description(cls) -> str:
|
|
35
|
+
return (
|
|
36
|
+
"Parses a structured object representing a complete task plan, converts it into a "
|
|
37
|
+
"system-ready format, and loads it onto the team's shared task board. "
|
|
38
|
+
"This action resets the task board with the new plan. Upon success, it returns "
|
|
39
|
+
"the initial status of the newly loaded task board. "
|
|
40
|
+
"This tool should typically only be used by the team coordinator."
|
|
41
|
+
)
|
|
42
|
+
|
|
43
|
+
@classmethod
|
|
44
|
+
def get_argument_schema(cls) -> Optional[ParameterSchema]:
|
|
45
|
+
schema = ParameterSchema()
|
|
46
|
+
|
|
47
|
+
# CORRECTED IMPLEMENTATION:
|
|
48
|
+
# A direct, standard call to model_json_schema(). This generates a valid
|
|
49
|
+
# JSON schema with $refs, which the framework handles correctly.
|
|
50
|
+
# This completely avoids the TypeError caused by the unsupported 'ref_strategy' argument.
|
|
51
|
+
object_json_schema = TaskPlanDefinitionSchema.model_json_schema()
|
|
52
|
+
|
|
53
|
+
schema.add_parameter(ParameterDefinition(
|
|
54
|
+
name="plan",
|
|
55
|
+
param_type=ParameterType.OBJECT,
|
|
56
|
+
description=(
|
|
57
|
+
"A structured object representing a complete task plan. This object defines the overall goal "
|
|
58
|
+
"and a list of tasks with their assignees, descriptions, and dependencies. "
|
|
59
|
+
"Each task must have a unique name within the plan."
|
|
60
|
+
),
|
|
61
|
+
required=True,
|
|
62
|
+
object_schema=object_json_schema
|
|
63
|
+
))
|
|
64
|
+
return schema
|
|
65
|
+
|
|
66
|
+
async def _execute(self, context: 'AgentContext', plan: Dict[str, Any]) -> str:
|
|
67
|
+
"""
|
|
68
|
+
Executes the tool by validating the plan object, using a converter to create a TaskPlan,
|
|
69
|
+
and loading it onto the task board.
|
|
70
|
+
"""
|
|
71
|
+
logger.info(f"Agent '{context.agent_id}' is executing PublishTaskPlan.")
|
|
72
|
+
|
|
73
|
+
team_context: Optional['AgentTeamContext'] = context.custom_data.get("team_context")
|
|
74
|
+
if not team_context:
|
|
75
|
+
error_msg = "Error: Team context is not available. Cannot access the task board."
|
|
76
|
+
logger.error(f"Agent '{context.agent_id}': {error_msg}")
|
|
77
|
+
return error_msg
|
|
78
|
+
|
|
79
|
+
task_board = getattr(team_context.state, 'task_board', None)
|
|
80
|
+
if not task_board:
|
|
81
|
+
error_msg = "Error: Task board has not been initialized for this team."
|
|
82
|
+
logger.error(f"Agent '{context.agent_id}': {error_msg}")
|
|
83
|
+
return error_msg
|
|
84
|
+
|
|
85
|
+
try:
|
|
86
|
+
# Step 1: The input is now a dictionary, so we can directly validate it.
|
|
87
|
+
plan_definition_schema = TaskPlanDefinitionSchema(**plan)
|
|
88
|
+
|
|
89
|
+
# Step 2: Use the dedicated converter to create the internal TaskPlan object.
|
|
90
|
+
final_plan = TaskPlanConverter.from_schema(plan_definition_schema)
|
|
91
|
+
|
|
92
|
+
except (ValidationError, ValueError) as e:
|
|
93
|
+
error_msg = f"Invalid or inconsistent task plan provided: {e}"
|
|
94
|
+
logger.warning(f"Agent '{context.agent_id}' provided an invalid plan for PublishTaskPlan: {error_msg}")
|
|
95
|
+
return f"Error: {error_msg}"
|
|
96
|
+
except Exception as e:
|
|
97
|
+
error_msg = f"An unexpected error occurred during plan parsing or conversion: {e}"
|
|
98
|
+
logger.error(f"Agent '{context.agent_id}': {error_msg}", exc_info=True)
|
|
99
|
+
return f"Error: {error_msg}"
|
|
100
|
+
|
|
101
|
+
if task_board.load_task_plan(final_plan):
|
|
102
|
+
logger.info(f"Agent '{context.agent_id}': Task plan published successfully. Returning new board status.")
|
|
103
|
+
# Convert the new state of the board back to an LLM-friendly schema and return it.
|
|
104
|
+
status_report_schema = TaskBoardConverter.to_schema(task_board)
|
|
105
|
+
if status_report_schema:
|
|
106
|
+
return status_report_schema.model_dump_json(indent=2)
|
|
107
|
+
else:
|
|
108
|
+
# This is a fallback case, shouldn't happen right after a successful load.
|
|
109
|
+
return "Task plan published successfully, but could not generate status report."
|
|
110
|
+
else:
|
|
111
|
+
error_msg = "Failed to load task plan onto the board. This can happen if the board implementation rejects the plan."
|
|
112
|
+
logger.error(f"Agent '{context.agent_id}': {error_msg}")
|
|
113
|
+
return f"Error: {error_msg}"
|
|
@@ -0,0 +1,135 @@
|
|
|
1
|
+
import logging
|
|
2
|
+
from typing import TYPE_CHECKING, Optional, List, Dict, Any
|
|
3
|
+
|
|
4
|
+
from pydantic import ValidationError
|
|
5
|
+
|
|
6
|
+
from autobyteus.tools.base_tool import BaseTool
|
|
7
|
+
from autobyteus.tools.tool_category import ToolCategory
|
|
8
|
+
from autobyteus.tools.parameter_schema import ParameterSchema, ParameterDefinition, ParameterType
|
|
9
|
+
from autobyteus.task_management.base_task_board import TaskStatus
|
|
10
|
+
from autobyteus.task_management.deliverable import FileDeliverable
|
|
11
|
+
from autobyteus.task_management.schemas import FileDeliverableSchema
|
|
12
|
+
|
|
13
|
+
if TYPE_CHECKING:
|
|
14
|
+
from autobyteus.agent.context import AgentContext
|
|
15
|
+
from autobyteus.agent_team.context import AgentTeamContext
|
|
16
|
+
|
|
17
|
+
logger = logging.getLogger(__name__)
|
|
18
|
+
|
|
19
|
+
class UpdateTaskStatus(BaseTool):
|
|
20
|
+
"""A tool for member agents to update their progress and submit file deliverables on the TaskBoard."""
|
|
21
|
+
|
|
22
|
+
CATEGORY = ToolCategory.TASK_MANAGEMENT
|
|
23
|
+
|
|
24
|
+
@classmethod
|
|
25
|
+
def get_name(cls) -> str:
|
|
26
|
+
return "UpdateTaskStatus"
|
|
27
|
+
|
|
28
|
+
@classmethod
|
|
29
|
+
def get_description(cls) -> str:
|
|
30
|
+
return (
|
|
31
|
+
"Updates the status of a specific task on the team's shared task board. "
|
|
32
|
+
"When completing a task, this tool can also be used to formally submit a list of file deliverables."
|
|
33
|
+
)
|
|
34
|
+
|
|
35
|
+
@classmethod
|
|
36
|
+
def get_argument_schema(cls) -> Optional[ParameterSchema]:
|
|
37
|
+
schema = ParameterSchema()
|
|
38
|
+
schema.add_parameter(ParameterDefinition(
|
|
39
|
+
name="task_name",
|
|
40
|
+
param_type=ParameterType.STRING,
|
|
41
|
+
description="The unique name of the task to update (e.g., 'implement_scraper').",
|
|
42
|
+
required=True
|
|
43
|
+
))
|
|
44
|
+
schema.add_parameter(ParameterDefinition(
|
|
45
|
+
name="status",
|
|
46
|
+
param_type=ParameterType.ENUM,
|
|
47
|
+
description=f"The new status for the task. Must be one of: {', '.join([s.value for s in TaskStatus])}.",
|
|
48
|
+
required=True,
|
|
49
|
+
enum_values=[s.value for s in TaskStatus]
|
|
50
|
+
))
|
|
51
|
+
schema.add_parameter(ParameterDefinition(
|
|
52
|
+
name="deliverables",
|
|
53
|
+
param_type=ParameterType.ARRAY,
|
|
54
|
+
description="Optional. A list of file deliverables to submit for this task, typically when status is 'completed'. Each deliverable must include a file_path and a summary.",
|
|
55
|
+
required=False,
|
|
56
|
+
array_item_schema=FileDeliverableSchema.model_json_schema()
|
|
57
|
+
))
|
|
58
|
+
return schema
|
|
59
|
+
|
|
60
|
+
async def _execute(self, context: 'AgentContext', task_name: str, status: str, deliverables: Optional[List[Dict[str, Any]]] = None) -> str:
|
|
61
|
+
"""
|
|
62
|
+
Executes the tool to update a task's status and optionally submit deliverables.
|
|
63
|
+
"""
|
|
64
|
+
agent_name = context.config.name
|
|
65
|
+
log_msg = f"Agent '{agent_name}' is executing UpdateTaskStatus for task '{task_name}' to status '{status}'"
|
|
66
|
+
if deliverables:
|
|
67
|
+
log_msg += f" with {len(deliverables)} deliverable(s)."
|
|
68
|
+
logger.info(log_msg)
|
|
69
|
+
|
|
70
|
+
team_context: Optional['AgentTeamContext'] = context.custom_data.get("team_context")
|
|
71
|
+
if not team_context:
|
|
72
|
+
error_msg = "Error: Team context is not available. Cannot access the task board."
|
|
73
|
+
logger.error(f"Agent '{agent_name}': {error_msg}")
|
|
74
|
+
return error_msg
|
|
75
|
+
|
|
76
|
+
task_board = getattr(team_context.state, 'task_board', None)
|
|
77
|
+
if not task_board:
|
|
78
|
+
error_msg = "Error: Task board has not been initialized for this team."
|
|
79
|
+
logger.error(f"Agent '{agent_name}': {error_msg}")
|
|
80
|
+
return error_msg
|
|
81
|
+
|
|
82
|
+
if not task_board.current_plan:
|
|
83
|
+
error_msg = "Error: No task plan is currently loaded on the task board."
|
|
84
|
+
logger.warning(f"Agent '{agent_name}' tried to update task status, but no plan is loaded.")
|
|
85
|
+
return error_msg
|
|
86
|
+
|
|
87
|
+
# Find the task by name
|
|
88
|
+
target_task = None
|
|
89
|
+
for task in task_board.current_plan.tasks:
|
|
90
|
+
if task.task_name == task_name:
|
|
91
|
+
target_task = task
|
|
92
|
+
break
|
|
93
|
+
|
|
94
|
+
if not target_task:
|
|
95
|
+
error_msg = f"Failed to update status for task '{task_name}'. The task name does not exist on the current plan."
|
|
96
|
+
logger.warning(f"Agent '{agent_name}' failed to update status for non-existent task '{task_name}'.")
|
|
97
|
+
return f"Error: {error_msg}"
|
|
98
|
+
|
|
99
|
+
try:
|
|
100
|
+
status_enum = TaskStatus(status)
|
|
101
|
+
except ValueError:
|
|
102
|
+
error_msg = f"Invalid status '{status}'. Must be one of: {', '.join([s.value for s in TaskStatus])}."
|
|
103
|
+
logger.warning(f"Agent '{agent_name}' provided invalid status for UpdateTaskStatus: {status}")
|
|
104
|
+
return f"Error: {error_msg}"
|
|
105
|
+
|
|
106
|
+
# --- Process Deliverables FIRST --- (CORRECTED ORDER)
|
|
107
|
+
if deliverables:
|
|
108
|
+
try:
|
|
109
|
+
for d_data in deliverables:
|
|
110
|
+
# Validate and create the internal deliverable object
|
|
111
|
+
deliverable_schema = FileDeliverableSchema(**d_data)
|
|
112
|
+
full_deliverable = FileDeliverable(
|
|
113
|
+
**deliverable_schema.model_dump(),
|
|
114
|
+
author_agent_name=agent_name
|
|
115
|
+
)
|
|
116
|
+
# Append to the task object
|
|
117
|
+
target_task.file_deliverables.append(full_deliverable)
|
|
118
|
+
logger.info(f"Agent '{agent_name}' successfully processed and added {len(deliverables)} deliverables to task '{task_name}'.")
|
|
119
|
+
except (ValidationError, TypeError) as e:
|
|
120
|
+
error_msg = f"Failed to process deliverables due to invalid data: {e}. Task status was NOT updated."
|
|
121
|
+
logger.warning(f"Agent '{agent_name}': {error_msg}")
|
|
122
|
+
return f"Error: {error_msg}"
|
|
123
|
+
|
|
124
|
+
# --- Update Status SECOND --- (CORRECTED ORDER)
|
|
125
|
+
# This will now emit an event with the deliverables already attached to the task.
|
|
126
|
+
if not task_board.update_task_status(target_task.task_id, status_enum, agent_name):
|
|
127
|
+
error_msg = f"Failed to update status for task '{task_name}'. An unexpected error occurred on the task board."
|
|
128
|
+
logger.error(f"Agent '{agent_name}': {error_msg}")
|
|
129
|
+
return f"Error: {error_msg}"
|
|
130
|
+
|
|
131
|
+
success_msg = f"Successfully updated status of task '{task_name}' to '{status}'."
|
|
132
|
+
if deliverables:
|
|
133
|
+
success_msg += f" and submitted {len(deliverables)} deliverable(s)."
|
|
134
|
+
logger.info(f"Agent '{agent_name}': {success_msg}")
|
|
135
|
+
return success_msg
|
autobyteus/tools/__init__.py
CHANGED
|
@@ -10,6 +10,7 @@ from .base_tool import BaseTool
|
|
|
10
10
|
from .functional_tool import tool # The @tool decorator
|
|
11
11
|
from .parameter_schema import ParameterSchema, ParameterDefinition, ParameterType
|
|
12
12
|
from .tool_config import ToolConfig # Configuration data object, primarily for class-based tools
|
|
13
|
+
from .tool_origin import ToolOrigin
|
|
13
14
|
from .tool_category import ToolCategory
|
|
14
15
|
|
|
15
16
|
# --- Re-export specific tools for easier access ---
|
|
@@ -48,6 +49,7 @@ __all__ = [
|
|
|
48
49
|
"ParameterDefinition",
|
|
49
50
|
"ParameterType",
|
|
50
51
|
"ToolConfig",
|
|
52
|
+
"ToolOrigin",
|
|
51
53
|
"ToolCategory",
|
|
52
54
|
|
|
53
55
|
# Re-exported functional tool instances
|
|
@@ -3,13 +3,14 @@ import logging
|
|
|
3
3
|
from typing import TYPE_CHECKING
|
|
4
4
|
|
|
5
5
|
from autobyteus.tools import tool # Main @tool decorator
|
|
6
|
+
from autobyteus.tools.tool_category import ToolCategory
|
|
6
7
|
|
|
7
8
|
if TYPE_CHECKING:
|
|
8
9
|
from autobyteus.agent.context import AgentContext
|
|
9
10
|
|
|
10
11
|
logger = logging.getLogger(__name__)
|
|
11
12
|
|
|
12
|
-
@tool(name="AskUserInput")
|
|
13
|
+
@tool(name="AskUserInput", category=ToolCategory.USER_INTERACTION)
|
|
13
14
|
async def ask_user_input(context: 'AgentContext', request: str) -> str: # Function name can be ask_user_input
|
|
14
15
|
"""
|
|
15
16
|
Requests input from the user based on a given prompt and returns the user's textual response.
|
|
@@ -1,37 +1,73 @@
|
|
|
1
1
|
import asyncio
|
|
2
2
|
import subprocess
|
|
3
3
|
import logging
|
|
4
|
+
import shutil
|
|
5
|
+
import tempfile
|
|
4
6
|
from typing import TYPE_CHECKING, Optional
|
|
5
7
|
|
|
6
8
|
from autobyteus.tools import tool
|
|
9
|
+
from autobyteus.tools.tool_category import ToolCategory
|
|
7
10
|
|
|
8
11
|
if TYPE_CHECKING:
|
|
9
12
|
from autobyteus.agent.context import AgentContext
|
|
10
13
|
|
|
11
14
|
logger = logging.getLogger(__name__)
|
|
12
15
|
|
|
13
|
-
@tool(name="BashExecutor")
|
|
14
|
-
async def bash_executor(context: Optional['AgentContext'], command: str
|
|
16
|
+
@tool(name="BashExecutor", category=ToolCategory.SYSTEM)
|
|
17
|
+
async def bash_executor(context: Optional['AgentContext'], command: str) -> str:
|
|
15
18
|
"""
|
|
16
|
-
Executes bash commands
|
|
19
|
+
Executes bash commands using the '/bin/bash' interpreter.
|
|
20
|
+
On success, it returns a formatted string containing the command's standard output (stdout) and/or diagnostic logs.
|
|
21
|
+
On failure, it raises an exception.
|
|
22
|
+
- If a command has only stdout, its content is returned directly.
|
|
23
|
+
- If a command has diagnostic output (from stderr), it will be included and labeled as 'LOGS' in the output.
|
|
17
24
|
'command' is the bash command string to be executed.
|
|
18
|
-
|
|
19
|
-
Errors during command execution are raised as exceptions.
|
|
25
|
+
The command is executed in the agent's workspace directory if available.
|
|
20
26
|
"""
|
|
27
|
+
if not shutil.which("bash"):
|
|
28
|
+
error_msg = "'bash' executable not found in system PATH. The BashExecutor tool cannot be used."
|
|
29
|
+
logger.error(error_msg)
|
|
30
|
+
raise FileNotFoundError(error_msg)
|
|
31
|
+
|
|
21
32
|
agent_id_str = context.agent_id if context else "Non-Agent"
|
|
22
|
-
|
|
33
|
+
|
|
34
|
+
effective_cwd = None
|
|
35
|
+
log_cwd_source = ""
|
|
36
|
+
|
|
37
|
+
if context and hasattr(context, 'workspace') and context.workspace:
|
|
38
|
+
try:
|
|
39
|
+
base_path = context.workspace.get_base_path()
|
|
40
|
+
if base_path and isinstance(base_path, str):
|
|
41
|
+
effective_cwd = base_path
|
|
42
|
+
log_cwd_source = f"agent workspace: {effective_cwd}"
|
|
43
|
+
else:
|
|
44
|
+
logger.warning(f"Agent '{agent_id_str}' has a workspace, but it provided an invalid base path ('{base_path}'). "
|
|
45
|
+
f"Falling back to system temporary directory.")
|
|
46
|
+
except Exception as e:
|
|
47
|
+
logger.warning(f"Could not retrieve workspace for agent '{agent_id_str}': {e}. "
|
|
48
|
+
f"Falling back to system temporary directory.")
|
|
49
|
+
|
|
50
|
+
if not effective_cwd:
|
|
51
|
+
effective_cwd = tempfile.gettempdir()
|
|
52
|
+
log_cwd_source = f"system temporary directory: {effective_cwd}"
|
|
53
|
+
|
|
54
|
+
logger.debug(f"Functional BashExecutor tool executing for '{agent_id_str}': {command} in cwd from {log_cwd_source}")
|
|
23
55
|
|
|
24
56
|
try:
|
|
25
|
-
|
|
26
|
-
|
|
57
|
+
# Explicitly use 'bash -c' for reliable execution
|
|
58
|
+
process = await asyncio.create_subprocess_exec(
|
|
59
|
+
'bash', '-c', command,
|
|
27
60
|
stdout=asyncio.subprocess.PIPE,
|
|
28
61
|
stderr=asyncio.subprocess.PIPE,
|
|
29
|
-
cwd=
|
|
62
|
+
cwd=effective_cwd
|
|
30
63
|
)
|
|
31
64
|
stdout, stderr = await process.communicate()
|
|
65
|
+
|
|
66
|
+
stdout_output = stdout.decode().strip() if stdout else ""
|
|
67
|
+
stderr_output = stderr.decode().strip() if stderr else ""
|
|
32
68
|
|
|
33
69
|
if process.returncode != 0:
|
|
34
|
-
error_message =
|
|
70
|
+
error_message = stderr_output if stderr_output else "Unknown error"
|
|
35
71
|
if not error_message and process.returncode != 0:
|
|
36
72
|
error_message = f"Command failed with exit code {process.returncode} and no stderr output."
|
|
37
73
|
|
|
@@ -39,16 +75,26 @@ async def bash_executor(context: Optional['AgentContext'], command: str, cwd: Op
|
|
|
39
75
|
raise subprocess.CalledProcessError(
|
|
40
76
|
returncode=process.returncode,
|
|
41
77
|
cmd=command,
|
|
42
|
-
output=
|
|
78
|
+
output=stdout_output,
|
|
43
79
|
stderr=error_message
|
|
44
80
|
)
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
81
|
+
|
|
82
|
+
# Adaptive return for successful commands to provide maximum context to the agent.
|
|
83
|
+
if stdout_output and stderr_output:
|
|
84
|
+
return f"STDOUT:\n{stdout_output}\n\nLOGS:\n{stderr_output}"
|
|
85
|
+
elif stdout_output:
|
|
86
|
+
return stdout_output # Keep it simple for commands with only stdout
|
|
87
|
+
elif stderr_output:
|
|
88
|
+
return f"LOGS:\n{stderr_output}"
|
|
89
|
+
else:
|
|
90
|
+
return "Command executed successfully with no output."
|
|
49
91
|
|
|
50
92
|
except subprocess.CalledProcessError:
|
|
51
93
|
raise
|
|
94
|
+
except FileNotFoundError:
|
|
95
|
+
# This can be raised by create_subprocess_exec if 'bash' is not found, despite the initial check.
|
|
96
|
+
logger.error("'bash' executable not found when attempting to execute command. Please ensure it is installed and in the PATH.")
|
|
97
|
+
raise
|
|
52
98
|
except Exception as e:
|
|
53
99
|
logger.exception(f"An error occurred while preparing or executing command '{command}': {str(e)}")
|
|
54
100
|
raise RuntimeError(f"Failed to execute command '{command}': {str(e)}")
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
from autobyteus.tools.browser.session_aware.browser_session_aware_tool import BrowserSessionAwareTool
|
|
2
2
|
from autobyteus.tools.browser.session_aware.shared_browser_session import SharedBrowserSession
|
|
3
3
|
from autobyteus.tools.tool_config import ToolConfig
|
|
4
|
+
from autobyteus.tools.tool_category import ToolCategory
|
|
4
5
|
from urllib.parse import urlparse
|
|
5
6
|
from typing import Optional, TYPE_CHECKING, Any
|
|
6
7
|
import logging
|
|
@@ -16,6 +17,7 @@ class BrowserSessionAwareNavigateTo(BrowserSessionAwareTool):
|
|
|
16
17
|
"""
|
|
17
18
|
A session-aware tool for navigating to a specified website using a shared browser session.
|
|
18
19
|
"""
|
|
20
|
+
CATEGORY = ToolCategory.WEB
|
|
19
21
|
|
|
20
22
|
def __init__(self, config: Optional[ToolConfig] = None):
|
|
21
23
|
super().__init__(config=config)
|
|
@@ -9,6 +9,7 @@ from autobyteus.tools.browser.session_aware.shared_browser_session import Shared
|
|
|
9
9
|
from autobyteus.tools.browser.session_aware.web_element_action import WebElementAction
|
|
10
10
|
from autobyteus.tools.parameter_schema import ParameterSchema, ParameterDefinition, ParameterType
|
|
11
11
|
from autobyteus.tools.tool_config import ToolConfig
|
|
12
|
+
from autobyteus.tools.tool_category import ToolCategory
|
|
12
13
|
|
|
13
14
|
if TYPE_CHECKING:
|
|
14
15
|
pass
|
|
@@ -19,6 +20,8 @@ class BrowserSessionAwareWebElementTrigger(BrowserSessionAwareTool):
|
|
|
19
20
|
"""
|
|
20
21
|
A session-aware tool to trigger actions on web elements identified by a CSS selector.
|
|
21
22
|
"""
|
|
23
|
+
CATEGORY = ToolCategory.WEB
|
|
24
|
+
|
|
22
25
|
def __init__(self, config: Optional[ToolConfig] = None):
|
|
23
26
|
super().__init__(config=config)
|
|
24
27
|
logger.debug("BrowserSessionAwareWebElementTrigger tool initialized.")
|
|
@@ -6,6 +6,7 @@ from autobyteus.tools.browser.session_aware.browser_session_aware_tool import Br
|
|
|
6
6
|
from autobyteus.tools.browser.session_aware.shared_browser_session import SharedBrowserSession
|
|
7
7
|
from autobyteus.tools.tool_config import ToolConfig
|
|
8
8
|
from autobyteus.tools.parameter_schema import ParameterSchema, ParameterDefinition, ParameterType
|
|
9
|
+
from autobyteus.tools.tool_category import ToolCategory
|
|
9
10
|
from autobyteus.utils.html_cleaner import clean, CleaningMode
|
|
10
11
|
|
|
11
12
|
if TYPE_CHECKING:
|
|
@@ -18,6 +19,8 @@ class BrowserSessionAwareWebPageReader(BrowserSessionAwareTool):
|
|
|
18
19
|
A session-aware tool to read and clean HTML content from the current page
|
|
19
20
|
in a shared browser session.
|
|
20
21
|
"""
|
|
22
|
+
CATEGORY = ToolCategory.WEB
|
|
23
|
+
|
|
21
24
|
def __init__(self, config: Optional[ToolConfig] = None):
|
|
22
25
|
super().__init__(config=config)
|
|
23
26
|
|
|
@@ -7,6 +7,7 @@ from autobyteus.tools.browser.session_aware.browser_session_aware_tool import Br
|
|
|
7
7
|
from autobyteus.tools.browser.session_aware.shared_browser_session import SharedBrowserSession
|
|
8
8
|
from autobyteus.tools.tool_config import ToolConfig
|
|
9
9
|
from autobyteus.tools.parameter_schema import ParameterSchema, ParameterDefinition, ParameterType
|
|
10
|
+
from autobyteus.tools.tool_category import ToolCategory
|
|
10
11
|
|
|
11
12
|
if TYPE_CHECKING:
|
|
12
13
|
from autobyteus.agent.context import AgentContext
|
|
@@ -17,6 +18,8 @@ class BrowserSessionAwareWebPageScreenshotTaker(BrowserSessionAwareTool):
|
|
|
17
18
|
"""
|
|
18
19
|
A session-aware tool to take a screenshot of the current page in a shared browser session.
|
|
19
20
|
"""
|
|
21
|
+
CATEGORY = ToolCategory.WEB
|
|
22
|
+
|
|
20
23
|
def __init__(self, config: Optional[ToolConfig] = None):
|
|
21
24
|
super().__init__(config=config)
|
|
22
25
|
|
|
@@ -9,6 +9,7 @@ from typing import Optional, TYPE_CHECKING, Any
|
|
|
9
9
|
from autobyteus.tools.base_tool import BaseTool
|
|
10
10
|
from autobyteus.tools.tool_config import ToolConfig
|
|
11
11
|
from autobyteus.tools.parameter_schema import ParameterSchema, ParameterDefinition, ParameterType
|
|
12
|
+
from autobyteus.tools.tool_category import ToolCategory
|
|
12
13
|
from brui_core.ui_integrator import UIIntegrator
|
|
13
14
|
from autobyteus.utils.html_cleaner import clean, CleaningMode
|
|
14
15
|
|
|
@@ -22,6 +23,7 @@ class GoogleSearch(BaseTool, UIIntegrator): # Multiple inheritance
|
|
|
22
23
|
A tool that allows for performing a Google search using Playwright and retrieving the search results.
|
|
23
24
|
Inherits from BaseTool for tool framework compatibility and UIIntegrator for Playwright integration.
|
|
24
25
|
"""
|
|
26
|
+
CATEGORY = ToolCategory.WEB
|
|
25
27
|
|
|
26
28
|
def __init__(self, config: Optional[ToolConfig] = None):
|
|
27
29
|
BaseTool.__init__(self, config=config)
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
from autobyteus.tools.base_tool import BaseTool
|
|
2
2
|
from autobyteus.tools.tool_config import ToolConfig
|
|
3
|
+
from autobyteus.tools.tool_category import ToolCategory
|
|
3
4
|
from brui_core.ui_integrator import UIIntegrator
|
|
4
5
|
from urllib.parse import urlparse
|
|
5
6
|
from typing import Optional, TYPE_CHECKING, Any
|
|
@@ -17,6 +18,7 @@ class NavigateTo(BaseTool, UIIntegrator):
|
|
|
17
18
|
A standalone tool for navigating to a specified website using Playwright.
|
|
18
19
|
It initializes and closes its own browser instance for each navigation.
|
|
19
20
|
"""
|
|
21
|
+
CATEGORY = ToolCategory.WEB
|
|
20
22
|
|
|
21
23
|
def __init__(self, config: Optional[ToolConfig] = None):
|
|
22
24
|
BaseTool.__init__(self, config=config)
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
from autobyteus.tools.base_tool import BaseTool
|
|
2
2
|
from autobyteus.tools.tool_config import ToolConfig
|
|
3
|
+
from autobyteus.tools.tool_category import ToolCategory
|
|
3
4
|
from brui_core.ui_integrator import UIIntegrator
|
|
4
5
|
import os
|
|
5
6
|
import logging
|
|
@@ -18,6 +19,8 @@ class WebPagePDFGenerator(BaseTool, UIIntegrator):
|
|
|
18
19
|
A class that generates a PDF of a given webpage URL using Playwright.
|
|
19
20
|
Saves the PDF to a specified directory. This is a standalone browser tool.
|
|
20
21
|
"""
|
|
22
|
+
CATEGORY = ToolCategory.WEB
|
|
23
|
+
|
|
21
24
|
def __init__(self, config: Optional[ToolConfig] = None):
|
|
22
25
|
BaseTool.__init__(self, config=config)
|
|
23
26
|
UIIntegrator.__init__(self)
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
from autobyteus.tools.base_tool import BaseTool
|
|
2
2
|
from autobyteus.tools.tool_config import ToolConfig
|
|
3
|
+
from autobyteus.tools.tool_category import ToolCategory
|
|
3
4
|
from brui_core.ui_integrator import UIIntegrator
|
|
4
5
|
import os
|
|
5
6
|
import logging
|
|
@@ -18,6 +19,8 @@ class WebPageImageDownloader(BaseTool, UIIntegrator):
|
|
|
18
19
|
A class that downloads images (excluding SVGs and data URIs) from a given webpage URL using Playwright.
|
|
19
20
|
Saves images to a specified directory.
|
|
20
21
|
"""
|
|
22
|
+
CATEGORY = ToolCategory.WEB
|
|
23
|
+
|
|
21
24
|
def __init__(self, config: Optional[ToolConfig] = None):
|
|
22
25
|
BaseTool.__init__(self, config=config)
|
|
23
26
|
UIIntegrator.__init__(self)
|
|
@@ -8,6 +8,7 @@ from typing import Optional, TYPE_CHECKING, Any
|
|
|
8
8
|
from autobyteus.tools.base_tool import BaseTool
|
|
9
9
|
from autobyteus.tools.tool_config import ToolConfig
|
|
10
10
|
from autobyteus.tools.parameter_schema import ParameterSchema, ParameterDefinition, ParameterType
|
|
11
|
+
from autobyteus.tools.tool_category import ToolCategory
|
|
11
12
|
from brui_core.ui_integrator import UIIntegrator
|
|
12
13
|
from autobyteus.utils.html_cleaner import clean, CleaningMode
|
|
13
14
|
|
|
@@ -20,6 +21,7 @@ class WebPageReader(BaseTool, UIIntegrator):
|
|
|
20
21
|
"""
|
|
21
22
|
A class that reads and cleans the HTML content from a given webpage using Playwright.
|
|
22
23
|
"""
|
|
24
|
+
CATEGORY = ToolCategory.WEB
|
|
23
25
|
|
|
24
26
|
def __init__(self, config: Optional[ToolConfig] = None):
|
|
25
27
|
BaseTool.__init__(self, config=config)
|
|
@@ -2,6 +2,7 @@ from typing import Optional, TYPE_CHECKING, Any
|
|
|
2
2
|
from autobyteus.tools.base_tool import BaseTool
|
|
3
3
|
from autobyteus.tools.tool_config import ToolConfig
|
|
4
4
|
from autobyteus.tools.parameter_schema import ParameterSchema, ParameterDefinition, ParameterType
|
|
5
|
+
from autobyteus.tools.tool_category import ToolCategory
|
|
5
6
|
from brui_core.ui_integrator import UIIntegrator
|
|
6
7
|
import logging
|
|
7
8
|
import os
|
|
@@ -15,6 +16,8 @@ class WebPageScreenshotTaker(BaseTool, UIIntegrator):
|
|
|
15
16
|
"""
|
|
16
17
|
A class that takes a screenshot of a given webpage using Playwright and saves it.
|
|
17
18
|
"""
|
|
19
|
+
CATEGORY = ToolCategory.WEB
|
|
20
|
+
|
|
18
21
|
def __init__(self, config: Optional[ToolConfig] = None):
|
|
19
22
|
BaseTool.__init__(self, config=config)
|
|
20
23
|
UIIntegrator.__init__(self)
|
|
@@ -3,27 +3,54 @@ import logging
|
|
|
3
3
|
from typing import TYPE_CHECKING
|
|
4
4
|
|
|
5
5
|
from autobyteus.tools import tool
|
|
6
|
+
from autobyteus.tools.tool_category import ToolCategory
|
|
6
7
|
|
|
7
8
|
if TYPE_CHECKING:
|
|
8
9
|
from autobyteus.agent.context import AgentContext
|
|
9
10
|
|
|
10
11
|
logger = logging.getLogger(__name__)
|
|
11
12
|
|
|
12
|
-
@tool(name="FileReader")
|
|
13
|
-
async def file_reader(context: 'AgentContext', path: str) -> str:
|
|
13
|
+
@tool(name="FileReader", category=ToolCategory.FILE_SYSTEM)
|
|
14
|
+
async def file_reader(context: 'AgentContext', path: str) -> str:
|
|
14
15
|
"""
|
|
15
16
|
Reads content from a specified file.
|
|
16
|
-
'path' is the
|
|
17
|
+
'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.
|
|
17
19
|
Raises FileNotFoundError if the file does not exist.
|
|
18
20
|
Raises IOError if file reading fails for other reasons.
|
|
19
21
|
"""
|
|
20
|
-
logger.debug(f"Functional FileReader tool for agent {context.agent_id}, path: {path}")
|
|
21
|
-
|
|
22
|
-
|
|
22
|
+
logger.debug(f"Functional FileReader tool for agent {context.agent_id}, initial path: {path}")
|
|
23
|
+
|
|
24
|
+
final_path: str
|
|
25
|
+
if os.path.isabs(path):
|
|
26
|
+
final_path = path
|
|
27
|
+
logger.debug(f"Path '{path}' is absolute. Using it directly.")
|
|
28
|
+
else:
|
|
29
|
+
if not context.workspace:
|
|
30
|
+
error_msg = f"Relative path '{path}' provided, but no workspace is configured for agent '{context.agent_id}'. A workspace is required to resolve relative paths."
|
|
31
|
+
logger.error(error_msg)
|
|
32
|
+
raise ValueError(error_msg)
|
|
33
|
+
|
|
34
|
+
base_path = context.workspace.get_base_path()
|
|
35
|
+
if not base_path or not isinstance(base_path, str):
|
|
36
|
+
error_msg = f"Agent '{context.agent_id}' has a configured workspace, but it provided an invalid base path ('{base_path}'). Cannot resolve relative path '{path}'."
|
|
37
|
+
logger.error(error_msg)
|
|
38
|
+
raise ValueError(error_msg)
|
|
39
|
+
|
|
40
|
+
final_path = os.path.join(base_path, path)
|
|
41
|
+
logger.debug(f"Path '{path}' is relative. Resolved to '{final_path}' using workspace base path '{base_path}'.")
|
|
42
|
+
|
|
43
|
+
# It's good practice to normalize the path to handle things like '..'
|
|
44
|
+
final_path = os.path.normpath(final_path)
|
|
45
|
+
|
|
46
|
+
if not os.path.exists(final_path):
|
|
47
|
+
raise FileNotFoundError(f"The file at resolved path {final_path} does not exist.")
|
|
48
|
+
|
|
23
49
|
try:
|
|
24
|
-
with open(
|
|
50
|
+
with open(final_path, 'r', encoding='utf-8') as file:
|
|
25
51
|
content = file.read()
|
|
52
|
+
logger.info(f"File successfully read from '{final_path}' for agent '{context.agent_id}'.")
|
|
26
53
|
return content
|
|
27
54
|
except Exception as e:
|
|
28
|
-
logger.error(f"Error reading file {
|
|
29
|
-
raise IOError(f"Could not read file at {
|
|
55
|
+
logger.error(f"Error reading file from final path '{final_path}' for agent {context.agent_id}: {e}", exc_info=True)
|
|
56
|
+
raise IOError(f"Could not read file at {final_path}: {str(e)}")
|