docus 5.12.1 → 5.12.2

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.
Files changed (55) hide show
  1. package/app/app.config.ts +7 -16
  2. package/app/components/app/AppHeaderBody.vue +14 -1
  3. package/app/components/app/AppHeaderCenter.vue +1 -1
  4. package/app/components/docs/DocsAsideLeftBody.vue +1 -0
  5. package/app/components/docs/DocsAsideMobileBar.vue +4 -4
  6. package/app/components/docs/DocsAsideRight.vue +1 -1
  7. package/app/composables/useSubNavigation.ts +1 -1
  8. package/app/composables/useUIConfig.ts +1 -1
  9. package/app/utils/assistantTools.ts +88 -0
  10. package/i18n/locales/ar.json +15 -1
  11. package/i18n/locales/be.json +15 -1
  12. package/i18n/locales/bg.json +15 -1
  13. package/i18n/locales/bn.json +15 -1
  14. package/i18n/locales/ca.json +15 -1
  15. package/i18n/locales/ckb.json +15 -1
  16. package/i18n/locales/cs.json +15 -1
  17. package/i18n/locales/da.json +15 -1
  18. package/i18n/locales/de.json +15 -1
  19. package/i18n/locales/el.json +15 -1
  20. package/i18n/locales/en.json +15 -1
  21. package/i18n/locales/es.json +15 -1
  22. package/i18n/locales/et.json +15 -1
  23. package/i18n/locales/fi.json +15 -1
  24. package/i18n/locales/fr.json +15 -1
  25. package/i18n/locales/he.json +15 -1
  26. package/i18n/locales/hi.json +15 -1
  27. package/i18n/locales/hy.json +15 -1
  28. package/i18n/locales/id.json +15 -1
  29. package/i18n/locales/it.json +15 -1
  30. package/i18n/locales/ja.json +15 -1
  31. package/i18n/locales/kk.json +15 -1
  32. package/i18n/locales/km.json +15 -1
  33. package/i18n/locales/ko.json +15 -1
  34. package/i18n/locales/ky.json +15 -1
  35. package/i18n/locales/lb.json +15 -1
  36. package/i18n/locales/ms.json +15 -1
  37. package/i18n/locales/nb.json +15 -1
  38. package/i18n/locales/nl.json +15 -1
  39. package/i18n/locales/pl.json +15 -1
  40. package/i18n/locales/pt-BR.json +15 -1
  41. package/i18n/locales/ro.json +15 -1
  42. package/i18n/locales/ru.json +15 -1
  43. package/i18n/locales/si.json +15 -1
  44. package/i18n/locales/sl.json +15 -1
  45. package/i18n/locales/sv.json +15 -1
  46. package/i18n/locales/tr.json +15 -1
  47. package/i18n/locales/uk.json +15 -1
  48. package/i18n/locales/ur.json +15 -1
  49. package/i18n/locales/vi.json +15 -1
  50. package/i18n/locales/zh-CN.json +15 -1
  51. package/modules/assistant/runtime/components/AssistantFloatingInput.vue +13 -2
  52. package/modules/assistant/runtime/components/AssistantIndicator.vue +15 -6
  53. package/modules/assistant/runtime/components/AssistantPanel.vue +13 -42
  54. package/modules/assistant/runtime/server/api/search.ts +14 -16
  55. package/package.json +15 -15
@@ -43,7 +43,6 @@
43
43
  "close": "වසන්න",
44
44
  "expand": "පුළුල් කරන්න",
45
45
  "collapse": "හකුළන්න",
46
- "thinking": "සිතමින්...",
47
46
  "askMeAnything": "ඕන දෙයක් අහන්න",
48
47
  "askMeAnythingDescription": "ලේඛන සැරිසැරීමට, සංකල්ප තේරුම් ගැනීමට සහ පිළිතුරු සෙවීමට උදවු ලබා ගන්න.",
49
48
  "faq": "නිතර අසන පැන",
@@ -52,7 +51,22 @@
52
51
  "explainWithAi": "AI සමඟ පැහැදිලි කරන්න",
53
52
  "toolListPages": "ලැයිස්තුගත ලේඛන පිටු",
54
53
  "toolReadPage": "කියවන්න",
