refactor(block-h): resolve CommConversation hardcoding via kommunikation contract

This commit is contained in:
Agent Zero
2026-08-23 12:02:29 +02:00
parent 1f4a621910
commit a7699d3598
4 changed files with 40 additions and 27 deletions
+7 -13
View File
@@ -394,27 +394,21 @@ async def run_react_loop(
if agent_run_id: if agent_run_id:
try: try:
from app.plugins.builtins.contracts import get_contract_registry from app.plugins.builtins.contracts import get_contract_registry
from app.plugins.builtins.kommunikation.models import CommConversation
from sqlalchemy import select as sa_select
komm = get_contract_registry().get("kommunikation") komm = get_contract_registry().get("kommunikation")
if komm: if komm:
agent_id = getattr(agent_definition, "id", uuid.uuid4()) agent_id = getattr(agent_definition, "id", uuid.uuid4())
room_title = f"Agent: {getattr(agent_definition, 'name', 'Agent')}" room_title = f"Agent: {getattr(agent_definition, 'name', 'Agent')}"
existing = await db.execute( conv_id = await komm.find_locked_room_id(
sa_select(CommConversation).where( db=db,
CommConversation.tenant_id == tenant_id, tenant_id=tenant_id,
CommConversation.title == room_title, plugin_name="automation",
CommConversation.is_locked.is_(True), title=room_title,
CommConversation.locked_by == "automation",
CommConversation.deleted_at.is_(None),
)
) )
conv = existing.scalar_one_or_none() if conv_id:
if conv:
await komm.send_message( await komm.send_message(
db=db, db=db,
tenant_id=tenant_id, tenant_id=tenant_id,
conversation_id=conv.id, conversation_id=conv_id,
sender_id=agent_id, sender_id=agent_id,
sender_type="agent", sender_type="agent",
content=f"Approval required for tool '{tool_name}'", content=f"Approval required for tool '{tool_name}'",
@@ -31,6 +31,7 @@ from app.plugins.builtins.kommunikation.participant_registry import (
) )
from app.plugins.builtins.kommunikation.services import ( from app.plugins.builtins.kommunikation.services import (
create_plugin_room, create_plugin_room,
find_locked_room_id,
get_conversation, get_conversation,
get_messages, get_messages,
parse_mentions, parse_mentions,
@@ -55,6 +56,7 @@ class KommunikationContract:
get_messages = staticmethod(get_messages) get_messages = staticmethod(get_messages)
send_message = staticmethod(send_message) send_message = staticmethod(send_message)
create_plugin_room = staticmethod(create_plugin_room) create_plugin_room = staticmethod(create_plugin_room)
find_locked_room_id = staticmethod(find_locked_room_id)
# ─── participant registry ─── # ─── participant registry ───
get_participant_registry = staticmethod(get_participant_registry) get_participant_registry = staticmethod(get_participant_registry)
@@ -92,6 +94,7 @@ __all__ = [
"get_messages", "get_messages",
"send_message", "send_message",
"create_plugin_room", "create_plugin_room",
"find_locked_room_id",
"CommConversation", "CommConversation",
"CommMessage", "CommMessage",
"CommParticipant", "CommParticipant",
@@ -1047,6 +1047,30 @@ async def _get_unread_count(
# ─── Plugin Room Creation ─── # ─── Plugin Room Creation ───
async def find_locked_room_id(
db: AsyncSession,
tenant_id: uuid.UUID,
plugin_name: str,
title: str,
) -> uuid.UUID | None:
"""Find the conversation ID of a locked plugin room by tenant and title.
Matches the same room semantics as ``create_plugin_room``: locked rooms
are owned by the plugin (``locked_by == plugin_name``) and soft-deleted
conversations are excluded. Returns ``None`` when no room exists.
"""
result = await db.execute(
select(CommConversation.id).where(
CommConversation.tenant_id == tenant_id,
CommConversation.title == title,
CommConversation.is_locked.is_(True),
CommConversation.locked_by == plugin_name,
CommConversation.deleted_at.is_(None),
)
)
return result.scalar_one_or_none()
async def create_plugin_room( async def create_plugin_room(
db: AsyncSession, db: AsyncSession,
tenant_id: uuid.UUID, tenant_id: uuid.UUID,
+6 -14
View File
@@ -92,22 +92,16 @@ class WorkflowEngine:
# Post workflow completion to Communication (G-WORK) # Post workflow completion to Communication (G-WORK)
try: try:
from app.plugins.builtins.contracts import get_contract_registry from app.plugins.builtins.contracts import get_contract_registry
from app.plugins.builtins.kommunikation.models import CommConversation
from sqlalchemy import select as sa_select
komm = get_contract_registry().get("kommunikation") komm = get_contract_registry().get("kommunikation")
if komm and instance.initiated_by: if komm and instance.initiated_by:
room_title = f"Workflow: {workflow.name if hasattr(workflow, 'name') else str(instance.workflow_id)}" room_title = f"Workflow: {workflow.name if hasattr(workflow, 'name') else str(instance.workflow_id)}"
existing = await self.db.execute( conv_id = await komm.find_locked_room_id(
sa_select(CommConversation).where( db=self.db,
CommConversation.tenant_id == self.tenant_id, tenant_id=self.tenant_id,
CommConversation.title == room_title, plugin_name="workflow",
CommConversation.is_locked.is_(True), title=room_title,
CommConversation.locked_by == "workflow",
CommConversation.deleted_at.is_(None),
)
) )
conv = existing.scalar_one_or_none() if not conv_id:
if not conv:
room = await komm.create_plugin_room( room = await komm.create_plugin_room(
db=self.db, db=self.db,
tenant_id=self.tenant_id, tenant_id=self.tenant_id,
@@ -117,8 +111,6 @@ class WorkflowEngine:
participant_type="workflow", participant_type="workflow",
) )
conv_id = uuid.UUID(room["conversation_id"]) conv_id = uuid.UUID(room["conversation_id"])
else:
conv_id = conv.id
await komm.send_message( await komm.send_message(
db=self.db, db=self.db,
tenant_id=self.tenant_id, tenant_id=self.tenant_id,