This commit is contained in:
Timothy Jaeryang Baek committed 2026-07-15 22:34:52 -04:00
1 parent b16a4c4e9a
commit 185bca8552
20 files changed
+693 -156

No files matched your search

@@ -283,31 +283,35 @@
onPreview={previewHandler}
/>
{:else if $settings?.renderMarkdownInAssistantMessages ?? true}
<Markdown
{id}
content={formatMessageContent(content)}
{model}
{save}
{preview}
{done}
{editCodeBlock}
{topPadding}
{sourceIds}
{onSourceClick}
{onTaskClick}
{onSave}
onUpdate={markdownUpdateHandler}
onPreview={previewHandler}
/>
<div class="markdown-prose">
<Markdown
{id}
content={formatMessageContent(content)}
{model}
{save}
{preview}
{done}
{editCodeBlock}
{topPadding}
{sourceIds}
{onSourceClick}
{onTaskClick}
{onSave}
onUpdate={markdownUpdateHandler}
onPreview={previewHandler}
/>
</div>
{:else}
{@const extracted = extractDetailsBlocks(content)}
{#if extracted.detailsContent}
<!-- Render structural blocks (tool calls, reasoning, etc.) through Markdown -->
<Markdown {id} content={extracted.detailsContent} {done} />
<div class="markdown-prose">
<Markdown {id} content={extracted.detailsContent} {done} />
</div>
{/if}
{#if extracted.plainContent}
<div class="whitespace-pre-wrap">{extracted.plainContent}</div>
<div class="whitespace-pre-wrap text-sm">{extracted.plainContent}</div>
{/if}
{/if}
</div>
@@ -38,11 +38,11 @@
</script>
<div
class="my-2 flex w-full items-start gap-3 rounded-3xl bg-black/[0.03] px-4 py-3 text-gray-500 dark:bg-white/[0.04] dark:text-gray-400"
class="my-1.5 flex w-full items-start gap-2 rounded-2xl bg-black/[0.03] px-3 py-2 text-gray-500 dark:bg-white/[0.04] dark:text-gray-400"
>
<Info className="mt-0.5 size-5 shrink-0 text-gray-400 dark:text-gray-500" strokeWidth="2" />
<Info className="mt-0.5 size-4 shrink-0 text-gray-400 dark:text-gray-500" strokeWidth="1.8" />
<div class="min-w-0 break-words text-sm leading-6">
<div class="min-w-0 break-words text-[0.8125rem] leading-5">
{message}
</div>
</div>
@@ -10,8 +10,7 @@
import citationExtension from '$lib/utils/marked/citation-extension';
const options = {
throwOnError: false,
breaks: true
throwOnError: false
};
marked.use(markedKatexExtension(options));
@@ -112,7 +112,7 @@
<div {id} class="w-full">
<!-- svelte-ignore a11y-no-static-element-interactions -->
<button
class="w-fit text-left text-gray-500 hover:text-gray-700 dark:hover:text-gray-300 transition cursor-pointer"
class="w-fit py-1 text-left text-sm text-gray-500 hover:text-gray-700 dark:hover:text-gray-300 transition cursor-pointer"
aria-label={$i18n.t('Toggle details')}
aria-expanded={open}
on:click={() => {
@@ -158,7 +158,7 @@
{#if open}
<div transition:slide={{ duration: 300, easing: quintOut, axis: 'y' }}>
<div class="mb-0.5 space-y-0.5">
<div class="mb-1 space-y-1.5">
<slot name="content" />
</div>
</div>
@@ -98,6 +98,9 @@
};
$: displayTokens = getDisplayTokens(tokens);
$: singlePlainBlock =
displayTokens.length === 1 &&
(displayTokens[0]?.type === 'paragraph' || displayTokens[0]?.type === 'text');
const exportTableToCSVHandler = (token, tokenIdx = 0) => {
console.log('Exporting table to CSV');
@@ -141,7 +144,7 @@
<!-- {JSON.stringify(tokens)} -->
{#each displayTokens as token, tokenIdx (tokenIdx)}
{#if token.type === 'hr'}
<hr class=" border-gray-100/30 dark:border-gray-850/30" />
<hr class="border-gray-50 dark:border-gray-850/30" />
{:else if token.type === 'heading'}
<svelte:element this={headerComponent(token.depth)} dir="auto">
<MarkdownInlineTokens
@@ -385,7 +388,7 @@
resultContent={getDetailTextContent(detailToken)}
grouped={true}
open={$settings?.expandDetails ?? false}
className="w-full space-y-1"
className="w-full space-y-2"
/>
{:else if textContent.length > 0}
<Collapsible
@@ -393,7 +396,7 @@
open={$settings?.expandDetails ?? false}
attributes={detailToken?.attributes}
messageDone={done}
className="w-full space-y-1"
className="w-full space-y-2"
dir="auto"
>
<div class="mb-1.5" slot="content">
@@ -416,7 +419,7 @@
disabled={true}
attributes={detailToken?.attributes}
messageDone={done}
className="w-full space-y-1"
className="w-full space-y-2"
dir="auto"
/>
{/if}
@@ -433,7 +436,7 @@
attributes={token.attributes}
resultContent={getDetailTextContent(token)}
open={$settings?.expandDetails ?? false}
className="w-full space-y-1"
className="w-full space-y-2"
/>
{:else if textContent.length > 0}
<Collapsible
@@ -441,7 +444,7 @@
open={$settings?.expandDetails ?? false}
attributes={token?.attributes}
messageDone={done}
className="w-full space-y-1"
className="w-full space-y-2"
dir="auto"
>
<div class=" mb-1.5" slot="content">
@@ -464,7 +467,7 @@
disabled={true}
attributes={token?.attributes}
messageDone={done}
className="w-full space-y-1"
className="w-full space-y-2"
dir="auto"
/>
{/if}
@@ -495,7 +498,7 @@
/>
</span>
{:else}
<p dir="auto">
<p dir="auto" class={singlePlainBlock ? '!my-0' : ''}>
<MarkdownInlineTokens
id={`${id}-${tokenIdx}-p`}
tokens={token.tokens ?? []}
@@ -507,7 +510,7 @@
{/if}
{:else if token.type === 'text'}
{#if top}
<p>
<p class={singlePlainBlock ? '!my-0' : ''}>
{#if token.tokens}
<MarkdownInlineTokens
id={`${id}-${tokenIdx}-t`}
@@ -551,7 +554,7 @@
{onSourceClick}
/>
{:else if token.type === 'space'}
<div class="my-2" />
<!-- skip -->
{:else}
{console.log('Unknown token', token)}
{/if}
@@ -405,11 +405,13 @@
{$i18n.t('Merged Response')}
</Name>
<div class="mt-1 markdown-prose w-full min-w-full">
<div class="mt-1 w-full min-w-full">
{#if (message?.content ?? '') === ''}
<Skeleton />
{:else}
<Markdown id={`merged`} content={message.content ?? ''} />
<div class="markdown-prose">
<Markdown id={`merged`} content={message.content ?? ''} />
</div>
{/if}
</div>
+1 -1
View File
@@ -1,3 +1,3 @@
<div class=" self-center font-normal line-clamp-1 flex gap-1 items-center">
<div class=" self-center text-sm font-normal line-clamp-1 flex gap-1 items-center">
<slot />
</div>
@@ -655,10 +655,10 @@
dir={$settings.chatDirection}
style="scroll-margin-top: 3rem;"
>
<div class={`shrink-0 ltr:mr-3 rtl:ml-3 hidden @lg:flex mt-1 `}>
<div class={`shrink-0 ltr:mr-2 rtl:ml-2 hidden @lg:flex mt-0.5 `}>
<ProfileImage
src={`${WEBUI_API_BASE_URL}/models/model/profile/image?id=${model?.id}&lang=${$i18n.language}`}
className={'size-8 assistant-message-profile-image'}
className={'size-7 assistant-message-profile-image'}
/>
</div>
@@ -672,7 +672,7 @@
</Name>
<div>
<div class="chat-{message.role} w-full min-w-full markdown-prose">
<div class="chat-{message.role} w-full min-w-full">
<div>
{#if model?.info?.meta?.capabilities?.status_updates ?? true}
<StatusHistory statusHistory={message?.statusHistory} />
@@ -38,24 +38,26 @@
{#each displayItems as displayItem (displayItem.id)}
{#if displayItem.type === 'message'}
{#if renderMarkdown}
<Markdown
id={`${id}-${displayItem.id}`}
content={formatMessageContent(displayItem.text)}
{model}
{save}
{preview}
{done}
{editCodeBlock}
{topPadding}
{sourceIds}
{onSourceClick}
{onTaskClick}
{onSave}
{onUpdate}
{onPreview}
/>
<div class="markdown-prose">
<Markdown
id={`${id}-${displayItem.id}`}
content={formatMessageContent(displayItem.text)}
{model}
{save}
{preview}
{done}
{editCodeBlock}
{topPadding}
{sourceIds}
{onSourceClick}
{onTaskClick}
{onSave}
{onUpdate}
{onPreview}
/>
</div>
{:else}
<div class="whitespace-pre-wrap">{displayItem.text}</div>
<div class="whitespace-pre-wrap text-sm">{displayItem.text}</div>
{/if}
{:else if displayItem.type === 'detail_group'}
<ConsecutiveDetailsGroup
@@ -63,7 +65,7 @@
tokens={displayItem.tokens}
messageDone={done}
>
<div slot="content" class="space-y-1">
<div slot="content" class="space-y-2">
{#each displayItem.tokens as detailToken, detailIndex}
{#if detailToken.attributes?.type === 'tool_calls'}
<ToolCallDisplay
@@ -72,7 +74,7 @@
resultContent={detailToken.text}
grouped={true}
open={$settings?.expandDetails ?? false}
className="w-full space-y-1"
className="w-full space-y-2"
/>
{:else if detailToken.text?.length > 0}
<Collapsible
@@ -80,15 +82,17 @@
open={$settings?.expandDetails ?? false}
attributes={getDetailAttributes(detailToken)}
messageDone={done}
className="w-full space-y-1"
className="w-full space-y-2"
>
<div class="mb-1.5" slot="content">
<Markdown
id={`${id}-${displayItem.id}-${detailIndex}-detail`}
content={detailToken.text}
{done}
{editCodeBlock}
/>
<div class="markdown-prose">
<Markdown
id={`${id}-${displayItem.id}-${detailIndex}-detail`}
content={detailToken.text}
{done}
{editCodeBlock}
/>
</div>
</div>
</Collapsible>
{:else}
@@ -98,7 +102,7 @@
disabled={true}
attributes={getDetailAttributes(detailToken)}
messageDone={done}
className="w-full space-y-1"
className="w-full space-y-2"
/>
{/if}
{/each}
@@ -112,7 +116,7 @@
attributes={detailToken.attributes}
resultContent={detailToken.text}
open={$settings?.expandDetails ?? false}
className="w-full space-y-1"
className="w-full space-y-2"
/>
{:else if detailToken.text?.length > 0}
<Collapsible
@@ -120,15 +124,17 @@
open={$settings?.expandDetails ?? false}
attributes={getDetailAttributes(detailToken)}
messageDone={done}
className="w-full space-y-1"
className="w-full space-y-2"
>
<div class="mb-1.5" slot="content">
<Markdown
id={`${id}-${displayItem.id}-detail`}
content={detailToken.text}
{done}
{editCodeBlock}
/>
<div class="markdown-prose">
<Markdown
id={`${id}-${displayItem.id}-detail`}
content={detailToken.text}
{done}
{editCodeBlock}
/>
</div>
</div>
</Collapsible>
{:else}
@@ -138,7 +144,7 @@
disabled={true}
attributes={getDetailAttributes(detailToken)}
messageDone={done}
className="w-full space-y-1"
className="w-full space-y-2"
/>
{/if}
{/if}
@@ -144,12 +144,12 @@
style="scroll-margin-top: 3rem;"
>
{#if !($settings?.chatBubble ?? true) && !subagentResult}
<div class={`shrink-0 ltr:mr-3 rtl:ml-3 mt-1`}>
<div class={`shrink-0 ltr:mr-2 rtl:ml-2 mt-0.5`}>
<ProfileImage
src={user?.id
? `${WEBUI_API_BASE_URL}/users/${user.id}/profile/image`
: `${WEBUI_BASE_URL}/static/favicon.png`}
className={'size-8 user-message-profile-image'}
className={'size-7 user-message-profile-image'}
/>
</div>
{/if}
@@ -169,7 +169,7 @@
</div>
{/if}
<div class="chat-{message.role} w-full min-w-full markdown-prose">
<div class="chat-{message.role} w-full min-w-full">
{#if edit !== true}
{#if message.files}
<div
@@ -271,7 +271,7 @@
<textarea
id="message-edit-{message.id}"
bind:this={messageEditTextAreaElement}
class=" bg-transparent outline-hidden w-full resize-none"
class=" bg-transparent outline-hidden w-full resize-none text-sm"
bind:value={editedContent}
on:input={(e) => {
const messagesContainer = document.getElementById('messages-container');
@@ -349,14 +349,16 @@
>
{#if message.content}
{#if $settings?.renderMarkdownInUserMessages ?? true}
<Markdown
id={`${chatId}-${message.id}`}
content={message.content}
{editCodeBlock}
{topPadding}
/>
<div class="markdown-prose">
<Markdown
id={`${chatId}-${message.id}`}
content={message.content}
{editCodeBlock}
{topPadding}
/>
</div>
{:else}
<div class="whitespace-pre-wrap" dir={$settings?.chatDirection ?? 'auto'}>
<div class="whitespace-pre-wrap text-sm" dir={$settings?.chatDirection ?? 'auto'}>
{message.content}
</div>
{/if}