a:hover]:text-primary [&>a]:underline [&>a]:underline-offset-4 [[data-slot=empty-title]+&]:mt-1",
+ className,
+ )}
+ data-slot="empty-description"
+ {...props}
+ />
+ );
+}
+
+function EmptyContent({ className, ...props }: React.ComponentProps<"div">) {
+ return (
+
+ );
+}
+
+export {
+ Empty,
+ EmptyHeader,
+ EmptyTitle,
+ EmptyDescription,
+ EmptyContent,
+ EmptyMedia,
+};
diff --git a/apps/web/src/components/ui/field.tsx b/apps/web/src/components/ui/field.tsx
new file mode 100644
index 0000000000000000000000000000000000000000..47ad20052f97e63af1cd90b42de26f3091157b96
--- /dev/null
+++ b/apps/web/src/components/ui/field.tsx
@@ -0,0 +1,74 @@
+"use client";
+
+import { Field as FieldPrimitive } from "@base-ui/react/field";
+
+import { cn } from "~/lib/utils";
+
+function Field({ className, ...props }: FieldPrimitive.Root.Props) {
+ return (
+
+ );
+}
+
+function FieldLabel({ className, ...props }: FieldPrimitive.Label.Props) {
+ return (
+
+ );
+}
+
+function FieldItem({ className, ...props }: FieldPrimitive.Item.Props) {
+ return (
+
+ );
+}
+
+function FieldDescription({
+ className,
+ ...props
+}: FieldPrimitive.Description.Props) {
+ return (
+
+ );
+}
+
+function FieldError({ className, ...props }: FieldPrimitive.Error.Props) {
+ return (
+
+ );
+}
+
+const FieldControl = FieldPrimitive.Control;
+const FieldValidity = FieldPrimitive.Validity;
+
+export {
+ Field,
+ FieldLabel,
+ FieldDescription,
+ FieldError,
+ FieldControl,
+ FieldItem,
+ FieldValidity,
+};
diff --git a/apps/web/src/components/ui/fieldset.tsx b/apps/web/src/components/ui/fieldset.tsx
new file mode 100644
index 0000000000000000000000000000000000000000..9c054e210578aeed40d6832b9c68f8ca30ff4951
--- /dev/null
+++ b/apps/web/src/components/ui/fieldset.tsx
@@ -0,0 +1,29 @@
+"use client";
+
+import { Fieldset as FieldsetPrimitive } from "@base-ui/react/fieldset";
+
+import { cn } from "~/lib/utils";
+
+function Fieldset({ className, ...props }: FieldsetPrimitive.Root.Props) {
+ return (
+
+ );
+}
+function FieldsetLegend({
+ className,
+ ...props
+}: FieldsetPrimitive.Legend.Props) {
+ return (
+
+ );
+}
+
+export { Fieldset, FieldsetLegend };
diff --git a/apps/web/src/components/ui/form.tsx b/apps/web/src/components/ui/form.tsx
new file mode 100644
index 0000000000000000000000000000000000000000..641fc2ee6270c7681e3054bcaafd640666bb83bf
--- /dev/null
+++ b/apps/web/src/components/ui/form.tsx
@@ -0,0 +1,17 @@
+"use client";
+
+import { Form as FormPrimitive } from "@base-ui/react/form";
+
+import { cn } from "~/lib/utils";
+
+function Form({ className, ...props }: FormPrimitive.Props) {
+ return (
+
+ );
+}
+
+export { Form };
diff --git a/apps/web/src/components/ui/group.tsx b/apps/web/src/components/ui/group.tsx
new file mode 100644
index 0000000000000000000000000000000000000000..6eedfdda922899022b175e0d5d31a00dc6e67beb
--- /dev/null
+++ b/apps/web/src/components/ui/group.tsx
@@ -0,0 +1,93 @@
+"use client";
+
+import { mergeProps } from "@base-ui/react/merge-props";
+import { useRender } from "@base-ui/react/use-render";
+import { cva, type VariantProps } from "class-variance-authority";
+import type * as React from "react";
+
+import { cn } from "~/lib/utils";
+import { Separator } from "./separator";
+
+const groupVariants = cva(
+ "flex w-fit *:focus-visible:z-1 has-[>[data-slot=group]]:gap-2 *:has-focus-visible:z-1 dark:*:[[data-slot=button]:hover~[data-slot=separator]:not([data-slot]:hover~[data-slot=separator]~[data-slot=separator]),[data-slot][data-pressed]~[data-slot=separator]:not([data-slot][data-pressed]~[data-slot=separator]~[data-slot=separator])]:before:bg-input/64 dark:*:[[data-slot=separator]:has(~[data-slot=button]:hover):not(:has(~[data-slot=separator]~[data-slot]:hover)),[data-slot=separator]:has(~[data-slot][data-pressed]):not(:has(~[data-slot=separator]~[data-slot][data-pressed]))]:before:bg-input/64",
+ {
+ defaultVariants: {
+ orientation: "horizontal",
+ },
+ variants: {
+ orientation: {
+ horizontal:
+ "*:[[data-slot]~[data-slot]:not([data-slot=separator])]:before:-start-[0.5px] *:data-slot:not-data-[slot=separator]:has-[~[data-slot]]:before:-end-[0.5px] *:pointer-coarse:after:min-w-auto *:data-slot:has-[~[data-slot]]:rounded-e-none *:data-slot:has-[~[data-slot]]:border-e-0 *:data-slot:has-[~[data-slot]]:before:rounded-e-none *:[[data-slot]~[data-slot]]:rounded-s-none *:[[data-slot]~[data-slot]]:border-s-0 *:[[data-slot]~[data-slot]]:before:rounded-s-none",
+ vertical:
+ "*:[[data-slot]~[data-slot]:not([data-slot=separator])]:before:-top-[0.5px] *:data-slot:not-data-[slot=separator]:has-[~[data-slot]]:before:-bottom-[0.5px] flex-col *:pointer-coarse:after:min-h-auto *:data-slot:has-[~[data-slot]]:rounded-b-none *:data-slot:has-[~[data-slot]]:border-b-0 *:data-slot:not-data-[slot=separator]:has-[~[data-slot]]:before:hidden *:data-slot:has-[~[data-slot]]:before:rounded-b-none dark:*:last:before:hidden dark:*:first:before:block *:[[data-slot]~[data-slot]]:rounded-t-none *:[[data-slot]~[data-slot]]:border-t-0 *:[[data-slot]~[data-slot]]:before:rounded-t-none",
+ },
+ },
+ },
+);
+
+function Group({
+ className,
+ orientation,
+ children,
+ ...props
+}: {
+ className?: string;
+ orientation?: VariantProps
["orientation"];
+ children: React.ReactNode;
+} & React.ComponentProps<"div">) {
+ return (
+
+ {children}
+
+ );
+}
+
+function GroupText({ className, render, ...props }: useRender.ComponentProps<"div">) {
+ const defaultProps = {
+ className: cn(
+ "relative inline-flex items-center whitespace-nowrap gap-2 rounded-lg border border-input bg-muted not-dark:bg-clip-padding px-[calc(--spacing(3)-1px)] text-muted-foreground text-base sm:text-sm shadow-xs/5 outline-none transition-shadow before:pointer-events-none before:absolute before:inset-0 before:rounded-[calc(var(--radius-lg)-1px)] before:shadow-[0_1px_--theme(--color-black/6%)] dark:bg-input/64 dark:before:shadow-[0_-1px_--theme(--color-white/6%)] [&_svg:not([class*='size-'])]:size-4.5 sm:[&_svg:not([class*='size-'])]:size-4 [&_svg]:shrink-0 [&_svg]:-mx-0.5",
+ className,
+ ),
+ "data-slot": "group-text",
+ };
+ return useRender({
+ defaultTagName: "div",
+ props: mergeProps(defaultProps, props),
+ render,
+ });
+}
+
+function GroupSeparator({
+ className,
+ orientation = "vertical",
+ ...props
+}: {
+ className?: string;
+} & React.ComponentProps) {
+ return (
+
+ );
+}
+
+export {
+ Group,
+ Group as ButtonGroup,
+ GroupText,
+ GroupText as ButtonGroupText,
+ GroupSeparator,
+ GroupSeparator as ButtonGroupSeparator,
+ groupVariants,
+};
diff --git a/apps/web/src/components/ui/input-group.tsx b/apps/web/src/components/ui/input-group.tsx
new file mode 100644
index 0000000000000000000000000000000000000000..b6e142c7014222a658e60e37bc89a1078a4356a2
--- /dev/null
+++ b/apps/web/src/components/ui/input-group.tsx
@@ -0,0 +1,101 @@
+"use client";
+
+import { cva, type VariantProps } from "class-variance-authority";
+import type * as React from "react";
+
+import { cn } from "~/lib/utils";
+import { Input, type InputProps } from "~/components/ui/input";
+import { Textarea, type TextareaProps } from "~/components/ui/textarea";
+
+function InputGroup({ className, ...props }: React.ComponentProps<"div">) {
+ return (
+
+ );
+}
+
+const inputGroupAddonVariants = cva(
+ "[&_svg]:-mx-0.5 flex h-auto cursor-text select-none items-center justify-center gap-2 leading-none [&>kbd]:rounded-[calc(var(--radius)-5px)] in-[[data-slot=input-group]:has([data-slot=input-control],[data-slot=textarea-control])]:[&_svg:not([class*='size-'])]:size-4.5 sm:in-[[data-slot=input-group]:has([data-slot=input-control],[data-slot=textarea-control])]:[&_svg:not([class*='size-'])]:size-4 not-has-[button]:**:[svg:not([class*='opacity-'])]:opacity-80",
+ {
+ defaultVariants: {
+ align: "inline-start",
+ },
+ variants: {
+ align: {
+ "block-end":
+ "order-last w-full justify-start px-[calc(--spacing(3)-1px)] pb-[calc(--spacing(3)-1px)] [.border-t]:pt-[calc(--spacing(3)-1px)] [[data-size=sm]+&]:px-[calc(--spacing(2.5)-1px)]",
+ "block-start":
+ "order-first w-full justify-start px-[calc(--spacing(3)-1px)] pt-[calc(--spacing(3)-1px)] [.border-b]:pb-[calc(--spacing(3)-1px)] [[data-size=sm]+&]:px-[calc(--spacing(2.5)-1px)]",
+ "inline-end":
+ "has-[>:last-child[data-slot=badge]]:-me-1.5 has-[>button]:-me-2 order-last pe-[calc(--spacing(3)-1px)] has-[>kbd:last-child]:me-[-0.35rem] [[data-size=sm]+&]:pe-[calc(--spacing(2.5)-1px)]",
+ "inline-start":
+ "has-[>:last-child[data-slot=badge]]:-ms-1.5 has-[>button]:-ms-2 order-first ps-[calc(--spacing(3)-1px)] has-[>kbd:last-child]:ms-[-0.35rem] [[data-size=sm]+&]:ps-[calc(--spacing(2.5)-1px)]",
+ },
+ },
+ },
+);
+
+function InputGroupAddon({
+ className,
+ align = "inline-start",
+ ...props
+}: React.ComponentProps<"div"> & VariantProps) {
+ return (
+ {
+ const target = e.target as HTMLElement;
+ const isInteractive = target.closest(
+ "button, a, input, select, textarea, [role='button'], [role='combobox'], [role='listbox'], [data-slot='select-trigger']",
+ );
+ if (isInteractive) return;
+ e.preventDefault();
+ const parent = e.currentTarget.parentElement;
+ const input = parent?.querySelector<
+ HTMLInputElement | HTMLTextAreaElement
+ >("input, textarea");
+ if (input && !parent?.querySelector("input:focus, textarea:focus")) {
+ input.focus();
+ }
+ }}
+ {...props}
+ />
+ );
+}
+
+function InputGroupText({ className, ...props }: React.ComponentProps<"span">) {
+ return (
+
+ );
+}
+
+function InputGroupInput({ className, ...props }: InputProps) {
+ return
;
+}
+
+function InputGroupTextarea({ className, ...props }: TextareaProps) {
+ return
;
+}
+
+export {
+ InputGroup,
+ InputGroupAddon,
+ InputGroupText,
+ InputGroupInput,
+ InputGroupTextarea,
+};
diff --git a/apps/web/src/components/ui/input.tsx b/apps/web/src/components/ui/input.tsx
new file mode 100644
index 0000000000000000000000000000000000000000..a137f39a557832851b425b01164e9a9b401a1a73
--- /dev/null
+++ b/apps/web/src/components/ui/input.tsx
@@ -0,0 +1,66 @@
+"use client";
+
+import { Input as InputPrimitive } from "@base-ui/react/input";
+import type * as React from "react";
+
+import { cn } from "~/lib/utils";
+
+type InputProps = Omit<
+ InputPrimitive.Props & React.RefAttributes
,
+ "size"
+> & {
+ size?: "sm" | "default" | "lg" | number;
+ unstyled?: boolean;
+ nativeInput?: boolean;
+};
+
+function Input({
+ className,
+ size = "default",
+ unstyled = false,
+ nativeInput = false,
+ ...props
+}: InputProps) {
+ const inputClassName = cn(
+ "h-8.5 w-full min-w-0 rounded-[inherit] px-[calc(--spacing(3)-1px)] leading-8.5 outline-none placeholder:text-muted-foreground/72 sm:h-7.5 sm:leading-7.5 [transition:background-color_5000000s_ease-in-out_0s]",
+ size === "sm" &&
+ "h-7.5 px-[calc(--spacing(2.5)-1px)] leading-7.5 sm:h-6.5 sm:leading-6.5",
+ size === "lg" && "h-9.5 leading-9.5 sm:h-8.5 sm:leading-8.5",
+ props.type === "search" &&
+ "[&::-webkit-search-cancel-button]:appearance-none [&::-webkit-search-decoration]:appearance-none [&::-webkit-search-results-button]:appearance-none [&::-webkit-search-results-decoration]:appearance-none",
+ props.type === "file" &&
+ "text-muted-foreground file:me-3 file:bg-transparent file:font-medium file:text-foreground file:text-sm",
+ );
+
+ return (
+
+ {nativeInput ? (
+
+ ) : (
+
+ )}
+
+ );
+}
+
+export { Input, type InputProps };
diff --git a/apps/web/src/components/ui/kbd.tsx b/apps/web/src/components/ui/kbd.tsx
new file mode 100644
index 0000000000000000000000000000000000000000..04a23f2b6cb36d5265095e39a0b4e762b3a70df7
--- /dev/null
+++ b/apps/web/src/components/ui/kbd.tsx
@@ -0,0 +1,28 @@
+import type * as React from "react";
+
+import { cn } from "~/lib/utils";
+
+function Kbd({ className, ...props }: React.ComponentProps<"kbd">) {
+ return (
+
+ );
+}
+
+function KbdGroup({ className, ...props }: React.ComponentProps<"kbd">) {
+ return (
+
+ );
+}
+
+export { Kbd, KbdGroup };
diff --git a/apps/web/src/components/ui/label.tsx b/apps/web/src/components/ui/label.tsx
new file mode 100644
index 0000000000000000000000000000000000000000..ff8ded33c1d8ee7e741ce704ed36fed9033f81b5
--- /dev/null
+++ b/apps/web/src/components/ui/label.tsx
@@ -0,0 +1,28 @@
+"use client";
+
+import { mergeProps } from "@base-ui/react/merge-props";
+import { useRender } from "@base-ui/react/use-render";
+
+import { cn } from "~/lib/utils";
+
+function Label({
+ className,
+ render,
+ ...props
+}: useRender.ComponentProps<"label">) {
+ const defaultProps = {
+ className: cn(
+ "inline-flex items-center gap-2 text-base/4.5 sm:text-sm/4 font-medium text-foreground",
+ className,
+ ),
+ "data-slot": "label",
+ };
+
+ return useRender({
+ defaultTagName: "label",
+ props: mergeProps<"label">(defaultProps, props),
+ render,
+ });
+}
+
+export { Label };
diff --git a/apps/web/src/components/ui/menu.tsx b/apps/web/src/components/ui/menu.tsx
new file mode 100644
index 0000000000000000000000000000000000000000..b5c055e81367f49301661ac6d1172fc766405f69
--- /dev/null
+++ b/apps/web/src/components/ui/menu.tsx
@@ -0,0 +1,326 @@
+"use client";
+
+import { Menu as MenuPrimitive } from "@base-ui/react/menu";
+import { ChevronRightIcon } from "lucide-react";
+import type * as React from "react";
+
+import { cn } from "~/lib/utils";
+
+const MenuCreateHandle = MenuPrimitive.createHandle;
+
+const Menu = MenuPrimitive.Root;
+
+const MenuPortal = MenuPrimitive.Portal;
+
+function MenuTrigger({
+ className,
+ children,
+ ...props
+}: MenuPrimitive.Trigger.Props) {
+ return (
+
+ {children}
+
+ );
+}
+
+function MenuPopup({
+ children,
+ className,
+ sideOffset = 4,
+ align = "center",
+ alignOffset,
+ side = "bottom",
+ anchor,
+ ...props
+}: MenuPrimitive.Popup.Props & {
+ align?: MenuPrimitive.Positioner.Props["align"];
+ sideOffset?: MenuPrimitive.Positioner.Props["sideOffset"];
+ alignOffset?: MenuPrimitive.Positioner.Props["alignOffset"];
+ side?: MenuPrimitive.Positioner.Props["side"];
+ anchor?: MenuPrimitive.Positioner.Props["anchor"];
+}) {
+ return (
+
+
+
+
+ {children}
+
+
+
+
+ );
+}
+
+function MenuGroup(props: MenuPrimitive.Group.Props) {
+ return ;
+}
+
+function MenuItem({
+ className,
+ inset,
+ variant = "default",
+ ...props
+}: MenuPrimitive.Item.Props & {
+ inset?: boolean;
+ variant?: "default" | "destructive";
+}) {
+ return (
+ svg]:-mx-0.5 flex min-h-8 cursor-default select-none items-center gap-2 rounded-sm px-2 py-1 text-base text-foreground outline-none data-disabled:pointer-events-none data-highlighted:bg-accent data-inset:ps-8 data-[variant=destructive]:text-destructive-foreground data-highlighted:text-accent-foreground data-disabled:opacity-64 sm:min-h-7 sm:text-sm [&>svg:not([class*='opacity-'])]:opacity-80 [&>svg:not([class*='size-'])]:size-4.5 sm:[&>svg:not([class*='size-'])]:size-4 [&>svg]:pointer-events-none [&>svg]:shrink-0",
+ className,
+ )}
+ data-inset={inset}
+ data-slot="menu-item"
+ data-variant={variant}
+ {...props}
+ />
+ );
+}
+
+function MenuCheckboxItem({
+ className,
+ children,
+ checked,
+ variant = "default",
+ ...props
+}: MenuPrimitive.CheckboxItem.Props & {
+ variant?: "default" | "switch";
+}) {
+ return (
+
+ {variant === "switch" ? (
+ <>
+ {children}
+
+
+
+ >
+ ) : (
+ <>
+
+
+
+ {children}
+ >
+ )}
+
+ );
+}
+
+function MenuRadioGroup(props: MenuPrimitive.RadioGroup.Props) {
+ return ;
+}
+
+function MenuRadioItem({
+ className,
+ children,
+ ...props
+}: MenuPrimitive.RadioItem.Props) {
+ return (
+
+
+
+
+ {children}
+
+ );
+}
+
+function MenuGroupLabel({
+ className,
+ inset,
+ ...props
+}: MenuPrimitive.GroupLabel.Props & {
+ inset?: boolean;
+}) {
+ return (
+
+ );
+}
+
+function MenuSeparator({ className, ...props }: MenuPrimitive.Separator.Props) {
+ return (
+
+ );
+}
+
+function MenuShortcut({ className, ...props }: React.ComponentProps<"kbd">) {
+ return (
+
+ );
+}
+
+function MenuSub(props: MenuPrimitive.SubmenuRoot.Props) {
+ return ;
+}
+
+function MenuSubTrigger({
+ className,
+ inset,
+ children,
+ ...props
+}: MenuPrimitive.SubmenuTrigger.Props & {
+ inset?: boolean;
+}) {
+ return (
+
+ {children}
+
+
+ );
+}
+
+function MenuSubPopup({
+ className,
+ sideOffset = 0,
+ alignOffset,
+ align = "start",
+ ...props
+}: MenuPrimitive.Popup.Props & {
+ align?: MenuPrimitive.Positioner.Props["align"];
+ sideOffset?: MenuPrimitive.Positioner.Props["sideOffset"];
+ alignOffset?: MenuPrimitive.Positioner.Props["alignOffset"];
+}) {
+ const defaultAlignOffset = align !== "center" ? -5 : undefined;
+
+ return (
+
+ );
+}
+
+export {
+ MenuCreateHandle,
+ MenuCreateHandle as DropdownMenuCreateHandle,
+ Menu,
+ Menu as DropdownMenu,
+ MenuPortal,
+ MenuPortal as DropdownMenuPortal,
+ MenuTrigger,
+ MenuTrigger as DropdownMenuTrigger,
+ MenuPopup,
+ MenuPopup as DropdownMenuContent,
+ MenuGroup,
+ MenuGroup as DropdownMenuGroup,
+ MenuItem,
+ MenuItem as DropdownMenuItem,
+ MenuCheckboxItem,
+ MenuCheckboxItem as DropdownMenuCheckboxItem,
+ MenuRadioGroup,
+ MenuRadioGroup as DropdownMenuRadioGroup,
+ MenuRadioItem,
+ MenuRadioItem as DropdownMenuRadioItem,
+ MenuGroupLabel,
+ MenuGroupLabel as DropdownMenuLabel,
+ MenuSeparator,
+ MenuSeparator as DropdownMenuSeparator,
+ MenuShortcut,
+ MenuShortcut as DropdownMenuShortcut,
+ MenuSub,
+ MenuSub as DropdownMenuSub,
+ MenuSubTrigger,
+ MenuSubTrigger as DropdownMenuSubTrigger,
+ MenuSubPopup,
+ MenuSubPopup as DropdownMenuSubContent,
+};
diff --git a/apps/web/src/components/ui/popover.tsx b/apps/web/src/components/ui/popover.tsx
new file mode 100644
index 0000000000000000000000000000000000000000..9a4a8a32405c111839784f7e540e0c397efbd148
--- /dev/null
+++ b/apps/web/src/components/ui/popover.tsx
@@ -0,0 +1,119 @@
+"use client";
+
+import { Popover as PopoverPrimitive } from "@base-ui/react/popover";
+
+import { cn } from "~/lib/utils";
+
+const PopoverCreateHandle = PopoverPrimitive.createHandle;
+
+const Popover = PopoverPrimitive.Root;
+
+function PopoverTrigger({
+ className,
+ children,
+ ...props
+}: PopoverPrimitive.Trigger.Props) {
+ return (
+
+ {children}
+
+ );
+}
+
+function PopoverPopup({
+ children,
+ className,
+ side = "bottom",
+ align = "center",
+ sideOffset = 4,
+ alignOffset = 0,
+ tooltipStyle = false,
+ anchor,
+ ...props
+}: PopoverPrimitive.Popup.Props & {
+ side?: PopoverPrimitive.Positioner.Props["side"];
+ align?: PopoverPrimitive.Positioner.Props["align"];
+ sideOffset?: PopoverPrimitive.Positioner.Props["sideOffset"];
+ alignOffset?: PopoverPrimitive.Positioner.Props["alignOffset"];
+ tooltipStyle?: boolean;
+ anchor?: PopoverPrimitive.Positioner.Props["anchor"];
+}) {
+ return (
+
+
+
+
+ {children}
+
+
+
+
+ );
+}
+
+function PopoverClose({ ...props }: PopoverPrimitive.Close.Props) {
+ return ;
+}
+
+function PopoverTitle({ className, ...props }: PopoverPrimitive.Title.Props) {
+ return (
+
+ );
+}
+
+function PopoverDescription({
+ className,
+ ...props
+}: PopoverPrimitive.Description.Props) {
+ return (
+
+ );
+}
+
+export {
+ PopoverCreateHandle,
+ Popover,
+ PopoverTrigger,
+ PopoverPopup,
+ PopoverPopup as PopoverContent,
+ PopoverTitle,
+ PopoverDescription,
+ PopoverClose,
+};
diff --git a/apps/web/src/components/ui/radio-group.tsx b/apps/web/src/components/ui/radio-group.tsx
new file mode 100644
index 0000000000000000000000000000000000000000..025ba7a84feb104e8b60672de40b013a98ece629
--- /dev/null
+++ b/apps/web/src/components/ui/radio-group.tsx
@@ -0,0 +1,36 @@
+"use client";
+
+import { Radio as RadioPrimitive } from "@base-ui/react/radio";
+import { RadioGroup as RadioGroupPrimitive } from "@base-ui/react/radio-group";
+
+import { cn } from "~/lib/utils";
+
+function RadioGroup({ className, ...props }: RadioGroupPrimitive.Props) {
+ return (
+
+ );
+}
+
+function Radio({ className, ...props }: RadioPrimitive.Root.Props) {
+ return (
+
+
+
+ );
+}
+
+export { RadioGroup, Radio, Radio as RadioGroupItem };
diff --git a/apps/web/src/components/ui/scroll-area.tsx b/apps/web/src/components/ui/scroll-area.tsx
new file mode 100644
index 0000000000000000000000000000000000000000..d39b1d1561474249b5554768378ef0aed3f1d928
--- /dev/null
+++ b/apps/web/src/components/ui/scroll-area.tsx
@@ -0,0 +1,64 @@
+"use client";
+
+import { ScrollArea as ScrollAreaPrimitive } from "@base-ui/react/scroll-area";
+
+import { cn } from "~/lib/utils";
+
+function ScrollArea({
+ className,
+ children,
+ scrollFade = false,
+ scrollbarGutter = false,
+ ...props
+}: ScrollAreaPrimitive.Root.Props & {
+ scrollFade?: boolean;
+ scrollbarGutter?: boolean;
+}) {
+ return (
+
+
+ {children}
+
+
+
+
+
+ );
+}
+
+function ScrollBar({
+ className,
+ orientation = "vertical",
+ ...props
+}: ScrollAreaPrimitive.Scrollbar.Props) {
+ return (
+
+
+
+ );
+}
+
+export { ScrollArea, ScrollBar };
diff --git a/apps/web/src/components/ui/select.tsx b/apps/web/src/components/ui/select.tsx
new file mode 100644
index 0000000000000000000000000000000000000000..d3c30ae0e02fe744fdbb79db8a1fb10c106ede06
--- /dev/null
+++ b/apps/web/src/components/ui/select.tsx
@@ -0,0 +1,234 @@
+"use client";
+
+import { mergeProps } from "@base-ui/react/merge-props";
+import { Select as SelectPrimitive } from "@base-ui/react/select";
+import { useRender } from "@base-ui/react/use-render";
+import { cva, type VariantProps } from "class-variance-authority";
+import { ChevronDownIcon, ChevronsUpDownIcon, ChevronUpIcon } from "lucide-react";
+import type * as React from "react";
+
+import { cn } from "~/lib/utils";
+
+const Select = SelectPrimitive.Root;
+
+const selectTriggerVariants = cva(
+ "relative inline-flex select-none items-center justify-between gap-2 border rounded-lg text-left text-base outline-none transition-[color,box-shadow,background-color] data-disabled:pointer-events-none data-disabled:opacity-64 sm:text-sm [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4.5 sm:[&_svg:not([class*='size-'])]:size-4",
+ {
+ defaultVariants: {
+ size: "default",
+ variant: "default",
+ },
+ variants: {
+ variant: {
+ default:
+ "w-full min-w-36 border-input bg-background not-dark:bg-clip-padding text-foreground shadow-xs/5 ring-ring/24 before:pointer-events-none before:absolute before:inset-0 before:rounded-[calc(var(--radius-lg)-1px)] not-data-disabled:not-focus-visible:not-aria-invalid:not-data-pressed:before:shadow-[0_1px_--theme(--color-black/4%)] pointer-coarse:after:absolute pointer-coarse:after:size-full pointer-coarse:after:min-h-11 focus-visible:border-ring focus-visible:ring-[3px] aria-invalid:border-destructive/36 focus-visible:aria-invalid:border-destructive/64 focus-visible:aria-invalid:ring-destructive/16 dark:bg-input/32 dark:aria-invalid:ring-destructive/24 dark:not-data-disabled:not-focus-visible:not-aria-invalid:not-data-pressed:before:shadow-[0_-1px_--theme(--color-white/6%)] [&_svg:not([class*='opacity-'])]:opacity-80 [[data-disabled],:focus-visible,[aria-invalid],[data-pressed]]:shadow-none",
+ ghost:
+ "border-transparent text-muted-foreground/70 focus-visible:ring-2 focus-visible:ring-ring data-pressed:bg-accent [:hover,[data-pressed]]:bg-accent [:hover,[data-pressed]]:text-foreground/80",
+ },
+ size: {
+ default: "min-h-9 px-[calc(--spacing(3)-1px)] sm:min-h-8",
+ lg: "min-h-10 px-[calc(--spacing(3)-1px)] sm:min-h-9",
+ sm: "min-h-8 gap-1.5 px-[calc(--spacing(2.5)-1px)] sm:min-h-7",
+ },
+ },
+ },
+);
+
+const selectTriggerIconClassName = "-me-1 size-4.5 opacity-80 sm:size-4";
+
+interface SelectButtonProps extends useRender.ComponentProps<"button"> {
+ size?: VariantProps["size"];
+ variant?: VariantProps["variant"];
+}
+
+function SelectButton({ className, size, variant, render, children, ...props }: SelectButtonProps) {
+ const typeValue: React.ButtonHTMLAttributes["type"] = render
+ ? undefined
+ : "button";
+
+ const defaultProps = {
+ children: (
+ <>
+
+ {children}
+
+ {variant === "ghost" ? (
+
+ ) : (
+
+ )}
+ >
+ ),
+ className: cn(selectTriggerVariants({ size, variant }), "min-w-none", className),
+ "data-slot": "select-button",
+ type: typeValue,
+ };
+
+ return useRender({
+ defaultTagName: "button",
+ props: mergeProps<"button">(defaultProps, props),
+ render,
+ });
+}
+
+function SelectTrigger({
+ className,
+ size = "default",
+ variant = "default",
+ children,
+ ...props
+}: SelectPrimitive.Trigger.Props & VariantProps) {
+ return (
+
+ {children}
+
+
+
+
+ );
+}
+
+function SelectValue({ className, ...props }: SelectPrimitive.Value.Props) {
+ return (
+
+ );
+}
+
+function SelectPopup({
+ className,
+ children,
+ side = "bottom",
+ sideOffset = 4,
+ align = "start",
+ alignOffset = 0,
+ alignItemWithTrigger = true,
+ anchor,
+ ...props
+}: SelectPrimitive.Popup.Props & {
+ side?: SelectPrimitive.Positioner.Props["side"];
+ sideOffset?: SelectPrimitive.Positioner.Props["sideOffset"];
+ align?: SelectPrimitive.Positioner.Props["align"];
+ alignOffset?: SelectPrimitive.Positioner.Props["alignOffset"];
+ alignItemWithTrigger?: SelectPrimitive.Positioner.Props["alignItemWithTrigger"];
+ anchor?: SelectPrimitive.Positioner.Props["anchor"];
+}) {
+ return (
+
+
+
+
+
+
+
+
+ {children}
+
+
+
+
+
+
+
+
+ );
+}
+
+function SelectItem({ className, children, ...props }: SelectPrimitive.Item.Props) {
+ return (
+
+
+
+
+
+ {children}
+
+
+ );
+}
+
+function SelectSeparator({ className, ...props }: SelectPrimitive.Separator.Props) {
+ return (
+
+ );
+}
+
+function SelectGroup(props: SelectPrimitive.Group.Props) {
+ return ;
+}
+
+function SelectGroupLabel(props: SelectPrimitive.GroupLabel.Props) {
+ return (
+
+ );
+}
+
+export {
+ Select,
+ SelectTrigger,
+ SelectButton,
+ selectTriggerVariants,
+ SelectValue,
+ SelectPopup,
+ SelectPopup as SelectContent,
+ SelectItem,
+ SelectSeparator,
+ SelectGroup,
+ SelectGroupLabel,
+};
diff --git a/apps/web/src/components/ui/separator.tsx b/apps/web/src/components/ui/separator.tsx
new file mode 100644
index 0000000000000000000000000000000000000000..170049a7bda961563dd38e15cf3f687c23206a48
--- /dev/null
+++ b/apps/web/src/components/ui/separator.tsx
@@ -0,0 +1,23 @@
+import { Separator as SeparatorPrimitive } from "@base-ui/react/separator";
+
+import { cn } from "~/lib/utils";
+
+function Separator({
+ className,
+ orientation = "horizontal",
+ ...props
+}: SeparatorPrimitive.Props) {
+ return (
+
+ );
+}
+
+export { Separator };
diff --git a/apps/web/src/components/ui/sheet.tsx b/apps/web/src/components/ui/sheet.tsx
new file mode 100644
index 0000000000000000000000000000000000000000..0b8bafb2a14d6e4ca738d70ccc0ed642c52c710f
--- /dev/null
+++ b/apps/web/src/components/ui/sheet.tsx
@@ -0,0 +1,203 @@
+"use client";
+
+import { Dialog as SheetPrimitive } from "@base-ui/react/dialog";
+import { XIcon } from "lucide-react";
+import { cn } from "~/lib/utils";
+import { Button } from "~/components/ui/button";
+import { ScrollArea } from "~/components/ui/scroll-area";
+
+const Sheet = SheetPrimitive.Root;
+
+const SheetPortal = SheetPrimitive.Portal;
+
+function SheetTrigger(props: SheetPrimitive.Trigger.Props) {
+ return ;
+}
+
+function SheetClose(props: SheetPrimitive.Close.Props) {
+ return ;
+}
+
+function SheetBackdrop({ className, ...props }: SheetPrimitive.Backdrop.Props) {
+ return (
+
+ );
+}
+
+function SheetViewport({
+ className,
+ side,
+ variant = "default",
+ ...props
+}: SheetPrimitive.Viewport.Props & {
+ side?: "right" | "left" | "top" | "bottom";
+ variant?: "default" | "inset";
+}) {
+ return (
+
+ );
+}
+
+function SheetPopup({
+ className,
+ children,
+ showCloseButton = true,
+ side = "right",
+ variant = "default",
+ ...props
+}: SheetPrimitive.Popup.Props & {
+ showCloseButton?: boolean;
+ side?: "right" | "left" | "top" | "bottom";
+ variant?: "default" | "inset";
+}) {
+ return (
+
+
+
+
+ {children}
+ {showCloseButton && (
+ }
+ >
+
+
+ )}
+
+
+
+ );
+}
+
+function SheetHeader({ className, ...props }: React.ComponentProps<"div">) {
+ return (
+
+ );
+}
+
+function SheetFooter({
+ className,
+ variant = "default",
+ ...props
+}: React.ComponentProps<"div"> & {
+ variant?: "default" | "bare";
+}) {
+ return (
+
+ );
+}
+
+function SheetTitle({ className, ...props }: SheetPrimitive.Title.Props) {
+ return (
+
+ );
+}
+
+function SheetDescription({
+ className,
+ ...props
+}: SheetPrimitive.Description.Props) {
+ return (
+
+ );
+}
+
+function SheetPanel({
+ className,
+ scrollFade = true,
+ ...props
+}: React.ComponentProps<"div"> & { scrollFade?: boolean }) {
+ return (
+
+
+
+ );
+}
+
+export {
+ Sheet,
+ SheetTrigger,
+ SheetPortal,
+ SheetClose,
+ SheetBackdrop,
+ SheetBackdrop as SheetOverlay,
+ SheetPopup,
+ SheetPopup as SheetContent,
+ SheetHeader,
+ SheetFooter,
+ SheetTitle,
+ SheetDescription,
+ SheetPanel,
+};
diff --git a/apps/web/src/components/ui/skeleton.tsx b/apps/web/src/components/ui/skeleton.tsx
new file mode 100644
index 0000000000000000000000000000000000000000..b1e481784196f61860ec58eed1986d03221058df
--- /dev/null
+++ b/apps/web/src/components/ui/skeleton.tsx
@@ -0,0 +1,16 @@
+import { cn } from "~/lib/utils";
+
+function Skeleton({ className, ...props }: React.ComponentProps<"div">) {
+ return (
+
+ );
+}
+
+export { Skeleton };
diff --git a/apps/web/src/components/ui/spinner.tsx b/apps/web/src/components/ui/spinner.tsx
new file mode 100644
index 0000000000000000000000000000000000000000..a4e863f15e9d286d9568244b0b3b5d17473243ce
--- /dev/null
+++ b/apps/web/src/components/ui/spinner.tsx
@@ -0,0 +1,18 @@
+import { Loader2Icon } from "lucide-react";
+import { cn } from "~/lib/utils";
+
+function Spinner({
+ className,
+ ...props
+}: React.ComponentProps) {
+ return (
+
+ );
+}
+
+export { Spinner };
diff --git a/apps/web/src/components/ui/switch.tsx b/apps/web/src/components/ui/switch.tsx
new file mode 100644
index 0000000000000000000000000000000000000000..135e0fc30f727ca051a567a20cc394558f975614
--- /dev/null
+++ b/apps/web/src/components/ui/switch.tsx
@@ -0,0 +1,27 @@
+"use client";
+
+import { Switch as SwitchPrimitive } from "@base-ui/react/switch";
+
+import { cn } from "~/lib/utils";
+
+function Switch({ className, ...props }: SwitchPrimitive.Root.Props) {
+ return (
+
+
+
+ );
+}
+
+export { Switch };
diff --git a/apps/web/src/components/ui/textarea.tsx b/apps/web/src/components/ui/textarea.tsx
new file mode 100644
index 0000000000000000000000000000000000000000..f9911e51e4e04433ee2399203993f4964d09eccd
--- /dev/null
+++ b/apps/web/src/components/ui/textarea.tsx
@@ -0,0 +1,51 @@
+"use client";
+
+import { Field as FieldPrimitive } from "@base-ui/react/field";
+import { mergeProps } from "@base-ui/react/merge-props";
+import type * as React from "react";
+
+import { cn } from "~/lib/utils";
+
+type TextareaProps = React.ComponentProps<"textarea"> & {
+ size?: "sm" | "default" | "lg" | number;
+ unstyled?: boolean;
+};
+
+function Textarea({
+ className,
+ size = "default",
+ unstyled = false,
+ ...props
+}: TextareaProps) {
+ return (
+
+ (
+
+ )}
+ />
+
+ );
+}
+
+export { Textarea, type TextareaProps };
diff --git a/apps/web/src/components/ui/toast.tsx b/apps/web/src/components/ui/toast.tsx
new file mode 100644
index 0000000000000000000000000000000000000000..7485f6057e361f8e9f2dc033a7ec0c633f6f5140
--- /dev/null
+++ b/apps/web/src/components/ui/toast.tsx
@@ -0,0 +1,269 @@
+"use client";
+
+import { Toast } from "@base-ui/react/toast";
+import {
+ CircleAlertIcon,
+ CircleCheckIcon,
+ InfoIcon,
+ LoaderCircleIcon,
+ TriangleAlertIcon,
+} from "lucide-react";
+
+import { cn } from "~/lib/utils";
+import { buttonVariants } from "~/components/ui/button";
+
+const toastManager = Toast.createToastManager();
+const anchoredToastManager = Toast.createToastManager();
+
+const TOAST_ICONS = {
+ error: CircleAlertIcon,
+ info: InfoIcon,
+ loading: LoaderCircleIcon,
+ success: CircleCheckIcon,
+ warning: TriangleAlertIcon,
+} as const;
+
+type ToastPosition =
+ | "top-left"
+ | "top-center"
+ | "top-right"
+ | "bottom-left"
+ | "bottom-center"
+ | "bottom-right";
+
+interface ToastProviderProps extends Toast.Provider.Props {
+ position?: ToastPosition;
+}
+
+function ToastProvider({
+ children,
+ position = "bottom-right",
+ ...props
+}: ToastProviderProps) {
+ return (
+
+ {children}
+
+
+ );
+}
+
+function Toasts({ position = "bottom-right" }: { position: ToastPosition }) {
+ const { toasts } = Toast.useToastManager();
+ const isTop = position.startsWith("top");
+
+ return (
+
+
+ {toasts.map((toast) => {
+ const Icon = toast.type
+ ? TOAST_ICONS[toast.type as keyof typeof TOAST_ICONS]
+ : null;
+
+ return (
+
+
+
+ {Icon && (
+
+
+
+ )}
+
+
+
+
+
+
+ {toast.actionProps && (
+
+ {toast.actionProps.children}
+
+ )}
+
+
+ );
+ })}
+
+
+ );
+}
+
+function AnchoredToastProvider({ children, ...props }: Toast.Provider.Props) {
+ return (
+
+ {children}
+
+
+ );
+}
+
+function AnchoredToasts() {
+ const { toasts } = Toast.useToastManager();
+
+ return (
+
+
+ {toasts.map((toast) => {
+ const Icon = toast.type
+ ? TOAST_ICONS[toast.type as keyof typeof TOAST_ICONS]
+ : null;
+ const tooltipStyle =
+ (toast.data as { tooltipStyle?: boolean })?.tooltipStyle ?? false;
+ const positionerProps = toast.positionerProps;
+
+ if (!positionerProps?.anchor) {
+ return null;
+ }
+
+ return (
+
+
+ {tooltipStyle ? (
+
+
+
+ ) : (
+
+
+ {Icon && (
+
+
+
+ )}
+
+
+
+
+
+
+ {toast.actionProps && (
+
+ {toast.actionProps.children}
+
+ )}
+
+ )}
+
+
+ );
+ })}
+
+
+ );
+}
+
+export {
+ ToastProvider,
+ type ToastPosition,
+ toastManager,
+ AnchoredToastProvider,
+ anchoredToastManager,
+};
diff --git a/apps/web/src/index.css b/apps/web/src/index.css
index 4cec18a7f77d40df4dbae0ef57e3512d614f354c..d914e63362b742147c2f5a683f68583cde986e1d 100644
--- a/apps/web/src/index.css
+++ b/apps/web/src/index.css
@@ -11,19 +11,6 @@
--color-info-foreground: var(--info-foreground);
--color-info: var(--info);
--color-destructive-foreground: var(--destructive-foreground);
- --color-sidebar-ring: var(--sidebar-ring);
- --color-sidebar-border: var(--sidebar-border);
- --color-sidebar-accent-foreground: var(--sidebar-accent-foreground);
- --color-sidebar-accent: var(--sidebar-accent);
- --color-sidebar-primary-foreground: var(--sidebar-primary-foreground);
- --color-sidebar-primary: var(--sidebar-primary);
- --color-sidebar-foreground: var(--sidebar-foreground);
- --color-sidebar: var(--sidebar);
- --color-chart-5: var(--chart-5);
- --color-chart-4: var(--chart-4);
- --color-chart-3: var(--chart-3);
- --color-chart-2: var(--chart-2);
- --color-chart-1: var(--chart-1);
--color-ring: var(--ring);
--color-input: var(--input);
--color-border: var(--border);
@@ -61,7 +48,7 @@
@apply border-border outline-ring/50;
}
body {
- @apply bg-background text-foreground;
+ @apply bg-background text-foreground relative;
}
}
@@ -89,25 +76,12 @@
--secondary-foreground: var(--color-neutral-800);
--muted: --alpha(var(--color-black) / 4%);
--muted-foreground: color-mix(in srgb, var(--color-neutral-500) 90%, var(--color-black));
- --accent: --alpha(var(--color-black) / 5%);
+ --accent: --alpha(var(--color-black) / 4%);
--accent-foreground: var(--color-neutral-800);
--destructive: var(--color-red-500);
--border: --alpha(var(--color-black) / 8%);
--input: --alpha(var(--color-black) / 10%);
--ring: oklch(0.488 0.217 264);
- --chart-1: oklch(0.646 0.222 41.116);
- --chart-2: oklch(0.6 0.118 184.704);
- --chart-3: oklch(0.398 0.07 227.392);
- --chart-4: oklch(0.828 0.189 84.429);
- --chart-5: oklch(0.769 0.188 70.08);
- --sidebar: oklch(0.985 0 0);
- --sidebar-foreground: oklch(0.141 0.005 285.823);
- --sidebar-primary: oklch(0.21 0.006 285.885);
- --sidebar-primary-foreground: oklch(0.985 0 0);
- --sidebar-accent: oklch(0.967 0.001 286.375);
- --sidebar-accent-foreground: oklch(0.21 0.006 285.885);
- --sidebar-border: oklch(0.92 0.004 286.32);
- --sidebar-ring: oklch(0.705 0.015 286.067);
--destructive-foreground: var(--color-red-700);
--info: var(--color-blue-500);
--info-foreground: var(--color-blue-700);
@@ -136,19 +110,6 @@
--border: --alpha(var(--color-white) / 6%);
--input: --alpha(var(--color-white) / 8%);
--ring: oklch(0.588 0.217 264);
- --chart-1: oklch(0.488 0.243 264.376);
- --chart-2: oklch(0.696 0.17 162.48);
- --chart-3: oklch(0.769 0.188 70.08);
- --chart-4: oklch(0.627 0.265 303.9);
- --chart-5: oklch(0.645 0.246 16.439);
- --sidebar: oklch(0.21 0.006 285.885);
- --sidebar-foreground: oklch(0.985 0 0);
- --sidebar-primary: oklch(0.488 0.243 264.376);
- --sidebar-primary-foreground: oklch(0.985 0 0);
- --sidebar-accent: oklch(0.274 0.006 286.033);
- --sidebar-accent-foreground: oklch(0.985 0 0);
- --sidebar-border: oklch(1 0 0 / 10%);
- --sidebar-ring: oklch(0.552 0.016 285.938);
--destructive-foreground: var(--color-red-400);
--info: var(--color-blue-500);
--info-foreground: var(--color-blue-400);
diff --git a/apps/web/src/lib/utils.ts b/apps/web/src/lib/utils.ts
new file mode 100644
index 0000000000000000000000000000000000000000..365058cebd7d2bdb327ca1c081b16e4937e11050
--- /dev/null
+++ b/apps/web/src/lib/utils.ts
@@ -0,0 +1,6 @@
+import { type ClassValue, clsx } from "clsx";
+import { twMerge } from "tailwind-merge";
+
+export function cn(...inputs: ClassValue[]) {
+ return twMerge(clsx(inputs));
+}
diff --git a/apps/web/src/model-logic.ts b/apps/web/src/model-logic.ts
index 72f615b188d55c5d1728bc0369d29000b502e6e2..df1e8591a6365d9e1124bc76793a9dc5af0cb15d 100644
--- a/apps/web/src/model-logic.ts
+++ b/apps/web/src/model-logic.ts
@@ -6,4 +6,5 @@ export {
} from "@t3tools/contracts";
export const REASONING_OPTIONS = ["xhigh", "high", "medium", "low"] as const;
-export const DEFAULT_REASONING = "high";
+export type ReasoningEffort = (typeof REASONING_OPTIONS)[number];
+export const DEFAULT_REASONING: ReasoningEffort = "high";
diff --git a/apps/web/tsconfig.json b/apps/web/tsconfig.json
index 86307ececcae55ed61c43377c9935faefe54e810..bc4213c0d2046f36c8a62c4d7c045fbfea9ab0dd 100644
--- a/apps/web/tsconfig.json
+++ b/apps/web/tsconfig.json
@@ -4,7 +4,10 @@
"composite": true,
"jsx": "react-jsx",
"lib": ["ES2023", "DOM", "DOM.Iterable"],
- "types": ["vite/client"]
+ "types": ["vite/client"],
+ "paths": {
+ "~/*": ["./src/*"]
+ }
},
"include": ["src", "vite.config.ts"]
}
diff --git a/apps/web/vite.config.ts b/apps/web/vite.config.ts
index 34f6a3f6312f88b63e65b76776fdcd3014af7484..5c548b5067c9863b702a35b21ce5f09d6eb6481d 100644
--- a/apps/web/vite.config.ts
+++ b/apps/web/vite.config.ts
@@ -17,6 +17,12 @@ export default defineConfig({
// In dev mode, tell the web app where the WebSocket server lives
"import.meta.env.VITE_WS_URL": JSON.stringify(process.env.VITE_WS_URL ?? ""),
},
+ experimental: {
+ enableNativePlugin: true,
+ },
+ resolve: {
+ tsconfigPaths: true,
+ },
server: {
port,
strictPort: true,
diff --git a/bun.lock b/bun.lock
index cb95146c29fe84cc7d7ef0052d3cdc64c616dbb1..070abdca67845430f7fe783de465385a043ba9e5 100644
--- a/bun.lock
+++ b/bun.lock
@@ -51,17 +51,20 @@
"name": "@t3tools/web",
"version": "0.0.0",
"dependencies": {
+ "@base-ui/react": "^1.2.0",
"@t3tools/contracts": "workspace:*",
"@tanstack/react-query": "^5.90.0",
"@xterm/addon-fit": "^0.11.0",
"@xterm/xterm": "^6.0.0",
+ "class-variance-authority": "^0.7.1",
"highlight.js": "^11.11.1",
- "lucide-react": "^0.563.0",
+ "lucide-react": "^0.564.0",
"react": "^19.0.0",
"react-dom": "^19.0.0",
"react-markdown": "^10.1.0",
"rehype-highlight": "^7.0.2",
"remark-gfm": "^4.0.1",
+ "tailwind-merge": "^3.4.0",
"zod": "^3.24.1",
},
"devDependencies": {
@@ -120,12 +123,18 @@
"@babel/plugin-transform-react-jsx-source": ["@babel/plugin-transform-react-jsx-source@7.27.1", "", { "dependencies": { "@babel/helper-plugin-utils": "^7.27.1" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-zbwoTsBruTeKB9hSq73ha66iFeJHuaFkUbwvqElnygoNbj/jHRsSeokowZFN3CZ64IvEqcmmkVe89OPXc7ldAw=="],
+ "@babel/runtime": ["@babel/runtime@7.28.6", "", {}, "sha512-05WQkdpL9COIMz4LjTxGpPNCdlpyimKppYNoJ5Di5EUObifl8t4tuLuUBBZEpoLYOmfvIWrsp9fCl0HoPRVTdA=="],
+
"@babel/template": ["@babel/template@7.28.6", "", { "dependencies": { "@babel/code-frame": "^7.28.6", "@babel/parser": "^7.28.6", "@babel/types": "^7.28.6" } }, "sha512-YA6Ma2KsCdGb+WC6UpBVFJGXL58MDA6oyONbjyF/+5sBgxY/dwkhLogbMT2GXXyU84/IhRw/2D1Os1B/giz+BQ=="],
"@babel/traverse": ["@babel/traverse@7.29.0", "", { "dependencies": { "@babel/code-frame": "^7.29.0", "@babel/generator": "^7.29.0", "@babel/helper-globals": "^7.28.0", "@babel/parser": "^7.29.0", "@babel/template": "^7.28.6", "@babel/types": "^7.29.0", "debug": "^4.3.1" } }, "sha512-4HPiQr0X7+waHfyXPZpWPfWL/J7dcN1mx9gL6WdQVMbPnF3+ZhSMs8tCxN7oHddJE9fhNE7+lxdnlyemKfJRuA=="],
"@babel/types": ["@babel/types@7.29.0", "", { "dependencies": { "@babel/helper-string-parser": "^7.27.1", "@babel/helper-validator-identifier": "^7.28.5" } }, "sha512-LwdZHpScM4Qz8Xw2iKSzS+cfglZzJGvofQICy7W7v4caru4EaAmyUuO6BGrbyQ2mYV11W0U8j5mBhd14dd3B0A=="],
+ "@base-ui/react": ["@base-ui/react@1.2.0", "", { "dependencies": { "@babel/runtime": "^7.28.6", "@base-ui/utils": "0.2.5", "@floating-ui/react-dom": "^2.1.6", "@floating-ui/utils": "^0.2.10", "tabbable": "^6.4.0", "use-sync-external-store": "^1.6.0" }, "peerDependencies": { "@types/react": "^17 || ^18 || ^19", "react": "^17 || ^18 || ^19", "react-dom": "^17 || ^18 || ^19" }, "optionalPeers": ["@types/react"] }, "sha512-O6aEQHcm+QyGTFY28xuwRD3SEJGZOBDpyjN2WvpfWYFVhg+3zfXPysAILqtM0C1kWC82MccOE/v1j+GHXE4qIw=="],
+
+ "@base-ui/utils": ["@base-ui/utils@0.2.5", "", { "dependencies": { "@babel/runtime": "^7.28.6", "@floating-ui/utils": "^0.2.10", "reselect": "^5.1.1", "use-sync-external-store": "^1.6.0" }, "peerDependencies": { "@types/react": "^17 || ^18 || ^19", "react": "^17 || ^18 || ^19", "react-dom": "^17 || ^18 || ^19" }, "optionalPeers": ["@types/react"] }, "sha512-oYC7w0gp76RI5MxprlGLV0wze0SErZaRl3AAkeP3OnNB/UBMb6RqNf6ZSIlxOc9Qp68Ab3C2VOcJQyRs7Xc7Vw=="],
+
"@electron/get": ["@electron/get@2.0.3", "", { "dependencies": { "debug": "^4.1.1", "env-paths": "^2.2.0", "fs-extra": "^8.1.0", "got": "^11.8.5", "progress": "^2.0.3", "semver": "^6.2.0", "sumchecker": "^3.0.1" }, "optionalDependencies": { "global-agent": "^3.0.0" } }, "sha512-Qkzpg2s9GnVV2I2BjRksUi43U5e6+zaQMcjoJy0C+C5oxaKl+fmckGDQFtRpZpZV0NQekuZZ+tGz7EA9TVnQtQ=="],
"@emnapi/core": ["@emnapi/core@1.8.1", "", { "dependencies": { "@emnapi/wasi-threads": "1.1.0", "tslib": "^2.4.0" } }, "sha512-AvT9QFpxK0Zd8J0jopedNm+w/2fIzvtPKPjqyw9jwvBaReTTqPBk9Hixaz7KbjimP+QNz605/XnjFcDAL2pqBg=="],
@@ -186,6 +195,14 @@
"@esbuild/win32-x64": ["@esbuild/win32-x64@0.27.3", "", { "os": "win32", "cpu": "x64" }, "sha512-4uJGhsxuptu3OcpVAzli+/gWusVGwZZHTlS63hh++ehExkVT8SgiEf7/uC/PclrPPkLhZqGgCTjd0VWLo6xMqA=="],
+ "@floating-ui/core": ["@floating-ui/core@1.7.4", "", { "dependencies": { "@floating-ui/utils": "^0.2.10" } }, "sha512-C3HlIdsBxszvm5McXlB8PeOEWfBhcGBTZGkGlWc2U0KFY5IwG5OQEuQ8rq52DZmcHDlPLd+YFBK+cZcytwIFWg=="],
+
+ "@floating-ui/dom": ["@floating-ui/dom@1.7.5", "", { "dependencies": { "@floating-ui/core": "^1.7.4", "@floating-ui/utils": "^0.2.10" } }, "sha512-N0bD2kIPInNHUHehXhMke1rBGs1dwqvC9O9KYMyyjK7iXt7GAhnro7UlcuYcGdS/yYOlq0MAVgrow8IbWJwyqg=="],
+
+ "@floating-ui/react-dom": ["@floating-ui/react-dom@2.1.7", "", { "dependencies": { "@floating-ui/dom": "^1.7.5" }, "peerDependencies": { "react": ">=16.8.0", "react-dom": ">=16.8.0" } }, "sha512-0tLRojf/1Go2JgEVm+3Frg9A3IW8bJgKgdO0BN5RkF//ufuz2joZM63Npau2ff3J6lUVYgDSNzNkR+aH3IVfjg=="],
+
+ "@floating-ui/utils": ["@floating-ui/utils@0.2.10", "", {}, "sha512-aGTxbpbg8/b5JfU1HXSrbH3wXZuLPJcNEcZQFMxLs3oSzgtVu6nFPkbbGGUvBcUjKV2YyB9Wxxabo+HEH9tcRQ=="],
+
"@hapi/address": ["@hapi/address@5.1.1", "", { "dependencies": { "@hapi/hoek": "^11.0.2" } }, "sha512-A+po2d/dVoY7cYajycYI43ZbYMXukuopIsqCjh5QzsBCipDtdofHntljDlpccMjIfTy6UOkg+5KPriwYch2bXA=="],
"@hapi/formula": ["@hapi/formula@3.0.2", "", {}, "sha512-hY5YPNXzw1He7s0iqkRQi+uMGh383CGdyyIGYtB+W5N3KHPXoqychklvHhKCC9M3Xtv0OCs/IHw+r4dcHtBYWw=="],
@@ -198,6 +215,16 @@
"@hapi/topo": ["@hapi/topo@6.0.2", "", { "dependencies": { "@hapi/hoek": "^11.0.2" } }, "sha512-KR3rD5inZbGMrHmgPxsJ9dbi6zEK+C3ZwUwTa+eMwWLz7oijWUTWD2pMSNNYJAU6Qq+65NkxXjqHr/7LM2Xkqg=="],
+ "@inquirer/ansi": ["@inquirer/ansi@1.0.2", "", {}, "sha512-S8qNSZiYzFd0wAcyG5AXCvUHC5Sr7xpZ9wZ2py9XR88jUz8wooStVx5M6dRzczbBWjic9NP7+rY0Xi7qqK/aMQ=="],
+
+ "@inquirer/confirm": ["@inquirer/confirm@5.1.21", "", { "dependencies": { "@inquirer/core": "^10.3.2", "@inquirer/type": "^3.0.10" }, "peerDependencies": { "@types/node": ">=18" }, "optionalPeers": ["@types/node"] }, "sha512-KR8edRkIsUayMXV+o3Gv+q4jlhENF9nMYUZs9PA2HzrXeHI8M5uDag70U7RJn9yyiMZSbtF5/UexBtAVtZGSbQ=="],
+
+ "@inquirer/core": ["@inquirer/core@10.3.2", "", { "dependencies": { "@inquirer/ansi": "^1.0.2", "@inquirer/figures": "^1.0.15", "@inquirer/type": "^3.0.10", "cli-width": "^4.1.0", "mute-stream": "^2.0.0", "signal-exit": "^4.1.0", "wrap-ansi": "^6.2.0", "yoctocolors-cjs": "^2.1.3" }, "peerDependencies": { "@types/node": ">=18" }, "optionalPeers": ["@types/node"] }, "sha512-43RTuEbfP8MbKzedNqBrlhhNKVwoK//vUFNW3Q3vZ88BLcrs4kYpGg+B2mm5p2K/HfygoCxuKwJJiv8PbGmE0A=="],
+
+ "@inquirer/figures": ["@inquirer/figures@1.0.15", "", {}, "sha512-t2IEY+unGHOzAaVM5Xx6DEWKeXlDDcNPeDyUpsRc6CUhBfU3VQOEl+Vssh7VNp1dR8MdUJBWhuObjXCsVpjN5g=="],
+
+ "@inquirer/type": ["@inquirer/type@3.0.10", "", { "peerDependencies": { "@types/node": ">=18" }, "optionalPeers": ["@types/node"] }, "sha512-BvziSRxfz5Ov8ch0z/n3oijRSEcEsHnhggm4xFZe93DHcUCTlutlq9Ox4SVENAfcRD22UQq7T/atg9Wr3k09eA=="],
+
"@jridgewell/gen-mapping": ["@jridgewell/gen-mapping@0.3.13", "", { "dependencies": { "@jridgewell/sourcemap-codec": "^1.5.0", "@jridgewell/trace-mapping": "^0.3.24" } }, "sha512-2kkt/7niJ6MgEPxF0bYdQ6etZaA+fQvDcLKckhy1yIQOzaoKjBBjSj63/aLVjYE3qhRt5dvM+uUyfCg6UKCBbA=="],
"@jridgewell/remapping": ["@jridgewell/remapping@2.3.5", "", { "dependencies": { "@jridgewell/gen-mapping": "^0.3.5", "@jridgewell/trace-mapping": "^0.3.24" } }, "sha512-LI9u/+laYG4Ds1TDKSJW2YPrIlcVYOwi2fUC6xB43lueCjgxV4lffOCZCtYFiH6TNOX+tQKXx97T4IKHbhyHEQ=="],
@@ -208,8 +235,16 @@
"@jridgewell/trace-mapping": ["@jridgewell/trace-mapping@0.3.31", "", { "dependencies": { "@jridgewell/resolve-uri": "^3.1.0", "@jridgewell/sourcemap-codec": "^1.4.14" } }, "sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw=="],
+ "@mswjs/interceptors": ["@mswjs/interceptors@0.41.3", "", { "dependencies": { "@open-draft/deferred-promise": "^2.2.0", "@open-draft/logger": "^0.3.0", "@open-draft/until": "^2.0.0", "is-node-process": "^1.2.0", "outvariant": "^1.4.3", "strict-event-emitter": "^0.5.1" } }, "sha512-cXu86tF4VQVfwz8W1SPbhoRyHJkti6mjH/XJIxp40jhO4j2k1m4KYrEykxqWPkFF3vrK4rgQppBh//AwyGSXPA=="],
+
"@napi-rs/wasm-runtime": ["@napi-rs/wasm-runtime@1.1.1", "", { "dependencies": { "@emnapi/core": "^1.7.1", "@emnapi/runtime": "^1.7.1", "@tybys/wasm-util": "^0.10.1" } }, "sha512-p64ah1M1ld8xjWv3qbvFwHiFVWrq1yFvV4f7w+mzaqiR4IlSgkqhcRdHwsGgomwzBH51sRY4NEowLxnaBjcW/A=="],
+ "@open-draft/deferred-promise": ["@open-draft/deferred-promise@2.2.0", "", {}, "sha512-CecwLWx3rhxVQF6V4bAgPS5t+So2sTbPgAzafKkVizyi7tlwpcFpdFqq+wqF2OwNBmqFuu6tOyouTuxgpMfzmA=="],
+
+ "@open-draft/logger": ["@open-draft/logger@0.3.0", "", { "dependencies": { "is-node-process": "^1.2.0", "outvariant": "^1.4.0" } }, "sha512-X2g45fzhxH238HKO4xbSr7+wBS8Fvw6ixhTDuvLd5mqh6bJJCFAPwU9mPDxbcrRtfxv4u5IHCEH77BmxvXmmxQ=="],
+
+ "@open-draft/until": ["@open-draft/until@2.1.0", "", {}, "sha512-U69T3ItWHvLwGg5eJ0n3I62nWuE6ilHlmz7zM0npLBRvPRd7e6NYmg54vvRtP5mZG7kZqZCFVdsTWo7BPtBujg=="],
+
"@oxc-project/runtime": ["@oxc-project/runtime@0.112.0", "", {}, "sha512-4vYtWXMnXM6EaweCxbJ6bISAhkNHeN33SihvuX3wrpqaSJA4ZEoW35i9mSvE74+GDf1yTeVE+aEHA+WBpjDk/g=="],
"@oxc-project/types": ["@oxc-project/types@0.112.0", "", {}, "sha512-m6RebKHIRsax2iCwVpYW2ErQwa4ywHJrE4sCK3/8JK8ZZAWOKXaRJFl/uP51gaVyyXlaS4+chU1nSCdzYf6QqQ=="],
@@ -436,6 +471,8 @@
"@types/responselike": ["@types/responselike@1.0.3", "", { "dependencies": { "@types/node": "*" } }, "sha512-H/+L+UkTV33uf49PH5pCAUBVPNj2nDBXTN+qS1dOwyyg24l3CcicicCA7ca+HMvJBZcFgl5r8e+RR6elsb4Lyw=="],
+ "@types/statuses": ["@types/statuses@2.0.6", "", {}, "sha512-xMAgYwceFhRA2zY+XbEA7mxYbA093wdiW8Vu6gZPGWy9cmOyU9XesH1tNcEWsKFd5Vzrqx5T3D38PWx1FIIXkA=="],
+
"@types/unist": ["@types/unist@3.0.3", "", {}, "sha512-ko/gIFJRv177XgZsZcBwnqJN5x/Gien8qNOn0D5bQU/zAzVf9Zt3BlcUiLqhV9y4ARk0GbT3tnUiPNgnTXzc/Q=="],
"@types/ws": ["@types/ws@8.18.1", "", { "dependencies": { "@types/node": "*" } }, "sha512-ThVF6DCVhA8kUGy+aazFQ4kXQ7E1Ty7A3ypFOe0IcJV8O/M511G99AW24irKrW56Wt44yG9+ij8FaqoBGkuBXg=="],
@@ -464,6 +501,8 @@
"@xterm/xterm": ["@xterm/xterm@6.0.0", "", {}, "sha512-TQwDdQGtwwDt+2cgKDLn0IRaSxYu1tSUjgKarSDkUM0ZNiSRXFpjxEsvc/Zgc5kq5omJ+V0a8/kIM2WD3sMOYg=="],
+ "ansi-regex": ["ansi-regex@5.0.1", "", {}, "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ=="],
+
"ansi-styles": ["ansi-styles@4.3.0", "", { "dependencies": { "color-convert": "^2.0.1" } }, "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg=="],
"ansis": ["ansis@4.2.0", "", {}, "sha512-HqZ5rWlFjGiV0tDm3UxxgNRqsOTniqoKZu0pIAfh7TZQMGuZK+hH0drySty0si0QXj1ieop4+SkSfPZBPPkHig=="],
@@ -518,8 +557,16 @@
"character-reference-invalid": ["character-reference-invalid@2.0.1", "", {}, "sha512-iBZ4F4wRbyORVsu0jPV7gXkOsGYjGHPmAyv+HiHG8gi5PtC9KI2j1+v8/tlibRvjoWX027ypmG/n0HtO5t7unw=="],
+ "class-variance-authority": ["class-variance-authority@0.7.1", "", { "dependencies": { "clsx": "^2.1.1" } }, "sha512-Ka+9Trutv7G8M6WT6SeiRWz792K5qEqIGEGzXKhAE6xOWAY6pPH8U+9IY3oCMv6kqTmLsv7Xh/2w2RigkePMsg=="],
+
+ "cli-width": ["cli-width@4.1.0", "", {}, "sha512-ouuZd4/dm2Sw5Gmqy6bGyNNNe1qt9RpmxveLSO7KcgsTnU7RXfsw+/bukWGo1abgBiMAic068rclZsO4IWmmxQ=="],
+
+ "cliui": ["cliui@8.0.1", "", { "dependencies": { "string-width": "^4.2.0", "strip-ansi": "^6.0.1", "wrap-ansi": "^7.0.0" } }, "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ=="],
+
"clone-response": ["clone-response@1.0.3", "", { "dependencies": { "mimic-response": "^1.0.0" } }, "sha512-ROoL94jJH2dUVML2Y/5PEDNaSHgeOdSDicUyS7izcF63G6sTc/FTjLub4b8Il9S8S0beOfYt0TaA5qvFK+w0wA=="],
+ "clsx": ["clsx@2.1.1", "", {}, "sha512-eYm0QWBtUrBWZWG0d386OGAw16Z995PiOVo2B7bjWSbHedGl5e0ZWaq65kOGgUSNesEIDkB9ISbTg/JK9dhCZA=="],
+
"color-convert": ["color-convert@2.0.1", "", { "dependencies": { "color-name": "~1.1.4" } }, "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ=="],
"color-name": ["color-name@1.1.4", "", {}, "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA=="],
@@ -530,6 +577,8 @@
"convert-source-map": ["convert-source-map@2.0.0", "", {}, "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg=="],
+ "cookie": ["cookie@1.1.1", "", {}, "sha512-ei8Aos7ja0weRpFzJnEA9UHJ/7XQmqglbRwnf2ATjcB9Wq874VKH9kfjjirM6UhU2/E5fFYadylyhFldcqSidQ=="],
+
"csstype": ["csstype@3.2.3", "", {}, "sha512-z1HGKcYy2xA8AGQfwrn0PAy+PB7X/GSj3UVJW9qKyn43xWa+gl5nXmU4qqLMRzWVLFC8KusUX8T/0kCiOYpAIQ=="],
"debug": ["debug@4.4.3", "", { "dependencies": { "ms": "^2.1.3" } }, "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA=="],
@@ -572,6 +621,8 @@
"electronmon": ["electronmon@2.0.4", "", { "dependencies": { "chalk": "^3.0.0", "import-from": "^3.0.0", "runtime-required": "^1.1.0", "watchboy": "^0.4.3" }, "bin": { "electronmon": "bin/cli.js" } }, "sha512-u6eDrvUbqa+wsnMrhG2vHmo5neL1owLg2e5i1avGWcOb4rHsUf9lSfbs0FvfPsBNpLxxlPO98nrMhAGV+zw/fQ=="],
+ "emoji-regex": ["emoji-regex@8.0.0", "", {}, "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A=="],
+
"empathic": ["empathic@2.0.0", "", {}, "sha512-i6UzDscO/XfAcNYD75CfICkmfLedpyPDdozrLMmQc5ORaQcdMoc21OnlEylMIqI7U8eniKrPMxxtj8k0vhmJhA=="],
"end-of-stream": ["end-of-stream@1.4.5", "", { "dependencies": { "once": "^1.4.0" } }, "sha512-ooEGc6HP26xXq/N+GCGOT0JKCLDGrq2bQUZrQ7gyrJiZANJ/8YDTxTpQBXGMn+WbIQXNVpyWymm7KYVICQnyOg=="],
@@ -626,6 +677,8 @@
"gensync": ["gensync@1.0.0-beta.2", "", {}, "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg=="],
+ "get-caller-file": ["get-caller-file@2.0.5", "", {}, "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg=="],
+
"get-intrinsic": ["get-intrinsic@1.3.0", "", { "dependencies": { "call-bind-apply-helpers": "^1.0.2", "es-define-property": "^1.0.1", "es-errors": "^1.3.0", "es-object-atoms": "^1.1.1", "function-bind": "^1.1.2", "get-proto": "^1.0.1", "gopd": "^1.2.0", "has-symbols": "^1.1.0", "hasown": "^2.0.2", "math-intrinsics": "^1.1.0" } }, "sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ=="],
"get-proto": ["get-proto@1.0.1", "", { "dependencies": { "dunder-proto": "^1.0.1", "es-object-atoms": "^1.0.0" } }, "sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g=="],
@@ -644,6 +697,8 @@
"graceful-fs": ["graceful-fs@4.2.11", "", {}, "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ=="],
+ "graphql": ["graphql@16.12.0", "", {}, "sha512-DKKrynuQRne0PNpEbzuEdHlYOMksHSUI8Zc9Unei5gTsMNA2/vMpoMz/yKba50pejK56qj98qM0SjYxAKi13gQ=="],
+
"has-flag": ["has-flag@4.0.0", "", {}, "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ=="],
"has-property-descriptors": ["has-property-descriptors@1.0.2", "", { "dependencies": { "es-define-property": "^1.0.0" } }, "sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg=="],
@@ -662,6 +717,8 @@
"hast-util-whitespace": ["hast-util-whitespace@3.0.0", "", { "dependencies": { "@types/hast": "^3.0.0" } }, "sha512-88JUN06ipLwsnv+dVn+OIYOvAuvBMy/Qoi6O7mQHxdPXpjy+Cd6xRkWwux7DKO+4sYILtLBRIKgsdpS2gQc7qw=="],
+ "headers-polyfill": ["headers-polyfill@4.0.3", "", {}, "sha512-IScLbePpkvO846sIwOtOTDjutRMWdXdJmXdMvk6gCBHxFO8d+QKOQedyZSxFTTFYRSmlgSTDtXqqq4pcenBXLQ=="],
+
"highlight.js": ["highlight.js@11.11.1", "", {}, "sha512-Xwwo44whKBVCYoliBQwaPvtd/2tYFkRQtXDWj1nackaV2JPXx3L0+Jvd8/qCJ2p+ML0/XVkJ2q+Mr+UVdpJK5w=="],
"hookable": ["hookable@6.0.1", "", {}, "sha512-uKGyY8BuzN/a5gvzvA+3FVWo0+wUjgtfSdnmjtrOVwQCZPHpHDH2WRO3VZSOeluYrHoDCiXFffZXs8Dj1ULWtw=="],
@@ -686,10 +743,14 @@
"is-docker": ["is-docker@3.0.0", "", { "bin": { "is-docker": "cli.js" } }, "sha512-eljcgEDlEns/7AXFosB5K/2nCM4P7FQPkGc/DWLy5rmFEWvZayGrik1d9/QIY5nJ4f9YsVvBkA6kJpHn9rISdQ=="],
+ "is-fullwidth-code-point": ["is-fullwidth-code-point@3.0.0", "", {}, "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg=="],
+
"is-hexadecimal": ["is-hexadecimal@2.0.1", "", {}, "sha512-DgZQp241c8oO6cA1SbTEWiXeoxV42vlcJxgH+B3hi1AiqqKruZR3ZGF8In3fj4+/y/7rHvlOZLZtgJ/4ttYGZg=="],
"is-inside-container": ["is-inside-container@1.0.0", "", { "dependencies": { "is-docker": "^3.0.0" }, "bin": { "is-inside-container": "cli.js" } }, "sha512-KIYLCCJghfHZxqjYBE7rEy0OBuTd5xCHS7tHVgvCLkx7StIoaxwNW3hCALgEUjFfeRk+MG/Qxmp/vtETEF3tRA=="],
+ "is-node-process": ["is-node-process@1.2.0", "", {}, "sha512-Vg4o6/fqPxIjtxgUH5QLJhwZ7gW5diGCVlXpuUfELC62CuxM1iHcRe51f2W1FDy04Ai4KJkagKjx3XaqyfRKXw=="],
+
"is-number": ["is-number@7.0.0", "", {}, "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng=="],
"is-plain-obj": ["is-plain-obj@4.1.0", "", {}, "sha512-+Pgi+vMuUNkJyExiMBt5IlFoMyKnr5zhJ4Uspz58WOhBF5QoIZkFyNHIbBAtHwzVAgk5RtndVNsDRN61/mmDqg=="],
@@ -750,7 +811,7 @@
"lru-cache": ["lru-cache@5.1.1", "", { "dependencies": { "yallist": "^3.0.2" } }, "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w=="],
- "lucide-react": ["lucide-react@0.563.0", "", { "peerDependencies": { "react": "^16.5.1 || ^17.0.0 || ^18.0.0 || ^19.0.0" } }, "sha512-8dXPB2GI4dI8jV4MgUDGBeLdGk8ekfqVZ0BdLcrRzocGgG75ltNEmWS+gE7uokKF/0oSUuczNDT+g9hFJ23FkA=="],
+ "lucide-react": ["lucide-react@0.564.0", "", { "peerDependencies": { "react": "^16.5.1 || ^17.0.0 || ^18.0.0 || ^19.0.0" } }, "sha512-JJ8GVTQqFwuliifD48U6+h7DXEHdkhJ/E87kksGByII3qHxtPciVb8T8woQONHBQgHVOl7rSMrrip3SeVNy7Fg=="],
"magic-string": ["magic-string@0.30.21", "", { "dependencies": { "@jridgewell/sourcemap-codec": "^1.5.5" } }, "sha512-vd2F4YUyEXKGcLHoq+TEyCjxueSeHnFxyyjNp80yg0XV4vUhnDer/lvvlqM/arB5bXQN5K2/3oinyCRyx8T2CQ=="],
@@ -858,6 +919,10 @@
"ms": ["ms@2.1.3", "", {}, "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA=="],
+ "msw": ["msw@2.12.10", "", { "dependencies": { "@inquirer/confirm": "^5.0.0", "@mswjs/interceptors": "^0.41.2", "@open-draft/deferred-promise": "^2.2.0", "@types/statuses": "^2.0.6", "cookie": "^1.0.2", "graphql": "^16.12.0", "headers-polyfill": "^4.0.2", "is-node-process": "^1.2.0", "outvariant": "^1.4.3", "path-to-regexp": "^6.3.0", "picocolors": "^1.1.1", "rettime": "^0.10.1", "statuses": "^2.0.2", "strict-event-emitter": "^0.5.1", "tough-cookie": "^6.0.0", "type-fest": "^5.2.0", "until-async": "^3.0.2", "yargs": "^17.7.2" }, "peerDependencies": { "typescript": ">= 4.8.x" }, "optionalPeers": ["typescript"], "bin": { "msw": "cli/index.js" } }, "sha512-G3VUymSE0/iegFnuipujpwyTM2GuZAKXNeerUSrG2+Eg391wW63xFs5ixWsK9MWzr1AGoSkYGmyAzNgbR3+urw=="],
+
+ "mute-stream": ["mute-stream@2.0.0", "", {}, "sha512-WWdIxpyjEn+FhQJQQv9aQAYlHoNVdzIzUySNV1gHUPDSdZJ3yZn7pAAbQcV7B56Mvu881q9FZV+0Vx2xC44VWA=="],
+
"nanoid": ["nanoid@3.3.11", "", { "bin": { "nanoid": "bin/nanoid.cjs" } }, "sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w=="],
"node-addon-api": ["node-addon-api@7.1.1", "", {}, "sha512-5m3bsyrjFWE1xf7nz7YXdN4udnVtXK6/Yfgn5qnahL6bCkf2yKt4k3nuTKAtT4r3IG8JNR2ncsIMdZuAzJjHQQ=="],
@@ -878,6 +943,8 @@
"open": ["open@10.2.0", "", { "dependencies": { "default-browser": "^5.2.1", "define-lazy-prop": "^3.0.0", "is-inside-container": "^1.0.0", "wsl-utils": "^0.1.0" } }, "sha512-YgBpdJHPyQ2UE5x+hlSXcnejzAvD0b22U2OuAP+8OnlJT+PjWPxtgmGqKKc+RgTM63U9gN0YzrYc71R2WT/hTA=="],
+ "outvariant": ["outvariant@1.4.3", "", {}, "sha512-+Sl2UErvtsoajRDKCE5/dBz4DIvHXQQnAxtQTF04OJxY0+DyZXSo5P5Bb7XYWOh81syohlYL24hbDwxedPUJCA=="],
+
"oxfmt": ["oxfmt@0.28.0", "", { "dependencies": { "tinypool": "2.1.0" }, "optionalDependencies": { "@oxfmt/darwin-arm64": "0.28.0", "@oxfmt/darwin-x64": "0.28.0", "@oxfmt/linux-arm64-gnu": "0.28.0", "@oxfmt/linux-arm64-musl": "0.28.0", "@oxfmt/linux-x64-gnu": "0.28.0", "@oxfmt/linux-x64-musl": "0.28.0", "@oxfmt/win32-arm64": "0.28.0", "@oxfmt/win32-x64": "0.28.0" }, "bin": { "oxfmt": "bin/oxfmt" } }, "sha512-3+hhBqPE6Kp22KfJmnstrZbl+KdOVSEu1V0ABaFIg1rYLtrMgrupx9znnHgHLqKxAVHebjTdiCJDk30CXOt6cw=="],
"oxlint": ["oxlint@1.46.0", "", { "optionalDependencies": { "@oxlint/binding-android-arm-eabi": "1.46.0", "@oxlint/binding-android-arm64": "1.46.0", "@oxlint/binding-darwin-arm64": "1.46.0", "@oxlint/binding-darwin-x64": "1.46.0", "@oxlint/binding-freebsd-x64": "1.46.0", "@oxlint/binding-linux-arm-gnueabihf": "1.46.0", "@oxlint/binding-linux-arm-musleabihf": "1.46.0", "@oxlint/binding-linux-arm64-gnu": "1.46.0", "@oxlint/binding-linux-arm64-musl": "1.46.0", "@oxlint/binding-linux-ppc64-gnu": "1.46.0", "@oxlint/binding-linux-riscv64-gnu": "1.46.0", "@oxlint/binding-linux-riscv64-musl": "1.46.0", "@oxlint/binding-linux-s390x-gnu": "1.46.0", "@oxlint/binding-linux-x64-gnu": "1.46.0", "@oxlint/binding-linux-x64-musl": "1.46.0", "@oxlint/binding-openharmony-arm64": "1.46.0", "@oxlint/binding-win32-arm64-msvc": "1.46.0", "@oxlint/binding-win32-ia32-msvc": "1.46.0", "@oxlint/binding-win32-x64-msvc": "1.46.0" }, "peerDependencies": { "oxlint-tsgolint": ">=0.11.2" }, "optionalPeers": ["oxlint-tsgolint"], "bin": { "oxlint": "bin/oxlint" } }, "sha512-I9h42QDtAVsRwoueJ4PL/7qN5jFzIUXvbO4Z5ddtII92ZCiD7uiS/JW2V4viBSfGLsbZkQp3YEs6Ls4I8q+8tA=="],
@@ -886,6 +953,8 @@
"parse-entities": ["parse-entities@4.0.2", "", { "dependencies": { "@types/unist": "^2.0.0", "character-entities-legacy": "^3.0.0", "character-reference-invalid": "^2.0.0", "decode-named-character-reference": "^1.0.0", "is-alphanumerical": "^2.0.0", "is-decimal": "^2.0.0", "is-hexadecimal": "^2.0.0" } }, "sha512-GG2AQYWoLgL877gQIKeRPGO1xF9+eG1ujIb5soS5gPvLQ1y2o8FL90w2QWNdf9I361Mpp7726c+lj3U0qK1uGw=="],
+ "path-to-regexp": ["path-to-regexp@6.3.0", "", {}, "sha512-Yhpw4T9C6hPpgPeA28us07OJeqZ5EzQTkbfwuhsUg0c237RomFoETJgmp2sa3F/41gfLE6G5cqcYwznmeEeOlQ=="],
+
"pathe": ["pathe@2.0.3", "", {}, "sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w=="],
"pend": ["pend@1.2.0", "", {}, "sha512-F3asv42UuXchdzt+xXqfW1OGlVBe+mxa2mqI0pg5yAHZPvFmY3Y6drSf/GQ1A86WgWEN9Kzh/WrgKa6iGcHXLg=="],
@@ -930,6 +999,10 @@
"remove-trailing-separator": ["remove-trailing-separator@1.1.0", "", {}, "sha512-/hS+Y0u3aOfIETiaiirUFwDBDzmXPvO+jAfKTitUngIPzdKc6Z0LoFjM/CK5PL4C+eKwHohlHAb6H0VFfmmUsw=="],
+ "require-directory": ["require-directory@2.1.1", "", {}, "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q=="],
+
+ "reselect": ["reselect@5.1.1", "", {}, "sha512-K/BG6eIky/SBpzfHZv/dd+9JBFiS4SWV7FIujVyJRux6e45+73RaUHXLmIR1f7WOMaQ0U1km6qwklRQxpJJY0w=="],
+
"resolve-alpn": ["resolve-alpn@1.2.1", "", {}, "sha512-0a1F4l73/ZFZOakJnQ3FvkJ2+gSTQWz/r2KE5OdDY0TxPm5h4GkqkWWfM47T7HsbnOtcJVEF4epCVy6u7Q3K+g=="],
"resolve-from": ["resolve-from@5.0.0", "", {}, "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw=="],
@@ -938,6 +1011,8 @@
"responselike": ["responselike@2.0.1", "", { "dependencies": { "lowercase-keys": "^2.0.0" } }, "sha512-4gl03wn3hj1HP3yzgdI7d3lCkF95F21Pz4BPGvKHinyQzALR5CapwC8yIi0Rh58DEMQ/SguC03wFj2k0M/mHhw=="],
+ "rettime": ["rettime@0.10.1", "", {}, "sha512-uyDrIlUEH37cinabq0AX4QbgV4HbFZ/gqoiunWQ1UqBtRvTTytwhNYjE++pO/MjPTZL5KQCf2bEoJ/BJNVQ5Kw=="],
+
"roarr": ["roarr@2.15.4", "", { "dependencies": { "boolean": "^3.0.1", "detect-node": "^2.0.4", "globalthis": "^1.0.1", "json-stringify-safe": "^5.0.1", "semver-compare": "^1.0.0", "sprintf-js": "^1.1.2" } }, "sha512-CHhPh+UNHD2GTXNYhPWLnU8ONHdI+5DI+4EYIAOaiD63rHeYlZvyh8P+in5999TTSFgUYuKUAjzRI4mdh/p+2A=="],
"rolldown": ["rolldown@1.0.0-rc.3", "", { "dependencies": { "@oxc-project/types": "=0.112.0", "@rolldown/pluginutils": "1.0.0-rc.3" }, "optionalDependencies": { "@rolldown/binding-android-arm64": "1.0.0-rc.3", "@rolldown/binding-darwin-arm64": "1.0.0-rc.3", "@rolldown/binding-darwin-x64": "1.0.0-rc.3", "@rolldown/binding-freebsd-x64": "1.0.0-rc.3", "@rolldown/binding-linux-arm-gnueabihf": "1.0.0-rc.3", "@rolldown/binding-linux-arm64-gnu": "1.0.0-rc.3", "@rolldown/binding-linux-arm64-musl": "1.0.0-rc.3", "@rolldown/binding-linux-x64-gnu": "1.0.0-rc.3", "@rolldown/binding-linux-x64-musl": "1.0.0-rc.3", "@rolldown/binding-openharmony-arm64": "1.0.0-rc.3", "@rolldown/binding-wasm32-wasi": "1.0.0-rc.3", "@rolldown/binding-win32-arm64-msvc": "1.0.0-rc.3", "@rolldown/binding-win32-x64-msvc": "1.0.0-rc.3" }, "bin": { "rolldown": "bin/cli.mjs" } }, "sha512-Po/YZECDOqVXjIXrtC5h++a5NLvKAQNrd9ggrIG3sbDfGO5BqTUsrI6l8zdniKRp3r5Tp/2JTrXqx4GIguFCMw=="],
@@ -962,6 +1037,8 @@
"siginfo": ["siginfo@2.0.0", "", {}, "sha512-ybx0WO1/8bSBLEWXZvEd7gMW3Sn3JFlW3TvX1nREbDLRNQNaeNN8WK0meBwPdAaOI7TtRRRJn/Es1zhrrCHu7g=="],
+ "signal-exit": ["signal-exit@4.1.0", "", {}, "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw=="],
+
"source-map-js": ["source-map-js@1.2.1", "", {}, "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA=="],
"space-separated-tokens": ["space-separated-tokens@2.0.2", "", {}, "sha512-PEGlAwrG8yXGXRjW32fGbg66JAlOAwbObuqVoJpv/mRgoWDQfgH1wDPvtzWyUSNAXBGSk8h755YDbbcEy3SH2Q=="],
@@ -970,10 +1047,18 @@
"stackback": ["stackback@0.0.2", "", {}, "sha512-1XMJE5fQo1jGH6Y/7ebnwPOBEkIEnT4QF32d5R1+VXdXveM0IBMJt8zfaxX1P3QhVwrYe+576+jkANtSS2mBbw=="],
+ "statuses": ["statuses@2.0.2", "", {}, "sha512-DvEy55V3DB7uknRo+4iOGT5fP1slR8wQohVdknigZPMpMstaKJQWhwiYBACJE3Ul2pTnATihhBYnRhZQHGBiRw=="],
+
"std-env": ["std-env@3.10.0", "", {}, "sha512-5GS12FdOZNliM5mAOxFRg7Ir0pWz8MdpYm6AY6VPkGpbA7ZzmbzNcBJQ0GPvvyWgcY7QAhCgf9Uy89I03faLkg=="],
+ "strict-event-emitter": ["strict-event-emitter@0.5.1", "", {}, "sha512-vMgjE/GGEPEFnhFub6pa4FmJBRBVOLpIII2hvCZ8Kzb7K0hlHo7mQv6xYrBvCL2LtAIBwFUK8wvuJgTVSQ5MFQ=="],
+
+ "string-width": ["string-width@4.2.3", "", { "dependencies": { "emoji-regex": "^8.0.0", "is-fullwidth-code-point": "^3.0.0", "strip-ansi": "^6.0.1" } }, "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g=="],
+
"stringify-entities": ["stringify-entities@4.0.4", "", { "dependencies": { "character-entities-html4": "^2.0.0", "character-entities-legacy": "^3.0.0" } }, "sha512-IwfBptatlO+QCJUo19AqvrPNqlVMpW9YEL2LIVY+Rpv2qsjCGxaDLNRgeGsQWJhfItebuJhsGSLjaBbNSQ+ieg=="],
+ "strip-ansi": ["strip-ansi@6.0.1", "", { "dependencies": { "ansi-regex": "^5.0.1" } }, "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A=="],
+
"style-to-js": ["style-to-js@1.1.21", "", { "dependencies": { "style-to-object": "1.0.14" } }, "sha512-RjQetxJrrUJLQPHbLku6U/ocGtzyjbJMP9lCNK7Ag0CNh690nSH8woqWH9u16nMjYBAok+i7JO1NP2pOy8IsPQ=="],
"style-to-object": ["style-to-object@1.0.14", "", { "dependencies": { "inline-style-parser": "0.2.7" } }, "sha512-LIN7rULI0jBscWQYaSswptyderlarFkjQ+t79nzty8tcIAceVomEVlLzH5VP4Cmsv6MtKhs7qaAiwlcp+Mgaxw=="],
@@ -984,6 +1069,12 @@
"t3": ["t3@workspace:apps/server"],
+ "tabbable": ["tabbable@6.4.0", "", {}, "sha512-05PUHKSNE8ou2dwIxTngl4EzcnsCDZGJ/iCLtDflR/SHB/ny14rXc+qU5P4mG9JkusiV7EivzY9Mhm55AzAvCg=="],
+
+ "tagged-tag": ["tagged-tag@1.0.0", "", {}, "sha512-yEFYrVhod+hdNyx7g5Bnkkb0G6si8HJurOoOEgC8B/O0uXLHlaey/65KRv6cuWBNhBgHKAROVpc7QyYqE5gFng=="],
+
+ "tailwind-merge": ["tailwind-merge@3.4.0", "", {}, "sha512-uSaO4gnW+b3Y2aWoWfFpX62vn2sR3skfhbjsEnaBI81WD1wBLlHZe5sWf0AqjksNdYTbGBEd0UasQMT3SNV15g=="],
+
"tailwindcss": ["tailwindcss@4.1.18", "", {}, "sha512-4+Z+0yiYyEtUVCScyfHCxOYP06L5Ne+JiHhY2IjR2KWMIWhJOYZKLSGZaP5HkZ8+bY0cxfzwDE5uOmzFXyIwxw=="],
"tapable": ["tapable@2.3.0", "", {}, "sha512-g9ljZiwki/LfxmQADO3dEY1CbpmXT5Hm2fJ+QaGKwSXUylMybePR7/67YW7jOrrvjEgL1Fmz5kzyAjWVWLlucg=="],
@@ -998,8 +1089,14 @@
"tinyrainbow": ["tinyrainbow@3.0.3", "", {}, "sha512-PSkbLUoxOFRzJYjjxHJt9xro7D+iilgMX/C9lawzVuYiIdcihh9DXmVibBe8lmcFrRi/VzlPjBxbN7rH24q8/Q=="],
+ "tldts": ["tldts@7.0.23", "", { "dependencies": { "tldts-core": "^7.0.23" }, "bin": { "tldts": "bin/cli.js" } }, "sha512-ASdhgQIBSay0R/eXggAkQ53G4nTJqTXqC2kbaBbdDwM7SkjyZyO0OaaN1/FH7U/yCeqOHDwFO5j8+Os/IS1dXw=="],
+
+ "tldts-core": ["tldts-core@7.0.23", "", {}, "sha512-0g9vrtDQLrNIiCj22HSe9d4mLVG3g5ph5DZ8zCKBr4OtrspmNB6ss7hVyzArAeE88ceZocIEGkyW1Ime7fxPtQ=="],
+
"to-regex-range": ["to-regex-range@5.0.1", "", { "dependencies": { "is-number": "^7.0.0" } }, "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ=="],
+ "tough-cookie": ["tough-cookie@6.0.0", "", { "dependencies": { "tldts": "^7.0.5" } }, "sha512-kXuRi1mtaKMrsLUxz3sQYvVl37B0Ns6MzfrtV5DvJceE9bPyspOqk9xxv7XbZWcfLWbFmm997vl83qUWVJA64w=="],
+
"tree-kill": ["tree-kill@1.2.2", "", { "bin": { "tree-kill": "cli.js" } }, "sha512-L0Orpi8qGpRG//Nd+H90vFB+3iHnue1zSSGmNOOCh1GLJ7rUKVwV2HvijphGQS2UmhUZewS9VgvxYIdgr+fG1A=="],
"trim-lines": ["trim-lines@3.0.1", "", {}, "sha512-kRj8B+YHZCc9kQYdWfJB2/oUl9rA99qbowYYBtr4ui4mZyAQ2JpvVBd/6U2YloATfqBhBTSMhTpgBHtU0Mf3Rg=="],
@@ -1024,7 +1121,7 @@
"turbo-windows-arm64": ["turbo-windows-arm64@2.8.7", "", { "os": "win32", "cpu": "arm64" }, "sha512-WyGiOI2Zp3AhuzVagzQN+T+iq0fWx0oGxDfAWT3ZiLEd4U0cDUkwUZDKVGb3rKqPjDL6lWnuxKKu73ge5xtovQ=="],
- "type-fest": ["type-fest@0.13.1", "", {}, "sha512-34R7HTnG0XIJcBSn5XhDd7nNFPRcXYRZrBB2O2jdKqYODldSzBAqzsWoZYYvduky73toYS/ESqxPvkDf/F0XMg=="],
+ "type-fest": ["type-fest@5.4.4", "", { "dependencies": { "tagged-tag": "^1.0.0" } }, "sha512-JnTrzGu+zPV3aXIUhnyWJj4z/wigMsdYajGLIYakqyOW1nPllzXEJee0QQbHj+CTIQtXGlAjuK0UY+2xTyjVAw=="],
"typescript": ["typescript@5.9.3", "", { "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" } }, "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw=="],
@@ -1052,8 +1149,12 @@
"unrun": ["unrun@0.2.27", "", { "dependencies": { "rolldown": "1.0.0-rc.3" }, "peerDependencies": { "synckit": "^0.11.11" }, "optionalPeers": ["synckit"], "bin": { "unrun": "dist/cli.mjs" } }, "sha512-Mmur1UJpIbfxasLOhPRvox/QS4xBiDii71hMP7smfRthGcwFL2OAmYRgduLANOAU4LUkvVamuP+02U+c90jlrw=="],
+ "until-async": ["until-async@3.0.2", "", {}, "sha512-IiSk4HlzAMqTUseHHe3VhIGyuFmN90zMTpD3Z3y8jeQbzLIq500MVM7Jq2vUAnTKAFPJrqwkzr6PoTcPhGcOiw=="],
+
"update-browserslist-db": ["update-browserslist-db@1.2.3", "", { "dependencies": { "escalade": "^3.2.0", "picocolors": "^1.1.1" }, "peerDependencies": { "browserslist": ">= 4.21.0" }, "bin": { "update-browserslist-db": "cli.js" } }, "sha512-Js0m9cx+qOgDxo0eMiFGEueWztz+d4+M3rGlmKPT+T4IS/jP4ylw3Nwpu6cpTTP8R1MAC1kF4VbdLt3ARf209w=="],
+ "use-sync-external-store": ["use-sync-external-store@1.6.0", "", { "peerDependencies": { "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0" } }, "sha512-Pp6GSwGP/NrPIrxVFAIkOQeyw8lFenOHijQWkUTrDvrF4ALqylP2C/KCkeS9dpUM3KvYRQhna5vt7IL95+ZQ9w=="],
+
"vfile": ["vfile@6.0.3", "", { "dependencies": { "@types/unist": "^3.0.0", "vfile-message": "^4.0.0" } }, "sha512-KzIbH/9tXat2u30jf+smMwFCsno4wHVdNmzFyL+T/L3UGqqk6JKfVqOFOZEpZSHADH1k40ab6NUIXZq422ov3Q=="],
"vfile-message": ["vfile-message@4.0.3", "", { "dependencies": { "@types/unist": "^3.0.0", "unist-util-stringify-position": "^4.0.0" } }, "sha512-QTHzsGd1EhbZs4AsQ20JX1rC3cOlt/IWJruk893DfLRr57lcnOeMaWG4K0JrRta4mIJZKth2Au3mM3u03/JWKw=="],
@@ -1068,16 +1169,26 @@
"why-is-node-running": ["why-is-node-running@2.3.0", "", { "dependencies": { "siginfo": "^2.0.0", "stackback": "0.0.2" }, "bin": { "why-is-node-running": "cli.js" } }, "sha512-hUrmaWBdVDcxvYqnyh09zunKzROWjbZTiNy8dBEjkS7ehEDQibXJ7XvlmtbwuTclUiIyN+CyXQD4Vmko8fNm8w=="],
+ "wrap-ansi": ["wrap-ansi@6.2.0", "", { "dependencies": { "ansi-styles": "^4.0.0", "string-width": "^4.1.0", "strip-ansi": "^6.0.0" } }, "sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA=="],
+
"wrappy": ["wrappy@1.0.2", "", {}, "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ=="],
"ws": ["ws@8.19.0", "", { "peerDependencies": { "bufferutil": "^4.0.1", "utf-8-validate": ">=5.0.2" }, "optionalPeers": ["bufferutil", "utf-8-validate"] }, "sha512-blAT2mjOEIi0ZzruJfIhb3nps74PRWTCz1IjglWEEpQl5XS/UNama6u2/rjFkDDouqr4L67ry+1aGIALViWjDg=="],
"wsl-utils": ["wsl-utils@0.1.0", "", { "dependencies": { "is-wsl": "^3.1.0" } }, "sha512-h3Fbisa2nKGPxCpm89Hk33lBLsnaGBvctQopaBSOW/uIs6FTe1ATyAnKFJrzVs9vpGdsTe73WF3V4lIsk4Gacw=="],
+ "y18n": ["y18n@5.0.8", "", {}, "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA=="],
+
"yallist": ["yallist@3.1.1", "", {}, "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g=="],
+ "yargs": ["yargs@17.7.2", "", { "dependencies": { "cliui": "^8.0.1", "escalade": "^3.1.1", "get-caller-file": "^2.0.5", "require-directory": "^2.1.1", "string-width": "^4.2.3", "y18n": "^5.0.5", "yargs-parser": "^21.1.1" } }, "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w=="],
+
+ "yargs-parser": ["yargs-parser@21.1.1", "", {}, "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw=="],
+
"yauzl": ["yauzl@2.10.0", "", { "dependencies": { "buffer-crc32": "~0.2.3", "fd-slicer": "~1.1.0" } }, "sha512-p4a9I6X6nu6IhoGmBqAcbJy1mlC4j27vEPZX9F4L4/vZT3Lyq1VkFHw/V/PUcB9Buo+DG3iHkT0x3Qya58zc3g=="],
+ "yoctocolors-cjs": ["yoctocolors-cjs@2.1.3", "", {}, "sha512-U/PBtDf35ff0D8X8D0jfdzHYEPFxAI7jJlxZXwCSez5M3190m+QobIfh+sWDWSHMCWWJN2AWamkegn6vr6YBTw=="],
+
"zod": ["zod@3.25.76", "", {}, "sha512-gzUt/qt81nXsFGKIFcC3YnfEAx5NkunCfnDlvuBSSFS02bcXu4Lmea0AFIUwbLWxWPx3d9p8S5QoaujKcNQxcQ=="],
"zwitch": ["zwitch@2.0.4", "", {}, "sha512-bXE4cR/kVZhKZX/RjPEflHaKVhUVl85noU3v6b8apfQEc1x4A+zBxjZ4lN8LqGd6WZ3dl98pY4o717VFmoPp+A=="],
@@ -1130,6 +1241,8 @@
"@vitejs/plugin-react/vite": ["vite@7.3.1", "", { "dependencies": { "esbuild": "^0.27.0", "fdir": "^6.5.0", "picomatch": "^4.0.3", "postcss": "^8.5.6", "rollup": "^4.43.0", "tinyglobby": "^0.2.15" }, "optionalDependencies": { "fsevents": "~2.3.3" }, "peerDependencies": { "@types/node": "^20.19.0 || >=22.12.0", "jiti": ">=1.21.0", "less": "^4.0.0", "lightningcss": "^1.21.0", "sass": "^1.70.0", "sass-embedded": "^1.70.0", "stylus": ">=0.54.8", "sugarss": "^5.0.0", "terser": "^5.16.0", "tsx": "^4.8.1", "yaml": "^2.4.2" }, "optionalPeers": ["@types/node", "jiti", "less", "lightningcss", "sass", "sass-embedded", "stylus", "sugarss", "terser", "tsx", "yaml"], "bin": { "vite": "bin/vite.js" } }, "sha512-w+N7Hifpc3gRjZ63vYBXA56dvvRlNWRczTdmCBBa+CotUzAPf5b7YMdMR/8CQoeYE5LX3W4wj6RYTgonm1b9DA=="],
+ "cliui/wrap-ansi": ["wrap-ansi@7.0.0", "", { "dependencies": { "ansi-styles": "^4.0.0", "string-width": "^4.1.0", "strip-ansi": "^6.0.0" } }, "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q=="],
+
"clone-response/mimic-response": ["mimic-response@1.0.1", "", {}, "sha512-j5EctnkH7amfV/q5Hgmoal1g2QHFJRraOtmx0JpIqkxhBhI/lJSl1nMpQ45hVarwNETOoWEimndZ4QK0RHxuxQ=="],
"electron/@types/node": ["@types/node@20.19.33", "", { "dependencies": { "undici-types": "~6.21.0" } }, "sha512-Rs1bVAIdBs5gbTIKza/tgpMuG1k3U/UMJLWecIMxNdJFDMzcM5LOiLVRYh3PilWEYDIeUDv7bpiHPLPsbydGcw=="],
@@ -1142,6 +1255,8 @@
"rolldown-plugin-dts/@babel/types": ["@babel/types@8.0.0-rc.1", "", { "dependencies": { "@babel/helper-string-parser": "^8.0.0-rc.1", "@babel/helper-validator-identifier": "^8.0.0-rc.1" } }, "sha512-ubmJ6TShyaD69VE9DQrlXcdkvJbmwWPB8qYj0H2kaJi29O7vJT9ajSdBd2W8CG34pwL9pYA74fi7RHC1qbLoVQ=="],
+ "serialize-error/type-fest": ["type-fest@0.13.1", "", {}, "sha512-34R7HTnG0XIJcBSn5XhDd7nNFPRcXYRZrBB2O2jdKqYODldSzBAqzsWoZYYvduky73toYS/ESqxPvkDf/F0XMg=="],
+
"vitest/vite": ["vite@7.3.1", "", { "dependencies": { "esbuild": "^0.27.0", "fdir": "^6.5.0", "picomatch": "^4.0.3", "postcss": "^8.5.6", "rollup": "^4.43.0", "tinyglobby": "^0.2.15" }, "optionalDependencies": { "fsevents": "~2.3.3" }, "peerDependencies": { "@types/node": "^20.19.0 || >=22.12.0", "jiti": ">=1.21.0", "less": "^4.0.0", "lightningcss": "^1.21.0", "sass": "^1.70.0", "sass-embedded": "^1.70.0", "stylus": ">=0.54.8", "sugarss": "^5.0.0", "terser": "^5.16.0", "tsx": "^4.8.1", "yaml": "^2.4.2" }, "optionalPeers": ["@types/node", "jiti", "less", "lightningcss", "sass", "sass-embedded", "stylus", "sugarss", "terser", "tsx", "yaml"], "bin": { "vite": "bin/vite.js" } }, "sha512-w+N7Hifpc3gRjZ63vYBXA56dvvRlNWRczTdmCBBa+CotUzAPf5b7YMdMR/8CQoeYE5LX3W4wj6RYTgonm1b9DA=="],
"@babel/generator/@babel/types/@babel/helper-string-parser": ["@babel/helper-string-parser@8.0.0-rc.1", "", {}, "sha512-vi/pfmbrOtQmqgfboaBhaCU50G7mcySVu69VU8z+lYoPPB6WzI9VgV7WQfL908M4oeSH5fDkmoupIqoE0SdApw=="],
diff --git a/packages/contracts/src/model.test.ts b/packages/contracts/src/model.test.ts
index f0469e2ccee1cca99b0ed8e30824e3d53640f900..1c279983b30f8220cd5e7052aa84d72453f7d258 100644
--- a/packages/contracts/src/model.test.ts
+++ b/packages/contracts/src/model.test.ts
@@ -29,7 +29,7 @@ describe("resolveModelSlug", () => {
it("resolves only supported model options", () => {
for (const model of MODEL_OPTIONS) {
- expect(resolveModelSlug(model)).toBe(model);
+ expect(resolveModelSlug(model.slug)).toBe(model.slug);
}
});
});
diff --git a/packages/contracts/src/model.ts b/packages/contracts/src/model.ts
index fa07d3e92fbe23326503224603142abf2b40c710..1c8d238c3f36e5500c090b350e942162bd35ddc8 100644
--- a/packages/contracts/src/model.ts
+++ b/packages/contracts/src/model.ts
@@ -1,20 +1,22 @@
export const MODEL_OPTIONS = [
- "gpt-5.3-codex",
- "gpt-5.3-codex-spark",
- "gpt-5.2-codex",
- "gpt-5.2",
+ { slug: "gpt-5.3-codex", name: "GPT-5.3 Codex" },
+ { slug: "gpt-5.3-codex-spark", name: "GPT-5.3 Codex Spark" },
+ { slug: "gpt-5.2-codex", name: "GPT-5.2 Codex" },
+ { slug: "gpt-5.2", name: "GPT-5.2" },
] as const;
+export type ModelSlug = (typeof MODEL_OPTIONS)[number]["slug"];
+
export const DEFAULT_MODEL = "gpt-5.3-codex";
-export const MODEL_SLUG_ALIASES: Record = {
+export const MODEL_SLUG_ALIASES: Record = {
"5.3": "gpt-5.3-codex",
"gpt-5.3": "gpt-5.3-codex",
"5.3-spark": "gpt-5.3-codex-spark",
"gpt-5.3-spark": "gpt-5.3-codex-spark",
};
-export function normalizeModelSlug(model: string | null | undefined): string | null {
+export function normalizeModelSlug(model: string | null | undefined): ModelSlug | null {
if (typeof model !== "string") {
return null;
}
@@ -24,16 +26,14 @@ export function normalizeModelSlug(model: string | null | undefined): string | n
return null;
}
- return MODEL_SLUG_ALIASES[trimmed] ?? trimmed;
+ return MODEL_SLUG_ALIASES[trimmed] ?? (trimmed as ModelSlug);
}
-export function resolveModelSlug(model: string | null | undefined): string {
+export function resolveModelSlug(model: string | null | undefined): ModelSlug {
const normalized = normalizeModelSlug(model);
if (!normalized) {
return DEFAULT_MODEL;
}
- return MODEL_OPTIONS.includes(normalized as (typeof MODEL_OPTIONS)[number])
- ? normalized
- : DEFAULT_MODEL;
+ return MODEL_OPTIONS.some((option) => option.slug === normalized) ? normalized : DEFAULT_MODEL;
}