Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
43 changes: 43 additions & 0 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,7 @@
"prettier-plugin-tailwindcss": "^0.6.11",
"prom-client": "^15.1.2",
"sade": "^1.8.1",
"superjson": "^2.2.2",
"svelte": "^5.33.3",
"svelte-check": "^4.0.0",
"svelte-gestures": "^5.1.3",
Expand Down
27 changes: 12 additions & 15 deletions src/lib/APIClient.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import type { App } from "$api";
import { base } from "$app/paths";
import { treaty, type Treaty } from "@elysiajs/eden";
import { browser } from "$app/environment";
import superjson from "superjson";

export function useAPIClient({ fetch }: { fetch?: Treaty.Config["fetcher"] } = {}) {
let url;
Expand All @@ -26,30 +27,26 @@ export function useAPIClient({ fetch }: { fetch?: Treaty.Config["fetcher"] } = {
url = `${window.location.origin}${base}/api/v2`;
}
const app = treaty<App>(url, { fetcher: fetch });

return app;
}

export function throwOnErrorNullable<T extends Record<number, unknown>>(
export function handleResponse<T extends Record<number, unknown>>(
response: Treaty.TreatyResponse<T>
): T[200] {
if (response.error) {
throw new Error(JSON.stringify(response.error));
}

return response.data as T[200];
return superjson.parse(
typeof response.data === "string" ? response.data : JSON.stringify(response.data)
) as T[200];
}

export function throwOnError<T extends Record<number, unknown>>(
response: Treaty.TreatyResponse<T>
): NonNullable<T[200]> {
if (response.error) {
throw new Error(JSON.stringify(response.error));
}

if (response.data === null) {
throw new Error("No data received on API call");
// eslint-disable-next-line @typescript-eslint/no-explicit-any
export type Success<T extends (...args: any) => any> =
Awaited<ReturnType<T>> extends {
data: infer D;
error: unknown;
}

return response.data as NonNullable<T[200]>;
}
? D
: never;
19 changes: 16 additions & 3 deletions src/lib/components/AssistantSettings.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -55,8 +55,8 @@
let inputMessage3 = $state(assistant?.exampleInputs[2] ?? "");
let inputMessage4 = $state(assistant?.exampleInputs[3] ?? "");

function resetErrors() {
errors = [];
function clearError(field: string) {
errors = errors.filter((e) => e.field !== field);
}

function onFilesChange(e: Event) {
Expand All @@ -70,7 +70,7 @@
return;
}
files = inputEl.files;
resetErrors();
clearError("avatar");
deleteExistingAvatar = false;
}
}
Expand Down Expand Up @@ -164,6 +164,7 @@
} else {
$error = response.statusText;
}
loading = false;
}
} else {
response = await fetch(`${base}/api/assistant`, {
Expand All @@ -181,6 +182,7 @@
} else {
$error = response.statusText;
}
loading = false;
}
}
}}
Expand Down Expand Up @@ -245,6 +247,7 @@
e.stopPropagation();
files = null;
deleteExistingAvatar = true;
clearError("avatar");
}}
class="mx-auto w-max text-center text-xs text-gray-600 hover:underline"
>
Expand All @@ -271,6 +274,7 @@
class="w-full rounded-lg border-2 border-gray-200 bg-gray-100 p-2"
placeholder="Assistant Name"
value={assistant?.name ?? ""}
oninput={() => clearError("name")}
/>
<p class="text-xs text-red-500">{getError("name")}</p>
</label>
Expand All @@ -282,6 +286,7 @@
class="h-15 w-full rounded-lg border-2 border-gray-200 bg-gray-100 p-2"
placeholder="It knows everything about python"
value={assistant?.description ?? ""}
oninput={() => clearError("description")}
></textarea>
<p class="text-xs text-red-500">{getError("description")}</p>
</label>
Expand All @@ -293,6 +298,7 @@
name="modelId"
class="w-full rounded-lg border-2 border-gray-200 bg-gray-100 p-2"
bind:value={modelId}
onchange={() => clearError("modelId")}
>
{#each models.filter((model) => !model.unlisted) as model}
<option value={model.id}>{model.displayName}</option>
Expand Down Expand Up @@ -415,25 +421,29 @@
placeholder="Start Message 1"
bind:value={inputMessage1}
class="w-full rounded-lg border-2 border-gray-200 bg-gray-100 p-2"
oninput={() => clearError("inputMessage1")}
/>
<input
name="exampleInput2"
placeholder="Start Message 2"
bind:value={inputMessage2}
class="w-full rounded-lg border-2 border-gray-200 bg-gray-100 p-2"
oninput={() => clearError("inputMessage1")}
/>

<input
name="exampleInput3"
placeholder="Start Message 3"
bind:value={inputMessage3}
class="w-full rounded-lg border-2 border-gray-200 bg-gray-100 p-2"
oninput={() => clearError("inputMessage1")}
/>
<input
name="exampleInput4"
placeholder="Start Message 4"
bind:value={inputMessage4}
class="w-full rounded-lg border-2 border-gray-200 bg-gray-100 p-2"
oninput={() => clearError("inputMessage1")}
/>
</div>
<p class="text-xs text-red-500">{getError("inputMessage1")}</p>
Expand Down Expand Up @@ -524,6 +534,7 @@
class="w-full rounded-lg border-2 border-gray-200 bg-gray-100 p-2"
placeholder="wikipedia.org,bbc.com"
value={assistant?.rag?.allowedDomains?.join(",") ?? ""}
oninput={() => clearError("ragDomainList")}
/>
<p class="text-xs text-red-500">{getError("ragDomainList")}</p>
{/if}
Expand All @@ -550,6 +561,7 @@
class="w-full rounded-lg border-2 border-gray-200 bg-gray-100 p-2"
placeholder="https://raw.githubusercontent.com/huggingface/chat-ui/main/README.md"
value={assistant?.rag?.allowedLinks.join(",") ?? ""}
oninput={() => clearError("ragLinkList")}
/>
<p class="text-xs text-red-500">{getError("ragLinkList")}</p>
{/if}
Expand Down Expand Up @@ -605,6 +617,7 @@
class="min-h-[8lh] flex-1 rounded-lg border-2 border-gray-200 bg-gray-100 p-2 text-sm"
placeholder="You'll act as..."
bind:value={systemPrompt}
oninput={() => clearError("preprompt")}
></textarea>
{#if modelId}
{@const model = models.find((_model) => _model.id === modelId)}
Expand Down
6 changes: 3 additions & 3 deletions src/lib/components/NavConversationItem.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,7 @@
onclick={(e) => {
e.preventDefault();
confirmDelete = false;
dispatch("deleteConversation", conv.id);
dispatch("deleteConversation", conv.id.toString());
}}
>
<CarbonCheckmark
Expand All @@ -109,7 +109,7 @@
e.preventDefault();
const newTitle = prompt("Edit this conversation title:", conv.title);
if (!newTitle) return;
dispatch("editConversationTitle", { id: conv.id, title: newTitle });
dispatch("editConversationTitle", { id: conv.id.toString(), title: newTitle });
}}
>
<CarbonEdit class="text-xs text-gray-400 hover:text-gray-500 dark:hover:text-gray-300" />
Expand All @@ -122,7 +122,7 @@
onclick={(event) => {
event.preventDefault();
if (event.shiftKey) {
dispatch("deleteConversation", conv.id);
dispatch("deleteConversation", conv.id.toString());
} else {
confirmDelete = true;
}
Expand Down
12 changes: 3 additions & 9 deletions src/lib/components/NavMenu.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -29,8 +29,7 @@
import { usePublicConfig } from "$lib/utils/PublicConfig.svelte";

import { isVirtualKeyboard } from "$lib/utils/isVirtualKeyboard";
import { useAPIClient, throwOnError } from "$lib/APIClient";
import { jsonSerialize } from "$lib/utils/serialize";
import { useAPIClient, handleResponse } from "$lib/APIClient";

const publicConfig = usePublicConfig();
const client = useAPIClient();
Expand Down Expand Up @@ -77,13 +76,8 @@
p,
},
})
.then(throwOnError)
.then(({ conversations }) =>
conversations.map((conv) => ({
...jsonSerialize(conv),
updatedAt: new Date(conv.updatedAt),
}))
)
.then(handleResponse)
.then((r) => r.conversations)
.catch(() => []);

