claudmax 2.0.0 → 2.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/claudmax-1.0.16.tgz +0 -0
- package/{packages/cli/index.js → index.js} +2 -0
- package/package.json +27 -55
- package/.claude/settings.local.json +0 -7
- package/.env.example +0 -24
- package/.github/workflows/publish.yml +0 -31
- package/README.md +0 -178
- package/claudmax-mcp-1.0.2.tgz +0 -0
- package/help +0 -0
- package/help-wal +0 -0
- package/next-env.d.ts +0 -6
- package/next.config.mjs +0 -43
- package/packages/cli/claudmax-1.0.16.tgz +0 -0
- package/packages/cli/package.json +0 -33
- package/packages/mcp/claudmax-mcp-1.0.0.tgz +0 -0
- package/packages/mcp/claudmax-mcp-1.0.1.tgz +0 -0
- package/packages/mcp/claudmax-mcp-1.0.2.tgz +0 -0
- package/packages/mcp/claudmax-mcp-1.0.3.tgz +0 -0
- package/packages/mcp/index.js +0 -129
- package/packages/mcp/package-lock.json +0 -1146
- package/packages/mcp/package.json +0 -32
- package/postcss.config.mjs +0 -6
- package/prisma/schema.prisma +0 -130
- package/prisma/seed.ts +0 -27
- package/public/favicon.svg +0 -10
- package/public/robots.txt +0 -10
- package/run_build.sh +0 -4
- package/scripts/migrate-plans.js +0 -98
- package/scripts/seed-blog.ts +0 -1014
- package/src/app/admin/dashboard/AdminDashboardClient.tsx +0 -1546
- package/src/app/admin/dashboard/page.tsx +0 -13
- package/src/app/admin/page.tsx +0 -132
- package/src/app/api/admin/auth/me/route.ts +0 -34
- package/src/app/api/admin/health/route.ts +0 -110
- package/src/app/api/admin/keys/[id]/route.ts +0 -116
- package/src/app/api/admin/keys/route.ts +0 -192
- package/src/app/api/admin/keys-list/route.ts +0 -81
- package/src/app/api/admin/login/route.ts +0 -72
- package/src/app/api/admin/logout/route.ts +0 -8
- package/src/app/api/admin/migrate/route.ts +0 -133
- package/src/app/api/admin/plans/[id]/route.ts +0 -65
- package/src/app/api/admin/plans/route.ts +0 -66
- package/src/app/api/admin/posts/[id]/route.ts +0 -81
- package/src/app/api/admin/posts/route.ts +0 -83
- package/src/app/api/admin/seed/route.ts +0 -145
- package/src/app/api/admin/settings/route.ts +0 -44
- package/src/app/api/admin/stats/route.ts +0 -74
- package/src/app/api/admin/users/[id]/route.ts +0 -166
- package/src/app/api/admin/users/plans/route.ts +0 -45
- package/src/app/api/admin/users/route.ts +0 -202
- package/src/app/api/blog/[slug]/route.ts +0 -22
- package/src/app/api/blog/route.ts +0 -40
- package/src/app/api/cron/daily-status/route.ts +0 -208
- package/src/app/api/support/chat/route.ts +0 -55
- package/src/app/api/support/chat/session/route.ts +0 -62
- package/src/app/api/support/chat/stream/route.ts +0 -44
- package/src/app/api/support/email/route.ts +0 -63
- package/src/app/api/tools/understand_image/route.ts +0 -113
- package/src/app/api/tools/upload/route.ts +0 -179
- package/src/app/api/tools/web_search/route.ts +0 -99
- package/src/app/api/v1/audio/route.ts +0 -67
- package/src/app/api/v1/audio/speech/route.ts +0 -73
- package/src/app/api/v1/chat/completions/route.ts +0 -3
- package/src/app/api/v1/chat/route.ts +0 -1079
- package/src/app/api/v1/images/generations/route.ts +0 -93
- package/src/app/api/v1/info/route.ts +0 -30
- package/src/app/api/v1/key-status/route.ts +0 -109
- package/src/app/api/v1/key-status/stream/route.ts +0 -135
- package/src/app/api/v1/messages/count_tokens/route.ts +0 -22
- package/src/app/api/v1/messages/route.ts +0 -807
- package/src/app/api/v1/models/route.ts +0 -14
- package/src/app/api/v1/route.ts +0 -18
- package/src/app/blog/BlogClient.tsx +0 -193
- package/src/app/blog/[slug]/page.tsx +0 -117
- package/src/app/blog/page.tsx +0 -20
- package/src/app/check-usage/CheckUsageClient.tsx +0 -186
- package/src/app/check-usage/layout.tsx +0 -11
- package/src/app/check-usage/page.tsx +0 -15
- package/src/app/docs/layout.tsx +0 -16
- package/src/app/docs/page.tsx +0 -1055
- package/src/app/faq/FAQClient.tsx +0 -227
- package/src/app/faq/page.tsx +0 -21
- package/src/app/globals.css +0 -75
- package/src/app/layout.tsx +0 -80
- package/src/app/page.tsx +0 -256
- package/src/app/reseller/ResellerClient.tsx +0 -435
- package/src/app/reseller/page.tsx +0 -15
- package/src/app/setup.ps1/route.ts +0 -79
- package/src/app/setup.sh/route.ts +0 -113
- package/src/app/sitemap.ts +0 -50
- package/src/app/status/StatusClient.tsx +0 -103
- package/src/app/status/layout.tsx +0 -11
- package/src/app/status/page.tsx +0 -15
- package/src/app/support/SupportClient.tsx +0 -411
- package/src/app/support/page.tsx +0 -25
- package/src/app/v1/chat/completions/route.ts +0 -3
- package/src/app/v1/chat/route.ts +0 -4
- package/src/app/v1/messages/route.ts +0 -3
- package/src/components/Footer.tsx +0 -120
- package/src/components/Header.tsx +0 -131
- package/src/components/landing/features.tsx +0 -99
- package/src/components/ui/badge.tsx +0 -32
- package/src/components/ui/button.tsx +0 -46
- package/src/components/ui/card.tsx +0 -50
- package/src/components/ui/dialog.tsx +0 -97
- package/src/components/ui/dropdown-menu.tsx +0 -156
- package/src/components/ui/input.tsx +0 -21
- package/src/components/ui/label.tsx +0 -15
- package/src/components/ui/separator.tsx +0 -22
- package/src/components/ui/switch.tsx +0 -27
- package/src/components/ui/tabs.tsx +0 -51
- package/src/components/ui/toast.tsx +0 -103
- package/src/lib/auth.ts +0 -45
- package/src/lib/prisma.ts +0 -20
- package/src/lib/providers.ts +0 -158
- package/src/lib/security.ts +0 -165
- package/src/lib/utils.ts +0 -14
- package/src/middleware.ts +0 -30
- package/tailwind.config.ts +0 -53
- package/tsconfig.json +0 -41
- package/tsconfig.tsbuildinfo +0 -1
- package/vercel.json +0 -8
- /package/{packages/cli/bin → bin}/claudmax.js +0 -0
- /package/{packages/cli/claudmax-1.0.17.tgz → claudmax-1.0.17.tgz} +0 -0
|
@@ -1,156 +0,0 @@
|
|
|
1
|
-
'use client';
|
|
2
|
-
|
|
3
|
-
import * as React from 'react';
|
|
4
|
-
import * as DropdownMenuPrimitive from '@radix-ui/react-dropdown-menu';
|
|
5
|
-
import { Check, ChevronRight, Circle } from 'lucide-react';
|
|
6
|
-
import { cn } from '@/lib/utils';
|
|
7
|
-
|
|
8
|
-
const DropdownMenu = DropdownMenuPrimitive.Root;
|
|
9
|
-
const DropdownMenuTrigger = DropdownMenuPrimitive.Trigger;
|
|
10
|
-
const DropdownMenuGroup = DropdownMenuPrimitive.Group;
|
|
11
|
-
const DropdownMenuPortal = DropdownMenuPrimitive.Portal;
|
|
12
|
-
const DropdownMenuSub = DropdownMenuPrimitive.Sub;
|
|
13
|
-
const DropdownMenuRadioGroup = DropdownMenuPrimitive.RadioGroup;
|
|
14
|
-
|
|
15
|
-
const DropdownMenuSubTrigger = React.forwardRef<
|
|
16
|
-
React.ElementRef<typeof DropdownMenuPrimitive.SubTrigger>,
|
|
17
|
-
React.ComponentPropsWithoutRef<typeof DropdownMenuPrimitive.SubTrigger> & { inset?: boolean }
|
|
18
|
-
>(({ className, inset, children, ...props }, ref) => (
|
|
19
|
-
<DropdownMenuPrimitive.SubTrigger
|
|
20
|
-
ref={ref}
|
|
21
|
-
className={cn('flex cursor-default select-none items-center rounded-sm px-2 py-1.5 text-sm outline-none focus:bg-accent data-[state=open]:bg-accent', inset && 'pl-8', className)}
|
|
22
|
-
{...props}
|
|
23
|
-
>
|
|
24
|
-
{children}
|
|
25
|
-
<ChevronRight className="ml-auto h-4 w-4" />
|
|
26
|
-
</DropdownMenuPrimitive.SubTrigger>
|
|
27
|
-
));
|
|
28
|
-
DropdownMenuSubTrigger.displayName = DropdownMenuPrimitive.SubTrigger.displayName;
|
|
29
|
-
|
|
30
|
-
const DropdownMenuSubContent = React.forwardRef<
|
|
31
|
-
React.ElementRef<typeof DropdownMenuPrimitive.SubContent>,
|
|
32
|
-
React.ComponentPropsWithoutRef<typeof DropdownMenuPrimitive.SubContent>
|
|
33
|
-
>(({ className, ...props }, ref) => (
|
|
34
|
-
<DropdownMenuPrimitive.SubContent
|
|
35
|
-
ref={ref}
|
|
36
|
-
className={cn('z-50 min-w-[8rem] overflow-hidden rounded-md border bg-popover p-1 text-popover-foreground shadow-lg data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2', className)}
|
|
37
|
-
{...props}
|
|
38
|
-
/>
|
|
39
|
-
));
|
|
40
|
-
DropdownMenuSubContent.displayName = DropdownMenuPrimitive.SubContent.displayName;
|
|
41
|
-
|
|
42
|
-
const DropdownMenuContent = React.forwardRef<
|
|
43
|
-
React.ElementRef<typeof DropdownMenuPrimitive.Content>,
|
|
44
|
-
React.ComponentPropsWithoutRef<typeof DropdownMenuPrimitive.Content>
|
|
45
|
-
>(({ className, sideOffset = 4, ...props }, ref) => (
|
|
46
|
-
<DropdownMenuPrimitive.Portal>
|
|
47
|
-
<DropdownMenuPrimitive.Content
|
|
48
|
-
ref={ref}
|
|
49
|
-
sideOffset={sideOffset}
|
|
50
|
-
className={cn(
|
|
51
|
-
'z-50 min-w-[8rem] overflow-hidden rounded-xl border bg-popover p-1 text-popover-foreground shadow-xl backdrop-blur-xl data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2',
|
|
52
|
-
className
|
|
53
|
-
)}
|
|
54
|
-
{...props}
|
|
55
|
-
/>
|
|
56
|
-
</DropdownMenuPrimitive.Portal>
|
|
57
|
-
));
|
|
58
|
-
DropdownMenuContent.displayName = DropdownMenuPrimitive.Content.displayName;
|
|
59
|
-
|
|
60
|
-
const DropdownMenuItem = React.forwardRef<
|
|
61
|
-
React.ElementRef<typeof DropdownMenuPrimitive.Item>,
|
|
62
|
-
React.ComponentPropsWithoutRef<typeof DropdownMenuPrimitive.Item> & { inset?: boolean }
|
|
63
|
-
>(({ className, inset, ...props }, ref) => (
|
|
64
|
-
<DropdownMenuPrimitive.Item
|
|
65
|
-
ref={ref}
|
|
66
|
-
className={cn('relative flex cursor-default select-none items-center rounded-lg px-2 py-2 text-sm outline-none transition-colors focus:bg-accent focus:text-accent-foreground data-[disabled]:pointer-events-none data-[disabled]:opacity-50', inset && 'pl-8', className)}
|
|
67
|
-
{...props}
|
|
68
|
-
/>
|
|
69
|
-
));
|
|
70
|
-
DropdownMenuItem.displayName = DropdownMenuPrimitive.Item.displayName;
|
|
71
|
-
|
|
72
|
-
const DropdownMenuCheckboxItem = React.forwardRef<
|
|
73
|
-
React.ElementRef<typeof DropdownMenuPrimitive.CheckboxItem>,
|
|
74
|
-
React.ComponentPropsWithoutRef<typeof DropdownMenuPrimitive.CheckboxItem>
|
|
75
|
-
>(({ className, children, checked, ...props }, ref) => (
|
|
76
|
-
<DropdownMenuPrimitive.CheckboxItem
|
|
77
|
-
ref={ref}
|
|
78
|
-
className={cn('relative flex cursor-default select-none items-center rounded-sm py-1.5 pl-8 pr-2 text-sm outline-none transition-colors focus:bg-accent focus:text-accent-foreground data-[disabled]:pointer-events-none data-[disabled]:opacity-50', className)}
|
|
79
|
-
checked={checked}
|
|
80
|
-
{...props}
|
|
81
|
-
>
|
|
82
|
-
<span className="absolute left-2 flex h-3.5 w-3.5 items-center justify-center">
|
|
83
|
-
<DropdownMenuPrimitive.ItemIndicator>
|
|
84
|
-
<Check className="h-4 w-4" />
|
|
85
|
-
</DropdownMenuPrimitive.ItemIndicator>
|
|
86
|
-
</span>
|
|
87
|
-
{children}
|
|
88
|
-
</DropdownMenuPrimitive.CheckboxItem>
|
|
89
|
-
));
|
|
90
|
-
DropdownMenuCheckboxItem.displayName = DropdownMenuPrimitive.CheckboxItem.displayName;
|
|
91
|
-
|
|
92
|
-
const DropdownMenuRadioItem = React.forwardRef<
|
|
93
|
-
React.ElementRef<typeof DropdownMenuPrimitive.RadioItem>,
|
|
94
|
-
React.ComponentPropsWithoutRef<typeof DropdownMenuPrimitive.RadioItem>
|
|
95
|
-
>(({ className, children, ...props }, ref) => (
|
|
96
|
-
<DropdownMenuPrimitive.RadioItem
|
|
97
|
-
ref={ref}
|
|
98
|
-
className={cn('relative flex cursor-default select-none items-center rounded-sm py-1.5 pl-8 pr-2 text-sm outline-none transition-colors focus:bg-accent focus:text-accent-foreground data-[disabled]:pointer-events-none data-[disabled]:opacity-50', className)}
|
|
99
|
-
{...props}
|
|
100
|
-
>
|
|
101
|
-
<span className="absolute left-2 flex h-3.5 w-3.5 items-center justify-center">
|
|
102
|
-
<DropdownMenuPrimitive.ItemIndicator>
|
|
103
|
-
<Circle className="h-2 w-2 fill-current" />
|
|
104
|
-
</DropdownMenuPrimitive.ItemIndicator>
|
|
105
|
-
</span>
|
|
106
|
-
{children}
|
|
107
|
-
</DropdownMenuPrimitive.RadioItem>
|
|
108
|
-
));
|
|
109
|
-
DropdownMenuRadioItem.displayName = DropdownMenuPrimitive.RadioItem.displayName;
|
|
110
|
-
|
|
111
|
-
const DropdownMenuLabel = React.forwardRef<
|
|
112
|
-
React.ElementRef<typeof DropdownMenuPrimitive.Label>,
|
|
113
|
-
React.ComponentPropsWithoutRef<typeof DropdownMenuPrimitive.Label> & { inset?: boolean }
|
|
114
|
-
>(({ className, inset, ...props }, ref) => (
|
|
115
|
-
<DropdownMenuPrimitive.Label
|
|
116
|
-
ref={ref}
|
|
117
|
-
className={cn('px-2 py-1.5 text-sm font-semibold', inset && 'pl-8', className)}
|
|
118
|
-
{...props}
|
|
119
|
-
/>
|
|
120
|
-
));
|
|
121
|
-
DropdownMenuLabel.displayName = DropdownMenuPrimitive.Label.displayName;
|
|
122
|
-
|
|
123
|
-
const DropdownMenuSeparator = React.forwardRef<
|
|
124
|
-
React.ElementRef<typeof DropdownMenuPrimitive.Separator>,
|
|
125
|
-
React.ComponentPropsWithoutRef<typeof DropdownMenuPrimitive.Separator>
|
|
126
|
-
>(({ className, ...props }, ref) => (
|
|
127
|
-
<DropdownMenuPrimitive.Separator
|
|
128
|
-
ref={ref}
|
|
129
|
-
className={cn('-mx-1 my-1 h-px bg-border/50', className)}
|
|
130
|
-
{...props}
|
|
131
|
-
/>
|
|
132
|
-
));
|
|
133
|
-
DropdownMenuSeparator.displayName = DropdownMenuPrimitive.Separator.displayName;
|
|
134
|
-
|
|
135
|
-
const DropdownMenuShortcut = ({ className, ...props }: React.HTMLAttributes<HTMLSpanElement>) => {
|
|
136
|
-
return <span className={cn('ml-auto text-xs tracking-widest opacity-60', className)} {...props} />;
|
|
137
|
-
};
|
|
138
|
-
DropdownMenuShortcut.displayName = 'DropdownMenuShortcut';
|
|
139
|
-
|
|
140
|
-
export {
|
|
141
|
-
DropdownMenu,
|
|
142
|
-
DropdownMenuTrigger,
|
|
143
|
-
DropdownMenuContent,
|
|
144
|
-
DropdownMenuItem,
|
|
145
|
-
DropdownMenuCheckboxItem,
|
|
146
|
-
DropdownMenuRadioItem,
|
|
147
|
-
DropdownMenuLabel,
|
|
148
|
-
DropdownMenuSeparator,
|
|
149
|
-
DropdownMenuShortcut,
|
|
150
|
-
DropdownMenuGroup,
|
|
151
|
-
DropdownMenuPortal,
|
|
152
|
-
DropdownMenuSub,
|
|
153
|
-
DropdownMenuSubContent,
|
|
154
|
-
DropdownMenuSubTrigger,
|
|
155
|
-
DropdownMenuRadioGroup,
|
|
156
|
-
};
|
|
@@ -1,21 +0,0 @@
|
|
|
1
|
-
import * as React from 'react';
|
|
2
|
-
import { cn } from '@/lib/utils';
|
|
3
|
-
|
|
4
|
-
export interface InputProps extends React.InputHTMLAttributes<HTMLInputElement> {}
|
|
5
|
-
|
|
6
|
-
const Input = React.forwardRef<HTMLInputElement, InputProps>(({ className, type, ...props }, ref) => {
|
|
7
|
-
return (
|
|
8
|
-
<input
|
|
9
|
-
type={type}
|
|
10
|
-
className={cn(
|
|
11
|
-
'flex h-10 w-full rounded-lg border border-input bg-background px-4 py-2 text-sm ring-offset-background file:border-0 file:bg-transparent file:text-sm file:font-medium placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50 transition-all duration-200',
|
|
12
|
-
className
|
|
13
|
-
)}
|
|
14
|
-
ref={ref}
|
|
15
|
-
{...props}
|
|
16
|
-
/>
|
|
17
|
-
);
|
|
18
|
-
});
|
|
19
|
-
Input.displayName = 'Input';
|
|
20
|
-
|
|
21
|
-
export { Input };
|
|
@@ -1,15 +0,0 @@
|
|
|
1
|
-
import * as React from 'react';
|
|
2
|
-
import { cn } from '@/lib/utils';
|
|
3
|
-
|
|
4
|
-
const Label = React.forwardRef<HTMLLabelElement, React.LabelHTMLAttributes<HTMLLabelElement>>(
|
|
5
|
-
({ className, ...props }, ref) => (
|
|
6
|
-
<label
|
|
7
|
-
ref={ref}
|
|
8
|
-
className={cn('text-sm font-medium leading-none peer-disabled:cursor-not-allowed peer-disabled:opacity-70', className)}
|
|
9
|
-
{...props}
|
|
10
|
-
/>
|
|
11
|
-
)
|
|
12
|
-
);
|
|
13
|
-
Label.displayName = 'Label';
|
|
14
|
-
|
|
15
|
-
export { Label };
|
|
@@ -1,22 +0,0 @@
|
|
|
1
|
-
import * as React from 'react';
|
|
2
|
-
import { cn } from '@/lib/utils';
|
|
3
|
-
|
|
4
|
-
const Separator = React.forwardRef<
|
|
5
|
-
HTMLDivElement,
|
|
6
|
-
React.ComponentPropsWithoutRef<'div'> & {
|
|
7
|
-
orientation?: 'horizontal' | 'vertical';
|
|
8
|
-
}
|
|
9
|
-
>(({ className, orientation = 'horizontal', ...props }, ref) => (
|
|
10
|
-
<div
|
|
11
|
-
ref={ref}
|
|
12
|
-
className={cn(
|
|
13
|
-
'shrink-0 bg-border',
|
|
14
|
-
orientation === 'horizontal' ? 'h-[1px] w-full' : 'h-full w-[1px]',
|
|
15
|
-
className
|
|
16
|
-
)}
|
|
17
|
-
{...props}
|
|
18
|
-
/>
|
|
19
|
-
));
|
|
20
|
-
Separator.displayName = 'Separator';
|
|
21
|
-
|
|
22
|
-
export { Separator };
|
|
@@ -1,27 +0,0 @@
|
|
|
1
|
-
import * as React from 'react';
|
|
2
|
-
import { cn } from '@/lib/utils';
|
|
3
|
-
|
|
4
|
-
export interface SwitchProps extends React.InputHTMLAttributes<HTMLInputElement> {
|
|
5
|
-
onCheckedChange?: (checked: boolean) => void;
|
|
6
|
-
}
|
|
7
|
-
|
|
8
|
-
const Switch = React.forwardRef<HTMLInputElement, SwitchProps>(
|
|
9
|
-
({ className, onCheckedChange, ...props }, ref) => {
|
|
10
|
-
return (
|
|
11
|
-
<input
|
|
12
|
-
type="checkbox"
|
|
13
|
-
role="switch"
|
|
14
|
-
ref={ref}
|
|
15
|
-
className={cn(
|
|
16
|
-
'peer inline-flex h-6 w-11 shrink-0 cursor-pointer items-center rounded-full border-2 border-transparent transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 focus-visible:ring-offset-background disabled:cursor-not-allowed disabled:opacity-50 data-[state=checked]:bg-primary data-[state=unchecked]:bg-input',
|
|
17
|
-
className
|
|
18
|
-
)}
|
|
19
|
-
onChange={(e) => onCheckedChange?.(e.target.checked)}
|
|
20
|
-
{...props}
|
|
21
|
-
/>
|
|
22
|
-
);
|
|
23
|
-
}
|
|
24
|
-
);
|
|
25
|
-
Switch.displayName = 'Switch';
|
|
26
|
-
|
|
27
|
-
export { Switch };
|
|
@@ -1,51 +0,0 @@
|
|
|
1
|
-
'use client';
|
|
2
|
-
|
|
3
|
-
import * as React from 'react';
|
|
4
|
-
import * as TabsPrimitive from '@radix-ui/react-tabs';
|
|
5
|
-
import { cn } from '@/lib/utils';
|
|
6
|
-
|
|
7
|
-
const Tabs = TabsPrimitive.Root;
|
|
8
|
-
|
|
9
|
-
const TabsList = React.forwardRef<
|
|
10
|
-
React.ElementRef<typeof TabsPrimitive.List>,
|
|
11
|
-
React.ComponentPropsWithoutRef<typeof TabsPrimitive.List>
|
|
12
|
-
>(({ className, ...props }, ref) => (
|
|
13
|
-
<TabsPrimitive.List
|
|
14
|
-
ref={ref}
|
|
15
|
-
className={cn(
|
|
16
|
-
'inline-flex h-10 items-center justify-center rounded-lg bg-muted p-1 text-muted-foreground',
|
|
17
|
-
className
|
|
18
|
-
)}
|
|
19
|
-
{...props}
|
|
20
|
-
/>
|
|
21
|
-
));
|
|
22
|
-
TabsList.displayName = TabsPrimitive.List.displayName;
|
|
23
|
-
|
|
24
|
-
const TabsTrigger = React.forwardRef<
|
|
25
|
-
React.ElementRef<typeof TabsPrimitive.Trigger>,
|
|
26
|
-
React.ComponentPropsWithoutRef<typeof TabsPrimitive.Trigger>
|
|
27
|
-
>(({ className, ...props }, ref) => (
|
|
28
|
-
<TabsPrimitive.Trigger
|
|
29
|
-
ref={ref}
|
|
30
|
-
className={cn(
|
|
31
|
-
'inline-flex items-center justify-center whitespace-nowrap rounded-md px-3 py-1.5 text-sm font-medium ring-offset-background transition-all focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50 data-[state=active]:bg-background data-[state=active]:text-foreground data-[state=active]:shadow-sm',
|
|
32
|
-
className
|
|
33
|
-
)}
|
|
34
|
-
{...props}
|
|
35
|
-
/>
|
|
36
|
-
));
|
|
37
|
-
TabsTrigger.displayName = TabsPrimitive.Trigger.displayName;
|
|
38
|
-
|
|
39
|
-
const TabsContent = React.forwardRef<
|
|
40
|
-
React.ElementRef<typeof TabsPrimitive.Content>,
|
|
41
|
-
React.ComponentPropsWithoutRef<typeof TabsPrimitive.Content>
|
|
42
|
-
>(({ className, ...props }, ref) => (
|
|
43
|
-
<TabsPrimitive.Content
|
|
44
|
-
ref={ref}
|
|
45
|
-
className={cn('mt-2 ring-offset-background focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2', className)}
|
|
46
|
-
{...props}
|
|
47
|
-
/>
|
|
48
|
-
));
|
|
49
|
-
TabsContent.displayName = TabsPrimitive.Content.displayName;
|
|
50
|
-
|
|
51
|
-
export { Tabs, TabsList, TabsTrigger, TabsContent };
|
|
@@ -1,103 +0,0 @@
|
|
|
1
|
-
'use client';
|
|
2
|
-
|
|
3
|
-
import * as React from 'react';
|
|
4
|
-
import * as ToastPrimitives from '@radix-ui/react-toast';
|
|
5
|
-
import { cva, type VariantProps } from 'class-variance-authority';
|
|
6
|
-
import { X } from 'lucide-react';
|
|
7
|
-
import { cn } from '@/lib/utils';
|
|
8
|
-
|
|
9
|
-
const ToastProvider = ToastPrimitives.Provider;
|
|
10
|
-
|
|
11
|
-
const ToastViewport = React.forwardRef<
|
|
12
|
-
React.ElementRef<typeof ToastPrimitives.Viewport>,
|
|
13
|
-
React.ComponentPropsWithoutRef<typeof ToastPrimitives.Viewport>
|
|
14
|
-
>(({ className, ...props }, ref) => (
|
|
15
|
-
<ToastPrimitives.Viewport
|
|
16
|
-
ref={ref}
|
|
17
|
-
className={cn('fixed top-0 z-[100] flex max-h-screen w-full flex-col-reverse p-4 sm:bottom-0 sm:right-0 sm:top-auto sm:flex-col md:max-w-[420px]', className)}
|
|
18
|
-
{...props}
|
|
19
|
-
/>
|
|
20
|
-
));
|
|
21
|
-
ToastViewport.displayName = ToastPrimitives.Viewport.displayName;
|
|
22
|
-
|
|
23
|
-
const toastVariants = cva(
|
|
24
|
-
'group pointer-events-auto relative flex w-full items-center justify-between space-x-4 overflow-hidden rounded-xl border p-6 pr-8 shadow-lg transition-all data-[swipe=cancel]:translate-x-0 data-[swipe=end]:translate-x-[var(--radix-toast-swipe-end-x)] data-[swipe=move]:translate-x-[var(--radix-toast-swipe-move-x)] data-[swipe=move]:transition-none data-[state=open]:animate-in data-[state=closed]:animate-out data-[swipe=end]:animate-out data-[state=closed]:fade-out-80 data-[state=closed]:slide-out-to-right-full data-[state=open]:slide-in-from-top-full',
|
|
25
|
-
{
|
|
26
|
-
variants: {
|
|
27
|
-
variant: {
|
|
28
|
-
default: 'border bg-card text-foreground',
|
|
29
|
-
destructive: 'destructive group border-destructive bg-destructive text-destructive-foreground',
|
|
30
|
-
success: 'border-emerald-500/50 bg-card text-foreground',
|
|
31
|
-
},
|
|
32
|
-
},
|
|
33
|
-
defaultVariants: {
|
|
34
|
-
variant: 'default',
|
|
35
|
-
},
|
|
36
|
-
}
|
|
37
|
-
);
|
|
38
|
-
|
|
39
|
-
const Toast = React.forwardRef<
|
|
40
|
-
React.ElementRef<typeof ToastPrimitives.Root>,
|
|
41
|
-
React.ComponentPropsWithoutRef<typeof ToastPrimitives.Root> & VariantProps<typeof toastVariants>
|
|
42
|
-
>(({ className, variant, ...props }, ref) => {
|
|
43
|
-
return <ToastPrimitives.Root ref={ref} className={cn(toastVariants({ variant }), className)} {...props} />;
|
|
44
|
-
});
|
|
45
|
-
Toast.displayName = ToastPrimitives.Root.displayName;
|
|
46
|
-
|
|
47
|
-
const ToastAction = React.forwardRef<
|
|
48
|
-
React.ElementRef<typeof ToastPrimitives.Action>,
|
|
49
|
-
React.ComponentPropsWithoutRef<typeof ToastPrimitives.Action>
|
|
50
|
-
>(({ className, ...props }, ref) => (
|
|
51
|
-
<ToastPrimitives.Action
|
|
52
|
-
ref={ref}
|
|
53
|
-
className={cn('inline-flex h-8 shrink-0 items-center justify-center rounded-md border bg-transparent px-3 text-sm font-medium ring-offset-background transition-colors hover:bg-secondary focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2 disabled:pointer-events-none disabled:opacity-50 group-[.destructive]:border-muted/40 group-[.destructive]:hover:border-destructive/30 group-[.destructive]:hover:bg-destructive group-[.destructive]:hover:text-destructive-foreground group-[.destructive]:focus:ring-destructive', className)}
|
|
54
|
-
{...props}
|
|
55
|
-
/>
|
|
56
|
-
));
|
|
57
|
-
ToastAction.displayName = ToastPrimitives.Action.displayName;
|
|
58
|
-
|
|
59
|
-
const ToastClose = React.forwardRef<
|
|
60
|
-
React.ElementRef<typeof ToastPrimitives.Close>,
|
|
61
|
-
React.ComponentPropsWithoutRef<typeof ToastPrimitives.Close>
|
|
62
|
-
>(({ className, ...props }, ref) => (
|
|
63
|
-
<ToastPrimitives.Close
|
|
64
|
-
ref={ref}
|
|
65
|
-
className={cn('absolute right-2 top-2 rounded-md p-1 text-foreground/50 opacity-0 transition-opacity hover:text-foreground focus:opacity-100 focus:outline-none focus:ring-2 group-hover:opacity-100 group-[.destructive]:text-red-300 group-[.destructive]:hover:text-red-50 group-[.destructive]:focus:ring-red-400 group-[.destructive]:focus:ring-offset-red-600', className)}
|
|
66
|
-
toast-close=""
|
|
67
|
-
{...props}
|
|
68
|
-
>
|
|
69
|
-
<X className="h-4 w-4" />
|
|
70
|
-
</ToastPrimitives.Close>
|
|
71
|
-
));
|
|
72
|
-
ToastClose.displayName = ToastPrimitives.Close.displayName;
|
|
73
|
-
|
|
74
|
-
const ToastTitle = React.forwardRef<
|
|
75
|
-
React.ElementRef<typeof ToastPrimitives.Title>,
|
|
76
|
-
React.ComponentPropsWithoutRef<typeof ToastPrimitives.Title>
|
|
77
|
-
>(({ className, ...props }, ref) => (
|
|
78
|
-
<ToastPrimitives.Title ref={ref} className={cn('text-sm font-semibold', className)} {...props} />
|
|
79
|
-
));
|
|
80
|
-
ToastTitle.displayName = ToastPrimitives.Title.displayName;
|
|
81
|
-
|
|
82
|
-
const ToastDescription = React.forwardRef<
|
|
83
|
-
React.ElementRef<typeof ToastPrimitives.Description>,
|
|
84
|
-
React.ComponentPropsWithoutRef<typeof ToastPrimitives.Description>
|
|
85
|
-
>(({ className, ...props }, ref) => (
|
|
86
|
-
<ToastPrimitives.Description ref={ref} className={cn('text-sm opacity-90', className)} {...props} />
|
|
87
|
-
));
|
|
88
|
-
ToastDescription.displayName = ToastPrimitives.Description.displayName;
|
|
89
|
-
|
|
90
|
-
type ToastProps = React.ComponentPropsWithoutRef<typeof Toast>;
|
|
91
|
-
type ToastActionElement = React.ReactElement<typeof ToastAction>;
|
|
92
|
-
|
|
93
|
-
export {
|
|
94
|
-
type ToastProps,
|
|
95
|
-
type ToastActionElement,
|
|
96
|
-
ToastProvider,
|
|
97
|
-
ToastViewport,
|
|
98
|
-
Toast,
|
|
99
|
-
ToastTitle,
|
|
100
|
-
ToastDescription,
|
|
101
|
-
ToastClose,
|
|
102
|
-
ToastAction,
|
|
103
|
-
};
|
package/src/lib/auth.ts
DELETED
|
@@ -1,45 +0,0 @@
|
|
|
1
|
-
import jwt from 'jsonwebtoken';
|
|
2
|
-
import { cookies } from 'next/headers';
|
|
3
|
-
|
|
4
|
-
export interface AuthUser {
|
|
5
|
-
id: string;
|
|
6
|
-
username: string;
|
|
7
|
-
name: string;
|
|
8
|
-
role: 'super_admin' | 'admin' | 'reseller';
|
|
9
|
-
isActive: boolean;
|
|
10
|
-
canCreateKey: boolean;
|
|
11
|
-
canDeleteKey: boolean;
|
|
12
|
-
canBlockKey: boolean;
|
|
13
|
-
canManageTokens: boolean;
|
|
14
|
-
canCreateReseller: boolean;
|
|
15
|
-
canManageResellers: boolean;
|
|
16
|
-
canManageUsers: boolean;
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
export function signToken(payload: AuthUser): string {
|
|
20
|
-
if (!process.env.JWT_SECRET) {
|
|
21
|
-
throw new Error('JWT_SECRET environment variable is not set — cannot sign tokens');
|
|
22
|
-
}
|
|
23
|
-
return jwt.sign(payload, process.env.JWT_SECRET, { expiresIn: '24h' });
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
export function verifyToken(token: string): AuthUser | null {
|
|
27
|
-
try {
|
|
28
|
-
if (!process.env.JWT_SECRET) return null;
|
|
29
|
-
return jwt.verify(token, process.env.JWT_SECRET) as AuthUser;
|
|
30
|
-
} catch {
|
|
31
|
-
return null;
|
|
32
|
-
}
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
export async function getAuthUser(): Promise<AuthUser | null> {
|
|
36
|
-
const cookieStore = await cookies();
|
|
37
|
-
const token = cookieStore.get('admin_token')?.value;
|
|
38
|
-
if (!token) return null;
|
|
39
|
-
return verifyToken(token);
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
export function requireRole(user: AuthUser | null, ...roles: string[]): boolean {
|
|
43
|
-
if (!user) return false;
|
|
44
|
-
return roles.includes(user.role);
|
|
45
|
-
}
|
package/src/lib/prisma.ts
DELETED
|
@@ -1,20 +0,0 @@
|
|
|
1
|
-
import { PrismaClient } from '@prisma/client';
|
|
2
|
-
import { PrismaLibSql } from '@prisma/adapter-libsql';
|
|
3
|
-
|
|
4
|
-
const globalForPrisma = globalThis as unknown as {
|
|
5
|
-
prisma: PrismaClient | undefined;
|
|
6
|
-
};
|
|
7
|
-
|
|
8
|
-
function createPrismaClient() {
|
|
9
|
-
const databaseUrl = process.env.DATABASE_URL;
|
|
10
|
-
if (!databaseUrl) {
|
|
11
|
-
throw new Error('DATABASE_URL environment variable is not set');
|
|
12
|
-
}
|
|
13
|
-
|
|
14
|
-
const adapter = new PrismaLibSql({ url: databaseUrl });
|
|
15
|
-
return new PrismaClient({ adapter } as any);
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
export const prisma = globalForPrisma.prisma ?? createPrismaClient();
|
|
19
|
-
|
|
20
|
-
if (process.env.NODE_ENV !== 'production') globalForPrisma.prisma = prisma;
|
package/src/lib/providers.ts
DELETED
|
@@ -1,158 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* LiteRouter + OpenRouter provider abstraction.
|
|
3
|
-
* LiteRouter is the primary backend; OpenRouter is the fallback.
|
|
4
|
-
*/
|
|
5
|
-
|
|
6
|
-
// ── LiteRouter Config ────────────────────────────────────────────────────────
|
|
7
|
-
export const LITE_ROUTER_CONFIG = {
|
|
8
|
-
name: 'literouter',
|
|
9
|
-
baseUrl: 'https://literouter.com/api/v1',
|
|
10
|
-
};
|
|
11
|
-
|
|
12
|
-
export const LITE_ROUTER_FREE_MODELS = [
|
|
13
|
-
'gemini-free',
|
|
14
|
-
'gpt-free',
|
|
15
|
-
'deepseek-free',
|
|
16
|
-
'glm-free',
|
|
17
|
-
'kimi-k2-thinking-free',
|
|
18
|
-
'google/gemma-4-31b:free', // vision-capable
|
|
19
|
-
];
|
|
20
|
-
|
|
21
|
-
export const LITE_ROUTER_VISION_MODELS = ['google/gemma-4-31b:free'];
|
|
22
|
-
|
|
23
|
-
// ── In-Memory Maps (per-process; shared across all API calls) ────────────────
|
|
24
|
-
|
|
25
|
-
/** keyId → timestamp of last LiteRouter request */
|
|
26
|
-
export const liteRouterCooldownMap = new Map<string, number>();
|
|
27
|
-
|
|
28
|
-
/** keyId → true if a LiteRouter request is currently in flight */
|
|
29
|
-
export const liteRouterInFlightMap = new Map<string, boolean>();
|
|
30
|
-
|
|
31
|
-
// ── Model Mapping: Claude model name → LiteRouter free model ─────────────────
|
|
32
|
-
|
|
33
|
-
export const LITE_ROUTER_MODEL_MAP: Record<string, string> = {
|
|
34
|
-
// Opus tier → gemini-free (best all-rounder)
|
|
35
|
-
'claude-opus-4-6': 'gemini-free',
|
|
36
|
-
'opus-4': 'gemini-free',
|
|
37
|
-
'opus': 'gemini-free',
|
|
38
|
-
'Opus 4.6': 'gemini-free',
|
|
39
|
-
'Opus 4.5': 'gemini-free',
|
|
40
|
-
'Opus 4': 'gemini-free',
|
|
41
|
-
|
|
42
|
-
// Sonnet tier → gpt-free (GPT-4 level)
|
|
43
|
-
'claude-sonnet-4-6': 'gpt-free',
|
|
44
|
-
'sonnet': 'gpt-free',
|
|
45
|
-
'Sonnet 4.6': 'gpt-free',
|
|
46
|
-
'Sonnet 4.5': 'gpt-free',
|
|
47
|
-
'Sonnet 4': 'gpt-free',
|
|
48
|
-
'Sonnet 4.5 (Extended Thinking)': 'gpt-free',
|
|
49
|
-
|
|
50
|
-
// Haiku tier → deepseek-free (strong reasoning/coding)
|
|
51
|
-
'claude-haiku-4-5': 'deepseek-free',
|
|
52
|
-
'haiku': 'deepseek-free',
|
|
53
|
-
'Haiku 4.5': 'deepseek-free',
|
|
54
|
-
'Haiku 3.5': 'deepseek-free',
|
|
55
|
-
'claude-haiku-4-5-20251001': 'deepseek-free',
|
|
56
|
-
'claude-haiku-4-5-20260219': 'deepseek-free',
|
|
57
|
-
// Vision — LiteRouter gemma-4-31b (vision-capable free model)
|
|
58
|
-
'claude-sonnet-4-vision': 'google/gemma-4-31b:free',
|
|
59
|
-
'claude-3-5-sonnet-latest': 'google/gemma-4-31b:free',
|
|
60
|
-
};
|
|
61
|
-
|
|
62
|
-
/**
|
|
63
|
-
* Map a Claude model name to a LiteRouter free model.
|
|
64
|
-
* Falls back to 'gemini-free' for any unmapped model.
|
|
65
|
-
*/
|
|
66
|
-
export function mapToLiteRouter(model: string): string {
|
|
67
|
-
return LITE_ROUTER_MODEL_MAP[model] ?? 'gemini-free';
|
|
68
|
-
}
|
|
69
|
-
|
|
70
|
-
/**
|
|
71
|
-
* Map a LiteRouter response model back to a Claude display name.
|
|
72
|
-
*/
|
|
73
|
-
export function remapLiteRouterModel(model: string): string {
|
|
74
|
-
switch (model) {
|
|
75
|
-
case 'gemini-free': return 'claude-opus-4-6';
|
|
76
|
-
case 'gpt-free': return 'claude-sonnet-4-6';
|
|
77
|
-
case 'deepseek-free': return 'claude-haiku-4-5';
|
|
78
|
-
case 'glm-free': return 'claude-haiku-3-5';
|
|
79
|
-
case 'kimi-k2-thinking-free': return 'claude-haiku-3-5';
|
|
80
|
-
case 'google/gemma-4-31b:free': return 'claude-sonnet-4-vision';
|
|
81
|
-
default: return 'claude-opus-4-6';
|
|
82
|
-
}
|
|
83
|
-
}
|
|
84
|
-
|
|
85
|
-
// ── Cooldown ─────────────────────────────────────────────────────────────────
|
|
86
|
-
|
|
87
|
-
const COOLDOWN_MS = 7500; // 7.5s — slightly above the 7s LiteRouter minimum
|
|
88
|
-
|
|
89
|
-
/**
|
|
90
|
-
* Returns a promise that resolves when the cooldown period has elapsed.
|
|
91
|
-
* Updates the cooldown map with the current timestamp.
|
|
92
|
-
*/
|
|
93
|
-
export async function waitForCooldown(keyId: string): Promise<void> {
|
|
94
|
-
const last = liteRouterCooldownMap.get(keyId) ?? 0;
|
|
95
|
-
const elapsed = Date.now() - last;
|
|
96
|
-
if (elapsed < COOLDOWN_MS) {
|
|
97
|
-
await new Promise(r => setTimeout(r, COOLDOWN_MS - elapsed));
|
|
98
|
-
}
|
|
99
|
-
// Set cooldown start time
|
|
100
|
-
liteRouterCooldownMap.set(keyId, Date.now());
|
|
101
|
-
}
|
|
102
|
-
|
|
103
|
-
/**
|
|
104
|
-
* Try to acquire an in-flight slot for a key.
|
|
105
|
-
* Returns true if acquired (no other request in flight).
|
|
106
|
-
*/
|
|
107
|
-
export function acquireInFlight(keyId: string): boolean {
|
|
108
|
-
if (liteRouterInFlightMap.get(keyId)) return false;
|
|
109
|
-
liteRouterInFlightMap.set(keyId, true);
|
|
110
|
-
return true;
|
|
111
|
-
}
|
|
112
|
-
|
|
113
|
-
/**
|
|
114
|
-
* Release the in-flight slot for a key.
|
|
115
|
-
*/
|
|
116
|
-
export function releaseInFlight(keyId: string): void {
|
|
117
|
-
liteRouterInFlightMap.delete(keyId);
|
|
118
|
-
}
|
|
119
|
-
|
|
120
|
-
// ── LiteRouter API Call ───────────────────────────────────────────────────────
|
|
121
|
-
|
|
122
|
-
export interface LiteRouterCallOptions {
|
|
123
|
-
model: string; // LiteRouter model (e.g. 'gemini-free')
|
|
124
|
-
messages: any[];
|
|
125
|
-
stream: boolean;
|
|
126
|
-
max_tokens?: number;
|
|
127
|
-
temperature?: number;
|
|
128
|
-
}
|
|
129
|
-
|
|
130
|
-
export async function callLiteRouter(
|
|
131
|
-
keyId: string,
|
|
132
|
-
options: LiteRouterCallOptions
|
|
133
|
-
): Promise<Response> {
|
|
134
|
-
const apiKey = process.env.LITEROUTER_API_KEY;
|
|
135
|
-
if (!apiKey) {
|
|
136
|
-
return new Response(JSON.stringify({ error: { message: 'LiteRouter API key not configured' } }), {
|
|
137
|
-
status: 500,
|
|
138
|
-
headers: { 'Content-Type': 'application/json' },
|
|
139
|
-
});
|
|
140
|
-
}
|
|
141
|
-
|
|
142
|
-
const res = await fetch(`${LITE_ROUTER_CONFIG.baseUrl}/chat/completions`, {
|
|
143
|
-
method: 'POST',
|
|
144
|
-
headers: {
|
|
145
|
-
'Authorization': `Bearer ${apiKey}`,
|
|
146
|
-
'Content-Type': 'application/json',
|
|
147
|
-
},
|
|
148
|
-
body: JSON.stringify({
|
|
149
|
-
model: options.model,
|
|
150
|
-
messages: options.messages,
|
|
151
|
-
stream: options.stream,
|
|
152
|
-
max_tokens: options.max_tokens,
|
|
153
|
-
temperature: options.temperature,
|
|
154
|
-
}),
|
|
155
|
-
});
|
|
156
|
-
|
|
157
|
-
return res;
|
|
158
|
-
}
|