@copilotz/admin 0.3.6 → 0.3.8
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/dist/index.cjs +2394 -283
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +99 -20
- package/dist/index.d.ts +99 -20
- package/dist/index.js +2405 -285
- package/dist/index.js.map +1 -1
- package/dist/styles.css +1467 -79
- package/package.json +5 -1
package/dist/index.cjs
CHANGED
|
@@ -31,25 +31,34 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
|
|
|
31
31
|
var index_exports = {};
|
|
32
32
|
__export(index_exports, {
|
|
33
33
|
CopilotzAdmin: () => CopilotzAdmin,
|
|
34
|
+
createCollectionItem: () => createCollectionItem,
|
|
34
35
|
defaultAdminConfig: () => defaultAdminConfig,
|
|
36
|
+
deleteCollectionItem: () => deleteCollectionItem,
|
|
35
37
|
fetchAdminActivity: () => fetchAdminActivity,
|
|
36
38
|
fetchAdminAgents: () => fetchAdminAgents,
|
|
37
39
|
fetchAdminOverview: () => fetchAdminOverview,
|
|
38
40
|
fetchAdminParticipants: () => fetchAdminParticipants,
|
|
39
41
|
fetchAdminThreads: () => fetchAdminThreads,
|
|
42
|
+
fetchCollectionItem: () => fetchCollectionItem,
|
|
43
|
+
fetchCollectionItems: () => fetchCollectionItems,
|
|
44
|
+
fetchCollectionNames: () => fetchCollectionNames,
|
|
45
|
+
fetchParticipantDetail: () => fetchParticipantDetail,
|
|
46
|
+
fetchThreadEvents: () => fetchThreadEvents,
|
|
40
47
|
mergeAdminConfig: () => mergeAdminConfig,
|
|
48
|
+
updateCollectionItem: () => updateCollectionItem,
|
|
49
|
+
updateParticipant: () => updateParticipant,
|
|
41
50
|
useCopilotzAdmin: () => useCopilotzAdmin
|
|
42
51
|
});
|
|
43
52
|
module.exports = __toCommonJS(index_exports);
|
|
44
53
|
|
|
45
54
|
// src/CopilotzAdmin.tsx
|
|
46
|
-
var
|
|
55
|
+
var import_react7 = require("react");
|
|
47
56
|
|
|
48
57
|
// src/config.ts
|
|
49
58
|
var defaultAdminConfig = {
|
|
50
59
|
branding: {
|
|
51
60
|
title: "Copilotz Admin",
|
|
52
|
-
subtitle: "
|
|
61
|
+
subtitle: "Operational visibility for Copilotz clients",
|
|
53
62
|
logo: null,
|
|
54
63
|
actions: null
|
|
55
64
|
},
|
|
@@ -83,24 +92,36 @@ var defaultAdminConfig = {
|
|
|
83
92
|
scopeScoped: "Scoped",
|
|
84
93
|
configured: "Configured",
|
|
85
94
|
unconfigured: "Observed only",
|
|
86
|
-
noResults: "No results"
|
|
95
|
+
noResults: "No results",
|
|
96
|
+
eventsTitle: "Events",
|
|
97
|
+
dashboardTitle: "Dashboard",
|
|
98
|
+
collectionsTitle: "Collections",
|
|
99
|
+
collectionsEndpoint: "/v1/collections"
|
|
87
100
|
},
|
|
88
101
|
features: {
|
|
89
102
|
showOverview: true,
|
|
90
103
|
showActivity: true,
|
|
91
104
|
showThreads: true,
|
|
92
105
|
showParticipants: true,
|
|
93
|
-
showAgents: true
|
|
106
|
+
showAgents: true,
|
|
107
|
+
showEvents: true,
|
|
108
|
+
showCollections: true
|
|
94
109
|
},
|
|
95
110
|
ui: {
|
|
96
111
|
compact: false,
|
|
97
112
|
maxActivityBars: 18
|
|
98
113
|
},
|
|
114
|
+
sidebar: {
|
|
115
|
+
defaultOpen: true,
|
|
116
|
+
collapsible: "icon"
|
|
117
|
+
},
|
|
99
118
|
baseUrl: "",
|
|
100
119
|
getRequestHeaders: async () => ({}),
|
|
101
120
|
namespace: "",
|
|
102
121
|
initialRange: "7d",
|
|
103
|
-
initialInterval: "day"
|
|
122
|
+
initialInterval: "day",
|
|
123
|
+
defaultPage: "dashboard",
|
|
124
|
+
onNavigate: null
|
|
104
125
|
};
|
|
105
126
|
function mergeAdminConfig(_baseConfig, userConfig) {
|
|
106
127
|
if (!userConfig) return defaultAdminConfig;
|
|
@@ -121,11 +142,17 @@ function mergeAdminConfig(_baseConfig, userConfig) {
|
|
|
121
142
|
...defaultAdminConfig.ui,
|
|
122
143
|
...userConfig.ui
|
|
123
144
|
},
|
|
145
|
+
sidebar: {
|
|
146
|
+
...defaultAdminConfig.sidebar,
|
|
147
|
+
...userConfig.sidebar
|
|
148
|
+
},
|
|
124
149
|
baseUrl: userConfig.baseUrl ?? defaultAdminConfig.baseUrl,
|
|
125
150
|
getRequestHeaders: userConfig.getRequestHeaders ?? defaultAdminConfig.getRequestHeaders,
|
|
126
151
|
namespace: userConfig.namespace ?? defaultAdminConfig.namespace,
|
|
127
152
|
initialRange: userConfig.initialRange ?? defaultAdminConfig.initialRange,
|
|
128
|
-
initialInterval: userConfig.initialInterval ?? defaultAdminConfig.initialInterval
|
|
153
|
+
initialInterval: userConfig.initialInterval ?? defaultAdminConfig.initialInterval,
|
|
154
|
+
defaultPage: userConfig.defaultPage ?? defaultAdminConfig.defaultPage,
|
|
155
|
+
onNavigate: userConfig.onNavigate ?? defaultAdminConfig.onNavigate
|
|
129
156
|
};
|
|
130
157
|
}
|
|
131
158
|
|
|
@@ -195,6 +222,21 @@ async function fetchAdminJson(path, params, options) {
|
|
|
195
222
|
const payload = await response.json();
|
|
196
223
|
return payload.data;
|
|
197
224
|
}
|
|
225
|
+
async function fetchRawJson(path, params, options) {
|
|
226
|
+
const url = new URL(`${resolveBaseUrl(options?.baseUrl)}${path}`, window.location.origin);
|
|
227
|
+
for (const [key, value] of Object.entries(params)) {
|
|
228
|
+
if (typeof value === "string" && value.length > 0) {
|
|
229
|
+
url.searchParams.set(key, value);
|
|
230
|
+
}
|
|
231
|
+
}
|
|
232
|
+
const response = await fetch(url.toString(), {
|
|
233
|
+
headers: await withAuthHeaders({}, options?.getRequestHeaders)
|
|
234
|
+
});
|
|
235
|
+
if (!response.ok) {
|
|
236
|
+
throw new Error(`Admin request failed (${response.status})`);
|
|
237
|
+
}
|
|
238
|
+
return await response.json();
|
|
239
|
+
}
|
|
198
240
|
async function fetchAdminOverview(range, namespace, options) {
|
|
199
241
|
const windowRange = getRangeWindow(range);
|
|
200
242
|
return await fetchAdminJson("/v1/admin/overview", {
|
|
@@ -233,6 +275,139 @@ async function fetchAdminAgents(search, namespace, options) {
|
|
|
233
275
|
limit: "8"
|
|
234
276
|
}, options);
|
|
235
277
|
}
|
|
278
|
+
async function fetchThreadDetail(threadId, options) {
|
|
279
|
+
return await fetchAdminJson(
|
|
280
|
+
`/v1/threads/${encodeURIComponent(threadId)}`,
|
|
281
|
+
{},
|
|
282
|
+
options
|
|
283
|
+
);
|
|
284
|
+
}
|
|
285
|
+
async function fetchThreadMessages(threadId, messageOptions, options) {
|
|
286
|
+
return await fetchRawJson(
|
|
287
|
+
`/v1/threads/${encodeURIComponent(threadId)}/messages`,
|
|
288
|
+
{
|
|
289
|
+
limit: messageOptions?.limit?.toString(),
|
|
290
|
+
before: messageOptions?.before
|
|
291
|
+
},
|
|
292
|
+
options
|
|
293
|
+
);
|
|
294
|
+
}
|
|
295
|
+
async function fetchParticipantDetail(participantId, options) {
|
|
296
|
+
return await fetchAdminJson(
|
|
297
|
+
`/v1/participants/${encodeURIComponent(participantId)}`,
|
|
298
|
+
{},
|
|
299
|
+
options
|
|
300
|
+
);
|
|
301
|
+
}
|
|
302
|
+
async function updateParticipant(participantId, data, options) {
|
|
303
|
+
const url = new URL(
|
|
304
|
+
`${resolveBaseUrl(options?.baseUrl)}/v1/participants/${encodeURIComponent(participantId)}`,
|
|
305
|
+
window.location.origin
|
|
306
|
+
);
|
|
307
|
+
const response = await fetch(url.toString(), {
|
|
308
|
+
method: "PUT",
|
|
309
|
+
headers: await withAuthHeaders(
|
|
310
|
+
{ "Content-Type": "application/json" },
|
|
311
|
+
options?.getRequestHeaders
|
|
312
|
+
),
|
|
313
|
+
body: JSON.stringify(data)
|
|
314
|
+
});
|
|
315
|
+
if (!response.ok) {
|
|
316
|
+
throw new Error(`Update participant failed (${response.status})`);
|
|
317
|
+
}
|
|
318
|
+
const payload = await response.json();
|
|
319
|
+
return payload.data;
|
|
320
|
+
}
|
|
321
|
+
async function fetchCollectionNames(options) {
|
|
322
|
+
return await fetchAdminJson("/v1/collections", {}, options);
|
|
323
|
+
}
|
|
324
|
+
async function fetchCollectionItems(collection, queryOptions, options) {
|
|
325
|
+
const params = {
|
|
326
|
+
namespace: queryOptions?.namespace,
|
|
327
|
+
limit: queryOptions?.limit?.toString()
|
|
328
|
+
};
|
|
329
|
+
if (queryOptions?.search) {
|
|
330
|
+
params.q = queryOptions.search;
|
|
331
|
+
} else {
|
|
332
|
+
params.offset = queryOptions?.offset?.toString();
|
|
333
|
+
}
|
|
334
|
+
return await fetchAdminJson(
|
|
335
|
+
`/v1/collections/${encodeURIComponent(collection)}`,
|
|
336
|
+
params,
|
|
337
|
+
options
|
|
338
|
+
);
|
|
339
|
+
}
|
|
340
|
+
async function fetchCollectionItem(collection, itemId, namespace, options) {
|
|
341
|
+
return await fetchAdminJson(
|
|
342
|
+
`/v1/collections/${encodeURIComponent(collection)}/${encodeURIComponent(itemId)}`,
|
|
343
|
+
{ namespace },
|
|
344
|
+
options
|
|
345
|
+
);
|
|
346
|
+
}
|
|
347
|
+
async function createCollectionItem(collection, data, namespace, options) {
|
|
348
|
+
const url = new URL(
|
|
349
|
+
`${resolveBaseUrl(options?.baseUrl)}/v1/collections/${encodeURIComponent(collection)}`,
|
|
350
|
+
window.location.origin
|
|
351
|
+
);
|
|
352
|
+
if (namespace) url.searchParams.set("namespace", namespace);
|
|
353
|
+
const response = await fetch(url.toString(), {
|
|
354
|
+
method: "POST",
|
|
355
|
+
headers: await withAuthHeaders(
|
|
356
|
+
{ "Content-Type": "application/json" },
|
|
357
|
+
options?.getRequestHeaders
|
|
358
|
+
),
|
|
359
|
+
body: JSON.stringify(data)
|
|
360
|
+
});
|
|
361
|
+
if (!response.ok) {
|
|
362
|
+
throw new Error(`Create collection item failed (${response.status})`);
|
|
363
|
+
}
|
|
364
|
+
const payload = await response.json();
|
|
365
|
+
if ("body" in payload && payload.body && typeof payload.body === "object") {
|
|
366
|
+
return payload.body;
|
|
367
|
+
}
|
|
368
|
+
return payload;
|
|
369
|
+
}
|
|
370
|
+
async function updateCollectionItem(collection, itemId, data, namespace, options) {
|
|
371
|
+
const url = new URL(
|
|
372
|
+
`${resolveBaseUrl(options?.baseUrl)}/v1/collections/${encodeURIComponent(collection)}/${encodeURIComponent(itemId)}`,
|
|
373
|
+
window.location.origin
|
|
374
|
+
);
|
|
375
|
+
if (namespace) url.searchParams.set("namespace", namespace);
|
|
376
|
+
const response = await fetch(url.toString(), {
|
|
377
|
+
method: "PUT",
|
|
378
|
+
headers: await withAuthHeaders(
|
|
379
|
+
{ "Content-Type": "application/json" },
|
|
380
|
+
options?.getRequestHeaders
|
|
381
|
+
),
|
|
382
|
+
body: JSON.stringify(data)
|
|
383
|
+
});
|
|
384
|
+
if (!response.ok) {
|
|
385
|
+
throw new Error(`Update collection item failed (${response.status})`);
|
|
386
|
+
}
|
|
387
|
+
const payload = await response.json();
|
|
388
|
+
return payload.data;
|
|
389
|
+
}
|
|
390
|
+
async function deleteCollectionItem(collection, itemId, namespace, options) {
|
|
391
|
+
const url = new URL(
|
|
392
|
+
`${resolveBaseUrl(options?.baseUrl)}/v1/collections/${encodeURIComponent(collection)}/${encodeURIComponent(itemId)}`,
|
|
393
|
+
window.location.origin
|
|
394
|
+
);
|
|
395
|
+
if (namespace) url.searchParams.set("namespace", namespace);
|
|
396
|
+
const response = await fetch(url.toString(), {
|
|
397
|
+
method: "DELETE",
|
|
398
|
+
headers: await withAuthHeaders({}, options?.getRequestHeaders)
|
|
399
|
+
});
|
|
400
|
+
if (!response.ok) {
|
|
401
|
+
throw new Error(`Delete collection item failed (${response.status})`);
|
|
402
|
+
}
|
|
403
|
+
}
|
|
404
|
+
async function fetchThreadEvents(threadId, options) {
|
|
405
|
+
return await fetchAdminJson(
|
|
406
|
+
`/v1/threads/${encodeURIComponent(threadId)}/events`,
|
|
407
|
+
{},
|
|
408
|
+
options
|
|
409
|
+
);
|
|
410
|
+
}
|
|
236
411
|
|
|
237
412
|
// src/useCopilotzAdmin.ts
|
|
238
413
|
function useCopilotzAdmin(options = {}) {
|
|
@@ -358,6 +533,19 @@ function Card({ className, ...props }) {
|
|
|
358
533
|
}
|
|
359
534
|
);
|
|
360
535
|
}
|
|
536
|
+
function CardHeader({ className, ...props }) {
|
|
537
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
538
|
+
"div",
|
|
539
|
+
{
|
|
540
|
+
"data-slot": "card-header",
|
|
541
|
+
className: cn(
|
|
542
|
+
"@container/card-header grid auto-rows-min grid-rows-[auto_auto] items-start gap-1.5 px-6 has-data-[slot=card-action]:grid-cols-[1fr_auto] [.border-b]:pb-6",
|
|
543
|
+
className
|
|
544
|
+
),
|
|
545
|
+
...props
|
|
546
|
+
}
|
|
547
|
+
);
|
|
548
|
+
}
|
|
361
549
|
function CardContent({ className, ...props }) {
|
|
362
550
|
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
363
551
|
"div",
|
|
@@ -416,10 +604,83 @@ function Button({
|
|
|
416
604
|
);
|
|
417
605
|
}
|
|
418
606
|
|
|
419
|
-
// src/components/ui/
|
|
607
|
+
// src/components/ui/tooltip.tsx
|
|
608
|
+
var TooltipPrimitive = __toESM(require("@radix-ui/react-tooltip"), 1);
|
|
420
609
|
var import_jsx_runtime3 = require("react/jsx-runtime");
|
|
421
|
-
function
|
|
610
|
+
function TooltipProvider({
|
|
611
|
+
delayDuration = 0,
|
|
612
|
+
...props
|
|
613
|
+
}) {
|
|
422
614
|
return /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
615
|
+
TooltipPrimitive.Provider,
|
|
616
|
+
{
|
|
617
|
+
"data-slot": "tooltip-provider",
|
|
618
|
+
delayDuration,
|
|
619
|
+
...props
|
|
620
|
+
}
|
|
621
|
+
);
|
|
622
|
+
}
|
|
623
|
+
function Tooltip({
|
|
624
|
+
...props
|
|
625
|
+
}) {
|
|
626
|
+
return /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(TooltipProvider, { children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(TooltipPrimitive.Root, { "data-slot": "tooltip", ...props }) });
|
|
627
|
+
}
|
|
628
|
+
function TooltipTrigger({
|
|
629
|
+
...props
|
|
630
|
+
}) {
|
|
631
|
+
return /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(TooltipPrimitive.Trigger, { "data-slot": "tooltip-trigger", ...props });
|
|
632
|
+
}
|
|
633
|
+
function TooltipContent({
|
|
634
|
+
className,
|
|
635
|
+
sideOffset = 0,
|
|
636
|
+
children,
|
|
637
|
+
...props
|
|
638
|
+
}) {
|
|
639
|
+
return /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(TooltipPrimitive.Portal, { children: /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(
|
|
640
|
+
TooltipPrimitive.Content,
|
|
641
|
+
{
|
|
642
|
+
"data-slot": "tooltip-content",
|
|
643
|
+
sideOffset,
|
|
644
|
+
className: cn(
|
|
645
|
+
"bg-primary text-primary-foreground animate-in fade-in-0 zoom-in-95 data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=closed]:zoom-out-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 z-50 w-fit origin-(--radix-tooltip-content-transform-origin) rounded-md px-3 py-1.5 text-xs text-balance",
|
|
646
|
+
className
|
|
647
|
+
),
|
|
648
|
+
...props,
|
|
649
|
+
children: [
|
|
650
|
+
children,
|
|
651
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(TooltipPrimitive.Arrow, { className: "bg-primary fill-primary z-50 size-2.5 translate-y-[calc(-50%_-_2px)] rotate-45 rounded-[2px]" })
|
|
652
|
+
]
|
|
653
|
+
}
|
|
654
|
+
) });
|
|
655
|
+
}
|
|
656
|
+
|
|
657
|
+
// src/components/ui/sidebar.tsx
|
|
658
|
+
var React3 = __toESM(require("react"), 1);
|
|
659
|
+
var import_react_slot2 = require("@radix-ui/react-slot");
|
|
660
|
+
var import_class_variance_authority2 = require("class-variance-authority");
|
|
661
|
+
var import_lucide_react2 = require("lucide-react");
|
|
662
|
+
|
|
663
|
+
// src/hooks/use-mobile.ts
|
|
664
|
+
var React = __toESM(require("react"), 1);
|
|
665
|
+
var MOBILE_BREAKPOINT = 768;
|
|
666
|
+
function useIsMobile() {
|
|
667
|
+
const [isMobile, setIsMobile] = React.useState(void 0);
|
|
668
|
+
React.useEffect(() => {
|
|
669
|
+
const mql = window.matchMedia(`(max-width: ${MOBILE_BREAKPOINT - 1}px)`);
|
|
670
|
+
const onChange = () => {
|
|
671
|
+
setIsMobile(window.innerWidth < MOBILE_BREAKPOINT);
|
|
672
|
+
};
|
|
673
|
+
mql.addEventListener("change", onChange);
|
|
674
|
+
setIsMobile(window.innerWidth < MOBILE_BREAKPOINT);
|
|
675
|
+
return () => mql.removeEventListener("change", onChange);
|
|
676
|
+
}, []);
|
|
677
|
+
return !!isMobile;
|
|
678
|
+
}
|
|
679
|
+
|
|
680
|
+
// src/components/ui/input.tsx
|
|
681
|
+
var import_jsx_runtime4 = require("react/jsx-runtime");
|
|
682
|
+
function Input({ className, type, ...props }) {
|
|
683
|
+
return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
423
684
|
"input",
|
|
424
685
|
{
|
|
425
686
|
type,
|
|
@@ -435,326 +696,1001 @@ function Input({ className, type, ...props }) {
|
|
|
435
696
|
);
|
|
436
697
|
}
|
|
437
698
|
|
|
438
|
-
// src/components/ui/
|
|
439
|
-
var
|
|
440
|
-
var
|
|
441
|
-
|
|
442
|
-
var badgeVariants = (0, import_class_variance_authority2.cva)(
|
|
443
|
-
"inline-flex items-center justify-center rounded-md border px-2 py-0.5 text-xs font-medium w-fit whitespace-nowrap shrink-0 [&>svg]:size-3 gap-1 [&>svg]:pointer-events-none focus-visible:border-ring focus-visible:ring-ring/50 focus-visible:ring-[3px] aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive transition-[color,box-shadow] overflow-hidden",
|
|
444
|
-
{
|
|
445
|
-
variants: {
|
|
446
|
-
variant: {
|
|
447
|
-
default: "border-transparent bg-primary text-primary-foreground [a&]:hover:bg-primary/90",
|
|
448
|
-
secondary: "border-transparent bg-secondary text-secondary-foreground [a&]:hover:bg-secondary/90",
|
|
449
|
-
destructive: "border-transparent bg-destructive text-white [a&]:hover:bg-destructive/90 focus-visible:ring-destructive/20 dark:focus-visible:ring-destructive/40 dark:bg-destructive/60",
|
|
450
|
-
outline: "text-foreground [a&]:hover:bg-accent [a&]:hover:text-accent-foreground"
|
|
451
|
-
}
|
|
452
|
-
},
|
|
453
|
-
defaultVariants: {
|
|
454
|
-
variant: "default"
|
|
455
|
-
}
|
|
456
|
-
}
|
|
457
|
-
);
|
|
458
|
-
function Badge({
|
|
699
|
+
// src/components/ui/separator.tsx
|
|
700
|
+
var SeparatorPrimitive = __toESM(require("@radix-ui/react-separator"), 1);
|
|
701
|
+
var import_jsx_runtime5 = require("react/jsx-runtime");
|
|
702
|
+
function Separator({
|
|
459
703
|
className,
|
|
460
|
-
|
|
461
|
-
|
|
704
|
+
orientation = "horizontal",
|
|
705
|
+
decorative = true,
|
|
462
706
|
...props
|
|
463
707
|
}) {
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
Comp,
|
|
708
|
+
return /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
|
|
709
|
+
SeparatorPrimitive.Root,
|
|
467
710
|
{
|
|
468
|
-
"data-slot": "
|
|
469
|
-
|
|
711
|
+
"data-slot": "separator",
|
|
712
|
+
decorative,
|
|
713
|
+
orientation,
|
|
714
|
+
className: cn(
|
|
715
|
+
"bg-border shrink-0 data-[orientation=horizontal]:h-px data-[orientation=horizontal]:w-full data-[orientation=vertical]:h-full data-[orientation=vertical]:w-px",
|
|
716
|
+
className
|
|
717
|
+
),
|
|
470
718
|
...props
|
|
471
719
|
}
|
|
472
720
|
);
|
|
473
721
|
}
|
|
474
722
|
|
|
475
|
-
// src/components/ui/
|
|
476
|
-
var
|
|
477
|
-
var
|
|
723
|
+
// src/components/ui/sheet.tsx
|
|
724
|
+
var React2 = __toESM(require("react"), 1);
|
|
725
|
+
var SheetPrimitive = __toESM(require("@radix-ui/react-dialog"), 1);
|
|
478
726
|
var import_lucide_react = require("lucide-react");
|
|
479
|
-
var
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
SelectPrimitive.Trigger,
|
|
484
|
-
{
|
|
485
|
-
ref,
|
|
486
|
-
className: cn(
|
|
487
|
-
"flex h-9 w-full items-center justify-between gap-2 rounded-md border border-input bg-transparent px-3 py-1 text-sm shadow-xs outline-none transition-colors placeholder:text-muted-foreground focus:ring-2 focus:ring-ring/40 disabled:cursor-not-allowed disabled:opacity-50",
|
|
488
|
-
className
|
|
489
|
-
),
|
|
490
|
-
...props,
|
|
491
|
-
children: [
|
|
492
|
-
children,
|
|
493
|
-
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)(SelectPrimitive.Icon, { asChild: true, children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_lucide_react.ChevronDown, { className: "h-4 w-4 opacity-50" }) })
|
|
494
|
-
]
|
|
727
|
+
var import_jsx_runtime6 = require("react/jsx-runtime");
|
|
728
|
+
function cleanupBodyStyles() {
|
|
729
|
+
if (typeof document !== "undefined" && document.body.style.pointerEvents === "none") {
|
|
730
|
+
document.body.style.pointerEvents = "";
|
|
495
731
|
}
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
732
|
+
}
|
|
733
|
+
function Sheet({ open, onOpenChange, ...props }) {
|
|
734
|
+
const prevOpenRef = React2.useRef(open);
|
|
735
|
+
React2.useEffect(() => {
|
|
736
|
+
if (prevOpenRef.current === true && open === false) {
|
|
737
|
+
const timeout = setTimeout(cleanupBodyStyles, 350);
|
|
738
|
+
return () => clearTimeout(timeout);
|
|
739
|
+
}
|
|
740
|
+
prevOpenRef.current = open;
|
|
741
|
+
}, [open]);
|
|
742
|
+
React2.useEffect(() => {
|
|
743
|
+
return () => {
|
|
744
|
+
cleanupBodyStyles();
|
|
745
|
+
};
|
|
746
|
+
}, []);
|
|
747
|
+
return /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(SheetPrimitive.Root, { "data-slot": "sheet", open, onOpenChange, ...props });
|
|
748
|
+
}
|
|
749
|
+
function SheetPortal({
|
|
750
|
+
...props
|
|
751
|
+
}) {
|
|
752
|
+
return /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(SheetPrimitive.Portal, { "data-slot": "sheet-portal", ...props });
|
|
753
|
+
}
|
|
754
|
+
function SheetOverlay({
|
|
755
|
+
className,
|
|
756
|
+
...props
|
|
757
|
+
}) {
|
|
758
|
+
return /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
|
|
759
|
+
SheetPrimitive.Overlay,
|
|
760
|
+
{
|
|
761
|
+
"data-slot": "sheet-overlay",
|
|
762
|
+
className: cn(
|
|
763
|
+
"fixed inset-0 z-50 bg-black/50",
|
|
764
|
+
"data-[state=open]:animate-in data-[state=closed]:animate-out",
|
|
765
|
+
"data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0",
|
|
766
|
+
"data-[state=closed]:pointer-events-none",
|
|
767
|
+
className
|
|
520
768
|
),
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
}
|
|
524
|
-
) }));
|
|
525
|
-
SelectContent.displayName = SelectPrimitive.Content.displayName;
|
|
526
|
-
var SelectItem = React.forwardRef(({ className, children, ...props }, ref) => /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(
|
|
527
|
-
SelectPrimitive.Item,
|
|
528
|
-
{
|
|
529
|
-
ref,
|
|
530
|
-
className: cn(
|
|
531
|
-
"relative flex w-full cursor-default select-none items-center rounded-sm py-1.5 pl-2 pr-8 text-sm outline-none focus:bg-accent focus:text-accent-foreground data-[disabled]:pointer-events-none data-[disabled]:opacity-50",
|
|
532
|
-
className
|
|
533
|
-
),
|
|
534
|
-
...props,
|
|
535
|
-
children: [
|
|
536
|
-
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)(SelectPrimitive.ItemText, { children }),
|
|
537
|
-
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)(SelectPrimitive.ItemIndicator, { className: "absolute right-2 inline-flex items-center justify-center", children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_lucide_react.Check, { className: "h-4 w-4" }) })
|
|
538
|
-
]
|
|
539
|
-
}
|
|
540
|
-
));
|
|
541
|
-
SelectItem.displayName = SelectPrimitive.Item.displayName;
|
|
542
|
-
|
|
543
|
-
// src/CopilotzAdmin.tsx
|
|
544
|
-
var import_jsx_runtime6 = require("react/jsx-runtime");
|
|
545
|
-
var CopilotzAdmin = ({
|
|
546
|
-
config: userConfig,
|
|
547
|
-
className
|
|
548
|
-
}) => {
|
|
549
|
-
const config = (0, import_react2.useMemo)(
|
|
550
|
-
() => mergeAdminConfig(defaultAdminConfig, userConfig),
|
|
551
|
-
[userConfig]
|
|
769
|
+
...props
|
|
770
|
+
}
|
|
552
771
|
);
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
|
|
772
|
+
}
|
|
773
|
+
function SheetContent({
|
|
774
|
+
className,
|
|
775
|
+
children,
|
|
776
|
+
side = "right",
|
|
777
|
+
...props
|
|
778
|
+
}) {
|
|
779
|
+
return /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(SheetPortal, { children: [
|
|
780
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)(SheetOverlay, {}),
|
|
781
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(
|
|
782
|
+
SheetPrimitive.Content,
|
|
783
|
+
{
|
|
784
|
+
"data-slot": "sheet-content",
|
|
785
|
+
"aria-describedby": void 0,
|
|
786
|
+
className: cn(
|
|
787
|
+
"bg-background data-[state=open]:animate-in data-[state=closed]:animate-out fixed z-50 flex flex-col gap-4 shadow-lg transition ease-in-out data-[state=closed]:duration-300 data-[state=open]:duration-500",
|
|
788
|
+
side === "right" && "data-[state=closed]:slide-out-to-right data-[state=open]:slide-in-from-right inset-y-0 right-0 h-full w-3/4 border-l sm:max-w-sm",
|
|
789
|
+
side === "left" && "data-[state=closed]:slide-out-to-left data-[state=open]:slide-in-from-left inset-y-0 left-0 h-full w-3/4 border-r sm:max-w-sm",
|
|
790
|
+
side === "top" && "data-[state=closed]:slide-out-to-top data-[state=open]:slide-in-from-top inset-x-0 top-0 h-auto border-b",
|
|
791
|
+
side === "bottom" && "data-[state=closed]:slide-out-to-bottom data-[state=open]:slide-in-from-bottom inset-x-0 bottom-0 h-auto border-t",
|
|
792
|
+
className
|
|
793
|
+
),
|
|
794
|
+
...props,
|
|
795
|
+
children: [
|
|
796
|
+
children,
|
|
797
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(SheetPrimitive.Close, { className: "ring-offset-background focus:ring-ring data-[state=open]:bg-secondary absolute top-4 right-4 rounded-xs opacity-70 transition-opacity hover:opacity-100 focus:ring-2 focus:ring-offset-2 focus:outline-hidden disabled:pointer-events-none", children: [
|
|
798
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)(import_lucide_react.XIcon, { className: "size-4" }),
|
|
799
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { className: "sr-only", children: "Close" })
|
|
800
|
+
] })
|
|
801
|
+
]
|
|
802
|
+
}
|
|
803
|
+
)
|
|
804
|
+
] });
|
|
805
|
+
}
|
|
806
|
+
function SheetHeader({ className, ...props }) {
|
|
807
|
+
return /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
|
|
808
|
+
"div",
|
|
575
809
|
{
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
}
|
|
810
|
+
"data-slot": "sheet-header",
|
|
811
|
+
className: cn("flex flex-col gap-1.5 p-4", className),
|
|
812
|
+
...props
|
|
813
|
+
}
|
|
814
|
+
);
|
|
815
|
+
}
|
|
816
|
+
function SheetTitle({
|
|
817
|
+
className,
|
|
818
|
+
...props
|
|
819
|
+
}) {
|
|
820
|
+
return /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
|
|
821
|
+
SheetPrimitive.Title,
|
|
580
822
|
{
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
823
|
+
"data-slot": "sheet-title",
|
|
824
|
+
className: cn("text-foreground font-semibold", className),
|
|
825
|
+
...props
|
|
826
|
+
}
|
|
827
|
+
);
|
|
828
|
+
}
|
|
829
|
+
function SheetDescription({
|
|
830
|
+
className,
|
|
831
|
+
...props
|
|
832
|
+
}) {
|
|
833
|
+
return /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
|
|
834
|
+
SheetPrimitive.Description,
|
|
835
|
+
{
|
|
836
|
+
"data-slot": "sheet-description",
|
|
837
|
+
className: cn("text-muted-foreground text-sm", className),
|
|
838
|
+
...props
|
|
839
|
+
}
|
|
840
|
+
);
|
|
841
|
+
}
|
|
842
|
+
|
|
843
|
+
// src/components/ui/sidebar.tsx
|
|
844
|
+
var import_jsx_runtime7 = require("react/jsx-runtime");
|
|
845
|
+
var SIDEBAR_COOKIE_NAME = "sidebar_state";
|
|
846
|
+
var SIDEBAR_COOKIE_MAX_AGE = 60 * 60 * 24 * 7;
|
|
847
|
+
var SIDEBAR_WIDTH = "16rem";
|
|
848
|
+
var SIDEBAR_WIDTH_MOBILE = "18rem";
|
|
849
|
+
var SIDEBAR_WIDTH_ICON = "3rem";
|
|
850
|
+
var SIDEBAR_KEYBOARD_SHORTCUT = "b";
|
|
851
|
+
var SidebarContext = React3.createContext(null);
|
|
852
|
+
function useSidebar() {
|
|
853
|
+
const context = React3.useContext(SidebarContext);
|
|
854
|
+
if (!context) {
|
|
855
|
+
throw new Error("useSidebar must be used within a SidebarProvider.");
|
|
856
|
+
}
|
|
857
|
+
return context;
|
|
858
|
+
}
|
|
859
|
+
function SidebarProvider({
|
|
860
|
+
defaultOpen = true,
|
|
861
|
+
open: openProp,
|
|
862
|
+
onOpenChange: setOpenProp,
|
|
863
|
+
className,
|
|
864
|
+
style,
|
|
865
|
+
children,
|
|
866
|
+
...props
|
|
867
|
+
}) {
|
|
868
|
+
const isMobile = useIsMobile();
|
|
869
|
+
const [openMobile, setOpenMobile] = React3.useState(false);
|
|
870
|
+
const [_open, _setOpen] = React3.useState(defaultOpen);
|
|
871
|
+
const open = openProp ?? _open;
|
|
872
|
+
const setOpen = React3.useCallback(
|
|
873
|
+
(value) => {
|
|
874
|
+
const openState = typeof value === "function" ? value(open) : value;
|
|
875
|
+
if (setOpenProp) {
|
|
876
|
+
setOpenProp(openState);
|
|
877
|
+
} else {
|
|
878
|
+
_setOpen(openState);
|
|
879
|
+
}
|
|
880
|
+
document.cookie = `${SIDEBAR_COOKIE_NAME}=${openState}; path=/; max-age=${SIDEBAR_COOKIE_MAX_AGE}`;
|
|
584
881
|
},
|
|
882
|
+
[setOpenProp, open]
|
|
883
|
+
);
|
|
884
|
+
const toggleSidebar = React3.useCallback(() => {
|
|
885
|
+
return isMobile ? setOpenMobile((open2) => !open2) : setOpen((open2) => !open2);
|
|
886
|
+
}, [isMobile, setOpen, setOpenMobile]);
|
|
887
|
+
React3.useEffect(() => {
|
|
888
|
+
const handleKeyDown = (event) => {
|
|
889
|
+
if (event.key === SIDEBAR_KEYBOARD_SHORTCUT && (event.metaKey || event.ctrlKey)) {
|
|
890
|
+
event.preventDefault();
|
|
891
|
+
toggleSidebar();
|
|
892
|
+
}
|
|
893
|
+
};
|
|
894
|
+
window.addEventListener("keydown", handleKeyDown);
|
|
895
|
+
return () => window.removeEventListener("keydown", handleKeyDown);
|
|
896
|
+
}, [toggleSidebar]);
|
|
897
|
+
const state = open ? "expanded" : "collapsed";
|
|
898
|
+
const contextValue = React3.useMemo(
|
|
899
|
+
() => ({
|
|
900
|
+
state,
|
|
901
|
+
open,
|
|
902
|
+
setOpen,
|
|
903
|
+
isMobile,
|
|
904
|
+
openMobile,
|
|
905
|
+
setOpenMobile,
|
|
906
|
+
toggleSidebar
|
|
907
|
+
}),
|
|
908
|
+
[state, open, setOpen, isMobile, openMobile, setOpenMobile, toggleSidebar]
|
|
909
|
+
);
|
|
910
|
+
return /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(SidebarContext.Provider, { value: contextValue, children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(TooltipProvider, { delayDuration: 0, children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
|
|
911
|
+
"div",
|
|
585
912
|
{
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
913
|
+
"data-slot": "sidebar-wrapper",
|
|
914
|
+
style: {
|
|
915
|
+
"--sidebar-width": SIDEBAR_WIDTH,
|
|
916
|
+
"--sidebar-width-icon": SIDEBAR_WIDTH_ICON,
|
|
917
|
+
...style
|
|
918
|
+
},
|
|
919
|
+
className: cn(
|
|
920
|
+
"group/sidebar-wrapper has-data-[variant=inset]:bg-sidebar flex min-h-svh w-full",
|
|
921
|
+
className
|
|
922
|
+
),
|
|
923
|
+
...props,
|
|
924
|
+
children
|
|
925
|
+
}
|
|
926
|
+
) }) });
|
|
927
|
+
}
|
|
928
|
+
function Sidebar({
|
|
929
|
+
side = "left",
|
|
930
|
+
variant = "sidebar",
|
|
931
|
+
collapsible = "offcanvas",
|
|
932
|
+
className,
|
|
933
|
+
children,
|
|
934
|
+
...props
|
|
935
|
+
}) {
|
|
936
|
+
const { isMobile, state, openMobile, setOpenMobile } = useSidebar();
|
|
937
|
+
if (collapsible === "none") {
|
|
938
|
+
return /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
|
|
939
|
+
"div",
|
|
940
|
+
{
|
|
941
|
+
"data-slot": "sidebar",
|
|
942
|
+
className: cn(
|
|
943
|
+
"bg-sidebar text-sidebar-foreground flex h-full w-(--sidebar-width) flex-col",
|
|
944
|
+
className
|
|
945
|
+
),
|
|
946
|
+
...props,
|
|
947
|
+
children
|
|
948
|
+
}
|
|
949
|
+
);
|
|
950
|
+
}
|
|
951
|
+
if (isMobile) {
|
|
952
|
+
return /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(Sheet, { open: openMobile, onOpenChange: setOpenMobile, ...props, children: /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(
|
|
953
|
+
SheetContent,
|
|
954
|
+
{
|
|
955
|
+
"data-sidebar": "sidebar",
|
|
956
|
+
"data-slot": "sidebar",
|
|
957
|
+
"data-mobile": "true",
|
|
958
|
+
className: "bg-sidebar text-sidebar-foreground w-(--sidebar-width) p-0 [&>button]:hidden",
|
|
959
|
+
style: {
|
|
960
|
+
"--sidebar-width": SIDEBAR_WIDTH_MOBILE
|
|
961
|
+
},
|
|
962
|
+
side,
|
|
963
|
+
children: [
|
|
964
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(SheetHeader, { className: "sr-only", children: [
|
|
965
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)(SheetTitle, { children: "Sidebar" }),
|
|
966
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)(SheetDescription, { children: "Displays the mobile sidebar." })
|
|
967
|
+
] }),
|
|
968
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { className: "flex h-full w-full flex-col", children })
|
|
969
|
+
]
|
|
970
|
+
}
|
|
971
|
+
) });
|
|
972
|
+
}
|
|
973
|
+
return /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(
|
|
974
|
+
"div",
|
|
975
|
+
{
|
|
976
|
+
className: "group peer text-sidebar-foreground hidden md:block",
|
|
977
|
+
"data-state": state,
|
|
978
|
+
"data-collapsible": state === "collapsed" ? collapsible : "",
|
|
979
|
+
"data-variant": variant,
|
|
980
|
+
"data-side": side,
|
|
981
|
+
"data-slot": "sidebar",
|
|
982
|
+
children: [
|
|
983
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
|
|
984
|
+
"div",
|
|
985
|
+
{
|
|
986
|
+
"data-slot": "sidebar-gap",
|
|
987
|
+
className: cn(
|
|
988
|
+
"relative w-(--sidebar-width) bg-transparent transition-[width] duration-200 ease-linear",
|
|
989
|
+
"group-data-[collapsible=offcanvas]:w-0",
|
|
990
|
+
"group-data-[side=right]:rotate-180",
|
|
991
|
+
variant === "floating" || variant === "inset" ? "group-data-[collapsible=icon]:w-[calc(var(--sidebar-width-icon)+(--spacing(4)))]" : "group-data-[collapsible=icon]:w-(--sidebar-width-icon)"
|
|
992
|
+
)
|
|
993
|
+
}
|
|
994
|
+
),
|
|
995
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
|
|
996
|
+
"div",
|
|
997
|
+
{
|
|
998
|
+
"data-slot": "sidebar-container",
|
|
999
|
+
className: cn(
|
|
1000
|
+
"fixed inset-y-0 z-10 hidden h-svh w-(--sidebar-width) transition-[left,right,width] duration-200 ease-linear md:flex",
|
|
1001
|
+
side === "left" ? "left-0 group-data-[collapsible=offcanvas]:left-[calc(var(--sidebar-width)*-1)]" : "right-0 group-data-[collapsible=offcanvas]:right-[calc(var(--sidebar-width)*-1)]",
|
|
1002
|
+
variant === "floating" || variant === "inset" ? "p-2 group-data-[collapsible=icon]:w-[calc(var(--sidebar-width-icon)+(--spacing(4))+2px)]" : "group-data-[collapsible=icon]:w-(--sidebar-width-icon) group-data-[side=left]:border-r group-data-[side=right]:border-l",
|
|
1003
|
+
className
|
|
1004
|
+
),
|
|
1005
|
+
...props,
|
|
1006
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
|
|
1007
|
+
"div",
|
|
1008
|
+
{
|
|
1009
|
+
"data-sidebar": "sidebar",
|
|
1010
|
+
"data-slot": "sidebar-inner",
|
|
1011
|
+
className: "bg-sidebar group-data-[variant=floating]:border-sidebar-border flex h-full w-full flex-col group-data-[variant=floating]:rounded-lg group-data-[variant=floating]:border group-data-[variant=floating]:shadow-sm",
|
|
1012
|
+
children
|
|
1013
|
+
}
|
|
1014
|
+
)
|
|
1015
|
+
}
|
|
1016
|
+
)
|
|
1017
|
+
]
|
|
1018
|
+
}
|
|
1019
|
+
);
|
|
1020
|
+
}
|
|
1021
|
+
function SidebarTrigger({
|
|
1022
|
+
className,
|
|
1023
|
+
onClick,
|
|
1024
|
+
...props
|
|
1025
|
+
}) {
|
|
1026
|
+
const { toggleSidebar } = useSidebar();
|
|
1027
|
+
return /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(
|
|
1028
|
+
Button,
|
|
1029
|
+
{
|
|
1030
|
+
"data-sidebar": "trigger",
|
|
1031
|
+
"data-slot": "sidebar-trigger",
|
|
1032
|
+
variant: "ghost",
|
|
1033
|
+
size: "icon",
|
|
1034
|
+
className: cn("size-7", className),
|
|
1035
|
+
onClick: (event) => {
|
|
1036
|
+
onClick?.(event);
|
|
1037
|
+
toggleSidebar();
|
|
1038
|
+
},
|
|
1039
|
+
...props,
|
|
1040
|
+
children: [
|
|
1041
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)(import_lucide_react2.PanelLeftIcon, {}),
|
|
1042
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)("span", { className: "sr-only", children: "Toggle Sidebar" })
|
|
1043
|
+
]
|
|
1044
|
+
}
|
|
1045
|
+
);
|
|
1046
|
+
}
|
|
1047
|
+
function SidebarRail({ className, ...props }) {
|
|
1048
|
+
const { toggleSidebar } = useSidebar();
|
|
1049
|
+
return /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
|
|
1050
|
+
"button",
|
|
1051
|
+
{
|
|
1052
|
+
"data-sidebar": "rail",
|
|
1053
|
+
"data-slot": "sidebar-rail",
|
|
1054
|
+
"aria-label": "Toggle Sidebar",
|
|
1055
|
+
tabIndex: -1,
|
|
1056
|
+
onClick: toggleSidebar,
|
|
1057
|
+
title: "Toggle Sidebar",
|
|
1058
|
+
className: cn(
|
|
1059
|
+
"hover:after:bg-sidebar-border absolute inset-y-0 z-20 hidden w-4 -translate-x-1/2 transition-all ease-linear group-data-[side=left]:-right-4 group-data-[side=right]:left-0 after:absolute after:inset-y-0 after:left-1/2 after:w-[2px] sm:flex",
|
|
1060
|
+
"in-data-[side=left]:cursor-w-resize in-data-[side=right]:cursor-e-resize",
|
|
1061
|
+
"[[data-side=left][data-state=collapsed]_&]:cursor-e-resize [[data-side=right][data-state=collapsed]_&]:cursor-w-resize",
|
|
1062
|
+
"hover:group-data-[collapsible=offcanvas]:bg-sidebar group-data-[collapsible=offcanvas]:translate-x-0 group-data-[collapsible=offcanvas]:after:left-full",
|
|
1063
|
+
"[[data-side=left][data-collapsible=offcanvas]_&]:-right-2",
|
|
1064
|
+
"[[data-side=right][data-collapsible=offcanvas]_&]:-left-2",
|
|
1065
|
+
className
|
|
1066
|
+
),
|
|
1067
|
+
...props
|
|
1068
|
+
}
|
|
1069
|
+
);
|
|
1070
|
+
}
|
|
1071
|
+
function SidebarInset({ className, ...props }) {
|
|
1072
|
+
return /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
|
|
1073
|
+
"main",
|
|
1074
|
+
{
|
|
1075
|
+
"data-slot": "sidebar-inset",
|
|
1076
|
+
className: cn(
|
|
1077
|
+
"bg-background relative flex w-full flex-1 flex-col",
|
|
1078
|
+
"md:peer-data-[variant=inset]:m-2 md:peer-data-[variant=inset]:ml-0 md:peer-data-[variant=inset]:rounded-xl md:peer-data-[variant=inset]:shadow-sm md:peer-data-[variant=inset]:peer-data-[state=collapsed]:ml-2",
|
|
1079
|
+
className
|
|
1080
|
+
),
|
|
1081
|
+
...props
|
|
1082
|
+
}
|
|
1083
|
+
);
|
|
1084
|
+
}
|
|
1085
|
+
function SidebarHeader({ className, ...props }) {
|
|
1086
|
+
return /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
|
|
1087
|
+
"div",
|
|
1088
|
+
{
|
|
1089
|
+
"data-slot": "sidebar-header",
|
|
1090
|
+
"data-sidebar": "header",
|
|
1091
|
+
className: cn("flex flex-col gap-2 p-2", className),
|
|
1092
|
+
...props
|
|
1093
|
+
}
|
|
1094
|
+
);
|
|
1095
|
+
}
|
|
1096
|
+
function SidebarFooter({ className, ...props }) {
|
|
1097
|
+
return /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
|
|
1098
|
+
"div",
|
|
1099
|
+
{
|
|
1100
|
+
"data-slot": "sidebar-footer",
|
|
1101
|
+
"data-sidebar": "footer",
|
|
1102
|
+
className: cn("flex flex-col gap-2 p-2", className),
|
|
1103
|
+
...props
|
|
1104
|
+
}
|
|
1105
|
+
);
|
|
1106
|
+
}
|
|
1107
|
+
function SidebarSeparator({
|
|
1108
|
+
className,
|
|
1109
|
+
...props
|
|
1110
|
+
}) {
|
|
1111
|
+
return /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
|
|
1112
|
+
Separator,
|
|
1113
|
+
{
|
|
1114
|
+
"data-slot": "sidebar-separator",
|
|
1115
|
+
"data-sidebar": "separator",
|
|
1116
|
+
className: cn("bg-sidebar-border mx-2 w-auto", className),
|
|
1117
|
+
...props
|
|
1118
|
+
}
|
|
1119
|
+
);
|
|
1120
|
+
}
|
|
1121
|
+
function SidebarContent({ className, ...props }) {
|
|
1122
|
+
return /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
|
|
1123
|
+
"div",
|
|
1124
|
+
{
|
|
1125
|
+
"data-slot": "sidebar-content",
|
|
1126
|
+
"data-sidebar": "content",
|
|
1127
|
+
className: cn(
|
|
1128
|
+
"flex min-h-0 flex-1 flex-col gap-2 overflow-auto group-data-[collapsible=icon]:overflow-hidden",
|
|
1129
|
+
className
|
|
1130
|
+
),
|
|
1131
|
+
...props
|
|
1132
|
+
}
|
|
1133
|
+
);
|
|
1134
|
+
}
|
|
1135
|
+
function SidebarGroup({ className, ...props }) {
|
|
1136
|
+
return /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
|
|
1137
|
+
"div",
|
|
1138
|
+
{
|
|
1139
|
+
"data-slot": "sidebar-group",
|
|
1140
|
+
"data-sidebar": "group",
|
|
1141
|
+
className: cn("relative flex w-full min-w-0 flex-col p-2", className),
|
|
1142
|
+
...props
|
|
1143
|
+
}
|
|
1144
|
+
);
|
|
1145
|
+
}
|
|
1146
|
+
function SidebarGroupLabel({
|
|
1147
|
+
className,
|
|
1148
|
+
asChild = false,
|
|
1149
|
+
...props
|
|
1150
|
+
}) {
|
|
1151
|
+
const Comp = asChild ? import_react_slot2.Slot : "div";
|
|
1152
|
+
return /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
|
|
1153
|
+
Comp,
|
|
1154
|
+
{
|
|
1155
|
+
"data-slot": "sidebar-group-label",
|
|
1156
|
+
"data-sidebar": "group-label",
|
|
1157
|
+
className: cn(
|
|
1158
|
+
"text-sidebar-foreground/70 ring-sidebar-ring flex h-8 shrink-0 items-center rounded-md px-2 text-xs font-medium outline-hidden transition-[margin,opacity] duration-200 ease-linear focus-visible:ring-2 [&>svg]:size-4 [&>svg]:shrink-0",
|
|
1159
|
+
"group-data-[collapsible=icon]:-mt-8 group-data-[collapsible=icon]:opacity-0",
|
|
1160
|
+
className
|
|
1161
|
+
),
|
|
1162
|
+
...props
|
|
1163
|
+
}
|
|
1164
|
+
);
|
|
1165
|
+
}
|
|
1166
|
+
function SidebarGroupContent({
|
|
1167
|
+
className,
|
|
1168
|
+
...props
|
|
1169
|
+
}) {
|
|
1170
|
+
return /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
|
|
1171
|
+
"div",
|
|
1172
|
+
{
|
|
1173
|
+
"data-slot": "sidebar-group-content",
|
|
1174
|
+
"data-sidebar": "group-content",
|
|
1175
|
+
className: cn("w-full text-sm", className),
|
|
1176
|
+
...props
|
|
1177
|
+
}
|
|
1178
|
+
);
|
|
1179
|
+
}
|
|
1180
|
+
function SidebarMenu({ className, ...props }) {
|
|
1181
|
+
return /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
|
|
1182
|
+
"ul",
|
|
1183
|
+
{
|
|
1184
|
+
"data-slot": "sidebar-menu",
|
|
1185
|
+
"data-sidebar": "menu",
|
|
1186
|
+
className: cn("flex w-full min-w-0 flex-col gap-1", className),
|
|
1187
|
+
...props
|
|
1188
|
+
}
|
|
1189
|
+
);
|
|
1190
|
+
}
|
|
1191
|
+
function SidebarMenuItem({ className, ...props }) {
|
|
1192
|
+
return /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
|
|
1193
|
+
"li",
|
|
1194
|
+
{
|
|
1195
|
+
"data-slot": "sidebar-menu-item",
|
|
1196
|
+
"data-sidebar": "menu-item",
|
|
1197
|
+
className: cn("group/menu-item relative", className),
|
|
1198
|
+
...props
|
|
1199
|
+
}
|
|
1200
|
+
);
|
|
1201
|
+
}
|
|
1202
|
+
var sidebarMenuButtonVariants = (0, import_class_variance_authority2.cva)(
|
|
1203
|
+
"peer/menu-button flex w-full items-center gap-2 overflow-hidden rounded-md p-2 text-left text-sm outline-hidden ring-sidebar-ring transition-[width,height,padding] hover:bg-sidebar-accent hover:text-sidebar-accent-foreground focus-visible:ring-2 active:bg-sidebar-accent active:text-sidebar-accent-foreground disabled:pointer-events-none disabled:opacity-50 group-has-data-[sidebar=menu-action]/menu-item:pr-8 aria-disabled:pointer-events-none aria-disabled:opacity-50 data-[active=true]:bg-sidebar-accent data-[active=true]:font-medium data-[active=true]:text-sidebar-accent-foreground data-[state=open]:hover:bg-sidebar-accent data-[state=open]:hover:text-sidebar-accent-foreground group-data-[collapsible=icon]:size-8! group-data-[collapsible=icon]:p-2! [&>span:last-child]:truncate [&>svg]:size-4 [&>svg]:shrink-0",
|
|
1204
|
+
{
|
|
1205
|
+
variants: {
|
|
1206
|
+
variant: {
|
|
1207
|
+
default: "hover:bg-sidebar-accent hover:text-sidebar-accent-foreground",
|
|
1208
|
+
outline: "bg-background shadow-[0_0_0_1px_hsl(var(--sidebar-border))] hover:bg-sidebar-accent hover:text-sidebar-accent-foreground hover:shadow-[0_0_0_1px_hsl(var(--sidebar-accent))]"
|
|
1209
|
+
},
|
|
1210
|
+
size: {
|
|
1211
|
+
default: "h-8 text-sm",
|
|
1212
|
+
sm: "h-7 text-xs",
|
|
1213
|
+
lg: "h-12 text-sm group-data-[collapsible=icon]:p-0!"
|
|
1214
|
+
}
|
|
589
1215
|
},
|
|
1216
|
+
defaultVariants: {
|
|
1217
|
+
variant: "default",
|
|
1218
|
+
size: "default"
|
|
1219
|
+
}
|
|
1220
|
+
}
|
|
1221
|
+
);
|
|
1222
|
+
function SidebarMenuButton({
|
|
1223
|
+
asChild = false,
|
|
1224
|
+
isActive = false,
|
|
1225
|
+
variant = "default",
|
|
1226
|
+
size = "default",
|
|
1227
|
+
tooltip,
|
|
1228
|
+
className,
|
|
1229
|
+
...props
|
|
1230
|
+
}) {
|
|
1231
|
+
const Comp = asChild ? import_react_slot2.Slot : "button";
|
|
1232
|
+
const { isMobile, state } = useSidebar();
|
|
1233
|
+
const button = /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
|
|
1234
|
+
Comp,
|
|
590
1235
|
{
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
|
|
1236
|
+
"data-slot": "sidebar-menu-button",
|
|
1237
|
+
"data-sidebar": "menu-button",
|
|
1238
|
+
"data-size": size,
|
|
1239
|
+
"data-active": isActive,
|
|
1240
|
+
className: cn(sidebarMenuButtonVariants({ variant, size }), className),
|
|
1241
|
+
...props
|
|
594
1242
|
}
|
|
595
|
-
|
|
596
|
-
if (
|
|
597
|
-
return
|
|
1243
|
+
);
|
|
1244
|
+
if (!tooltip) {
|
|
1245
|
+
return button;
|
|
598
1246
|
}
|
|
599
|
-
if (
|
|
600
|
-
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
|
|
1247
|
+
if (typeof tooltip === "string") {
|
|
1248
|
+
tooltip = {
|
|
1249
|
+
children: tooltip
|
|
1250
|
+
};
|
|
1251
|
+
}
|
|
1252
|
+
return /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(Tooltip, { children: [
|
|
1253
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)(TooltipTrigger, { asChild: true, children: button }),
|
|
1254
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
|
|
1255
|
+
TooltipContent,
|
|
1256
|
+
{
|
|
1257
|
+
side: "right",
|
|
1258
|
+
align: "center",
|
|
1259
|
+
hidden: state !== "collapsed" || isMobile,
|
|
1260
|
+
...tooltip
|
|
1261
|
+
}
|
|
1262
|
+
)
|
|
1263
|
+
] });
|
|
1264
|
+
}
|
|
1265
|
+
|
|
1266
|
+
// src/components/layout/AdminSidebar.tsx
|
|
1267
|
+
var import_lucide_react4 = require("lucide-react");
|
|
1268
|
+
|
|
1269
|
+
// src/components/ui/select.tsx
|
|
1270
|
+
var React4 = __toESM(require("react"), 1);
|
|
1271
|
+
var SelectPrimitive = __toESM(require("@radix-ui/react-select"), 1);
|
|
1272
|
+
var import_lucide_react3 = require("lucide-react");
|
|
1273
|
+
var import_jsx_runtime8 = require("react/jsx-runtime");
|
|
1274
|
+
var Select = SelectPrimitive.Root;
|
|
1275
|
+
var SelectValue = SelectPrimitive.Value;
|
|
1276
|
+
var SelectTrigger = React4.forwardRef(({ className, children, ...props }, ref) => /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(
|
|
1277
|
+
SelectPrimitive.Trigger,
|
|
1278
|
+
{
|
|
1279
|
+
ref,
|
|
1280
|
+
className: cn(
|
|
1281
|
+
"flex h-9 w-full items-center justify-between gap-2 rounded-md border border-input bg-transparent px-3 py-1 text-sm shadow-xs outline-none transition-colors placeholder:text-muted-foreground focus:ring-2 focus:ring-ring/40 disabled:cursor-not-allowed disabled:opacity-50",
|
|
1282
|
+
className
|
|
1283
|
+
),
|
|
1284
|
+
...props,
|
|
1285
|
+
children: [
|
|
1286
|
+
children,
|
|
1287
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)(SelectPrimitive.Icon, { asChild: true, children: /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(import_lucide_react3.ChevronDown, { className: "h-4 w-4 opacity-50" }) })
|
|
1288
|
+
]
|
|
1289
|
+
}
|
|
1290
|
+
));
|
|
1291
|
+
SelectTrigger.displayName = SelectPrimitive.Trigger.displayName;
|
|
1292
|
+
var SelectContent = React4.forwardRef(({ className, children, position = "popper", ...props }, ref) => /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(SelectPrimitive.Portal, { children: /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(
|
|
1293
|
+
SelectPrimitive.Content,
|
|
1294
|
+
{
|
|
1295
|
+
ref,
|
|
1296
|
+
className: cn(
|
|
1297
|
+
"relative z-50 min-w-[8rem] overflow-hidden rounded-md border bg-popover text-popover-foreground shadow-md",
|
|
1298
|
+
position === "popper" && "translate-y-1",
|
|
1299
|
+
className
|
|
1300
|
+
),
|
|
1301
|
+
position,
|
|
1302
|
+
...props,
|
|
1303
|
+
children: [
|
|
1304
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)(SelectPrimitive.ScrollUpButton, { className: "flex cursor-default items-center justify-center py-1", children: /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(import_lucide_react3.ChevronUp, { className: "h-4 w-4" }) }),
|
|
1305
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
|
|
1306
|
+
SelectPrimitive.Viewport,
|
|
604
1307
|
{
|
|
605
|
-
|
|
606
|
-
|
|
607
|
-
|
|
1308
|
+
className: cn(
|
|
1309
|
+
"p-1",
|
|
1310
|
+
position === "popper" && "h-[var(--radix-select-trigger-height)] w-full min-w-[var(--radix-select-trigger-width)]"
|
|
1311
|
+
),
|
|
1312
|
+
children
|
|
608
1313
|
}
|
|
609
|
-
)
|
|
610
|
-
|
|
1314
|
+
),
|
|
1315
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)(SelectPrimitive.ScrollDownButton, { className: "flex cursor-default items-center justify-center py-1", children: /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(import_lucide_react3.ChevronDown, { className: "h-4 w-4" }) })
|
|
1316
|
+
]
|
|
1317
|
+
}
|
|
1318
|
+
) }));
|
|
1319
|
+
SelectContent.displayName = SelectPrimitive.Content.displayName;
|
|
1320
|
+
var SelectItem = React4.forwardRef(({ className, children, ...props }, ref) => /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(
|
|
1321
|
+
SelectPrimitive.Item,
|
|
1322
|
+
{
|
|
1323
|
+
ref,
|
|
1324
|
+
className: cn(
|
|
1325
|
+
"relative flex w-full cursor-default select-none items-center rounded-sm py-1.5 pl-2 pr-8 text-sm outline-none focus:bg-accent focus:text-accent-foreground data-[disabled]:pointer-events-none data-[disabled]:opacity-50",
|
|
1326
|
+
className
|
|
1327
|
+
),
|
|
1328
|
+
...props,
|
|
1329
|
+
children: [
|
|
1330
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)(SelectPrimitive.ItemText, { children }),
|
|
1331
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)(SelectPrimitive.ItemIndicator, { className: "absolute right-2 inline-flex items-center justify-center", children: /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(import_lucide_react3.Check, { className: "h-4 w-4" }) })
|
|
1332
|
+
]
|
|
611
1333
|
}
|
|
612
|
-
|
|
613
|
-
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
|
|
617
|
-
|
|
618
|
-
|
|
619
|
-
|
|
620
|
-
|
|
1334
|
+
));
|
|
1335
|
+
SelectItem.displayName = SelectPrimitive.Item.displayName;
|
|
1336
|
+
|
|
1337
|
+
// src/components/layout/AdminSidebar.tsx
|
|
1338
|
+
var import_jsx_runtime9 = require("react/jsx-runtime");
|
|
1339
|
+
var NAV_ITEMS = [
|
|
1340
|
+
{ page: "dashboard", label: "Dashboard", icon: import_lucide_react4.LayoutDashboard },
|
|
1341
|
+
{ page: "threads", label: "Threads", icon: import_lucide_react4.MessageSquare, featureKey: "showThreads" },
|
|
1342
|
+
{ page: "participants", label: "Participants", icon: import_lucide_react4.Users, featureKey: "showParticipants" },
|
|
1343
|
+
{ page: "agents", label: "Agents", icon: import_lucide_react4.Bot, featureKey: "showAgents" },
|
|
1344
|
+
{ page: "events", label: "Events", icon: import_lucide_react4.Activity, featureKey: "showEvents" }
|
|
1345
|
+
];
|
|
1346
|
+
var AdminSidebar = ({
|
|
1347
|
+
config,
|
|
1348
|
+
currentPage,
|
|
1349
|
+
currentRoute,
|
|
1350
|
+
onNavigate,
|
|
1351
|
+
onNavigateRoute,
|
|
1352
|
+
collections,
|
|
1353
|
+
namespace,
|
|
1354
|
+
onNamespaceChange
|
|
1355
|
+
}) => {
|
|
1356
|
+
const visibleItems = NAV_ITEMS.filter(
|
|
1357
|
+
(item) => !item.featureKey || config.features[item.featureKey]
|
|
1358
|
+
);
|
|
1359
|
+
const showCollections = config.features.showCollections && collections.length > 0;
|
|
1360
|
+
return /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)(Sidebar, { collapsible: config.sidebar.collapsible, children: [
|
|
1361
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsx)(SidebarHeader, { children: /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("div", { className: "flex items-center gap-3 px-2 py-3", children: [
|
|
1362
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsx)("div", { className: "flex items-center justify-center shrink-0", children: config.branding.logo || /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("div", { className: "flex h-8 w-8 items-center justify-center rounded-lg bg-primary text-primary-foreground", children: /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(import_lucide_react4.LayoutDashboard, { className: "h-4 w-4" }) }) }),
|
|
1363
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("div", { className: "flex flex-col min-w-0 group-data-[collapsible=icon]:hidden", children: [
|
|
1364
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsx)("span", { className: "text-sm font-semibold truncate", children: config.branding.title }),
|
|
1365
|
+
config.branding.subtitle && /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("span", { className: "text-xs text-muted-foreground truncate", children: config.branding.subtitle })
|
|
1366
|
+
] })
|
|
1367
|
+
] }) }),
|
|
1368
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsxs)(SidebarContent, { children: [
|
|
1369
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsxs)(SidebarGroup, { children: [
|
|
1370
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsx)(SidebarGroupLabel, { className: "group-data-[collapsible=icon]:hidden", children: "Navigation" }),
|
|
1371
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsx)(SidebarGroupContent, { children: /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(SidebarMenu, { children: visibleItems.map((item) => {
|
|
1372
|
+
const Icon2 = item.icon;
|
|
1373
|
+
const label = config.labels[`${item.page}Title`] || item.label;
|
|
1374
|
+
return /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(SidebarMenuItem, { children: /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)(
|
|
1375
|
+
SidebarMenuButton,
|
|
1376
|
+
{
|
|
1377
|
+
isActive: currentPage === item.page,
|
|
1378
|
+
onClick: () => onNavigate(item.page),
|
|
1379
|
+
tooltip: label,
|
|
1380
|
+
children: [
|
|
1381
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsx)(Icon2, {}),
|
|
1382
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsx)("span", { children: label })
|
|
1383
|
+
]
|
|
1384
|
+
}
|
|
1385
|
+
) }, item.page);
|
|
1386
|
+
}) }) })
|
|
1387
|
+
] }),
|
|
1388
|
+
showCollections && /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)(import_jsx_runtime9.Fragment, { children: [
|
|
1389
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsx)(SidebarSeparator, {}),
|
|
1390
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsxs)(SidebarGroup, { children: [
|
|
1391
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsx)(SidebarGroupLabel, { className: "group-data-[collapsible=icon]:hidden", children: config.labels.collectionsTitle }),
|
|
1392
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsx)(SidebarGroupContent, { children: /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(SidebarMenu, { children: collections.map((col) => /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(SidebarMenuItem, { children: /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)(
|
|
1393
|
+
SidebarMenuButton,
|
|
1394
|
+
{
|
|
1395
|
+
isActive: currentRoute.page === "collection-items" && currentRoute.collection === col,
|
|
1396
|
+
onClick: () => onNavigateRoute({ page: "collection-items", collection: col }),
|
|
1397
|
+
tooltip: col,
|
|
1398
|
+
children: [
|
|
1399
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsx)(import_lucide_react4.Database, {}),
|
|
1400
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsx)("span", { className: "capitalize", children: col })
|
|
1401
|
+
]
|
|
1402
|
+
}
|
|
1403
|
+
) }, col)) }) })
|
|
1404
|
+
] })
|
|
1405
|
+
] })
|
|
1406
|
+
] }),
|
|
1407
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsxs)(SidebarFooter, { children: [
|
|
1408
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("div", { className: "group-data-[collapsible=icon]:hidden", children: [
|
|
1409
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsx)("label", { className: "text-xs font-medium text-muted-foreground mb-1 block px-2", children: "Namespace" }),
|
|
1410
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsxs)(Select, { value: namespace || "__all__", onValueChange: (v) => onNamespaceChange(v === "__all__" ? "" : v), children: [
|
|
1411
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsx)(SelectTrigger, { className: "h-8 text-xs", children: /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(SelectValue, { placeholder: "All namespaces" }) }),
|
|
1412
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsxs)(SelectContent, { children: [
|
|
1413
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsx)(SelectItem, { value: "__all__", children: "All namespaces" }),
|
|
1414
|
+
config.namespace && /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(SelectItem, { value: config.namespace, children: config.namespace })
|
|
621
1415
|
] })
|
|
622
|
-
] })
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
|
|
1416
|
+
] })
|
|
1417
|
+
] }),
|
|
1418
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsx)("div", { className: "hidden group-data-[collapsible=icon]:flex justify-center", children: /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(import_lucide_react4.ChevronsUpDown, { className: "h-4 w-4 text-muted-foreground" }) })
|
|
1419
|
+
] }),
|
|
1420
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsx)(SidebarRail, {})
|
|
1421
|
+
] });
|
|
1422
|
+
};
|
|
1423
|
+
|
|
1424
|
+
// src/components/layout/AdminHeader.tsx
|
|
1425
|
+
var import_lucide_react5 = require("lucide-react");
|
|
1426
|
+
var import_jsx_runtime10 = require("react/jsx-runtime");
|
|
1427
|
+
var PAGE_TITLES = {
|
|
1428
|
+
dashboard: "Dashboard",
|
|
1429
|
+
threads: "Threads",
|
|
1430
|
+
"thread-detail": "Thread Detail",
|
|
1431
|
+
participants: "Participants",
|
|
1432
|
+
"participant-detail": "Participant Detail",
|
|
1433
|
+
agents: "Agents",
|
|
1434
|
+
"agent-detail": "Agent Detail",
|
|
1435
|
+
"collection-items": "Collection",
|
|
1436
|
+
"collection-item-detail": "Item Detail",
|
|
1437
|
+
events: "Events"
|
|
1438
|
+
};
|
|
1439
|
+
var AdminHeader = ({
|
|
1440
|
+
config,
|
|
1441
|
+
currentRoute,
|
|
1442
|
+
range,
|
|
1443
|
+
interval,
|
|
1444
|
+
onRangeChange,
|
|
1445
|
+
onIntervalChange,
|
|
1446
|
+
onRefresh,
|
|
1447
|
+
isLoading
|
|
1448
|
+
}) => {
|
|
1449
|
+
let pageTitle = config.labels[`${currentRoute.page}Title`] || PAGE_TITLES[currentRoute.page] || currentRoute.page;
|
|
1450
|
+
if (currentRoute.page === "collection-items" && currentRoute.collection) {
|
|
1451
|
+
pageTitle = currentRoute.collection.charAt(0).toUpperCase() + currentRoute.collection.slice(1);
|
|
1452
|
+
}
|
|
1453
|
+
return /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(Card, { className: "py-0 border-b rounded-none relative z-10 bg-background/95 backdrop-blur supports-[backdrop-filter]:bg-background/80", children: /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(CardHeader, { className: "p-2", children: /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("div", { className: "flex items-center justify-between gap-2", children: [
|
|
1454
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("div", { className: "flex items-center gap-1", children: [
|
|
1455
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsxs)(Tooltip, { children: [
|
|
1456
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(SidebarTrigger, { className: "-ml-1" }) }),
|
|
1457
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)(TooltipContent, { children: "Toggle Sidebar" })
|
|
627
1458
|
] }),
|
|
628
|
-
/* @__PURE__ */ (0,
|
|
629
|
-
|
|
1459
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)("h1", { className: "text-sm font-medium ml-2", children: pageTitle })
|
|
1460
|
+
] }),
|
|
1461
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)("div", { className: "flex-1" }),
|
|
1462
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("div", { className: "flex items-center gap-1", children: [
|
|
1463
|
+
currentRoute.page === "dashboard" && /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)(import_jsx_runtime10.Fragment, { children: [
|
|
1464
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
|
|
630
1465
|
Button,
|
|
631
1466
|
{
|
|
632
|
-
variant:
|
|
1467
|
+
variant: range === "24h" ? "default" : "ghost",
|
|
633
1468
|
size: "sm",
|
|
634
|
-
|
|
1469
|
+
className: "h-7 text-xs",
|
|
1470
|
+
onClick: () => onRangeChange("24h"),
|
|
635
1471
|
children: config.labels.range24h
|
|
636
1472
|
}
|
|
637
1473
|
),
|
|
638
|
-
/* @__PURE__ */ (0,
|
|
1474
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
|
|
639
1475
|
Button,
|
|
640
1476
|
{
|
|
641
|
-
variant:
|
|
1477
|
+
variant: range === "7d" ? "default" : "ghost",
|
|
642
1478
|
size: "sm",
|
|
643
|
-
|
|
1479
|
+
className: "h-7 text-xs",
|
|
1480
|
+
onClick: () => onRangeChange("7d"),
|
|
644
1481
|
children: config.labels.range7d
|
|
645
1482
|
}
|
|
646
1483
|
),
|
|
647
|
-
/* @__PURE__ */ (0,
|
|
1484
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
|
|
648
1485
|
Button,
|
|
649
1486
|
{
|
|
650
|
-
variant:
|
|
1487
|
+
variant: range === "30d" ? "default" : "ghost",
|
|
651
1488
|
size: "sm",
|
|
652
|
-
|
|
1489
|
+
className: "h-7 text-xs",
|
|
1490
|
+
onClick: () => onRangeChange("30d"),
|
|
653
1491
|
children: config.labels.range30d
|
|
654
1492
|
}
|
|
655
1493
|
),
|
|
656
|
-
/* @__PURE__ */ (0,
|
|
1494
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsxs)(
|
|
657
1495
|
Select,
|
|
658
1496
|
{
|
|
659
|
-
value:
|
|
660
|
-
onValueChange: (v) =>
|
|
1497
|
+
value: interval,
|
|
1498
|
+
onValueChange: (v) => onIntervalChange(v),
|
|
661
1499
|
children: [
|
|
662
|
-
/* @__PURE__ */ (0,
|
|
663
|
-
/* @__PURE__ */ (0,
|
|
664
|
-
/* @__PURE__ */ (0,
|
|
665
|
-
/* @__PURE__ */ (0,
|
|
1500
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)(SelectTrigger, { className: "h-7 w-[90px] text-xs", children: /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(SelectValue, {}) }),
|
|
1501
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsxs)(SelectContent, { children: [
|
|
1502
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)(SelectItem, { value: "hour", children: config.labels.intervalHour }),
|
|
1503
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)(SelectItem, { value: "day", children: config.labels.intervalDay })
|
|
666
1504
|
] })
|
|
667
1505
|
]
|
|
668
1506
|
}
|
|
669
|
-
)
|
|
670
|
-
|
|
1507
|
+
)
|
|
1508
|
+
] }),
|
|
1509
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsxs)(Tooltip, { children: [
|
|
1510
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
|
|
671
1511
|
Button,
|
|
672
1512
|
{
|
|
673
|
-
variant: "
|
|
674
|
-
size: "
|
|
675
|
-
|
|
676
|
-
|
|
1513
|
+
variant: "ghost",
|
|
1514
|
+
size: "icon",
|
|
1515
|
+
className: "h-7 w-7",
|
|
1516
|
+
onClick: onRefresh,
|
|
1517
|
+
disabled: isLoading,
|
|
1518
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
|
|
1519
|
+
import_lucide_react5.RefreshCw,
|
|
1520
|
+
{
|
|
1521
|
+
className: `h-4 w-4 ${isLoading ? "animate-spin" : ""}`
|
|
1522
|
+
}
|
|
1523
|
+
)
|
|
677
1524
|
}
|
|
678
|
-
),
|
|
679
|
-
config.
|
|
680
|
-
] })
|
|
1525
|
+
) }),
|
|
1526
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)(TooltipContent, { children: config.labels.refresh })
|
|
1527
|
+
] }),
|
|
1528
|
+
config.branding.actions
|
|
1529
|
+
] })
|
|
1530
|
+
] }) }) });
|
|
1531
|
+
};
|
|
1532
|
+
|
|
1533
|
+
// src/components/ui/badge.tsx
|
|
1534
|
+
var import_react_slot3 = require("@radix-ui/react-slot");
|
|
1535
|
+
var import_class_variance_authority3 = require("class-variance-authority");
|
|
1536
|
+
var import_jsx_runtime11 = require("react/jsx-runtime");
|
|
1537
|
+
var badgeVariants = (0, import_class_variance_authority3.cva)(
|
|
1538
|
+
"inline-flex items-center justify-center rounded-md border px-2 py-0.5 text-xs font-medium w-fit whitespace-nowrap shrink-0 [&>svg]:size-3 gap-1 [&>svg]:pointer-events-none focus-visible:border-ring focus-visible:ring-ring/50 focus-visible:ring-[3px] aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive transition-[color,box-shadow] overflow-hidden",
|
|
1539
|
+
{
|
|
1540
|
+
variants: {
|
|
1541
|
+
variant: {
|
|
1542
|
+
default: "border-transparent bg-primary text-primary-foreground [a&]:hover:bg-primary/90",
|
|
1543
|
+
secondary: "border-transparent bg-secondary text-secondary-foreground [a&]:hover:bg-secondary/90",
|
|
1544
|
+
destructive: "border-transparent bg-destructive text-white [a&]:hover:bg-destructive/90 focus-visible:ring-destructive/20 dark:focus-visible:ring-destructive/40 dark:bg-destructive/60",
|
|
1545
|
+
outline: "text-foreground [a&]:hover:bg-accent [a&]:hover:text-accent-foreground"
|
|
1546
|
+
}
|
|
1547
|
+
},
|
|
1548
|
+
defaultVariants: {
|
|
1549
|
+
variant: "default"
|
|
1550
|
+
}
|
|
1551
|
+
}
|
|
1552
|
+
);
|
|
1553
|
+
function Badge({
|
|
1554
|
+
className,
|
|
1555
|
+
variant,
|
|
1556
|
+
asChild = false,
|
|
1557
|
+
...props
|
|
1558
|
+
}) {
|
|
1559
|
+
const Comp = asChild ? import_react_slot3.Slot : "span";
|
|
1560
|
+
return /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
|
|
1561
|
+
Comp,
|
|
1562
|
+
{
|
|
1563
|
+
"data-slot": "badge",
|
|
1564
|
+
className: cn(badgeVariants({ variant }), className),
|
|
1565
|
+
...props
|
|
1566
|
+
}
|
|
1567
|
+
);
|
|
1568
|
+
}
|
|
1569
|
+
|
|
1570
|
+
// src/components/views/DashboardView.tsx
|
|
1571
|
+
var import_jsx_runtime12 = require("react/jsx-runtime");
|
|
1572
|
+
var DashboardView = ({
|
|
1573
|
+
config,
|
|
1574
|
+
overview,
|
|
1575
|
+
activity,
|
|
1576
|
+
threads,
|
|
1577
|
+
participants,
|
|
1578
|
+
agents,
|
|
1579
|
+
interval,
|
|
1580
|
+
threadSearch,
|
|
1581
|
+
participantSearch,
|
|
1582
|
+
agentSearch,
|
|
1583
|
+
onThreadSearchChange,
|
|
1584
|
+
onParticipantSearchChange,
|
|
1585
|
+
onAgentSearchChange,
|
|
1586
|
+
onThreadClick
|
|
1587
|
+
}) => {
|
|
1588
|
+
const cards = [
|
|
1589
|
+
{
|
|
1590
|
+
label: config.labels.messagesCard,
|
|
1591
|
+
value: overview?.messageTotals.total ?? 0,
|
|
1592
|
+
detail: `${overview?.messageTotals.toolCallMessages ?? 0} tool-call messages`
|
|
1593
|
+
},
|
|
1594
|
+
{
|
|
1595
|
+
label: config.labels.activeThreadsCard,
|
|
1596
|
+
value: overview?.threadTotals.active ?? 0,
|
|
1597
|
+
detail: `${overview?.threadTotals.total ?? 0} total threads`
|
|
1598
|
+
},
|
|
1599
|
+
{
|
|
1600
|
+
label: config.labels.participantsCard,
|
|
1601
|
+
value: overview?.participantTotals.total ?? 0,
|
|
1602
|
+
detail: `${overview?.participantTotals.agents ?? 0} agents`
|
|
1603
|
+
},
|
|
1604
|
+
{
|
|
1605
|
+
label: config.labels.tokensCard,
|
|
1606
|
+
value: overview?.llmTotals.totalTokens ?? 0,
|
|
1607
|
+
detail: `${overview?.llmTotals.totalCalls ?? 0} calls`
|
|
1608
|
+
},
|
|
1609
|
+
{
|
|
1610
|
+
label: config.labels.queueCard,
|
|
1611
|
+
value: overview?.queueTotals.pending ?? 0,
|
|
1612
|
+
detail: `${overview?.queueTotals.failed ?? 0} failed`
|
|
1613
|
+
}
|
|
1614
|
+
];
|
|
1615
|
+
const isEmpty = cards.every((card) => card.value === 0) && activity.length === 0 && threads.length === 0 && participants.length === 0 && agents.length === 0;
|
|
1616
|
+
return /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("div", { className: "space-y-6", children: [
|
|
1617
|
+
isEmpty && /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("div", { className: "rounded-xl border border-dashed p-10 text-center", children: [
|
|
1618
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)("h3", { className: "text-lg font-semibold", children: config.labels.emptyTitle }),
|
|
1619
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)("p", { className: "mt-2 text-sm text-muted-foreground", children: config.labels.emptyDescription })
|
|
681
1620
|
] }),
|
|
682
|
-
|
|
683
|
-
/* @__PURE__ */ (0,
|
|
684
|
-
/* @__PURE__ */ (0,
|
|
685
|
-
] }) : null,
|
|
686
|
-
config.features.showOverview ? /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("section", { className: "space-y-4", children: [
|
|
687
|
-
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)(SectionHeading, { title: config.labels.overviewTitle }),
|
|
688
|
-
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { className: "grid grid-cols-2 gap-4 md:grid-cols-3 lg:grid-cols-5", children: cards.map((card) => /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(
|
|
1621
|
+
config.features.showOverview && /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("section", { className: "space-y-4", children: [
|
|
1622
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)(SectionHeading, { title: config.labels.overviewTitle }),
|
|
1623
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)("div", { className: "grid grid-cols-2 gap-4 md:grid-cols-3 lg:grid-cols-5", children: cards.map((card) => /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)(
|
|
689
1624
|
"div",
|
|
690
1625
|
{
|
|
691
|
-
className: "rounded-xl border bg-
|
|
1626
|
+
className: "rounded-xl border bg-card p-5 shadow-sm",
|
|
692
1627
|
children: [
|
|
693
|
-
/* @__PURE__ */ (0,
|
|
694
|
-
/* @__PURE__ */ (0,
|
|
695
|
-
/* @__PURE__ */ (0,
|
|
1628
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)("p", { className: "text-sm font-medium text-muted-foreground", children: card.label }),
|
|
1629
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)("p", { className: "mt-3 text-3xl font-semibold tracking-tight", children: formatNumber(card.value) }),
|
|
1630
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)("p", { className: "mt-2 text-xs text-muted-foreground", children: card.detail })
|
|
696
1631
|
]
|
|
697
1632
|
},
|
|
698
1633
|
card.label
|
|
699
1634
|
)) })
|
|
700
|
-
] })
|
|
701
|
-
config.features.showActivity
|
|
702
|
-
/* @__PURE__ */ (0,
|
|
703
|
-
/* @__PURE__ */ (0,
|
|
1635
|
+
] }),
|
|
1636
|
+
config.features.showActivity && /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("section", { className: "space-y-4", children: [
|
|
1637
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)(SectionHeading, { title: config.labels.activityTitle }),
|
|
1638
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
|
|
704
1639
|
ActivityChart,
|
|
705
1640
|
{
|
|
706
|
-
interval
|
|
1641
|
+
interval,
|
|
707
1642
|
labels: config.labels,
|
|
708
1643
|
maxBars: config.ui.maxActivityBars,
|
|
709
|
-
points:
|
|
1644
|
+
points: activity
|
|
710
1645
|
}
|
|
711
1646
|
)
|
|
712
|
-
] })
|
|
713
|
-
/* @__PURE__ */ (0,
|
|
714
|
-
config.features.showThreads
|
|
1647
|
+
] }),
|
|
1648
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("div", { className: "grid gap-6 lg:grid-cols-3", children: [
|
|
1649
|
+
config.features.showThreads && /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
|
|
715
1650
|
DataTable,
|
|
716
1651
|
{
|
|
717
|
-
rows:
|
|
1652
|
+
rows: threads,
|
|
718
1653
|
searchPlaceholder: config.labels.threadSearchPlaceholder,
|
|
719
1654
|
searchValue: threadSearch,
|
|
720
|
-
setSearchValue:
|
|
1655
|
+
setSearchValue: onThreadSearchChange,
|
|
721
1656
|
title: config.labels.threadsTitle,
|
|
722
|
-
children: /* @__PURE__ */ (0,
|
|
1657
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
|
|
1658
|
+
ThreadsTable,
|
|
1659
|
+
{
|
|
1660
|
+
rows: threads,
|
|
1661
|
+
labels: config.labels,
|
|
1662
|
+
onThreadClick
|
|
1663
|
+
}
|
|
1664
|
+
)
|
|
723
1665
|
}
|
|
724
|
-
)
|
|
725
|
-
config.features.showParticipants
|
|
1666
|
+
),
|
|
1667
|
+
config.features.showParticipants && /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
|
|
726
1668
|
DataTable,
|
|
727
1669
|
{
|
|
728
|
-
rows:
|
|
1670
|
+
rows: participants,
|
|
729
1671
|
searchPlaceholder: config.labels.participantSearchPlaceholder,
|
|
730
1672
|
searchValue: participantSearch,
|
|
731
|
-
setSearchValue:
|
|
1673
|
+
setSearchValue: onParticipantSearchChange,
|
|
732
1674
|
title: config.labels.participantsTitle,
|
|
733
|
-
children: /* @__PURE__ */ (0,
|
|
734
|
-
ParticipantsTable,
|
|
735
|
-
{
|
|
736
|
-
rows: admin.participants,
|
|
737
|
-
labels: config.labels
|
|
738
|
-
}
|
|
739
|
-
)
|
|
1675
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(ParticipantsTable, { rows: participants, labels: config.labels })
|
|
740
1676
|
}
|
|
741
|
-
)
|
|
742
|
-
config.features.showAgents
|
|
1677
|
+
),
|
|
1678
|
+
config.features.showAgents && /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
|
|
743
1679
|
DataTable,
|
|
744
1680
|
{
|
|
745
|
-
rows:
|
|
1681
|
+
rows: agents,
|
|
746
1682
|
searchPlaceholder: config.labels.agentSearchPlaceholder,
|
|
747
1683
|
searchValue: agentSearch,
|
|
748
|
-
setSearchValue:
|
|
1684
|
+
setSearchValue: onAgentSearchChange,
|
|
749
1685
|
title: config.labels.agentsTitle,
|
|
750
|
-
children: /* @__PURE__ */ (0,
|
|
1686
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(AgentsTable, { rows: agents, labels: config.labels })
|
|
751
1687
|
}
|
|
752
|
-
)
|
|
1688
|
+
)
|
|
753
1689
|
] })
|
|
754
|
-
] })
|
|
1690
|
+
] });
|
|
755
1691
|
};
|
|
756
1692
|
function SectionHeading({ title }) {
|
|
757
|
-
return /* @__PURE__ */ (0,
|
|
1693
|
+
return /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("h3", { className: "text-lg font-semibold tracking-tight", children: title });
|
|
758
1694
|
}
|
|
759
1695
|
function ActivityChart(props) {
|
|
760
1696
|
const trimmedPoints = props.points.slice(-props.maxBars);
|
|
@@ -762,12 +1698,12 @@ function ActivityChart(props) {
|
|
|
762
1698
|
...trimmedPoints.map((point) => point.messageCount),
|
|
763
1699
|
1
|
|
764
1700
|
);
|
|
765
|
-
return /* @__PURE__ */ (0,
|
|
1701
|
+
return /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("div", { className: "rounded-xl border bg-card p-5 shadow-sm", children: trimmedPoints.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("p", { className: "text-sm text-muted-foreground", children: props.labels.noResults }) : /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("div", { className: "flex min-h-48 items-end gap-2", children: trimmedPoints.map((point) => /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)(
|
|
766
1702
|
"div",
|
|
767
1703
|
{
|
|
768
1704
|
className: "flex min-w-0 flex-1 flex-col items-center gap-2",
|
|
769
1705
|
children: [
|
|
770
|
-
/* @__PURE__ */ (0,
|
|
1706
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)("div", { className: "flex h-36 w-full items-end rounded-lg bg-muted px-1 pb-1", children: /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
|
|
771
1707
|
"div",
|
|
772
1708
|
{
|
|
773
1709
|
className: "w-full rounded-md bg-primary transition-all",
|
|
@@ -776,9 +1712,9 @@ function ActivityChart(props) {
|
|
|
776
1712
|
}
|
|
777
1713
|
}
|
|
778
1714
|
) }),
|
|
779
|
-
/* @__PURE__ */ (0,
|
|
780
|
-
/* @__PURE__ */ (0,
|
|
781
|
-
/* @__PURE__ */ (0,
|
|
1715
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("div", { className: "text-center", children: [
|
|
1716
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)("p", { className: "text-xs font-medium", children: formatBucket(point.bucket, props.interval) }),
|
|
1717
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("p", { className: "text-[11px] text-muted-foreground", children: [
|
|
782
1718
|
formatNumber(point.messageCount),
|
|
783
1719
|
" msg"
|
|
784
1720
|
] })
|
|
@@ -789,10 +1725,10 @@ function ActivityChart(props) {
|
|
|
789
1725
|
)) }) });
|
|
790
1726
|
}
|
|
791
1727
|
function DataTable(props) {
|
|
792
|
-
return /* @__PURE__ */ (0,
|
|
793
|
-
/* @__PURE__ */ (0,
|
|
794
|
-
/* @__PURE__ */ (0,
|
|
795
|
-
/* @__PURE__ */ (0,
|
|
1728
|
+
return /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("div", { className: "rounded-xl border bg-card p-5 shadow-sm", children: [
|
|
1729
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("div", { className: "mb-4 flex items-center justify-between gap-3", children: [
|
|
1730
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)(SectionHeading, { title: props.title }),
|
|
1731
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
|
|
796
1732
|
Input,
|
|
797
1733
|
{
|
|
798
1734
|
className: "h-8 w-full max-w-44",
|
|
@@ -802,24 +1738,29 @@ function DataTable(props) {
|
|
|
802
1738
|
}
|
|
803
1739
|
)
|
|
804
1740
|
] }),
|
|
805
|
-
props.rows.length === 0 ? /* @__PURE__ */ (0,
|
|
1741
|
+
props.rows.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("p", { className: "text-sm text-muted-foreground", children: "No results" }) : props.children
|
|
806
1742
|
] });
|
|
807
1743
|
}
|
|
808
1744
|
function ThreadsTable({
|
|
809
1745
|
rows,
|
|
810
|
-
labels
|
|
1746
|
+
labels,
|
|
1747
|
+
onThreadClick
|
|
811
1748
|
}) {
|
|
812
|
-
return /* @__PURE__ */ (0,
|
|
1749
|
+
return /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("div", { className: "space-y-3", children: rows.map((thread) => /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)(
|
|
813
1750
|
"div",
|
|
814
1751
|
{
|
|
815
|
-
className:
|
|
1752
|
+
className: cn(
|
|
1753
|
+
"rounded-lg border bg-muted/50 p-4",
|
|
1754
|
+
onThreadClick && "cursor-pointer hover:bg-muted transition-colors"
|
|
1755
|
+
),
|
|
1756
|
+
onClick: () => onThreadClick?.(thread.threadId),
|
|
816
1757
|
children: [
|
|
817
|
-
/* @__PURE__ */ (0,
|
|
818
|
-
/* @__PURE__ */ (0,
|
|
819
|
-
/* @__PURE__ */ (0,
|
|
820
|
-
/* @__PURE__ */ (0,
|
|
1758
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("div", { className: "flex items-start justify-between gap-3", children: [
|
|
1759
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("div", { className: "min-w-0", children: [
|
|
1760
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)("p", { className: "font-medium", children: thread.name }),
|
|
1761
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)("p", { className: "mt-1 truncate text-xs text-muted-foreground", children: thread.summary ?? thread.lastMessagePreview ?? "No summary yet" })
|
|
821
1762
|
] }),
|
|
822
|
-
/* @__PURE__ */ (0,
|
|
1763
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
|
|
823
1764
|
Badge,
|
|
824
1765
|
{
|
|
825
1766
|
variant: thread.status === "archived" ? "secondary" : "default",
|
|
@@ -827,16 +1768,16 @@ function ThreadsTable({
|
|
|
827
1768
|
}
|
|
828
1769
|
)
|
|
829
1770
|
] }),
|
|
830
|
-
/* @__PURE__ */ (0,
|
|
831
|
-
/* @__PURE__ */ (0,
|
|
1771
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("div", { className: "mt-3 flex flex-wrap gap-3 text-xs text-muted-foreground", children: [
|
|
1772
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("span", { children: [
|
|
832
1773
|
formatNumber(thread.messageCount),
|
|
833
1774
|
" messages"
|
|
834
1775
|
] }),
|
|
835
|
-
/* @__PURE__ */ (0,
|
|
1776
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("span", { children: [
|
|
836
1777
|
thread.participantIds.length,
|
|
837
1778
|
" participants"
|
|
838
1779
|
] }),
|
|
839
|
-
/* @__PURE__ */ (0,
|
|
1780
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)("span", { children: formatDate(thread.lastActivityAt) })
|
|
840
1781
|
] })
|
|
841
1782
|
]
|
|
842
1783
|
},
|
|
@@ -847,28 +1788,28 @@ function ParticipantsTable({
|
|
|
847
1788
|
rows,
|
|
848
1789
|
labels
|
|
849
1790
|
}) {
|
|
850
|
-
return /* @__PURE__ */ (0,
|
|
1791
|
+
return /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("div", { className: "space-y-3", children: rows.map((participant) => /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)(
|
|
851
1792
|
"div",
|
|
852
1793
|
{
|
|
853
1794
|
className: "rounded-lg border bg-muted/50 p-4",
|
|
854
1795
|
children: [
|
|
855
|
-
/* @__PURE__ */ (0,
|
|
856
|
-
/* @__PURE__ */ (0,
|
|
857
|
-
/* @__PURE__ */ (0,
|
|
858
|
-
/* @__PURE__ */ (0,
|
|
1796
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("div", { className: "flex items-start justify-between gap-3", children: [
|
|
1797
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("div", { className: "min-w-0", children: [
|
|
1798
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)("p", { className: "font-medium", children: participant.displayName }),
|
|
1799
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)("p", { className: "mt-1 text-xs uppercase tracking-[0.18em] text-muted-foreground", children: participant.participantType })
|
|
859
1800
|
] }),
|
|
860
|
-
/* @__PURE__ */ (0,
|
|
1801
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)(Badge, { variant: "outline", children: participant.isGlobal ? labels.scopeGlobal : labels.scopeScoped })
|
|
861
1802
|
] }),
|
|
862
|
-
/* @__PURE__ */ (0,
|
|
863
|
-
/* @__PURE__ */ (0,
|
|
1803
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("div", { className: "mt-3 flex flex-wrap gap-3 text-xs text-muted-foreground", children: [
|
|
1804
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("span", { children: [
|
|
864
1805
|
formatNumber(participant.messageCount),
|
|
865
1806
|
" messages"
|
|
866
1807
|
] }),
|
|
867
|
-
/* @__PURE__ */ (0,
|
|
1808
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("span", { children: [
|
|
868
1809
|
formatNumber(participant.threadCount),
|
|
869
1810
|
" threads"
|
|
870
1811
|
] }),
|
|
871
|
-
/* @__PURE__ */ (0,
|
|
1812
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)("span", { children: formatDate(participant.lastActivityAt) })
|
|
872
1813
|
] })
|
|
873
1814
|
]
|
|
874
1815
|
},
|
|
@@ -879,32 +1820,32 @@ function AgentsTable({
|
|
|
879
1820
|
rows,
|
|
880
1821
|
labels
|
|
881
1822
|
}) {
|
|
882
|
-
return /* @__PURE__ */ (0,
|
|
1823
|
+
return /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("div", { className: "space-y-3", children: rows.map((agent) => /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)(
|
|
883
1824
|
"div",
|
|
884
1825
|
{
|
|
885
1826
|
className: "rounded-lg border bg-muted/50 p-4",
|
|
886
1827
|
children: [
|
|
887
|
-
/* @__PURE__ */ (0,
|
|
888
|
-
/* @__PURE__ */ (0,
|
|
889
|
-
/* @__PURE__ */ (0,
|
|
890
|
-
/* @__PURE__ */ (0,
|
|
1828
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("div", { className: "flex items-start justify-between gap-3", children: [
|
|
1829
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("div", { className: "min-w-0", children: [
|
|
1830
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)("p", { className: "font-medium", children: agent.displayName }),
|
|
1831
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)("p", { className: "mt-1 truncate text-xs text-muted-foreground", children: agent.description ?? agent.agentId })
|
|
891
1832
|
] }),
|
|
892
|
-
/* @__PURE__ */ (0,
|
|
1833
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)(Badge, { variant: "outline", children: agent.isConfigured ? labels.configured : labels.unconfigured })
|
|
893
1834
|
] }),
|
|
894
|
-
/* @__PURE__ */ (0,
|
|
895
|
-
/* @__PURE__ */ (0,
|
|
1835
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("div", { className: "mt-3 grid grid-cols-2 gap-2 text-xs text-muted-foreground", children: [
|
|
1836
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("span", { children: [
|
|
896
1837
|
formatNumber(agent.messageCount),
|
|
897
1838
|
" messages"
|
|
898
1839
|
] }),
|
|
899
|
-
/* @__PURE__ */ (0,
|
|
1840
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("span", { children: [
|
|
900
1841
|
formatNumber(agent.llmCallCount),
|
|
901
1842
|
" LLM calls"
|
|
902
1843
|
] }),
|
|
903
|
-
/* @__PURE__ */ (0,
|
|
1844
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("span", { children: [
|
|
904
1845
|
formatNumber(agent.toolCallMessageCount),
|
|
905
1846
|
" tool calls"
|
|
906
1847
|
] }),
|
|
907
|
-
/* @__PURE__ */ (0,
|
|
1848
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("span", { children: [
|
|
908
1849
|
formatNumber(agent.totalTokens),
|
|
909
1850
|
" tokens"
|
|
910
1851
|
] })
|
|
@@ -940,16 +1881,1186 @@ function formatDate(value) {
|
|
|
940
1881
|
function formatNumber(value) {
|
|
941
1882
|
return new Intl.NumberFormat().format(value);
|
|
942
1883
|
}
|
|
1884
|
+
|
|
1885
|
+
// src/components/views/ThreadsView.tsx
|
|
1886
|
+
var import_lucide_react6 = require("lucide-react");
|
|
1887
|
+
var import_jsx_runtime13 = require("react/jsx-runtime");
|
|
1888
|
+
var ThreadsView = ({
|
|
1889
|
+
config,
|
|
1890
|
+
threads,
|
|
1891
|
+
searchValue,
|
|
1892
|
+
onSearchChange,
|
|
1893
|
+
onThreadClick
|
|
1894
|
+
}) => {
|
|
1895
|
+
return /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)("div", { className: "space-y-4", children: [
|
|
1896
|
+
/* @__PURE__ */ (0, import_jsx_runtime13.jsxs)("div", { className: "relative max-w-sm", children: [
|
|
1897
|
+
/* @__PURE__ */ (0, import_jsx_runtime13.jsx)(import_lucide_react6.Search, { className: "pointer-events-none absolute left-3 top-1/2 h-4 w-4 -translate-y-1/2 text-muted-foreground" }),
|
|
1898
|
+
/* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
|
|
1899
|
+
Input,
|
|
1900
|
+
{
|
|
1901
|
+
className: "pl-9",
|
|
1902
|
+
placeholder: config.labels.threadSearchPlaceholder,
|
|
1903
|
+
value: searchValue,
|
|
1904
|
+
onChange: (e) => onSearchChange(e.target.value)
|
|
1905
|
+
}
|
|
1906
|
+
)
|
|
1907
|
+
] }),
|
|
1908
|
+
threads.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)("div", { className: "rounded-xl border border-dashed p-10 text-center", children: [
|
|
1909
|
+
/* @__PURE__ */ (0, import_jsx_runtime13.jsx)(import_lucide_react6.MessageSquare, { className: "mx-auto h-8 w-8 text-muted-foreground/50" }),
|
|
1910
|
+
/* @__PURE__ */ (0, import_jsx_runtime13.jsx)("p", { className: "mt-3 text-sm text-muted-foreground", children: searchValue ? config.labels.noResults : config.labels.emptyDescription })
|
|
1911
|
+
] }) : /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("div", { className: "space-y-2", children: threads.map((thread) => /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)(
|
|
1912
|
+
"div",
|
|
1913
|
+
{
|
|
1914
|
+
className: "flex items-center gap-4 rounded-lg border bg-card p-4 transition-colors hover:bg-muted/50 cursor-pointer",
|
|
1915
|
+
onClick: () => onThreadClick?.(thread.threadId),
|
|
1916
|
+
children: [
|
|
1917
|
+
/* @__PURE__ */ (0, import_jsx_runtime13.jsxs)("div", { className: "flex-1 min-w-0", children: [
|
|
1918
|
+
/* @__PURE__ */ (0, import_jsx_runtime13.jsxs)("div", { className: "flex items-center gap-2", children: [
|
|
1919
|
+
/* @__PURE__ */ (0, import_jsx_runtime13.jsx)("p", { className: "font-medium truncate", children: thread.name }),
|
|
1920
|
+
/* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
|
|
1921
|
+
Badge,
|
|
1922
|
+
{
|
|
1923
|
+
variant: thread.status === "archived" ? "secondary" : "default",
|
|
1924
|
+
className: "shrink-0",
|
|
1925
|
+
children: thread.status === "archived" ? config.labels.statusArchived : config.labels.statusActive
|
|
1926
|
+
}
|
|
1927
|
+
)
|
|
1928
|
+
] }),
|
|
1929
|
+
/* @__PURE__ */ (0, import_jsx_runtime13.jsx)("p", { className: "mt-1 text-sm text-muted-foreground truncate", children: thread.summary ?? thread.lastMessagePreview ?? "No summary yet" })
|
|
1930
|
+
] }),
|
|
1931
|
+
/* @__PURE__ */ (0, import_jsx_runtime13.jsxs)("div", { className: "text-right text-xs text-muted-foreground shrink-0 space-y-1", children: [
|
|
1932
|
+
/* @__PURE__ */ (0, import_jsx_runtime13.jsxs)("p", { children: [
|
|
1933
|
+
formatNumber2(thread.messageCount),
|
|
1934
|
+
" messages"
|
|
1935
|
+
] }),
|
|
1936
|
+
/* @__PURE__ */ (0, import_jsx_runtime13.jsxs)("p", { children: [
|
|
1937
|
+
thread.participantIds.length,
|
|
1938
|
+
" participants"
|
|
1939
|
+
] }),
|
|
1940
|
+
/* @__PURE__ */ (0, import_jsx_runtime13.jsx)("p", { children: formatDate2(thread.lastActivityAt) })
|
|
1941
|
+
] })
|
|
1942
|
+
]
|
|
1943
|
+
},
|
|
1944
|
+
thread.threadId
|
|
1945
|
+
)) })
|
|
1946
|
+
] });
|
|
1947
|
+
};
|
|
1948
|
+
function formatDate2(value) {
|
|
1949
|
+
if (!value) return "No activity";
|
|
1950
|
+
const date = new Date(value);
|
|
1951
|
+
if (Number.isNaN(date.getTime())) return value;
|
|
1952
|
+
return date.toLocaleString(void 0, {
|
|
1953
|
+
month: "short",
|
|
1954
|
+
day: "numeric",
|
|
1955
|
+
hour: "numeric",
|
|
1956
|
+
minute: "2-digit"
|
|
1957
|
+
});
|
|
1958
|
+
}
|
|
1959
|
+
function formatNumber2(value) {
|
|
1960
|
+
return new Intl.NumberFormat().format(value);
|
|
1961
|
+
}
|
|
1962
|
+
|
|
1963
|
+
// src/components/views/ThreadDetailView.tsx
|
|
1964
|
+
var import_react2 = require("react");
|
|
1965
|
+
var import_lucide_react7 = require("lucide-react");
|
|
1966
|
+
var import_jsx_runtime14 = require("react/jsx-runtime");
|
|
1967
|
+
var MESSAGES_PAGE_SIZE = 50;
|
|
1968
|
+
var ThreadDetailView = ({
|
|
1969
|
+
threadId,
|
|
1970
|
+
config,
|
|
1971
|
+
onBack
|
|
1972
|
+
}) => {
|
|
1973
|
+
const [thread, setThread] = (0, import_react2.useState)(null);
|
|
1974
|
+
const [messages, setMessages] = (0, import_react2.useState)([]);
|
|
1975
|
+
const [pageInfo, setPageInfo] = (0, import_react2.useState)(null);
|
|
1976
|
+
const [isLoading, setIsLoading] = (0, import_react2.useState)(true);
|
|
1977
|
+
const [isLoadingMore, setIsLoadingMore] = (0, import_react2.useState)(false);
|
|
1978
|
+
const [error, setError] = (0, import_react2.useState)(null);
|
|
1979
|
+
const fetchOptions = {
|
|
1980
|
+
baseUrl: config.baseUrl,
|
|
1981
|
+
getRequestHeaders: config.getRequestHeaders
|
|
1982
|
+
};
|
|
1983
|
+
const loadInitial = (0, import_react2.useCallback)(async () => {
|
|
1984
|
+
setIsLoading(true);
|
|
1985
|
+
setError(null);
|
|
1986
|
+
try {
|
|
1987
|
+
const [threadData, messagesData] = await Promise.all([
|
|
1988
|
+
fetchThreadDetail(threadId, fetchOptions),
|
|
1989
|
+
fetchThreadMessages(threadId, { limit: MESSAGES_PAGE_SIZE }, fetchOptions)
|
|
1990
|
+
]);
|
|
1991
|
+
setThread(threadData);
|
|
1992
|
+
setMessages(messagesData.data);
|
|
1993
|
+
setPageInfo(messagesData.pageInfo);
|
|
1994
|
+
} catch (err) {
|
|
1995
|
+
setError(
|
|
1996
|
+
err instanceof Error ? err : new Error("Failed to load thread")
|
|
1997
|
+
);
|
|
1998
|
+
} finally {
|
|
1999
|
+
setIsLoading(false);
|
|
2000
|
+
}
|
|
2001
|
+
}, [threadId, config.baseUrl, config.getRequestHeaders]);
|
|
2002
|
+
(0, import_react2.useEffect)(() => {
|
|
2003
|
+
void loadInitial();
|
|
2004
|
+
}, [loadInitial]);
|
|
2005
|
+
const loadMore = (0, import_react2.useCallback)(async () => {
|
|
2006
|
+
if (!pageInfo?.hasMoreBefore || !pageInfo.oldestMessageId || isLoadingMore) {
|
|
2007
|
+
return;
|
|
2008
|
+
}
|
|
2009
|
+
setIsLoadingMore(true);
|
|
2010
|
+
try {
|
|
2011
|
+
const older = await fetchThreadMessages(
|
|
2012
|
+
threadId,
|
|
2013
|
+
{ limit: MESSAGES_PAGE_SIZE, before: pageInfo.oldestMessageId },
|
|
2014
|
+
fetchOptions
|
|
2015
|
+
);
|
|
2016
|
+
setMessages((prev) => [...older.data, ...prev]);
|
|
2017
|
+
setPageInfo(older.pageInfo);
|
|
2018
|
+
} catch {
|
|
2019
|
+
} finally {
|
|
2020
|
+
setIsLoadingMore(false);
|
|
2021
|
+
}
|
|
2022
|
+
}, [threadId, pageInfo, isLoadingMore, config.baseUrl, config.getRequestHeaders]);
|
|
2023
|
+
if (isLoading) {
|
|
2024
|
+
return /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("div", { className: "flex items-center justify-center py-20", children: /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(import_lucide_react7.Loader2, { className: "h-6 w-6 animate-spin text-muted-foreground" }) });
|
|
2025
|
+
}
|
|
2026
|
+
if (error) {
|
|
2027
|
+
return /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)("div", { className: "space-y-4 py-10 text-center", children: [
|
|
2028
|
+
/* @__PURE__ */ (0, import_jsx_runtime14.jsx)("p", { className: "text-destructive font-medium", children: error.message }),
|
|
2029
|
+
/* @__PURE__ */ (0, import_jsx_runtime14.jsxs)("div", { className: "flex justify-center gap-2", children: [
|
|
2030
|
+
/* @__PURE__ */ (0, import_jsx_runtime14.jsxs)(Button, { variant: "outline", onClick: onBack, children: [
|
|
2031
|
+
/* @__PURE__ */ (0, import_jsx_runtime14.jsx)(import_lucide_react7.ArrowLeft, { className: "mr-2 h-4 w-4" }),
|
|
2032
|
+
"Back"
|
|
2033
|
+
] }),
|
|
2034
|
+
/* @__PURE__ */ (0, import_jsx_runtime14.jsx)(Button, { variant: "destructive", onClick: () => void loadInitial(), children: config.labels.retry })
|
|
2035
|
+
] })
|
|
2036
|
+
] });
|
|
2037
|
+
}
|
|
2038
|
+
return /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)("div", { className: "space-y-6", children: [
|
|
2039
|
+
/* @__PURE__ */ (0, import_jsx_runtime14.jsxs)("div", { className: "flex items-start gap-4", children: [
|
|
2040
|
+
/* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
|
|
2041
|
+
Button,
|
|
2042
|
+
{
|
|
2043
|
+
variant: "ghost",
|
|
2044
|
+
size: "icon",
|
|
2045
|
+
className: "mt-1 shrink-0",
|
|
2046
|
+
onClick: onBack,
|
|
2047
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(import_lucide_react7.ArrowLeft, { className: "h-4 w-4" })
|
|
2048
|
+
}
|
|
2049
|
+
),
|
|
2050
|
+
/* @__PURE__ */ (0, import_jsx_runtime14.jsxs)("div", { className: "flex-1 min-w-0", children: [
|
|
2051
|
+
/* @__PURE__ */ (0, import_jsx_runtime14.jsxs)("div", { className: "flex items-center gap-2", children: [
|
|
2052
|
+
/* @__PURE__ */ (0, import_jsx_runtime14.jsx)("h2", { className: "text-xl font-semibold truncate", children: thread?.name ?? threadId }),
|
|
2053
|
+
/* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
|
|
2054
|
+
Badge,
|
|
2055
|
+
{
|
|
2056
|
+
variant: thread?.status === "archived" ? "secondary" : "default",
|
|
2057
|
+
children: thread?.status === "archived" ? config.labels.statusArchived : config.labels.statusActive
|
|
2058
|
+
}
|
|
2059
|
+
)
|
|
2060
|
+
] }),
|
|
2061
|
+
thread?.summary && /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("p", { className: "mt-1 text-sm text-muted-foreground", children: thread.summary }),
|
|
2062
|
+
/* @__PURE__ */ (0, import_jsx_runtime14.jsxs)("div", { className: "mt-2 flex flex-wrap gap-4 text-xs text-muted-foreground", children: [
|
|
2063
|
+
thread?.createdAt && /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)("span", { children: [
|
|
2064
|
+
"Created ",
|
|
2065
|
+
formatDate3(thread.createdAt)
|
|
2066
|
+
] }),
|
|
2067
|
+
thread?.updatedAt && /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)("span", { children: [
|
|
2068
|
+
"Updated ",
|
|
2069
|
+
formatDate3(thread.updatedAt)
|
|
2070
|
+
] }),
|
|
2071
|
+
thread?.participants && /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)("span", { children: [
|
|
2072
|
+
thread.participants.length,
|
|
2073
|
+
" participants"
|
|
2074
|
+
] })
|
|
2075
|
+
] })
|
|
2076
|
+
] })
|
|
2077
|
+
] }),
|
|
2078
|
+
/* @__PURE__ */ (0, import_jsx_runtime14.jsxs)("div", { className: "space-y-1", children: [
|
|
2079
|
+
/* @__PURE__ */ (0, import_jsx_runtime14.jsx)("div", { className: "flex items-center justify-between", children: /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)("h3", { className: "text-sm font-medium text-muted-foreground", children: [
|
|
2080
|
+
"Messages (",
|
|
2081
|
+
messages.length,
|
|
2082
|
+
pageInfo?.hasMoreBefore ? "+" : "",
|
|
2083
|
+
")"
|
|
2084
|
+
] }) }),
|
|
2085
|
+
pageInfo?.hasMoreBefore && /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("div", { className: "flex justify-center py-2", children: /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)(
|
|
2086
|
+
Button,
|
|
2087
|
+
{
|
|
2088
|
+
variant: "ghost",
|
|
2089
|
+
size: "sm",
|
|
2090
|
+
onClick: () => void loadMore(),
|
|
2091
|
+
disabled: isLoadingMore,
|
|
2092
|
+
children: [
|
|
2093
|
+
isLoadingMore ? /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(import_lucide_react7.Loader2, { className: "mr-2 h-3 w-3 animate-spin" }) : /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(import_lucide_react7.ChevronUp, { className: "mr-2 h-3 w-3" }),
|
|
2094
|
+
"Load older messages"
|
|
2095
|
+
]
|
|
2096
|
+
}
|
|
2097
|
+
) }),
|
|
2098
|
+
/* @__PURE__ */ (0, import_jsx_runtime14.jsx)("div", { className: "rounded-lg border bg-card", children: messages.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("p", { className: "p-6 text-center text-sm text-muted-foreground", children: "No messages in this thread yet." }) : /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("div", { className: "divide-y", children: messages.map((message) => /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(MessageRow, { message }, message.id)) }) })
|
|
2099
|
+
] })
|
|
2100
|
+
] });
|
|
2101
|
+
};
|
|
2102
|
+
function MessageRow({ message }) {
|
|
2103
|
+
const [expanded, setExpanded] = (0, import_react2.useState)(false);
|
|
2104
|
+
const hasToolCalls = Array.isArray(message.toolCalls) && message.toolCalls.length > 0;
|
|
2105
|
+
const hasReasoning = !!message.reasoning;
|
|
2106
|
+
return /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("div", { className: "px-4 py-3", children: /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)("div", { className: "flex items-start gap-3", children: [
|
|
2107
|
+
/* @__PURE__ */ (0, import_jsx_runtime14.jsx)(SenderIcon, { senderType: message.senderType }),
|
|
2108
|
+
/* @__PURE__ */ (0, import_jsx_runtime14.jsxs)("div", { className: "flex-1 min-w-0", children: [
|
|
2109
|
+
/* @__PURE__ */ (0, import_jsx_runtime14.jsxs)("div", { className: "flex items-center gap-2 text-xs", children: [
|
|
2110
|
+
/* @__PURE__ */ (0, import_jsx_runtime14.jsx)("span", { className: "font-medium", children: message.senderId ?? message.senderUserId ?? message.senderType }),
|
|
2111
|
+
/* @__PURE__ */ (0, import_jsx_runtime14.jsx)(Badge, { variant: "outline", className: "text-[10px] px-1.5 py-0", children: message.senderType }),
|
|
2112
|
+
message.createdAt && /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("span", { className: "text-muted-foreground", children: formatTimestamp(message.createdAt) })
|
|
2113
|
+
] }),
|
|
2114
|
+
message.content && /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("p", { className: "mt-1 text-sm whitespace-pre-wrap break-words", children: message.content }),
|
|
2115
|
+
(hasToolCalls || hasReasoning) && /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)("div", { className: "mt-2 space-y-2", children: [
|
|
2116
|
+
hasToolCalls && /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)(
|
|
2117
|
+
"button",
|
|
2118
|
+
{
|
|
2119
|
+
type: "button",
|
|
2120
|
+
onClick: () => setExpanded(!expanded),
|
|
2121
|
+
className: "inline-flex items-center gap-1 text-xs text-muted-foreground hover:text-foreground transition-colors",
|
|
2122
|
+
children: [
|
|
2123
|
+
/* @__PURE__ */ (0, import_jsx_runtime14.jsx)(import_lucide_react7.Wrench, { className: "h-3 w-3" }),
|
|
2124
|
+
message.toolCalls.length,
|
|
2125
|
+
" tool call",
|
|
2126
|
+
message.toolCalls.length > 1 ? "s" : ""
|
|
2127
|
+
]
|
|
2128
|
+
}
|
|
2129
|
+
),
|
|
2130
|
+
hasReasoning && /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)(
|
|
2131
|
+
"button",
|
|
2132
|
+
{
|
|
2133
|
+
type: "button",
|
|
2134
|
+
onClick: () => setExpanded(!expanded),
|
|
2135
|
+
className: "inline-flex items-center gap-1 text-xs text-muted-foreground hover:text-foreground transition-colors",
|
|
2136
|
+
children: [
|
|
2137
|
+
/* @__PURE__ */ (0, import_jsx_runtime14.jsx)(import_lucide_react7.Cpu, { className: "h-3 w-3" }),
|
|
2138
|
+
"Reasoning"
|
|
2139
|
+
]
|
|
2140
|
+
}
|
|
2141
|
+
),
|
|
2142
|
+
expanded && /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("pre", { className: "mt-2 rounded-md bg-muted p-3 text-xs overflow-auto max-h-60", children: JSON.stringify(
|
|
2143
|
+
{
|
|
2144
|
+
...hasToolCalls ? { toolCalls: message.toolCalls } : {},
|
|
2145
|
+
...hasReasoning ? { reasoning: message.reasoning } : {}
|
|
2146
|
+
},
|
|
2147
|
+
null,
|
|
2148
|
+
2
|
|
2149
|
+
) })
|
|
2150
|
+
] })
|
|
2151
|
+
] })
|
|
2152
|
+
] }) });
|
|
2153
|
+
}
|
|
2154
|
+
function SenderIcon({ senderType }) {
|
|
2155
|
+
const base = "flex h-7 w-7 shrink-0 items-center justify-center rounded-full";
|
|
2156
|
+
switch (senderType) {
|
|
2157
|
+
case "agent":
|
|
2158
|
+
return /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("div", { className: cn(base, "bg-primary/10 text-primary"), children: /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(import_lucide_react7.Bot, { className: "h-3.5 w-3.5" }) });
|
|
2159
|
+
case "user":
|
|
2160
|
+
return /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("div", { className: cn(base, "bg-secondary text-secondary-foreground"), children: /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(import_lucide_react7.User, { className: "h-3.5 w-3.5" }) });
|
|
2161
|
+
case "tool":
|
|
2162
|
+
return /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("div", { className: cn(base, "bg-muted text-muted-foreground"), children: /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(import_lucide_react7.Wrench, { className: "h-3.5 w-3.5" }) });
|
|
2163
|
+
default:
|
|
2164
|
+
return /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("div", { className: cn(base, "bg-muted text-muted-foreground"), children: /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(import_lucide_react7.Cpu, { className: "h-3.5 w-3.5" }) });
|
|
2165
|
+
}
|
|
2166
|
+
}
|
|
2167
|
+
function formatDate3(value) {
|
|
2168
|
+
const date = new Date(value);
|
|
2169
|
+
if (Number.isNaN(date.getTime())) return value;
|
|
2170
|
+
return date.toLocaleDateString(void 0, {
|
|
2171
|
+
month: "short",
|
|
2172
|
+
day: "numeric",
|
|
2173
|
+
year: "numeric"
|
|
2174
|
+
});
|
|
2175
|
+
}
|
|
2176
|
+
function formatTimestamp(value) {
|
|
2177
|
+
const date = new Date(value);
|
|
2178
|
+
if (Number.isNaN(date.getTime())) return value;
|
|
2179
|
+
return date.toLocaleString(void 0, {
|
|
2180
|
+
month: "short",
|
|
2181
|
+
day: "numeric",
|
|
2182
|
+
hour: "numeric",
|
|
2183
|
+
minute: "2-digit",
|
|
2184
|
+
second: "2-digit"
|
|
2185
|
+
});
|
|
2186
|
+
}
|
|
2187
|
+
|
|
2188
|
+
// src/components/views/ParticipantsView.tsx
|
|
2189
|
+
var import_lucide_react8 = require("lucide-react");
|
|
2190
|
+
var import_jsx_runtime15 = require("react/jsx-runtime");
|
|
2191
|
+
var ParticipantsView = ({
|
|
2192
|
+
config,
|
|
2193
|
+
participants,
|
|
2194
|
+
searchValue,
|
|
2195
|
+
onSearchChange,
|
|
2196
|
+
onParticipantClick
|
|
2197
|
+
}) => {
|
|
2198
|
+
return /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)("div", { className: "space-y-4", children: [
|
|
2199
|
+
/* @__PURE__ */ (0, import_jsx_runtime15.jsxs)("div", { className: "relative max-w-sm", children: [
|
|
2200
|
+
/* @__PURE__ */ (0, import_jsx_runtime15.jsx)(import_lucide_react8.Search, { className: "pointer-events-none absolute left-3 top-1/2 h-4 w-4 -translate-y-1/2 text-muted-foreground" }),
|
|
2201
|
+
/* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
|
|
2202
|
+
Input,
|
|
2203
|
+
{
|
|
2204
|
+
className: "pl-9",
|
|
2205
|
+
placeholder: config.labels.participantSearchPlaceholder,
|
|
2206
|
+
value: searchValue,
|
|
2207
|
+
onChange: (e) => onSearchChange(e.target.value)
|
|
2208
|
+
}
|
|
2209
|
+
)
|
|
2210
|
+
] }),
|
|
2211
|
+
participants.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)("div", { className: "rounded-xl border border-dashed p-10 text-center", children: [
|
|
2212
|
+
/* @__PURE__ */ (0, import_jsx_runtime15.jsx)(import_lucide_react8.Users, { className: "mx-auto h-8 w-8 text-muted-foreground/50" }),
|
|
2213
|
+
/* @__PURE__ */ (0, import_jsx_runtime15.jsx)("p", { className: "mt-3 text-sm text-muted-foreground", children: searchValue ? config.labels.noResults : config.labels.emptyDescription })
|
|
2214
|
+
] }) : /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("div", { className: "space-y-2", children: participants.map((p) => /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)(
|
|
2215
|
+
"div",
|
|
2216
|
+
{
|
|
2217
|
+
className: "flex items-center gap-4 rounded-lg border bg-card p-4 transition-colors hover:bg-muted/50 cursor-pointer",
|
|
2218
|
+
onClick: () => onParticipantClick?.(p.externalId),
|
|
2219
|
+
children: [
|
|
2220
|
+
/* @__PURE__ */ (0, import_jsx_runtime15.jsxs)("div", { className: "flex-1 min-w-0", children: [
|
|
2221
|
+
/* @__PURE__ */ (0, import_jsx_runtime15.jsxs)("div", { className: "flex items-center gap-2", children: [
|
|
2222
|
+
/* @__PURE__ */ (0, import_jsx_runtime15.jsx)("p", { className: "font-medium truncate", children: p.displayName }),
|
|
2223
|
+
/* @__PURE__ */ (0, import_jsx_runtime15.jsx)(Badge, { variant: "outline", className: "shrink-0 text-xs", children: p.participantType }),
|
|
2224
|
+
/* @__PURE__ */ (0, import_jsx_runtime15.jsx)(Badge, { variant: p.isGlobal ? "default" : "secondary", className: "shrink-0 text-xs", children: p.isGlobal ? config.labels.scopeGlobal : config.labels.scopeScoped })
|
|
2225
|
+
] }),
|
|
2226
|
+
/* @__PURE__ */ (0, import_jsx_runtime15.jsx)("p", { className: "mt-1 text-xs text-muted-foreground", children: p.externalId })
|
|
2227
|
+
] }),
|
|
2228
|
+
/* @__PURE__ */ (0, import_jsx_runtime15.jsxs)("div", { className: "text-right text-xs text-muted-foreground shrink-0 space-y-1", children: [
|
|
2229
|
+
/* @__PURE__ */ (0, import_jsx_runtime15.jsxs)("p", { children: [
|
|
2230
|
+
formatNumber3(p.messageCount),
|
|
2231
|
+
" messages"
|
|
2232
|
+
] }),
|
|
2233
|
+
/* @__PURE__ */ (0, import_jsx_runtime15.jsxs)("p", { children: [
|
|
2234
|
+
formatNumber3(p.threadCount),
|
|
2235
|
+
" threads"
|
|
2236
|
+
] }),
|
|
2237
|
+
/* @__PURE__ */ (0, import_jsx_runtime15.jsx)("p", { children: formatDate4(p.lastActivityAt) })
|
|
2238
|
+
] })
|
|
2239
|
+
]
|
|
2240
|
+
},
|
|
2241
|
+
`${p.namespace}:${p.externalId}`
|
|
2242
|
+
)) })
|
|
2243
|
+
] });
|
|
2244
|
+
};
|
|
2245
|
+
function formatDate4(value) {
|
|
2246
|
+
if (!value) return "No activity";
|
|
2247
|
+
const date = new Date(value);
|
|
2248
|
+
if (Number.isNaN(date.getTime())) return value;
|
|
2249
|
+
return date.toLocaleString(void 0, { month: "short", day: "numeric", hour: "numeric", minute: "2-digit" });
|
|
2250
|
+
}
|
|
2251
|
+
function formatNumber3(value) {
|
|
2252
|
+
return new Intl.NumberFormat().format(value);
|
|
2253
|
+
}
|
|
2254
|
+
|
|
2255
|
+
// src/components/views/ParticipantDetailView.tsx
|
|
2256
|
+
var import_react3 = require("react");
|
|
2257
|
+
var import_lucide_react9 = require("lucide-react");
|
|
2258
|
+
var import_jsx_runtime16 = require("react/jsx-runtime");
|
|
2259
|
+
var ParticipantDetailView = ({
|
|
2260
|
+
participantId,
|
|
2261
|
+
config,
|
|
2262
|
+
onBack
|
|
2263
|
+
}) => {
|
|
2264
|
+
const [data, setData] = (0, import_react3.useState)(null);
|
|
2265
|
+
const [editJson, setEditJson] = (0, import_react3.useState)("");
|
|
2266
|
+
const [isLoading, setIsLoading] = (0, import_react3.useState)(true);
|
|
2267
|
+
const [isSaving, setIsSaving] = (0, import_react3.useState)(false);
|
|
2268
|
+
const [error, setError] = (0, import_react3.useState)(null);
|
|
2269
|
+
const [saveMessage, setSaveMessage] = (0, import_react3.useState)(null);
|
|
2270
|
+
const fetchOptions = {
|
|
2271
|
+
baseUrl: config.baseUrl,
|
|
2272
|
+
getRequestHeaders: config.getRequestHeaders
|
|
2273
|
+
};
|
|
2274
|
+
const load = (0, import_react3.useCallback)(async () => {
|
|
2275
|
+
setIsLoading(true);
|
|
2276
|
+
setError(null);
|
|
2277
|
+
try {
|
|
2278
|
+
const result = await fetchParticipantDetail(participantId, fetchOptions);
|
|
2279
|
+
setData(result);
|
|
2280
|
+
setEditJson(JSON.stringify(result, null, 2));
|
|
2281
|
+
} catch (err) {
|
|
2282
|
+
setError(err instanceof Error ? err.message : "Failed to load participant");
|
|
2283
|
+
} finally {
|
|
2284
|
+
setIsLoading(false);
|
|
2285
|
+
}
|
|
2286
|
+
}, [participantId, config.baseUrl, config.getRequestHeaders]);
|
|
2287
|
+
(0, import_react3.useEffect)(() => {
|
|
2288
|
+
void load();
|
|
2289
|
+
}, [load]);
|
|
2290
|
+
const handleSave = async () => {
|
|
2291
|
+
setIsSaving(true);
|
|
2292
|
+
setError(null);
|
|
2293
|
+
setSaveMessage(null);
|
|
2294
|
+
try {
|
|
2295
|
+
const parsed = JSON.parse(editJson);
|
|
2296
|
+
const updated = await updateParticipant(participantId, parsed, fetchOptions);
|
|
2297
|
+
setData(updated);
|
|
2298
|
+
setEditJson(JSON.stringify(updated, null, 2));
|
|
2299
|
+
setSaveMessage("Saved successfully");
|
|
2300
|
+
setTimeout(() => setSaveMessage(null), 3e3);
|
|
2301
|
+
} catch (err) {
|
|
2302
|
+
setError(err instanceof Error ? err.message : "Failed to save");
|
|
2303
|
+
} finally {
|
|
2304
|
+
setIsSaving(false);
|
|
2305
|
+
}
|
|
2306
|
+
};
|
|
2307
|
+
if (isLoading) {
|
|
2308
|
+
return /* @__PURE__ */ (0, import_jsx_runtime16.jsx)("div", { className: "flex items-center justify-center py-20", children: /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(import_lucide_react9.Loader2, { className: "h-6 w-6 animate-spin text-muted-foreground" }) });
|
|
2309
|
+
}
|
|
2310
|
+
return /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)("div", { className: "space-y-6", children: [
|
|
2311
|
+
/* @__PURE__ */ (0, import_jsx_runtime16.jsxs)("div", { className: "flex items-center gap-4", children: [
|
|
2312
|
+
/* @__PURE__ */ (0, import_jsx_runtime16.jsx)(Button, { variant: "ghost", size: "icon", onClick: onBack, children: /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(import_lucide_react9.ArrowLeft, { className: "h-4 w-4" }) }),
|
|
2313
|
+
/* @__PURE__ */ (0, import_jsx_runtime16.jsxs)("div", { className: "flex-1 min-w-0", children: [
|
|
2314
|
+
/* @__PURE__ */ (0, import_jsx_runtime16.jsx)("h2", { className: "text-xl font-semibold truncate", children: participantId }),
|
|
2315
|
+
/* @__PURE__ */ (0, import_jsx_runtime16.jsx)("p", { className: "text-sm text-muted-foreground", children: "Participant Detail" })
|
|
2316
|
+
] }),
|
|
2317
|
+
/* @__PURE__ */ (0, import_jsx_runtime16.jsxs)("div", { className: "flex items-center gap-2", children: [
|
|
2318
|
+
saveMessage && /* @__PURE__ */ (0, import_jsx_runtime16.jsx)("span", { className: "text-xs text-emerald-600", children: saveMessage }),
|
|
2319
|
+
/* @__PURE__ */ (0, import_jsx_runtime16.jsxs)(Button, { size: "sm", onClick: () => void handleSave(), disabled: isSaving, children: [
|
|
2320
|
+
isSaving ? /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(import_lucide_react9.Loader2, { className: "mr-2 h-3 w-3 animate-spin" }) : /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(import_lucide_react9.Save, { className: "mr-2 h-3 w-3" }),
|
|
2321
|
+
"Save"
|
|
2322
|
+
] })
|
|
2323
|
+
] })
|
|
2324
|
+
] }),
|
|
2325
|
+
error && /* @__PURE__ */ (0, import_jsx_runtime16.jsx)("div", { className: "rounded-lg border border-destructive/50 bg-destructive/10 p-3 text-sm text-destructive", children: error }),
|
|
2326
|
+
/* @__PURE__ */ (0, import_jsx_runtime16.jsx)("div", { className: "rounded-lg border bg-card", children: /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
|
|
2327
|
+
"textarea",
|
|
2328
|
+
{
|
|
2329
|
+
className: "w-full min-h-[400px] p-4 font-mono text-sm bg-transparent resize-y focus:outline-none",
|
|
2330
|
+
value: editJson,
|
|
2331
|
+
onChange: (e) => setEditJson(e.target.value),
|
|
2332
|
+
spellCheck: false
|
|
2333
|
+
}
|
|
2334
|
+
) })
|
|
2335
|
+
] });
|
|
2336
|
+
};
|
|
2337
|
+
|
|
2338
|
+
// src/components/views/AgentsView.tsx
|
|
2339
|
+
var import_lucide_react10 = require("lucide-react");
|
|
2340
|
+
var import_jsx_runtime17 = require("react/jsx-runtime");
|
|
2341
|
+
var AgentsView = ({
|
|
2342
|
+
config,
|
|
2343
|
+
agents,
|
|
2344
|
+
searchValue,
|
|
2345
|
+
onSearchChange,
|
|
2346
|
+
onAgentClick
|
|
2347
|
+
}) => {
|
|
2348
|
+
return /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)("div", { className: "space-y-4", children: [
|
|
2349
|
+
/* @__PURE__ */ (0, import_jsx_runtime17.jsxs)("div", { className: "relative max-w-sm", children: [
|
|
2350
|
+
/* @__PURE__ */ (0, import_jsx_runtime17.jsx)(import_lucide_react10.Search, { className: "pointer-events-none absolute left-3 top-1/2 h-4 w-4 -translate-y-1/2 text-muted-foreground" }),
|
|
2351
|
+
/* @__PURE__ */ (0, import_jsx_runtime17.jsx)(
|
|
2352
|
+
Input,
|
|
2353
|
+
{
|
|
2354
|
+
className: "pl-9",
|
|
2355
|
+
placeholder: config.labels.agentSearchPlaceholder,
|
|
2356
|
+
value: searchValue,
|
|
2357
|
+
onChange: (e) => onSearchChange(e.target.value)
|
|
2358
|
+
}
|
|
2359
|
+
)
|
|
2360
|
+
] }),
|
|
2361
|
+
agents.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)("div", { className: "rounded-xl border border-dashed p-10 text-center", children: [
|
|
2362
|
+
/* @__PURE__ */ (0, import_jsx_runtime17.jsx)(import_lucide_react10.Bot, { className: "mx-auto h-8 w-8 text-muted-foreground/50" }),
|
|
2363
|
+
/* @__PURE__ */ (0, import_jsx_runtime17.jsx)("p", { className: "mt-3 text-sm text-muted-foreground", children: searchValue ? config.labels.noResults : config.labels.emptyDescription })
|
|
2364
|
+
] }) : /* @__PURE__ */ (0, import_jsx_runtime17.jsx)("div", { className: "grid gap-4 md:grid-cols-2 lg:grid-cols-3", children: agents.map((agent) => /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)(
|
|
2365
|
+
"div",
|
|
2366
|
+
{
|
|
2367
|
+
className: "rounded-lg border bg-card p-5 transition-colors hover:bg-muted/50 cursor-pointer",
|
|
2368
|
+
onClick: () => onAgentClick?.(agent.agentId),
|
|
2369
|
+
children: [
|
|
2370
|
+
/* @__PURE__ */ (0, import_jsx_runtime17.jsxs)("div", { className: "flex items-start justify-between gap-3", children: [
|
|
2371
|
+
/* @__PURE__ */ (0, import_jsx_runtime17.jsxs)("div", { className: "min-w-0", children: [
|
|
2372
|
+
/* @__PURE__ */ (0, import_jsx_runtime17.jsx)("p", { className: "font-medium truncate", children: agent.displayName }),
|
|
2373
|
+
/* @__PURE__ */ (0, import_jsx_runtime17.jsx)("p", { className: "mt-1 truncate text-xs text-muted-foreground", children: agent.description ?? agent.agentId })
|
|
2374
|
+
] }),
|
|
2375
|
+
/* @__PURE__ */ (0, import_jsx_runtime17.jsx)(Badge, { variant: "outline", className: "shrink-0", children: agent.isConfigured ? config.labels.configured : config.labels.unconfigured })
|
|
2376
|
+
] }),
|
|
2377
|
+
/* @__PURE__ */ (0, import_jsx_runtime17.jsxs)("div", { className: "mt-4 grid grid-cols-2 gap-2 text-xs text-muted-foreground", children: [
|
|
2378
|
+
/* @__PURE__ */ (0, import_jsx_runtime17.jsxs)("span", { children: [
|
|
2379
|
+
formatNumber4(agent.messageCount),
|
|
2380
|
+
" messages"
|
|
2381
|
+
] }),
|
|
2382
|
+
/* @__PURE__ */ (0, import_jsx_runtime17.jsxs)("span", { children: [
|
|
2383
|
+
formatNumber4(agent.llmCallCount),
|
|
2384
|
+
" LLM calls"
|
|
2385
|
+
] }),
|
|
2386
|
+
/* @__PURE__ */ (0, import_jsx_runtime17.jsxs)("span", { children: [
|
|
2387
|
+
formatNumber4(agent.toolCallMessageCount),
|
|
2388
|
+
" tool calls"
|
|
2389
|
+
] }),
|
|
2390
|
+
/* @__PURE__ */ (0, import_jsx_runtime17.jsxs)("span", { children: [
|
|
2391
|
+
formatNumber4(agent.totalTokens),
|
|
2392
|
+
" tokens"
|
|
2393
|
+
] })
|
|
2394
|
+
] }),
|
|
2395
|
+
/* @__PURE__ */ (0, import_jsx_runtime17.jsx)("p", { className: "mt-3 text-xs text-muted-foreground", children: formatDate5(agent.lastActivityAt) })
|
|
2396
|
+
]
|
|
2397
|
+
},
|
|
2398
|
+
`${agent.namespace}:${agent.agentId}`
|
|
2399
|
+
)) })
|
|
2400
|
+
] });
|
|
2401
|
+
};
|
|
2402
|
+
function formatDate5(value) {
|
|
2403
|
+
if (!value) return "No activity";
|
|
2404
|
+
const date = new Date(value);
|
|
2405
|
+
if (Number.isNaN(date.getTime())) return value;
|
|
2406
|
+
return date.toLocaleString(void 0, { month: "short", day: "numeric", hour: "numeric", minute: "2-digit" });
|
|
2407
|
+
}
|
|
2408
|
+
function formatNumber4(value) {
|
|
2409
|
+
return new Intl.NumberFormat().format(value);
|
|
2410
|
+
}
|
|
2411
|
+
|
|
2412
|
+
// src/components/views/AgentDetailView.tsx
|
|
2413
|
+
var import_lucide_react11 = require("lucide-react");
|
|
2414
|
+
var import_jsx_runtime18 = require("react/jsx-runtime");
|
|
2415
|
+
var AgentDetailView = ({
|
|
2416
|
+
agentId,
|
|
2417
|
+
config,
|
|
2418
|
+
agents,
|
|
2419
|
+
onBack
|
|
2420
|
+
}) => {
|
|
2421
|
+
const agent = agents.find((a) => a.agentId === agentId);
|
|
2422
|
+
if (!agent) {
|
|
2423
|
+
return /* @__PURE__ */ (0, import_jsx_runtime18.jsxs)("div", { className: "space-y-4 py-10 text-center", children: [
|
|
2424
|
+
/* @__PURE__ */ (0, import_jsx_runtime18.jsxs)("p", { className: "text-muted-foreground", children: [
|
|
2425
|
+
"Agent not found: ",
|
|
2426
|
+
agentId
|
|
2427
|
+
] }),
|
|
2428
|
+
/* @__PURE__ */ (0, import_jsx_runtime18.jsxs)(Button, { variant: "outline", onClick: onBack, children: [
|
|
2429
|
+
/* @__PURE__ */ (0, import_jsx_runtime18.jsx)(import_lucide_react11.ArrowLeft, { className: "mr-2 h-4 w-4" }),
|
|
2430
|
+
" Back"
|
|
2431
|
+
] })
|
|
2432
|
+
] });
|
|
2433
|
+
}
|
|
2434
|
+
const stats = [
|
|
2435
|
+
{ label: "Messages", value: agent.messageCount },
|
|
2436
|
+
{ label: "LLM Calls", value: agent.llmCallCount },
|
|
2437
|
+
{ label: "Tool Calls", value: agent.toolCallMessageCount },
|
|
2438
|
+
{ label: "Input Tokens", value: agent.inputTokens },
|
|
2439
|
+
{ label: "Output Tokens", value: agent.outputTokens },
|
|
2440
|
+
{ label: "Reasoning Tokens", value: agent.reasoningTokens },
|
|
2441
|
+
{ label: "Cache Read", value: agent.cacheReadInputTokens },
|
|
2442
|
+
{ label: "Cache Created", value: agent.cacheCreationInputTokens },
|
|
2443
|
+
{ label: "Total Tokens", value: agent.totalTokens }
|
|
2444
|
+
];
|
|
2445
|
+
return /* @__PURE__ */ (0, import_jsx_runtime18.jsxs)("div", { className: "space-y-6", children: [
|
|
2446
|
+
/* @__PURE__ */ (0, import_jsx_runtime18.jsxs)("div", { className: "flex items-start gap-4", children: [
|
|
2447
|
+
/* @__PURE__ */ (0, import_jsx_runtime18.jsx)(Button, { variant: "ghost", size: "icon", className: "mt-1 shrink-0", onClick: onBack, children: /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(import_lucide_react11.ArrowLeft, { className: "h-4 w-4" }) }),
|
|
2448
|
+
/* @__PURE__ */ (0, import_jsx_runtime18.jsxs)("div", { className: "flex-1 min-w-0", children: [
|
|
2449
|
+
/* @__PURE__ */ (0, import_jsx_runtime18.jsxs)("div", { className: "flex items-center gap-3", children: [
|
|
2450
|
+
/* @__PURE__ */ (0, import_jsx_runtime18.jsx)("div", { className: "flex h-10 w-10 shrink-0 items-center justify-center rounded-lg bg-primary/10 text-primary", children: /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(import_lucide_react11.Bot, { className: "h-5 w-5" }) }),
|
|
2451
|
+
/* @__PURE__ */ (0, import_jsx_runtime18.jsxs)("div", { children: [
|
|
2452
|
+
/* @__PURE__ */ (0, import_jsx_runtime18.jsxs)("div", { className: "flex items-center gap-2", children: [
|
|
2453
|
+
/* @__PURE__ */ (0, import_jsx_runtime18.jsx)("h2", { className: "text-xl font-semibold", children: agent.displayName }),
|
|
2454
|
+
/* @__PURE__ */ (0, import_jsx_runtime18.jsx)(Badge, { variant: "outline", children: agent.isConfigured ? config.labels.configured : config.labels.unconfigured })
|
|
2455
|
+
] }),
|
|
2456
|
+
agent.description && /* @__PURE__ */ (0, import_jsx_runtime18.jsx)("p", { className: "text-sm text-muted-foreground", children: agent.description })
|
|
2457
|
+
] })
|
|
2458
|
+
] }),
|
|
2459
|
+
/* @__PURE__ */ (0, import_jsx_runtime18.jsxs)("div", { className: "mt-2 flex flex-wrap gap-4 text-xs text-muted-foreground", children: [
|
|
2460
|
+
/* @__PURE__ */ (0, import_jsx_runtime18.jsxs)("span", { children: [
|
|
2461
|
+
"ID: ",
|
|
2462
|
+
agent.agentId
|
|
2463
|
+
] }),
|
|
2464
|
+
/* @__PURE__ */ (0, import_jsx_runtime18.jsxs)("span", { children: [
|
|
2465
|
+
"Namespace: ",
|
|
2466
|
+
agent.namespace
|
|
2467
|
+
] }),
|
|
2468
|
+
agent.lastActivityAt && /* @__PURE__ */ (0, import_jsx_runtime18.jsxs)("span", { children: [
|
|
2469
|
+
"Last active: ",
|
|
2470
|
+
formatDate6(agent.lastActivityAt)
|
|
2471
|
+
] })
|
|
2472
|
+
] })
|
|
2473
|
+
] })
|
|
2474
|
+
] }),
|
|
2475
|
+
/* @__PURE__ */ (0, import_jsx_runtime18.jsx)("div", { className: "grid gap-4 sm:grid-cols-3 lg:grid-cols-3", children: stats.map((stat) => /* @__PURE__ */ (0, import_jsx_runtime18.jsxs)("div", { className: "rounded-xl border bg-card p-5 shadow-sm", children: [
|
|
2476
|
+
/* @__PURE__ */ (0, import_jsx_runtime18.jsx)("p", { className: "text-sm font-medium text-muted-foreground", children: stat.label }),
|
|
2477
|
+
/* @__PURE__ */ (0, import_jsx_runtime18.jsx)("p", { className: "mt-2 text-2xl font-semibold tracking-tight", children: new Intl.NumberFormat().format(stat.value) })
|
|
2478
|
+
] }, stat.label)) })
|
|
2479
|
+
] });
|
|
2480
|
+
};
|
|
2481
|
+
function formatDate6(value) {
|
|
2482
|
+
const date = new Date(value);
|
|
2483
|
+
if (Number.isNaN(date.getTime())) return value;
|
|
2484
|
+
return date.toLocaleString(void 0, { month: "short", day: "numeric", hour: "numeric", minute: "2-digit" });
|
|
2485
|
+
}
|
|
2486
|
+
|
|
2487
|
+
// src/components/views/CollectionItemsView.tsx
|
|
2488
|
+
var import_react4 = require("react");
|
|
2489
|
+
var import_lucide_react12 = require("lucide-react");
|
|
2490
|
+
var import_jsx_runtime19 = require("react/jsx-runtime");
|
|
2491
|
+
var CollectionItemsView = ({
|
|
2492
|
+
collection,
|
|
2493
|
+
config,
|
|
2494
|
+
namespace,
|
|
2495
|
+
onItemClick,
|
|
2496
|
+
onCreateNew
|
|
2497
|
+
}) => {
|
|
2498
|
+
const [items, setItems] = (0, import_react4.useState)([]);
|
|
2499
|
+
const [isLoading, setIsLoading] = (0, import_react4.useState)(true);
|
|
2500
|
+
const [search, setSearch] = (0, import_react4.useState)("");
|
|
2501
|
+
const [error, setError] = (0, import_react4.useState)(null);
|
|
2502
|
+
const fetchOptions = {
|
|
2503
|
+
baseUrl: config.baseUrl,
|
|
2504
|
+
getRequestHeaders: config.getRequestHeaders
|
|
2505
|
+
};
|
|
2506
|
+
const load = (0, import_react4.useCallback)(async () => {
|
|
2507
|
+
setIsLoading(true);
|
|
2508
|
+
setError(null);
|
|
2509
|
+
try {
|
|
2510
|
+
const result = await fetchCollectionItems(
|
|
2511
|
+
collection,
|
|
2512
|
+
{ search: search || void 0, namespace, limit: 50 },
|
|
2513
|
+
fetchOptions
|
|
2514
|
+
);
|
|
2515
|
+
setItems(result);
|
|
2516
|
+
} catch (err) {
|
|
2517
|
+
setError(err instanceof Error ? err.message : "Failed to load items");
|
|
2518
|
+
} finally {
|
|
2519
|
+
setIsLoading(false);
|
|
2520
|
+
}
|
|
2521
|
+
}, [collection, search, namespace, config.baseUrl, config.getRequestHeaders]);
|
|
2522
|
+
(0, import_react4.useEffect)(() => {
|
|
2523
|
+
void load();
|
|
2524
|
+
}, [load]);
|
|
2525
|
+
const getItemId = (item) => {
|
|
2526
|
+
return String(item.id ?? item._id ?? JSON.stringify(item).slice(0, 40));
|
|
2527
|
+
};
|
|
2528
|
+
const getItemPreview = (item) => {
|
|
2529
|
+
const { id, _id, ...rest } = item;
|
|
2530
|
+
const name = item.name ?? item.title ?? item.displayName ?? item.label;
|
|
2531
|
+
if (typeof name === "string") return name;
|
|
2532
|
+
const keys = Object.keys(rest);
|
|
2533
|
+
if (keys.length === 0) return "(empty)";
|
|
2534
|
+
return keys.slice(0, 3).map((k) => `${k}: ${JSON.stringify(rest[k])?.slice(0, 30)}`).join(", ");
|
|
2535
|
+
};
|
|
2536
|
+
return /* @__PURE__ */ (0, import_jsx_runtime19.jsxs)("div", { className: "space-y-4", children: [
|
|
2537
|
+
/* @__PURE__ */ (0, import_jsx_runtime19.jsxs)("div", { className: "flex items-center justify-between gap-4", children: [
|
|
2538
|
+
/* @__PURE__ */ (0, import_jsx_runtime19.jsx)("h2", { className: "text-lg font-semibold capitalize", children: collection }),
|
|
2539
|
+
onCreateNew && /* @__PURE__ */ (0, import_jsx_runtime19.jsxs)(Button, { size: "sm", onClick: onCreateNew, children: [
|
|
2540
|
+
/* @__PURE__ */ (0, import_jsx_runtime19.jsx)(import_lucide_react12.Plus, { className: "mr-2 h-3 w-3" }),
|
|
2541
|
+
" New"
|
|
2542
|
+
] })
|
|
2543
|
+
] }),
|
|
2544
|
+
/* @__PURE__ */ (0, import_jsx_runtime19.jsxs)("div", { className: "relative max-w-sm", children: [
|
|
2545
|
+
/* @__PURE__ */ (0, import_jsx_runtime19.jsx)(import_lucide_react12.Search, { className: "pointer-events-none absolute left-3 top-1/2 h-4 w-4 -translate-y-1/2 text-muted-foreground" }),
|
|
2546
|
+
/* @__PURE__ */ (0, import_jsx_runtime19.jsx)(
|
|
2547
|
+
Input,
|
|
2548
|
+
{
|
|
2549
|
+
className: "pl-9",
|
|
2550
|
+
placeholder: `Search ${collection}...`,
|
|
2551
|
+
value: search,
|
|
2552
|
+
onChange: (e) => setSearch(e.target.value)
|
|
2553
|
+
}
|
|
2554
|
+
)
|
|
2555
|
+
] }),
|
|
2556
|
+
error && /* @__PURE__ */ (0, import_jsx_runtime19.jsx)("div", { className: "rounded-lg border border-destructive/50 bg-destructive/10 p-3 text-sm text-destructive", children: error }),
|
|
2557
|
+
isLoading ? /* @__PURE__ */ (0, import_jsx_runtime19.jsx)("div", { className: "flex items-center justify-center py-20", children: /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(import_lucide_react12.Loader2, { className: "h-6 w-6 animate-spin text-muted-foreground" }) }) : items.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime19.jsxs)("div", { className: "rounded-xl border border-dashed p-10 text-center", children: [
|
|
2558
|
+
/* @__PURE__ */ (0, import_jsx_runtime19.jsx)(import_lucide_react12.Database, { className: "mx-auto h-8 w-8 text-muted-foreground/50" }),
|
|
2559
|
+
/* @__PURE__ */ (0, import_jsx_runtime19.jsx)("p", { className: "mt-3 text-sm text-muted-foreground", children: search ? config.labels.noResults : `No items in ${collection}` })
|
|
2560
|
+
] }) : /* @__PURE__ */ (0, import_jsx_runtime19.jsx)("div", { className: "space-y-2", children: items.map((item, idx) => {
|
|
2561
|
+
const itemId = getItemId(item);
|
|
2562
|
+
return /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(
|
|
2563
|
+
"div",
|
|
2564
|
+
{
|
|
2565
|
+
className: "flex items-center gap-4 rounded-lg border bg-card p-4 transition-colors hover:bg-muted/50 cursor-pointer",
|
|
2566
|
+
onClick: () => onItemClick?.(itemId),
|
|
2567
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime19.jsxs)("div", { className: "flex-1 min-w-0", children: [
|
|
2568
|
+
/* @__PURE__ */ (0, import_jsx_runtime19.jsx)("p", { className: "font-medium font-mono text-sm truncate", children: itemId }),
|
|
2569
|
+
/* @__PURE__ */ (0, import_jsx_runtime19.jsx)("p", { className: "mt-1 text-xs text-muted-foreground truncate", children: getItemPreview(item) })
|
|
2570
|
+
] })
|
|
2571
|
+
},
|
|
2572
|
+
itemId + idx
|
|
2573
|
+
);
|
|
2574
|
+
}) })
|
|
2575
|
+
] });
|
|
2576
|
+
};
|
|
2577
|
+
|
|
2578
|
+
// src/components/views/CollectionItemDetailView.tsx
|
|
2579
|
+
var import_react5 = require("react");
|
|
2580
|
+
var import_lucide_react13 = require("lucide-react");
|
|
2581
|
+
var import_jsx_runtime20 = require("react/jsx-runtime");
|
|
2582
|
+
var CollectionItemDetailView = ({
|
|
2583
|
+
collection,
|
|
2584
|
+
itemId,
|
|
2585
|
+
config,
|
|
2586
|
+
namespace,
|
|
2587
|
+
onBack,
|
|
2588
|
+
onDeleted
|
|
2589
|
+
}) => {
|
|
2590
|
+
const isNew = !itemId;
|
|
2591
|
+
const [editJson, setEditJson] = (0, import_react5.useState)(isNew ? "{\n \n}" : "");
|
|
2592
|
+
const [isLoading, setIsLoading] = (0, import_react5.useState)(!isNew);
|
|
2593
|
+
const [isSaving, setIsSaving] = (0, import_react5.useState)(false);
|
|
2594
|
+
const [isDeleting, setIsDeleting] = (0, import_react5.useState)(false);
|
|
2595
|
+
const [error, setError] = (0, import_react5.useState)(null);
|
|
2596
|
+
const [saveMessage, setSaveMessage] = (0, import_react5.useState)(null);
|
|
2597
|
+
const fetchOptions = {
|
|
2598
|
+
baseUrl: config.baseUrl,
|
|
2599
|
+
getRequestHeaders: config.getRequestHeaders
|
|
2600
|
+
};
|
|
2601
|
+
const load = (0, import_react5.useCallback)(async () => {
|
|
2602
|
+
if (!itemId) return;
|
|
2603
|
+
setIsLoading(true);
|
|
2604
|
+
setError(null);
|
|
2605
|
+
try {
|
|
2606
|
+
const result = await fetchCollectionItem(collection, itemId, namespace, fetchOptions);
|
|
2607
|
+
setEditJson(JSON.stringify(result, null, 2));
|
|
2608
|
+
} catch (err) {
|
|
2609
|
+
setError(err instanceof Error ? err.message : "Failed to load item");
|
|
2610
|
+
} finally {
|
|
2611
|
+
setIsLoading(false);
|
|
2612
|
+
}
|
|
2613
|
+
}, [collection, itemId, namespace, config.baseUrl, config.getRequestHeaders]);
|
|
2614
|
+
(0, import_react5.useEffect)(() => {
|
|
2615
|
+
void load();
|
|
2616
|
+
}, [load]);
|
|
2617
|
+
const handleSave = async () => {
|
|
2618
|
+
setIsSaving(true);
|
|
2619
|
+
setError(null);
|
|
2620
|
+
setSaveMessage(null);
|
|
2621
|
+
try {
|
|
2622
|
+
const parsed = JSON.parse(editJson);
|
|
2623
|
+
if (isNew) {
|
|
2624
|
+
const created = await createCollectionItem(collection, parsed, namespace, fetchOptions);
|
|
2625
|
+
setEditJson(JSON.stringify(created, null, 2));
|
|
2626
|
+
setSaveMessage("Created successfully");
|
|
2627
|
+
} else {
|
|
2628
|
+
const updated = await updateCollectionItem(collection, itemId, parsed, namespace, fetchOptions);
|
|
2629
|
+
setEditJson(JSON.stringify(updated, null, 2));
|
|
2630
|
+
setSaveMessage("Saved successfully");
|
|
2631
|
+
}
|
|
2632
|
+
setTimeout(() => setSaveMessage(null), 3e3);
|
|
2633
|
+
} catch (err) {
|
|
2634
|
+
setError(err instanceof Error ? err.message : "Failed to save");
|
|
2635
|
+
} finally {
|
|
2636
|
+
setIsSaving(false);
|
|
2637
|
+
}
|
|
2638
|
+
};
|
|
2639
|
+
const handleDelete = async () => {
|
|
2640
|
+
if (!itemId) return;
|
|
2641
|
+
if (!window.confirm(`Delete this item from ${collection}?`)) return;
|
|
2642
|
+
setIsDeleting(true);
|
|
2643
|
+
setError(null);
|
|
2644
|
+
try {
|
|
2645
|
+
await deleteCollectionItem(collection, itemId, namespace, fetchOptions);
|
|
2646
|
+
onDeleted?.();
|
|
2647
|
+
onBack();
|
|
2648
|
+
} catch (err) {
|
|
2649
|
+
setError(err instanceof Error ? err.message : "Failed to delete");
|
|
2650
|
+
} finally {
|
|
2651
|
+
setIsDeleting(false);
|
|
2652
|
+
}
|
|
2653
|
+
};
|
|
2654
|
+
if (isLoading) {
|
|
2655
|
+
return /* @__PURE__ */ (0, import_jsx_runtime20.jsx)("div", { className: "flex items-center justify-center py-20", children: /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(import_lucide_react13.Loader2, { className: "h-6 w-6 animate-spin text-muted-foreground" }) });
|
|
2656
|
+
}
|
|
2657
|
+
return /* @__PURE__ */ (0, import_jsx_runtime20.jsxs)("div", { className: "space-y-6", children: [
|
|
2658
|
+
/* @__PURE__ */ (0, import_jsx_runtime20.jsxs)("div", { className: "flex items-center gap-4", children: [
|
|
2659
|
+
/* @__PURE__ */ (0, import_jsx_runtime20.jsx)(Button, { variant: "ghost", size: "icon", onClick: onBack, children: /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(import_lucide_react13.ArrowLeft, { className: "h-4 w-4" }) }),
|
|
2660
|
+
/* @__PURE__ */ (0, import_jsx_runtime20.jsx)("div", { className: "flex-1 min-w-0", children: /* @__PURE__ */ (0, import_jsx_runtime20.jsx)("h2", { className: "text-xl font-semibold truncate capitalize", children: isNew ? `New ${collection} item` : `${collection} / ${itemId}` }) }),
|
|
2661
|
+
/* @__PURE__ */ (0, import_jsx_runtime20.jsxs)("div", { className: "flex items-center gap-2", children: [
|
|
2662
|
+
saveMessage && /* @__PURE__ */ (0, import_jsx_runtime20.jsx)("span", { className: "text-xs text-emerald-600", children: saveMessage }),
|
|
2663
|
+
!isNew && /* @__PURE__ */ (0, import_jsx_runtime20.jsxs)(
|
|
2664
|
+
Button,
|
|
2665
|
+
{
|
|
2666
|
+
variant: "destructive",
|
|
2667
|
+
size: "sm",
|
|
2668
|
+
onClick: () => void handleDelete(),
|
|
2669
|
+
disabled: isDeleting,
|
|
2670
|
+
children: [
|
|
2671
|
+
isDeleting ? /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(import_lucide_react13.Loader2, { className: "mr-2 h-3 w-3 animate-spin" }) : /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(import_lucide_react13.Trash2, { className: "mr-2 h-3 w-3" }),
|
|
2672
|
+
"Delete"
|
|
2673
|
+
]
|
|
2674
|
+
}
|
|
2675
|
+
),
|
|
2676
|
+
/* @__PURE__ */ (0, import_jsx_runtime20.jsxs)(Button, { size: "sm", onClick: () => void handleSave(), disabled: isSaving, children: [
|
|
2677
|
+
isSaving ? /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(import_lucide_react13.Loader2, { className: "mr-2 h-3 w-3 animate-spin" }) : /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(import_lucide_react13.Save, { className: "mr-2 h-3 w-3" }),
|
|
2678
|
+
isNew ? "Create" : "Save"
|
|
2679
|
+
] })
|
|
2680
|
+
] })
|
|
2681
|
+
] }),
|
|
2682
|
+
error && /* @__PURE__ */ (0, import_jsx_runtime20.jsx)("div", { className: "rounded-lg border border-destructive/50 bg-destructive/10 p-3 text-sm text-destructive", children: error }),
|
|
2683
|
+
/* @__PURE__ */ (0, import_jsx_runtime20.jsx)("div", { className: "rounded-lg border bg-card", children: /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(
|
|
2684
|
+
"textarea",
|
|
2685
|
+
{
|
|
2686
|
+
className: "w-full min-h-[400px] p-4 font-mono text-sm bg-transparent resize-y focus:outline-none",
|
|
2687
|
+
value: editJson,
|
|
2688
|
+
onChange: (e) => setEditJson(e.target.value),
|
|
2689
|
+
spellCheck: false
|
|
2690
|
+
}
|
|
2691
|
+
) })
|
|
2692
|
+
] });
|
|
2693
|
+
};
|
|
2694
|
+
|
|
2695
|
+
// src/components/views/EventsView.tsx
|
|
2696
|
+
var import_react6 = require("react");
|
|
2697
|
+
var import_lucide_react14 = require("lucide-react");
|
|
2698
|
+
var import_jsx_runtime21 = require("react/jsx-runtime");
|
|
2699
|
+
var STATUS_VARIANTS = {
|
|
2700
|
+
pending: "outline",
|
|
2701
|
+
processing: "default",
|
|
2702
|
+
completed: "secondary",
|
|
2703
|
+
failed: "destructive",
|
|
2704
|
+
expired: "secondary",
|
|
2705
|
+
overwritten: "secondary"
|
|
2706
|
+
};
|
|
2707
|
+
var EventsView = ({ config }) => {
|
|
2708
|
+
const [threadId, setThreadId] = (0, import_react6.useState)("");
|
|
2709
|
+
const [event, setEvent] = (0, import_react6.useState)(null);
|
|
2710
|
+
const [hasSearched, setHasSearched] = (0, import_react6.useState)(false);
|
|
2711
|
+
const [isLoading, setIsLoading] = (0, import_react6.useState)(false);
|
|
2712
|
+
const [error, setError] = (0, import_react6.useState)(null);
|
|
2713
|
+
const fetchOptions = {
|
|
2714
|
+
baseUrl: config.baseUrl,
|
|
2715
|
+
getRequestHeaders: config.getRequestHeaders
|
|
2716
|
+
};
|
|
2717
|
+
const handleSearch = (0, import_react6.useCallback)(async () => {
|
|
2718
|
+
if (!threadId.trim()) return;
|
|
2719
|
+
setIsLoading(true);
|
|
2720
|
+
setError(null);
|
|
2721
|
+
setHasSearched(true);
|
|
2722
|
+
try {
|
|
2723
|
+
const result = await fetchThreadEvents(threadId.trim(), fetchOptions);
|
|
2724
|
+
setEvent(result ?? null);
|
|
2725
|
+
} catch (err) {
|
|
2726
|
+
setError(err instanceof Error ? err.message : "Failed to load events");
|
|
2727
|
+
} finally {
|
|
2728
|
+
setIsLoading(false);
|
|
2729
|
+
}
|
|
2730
|
+
}, [threadId, config.baseUrl, config.getRequestHeaders]);
|
|
2731
|
+
return /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("div", { className: "space-y-6", children: [
|
|
2732
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("div", { className: "flex items-end gap-3 max-w-lg", children: [
|
|
2733
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("div", { className: "flex-1", children: [
|
|
2734
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)("label", { className: "text-sm font-medium mb-1 block", children: "Thread ID" }),
|
|
2735
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("div", { className: "relative", children: [
|
|
2736
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)(import_lucide_react14.Search, { className: "pointer-events-none absolute left-3 top-1/2 h-4 w-4 -translate-y-1/2 text-muted-foreground" }),
|
|
2737
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
|
|
2738
|
+
Input,
|
|
2739
|
+
{
|
|
2740
|
+
className: "pl-9",
|
|
2741
|
+
placeholder: "Enter thread ID to inspect events...",
|
|
2742
|
+
value: threadId,
|
|
2743
|
+
onChange: (e) => setThreadId(e.target.value),
|
|
2744
|
+
onKeyDown: (e) => e.key === "Enter" && void handleSearch()
|
|
2745
|
+
}
|
|
2746
|
+
)
|
|
2747
|
+
] })
|
|
2748
|
+
] }),
|
|
2749
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsxs)(Button, { onClick: () => void handleSearch(), disabled: isLoading || !threadId.trim(), children: [
|
|
2750
|
+
isLoading ? /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(import_lucide_react14.Loader2, { className: "mr-2 h-4 w-4 animate-spin" }) : null,
|
|
2751
|
+
"Inspect"
|
|
2752
|
+
] })
|
|
2753
|
+
] }),
|
|
2754
|
+
error && /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("div", { className: "rounded-lg border border-destructive/50 bg-destructive/10 p-3 text-sm text-destructive", children: error }),
|
|
2755
|
+
!hasSearched ? /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("div", { className: "rounded-xl border border-dashed p-10 text-center", children: [
|
|
2756
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)(import_lucide_react14.Activity, { className: "mx-auto h-8 w-8 text-muted-foreground/50" }),
|
|
2757
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)("p", { className: "mt-3 text-sm text-muted-foreground", children: "Enter a thread ID to inspect its next pending queue event." })
|
|
2758
|
+
] }) : isLoading ? /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("div", { className: "flex items-center justify-center py-20", children: /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(import_lucide_react14.Loader2, { className: "h-6 w-6 animate-spin text-muted-foreground" }) }) : !event ? /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("div", { className: "rounded-xl border border-dashed p-10 text-center", children: [
|
|
2759
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)(import_lucide_react14.Activity, { className: "mx-auto h-8 w-8 text-muted-foreground/50" }),
|
|
2760
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)("p", { className: "mt-3 text-sm text-muted-foreground", children: "No pending events found for this thread." })
|
|
2761
|
+
] }) : /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("div", { className: "rounded-lg border bg-card p-5 space-y-4", children: [
|
|
2762
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("div", { className: "flex items-start justify-between gap-3", children: [
|
|
2763
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("div", { children: [
|
|
2764
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)("p", { className: "font-medium", children: event.eventType }),
|
|
2765
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)("p", { className: "text-xs text-muted-foreground font-mono mt-1", children: event.id })
|
|
2766
|
+
] }),
|
|
2767
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)(Badge, { variant: STATUS_VARIANTS[event.status] ?? "outline", children: event.status })
|
|
2768
|
+
] }),
|
|
2769
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("div", { className: "grid gap-3 sm:grid-cols-2 text-sm", children: [
|
|
2770
|
+
event.traceId && /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("div", { children: [
|
|
2771
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)("span", { className: "text-muted-foreground", children: "Trace:" }),
|
|
2772
|
+
" ",
|
|
2773
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)("span", { className: "font-mono text-xs", children: event.traceId })
|
|
2774
|
+
] }),
|
|
2775
|
+
event.parentEventId && /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("div", { children: [
|
|
2776
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)("span", { className: "text-muted-foreground", children: "Parent:" }),
|
|
2777
|
+
" ",
|
|
2778
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)("span", { className: "font-mono text-xs", children: event.parentEventId })
|
|
2779
|
+
] }),
|
|
2780
|
+
event.priority != null && /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("div", { children: [
|
|
2781
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)("span", { className: "text-muted-foreground", children: "Priority:" }),
|
|
2782
|
+
" ",
|
|
2783
|
+
event.priority
|
|
2784
|
+
] }),
|
|
2785
|
+
event.createdAt && /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("div", { children: [
|
|
2786
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)("span", { className: "text-muted-foreground", children: "Created:" }),
|
|
2787
|
+
" ",
|
|
2788
|
+
formatTimestamp2(event.createdAt)
|
|
2789
|
+
] })
|
|
2790
|
+
] }),
|
|
2791
|
+
event.payload != null && /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("div", { children: [
|
|
2792
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)("p", { className: "text-xs font-medium text-muted-foreground mb-1", children: "Payload" }),
|
|
2793
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)("pre", { className: "rounded-md bg-muted p-3 text-xs overflow-auto max-h-60", children: JSON.stringify(event.payload, null, 2) })
|
|
2794
|
+
] }),
|
|
2795
|
+
event.metadata != null && Object.keys(event.metadata).length > 0 && /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("div", { children: [
|
|
2796
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)("p", { className: "text-xs font-medium text-muted-foreground mb-1", children: "Metadata" }),
|
|
2797
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)("pre", { className: "rounded-md bg-muted p-3 text-xs overflow-auto max-h-40", children: JSON.stringify(event.metadata, null, 2) })
|
|
2798
|
+
] })
|
|
2799
|
+
] })
|
|
2800
|
+
] });
|
|
2801
|
+
};
|
|
2802
|
+
function formatTimestamp2(value) {
|
|
2803
|
+
const date = new Date(value);
|
|
2804
|
+
if (Number.isNaN(date.getTime())) return value;
|
|
2805
|
+
return date.toLocaleString(void 0, {
|
|
2806
|
+
month: "short",
|
|
2807
|
+
day: "numeric",
|
|
2808
|
+
hour: "numeric",
|
|
2809
|
+
minute: "2-digit",
|
|
2810
|
+
second: "2-digit"
|
|
2811
|
+
});
|
|
2812
|
+
}
|
|
2813
|
+
|
|
2814
|
+
// src/CopilotzAdmin.tsx
|
|
2815
|
+
var import_jsx_runtime22 = require("react/jsx-runtime");
|
|
2816
|
+
var CopilotzAdmin = ({
|
|
2817
|
+
config: userConfig,
|
|
2818
|
+
className
|
|
2819
|
+
}) => {
|
|
2820
|
+
const config = (0, import_react7.useMemo)(
|
|
2821
|
+
() => mergeAdminConfig(defaultAdminConfig, userConfig),
|
|
2822
|
+
[userConfig]
|
|
2823
|
+
);
|
|
2824
|
+
const [route, setRoute] = (0, import_react7.useState)({ page: config.defaultPage });
|
|
2825
|
+
const [namespace, setNamespace] = (0, import_react7.useState)(config.namespace);
|
|
2826
|
+
const [collections, setCollections] = (0, import_react7.useState)([]);
|
|
2827
|
+
const [threadSearch, setThreadSearch] = (0, import_react7.useState)("");
|
|
2828
|
+
const [participantSearch, setParticipantSearch] = (0, import_react7.useState)("");
|
|
2829
|
+
const [agentSearch, setAgentSearch] = (0, import_react7.useState)("");
|
|
2830
|
+
const deferredThreadSearch = (0, import_react7.useDeferredValue)(threadSearch);
|
|
2831
|
+
const deferredParticipantSearch = (0, import_react7.useDeferredValue)(participantSearch);
|
|
2832
|
+
const deferredAgentSearch = (0, import_react7.useDeferredValue)(agentSearch);
|
|
2833
|
+
const admin = useCopilotzAdmin({
|
|
2834
|
+
baseUrl: config.baseUrl,
|
|
2835
|
+
getRequestHeaders: config.getRequestHeaders,
|
|
2836
|
+
namespace,
|
|
2837
|
+
range: config.initialRange,
|
|
2838
|
+
interval: config.initialInterval,
|
|
2839
|
+
threadSearch: deferredThreadSearch,
|
|
2840
|
+
participantSearch: deferredParticipantSearch,
|
|
2841
|
+
agentSearch: deferredAgentSearch
|
|
2842
|
+
});
|
|
2843
|
+
(0, import_react7.useEffect)(() => {
|
|
2844
|
+
if (!config.features.showCollections) return;
|
|
2845
|
+
fetchCollectionNames({
|
|
2846
|
+
baseUrl: config.baseUrl,
|
|
2847
|
+
getRequestHeaders: config.getRequestHeaders
|
|
2848
|
+
}).then(setCollections).catch(() => setCollections([]));
|
|
2849
|
+
}, [config.baseUrl, config.getRequestHeaders, config.features.showCollections]);
|
|
2850
|
+
const navigate = (0, import_react7.useCallback)(
|
|
2851
|
+
(next) => {
|
|
2852
|
+
setRoute(next);
|
|
2853
|
+
config.onNavigate?.(next);
|
|
2854
|
+
},
|
|
2855
|
+
[config]
|
|
2856
|
+
);
|
|
2857
|
+
const handleSidebarNavigate = (0, import_react7.useCallback)(
|
|
2858
|
+
(page) => navigate({ page }),
|
|
2859
|
+
[navigate]
|
|
2860
|
+
);
|
|
2861
|
+
const handleSidebarRouteNavigate = (0, import_react7.useCallback)(
|
|
2862
|
+
(r) => navigate(r),
|
|
2863
|
+
[navigate]
|
|
2864
|
+
);
|
|
2865
|
+
const handleThreadClick = (0, import_react7.useCallback)(
|
|
2866
|
+
(threadId) => navigate({ page: "thread-detail", resourceId: threadId }),
|
|
2867
|
+
[navigate]
|
|
2868
|
+
);
|
|
2869
|
+
const handleBackToThreads = (0, import_react7.useCallback)(() => navigate({ page: "threads" }), [navigate]);
|
|
2870
|
+
const handleParticipantClick = (0, import_react7.useCallback)(
|
|
2871
|
+
(id) => navigate({ page: "participant-detail", resourceId: id }),
|
|
2872
|
+
[navigate]
|
|
2873
|
+
);
|
|
2874
|
+
const handleBackToParticipants = (0, import_react7.useCallback)(() => navigate({ page: "participants" }), [navigate]);
|
|
2875
|
+
const handleAgentClick = (0, import_react7.useCallback)(
|
|
2876
|
+
(id) => navigate({ page: "agent-detail", resourceId: id }),
|
|
2877
|
+
[navigate]
|
|
2878
|
+
);
|
|
2879
|
+
const handleBackToAgents = (0, import_react7.useCallback)(() => navigate({ page: "agents" }), [navigate]);
|
|
2880
|
+
const handleCollectionItemClick = (0, import_react7.useCallback)(
|
|
2881
|
+
(itemId) => navigate({ page: "collection-item-detail", resourceId: itemId, collection: route.collection }),
|
|
2882
|
+
[navigate, route.collection]
|
|
2883
|
+
);
|
|
2884
|
+
const handleCollectionCreateNew = (0, import_react7.useCallback)(
|
|
2885
|
+
() => navigate({ page: "collection-item-detail", resourceId: void 0, collection: route.collection }),
|
|
2886
|
+
[navigate, route.collection]
|
|
2887
|
+
);
|
|
2888
|
+
const handleBackToCollectionItems = (0, import_react7.useCallback)(
|
|
2889
|
+
() => navigate({ page: "collection-items", collection: route.collection }),
|
|
2890
|
+
[navigate, route.collection]
|
|
2891
|
+
);
|
|
2892
|
+
const sidebarPage = (() => {
|
|
2893
|
+
switch (route.page) {
|
|
2894
|
+
case "thread-detail":
|
|
2895
|
+
return "threads";
|
|
2896
|
+
case "participant-detail":
|
|
2897
|
+
return "participants";
|
|
2898
|
+
case "agent-detail":
|
|
2899
|
+
return "agents";
|
|
2900
|
+
case "collection-item-detail":
|
|
2901
|
+
return "collection-items";
|
|
2902
|
+
default:
|
|
2903
|
+
return route.page;
|
|
2904
|
+
}
|
|
2905
|
+
})();
|
|
2906
|
+
if (admin.isLoading && !admin.overview) {
|
|
2907
|
+
return /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(Card, { className: cn("border-border", className), children: /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(CardContent, { className: "text-muted-foreground flex items-center justify-center min-h-[200px]", children: config.labels.loading }) });
|
|
2908
|
+
}
|
|
2909
|
+
if (admin.error && !admin.overview) {
|
|
2910
|
+
return /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(Card, { className: cn("border-destructive/50 bg-destructive/10", className), children: /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)(CardContent, { className: "space-y-4", children: [
|
|
2911
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsx)("p", { className: "text-base font-semibold text-destructive", children: admin.error.message }),
|
|
2912
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsx)(Button, { variant: "destructive", onClick: () => void admin.refresh(), children: config.labels.retry })
|
|
2913
|
+
] }) });
|
|
2914
|
+
}
|
|
2915
|
+
const renderCurrentView = () => {
|
|
2916
|
+
switch (route.page) {
|
|
2917
|
+
case "dashboard":
|
|
2918
|
+
return /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
|
|
2919
|
+
DashboardView,
|
|
2920
|
+
{
|
|
2921
|
+
config,
|
|
2922
|
+
overview: admin.overview,
|
|
2923
|
+
activity: admin.activity,
|
|
2924
|
+
threads: admin.threads,
|
|
2925
|
+
participants: admin.participants,
|
|
2926
|
+
agents: admin.agents,
|
|
2927
|
+
interval: admin.filters.interval,
|
|
2928
|
+
threadSearch,
|
|
2929
|
+
participantSearch,
|
|
2930
|
+
agentSearch,
|
|
2931
|
+
onThreadSearchChange: setThreadSearch,
|
|
2932
|
+
onParticipantSearchChange: setParticipantSearch,
|
|
2933
|
+
onAgentSearchChange: setAgentSearch,
|
|
2934
|
+
onThreadClick: handleThreadClick
|
|
2935
|
+
}
|
|
2936
|
+
);
|
|
2937
|
+
case "threads":
|
|
2938
|
+
return /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
|
|
2939
|
+
ThreadsView,
|
|
2940
|
+
{
|
|
2941
|
+
config,
|
|
2942
|
+
threads: admin.threads,
|
|
2943
|
+
searchValue: threadSearch,
|
|
2944
|
+
onSearchChange: setThreadSearch,
|
|
2945
|
+
onThreadClick: handleThreadClick
|
|
2946
|
+
}
|
|
2947
|
+
);
|
|
2948
|
+
case "thread-detail":
|
|
2949
|
+
return route.resourceId ? /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(ThreadDetailView, { threadId: route.resourceId, config, onBack: handleBackToThreads }) : null;
|
|
2950
|
+
case "participants":
|
|
2951
|
+
return /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
|
|
2952
|
+
ParticipantsView,
|
|
2953
|
+
{
|
|
2954
|
+
config,
|
|
2955
|
+
participants: admin.participants,
|
|
2956
|
+
searchValue: participantSearch,
|
|
2957
|
+
onSearchChange: setParticipantSearch,
|
|
2958
|
+
onParticipantClick: handleParticipantClick
|
|
2959
|
+
}
|
|
2960
|
+
);
|
|
2961
|
+
case "participant-detail":
|
|
2962
|
+
return route.resourceId ? /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(ParticipantDetailView, { participantId: route.resourceId, config, onBack: handleBackToParticipants }) : null;
|
|
2963
|
+
case "agents":
|
|
2964
|
+
return /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
|
|
2965
|
+
AgentsView,
|
|
2966
|
+
{
|
|
2967
|
+
config,
|
|
2968
|
+
agents: admin.agents,
|
|
2969
|
+
searchValue: agentSearch,
|
|
2970
|
+
onSearchChange: setAgentSearch,
|
|
2971
|
+
onAgentClick: handleAgentClick
|
|
2972
|
+
}
|
|
2973
|
+
);
|
|
2974
|
+
case "agent-detail":
|
|
2975
|
+
return route.resourceId ? /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(AgentDetailView, { agentId: route.resourceId, config, agents: admin.agents, onBack: handleBackToAgents }) : null;
|
|
2976
|
+
case "collection-items":
|
|
2977
|
+
return route.collection ? /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
|
|
2978
|
+
CollectionItemsView,
|
|
2979
|
+
{
|
|
2980
|
+
collection: route.collection,
|
|
2981
|
+
config,
|
|
2982
|
+
namespace,
|
|
2983
|
+
onItemClick: handleCollectionItemClick,
|
|
2984
|
+
onCreateNew: handleCollectionCreateNew
|
|
2985
|
+
}
|
|
2986
|
+
) : null;
|
|
2987
|
+
case "collection-item-detail":
|
|
2988
|
+
return route.collection ? /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
|
|
2989
|
+
CollectionItemDetailView,
|
|
2990
|
+
{
|
|
2991
|
+
collection: route.collection,
|
|
2992
|
+
itemId: route.resourceId ?? null,
|
|
2993
|
+
config,
|
|
2994
|
+
namespace,
|
|
2995
|
+
onBack: handleBackToCollectionItems
|
|
2996
|
+
}
|
|
2997
|
+
) : null;
|
|
2998
|
+
case "events":
|
|
2999
|
+
return /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(EventsView, { config });
|
|
3000
|
+
default:
|
|
3001
|
+
return null;
|
|
3002
|
+
}
|
|
3003
|
+
};
|
|
3004
|
+
return /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(TooltipProvider, { children: /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(SidebarProvider, { defaultOpen: config.sidebar.defaultOpen, children: /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)(
|
|
3005
|
+
"div",
|
|
3006
|
+
{
|
|
3007
|
+
className: cn(
|
|
3008
|
+
"flex h-[100svh] md:h-screen bg-background w-full overflow-hidden",
|
|
3009
|
+
className
|
|
3010
|
+
),
|
|
3011
|
+
children: [
|
|
3012
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
|
|
3013
|
+
AdminSidebar,
|
|
3014
|
+
{
|
|
3015
|
+
config,
|
|
3016
|
+
currentPage: sidebarPage,
|
|
3017
|
+
currentRoute: route,
|
|
3018
|
+
onNavigate: handleSidebarNavigate,
|
|
3019
|
+
onNavigateRoute: handleSidebarRouteNavigate,
|
|
3020
|
+
collections,
|
|
3021
|
+
namespace,
|
|
3022
|
+
onNamespaceChange: setNamespace
|
|
3023
|
+
}
|
|
3024
|
+
),
|
|
3025
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsx)(SidebarInset, { children: /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)("div", { className: "flex flex-col h-full min-h-0", children: [
|
|
3026
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
|
|
3027
|
+
AdminHeader,
|
|
3028
|
+
{
|
|
3029
|
+
config,
|
|
3030
|
+
currentRoute: route,
|
|
3031
|
+
range: admin.filters.range,
|
|
3032
|
+
interval: admin.filters.interval,
|
|
3033
|
+
onRangeChange: admin.setRange,
|
|
3034
|
+
onIntervalChange: admin.setInterval,
|
|
3035
|
+
onRefresh: () => void admin.refresh(),
|
|
3036
|
+
isLoading: admin.isLoading
|
|
3037
|
+
}
|
|
3038
|
+
),
|
|
3039
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsx)("div", { className: "flex-1 overflow-auto p-6", children: renderCurrentView() })
|
|
3040
|
+
] }) })
|
|
3041
|
+
]
|
|
3042
|
+
}
|
|
3043
|
+
) }) });
|
|
3044
|
+
};
|
|
943
3045
|
// Annotate the CommonJS export names for ESM import in node:
|
|
944
3046
|
0 && (module.exports = {
|
|
945
3047
|
CopilotzAdmin,
|
|
3048
|
+
createCollectionItem,
|
|
946
3049
|
defaultAdminConfig,
|
|
3050
|
+
deleteCollectionItem,
|
|
947
3051
|
fetchAdminActivity,
|
|
948
3052
|
fetchAdminAgents,
|
|
949
3053
|
fetchAdminOverview,
|
|
950
3054
|
fetchAdminParticipants,
|
|
951
3055
|
fetchAdminThreads,
|
|
3056
|
+
fetchCollectionItem,
|
|
3057
|
+
fetchCollectionItems,
|
|
3058
|
+
fetchCollectionNames,
|
|
3059
|
+
fetchParticipantDetail,
|
|
3060
|
+
fetchThreadEvents,
|
|
952
3061
|
mergeAdminConfig,
|
|
3062
|
+
updateCollectionItem,
|
|
3063
|
+
updateParticipant,
|
|
953
3064
|
useCopilotzAdmin
|
|
954
3065
|
});
|
|
955
3066
|
//# sourceMappingURL=index.cjs.map
|