refactor(box): launch box runtime via the lbp CLI subcommand

Mirror the plugin runtime: box is now started through the same CLI entry
point (langbot_plugin.cli) instead of the box module directly.

- docker-compose.yaml: langbot_box command runs `langbot_plugin.cli ... box`
  (WebSocket is the default transport, no flag needed — matches `rt`).
- box/connector.py: both subprocess launch sites (_start_local_stdio and
  the Windows _start_subprocess_then_ws path) invoke
  `langbot_plugin.cli.__init__ box`, using `-s` for the stdio transport.
- docs/review: update stale `-m langbot_plugin.box[.server]` references.

Pairs with the SDK change that removes box's direct-launch entry points
(python -m langbot_plugin.box / .box.server) and the legacy --mode flag.
This commit is contained in:
Junyan Qin
2026-05-21 13:21:03 +08:00
parent d1ddff9cdb
commit 34302213ae
4 changed files with 16 additions and 5 deletions

View File

@@ -43,7 +43,12 @@ services:
# The Box runtime does NOT read box.local.* from config.yaml or env; it
# receives its configuration from LangBot via the INIT RPC action.
# Do not add LANGBOT_BOX_* / BOX__* here — they would be silently ignored.
command: ["uv", "run", "--no-sync", "-m", "langbot_plugin.box", "--mode", "ws"]
# Launched through the same CLI entry point as the plugin runtime
# (`langbot_plugin.cli.__init__ <subcommand>`). WebSocket is the default
# control transport — mirrors `rt`, which also runs with no flag. Pass
# `-s` / `--stdio-control` only for the stdio mode LangBot uses outside
# containers.
command: ["uv", "run", "--no-sync", "-m", "langbot_plugin.cli.__init__", "box"]
networks:
- langbot_network

View File

@@ -142,7 +142,7 @@ BoxService
管理与 Box Runtime 的通信连接:
- **本地 stdio**: Unix/macOS 默认路径fork `python -m langbot_plugin.box --port {port}` 子进程
- **本地 stdio**: Unix/macOS 默认路径fork `python -m langbot_plugin.cli.__init__ box -s --ws-control-port {port}` 子进程(与 plugin runtime 统一走 `lbp` CLI 入口)
- **本地 subprocess + WS**: Windows 本地asyncio ProactorEventLoop 不支持 stdio pipe
- **远程 WebSocket**: Docker 部署 / `box.runtime.endpoint` 显式配置时,连接 `ws://{host}:{port}/rpc/ws`
- **同步等待**: `asyncio.Event` + `wait_for(timeout=30s)` 模式确认连接

View File

@@ -75,7 +75,7 @@ else:
```
connector._start_local_stdio()
├─ connected = asyncio.Event()
├─ ctrl = StdioClientController(python, ['-m', 'langbot_plugin.box.server', '--port', N])
├─ ctrl = StdioClientController(python, ['-m', 'langbot_plugin.cli.__init__', 'box', '-s', '--ws-control-port', N])
├─ _ctrl_task = create_task(ctrl.run(callback))
│ callback:
│ handler = Handler(connection) ← 基础 Handler, 无 disconnect_callback

View File

@@ -181,7 +181,10 @@ class BoxRuntimeConnector(ManagedRuntimeConnector):
ctrl = StdioClientController(
command=python_path,
args=['-m', 'langbot_plugin.box.server', '--stdio-control', '--ws-control-port', str(self._relay_port)],
# Launched through the same CLI entry point as the plugin runtime
# (cli.__init__ <subcommand>); `-s` selects the stdio transport,
# mirroring `rt -s`.
args=['-m', 'langbot_plugin.cli.__init__', 'box', '-s', '--ws-control-port', str(self._relay_port)],
env=env,
)
self._ctrl_task = asyncio.create_task(
@@ -207,10 +210,13 @@ class BoxRuntimeConnector(ManagedRuntimeConnector):
env['LANGBOT_BOX_CONFIG'] = json.dumps(self._filtered_box_config)
python_path = sys.executable
# Launched through the same CLI entry point as the plugin runtime
# (cli.__init__ <subcommand>); no flag => WebSocket transport.
self.runtime_subprocess = await asyncio.create_subprocess_exec(
python_path,
'-m',
'langbot_plugin.box.server',
'langbot_plugin.cli.__init__',
'box',
'--ws-control-port',
str(self._relay_port),
env=env,