Spaces:
Running
Running
add provider
Browse files- src/lib/components/chat/User.svelte +1 -0
- src/lib/components/model/SettingsModel.svelte +60 -4
- src/lib/components/ui/select/index.ts +37 -0
- src/lib/components/ui/select/select-content.svelte +45 -0
- src/lib/components/ui/select/select-group-heading.svelte +21 -0
- src/lib/components/ui/select/select-group.svelte +7 -0
- src/lib/components/ui/select/select-item.svelte +38 -0
- src/lib/components/ui/select/select-label.svelte +20 -0
- src/lib/components/ui/select/select-portal.svelte +7 -0
- src/lib/components/ui/select/select-scroll-down-button.svelte +20 -0
- src/lib/components/ui/select/select-scroll-up-button.svelte +20 -0
- src/lib/components/ui/select/select-separator.svelte +18 -0
- src/lib/components/ui/select/select-trigger.svelte +29 -0
- src/lib/components/ui/select/select.svelte +11 -0
- src/lib/components/ui/separator/index.ts +7 -0
- src/lib/components/ui/separator/separator.svelte +21 -0
- src/lib/helpers/types.ts +1 -0
- src/lib/state/models.svelte.ts +2 -1
- src/routes/api/+server.ts +2 -2
src/lib/components/chat/User.svelte
CHANGED
|
@@ -118,6 +118,7 @@
|
|
| 118 |
body: JSON.stringify({
|
| 119 |
model: model.id,
|
| 120 |
prompt,
|
|
|
|
| 121 |
options: {
|
| 122 |
temperature: model.temperature,
|
| 123 |
max_tokens: model.max_tokens,
|
|
|
|
| 118 |
body: JSON.stringify({
|
| 119 |
model: model.id,
|
| 120 |
prompt,
|
| 121 |
+
provider: model.provider,
|
| 122 |
options: {
|
| 123 |
temperature: model.temperature,
|
| 124 |
max_tokens: model.max_tokens,
|
src/lib/components/model/SettingsModel.svelte
CHANGED
|
@@ -1,12 +1,14 @@
|
|
| 1 |
<script lang="ts">
|
| 2 |
import type { Snippet } from 'svelte';
|
| 3 |
-
import { X } from '@lucide/svelte';
|
| 4 |
|
| 5 |
import * as Popover from '$lib/components/ui/popover/index.js';
|
| 6 |
import type { ChatModel } from '$lib/helpers/types';
|
| 7 |
import { Button } from '$lib/components/ui/button';
|
| 8 |
import { Slider } from '$lib/components/ui/slider';
|
| 9 |
import Input from '$lib/components/ui/input/input.svelte';
|
|
|
|
|
|
|
| 10 |
|
| 11 |
let {
|
| 12 |
model,
|
|
@@ -25,14 +27,30 @@
|
|
| 25 |
// svelte-ignore state_referenced_locally
|
| 26 |
let top_p = $state<number | undefined>(model.top_p ?? undefined);
|
| 27 |
let open = $state<boolean>(false);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 28 |
</script>
|
| 29 |
|
| 30 |
<Popover.Root bind:open>
|
| 31 |
<Popover.Trigger>{@render children?.()}</Popover.Trigger>
|
| 32 |
<Popover.Content class="w-80 rounded-2xl p-0">
|
| 33 |
<div class="grid gap-4">
|
| 34 |
-
<header class="
|
| 35 |
-
<h4 class="text-sm leading-none font-medium text-
|
| 36 |
</header>
|
| 37 |
<main class="grid gap-5 px-5 py-0">
|
| 38 |
<div class="space-y-1">
|
|
@@ -128,12 +146,50 @@
|
|
| 128 |
{/if}
|
| 129 |
</div>
|
| 130 |
</main>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 131 |
<footer class="flex justify-end border-t border-border px-5 pt-3 pb-3">
|
| 132 |
<Button
|
| 133 |
variant="default"
|
| 134 |
size="xs"
|
| 135 |
onclick={() => {
|
| 136 |
-
onSave({ ...model, temperature, max_tokens, top_p });
|
| 137 |
open = false;
|
| 138 |
}}>Save Settings</Button
|
| 139 |
>
|
|
|
|
| 1 |
<script lang="ts">
|
| 2 |
import type { Snippet } from 'svelte';
|
| 3 |
+
import { DollarSign, Star, X, Zap } from '@lucide/svelte';
|
| 4 |
|
| 5 |
import * as Popover from '$lib/components/ui/popover/index.js';
|
| 6 |
import type { ChatModel } from '$lib/helpers/types';
|
| 7 |
import { Button } from '$lib/components/ui/button';
|
| 8 |
import { Slider } from '$lib/components/ui/slider';
|
| 9 |
import Input from '$lib/components/ui/input/input.svelte';
|
| 10 |
+
import * as Select from '$lib/components/ui/select/index.js';
|
| 11 |
+
import { modeStorageKey } from 'mode-watcher';
|
| 12 |
|
| 13 |
let {
|
| 14 |
model,
|
|
|
|
| 27 |
// svelte-ignore state_referenced_locally
|
| 28 |
let top_p = $state<number | undefined>(model.top_p ?? undefined);
|
| 29 |
let open = $state<boolean>(false);
|
| 30 |
+
// svelte-ignore state_referenced_locally
|
| 31 |
+
let provider = $state<string>(model.provider ?? 'auto');
|
| 32 |
+
let availableProviders = $state<string[]>([]);
|
| 33 |
+
|
| 34 |
+
async function getProviders() {
|
| 35 |
+
const response = await fetch(`https://router.huggingface.co/v1/models/${model.id}`);
|
| 36 |
+
const { data } = await response.json();
|
| 37 |
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
| 38 |
+
return data.providers.map((provider: any) => provider.provider);
|
| 39 |
+
}
|
| 40 |
+
|
| 41 |
+
$effect(() => {
|
| 42 |
+
getProviders().then((providers) => {
|
| 43 |
+
availableProviders = providers;
|
| 44 |
+
});
|
| 45 |
+
});
|
| 46 |
</script>
|
| 47 |
|
| 48 |
<Popover.Root bind:open>
|
| 49 |
<Popover.Trigger>{@render children?.()}</Popover.Trigger>
|
| 50 |
<Popover.Content class="w-80 rounded-2xl p-0">
|
| 51 |
<div class="grid gap-4">
|
| 52 |
+
<header class="px-5 pt-4">
|
| 53 |
+
<h4 class="text-sm leading-none font-medium text-muted-foreground">Generation Settings</h4>
|
| 54 |
</header>
|
| 55 |
<main class="grid gap-5 px-5 py-0">
|
| 56 |
<div class="space-y-1">
|
|
|
|
| 146 |
{/if}
|
| 147 |
</div>
|
| 148 |
</main>
|
| 149 |
+
<header class="border-t border-border px-5 pt-4">
|
| 150 |
+
<h4 class="text-sm leading-none font-medium text-muted-foreground">Provider</h4>
|
| 151 |
+
</header>
|
| 152 |
+
<main class="w-full px-5">
|
| 153 |
+
<Select.Root type="single" bind:value={provider}>
|
| 154 |
+
<Select.Trigger class="flex w-full items-center justify-between gap-2 capitalize">
|
| 155 |
+
<div class="flex items-center gap-2">
|
| 156 |
+
{#if provider === 'auto'}
|
| 157 |
+
<Star class="size-4 fill-yellow-500 text-yellow-500" />
|
| 158 |
+
{:else}
|
| 159 |
+
<img
|
| 160 |
+
src={`https://huggingface.co/api/avatars/${provider}`}
|
| 161 |
+
alt={provider}
|
| 162 |
+
class="size-4"
|
| 163 |
+
/>
|
| 164 |
+
{/if}
|
| 165 |
+
{provider}
|
| 166 |
+
</div>
|
| 167 |
+
</Select.Trigger>
|
| 168 |
+
<Select.Content>
|
| 169 |
+
<Select.Item value="auto"
|
| 170 |
+
><Star class="size-4 fill-yellow-500 text-yellow-500" /> Auto</Select.Item
|
| 171 |
+
>
|
| 172 |
+
{#each availableProviders as provider}
|
| 173 |
+
<Select.Item value={provider}>
|
| 174 |
+
<div class="flex items-center gap-2">
|
| 175 |
+
<img
|
| 176 |
+
src={`https://huggingface.co/api/avatars/${provider}`}
|
| 177 |
+
alt={provider}
|
| 178 |
+
class="size-4"
|
| 179 |
+
/>
|
| 180 |
+
{provider}
|
| 181 |
+
</div>
|
| 182 |
+
</Select.Item>
|
| 183 |
+
{/each}
|
| 184 |
+
</Select.Content>
|
| 185 |
+
</Select.Root>
|
| 186 |
+
</main>
|
| 187 |
<footer class="flex justify-end border-t border-border px-5 pt-3 pb-3">
|
| 188 |
<Button
|
| 189 |
variant="default"
|
| 190 |
size="xs"
|
| 191 |
onclick={() => {
|
| 192 |
+
onSave({ ...model, temperature, max_tokens, top_p, provider });
|
| 193 |
open = false;
|
| 194 |
}}>Save Settings</Button
|
| 195 |
>
|
src/lib/components/ui/select/index.ts
ADDED
|
@@ -0,0 +1,37 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import Root from "./select.svelte";
|
| 2 |
+
import Group from "./select-group.svelte";
|
| 3 |
+
import Label from "./select-label.svelte";
|
| 4 |
+
import Item from "./select-item.svelte";
|
| 5 |
+
import Content from "./select-content.svelte";
|
| 6 |
+
import Trigger from "./select-trigger.svelte";
|
| 7 |
+
import Separator from "./select-separator.svelte";
|
| 8 |
+
import ScrollDownButton from "./select-scroll-down-button.svelte";
|
| 9 |
+
import ScrollUpButton from "./select-scroll-up-button.svelte";
|
| 10 |
+
import GroupHeading from "./select-group-heading.svelte";
|
| 11 |
+
import Portal from "./select-portal.svelte";
|
| 12 |
+
|
| 13 |
+
export {
|
| 14 |
+
Root,
|
| 15 |
+
Group,
|
| 16 |
+
Label,
|
| 17 |
+
Item,
|
| 18 |
+
Content,
|
| 19 |
+
Trigger,
|
| 20 |
+
Separator,
|
| 21 |
+
ScrollDownButton,
|
| 22 |
+
ScrollUpButton,
|
| 23 |
+
GroupHeading,
|
| 24 |
+
Portal,
|
| 25 |
+
//
|
| 26 |
+
Root as Select,
|
| 27 |
+
Group as SelectGroup,
|
| 28 |
+
Label as SelectLabel,
|
| 29 |
+
Item as SelectItem,
|
| 30 |
+
Content as SelectContent,
|
| 31 |
+
Trigger as SelectTrigger,
|
| 32 |
+
Separator as SelectSeparator,
|
| 33 |
+
ScrollDownButton as SelectScrollDownButton,
|
| 34 |
+
ScrollUpButton as SelectScrollUpButton,
|
| 35 |
+
GroupHeading as SelectGroupHeading,
|
| 36 |
+
Portal as SelectPortal,
|
| 37 |
+
};
|
src/lib/components/ui/select/select-content.svelte
ADDED
|
@@ -0,0 +1,45 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
<script lang="ts">
|
| 2 |
+
import { Select as SelectPrimitive } from "bits-ui";
|
| 3 |
+
import SelectPortal from "./select-portal.svelte";
|
| 4 |
+
import SelectScrollUpButton from "./select-scroll-up-button.svelte";
|
| 5 |
+
import SelectScrollDownButton from "./select-scroll-down-button.svelte";
|
| 6 |
+
import { cn, type WithoutChild } from "$lib/utils.js";
|
| 7 |
+
import type { ComponentProps } from "svelte";
|
| 8 |
+
import type { WithoutChildrenOrChild } from "$lib/utils.js";
|
| 9 |
+
|
| 10 |
+
let {
|
| 11 |
+
ref = $bindable(null),
|
| 12 |
+
class: className,
|
| 13 |
+
sideOffset = 4,
|
| 14 |
+
portalProps,
|
| 15 |
+
children,
|
| 16 |
+
preventScroll = true,
|
| 17 |
+
...restProps
|
| 18 |
+
}: WithoutChild<SelectPrimitive.ContentProps> & {
|
| 19 |
+
portalProps?: WithoutChildrenOrChild<ComponentProps<typeof SelectPortal>>;
|
| 20 |
+
} = $props();
|
| 21 |
+
</script>
|
| 22 |
+
|
| 23 |
+
<SelectPortal {...portalProps}>
|
| 24 |
+
<SelectPrimitive.Content
|
| 25 |
+
bind:ref
|
| 26 |
+
{sideOffset}
|
| 27 |
+
{preventScroll}
|
| 28 |
+
data-slot="select-content"
|
| 29 |
+
class={cn(
|
| 30 |
+
"bg-popover text-popover-foreground 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-end-2 data-[side=right]:slide-in-from-start-2 data-[side=top]:slide-in-from-bottom-2 relative z-50 max-h-(--bits-select-content-available-height) min-w-[8rem] origin-(--bits-select-content-transform-origin) overflow-x-hidden overflow-y-auto rounded-md border shadow-md data-[side=bottom]:translate-y-1 data-[side=left]:-translate-x-1 data-[side=right]:translate-x-1 data-[side=top]:-translate-y-1",
|
| 31 |
+
className
|
| 32 |
+
)}
|
| 33 |
+
{...restProps}
|
| 34 |
+
>
|
| 35 |
+
<SelectScrollUpButton />
|
| 36 |
+
<SelectPrimitive.Viewport
|
| 37 |
+
class={cn(
|
| 38 |
+
"h-(--bits-select-anchor-height) w-full min-w-(--bits-select-anchor-width) scroll-my-1 p-1"
|
| 39 |
+
)}
|
| 40 |
+
>
|
| 41 |
+
{@render children?.()}
|
| 42 |
+
</SelectPrimitive.Viewport>
|
| 43 |
+
<SelectScrollDownButton />
|
| 44 |
+
</SelectPrimitive.Content>
|
| 45 |
+
</SelectPortal>
|
src/lib/components/ui/select/select-group-heading.svelte
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
<script lang="ts">
|
| 2 |
+
import { Select as SelectPrimitive } from "bits-ui";
|
| 3 |
+
import { cn } from "$lib/utils.js";
|
| 4 |
+
import type { ComponentProps } from "svelte";
|
| 5 |
+
|
| 6 |
+
let {
|
| 7 |
+
ref = $bindable(null),
|
| 8 |
+
class: className,
|
| 9 |
+
children,
|
| 10 |
+
...restProps
|
| 11 |
+
}: ComponentProps<typeof SelectPrimitive.GroupHeading> = $props();
|
| 12 |
+
</script>
|
| 13 |
+
|
| 14 |
+
<SelectPrimitive.GroupHeading
|
| 15 |
+
bind:ref
|
| 16 |
+
data-slot="select-group-heading"
|
| 17 |
+
class={cn("text-muted-foreground px-2 py-1.5 text-xs", className)}
|
| 18 |
+
{...restProps}
|
| 19 |
+
>
|
| 20 |
+
{@render children?.()}
|
| 21 |
+
</SelectPrimitive.GroupHeading>
|
src/lib/components/ui/select/select-group.svelte
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
<script lang="ts">
|
| 2 |
+
import { Select as SelectPrimitive } from "bits-ui";
|
| 3 |
+
|
| 4 |
+
let { ref = $bindable(null), ...restProps }: SelectPrimitive.GroupProps = $props();
|
| 5 |
+
</script>
|
| 6 |
+
|
| 7 |
+
<SelectPrimitive.Group bind:ref data-slot="select-group" {...restProps} />
|
src/lib/components/ui/select/select-item.svelte
ADDED
|
@@ -0,0 +1,38 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
<script lang="ts">
|
| 2 |
+
import CheckIcon from '@lucide/svelte/icons/check';
|
| 3 |
+
import { Select as SelectPrimitive } from 'bits-ui';
|
| 4 |
+
import { cn, type WithoutChild } from '$lib/utils.js';
|
| 5 |
+
|
| 6 |
+
let {
|
| 7 |
+
ref = $bindable(null),
|
| 8 |
+
class: className,
|
| 9 |
+
value,
|
| 10 |
+
label,
|
| 11 |
+
children: childrenProp,
|
| 12 |
+
...restProps
|
| 13 |
+
}: WithoutChild<SelectPrimitive.ItemProps> = $props();
|
| 14 |
+
</script>
|
| 15 |
+
|
| 16 |
+
<SelectPrimitive.Item
|
| 17 |
+
bind:ref
|
| 18 |
+
{value}
|
| 19 |
+
data-slot="select-item"
|
| 20 |
+
class={cn(
|
| 21 |
+
"relative flex w-full cursor-pointer items-center gap-2 rounded-sm py-1.5 ps-2 pe-8 text-sm outline-hidden select-none data-[disabled]:pointer-events-none data-[disabled]:opacity-50 data-[highlighted]:bg-accent data-[highlighted]:text-accent-foreground [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4 [&_svg:not([class*='text-'])]:text-muted-foreground *:[span]:last:flex *:[span]:last:items-center *:[span]:last:gap-2",
|
| 22 |
+
className
|
| 23 |
+
)}
|
| 24 |
+
{...restProps}
|
| 25 |
+
>
|
| 26 |
+
{#snippet children({ selected, highlighted })}
|
| 27 |
+
<span class="absolute end-2 flex size-3.5 items-center justify-center">
|
| 28 |
+
{#if selected}
|
| 29 |
+
<CheckIcon class="size-4" />
|
| 30 |
+
{/if}
|
| 31 |
+
</span>
|
| 32 |
+
{#if childrenProp}
|
| 33 |
+
{@render childrenProp({ selected, highlighted })}
|
| 34 |
+
{:else}
|
| 35 |
+
{label || value}
|
| 36 |
+
{/if}
|
| 37 |
+
{/snippet}
|
| 38 |
+
</SelectPrimitive.Item>
|
src/lib/components/ui/select/select-label.svelte
ADDED
|
@@ -0,0 +1,20 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
<script lang="ts">
|
| 2 |
+
import { cn, type WithElementRef } from "$lib/utils.js";
|
| 3 |
+
import type { HTMLAttributes } from "svelte/elements";
|
| 4 |
+
|
| 5 |
+
let {
|
| 6 |
+
ref = $bindable(null),
|
| 7 |
+
class: className,
|
| 8 |
+
children,
|
| 9 |
+
...restProps
|
| 10 |
+
}: WithElementRef<HTMLAttributes<HTMLDivElement>> & {} = $props();
|
| 11 |
+
</script>
|
| 12 |
+
|
| 13 |
+
<div
|
| 14 |
+
bind:this={ref}
|
| 15 |
+
data-slot="select-label"
|
| 16 |
+
class={cn("text-muted-foreground px-2 py-1.5 text-xs", className)}
|
| 17 |
+
{...restProps}
|
| 18 |
+
>
|
| 19 |
+
{@render children?.()}
|
| 20 |
+
</div>
|
src/lib/components/ui/select/select-portal.svelte
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
<script lang="ts">
|
| 2 |
+
import { Select as SelectPrimitive } from "bits-ui";
|
| 3 |
+
|
| 4 |
+
let { ...restProps }: SelectPrimitive.PortalProps = $props();
|
| 5 |
+
</script>
|
| 6 |
+
|
| 7 |
+
<SelectPrimitive.Portal {...restProps} />
|
src/lib/components/ui/select/select-scroll-down-button.svelte
ADDED
|
@@ -0,0 +1,20 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
<script lang="ts">
|
| 2 |
+
import ChevronDownIcon from "@lucide/svelte/icons/chevron-down";
|
| 3 |
+
import { Select as SelectPrimitive } from "bits-ui";
|
| 4 |
+
import { cn, type WithoutChildrenOrChild } from "$lib/utils.js";
|
| 5 |
+
|
| 6 |
+
let {
|
| 7 |
+
ref = $bindable(null),
|
| 8 |
+
class: className,
|
| 9 |
+
...restProps
|
| 10 |
+
}: WithoutChildrenOrChild<SelectPrimitive.ScrollDownButtonProps> = $props();
|
| 11 |
+
</script>
|
| 12 |
+
|
| 13 |
+
<SelectPrimitive.ScrollDownButton
|
| 14 |
+
bind:ref
|
| 15 |
+
data-slot="select-scroll-down-button"
|
| 16 |
+
class={cn("flex cursor-default items-center justify-center py-1", className)}
|
| 17 |
+
{...restProps}
|
| 18 |
+
>
|
| 19 |
+
<ChevronDownIcon class="size-4" />
|
| 20 |
+
</SelectPrimitive.ScrollDownButton>
|
src/lib/components/ui/select/select-scroll-up-button.svelte
ADDED
|
@@ -0,0 +1,20 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
<script lang="ts">
|
| 2 |
+
import ChevronUpIcon from "@lucide/svelte/icons/chevron-up";
|
| 3 |
+
import { Select as SelectPrimitive } from "bits-ui";
|
| 4 |
+
import { cn, type WithoutChildrenOrChild } from "$lib/utils.js";
|
| 5 |
+
|
| 6 |
+
let {
|
| 7 |
+
ref = $bindable(null),
|
| 8 |
+
class: className,
|
| 9 |
+
...restProps
|
| 10 |
+
}: WithoutChildrenOrChild<SelectPrimitive.ScrollUpButtonProps> = $props();
|
| 11 |
+
</script>
|
| 12 |
+
|
| 13 |
+
<SelectPrimitive.ScrollUpButton
|
| 14 |
+
bind:ref
|
| 15 |
+
data-slot="select-scroll-up-button"
|
| 16 |
+
class={cn("flex cursor-default items-center justify-center py-1", className)}
|
| 17 |
+
{...restProps}
|
| 18 |
+
>
|
| 19 |
+
<ChevronUpIcon class="size-4" />
|
| 20 |
+
</SelectPrimitive.ScrollUpButton>
|
src/lib/components/ui/select/select-separator.svelte
ADDED
|
@@ -0,0 +1,18 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
<script lang="ts">
|
| 2 |
+
import type { Separator as SeparatorPrimitive } from "bits-ui";
|
| 3 |
+
import { Separator } from "$lib/components/ui/separator/index.js";
|
| 4 |
+
import { cn } from "$lib/utils.js";
|
| 5 |
+
|
| 6 |
+
let {
|
| 7 |
+
ref = $bindable(null),
|
| 8 |
+
class: className,
|
| 9 |
+
...restProps
|
| 10 |
+
}: SeparatorPrimitive.RootProps = $props();
|
| 11 |
+
</script>
|
| 12 |
+
|
| 13 |
+
<Separator
|
| 14 |
+
bind:ref
|
| 15 |
+
data-slot="select-separator"
|
| 16 |
+
class={cn("bg-border pointer-events-none -mx-1 my-1 h-px", className)}
|
| 17 |
+
{...restProps}
|
| 18 |
+
/>
|
src/lib/components/ui/select/select-trigger.svelte
ADDED
|
@@ -0,0 +1,29 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
<script lang="ts">
|
| 2 |
+
import { Select as SelectPrimitive } from "bits-ui";
|
| 3 |
+
import ChevronDownIcon from "@lucide/svelte/icons/chevron-down";
|
| 4 |
+
import { cn, type WithoutChild } from "$lib/utils.js";
|
| 5 |
+
|
| 6 |
+
let {
|
| 7 |
+
ref = $bindable(null),
|
| 8 |
+
class: className,
|
| 9 |
+
children,
|
| 10 |
+
size = "default",
|
| 11 |
+
...restProps
|
| 12 |
+
}: WithoutChild<SelectPrimitive.TriggerProps> & {
|
| 13 |
+
size?: "sm" | "default";
|
| 14 |
+
} = $props();
|
| 15 |
+
</script>
|
| 16 |
+
|
| 17 |
+
<SelectPrimitive.Trigger
|
| 18 |
+
bind:ref
|
| 19 |
+
data-slot="select-trigger"
|
| 20 |
+
data-size={size}
|
| 21 |
+
class={cn(
|
| 22 |
+
"border-input data-[placeholder]:text-muted-foreground [&_svg:not([class*='text-'])]:text-muted-foreground focus-visible:border-ring focus-visible:ring-ring/50 aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive dark:bg-input/30 dark:hover:bg-input/50 flex w-fit items-center justify-between gap-2 rounded-md border bg-transparent px-3 py-2 text-sm whitespace-nowrap shadow-xs transition-[color,box-shadow] outline-none select-none focus-visible:ring-[3px] disabled:cursor-not-allowed disabled:opacity-50 data-[size=default]:h-9 data-[size=sm]:h-8 *:data-[slot=select-value]:line-clamp-1 *:data-[slot=select-value]:flex *:data-[slot=select-value]:items-center *:data-[slot=select-value]:gap-2 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4",
|
| 23 |
+
className
|
| 24 |
+
)}
|
| 25 |
+
{...restProps}
|
| 26 |
+
>
|
| 27 |
+
{@render children?.()}
|
| 28 |
+
<ChevronDownIcon class="size-4 opacity-50" />
|
| 29 |
+
</SelectPrimitive.Trigger>
|
src/lib/components/ui/select/select.svelte
ADDED
|
@@ -0,0 +1,11 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
<script lang="ts">
|
| 2 |
+
import { Select as SelectPrimitive } from "bits-ui";
|
| 3 |
+
|
| 4 |
+
let {
|
| 5 |
+
open = $bindable(false),
|
| 6 |
+
value = $bindable(),
|
| 7 |
+
...restProps
|
| 8 |
+
}: SelectPrimitive.RootProps = $props();
|
| 9 |
+
</script>
|
| 10 |
+
|
| 11 |
+
<SelectPrimitive.Root bind:open bind:value={value as never} {...restProps} />
|
src/lib/components/ui/separator/index.ts
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import Root from "./separator.svelte";
|
| 2 |
+
|
| 3 |
+
export {
|
| 4 |
+
Root,
|
| 5 |
+
//
|
| 6 |
+
Root as Separator,
|
| 7 |
+
};
|
src/lib/components/ui/separator/separator.svelte
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
<script lang="ts">
|
| 2 |
+
import { Separator as SeparatorPrimitive } from "bits-ui";
|
| 3 |
+
import { cn } from "$lib/utils.js";
|
| 4 |
+
|
| 5 |
+
let {
|
| 6 |
+
ref = $bindable(null),
|
| 7 |
+
class: className,
|
| 8 |
+
"data-slot": dataSlot = "separator",
|
| 9 |
+
...restProps
|
| 10 |
+
}: SeparatorPrimitive.RootProps = $props();
|
| 11 |
+
</script>
|
| 12 |
+
|
| 13 |
+
<SeparatorPrimitive.Root
|
| 14 |
+
bind:ref
|
| 15 |
+
data-slot={dataSlot}
|
| 16 |
+
class={cn(
|
| 17 |
+
"bg-border shrink-0 data-[orientation=horizontal]:h-px data-[orientation=horizontal]:w-full data-[orientation=vertical]:min-h-full data-[orientation=vertical]:w-px",
|
| 18 |
+
className
|
| 19 |
+
)}
|
| 20 |
+
{...restProps}
|
| 21 |
+
/>
|
src/lib/helpers/types.ts
CHANGED
|
@@ -10,6 +10,7 @@ export interface ChatModel {
|
|
| 10 |
temperature?: number;
|
| 11 |
max_tokens?: number;
|
| 12 |
top_p?: number;
|
|
|
|
| 13 |
}
|
| 14 |
export interface ChatMessage {
|
| 15 |
role: 'user' | 'assistant';
|
|
|
|
| 10 |
temperature?: number;
|
| 11 |
max_tokens?: number;
|
| 12 |
top_p?: number;
|
| 13 |
+
provider: string;
|
| 14 |
}
|
| 15 |
export interface ChatMessage {
|
| 16 |
role: 'user' | 'assistant';
|
src/lib/state/models.svelte.ts
CHANGED
|
@@ -12,7 +12,8 @@ function mapHFModelToChatModel(hfModel: ChatModel): ChatModel {
|
|
| 12 |
author,
|
| 13 |
modelId: hfModel.modelId,
|
| 14 |
avatarUrl: `https://huggingface.co/api/avatars/${author}`,
|
| 15 |
-
pipeline_tag: isTextGen ? 'text-generation' : isImageText ? 'image-text-to-text' : undefined
|
|
|
|
| 16 |
};
|
| 17 |
}
|
| 18 |
|
|
|
|
| 12 |
author,
|
| 13 |
modelId: hfModel.modelId,
|
| 14 |
avatarUrl: `https://huggingface.co/api/avatars/${author}`,
|
| 15 |
+
pipeline_tag: isTextGen ? 'text-generation' : isImageText ? 'image-text-to-text' : undefined,
|
| 16 |
+
provider: 'auto'
|
| 17 |
};
|
| 18 |
}
|
| 19 |
|
src/routes/api/+server.ts
CHANGED
|
@@ -4,7 +4,7 @@ import { InferenceClient } from '@huggingface/inference';
|
|
| 4 |
import { env } from '$env/dynamic/private';
|
| 5 |
|
| 6 |
export async function POST({ request }: RequestEvent) {
|
| 7 |
-
const { model, prompt, messages, options } = await request.json();
|
| 8 |
|
| 9 |
if (!model || !prompt) {
|
| 10 |
return json({ error: 'Model and prompt are required' }, { status: 400 });
|
|
@@ -14,7 +14,7 @@ export async function POST({ request }: RequestEvent) {
|
|
| 14 |
|
| 15 |
const stream = client.chatCompletionStream(
|
| 16 |
{
|
| 17 |
-
model: model,
|
| 18 |
...(options ?? {}),
|
| 19 |
messages: [
|
| 20 |
{
|
|
|
|
| 4 |
import { env } from '$env/dynamic/private';
|
| 5 |
|
| 6 |
export async function POST({ request }: RequestEvent) {
|
| 7 |
+
const { model, prompt, messages, options, provider = 'auto' } = await request.json();
|
| 8 |
|
| 9 |
if (!model || !prompt) {
|
| 10 |
return json({ error: 'Model and prompt are required' }, { status: 400 });
|
|
|
|
| 14 |
|
| 15 |
const stream = client.chatCompletionStream(
|
| 16 |
{
|
| 17 |
+
model: model + (provider !== 'auto' ? `:${provider}` : ''),
|
| 18 |
...(options ?? {}),
|
| 19 |
messages: [
|
| 20 |
{
|