blob: c8b3f6e4aa47f8da8da3d03d71a4f14cd0d1da9e (
plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
|
<script lang="ts">
import type { ChatMessage } from "../types.js";
import MarkdownRenderer from "./MarkdownRenderer.svelte";
import ToolCallDisplay from "./ToolCallDisplay.svelte";
const { message }: { message: ChatMessage } = $props();
const isUser = $derived(message.role === "user");
const isSystem = $derived(message.role === "system");
</script>
{#if isSystem}
<div class="flex justify-center my-2">
<div class="badge badge-ghost gap-1 text-xs opacity-60">
{#each message.content as segment}
{#if segment.type === "text"}
{segment.text}
{/if}
{/each}
</div>
</div>
{:else}
<div class="chat chat-start mb-2">
<div class="chat-bubble max-w-[80%] break-words {isUser ? 'chat-bubble-primary' : 'bg-transparent'}">
{#if message.thinking}
<div class="collapse collapse-arrow mb-2 p-1">
<input type="checkbox" />
<div class="collapse-title text-sm opacity-60 italic py-0 pl-0 pr-8 min-h-0">Thinking...</div>
<div class="collapse-content text-sm opacity-60 italic p-0">
<p class="whitespace-pre-wrap mt-1">{message.thinking}</p>
</div>
</div>
{/if}
{#each message.content as segment, i (segment.type === "tool-call" ? segment.id : i)}
{#if segment.type === "text"}
<MarkdownRenderer text={segment.text} streaming={message.isStreaming} />
{:else if segment.type === "tool-call"}
<ToolCallDisplay toolCall={segment} />
{/if}
{/each}
{#if message.isStreaming}
<span class="inline-block w-2 h-4 bg-current animate-pulse ml-0.5 align-middle">▌</span>
{/if}
</div>
</div>
{/if}
|