mirror of
https://github.com/langbot-app/LangBot.git
synced 2026-06-12 16:56:02 +00:00
refactor(box): remove legacy in-process runtime code and clean up smells
After the architecture settled on always using an independent Box Runtime service, several pieces of compatibility code and design shortcuts were left behind. This commit cleans them up: - Remove `LocalBoxRuntimeClient` and `create_box_runtime_client` from production code (moved to test-only helper). - Remove unused `_clip_bytes` method from backend. - Remove `__langbot_session_placeholder__` hack by making `BoxSpec.cmd` default to empty and validating non-empty only in `runtime.execute()`. - Extract `get_box_config()` helper to eliminate 5× duplicated config access boilerplate. - Remove `session_id`/`host_path`/`host_path_mode` from the LLM-facing tool schema to enforce request-scoped session isolation. - Fix dual shutdown path: `NativeToolLoader.shutdown()` no longer calls `box_service.shutdown()` (handled by `Application.dispose()`). - Simplify `_assert_session_compatible` with a loop. - Inline client creation in `BoxRuntimeConnector`. - Remove redundant `BOX__RUNTIME_URL` env var from docker-compose (auto-detected by code). Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -6,7 +6,7 @@ import datetime as dt
|
||||
import logging
|
||||
|
||||
from .backend import BaseSandboxBackend, DockerBackend, PodmanBackend
|
||||
from .errors import BoxBackendUnavailableError, BoxSessionConflictError, BoxSessionNotFoundError
|
||||
from .errors import BoxBackendUnavailableError, BoxSessionConflictError, BoxSessionNotFoundError, BoxValidationError
|
||||
from .models import BoxExecutionResult, BoxExecutionStatus, BoxSessionInfo, BoxSpec
|
||||
|
||||
_UTC = dt.timezone.utc
|
||||
@@ -36,6 +36,8 @@ class BoxRuntime:
|
||||
self._backend = await self._select_backend()
|
||||
|
||||
async def execute(self, spec: BoxSpec) -> BoxExecutionResult:
|
||||
if not spec.cmd:
|
||||
raise BoxValidationError('cmd must not be empty')
|
||||
session = await self._get_or_create_session(spec)
|
||||
|
||||
async with session.lock:
|
||||
@@ -183,38 +185,18 @@ class BoxRuntime:
|
||||
self.logger.warning(f'Failed to clean up box session {session_id}: {exc}')
|
||||
|
||||
def _assert_session_compatible(self, session: BoxSessionInfo, spec: BoxSpec):
|
||||
if session.network != spec.network:
|
||||
raise BoxSessionConflictError(
|
||||
f'sandbox_exec session {spec.session_id} already exists with network={session.network.value}'
|
||||
)
|
||||
if session.image != spec.image:
|
||||
raise BoxSessionConflictError(
|
||||
f'sandbox_exec session {spec.session_id} already exists with image={session.image}'
|
||||
)
|
||||
if session.host_path != spec.host_path:
|
||||
raise BoxSessionConflictError(
|
||||
f'sandbox_exec session {spec.session_id} already exists with host_path={session.host_path}'
|
||||
)
|
||||
if session.host_path_mode != spec.host_path_mode:
|
||||
raise BoxSessionConflictError(
|
||||
f'sandbox_exec session {spec.session_id} already exists with host_path_mode={session.host_path_mode.value}'
|
||||
)
|
||||
if session.cpus != spec.cpus:
|
||||
raise BoxSessionConflictError(
|
||||
f'sandbox_exec session {spec.session_id} already exists with cpus={session.cpus}'
|
||||
)
|
||||
if session.memory_mb != spec.memory_mb:
|
||||
raise BoxSessionConflictError(
|
||||
f'sandbox_exec session {spec.session_id} already exists with memory_mb={session.memory_mb}'
|
||||
)
|
||||
if session.pids_limit != spec.pids_limit:
|
||||
raise BoxSessionConflictError(
|
||||
f'sandbox_exec session {spec.session_id} already exists with pids_limit={session.pids_limit}'
|
||||
)
|
||||
if session.read_only_rootfs != spec.read_only_rootfs:
|
||||
raise BoxSessionConflictError(
|
||||
f'sandbox_exec session {spec.session_id} already exists with read_only_rootfs={session.read_only_rootfs}'
|
||||
)
|
||||
_COMPAT_FIELDS = (
|
||||
'network', 'image', 'host_path', 'host_path_mode',
|
||||
'cpus', 'memory_mb', 'pids_limit', 'read_only_rootfs',
|
||||
)
|
||||
for field in _COMPAT_FIELDS:
|
||||
session_val = getattr(session, field)
|
||||
spec_val = getattr(spec, field)
|
||||
if session_val != spec_val:
|
||||
display = session_val.value if hasattr(session_val, 'value') else session_val
|
||||
raise BoxSessionConflictError(
|
||||
f'sandbox_exec session {spec.session_id} already exists with {field}={display}'
|
||||
)
|
||||
|
||||
@staticmethod
|
||||
def _session_to_dict(info: BoxSessionInfo) -> dict:
|
||||
|
||||
Reference in New Issue
Block a user