@ant-design/agentic-ui 2.30.12 → 2.30.14

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 (51) hide show
  1. package/dist/Bubble/AIBubble.js +32 -18
  2. package/dist/Bubble/ContentFilemapView.d.ts +14 -0
  3. package/dist/Bubble/ContentFilemapView.js +95 -0
  4. package/dist/Bubble/MessagesContent/MarkdownPreview.js +3 -2
  5. package/dist/Bubble/UserBubble.js +48 -6
  6. package/dist/Bubble/extractFilemapBlocks.d.ts +17 -0
  7. package/dist/Bubble/extractFilemapBlocks.js +23 -0
  8. package/dist/Bubble/type.d.ts +3 -0
  9. package/dist/Hooks/useLanguage.d.ts +2 -0
  10. package/dist/I18n/locales.d.ts +2 -0
  11. package/dist/I18n/locales.js +5 -1
  12. package/dist/MarkdownEditor/editor/elements/AgenticUiBlocks/agenticUiEmbedUtils.d.ts +5 -1
  13. package/dist/MarkdownEditor/editor/elements/AgenticUiBlocks/agenticUiEmbedUtils.js +10 -2
  14. package/dist/MarkdownEditor/editor/elements/Code/index.js +22 -14
  15. package/dist/MarkdownEditor/editor/parser/constants.d.ts +10 -0
  16. package/dist/MarkdownEditor/editor/parser/constants.js +46 -0
  17. package/dist/MarkdownEditor/editor/parser/parserMarkdownToSlateNode.js +3 -1
  18. package/dist/MarkdownEditor/editor/parser/parserSlateNodeToMarkdown.js +11 -0
  19. package/dist/MarkdownEditor/editor/utils/markdownToHtml.js +6 -4
  20. package/dist/MarkdownEditor/types.d.ts +6 -0
  21. package/dist/MarkdownInputField/AttachmentButton/AttachmentFileList/AttachmentFileIcon.js +3 -1
  22. package/dist/MarkdownInputField/AttachmentButton/AttachmentFileList/AttachmentFileListItem.js +2 -2
  23. package/dist/MarkdownInputField/AttachmentButton/AttachmentFileList/index.js +6 -1
  24. package/dist/MarkdownInputField/AttachmentButton/AttachmentFileList/style.js +11 -1
  25. package/dist/MarkdownInputField/AttachmentButton/index.d.ts +12 -0
  26. package/dist/MarkdownInputField/AttachmentButton/index.js +23 -13
  27. package/dist/MarkdownInputField/FileMapView/FileMapViewItem.js +20 -1
  28. package/dist/MarkdownInputField/FileMapView/index.d.ts +13 -1
  29. package/dist/MarkdownInputField/FileMapView/index.js +57 -18
  30. package/dist/MarkdownInputField/FileMapView/style.js +6 -0
  31. package/dist/MarkdownInputField/FileUploadManager/index.js +4 -26
  32. package/dist/MarkdownInputField/style.js +7 -0
  33. package/dist/MarkdownRenderer/MarkdownRenderer.js +10 -6
  34. package/dist/MarkdownRenderer/index.d.ts +1 -1
  35. package/dist/MarkdownRenderer/renderers/AgenticUiFileMapBlockRenderer.d.ts +4 -2
  36. package/dist/MarkdownRenderer/renderers/AgenticUiFileMapBlockRenderer.js +47 -5
  37. package/dist/MarkdownRenderer/renderers/ChartRenderer.js +9 -0
  38. package/dist/MarkdownRenderer/streaming/useStreamingMarkdownReact.js +2 -2
  39. package/dist/MarkdownRenderer/types.d.ts +45 -2
  40. package/dist/MarkdownRenderer/useMarkdownToReact.js +2 -2
  41. package/dist/Plugins/chart/ChartRender.js +30 -9
  42. package/dist/Plugins/chart/DonutChart/index.js +21 -7
  43. package/dist/Plugins/chart/HistogramChart/index.d.ts +5 -1
  44. package/dist/Plugins/chart/HistogramChart/index.js +79 -12
  45. package/dist/Plugins/chart/ScatterChart/index.d.ts +8 -0
  46. package/dist/Plugins/chart/ScatterChart/index.js +78 -8
  47. package/dist/Plugins/chart/components/ChartContainer/ChartErrorBoundary.d.ts +4 -0
  48. package/dist/Plugins/code/components/AceEditor.js +69 -8
  49. package/dist/Plugins/code/components/CodeRenderer.js +0 -1
  50. package/dist/Workspace/Browser/index.js +3 -1
  51. package/package.json +1 -1
@@ -212,7 +212,7 @@ function _ts_generator(thisArg, body) {
212
212
  };
213
213
  }
214
214
  }
215
- import { memo, useContext, useRef } from "react";
215
+ import { memo, useContext, useMemo, useRef } from "react";
216
216
  import { ConfigProvider, Flex } from "antd";
217
217
  import clsx from "clsx";
218
218
  import { nanoid } from "nanoid";
@@ -220,11 +220,13 @@ import React from "react";
220
220
  import { BubbleAvatar } from "./Avatar";
221
221
  import { BubbleBeforeNode } from "./BubbleBeforeNode";
222
222
  import { BubbleConfigContext } from "./BubbleConfigProvide";
223
+ import { ContentFilemapView } from "./ContentFilemapView";
223
224
  import { BubbleFileView } from "./FileView";
224
225
  import { BubbleMessageDisplay } from "./MessagesContent";
225
226
  import { MessagesContext } from "./MessagesContent/BubbleContext";
226
227
  import { LOADING_FLAT } from "./MessagesContent";
227
228
  import { BubbleExtra } from "./MessagesContent/BubbleExtra";
229
+ import { extractFilemapBlocks } from "./extractFilemapBlocks";
228
230
  import { useStyle } from "./style";
