""" title: UltiAI NC Sync author: ulti-suite version: 0.1.0 description: Sync completed chats to Nextcloud via ulti-backend. """ from typing import Optional import os import json import urllib.request class Pipeline: def __init__(self): self.ultid_api = os.environ.get("ULTID_API_URL", "http://ultid:8080/api/v1").rstrip("/") self.sync_token = os.environ.get("ULTI_AI_SYNC_TOKEN", "") async def on_shutdown(self): pass async def inlet(self, body: dict, user: Optional[dict] = None) -> dict: return body async def outlet(self, body: dict, user: Optional[dict] = None) -> dict: chat = body.get("chat") or body.get("messages") if not chat: return body chat_id = body.get("chat_id") or body.get("id") if not chat_id: return body record = { "id": chat_id, "title": body.get("title") or "Conversation", "source": "openwebui", "openwebui_chat_id": chat_id, "messages": body.get("messages") or [], "meta": { "model": body.get("model"), "context": body.get("context") or "standalone", }, } try: payload = json.dumps(record).encode("utf-8") req = urllib.request.Request( f"{self.ultid_api}/ai/chats/sync", data=payload, headers={ "Content-Type": "application/json", "Authorization": f"Bearer {self.sync_token}" if self.sync_token else "", }, method="POST", ) with urllib.request.urlopen(req, timeout=15) as resp: if resp.status >= 400: print(f"[ulti-nc-sync] sync failed: {resp.status}") except Exception as exc: print(f"[ulti-nc-sync] sync error: {exc}") return body