@antv/dumi-theme-antv 0.8.0-beta.0 → 0.8.0-beta.10

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 (84) 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/index.js +4 -1
  4. package/dist/components/AI/HomeDialog/ModeSelector/index.module.less +39 -22
  5. package/dist/components/AI/HomeDialog/PromptTextarea/ChooseLib/index.js +5 -2
  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/Uploader/DataUploader.js +225 -0
  9. package/dist/components/AI/HomeDialog/PromptTextarea/index.js +66 -34
  10. package/dist/components/AI/HomeDialog/PromptTextarea/index.module.less +9 -8
  11. package/dist/components/AI/HomeDialog/RecommendCase/Card.js +13 -8
  12. package/dist/components/AI/HomeDialog/RecommendCase/card.module.less +1 -1
  13. package/dist/components/AI/HomeDialog/RecommendCase/index.js +46 -14
  14. package/dist/components/AI/HomeDialog/RecommendCase/index.module.less +3 -2
  15. package/dist/components/AI/HomeDialog/index.js +18 -4
  16. package/dist/components/AI/constant.js +2 -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/useStreamingText.js +38 -18
  30. package/dist/hooks/useTypewriter.js +69 -0
  31. package/dist/layouts/DocLayout.js +2 -1
  32. package/dist/layouts/GlobalLayout/index.js +10 -4
  33. package/dist/locales/en.json +121 -1
  34. package/dist/locales/zh.json +121 -1
  35. package/dist/model/AIChat.js +79 -11
  36. package/dist/model/auth.js +133 -0
  37. package/dist/pages/AIPlayground/components/ConversationsMenu/index.js +31 -10
  38. package/dist/pages/AIPlayground/components/ConversationsMenu/index.module.less +2 -0
  39. package/dist/pages/AIPlayground/components/MarkdownComponent/MarkdownCodeBlock.js +47 -20
  40. package/dist/pages/AIPlayground/components/MarkdownComponent/MarkdownCodeBlock.module.less +13 -0
  41. package/dist/pages/AIPlayground/components/MarkdownComponent/index.js +6 -3
  42. package/dist/pages/AIPlayground/components/MsgBox/index.js +250 -106
  43. package/dist/pages/AIPlayground/components/MsgBox/index.module.less +3 -2
  44. package/dist/pages/AIPlayground/components/MsgBox/useAutoScroll.js +46 -0
  45. package/dist/pages/AIPlayground/components/SessionLayout/index.js +18 -10
  46. package/dist/pages/AIPlayground/components/SessionLayout/index.module.less +3 -1
  47. package/dist/pages/AIPlayground/components/TaskBox/generateCode.js +10 -5
  48. package/dist/pages/AIPlayground/components/TaskBox/index.js +79 -54
  49. package/dist/pages/AIPlayground/components/TaskBox/index.module.less +1 -0
  50. package/dist/pages/Examples/components/Accouncement/index.module.less +1 -1
  51. package/dist/pages/Examples/index.module.less +11 -11
  52. package/dist/pages/Index/components/Cases/index.module.less +8 -8
  53. package/dist/pages/Index/components/Companies/index.module.less +4 -3
  54. package/dist/pages/Index/components/Features/FeatureCard.module.less +4 -5
  55. package/dist/pages/Index/components/Features/index.module.less +5 -5
  56. package/dist/pages/Index/components/_.less +9 -9
  57. package/dist/plugin/index.js +2 -2
  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 +20 -8
  61. package/dist/slots/CodeEditor/Toolbar.module.less +1 -0
  62. package/dist/slots/CodeEditor/index.js +30 -10
  63. package/dist/slots/CodeEditor/index.module.less +3 -0
  64. package/dist/slots/CodePreview/index.module.less +0 -3
  65. package/dist/slots/CodeRunner/index.js +6 -2
  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.module.less +11 -14
  69. package/dist/slots/ExampleSider/index.module.less +3 -4
  70. package/dist/slots/Footer/index.module.less +2 -2
  71. package/dist/slots/Header/Products/Product.module.less +2 -2
  72. package/dist/slots/Header/Search/SearchResult.js +23 -7
  73. package/dist/slots/Header/Search/SearchResult.module.less +1 -0
  74. package/dist/slots/Header/index.js +56 -11
  75. package/dist/slots/Header/index.module.less +13 -5
  76. package/dist/slots/LiveExample/index.module.less +1 -1
  77. package/dist/slots/Loading/index.module.less +30 -28
  78. package/dist/slots/ManualContent/index.module.less +14 -17
  79. package/dist/slots/_.less +9 -9
  80. package/dist/static/user.svg +3 -0
  81. package/dist/utils/code.js +35 -0
  82. package/dist/utils/env.js +37 -0
  83. package/dist/utils/request.js +42 -0
  84. package/package.json +7 -2
