fix: resolve circular import by moving sandbox utils to separate module

This commit is contained in:
aran-yogesh 2026-02-12 16:47:03 -08:00
parent 5c6b9b26b2
commit 4e800dfb50
3 changed files with 57 additions and 53 deletions

View file

@ -36,56 +36,7 @@ from .middleware import (
)
from .prompt import construct_system_prompt
from .tools import commit_and_open_pr, fetch_url, http_request
def _get_langsmith_api_key() -> str | None:
"""Get LangSmith API key from environment.
Checks LANGSMITH_API_KEY first, then falls back to LANGSMITH_API_KEY_PROD
for LangGraph Cloud deployments where LANGSMITH_API_KEY is reserved.
"""
return os.environ.get("LANGSMITH_API_KEY") or os.environ.get("LANGSMITH_API_KEY_PROD")
def _get_sandbox_template_config() -> tuple[str | None, str | None]:
"""Get sandbox template configuration from environment.
Returns:
Tuple of (template_name, template_image) from environment variables.
Values are None if not set in environment.
"""
template_name = os.environ.get("DEFAULT_SANDBOX_TEMPLATE_NAME")
template_image = os.environ.get("DEFAULT_SANDBOX_TEMPLATE_IMAGE")
return template_name, template_image
def _create_langsmith_sandbox(
sandbox_id: str | None = None,
) -> SandboxBackendProtocol:
"""Create or connect to a LangSmith sandbox without automatic cleanup.
This function directly uses the LangSmithProvider to create/connect to sandboxes
without the context manager cleanup, allowing sandboxes to persist across
multiple agent invocations.
Args:
sandbox_id: Optional existing sandbox ID to connect to.
If None, creates a new sandbox.
Returns:
SandboxBackendProtocol instance
"""
from .integrations.langsmith import LangSmithProvider
api_key = _get_langsmith_api_key()
template_name, template_image = _get_sandbox_template_config()
provider = LangSmithProvider(api_key=api_key)
return provider.get_or_create(
sandbox_id=sandbox_id,
template=template_name,
template_image=template_image,
)
from .utils.sandbox import _create_langsmith_sandbox
client = get_client()

View file

@ -5,6 +5,7 @@ from typing import Any
from langgraph.config import get_config
from ..encryption import decrypt_token
from ..utils.sandbox import _create_langsmith_sandbox
from ..utils.github import (
create_github_pr,
get_github_default_branch,
@ -133,9 +134,6 @@ def commit_and_open_pr(
if not sandbox_id:
return {"success": False, "error": "No sandbox found for thread", "pr_url": None}
# Import here to avoid circular import with server.py
from ..server import _create_langsmith_sandbox
sandbox_backend = _create_langsmith_sandbox(sandbox_id)
SANDBOX_BACKENDS[thread_id] = sandbox_backend

View file

@ -0,0 +1,55 @@
"""Sandbox creation and configuration utilities."""
import os
from deepagents.backends.protocol import SandboxBackendProtocol
def _get_langsmith_api_key() -> str | None:
"""Get LangSmith API key from environment.
Checks LANGSMITH_API_KEY first, then falls back to LANGSMITH_API_KEY_PROD
for LangGraph Cloud deployments where LANGSMITH_API_KEY is reserved.
"""
return os.environ.get("LANGSMITH_API_KEY") or os.environ.get("LANGSMITH_API_KEY_PROD")
def _get_sandbox_template_config() -> tuple[str | None, str | None]:
"""Get sandbox template configuration from environment.
Returns:
Tuple of (template_name, template_image) from environment variables.
Values are None if not set in environment.
"""
template_name = os.environ.get("DEFAULT_SANDBOX_TEMPLATE_NAME")
template_image = os.environ.get("DEFAULT_SANDBOX_TEMPLATE_IMAGE")
return template_name, template_image
def _create_langsmith_sandbox(
sandbox_id: str | None = None,
) -> SandboxBackendProtocol:
"""Create or connect to a LangSmith sandbox without automatic cleanup.
This function directly uses the LangSmithProvider to create/connect to sandboxes
without the context manager cleanup, allowing sandboxes to persist across
multiple agent invocations.
Args:
sandbox_id: Optional existing sandbox ID to connect to.
If None, creates a new sandbox.
Returns:
SandboxBackendProtocol instance
"""
from ..integrations.langsmith import LangSmithProvider
api_key = _get_langsmith_api_key()
template_name, template_image = _get_sandbox_template_config()
provider = LangSmithProvider(api_key=api_key)
return provider.get_or_create(
sandbox_id=sandbox_id,
template=template_name,
template_image=template_image,
)