refactor: update imports to use provisioning_db and gateway_rpc modules

This commit is contained in:
Abhimanyu Saharan
2026-02-11 00:00:19 +05:30
parent 997d21c913
commit b038d0df4c
22 changed files with 1391 additions and 1438 deletions

View File

@@ -44,9 +44,9 @@ from app.schemas.gateway_coordination import (
from app.schemas.pagination import DefaultLimitOffsetPage
from app.schemas.tasks import TaskCommentCreate, TaskCommentRead, TaskCreate, TaskRead, TaskUpdate
from app.services.activity_log import record_activity
from app.services.openclaw.agent_service import AgentLifecycleService
from app.services.openclaw.coordination_service import GatewayCoordinationService
from app.services.openclaw.policies import OpenClawAuthorizationPolicy
from app.services.openclaw.provisioning_db import AgentLifecycleService
from app.services.task_dependencies import (
blocked_by_dependency_ids,
dependency_status_by_id,

View File

@@ -21,7 +21,7 @@ from app.schemas.agents import (
)
from app.schemas.common import OkResponse
from app.schemas.pagination import DefaultLimitOffsetPage
from app.services.openclaw.agent_service import AgentLifecycleService, AgentUpdateOptions
from app.services.openclaw.provisioning_db import AgentLifecycleService, AgentUpdateOptions
from app.services.organizations import OrganizationContext
if TYPE_CHECKING:

View File

@@ -9,11 +9,6 @@ from fastapi import APIRouter, Depends, Query
from app.api.deps import require_org_admin
from app.core.auth import AuthContext, get_auth_context
from app.db.session import get_session
from app.integrations.openclaw_gateway_protocol import (
GATEWAY_EVENTS,
GATEWAY_METHODS,
PROTOCOL_VERSION,
)
from app.schemas.common import OkResponse
from app.schemas.gateway_api import (
GatewayCommandsResponse,
@@ -24,6 +19,7 @@ from app.schemas.gateway_api import (
GatewaySessionsResponse,
GatewaysStatusResponse,
)
from app.services.openclaw.gateway_rpc import GATEWAY_EVENTS, GATEWAY_METHODS, PROTOCOL_VERSION
from app.services.openclaw.session_service import GatewaySessionService
from app.services.organizations import OrganizationContext

View File

@@ -1,125 +0,0 @@
"""OpenClaw gateway protocol constants shared across integration layers."""
from __future__ import annotations
PROTOCOL_VERSION = 3
# NOTE: These are the base gateway methods from the OpenClaw gateway repo.
# The gateway can expose additional methods at runtime via channel plugins.
GATEWAY_METHODS = [
"health",
"logs.tail",
"channels.status",
"channels.logout",
"status",
"usage.status",
"usage.cost",
"tts.status",
"tts.providers",
"tts.enable",
"tts.disable",
"tts.convert",
"tts.setProvider",
"config.get",
"config.set",
"config.apply",
"config.patch",
"config.schema",
"exec.approvals.get",
"exec.approvals.set",
"exec.approvals.node.get",
"exec.approvals.node.set",
"exec.approval.request",
"exec.approval.resolve",
"wizard.start",
"wizard.next",
"wizard.cancel",
"wizard.status",
"talk.mode",
"models.list",
"agents.list",
"agents.create",
"agents.update",
"agents.delete",
"agents.files.list",
"agents.files.get",
"agents.files.set",
"skills.status",
"skills.bins",
"skills.install",
"skills.update",
"update.run",
"voicewake.get",
"voicewake.set",
"sessions.list",
"sessions.preview",
"sessions.patch",
"sessions.reset",
"sessions.delete",
"sessions.compact",
"last-heartbeat",
"set-heartbeats",
"wake",
"node.pair.request",
"node.pair.list",
"node.pair.approve",
"node.pair.reject",
"node.pair.verify",
"device.pair.list",
"device.pair.approve",
"device.pair.reject",
"device.token.rotate",
"device.token.revoke",
"node.rename",
"node.list",
"node.describe",
"node.invoke",
"node.invoke.result",
"node.event",
"cron.list",
"cron.status",
"cron.add",
"cron.update",
"cron.remove",
"cron.run",
"cron.runs",
"system-presence",
"system-event",
"send",
"agent",
"agent.identity.get",
"agent.wait",
"browser.request",
"chat.history",
"chat.abort",
"chat.send",
]
GATEWAY_EVENTS = [
"connect.challenge",
"agent",
"chat",
"presence",
"tick",
"talk.mode",
"shutdown",
"health",
"heartbeat",
"cron",
"node.pair.requested",
"node.pair.resolved",
"node.invoke.request",
"device.pair.requested",
"device.pair.resolved",
"voicewake.changed",
"exec.approval.requested",
"exec.approval.resolved",
]
GATEWAY_METHODS_SET = frozenset(GATEWAY_METHODS)
GATEWAY_EVENTS_SET = frozenset(GATEWAY_EVENTS)
def is_known_gateway_method(method: str) -> bool:
"""Return whether a method name is part of the known base gateway methods."""
return method in GATEWAY_METHODS_SET

View File

@@ -15,7 +15,7 @@ from app.schemas.approvals import ApprovalRead
from app.schemas.board_memory import BoardMemoryRead
from app.schemas.boards import BoardRead
from app.schemas.view_models import BoardSnapshot, TaskCardRead
from app.services.openclaw.agent_service import AgentLifecycleService
from app.services.openclaw.provisioning_db import AgentLifecycleService
from app.services.task_dependencies import (
blocked_by_dependency_ids,
dependency_ids_by_task_id,

View File

@@ -1,6 +1,6 @@
"""OpenClaw lifecycle package.
Import concrete modules directly (for example: ``app.services.openclaw.agent_service``)
Import concrete modules directly (for example: ``app.services.openclaw.provisioning_db``)
to keep architectural boundaries explicit.
"""

View File

@@ -14,11 +14,6 @@ from app.core.agent_tokens import generate_agent_token, hash_agent_token
from app.core.auth import AuthContext
from app.core.time import utcnow
from app.db import crud
from app.integrations.openclaw_gateway import GatewayConfig as GatewayClientConfig
from app.integrations.openclaw_gateway import (
OpenClawGatewayError,
openclaw_call,
)
from app.models.activity_events import ActivityEvent
from app.models.agents import Agent
from app.models.approvals import Approval
@@ -26,6 +21,8 @@ from app.models.gateways import Gateway
from app.models.tasks import Task
from app.schemas.gateways import GatewayTemplatesSyncResult
from app.services.openclaw.constants import DEFAULT_HEARTBEAT_CONFIG
from app.services.openclaw.gateway_rpc import GatewayConfig as GatewayClientConfig
from app.services.openclaw.gateway_rpc import OpenClawGatewayError, openclaw_call
from app.services.openclaw.provisioning import OpenClawGatewayProvisioner
from app.services.openclaw.provisioning_db import (
GatewayTemplateSyncOptions,

File diff suppressed because it is too large Load Diff

View File

@@ -14,8 +14,6 @@ from sqlmodel import col, select
from app.core.config import settings
from app.core.time import utcnow
from app.integrations.openclaw_gateway import GatewayConfig as GatewayClientConfig
from app.integrations.openclaw_gateway import OpenClawGatewayError, openclaw_call
from app.models.agents import Agent
from app.models.boards import Board
from app.models.gateways import Gateway
@@ -34,6 +32,8 @@ from app.services.openclaw.exceptions import (
map_gateway_error_message,
map_gateway_error_to_http_exception,
)
from app.services.openclaw.gateway_rpc import GatewayConfig as GatewayClientConfig
from app.services.openclaw.gateway_rpc import OpenClawGatewayError, openclaw_call
from app.services.openclaw.internal import agent_key, with_coordination_gateway_retry
from app.services.openclaw.policies import OpenClawAuthorizationPolicy
from app.services.openclaw.provisioning_db import (

View File

@@ -1,4 +1,9 @@
"""OpenClaw gateway client helpers for websocket RPC calls."""
"""OpenClaw gateway websocket RPC client and protocol constants.
This is the low-level, DB-free interface for talking to the OpenClaw gateway.
Keep gateway RPC protocol details and client helpers here so OpenClaw services
operate within a single scope (no `app.integrations.*` plumbing).
"""
from __future__ import annotations
@@ -12,20 +17,133 @@ from uuid import uuid4
import websockets
from websockets.exceptions import WebSocketException
from app.integrations.openclaw_gateway_protocol import PROTOCOL_VERSION
PROTOCOL_VERSION = 3
# NOTE: These are the base gateway methods from the OpenClaw gateway repo.
# The gateway can expose additional methods at runtime via channel plugins.
GATEWAY_METHODS = [
"health",
"logs.tail",
"channels.status",
"channels.logout",
"status",
"usage.status",
"usage.cost",
"tts.status",
"tts.providers",
"tts.enable",
"tts.disable",
"tts.convert",
"tts.setProvider",
"config.get",
"config.set",
"config.apply",
"config.patch",
"config.schema",
"exec.approvals.get",
"exec.approvals.set",
"exec.approvals.node.get",
"exec.approvals.node.set",
"exec.approval.request",
"exec.approval.resolve",
"wizard.start",
"wizard.next",
"wizard.cancel",
"wizard.status",
"talk.mode",
"models.list",
"agents.list",
"agents.create",
"agents.update",
"agents.delete",
"agents.files.list",
"agents.files.get",
"agents.files.set",
"skills.status",
"skills.bins",
"skills.install",
"skills.update",
"update.run",
"voicewake.get",
"voicewake.set",
"sessions.list",
"sessions.preview",
"sessions.patch",
"sessions.reset",
"sessions.delete",
"sessions.compact",
"last-heartbeat",
"set-heartbeats",
"wake",
"node.pair.request",
"node.pair.list",
"node.pair.approve",
"node.pair.reject",
"node.pair.verify",
"device.pair.list",
"device.pair.approve",
"device.pair.reject",
"device.token.rotate",
"device.token.revoke",
"node.rename",
"node.list",
"node.describe",
"node.invoke",
"node.invoke.result",
"node.event",
"cron.list",
"cron.status",
"cron.add",
"cron.update",
"cron.remove",
"cron.run",
"cron.runs",
"system-presence",
"system-event",
"send",
"agent",
"agent.identity.get",
"agent.wait",
"browser.request",
"chat.history",
"chat.abort",
"chat.send",
]
GATEWAY_EVENTS = [
"connect.challenge",
"agent",
"chat",
"presence",
"tick",
"talk.mode",
"shutdown",
"health",
"heartbeat",
"cron",
"node.pair.requested",
"node.pair.resolved",
"node.invoke.request",
"device.pair.requested",
"device.pair.resolved",
"voicewake.changed",
"exec.approval.requested",
"exec.approval.resolved",
]
GATEWAY_METHODS_SET = frozenset(GATEWAY_METHODS)
GATEWAY_EVENTS_SET = frozenset(GATEWAY_EVENTS)
def is_known_gateway_method(method: str) -> bool:
"""Return whether a method name is part of the known base gateway methods."""
return method in GATEWAY_METHODS_SET
class OpenClawGatewayError(RuntimeError):
"""Raised when OpenClaw gateway calls fail."""
@dataclass
class OpenClawResponse:
"""Container for raw OpenClaw payloads."""
payload: Any
@dataclass(frozen=True)
class GatewayConfig:
"""Connection configuration for the OpenClaw gateway."""
@@ -37,7 +155,7 @@ class GatewayConfig:
def _build_gateway_url(config: GatewayConfig) -> str:
base_url: str = (config.url or "").strip()
if not base_url:
message = "Gateway URL is not configured for this board."
message = "Gateway URL is not configured."
raise OpenClawGatewayError(message)
token = config.token
if not token:

View File

@@ -6,7 +6,6 @@ import asyncio
from collections.abc import Awaitable, Callable
from typing import TypeVar
from app.integrations.openclaw_gateway import OpenClawGatewayError
from app.services.openclaw.constants import (
_COORDINATION_GATEWAY_BASE_DELAY_S,
_COORDINATION_GATEWAY_MAX_DELAY_S,
@@ -15,6 +14,7 @@ from app.services.openclaw.constants import (
_SECURE_RANDOM,
_TRANSIENT_GATEWAY_ERROR_MARKERS,
)
from app.services.openclaw.gateway_rpc import OpenClawGatewayError
_T = TypeVar("_T")

View File

@@ -2,11 +2,11 @@
from __future__ import annotations
from app.integrations.openclaw_gateway import OpenClawGatewayError
from app.models.board_onboarding import BoardOnboardingSession
from app.models.boards import Board
from app.services.openclaw.coordination_service import AbstractGatewayMessagingService
from app.services.openclaw.exceptions import GatewayOperation, map_gateway_error_to_http_exception
from app.services.openclaw.gateway_rpc import OpenClawGatewayError
from app.services.openclaw.shared import (
GatewayAgentIdentity,
require_gateway_config_for_board,

View File

@@ -18,13 +18,6 @@ from uuid import uuid4
from jinja2 import Environment, FileSystemLoader, StrictUndefined, select_autoescape
from app.core.config import settings
from app.integrations.openclaw_gateway import GatewayConfig as GatewayClientConfig
from app.integrations.openclaw_gateway import (
OpenClawGatewayError,
ensure_session,
openclaw_call,
send_message,
)
from app.models.agents import Agent
from app.models.boards import Board
from app.models.gateways import Gateway
@@ -40,6 +33,13 @@ from app.services.openclaw.constants import (
MAIN_TEMPLATE_MAP,
PRESERVE_AGENT_EDITABLE_FILES,
)
from app.services.openclaw.gateway_rpc import GatewayConfig as GatewayClientConfig
from app.services.openclaw.gateway_rpc import (
OpenClawGatewayError,
ensure_session,
openclaw_call,
send_message,
)
from app.services.openclaw.internal import agent_key as _agent_key
from app.services.openclaw.shared import GatewayAgentIdentity

File diff suppressed because it is too large Load Diff

View File

@@ -11,14 +11,6 @@ from uuid import UUID
from fastapi import HTTPException, status
from sqlmodel import col
from app.integrations.openclaw_gateway import GatewayConfig as GatewayClientConfig
from app.integrations.openclaw_gateway import (
OpenClawGatewayError,
ensure_session,
get_chat_history,
openclaw_call,
send_message,
)
from app.models.agents import Agent
from app.models.boards import Board
from app.models.gateways import Gateway
@@ -30,6 +22,14 @@ from app.schemas.gateway_api import (
GatewaySessionsResponse,
GatewaysStatusResponse,
)
from app.services.openclaw.gateway_rpc import GatewayConfig as GatewayClientConfig
from app.services.openclaw.gateway_rpc import (
OpenClawGatewayError,
ensure_session,
get_chat_history,
openclaw_call,
send_message,
)
from app.services.openclaw.policies import OpenClawAuthorizationPolicy
from app.services.organizations import require_board_access

View File

@@ -8,8 +8,6 @@ from uuid import UUID, uuid4
from fastapi import HTTPException, status
from app.integrations.openclaw_gateway import GatewayConfig as _GatewayClientConfig
from app.integrations.openclaw_gateway import OpenClawGatewayError, ensure_session, send_message
from app.models.boards import Board
from app.models.gateways import Gateway
from app.services.openclaw.constants import (
@@ -17,6 +15,8 @@ from app.services.openclaw.constants import (
_GATEWAY_AGENT_SUFFIX,
_GATEWAY_OPENCLAW_AGENT_PREFIX,
)
from app.services.openclaw.gateway_rpc import GatewayConfig as _GatewayClientConfig
from app.services.openclaw.gateway_rpc import OpenClawGatewayError, ensure_session, send_message
if TYPE_CHECKING:
from sqlmodel.ext.asyncio.session import AsyncSession

View File

@@ -9,7 +9,7 @@ from uuid import UUID, uuid4
import pytest
import app.services.openclaw.agent_service as agent_service
import app.services.openclaw.provisioning_db as agent_service
@dataclass

View File

@@ -8,7 +8,7 @@ from uuid import UUID, uuid4
import pytest
import app.services.openclaw.provisioning as agent_provisioning
from app.services.openclaw.agent_service import AgentLifecycleService
from app.services.openclaw.provisioning_db import AgentLifecycleService
from app.services.openclaw.shared import GatewayAgentIdentity

View File

@@ -13,8 +13,8 @@ from fastapi import HTTPException, status
import app.services.openclaw.coordination_service as coordination_lifecycle
import app.services.openclaw.onboarding_service as onboarding_lifecycle
from app.integrations.openclaw_gateway import GatewayConfig as GatewayClientConfig
from app.integrations.openclaw_gateway import OpenClawGatewayError
from app.services.openclaw.gateway_rpc import GatewayConfig as GatewayClientConfig
from app.services.openclaw.gateway_rpc import OpenClawGatewayError
from app.services.openclaw.shared import GatewayAgentIdentity

View File

@@ -27,6 +27,6 @@ def test_no_openclaw_package_barrel_imports() -> None:
assert not violations, (
"Use concrete OpenClaw modules (for example "
"`from app.services.openclaw.agent_service import ...`) instead of package imports. "
"`from app.services.openclaw.provisioning_db import ...`) instead of package imports. "
f"Violations: {', '.join(violations)}"
)

View File

@@ -51,8 +51,7 @@ flowchart LR
### Gateway integration (optional)
Mission Control can call into an OpenClaw Gateway over WebSockets.
- Client: `backend/app/integrations/openclaw_gateway.py`
- Known methods/events: `backend/app/integrations/openclaw_gateway_protocol.py`
- Client + protocol: `backend/app/services/openclaw/gateway_rpc.py`
- Protocol doc: `docs/openclaw_gateway_ws.md`
- Base gateway config (getting started): `docs/openclaw_gateway_base_config.md`

View File

@@ -151,7 +151,7 @@ In the Mission Control UI:
4. Use the "Check connection" action to confirm reachability.
Implementation note (how Mission Control sends tokens):
- If you provide a token, Mission Control's backend will include it when connecting to the gateway (it attaches it to the URL query string and also sends it in the `connect` params). See `backend/app/integrations/openclaw_gateway.py`.
- If you provide a token, Mission Control's backend will include it when connecting to the gateway (it attaches it to the URL query string and also sends it in the `connect` params). See `backend/app/services/openclaw/gateway_rpc.py`.
### Workspace Root (Mission Control) vs Workspace (Gateway)