feat: Unified Messaging System — kommunikation plugin, AI/Proactive/System participants, MessageSidebar, Rich Content Renderer
Phase 1: Backend plugin kommunikation (13 files, 10 tables, REST API, WebSocket, RBAC, DMS Bridge, Participant Registry, Mini-App Registry, Search Provider) Phase 2: AI plugins as participants (ai_assistant + ai_proactive dock as participants, heartbeat job) Phase 3: system_notif plugin (system events → chat messages, pinned System room) Phase 4: Frontend MessageSidebar (replaces AISidebar, same design, comm API client, WebSocket hook, commStore) Phase 5: Rich Content Block Renderer (11 components: Markdown, HTML, Image, Audio, Video, File, ActionCard, ContactCard, MiniApp, BlockRenderer) BasePlugin: added services property + _container in on_activate
This commit is contained in:
@@ -314,3 +314,84 @@ async def deep_analysis(
|
||||
entity_type,
|
||||
entity_id,
|
||||
)
|
||||
|
||||
|
||||
# ─── Heartbeat Job ───
|
||||
|
||||
|
||||
async def heartbeat(ctx: dict[str, Any], user_id: str, tenant_id: str) -> None:
|
||||
"""Heartbeat job for the AI Proactive plugin.
|
||||
|
||||
Runs every 5 minutes (scheduled by the plugin on activation).
|
||||
Posts a status message to the 'Live KI' room in the kommunikation system.
|
||||
"""
|
||||
try:
|
||||
uid = uuid.UUID(user_id)
|
||||
tid = uuid.UUID(tenant_id)
|
||||
except (ValueError, TypeError):
|
||||
logger.warning("heartbeat: invalid UUID parameters (user_id=%s, tenant_id=%s)", user_id, tenant_id)
|
||||
return
|
||||
|
||||
try:
|
||||
from app.core.db import create_db_session
|
||||
from app.plugins.builtins.kommunikation.services import (
|
||||
create_plugin_room,
|
||||
send_message,
|
||||
)
|
||||
|
||||
async with create_db_session(tid) as db:
|
||||
# Create or get the 'Live KI' room for this user
|
||||
room = await create_plugin_room(
|
||||
db,
|
||||
tid,
|
||||
uid,
|
||||
plugin_name="ai_proactive",
|
||||
title="Live KI",
|
||||
participant_type="ai_proactive",
|
||||
user_role="member",
|
||||
)
|
||||
|
||||
conversation_id_str = room.get("id")
|
||||
if not conversation_id_str:
|
||||
logger.warning("heartbeat: could not create/get Live KI room")
|
||||
return
|
||||
|
||||
conversation_id = uuid.UUID(conversation_id_str)
|
||||
|
||||
# Gather some stats for the status message
|
||||
from sqlalchemy import func, select
|
||||
|
||||
from app.models.contact import Contact
|
||||
|
||||
contact_count_result = await db.execute(
|
||||
select(func.count()).select_from(Contact).where(
|
||||
Contact.tenant_id == tid,
|
||||
Contact.deleted_at.is_(None),
|
||||
)
|
||||
)
|
||||
contact_count = contact_count_result.scalar() or 0
|
||||
|
||||
# Build status message
|
||||
from datetime import datetime, timezone
|
||||
|
||||
now_str = datetime.now(timezone.utc).strftime("%H:%M:%S")
|
||||
status_content = (
|
||||
f"**System aktiv** — überwacht {contact_count} Kontakte\n"
|
||||
f"_Letztes Update: {now_str}_"
|
||||
)
|
||||
|
||||
await send_message(
|
||||
db=db,
|
||||
tenant_id=tid,
|
||||
conversation_id=conversation_id,
|
||||
sender_id=None,
|
||||
sender_type="ai_proactive",
|
||||
content=status_content,
|
||||
content_format="markdown",
|
||||
)
|
||||
|
||||
await db.commit()
|
||||
logger.info("heartbeat: posted status to Live KI room for user %s", user_id)
|
||||
|
||||
except Exception:
|
||||
logger.exception("heartbeat: error posting status message")
|
||||
|
||||
Reference in New Issue
Block a user