@antv/dumi-theme-antv 0.8.0-beta.1 → 0.8.0-beta.11

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 (81) 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 +4 -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 +74 -43
  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 +19 -17
  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/layouts/DocLayout.js +2 -1
  30. package/dist/layouts/GlobalLayout/index.js +10 -4
  31. package/dist/locales/en.json +125 -1
  32. package/dist/locales/zh.json +125 -1
  33. package/dist/model/AIChat.js +72 -8
  34. package/dist/model/auth.js +133 -0
  35. package/dist/pages/AIPlayground/components/ConversationsMenu/index.js +36 -12
  36. package/dist/pages/AIPlayground/components/ConversationsMenu/index.module.less +2 -0
  37. package/dist/pages/AIPlayground/components/MarkdownComponent/MarkdownCodeBlock.js +25 -11
  38. package/dist/pages/AIPlayground/components/MarkdownComponent/MarkdownCodeBlock.module.less +1 -2
  39. package/dist/pages/AIPlayground/components/MarkdownComponent/index.js +5 -2
  40. package/dist/pages/AIPlayground/components/MsgBox/index.js +202 -146
  41. package/dist/pages/AIPlayground/components/MsgBox/index.module.less +3 -2
  42. package/dist/pages/AIPlayground/components/MsgBox/useAutoScroll.js +46 -0
  43. package/dist/pages/AIPlayground/components/SessionLayout/index.js +2 -2
  44. package/dist/pages/AIPlayground/components/SessionLayout/index.module.less +4 -2
  45. package/dist/pages/AIPlayground/components/TaskBox/generateCode.js +7 -1
  46. package/dist/pages/AIPlayground/components/TaskBox/index.js +78 -55
  47. package/dist/pages/AIPlayground/components/TaskBox/index.module.less +1 -0
  48. package/dist/pages/Examples/components/Accouncement/index.module.less +1 -1
  49. package/dist/pages/Examples/index.module.less +11 -11
  50. package/dist/pages/Index/components/Cases/index.module.less +8 -8
  51. package/dist/pages/Index/components/Companies/index.module.less +4 -3
  52. package/dist/pages/Index/components/Features/FeatureCard.module.less +4 -5
  53. package/dist/pages/Index/components/Features/index.module.less +5 -5
  54. package/dist/pages/Index/components/_.less +9 -9
  55. package/dist/plugin/index.js +2 -2
  56. package/dist/slots/Banner/Notification.module.less +8 -8
  57. package/dist/slots/Banner/index.module.less +10 -9
  58. package/dist/slots/CodeEditor/Toolbar.js +15 -9
  59. package/dist/slots/CodeEditor/index.js +35 -12
  60. package/dist/slots/CodeEditor/index.module.less +3 -1
  61. package/dist/slots/CodePreview/index.module.less +0 -3
  62. package/dist/slots/CodeRunner/index.js +5 -2
  63. package/dist/slots/ContentTable/index.module.less +2 -1
  64. package/dist/slots/Detail/News.module.less +9 -9
  65. package/dist/slots/Detail/index.module.less +11 -14
  66. package/dist/slots/ExampleSider/index.module.less +3 -4
  67. package/dist/slots/Footer/index.module.less +2 -2
  68. package/dist/slots/Header/Products/Product.module.less +2 -2
  69. package/dist/slots/Header/Search/SearchResult.js +23 -8
  70. package/dist/slots/Header/Search/SearchResult.module.less +1 -0
  71. package/dist/slots/Header/index.js +72 -12
  72. package/dist/slots/Header/index.module.less +13 -5
  73. package/dist/slots/LiveExample/index.module.less +1 -1
  74. package/dist/slots/Loading/index.module.less +30 -28
  75. package/dist/slots/ManualContent/index.module.less +14 -17
  76. package/dist/slots/_.less +9 -9
  77. package/dist/static/user.svg +3 -0
  78. package/dist/utils/env.js +37 -0
  79. package/dist/utils/index.js +7 -0
  80. package/dist/utils/request.js +42 -0
  81. package/package.json +7 -3
