]> git.djapps.eu Git - pkg/ggml/sources/llama.cpp/blob
f902ec88d594f9ae7ea1bb2f3476eb5c49023dbc
[pkg/ggml/sources/llama.cpp] /
1 <script lang="ts">
2 import {
3 ChatMessageActionIcons,
4 ChatMessageEditForm,
5 ChatMessageStatistics,
6 ChatMessageUserBubble
7 } from '$lib/components/app/chat';
8 import { getMessageEditContext } from '$lib/contexts';
9 import { ChatMessageStatisticsMode, MessageRole } from '$lib/enums';
10 import { useProcessingState } from '$lib/hooks/use-processing-state.svelte';
11 import { chatStore, settingsStore } from '$lib/stores';
12
13 interface Props {
14 class?: string;
15 message: DatabaseMessage;
16 siblingInfo?: ChatMessageSiblingInfo | null;
17 deletionInfo: {
18 totalCount: number;
19 userMessages: number;
20 assistantMessages: number;
21 messageTypes: string[];
22 } | null;
23 isLastUserMessage?: boolean;
24 nextAssistantMessage?: DatabaseMessage | null;
25 showDeleteDialog: boolean;
26 onEdit: () => void;
27 onDelete: () => void;
28 onConfirmDelete: () => void;
29 onForkConversation?: (options: { name: string; includeAttachments: boolean }) => void;
30 onShowDeleteDialogChange: (show: boolean) => void;
31 onNavigateToSibling?: (siblingId: string) => void;
32 onCopy: () => void;
33 }
34
35 let {
36 class: className = '',
37 deletionInfo,
38 isLastUserMessage = false,
39 message,
40 nextAssistantMessage = null,
41 onConfirmDelete,
42 onCopy,
43 onDelete,
44 onEdit,
45 onForkConversation,
46 onNavigateToSibling,
47 onShowDeleteDialogChange,
48 showDeleteDialog,
49 siblingInfo = null
50 }: Props = $props();
51
52 // Get contexts
53 const editCtx = getMessageEditContext();
54 const processingState = useProcessingState();
55
56 const currentConfig = $derived(settingsStore.config);
57 const isActivelyProcessing = $derived(isLastUserMessage && chatStore.isLoading);
58
59 // For agentic turns, prefer the cumulative agentic.llm totals over per-call timings.
60 let storedReadingStats = $derived.by(() => {
61 const timings = nextAssistantMessage?.timings;
62
63 if (!timings?.prompt_n || !timings?.prompt_ms) return null;
64
65 const agentic = timings.agentic;
66
67 return {
68 promptMs: agentic ? agentic.llm.prompt_ms : timings.prompt_ms,
69 promptTokens: agentic ? agentic.llm.prompt_n : timings.prompt_n
70 };
71 });
72
73 let showStoredReadingStats = $derived(
74 Boolean(currentConfig.showMessageStats) && storedReadingStats !== null
75 );
76
77 let showLiveReadingStats = $derived(
78 Boolean(currentConfig.showMessageStats) && isActivelyProcessing && storedReadingStats === null
79 );
80
81 $effect(() => {
82 if (showLiveReadingStats) {
83 processingState.startMonitoring();
84 }
85 });
86 </script>
87
88 <div
89 aria-label="User message with actions"
90 class="chat-message-user group flex flex-col items-end gap-3 md:gap-2 {className}"
91 role="group"
92 >
93 {#if editCtx.isEditing}
94 <ChatMessageEditForm />
95 {:else}
96 <ChatMessageUserBubble
97 content={message.content}
98 attachments={message.extra}
99 renderMarkdown={true}
100 />
101
102 {#if showStoredReadingStats}
103 <!-- Reading stats sourced from the assistant message that followed this turn -->
104 <div class="info my-2 grid w-full justify-items-end gap-4 tabular-nums">
105 <div
106 class="inline-flex flex-wrap items-start justify-end gap-2 text-xs text-muted-foreground"
107 >
108 <ChatMessageStatistics
109 mode={ChatMessageStatisticsMode.READING}
110 promptTokens={storedReadingStats!.promptTokens}
111 promptMs={storedReadingStats!.promptMs}
112 />
113 </div>
114 </div>
115 {:else if showLiveReadingStats}
116 {@const liveStats = processingState.getLiveProcessingStats()}
117 {#if liveStats}
118 <div class="info my-2 grid w-full justify-items-end gap-4 tabular-nums">
119 <div
120 class="inline-flex flex-wrap items-start justify-end gap-2 text-xs text-muted-foreground"
121 >
122 <ChatMessageStatistics
123 mode={ChatMessageStatisticsMode.READING}
124 isLive
125 promptTokens={liveStats.tokensProcessed}
126 promptMs={liveStats.timeMs}
127 />
128 </div>
129 </div>
130 {/if}
131 {/if}
132
133 {#if message.timestamp}
134 <div class="max-w-[80%]">
135 <ChatMessageActionIcons
136 actionsPosition="right"
137 {deletionInfo}
138 justify="end"
139 {onConfirmDelete}
140 {onCopy}
141 {onDelete}
142 {onEdit}
143 {onForkConversation}
144 {onNavigateToSibling}
145 {onShowDeleteDialogChange}
146 {siblingInfo}
147 {showDeleteDialog}
148 role={MessageRole.USER}
149 />
150 </div>
151 {/if}
152 {/if}
153 </div>