@movk/nuxt-docs 1.6.2 → 1.7.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/app/app.config.ts +37 -0
- package/app/app.vue +8 -3
- package/app/components/DocsAsideRightBottom.vue +17 -22
- package/app/components/PageHeaderLinks.vue +6 -1
- package/app/components/content/PageLastCommit.vue +5 -5
- package/app/components/header/Header.vue +1 -1
- package/app/components/header/HeaderBody.vue +12 -2
- package/app/components/header/HeaderBottom.vue +1 -0
- package/app/components/header/HeaderCTA.vue +2 -2
- package/app/components/header/HeaderCenter.vue +1 -1
- package/app/components/header/HeaderLogo.vue +1 -1
- package/app/layouts/default.vue +3 -1
- package/app/layouts/docs.vue +1 -1
- package/app/pages/docs/[...slug].vue +3 -2
- package/app/templates/releases.vue +98 -0
- package/app/types/index.d.ts +149 -0
- package/content.config.ts +24 -2
- package/modules/ai-chat/index.ts +53 -21
- package/modules/ai-chat/runtime/components/AiChat.vue +4 -10
- package/modules/ai-chat/runtime/components/AiChatDisabled.vue +3 -0
- package/modules/ai-chat/runtime/components/AiChatFloatingInput.vue +24 -9
- package/modules/ai-chat/runtime/components/AiChatModelSelect.vue +2 -0
- package/modules/ai-chat/runtime/components/AiChatPanel.vue +318 -0
- package/modules/ai-chat/runtime/components/AiChatPreStream.vue +1 -0
- package/modules/ai-chat/runtime/components/AiChatReasoning.vue +3 -3
- package/modules/ai-chat/runtime/components/AiChatSlideoverFaq.vue +2 -5
- package/modules/ai-chat/runtime/composables/useAIChat.ts +48 -0
- package/modules/ai-chat/runtime/composables/useModels.ts +3 -6
- package/modules/ai-chat/runtime/server/api/ai-chat.ts +40 -32
- package/modules/ai-chat/runtime/server/utils/docs_agent.ts +23 -15
- package/modules/ai-chat/runtime/types.ts +6 -0
- package/modules/css.ts +3 -2
- package/modules/routing.ts +26 -0
- package/nuxt.config.ts +2 -0
- package/nuxt.schema.ts +493 -0
- package/package.json +11 -9
- package/app/composables/useFaq.ts +0 -21
- package/modules/ai-chat/runtime/components/AiChatSlideover.vue +0 -255
- /package/{app → modules/ai-chat/runtime}/composables/useHighlighter.ts +0 -0
|
@@ -1,255 +0,0 @@
|
|
|
1
|
-
<script setup lang="ts">
|
|
2
|
-
import type { DefineComponent } from 'vue'
|
|
3
|
-
import { Chat } from '@ai-sdk/vue'
|
|
4
|
-
import { DefaultChatTransport } from 'ai'
|
|
5
|
-
import AiChatPreStream from './AiChatPreStream.vue'
|
|
6
|
-
import type { FaqCategory } from './AiChatSlideoverFaq.vue'
|
|
7
|
-
|
|
8
|
-
const {
|
|
9
|
-
title = 'AI 助手',
|
|
10
|
-
description = ' ',
|
|
11
|
-
placeholder = '输入你的问题...',
|
|
12
|
-
faqQuestions = []
|
|
13
|
-
} = defineProps<{
|
|
14
|
-
/**
|
|
15
|
-
* 标题栏显示的标题
|
|
16
|
-
* @defaultValue AI 助手
|
|
17
|
-
*/
|
|
18
|
-
title?: string
|
|
19
|
-
/**
|
|
20
|
-
* 标题栏显示的描述
|
|
21
|
-
* @defaultValue ' '
|
|
22
|
-
*/
|
|
23
|
-
description?: string
|
|
24
|
-
/**
|
|
25
|
-
* 输入框占位符文本
|
|
26
|
-
* @defaultValue 输入你的问题...
|
|
27
|
-
*/
|
|
28
|
-
placeholder?: string
|
|
29
|
-
/**
|
|
30
|
-
* 聊天为空时显示的常见问题分类
|
|
31
|
-
* @defaultValue []
|
|
32
|
-
*/
|
|
33
|
-
faqQuestions?: FaqCategory[]
|
|
34
|
-
}>()
|
|
35
|
-
|
|
36
|
-
const components = {
|
|
37
|
-
pre: AiChatPreStream as unknown as DefineComponent
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
const { messages, isOpen, pendingMessage, clearPending } = useAIChat()
|
|
41
|
-
const { apiPath } = useRuntimeConfig().public.aiChat
|
|
42
|
-
|
|
43
|
-
const { tools } = useToolCall()
|
|
44
|
-
function getToolLabel(toolName: string, args?: any): string {
|
|
45
|
-
const label = tools[toolName]
|
|
46
|
-
|
|
47
|
-
if (!label) {
|
|
48
|
-
return toolName
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
return typeof label === 'function' ? label(args) : label
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
const { model } = useModels()
|
|
55
|
-
|
|
56
|
-
const input = ref('')
|
|
57
|
-
|
|
58
|
-
watch(pendingMessage, (message) => {
|
|
59
|
-
if (message) {
|
|
60
|
-
if (messages.value.length === 0 && chat.messages.length > 0) {
|
|
61
|
-
chat.messages.length = 0
|
|
62
|
-
}
|
|
63
|
-
chat.sendMessage({
|
|
64
|
-
text: message
|
|
65
|
-
})
|
|
66
|
-
clearPending()
|
|
67
|
-
}
|
|
68
|
-
}, { immediate: true })
|
|
69
|
-
|
|
70
|
-
watch(messages, (newMessages) => {
|
|
71
|
-
if (newMessages.length === 0 && chat.messages.length > 0) {
|
|
72
|
-
chat.messages.length = 0
|
|
73
|
-
}
|
|
74
|
-
}, { deep: true })
|
|
75
|
-
|
|
76
|
-
const toast = useToast()
|
|
77
|
-
const lastMessage = computed(() => chat.messages.at(-1))
|
|
78
|
-
|
|
79
|
-
const chat = new Chat({
|
|
80
|
-
messages: messages.value,
|
|
81
|
-
transport: new DefaultChatTransport({
|
|
82
|
-
api: apiPath,
|
|
83
|
-
body: () => ({ model: model.value })
|
|
84
|
-
}),
|
|
85
|
-
onError(error) {
|
|
86
|
-
const { message } = typeof error.message === 'string' && error.message[0] === '{' ? JSON.parse(error.message) : error
|
|
87
|
-
toast.add({
|
|
88
|
-
description: message,
|
|
89
|
-
icon: 'i-lucide-circle-alert',
|
|
90
|
-
color: 'error',
|
|
91
|
-
duration: 0
|
|
92
|
-
})
|
|
93
|
-
},
|
|
94
|
-
onFinish: () => {
|
|
95
|
-
messages.value = chat.messages
|
|
96
|
-
}
|
|
97
|
-
})
|
|
98
|
-
|
|
99
|
-
function handleSubmit(event?: Event) {
|
|
100
|
-
event?.preventDefault()
|
|
101
|
-
|
|
102
|
-
if (!input.value.trim()) {
|
|
103
|
-
return
|
|
104
|
-
}
|
|
105
|
-
|
|
106
|
-
chat.sendMessage({
|
|
107
|
-
text: input.value
|
|
108
|
-
})
|
|
109
|
-
|
|
110
|
-
input.value = ''
|
|
111
|
-
}
|
|
112
|
-
|
|
113
|
-
function askQuestion(question: string) {
|
|
114
|
-
chat.sendMessage({
|
|
115
|
-
text: question
|
|
116
|
-
})
|
|
117
|
-
}
|
|
118
|
-
|
|
119
|
-
function resetChat() {
|
|
120
|
-
chat.stop()
|
|
121
|
-
messages.value = []
|
|
122
|
-
chat.messages.length = 0
|
|
123
|
-
}
|
|
124
|
-
|
|
125
|
-
onMounted(() => {
|
|
126
|
-
if (pendingMessage.value) {
|
|
127
|
-
chat.sendMessage({
|
|
128
|
-
text: pendingMessage.value
|
|
129
|
-
})
|
|
130
|
-
clearPending()
|
|
131
|
-
} else if (chat.lastMessage?.role === 'user') {
|
|
132
|
-
chat.regenerate()
|
|
133
|
-
}
|
|
134
|
-
})
|
|
135
|
-
</script>
|
|
136
|
-
|
|
137
|
-
<template>
|
|
138
|
-
<USlideover
|
|
139
|
-
v-model:open="isOpen"
|
|
140
|
-
:description="description"
|
|
141
|
-
:close="{ size: 'sm' }"
|
|
142
|
-
:ui="{
|
|
143
|
-
body: 'flex p-4!',
|
|
144
|
-
title: 'flex w-100 pr-6',
|
|
145
|
-
overlay: 'bg-default/60 backdrop-blur-sm',
|
|
146
|
-
content: 'w-full sm:max-w-md bg-default/95 backdrop-blur-xl shadow-2xl'
|
|
147
|
-
}"
|
|
148
|
-
>
|
|
149
|
-
<template #title>
|
|
150
|
-
<div class="flex items-center gap-2 flex-1">
|
|
151
|
-
<UBadge icon="i-lucide-sparkles" variant="soft" square />
|
|
152
|
-
<span class="font-medium text-highlighted">{{ title }}</span>
|
|
153
|
-
</div>
|
|
154
|
-
|
|
155
|
-
<div class="flex items-center gap-2">
|
|
156
|
-
<UTooltip v-if="chat.messages.length > 0" text="清空聊天">
|
|
157
|
-
<UButton
|
|
158
|
-
icon="i-lucide-trash-2"
|
|
159
|
-
color="neutral"
|
|
160
|
-
variant="ghost"
|
|
161
|
-
size="sm"
|
|
162
|
-
@click="resetChat"
|
|
163
|
-
/>
|
|
164
|
-
</UTooltip>
|
|
165
|
-
</div>
|
|
166
|
-
</template>
|
|
167
|
-
|
|
168
|
-
<template #body>
|
|
169
|
-
<UChatPalette class="flex-1" :ui="{ prompt: 'border-0 px-2.5' }">
|
|
170
|
-
<UChatMessages
|
|
171
|
-
v-if="chat.messages.length > 0"
|
|
172
|
-
should-auto-scroll
|
|
173
|
-
:messages="chat.messages"
|
|
174
|
-
compact
|
|
175
|
-
:status="chat.status"
|
|
176
|
-
:user="{ ui: { container: 'pb-2', content: 'text-sm' } }"
|
|
177
|
-
:ui="{ indicator: '*:bg-accented' }"
|
|
178
|
-
>
|
|
179
|
-
<template #content="{ message }">
|
|
180
|
-
<div class="flex flex-col gap-2">
|
|
181
|
-
<template
|
|
182
|
-
v-for="(part, index) in message.parts"
|
|
183
|
-
:key="`${message.id}-${part.type}-${index}${'state' in part ? `-${part.state}` : ''}`"
|
|
184
|
-
>
|
|
185
|
-
<AiChatReasoning v-if="part.type === 'reasoning'" :text="part.text" :is-streaming="part.state !== 'done'" />
|
|
186
|
-
<MDCCached
|
|
187
|
-
v-else-if="part.type === 'text'"
|
|
188
|
-
:value="part.text"
|
|
189
|
-
:cache-key="`${message.id}-${index}`"
|
|
190
|
-
:components="components"
|
|
191
|
-
:parser-options="{ highlight: false }"
|
|
192
|
-
class="*:first:mt-0 *:last:mb-0"
|
|
193
|
-
/>
|
|
194
|
-
<template v-else-if="part.type === 'data-tool-calls'">
|
|
195
|
-
<AiChatToolCall
|
|
196
|
-
v-for="tool in (part as any).data.tools"
|
|
197
|
-
:key="tool.toolCallId"
|
|
198
|
-
:text="getToolLabel(tool.toolName, tool.input)"
|
|
199
|
-
:is-loading="false"
|
|
200
|
-
/>
|
|
201
|
-
</template>
|
|
202
|
-
</template>
|
|
203
|
-
<UButton
|
|
204
|
-
v-if="chat.status === 'streaming' && message.id === lastMessage?.id"
|
|
205
|
-
class="px-0"
|
|
206
|
-
color="neutral"
|
|
207
|
-
variant="link"
|
|
208
|
-
size="sm"
|
|
209
|
-
label="Loading..."
|
|
210
|
-
loading
|
|
211
|
-
loading-icon="i-lucide-loader"
|
|
212
|
-
/>
|
|
213
|
-
</div>
|
|
214
|
-
</template>
|
|
215
|
-
</UChatMessages>
|
|
216
|
-
<div v-else class="flex-1 overflow-y-auto px-4 py-4">
|
|
217
|
-
<p class="text-sm font-medium text-muted mb-4">
|
|
218
|
-
FAQ 建议
|
|
219
|
-
</p>
|
|
220
|
-
<AiChatSlideoverFaq :faq-questions="faqQuestions" @ask-question="askQuestion" />
|
|
221
|
-
</div>
|
|
222
|
-
<template #prompt>
|
|
223
|
-
<UChatPrompt
|
|
224
|
-
v-model="input"
|
|
225
|
-
:error="chat.error"
|
|
226
|
-
:placeholder="placeholder"
|
|
227
|
-
variant="subtle"
|
|
228
|
-
class="[view-transition-name:chat-prompt]"
|
|
229
|
-
:ui="{ base: 'px-1.5 text-sm' }"
|
|
230
|
-
@submit="handleSubmit"
|
|
231
|
-
>
|
|
232
|
-
<template #footer>
|
|
233
|
-
<div class="flex items-center gap-1">
|
|
234
|
-
<AiChatModelSelect v-model="model" />
|
|
235
|
-
<div class="flex gap-1 justify-between items-center px-1 text-xs text-dimmed">
|
|
236
|
-
换行
|
|
237
|
-
<UKbd value="shift" />
|
|
238
|
-
<UKbd value="enter" />
|
|
239
|
-
</div>
|
|
240
|
-
</div>
|
|
241
|
-
|
|
242
|
-
<UChatPromptSubmit
|
|
243
|
-
:status="chat.status"
|
|
244
|
-
color="neutral"
|
|
245
|
-
size="sm"
|
|
246
|
-
@stop="chat.stop()"
|
|
247
|
-
@reload="chat.regenerate()"
|
|
248
|
-
/>
|
|
249
|
-
</template>
|
|
250
|
-
</UChatPrompt>
|
|
251
|
-
</template>
|
|
252
|
-
</UChatPalette>
|
|
253
|
-
</template>
|
|
254
|
-
</USlideover>
|
|
255
|
-
</template>
|
|
File without changes
|