if (newConvs.length === 0) {
Expand Down
4 changes: 2 additions & 2 deletions src/lib/components/ToolBadge.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
import ToolLogo from "./ToolLogo.svelte";
import { base } from "$app/paths";
import { browser } from "$app/environment";
import { throwOnError, useAPIClient } from "$lib/APIClient";
import { handleResponse, useAPIClient } from "$lib/APIClient";

interface Props {
toolId: string;
Expand All @@ -17,7 +17,7 @@
class="relative flex items-center justify-center space-x-2 rounded border border-gray-300 bg-gray-200 px-2 py-1"
>
{#if browser}
{#await client.tools({ id: toolId }).get().then(throwOnError) then value}
{#await client.tools({ id: toolId }).get().then(handleResponse) then value}
{#key value.color + value.icon}
<ToolLogo color={value.color} icon={value.icon} size="sm" />
{/key}
Expand Down
3 changes: 1 addition & 2 deletions src/lib/components/chat/AssistantIntroduction.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -18,14 +18,13 @@
import { usePublicConfig } from "$lib/utils/PublicConfig.svelte";

import { page } from "$app/state";
import type { Serialize } from "$lib/utils/serialize";

const publicConfig = usePublicConfig();

interface Props {
models: Model[];
assistant: Pick<
Serialize<Assistant>,
Assistant,
| "avatar"
| "name"
| "rag"
Expand Down
3 changes: 1 addition & 2 deletions src/lib/components/chat/ChatInput.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,6 @@
import { captureScreen } from "$lib/utils/screenshot";
import IconScreenshot from "../icons/IconScreenshot.svelte";
import { loginModalOpen } from "$lib/stores/loginModal";
import type { Serialize } from "$lib/utils/serialize";

import { isVirtualKeyboard } from "$lib/utils/isVirtualKeyboard";
interface Props {
Expand All @@ -33,7 +32,7 @@
placeholder?: string;
loading?: boolean;
disabled?: boolean;
assistant?: Serialize<Assistant> | undefined;
assistant?: Assistant | undefined;
modelHasTools?: boolean;
modelIsMultimodal?: boolean;
children?: import("svelte").Snippet;
Expand Down
3 changes: 1 addition & 2 deletions src/lib/components/chat/ChatWindow.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,6 @@
import { cubicInOut } from "svelte/easing";
import type { ToolFront } from "$lib/types/Tool";
import { loginModalOpen } from "$lib/stores/loginModal";
import type { Serialize } from "$lib/utils/serialize";
import { beforeNavigate } from "$app/navigation";
import { isVirtualKeyboard } from "$lib/utils/isVirtualKeyboard";

Expand All @@ -49,7 +48,7 @@
shared?: boolean;
currentModel: Model;
models: Model[];
assistant?: Serialize<Assistant> | undefined;
assistant?: Assistant | undefined;
preprompt?: string | undefined;
files?: File[];
}
Expand Down
Loading