mirror of
https://github.com/eliasstepanik/core.git
synced 2026-01-11 16:48:27 +00:00
Feat: logs ui
This commit is contained in:
parent
704dffdef5
commit
72fe9f18bc
228
apps/webapp/app/components/logs/logs-filters.tsx
Normal file
228
apps/webapp/app/components/logs/logs-filters.tsx
Normal file
@ -0,0 +1,228 @@
|
||||
import { useState } from "react";
|
||||
import { Check, ChevronsUpDown, Filter, X } from "lucide-react";
|
||||
import { Button } from "~/components/ui/button";
|
||||
import {
|
||||
Command,
|
||||
CommandEmpty,
|
||||
CommandGroup,
|
||||
CommandInput,
|
||||
CommandItem,
|
||||
CommandList,
|
||||
} from "~/components/ui/command";
|
||||
import {
|
||||
Popover,
|
||||
PopoverContent,
|
||||
PopoverTrigger,
|
||||
} from "~/components/ui/popover";
|
||||
import { Badge } from "~/components/ui/badge";
|
||||
import { cn } from "~/lib/utils";
|
||||
|
||||
interface LogsFiltersProps {
|
||||
availableSources: Array<{ name: string; slug: string }>;
|
||||
selectedSource?: string;
|
||||
selectedStatus?: string;
|
||||
onSourceChange: (source?: string) => void;
|
||||
onStatusChange: (status?: string) => void;
|
||||
}
|
||||
|
||||
const statusOptions = [
|
||||
{ value: "PENDING", label: "Pending" },
|
||||
{ value: "PROCESSING", label: "Processing" },
|
||||
{ value: "COMPLETED", label: "Completed" },
|
||||
{ value: "FAILED", label: "Failed" },
|
||||
{ value: "CANCELLED", label: "Cancelled" },
|
||||
];
|
||||
|
||||
export function LogsFilters({
|
||||
availableSources,
|
||||
selectedSource,
|
||||
selectedStatus,
|
||||
onSourceChange,
|
||||
onStatusChange,
|
||||
}: LogsFiltersProps) {
|
||||
const [sourceOpen, setSourceOpen] = useState(false);
|
||||
const [statusOpen, setStatusOpen] = useState(false);
|
||||
|
||||
const selectedSourceName = availableSources.find(
|
||||
(s) => s.slug === selectedSource,
|
||||
)?.name;
|
||||
const selectedStatusLabel = statusOptions.find(
|
||||
(s) => s.value === selectedStatus,
|
||||
)?.label;
|
||||
|
||||
const clearFilters = () => {
|
||||
onSourceChange(undefined);
|
||||
onStatusChange(undefined);
|
||||
};
|
||||
|
||||
const hasFilters = selectedSource || selectedStatus;
|
||||
|
||||
return (
|
||||
<div className="mb-4 flex items-center gap-2">
|
||||
<div className="flex items-center gap-2">
|
||||
<Filter className="text-muted-foreground h-4 w-4" />
|
||||
<span className="text-sm font-medium">Filters:</span>
|
||||
</div>
|
||||
|
||||
{/* Source Filter */}
|
||||
<Popover open={sourceOpen} onOpenChange={setSourceOpen}>
|
||||
<PopoverTrigger asChild>
|
||||
<Button
|
||||
variant="outline"
|
||||
role="combobox"
|
||||
aria-expanded={sourceOpen}
|
||||
className="w-[200px] justify-between"
|
||||
>
|
||||
{selectedSourceName || "Select source..."}
|
||||
<ChevronsUpDown className="ml-2 h-4 w-4 shrink-0 opacity-50" />
|
||||
</Button>
|
||||
</PopoverTrigger>
|
||||
<PopoverContent className="w-[200px] p-0">
|
||||
<Command>
|
||||
<CommandInput placeholder="Search sources..." />
|
||||
<CommandList>
|
||||
<CommandEmpty>No sources found.</CommandEmpty>
|
||||
<CommandGroup>
|
||||
<CommandItem
|
||||
value=""
|
||||
onSelect={() => {
|
||||
onSourceChange(undefined);
|
||||
setSourceOpen(false);
|
||||
}}
|
||||
>
|
||||
<Check
|
||||
className={cn(
|
||||
"mr-2 h-4 w-4",
|
||||
!selectedSource ? "opacity-100" : "opacity-0",
|
||||
)}
|
||||
/>
|
||||
All sources
|
||||
</CommandItem>
|
||||
{availableSources.map((source) => (
|
||||
<CommandItem
|
||||
key={source.slug}
|
||||
value={source.slug}
|
||||
onSelect={() => {
|
||||
onSourceChange(
|
||||
source.slug === selectedSource
|
||||
? undefined
|
||||
: source.slug,
|
||||
);
|
||||
setSourceOpen(false);
|
||||
}}
|
||||
>
|
||||
<Check
|
||||
className={cn(
|
||||
"mr-2 h-4 w-4",
|
||||
selectedSource === source.slug
|
||||
? "opacity-100"
|
||||
: "opacity-0",
|
||||
)}
|
||||
/>
|
||||
{source.name}
|
||||
</CommandItem>
|
||||
))}
|
||||
</CommandGroup>
|
||||
</CommandList>
|
||||
</Command>
|
||||
</PopoverContent>
|
||||
</Popover>
|
||||
|
||||
{/* Status Filter */}
|
||||
<Popover open={statusOpen} onOpenChange={setStatusOpen}>
|
||||
<PopoverTrigger asChild>
|
||||
<Button
|
||||
variant="outline"
|
||||
role="combobox"
|
||||
aria-expanded={statusOpen}
|
||||
className="w-[200px] justify-between"
|
||||
>
|
||||
{selectedStatusLabel || "Select status..."}
|
||||
<ChevronsUpDown className="ml-2 h-4 w-4 shrink-0 opacity-50" />
|
||||
</Button>
|
||||
</PopoverTrigger>
|
||||
<PopoverContent className="w-[200px] p-0">
|
||||
<Command>
|
||||
<CommandInput placeholder="Search status..." />
|
||||
<CommandList>
|
||||
<CommandEmpty>No status found.</CommandEmpty>
|
||||
<CommandGroup>
|
||||
<CommandItem
|
||||
value=""
|
||||
onSelect={() => {
|
||||
onStatusChange(undefined);
|
||||
setStatusOpen(false);
|
||||
}}
|
||||
>
|
||||
<Check
|
||||
className={cn(
|
||||
"mr-2 h-4 w-4",
|
||||
!selectedStatus ? "opacity-100" : "opacity-0",
|
||||
)}
|
||||
/>
|
||||
All statuses
|
||||
</CommandItem>
|
||||
{statusOptions.map((status) => (
|
||||
<CommandItem
|
||||
key={status.value}
|
||||
value={status.value}
|
||||
onSelect={() => {
|
||||
onStatusChange(
|
||||
status.value === selectedStatus
|
||||
? undefined
|
||||
: status.value,
|
||||
);
|
||||
setStatusOpen(false);
|
||||
}}
|
||||
>
|
||||
<Check
|
||||
className={cn(
|
||||
"mr-2 h-4 w-4",
|
||||
selectedStatus === status.value
|
||||
? "opacity-100"
|
||||
: "opacity-0",
|
||||
)}
|
||||
/>
|
||||
{status.label}
|
||||
</CommandItem>
|
||||
))}
|
||||
</CommandGroup>
|
||||
</CommandList>
|
||||
</Command>
|
||||
</PopoverContent>
|
||||
</Popover>
|
||||
|
||||
{/* Active Filters */}
|
||||
{hasFilters && (
|
||||
<div className="flex items-center gap-2">
|
||||
{selectedSource && (
|
||||
<Badge variant="secondary" className="gap-1">
|
||||
{selectedSourceName}
|
||||
<X
|
||||
className="hover:text-destructive h-3 w-3 cursor-pointer"
|
||||
onClick={() => onSourceChange(undefined)}
|
||||
/>
|
||||
</Badge>
|
||||
)}
|
||||
{selectedStatus && (
|
||||
<Badge variant="secondary" className="gap-1">
|
||||
{selectedStatusLabel}
|
||||
<X
|
||||
className="hover:text-destructive h-3 w-3 cursor-pointer"
|
||||
onClick={() => onStatusChange(undefined)}
|
||||
/>
|
||||
</Badge>
|
||||
)}
|
||||
<Button
|
||||
variant="ghost"
|
||||
size="sm"
|
||||
onClick={clearFilters}
|
||||
className="h-6 px-2 text-xs"
|
||||
>
|
||||
Clear all
|
||||
</Button>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
198
apps/webapp/app/components/logs/virtual-logs-list.tsx
Normal file
198
apps/webapp/app/components/logs/virtual-logs-list.tsx
Normal file
@ -0,0 +1,198 @@
|
||||
import { useEffect, useRef, useState } from "react";
|
||||
import { List, InfiniteLoader, WindowScroller } from "react-virtualized";
|
||||
import { LogItem } from "~/hooks/use-logs";
|
||||
import { Badge } from "~/components/ui/badge";
|
||||
import { Card, CardContent } from "~/components/ui/card";
|
||||
import { AlertCircle, CheckCircle, Clock, XCircle } from "lucide-react";
|
||||
import { cn } from "~/lib/utils";
|
||||
|
||||
interface VirtualLogsListProps {
|
||||
logs: LogItem[];
|
||||
hasMore: boolean;
|
||||
loadMore: () => void;
|
||||
isLoading: boolean;
|
||||
height?: number;
|
||||
}
|
||||
|
||||
const ITEM_HEIGHT = 120;
|
||||
|
||||
interface LogItemRendererProps {
|
||||
index: number;
|
||||
key: string;
|
||||
style: React.CSSProperties;
|
||||
}
|
||||
|
||||
function LogItemRenderer(props: LogItemRendererProps, logs: LogItem[]) {
|
||||
const { index, key, style } = props;
|
||||
const log = logs[index];
|
||||
|
||||
if (!log) {
|
||||
return (
|
||||
<div key={key} style={style} className="p-4">
|
||||
<div className="h-24 animate-pulse rounded bg-gray-200" />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
const getStatusIcon = (status: string) => {
|
||||
switch (status) {
|
||||
case "PROCESSING":
|
||||
return <Clock className="h-4 w-4 text-blue-500" />;
|
||||
case "PENDING":
|
||||
return <Clock className="h-4 w-4 text-yellow-500" />;
|
||||
case "COMPLETED":
|
||||
return <CheckCircle className="h-4 w-4 text-green-500" />;
|
||||
case "FAILED":
|
||||
return <XCircle className="h-4 w-4 text-red-500" />;
|
||||
case "CANCELLED":
|
||||
return <XCircle className="h-4 w-4 text-gray-500" />;
|
||||
default:
|
||||
return <AlertCircle className="h-4 w-4 text-gray-500" />;
|
||||
}
|
||||
};
|
||||
|
||||
const getStatusColor = (status: string) => {
|
||||
switch (status) {
|
||||
case "PROCESSING":
|
||||
return "bg-blue-100 text-blue-800";
|
||||
case "PENDING":
|
||||
return "bg-yellow-100 text-yellow-800";
|
||||
case "COMPLETED":
|
||||
return "bg-green-100 text-green-800";
|
||||
case "FAILED":
|
||||
return "bg-red-100 text-red-800";
|
||||
case "CANCELLED":
|
||||
return "bg-gray-100 text-gray-800";
|
||||
default:
|
||||
return "bg-gray-100 text-gray-800";
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<div key={key} style={style} className="p-2">
|
||||
<Card className="h-full">
|
||||
<CardContent className="p-4">
|
||||
<div className="mb-2 flex items-start justify-between">
|
||||
<div className="flex items-center gap-2">
|
||||
<Badge variant="outline" className="text-xs">
|
||||
{log.source}
|
||||
</Badge>
|
||||
<div className="flex items-center gap-1">
|
||||
{getStatusIcon(log.status)}
|
||||
<Badge className={cn("text-xs", getStatusColor(log.status))}>
|
||||
{log.status.toLowerCase()}
|
||||
</Badge>
|
||||
</div>
|
||||
</div>
|
||||
<div className="text-muted-foreground text-xs">
|
||||
{new Date(log.time).toLocaleString()}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="mb-2">
|
||||
<p className="line-clamp-2 text-sm text-gray-700">
|
||||
{log.ingestText}
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div className="text-muted-foreground flex items-center justify-between text-xs">
|
||||
<div className="flex items-center gap-4">
|
||||
{log.sourceURL && (
|
||||
<a
|
||||
href={log.sourceURL}
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
className="text-blue-600 underline hover:text-blue-800"
|
||||
>
|
||||
Source URL
|
||||
</a>
|
||||
)}
|
||||
{log.processedAt && (
|
||||
<span>
|
||||
Processed: {new Date(log.processedAt).toLocaleString()}
|
||||
</span>
|
||||
)}
|
||||
</div>
|
||||
|
||||
{log.error && (
|
||||
<div className="flex items-center gap-1 text-red-600">
|
||||
<AlertCircle className="h-3 w-3" />
|
||||
<span className="max-w-[200px] truncate" title={log.error}>
|
||||
{log.error}
|
||||
</span>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</CardContent>
|
||||
</Card>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
export function VirtualLogsList({
|
||||
logs,
|
||||
hasMore,
|
||||
loadMore,
|
||||
isLoading,
|
||||
height = 600,
|
||||
}: VirtualLogsListProps) {
|
||||
const [containerHeight, setContainerHeight] = useState(height);
|
||||
|
||||
useEffect(() => {
|
||||
const updateHeight = () => {
|
||||
const availableHeight = window.innerHeight - 300; // Account for header, filters, etc.
|
||||
setContainerHeight(Math.min(availableHeight, height));
|
||||
};
|
||||
|
||||
updateHeight();
|
||||
window.addEventListener("resize", updateHeight);
|
||||
return () => window.removeEventListener("resize", updateHeight);
|
||||
}, [height]);
|
||||
|
||||
const isRowLoaded = ({ index }: { index: number }) => {
|
||||
return !!logs[index];
|
||||
};
|
||||
|
||||
const loadMoreRows = async () => {
|
||||
if (hasMore) {
|
||||
return loadMore();
|
||||
}
|
||||
|
||||
return false;
|
||||
};
|
||||
|
||||
const rowRenderer = (props: LogItemRendererProps) => {
|
||||
return LogItemRenderer(props, logs);
|
||||
};
|
||||
|
||||
const itemCount = hasMore ? logs.length + 1 : logs.length;
|
||||
|
||||
return (
|
||||
<div className="overflow-hidden rounded-lg border">
|
||||
<InfiniteLoader
|
||||
isRowLoaded={isRowLoaded}
|
||||
loadMoreRows={loadMoreRows}
|
||||
rowCount={itemCount}
|
||||
threshold={5}
|
||||
>
|
||||
{({ onRowsRendered, registerChild }) => (
|
||||
<List
|
||||
ref={registerChild}
|
||||
height={containerHeight}
|
||||
rowCount={itemCount}
|
||||
rowHeight={ITEM_HEIGHT}
|
||||
onRowsRendered={onRowsRendered}
|
||||
rowRenderer={rowRenderer}
|
||||
className="scrollbar-thin scrollbar-thumb-gray-300 scrollbar-track-gray-100"
|
||||
/>
|
||||
)}
|
||||
</InfiniteLoader>
|
||||
|
||||
{isLoading && (
|
||||
<div className="text-muted-foreground p-4 text-center text-sm">
|
||||
Loading more logs...
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
@ -28,8 +28,8 @@ const data = {
|
||||
icon: Network,
|
||||
},
|
||||
{
|
||||
title: "Activity",
|
||||
url: "/home/activity",
|
||||
title: "Logs",
|
||||
url: "/home/logs/all",
|
||||
icon: Activity,
|
||||
},
|
||||
{
|
||||
|
||||
179
apps/webapp/app/components/ui/command.tsx
Normal file
179
apps/webapp/app/components/ui/command.tsx
Normal file
@ -0,0 +1,179 @@
|
||||
import { type DialogProps } from "@radix-ui/react-dialog";
|
||||
import { MagnifyingGlassIcon } from "@radix-ui/react-icons";
|
||||
import { Command as CommandPrimitive } from "cmdk";
|
||||
import React from "react";
|
||||
|
||||
import { Dialog, DialogContent } from "./dialog";
|
||||
import { cn } from "../../lib/utils";
|
||||
|
||||
const Command = React.forwardRef<
|
||||
React.ElementRef<typeof CommandPrimitive>,
|
||||
React.ComponentPropsWithoutRef<typeof CommandPrimitive>
|
||||
>(({ className, ...props }, ref) => (
|
||||
<CommandPrimitive
|
||||
ref={ref}
|
||||
className={cn(
|
||||
"bg-popover text-popover-foreground flex h-full w-full flex-col overflow-hidden rounded-md font-sans",
|
||||
className,
|
||||
)}
|
||||
{...props}
|
||||
/>
|
||||
));
|
||||
Command.displayName = CommandPrimitive.displayName;
|
||||
|
||||
interface CommandDialogProps extends DialogProps {
|
||||
commandProps?: React.ComponentPropsWithoutRef<typeof CommandPrimitive>;
|
||||
}
|
||||
|
||||
interface CommandInputProps
|
||||
extends React.ComponentPropsWithoutRef<typeof CommandPrimitive.Input> {
|
||||
icon?: boolean;
|
||||
containerClassName?: string;
|
||||
}
|
||||
|
||||
const CommandDialog = ({
|
||||
children,
|
||||
commandProps,
|
||||
...props
|
||||
}: CommandDialogProps) => {
|
||||
return (
|
||||
<Dialog {...props}>
|
||||
<DialogContent className={cn("overflow-hidden p-0 font-sans")}>
|
||||
<Command
|
||||
className="[&_[cmdk-group-heading]]:text-muted-foreground [&_[cmdk-group-heading]]:font-medium [&_[cmdk-group]:not([hidden])_~[cmdk-group]]:pt-0 [&_[cmdk-input-wrapper]_svg]:h-5 [&_[cmdk-input-wrapper]_svg]:w-5 [&_[cmdk-input]]:h-12 [&_[cmdk-item]]:px-2 [&_[cmdk-item]]:py-3 [&_[cmdk-item]_svg]:h-5 [&_[cmdk-item]_svg]:w-5"
|
||||
{...commandProps}
|
||||
>
|
||||
{children}
|
||||
</Command>
|
||||
</DialogContent>
|
||||
</Dialog>
|
||||
);
|
||||
};
|
||||
|
||||
const CommandInput = React.forwardRef<
|
||||
React.ElementRef<typeof CommandPrimitive.Input>,
|
||||
CommandInputProps
|
||||
>(({ className, icon, containerClassName, ...props }, ref) => (
|
||||
<div
|
||||
className={cn(
|
||||
"border-border flex items-center border-b px-3",
|
||||
containerClassName,
|
||||
)}
|
||||
cmdk-input-wrapper=""
|
||||
>
|
||||
{icon && (
|
||||
<MagnifyingGlassIcon className="mr-2 h-5 w-5 shrink-0 opacity-50" />
|
||||
)}
|
||||
<CommandPrimitive.Input
|
||||
ref={ref}
|
||||
className={cn(
|
||||
"placeholder:text-muted-foreground flex h-8 w-full rounded-md bg-transparent py-3 outline-none disabled:cursor-not-allowed disabled:opacity-50",
|
||||
className,
|
||||
)}
|
||||
{...props}
|
||||
/>
|
||||
</div>
|
||||
));
|
||||
|
||||
CommandInput.displayName = CommandPrimitive.Input.displayName;
|
||||
|
||||
const CommandList = React.forwardRef<
|
||||
React.ElementRef<typeof CommandPrimitive.List>,
|
||||
React.ComponentPropsWithoutRef<typeof CommandPrimitive.List>
|
||||
>(({ className, ...props }, ref) => (
|
||||
<CommandPrimitive.List
|
||||
ref={ref}
|
||||
className={cn(
|
||||
"command-list max-h-[500px] overflow-x-hidden overflow-y-auto",
|
||||
className,
|
||||
)}
|
||||
{...props}
|
||||
/>
|
||||
));
|
||||
|
||||
CommandList.displayName = CommandPrimitive.List.displayName;
|
||||
|
||||
const CommandEmpty = React.forwardRef<
|
||||
React.ElementRef<typeof CommandPrimitive.Empty>,
|
||||
React.ComponentPropsWithoutRef<typeof CommandPrimitive.Empty>
|
||||
>((props, ref) => (
|
||||
<CommandPrimitive.Empty
|
||||
ref={ref}
|
||||
className="py-6 text-center text-sm"
|
||||
{...props}
|
||||
/>
|
||||
));
|
||||
|
||||
CommandEmpty.displayName = CommandPrimitive.Empty.displayName;
|
||||
|
||||
const CommandGroup = React.forwardRef<
|
||||
React.ElementRef<typeof CommandPrimitive.Group>,
|
||||
React.ComponentPropsWithoutRef<typeof CommandPrimitive.Group>
|
||||
>(({ className, ...props }, ref) => (
|
||||
<CommandPrimitive.Group
|
||||
ref={ref}
|
||||
className={cn(
|
||||
"text-foreground [&_[cmdk-group-heading]]:text-muted-foreground overflow-hidden p-1 [&_[cmdk-group-heading]]:px-2 [&_[cmdk-group-heading]]:py-1.5 [&_[cmdk-group-heading]]:text-xs [&_[cmdk-group-heading]]:font-medium",
|
||||
className,
|
||||
)}
|
||||
{...props}
|
||||
/>
|
||||
));
|
||||
|
||||
CommandGroup.displayName = CommandPrimitive.Group.displayName;
|
||||
|
||||
const CommandSeparator = React.forwardRef<
|
||||
React.ElementRef<typeof CommandPrimitive.Separator>,
|
||||
React.ComponentPropsWithoutRef<typeof CommandPrimitive.Separator>
|
||||
>(({ className, ...props }, ref) => (
|
||||
<CommandPrimitive.Separator
|
||||
ref={ref}
|
||||
className={cn("bg-border -mx-1 h-px", className)}
|
||||
{...props}
|
||||
/>
|
||||
));
|
||||
CommandSeparator.displayName = CommandPrimitive.Separator.displayName;
|
||||
|
||||
const CommandItem = React.forwardRef<
|
||||
React.ElementRef<typeof CommandPrimitive.Item>,
|
||||
React.ComponentPropsWithoutRef<typeof CommandPrimitive.Item>
|
||||
>(({ className, ...props }, ref) => (
|
||||
<CommandPrimitive.Item
|
||||
ref={ref}
|
||||
className={cn(
|
||||
"command-item aria-selected:bg-accent aria-selected:text-accent-foreground relative flex cursor-default items-center rounded-sm px-2 py-1 outline-none select-none data-[disabled]:pointer-events-none data-[disabled]:opacity-50",
|
||||
className,
|
||||
)}
|
||||
{...props}
|
||||
/>
|
||||
));
|
||||
|
||||
CommandItem.displayName = CommandPrimitive.Item.displayName;
|
||||
|
||||
const CommandShortcut = ({
|
||||
className,
|
||||
...props
|
||||
}: React.HTMLAttributes<HTMLSpanElement>) => {
|
||||
return (
|
||||
<span
|
||||
className={cn(
|
||||
"text-muted-foreground ml-auto text-xs tracking-widest",
|
||||
className,
|
||||
)}
|
||||
{...props}
|
||||
/>
|
||||
);
|
||||
};
|
||||
CommandShortcut.displayName = "CommandShortcut";
|
||||
|
||||
export {
|
||||
Command,
|
||||
CommandDialog,
|
||||
CommandInput,
|
||||
CommandList,
|
||||
CommandEmpty,
|
||||
CommandGroup,
|
||||
CommandItem,
|
||||
CommandShortcut,
|
||||
CommandSeparator,
|
||||
};
|
||||
@ -7,7 +7,7 @@ const PAGE_TITLES: Record<string, string> = {
|
||||
"/home/dashboard": "Memory graph",
|
||||
"/home/conversation": "Conversation",
|
||||
"/home/integrations": "Integrations",
|
||||
"/home/activity": "Activity",
|
||||
"/home/logs": "Logs",
|
||||
};
|
||||
|
||||
function getHeaderTitle(pathname: string): string {
|
||||
@ -26,12 +26,17 @@ function isConversationDetail(pathname: string): boolean {
|
||||
return /^\/home\/conversation\/[^/]+$/.test(pathname);
|
||||
}
|
||||
|
||||
function isIntegrationsPage(pathname: string): boolean {
|
||||
return pathname === "/home/integrations";
|
||||
}
|
||||
|
||||
export function SiteHeader() {
|
||||
const location = useLocation();
|
||||
const navigate = useNavigate();
|
||||
const title = getHeaderTitle(location.pathname);
|
||||
|
||||
const showNewConversationButton = isConversationDetail(location.pathname);
|
||||
const showRequestIntegrationButton = isIntegrationsPage(location.pathname);
|
||||
|
||||
return (
|
||||
<header className="flex h-(--header-height) shrink-0 items-center gap-2 border-b border-gray-300 transition-[width,height] ease-linear group-has-data-[collapsible=icon]/sidebar-wrapper:h-(--header-height)">
|
||||
@ -51,6 +56,16 @@ export function SiteHeader() {
|
||||
New conversation
|
||||
</Button>
|
||||
)}
|
||||
{showRequestIntegrationButton && (
|
||||
<Button
|
||||
onClick={() => window.open("https://github.com/redplanethq/core/issues/new", "_blank")}
|
||||
variant="secondary"
|
||||
className="gap-2"
|
||||
>
|
||||
<Plus size={14} />
|
||||
Request New Integration
|
||||
</Button>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
</header>
|
||||
|
||||
@ -263,7 +263,8 @@ function SidebarTrigger({
|
||||
data-sidebar="trigger"
|
||||
data-slot="sidebar-trigger"
|
||||
variant="ghost"
|
||||
className={cn("size-8", className)}
|
||||
size="xs"
|
||||
className={cn("size-6 rounded-md", className)}
|
||||
onClick={(event) => {
|
||||
onClick?.(event);
|
||||
toggleSidebar();
|
||||
|
||||
@ -36,7 +36,7 @@ export function useIngestionStatus() {
|
||||
clearInterval(interval);
|
||||
setIsPolling(false);
|
||||
};
|
||||
}, [fetcher]);
|
||||
}, []); // Remove fetcher from dependencies to prevent infinite loop
|
||||
|
||||
return {
|
||||
data: fetcher.data,
|
||||
|
||||
108
apps/webapp/app/hooks/use-logs.tsx
Normal file
108
apps/webapp/app/hooks/use-logs.tsx
Normal file
@ -0,0 +1,108 @@
|
||||
import { useEffect, useState, useCallback } from "react";
|
||||
import { useFetcher } from "@remix-run/react";
|
||||
|
||||
export interface LogItem {
|
||||
id: string;
|
||||
source: string;
|
||||
ingestText: string;
|
||||
time: string;
|
||||
processedAt?: string;
|
||||
status: "PENDING" | "PROCESSING" | "COMPLETED" | "FAILED" | "CANCELLED";
|
||||
error?: string;
|
||||
sourceURL?: string;
|
||||
integrationSlug?: string;
|
||||
activityId?: string;
|
||||
}
|
||||
|
||||
export interface LogsResponse {
|
||||
logs: LogItem[];
|
||||
totalCount: number;
|
||||
page: number;
|
||||
limit: number;
|
||||
hasMore: boolean;
|
||||
availableSources: Array<{ name: string; slug: string }>;
|
||||
}
|
||||
|
||||
export interface UseLogsOptions {
|
||||
endpoint: string; // '/api/v1/logs/all' or '/api/v1/logs/activity'
|
||||
source?: string;
|
||||
status?: string;
|
||||
}
|
||||
|
||||
export function useLogs({ endpoint, source, status }: UseLogsOptions) {
|
||||
const fetcher = useFetcher<LogsResponse>();
|
||||
const [logs, setLogs] = useState<LogItem[]>([]);
|
||||
const [page, setPage] = useState(1);
|
||||
const [hasMore, setHasMore] = useState(true);
|
||||
const [availableSources, setAvailableSources] = useState<Array<{ name: string; slug: string }>>([]);
|
||||
const [isInitialLoad, setIsInitialLoad] = useState(true);
|
||||
|
||||
const buildUrl = useCallback((pageNum: number) => {
|
||||
const params = new URLSearchParams();
|
||||
params.set('page', pageNum.toString());
|
||||
params.set('limit', '20');
|
||||
if (source) params.set('source', source);
|
||||
if (status) params.set('status', status);
|
||||
return `${endpoint}?${params.toString()}`;
|
||||
}, [endpoint, source, status]);
|
||||
|
||||
const loadMore = useCallback(() => {
|
||||
if (fetcher.state === 'idle' && hasMore) {
|
||||
fetcher.load(buildUrl(page + 1));
|
||||
}
|
||||
}, [hasMore, page, buildUrl]);
|
||||
|
||||
const reset = useCallback(() => {
|
||||
setLogs([]);
|
||||
setPage(1);
|
||||
setHasMore(true);
|
||||
setIsInitialLoad(true);
|
||||
fetcher.load(buildUrl(1));
|
||||
}, [buildUrl]);
|
||||
|
||||
// Effect to handle fetcher data
|
||||
useEffect(() => {
|
||||
if (fetcher.data) {
|
||||
const { logs: newLogs, hasMore: newHasMore, page: currentPage, availableSources: sources } = fetcher.data;
|
||||
|
||||
if (currentPage === 1) {
|
||||
// First page or reset
|
||||
setLogs(newLogs);
|
||||
setIsInitialLoad(false);
|
||||
} else {
|
||||
// Append to existing logs
|
||||
setLogs(prev => [...prev, ...newLogs]);
|
||||
}
|
||||
|
||||
setHasMore(newHasMore);
|
||||
setPage(currentPage);
|
||||
setAvailableSources(sources);
|
||||
}
|
||||
}, [fetcher.data]);
|
||||
|
||||
// Effect to reset when filters change
|
||||
useEffect(() => {
|
||||
setLogs([]);
|
||||
setPage(1);
|
||||
setHasMore(true);
|
||||
setIsInitialLoad(true);
|
||||
fetcher.load(buildUrl(1));
|
||||
}, [source, status, buildUrl]); // Inline reset logic to avoid dependency issues
|
||||
|
||||
// Initial load
|
||||
useEffect(() => {
|
||||
if (isInitialLoad) {
|
||||
fetcher.load(buildUrl(1));
|
||||
}
|
||||
}, [isInitialLoad, buildUrl]);
|
||||
|
||||
return {
|
||||
logs,
|
||||
hasMore,
|
||||
loadMore,
|
||||
reset,
|
||||
availableSources,
|
||||
isLoading: fetcher.state === 'loading',
|
||||
isInitialLoad,
|
||||
};
|
||||
}
|
||||
@ -16,6 +16,7 @@ export const IngestBodyRequest = z.object({
|
||||
export const addToQueue = async (
|
||||
body: z.infer<typeof IngestBodyRequest>,
|
||||
userId: string,
|
||||
activityId?: string,
|
||||
) => {
|
||||
const user = await prisma.user.findFirst({
|
||||
where: {
|
||||
@ -39,6 +40,7 @@ export const addToQueue = async (
|
||||
status: IngestionStatus.PENDING,
|
||||
priority: 1,
|
||||
workspaceId: user.Workspace.id,
|
||||
activityId,
|
||||
},
|
||||
});
|
||||
|
||||
|
||||
@ -40,7 +40,6 @@ const { action, loader } = createActionApiRoute(
|
||||
throw new Error("User not found");
|
||||
}
|
||||
|
||||
|
||||
// Create the activity record
|
||||
const activity = await prisma.activity.create({
|
||||
data: {
|
||||
@ -64,7 +63,11 @@ const { action, loader } = createActionApiRoute(
|
||||
},
|
||||
};
|
||||
|
||||
const queueResponse = await addToQueue(ingestData, authentication.userId);
|
||||
const queueResponse = await addToQueue(
|
||||
ingestData,
|
||||
authentication.userId,
|
||||
activity.id,
|
||||
);
|
||||
|
||||
logger.log("Activity created and queued for ingestion", {
|
||||
activityId: activity.id,
|
||||
@ -90,4 +93,4 @@ const { action, loader } = createActionApiRoute(
|
||||
},
|
||||
);
|
||||
|
||||
export { action, loader };
|
||||
export { action, loader };
|
||||
|
||||
130
apps/webapp/app/routes/api.v1.logs.activity.tsx
Normal file
130
apps/webapp/app/routes/api.v1.logs.activity.tsx
Normal file
@ -0,0 +1,130 @@
|
||||
import { LoaderFunctionArgs, json } from "@remix-run/node";
|
||||
import { prisma } from "~/db.server";
|
||||
import { requireUserId } from "~/services/session.server";
|
||||
|
||||
export async function loader({ request }: LoaderFunctionArgs) {
|
||||
const userId = await requireUserId(request);
|
||||
const url = new URL(request.url);
|
||||
|
||||
const page = parseInt(url.searchParams.get("page") || "1");
|
||||
const limit = parseInt(url.searchParams.get("limit") || "20");
|
||||
const source = url.searchParams.get("source");
|
||||
const status = url.searchParams.get("status");
|
||||
const skip = (page - 1) * limit;
|
||||
|
||||
const user = await prisma.user.findUnique({
|
||||
where: { id: userId },
|
||||
include: { Workspace: true },
|
||||
});
|
||||
|
||||
if (!user?.Workspace) {
|
||||
throw new Response("Workspace not found", { status: 404 });
|
||||
}
|
||||
|
||||
// Build where clause for filtering - only items with activityId
|
||||
const whereClause: any = {
|
||||
workspaceId: user.Workspace.id,
|
||||
activityId: {
|
||||
not: null,
|
||||
},
|
||||
};
|
||||
|
||||
if (status) {
|
||||
whereClause.status = status;
|
||||
}
|
||||
|
||||
// If source filter is provided, we need to filter by integration source
|
||||
if (source) {
|
||||
whereClause.activity = {
|
||||
integrationAccount: {
|
||||
integrationDefinition: {
|
||||
slug: source,
|
||||
},
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
const [logs, totalCount] = await Promise.all([
|
||||
prisma.ingestionQueue.findMany({
|
||||
where: whereClause,
|
||||
include: {
|
||||
activity: {
|
||||
include: {
|
||||
integrationAccount: {
|
||||
include: {
|
||||
integrationDefinition: {
|
||||
select: {
|
||||
name: true,
|
||||
slug: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
orderBy: {
|
||||
createdAt: "desc",
|
||||
},
|
||||
skip,
|
||||
take: limit,
|
||||
}),
|
||||
prisma.ingestionQueue.count({
|
||||
where: whereClause,
|
||||
}),
|
||||
]);
|
||||
|
||||
// Get available sources for filtering (only those with activities)
|
||||
const availableSources = await prisma.integrationDefinitionV2.findMany({
|
||||
where: {
|
||||
IntegrationAccount: {
|
||||
some: {
|
||||
workspaceId: user.Workspace.id,
|
||||
Activity: {
|
||||
some: {
|
||||
IngestionQueue: {
|
||||
some: {
|
||||
activityId: {
|
||||
not: null,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
select: {
|
||||
name: true,
|
||||
slug: true,
|
||||
},
|
||||
});
|
||||
|
||||
// Format the response
|
||||
const formattedLogs = logs.map((log) => ({
|
||||
id: log.id,
|
||||
source: log.activity?.integrationAccount?.integrationDefinition?.name ||
|
||||
(log.data as any)?.source ||
|
||||
'Unknown',
|
||||
ingestText: log.activity?.text ||
|
||||
(log.data as any)?.episodeBody ||
|
||||
(log.data as any)?.text ||
|
||||
'No content',
|
||||
time: log.createdAt,
|
||||
processedAt: log.processedAt,
|
||||
status: log.status,
|
||||
error: log.error,
|
||||
sourceURL: log.activity?.sourceURL,
|
||||
integrationSlug: log.activity?.integrationAccount?.integrationDefinition?.slug,
|
||||
activityId: log.activityId,
|
||||
}));
|
||||
|
||||
return json({
|
||||
logs: formattedLogs,
|
||||
totalCount,
|
||||
page,
|
||||
limit,
|
||||
hasMore: skip + logs.length < totalCount,
|
||||
availableSources,
|
||||
});
|
||||
}
|
||||
137
apps/webapp/app/routes/api.v1.logs.all.tsx
Normal file
137
apps/webapp/app/routes/api.v1.logs.all.tsx
Normal file
@ -0,0 +1,137 @@
|
||||
import { type LoaderFunctionArgs, json } from "@remix-run/node";
|
||||
import { prisma } from "~/db.server";
|
||||
import { requireUserId } from "~/services/session.server";
|
||||
|
||||
/**
|
||||
* Optimizations:
|
||||
* - Use `findMany` with `select` instead of `include` to fetch only required fields.
|
||||
* - Use `count` with the same where clause, but only after fetching logs (to avoid unnecessary count if no logs).
|
||||
* - Use a single query for availableSources with minimal fields.
|
||||
* - Avoid unnecessary object spreading and type casting.
|
||||
* - Minimize nested object traversal in mapping.
|
||||
*/
|
||||
export async function loader({ request }: LoaderFunctionArgs) {
|
||||
const userId = await requireUserId(request);
|
||||
const url = new URL(request.url);
|
||||
|
||||
const page = parseInt(url.searchParams.get("page") || "1");
|
||||
const limit = parseInt(url.searchParams.get("limit") || "20");
|
||||
const source = url.searchParams.get("source");
|
||||
const status = url.searchParams.get("status");
|
||||
const skip = (page - 1) * limit;
|
||||
|
||||
// Get user and workspace in one query
|
||||
const user = await prisma.user.findUnique({
|
||||
where: { id: userId },
|
||||
select: { Workspace: { select: { id: true } } },
|
||||
});
|
||||
|
||||
if (!user?.Workspace) {
|
||||
throw new Response("Workspace not found", { status: 404 });
|
||||
}
|
||||
|
||||
// Build where clause for filtering
|
||||
const whereClause: any = {
|
||||
workspaceId: user.Workspace.id,
|
||||
};
|
||||
|
||||
if (status) {
|
||||
whereClause.status = status;
|
||||
}
|
||||
|
||||
// If source filter is provided, filter by integration source
|
||||
if (source) {
|
||||
whereClause.activity = {
|
||||
integrationAccount: {
|
||||
integrationDefinition: {
|
||||
slug: source,
|
||||
},
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
// Use select to fetch only required fields for logs
|
||||
const [logs, totalCount, availableSources] = await Promise.all([
|
||||
prisma.ingestionQueue.findMany({
|
||||
where: whereClause,
|
||||
select: {
|
||||
id: true,
|
||||
createdAt: true,
|
||||
processedAt: true,
|
||||
status: true,
|
||||
error: true,
|
||||
data: true,
|
||||
activity: {
|
||||
select: {
|
||||
text: true,
|
||||
sourceURL: true,
|
||||
integrationAccount: {
|
||||
select: {
|
||||
integrationDefinition: {
|
||||
select: {
|
||||
name: true,
|
||||
slug: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
orderBy: {
|
||||
createdAt: "desc",
|
||||
},
|
||||
skip,
|
||||
take: limit,
|
||||
}),
|
||||
|
||||
prisma.ingestionQueue.count({
|
||||
where: whereClause,
|
||||
}),
|
||||
|
||||
prisma.integrationDefinitionV2.findMany({
|
||||
where: {
|
||||
IntegrationAccount: {
|
||||
some: {
|
||||
workspaceId: user.Workspace.id,
|
||||
},
|
||||
},
|
||||
},
|
||||
select: {
|
||||
name: true,
|
||||
slug: true,
|
||||
},
|
||||
}),
|
||||
]);
|
||||
|
||||
// Format the response
|
||||
const formattedLogs = logs.map((log) => {
|
||||
const integrationDef =
|
||||
log.activity?.integrationAccount?.integrationDefinition;
|
||||
const logData = log.data as any;
|
||||
return {
|
||||
id: log.id,
|
||||
source: integrationDef?.name || logData?.source || "Unknown",
|
||||
ingestText:
|
||||
log.activity?.text ||
|
||||
logData?.episodeBody ||
|
||||
logData?.text ||
|
||||
"No content",
|
||||
time: log.createdAt,
|
||||
processedAt: log.processedAt,
|
||||
status: log.status,
|
||||
error: log.error,
|
||||
sourceURL: log.activity?.sourceURL,
|
||||
integrationSlug: integrationDef?.slug,
|
||||
};
|
||||
});
|
||||
|
||||
return json({
|
||||
logs: formattedLogs,
|
||||
totalCount,
|
||||
page,
|
||||
limit,
|
||||
hasMore: skip + logs.length < totalCount,
|
||||
availableSources,
|
||||
});
|
||||
}
|
||||
@ -6,19 +6,33 @@ import { requireUserId, requireWorkpace } from "~/services/session.server";
|
||||
import { getIntegrationDefinitions } from "~/services/integrationDefinition.server";
|
||||
import { getIntegrationAccounts } from "~/services/integrationAccount.server";
|
||||
|
||||
import { Card, CardContent, CardDescription, CardFooter, CardHeader, CardTitle } from "~/components/ui/card";
|
||||
import {
|
||||
Card,
|
||||
CardContent,
|
||||
CardDescription,
|
||||
CardFooter,
|
||||
CardHeader,
|
||||
CardTitle,
|
||||
} from "~/components/ui/card";
|
||||
import { Button } from "~/components/ui/button";
|
||||
import { Dialog, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogTitle, DialogTrigger } from "~/components/ui/dialog";
|
||||
import {
|
||||
Dialog,
|
||||
DialogContent,
|
||||
DialogDescription,
|
||||
DialogFooter,
|
||||
DialogHeader,
|
||||
DialogTitle,
|
||||
DialogTrigger,
|
||||
} from "~/components/ui/dialog";
|
||||
import { Input } from "~/components/ui/input";
|
||||
import { FormButtons } from "~/components/ui/FormButtons";
|
||||
import { Plus, Search } from "lucide-react";
|
||||
import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "~/components/ui/select";
|
||||
|
||||
// Loader to fetch integration definitions and existing accounts
|
||||
export async function loader({ request }: LoaderFunctionArgs) {
|
||||
const userId = await requireUserId(request);
|
||||
const workspace = await requireWorkpace(request);
|
||||
|
||||
|
||||
const [integrationDefinitions, integrationAccounts] = await Promise.all([
|
||||
getIntegrationDefinitions(workspace.id),
|
||||
getIntegrationAccounts(userId),
|
||||
@ -32,46 +46,26 @@ export async function loader({ request }: LoaderFunctionArgs) {
|
||||
}
|
||||
|
||||
export default function Integrations() {
|
||||
const { integrationDefinitions, integrationAccounts, userId } = useLoaderData<typeof loader>();
|
||||
const [selectedCategory, setSelectedCategory] = useState<string>("all");
|
||||
const { integrationDefinitions, integrationAccounts, userId } =
|
||||
useLoaderData<typeof loader>();
|
||||
const [selectedIntegration, setSelectedIntegration] = useState<any>(null);
|
||||
const [apiKey, setApiKey] = useState("");
|
||||
const [isLoading, setIsLoading] = useState(false);
|
||||
const [isConnecting, setIsConnecting] = useState(false);
|
||||
|
||||
// Extract categories from integration definitions
|
||||
const categories = Array.from(
|
||||
new Set(integrationDefinitions.map((integration) => {
|
||||
const specData = typeof integration.spec === 'string'
|
||||
? JSON.parse(integration.spec)
|
||||
: integration.spec;
|
||||
return specData?.category || "Uncategorized";
|
||||
}))
|
||||
);
|
||||
|
||||
// Filter integrations by selected category
|
||||
const filteredIntegrations = selectedCategory === "all"
|
||||
? integrationDefinitions
|
||||
: integrationDefinitions.filter(
|
||||
(integration) => {
|
||||
const specData = typeof integration.spec === 'string'
|
||||
? JSON.parse(integration.spec)
|
||||
: integration.spec;
|
||||
return specData?.category === selectedCategory;
|
||||
}
|
||||
);
|
||||
|
||||
// Check if user has an active account for an integration
|
||||
const hasActiveAccount = (integrationDefinitionId: string) => {
|
||||
return integrationAccounts.some(
|
||||
(account) => account.integrationDefinitionId === integrationDefinitionId && account.isActive
|
||||
(account) =>
|
||||
account.integrationDefinitionId === integrationDefinitionId &&
|
||||
account.isActive,
|
||||
);
|
||||
};
|
||||
|
||||
// Handle connection with API key
|
||||
const handleApiKeyConnect = async () => {
|
||||
if (!selectedIntegration || !apiKey.trim()) return;
|
||||
|
||||
|
||||
setIsLoading(true);
|
||||
try {
|
||||
const response = await fetch("/api/v1/integration_account", {
|
||||
@ -84,12 +78,12 @@ export default function Integrations() {
|
||||
apiKey,
|
||||
}),
|
||||
});
|
||||
|
||||
|
||||
if (!response.ok) {
|
||||
const errorData = await response.json();
|
||||
throw new Error(errorData.error || "Failed to connect integration");
|
||||
}
|
||||
|
||||
|
||||
// Refresh the page to show the new integration account
|
||||
window.location.reload();
|
||||
} catch (error) {
|
||||
@ -103,7 +97,7 @@ export default function Integrations() {
|
||||
// Handle OAuth connection
|
||||
const handleOAuthConnect = async () => {
|
||||
if (!selectedIntegration) return;
|
||||
|
||||
|
||||
setIsConnecting(true);
|
||||
try {
|
||||
const response = await fetch("/api/v1/oauth", {
|
||||
@ -116,12 +110,12 @@ export default function Integrations() {
|
||||
userId,
|
||||
}),
|
||||
});
|
||||
|
||||
|
||||
if (!response.ok) {
|
||||
const errorData = await response.json();
|
||||
throw new Error(errorData.error || "Failed to start OAuth flow");
|
||||
}
|
||||
|
||||
|
||||
const { url } = await response.json();
|
||||
// Redirect to OAuth authorization URL
|
||||
window.location.href = url;
|
||||
@ -134,117 +128,93 @@ export default function Integrations() {
|
||||
};
|
||||
|
||||
return (
|
||||
<div className="home flex h-full flex-col overflow-y-auto p-3">
|
||||
<div className="flex items-center justify-between">
|
||||
<div className="space-y-1 text-base">
|
||||
<h2 className="text-lg font-semibold">Integrations</h2>
|
||||
<p className="text-muted-foreground">Connect your tools and services</p>
|
||||
</div>
|
||||
<div className="flex items-center gap-2">
|
||||
{/* Category filter */}
|
||||
<Select
|
||||
value={selectedCategory}
|
||||
onValueChange={setSelectedCategory}
|
||||
>
|
||||
<SelectTrigger className="w-[180px]">
|
||||
<SelectValue placeholder="Category" />
|
||||
</SelectTrigger>
|
||||
<SelectContent>
|
||||
<SelectItem value="all">All Categories</SelectItem>
|
||||
{categories.map((category) => (
|
||||
<SelectItem key={category} value={category}>{category}</SelectItem>
|
||||
))}
|
||||
</SelectContent>
|
||||
</Select>
|
||||
|
||||
{/* Add integration button */}
|
||||
<Button variant="default" size="sm">
|
||||
<Plus className="mr-1 h-3.5 w-3.5" />
|
||||
Add integration
|
||||
</Button>
|
||||
</div>
|
||||
<div className="home flex h-full flex-col overflow-y-auto p-4 px-5">
|
||||
<div className="space-y-1 text-base">
|
||||
<p className="text-muted-foreground">Connect your tools and services</p>
|
||||
</div>
|
||||
|
||||
|
||||
{/* Integration cards grid */}
|
||||
<div className="mt-6 grid grid-cols-1 gap-4 sm:grid-cols-2 md:grid-cols-3 lg:grid-cols-4 xl:grid-cols-5">
|
||||
{filteredIntegrations.map((integration) => {
|
||||
{integrationDefinitions.map((integration) => {
|
||||
const isConnected = hasActiveAccount(integration.id);
|
||||
const authType = integration.spec?.auth?.type || "unknown";
|
||||
|
||||
|
||||
return (
|
||||
<Dialog key={integration.id} onOpenChange={(open) => {
|
||||
if (open) {
|
||||
setSelectedIntegration(integration);
|
||||
setApiKey("");
|
||||
} else {
|
||||
setSelectedIntegration(null);
|
||||
}
|
||||
}}>
|
||||
<Dialog
|
||||
key={integration.id}
|
||||
onOpenChange={(open) => {
|
||||
if (open) {
|
||||
setSelectedIntegration(integration);
|
||||
setApiKey("");
|
||||
} else {
|
||||
setSelectedIntegration(null);
|
||||
}
|
||||
}}
|
||||
>
|
||||
<DialogTrigger asChild>
|
||||
<Card className="cursor-pointer transition-all hover:shadow-md">
|
||||
<CardHeader className="p-4">
|
||||
<div className="mb-2 flex h-10 w-10 items-center justify-center rounded bg-background-2">
|
||||
<div className="bg-background-2 mb-2 flex h-10 w-10 items-center justify-center rounded">
|
||||
{integration.icon ? (
|
||||
<img
|
||||
src={integration.icon}
|
||||
alt={integration.name}
|
||||
className="h-6 w-6"
|
||||
<img
|
||||
src={integration.icon}
|
||||
alt={integration.name}
|
||||
className="h-6 w-6"
|
||||
/>
|
||||
) : (
|
||||
<div className="h-6 w-6 rounded-full bg-gray-300" />
|
||||
)}
|
||||
</div>
|
||||
<CardTitle className="text-base">{integration.name}</CardTitle>
|
||||
<CardTitle className="text-base">
|
||||
{integration.name}
|
||||
</CardTitle>
|
||||
<CardDescription className="line-clamp-2 text-xs">
|
||||
{integration.description || "Connect to " + integration.name}
|
||||
{integration.description ||
|
||||
"Connect to " + integration.name}
|
||||
</CardDescription>
|
||||
</CardHeader>
|
||||
<CardFooter className="border-t p-3">
|
||||
<div className="flex w-full items-center justify-between">
|
||||
<span className="text-xs text-muted-foreground">
|
||||
{(() => {
|
||||
const specData = typeof integration.spec === 'string'
|
||||
? JSON.parse(integration.spec)
|
||||
: integration.spec;
|
||||
return specData?.category || "Uncategorized";
|
||||
})()}
|
||||
</span>
|
||||
<div className="flex w-full items-center justify-end">
|
||||
{isConnected ? (
|
||||
<span className="rounded-full bg-green-100 px-2 py-0.5 text-xs text-green-800">
|
||||
Connected
|
||||
</span>
|
||||
) : (
|
||||
<span className="text-xs text-muted-foreground">Not connected</span>
|
||||
<span className="text-muted-foreground text-xs">
|
||||
Not connected
|
||||
</span>
|
||||
)}
|
||||
</div>
|
||||
</CardFooter>
|
||||
</Card>
|
||||
</DialogTrigger>
|
||||
|
||||
|
||||
<DialogContent className="sm:max-w-md">
|
||||
<DialogHeader>
|
||||
<DialogTitle>Connect to {integration.name}</DialogTitle>
|
||||
<DialogDescription>
|
||||
{integration.description || `Connect your ${integration.name} account to enable integration.`}
|
||||
{integration.description ||
|
||||
`Connect your ${integration.name} account to enable integration.`}
|
||||
</DialogDescription>
|
||||
</DialogHeader>
|
||||
|
||||
|
||||
{/* API Key Authentication */}
|
||||
{(() => {
|
||||
const specData = typeof integration.spec === 'string'
|
||||
? JSON.parse(integration.spec)
|
||||
: integration.spec;
|
||||
const specData =
|
||||
typeof integration.spec === "string"
|
||||
? JSON.parse(integration.spec)
|
||||
: integration.spec;
|
||||
return specData?.auth?.api_key;
|
||||
})() && (
|
||||
<div className="space-y-4 py-4">
|
||||
<div className="space-y-2">
|
||||
<label htmlFor="apiKey" className="text-sm font-medium">
|
||||
{(() => {
|
||||
const specData = typeof integration.spec === 'string'
|
||||
? JSON.parse(integration.spec)
|
||||
: integration.spec;
|
||||
return specData?.auth?.api_key?.label || "API Key";
|
||||
})()}
|
||||
const specData =
|
||||
typeof integration.spec === "string"
|
||||
? JSON.parse(integration.spec)
|
||||
: integration.spec;
|
||||
return specData?.auth?.api_key?.label || "API Key";
|
||||
})()}
|
||||
</label>
|
||||
<Input
|
||||
id="apiKey"
|
||||
@ -254,40 +224,45 @@ export default function Integrations() {
|
||||
onChange={(e) => setApiKey(e.target.value)}
|
||||
/>
|
||||
{(() => {
|
||||
const specData = typeof integration.spec === 'string'
|
||||
? JSON.parse(integration.spec)
|
||||
: integration.spec;
|
||||
const specData =
|
||||
typeof integration.spec === "string"
|
||||
? JSON.parse(integration.spec)
|
||||
: integration.spec;
|
||||
return specData?.auth?.api_key?.description;
|
||||
})() && (
|
||||
<p className="text-xs text-muted-foreground">
|
||||
<p className="text-muted-foreground text-xs">
|
||||
{(() => {
|
||||
const specData = typeof integration.spec === 'string'
|
||||
? JSON.parse(integration.spec)
|
||||
: integration.spec;
|
||||
const specData =
|
||||
typeof integration.spec === "string"
|
||||
? JSON.parse(integration.spec)
|
||||
: integration.spec;
|
||||
return specData?.auth?.api_key?.description;
|
||||
})()}
|
||||
</p>
|
||||
)}
|
||||
</div>
|
||||
|
||||
<FormButtons>
|
||||
<Button
|
||||
type="button"
|
||||
variant="default"
|
||||
disabled={isLoading || !apiKey.trim()}
|
||||
onClick={handleApiKeyConnect}
|
||||
>
|
||||
{isLoading ? "Connecting..." : "Connect"}
|
||||
</Button>
|
||||
</FormButtons>
|
||||
|
||||
<FormButtons
|
||||
confirmButton={
|
||||
<Button
|
||||
type="button"
|
||||
variant="default"
|
||||
disabled={isLoading || !apiKey.trim()}
|
||||
onClick={handleApiKeyConnect}
|
||||
>
|
||||
{isLoading ? "Connecting..." : "Connect"}
|
||||
</Button>
|
||||
}
|
||||
></FormButtons>
|
||||
</div>
|
||||
)}
|
||||
|
||||
|
||||
{/* OAuth Authentication */}
|
||||
{(() => {
|
||||
const specData = typeof integration.spec === 'string'
|
||||
? JSON.parse(integration.spec)
|
||||
: integration.spec;
|
||||
const specData =
|
||||
typeof integration.spec === "string"
|
||||
? JSON.parse(integration.spec)
|
||||
: integration.spec;
|
||||
return specData?.auth?.oauth2;
|
||||
})() && (
|
||||
<div className="flex justify-center py-8">
|
||||
@ -298,26 +273,30 @@ export default function Integrations() {
|
||||
disabled={isConnecting}
|
||||
onClick={handleOAuthConnect}
|
||||
>
|
||||
{isConnecting ? "Connecting..." : `Connect to ${integration.name}`}
|
||||
{isConnecting
|
||||
? "Connecting..."
|
||||
: `Connect to ${integration.name}`}
|
||||
</Button>
|
||||
</div>
|
||||
)}
|
||||
|
||||
|
||||
{/* No authentication method found */}
|
||||
{(() => {
|
||||
const specData = typeof integration.spec === 'string'
|
||||
? JSON.parse(integration.spec)
|
||||
: integration.spec;
|
||||
const specData =
|
||||
typeof integration.spec === "string"
|
||||
? JSON.parse(integration.spec)
|
||||
: integration.spec;
|
||||
return !specData?.auth?.api_key && !specData?.auth?.oauth2;
|
||||
})() && (
|
||||
<div className="py-4 text-center text-muted-foreground">
|
||||
<div className="text-muted-foreground py-4 text-center">
|
||||
This integration doesn't specify an authentication method.
|
||||
</div>
|
||||
)}
|
||||
|
||||
|
||||
<DialogFooter className="sm:justify-start">
|
||||
<div className="w-full text-xs text-muted-foreground">
|
||||
By connecting, you agree to the {integration.name} terms of service.
|
||||
<div className="text-muted-foreground w-full text-xs">
|
||||
By connecting, you agree to the {integration.name} terms of
|
||||
service.
|
||||
</div>
|
||||
</DialogFooter>
|
||||
</DialogContent>
|
||||
@ -325,19 +304,14 @@ export default function Integrations() {
|
||||
);
|
||||
})}
|
||||
</div>
|
||||
|
||||
|
||||
{/* Empty state */}
|
||||
{filteredIntegrations.length === 0 && (
|
||||
{integrationDefinitions.length === 0 && (
|
||||
<div className="mt-20 flex flex-col items-center justify-center">
|
||||
<Search className="mb-2 h-12 w-12 text-muted-foreground" />
|
||||
<Search className="text-muted-foreground mb-2 h-12 w-12" />
|
||||
<h3 className="text-lg font-medium">No integrations found</h3>
|
||||
<p className="text-muted-foreground">
|
||||
{selectedCategory === "all"
|
||||
? "No integrations are available at this time."
|
||||
: `No integrations found in the "${selectedCategory}" category.`}
|
||||
</p>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
116
apps/webapp/app/routes/home.logs.activity.tsx
Normal file
116
apps/webapp/app/routes/home.logs.activity.tsx
Normal file
@ -0,0 +1,116 @@
|
||||
import { useState } from "react";
|
||||
import { useLogs } from "~/hooks/use-logs";
|
||||
import { LogsFilters } from "~/components/logs/logs-filters";
|
||||
import { VirtualLogsList } from "~/components/logs/virtual-logs-list";
|
||||
import { AppContainer, PageContainer, PageBody } from "~/components/layout/app-layout";
|
||||
import { Card, CardContent, CardHeader, CardTitle } from "~/components/ui/card";
|
||||
import { Badge } from "~/components/ui/badge";
|
||||
import { Activity } from "lucide-react";
|
||||
|
||||
export default function LogsActivity() {
|
||||
const [selectedSource, setSelectedSource] = useState<string | undefined>();
|
||||
const [selectedStatus, setSelectedStatus] = useState<string | undefined>();
|
||||
|
||||
const {
|
||||
logs,
|
||||
hasMore,
|
||||
loadMore,
|
||||
availableSources,
|
||||
isLoading,
|
||||
isInitialLoad
|
||||
} = useLogs({
|
||||
endpoint: '/api/v1/logs/activity',
|
||||
source: selectedSource,
|
||||
status: selectedStatus
|
||||
});
|
||||
|
||||
if (isInitialLoad) {
|
||||
return (
|
||||
<AppContainer>
|
||||
<PageContainer>
|
||||
<div className="flex items-center justify-center h-64">
|
||||
<div className="animate-spin rounded-full h-8 w-8 border-b-2 border-primary"></div>
|
||||
</div>
|
||||
</PageContainer>
|
||||
</AppContainer>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<AppContainer>
|
||||
<PageContainer>
|
||||
<PageBody>
|
||||
<div className="space-y-6">
|
||||
{/* Header */}
|
||||
<div className="flex items-center justify-between">
|
||||
<div className="flex items-center gap-3">
|
||||
<Activity className="h-6 w-6 text-primary" />
|
||||
<div>
|
||||
<h1 className="text-2xl font-bold">Activity Ingestion Logs</h1>
|
||||
<p className="text-muted-foreground">
|
||||
View ingestion logs for activities from connected integrations
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
<Badge variant="outline" className="text-sm">
|
||||
{logs.length} activity logs loaded
|
||||
</Badge>
|
||||
</div>
|
||||
|
||||
{/* Filters */}
|
||||
<Card>
|
||||
<CardHeader>
|
||||
<CardTitle className="text-lg">Filters</CardTitle>
|
||||
</CardHeader>
|
||||
<CardContent>
|
||||
<LogsFilters
|
||||
availableSources={availableSources}
|
||||
selectedSource={selectedSource}
|
||||
selectedStatus={selectedStatus}
|
||||
onSourceChange={setSelectedSource}
|
||||
onStatusChange={setSelectedStatus}
|
||||
/>
|
||||
</CardContent>
|
||||
</Card>
|
||||
|
||||
{/* Logs List */}
|
||||
<div className="space-y-4">
|
||||
<div className="flex items-center justify-between">
|
||||
<h2 className="text-lg font-semibold">Activity Ingestion Queue</h2>
|
||||
{hasMore && (
|
||||
<span className="text-sm text-muted-foreground">
|
||||
Scroll to load more...
|
||||
</span>
|
||||
)}
|
||||
</div>
|
||||
|
||||
{logs.length === 0 ? (
|
||||
<Card>
|
||||
<CardContent className="flex items-center justify-center py-16">
|
||||
<div className="text-center">
|
||||
<Activity className="h-12 w-12 text-muted-foreground mx-auto mb-4" />
|
||||
<h3 className="text-lg font-semibold mb-2">No activity logs found</h3>
|
||||
<p className="text-muted-foreground">
|
||||
{selectedSource || selectedStatus
|
||||
? 'Try adjusting your filters to see more results.'
|
||||
: 'No activity ingestion logs are available yet.'}
|
||||
</p>
|
||||
</div>
|
||||
</CardContent>
|
||||
</Card>
|
||||
) : (
|
||||
<VirtualLogsList
|
||||
logs={logs}
|
||||
hasMore={hasMore}
|
||||
loadMore={loadMore}
|
||||
isLoading={isLoading}
|
||||
height={600}
|
||||
/>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
</PageBody>
|
||||
</PageContainer>
|
||||
</AppContainer>
|
||||
);
|
||||
}
|
||||
102
apps/webapp/app/routes/home.logs.all.tsx
Normal file
102
apps/webapp/app/routes/home.logs.all.tsx
Normal file
@ -0,0 +1,102 @@
|
||||
import { useState } from "react";
|
||||
import { useLogs } from "~/hooks/use-logs";
|
||||
import { LogsFilters } from "~/components/logs/logs-filters";
|
||||
import { VirtualLogsList } from "~/components/logs/virtual-logs-list";
|
||||
import {
|
||||
AppContainer,
|
||||
PageContainer,
|
||||
PageBody,
|
||||
} from "~/components/layout/app-layout";
|
||||
import { Card, CardContent, CardHeader, CardTitle } from "~/components/ui/card";
|
||||
import { Badge } from "~/components/ui/badge";
|
||||
import { Database } from "lucide-react";
|
||||
|
||||
export default function LogsAll() {
|
||||
const [selectedSource, setSelectedSource] = useState<string | undefined>();
|
||||
const [selectedStatus, setSelectedStatus] = useState<string | undefined>();
|
||||
|
||||
const {
|
||||
logs,
|
||||
hasMore,
|
||||
loadMore,
|
||||
availableSources,
|
||||
isLoading,
|
||||
isInitialLoad,
|
||||
} = useLogs({
|
||||
endpoint: "/api/v1/logs/all",
|
||||
source: selectedSource,
|
||||
status: selectedStatus,
|
||||
});
|
||||
|
||||
if (isInitialLoad) {
|
||||
return (
|
||||
<AppContainer>
|
||||
<PageContainer>
|
||||
<div className="flex h-64 items-center justify-center">
|
||||
<div className="border-primary h-8 w-8 animate-spin rounded-full border-b-2"></div>
|
||||
</div>
|
||||
</PageContainer>
|
||||
</AppContainer>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="space-y-6 p-4 px-5">
|
||||
{/* Header */}
|
||||
<div className="flex items-center justify-between">
|
||||
<div className="flex items-center gap-3">
|
||||
<div>
|
||||
<p className="text-muted-foreground">
|
||||
View all ingestion queue items and their processing status
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Filters */}
|
||||
<LogsFilters
|
||||
availableSources={availableSources}
|
||||
selectedSource={selectedSource}
|
||||
selectedStatus={selectedStatus}
|
||||
onSourceChange={setSelectedSource}
|
||||
onStatusChange={setSelectedStatus}
|
||||
/>
|
||||
|
||||
{/* Logs List */}
|
||||
<div className="space-y-4">
|
||||
<div className="flex items-center justify-between">
|
||||
<h2 className="text-lg font-semibold">Ingestion Queue</h2>
|
||||
{hasMore && (
|
||||
<span className="text-muted-foreground text-sm">
|
||||
Scroll to load more...
|
||||
</span>
|
||||
)}
|
||||
</div>
|
||||
|
||||
{logs.length === 0 ? (
|
||||
<Card>
|
||||
<CardContent className="flex items-center justify-center py-16">
|
||||
<div className="text-center">
|
||||
<Database className="text-muted-foreground mx-auto mb-4 h-12 w-12" />
|
||||
<h3 className="mb-2 text-lg font-semibold">No logs found</h3>
|
||||
<p className="text-muted-foreground">
|
||||
{selectedSource || selectedStatus
|
||||
? "Try adjusting your filters to see more results."
|
||||
: "No ingestion logs are available yet."}
|
||||
</p>
|
||||
</div>
|
||||
</CardContent>
|
||||
</Card>
|
||||
) : (
|
||||
<VirtualLogsList
|
||||
logs={logs}
|
||||
hasMore={hasMore}
|
||||
loadMore={loadMore}
|
||||
isLoading={isLoading}
|
||||
height={600}
|
||||
/>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
@ -80,6 +80,7 @@
|
||||
"class-validator": "0.14.1",
|
||||
"class-variance-authority": "^0.7.1",
|
||||
"clsx": "^2.1.1",
|
||||
"cmdk": "^0.2.1",
|
||||
"compression": "^1.7.4",
|
||||
"cross-env": "^7.0.3",
|
||||
"d3": "^7.9.0",
|
||||
|
||||
@ -0,0 +1,5 @@
|
||||
-- AlterTable
|
||||
ALTER TABLE "IngestionQueue" ADD COLUMN "activityId" TEXT;
|
||||
|
||||
-- AddForeignKey
|
||||
ALTER TABLE "IngestionQueue" ADD CONSTRAINT "IngestionQueue_activityId_fkey" FOREIGN KEY ("activityId") REFERENCES "Activity"("id") ON DELETE SET NULL ON UPDATE CASCADE;
|
||||
@ -31,6 +31,7 @@ model Activity {
|
||||
WebhookDeliveryLog WebhookDeliveryLog[]
|
||||
|
||||
ConversationHistory ConversationHistory[]
|
||||
IngestionQueue IngestionQueue[]
|
||||
}
|
||||
|
||||
model AuthorizationCode {
|
||||
@ -136,6 +137,9 @@ model IngestionQueue {
|
||||
workspaceId String
|
||||
workspace Workspace @relation(fields: [workspaceId], references: [id])
|
||||
|
||||
activity Activity? @relation(fields: [activityId], references: [id])
|
||||
activityId String?
|
||||
|
||||
// Error handling
|
||||
error String?
|
||||
retryCount Int @default(0)
|
||||
|
||||
405
pnpm-lock.yaml
generated
405
pnpm-lock.yaml
generated
@ -234,6 +234,9 @@ importers:
|
||||
clsx:
|
||||
specifier: ^2.1.1
|
||||
version: 2.1.1
|
||||
cmdk:
|
||||
specifier: ^0.2.1
|
||||
version: 0.2.1(@types/react@18.2.69)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
|
||||
compression:
|
||||
specifier: ^1.7.4
|
||||
version: 1.8.0
|
||||
@ -378,7 +381,7 @@ importers:
|
||||
devDependencies:
|
||||
'@remix-run/dev':
|
||||
specifier: 2.16.7
|
||||
version: 2.16.7(@remix-run/react@2.16.7(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.8.3))(@remix-run/serve@2.16.7(typescript@5.8.3))(@types/node@20.19.7)(jiti@2.4.2)(lightningcss@1.30.1)(terser@5.42.0)(typescript@5.8.3)(vite@6.3.5(@types/node@20.19.7)(jiti@2.4.2)(lightningcss@1.30.1)(terser@5.42.0)(yaml@2.8.0))(yaml@2.8.0)
|
||||
version: 2.16.7(@remix-run/react@2.16.7(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.8.3))(@remix-run/serve@2.16.7(typescript@5.8.3))(@types/node@22.16.0)(jiti@2.4.2)(lightningcss@1.30.1)(terser@5.42.0)(typescript@5.8.3)(vite@6.3.5(@types/node@22.16.0)(jiti@2.4.2)(lightningcss@1.30.1)(terser@5.42.0)(yaml@2.8.0))(yaml@2.8.0)
|
||||
'@remix-run/eslint-config':
|
||||
specifier: 2.16.7
|
||||
version: 2.16.7(eslint@8.57.1)(react@18.3.1)(typescript@5.8.3)
|
||||
@ -393,7 +396,7 @@ importers:
|
||||
version: 0.5.16(tailwindcss@4.1.7)
|
||||
'@tailwindcss/vite':
|
||||
specifier: ^4.1.7
|
||||
version: 4.1.9(vite@6.3.5(@types/node@20.19.7)(jiti@2.4.2)(lightningcss@1.30.1)(terser@5.42.0)(yaml@2.8.0))
|
||||
version: 4.1.9(vite@6.3.5(@types/node@22.16.0)(jiti@2.4.2)(lightningcss@1.30.1)(terser@5.42.0)(yaml@2.8.0))
|
||||
'@trigger.dev/build':
|
||||
specifier: ^4.0.0-v4-beta.22
|
||||
version: 4.0.0-v4-beta.22(typescript@5.8.3)
|
||||
@ -489,10 +492,10 @@ importers:
|
||||
version: 5.8.3
|
||||
vite:
|
||||
specifier: ^6.0.0
|
||||
version: 6.3.5(@types/node@20.19.7)(jiti@2.4.2)(lightningcss@1.30.1)(terser@5.42.0)(yaml@2.8.0)
|
||||
version: 6.3.5(@types/node@22.16.0)(jiti@2.4.2)(lightningcss@1.30.1)(terser@5.42.0)(yaml@2.8.0)
|
||||
vite-tsconfig-paths:
|
||||
specifier: ^4.2.1
|
||||
version: 4.3.2(typescript@5.8.3)(vite@6.3.5(@types/node@20.19.7)(jiti@2.4.2)(lightningcss@1.30.1)(terser@5.42.0)(yaml@2.8.0))
|
||||
version: 4.3.2(typescript@5.8.3)(vite@6.3.5(@types/node@22.16.0)(jiti@2.4.2)(lightningcss@1.30.1)(terser@5.42.0)(yaml@2.8.0))
|
||||
|
||||
packages/database:
|
||||
dependencies:
|
||||
@ -547,6 +550,40 @@ importers:
|
||||
specifier: 18.2.69
|
||||
version: 18.2.69
|
||||
|
||||
packages/mcp:
|
||||
dependencies:
|
||||
'@modelcontextprotocol/sdk':
|
||||
specifier: 1.0.1
|
||||
version: 1.0.1
|
||||
'@types/node':
|
||||
specifier: ^22.14.1
|
||||
version: 22.16.0
|
||||
'@types/uuid':
|
||||
specifier: ^10.0.0
|
||||
version: 10.0.0
|
||||
axios:
|
||||
specifier: ^1.8.4
|
||||
version: 1.10.0
|
||||
dotenv:
|
||||
specifier: ^16.5.0
|
||||
version: 16.5.0
|
||||
uuid:
|
||||
specifier: ^11.1.0
|
||||
version: 11.1.0
|
||||
zod:
|
||||
specifier: ^3.24.3
|
||||
version: 3.25.76
|
||||
zod-to-json-schema:
|
||||
specifier: ^3.24.5
|
||||
version: 3.24.5(zod@3.25.76)
|
||||
devDependencies:
|
||||
shx:
|
||||
specifier: ^0.3.4
|
||||
version: 0.3.4
|
||||
typescript:
|
||||
specifier: ^5.8.3
|
||||
version: 5.8.3
|
||||
|
||||
packages/mcp-proxy:
|
||||
dependencies:
|
||||
'@modelcontextprotocol/sdk':
|
||||
@ -1790,6 +1827,9 @@ packages:
|
||||
'@mjackson/headers@0.9.0':
|
||||
resolution: {integrity: sha512-1WFCu2iRaqbez9hcYYI611vcH1V25R+fDfOge/CyKc8sdbzniGfy/FRhNd3DgvFF4ZEEX2ayBrvFHLtOpfvadw==}
|
||||
|
||||
'@modelcontextprotocol/sdk@1.0.1':
|
||||
resolution: {integrity: sha512-slLdFaxQJ9AlRg+hw28iiTtGvShAOgOKXcD0F91nUcRYiOMuS9ZBYjcdNZRXW9G5JQ511GRTdUy1zQVZDpJ+4w==}
|
||||
|
||||
'@modelcontextprotocol/sdk@1.13.2':
|
||||
resolution: {integrity: sha512-Vx7qOcmoKkR3qhaQ9qf3GxiVKCEu+zfJddHv6x3dY/9P6+uIwJnmuAur5aB+4FDXf41rRrDnOEGkviX5oYZ67w==}
|
||||
engines: {node: '>=18'}
|
||||
@ -2139,6 +2179,9 @@ packages:
|
||||
'@radix-ui/number@1.1.1':
|
||||
resolution: {integrity: sha512-MkKCwxlXTgz6CFoJx3pCwn07GKp36+aZyu/u2Ln2VrA5DcdyCZkASEDBTd8x5whTQQL5CiYf4prXKLcgQdv29g==}
|
||||
|
||||
'@radix-ui/primitive@1.0.0':
|
||||
resolution: {integrity: sha512-3e7rn8FDMin4CgeL7Z/49smCA3rFYY3Ha2rUQ7HRWFadS5iCRw08ZgVT1LaNTCNqgvrUiyczLflrVrF0SRQtNA==}
|
||||
|
||||
'@radix-ui/primitive@1.1.0':
|
||||
resolution: {integrity: sha512-4Z8dn6Upk0qk4P74xBhZ6Hd/w0mPEzOOLxy4xiPXOXqjF7jZS0VAKk7/x/H6FyY2zCkYJqePf1G5KmkmNJ4RBA==}
|
||||
|
||||
@ -2275,6 +2318,11 @@ packages:
|
||||
'@types/react-dom':
|
||||
optional: true
|
||||
|
||||
'@radix-ui/react-compose-refs@1.0.0':
|
||||
resolution: {integrity: sha512-0KaSv6sx787/hK3eF53iOkiSLwAGlFMx5lotrqD2pTjB18KbybKoEIgkNZTKC60YECDQTKGTRcDBILwZVqVKvA==}
|
||||
peerDependencies:
|
||||
react: ^16.8 || ^17.0 || ^18.0
|
||||
|
||||
'@radix-ui/react-compose-refs@1.0.1':
|
||||
resolution: {integrity: sha512-fDSBgd44FKHa1FRMU59qBMPFcl2PZE+2nmqunj+BWFyYYjnhIDWL2ItDs3rrbJDQOtzt5nIebLCQc4QRfz6LJw==}
|
||||
peerDependencies:
|
||||
@ -2302,6 +2350,11 @@ packages:
|
||||
'@types/react':
|
||||
optional: true
|
||||
|
||||
'@radix-ui/react-context@1.0.0':
|
||||
resolution: {integrity: sha512-1pVM9RfOQ+n/N5PJK33kRSKsr1glNxomxONs5c49MliinBY6Yw2Q995qfBUUo0/Mbg05B/sGA0gkgPI7kmSHBg==}
|
||||
peerDependencies:
|
||||
react: ^16.8 || ^17.0 || ^18.0
|
||||
|
||||
'@radix-ui/react-context@1.1.0':
|
||||
resolution: {integrity: sha512-OKrckBy+sMEgYM/sMmqmErVn0kZqrHPJze+Ql3DzYsDDp0hl0L62nx/2122/Bvps1qz645jlcu2tD9lrRSdf8A==}
|
||||
peerDependencies:
|
||||
@ -2320,6 +2373,12 @@ packages:
|
||||
'@types/react':
|
||||
optional: true
|
||||
|
||||
'@radix-ui/react-dialog@1.0.0':
|
||||
resolution: {integrity: sha512-Yn9YU+QlHYLWwV1XfKiqnGVpWYWk6MeBVM6x/bcoyPvxgjQGoeT35482viLPctTMWoMw0PoHgqfSox7Ig+957Q==}
|
||||
peerDependencies:
|
||||
react: ^16.8 || ^17.0 || ^18.0
|
||||
react-dom: ^16.8 || ^17.0 || ^18.0
|
||||
|
||||
'@radix-ui/react-dialog@1.1.14':
|
||||
resolution: {integrity: sha512-+CpweKjqpzTmwRwcYECQcNYbI8V9VSQt0SNFKeEBLgfucbsLssU6Ppq7wUdNXEGb573bMjFhVjKVll8rmV6zMw==}
|
||||
peerDependencies:
|
||||
@ -2351,6 +2410,12 @@ packages:
|
||||
'@types/react':
|
||||
optional: true
|
||||
|
||||
'@radix-ui/react-dismissable-layer@1.0.0':
|
||||
resolution: {integrity: sha512-n7kDRfx+LB1zLueRDvZ1Pd0bxdJWDUZNQ/GWoxDn2prnuJKRdxsjulejX/ePkOsLi2tTm6P24mDqlMSgQpsT6g==}
|
||||
peerDependencies:
|
||||
react: ^16.8 || ^17.0 || ^18.0
|
||||
react-dom: ^16.8 || ^17.0 || ^18.0
|
||||
|
||||
'@radix-ui/react-dismissable-layer@1.1.0':
|
||||
resolution: {integrity: sha512-/UovfmmXGptwGcBQawLzvn2jOfM0t4z3/uKffoBlj724+n3FvBbZ7M0aaBOmkp6pqFYpO4yx8tSVJjx3Fl2jig==}
|
||||
peerDependencies:
|
||||
@ -2390,6 +2455,11 @@ packages:
|
||||
'@types/react-dom':
|
||||
optional: true
|
||||
|
||||
'@radix-ui/react-focus-guards@1.0.0':
|
||||
resolution: {integrity: sha512-UagjDk4ijOAnGu4WMUPj9ahi7/zJJqNZ9ZAiGPp7waUWJO0O1aWXi/udPphI0IUjvrhBsZJGSN66dR2dsueLWQ==}
|
||||
peerDependencies:
|
||||
react: ^16.8 || ^17.0 || ^18.0
|
||||
|
||||
'@radix-ui/react-focus-guards@1.1.0':
|
||||
resolution: {integrity: sha512-w6XZNUPVv6xCpZUqb/yN9DL6auvpGX3C/ee6Hdi16v2UUy25HV2Q5bcflsiDyT/g5RwbPQ/GIT1vLkeRb+ITBw==}
|
||||
peerDependencies:
|
||||
@ -2408,6 +2478,12 @@ packages:
|
||||
'@types/react':
|
||||
optional: true
|
||||
|
||||
'@radix-ui/react-focus-scope@1.0.0':
|
||||
resolution: {integrity: sha512-C4SWtsULLGf/2L4oGeIHlvWQx7Rf+7cX/vKOAD2dXW0A1b5QXwi3wWeaEgW+wn+SEVrraMUk05vLU9fZZz5HbQ==}
|
||||
peerDependencies:
|
||||
react: ^16.8 || ^17.0 || ^18.0
|
||||
react-dom: ^16.8 || ^17.0 || ^18.0
|
||||
|
||||
'@radix-ui/react-focus-scope@1.1.0':
|
||||
resolution: {integrity: sha512-200UD8zylvEyL8Bx+z76RJnASR2gRMuxlgFCPAe/Q/679a/r0eK3MBVYMb7vZODZcffZBdob1EGnky78xmVvcA==}
|
||||
peerDependencies:
|
||||
@ -2439,6 +2515,11 @@ packages:
|
||||
peerDependencies:
|
||||
react: ^16.x || ^17.x || ^18.x || ^19.0.0 || ^19.0.0-rc
|
||||
|
||||
'@radix-ui/react-id@1.0.0':
|
||||
resolution: {integrity: sha512-Q6iAB/U7Tq3NTolBBQbHTgclPmGWE3OlktGGqrClPozSw4vkQ1DfQAOtzgRPecKsMdJINE05iaoDUG8tRzCBjw==}
|
||||
peerDependencies:
|
||||
react: ^16.8 || ^17.0 || ^18.0
|
||||
|
||||
'@radix-ui/react-id@1.1.0':
|
||||
resolution: {integrity: sha512-EJUrI8yYh7WOjNOqpoJaf1jlFIH2LvtgAl+YcFqNCa+4hj64ZXmPkAKOFs/ukjz3byN6bdb/AVUqHkI8/uWWMA==}
|
||||
peerDependencies:
|
||||
@ -2535,6 +2616,12 @@ packages:
|
||||
'@types/react-dom':
|
||||
optional: true
|
||||
|
||||
'@radix-ui/react-portal@1.0.0':
|
||||
resolution: {integrity: sha512-a8qyFO/Xb99d8wQdu4o7qnigNjTPG123uADNecz0eX4usnQEj7o+cG4ZX4zkqq98NYekT7UoEQIjxBNWIFuqTA==}
|
||||
peerDependencies:
|
||||
react: ^16.8 || ^17.0 || ^18.0
|
||||
react-dom: ^16.8 || ^17.0 || ^18.0
|
||||
|
||||
'@radix-ui/react-portal@1.1.1':
|
||||
resolution: {integrity: sha512-A3UtLk85UtqhzFqtoC8Q0KvR2GbXF3mtPgACSazajqq6A41mEQgo53iPzY4i6BwDxlIFqWIhiQ2G729n+2aw/g==}
|
||||
peerDependencies:
|
||||
@ -2561,6 +2648,12 @@ packages:
|
||||
'@types/react-dom':
|
||||
optional: true
|
||||
|
||||
'@radix-ui/react-presence@1.0.0':
|
||||
resolution: {integrity: sha512-A+6XEvN01NfVWiKu38ybawfHsBjWum42MRPnEuqPsBZ4eV7e/7K321B5VgYMPv3Xx5An6o1/l9ZuDBgmcmWK3w==}
|
||||
peerDependencies:
|
||||
react: ^16.8 || ^17.0 || ^18.0
|
||||
react-dom: ^16.8 || ^17.0 || ^18.0
|
||||
|
||||
'@radix-ui/react-presence@1.1.0':
|
||||
resolution: {integrity: sha512-Gq6wuRN/asf9H/E/VzdKoUtT8GC9PQc9z40/vEr0VCJ4u5XvvhWIrSsCB6vD2/cH7ugTdSfYq9fLJCcM00acrQ==}
|
||||
peerDependencies:
|
||||
@ -2587,6 +2680,12 @@ packages:
|
||||
'@types/react-dom':
|
||||
optional: true
|
||||
|
||||
'@radix-ui/react-primitive@1.0.0':
|
||||
resolution: {integrity: sha512-EyXe6mnRlHZ8b6f4ilTDrXmkLShICIuOTTj0GX4w1rp+wSxf3+TD05u1UOITC8VsJ2a9nwHvdXtOXEOl0Cw/zQ==}
|
||||
peerDependencies:
|
||||
react: ^16.8 || ^17.0 || ^18.0
|
||||
react-dom: ^16.8 || ^17.0 || ^18.0
|
||||
|
||||
'@radix-ui/react-primitive@2.0.0':
|
||||
resolution: {integrity: sha512-ZSpFm0/uHa8zTvKBDjLFWLo8dkr4MBsiDLz0g3gMUwqgLHz9rTaRRGYDgvZPtBJgYCBKXkS9fzmoySgr8CO6Cw==}
|
||||
peerDependencies:
|
||||
@ -2678,6 +2777,11 @@ packages:
|
||||
'@types/react-dom':
|
||||
optional: true
|
||||
|
||||
'@radix-ui/react-slot@1.0.0':
|
||||
resolution: {integrity: sha512-3mrKauI/tWXo1Ll+gN5dHcxDPdm/Df1ufcDLCecn+pnCIVcdWE7CujXo8QaXOWRJyZyQWWbpB8eFwHzWXlv5mQ==}
|
||||
peerDependencies:
|
||||
react: ^16.8 || ^17.0 || ^18.0
|
||||
|
||||
'@radix-ui/react-slot@1.0.2':
|
||||
resolution: {integrity: sha512-YeTpuq4deV+6DusvVUW4ivBgnkHwECUu0BiN43L5UCDFgdhsRUWAghhTF5MbvNTPzmiFOx90asDSUjWuCNapwg==}
|
||||
peerDependencies:
|
||||
@ -2796,6 +2900,11 @@ packages:
|
||||
'@types/react-dom':
|
||||
optional: true
|
||||
|
||||
'@radix-ui/react-use-callback-ref@1.0.0':
|
||||
resolution: {integrity: sha512-GZtyzoHz95Rhs6S63D2t/eqvdFCm7I+yHMLVQheKM7nBD8mbZIt+ct1jz4536MDnaOGKIxynJ8eHTkVGVVkoTg==}
|
||||
peerDependencies:
|
||||
react: ^16.8 || ^17.0 || ^18.0
|
||||
|
||||
'@radix-ui/react-use-callback-ref@1.1.0':
|
||||
resolution: {integrity: sha512-CasTfvsy+frcFkbXtSJ2Zu9JHpN8TYKxkgJGWbjiZhFivxaeW7rMeZt7QELGVLaYVfFMsKHjb7Ak0nMEe+2Vfw==}
|
||||
peerDependencies:
|
||||
@ -2814,6 +2923,11 @@ packages:
|
||||
'@types/react':
|
||||
optional: true
|
||||
|
||||
'@radix-ui/react-use-controllable-state@1.0.0':
|
||||
resolution: {integrity: sha512-FohDoZvk3mEXh9AWAVyRTYR4Sq7/gavuofglmiXB2g1aKyboUD4YtgWxKj8O5n+Uak52gXQ4wKz5IFST4vtJHg==}
|
||||
peerDependencies:
|
||||
react: ^16.8 || ^17.0 || ^18.0
|
||||
|
||||
'@radix-ui/react-use-controllable-state@1.1.0':
|
||||
resolution: {integrity: sha512-MtfMVJiSr2NjzS0Aa90NPTnvTSg6C/JLCV7ma0W6+OMV78vd8OyRpID+Ng9LxzsPbLeuBnWBA1Nq30AtBIDChw==}
|
||||
peerDependencies:
|
||||
@ -2841,6 +2955,11 @@ packages:
|
||||
'@types/react':
|
||||
optional: true
|
||||
|
||||
'@radix-ui/react-use-escape-keydown@1.0.0':
|
||||
resolution: {integrity: sha512-JwfBCUIfhXRxKExgIqGa4CQsiMemo1Xt0W/B4ei3fpzpvPENKpMKQ8mZSB6Acj3ebrAEgi2xiQvcI1PAAodvyg==}
|
||||
peerDependencies:
|
||||
react: ^16.8 || ^17.0 || ^18.0
|
||||
|
||||
'@radix-ui/react-use-escape-keydown@1.1.0':
|
||||
resolution: {integrity: sha512-L7vwWlR1kTTQ3oh7g1O0CBF3YCyyTj8NmhLR+phShpyA50HCfBFKVJTpshm9PzLiKmehsrQzTYTpX9HvmC9rhw==}
|
||||
peerDependencies:
|
||||
@ -2868,6 +2987,11 @@ packages:
|
||||
'@types/react':
|
||||
optional: true
|
||||
|
||||
'@radix-ui/react-use-layout-effect@1.0.0':
|
||||
resolution: {integrity: sha512-6Tpkq+R6LOlmQb1R5NNETLG0B4YP0wc+klfXafpUCj6JGyaUc8il7/kUZ7m59rGbXGczE9Bs+iz2qloqsZBduQ==}
|
||||
peerDependencies:
|
||||
react: ^16.8 || ^17.0 || ^18.0
|
||||
|
||||
'@radix-ui/react-use-layout-effect@1.1.0':
|
||||
resolution: {integrity: sha512-+FPE0rOdziWSrH9athwI1R0HDVbWlEhd+FR+aSDk4uWGmSJ9Z54sdZVDQPZAinJhJXwfT+qnj969mCsT2gfm5w==}
|
||||
peerDependencies:
|
||||
@ -4310,6 +4434,9 @@ packages:
|
||||
'@types/use-sync-external-store@0.0.6':
|
||||
resolution: {integrity: sha512-zFDAD+tlpf2r4asuHEj0XH6pY6i0g5NeAHPn+15wk3BV6JA69eERFXC1gyGThDkVa1zCyKr5jox1+2LbV/AMLg==}
|
||||
|
||||
'@types/uuid@10.0.0':
|
||||
resolution: {integrity: sha512-7gqG38EyHgyP1S+7+xomFtL+ZNHcKv6DwNaCZmJmo1vgMugyF3TCnXVg4t1uk89mLNwnLtnY3TpOpCOyp1/xHQ==}
|
||||
|
||||
'@types/uuid@9.0.8':
|
||||
resolution: {integrity: sha512-jg+97EGIcY9AGHJJRaaPVgetKDsrTgbRjQ5Msgjh/DQKEFl0DtyRr/VCOyD1T2R1MNeWPK/u7JoGhlDZnKBAfA==}
|
||||
|
||||
@ -5077,6 +5204,12 @@ packages:
|
||||
resolution: {integrity: sha512-RMr0FhtfXemyinomL4hrWcYJxmX6deFdCxpJzhDttxgO1+bcCnkk+9drydLVDmAMG7NE6aN/fl4F7ucU/90gAA==}
|
||||
engines: {node: '>=0.10.0'}
|
||||
|
||||
cmdk@0.2.1:
|
||||
resolution: {integrity: sha512-U6//9lQ6JvT47+6OF6Gi8BvkxYQ8SCRRSKIJkthIMsFsLZRG0cKvTtuTaefyIKMQb8rvvXy0wGdpTNq/jPtm+g==}
|
||||
peerDependencies:
|
||||
react: ^18.0.0
|
||||
react-dom: ^18.0.0
|
||||
|
||||
cmdk@1.1.1:
|
||||
resolution: {integrity: sha512-Vsv7kFaXm+ptHDMZ7izaRsP70GgrW9NBNGswt9OZaVBLlE0SNpDq8eu/VGXyF9r7M0azK3Wy7OlYXsuyYLFzHg==}
|
||||
peerDependencies:
|
||||
@ -6576,6 +6709,10 @@ packages:
|
||||
resolution: {integrity: sha512-5Hh7Y1wQbvY5ooGgPbDaL5iYLAPzMTUrjMulskHLH6wnv/A+1q5rgEaiuqEjB+oxGXIVZs1FF+R/KPN3ZSQYYg==}
|
||||
engines: {node: '>=12'}
|
||||
|
||||
interpret@1.4.0:
|
||||
resolution: {integrity: sha512-agE4QfB2Lkp9uICn7BAqoscw4SZP9kTE2hxiFI3jBPmXJfdqiahTbUuKGsMoN2GtqL9AxhYioAcVvgsb1HvRbA==}
|
||||
engines: {node: '>= 0.10'}
|
||||
|
||||
ioredis@5.6.1:
|
||||
resolution: {integrity: sha512-UxC0Yv1Y4WRJiGQxQkP0hfdL0/5/6YvdfOOClRgJ0qppSarkhneSa6UvkMkms0AkdGimSH3Ikqm+6mkMmX7vGA==}
|
||||
engines: {node: '>=12.22.0'}
|
||||
@ -8544,6 +8681,16 @@ packages:
|
||||
'@types/react':
|
||||
optional: true
|
||||
|
||||
react-remove-scroll@2.5.4:
|
||||
resolution: {integrity: sha512-xGVKJJr0SJGQVirVFAUZ2k1QLyO6m+2fy0l8Qawbp5Jgrv3DeLalrfMNBFSlmz5kriGGzsVBtGVnf4pTKIhhWA==}
|
||||
engines: {node: '>=10'}
|
||||
peerDependencies:
|
||||
'@types/react': ^16.8.0 || ^17.0.0 || ^18.0.0
|
||||
react: ^16.8.0 || ^17.0.0 || ^18.0.0
|
||||
peerDependenciesMeta:
|
||||
'@types/react':
|
||||
optional: true
|
||||
|
||||
react-remove-scroll@2.5.7:
|
||||
resolution: {integrity: sha512-FnrTWO4L7/Bhhf3CYBNArEG/yROV0tKmTv7/3h9QCFvH6sndeFf1wPqOcbFVu5VAulS5dV1wGT3GZZ/1GawqiA==}
|
||||
engines: {node: '>=10'}
|
||||
@ -8650,6 +8797,10 @@ packages:
|
||||
resolution: {integrity: sha512-GDhwkLfywWL2s6vEjyhri+eXmfH6j1L7JE27WhqLeYzoh/A3DBaYGEj2H/HFZCn/kMfim73FXxEJTw06WtxQwg==}
|
||||
engines: {node: '>= 14.18.0'}
|
||||
|
||||
rechoir@0.6.2:
|
||||
resolution: {integrity: sha512-HFM8rkZ+i3zrV+4LQjwQ0W+ez98pApMGM3HUrN04j3CqzPOzl9nmP15Y8YXNm8QHGv/eacOVEjqhmWpkRV0NAw==}
|
||||
engines: {node: '>= 0.10'}
|
||||
|
||||
redent@3.0.0:
|
||||
resolution: {integrity: sha512-6tDA8g98We0zd0GvVeMT9arEOnTw9qM03L9cJXaCjrip1OO764RDBLBfrB4cwzNGDj5OA5ioymC9GkizgWJDUg==}
|
||||
engines: {node: '>=8'}
|
||||
@ -8968,9 +9119,19 @@ packages:
|
||||
resolution: {integrity: sha512-ObmnIF4hXNg1BqhnHmgbDETF8dLPCggZWBjkQfhZpbszZnYur5DUljTcCHii5LC3J5E0yeO/1LIMyH+UvHQgyw==}
|
||||
engines: {node: '>= 0.4'}
|
||||
|
||||
shelljs@0.8.5:
|
||||
resolution: {integrity: sha512-TiwcRcrkhHvbrZbnRcFYMLl30Dfov3HKqzp5tO5b4pt6G/SezKcYhmDg15zXVBswHmctSAQKznqNW2LO5tTDow==}
|
||||
engines: {node: '>=4'}
|
||||
hasBin: true
|
||||
|
||||
shimmer@1.2.1:
|
||||
resolution: {integrity: sha512-sQTKC1Re/rM6XyFM6fIAGHRPVGvyXfgzIDvzoq608vM+jeyVD0Tu1E6Np0Kc2zAIFWIj963V2800iF/9LPieQw==}
|
||||
|
||||
shx@0.3.4:
|
||||
resolution: {integrity: sha512-N6A9MLVqjxZYcVn8hLmtneQWIJtp8IKzMP4eMnx+nqkvXoqinUPCbUFLp2UcWTEIUONhlk0ewxr/jaVGlc+J+g==}
|
||||
engines: {node: '>=6'}
|
||||
hasBin: true
|
||||
|
||||
side-channel-list@1.0.0:
|
||||
resolution: {integrity: sha512-FCLHtRD/gnpCiCHEiJLOwdmFP+wzCmDEkc9y7NsYxeF4u7Btsn1ZuwgwJGxImImHicJArLP4R0yX4c2KCrMrTA==}
|
||||
engines: {node: '>= 0.4'}
|
||||
@ -9753,6 +9914,10 @@ packages:
|
||||
resolution: {integrity: sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA==}
|
||||
engines: {node: '>= 0.4.0'}
|
||||
|
||||
uuid@11.1.0:
|
||||
resolution: {integrity: sha512-0/A9rDy9P7cJ+8w1c9WD9V//9Wj15Ce2MPz8Ri6032usz+NfePxx5AcN3bN+r6ZL6jEo066/yNYB3tn4pQEx+A==}
|
||||
hasBin: true
|
||||
|
||||
uuid@9.0.1:
|
||||
resolution: {integrity: sha512-b+1eJOlsR9K8HJpow9Ok3fiWOWSIcIzXodvv0rQjVoOVNpWMpxf1wZNpt4y9h10odCNrqnYp1OBzRktckBe3sA==}
|
||||
hasBin: true
|
||||
@ -10089,6 +10254,9 @@ packages:
|
||||
zod@3.23.8:
|
||||
resolution: {integrity: sha512-XBx9AXhXktjUqnepgTiE5flcKIYWi/rme0Eaj+5Y0lftuGBq+jyRu/md4WnuxqgP1ubdpNCsYEYPxrzVHD8d6g==}
|
||||
|
||||
zod@3.25.76:
|
||||
resolution: {integrity: sha512-gzUt/qt81nXsFGKIFcC3YnfEAx5NkunCfnDlvuBSSFS02bcXu4Lmea0AFIUwbLWxWPx3d9p8S5QoaujKcNQxcQ==}
|
||||
|
||||
zustand@4.5.7:
|
||||
resolution: {integrity: sha512-CHOUy7mu3lbD6o6LJLfllpjkzhHXSBlX8B9+qPddUsIfeF5S/UZ5q0kmCsnRqT1UHFQZchNFDDzMbQsuesHWlw==}
|
||||
engines: {node: '>=12.7.0'}
|
||||
@ -11470,6 +11638,12 @@ snapshots:
|
||||
|
||||
'@mjackson/headers@0.9.0': {}
|
||||
|
||||
'@modelcontextprotocol/sdk@1.0.1':
|
||||
dependencies:
|
||||
content-type: 1.0.5
|
||||
raw-body: 3.0.0
|
||||
zod: 3.25.76
|
||||
|
||||
'@modelcontextprotocol/sdk@1.13.2':
|
||||
dependencies:
|
||||
ajv: 6.12.6
|
||||
@ -11832,6 +12006,10 @@ snapshots:
|
||||
|
||||
'@radix-ui/number@1.1.1': {}
|
||||
|
||||
'@radix-ui/primitive@1.0.0':
|
||||
dependencies:
|
||||
'@babel/runtime': 7.27.6
|
||||
|
||||
'@radix-ui/primitive@1.1.0': {}
|
||||
|
||||
'@radix-ui/primitive@1.1.2': {}
|
||||
@ -11970,6 +12148,11 @@ snapshots:
|
||||
'@types/react': 18.2.69
|
||||
'@types/react-dom': 18.3.7(@types/react@18.2.69)
|
||||
|
||||
'@radix-ui/react-compose-refs@1.0.0(react@18.3.1)':
|
||||
dependencies:
|
||||
'@babel/runtime': 7.27.6
|
||||
react: 18.3.1
|
||||
|
||||
'@radix-ui/react-compose-refs@1.0.1(@types/react@18.2.69)(react@18.3.1)':
|
||||
dependencies:
|
||||
'@babel/runtime': 7.27.6
|
||||
@ -11989,6 +12172,11 @@ snapshots:
|
||||
optionalDependencies:
|
||||
'@types/react': 18.2.69
|
||||
|
||||
'@radix-ui/react-context@1.0.0(react@18.3.1)':
|
||||
dependencies:
|
||||
'@babel/runtime': 7.27.6
|
||||
react: 18.3.1
|
||||
|
||||
'@radix-ui/react-context@1.1.0(@types/react@18.2.47)(react@18.3.1)':
|
||||
dependencies:
|
||||
react: 18.3.1
|
||||
@ -12001,6 +12189,28 @@ snapshots:
|
||||
optionalDependencies:
|
||||
'@types/react': 18.2.69
|
||||
|
||||
'@radix-ui/react-dialog@1.0.0(@types/react@18.2.69)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)':
|
||||
dependencies:
|
||||
'@babel/runtime': 7.27.6
|
||||
'@radix-ui/primitive': 1.0.0
|
||||
'@radix-ui/react-compose-refs': 1.0.0(react@18.3.1)
|
||||
'@radix-ui/react-context': 1.0.0(react@18.3.1)
|
||||
'@radix-ui/react-dismissable-layer': 1.0.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
|
||||
'@radix-ui/react-focus-guards': 1.0.0(react@18.3.1)
|
||||
'@radix-ui/react-focus-scope': 1.0.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
|
||||
'@radix-ui/react-id': 1.0.0(react@18.3.1)
|
||||
'@radix-ui/react-portal': 1.0.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
|
||||
'@radix-ui/react-presence': 1.0.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
|
||||
'@radix-ui/react-primitive': 1.0.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
|
||||
'@radix-ui/react-slot': 1.0.0(react@18.3.1)
|
||||
'@radix-ui/react-use-controllable-state': 1.0.0(react@18.3.1)
|
||||
aria-hidden: 1.2.6
|
||||
react: 18.3.1
|
||||
react-dom: 18.3.1(react@18.3.1)
|
||||
react-remove-scroll: 2.5.4(@types/react@18.2.69)(react@18.3.1)
|
||||
transitivePeerDependencies:
|
||||
- '@types/react'
|
||||
|
||||
'@radix-ui/react-dialog@1.1.14(@types/react-dom@18.3.7(@types/react@18.2.69))(@types/react@18.2.69)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)':
|
||||
dependencies:
|
||||
'@radix-ui/primitive': 1.1.2
|
||||
@ -12035,6 +12245,17 @@ snapshots:
|
||||
optionalDependencies:
|
||||
'@types/react': 18.2.69
|
||||
|
||||
'@radix-ui/react-dismissable-layer@1.0.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1)':
|
||||
dependencies:
|
||||
'@babel/runtime': 7.27.6
|
||||
'@radix-ui/primitive': 1.0.0
|
||||
'@radix-ui/react-compose-refs': 1.0.0(react@18.3.1)
|
||||
'@radix-ui/react-primitive': 1.0.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
|
||||
'@radix-ui/react-use-callback-ref': 1.0.0(react@18.3.1)
|
||||
'@radix-ui/react-use-escape-keydown': 1.0.0(react@18.3.1)
|
||||
react: 18.3.1
|
||||
react-dom: 18.3.1(react@18.3.1)
|
||||
|
||||
'@radix-ui/react-dismissable-layer@1.1.0(@types/react-dom@18.3.7(@types/react@18.2.47))(@types/react@18.2.47)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)':
|
||||
dependencies:
|
||||
'@radix-ui/primitive': 1.1.0
|
||||
@ -12076,6 +12297,11 @@ snapshots:
|
||||
'@types/react': 18.2.69
|
||||
'@types/react-dom': 18.3.7(@types/react@18.2.69)
|
||||
|
||||
'@radix-ui/react-focus-guards@1.0.0(react@18.3.1)':
|
||||
dependencies:
|
||||
'@babel/runtime': 7.27.6
|
||||
react: 18.3.1
|
||||
|
||||
'@radix-ui/react-focus-guards@1.1.0(@types/react@18.2.47)(react@18.3.1)':
|
||||
dependencies:
|
||||
react: 18.3.1
|
||||
@ -12088,6 +12314,15 @@ snapshots:
|
||||
optionalDependencies:
|
||||
'@types/react': 18.2.69
|
||||
|
||||
'@radix-ui/react-focus-scope@1.0.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1)':
|
||||
dependencies:
|
||||
'@babel/runtime': 7.27.6
|
||||
'@radix-ui/react-compose-refs': 1.0.0(react@18.3.1)
|
||||
'@radix-ui/react-primitive': 1.0.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
|
||||
'@radix-ui/react-use-callback-ref': 1.0.0(react@18.3.1)
|
||||
react: 18.3.1
|
||||
react-dom: 18.3.1(react@18.3.1)
|
||||
|
||||
'@radix-ui/react-focus-scope@1.1.0(@types/react-dom@18.3.7(@types/react@18.2.47))(@types/react@18.2.47)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)':
|
||||
dependencies:
|
||||
'@radix-ui/react-compose-refs': 1.1.0(@types/react@18.2.47)(react@18.3.1)
|
||||
@ -12114,6 +12349,12 @@ snapshots:
|
||||
dependencies:
|
||||
react: 18.3.1
|
||||
|
||||
'@radix-ui/react-id@1.0.0(react@18.3.1)':
|
||||
dependencies:
|
||||
'@babel/runtime': 7.27.6
|
||||
'@radix-ui/react-use-layout-effect': 1.0.0(react@18.3.1)
|
||||
react: 18.3.1
|
||||
|
||||
'@radix-ui/react-id@1.1.0(@types/react@18.2.47)(react@18.3.1)':
|
||||
dependencies:
|
||||
'@radix-ui/react-use-layout-effect': 1.1.0(@types/react@18.2.47)(react@18.3.1)
|
||||
@ -12245,6 +12486,13 @@ snapshots:
|
||||
'@types/react': 18.2.69
|
||||
'@types/react-dom': 18.3.7(@types/react@18.2.69)
|
||||
|
||||
'@radix-ui/react-portal@1.0.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1)':
|
||||
dependencies:
|
||||
'@babel/runtime': 7.27.6
|
||||
'@radix-ui/react-primitive': 1.0.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
|
||||
react: 18.3.1
|
||||
react-dom: 18.3.1(react@18.3.1)
|
||||
|
||||
'@radix-ui/react-portal@1.1.1(@types/react-dom@18.3.7(@types/react@18.2.47))(@types/react@18.2.47)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)':
|
||||
dependencies:
|
||||
'@radix-ui/react-primitive': 2.0.0(@types/react-dom@18.3.7(@types/react@18.2.47))(@types/react@18.2.47)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
|
||||
@ -12265,6 +12513,14 @@ snapshots:
|
||||
'@types/react': 18.2.69
|
||||
'@types/react-dom': 18.3.7(@types/react@18.2.69)
|
||||
|
||||
'@radix-ui/react-presence@1.0.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1)':
|
||||
dependencies:
|
||||
'@babel/runtime': 7.27.6
|
||||
'@radix-ui/react-compose-refs': 1.0.0(react@18.3.1)
|
||||
'@radix-ui/react-use-layout-effect': 1.0.0(react@18.3.1)
|
||||
react: 18.3.1
|
||||
react-dom: 18.3.1(react@18.3.1)
|
||||
|
||||
'@radix-ui/react-presence@1.1.0(@types/react-dom@18.3.7(@types/react@18.2.47))(@types/react@18.2.47)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)':
|
||||
dependencies:
|
||||
'@radix-ui/react-compose-refs': 1.1.0(@types/react@18.2.47)(react@18.3.1)
|
||||
@ -12285,6 +12541,13 @@ snapshots:
|
||||
'@types/react': 18.2.69
|
||||
'@types/react-dom': 18.3.7(@types/react@18.2.69)
|
||||
|
||||
'@radix-ui/react-primitive@1.0.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1)':
|
||||
dependencies:
|
||||
'@babel/runtime': 7.27.6
|
||||
'@radix-ui/react-slot': 1.0.0(react@18.3.1)
|
||||
react: 18.3.1
|
||||
react-dom: 18.3.1(react@18.3.1)
|
||||
|
||||
'@radix-ui/react-primitive@2.0.0(@types/react-dom@18.3.7(@types/react@18.2.47))(@types/react@18.2.47)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)':
|
||||
dependencies:
|
||||
'@radix-ui/react-slot': 1.1.0(@types/react@18.2.47)(react@18.3.1)
|
||||
@ -12392,6 +12655,12 @@ snapshots:
|
||||
'@types/react': 18.2.69
|
||||
'@types/react-dom': 18.3.7(@types/react@18.2.69)
|
||||
|
||||
'@radix-ui/react-slot@1.0.0(react@18.3.1)':
|
||||
dependencies:
|
||||
'@babel/runtime': 7.27.6
|
||||
'@radix-ui/react-compose-refs': 1.0.0(react@18.3.1)
|
||||
react: 18.3.1
|
||||
|
||||
'@radix-ui/react-slot@1.0.2(@types/react@18.2.69)(react@18.3.1)':
|
||||
dependencies:
|
||||
'@babel/runtime': 7.27.6
|
||||
@ -12531,6 +12800,11 @@ snapshots:
|
||||
'@types/react': 18.2.69
|
||||
'@types/react-dom': 18.3.7(@types/react@18.2.69)
|
||||
|
||||
'@radix-ui/react-use-callback-ref@1.0.0(react@18.3.1)':
|
||||
dependencies:
|
||||
'@babel/runtime': 7.27.6
|
||||
react: 18.3.1
|
||||
|
||||
'@radix-ui/react-use-callback-ref@1.1.0(@types/react@18.2.47)(react@18.3.1)':
|
||||
dependencies:
|
||||
react: 18.3.1
|
||||
@ -12543,6 +12817,12 @@ snapshots:
|
||||
optionalDependencies:
|
||||
'@types/react': 18.2.69
|
||||
|
||||
'@radix-ui/react-use-controllable-state@1.0.0(react@18.3.1)':
|
||||
dependencies:
|
||||
'@babel/runtime': 7.27.6
|
||||
'@radix-ui/react-use-callback-ref': 1.0.0(react@18.3.1)
|
||||
react: 18.3.1
|
||||
|
||||
'@radix-ui/react-use-controllable-state@1.1.0(@types/react@18.2.47)(react@18.3.1)':
|
||||
dependencies:
|
||||
'@radix-ui/react-use-callback-ref': 1.1.0(@types/react@18.2.47)(react@18.3.1)
|
||||
@ -12565,6 +12845,12 @@ snapshots:
|
||||
optionalDependencies:
|
||||
'@types/react': 18.2.69
|
||||
|
||||
'@radix-ui/react-use-escape-keydown@1.0.0(react@18.3.1)':
|
||||
dependencies:
|
||||
'@babel/runtime': 7.27.6
|
||||
'@radix-ui/react-use-callback-ref': 1.0.0(react@18.3.1)
|
||||
react: 18.3.1
|
||||
|
||||
'@radix-ui/react-use-escape-keydown@1.1.0(@types/react@18.2.47)(react@18.3.1)':
|
||||
dependencies:
|
||||
'@radix-ui/react-use-callback-ref': 1.1.0(@types/react@18.2.47)(react@18.3.1)
|
||||
@ -12586,6 +12872,11 @@ snapshots:
|
||||
optionalDependencies:
|
||||
'@types/react': 18.2.69
|
||||
|
||||
'@radix-ui/react-use-layout-effect@1.0.0(react@18.3.1)':
|
||||
dependencies:
|
||||
'@babel/runtime': 7.27.6
|
||||
react: 18.3.1
|
||||
|
||||
'@radix-ui/react-use-layout-effect@1.1.0(@types/react@18.2.47)(react@18.3.1)':
|
||||
dependencies:
|
||||
react: 18.3.1
|
||||
@ -12791,7 +13082,7 @@ snapshots:
|
||||
transitivePeerDependencies:
|
||||
- encoding
|
||||
|
||||
'@remix-run/dev@2.16.7(@remix-run/react@2.16.7(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.8.3))(@remix-run/serve@2.16.7(typescript@5.8.3))(@types/node@20.19.7)(jiti@2.4.2)(lightningcss@1.30.1)(terser@5.42.0)(typescript@5.8.3)(vite@6.3.5(@types/node@20.19.7)(jiti@2.4.2)(lightningcss@1.30.1)(terser@5.42.0)(yaml@2.8.0))(yaml@2.8.0)':
|
||||
'@remix-run/dev@2.16.7(@remix-run/react@2.16.7(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.8.3))(@remix-run/serve@2.16.7(typescript@5.8.3))(@types/node@22.16.0)(jiti@2.4.2)(lightningcss@1.30.1)(terser@5.42.0)(typescript@5.8.3)(vite@6.3.5(@types/node@22.16.0)(jiti@2.4.2)(lightningcss@1.30.1)(terser@5.42.0)(yaml@2.8.0))(yaml@2.8.0)':
|
||||
dependencies:
|
||||
'@babel/core': 7.27.4
|
||||
'@babel/generator': 7.27.5
|
||||
@ -12808,7 +13099,7 @@ snapshots:
|
||||
'@remix-run/router': 1.23.0
|
||||
'@remix-run/server-runtime': 2.16.7(typescript@5.8.3)
|
||||
'@types/mdx': 2.0.13
|
||||
'@vanilla-extract/integration': 6.5.0(@types/node@20.19.7)(lightningcss@1.30.1)(terser@5.42.0)
|
||||
'@vanilla-extract/integration': 6.5.0(@types/node@22.16.0)(lightningcss@1.30.1)(terser@5.42.0)
|
||||
arg: 5.0.2
|
||||
cacache: 17.1.4
|
||||
chalk: 4.1.2
|
||||
@ -12848,12 +13139,12 @@ snapshots:
|
||||
tar-fs: 2.1.3
|
||||
tsconfig-paths: 4.2.0
|
||||
valibot: 0.41.0(typescript@5.8.3)
|
||||
vite-node: 3.2.3(@types/node@20.19.7)(jiti@2.4.2)(lightningcss@1.30.1)(terser@5.42.0)(yaml@2.8.0)
|
||||
vite-node: 3.2.3(@types/node@22.16.0)(jiti@2.4.2)(lightningcss@1.30.1)(terser@5.42.0)(yaml@2.8.0)
|
||||
ws: 7.5.10
|
||||
optionalDependencies:
|
||||
'@remix-run/serve': 2.16.7(typescript@5.8.3)
|
||||
typescript: 5.8.3
|
||||
vite: 6.3.5(@types/node@20.19.7)(jiti@2.4.2)(lightningcss@1.30.1)(terser@5.42.0)(yaml@2.8.0)
|
||||
vite: 6.3.5(@types/node@22.16.0)(jiti@2.4.2)(lightningcss@1.30.1)(terser@5.42.0)(yaml@2.8.0)
|
||||
transitivePeerDependencies:
|
||||
- '@types/node'
|
||||
- babel-plugin-macros
|
||||
@ -13592,12 +13883,12 @@ snapshots:
|
||||
postcss-selector-parser: 6.0.10
|
||||
tailwindcss: 4.1.7
|
||||
|
||||
'@tailwindcss/vite@4.1.9(vite@6.3.5(@types/node@20.19.7)(jiti@2.4.2)(lightningcss@1.30.1)(terser@5.42.0)(yaml@2.8.0))':
|
||||
'@tailwindcss/vite@4.1.9(vite@6.3.5(@types/node@22.16.0)(jiti@2.4.2)(lightningcss@1.30.1)(terser@5.42.0)(yaml@2.8.0))':
|
||||
dependencies:
|
||||
'@tailwindcss/node': 4.1.9
|
||||
'@tailwindcss/oxide': 4.1.9
|
||||
tailwindcss: 4.1.9
|
||||
vite: 6.3.5(@types/node@20.19.7)(jiti@2.4.2)(lightningcss@1.30.1)(terser@5.42.0)(yaml@2.8.0)
|
||||
vite: 6.3.5(@types/node@22.16.0)(jiti@2.4.2)(lightningcss@1.30.1)(terser@5.42.0)(yaml@2.8.0)
|
||||
|
||||
'@tanstack/react-table@8.21.3(react-dom@18.3.1(react@18.3.1))(react@18.3.1)':
|
||||
dependencies:
|
||||
@ -13947,7 +14238,7 @@ snapshots:
|
||||
'@types/body-parser@1.19.6':
|
||||
dependencies:
|
||||
'@types/connect': 3.4.38
|
||||
'@types/node': 18.19.115
|
||||
'@types/node': 22.16.0
|
||||
|
||||
'@types/compression@1.8.1':
|
||||
dependencies:
|
||||
@ -13958,7 +14249,7 @@ snapshots:
|
||||
|
||||
'@types/connect@3.4.38':
|
||||
dependencies:
|
||||
'@types/node': 18.19.115
|
||||
'@types/node': 22.16.0
|
||||
|
||||
'@types/cookie@0.4.1': {}
|
||||
|
||||
@ -13966,7 +14257,7 @@ snapshots:
|
||||
|
||||
'@types/cors@2.8.19':
|
||||
dependencies:
|
||||
'@types/node': 18.19.115
|
||||
'@types/node': 22.16.0
|
||||
|
||||
'@types/d3-array@3.2.1': {}
|
||||
|
||||
@ -14113,7 +14404,7 @@ snapshots:
|
||||
|
||||
'@types/express-serve-static-core@4.19.6':
|
||||
dependencies:
|
||||
'@types/node': 18.19.115
|
||||
'@types/node': 22.16.0
|
||||
'@types/qs': 6.14.0
|
||||
'@types/range-parser': 1.2.7
|
||||
'@types/send': 0.17.5
|
||||
@ -14234,12 +14525,12 @@ snapshots:
|
||||
'@types/send@0.17.5':
|
||||
dependencies:
|
||||
'@types/mime': 1.3.5
|
||||
'@types/node': 18.19.115
|
||||
'@types/node': 22.16.0
|
||||
|
||||
'@types/serve-static@1.15.8':
|
||||
dependencies:
|
||||
'@types/http-errors': 2.0.5
|
||||
'@types/node': 18.19.115
|
||||
'@types/node': 22.16.0
|
||||
'@types/send': 0.17.5
|
||||
|
||||
'@types/shimmer@1.2.0': {}
|
||||
@ -14254,13 +14545,15 @@ snapshots:
|
||||
|
||||
'@types/use-sync-external-store@0.0.6': {}
|
||||
|
||||
'@types/uuid@10.0.0': {}
|
||||
|
||||
'@types/uuid@9.0.8': {}
|
||||
|
||||
'@types/validator@13.15.2': {}
|
||||
|
||||
'@types/webpack@5.28.5(@swc/core@1.3.101(@swc/helpers@0.5.17))(esbuild@0.19.11)':
|
||||
dependencies:
|
||||
'@types/node': 18.19.115
|
||||
'@types/node': 22.16.0
|
||||
tapable: 2.2.2
|
||||
webpack: 5.99.9(@swc/core@1.3.101(@swc/helpers@0.5.17))(esbuild@0.19.11)
|
||||
transitivePeerDependencies:
|
||||
@ -14523,7 +14816,7 @@ snapshots:
|
||||
transitivePeerDependencies:
|
||||
- babel-plugin-macros
|
||||
|
||||
'@vanilla-extract/integration@6.5.0(@types/node@20.19.7)(lightningcss@1.30.1)(terser@5.42.0)':
|
||||
'@vanilla-extract/integration@6.5.0(@types/node@22.16.0)(lightningcss@1.30.1)(terser@5.42.0)':
|
||||
dependencies:
|
||||
'@babel/core': 7.27.4
|
||||
'@babel/plugin-syntax-typescript': 7.27.1(@babel/core@7.27.4)
|
||||
@ -14536,8 +14829,8 @@ snapshots:
|
||||
lodash: 4.17.21
|
||||
mlly: 1.7.4
|
||||
outdent: 0.8.0
|
||||
vite: 5.4.19(@types/node@20.19.7)(lightningcss@1.30.1)(terser@5.42.0)
|
||||
vite-node: 1.6.1(@types/node@20.19.7)(lightningcss@1.30.1)(terser@5.42.0)
|
||||
vite: 5.4.19(@types/node@22.16.0)(lightningcss@1.30.1)(terser@5.42.0)
|
||||
vite-node: 1.6.1(@types/node@22.16.0)(lightningcss@1.30.1)(terser@5.42.0)
|
||||
transitivePeerDependencies:
|
||||
- '@types/node'
|
||||
- babel-plugin-macros
|
||||
@ -15174,6 +15467,14 @@ snapshots:
|
||||
|
||||
cluster-key-slot@1.1.2: {}
|
||||
|
||||
cmdk@0.2.1(@types/react@18.2.69)(react-dom@18.3.1(react@18.3.1))(react@18.3.1):
|
||||
dependencies:
|
||||
'@radix-ui/react-dialog': 1.0.0(@types/react@18.2.69)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
|
||||
react: 18.3.1
|
||||
react-dom: 18.3.1(react@18.3.1)
|
||||
transitivePeerDependencies:
|
||||
- '@types/react'
|
||||
|
||||
cmdk@1.1.1(@types/react-dom@18.3.7(@types/react@18.2.69))(@types/react@18.2.69)(react-dom@18.3.1(react@18.3.1))(react@18.3.1):
|
||||
dependencies:
|
||||
'@radix-ui/react-compose-refs': 1.1.2(@types/react@18.2.69)(react@18.3.1)
|
||||
@ -15794,7 +16095,7 @@ snapshots:
|
||||
dependencies:
|
||||
'@types/cookie': 0.4.1
|
||||
'@types/cors': 2.8.19
|
||||
'@types/node': 18.19.115
|
||||
'@types/node': 22.16.0
|
||||
accepts: 1.3.8
|
||||
base64id: 2.0.0
|
||||
cookie: 0.4.2
|
||||
@ -16407,7 +16708,7 @@ snapshots:
|
||||
|
||||
eval@0.1.8:
|
||||
dependencies:
|
||||
'@types/node': 18.19.115
|
||||
'@types/node': 22.16.0
|
||||
require-like: 0.1.2
|
||||
|
||||
event-target-shim@5.0.1: {}
|
||||
@ -17092,6 +17393,8 @@ snapshots:
|
||||
|
||||
internmap@2.0.3: {}
|
||||
|
||||
interpret@1.4.0: {}
|
||||
|
||||
ioredis@5.6.1:
|
||||
dependencies:
|
||||
'@ioredis/commands': 1.2.0
|
||||
@ -17326,7 +17629,7 @@ snapshots:
|
||||
|
||||
jest-worker@27.5.1:
|
||||
dependencies:
|
||||
'@types/node': 18.19.115
|
||||
'@types/node': 22.16.0
|
||||
merge-stream: 2.0.0
|
||||
supports-color: 8.1.1
|
||||
|
||||
@ -19209,7 +19512,7 @@ snapshots:
|
||||
'@protobufjs/path': 1.1.2
|
||||
'@protobufjs/pool': 1.1.0
|
||||
'@protobufjs/utf8': 1.1.0
|
||||
'@types/node': 18.19.115
|
||||
'@types/node': 22.16.0
|
||||
long: 5.3.2
|
||||
|
||||
proxy-addr@2.0.7:
|
||||
@ -19416,6 +19719,17 @@ snapshots:
|
||||
optionalDependencies:
|
||||
'@types/react': 18.2.69
|
||||
|
||||
react-remove-scroll@2.5.4(@types/react@18.2.69)(react@18.3.1):
|
||||
dependencies:
|
||||
react: 18.3.1
|
||||
react-remove-scroll-bar: 2.3.8(@types/react@18.2.69)(react@18.3.1)
|
||||
react-style-singleton: 2.2.3(@types/react@18.2.69)(react@18.3.1)
|
||||
tslib: 2.8.1
|
||||
use-callback-ref: 1.3.3(@types/react@18.2.69)(react@18.3.1)
|
||||
use-sidecar: 1.1.3(@types/react@18.2.69)(react@18.3.1)
|
||||
optionalDependencies:
|
||||
'@types/react': 18.2.69
|
||||
|
||||
react-remove-scroll@2.5.7(@types/react@18.2.47)(react@18.3.1):
|
||||
dependencies:
|
||||
react: 18.3.1
|
||||
@ -19554,6 +19868,10 @@ snapshots:
|
||||
|
||||
readdirp@4.1.2: {}
|
||||
|
||||
rechoir@0.6.2:
|
||||
dependencies:
|
||||
resolve: 1.22.10
|
||||
|
||||
redent@3.0.0:
|
||||
dependencies:
|
||||
indent-string: 4.0.0
|
||||
@ -19956,8 +20274,19 @@ snapshots:
|
||||
|
||||
shell-quote@1.8.3: {}
|
||||
|
||||
shelljs@0.8.5:
|
||||
dependencies:
|
||||
glob: 7.2.3
|
||||
interpret: 1.4.0
|
||||
rechoir: 0.6.2
|
||||
|
||||
shimmer@1.2.1: {}
|
||||
|
||||
shx@0.3.4:
|
||||
dependencies:
|
||||
minimist: 1.2.8
|
||||
shelljs: 0.8.5
|
||||
|
||||
side-channel-list@1.0.0:
|
||||
dependencies:
|
||||
es-errors: 1.3.0
|
||||
@ -20920,6 +21249,8 @@ snapshots:
|
||||
|
||||
utils-merge@1.0.1: {}
|
||||
|
||||
uuid@11.1.0: {}
|
||||
|
||||
uuid@9.0.1: {}
|
||||
|
||||
uvu@0.5.6:
|
||||
@ -20966,13 +21297,13 @@ snapshots:
|
||||
'@types/unist': 3.0.3
|
||||
vfile-message: 4.0.2
|
||||
|
||||
vite-node@1.6.1(@types/node@20.19.7)(lightningcss@1.30.1)(terser@5.42.0):
|
||||
vite-node@1.6.1(@types/node@22.16.0)(lightningcss@1.30.1)(terser@5.42.0):
|
||||
dependencies:
|
||||
cac: 6.7.14
|
||||
debug: 4.4.1
|
||||
pathe: 1.1.2
|
||||
picocolors: 1.1.1
|
||||
vite: 5.4.19(@types/node@20.19.7)(lightningcss@1.30.1)(terser@5.42.0)
|
||||
vite: 5.4.19(@types/node@22.16.0)(lightningcss@1.30.1)(terser@5.42.0)
|
||||
transitivePeerDependencies:
|
||||
- '@types/node'
|
||||
- less
|
||||
@ -20984,13 +21315,13 @@ snapshots:
|
||||
- supports-color
|
||||
- terser
|
||||
|
||||
vite-node@3.2.3(@types/node@20.19.7)(jiti@2.4.2)(lightningcss@1.30.1)(terser@5.42.0)(yaml@2.8.0):
|
||||
vite-node@3.2.3(@types/node@22.16.0)(jiti@2.4.2)(lightningcss@1.30.1)(terser@5.42.0)(yaml@2.8.0):
|
||||
dependencies:
|
||||
cac: 6.7.14
|
||||
debug: 4.4.1
|
||||
es-module-lexer: 1.7.0
|
||||
pathe: 2.0.3
|
||||
vite: 6.3.5(@types/node@20.19.7)(jiti@2.4.2)(lightningcss@1.30.1)(terser@5.42.0)(yaml@2.8.0)
|
||||
vite: 6.3.5(@types/node@22.16.0)(jiti@2.4.2)(lightningcss@1.30.1)(terser@5.42.0)(yaml@2.8.0)
|
||||
transitivePeerDependencies:
|
||||
- '@types/node'
|
||||
- jiti
|
||||
@ -21005,29 +21336,29 @@ snapshots:
|
||||
- tsx
|
||||
- yaml
|
||||
|
||||
vite-tsconfig-paths@4.3.2(typescript@5.8.3)(vite@6.3.5(@types/node@20.19.7)(jiti@2.4.2)(lightningcss@1.30.1)(terser@5.42.0)(yaml@2.8.0)):
|
||||
vite-tsconfig-paths@4.3.2(typescript@5.8.3)(vite@6.3.5(@types/node@22.16.0)(jiti@2.4.2)(lightningcss@1.30.1)(terser@5.42.0)(yaml@2.8.0)):
|
||||
dependencies:
|
||||
debug: 4.4.1
|
||||
globrex: 0.1.2
|
||||
tsconfck: 3.1.6(typescript@5.8.3)
|
||||
optionalDependencies:
|
||||
vite: 6.3.5(@types/node@20.19.7)(jiti@2.4.2)(lightningcss@1.30.1)(terser@5.42.0)(yaml@2.8.0)
|
||||
vite: 6.3.5(@types/node@22.16.0)(jiti@2.4.2)(lightningcss@1.30.1)(terser@5.42.0)(yaml@2.8.0)
|
||||
transitivePeerDependencies:
|
||||
- supports-color
|
||||
- typescript
|
||||
|
||||
vite@5.4.19(@types/node@20.19.7)(lightningcss@1.30.1)(terser@5.42.0):
|
||||
vite@5.4.19(@types/node@22.16.0)(lightningcss@1.30.1)(terser@5.42.0):
|
||||
dependencies:
|
||||
esbuild: 0.21.5
|
||||
postcss: 8.5.5
|
||||
rollup: 4.43.0
|
||||
optionalDependencies:
|
||||
'@types/node': 20.19.7
|
||||
'@types/node': 22.16.0
|
||||
fsevents: 2.3.3
|
||||
lightningcss: 1.30.1
|
||||
terser: 5.42.0
|
||||
|
||||
vite@6.3.5(@types/node@20.19.7)(jiti@2.4.2)(lightningcss@1.30.1)(terser@5.42.0)(yaml@2.8.0):
|
||||
vite@6.3.5(@types/node@22.16.0)(jiti@2.4.2)(lightningcss@1.30.1)(terser@5.42.0)(yaml@2.8.0):
|
||||
dependencies:
|
||||
esbuild: 0.25.5
|
||||
fdir: 6.4.6(picomatch@4.0.2)
|
||||
@ -21036,7 +21367,7 @@ snapshots:
|
||||
rollup: 4.43.0
|
||||
tinyglobby: 0.2.14
|
||||
optionalDependencies:
|
||||
'@types/node': 20.19.7
|
||||
'@types/node': 22.16.0
|
||||
fsevents: 2.3.3
|
||||
jiti: 2.4.2
|
||||
lightningcss: 1.30.1
|
||||
@ -21293,12 +21624,18 @@ snapshots:
|
||||
dependencies:
|
||||
zod: 3.23.8
|
||||
|
||||
zod-to-json-schema@3.24.5(zod@3.25.76):
|
||||
dependencies:
|
||||
zod: 3.25.76
|
||||
|
||||
zod-validation-error@1.5.0(zod@3.23.8):
|
||||
dependencies:
|
||||
zod: 3.23.8
|
||||
|
||||
zod@3.23.8: {}
|
||||
|
||||
zod@3.25.76: {}
|
||||
|
||||
zustand@4.5.7(@types/react@18.2.69)(react@18.3.1):
|
||||
dependencies:
|
||||
use-sync-external-store: 1.5.0(react@18.3.1)
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user