{#key message.id}
{model?.name ?? message.model} {#if message.timestamp}
{dayjs(message.timestamp * 1000).format($i18n.t('h:mm a'))}
{/if}
{#if (message?.files ?? []).filter((f) => f.type === 'image').length > 0}
{#each message.files as file}
{#if file.type === 'image'}
{/if}
{/each}
{/if}
{#if (message?.statusHistory ?? [...(message?.status ? [message?.status] : [])]).length > 0} {@const status = ( message?.statusHistory ?? [...(message?.status ? [message?.status] : [])] ).at(-1)}
{#if status.done === false}
{/if} {#if status?.action === 'web_search' && status?.urls}
{status?.description}
{:else}
{status?.description}
{/if}
{/if} {#if edit === true}
{ e.target.style.height = ''; e.target.style.height = `${e.target.scrollHeight}px`; }} on:keydown={(e) => { if (e.key === 'Escape') { document.getElementById('close-edit-message-button')?.click(); } const isCmdOrCtrlPressed = e.metaKey || e.ctrlKey; const isEnterPressed = e.key === 'Enter'; if (isCmdOrCtrlPressed && isEnterPressed) { document.getElementById('save-edit-message-button')?.click(); } }} />
{ cancelEditMessage(); }} > {$i18n.t('Cancel')}
{ editMessageConfirmHandler(); }} > {$i18n.t('Save')}
{:else}
{#if message.content === '' && !message.error}
{:else if message.content && message.error !== true} {#each tokens as token, tokenIdx} {#if token.type === 'code'} {#if token.lang === 'mermaid'}
{revertSanitizedResponseContent(token.text)}
{:else}
{/if} {:else} {@html marked.parse(token.raw, { ...defaults, gfm: true, breaks: true, renderer })} {/if} {/each} {/if} {#if message.error}
{message?.error?.content ?? message.content}
{/if} {#if message.citations}
{#each message.citations.reduce((acc, citation) => { citation.document.forEach((document, index) => { const metadata = citation.metadata?.[index]; const id = metadata?.source ?? 'N/A'; let source = citation?.source; // Check if ID looks like a URL if (id.startsWith('http://') || id.startsWith('https://')) { source = { name: id }; } const existingSource = acc.find((item) => item.id === id); if (existingSource) { existingSource.document.push(document); existingSource.metadata.push(metadata); } else { acc.push( { id: id, source: source, document: [document], metadata: metadata ? [metadata] : [] } ); } }); return acc; }, []) as citation, idx}
{ showCitationModal = true; selectedCitation = citation; }} >
{idx + 1}
{citation.source.name}
{/each}
{/if} {#if message.done || siblings.length > 1}
{#if siblings.length > 1}
{ showPreviousMessage(message); }} >
{siblings.indexOf(message.id) + 1}/{siblings.length}
{ showNextMessage(message); }} >
{/if} {#if message.done} {#if !readOnly}
{ editMessageHandler(); }} >
{/if}
{ copyToClipboard(message.content); }} >
{ if (!loadingSpeech) { toggleSpeakMessage(message); } }} > {#if loadingSpeech}
{:else if speaking}
{:else}
{/if}
{#if $config?.features.enable_image_generation && !readOnly}
{ if (!generatingImage) { generateImage(message); } }} > {#if generatingImage}
{:else}
{/if}
{/if} {#if message.info}
{ console.log(message); }} id="info-{message.id}" >
{/if} {#if !readOnly}
{ rateMessage(message.id, 1); showRateComment = true; window.setTimeout(() => { document .getElementById(`message-feedback-${message.id}`) ?.scrollIntoView(); }, 0); }} >
{ rateMessage(message.id, -1); showRateComment = true; window.setTimeout(() => { document .getElementById(`message-feedback-${message.id}`) ?.scrollIntoView(); }, 0); }} >
{#if isLastMessage}
{ continueGeneration(); }} >
{ showRateComment = false; regenerateResponse(message); }} >
{#each model?.actions ?? [] as action}
{ chatActionHandler(action.id, message.model, message.id); console.log('action'); }} >
{/each} {/if} {/if} {/if}
{/if} {#if message.done && showRateComment}
{ updateChatMessages(); }} /> {/if}
{/if}
{/key}