229
231
  import { BubbleTitle } from "./Title";
230
232
  var AI_PLACEMENT = 'left';
@@ -310,13 +312,20 @@ var getTaskList = function getTaskList(originData) {
310
312
  }
311
313
  }
312
314
  var messageDisplayKey = (_ref = (_messageDisplayKeyRef_current = messageDisplayKeyRef.current) !== null && _messageDisplayKeyRef_current !== void 0 ? _messageDisplayKeyRef_current : id) !== null && _ref !== void 0 ? _ref : nanoid();
315
+ var rawContent = props === null || props === void 0 ? void 0 : (_props_originData1 = props.originData) === null || _props_originData1 === void 0 ? void 0 : _props_originData1.content;
316
+ var _useMemo = useMemo(function() {
317
+ return extractFilemapBlocks(typeof rawContent === 'string' ? rawContent : '');
318
+ }, [
319
+ rawContent
320
+ ]), filemapBlocks = _useMemo.blocks, strippedContent = _useMemo.stripped;
321
+ var contentForDisplay = filemapBlocks.length > 0 ? strippedContent : rawContent;
313
322
  var messageContent = /*#__PURE__*/ React.createElement(BubbleMessageDisplay, {
314
323
  markdownRenderConfig: props.markdownRenderConfig,
315
324
  docListProps: props.docListProps,
316
325
  bubbleListRef: props.bubbleListRef,
317
326
  bubbleListItemExtraStyle: styles === null || styles === void 0 ? void 0 : styles.bubbleListItemExtraStyle,
318
327
  bubbleRef: props.bubbleRef,
319
- content: props === null || props === void 0 ? void 0 : (_props_originData1 = props.originData) === null || _props_originData1 === void 0 ? void 0 : _props_originData1.content,
328
+ content: contentForDisplay,
320
329
  key: messageDisplayKey,
321
330
  "data-id": props === null || props === void 0 ? void 0 : (_props_originData2 = props.originData) === null || _props_originData2 === void 0 ? void 0 : _props_originData2.id,
322
331
  avatar: props === null || props === void 0 ? void 0 : (_props_originData3 = props.originData) === null || _props_originData3 === void 0 ? void 0 : _props_originData3.meta,
@@ -338,22 +347,22 @@ var getTaskList = function getTaskList(originData) {
338
347
  fileViewConfig: props.fileViewConfig,
339
348
  renderFileMoreAction: props.renderFileMoreAction,
340
349
  shouldShowVoice: props.shouldShowVoice,
341
- bubbleRenderConfig: props.bubbleRenderConfig,
342
- contentAfterDom: ((props === null || props === void 0 ? void 0 : (_props_originData6 = props.originData) === null || _props_originData6 === void 0 ? void 0 : (_props_originData_fileMap = _props_originData6.fileMap) === null || _props_originData_fileMap === void 0 ? void 0 : _props_originData_fileMap.size) || 0) > 0 ? /*#__PURE__*/ React.createElement("div", {
343
- style: _object_spread({
344
- minWidth: standalone ? 'min(296px,100%)' : '0px',
345
- paddingLeft: 12,
346
- maxWidth: '100%',
347
- width: '100%'
348
- }, styles === null || styles === void 0 ? void 0 : styles.bubbleListItemExtraStyle),
349
- className: clsx("".concat(prefixClass, "-bubble-after"), "".concat(prefixClass, "-bubble-after-").concat(placement), "".concat(prefixClass, "-bubble-after-ai"), hashId),
350
- "data-testid": "message-after"
351
- }, /*#__PURE__*/ React.createElement(BubbleFileView, {
352
- placement: placement,
353
- bubbleListRef: props.bubbleListRef,
354
- bubble: props
355
- })) : null
350
+ bubbleRenderConfig: props.bubbleRenderConfig
356
351
  });
352
+ var hasFileMap = ((props === null || props === void 0 ? void 0 : (_props_originData6 = props.originData) === null || _props_originData6 === void 0 ? void 0 : (_props_originData_fileMap = _props_originData6.fileMap) === null || _props_originData_fileMap === void 0 ? void 0 : _props_originData_fileMap.size) || 0) > 0;
353
+ var fileViewDom = hasFileMap ? /*#__PURE__*/ React.createElement("div", {
354
+ style: _object_spread({
355
+ minWidth: standalone ? 'min(296px,100%)' : '0px',
356
+ paddingLeft: 12,
357
+ maxWidth: '100%'
358
+ }, styles === null || styles === void 0 ? void 0 : styles.bubbleListItemExtraStyle),
359
+ className: clsx("".concat(prefixClass, "-bubble-after"), "".concat(prefixClass, "-bubble-after-").concat(placement), "".concat(prefixClass, "-bubble-after-ai"), hashId),
360
+ "data-testid": "message-after"
361
+ }, /*#__PURE__*/ React.createElement(BubbleFileView, {
362
+ placement: placement,
363
+ bubbleListRef: props.bubbleListRef,
364
+ bubble: props
365
+ })) : null;
357
366
  var childrenDom = runRender(bubbleRenderConfig === null || bubbleRenderConfig === void 0 ? void 0 : bubbleRenderConfig.contentRender, props, messageContent);
358
367
  var taskList = getTaskList(originData);
359
368
  var shouldShowBeforeContent = shouldRenderBeforeContent(placement, originData === null || originData === void 0 ? void 0 : originData.role, context === null || context === void 0 ? void 0 : context.thoughtChain, taskList.length);
@@ -402,7 +411,12 @@ var getTaskList = function getTaskList(originData) {
402
411
  className: clsx("".concat(prefixClass, "-bubble-content"), "".concat(prefixClass, "-bubble-content-").concat(placement), "".concat(prefixClass, "-bubble-content-ai"), _define_property({}, "".concat(prefixClass, "-bubble-content-pure"), props.pure), classNames === null || classNames === void 0 ? void 0 : classNames.bubbleListItemContentClassName, hashId),
403
412
  onDoubleClick: props.onDoubleClick,
404
413
  "data-testid": "message-content"
405
- }, childrenDom) : null, contentAfterDom)))));
414
+ }, childrenDom) : null, fileViewDom, contentAfterDom)), filemapBlocks.length > 0 && /*#__PURE__*/ React.createElement(ContentFilemapView, {
415
+ blocks: filemapBlocks,
416
+ fileViewConfig: props.fileViewConfig,
417
+ fileViewEvents: props.fileViewEvents,
418
+ placement: placement
419
+ }))));
406
420
  if ((bubbleRenderConfig === null || bubbleRenderConfig === void 0 ? void 0 : bubbleRenderConfig.render) === false) return null;
