diff --git a/src/lib/components/Ai/ChangeModelBox.svelte b/src/lib/components/Ai/ChangeModelBox.svelte
new file mode 100644
index 0000000..a4301e9
--- /dev/null
+++ b/src/lib/components/Ai/ChangeModelBox.svelte
@@ -0,0 +1,120 @@
+
+
+
+
+ {#each models as m (m.name + m.brand)}
+ {@const isSelected =
+ m.brand === model.brand && m.name === model.name && m.endpoint === model.endpoint}
+ -
+
+
+ {/each}
+
+
+
+
diff --git a/src/lib/components/Ai/Chat.svelte b/src/lib/components/Ai/Chat.svelte
index 467b0b6..5e691f8 100644
--- a/src/lib/components/Ai/Chat.svelte
+++ b/src/lib/components/Ai/Chat.svelte
@@ -2,12 +2,13 @@
import { autoresize } from '$lib/actions/autoresize.svelte';
import { scroll_to_bottom } from '$lib/actions/scrollToBottom.svelte';
import Select from '$lib/components/Select.svelte';
+ import ChevronDown from '$lib/icons/ChevronDown.svelte';
import CircleStack from '$lib/icons/CircleStack.svelte';
import CircleStopSolid from '$lib/icons/CircleStopSolid.svelte';
import Plus from '$lib/icons/Plus.svelte';
import { getTextFromElement, transform } from '$lib/markdown';
import type { Table } from '$lib/olap-engine';
- import { deserializeModel, serializeModel } from '.';
+ import ChangeModelBox from './ChangeModelBox.svelte';
import DatasetsBox from './DatasetsBox.svelte';
import Loader from './Loader.svelte';
import type { ChatInput, ChatOutput, Model } from './types';
@@ -37,11 +38,11 @@
let loading = $state(false);
let submitter = $state();
let message = $state('');
- let select = $state>();
+ let datasetSelectbox = $state>();
let textarea = $state();
let abortController: AbortController | undefined;
let chatMessages = $derived(messages.filter((m) => m.role === 'user' || m.role === 'assistant'));
- let modelsOptions = $derived(Object.entries(Object.groupBy(models, (item) => item.brand)));
+ let modelSelectbox = $state>();
function getContextFromTable(table: Table): string {
const columns = table.columns.map((col) => `- ${col.name} (${col.type})`).join('\n');
@@ -195,38 +196,47 @@
-
+
{#if loading}
select {
- border: none;
- outline: none;
- background-color: transparent;
- color: hsl(0deg 0% 65%);
- font-size: 11px;
- border-radius: 4px;
- padding: 2px 0;
-
- &:disabled {
- appearance: none;
- }
-
- &:not(:disabled):hover {
- cursor: pointer;
- background-color: hsl(0deg 0% 10%);
- }
- }
-
.submitter > button {
display: grid;
place-items: center;
@@ -389,6 +380,18 @@
background-color: transparent;
}
}
+
+ &.select-trigger {
+ aspect-ratio: initial;
+ padding: 0 4px;
+ display: flex;
+ gap: 4px;
+ }
+ }
+
+ :global(body:has(#change-model)) .select-trigger :global(> svg) {
+ transform-origin: center;
+ transform: rotate(180deg);
}
button {
diff --git a/src/lib/components/Select.svelte b/src/lib/components/Select.svelte
index faf1b9b..8df05a1 100644
--- a/src/lib/components/Select.svelte
+++ b/src/lib/components/Select.svelte
@@ -10,9 +10,10 @@
children?: Snippet;
onClose?: () => void;
anchor_size?: boolean;
+ id?: HTMLElement['id'];
}
- let { placement = 'bottom-start', children, onClose, anchor_size = false }: Props = $props();
+ let { placement = 'bottom-start', children, onClose, anchor_size = false, id }: Props = $props();
let opened = $state(false);
let dropdown = $state();
@@ -65,6 +66,7 @@
transition:fade={{ duration: 150 }}
role="presentation"
onclick={(e) => e.target === e.currentTarget && close()}
+ {id}
>
{@render children?.()}
diff --git a/src/lib/icons/ChevronDown.svelte b/src/lib/icons/ChevronDown.svelte
new file mode 100644
index 0000000..129fd9e
--- /dev/null
+++ b/src/lib/icons/ChevronDown.svelte
@@ -0,0 +1,15 @@
+
+
+