@supaku/agentfactory-dashboard 0.5.0

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.
Files changed (47) hide show
  1. package/LICENSE +21 -0
  2. package/components.json +16 -0
  3. package/package.json +47 -0
  4. package/src/components/fleet/agent-card.tsx +62 -0
  5. package/src/components/fleet/fleet-overview.tsx +89 -0
  6. package/src/components/fleet/provider-icon.tsx +61 -0
  7. package/src/components/fleet/stat-card.tsx +43 -0
  8. package/src/components/fleet/status-dot.tsx +32 -0
  9. package/src/components/layout/bottom-bar.tsx +50 -0
  10. package/src/components/layout/shell.tsx +57 -0
  11. package/src/components/layout/sidebar.tsx +81 -0
  12. package/src/components/layout/top-bar.tsx +55 -0
  13. package/src/components/pipeline/pipeline-card.tsx +42 -0
  14. package/src/components/pipeline/pipeline-column.tsx +40 -0
  15. package/src/components/pipeline/pipeline-view.tsx +75 -0
  16. package/src/components/sessions/session-detail.tsx +132 -0
  17. package/src/components/sessions/session-list.tsx +109 -0
  18. package/src/components/sessions/session-timeline.tsx +54 -0
  19. package/src/components/sessions/token-chart.tsx +51 -0
  20. package/src/components/settings/settings-view.tsx +155 -0
  21. package/src/components/shared/empty-state.tsx +29 -0
  22. package/src/components/shared/logo.tsx +37 -0
  23. package/src/components/ui/badge.tsx +33 -0
  24. package/src/components/ui/button.tsx +54 -0
  25. package/src/components/ui/card.tsx +50 -0
  26. package/src/components/ui/dropdown-menu.tsx +77 -0
  27. package/src/components/ui/scroll-area.tsx +45 -0
  28. package/src/components/ui/separator.tsx +25 -0
  29. package/src/components/ui/sheet.tsx +88 -0
  30. package/src/components/ui/skeleton.tsx +12 -0
  31. package/src/components/ui/tabs.tsx +54 -0
  32. package/src/components/ui/tooltip.tsx +29 -0
  33. package/src/hooks/use-sessions.ts +13 -0
  34. package/src/hooks/use-stats.ts +13 -0
  35. package/src/hooks/use-workers.ts +17 -0
  36. package/src/index.ts +82 -0
  37. package/src/lib/format.ts +36 -0
  38. package/src/lib/status-config.ts +58 -0
  39. package/src/lib/utils.ts +6 -0
  40. package/src/lib/work-type-config.ts +53 -0
  41. package/src/pages/dashboard-page.tsx +7 -0
  42. package/src/pages/pipeline-page.tsx +7 -0
  43. package/src/pages/session-page.tsx +29 -0
  44. package/src/pages/settings-page.tsx +7 -0
  45. package/src/styles/globals.css +38 -0
  46. package/src/types/api.ts +45 -0
  47. package/tailwind.config.ts +88 -0