407
421
  return /*#__PURE__*/ React.createElement(MessagesContext.Provider, {
408
422
  value: {
@@ -0,0 +1,14 @@
1
+ import React from 'react';
2
+ import type { FilemapBlock } from './extractFilemapBlocks';
3
+ import type { BubbleProps } from './type';
4
+ /**
5
+ * 将从 markdown content 中提取出的 agentic-ui-filemap 块渲染为 FileMapView 列表。
6
+ * 渲染在气泡内容框外部,避免图片被包在带样式的气泡背景里。
7
+ */
8
+ export declare const ContentFilemapView: React.FC<{
9
+ blocks: FilemapBlock[];
10
+ fileViewConfig?: BubbleProps['fileViewConfig'];
11
+ fileViewEvents?: BubbleProps['fileViewEvents'];
12
+ placement?: 'left' | 'right';
13
+ style?: React.CSSProperties;
14
+ }>;
@@ -0,0 +1,95 @@
1
+ import json5 from "json5";
2
+ import React, { useMemo } from "react";
3
+ import { normalizeFileMapPropsFromJson } from "../MarkdownEditor/editor/elements/AgenticUiBlocks/agenticUiEmbedUtils";
4
+ import partialParse from "../MarkdownEditor/editor/parser/json-parse";
5
+ import { FileMapView } from "../MarkdownInputField/FileMapView";
6
+ var parseBody = function parseBody(body) {
7
+ try {
8
+ return json5.parse(body || '{}');
9
+ } catch (unused) {
10
+ try {
11
+ return partialParse(body || '{}');
12
+ } catch (unused) {
13
+ return null;
14
+ }
15
+ }
16
+ };
17
+ var FilemapItem = function FilemapItem(param) {
18
+ var body = param.body, fileViewConfig = param.fileViewConfig, fileViewEvents = param.fileViewEvents, placement = param.placement;
19
+ var parsed = useMemo(function() {
20
+ return parseBody(body);
21
+ }, [
22
+ body
23
+ ]);
24
+ var _useMemo = useMemo(function() {
25
+ return normalizeFileMapPropsFromJson(parsed);
26
+ }, [
27
+ parsed
28
+ ]), fileList = _useMemo.fileList, className = _useMemo.className;
29
+ var fileMap = useMemo(function() {
30
+ return new Map(fileList.map(function(f) {
31
+ return [
32
+ f.uuid || f.name,
33
+ f
34
+ ];
35
+ }));
36
+ }, [
37
+ fileList
38
+ ]);
39
+ var defaultHandlers = useMemo(function() {
40
+ return {
41
+ onPreview: function onPreview(file) {
42
+ var url = (file === null || file === void 0 ? void 0 : file.previewUrl) || (file === null || file === void 0 ? void 0 : file.url);
43
+ if (url && typeof window !== 'undefined') window.open(url, '_blank');
44
+ },
45
+ onDownload: function onDownload(file) {
46
+ var url = (file === null || file === void 0 ? void 0 : file.url) || (file === null || file === void 0 ? void 0 : file.previewUrl);
47
+ if (!url || typeof document === 'undefined') return;
48
+ var link = document.createElement('a');
49
+ link.href = url;
50
+ link.download = (file === null || file === void 0 ? void 0 : file.name) || 'download';
51
+ document.body.appendChild(link);
52
+ link.click();
53
+ document.body.removeChild(link);
54
+ },
55
+ onViewAll: function onViewAll() {}
56
+ };
57
+ }, []);
58
+ var events = {};
59
+ try {
60
+ events = (fileViewEvents === null || fileViewEvents === void 0 ? void 0 : fileViewEvents(defaultHandlers)) || {};
61
+ } catch (unused) {}
62
+ if (parsed === null || fileMap.size === 0) return null;
63
+ return /*#__PURE__*/ React.createElement(FileMapView, {
64
+ fileMap: fileMap,
65
+ className: className !== null && className !== void 0 ? className : fileViewConfig === null || fileViewConfig === void 0 ? void 0 : fileViewConfig.className,
66
+ style: fileViewConfig === null || fileViewConfig === void 0 ? void 0 : fileViewConfig.style,
67
+ placement: placement,
68
+ onPreview: events === null || events === void 0 ? void 0 : events.onPreview,
69
+ onDownload: events === null || events === void 0 ? void 0 : events.onDownload,
70
+ itemRender: fileViewConfig === null || fileViewConfig === void 0 ? void 0 : fileViewConfig.itemRender,
71
+ maxDisplayCount: fileViewConfig === null || fileViewConfig === void 0 ? void 0 : fileViewConfig.maxDisplayCount,
72
+ showMoreButton: fileViewConfig === null || fileViewConfig === void 0 ? void 0 : fileViewConfig.showMoreButton,
73
+ customSlot: fileViewConfig === null || fileViewConfig === void 0 ? void 0 : fileViewConfig.customSlot,
74
+ renderMoreAction: fileViewConfig === null || fileViewConfig === void 0 ? void 0 : fileViewConfig.renderFileMoreAction
75
+ });
76
+ };
77
+ /**
78
+ * 将从 markdown content 中提取出的 agentic-ui-filemap 块渲染为 FileMapView 列表。
79
+ * 渲染在气泡内容框外部,避免图片被包在带样式的气泡背景里。
80
+ */ export var ContentFilemapView = function ContentFilemapView(param) {
81
+ var blocks = param.blocks, fileViewConfig = param.fileViewConfig, fileViewEvents = param.fileViewEvents, placement = param.placement, style = param.style;
82
+ if (blocks.length === 0) return null;
83
+ return /*#__PURE__*/ React.createElement("div", {
84
+ style: style,
85
+ "data-testid": "content-filemap-view"
86
+ }, blocks.map(function(block, i) {
87
+ return /*#__PURE__*/ React.createElement(FilemapItem, {
88
+ key: i,
89
+ body: block.body,
90
+ fileViewConfig: fileViewConfig,
91
+ fileViewEvents: fileViewEvents,
92
+ placement: placement
93
+ });
94
+ }));
95
+ };
@@ -125,7 +125,7 @@ import { MessagesContext } from "./BubbleContext";
125
125
  var _content_includes, _htmlRef_current, _htmlRef_current1, _props_markdownRenderConfig, _props_originData, _props_originData1, _props_originData2, _props_markdownRenderConfig1, _props_markdownRenderConfig2, _props_markdownRenderConfig3;
126
126
  // MarkdownRenderer 渲染路径——轻量,不创建 Slate 实例
127
127
  if (renderMode === 'markdown') {
128
- var _props_originData3, _props_markdownRenderConfig4, _props_markdownRenderConfig5, _props_markdownRenderConfig6, _props_markdownRenderConfig7, _props_markdownRenderConfig8, _props_markdownRenderConfig9;
128
+ var _props_originData3, _props_markdownRenderConfig4, _props_markdownRenderConfig5, _props_markdownRenderConfig6, _props_markdownRenderConfig7, _props_markdownRenderConfig8, _props_markdownRenderConfig9, _props_markdownRenderConfig10;
129
129
  return /*#__PURE__*/ React.createElement(MarkdownRenderer, {
130
130
  content: content,
131
131
  streaming: typing,
@@ -140,7 +140,8 @@ import { MessagesContext } from "./BubbleContext";
140
140
  margin: isPaddingHidden ? 0 : undefined
141
141
  }, ((_props_markdownRenderConfig7 = props.markdownRenderConfig) === null || _props_markdownRenderConfig7 === void 0 ? void 0 : _props_markdownRenderConfig7.style) || {}),
142
142
  codeProps: (_props_markdownRenderConfig8 = props.markdownRenderConfig) === null || _props_markdownRenderConfig8 === void 0 ? void 0 : _props_markdownRenderConfig8.codeProps,
143
- apaasify: (_props_markdownRenderConfig9 = props.markdownRenderConfig) === null || _props_markdownRenderConfig9 === void 0 ? void 0 : _props_markdownRenderConfig9.apaasify
143
+ apaasify: (_props_markdownRenderConfig9 = props.markdownRenderConfig) === null || _props_markdownRenderConfig9 === void 0 ? void 0 : _props_markdownRenderConfig9.apaasify,
144
+ fileMapConfig: (_props_markdownRenderConfig10 = props.markdownRenderConfig) === null || _props_markdownRenderConfig10 === void 0 ? void 0 : _props_markdownRenderConfig10.fileMapConfig
144
145
  });
145
146
  }
146
147
  // Slate 渲染路径——保持向后兼容
@@ -61,6 +61,30 @@ function _object_spread(target) {
61
61
  }
62
62
  return target;
63
63
  }
