mirror of
https://github.com/langbot-app/LangBot.git
synced 2026-08-18 00:10:59 +00:00
refactor(box): run Box Runtime as subprocess inside LangBot container
Remove the separate langbot_box_runtime Docker service. Box Runtime now always launches as a local stdio subprocess, regardless of whether LangBot runs in Docker or not. The WebSocket transport path is kept only for explicit runtime_url configuration (remote deployment). This simplifies deployment by eliminating cross-container path mapping and network hops. Box Runtime is a pure scheduling process (talks to Docker socket / nsjail), it does not execute user code or touch the filesystem, so container isolation is unnecessary — unlike Plugin Runtime.
This commit is contained in:
@@ -4,24 +4,6 @@ version: "3"
|
|||||||
|
|
||||||
services:
|
services:
|
||||||
|
|
||||||
langbot_box_runtime:
|
|
||||||
image: rockchin/langbot:latest
|
|
||||||
container_name: langbot_box_runtime
|
|
||||||
command: ["uv", "run", "--no-sync", "-m", "langbot_plugin.box.server"]
|
|
||||||
volumes:
|
|
||||||
# Mount the container runtime socket from the host.
|
|
||||||
# Uncomment the one that matches your container runtime:
|
|
||||||
# - /var/run/podman/podman.sock:/var/run/podman/podman.sock # Podman
|
|
||||||
- /var/run/docker.sock:/var/run/docker.sock # Docker
|
|
||||||
- ./data/box:/workspaces
|
|
||||||
ports:
|
|
||||||
- 5410:5410
|
|
||||||
restart: on-failure
|
|
||||||
environment:
|
|
||||||
- TZ=Asia/Shanghai
|
|
||||||
networks:
|
|
||||||
- langbot_network
|
|
||||||
|
|
||||||
langbot_plugin_runtime:
|
langbot_plugin_runtime:
|
||||||
image: rockchin/langbot:latest
|
image: rockchin/langbot:latest
|
||||||
container_name: langbot_plugin_runtime
|
container_name: langbot_plugin_runtime
|
||||||
@@ -42,6 +24,10 @@ services:
|
|||||||
volumes:
|
volumes:
|
||||||
- ./data:/app/data
|
- ./data:/app/data
|
||||||
- ./data/box:/workspaces
|
- ./data/box:/workspaces
|
||||||
|
# Mount container runtime socket for Box sandbox (Docker backend).
|
||||||
|
# Uncomment the one that matches your container runtime:
|
||||||
|
# - /var/run/podman/podman.sock:/var/run/podman/podman.sock # Podman
|
||||||
|
- /var/run/docker.sock:/var/run/docker.sock # Docker
|
||||||
restart: on-failure
|
restart: on-failure
|
||||||
environment:
|
environment:
|
||||||
- TZ=Asia/Shanghai
|
- TZ=Asia/Shanghai
|
||||||
|
|||||||
@@ -12,7 +12,6 @@ from langbot_plugin.runtime.io.connection import Connection
|
|||||||
|
|
||||||
from langbot_plugin.box.client import ActionRPCBoxClient
|
from langbot_plugin.box.client import ActionRPCBoxClient
|
||||||
from langbot_plugin.box.errors import BoxRuntimeUnavailableError
|
from langbot_plugin.box.errors import BoxRuntimeUnavailableError
|
||||||
from ..utils import platform
|
|
||||||
|
|
||||||
if TYPE_CHECKING:
|
if TYPE_CHECKING:
|
||||||
from ..core import app as core_app
|
from ..core import app as core_app
|
||||||
@@ -31,8 +30,6 @@ def resolve_box_ws_relay_url(ap: core_app.Application) -> str:
|
|||||||
if runtime_url:
|
if runtime_url:
|
||||||
return runtime_url
|
return runtime_url
|
||||||
|
|
||||||
if platform.get_platform() == 'docker':
|
|
||||||
return 'http://langbot_box_runtime:5410'
|
|
||||||
return 'http://127.0.0.1:5410'
|
return 'http://127.0.0.1:5410'
|
||||||
|
|
||||||
|
|
||||||
@@ -160,4 +157,4 @@ class BoxRuntimeConnector:
|
|||||||
return str(_get_box_config(self.ap).get('runtime_url', '')).strip()
|
return str(_get_box_config(self.ap).get('runtime_url', '')).strip()
|
||||||
|
|
||||||
def _should_manage_local_runtime(self) -> bool:
|
def _should_manage_local_runtime(self) -> bool:
|
||||||
return not self.configured_runtime_url and platform.get_platform() != 'docker'
|
return not self.configured_runtime_url
|
||||||
|
|||||||
@@ -89,7 +89,7 @@ monitoring:
|
|||||||
check_interval_hours: 1
|
check_interval_hours: 1
|
||||||
box:
|
box:
|
||||||
profile: 'default'
|
profile: 'default'
|
||||||
runtime_url: '' # Leave empty to use defaults: http://127.0.0.1:5410 locally, http://langbot_box_runtime:5410 in Docker
|
runtime_url: '' # Leave empty to auto-launch local Box Runtime subprocess. Set to a URL only for remote/external deployment.
|
||||||
shared_host_root: './data/box' # For Docker deployment, use '/workspaces'
|
shared_host_root: './data/box' # For Docker deployment, use '/workspaces'
|
||||||
default_host_workspace: '' # Defaults to '<shared_host_root>/default'
|
default_host_workspace: '' # Defaults to '<shared_host_root>/default'
|
||||||
allowed_host_mount_roots: # Defaults to ['<shared_host_root>'] when left empty
|
allowed_host_mount_roots: # Defaults to ['<shared_host_root>'] when left empty
|
||||||
|
|||||||
@@ -25,12 +25,7 @@ def make_app(logger: Mock, runtime_url: str = ''):
|
|||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
def patch_platform(monkeypatch: pytest.MonkeyPatch, value: str):
|
def test_box_runtime_connector_manages_local_when_no_url():
|
||||||
monkeypatch.setattr('langbot.pkg.box.connector.platform.get_platform', lambda: value)
|
|
||||||
|
|
||||||
|
|
||||||
def test_box_runtime_connector_manages_local_when_no_url(monkeypatch: pytest.MonkeyPatch):
|
|
||||||
patch_platform(monkeypatch, 'linux')
|
|
||||||
connector = BoxRuntimeConnector(make_app(Mock()))
|
connector = BoxRuntimeConnector(make_app(Mock()))
|
||||||
|
|
||||||
assert connector.manages_local_runtime is True
|
assert connector.manages_local_runtime is True
|
||||||
@@ -45,16 +40,15 @@ def test_box_runtime_connector_remote_when_url_configured():
|
|||||||
assert isinstance(connector.client, ActionRPCBoxClient)
|
assert isinstance(connector.client, ActionRPCBoxClient)
|
||||||
|
|
||||||
|
|
||||||
def test_box_runtime_connector_remote_when_docker(monkeypatch: pytest.MonkeyPatch):
|
def test_box_runtime_connector_manages_local_in_docker(monkeypatch: pytest.MonkeyPatch):
|
||||||
patch_platform(monkeypatch, 'docker')
|
monkeypatch.setattr('langbot.pkg.utils.platform.get_platform', lambda: 'docker')
|
||||||
connector = BoxRuntimeConnector(make_app(Mock()))
|
connector = BoxRuntimeConnector(make_app(Mock()))
|
||||||
|
|
||||||
assert connector.manages_local_runtime is False
|
assert connector.manages_local_runtime is True
|
||||||
assert connector.ws_relay_base_url == 'http://langbot_box_runtime:5410'
|
assert connector.ws_relay_base_url == 'http://127.0.0.1:5410'
|
||||||
|
|
||||||
|
|
||||||
def test_box_runtime_connector_ws_relay_url_default(monkeypatch: pytest.MonkeyPatch):
|
def test_box_runtime_connector_ws_relay_url_default():
|
||||||
patch_platform(monkeypatch, 'linux')
|
|
||||||
connector = BoxRuntimeConnector(make_app(Mock()))
|
connector = BoxRuntimeConnector(make_app(Mock()))
|
||||||
|
|
||||||
assert connector.ws_relay_base_url == 'http://127.0.0.1:5410'
|
assert connector.ws_relay_base_url == 'http://127.0.0.1:5410'
|
||||||
|
|||||||
Reference in New Issue
Block a user