@openviking/react 0.1.3 → 0.1.5

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 (209) hide show
  1. package/LICENSE.arco-design +21 -0
  2. package/README.md +27 -15
  3. package/dist/0~0.js +19 -0
  4. package/dist/28~0.js +15 -0
  5. package/dist/2~0.js +2270 -29
  6. package/dist/2~0.js.LICENSE.txt +23 -0
  7. package/dist/3c~0.js +2208 -0
  8. package/dist/3~0.js +1207 -1982
  9. package/dist/4~0.js +18 -0
  10. package/dist/9~0.js +43 -0
  11. package/dist/{1~0.js → ae~0.js} +11 -26
  12. package/dist/ark-message-list-view~0.js +530 -119
  13. package/dist/a~0.js +1300 -14
  14. package/dist/c7~0.js +38 -2
  15. package/dist/ck~0.js +23 -0
  16. package/dist/client/provider.d.ts +15 -9
  17. package/dist/client/types.d.ts +5 -5
  18. package/dist/client.js +2 -1
  19. package/dist/components/agent-connect/agent-connect-code-block.d.ts +14 -0
  20. package/dist/components/agent-connect/agent-connect-copy.d.ts +22 -33
  21. package/dist/components/agent-connect/agent-connect-design.d.ts +1936 -168
  22. package/dist/components/agent-connect/agent-connect-installer.d.ts +1 -0
  23. package/dist/components/agent-connect/agent-connect-instructions-view.d.ts +4 -6
  24. package/dist/components/agent-connect/agent-connect-instructions.d.ts +148 -0
  25. package/dist/components/agent-connect/agent-connect-markdown.d.ts +8 -2
  26. package/dist/components/agent-connect/agent-connect-mask.d.ts +10 -0
  27. package/dist/components/agent-connect/agent-connect.d.ts +1 -1
  28. package/dist/components/agent-connect/locales/en-US.d.ts +23 -0
  29. package/dist/components/agent-connect/locales/zh-CN.d.ts +3 -0
  30. package/dist/components/agent-connect/style.css +129 -3
  31. package/dist/components/agent-connect/types.d.ts +7 -4
  32. package/dist/components/agent-connect/use-agent-connect-copy.d.ts +6 -0
  33. package/dist/components/directory-tour/directory-tour.d.ts +3 -0
  34. package/dist/components/directory-tour/index.d.ts +3 -0
  35. package/dist/components/directory-tour/locales/en-US.d.ts +3 -0
  36. package/dist/components/directory-tour/locales/zh-CN.d.ts +3 -0
  37. package/dist/components/directory-tour/steps.d.ts +5 -0
  38. package/dist/components/directory-tour/style.css +237 -0
  39. package/dist/components/directory-tour/style.js +0 -0
  40. package/dist/components/directory-tour/types.d.ts +43 -0
  41. package/dist/components/directory-tour/use-tour-anchor.d.ts +5 -0
  42. package/dist/components/directory-tour/use-tour-position.d.ts +12 -0
  43. package/dist/components/directory-tour.js +40 -0
  44. package/dist/components/file-browser-entries/file-browser-entries.d.ts +5 -5
  45. package/dist/components/file-browser-entries/labels.d.ts +3 -0
  46. package/dist/components/file-browser-entries/locales/en-US.d.ts +6 -0
  47. package/dist/components/file-browser-entries/locales/zh-CN.d.ts +6 -0
  48. package/dist/components/file-browser-entries/style.css +866 -2
  49. package/dist/components/file-browser-entries/types.d.ts +34 -16
  50. package/dist/components/file-preview/file-preview-adapters.d.ts +2 -1
  51. package/dist/components/file-preview/file-preview-body.d.ts +2 -1
  52. package/dist/components/file-preview/file-preview-breadcrumb-menu.d.ts +2 -1
  53. package/dist/components/file-preview/file-preview-breadcrumb.d.ts +2 -1
  54. package/dist/components/file-preview/file-preview-directory.d.ts +2 -1
  55. package/dist/components/file-preview/file-preview-handle-adapters.d.ts +2 -1
  56. package/dist/components/file-preview/file-preview-header.d.ts +6 -2
  57. package/dist/components/file-preview/file-preview-image-frame.d.ts +5 -0
  58. package/dist/components/file-preview/file-preview-labels.d.ts +2 -14
  59. package/dist/components/file-preview/file-preview-level-tabs.d.ts +7 -0
  60. package/dist/components/file-preview/file-preview-markdown-images.d.ts +13 -0
  61. package/dist/components/file-preview/file-preview-panels.d.ts +5 -2
  62. package/dist/components/file-preview/file-preview-viewer.d.ts +2 -1
  63. package/dist/components/file-preview/file-preview.d.ts +0 -1
  64. package/dist/components/file-preview/index.d.ts +2 -1
  65. package/dist/components/file-preview/locales/en-US.d.ts +16 -0
  66. package/dist/components/file-preview/locales/zh-CN.d.ts +16 -0
  67. package/dist/components/file-preview/style.css +160 -2
  68. package/dist/components/file-preview/types.d.ts +34 -10
  69. package/dist/components/file-preview/use-file-preview-levels.d.ts +7 -0
  70. package/dist/components/file-preview/use-file-preview-view-state.d.ts +15 -0
  71. package/dist/components/file-preview.js +1 -1
  72. package/dist/components/file-tree/file-tree-info-labels.d.ts +0 -15
  73. package/dist/components/file-tree/file-tree-labels.d.ts +4 -0
  74. package/dist/components/file-tree/file-tree-row-shared.d.ts +2 -12
  75. package/dist/components/file-tree/file-tree-toolbar.d.ts +11 -0
  76. package/dist/components/file-tree/locales/en-US.d.ts +69 -0
  77. package/dist/components/file-tree/locales/zh-CN.d.ts +69 -0
  78. package/dist/components/file-tree/style.css +143 -15
  79. package/dist/components/file-tree/types.d.ts +38 -10
  80. package/dist/components/file-tree/use-file-tree-actions.d.ts +4 -1
  81. package/dist/components/scope-switcher/labels.d.ts +3 -0
  82. package/dist/components/scope-switcher/locales/en-US.d.ts +8 -0
  83. package/dist/components/scope-switcher/locales/zh-CN.d.ts +8 -0
  84. package/dist/components/scope-switcher/scope-panel.d.ts +1 -1
  85. package/dist/components/scope-switcher/scope-switcher.d.ts +2 -2
  86. package/dist/components/scope-switcher/style.css +14 -2
  87. package/dist/components/scope-switcher/types.d.ts +12 -6
  88. package/dist/components/style.css +10030 -6763
  89. package/dist/components/tui/locales/en-US.d.ts +35 -0
  90. package/dist/components/tui/locales/zh-CN.d.ts +35 -0
  91. package/dist/components/tui/style.css +310 -18
  92. package/dist/components/tui/tui-copy-button.d.ts +1 -1
  93. package/dist/components/tui/tui-empty.d.ts +25 -0
  94. package/dist/components/tui/tui-labels.d.ts +2 -2
  95. package/dist/components/tui/tui.d.ts +1 -1
  96. package/dist/components/tui/types.d.ts +35 -12
  97. package/dist/components/tui.js +1 -1
  98. package/dist/components/viking-bot/ark-adapter.d.ts +2 -0
  99. package/dist/components/viking-bot/ark-message-body.d.ts +1 -7
  100. package/dist/components/viking-bot/ark-message-list-view.d.ts +4 -1
  101. package/dist/components/viking-bot/ark-message-row.d.ts +3 -1
  102. package/dist/components/viking-bot/bot-popover.d.ts +9 -0
  103. package/dist/components/viking-bot/capabilities.d.ts +49 -0
  104. package/dist/components/viking-bot/composer-attachments.d.ts +13 -0
  105. package/dist/components/viking-bot/composer-controls.d.ts +10 -0
  106. package/dist/components/viking-bot/composer-footer.d.ts +17 -0
  107. package/dist/components/viking-bot/composer-references.d.ts +20 -0
  108. package/dist/components/viking-bot/composer-text.d.ts +10 -0
  109. package/dist/components/viking-bot/index.d.ts +3 -1
  110. package/dist/components/viking-bot/interaction/ask-human-fields.d.ts +1 -1
  111. package/dist/components/viking-bot/interaction/labels.d.ts +2 -1
  112. package/dist/components/viking-bot/interaction/locales/en-US.d.ts +17 -0
  113. package/dist/components/viking-bot/interaction/locales/zh-CN.d.ts +17 -0
  114. package/dist/components/viking-bot/interaction/types.d.ts +8 -3
  115. package/dist/components/viking-bot/interaction/viking-bot-interaction.d.ts +1 -1
  116. package/dist/components/viking-bot/labels.d.ts +2 -0
  117. package/dist/components/viking-bot/locales/en-US.d.ts +40 -0
  118. package/dist/components/viking-bot/locales/zh-CN.d.ts +40 -0
  119. package/dist/components/viking-bot/markdown-links.d.ts +27 -0
  120. package/dist/components/viking-bot/message-activity.d.ts +7 -0
  121. package/dist/components/viking-bot/message-code-block.d.ts +8 -0
  122. package/dist/components/viking-bot/message-footer.d.ts +8 -0
  123. package/dist/components/viking-bot/message-markdown.d.ts +9 -0
  124. package/dist/components/viking-bot/model.d.ts +37 -3
  125. package/dist/components/viking-bot/quick-input-tracker.d.ts +16 -0
  126. package/dist/components/viking-bot/quick-inputs.d.ts +6 -0
  127. package/dist/components/viking-bot/reference-picker.d.ts +16 -0
  128. package/dist/components/viking-bot/session-actions.d.ts +11 -0
  129. package/dist/components/viking-bot/style.css +1486 -48
  130. package/dist/components/viking-bot/tool-activity.d.ts +9 -0
  131. package/dist/components/viking-bot/tool-result-links.d.ts +6 -0
  132. package/dist/components/viking-bot/types.d.ts +20 -8
  133. package/dist/components/viking-bot/use-quick-input.d.ts +17 -0
  134. package/dist/components/viking-bot/viking-bot.d.ts +1 -6
  135. package/dist/components/viking-bot/welcome.d.ts +8 -0
  136. package/dist/components/viking-bot.js +1 -1
  137. package/dist/c~0.js +550 -69
  138. package/dist/e~0.js +335 -0
  139. package/dist/file-preview-viewer~0.js +90 -8
  140. package/dist/f~0.js +49 -51
  141. package/dist/h~0.js +5 -1
  142. package/dist/icons/console-icons.d.ts +12 -0
  143. package/dist/icons/index.d.ts +2 -0
  144. package/dist/icons/viking-bot-icons.d.ts +6 -0
  145. package/dist/icons.js +1 -0
  146. package/dist/index.d.ts +2 -0
  147. package/dist/index.js +2 -1
  148. package/dist/k~0.js +1 -0
  149. package/dist/lg~0.js +155 -0
  150. package/dist/lk~0.js +40 -8
  151. package/dist/l~0.js +170 -181
  152. package/dist/modules/console/command-messages.d.ts +19 -0
  153. package/dist/modules/console/command-parser.d.ts +15 -0
  154. package/dist/modules/console/command-specs.d.ts +15 -0
  155. package/dist/modules/console/commands.d.ts +6 -0
  156. package/dist/modules/console/console-history.d.ts +10 -0
  157. package/dist/modules/console/console-toolbar.d.ts +18 -0
  158. package/dist/modules/console/console.d.ts +1 -3
  159. package/dist/modules/console/controller.d.ts +17 -0
  160. package/dist/modules/console/index.d.ts +2 -0
  161. package/dist/modules/console/labels.d.ts +61 -0
  162. package/dist/modules/console/locales/en-US.d.ts +49 -0
  163. package/dist/modules/console/locales/zh-CN.d.ts +3 -0
  164. package/dist/modules/console/localize-records.d.ts +11 -0
  165. package/dist/modules/console/results.d.ts +2 -0
  166. package/dist/modules/console/style.css +10905 -15
  167. package/dist/modules/console/types.d.ts +59 -80
  168. package/dist/modules/console/use-console.d.ts +3 -0
  169. package/dist/modules/console.js +1 -1
  170. package/dist/modules/file-browser/file-browser-detail.d.ts +2 -1
  171. package/dist/modules/file-browser/file-browser-labels.d.ts +11 -12
  172. package/dist/modules/file-browser/file-browser-toolbar.d.ts +3 -4
  173. package/dist/modules/file-browser/file-browser-tree-pane.d.ts +7 -5
  174. package/dist/modules/file-browser/file-browser.d.ts +1 -1
  175. package/dist/modules/file-browser/fs-read-directory.d.ts +2 -6
  176. package/dist/modules/file-browser/locales/en-US.d.ts +25 -0
  177. package/dist/modules/file-browser/locales/zh-CN.d.ts +25 -0
  178. package/dist/modules/file-browser/style.css +1695 -126
  179. package/dist/modules/file-browser/types.d.ts +38 -29
  180. package/dist/modules/file-browser/use-file-browser.d.ts +6 -1
  181. package/dist/modules/file-browser/use-fs-preview.d.ts +15 -1
  182. package/dist/modules/scope-cascade/labels.d.ts +6 -0
  183. package/dist/modules/scope-cascade/locales/en-US.d.ts +6 -0
  184. package/dist/modules/scope-cascade/locales/zh-CN.d.ts +3 -0
  185. package/dist/modules/scope-cascade/scope-cascade.d.ts +2 -2
  186. package/dist/modules/scope-cascade/style.css +14 -2
  187. package/dist/modules/scope-cascade/types.d.ts +3 -0
  188. package/dist/modules/style.css +15938 -3455
  189. package/dist/nx~0.js +15 -0
  190. package/dist/n~0.js +240 -83
  191. package/dist/o~0.js +10 -7
  192. package/dist/p~0.js +27 -0
  193. package/dist/rslib-runtime~0.js +42 -0
  194. package/dist/r~0.js +152 -0
  195. package/dist/shared/components/drawer/drawer.d.ts +13 -0
  196. package/dist/shared/components/drawer/index.d.ts +1 -0
  197. package/dist/shared/components/overlay/use-overlay-position.d.ts +2 -2
  198. package/dist/shared/components/tooltip/use-portal-theme.d.ts +3 -0
  199. package/dist/shared/locale-context.d.ts +8 -0
  200. package/dist/shared/locale.d.ts +6 -0
  201. package/dist/style.css +26339 -10577
  202. package/dist/u~0.js +397 -152
  203. package/dist/viking-bot-composer~0.js +436 -77
  204. package/dist/viking-bot-interaction~0.js +13 -11
  205. package/package.json +15 -4
  206. package/dist/30~0.js +0 -1332
  207. package/dist/components/tui/tui-labels-zh.d.ts +0 -2
  208. package/dist/modules/file-browser/tree-info-copy.d.ts +0 -15
  209. package/dist/modules/file-browser/tree-info-copy.zh-CN.d.ts +0 -15
