feat(plugins): add runtime handshake boundary

This commit is contained in:
DCCONSTRUCTIONS
2026-07-17 19:50:01 +03:00
parent 24a47318f2
commit 9d51080d2e
22 changed files with 856 additions and 138 deletions
+18 -4
View File
@@ -15,7 +15,10 @@ from pathlib import Path
from typing import Any, Literal, Protocol, cast
from bleak.exc import BleakError
from missioncore_plugin_sdk.v0alpha2 import RuntimeActionInvocation
from missioncore_plugin_sdk.v0alpha2 import (
RuntimeActionInvocation,
RuntimePluginDescriptor,
)
from pydantic import BaseModel, ConfigDict, Field, SecretStr, ValidationError
from k1link.artifacts import write_json_atomic
@@ -50,11 +53,13 @@ from k1link.web.device_lifecycle import (
)
from k1link.web.plugin_runtime import (
DevicePluginRuntimeContribution,
InProcessDevicePluginRuntime,
PluginActionNotFoundError,
PluginExecutionError,
)
XGRIDS_K1_PLUGIN_ID = "nodedc.device.xgrids-lixelkity-k1"
XGRIDS_K1_PLUGIN_VERSION = "0.3.0"
XGRIDS_K1_MODEL_ID = "xgrids.lixelkity-k1"
XGRIDS_K1_COMPATIBILITY_PROFILE_ID = "xgrids.lixelkity-k1.fw-3.0.2.direct-lan.v1"
@@ -1821,15 +1826,24 @@ def build_xgrids_k1_plugin(repository_root: Path) -> DevicePluginRuntimeContribu
_validate_installed_compatibility_profile(repository_root)
service = XgridsK1CompatibilityService(repository_root)
adapter = XgridsK1PluginFacade(service)
runtime = InProcessDevicePluginRuntime(
adapter,
RuntimePluginDescriptor(
plugin_id=XGRIDS_K1_PLUGIN_ID,
plugin_version=XGRIDS_K1_PLUGIN_VERSION,
supported_host_api_versions=("missioncore.nodedc/v1alpha2",),
action_ids=tuple(sorted(adapter.action_ids)),
),
close=service.close,
)
return DevicePluginRuntimeContribution(
adapter=adapter,
runtime=runtime,
legacy_routers=(
build_xgrids_k1_legacy_router(adapter),
build_xgrids_k1_legacy_router(runtime),
build_xgrids_k1_camera_router(
service.camera_preview,
XGRIDS_K1_PLUGIN_ID,
),
),
observation=build_xgrids_k1_observation(repository_root),
close=service.close,
)
@@ -18,25 +18,28 @@ from k1link.device_plugins.xgrids_k1.facade import (
LiveRequest,
ReplayRequest,
ViewerSettingsRequest,
XgridsK1PluginFacade,
)
from k1link.web.plugin_runtime import PluginExecutionError, invoke_device_plugin_adapter
from k1link.web.plugin_runtime import (
DevicePluginRuntimeTransport,
PluginExecutionError,
invoke_device_plugin_runtime,
)
def build_xgrids_k1_legacy_router(adapter: XgridsK1PluginFacade) -> APIRouter:
def build_xgrids_k1_legacy_router(runtime: DevicePluginRuntimeTransport) -> APIRouter:
"""Temporary flat API kept for scripts created before the plugin boundary."""
router = APIRouter(include_in_schema=True)
@router.get("/api/state", deprecated=True)
async def get_state() -> dict[str, Any]:
return await invoke_device_plugin_adapter(adapter, ACTION_STATE_READ, {})
return await invoke_device_plugin_runtime(runtime, ACTION_STATE_READ, {})
@router.post("/api/ble/scan", deprecated=True)
async def scan_ble(request: BleScanRequest) -> dict[str, Any]:
try:
return await invoke_device_plugin_adapter(
adapter,
return await invoke_device_plugin_runtime(
runtime,
ACTION_DISCOVERY_SCAN,
request.model_dump(),
)
@@ -46,8 +49,8 @@ def build_xgrids_k1_legacy_router(adapter: XgridsK1PluginFacade) -> APIRouter:
@router.post("/api/connect", deprecated=True)
async def connect(request: ConnectRequest) -> dict[str, Any]:
try:
return await invoke_device_plugin_adapter(
adapter,
return await invoke_device_plugin_runtime(
runtime,
ACTION_NETWORK_PROVISION,
request.model_dump(),
)
@@ -60,8 +63,8 @@ def build_xgrids_k1_legacy_router(adapter: XgridsK1PluginFacade) -> APIRouter:
@router.post("/api/session/live", deprecated=True)
async def start_live(request: LiveRequest) -> dict[str, Any]:
try:
return await invoke_device_plugin_adapter(
adapter,
return await invoke_device_plugin_runtime(
runtime,
ACTION_STREAM_START_LIVE,
request.model_dump(),
)
@@ -71,8 +74,8 @@ def build_xgrids_k1_legacy_router(adapter: XgridsK1PluginFacade) -> APIRouter:
@router.post("/api/session/replay", deprecated=True)
async def start_replay(request: ReplayRequest) -> dict[str, Any]:
try:
return await invoke_device_plugin_adapter(
adapter,
return await invoke_device_plugin_runtime(
runtime,
ACTION_STREAM_START_REPLAY,
request.model_dump(),
)
@@ -81,12 +84,12 @@ def build_xgrids_k1_legacy_router(adapter: XgridsK1PluginFacade) -> APIRouter:
@router.post("/api/session/stop", deprecated=True)
async def stop_session() -> dict[str, Any]:
return await invoke_device_plugin_adapter(adapter, ACTION_STREAM_STOP, {})
return await invoke_device_plugin_runtime(runtime, ACTION_STREAM_STOP, {})
@router.post("/api/viewer/settings", deprecated=True)
async def update_viewer_settings(request: ViewerSettingsRequest) -> dict[str, Any]:
return await invoke_device_plugin_adapter(
adapter,
return await invoke_device_plugin_runtime(
runtime,
ACTION_VIEWER_SETTINGS_UPDATE,
request.model_dump(),
)
@@ -98,8 +101,8 @@ def build_xgrids_k1_legacy_router(adapter: XgridsK1PluginFacade) -> APIRouter:
while True:
await websocket.send_json(
{
"state": await invoke_device_plugin_adapter(
adapter,
"state": await invoke_device_plugin_runtime(
runtime,
ACTION_STATE_READ,
{},
)