@antv/dumi-theme-antv 0.8.0-beta.2 → 0.8.0-beta.21

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 (88) hide show
  1. package/dist/builtins/Playground/index.module.less +0 -1
  2. package/dist/components/AI/HomeDialog/AntVBanner/index.module.less +2 -2
  3. package/dist/components/AI/HomeDialog/ModeSelector/ModeSelectorDropdown.js +42 -0
  4. package/dist/components/AI/HomeDialog/ModeSelector/index.module.less +39 -22
  5. package/dist/components/AI/HomeDialog/PromptTextarea/ChooseLib/index.js +12 -4
  6. package/dist/components/AI/HomeDialog/PromptTextarea/ChooseLib/index.module.less +0 -1
  7. package/dist/components/AI/HomeDialog/PromptTextarea/DatasourceCard/index.module.less +3 -3
  8. package/dist/components/AI/HomeDialog/PromptTextarea/index.js +38 -36
  9. package/dist/components/AI/HomeDialog/PromptTextarea/index.module.less +8 -8
  10. package/dist/components/AI/HomeDialog/RecommendCase/Card.js +14 -11
  11. package/dist/components/AI/HomeDialog/RecommendCase/card.module.less +3 -3
  12. package/dist/components/AI/HomeDialog/RecommendCase/index.js +73 -24
  13. package/dist/components/AI/HomeDialog/RecommendCase/index.module.less +4 -2
  14. package/dist/components/AI/HomeDialog/RecommendCase/recommend.json +41 -17
  15. package/dist/components/AI/HomeDialog/index.js +21 -33
  16. package/dist/components/AI/constant.js +4 -2
  17. package/dist/components/Login/Captcha/index.js +185 -0
  18. package/dist/components/Login/Captcha/index.less +91 -0
  19. package/dist/components/Login/CheckCode/index.js +244 -0
  20. package/dist/components/Login/CheckCode/index.less +137 -0
  21. package/dist/components/Login/CountDownButton/index.js +109 -0
  22. package/dist/components/Login/CountDownButton/index.less +8 -0
  23. package/dist/components/Login/LoginForm.js +239 -0
  24. package/dist/components/Login/LoginForm.less +409 -0
  25. package/dist/components/Login/index.js +24 -0
  26. package/dist/components/Login/openAuthWindow.js +54 -0
  27. package/dist/components/Login/types.js +5 -0
  28. package/dist/components/Login/utils.js +47 -0
  29. package/dist/hooks/useProducts.js +22 -1
  30. package/dist/layouts/DocLayout.js +2 -1
  31. package/dist/layouts/GlobalLayout/index.js +11 -4
  32. package/dist/locales/en.json +43 -2
  33. package/dist/locales/zh.json +43 -2
  34. package/dist/model/AIChat.js +93 -6
  35. package/dist/model/auth.js +147 -0
  36. package/dist/pages/AIPlayground/components/ConversationsMenu/index.js +15 -7
  37. package/dist/pages/AIPlayground/components/ConversationsMenu/index.module.less +2 -0
  38. package/dist/pages/AIPlayground/components/MarkdownComponent/MarkdownCodeBlock.js +26 -17
  39. package/dist/pages/AIPlayground/components/MarkdownComponent/MarkdownCodeBlock.module.less +1 -2
  40. package/dist/pages/AIPlayground/components/MarkdownComponent/index.js +7 -4
  41. package/dist/pages/AIPlayground/components/MsgBox/index.js +266 -149
  42. package/dist/pages/AIPlayground/components/MsgBox/index.module.less +3 -2
  43. package/dist/pages/AIPlayground/components/MsgBox/useAutoScroll.js +46 -0
  44. package/dist/pages/AIPlayground/components/SessionLayout/index.js +41 -12
  45. package/dist/pages/AIPlayground/components/SessionLayout/index.module.less +4 -4
  46. package/dist/pages/AIPlayground/components/TaskBox/generateCode.js +129 -8
  47. package/dist/pages/AIPlayground/components/TaskBox/index.js +92 -55
  48. package/dist/pages/AIPlayground/components/TaskBox/index.module.less +1 -0
  49. package/dist/pages/AIPlayground/index.js +4 -1
  50. package/dist/pages/AIPlayground/index.module.less +5 -0
  51. package/dist/pages/Examples/components/Accouncement/index.module.less +1 -1
  52. package/dist/pages/Examples/index.module.less +11 -11
  53. package/dist/pages/Index/components/Cases/index.module.less +8 -8
  54. package/dist/pages/Index/components/Companies/index.module.less +4 -3
  55. package/dist/pages/Index/components/Features/FeatureCard.module.less +4 -5
  56. package/dist/pages/Index/components/Features/index.module.less +5 -5
  57. package/dist/pages/Index/components/_.less +9 -9
  58. package/dist/slots/Banner/Notification.module.less +8 -8
  59. package/dist/slots/Banner/index.module.less +10 -9
  60. package/dist/slots/CodeEditor/Toolbar.js +7 -25
  61. package/dist/slots/CodeEditor/index.js +34 -12
  62. package/dist/slots/CodeEditor/index.module.less +3 -1
  63. package/dist/slots/CodeEditor/utils.js +2 -1
  64. package/dist/slots/CodePreview/index.module.less +0 -3
  65. package/dist/slots/CodeRunner/index.js +23 -11
  66. package/dist/slots/ContentTable/index.module.less +2 -1
  67. package/dist/slots/Detail/News.module.less +9 -9
  68. package/dist/slots/Detail/index.js +2 -1
  69. package/dist/slots/Detail/index.module.less +11 -14
  70. package/dist/slots/ExampleSider/index.module.less +3 -4
  71. package/dist/slots/Footer/index.module.less +2 -2
  72. package/dist/slots/Header/Products/Product.module.less +2 -2
  73. package/dist/slots/Header/Search/SearchResult.js +20 -8
  74. package/dist/slots/Header/Search/SearchResult.module.less +1 -0
  75. package/dist/slots/Header/index.js +51 -25
  76. package/dist/slots/Header/index.module.less +13 -5
  77. package/dist/slots/LiveExample/index.module.less +1 -1
  78. package/dist/slots/Loading/index.module.less +30 -28
  79. package/dist/slots/ManualContent/index.module.less +14 -17
  80. package/dist/slots/_.less +9 -9
  81. package/dist/static/user.svg +3 -0
  82. package/dist/typings.d.ts +6 -0
  83. package/dist/utils/analytics.js +16 -0
  84. package/dist/utils/env.js +63 -0
  85. package/dist/utils/index.js +7 -0
  86. package/dist/utils/request.js +42 -0
  87. package/package.json +9 -5
  88. package/dist/static/SearchAiIcon.svg +0 -14
