{#key message.id}
{model?.name ?? message.model} {#if message.timestamp}
{dayjs(message.timestamp * 1000).format($i18n.t('h:mm a'))}
{/if}
{#if message?.files && 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('confirm-edit-message-button')?.click(); } }} />
{ saveAsCopyHandler(); }} > {$i18n.t('Save As Copy')}
{ cancelEditMessage(); }} > {$i18n.t('Cancel')}
{ editMessageConfirmHandler(); }} > {$i18n.t('Save')}
{:else}
{#if message.content === '' && !message.error}
{:else if message.content && message.error !== true}
{ const { raw, oldContent, newContent } = e.detail; history.messages[message.id].content = history.messages[ message.id ].content.replace(raw, raw.replace(oldContent, newContent)); dispatch('update'); }} on:select={(e) => { const { type, content } = e.detail; if (type === 'explain') { dispatch('submit', { parentId: message.id, prompt: `Explain this section to me in more detail\n\n\`\`\`\n${content}\n\`\`\`` }); } else if (type === 'ask') { const input = e.detail?.input ?? ''; dispatch('submit', { parentId: message.id, prompt: `\`\`\`\n${content}\n\`\`\`\n${input}` }); } }} /> {/if} {#if message.error}
{/if} {#if message.citations}
{/if} {#if message.code_executions}
{/if}
{/if}
{#if !edit} {#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} {#if $user.role === 'user' ? ($config?.permissions?.chat?.editing ?? true) : true}
{ editMessageHandler(); }} >
{/if} {/if}
{ copyToClipboard(message.content); }} >
{ if (!loadingSpeech) { toggleSpeakMessage(); } }} > {#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}
${sanitizeResponseContent( JSON.stringify(message.info.usage, null, 2) .replace(/"([^(")"]+)":/g, '$1:') .slice(1, -1) .split('\n') .map((line) => line.slice(2)) .map((line) => (line.endsWith(',') ? line.slice(0, -1) : line)) .join('\n') )}` : `prompt_tokens: ${message.info.prompt_tokens ?? 'N/A'}
completion_tokens: ${message.info.completion_tokens ?? 'N/A'}
total_tokens: ${message.info.total_tokens ?? 'N/A'}` : `response_token/s: ${ `${ Math.round( ((message.info.eval_count ?? 0) / ((message.info.eval_duration ?? 0) / 1000000000)) * 100 ) / 100 } tokens` ?? 'N/A' }
prompt_token/s: ${ Math.round( ((message.info.prompt_eval_count ?? 0) / ((message.info.prompt_eval_duration ?? 0) / 1000000000)) * 100 ) / 100 ?? 'N/A' } tokens
total_duration: ${ Math.round(((message.info.total_duration ?? 0) / 1000000) * 100) / 100 ?? 'N/A' }ms
load_duration: ${ Math.round(((message.info.load_duration ?? 0) / 1000000) * 100) / 100 ?? 'N/A' }ms
prompt_eval_count: ${message.info.prompt_eval_count ?? 'N/A'}
prompt_eval_duration: ${ Math.round(((message.info.prompt_eval_duration ?? 0) / 1000000) * 100) / 100 ?? 'N/A' }ms
eval_count: ${message.info.eval_count ?? 'N/A'}
eval_duration: ${ Math.round(((message.info.eval_duration ?? 0) / 1000000) * 100) / 100 ?? 'N/A' }ms
approximate_total: ${approximateToHumanReadable(message.info.total_duration ?? 0)}`} placement="top" >
{ console.log(message); }} id="info-{message.id}" >
{/if} {#if !readOnly} {#if $config?.features.enable_message_rating ?? true}
{ await feedbackHandler(1); (model?.actions ?? []) .filter((action) => action?.__webui__ ?? false) .forEach((action) => { dispatch('action', { id: action.id, event: { id: 'good-response', data: { messageId: message.id } } }); }); window.setTimeout(() => { document .getElementById(`message-feedback-${message.id}`) ?.scrollIntoView(); }, 0); }} >
{ await feedbackHandler(-1); (model?.actions ?? []) .filter((action) => action?.__webui__ ?? false) .forEach((action) => { dispatch('action', { id: action.id, event: { id: 'bad-response', data: { messageId: message.id } } }); }); window.setTimeout(() => { document .getElementById(`message-feedback-${message.id}`) ?.scrollIntoView(); }, 0); }} >
{/if} {#if isLastMessage}
{ continueResponse(); (model?.actions ?? []) .filter((action) => action?.__webui__ ?? false) .forEach((action) => { dispatch('action', { id: action.id, event: { id: 'continue-response', data: { messageId: message.id } } }); }); }} >
{ showRateComment = false; regenerateResponse(message); (model?.actions ?? []) .filter((action) => action?.__webui__ ?? false) .forEach((action) => { dispatch('action', { id: action.id, event: { id: 'regenerate-response', data: { messageId: message.id } } }); }); }} >
{#each (model?.actions ?? []).filter((action) => !(action?.__webui__ ?? false)) as action}
{ dispatch('action', action.id); }} > {#if action.icon_url}
{:else}
{/if}
{/each} {/if} {/if} {/if}
{/if} {#if message.done && showRateComment}
{ await feedbackHandler(null, { tags: e.detail.tags, comment: e.detail.comment, reason: e.detail.reason }); (model?.actions ?? []) .filter((action) => action?.__webui__ ?? false) .forEach((action) => { dispatch('action', { id: action.id, event: { id: 'rate-comment', data: { messageId: message.id, comment: e.detail.comment, reason: e.detail.reason } } }); }); }} /> {/if} {/if}
{/key}