@vertesia/tools-admin-ui 1.2.0 → 1.4.0-dev.20260615.042549Z
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/LICENSE +198 -10
- package/lib/AdminApp.d.ts +1 -1
- package/lib/AdminApp.d.ts.map +1 -1
- package/lib/components/AdminTopBar.d.ts +1 -1
- package/lib/components/AdminTopBar.d.ts.map +1 -1
- package/lib/components/CollectionCard.d.ts +1 -1
- package/lib/components/CollectionCard.d.ts.map +1 -1
- package/lib/components/DetailPage.d.ts +1 -1
- package/lib/components/DetailPage.d.ts.map +1 -1
- package/lib/components/EndpointPanel.d.ts +1 -1
- package/lib/components/EndpointPanel.d.ts.map +1 -1
- package/lib/components/HeroSection.d.ts +1 -1
- package/lib/components/HeroSection.d.ts.map +1 -1
- package/lib/components/ResourceCard.d.ts +1 -1
- package/lib/components/ResourceCard.d.ts.map +1 -1
- package/lib/components/ResourceSection.d.ts +1 -1
- package/lib/components/ResourceSection.d.ts.map +1 -1
- package/lib/components/SearchBar.d.ts +1 -1
- package/lib/components/SearchBar.d.ts.map +1 -1
- package/lib/components/SummaryBadge.d.ts +1 -1
- package/lib/components/SummaryBadge.d.ts.map +1 -1
- package/lib/hooks.d.ts +2 -2
- package/lib/hooks.d.ts.map +1 -1
- package/lib/index.d.ts +4 -4
- package/lib/index.d.ts.map +1 -1
- package/lib/pages/ActivityCollection.d.ts +1 -1
- package/lib/pages/ActivityCollection.d.ts.map +1 -1
- package/lib/pages/HomePage.d.ts +1 -1
- package/lib/pages/HomePage.d.ts.map +1 -1
- package/lib/pages/InteractionCollection.d.ts +1 -1
- package/lib/pages/InteractionCollection.d.ts.map +1 -1
- package/lib/pages/InteractionDetail.d.ts +1 -1
- package/lib/pages/InteractionDetail.d.ts.map +1 -1
- package/lib/pages/SkillCollection.d.ts +1 -1
- package/lib/pages/SkillCollection.d.ts.map +1 -1
- package/lib/pages/SkillDetail.d.ts +1 -1
- package/lib/pages/SkillDetail.d.ts.map +1 -1
- package/lib/pages/TemplateCollection.d.ts +1 -1
- package/lib/pages/TemplateCollection.d.ts.map +1 -1
- package/lib/pages/TemplateDetail.d.ts +1 -1
- package/lib/pages/TemplateDetail.d.ts.map +1 -1
- package/lib/pages/ToolCollection.d.ts +1 -1
- package/lib/pages/ToolCollection.d.ts.map +1 -1
- package/lib/pages/TypeCollection.d.ts +1 -1
- package/lib/pages/TypeCollection.d.ts.map +1 -1
- package/lib/pages/TypeDetail.d.ts +1 -1
- package/lib/pages/TypeDetail.d.ts.map +1 -1
- package/lib/tools-admin-ui.js +1484 -969
- package/lib/tools-admin-ui.js.map +1 -1
- package/lib/types.d.ts.map +1 -1
- package/package.json +16 -14
- package/src/AdminApp.tsx +14 -15
- package/src/components/AdminTopBar.tsx +7 -7
- package/src/components/CollectionCard.tsx +3 -1
- package/src/components/DetailPage.tsx +10 -4
- package/src/components/EndpointPanel.tsx +2 -9
- package/src/components/HeroSection.tsx +12 -3
- package/src/components/ResourceCard.tsx +8 -6
- package/src/components/ResourceSection.tsx +1 -1
- package/src/components/SearchBar.tsx +1 -5
- package/src/components/SummaryBadge.tsx +2 -1
- package/src/dev/env.ts +8 -8
- package/src/dev/main.tsx +20 -15
- package/src/hooks.ts +19 -12
- package/src/index.ts +4 -4
- package/src/pages/ActivityCollection.tsx +30 -12
- package/src/pages/HomePage.tsx +65 -57
- package/src/pages/InteractionCollection.tsx +26 -11
- package/src/pages/InteractionDetail.tsx +28 -13
- package/src/pages/SkillCollection.tsx +38 -18
- package/src/pages/SkillDetail.tsx +37 -13
- package/src/pages/TemplateCollection.tsx +28 -17
- package/src/pages/TemplateDetail.tsx +13 -7
- package/src/pages/ToolCollection.tsx +21 -10
- package/src/pages/TypeCollection.tsx +26 -17
- package/src/pages/TypeDetail.tsx +12 -6
- package/src/types.ts +16 -35
package/lib/tools-admin-ui.js
CHANGED
|
@@ -1,1037 +1,1552 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
4
|
-
import { createContext, useContext, useState, useMemo } from "react";
|
|
1
|
+
import { Avatar, Badge, Button, Card, CardContent, DotBadge, Input, ModeToggle, Separator, Spinner, useFetch } from "@vertesia/ui/core";
|
|
2
|
+
import { NavLink, NestedRouterProvider, RouteComponent, useParams } from "@vertesia/ui/router";
|
|
3
|
+
import { createContext, useContext, useMemo, useState } from "react";
|
|
5
4
|
import { useUserSession } from "@vertesia/ui/session";
|
|
6
|
-
import {
|
|
7
|
-
|
|
5
|
+
import { ArrowLeft, Check, Copy, Download, LayoutDashboard, LogOut } from "lucide-react";
|
|
6
|
+
import { Fragment, jsx, jsxs } from "react/jsx-runtime";
|
|
7
|
+
//#region src/AdminContext.ts
|
|
8
|
+
var AdminContext = createContext(void 0);
|
|
8
9
|
function useAdminContext() {
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
10
|
+
const ctx = useContext(AdminContext);
|
|
11
|
+
if (!ctx) throw new Error("useAdminContext must be used within AdminApp");
|
|
12
|
+
return ctx;
|
|
12
13
|
}
|
|
14
|
+
//#endregion
|
|
15
|
+
//#region src/components/AdminTopBar.tsx
|
|
13
16
|
function AdminTopBar({ title }) {
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
17
|
+
const { user, logout } = useUserSession();
|
|
18
|
+
return /* @__PURE__ */ jsxs("header", {
|
|
19
|
+
className: "sticky top-0 z-40 flex h-14 items-center justify-between border-b border-border bg-background px-6",
|
|
20
|
+
children: [/* @__PURE__ */ jsxs("div", {
|
|
21
|
+
className: "flex items-center gap-3",
|
|
22
|
+
children: [/* @__PURE__ */ jsx("div", {
|
|
23
|
+
className: "flex size-8 items-center justify-center rounded-lg bg-primary text-xs font-semibold uppercase tracking-wider text-primary-foreground",
|
|
24
|
+
children: title.split(/\s+/).map((w) => w[0]).filter(Boolean).slice(0, 2).join("")
|
|
25
|
+
}), /* @__PURE__ */ jsx("span", {
|
|
26
|
+
className: "text-sm font-semibold text-foreground",
|
|
27
|
+
children: title
|
|
28
|
+
})]
|
|
29
|
+
}), /* @__PURE__ */ jsxs("div", {
|
|
30
|
+
className: "flex items-center gap-3",
|
|
31
|
+
children: [/* @__PURE__ */ jsx(ModeToggle, { label: false }), user && /* @__PURE__ */ jsxs(Fragment, { children: [/* @__PURE__ */ jsx(Avatar, {
|
|
32
|
+
size: "sm",
|
|
33
|
+
name: user.name,
|
|
34
|
+
color: "bg-primary"
|
|
35
|
+
}), /* @__PURE__ */ jsx(Button, {
|
|
36
|
+
variant: "outline",
|
|
37
|
+
size: "sm",
|
|
38
|
+
onClick: () => logout(),
|
|
39
|
+
alt: "Sign out",
|
|
40
|
+
children: /* @__PURE__ */ jsx(LogOut, { className: "size-4" })
|
|
41
|
+
})] })]
|
|
42
|
+
})]
|
|
43
|
+
});
|
|
37
44
|
}
|
|
45
|
+
//#endregion
|
|
46
|
+
//#region src/types.ts
|
|
47
|
+
/**
|
|
48
|
+
* Formats a kebab/snake-case name into a title.
|
|
49
|
+
*/
|
|
38
50
|
function formatTitle(name) {
|
|
39
|
-
|
|
51
|
+
return name.replace(/[-_]/g, " ").replace(/\b\w/g, (c) => c.toUpperCase());
|
|
40
52
|
}
|
|
53
|
+
/**
|
|
54
|
+
* Counts items per collection by matching each item to a collection name.
|
|
55
|
+
* If there is only one collection, all items belong to it.
|
|
56
|
+
*/
|
|
41
57
|
function countPerCollection(items, collections, extractCollection) {
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
}
|
|
54
|
-
return counts;
|
|
58
|
+
const counts = /* @__PURE__ */ new Map();
|
|
59
|
+
for (const col of collections) counts.set(col.name, 0);
|
|
60
|
+
if (collections.length === 1) {
|
|
61
|
+
counts.set(collections[0].name, items.length);
|
|
62
|
+
return counts;
|
|
63
|
+
}
|
|
64
|
+
for (const item of items) {
|
|
65
|
+
const colName = extractCollection(item);
|
|
66
|
+
if (colName && counts.has(colName)) counts.set(colName, (counts.get(colName) || 0) + 1);
|
|
67
|
+
}
|
|
68
|
+
return counts;
|
|
55
69
|
}
|
|
70
|
+
/**
|
|
71
|
+
* Builds collections and a flat resource list from the 5 endpoint responses + MCP endpoints.
|
|
72
|
+
*/
|
|
56
73
|
function buildResourceData(interactionsResp, toolsResp, skillsResp, activitiesResp, typesResp, templatesResp, mcpEndpoints) {
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
name: t.name,
|
|
169
|
-
title: formatTitle(t.name),
|
|
170
|
-
description: t.description || "",
|
|
171
|
-
type: "type",
|
|
172
|
-
tags: t.tags
|
|
173
|
-
});
|
|
174
|
-
}
|
|
175
|
-
const tmplCounts = countPerCollection(
|
|
176
|
-
templatesResp.templates,
|
|
177
|
-
templatesResp.collections,
|
|
178
|
-
(t) => {
|
|
179
|
-
const segments = t.path?.split("/");
|
|
180
|
-
return segments && segments.length >= 4 ? segments[3] : void 0;
|
|
181
|
-
}
|
|
182
|
-
);
|
|
183
|
-
for (const col of templatesResp.collections) {
|
|
184
|
-
collections.push({
|
|
185
|
-
name: col.name,
|
|
186
|
-
title: col.title || formatTitle(col.name),
|
|
187
|
-
description: col.description || "",
|
|
188
|
-
type: "template",
|
|
189
|
-
count: tmplCounts.get(col.name) || 0
|
|
190
|
-
});
|
|
191
|
-
}
|
|
192
|
-
for (const tmpl of templatesResp.templates) {
|
|
193
|
-
resources.push({
|
|
194
|
-
name: tmpl.name,
|
|
195
|
-
title: tmpl.title || formatTitle(tmpl.name),
|
|
196
|
-
description: tmpl.description || "",
|
|
197
|
-
type: "template",
|
|
198
|
-
tags: tmpl.tags,
|
|
199
|
-
url: tmpl.path
|
|
200
|
-
});
|
|
201
|
-
}
|
|
202
|
-
for (const endpoint of mcpEndpoints || []) {
|
|
203
|
-
const name = endpoint.split("/").pop() || endpoint;
|
|
204
|
-
resources.push({
|
|
205
|
-
name,
|
|
206
|
-
title: formatTitle(name),
|
|
207
|
-
description: "",
|
|
208
|
-
type: "mcp",
|
|
209
|
-
url: endpoint
|
|
210
|
-
});
|
|
211
|
-
}
|
|
212
|
-
return { collections, resources };
|
|
74
|
+
const collections = [];
|
|
75
|
+
const resources = [];
|
|
76
|
+
const interCounts = countPerCollection(interactionsResp.interactions, interactionsResp.collections, (i) => i.id.split(":")[0]);
|
|
77
|
+
for (const col of interactionsResp.collections) collections.push({
|
|
78
|
+
name: col.name,
|
|
79
|
+
title: col.title || formatTitle(col.name),
|
|
80
|
+
description: col.description || "",
|
|
81
|
+
type: "interaction",
|
|
82
|
+
count: interCounts.get(col.name) || 0
|
|
83
|
+
});
|
|
84
|
+
for (const inter of interactionsResp.interactions) resources.push({
|
|
85
|
+
id: inter.id,
|
|
86
|
+
name: inter.name,
|
|
87
|
+
title: inter.title || formatTitle(inter.name),
|
|
88
|
+
description: inter.description || "",
|
|
89
|
+
type: "interaction",
|
|
90
|
+
tags: inter.tags
|
|
91
|
+
});
|
|
92
|
+
const toolCounts = countPerCollection(toolsResp.tools, toolsResp.collections, (t) => t.url?.split("/").pop());
|
|
93
|
+
for (const col of toolsResp.collections) collections.push({
|
|
94
|
+
name: col.name,
|
|
95
|
+
title: col.title || formatTitle(col.name),
|
|
96
|
+
description: col.description || "",
|
|
97
|
+
type: "tool",
|
|
98
|
+
count: toolCounts.get(col.name) || 0
|
|
99
|
+
});
|
|
100
|
+
for (const tool of toolsResp.tools) resources.push({
|
|
101
|
+
name: tool.name,
|
|
102
|
+
title: formatTitle(tool.name),
|
|
103
|
+
description: tool.description || "",
|
|
104
|
+
type: "tool",
|
|
105
|
+
url: tool.url
|
|
106
|
+
});
|
|
107
|
+
const skillCounts = countPerCollection(skillsResp.tools, skillsResp.collections, (t) => t.url?.split("/").pop());
|
|
108
|
+
for (const col of skillsResp.collections) collections.push({
|
|
109
|
+
name: col.name,
|
|
110
|
+
title: col.title || formatTitle(col.name),
|
|
111
|
+
description: col.description || "",
|
|
112
|
+
type: "skill",
|
|
113
|
+
count: skillCounts.get(col.name) || 0
|
|
114
|
+
});
|
|
115
|
+
for (const skill of skillsResp.tools) resources.push({
|
|
116
|
+
name: skill.name,
|
|
117
|
+
title: formatTitle(skill.name),
|
|
118
|
+
description: skill.description || "",
|
|
119
|
+
type: "skill",
|
|
120
|
+
url: skill.url
|
|
121
|
+
});
|
|
122
|
+
const actCounts = countPerCollection(activitiesResp.activities, activitiesResp.collections, (a) => a.collection);
|
|
123
|
+
for (const col of activitiesResp.collections) collections.push({
|
|
124
|
+
name: col.name,
|
|
125
|
+
title: col.title || formatTitle(col.name),
|
|
126
|
+
description: col.description || "",
|
|
127
|
+
type: "activity",
|
|
128
|
+
count: actCounts.get(col.name) || 0
|
|
129
|
+
});
|
|
130
|
+
for (const act of activitiesResp.activities) resources.push({
|
|
131
|
+
name: act.name,
|
|
132
|
+
title: act.title || formatTitle(act.name),
|
|
133
|
+
description: act.description || "",
|
|
134
|
+
type: "activity",
|
|
135
|
+
url: act.url
|
|
136
|
+
});
|
|
137
|
+
const typeCounts = countPerCollection(typesResp.types, typesResp.collections, (t) => t.id?.split(":")[0]);
|
|
138
|
+
for (const col of typesResp.collections) collections.push({
|
|
139
|
+
name: col.name,
|
|
140
|
+
title: col.title || formatTitle(col.name),
|
|
141
|
+
description: col.description || "",
|
|
142
|
+
type: "type",
|
|
143
|
+
count: typeCounts.get(col.name) || 0
|
|
144
|
+
});
|
|
145
|
+
for (const t of typesResp.types) resources.push({
|
|
146
|
+
name: t.name,
|
|
147
|
+
title: formatTitle(t.name),
|
|
148
|
+
description: t.description || "",
|
|
149
|
+
type: "type",
|
|
150
|
+
tags: t.tags
|
|
151
|
+
});
|
|
152
|
+
const tmplCounts = countPerCollection(templatesResp.templates, templatesResp.collections, (t) => {
|
|
153
|
+
const segments = t.path?.split("/");
|
|
154
|
+
return segments && segments.length >= 4 ? segments[3] : void 0;
|
|
155
|
+
});
|
|
156
|
+
for (const col of templatesResp.collections) collections.push({
|
|
157
|
+
name: col.name,
|
|
158
|
+
title: col.title || formatTitle(col.name),
|
|
159
|
+
description: col.description || "",
|
|
160
|
+
type: "template",
|
|
161
|
+
count: tmplCounts.get(col.name) || 0
|
|
162
|
+
});
|
|
163
|
+
for (const tmpl of templatesResp.templates) resources.push({
|
|
164
|
+
name: tmpl.name,
|
|
165
|
+
title: tmpl.title || formatTitle(tmpl.name),
|
|
166
|
+
description: tmpl.description || "",
|
|
167
|
+
type: "template",
|
|
168
|
+
tags: tmpl.tags,
|
|
169
|
+
url: tmpl.path
|
|
170
|
+
});
|
|
171
|
+
for (const endpoint of mcpEndpoints || []) {
|
|
172
|
+
const name = endpoint.split("/").pop() || endpoint;
|
|
173
|
+
resources.push({
|
|
174
|
+
name,
|
|
175
|
+
title: formatTitle(name),
|
|
176
|
+
description: "",
|
|
177
|
+
type: "mcp",
|
|
178
|
+
url: endpoint
|
|
179
|
+
});
|
|
180
|
+
}
|
|
181
|
+
return {
|
|
182
|
+
collections,
|
|
183
|
+
resources
|
|
184
|
+
};
|
|
213
185
|
}
|
|
186
|
+
/**
|
|
187
|
+
* Filters resources by a search query, matching against name, title, description, type, and tags.
|
|
188
|
+
*/
|
|
214
189
|
function filterResources(items, query) {
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
(item) => item.name.toLowerCase().includes(q) || item.title.toLowerCase().includes(q) || item.description.toLowerCase().includes(q) || item.type.includes(q) || item.tags?.some((t) => t.toLowerCase().includes(q))
|
|
219
|
-
);
|
|
190
|
+
const q = query.toLowerCase().trim();
|
|
191
|
+
if (!q) return items;
|
|
192
|
+
return items.filter((item) => item.name.toLowerCase().includes(q) || item.title.toLowerCase().includes(q) || item.description.toLowerCase().includes(q) || item.type.includes(q) || item.tags?.some((t) => t.toLowerCase().includes(q)));
|
|
220
193
|
}
|
|
194
|
+
//#endregion
|
|
195
|
+
//#region src/hooks.ts
|
|
196
|
+
/**
|
|
197
|
+
* Data fetching hooks for the admin panel.
|
|
198
|
+
*/
|
|
199
|
+
async function fetchJson(url) {
|
|
200
|
+
const response = await fetch(url);
|
|
201
|
+
if (!response.ok) throw new Error(`Request failed: ${response.status} ${response.statusText}`);
|
|
202
|
+
return response.json();
|
|
203
|
+
}
|
|
204
|
+
/**
|
|
205
|
+
* Fetches the tool server info (message, version, endpoints).
|
|
206
|
+
*/
|
|
221
207
|
function useServerInfo(baseUrl) {
|
|
222
|
-
|
|
223
|
-
() => fetch(baseUrl).then((r) => r.json()),
|
|
224
|
-
[baseUrl]
|
|
225
|
-
);
|
|
208
|
+
return useFetch(() => fetchJson(baseUrl), [baseUrl]);
|
|
226
209
|
}
|
|
210
|
+
/**
|
|
211
|
+
* Fetches all 5 resource endpoints in parallel and builds collections + flat resource list.
|
|
212
|
+
* MCP endpoints are passed separately since they come from serverInfo.
|
|
213
|
+
*/
|
|
227
214
|
function useResourceData(baseUrl, mcpEndpoints) {
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
);
|
|
240
|
-
}, [baseUrl, mcpEndpoints]);
|
|
215
|
+
return useFetch(() => {
|
|
216
|
+
const fetchResource = (path) => fetchJson(`${baseUrl}/${path}`);
|
|
217
|
+
return Promise.all([
|
|
218
|
+
fetchResource("interactions"),
|
|
219
|
+
fetchResource("tools"),
|
|
220
|
+
fetchResource("skills"),
|
|
221
|
+
fetchResource("activities"),
|
|
222
|
+
fetchResource("types"),
|
|
223
|
+
fetchResource("templates")
|
|
224
|
+
]).then(([interactions, tools, skills, activities, types, templates]) => buildResourceData(interactions, tools, skills, activities, types, templates, mcpEndpoints));
|
|
225
|
+
}, [baseUrl, mcpEndpoints]);
|
|
241
226
|
}
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
227
|
+
//#endregion
|
|
228
|
+
//#region src/components/typeVariants.ts
|
|
229
|
+
/** Tailwind class mappings for resource type badges. */
|
|
230
|
+
var TYPE_VARIANTS = {
|
|
231
|
+
tool: "bg-blue-100 text-blue-800 dark:bg-blue-500/15 dark:text-blue-300",
|
|
232
|
+
skill: "bg-emerald-100 text-emerald-800 dark:bg-emerald-500/15 dark:text-emerald-300",
|
|
233
|
+
interaction: "bg-amber-100 text-amber-800 dark:bg-amber-500/15 dark:text-amber-300",
|
|
234
|
+
type: "bg-gray-100 text-gray-700 dark:bg-gray-500/20 dark:text-gray-300",
|
|
235
|
+
template: "bg-violet-100 text-violet-800 dark:bg-violet-500/15 dark:text-violet-300",
|
|
236
|
+
activity: "bg-rose-100 text-rose-800 dark:bg-rose-500/15 dark:text-rose-300",
|
|
237
|
+
mcp: "bg-pink-100 text-pink-800 dark:bg-pink-500/15 dark:text-pink-300"
|
|
250
238
|
};
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
239
|
+
/** Tailwind class mappings for prompt role badges. */
|
|
240
|
+
var ROLE_VARIANTS = {
|
|
241
|
+
system: "bg-blue-100 text-blue-800 dark:bg-blue-500/15 dark:text-blue-300",
|
|
242
|
+
user: "bg-emerald-100 text-emerald-800 dark:bg-emerald-500/15 dark:text-emerald-300",
|
|
243
|
+
assistant: "bg-violet-100 text-violet-800 dark:bg-violet-500/15 dark:text-violet-300",
|
|
244
|
+
safety: "bg-pink-100 text-pink-800 dark:bg-pink-500/15 dark:text-pink-300",
|
|
245
|
+
tool: "bg-amber-100 text-amber-800 dark:bg-amber-500/15 dark:text-amber-300"
|
|
257
246
|
};
|
|
247
|
+
//#endregion
|
|
248
|
+
//#region src/components/DetailPage.tsx
|
|
258
249
|
function DetailPage({ type, title, description, tags, backHref = "/", children }) {
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
250
|
+
return /* @__PURE__ */ jsxs("div", {
|
|
251
|
+
className: "mx-auto max-w-5xl px-7 py-10",
|
|
252
|
+
children: [
|
|
253
|
+
/* @__PURE__ */ jsxs("nav", {
|
|
254
|
+
className: "mb-5 flex items-center gap-4",
|
|
255
|
+
children: [backHref !== "/" && /* @__PURE__ */ jsx(NavLink, {
|
|
256
|
+
href: "/",
|
|
257
|
+
className: "text-sm text-primary hover:opacity-75",
|
|
258
|
+
children: "Home"
|
|
259
|
+
}), /* @__PURE__ */ jsxs(NavLink, {
|
|
260
|
+
href: backHref,
|
|
261
|
+
className: "flex items-center gap-1 text-sm text-primary hover:opacity-75",
|
|
262
|
+
children: [/* @__PURE__ */ jsx(ArrowLeft, { className: "size-3.5" }), "Back"]
|
|
263
|
+
})]
|
|
264
|
+
}),
|
|
265
|
+
/* @__PURE__ */ jsxs("div", {
|
|
266
|
+
className: "mb-8",
|
|
267
|
+
children: [
|
|
268
|
+
/* @__PURE__ */ jsx("span", {
|
|
269
|
+
className: `mb-2 inline-block rounded-full px-2 py-0.5 text-[0.7rem] font-semibold uppercase tracking-wide ${TYPE_VARIANTS[type] ?? ""}`,
|
|
270
|
+
children: type
|
|
271
|
+
}),
|
|
272
|
+
/* @__PURE__ */ jsx("h1", {
|
|
273
|
+
className: "-tracking-wide text-3xl font-bold text-foreground",
|
|
274
|
+
children: title
|
|
275
|
+
}),
|
|
276
|
+
description && /* @__PURE__ */ jsx("p", {
|
|
277
|
+
className: "mt-1 text-sm leading-relaxed text-muted-foreground",
|
|
278
|
+
children: description
|
|
279
|
+
}),
|
|
280
|
+
tags && tags.length > 0 && /* @__PURE__ */ jsx("div", {
|
|
281
|
+
className: "mt-3 flex flex-wrap gap-1.5",
|
|
282
|
+
children: tags.map((tag) => /* @__PURE__ */ jsx(Badge, {
|
|
283
|
+
variant: "default",
|
|
284
|
+
children: tag
|
|
285
|
+
}, tag))
|
|
286
|
+
})
|
|
287
|
+
]
|
|
288
|
+
}),
|
|
289
|
+
children
|
|
290
|
+
]
|
|
291
|
+
});
|
|
275
292
|
}
|
|
293
|
+
//#endregion
|
|
294
|
+
//#region src/pages/ActivityCollection.tsx
|
|
276
295
|
function ActivityCollection() {
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
296
|
+
const collection = useParams("collection");
|
|
297
|
+
const { baseUrl } = useAdminContext();
|
|
298
|
+
const { data, error } = useFetch(() => fetch(`${baseUrl}/activities/${collection}`).then((r) => {
|
|
299
|
+
if (!r.ok) throw new Error(`Failed to load collection: ${r.statusText}`);
|
|
300
|
+
return r.json();
|
|
301
|
+
}), [baseUrl, collection]);
|
|
302
|
+
if (error) return /* @__PURE__ */ jsxs("div", {
|
|
303
|
+
className: "p-6 text-destructive",
|
|
304
|
+
children: [
|
|
305
|
+
"Failed to load activity collection “",
|
|
306
|
+
collection,
|
|
307
|
+
"”."
|
|
308
|
+
]
|
|
309
|
+
});
|
|
310
|
+
if (!data) return /* @__PURE__ */ jsx("div", {
|
|
311
|
+
className: "flex h-64 items-center justify-center text-muted-foreground",
|
|
312
|
+
children: /* @__PURE__ */ jsx(Spinner, {})
|
|
313
|
+
});
|
|
314
|
+
return /* @__PURE__ */ jsx(DetailPage, {
|
|
315
|
+
type: "activity",
|
|
316
|
+
title: data.title || collection,
|
|
317
|
+
description: data.description || `${data.activities.length} activit${data.activities.length !== 1 ? "ies" : "y"} in this collection.`,
|
|
318
|
+
children: data.activities.map((activity) => /* @__PURE__ */ jsx(Card, {
|
|
319
|
+
className: "mb-4",
|
|
320
|
+
children: /* @__PURE__ */ jsxs(CardContent, {
|
|
321
|
+
className: "p-5",
|
|
322
|
+
children: [
|
|
323
|
+
/* @__PURE__ */ jsxs("div", {
|
|
324
|
+
className: "mb-2 flex items-center gap-2",
|
|
325
|
+
children: [/* @__PURE__ */ jsx("span", {
|
|
326
|
+
className: `inline-block rounded-full px-2 py-0.5 text-[0.7rem] font-semibold uppercase tracking-wide ${TYPE_VARIANTS.activity}`,
|
|
327
|
+
children: "activity"
|
|
328
|
+
}), /* @__PURE__ */ jsx("span", {
|
|
329
|
+
className: "font-semibold text-card-foreground",
|
|
330
|
+
children: activity.name
|
|
331
|
+
})]
|
|
332
|
+
}),
|
|
333
|
+
/* @__PURE__ */ jsx("div", {
|
|
334
|
+
className: "text-sm text-muted-foreground",
|
|
335
|
+
children: activity.description || "No description"
|
|
336
|
+
}),
|
|
337
|
+
activity.input_schema && /* @__PURE__ */ jsxs("div", {
|
|
338
|
+
className: "mt-3",
|
|
339
|
+
children: [/* @__PURE__ */ jsx("p", {
|
|
340
|
+
className: "mb-1 text-xs font-semibold uppercase tracking-wide text-muted-foreground",
|
|
341
|
+
children: "Input Schema"
|
|
342
|
+
}), /* @__PURE__ */ jsx("pre", {
|
|
343
|
+
className: "whitespace-pre-wrap wrap-break-word rounded-lg border border-border bg-muted-background p-4 font-mono text-sm text-foreground",
|
|
344
|
+
children: JSON.stringify(activity.input_schema, null, 2)
|
|
345
|
+
})]
|
|
346
|
+
}),
|
|
347
|
+
activity.output_schema && /* @__PURE__ */ jsxs("div", {
|
|
348
|
+
className: "mt-3",
|
|
349
|
+
children: [/* @__PURE__ */ jsx("p", {
|
|
350
|
+
className: "mb-1 text-xs font-semibold uppercase tracking-wide text-muted-foreground",
|
|
351
|
+
children: "Output Schema"
|
|
352
|
+
}), /* @__PURE__ */ jsx("pre", {
|
|
353
|
+
className: "whitespace-pre-wrap wrap-break-word rounded-lg border border-border bg-muted-background p-4 font-mono text-sm text-foreground",
|
|
354
|
+
children: JSON.stringify(activity.output_schema, null, 2)
|
|
355
|
+
})]
|
|
356
|
+
})
|
|
357
|
+
]
|
|
358
|
+
})
|
|
359
|
+
}, activity.name))
|
|
360
|
+
});
|
|
315
361
|
}
|
|
362
|
+
//#endregion
|
|
363
|
+
//#region src/components/CollectionCard.tsx
|
|
316
364
|
function CollectionCard({ collection }) {
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
365
|
+
return /* @__PURE__ */ jsx(NavLink, {
|
|
366
|
+
href: `/${collection.type === "activity" ? "activities" : `${collection.type}s`}/${collection.name}`,
|
|
367
|
+
className: "block no-underline",
|
|
368
|
+
children: /* @__PURE__ */ jsx(Card, {
|
|
369
|
+
className: "cursor-pointer transition-all hover:-translate-y-0.5 hover:shadow-md",
|
|
370
|
+
children: /* @__PURE__ */ jsxs(CardContent, {
|
|
371
|
+
className: "p-5",
|
|
372
|
+
children: [
|
|
373
|
+
/* @__PURE__ */ jsx("span", {
|
|
374
|
+
className: `mb-2 inline-block rounded-full px-2 py-0.5 text-[0.7rem] font-semibold uppercase tracking-wide ${TYPE_VARIANTS[collection.type] ?? ""}`,
|
|
375
|
+
children: collection.type
|
|
376
|
+
}),
|
|
377
|
+
/* @__PURE__ */ jsx("div", {
|
|
378
|
+
className: "font-semibold text-card-foreground",
|
|
379
|
+
children: collection.title
|
|
380
|
+
}),
|
|
381
|
+
/* @__PURE__ */ jsx("div", {
|
|
382
|
+
className: "mt-1 text-sm text-muted-foreground",
|
|
383
|
+
children: collection.description || "No description"
|
|
384
|
+
}),
|
|
385
|
+
/* @__PURE__ */ jsxs("div", {
|
|
386
|
+
className: "mt-2 font-mono text-xs text-muted-foreground",
|
|
387
|
+
children: [
|
|
388
|
+
collection.count,
|
|
389
|
+
" ",
|
|
390
|
+
collection.count === 1 ? "item" : "items"
|
|
391
|
+
]
|
|
392
|
+
})
|
|
393
|
+
]
|
|
394
|
+
})
|
|
395
|
+
})
|
|
396
|
+
});
|
|
329
397
|
}
|
|
398
|
+
//#endregion
|
|
399
|
+
//#region src/components/EndpointPanel.tsx
|
|
330
400
|
function EndpointPanel({ label, path }) {
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
401
|
+
const [copied, setCopied] = useState(false);
|
|
402
|
+
function handleCopy() {
|
|
403
|
+
const url = window.location.origin + path;
|
|
404
|
+
navigator.clipboard.writeText(url);
|
|
405
|
+
setCopied(true);
|
|
406
|
+
setTimeout(() => setCopied(false), 1500);
|
|
407
|
+
}
|
|
408
|
+
return /* @__PURE__ */ jsxs("div", {
|
|
409
|
+
className: "mb-3",
|
|
410
|
+
children: [/* @__PURE__ */ jsx("div", {
|
|
411
|
+
className: "mb-1 text-[0.7rem] font-medium uppercase tracking-widest text-primary",
|
|
412
|
+
children: label
|
|
413
|
+
}), /* @__PURE__ */ jsxs("div", {
|
|
414
|
+
className: "flex items-center gap-2 rounded-lg border border-border bg-muted-background px-3 py-2",
|
|
415
|
+
children: [/* @__PURE__ */ jsx("code", {
|
|
416
|
+
className: "flex-1 font-mono text-sm text-foreground",
|
|
417
|
+
children: path
|
|
418
|
+
}), /* @__PURE__ */ jsx(Button, {
|
|
419
|
+
variant: "ghost",
|
|
420
|
+
size: "xs",
|
|
421
|
+
onClick: handleCopy,
|
|
422
|
+
"aria-label": "Copy full URL",
|
|
423
|
+
children: copied ? /* @__PURE__ */ jsx(Check, { className: "size-3.5" }) : /* @__PURE__ */ jsx(Copy, { className: "size-3.5" })
|
|
424
|
+
})]
|
|
425
|
+
})]
|
|
426
|
+
});
|
|
354
427
|
}
|
|
428
|
+
//#endregion
|
|
429
|
+
//#region src/components/SummaryBadge.tsx
|
|
355
430
|
function SummaryBadge({ count, label }) {
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
431
|
+
if (count === 0) return null;
|
|
432
|
+
return /* @__PURE__ */ jsxs(DotBadge, {
|
|
433
|
+
variant: "success",
|
|
434
|
+
children: [
|
|
435
|
+
count,
|
|
436
|
+
" ",
|
|
437
|
+
label,
|
|
438
|
+
count !== 1 ? "s" : ""
|
|
439
|
+
]
|
|
440
|
+
});
|
|
363
441
|
}
|
|
442
|
+
//#endregion
|
|
443
|
+
//#region src/components/HeroSection.tsx
|
|
364
444
|
function getInitials(title) {
|
|
365
|
-
|
|
445
|
+
return title.split(/\s+/).map((w) => w[0]).filter(Boolean).slice(0, 2).join("").toUpperCase();
|
|
366
446
|
}
|
|
367
447
|
function countByType(resources) {
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
}
|
|
372
|
-
return counts;
|
|
448
|
+
const counts = {};
|
|
449
|
+
for (const r of resources) counts[r.type] = (counts[r.type] || 0) + 1;
|
|
450
|
+
return counts;
|
|
373
451
|
}
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
452
|
+
var badgeLabels = [
|
|
453
|
+
{
|
|
454
|
+
type: "tool",
|
|
455
|
+
label: "tool"
|
|
456
|
+
},
|
|
457
|
+
{
|
|
458
|
+
type: "activity",
|
|
459
|
+
label: "activity"
|
|
460
|
+
},
|
|
461
|
+
{
|
|
462
|
+
type: "skill",
|
|
463
|
+
label: "skill"
|
|
464
|
+
},
|
|
465
|
+
{
|
|
466
|
+
type: "interaction",
|
|
467
|
+
label: "interaction"
|
|
468
|
+
},
|
|
469
|
+
{
|
|
470
|
+
type: "type",
|
|
471
|
+
label: "content type"
|
|
472
|
+
},
|
|
473
|
+
{
|
|
474
|
+
type: "template",
|
|
475
|
+
label: "template"
|
|
476
|
+
},
|
|
477
|
+
{
|
|
478
|
+
type: "mcp",
|
|
479
|
+
label: "MCP provider"
|
|
480
|
+
}
|
|
382
481
|
];
|
|
383
482
|
function HeroSection({ title, version, resources }) {
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
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
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
483
|
+
const counts = countByType(resources);
|
|
484
|
+
return /* @__PURE__ */ jsx(Card, {
|
|
485
|
+
className: "mb-10 overflow-hidden border bg-linear-to-br from-card to-muted-background",
|
|
486
|
+
children: /* @__PURE__ */ jsxs("div", {
|
|
487
|
+
className: "flex flex-col gap-6 p-6 md:flex-row md:items-start md:justify-between",
|
|
488
|
+
children: [/* @__PURE__ */ jsxs("div", {
|
|
489
|
+
className: "flex flex-1 flex-col gap-3",
|
|
490
|
+
children: [
|
|
491
|
+
/* @__PURE__ */ jsxs("div", {
|
|
492
|
+
className: "flex items-center gap-4",
|
|
493
|
+
children: [/* @__PURE__ */ jsx("div", {
|
|
494
|
+
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",
|
|
495
|
+
children: getInitials(title)
|
|
496
|
+
}), /* @__PURE__ */ jsxs("div", { children: [/* @__PURE__ */ jsx("p", {
|
|
497
|
+
className: "text-xs font-medium uppercase tracking-widest text-muted-foreground",
|
|
498
|
+
children: "Tools Server"
|
|
499
|
+
}), /* @__PURE__ */ jsx("h1", {
|
|
500
|
+
className: "-tracking-wide text-2xl font-bold text-foreground",
|
|
501
|
+
children: title
|
|
502
|
+
})] })]
|
|
503
|
+
}),
|
|
504
|
+
/* @__PURE__ */ jsx("p", {
|
|
505
|
+
className: "text-sm text-muted-foreground",
|
|
506
|
+
children: "Discover the tools, skills, interactions, and content types exposed by this server."
|
|
507
|
+
}),
|
|
508
|
+
/* @__PURE__ */ jsx("div", {
|
|
509
|
+
className: "flex flex-wrap gap-2",
|
|
510
|
+
children: badgeLabels.map(({ type, label }) => /* @__PURE__ */ jsx(SummaryBadge, {
|
|
511
|
+
count: counts[type] || 0,
|
|
512
|
+
label
|
|
513
|
+
}, type))
|
|
514
|
+
}),
|
|
515
|
+
/* @__PURE__ */ jsxs("div", {
|
|
516
|
+
className: "flex flex-wrap gap-3 pt-1",
|
|
517
|
+
children: [/* @__PURE__ */ jsxs("a", {
|
|
518
|
+
href: "/app/",
|
|
519
|
+
target: "_blank",
|
|
520
|
+
rel: "noopener noreferrer",
|
|
521
|
+
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",
|
|
522
|
+
children: [/* @__PURE__ */ jsx(LayoutDashboard, { className: "size-4" }), "UI Plugin Dev"]
|
|
523
|
+
}), /* @__PURE__ */ jsxs("a", {
|
|
524
|
+
href: "/lib/plugin.js",
|
|
525
|
+
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",
|
|
526
|
+
children: [/* @__PURE__ */ jsx(Download, { className: "size-4" }), "Plugin Bundle"]
|
|
527
|
+
})]
|
|
528
|
+
})
|
|
529
|
+
]
|
|
530
|
+
}), /* @__PURE__ */ jsxs("aside", {
|
|
531
|
+
className: "min-w-55 max-w-65 shrink-0",
|
|
532
|
+
children: [
|
|
533
|
+
/* @__PURE__ */ jsx(EndpointPanel, {
|
|
534
|
+
label: "Base endpoint",
|
|
535
|
+
path: "/api"
|
|
536
|
+
}),
|
|
537
|
+
/* @__PURE__ */ jsx(EndpointPanel, {
|
|
538
|
+
label: "Package endpoint",
|
|
539
|
+
path: "/api/package"
|
|
540
|
+
}),
|
|
541
|
+
/* @__PURE__ */ jsxs("p", {
|
|
542
|
+
className: "mt-2 text-xs leading-relaxed text-muted-foreground",
|
|
543
|
+
children: [
|
|
544
|
+
"Use ",
|
|
545
|
+
/* @__PURE__ */ jsx("strong", {
|
|
546
|
+
className: "text-foreground",
|
|
547
|
+
children: "POST /api/tools/<collection>"
|
|
548
|
+
}),
|
|
549
|
+
" or",
|
|
550
|
+
" ",
|
|
551
|
+
/* @__PURE__ */ jsx("strong", {
|
|
552
|
+
className: "text-foreground",
|
|
553
|
+
children: "POST /api/skills/<collection>"
|
|
554
|
+
}),
|
|
555
|
+
" to call these from your apps or agents."
|
|
556
|
+
]
|
|
557
|
+
}),
|
|
558
|
+
/* @__PURE__ */ jsxs("p", {
|
|
559
|
+
className: "mt-1 text-xs text-muted-foreground",
|
|
560
|
+
children: ["v", version]
|
|
561
|
+
})
|
|
562
|
+
]
|
|
563
|
+
})]
|
|
564
|
+
})
|
|
565
|
+
});
|
|
440
566
|
}
|
|
567
|
+
//#endregion
|
|
568
|
+
//#region src/components/ResourceCard.tsx
|
|
441
569
|
function ResourceCard({ resource }) {
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
570
|
+
return /* @__PURE__ */ jsx(Card, {
|
|
571
|
+
className: "transition-all hover:-translate-y-0.5 hover:shadow-md",
|
|
572
|
+
children: /* @__PURE__ */ jsxs(CardContent, {
|
|
573
|
+
className: "p-5",
|
|
574
|
+
children: [
|
|
575
|
+
/* @__PURE__ */ jsx("span", {
|
|
576
|
+
className: `mb-2 inline-block rounded-full px-2 py-0.5 text-[0.7rem] font-semibold uppercase tracking-wide ${TYPE_VARIANTS[resource.type] ?? ""}`,
|
|
577
|
+
children: resource.type
|
|
578
|
+
}),
|
|
579
|
+
/* @__PURE__ */ jsx("div", {
|
|
580
|
+
className: "font-semibold text-card-foreground",
|
|
581
|
+
children: resource.title
|
|
582
|
+
}),
|
|
583
|
+
/* @__PURE__ */ jsx("div", {
|
|
584
|
+
className: "mt-1 text-sm text-muted-foreground",
|
|
585
|
+
children: resource.description || "No description"
|
|
586
|
+
}),
|
|
587
|
+
resource.tags && resource.tags.length > 0 && /* @__PURE__ */ jsx("div", {
|
|
588
|
+
className: "mt-2 flex flex-wrap gap-1",
|
|
589
|
+
children: resource.tags.map((tag) => /* @__PURE__ */ jsx(Badge, {
|
|
590
|
+
variant: "default",
|
|
591
|
+
children: tag
|
|
592
|
+
}, tag))
|
|
593
|
+
}),
|
|
594
|
+
resource.url && /* @__PURE__ */ jsx("div", {
|
|
595
|
+
className: "mt-2 truncate font-mono text-xs text-muted-foreground",
|
|
596
|
+
children: resource.url
|
|
597
|
+
})
|
|
598
|
+
]
|
|
599
|
+
})
|
|
600
|
+
});
|
|
449
601
|
}
|
|
602
|
+
//#endregion
|
|
603
|
+
//#region src/components/ResourceSection.tsx
|
|
450
604
|
function ResourceSection({ title, subtitle, resources, showDivider }) {
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
605
|
+
if (resources.length === 0) return null;
|
|
606
|
+
return /* @__PURE__ */ jsxs("section", { children: [
|
|
607
|
+
showDivider && /* @__PURE__ */ jsx(Separator, { className: "my-8" }),
|
|
608
|
+
/* @__PURE__ */ jsxs("div", { children: [/* @__PURE__ */ jsxs("h2", {
|
|
609
|
+
className: "text-xl font-semibold text-foreground",
|
|
610
|
+
children: [title, /* @__PURE__ */ jsxs("span", {
|
|
611
|
+
className: "ml-2 text-sm font-normal text-muted-foreground",
|
|
612
|
+
children: [
|
|
613
|
+
"(",
|
|
614
|
+
resources.length,
|
|
615
|
+
")"
|
|
616
|
+
]
|
|
617
|
+
})]
|
|
618
|
+
}), /* @__PURE__ */ jsx("p", {
|
|
619
|
+
className: "mb-4 text-sm text-muted-foreground",
|
|
620
|
+
children: subtitle
|
|
621
|
+
})] }),
|
|
622
|
+
/* @__PURE__ */ jsx("div", {
|
|
623
|
+
className: "grid grid-cols-1 gap-6 sm:grid-cols-2 lg:grid-cols-3",
|
|
624
|
+
children: resources.map((r) => /* @__PURE__ */ jsx(ResourceCard, { resource: r }, `${r.type}:${r.name}`))
|
|
625
|
+
})
|
|
626
|
+
] });
|
|
467
627
|
}
|
|
628
|
+
//#endregion
|
|
629
|
+
//#region src/components/SearchBar.tsx
|
|
468
630
|
function SearchBar({ value, onChange, placeholder, resultCount, totalCount }) {
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
631
|
+
const hasQuery = value.trim().length > 0;
|
|
632
|
+
const noResults = hasQuery && resultCount === 0;
|
|
633
|
+
return /* @__PURE__ */ jsxs("div", {
|
|
634
|
+
className: "mb-7",
|
|
635
|
+
children: [
|
|
636
|
+
/* @__PURE__ */ jsx(Input, {
|
|
637
|
+
type: "search",
|
|
638
|
+
value,
|
|
639
|
+
onChange,
|
|
640
|
+
placeholder: placeholder || "Search collections...",
|
|
641
|
+
className: "max-w-sm rounded-full",
|
|
642
|
+
autoComplete: "off"
|
|
643
|
+
}),
|
|
644
|
+
hasQuery && !noResults && /* @__PURE__ */ jsxs("p", {
|
|
645
|
+
className: "mt-1.5 text-xs text-muted-foreground",
|
|
646
|
+
children: [
|
|
647
|
+
"Showing ",
|
|
648
|
+
resultCount,
|
|
649
|
+
" of ",
|
|
650
|
+
totalCount,
|
|
651
|
+
" resources"
|
|
652
|
+
]
|
|
653
|
+
}),
|
|
654
|
+
noResults && /* @__PURE__ */ jsx("p", {
|
|
655
|
+
className: "mt-2 text-sm text-destructive",
|
|
656
|
+
children: "No resources match this search."
|
|
657
|
+
})
|
|
658
|
+
]
|
|
659
|
+
});
|
|
492
660
|
}
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
661
|
+
//#endregion
|
|
662
|
+
//#region src/pages/HomePage.tsx
|
|
663
|
+
var sections = [
|
|
664
|
+
{
|
|
665
|
+
type: "tool",
|
|
666
|
+
title: "Tools",
|
|
667
|
+
subtitle: "Remote tools available to agents via Vertesia."
|
|
668
|
+
},
|
|
669
|
+
{
|
|
670
|
+
type: "activity",
|
|
671
|
+
title: "Activities",
|
|
672
|
+
subtitle: "Remote activities for DSL workflows, invoked via HTTP."
|
|
673
|
+
},
|
|
674
|
+
{
|
|
675
|
+
type: "skill",
|
|
676
|
+
title: "Skills",
|
|
677
|
+
subtitle: "Reusable instructions and scripts packaged as tools."
|
|
678
|
+
},
|
|
679
|
+
{
|
|
680
|
+
type: "interaction",
|
|
681
|
+
title: "Interactions",
|
|
682
|
+
subtitle: "Conversation blueprints surfaced in the Vertesia UI."
|
|
683
|
+
},
|
|
684
|
+
{
|
|
685
|
+
type: "type",
|
|
686
|
+
title: "Content Types",
|
|
687
|
+
subtitle: "Schema definitions for structured content in the data store."
|
|
688
|
+
},
|
|
689
|
+
{
|
|
690
|
+
type: "template",
|
|
691
|
+
title: "Rendering Templates",
|
|
692
|
+
subtitle: "Document and presentation templates for content generation."
|
|
693
|
+
},
|
|
694
|
+
{
|
|
695
|
+
type: "mcp",
|
|
696
|
+
title: "MCP Providers",
|
|
697
|
+
subtitle: "Remote MCP servers available through this tools server."
|
|
698
|
+
}
|
|
501
699
|
];
|
|
502
700
|
function HomePage() {
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
|
|
701
|
+
const { serverInfo, collections, resources } = useAdminContext();
|
|
702
|
+
const [search, setSearch] = useState("");
|
|
703
|
+
const filtered = useMemo(() => filterResources(resources, search), [resources, search]);
|
|
704
|
+
const isSearching = search.trim().length > 0;
|
|
705
|
+
return /* @__PURE__ */ jsxs("div", {
|
|
706
|
+
className: "mx-auto max-w-5xl px-7 py-10",
|
|
707
|
+
children: [
|
|
708
|
+
/* @__PURE__ */ jsx(HeroSection, {
|
|
709
|
+
title: serverInfo.message.replace("Vertesia Tools API", "Tools Server"),
|
|
710
|
+
version: serverInfo.version,
|
|
711
|
+
resources
|
|
712
|
+
}),
|
|
713
|
+
/* @__PURE__ */ jsx(SearchBar, {
|
|
714
|
+
value: search,
|
|
715
|
+
onChange: setSearch,
|
|
716
|
+
placeholder: "Search tools, skills, interactions, types, templates...",
|
|
717
|
+
resultCount: filtered.length,
|
|
718
|
+
totalCount: resources.length
|
|
719
|
+
}),
|
|
720
|
+
isSearching ? sections.map((section, i) => {
|
|
721
|
+
const sectionItems = filtered.filter((r) => r.type === section.type);
|
|
722
|
+
return /* @__PURE__ */ jsx(ResourceSection, {
|
|
723
|
+
title: section.title,
|
|
724
|
+
subtitle: section.subtitle,
|
|
725
|
+
resources: sectionItems,
|
|
726
|
+
showDivider: i > 0
|
|
727
|
+
}, section.type);
|
|
728
|
+
}) : sections.map((section, i) => {
|
|
729
|
+
const sectionCollections = collections.filter((c) => c.type === section.type);
|
|
730
|
+
const mcpResources = section.type === "mcp" ? resources.filter((r) => r.type === "mcp") : [];
|
|
731
|
+
if (sectionCollections.length === 0 && mcpResources.length === 0) return null;
|
|
732
|
+
return /* @__PURE__ */ jsxs("section", { children: [
|
|
733
|
+
i > 0 && /* @__PURE__ */ jsx(Separator, { className: "my-8" }),
|
|
734
|
+
/* @__PURE__ */ jsxs("div", { children: [/* @__PURE__ */ jsxs("h2", {
|
|
735
|
+
className: "text-xl font-semibold text-foreground",
|
|
736
|
+
children: [section.title, /* @__PURE__ */ jsxs("span", {
|
|
737
|
+
className: "ml-2 text-sm font-normal text-muted-foreground",
|
|
738
|
+
children: [
|
|
739
|
+
"(",
|
|
740
|
+
sectionCollections.length,
|
|
741
|
+
sectionCollections.length === 1 ? " collection" : " collections",
|
|
742
|
+
")"
|
|
743
|
+
]
|
|
744
|
+
})]
|
|
745
|
+
}), /* @__PURE__ */ jsx("p", {
|
|
746
|
+
className: "mb-4 text-sm text-muted-foreground",
|
|
747
|
+
children: section.subtitle
|
|
748
|
+
})] }),
|
|
749
|
+
/* @__PURE__ */ jsxs("div", {
|
|
750
|
+
className: "grid grid-cols-1 gap-6 sm:grid-cols-2 lg:grid-cols-3",
|
|
751
|
+
children: [sectionCollections.map((col) => /* @__PURE__ */ jsx(CollectionCard, { collection: col }, `${col.type}:${col.name}`)), mcpResources.map((r) => /* @__PURE__ */ jsxs("div", {
|
|
752
|
+
className: "rounded-xl border border-border bg-card p-5 shadow-sm",
|
|
753
|
+
children: [
|
|
754
|
+
/* @__PURE__ */ jsx("span", {
|
|
755
|
+
className: `mb-2 inline-block rounded-full px-2 py-0.5 text-[0.7rem] font-semibold uppercase tracking-wide ${TYPE_VARIANTS.mcp}`,
|
|
756
|
+
children: "mcp"
|
|
757
|
+
}),
|
|
758
|
+
/* @__PURE__ */ jsx("div", {
|
|
759
|
+
className: "font-semibold text-card-foreground",
|
|
760
|
+
children: r.title
|
|
761
|
+
}),
|
|
762
|
+
/* @__PURE__ */ jsx("div", {
|
|
763
|
+
className: "mt-1 text-sm text-muted-foreground",
|
|
764
|
+
children: r.description || "No description"
|
|
765
|
+
}),
|
|
766
|
+
r.url && /* @__PURE__ */ jsx("div", {
|
|
767
|
+
className: "mt-2 truncate font-mono text-xs text-muted-foreground",
|
|
768
|
+
children: r.url
|
|
769
|
+
})
|
|
770
|
+
]
|
|
771
|
+
}, r.name))]
|
|
772
|
+
})
|
|
773
|
+
] }, section.type);
|
|
774
|
+
})
|
|
775
|
+
]
|
|
776
|
+
});
|
|
571
777
|
}
|
|
778
|
+
//#endregion
|
|
779
|
+
//#region src/pages/InteractionCollection.tsx
|
|
572
780
|
function InteractionCollection() {
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
|
|
604
|
-
|
|
605
|
-
|
|
781
|
+
const collection = useParams("collection");
|
|
782
|
+
const { baseUrl } = useAdminContext();
|
|
783
|
+
const { data: interactions, error } = useFetch(() => fetch(`${baseUrl}/interactions/${collection}`).then((r) => {
|
|
784
|
+
if (!r.ok) throw new Error(`Failed to load collection: ${r.statusText}`);
|
|
785
|
+
return r.json();
|
|
786
|
+
}), [baseUrl, collection]);
|
|
787
|
+
if (error) return /* @__PURE__ */ jsxs("div", {
|
|
788
|
+
className: "p-6 text-destructive",
|
|
789
|
+
children: [
|
|
790
|
+
"Failed to load collection “",
|
|
791
|
+
collection,
|
|
792
|
+
"”."
|
|
793
|
+
]
|
|
794
|
+
});
|
|
795
|
+
if (!interactions) return /* @__PURE__ */ jsx("div", {
|
|
796
|
+
className: "flex h-64 items-center justify-center text-muted-foreground",
|
|
797
|
+
children: /* @__PURE__ */ jsx(Spinner, {})
|
|
798
|
+
});
|
|
799
|
+
return /* @__PURE__ */ jsx(DetailPage, {
|
|
800
|
+
type: "interaction",
|
|
801
|
+
title: collection,
|
|
802
|
+
description: `${interactions.length} interaction${interactions.length !== 1 ? "s" : ""} in this collection.`,
|
|
803
|
+
children: /* @__PURE__ */ jsx("div", {
|
|
804
|
+
className: "grid grid-cols-1 gap-6 sm:grid-cols-2 lg:grid-cols-3",
|
|
805
|
+
children: interactions.map((inter) => /* @__PURE__ */ jsx(NavLink, {
|
|
806
|
+
href: `/interactions/${collection}/${inter.name}`,
|
|
807
|
+
className: "block no-underline",
|
|
808
|
+
children: /* @__PURE__ */ jsx(Card, {
|
|
809
|
+
className: "cursor-pointer transition-all hover:-translate-y-0.5 hover:shadow-md",
|
|
810
|
+
children: /* @__PURE__ */ jsxs(CardContent, {
|
|
811
|
+
className: "p-5",
|
|
812
|
+
children: [
|
|
813
|
+
/* @__PURE__ */ jsx("span", {
|
|
814
|
+
className: `mb-2 inline-block rounded-full px-2 py-0.5 text-[0.7rem] font-semibold uppercase tracking-wide ${TYPE_VARIANTS.interaction}`,
|
|
815
|
+
children: "interaction"
|
|
816
|
+
}),
|
|
817
|
+
/* @__PURE__ */ jsx("div", {
|
|
818
|
+
className: "font-semibold text-card-foreground",
|
|
819
|
+
children: inter.title || inter.name
|
|
820
|
+
}),
|
|
821
|
+
/* @__PURE__ */ jsx("div", {
|
|
822
|
+
className: "mt-1 text-sm text-muted-foreground",
|
|
823
|
+
children: inter.description || "No description"
|
|
824
|
+
}),
|
|
825
|
+
inter.tags && inter.tags.length > 0 && /* @__PURE__ */ jsx("div", {
|
|
826
|
+
className: "mt-2 flex flex-wrap gap-1",
|
|
827
|
+
children: inter.tags.map((tag) => /* @__PURE__ */ jsx(Badge, { children: tag }, tag))
|
|
828
|
+
})
|
|
829
|
+
]
|
|
830
|
+
})
|
|
831
|
+
})
|
|
832
|
+
}, inter.id))
|
|
833
|
+
})
|
|
834
|
+
});
|
|
606
835
|
}
|
|
836
|
+
//#endregion
|
|
837
|
+
//#region src/pages/InteractionDetail.tsx
|
|
607
838
|
function InteractionDetail() {
|
|
608
|
-
|
|
609
|
-
|
|
610
|
-
|
|
611
|
-
|
|
612
|
-
|
|
613
|
-
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
|
|
617
|
-
|
|
618
|
-
|
|
619
|
-
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
|
|
635
|
-
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
|
|
639
|
-
|
|
640
|
-
|
|
641
|
-
|
|
642
|
-
|
|
643
|
-
|
|
644
|
-
|
|
645
|
-
|
|
646
|
-
|
|
647
|
-
|
|
648
|
-
|
|
649
|
-
|
|
650
|
-
|
|
651
|
-
|
|
652
|
-
|
|
653
|
-
|
|
654
|
-
|
|
655
|
-
|
|
656
|
-
|
|
657
|
-
|
|
658
|
-
|
|
659
|
-
|
|
660
|
-
|
|
661
|
-
|
|
662
|
-
|
|
663
|
-
|
|
664
|
-
|
|
665
|
-
|
|
666
|
-
|
|
667
|
-
|
|
668
|
-
|
|
669
|
-
|
|
839
|
+
const { client } = useUserSession();
|
|
840
|
+
const params = useParams();
|
|
841
|
+
const collection = params.collection;
|
|
842
|
+
const name = params.name;
|
|
843
|
+
const { baseUrl } = useAdminContext();
|
|
844
|
+
const { data: interaction, error } = useFetch(() => client.getRawJWT().then((token) => fetch(`${baseUrl}/interactions/${collection}/${name}`, { headers: { Authorization: `Bearer ${token}` } })).then((r) => {
|
|
845
|
+
if (!r.ok) throw new Error(`Failed to load interaction: ${r.statusText}`);
|
|
846
|
+
return r.json();
|
|
847
|
+
}), [
|
|
848
|
+
baseUrl,
|
|
849
|
+
collection,
|
|
850
|
+
name
|
|
851
|
+
]);
|
|
852
|
+
if (error) return /* @__PURE__ */ jsxs("div", {
|
|
853
|
+
className: "p-6 text-destructive",
|
|
854
|
+
children: [
|
|
855
|
+
"Failed to load interaction “",
|
|
856
|
+
name,
|
|
857
|
+
"”."
|
|
858
|
+
]
|
|
859
|
+
});
|
|
860
|
+
if (!interaction) return /* @__PURE__ */ jsx("div", {
|
|
861
|
+
className: "flex h-64 items-center justify-center text-muted-foreground",
|
|
862
|
+
children: /* @__PURE__ */ jsx(Spinner, {})
|
|
863
|
+
});
|
|
864
|
+
const { agent_runner_options } = interaction;
|
|
865
|
+
const hasAgentFlags = agent_runner_options && (agent_runner_options.is_agent || agent_runner_options.is_tool || agent_runner_options.is_skill);
|
|
866
|
+
return /* @__PURE__ */ jsxs(DetailPage, {
|
|
867
|
+
type: "interaction",
|
|
868
|
+
title: interaction.title || interaction.name,
|
|
869
|
+
description: interaction.description,
|
|
870
|
+
tags: interaction.tags,
|
|
871
|
+
backHref: `/interactions/${collection}`,
|
|
872
|
+
children: [
|
|
873
|
+
interaction.prompts && interaction.prompts.length > 0 && /* @__PURE__ */ jsxs("div", {
|
|
874
|
+
className: "mb-8",
|
|
875
|
+
children: [/* @__PURE__ */ jsx("h2", {
|
|
876
|
+
className: "mb-3 text-lg font-semibold text-foreground",
|
|
877
|
+
children: "Prompts"
|
|
878
|
+
}), interaction.prompts.map((prompt) => /* @__PURE__ */ jsx(Card, {
|
|
879
|
+
className: "mb-3",
|
|
880
|
+
children: /* @__PURE__ */ jsxs(CardContent, {
|
|
881
|
+
className: "p-4",
|
|
882
|
+
children: [/* @__PURE__ */ jsxs("div", {
|
|
883
|
+
className: "mb-2 flex items-center gap-2",
|
|
884
|
+
children: [/* @__PURE__ */ jsx("span", {
|
|
885
|
+
className: `rounded-full px-2 py-0.5 text-[0.7rem] font-semibold uppercase tracking-wide ${ROLE_VARIANTS[prompt.role] ?? ""}`,
|
|
886
|
+
children: prompt.role
|
|
887
|
+
}), prompt.name && /* @__PURE__ */ jsx("span", {
|
|
888
|
+
className: "text-sm italic text-muted-foreground",
|
|
889
|
+
children: prompt.name
|
|
890
|
+
})]
|
|
891
|
+
}), /* @__PURE__ */ jsx("pre", {
|
|
892
|
+
className: "whitespace-pre-wrap wrap-break-word rounded-lg border border-border bg-muted-background p-4 font-mono text-sm text-foreground",
|
|
893
|
+
children: prompt.content
|
|
894
|
+
})]
|
|
895
|
+
})
|
|
896
|
+
}, `${prompt.role}-${prompt.name ?? ""}`))]
|
|
897
|
+
}),
|
|
898
|
+
interaction.result_schema && /* @__PURE__ */ jsxs("div", {
|
|
899
|
+
className: "mb-8",
|
|
900
|
+
children: [/* @__PURE__ */ jsx("h2", {
|
|
901
|
+
className: "mb-3 text-lg font-semibold text-foreground",
|
|
902
|
+
children: "Result Schema"
|
|
903
|
+
}), /* @__PURE__ */ jsx("pre", {
|
|
904
|
+
className: "whitespace-pre-wrap wrap-break-word rounded-lg border border-border bg-muted-background p-4 font-mono text-sm text-foreground",
|
|
905
|
+
children: JSON.stringify(interaction.result_schema, null, 2)
|
|
906
|
+
})]
|
|
907
|
+
}),
|
|
908
|
+
hasAgentFlags && /* @__PURE__ */ jsxs("div", {
|
|
909
|
+
className: "mb-8",
|
|
910
|
+
children: [/* @__PURE__ */ jsx("h2", {
|
|
911
|
+
className: "mb-3 text-lg font-semibold text-foreground",
|
|
912
|
+
children: "Agent Runner"
|
|
913
|
+
}), /* @__PURE__ */ jsxs("div", {
|
|
914
|
+
className: "flex flex-wrap gap-2",
|
|
915
|
+
children: [
|
|
916
|
+
agent_runner_options.is_agent && /* @__PURE__ */ jsx(Badge, {
|
|
917
|
+
variant: "success",
|
|
918
|
+
children: "Agent"
|
|
919
|
+
}),
|
|
920
|
+
agent_runner_options.is_tool && /* @__PURE__ */ jsx(Badge, {
|
|
921
|
+
variant: "success",
|
|
922
|
+
children: "Tool"
|
|
923
|
+
}),
|
|
924
|
+
agent_runner_options.is_skill && /* @__PURE__ */ jsx(Badge, {
|
|
925
|
+
variant: "success",
|
|
926
|
+
children: "Skill"
|
|
927
|
+
})
|
|
928
|
+
]
|
|
929
|
+
})]
|
|
930
|
+
})
|
|
931
|
+
]
|
|
932
|
+
});
|
|
670
933
|
}
|
|
934
|
+
//#endregion
|
|
935
|
+
//#region src/pages/SkillCollection.tsx
|
|
936
|
+
/** Strip the learn_ prefix added by the SDK when exposing skills as tools. */
|
|
671
937
|
function skillDisplayName(name) {
|
|
672
|
-
|
|
938
|
+
return name.startsWith("learn_") ? name.slice(6) : name;
|
|
673
939
|
}
|
|
674
940
|
function SkillCollection() {
|
|
675
|
-
|
|
676
|
-
|
|
677
|
-
|
|
678
|
-
|
|
679
|
-
|
|
680
|
-
|
|
681
|
-
|
|
682
|
-
|
|
683
|
-
|
|
684
|
-
|
|
685
|
-
|
|
686
|
-
|
|
687
|
-
|
|
688
|
-
|
|
689
|
-
|
|
690
|
-
|
|
691
|
-
|
|
692
|
-
|
|
693
|
-
|
|
694
|
-
|
|
695
|
-
|
|
696
|
-
|
|
697
|
-
|
|
698
|
-
|
|
699
|
-
|
|
700
|
-
|
|
701
|
-
|
|
702
|
-
|
|
703
|
-
|
|
704
|
-
|
|
705
|
-
|
|
706
|
-
|
|
707
|
-
|
|
708
|
-
|
|
709
|
-
|
|
710
|
-
|
|
711
|
-
|
|
712
|
-
|
|
713
|
-
|
|
714
|
-
|
|
715
|
-
|
|
716
|
-
|
|
717
|
-
|
|
718
|
-
|
|
719
|
-
|
|
720
|
-
|
|
721
|
-
|
|
722
|
-
|
|
723
|
-
|
|
724
|
-
|
|
725
|
-
|
|
726
|
-
|
|
727
|
-
|
|
941
|
+
const collection = useParams("collection");
|
|
942
|
+
const { baseUrl } = useAdminContext();
|
|
943
|
+
const { data, error } = useFetch(() => fetch(`${baseUrl}/skills/${collection}`).then((r) => {
|
|
944
|
+
if (!r.ok) throw new Error(`Failed to load collection: ${r.statusText}`);
|
|
945
|
+
return r.json();
|
|
946
|
+
}), [baseUrl, collection]);
|
|
947
|
+
const { data: widgetsData } = useFetch(() => fetch(`${baseUrl}/package?scope=widgets`).then((r) => r.ok ? r.json() : { widgets: {} }), [baseUrl]);
|
|
948
|
+
const collectionWidgets = useMemo(() => {
|
|
949
|
+
if (!widgetsData?.widgets) return [];
|
|
950
|
+
return Object.entries(widgetsData.widgets).filter(([_, w]) => w.collection === collection).map(([name, w]) => ({
|
|
951
|
+
name,
|
|
952
|
+
...w
|
|
953
|
+
}));
|
|
954
|
+
}, [widgetsData, collection]);
|
|
955
|
+
if (error) return /* @__PURE__ */ jsxs("div", {
|
|
956
|
+
className: "p-6 text-destructive",
|
|
957
|
+
children: [
|
|
958
|
+
"Failed to load skill collection “",
|
|
959
|
+
collection,
|
|
960
|
+
"”."
|
|
961
|
+
]
|
|
962
|
+
});
|
|
963
|
+
if (!data) return /* @__PURE__ */ jsx("div", {
|
|
964
|
+
className: "flex h-64 items-center justify-center text-muted-foreground",
|
|
965
|
+
children: /* @__PURE__ */ jsx(Spinner, {})
|
|
966
|
+
});
|
|
967
|
+
return /* @__PURE__ */ jsxs(DetailPage, {
|
|
968
|
+
type: "skill",
|
|
969
|
+
title: data.title || collection,
|
|
970
|
+
description: data.description || `${data.tools.length} skill${data.tools.length !== 1 ? "s" : ""} in this collection.`,
|
|
971
|
+
children: [collectionWidgets.length > 0 && /* @__PURE__ */ jsxs("div", {
|
|
972
|
+
className: "mb-8",
|
|
973
|
+
children: [/* @__PURE__ */ jsx("h2", {
|
|
974
|
+
className: "mb-3 text-lg font-semibold text-foreground",
|
|
975
|
+
children: "Widgets"
|
|
976
|
+
}), /* @__PURE__ */ jsx("div", {
|
|
977
|
+
className: "flex flex-wrap gap-2",
|
|
978
|
+
children: collectionWidgets.map((w) => /* @__PURE__ */ jsxs(Badge, {
|
|
979
|
+
variant: "success",
|
|
980
|
+
children: [w.name, /* @__PURE__ */ jsxs("span", {
|
|
981
|
+
className: "ml-2 font-mono text-xs opacity-70",
|
|
982
|
+
children: [
|
|
983
|
+
"(skill: ",
|
|
984
|
+
w.skill,
|
|
985
|
+
")"
|
|
986
|
+
]
|
|
987
|
+
})]
|
|
988
|
+
}, w.name))
|
|
989
|
+
})]
|
|
990
|
+
}), /* @__PURE__ */ jsx("div", {
|
|
991
|
+
className: "grid grid-cols-1 gap-6 sm:grid-cols-2 lg:grid-cols-3",
|
|
992
|
+
children: data.tools.map((skill) => {
|
|
993
|
+
const displayName = skillDisplayName(skill.name);
|
|
994
|
+
return /* @__PURE__ */ jsx(NavLink, {
|
|
995
|
+
href: `/skills/${collection}/${displayName}`,
|
|
996
|
+
className: "block no-underline",
|
|
997
|
+
children: /* @__PURE__ */ jsx(Card, {
|
|
998
|
+
className: "cursor-pointer transition-all hover:-translate-y-0.5 hover:shadow-md",
|
|
999
|
+
children: /* @__PURE__ */ jsxs(CardContent, {
|
|
1000
|
+
className: "p-5",
|
|
1001
|
+
children: [
|
|
1002
|
+
/* @__PURE__ */ jsx("span", {
|
|
1003
|
+
className: `mb-2 inline-block rounded-full px-2 py-0.5 text-[0.7rem] font-semibold uppercase tracking-wide ${TYPE_VARIANTS.skill}`,
|
|
1004
|
+
children: "skill"
|
|
1005
|
+
}),
|
|
1006
|
+
/* @__PURE__ */ jsx("div", {
|
|
1007
|
+
className: "font-semibold text-card-foreground",
|
|
1008
|
+
children: displayName
|
|
1009
|
+
}),
|
|
1010
|
+
/* @__PURE__ */ jsx("div", {
|
|
1011
|
+
className: "mt-1 text-sm text-muted-foreground",
|
|
1012
|
+
children: skill.description || "No description"
|
|
1013
|
+
}),
|
|
1014
|
+
skill.tools && skill.tools.length > 0 && /* @__PURE__ */ jsx("div", {
|
|
1015
|
+
className: "mt-2 flex flex-wrap gap-1",
|
|
1016
|
+
children: skill.tools.map((t) => /* @__PURE__ */ jsx(Badge, { children: t }, t))
|
|
1017
|
+
})
|
|
1018
|
+
]
|
|
1019
|
+
})
|
|
1020
|
+
})
|
|
1021
|
+
}, skill.name);
|
|
1022
|
+
})
|
|
1023
|
+
})]
|
|
1024
|
+
});
|
|
728
1025
|
}
|
|
1026
|
+
//#endregion
|
|
1027
|
+
//#region src/pages/SkillDetail.tsx
|
|
729
1028
|
function SkillDetail() {
|
|
730
|
-
|
|
731
|
-
|
|
732
|
-
|
|
733
|
-
|
|
734
|
-
|
|
735
|
-
|
|
736
|
-
|
|
737
|
-
|
|
738
|
-
|
|
739
|
-
|
|
740
|
-
|
|
741
|
-
|
|
742
|
-
|
|
743
|
-
|
|
744
|
-
|
|
745
|
-
|
|
746
|
-
|
|
747
|
-
|
|
748
|
-
|
|
749
|
-
|
|
750
|
-
|
|
751
|
-
|
|
752
|
-
|
|
753
|
-
|
|
754
|
-
|
|
755
|
-
|
|
756
|
-
|
|
757
|
-
|
|
758
|
-
|
|
759
|
-
|
|
760
|
-
|
|
761
|
-
|
|
762
|
-
|
|
763
|
-
|
|
764
|
-
|
|
765
|
-
|
|
766
|
-
|
|
767
|
-
|
|
768
|
-
|
|
769
|
-
|
|
770
|
-
|
|
771
|
-
|
|
772
|
-
|
|
773
|
-
|
|
774
|
-
|
|
775
|
-
|
|
776
|
-
|
|
777
|
-
|
|
778
|
-
|
|
779
|
-
|
|
780
|
-
|
|
781
|
-
|
|
782
|
-
|
|
783
|
-
|
|
784
|
-
|
|
785
|
-
|
|
786
|
-
|
|
787
|
-
|
|
1029
|
+
const params = useParams();
|
|
1030
|
+
const collection = params.collection;
|
|
1031
|
+
const name = params.name;
|
|
1032
|
+
const { baseUrl } = useAdminContext();
|
|
1033
|
+
const { data: skill, error } = useFetch(() => fetch(`${baseUrl}/skills/${collection}/${name}`).then((r) => {
|
|
1034
|
+
if (!r.ok) throw new Error(`Failed to load skill: ${r.statusText}`);
|
|
1035
|
+
return r.json();
|
|
1036
|
+
}), [
|
|
1037
|
+
baseUrl,
|
|
1038
|
+
collection,
|
|
1039
|
+
name
|
|
1040
|
+
]);
|
|
1041
|
+
if (error) return /* @__PURE__ */ jsxs("div", {
|
|
1042
|
+
className: "p-6 text-destructive",
|
|
1043
|
+
children: [
|
|
1044
|
+
"Failed to load skill “",
|
|
1045
|
+
name,
|
|
1046
|
+
"”."
|
|
1047
|
+
]
|
|
1048
|
+
});
|
|
1049
|
+
if (!skill) return /* @__PURE__ */ jsx("div", {
|
|
1050
|
+
className: "flex h-64 items-center justify-center text-muted-foreground",
|
|
1051
|
+
children: /* @__PURE__ */ jsx(Spinner, {})
|
|
1052
|
+
});
|
|
1053
|
+
return /* @__PURE__ */ jsxs(DetailPage, {
|
|
1054
|
+
type: "skill",
|
|
1055
|
+
title: skill.title || skill.name,
|
|
1056
|
+
description: skill.description,
|
|
1057
|
+
backHref: `/skills/${collection}`,
|
|
1058
|
+
children: [
|
|
1059
|
+
skill.widgets && skill.widgets.length > 0 && /* @__PURE__ */ jsxs("div", {
|
|
1060
|
+
className: "mb-8",
|
|
1061
|
+
children: [/* @__PURE__ */ jsx("h2", {
|
|
1062
|
+
className: "mb-3 text-lg font-semibold text-foreground",
|
|
1063
|
+
children: "Widgets"
|
|
1064
|
+
}), /* @__PURE__ */ jsx("div", {
|
|
1065
|
+
className: "flex flex-wrap gap-2",
|
|
1066
|
+
children: skill.widgets.map((w) => /* @__PURE__ */ jsx(Badge, {
|
|
1067
|
+
variant: "success",
|
|
1068
|
+
children: w
|
|
1069
|
+
}, w))
|
|
1070
|
+
})]
|
|
1071
|
+
}),
|
|
1072
|
+
skill.scripts && skill.scripts.length > 0 && /* @__PURE__ */ jsxs("div", {
|
|
1073
|
+
className: "mb-8",
|
|
1074
|
+
children: [/* @__PURE__ */ jsx("h2", {
|
|
1075
|
+
className: "mb-3 text-lg font-semibold text-foreground",
|
|
1076
|
+
children: "Scripts"
|
|
1077
|
+
}), /* @__PURE__ */ jsx("div", {
|
|
1078
|
+
className: "flex flex-wrap gap-2",
|
|
1079
|
+
children: skill.scripts.map((s) => /* @__PURE__ */ jsx(Badge, {
|
|
1080
|
+
variant: "success",
|
|
1081
|
+
children: s
|
|
1082
|
+
}, s))
|
|
1083
|
+
})]
|
|
1084
|
+
}),
|
|
1085
|
+
skill.tools && skill.tools.length > 0 && /* @__PURE__ */ jsxs("div", {
|
|
1086
|
+
className: "mb-8",
|
|
1087
|
+
children: [/* @__PURE__ */ jsx("h2", {
|
|
1088
|
+
className: "mb-3 text-lg font-semibold text-foreground",
|
|
1089
|
+
children: "Related Tools"
|
|
1090
|
+
}), /* @__PURE__ */ jsx("div", {
|
|
1091
|
+
className: "flex flex-wrap gap-2",
|
|
1092
|
+
children: skill.tools.map((t) => /* @__PURE__ */ jsx(Badge, {
|
|
1093
|
+
variant: "success",
|
|
1094
|
+
children: t
|
|
1095
|
+
}, t))
|
|
1096
|
+
})]
|
|
1097
|
+
}),
|
|
1098
|
+
skill.execution && /* @__PURE__ */ jsxs("div", {
|
|
1099
|
+
className: "mb-8",
|
|
1100
|
+
children: [/* @__PURE__ */ jsx("h2", {
|
|
1101
|
+
className: "mb-3 text-lg font-semibold text-foreground",
|
|
1102
|
+
children: "Execution"
|
|
1103
|
+
}), /* @__PURE__ */ jsxs("div", {
|
|
1104
|
+
className: "flex flex-wrap gap-2",
|
|
1105
|
+
children: [/* @__PURE__ */ jsx(Badge, {
|
|
1106
|
+
variant: "success",
|
|
1107
|
+
children: skill.execution.language
|
|
1108
|
+
}), skill.execution.packages?.map((p) => /* @__PURE__ */ jsx(Badge, {
|
|
1109
|
+
variant: "success",
|
|
1110
|
+
children: p
|
|
1111
|
+
}, p))]
|
|
1112
|
+
})]
|
|
1113
|
+
}),
|
|
1114
|
+
/* @__PURE__ */ jsxs("div", {
|
|
1115
|
+
className: "mb-8",
|
|
1116
|
+
children: [/* @__PURE__ */ jsxs("h2", {
|
|
1117
|
+
className: "mb-3 text-lg font-semibold text-foreground",
|
|
1118
|
+
children: ["Instructions", skill.content_type === "jst" && /* @__PURE__ */ jsx(Badge, {
|
|
1119
|
+
className: "ml-2",
|
|
1120
|
+
children: "JST template"
|
|
1121
|
+
})]
|
|
1122
|
+
}), /* @__PURE__ */ jsx("pre", {
|
|
1123
|
+
className: "whitespace-pre-wrap wrap-break-word rounded-lg border border-border bg-muted-background p-4 font-mono text-sm text-foreground",
|
|
1124
|
+
children: skill.instructions
|
|
1125
|
+
})]
|
|
1126
|
+
}),
|
|
1127
|
+
skill.input_schema && /* @__PURE__ */ jsxs("div", {
|
|
1128
|
+
className: "mb-8",
|
|
1129
|
+
children: [/* @__PURE__ */ jsx("h2", {
|
|
1130
|
+
className: "mb-3 text-lg font-semibold text-foreground",
|
|
1131
|
+
children: "Input Schema"
|
|
1132
|
+
}), /* @__PURE__ */ jsx("pre", {
|
|
1133
|
+
className: "whitespace-pre-wrap wrap-break-word rounded-lg border border-border bg-muted-background p-4 font-mono text-sm text-foreground",
|
|
1134
|
+
children: JSON.stringify(skill.input_schema, null, 2)
|
|
1135
|
+
})]
|
|
1136
|
+
})
|
|
1137
|
+
]
|
|
1138
|
+
});
|
|
788
1139
|
}
|
|
1140
|
+
//#endregion
|
|
1141
|
+
//#region src/pages/TemplateCollection.tsx
|
|
789
1142
|
function TemplateCollection() {
|
|
790
|
-
|
|
791
|
-
|
|
792
|
-
|
|
793
|
-
|
|
794
|
-
|
|
795
|
-
|
|
796
|
-
|
|
797
|
-
|
|
798
|
-
|
|
799
|
-
|
|
800
|
-
|
|
801
|
-
|
|
802
|
-
|
|
803
|
-
|
|
804
|
-
|
|
805
|
-
|
|
806
|
-
|
|
807
|
-
|
|
808
|
-
|
|
809
|
-
|
|
810
|
-
|
|
811
|
-
|
|
812
|
-
|
|
813
|
-
|
|
814
|
-
|
|
815
|
-
|
|
816
|
-
|
|
817
|
-
|
|
818
|
-
|
|
819
|
-
|
|
820
|
-
|
|
821
|
-
|
|
822
|
-
|
|
823
|
-
|
|
824
|
-
|
|
825
|
-
|
|
826
|
-
|
|
1143
|
+
const collection = useParams("collection");
|
|
1144
|
+
const { baseUrl } = useAdminContext();
|
|
1145
|
+
const { data: templates, error } = useFetch(() => fetch(`${baseUrl}/templates/${collection}`).then((r) => {
|
|
1146
|
+
if (!r.ok) throw new Error(`Failed to load collection: ${r.statusText}`);
|
|
1147
|
+
return r.json();
|
|
1148
|
+
}), [baseUrl, collection]);
|
|
1149
|
+
if (error) return /* @__PURE__ */ jsxs("div", {
|
|
1150
|
+
className: "p-6 text-destructive",
|
|
1151
|
+
children: [
|
|
1152
|
+
"Failed to load template collection “",
|
|
1153
|
+
collection,
|
|
1154
|
+
"”."
|
|
1155
|
+
]
|
|
1156
|
+
});
|
|
1157
|
+
if (!templates) return /* @__PURE__ */ jsx("div", {
|
|
1158
|
+
className: "flex h-64 items-center justify-center text-muted-foreground",
|
|
1159
|
+
children: /* @__PURE__ */ jsx(Spinner, {})
|
|
1160
|
+
});
|
|
1161
|
+
return /* @__PURE__ */ jsx(DetailPage, {
|
|
1162
|
+
type: "template",
|
|
1163
|
+
title: collection,
|
|
1164
|
+
description: `${templates.length} template${templates.length !== 1 ? "s" : ""} in this collection.`,
|
|
1165
|
+
children: /* @__PURE__ */ jsx("div", {
|
|
1166
|
+
className: "grid grid-cols-1 gap-6 sm:grid-cols-2 lg:grid-cols-3",
|
|
1167
|
+
children: templates.map((tmpl) => /* @__PURE__ */ jsx(NavLink, {
|
|
1168
|
+
href: `/templates/${collection}/${tmpl.name}`,
|
|
1169
|
+
className: "no-underline",
|
|
1170
|
+
children: /* @__PURE__ */ jsx(Card, {
|
|
1171
|
+
className: "h-full transition-all hover:-translate-y-0.5 hover:shadow-md",
|
|
1172
|
+
children: /* @__PURE__ */ jsxs(CardContent, {
|
|
1173
|
+
className: "p-5",
|
|
1174
|
+
children: [
|
|
1175
|
+
/* @__PURE__ */ jsx("span", {
|
|
1176
|
+
className: `mb-2 inline-block rounded-full px-2 py-0.5 text-[0.7rem] font-semibold uppercase tracking-wide ${TYPE_VARIANTS.template}`,
|
|
1177
|
+
children: tmpl.type || "template"
|
|
1178
|
+
}),
|
|
1179
|
+
/* @__PURE__ */ jsx("div", {
|
|
1180
|
+
className: "font-semibold text-card-foreground",
|
|
1181
|
+
children: tmpl.title || tmpl.name
|
|
1182
|
+
}),
|
|
1183
|
+
/* @__PURE__ */ jsx("div", {
|
|
1184
|
+
className: "mt-1 text-sm text-muted-foreground",
|
|
1185
|
+
children: tmpl.description || "No description"
|
|
1186
|
+
}),
|
|
1187
|
+
tmpl.tags && tmpl.tags.length > 0 && /* @__PURE__ */ jsx("div", {
|
|
1188
|
+
className: "mt-3 flex flex-wrap gap-1.5",
|
|
1189
|
+
children: tmpl.tags.map((tag) => /* @__PURE__ */ jsx(Badge, {
|
|
1190
|
+
variant: "default",
|
|
1191
|
+
children: tag
|
|
1192
|
+
}, tag))
|
|
1193
|
+
})
|
|
1194
|
+
]
|
|
1195
|
+
})
|
|
1196
|
+
})
|
|
1197
|
+
}, tmpl.name))
|
|
1198
|
+
})
|
|
1199
|
+
});
|
|
827
1200
|
}
|
|
1201
|
+
//#endregion
|
|
1202
|
+
//#region src/pages/TemplateDetail.tsx
|
|
828
1203
|
function TemplateDetail() {
|
|
829
|
-
|
|
830
|
-
|
|
831
|
-
|
|
832
|
-
|
|
833
|
-
|
|
834
|
-
|
|
835
|
-
|
|
836
|
-
|
|
837
|
-
|
|
838
|
-
|
|
839
|
-
|
|
840
|
-
|
|
841
|
-
|
|
842
|
-
|
|
843
|
-
|
|
844
|
-
|
|
845
|
-
|
|
846
|
-
|
|
847
|
-
|
|
848
|
-
|
|
849
|
-
|
|
850
|
-
|
|
851
|
-
|
|
852
|
-
|
|
853
|
-
|
|
854
|
-
|
|
855
|
-
|
|
856
|
-
|
|
857
|
-
|
|
858
|
-
|
|
859
|
-
|
|
860
|
-
|
|
861
|
-
|
|
862
|
-
|
|
863
|
-
|
|
864
|
-
|
|
865
|
-
|
|
866
|
-
|
|
1204
|
+
const params = useParams();
|
|
1205
|
+
const collection = params.collection;
|
|
1206
|
+
const name = params.name;
|
|
1207
|
+
const { baseUrl } = useAdminContext();
|
|
1208
|
+
const { data: template, error } = useFetch(() => fetch(`${baseUrl}/templates/${collection}/${name}`).then((r) => {
|
|
1209
|
+
if (!r.ok) throw new Error(`Failed to load template: ${r.statusText}`);
|
|
1210
|
+
return r.json();
|
|
1211
|
+
}), [
|
|
1212
|
+
baseUrl,
|
|
1213
|
+
collection,
|
|
1214
|
+
name
|
|
1215
|
+
]);
|
|
1216
|
+
if (error) return /* @__PURE__ */ jsxs("div", {
|
|
1217
|
+
className: "p-6 text-destructive",
|
|
1218
|
+
children: [
|
|
1219
|
+
"Failed to load template “",
|
|
1220
|
+
name,
|
|
1221
|
+
"”."
|
|
1222
|
+
]
|
|
1223
|
+
});
|
|
1224
|
+
if (!template) return /* @__PURE__ */ jsx("div", {
|
|
1225
|
+
className: "flex h-64 items-center justify-center text-muted-foreground",
|
|
1226
|
+
children: /* @__PURE__ */ jsx(Spinner, {})
|
|
1227
|
+
});
|
|
1228
|
+
return /* @__PURE__ */ jsxs(DetailPage, {
|
|
1229
|
+
type: "template",
|
|
1230
|
+
title: template.title || template.name,
|
|
1231
|
+
description: template.description,
|
|
1232
|
+
tags: template.tags,
|
|
1233
|
+
backHref: `/templates/${collection}`,
|
|
1234
|
+
children: [
|
|
1235
|
+
/* @__PURE__ */ jsx("div", {
|
|
1236
|
+
className: "mb-8",
|
|
1237
|
+
children: /* @__PURE__ */ jsx("div", {
|
|
1238
|
+
className: "flex flex-wrap gap-2",
|
|
1239
|
+
children: /* @__PURE__ */ jsx(Badge, {
|
|
1240
|
+
variant: "success",
|
|
1241
|
+
children: template.type
|
|
1242
|
+
})
|
|
1243
|
+
})
|
|
1244
|
+
}),
|
|
1245
|
+
template.assets && template.assets.length > 0 && /* @__PURE__ */ jsxs("div", {
|
|
1246
|
+
className: "mb-8",
|
|
1247
|
+
children: [/* @__PURE__ */ jsx("h2", {
|
|
1248
|
+
className: "mb-3 text-lg font-semibold text-foreground",
|
|
1249
|
+
children: "Assets"
|
|
1250
|
+
}), /* @__PURE__ */ jsx("div", {
|
|
1251
|
+
className: "flex flex-wrap gap-2",
|
|
1252
|
+
children: template.assets.map((asset) => /* @__PURE__ */ jsx(Badge, {
|
|
1253
|
+
variant: "success",
|
|
1254
|
+
children: asset.split("/").pop()
|
|
1255
|
+
}, asset))
|
|
1256
|
+
})]
|
|
1257
|
+
}),
|
|
1258
|
+
/* @__PURE__ */ jsxs("div", {
|
|
1259
|
+
className: "mb-8",
|
|
1260
|
+
children: [/* @__PURE__ */ jsx("h2", {
|
|
1261
|
+
className: "mb-3 text-lg font-semibold text-foreground",
|
|
1262
|
+
children: "Instructions"
|
|
1263
|
+
}), /* @__PURE__ */ jsx("pre", {
|
|
1264
|
+
className: "whitespace-pre-wrap wrap-break-word rounded-lg border border-border bg-muted-background p-4 font-mono text-sm text-foreground",
|
|
1265
|
+
children: template.instructions
|
|
1266
|
+
})]
|
|
1267
|
+
})
|
|
1268
|
+
]
|
|
1269
|
+
});
|
|
867
1270
|
}
|
|
1271
|
+
//#endregion
|
|
1272
|
+
//#region src/pages/ToolCollection.tsx
|
|
868
1273
|
function ToolCollection() {
|
|
869
|
-
|
|
870
|
-
|
|
871
|
-
|
|
872
|
-
|
|
873
|
-
|
|
874
|
-
|
|
875
|
-
|
|
876
|
-
|
|
877
|
-
|
|
878
|
-
|
|
879
|
-
|
|
880
|
-
|
|
881
|
-
|
|
882
|
-
|
|
883
|
-
|
|
884
|
-
|
|
885
|
-
|
|
886
|
-
|
|
887
|
-
|
|
888
|
-
|
|
889
|
-
|
|
890
|
-
|
|
891
|
-
|
|
892
|
-
|
|
893
|
-
|
|
894
|
-
|
|
895
|
-
|
|
896
|
-
|
|
897
|
-
|
|
898
|
-
|
|
899
|
-
|
|
1274
|
+
const collection = useParams("collection");
|
|
1275
|
+
const { baseUrl } = useAdminContext();
|
|
1276
|
+
const { data, error } = useFetch(() => fetch(`${baseUrl}/tools/${collection}`).then((r) => {
|
|
1277
|
+
if (!r.ok) throw new Error(`Failed to load collection: ${r.statusText}`);
|
|
1278
|
+
return r.json();
|
|
1279
|
+
}), [baseUrl, collection]);
|
|
1280
|
+
if (error) return /* @__PURE__ */ jsxs("div", {
|
|
1281
|
+
className: "p-6 text-destructive",
|
|
1282
|
+
children: [
|
|
1283
|
+
"Failed to load tool collection “",
|
|
1284
|
+
collection,
|
|
1285
|
+
"”."
|
|
1286
|
+
]
|
|
1287
|
+
});
|
|
1288
|
+
if (!data) return /* @__PURE__ */ jsx("div", {
|
|
1289
|
+
className: "flex h-64 items-center justify-center text-muted-foreground",
|
|
1290
|
+
children: /* @__PURE__ */ jsx(Spinner, {})
|
|
1291
|
+
});
|
|
1292
|
+
return /* @__PURE__ */ jsx(DetailPage, {
|
|
1293
|
+
type: "tool",
|
|
1294
|
+
title: data.title || collection,
|
|
1295
|
+
description: data.description || `${data.tools.length} tool${data.tools.length !== 1 ? "s" : ""} in this collection.`,
|
|
1296
|
+
children: data.tools.map((tool) => /* @__PURE__ */ jsx(Card, {
|
|
1297
|
+
className: "mb-4",
|
|
1298
|
+
children: /* @__PURE__ */ jsxs(CardContent, {
|
|
1299
|
+
className: "p-5",
|
|
1300
|
+
children: [
|
|
1301
|
+
/* @__PURE__ */ jsxs("div", {
|
|
1302
|
+
className: "mb-2 flex items-center gap-2",
|
|
1303
|
+
children: [/* @__PURE__ */ jsx("span", {
|
|
1304
|
+
className: `inline-block rounded-full px-2 py-0.5 text-[0.7rem] font-semibold uppercase tracking-wide ${TYPE_VARIANTS.tool}`,
|
|
1305
|
+
children: "tool"
|
|
1306
|
+
}), /* @__PURE__ */ jsx("span", {
|
|
1307
|
+
className: "font-semibold text-card-foreground",
|
|
1308
|
+
children: tool.name
|
|
1309
|
+
})]
|
|
1310
|
+
}),
|
|
1311
|
+
/* @__PURE__ */ jsx("div", {
|
|
1312
|
+
className: "text-sm text-muted-foreground",
|
|
1313
|
+
children: tool.description || "No description"
|
|
1314
|
+
}),
|
|
1315
|
+
tool.input_schema && /* @__PURE__ */ jsx("pre", {
|
|
1316
|
+
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",
|
|
1317
|
+
children: JSON.stringify(tool.input_schema, null, 2)
|
|
1318
|
+
})
|
|
1319
|
+
]
|
|
1320
|
+
})
|
|
1321
|
+
}, tool.name))
|
|
1322
|
+
});
|
|
900
1323
|
}
|
|
1324
|
+
//#endregion
|
|
1325
|
+
//#region src/pages/TypeCollection.tsx
|
|
901
1326
|
function TypeCollection() {
|
|
902
|
-
|
|
903
|
-
|
|
904
|
-
|
|
905
|
-
|
|
906
|
-
|
|
907
|
-
|
|
908
|
-
|
|
909
|
-
|
|
910
|
-
|
|
911
|
-
|
|
912
|
-
|
|
913
|
-
|
|
914
|
-
|
|
915
|
-
|
|
916
|
-
|
|
917
|
-
|
|
918
|
-
|
|
919
|
-
|
|
920
|
-
|
|
921
|
-
|
|
922
|
-
|
|
923
|
-
|
|
924
|
-
|
|
925
|
-
|
|
926
|
-
|
|
927
|
-
|
|
928
|
-
|
|
929
|
-
|
|
930
|
-
|
|
931
|
-
|
|
932
|
-
|
|
933
|
-
|
|
934
|
-
|
|
935
|
-
|
|
936
|
-
|
|
937
|
-
|
|
938
|
-
|
|
939
|
-
|
|
940
|
-
|
|
941
|
-
|
|
942
|
-
|
|
943
|
-
|
|
944
|
-
|
|
945
|
-
|
|
946
|
-
|
|
1327
|
+
const collection = useParams("collection");
|
|
1328
|
+
const { baseUrl } = useAdminContext();
|
|
1329
|
+
const { data: types, error } = useFetch(() => fetch(`${baseUrl}/types/${collection}`).then((r) => {
|
|
1330
|
+
if (!r.ok) throw new Error(`Failed to load collection: ${r.statusText}`);
|
|
1331
|
+
return r.json();
|
|
1332
|
+
}), [baseUrl, collection]);
|
|
1333
|
+
if (error) return /* @__PURE__ */ jsxs("div", {
|
|
1334
|
+
className: "p-6 text-destructive",
|
|
1335
|
+
children: [
|
|
1336
|
+
"Failed to load type collection “",
|
|
1337
|
+
collection,
|
|
1338
|
+
"”."
|
|
1339
|
+
]
|
|
1340
|
+
});
|
|
1341
|
+
if (!types) return /* @__PURE__ */ jsx("div", {
|
|
1342
|
+
className: "flex h-64 items-center justify-center text-muted-foreground",
|
|
1343
|
+
children: /* @__PURE__ */ jsx(Spinner, {})
|
|
1344
|
+
});
|
|
1345
|
+
return /* @__PURE__ */ jsx(DetailPage, {
|
|
1346
|
+
type: "type",
|
|
1347
|
+
title: collection,
|
|
1348
|
+
description: `${types.length} content type${types.length !== 1 ? "s" : ""} in this collection.`,
|
|
1349
|
+
children: /* @__PURE__ */ jsx("div", {
|
|
1350
|
+
className: "grid grid-cols-1 gap-6 sm:grid-cols-2 lg:grid-cols-3",
|
|
1351
|
+
children: types.map((t) => {
|
|
1352
|
+
return /* @__PURE__ */ jsx(NavLink, {
|
|
1353
|
+
href: `/types/${collection}/${t.id?.split(":")[1] || t.name}`,
|
|
1354
|
+
className: "no-underline",
|
|
1355
|
+
children: /* @__PURE__ */ jsx(Card, {
|
|
1356
|
+
className: "h-full transition-all hover:-translate-y-0.5 hover:shadow-md",
|
|
1357
|
+
children: /* @__PURE__ */ jsxs(CardContent, {
|
|
1358
|
+
className: "p-5",
|
|
1359
|
+
children: [
|
|
1360
|
+
/* @__PURE__ */ jsx("span", {
|
|
1361
|
+
className: `mb-2 inline-block rounded-full px-2 py-0.5 text-[0.7rem] font-semibold uppercase tracking-wide ${TYPE_VARIANTS.type}`,
|
|
1362
|
+
children: "type"
|
|
1363
|
+
}),
|
|
1364
|
+
/* @__PURE__ */ jsx("div", {
|
|
1365
|
+
className: "font-semibold text-card-foreground",
|
|
1366
|
+
children: t.name
|
|
1367
|
+
}),
|
|
1368
|
+
/* @__PURE__ */ jsx("div", {
|
|
1369
|
+
className: "mt-1 text-sm text-muted-foreground",
|
|
1370
|
+
children: t.description || "No description"
|
|
1371
|
+
}),
|
|
1372
|
+
t.tags && t.tags.length > 0 && /* @__PURE__ */ jsx("div", {
|
|
1373
|
+
className: "mt-3 flex flex-wrap gap-1.5",
|
|
1374
|
+
children: t.tags.map((tag) => /* @__PURE__ */ jsx(Badge, {
|
|
1375
|
+
variant: "default",
|
|
1376
|
+
children: tag
|
|
1377
|
+
}, tag))
|
|
1378
|
+
}),
|
|
1379
|
+
(t.is_chunkable || t.strict_mode) && /* @__PURE__ */ jsxs("div", {
|
|
1380
|
+
className: "mt-2 truncate font-mono text-xs text-muted-foreground",
|
|
1381
|
+
children: [
|
|
1382
|
+
t.is_chunkable && "chunkable",
|
|
1383
|
+
t.is_chunkable && t.strict_mode && " · ",
|
|
1384
|
+
t.strict_mode && "strict"
|
|
1385
|
+
]
|
|
1386
|
+
})
|
|
1387
|
+
]
|
|
1388
|
+
})
|
|
1389
|
+
})
|
|
1390
|
+
}, t.name);
|
|
1391
|
+
})
|
|
1392
|
+
})
|
|
1393
|
+
});
|
|
947
1394
|
}
|
|
1395
|
+
//#endregion
|
|
1396
|
+
//#region src/pages/TypeDetail.tsx
|
|
948
1397
|
function TypeDetail() {
|
|
949
|
-
|
|
950
|
-
|
|
951
|
-
|
|
952
|
-
|
|
953
|
-
|
|
954
|
-
|
|
955
|
-
|
|
956
|
-
|
|
957
|
-
|
|
958
|
-
|
|
959
|
-
|
|
960
|
-
|
|
961
|
-
|
|
962
|
-
|
|
963
|
-
|
|
964
|
-
|
|
965
|
-
|
|
966
|
-
|
|
967
|
-
|
|
968
|
-
|
|
969
|
-
|
|
970
|
-
|
|
971
|
-
|
|
972
|
-
|
|
973
|
-
|
|
974
|
-
|
|
975
|
-
|
|
976
|
-
|
|
977
|
-
|
|
978
|
-
|
|
979
|
-
|
|
980
|
-
|
|
981
|
-
|
|
982
|
-
|
|
983
|
-
|
|
984
|
-
|
|
985
|
-
|
|
986
|
-
|
|
987
|
-
|
|
988
|
-
|
|
989
|
-
|
|
1398
|
+
const params = useParams();
|
|
1399
|
+
const collection = params.collection;
|
|
1400
|
+
const name = params.name;
|
|
1401
|
+
const { baseUrl } = useAdminContext();
|
|
1402
|
+
const { data: typeDef, error } = useFetch(() => fetch(`${baseUrl}/types/${collection}/${name}`).then((r) => {
|
|
1403
|
+
if (!r.ok) throw new Error(`Failed to load type: ${r.statusText}`);
|
|
1404
|
+
return r.json();
|
|
1405
|
+
}), [
|
|
1406
|
+
baseUrl,
|
|
1407
|
+
collection,
|
|
1408
|
+
name
|
|
1409
|
+
]);
|
|
1410
|
+
if (error) return /* @__PURE__ */ jsxs("div", {
|
|
1411
|
+
className: "p-6 text-destructive",
|
|
1412
|
+
children: [
|
|
1413
|
+
"Failed to load type “",
|
|
1414
|
+
name,
|
|
1415
|
+
"”."
|
|
1416
|
+
]
|
|
1417
|
+
});
|
|
1418
|
+
if (!typeDef) return /* @__PURE__ */ jsx("div", {
|
|
1419
|
+
className: "flex h-64 items-center justify-center text-muted-foreground",
|
|
1420
|
+
children: /* @__PURE__ */ jsx(Spinner, {})
|
|
1421
|
+
});
|
|
1422
|
+
return /* @__PURE__ */ jsxs(DetailPage, {
|
|
1423
|
+
type: "type",
|
|
1424
|
+
title: typeDef.name,
|
|
1425
|
+
description: typeDef.description,
|
|
1426
|
+
tags: typeDef.tags,
|
|
1427
|
+
backHref: `/types/${collection}`,
|
|
1428
|
+
children: [
|
|
1429
|
+
(typeDef.is_chunkable || typeDef.strict_mode) && /* @__PURE__ */ jsx("div", {
|
|
1430
|
+
className: "mb-8",
|
|
1431
|
+
children: /* @__PURE__ */ jsxs("div", {
|
|
1432
|
+
className: "flex flex-wrap gap-2",
|
|
1433
|
+
children: [typeDef.is_chunkable && /* @__PURE__ */ jsx(Badge, {
|
|
1434
|
+
variant: "success",
|
|
1435
|
+
children: "Chunkable"
|
|
1436
|
+
}), typeDef.strict_mode && /* @__PURE__ */ jsx(Badge, {
|
|
1437
|
+
variant: "success",
|
|
1438
|
+
children: "Strict Mode"
|
|
1439
|
+
})]
|
|
1440
|
+
})
|
|
1441
|
+
}),
|
|
1442
|
+
typeDef.object_schema && /* @__PURE__ */ jsxs("div", {
|
|
1443
|
+
className: "mb-8",
|
|
1444
|
+
children: [/* @__PURE__ */ jsx("h2", {
|
|
1445
|
+
className: "mb-3 text-lg font-semibold text-foreground",
|
|
1446
|
+
children: "Object Schema"
|
|
1447
|
+
}), /* @__PURE__ */ jsx("pre", {
|
|
1448
|
+
className: "whitespace-pre-wrap wrap-break-word rounded-lg border border-border bg-muted-background p-4 font-mono text-sm text-foreground",
|
|
1449
|
+
children: JSON.stringify(typeDef.object_schema, null, 2)
|
|
1450
|
+
})]
|
|
1451
|
+
}),
|
|
1452
|
+
typeDef.table_layout && typeDef.table_layout.length > 0 && /* @__PURE__ */ jsxs("div", {
|
|
1453
|
+
className: "mb-8",
|
|
1454
|
+
children: [/* @__PURE__ */ jsx("h2", {
|
|
1455
|
+
className: "mb-3 text-lg font-semibold text-foreground",
|
|
1456
|
+
children: "Table Layout"
|
|
1457
|
+
}), /* @__PURE__ */ jsx("pre", {
|
|
1458
|
+
className: "whitespace-pre-wrap wrap-break-word rounded-lg border border-border bg-muted-background p-4 font-mono text-sm text-foreground",
|
|
1459
|
+
children: JSON.stringify(typeDef.table_layout, null, 2)
|
|
1460
|
+
})]
|
|
1461
|
+
})
|
|
1462
|
+
]
|
|
1463
|
+
});
|
|
990
1464
|
}
|
|
991
|
-
|
|
992
|
-
|
|
993
|
-
|
|
994
|
-
|
|
995
|
-
|
|
996
|
-
|
|
997
|
-
|
|
998
|
-
|
|
999
|
-
|
|
1000
|
-
|
|
1001
|
-
|
|
1002
|
-
|
|
1465
|
+
//#endregion
|
|
1466
|
+
//#region src/AdminApp.tsx
|
|
1467
|
+
var routes = [
|
|
1468
|
+
{
|
|
1469
|
+
path: "/",
|
|
1470
|
+
Component: HomePage
|
|
1471
|
+
},
|
|
1472
|
+
{
|
|
1473
|
+
path: "/interactions/:collection",
|
|
1474
|
+
Component: InteractionCollection
|
|
1475
|
+
},
|
|
1476
|
+
{
|
|
1477
|
+
path: "/interactions/:collection/:name",
|
|
1478
|
+
Component: InteractionDetail
|
|
1479
|
+
},
|
|
1480
|
+
{
|
|
1481
|
+
path: "/tools/:collection",
|
|
1482
|
+
Component: ToolCollection
|
|
1483
|
+
},
|
|
1484
|
+
{
|
|
1485
|
+
path: "/activities/:collection",
|
|
1486
|
+
Component: ActivityCollection
|
|
1487
|
+
},
|
|
1488
|
+
{
|
|
1489
|
+
path: "/skills/:collection",
|
|
1490
|
+
Component: SkillCollection
|
|
1491
|
+
},
|
|
1492
|
+
{
|
|
1493
|
+
path: "/skills/:collection/:name",
|
|
1494
|
+
Component: SkillDetail
|
|
1495
|
+
},
|
|
1496
|
+
{
|
|
1497
|
+
path: "/types/:collection",
|
|
1498
|
+
Component: TypeCollection
|
|
1499
|
+
},
|
|
1500
|
+
{
|
|
1501
|
+
path: "/types/:collection/:name",
|
|
1502
|
+
Component: TypeDetail
|
|
1503
|
+
},
|
|
1504
|
+
{
|
|
1505
|
+
path: "/templates/:collection",
|
|
1506
|
+
Component: TemplateCollection
|
|
1507
|
+
},
|
|
1508
|
+
{
|
|
1509
|
+
path: "/templates/:collection/:name",
|
|
1510
|
+
Component: TemplateDetail
|
|
1511
|
+
}
|
|
1003
1512
|
];
|
|
1513
|
+
/**
|
|
1514
|
+
* Admin app shell — loads data, provides context, and renders nested routes.
|
|
1515
|
+
*
|
|
1516
|
+
* Requires a parent VertesiaShell (or equivalent providers for ThemeProvider,
|
|
1517
|
+
* UserSessionProvider, ToastProvider).
|
|
1518
|
+
*/
|
|
1004
1519
|
function AdminApp({ baseUrl = "/api" }) {
|
|
1005
|
-
|
|
1006
|
-
|
|
1007
|
-
|
|
1008
|
-
|
|
1009
|
-
|
|
1010
|
-
|
|
1011
|
-
|
|
1012
|
-
|
|
1013
|
-
|
|
1014
|
-
|
|
1015
|
-
|
|
1016
|
-
|
|
1017
|
-
|
|
1018
|
-
|
|
1019
|
-
|
|
1020
|
-
|
|
1021
|
-
|
|
1022
|
-
|
|
1023
|
-
|
|
1024
|
-
|
|
1025
|
-
|
|
1026
|
-
|
|
1027
|
-
|
|
1028
|
-
|
|
1520
|
+
const { data: serverInfo, isLoading: loadingInfo, error: infoError } = useServerInfo(baseUrl);
|
|
1521
|
+
const { data: resourceData, isLoading: loadingData, error: dataError } = useResourceData(baseUrl, serverInfo?.endpoints?.mcp);
|
|
1522
|
+
const isLoading = loadingInfo || loadingData;
|
|
1523
|
+
const error = infoError || dataError;
|
|
1524
|
+
if (isLoading) return /* @__PURE__ */ jsx("div", {
|
|
1525
|
+
className: "flex h-64 items-center justify-center text-muted-foreground",
|
|
1526
|
+
children: /* @__PURE__ */ jsx(Spinner, {})
|
|
1527
|
+
});
|
|
1528
|
+
if (error) return /* @__PURE__ */ jsx("div", {
|
|
1529
|
+
className: "p-6 text-destructive",
|
|
1530
|
+
children: "Failed to load server info. Is the API running?"
|
|
1531
|
+
});
|
|
1532
|
+
if (!serverInfo || !resourceData) return null;
|
|
1533
|
+
return /* @__PURE__ */ jsxs("div", {
|
|
1534
|
+
className: "min-h-screen bg-background text-foreground",
|
|
1535
|
+
children: [/* @__PURE__ */ jsx(AdminTopBar, { title: serverInfo.message.replace("Vertesia Tools API", "Tools Server") }), /* @__PURE__ */ jsx(AdminContext.Provider, {
|
|
1536
|
+
value: {
|
|
1537
|
+
serverInfo,
|
|
1538
|
+
collections: resourceData.collections,
|
|
1539
|
+
resources: resourceData.resources,
|
|
1540
|
+
baseUrl
|
|
1541
|
+
},
|
|
1542
|
+
children: /* @__PURE__ */ jsx(NestedRouterProvider, {
|
|
1543
|
+
routes,
|
|
1544
|
+
children: /* @__PURE__ */ jsx(RouteComponent, {})
|
|
1545
|
+
})
|
|
1546
|
+
})]
|
|
1547
|
+
});
|
|
1029
1548
|
}
|
|
1030
|
-
|
|
1031
|
-
|
|
1032
|
-
|
|
1033
|
-
|
|
1034
|
-
filterResources,
|
|
1035
|
-
useAdminContext
|
|
1036
|
-
};
|
|
1037
|
-
//# sourceMappingURL=tools-admin-ui.js.map
|
|
1549
|
+
//#endregion
|
|
1550
|
+
export { AdminApp, AdminContext, buildResourceData, filterResources, useAdminContext };
|
|
1551
|
+
|
|
1552
|
+
//# sourceMappingURL=tools-admin-ui.js.map
|