]> git.djapps.eu Git - pkg/ggml/sources/llama.cpp/commitdiff
webui: Stop generation from chat sidebar (#17806)
authorAleksander Grygier <redacted>
Sat, 6 Dec 2025 12:29:15 +0000 (13:29 +0100)
committerGitHub <redacted>
Sat, 6 Dec 2025 12:29:15 +0000 (13:29 +0100)
* feat: Add stop generation button for Conversation Item

* chore: update webui build output

tools/server/public/index.html.gz
tools/server/webui/src/lib/components/app/chat/ChatSidebar/ChatSidebar.svelte
tools/server/webui/src/lib/components/app/chat/ChatSidebar/ChatSidebarConversationItem.svelte
tools/server/webui/src/lib/stores/chat.svelte.ts

index a9dba62abeb2190ce21f7a99cae86cd4d400eb21..2db04e9522742e0d7bb36034054bcbb58a958520 100644 (file)
Binary files a/tools/server/public/index.html.gz and b/tools/server/public/index.html.gz differ
index a113acbcb706a3d1347a720a1016f23c6f37047b..1d313e284e1dfd320babdc4ade50706bab478d7b 100644 (file)
@@ -8,6 +8,7 @@
        import * as AlertDialog from '$lib/components/ui/alert-dialog';
        import Input from '$lib/components/ui/input/input.svelte';
        import { conversationsStore, conversations } from '$lib/stores/conversations.svelte';
+       import { chatStore } from '$lib/stores/chat.svelte';
        import ChatSidebarActions from './ChatSidebarActions.svelte';
 
        const sidebar = Sidebar.useSidebar();
 
                await goto(`#/chat/${id}`);
        }
+
+       function handleStopGeneration(id: string) {
+               chatStore.stopGenerationForChat(id);
+       }
 </script>
 
 <ScrollArea class="h-[100vh]">
                                                        onSelect={selectConversation}
                                                        onEdit={handleEditConversation}
                                                        onDelete={handleDeleteConversation}
+                                                       onStop={handleStopGeneration}
                                                />
                                        </Sidebar.MenuItem>
                                {/each}
index 82685f83a52be79123f1ef24d3e9fe5fbd0387e5..bf2fa4f9e98d8c4f7f7707638e45b59f5d48a55b 100644 (file)
@@ -1,6 +1,7 @@
 <script lang="ts">
-       import { Trash2, Pencil, MoreHorizontal, Download, Loader2 } from '@lucide/svelte';
+       import { Trash2, Pencil, MoreHorizontal, Download, Loader2, Square } from '@lucide/svelte';
        import { ActionDropdown } from '$lib/components/app';
+       import * as Tooltip from '$lib/components/ui/tooltip';
        import { getAllLoadingChats } from '$lib/stores/chat.svelte';
        import { conversationsStore } from '$lib/stores/conversations.svelte';
        import { onMount } from 'svelte';
@@ -12,6 +13,7 @@
                onDelete?: (id: string) => void;
                onEdit?: (id: string) => void;
                onSelect?: (id: string) => void;
+               onStop?: (id: string) => void;
        }
 
        let {
@@ -20,6 +22,7 @@
                onDelete,
                onEdit,
                onSelect,
+               onStop,
                isActive = false
        }: Props = $props();
 
                onDelete?.(conversation.id);
        }
 
+       function handleStop(event: Event) {
+               event.stopPropagation();
+               onStop?.(conversation.id);
+       }
+
        function handleGlobalEditEvent(event: Event) {
                const customEvent = event as CustomEvent<{ conversationId: string }>;
+
                if (customEvent.detail.conversationId === conversation.id && isActive) {
                        handleEdit(event);
                }
 >
        <div class="flex min-w-0 flex-1 items-center gap-2">
                {#if isLoading}
-                       <Loader2 class="h-3.5 w-3.5 shrink-0 animate-spin text-muted-foreground" />
+                       <Tooltip.Root>
+                               <Tooltip.Trigger>
+                                       <div
+                                               class="stop-button flex h-4 w-4 shrink-0 cursor-pointer items-center justify-center rounded text-muted-foreground transition-colors hover:text-foreground"
+                                               onclick={handleStop}
+                                               onkeydown={(e) => e.key === 'Enter' && handleStop(e)}
+                                               role="button"
+                                               tabindex="0"
+                                               aria-label="Stop generation"
+                                       >
+                                               <Loader2 class="loading-icon h-3.5 w-3.5 animate-spin" />
+
+                                               <Square class="stop-icon hidden h-3 w-3 fill-current text-destructive" />
+                                       </div>
+                               </Tooltip.Trigger>
+
+                               <Tooltip.Content>
+                                       <p>Stop generation</p>
+                               </Tooltip.Content>
+                       </Tooltip.Root>
                {/if}
+
                <!-- svelte-ignore a11y_click_events_have_key_events -->
                <!-- svelte-ignore a11y_no_static_element_interactions -->
                <span class="truncate text-sm font-medium" onclick={handleMobileSidebarItemClick}>
                                opacity: 1 !important;
                        }
                }
+
+               .stop-button {
+                       :global(.stop-icon) {
+                               display: none;
+                       }
+
+                       :global(.loading-icon) {
+                               display: block;
+                       }
+               }
+
+               &:is(:hover) .stop-button {
+                       :global(.stop-icon) {
+                               display: block;
+                       }
+
+                       :global(.loading-icon) {
+                               display: none;
+                       }
+               }
        }
 </style>
index 167f24288f32e43312214b851b615e930a20a4e6..4f78840a57d2aa208ebb49f610d6c470865be4fa 100644 (file)
@@ -701,13 +701,17 @@ class ChatStore {
 
                if (!activeConv) return;
 
-               await this.savePartialResponseIfNeeded(activeConv.id);
+               await this.stopGenerationForChat(activeConv.id);
+       }
+
+       async stopGenerationForChat(convId: string): Promise<void> {
+               await this.savePartialResponseIfNeeded(convId);
 
                this.stopStreaming();
-               this.abortRequest(activeConv.id);
-               this.setChatLoading(activeConv.id, false);
-               this.clearChatStreaming(activeConv.id);
-               this.clearProcessingState(activeConv.id);
+               this.abortRequest(convId);
+               this.setChatLoading(convId, false);
+               this.clearChatStreaming(convId);
+               this.clearProcessingState(convId);
        }
 
        /**