Compare commits

...

7 Commits
v1.1.3 ... v1

Author SHA1 Message Date
Rafi
13798e668a update demo 2023-02-16 18:19:28 +08:00
Wong Saang
d431048dc4 Merge pull request #5 from WongSaang/dev
feat: i18n
2023-02-16 17:55:03 +08:00
Rafi
9215965d45 feat: i18n
Add simplified Chinese translation
2023-02-16 17:34:40 +08:00
Rafi
66767d9352 feat: i18n config 2023-02-15 18:20:49 +08:00
Rafi
5abd5edba5 i18n config 2023-02-14 21:24:33 +08:00
Rafi
233eb9c27a feat: i18n 2023-02-14 18:32:49 +08:00
Rafi
5201349363 fix error when clicking the stop button and optimize SSE logic 2023-02-14 15:49:44 +08:00
14 changed files with 536 additions and 104 deletions

20
app.vue
View File

@@ -1,11 +1,12 @@
<script setup> <script setup>
const { $i18n } = useNuxtApp()
const runtimeConfig = useRuntimeConfig() const runtimeConfig = useRuntimeConfig()
const colorMode = useColorMode() const colorMode = useColorMode()
const drawer = ref(null) const drawer = ref(null)
const themes = ref([ const themes = ref([
{ title: 'Light', value: 'light' }, { title: $i18n.t('lightMode'), value: 'light' },
{ title: 'Dark', value: 'dark' }, { title: $i18n.t('darkMode'), value: 'dark' },
{ title: 'System', value: 'system'} { title: $i18n.t('followSystem'), value: 'system'}
]) ])
const setTheme = (theme) => { const setTheme = (theme) => {
colorMode.preference = theme colorMode.preference = theme
@@ -13,6 +14,11 @@ const setTheme = (theme) => {
const feedback = () => { const feedback = () => {
window.open('https://github.com/WongSaang/chatgpt-ui/issues', '_blank') window.open('https://github.com/WongSaang/chatgpt-ui/issues', '_blank')
} }
const { locale, locales, setLocale } = useI18n()
const setLang = (lang) => {
setLocale(lang)
}
</script> </script>
<template> <template>
@@ -38,7 +44,7 @@ const feedback = () => {
v-bind="props" v-bind="props"
rounded="xl" rounded="xl"
:prepend-icon="$colorMode.value === 'light' ? 'light_mode' : 'dark_mode'" :prepend-icon="$colorMode.value === 'light' ? 'light_mode' : 'dark_mode'"
title="Theme mode" :title="$t('themeMode')"
></v-list-item> ></v-list-item>
</template> </template>
<v-list <v-list
@@ -54,10 +60,12 @@ const feedback = () => {
</v-list> </v-list>
</v-menu> </v-menu>
<SettingsLanguages/>
<v-list-item <v-list-item
rounded="xl" rounded="xl"
prepend-icon="help_outline" prepend-icon="help_outline"
title="Feedback" :title="$t('feedback')"
@click="feedback" @click="feedback"
></v-list-item> ></v-list-item>
</v-list> </v-list>
@@ -87,7 +95,7 @@ const feedback = () => {
<v-list-item <v-list-item
@click="feedback" @click="feedback"
> >
<v-list-item-title>Feedback</v-list-item-title> <v-list-item-title>{{ $t('feedback') }}</v-list-item-title>
</v-list-item> </v-list-item>
</v-list> </v-list>
</v-menu> </v-menu>

View File

@@ -10,17 +10,17 @@
prepend-icon="vpn_key" prepend-icon="vpn_key"
color="primary" color="primary"
> >
Set OpenAI Api Key {{ $t('setApiKey') }}
</v-list-item> </v-list-item>
</template> </template>
<v-card> <v-card>
<v-card-title> <v-card-title>
<span class="text-h5">OpenAI Api Key</span> <span class="text-h5">{{ $t('openAIApiKey') }}</span>
</v-card-title> </v-card-title>
<v-divider></v-divider> <v-divider></v-divider>
<v-card-text> <v-card-text>
<div> <div>
Get a key: {{ $t('getAKey') }}:
<a target="_blank" href="https://platform.openai.com/account/api-keys">https://platform.openai.com/account/api-keys</a> <a target="_blank" href="https://platform.openai.com/account/api-keys">https://platform.openai.com/account/api-keys</a>
</div> </div>
<div <div

View File

@@ -17,12 +17,12 @@
</template> </template>
<v-card> <v-card>
<v-card-title> <v-card-title>
<span class="text-h5">OpenAI Models</span> <span class="text-h5">{{ $t('openAIModels') }}</span>
</v-card-title> </v-card-title>
<v-divider></v-divider> <v-divider></v-divider>
<v-card-text> <v-card-text>
<div> <div>
About the models: {{ $t('aboutTheModels') }}:
<a target="_blank" href="https://platform.openai.com/docs/models/overview">https://platform.openai.com/docs/models/overview</a> <a target="_blank" href="https://platform.openai.com/docs/models/overview">https://platform.openai.com/docs/models/overview</a>
</div> </div>
<div <div
@@ -77,7 +77,7 @@
color="primary" color="primary"
@click="save" @click="save"
> >
Save & Close {{ $t('saveAndClose') }}
</v-btn> </v-btn>
</v-card-actions> </v-card-actions>
</v-card> </v-card>
@@ -85,6 +85,7 @@
</template> </template>
<script setup> <script setup>
const { $i18n } = useNuxtApp()
const dialog = ref(false) const dialog = ref(false)
const models = useModels() const models = useModels()
const currentModel = useCurrentModel() const currentModel = useCurrentModel()
@@ -110,7 +111,7 @@ const removeModel = (index) => {
} }
const save = async () => { const save = async () => {
if (!currentModel.value) { if (!currentModel.value) {
showWarning('Please select at least one model.') showWarning($i18n.t('pleaseSelectAtLeastOneModelDot'))
return return
} }
setModels(models.value) setModels(models.value)

View File

@@ -1,13 +1,14 @@
<template> <template>
<v-textarea <v-textarea
v-model="message" v-model="message"
label="Write a message..." :label="$t('writeAMessage')"
placeholder="Write a message..." :placeholder="$t('writeAMessage') + '...'"
rows="1" rows="1"
:auto-grow="autoGrow" :auto-grow="autoGrow"
:disabled="disabled" :disabled="disabled"
:loading="loading" :loading="loading"
:hint="hint" :hint="hint"
:hide-details="loading"
append-inner-icon="send" append-inner-icon="send"
@keyup.enter.exact="enterOnly" @keyup.enter.exact="enterOnly"
@click:appendInner="clickSendBtn" @click:appendInner="clickSendBtn"
@@ -32,7 +33,7 @@ export default {
}, },
computed: { computed: {
hint() { hint() {
return isMobile() ? "" : "Press Enter to send your message or Shift+Enter to add a new line."; return isMobile() ? "" : "Press Enter to send your message or Shift+Enter to add a new line";
}, },
}, },
watch: { watch: {

View File

@@ -3,11 +3,11 @@
<v-row> <v-row>
<v-col cols="12"> <v-col cols="12">
<div class="text-center"> <div class="text-center">
<h2 class="text-h2">Welcome to <span class="text-primary">{{ runtimeConfig.public.appName }}</span></h2> <h2 class="text-h2">{{ $t('welcomeTo') }} <span class="text-primary">{{ runtimeConfig.public.appName }}</span></h2>
<p class="text-caption mt-5"> <p class="text-caption mt-5">
{{ runtimeConfig.public.appName }} is an unofficial client for ChatGPT, but uses the official OpenAI API. {{ runtimeConfig.public.appName }} {{ $t('welcomeScreen.introduction1') }}
<br> <br>
You will need an OpenAI API Key before you can use this client. {{ $t('welcomeScreen.introduction2') }}
</p> </p>
</div> </div>
</v-col> </v-col>
@@ -23,7 +23,7 @@
<v-col> <v-col>
<div class="d-flex flex-column align-center"> <div class="d-flex flex-column align-center">
<v-icon icon="sunny"></v-icon> <v-icon icon="sunny"></v-icon>
<h3 class="text-h6">Examples</h3> <h3 class="text-h6">{{ $t('welcomeScreen.examples.title') }}</h3>
</div> </div>
</v-col> </v-col>
</v-row> </v-row>
@@ -37,7 +37,7 @@
<v-col> <v-col>
<div class="d-flex flex-column align-center"> <div class="d-flex flex-column align-center">
<v-icon icon="bolt"></v-icon> <v-icon icon="bolt"></v-icon>
<h3 class="text-h6">Capabilities</h3> <h3 class="text-h6">{{ $t('welcomeScreen.capabilities.title') }}</h3>
</div> </div>
</v-col> </v-col>
</v-row> </v-row>
@@ -51,7 +51,7 @@
<v-col> <v-col>
<div class="d-flex flex-column align-center"> <div class="d-flex flex-column align-center">
<v-icon icon="warning_amber"></v-icon> <v-icon icon="warning_amber"></v-icon>
<h3 class="text-h6">Limitations</h3> <h3 class="text-h6">{{ $t('welcomeScreen.limitations.title') }}</h3>
</div> </div>
</v-col> </v-col>
</v-row> </v-row>
@@ -65,19 +65,20 @@
<script setup> <script setup>
const runtimeConfig = useRuntimeConfig() const runtimeConfig = useRuntimeConfig()
const { $i18n } = useNuxtApp()
const examples = ref([ const examples = ref([
'"Explain quantum computing in simple terms"', $i18n.t('welcomeScreen.examples.item1'),
'"Got any creative ideas for a 10 year olds birthday?"', $i18n.t('welcomeScreen.examples.item2'),
'"How do I make an HTTP request in Javascript?"' $i18n.t('welcomeScreen.examples.item3')
]) ])
const capabilities = ref([ const capabilities = ref([
'Remembers what user said earlier in the conversation', $i18n.t('welcomeScreen.capabilities.item1'),
'Allows user to provide follow-up corrections', $i18n.t('welcomeScreen.capabilities.item2'),
'Trained to decline inappropriate requests' $i18n.t('welcomeScreen.capabilities.item3')
]) ])
const limitations = ref([ const limitations = ref([
'May occasionally generate incorrect information', $i18n.t('welcomeScreen.limitations.item1'),
'May occasionally produce harmful instructions or biased content', $i18n.t('welcomeScreen.limitations.item2'),
'Limited knowledge of world and events after 2021' $i18n.t('welcomeScreen.limitations.item3')
]) ])
</script> </script>

View File

@@ -0,0 +1,86 @@
<template>
<v-dialog
v-model="dialog"
fullscreen
:scrim="false"
transition="dialog-bottom-transition"
>
<template v-slot:activator="{ props }">
<v-list-item
v-bind="props"
rounded="xl"
prepend-icon="language"
:title="$t('language')"
></v-list-item>
</template>
<v-card>
<v-toolbar
dark
color="primary"
>
<v-btn
icon
dark
@click="dialog = false"
>
<v-icon>close</v-icon>
</v-btn>
<v-toolbar-title>{{ $t('language') }}</v-toolbar-title>
<v-spacer></v-spacer>
<!-- <v-toolbar-items>-->
<!-- <v-btn-->
<!-- variant="text"-->
<!-- @click="dialog = false"-->
<!-- >-->
<!-- Save-->
<!-- </v-btn>-->
<!-- </v-toolbar-items>-->
</v-toolbar>
<v-list
>
<!-- <v-list-item-->
<!-- title="Use device language"-->
<!-- :append-icon="usingDeviceLanguage() ? 'radio_button_checked' : 'radio_button_unchecked'"-->
<!-- @click="useDeviceLanguage"-->
<!-- >-->
<!-- </v-list-item>-->
<v-list-item
v-for="l in locales"
:key="l.code"
:title="l.name"
:append-icon="radioIcon(l.code)"
@click="updateLocale(l.code)"
>
</v-list-item>
</v-list>
</v-card>
</v-dialog>
</template>
<script setup>
const dialog = ref(false)
const { locale, locales, setLocale } = useI18n()
const { $i18n } = useNuxtApp()
// const usingDeviceLanguage = () => {
// return ($i18n.getLocaleCookie() === undefined || $i18n.getLocaleCookie() === 'undefined')
// }
const updateLocale = (lang) => {
setLocale(lang)
}
const radioIcon = (code) => {
return code === locale.value ? 'radio_button_checked' : 'radio_button_unchecked'
}
// const useDeviceLanguage = () => {
// setLocale($i18n.getBrowserLocale())
// $i18n.setLocaleCookie(undefined)
// }
</script>
<style scoped>
</style>

Binary file not shown.

Before

Width:  |  Height:  |  Size: 917 KiB

After

Width:  |  Height:  |  Size: 143 KiB

45
lang/en-US.json Normal file
View File

@@ -0,0 +1,45 @@
{
"welcomeTo": "Welcome to",
"language": "Language",
"setApiKey": "Set API Key",
"setOpenAIApiKey": "Set OpenAI API Key",
"openAIApiKey": "OpenAI API Key",
"getAKey": "Get a key",
"openAIModels": "OpenAI Models",
"aboutTheModels": "About the models",
"saveAndClose": "Save & Close",
"pleaseSelectAtLeastOneModelDot": "Please select at least one model.",
"writeAMessage": "Write a message",
"pressEnterToSendYourMessageOrShiftEnterToAddANewLine": "Press Enter to send your message or Shift+Enter to add a new line",
"lightMode": "Light Mode",
"darkMode": "Dark Mode",
"followSystem": "Follow system",
"themeMode": "Theme Mode",
"feedback": "Feedback",
"roles": {
"me": "Me",
"ai": "AI"
},
"welcomeScreen": {
"introduction1": "is an unofficial client for ChatGPT, but uses the official OpenAI API.",
"introduction2": "You will need an OpenAI API Key before you can use this client.",
"examples": {
"title": "Examples",
"item1": "\"Explain quantum computing in simple terms\"",
"item2": "\"Got any creative ideas for a 10 year olds birthday?\"",
"item3": "\"How do I make an HTTP request in Javascript?\""
},
"capabilities": {
"title": "Capabilities",
"item1": "Remembers what user said earlier in the conversation",
"item2": "Allows user to provide follow-up corrections",
"item3": "Trained to decline inappropriate requests"
},
"limitations": {
"title": "Limitations",
"item1": "May occasionally generate incorrect information",
"item2": "May occasionally produce harmful instructions or biased content",
"item3": "Limited knowledge of world and events after 2021"
}
}
}

45
lang/zh-CN.json Normal file
View File

@@ -0,0 +1,45 @@
{
"welcomeTo": "欢迎来到",
"language": "语言",
"setApiKey": "设置API密钥",
"setOpenAIApiKey": "设置OpenAI的API密钥",
"openAIApiKey": "OpenAI的API密钥",
"getAKey": "获取钥匙",
"openAIModels": "OpenAI模型",
"aboutTheModels": "关于模型",
"saveAndClose": "保存并关闭",
"pleaseSelectAtLeastOneModelDot": "请至少选择一个模型",
"writeAMessage": "输入信息",
"pressEnterToSendYourMessageOrShiftEnterToAddANewLine": "按回车键发送您的信息或按Shift+Enter键添加新行",
"lightMode": "明亮模式",
"darkMode": "暗色模式",
"followSystem": "跟随系统",
"themeMode": "主题模式",
"feedback": "反馈",
"roles": {
"me": "我",
"ai": "AI"
},
"welcomeScreen": {
"introduction1": "是一个非官方的ChatGPT客户端但使用OpenAI的官方API",
"introduction2": "在使用本客户端之前您需要一个OpenAI API密钥。",
"examples": {
"title": "例子",
"item1": "\"用简单的语言解释量子计算\"",
"item2": "\"为10岁的孩子过生日有什么创造性的想法吗\"",
"item3": "\"我如何在Javascript中进行HTTP请求\""
},
"capabilities": {
"title": "能力",
"item1": "记得用户在谈话中早先说过的话",
"item2": "允许用户提供后续更正",
"item3": "经过培训,可以拒绝不适当的请求"
},
"limitations": {
"title": "局限",
"item1": "偶尔可能会产生不正确的信息",
"item2": "可能偶尔会产生有害的指示或有偏见的内容",
"item3": "对2021年以后的世界和事件了解有限"
}
}
}

View File

@@ -22,5 +22,31 @@ export default defineNuxtConfig({
'material-design-icons-iconfont/dist/material-design-icons.css', 'material-design-icons-iconfont/dist/material-design-icons.css',
'highlight.js/styles/panda-syntax-dark.css', 'highlight.js/styles/panda-syntax-dark.css',
], ],
modules: ['@nuxtjs/color-mode'] modules: [
'@nuxtjs/color-mode',
'@nuxtjs/i18n'
],
i18n: {
strategy: 'no_prefix',
locales: [
{
code: 'en',
iso: 'en-US',
name: 'English',
file: 'en-US.json',
},
{
code: 'zh-CN',
iso: 'zh-CN',
name: '简体中文',
file: 'zh-CN.json',
}
],
lazy: true,
langDir: 'lang',
defaultLocale: 'en',
vueI18n: {
fallbackLocale: 'en',
},
}
}) })

View File

@@ -9,6 +9,7 @@
}, },
"devDependencies": { "devDependencies": {
"@nuxtjs/color-mode": "^3.2.0", "@nuxtjs/color-mode": "^3.2.0",
"@nuxtjs/i18n": "^8.0.0-beta.9",
"material-design-icons-iconfont": "^6.7.0", "material-design-icons-iconfont": "^6.7.0",
"nuxt": "^3.2.0" "nuxt": "^3.2.0"
}, },
@@ -18,6 +19,7 @@
"highlight.js": "^11.7.0", "highlight.js": "^11.7.0",
"is-mobile": "^3.1.1", "is-mobile": "^3.1.1",
"marked": "^4.2.12", "marked": "^4.2.12",
"nanoid": "^4.0.1",
"vuetify": "^3.0.6" "vuetify": "^3.0.6"
}, },
"license": "MIT" "license": "MIT"

