| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100 |
- <script lang="ts">
- import { LibraryBig, Toolbox } from '@lucide/svelte';
- import type { ClassValue } from 'svelte/elements';
- import { resolve } from '$app/paths';
- import { GlassPane } from '$lib/components/common/glass-pane';
- import { Icon } from '$lib/components/common/icon';
- import { StatusBadge } from '$lib/components/common/status-badge';
- import { Tags } from '$lib/components/common/tags';
- import type { Agent } from '$lib/types/entities';
- let {
- class: className = '',
- agent,
- selectedTags,
- onselect,
- }: {
- class?: ClassValue;
- agent: Agent;
- selectedTags?: Set<string>;
- onselect?: () => void;
- } = $props();
- </script>
- {#snippet content()}
- <GlassPane
- class={[
- 'relative flex h-64 flex-col gap-2 overflow-hidden rounded-xl p-4 hover:border-white/20 hover:bg-white/5',
- className,
- ]}
- reactive
- >
- <!-- header -->
- <div class="flex shrink-0 items-center gap-2">
- <Icon icon={agent.icon} size={36} />
- <div
- class="text-md line-clamp-2 flex-1 truncate leading-none font-medium text-wrap text-white/75 group-hover:text-white"
- >
- {agent.name}
- </div>
- {#if agent.status}
- <StatusBadge class="shrink-0" status={agent.status} />
- {/if}
- </div>
- {#if agent.description}
- <div class="line-clamp-3 shrink-0 text-sm text-white/50">
- {agent.description}
- </div>
- {:else}
- <div class="shrink-0 text-xs text-white/25"><no description></div>
- {/if}
- <div class="mb-2 overflow-hidden">
- {#if agent.tags.length > 0}
- <Tags activeTags={selectedTags} tags={agent.tags} />
- {/if}
- </div>
- <div class="mt-auto flex shrink-0 flex-col gap-2">
- {#if agent.kbs.length > 0}
- {@const visible = agent.kbs.slice(0, 2)}
- {@const overflow = agent.kbs.length - visible.length}
- <div class="flex items-center gap-1 text-xs text-white/50">
- <LibraryBig class="shrink-0 text-primary/75" size={16} strokeWidth={2} />
- <span class="truncate">
- {visible.map((kb) => kb.name).join(', ')}{overflow > 0 ? ` +${overflow}` : ''}
- </span>
- </div>
- {/if}
- {#if agent.tools.length > 0}
- {@const visible = agent.tools.slice(0, 2)}
- {@const overflow = agent.tools.length - visible.length}
- <div class="flex items-center gap-1 text-xs text-white/50">
- <Toolbox class="shrink-0 text-primary/75" size={16} strokeWidth={2} />
- <span class="truncate">
- {visible.map((t) => t.name).join(', ')}{overflow > 0 ? ` +${overflow}` : ''}
- </span>
- </div>
- {/if}
- </div>
- </GlassPane>
- {/snippet}
- {#if onselect === undefined}
- <a class="group block" href={resolve('/workloads/agents/[id]', { id: agent.id })}>
- {@render content()}
- </a>
- {:else}
- <div
- class="group block"
- role="button"
- tabindex="0"
- onclick={() => onselect()}
- onkeydown={(e) => e.key === 'Enter' && onselect()}
- >
- {@render content()}
- </div>
- {/if}
|