Spaces:
Runtime error
Runtime error
Thomas G. Lopes
commited on
Commit
·
c3571d4
1
Parent(s):
de05e6a
better loading logic
Browse files- package.json +1 -1
- pnpm-lock.yaml +11 -11
- src/lib/components/inference-playground/hf-token-modal.svelte +96 -93
- src/lib/components/inference-playground/playground.svelte +6 -29
- src/lib/state/models.svelte.ts +9 -1
- src/routes/+layout.svelte +3 -2
- src/routes/canvas/+page.svelte +1 -0
- src/routes/canvas/chat-node.svelte +2 -0
package.json
CHANGED
@@ -35,7 +35,7 @@
|
|
35 |
"@samchon/openapi": "^4.7.1",
|
36 |
"@sveltejs/adapter-auto": "^3.3.1",
|
37 |
"@sveltejs/adapter-node": "^5.3.2",
|
38 |
-
"@sveltejs/kit": "^2.
|
39 |
"@sveltejs/vite-plugin-svelte": "^4.0.4",
|
40 |
"@tailwindcss/container-queries": "^0.1.1",
|
41 |
"@tailwindcss/postcss": "^4.0.9",
|
|
|
35 |
"@samchon/openapi": "^4.7.1",
|
36 |
"@sveltejs/adapter-auto": "^3.3.1",
|
37 |
"@sveltejs/adapter-node": "^5.3.2",
|
38 |
+
"@sveltejs/kit": "^2.42.1",
|
39 |
"@sveltejs/vite-plugin-svelte": "^4.0.4",
|
40 |
"@tailwindcss/container-queries": "^0.1.1",
|
41 |
"@tailwindcss/postcss": "^4.0.9",
|
pnpm-lock.yaml
CHANGED
@@ -86,13 +86,13 @@ importers:
|
|
86 |
version: 4.7.1
|
87 |
'@sveltejs/adapter-auto':
|
88 |
specifier: ^3.3.1
|
89 |
-
version: 3.3.1(@sveltejs/kit@2.
|
90 |
'@sveltejs/adapter-node':
|
91 |
specifier: ^5.3.2
|
92 |
-
version: 5.3.2(@sveltejs/kit@2.
|
93 |
'@sveltejs/kit':
|
94 |
-
specifier: ^2.
|
95 |
-
version: 2.
|
96 |
'@sveltejs/vite-plugin-svelte':
|
97 |
specifier: ^4.0.4
|
98 |
version: 4.0.4(svelte@5.38.10)(vite@5.4.14(@types/node@22.14.1)(lightningcss@1.29.1))
|
@@ -942,8 +942,8 @@ packages:
|
|
942 |
peerDependencies:
|
943 |
'@sveltejs/kit': ^2.4.0
|
944 |
|
945 |
-
'@sveltejs/kit@2.
|
946 |
-
resolution: {integrity: sha512-
|
947 |
engines: {node: '>=18.13'}
|
948 |
hasBin: true
|
949 |
peerDependencies:
|
@@ -4076,20 +4076,20 @@ snapshots:
|
|
4076 |
dependencies:
|
4077 |
acorn: 8.15.0
|
4078 |
|
4079 |
-
'@sveltejs/adapter-auto@3.3.1(@sveltejs/kit@2.
|
4080 |
dependencies:
|
4081 |
-
'@sveltejs/kit': 2.
|
4082 |
import-meta-resolve: 4.1.0
|
4083 |
|
4084 |
-
'@sveltejs/adapter-node@5.3.2(@sveltejs/kit@2.
|
4085 |
dependencies:
|
4086 |
'@rollup/plugin-commonjs': 28.0.2(rollup@4.34.9)
|
4087 |
'@rollup/plugin-json': 6.1.0(rollup@4.34.9)
|
4088 |
'@rollup/plugin-node-resolve': 16.0.0(rollup@4.34.9)
|
4089 |
-
'@sveltejs/kit': 2.
|
4090 |
rollup: 4.34.9
|
4091 |
|
4092 |
-
'@sveltejs/kit@2.
|
4093 |
dependencies:
|
4094 |
'@standard-schema/spec': 1.0.0
|
4095 |
'@sveltejs/acorn-typescript': 1.0.5(acorn@8.15.0)
|
|
|
86 |
version: 4.7.1
|
87 |
'@sveltejs/adapter-auto':
|
88 |
specifier: ^3.3.1
|
89 |
+
version: 3.3.1(@sveltejs/kit@2.42.1(@sveltejs/vite-plugin-svelte@4.0.4(svelte@5.38.10)(vite@5.4.14(@types/node@22.14.1)(lightningcss@1.29.1)))(svelte@5.38.10)(vite@5.4.14(@types/node@22.14.1)(lightningcss@1.29.1)))
|
90 |
'@sveltejs/adapter-node':
|
91 |
specifier: ^5.3.2
|
92 |
+
version: 5.3.2(@sveltejs/kit@2.42.1(@sveltejs/vite-plugin-svelte@4.0.4(svelte@5.38.10)(vite@5.4.14(@types/node@22.14.1)(lightningcss@1.29.1)))(svelte@5.38.10)(vite@5.4.14(@types/node@22.14.1)(lightningcss@1.29.1)))
|
93 |
'@sveltejs/kit':
|
94 |
+
specifier: ^2.42.1
|
95 |
+
version: 2.42.1(@sveltejs/vite-plugin-svelte@4.0.4(svelte@5.38.10)(vite@5.4.14(@types/node@22.14.1)(lightningcss@1.29.1)))(svelte@5.38.10)(vite@5.4.14(@types/node@22.14.1)(lightningcss@1.29.1))
|
96 |
'@sveltejs/vite-plugin-svelte':
|
97 |
specifier: ^4.0.4
|
98 |
version: 4.0.4(svelte@5.38.10)(vite@5.4.14(@types/node@22.14.1)(lightningcss@1.29.1))
|
|
|
942 |
peerDependencies:
|
943 |
'@sveltejs/kit': ^2.4.0
|
944 |
|
945 |
+
'@sveltejs/kit@2.42.1':
|
946 |
+
resolution: {integrity: sha512-SoWdb/OxEKHMlXZ78eNZa4pR1YdOGnUfcFj5NylJv+ZaTrnHK5xapw+7RJP2MiS1D4T+sEH25/tmMtmEl8p6VA==}
|
947 |
engines: {node: '>=18.13'}
|
948 |
hasBin: true
|
949 |
peerDependencies:
|
|
|
4076 |
dependencies:
|
4077 |
acorn: 8.15.0
|
4078 |
|
4079 |
+
'@sveltejs/adapter-auto@3.3.1(@sveltejs/kit@2.42.1(@sveltejs/vite-plugin-svelte@4.0.4(svelte@5.38.10)(vite@5.4.14(@types/node@22.14.1)(lightningcss@1.29.1)))(svelte@5.38.10)(vite@5.4.14(@types/node@22.14.1)(lightningcss@1.29.1)))':
|
4080 |
dependencies:
|
4081 |
+
'@sveltejs/kit': 2.42.1(@sveltejs/vite-plugin-svelte@4.0.4(svelte@5.38.10)(vite@5.4.14(@types/node@22.14.1)(lightningcss@1.29.1)))(svelte@5.38.10)(vite@5.4.14(@types/node@22.14.1)(lightningcss@1.29.1))
|
4082 |
import-meta-resolve: 4.1.0
|
4083 |
|
4084 |
+
'@sveltejs/adapter-node@5.3.2(@sveltejs/kit@2.42.1(@sveltejs/vite-plugin-svelte@4.0.4(svelte@5.38.10)(vite@5.4.14(@types/node@22.14.1)(lightningcss@1.29.1)))(svelte@5.38.10)(vite@5.4.14(@types/node@22.14.1)(lightningcss@1.29.1)))':
|
4085 |
dependencies:
|
4086 |
'@rollup/plugin-commonjs': 28.0.2(rollup@4.34.9)
|
4087 |
'@rollup/plugin-json': 6.1.0(rollup@4.34.9)
|
4088 |
'@rollup/plugin-node-resolve': 16.0.0(rollup@4.34.9)
|
4089 |
+
'@sveltejs/kit': 2.42.1(@sveltejs/vite-plugin-svelte@4.0.4(svelte@5.38.10)(vite@5.4.14(@types/node@22.14.1)(lightningcss@1.29.1)))(svelte@5.38.10)(vite@5.4.14(@types/node@22.14.1)(lightningcss@1.29.1))
|
4090 |
rollup: 4.34.9
|
4091 |
|
4092 |
+
'@sveltejs/kit@2.42.1(@sveltejs/vite-plugin-svelte@4.0.4(svelte@5.38.10)(vite@5.4.14(@types/node@22.14.1)(lightningcss@1.29.1)))(svelte@5.38.10)(vite@5.4.14(@types/node@22.14.1)(lightningcss@1.29.1))':
|
4093 |
dependencies:
|
4094 |
'@standard-schema/spec': 1.0.0
|
4095 |
'@sveltejs/acorn-typescript': 1.0.5(acorn@8.15.0)
|
src/lib/components/inference-playground/hf-token-modal.svelte
CHANGED
@@ -1,121 +1,124 @@
|
|
1 |
<script lang="ts">
|
2 |
-
import { createBubbler, preventDefault } from "svelte/legacy";
|
3 |
-
|
4 |
-
const bubble = createBubbler();
|
5 |
import { clickOutside } from "$lib/attachments/click-outside.js";
|
6 |
-
import { createEventDispatcher, onDestroy, onMount } from "svelte";
|
7 |
|
8 |
-
import IconCross from "~icons/carbon/close";
|
9 |
import { autofocus } from "$lib/attachments/autofocus.js";
|
10 |
-
|
11 |
-
|
12 |
-
storeLocallyHfToken?: boolean;
|
13 |
-
}
|
14 |
-
|
15 |
-
let { storeLocallyHfToken = $bindable(false) }: Props = $props();
|
16 |
|
17 |
let backdropEl = $state<HTMLDivElement>();
|
18 |
let modalEl = $state<HTMLDivElement>();
|
19 |
|
20 |
-
const dispatch = createEventDispatcher<{ close: void }>();
|
21 |
-
|
22 |
function handleKeydown(event: KeyboardEvent) {
|
23 |
const { key } = event;
|
24 |
if (key === "Escape") {
|
25 |
event.preventDefault();
|
26 |
-
|
27 |
}
|
28 |
}
|
29 |
|
30 |
-
|
31 |
-
|
32 |
-
|
33 |
-
|
34 |
-
onDestroy(() => {
|
35 |
-
// remove inert attribute if this is the last modal
|
36 |
-
if (document.querySelectorAll('[role="dialog"]:not(#app *)').length === 1) {
|
37 |
document.getElementById("app")?.removeAttribute("inert");
|
38 |
}
|
39 |
});
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
40 |
</script>
|
41 |
|
42 |
-
|
43 |
-
id="default-modal"
|
44 |
-
aria-hidden="true"
|
45 |
-
class="fixed inset-0 z-50 flex items-center justify-center overflow-hidden bg-black/85"
|
46 |
-
bind:this={backdropEl}
|
47 |
-
>
|
48 |
<div
|
49 |
-
|
50 |
-
|
51 |
-
class="
|
52 |
-
bind:this={
|
53 |
-
onkeydown={handleKeydown}
|
54 |
-
{@attach clickOutside(() => dispatch("close"))}
|
55 |
>
|
56 |
-
<
|
57 |
-
|
58 |
-
|
59 |
-
|
60 |
-
|
61 |
-
|
62 |
-
|
63 |
-
|
64 |
-
|
65 |
-
<
|
66 |
-
|
67 |
-
|
68 |
-
|
69 |
-
|
70 |
-
|
71 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
72 |
</div>
|
73 |
-
<
|
74 |
-
|
75 |
-
|
76 |
-
|
77 |
-
<div class="p-4 md:p-5">
|
78 |
-
<p class="mb-5 text-base leading-relaxed text-gray-800 2xl:text-balance dark:text-gray-300">
|
79 |
-
You need a free Hugging Face token to use this application. <strong class="font-semibold"
|
80 |
-
>Make sure you create a token with Inference API permission.</strong
|
81 |
-
><br /> Your token is kept safe by only being used from your browser.
|
82 |
-
</p>
|
83 |
-
<div>
|
84 |
-
<label for="hf-token" class="mb-2 block text-sm font-medium text-gray-900 dark:text-white">
|
85 |
-
Hugging Face Token
|
86 |
-
</label>
|
87 |
-
<input
|
88 |
-
required
|
89 |
-
placeholder="Enter HF Token"
|
90 |
-
type="text"
|
91 |
-
id="hf-token"
|
92 |
-
name="hf-token"
|
93 |
-
class="block w-full rounded-lg border border-gray-300 bg-gray-50 p-2.5 text-sm text-gray-900 focus:border-blue-500 focus:ring-blue-500 dark:border-gray-600 dark:bg-gray-700 dark:text-white dark:placeholder-gray-400 dark:focus:border-blue-500 dark:focus:ring-blue-500"
|
94 |
-
{@attach autofocus()}
|
95 |
-
/>
|
96 |
</div>
|
97 |
-
<label class="mt-4 flex items-center gap-x-1.5 text-gray-900 dark:text-gray-200">
|
98 |
-
<input type="checkbox" bind:checked={storeLocallyHfToken} />
|
99 |
-
<p class="text-sm leading-none">Save to local storage for future use</p></label
|
100 |
-
>
|
101 |
-
</div>
|
102 |
|
103 |
-
|
104 |
-
|
105 |
-
|
106 |
-
href="https://huggingface.co/settings/tokens/new?ownUserPermissions=inference.serverless.write&tokenType=fineGrained"
|
107 |
-
tabindex="-1"
|
108 |
-
target="_blank"
|
109 |
-
class="rounded-lg border border-gray-200 bg-white px-5 py-2.5 text-sm font-medium text-gray-900 hover:bg-gray-100 hover:text-blue-700 focus:z-10 focus:ring-4 focus:ring-gray-100 focus:outline-hidden dark:border-gray-600 dark:bg-gray-800 dark:text-gray-400 dark:hover:bg-gray-700 dark:hover:text-white dark:focus:ring-gray-700"
|
110 |
-
>Create new token</a
|
111 |
>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
112 |
|
113 |
-
|
114 |
-
|
115 |
-
|
116 |
-
|
117 |
-
|
118 |
-
|
119 |
-
|
|
|
120 |
</div>
|
121 |
-
|
|
|
1 |
<script lang="ts">
|
|
|
|
|
|
|
2 |
import { clickOutside } from "$lib/attachments/click-outside.js";
|
|
|
3 |
|
|
|
4 |
import { autofocus } from "$lib/attachments/autofocus.js";
|
5 |
+
import { token } from "$lib/state/token.svelte";
|
6 |
+
import IconCross from "~icons/carbon/close";
|
|
|
|
|
|
|
|
|
7 |
|
8 |
let backdropEl = $state<HTMLDivElement>();
|
9 |
let modalEl = $state<HTMLDivElement>();
|
10 |
|
|
|
|
|
11 |
function handleKeydown(event: KeyboardEvent) {
|
12 |
const { key } = event;
|
13 |
if (key === "Escape") {
|
14 |
event.preventDefault();
|
15 |
+
token.showModal = false;
|
16 |
}
|
17 |
}
|
18 |
|
19 |
+
$effect(() => {
|
20 |
+
if (token.showModal) {
|
21 |
+
document.getElementById("app")?.setAttribute("inert", "true");
|
22 |
+
} else {
|
|
|
|
|
|
|
23 |
document.getElementById("app")?.removeAttribute("inert");
|
24 |
}
|
25 |
});
|
26 |
+
|
27 |
+
function handleTokenSubmit(e: Event) {
|
28 |
+
e.preventDefault();
|
29 |
+
const form = e.target as HTMLFormElement;
|
30 |
+
const formData = new FormData(form);
|
31 |
+
const submittedHfToken = (formData.get("hf-token") as string).trim() ?? "";
|
32 |
+
const RE_HF_TOKEN = /\bhf_[a-zA-Z0-9]{34}\b/;
|
33 |
+
if (RE_HF_TOKEN.test(submittedHfToken)) {
|
34 |
+
token.value = submittedHfToken;
|
35 |
+
} else {
|
36 |
+
alert("Please provide a valid HF token.");
|
37 |
+
}
|
38 |
+
}
|
39 |
</script>
|
40 |
|
41 |
+
{#if token.showModal}
|
|
|
|
|
|
|
|
|
|
|
42 |
<div
|
43 |
+
id="default-modal"
|
44 |
+
aria-hidden="true"
|
45 |
+
class="fixed inset-0 z-50 flex items-center justify-center overflow-hidden bg-black/85"
|
46 |
+
bind:this={backdropEl}
|
|
|
|
|
47 |
>
|
48 |
+
<div
|
49 |
+
role="dialog"
|
50 |
+
tabindex="-1"
|
51 |
+
class="relative max-h-full w-full max-w-xl p-4 outline-hidden"
|
52 |
+
bind:this={modalEl}
|
53 |
+
onkeydown={handleKeydown}
|
54 |
+
{@attach clickOutside(() => (token.showModal = false))}
|
55 |
+
>
|
56 |
+
<form onsubmit={handleTokenSubmit} class="relative rounded-lg bg-white shadow-sm dark:bg-gray-900">
|
57 |
+
<div class="flex items-center justify-between rounded-t border-b p-4 md:px-5 md:py-4 dark:border-gray-800">
|
58 |
+
<h3 class="flex items-center gap-2.5 text-lg font-semibold text-gray-900 dark:text-white">
|
59 |
+
<img
|
60 |
+
alt="Hugging Face's logo"
|
61 |
+
class="w-7"
|
62 |
+
src="https://huggingface.co/front/assets/huggingface_logo-noborder.svg"
|
63 |
+
/> Add a Hugging Face Token
|
64 |
+
</h3>
|
65 |
+
<button
|
66 |
+
type="button"
|
67 |
+
onclick={() => (token.showModal = false)}
|
68 |
+
class="ms-auto inline-flex h-8 w-8 items-center justify-center rounded-lg bg-transparent text-sm text-gray-400 hover:bg-gray-200 hover:text-gray-900 dark:hover:bg-gray-600 dark:hover:text-white"
|
69 |
+
>
|
70 |
+
<div class="text-xl">
|
71 |
+
<IconCross />
|
72 |
+
</div>
|
73 |
+
<span class="sr-only">Close modal</span>
|
74 |
+
</button>
|
75 |
+
</div>
|
76 |
+
<!-- Modal body -->
|
77 |
+
<div class="p-4 md:p-5">
|
78 |
+
<p class="mb-5 text-base leading-relaxed text-gray-800 2xl:text-balance dark:text-gray-300">
|
79 |
+
You need a free Hugging Face token to use this application. <strong class="font-semibold"
|
80 |
+
>Make sure you create a token with Inference API permission.</strong
|
81 |
+
><br /> Your token is kept safe by only being used from your browser.
|
82 |
+
</p>
|
83 |
+
<div>
|
84 |
+
<label for="hf-token" class="mb-2 block text-sm font-medium text-gray-900 dark:text-white">
|
85 |
+
Hugging Face Token
|
86 |
+
</label>
|
87 |
+
<input
|
88 |
+
required
|
89 |
+
placeholder="Enter HF Token"
|
90 |
+
type="text"
|
91 |
+
id="hf-token"
|
92 |
+
name="hf-token"
|
93 |
+
class="block w-full rounded-lg border border-gray-300 bg-gray-50 p-2.5 text-sm text-gray-900 focus:border-blue-500 focus:ring-blue-500 dark:border-gray-600 dark:bg-gray-700 dark:text-white dark:placeholder-gray-400 dark:focus:border-blue-500 dark:focus:ring-blue-500"
|
94 |
+
{@attach autofocus()}
|
95 |
+
/>
|
96 |
</div>
|
97 |
+
<label class="mt-4 flex items-center gap-x-1.5 text-gray-900 dark:text-gray-200">
|
98 |
+
<input type="checkbox" bind:checked={token.writeToLocalStorage} />
|
99 |
+
<p class="text-sm leading-none">Save to local storage for future use</p></label
|
100 |
+
>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
101 |
</div>
|
|
|
|
|
|
|
|
|
|
|
102 |
|
103 |
+
<!-- Modal footer -->
|
104 |
+
<div
|
105 |
+
class="flex items-center justify-between rounded-b border-t border-gray-200 p-4 md:p-5 dark:border-gray-800"
|
|
|
|
|
|
|
|
|
|
|
106 |
>
|
107 |
+
<a
|
108 |
+
href="https://huggingface.co/settings/tokens/new?ownUserPermissions=inference.serverless.write&tokenType=fineGrained"
|
109 |
+
tabindex="-1"
|
110 |
+
target="_blank"
|
111 |
+
class="rounded-lg border border-gray-200 bg-white px-5 py-2.5 text-sm font-medium text-gray-900 hover:bg-gray-100 hover:text-blue-700 focus:z-10 focus:ring-4 focus:ring-gray-100 focus:outline-hidden dark:border-gray-600 dark:bg-gray-800 dark:text-gray-400 dark:hover:bg-gray-700 dark:hover:text-white dark:focus:ring-gray-700"
|
112 |
+
>Create new token</a
|
113 |
+
>
|
114 |
|
115 |
+
<button
|
116 |
+
type="submit"
|
117 |
+
class="rounded-lg bg-black px-5 py-2.5 text-sm font-medium text-white hover:bg-gray-900 focus:ring-4 focus:ring-gray-300 focus:outline-hidden dark:border-gray-700 dark:bg-gray-800 dark:hover:bg-gray-700 dark:focus:ring-gray-700"
|
118 |
+
>Submit</button
|
119 |
+
>
|
120 |
+
</div>
|
121 |
+
</form>
|
122 |
+
</div>
|
123 |
</div>
|
124 |
+
{/if}
|
src/lib/components/inference-playground/playground.svelte
CHANGED
@@ -1,35 +1,34 @@
|
|
1 |
<script lang="ts">
|
2 |
import { observe, observed, ObservedElements } from "$lib/attachments/observe.svelte.js";
|
|
|
3 |
import { conversations } from "$lib/state/conversations.svelte";
|
4 |
import { projects } from "$lib/state/projects.svelte";
|
5 |
import { token } from "$lib/state/token.svelte.js";
|
6 |
import { isHFModel } from "$lib/types.js";
|
7 |
import { iterate } from "$lib/utils/array.js";
|
8 |
import { isSystemPromptSupported } from "$lib/utils/business.svelte.js";
|
|
|
9 |
import IconExternal from "~icons/carbon/arrow-up-right";
|
10 |
import IconWaterfall from "~icons/carbon/chart-waterfall";
|
|
|
11 |
import IconCode from "~icons/carbon/code";
|
12 |
import IconCompare from "~icons/carbon/compare";
|
13 |
import IconInfo from "~icons/carbon/information";
|
14 |
import IconSettings from "~icons/carbon/settings";
|
15 |
import IconShare from "~icons/carbon/share";
|
16 |
import { default as IconDelete } from "~icons/carbon/trash-can";
|
|
|
17 |
import { showShareModal } from "../share-modal.svelte";
|
18 |
import Toaster from "../toaster.svelte";
|
19 |
import Tooltip from "../tooltip.svelte";
|
|
|
20 |
import PlaygroundConversationHeader from "./conversation-header.svelte";
|
21 |
import PlaygroundConversation from "./conversation.svelte";
|
22 |
import GenerationConfig from "./generation-config.svelte";
|
23 |
-
import
|
24 |
import ModelSelectorModal from "./model-selector-modal.svelte";
|
25 |
import ModelSelector from "./model-selector.svelte";
|
26 |
import ProjectSelect from "./project-select.svelte";
|
27 |
-
import BillingModal from "./billing-modal.svelte";
|
28 |
-
import BillingIndicator from "../billing-indicator.svelte";
|
29 |
-
import { TEST_IDS } from "$lib/constants.js";
|
30 |
-
import MessageTextarea from "./message-textarea.svelte";
|
31 |
-
import { atLeastNDecimals } from "$lib/utils/number.js";
|
32 |
-
import IconClose from "~icons/carbon/close";
|
33 |
|
34 |
let viewCode = $state(false);
|
35 |
let viewSettings = $state(false);
|
@@ -39,30 +38,8 @@
|
|
39 |
|
40 |
const systemPromptSupported = $derived(conversations.active.some(c => isSystemPromptSupported(c.model)));
|
41 |
const compareActive = $derived(conversations.active.length === 2);
|
42 |
-
|
43 |
-
function handleTokenSubmit(e: Event) {
|
44 |
-
const form = e.target as HTMLFormElement;
|
45 |
-
const formData = new FormData(form);
|
46 |
-
const submittedHfToken = (formData.get("hf-token") as string).trim() ?? "";
|
47 |
-
const RE_HF_TOKEN = /\bhf_[a-zA-Z0-9]{34}\b/;
|
48 |
-
if (RE_HF_TOKEN.test(submittedHfToken)) {
|
49 |
-
token.value = submittedHfToken;
|
50 |
-
// TODO: Only submit when previous action was trying to submit
|
51 |
-
// submit();
|
52 |
-
} else {
|
53 |
-
alert("Please provide a valid HF token.");
|
54 |
-
}
|
55 |
-
}
|
56 |
</script>
|
57 |
|
58 |
-
{#if token.showModal}
|
59 |
-
<HFTokenModal
|
60 |
-
bind:storeLocallyHfToken={token.writeToLocalStorage}
|
61 |
-
on:close={() => (token.showModal = false)}
|
62 |
-
on:submit={handleTokenSubmit}
|
63 |
-
/>
|
64 |
-
{/if}
|
65 |
-
|
66 |
<div
|
67 |
class={[
|
68 |
"motion-safe:animate-fade-in grid h-dvh divide-gray-200 overflow-hidden bg-gray-100/50",
|
|
|
1 |
<script lang="ts">
|
2 |
import { observe, observed, ObservedElements } from "$lib/attachments/observe.svelte.js";
|
3 |
+
import { TEST_IDS } from "$lib/constants.js";
|
4 |
import { conversations } from "$lib/state/conversations.svelte";
|
5 |
import { projects } from "$lib/state/projects.svelte";
|
6 |
import { token } from "$lib/state/token.svelte.js";
|
7 |
import { isHFModel } from "$lib/types.js";
|
8 |
import { iterate } from "$lib/utils/array.js";
|
9 |
import { isSystemPromptSupported } from "$lib/utils/business.svelte.js";
|
10 |
+
import { atLeastNDecimals } from "$lib/utils/number.js";
|
11 |
import IconExternal from "~icons/carbon/arrow-up-right";
|
12 |
import IconWaterfall from "~icons/carbon/chart-waterfall";
|
13 |
+
import IconClose from "~icons/carbon/close";
|
14 |
import IconCode from "~icons/carbon/code";
|
15 |
import IconCompare from "~icons/carbon/compare";
|
16 |
import IconInfo from "~icons/carbon/information";
|
17 |
import IconSettings from "~icons/carbon/settings";
|
18 |
import IconShare from "~icons/carbon/share";
|
19 |
import { default as IconDelete } from "~icons/carbon/trash-can";
|
20 |
+
import BillingIndicator from "../billing-indicator.svelte";
|
21 |
import { showShareModal } from "../share-modal.svelte";
|
22 |
import Toaster from "../toaster.svelte";
|
23 |
import Tooltip from "../tooltip.svelte";
|
24 |
+
import BillingModal from "./billing-modal.svelte";
|
25 |
import PlaygroundConversationHeader from "./conversation-header.svelte";
|
26 |
import PlaygroundConversation from "./conversation.svelte";
|
27 |
import GenerationConfig from "./generation-config.svelte";
|
28 |
+
import MessageTextarea from "./message-textarea.svelte";
|
29 |
import ModelSelectorModal from "./model-selector-modal.svelte";
|
30 |
import ModelSelector from "./model-selector.svelte";
|
31 |
import ProjectSelect from "./project-select.svelte";
|
|
|
|
|
|
|
|
|
|
|
|
|
32 |
|
33 |
let viewCode = $state(false);
|
34 |
let viewSettings = $state(false);
|
|
|
38 |
|
39 |
const systemPromptSupported = $derived(conversations.active.some(c => isSystemPromptSupported(c.model)));
|
40 |
const compareActive = $derived(conversations.active.length === 2);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
41 |
</script>
|
42 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
43 |
<div
|
44 |
class={[
|
45 |
"motion-safe:animate-fade-in grid h-dvh divide-gray-200 overflow-hidden bg-gray-100/50",
|
src/lib/state/models.svelte.ts
CHANGED
@@ -16,6 +16,8 @@ class Models {
|
|
16 |
nonTrending = $derived(this.remote.filter(m => !this.trending.includes(m)).toSorted(trendingSort));
|
17 |
all = $derived([...this.remote, ...this.custom]);
|
18 |
|
|
|
|
|
19 |
constructor() {
|
20 |
const savedData = localStorage.getItem(LOCAL_STORAGE_KEY);
|
21 |
if (!savedData) return;
|
@@ -30,10 +32,16 @@ class Models {
|
|
30 |
}
|
31 |
|
32 |
async load() {
|
33 |
-
|
|
|
|
|
|
|
|
|
34 |
this.remote = models;
|
35 |
this.routerData = data;
|
36 |
});
|
|
|
|
|
37 |
}
|
38 |
|
39 |
#custom = $state.raw<CustomModel[]>([]);
|
|
|
16 |
nonTrending = $derived(this.remote.filter(m => !this.trending.includes(m)).toSorted(trendingSort));
|
17 |
all = $derived([...this.remote, ...this.custom]);
|
18 |
|
19 |
+
loading: Promise<void> | null = null;
|
20 |
+
|
21 |
constructor() {
|
22 |
const savedData = localStorage.getItem(LOCAL_STORAGE_KEY);
|
23 |
if (!savedData) return;
|
|
|
32 |
}
|
33 |
|
34 |
async load() {
|
35 |
+
if (this.loading || this.remote.length > 0) {
|
36 |
+
return await this.loading;
|
37 |
+
}
|
38 |
+
|
39 |
+
this.loading = Promise.all([getModels(), getRouterData()]).then(([models, data]) => {
|
40 |
this.remote = models;
|
41 |
this.routerData = data;
|
42 |
});
|
43 |
+
await this.loading;
|
44 |
+
this.loading = null;
|
45 |
}
|
46 |
|
47 |
#custom = $state.raw<CustomModel[]>([]);
|
src/routes/+layout.svelte
CHANGED
@@ -1,14 +1,13 @@
|
|
1 |
<script lang="ts">
|
2 |
import IconLoadingLoop from "~icons/line-md/loading-loop";
|
3 |
import "../app.css";
|
4 |
-
import
|
5 |
|
6 |
interface Props {
|
7 |
children?: import("svelte").Snippet;
|
8 |
}
|
9 |
|
10 |
let { children }: Props = $props();
|
11 |
-
models.load();
|
12 |
</script>
|
13 |
|
14 |
<svelte:boundary>
|
@@ -18,3 +17,5 @@
|
|
18 |
<IconLoadingLoop class="abs-center absolute text-6xl dark:text-blue-300" />
|
19 |
{/snippet}
|
20 |
</svelte:boundary>
|
|
|
|
|
|
1 |
<script lang="ts">
|
2 |
import IconLoadingLoop from "~icons/line-md/loading-loop";
|
3 |
import "../app.css";
|
4 |
+
import HfTokenModal from "$lib/components/inference-playground/hf-token-modal.svelte";
|
5 |
|
6 |
interface Props {
|
7 |
children?: import("svelte").Snippet;
|
8 |
}
|
9 |
|
10 |
let { children }: Props = $props();
|
|
|
11 |
</script>
|
12 |
|
13 |
<svelte:boundary>
|
|
|
17 |
<IconLoadingLoop class="abs-center absolute text-6xl dark:text-blue-300" />
|
18 |
{/snippet}
|
19 |
</svelte:boundary>
|
20 |
+
|
21 |
+
<HfTokenModal />
|
src/routes/canvas/+page.svelte
CHANGED
@@ -1,4 +1,5 @@
|
|
1 |
<script lang="ts">
|
|
|
2 |
import type { Node } from "@xyflow/svelte";
|
3 |
import { Background, Controls, MiniMap, SvelteFlow } from "@xyflow/svelte";
|
4 |
import "@xyflow/svelte/dist/style.css";
|
|
|
1 |
<script lang="ts">
|
2 |
+
import "@xyflow/svelte/dist/style.css";
|
3 |
import type { Node } from "@xyflow/svelte";
|
4 |
import { Background, Controls, MiniMap, SvelteFlow } from "@xyflow/svelte";
|
5 |
import "@xyflow/svelte/dist/style.css";
|
src/routes/canvas/chat-node.svelte
CHANGED
@@ -20,6 +20,8 @@
|
|
20 |
};
|
21 |
let { id, data }: Props = $props();
|
22 |
|
|
|
|
|
23 |
let { updateNodeData, updateNode, getNode } = useSvelteFlow();
|
24 |
onMount(() => {
|
25 |
if (!data.modelId) data.modelId = models.trending[0]?.id;
|
|
|
20 |
};
|
21 |
let { id, data }: Props = $props();
|
22 |
|
23 |
+
await models.load();
|
24 |
+
|
25 |
let { updateNodeData, updateNode, getNode } = useSvelteFlow();
|
26 |
onMount(() => {
|
27 |
if (!data.modelId) data.modelId = models.trending[0]?.id;
|