64
+ function ownKeys(object, enumerableOnly) {
65
+ var keys = Object.keys(object);
66
+ if (Object.getOwnPropertySymbols) {
67
+ var symbols = Object.getOwnPropertySymbols(object);
68
+ if (enumerableOnly) {
69
+ symbols = symbols.filter(function(sym) {
70
+ return Object.getOwnPropertyDescriptor(object, sym).enumerable;
71
+ });
72
+ }
73
+ keys.push.apply(keys, symbols);
74
+ }
75
+ return keys;
76
+ }
77
+ function _object_spread_props(target, source) {
78
+ source = source != null ? source : {};
79
+ if (Object.getOwnPropertyDescriptors) {
80
+ Object.defineProperties(target, Object.getOwnPropertyDescriptors(source));
81
+ } else {
82
+ ownKeys(Object(source)).forEach(function(key) {
83
+ Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key));
84
+ });
85
+ }
86
+ return target;
87
+ }
64
88
  function _sliced_to_array(arr, i) {
65
89
  return _array_with_holes(arr) || _iterable_to_array_limit(arr, i) || _unsupported_iterable_to_array(arr, i) || _non_iterable_rest();
66
90
  }
@@ -72,15 +96,17 @@ function _unsupported_iterable_to_array(o, minLen) {
72
96
  if (n === "Map" || n === "Set") return Array.from(n);
73
97
  if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _array_like_to_array(o, minLen);
74
98
  }
75
- import { memo, useContext } from "react";
99
+ import { memo, useContext, useMemo } from "react";
76
100
  import { ConfigProvider, Flex } from "antd";
77
101
  import clsx from "clsx";
78
102
  import React from "react";
79
103
  import { Quote } from "../Quote";
80
104
  import { BubbleConfigContext } from "./BubbleConfigProvide";
105
+ import { ContentFilemapView } from "./ContentFilemapView";
81
106
  import { BubbleMessageDisplay } from "./MessagesContent";
