mirror of
https://github.com/infiniflow/ragflow.git
synced 2026-07-08 12:24:48 +08:00
240 lines
7.1 KiB
Python
240 lines
7.1 KiB
Python
|
|
#
|
||
|
|
# Copyright 2025 The InfiniFlow Authors. All Rights Reserved.
|
||
|
|
#
|
||
|
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
||
|
|
# you may not use this file except in compliance with the License.
|
||
|
|
# You may obtain a copy of the License at
|
||
|
|
#
|
||
|
|
# http://www.apache.org/licenses/LICENSE-2.0
|
||
|
|
#
|
||
|
|
# Unless required by applicable law or agreed to in writing, software
|
||
|
|
# distributed under the License is distributed on an "AS IS" BASIS,
|
||
|
|
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||
|
|
# See the License for the specific language governing permissions and
|
||
|
|
# limitations under the License.
|
||
|
|
#
|
||
|
|
|
||
|
|
"""
|
||
|
|
Sandbox client for agent components.
|
||
|
|
|
||
|
|
This module provides a unified interface for agent components to interact
|
||
|
|
with the configured sandbox provider.
|
||
|
|
"""
|
||
|
|
|
||
|
|
import json
|
||
|
|
import logging
|
||
|
|
from typing import Dict, Any, Optional
|
||
|
|
|
||
|
|
from api.db.services.system_settings_service import SystemSettingsService
|
||
|
|
from agent.sandbox.providers import ProviderManager
|
||
|
|
from agent.sandbox.providers.base import ExecutionResult
|
||
|
|
|
||
|
|
logger = logging.getLogger(__name__)
|
||
|
|
|
||
|
|
|
||
|
|
# Global provider manager instance
|
||
|
|
_provider_manager: Optional[ProviderManager] = None
|
||
|
|
|
||
|
|
|
||
|
|
def get_provider_manager() -> ProviderManager:
|
||
|
|
"""
|
||
|
|
Get the global provider manager instance.
|
||
|
|
|
||
|
|
Returns:
|
||
|
|
ProviderManager instance with active provider loaded
|
||
|
|
"""
|
||
|
|
global _provider_manager
|
||
|
|
|
||
|
|
if _provider_manager is not None:
|
||
|
|
return _provider_manager
|
||
|
|
|
||
|
|
# Initialize provider manager with system settings
|
||
|
|
_provider_manager = ProviderManager()
|
||
|
|
_load_provider_from_settings()
|
||
|
|
|
||
|
|
return _provider_manager
|
||
|
|
|
||
|
|
|
||
|
|
def _load_provider_from_settings() -> None:
|
||
|
|
"""
|
||
|
|
Load sandbox provider from system settings and configure the provider manager.
|
||
|
|
|
||
|
|
This function reads the system settings to determine which provider is active
|
||
|
|
and initializes it with the appropriate configuration.
|
||
|
|
"""
|
||
|
|
global _provider_manager
|
||
|
|
|
||
|
|
if _provider_manager is None:
|
||
|
|
return
|
||
|
|
|
||
|
|
try:
|
||
|
|
# Get active provider type
|
||
|
|
provider_type_settings = SystemSettingsService.get_by_name("sandbox.provider_type")
|
||
|
|
if not provider_type_settings:
|
||
|
|
raise RuntimeError(
|
||
|
|
"Sandbox provider type not configured. Please set 'sandbox.provider_type' in system settings."
|
||
|
|
)
|
||
|
|
provider_type = provider_type_settings[0].value
|
||
|
|
|
||
|
|
# Get provider configuration
|
||
|
|
provider_config_settings = SystemSettingsService.get_by_name(f"sandbox.{provider_type}")
|
||
|
|
|
||
|
|
if not provider_config_settings:
|
||
|
|
logger.warning(f"No configuration found for provider: {provider_type}")
|
||
|
|
config = {}
|
||
|
|
else:
|
||
|
|
try:
|
||
|
|
config = json.loads(provider_config_settings[0].value)
|
||
|
|
except json.JSONDecodeError as e:
|
||
|
|
logger.error(f"Failed to parse sandbox config for {provider_type}: {e}")
|
||
|
|
config = {}
|
||
|
|
|
||
|
|
# Import and instantiate the provider
|
||
|
|
from agent.sandbox.providers import (
|
||
|
|
SelfManagedProvider,
|
||
|
|
AliyunCodeInterpreterProvider,
|
||
|
|
E2BProvider,
|
||
|
|
)
|
||
|
|
|
||
|
|
provider_classes = {
|
||
|
|
"self_managed": SelfManagedProvider,
|
||
|
|
"aliyun_codeinterpreter": AliyunCodeInterpreterProvider,
|
||
|
|
"e2b": E2BProvider,
|
||
|
|
}
|
||
|
|
|
||
|
|
if provider_type not in provider_classes:
|
||
|
|
logger.error(f"Unknown provider type: {provider_type}")
|
||
|
|
return
|
||
|
|
|
||
|
|
provider_class = provider_classes[provider_type]
|
||
|
|
provider = provider_class()
|
||
|
|
|
||
|
|
# Initialize the provider
|
||
|
|
if not provider.initialize(config):
|
||
|
|
logger.error(f"Failed to initialize sandbox provider: {provider_type}. Config keys: {list(config.keys())}")
|
||
|
|
return
|
||
|
|
|
||
|
|
# Set the active provider
|
||
|
|
_provider_manager.set_provider(provider_type, provider)
|
||
|
|
logger.info(f"Sandbox provider '{provider_type}' initialized successfully")
|
||
|
|
|
||
|
|
except Exception as e:
|
||
|
|
logger.error(f"Failed to load sandbox provider from settings: {e}")
|
||
|
|
import traceback
|
||
|
|
traceback.print_exc()
|
||
|
|
|
||
|
|
|
||
|
|
def reload_provider() -> None:
|
||
|
|
"""
|
||
|
|
Reload the sandbox provider from system settings.
|
||
|
|
|
||
|
|
Use this function when sandbox settings have been updated.
|
||
|
|
"""
|
||
|
|
global _provider_manager
|
||
|
|
_provider_manager = None
|
||
|
|
_load_provider_from_settings()
|
||
|
|
|
||
|
|
|
||
|
|
def execute_code(
|
||
|
|
code: str,
|
||
|
|
language: str = "python",
|
||
|
|
timeout: int = 30,
|
||
|
|
arguments: Optional[Dict[str, Any]] = None
|
||
|
|
) -> ExecutionResult:
|
||
|
|
"""
|
||
|
|
Execute code in the configured sandbox.
|
||
|
|
|
||
|
|
This is the main entry point for agent components to execute code.
|
||
|
|
|
||
|
|
Args:
|
||
|
|
code: Source code to execute
|
||
|
|
language: Programming language (python, nodejs, javascript)
|
||
|
|
timeout: Maximum execution time in seconds
|
||
|
|
arguments: Optional arguments dict to pass to main() function
|
||
|
|
|
||
|
|
Returns:
|
||
|
|
ExecutionResult containing stdout, stderr, exit_code, and metadata
|
||
|
|
|
||
|
|
Raises:
|
||
|
|
RuntimeError: If no provider is configured or execution fails
|
||
|
|
"""
|
||
|
|
provider_manager = get_provider_manager()
|
||
|
|
|
||
|
|
if not provider_manager.is_configured():
|
||
|
|
raise RuntimeError(
|
||
|
|
"No sandbox provider configured. Please configure sandbox settings in the admin panel."
|
||
|
|
)
|
||
|
|
|
||
|
|
provider = provider_manager.get_provider()
|
||
|
|
|
||
|
|
# Create a sandbox instance
|
||
|
|
instance = provider.create_instance(template=language)
|
||
|
|
|
||
|
|
try:
|
||
|
|
# Execute the code
|
||
|
|
result = provider.execute_code(
|
||
|
|
instance_id=instance.instance_id,
|
||
|
|
code=code,
|
||
|
|
language=language,
|
||
|
|
timeout=timeout,
|
||
|
|
arguments=arguments
|
||
|
|
)
|
||
|
|
|
||
|
|
return result
|
||
|
|
|
||
|
|
finally:
|
||
|
|
# Clean up the instance
|
||
|
|
try:
|
||
|
|
provider.destroy_instance(instance.instance_id)
|
||
|
|
except Exception as e:
|
||
|
|
logger.warning(f"Failed to destroy sandbox instance {instance.instance_id}: {e}")
|
||
|
|
|
||
|
|
|
||
|
|
def health_check() -> bool:
|
||
|
|
"""
|
||
|
|
Check if the sandbox provider is healthy.
|
||
|
|
|
||
|
|
Returns:
|
||
|
|
True if provider is configured and healthy, False otherwise
|
||
|
|
"""
|
||
|
|
try:
|
||
|
|
provider_manager = get_provider_manager()
|
||
|
|
|
||
|
|
if not provider_manager.is_configured():
|
||
|
|
return False
|
||
|
|
|
||
|
|
provider = provider_manager.get_provider()
|
||
|
|
return provider.health_check()
|
||
|
|
|
||
|
|
except Exception as e:
|
||
|
|
logger.error(f"Sandbox health check failed: {e}")
|
||
|
|
return False
|
||
|
|
|
||
|
|
|
||
|
|
def get_provider_info() -> Dict[str, Any]:
|
||
|
|
"""
|
||
|
|
Get information about the current sandbox provider.
|
||
|
|
|
||
|
|
Returns:
|
||
|
|
Dictionary with provider information:
|
||
|
|
- provider_type: Type of the active provider
|
||
|
|
- configured: Whether provider is configured
|
||
|
|
- healthy: Whether provider is healthy
|
||
|
|
"""
|
||
|
|
try:
|
||
|
|
provider_manager = get_provider_manager()
|
||
|
|
|
||
|
|
return {
|
||
|
|
"provider_type": provider_manager.get_provider_name(),
|
||
|
|
"configured": provider_manager.is_configured(),
|
||
|
|
"healthy": health_check(),
|
||
|
|
}
|
||
|
|
|
||
|
|
except Exception as e:
|
||
|
|
logger.error(f"Failed to get provider info: {e}")
|
||
|
|
return {
|
||
|
|
"provider_type": None,
|
||
|
|
"configured": False,
|
||
|
|
"healthy": False,
|
||
|
|
}
|