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