@@ -1,27 +1,26 @@
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); }
5
1
  function _slicedToArray(arr, i) { return _arrayWithHoles(arr) || _iterableToArrayLimit(arr, i) || _unsupportedIterableToArray(arr, i) || _nonIterableRest(); }
6
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."); }
7
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); }
8
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; }
9
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; } }
10
6
  function _arrayWithHoles(arr) { if (Array.isArray(arr)) return arr; }
11
- import { CheckOutlined, CopyOutlined, DislikeOutlined, LikeOutlined, PlusSquareOutlined, SyncOutlined } from '@ant-design/icons';
7
+ import { CheckOutlined, CopyOutlined, PlusSquareOutlined, SyncOutlined } from '@ant-design/icons';
12
8
  import { Bubble } from '@ant-design/x';
13
9
  import { Button, Flex, Space, Tooltip } from 'antd';
14
- import { history, useSiteData } from 'dumi';
10
+ import { useChat } from '@ai-sdk/react';
11
+ import { TextStreamChatTransport } from 'ai';
12
+ import { useIntl } from 'dumi';
15
13
  import { findLast } from 'lodash-es';
16
- import React, { useEffect, useState } from 'react';
14
+ import React, { useEffect, useState, useMemo, useRef } from 'react';
17
15
  import { useCopyToClipboard } from 'react-use';
18
16
  import { useSnapshot } from 'valtio';
19
17
  import { PromptTextarea } from "../../../../components/AI/HomeDialog/PromptTextarea";
20
- import { useStreamingText } from "../../../../hooks/useStreamingText";
21
- import { AIChatStore, clearEmptySession, createPureNewSession, derivedState } from "../../../../model/AIChat";
18
+ import { AIChatStore, createPureNewSession, derivedState } from "../../../../model/AIChat";
22
19
  import { getCodeFromMarkdown, isPreviewable } from "../../../../utils/code";
23
20
  import { MarkdownComponent } from "../MarkdownComponent";
24
21
  import styles from "./index.module.less";
22
+ import { useAutoScroll } from "./useAutoScroll";
23
+ import { getBaseURL } from "../../../../utils/env";
25
24
  var avatar = {
26
25
  icon: /*#__PURE__*/React.createElement("img", {
27
26
  draggable: false,
@@ -35,40 +34,52 @@ var avatar = {
35
34
  };
36
35
  var chatScrollIntoView = function chatScrollIntoView() {
37
36
  setTimeout(function () {
38
- var nodeList = document.querySelectorAll('.ant-bubble');
39
- nodeList[nodeList.length - 1].scrollIntoView({
40
- behavior: 'smooth'
37
+ document.getElementById('msgBoxAnchor').scrollIntoView({
38
+ block: 'end'
41
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
+ };
42
54
  });
43
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
+ };
44
65
  function MsgBox(props) {
45
- var _derivedSnap$activeSe, _derivedSnap$activeSe2, _derivedSnap$activeSe3;
66
+ var _derivedSnap$activeSe, _derivedSnap$activeSe2, _derivedSnap$activeSe4, _derivedSnap$activeSe7, _derivedSnap$activeSe8, _messages;
46
67
  var _props$messages = props.messages,
47
- messages = _props$messages === void 0 ? [] : _props$messages,
68
+ initialMessages = _props$messages === void 0 ? [] : _props$messages,
48
69
  _props$simple = props.simple,
49
70
  simple = _props$simple === void 0 ? false : _props$simple,
50
- _props$context = props.context,
51
- context = _props$context === void 0 ? '' : _props$context,
52
71
  onCodegen = props.onCodegen,
53
72
  title = props.title;
54
- var _useSiteData = useSiteData(),
55
- themeConfig = _useSiteData.themeConfig;
56
- var _useState = useState(!themeConfig.isAntVSite ? themeConfig.title : undefined),
73
+ var _useIntl = useIntl(),
74
+ formatMessage = _useIntl.formatMessage;
75
+ var _useState = useState(''),
57
76
  _useState2 = _slicedToArray(_useState, 2),
58
- lib = _useState2[0],
59
- setLib = _useState2[1];
77
+ promptText = _useState2[0],
78
+ setPromptText = _useState2[1];
60
79
  var _useState3 = useState(''),
61
80
  _useState4 = _slicedToArray(_useState3, 2),
62
- promptText = _useState4[0],
63
- setPromptText = _useState4[1];
64
- var _useState5 = useState(false),
65
- _useState6 = _slicedToArray(_useState5, 2),
66
- isStreaming = _useState6[0],
67
- setIsStreaming = _useState6[1]; // trigger
68
- var _useState7 = useState(false),
69
- _useState8 = _slicedToArray(_useState7, 2),
70
- loading = _useState8[0],
71
- setLoading = _useState8[1];
81
+ fileSummary = _useState4[0],
82
+ setFileSummary = _useState4[1];
72
83
  var snap = useSnapshot(AIChatStore);
73
84
  var derivedSnap = useSnapshot(derivedState);
74
85
  var _useCopyToClipboard = useCopyToClipboard(),
@@ -78,192 +89,237 @@ function MsgBox(props) {
78
89
  var latestUserMessage = findLast((_derivedSnap$activeSe = derivedSnap.activeSession) === null || _derivedSnap$activeSe === void 0 ? void 0 : _derivedSnap$activeSe.messages, function (msg) {
79
90
  return msg.role === 'user';
80
91
  });
81
- var streamingText = useStreamingText({
82
- url: 'https://webgw-pre.alipay.com/visqaservice/external/chat',
83
- method: 'POST',
84
- body: {
85
- gptConversationId: (_derivedSnap$activeSe2 = derivedSnap.activeSession) === null || _derivedSnap$activeSe2 === void 0 ? void 0 : _derivedSnap$activeSe2.id,
86
- query: latestUserMessage === null || latestUserMessage === void 0 ? void 0 : latestUserMessage.content,
87
- library: (latestUserMessage === null || latestUserMessage === void 0 ? void 0 : latestUserMessage.lib) || lib,
88
- mode: latestUserMessage === null || latestUserMessage === void 0 ? void 0 : latestUserMessage.mode,
89
- anonymousUserId: snap.anonymousUserId,
90
- context: (latestUserMessage === null || latestUserMessage === void 0 ? void 0 : latestUserMessage.context) || context,
91
- mountId: "container"
92
- },
93
- trigger: isStreaming,
94
- // 将 isStreaming 状态作为 trigger
95
- headers: {
96
- 'Content-Type': 'application/json',
97
- 'x-webgw-version': '2.0',
98
- 'x-webgw-appid': '180020010001210065'
99
- },
100
- beforeStart: function beforeStart() {
101
- setLoading(true);
102
- },
103
- onFinish: function onFinish(finalText) {
104
- try {
105
- var _derivedState$activeS;
106
- var finalJSON = JSON.parse(finalText);
107
- (_derivedState$activeS = derivedState.activeSession) === null || _derivedState$activeS === void 0 || (_derivedState$activeS = _derivedState$activeS.messages) === null || _derivedState$activeS === void 0 || _derivedState$activeS.push({
92
+ // 使用 ref 存储动态值,避免重新创建 transport
93
+ var anonymousUserIdRef = useRef(snap.anonymousUserId);
94
+ var activeSessionIdRef = useRef((_derivedSnap$activeSe2 = derivedSnap.activeSession) === null || _derivedSnap$activeSe2 === void 0 ? void 0 : _derivedSnap$activeSe2.id);
95
+ useEffect(function () {
96
+ var _derivedSnap$activeSe3;
97
+ anonymousUserIdRef.current = snap.anonymousUserId;
98
+ activeSessionIdRef.current = (_derivedSnap$activeSe3 = derivedSnap.activeSession) === null || _derivedSnap$activeSe3 === void 0 ? void 0 : _derivedSnap$activeSe3.id;
99
+ }, [snap.anonymousUserId, (_derivedSnap$activeSe4 = derivedSnap.activeSession) === null || _derivedSnap$activeSe4 === void 0 ? void 0 : _derivedSnap$activeSe4.id]);
100
+
101
+ // 转换初始消息为新格式
102
+ var convertedInitialMessages = useMemo(function () {
103
+ return convertToUIMessages(initialMessages);
104
+ }, [initialMessages]);
105
+
106
+ // 核心:使用 useChat hook,配置 DefaultChatTransport
107
+ var _useChat = useChat({
108
+ transport: new TextStreamChatTransport({
109
+ api: getBaseURL() + '/api/modules/antv/ai/chat',
110
+ credentials: 'include',
111
+ headers: {
112
+ // xxx
113
+ },
114
+ // body 可以是函数,用于获取最新的动态值
115
+ body: {
116
+ gptConversationId: activeSessionIdRef.current,
117
+ anonymousUserId: anonymousUserIdRef.current,
118
+ mountId: 'container',
119
+ antvContext: (latestUserMessage === null || latestUserMessage === void 0 ? void 0 : latestUserMessage.context) || props.context,
120
+ library: snap.lib,
121
+ mode: latestUserMessage === null || latestUserMessage === void 0 ? void 0 : latestUserMessage.mode
122
+ }
123
+ }),
124
+ messages: convertedInitialMessages,
125
+ // 当AI响应结束时触发
126
+ onFinish: function onFinish(_ref) {
127
+ var message = _ref.message,
128
+ isAbort = _ref.isAbort,
129
+ isDisconnect = _ref.isDisconnect,
130
+ isError = _ref.isError;
131
+ if (!isAbort && !isDisconnect && !isError) {
132
+ var _derivedState$activeS;
133
+ var messageContent = getTextContent(message);
134
+ if (isPreviewable(messageContent)) {
135
+ var codeBlock = getCodeFromMarkdown(messageContent).code;
136
+ AIChatStore.codeBlock = codeBlock;
137
+ onCodegen === null || onCodegen === void 0 || onCodegen(codeBlock);
138
+ } else {
139
+ AIChatStore.codeBlock = '';
140
+ }
141
+ (_derivedState$activeS = derivedState.activeSession) === null || _derivedState$activeS === void 0 || (_derivedState$activeS = _derivedState$activeS.messages) === null || _derivedState$activeS === void 0 || _derivedState$activeS.push({
142
+ id: crypto.randomUUID(),
143
+ role: 'assistant',
144
+ content: messageContent,
145
+ createdAt: Date.now()
146
+ });
147
+ }
148
+ },
149
+ onError: function onError(error) {
150
+ var _derivedState$activeS2;
151
+ console.error('回答失败', error);
152
+ // 同步错误消息到 valtio
153
+ (_derivedState$activeS2 = derivedState.activeSession) === null || _derivedState$activeS2 === void 0 || (_derivedState$activeS2 = _derivedState$activeS2.messages) === null || _derivedState$activeS2 === void 0 || _derivedState$activeS2.push({
108
154
  id: crypto.randomUUID(),
109
155
  role: 'assistant',
110
- content: finalJSON.content,
156
+ content: formatMessage({
157
+ id: 'ai.msgbox.error.response'
158
+ }),
111
159
  createdAt: Date.now()
112
160
  // mode,
113
161
  // lib,
114
162
  });
115
- if (isPreviewable(finalJSON.content)) {
116
- var codeBlock = getCodeFromMarkdown(finalJSON.content).code;
117
- AIChatStore.codeBlock = codeBlock;
118
- onCodegen === null || onCodegen === void 0 || onCodegen(codeBlock);
119
- }
120
- } catch (e) {
121
- // 说明不是JSON格式
122
- } finally {
123
- // 当流结束时,更新最后一条消息并重置 trigger
124
- setIsStreaming(false); // **关键:流结束后,关闭 trigger**
125
- setLoading(false);
126
- chatScrollIntoView();
127
163
  }
128
- },
129
- onError: function onError(error) {
130
- var _derivedState$activeS2;
131
- console.log('回答失败', error);
132
- // 处理错误
133
- (_derivedState$activeS2 = derivedState.activeSession) === null || _derivedState$activeS2 === void 0 || (_derivedState$activeS2 = _derivedState$activeS2.messages) === null || _derivedState$activeS2 === void 0 || _derivedState$activeS2.push({
134
- id: crypto.randomUUID(),
135
- role: 'assistant',
136
- content: "\u62B1\u6B49\uFF0C\u6211\u6CA1\u80FD\u6210\u529F\u5904\u7406\u60A8\u7684\u8BF7\u6C42\uFF0C\u8BF7\u7A0D\u540E\u518D\u6B21\u63D0\u95EE",
137
- createdAt: Date.now()
138
- // mode,
139
- // lib,
140
- });
141
- setIsStreaming(false);
142
- setLoading(false);
143
- }
144
- });
164
+ }),
165
+ messages = _useChat.messages,
166
+ setMessages = _useChat.setMessages,
167
+ sendMessage = _useChat.sendMessage,
168
+ regenerate = _useChat.regenerate,
169
+ status = _useChat.status,
170
+ stop = _useChat.stop;
145
171
 
146
- // 3. 处理用户提交
172
+ // 处理用户提交
147
173
  var handleSubmit = function handleSubmit() {
148
- var _derivedState$activeS3;
149
- if (!promptText.trim() || isStreaming) return; // 如果正在流式输出,则不允许发送
174
+ var _derivedSnap$activeSe5, _derivedState$activeS3;
175
+ var trimmedPrompt = promptText.trim();
176
+ if (!trimmedPrompt || status === 'streaming' || status === 'submitted') return;
177
+ if (derivedSnap.activeSession && ((_derivedSnap$activeSe5 = derivedSnap.activeSession.messages) === null || _derivedSnap$activeSe5 === void 0 ? void 0 : _derivedSnap$activeSe5.length) === 0) {
178
+ derivedState.activeSession.title = trimmedPrompt;
179
+ }
180
+ // 使用 sendMessage 函数发送新消息
181
+ // 第二个参数传递每次请求特定的额外数据
182
+ sendMessage({
183
+ text: promptText
184
+ }, {
185
+ body: {
186
+ context: fileSummary,
187
+ lib: snap.lib,
188
+ mode: 'implement'
189
+ }
190
+ });
150
191
  setPromptText('');
151
192
  (_derivedState$activeS3 = derivedState.activeSession) === null || _derivedState$activeS3 === void 0 || (_derivedState$activeS3 = _derivedState$activeS3.messages) === null || _derivedState$activeS3 === void 0 || _derivedState$activeS3.push({
152
193
  id: crypto.randomUUID(),
153
194
  role: 'user',
154
195
  content: promptText,
155
196
  createdAt: Date.now(),
156
- lib: lib
197
+ context: fileSummary,
198
+ lib: snap.lib
157
199
  });
158
- // **关键:开启 trigger,开始请求**
159
- setIsStreaming(true);
160
200
  chatScrollIntoView();
161
201
  };
202
+
203
+ // 同步 Valtio store -> useChat state
162
204
  useEffect(function () {
163
- // 检查是否存在临时消息
164
- if (snap.tempMessage) {
165
- var activeSession = derivedState.activeSession;
166
- if (activeSession) {
167
- // 1. 将临时消息正式添加到当前会话中
168
- activeSession.messages.push(snap.tempMessage);
169
- setIsStreaming(true);
170
- AIChatStore.tempMessage = null;
205
+ if (simple) {
206
+ return;
207
+ }
208
+ setTimeout(function () {
209
+ var _derivedSnap$activeSe6;
210
+ var sessionMessages = (_derivedSnap$activeSe6 = derivedSnap.activeSession) === null || _derivedSnap$activeSe6 === void 0 ? void 0 : _derivedSnap$activeSe6.messages;
211
+ if ((sessionMessages === null || sessionMessages === void 0 ? void 0 : sessionMessages.length) > 0) {
212
+ var converted = convertToUIMessages(sessionMessages);
213
+ // 避免无限循环,仅当消息数量或内容不同时更新
214
+ if (messages.length !== converted.length || JSON.stringify(messages) !== JSON.stringify(converted)) {
215
+ setMessages(converted);
216
+ }
217
+ } else {
218
+ setMessages([]);
171
219
  }
220
+ });
221
+ }, [(_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]);
222
+
223
+ // 处理从外部(如demo页)发起的对话
224
+ useEffect(function () {
225
+ if (snap.tempMessage) {
226
+ var _derivedState$activeS4, _derivedState$activeS5;
227
+ sendMessage({
228
+ text: snap.tempMessage.content
229
+ });
230
+ (_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);
231
+ AIChatStore.tempMessage = null;
172
232
  }
233
+ }, [snap.tempMessage]);
234
+ useEffect(function () {
235
+ chatScrollIntoView();
173
236
  if (simple) {
174
237
  createPureNewSession(title);
175
238
  }
176
- return function () {
177
- clearEmptySession();
178
- };
179
239
  }, []);
180
240
  useEffect(function () {
181
- if (derivedState.activeSession && Date.now() - derivedState.activeSession.createdAt > 5000) {
182
- setLoading(false);
183
- setIsStreaming(false);
184
- }
241
+ chatScrollIntoView();
242
+ stop();
185
243
  }, [snap.activeSessionId]);
186
- var showMessages = [].concat(_toConsumableArray(messages), _toConsumableArray((_derivedSnap$activeSe3 = derivedSnap.activeSession) === null || _derivedSnap$activeSe3 === void 0 ? void 0 : _derivedSnap$activeSe3.messages));
244
+
245
+ // 将 messages 数组作为依赖项。当它变化时,Hook 会运行。
246
+ var _useAutoScroll = useAutoScroll(messages),
247
+ containerRef = _useAutoScroll.containerRef,
248
+ anchorRef = _useAutoScroll.anchorRef;
187
249
  return /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement(Flex, {
188
250
  gap: "middle",
189
251
  vertical: true,
190
- className: styles.chatContainer
191
- }, showMessages === null || showMessages === void 0 ? void 0 : showMessages.map(function (msg, index) {
252
+ className: styles.chatContainer,
253
+ ref: containerRef
254
+ }, messages.map(function (msg, index) {
255
+ var textContent = getTextContent(msg);
192
256
  return /*#__PURE__*/React.createElement(Bubble, {
193
- key: index,
257
+ key: msg.id || index,
194
258
  content: /*#__PURE__*/React.createElement(MarkdownComponent, {
195
- content: msg.content
259
+ content: textContent,
260
+ showRunButton: !props.simple
196
261
  }),
197
262
  avatar: msg.role === 'assistant' ? avatar : null,
198
- footer: msg.role === 'assistant' && index > 0 ? /*#__PURE__*/React.createElement(Space, {
263
+ footer: msg.role === 'assistant' && index > 0 && index === messages.length - 1 && status === 'ready' ? /*#__PURE__*/React.createElement(Space, {
199
264
  size: "small"
200
265
  }, /*#__PURE__*/React.createElement(Tooltip, {
201
- title: "\u70B9\u8D5E"
202
- }, /*#__PURE__*/React.createElement(Button, {
203
- color: "default",
204
- variant: "text",
205
- size: "small",
206
- icon: /*#__PURE__*/React.createElement(LikeOutlined, null)
207
- })), /*#__PURE__*/React.createElement(Tooltip, {
208
- title: "\u70B9\u8E29"
209
- }, /*#__PURE__*/React.createElement(Button, {
210
- color: "default",
211
- variant: "text",
212
- size: "small",
213
- icon: /*#__PURE__*/React.createElement(DislikeOutlined, null)
214
- })), index === showMessages.length - 1 && /*#__PURE__*/React.createElement(Tooltip, {
215
- title: "\u518D\u6765\u4E00\u6B21"
266
+ title: formatMessage({
267
+ id: 'ai.msgbox.retry'
268
+ })
216
269
  }, /*#__PURE__*/React.createElement(Button, {
217
270
  onClick: function onClick() {
271
+ regenerate();
218
272
  derivedState.activeSession.messages.pop();
219
- setIsStreaming(true);
220
273
  },
221
274
  color: "default",
222
275
  variant: "text",
223
276
  size: "small",
224
277
  icon: /*#__PURE__*/React.createElement(SyncOutlined, null)
225
278
  })), /*#__PURE__*/React.createElement(Tooltip, {
226
- title: "\u590D\u5236"
279
+ title: formatMessage({
280
+ id: 'ai.msgbox.copy'
281
+ })
227
282
  }, /*#__PURE__*/React.createElement(Button, {
228
283
  color: "default",
229
284
  variant: "text",
230
285
  size: "small",
231
286
  onClick: function onClick() {
232
- return copyToClipboard(msg.content);
287
+ return copyToClipboard(textContent);
233
288
  },
234
- icon: copyState.value === msg.content ? /*#__PURE__*/React.createElement(CheckOutlined, null) : /*#__PURE__*/React.createElement(CopyOutlined, null)
289
+ icon: copyState.value === textContent ? /*#__PURE__*/React.createElement(CheckOutlined, null) : /*#__PURE__*/React.createElement(CopyOutlined, null)
235
290
  }))) : null,
236
291
  placement: msg.role === 'user' ? 'end' : 'start'
237
292
  });
238
- }), loading && /*#__PURE__*/React.createElement(Bubble, {
293
+ }), (status === 'streaming' || status === 'submitted') && ((_messages = messages[messages.length - 1]) === null || _messages === void 0 ? void 0 : _messages.role) === 'user' && /*#__PURE__*/React.createElement(Bubble, {
239
294
  placement: "start",
240
295
  avatar: avatar,
241
- loading: loading
296
+ loading: true
297
+ }), /*#__PURE__*/React.createElement("div", {
298
+ ref: anchorRef,
299
+ id: "msgBoxAnchor"
242
300
  })), /*#__PURE__*/React.createElement("div", null, !props.simple && /*#__PURE__*/React.createElement("div", {
243
301
  className: styles.newButtonContainer
244
- }, /*#__PURE__*/React.createElement("button", {
302
+ }, /*#__PURE__*/React.createElement(Space, null, /*#__PURE__*/React.createElement("button", {
245
303
  type: "button",
246
304
  onClick: function onClick() {
247
- return history.push('/');
305
+ return createPureNewSession();
248
306
  },
249
307
  className: styles.newButton
250
- }, /*#__PURE__*/React.createElement(Space, null, /*#__PURE__*/React.createElement(PlusSquareOutlined, null), "\u5F00\u59CB\u65B0\u5BF9\u8BDD"))), /*#__PURE__*/React.createElement(PromptTextarea, {
308
+ }, /*#__PURE__*/React.createElement(Space, null, /*#__PURE__*/React.createElement(PlusSquareOutlined, null), formatMessage({
309
+ id: 'ai.msgbox.start.new.chat'
310
+ }))))), /*#__PURE__*/React.createElement(PromptTextarea, {
251
311
  size: "compact",
252
312
  mode: "implement",
253
313
  value: promptText,
254
314
  onChange: setPromptText,
255
- loading: loading,
256
- onCancel: function onCancel() {
257
- setIsStreaming(false);
258
- setLoading(false);
259
- },
315
+ loading: status === 'streaming' || status === 'submitted',
316
+ onCancel: stop,
260
317
  showAction: !props.simple,
261
318
  style: {
262
319
  marginBottom: 0
263
320
  },
264
321
  onConfirm: handleSubmit,
265
- lib: lib,
266
- onLibChange: setLib
322
+ onDataSummaryChange: setFileSummary
267
323
  })));
268
324
  }
269
325
  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
+ };
@@ -6,8 +6,8 @@ import React from 'react';
6
6
  import styles from "./index.module.less";
7
7
  import { ConversationsMenu } from "../ConversationsMenu";
8
8
  import { AIChatStore } from "../../../../model/AIChat";
9
- import { useSnapshot } from "valtio";
10
- import classnames from "classnames";
9
+ import { useSnapshot } from 'valtio';
10
+ import classnames from 'classnames';
11
11
  function SessionLayout(props) {
12
12
  var children = props.children;
13
13
  var snap = useSnapshot(AIChatStore);
@@ -14,13 +14,14 @@
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;
20
21
  }
21
22
 
22
23
  .msgBoxHalf {
23
- max-width: 30vw;
24
+ max-width: 40vw;
24
25
  }
25
26
 
26
27
  .msgBoxFull {
@@ -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
  }