Skip to content

Commit e20a1e9

Browse files
committed
(feat): show highlighted agents
1 parent fbdaa46 commit e20a1e9

File tree

2 files changed

+110
-176
lines changed

2 files changed

+110
-176
lines changed

web/src/lib/components/CreateAgentDialog.svelte

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,15 @@
2727
// Preload the sound effect
2828
soundEffect = new Audio('whoosh.mp3');
2929
soundEffect.preload = 'auto';
30-
soundEffect.volume = 0.5
30+
soundEffect.volume = 0.5;
31+
32+
// Preload the images
33+
platforms.forEach(platform => {
34+
if (platform.id !== 'github') {
35+
const img = new Image();
36+
img.src = platform.icon;
37+
}
38+
});
3139
}
3240
3341
const onCreateAgent = () => {
@@ -78,7 +86,6 @@
7886
{:else}
7987
<img src={platform.icon} alt={platform.label} class="w-10 h-10 mb-1" />
8088
{/if}
81-
8289
</div>
8390
<span class="text-xs text-gray-300">{platform.label}</span>
8491
</button>

web/src/routes/+page.svelte

Lines changed: 101 additions & 174 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
let searchValue: string = "";
1919
let showModal: boolean = false;
2020
let currentAgent: Agent;
21+
let sections: { [key: string]: Agent[] } = {};
2122
2223
const promotedAgent: Agent = {
2324
name: "promoted-agent",
@@ -36,33 +37,51 @@
3637
3738
onMount(async () => {
3839
loading = true;
39-
const response = await fetch(
40-
"https://api.commanddash.dev/agent/web/get-agent-list",
41-
{
42-
headers: {
43-
"Content-Type": "application/json",
44-
},
45-
method: "POST",
46-
body: JSON.stringify({ cli_version: "0.0.1" }),
47-
},
48-
);
40+
try {
41+
const [existingResponse, newResponse] = await Promise.all([
42+
fetch("https://api.commanddash.dev/agent/web/get-agent-list", {
43+
headers: {
44+
"Content-Type": "application/json",
45+
},
46+
method: "POST",
47+
body: JSON.stringify({ cli_version: "0.0.1" }),
48+
}),
49+
fetch("https://api.commanddash.dev/agent/web/get-highlighted-agent-list", {
50+
headers: {
51+
"Content-Type": "application/json",
52+
},
53+
method: "POST",
54+
body: JSON.stringify({ cli_version: "0.0.1" }),
55+
})
56+
]);
4957
50-
const _response = await response.json();
51-
if (!response.ok) {
52-
loading = false;
53-
appInsights.trackException({
54-
error: new Error("Failed to fetch agents"),
55-
}); // Track
56-
}
57-
agents = _response;
58-
filteredAgents = _response;
59-
loading = false;
60-
appInsights.trackEvent({ name: "AgentsLoaded" }); // Track custom event
58+
const existingAgents = await existingResponse.json();
59+
const newAgents = await newResponse.json();
60+
61+
if (!existingResponse.ok || !newResponse.ok) {
62+
throw new Error("Failed to fetch agents");
63+
}
64+
65+
agents = existingAgents;
66+
filteredAgents = existingAgents;
67+
68+
// Combine agents from new API into sections
69+
sections = newAgents;
70+
71+
// Add existing agents under "All Agents" section
72+
sections["All Agents"] = existingAgents;
73+
74+
appInsights.trackEvent({ name: "AgentsLoaded" }); // Track custom event
6175
62-
// Check if the 'create' query parameter is set to 'true'
63-
const urlParams = new URLSearchParams(window.location.search);
64-
if (urlParams.get('create') === 'true') {
65-
showModal = true;
76+
// Check if the 'create' query parameter is set to 'true'
77+
const urlParams = new URLSearchParams(window.location.search);
78+
if (urlParams.get('create') === 'true') {
79+
showModal = true;
80+
}
81+
} catch (error) {
82+
appInsights.trackException({ error });
83+
} finally {
84+
loading = false;
6685
}
6786
});
6887
@@ -81,11 +100,11 @@
81100
agent.metadata.display_name
82101
.toLowerCase()
83102
.includes(searchValue) ||
84-
agent.author.name.toLowerCase().includes(searchValue) ||
85-
agent.author.source_url?.toLowerCase().includes(searchValue)
103+
agent.author?.name.toLowerCase().includes(searchValue) ||
104+
agent.author?.source_url?.toLowerCase().includes(searchValue)
86105
);
87106
});
88-
appInsights.trackEvent({ name: "Search", properties: { searchValue } }); // Track cus
107+
appInsights.trackEvent({ name: "Search", properties: { searchValue } }); // Track custom event
89108
}, SEARCH_DEBOUNCE_DELAY);
90109
91110
const formatGithubUrl = (url: string) => {
@@ -122,10 +141,10 @@
122141
<div class="flex flex-row">
123142
<div>
124143
<div class="flex items-center">
125-
<h1 class="text-2xl font-bold">AI Agents for Libraries and SDKs</h1>
144+
<h1 class="text-2xl font-bold">AI Agents for Libraries</h1>
126145
</div>
127146
<h3 class="text-gray-500">
128-
Build apps faster with specialized agents at your command.
147+
Personalized answers from expert agents at your command
129148
</h3>
130149
</div>
131150
<button
@@ -164,163 +183,71 @@
164183
</div>
165184
</div>
166185
{:else}
167-
<div
168-
class="mt-7 flex flex-wrap items-center gap-x-2 gap-y-3 text-sm"
169-
></div>
170-
<div
171-
class="mt-8 grid grid-cols-2 gap-3 sm:gap-5 md:grid-cols-3 lg:grid-cols-4"
172-
>
173-
{#if filteredAgents.length > 0}
174-
{#each filteredAgents as agent, index}
175-
{#if index === 2}
186+
{#each Object.keys(sections) as section}
187+
<div class="mt-7">
188+
<h2 class="text-xl font-semibold">{section}</h2>
189+
<div
190+
class="mt-4 grid grid-cols-2 gap-3 sm:gap-5 md:grid-cols-3 lg:grid-cols-4"
191+
>
192+
{#each sections[section] as agent, index}
193+
{#if index === 2 && section === "All Agents"}
194+
<button
195+
class="relative flex flex-col items-center justify-center overflow-hidden text-balance rounded-xl border bg-gray-50/50 px-4 py-6 text-center shadow hover:bg-gray-50 hover:shadow-inner max-sm:px-4 sm:h-64 sm:pb-4 xl:pt-8 dark:border-gray-800/70 dark:bg-gray-950/20 dark:hover:bg-gray-950/40 promoted-card"
196+
on:click={() => window.open(promotedAgent.author.source_url, "_blank")}
197+
>
198+
<img
199+
src={promotedAgent.metadata.avatar_id}
200+
alt="Avatar"
201+
class="mb-2 aspect-square size-12 flex-none rounded-full object-cover sm:mb-6 sm:size-20"
202+
/>
203+
<h3
204+
class="mb-2 line-clamp-2 max-w-full break-words text-center text-[.8rem] font-semibold leading-snug sm:text-sm promoted-text"
205+
>
206+
{promotedAgent.metadata.display_name}
207+
</h3>
208+
<p
209+
class="line-clamp-4 text-xs text-gray-700 sm:line-clamp-2 dark:text-gray-400 promoted-text"
210+
>
211+
{promotedAgent.metadata.description}
212+
</p>
213+
<span class="promoted-indicator">Promoted</span>
214+
</button>
215+
{/if}
176216
<button
177-
class="relative flex flex-col items-center justify-center overflow-hidden text-balance rounded-xl border bg-gray-50/50 px-4 py-6 text-center shadow hover:bg-gray-50 hover:shadow-inner max-sm:px-4 sm:h-64 sm:pb-4 xl:pt-8 dark:border-gray-800/70 dark:bg-gray-950/20 dark:hover:bg-gray-950/40 promoted-card"
178-
on:click={() => window.open(promotedAgent.author.source_url, "_blank")}
217+
class="relative flex flex-col items-center justify-center overflow-hidden text-balance rounded-xl border bg-gray-50/50 px-4 py-6 text-center shadow hover:bg-gray-50 hover:shadow-inner max-sm:px-4 sm:h-64 sm:pb-4 xl:pt-8 dark:border-gray-800/70 dark:bg-gray-950/20 dark:hover:bg-gray-950/40"
218+
on:click={() => navigateAgents(agent)}
179219
>
180220
<img
181-
src={promotedAgent.metadata.avatar_id}
221+
src={agent.metadata.avatar_id}
182222
alt="Avatar"
183223
class="mb-2 aspect-square size-12 flex-none rounded-full object-cover sm:mb-6 sm:size-20"
184224
/>
185225
<h3
186-
class="mb-2 line-clamp-2 max-w-full break-words text-center text-[.8rem] font-semibold leading-snug sm:text-sm promoted-text"
226+
class="mb-2 line-clamp-2 max-w-full break-words text-center text-[.8rem] font-semibold leading-snug sm:text-sm"
187227
>
188-
{promotedAgent.metadata.display_name}
228+
{agent.metadata.display_name}
189229
</h3>
190230
<p
191-
class="line-clamp-4 text-xs text-gray-700 sm:line-clamp-2 dark:text-gray-400 promoted-text"
231+
class="line-clamp-4 text-xs text-gray-700 sm:line-clamp-2 dark:text-gray-400"
192232
>
193-
{promotedAgent.metadata.description}
233+
{agent.metadata.description}
194234
</p>
195-
<span class="promoted-indicator">Promoted</span>
235+
{#if agent.author?.source_url}
236+
<a
237+
href={agent.author.source_url}
238+
class="mt-auto pt-2 text-xs text-gray-400 dark:text-gray-500 line-clamp-1 hover:underline inline-flex flex-row items-center"
239+
target="_blank"
240+
rel="noreferrer"
241+
>
242+
<CarbonGithub class="mx-1" />
243+
{formatText(agent.author.source_url, 20)}
244+
</a>
245+
{/if}
196246
</button>
197-
{/if}
198-
<button
199-
class="relative flex flex-col items-center justify-center overflow-hidden text-balance rounded-xl border bg-gray-50/50 px-4 py-6 text-center shadow hover:bg-gray-50 hover:shadow-inner max-sm:px-4 sm:h-64 sm:pb-4 xl:pt-8 dark:border-gray-800/70 dark:bg-gray-950/20 dark:hover:bg-gray-950/40"
200-
on:click={() => navigateAgents(agent)}
201-
>
202-
<img
203-
src={agent.metadata.avatar_id}
204-
alt="Avatar"
205-
class="mb-2 aspect-square size-12 flex-none rounded-full object-cover sm:mb-6 sm:size-20"
206-
/>
207-
<h3
208-
class="mb-2 line-clamp-2 max-w-full break-words text-center text-[.8rem] font-semibold leading-snug sm:text-sm"
209-
>
210-
{agent.metadata.display_name}
211-
</h3>
212-
<p
213-
class="line-clamp-4 text-xs text-gray-700 sm:line-clamp-2 dark:text-gray-400"
214-
>
215-
{agent.metadata.description}
216-
</p>
217-
{#if agent.author.source_url}
218-
<a
219-
href={agent.author.source_url}
220-
class="mt-auto pt-2 text-xs text-gray-400 dark:text-gray-500 line-clamp-1 hover:underline inline-flex flex-row items-center"
221-
target="_blank"
222-
rel="noreferrer"
223-
>
224-
<CarbonGithub class="mx-1" />
225-
{formatText(agent.author.source_url, 20)}
226-
</a>
227-
{/if}
228-
</button>
229-
{/each}
230-
{#if filteredAgents.length <= 2}
231-
<button
232-
class="relative flex flex-col items-center justify-center overflow-hidden text-balance rounded-xl border bg-gray-50/50 px-4 py-6 text-center shadow hover:bg-gray-50 hover:shadow-inner max-sm:px-4 sm:h-64 sm:pb-4 xl:pt-8 dark:border-gray-800/70 dark:bg-gray-950/20 dark:hover:bg-gray-950/40 promoted-card"
233-
on:click={() => window.open(promotedAgent.author.source_url, "_blank")}
234-
>
235-
<img
236-
src={promotedAgent.metadata.avatar_id}
237-
alt="Avatar"
238-
class="mb-2 aspect-square size-12 flex-none rounded-full object-cover sm:mb-6 sm:size-20"
239-
/>
240-
<h3
241-
class="mb-2 line-clamp-2 max-w-full break-words text-center text-[.8rem] font-semibold leading-snug sm:text-sm promoted-text"
242-
>
243-
{promotedAgent.metadata.display_name}
244-
</h3>
245-
<p
246-
class="line-clamp-4 text-xs text-gray-700 sm:line-clamp-2 dark:text-gray-400 promoted-text"
247-
>
248-
{promotedAgent.metadata.description}
249-
</p>
250-
<span class="promoted-indicator">Promoted</span>
251-
</button>
252-
{/if}
253-
{:else}
254-
<button
255-
class="relative flex flex-col items-center justify-center overflow-hidden text-balance rounded-xl border bg-gray-50/50 px-4 py-6 text-center shadow hover:bg-gray-50 hover:shadow-inner max-sm:px-4 sm:h-64 sm:pb-4 xl:pt-8 dark:border-gray-800/70 dark:bg-gray-950/20 dark:hover:bg-gray-950/40 promoted-card"
256-
on:click={() => window.open(promotedAgent.author.source_url, "_blank")}
257-
>
258-
<img
259-
src={promotedAgent.metadata.avatar_id}
260-
alt="Avatar"
261-
class="mb-2 aspect-square size-12 flex-none rounded-full object-cover sm:mb-6 sm:size-20"
262-
/>
263-
<h3
264-
class="mb-2 line-clamp-2 max-w-full break-words text-center text-[.8rem] font-semibold leading-snug sm:text-sm promoted-text"
265-
>
266-
{promotedAgent.metadata.display_name}
267-
</h3>
268-
<p
269-
class="line-clamp-4 text-xs text-gray-700 sm:line-clamp-2 dark:text-gray-400 promoted-text"
270-
>
271-
{promotedAgent.metadata.description}
272-
</p>
273-
<span class="promoted-indicator">Promoted</span>
274-
</button>
275-
{#each filteredAgents as agent}
276-
<button
277-
class="relative flex flex-col items-center justify-center overflow-hidden text-balance rounded-xl border bg-gray-50/50 px-4 py-6 text-center shadow hover:bg-gray-50 hover:shadow-inner max-sm:px-4 sm:h-64 sm:pb-4 xl:pt-8 dark:border-gray-800/70 dark:bg-gray-950/20 dark:hover:bg-gray-950/40"
278-
on:click={() => navigateAgents(agent)}
279-
>
280-
<img
281-
src={agent.metadata.avatar_id}
282-
alt="Avatar"
283-
class="mb-2 aspect-square size-12 flex-none rounded-full object-cover sm:mb-6 sm:size-20"
284-
/>
285-
<h3
286-
class="mb-2 line-clamp-2 max-w-full break-words text-center text-[.8rem] font-semibold leading-snug sm:text-sm"
287-
>
288-
{agent.metadata.display_name}
289-
</h3>
290-
<p
291-
class="line-clamp-4 text-xs text-gray-700 sm:line-clamp-2 dark:text-gray-400"
292-
>
293-
{agent.metadata.description}
294-
</p>
295-
{#if agent.author.source_url}
296-
<a
297-
href={agent.author.source_url}
298-
class="mt-auto pt-2 text-xs text-gray-400 dark:text-gray-500 line-clamp-1 hover:underline inline-flex flex-row items-center"
299-
target="_blank"
300-
rel="noreferrer"
301-
>
302-
<CarbonGithub class="mx-1" />
303-
{formatText(agent.author.source_url, 20)}
304-
<span class="ml-1">→</span>
305-
</a>
306-
{/if}
307-
</button>
308-
{/each}
309-
{/if}
310-
<button
311-
class="relative flex flex-col items-center justify-center overflow-hidden text-balance rounded-xl border bg-gray-50/50 px-4 py-6 text-center shadow hover:bg-gray-50 hover:shadow-inner max-sm:px-4 sm:h-64 sm:pb-4 xl:pt-8 dark:border-gray-800/70 dark:bg-gray-950/20 dark:hover:bg-gray-950/40"
312-
on:click={() => {
313-
showModal = true;
314-
}}
315-
>
316-
<CarbonAdd height="5.5em" width="5.5em" />
317-
<h3
318-
class="mb-2 line-clamp-2 max-w-full break-words text-center text-[.8rem] font-semibold leading-snug sm:text-sm mt-2"
319-
>
320-
Create Agent
321-
</h3>
322-
</button>
323-
</div>
247+
{/each}
248+
</div>
249+
</div>
250+
{/each}
324251
{/if}
325252
</div>
326253
</div>

0 commit comments

Comments
 (0)