View File

@@ -1,12 +1,21 @@
<script setup> <script setup>
import { fetchEventSource } from '@microsoft/fetch-event-source' import {EventStreamContentType, fetchEventSource} from '@microsoft/fetch-event-source'
const { $i18n } = useNuxtApp()
const runtimeConfig = useRuntimeConfig() const runtimeConfig = useRuntimeConfig()
const currentModel = useCurrentModel() const currentModel = useCurrentModel()
const openaiApiKey = useApiKey() const openaiApiKey = useApiKey()
const fetchingResponse = ref(false) const fetchingResponse = ref(false)
let ctrl
const abortFetch = () => {
if (ctrl) {
ctrl.abort()
}
fetchingResponse.value = false
}
const fetchReply = async (message, parentMessageId) => { const fetchReply = async (message, parentMessageId) => {
const ctrl = new AbortController() ctrl = new AbortController()
try { try {
await fetchEventSource('/api/conversation', { await fetchEventSource('/api/conversation', {
signal: ctrl.signal, signal: ctrl.signal,
@@ -22,43 +31,50 @@ const fetchReply = async (message, parentMessageId) => {
conversationId: currentConversation.value.id conversationId: currentConversation.value.id
}), }),
onopen(response) { onopen(response) {
if (response.status === 200) { if (response.ok && response.headers.get('content-type') === EventStreamContentType) {
return; return;
} }
throw new Error(`Failed to send message. HTTP ${response.status} - ${response.statusText}`); throw new Error(`Failed to send message. HTTP ${response.status} - ${response.statusText}`);
}, },
onclose() { onclose() {
if (ctrl.signal.aborted === true) {
return;
}
throw new Error(`Failed to send message. Server closed the connection unexpectedly.`); throw new Error(`Failed to send message. Server closed the connection unexpectedly.`);
}, },
onerror(err) { onerror(err) {
throw err; throw err;
}, },
onmessage(message) { onmessage(message) {
if (message.event === 'error') { const event = message.event
throw new Error(JSON.parse(message.data).error); const data = JSON.parse(message.data)
if (event === 'error') {
throw new Error(data.error);
} }
const { type, data } = JSON.parse(message.data);
if (type === 'done') { if (event === 'done') {
if (currentConversation.value.id === null) { if (currentConversation.value.id === null) {
currentConversation.value.id = data.conversationId currentConversation.value.id = data.conversationId
} }
currentConversation.value.messages[currentConversation.value.messages.length - 1].id = data.messageId currentConversation.value.messages[currentConversation.value.messages.length - 1].id = data.messageId
ctrl.abort(); abortFetch()
fetchingResponse.value = false
return; return;
} }
if (currentConversation.value.messages[currentConversation.value.messages.length - 1].from === 'ai') { if (currentConversation.value.messages[currentConversation.value.messages.length - 1].from === 'ai') {
currentConversation.value.messages[currentConversation.value.messages.length - 1].message += data currentConversation.value.messages[currentConversation.value.messages.length - 1].message += data.content
} else { } else {
currentConversation.value.messages.push({id: null, from: 'ai', message: data}) currentConversation.value.messages.push({id: null, from: 'ai', message: data.content})
} }
scrollChatWindow() scrollChatWindow()
}, },
}) })
} catch (err) { } catch (err) {
ctrl.abort() console.log(err)
abortFetch()
showSnackbar(err.message) showSnackbar(err.message)
fetchingResponse.value = false
} }
} }
@@ -70,6 +86,9 @@ const currentConversation = ref({})
const grab = ref(null) const grab = ref(null)
const scrollChatWindow = () => { const scrollChatWindow = () => {
if (grab.value === null) {
return;
}
grab.value.scrollIntoView({behavior: 'smooth'}) grab.value.scrollIntoView({behavior: 'smooth'})
} }
@@ -91,8 +110,7 @@ const send = (message) => {
scrollChatWindow() scrollChatWindow()
} }
const stop = () => { const stop = () => {
ctrl.abort(); abortFetch()
fetchingResponse.value = false
} }
const snackbar = ref(false) const snackbar = ref(false)
@@ -118,14 +136,14 @@ createNewConversation()
:variant="conversation.from === 'ai' ? 'tonal' : 'text'" :variant="conversation.from === 'ai' ? 'tonal' : 'text'"
> >
<v-container> <v-container>
<v-card-text class="text-caption text-disabled">{{ conversation.from }}</v-card-text> <v-card-text class="text-caption text-disabled">{{ $t(`roles.${conversation.from}`) }}</v-card-text>
<v-card-text> <v-card-text>
<MsgContent :content="conversation.message" /> <MsgContent :content="conversation.message" />
</v-card-text> </v-card-text>
</v-container> </v-container>
<v-divider></v-divider> <v-divider></v-divider>
</v-card> </v-card>
<div ref="grab" class="w-100" style="height: 150px;"></div> <div ref="grab" class="w-100" style="height: 200px;"></div>
</div> </div>
<Welcome v-else /> <Welcome v-else />
<v-footer app class="d-flex flex-column"> <v-footer app class="d-flex flex-column">
@@ -141,7 +159,7 @@ createNewConversation()
</div> </div>
<div class="px-4 py-2 text-disabled text-caption font-weight-light text-center w-100"> <div class="px-4 py-2 text-disabled text-caption font-weight-light text-center w-100">
© {{ new Date().getFullYear() }} {{ runtimeConfig.public.appName }} © {{ new Date().getFullYear() }} {{ runtimeConfig.public.appName }}
</div> </div>
</v-footer> </v-footer>
<v-snackbar <v-snackbar

