import { Alert } from "@mariozechner/mini-lit"; import type { Message } from "@mariozechner/pi-ai"; import { html } from "lit"; import { registerMessageRenderer } from "@mariozechner/pi-web-ui"; import type { AppMessage, MessageRenderer } from "@mariozechner/pi-web-ui"; // ============================================================================ // 1. EXTEND AppMessage TYPE VIA DECLARATION MERGING // ============================================================================ // Define custom message types export interface SystemNotificationMessage { role: "system-notification"; message: string; variant: "default" | "destructive"; timestamp: string; } // Extend CustomMessages interface via declaration merging declare module "@mariozechner/pi-web-ui" { interface CustomMessages { "system-notification": SystemNotificationMessage; } } // ============================================================================ // 2. CREATE CUSTOM RENDERER (TYPED TO SystemNotificationMessage) // ============================================================================ const systemNotificationRenderer: MessageRenderer = { render: (notification) => { // notification is fully typed as SystemNotificationMessage! return html`
${Alert({ variant: notification.variant, children: html`
${notification.message}
${new Date(notification.timestamp).toLocaleTimeString()}
`, })}
`; }, }; // ============================================================================ // 3. REGISTER RENDERER // ============================================================================ export function registerCustomMessageRenderers() { registerMessageRenderer("system-notification", systemNotificationRenderer); } // ============================================================================ // 4. HELPER TO CREATE CUSTOM MESSAGES // ============================================================================ export function createSystemNotification( message: string, variant: "default" | "destructive" = "default", ): SystemNotificationMessage { return { role: "system-notification", message, variant, timestamp: new Date().toISOString(), }; } // ============================================================================ // 5. CUSTOM MESSAGE TRANSFORMER // ============================================================================ // Transform custom messages to user messages with tags so LLM can see them export function customMessageTransformer(messages: AppMessage[]): Message[] { return messages .filter((m) => { // Filter out artifact messages - they're for session reconstruction only if (m.role === "artifact") { return false; } // Keep LLM-compatible messages + custom messages return ( m.role === "user" || m.role === "assistant" || m.role === "toolResult" || m.role === "system-notification" ); }) .map((m) => { // Transform system notifications to user messages if (m.role === "system-notification") { const notification = m as SystemNotificationMessage; return { role: "user", content: `${notification.message}`, } as Message; } // Strip attachments from user messages if (m.role === "user") { const { attachments, ...rest } = m as any; return rest as Message; } return m as Message; }); }