refactor: update imports to use provisioning_db and gateway_rpc modules
This commit is contained in:
@@ -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,
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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
|
||||
@@ -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,
|
||||
|
||||
@@ -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.
|
||||
"""
|
||||
|
||||
|
||||
@@ -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
@@ -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 (
|
||||
|
||||
@@ -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:
|
||||
@@ -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")
|
||||
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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
@@ -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
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
|
||||
@@ -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)}"
|
||||
)
|
||||
|
||||
@@ -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`
|
||||
|
||||
|
||||
@@ -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)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user