mirror of
https://github.com/open-webui/open-webui.git
synced 2026-10-29 06:32:52 +00:00
refac
This commit is contained in:
parent
06c382e5d2
commit
f465a4be11
7 changed files with 88 additions and 7 deletions
|
|
@ -0,0 +1,34 @@
|
|||
<script lang="ts">
|
||||
import { getContext } from 'svelte';
|
||||
|
||||
const i18n = getContext<typeof import('$lib/i18n').default>('i18n');
|
||||
|
||||
export let summary = '';
|
||||
</script>
|
||||
|
||||
{#if summary.trim()}
|
||||
<!-- Only stop the response card's click handler; summary provides keyboard interaction. -->
|
||||
<!-- svelte-ignore a11y_click_events_have_key_events a11y_no_noninteractive_element_interactions -->
|
||||
<details class="my-1" on:click|stopPropagation>
|
||||
<summary
|
||||
class="flex w-full cursor-pointer items-center gap-2 text-xs leading-5 text-gray-500 outline-offset-4 transition-colors before:flex-1 before:border-t before:border-dashed before:border-current before:opacity-25 after:flex-1 after:border-t after:border-dashed after:border-current after:opacity-25 hover:text-gray-700 focus-visible:outline-2 focus-visible:outline-gray-400 dark:text-gray-400 dark:hover:text-gray-200 [&::-webkit-details-marker]:hidden"
|
||||
>
|
||||
<span class="min-w-0 px-2 text-center">
|
||||
{$i18n.t('Context compacted')}
|
||||
</span>
|
||||
</summary>
|
||||
<div
|
||||
role="region"
|
||||
aria-label={$i18n.t('Compaction summary')}
|
||||
class="my-1.5 max-h-80 overflow-y-auto whitespace-pre-wrap break-words text-xs leading-5 text-gray-600 dark:text-gray-300"
|
||||
>
|
||||
{summary}
|
||||
</div>
|
||||
</details>
|
||||
{:else}
|
||||
<div
|
||||
class="my-1 flex w-full items-center gap-2 text-xs leading-5 text-gray-500 before:flex-1 before:border-t before:border-dashed before:border-current before:opacity-25 after:flex-1 after:border-t after:border-dashed after:border-current after:opacity-25 dark:text-gray-400"
|
||||
>
|
||||
<span class="min-w-0 px-2 text-center">{$i18n.t('Context compacted')}</span>
|
||||
</div>
|
||||
{/if}
|
||||
|
|
@ -61,6 +61,7 @@
|
|||
import Citations from './Citations.svelte';
|
||||
import CodeExecutions from './CodeExecutions.svelte';
|
||||
import ContentRenderer from './ContentRenderer.svelte';
|
||||
import ContextCompactionLabel from './ContextCompactionLabel.svelte';
|
||||
import { KokoroWorker } from '$lib/workers/KokoroWorker';
|
||||
import FileItem from '$lib/components/common/FileItem.svelte';
|
||||
import FollowUps from './ResponseMessage/FollowUps.svelte';
|
||||
|
|
@ -78,6 +79,7 @@
|
|||
model: string;
|
||||
content: string;
|
||||
output?: OutputItem[];
|
||||
contextSummary?: string;
|
||||
files?: { type: string; url: string }[];
|
||||
timestamp: number;
|
||||
role: string;
|
||||
|
|
@ -712,6 +714,10 @@
|
|||
</Name>
|
||||
{/if}
|
||||
|
||||
{#if message.contextSummary}
|
||||
<ContextCompactionLabel summary={message.contextSummary} />
|
||||
{/if}
|
||||
|
||||
<div>
|
||||
<div class="chat-{message.role} w-full min-w-full">
|
||||
<div>
|
||||
|
|
|
|||
|
|
@ -8,6 +8,7 @@
|
|||
|
||||
import Markdown from './Markdown.svelte';
|
||||
import ConsecutiveDetailsGroup from './Markdown/ConsecutiveDetailsGroup.svelte';
|
||||
import ContextCompactionLabel from './ContextCompactionLabel.svelte';
|
||||
import {
|
||||
buildOutputDisplayItems,
|
||||
type OutputDetailToken,
|
||||
|
|
@ -170,6 +171,8 @@
|
|||
{#if displayItem.item?.displayed || $settings?.terminalFileDisplay === 'inline'}
|
||||
<TerminalOutputFile item={displayItem.item} {chatId} />
|
||||
{/if}
|
||||
{:else if displayItem.type === 'context_compaction'}
|
||||
<ContextCompactionLabel summary={displayItem.summary} />
|
||||
{:else}
|
||||
{@const detailToken = displayItem.token}
|
||||
{#if detailToken.attributes?.type === 'tool_calls'}
|
||||
|
|
|
|||
|
|
@ -18,6 +18,7 @@
|
|||
import equal from 'fast-deep-equal';
|
||||
|
||||
import Name from './Name.svelte';
|
||||
import ContextCompactionLabel from './ContextCompactionLabel.svelte';
|
||||
import ProfileImage from './ProfileImage.svelte';
|
||||
import ProfilePreview from '$lib/components/channel/Messages/Message/ProfilePreview.svelte';
|
||||
import Tooltip from '$lib/components/common/Tooltip.svelte';
|
||||
|
|
@ -195,6 +196,10 @@
|
|||
</div>
|
||||
{/if}
|
||||
|
||||
{#if message.contextSummary}
|
||||
<ContextCompactionLabel summary={message.contextSummary} />
|
||||
{/if}
|
||||
|
||||
<div class="chat-{message.role} w-full min-w-full">
|
||||
{#if edit !== true}
|
||||
{#if message.files}
|
||||
|
|
|
|||
|
|
@ -14,7 +14,7 @@ export type OutputItem = {
|
|||
status?: string;
|
||||
arguments?: unknown;
|
||||
content?: OutputContentPart[];
|
||||
summary?: OutputContentPart[];
|
||||
summary?: OutputContentPart[] | string;
|
||||
output?: OutputContentPart[];
|
||||
files?: unknown;
|
||||
embeds?: unknown;
|
||||
|
|
@ -64,6 +64,11 @@ export type OutputDisplayItem =
|
|||
type: 'file';
|
||||
id: string;
|
||||
item: Record<string, unknown>;
|
||||
}
|
||||
| {
|
||||
type: 'context_compaction';
|
||||
id: string;
|
||||
summary: string;
|
||||
};
|
||||
|
||||
type ResponseStreamEvent = {
|
||||
|
|
@ -409,6 +414,16 @@ export function buildOutputDisplayItems(output: OutputItem[] = []): OutputDispla
|
|||
return;
|
||||
}
|
||||
|
||||
if (item.type === 'open_webui:context_compaction') {
|
||||
flushDetails();
|
||||
displayItems.push({
|
||||
type: 'context_compaction',
|
||||
id: item.id ?? `context-compaction-${index}`,
|
||||
summary: typeof item.summary === 'string' ? item.summary : ''
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
if (item.type === 'message') {
|
||||
const text = getMessageText(item);
|
||||
if (text.trim()) {
|
||||
|
|
@ -618,7 +633,7 @@ export function applyResponseStreamEvent(
|
|||
if (!event.part) {
|
||||
return nextOutput;
|
||||
}
|
||||
item.summary = [...(item.summary ?? [])];
|
||||
item.summary = Array.isArray(item.summary) ? [...item.summary] : [];
|
||||
const summaryIndex = event.summary_index ?? item.summary.length;
|
||||
setPart(item.summary, summaryIndex, { ...event.part }, { type: 'summary_text', text: '' });
|
||||
return nextOutput;
|
||||
|
|
@ -633,7 +648,7 @@ export function applyResponseStreamEvent(
|
|||
|
||||
if (deltaType === 'reasoning_summary_text') {
|
||||
const summaryIndex = event.summary_index ?? 0;
|
||||
item.summary = [...(item.summary ?? [])];
|
||||
item.summary = Array.isArray(item.summary) ? [...item.summary] : [];
|
||||
const part = ensurePart(item.summary, summaryIndex, { type: 'summary_text', text: '' });
|
||||
part.text = appendDelta(part.text ?? '', event.delta);
|
||||
return nextOutput;
|
||||
|
|
|
|||
|
|
@ -18,6 +18,10 @@
|
|||
getOutputText(nodeData?.message?.output) || nodeData?.message?.content || '';
|
||||
|
||||
$: messageContent = getMessageContent(data);
|
||||
$: isCompacted =
|
||||
data?.message?.contextSummary ||
|
||||
data?.message?.output?.some((item) => item?.type === 'open_webui:context_compaction');
|
||||
$: previewClass = `text-xs mt-0.5 ${isCompacted ? 'line-clamp-1' : 'line-clamp-2'}`;
|
||||
$: modelName = data?.model
|
||||
? resolveLocalizedModelName(data.model, $i18n.language)
|
||||
: (data?.message?.model ?? 'Assistant');
|
||||
|
|
@ -45,9 +49,13 @@
|
|||
</div>
|
||||
|
||||
{#if data?.message?.error}
|
||||
<div class="text-red-500 line-clamp-2 text-xs mt-0.5">{data.message.error.content}</div>
|
||||
<div class="text-red-500 {previewClass}">
|
||||
{data.message.error.content}
|
||||
</div>
|
||||
{:else}
|
||||
<div class="text-gray-500 line-clamp-2 text-xs mt-0.5">{messageContent}</div>
|
||||
<div class="text-gray-500 {previewClass}">
|
||||
{messageContent}
|
||||
</div>
|
||||
{/if}
|
||||
</div>
|
||||
</div>
|
||||
|
|
@ -83,16 +91,25 @@
|
|||
</div>
|
||||
|
||||
{#if data?.message?.error}
|
||||
<div class="text-red-500 line-clamp-2 text-xs mt-0.5">
|
||||
<div class="text-red-500 {previewClass}">
|
||||
{data.message.error.content}
|
||||
</div>
|
||||
{:else}
|
||||
<div class="text-gray-500 line-clamp-2 text-xs mt-0.5">{messageContent}</div>
|
||||
<div class="text-gray-500 {previewClass}">
|
||||
{messageContent}
|
||||
</div>
|
||||
{/if}
|
||||
</div>
|
||||
</div>
|
||||
{/if}
|
||||
</Tooltip>
|
||||
{#if isCompacted}
|
||||
<div
|
||||
class="ms-7 mt-0.5 w-fit max-w-[calc(100%-1.75rem)] truncate rounded bg-gray-100 px-1.5 text-[10px] leading-4 text-gray-500 dark:bg-gray-900 dark:text-gray-400"
|
||||
>
|
||||
{$i18n.t('Context compacted')}
|
||||
</div>
|
||||
{/if}
|
||||
<Handle
|
||||
type="target"
|
||||
position={data?.direction === 'horizontal' ? Position.Left : Position.Top}
|
||||
|
|
|
|||
|
|
@ -554,6 +554,7 @@
|
|||
"Compact: shorten older messages so this chat can keep going.": "",
|
||||
"Compacting context": "",
|
||||
"Compacting context...": "",
|
||||
"Compaction summary": "",
|
||||
"Compare": "",
|
||||
"Compare files": "",
|
||||
"Compare revision": "",
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue