import { Button, html, icon } 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, state } from "lit/decorators.js"; import { Bug, Loader, Wrench } from "lucide"; 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[] }; // Base message union type BaseMessage = AssistantMessageType | UserMessageWithAttachments | ToolResultMessageType; // 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`