93 lines
3.0 KiB
Vue
93 lines
3.0 KiB
Vue
<script setup lang="ts">
|
|
import type { ModelWithProvider, ProviderWithModels } from '~/composables/useModels';
|
|
|
|
const route = useRoute();
|
|
const pendingMessage = ref<Message | null>(null);
|
|
|
|
const { createTopic, sendMessage, autoRename } = useChat(route.params.id as string);
|
|
const { getAgent, unsubscribe: unsubscribeAgents } = await useAgents();
|
|
const { providers, unsubscribe: unsubscribeModels } = await useModels();
|
|
|
|
const agent = computed(() => {
|
|
if (route.params.id === null || typeof route.params.id !== 'string') {
|
|
throw new Error('Invalid agent ID');
|
|
}
|
|
|
|
return getAgent(route.params.id)!;
|
|
});
|
|
|
|
if (!agent.value) navigateTo('/');
|
|
|
|
const handleSubmit = async (message: string, model: ModelWithProvider | null) => {
|
|
if (!model) {
|
|
console.error('No model selected');
|
|
return;
|
|
}
|
|
|
|
const user = useAuth().user;
|
|
if (!user) {
|
|
console.error('No user');
|
|
return;
|
|
}
|
|
|
|
pendingMessage.value = {
|
|
id: '',
|
|
userId: user.value!.id,
|
|
topicId: null,
|
|
content: message,
|
|
role: 'user',
|
|
parts: [],
|
|
generation: null,
|
|
parentMessageId: null,
|
|
children: [],
|
|
generationId: null,
|
|
focusedIndex: null,
|
|
deleted: false,
|
|
createdAt: new Date(),
|
|
}
|
|
|
|
const topic = await createTopic();
|
|
if (!topic) throw new Error('Failed to create topic');
|
|
|
|
autoRename(topic.id, message);
|
|
|
|
await navigateTo(`/agent/${route.params.id}/topic/${topic.id}`);
|
|
|
|
return sendMessage(message, topic, [], agent.value!, model.provider, model);
|
|
};
|
|
|
|
onUnmounted(() => {
|
|
unsubscribeAgents?.();
|
|
unsubscribeModels?.();
|
|
});
|
|
</script>
|
|
|
|
|
|
<template>
|
|
<div class="h-full w-full">
|
|
<!-- chat pane -->
|
|
<div class="flex flex-col w-full px-4 overflow-y-auto h-full"
|
|
style="scrollbar-width: thin; scrollbar-color: #888 transparent;" ref="chatPane">
|
|
<div class="flex-grow w-full flex justify-center">
|
|
<div class="flex h-full max-w-4xl w-full flex-col gap-2"
|
|
:class="pendingMessage === null ? 'justify-end' : ''">
|
|
<div v-if="pendingMessage === null">
|
|
<h1 v-if="agent" class="font-bold">{{ agent.name }}</h1>
|
|
<p class="mb-28 text-[var(--color-muted)]">Select a topic to continue or create a new one</p>
|
|
</div>
|
|
<div class="opacity-70" v-else>
|
|
<Message :message="pendingMessage" />
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="sticky max-h-full z-10 bottom-0 w-full flex justify-center">
|
|
<div class="pb-4 w-full max-w-4xl bg-[var(--color-neutral)] rounded-t-2xl">
|
|
<ChatInput class="[view-transition-name:chat-prompt] duration-150 ease-in-out" :agent="agent"
|
|
:providers="providers.filter(p => p.enabled)" @submit="handleSubmit"></ChatInput>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</template>
|