Phase 0 Complete: Tasks 0.7-0.20

- 0.7: UI-Design-Richtlinien (docs/ui-design-guidelines.md, 535 lines)
- 0.8: Theme-Customization Backend (4 theme fields, migration 0023)
- 0.9: Theme-Customization Frontend (SettingsTheme.tsx, themeStore.ts, live preview)
- 0.10: RBAC-Audit (4 plugins secured, 53 routes with require_permission)
- 0.11: LiteLLM-Cleanup (llm_client.py migrated from httpx to litellm)
- 0.12: KI-Agent-Framework docs (plugin-development-guide.md, agent_capabilities field)
- 0.13: Heartbeat configurable (ProactiveSettings, migration 0024, frontend UI)
- 0.14: Unified Search Field-Level RBAC (resolve_permissions + filter_fields_by_permission)
- 0.15: Undo/History-System (EntityHistory model, service, routes, migration 0025, HistoryViewer)
- 0.16: Storage Backend (LocalStorage + S3Storage, DMS/attachments/mail updated)
- 0.17: Import/Export unified Contact fields (firstname, surname, email_1, phone_1)
- 0.18: .gitignore & Config-Cleanup (webui→frontend, python-jose removed, .env untracked)
- 0.19: Mail-Salt Security-Fix (per-account random salt, migration 0026)
- 0.20: AGPL replaced (PyMuPDF→pypdf, OnlyOffice→Collabora, LICENSE + THIRD_PARTY_LICENSES.md)
This commit is contained in:
Agent Zero
2026-07-23 08:42:26 +02:00
parent 3d06cb2353
commit ec81940178
65 changed files with 3061 additions and 277 deletions
+25 -4
View File
@@ -322,8 +322,9 @@ async def deep_analysis(
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.
Interval is configurable via ProactiveSettings.heartbeat_interval_seconds.
Target room is configurable via ProactiveSettings.heartbeat_target_room.
Posts a status message to the configured room in the kommunikation system.
"""
try:
uid = uuid.UUID(user_id)
@@ -340,13 +341,33 @@ async def heartbeat(ctx: dict[str, Any], user_id: str, tenant_id: str) -> None:
)
async with create_db_session(tid) as db:
# Create or get the 'Live KI' room for this user
# Check if heartbeat is enabled and get configuration
from app.plugins.builtins.ai_proactive.models import ProactiveSettings
from sqlalchemy import select as sa_select
settings_result = await db.execute(
sa_select(ProactiveSettings)
.where(ProactiveSettings.tenant_id == tid)
.where(ProactiveSettings.user_id == uid)
.limit(1)
)
settings = settings_result.scalar_one_or_none()
# If no settings or heartbeat disabled, skip
if settings is not None and not settings.heartbeat_enabled:
logger.debug("heartbeat: disabled for user %s", user_id)
return
# Get target room name from settings or use default
target_room_title = settings.heartbeat_target_room if settings else "Live KI"
# Create or get the target room for this user
room = await create_plugin_room(
db,
tid,
uid,
plugin_name="ai_proactive",
title="Live KI",
title=target_room_title,
participant_type="ai_proactive",
user_role="member",
)
@@ -109,3 +109,7 @@ class ProactiveSettings(Base, TenantMixin):
Integer, nullable=False, default=10
)
model: Mapped[str] = mapped_column(String(100), nullable=False, default="ollama/deepseek-v4-flash")
# Heartbeat configuration
heartbeat_enabled: Mapped[bool] = mapped_column(Boolean, nullable=False, default=True)
heartbeat_interval_seconds: Mapped[int] = mapped_column(Integer, nullable=False, default=300)
heartbeat_target_room: Mapped[str] = mapped_column(String(200), nullable=False, default="Live KI")
@@ -72,6 +72,9 @@ def _settings_to_response(s: ProactiveSettings) -> SettingsResponse:
confidence_threshold=s.confidence_threshold,
rate_limit_seconds=s.rate_limit_seconds,
model=s.model,
heartbeat_enabled=s.heartbeat_enabled,
heartbeat_interval_seconds=s.heartbeat_interval_seconds,
heartbeat_target_room=s.heartbeat_target_room,
)
@@ -73,6 +73,9 @@ class SettingsResponse(BaseModel):
confidence_threshold: float
rate_limit_seconds: int
model: str
heartbeat_enabled: bool = True
heartbeat_interval_seconds: int = 300
heartbeat_target_room: str = "Live KI"
available_models: list[str] = Field(default_factory=lambda: [
'ollama/deepseek-v4-flash',
'ollama/deepseek-v4-pro',
@@ -90,6 +93,9 @@ class SettingsUpdate(BaseModel):
confidence_threshold: float | None = None
rate_limit_seconds: int | None = None
model: str | None = None
heartbeat_enabled: bool | None = None
heartbeat_interval_seconds: int | None = None
heartbeat_target_room: str | None = None
class StatsResponse(BaseModel):
@@ -114,6 +114,9 @@ async def get_user_settings(
confidence_threshold=0.5,
rate_limit_seconds=10,
model="ollama/deepseek-v4-flash",
heartbeat_enabled=True,
heartbeat_interval_seconds=300,
heartbeat_target_room="Live KI",
)
db.add(settings)
await db.flush()