import { html } from "@mariozechner/mini-lit"; import type { AgentTool, AssistantMessage as AssistantMessageType, ToolCall, ToolResultMessage as ToolResultMessageType, UserMessage as UserMessageType, } from "@mariozechner/pi-ai"; import { LitElement, type TemplateResult } from "lit"; import { customElement, property } from "lit/decorators.js"; import { renderTool } from "../tools/index.js"; import type { Attachment } from "../utils/attachment-utils.js"; import { formatUsage } from "../utils/format.js"; import { i18n } from "../utils/i18n.js"; export type UserMessageWithAttachments = UserMessageType & { attachments?: Attachment[] }; // Artifact message type for session persistence export interface ArtifactMessage { role: "artifact"; action: "create" | "update" | "delete"; filename: string; content?: string; title?: string; timestamp: string; } // Base message union type BaseMessage = AssistantMessageType | UserMessageWithAttachments | ToolResultMessageType | ArtifactMessage; // Extensible interface - apps can extend via declaration merging // Example: // declare module "@mariozechner/pi-web-ui" { // interface CustomMessages { // "system-notification": SystemNotificationMessage; // } // } export interface CustomMessages { // Empty by default - apps extend via declaration merging } // AppMessage is union of base messages + custom messages export type AppMessage = BaseMessage | CustomMessages[keyof CustomMessages]; @customElement("user-message") export class UserMessage extends LitElement { @property({ type: Object }) message!: UserMessageWithAttachments; protected override createRenderRoot(): HTMLElement | DocumentFragment { return this; } override connectedCallback(): void { super.connectedCallback(); this.style.display = "block"; } override render() { const content = typeof this.message.content === "string" ? this.message.content : this.message.content.find((c) => c.type === "text")?.text || ""; return html`