From a3cd6158bb188837dcbfbc11ade56d1a1f748db2 Mon Sep 17 00:00:00 2001 From: Timothy Jaeryang Baek Date: Sat, 10 Oct 2026 18:51:24 +0400 Subject: [PATCH] refac --- backend/open_webui/utils/skill_files.py | 2 +- src/lib/components/workspace/Skills.svelte | 43 +++++++++++++++++++ .../workspace/Skills/SkillMenu.svelte | 13 +++++- .../workspace/skills/create/+page.svelte | 40 +++++++++++++++-- 4 files changed, 93 insertions(+), 5 deletions(-) diff --git a/backend/open_webui/utils/skill_files.py b/backend/open_webui/utils/skill_files.py index 9ec201dfbc..c75e24c7ae 100644 --- a/backend/open_webui/utils/skill_files.py +++ b/backend/open_webui/utils/skill_files.py @@ -237,7 +237,7 @@ def parse_import( 'name': str(name), 'description': package.get('description', fm.get('description', '')), 'meta': package.get('meta') or {}, - 'is_active': package.get('is_active', True), + **({'is_active': package['is_active']} if 'is_active' in package else {}), 'files': files, } ) diff --git a/src/lib/components/workspace/Skills.svelte b/src/lib/components/workspace/Skills.svelte index 307125613d..6358c2228b 100644 --- a/src/lib/components/workspace/Skills.svelte +++ b/src/lib/components/workspace/Skills.svelte @@ -43,6 +43,40 @@ import Badge from '$lib/components/common/Badge.svelte'; import Switch from '../common/Switch.svelte'; import SkillMenu from './Skills/SkillMenu.svelte'; + import CommunityDiscover from './common/CommunityDiscover.svelte'; + import { config } from '$lib/stores'; + let stopSkillShare = () => {}; + const shareHandler = (skill: { id: string }) => { + stopSkillShare(); + const tab = window.open('https://openwebui.com/post?type=skill', '_blank'); + if (!tab) { + toast.error($i18n.t('Please allow popups to share your skill.')); + return; + } + const receiveLoaded = async (event: MessageEvent) => { + if ( + event.origin !== 'https://openwebui.com' || + event.source !== tab || + event.data !== 'loaded' + ) + return; + stopSkillShare(); + try { + const exported = JSON.parse( + await (await exportSkillBundle(localStorage.token, 'json', [skill.id])).text() + ); + const { id, name, description, files } = Array.isArray(exported) ? exported[0] : exported; + const data = JSON.stringify({ id, name, description, files }); + if (new Blob([data]).size > 15 * 1024 * 1024) + throw new Error('Community skill JSON exceeds 15 MiB'); + tab.postMessage(data, 'https://openwebui.com'); + } catch (error) { + toast.error(skillError(error)); + } + }; + window.addEventListener('message', receiveLoaded); + stopSkillShare = () => window.removeEventListener('message', receiveLoaded); + }; import SkillImport from './Skills/SkillImport.svelte'; import ImportModal from '$lib/components/ImportModal.svelte'; import { cloneSkill, exportSkillBundle, loadSkillByUrl, skillError } from '$lib/apis/skills'; @@ -289,6 +323,7 @@ }); onDestroy(() => { + stopSkillShare(); searchController?.abort(); clearTimeout(searchDebounceTimer); }); @@ -564,6 +599,7 @@ {:else}
shareHandler(skill)} accessHandler={() => accessModal.open(skill.id)} show={openSkillMenuId === skill.id} editHandler={() => { @@ -655,6 +691,13 @@ {resolveLocalizedResource(selectedSkill, $i18n.language)}.
+ {#if $config?.features?.enable_community_sharing} + + {/if} {:else}
diff --git a/src/lib/components/workspace/Skills/SkillMenu.svelte b/src/lib/components/workspace/Skills/SkillMenu.svelte index 4c344e3ff8..5c1e62e134 100644 --- a/src/lib/components/workspace/Skills/SkillMenu.svelte +++ b/src/lib/components/workspace/Skills/SkillMenu.svelte @@ -8,13 +8,14 @@ import Tooltip from '$lib/components/common/Tooltip.svelte'; import DocumentDuplicate from '$lib/components/icons/DocumentDuplicate.svelte'; import Download from '$lib/components/icons/Download.svelte'; - import { user } from '$lib/stores'; + import { user, config } from '$lib/stores'; const i18n = getContext('i18n'); export let editHandler: Function; export let cloneHandler: Function; export let exportHandler: Function; + export let shareHandler: (() => void) | null = null; export let deleteHandler: Function; export let accessHandler: (() => void) | null = null; export let onClose: Function; @@ -90,6 +91,16 @@
{$i18n.t('Clone')}
+ {#if shareHandler && $config?.features?.enable_community_sharing && ($user?.role === 'admin' || $user?.permissions?.workspace?.skills_export)} + + {/if} {#if $user?.role === 'admin' || $user?.permissions?.workspace?.skills_export}