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.
Files changed (124) hide show
  1. package/claudmax-1.0.16.tgz +0 -0
  2. package/{packages/cli/index.js → index.js} +2 -0
  3. package/package.json +27 -55
  4. package/.claude/settings.local.json +0 -7
  5. package/.env.example +0 -24
  6. package/.github/workflows/publish.yml +0 -31
  7. package/README.md +0 -178
  8. package/claudmax-mcp-1.0.2.tgz +0 -0
  9. package/help +0 -0
  10. package/help-wal +0 -0
  11. package/next-env.d.ts +0 -6
  12. package/next.config.mjs +0 -43
  13. package/packages/cli/claudmax-1.0.16.tgz +0 -0
  14. package/packages/cli/package.json +0 -33
  15. package/packages/mcp/claudmax-mcp-1.0.0.tgz +0 -0
  16. package/packages/mcp/claudmax-mcp-1.0.1.tgz +0 -0
  17. package/packages/mcp/claudmax-mcp-1.0.2.tgz +0 -0
  18. package/packages/mcp/claudmax-mcp-1.0.3.tgz +0 -0
  19. package/packages/mcp/index.js +0 -129
  20. package/packages/mcp/package-lock.json +0 -1146
  21. package/packages/mcp/package.json +0 -32
  22. package/postcss.config.mjs +0 -6
  23. package/prisma/schema.prisma +0 -130
  24. package/prisma/seed.ts +0 -27
  25. package/public/favicon.svg +0 -10
  26. package/public/robots.txt +0 -10
  27. package/run_build.sh +0 -4
  28. package/scripts/migrate-plans.js +0 -98
  29. package/scripts/seed-blog.ts +0 -1014
  30. package/src/app/admin/dashboard/AdminDashboardClient.tsx +0 -1546
  31. package/src/app/admin/dashboard/page.tsx +0 -13
  32. package/src/app/admin/page.tsx +0 -132
  33. package/src/app/api/admin/auth/me/route.ts +0 -34
  34. package/src/app/api/admin/health/route.ts +0 -110
  35. package/src/app/api/admin/keys/[id]/route.ts +0 -116
  36. package/src/app/api/admin/keys/route.ts +0 -192
  37. package/src/app/api/admin/keys-list/route.ts +0 -81
  38. package/src/app/api/admin/login/route.ts +0 -72
  39. package/src/app/api/admin/logout/route.ts +0 -8
  40. package/src/app/api/admin/migrate/route.ts +0 -133
  41. package/src/app/api/admin/plans/[id]/route.ts +0 -65
  42. package/src/app/api/admin/plans/route.ts +0 -66
  43. package/src/app/api/admin/posts/[id]/route.ts +0 -81
  44. package/src/app/api/admin/posts/route.ts +0 -83
  45. package/src/app/api/admin/seed/route.ts +0 -145
  46. package/src/app/api/admin/settings/route.ts +0 -44
  47. package/src/app/api/admin/stats/route.ts +0 -74
  48. package/src/app/api/admin/users/[id]/route.ts +0 -166
  49. package/src/app/api/admin/users/plans/route.ts +0 -45
  50. package/src/app/api/admin/users/route.ts +0 -202
  51. package/src/app/api/blog/[slug]/route.ts +0 -22
  52. package/src/app/api/blog/route.ts +0 -40
  53. package/src/app/api/cron/daily-status/route.ts +0 -208
  54. package/src/app/api/support/chat/route.ts +0 -55
  55. package/src/app/api/support/chat/session/route.ts +0 -62
  56. package/src/app/api/support/chat/stream/route.ts +0 -44
  57. package/src/app/api/support/email/route.ts +0 -63
  58. package/src/app/api/tools/understand_image/route.ts +0 -113
  59. package/src/app/api/tools/upload/route.ts +0 -179
  60. package/src/app/api/tools/web_search/route.ts +0 -99
  61. package/src/app/api/v1/audio/route.ts +0 -67
  62. package/src/app/api/v1/audio/speech/route.ts +0 -73
  63. package/src/app/api/v1/chat/completions/route.ts +0 -3
  64. package/src/app/api/v1/chat/route.ts +0 -1079
  65. package/src/app/api/v1/images/generations/route.ts +0 -93
  66. package/src/app/api/v1/info/route.ts +0 -30
  67. package/src/app/api/v1/key-status/route.ts +0 -109
  68. package/src/app/api/v1/key-status/stream/route.ts +0 -135
  69. package/src/app/api/v1/messages/count_tokens/route.ts +0 -22
  70. package/src/app/api/v1/messages/route.ts +0 -807
  71. package/src/app/api/v1/models/route.ts +0 -14
  72. package/src/app/api/v1/route.ts +0 -18
  73. package/src/app/blog/BlogClient.tsx +0 -193
  74. package/src/app/blog/[slug]/page.tsx +0 -117
  75. package/src/app/blog/page.tsx +0 -20
  76. package/src/app/check-usage/CheckUsageClient.tsx +0 -186
  77. package/src/app/check-usage/layout.tsx +0 -11
  78. package/src/app/check-usage/page.tsx +0 -15
  79. package/src/app/docs/layout.tsx +0 -16
  80. package/src/app/docs/page.tsx +0 -1055
  81. package/src/app/faq/FAQClient.tsx +0 -227
  82. package/src/app/faq/page.tsx +0 -21
  83. package/src/app/globals.css +0 -75
  84. package/src/app/layout.tsx +0 -80
  85. package/src/app/page.tsx +0 -256
  86. package/src/app/reseller/ResellerClient.tsx +0 -435
  87. package/src/app/reseller/page.tsx +0 -15
  88. package/src/app/setup.ps1/route.ts +0 -79
  89. package/src/app/setup.sh/route.ts +0 -113
  90. package/src/app/sitemap.ts +0 -50
  91. package/src/app/status/StatusClient.tsx +0 -103
  92. package/src/app/status/layout.tsx +0 -11
  93. package/src/app/status/page.tsx +0 -15
  94. package/src/app/support/SupportClient.tsx +0 -411
  95. package/src/app/support/page.tsx +0 -25
  96. package/src/app/v1/chat/completions/route.ts +0 -3
  97. package/src/app/v1/chat/route.ts +0 -4
  98. package/src/app/v1/messages/route.ts +0 -3
  99. package/src/components/Footer.tsx +0 -120
  100. package/src/components/Header.tsx +0 -131
  101. package/src/components/landing/features.tsx +0 -99
  102. package/src/components/ui/badge.tsx +0 -32
  103. package/src/components/ui/button.tsx +0 -46
  104. package/src/components/ui/card.tsx +0 -50
  105. package/src/components/ui/dialog.tsx +0 -97
  106. package/src/components/ui/dropdown-menu.tsx +0 -156
  107. package/src/components/ui/input.tsx +0 -21
  108. package/src/components/ui/label.tsx +0 -15
  109. package/src/components/ui/separator.tsx +0 -22
  110. package/src/components/ui/switch.tsx +0 -27
  111. package/src/components/ui/tabs.tsx +0 -51
  112. package/src/components/ui/toast.tsx +0 -103
  113. package/src/lib/auth.ts +0 -45
  114. package/src/lib/prisma.ts +0 -20
  115. package/src/lib/providers.ts +0 -158
  116. package/src/lib/security.ts +0 -165
  117. package/src/lib/utils.ts +0 -14
  118. package/src/middleware.ts +0 -30
  119. package/tailwind.config.ts +0 -53
  120. package/tsconfig.json +0 -41
  121. package/tsconfig.tsbuildinfo +0 -1
  122. package/vercel.json +0 -8
  123. /package/{packages/cli/bin → bin}/claudmax.js +0 -0
  124. /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;
@@ -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
- }