82
107
  import { MessagesContext } from "./MessagesContent/BubbleContext";
83
108
  import { BubbleExtra } from "./MessagesContent/BubbleExtra";
109
+ import { extractFilemapBlocks } from "./extractFilemapBlocks";
84
110
  import { useStyle } from "./style";
85
111
  import { runRender } from "./AIBubble";
86
112
  import { BubbleFileView } from "./FileView";
@@ -134,6 +160,12 @@ var getContentStyle = function getContentStyle(standalone, customStyle) {
134
160
  var time = (originData === null || originData === void 0 ? void 0 : originData.createAt) || props.time;
135
161
  var placement = USER_PLACEMENT;
136
162
  var hasFileMap = ((originData === null || originData === void 0 ? void 0 : (_originData_fileMap = originData.fileMap) === null || _originData_fileMap === void 0 ? void 0 : _originData_fileMap.size) || 0) > 0;
163
+ var rawContent = originData === null || originData === void 0 ? void 0 : originData.content;
164
+ var _useMemo = useMemo(function() {
165
+ return extractFilemapBlocks(typeof rawContent === 'string' ? rawContent : '');
166
+ }, [
167
+ rawContent
168
+ ]), filemapBlocks = _useMemo.blocks, strippedContent = _useMemo.stripped;
137
169
  var quoteElement = (quote === null || quote === void 0 ? void 0 : quote.quoteDescription) ? /*#__PURE__*/ React.createElement(Quote, quote) : null;
138
170
  var titleDom = runRender(bubbleRenderConfig === null || bubbleRenderConfig === void 0 ? void 0 : bubbleRenderConfig.titleRender, props, /*#__PURE__*/ React.createElement(BubbleTitle, {
139
171
  quote: quoteElement,
@@ -151,7 +183,7 @@ var getContentStyle = function getContentStyle(standalone, customStyle) {
151
183
  bubbleListRef: props.bubbleListRef,
152
184
  bubbleListItemExtraStyle: styles === null || styles === void 0 ? void 0 : styles.bubbleListItemExtraStyle,
153
185
  bubbleRef: props.bubbleRef,
154
- content: originData === null || originData === void 0 ? void 0 : originData.content,
186
+ content: filemapBlocks.length > 0 ? strippedContent : originData === null || originData === void 0 ? void 0 : originData.content,
155
187
  key: originData === null || originData === void 0 ? void 0 : originData.id,
156
188
  "data-id": originData === null || originData === void 0 ? void 0 : originData.id,
157
189
  avatar: originData === null || originData === void 0 ? void 0 : originData.meta,
@@ -211,15 +243,25 @@ var getContentStyle = function getContentStyle(standalone, customStyle) {
211
243
  className: clsx("".concat(prefixClass, "-bubble-content"), "".concat(prefixClass, "-bubble-content-").concat(placement), "".concat(prefixClass, "-bubble-content-user"), _define_property({}, "".concat(prefixClass, "-bubble-content-pure"), props.pure), classNames === null || classNames === void 0 ? void 0 : classNames.bubbleListItemContentClassName, hashId),
212
244
  onDoubleClick: props.onDoubleClick,
213
245
  "data-testid": "message-content"
214
- }, childrenDom) : null, hasFileMap && /*#__PURE__*/ React.createElement("div", {
215
- style: fileViewStyle,
216
- className: clsx("".concat(prefixClass, "-bubble-after"), "".concat(prefixClass, "-bubble-after-").concat(placement), "".concat(prefixClass, "-bubble-after-ai"), hashId),
246
+ }, childrenDom) : null, contentAfterDom)), hasFileMap && /*#__PURE__*/ React.createElement("div", {
247
+ style: _object_spread_props(_object_spread({}, fileViewStyle), {
248
+ alignSelf: 'flex-end'
249
+ }),
250
+ className: clsx("".concat(prefixClass, "-bubble-after"), "".concat(prefixClass, "-bubble-after-").concat(placement), "".concat(prefixClass, "-bubble-after-user"), hashId),
217
251
  "data-testid": "message-after"
218
252
  }, /*#__PURE__*/ React.createElement(BubbleFileView, {
219
253
  bubbleListRef: props.bubbleListRef,
220
254
  bubble: props,
221
255
  placement: placement
222
- })), contentAfterDom)))));
256
+ })), filemapBlocks.length > 0 && /*#__PURE__*/ React.createElement(ContentFilemapView, {
257
+ blocks: filemapBlocks,
258
+ fileViewConfig: props.fileViewConfig,
259
+ fileViewEvents: props.fileViewEvents,
260
+ placement: placement,
261
+ style: {
262
+ alignSelf: 'flex-end'
263
+ }
264
+ }))));
223
265
  if ((bubbleRenderConfig === null || bubbleRenderConfig === void 0 ? void 0 : bubbleRenderConfig.render) === false) return null;
