aip-agents-binary 0.5.20__py3-none-any.whl → 0.5.22__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.
- aip_agents/__init__.pyi +19 -0
- aip_agents/a2a/__init__.pyi +3 -0
- aip_agents/a2a/server/__init__.pyi +4 -0
- aip_agents/a2a/server/base_executor.pyi +73 -0
- aip_agents/a2a/server/google_adk_executor.pyi +51 -0
- aip_agents/a2a/server/langflow_executor.pyi +43 -0
- aip_agents/a2a/server/langgraph_executor.pyi +47 -0
- aip_agents/a2a/types.pyi +132 -0
- aip_agents/agent/__init__.pyi +9 -0
- aip_agents/agent/base_agent.pyi +221 -0
- aip_agents/agent/base_langgraph_agent.pyi +232 -0
- aip_agents/agent/google_adk_agent.pyi +141 -0
- aip_agents/agent/google_adk_constants.pyi +3 -0
- aip_agents/agent/hitl/__init__.pyi +6 -0
- aip_agents/agent/hitl/config.pyi +15 -0
- aip_agents/agent/hitl/langgraph_hitl_mixin.pyi +42 -0
- aip_agents/agent/hitl/manager.pyi +200 -0
- aip_agents/agent/hitl/models.pyi +3 -0
- aip_agents/agent/hitl/prompt/__init__.pyi +4 -0
- aip_agents/agent/hitl/prompt/base.pyi +24 -0
- aip_agents/agent/hitl/prompt/deferred.pyi +30 -0
- aip_agents/agent/hitl/registry.pyi +101 -0
- aip_agents/agent/interface.pyi +81 -0
- aip_agents/agent/interfaces.pyi +44 -0
- aip_agents/agent/langflow_agent.pyi +133 -0
- aip_agents/agent/langgraph_memory_enhancer_agent.pyi +49 -0
- aip_agents/agent/langgraph_react_agent.pyi +126 -0
- aip_agents/agent/system_instruction_context.pyi +13 -0
- aip_agents/clients/__init__.pyi +4 -0
- aip_agents/clients/langflow/__init__.pyi +4 -0
- aip_agents/clients/langflow/client.pyi +140 -0
- aip_agents/clients/langflow/types.pyi +7 -0
- aip_agents/constants.pyi +7 -0
- aip_agents/examples/__init__.pyi +0 -0
- aip_agents/examples/compare_streaming_client.pyi +48 -0
- aip_agents/examples/compare_streaming_server.pyi +18 -0
- aip_agents/examples/demo_memory_recall.pyi +58 -0
- aip_agents/examples/hello_world_a2a_google_adk_client.pyi +9 -0
- aip_agents/examples/hello_world_a2a_google_adk_client_agent.pyi +9 -0
- aip_agents/examples/hello_world_a2a_google_adk_client_streaming.pyi +9 -0
- aip_agents/examples/hello_world_a2a_google_adk_server.pyi +15 -0
- aip_agents/examples/hello_world_a2a_langchain_client.pyi +5 -0
- aip_agents/examples/hello_world_a2a_langchain_client_agent.pyi +5 -0
- aip_agents/examples/hello_world_a2a_langchain_client_lm_invoker.pyi +5 -0
- aip_agents/examples/hello_world_a2a_langchain_client_streaming.pyi +5 -0
- aip_agents/examples/hello_world_a2a_langchain_reference_client_streaming.pyi +5 -0
- aip_agents/examples/hello_world_a2a_langchain_reference_server.pyi +15 -0
- aip_agents/examples/hello_world_a2a_langchain_server.pyi +15 -0
- aip_agents/examples/hello_world_a2a_langchain_server_lm_invoker.pyi +15 -0
- aip_agents/examples/hello_world_a2a_langflow_client.pyi +9 -0
- aip_agents/examples/hello_world_a2a_langflow_server.pyi +14 -0
- aip_agents/examples/hello_world_a2a_langgraph_artifact_client.pyi +5 -0
- aip_agents/examples/hello_world_a2a_langgraph_artifact_client_streaming.pyi +5 -0
- aip_agents/examples/hello_world_a2a_langgraph_artifact_server.pyi +16 -0
- aip_agents/examples/hello_world_a2a_langgraph_client.pyi +9 -0
- aip_agents/examples/hello_world_a2a_langgraph_client_agent.pyi +9 -0
- aip_agents/examples/hello_world_a2a_langgraph_client_agent_lm_invoker.pyi +2 -0
- aip_agents/examples/hello_world_a2a_langgraph_client_streaming.pyi +9 -0
- aip_agents/examples/hello_world_a2a_langgraph_client_streaming_lm_invoker.pyi +5 -0
- aip_agents/examples/hello_world_a2a_langgraph_client_streaming_tool_streaming.pyi +5 -0
- aip_agents/examples/hello_world_a2a_langgraph_server.pyi +14 -0
- aip_agents/examples/hello_world_a2a_langgraph_server_lm_invoker.pyi +15 -0
- aip_agents/examples/hello_world_a2a_langgraph_server_tool_streaming.pyi +15 -0
- aip_agents/examples/hello_world_a2a_mcp_langgraph.pyi +48 -0
- aip_agents/examples/hello_world_a2a_three_level_agent_hierarchy_client.pyi +48 -0
- aip_agents/examples/hello_world_a2a_three_level_agent_hierarchy_server.pyi +45 -0
- aip_agents/examples/hello_world_a2a_with_metadata_langchain_client.pyi +5 -0
- aip_agents/examples/hello_world_a2a_with_metadata_langchain_server_lm_invoker.pyi +15 -0
- aip_agents/examples/hello_world_google_adk.pyi +5 -0
- aip_agents/examples/hello_world_google_adk_mcp_http.pyi +5 -0
- aip_agents/examples/hello_world_google_adk_mcp_http_stream.pyi +5 -0
- aip_agents/examples/hello_world_google_adk_mcp_sse.pyi +5 -0
- aip_agents/examples/hello_world_google_adk_mcp_sse_stream.pyi +5 -0
- aip_agents/examples/hello_world_google_adk_mcp_stdio.pyi +5 -0
- aip_agents/examples/hello_world_google_adk_mcp_stdio_stream.pyi +5 -0
- aip_agents/examples/hello_world_google_adk_stream.pyi +5 -0
- aip_agents/examples/hello_world_langchain.pyi +5 -0
- aip_agents/examples/hello_world_langchain_lm_invoker.pyi +2 -0
- aip_agents/examples/hello_world_langchain_mcp_http.pyi +5 -0
- aip_agents/examples/hello_world_langchain_mcp_http_interactive.pyi +16 -0
- aip_agents/examples/hello_world_langchain_mcp_http_stream.pyi +5 -0
- aip_agents/examples/hello_world_langchain_mcp_multi_server.pyi +18 -0
- aip_agents/examples/hello_world_langchain_mcp_sse.pyi +5 -0
- aip_agents/examples/hello_world_langchain_mcp_sse_stream.pyi +5 -0
- aip_agents/examples/hello_world_langchain_mcp_stdio.pyi +5 -0
- aip_agents/examples/hello_world_langchain_mcp_stdio_stream.pyi +5 -0
- aip_agents/examples/hello_world_langchain_stream.pyi +5 -0
- aip_agents/examples/hello_world_langchain_stream_lm_invoker.pyi +5 -0
- aip_agents/examples/hello_world_langflow_agent.pyi +35 -0
- aip_agents/examples/hello_world_langgraph.pyi +5 -0
- aip_agents/examples/{hello_world_langgraph_bosa_twitter.py → hello_world_langgraph_gl_connector_twitter.py} +10 -8
- aip_agents/examples/hello_world_langgraph_gl_connector_twitter.pyi +5 -0
- aip_agents/examples/hello_world_langgraph_mcp_http.pyi +5 -0
- aip_agents/examples/hello_world_langgraph_mcp_http_stream.pyi +5 -0
- aip_agents/examples/hello_world_langgraph_mcp_sse.pyi +5 -0
- aip_agents/examples/hello_world_langgraph_mcp_sse_stream.pyi +5 -0
- aip_agents/examples/hello_world_langgraph_mcp_stdio.pyi +5 -0
- aip_agents/examples/hello_world_langgraph_mcp_stdio_stream.pyi +5 -0
- aip_agents/examples/hello_world_langgraph_stream.pyi +5 -0
- aip_agents/examples/hello_world_langgraph_stream_lm_invoker.pyi +5 -0
- aip_agents/examples/hello_world_model_switch_cli.pyi +30 -0
- aip_agents/examples/hello_world_multi_agent_adk.pyi +6 -0
- aip_agents/examples/hello_world_multi_agent_langchain.pyi +5 -0
- aip_agents/examples/hello_world_multi_agent_langgraph.pyi +5 -0
- aip_agents/examples/hello_world_multi_agent_langgraph_lm_invoker.pyi +5 -0
- aip_agents/examples/hello_world_pii_logger.pyi +5 -0
- aip_agents/examples/hello_world_sentry.py +8 -7
- aip_agents/examples/hello_world_sentry.pyi +21 -0
- aip_agents/examples/hello_world_step_limits.pyi +17 -0
- aip_agents/examples/hello_world_stock_a2a_server.pyi +17 -0
- aip_agents/examples/hello_world_tool_output_client.pyi +5 -0
- aip_agents/examples/hello_world_tool_output_server.pyi +19 -0
- aip_agents/examples/hitl_demo.pyi +67 -0
- aip_agents/examples/pii_demo_langgraph_client.pyi +5 -0
- aip_agents/examples/pii_demo_langgraph_server.pyi +20 -0
- aip_agents/examples/pii_demo_multi_agent_client.pyi +5 -0
- aip_agents/examples/pii_demo_multi_agent_server.pyi +40 -0
- aip_agents/examples/todolist_planning_a2a_langchain_client.pyi +5 -0
- aip_agents/examples/todolist_planning_a2a_langgraph_server.pyi +19 -0
- aip_agents/examples/tools/__init__.pyi +9 -0
- aip_agents/examples/tools/adk_arithmetic_tools.pyi +24 -0
- aip_agents/examples/tools/adk_weather_tool.pyi +18 -0
- aip_agents/examples/tools/data_generator_tool.pyi +15 -0
- aip_agents/examples/tools/data_visualization_tool.pyi +19 -0
- aip_agents/examples/tools/image_artifact_tool.pyi +26 -0
- aip_agents/examples/tools/langchain_arithmetic_tools.pyi +17 -0
- aip_agents/examples/tools/langchain_currency_exchange_tool.pyi +20 -0
- aip_agents/examples/tools/langchain_graph_artifact_tool.pyi +25 -0
- aip_agents/examples/tools/langchain_weather_tool.pyi +19 -0
- aip_agents/examples/tools/langgraph_streaming_tool.pyi +43 -0
- aip_agents/examples/tools/mock_retrieval_tool.pyi +13 -0
- aip_agents/examples/tools/pii_demo_tools.pyi +54 -0
- aip_agents/examples/tools/random_chart_tool.pyi +20 -0
- aip_agents/examples/tools/serper_tool.pyi +16 -0
- aip_agents/examples/tools/stock_tools.pyi +36 -0
- aip_agents/examples/tools/table_generator_tool.pyi +22 -0
- aip_agents/examples/tools/time_tool.pyi +15 -0
- aip_agents/examples/tools/weather_forecast_tool.pyi +14 -0
- aip_agents/mcp/__init__.pyi +0 -0
- aip_agents/mcp/client/__init__.pyi +5 -0
- aip_agents/mcp/client/base_mcp_client.pyi +148 -0
- aip_agents/mcp/client/connection_manager.pyi +48 -0
- aip_agents/mcp/client/google_adk/__init__.pyi +3 -0
- aip_agents/mcp/client/google_adk/client.pyi +75 -0
- aip_agents/mcp/client/langchain/__init__.pyi +3 -0
- aip_agents/mcp/client/langchain/client.pyi +48 -0
- aip_agents/mcp/client/persistent_session.pyi +113 -0
- aip_agents/mcp/client/session_pool.pyi +101 -0
- aip_agents/mcp/client/transports.pyi +123 -0
- aip_agents/mcp/utils/__init__.pyi +0 -0
- aip_agents/mcp/utils/config_validator.pyi +82 -0
- aip_agents/memory/__init__.pyi +5 -0
- aip_agents/memory/adapters/__init__.pyi +4 -0
- aip_agents/memory/adapters/base_adapter.pyi +150 -0
- aip_agents/memory/adapters/mem0.pyi +22 -0
- aip_agents/memory/base.pyi +60 -0
- aip_agents/memory/constants.pyi +25 -0
- aip_agents/memory/factory.pyi +24 -0
- aip_agents/memory/guidance.pyi +3 -0
- aip_agents/memory/simple_memory.pyi +23 -0
- aip_agents/middleware/__init__.pyi +5 -0
- aip_agents/middleware/base.pyi +71 -0
- aip_agents/middleware/manager.pyi +80 -0
- aip_agents/middleware/todolist.pyi +125 -0
- aip_agents/schema/__init__.pyi +9 -0
- aip_agents/schema/a2a.pyi +40 -0
- aip_agents/schema/agent.pyi +65 -0
- aip_agents/schema/hitl.pyi +89 -0
- aip_agents/schema/langgraph.pyi +28 -0
- aip_agents/schema/model_id.pyi +54 -0
- aip_agents/schema/step_limit.pyi +63 -0
- aip_agents/schema/storage.pyi +21 -0
- aip_agents/sentry/__init__.py +1 -1
- aip_agents/sentry/__init__.pyi +3 -0
- aip_agents/sentry/sentry.py +17 -10
- aip_agents/sentry/sentry.pyi +48 -0
- aip_agents/storage/__init__.pyi +8 -0
- aip_agents/storage/base.pyi +58 -0
- aip_agents/storage/clients/__init__.pyi +3 -0
- aip_agents/storage/clients/minio_client.pyi +137 -0
- aip_agents/storage/config.pyi +29 -0
- aip_agents/storage/providers/__init__.pyi +5 -0
- aip_agents/storage/providers/base.pyi +88 -0
- aip_agents/storage/providers/memory.pyi +79 -0
- aip_agents/storage/providers/object_storage.pyi +98 -0
- aip_agents/tools/__init__.py +26 -6
- aip_agents/tools/__init__.pyi +9 -0
- aip_agents/tools/browser_use/__init__.pyi +14 -0
- aip_agents/tools/browser_use/action_parser.pyi +18 -0
- aip_agents/tools/browser_use/browser_use_tool.pyi +50 -0
- aip_agents/tools/browser_use/llm_config.pyi +52 -0
- aip_agents/tools/browser_use/minio_storage.pyi +109 -0
- aip_agents/tools/browser_use/schemas.pyi +32 -0
- aip_agents/tools/browser_use/session.pyi +4 -0
- aip_agents/tools/browser_use/session_errors.pyi +53 -0
- aip_agents/tools/browser_use/steel_session_recording.pyi +63 -0
- aip_agents/tools/browser_use/streaming.pyi +81 -0
- aip_agents/tools/browser_use/structured_data_parser.pyi +86 -0
- aip_agents/tools/browser_use/structured_data_recovery.pyi +43 -0
- aip_agents/tools/browser_use/types.pyi +45 -0
- aip_agents/tools/code_sandbox/__init__.pyi +3 -0
- aip_agents/tools/code_sandbox/constant.pyi +4 -0
- aip_agents/tools/code_sandbox/e2b_cloud_sandbox_extended.pyi +86 -0
- aip_agents/tools/code_sandbox/e2b_sandbox_tool.pyi +29 -0
- aip_agents/tools/constants.py +26 -12
- aip_agents/tools/constants.pyi +138 -0
- aip_agents/tools/document_loader/__init__.pyi +7 -0
- aip_agents/tools/document_loader/base_reader.pyi +75 -0
- aip_agents/tools/document_loader/docx_reader_tool.pyi +10 -0
- aip_agents/tools/document_loader/excel_reader_tool.pyi +26 -0
- aip_agents/tools/document_loader/pdf_reader_tool.pyi +11 -0
- aip_agents/tools/document_loader/pdf_splitter.pyi +18 -0
- aip_agents/tools/gl_connector/__init__.py +1 -1
- aip_agents/tools/gl_connector/__init__.pyi +3 -0
- aip_agents/tools/gl_connector/tool.py +104 -45
- aip_agents/tools/gl_connector/tool.pyi +74 -0
- aip_agents/tools/gl_connector_tools.py +122 -0
- aip_agents/tools/gl_connector_tools.pyi +39 -0
- aip_agents/tools/memory_search/__init__.pyi +5 -0
- aip_agents/tools/memory_search/base.pyi +69 -0
- aip_agents/tools/memory_search/mem0.pyi +19 -0
- aip_agents/tools/memory_search/schema.pyi +15 -0
- aip_agents/tools/memory_search_tool.pyi +3 -0
- aip_agents/tools/time_tool.pyi +16 -0
- aip_agents/tools/tool_config_injector.pyi +26 -0
- aip_agents/tools/web_search/__init__.pyi +3 -0
- aip_agents/tools/web_search/serper_tool.pyi +19 -0
- aip_agents/types/__init__.pyi +36 -0
- aip_agents/types/a2a_events.pyi +3 -0
- aip_agents/utils/__init__.pyi +11 -0
- aip_agents/utils/a2a_connector.pyi +146 -0
- aip_agents/utils/artifact_helpers.pyi +203 -0
- aip_agents/utils/constants.pyi +10 -0
- aip_agents/utils/datetime/__init__.pyi +4 -0
- aip_agents/utils/datetime/normalization.pyi +95 -0
- aip_agents/utils/datetime/timezone.pyi +48 -0
- aip_agents/utils/env_loader.pyi +10 -0
- aip_agents/utils/event_handler_registry.pyi +23 -0
- aip_agents/utils/file_prompt_utils.pyi +21 -0
- aip_agents/utils/final_response_builder.pyi +34 -0
- aip_agents/utils/formatter_llm_client.pyi +71 -0
- aip_agents/utils/langgraph/__init__.pyi +3 -0
- aip_agents/utils/langgraph/converter.pyi +49 -0
- aip_agents/utils/langgraph/tool_managers/__init__.pyi +5 -0
- aip_agents/utils/langgraph/tool_managers/a2a_tool_manager.pyi +35 -0
- aip_agents/utils/langgraph/tool_managers/base_tool_manager.pyi +48 -0
- aip_agents/utils/langgraph/tool_managers/delegation_tool_manager.pyi +56 -0
- aip_agents/utils/langgraph/tool_output_management.pyi +292 -0
- aip_agents/utils/logger.pyi +60 -0
- aip_agents/utils/metadata/__init__.pyi +5 -0
- aip_agents/utils/metadata/activity_metadata_helper.pyi +25 -0
- aip_agents/utils/metadata/activity_narrative/__init__.pyi +7 -0
- aip_agents/utils/metadata/activity_narrative/builder.pyi +35 -0
- aip_agents/utils/metadata/activity_narrative/constants.pyi +10 -0
- aip_agents/utils/metadata/activity_narrative/context.pyi +32 -0
- aip_agents/utils/metadata/activity_narrative/formatters.pyi +48 -0
- aip_agents/utils/metadata/activity_narrative/utils.pyi +12 -0
- aip_agents/utils/metadata/schemas/__init__.pyi +4 -0
- aip_agents/utils/metadata/schemas/activity_schema.pyi +18 -0
- aip_agents/utils/metadata/schemas/thinking_schema.pyi +20 -0
- aip_agents/utils/metadata/thinking_metadata_helper.pyi +4 -0
- aip_agents/utils/metadata_helper.pyi +117 -0
- aip_agents/utils/name_preprocessor/__init__.pyi +6 -0
- aip_agents/utils/name_preprocessor/base_name_preprocessor.pyi +52 -0
- aip_agents/utils/name_preprocessor/google_name_preprocessor.pyi +38 -0
- aip_agents/utils/name_preprocessor/name_preprocessor.pyi +41 -0
- aip_agents/utils/name_preprocessor/openai_name_preprocessor.pyi +34 -0
- aip_agents/utils/pii/__init__.pyi +5 -0
- aip_agents/utils/pii/pii_handler.pyi +96 -0
- aip_agents/utils/pii/pii_helper.pyi +78 -0
- aip_agents/utils/pii/uuid_deanonymizer_mapping.pyi +73 -0
- aip_agents/utils/reference_helper.pyi +81 -0
- aip_agents/utils/sse_chunk_transformer.pyi +166 -0
- aip_agents/utils/step_limit_manager.pyi +112 -0
- aip_agents/utils/token_usage_helper.pyi +60 -0
- {aip_agents_binary-0.5.20.dist-info → aip_agents_binary-0.5.22.dist-info}/METADATA +3 -3
- aip_agents_binary-0.5.22.dist-info/RECORD +546 -0
- aip_agents/tools/bosa_tools.py +0 -105
- aip_agents_binary-0.5.20.dist-info/RECORD +0 -280
- {aip_agents_binary-0.5.20.dist-info → aip_agents_binary-0.5.22.dist-info}/WHEEL +0 -0
- {aip_agents_binary-0.5.20.dist-info → aip_agents_binary-0.5.22.dist-info}/top_level.txt +0 -0
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
from browser_use.llm import ChatOpenAI
|
|
2
|
+
from typing import Any
|
|
3
|
+
|
|
4
|
+
__all__ = ['build_browser_use_llm', 'configure_browser_use_environment', 'model_disallows_tunable_params', 'supports_frequency_penalty', 'supports_temperature_override']
|
|
5
|
+
|
|
6
|
+
def model_disallows_tunable_params(model: Any) -> bool:
|
|
7
|
+
"""Return True if the provider forbids temperature/frequency overrides for the model.
|
|
8
|
+
|
|
9
|
+
Args:
|
|
10
|
+
model: The model name or identifier to check.
|
|
11
|
+
|
|
12
|
+
Returns:
|
|
13
|
+
bool: True if the model disallows tunable parameters, False otherwise.
|
|
14
|
+
"""
|
|
15
|
+
def supports_temperature_override(model: Any) -> bool:
|
|
16
|
+
"""Return True when the given model supports setting a custom temperature.
|
|
17
|
+
|
|
18
|
+
Args:
|
|
19
|
+
model: The model name or identifier to check.
|
|
20
|
+
|
|
21
|
+
Returns:
|
|
22
|
+
bool: True if the model supports temperature override, False otherwise.
|
|
23
|
+
"""
|
|
24
|
+
def supports_frequency_penalty(model: Any) -> bool:
|
|
25
|
+
"""Return True when the given model supports custom frequency penalties.
|
|
26
|
+
|
|
27
|
+
Args:
|
|
28
|
+
model: The model name or identifier to check.
|
|
29
|
+
|
|
30
|
+
Returns:
|
|
31
|
+
bool: True if the model supports frequency penalty override, False otherwise.
|
|
32
|
+
"""
|
|
33
|
+
def build_browser_use_llm(*, model: Any, reasoning_effort: Any, temperature: float | None, api_key: str, base_url: str | None = None) -> ChatOpenAI:
|
|
34
|
+
"""Construct a ChatOpenAI instance with browser-use specific safeguards.
|
|
35
|
+
|
|
36
|
+
Args:
|
|
37
|
+
model: The model name or identifier to use.
|
|
38
|
+
reasoning_effort: The reasoning effort level for the model.
|
|
39
|
+
temperature: Optional temperature setting for the model. Can be None.
|
|
40
|
+
api_key: The API key for authentication.
|
|
41
|
+
base_url: The base URL for the model.
|
|
42
|
+
|
|
43
|
+
Returns:
|
|
44
|
+
ChatOpenAI: The configured ChatOpenAI instance.
|
|
45
|
+
"""
|
|
46
|
+
def configure_browser_use_environment(enable_cloud_sync: bool, logging_level: str) -> None:
|
|
47
|
+
"""Ensure Browser Use environment flags are aligned with tool configuration.
|
|
48
|
+
|
|
49
|
+
Args:
|
|
50
|
+
enable_cloud_sync: Whether to enable cloud synchronization for browser sessions.
|
|
51
|
+
logging_level: The desired logging level for browser use operations.
|
|
52
|
+
"""
|
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
from _typeshed import Incomplete
|
|
2
|
+
|
|
3
|
+
OBJECT_NAME_PREFIX: str
|
|
4
|
+
|
|
5
|
+
class MinIOStorage:
|
|
6
|
+
"""Handles MinIO cloud storage operations for video files.
|
|
7
|
+
|
|
8
|
+
This class provides a complete interface for MinIO operations including:
|
|
9
|
+
- Connection management with authentication
|
|
10
|
+
- Bucket existence validation and creation
|
|
11
|
+
- File upload with proper metadata
|
|
12
|
+
- Presigned URL generation for secure access
|
|
13
|
+
|
|
14
|
+
Attributes:
|
|
15
|
+
endpoint: MinIO server endpoint URL.
|
|
16
|
+
access_key: MinIO access key for authentication.
|
|
17
|
+
secret_key: MinIO secret key for authentication.
|
|
18
|
+
secure: Whether to use HTTPS/TLS for connections.
|
|
19
|
+
bucket_name: Target bucket for file storage.
|
|
20
|
+
directory_prefix: Optional directory prefix for organized storage.
|
|
21
|
+
client: MinIO client instance for API operations.
|
|
22
|
+
"""
|
|
23
|
+
endpoint: Incomplete
|
|
24
|
+
access_key: Incomplete
|
|
25
|
+
secret_key: Incomplete
|
|
26
|
+
secure: Incomplete
|
|
27
|
+
bucket_name: Incomplete
|
|
28
|
+
directory_prefix: Incomplete
|
|
29
|
+
client: Incomplete
|
|
30
|
+
def __init__(self) -> None:
|
|
31
|
+
"""Initialize MinIO storage with configuration from environment variables.
|
|
32
|
+
|
|
33
|
+
Reads configuration from the following environment variables:
|
|
34
|
+
- OBJECT_STORAGE_URL: MinIO server endpoint
|
|
35
|
+
- OBJECT_STORAGE_USER: MinIO access key
|
|
36
|
+
- OBJECT_STORAGE_PASSWORD: MinIO secret key
|
|
37
|
+
- OBJECT_STORAGE_SECURE: Whether to use HTTPS (default: False)
|
|
38
|
+
- OBJECT_STORAGE_BUCKET: Target bucket name
|
|
39
|
+
- OBJECT_STORAGE_DIRECTORY_PREFIX: Optional directory prefix
|
|
40
|
+
|
|
41
|
+
Raises:
|
|
42
|
+
ValueError: If required environment variables are missing.
|
|
43
|
+
Exception: If bucket creation or validation fails.
|
|
44
|
+
|
|
45
|
+
Note:
|
|
46
|
+
The method automatically ensures the target bucket exists,
|
|
47
|
+
creating it if necessary.
|
|
48
|
+
"""
|
|
49
|
+
def get_object_name(self, object_name: str) -> str:
|
|
50
|
+
'''Get the object name with the directory prefix.
|
|
51
|
+
|
|
52
|
+
This method constructs the full object path by combining the directory
|
|
53
|
+
prefix with the base object name. It ensures consistent path structure
|
|
54
|
+
for all stored files.
|
|
55
|
+
|
|
56
|
+
Args:
|
|
57
|
+
object_name: Name of the object in MinIO.
|
|
58
|
+
|
|
59
|
+
Returns:
|
|
60
|
+
str: Object name with the directory prefix and steel-recordings subdirectory.
|
|
61
|
+
Format: {prefix}/steel-recordings/{object_name} or steel-recordings/{object_name}
|
|
62
|
+
|
|
63
|
+
Note:
|
|
64
|
+
The method automatically adds a "steel-recordings" subdirectory to
|
|
65
|
+
organize video files separately from other content.
|
|
66
|
+
'''
|
|
67
|
+
def upload_file(self, file_path: str, object_name: str) -> None:
|
|
68
|
+
'''Upload a file to MinIO bucket.
|
|
69
|
+
|
|
70
|
+
This method handles the complete file upload process including:
|
|
71
|
+
- File existence validation
|
|
72
|
+
- Proper content type setting for video files
|
|
73
|
+
- Error handling and logging
|
|
74
|
+
- Structured object naming with prefixes
|
|
75
|
+
|
|
76
|
+
Args:
|
|
77
|
+
file_path: Local path to the file to upload.
|
|
78
|
+
object_name: Name to use for the object in MinIO.
|
|
79
|
+
|
|
80
|
+
Raises:
|
|
81
|
+
Exception: If the file doesn\'t exist or upload fails.
|
|
82
|
+
Specific S3Error details are included in the exception message.
|
|
83
|
+
|
|
84
|
+
Note:
|
|
85
|
+
The method automatically sets the content type to "video/webm"
|
|
86
|
+
for proper video file handling in browsers and applications.
|
|
87
|
+
'''
|
|
88
|
+
def get_file_url(self, object_name: str) -> str:
|
|
89
|
+
"""Generate a presigned URL for accessing the uploaded file.
|
|
90
|
+
|
|
91
|
+
This method creates a temporary, secure URL that allows access to the
|
|
92
|
+
uploaded file without requiring MinIO credentials. The URL is valid
|
|
93
|
+
for a limited time and provides secure, direct access to the file.
|
|
94
|
+
|
|
95
|
+
Args:
|
|
96
|
+
object_name: Name of the object in MinIO.
|
|
97
|
+
|
|
98
|
+
Returns:
|
|
99
|
+
str: Presigned URL for secure file access.
|
|
100
|
+
The URL includes authentication tokens and is valid for a limited time.
|
|
101
|
+
|
|
102
|
+
Raises:
|
|
103
|
+
Exception: If presigned URL generation fails.
|
|
104
|
+
S3Error details are included in the exception message.
|
|
105
|
+
|
|
106
|
+
Note:
|
|
107
|
+
Presigned URLs are useful for sharing files temporarily without
|
|
108
|
+
exposing MinIO credentials or requiring users to have storage access.
|
|
109
|
+
"""
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
from openai.types.shared.chat_model import ChatModel
|
|
2
|
+
from pydantic import BaseModel
|
|
3
|
+
from typing import Literal
|
|
4
|
+
|
|
5
|
+
class BrowserUseToolInput(BaseModel):
|
|
6
|
+
"""Input schema for Browser Use tool."""
|
|
7
|
+
task: str
|
|
8
|
+
|
|
9
|
+
class BrowserUseToolConfig(BaseModel):
|
|
10
|
+
"""Tool configuration schema for Browser Use tool."""
|
|
11
|
+
steel_api_key: str
|
|
12
|
+
steel_base_url: str
|
|
13
|
+
steel_ws_url: str
|
|
14
|
+
steel_timeout_in_ms: int
|
|
15
|
+
browser_use_llm_openai_api_key: str
|
|
16
|
+
browser_use_llm_openai_model: ChatModel | str
|
|
17
|
+
browser_use_llm_openai_temperature: float | None
|
|
18
|
+
browser_use_llm_openai_reasoning_effort: Literal['minimal', 'low', 'medium', 'high']
|
|
19
|
+
browser_use_llm_openai_base_url: str | None
|
|
20
|
+
browser_use_page_extraction_llm_openai_api_key: str
|
|
21
|
+
browser_use_page_extraction_llm_openai_model: ChatModel | str
|
|
22
|
+
browser_use_page_extraction_llm_openai_temperature: float | None
|
|
23
|
+
browser_use_page_extraction_llm_openai_reasoning_effort: Literal['minimal', 'low', 'medium', 'high']
|
|
24
|
+
browser_use_page_extraction_llm_openai_base_url: str | None
|
|
25
|
+
browser_use_extend_system_message: str | None
|
|
26
|
+
browser_use_vision_detail_level: Literal['auto', 'low', 'high']
|
|
27
|
+
browser_use_enable_cloud_sync: bool
|
|
28
|
+
browser_use_logging_level: Literal['debug', 'info', 'warning', 'error', 'result']
|
|
29
|
+
browser_use_llm_timeout_in_s: int
|
|
30
|
+
browser_use_step_timeout_in_s: int
|
|
31
|
+
browser_use_max_session_retries: int
|
|
32
|
+
browser_use_session_retry_delay_in_s: float
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
from collections.abc import Iterable
|
|
2
|
+
from dataclasses import dataclass
|
|
3
|
+
|
|
4
|
+
__all__ = ['SessionErrorCategory', 'categorize_fatal_message', 'categorize_warning_message', 'find_fatal_message', 'is_recoverable_message']
|
|
5
|
+
|
|
6
|
+
@dataclass(frozen=True)
|
|
7
|
+
class SessionErrorCategory:
|
|
8
|
+
"""Represents a fatal Steel/browser disconnect classification."""
|
|
9
|
+
name: str
|
|
10
|
+
markers: tuple[str, ...]
|
|
11
|
+
fatal: bool
|
|
12
|
+
retryable: bool
|
|
13
|
+
|
|
14
|
+
def categorize_fatal_message(message: str) -> SessionErrorCategory | None:
|
|
15
|
+
"""Return the fatal session category associated with the given message, if any.
|
|
16
|
+
|
|
17
|
+
Args:
|
|
18
|
+
message: The error message to categorize.
|
|
19
|
+
|
|
20
|
+
Returns:
|
|
21
|
+
The SessionErrorCategory if the message matches a fatal error pattern,
|
|
22
|
+
None otherwise.
|
|
23
|
+
"""
|
|
24
|
+
def categorize_warning_message(message: str) -> str | None:
|
|
25
|
+
"""Return the name of a known non-fatal warning when present in the message.
|
|
26
|
+
|
|
27
|
+
Args:
|
|
28
|
+
message: The error message to check for warning patterns.
|
|
29
|
+
|
|
30
|
+
Returns:
|
|
31
|
+
The warning name if the message matches a known warning pattern,
|
|
32
|
+
None otherwise.
|
|
33
|
+
"""
|
|
34
|
+
def find_fatal_message(messages: Iterable[str]) -> tuple[str, SessionErrorCategory] | None:
|
|
35
|
+
"""Return the first fatal message detected in the iterable.
|
|
36
|
+
|
|
37
|
+
Args:
|
|
38
|
+
messages: An iterable of error messages to search through.
|
|
39
|
+
|
|
40
|
+
Returns:
|
|
41
|
+
A tuple of (message, category) for the first fatal message found,
|
|
42
|
+
None if no fatal messages are detected.
|
|
43
|
+
"""
|
|
44
|
+
def is_recoverable_message(message: str) -> bool:
|
|
45
|
+
"""Return True when the message maps to a retryable session disconnect.
|
|
46
|
+
|
|
47
|
+
Args:
|
|
48
|
+
message: The error message to check for recoverability.
|
|
49
|
+
|
|
50
|
+
Returns:
|
|
51
|
+
True if the message corresponds to a retryable fatal error,
|
|
52
|
+
False otherwise.
|
|
53
|
+
"""
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
from _typeshed import Incomplete
|
|
2
|
+
from aip_agents.tools.browser_use.minio_storage import MinIOStorage as MinIOStorage
|
|
3
|
+
from aip_agents.utils.logger import get_logger as get_logger
|
|
4
|
+
|
|
5
|
+
logger: Incomplete
|
|
6
|
+
VIDEO_FILE_NAME_PREFIX: str
|
|
7
|
+
MANIFEST_TEMP_SUFFIX: str
|
|
8
|
+
|
|
9
|
+
class SteelSessionRecorder:
|
|
10
|
+
"""High-level helper to export Steel sessions via their HLS manifests.
|
|
11
|
+
|
|
12
|
+
This class provides a high-level interface for exporting Steel sessions via their HLS manifests.
|
|
13
|
+
It provides methods for sanitizing session IDs, building safe filenames, and generating video filenames.
|
|
14
|
+
It also provides methods for downloading and merging HLS manifests, and uploading videos to MinIO.
|
|
15
|
+
"""
|
|
16
|
+
@staticmethod
|
|
17
|
+
def safe_session_id(session_id: str) -> str:
|
|
18
|
+
"""Sanitize a session ID for filename usage.
|
|
19
|
+
|
|
20
|
+
Args:
|
|
21
|
+
session_id: The session ID to sanitize.
|
|
22
|
+
|
|
23
|
+
Returns:
|
|
24
|
+
str: The sanitized session ID.
|
|
25
|
+
"""
|
|
26
|
+
@staticmethod
|
|
27
|
+
def safe_session_filename(session_id: str, extension: str) -> str:
|
|
28
|
+
"""Build a safe filename for a session recording.
|
|
29
|
+
|
|
30
|
+
Args:
|
|
31
|
+
session_id: The session ID to build a filename for.
|
|
32
|
+
extension: The extension of the filename.
|
|
33
|
+
|
|
34
|
+
Returns:
|
|
35
|
+
str: The safe filename.
|
|
36
|
+
"""
|
|
37
|
+
@staticmethod
|
|
38
|
+
def generate_video_filename(session_id: str, extension: str = '.mp4') -> str:
|
|
39
|
+
"""Generate a filename for a session recording.
|
|
40
|
+
|
|
41
|
+
Args:
|
|
42
|
+
session_id: The session ID to generate a filename for.
|
|
43
|
+
extension: The extension of the filename.
|
|
44
|
+
|
|
45
|
+
Returns:
|
|
46
|
+
str: The generated filename.
|
|
47
|
+
"""
|
|
48
|
+
base_url: Incomplete
|
|
49
|
+
api_key: Incomplete
|
|
50
|
+
minio_storage: Incomplete
|
|
51
|
+
def __init__(self, base_url: str, api_key: str) -> None:
|
|
52
|
+
"""Initialize the recorder.
|
|
53
|
+
|
|
54
|
+
Args:
|
|
55
|
+
base_url: Steel API base URL.
|
|
56
|
+
api_key: Steel API key for authentication.
|
|
57
|
+
"""
|
|
58
|
+
async def record_session_to_video(self, session_id: str) -> None:
|
|
59
|
+
"""Download the HLS manifest and upload the merged video to MinIO.
|
|
60
|
+
|
|
61
|
+
Args:
|
|
62
|
+
session_id: The session ID to record.
|
|
63
|
+
"""
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
from aip_agents.tools.browser_use.types import StreamingResponse, ToolCallInfo
|
|
2
|
+
from browser_use import Agent
|
|
3
|
+
from typing import Any, Literal
|
|
4
|
+
|
|
5
|
+
__all__ = ['PROCESSING_MESSAGE', 'TASK_COMPLETED_MESSAGE', 'create_error_response', 'create_step_response', 'generate_step_content', 'generate_thinking_message', 'yield_iframe_activity', 'yield_status_message', 'yield_thinking_marker']
|
|
6
|
+
|
|
7
|
+
TASK_COMPLETED_MESSAGE: str
|
|
8
|
+
PROCESSING_MESSAGE: str
|
|
9
|
+
|
|
10
|
+
def create_step_response(agent: Agent, tool_calls: list[ToolCallInfo], is_done: bool, content: str, thinking_message: str | None) -> StreamingResponse:
|
|
11
|
+
"""Compose the per-step payload emitted during browser-use streaming.
|
|
12
|
+
|
|
13
|
+
Args:
|
|
14
|
+
agent: Browser-use agent producing the step output.
|
|
15
|
+
tool_calls: Tool call descriptors extracted from the step.
|
|
16
|
+
is_done: Flag indicating whether this is the final step in the run.
|
|
17
|
+
content: High-level status text describing the step progress.
|
|
18
|
+
thinking_message: Optional preformatted thinking summary to attach.
|
|
19
|
+
|
|
20
|
+
Returns:
|
|
21
|
+
StreamingResponse: Serialized payload for the current streaming step.
|
|
22
|
+
"""
|
|
23
|
+
async def generate_thinking_message(content: str, tool_calls: list[dict[str, Any]], *, is_final: bool) -> str | None:
|
|
24
|
+
"""Generate a user-facing thinking summary using the formatter LLM when available.
|
|
25
|
+
|
|
26
|
+
Args:
|
|
27
|
+
content: High-level status text describing the step progress.
|
|
28
|
+
tool_calls: Serialized tool call dictionaries with outputs.
|
|
29
|
+
is_final: Whether the task has completed.
|
|
30
|
+
|
|
31
|
+
Returns:
|
|
32
|
+
Markdown-formatted summary string, or ``None`` when not applicable.
|
|
33
|
+
"""
|
|
34
|
+
def create_error_response(error_message: str, recording_url: str = '') -> dict:
|
|
35
|
+
"""Create a standardized error response.
|
|
36
|
+
|
|
37
|
+
Args:
|
|
38
|
+
error_message: The error message to include.
|
|
39
|
+
recording_url: The recording URL if available.
|
|
40
|
+
|
|
41
|
+
Returns:
|
|
42
|
+
dict: Standardized error response.
|
|
43
|
+
"""
|
|
44
|
+
def generate_step_content(tool_calls: list[ToolCallInfo], is_done: bool) -> str:
|
|
45
|
+
"""Return user-friendly status text derived from tool call outputs.
|
|
46
|
+
|
|
47
|
+
Args:
|
|
48
|
+
tool_calls: Tool call descriptors extracted from the step.
|
|
49
|
+
is_done: Flag indicating whether this is the final step in the run.
|
|
50
|
+
|
|
51
|
+
Returns:
|
|
52
|
+
User-friendly status text string.
|
|
53
|
+
"""
|
|
54
|
+
def yield_iframe_activity(url: str, content: str) -> dict:
|
|
55
|
+
"""Create and return an iframe activity streaming response.
|
|
56
|
+
|
|
57
|
+
Args:
|
|
58
|
+
url: The URL to display in the iframe.
|
|
59
|
+
content: The content message for the response.
|
|
60
|
+
|
|
61
|
+
Returns:
|
|
62
|
+
dict: Streaming response dictionary.
|
|
63
|
+
"""
|
|
64
|
+
def yield_status_message(content: str) -> dict:
|
|
65
|
+
"""Create a status update event notifying clients about recovery attempts.
|
|
66
|
+
|
|
67
|
+
Args:
|
|
68
|
+
content: The status message content to include in the event.
|
|
69
|
+
|
|
70
|
+
Returns:
|
|
71
|
+
dict: Streaming response dictionary for the status update event.
|
|
72
|
+
"""
|
|
73
|
+
def yield_thinking_marker(marker_type: Literal['start', 'end']) -> dict:
|
|
74
|
+
"""Create and return a thinking marker streaming response.
|
|
75
|
+
|
|
76
|
+
Args:
|
|
77
|
+
marker_type: Either 'start' or 'end' to indicate thinking phase.
|
|
78
|
+
|
|
79
|
+
Returns:
|
|
80
|
+
dict: Streaming response dictionary.
|
|
81
|
+
"""
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
from aip_agents.tools.browser_use.types import ToolCallInfo
|
|
2
|
+
from collections.abc import Callable, Sequence
|
|
3
|
+
from typing import Any
|
|
4
|
+
|
|
5
|
+
__all__ = ['attempt_json_recovery', 'detect_structured_data_failure', 'extract_content_after_marker', 'extract_json_blob', 'parse_structured_data', 'payload_reports_empty', 'payload_reports_error', 'structured_data_failure_for_call']
|
|
6
|
+
|
|
7
|
+
def detect_structured_data_failure(tool_calls: Sequence[ToolCallInfo], summarize_error: Callable[[str], str]) -> str | None:
|
|
8
|
+
"""Return a descriptive error when structured data extraction yields no results.
|
|
9
|
+
|
|
10
|
+
Args:
|
|
11
|
+
tool_calls: Tool call descriptors extracted from the latest agent step.
|
|
12
|
+
summarize_error: Function to summarize error messages.
|
|
13
|
+
|
|
14
|
+
Returns:
|
|
15
|
+
str | None: Failure reason when extraction yielded nothing, otherwise None.
|
|
16
|
+
"""
|
|
17
|
+
def structured_data_failure_for_call(call: ToolCallInfo, summarize_error: Callable[[str], str]) -> str | None:
|
|
18
|
+
"""Evaluate a single tool call for extractor failures.
|
|
19
|
+
|
|
20
|
+
Args:
|
|
21
|
+
call: Tool call descriptor encapsulating name/args/output.
|
|
22
|
+
summarize_error: Function to summarize error messages.
|
|
23
|
+
|
|
24
|
+
Returns:
|
|
25
|
+
str | None: Failure message when the call represents a bad extraction.
|
|
26
|
+
"""
|
|
27
|
+
def payload_reports_error(payload: dict[str, Any], raw_output: str, summarize_error: Callable[[str], str]) -> str | None:
|
|
28
|
+
"""Return a formatted error message when extractor status indicates failure.
|
|
29
|
+
|
|
30
|
+
Args:
|
|
31
|
+
payload: Parsed JSON payload emitted by the extractor.
|
|
32
|
+
raw_output: Original extractor output (used for fallback summaries).
|
|
33
|
+
summarize_error: Function to summarize error messages.
|
|
34
|
+
|
|
35
|
+
Returns:
|
|
36
|
+
str | None: Human-readable failure string when extraction failed.
|
|
37
|
+
"""
|
|
38
|
+
def payload_reports_empty(payload: dict[str, Any], raw_output: str, summarize_error: Callable[[str], str]) -> str | None:
|
|
39
|
+
"""Return a formatted message when the extractor returned no usable data.
|
|
40
|
+
|
|
41
|
+
Args:
|
|
42
|
+
payload: Parsed JSON payload emitted by the extractor.
|
|
43
|
+
raw_output: Original extractor output string.
|
|
44
|
+
summarize_error: Function to summarize error messages.
|
|
45
|
+
|
|
46
|
+
Returns:
|
|
47
|
+
str | None: Human-readable failure message when no content was extracted.
|
|
48
|
+
"""
|
|
49
|
+
def parse_structured_data(output: str, summarize_error: Callable[[str], str]) -> tuple[dict[str, Any] | list[Any] | None, str | None]:
|
|
50
|
+
"""Extract the JSON blob emitted by extract_structured_data if present.
|
|
51
|
+
|
|
52
|
+
Args:
|
|
53
|
+
output: Raw string payload returned by extract_structured_data.
|
|
54
|
+
summarize_error: Function to summarize error messages.
|
|
55
|
+
|
|
56
|
+
Returns:
|
|
57
|
+
tuple[dict[str, Any] | list[Any] | None, str | None]: Parsed JSON payload when extraction succeeds,
|
|
58
|
+
otherwise a tuple containing None and a diagnostic string on failure.
|
|
59
|
+
"""
|
|
60
|
+
def extract_content_after_marker(output: str) -> str | None:
|
|
61
|
+
"""Extract content after the 'Extracted Content:' marker and clean trailing metadata.
|
|
62
|
+
|
|
63
|
+
Args:
|
|
64
|
+
output: Raw string payload returned by extract_structured_data.
|
|
65
|
+
|
|
66
|
+
Returns:
|
|
67
|
+
str | None: Cleaned content after the marker, or None if marker not found.
|
|
68
|
+
"""
|
|
69
|
+
def extract_json_blob(content: str) -> str | None:
|
|
70
|
+
"""Extract the JSON blob from content by finding delimiters and trimming trailing content.
|
|
71
|
+
|
|
72
|
+
Args:
|
|
73
|
+
content: Content string potentially containing JSON.
|
|
74
|
+
|
|
75
|
+
Returns:
|
|
76
|
+
str | None: Extracted JSON blob, or None if no valid JSON delimiters found.
|
|
77
|
+
"""
|
|
78
|
+
def attempt_json_recovery(json_blob: str) -> dict[str, Any] | list[Any] | None:
|
|
79
|
+
"""Attempt to parse JSON blob, with recovery strategies for common issues.
|
|
80
|
+
|
|
81
|
+
Args:
|
|
82
|
+
json_blob: JSON string to attempt parsing.
|
|
83
|
+
|
|
84
|
+
Returns:
|
|
85
|
+
dict[str, Any] | list[Any] | None: Parsed JSON data if successful, None if all recovery attempts fail.
|
|
86
|
+
"""
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
from _typeshed import Incomplete
|
|
2
|
+
from aip_agents.utils.logger import get_logger as get_logger
|
|
3
|
+
from typing import Any
|
|
4
|
+
|
|
5
|
+
logger: Incomplete
|
|
6
|
+
|
|
7
|
+
def recover_concatenated_json_objects(json_blob: str) -> dict[str, Any] | None:
|
|
8
|
+
"""Normalize concatenated JSON object strings into a structured payload.
|
|
9
|
+
|
|
10
|
+
Args:
|
|
11
|
+
json_blob: Raw JSON-like string returned by the structured data extractor.
|
|
12
|
+
|
|
13
|
+
Returns:
|
|
14
|
+
dict[str, Any] | None: Standardized payload when multiple objects are recovered,
|
|
15
|
+
otherwise None.
|
|
16
|
+
"""
|
|
17
|
+
def repair_json_blob(json_blob: str) -> str | None:
|
|
18
|
+
"""Apply json_repair to malformed JSON strings and return the mutated payload.
|
|
19
|
+
|
|
20
|
+
Args:
|
|
21
|
+
json_blob: Raw JSON string that may contain syntax mistakes.
|
|
22
|
+
|
|
23
|
+
Returns:
|
|
24
|
+
str | None: Repaired JSON string when modifications were applied, otherwise None.
|
|
25
|
+
"""
|
|
26
|
+
|
|
27
|
+
class _JsonObjectSplitter:
|
|
28
|
+
"""Helper class to split JSON objects with reduced cognitive complexity."""
|
|
29
|
+
json_blob: Incomplete
|
|
30
|
+
segments: list[str]
|
|
31
|
+
depth: int
|
|
32
|
+
start: int | None
|
|
33
|
+
last_end: int
|
|
34
|
+
in_string: bool
|
|
35
|
+
escaping: bool
|
|
36
|
+
def __init__(self, json_blob: str) -> None:
|
|
37
|
+
"""Initialize the splitter with the raw JSON string.
|
|
38
|
+
|
|
39
|
+
Args:
|
|
40
|
+
json_blob: Raw string potentially containing concatenated JSON objects.
|
|
41
|
+
"""
|
|
42
|
+
def split_objects(self) -> list[str]:
|
|
43
|
+
"""Main method to split JSON objects."""
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
from dataclasses import dataclass
|
|
2
|
+
from typing import Any
|
|
3
|
+
|
|
4
|
+
__all__ = ['BrowserUseFatalError', 'RetryDecision', 'StreamingResponse', 'StreamingState', 'ToolCallInfo']
|
|
5
|
+
|
|
6
|
+
class BrowserUseFatalError(RuntimeError):
|
|
7
|
+
"""Raised when the Browser Use session must terminate immediately."""
|
|
8
|
+
|
|
9
|
+
@dataclass
|
|
10
|
+
class ToolCallInfo:
|
|
11
|
+
"""Structured information for a single tool call."""
|
|
12
|
+
name: str
|
|
13
|
+
args: dict[str, Any]
|
|
14
|
+
output: str
|
|
15
|
+
|
|
16
|
+
@dataclass
|
|
17
|
+
class StreamingResponse:
|
|
18
|
+
"""Standardized streaming response structure."""
|
|
19
|
+
event_type: str
|
|
20
|
+
content: str
|
|
21
|
+
thinking_and_activity_info: dict
|
|
22
|
+
is_final: bool
|
|
23
|
+
tool_info: dict[str, Any] | None = ...
|
|
24
|
+
metadata: dict[str, Any] | None = ...
|
|
25
|
+
def to_dict(self) -> dict[str, Any]:
|
|
26
|
+
"""Convert to dictionary format for yielding."""
|
|
27
|
+
|
|
28
|
+
@dataclass
|
|
29
|
+
class StreamingState:
|
|
30
|
+
"""State management for streaming operations."""
|
|
31
|
+
debug_url: str
|
|
32
|
+
recording_url: str
|
|
33
|
+
step_count: int = ...
|
|
34
|
+
is_complete: bool = ...
|
|
35
|
+
session_id: str | None = ...
|
|
36
|
+
terminal_error: str | None = ...
|
|
37
|
+
recording_started: bool = ...
|
|
38
|
+
|
|
39
|
+
@dataclass
|
|
40
|
+
class RetryDecision:
|
|
41
|
+
"""Encapsulate retry metadata when Steel sessions need to be restarted."""
|
|
42
|
+
retries_remaining: int
|
|
43
|
+
attempted_retries: int
|
|
44
|
+
message: str
|
|
45
|
+
delay: float
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
from _typeshed import Incomplete
|
|
2
|
+
from aip_agents.tools.code_sandbox.constant import DATA_FILE_PATH as DATA_FILE_PATH
|
|
3
|
+
from aip_agents.utils.logger import get_logger as get_logger
|
|
4
|
+
from gllm_inference.schema import Attachment as Attachment
|
|
5
|
+
from gllm_tools.code_interpreter.code_sandbox.e2b_cloud_sandbox import E2BCloudSandbox
|
|
6
|
+
from gllm_tools.code_interpreter.code_sandbox.models import ExecutionResult
|
|
7
|
+
from typing import Any
|
|
8
|
+
|
|
9
|
+
logger: Incomplete
|
|
10
|
+
|
|
11
|
+
class SandboxFileWatcher:
|
|
12
|
+
"""File watcher for monitoring file creation in sandbox environments."""
|
|
13
|
+
sandbox: Incomplete
|
|
14
|
+
def __init__(self, sandbox: Any) -> None:
|
|
15
|
+
"""Initialize the file watcher with a sandbox instance.
|
|
16
|
+
|
|
17
|
+
Args:
|
|
18
|
+
sandbox (Any): The sandbox instance to monitor.
|
|
19
|
+
"""
|
|
20
|
+
def setup_monitoring(self) -> None:
|
|
21
|
+
"""Set up filesystem watchers for monitoring file creation.
|
|
22
|
+
|
|
23
|
+
Note: /tmp/output is a sandbox-isolated directory, not a shared system /tmp.
|
|
24
|
+
This directory is scoped to the E2B sandbox instance and is safe for use.
|
|
25
|
+
"""
|
|
26
|
+
async def process_events(self) -> None:
|
|
27
|
+
"""Process filesystem events from watchers and update created files list."""
|
|
28
|
+
def reset_created_files(self) -> None:
|
|
29
|
+
"""Reset the list of created files."""
|
|
30
|
+
def get_created_files(self) -> list[str]:
|
|
31
|
+
"""Get the list of files created during monitoring.
|
|
32
|
+
|
|
33
|
+
Returns:
|
|
34
|
+
list[str]: List of file paths that were created.
|
|
35
|
+
"""
|
|
36
|
+
|
|
37
|
+
class MyE2BCloudSandbox(E2BCloudSandbox):
|
|
38
|
+
"""Extended E2B Cloud Sandbox with filesystem monitoring capabilities."""
|
|
39
|
+
file_watcher: SandboxFileWatcher | None
|
|
40
|
+
def __init__(self, *args, **kwargs) -> None:
|
|
41
|
+
"""Initialize the sandbox with monitoring capabilities.
|
|
42
|
+
|
|
43
|
+
Args:
|
|
44
|
+
*args: Positional arguments forwarded to ``E2BCloudSandbox``.
|
|
45
|
+
**kwargs: Keyword arguments forwarded to ``E2BCloudSandbox``.
|
|
46
|
+
"""
|
|
47
|
+
async def execute_code(self, code: str, timeout: int = 30, files: list[Attachment] | None = None, **kwargs: Any) -> ExecutionResult:
|
|
48
|
+
"""Execute code in the E2B Cloud sandbox with filesystem monitoring.
|
|
49
|
+
|
|
50
|
+
This override fixes the Pydantic validation error by ensuring execution.error
|
|
51
|
+
is converted to string. Always enables filesystem monitoring to track
|
|
52
|
+
created files.
|
|
53
|
+
|
|
54
|
+
Args:
|
|
55
|
+
code (str): The code to execute.
|
|
56
|
+
timeout (int, optional): Maximum execution time in seconds. Defaults to 30.
|
|
57
|
+
files (list[Attachment] | None, optional): List of Attachment objects with file details. Defaults to None.
|
|
58
|
+
**kwargs (Any): Additional execution parameters.
|
|
59
|
+
|
|
60
|
+
Returns:
|
|
61
|
+
ExecutionResult: Structured result of the execution.
|
|
62
|
+
|
|
63
|
+
Raises:
|
|
64
|
+
RuntimeError: If sandbox is not initialized.
|
|
65
|
+
"""
|
|
66
|
+
def get_created_files(self) -> list[str]:
|
|
67
|
+
"""Get the list of files created during the last monitored execution.
|
|
68
|
+
|
|
69
|
+
Returns:
|
|
70
|
+
list[str]: List of file paths that were created.
|
|
71
|
+
"""
|
|
72
|
+
def download_file(self, file_path: str) -> bytes | None:
|
|
73
|
+
"""Download file content from the sandbox.
|
|
74
|
+
|
|
75
|
+
Uses download_url method to get a direct URL and downloads via HTTP,
|
|
76
|
+
which avoids the binary corruption issue with files.read().
|
|
77
|
+
|
|
78
|
+
Args:
|
|
79
|
+
file_path (str): Path to the file in the sandbox.
|
|
80
|
+
|
|
81
|
+
Returns:
|
|
82
|
+
bytes | None: File content as bytes, or None if download fails.
|
|
83
|
+
|
|
84
|
+
Raises:
|
|
85
|
+
RuntimeError: If sandbox is not initialized.
|
|
86
|
+
"""
|