@@ -4,18 +4,23 @@ function _unsupportedIterableToArray(o, minLen) { if (!o) return; if (typeof o =
4
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
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
6
  function _arrayWithHoles(arr) { if (Array.isArray(arr)) return arr; }
7
- import React, { useEffect, useState } from 'react';
8
- import { PromptTextarea } from "../../../../components/AI/HomeDialog/PromptTextarea";
9
- import { Flex, Space } from 'antd';
7
+ import { CheckOutlined, CopyOutlined, PlusSquareOutlined, SyncOutlined } from '@ant-design/icons';
10
8
  import { Bubble } from '@ant-design/x';
11
- import { history } from 'dumi';
12
- import { useStreamingText } from "../../../../hooks/useStreamingText";
13
- import { PlusSquareOutlined } from "@ant-design/icons";
14
- import styles from "./index.module.less";
9
+ import { Button, Flex, Space, Tooltip } from 'antd';
10
+ import { useChat } from '@ai-sdk/react';
11
+ import { TextStreamChatTransport } from 'ai';
12
+ import { useIntl, useSiteData } from 'dumi';
13
+ import { findLast } from 'lodash-es';
14
+ import React, { useEffect, useState, useMemo, useRef } from 'react';
15
+ import { useCopyToClipboard } from 'react-use';
15
16
  import { useSnapshot } from 'valtio';
16
- import { AIChatStore, createNewSession, derivedState } from "../../../../model/AIChat";
17
- import { findLast } from "lodash-es";
17
+ import { PromptTextarea } from "../../../../components/AI/HomeDialog/PromptTextarea";
18
+ import { AIChatStore, createPureNewSession, derivedState } from "../../../../model/AIChat";
19
+ import { getCodeFromMarkdown, isPreviewable } from "../../../../utils/code";
18
20
  import { MarkdownComponent } from "../MarkdownComponent";
21
+ import styles from "./index.module.less";
22
+ import { useAutoScroll } from "./useAutoScroll";
23
+ import { getBaseURL } from "../../../../utils/env";
19
24
  var avatar = {
20
25
  icon: /*#__PURE__*/React.createElement("img", {
21
26
  draggable: false,
@@ -24,164 +29,303 @@ var avatar = {
24
29
  }),
25
30
  style: {
26
31
  borderRadius: 0,
27
- backgroundColor: "transparent"
32
+ backgroundColor: 'transparent'
28
33
  }
29
34
  };
30
35
  var chatScrollIntoView = function chatScrollIntoView() {
31
36
  setTimeout(function () {
32
- var nodeList = document.querySelectorAll(".ant-bubble");
33
- nodeList[nodeList.length - 1].scrollIntoView({
34
- behavior: "smooth",
35
- block: "center"
37
+ document.getElementById('msgBoxAnchor').scrollIntoView({
38
+ block: 'end'
36
39
  });
40
+ }, 100);
41
+ };
42
+
43
+ // 辅助函数:将旧的 Message 格式转换为新的 UIMessage 格式
44
+ var convertToUIMessages = function convertToUIMessages(messages) {
45
+ return messages.map(function (msg) {
46
+ return {
47
+ id: msg.id,
48
+ role: msg.role,
49
+ parts: [{
50
+ type: 'text',
51
+ text: msg.content
52
+ }]
53
+ };
37
54
  });
38
55
  };
56
+
57
+ // 辅助函数:从 UIMessage 提取文本内容
58
+ var getTextContent = function getTextContent(message) {
59
+ return message.parts.filter(function (part) {
60
+ return part.type === 'text';
61
+ }).map(function (part) {
62
+ return part.text;
63
+ }).join('');
64
+ };
39
65
  function MsgBox(props) {
40
- var _derivedSnap$activeSe, _findLast, _derivedSnap$activeSe2, _ref, _props$messages, _derivedSnap$activeSe3;
41
- var _useState = useState(''),
66
+ var _derivedSnap$activeSe, _derivedSnap$activeSe2, _derivedSnap$activeSe4, _derivedSnap$activeSe7, _derivedSnap$activeSe8, _messages;
67
+ var _props$messages = props.messages,
68
+ initialMessages = _props$messages === void 0 ? [] : _props$messages,
69
+ _props$simple = props.simple,
70
+ simple = _props$simple === void 0 ? false : _props$simple,
71
+ onCodegen = props.onCodegen,
72
+ title = props.title;
73
+ var _useSiteData = useSiteData(),
74
+ themeConfig = _useSiteData.themeConfig;
75
+ var _useIntl = useIntl(),
76
+ formatMessage = _useIntl.formatMessage;
77
+ var _useState = useState(!themeConfig.isAntVSite ? themeConfig.title : undefined),
42
78
  _useState2 = _slicedToArray(_useState, 2),
43
- promptText = _useState2[0],
44
- setPromptText = _useState2[1];
45
- var _useState3 = useState(false),
79
+ lib = _useState2[0],
80
+ setLib = _useState2[1];
81
+ var _useState3 = useState(''),
46
82
  _useState4 = _slicedToArray(_useState3, 2),
47
- isStreaming = _useState4[0],
48
- setIsStreaming = _useState4[1]; // trigger
49
- var _useState5 = useState(false),
83
+ promptText = _useState4[0],
84
+ setPromptText = _useState4[1];
85
+ var _useState5 = useState(''),
50
86
  _useState6 = _slicedToArray(_useState5, 2),
51
- loading = _useState6[0],
52
- setLoading = _useState6[1];
87
+ fileSummary = _useState6[0],
88
+ setFileSummary = _useState6[1];
53
89
  var snap = useSnapshot(AIChatStore);
54
90
  var derivedSnap = useSnapshot(derivedState);
55
- var streamingText = useStreamingText({
56
- url: 'http://127.0.0.1:7001/ai/chat',
57
- method: 'POST',
58
- body: {
59
- "gptConversationId": (_derivedSnap$activeSe = derivedSnap.activeSession) === null || _derivedSnap$activeSe === void 0 ? void 0 : _derivedSnap$activeSe.id,
60
- "query": (_findLast = findLast((_derivedSnap$activeSe2 = derivedSnap.activeSession) === null || _derivedSnap$activeSe2 === void 0 ? void 0 : _derivedSnap$activeSe2.messages, function (msg) {
61
- return msg.role === 'user';
62
- })) === null || _findLast === void 0 ? void 0 : _findLast.content
63
- },
64
- trigger: isStreaming,
65
- // isStreaming 状态作为 trigger
66
- headers: {
67
- 'Content-Type': 'application/json'
68
- },
69
- beforeStart: function beforeStart() {
70
- setLoading(true);
71
- },
72
- onFinish: function onFinish(finalText) {
73
- try {
74
- var _derivedState$activeS;
75
- var finalJSON = JSON.parse(finalText);
76
- (_derivedState$activeS = derivedState.activeSession) === null || _derivedState$activeS === void 0 || (_derivedState$activeS = _derivedState$activeS.messages) === null || _derivedState$activeS === void 0 || _derivedState$activeS.push({
91
+ var _useCopyToClipboard = useCopyToClipboard(),
92
+ _useCopyToClipboard2 = _slicedToArray(_useCopyToClipboard, 2),
93
+ copyState = _useCopyToClipboard2[0],
94
+ copyToClipboard = _useCopyToClipboard2[1];
95
+ var latestUserMessage = findLast((_derivedSnap$activeSe = derivedSnap.activeSession) === null || _derivedSnap$activeSe === void 0 ? void 0 : _derivedSnap$activeSe.messages, function (msg) {
96
+ return msg.role === 'user';
97
+ });
98
+ // 使用 ref 存储动态值,避免重新创建 transport
99
+ var anonymousUserIdRef = useRef(snap.anonymousUserId);
100
+ var activeSessionIdRef = useRef((_derivedSnap$activeSe2 = derivedSnap.activeSession) === null || _derivedSnap$activeSe2 === void 0 ? void 0 : _derivedSnap$activeSe2.id);
101
+ useEffect(function () {
102
+ var _derivedSnap$activeSe3;
103
+ anonymousUserIdRef.current = snap.anonymousUserId;
104
+ activeSessionIdRef.current = (_derivedSnap$activeSe3 = derivedSnap.activeSession) === null || _derivedSnap$activeSe3 === void 0 ? void 0 : _derivedSnap$activeSe3.id;
105
+ }, [snap.anonymousUserId, (_derivedSnap$activeSe4 = derivedSnap.activeSession) === null || _derivedSnap$activeSe4 === void 0 ? void 0 : _derivedSnap$activeSe4.id]);
106
+
107
+ // 转换初始消息为新格式
108
+ var convertedInitialMessages = useMemo(function () {
109
+ return convertToUIMessages(initialMessages);
110
+ }, [initialMessages]);
111
+
112
+ // 核心:使用 useChat hook,配置 DefaultChatTransport
113
+ var _useChat = useChat({
114
+ transport: new TextStreamChatTransport({
115
+ api: getBaseURL() + '/api/modules/antv/ai/chat',
116
+ credentials: 'include',
117
+ headers: {
118
+ // xxx
119
+ },
120
+ // body 可以是函数,用于获取最新的动态值
121
+ body: {
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: (latestUserMessage === null || latestUserMessage === void 0 ? void 0 : latestUserMessage.lib) || lib,
127
+ mode: latestUserMessage === null || latestUserMessage === void 0 ? void 0 : latestUserMessage.mode
128
+ }
129
+ }),
130
+ messages: convertedInitialMessages,
131
+ // 当AI响应结束时触发
132
+ onFinish: function onFinish(_ref) {
133
+ var message = _ref.message,
134
+ isAbort = _ref.isAbort,
135
+ isDisconnect = _ref.isDisconnect,
136
+ isError = _ref.isError;
137
+ if (!isAbort && !isDisconnect && !isError) {
138
+ var _derivedState$activeS;
139
+ var messageContent = getTextContent(message);
140
+ if (isPreviewable(messageContent)) {
141
+ var codeBlock = getCodeFromMarkdown(messageContent).code;
142
+ AIChatStore.codeBlock = codeBlock;
143
+ onCodegen === null || onCodegen === void 0 || onCodegen(codeBlock);
144
+ }
145
+ (_derivedState$activeS = derivedState.activeSession) === null || _derivedState$activeS === void 0 || (_derivedState$activeS = _derivedState$activeS.messages) === null || _derivedState$activeS === void 0 || _derivedState$activeS.push({
146
+ id: crypto.randomUUID(),
147
+ role: 'assistant',
148
+ content: messageContent,
149
+ createdAt: Date.now()
150
+ });
151
+ }
152
+ },
153
+ onError: function onError(error) {
154
+ var _derivedState$activeS2;
155
+ console.error('回答失败', error);
156
+ // 同步错误消息到 valtio
157
+ (_derivedState$activeS2 = derivedState.activeSession) === null || _derivedState$activeS2 === void 0 || (_derivedState$activeS2 = _derivedState$activeS2.messages) === null || _derivedState$activeS2 === void 0 || _derivedState$activeS2.push({
77
158
  id: crypto.randomUUID(),
78
159
  role: 'assistant',
79
- content: finalJSON.content,
160
+ content: formatMessage({
161
+ id: 'ai.msgbox.error.response'
162
+ }),
80
163
  createdAt: Date.now()
81
164
  // mode,
82
165
  // lib,
83
166
  });
84
- } catch (e) {
85
- // 说明不是JSON格式
86
- } finally {
87
- // 当流结束时,更新最后一条消息并重置 trigger
88
- setIsStreaming(false); // **关键:流结束后,关闭 trigger**
89
- setLoading(false);
90
- chatScrollIntoView();
91
167
  }
92
- },
93
- onError: function onError(error) {
94
- // 处理错误
95
- console.error("AI stream failed:", error);
96
- // setMessages(prev => [
97
- // ...prev,
98
- // { id: Date.now(), role: 'assistant', content: `Sorry, an error occurred: ${error.message}` }
99
- // ]);
100
- setIsStreaming(false); // **关键:出错后,也要关闭 trigger**
101
- }
102
- });
168
+ }),
169
+ messages = _useChat.messages,
170
+ setMessages = _useChat.setMessages,
171
+ sendMessage = _useChat.sendMessage,
172
+ regenerate = _useChat.regenerate,
173
+ status = _useChat.status,
174
+ stop = _useChat.stop;
103
175
 
104
- // 3. 处理用户提交
176
+ // 处理用户提交
105
177
  var handleSubmit = function handleSubmit() {
106
- var _derivedState$activeS2;
107
- if (props.simple) {
108
- createNewSession({
109
- promptText: promptText
110
- });
111
- return;
178
+ var _derivedSnap$activeSe5, _derivedState$activeS3;
179
+ var trimmedPrompt = promptText.trim();
180
+ if (!trimmedPrompt || status === 'streaming' || status === 'submitted') return;
181
+ if (derivedSnap.activeSession && ((_derivedSnap$activeSe5 = derivedSnap.activeSession.messages) === null || _derivedSnap$activeSe5 === void 0 ? void 0 : _derivedSnap$activeSe5.length) === 0) {
182
+ derivedState.activeSession.title = trimmedPrompt;
112
183
  }
113
- if (!promptText.trim() || isStreaming) return; // 如果正在流式输出,则不允许发送
184
+ // 使用 sendMessage 函数发送新消息
185
+ // 第二个参数传递每次请求特定的额外数据
186
+ sendMessage({
187
+ text: promptText
188
+ }, {
189
+ body: {
190
+ context: fileSummary,
191
+ lib: lib,
192
+ mode: 'implement'
193
+ }
194
+ });
114
195
  setPromptText('');
115
- (_derivedState$activeS2 = derivedState.activeSession) === null || _derivedState$activeS2 === void 0 || (_derivedState$activeS2 = _derivedState$activeS2.messages) === null || _derivedState$activeS2 === void 0 || _derivedState$activeS2.push({
196
+ (_derivedState$activeS3 = derivedState.activeSession) === null || _derivedState$activeS3 === void 0 || (_derivedState$activeS3 = _derivedState$activeS3.messages) === null || _derivedState$activeS3 === void 0 || _derivedState$activeS3.push({
116
197
  id: crypto.randomUUID(),
117
198
  role: 'user',
118
199
  content: promptText,
119
- createdAt: Date.now()
120
- // mode,
121
- // lib,
200
+ createdAt: Date.now(),
201
+ context: fileSummary,
202
+ lib: lib
122
203
  });
123
- // **关键:开启 trigger,开始请求**
124
- setIsStreaming(true);
125
204
  chatScrollIntoView();
126
205
  };
206
+
207
+ // 同步 Valtio store -> useChat state
127
208
  useEffect(function () {
128
- // 检查是否存在临时消息
129
- if (snap.tempMessage) {
130
- var activeSession = derivedState.activeSession;
131
- if (activeSession) {
132
- // 1. 将临时消息正式添加到当前会话中
133
- activeSession.messages.push(snap.tempMessage);
134
- setIsStreaming(true);
135
- AIChatStore.tempMessage = null;
209
+ if (simple) {
210
+ return;
211
+ }
212
+ setTimeout(function () {
213
+ var _derivedSnap$activeSe6;
214
+ var sessionMessages = (_derivedSnap$activeSe6 = derivedSnap.activeSession) === null || _derivedSnap$activeSe6 === void 0 ? void 0 : _derivedSnap$activeSe6.messages;
215
+ if ((sessionMessages === null || sessionMessages === void 0 ? void 0 : sessionMessages.length) > 0) {
216
+ var converted = convertToUIMessages(sessionMessages);
217
+ // 避免无限循环,仅当消息数量或内容不同时更新
218
+ if (messages.length !== converted.length || JSON.stringify(messages) !== JSON.stringify(converted)) {
219
+ setMessages(converted);
220
+ }
221
+ } else {
222
+ setMessages([]);
136
223
  }
224
+ });
225
+ }, [(_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]);
226
+
227
+ // 处理从外部(如demo页)发起的对话
228
+ useEffect(function () {
229
+ if (snap.tempMessage) {
230
+ var _derivedState$activeS4, _derivedState$activeS5;
231
+ sendMessage({
232
+ text: snap.tempMessage.content
233
+ });
234
+ (_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);
235
+ AIChatStore.tempMessage = null;
137
236
  }
138
- }, []);
237
+ }, [snap.tempMessage]);
139
238
  useEffect(function () {
140
- if (derivedState.activeSession && Date.now() - derivedState.activeSession.createdAt > 5000) {
141
- setLoading(false);
142
- setIsStreaming(false);
239
+ chatScrollIntoView();
240
+ if (simple) {
241
+ createPureNewSession(title);
143
242
  }
243
+ }, []);
244
+ useEffect(function () {
245
+ chatScrollIntoView();
246
+ stop();
144
247
  }, [snap.activeSessionId]);
248
+
249
+ // 将 messages 数组作为依赖项。当它变化时,Hook 会运行。
250
+ var _useAutoScroll = useAutoScroll(messages),
251
+ containerRef = _useAutoScroll.containerRef,
252
+ anchorRef = _useAutoScroll.anchorRef;
145
253
  return /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement(Flex, {
146
254
  gap: "middle",
147
255
  vertical: true,
148
- className: styles.chatContainer
149
- }, (_ref = (_props$messages = props.messages) !== null && _props$messages !== void 0 ? _props$messages : (_derivedSnap$activeSe3 = derivedSnap.activeSession) === null || _derivedSnap$activeSe3 === void 0 ? void 0 : _derivedSnap$activeSe3.messages) === null || _ref === void 0 ? void 0 : _ref.map(function (msg, index) {
256
+ className: styles.chatContainer,
257
+ ref: containerRef
258
+ }, messages.map(function (msg, index) {
259
+ var textContent = getTextContent(msg);
150
260
  return /*#__PURE__*/React.createElement(Bubble, {
151
- key: index,
261
+ key: msg.id || index,
152
262
  content: /*#__PURE__*/React.createElement(MarkdownComponent, {
153
- content: msg.content
263
+ content: textContent,
264
+ showRunButton: !props.simple
154
265
  }),
155
266
  avatar: msg.role === 'assistant' ? avatar : null,
267
+ footer: msg.role === 'assistant' && index > 0 && index === messages.length - 1 && status === 'ready' ? /*#__PURE__*/React.createElement(Space, {
268
+ size: "small"
269
+ }, /*#__PURE__*/React.createElement(Tooltip, {
270
+ title: formatMessage({
271
+ id: 'ai.msgbox.retry'
272
+ })
273
+ }, /*#__PURE__*/React.createElement(Button, {
274
+ onClick: function onClick() {
275
+ regenerate();
276
+ derivedState.activeSession.messages.pop();
277
+ },
278
+ color: "default",
279
+ variant: "text",
280
+ size: "small",
281
+ icon: /*#__PURE__*/React.createElement(SyncOutlined, null)
282
+ })), /*#__PURE__*/React.createElement(Tooltip, {
283
+ title: formatMessage({
284
+ id: 'ai.msgbox.copy'
285
+ })
286
+ }, /*#__PURE__*/React.createElement(Button, {
287
+ color: "default",
288
+ variant: "text",
289
+ size: "small",
290
+ onClick: function onClick() {
291
+ return copyToClipboard(textContent);
292
+ },
293
+ icon: copyState.value === textContent ? /*#__PURE__*/React.createElement(CheckOutlined, null) : /*#__PURE__*/React.createElement(CopyOutlined, null)
294
+ }))) : null,
156
295
  placement: msg.role === 'user' ? 'end' : 'start'
157
296
  });
158
- }), loading && /*#__PURE__*/React.createElement(Bubble, {
297
+ }), (status === 'streaming' || status === 'submitted') && ((_messages = messages[messages.length - 1]) === null || _messages === void 0 ? void 0 : _messages.role) === 'user' && /*#__PURE__*/React.createElement(Bubble, {
159
298
  placement: "start",
160
299
  avatar: avatar,
161
- loading: loading
300
+ loading: true
301
+ }), /*#__PURE__*/React.createElement("div", {
302
+ ref: anchorRef,
303
+ id: "msgBoxAnchor"
162
304
  })), /*#__PURE__*/React.createElement("div", null, !props.simple && /*#__PURE__*/React.createElement("div", {
163
305
  className: styles.newButtonContainer
164
- }, /*#__PURE__*/React.createElement("button", {
306
+ }, /*#__PURE__*/React.createElement(Space, null, /*#__PURE__*/React.createElement("button", {
165
307
  type: "button",
166
308
  onClick: function onClick() {
167
- return history.push('/');
309
+ return createPureNewSession();
168
310
  },
169
311
  className: styles.newButton
170
- }, /*#__PURE__*/React.createElement(Space, null, /*#__PURE__*/React.createElement(PlusSquareOutlined, null), "\u5F00\u59CB\u65B0\u5BF9\u8BDD"))), /*#__PURE__*/React.createElement(PromptTextarea, {
312
+ }, /*#__PURE__*/React.createElement(Space, null, /*#__PURE__*/React.createElement(PlusSquareOutlined, null), formatMessage({
313
+ id: 'ai.msgbox.start.new.chat'
314
+ }))))), /*#__PURE__*/React.createElement(PromptTextarea, {
171
315
  size: "compact",
172
316
  mode: "implement",
173
317
  value: promptText,
174
318
  onChange: setPromptText,
175
- loading: loading,
176
- onCancel: function onCancel() {
177
- setIsStreaming(false);
178
- setLoading(false);
179
- },
319
+ loading: status === 'streaming' || status === 'submitted',
320
+ onCancel: stop,
180
321
  showAction: !props.simple,
181
322
  style: {
182
323
  marginBottom: 0
183
324
  },
184
- onConfirm: handleSubmit
325
+ onConfirm: handleSubmit,
326
+ lib: lib,
327
+ onLibChange: setLib,
328
+ onDataSummaryChange: setFileSummary
185
329
  })));
186
330
  }
187
331
  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
+ };
@@ -1,13 +1,10 @@
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); }
2
- function _defineProperty(obj, key, value) { key = _toPropertyKey(key); if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }
3
- function _toPropertyKey(t) { var i = _toPrimitive(t, "string"); return "symbol" == _typeof(i) ? i : String(i); }
4
- function _toPrimitive(t, r) { if ("object" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || "default"); if ("object" != _typeof(i)) return i; throw new TypeError("@@toPrimitive must return a primitive value."); } return ("string" === r ? String : Number)(t); }
5
1
  import React from 'react';
6
2
  import styles from "./index.module.less";
7
3
  import { ConversationsMenu } from "../ConversationsMenu";
8
4
  import { AIChatStore } from "../../../../model/AIChat";
9
- import { useSnapshot } from "valtio";
10
- import classnames from "classnames";
5
+ import { useSnapshot } from 'valtio';
6
+ import classnames from 'classnames';
7
+ import SplitPane from 'react-split-pane';
11
8
  function SessionLayout(props) {
12
9
  var children = props.children;
13
10
  var snap = useSnapshot(AIChatStore);
@@ -16,10 +13,21 @@ function SessionLayout(props) {
16
13
  }
17
14
  return /*#__PURE__*/React.createElement("div", {
18
15
  className: styles.container
19
- }, /*#__PURE__*/React.createElement(ConversationsMenu, null), /*#__PURE__*/React.createElement("div", {
20
- className: classnames(styles.msgBox, _defineProperty(_defineProperty({}, styles.msgBoxHalf, snap.codeBlock), styles.msgBoxFull, !snap.codeBlock))
21
- }, children[0]), snap.codeBlock && /*#__PURE__*/React.createElement("div", {
16
+ }, /*#__PURE__*/React.createElement(ConversationsMenu, null),
17
+ // @ts-ignore
18
+ snap.codeBlock ? /*#__PURE__*/React.createElement(SplitPane, {
19
+ split: "vertical",
20
+ defaultSize: "50vw",
21
+ primary: "second",
22
+ style: {
23
+ position: "unset"
24
+ }
25
+ }, /*#__PURE__*/React.createElement("div", {
26
+ className: classnames(styles.msgBox)
27
+ }, children[0]), /*#__PURE__*/React.createElement("div", {
22
28
  className: styles.taskBox
23
- }, children[1]));
29
+ }, children[1])) : /*#__PURE__*/React.createElement("div", {
30
+ className: classnames(styles.msgBox, styles.msgBoxFull)
31
+ }, children[0]));
24
32
  }
25
33
  export { SessionLayout };
@@ -14,6 +14,7 @@
14
14
  }
15
15
 
16
16
  .msgBox {
17
+ height: 100%;
17
18
  padding: 16px;
18
19
  min-width: 400px;
19
20
  justify-content: space-between;
@@ -28,7 +29,8 @@
28
29
  }
29
30
 
30
31
  .taskBox {
32
+ height: calc(100% - 32px);
31
33
  margin: 16px;
32
34
  flex-grow: 1;
33
- background: #ffffff;
35
+ background: #fff;
34
36
  }
@@ -77,14 +77,20 @@ export function generateDependencies(codeString) {
77
77
  }
78
78
  export function wrap2VisionSnap() {
79
79
  var codeBlock = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : '';
80
+ var dependencies = generateDependencies(codeBlock);
81
+ var rootElementType = dependencies['@antv/f2'] ? 'canvas' : 'div';
80
82
  return {
81
83
  modules: {
82
84
  '/package.json': {
83
85
  fpath: '/package.json',
84
- code: "{\n \"name\": \"AntV-master\",\n \"version\": \"1.0.0\",\n \"main\": \"/src/index.jsx\",\n \"dependencies\": ".concat(JSON.stringify(generateDependencies(codeBlock), null, 2), "\n}")
86
+ code: "{\n \"name\": \"AntV-adapted-project\",\n \"version\": \"1.0.0\",\n \"main\": \"/src/index.jsx\",\n \"dependencies\": ".concat(JSON.stringify(dependencies, null, 2), "\n}")
85
87
  },
86
88
  '/src/index.jsx': {
87
89
  fpath: '/src/index.jsx',
90
+ code: "\n// --- Adapter Script ---\n\n// 1. \u627E\u5230\u7F16\u8F91\u5668\u73AF\u5883\u63D0\u4F9B\u7684\u6839\u8282\u70B9 #root\nconst rootElement = document.getElementById('root');\n\nif (rootElement) {\n // 2. \u5728 #root \u5185\u90E8\u521B\u5EFA\u4E00\u4E2A ".concat(rootElementType, "\n const containerElement = document.createElement('").concat(rootElementType, "');\n\n // 3. \u5C06\u8FD9\u4E2A div \u7684 id \u8BBE\u7F6E\u4E3A 'container'\uFF0C\u4EE5\u6EE1\u8DB3\u7528\u6237\u4EE3\u7801\u7684\u9700\u6C42\n containerElement.id = 'container';\n\n // 4. \u5C06\u5B83\u6DFB\u52A0\u5230 #root \u4E2D\n rootElement.appendChild(containerElement);\n\n // 5. \u73B0\u5728 DOM \u4E2D\u5DF2\u7ECF\u5B58\u5728 #container\uFF0C\u5B89\u5168\u5730\u5BFC\u5165\u5E76\u6267\u884C\u7528\u6237\u7684\u4EE3\u7801\n import('./App.jsx');\n\n}\n ")
91
+ },
92
+ '/src/App.jsx': {
93
+ fpath: '/src/App.jsx',
88
94
  code: codeBlock
89
95
  }
90
96
  }
@@ -97,14 +103,13 @@ export function wrap2Sandpack() {
97
103
  // if (match) {
98
104
  return {
99
105
  "/package.json": {
100
- code: "{\n \"name\": \"AntV-AI-Code\",\n \"version\": \"1.0.0\",\n \"main\": \"/index.js\",\n \"dependencies\": ".concat(JSON.stringify(generateDependencies(codeBlock), null, 2), "\n }")
106
+ code: "{\n \"name\": \"AntV-AI-Code\",\n \"version\": \"1.0.0\",\n \"main\": \"/index.tsx\",\n \"dependencies\": ".concat(JSON.stringify(generateDependencies(codeBlock), null, 2), "\n }")
101
107
  },
102
- "/index.js": {
103
- // 入口文件是纯 JS
108
+ "/index.tsx": {
104
109
  code: codeBlock
105
110
  },
106
111
  "/index.html": {
107
- code: "<!DOCTYPE html>\n<html>\n<head>\n <title>Vanilla JS Example</title>\n</head>\n<body>\n <div id=\"root\"></div>\n <div id=\"container\"></div>\n <script src=\"index.js\"></script>\n</body>\n</html>"
112
+ code: "<!DOCTYPE html>\n<html>\n<head>\n <title>Vanilla JS Example</title>\n</head>\n<body>\n <div id=\"root\"></div>\n <div id=\"container\"></div>\n <script src=\"index.tsx\"></script>\n</body>\n</html>"
108
113
  }
109
114
  };
110
115
  }