@@ -1,12 +1,397 @@
1
1
  import { Fragment, jsx, jsxs } from "react/jsx-runtime";
2
2
  import { ChatMessageList } from "@ark-design/ui/message-list";
3
- import { Bubble } from "@ark-design/ui/bubble";
3
+ import { Bubble, BubbleTools } from "@ark-design/ui/bubble";
4
4
  import { ErrorCard } from "@ark-design/ui/error-card";
5
+ import { useEffect, useMemo, useState } from "react";
5
6
  import { ActivityTimeline } from "@ark-design/ui/activity-timeline";
6
7
  import { MDRenderer } from "@ark-design/ui/markdown-renderer";
7
- import { useState } from "react";
8
- import { groupActivityParts, toRenderItems, DEFAULT_LABELS } from "./c~0.js";
9
- import { messageText, groupMessages } from "./h~0.js";
8
+ import { DocumentIcon } from "./k~0.js";
9
+ import { VikingBotIcon } from "./lg~0.js";
10
+ import { groupActivityParts, mergeToolResults, resolveVikingBotLabels, toRenderItems } from "./c~0.js";
11
+ import { groupByActivity, messageText, groupMessages } from "./h~0.js";
12
+ const PREFIX = '#viking-uri=';
13
+ const RESOURCE = /viking:\/\/[^\s<>"'`]+/gi;
14
+ const PROSE_RESOURCE = /viking:\/\/[^\s<>"'`,。;!?)\]]+/gi;
15
+ const SKIP = new Set([
16
+ 'link',
17
+ 'linkReference',
18
+ 'definition',
19
+ 'code',
20
+ 'html'
21
+ ]);
22
+ function safeMarkdownHref(value) {
23
+ if (!value) return;
24
+ try {
25
+ return [
26
+ 'http:',
27
+ 'https:',
28
+ 'mailto:',
29
+ 'tel:'
30
+ ].includes(new URL(value, 'https://openviking.invalid').protocol) ? value : void 0;
31
+ } catch {
32
+ return;
33
+ }
34
+ }
35
+ function resourceHref(value) {
36
+ if (value?.startsWith(PREFIX)) try {
37
+ value = decodeURIComponent(value.slice(PREFIX.length));
38
+ } catch {
39
+ return;
40
+ }
41
+ return value && /^viking:\/\/[^\s<>"'`]+$/i.test(value) ? value : void 0;
42
+ }
43
+ function resourceText(value, prose = true) {
44
+ const matches = [];
45
+ for (const match of value.matchAll(new RegExp(prose ? PROSE_RESOURCE : RESOURCE))){
46
+ const uri = prose ? match[0].replace(/[.!?;:]+$/u, '') : match[0];
47
+ matches.push({
48
+ start: match.index,
49
+ end: match.index + uri.length,
50
+ uri
51
+ });
52
+ }
53
+ return matches;
54
+ }
55
+ const markdown_links_link = (uri, child)=>({
56
+ type: 'link',
57
+ url: PREFIX + encodeURIComponent(uri),
58
+ children: [
59
+ child
60
+ ]
61
+ });
62
+ function linkResourceNodes(node) {
63
+ if (('link' === node.type || 'definition' === node.type) && node.url) {
64
+ const uri = resourceHref(node.url);
65
+ if (uri) node.url = PREFIX + encodeURIComponent(uri);
66
+ }
67
+ if (!node.children || SKIP.has(node.type ?? '')) return node;
68
+ node.children = node.children.flatMap((child)=>{
69
+ if ('inlineCode' === child.type) {
70
+ const uri = resourceHref(child.value);
71
+ return uri ? [
72
+ markdown_links_link(uri, child)
73
+ ] : [
74
+ child
75
+ ];
76
+ }
77
+ if ('text' !== child.type || !child.value) return [
78
+ linkResourceNodes(child)
79
+ ];
80
+ const pieces = [];
81
+ let cursor = 0;
82
+ for (const match of resourceText(child.value)){
83
+ if (match.start > cursor) pieces.push({
84
+ type: 'text',
85
+ value: child.value.slice(cursor, match.start)
86
+ });
87
+ pieces.push(markdown_links_link(match.uri, {
88
+ type: 'text',
89
+ value: match.uri
90
+ }));
91
+ cursor = match.end;
92
+ }
93
+ if (!pieces.length) return [
94
+ child
95
+ ];
96
+ if (cursor < child.value.length) pieces.push({
97
+ type: 'text',
98
+ value: child.value.slice(cursor)
99
+ });
100
+ return pieces;
101
+ });
102
+ return node;
103
+ }
104
+ const resourceAstPlugin = {
105
+ name: 'openviking-viking-uri-linkify',
106
+ config: {},
107
+ before: ()=>{},
108
+ after: ()=>{},
109
+ beforeEach: ()=>{},
110
+ afterEach: ()=>{},
111
+ modifier: (ast)=>{
112
+ if (ast && 'object' == typeof ast && 'type' in ast) linkResourceNodes(ast);
113
+ }
114
+ };
115
+ function MessageCodeBlock({ code, language = 'text', labels, onOpenUri }) {
116
+ const { copy, copied } = labels;
117
+ const slots = useMemo(()=>({
118
+ CodeBlockHeader: ()=>/*#__PURE__*/ jsx(BubbleTools, {
119
+ className: "ov-viking-bot__code-copy",
120
+ items: [
121
+ 'copy'
122
+ ],
123
+ copyText: code,
124
+ labels: {
125
+ copy,
126
+ copied
127
+ }
128
+ }),
129
+ .../^(bash|shell|sh|text|txt)$/i.test(language) && onOpenUri && resourceText(code, false).length ? {
130
+ CodeBlockHighlighter: ()=>{
131
+ let cursor = 0;
132
+ const nodes = resourceText(code, false).flatMap((match)=>{
133
+ const before = code.slice(cursor, match.start);
134
+ cursor = match.end;
135
+ return [
136
+ before,
137
+ /*#__PURE__*/ jsx("a", {
138
+ href: match.uri,
139
+ onClick: (event)=>{
140
+ event.preventDefault();
141
+ onOpenUri(match.uri);
142
+ },
143
+ children: match.uri
144
+ }, match.start)
145
+ ];
146
+ });
147
+ return /*#__PURE__*/ jsx("pre", {
148
+ children: /*#__PURE__*/ jsxs("code", {
149
+ children: [
150
+ nodes,
151
+ code.slice(cursor)
152
+ ]
153
+ })
154
+ });
155
+ }
156
+ } : {}
157
+ }), [
158
+ code,
159
+ language,
160
+ onOpenUri,
161
+ copy,
162
+ copied
163
+ ]);
164
+ const fence = '`'.repeat(Math.max(3, ...Array.from(code.matchAll(/`+/g), (match)=>match[0].length + 1)));
165
+ return /*#__PURE__*/ jsx("div", {
166
+ className: `ov-viking-bot__code${'text' === language ? ' ov-viking-bot__code--wrap' : ''}`,
167
+ children: /*#__PURE__*/ jsx(MDRenderer, {
168
+ markdown: `${fence}${language.replace(/[^\w+-]/g, '')}\n${code}\n${fence}`,
169
+ slots: slots
170
+ })
171
+ });
172
+ }
173
+ function ToolResultLinks({ results, labels, onOpenUri }) {
174
+ return /*#__PURE__*/ jsx("div", {
175
+ className: "ov-viking-bot__tool-results",
176
+ children: results.map((result, index)=>/*#__PURE__*/ jsxs("button", {
177
+ type: "button",
178
+ className: "ov-viking-bot__tool-result",
179
+ disabled: !onOpenUri,
180
+ title: result.uri,
181
+ onClick: ()=>onOpenUri?.(result.uri),
182
+ children: [
183
+ void 0 !== result.score && Number.isFinite(result.score) ? /*#__PURE__*/ jsxs("span", {
184
+ className: "ov-viking-bot__tool-result-score",
185
+ children: [
186
+ labels.similarity,
187
+ " ",
188
+ /*#__PURE__*/ jsx("strong", {
189
+ children: result.score.toFixed(2)
190
+ })
191
+ ]
192
+ }) : null,
193
+ /*#__PURE__*/ jsx(DocumentIcon, {
194
+ width: 12,
195
+ height: 12,
196
+ "aria-hidden": "true"
197
+ }),
198
+ /*#__PURE__*/ jsx("span", {
199
+ className: "ov-viking-bot__tool-result-name",
200
+ children: result.label ?? result.uri.replace(/\/$/, '').split('/').pop() ?? result.uri
201
+ }),
202
+ /*#__PURE__*/ jsx("span", {
203
+ className: "ov-viking-bot__tool-result-uri",
204
+ children: result.uri
205
+ })
206
+ ]
207
+ }, `${result.uri}:${index}`))
208
+ });
209
+ }
210
+ const payload = (value)=>{
211
+ if (null == value) return {
212
+ code: '',
213
+ language: 'text'
214
+ };
215
+ if ('string' != typeof value) return {
216
+ code: JSON.stringify(value, null, 2),
217
+ language: 'json'
218
+ };
219
+ try {
220
+ return {
221
+ code: JSON.stringify(JSON.parse(value), null, 2),
222
+ language: 'json'
223
+ };
224
+ } catch {
225
+ return {
226
+ code: value,
227
+ language: 'text'
228
+ };
229
+ }
230
+ };
231
+ function ToolActivity({ context, labels, onOpenUri, results }) {
232
+ const Disclosure = context.components.ActivityToolDisclosure;
233
+ const input = payload(context.item.arguments);
234
+ const output = payload(context.item.error ?? context.item.resultPreview);
235
+ const status = context.item.status;
236
+ const name = [
237
+ context.item.server,
238
+ context.item.tool
239
+ ].filter(Boolean).join('.');
240
+ const title = context.item.titleOverride ?? `${'running' === status || 'queued' === status ? labels.toolRunning : 'failed' === status ? labels.toolError : labels.toolCompleted} ${name}`;
241
+ const detail = /*#__PURE__*/ jsx("div", {
242
+ className: "ov-viking-bot__tool-details",
243
+ children: [
244
+ {
245
+ value: input,
246
+ label: labels.toolInput
247
+ },
248
+ {
249
+ value: output,
250
+ label: labels.toolOutput,
251
+ results
252
+ }
253
+ ].filter(({ value, results })=>value.code || results?.length).map(({ value, label, results }, index)=>/*#__PURE__*/ jsxs("section", {
254
+ className: "ov-viking-bot__tool-payload-section",
255
+ children: [
256
+ /*#__PURE__*/ jsx("div", {
257
+ className: "ov-viking-bot__tool-payload-label",
258
+ children: label
259
+ }),
260
+ results?.length ? /*#__PURE__*/ jsx(ToolResultLinks, {
261
+ results: results,
262
+ labels: labels,
263
+ onOpenUri: onOpenUri
264
+ }) : /*#__PURE__*/ jsx("div", {
265
+ className: "ov-viking-bot__tool-payload",
266
+ children: /*#__PURE__*/ jsx(MessageCodeBlock, {
267
+ ...value,
268
+ labels: labels,
269
+ onOpenUri: onOpenUri
270
+ })
271
+ })
272
+ ]
273
+ }, index))
274
+ });
275
+ return /*#__PURE__*/ jsx(Disclosure, {
276
+ id: context.item.id,
277
+ icon: /*#__PURE__*/ jsx(VikingBotIcon, {
278
+ name: "tool"
279
+ }),
280
+ title: title,
281
+ expanded: context.expanded,
282
+ onExpandedChange: context.setExpanded,
283
+ status: context.status,
284
+ detail: input.code || output.code || results?.length ? detail : void 0
285
+ });
286
+ }
287
+ const timestamp = (value)=>void 0 === value ? 0 / 0 : 'number' == typeof value ? value : new Date(value).getTime();
288
+ function MessageActivity({ parts, labels, onOpenUri }) {
289
+ const { groups, order } = groupActivityParts(parts);
290
+ const resultLinks = useMemo(()=>{
291
+ const links = new Map();
292
+ for (const part of parts)if (('tool' === part.type || 'tool_result' === part.type) && void 0 !== part.results) links.set(part.id, part.results);
293
+ return links;
294
+ }, [
295
+ parts
296
+ ]);
297
+ const items = order.flatMap((id)=>groups.get(id)?.items ?? []);
298
+ const running = items.some((item)=>'running' === item.status || 'queued' === item.status);
299
+ const [now, setNow] = useState(()=>Date.now());
300
+ useEffect(()=>{
301
+ if (!running) return;
302
+ const timer = setInterval(()=>setNow(Date.now()), 1000);
303
+ return ()=>clearInterval(timer);
304
+ }, [
305
+ running
306
+ ]);
307
+ const starts = parts.flatMap((part)=>'startedAt' in part ? [
308
+ timestamp(part.startedAt)
309
+ ].filter(Number.isFinite) : []);
310
+ const ends = parts.flatMap((part)=>'completedAt' in part ? [
311
+ timestamp(part.completedAt)
312
+ ].filter(Number.isFinite) : []);
313
+ const elapsed = starts.length && (running || ends.length) ? Math.max(0, (running ? now : Math.max(...ends)) - Math.min(...starts)) : items.reduce((total, item)=>total + (item.durationMs ?? 0), 0);
314
+ const renderers = useMemo(()=>({
315
+ mcpToolCall: (context)=>/*#__PURE__*/ jsx(ToolActivity, {
316
+ context: context,
317
+ labels: labels,
318
+ onOpenUri: onOpenUri,
319
+ results: resultLinks.get(context.item.id)
320
+ })
321
+ }), [
322
+ labels,
323
+ onOpenUri,
324
+ resultLinks
325
+ ]);
326
+ return /*#__PURE__*/ jsx(ActivityTimeline, {
327
+ className: "ov-viking-bot__activity",
328
+ items: items.map((item)=>({
329
+ ...item,
330
+ durationMs: void 0 !== item.durationMs && item.durationMs >= 1000 ? item.durationMs : void 0
331
+ })),
332
+ defaultCollapseCompleted: true,
333
+ defaultExpanded: true,
334
+ density: "compact",
335
+ durationMs: elapsed >= 1000 ? 1000 * Math.floor(elapsed / 1000) : void 0,
336
+ statusLabel: running ? labels.activityRunning : labels.activityCompleted,
337
+ renderers: renderers,
338
+ onOpenSearchResult: (result)=>onOpenUri?.(result.url)
339
+ });
340
+ }
341
+ const AST_PLUGINS = [
342
+ resourceAstPlugin
343
+ ];
344
+ function MessageMarkdown({ text, streaming, user, labels, onOpenUri }) {
345
+ const { copy, copied } = labels;
346
+ const slots = useMemo(()=>({
347
+ CodeBlock: ({ code, language })=>/*#__PURE__*/ jsx(MessageCodeBlock, {
348
+ code: code,
349
+ language: language,
350
+ labels: {
351
+ copy,
352
+ copied
353
+ },
354
+ onOpenUri: onOpenUri
355
+ }),
356
+ Link: ({ children, href, title })=>{
357
+ const uri = resourceHref(href);
358
+ const safeHref = uri ?? safeMarkdownHref(href);
359
+ if (!safeHref) return /*#__PURE__*/ jsx(Fragment, {
360
+ children: children
361
+ });
362
+ return /*#__PURE__*/ jsx("a", {
363
+ href: safeHref,
364
+ title: title,
365
+ target: !uri && /^https?:/i.test(href ?? '') ? '_blank' : void 0,
366
+ rel: "noopener noreferrer",
367
+ onClick: uri ? (event)=>{
368
+ event.preventDefault();
369
+ onOpenUri?.(uri);
370
+ } : void 0,
371
+ children: children
372
+ });
373
+ }
374
+ }), [
375
+ onOpenUri,
376
+ copy,
377
+ copied
378
+ ]);
379
+ return /*#__PURE__*/ jsx(MDRenderer, {
380
+ className: "ov-viking-bot__text ov-viking-bot__text--markdown",
381
+ astPlugins: user ? void 0 : AST_PLUGINS,
382
+ parsing: user ? {
383
+ breaks: true,
384
+ enabledHtmlTags: false
385
+ } : void 0,
386
+ markdown: text,
387
+ showIndicator: streaming,
388
+ style: user ? {
389
+ fontSize: 'inherit',
390
+ overflowWrap: 'anywhere'
391
+ } : void 0,
392
+ slots: user ? void 0 : slots
393
+ });
394
+ }
10
395
  function renderPart(part, context) {
11
396
  const { labels, onOpenUri } = context;
12
397
  if ('text' === part.type) return 'markdown' === part.format ? /*#__PURE__*/ jsx("div", {
@@ -95,101 +480,97 @@ function renderPart(part, context) {
95
480
  function capitalize(value) {
96
481
  return value.charAt(0).toUpperCase() + value.slice(1);
97
482
  }
98
- function MessageText({ text, streaming, format }) {
99
- if ('plain' === format) return /*#__PURE__*/ jsx("div", {
100
- className: "ov-viking-bot__text",
101
- children: text
102
- });
103
- return /*#__PURE__*/ jsx(MDRenderer, {
104
- className: "ov-viking-bot__text ov-viking-bot__text--markdown",
105
- markdown: text,
106
- showIndicator: streaming
107
- });
108
- }
109
- function ActivityGroup({ id, items, running, labels, onOpenUri }) {
110
- const [expanded, setExpanded] = useState(running);
111
- const duration = items.reduce((total, item)=>total + (item.durationMs ?? 0), 0);
112
- const summary = running ? labels.thinking : duration > 0 ? `${labels.reasoning} · ${Math.round(duration / 1000)}s` : labels.reasoning;
113
- return /*#__PURE__*/ jsxs("section", {
114
- className: "ov-viking-bot__activity",
115
- "data-group": id,
116
- children: [
117
- /*#__PURE__*/ jsx("button", {
118
- type: "button",
119
- className: "ov-viking-bot__activity-toggle",
120
- "aria-expanded": expanded,
121
- onClick: ()=>setExpanded((current)=>!current),
122
- children: summary
123
- }),
124
- expanded ? /*#__PURE__*/ jsx(ActivityTimeline, {
125
- items: items,
126
- density: "compact",
127
- defaultExpanded: true,
128
- onOpenSearchResult: (result)=>onOpenUri?.(result.url)
129
- }) : null
130
- ]
131
- });
132
- }
133
483
  function MessageBody({ message, labels, onOpenUri }) {
134
- const activity = message.parts.filter((part)=>'reasoning' === part.type || 'tool' === part.type);
135
- const rest = message.parts.filter((part)=>'reasoning' !== part.type && 'tool' !== part.type);
136
- const { groups, order } = groupActivityParts(activity);
137
- return /*#__PURE__*/ jsxs(Fragment, {
138
- children: [
139
- order.map((key)=>{
140
- const group = groups.get(key);
141
- if (!group) return null;
142
- return /*#__PURE__*/ jsx(ActivityGroup, {
143
- id: group.id,
144
- items: group.items,
145
- running: group.items.some((item)=>'running' === item.status),
484
+ return /*#__PURE__*/ jsx(Fragment, {
485
+ children: groupByActivity(mergeToolResults(message.parts)).map((block, index)=>{
486
+ const part = block.parts[0];
487
+ if (!part) return null;
488
+ if ('reasoning' === part.type || 'tool' === part.type) return /*#__PURE__*/ jsx(MessageActivity, {
489
+ parts: block.parts,
490
+ labels: labels,
491
+ onOpenUri: onOpenUri
492
+ }, `${block.groupId ?? 'activity'}:${index}`);
493
+ return block.parts.map((value, offset)=>'text' === value.type ? 'plain' === value.format ? /*#__PURE__*/ jsx("div", {
494
+ className: "ov-viking-bot__text",
495
+ children: value.text
496
+ }, `${index}:${offset}`) : /*#__PURE__*/ jsx(MessageMarkdown, {
497
+ text: value.text,
498
+ streaming: message.streaming,
499
+ user: 'user' === message.role,
146
500
  labels: labels,
147
501
  onOpenUri: onOpenUri
148
- }, group.id);
149
- }),
150
- rest.map((part, index)=>'text' === part.type ? /*#__PURE__*/ jsx(MessageText, {
151
- text: part.text,
152
- format: part.format,
153
- streaming: message.streaming
154
- }, index) : /*#__PURE__*/ jsx("div", {
155
- children: renderPart(part, {
502
+ }, `${index}:${offset}`) : /*#__PURE__*/ jsx("div", {
503
+ children: 'tool_result' === value.type && value.results?.length ? /*#__PURE__*/ jsx(ToolResultLinks, {
504
+ results: value.results,
505
+ labels: labels,
506
+ onOpenUri: onOpenUri
507
+ }) : renderPart(value, {
156
508
  labels,
157
509
  onOpenUri
158
510
  })
159
- }, index))
160
- ]
511
+ }, `${index}:${offset}`));
512
+ })
161
513
  });
162
514
  }
163
- function MessageActions({ message, labels, onCopy, onMessageAction }) {
515
+ function MessageFooter({ message, showTime, labels, locale, onCopy }) {
164
516
  const text = messageText(message);
165
- const actions = message.actions ?? (message.action ? [
166
- {
167
- messageId: message.id,
168
- action: message.action
169
- }
170
- ] : []);
171
- if (0 === actions.length && !onCopy) return null;
517
+ const date = message.createdAt ? new Date(message.createdAt) : void 0;
518
+ const time = showTime && date && !Number.isNaN(date.getTime()) ? date.toLocaleString(locale, {
519
+ day: '2-digit',
520
+ hour: '2-digit',
521
+ hour12: false,
522
+ minute: '2-digit',
523
+ month: '2-digit',
524
+ year: 'numeric'
525
+ }) : '';
526
+ const canCopy = Boolean(text && ('user' === message.role || onCopy));
527
+ if (!time && !canCopy) return null;
172
528
  return /*#__PURE__*/ jsxs("div", {
173
- className: "ov-viking-bot__message-actions",
529
+ className: "ov-viking-bot__message-footer",
174
530
  children: [
175
- actions.map(({ messageId, action })=>/*#__PURE__*/ jsx("button", {
176
- type: "button",
177
- className: "ov-viking-bot__message-action",
178
- disabled: Boolean(action.disabledReason) || 'pending' === action.status || 'success' === action.status,
179
- title: action.disabledReason,
180
- onClick: ()=>onMessageAction?.(messageId, action.key),
181
- children: action.label ?? action.key
182
- }, `${messageId}:${action.key}`)),
183
- onCopy && text ? /*#__PURE__*/ jsx("button", {
531
+ time ? /*#__PURE__*/ jsx("time", {
532
+ dateTime: message.createdAt,
533
+ children: time
534
+ }) : null,
535
+ canCopy ? onCopy ? /*#__PURE__*/ jsx("button", {
184
536
  type: "button",
185
537
  className: "ov-viking-bot__copy",
186
538
  onClick: ()=>onCopy(text),
187
539
  children: labels.copy
540
+ }) : /*#__PURE__*/ jsx(BubbleTools, {
541
+ items: [
542
+ 'copy'
543
+ ],
544
+ copyText: text,
545
+ labels: {
546
+ copy: labels.copy,
547
+ copied: labels.copied
548
+ }
188
549
  }) : null
189
550
  ]
190
551
  });
191
552
  }
192
- function VikingBotMessageRow({ message, labels, onOpenUri, onCopy, onMessageAction, renderMessage }) {
553
+ function MessageActions({ message, onMessageAction }) {
554
+ const actions = message.actions ?? (message.action ? [
555
+ {
556
+ messageId: message.id,
557
+ action: message.action
558
+ }
559
+ ] : []);
560
+ if (0 === actions.length) return null;
561
+ return /*#__PURE__*/ jsx("div", {
562
+ className: "ov-viking-bot__message-actions",
563
+ children: actions.map(({ messageId, action })=>/*#__PURE__*/ jsx("button", {
564
+ type: "button",
565
+ className: "ov-viking-bot__message-action",
566
+ disabled: Boolean(action.disabledReason) || 'pending' === action.status || 'success' === action.status,
567
+ title: action.disabledReason,
568
+ onClick: ()=>onMessageAction?.(messageId, action.key),
569
+ children: action.label ?? action.key
570
+ }, `${messageId}:${action.key}`))
571
+ });
572
+ }
573
+ function VikingBotMessageRow({ message, labels, onOpenUri, onCopy, onMessageAction, renderMessage, showTime, locale }) {
193
574
  if (renderMessage) return /*#__PURE__*/ jsx("div", {
194
575
  className: "ov-viking-bot__message",
195
576
  children: renderMessage(message)
@@ -198,22 +579,43 @@ function VikingBotMessageRow({ message, labels, onOpenUri, onCopy, onMessageActi
198
579
  className: 'error' === message.tone ? 'ov-viking-bot__notice ov-viking-bot__notice--error' : 'ov-viking-bot__notice',
199
580
  content: messageText(message)
200
581
  });
201
- return /*#__PURE__*/ jsx(Bubble, {
582
+ const body = /*#__PURE__*/ jsx(MessageBody, {
583
+ message: message,
584
+ labels: labels,
585
+ onOpenUri: onOpenUri
586
+ });
587
+ const footer = /*#__PURE__*/ jsx(MessageFooter, {
588
+ message: message,
589
+ showTime: showTime || 'user' === message.role,
590
+ labels: labels,
591
+ locale: locale,
592
+ onCopy: onCopy
593
+ });
594
+ return /*#__PURE__*/ jsxs("article", {
202
595
  className: `ov-viking-bot__message ov-viking-bot__message--${message.role}`,
203
- placement: 'user' === message.role ? 'end' : 'start',
204
- variant: 'user' === message.role ? 'filled' : 'text',
205
- content: null,
206
- footer: /*#__PURE__*/ jsx(MessageActions, {
207
- message: message,
208
- labels: labels,
209
- onCopy: onCopy,
210
- onMessageAction: onMessageAction
211
- }),
212
- children: /*#__PURE__*/ jsx(MessageBody, {
213
- message: message,
214
- labels: labels,
215
- onOpenUri: onOpenUri
216
- })
596
+ children: [
597
+ 'user' === message.role ? /*#__PURE__*/ jsx(Bubble, {
598
+ className: "ov-viking-bot__user-bubble",
599
+ placement: "end",
600
+ variant: "filled",
601
+ maxHeight: "9999px",
602
+ footer: footer,
603
+ children: body
604
+ }) : message.streaming && 0 === message.parts.length ? /*#__PURE__*/ jsx(Bubble, {
605
+ loading: true,
606
+ placement: "start",
607
+ variant: "text"
608
+ }) : /*#__PURE__*/ jsxs(Fragment, {
609
+ children: [
610
+ body,
611
+ footer
612
+ ]
613
+ }),
614
+ /*#__PURE__*/ jsx(MessageActions, {
615
+ message: message,
616
+ onMessageAction: onMessageAction
617
+ })
618
+ ]
217
619
  });
218
620
  }
219
621
  function VikingBotStreamingRow({ streaming, labels, onOpenUri }) {
@@ -223,21 +625,15 @@ function VikingBotStreamingRow({ streaming, labels, onOpenUri }) {
223
625
  variant: "text",
224
626
  loading: true
225
627
  });
226
- return /*#__PURE__*/ jsx(Bubble, {
227
- className: "ov-viking-bot__message ov-viking-bot__message--assistant",
228
- placement: "start",
229
- variant: "text",
230
- content: null,
231
- children: /*#__PURE__*/ jsx(MessageBody, {
232
- message: {
233
- id: '__streaming__',
234
- role: 'assistant',
235
- parts: streaming.parts,
236
- streaming: true
237
- },
238
- labels: labels,
239
- onOpenUri: onOpenUri
240
- })
628
+ return /*#__PURE__*/ jsx(VikingBotMessageRow, {
629
+ message: {
630
+ id: '__streaming__',
631
+ role: 'assistant',
632
+ parts: streaming.parts,
633
+ streaming: true
634
+ },
635
+ labels: labels,
636
+ onOpenUri: onOpenUri
241
637
  });
242
638
  }
243
639
  const INITIAL_TARGET = {
@@ -247,7 +643,7 @@ const INITIAL_TARGET = {
247
643
  const SCROLLER_STYLE = {
248
644
  paddingLeft: 16,
249
645
  paddingRight: 16,
250
- paddingBottom: 24
646
+ paddingBottom: 48
251
647
  };
252
648
  const TURN_ANCHOR = {
253
649
  behavior: 'smooth',
@@ -263,12 +659,19 @@ const estimateSize = (item)=>{
263
659
  const activityCount = message.parts.filter((part)=>'reasoning' === part.type || 'tool' === part.type).length;
264
660
  return Math.max(72, Math.min(640, 72 + 0.4 * textLength + 48 * activityCount));
265
661
  };
266
- function VikingBotMessageListView({ messages, className, streaming, footer, listKey, onOpenUri, onCopy, onMessageAction, renderMessage, labels: overrides }) {
267
- const labels = {
268
- ...DEFAULT_LABELS,
269
- ...overrides
270
- };
662
+ function VikingBotMessageListView({ messages, className, streaming, footer, listKey, onOpenUri, onCopy, onMessageAction, renderMessage, locale, labels: overrides }) {
663
+ const labels = resolveVikingBotLabels(locale, overrides);
271
664
  const items = toRenderItems(messages, streaming, groupMessages);
665
+ const isStreaming = Boolean(streaming || messages.some((message)=>message.streaming));
666
+ let lastUser;
667
+ const timed = new Set();
668
+ let lastAssistant;
669
+ for (const item of items)if (item.message?.role === 'user') {
670
+ lastUser = item;
671
+ if (lastAssistant) timed.add(lastAssistant);
672
+ lastAssistant = void 0;
673
+ } else if (item.message?.role === 'assistant' && item.message.parts.some((part)=>'text' === part.type)) lastAssistant = item.id;
674
+ if (lastAssistant) timed.add(lastAssistant);
272
675
  return /*#__PURE__*/ jsxs("div", {
273
676
  className: [
274
677
  'ov-viking-bot__list',
@@ -281,12 +684,18 @@ function VikingBotMessageListView({ messages, className, streaming, footer, list
281
684
  getItemKey: (item)=>item.id,
282
685
  estimateItemSize: estimateSize,
283
686
  initialTarget: INITIAL_TARGET,
284
- followOutput: streaming ? 'smooth' : false,
687
+ followOutput: isStreaming ? 'smooth' : false,
688
+ run: lastUser ? {
689
+ anchorItemKey: lastUser.id,
690
+ runKey: lastUser.id,
691
+ status: isStreaming ? 'running' : 'complete'
692
+ } : null,
693
+ scrollToLatestButton: false,
285
694
  turnAnchor: TURN_ANCHOR,
286
695
  atEndThreshold: AT_END_THRESHOLD,
287
696
  scrollerStyle: SCROLLER_STYLE,
288
697
  shortContentAlign: "start",
289
- overscan: 480,
698
+ overscan: 600,
290
699
  renderItem: ({ item })=>item.streaming ? /*#__PURE__*/ jsx(VikingBotStreamingRow, {
291
700
  streaming: item.streaming,
292
701
  labels: labels,
@@ -297,7 +706,9 @@ function VikingBotMessageListView({ messages, className, streaming, footer, list
297
706
  onOpenUri: onOpenUri,
298
707
  onCopy: onCopy,
299
708
  onMessageAction: onMessageAction,
300
- renderMessage: renderMessage
709
+ renderMessage: renderMessage,
710
+ showTime: timed.has(item.id),
711
+ locale: locale
301
712
  }) : null
302
713
  }),
303
714
  footer ? /*#__PURE__*/ jsx("div", {