mirror of
https://github.com/Routstr/routstr-core.git
synced 2026-08-01 00:06:14 +00:00
Compare commits
8
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
31898192b2 | ||
|
|
855d60b4a5 | ||
|
|
27ace348b5 | ||
|
|
c8f8857f03 | ||
|
|
c9650441bb | ||
|
|
5ce9c2217f | ||
|
|
89b8488ab8 | ||
|
|
2ee917fa31 |
+132
-161
@@ -286,7 +286,9 @@ function ProviderBalance({
|
||||
<div className='rounded-lg border-2 border-gray-200 p-2 dark:border-gray-800'>
|
||||
{/* eslint-disable-next-line @next/next/no-img-element */}
|
||||
<img
|
||||
src={`https://api.qrserver.com/v1/create-qr-code/?size=256x256&data=${encodeURIComponent(invoiceData.payment_request)}`}
|
||||
src={`https://api.qrserver.com/v1/create-qr-code/?size=256x256&data=${encodeURIComponent(
|
||||
invoiceData.payment_request
|
||||
)}`}
|
||||
alt='Lightning Invoice QR Code'
|
||||
className='h-64 w-64'
|
||||
/>
|
||||
@@ -482,6 +484,25 @@ export default function ProvidersPage() {
|
||||
},
|
||||
});
|
||||
|
||||
const deleteModelMutation = useMutation({
|
||||
mutationFn: ({
|
||||
providerId,
|
||||
modelId,
|
||||
}: {
|
||||
providerId: number;
|
||||
modelId: string;
|
||||
}) => AdminService.deleteProviderModel(providerId, modelId),
|
||||
onSuccess: (_, variables) => {
|
||||
queryClient.invalidateQueries({
|
||||
queryKey: ['provider-models', variables.providerId],
|
||||
});
|
||||
toast.success('Model deleted successfully');
|
||||
},
|
||||
onError: (error: Error) => {
|
||||
toast.error(`Failed to delete model: ${error.message}`);
|
||||
},
|
||||
});
|
||||
|
||||
const handleCreateAccount = async () => {
|
||||
setIsCreatingAccount(true);
|
||||
try {
|
||||
@@ -560,6 +581,12 @@ export default function ProvidersPage() {
|
||||
}
|
||||
};
|
||||
|
||||
const handleDeleteModel = (providerId: number, modelId: string) => {
|
||||
if (confirm('Are you sure you want to delete this model?')) {
|
||||
deleteModelMutation.mutate({ providerId, modelId });
|
||||
}
|
||||
};
|
||||
|
||||
const getDefaultBaseUrl = (type: string) => {
|
||||
const providerType = providerTypes.find((pt) => pt.id === type);
|
||||
return providerType?.default_base_url || '';
|
||||
@@ -933,25 +960,71 @@ export default function ProvidersPage() {
|
||||
</div>
|
||||
) : providerModels &&
|
||||
viewingModels === provider.id ? (
|
||||
providerModels.remote_models.length === 0 ? (
|
||||
// No provided models - show custom models directly without tabs
|
||||
<div className='space-y-2'>
|
||||
{providerModels.db_models.length === 0 ? (
|
||||
<div className='flex flex-col items-center justify-center gap-2 py-4'>
|
||||
<Tabs
|
||||
defaultValue={
|
||||
providerModels.remote_models.length > 0
|
||||
? 'provided'
|
||||
: 'custom'
|
||||
}
|
||||
className='w-full'
|
||||
>
|
||||
<TabsList className='grid w-full grid-cols-2'>
|
||||
<TabsTrigger
|
||||
value='provided'
|
||||
className='text-xs sm:text-sm'
|
||||
>
|
||||
<span className='hidden sm:inline'>
|
||||
Provided Models
|
||||
</span>
|
||||
<span className='sm:hidden'>Provided</span>
|
||||
<Badge
|
||||
variant='secondary'
|
||||
className='ml-1 text-xs sm:ml-2'
|
||||
>
|
||||
{providerModels.remote_models.length}
|
||||
</Badge>
|
||||
</TabsTrigger>
|
||||
<TabsTrigger
|
||||
value='custom'
|
||||
className='text-xs sm:text-sm'
|
||||
>
|
||||
<span className='hidden sm:inline'>
|
||||
Custom Models
|
||||
</span>
|
||||
<span className='sm:hidden'>Custom</span>
|
||||
<Badge
|
||||
variant='secondary'
|
||||
className='ml-1 text-xs sm:ml-2'
|
||||
>
|
||||
{providerModels.db_models.length}
|
||||
</Badge>
|
||||
</TabsTrigger>
|
||||
</TabsList>
|
||||
<TabsContent
|
||||
value='custom'
|
||||
className='mt-4 space-y-2'
|
||||
>
|
||||
<div className='flex items-center justify-between'>
|
||||
{providerModels.db_models.length > 0 && (
|
||||
<div className='text-muted-foreground text-sm'>
|
||||
No models configured. Add custom models
|
||||
to use this provider.
|
||||
Custom models override or extend the
|
||||
provider's catalog.
|
||||
</div>
|
||||
<Button
|
||||
variant='outline'
|
||||
size='sm'
|
||||
onClick={() =>
|
||||
handleAddModel(provider.id)
|
||||
}
|
||||
>
|
||||
<Plus className='mr-2 h-4 w-4' />
|
||||
Add Custom Model
|
||||
</Button>
|
||||
)}
|
||||
<Button
|
||||
variant='outline'
|
||||
size='sm'
|
||||
onClick={() =>
|
||||
handleAddModel(provider.id)
|
||||
}
|
||||
>
|
||||
<Plus className='mr-2 h-4 w-4' />
|
||||
Add
|
||||
</Button>
|
||||
</div>
|
||||
{providerModels.db_models.length === 0 ? (
|
||||
<div className='text-muted-foreground py-4 text-center text-sm'>
|
||||
No custom models configured
|
||||
</div>
|
||||
) : (
|
||||
<div className='space-y-2'>
|
||||
@@ -1000,103 +1073,48 @@ export default function ProvidersPage() {
|
||||
>
|
||||
<Pencil className='h-4 w-4' />
|
||||
</Button>
|
||||
<Button
|
||||
variant='ghost'
|
||||
size='icon'
|
||||
className='text-destructive hover:text-destructive h-8 w-8'
|
||||
onClick={() =>
|
||||
handleDeleteModel(
|
||||
provider.id,
|
||||
model.id
|
||||
)
|
||||
}
|
||||
disabled={
|
||||
deleteModelMutation.isPending
|
||||
}
|
||||
>
|
||||
<Trash2 className='h-4 w-4' />
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
) : (
|
||||
// Has provided models - show tabs
|
||||
<Tabs
|
||||
defaultValue='provided'
|
||||
className='w-full'
|
||||
</TabsContent>
|
||||
<TabsContent
|
||||
value='provided'
|
||||
className='mt-4 space-y-2'
|
||||
>
|
||||
<TabsList className='grid w-full grid-cols-2'>
|
||||
<TabsTrigger
|
||||
value='provided'
|
||||
className='text-xs sm:text-sm'
|
||||
>
|
||||
<span className='hidden sm:inline'>
|
||||
Provided Models
|
||||
</span>
|
||||
<span className='sm:hidden'>
|
||||
Provided
|
||||
</span>
|
||||
<Badge
|
||||
variant='secondary'
|
||||
className='ml-1 text-xs sm:ml-2'
|
||||
>
|
||||
{providerModels.remote_models.length}
|
||||
</Badge>
|
||||
</TabsTrigger>
|
||||
<TabsTrigger
|
||||
value='custom'
|
||||
className='text-xs sm:text-sm'
|
||||
>
|
||||
<span className='hidden sm:inline'>
|
||||
Custom Models
|
||||
</span>
|
||||
<span className='sm:hidden'>Custom</span>
|
||||
<Badge
|
||||
variant='secondary'
|
||||
className='ml-1 text-xs sm:ml-2'
|
||||
>
|
||||
{providerModels.db_models.length}
|
||||
</Badge>
|
||||
</TabsTrigger>
|
||||
</TabsList>
|
||||
<TabsContent
|
||||
value='custom'
|
||||
className='mt-4 space-y-2'
|
||||
>
|
||||
<div className='flex items-center justify-between'>
|
||||
{providerModels.db_models.length > 0 && (
|
||||
<div className='text-muted-foreground text-sm'>
|
||||
Custom models override or extend the
|
||||
provider's catalog.
|
||||
</div>
|
||||
)}
|
||||
<Button
|
||||
variant='outline'
|
||||
size='sm'
|
||||
onClick={() =>
|
||||
handleAddModel(provider.id)
|
||||
}
|
||||
>
|
||||
<Plus className='mr-2 h-4 w-4' />
|
||||
Add
|
||||
</Button>
|
||||
</div>
|
||||
{providerModels.db_models.length === 0 ? (
|
||||
<div className='text-muted-foreground py-4 text-center text-sm'>
|
||||
No custom models configured
|
||||
{providerModels.remote_models.length > 0 ? (
|
||||
<>
|
||||
<div className='text-muted-foreground mb-3 text-sm'>
|
||||
Models automatically discovered from the
|
||||
provider's catalog.
|
||||
</div>
|
||||
) : (
|
||||
<div className='space-y-2'>
|
||||
{providerModels.db_models.map(
|
||||
{providerModels.remote_models.map(
|
||||
(model) => (
|
||||
<div
|
||||
key={model.id}
|
||||
className='hover:bg-accent flex flex-col gap-2 rounded-lg border p-3 transition-colors sm:flex-row sm:items-center sm:justify-between'
|
||||
>
|
||||
<div className='min-w-0 flex-1'>
|
||||
<div className='flex flex-col gap-1 sm:flex-row sm:items-center sm:gap-2'>
|
||||
<span className='truncate font-mono text-sm font-medium'>
|
||||
{model.id}
|
||||
</span>
|
||||
<Badge
|
||||
variant={
|
||||
model.enabled
|
||||
? 'default'
|
||||
: 'secondary'
|
||||
}
|
||||
className='w-fit text-xs'
|
||||
>
|
||||
{model.enabled
|
||||
? 'Enabled'
|
||||
: 'Disabled'}
|
||||
</Badge>
|
||||
<div className='truncate font-mono text-sm font-medium'>
|
||||
{model.id}
|
||||
</div>
|
||||
<div className='text-muted-foreground mt-1 text-xs break-words'>
|
||||
{model.description ||
|
||||
@@ -1109,79 +1127,32 @@ export default function ProvidersPage() {
|
||||
tokens
|
||||
</div>
|
||||
<Button
|
||||
variant='ghost'
|
||||
size='icon'
|
||||
className='h-8 w-8'
|
||||
variant='outline'
|
||||
size='sm'
|
||||
className='h-7 text-xs'
|
||||
onClick={() =>
|
||||
handleEditModel(
|
||||
handleOverrideModel(
|
||||
provider.id,
|
||||
model
|
||||
)
|
||||
}
|
||||
>
|
||||
<Pencil className='h-4 w-4' />
|
||||
<Plus className='mr-1 h-3 w-3' />
|
||||
Override
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
)}
|
||||
</div>
|
||||
)}
|
||||
</TabsContent>
|
||||
<TabsContent
|
||||
value='provided'
|
||||
className='mt-4 space-y-2'
|
||||
>
|
||||
{providerModels.remote_models.length >
|
||||
0 && (
|
||||
<div className='text-muted-foreground mb-3 text-sm'>
|
||||
Models automatically discovered from the
|
||||
provider's catalog.
|
||||
</div>
|
||||
)}
|
||||
<div className='space-y-2'>
|
||||
{providerModels.remote_models.map(
|
||||
(model) => (
|
||||
<div
|
||||
key={model.id}
|
||||
className='hover:bg-accent flex flex-col gap-2 rounded-lg border p-3 transition-colors sm:flex-row sm:items-center sm:justify-between'
|
||||
>
|
||||
<div className='min-w-0 flex-1'>
|
||||
<div className='truncate font-mono text-sm font-medium'>
|
||||
{model.id}
|
||||
</div>
|
||||
<div className='text-muted-foreground mt-1 text-xs break-words'>
|
||||
{model.description ||
|
||||
model.name}
|
||||
</div>
|
||||
</div>
|
||||
<div className='flex items-center gap-2'>
|
||||
<div className='text-muted-foreground text-xs whitespace-nowrap'>
|
||||
{model.context_length?.toLocaleString()}{' '}
|
||||
tokens
|
||||
</div>
|
||||
<Button
|
||||
variant='outline'
|
||||
size='sm'
|
||||
className='h-7 text-xs'
|
||||
onClick={() =>
|
||||
handleOverrideModel(
|
||||
provider.id,
|
||||
model
|
||||
)
|
||||
}
|
||||
>
|
||||
<Plus className='mr-1 h-3 w-3' />
|
||||
Override
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
)}
|
||||
</>
|
||||
) : (
|
||||
<div className='text-muted-foreground py-4 text-center text-sm'>
|
||||
No provided models available
|
||||
</div>
|
||||
</TabsContent>
|
||||
</Tabs>
|
||||
)
|
||||
)}
|
||||
</TabsContent>
|
||||
</Tabs>
|
||||
) : null}
|
||||
</div>
|
||||
)}
|
||||
|
||||
Reference in New Issue
Block a user