@@ -1,27 +1,29 @@
1
- function _toConsumableArray(arr) { return _arrayWithoutHoles(arr) || _iterableToArray(arr) || _unsupportedIterableToArray(arr) || _nonIterableSpread(); }
2
- function _nonIterableSpread() { throw new TypeError("Invalid attempt to spread non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); }
3
- function _iterableToArray(iter) { if (typeof Symbol !== "undefined" && iter[Symbol.iterator] != null || iter["@@iterator"] != null) return Array.from(iter); }
4
- function _arrayWithoutHoles(arr) { if (Array.isArray(arr)) return _arrayLikeToArray(arr); }
1
+ function _typeof(o) { "@babel/helpers - typeof"; return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && "function" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? "symbol" : typeof o; }, _typeof(o); }
5
2
  function _slicedToArray(arr, i) { return _arrayWithHoles(arr) || _iterableToArrayLimit(arr, i) || _unsupportedIterableToArray(arr, i) || _nonIterableRest(); }
6
3
  function _nonIterableRest() { throw new TypeError("Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); }
7
4
  function _unsupportedIterableToArray(o, minLen) { if (!o) return; if (typeof o === "string") return _arrayLikeToArray(o, minLen); var n = Object.prototype.toString.call(o).slice(8, -1); if (n === "Object" && o.constructor) n = o.constructor.name; if (n === "Map" || n === "Set") return Array.from(o); if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _arrayLikeToArray(o, minLen); }
8
5
  function _arrayLikeToArray(arr, len) { if (len == null || len > arr.length) len = arr.length; for (var i = 0, arr2 = new Array(len); i < len; i++) arr2[i] = arr[i]; return arr2; }
9
6
  function _iterableToArrayLimit(r, l) { var t = null == r ? null : "undefined" != typeof Symbol && r[Symbol.iterator] || r["@@iterator"]; if (null != t) { var e, n, i, u, a = [], f = !0, o = !1; try { if (i = (t = t.call(r)).next, 0 === l) { if (Object(t) !== t) return; f = !1; } else for (; !(f = (e = i.call(t)).done) && (a.push(e.value), a.length !== l); f = !0); } catch (r) { o = !0, n = r; } finally { try { if (!f && null != t.return && (u = t.return(), Object(u) !== u)) return; } finally { if (o) throw n; } } return a; } }
10
7
  function _arrayWithHoles(arr) { if (Array.isArray(arr)) return arr; }
11
- import { CheckOutlined, CopyOutlined, DislikeOutlined, LikeOutlined, PlusSquareOutlined, SyncOutlined } from '@ant-design/icons';
8
+ import { BranchesOutlined, CheckOutlined, CopyOutlined, DeleteOutlined, PlusSquareOutlined, SyncOutlined, ToolOutlined } from '@ant-design/icons';
12
9
  import { Bubble } from '@ant-design/x';
13
10
  import { Button, Flex, Space, Tooltip } from 'antd';
14
- import { history, useSiteData, useIntl } from 'dumi';
11
+ import { useChat } from '@ai-sdk/react';
12
+ import { TextStreamChatTransport } from 'ai';
13
+ import { useIntl, useSiteData } from 'dumi';
15
14
  import { findLast } from 'lodash-es';
16
- import React, { useEffect, useState } from 'react';
15
+ import React, { useEffect, useState, useMemo, useRef } from 'react';
17
16
  import { useCopyToClipboard } from 'react-use';
18
17
  import { useSnapshot } from 'valtio';
19
18
  import { PromptTextarea } from "../../../../components/AI/HomeDialog/PromptTextarea";
20
- import { useStreamingText } from "../../../../hooks/useStreamingText";
21
- import { AIChatStore, clearEmptySession, createPureNewSession, derivedState } from "../../../../model/AIChat";
19
+ import { AIChatStore, branchMessage, clearEmptySession, createPureNewSession, deleteMessage, derivedState } from "../../../../model/AIChat";
22
20
  import { getCodeFromMarkdown, isPreviewable } from "../../../../utils/code";
23
21
  import { MarkdownComponent } from "../MarkdownComponent";
24
22
  import styles from "./index.module.less";
23
+ import { useAutoScroll } from "./useAutoScroll";
24
+ import { getBaseURL } from "../../../../utils/env";
25
+ import { AIMode } from "../../../../components/AI/constant";
26
+ import { trackEvent } from "../../../../utils/analytics";
25
27
  var avatar = {
26
28
  icon: /*#__PURE__*/React.createElement("img", {
27
29
  draggable: false,
@@ -35,42 +37,52 @@ var avatar = {
35
37
  };
36
38
  var chatScrollIntoView = function chatScrollIntoView() {
37
39
  setTimeout(function () {
38
- var nodeList = document.querySelectorAll('.ant-bubble');
39
- nodeList[nodeList.length - 1].scrollIntoView({
40
- behavior: 'smooth'
40
+ document.getElementById('msgBoxAnchor').scrollIntoView({
41
+ block: 'end'
41
42
  });
43
+ }, 100);
44
+ };
45
+
46
+ // 辅助函数:将旧的 Message 格式转换为新的 UIMessage 格式
47
+ var convertToUIMessages = function convertToUIMessages(messages) {
48
+ return messages.map(function (msg) {
49
+ return {
50
+ id: msg.id,
51
+ role: msg.role,
52
+ parts: [{
53
+ type: 'text',
54
+ text: msg.content
55
+ }]
56
+ };
42
57
  });
43
58
  };
59
+
60
+ // 辅助函数:从 UIMessage 提取文本内容
61
+ var getTextContent = function getTextContent(message) {
62
+ return message.parts.filter(function (part) {
63
+ return part.type === 'text';
64
+ }).map(function (part) {
65
+ return part.text;
66
+ }).join('');
67
+ };
44
68
  function MsgBox(props) {
45
- var _derivedSnap$activeSe, _derivedSnap$activeSe2, _derivedSnap$activeSe3;
69
+ var _derivedSnap$activeSe, _derivedSnap$activeSe2, _derivedSnap$activeSe4, _derivedSnap$activeSe7, _derivedSnap$activeSe8, _messages;
46
70
  var _props$messages = props.messages,
47
- messages = _props$messages === void 0 ? [] : _props$messages,
71
+ initialMessages = _props$messages === void 0 ? [] : _props$messages,
48
72
  _props$simple = props.simple,
49
73
  simple = _props$simple === void 0 ? false : _props$simple,
50
- _props$context = props.context,
51
- context = _props$context === void 0 ? '' : _props$context,
52
74
  onCodegen = props.onCodegen,
53
75
  title = props.title;
54
- var _useSiteData = useSiteData(),
55
- themeConfig = _useSiteData.themeConfig;
56
76
  var _useIntl = useIntl(),
57
77
  formatMessage = _useIntl.formatMessage;
58
- var _useState = useState(!themeConfig.isAntVSite ? themeConfig.title : undefined),
78
+ var _useState = useState(''),
59
79
  _useState2 = _slicedToArray(_useState, 2),
60
- lib = _useState2[0],
61
- setLib = _useState2[1];
80
+ promptText = _useState2[0],
81
+ setPromptText = _useState2[1];
62
82
  var _useState3 = useState(''),
63
83
  _useState4 = _slicedToArray(_useState3, 2),
64
- promptText = _useState4[0],
65
- setPromptText = _useState4[1];
66
- var _useState5 = useState(false),
67
- _useState6 = _slicedToArray(_useState5, 2),
68
- isStreaming = _useState6[0],
69
- setIsStreaming = _useState6[1]; // trigger
70
- var _useState7 = useState(false),
71
- _useState8 = _slicedToArray(_useState7, 2),
72
- loading = _useState8[0],
73
- setLoading = _useState8[1];
84
+ fileSummary = _useState4[0],
85
+ setFileSummary = _useState4[1];
74
86
  var snap = useSnapshot(AIChatStore);
75
87
  var derivedSnap = useSnapshot(derivedState);
76
88
  var _useCopyToClipboard = useCopyToClipboard(),
@@ -80,81 +92,109 @@ function MsgBox(props) {
80
92
  var latestUserMessage = findLast((_derivedSnap$activeSe = derivedSnap.activeSession) === null || _derivedSnap$activeSe === void 0 ? void 0 : _derivedSnap$activeSe.messages, function (msg) {
81
93
  return msg.role === 'user';
82
94
  });
83
- var _useState9 = useState(''),
84
- _useState10 = _slicedToArray(_useState9, 2),
85
- fileSummary = _useState10[0],
86
- setFileSummary = _useState10[1];
87
- var streamingText = useStreamingText({
88
- url: 'https://webgw-pre.alipay.com/visqaservice/external/chat',
89
- method: 'POST',
90
- body: {
91
- gptConversationId: (_derivedSnap$activeSe2 = derivedSnap.activeSession) === null || _derivedSnap$activeSe2 === void 0 ? void 0 : _derivedSnap$activeSe2.id,
92
- query: latestUserMessage === null || latestUserMessage === void 0 ? void 0 : latestUserMessage.content,
93
- library: (latestUserMessage === null || latestUserMessage === void 0 ? void 0 : latestUserMessage.lib) || lib,
94
- mode: latestUserMessage === null || latestUserMessage === void 0 ? void 0 : latestUserMessage.mode,
95
- anonymousUserId: snap.anonymousUserId,
96
- context: (latestUserMessage === null || latestUserMessage === void 0 ? void 0 : latestUserMessage.context) || context,
97
- mountId: "container"
98
- },
99
- trigger: isStreaming,
100
- // isStreaming 状态作为 trigger
101
- headers: {
102
- 'Content-Type': 'application/json',
103
- 'x-webgw-version': '2.0',
104
- 'x-webgw-appid': '180020010001210065'
105
- },
106
- beforeStart: function beforeStart() {
107
- setLoading(true);
108
- },
109
- onFinish: function onFinish(finalText) {
110
- try {
111
- var _derivedState$activeS;
112
- var finalJSON = JSON.parse(finalText);
113
- (_derivedState$activeS = derivedState.activeSession) === null || _derivedState$activeS === void 0 || (_derivedState$activeS = _derivedState$activeS.messages) === null || _derivedState$activeS === void 0 || _derivedState$activeS.push({
95
+ // 使用 ref 存储动态值,避免重新创建 transport
96
+ var anonymousUserIdRef = useRef(snap.anonymousUserId);
97
+ var activeSessionIdRef = useRef((_derivedSnap$activeSe2 = derivedSnap.activeSession) === null || _derivedSnap$activeSe2 === void 0 ? void 0 : _derivedSnap$activeSe2.id);
98
+ var _useSiteData = useSiteData(),
99
+ themeConfig = _useSiteData.themeConfig;
100
+ useEffect(function () {
101
+ var _derivedSnap$activeSe3;
102
+ anonymousUserIdRef.current = snap.anonymousUserId;
103
+ activeSessionIdRef.current = (_derivedSnap$activeSe3 = derivedSnap.activeSession) === null || _derivedSnap$activeSe3 === void 0 ? void 0 : _derivedSnap$activeSe3.id;
104
+ }, [snap.anonymousUserId, (_derivedSnap$activeSe4 = derivedSnap.activeSession) === null || _derivedSnap$activeSe4 === void 0 ? void 0 : _derivedSnap$activeSe4.id]);
105
+
106
+ // 转换初始消息为新格式
107
+ var convertedInitialMessages = useMemo(function () {
108
+ return convertToUIMessages(initialMessages);
109
+ }, [initialMessages]);
110
+
111
+ // 核心:使用 useChat hook,配置 DefaultChatTransport
112
+ var _useChat = useChat({
113
+ transport: new TextStreamChatTransport({
114
+ api: getBaseURL() + '/api/modules/antv/ai/chat',
115
+ credentials: 'include',
116
+ headers: {
117
+ // xxx
118
+ },
119
+ // body 可以是函数,用于获取最新的动态值
120
+ body: function body() {
121
+ return {
122
+ gptConversationId: activeSessionIdRef.current,
123
+ anonymousUserId: anonymousUserIdRef.current,
124
+ mountId: 'container',
125
+ antvContext: (latestUserMessage === null || latestUserMessage === void 0 ? void 0 : latestUserMessage.context) || props.context,
126
+ library: AIChatStore.lib,
127
+ mode: AIChatStore.mode
128
+ };
129
+ }
130
+ }),
131
+ messages: convertedInitialMessages,
132
+ // 当AI响应结束时触发
133
+ onFinish: function onFinish(_ref) {
134
+ var message = _ref.message,
135
+ isAbort = _ref.isAbort,
136
+ isDisconnect = _ref.isDisconnect,
137
+ isError = _ref.isError;
138
+ if (!isAbort && !isDisconnect && !isError) {
139
+ var _derivedState$activeS;
140
+ var messageContent = getTextContent(message);
141
+ if (isPreviewable(messageContent)) {
142
+ var codeBlock = getCodeFromMarkdown(messageContent).code;
143
+ AIChatStore.codeBlock = codeBlock;
144
+ onCodegen === null || onCodegen === void 0 || onCodegen(codeBlock);
145
+ } else {
146
+ AIChatStore.codeBlock = '';
147
+ }
148
+ (_derivedState$activeS = derivedState.activeSession) === null || _derivedState$activeS === void 0 || (_derivedState$activeS = _derivedState$activeS.messages) === null || _derivedState$activeS === void 0 || _derivedState$activeS.push({
149
+ id: crypto.randomUUID(),
150
+ role: 'assistant',
151
+ content: messageContent,
152
+ createdAt: Date.now()
153
+ });
154
+ }
155
+ },
156
+ onError: function onError(error) {
157
+ var _derivedState$activeS2;
158
+ console.error('回答失败', error);
159
+ // 同步错误消息到 valtio
160
+ (_derivedState$activeS2 = derivedState.activeSession) === null || _derivedState$activeS2 === void 0 || (_derivedState$activeS2 = _derivedState$activeS2.messages) === null || _derivedState$activeS2 === void 0 || _derivedState$activeS2.push({
114
161
  id: crypto.randomUUID(),
115
162
  role: 'assistant',
116
- content: finalJSON.content,
163
+ content: formatMessage({
164
+ id: 'ai.msgbox.error.response'
165
+ }),
117
166
  createdAt: Date.now()
118
167
  // mode,
119
168
  // lib,
120
169
  });
121
- if (isPreviewable(finalJSON.content)) {
122
- var codeBlock = getCodeFromMarkdown(finalJSON.content).code;
123
- AIChatStore.codeBlock = codeBlock;
124
- onCodegen === null || onCodegen === void 0 || onCodegen(codeBlock);
125
- }
126
- } catch (e) {
127
- // 说明不是JSON格式
128
- } finally {
129
- // 当流结束时,更新最后一条消息并重置 trigger
130
- setIsStreaming(false); // **关键:流结束后,关闭 trigger**
131
- setLoading(false);
132
- chatScrollIntoView();
133
170
  }
134
- },
135
- onError: function onError(error) {
136
- var _derivedState$activeS2;
137
- console.log('回答失败', error);
138
- // 处理错误
139
- (_derivedState$activeS2 = derivedState.activeSession) === null || _derivedState$activeS2 === void 0 || (_derivedState$activeS2 = _derivedState$activeS2.messages) === null || _derivedState$activeS2 === void 0 || _derivedState$activeS2.push({
140
- id: crypto.randomUUID(),
141
- role: 'assistant',
142
- content: formatMessage({
143
- id: 'ai.msgbox.error.response'
144
- }),
145
- createdAt: Date.now()
146
- // mode,
147
- // lib,
148
- });
149
- setIsStreaming(false);
150
- setLoading(false);
151
- }
152
- });
171
+ }),
172
+ messages = _useChat.messages,
173
+ setMessages = _useChat.setMessages,
174
+ sendMessage = _useChat.sendMessage,
175
+ regenerate = _useChat.regenerate,
176
+ status = _useChat.status,
177
+ stop = _useChat.stop;
153
178
 
154
- // 3. 处理用户提交
179
+ // 处理用户提交
155
180
  var handleSubmit = function handleSubmit() {
156
- var _derivedState$activeS3;
157
- if (!promptText.trim() || isStreaming) return; // 如果正在流式输出,则不允许发送
181
+ var _derivedSnap$activeSe5, _derivedState$activeS3;
182
+ var trimmedPrompt = promptText.trim();
183
+ if (!trimmedPrompt || status === 'streaming' || status === 'submitted') return;
184
+ if (derivedSnap.activeSession && ((_derivedSnap$activeSe5 = derivedSnap.activeSession.messages) === null || _derivedSnap$activeSe5 === void 0 ? void 0 : _derivedSnap$activeSe5.length) === 0) {
185
+ derivedState.activeSession.title = trimmedPrompt;
186
+ }
187
+ // 使用 sendMessage 函数发送新消息
188
+ // 第二个参数传递每次请求特定的额外数据
189
+ sendMessage({
190
+ text: promptText
191
+ }, {
192
+ body: {
193
+ // context: fileSummary,
194
+ // lib: snap.lib,
195
+ // mode: snap.mode,
196
+ }
197
+ });
158
198
  setPromptText('');
159
199
  (_derivedState$activeS3 = derivedState.activeSession) === null || _derivedState$activeS3 === void 0 || (_derivedState$activeS3 = _derivedState$activeS3.messages) === null || _derivedState$activeS3 === void 0 || _derivedState$activeS3.push({
160
200
  id: crypto.randomUUID(),
@@ -162,128 +202,205 @@ function MsgBox(props) {
162
202
  content: promptText,
163
203
  createdAt: Date.now(),
164
204
  context: fileSummary,
165
- lib: lib
205
+ lib: snap.lib
166
206
  });
167
- // **关键:开启 trigger,开始请求**
168
- setIsStreaming(true);
169
207
  chatScrollIntoView();
208
+ // 埋点
209
+ if ((typeof window === "undefined" ? "undefined" : _typeof(window)) === 'object') {
210
+ trackEvent('start_ai_chat', {
211
+ entry_point: simple ? 'Drawer' : 'MsgBox',
212
+ mode: AIChatStore.mode,
213
+ lib: AIChatStore.lib,
214
+ page_title: document.title,
215
+ location: location.href
216
+ });
217
+ }
170
218
  };
219
+
220
+ // 同步 Valtio store -> useChat state
171
221
  useEffect(function () {
172
- // 检查是否存在临时消息
173
- if (snap.tempMessage) {
174
- var activeSession = derivedState.activeSession;
175
- if (activeSession) {
176
- // 1. 将临时消息正式添加到当前会话中
177
- activeSession.messages.push(snap.tempMessage);
178
- setIsStreaming(true);
179
- AIChatStore.tempMessage = null;
222
+ if (simple) {
223
+ return;
224
+ }
225
+ setTimeout(function () {
226
+ var _derivedSnap$activeSe6;
227
+ var sessionMessages = (_derivedSnap$activeSe6 = derivedSnap.activeSession) === null || _derivedSnap$activeSe6 === void 0 ? void 0 : _derivedSnap$activeSe6.messages;
228
+ if ((sessionMessages === null || sessionMessages === void 0 ? void 0 : sessionMessages.length) > 0) {
229
+ var converted = convertToUIMessages(sessionMessages);
230
+ // 避免无限循环,仅当消息数量或内容不同时更新
231
+ if (messages.length !== converted.length || JSON.stringify(messages) !== JSON.stringify(converted)) {
232
+ setMessages(converted);
233
+ }
234
+ } else {
235
+ setMessages([]);
180
236
  }
237
+ });
238
+ }, [(_derivedSnap$activeSe7 = derivedSnap.activeSession) === null || _derivedSnap$activeSe7 === void 0 ? void 0 : _derivedSnap$activeSe7.id, (_derivedSnap$activeSe8 = derivedSnap.activeSession) === null || _derivedSnap$activeSe8 === void 0 || (_derivedSnap$activeSe8 = _derivedSnap$activeSe8.messages) === null || _derivedSnap$activeSe8 === void 0 ? void 0 : _derivedSnap$activeSe8.length]);
239
+
240
+ // 处理从外部(如demo页)发起的对话
241
+ useEffect(function () {
242
+ if (snap.tempMessage) {
243
+ var _derivedState$activeS4, _derivedState$activeS5;
244
+ sendMessage({
245
+ text: snap.tempMessage.content
246
+ });
247
+ (_derivedState$activeS4 = derivedState.activeSession) === null || _derivedState$activeS4 === void 0 || (_derivedState$activeS4 = _derivedState$activeS4.messages) === null || _derivedState$activeS4 === void 0 || (_derivedState$activeS5 = _derivedState$activeS4.push) === null || _derivedState$activeS5 === void 0 || _derivedState$activeS5.call(_derivedState$activeS4, snap.tempMessage);
248
+ AIChatStore.tempMessage = null;
181
249
  }
250
+ }, [snap.tempMessage]);
251
+ useEffect(function () {
252
+ chatScrollIntoView();
182
253
  if (simple) {
183
254
  createPureNewSession(title);
255
+ AIChatStore.mode = AIMode.implement;
256
+ if (!themeConfig.isAntVSite && themeConfig.title) {
257
+ AIChatStore.lib = themeConfig.title;
258
+ }
184
259
  }
185
260
  return function () {
186
- clearEmptySession();
261
+ if (simple) {
262
+ clearEmptySession();
263
+ }
187
264
  };
188
265
  }, []);
189
266
  useEffect(function () {
190
- if (derivedState.activeSession && Date.now() - derivedState.activeSession.createdAt > 5000) {
191
- setLoading(false);
192
- setIsStreaming(false);
193
- }
267
+ chatScrollIntoView();
268
+ stop();
269
+ AIChatStore.errorMsg = null;
194
270
  }, [snap.activeSessionId]);
195
- var showMessages = [].concat(_toConsumableArray(messages), _toConsumableArray(((_derivedSnap$activeSe3 = derivedSnap.activeSession) === null || _derivedSnap$activeSe3 === void 0 ? void 0 : _derivedSnap$activeSe3.messages) || []));
271
+
272
+ // 将 messages 数组作为依赖项。当它变化时,Hook 会运行。
273
+ var _useAutoScroll = useAutoScroll(messages),
274
+ containerRef = _useAutoScroll.containerRef,
275
+ anchorRef = _useAutoScroll.anchorRef;
276
+ var autofix = function autofix() {
277
+ var _derivedState$activeS6;
278
+ var autoFixPromptText = "".concat(formatMessage({
279
+ id: 'ai.msgbox.auto.fix.prompt'
280
+ }), " [").concat(snap.errorMsg, "]");
281
+ sendMessage({
282
+ text: autoFixPromptText
283
+ }, {
284
+ body: {
285
+ antvContext: snap.codeBlock
286
+ }
287
+ });
288
+ AIChatStore.errorMsg = null;
289
+ (_derivedState$activeS6 = derivedState.activeSession) === null || _derivedState$activeS6 === void 0 || (_derivedState$activeS6 = _derivedState$activeS6.messages) === null || _derivedState$activeS6 === void 0 || _derivedState$activeS6.push({
290
+ id: crypto.randomUUID(),
291
+ role: 'user',
292
+ content: autoFixPromptText,
293
+ createdAt: Date.now(),
294
+ context: snap.codeBlock,
295
+ lib: snap.lib
296
+ });
297
+ chatScrollIntoView();
298
+ };
196
299
  return /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement(Flex, {
197
300
  gap: "middle",
198
301
  vertical: true,
199
- className: styles.chatContainer
200
- }, showMessages === null || showMessages === void 0 ? void 0 : showMessages.map(function (msg, index) {
302
+ className: styles.chatContainer,
303
+ ref: containerRef
304
+ }, messages.map(function (msg, index) {
305
+ var textContent = getTextContent(msg);
201
306
  return /*#__PURE__*/React.createElement(Bubble, {
202
- key: index,
307
+ key: msg.id || index,
203
308
  content: /*#__PURE__*/React.createElement(MarkdownComponent, {
204
- content: msg.content
309
+ content: textContent,
310
+ showRunButton: !props.simple
205
311
  }),
206
312
  avatar: msg.role === 'assistant' ? avatar : null,
207
- footer: msg.role === 'assistant' && index > 0 ? /*#__PURE__*/React.createElement(Space, {
313
+ footer: status === 'ready' && /*#__PURE__*/React.createElement(Space, {
208
314
  size: "small"
209
- }, /*#__PURE__*/React.createElement(Tooltip, {
315
+ }, msg.role === 'assistant' && index === messages.length - 1 && /*#__PURE__*/React.createElement(Tooltip, {
210
316
  title: formatMessage({
211
- id: 'ai.msgbox.like'
317
+ id: 'ai.msgbox.retry'
212
318
  })
213
319
  }, /*#__PURE__*/React.createElement(Button, {
320
+ onClick: function onClick() {
321
+ regenerate();
322
+ derivedState.activeSession.messages.pop();
323
+ },
214
324
  color: "default",
215
325
  variant: "text",
216
326
  size: "small",
217
- icon: /*#__PURE__*/React.createElement(LikeOutlined, null)
327
+ icon: /*#__PURE__*/React.createElement(SyncOutlined, null)
218
328
  })), /*#__PURE__*/React.createElement(Tooltip, {
219
329
  title: formatMessage({
220
- id: 'ai.msgbox.dislike'
330
+ id: 'ai.msgbox.copy'
221
331
  })
222
332
  }, /*#__PURE__*/React.createElement(Button, {
223
333
  color: "default",
224
334
  variant: "text",
225
335
  size: "small",
226
- icon: /*#__PURE__*/React.createElement(DislikeOutlined, null)
227
- })), index === showMessages.length - 1 && /*#__PURE__*/React.createElement(Tooltip, {
336
+ onClick: function onClick() {
337
+ return copyToClipboard(textContent);
338
+ },
339
+ icon: copyState.value === textContent ? /*#__PURE__*/React.createElement(CheckOutlined, null) : /*#__PURE__*/React.createElement(CopyOutlined, null)
340
+ })), /*#__PURE__*/React.createElement(Tooltip, {
228
341
  title: formatMessage({
229
- id: 'ai.msgbox.retry'
342
+ id: 'ai.msgbox.continue.from.here'
230
343
  })
231
344
  }, /*#__PURE__*/React.createElement(Button, {
232
- onClick: function onClick() {
233
- derivedState.activeSession.messages.pop();
234
- setIsStreaming(true);
235
- },
236
345
  color: "default",
237
346
  variant: "text",
238
347
  size: "small",
239
- icon: /*#__PURE__*/React.createElement(SyncOutlined, null)
240
- })), /*#__PURE__*/React.createElement(Tooltip, {
348
+ onClick: function onClick() {
349
+ return branchMessage(index);
350
+ },
351
+ icon: /*#__PURE__*/React.createElement(BranchesOutlined, null)
352
+ })), msg.role === 'assistant' && /*#__PURE__*/React.createElement(Tooltip, {
241
353
  title: formatMessage({
242
- id: 'ai.msgbox.copy'
354
+ id: 'ai.msgbox.delete'
243
355
  })
244
356
  }, /*#__PURE__*/React.createElement(Button, {
245
357
  color: "default",
246
358
  variant: "text",
247
359
  size: "small",
248
360
  onClick: function onClick() {
249
- return copyToClipboard(msg.content);
361
+ return deleteMessage(msg.id);
250
362
  },
251
- icon: copyState.value === msg.content ? /*#__PURE__*/React.createElement(CheckOutlined, null) : /*#__PURE__*/React.createElement(CopyOutlined, null)
252
- }))) : null,
363
+ icon: /*#__PURE__*/React.createElement(DeleteOutlined, null)
364
+ }))),
253
365
  placement: msg.role === 'user' ? 'end' : 'start'
254
366
  });
255
- }), loading && /*#__PURE__*/React.createElement(Bubble, {
367
+ }), (status === 'streaming' || status === 'submitted') && ((_messages = messages[messages.length - 1]) === null || _messages === void 0 ? void 0 : _messages.role) === 'user' && /*#__PURE__*/React.createElement(Bubble, {
256
368
  placement: "start",
257
369
  avatar: avatar,
258
- loading: loading
370
+ loading: true
371
+ }), /*#__PURE__*/React.createElement("div", {
372
+ ref: anchorRef,
373
+ id: "msgBoxAnchor"
259
374
  })), /*#__PURE__*/React.createElement("div", null, !props.simple && /*#__PURE__*/React.createElement("div", {
260
375
  className: styles.newButtonContainer
261
- }, /*#__PURE__*/React.createElement("button", {
376
+ }, /*#__PURE__*/React.createElement(Space, null, /*#__PURE__*/React.createElement("button", {
262
377
  type: "button",
263
378
  onClick: function onClick() {
264
- return history.push('/');
379
+ return createPureNewSession();
265
380
  },
266
381
  className: styles.newButton
267
382
  }, /*#__PURE__*/React.createElement(Space, null, /*#__PURE__*/React.createElement(PlusSquareOutlined, null), formatMessage({
268
383
  id: 'ai.msgbox.start.new.chat'
384
+ }))), snap.errorMsg && status === 'ready' && /*#__PURE__*/React.createElement(Button, {
385
+ onClick: autofix,
386
+ color: "danger",
387
+ variant: "filled",
388
+ icon: /*#__PURE__*/React.createElement(ToolOutlined, null)
389
+ }, formatMessage({
390
+ id: 'ai.msgbox.auto.fix'
269
391
  })))), /*#__PURE__*/React.createElement(PromptTextarea, {
270
392
  size: "compact",
271
- mode: "implement",
272
393
  value: promptText,
273
394
  onChange: setPromptText,
274
- loading: loading,
275
- onCancel: function onCancel() {
276
- setIsStreaming(false);
277
- setLoading(false);
278
- },
395
+ loading: status === 'streaming' || status === 'submitted',
396
+ onCancel: stop,
279
397
  showAction: !props.simple,
280
398
  style: {
281
399
  marginBottom: 0
282
400
  },
283
401
  onConfirm: handleSubmit,
284
- lib: lib,
285
- onLibChange: setLib,
286
- onDataSummaryChange: setFileSummary
402
+ onDataSummaryChange: setFileSummary,
403
+ showModeSelector: true
287
404
  })));
288
405
  }
289
406
  export default MsgBox;
@@ -5,7 +5,7 @@
5
5
 
6
6
  .query {
7
7
  background: #c9dfff;
8
- box-shadow: 0 4px 10px rgba(51, 113, 242, .1);
8
+ box-shadow: 0 4px 10px rgba(51, 113, 242, 10%);
9
9
  border-radius: 8px;
10
10
  padding: 8px 16px;
11
11
  max-width: calc(100% - 100px);
@@ -26,7 +26,7 @@
26
26
  padding: 0 8px;
27
27
  color: var(--primary-color);
28
28
  font-size: 14px;
29
- background: rgba(135, 59, 244, .145);
29
+ background: rgba(135, 59, 244, 14.5%);
30
30
  border-radius: 6px;
31
31
  line-height: 22px;
32
32
  margin: 12px auto;
@@ -34,6 +34,7 @@
34
34
 
35
35
  .newButtonContainer {
36
36
  display: flex;
37
+ justify-content: center;
37
38
  }
38
39
 
39
40
  .chatContainer {
@@ -0,0 +1,46 @@
1
+ function _slicedToArray(arr, i) { return _arrayWithHoles(arr) || _iterableToArrayLimit(arr, i) || _unsupportedIterableToArray(arr, i) || _nonIterableRest(); }
2
+ function _nonIterableRest() { throw new TypeError("Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); }
3
+ function _unsupportedIterableToArray(o, minLen) { if (!o) return; if (typeof o === "string") return _arrayLikeToArray(o, minLen); var n = Object.prototype.toString.call(o).slice(8, -1); if (n === "Object" && o.constructor) n = o.constructor.name; if (n === "Map" || n === "Set") return Array.from(o); if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _arrayLikeToArray(o, minLen); }
4
+ function _arrayLikeToArray(arr, len) { if (len == null || len > arr.length) len = arr.length; for (var i = 0, arr2 = new Array(len); i < len; i++) arr2[i] = arr[i]; return arr2; }
5
+ function _iterableToArrayLimit(r, l) { var t = null == r ? null : "undefined" != typeof Symbol && r[Symbol.iterator] || r["@@iterator"]; if (null != t) { var e, n, i, u, a = [], f = !0, o = !1; try { if (i = (t = t.call(r)).next, 0 === l) { if (Object(t) !== t) return; f = !1; } else for (; !(f = (e = i.call(t)).done) && (a.push(e.value), a.length !== l); f = !0); } catch (r) { o = !0, n = r; } finally { try { if (!f && null != t.return && (u = t.return(), Object(u) !== u)) return; } finally { if (o) throw n; } } return a; } }
6
+ function _arrayWithHoles(arr) { if (Array.isArray(arr)) return arr; }
7
+ import { useRef, useLayoutEffect, useState } from 'react';
8
+
9
+ // threshold: 容差值,表示离底部多远以内都算“在底部”
10
+ export var useAutoScroll = function useAutoScroll(dependencies) {
11
+ var threshold = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 100;
12
+ // 指向滚动容器
13
+ var containerRef = useRef(null);
14
+ // 指向一个永远在列表末尾的空div,作为滚动的目标
15
+ var anchorRef = useRef(null);
16
+ var _useState = useState(false),
17
+ _useState2 = _slicedToArray(_useState, 2),
18
+ showScrollDownButton = _useState2[0],
19
+ setShowScrollDownButton = _useState2[1];
20
+ useLayoutEffect(function () {
21
+ var container = containerRef.current;
22
+ if (!container) return;
23
+
24
+ // scrollTop: 滚动条距离顶部的距离
25
+ // scrollHeight: 整个可滚动内容的总高度
26
+ // clientHeight: 容器可视区域的高度
27
+ var isAtBottom = container.scrollHeight - container.scrollTop <= container.clientHeight + threshold + 200;
28
+
29
+ // 只有当用户已经在底部时,才执行自动滚动
30
+ if (isAtBottom) {
31
+ var _anchorRef$current;
32
+ (_anchorRef$current = anchorRef.current) === null || _anchorRef$current === void 0 || _anchorRef$current.scrollIntoView({
33
+ block: 'end' // 滚动到元素的末尾
34
+ });
35
+ setShowScrollDownButton(false);
36
+ } else {
37
+ setShowScrollDownButton(true);
38
+ }
39
+ }, [dependencies, threshold]); // 依赖项改变时(比如新消息来了),触发此 effect
40
+
41
+ return {
42
+ containerRef: containerRef,
43
+ anchorRef: anchorRef,
44
+ showScrollDownButton: showScrollDownButton
45
+ };
46
+ };