View File

@@ -1,25 +1,13 @@
import ChatGPTClient from '@waylaidwanderer/chatgpt-api' import ChatGPTClient from '@waylaidwanderer/chatgpt-api'
import { PassThrough } from 'node:stream' import { PassThrough } from 'node:stream'
import { nanoid } from 'nanoid'
const serializeSSEEvent = (chunk) => { const serializeSSEEvent = (event, data) => {
let payload = ""; const id = nanoid();
if (chunk.id) { const eventStr = event ? `event: ${event}\n` : '';
payload += `id: ${chunk.id}\n`; const dataStr = data ? `data: ${JSON.stringify(data)}\n` : '';
}
if (chunk.event) { return `id: ${id}\n${eventStr}${dataStr}\n`;
payload += `event: ${chunk.event}\n`;
}
if (chunk.data) {
payload += `data: ${chunk.data}\n`;
}
if (chunk.retry) {
payload += `retry: ${chunk.retry}\n`;
}
if (!payload) {
return "";
}
payload += "\n";
return payload;
} }
export default defineEventHandler(async (event) => { export default defineEventHandler(async (event) => {
@@ -27,9 +15,13 @@ export default defineEventHandler(async (event) => {
const conversationId = body.conversationId ? body.conversationId.toString() : undefined const conversationId = body.conversationId ? body.conversationId.toString() : undefined
const parentMessageId = body.parentMessageId ? body.parentMessageId.toString() : undefined const parentMessageId = body.parentMessageId ? body.parentMessageId.toString() : undefined
const tunnel = new PassThrough() const tunnel = new PassThrough()
const writeToTunnel = (data) => { const writeToTunnel = (event, data) => {
tunnel.write(serializeSSEEvent(data)) tunnel.write(serializeSSEEvent(event, data))
} }
const endTunnel = () => {
tunnel.end()
}
setResponseHeaders(event, { setResponseHeaders(event, {
'Content-Type': 'text/event-stream', 'Content-Type': 'text/event-stream',
'Cache-Control': 'no-cache', 'Cache-Control': 'no-cache',
@@ -37,13 +29,11 @@ export default defineEventHandler(async (event) => {
}) })
if (!body.openaiApiKey) { if (!body.openaiApiKey) {
writeToTunnel({ writeToTunnel('error', {
event: 'error', code: 503,
data: JSON.stringify({ error: 'You haven\'t set the api key of openai',
code: 503,
error: 'You haven\'t set the api key of openai',
}),
}) })
endTunnel()
return sendStream(event, tunnel) return sendStream(event, tunnel)
} }
@@ -79,29 +69,19 @@ export default defineEventHandler(async (event) => {
parentMessageId, parentMessageId,
onProgress: (token) => { onProgress: (token) => {
// console.log(token) // console.log(token)
writeToTunnel({ data: JSON.stringify({ writeToTunnel('message',{content: token})
type: 'token',
data: token
})
})
} }
}); });
writeToTunnel({ data: JSON.stringify({ writeToTunnel('done',response)
type: 'done', console.info(response)
data: response
}) })
console.log(response)
} catch (e) { } catch (e) {
const code = e?.json?.data?.code || 503; const code = e?.json?.data?.code || 503;
const message = e?.json?.error?.message || 'There was an error communicating with ChatGPT.'; const message = e?.json?.error?.message || 'There was an error communicating with ChatGPT.';
writeToTunnel({ writeToTunnel('error', {
event: 'error', code,
data: JSON.stringify({ error: message
code,
error: message,
}),
}) })
} }
tunnel.end()
return sendStream(event, tunnel) return sendStream(event, tunnel)
}) })

