@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.
- package/LICENSE +21 -0
- package/components.json +16 -0
- package/package.json +47 -0
- package/src/components/fleet/agent-card.tsx +62 -0
- package/src/components/fleet/fleet-overview.tsx +89 -0
- package/src/components/fleet/provider-icon.tsx +61 -0
- package/src/components/fleet/stat-card.tsx +43 -0
- package/src/components/fleet/status-dot.tsx +32 -0
- package/src/components/layout/bottom-bar.tsx +50 -0
- package/src/components/layout/shell.tsx +57 -0
- package/src/components/layout/sidebar.tsx +81 -0
- package/src/components/layout/top-bar.tsx +55 -0
- package/src/components/pipeline/pipeline-card.tsx +42 -0
- package/src/components/pipeline/pipeline-column.tsx +40 -0
- package/src/components/pipeline/pipeline-view.tsx +75 -0
- package/src/components/sessions/session-detail.tsx +132 -0
- package/src/components/sessions/session-list.tsx +109 -0
- package/src/components/sessions/session-timeline.tsx +54 -0
- package/src/components/sessions/token-chart.tsx +51 -0
- package/src/components/settings/settings-view.tsx +155 -0
- package/src/components/shared/empty-state.tsx +29 -0
- package/src/components/shared/logo.tsx +37 -0
- package/src/components/ui/badge.tsx +33 -0
- package/src/components/ui/button.tsx +54 -0
- package/src/components/ui/card.tsx +50 -0
- package/src/components/ui/dropdown-menu.tsx +77 -0
- package/src/components/ui/scroll-area.tsx +45 -0
- package/src/components/ui/separator.tsx +25 -0
- package/src/components/ui/sheet.tsx +88 -0
- package/src/components/ui/skeleton.tsx +12 -0
- package/src/components/ui/tabs.tsx +54 -0
- package/src/components/ui/tooltip.tsx +29 -0
- package/src/hooks/use-sessions.ts +13 -0
- package/src/hooks/use-stats.ts +13 -0
- package/src/hooks/use-workers.ts +17 -0
- package/src/index.ts +82 -0
- package/src/lib/format.ts +36 -0
- package/src/lib/status-config.ts +58 -0
- package/src/lib/utils.ts +6 -0
- package/src/lib/work-type-config.ts +53 -0
- package/src/pages/dashboard-page.tsx +7 -0
- package/src/pages/pipeline-page.tsx +7 -0
- package/src/pages/session-page.tsx +29 -0
- package/src/pages/settings-page.tsx +7 -0
- package/src/styles/globals.css +38 -0
- package/src/types/api.ts +45 -0
- 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'
|