]> git.djapps.eu Git - pkg/ggml/sources/llama.cpp/blob
d08dafcff54f399fa3fecf658dff3fd423d711a6
[pkg/ggml/sources/llama.cpp] /
1 <script lang="ts">
2 import { ArrowRight, Copy, Edit, GitBranch, RefreshCw, Trash2 } from '@lucide/svelte';
3 import {
4 ActionIcon,
5 ChatMessageActionIconsBranchingControls,
6 DialogConfirmation
7 } from '$lib/components/app';
8 import { Checkbox } from '$lib/components/ui/checkbox';
9 import Input from '$lib/components/ui/input/input.svelte';
10 import Label from '$lib/components/ui/label/label.svelte';
11 import { Switch } from '$lib/components/ui/switch';
12 import { MessageRole } from '$lib/enums';
13 import { activeConversation } from '$lib/stores/conversations.svelte';
14
15 interface Props {
16 role: MessageRole.USER | MessageRole.ASSISTANT;
17 justify: 'start' | 'end';
18 actionsPosition: 'left' | 'right';
19 siblingInfo?: ChatMessageSiblingInfo | null;
20 showDeleteDialog: boolean;
21 deletionInfo: {
22 totalCount: number;
23 userMessages: number;
24 assistantMessages: number;
25 messageTypes: string[];
26 } | null;
27 onCopy: () => void;
28 onEdit?: () => void;
29 onRegenerate?: () => void;
30 onContinue?: () => void;
31 onForkConversation?: (options: { name: string; includeAttachments: boolean }) => void;
32 onDelete: () => void;
33 onConfirmDelete: () => void;
34 onNavigateToSibling?: (siblingId: string) => void;
35 onShowDeleteDialogChange: (show: boolean) => void;
36 showRawOutputSwitch?: boolean;
37 rawOutputEnabled?: boolean;
38 onRawOutputToggle?: (enabled: boolean) => void;
39 }
40
41 let {
42 actionsPosition,
43 deletionInfo,
44 justify,
45 onConfirmDelete,
46 onContinue,
47 onCopy,
48 onDelete,
49 onEdit,
50 onForkConversation,
51 onNavigateToSibling,
52 onRawOutputToggle,
53 onRegenerate,
54 onShowDeleteDialogChange,
55 rawOutputEnabled = false,
56 role,
57 showDeleteDialog,
58 showRawOutputSwitch = false,
59 siblingInfo = null
60 }: Props = $props();
61
62 let showForkDialog = $state(false);
63 let forkName = $state('');
64 let forkIncludeAttachments = $state(true);
65
66 function handleConfirmDelete() {
67 onConfirmDelete();
68 onShowDeleteDialogChange(false);
69 }
70
71 function handleOpenForkDialog() {
72 const conv = activeConversation();
73
74 forkName = `Fork of ${conv?.name ?? 'Conversation'}`;
75 forkIncludeAttachments = true;
76 showForkDialog = true;
77 }
78
79 function handleConfirmFork() {
80 onForkConversation?.({ includeAttachments: forkIncludeAttachments, name: forkName.trim() });
81 showForkDialog = false;
82 }
83 </script>
84
85 <div class="relative {justify === 'start' ? 'mt-2' : ''} flex h-6 items-center justify-between">
86 <div
87 class="{actionsPosition === 'left'
88 ? 'left-0'
89 : 'right-0'} flex items-center gap-2 opacity-100 transition-opacity"
90 >
91 {#if siblingInfo && siblingInfo.totalSiblings > 1}
92 <ChatMessageActionIconsBranchingControls {siblingInfo} {onNavigateToSibling} />
93 {/if}
94
95 <div
96 class="pointer-events-auto inset-0 flex items-center gap-1 opacity-100 transition-all duration-150"
97 >
98 <ActionIcon icon={Copy} tooltip="Copy" onclick={onCopy} />
99
100 {#if onEdit}
101 <ActionIcon icon={Edit} tooltip="Edit" onclick={onEdit} />
102 {/if}
103
104 {#if role === MessageRole.ASSISTANT && onRegenerate}
105 <ActionIcon icon={RefreshCw} tooltip="Regenerate" onclick={() => onRegenerate()} />
106 {/if}
107
108 {#if role === MessageRole.ASSISTANT && onContinue}
109 <ActionIcon icon={ArrowRight} tooltip="Continue" onclick={onContinue} />
110 {/if}
111
112 {#if onForkConversation}
113 <ActionIcon icon={GitBranch} tooltip="Fork conversation" onclick={handleOpenForkDialog} />
114 {/if}
115
116 <ActionIcon icon={Trash2} tooltip="Delete" onclick={onDelete} />
117 </div>
118 </div>
119
120 {#if showRawOutputSwitch}
121 <div class="flex items-center gap-2">
122 <span class="text-xs text-muted-foreground">Show raw output</span>
123 <Switch
124 checked={rawOutputEnabled}
125 onCheckedChange={(checked) => onRawOutputToggle?.(checked)}
126 />
127 </div>
128 {/if}
129 </div>
130
131 <DialogConfirmation
132 bind:open={showDeleteDialog}
133 title="Delete Message"
134 description={deletionInfo && deletionInfo.totalCount > 1
135 ? `This will delete ${deletionInfo.totalCount} messages including: ${deletionInfo.userMessages} user message${deletionInfo.userMessages > 1 ? 's' : ''} and ${deletionInfo.assistantMessages} assistant response${deletionInfo.assistantMessages > 1 ? 's' : ''}. All messages in this branch and their responses will be permanently removed. This action cannot be undone.`
136 : 'Are you sure you want to delete this message? This action cannot be undone.'}
137 confirmText={deletionInfo && deletionInfo.totalCount > 1
138 ? `Delete ${deletionInfo.totalCount} Messages`
139 : 'Delete'}
140 cancelText="Cancel"
141 variant="destructive"
142 icon={Trash2}
143 onConfirm={handleConfirmDelete}
144 onCancel={() => onShowDeleteDialogChange(false)}
145 />
146
147 <DialogConfirmation
148 bind:open={showForkDialog}
149 title="Fork Conversation"
150 description="Create a new conversation branching from this message."
151 confirmText="Fork"
152 cancelText="Cancel"
153 icon={GitBranch}
154 onConfirm={handleConfirmFork}
155 onCancel={() => (showForkDialog = false)}
156 >
157 <div class="flex flex-col gap-4 py-2">
158 <div class="flex flex-col gap-2">
159 <Label for="fork-name">Title</Label>
160
161 <Input
162 id="fork-name"
163 class="text-foreground"
164 placeholder="Enter fork name"
165 type="text"
166 bind:value={forkName}
167 />
168 </div>
169
170 <div class="flex items-center gap-2">
171 <Checkbox
172 id="fork-attachments"
173 checked={forkIncludeAttachments}
174 onCheckedChange={(checked) => {
175 forkIncludeAttachments = checked === true;
176 }}
177 />
178
179 <Label for="fork-attachments" class="cursor-pointer text-sm font-normal">
180 Include all attachments
181 </Label>
182 </div>
183 </div>
184 </DialogConfirmation>