refac/enh: status history
This commit is contained in:
@@ -52,6 +52,7 @@
|
||||
import { fade } from 'svelte/transition';
|
||||
import { flyAndScale } from '$lib/utils/transitions';
|
||||
import RegenerateMenu from './ResponseMessage/RegenerateMenu.svelte';
|
||||
import StatusHistory from './ResponseMessage/StatusHistory.svelte';
|
||||
|
||||
interface MessageType {
|
||||
id: string;
|
||||
@@ -642,77 +643,7 @@
|
||||
<div>
|
||||
<div class="chat-{message.role} w-full min-w-full markdown-prose">
|
||||
<div>
|
||||
{#if (message?.statusHistory ?? [...(message?.status ? [message?.status] : [])]).length > 0}
|
||||
{@const status = (
|
||||
message?.statusHistory ?? [...(message?.status ? [message?.status] : [])]
|
||||
).at(-1)}
|
||||
{#if !status?.hidden}
|
||||
<div class="status-description flex items-center gap-2 py-0.5">
|
||||
{#if status?.action === 'web_search' && status?.urls}
|
||||
<WebSearchResults {status}>
|
||||
<div class="flex flex-col justify-center -space-y-0.5">
|
||||
<div
|
||||
class="{status?.done === false
|
||||
? 'shimmer'
|
||||
: ''} text-base line-clamp-1 text-wrap"
|
||||
>
|
||||
<!-- $i18n.t("Generating search query") -->
|
||||
<!-- $i18n.t("No search query generated") -->
|
||||
|
||||
<!-- $i18n.t('Searched {{count}} sites') -->
|
||||
{#if status?.description.includes('{{count}}')}
|
||||
{$i18n.t(status?.description, {
|
||||
count: status?.urls.length
|
||||
})}
|
||||
{:else if status?.description === 'No search query generated'}
|
||||
{$i18n.t('No search query generated')}
|
||||
{:else if status?.description === 'Generating search query'}
|
||||
{$i18n.t('Generating search query')}
|
||||
{:else}
|
||||
{status?.description}
|
||||
{/if}
|
||||
</div>
|
||||
</div>
|
||||
</WebSearchResults>
|
||||
{:else if status?.action === 'knowledge_search'}
|
||||
<div class="flex flex-col justify-center -space-y-0.5">
|
||||
<div
|
||||
class="{status?.done === false
|
||||
? 'shimmer'
|
||||
: ''} text-gray-500 dark:text-gray-500 text-base line-clamp-1 text-wrap"
|
||||
>
|
||||
{$i18n.t(`Searching Knowledge for "{{searchQuery}}"`, {
|
||||
searchQuery: status.query
|
||||
})}
|
||||
</div>
|
||||
</div>
|
||||
{:else}
|
||||
<div class="flex flex-col justify-center -space-y-0.5">
|
||||
<div
|
||||
class="{status?.done === false
|
||||
? 'shimmer'
|
||||
: ''} text-gray-500 dark:text-gray-500 text-base line-clamp-1 text-wrap"
|
||||
>
|
||||
<!-- $i18n.t(`Searching "{{searchQuery}}"`) -->
|
||||
{#if status?.description.includes('{{searchQuery}}')}
|
||||
{$i18n.t(status?.description, {
|
||||
searchQuery: status?.query
|
||||
})}
|
||||
{:else if status?.description === 'No search query generated'}
|
||||
{$i18n.t('No search query generated')}
|
||||
{:else if status?.description === 'Generating search query'}
|
||||
{$i18n.t('Generating search query')}
|
||||
{:else if status?.description === 'Searching the web'}
|
||||
{$i18n.t('Searching the web...')}
|
||||
{:else}
|
||||
{status?.description}
|
||||
{/if}
|
||||
</div>
|
||||
</div>
|
||||
{/if}
|
||||
</div>
|
||||
{/if}
|
||||
{/if}
|
||||
<StatusHistory statusHistory={message?.statusHistory} />
|
||||
|
||||
{#if message?.files && message.files?.filter((f) => f.type === 'image').length > 0}
|
||||
<div class="my-1 w-full flex overflow-x-auto gap-2 flex-wrap">
|
||||
|
||||
@@ -0,0 +1,74 @@
|
||||
<script>
|
||||
import { getContext } from 'svelte';
|
||||
const i18n = getContext('i18n');
|
||||
|
||||
import Collapsible from '$lib/components/common/Collapsible.svelte';
|
||||
import StatusItem from './StatusHistory/StatusItem.svelte';
|
||||
export let statusHistory = [];
|
||||
|
||||
let showHistory = false;
|
||||
</script>
|
||||
|
||||
<!-- <Collapsible open={false} growDirection="up" className="w-full space-y-1" buttonClassName="w-full">
|
||||
<div
|
||||
class="flex items-center gap-2 text-gray-500 hover:text-gray-700 dark:hover:text-gray-300 transition w-full"
|
||||
>
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
</Collapsible> -->
|
||||
|
||||
{#if statusHistory}
|
||||
<div class="text-sm flex flex-col w-full">
|
||||
{#if showHistory}
|
||||
<div class="flex flex-row">
|
||||
{#if statusHistory.length > 1}
|
||||
<div class="w-1 border-r border-gray-50 dark:border-gray-800 mt-3 -mb-2.5" />
|
||||
|
||||
<div class="w-full -translate-x-[7.5px]">
|
||||
{#each statusHistory as status, idx}
|
||||
{#if idx !== statusHistory.length - 1}
|
||||
<div class="flex items-start gap-2 mb-1">
|
||||
<div class="pt-3 px-1">
|
||||
<span class="relative flex size-2">
|
||||
<span
|
||||
class="relative inline-flex size-1.5 rounded-full bg-gray-200 dark:bg-gray-700"
|
||||
></span>
|
||||
</span>
|
||||
</div>
|
||||
<StatusItem {status} done={true} />
|
||||
</div>
|
||||
{/if}
|
||||
{/each}
|
||||
</div>
|
||||
{/if}
|
||||
</div>
|
||||
{/if}
|
||||
|
||||
{#if statusHistory.length > 0}
|
||||
{@const status = statusHistory.at(-1)}
|
||||
<button
|
||||
class="w-full -translate-x-[3.5px]"
|
||||
on:click={() => {
|
||||
showHistory = !showHistory;
|
||||
}}
|
||||
>
|
||||
<div class="flex items-start gap-2 mb-1">
|
||||
<div class="pt-3 px-1">
|
||||
<span class="relative flex size-2">
|
||||
{#if status?.done === false}
|
||||
<span
|
||||
class="absolute inline-flex h-full w-full animate-ping rounded-full bg-gray-400 dark:bg-gray-700 opacity-75"
|
||||
></span>
|
||||
{/if}
|
||||
<span class="relative inline-flex size-1.5 rounded-full bg-gray-200 dark:bg-gray-700"
|
||||
></span>
|
||||
</span>
|
||||
</div>
|
||||
<StatusItem {status} />
|
||||
</div>
|
||||
</button>
|
||||
{/if}
|
||||
</div>
|
||||
{/if}
|
||||
@@ -0,0 +1,101 @@
|
||||
<script>
|
||||
import { getContext } from 'svelte';
|
||||
const i18n = getContext('i18n');
|
||||
import WebSearchResults from '../WebSearchResults.svelte';
|
||||
import Search from '$lib/components/icons/Search.svelte';
|
||||
|
||||
export let status = null;
|
||||
export let done = false;
|
||||
</script>
|
||||
|
||||
{#if !status?.hidden}
|
||||
<div class="status-description flex items-center gap-2 py-0.5 w-full text-left">
|
||||
{#if status?.action === 'web_search' && (status?.urls || status?.items)}
|
||||
<WebSearchResults {status}>
|
||||
<div class="flex flex-col justify-center -space-y-0.5">
|
||||
<div
|
||||
class="{(done || status?.done) === false
|
||||
? 'shimmer'
|
||||
: ''} text-base line-clamp-1 text-wrap"
|
||||
>
|
||||
<!-- $i18n.t("Generating search query") -->
|
||||
<!-- $i18n.t("No search query generated") -->
|
||||
<!-- $i18n.t('Searched {{count}} sites') -->
|
||||
{#if status?.description.includes('{{count}}')}
|
||||
{$i18n.t(status?.description, {
|
||||
count: (status?.urls || status?.items).length
|
||||
})}
|
||||
{:else if status?.description === 'No search query generated'}
|
||||
{$i18n.t('No search query generated')}
|
||||
{:else if status?.description === 'Generating search query'}
|
||||
{$i18n.t('Generating search query')}
|
||||
{:else}
|
||||
{status?.description}
|
||||
{/if}
|
||||
</div>
|
||||
</div>
|
||||
</WebSearchResults>
|
||||
{:else if status?.action === 'knowledge_search'}
|
||||
<div class="flex flex-col justify-center -space-y-0.5">
|
||||
<div
|
||||
class="{(done || status?.done) === false
|
||||
? 'shimmer'
|
||||
: ''} text-gray-500 dark:text-gray-500 text-base line-clamp-1 text-wrap"
|
||||
>
|
||||
{$i18n.t(`Searching Knowledge for "{{searchQuery}}"`, {
|
||||
searchQuery: status.query
|
||||
})}
|
||||
</div>
|
||||
</div>
|
||||
{:else if status?.action === 'web_search_queries_generated' && status?.queries}
|
||||
<div class="flex flex-col justify-center -space-y-0.5">
|
||||
<div
|
||||
class="{(done || status?.done) === false
|
||||
? 'shimmer'
|
||||
: ''} text-gray-500 dark:text-gray-500 text-base line-clamp-1 text-wrap"
|
||||
>
|
||||
{$i18n.t(`Searching`)}
|
||||
</div>
|
||||
|
||||
<div class=" flex gap-1 flex-wrap mt-2">
|
||||
{#each status.queries as query, idx (query)}
|
||||
<div
|
||||
class="bg-gray-50 dark:bg-gray-850 flex rounded-lg py-1 px-2 items-center gap-1 text-xs"
|
||||
>
|
||||
<div>
|
||||
<Search className="size-3" />
|
||||
</div>
|
||||
|
||||
<span class=" ">
|
||||
{query}
|
||||
</span>
|
||||
</div>
|
||||
{/each}
|
||||
</div>
|
||||
</div>
|
||||
{:else}
|
||||
<div class="flex flex-col justify-center -space-y-0.5">
|
||||
<div
|
||||
class="{(done || status?.done) === false
|
||||
? 'shimmer'
|
||||
: ''} text-gray-500 dark:text-gray-500 text-base line-clamp-1 text-wrap"
|
||||
>
|
||||
<!-- $i18n.t(`Searching "{{searchQuery}}"`) -->
|
||||
{#if status?.description.includes('{{searchQuery}}')}
|
||||
{$i18n.t(status?.description, {
|
||||
searchQuery: status?.query
|
||||
})}
|
||||
{:else if status?.description === 'No search query generated'}
|
||||
{$i18n.t('No search query generated')}
|
||||
{:else if status?.description === 'Generating search query'}
|
||||
{$i18n.t('Generating search query')}
|
||||
{:else if status?.description === 'Searching the web'}
|
||||
{$i18n.t('Searching the web')}
|
||||
{:else}
|
||||
{status?.description}
|
||||
{/if}
|
||||
</div>
|
||||
</div>
|
||||
{/if}
|
||||
</div>
|
||||
{/if}
|
||||
@@ -8,20 +8,13 @@
|
||||
let state = false;
|
||||
</script>
|
||||
|
||||
<Collapsible bind:open={state} className="w-full space-y-1">
|
||||
<div
|
||||
class="flex items-center gap-2 text-gray-500 hover:text-gray-700 dark:hover:text-gray-300 transition"
|
||||
>
|
||||
<Collapsible grow={true} className="w-full" buttonClassName="w-full">
|
||||
<div class="flex items-center gap-2 text-gray-500 transition">
|
||||
<slot />
|
||||
|
||||
{#if state}
|
||||
<ChevronUp strokeWidth="3.5" className="size-3.5 " />
|
||||
{:else}
|
||||
<ChevronDown strokeWidth="3.5" className="size-3.5 " />
|
||||
{/if}
|
||||
</div>
|
||||
|
||||
<div
|
||||
class="text-sm border border-gray-50 dark:border-gray-850 rounded-xl mb-1.5 p-2"
|
||||
class="text-sm border border-gray-50 dark:border-gray-850 rounded-xl my-1.5 p-2 w-full"
|
||||
slot="content"
|
||||
>
|
||||
{#if status?.query}
|
||||
|
||||
Reference in New Issue
Block a user