224
266
  return /*#__PURE__*/ React.createElement(MessagesContext.Provider, {
225
267
  value: {
@@ -0,0 +1,17 @@
1
+ export interface FilemapBlock {
2
+ raw: string;
3
+ body: string;
4
+ }
5
+ /**
6
+ * 从 markdown 字符串中提取所有 ```agentic-ui-filemap 代码块。
7
+ *
8
+ * 返回:
9
+ * - `blocks`:提取到的代码块列表,每项包含原始文本和内部 JSON body
10
+ * - `stripped`:移除了所有 filemap 块之后的干净 markdown 字符串
11
+ *
12
+ * 当消息内容中只含 filemap 块、没有其他文字时 `stripped` 为空字符串。
13
+ */
14
+ export declare const extractFilemapBlocks: (content: string) => {
15
+ blocks: FilemapBlock[];
16
+ stripped: string;
17
+ };
@@ -0,0 +1,23 @@
1
+ var FILEMAP_FENCE_RE = /^```agentic-ui-filemap[ \t]*\r?\n([\s\S]*?)^```[ \t]*$/gm;
2
+ /**
3
+ * 从 markdown 字符串中提取所有 ```agentic-ui-filemap 代码块。
4
+ *
5
+ * 返回:
6
+ * - `blocks`:提取到的代码块列表,每项包含原始文本和内部 JSON body
7
+ * - `stripped`:移除了所有 filemap 块之后的干净 markdown 字符串
8
+ *
9
+ * 当消息内容中只含 filemap 块、没有其他文字时 `stripped` 为空字符串。
10
+ */ export var extractFilemapBlocks = function extractFilemapBlocks(content) {
11
+ var blocks = [];
12
+ var stripped = content.replace(FILEMAP_FENCE_RE, function(raw, body) {
13
+ blocks.push({
14
+ raw: raw,
15
+ body: body.trim()
16
+ });
17
+ return '';
18
+ });
19
+ return {
20
+ blocks: blocks,
21
+ stripped: stripped.trim()
22
+ };
23
+ };
@@ -2,6 +2,7 @@ import { TooltipProps } from 'antd';
2
2
  import { ReactNode } from 'react';
3
3
  import { MarkdownEditorProps } from '../MarkdownEditor/types';
4
4
  import { AttachmentFile } from '../MarkdownInputField/AttachmentButton/types';
5
+ import type { FileMapViewProps } from '../MarkdownInputField/FileMapView';
5
6
  import { BaseStyleProps, BubbleMetaData, MessageBubbleData, MultiClassNameProps, MultiStyleProps, WithFalse } from '../Types';
6
7
  import type { UseSpeechAdapter } from './MessagesContent/VoiceButton';
7
8
  import { BubbleExtraProps } from './types/BubbleExtra';
@@ -406,6 +407,8 @@ export interface BubbleProps<T = Record<string, any>> extends BubbleItemStylePro
406
407
  className?: string;
407
408
  /** 自定义根容器样式 */
408
409
  style?: React.CSSProperties;
410
+ /** 自定义每个媒体(图片/视频)条目的渲染,透传 FileMapView */
411
+ itemRender?: FileMapViewProps['itemRender'];
409
412
  /** 最大展示条目数(默认 3) */
410
413
  maxDisplayCount?: number;
411
414
  /** 是否显示"查看更多"按钮 */
@@ -350,6 +350,8 @@ export declare function useLanguage(): {
350
350
  'suggestion.select': string;
351
351
  'suggestion.followUp': string;
352
352
  'input.fileUpload': string;
353
+ 'input.attachmentListTitle': string;
354
+ 'chat.fileMapTitle': string;
353
355
  'input.voiceInput': string;
354
356
  'input.voiceInputting': string;
355
357
  'input.placeholder': string;
@@ -312,6 +312,8 @@ export declare const cnLabels: {
312
312
  'suggestion.select': string;
313
313
  'suggestion.followUp': string;
314
314
  'input.fileUpload': string;
315
+ 'input.attachmentListTitle': string;
316
+ 'chat.fileMapTitle': string;
315
317
  'input.voiceInput': string;
316
318
  'input.voiceInputting': string;
317
319
  'input.placeholder': string;
@@ -332,6 +332,8 @@
332
332
  'suggestion.followUp': '追问',
333
333
  // MarkdownInputField related
334
334
  'input.fileUpload': '文件上传',
335
+ 'input.attachmentListTitle': '上传附件',
336
+ 'chat.fileMapTitle': '结果文件',
335
337
  'input.voiceInput': '语音输入',
336
338
  'input.voiceInputting': '语音输入中,点击可停止。',
337
339
  'input.placeholder': '请输入',
@@ -757,7 +759,9 @@
757
759
  'suggestion.select': 'Select suggestion',
758
760
  'suggestion.followUp': 'Follow-up',
759
761
  // MarkdownInputField related
760
- 'input.fileUpload': 'File upload',
762
+ 'input.fileUpload': 'Upload attachments',
763
+ 'input.attachmentListTitle': 'Uploaded attachments',
764
+ 'chat.fileMapTitle': 'Result files',
761
765
  'input.voiceInput': 'Voice input',
762
766
  'input.voiceInputting': 'Voice input in progress, click to stop.',
763
767
  'input.placeholder': 'Please input',
@@ -26,5 +26,9 @@ export interface NormalizedFileMapEmbedProps {
26
26
  }
27
27
  /**
28
28
  * 将 ```agentic-ui-filemap JSON 规范化为 FileMapView 所需 props
29
+ *
30
+ * @param parsed - 解析后的 JSON 数据
31
+ * @param normalizeFile - 可选的自定义文件规范化函数,接收原始 JSON 条目和默认生成的
32
+ * AttachmentFile,返回最终的 AttachmentFile;返回 null 时该条目被过滤掉
29
33
  */
30
- export declare function normalizeFileMapPropsFromJson(parsed: unknown): NormalizedFileMapEmbedProps;
34
+ export declare function normalizeFileMapPropsFromJson(parsed: unknown, normalizeFile?: (raw: Record<string, unknown>, defaultFile: AttachmentFile) => AttachmentFile | null): NormalizedFileMapEmbedProps;
@@ -190,7 +190,11 @@ var fileItemFromRecord = function fileItemFromRecord(x, index) {
190
190
  };
191
191
  /**
192
192
  * 将 ```agentic-ui-filemap JSON 规范化为 FileMapView 所需 props
193
- */ export function normalizeFileMapPropsFromJson(parsed) {
193
+ *
194
+ * @param parsed - 解析后的 JSON 数据
195
+ * @param normalizeFile - 可选的自定义文件规范化函数,接收原始 JSON 条目和默认生成的
196
+ * AttachmentFile,返回最终的 AttachmentFile;返回 null 时该条目被过滤掉
197
+ */ export function normalizeFileMapPropsFromJson(parsed, normalizeFile) {
194
198
  var root = parsed && (typeof parsed === "undefined" ? "undefined" : _type_of(parsed)) === 'object' && !Array.isArray(parsed) ? parsed : null;
195
199
  var rawItems = [];
196
200
  if (root && Array.isArray(root.fileList)) {
@@ -203,7 +207,11 @@ var fileItemFromRecord = function fileItemFromRecord(x, index) {
203
207
  var fileList = rawItems.filter(function(x) {
204
208
  return !!x && (typeof x === "undefined" ? "undefined" : _type_of(x)) === 'object';
205
209
  }).map(function(x, i) {
206
- return fileItemFromRecord(x, i);
210
+ var defaultFile = fileItemFromRecord(x, i);
211
+ if (!normalizeFile) return defaultFile;
212
+ return normalizeFile(x, defaultFile);
213
+ }).filter(function(f) {
214
+ return f !== null;
207
215
  });
208
216
  var className = root && typeof root.className === 'string' ? root.className : undefined;
209
217
  return {
@@ -55,7 +55,7 @@ import React from "react";
55
55
  import { debugInfo } from "../../../../Utils/debugUtils";
56
56
  export var Code = function Code(param) {
57
57
  var attributes = param.attributes, children = param.children, element = param.element;
58
- var _element_value, _element_otherProps, _element_otherProps1, _element_otherProps2, _element_otherProps3, _element_value1;
58
+ var _element_value, _element_otherProps, _element_otherProps1, _element_otherProps2;
59
59
  debugInfo('Code - 渲染代码块', {
60
60
  language: element === null || element === void 0 ? void 0 : element.language,
61
61
  valueLength: element === null || element === void 0 ? void 0 : (_element_value = element.value) === null || _element_value === void 0 ? void 0 : _element_value.length,
@@ -63,24 +63,31 @@ export var Code = function Code(param) {
63
63
  finished: element === null || element === void 0 ? void 0 : (_element_otherProps1 = element.otherProps) === null || _element_otherProps1 === void 0 ? void 0 : _element_otherProps1.finished
64
64
  });
65
65
  if ((element === null || element === void 0 ? void 0 : element.language) === 'html') {
66
- var _element_otherProps4, _element_otherProps5, _element_otherProps6, _element_value2;
66
+ var _element_otherProps3, _element_otherProps4, _element_otherProps5, _element_value1;
67
67
  debugInfo('Code - HTML 代码块', {
68
- isConfig: element === null || element === void 0 ? void 0 : (_element_otherProps4 = element.otherProps) === null || _element_otherProps4 === void 0 ? void 0 : _element_otherProps4.isConfig
68
+ isConfig: element === null || element === void 0 ? void 0 : (_element_otherProps3 = element.otherProps) === null || _element_otherProps3 === void 0 ? void 0 : _element_otherProps3.isConfig
69
69
  });
70
70
  return /*#__PURE__*/ React.createElement("div", _object_spread_props(_object_spread({}, attributes), {
71
71
  style: {
72
- display: (element === null || element === void 0 ? void 0 : (_element_otherProps5 = element.otherProps) === null || _element_otherProps5 === void 0 ? void 0 : _element_otherProps5.isConfig) ? 'none' : 'block'
72
+ display: (element === null || element === void 0 ? void 0 : (_element_otherProps4 = element.otherProps) === null || _element_otherProps4 === void 0 ? void 0 : _element_otherProps4.isConfig) ? 'none' : 'block'
73
73
  }
74
- }), (element === null || element === void 0 ? void 0 : (_element_otherProps6 = element.otherProps) === null || _element_otherProps6 === void 0 ? void 0 : _element_otherProps6.isConfig) ? '' : DOMPurify.sanitize(element === null || element === void 0 ? void 0 : (_element_value2 = element.value) === null || _element_value2 === void 0 ? void 0 : _element_value2.trim()));
74
+ }), (element === null || element === void 0 ? void 0 : (_element_otherProps5 = element.otherProps) === null || _element_otherProps5 === void 0 ? void 0 : _element_otherProps5.isConfig) ? null : /*#__PURE__*/ React.createElement("div", {
75
+ contentEditable: false,
76
+ dangerouslySetInnerHTML: {
77
+ __html: DOMPurify.sanitize((element === null || element === void 0 ? void 0 : (_element_value1 = element.value) === null || _element_value1 === void 0 ? void 0 : _element_value1.trim()) || '')
78
+ }
79
+ }), /*#__PURE__*/ React.createElement("span", {
80
+ style: {
81
+ display: 'none'
82
+ }
83
+ }, children));
75
84
  }
76
85
  // 检查代码块是否未闭合
77
86
  var isUnclosed = (element === null || element === void 0 ? void 0 : (_element_otherProps2 = element.otherProps) === null || _element_otherProps2 === void 0 ? void 0 : _element_otherProps2.finished) === false;
78
87
  return /*#__PURE__*/ React.createElement("div", _object_spread_props(_object_spread({}, attributes), {
79
88
  "data-is-unclosed": isUnclosed,
80
89
  "data-language": element === null || element === void 0 ? void 0 : element.language,
81
- style: (element === null || element === void 0 ? void 0 : element.language) === 'html' ? {
82
- display: (element === null || element === void 0 ? void 0 : (_element_otherProps3 = element.otherProps) === null || _element_otherProps3 === void 0 ? void 0 : _element_otherProps3.isConfig) ? 'none' : 'block'
83
- } : {
90
+ style: {
84
91
  height: '240px',
85
92
  minWidth: '398px',
86
93
  maxWidth: '800px',
@@ -93,17 +100,18 @@ export var Code = function Code(param) {
93
100
  color: 'rgb(27, 27, 27)',
94
101
  padding: '1em',
95
102
  margin: '1em 0',
96
- fontSize: '0.8em',
103
+ fontSize: '1em',
97
104
  lineHeight: '1.5',
98
105
  overflowX: 'auto',
99
- whiteSpace: 'pre-wrap',
100
- wordBreak: 'break-all',
101
- fontFamily: "'SFMono-Regular', Consolas, 'Liberation Mono', Menlo, Courier, monospace",
102
- wordWrap: 'break-word',
103
106
  borderRadius: '12px',
104
107
  background: '#FFFFFF',
105
108
  boxShadow: 'var(--shadow-control-base)',
106
109
  position: 'relative'
107
110
  }
108
- }), (element === null || element === void 0 ? void 0 : (_element_value1 = element.value) === null || _element_value1 === void 0 ? void 0 : _element_value1.trim()) || children);
111
+ }), /*#__PURE__*/ React.createElement("div", {
112
+ style: {
113
+ width: '100%',
114
+ height: '100%'
115
+ }
116
+ }, children));
109
117
  };
@@ -3,6 +3,16 @@
3
3
  * 在 markdown 解析前替换,渲染与序列化时还原为 $。
4
4
  */
5
5
  export declare const JINJA_DOLLAR_PLACEHOLDER = "\uE01A";
6
+ /**
7
+ * 将行首的双冒号写法规范化为三冒号,使其能被 remarkDirectiveContainersOnly 正确解析。
8
+ *
9
+ * 处理两种模式:
10
+ * - `::name` → `:::name`(开启行,后跟合法标识符字母)
11
+ * - `::` 单独一行 → `:::`(关闭行,行首恰好两个冒号且后无非空字符)
12
+ *
13
+ * 代码围栏内的行不处理。
14
+ */
15
+ export declare function preprocessNormalizeLeafToContainerDirective(markdown: string): string;
6
16
  /**
7
17
  * 保护时间格式(如 02:20:31)不被 remark-directive 误解析为 textDirective。
8
18
  * remark-directive 会将 ":20"、":31" 等解析为指令,导致 "Cannot handle unknown node textDirective"。
@@ -58,6 +58,52 @@ function protectLineFromDirectiveTime(markdownLine) {
58
58
  }
59
59
  return result;
60
60
  }
61
+ /**
62
+ * 将行首的双冒号写法规范化为三冒号,使其能被 remarkDirectiveContainersOnly 正确解析。
63
+ *
64
+ * 处理两种模式:
65
+ * - `::name` → `:::name`(开启行,后跟合法标识符字母)
66
+ * - `::` 单独一行 → `:::`(关闭行,行首恰好两个冒号且后无非空字符)
67
+ *
68
+ * 代码围栏内的行不处理。
69
+ */ export function preprocessNormalizeLeafToContainerDirective(markdown) {
70
+ if (!markdown || markdown.length === 0) return markdown;
71
+ var lines = markdown.split('\n');
72
+ var inFence = false;
73
+ var out = [];
74
+ var _iteratorNormalCompletion = true, _didIteratorError = false, _iteratorError = undefined;
75
+ try {
76
+ for(var _iterator = lines[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true){
77
+ var line = _step.value;
78
+ if (FENCE_DELIMITER_LINE.test(line)) {
79
+ inFence = !inFence;
80
+ out.push(line);
81
+ continue;
82
+ }
83
+ if (!inFence && /^:{2}(?!:)[a-zA-Z]/.test(line)) {
84
+ out.push(':' + line);
85
+ } else if (!inFence && /^:{2}\s*$/.test(line)) {
86
+ out.push(':::');
87
+ } else {
88
+ out.push(line);
89
+ }
90
+ }
91
+ } catch (err) {
92
+ _didIteratorError = true;
93
+ _iteratorError = err;
94
+ } finally{
95
+ try {
96
+ if (!_iteratorNormalCompletion && _iterator.return != null) {
97
+ _iterator.return();
98
+ }
99
+ } finally{
100
+ if (_didIteratorError) {
101
+ throw _iteratorError;
102
+ }
103
+ }
104
+ }
105
+ return out.join('\n');
106
+ }
61
107
  /**
62
108
  * 保护时间格式(如 02:20:31)不被 remark-directive 误解析为 textDirective。
63
109
  * remark-directive 会将 ":20"、":31" 等解析为指令,导致 "Cannot handle unknown node textDirective"。
@@ -108,6 +108,7 @@ import { handleHtml, preprocessNonStandardHtmlTags, preprocessThinkTags } from "
108
108
  import { handleInlineMath, handleMath } from "./parse/parseMath";
109
109
  import { handleImage } from "./parse/parseMedia";
110
110
  import { parseTableOrChart, preprocessMarkdownTableNewlines } from "./parse/parseTable";
111
+ import { preprocessNormalizeLeafToContainerDirective } from "./constants";
111
112
  import mdastParser from "./remarkParse";
112
113
  // 全局解析缓存
113
114
  var parseCache = new Map();
@@ -237,7 +238,8 @@ var removeAnswerTags = function removeAnswerTags(text) {
237
238
  value: function preprocessMarkdown(md) {
238
239
  var thinkProcessed = removeAnswerTags(preprocessThinkTags(md || ''));
239
240
  var nonStandardProcessed = removeAnswerTags(preprocessNonStandardHtmlTags(thinkProcessed));
240
- return preprocessMarkdownTableNewlines(nonStandardProcessed);
241
+ var tableProcessed = preprocessMarkdownTableNewlines(nonStandardProcessed);
242
+ return preprocessNormalizeLeafToContainerDirective(tableProcessed);
241
243
  }
242
244
  },
243
245
  {