2026-02-10 14:50:27 +05:30
|
|
|
"""Thin gateway session-inspection API wrappers."""
|
2026-02-09 16:23:41 +05:30
|
|
|
|
2026-02-04 02:28:51 +05:30
|
|
|
from __future__ import annotations
|
|
|
|
|
|
2026-02-09 16:23:41 +05:30
|
|
|
from typing import TYPE_CHECKING
|
|
|
|
|
|
2026-02-10 14:50:27 +05:30
|
|
|
from fastapi import APIRouter, Depends, Query
|
2026-02-04 02:28:51 +05:30
|
|
|
|
2026-02-08 21:16:26 +05:30
|
|
|
from app.api.deps import require_org_admin
|
2026-02-04 23:07:22 +05:30
|
|
|
from app.core.auth import AuthContext, get_auth_context
|
2026-02-05 00:21:33 +05:30
|
|
|
from app.db.session import get_session
|
2026-02-06 16:12:04 +05:30
|
|
|
from app.schemas.common import OkResponse
|
|
|
|
|
from app.schemas.gateway_api import (
|
|
|
|
|
GatewayCommandsResponse,
|
|
|
|
|
GatewayResolveQuery,
|
|
|
|
|
GatewaySessionHistoryResponse,
|
|
|
|
|
GatewaySessionMessageRequest,
|
|
|
|
|
GatewaySessionResponse,
|
|
|
|
|
GatewaySessionsResponse,
|
|
|
|
|
GatewaysStatusResponse,
|
|
|
|
|
)
|
2026-02-11 00:00:19 +05:30
|
|
|
from app.services.openclaw.gateway_rpc import GATEWAY_EVENTS, GATEWAY_METHODS, PROTOCOL_VERSION
|
2026-02-10 15:08:14 +05:30
|
|
|
from app.services.openclaw.session_service import GatewaySessionService
|
2026-02-10 14:50:27 +05:30
|
|
|
from app.services.organizations import OrganizationContext
|
2026-02-04 02:28:51 +05:30
|
|
|
|
2026-02-09 16:23:41 +05:30
|
|
|
if TYPE_CHECKING:
|
|
|
|
|
from sqlmodel.ext.asyncio.session import AsyncSession
|
|
|
|
|
|
2026-02-04 23:07:22 +05:30
|
|
|
router = APIRouter(prefix="/gateways", tags=["gateways"])
|
2026-02-09 16:23:41 +05:30
|
|
|
SESSION_DEP = Depends(get_session)
|
|
|
|
|
AUTH_DEP = Depends(get_auth_context)
|
|
|
|
|
ORG_ADMIN_DEP = Depends(require_org_admin)
|
|
|
|
|
BOARD_ID_QUERY = Query(default=None)
|
|
|
|
|
|
|
|
|
|
|
2026-02-10 00:45:15 +05:30
|
|
|
def _query_to_resolve_input(
|
|
|
|
|
board_id: str | None = Query(default=None),
|
|
|
|
|
gateway_url: str | None = Query(default=None),
|
|
|
|
|
gateway_token: str | None = Query(default=None),
|
2026-03-03 01:51:52 +05:30
|
|
|
gateway_disable_device_pairing: bool | None = Query(default=None),
|
|
|
|
|
gateway_allow_insecure_tls: bool | None = Query(default=None),
|
2026-02-10 00:45:15 +05:30
|
|
|
) -> GatewayResolveQuery:
|
2026-02-10 14:50:27 +05:30
|
|
|
return GatewaySessionService.to_resolve_query(
|
2026-02-10 00:45:15 +05:30
|
|
|
board_id=board_id,
|
|
|
|
|
gateway_url=gateway_url,
|
|
|
|
|
gateway_token=gateway_token,
|
2026-02-22 19:19:26 +05:30
|
|
|
gateway_disable_device_pairing=gateway_disable_device_pairing,
|
2026-02-22 20:20:19 +05:30
|
|
|
gateway_allow_insecure_tls=gateway_allow_insecure_tls,
|
2026-02-10 00:45:15 +05:30
|
|
|
)
|
2026-02-09 16:23:41 +05:30
|
|
|
|
|
|
|
|
|
|
|
|
|
RESOLVE_INPUT_DEP = Depends(_query_to_resolve_input)
|
2026-02-04 02:28:51 +05:30
|
|
|
|
|
|
|
|
|
2026-02-06 16:12:04 +05:30
|
|
|
@router.get("/status", response_model=GatewaysStatusResponse)
|
2026-02-04 23:07:22 +05:30
|
|
|
async def gateways_status(
|
2026-02-09 16:23:41 +05:30
|
|
|
params: GatewayResolveQuery = RESOLVE_INPUT_DEP,
|
|
|
|
|
session: AsyncSession = SESSION_DEP,
|
|
|
|
|
auth: AuthContext = AUTH_DEP,
|
|
|
|
|
ctx: OrganizationContext = ORG_ADMIN_DEP,
|
2026-02-06 16:12:04 +05:30
|
|
|
) -> GatewaysStatusResponse:
|
2026-02-09 16:23:41 +05:30
|
|
|
"""Return gateway connectivity and session status."""
|
2026-02-10 14:50:27 +05:30
|
|
|
service = GatewaySessionService(session)
|
|
|
|
|
return await service.get_status(
|
|
|
|
|
params=params,
|
|
|
|
|
organization_id=ctx.organization.id,
|
2026-02-08 21:16:26 +05:30
|
|
|
user=auth.user,
|
2026-02-04 21:44:21 +05:30
|
|
|
)
|
2026-02-04 02:28:51 +05:30
|
|
|
|
|
|
|
|
|
2026-02-06 16:12:04 +05:30
|
|
|
@router.get("/sessions", response_model=GatewaySessionsResponse)
|
2026-02-04 23:07:22 +05:30
|
|
|
async def list_gateway_sessions(
|
2026-02-09 16:23:41 +05:30
|
|
|
board_id: str | None = BOARD_ID_QUERY,
|
|
|
|
|
session: AsyncSession = SESSION_DEP,
|
|
|
|
|
auth: AuthContext = AUTH_DEP,
|
|
|
|
|
ctx: OrganizationContext = ORG_ADMIN_DEP,
|
2026-02-06 16:12:04 +05:30
|
|
|
) -> GatewaySessionsResponse:
|
2026-02-09 16:23:41 +05:30
|
|
|
"""List sessions for a gateway associated with a board."""
|
2026-02-10 14:50:27 +05:30
|
|
|
service = GatewaySessionService(session)
|
|
|
|
|
return await service.get_sessions(
|
|
|
|
|
board_id=board_id,
|
|
|
|
|
organization_id=ctx.organization.id,
|
2026-02-08 21:16:26 +05:30
|
|
|
user=auth.user,
|
2026-02-04 21:44:21 +05:30
|
|
|
)
|
2026-02-09 16:23:41 +05:30
|
|
|
|
|
|
|
|
|
2026-02-06 16:12:04 +05:30
|
|
|
@router.get("/sessions/{session_id}", response_model=GatewaySessionResponse)
|
2026-02-04 16:04:52 +05:30
|
|
|
async def get_gateway_session(
|
|
|
|
|
session_id: str,
|
2026-02-09 16:23:41 +05:30
|
|
|
board_id: str | None = BOARD_ID_QUERY,
|
|
|
|
|
session: AsyncSession = SESSION_DEP,
|
|
|
|
|
auth: AuthContext = AUTH_DEP,
|
|
|
|
|
ctx: OrganizationContext = ORG_ADMIN_DEP,
|
2026-02-06 16:12:04 +05:30
|
|
|
) -> GatewaySessionResponse:
|
2026-02-09 16:23:41 +05:30
|
|
|
"""Get a specific gateway session by key."""
|
2026-02-10 14:50:27 +05:30
|
|
|
service = GatewaySessionService(session)
|
|
|
|
|
return await service.get_session(
|
|
|
|
|
session_id=session_id,
|
|
|
|
|
board_id=board_id,
|
|
|
|
|
organization_id=ctx.organization.id,
|
2026-02-08 21:16:26 +05:30
|
|
|
user=auth.user,
|
2026-02-04 21:44:21 +05:30
|
|
|
)
|
2026-02-04 02:28:51 +05:30
|
|
|
|
|
|
|
|
|
2026-02-10 14:50:27 +05:30
|
|
|
@router.get("/sessions/{session_id}/history", response_model=GatewaySessionHistoryResponse)
|
2026-02-04 03:57:19 +05:30
|
|
|
async def get_session_history(
|
2026-02-04 16:04:52 +05:30
|
|
|
session_id: str,
|
2026-02-09 16:23:41 +05:30
|
|
|
board_id: str | None = BOARD_ID_QUERY,
|
|
|
|
|
session: AsyncSession = SESSION_DEP,
|
|
|
|
|
auth: AuthContext = AUTH_DEP,
|
|
|
|
|
ctx: OrganizationContext = ORG_ADMIN_DEP,
|
2026-02-06 16:12:04 +05:30
|
|
|
) -> GatewaySessionHistoryResponse:
|
2026-02-09 16:23:41 +05:30
|
|
|
"""Fetch chat history for a gateway session."""
|
2026-02-10 14:50:27 +05:30
|
|
|
service = GatewaySessionService(session)
|
|
|
|
|
return await service.get_session_history(
|
|
|
|
|
session_id=session_id,
|
|
|
|
|
board_id=board_id,
|
|
|
|
|
organization_id=ctx.organization.id,
|
|
|
|
|
user=auth.user,
|
|
|
|
|
)
|
2026-02-04 02:28:51 +05:30
|
|
|
|
|
|
|
|
|
2026-02-06 16:12:04 +05:30
|
|
|
@router.post("/sessions/{session_id}/message", response_model=OkResponse)
|
2026-02-04 23:07:22 +05:30
|
|
|
async def send_gateway_session_message(
|
2026-02-04 02:28:51 +05:30
|
|
|
session_id: str,
|
2026-02-06 16:12:04 +05:30
|
|
|
payload: GatewaySessionMessageRequest,
|
2026-02-09 16:23:41 +05:30
|
|
|
board_id: str | None = BOARD_ID_QUERY,
|
|
|
|
|
session: AsyncSession = SESSION_DEP,
|
|
|
|
|
auth: AuthContext = AUTH_DEP,
|
2026-02-06 16:12:04 +05:30
|
|
|
) -> OkResponse:
|
2026-02-09 16:23:41 +05:30
|
|
|
"""Send a message into a specific gateway session."""
|
2026-02-10 14:50:27 +05:30
|
|
|
service = GatewaySessionService(session)
|
|
|
|
|
await service.send_session_message(
|
|
|
|
|
session_id=session_id,
|
|
|
|
|
payload=payload,
|
|
|
|
|
board_id=board_id,
|
2026-02-09 20:44:05 +05:30
|
|
|
user=auth.user,
|
2026-02-09 16:23:41 +05:30
|
|
|
)
|
2026-02-06 16:12:04 +05:30
|
|
|
return OkResponse()
|
2026-02-04 17:05:58 +05:30
|
|
|
|
|
|
|
|
|
2026-02-06 16:12:04 +05:30
|
|
|
@router.get("/commands", response_model=GatewayCommandsResponse)
|
2026-02-04 17:05:58 +05:30
|
|
|
async def gateway_commands(
|
2026-02-09 16:23:41 +05:30
|
|
|
_auth: AuthContext = AUTH_DEP,
|
|
|
|
|
_ctx: OrganizationContext = ORG_ADMIN_DEP,
|
2026-02-06 16:12:04 +05:30
|
|
|
) -> GatewayCommandsResponse:
|
2026-02-09 16:23:41 +05:30
|
|
|
"""Return supported gateway protocol methods and events."""
|
2026-02-06 16:12:04 +05:30
|
|
|
return GatewayCommandsResponse(
|
|
|
|
|
protocol_version=PROTOCOL_VERSION,
|
|
|
|
|
methods=GATEWAY_METHODS,
|
|
|
|
|
events=GATEWAY_EVENTS,
|
|
|
|
|
)
|