2 import { Loader2, AlertCircle } from '@lucide/svelte';
3 import { mcpStore } from '$lib/stores/mcp.svelte';
4 import type { MCPResourceAttachment } from '$lib/types';
5 import * as Tooltip from '$lib/components/ui/tooltip';
6 import { ActionIcon } from '$lib/components/app';
7 import { X } from '@lucide/svelte';
8 import { getResourceIcon, getResourceDisplayName } from '$lib/utils';
11 attachment: MCPResourceAttachment;
14 onRemove?: (attachmentId: string) => void;
17 let { attachment, class: className, onclick, onRemove }: Props = $props();
19 const ResourceIcon = $derived(
20 getResourceIcon(attachment.resource.mimeType, attachment.resource.uri)
22 const serverName = $derived(mcpStore.getServerDisplayName(attachment.resource.serverName));
23 const favicon = $derived(mcpStore.getServerFavicon(attachment.resource.serverName));
25 function getStatusClass(attachment: MCPResourceAttachment): string {
26 if (attachment.error) return 'border-red-500/50 bg-red-500/10';
27 if (attachment.loading) return 'border-border/50 bg-muted/30';
29 return 'border-border/50 bg-muted/30';
37 'flex flex-shrink-0 items-center gap-1.5 rounded-md border px-2 py-0.75 text-sm transition-colors',
38 getStatusClass(attachment),
39 onclick && 'cursor-pointer hover:bg-muted/50',
46 {#if attachment.loading}
47 <Loader2 class="h-3 w-3 animate-spin text-muted-foreground" />
48 {:else if attachment.error}
49 <AlertCircle class="h-3 w-3 text-red-500" />
51 <ResourceIcon class="h-3 w-3 text-muted-foreground" />
54 <span class="max-w-[150px] truncate text-xs">
55 {getResourceDisplayName(attachment.resource)}
60 class="-my-2 -mr-1.5 bg-transparent"
63 onclick={() => onRemove?.(attachment.id)}
64 stopPropagationOnClick
72 <div class="flex items-center gap-1 text-xs">
75 alt={attachment.resource.serverName}
76 class="h-3 w-3 shrink-0 rounded-sm"
78 (e.currentTarget as HTMLImageElement).style.display = 'none';
84 <span class="truncate">