@@ -0,0 +1,37 @@
1
+ import { cn } from '../../lib/utils'
2
+
3
+ interface LogoProps {
4
+ className?: string
5
+ size?: number
6
+ }
7
+
8
+ export function Logo({ className, size = 32 }: LogoProps) {
9
+ return (
10
+ <svg
11
+ width={size}
12
+ height={size}
13
+ viewBox="0 0 512 512"
14
+ fill="none"
15
+ xmlns="http://www.w3.org/2000/svg"
16
+ className={cn('text-af-accent', className)}
17
+ >
18
+ <g transform="matrix(1.28321,0,0,1.28321,-56.4612,-56.0276)">
19
+ <g transform="matrix(1,0,0,1,-278,-269)">
20
+ <path
21
+ d="M458,365L448,370L440,378L436,388L436,401L441,412L448,419L459,425L459,569L505,616L504.5,650.092L494.5,655.092L486.5,664.092L482.5,674.092L482.5,686.092L488.5,699.092L496.5,706.092L502.5,709.092L516.5,710.092L530.5,704.092L539.5,693.092L541.5,687.092L541.5,673.092L537.5,664.092L529.5,655.092L519.5,650.092L519,614L564,569L564,507L573,499L577,489L576,481L572,474L562,468L549,469L539,479L539,495L542,500L550,506L550,563L524,589L520,589L519,476L555,447L560,447L648,518L655,521L668,330L693.779,330L695,335L707,467L707,696L704,698L566,698L564,696L565,632L610,587L610,546L620,537L623,524L620,516L613,509L599,507L592,510L584,521L585,535L596,546L596,581L550,627L550,711.779L721,712L721,467L709,334L706,312.662L655,312.662L644,491L637,491L564,431L564,429L575,423L585,411L587,405L587,392L584,384L574,373L565,369L547,370L533,381L528,392L528,405L530,411L541,424L550,428L550,433L524,454L519,453L519,374L528,370L537,361L541,351L540,335L535,326L529,320L517,315L502,316L494,320L488,326L482,339L482,351L487,362L494,369L503,373L505,373.559L504,588L499,589L473,563L473,424L482,420L492,409L495,401L495,388L490,377L482,369L473,365L458,365ZM528.287,679.998C528.287,671.063 520.935,663.711 512,663.711C503.065,663.711 495.713,671.063 495.713,679.998C495.713,688.933 503.065,696.285 512,696.285C520.935,696.285 528.287,688.933 528.287,679.998ZM527.607,344.629C527.607,344.587 527.608,344.545 527.608,344.502C527.608,335.705 520.368,328.465 511.57,328.465C502.773,328.465 495.534,335.705 495.534,344.502C495.534,344.545 495.534,344.587 495.534,344.629C495.534,344.671 495.534,344.713 495.534,344.756C495.534,353.553 502.773,360.793 511.57,360.793C520.368,360.793 527.608,353.553 527.608,344.756C527.608,344.713 527.607,344.671 527.607,344.629ZM573.561,398.285C573.561,389.447 566.288,382.174 557.45,382.174C548.612,382.174 541.339,389.447 541.339,398.285L541.339,398.285C541.339,407.123 548.612,414.396 557.45,414.396C566.288,414.396 573.561,407.123 573.561,398.285L573.561,398.285ZM481.681,394.375C481.681,385.567 474.433,378.319 465.625,378.319C456.817,378.319 449.569,385.567 449.569,394.375L449.569,394.375C449.569,403.183 456.817,410.431 465.625,410.431C474.433,410.431 481.681,403.183 481.681,394.375L481.681,394.375Z"
22
+ fill="currentColor"
23
+ fillRule="evenodd"
24
+ clipRule="evenodd"
25
+ />
26
+ </g>
27
+ <g transform="matrix(1,0,0,1,-278,-269)">
28
+ <path
29
+ d="M427,365L424,365L322,469L322,712L473,711.779L473,628L427,581L427,520L438,509L439,495L431,484L424,481L416,481L409,484L403,490L400,499L403,511L413,520L413,587L459,634L459,696L457,698L339,698L337,696L337,476L408,401.455L413,397L413,460L426,460L427,365Z"
30
+ fill="currentColor"
31
+ fillRule="nonzero"
32
+ />
33
+ </g>
34
+ </g>
35
+ </svg>
36
+ )
37
+ }
@@ -0,0 +1,33 @@
1
+ import * as React from 'react'
2
+ import { cva, type VariantProps } from 'class-variance-authority'
3
+ import { cn } from '../../lib/utils'
4
+
5
+ const badgeVariants = cva(
6
+ 'inline-flex items-center rounded-full border px-2 py-0.5 text-xs font-medium transition-colors focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2',
7
+ {
8
+ variants: {
9
+ variant: {
10
+ default: 'border-transparent bg-primary text-primary-foreground',
11
+ secondary: 'border-transparent bg-secondary text-secondary-foreground',
12
+ destructive: 'border-transparent bg-destructive text-destructive-foreground',
13
+ outline: 'text-foreground',
14
+ success: 'border-transparent bg-af-status-success/10 text-af-status-success',
15
+ warning: 'border-transparent bg-af-status-warning/10 text-af-status-warning',
16
+ error: 'border-transparent bg-af-status-error/10 text-af-status-error',
17
+ },
18
+ },
19
+ defaultVariants: {
20
+ variant: 'default',
21
+ },
22
+ }
23
+ )
24
+
25
+ export interface BadgeProps
26
+ extends React.HTMLAttributes<HTMLDivElement>,
27
+ VariantProps<typeof badgeVariants> {}
28
+
29
+ function Badge({ className, variant, ...props }: BadgeProps) {
30
+ return <div className={cn(badgeVariants({ variant }), className)} {...props} />
31
+ }
32
+
33
+ export { Badge, badgeVariants }
@@ -0,0 +1,54 @@
1
+ 'use client'
2
+
3
+ import * as React from 'react'
4
+ import { Slot } from '@radix-ui/react-slot'
5
+ import { cva, type VariantProps } from 'class-variance-authority'
6
+ import { cn } from '../../lib/utils'
7
+
8
+ const buttonVariants = cva(
9
+ 'inline-flex items-center justify-center whitespace-nowrap rounded-md text-sm font-medium ring-offset-background transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50',
10
+ {
11
+ variants: {
12
+ variant: {
13
+ default: 'bg-primary text-primary-foreground hover:bg-primary/90',
14
+ destructive: 'bg-destructive text-destructive-foreground hover:bg-destructive/90',
15
+ outline: 'border border-input bg-background hover:bg-accent hover:text-accent-foreground',
16
+ secondary: 'bg-secondary text-secondary-foreground hover:bg-secondary/80',
17
+ ghost: 'hover:bg-accent hover:text-accent-foreground',
18
+ link: 'text-primary underline-offset-4 hover:underline',
19
+ },
20
+ size: {
21
+ default: 'h-9 px-4 py-2',
22
+ sm: 'h-8 rounded-md px-3',
23
+ lg: 'h-10 rounded-md px-8',
24
+ icon: 'h-9 w-9',
25
+ },
26
+ },
27
+ defaultVariants: {
28
+ variant: 'default',
29
+ size: 'default',
30
+ },
31
+ }
32
+ )
33
+
34
+ export interface ButtonProps
35
+ extends React.ButtonHTMLAttributes<HTMLButtonElement>,
36
+ VariantProps<typeof buttonVariants> {
37
+ asChild?: boolean
38
+ }
39
+
40
+ const Button = React.forwardRef<HTMLButtonElement, ButtonProps>(
41
+ ({ className, variant, size, asChild = false, ...props }, ref) => {
42
+ const Comp = asChild ? Slot : 'button'
43
+ return (
44
+ <Comp
45
+ className={cn(buttonVariants({ variant, size, className }))}
46
+ ref={ref}
47
+ {...props}
48
+ />
49
+ )
50
+ }
51
+ )
52
+ Button.displayName = 'Button'
53
+
54
+ export { Button, buttonVariants }
@@ -0,0 +1,50 @@
1
+ import * as React from 'react'
2
+ import { cn } from '../../lib/utils'
3
+
4
+ const Card = React.forwardRef<HTMLDivElement, React.HTMLAttributes<HTMLDivElement>>(
5
+ ({ className, ...props }, ref) => (
6
+ <div
7
+ ref={ref}
8
+ className={cn('rounded-lg border border-af-surface-border bg-af-surface text-card-foreground', className)}
9
+ {...props}
10
+ />
11
+ )
12
+ )
13
+ Card.displayName = 'Card'
14
+
15
+ const CardHeader = React.forwardRef<HTMLDivElement, React.HTMLAttributes<HTMLDivElement>>(
16
+ ({ className, ...props }, ref) => (
17
+ <div ref={ref} className={cn('flex flex-col space-y-1.5 p-5', className)} {...props} />
18
+ )
19
+ )
20
+ CardHeader.displayName = 'CardHeader'
21
+
22
+ const CardTitle = React.forwardRef<HTMLParagraphElement, React.HTMLAttributes<HTMLHeadingElement>>(
23
+ ({ className, ...props }, ref) => (
24
+ <h3 ref={ref} className={cn('text-sm font-medium leading-none tracking-tight', className)} {...props} />
25
+ )
26
+ )
27
+ CardTitle.displayName = 'CardTitle'
28
+
29
+ const CardDescription = React.forwardRef<HTMLParagraphElement, React.HTMLAttributes<HTMLParagraphElement>>(
30
+ ({ className, ...props }, ref) => (
31
+ <p ref={ref} className={cn('text-sm text-muted-foreground', className)} {...props} />
32
+ )
33
+ )
34
+ CardDescription.displayName = 'CardDescription'
35
+
36
+ const CardContent = React.forwardRef<HTMLDivElement, React.HTMLAttributes<HTMLDivElement>>(
37
+ ({ className, ...props }, ref) => (
38
+ <div ref={ref} className={cn('p-5 pt-0', className)} {...props} />
39
+ )
40
+ )
41
+ CardContent.displayName = 'CardContent'
42
+
43
+ const CardFooter = React.forwardRef<HTMLDivElement, React.HTMLAttributes<HTMLDivElement>>(
44
+ ({ className, ...props }, ref) => (
45
+ <div ref={ref} className={cn('flex items-center p-5 pt-0', className)} {...props} />
46
+ )
47
+ )
48
+ CardFooter.displayName = 'CardFooter'
49
+
50
+ export { Card, CardHeader, CardFooter, CardTitle, CardDescription, CardContent }
@@ -0,0 +1,77 @@
1
+ 'use client'
2
+
3
+ import * as React from 'react'
4
+ import * as DropdownMenuPrimitive from '@radix-ui/react-dropdown-menu'
5
+ import { cn } from '../../lib/utils'
6
+
7
+ const DropdownMenu = DropdownMenuPrimitive.Root
8
+ const DropdownMenuTrigger = DropdownMenuPrimitive.Trigger
9
+ const DropdownMenuGroup = DropdownMenuPrimitive.Group
10
+
11
+ const DropdownMenuContent = React.forwardRef<
12
+ React.ComponentRef<typeof DropdownMenuPrimitive.Content>,
13
+ React.ComponentPropsWithoutRef<typeof DropdownMenuPrimitive.Content>
14
+ >(({ className, sideOffset = 4, ...props }, ref) => (
15
+ <DropdownMenuPrimitive.Portal>
16
+ <DropdownMenuPrimitive.Content
17
+ ref={ref}
18
+ sideOffset={sideOffset}
19
+ className={cn(
20
+ 'z-50 min-w-[8rem] overflow-hidden rounded-md border bg-popover p-1 text-popover-foreground shadow-md data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-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',
21
+ className
22
+ )}
23
+ {...props}
24
+ />
25
+ </DropdownMenuPrimitive.Portal>
26
+ ))
27
+ DropdownMenuContent.displayName = DropdownMenuPrimitive.Content.displayName
28
+
29
+ const DropdownMenuItem = React.forwardRef<
30
+ React.ComponentRef<typeof DropdownMenuPrimitive.Item>,
31
+ React.ComponentPropsWithoutRef<typeof DropdownMenuPrimitive.Item> & { inset?: boolean }
32
+ >(({ className, inset, ...props }, ref) => (
33
+ <DropdownMenuPrimitive.Item
34
+ ref={ref}
35
+ className={cn(
36
+ 'relative flex cursor-default select-none items-center rounded-sm px-2 py-1.5 text-sm outline-none transition-colors focus:bg-accent focus:text-accent-foreground data-[disabled]:pointer-events-none data-[disabled]:opacity-50',
37
+ inset && 'pl-8',
38
+ className
39
+ )}
40
+ {...props}
41
+ />
42
+ ))
43
+ DropdownMenuItem.displayName = DropdownMenuPrimitive.Item.displayName
44
+
45
+ const DropdownMenuSeparator = React.forwardRef<
46
+ React.ComponentRef<typeof DropdownMenuPrimitive.Separator>,
47
+ React.ComponentPropsWithoutRef<typeof DropdownMenuPrimitive.Separator>
48
+ >(({ className, ...props }, ref) => (
49
+ <DropdownMenuPrimitive.Separator
50
+ ref={ref}
51
+ className={cn('-mx-1 my-1 h-px bg-muted', className)}
52
+ {...props}
53
+ />
54
+ ))
55
+ DropdownMenuSeparator.displayName = DropdownMenuPrimitive.Separator.displayName
56
+
57
+ const DropdownMenuLabel = React.forwardRef<
58
+ React.ComponentRef<typeof DropdownMenuPrimitive.Label>,
59
+ React.ComponentPropsWithoutRef<typeof DropdownMenuPrimitive.Label> & { inset?: boolean }
60
+ >(({ className, inset, ...props }, ref) => (
61
+ <DropdownMenuPrimitive.Label
62
+ ref={ref}
63
+ className={cn('px-2 py-1.5 text-sm font-semibold', inset && 'pl-8', className)}
64
+ {...props}
65
+ />
66
+ ))
67
+ DropdownMenuLabel.displayName = DropdownMenuPrimitive.Label.displayName
68
+
69
+ export {
70
+ DropdownMenu,
71
+ DropdownMenuTrigger,
72
+ DropdownMenuContent,
73
+ DropdownMenuItem,
74
+ DropdownMenuSeparator,
75
+ DropdownMenuLabel,
76
+ DropdownMenuGroup,
77
+ }
@@ -0,0 +1,45 @@
1
+ 'use client'
2
+
3
+ import * as React from 'react'
4
+ import * as ScrollAreaPrimitive from '@radix-ui/react-scroll-area'
5
+ import { cn } from '../../lib/utils'
6
+
7
+ const ScrollArea = React.forwardRef<
8
+ React.ComponentRef<typeof ScrollAreaPrimitive.Root>,
9
+ React.ComponentPropsWithoutRef<typeof ScrollAreaPrimitive.Root>
10
+ >(({ className, children, ...props }, ref) => (
11
+ <ScrollAreaPrimitive.Root
12
+ ref={ref}
13
+ className={cn('relative overflow-hidden', className)}
14
+ {...props}
15
+ >
16
+ <ScrollAreaPrimitive.Viewport className="h-full w-full rounded-[inherit]">
17
+ {children}
18
+ </ScrollAreaPrimitive.Viewport>
19
+ <ScrollBar />
20
+ <ScrollAreaPrimitive.Corner />
21
+ </ScrollAreaPrimitive.Root>
22
+ ))
23
+ ScrollArea.displayName = ScrollAreaPrimitive.Root.displayName
24
+
25
+ const ScrollBar = React.forwardRef<
26
+ React.ComponentRef<typeof ScrollAreaPrimitive.ScrollAreaScrollbar>,
27
+ React.ComponentPropsWithoutRef<typeof ScrollAreaPrimitive.ScrollAreaScrollbar>
28
+ >(({ className, orientation = 'vertical', ...props }, ref) => (
29
+ <ScrollAreaPrimitive.ScrollAreaScrollbar
30
+ ref={ref}
31
+ orientation={orientation}
32
+ className={cn(
33
+ 'flex touch-none select-none transition-colors',
34
+ orientation === 'vertical' && 'h-full w-2.5 border-l border-l-transparent p-[1px]',
35
+ orientation === 'horizontal' && 'h-2.5 flex-col border-t border-t-transparent p-[1px]',
36
+ className
37
+ )}
38
+ {...props}
39
+ >
40
+ <ScrollAreaPrimitive.ScrollAreaThumb className="relative flex-1 rounded-full bg-border" />
41
+ </ScrollAreaPrimitive.ScrollAreaScrollbar>
42
+ ))
43
+ ScrollBar.displayName = ScrollAreaPrimitive.ScrollAreaScrollbar.displayName
44
+
45
+ export { ScrollArea, ScrollBar }
@@ -0,0 +1,25 @@
1
+ 'use client'
2
+
3
+ import * as React from 'react'
4
+ import * as SeparatorPrimitive from '@radix-ui/react-separator'
5
+ import { cn } from '../../lib/utils'
6
+
7
+ const Separator = React.forwardRef<
8
+ React.ComponentRef<typeof SeparatorPrimitive.Root>,
9
+ React.ComponentPropsWithoutRef<typeof SeparatorPrimitive.Root>
10
+ >(({ className, orientation = 'horizontal', decorative = true, ...props }, ref) => (
11
+ <SeparatorPrimitive.Root
12
+ ref={ref}
13
+ decorative={decorative}
14
+ orientation={orientation}
15
+ className={cn(
16
+ 'shrink-0 bg-border',
17
+ orientation === 'horizontal' ? 'h-[1px] w-full' : 'h-full w-[1px]',
18
+ className
19
+ )}
20
+ {...props}
21
+ />
22
+ ))
23
+ Separator.displayName = SeparatorPrimitive.Root.displayName
24
+
25
+ export { Separator }
@@ -0,0 +1,88 @@
1
+ 'use client'
2
+
3
+ import * as React from 'react'
4
+ import * as DialogPrimitive from '@radix-ui/react-dialog'
5
+ import { cva, type VariantProps } from 'class-variance-authority'
6
+ import { X } from 'lucide-react'
7
+ import { cn } from '../../lib/utils'
8
+
9
+ const Sheet = DialogPrimitive.Root
10
+ const SheetTrigger = DialogPrimitive.Trigger
11
+ const SheetClose = DialogPrimitive.Close
12
+ const SheetPortal = DialogPrimitive.Portal
13
+
14
+ const SheetOverlay = React.forwardRef<
15
+ React.ComponentRef<typeof DialogPrimitive.Overlay>,
16
+ React.ComponentPropsWithoutRef<typeof DialogPrimitive.Overlay>
17
+ >(({ className, ...props }, ref) => (
18
+ <DialogPrimitive.Overlay
19
+ className={cn(
20
+ 'fixed inset-0 z-50 bg-black/80 data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0',
21
+ className
22
+ )}
23
+ {...props}
24
+ ref={ref}
25
+ />
26
+ ))
27
+ SheetOverlay.displayName = DialogPrimitive.Overlay.displayName
28
+
29
+ const sheetVariants = cva(
30
+ 'fixed z-50 gap-4 bg-af-bg-secondary p-6 shadow-lg transition ease-in-out data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:duration-300 data-[state=open]:duration-500',
31
+ {
32
+ variants: {
33
+ side: {
34
+ top: 'inset-x-0 top-0 border-b data-[state=closed]:slide-out-to-top data-[state=open]:slide-in-from-top',
35
+ bottom: 'inset-x-0 bottom-0 border-t data-[state=closed]:slide-out-to-bottom data-[state=open]:slide-in-from-bottom',
36
+ left: 'inset-y-0 left-0 h-full w-3/4 border-r data-[state=closed]:slide-out-to-left data-[state=open]:slide-in-from-left sm:max-w-sm',
37
+ right: 'inset-y-0 right-0 h-full w-3/4 border-r data-[state=closed]:slide-out-to-right data-[state=open]:slide-in-from-right sm:max-w-sm',
38
+ },
39
+ },
40
+ defaultVariants: {
41
+ side: 'right',
42
+ },
43
+ }
44
+ )
45
+
46
+ interface SheetContentProps
47
+ extends React.ComponentPropsWithoutRef<typeof DialogPrimitive.Content>,
48
+ VariantProps<typeof sheetVariants> {}
49
+
50
+ const SheetContent = React.forwardRef<
51
+ React.ComponentRef<typeof DialogPrimitive.Content>,
52
+ SheetContentProps
53
+ >(({ side = 'left', className, children, ...props }, ref) => (
54
+ <SheetPortal>
55
+ <SheetOverlay />
56
+ <DialogPrimitive.Content
57
+ ref={ref}
58
+ className={cn(sheetVariants({ side }), className)}
59
+ {...props}
60
+ >
61
+ {children}
62
+ <DialogPrimitive.Close className="absolute right-4 top-4 rounded-sm opacity-70 ring-offset-background transition-opacity hover:opacity-100 focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2 disabled:pointer-events-none data-[state=open]:bg-secondary">
63
+ <X className="h-4 w-4" />
64
+ <span className="sr-only">Close</span>
65
+ </DialogPrimitive.Close>
66
+ </DialogPrimitive.Content>
67
+ </SheetPortal>
68
+ ))
69
+ SheetContent.displayName = DialogPrimitive.Content.displayName
70
+
71
+ const SheetHeader = ({ className, ...props }: React.HTMLAttributes<HTMLDivElement>) => (
72
+ <div className={cn('flex flex-col space-y-2 text-center sm:text-left', className)} {...props} />
73
+ )
74
+ SheetHeader.displayName = 'SheetHeader'
75
+
76
+ const SheetTitle = React.forwardRef<
77
+ React.ComponentRef<typeof DialogPrimitive.Title>,
78
+ React.ComponentPropsWithoutRef<typeof DialogPrimitive.Title>
79
+ >(({ className, ...props }, ref) => (
80
+ <DialogPrimitive.Title
81
+ ref={ref}
82
+ className={cn('text-lg font-semibold text-foreground', className)}
83
+ {...props}
84
+ />
85
+ ))
86
+ SheetTitle.displayName = DialogPrimitive.Title.displayName
87
+
88
+ export { Sheet, SheetTrigger, SheetClose, SheetContent, SheetHeader, SheetTitle }
@@ -0,0 +1,12 @@
1
+ import { cn } from '../../lib/utils'
2
+
3
+ function Skeleton({ className, ...props }: React.HTMLAttributes<HTMLDivElement>) {
4
+ return (
5
+ <div
6
+ className={cn('animate-pulse rounded-md bg-muted', className)}
7
+ {...props}
8
+ />
9
+ )
10
+ }
11
+
12
+ export { Skeleton }
@@ -0,0 +1,54 @@
1
+ 'use client'
2
+
3
+ import * as React from 'react'
4
+ import * as TabsPrimitive from '@radix-ui/react-tabs'
5
+ import { cn } from '../../lib/utils'
6
+
7
+ const Tabs = TabsPrimitive.Root
8
+
9
+ const TabsList = React.forwardRef<
10
+ React.ComponentRef<typeof TabsPrimitive.List>,
11
+ React.ComponentPropsWithoutRef<typeof TabsPrimitive.List>
12
+ >(({ className, ...props }, ref) => (
13
+ <TabsPrimitive.List
14
+ ref={ref}
15
+ className={cn(
16
+ 'inline-flex h-9 items-center justify-center rounded-lg bg-muted p-1 text-muted-foreground',
17
+ className
18
+ )}
19
+ {...props}
20
+ />
21
+ ))
22
+ TabsList.displayName = TabsPrimitive.List.displayName
23
+
24
+ const TabsTrigger = React.forwardRef<
25
+ React.ComponentRef<typeof TabsPrimitive.Trigger>,
26
+ React.ComponentPropsWithoutRef<typeof TabsPrimitive.Trigger>
27
+ >(({ className, ...props }, ref) => (
28
+ <TabsPrimitive.Trigger
29
+ ref={ref}
30
+ className={cn(
31
+ 'inline-flex items-center justify-center whitespace-nowrap rounded-md px-3 py-1 text-sm font-medium ring-offset-background transition-all focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50 data-[state=active]:bg-background data-[state=active]:text-foreground data-[state=active]:shadow-sm',
32
+ className
33
+ )}
34
+ {...props}
35
+ />
36
+ ))
37
+ TabsTrigger.displayName = TabsPrimitive.Trigger.displayName
38
+
39
+ const TabsContent = React.forwardRef<
40
+ React.ComponentRef<typeof TabsPrimitive.Content>,
41
+ React.ComponentPropsWithoutRef<typeof TabsPrimitive.Content>
42
+ >(({ className, ...props }, ref) => (
43
+ <TabsPrimitive.Content
44
+ ref={ref}
45
+ className={cn(
46
+ 'mt-2 ring-offset-background focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2',
47
+ className
48
+ )}
49
+ {...props}
50
+ />
51
+ ))
52
+ TabsContent.displayName = TabsPrimitive.Content.displayName
53
+
54
+ export { Tabs, TabsList, TabsTrigger, TabsContent }
@@ -0,0 +1,29 @@
1
+ 'use client'
2
+
3
+ import * as React from 'react'
4
+ import * as TooltipPrimitive from '@radix-ui/react-tooltip'
5
+ import { cn } from '../../lib/utils'
6
+
7
+ const TooltipProvider = TooltipPrimitive.Provider
8
+
9
+ const Tooltip = TooltipPrimitive.Root
10
+
11
+ const TooltipTrigger = TooltipPrimitive.Trigger
12
+
13
+ const TooltipContent = React.forwardRef<
14
+ React.ComponentRef<typeof TooltipPrimitive.Content>,
15
+ React.ComponentPropsWithoutRef<typeof TooltipPrimitive.Content>
16
+ >(({ className, sideOffset = 4, ...props }, ref) => (
17
+ <TooltipPrimitive.Content
18
+ ref={ref}
19
+ sideOffset={sideOffset}
20
+ className={cn(
21
+ 'z-50 overflow-hidden rounded-md bg-popover px-3 py-1.5 text-xs text-popover-foreground shadow-md 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',
22
+ className
23
+ )}
24
+ {...props}
25
+ />
26
+ ))
27
+ TooltipContent.displayName = TooltipPrimitive.Content.displayName
28
+
29
+ export { Tooltip, TooltipTrigger, TooltipContent, TooltipProvider }
@@ -0,0 +1,13 @@
1
+ 'use client'
2
+
3
+ import useSWR from 'swr'
4
+ import type { PublicSessionsListResponse } from '../types/api'
5
+
6
+ const fetcher = (url: string) => fetch(url).then((r) => r.json())
7
+
8
+ export function useSessions(refreshInterval = 5000) {
9
+ return useSWR<PublicSessionsListResponse>('/api/public/sessions', fetcher, {
10
+ refreshInterval,
11
+ dedupingInterval: 2000,
12
+ })
13
+ }
@@ -0,0 +1,13 @@
1
+ 'use client'
2
+
3
+ import useSWR from 'swr'
4
+ import type { PublicStatsResponse } from '../types/api'
5
+
6
+ const fetcher = (url: string) => fetch(url).then((r) => r.json())
7
+
8
+ export function useStats(refreshInterval = 5000) {
9
+ return useSWR<PublicStatsResponse>('/api/public/stats', fetcher, {
10
+ refreshInterval,
11
+ dedupingInterval: 2000,
12
+ })
13
+ }
@@ -0,0 +1,17 @@
1
+ 'use client'
2
+
3
+ import useSWR from 'swr'
4
+ import type { WorkersListResponse } from '../types/api'
5
+
6
+ const authedFetcher = async (url: string) => {
7
+ const res = await fetch(url)
8
+ if (res.status === 401) return null
9
+ return res.json()
10
+ }
11
+
12
+ export function useWorkers(refreshInterval = 10000) {
13
+ return useSWR<WorkersListResponse | null>('/api/workers', authedFetcher, {
14
+ refreshInterval,
15
+ dedupingInterval: 5000,
16
+ })
17
+ }
package/src/index.ts ADDED
@@ -0,0 +1,82 @@
1
+ // Layout
2
+ export { DashboardShell } from './components/layout/shell'
3
+ export { Sidebar } from './components/layout/sidebar'
4
+ export { TopBar } from './components/layout/top-bar'
5
+ export { BottomBar } from './components/layout/bottom-bar'
6
+
7
+ // Pages
8
+ export { DashboardPage } from './pages/dashboard-page'
9
+ export { PipelinePage } from './pages/pipeline-page'
10
+ export { SessionPage } from './pages/session-page'
11
+ export { SettingsPage } from './pages/settings-page'
12
+
13
+ // Fleet components
14
+ export { FleetOverview } from './components/fleet/fleet-overview'
15
+ export { AgentCard } from './components/fleet/agent-card'
16
+ export { StatCard } from './components/fleet/stat-card'
17
+ export { StatusDot } from './components/fleet/status-dot'
18
+ export { ProviderIcon } from './components/fleet/provider-icon'
19
+
20
+ // Pipeline components
21
+ export { PipelineView } from './components/pipeline/pipeline-view'
22
+ export { PipelineColumn } from './components/pipeline/pipeline-column'
23
+ export { PipelineCard } from './components/pipeline/pipeline-card'
24
+
25
+ // Session components
26
+ export { SessionList } from './components/sessions/session-list'
27
+ export { SessionDetail } from './components/sessions/session-detail'
28
+ export { SessionTimeline } from './components/sessions/session-timeline'
29
+ export { TokenChart } from './components/sessions/token-chart'
30
+
31
+ // Settings
32
+ export { SettingsView } from './components/settings/settings-view'
33
+
34
+ // Shared
35
+ export { Logo } from './components/shared/logo'
36
+ export { EmptyState } from './components/shared/empty-state'
37
+
38
+ // UI primitives
39
+ export { Button } from './components/ui/button'
40
+ export { Card, CardHeader, CardFooter, CardTitle, CardDescription, CardContent } from './components/ui/card'
41
+ export { Badge } from './components/ui/badge'
42
+ export { Skeleton } from './components/ui/skeleton'
43
+ export { Separator } from './components/ui/separator'
44
+ export { ScrollArea, ScrollBar } from './components/ui/scroll-area'
45
+ export { Tabs, TabsList, TabsTrigger, TabsContent } from './components/ui/tabs'
46
+ export { Tooltip, TooltipTrigger, TooltipContent, TooltipProvider } from './components/ui/tooltip'
47
+ export { Sheet, SheetTrigger, SheetClose, SheetContent, SheetHeader, SheetTitle } from './components/ui/sheet'
48
+ export {
49
+ DropdownMenu,
50
+ DropdownMenuTrigger,
51
+ DropdownMenuContent,
52
+ DropdownMenuItem,
53
+ DropdownMenuSeparator,
54
+ DropdownMenuLabel,
55
+ DropdownMenuGroup,
56
+ } from './components/ui/dropdown-menu'
57
+
58
+ // Hooks
59
+ export { useStats } from './hooks/use-stats'
60
+ export { useSessions } from './hooks/use-sessions'
61
+ export { useWorkers } from './hooks/use-workers'
62
+
63
+ // Utilities
64
+ export { cn } from './lib/utils'
65
+ export { formatDuration, formatCost, formatTokens, formatRelativeTime } from './lib/format'
66
+ export { getWorkTypeConfig } from './lib/work-type-config'
67
+ export { getStatusConfig } from './lib/status-config'
68
+
69
+ // Types
70
+ export type {
71
+ PublicStatsResponse,
72
+ PublicSessionResponse,
73
+ PublicSessionsListResponse,
74
+ SessionStatus,
75
+ WorkerResponse,
76
+ WorkersListResponse,
77
+ PipelineStatus,
78
+ } from './types/api'
79
+ export type { WorkTypeConfig } from './lib/work-type-config'
80
+ export type { StatusConfig } from './lib/status-config'
81
+ export type { TimelineEvent } from './components/sessions/session-timeline'
82
+ export type { NavItem } from './components/layout/sidebar'