This commit is contained in:
Timothy Jaeryang Baek 2026-10-10 14:42:55 +04:00
parent f27fd3d2e6
commit 90496c28ae
14 changed files with 124 additions and 22 deletions

View file

@ -1,4 +1,5 @@
<script lang="ts">
import ModelSettingsLabel from '$lib/components/workspace/Models/ModelSettingsLabel.svelte';
import { getContext, tick } from 'svelte';
// @ts-expect-error The existing SortableJS dependency does not ship declarations.
import Sortable from 'sortablejs';
@ -137,7 +138,10 @@
class="grid grid-cols-[7rem_minmax(0,1fr)_auto] items-center gap-2 px-1 py-1.5 text-xs sm:grid-cols-[8rem_minmax(0,1fr)_auto]"
>
<span class="text-xs font-normal text-gray-600 dark:text-gray-400"
>{$i18n.t('Model controls')}</span
><ModelSettingsLabel
label={$i18n.t('Model controls')}
description={$i18n.t('Let people choose approved parameter presets in chat.')}
/></span
>
<p
class="truncate text-gray-500 dark:text-gray-400"

View file

@ -19,6 +19,7 @@
<TypeaheadSelector
id="model-actionsselector"
label={$i18n.t('Actions')}
description={$i18n.t('Add custom action buttons to model responses.')}
items={actions}
selectedIds={selectedActionIds}
{disabled}

View file