239
yarn.lock
View File

@@ -538,6 +538,101 @@
dependencies: dependencies:
fast-json-stringify "^5.0.0" fast-json-stringify "^5.0.0"
"@intlify/bundle-utils@^3.4.0":
version "3.4.0"
resolved "https://registry.npmmirror.com/@intlify/bundle-utils/-/bundle-utils-3.4.0.tgz#72558611f4b223a6791f591363dc48a4bcacdf70"
integrity sha512-2UQkqiSAOSPEHMGWlybqWm4G2K0X+FyYho5AwXz6QklSX1EY5EDmOSxZmwscn2qmKBnp6OYsme5kUrnN9xrWzQ==
dependencies:
"@intlify/message-compiler" next
"@intlify/shared" next
jsonc-eslint-parser "^1.0.1"
source-map "0.6.1"
yaml-eslint-parser "^0.3.2"
"@intlify/bundle-utils@^4.0.0":
version "4.0.0"
resolved "https://registry.npmmirror.com/@intlify/bundle-utils/-/bundle-utils-4.0.0.tgz#29c1d602c7e4e33b516581496a7c6740ed7e2585"
integrity sha512-klXrYT9VXyKEXsD6UY3pShg0O5MPC07n0TZ5RrSs5ry6T1eZVolIFGJi9c3qcDrh1qjJxgikRnPBmD7qGDqbjw==
dependencies:
"@intlify/message-compiler" next
"@intlify/shared" next
jsonc-eslint-parser "^1.0.1"
source-map "0.6.1"
yaml-eslint-parser "^0.3.2"
"@intlify/core-base@9.3.0-beta.16":
version "9.3.0-beta.16"
resolved "https://registry.npmmirror.com/@intlify/core-base/-/core-base-9.3.0-beta.16.tgz#bd993fde9c0a96f081a5805a78bece953bfdce9e"
integrity sha512-BoAxVoPIJoPKCCMdsuNXKaaJxvetvHrW2KA43IpkwgPd2/w6zPebh/+v8e4zpXKjFVSgcF97zP87KeVcM/Lxwg==
dependencies:
"@intlify/devtools-if" "9.3.0-beta.16"
"@intlify/message-compiler" "9.3.0-beta.16"
"@intlify/shared" "9.3.0-beta.16"
"@intlify/vue-devtools" "9.3.0-beta.16"
"@intlify/devtools-if@9.3.0-beta.16":
version "9.3.0-beta.16"
resolved "https://registry.npmmirror.com/@intlify/devtools-if/-/devtools-if-9.3.0-beta.16.tgz#fab2bf0166686e998c9a1539e1eff1e07ee2beb6"
integrity sha512-9WXn8YMAnL/DHdoWqCy6yLTXcLFxd8eXB9UNsViQA5JJV7neR+yahr+23X1wP0prhG338MruxAu65khRf+AJCw==
dependencies:
"@intlify/shared" "9.3.0-beta.16"
"@intlify/message-compiler@9.3.0-beta.16", "@intlify/message-compiler@next":
version "9.3.0-beta.16"
resolved "https://registry.npmmirror.com/@intlify/message-compiler/-/message-compiler-9.3.0-beta.16.tgz#335f7bdb06cfb84d04a1a1c1d6eff2532dfd88e7"
integrity sha512-CGQI3xRcs1ET75eDQ0DUy3MRYOqTauRIIgaMoISKiF83gqRWg93FqN8lGMKcpBqaF4tI0JhsfosCaGiBL9+dnw==
dependencies:
"@intlify/shared" "9.3.0-beta.16"
source-map "0.6.1"
"@intlify/shared@9.3.0-beta.11":
version "9.3.0-beta.11"
resolved "https://registry.npmmirror.com/@intlify/shared/-/shared-9.3.0-beta.11.tgz#a98668c7685ba3b62ccd18767bc52d8087e9e414"
integrity sha512-CtbotesxTRiC3bRyXyv1NG39fkqJ790f8z8xFaeIXSZpOdiyxoh5BIyypCzSFQZDGLwz0Q9gyWbW1XpxQJm68Q==
"@intlify/shared@9.3.0-beta.16", "@intlify/shared@next":
version "9.3.0-beta.16"
resolved "https://registry.npmmirror.com/@intlify/shared/-/shared-9.3.0-beta.16.tgz#74f254dbb7eac633b86d690a341349db29573896"
integrity sha512-kXbm4svALe3lX+EjdJxfnabOphqS4yQ1Ge/iIlR8tvUiYRCoNz3hig1M4336iY++Dfx5ytEQJPNjIcknNIuvig==
"@intlify/unplugin-vue-i18n@^0.8.1":
version "0.8.2"
resolved "https://registry.npmmirror.com/@intlify/unplugin-vue-i18n/-/unplugin-vue-i18n-0.8.2.tgz#4196cb5bee4243bb3a33af76ce9663f3e106809a"
integrity sha512-cRnzPqSEZQOmTD+p4pwc3RTS9HxreLqfID0keoqZDZweCy/CGRMLLTNd15S4TUf1vSBhPF03DItEFDr1F+8MDA==
dependencies:
"@intlify/bundle-utils" "^4.0.0"
"@intlify/shared" next
"@rollup/pluginutils" "^4.2.0"
"@vue/compiler-sfc" "^3.2.45"
debug "^4.3.1"
fast-glob "^3.2.5"
js-yaml "^4.1.0"
json5 "^2.2.0"
pathe "^1.0.0"
picocolors "^1.0.0"
source-map "0.6.1"
unplugin "^1.0.0"
"@intlify/vue-devtools@9.3.0-beta.16":
version "9.3.0-beta.16"
resolved "https://registry.npmmirror.com/@intlify/vue-devtools/-/vue-devtools-9.3.0-beta.16.tgz#70a615f56d70e2fcaa91eb1a362c3bca1c553f3e"
integrity sha512-rQ/jSW0gBciYLBBi+XN65r80B59Ypege9oqUi+EZ2QpOaK54wDcy1xq9w6Zbj6WpY1qgf34KtYawKIF10mMr6w==
dependencies:
"@intlify/core-base" "9.3.0-beta.16"
"@intlify/shared" "9.3.0-beta.16"
"@intlify/vue-i18n-bridge@^0.8.0":
version "0.8.0"
resolved "https://registry.npmmirror.com/@intlify/vue-i18n-bridge/-/vue-i18n-bridge-0.8.0.tgz#e574f893b68abfee31cc27dd87fdc296056213fc"
integrity sha512-wQ18fSccm9QaWpUW2vq2QHvojgKIog7s+UMj9LeY3pUV3yD9bU4YZI+1PTNoX3tOA+BE71gQyqVGox/TVQKP6Q==
"@intlify/vue-router-bridge@^0.8.0":
version "0.8.0"
resolved "https://registry.npmmirror.com/@intlify/vue-router-bridge/-/vue-router-bridge-0.8.0.tgz#da3db5cb3efcedecb403037f957eb49a92223a40"
integrity sha512-CNxOgvyQcRhtGmRrksicL+HGjDijXtz+J/x04C/RslZ74CFdZkxjCe8MABkeD3xr+ry8G8tCm2nV2hLjZbynQw==
dependencies:
vue-demi "^0.13.5"
"@ioredis/commands@^1.1.1": "@ioredis/commands@^1.1.1":
version "1.2.0" version "1.2.0"
resolved "https://registry.npmmirror.com/@ioredis/commands/-/commands-1.2.0.tgz#6d61b3097470af1fdbbe622795b8921d42018e11" resolved "https://registry.npmmirror.com/@ioredis/commands/-/commands-1.2.0.tgz#6d61b3097470af1fdbbe622795b8921d42018e11"
@@ -809,6 +904,31 @@
lodash.template "^4.5.0" lodash.template "^4.5.0"
pathe "^1.0.0" pathe "^1.0.0"
"@nuxtjs/i18n@^8.0.0-beta.9":
version "8.0.0-beta.9"
resolved "https://registry.npmmirror.com/@nuxtjs/i18n/-/i18n-8.0.0-beta.9.tgz#6bccff4f900a09a9cb220f35dfa22f248a0a0d0c"
integrity sha512-Vz90kpmr1WJIPqAhlLWD3Yov8/DWCUQiT/5Xu8Kuqw+iZ47ZI7HI2W6BzwusHSRHn+fINxg/lKgs0uWw38PfKw==
dependencies:
"@intlify/bundle-utils" "^3.4.0"
"@intlify/shared" "9.3.0-beta.11"
"@intlify/unplugin-vue-i18n" "^0.8.1"
"@nuxt/kit" "^3.0.0"
"@vue/compiler-sfc" "^3.2.45"
cookie-es "^0.5.0"
debug "^4.3.4"
estree-walker "^3.0.1"
is-https "^4.0.0"
js-cookie "^3.0.1"
knitwork "^1.0.0"
magic-string "^0.27.0"
mlly "^1.0.0"
pathe "^1.0.0"
pkg-types "^1.0.1"
ufo "^1.0.1"
unplugin "^1.0.1"
vue-i18n "9.3.0-beta.16"
vue-i18n-routing "^0.10.2"
"@planetscale/database@^1.5.0": "@planetscale/database@^1.5.0":
version "1.5.0" version "1.5.0"
resolved "https://registry.npmmirror.com/@planetscale/database/-/database-1.5.0.tgz#073d9ca9841ad62896a6e31f610e89112e6264ef" resolved "https://registry.npmmirror.com/@planetscale/database/-/database-1.5.0.tgz#073d9ca9841ad62896a6e31f610e89112e6264ef"
@@ -883,7 +1003,7 @@
resolved "https://registry.npmmirror.com/@rollup/plugin-wasm/-/plugin-wasm-6.1.2.tgz#faf57f8e2ed12b9e0e898ba67963c52e1cd5f4c3" resolved "https://registry.npmmirror.com/@rollup/plugin-wasm/-/plugin-wasm-6.1.2.tgz#faf57f8e2ed12b9e0e898ba67963c52e1cd5f4c3"
integrity sha512-YdrQ7zfnZ54Y+6raCev3tR1PrhQGxYKSTajGylhyP0oBacouuNo6KcNCk+pYKw9M98jxRWLFFca/udi76IDXzg== integrity sha512-YdrQ7zfnZ54Y+6raCev3tR1PrhQGxYKSTajGylhyP0oBacouuNo6KcNCk+pYKw9M98jxRWLFFca/udi76IDXzg==
"@rollup/pluginutils@^4.0.0": "@rollup/pluginutils@^4.0.0", "@rollup/pluginutils@^4.2.0":
version "4.2.1" version "4.2.1"
resolved "https://registry.npmmirror.com/@rollup/pluginutils/-/pluginutils-4.2.1.tgz#e6c6c3aba0744edce3fb2074922d3776c0af2a6d" resolved "https://registry.npmmirror.com/@rollup/pluginutils/-/pluginutils-4.2.1.tgz#e6c6c3aba0744edce3fb2074922d3776c0af2a6d"
integrity sha512-iKnFXr7NkdZAIHiIWE+BX5ULi/ucVFYWD6TbAV+rZctiRTY2PL6tsIKhoIOaoskiWAkgu+VsbXgUVDNLHf+InQ== integrity sha512-iKnFXr7NkdZAIHiIWE+BX5ULi/ucVFYWD6TbAV+rZctiRTY2PL6tsIKhoIOaoskiWAkgu+VsbXgUVDNLHf+InQ==
@@ -1014,7 +1134,7 @@
"@vue/compiler-core" "3.2.47" "@vue/compiler-core" "3.2.47"
"@vue/shared" "3.2.47" "@vue/shared" "3.2.47"
"@vue/compiler-sfc@3.2.47": "@vue/compiler-sfc@3.2.47", "@vue/compiler-sfc@^3.2.45":
version "3.2.47" version "3.2.47"
resolved "https://registry.npmmirror.com/@vue/compiler-sfc/-/compiler-sfc-3.2.47.tgz#1bdc36f6cdc1643f72e2c397eb1a398f5004ad3d" resolved "https://registry.npmmirror.com/@vue/compiler-sfc/-/compiler-sfc-3.2.47.tgz#1bdc36f6cdc1643f72e2c397eb1a398f5004ad3d"
integrity sha512-rog05W+2IFfxjMcFw10tM9+f7i/+FFpZJJ5XHX72NP9eC2uRD+42M3pYcQqDXVYoj74kHMSEdQ/WmCjt8JFksQ== integrity sha512-rog05W+2IFfxjMcFw10tM9+f7i/+FFpZJJ5XHX72NP9eC2uRD+42M3pYcQqDXVYoj74kHMSEdQ/WmCjt8JFksQ==
@@ -1038,7 +1158,7 @@
"@vue/compiler-dom" "3.2.47" "@vue/compiler-dom" "3.2.47"
"@vue/shared" "3.2.47" "@vue/shared" "3.2.47"
"@vue/devtools-api@^6.4.5": "@vue/devtools-api@^6.2.1", "@vue/devtools-api@^6.4.5":
version "6.5.0" version "6.5.0"
resolved "https://registry.npmmirror.com/@vue/devtools-api/-/devtools-api-6.5.0.tgz#98b99425edee70b4c992692628fa1ea2c1e57d07" resolved "https://registry.npmmirror.com/@vue/devtools-api/-/devtools-api-6.5.0.tgz#98b99425edee70b4c992692628fa1ea2c1e57d07"
integrity sha512-o9KfBeaBmCKl10usN4crU53fYtC1r7jJwdGKjPT24t348rHxgfpZ0xL3Xm/gLUYnc0oTp8LAmrxOeLyu6tbk2Q== integrity sha512-o9KfBeaBmCKl10usN4crU53fYtC1r7jJwdGKjPT24t348rHxgfpZ0xL3Xm/gLUYnc0oTp8LAmrxOeLyu6tbk2Q==
@@ -1149,6 +1269,16 @@ abstract-logging@^2.0.1:
resolved "https://registry.npmmirror.com/abstract-logging/-/abstract-logging-2.0.1.tgz#6b0c371df212db7129b57d2e7fcf282b8bf1c839" resolved "https://registry.npmmirror.com/abstract-logging/-/abstract-logging-2.0.1.tgz#6b0c371df212db7129b57d2e7fcf282b8bf1c839"
integrity sha512-2BjRTZxTPvheOvGbBslFSYOUkr+SjPtOnrLP33f+VIWLzezQpZcqVg7ja3L4dBXmzzgwT+a029jRx5PCi3JuiA== integrity sha512-2BjRTZxTPvheOvGbBslFSYOUkr+SjPtOnrLP33f+VIWLzezQpZcqVg7ja3L4dBXmzzgwT+a029jRx5PCi3JuiA==
acorn-jsx@^5.2.0:
version "5.3.2"
resolved "https://registry.npmmirror.com/acorn-jsx/-/acorn-jsx-5.3.2.tgz#7ed5bb55908b3b2f1bc55c6af1653bada7f07937"
integrity sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==
acorn@^7.1.1, acorn@^7.4.1:
version "7.4.1"
resolved "https://registry.npmmirror.com/acorn/-/acorn-7.4.1.tgz#feaed255973d2e77555b83dbc08851a6c63520fa"
integrity sha512-nQyp0o1/mNdbTO1PO6kHkwSrmgZ0MT/jCCpNiwbUjGoRN4dlBhqJtoQuCnEOKzgTVwg0ZWiCoQy6SxMebQVh8A==
acorn@^8.5.0, acorn@^8.6.0, acorn@^8.8.1, acorn@^8.8.2: acorn@^8.5.0, acorn@^8.6.0, acorn@^8.8.1, acorn@^8.8.2:
version "8.8.2" version "8.8.2"
resolved "https://registry.npmmirror.com/acorn/-/acorn-8.8.2.tgz#1b2f25db02af965399b9776b0c2c391276d37c4a" resolved "https://registry.npmmirror.com/acorn/-/acorn-8.8.2.tgz#1b2f25db02af965399b9776b0c2c391276d37c4a"
@@ -1288,6 +1418,11 @@ are-we-there-yet@^2.0.0:
delegates "^1.0.0" delegates "^1.0.0"
readable-stream "^3.6.0" readable-stream "^3.6.0"
argparse@^2.0.1:
version "2.0.1"
resolved "https://registry.npmmirror.com/argparse/-/argparse-2.0.1.tgz#246f50f3ca78a3240f6c997e8a9bd1eac49e4b38"
integrity sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==
async-sema@^3.1.1: async-sema@^3.1.1:
version "3.1.1" version "3.1.1"
resolved "https://registry.npmmirror.com/async-sema/-/async-sema-3.1.1.tgz#e527c08758a0f8f6f9f15f799a173ff3c40ea808" resolved "https://registry.npmmirror.com/async-sema/-/async-sema-3.1.1.tgz#e527c08758a0f8f6f9f15f799a173ff3c40ea808"
@@ -1835,7 +1970,7 @@ debug@2.6.9:
dependencies: dependencies:
ms "2.0.0" ms "2.0.0"
debug@4, debug@^4.0.0, debug@^4.1.0, debug@^4.1.1, debug@^4.3.4: debug@4, debug@^4.0.0, debug@^4.1.0, debug@^4.1.1, debug@^4.3.1, debug@^4.3.4:
version "4.3.4" version "4.3.4"
resolved "https://registry.npmmirror.com/debug/-/debug-4.3.4.tgz#1319f6579357f2338d3337d2cdd4914bb5dcc865" resolved "https://registry.npmmirror.com/debug/-/debug-4.3.4.tgz#1319f6579357f2338d3337d2cdd4914bb5dcc865"
integrity sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ== integrity sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==
@@ -2090,6 +2225,27 @@ escape-string-regexp@^5.0.0:
resolved "https://registry.npmmirror.com/escape-string-regexp/-/escape-string-regexp-5.0.0.tgz#4683126b500b61762f2dbebace1806e8be31b1c8" resolved "https://registry.npmmirror.com/escape-string-regexp/-/escape-string-regexp-5.0.0.tgz#4683126b500b61762f2dbebace1806e8be31b1c8"
integrity sha512-/veY75JbMK4j1yjvuUxuVsiS/hr/4iHs9FTT6cgTexxdE0Ly/glccBAkloH/DofkjRbZU3bnoj38mOmhkZ0lHw== integrity sha512-/veY75JbMK4j1yjvuUxuVsiS/hr/4iHs9FTT6cgTexxdE0Ly/glccBAkloH/DofkjRbZU3bnoj38mOmhkZ0lHw==
eslint-utils@^2.1.0:
version "2.1.0"
resolved "https://registry.npmmirror.com/eslint-utils/-/eslint-utils-2.1.0.tgz#d2de5e03424e707dc10c74068ddedae708741b27"
integrity sha512-w94dQYoauyvlDc43XnGB8lU3Zt713vNChgt4EWwhXAP2XkBvndfxF0AgIqKOOasjPIPzj9JqgwkwbCYD0/V3Zg==
dependencies:
eslint-visitor-keys "^1.1.0"
eslint-visitor-keys@^1.1.0, eslint-visitor-keys@^1.3.0:
version "1.3.0"
resolved "https://registry.npmmirror.com/eslint-visitor-keys/-/eslint-visitor-keys-1.3.0.tgz#30ebd1ef7c2fdff01c3a4f151044af25fab0523e"
integrity sha512-6J72N8UNa462wa/KFODt/PJ3IU60SDpC3QXC1Hjc1BXXpfL2C9R5+AU7jhe0F6GREqVMh4Juu+NY7xn+6dipUQ==
espree@^6.0.0:
version "6.2.1"
resolved "https://registry.npmmirror.com/espree/-/espree-6.2.1.tgz#77fc72e1fd744a2052c20f38a5b575832e82734a"
integrity sha512-ysCxRQY3WaXJz9tdbWOwuWr5Y/XrPTGX9Kiz3yoUXwW0VZ4w30HTkQLaGx/+ttFjF8i+ACbArnB4ce68a9m5hw==
dependencies:
acorn "^7.1.1"
acorn-jsx "^5.2.0"
eslint-visitor-keys "^1.1.0"
estree-walker@2.0.2, estree-walker@^2.0.1, estree-walker@^2.0.2: estree-walker@2.0.2, estree-walker@^2.0.1, estree-walker@^2.0.2:
version "2.0.2" version "2.0.2"
resolved "https://registry.npmmirror.com/estree-walker/-/estree-walker-2.0.2.tgz#52f010178c2a4c117a7757cfe942adb7d2da4cac" resolved "https://registry.npmmirror.com/estree-walker/-/estree-walker-2.0.2.tgz#52f010178c2a4c117a7757cfe942adb7d2da4cac"
@@ -2176,7 +2332,7 @@ fast-fifo@^1.0.0:
resolved "https://registry.npmmirror.com/fast-fifo/-/fast-fifo-1.1.0.tgz#17d1a3646880b9891dfa0c54e69c5fef33cad779" resolved "https://registry.npmmirror.com/fast-fifo/-/fast-fifo-1.1.0.tgz#17d1a3646880b9891dfa0c54e69c5fef33cad779"
integrity sha512-Kl29QoNbNvn4nhDsLYjyIAaIqaJB6rBx5p3sL9VjaefJ+eMFBWVZiaoguaoZfzEKr5RhAti0UgM8703akGPJ6g== integrity sha512-Kl29QoNbNvn4nhDsLYjyIAaIqaJB6rBx5p3sL9VjaefJ+eMFBWVZiaoguaoZfzEKr5RhAti0UgM8703akGPJ6g==
fast-glob@^3.2.11, fast-glob@^3.2.12, fast-glob@^3.2.7: fast-glob@^3.2.11, fast-glob@^3.2.12, fast-glob@^3.2.5, fast-glob@^3.2.7:
version "3.2.12" version "3.2.12"
resolved "https://registry.npmmirror.com/fast-glob/-/fast-glob-3.2.12.tgz#7f39ec99c2e6ab030337142da9e0c18f37afae80" resolved "https://registry.npmmirror.com/fast-glob/-/fast-glob-3.2.12.tgz#7f39ec99c2e6ab030337142da9e0c18f37afae80"
integrity sha512-DVj4CQIYYow0BlaelwK1pHl5n5cRSJfM60UA0zK891sVInoPri2Ekj7+e1CT3/3qxXenpI+nBBmQAcJPJgaj4w== integrity sha512-DVj4CQIYYow0BlaelwK1pHl5n5cRSJfM60UA0zK891sVInoPri2Ekj7+e1CT3/3qxXenpI+nBBmQAcJPJgaj4w==
@@ -2765,6 +2921,11 @@ is-glob@^4.0.1, is-glob@~4.0.1:
dependencies: dependencies:
is-extglob "^2.1.1" is-extglob "^2.1.1"
is-https@^4.0.0:
version "4.0.0"
resolved "https://registry.npmmirror.com/is-https/-/is-https-4.0.0.tgz#9ee725a334fb517b988278d2674efc96e4f348ed"
integrity sha512-FeMLiqf8E5g6SdiVJsPcNZX8k4h2fBs1wp5Bb6uaNxn58ufK1axBqQZdmAQsqh0t9BuwFObybrdVJh6MKyPlyg==
is-interactive@^2.0.0: is-interactive@^2.0.0:
version "2.0.0" version "2.0.0"
resolved "https://registry.npmmirror.com/is-interactive/-/is-interactive-2.0.0.tgz#40c57614593826da1100ade6059778d597f16e90" resolved "https://registry.npmmirror.com/is-interactive/-/is-interactive-2.0.0.tgz#40c57614593826da1100ade6059778d597f16e90"
@@ -2865,11 +3026,23 @@ jiti@^1.17.0:
resolved "https://registry.npmmirror.com/jiti/-/jiti-1.17.0.tgz#9a4e1787b9d83e594a5ad27cdf9c9ab555112ac1" resolved "https://registry.npmmirror.com/jiti/-/jiti-1.17.0.tgz#9a4e1787b9d83e594a5ad27cdf9c9ab555112ac1"
integrity sha512-CByzPgFqYoB9odEeef7GNmQ3S5THIBOtzRYoSCya2Sv27AuQxy2jgoFjQ6VTF53xsq1MXRm+YWNvOoDHUAteOw== integrity sha512-CByzPgFqYoB9odEeef7GNmQ3S5THIBOtzRYoSCya2Sv27AuQxy2jgoFjQ6VTF53xsq1MXRm+YWNvOoDHUAteOw==
js-cookie@^3.0.1:
version "3.0.1"
resolved "https://registry.npmmirror.com/js-cookie/-/js-cookie-3.0.1.tgz#9e39b4c6c2f56563708d7d31f6f5f21873a92414"
integrity sha512-+0rgsUXZu4ncpPxRL+lNEptWMOWl9etvPHc/koSRp6MPwpRYAhmk0dUG00J4bxVV3r9uUzfo24wW0knS07SKSw==
js-tokens@^4.0.0: js-tokens@^4.0.0:
version "4.0.0" version "4.0.0"
resolved "https://registry.npmmirror.com/js-tokens/-/js-tokens-4.0.0.tgz#19203fb59991df98e3a287050d4647cdeaf32499" resolved "https://registry.npmmirror.com/js-tokens/-/js-tokens-4.0.0.tgz#19203fb59991df98e3a287050d4647cdeaf32499"
integrity sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ== integrity sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==
js-yaml@^4.1.0:
version "4.1.0"
resolved "https://registry.npmmirror.com/js-yaml/-/js-yaml-4.1.0.tgz#c1fb65f8f5017901cdd2c951864ba18458a10602"
integrity sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==
dependencies:
argparse "^2.0.1"
jsesc@^2.5.1: jsesc@^2.5.1:
version "2.5.2" version "2.5.2"
resolved "https://registry.npmmirror.com/jsesc/-/jsesc-2.5.2.tgz#80564d2e483dacf6e8ef209650a67df3f0c283a4" resolved "https://registry.npmmirror.com/jsesc/-/jsesc-2.5.2.tgz#80564d2e483dacf6e8ef209650a67df3f0c283a4"
@@ -2885,11 +3058,22 @@ json-schema-traverse@^1.0.0:
resolved "https://registry.npmmirror.com/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz#ae7bcb3656ab77a73ba5c49bf654f38e6b6860e2" resolved "https://registry.npmmirror.com/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz#ae7bcb3656ab77a73ba5c49bf654f38e6b6860e2"
integrity sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug== integrity sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==
json5@^2.2.2: json5@^2.2.0, json5@^2.2.2:
version "2.2.3" version "2.2.3"
resolved "https://registry.npmmirror.com/json5/-/json5-2.2.3.tgz#78cd6f1a19bdc12b73db5ad0c61efd66c1e29283" resolved "https://registry.npmmirror.com/json5/-/json5-2.2.3.tgz#78cd6f1a19bdc12b73db5ad0c61efd66c1e29283"
integrity sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg== integrity sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==
jsonc-eslint-parser@^1.0.1:
version "1.4.1"
resolved "https://registry.npmmirror.com/jsonc-eslint-parser/-/jsonc-eslint-parser-1.4.1.tgz#8cbe99f6f5199acbc5a823c4c0b6135411027fa6"
integrity sha512-hXBrvsR1rdjmB2kQmUjf1rEIa+TqHBGMge8pwi++C+Si1ad7EjZrJcpgwym+QGK/pqTx+K7keFAtLlVNdLRJOg==
dependencies:
acorn "^7.4.1"
eslint-utils "^2.1.0"
eslint-visitor-keys "^1.3.0"
espree "^6.0.0"
semver "^6.3.0"
jsonc-parser@^3.2.0: jsonc-parser@^3.2.0:
version "3.2.0" version "3.2.0"
resolved "https://registry.npmmirror.com/jsonc-parser/-/jsonc-parser-3.2.0.tgz#31ff3f4c2b9793f89c67212627c51c6394f88e76" resolved "https://registry.npmmirror.com/jsonc-parser/-/jsonc-parser-3.2.0.tgz#31ff3f4c2b9793f89c67212627c51c6394f88e76"
@@ -3047,7 +3231,7 @@ lodash.uniq@^4.5.0:
resolved "https://registry.npmmirror.com/lodash.uniq/-/lodash.uniq-4.5.0.tgz#d0225373aeb652adc1bc82e4945339a842754773" resolved "https://registry.npmmirror.com/lodash.uniq/-/lodash.uniq-4.5.0.tgz#d0225373aeb652adc1bc82e4945339a842754773"
integrity sha512-xfBaXQd9ryd9dlSDvnvI0lvxfLJlYAZzXomUYzLKtUeOQvOP5piqAWuGtrhWeqaXK9hhoM/iyJc5AV+XfsX3HQ== integrity sha512-xfBaXQd9ryd9dlSDvnvI0lvxfLJlYAZzXomUYzLKtUeOQvOP5piqAWuGtrhWeqaXK9hhoM/iyJc5AV+XfsX3HQ==
lodash@^4.17.21: lodash@^4.17.20, lodash@^4.17.21:
version "4.17.21" version "4.17.21"
resolved "https://registry.npmmirror.com/lodash/-/lodash-4.17.21.tgz#679591c564c3bffaae8454cf0b3df370c3d6911c" resolved "https://registry.npmmirror.com/lodash/-/lodash-4.17.21.tgz#679591c564c3bffaae8454cf0b3df370c3d6911c"
integrity sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg== integrity sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==
@@ -3266,7 +3450,7 @@ nanoid@^3.3.4:
resolved "https://registry.npmmirror.com/nanoid/-/nanoid-3.3.4.tgz#730b67e3cd09e2deacf03c027c81c9d9dbc5e8ab" resolved "https://registry.npmmirror.com/nanoid/-/nanoid-3.3.4.tgz#730b67e3cd09e2deacf03c027c81c9d9dbc5e8ab"
integrity sha512-MqBkQh/OHTS2egovRtLk45wEyNXwF+cokD+1YPf9u5VfJiRdAiRwB2froX5Co9Rh20xs4siNPm8naNotSD6RBw== integrity sha512-MqBkQh/OHTS2egovRtLk45wEyNXwF+cokD+1YPf9u5VfJiRdAiRwB2froX5Co9Rh20xs4siNPm8naNotSD6RBw==
nanoid@^4.0.0: nanoid@^4.0.0, nanoid@^4.0.1:
version "4.0.1" version "4.0.1"
resolved "https://registry.npmmirror.com/nanoid/-/nanoid-4.0.1.tgz#398d7ccfdbf9faf2231b2ca7e8fff5dbca6a509b" resolved "https://registry.npmmirror.com/nanoid/-/nanoid-4.0.1.tgz#398d7ccfdbf9faf2231b2ca7e8fff5dbca6a509b"
integrity sha512-udKGtCCUafD3nQtJg9wBhRP3KMbPglUsgV5JVsXhvyBs/oefqb4sqMEhKBBgqZncYowu58p1prsZQBYvAj/Gww== integrity sha512-udKGtCCUafD3nQtJg9wBhRP3KMbPglUsgV5JVsXhvyBs/oefqb4sqMEhKBBgqZncYowu58p1prsZQBYvAj/Gww==
@@ -4325,7 +4509,7 @@ source-map-support@^0.5.21, source-map-support@~0.5.20:
buffer-from "^1.0.0" buffer-from "^1.0.0"
source-map "^0.6.0" source-map "^0.6.0"
source-map@^0.6.0, source-map@^0.6.1: source-map@0.6.1, source-map@^0.6.0, source-map@^0.6.1:
version "0.6.1" version "0.6.1"
resolved "https://registry.npmmirror.com/source-map/-/source-map-0.6.1.tgz#74722af32e9614e9c287a8d0bbde48b5e2f1a263" resolved "https://registry.npmmirror.com/source-map/-/source-map-0.6.1.tgz#74722af32e9614e9c287a8d0bbde48b5e2f1a263"
integrity sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g== integrity sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==
@@ -4830,11 +5014,37 @@ vue-bundle-renderer@^1.0.1:
dependencies: dependencies:
ufo "^1.0.1" ufo "^1.0.1"
vue-demi@^0.13.11, vue-demi@^0.13.5:
version "0.13.11"
resolved "https://registry.npmmirror.com/vue-demi/-/vue-demi-0.13.11.tgz#7d90369bdae8974d87b1973564ad390182410d99"
integrity sha512-IR8HoEEGM65YY3ZJYAjMlKygDQn25D5ajNFNoKh9RSDMQtlzCxtfQjdQgv9jjK+m3377SsJXY8ysq8kLCZL25A==
vue-devtools-stub@^0.1.0: vue-devtools-stub@^0.1.0:
version "0.1.0" version "0.1.0"
resolved "https://registry.npmmirror.com/vue-devtools-stub/-/vue-devtools-stub-0.1.0.tgz#a65b9485edecd4273cedcb8102c739b83add2c81" resolved "https://registry.npmmirror.com/vue-devtools-stub/-/vue-devtools-stub-0.1.0.tgz#a65b9485edecd4273cedcb8102c739b83add2c81"
integrity sha512-RutnB7X8c5hjq39NceArgXg28WZtZpGc3+J16ljMiYnFhKvd8hITxSWQSQ5bvldxMDU6gG5mkxl1MTQLXckVSQ== integrity sha512-RutnB7X8c5hjq39NceArgXg28WZtZpGc3+J16ljMiYnFhKvd8hITxSWQSQ5bvldxMDU6gG5mkxl1MTQLXckVSQ==
vue-i18n-routing@^0.10.2:
version "0.10.3"
resolved "https://registry.npmmirror.com/vue-i18n-routing/-/vue-i18n-routing-0.10.3.tgz#708191af565b27744fb74e5af357409dc8c3b690"
integrity sha512-U+tD43Lbv1+ZrMW2lDwF/suYfHc+ezeDZXSkyQOMcmsm/Brfw8CwpAx822Ur8SKYeUjsNLhIyEn9QX8df/Ey+Q==
dependencies:
"@intlify/shared" next
"@intlify/vue-i18n-bridge" "^0.8.0"
"@intlify/vue-router-bridge" "^0.8.0"
ufo "^1.0.0"
vue-demi "^0.13.11"
vue-i18n@9.3.0-beta.16:
version "9.3.0-beta.16"
resolved "https://registry.npmmirror.com/vue-i18n/-/vue-i18n-9.3.0-beta.16.tgz#7d48c2a16087e47e388e1cd43a95ae38071a8c3d"
integrity sha512-huhBeRB0SEvv2gIgCS7Zo06nb8AAhbPQCoB/vwDfbDNs8F+giv9QCmhEed+TkLTih/54JGnXkxN6tw1VZqVY/w==
dependencies:
"@intlify/core-base" "9.3.0-beta.16"
"@intlify/shared" "9.3.0-beta.16"
"@intlify/vue-devtools" "9.3.0-beta.16"
"@vue/devtools-api" "^6.2.1"
vue-router@^4.1.6: vue-router@^4.1.6:
version "4.1.6" version "4.1.6"
resolved "https://registry.npmmirror.com/vue-router/-/vue-router-4.1.6.tgz#b70303737e12b4814578d21d68d21618469375a1" resolved "https://registry.npmmirror.com/vue-router/-/vue-router-4.1.6.tgz#b70303737e12b4814578d21d68d21618469375a1"
@@ -4964,7 +5174,16 @@ yallist@^4.0.0:
resolved "https://registry.npmmirror.com/yallist/-/yallist-4.0.0.tgz#9bb92790d9c0effec63be73519e11a35019a3a72" resolved "https://registry.npmmirror.com/yallist/-/yallist-4.0.0.tgz#9bb92790d9c0effec63be73519e11a35019a3a72"
integrity sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A== integrity sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==
yaml@^1.10.2: yaml-eslint-parser@^0.3.2:
version "0.3.2"
resolved "https://registry.npmmirror.com/yaml-eslint-parser/-/yaml-eslint-parser-0.3.2.tgz#c7f5f3904f1c06ad55dc7131a731b018426b4898"
integrity sha512-32kYO6kJUuZzqte82t4M/gB6/+11WAuHiEnK7FreMo20xsCKPeFH5tDBU7iWxR7zeJpNnMXfJyXwne48D0hGrg==
dependencies:
eslint-visitor-keys "^1.3.0"
lodash "^4.17.20"
yaml "^1.10.0"
yaml@^1.10.0, yaml@^1.10.2:
version "1.10.2" version "1.10.2"
resolved "https://registry.npmmirror.com/yaml/-/yaml-1.10.2.tgz#2301c5ffbf12b467de8da2333a459e29e7920e4b" resolved "https://registry.npmmirror.com/yaml/-/yaml-1.10.2.tgz#2301c5ffbf12b467de8da2333a459e29e7920e4b"
integrity sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg== integrity sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg==