refactor: streamline agent lifecycle management with new DB service helpers
This commit is contained in:
@@ -33,10 +33,7 @@ from app.models.users import User
|
||||
from app.schemas.board_group_memory import BoardGroupMemoryCreate, BoardGroupMemoryRead
|
||||
from app.schemas.pagination import DefaultLimitOffsetPage
|
||||
from app.services.mentions import extract_mentions, matches_agent_mention
|
||||
from app.services.openclaw.shared import (
|
||||
optional_gateway_config_for_board,
|
||||
send_gateway_agent_message_safe,
|
||||
)
|
||||
from app.services.openclaw.gateway_dispatch import GatewayDispatchService
|
||||
from app.services.organizations import (
|
||||
is_org_admin,
|
||||
list_accessible_board_ids,
|
||||
@@ -206,6 +203,7 @@ def _group_header(*, is_broadcast: bool, mentioned: bool) -> str:
|
||||
@dataclass(frozen=True)
|
||||
class _NotifyGroupContext:
|
||||
session: AsyncSession
|
||||
dispatch: GatewayDispatchService
|
||||
group: BoardGroup
|
||||
board_by_id: dict[UUID, Board]
|
||||
mentions: set[str]
|
||||
@@ -226,7 +224,7 @@ async def _notify_group_target(
|
||||
board = context.board_by_id.get(board_id)
|
||||
if board is None:
|
||||
return
|
||||
config = await optional_gateway_config_for_board(context.session, board)
|
||||
config = await context.dispatch.optional_gateway_config_for_board(board)
|
||||
if config is None:
|
||||
return
|
||||
header = _group_header(
|
||||
@@ -242,7 +240,7 @@ async def _notify_group_target(
|
||||
f"POST {context.base_url}/api/v1/boards/{board.id}/group-memory\n"
|
||||
'Body: {"content":"...","tags":["chat"]}'
|
||||
)
|
||||
error = await send_gateway_agent_message_safe(
|
||||
error = await context.dispatch.try_send_agent_message(
|
||||
session_key=session_key,
|
||||
config=config,
|
||||
agent_name=agent.name,
|
||||
@@ -294,6 +292,7 @@ async def _notify_group_memory_targets(
|
||||
|
||||
context = _NotifyGroupContext(
|
||||
session=session,
|
||||
dispatch=GatewayDispatchService(session),
|
||||
group=group,
|
||||
board_by_id=board_by_id,
|
||||
mentions=mentions,
|
||||
|
||||
@@ -30,8 +30,8 @@ from app.schemas.pagination import DefaultLimitOffsetPage
|
||||
from app.schemas.view_models import BoardGroupSnapshot
|
||||
from app.services.board_group_snapshot import build_group_snapshot
|
||||
from app.services.openclaw.constants import DEFAULT_HEARTBEAT_CONFIG
|
||||
from app.services.openclaw.gateway_rpc import OpenClawGatewayError
|
||||
from app.services.openclaw.provisioning import OpenClawGatewayProvisioner
|
||||
from app.services.openclaw.shared import GatewayTransportError
|
||||
from app.services.organizations import (
|
||||
OrganizationContext,
|
||||
board_access_filter,
|
||||
@@ -273,7 +273,7 @@ async def _sync_gateway_heartbeats(
|
||||
gateway,
|
||||
gateway_agents,
|
||||
)
|
||||
except GatewayTransportError:
|
||||
except OpenClawGatewayError:
|
||||
failed_agent_ids.extend([agent.id for agent in gateway_agents])
|
||||
return failed_agent_ids
|
||||
|
||||
|
||||
@@ -28,11 +28,8 @@ from app.models.board_memory import BoardMemory
|
||||
from app.schemas.board_memory import BoardMemoryCreate, BoardMemoryRead
|
||||
from app.schemas.pagination import DefaultLimitOffsetPage
|
||||
from app.services.mentions import extract_mentions, matches_agent_mention
|
||||
from app.services.openclaw.shared import (
|
||||
GatewayClientConfig,
|
||||
optional_gateway_config_for_board,
|
||||
send_gateway_agent_message_safe,
|
||||
)
|
||||
from app.services.openclaw.gateway_dispatch import GatewayDispatchService
|
||||
from app.services.openclaw.gateway_rpc import GatewayConfig as GatewayClientConfig
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from collections.abc import AsyncIterator
|
||||
@@ -102,6 +99,7 @@ async def _send_control_command(
|
||||
session: AsyncSession,
|
||||
board: Board,
|
||||
actor: ActorContext,
|
||||
dispatch: GatewayDispatchService,
|
||||
config: GatewayClientConfig,
|
||||
command: str,
|
||||
) -> None:
|
||||
@@ -115,7 +113,7 @@ async def _send_control_command(
|
||||
continue
|
||||
if not agent.openclaw_session_id:
|
||||
continue
|
||||
error = await send_gateway_agent_message_safe(
|
||||
error = await dispatch.try_send_agent_message(
|
||||
session_key=agent.openclaw_session_id,
|
||||
config=config,
|
||||
agent_name=agent.name,
|
||||
@@ -161,7 +159,8 @@ async def _notify_chat_targets(
|
||||
) -> None:
|
||||
if not memory.content:
|
||||
return
|
||||
config = await optional_gateway_config_for_board(session, board)
|
||||
dispatch = GatewayDispatchService(session)
|
||||
config = await dispatch.optional_gateway_config_for_board(board)
|
||||
if config is None:
|
||||
return
|
||||
|
||||
@@ -174,6 +173,7 @@ async def _notify_chat_targets(
|
||||
session=session,
|
||||
board=board,
|
||||
actor=actor,
|
||||
dispatch=dispatch,
|
||||
config=config,
|
||||
command=command,
|
||||
)
|
||||
@@ -206,7 +206,7 @@ async def _notify_chat_targets(
|
||||
f"POST {base_url}/api/v1/agent/boards/{board.id}/memory\n"
|
||||
'Body: {"content":"...","tags":["chat"]}'
|
||||
)
|
||||
error = await send_gateway_agent_message_safe(
|
||||
error = await dispatch.try_send_agent_message(
|
||||
session_key=agent.openclaw_session_id,
|
||||
config=config,
|
||||
agent_name=agent.name,
|
||||
|
||||
@@ -33,6 +33,7 @@ from app.schemas.board_onboarding import (
|
||||
BoardOnboardingUserProfile,
|
||||
)
|
||||
from app.schemas.boards import BoardRead
|
||||
from app.services.openclaw.gateway_dispatch import GatewayDispatchService
|
||||
from app.services.openclaw.onboarding_service import BoardOnboardingMessagingService
|
||||
from app.services.openclaw.policies import OpenClawAuthorizationPolicy
|
||||
from app.services.openclaw.provisioning_db import (
|
||||
@@ -40,7 +41,6 @@ from app.services.openclaw.provisioning_db import (
|
||||
LeadAgentRequest,
|
||||
OpenClawProvisioningService,
|
||||
)
|
||||
from app.services.openclaw.shared import require_gateway_config_for_board
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from sqlmodel.ext.asyncio.session import AsyncSession
|
||||
@@ -396,7 +396,7 @@ async def confirm_onboarding(
|
||||
lead_agent = _parse_draft_lead_agent(onboarding.draft_goal)
|
||||
lead_options = _lead_agent_options(lead_agent)
|
||||
|
||||
gateway, config = await require_gateway_config_for_board(session, board)
|
||||
gateway, config = await GatewayDispatchService(session).require_gateway_config_for_board(board)
|
||||
session.add(board)
|
||||
session.add(onboarding)
|
||||
await session.commit()
|
||||
|
||||
@@ -39,8 +39,8 @@ from app.schemas.pagination import DefaultLimitOffsetPage
|
||||
from app.schemas.view_models import BoardGroupSnapshot, BoardSnapshot
|
||||
from app.services.board_group_snapshot import build_board_group_snapshot
|
||||
from app.services.board_snapshot import build_board_snapshot
|
||||
from app.services.openclaw.gateway_rpc import OpenClawGatewayError
|
||||
from app.services.openclaw.provisioning import OpenClawGatewayProvisioner
|
||||
from app.services.openclaw.shared import GatewayTransportError
|
||||
from app.services.organizations import OrganizationContext, board_access_filter
|
||||
|
||||
if TYPE_CHECKING:
|
||||
@@ -291,7 +291,7 @@ async def delete_board(
|
||||
agent=agent,
|
||||
gateway=config,
|
||||
)
|
||||
except GatewayTransportError as exc:
|
||||
except OpenClawGatewayError as exc:
|
||||
raise HTTPException(
|
||||
status_code=status.HTTP_502_BAD_GATEWAY,
|
||||
detail=f"Gateway cleanup failed: {exc}",
|
||||
|
||||
@@ -40,12 +40,9 @@ 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.mentions import extract_mentions, matches_agent_mention
|
||||
from app.services.openclaw.shared import (
|
||||
GatewayClientConfig,
|
||||
GatewayTransportError,
|
||||
optional_gateway_config_for_board,
|
||||
send_gateway_agent_message_safe,
|
||||
)
|
||||
from app.services.openclaw.gateway_dispatch import GatewayDispatchService
|
||||
from app.services.openclaw.gateway_rpc import GatewayConfig as GatewayClientConfig
|
||||
from app.services.openclaw.gateway_rpc import OpenClawGatewayError
|
||||
from app.services.organizations import require_board_access
|
||||
from app.services.task_dependencies import (
|
||||
blocked_by_dependency_ids,
|
||||
@@ -305,11 +302,12 @@ def _serialize_comment(event: ActivityEvent) -> dict[str, object]:
|
||||
|
||||
async def _send_lead_task_message(
|
||||
*,
|
||||
dispatch: GatewayDispatchService,
|
||||
session_key: str,
|
||||
config: GatewayClientConfig,
|
||||
message: str,
|
||||
) -> GatewayTransportError | None:
|
||||
return await send_gateway_agent_message_safe(
|
||||
) -> OpenClawGatewayError | None:
|
||||
return await dispatch.try_send_agent_message(
|
||||
session_key=session_key,
|
||||
config=config,
|
||||
agent_name="Lead Agent",
|
||||
@@ -320,12 +318,13 @@ async def _send_lead_task_message(
|
||||
|
||||
async def _send_agent_task_message(
|
||||
*,
|
||||
dispatch: GatewayDispatchService,
|
||||
session_key: str,
|
||||
config: GatewayClientConfig,
|
||||
agent_name: str,
|
||||
message: str,
|
||||
) -> GatewayTransportError | None:
|
||||
return await send_gateway_agent_message_safe(
|
||||
) -> OpenClawGatewayError | None:
|
||||
return await dispatch.try_send_agent_message(
|
||||
session_key=session_key,
|
||||
config=config,
|
||||
agent_name=agent_name,
|
||||
@@ -343,7 +342,8 @@ async def _notify_agent_on_task_assign(
|
||||
) -> None:
|
||||
if not agent.openclaw_session_id:
|
||||
return
|
||||
config = await optional_gateway_config_for_board(session, board)
|
||||
dispatch = GatewayDispatchService(session)
|
||||
config = await dispatch.optional_gateway_config_for_board(board)
|
||||
if config is None:
|
||||
return
|
||||
description = _truncate_snippet(task.description or "")
|
||||
@@ -361,6 +361,7 @@ async def _notify_agent_on_task_assign(
|
||||
+ ("\n\nTake action: open the task and begin work. " "Post updates as task comments.")
|
||||
)
|
||||
error = await _send_agent_task_message(
|
||||
dispatch=dispatch,
|
||||
session_key=agent.openclaw_session_id,
|
||||
config=config,
|
||||
agent_name=agent.name,
|
||||
@@ -415,7 +416,8 @@ async def _notify_lead_on_task_create(
|
||||
)
|
||||
if lead is None or not lead.openclaw_session_id:
|
||||
return
|
||||
config = await optional_gateway_config_for_board(session, board)
|
||||
dispatch = GatewayDispatchService(session)
|
||||
config = await dispatch.optional_gateway_config_for_board(board)
|
||||
if config is None:
|
||||
return
|
||||
description = _truncate_snippet(task.description or "")
|
||||
@@ -433,6 +435,7 @@ async def _notify_lead_on_task_create(
|
||||
+ "\n\nTake action: triage, assign, or plan next steps."
|
||||
)
|
||||
error = await _send_lead_task_message(
|
||||
dispatch=dispatch,
|
||||
session_key=lead.openclaw_session_id,
|
||||
config=config,
|
||||
message=message,
|
||||
@@ -470,7 +473,8 @@ async def _notify_lead_on_task_unassigned(
|
||||
)
|
||||
if lead is None or not lead.openclaw_session_id:
|
||||
return
|
||||
config = await optional_gateway_config_for_board(session, board)
|
||||
dispatch = GatewayDispatchService(session)
|
||||
config = await dispatch.optional_gateway_config_for_board(board)
|
||||
if config is None:
|
||||
return
|
||||
description = _truncate_snippet(task.description or "")
|
||||
@@ -488,6 +492,7 @@ async def _notify_lead_on_task_unassigned(
|
||||
+ "\n\nTake action: assign a new owner or adjust the plan."
|
||||
)
|
||||
error = await _send_lead_task_message(
|
||||
dispatch=dispatch,
|
||||
session_key=lead.openclaw_session_id,
|
||||
config=config,
|
||||
message=message,
|
||||
@@ -1029,8 +1034,11 @@ async def _notify_task_comment_targets(
|
||||
if request.task.board_id
|
||||
else None
|
||||
)
|
||||
config = await optional_gateway_config_for_board(session, board) if board else None
|
||||
if not board or not config:
|
||||
if board is None:
|
||||
return
|
||||
dispatch = GatewayDispatchService(session)
|
||||
config = await dispatch.optional_gateway_config_for_board(board)
|
||||
if not config:
|
||||
return
|
||||
|
||||
snippet = _truncate_snippet(request.message)
|
||||
@@ -1057,6 +1065,7 @@ async def _notify_task_comment_targets(
|
||||
"thread but do not change task status."
|
||||
)
|
||||
await _send_agent_task_message(
|
||||
dispatch=dispatch,
|
||||
session_key=agent.openclaw_session_id,
|
||||
config=config,
|
||||
agent_name=agent.name,
|
||||
|
||||
Reference in New Issue
Block a user