3 ChatAttachmentsListItemMcpPrompt,
4 ChatAttachmentsListItemMcpResource,
5 ChatAttachmentsListItemThumbnailImage,
6 ChatAttachmentsListItemThumbnailFile
7 } from '$lib/components/app';
8 import { AttachmentType } from '$lib/enums';
10 ChatAttachmentDisplayItem,
11 DatabaseMessageExtraMcpPrompt,
12 DatabaseMessageExtraMcpResource,
15 import { isMcpPrompt, isMcpResource, isPdfFile } from '$lib/utils';
22 item: ChatAttachmentDisplayItem;
23 limitToSingleRow?: boolean;
24 onFileRemove?: (fileId: string) => void;
25 onMcpResourcePreview?: (extra: DatabaseMessageExtraMcpResource) => void;
26 onPreview?: (item: ChatAttachmentDisplayItem) => void;
31 class: className = '',
34 imageWidth = 'w-auto',
36 limitToSingleRow = false,
43 const scrollClasses = $derived(limitToSingleRow ? 'first:ml-4 last:mr-4' : '');
45 function toMcpResourceAttachment(
46 extra: DatabaseMessageExtraMcpResource,
48 ): MCPResourceAttachment {
55 serverName: extra.serverName
61 {#if isMcpPrompt(item)}
63 item.attachment?.type === AttachmentType.MCP_PROMPT
64 ? (item.attachment as DatabaseMessageExtraMcpPrompt)
65 : item.uploadedFile?.mcpPrompt
67 type: AttachmentType.MCP_PROMPT as const,
69 serverName: item.uploadedFile.mcpPrompt.serverName,
70 promptName: item.uploadedFile.mcpPrompt.promptName,
71 content: item.textContent ?? '',
72 arguments: item.uploadedFile.mcpPrompt.arguments
76 <ChatAttachmentsListItemMcpPrompt
77 class="max-w-[300px] min-w-[200px] flex-shrink-0 {className} {scrollClasses}"
80 isLoading={item.isLoading}
81 loadError={item.loadError}
82 onRemove={onFileRemove ? () => onFileRemove(item.id) : undefined}
85 {:else if isMcpResource(item)}
86 {@const mcpResource = item.attachment as DatabaseMessageExtraMcpResource}
88 <ChatAttachmentsListItemMcpResource
89 class="flex-shrink-0 {className} {scrollClasses}"
90 attachment={toMcpResourceAttachment(mcpResource, item.id)}
91 onclick={() => onMcpResourcePreview?.(mcpResource)}
93 {:else if item.isImage && item.preview}
94 <ChatAttachmentsListItemThumbnailImage
95 class="flex-shrink-0 cursor-pointer {className} {scrollClasses}"
98 preview={item.preview}
100 onRemove={onFileRemove}
104 onclick={() => onPreview?.(item)}
106 {:else if isPdfFile(item.attachment, item.uploadedFile)}
107 <ChatAttachmentsListItemThumbnailFile
108 class="flex-shrink-0 cursor-pointer {className} {scrollClasses}"
113 onRemove={onFileRemove}
114 textContent={item.textContent}
115 attachment={item.attachment}
116 uploadedFile={item.uploadedFile}
117 onclick={() => onPreview?.(item)}
120 <ChatAttachmentsListItemThumbnailFile
121 class="flex-shrink-0 cursor-pointer {className} {scrollClasses}"
126 onRemove={onFileRemove}
127 textContent={item.textContent}
128 attachment={item.attachment}
129 uploadedFile={item.uploadedFile}
130 onclick={() => onPreview?.(item)}