feat: add skills management to chat component (#25037)

- Introduced skills functionality in Chat.svelte, MessageInput.svelte, and related components.
- Added SkillsModal for displaying and managing available skills.
- Updated state management to include selectedSkillIds and integrate skills API.
- Enhanced UI to show available skills and their descriptions.
- Updated translations to support skills-related text.
This commit is contained in:
Mr. Meowgi authored and GitHub committed 2026-06-01 12:53:30 -07:00
1 parent 42c2393f8e
commit a9da054572
6 files changed
+233 -3

No files matched your search

+32 -2
View File
@@ -38,6 +38,7 @@
showArtifacts,
artifactContents,
tools,
skills,
toolServers,
terminalServers,
functions,
@@ -92,6 +93,7 @@
getTaskIdsByChatId
} from '$lib/apis';
import { getTools } from '$lib/apis/tools';
import { getSkills } from '$lib/apis/skills';
import { uploadFile } from '$lib/apis/files';
import { createOpenAITextStream } from '$lib/apis/streaming';
import { getFunctions } from '$lib/apis/functions';
@@ -150,6 +152,7 @@
}
let selectedToolIds = [];
let selectedSkillIds = [];
let selectedFilterIds = [];
let pendingOAuthTools = [];
@@ -208,6 +211,7 @@
files = [];
selectedToolIds = [];
selectedSkillIds = [];
selectedFilterIds = [];
webSearchEnabled = false;
imageGenerationEnabled = false;
@@ -243,6 +247,7 @@
messageInput?.setText(input.prompt);
files = input.files;
selectedToolIds = input.selectedToolIds;
selectedSkillIds = input.selectedSkillIds ?? [];
selectedFilterIds = input.selectedFilterIds;
webSearchEnabled = input.webSearchEnabled;
imageGenerationEnabled = input.imageGenerationEnabled;
@@ -303,6 +308,7 @@
const resetInput = async () => {
selectedToolIds = [];
selectedSkillIds = [];
selectedFilterIds = [];
pendingOAuthTools = [];
webSearchEnabled = false;
@@ -329,6 +335,9 @@
if (!$functions) {
functions.set(await getFunctions(localStorage.token));
}
if (!$skills) {
skills.set(await getSkills(localStorage.token));
}
if (selectedModels.length !== 1 && !atSelectedModel) {
return;
}
@@ -366,6 +375,19 @@
selectedToolIds = selectedToolIds.filter((id) => !id.startsWith('direct_server:'));
}
// Set Default Skills
if (model?.info?.meta?.skillIds) {
selectedSkillIds = [
...new Set(
[...(model?.info?.meta?.skillIds ?? [])].filter((id) =>
($skills ?? []).find((s) => s.id === id && s.is_active)
)
)
];
} else {
selectedSkillIds = [];
}
// Set Default Filters (Toggleable only)
if (model?.info?.meta?.defaultFilterIds) {
selectedFilterIds = model.info.meta.defaultFilterIds.filter((id) =>
@@ -830,6 +852,7 @@
files = [];
selectedToolIds = [];
selectedSkillIds = [];
selectedFilterIds = [];
webSearchEnabled = false;
imageGenerationEnabled = false;
@@ -842,6 +865,7 @@
messageInput?.setText(input.prompt);
files = input.files;
selectedToolIds = input.selectedToolIds;
selectedSkillIds = input.selectedSkillIds ?? [];
selectedFilterIds = input.selectedFilterIds;
webSearchEnabled = input.webSearchEnabled;
imageGenerationEnabled = input.imageGenerationEnabled;
@@ -2365,11 +2389,15 @@
// Parse skill mentions (<$skillId|label>) from user messages
const skillMentionRegex = /<\$([^|>]+)\|?[^>]*>/g;
const skillIds = [];
const skillIds = [...selectedSkillIds];
const mentionSkillIds = [];
for (const message of messages) {
const content =
typeof message.content === 'string' ? message.content : (message.content?.[0]?.text ?? '');
for (const match of content.matchAll(skillMentionRegex)) {
if (!mentionSkillIds.includes(match[1])) {
mentionSkillIds.push(match[1]);
}
if (!skillIds.includes(match[1])) {
skillIds.push(match[1]);
}
@@ -2377,7 +2405,7 @@
}
// Strip skill mentions from message content
if (skillIds.length > 0) {
if (mentionSkillIds.length > 0) {
messages = messages.map((message) => {
if (typeof message.content === 'string') {
return {
@@ -3109,6 +3137,7 @@
bind:prompt
bind:autoScroll
bind:selectedToolIds
bind:selectedSkillIds
bind:selectedFilterIds
bind:imageGenerationEnabled
bind:codeInterpreterEnabled
@@ -3190,6 +3219,7 @@
bind:prompt
bind:autoScroll
bind:selectedToolIds
bind:selectedSkillIds
bind:selectedFilterIds
bind:imageGenerationEnabled
bind:codeInterpreterEnabled