Add runtime capability scaffolding and align docs

This commit is contained in:
Thales Maciel 2026-03-05 22:57:09 -03:00
parent fb8b985049
commit cbf212bb7b
19 changed files with 1048 additions and 71 deletions

72
src/pyro_mcp/vm_guest.py Normal file
View file

@ -0,0 +1,72 @@
"""Guest command transport over vsock-compatible JSON protocol."""
from __future__ import annotations
import json
import socket
from dataclasses import dataclass
from typing import Callable, Protocol
class SocketLike(Protocol):
def settimeout(self, timeout: int) -> None: ...
def connect(self, address: tuple[int, int]) -> None: ...
def sendall(self, data: bytes) -> None: ...
def recv(self, size: int) -> bytes: ...
def close(self) -> None: ...
SocketFactory = Callable[[int, int], SocketLike]
@dataclass(frozen=True)
class GuestExecResponse:
stdout: str
stderr: str
exit_code: int
duration_ms: int
class VsockExecClient:
"""Minimal JSON-over-stream client for a guest exec agent."""
def __init__(self, socket_factory: SocketFactory | None = None) -> None:
self._socket_factory = socket_factory or socket.socket
def exec(
self, guest_cid: int, port: int, command: str, timeout_seconds: int
) -> GuestExecResponse:
request = {
"command": command,
"timeout_seconds": timeout_seconds,
}
family = getattr(socket, "AF_VSOCK", None)
if family is None:
raise RuntimeError("vsock sockets are not supported on this host Python runtime")
sock = self._socket_factory(family, socket.SOCK_STREAM)
try:
sock.settimeout(timeout_seconds)
sock.connect((guest_cid, port))
sock.sendall((json.dumps(request) + "\n").encode("utf-8"))
chunks: list[bytes] = []
while True:
data = sock.recv(65536)
if data == b"":
break
chunks.append(data)
finally:
sock.close()
payload = json.loads(b"".join(chunks).decode("utf-8"))
if not isinstance(payload, dict):
raise RuntimeError("guest exec response must be a JSON object")
return GuestExecResponse(
stdout=str(payload.get("stdout", "")),
stderr=str(payload.get("stderr", "")),
exit_code=int(payload.get("exit_code", -1)),
duration_ms=int(payload.get("duration_ms", 0)),
)