@ -95,7 +95,12 @@
};
</script>
<ModelSettingsSection label={$i18n.t('settings.admin.models.builtinTools.title')}>
<ModelSettingsSection
label={$i18n.t('settings.admin.models.builtinTools.title')}
description={$i18n.t(
'Choose which built-in tools this model can use when Builtin Tools is enabled.'
)}
>
<span slot="summary" class="flex min-w-0 items-center gap-1 text-gray-900 dark:text-gray-100">
<span class="min-w-0 [overflow-wrap:anywhere]"
>{enabledTools

View file

@ -82,7 +82,12 @@
</script>
<div class="space-y-0.5">
<ModelSettingsSection label={$i18n.t('settings.admin.models.capabilities.title')}>
<ModelSettingsSection
label={$i18n.t('settings.admin.models.capabilities.title')}
description={$i18n.t(
'Choose which features are available for this model. The connected model and provider must support them.'
)}
>
<span slot="summary" class="flex min-w-0 items-center gap-1 text-gray-900 dark:text-gray-100">
<span class="min-w-0 [overflow-wrap:anywhere]"
>{enabledCapabilityIds
@ -107,7 +112,10 @@
</ModelSettingsSection>
{#if availableFeatures.length}
<ModelSettingsSection label={$i18n.t('settings.admin.models.defaultFeatures.title')}>
<ModelSettingsSection
label={$i18n.t('settings.admin.models.defaultFeatures.title')}
description={$i18n.t('Choose which available features start enabled in new chats.')}
>
<span slot="summary" class="flex min-w-0 items-center gap-1 text-gray-900 dark:text-gray-100">
<span class="min-w-0 [overflow-wrap:anywhere]"
>{enabledDefaultIds

View file

@ -21,6 +21,7 @@
<TypeaheadSelector
id="model-filtersselector"
label={$i18n.t('Filters')}
description={$i18n.t('Apply functions that process messages before or after the model responds.')}
items={filters}
selectedIds={selectedFilterIds}
bind:defaultIds={defaultFilterIds}

View file

@ -1,4 +1,5 @@
<script lang="ts">
import ModelSettingsLabel from './ModelSettingsLabel.svelte';
import { getContext, onMount } from 'svelte';
import { config, settings, user } from '$lib/stores';
@ -196,7 +197,14 @@
class="grid w-full grid-cols-[7rem_minmax(0,1fr)_auto] items-center gap-2 rounded-md px-1 py-1.5 text-left text-xs font-normal disabled:cursor-default sm:grid-cols-[8rem_minmax(0,1fr)_auto]"
>
<span class="text-gray-600 dark:text-gray-400"
><slot name="label">{$i18n.t('Knowledge')}</slot></span
><slot name="label"
><ModelSettingsLabel
label={$i18n.t('Knowledge')}
description={$i18n.t(
'Attach knowledge bases, notes, or files for this model to reference in chats.'
)}
/></slot
></span
>
<span
bind:this={valueElement}

View file

@ -1,4 +1,5 @@
<script lang="ts">
import ModelSettingsLabel from './ModelSettingsLabel.svelte';
import { toast } from 'svelte-sonner';
import { v4 as uuidv4 } from 'uuid';
import { beforeNavigate, goto } from '$app/navigation';
@ -1220,7 +1221,12 @@
class="grid min-w-0 grid-cols-[7rem_minmax(0,1fr)] items-center gap-2 sm:grid-cols-[8rem_minmax(0,1fr)]"
>
<div class="text-xs font-normal text-gray-600 dark:text-gray-400">
{$i18n.t('Base Model (From)')}
<ModelSettingsLabel
label={$i18n.t('Base Model (From)')}
description={$i18n.t(
'Choose the underlying model that generates responses for this custom model.'
)}
/>
</div>
<div class="min-w-0">
@ -1242,7 +1248,12 @@
class="grid min-w-0 grid-cols-[7rem_minmax(0,1fr)] items-start gap-2 sm:grid-cols-[8rem_minmax(0,1fr)]"
>
<div class="pt-1 text-xs font-normal text-gray-600 dark:text-gray-400">
{$i18n.t('Tags')}
<ModelSettingsLabel
label={$i18n.t('Tags')}
description={$i18n.t(
'Add tags to organize models and make them easier to find.'
)}
/>
</div>
<div class="min-w-0">
<Tags
@ -1271,7 +1282,12 @@
<section class="mt-4">
<div class="space-y-2 px-1">
<div class="text-xs font-normal text-gray-600 dark:text-gray-400">
{$i18n.t('System Prompt')}
<ModelSettingsLabel
label={$i18n.t('System Prompt')}
description={$i18n.t(
'Set instructions that guide how this model behaves throughout a chat.'
)}
/>
</div>
{#if showSystemPrompt || !system.trim()}
@ -1385,7 +1401,12 @@
on:click={() => (showAdvanced = !showAdvanced)}
>
<span class="font-normal text-gray-600 dark:text-gray-400"
>{$i18n.t('Advanced Params')}</span
><ModelSettingsLabel
label={$i18n.t('Advanced Params')}
description={$i18n.t(
'Override generation settings such as temperature, token limits, and sampling. Unmodified settings use the provider defaults.'
)}
/></span
>
<span class="text-gray-900 dark:text-gray-100">
{modifiedParamCount
@ -1414,6 +1435,9 @@
<section class="mt-0.5">
<ModelSettingsSection
label={$i18n.t('Prompts')}
description={$i18n.t(
'Set the starter suggestions people see when opening a new chat with this model.'
)}
summary={editingLocale
? Array.isArray(info.meta.i18n?.[editingLocale]?.suggestion_prompts)
? $i18n.t('Custom')
@ -1504,6 +1528,9 @@
/>
<ModelSettingsSection
label={$i18n.t('Voice')}
description={$i18n.t(
'Configure the realtime voice, voice avatar, and text-to-speech voice for this model.'
)}
summary={[
$config?.audio?.realtime?.enabled
? voice.voice || $i18n.t('Admin default')
@ -1571,24 +1598,19 @@
</fieldset>
<div class="my-2 text-xs text-gray-400 dark:text-gray-500">
<div class="flex w-full items-center gap-2">
<div class="flex w-full items-center gap-2 opacity-30 transition-opacity hover:opacity-60 focus-within:opacity-60">
<button
type="button"
class="group flex h-7 min-w-0 flex-1 items-center justify-between gap-3 rounded-sm text-start text-xs focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2"
class="flex h-7 min-w-0 flex-1 items-center justify-between gap-3 rounded-sm text-start text-xs focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2"
aria-expanded={showPreview}
on:click={() => (showPreview = !showPreview)}
>
<span class="font-normal text-gray-600 dark:text-gray-400"
>{$i18n.t('JSON Preview')}</span
>
<span
aria-hidden="true"
class="text-gray-500 transition group-hover:text-gray-700 dark:group-hover:text-gray-300"
>{showPreview ? $i18n.t('Hide') : $i18n.t('Show')}</span
<span class="font-normal">{$i18n.t('JSON Preview')}</span>
<span aria-hidden="true">{showPreview ? $i18n.t('Hide') : $i18n.t('Show')}</span
>
</button>
<button
class="px-1.5 py-0.5 text-xs flex rounded-sm transition"
class="px-1.5 py-0.5 text-xs flex rounded-sm"
type="button"
on:click={async () => {
const copied = await copyToClipboard(

View file

@ -0,0 +1,22 @@
<script lang="ts">
import Tooltip from '$lib/components/common/Tooltip.svelte';
export let label = '';
export let description = '';
</script>
{#if description}
<Tooltip
as="span"
className="inline-flex w-fit max-w-full"
content={description}
allowHTML={false}
>
<span
class="cursor-help underline decoration-dotted decoration-gray-400/70 underline-offset-4 dark:decoration-gray-500"
>{label}</span
>
</Tooltip>
{:else}
<span>{label}</span>
{/if}

View file

@ -1,7 +1,9 @@
<script lang="ts">
import ModelSettingsLabel from './ModelSettingsLabel.svelte';
import ChevronRight from '$lib/components/icons/ChevronRight.svelte';
export let label = '';
export let description = '';
export let summary = '';
export let open = false;
</script>
@ -10,7 +12,9 @@
<summary
class="grid cursor-pointer list-none grid-cols-[7rem_minmax(0,1fr)_auto] items-center gap-2 rounded-md px-1 py-1.5 text-xs font-normal focus-visible:outline focus-visible:outline-2 sm:grid-cols-[8rem_minmax(0,1fr)_auto] [&::-webkit-details-marker]:hidden"
>
<span class="text-gray-600 dark:text-gray-400">{label}</span>
<span class="text-gray-600 dark:text-gray-400"
><ModelSettingsLabel {label} {description} /></span
>
<slot name="summary">
<span class="truncate text-gray-900 dark:text-gray-100" title={summary}>{summary}</span>
</slot>

View file

@ -17,6 +17,7 @@
<TypeaheadSelector
id="model-skillsselector"
label={$i18n.t('Skills')}
description={$i18n.t('Attach reusable instructions and resources for specific tasks.')}
items={skills.filter((skill) => skill.is_active !== false)}
selectedIds={selectedSkillIds}
{disabled}

View file

@ -1,5 +1,6 @@
<script lang="ts">
import { getContext, onMount } from 'svelte';
import ModelSettingsLabel from './ModelSettingsLabel.svelte';
import { getTerminalServers, type TerminalServer } from '$lib/apis/terminal';
const i18n = getContext<any>('i18n');
@ -17,7 +18,10 @@
<label
class="flex min-h-8 items-center justify-between gap-3 px-1 text-xs font-normal text-gray-600 dark:text-gray-400"
>
<span>{$i18n.t('Default terminal')}</span>
<ModelSettingsLabel
label={$i18n.t('Default terminal')}
description={$i18n.t('Choose the terminal server selected by default for chats with this model.')}
/>
<select
class="min-w-0 max-w-[60%] cursor-pointer bg-transparent py-0 text-xs font-normal text-gray-900 outline-hidden dark:text-gray-100"
bind:value={terminalId}

View file

@ -18,6 +18,9 @@
<TypeaheadSelector
id="model-toolsselector"
label={$i18n.t('Tools')}
description={$i18n.t(
'Connect tools this model can call to retrieve information or perform actions.'
)}
items={tools}
selectedIds={selectedToolIds}
{disabled}

View file

@ -1,4 +1,5 @@
<script lang="ts">
import ModelSettingsLabel from './ModelSettingsLabel.svelte';
import { resolveLocalizedResource } from '$lib/utils/localizedContent';
import { createEventDispatcher, getContext, tick } from 'svelte';
import Dropdown from '$lib/components/common/Dropdown.svelte';
@ -23,6 +24,7 @@
export let triggerLabel = '';
export let emptyLabel = '';
export let label = '';
export let description = '';
export let emptyHint = '';
export let workspaceHref = '';
export let disabled = false;
@ -124,7 +126,9 @@
: 'flex min-w-0 items-center bg-transparent text-xs text-gray-500 hover:text-gray-700 dark:text-gray-400 dark:hover:text-gray-300'}
>
{#if label}
<span class="text-gray-600 dark:text-gray-400">{label}</span>
<span class="text-gray-600 dark:text-gray-400"
><ModelSettingsLabel {label} {description} /></span
>
<span
bind:this={valueElement}
class="flex min-w-0 items-center gap-1 text-gray-900 dark:text-gray-100"

View file

@ -1,4 +1,19 @@
{
"Choose the terminal server selected by default for chats with this model.": "",
"Add tags to organize models and make them easier to find.": "",
"Connect tools this model can call to retrieve information or perform actions.": "",
"Attach reusable instructions and resources for specific tasks.": "",
"Apply functions that process messages before or after the model responds.": "",
"Add custom action buttons to model responses.": "",
"Attach knowledge bases, notes, or files for this model to reference in chats.": "",
"Choose which features are available for this model. The connected model and provider must support them.": "",
"Choose which available features start enabled in new chats.": "",
"Choose which built-in tools this model can use when Builtin Tools is enabled.": "",
"Set the starter suggestions people see when opening a new chat with this model.": "",
"Configure the realtime voice, voice avatar, and text-to-speech voice for this model.": "",
"Override generation settings such as temperature, token limits, and sampling. Unmodified settings use the provider defaults.": "",
"Set instructions that guide how this model behaves throughout a chat.": "",
"Choose the underlying model that generates responses for this custom model.": "",
"{{count}} modified": "",
"-1 for no limit, or a positive integer for a specific limit": "",
"(latest)": "",