feat(attachment): Support message attachments
This commit is contained in:
@@ -8,6 +8,7 @@ const currentModel = useCurrentModel()
|
|||||||
const openaiApiKey = useApiKey()
|
const openaiApiKey = useApiKey()
|
||||||
const fetchingResponse = ref(false)
|
const fetchingResponse = ref(false)
|
||||||
const messageQueue = []
|
const messageQueue = []
|
||||||
|
const attachment = ref(null)
|
||||||
let isProcessingQueue = false
|
let isProcessingQueue = false
|
||||||
|
|
||||||
const props = defineProps({
|
const props = defineProps({
|
||||||
@@ -72,7 +73,7 @@ const fetchReply = async (message) => {
|
|||||||
openaiApiKey: $settings.open_api_key_setting === 'True' ? openaiApiKey.value : null,
|
openaiApiKey: $settings.open_api_key_setting === 'True' ? openaiApiKey.value : null,
|
||||||
message: message,
|
message: message,
|
||||||
conversationId: props.conversation.id,
|
conversationId: props.conversation.id,
|
||||||
frugalMode: frugalMode.value
|
frugalMode: $settings.open_frugal_mode_control === 'True' && frugalMode.value
|
||||||
}, webSearchParams)
|
}, webSearchParams)
|
||||||
|
|
||||||
try {
|
try {
|
||||||
@@ -151,10 +152,20 @@ const send = (message) => {
|
|||||||
if (props.conversation.messages.length === 0) {
|
if (props.conversation.messages.length === 0) {
|
||||||
addConversation(props.conversation)
|
addConversation(props.conversation)
|
||||||
}
|
}
|
||||||
props.conversation.messages.push({message: message})
|
let newMessage = {
|
||||||
fetchReply(message)
|
id: null,
|
||||||
|
is_bot: false,
|
||||||
|
message: message
|
||||||
|
}
|
||||||
|
if (attachment.value) {
|
||||||
|
newMessage.attachments = [attachment.value]
|
||||||
|
attachment.value = null
|
||||||
|
}
|
||||||
|
props.conversation.messages.push(newMessage)
|
||||||
|
fetchReply(newMessage)
|
||||||
scrollChatWindow()
|
scrollChatWindow()
|
||||||
}
|
}
|
||||||
|
|
||||||
const stop = () => {
|
const stop = () => {
|
||||||
abortFetch()
|
abortFetch()
|
||||||
}
|
}
|
||||||
@@ -175,6 +186,10 @@ const deleteMessage = (index) => {
|
|||||||
props.conversation.messages.splice(index, 1)
|
props.conversation.messages.splice(index, 1)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const updateAttachment = (file) => {
|
||||||
|
attachment.value = file
|
||||||
|
}
|
||||||
|
|
||||||
onNuxtReady(() => {
|
onNuxtReady(() => {
|
||||||
currentModel.value = getCurrentModel()
|
currentModel.value = getCurrentModel()
|
||||||
})
|
})
|
||||||
@@ -238,6 +253,20 @@ onNuxtReady(() => {
|
|||||||
class="footer"
|
class="footer"
|
||||||
>
|
>
|
||||||
<div class="px-md-16 w-100 d-flex flex-column">
|
<div class="px-md-16 w-100 d-flex flex-column">
|
||||||
|
<div
|
||||||
|
v-if="attachment"
|
||||||
|
class="mb-2"
|
||||||
|
>
|
||||||
|
<v-chip
|
||||||
|
closable
|
||||||
|
color="teal"
|
||||||
|
label
|
||||||
|
@click:close="attachment = null"
|
||||||
|
>
|
||||||
|
<v-icon start icon="attach_file"></v-icon>
|
||||||
|
{{ attachment.original_name }}
|
||||||
|
</v-chip>
|
||||||
|
</div>
|
||||||
<div class="d-flex align-center">
|
<div class="d-flex align-center">
|
||||||
<v-btn
|
<v-btn
|
||||||
v-show="fetchingResponse"
|
v-show="fetchingResponse"
|
||||||
@@ -252,11 +281,10 @@ onNuxtReady(() => {
|
|||||||
density="comfortable"
|
density="comfortable"
|
||||||
color="transparent"
|
color="transparent"
|
||||||
>
|
>
|
||||||
<Prompt v-show="!fetchingResponse" :use-prompt="usePrompt" />
|
<Prompt :use-prompt="usePrompt" />
|
||||||
<EditorToolsUploadFile />
|
<EditorToolsUploadFile :update-attachment="updateAttachment" />
|
||||||
<EditorToolsWebSearch v-if="$settings.open_web_search === 'True'" />
|
<EditorToolsWebSearch v-if="$settings.open_web_search === 'True'" />
|
||||||
<EditorToolsFrugalMode v-if="$settings.open_frugal_mode_control === 'True'" />
|
<EditorToolsFrugalMode v-if="$settings.open_frugal_mode_control === 'True'" />
|
||||||
|
|
||||||
</v-toolbar>
|
</v-toolbar>
|
||||||
</div>
|
</div>
|
||||||
</v-footer>
|
</v-footer>
|
||||||
|
|||||||
@@ -69,6 +69,19 @@ onMounted(() => {
|
|||||||
v-html="contentHtml"
|
v-html="contentHtml"
|
||||||
class="chat-msg-content pa-3"
|
class="chat-msg-content pa-3"
|
||||||
></div>
|
></div>
|
||||||
|
<template
|
||||||
|
v-if="message.attachments && message.attachments.length > 0"
|
||||||
|
>
|
||||||
|
<v-divider class="mx-4"></v-divider>
|
||||||
|
<v-card-text class="d-flex justify-space-between">
|
||||||
|
<v-chip
|
||||||
|
label
|
||||||
|
>
|
||||||
|
<v-icon start icon="attach_file"></v-icon>
|
||||||
|
{{ message.attachments[0].original_name }}
|
||||||
|
</v-chip>
|
||||||
|
</v-card-text>
|
||||||
|
</template>
|
||||||
</v-card>
|
</v-card>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
|||||||
@@ -1,19 +1,29 @@
|
|||||||
<script setup>
|
<script setup>
|
||||||
const { $i18n } = useNuxtApp()
|
const { $i18n } = useNuxtApp()
|
||||||
const dialog = ref(true)
|
const dialog = ref(false)
|
||||||
const uploading = ref(false)
|
const uploading = ref(false)
|
||||||
const file = ref(null)
|
const file = ref(null)
|
||||||
const errorMsg = ref('')
|
const errorMsg = ref('')
|
||||||
|
|
||||||
|
const props = defineProps({
|
||||||
|
updateAttachment: {
|
||||||
|
type: Function,
|
||||||
|
required: true
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
const fileChanged = () => {
|
const fileChanged = () => {
|
||||||
errorMsg.value = ''
|
errorMsg.value = ''
|
||||||
}
|
}
|
||||||
|
|
||||||
const upload = async () => {
|
const upload = async () => {
|
||||||
if (file.value === null) {
|
if (file.value.files.length < 1){
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
const fileObj = file.value.files[0]
|
||||||
uploading.value = true
|
uploading.value = true
|
||||||
const formData = new FormData()
|
const formData = new FormData()
|
||||||
formData.append('file', file.value.files[0])
|
formData.append('file', fileObj)
|
||||||
const { data, error } = await useAuthFetch('/api/chat/upload/', {
|
const { data, error } = await useAuthFetch('/api/chat/upload/', {
|
||||||
method: 'POST',
|
method: 'POST',
|
||||||
body: formData,
|
body: formData,
|
||||||
@@ -22,7 +32,7 @@ const upload = async () => {
|
|||||||
errorMsg.value = $i18n.t('Failed to upload file')
|
errorMsg.value = $i18n.t('Failed to upload file')
|
||||||
} else {
|
} else {
|
||||||
dialog.value = false
|
dialog.value = false
|
||||||
console.log(data.value)
|
props.updateAttachment(data.value.attachment)
|
||||||
}
|
}
|
||||||
uploading.value = false
|
uploading.value = false
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -13,4 +13,4 @@ export const useDrawer = () => useState('drawer', () => false)
|
|||||||
|
|
||||||
export const useEnableWebSearch = () => useState('enableWebSearch', () => false)
|
export const useEnableWebSearch = () => useState('enableWebSearch', () => false)
|
||||||
|
|
||||||
export const useFrugalMode = () => useState('frugalMode', () => false)
|
export const useFrugalMode = () => useState('frugalMode', () => true)
|
||||||
Reference in New Issue
Block a user