<script setup lang="ts">
import { useChat } from '@ai-sdk/vue'
import { DefaultChatTransport } from 'ai'
import { ref } from 'vue'
import {
Conversation,
ConversationContent,
ConversationScrollButton,
} from '@/components/ai-elements/conversation'
import { Message, MessageContent } from '@/components/ai-elements/message'
import {
PromptInput,
PromptInputSubmit,
PromptInputTextarea,
} from '@/components/ai-elements/prompt-input'
import { Response } from '@/components/ai-elements/response'
import {
Source,
Sources,
SourcesContent,
SourcesTrigger,
} from '@/components/ai-elements/sources'
const input = ref('')
const { messages, sendMessage, status } = useChat({
transport: new DefaultChatTransport({
api: '/api/sources',
}),
})
function handleSubmit() {
if (input.value.trim()) {
sendMessage({ text: input.value })
input.value = ''
}
}
function getSourceParts(message: any) {
return message.parts.filter((part: any) => part.type === 'source-url')
}
function getTextParts(message: any) {
return message.parts.filter((part: any) => part.type === 'text')
}
</script>
<template>
<div
class="max-w-4xl mx-auto p-6 relative size-full rounded-lg border h-[600px]"
>
<div class="flex flex-col h-full">
<div class="flex-1 overflow-auto mb-4">
<Conversation>
<ConversationContent>
<div v-for="message in messages" :key="message.id">
<Sources v-if="message.role === 'assistant'">
<SourcesTrigger :count="getSourceParts(message).length" />
<SourcesContent>
<template
v-for="(part, i) in getSourceParts(message)"
:key="`${message.id}-${i}`"
>
<Source :href="part.url" :title="part.url" />
</template>
</SourcesContent>
</Sources>
<Message :from="message.role">
<MessageContent>
<template
v-for="(part, i) in getTextParts(message)"
:key="`${message.id}-${i}`"
>
<Response>{{ part.text }}</Response>
</template>
</MessageContent>
</Message>
</div>
</ConversationContent>
<ConversationScrollButton />
</Conversation>
</div>
<PromptInput
class="mt-4 w-full max-w-2xl mx-auto relative"
@submit.prevent="handleSubmit"
>
<PromptInputTextarea
v-model="input"
placeholder="Ask a question and search the..."
class="pr-12"
/>
<PromptInputSubmit
:status="status === 'streaming' ? 'streaming' : 'ready'"
:disabled="!input.trim()"
class="absolute bottom-1 right-1"
/>
</PromptInput>
</div>
</div>
</template>