diff --git a/src/lib/components/workspace/Models/SkillsSelector.svelte b/src/lib/components/workspace/Models/SkillsSelector.svelte
index 01c38fd074..8eba2f018e 100644
--- a/src/lib/components/workspace/Models/SkillsSelector.svelte
+++ b/src/lib/components/workspace/Models/SkillsSelector.svelte
@@ -8,6 +8,7 @@
id: string;
name?: string;
description?: string;
+ is_active?: boolean;
};
export let skills: Skill[] = [];
@@ -15,11 +16,13 @@
const i18n = getContext('i18n') as any;
- $: selectedSkills = skills.filter((skill) => selectedSkillIds.includes(skill.id));
- $: availableSkills = skills.filter((skill) => !selectedSkillIds.includes(skill.id));
+ $: activeSkills = skills.filter((skill) => skill.is_active !== false);
+ $: selectedSkills = activeSkills.filter((skill) => selectedSkillIds.includes(skill.id));
- const selectSkill = (skill: Skill) => {
- selectedSkillIds = [...selectedSkillIds, skill.id];
+ const toggleSkill = (skill: Skill) => {
+ selectedSkillIds = selectedSkillIds.includes(skill.id)
+ ? selectedSkillIds.filter((id) => id !== skill.id)
+ : [...selectedSkillIds, skill.id];
};
@@ -29,14 +32,20 @@
- {#if skills.length > 0}
+ {#if activeSkills.length > 0}
{
- selectSkill(e.detail);
+ toggleSkill(e.detail);
+ }}
+ on:enableall={(e) => {
+ selectedSkillIds = [
+ ...new Set([...selectedSkillIds, ...e.detail.map((skill) => skill.id)])
+ ];
}}
/>
@@ -61,6 +70,18 @@
{/each}
+
+ {#if selectedSkills.length > 0}
+ {
+ selectedSkillIds = [];
+ }}
+ >
+ Disable all
+
+ {/if}
{/if}
diff --git a/src/lib/components/workspace/Models/TTSVoiceInput.svelte b/src/lib/components/workspace/Models/TTSVoiceInput.svelte
index ee2d91622c..b094523275 100644
--- a/src/lib/components/workspace/Models/TTSVoiceInput.svelte
+++ b/src/lib/components/workspace/Models/TTSVoiceInput.svelte
@@ -15,8 +15,12 @@
export let voices: Voice[] = [];
export let placeholder = '';
export let className = 'w-full';
+ export let selectedIds: string[] | null = null;
- const dispatch = createEventDispatcher<{ select: Voice }>();
+ const dispatch = createEventDispatcher<{
+ select: Voice;
+ enableall: Voice[];
+ }>();
const listboxId = `${id}-options`;
let inputElement: HTMLInputElement | null = null;
@@ -24,18 +28,17 @@
let suggestionsOpen = false;
$: query = value.trim().toLowerCase();
- $: filteredVoices = (voices ?? [])
- .filter((voice) => {
- const id = voice.id.toLowerCase();
- const name = (voice.name ?? '').toLowerCase();
- const description = (voice.description ?? voice.meta?.description ?? '').toLowerCase();
+ $: matchedVoices = (voices ?? []).filter((voice) => {
+ const id = voice.id.toLowerCase();
+ const name = (voice.name ?? '').toLowerCase();
+ const description = (voice.description ?? voice.meta?.description ?? '').toLowerCase();
- return (
- query === '' || id.includes(query) || name.includes(query) || description.includes(query)
- );
- })
- .slice(0, 8);
- $: if (suggestionsOpen && filteredVoices.length > 0) {
+ return (
+ query === '' || id.includes(query) || name.includes(query) || description.includes(query)
+ );
+ });
+ $: optionVoices = selectedIds === null ? matchedVoices.slice(0, 8) : matchedVoices;
+ $: if (suggestionsOpen && optionVoices.length > 0) {
tick().then(positionPopup);
}
@@ -60,11 +63,18 @@
};
const selectVoice = (voice: Voice) => {
- value = voice.id;
+ if (selectedIds === null) {
+ value = voice.id;
+ }
suggestionsOpen = false;
dispatch('select', voice);
};
+ const enableVoices = () => {
+ suggestionsOpen = false;
+ dispatch('enableall', matchedVoices);
+ };
+
const handlePointerDown = (event: PointerEvent) => {
if (!suggestionsOpen) return;
@@ -93,7 +103,7 @@
role="combobox"
aria-autocomplete="list"
aria-controls={listboxId}
- aria-expanded={suggestionsOpen && filteredVoices.length > 0}
+ aria-expanded={suggestionsOpen && optionVoices.length > 0}
autocomplete="off"
on:focus={() => {
suggestionsOpen = true;
@@ -117,7 +127,7 @@
}}
/>
-{#if suggestionsOpen && filteredVoices.length > 0}
+{#if suggestionsOpen && optionVoices.length > 0}
- {#each filteredVoices as voice (voice.id)}
+ {#if selectedIds !== null}
+ {#if matchedVoices.length > 0}
+ {
+ event.preventDefault();
+ }}
+ on:click={() => {
+ enableVoices();
+ }}
+ >
+ Enable all ({matchedVoices.length})
+
+ {/if}
+ {/if}
+ {#each optionVoices as voice (voice.id)}
{
event.preventDefault();
}}
diff --git a/src/lib/components/workspace/Models/ToolsSelector.svelte b/src/lib/components/workspace/Models/ToolsSelector.svelte
index 09aa2241b2..92e015f3a2 100644
--- a/src/lib/components/workspace/Models/ToolsSelector.svelte
+++ b/src/lib/components/workspace/Models/ToolsSelector.svelte
@@ -18,10 +18,11 @@
const i18n = getContext('i18n') as any;
$: selectedTools = tools.filter((tool) => selectedToolIds.includes(tool.id));
- $: availableTools = tools.filter((tool) => !selectedToolIds.includes(tool.id));
- const selectTool = (tool: Tool) => {
- selectedToolIds = [...selectedToolIds, tool.id];
+ const toggleTool = (tool: Tool) => {
+ selectedToolIds = selectedToolIds.includes(tool.id)
+ ? selectedToolIds.filter((id) => id !== tool.id)
+ : [...selectedToolIds, tool.id];
};
@@ -34,11 +35,15 @@
{#if tools.length > 0}
{
- selectTool(e.detail);
+ toggleTool(e.detail);
+ }}
+ on:enableall={(e) => {
+ selectedToolIds = [...new Set([...selectedToolIds, ...e.detail.map((tool) => tool.id)])];
}}
/>
@@ -63,11 +68,25 @@
{/each}
+
+ {#if selectedTools.length > 0}
+ {
+ selectedToolIds = [];
+ }}
+ >
+ Disable all
+
+ {/if}
{/if}
- {$i18n.t('To select toolkits here, add them to the "Tools" workspace first.')}
+ {$i18n.t(
+ 'To select toolkits here, add them to the "Tools" workspace or enable a tool server first.'
+ )}
diff --git a/src/lib/components/workspace/Models/TypeaheadSelector.svelte b/src/lib/components/workspace/Models/TypeaheadSelector.svelte
index 047069b7bb..db5c45593d 100644
--- a/src/lib/components/workspace/Models/TypeaheadSelector.svelte
+++ b/src/lib/components/workspace/Models/TypeaheadSelector.svelte
@@ -15,8 +15,12 @@
export let placeholder = '';
export let id = 'typeahead-selector';
export let className = 'w-full';
+ export let selectedIds: string[] | null = null;
- const dispatch = createEventDispatcher<{ select: Item }>();
+ const dispatch = createEventDispatcher<{
+ select: Item;
+ enableall: Item[];
+ }>();
let value = '';
@@ -26,10 +30,12 @@
voices={items}
{placeholder}
{className}
+ {selectedIds}
bind:value
on:select={(e) => {
dispatch('select', e.detail);
- value = '';
+ if (selectedIds === null) value = '';
}}
+ on:enableall={(e) => dispatch('enableall', e.detail)}
/>