mirror of
https://github.com/langgenius/dify.git
synced 2026-11-11 22:02:23 +08:00
Track backend integration, Ruff cleanup and migration reconciliation in ENG-1271. Retain required copy contracts without implementing frontend interactions.
87 lines
3.2 KiB
Python
87 lines
3.2 KiB
Python
"""Ordinary sandbox HTTP transport, preserving existing deployment behavior."""
|
|
|
|
import httpx
|
|
from yarl import URL
|
|
|
|
from configs import dify_config
|
|
from core.helper.http_client_pooling import get_pooled_http_client
|
|
from runtime_contracts.code_execution import CodeExecutionError, CodeExecutionResponse
|
|
|
|
code_execution_endpoint_url = URL(str(dify_config.CODE_EXECUTION_ENDPOINT))
|
|
CODE_EXECUTION_SSL_VERIFY = dify_config.CODE_EXECUTION_SSL_VERIFY
|
|
_CODE_EXECUTOR_CLIENT_LIMITS = httpx.Limits(
|
|
max_connections=dify_config.CODE_EXECUTION_POOL_MAX_CONNECTIONS,
|
|
max_keepalive_connections=dify_config.CODE_EXECUTION_POOL_MAX_KEEPALIVE_CONNECTIONS,
|
|
keepalive_expiry=dify_config.CODE_EXECUTION_POOL_KEEPALIVE_EXPIRY,
|
|
)
|
|
_CODE_EXECUTOR_CLIENT_KEY = "code_executor:http_client"
|
|
|
|
|
|
def _build_code_executor_client() -> httpx.Client:
|
|
return httpx.Client(
|
|
verify=CODE_EXECUTION_SSL_VERIFY,
|
|
limits=_CODE_EXECUTOR_CLIENT_LIMITS,
|
|
)
|
|
|
|
|
|
class OrdinaryCodeExecutionTransport:
|
|
def execute(self, *, language: str, preload: str, code: str) -> str:
|
|
"""Use the ordinary endpoint with its existing network and response semantics."""
|
|
url = code_execution_endpoint_url / "v1" / "sandbox" / "run"
|
|
|
|
headers = {"X-Api-Key": dify_config.CODE_EXECUTION_API_KEY}
|
|
|
|
data = {
|
|
"language": language,
|
|
"code": code,
|
|
"preload": preload,
|
|
"enable_network": True,
|
|
}
|
|
|
|
timeout = httpx.Timeout(
|
|
connect=dify_config.CODE_EXECUTION_CONNECT_TIMEOUT,
|
|
read=dify_config.CODE_EXECUTION_READ_TIMEOUT,
|
|
write=dify_config.CODE_EXECUTION_WRITE_TIMEOUT,
|
|
pool=None,
|
|
)
|
|
|
|
client = get_pooled_http_client(_CODE_EXECUTOR_CLIENT_KEY, _build_code_executor_client)
|
|
|
|
try:
|
|
response = client.post(
|
|
str(url),
|
|
json=data,
|
|
headers=headers,
|
|
timeout=timeout,
|
|
)
|
|
if response.status_code == 503:
|
|
raise CodeExecutionError("Code execution service is unavailable")
|
|
elif response.status_code != 200:
|
|
raise Exception(
|
|
f"Failed to execute code, got status code {response.status_code},"
|
|
f" please check if the sandbox service is running"
|
|
)
|
|
except CodeExecutionError as e:
|
|
raise e
|
|
except Exception as e:
|
|
raise CodeExecutionError(
|
|
"Failed to execute code, which is likely a network issue,"
|
|
" please check if the sandbox service is running."
|
|
f" ( Error: {str(e)} )"
|
|
) from e
|
|
|
|
try:
|
|
response_data = response.json()
|
|
except Exception as e:
|
|
raise CodeExecutionError("Failed to parse response") from e
|
|
|
|
if (code := response_data.get("code")) != 0:
|
|
raise CodeExecutionError(f"Got error code: {code}. Got error msg: {response_data.get('message')}")
|
|
|
|
response_code = CodeExecutionResponse.model_validate(response_data)
|
|
|
|
if response_code.data.error:
|
|
raise CodeExecutionError(response_code.data.error)
|
|
|
|
return response_code.data.stdout or ""
|