54
+ "tools": {
55
+ "searching": "සොයමින්",
56
+ "searched": "සෙව්වා",
57
+ "reading": "කියවමින්",
58
+ "read": "කියෙව්වා",
59
+ "finding": "සොයමින්",
60
+ "found": "හමු විය",
61
+ "opening": "විවෘත කරමින්",
62
+ "opened": "විවෘත කළා",
63
+ "generating": "ජනනය කරමින්",
64
+ "generated": "ජනනය කළා",
65
+ "creating": "සාදමින්",
66
+ "created": "සෑදුවා"
67
+ },
55
68
  "loading": {
69
+ "thinking": "සිතමින්...",
56
70
  "searching": "ලේඛන සෙවීම",
57
71
  "reading": "ලේඛන හරහා කියවීම",
58
72
  "analyzing": "අන්තර්ගතය විශ්ලේෂණය කිරීම",
@@ -43,7 +43,6 @@
43
43
  "close": "Zapri",
44
44
  "expand": "Razširi",
45
45
  "collapse": "Strni",
46
- "thinking": "Razmišljanje...",
47
46
  "askMeAnything": "Vprašaj karkoli",
48
47
  "askMeAnythingDescription": "Poiščite pomoč pri krmarjenju po dokumentaciji, razumevanju konceptov in iskanju odgovorov.",
49
48
  "faq": "Pogosta vprašanja",
@@ -52,7 +51,22 @@
52
51
  "explainWithAi": "Razloži z AI",
53
52
  "toolListPages": "Navedene strani dokumentacije",
54
53
  "toolReadPage": "Preberi",
54
+ "tools": {
55
+ "searching": "Iskanje",
56
+ "searched": "Najdeno",
57
+ "reading": "Branje",
58
+ "read": "Prebrano",
59
+ "finding": "Iskanje",
60
+ "found": "Najdeno",
61
+ "opening": "Odpiranje",
62
+ "opened": "Odprto",
63
+ "generating": "Generiranje",
64
+ "generated": "Generirano",
65
+ "creating": "Ustvarjanje",
66
+ "created": "Ustvarjeno"
67
+ },
55
68
  "loading": {
69
+ "thinking": "Razmišljanje...",
56
70
  "searching": "Iskanje po dokumentaciji",
57
71
  "reading": "Prebiranje dokumentov",
58
72
  "analyzing": "Analiza vsebine",
@@ -43,7 +43,6 @@
43
43
  "close": "Stäng",
44
44
  "expand": "Expandera",
45
45
  "collapse": "Kollapsa",
46
- "thinking": "Funderar...",
47
46
  "askMeAnything": "Fråga vad som helst",
48
47
  "askMeAnythingDescription": "Få hjälp med att navigera i dokumentationen, förstå begrepp och hitta svar.",
49
48
  "faq": "FAQ",
@@ -52,7 +51,22 @@
52
51
  "explainWithAi": "Förklara med AI",
53
52
  "toolListPages": "Listade dokumentationssidor",
54
53
  "toolReadPage": "Läs",
54
+ "tools": {
55
+ "searching": "Söker",
56
+ "searched": "Sökt",
57
+ "reading": "Läser",
58
+ "read": "Läst",
59
+ "finding": "Söker",
60
+ "found": "Hittade",
61
+ "opening": "Öppnar",
62
+ "opened": "Öppnad",
63
+ "generating": "Genererar",
64
+ "generated": "Genererad",
65
+ "creating": "Skapar",
66
+ "created": "Skapad"
67
+ },
55
68
  "loading": {
69
+ "thinking": "Funderar...",
56
70
  "searching": "Söker i dokumentationen",
57
71
  "reading": "Läser igenom dokumenten",
58
72
  "analyzing": "Analysera innehållet",
@@ -43,7 +43,6 @@
43
43
  "close": "Kapat",
44
44
  "expand": "Genişlet",
45
45
  "collapse": "Daralt",
46
- "thinking": "Düşünüyorum...",
47
46
  "askMeAnything": "Her şeyi sor",
48
47
  "askMeAnythingDescription": "Belgelerde gezinme, kavramları anlama ve yanıt bulma konusunda yardım alın.",
49
48
  "faq": "SSS",
@@ -52,7 +51,22 @@
52
51
  "explainWithAi": "Yapay zeka ile açıklayın",
53
52
  "toolListPages": "Listelenen dokümantasyon sayfaları",
54
53
  "toolReadPage": "Oku",
54
+ "tools": {
55
+ "searching": "Aranıyor",
56
+ "searched": "Arandı",
57
+ "reading": "Okunuyor",
58
+ "read": "Okundu",
59
+ "finding": "Aranıyor",
60
+ "found": "Bulundu",
61
+ "opening": "Açılıyor",
62
+ "opened": "Açıldı",
63
+ "generating": "Üretiliyor",
64
+ "generated": "Üretildi",
65
+ "creating": "Oluşturuluyor",
66
+ "created": "Oluşturuldu"
67
+ },
55
68
  "loading": {
69
+ "thinking": "Düşünüyorum...",
56
70
  "searching": "Dokümantasyonda arama",
57
71
  "reading": "Dokümanlar okunuyor",
58
72
  "analyzing": "İçerik analiz ediliyor",
@@ -43,7 +43,6 @@
43
43
  "close": "Закрити",
44
44
  "expand": "Розгорнути",
45
45
  "collapse": "Згорнути",
46
- "thinking": "Думаючи...",
47
46
  "askMeAnything": "Запитайте будь-що",
48
47
  "askMeAnythingDescription": "Отримайте допомогу в навігації документацією, розумінні понять і пошуку відповідей.",
49
48
  "faq": "Поширені запитання",
@@ -52,7 +51,22 @@
52
51
  "explainWithAi": "Поясніть за допомогою ШІ",
53
52
  "toolListPages": "Перелічені сторінки документації",
54
53
  "toolReadPage": "Читати",
54
+ "tools": {
55
+ "searching": "Пошук",
56
+ "searched": "Знайдено",
57
+ "reading": "Читання",
58
+ "read": "Прочитано",
59
+ "finding": "Пошук",
60
+ "found": "Знайдено",
61
+ "opening": "Відкриття",
62
+ "opened": "Відкрито",
63
+ "generating": "Генерація",
64
+ "generated": "Згенеровано",
65
+ "creating": "Створення",
66
+ "created": "Створено"
67
+ },
55
68
  "loading": {
69
+ "thinking": "Думаючи...",
56
70
  "searching": "Пошук документації",
57
71
  "reading": "Читання документів",
58
72
  "analyzing": "Аналіз змісту",
@@ -43,7 +43,6 @@
43
43
  "close": "بند",
44
44
  "expand": "پھیلائیں۔",
45
45
  "collapse": "سمٹنا",
46
- "thinking": "سوچ رہا ہے...",
47
46
  "askMeAnything": "کچھ بھی پوچھو",
48
47
  "askMeAnythingDescription": "دستاویزات کو نیویگیٹ کرنے، تصورات کو سمجھنے اور جوابات تلاش کرنے میں مدد حاصل کریں۔",
49
48
  "faq": "اکثر پوچھے گئے سوالات",
@@ -52,7 +51,22 @@
52
51
  "explainWithAi": "AI کے ساتھ وضاحت کریں۔",
53
52
  "toolListPages": "درج دستاویزات کے صفحات",
54
53
  "toolReadPage": "پڑھیں",
54
+ "tools": {
55
+ "searching": "تلاش جاری",
56
+ "searched": "تلاش مکمل",
57
+ "reading": "پڑھ رہے ہیں",
58
+ "read": "پڑھا",
59
+ "finding": "تلاش جاری",
60
+ "found": "مل گیا",
61
+ "opening": "کھول رہے ہیں",
62
+ "opened": "کھولا",
63
+ "generating": "تیار کر رہے ہیں",
64
+ "generated": "تیار کیا",
65
+ "creating": "بنا رہے ہیں",
66
+ "created": "بنایا"
67
+ },
55
68
  "loading": {
69
+ "thinking": "سوچ رہا ہے...",
56
70
  "searching": "دستاویزات کی تلاش",
57
71
  "reading": "دستاویزات کے ذریعے پڑھنا",
58
72
  "analyzing": "مواد کا تجزیہ",
@@ -43,7 +43,6 @@
43
43
  "close": "Đóng",
44
44
  "expand": "Mở rộng",
45
45
  "collapse": "Thu gọn",
46
- "thinking": "Đang suy nghĩ...",
47
46
  "askMeAnything": "Hỏi bất cứ điều gì",
48
47
  "askMeAnythingDescription": "Nhận trợ giúp điều hướng tài liệu, hiểu các khái niệm và tìm câu trả lời.",
49
48
  "faq": "Câu hỏi thường gặp",
@@ -52,7 +51,22 @@
52
51
  "explainWithAi": "Giải thích bằng AI",
53
52
  "toolListPages": "Các trang tài liệu được liệt kê",
54
53
  "toolReadPage": "Đọc",
54
+ "tools": {
55
+ "searching": "Đang tìm",
56
+ "searched": "Đã tìm",
57
+ "reading": "Đang đọc",
58
+ "read": "Đã đọc",
59
+ "finding": "Đang tìm",
60
+ "found": "Đã tìm thấy",
61
+ "opening": "Đang mở",
62
+ "opened": "Đã mở",
63
+ "generating": "Đang tạo",
64
+ "generated": "Đã tạo",
65
+ "creating": "Đang tạo",
66
+ "created": "Đã tạo"
67
+ },
55
68
  "loading": {
69
+ "thinking": "Đang suy nghĩ...",
56
70
  "searching": "Tìm kiếm tài liệu",
57
71
  "reading": "Đọc qua tài liệu",
58
72
  "analyzing": "Phân tích nội dung",
@@ -43,7 +43,6 @@
43
43
  "close": "关闭",
44
44
  "expand": "展开",
45
45
  "collapse": "崩溃",
46
- "thinking": "想着……",
47
46
  "askMeAnything": "询问任何事情",
48
47
  "askMeAnythingDescription": "获取浏览文档、理解概念和寻找答案的帮助。",
49
48
  "faq": "常见问题解答",
@@ -52,7 +51,22 @@
52
51
  "explainWithAi": "用AI解释",
53
52
  "toolListPages": "列出的文档页面",
54
53
  "toolReadPage": "阅读",
54
+ "tools": {
55
+ "searching": "搜索中",
56
+ "searched": "已搜索",
57
+ "reading": "读取中",
58
+ "read": "已读取",
59
+ "finding": "搜索中",
60
+ "found": "已找到",
61
+ "opening": "打开中",
62
+ "opened": "已打开",
63
+ "generating": "生成中",
64
+ "generated": "已生成",
65
+ "creating": "创建中",
66
+ "created": "已创建"
67
+ },
55
68
  "loading": {
69
+ "thinking": "想着……",
56
70
  "searching": "搜索文档",
57
71
  "reading": "通读文档",
58
72
  "analyzing": "分析内容",
@@ -49,6 +49,18 @@ defineShortcuts(shortcuts)
49
49
  function onEscape() {
50
50
  inputRef.value?.inputRef?.blur()
51
51
  }
52
+
53
+ function onKeydown(event: KeyboardEvent) {
54
+ if (event.key === 'Enter' && !event.shiftKey && !event.altKey && !event.ctrlKey && !event.metaKey) {
55
+ event.preventDefault()
56
+ handleSubmit()
57
+ return
58
+ }
59
+
60
+ if (event.key === 'Escape') {
61
+ onEscape()
62
+ }
63
+ }
52
64
  </script>
53
65
 
54
66
  <template>
@@ -79,8 +91,7 @@ function onEscape() {
79
91
  base: 'bg-default shadow-lg rounded-xl text-base',
80
92
  trailing: 'pe-2',
81
93
  }"
82
- @keydown.enter.exact.prevent="handleSubmit"
83
- @keydown.escape="onEscape"
94
+ @keydown="onKeydown"
84
95
  >
85
96
  <template #trailing>
86
97
  <div class="flex items-center gap-2">
@@ -1,4 +1,8 @@
1
1
  <script setup lang="ts">
2
+ import { useDocusI18n } from '../../../../app/composables/useDocusI18n'
3
+
4
+ const { t } = useDocusI18n()
5
+
2
6
  const size = 4
3
7
  const dotSize = 2
4
8
  const gap = 2
@@ -32,9 +36,14 @@ function nextStep() {
32
36
  }
33
37
  }
34
38
 
35
- const statusMessages = ['Thinking...', 'Searching...', 'Reading...', 'Analyzing...']
39
+ const statusMessages = computed(() => [
40
+ t('assistant.loading.thinking'),
41
+ t('assistant.loading.searching'),
42
+ t('assistant.loading.reading'),
43
+ t('assistant.loading.analyzing'),
44
+ ])
36
45
  const currentIndex = ref(0)
37
- const displayedText = ref(statusMessages[0]!)
46
+ const displayedText = ref(statusMessages.value[0]!)
38
47
  const chars = 'abcdefghijklmnopqrstuvwxyz'
39
48
 
40
49
  function scramble(from: string, to: string) {
@@ -80,8 +89,8 @@ onMounted(() => {
80
89
  matrixInterval = setInterval(nextStep, 120)
81
90
  textInterval = setInterval(() => {
82
91
  const prev = displayedText.value
83
- currentIndex.value = (currentIndex.value + 1) % statusMessages.length
84
- scramble(prev, statusMessages[currentIndex.value]!)
92
+ currentIndex.value = (currentIndex.value + 1) % statusMessages.value.length
93
+ scramble(prev, statusMessages.value[currentIndex.value]!)
85
94
  }, 3500)
86
95
  })
87
96
 
@@ -92,7 +101,7 @@ onUnmounted(() => {
92
101
  </script>
93
102
 
94
103
  <template>
95
- <div class="flex items-center text-xs text-muted overflow-hidden">
104
+ <div class="flex items-center text-sm text-muted overflow-hidden">
96
105
  <div
97
106
  class="shrink-0 mr-2 grid"
98
107
  :style="{
@@ -111,6 +120,6 @@ onUnmounted(() => {
111
120
  />
112
121
  </div>
113
122
 
114
- <UChatShimmer :text="displayedText" class="font-mono tracking-tight" />
123
+ <UChatShimmer :text="displayedText" />
115
124
  </div>
116
125
  </template>
@@ -1,9 +1,10 @@
1
1
  <script setup lang="ts">
2
2
  import type { ToolUIPart, DynamicToolUIPart } from 'ai'
3
- import { DefaultChatTransport, isToolUIPart, isReasoningUIPart, isTextUIPart, getToolName } from 'ai'
3
+ import { DefaultChatTransport, isToolUIPart, isReasoningUIPart, isTextUIPart } from 'ai'
4
4
  import { Chat } from '@ai-sdk/vue'
5
5
  import { isPartStreaming, isToolStreaming } from '@nuxt/ui/utils/ai'
6
6
  import { useDocusI18n } from '../../../../app/composables/useDocusI18n'
7
+ import { getToolText, getToolSuffix, getToolIcon } from '../../../../app/utils/assistantTools'
7
8
  import AssistantComark from './AssistantComark'
8
9
  import AssistantIndicator from './AssistantIndicator.vue'
9
10
 
@@ -71,54 +72,22 @@ watch(messages, (newMessages) => {
71
72
  const canClear = computed(() => messages.value.length > 0)
72
73
 
73
74
  type ToolPart = ToolUIPart | DynamicToolUIPart
74
- type ToolState = ToolPart['state']
75
-
76
- function getToolMessage(state: ToolState, toolName: string, input: Record<string, string | undefined>) {
77
- const searchVerb = state === 'output-available' ? 'Searched' : 'Searching'
78
- const readVerb = state === 'output-available' ? 'Read' : 'Reading'
79
-
80
- return {
81
- 'list-pages': `${searchVerb} pages`,
82
- 'get-page': `${readVerb} ${input.path || '...'}`,
83
- }[toolName] || `${searchVerb} ${toolName}`
84
- }
85
-
86
- function getToolText(part: ToolPart) {
87
- return getToolMessage(part.state, getToolName(part), (part.input || {}) as Record<string, string | undefined>)
88
- }
89
-
90
- function getToolIcon(part: ToolPart): string {
91
- const toolName = getToolName(part)
92
-
93
- return {
94
- 'get-page': 'i-lucide-file-text',
95
- }[toolName] || 'i-lucide-search'
96
- }
97
75
 
98
76
  function getToolOutput(part: ToolPart): string | undefined {
99
77
  if (part.state !== 'output-available' || !part.output) return undefined
100
78
 
101
79
  const output = part.output as Record<string, unknown>
80
+ const content = (output.content ?? output) as Array<{ text?: string }> | string
102
81
 
103
- if (getToolName(part) === 'list-pages') {
104
- const content = (output.content ?? output) as Array<{ text?: string }> | string
105
- if (typeof content === 'string') return content
106
- return content
107
- ?.map(c => c.text)
108
- .filter(Boolean)
109
- .join('\n') || undefined
82
+ if (typeof content === 'string') {
83
+ return content || undefined
110
84
  }
111
85
 
112
- if (getToolName(part) === 'get-page') {
113
- const content = (output.content ?? output) as Array<{ text?: string }> | string
114
- if (typeof content === 'string') {
115
- return content.length > 500 ? `${content.slice(0, 500)}…` : content
116
- }
117
- const text = content?.map(c => c.text).filter(Boolean).join('\n') || ''
118
- return text.length > 500 ? `${text.slice(0, 500)}…` : text || undefined
86
+ if (Array.isArray(content)) {
87
+ return content.map(c => c.text).filter(Boolean).join('\n') || undefined
119
88
  }
120
89
 
121
- return JSON.stringify(output, null, 2).slice(0, 500)
90
+ return JSON.stringify(output, null, 2)
122
91
  }
123
92
 
124
93
  function onSubmit() {
@@ -214,7 +183,7 @@ defineShortcuts({
214
183
  :status="chat.status"
215
184
  compact
216
185
  class="px-0 gap-2"
217
- :user="{ ui: { container: 'max-w-full' } }"
186
+ :user="{ ui: { container: 'max-w-full pb-3' } }"
218
187
  >
219
188
  <template #indicator>
220
189
  <AssistantIndicator />
@@ -230,6 +199,7 @@ defineShortcuts({
230
199
  :text="part.text"
231
200
  :streaming="isPartStreaming(part)"
232
201
  icon="i-lucide-brain"
202
+ chevron="leading"
233
203
  >
234
204
  <AssistantComark
235
205
  :markdown="part.text"
@@ -253,14 +223,15 @@ defineShortcuts({
253
223
 
254
224
  <UChatTool
255
225
  v-else-if="isToolUIPart(part)"
256
- :text="getToolText(part)"
226
+ :text="getToolText(part, t)"
227
+ :suffix="getToolSuffix(part)"
257
228
  :icon="getToolIcon(part)"
258
229
  :streaming="isToolStreaming(part)"
259
230
  chevron="leading"
260
231
  >
261
232
  <pre
262
233
  v-if="getToolOutput(part)"
263
- class="text-xs text-dimmed whitespace-pre-wrap"
234
+ class="text-xs text-muted whitespace-pre-wrap break-all rounded-md border border-muted bg-muted p-2 max-h-64 overflow-y-auto"
264
235
  v-text="getToolOutput(part)"
265
236
  />
266
237
  </UChatTool>
@@ -1,4 +1,4 @@
1
- import { streamText, convertToModelMessages } from 'ai'
1
+ import { streamText, convertToModelMessages, stepCountIs, smoothStream } from 'ai'
2
2
  import type { ToolSet } from 'ai'
3
3
  import { createMCPClient } from '@ai-sdk/mcp'
4
4
  import type { H3Event } from 'h3'
@@ -22,19 +22,6 @@ function createLocalFetch(event: H3Event): typeof fetch {
22
22
  }
23
23
  }
24
24
 
25
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
26
- function stopWhenResponseComplete({ steps }: { steps: { text?: string, toolCalls?: unknown[] }[] }): boolean {
27
- const lastStep = steps.at(-1)
28
- if (!lastStep) return false
29
-
30
- const hasText = Boolean(lastStep.text && lastStep.text.trim().length > 0)
31
- const hasNoToolCalls = !lastStep.toolCalls || lastStep.toolCalls.length === 0
32
-
33
- if (hasText && hasNoToolCalls) return true
34
-
35
- return steps.length >= MAX_STEPS
36
- }
37
-
38
25
  function getSystemPrompt(siteName: string) {
39
26
  return `You are the documentation assistant for ${siteName}. Help users navigate and understand the project documentation.
40
27
 
@@ -115,13 +102,24 @@ export default defineEventHandler(async (event) => {
115
102
 
116
103
  return streamText({
117
104
  model: config.assistant.model,
118
- maxOutputTokens: 4000,
105
+ maxOutputTokens: 8000,
119
106
  maxRetries: 2,
120
107
  abortSignal: abortController.signal,
121
- stopWhen: stopWhenResponseComplete,
108
+ stopWhen: stepCountIs(MAX_STEPS),
109
+ // On the last allowed step, disable tools so the model is forced to
110
+ // produce a final text answer instead of stopping mid tool-calling.
111
+ prepareStep: ({ stepNumber }) => {
112
+ return stepNumber >= MAX_STEPS - 1 ? { toolChoice: 'none' } : {}
113
+ },
114
+ providerOptions: {
115
+ gateway: {
116
+ caching: 'auto',
117
+ },
118
+ },
122
119
  system: getSystemPrompt(siteName),
123
120
  messages: await convertToModelMessages(messages),
124
121
  tools: mcpTools as ToolSet,
122
+ experimental_transform: smoothStream(),
125
123
  onFinish: closeMcp,
126
124
  onAbort: closeMcp,
127
125
  onError: closeMcp,
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "docus",
3
3
  "description": "Nuxt layer for Docus documentation theme",
4
- "version": "5.12.1",
4
+ "version": "5.12.2",
5
5
  "type": "module",
6
6
  "main": "./nuxt.config.ts",
7
7
  "repository": {
@@ -23,39 +23,39 @@
23
23
  "README.md"
24
24
  ],
25
25
  "dependencies": {
26
- "@ai-sdk/gateway": "^3.0.120",
27
- "@ai-sdk/mcp": "^1.0.43",
28
- "@ai-sdk/vue": "^3.0.191",
26
+ "@ai-sdk/gateway": "^3.0.131",
27
+ "@ai-sdk/mcp": "^1.0.50",
28
+ "@ai-sdk/vue": "^3.0.205",
29
29
  "@comark/vue": "^0.4.0",
30
- "@iconify-json/lucide": "^1.2.111",
31
- "@iconify-json/simple-icons": "^1.2.85",
32
- "@iconify-json/vscode-icons": "^1.2.53",
30
+ "@iconify-json/lucide": "^1.2.112",
31
+ "@iconify-json/simple-icons": "^1.2.86",
32
+ "@iconify-json/vscode-icons": "^1.2.57",
33
33
  "@nuxt/content": "^3.14.0",
34
34
  "@nuxt/image": "^2.0.0",
35
- "@nuxt/kit": "^4.4.7",
36
- "@nuxt/ui": "^4.8.1",
35
+ "@nuxt/kit": "^4.4.8",
36
+ "@nuxt/ui": "^4.8.2",
37
37
  "@nuxtjs/i18n": "^10.4.0",
38
38
  "@nuxtjs/mcp-toolkit": "^0.17.2",
39
39
  "@nuxtjs/mdc": "^0.22.0",
40
- "@nuxtjs/robots": "^6.0.9",
40
+ "@nuxtjs/robots": "^6.1.1",
41
41
  "@shikijs/core": "^4.2.0",
42
42
  "@shikijs/engine-javascript": "^4.2.0",
43
43
  "@shikijs/langs": "^4.2.0",
44
44
  "@shikijs/stream": "^4.2.0",
45
45
  "@shikijs/themes": "^4.2.0",
46
- "@takumi-rs/core": "^1.6.0",
46
+ "@takumi-rs/core": "^1.8.5",
47
47
  "@vueuse/core": "^14.3.0",
48
- "ai": "^6.0.191",
48
+ "ai": "^6.0.205",
49
49
  "defu": "^6.1.7",
50
50
  "exsolve": "^1.0.8",
51
51
  "git-url-parse": "^16.1.0",
52
- "motion-v": "^2.2.1",
52
+ "motion-v": "^2.3.0",
53
53
  "nuxt-llms": "^0.2.0",
54
- "nuxt-og-image": "^6.5.1",
54
+ "nuxt-og-image": "~6.6.0",
55
55
  "pathe": "^2.0.3",
56
56
  "pkg-types": "^2.3.1",
57
57
  "scule": "^1.3.0",
58
- "tailwindcss": "^4.3.0",
58
+ "tailwindcss": "^4.3.1",
59
59
  "ufo": "^1.6.4",
60
60
  "yaml": "^2.9.0",
61
61
  "zod": "^4.4.3",