@vertesia/tools-admin-ui 1.0.0-dev.20260227.112605Z → 1.0.0-dev.20260331.091034Z
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/AdminApp.d.ts +3 -1
- package/lib/AdminApp.d.ts.map +1 -1
- package/lib/components/AdminTopBar.d.ts +6 -0
- package/lib/components/AdminTopBar.d.ts.map +1 -0
- package/lib/components/CollectionCard.d.ts.map +1 -1
- package/lib/components/DetailPage.d.ts.map +1 -1
- package/lib/components/EndpointPanel.d.ts.map +1 -1
- package/lib/components/HeroSection.d.ts.map +1 -1
- package/lib/components/ResourceCard.d.ts.map +1 -1
- package/lib/components/ResourceSection.d.ts.map +1 -1
- package/lib/components/SearchBar.d.ts.map +1 -1
- package/lib/components/SummaryBadge.d.ts.map +1 -1
- package/lib/components/index.d.ts +6 -5
- package/lib/components/index.d.ts.map +1 -1
- package/lib/components/typeVariants.d.ts +5 -0
- package/lib/components/typeVariants.d.ts.map +1 -0
- package/lib/hooks.d.ts +1 -1
- package/lib/hooks.d.ts.map +1 -1
- package/lib/pages/ActivityCollection.d.ts +2 -0
- package/lib/pages/ActivityCollection.d.ts.map +1 -0
- package/lib/pages/HomePage.d.ts.map +1 -1
- package/lib/pages/InteractionCollection.d.ts.map +1 -1
- package/lib/pages/InteractionDetail.d.ts.map +1 -1
- package/lib/pages/SkillCollection.d.ts.map +1 -1
- package/lib/pages/SkillDetail.d.ts.map +1 -1
- package/lib/pages/TemplateCollection.d.ts.map +1 -1
- package/lib/pages/TemplateDetail.d.ts.map +1 -1
- package/lib/pages/ToolCollection.d.ts.map +1 -1
- package/lib/pages/TypeCollection.d.ts.map +1 -1
- package/lib/pages/TypeDetail.d.ts.map +1 -1
- package/lib/tools-admin-ui.js +481 -379
- package/lib/tools-admin-ui.js.map +1 -1
- package/lib/types.d.ts +8 -3
- package/lib/types.d.ts.map +1 -1
- package/package.json +8 -4
- package/src/AdminApp.tsx +23 -17
- package/src/components/AdminTopBar.tsx +39 -0
- package/src/components/CollectionCard.tsx +20 -14
- package/src/components/DetailPage.tsx +20 -11
- package/src/components/EndpointPanel.tsx +16 -7
- package/src/components/HeroSection.tsx +52 -45
- package/src/components/ResourceCard.tsx +23 -18
- package/src/components/ResourceSection.tsx +7 -5
- package/src/components/SearchBar.tsx +8 -6
- package/src/components/SummaryBadge.tsx +4 -3
- package/src/components/index.ts +6 -5
- package/src/components/typeVariants.ts +19 -0
- package/src/dev/env.ts +3 -3
- package/src/dev/index.css +13 -0
- package/src/dev/main.tsx +11 -5
- package/src/hooks.ts +5 -3
- package/src/pages/ActivityCollection.tsx +67 -0
- package/src/pages/HomePage.tsx +19 -15
- package/src/pages/InteractionCollection.tsx +25 -27
- package/src/pages/InteractionDetail.tsx +35 -34
- package/src/pages/SkillCollection.tsx +29 -32
- package/src/pages/SkillDetail.tsx +31 -41
- package/src/pages/TemplateCollection.tsx +25 -21
- package/src/pages/TemplateDetail.tsx +18 -17
- package/src/pages/ToolCollection.tsx +22 -16
- package/src/pages/TypeCollection.tsx +32 -24
- package/src/pages/TypeDetail.tsx +16 -18
- package/src/theme.css +12 -0
- package/src/types.ts +34 -1
- package/src/admin.css +0 -650
package/lib/tools-admin-ui.js
CHANGED
|
@@ -1,8 +1,40 @@
|
|
|
1
1
|
import { jsxs, jsx, Fragment } from "react/jsx-runtime";
|
|
2
|
+
import { ModeToggle, Avatar, Button, useFetch, Badge, Spinner, Card, CardContent, DotBadge, Separator, Input } from "@vertesia/ui/core";
|
|
2
3
|
import { NavLink, useParams, NestedRouterProvider, RouteComponent } from "@vertesia/ui/router";
|
|
3
|
-
import { useFetch } from "@vertesia/ui/core";
|
|
4
4
|
import { createContext, useContext, useState, useMemo } from "react";
|
|
5
5
|
import { useUserSession } from "@vertesia/ui/session";
|
|
6
|
+
import { LogOut, ArrowLeft, Check, Copy, LayoutDashboard, Download } from "lucide-react";
|
|
7
|
+
const AdminContext = createContext(void 0);
|
|
8
|
+
function useAdminContext() {
|
|
9
|
+
const ctx = useContext(AdminContext);
|
|
10
|
+
if (!ctx) throw new Error("useAdminContext must be used within AdminApp");
|
|
11
|
+
return ctx;
|
|
12
|
+
}
|
|
13
|
+
function AdminTopBar({ title }) {
|
|
14
|
+
const { user, logout } = useUserSession();
|
|
15
|
+
return /* @__PURE__ */ jsxs("header", { className: "sticky top-0 z-40 flex h-14 items-center justify-between border-b border-border bg-background px-6", children: [
|
|
16
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-center gap-3", children: [
|
|
17
|
+
/* @__PURE__ */ jsx("div", { className: "flex size-8 items-center justify-center rounded-lg bg-primary text-xs font-semibold uppercase tracking-wider text-primary-foreground", children: title.split(/\s+/).map((w) => w[0]).filter(Boolean).slice(0, 2).join("") }),
|
|
18
|
+
/* @__PURE__ */ jsx("span", { className: "text-sm font-semibold text-foreground", children: title })
|
|
19
|
+
] }),
|
|
20
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-center gap-3", children: [
|
|
21
|
+
/* @__PURE__ */ jsx(ModeToggle, { label: false }),
|
|
22
|
+
user && /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
23
|
+
/* @__PURE__ */ jsx(Avatar, { size: "sm", name: user.name, color: "bg-primary" }),
|
|
24
|
+
/* @__PURE__ */ jsx(
|
|
25
|
+
Button,
|
|
26
|
+
{
|
|
27
|
+
variant: "outline",
|
|
28
|
+
size: "sm",
|
|
29
|
+
onClick: () => logout(),
|
|
30
|
+
alt: "Sign out",
|
|
31
|
+
children: /* @__PURE__ */ jsx(LogOut, { className: "size-4" })
|
|
32
|
+
}
|
|
33
|
+
)
|
|
34
|
+
] })
|
|
35
|
+
] })
|
|
36
|
+
] });
|
|
37
|
+
}
|
|
6
38
|
function formatTitle(name) {
|
|
7
39
|
return name.replace(/[-_]/g, " ").replace(/\b\w/g, (c) => c.toUpperCase());
|
|
8
40
|
}
|
|
@@ -21,7 +53,7 @@ function countPerCollection(items, collections, extractCollection) {
|
|
|
21
53
|
}
|
|
22
54
|
return counts;
|
|
23
55
|
}
|
|
24
|
-
function buildResourceData(interactionsResp, toolsResp, skillsResp, typesResp, templatesResp, mcpEndpoints) {
|
|
56
|
+
function buildResourceData(interactionsResp, toolsResp, skillsResp, activitiesResp, typesResp, templatesResp, mcpEndpoints) {
|
|
25
57
|
const collections = [];
|
|
26
58
|
const resources = [];
|
|
27
59
|
const interCounts = countPerCollection(
|
|
@@ -94,6 +126,29 @@ function buildResourceData(interactionsResp, toolsResp, skillsResp, typesResp, t
|
|
|
94
126
|
url: skill.url
|
|
95
127
|
});
|
|
96
128
|
}
|
|
129
|
+
const actCounts = countPerCollection(
|
|
130
|
+
activitiesResp.activities,
|
|
131
|
+
activitiesResp.collections,
|
|
132
|
+
(a) => a.collection
|
|
133
|
+
);
|
|
134
|
+
for (const col of activitiesResp.collections) {
|
|
135
|
+
collections.push({
|
|
136
|
+
name: col.name,
|
|
137
|
+
title: col.title || formatTitle(col.name),
|
|
138
|
+
description: col.description || "",
|
|
139
|
+
type: "activity",
|
|
140
|
+
count: actCounts.get(col.name) || 0
|
|
141
|
+
});
|
|
142
|
+
}
|
|
143
|
+
for (const act of activitiesResp.activities) {
|
|
144
|
+
resources.push({
|
|
145
|
+
name: act.name,
|
|
146
|
+
title: act.title || formatTitle(act.name),
|
|
147
|
+
description: act.description || "",
|
|
148
|
+
type: "activity",
|
|
149
|
+
url: act.url
|
|
150
|
+
});
|
|
151
|
+
}
|
|
97
152
|
const typeCounts = countPerCollection(
|
|
98
153
|
typesResp.types,
|
|
99
154
|
typesResp.collections,
|
|
@@ -176,18 +231,101 @@ function useResourceData(baseUrl, mcpEndpoints) {
|
|
|
176
231
|
fetchJson("interactions"),
|
|
177
232
|
fetchJson("tools"),
|
|
178
233
|
fetchJson("skills"),
|
|
234
|
+
fetchJson("activities"),
|
|
179
235
|
fetchJson("types"),
|
|
180
236
|
fetchJson("templates")
|
|
181
237
|
]).then(
|
|
182
|
-
([interactions, tools, skills, types, templates]) => buildResourceData(interactions, tools, skills, types, templates, mcpEndpoints)
|
|
238
|
+
([interactions, tools, skills, activities, types, templates]) => buildResourceData(interactions, tools, skills, activities, types, templates, mcpEndpoints)
|
|
183
239
|
);
|
|
184
240
|
}, [baseUrl, mcpEndpoints]);
|
|
185
241
|
}
|
|
186
|
-
const
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
242
|
+
const TYPE_VARIANTS = {
|
|
243
|
+
tool: "bg-blue-100 text-blue-800 dark:bg-blue-500/15 dark:text-blue-300",
|
|
244
|
+
skill: "bg-emerald-100 text-emerald-800 dark:bg-emerald-500/15 dark:text-emerald-300",
|
|
245
|
+
interaction: "bg-amber-100 text-amber-800 dark:bg-amber-500/15 dark:text-amber-300",
|
|
246
|
+
type: "bg-gray-100 text-gray-700 dark:bg-gray-500/20 dark:text-gray-300",
|
|
247
|
+
template: "bg-violet-100 text-violet-800 dark:bg-violet-500/15 dark:text-violet-300",
|
|
248
|
+
activity: "bg-rose-100 text-rose-800 dark:bg-rose-500/15 dark:text-rose-300",
|
|
249
|
+
mcp: "bg-pink-100 text-pink-800 dark:bg-pink-500/15 dark:text-pink-300"
|
|
250
|
+
};
|
|
251
|
+
const ROLE_VARIANTS = {
|
|
252
|
+
system: "bg-blue-100 text-blue-800 dark:bg-blue-500/15 dark:text-blue-300",
|
|
253
|
+
user: "bg-emerald-100 text-emerald-800 dark:bg-emerald-500/15 dark:text-emerald-300",
|
|
254
|
+
assistant: "bg-violet-100 text-violet-800 dark:bg-violet-500/15 dark:text-violet-300",
|
|
255
|
+
safety: "bg-pink-100 text-pink-800 dark:bg-pink-500/15 dark:text-pink-300",
|
|
256
|
+
tool: "bg-amber-100 text-amber-800 dark:bg-amber-500/15 dark:text-amber-300"
|
|
257
|
+
};
|
|
258
|
+
function DetailPage({ type, title, description, tags, backHref = "/", children }) {
|
|
259
|
+
return /* @__PURE__ */ jsxs("div", { className: "mx-auto max-w-5xl px-7 py-10", children: [
|
|
260
|
+
/* @__PURE__ */ jsxs("nav", { className: "mb-5 flex items-center gap-4", children: [
|
|
261
|
+
backHref !== "/" && /* @__PURE__ */ jsx(NavLink, { href: "/", className: "text-sm text-primary hover:opacity-75", children: "Home" }),
|
|
262
|
+
/* @__PURE__ */ jsxs(NavLink, { href: backHref, className: "flex items-center gap-1 text-sm text-primary hover:opacity-75", children: [
|
|
263
|
+
/* @__PURE__ */ jsx(ArrowLeft, { className: "size-3.5" }),
|
|
264
|
+
"Back"
|
|
265
|
+
] })
|
|
266
|
+
] }),
|
|
267
|
+
/* @__PURE__ */ jsxs("div", { className: "mb-8", children: [
|
|
268
|
+
/* @__PURE__ */ jsx("span", { className: `mb-2 inline-block rounded-full px-2 py-0.5 text-[0.7rem] font-semibold uppercase tracking-wide ${TYPE_VARIANTS[type] ?? ""}`, children: type }),
|
|
269
|
+
/* @__PURE__ */ jsx("h1", { className: "-tracking-wide text-3xl font-bold text-foreground", children: title }),
|
|
270
|
+
description && /* @__PURE__ */ jsx("p", { className: "mt-1 text-sm leading-relaxed text-muted-foreground", children: description }),
|
|
271
|
+
tags && tags.length > 0 && /* @__PURE__ */ jsx("div", { className: "mt-3 flex flex-wrap gap-1.5", children: tags.map((tag) => /* @__PURE__ */ jsx(Badge, { variant: "default", children: tag }, tag)) })
|
|
272
|
+
] }),
|
|
273
|
+
children
|
|
274
|
+
] });
|
|
275
|
+
}
|
|
276
|
+
function ActivityCollection() {
|
|
277
|
+
const collection = useParams("collection");
|
|
278
|
+
const { baseUrl } = useAdminContext();
|
|
279
|
+
const { data, error } = useFetch(
|
|
280
|
+
() => fetch(`${baseUrl}/activities/${collection}`).then((r) => {
|
|
281
|
+
if (!r.ok) throw new Error(`Failed to load collection: ${r.statusText}`);
|
|
282
|
+
return r.json();
|
|
283
|
+
}),
|
|
284
|
+
[baseUrl, collection]
|
|
285
|
+
);
|
|
286
|
+
if (error) return /* @__PURE__ */ jsxs("div", { className: "p-6 text-destructive", children: [
|
|
287
|
+
"Failed to load activity collection “",
|
|
288
|
+
collection,
|
|
289
|
+
"”."
|
|
290
|
+
] });
|
|
291
|
+
if (!data) return /* @__PURE__ */ jsx("div", { className: "flex h-64 items-center justify-center text-muted-foreground", children: /* @__PURE__ */ jsx(Spinner, {}) });
|
|
292
|
+
return /* @__PURE__ */ jsx(
|
|
293
|
+
DetailPage,
|
|
294
|
+
{
|
|
295
|
+
type: "activity",
|
|
296
|
+
title: data.title || collection,
|
|
297
|
+
description: data.description || `${data.activities.length} activit${data.activities.length !== 1 ? "ies" : "y"} in this collection.`,
|
|
298
|
+
children: data.activities.map((activity) => /* @__PURE__ */ jsx(Card, { className: "mb-4", children: /* @__PURE__ */ jsxs(CardContent, { className: "p-5", children: [
|
|
299
|
+
/* @__PURE__ */ jsxs("div", { className: "mb-2 flex items-center gap-2", children: [
|
|
300
|
+
/* @__PURE__ */ jsx("span", { className: `inline-block rounded-full px-2 py-0.5 text-[0.7rem] font-semibold uppercase tracking-wide ${TYPE_VARIANTS.activity}`, children: "activity" }),
|
|
301
|
+
/* @__PURE__ */ jsx("span", { className: "font-semibold text-card-foreground", children: activity.name })
|
|
302
|
+
] }),
|
|
303
|
+
/* @__PURE__ */ jsx("div", { className: "text-sm text-muted-foreground", children: activity.description || "No description" }),
|
|
304
|
+
activity.input_schema && /* @__PURE__ */ jsxs("div", { className: "mt-3", children: [
|
|
305
|
+
/* @__PURE__ */ jsx("p", { className: "mb-1 text-xs font-semibold uppercase tracking-wide text-muted-foreground", children: "Input Schema" }),
|
|
306
|
+
/* @__PURE__ */ jsx("pre", { className: "whitespace-pre-wrap wrap-break-word rounded-lg border border-border bg-muted-background p-4 font-mono text-sm text-foreground", children: JSON.stringify(activity.input_schema, null, 2) })
|
|
307
|
+
] }),
|
|
308
|
+
activity.output_schema && /* @__PURE__ */ jsxs("div", { className: "mt-3", children: [
|
|
309
|
+
/* @__PURE__ */ jsx("p", { className: "mb-1 text-xs font-semibold uppercase tracking-wide text-muted-foreground", children: "Output Schema" }),
|
|
310
|
+
/* @__PURE__ */ jsx("pre", { className: "whitespace-pre-wrap wrap-break-word rounded-lg border border-border bg-muted-background p-4 font-mono text-sm text-foreground", children: JSON.stringify(activity.output_schema, null, 2) })
|
|
311
|
+
] })
|
|
312
|
+
] }) }, activity.name))
|
|
313
|
+
}
|
|
314
|
+
);
|
|
315
|
+
}
|
|
316
|
+
function CollectionCard({ collection }) {
|
|
317
|
+
const plural = collection.type === "activity" ? "activities" : `${collection.type}s`;
|
|
318
|
+
const href = `/${plural}/${collection.name}`;
|
|
319
|
+
return /* @__PURE__ */ jsx(NavLink, { href, className: "block no-underline", children: /* @__PURE__ */ jsx(Card, { className: "cursor-pointer transition-all hover:-translate-y-0.5 hover:shadow-md", children: /* @__PURE__ */ jsxs(CardContent, { className: "p-5", children: [
|
|
320
|
+
/* @__PURE__ */ jsx("span", { className: `mb-2 inline-block rounded-full px-2 py-0.5 text-[0.7rem] font-semibold uppercase tracking-wide ${TYPE_VARIANTS[collection.type] ?? ""}`, children: collection.type }),
|
|
321
|
+
/* @__PURE__ */ jsx("div", { className: "font-semibold text-card-foreground", children: collection.title }),
|
|
322
|
+
/* @__PURE__ */ jsx("div", { className: "mt-1 text-sm text-muted-foreground", children: collection.description || "No description" }),
|
|
323
|
+
/* @__PURE__ */ jsxs("div", { className: "mt-2 font-mono text-xs text-muted-foreground", children: [
|
|
324
|
+
collection.count,
|
|
325
|
+
" ",
|
|
326
|
+
collection.count === 1 ? "item" : "items"
|
|
327
|
+
] })
|
|
328
|
+
] }) }) });
|
|
191
329
|
}
|
|
192
330
|
function EndpointPanel({ label, path }) {
|
|
193
331
|
const [copied, setCopied] = useState(false);
|
|
@@ -197,18 +335,26 @@ function EndpointPanel({ label, path }) {
|
|
|
197
335
|
setCopied(true);
|
|
198
336
|
setTimeout(() => setCopied(false), 1500);
|
|
199
337
|
}
|
|
200
|
-
return /* @__PURE__ */ jsxs("div", { className: "
|
|
201
|
-
/* @__PURE__ */ jsx("div", { className: "
|
|
202
|
-
/* @__PURE__ */ jsxs("div", { className: "
|
|
203
|
-
/* @__PURE__ */ jsx("code", { className: "
|
|
204
|
-
/* @__PURE__ */ jsx(
|
|
338
|
+
return /* @__PURE__ */ jsxs("div", { className: "mb-3", children: [
|
|
339
|
+
/* @__PURE__ */ jsx("div", { className: "mb-1 text-[0.7rem] font-medium uppercase tracking-widest text-primary", children: label }),
|
|
340
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2 rounded-lg border border-border bg-muted-background px-3 py-2", children: [
|
|
341
|
+
/* @__PURE__ */ jsx("code", { className: "flex-1 font-mono text-sm text-foreground", children: path }),
|
|
342
|
+
/* @__PURE__ */ jsx(
|
|
343
|
+
Button,
|
|
344
|
+
{
|
|
345
|
+
variant: "ghost",
|
|
346
|
+
size: "xs",
|
|
347
|
+
onClick: handleCopy,
|
|
348
|
+
"aria-label": "Copy full URL",
|
|
349
|
+
children: copied ? /* @__PURE__ */ jsx(Check, { className: "size-3.5" }) : /* @__PURE__ */ jsx(Copy, { className: "size-3.5" })
|
|
350
|
+
}
|
|
351
|
+
)
|
|
205
352
|
] })
|
|
206
353
|
] });
|
|
207
354
|
}
|
|
208
355
|
function SummaryBadge({ count, label }) {
|
|
209
356
|
if (count === 0) return null;
|
|
210
|
-
return /* @__PURE__ */ jsxs(
|
|
211
|
-
/* @__PURE__ */ jsx("span", { className: "vta-badge-dot" }),
|
|
357
|
+
return /* @__PURE__ */ jsxs(DotBadge, { variant: "success", children: [
|
|
212
358
|
count,
|
|
213
359
|
" ",
|
|
214
360
|
label,
|
|
@@ -227,6 +373,7 @@ function countByType(resources) {
|
|
|
227
373
|
}
|
|
228
374
|
const badgeLabels = [
|
|
229
375
|
{ type: "tool", label: "tool" },
|
|
376
|
+
{ type: "activity", label: "activity" },
|
|
230
377
|
{ type: "skill", label: "skill" },
|
|
231
378
|
{ type: "interaction", label: "interaction" },
|
|
232
379
|
{ type: "type", label: "content type" },
|
|
@@ -235,135 +382,117 @@ const badgeLabels = [
|
|
|
235
382
|
];
|
|
236
383
|
function HeroSection({ title, version, resources }) {
|
|
237
384
|
const counts = countByType(resources);
|
|
238
|
-
return /* @__PURE__ */ jsxs("
|
|
239
|
-
/* @__PURE__ */ jsxs("div", { className: "
|
|
240
|
-
/* @__PURE__ */ jsxs("div", { className: "
|
|
241
|
-
/* @__PURE__ */ jsx("div", { className: "
|
|
385
|
+
return /* @__PURE__ */ jsx(Card, { className: "mb-10 overflow-hidden border bg-linear-to-br from-card to-muted-background", children: /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-6 p-6 md:flex-row md:items-start md:justify-between", children: [
|
|
386
|
+
/* @__PURE__ */ jsxs("div", { className: "flex flex-1 flex-col gap-3", children: [
|
|
387
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-center gap-4", children: [
|
|
388
|
+
/* @__PURE__ */ jsx("div", { className: "flex size-14 items-center justify-center rounded-xl bg-linear-to-br from-sky-400 to-indigo-500 text-sm font-semibold uppercase tracking-wider text-white shadow-lg", children: getInitials(title) }),
|
|
242
389
|
/* @__PURE__ */ jsxs("div", { children: [
|
|
243
|
-
/* @__PURE__ */ jsx("p", { className: "
|
|
244
|
-
/* @__PURE__ */ jsx("h1", { className: "
|
|
390
|
+
/* @__PURE__ */ jsx("p", { className: "text-xs font-medium uppercase tracking-widest text-muted-foreground", children: "Tools Server" }),
|
|
391
|
+
/* @__PURE__ */ jsx("h1", { className: "-tracking-wide text-2xl font-bold text-foreground", children: title })
|
|
245
392
|
] })
|
|
246
393
|
] }),
|
|
247
|
-
/* @__PURE__ */ jsx("p", { className: "
|
|
248
|
-
/* @__PURE__ */ jsx("div", { className: "
|
|
249
|
-
/* @__PURE__ */ jsxs("div", { className: "
|
|
250
|
-
/* @__PURE__ */ jsxs(
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
394
|
+
/* @__PURE__ */ jsx("p", { className: "text-sm text-muted-foreground", children: "Discover the tools, skills, interactions, and content types exposed by this server." }),
|
|
395
|
+
/* @__PURE__ */ jsx("div", { className: "flex flex-wrap gap-2", children: badgeLabels.map(({ type, label }) => /* @__PURE__ */ jsx(SummaryBadge, { count: counts[type] || 0, label }, type)) }),
|
|
396
|
+
/* @__PURE__ */ jsxs("div", { className: "flex flex-wrap gap-3 pt-1", children: [
|
|
397
|
+
/* @__PURE__ */ jsxs(
|
|
398
|
+
"a",
|
|
399
|
+
{
|
|
400
|
+
href: "/app/",
|
|
401
|
+
target: "_blank",
|
|
402
|
+
rel: "noopener noreferrer",
|
|
403
|
+
className: "inline-flex h-8 items-center gap-2 rounded bg-primary px-3 text-xs font-medium text-white shadow-xs hover:bg-primary/90",
|
|
404
|
+
children: [
|
|
405
|
+
/* @__PURE__ */ jsx(LayoutDashboard, { className: "size-4" }),
|
|
406
|
+
"UI Plugin Dev"
|
|
407
|
+
]
|
|
408
|
+
}
|
|
409
|
+
),
|
|
410
|
+
/* @__PURE__ */ jsxs(
|
|
411
|
+
"a",
|
|
412
|
+
{
|
|
413
|
+
href: "/lib/plugin.js",
|
|
414
|
+
className: "inline-flex h-8 items-center gap-2 rounded bg-primary/5 px-3 text-xs font-medium text-primary shadow-xs hover:bg-primary/10 dark:bg-primary/10 dark:hover:bg-primary/20",
|
|
415
|
+
children: [
|
|
416
|
+
/* @__PURE__ */ jsx(Download, { className: "size-4" }),
|
|
417
|
+
"Plugin Bundle"
|
|
418
|
+
]
|
|
419
|
+
}
|
|
420
|
+
)
|
|
265
421
|
] })
|
|
266
422
|
] }),
|
|
267
|
-
/* @__PURE__ */ jsxs("aside", { className: "
|
|
423
|
+
/* @__PURE__ */ jsxs("aside", { className: "min-w-55 max-w-65 shrink-0", children: [
|
|
268
424
|
/* @__PURE__ */ jsx(EndpointPanel, { label: "Base endpoint", path: "/api" }),
|
|
269
425
|
/* @__PURE__ */ jsx(EndpointPanel, { label: "Package endpoint", path: "/api/package" }),
|
|
270
|
-
/* @__PURE__ */ jsxs("p", { className: "
|
|
426
|
+
/* @__PURE__ */ jsxs("p", { className: "mt-2 text-xs leading-relaxed text-muted-foreground", children: [
|
|
271
427
|
"Use ",
|
|
272
|
-
/* @__PURE__ */ jsx("strong", { children: "POST /api/tools/<collection>" }),
|
|
428
|
+
/* @__PURE__ */ jsx("strong", { className: "text-foreground", children: "POST /api/tools/<collection>" }),
|
|
273
429
|
" or",
|
|
274
430
|
" ",
|
|
275
|
-
/* @__PURE__ */ jsx("strong", { children: "POST /api/skills/<collection>" }),
|
|
431
|
+
/* @__PURE__ */ jsx("strong", { className: "text-foreground", children: "POST /api/skills/<collection>" }),
|
|
276
432
|
" to call these from your apps or agents."
|
|
277
433
|
] }),
|
|
278
|
-
/* @__PURE__ */ jsxs("p", { className: "
|
|
434
|
+
/* @__PURE__ */ jsxs("p", { className: "mt-1 text-xs text-muted-foreground", children: [
|
|
279
435
|
"v",
|
|
280
436
|
version
|
|
281
437
|
] })
|
|
282
438
|
] })
|
|
439
|
+
] }) });
|
|
440
|
+
}
|
|
441
|
+
function ResourceCard({ resource }) {
|
|
442
|
+
return /* @__PURE__ */ jsx(Card, { className: "transition-all hover:-translate-y-0.5 hover:shadow-md", children: /* @__PURE__ */ jsxs(CardContent, { className: "p-5", children: [
|
|
443
|
+
/* @__PURE__ */ jsx("span", { className: `mb-2 inline-block rounded-full px-2 py-0.5 text-[0.7rem] font-semibold uppercase tracking-wide ${TYPE_VARIANTS[resource.type] ?? ""}`, children: resource.type }),
|
|
444
|
+
/* @__PURE__ */ jsx("div", { className: "font-semibold text-card-foreground", children: resource.title }),
|
|
445
|
+
/* @__PURE__ */ jsx("div", { className: "mt-1 text-sm text-muted-foreground", children: resource.description || "No description" }),
|
|
446
|
+
resource.tags && resource.tags.length > 0 && /* @__PURE__ */ jsx("div", { className: "mt-2 flex flex-wrap gap-1", children: resource.tags.map((tag) => /* @__PURE__ */ jsx(Badge, { variant: "default", children: tag }, tag)) }),
|
|
447
|
+
resource.url && /* @__PURE__ */ jsx("div", { className: "mt-2 truncate font-mono text-xs text-muted-foreground", children: resource.url })
|
|
448
|
+
] }) });
|
|
449
|
+
}
|
|
450
|
+
function ResourceSection({ title, subtitle, resources, showDivider }) {
|
|
451
|
+
if (resources.length === 0) return null;
|
|
452
|
+
return /* @__PURE__ */ jsxs("section", { children: [
|
|
453
|
+
showDivider && /* @__PURE__ */ jsx(Separator, { className: "my-8" }),
|
|
454
|
+
/* @__PURE__ */ jsxs("div", { children: [
|
|
455
|
+
/* @__PURE__ */ jsxs("h2", { className: "text-xl font-semibold text-foreground", children: [
|
|
456
|
+
title,
|
|
457
|
+
/* @__PURE__ */ jsxs("span", { className: "ml-2 text-sm font-normal text-muted-foreground", children: [
|
|
458
|
+
"(",
|
|
459
|
+
resources.length,
|
|
460
|
+
")"
|
|
461
|
+
] })
|
|
462
|
+
] }),
|
|
463
|
+
/* @__PURE__ */ jsx("p", { className: "mb-4 text-sm text-muted-foreground", children: subtitle })
|
|
464
|
+
] }),
|
|
465
|
+
/* @__PURE__ */ jsx("div", { className: "grid grid-cols-1 gap-6 sm:grid-cols-2 lg:grid-cols-3", children: resources.map((r) => /* @__PURE__ */ jsx(ResourceCard, { resource: r }, `${r.type}:${r.name}`)) })
|
|
283
466
|
] });
|
|
284
467
|
}
|
|
285
468
|
function SearchBar({ value, onChange, placeholder, resultCount, totalCount }) {
|
|
286
469
|
const hasQuery = value.trim().length > 0;
|
|
287
470
|
const noResults = hasQuery && resultCount === 0;
|
|
288
|
-
return /* @__PURE__ */ jsxs("div", { className: "
|
|
471
|
+
return /* @__PURE__ */ jsxs("div", { className: "mb-7", children: [
|
|
289
472
|
/* @__PURE__ */ jsx(
|
|
290
|
-
|
|
473
|
+
Input,
|
|
291
474
|
{
|
|
292
475
|
type: "search",
|
|
293
476
|
value,
|
|
294
|
-
onChange
|
|
477
|
+
onChange,
|
|
295
478
|
placeholder: placeholder || "Search collections...",
|
|
296
|
-
className: "
|
|
479
|
+
className: "max-w-sm rounded-full",
|
|
297
480
|
autoComplete: "off"
|
|
298
481
|
}
|
|
299
482
|
),
|
|
300
|
-
hasQuery && !noResults && /* @__PURE__ */ jsxs("p", { className: "
|
|
483
|
+
hasQuery && !noResults && /* @__PURE__ */ jsxs("p", { className: "mt-1.5 text-xs text-muted-foreground", children: [
|
|
301
484
|
"Showing ",
|
|
302
485
|
resultCount,
|
|
303
486
|
" of ",
|
|
304
487
|
totalCount,
|
|
305
488
|
" resources"
|
|
306
489
|
] }),
|
|
307
|
-
noResults && /* @__PURE__ */ jsx("p", { className: "
|
|
308
|
-
] });
|
|
309
|
-
}
|
|
310
|
-
function ResourceCard({ resource }) {
|
|
311
|
-
return /* @__PURE__ */ jsxs("div", { className: "vta-card", children: [
|
|
312
|
-
/* @__PURE__ */ jsx("span", { className: `vta-card-type vta-card-type--${resource.type}`, children: resource.type }),
|
|
313
|
-
/* @__PURE__ */ jsx("div", { className: "vta-card-title", children: resource.title }),
|
|
314
|
-
/* @__PURE__ */ jsx("div", { className: "vta-card-desc", children: resource.description || "No description" }),
|
|
315
|
-
resource.tags && resource.tags.length > 0 && /* @__PURE__ */ jsx("div", { className: "vta-card-tags", children: resource.tags.map((tag) => /* @__PURE__ */ jsx("span", { className: "vta-tag", children: tag }, tag)) }),
|
|
316
|
-
resource.url && /* @__PURE__ */ jsx("div", { className: "vta-card-url", children: resource.url })
|
|
317
|
-
] });
|
|
318
|
-
}
|
|
319
|
-
function ResourceSection({ title, subtitle, resources, showDivider }) {
|
|
320
|
-
if (resources.length === 0) return null;
|
|
321
|
-
return /* @__PURE__ */ jsxs("section", { children: [
|
|
322
|
-
showDivider && /* @__PURE__ */ jsx("hr", { className: "vta-divider" }),
|
|
323
|
-
/* @__PURE__ */ jsxs("div", { children: [
|
|
324
|
-
/* @__PURE__ */ jsxs("h2", { className: "vta-section-title", children: [
|
|
325
|
-
title,
|
|
326
|
-
/* @__PURE__ */ jsxs("span", { className: "vta-section-count", children: [
|
|
327
|
-
"(",
|
|
328
|
-
resources.length,
|
|
329
|
-
")"
|
|
330
|
-
] })
|
|
331
|
-
] }),
|
|
332
|
-
/* @__PURE__ */ jsx("p", { className: "vta-section-subtitle", children: subtitle })
|
|
333
|
-
] }),
|
|
334
|
-
/* @__PURE__ */ jsx("div", { className: "vta-card-grid", children: resources.map((r) => /* @__PURE__ */ jsx(ResourceCard, { resource: r }, `${r.type}:${r.name}`)) })
|
|
335
|
-
] });
|
|
336
|
-
}
|
|
337
|
-
function CollectionCard({ collection }) {
|
|
338
|
-
const href = `/${collection.type}s/${collection.name}`;
|
|
339
|
-
return /* @__PURE__ */ jsx(NavLink, { href, className: "vta-card-link", children: /* @__PURE__ */ jsxs("div", { className: "vta-card vta-card--link", children: [
|
|
340
|
-
/* @__PURE__ */ jsx("span", { className: `vta-card-type vta-card-type--${collection.type}`, children: collection.type }),
|
|
341
|
-
/* @__PURE__ */ jsx("div", { className: "vta-card-title", children: collection.title }),
|
|
342
|
-
/* @__PURE__ */ jsx("div", { className: "vta-card-desc", children: collection.description || "No description" }),
|
|
343
|
-
/* @__PURE__ */ jsxs("div", { className: "vta-card-url", children: [
|
|
344
|
-
collection.count,
|
|
345
|
-
" ",
|
|
346
|
-
collection.count === 1 ? "item" : "items"
|
|
347
|
-
] })
|
|
348
|
-
] }) });
|
|
349
|
-
}
|
|
350
|
-
function DetailPage({ type, title, description, tags, backHref = "/", children }) {
|
|
351
|
-
return /* @__PURE__ */ jsxs("div", { className: "vta-root", children: [
|
|
352
|
-
/* @__PURE__ */ jsxs("nav", { className: "vta-detail-nav", children: [
|
|
353
|
-
backHref !== "/" && /* @__PURE__ */ jsx(NavLink, { href: "/", className: "vta-detail-back", children: "Home" }),
|
|
354
|
-
/* @__PURE__ */ jsx(NavLink, { href: backHref, className: "vta-detail-back", children: "← Back" })
|
|
355
|
-
] }),
|
|
356
|
-
/* @__PURE__ */ jsxs("div", { className: "vta-detail-header", children: [
|
|
357
|
-
/* @__PURE__ */ jsx("span", { className: `vta-card-type vta-card-type--${type}`, children: type }),
|
|
358
|
-
/* @__PURE__ */ jsx("h1", { className: "vta-detail-title", children: title }),
|
|
359
|
-
description && /* @__PURE__ */ jsx("p", { className: "vta-detail-desc", children: description }),
|
|
360
|
-
tags && tags.length > 0 && /* @__PURE__ */ jsx("div", { className: "vta-card-tags", children: tags.map((tag) => /* @__PURE__ */ jsx("span", { className: "vta-tag", children: tag }, tag)) })
|
|
361
|
-
] }),
|
|
362
|
-
children
|
|
490
|
+
noResults && /* @__PURE__ */ jsx("p", { className: "mt-2 text-sm text-destructive", children: "No resources match this search." })
|
|
363
491
|
] });
|
|
364
492
|
}
|
|
365
493
|
const sections = [
|
|
366
494
|
{ type: "tool", title: "Tools", subtitle: "Remote tools available to agents via Vertesia." },
|
|
495
|
+
{ type: "activity", title: "Activities", subtitle: "Remote activities for DSL workflows, invoked via HTTP." },
|
|
367
496
|
{ type: "skill", title: "Skills", subtitle: "Reusable instructions and scripts packaged as tools." },
|
|
368
497
|
{ type: "interaction", title: "Interactions", subtitle: "Conversation blueprints surfaced in the Vertesia UI." },
|
|
369
498
|
{ type: "type", title: "Content Types", subtitle: "Schema definitions for structured content in the data store." },
|
|
@@ -378,7 +507,7 @@ function HomePage() {
|
|
|
378
507
|
[resources, search]
|
|
379
508
|
);
|
|
380
509
|
const isSearching = search.trim().length > 0;
|
|
381
|
-
return /* @__PURE__ */ jsxs("div", { className: "
|
|
510
|
+
return /* @__PURE__ */ jsxs("div", { className: "mx-auto max-w-5xl px-7 py-10", children: [
|
|
382
511
|
/* @__PURE__ */ jsx(
|
|
383
512
|
HeroSection,
|
|
384
513
|
{
|
|
@@ -397,95 +526,81 @@ function HomePage() {
|
|
|
397
526
|
totalCount: resources.length
|
|
398
527
|
}
|
|
399
528
|
),
|
|
400
|
-
isSearching ? (
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
/*
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
"(",
|
|
428
|
-
sectionCollections.length,
|
|
429
|
-
sectionCollections.length === 1 ? " collection" : " collections",
|
|
430
|
-
")"
|
|
431
|
-
] })
|
|
432
|
-
] }),
|
|
433
|
-
/* @__PURE__ */ jsx("p", { className: "vta-section-subtitle", children: section.subtitle })
|
|
529
|
+
isSearching ? sections.map((section, i) => {
|
|
530
|
+
const sectionItems = filtered.filter((r) => r.type === section.type);
|
|
531
|
+
return /* @__PURE__ */ jsx(
|
|
532
|
+
ResourceSection,
|
|
533
|
+
{
|
|
534
|
+
title: section.title,
|
|
535
|
+
subtitle: section.subtitle,
|
|
536
|
+
resources: sectionItems,
|
|
537
|
+
showDivider: i > 0
|
|
538
|
+
},
|
|
539
|
+
section.type
|
|
540
|
+
);
|
|
541
|
+
}) : sections.map((section, i) => {
|
|
542
|
+
const sectionCollections = collections.filter((c) => c.type === section.type);
|
|
543
|
+
const mcpResources = section.type === "mcp" ? resources.filter((r) => r.type === "mcp") : [];
|
|
544
|
+
if (sectionCollections.length === 0 && mcpResources.length === 0) return null;
|
|
545
|
+
return /* @__PURE__ */ jsxs("section", { children: [
|
|
546
|
+
i > 0 && /* @__PURE__ */ jsx(Separator, { className: "my-8" }),
|
|
547
|
+
/* @__PURE__ */ jsxs("div", { children: [
|
|
548
|
+
/* @__PURE__ */ jsxs("h2", { className: "text-xl font-semibold text-foreground", children: [
|
|
549
|
+
section.title,
|
|
550
|
+
/* @__PURE__ */ jsxs("span", { className: "ml-2 text-sm font-normal text-muted-foreground", children: [
|
|
551
|
+
"(",
|
|
552
|
+
sectionCollections.length,
|
|
553
|
+
sectionCollections.length === 1 ? " collection" : " collections",
|
|
554
|
+
")"
|
|
555
|
+
] })
|
|
434
556
|
] }),
|
|
435
|
-
/* @__PURE__ */
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
557
|
+
/* @__PURE__ */ jsx("p", { className: "mb-4 text-sm text-muted-foreground", children: section.subtitle })
|
|
558
|
+
] }),
|
|
559
|
+
/* @__PURE__ */ jsxs("div", { className: "grid grid-cols-1 gap-6 sm:grid-cols-2 lg:grid-cols-3", children: [
|
|
560
|
+
sectionCollections.map((col) => /* @__PURE__ */ jsx(CollectionCard, { collection: col }, `${col.type}:${col.name}`)),
|
|
561
|
+
mcpResources.map((r) => /* @__PURE__ */ jsxs("div", { className: "rounded-xl border border-border bg-card p-5 shadow-sm", children: [
|
|
562
|
+
/* @__PURE__ */ jsx("span", { className: `mb-2 inline-block rounded-full px-2 py-0.5 text-[0.7rem] font-semibold uppercase tracking-wide ${TYPE_VARIANTS.mcp}`, children: "mcp" }),
|
|
563
|
+
/* @__PURE__ */ jsx("div", { className: "font-semibold text-card-foreground", children: r.title }),
|
|
564
|
+
/* @__PURE__ */ jsx("div", { className: "mt-1 text-sm text-muted-foreground", children: r.description || "No description" }),
|
|
565
|
+
r.url && /* @__PURE__ */ jsx("div", { className: "mt-2 truncate font-mono text-xs text-muted-foreground", children: r.url })
|
|
566
|
+
] }, r.name))
|
|
567
|
+
] })
|
|
568
|
+
] }, section.type);
|
|
569
|
+
})
|
|
447
570
|
] });
|
|
448
571
|
}
|
|
449
572
|
function InteractionCollection() {
|
|
450
573
|
const collection = useParams("collection");
|
|
451
574
|
const { baseUrl } = useAdminContext();
|
|
452
|
-
const { data: interactions,
|
|
575
|
+
const { data: interactions, error } = useFetch(
|
|
453
576
|
() => fetch(`${baseUrl}/interactions/${collection}`).then((r) => {
|
|
454
577
|
if (!r.ok) throw new Error(`Failed to load collection: ${r.statusText}`);
|
|
455
578
|
return r.json();
|
|
456
579
|
}),
|
|
457
580
|
[baseUrl, collection]
|
|
458
581
|
);
|
|
459
|
-
if (
|
|
460
|
-
return /* @__PURE__ */
|
|
461
|
-
}
|
|
462
|
-
if (error || !interactions) {
|
|
463
|
-
return /* @__PURE__ */ jsxs("div", { className: "vta-error", children: [
|
|
582
|
+
if (error) {
|
|
583
|
+
return /* @__PURE__ */ jsxs("div", { className: "p-6 text-destructive", children: [
|
|
464
584
|
"Failed to load collection “",
|
|
465
585
|
collection,
|
|
466
586
|
"”."
|
|
467
587
|
] });
|
|
468
588
|
}
|
|
589
|
+
if (!interactions) {
|
|
590
|
+
return /* @__PURE__ */ jsx("div", { className: "flex h-64 items-center justify-center text-muted-foreground", children: /* @__PURE__ */ jsx(Spinner, {}) });
|
|
591
|
+
}
|
|
469
592
|
return /* @__PURE__ */ jsx(
|
|
470
593
|
DetailPage,
|
|
471
594
|
{
|
|
472
595
|
type: "interaction",
|
|
473
596
|
title: collection,
|
|
474
597
|
description: `${interactions.length} interaction${interactions.length !== 1 ? "s" : ""} in this collection.`,
|
|
475
|
-
children: /* @__PURE__ */ jsx("div", { className: "
|
|
476
|
-
|
|
477
|
-
{
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
/* @__PURE__ */ jsx("span", { className: "vta-card-type vta-card-type--interaction", children: "interaction" }),
|
|
482
|
-
/* @__PURE__ */ jsx("div", { className: "vta-card-title", children: inter.title || inter.name }),
|
|
483
|
-
/* @__PURE__ */ jsx("div", { className: "vta-card-desc", children: inter.description || "No description" }),
|
|
484
|
-
inter.tags && inter.tags.length > 0 && /* @__PURE__ */ jsx("div", { className: "vta-card-tags", children: inter.tags.map((tag) => /* @__PURE__ */ jsx("span", { className: "vta-tag", children: tag }, tag)) })
|
|
485
|
-
] })
|
|
486
|
-
},
|
|
487
|
-
inter.id
|
|
488
|
-
)) })
|
|
598
|
+
children: /* @__PURE__ */ jsx("div", { className: "grid grid-cols-1 gap-6 sm:grid-cols-2 lg:grid-cols-3", children: interactions.map((inter) => /* @__PURE__ */ jsx(NavLink, { href: `/interactions/${collection}/${inter.name}`, className: "block no-underline", children: /* @__PURE__ */ jsx(Card, { className: "cursor-pointer transition-all hover:-translate-y-0.5 hover:shadow-md", children: /* @__PURE__ */ jsxs(CardContent, { className: "p-5", children: [
|
|
599
|
+
/* @__PURE__ */ jsx("span", { className: `mb-2 inline-block rounded-full px-2 py-0.5 text-[0.7rem] font-semibold uppercase tracking-wide ${TYPE_VARIANTS.interaction}`, children: "interaction" }),
|
|
600
|
+
/* @__PURE__ */ jsx("div", { className: "font-semibold text-card-foreground", children: inter.title || inter.name }),
|
|
601
|
+
/* @__PURE__ */ jsx("div", { className: "mt-1 text-sm text-muted-foreground", children: inter.description || "No description" }),
|
|
602
|
+
inter.tags && inter.tags.length > 0 && /* @__PURE__ */ jsx("div", { className: "mt-2 flex flex-wrap gap-1", children: inter.tags.map((tag) => /* @__PURE__ */ jsx(Badge, { children: tag }, tag)) })
|
|
603
|
+
] }) }) }, inter.id)) })
|
|
489
604
|
}
|
|
490
605
|
);
|
|
491
606
|
}
|
|
@@ -495,7 +610,7 @@ function InteractionDetail() {
|
|
|
495
610
|
const collection = params.collection;
|
|
496
611
|
const name = params.name;
|
|
497
612
|
const { baseUrl } = useAdminContext();
|
|
498
|
-
const { data: interaction,
|
|
613
|
+
const { data: interaction, error } = useFetch(
|
|
499
614
|
() => client.getRawJWT().then((token) => fetch(`${baseUrl}/interactions/${collection}/${name}`, {
|
|
500
615
|
headers: {
|
|
501
616
|
Authorization: `Bearer ${token}`
|
|
@@ -506,16 +621,16 @@ function InteractionDetail() {
|
|
|
506
621
|
}),
|
|
507
622
|
[baseUrl, collection, name]
|
|
508
623
|
);
|
|
509
|
-
if (
|
|
510
|
-
return /* @__PURE__ */
|
|
511
|
-
}
|
|
512
|
-
if (error || !interaction) {
|
|
513
|
-
return /* @__PURE__ */ jsxs("div", { className: "vta-error", children: [
|
|
624
|
+
if (error) {
|
|
625
|
+
return /* @__PURE__ */ jsxs("div", { className: "p-6 text-destructive", children: [
|
|
514
626
|
"Failed to load interaction “",
|
|
515
627
|
name,
|
|
516
628
|
"”."
|
|
517
629
|
] });
|
|
518
630
|
}
|
|
631
|
+
if (!interaction) {
|
|
632
|
+
return /* @__PURE__ */ jsx("div", { className: "flex h-64 items-center justify-center text-muted-foreground", children: /* @__PURE__ */ jsx(Spinner, {}) });
|
|
633
|
+
}
|
|
519
634
|
const { agent_runner_options } = interaction;
|
|
520
635
|
const hasAgentFlags = agent_runner_options && (agent_runner_options.is_agent || agent_runner_options.is_tool || agent_runner_options.is_skill);
|
|
521
636
|
return /* @__PURE__ */ jsxs(
|
|
@@ -527,72 +642,39 @@ function InteractionDetail() {
|
|
|
527
642
|
tags: interaction.tags,
|
|
528
643
|
backHref: `/interactions/${collection}`,
|
|
529
644
|
children: [
|
|
530
|
-
interaction.prompts && interaction.prompts.length > 0 && /* @__PURE__ */ jsxs("div", { className: "
|
|
531
|
-
/* @__PURE__ */ jsx("h2", { children: "Prompts" }),
|
|
532
|
-
interaction.prompts.map((prompt
|
|
533
|
-
/* @__PURE__ */ jsxs("div", { className: "
|
|
534
|
-
/* @__PURE__ */ jsx("span", { className: `
|
|
535
|
-
prompt.name && /* @__PURE__ */ jsx("span", { className: "
|
|
645
|
+
interaction.prompts && interaction.prompts.length > 0 && /* @__PURE__ */ jsxs("div", { className: "mb-8", children: [
|
|
646
|
+
/* @__PURE__ */ jsx("h2", { className: "mb-3 text-lg font-semibold text-foreground", children: "Prompts" }),
|
|
647
|
+
interaction.prompts.map((prompt) => /* @__PURE__ */ jsx(Card, { className: "mb-3", children: /* @__PURE__ */ jsxs(CardContent, { className: "p-4", children: [
|
|
648
|
+
/* @__PURE__ */ jsxs("div", { className: "mb-2 flex items-center gap-2", children: [
|
|
649
|
+
/* @__PURE__ */ jsx("span", { className: `rounded-full px-2 py-0.5 text-[0.7rem] font-semibold uppercase tracking-wide ${ROLE_VARIANTS[prompt.role] ?? ""}`, children: prompt.role }),
|
|
650
|
+
prompt.name && /* @__PURE__ */ jsx("span", { className: "text-sm italic text-muted-foreground", children: prompt.name })
|
|
536
651
|
] }),
|
|
537
|
-
/* @__PURE__ */ jsx("pre", { className: "
|
|
538
|
-
] },
|
|
652
|
+
/* @__PURE__ */ jsx("pre", { className: "whitespace-pre-wrap wrap-break-word rounded-lg border border-border bg-muted-background p-4 font-mono text-sm text-foreground", children: prompt.content })
|
|
653
|
+
] }) }, `${prompt.role}-${prompt.name ?? ""}`))
|
|
539
654
|
] }),
|
|
540
|
-
interaction.result_schema && /* @__PURE__ */ jsxs("div", { className: "
|
|
541
|
-
/* @__PURE__ */ jsx("h2", { children: "Result Schema" }),
|
|
542
|
-
/* @__PURE__ */ jsx("pre", { className: "
|
|
655
|
+
interaction.result_schema && /* @__PURE__ */ jsxs("div", { className: "mb-8", children: [
|
|
656
|
+
/* @__PURE__ */ jsx("h2", { className: "mb-3 text-lg font-semibold text-foreground", children: "Result Schema" }),
|
|
657
|
+
/* @__PURE__ */ jsx("pre", { className: "whitespace-pre-wrap wrap-break-word rounded-lg border border-border bg-muted-background p-4 font-mono text-sm text-foreground", children: JSON.stringify(interaction.result_schema, null, 2) })
|
|
543
658
|
] }),
|
|
544
|
-
hasAgentFlags && /* @__PURE__ */ jsxs("div", { className: "
|
|
545
|
-
/* @__PURE__ */ jsx("h2", { children: "Agent Runner" }),
|
|
546
|
-
/* @__PURE__ */ jsxs("div", { className: "
|
|
547
|
-
agent_runner_options.is_agent && /* @__PURE__ */ jsx(
|
|
548
|
-
agent_runner_options.is_tool && /* @__PURE__ */ jsx(
|
|
549
|
-
agent_runner_options.is_skill && /* @__PURE__ */ jsx(
|
|
659
|
+
hasAgentFlags && /* @__PURE__ */ jsxs("div", { className: "mb-8", children: [
|
|
660
|
+
/* @__PURE__ */ jsx("h2", { className: "mb-3 text-lg font-semibold text-foreground", children: "Agent Runner" }),
|
|
661
|
+
/* @__PURE__ */ jsxs("div", { className: "flex flex-wrap gap-2", children: [
|
|
662
|
+
agent_runner_options.is_agent && /* @__PURE__ */ jsx(Badge, { variant: "success", children: "Agent" }),
|
|
663
|
+
agent_runner_options.is_tool && /* @__PURE__ */ jsx(Badge, { variant: "success", children: "Tool" }),
|
|
664
|
+
agent_runner_options.is_skill && /* @__PURE__ */ jsx(Badge, { variant: "success", children: "Skill" })
|
|
550
665
|
] })
|
|
551
666
|
] })
|
|
552
667
|
]
|
|
553
668
|
}
|
|
554
669
|
);
|
|
555
670
|
}
|
|
556
|
-
function ToolCollection() {
|
|
557
|
-
const collection = useParams("collection");
|
|
558
|
-
const { baseUrl } = useAdminContext();
|
|
559
|
-
const { data, isLoading, error } = useFetch(
|
|
560
|
-
() => fetch(`${baseUrl}/tools/${collection}`).then((r) => {
|
|
561
|
-
if (!r.ok) throw new Error(`Failed to load collection: ${r.statusText}`);
|
|
562
|
-
return r.json();
|
|
563
|
-
}),
|
|
564
|
-
[baseUrl, collection]
|
|
565
|
-
);
|
|
566
|
-
if (isLoading) return /* @__PURE__ */ jsx("div", { className: "vta-loading", children: "Loading collection..." });
|
|
567
|
-
if (error || !data) return /* @__PURE__ */ jsxs("div", { className: "vta-error", children: [
|
|
568
|
-
"Failed to load tool collection “",
|
|
569
|
-
collection,
|
|
570
|
-
"”."
|
|
571
|
-
] });
|
|
572
|
-
return /* @__PURE__ */ jsx(
|
|
573
|
-
DetailPage,
|
|
574
|
-
{
|
|
575
|
-
type: "tool",
|
|
576
|
-
title: data.title || collection,
|
|
577
|
-
description: data.description || `${data.tools.length} tool${data.tools.length !== 1 ? "s" : ""} in this collection.`,
|
|
578
|
-
children: data.tools.map((tool) => /* @__PURE__ */ jsxs("div", { className: "vta-detail-card", children: [
|
|
579
|
-
/* @__PURE__ */ jsxs("div", { className: "vta-detail-card-header", children: [
|
|
580
|
-
/* @__PURE__ */ jsx("span", { className: "vta-card-type vta-card-type--tool", children: "tool" }),
|
|
581
|
-
/* @__PURE__ */ jsx("div", { className: "vta-card-title", children: tool.name })
|
|
582
|
-
] }),
|
|
583
|
-
/* @__PURE__ */ jsx("div", { className: "vta-card-desc", children: tool.description || "No description" }),
|
|
584
|
-
tool.input_schema && /* @__PURE__ */ jsx("pre", { className: "vta-detail-code", children: JSON.stringify(tool.input_schema, null, 2) })
|
|
585
|
-
] }, tool.name))
|
|
586
|
-
}
|
|
587
|
-
);
|
|
588
|
-
}
|
|
589
671
|
function skillDisplayName(name) {
|
|
590
672
|
return name.startsWith("learn_") ? name.slice(6) : name;
|
|
591
673
|
}
|
|
592
674
|
function SkillCollection() {
|
|
593
675
|
const collection = useParams("collection");
|
|
594
676
|
const { baseUrl } = useAdminContext();
|
|
595
|
-
const { data,
|
|
677
|
+
const { data, error } = useFetch(
|
|
596
678
|
() => fetch(`${baseUrl}/skills/${collection}`).then((r) => {
|
|
597
679
|
if (!r.ok) throw new Error(`Failed to load collection: ${r.statusText}`);
|
|
598
680
|
return r.json();
|
|
@@ -607,12 +689,12 @@ function SkillCollection() {
|
|
|
607
689
|
if (!widgetsData?.widgets) return [];
|
|
608
690
|
return Object.entries(widgetsData.widgets).filter(([_, w]) => w.collection === collection).map(([name, w]) => ({ name, ...w }));
|
|
609
691
|
}, [widgetsData, collection]);
|
|
610
|
-
if (
|
|
611
|
-
if (error || !data) return /* @__PURE__ */ jsxs("div", { className: "vta-error", children: [
|
|
692
|
+
if (error) return /* @__PURE__ */ jsxs("div", { className: "p-6 text-destructive", children: [
|
|
612
693
|
"Failed to load skill collection “",
|
|
613
694
|
collection,
|
|
614
695
|
"”."
|
|
615
696
|
] });
|
|
697
|
+
if (!data) return /* @__PURE__ */ jsx("div", { className: "flex h-64 items-center justify-center text-muted-foreground", children: /* @__PURE__ */ jsx(Spinner, {}) });
|
|
616
698
|
return /* @__PURE__ */ jsxs(
|
|
617
699
|
DetailPage,
|
|
618
700
|
{
|
|
@@ -620,33 +702,25 @@ function SkillCollection() {
|
|
|
620
702
|
title: data.title || collection,
|
|
621
703
|
description: data.description || `${data.tools.length} skill${data.tools.length !== 1 ? "s" : ""} in this collection.`,
|
|
622
704
|
children: [
|
|
623
|
-
collectionWidgets.length > 0 && /* @__PURE__ */ jsxs("div", { className: "
|
|
624
|
-
/* @__PURE__ */ jsx("h2", { children: "Widgets" }),
|
|
625
|
-
/* @__PURE__ */ jsx("div", { className: "
|
|
705
|
+
collectionWidgets.length > 0 && /* @__PURE__ */ jsxs("div", { className: "mb-8", children: [
|
|
706
|
+
/* @__PURE__ */ jsx("h2", { className: "mb-3 text-lg font-semibold text-foreground", children: "Widgets" }),
|
|
707
|
+
/* @__PURE__ */ jsx("div", { className: "flex flex-wrap gap-2", children: collectionWidgets.map((w) => /* @__PURE__ */ jsxs(Badge, { variant: "success", children: [
|
|
626
708
|
w.name,
|
|
627
|
-
/* @__PURE__ */ jsxs("span", { className: "
|
|
709
|
+
/* @__PURE__ */ jsxs("span", { className: "ml-2 font-mono text-xs opacity-70", children: [
|
|
628
710
|
"(skill: ",
|
|
629
711
|
w.skill,
|
|
630
712
|
")"
|
|
631
713
|
] })
|
|
632
714
|
] }, w.name)) })
|
|
633
715
|
] }),
|
|
634
|
-
/* @__PURE__ */ jsx("div", { className: "
|
|
716
|
+
/* @__PURE__ */ jsx("div", { className: "grid grid-cols-1 gap-6 sm:grid-cols-2 lg:grid-cols-3", children: data.tools.map((skill) => {
|
|
635
717
|
const displayName = skillDisplayName(skill.name);
|
|
636
|
-
return /* @__PURE__ */ jsx(
|
|
637
|
-
|
|
638
|
-
{
|
|
639
|
-
|
|
640
|
-
|
|
641
|
-
|
|
642
|
-
/* @__PURE__ */ jsx("span", { className: "vta-card-type vta-card-type--skill", children: "skill" }),
|
|
643
|
-
/* @__PURE__ */ jsx("div", { className: "vta-card-title", children: displayName }),
|
|
644
|
-
/* @__PURE__ */ jsx("div", { className: "vta-card-desc", children: skill.description || "No description" }),
|
|
645
|
-
skill.related_tools && skill.related_tools.length > 0 && /* @__PURE__ */ jsx("div", { className: "vta-card-tags", children: skill.related_tools.map((t) => /* @__PURE__ */ jsx("span", { className: "vta-tag", children: t }, t)) })
|
|
646
|
-
] })
|
|
647
|
-
},
|
|
648
|
-
skill.name
|
|
649
|
-
);
|
|
718
|
+
return /* @__PURE__ */ jsx(NavLink, { href: `/skills/${collection}/${displayName}`, className: "block no-underline", children: /* @__PURE__ */ jsx(Card, { className: "cursor-pointer transition-all hover:-translate-y-0.5 hover:shadow-md", children: /* @__PURE__ */ jsxs(CardContent, { className: "p-5", children: [
|
|
719
|
+
/* @__PURE__ */ jsx("span", { className: `mb-2 inline-block rounded-full px-2 py-0.5 text-[0.7rem] font-semibold uppercase tracking-wide ${TYPE_VARIANTS.skill}`, children: "skill" }),
|
|
720
|
+
/* @__PURE__ */ jsx("div", { className: "font-semibold text-card-foreground", children: displayName }),
|
|
721
|
+
/* @__PURE__ */ jsx("div", { className: "mt-1 text-sm text-muted-foreground", children: skill.description || "No description" }),
|
|
722
|
+
skill.related_tools && skill.related_tools.length > 0 && /* @__PURE__ */ jsx("div", { className: "mt-2 flex flex-wrap gap-1", children: skill.related_tools.map((t) => /* @__PURE__ */ jsx(Badge, { children: t }, t)) })
|
|
723
|
+
] }) }) }, skill.name);
|
|
650
724
|
}) })
|
|
651
725
|
]
|
|
652
726
|
}
|
|
@@ -657,19 +731,19 @@ function SkillDetail() {
|
|
|
657
731
|
const collection = params.collection;
|
|
658
732
|
const name = params.name;
|
|
659
733
|
const { baseUrl } = useAdminContext();
|
|
660
|
-
const { data: skill,
|
|
734
|
+
const { data: skill, error } = useFetch(
|
|
661
735
|
() => fetch(`${baseUrl}/skills/${collection}/${name}`).then((r) => {
|
|
662
736
|
if (!r.ok) throw new Error(`Failed to load skill: ${r.statusText}`);
|
|
663
737
|
return r.json();
|
|
664
738
|
}),
|
|
665
739
|
[baseUrl, collection, name]
|
|
666
740
|
);
|
|
667
|
-
if (
|
|
668
|
-
if (error || !skill) return /* @__PURE__ */ jsxs("div", { className: "vta-error", children: [
|
|
741
|
+
if (error) return /* @__PURE__ */ jsxs("div", { className: "p-6 text-destructive", children: [
|
|
669
742
|
"Failed to load skill “",
|
|
670
743
|
name,
|
|
671
744
|
"”."
|
|
672
745
|
] });
|
|
746
|
+
if (!skill) return /* @__PURE__ */ jsx("div", { className: "flex h-64 items-center justify-center text-muted-foreground", children: /* @__PURE__ */ jsx(Spinner, {}) });
|
|
673
747
|
return /* @__PURE__ */ jsxs(
|
|
674
748
|
DetailPage,
|
|
675
749
|
{
|
|
@@ -678,215 +752,248 @@ function SkillDetail() {
|
|
|
678
752
|
description: skill.description,
|
|
679
753
|
backHref: `/skills/${collection}`,
|
|
680
754
|
children: [
|
|
681
|
-
skill.widgets && skill.widgets.length > 0 && /* @__PURE__ */ jsxs("div", { className: "
|
|
682
|
-
/* @__PURE__ */ jsx("h2", { children: "Widgets" }),
|
|
683
|
-
/* @__PURE__ */ jsx("div", { className: "
|
|
755
|
+
skill.widgets && skill.widgets.length > 0 && /* @__PURE__ */ jsxs("div", { className: "mb-8", children: [
|
|
756
|
+
/* @__PURE__ */ jsx("h2", { className: "mb-3 text-lg font-semibold text-foreground", children: "Widgets" }),
|
|
757
|
+
/* @__PURE__ */ jsx("div", { className: "flex flex-wrap gap-2", children: skill.widgets.map((w) => /* @__PURE__ */ jsx(Badge, { variant: "success", children: w }, w)) })
|
|
684
758
|
] }),
|
|
685
|
-
skill.scripts && skill.scripts.length > 0 && /* @__PURE__ */ jsxs("div", { className: "
|
|
686
|
-
/* @__PURE__ */ jsx("h2", { children: "Scripts" }),
|
|
687
|
-
/* @__PURE__ */ jsx("div", { className: "
|
|
759
|
+
skill.scripts && skill.scripts.length > 0 && /* @__PURE__ */ jsxs("div", { className: "mb-8", children: [
|
|
760
|
+
/* @__PURE__ */ jsx("h2", { className: "mb-3 text-lg font-semibold text-foreground", children: "Scripts" }),
|
|
761
|
+
/* @__PURE__ */ jsx("div", { className: "flex flex-wrap gap-2", children: skill.scripts.map((s) => /* @__PURE__ */ jsx(Badge, { variant: "success", children: s }, s)) })
|
|
688
762
|
] }),
|
|
689
|
-
skill.related_tools && skill.related_tools.length > 0 && /* @__PURE__ */ jsxs("div", { className: "
|
|
690
|
-
/* @__PURE__ */ jsx("h2", { children: "Related Tools" }),
|
|
691
|
-
/* @__PURE__ */ jsx("div", { className: "
|
|
763
|
+
skill.related_tools && skill.related_tools.length > 0 && /* @__PURE__ */ jsxs("div", { className: "mb-8", children: [
|
|
764
|
+
/* @__PURE__ */ jsx("h2", { className: "mb-3 text-lg font-semibold text-foreground", children: "Related Tools" }),
|
|
765
|
+
/* @__PURE__ */ jsx("div", { className: "flex flex-wrap gap-2", children: skill.related_tools.map((t) => /* @__PURE__ */ jsx(Badge, { variant: "success", children: t }, t)) })
|
|
692
766
|
] }),
|
|
693
|
-
skill.execution && /* @__PURE__ */ jsxs("div", { className: "
|
|
694
|
-
/* @__PURE__ */ jsx("h2", { children: "Execution" }),
|
|
695
|
-
/* @__PURE__ */ jsxs("div", { className: "
|
|
696
|
-
/* @__PURE__ */ jsx(
|
|
697
|
-
skill.execution.packages?.map((p) => /* @__PURE__ */ jsx(
|
|
767
|
+
skill.execution && /* @__PURE__ */ jsxs("div", { className: "mb-8", children: [
|
|
768
|
+
/* @__PURE__ */ jsx("h2", { className: "mb-3 text-lg font-semibold text-foreground", children: "Execution" }),
|
|
769
|
+
/* @__PURE__ */ jsxs("div", { className: "flex flex-wrap gap-2", children: [
|
|
770
|
+
/* @__PURE__ */ jsx(Badge, { variant: "success", children: skill.execution.language }),
|
|
771
|
+
skill.execution.packages?.map((p) => /* @__PURE__ */ jsx(Badge, { variant: "success", children: p }, p))
|
|
698
772
|
] })
|
|
699
773
|
] }),
|
|
700
|
-
/* @__PURE__ */ jsxs("div", { className: "
|
|
701
|
-
/* @__PURE__ */ jsxs("h2", { children: [
|
|
702
|
-
"Instructions
|
|
703
|
-
skill.content_type === "jst" && /* @__PURE__ */ jsx(
|
|
774
|
+
/* @__PURE__ */ jsxs("div", { className: "mb-8", children: [
|
|
775
|
+
/* @__PURE__ */ jsxs("h2", { className: "mb-3 text-lg font-semibold text-foreground", children: [
|
|
776
|
+
"Instructions",
|
|
777
|
+
skill.content_type === "jst" && /* @__PURE__ */ jsx(Badge, { className: "ml-2", children: "JST template" })
|
|
704
778
|
] }),
|
|
705
|
-
/* @__PURE__ */ jsx("pre", { className: "
|
|
779
|
+
/* @__PURE__ */ jsx("pre", { className: "whitespace-pre-wrap wrap-break-word rounded-lg border border-border bg-muted-background p-4 font-mono text-sm text-foreground", children: skill.instructions })
|
|
706
780
|
] }),
|
|
707
|
-
skill.input_schema && /* @__PURE__ */ jsxs("div", { className: "
|
|
708
|
-
/* @__PURE__ */ jsx("h2", { children: "Input Schema" }),
|
|
709
|
-
/* @__PURE__ */ jsx("pre", { className: "
|
|
781
|
+
skill.input_schema && /* @__PURE__ */ jsxs("div", { className: "mb-8", children: [
|
|
782
|
+
/* @__PURE__ */ jsx("h2", { className: "mb-3 text-lg font-semibold text-foreground", children: "Input Schema" }),
|
|
783
|
+
/* @__PURE__ */ jsx("pre", { className: "whitespace-pre-wrap wrap-break-word rounded-lg border border-border bg-muted-background p-4 font-mono text-sm text-foreground", children: JSON.stringify(skill.input_schema, null, 2) })
|
|
710
784
|
] })
|
|
711
785
|
]
|
|
712
786
|
}
|
|
713
787
|
);
|
|
714
788
|
}
|
|
715
|
-
function
|
|
789
|
+
function TemplateCollection() {
|
|
716
790
|
const collection = useParams("collection");
|
|
717
791
|
const { baseUrl } = useAdminContext();
|
|
718
|
-
const { data:
|
|
719
|
-
() => fetch(`${baseUrl}/
|
|
792
|
+
const { data: templates, error } = useFetch(
|
|
793
|
+
() => fetch(`${baseUrl}/templates/${collection}`).then((r) => {
|
|
720
794
|
if (!r.ok) throw new Error(`Failed to load collection: ${r.statusText}`);
|
|
721
795
|
return r.json();
|
|
722
796
|
}),
|
|
723
797
|
[baseUrl, collection]
|
|
724
798
|
);
|
|
725
|
-
if (
|
|
726
|
-
|
|
727
|
-
"Failed to load type collection “",
|
|
799
|
+
if (error) return /* @__PURE__ */ jsxs("div", { className: "p-6 text-destructive", children: [
|
|
800
|
+
"Failed to load template collection “",
|
|
728
801
|
collection,
|
|
729
802
|
"”."
|
|
730
803
|
] });
|
|
804
|
+
if (!templates) return /* @__PURE__ */ jsx("div", { className: "flex h-64 items-center justify-center text-muted-foreground", children: /* @__PURE__ */ jsx(Spinner, {}) });
|
|
731
805
|
return /* @__PURE__ */ jsx(
|
|
732
806
|
DetailPage,
|
|
733
807
|
{
|
|
734
|
-
type: "
|
|
808
|
+
type: "template",
|
|
735
809
|
title: collection,
|
|
736
|
-
description: `${
|
|
737
|
-
children: /* @__PURE__ */ jsx("div", { className: "
|
|
738
|
-
|
|
739
|
-
|
|
740
|
-
|
|
741
|
-
|
|
742
|
-
|
|
743
|
-
className:
|
|
744
|
-
|
|
745
|
-
|
|
746
|
-
|
|
747
|
-
|
|
748
|
-
|
|
749
|
-
|
|
750
|
-
|
|
751
|
-
t.is_chunkable && t.strict_mode && " · ",
|
|
752
|
-
t.strict_mode && "strict"
|
|
753
|
-
] })
|
|
754
|
-
] })
|
|
755
|
-
},
|
|
756
|
-
t.name
|
|
757
|
-
);
|
|
758
|
-
}) })
|
|
810
|
+
description: `${templates.length} template${templates.length !== 1 ? "s" : ""} in this collection.`,
|
|
811
|
+
children: /* @__PURE__ */ jsx("div", { className: "grid grid-cols-1 gap-6 sm:grid-cols-2 lg:grid-cols-3", children: templates.map((tmpl) => /* @__PURE__ */ jsx(
|
|
812
|
+
NavLink,
|
|
813
|
+
{
|
|
814
|
+
href: `/templates/${collection}/${tmpl.name}`,
|
|
815
|
+
className: "no-underline",
|
|
816
|
+
children: /* @__PURE__ */ jsx(Card, { className: "h-full transition-all hover:-translate-y-0.5 hover:shadow-md", children: /* @__PURE__ */ jsxs(CardContent, { className: "p-5", children: [
|
|
817
|
+
/* @__PURE__ */ jsx("span", { className: `mb-2 inline-block rounded-full px-2 py-0.5 text-[0.7rem] font-semibold uppercase tracking-wide ${TYPE_VARIANTS.template}`, children: tmpl.type || "template" }),
|
|
818
|
+
/* @__PURE__ */ jsx("div", { className: "font-semibold text-card-foreground", children: tmpl.title || tmpl.name }),
|
|
819
|
+
/* @__PURE__ */ jsx("div", { className: "mt-1 text-sm text-muted-foreground", children: tmpl.description || "No description" }),
|
|
820
|
+
tmpl.tags && tmpl.tags.length > 0 && /* @__PURE__ */ jsx("div", { className: "mt-3 flex flex-wrap gap-1.5", children: tmpl.tags.map((tag) => /* @__PURE__ */ jsx(Badge, { variant: "default", children: tag }, tag)) })
|
|
821
|
+
] }) })
|
|
822
|
+
},
|
|
823
|
+
tmpl.name
|
|
824
|
+
)) })
|
|
759
825
|
}
|
|
760
826
|
);
|
|
761
827
|
}
|
|
762
|
-
function
|
|
828
|
+
function TemplateDetail() {
|
|
763
829
|
const params = useParams();
|
|
764
830
|
const collection = params.collection;
|
|
765
831
|
const name = params.name;
|
|
766
832
|
const { baseUrl } = useAdminContext();
|
|
767
|
-
const { data:
|
|
768
|
-
() => fetch(`${baseUrl}/
|
|
769
|
-
if (!r.ok) throw new Error(`Failed to load
|
|
833
|
+
const { data: template, error } = useFetch(
|
|
834
|
+
() => fetch(`${baseUrl}/templates/${collection}/${name}`).then((r) => {
|
|
835
|
+
if (!r.ok) throw new Error(`Failed to load template: ${r.statusText}`);
|
|
770
836
|
return r.json();
|
|
771
837
|
}),
|
|
772
838
|
[baseUrl, collection, name]
|
|
773
839
|
);
|
|
774
|
-
if (
|
|
775
|
-
|
|
776
|
-
"Failed to load type “",
|
|
840
|
+
if (error) return /* @__PURE__ */ jsxs("div", { className: "p-6 text-destructive", children: [
|
|
841
|
+
"Failed to load template “",
|
|
777
842
|
name,
|
|
778
843
|
"”."
|
|
779
844
|
] });
|
|
845
|
+
if (!template) return /* @__PURE__ */ jsx("div", { className: "flex h-64 items-center justify-center text-muted-foreground", children: /* @__PURE__ */ jsx(Spinner, {}) });
|
|
780
846
|
return /* @__PURE__ */ jsxs(
|
|
781
847
|
DetailPage,
|
|
782
848
|
{
|
|
783
|
-
type: "
|
|
784
|
-
title:
|
|
785
|
-
description:
|
|
786
|
-
tags:
|
|
787
|
-
backHref: `/
|
|
849
|
+
type: "template",
|
|
850
|
+
title: template.title || template.name,
|
|
851
|
+
description: template.description,
|
|
852
|
+
tags: template.tags,
|
|
853
|
+
backHref: `/templates/${collection}`,
|
|
788
854
|
children: [
|
|
789
|
-
|
|
790
|
-
|
|
791
|
-
|
|
792
|
-
|
|
793
|
-
typeDef.object_schema && /* @__PURE__ */ jsxs("div", { className: "vta-detail-section", children: [
|
|
794
|
-
/* @__PURE__ */ jsx("h2", { children: "Object Schema" }),
|
|
795
|
-
/* @__PURE__ */ jsx("pre", { className: "vta-detail-code", children: JSON.stringify(typeDef.object_schema, null, 2) })
|
|
855
|
+
/* @__PURE__ */ jsx("div", { className: "mb-8", children: /* @__PURE__ */ jsx("div", { className: "flex flex-wrap gap-2", children: /* @__PURE__ */ jsx(Badge, { variant: "success", children: template.type }) }) }),
|
|
856
|
+
template.assets && template.assets.length > 0 && /* @__PURE__ */ jsxs("div", { className: "mb-8", children: [
|
|
857
|
+
/* @__PURE__ */ jsx("h2", { className: "mb-3 text-lg font-semibold text-foreground", children: "Assets" }),
|
|
858
|
+
/* @__PURE__ */ jsx("div", { className: "flex flex-wrap gap-2", children: template.assets.map((asset) => /* @__PURE__ */ jsx(Badge, { variant: "success", children: asset.split("/").pop() }, asset)) })
|
|
796
859
|
] }),
|
|
797
|
-
|
|
798
|
-
/* @__PURE__ */ jsx("h2", {
|
|
799
|
-
/* @__PURE__ */ jsx("pre", { className: "
|
|
860
|
+
/* @__PURE__ */ jsxs("div", { className: "mb-8", children: [
|
|
861
|
+
/* @__PURE__ */ jsx("h2", { className: "mb-3 text-lg font-semibold text-foreground", children: "Instructions" }),
|
|
862
|
+
/* @__PURE__ */ jsx("pre", { className: "whitespace-pre-wrap wrap-break-word rounded-lg border border-border bg-muted-background p-4 font-mono text-sm text-foreground", children: template.instructions })
|
|
800
863
|
] })
|
|
801
864
|
]
|
|
802
865
|
}
|
|
803
866
|
);
|
|
804
867
|
}
|
|
805
|
-
function
|
|
868
|
+
function ToolCollection() {
|
|
806
869
|
const collection = useParams("collection");
|
|
807
870
|
const { baseUrl } = useAdminContext();
|
|
808
|
-
const { data
|
|
809
|
-
() => fetch(`${baseUrl}/
|
|
871
|
+
const { data, error } = useFetch(
|
|
872
|
+
() => fetch(`${baseUrl}/tools/${collection}`).then((r) => {
|
|
810
873
|
if (!r.ok) throw new Error(`Failed to load collection: ${r.statusText}`);
|
|
811
874
|
return r.json();
|
|
812
875
|
}),
|
|
813
876
|
[baseUrl, collection]
|
|
814
877
|
);
|
|
815
|
-
if (
|
|
816
|
-
|
|
817
|
-
"Failed to load template collection “",
|
|
878
|
+
if (error) return /* @__PURE__ */ jsxs("div", { className: "p-6 text-destructive", children: [
|
|
879
|
+
"Failed to load tool collection “",
|
|
818
880
|
collection,
|
|
819
881
|
"”."
|
|
820
882
|
] });
|
|
883
|
+
if (!data) return /* @__PURE__ */ jsx("div", { className: "flex h-64 items-center justify-center text-muted-foreground", children: /* @__PURE__ */ jsx(Spinner, {}) });
|
|
821
884
|
return /* @__PURE__ */ jsx(
|
|
822
885
|
DetailPage,
|
|
823
886
|
{
|
|
824
|
-
type: "
|
|
887
|
+
type: "tool",
|
|
888
|
+
title: data.title || collection,
|
|
889
|
+
description: data.description || `${data.tools.length} tool${data.tools.length !== 1 ? "s" : ""} in this collection.`,
|
|
890
|
+
children: data.tools.map((tool) => /* @__PURE__ */ jsx(Card, { className: "mb-4", children: /* @__PURE__ */ jsxs(CardContent, { className: "p-5", children: [
|
|
891
|
+
/* @__PURE__ */ jsxs("div", { className: "mb-2 flex items-center gap-2", children: [
|
|
892
|
+
/* @__PURE__ */ jsx("span", { className: `inline-block rounded-full px-2 py-0.5 text-[0.7rem] font-semibold uppercase tracking-wide ${TYPE_VARIANTS.tool}`, children: "tool" }),
|
|
893
|
+
/* @__PURE__ */ jsx("span", { className: "font-semibold text-card-foreground", children: tool.name })
|
|
894
|
+
] }),
|
|
895
|
+
/* @__PURE__ */ jsx("div", { className: "text-sm text-muted-foreground", children: tool.description || "No description" }),
|
|
896
|
+
tool.input_schema && /* @__PURE__ */ jsx("pre", { className: "mt-3 whitespace-pre-wrap wrap-break-word rounded-lg border border-border bg-muted-background p-4 font-mono text-sm text-foreground", children: JSON.stringify(tool.input_schema, null, 2) })
|
|
897
|
+
] }) }, tool.name))
|
|
898
|
+
}
|
|
899
|
+
);
|
|
900
|
+
}
|
|
901
|
+
function TypeCollection() {
|
|
902
|
+
const collection = useParams("collection");
|
|
903
|
+
const { baseUrl } = useAdminContext();
|
|
904
|
+
const { data: types, error } = useFetch(
|
|
905
|
+
() => fetch(`${baseUrl}/types/${collection}`).then((r) => {
|
|
906
|
+
if (!r.ok) throw new Error(`Failed to load collection: ${r.statusText}`);
|
|
907
|
+
return r.json();
|
|
908
|
+
}),
|
|
909
|
+
[baseUrl, collection]
|
|
910
|
+
);
|
|
911
|
+
if (error) return /* @__PURE__ */ jsxs("div", { className: "p-6 text-destructive", children: [
|
|
912
|
+
"Failed to load type collection “",
|
|
913
|
+
collection,
|
|
914
|
+
"”."
|
|
915
|
+
] });
|
|
916
|
+
if (!types) return /* @__PURE__ */ jsx("div", { className: "flex h-64 items-center justify-center text-muted-foreground", children: /* @__PURE__ */ jsx(Spinner, {}) });
|
|
917
|
+
return /* @__PURE__ */ jsx(
|
|
918
|
+
DetailPage,
|
|
919
|
+
{
|
|
920
|
+
type: "type",
|
|
825
921
|
title: collection,
|
|
826
|
-
description: `${
|
|
827
|
-
children: /* @__PURE__ */ jsx("div", { className: "
|
|
828
|
-
|
|
829
|
-
|
|
830
|
-
|
|
831
|
-
|
|
832
|
-
|
|
833
|
-
|
|
834
|
-
/* @__PURE__ */ jsx(
|
|
835
|
-
|
|
836
|
-
|
|
837
|
-
|
|
838
|
-
|
|
839
|
-
|
|
840
|
-
|
|
922
|
+
description: `${types.length} content type${types.length !== 1 ? "s" : ""} in this collection.`,
|
|
923
|
+
children: /* @__PURE__ */ jsx("div", { className: "grid grid-cols-1 gap-6 sm:grid-cols-2 lg:grid-cols-3", children: types.map((t) => {
|
|
924
|
+
const typeName = t.id?.split(":")[1] || t.name;
|
|
925
|
+
return /* @__PURE__ */ jsx(
|
|
926
|
+
NavLink,
|
|
927
|
+
{
|
|
928
|
+
href: `/types/${collection}/${typeName}`,
|
|
929
|
+
className: "no-underline",
|
|
930
|
+
children: /* @__PURE__ */ jsx(Card, { className: "h-full transition-all hover:-translate-y-0.5 hover:shadow-md", children: /* @__PURE__ */ jsxs(CardContent, { className: "p-5", children: [
|
|
931
|
+
/* @__PURE__ */ jsx("span", { className: `mb-2 inline-block rounded-full px-2 py-0.5 text-[0.7rem] font-semibold uppercase tracking-wide ${TYPE_VARIANTS.type}`, children: "type" }),
|
|
932
|
+
/* @__PURE__ */ jsx("div", { className: "font-semibold text-card-foreground", children: t.name }),
|
|
933
|
+
/* @__PURE__ */ jsx("div", { className: "mt-1 text-sm text-muted-foreground", children: t.description || "No description" }),
|
|
934
|
+
t.tags && t.tags.length > 0 && /* @__PURE__ */ jsx("div", { className: "mt-3 flex flex-wrap gap-1.5", children: t.tags.map((tag) => /* @__PURE__ */ jsx(Badge, { variant: "default", children: tag }, tag)) }),
|
|
935
|
+
(t.is_chunkable || t.strict_mode) && /* @__PURE__ */ jsxs("div", { className: "mt-2 truncate font-mono text-xs text-muted-foreground", children: [
|
|
936
|
+
t.is_chunkable && "chunkable",
|
|
937
|
+
t.is_chunkable && t.strict_mode && " · ",
|
|
938
|
+
t.strict_mode && "strict"
|
|
939
|
+
] })
|
|
940
|
+
] }) })
|
|
941
|
+
},
|
|
942
|
+
t.name
|
|
943
|
+
);
|
|
944
|
+
}) })
|
|
841
945
|
}
|
|
842
946
|
);
|
|
843
947
|
}
|
|
844
|
-
function
|
|
948
|
+
function TypeDetail() {
|
|
845
949
|
const params = useParams();
|
|
846
950
|
const collection = params.collection;
|
|
847
951
|
const name = params.name;
|
|
848
952
|
const { baseUrl } = useAdminContext();
|
|
849
|
-
const { data:
|
|
850
|
-
() => fetch(`${baseUrl}/
|
|
851
|
-
if (!r.ok) throw new Error(`Failed to load
|
|
953
|
+
const { data: typeDef, error } = useFetch(
|
|
954
|
+
() => fetch(`${baseUrl}/types/${collection}/${name}`).then((r) => {
|
|
955
|
+
if (!r.ok) throw new Error(`Failed to load type: ${r.statusText}`);
|
|
852
956
|
return r.json();
|
|
853
957
|
}),
|
|
854
958
|
[baseUrl, collection, name]
|
|
855
959
|
);
|
|
856
|
-
if (
|
|
857
|
-
|
|
858
|
-
"Failed to load template “",
|
|
960
|
+
if (error) return /* @__PURE__ */ jsxs("div", { className: "p-6 text-destructive", children: [
|
|
961
|
+
"Failed to load type “",
|
|
859
962
|
name,
|
|
860
963
|
"”."
|
|
861
964
|
] });
|
|
965
|
+
if (!typeDef) return /* @__PURE__ */ jsx("div", { className: "flex h-64 items-center justify-center text-muted-foreground", children: /* @__PURE__ */ jsx(Spinner, {}) });
|
|
862
966
|
return /* @__PURE__ */ jsxs(
|
|
863
967
|
DetailPage,
|
|
864
968
|
{
|
|
865
|
-
type: "
|
|
866
|
-
title:
|
|
867
|
-
description:
|
|
868
|
-
tags:
|
|
869
|
-
backHref: `/
|
|
969
|
+
type: "type",
|
|
970
|
+
title: typeDef.name,
|
|
971
|
+
description: typeDef.description,
|
|
972
|
+
tags: typeDef.tags,
|
|
973
|
+
backHref: `/types/${collection}`,
|
|
870
974
|
children: [
|
|
871
|
-
|
|
872
|
-
|
|
873
|
-
/* @__PURE__ */ jsx("
|
|
874
|
-
|
|
975
|
+
(typeDef.is_chunkable || typeDef.strict_mode) && /* @__PURE__ */ jsx("div", { className: "mb-8", children: /* @__PURE__ */ jsxs("div", { className: "flex flex-wrap gap-2", children: [
|
|
976
|
+
typeDef.is_chunkable && /* @__PURE__ */ jsx(Badge, { variant: "success", children: "Chunkable" }),
|
|
977
|
+
typeDef.strict_mode && /* @__PURE__ */ jsx(Badge, { variant: "success", children: "Strict Mode" })
|
|
978
|
+
] }) }),
|
|
979
|
+
typeDef.object_schema && /* @__PURE__ */ jsxs("div", { className: "mb-8", children: [
|
|
980
|
+
/* @__PURE__ */ jsx("h2", { className: "mb-3 text-lg font-semibold text-foreground", children: "Object Schema" }),
|
|
981
|
+
/* @__PURE__ */ jsx("pre", { className: "whitespace-pre-wrap wrap-break-word rounded-lg border border-border bg-muted-background p-4 font-mono text-sm text-foreground", children: JSON.stringify(typeDef.object_schema, null, 2) })
|
|
875
982
|
] }),
|
|
876
|
-
/* @__PURE__ */ jsxs("div", { className: "
|
|
877
|
-
/* @__PURE__ */ jsx("h2", { children: "
|
|
878
|
-
/* @__PURE__ */ jsx("pre", { className: "
|
|
983
|
+
typeDef.table_layout && typeDef.table_layout.length > 0 && /* @__PURE__ */ jsxs("div", { className: "mb-8", children: [
|
|
984
|
+
/* @__PURE__ */ jsx("h2", { className: "mb-3 text-lg font-semibold text-foreground", children: "Table Layout" }),
|
|
985
|
+
/* @__PURE__ */ jsx("pre", { className: "whitespace-pre-wrap wrap-break-word rounded-lg border border-border bg-muted-background p-4 font-mono text-sm text-foreground", children: JSON.stringify(typeDef.table_layout, null, 2) })
|
|
879
986
|
] })
|
|
880
987
|
]
|
|
881
988
|
}
|
|
882
989
|
);
|
|
883
990
|
}
|
|
884
|
-
const adminStyles = "/**\n * Self-contained styles for the admin panel.\n * All classes are prefixed with `vta-` (Vertesia Tools Admin) to avoid\n * polluting the plugin app CSS or the host page.\n */\n\n/* ── Root container ─────────────────────────────────────────────── */\n\n.vta-root {\n max-width: 1120px;\n margin: 0 auto;\n padding: 2.5rem 1.75rem;\n font-family: system-ui, -apple-system, sans-serif;\n color: #0f172a;\n line-height: 1.5;\n}\n\n/* ── Hero header ────────────────────────────────────────────────── */\n\n.vta-hero {\n display: flex;\n justify-content: space-between;\n align-items: flex-start;\n gap: 2.25rem;\n padding: 1.75rem 2rem;\n margin-bottom: 2.5rem;\n border-radius: 1.25rem;\n background: linear-gradient(135deg, #ffffff, #f3f4ff);\n border: 1px solid #e5e7eb;\n box-shadow:\n 0 18px 40px rgba(15, 23, 42, 0.08),\n 0 0 0 1px rgba(248, 250, 252, 0.8);\n}\n\n.vta-hero-main {\n flex: 1;\n display: flex;\n flex-direction: column;\n gap: 0.75rem;\n}\n\n.vta-hero-identity {\n display: flex;\n align-items: center;\n gap: 1rem;\n}\n\n.vta-hero-logo {\n display: flex;\n align-items: center;\n justify-content: center;\n width: 56px;\n height: 56px;\n border-radius: 14px;\n background: radial-gradient(circle at 30% 0, #38bdf8, #6366f1);\n box-shadow:\n 0 0 0 1px rgba(15, 23, 42, 0.85),\n 0 12px 30px rgba(37, 99, 235, 0.6);\n font-size: 1.1rem;\n font-weight: 650;\n letter-spacing: 0.08em;\n text-transform: uppercase;\n color: #eff6ff;\n}\n\n.vta-hero-eyebrow {\n font-size: 0.75rem;\n letter-spacing: 0.12em;\n text-transform: uppercase;\n color: #6b7280;\n margin: 0;\n}\n\n.vta-hero-title {\n font-size: 1.9rem;\n font-weight: 650;\n letter-spacing: -0.03em;\n color: #0f172a;\n margin: 0;\n}\n\n.vta-hero-tagline {\n font-size: 0.95rem;\n color: #4b5563;\n margin: 0;\n}\n\n.vta-hero-summary {\n display: flex;\n flex-wrap: wrap;\n gap: 0.5rem;\n font-size: 0.8rem;\n color: #6b7280;\n}\n\n.vta-badge {\n display: inline-flex;\n align-items: center;\n gap: 0.35rem;\n padding: 0.15rem 0.55rem;\n border-radius: 999px;\n background: #f9fafb;\n border: 1px solid #e5e7eb;\n}\n\n.vta-badge-dot {\n width: 6px;\n height: 6px;\n border-radius: 999px;\n display: inline-block;\n background: #22c55e;\n}\n\n.vta-hero-links {\n display: flex;\n gap: 0.75rem;\n flex-wrap: wrap;\n margin-top: 0.25rem;\n}\n\n.vta-link-primary,\n.vta-link-secondary {\n display: inline-flex;\n align-items: center;\n gap: 0.5rem;\n padding: 0.5rem 1rem;\n border-radius: 6px;\n font-size: 0.875rem;\n font-weight: 500;\n text-decoration: none;\n color: white;\n transition: opacity 0.15s;\n}\n\n.vta-link-primary { background: #3b82f6; }\n.vta-link-secondary { background: #10b981; }\n.vta-link-primary:hover { opacity: 0.88; }\n.vta-link-secondary:hover { opacity: 0.88; }\n\n/* ── Hero aside panel ───────────────────────────────────────────── */\n\n.vta-hero-panel {\n min-width: 220px;\n max-width: 260px;\n flex-shrink: 0;\n}\n\n.vta-endpoint {\n margin-bottom: 0.75rem;\n}\n\n.vta-endpoint-label {\n font-size: 0.7rem;\n letter-spacing: 0.13em;\n text-transform: uppercase;\n color: #1d4ed8;\n margin-bottom: 0.35rem;\n}\n\n.vta-endpoint-box {\n display: flex;\n align-items: center;\n gap: 0.5rem;\n background: #f3f4f6;\n padding: 0.5rem 0.75rem;\n border-radius: 0.5rem;\n border: 1px solid #e5e7eb;\n}\n\n.vta-endpoint-code {\n flex: 1;\n font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, monospace;\n font-size: 0.82rem;\n color: #111827;\n}\n\n.vta-copy-btn {\n background: #e5e7eb;\n border: none;\n padding: 0.35rem;\n border-radius: 4px;\n cursor: pointer;\n color: #6b7280;\n font-size: 0.8rem;\n line-height: 1;\n transition: all 0.15s;\n}\n\n.vta-copy-btn:hover {\n background: #d1d5db;\n color: #374151;\n}\n\n.vta-hero-hint {\n margin-top: 0.6rem;\n font-size: 0.8rem;\n color: #6b7280;\n line-height: 1.4;\n}\n\n.vta-hero-hint strong {\n color: #111827;\n}\n\n.vta-hero-version {\n font-size: 0.75rem;\n color: #9ca3af;\n margin-top: 0.25rem;\n}\n\n/* ── Search bar ─────────────────────────────────────────────────── */\n\n.vta-search {\n margin-bottom: 1.75rem;\n}\n\n.vta-search-input {\n width: 100%;\n max-width: 360px;\n padding: 0.55rem 0.75rem;\n border-radius: 999px;\n border: 1px solid #e5e7eb;\n background: #ffffff;\n color: #111827;\n font-size: 0.9rem;\n font-family: inherit;\n box-shadow: 0 4px 10px rgba(15, 23, 42, 0.04);\n box-sizing: border-box;\n}\n\n.vta-search-input::placeholder { color: #9ca3af; }\n\n.vta-search-input:focus {\n outline: none;\n border-color: #60a5fa;\n box-shadow:\n 0 0 0 1px rgba(59, 130, 246, 0.4),\n 0 6px 18px rgba(37, 99, 235, 0.18);\n}\n\n.vta-search-hint {\n font-size: 0.75rem;\n color: #9ca3af;\n margin-top: 0.4rem;\n}\n\n.vta-search-empty {\n font-size: 0.85rem;\n color: #ef4444;\n margin-top: 0.5rem;\n}\n\n/* ── Section ────────────────────────────────────────────────────── */\n\n.vta-divider {\n border: none;\n border-top: 1px solid #e5e7eb;\n margin: 2rem 0;\n}\n\n.vta-section-title {\n font-size: 1.4rem;\n font-weight: 600;\n letter-spacing: 0.03em;\n color: #0f172a;\n margin: 0 0 0.25rem 0;\n}\n\n.vta-section-count {\n font-size: 0.85rem;\n font-weight: 400;\n color: #9ca3af;\n margin-left: 0.5rem;\n}\n\n.vta-section-subtitle {\n font-size: 0.8rem;\n color: #6b7280;\n margin: 0 0 1rem 0;\n}\n\n/* ── Resource card grid ─────────────────────────────────────────── */\n\n.vta-card-grid {\n display: grid;\n grid-template-columns: repeat(auto-fill, minmax(280px, 1fr));\n gap: 1.5rem;\n}\n\n.vta-card {\n background: radial-gradient(circle at 0 0, rgba(56, 189, 248, 0.12), transparent 75%),\n #ffffff;\n padding: 1.25rem 1.35rem;\n border-radius: 14px;\n box-shadow:\n 0 14px 30px rgba(15, 23, 42, 0.06),\n 0 0 0 1px rgba(248, 250, 252, 0.9);\n border: 1px solid #e5e7eb;\n transition: transform 0.15s, box-shadow 0.15s;\n}\n\n.vta-card:hover {\n transform: translateY(-3px);\n box-shadow:\n 0 18px 40px rgba(15, 23, 42, 0.10),\n 0 0 0 1px rgba(59, 130, 246, 0.6);\n}\n\n.vta-card-type {\n display: inline-block;\n font-size: 0.7rem;\n font-weight: 600;\n letter-spacing: 0.06em;\n text-transform: uppercase;\n padding: 0.15rem 0.55rem;\n border-radius: 999px;\n margin-bottom: 0.6rem;\n}\n\n/* Type-specific badge colours */\n.vta-card-type--tool { background: #dbeafe; color: #1e40af; }\n.vta-card-type--skill { background: #d1fae5; color: #065f46; }\n.vta-card-type--interaction { background: #fef3c7; color: #92400e; }\n.vta-card-type--type { background: #f3f4f6; color: #374151; }\n.vta-card-type--template { background: #ede9fe; color: #5b21b6; }\n.vta-card-type--mcp { background: #fce7f3; color: #9d174d; }\n\n.vta-card-title {\n font-weight: 600;\n font-size: 1.05rem;\n color: #0f172a;\n margin-bottom: 0.25rem;\n}\n\n.vta-card-desc {\n font-size: 0.875rem;\n color: #6b7280;\n margin-bottom: 0.5rem;\n}\n\n.vta-card-tags {\n display: flex;\n flex-wrap: wrap;\n gap: 0.35rem;\n margin-bottom: 0.4rem;\n}\n\n.vta-tag {\n font-size: 0.7rem;\n padding: 0.1rem 0.5rem;\n border-radius: 999px;\n background: #fef3c7;\n color: #92400e;\n}\n\n.vta-card-url {\n font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, monospace;\n font-size: 0.75rem;\n color: #9ca3af;\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n}\n\n/* ── Card link wrapper ─────────────────────────────────────────── */\n\n.vta-card-link {\n text-decoration: none;\n color: inherit;\n display: block;\n}\n\n.vta-card--link {\n cursor: pointer;\n}\n\n/* ── Detail page ───────────────────────────────────────────────── */\n\n.vta-detail-nav {\n display: flex;\n align-items: center;\n gap: 1rem;\n margin-bottom: 1.25rem;\n}\n\n.vta-detail-back {\n display: inline-flex;\n align-items: center;\n gap: 0.35rem;\n font-size: 0.875rem;\n color: #3b82f6;\n text-decoration: none;\n transition: opacity 0.15s;\n}\n\n.vta-detail-back:hover {\n opacity: 0.75;\n}\n\n.vta-detail-header {\n margin-bottom: 2rem;\n}\n\n.vta-detail-title {\n font-size: 1.75rem;\n font-weight: 650;\n letter-spacing: -0.02em;\n color: #0f172a;\n margin: 0.5rem 0 0.25rem;\n}\n\n.vta-detail-desc {\n font-size: 0.95rem;\n color: #4b5563;\n margin: 0 0 0.75rem;\n line-height: 1.6;\n}\n\n.vta-detail-section {\n margin-bottom: 2rem;\n}\n\n.vta-detail-section h2 {\n font-size: 1.15rem;\n font-weight: 600;\n color: #0f172a;\n margin: 0 0 0.75rem;\n}\n\n.vta-detail-card {\n background: #ffffff;\n border: 1px solid #e5e7eb;\n border-radius: 10px;\n padding: 1rem 1.25rem;\n margin-bottom: 0.75rem;\n}\n\n.vta-detail-card-header {\n display: flex;\n align-items: center;\n gap: 0.5rem;\n margin-bottom: 0.5rem;\n}\n\n.vta-detail-role {\n display: inline-block;\n font-size: 0.7rem;\n font-weight: 600;\n letter-spacing: 0.06em;\n text-transform: uppercase;\n padding: 0.15rem 0.55rem;\n border-radius: 999px;\n}\n\n.vta-detail-role--system { background: #dbeafe; color: #1e40af; }\n.vta-detail-role--user { background: #d1fae5; color: #065f46; }\n.vta-detail-role--assistant { background: #ede9fe; color: #5b21b6; }\n.vta-detail-role--safety { background: #fce7f3; color: #9d174d; }\n.vta-detail-role--tool { background: #fef3c7; color: #92400e; }\n\n.vta-detail-prompt-name {\n font-size: 0.8rem;\n color: #6b7280;\n font-style: italic;\n}\n\n.vta-detail-code {\n font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, monospace;\n font-size: 0.82rem;\n line-height: 1.6;\n background: #f9fafb;\n border: 1px solid #e5e7eb;\n border-radius: 8px;\n padding: 0.75rem 1rem;\n margin: 0;\n overflow-x: auto;\n white-space: pre-wrap;\n word-break: break-word;\n color: #111827;\n}\n\n.vta-detail-flags {\n display: flex;\n gap: 0.5rem;\n flex-wrap: wrap;\n}\n\n.vta-detail-flag {\n display: inline-flex;\n align-items: center;\n gap: 0.35rem;\n padding: 0.25rem 0.65rem;\n border-radius: 999px;\n font-size: 0.8rem;\n font-weight: 500;\n background: #d1fae5;\n color: #065f46;\n}\n\n/* ── Loading / error states ─────────────────────────────────────── */\n\n.vta-loading {\n display: flex;\n align-items: center;\n justify-content: center;\n height: 16rem;\n color: #9ca3af;\n font-size: 1rem;\n}\n\n.vta-error {\n padding: 1.5rem;\n color: #ef4444;\n font-size: 0.95rem;\n}\n\n/* ── Responsive ─────────────────────────────────────────────────── */\n\n@media (max-width: 768px) {\n .vta-root { padding: 1.75rem 1.25rem; }\n .vta-hero { flex-direction: column; padding: 1.5rem 1.35rem; }\n .vta-hero-panel { max-width: 100%; width: 100%; }\n}\n\n/* ── Dark mode ──────────────────────────────────────────────────── */\n\n@media (prefers-color-scheme: dark) {\n .vta-root { color: #e5e7eb; }\n\n .vta-hero {\n background: linear-gradient(135deg, rgba(15, 23, 42, 0.98), rgba(15, 23, 42, 0.92));\n border-color: rgba(148, 163, 184, 0.45);\n box-shadow:\n 0 24px 60px rgba(15, 23, 42, 0.85),\n 0 0 0 1px rgba(15, 23, 42, 0.75);\n }\n\n .vta-hero-eyebrow { color: #9ca3af; }\n .vta-hero-title { color: #f9fafb; }\n .vta-hero-tagline { color: #cbd5f5; }\n .vta-hero-summary { color: #9ca3af; }\n\n .vta-badge {\n background: rgba(15, 23, 42, 0.95);\n border-color: rgba(148, 163, 184, 0.45);\n }\n\n .vta-endpoint-label { color: #93c5fd; }\n\n .vta-endpoint-box {\n background: rgba(31, 41, 55, 0.95);\n border-color: rgba(148, 163, 184, 0.6);\n }\n\n .vta-endpoint-code { color: #e5e7eb; }\n\n .vta-copy-btn {\n background: rgba(55, 65, 81, 0.95);\n color: #e5e7eb;\n }\n .vta-copy-btn:hover {\n background: rgba(75, 85, 99, 0.98);\n color: #f9fafb;\n }\n\n .vta-hero-hint { color: #9ca3af; }\n .vta-hero-hint strong { color: #e5e7eb; }\n\n .vta-search-input {\n background: rgba(15, 23, 42, 0.96);\n border-color: rgba(55, 65, 81, 0.9);\n color: #e5e7eb;\n box-shadow:\n 0 6px 16px rgba(15, 23, 42, 0.9),\n 0 0 0 1px rgba(15, 23, 42, 0.9);\n }\n .vta-search-input::placeholder { color: #6b7280; }\n .vta-search-input:focus {\n border-color: #60a5fa;\n box-shadow:\n 0 0 0 1px rgba(59, 130, 246, 0.7),\n 0 10px 26px rgba(30, 64, 175, 0.7);\n }\n\n .vta-search-hint { color: #9ca3af; }\n .vta-divider { border-top-color: rgba(148, 163, 184, 0.4); }\n .vta-section-title { color: #e5e7eb; }\n\n .vta-card {\n background: radial-gradient(circle at 0 0, rgba(56, 189, 248, 0.12), transparent 75%),\n rgba(15, 23, 42, 0.9);\n box-shadow:\n 0 14px 30px rgba(15, 23, 42, 0.8),\n 0 0 0 1px rgba(15, 23, 42, 0.85);\n border-color: rgba(148, 163, 184, 0.5);\n }\n .vta-card:hover {\n box-shadow:\n 0 18px 40px rgba(15, 23, 42, 0.9),\n 0 0 0 1px rgba(59, 130, 246, 0.8);\n }\n\n .vta-card-title { color: #e5e7eb; }\n .vta-card-desc { color: #9ca3af; }\n .vta-card-url { color: #6b7280; }\n\n .vta-card-type--tool { background: rgba(59, 130, 246, 0.15); color: #93c5fd; }\n .vta-card-type--skill { background: rgba(16, 185, 129, 0.15); color: #6ee7b7; }\n .vta-card-type--interaction { background: rgba(245, 158, 11, 0.15); color: #fcd34d; }\n .vta-card-type--type { background: rgba(107, 114, 128, 0.2); color: #d1d5db; }\n .vta-card-type--template { background: rgba(139, 92, 246, 0.15); color: #c4b5fd; }\n .vta-card-type--mcp { background: rgba(236, 72, 153, 0.15); color: #f9a8d4; }\n\n .vta-tag {\n background: rgba(250, 204, 21, 0.12);\n color: #facc15;\n }\n\n /* Detail page dark mode */\n .vta-detail-back { color: #60a5fa; }\n\n .vta-detail-title { color: #f9fafb; }\n .vta-detail-desc { color: #cbd5e1; }\n\n .vta-detail-section h2 { color: #e5e7eb; }\n\n .vta-detail-card {\n background: rgba(15, 23, 42, 0.9);\n border-color: rgba(148, 163, 184, 0.5);\n }\n\n .vta-detail-role--system { background: rgba(59, 130, 246, 0.15); color: #93c5fd; }\n .vta-detail-role--user { background: rgba(16, 185, 129, 0.15); color: #6ee7b7; }\n .vta-detail-role--assistant { background: rgba(139, 92, 246, 0.15); color: #c4b5fd; }\n .vta-detail-role--safety { background: rgba(236, 72, 153, 0.15); color: #f9a8d4; }\n .vta-detail-role--tool { background: rgba(245, 158, 11, 0.15); color: #fcd34d; }\n\n .vta-detail-prompt-name { color: #9ca3af; }\n\n .vta-detail-code {\n background: rgba(15, 23, 42, 0.95);\n border-color: rgba(148, 163, 184, 0.4);\n color: #e5e7eb;\n }\n\n .vta-detail-flag {\n background: rgba(16, 185, 129, 0.15);\n color: #6ee7b7;\n }\n}\n";
|
|
885
991
|
const routes = [
|
|
886
992
|
{ path: "/", Component: HomePage },
|
|
887
993
|
{ path: "/interactions/:collection", Component: InteractionCollection },
|
|
888
994
|
{ path: "/interactions/:collection/:name", Component: InteractionDetail },
|
|
889
995
|
{ path: "/tools/:collection", Component: ToolCollection },
|
|
996
|
+
{ path: "/activities/:collection", Component: ActivityCollection },
|
|
890
997
|
{ path: "/skills/:collection", Component: SkillCollection },
|
|
891
998
|
{ path: "/skills/:collection/:name", Component: SkillDetail },
|
|
892
999
|
{ path: "/types/:collection", Component: TypeCollection },
|
|
@@ -903,20 +1010,15 @@ function AdminApp({ baseUrl = "/api" }) {
|
|
|
903
1010
|
const isLoading = loadingInfo || loadingData;
|
|
904
1011
|
const error = infoError || dataError;
|
|
905
1012
|
if (isLoading) {
|
|
906
|
-
return /* @__PURE__ */
|
|
907
|
-
/* @__PURE__ */ jsx("style", { children: adminStyles }),
|
|
908
|
-
/* @__PURE__ */ jsx("div", { className: "vta-loading", children: "Loading..." })
|
|
909
|
-
] });
|
|
1013
|
+
return /* @__PURE__ */ jsx("div", { className: "flex h-64 items-center justify-center text-muted-foreground", children: /* @__PURE__ */ jsx(Spinner, {}) });
|
|
910
1014
|
}
|
|
911
1015
|
if (error) {
|
|
912
|
-
return /* @__PURE__ */
|
|
913
|
-
/* @__PURE__ */ jsx("style", { children: adminStyles }),
|
|
914
|
-
/* @__PURE__ */ jsx("div", { className: "vta-error", children: "Failed to load server info. Is the API running?" })
|
|
915
|
-
] });
|
|
1016
|
+
return /* @__PURE__ */ jsx("div", { className: "p-6 text-destructive", children: "Failed to load server info. Is the API running?" });
|
|
916
1017
|
}
|
|
917
1018
|
if (!serverInfo || !resourceData) return null;
|
|
918
|
-
|
|
919
|
-
|
|
1019
|
+
const title = serverInfo.message.replace("Vertesia Tools API", "Tools Server");
|
|
1020
|
+
return /* @__PURE__ */ jsxs("div", { className: "min-h-screen bg-background text-foreground", children: [
|
|
1021
|
+
/* @__PURE__ */ jsx(AdminTopBar, { title }),
|
|
920
1022
|
/* @__PURE__ */ jsx(AdminContext.Provider, { value: {
|
|
921
1023
|
serverInfo,
|
|
922
1024
|
collections: resourceData.collections,
|