From 58078ab3045cc7aee409d9215f68adf0e02c9165 Mon Sep 17 00:00:00 2001 From: Timothy Jaeryang Baek Date: Mon, 14 Sep 2026 15:47:50 -0400 Subject: [PATCH] refac --- src/lib/components/chat/MessageInput.svelte | 26 +++++++++++++- .../MessageInput/CommandSuggestionList.svelte | 6 ++++ .../Commands/SlashCommands.svelte | 34 +++++++++++++++++++ 3 files changed, 65 insertions(+), 1 deletion(-) diff --git a/src/lib/components/chat/MessageInput.svelte b/src/lib/components/chat/MessageInput.svelte index c9f29fd2f6..d3cf5da88d 100644 --- a/src/lib/components/chat/MessageInput.svelte +++ b/src/lib/components/chat/MessageInput.svelte @@ -174,6 +174,12 @@ (history.currentId && history.messages[history.currentId]?.done != true) || generating); $: canCompact = !!history?.currentId; + $: hasChatContent = history?.currentId + ? createMessagesList(history, history.currentId).some( + (message) => + !!message?.content || !!message?.tool_calls || !!message?.files || !!message?.models + ) + : false; $: canToggleTemporary = !embedded && !chatId && @@ -578,6 +584,12 @@ } }; + const createSkillHandler = async () => { + prompt = '/skills:create'; + await tick(); + dispatch('submit', prompt); + }; + const insertTextAtCursor = async (text: string) => { const chatInput = document.getElementById('chat-input'); if (!chatInput) return; @@ -1418,7 +1430,17 @@ return; } - if (['compact', 'fork', 'status', 'model', 'settings', 'temporary'].includes(props?.id)) { + if ( + [ + 'compact', + 'fork', + 'status', + 'model', + 'settings', + 'temporary', + 'skills:create' + ].includes(props?.id) + ) { editor.chain().focus().deleteRange(range).run(); return; } @@ -1445,6 +1467,7 @@ ($_user?.role === 'admin' || ($_user?.permissions?.chat?.import ?? true)), forkDisabled: () => isActive, canTemporary: () => canToggleTemporary, + hasChatContent: hasChatContent, temporaryEnabled: () => $temporaryChatEnabled === true, contextUsage: () => statusContextUsage, onCompact: compactHandler, @@ -1453,6 +1476,7 @@ onModel: () => modelSelector?.open(), onSettings: () => showSettings.set(true), onTemporary: temporaryHandler, + onCreateSkill: createSkillHandler, onSelect: (e) => { const { type, data } = e; diff --git a/src/lib/components/chat/MessageInput/CommandSuggestionList.svelte b/src/lib/components/chat/MessageInput/CommandSuggestionList.svelte index 8ecf6f4e2e..8988ab9e29 100644 --- a/src/lib/components/chat/MessageInput/CommandSuggestionList.svelte +++ b/src/lib/components/chat/MessageInput/CommandSuggestionList.svelte @@ -23,6 +23,7 @@ export let onModel: () => void = () => {}; export let onSettings: () => void = () => {}; export let onTemporary: () => void = () => {}; + export let onCreateSkill: () => void = () => {}; export let insertTextHandler: (text: string) => void = () => {}; export let canCompact: boolean | (() => boolean) = false; export let compactDisabled: boolean | (() => boolean) = false; @@ -31,6 +32,7 @@ export let forkDisabled: boolean | (() => boolean) = false; export let canTemporary: boolean | (() => boolean) = false; export let temporaryEnabled: boolean | (() => boolean) = false; + export let hasChatContent = false; export let contextUsage = null; $: compactAvailable = typeof canCompact === 'function' ? canCompact() : canCompact; @@ -104,6 +106,7 @@ temporaryEnabled={isTemporaryEnabled} {contextPercent} {contextHasThreshold} + {hasChatContent} onSelect={(e) => { const { type, data } = e; @@ -132,6 +135,9 @@ } else if (type === 'command' && data.id === 'temporary') { command({ id: data.id, label: data.id }); onTemporary(); + } else if (type === 'command' && data.id === 'skills:create') { + command({ id: data.id, label: data.id }); + onCreateSkill(); } else if (type === 'skill') { command({ id: `${data.id}|${data.name}`, diff --git a/src/lib/components/chat/MessageInput/Commands/SlashCommands.svelte b/src/lib/components/chat/MessageInput/Commands/SlashCommands.svelte index 6f0e2f964d..2450422813 100644 --- a/src/lib/components/chat/MessageInput/Commands/SlashCommands.svelte +++ b/src/lib/components/chat/MessageInput/Commands/SlashCommands.svelte @@ -20,6 +20,7 @@ import ChatBubbleDottedChecked from '$lib/components/icons/ChatBubbleDottedChecked.svelte'; import Cube from '$lib/components/icons/Cube.svelte'; import Knobs from '$lib/components/icons/Knobs.svelte'; + import Plus from '$lib/components/icons/Plus.svelte'; import Sparkles from '$lib/components/icons/Sparkles.svelte'; const i18n: any = getContext('i18n'); @@ -33,6 +34,7 @@ export let forkDisabled = false; export let canTemporary = false; export let temporaryEnabled = false; + export let hasChatContent = false; export let contextPercent = 0; export let contextHasThreshold = false; @@ -66,6 +68,9 @@ : []), ...('settings'.startsWith(query.toLowerCase()) ? [{ type: 'command', data: { id: 'settings' } }] + : []), + ...(hasChatContent && $selectedTerminalId && 'skills:create'.startsWith(query.toLowerCase()) + ? [{ type: 'command', data: { id: 'skills:create' } }] : []) ]; @@ -375,6 +380,35 @@ + {:else if item.data.id === 'skills:create'} + + + {:else if item.data.id === 'settings'}