mirror of
https://github.com/AstrBotDevs/AstrBot
synced 2026-07-19 10:22:04 +08:00
- Introduce private v4 compatibility surface using _legacy_api.py, _legacy_runtime.py, _legacy_loader.py plus new _legacy_context.py and _legacy_star.py to centralize legacy adapters while keeping public APIs thin. - Extend InitializeOutput to carry protocol_version for negotiated protocol, enabling runtime to adapt to the chosen v4 version. - Add lightweight legacy support for Star/Context via new LegacyStar and LegacyContext shims and expose legacy API through the aggregate _legacy_api entry point. - Ensure legacy loader preserves class declaration order by iterating module.__dict__ instead of relying on alphabetical sorting. - Add tests: protocol_version handling in InitializeOutput, legacy main component order preservation, and embedded-newline framing in transport tests.
131 lines
3.7 KiB
Python
131 lines
3.7 KiB
Python
"""启动引导入口。
|
|
|
|
对外提供三个顶层启动函数:
|
|
|
|
- ``run_supervisor``: 启动 Supervisor 进程
|
|
- ``run_plugin_worker``: 启动单插件或组 Worker 进程
|
|
- ``run_websocket_server``: 以 WebSocket 方式启动 Worker
|
|
|
|
运行时核心类分布在同目录的子模块:
|
|
|
|
- ``runtime.supervisor``: ``SupervisorRuntime`` / ``WorkerSession``
|
|
- ``runtime.worker``: ``PluginWorkerRuntime`` / ``GroupWorkerRuntime``
|
|
"""
|
|
|
|
from __future__ import annotations
|
|
|
|
import asyncio
|
|
import sys
|
|
from pathlib import Path
|
|
from typing import IO
|
|
|
|
from .loader import PluginEnvironmentManager
|
|
from .supervisor import (
|
|
SupervisorRuntime,
|
|
WorkerSession,
|
|
_install_signal_handlers,
|
|
_prepare_stdio_transport,
|
|
_sdk_source_dir,
|
|
_wait_for_shutdown,
|
|
)
|
|
from .transport import StdioTransport, WebSocketServerTransport
|
|
from .worker import GroupWorkerRuntime, PluginWorkerRuntime
|
|
|
|
__all__ = [
|
|
"GroupWorkerRuntime",
|
|
"PluginWorkerRuntime",
|
|
"SupervisorRuntime",
|
|
"WorkerSession",
|
|
"_install_signal_handlers",
|
|
"_prepare_stdio_transport",
|
|
"_sdk_source_dir",
|
|
"_wait_for_shutdown",
|
|
"run_supervisor",
|
|
"run_plugin_worker",
|
|
"run_websocket_server",
|
|
]
|
|
|
|
|
|
async def run_supervisor(
|
|
*,
|
|
plugins_dir: Path = Path("plugins"),
|
|
stdin: IO[str] | None = None,
|
|
stdout: IO[str] | None = None,
|
|
env_manager: PluginEnvironmentManager | None = None,
|
|
) -> None:
|
|
transport_stdin, transport_stdout, original_stdout = _prepare_stdio_transport(
|
|
stdin,
|
|
stdout,
|
|
)
|
|
transport = StdioTransport(stdin=transport_stdin, stdout=transport_stdout)
|
|
runtime = SupervisorRuntime(
|
|
transport=transport,
|
|
plugins_dir=plugins_dir,
|
|
env_manager=env_manager,
|
|
)
|
|
|
|
try:
|
|
await runtime.start()
|
|
stop_event = asyncio.Event()
|
|
_install_signal_handlers(stop_event)
|
|
await _wait_for_shutdown(runtime.peer, stop_event)
|
|
finally:
|
|
await runtime.stop()
|
|
if original_stdout is not None:
|
|
sys.stdout = original_stdout
|
|
|
|
|
|
async def run_plugin_worker(
|
|
*,
|
|
plugin_dir: Path | None = None,
|
|
group_metadata: Path | None = None,
|
|
stdin: IO[str] | None = None,
|
|
stdout: IO[str] | None = None,
|
|
) -> None:
|
|
if plugin_dir is None and group_metadata is None:
|
|
raise ValueError("plugin_dir or group_metadata is required")
|
|
if plugin_dir is not None and group_metadata is not None:
|
|
raise ValueError("plugin_dir and group_metadata are mutually exclusive")
|
|
|
|
transport_stdin, transport_stdout, original_stdout = _prepare_stdio_transport(
|
|
stdin,
|
|
stdout,
|
|
)
|
|
transport = StdioTransport(stdin=transport_stdin, stdout=transport_stdout)
|
|
if group_metadata is not None:
|
|
runtime = GroupWorkerRuntime(
|
|
group_metadata_path=group_metadata,
|
|
transport=transport,
|
|
)
|
|
else:
|
|
runtime = PluginWorkerRuntime(plugin_dir=plugin_dir, transport=transport)
|
|
try:
|
|
await runtime.start()
|
|
stop_event = asyncio.Event()
|
|
_install_signal_handlers(stop_event)
|
|
await _wait_for_shutdown(runtime.peer, stop_event)
|
|
finally:
|
|
await runtime.stop()
|
|
if original_stdout is not None:
|
|
sys.stdout = original_stdout
|
|
|
|
|
|
async def run_websocket_server(
|
|
*,
|
|
host: str = "127.0.0.1",
|
|
port: int = 8765,
|
|
path: str = "/",
|
|
plugin_dir: Path | None = None,
|
|
) -> None:
|
|
runtime = PluginWorkerRuntime(
|
|
plugin_dir=plugin_dir or Path.cwd(),
|
|
transport=WebSocketServerTransport(host=host, port=port, path=path),
|
|
)
|
|
try:
|
|
await runtime.start()
|
|
stop_event = asyncio.Event()
|
|
_install_signal_handlers(stop_event)
|
|
await _wait_for_shutdown(runtime.peer, stop_event)
|
|
finally:
|
|
await runtime.stop()
|