@ant-design/agentic-ui 2.30.29 → 2.30.31

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 (56) hide show
  1. package/dist/Bubble/AIBubble.js +6 -3
  2. package/dist/Bubble/List/PureBubbleList.js +22 -1
  3. package/dist/Bubble/List/index.js +7 -5
  4. package/dist/Bubble/MessagesContent/BubbleExtra.js +4 -2
  5. package/dist/Components/ActionIconBox/index.js +8 -8
  6. package/dist/Hooks/useLanguage.d.ts +1 -0
  7. package/dist/I18n/locales.d.ts +1 -0
  8. package/dist/I18n/locales.js +2 -0
  9. package/dist/MarkdownEditor/BaseMarkdownEditor.d.ts +1 -0
  10. package/dist/MarkdownEditor/BaseMarkdownEditor.js +8 -4
  11. package/dist/MarkdownEditor/editor/parser/parse/parseHtml.js +15 -6
  12. package/dist/MarkdownEditor/style.js +0 -5
  13. package/dist/MarkdownEditor/utils/sanitizeChromeStyle.d.ts +6 -0
  14. package/dist/MarkdownEditor/utils/sanitizeChromeStyle.js +87 -0
  15. package/dist/MarkdownInputField/AttachmentButton/AttachmentFileList/style.js +0 -1
  16. package/dist/MarkdownInputField/MarkdownInputField.js +6 -3
  17. package/dist/MarkdownInputField/SendButton/index.d.ts +2 -2
  18. package/dist/MarkdownInputField/SendButton/index.js +45 -27
  19. package/dist/MarkdownInputField/SendButton/sendButtonPalette.d.ts +36 -0
  20. package/dist/MarkdownInputField/SendButton/sendButtonPalette.js +247 -0
  21. package/dist/MarkdownInputField/SendButton/style.js +9 -6
  22. package/dist/MarkdownInputField/style.js +3 -1
  23. package/dist/MarkdownRenderer/AnimationText.js +1 -2
  24. package/dist/MarkdownRenderer/CharacterQueue.js +3 -0
  25. package/dist/MarkdownRenderer/MarkdownRenderer.js +5 -18
  26. package/dist/MarkdownRenderer/markdownReactShared.d.ts +2 -1
  27. package/dist/MarkdownRenderer/markdownReactShared.js +57 -19
  28. package/dist/MarkdownRenderer/streaming/MarkdownBlockPiece.js +14 -10
  29. package/dist/MarkdownRenderer/streaming/fenceTracker.d.ts +7 -0
  30. package/dist/MarkdownRenderer/streaming/fenceTracker.js +28 -0
  31. package/dist/MarkdownRenderer/streaming/lastBlockThrottle.js +3 -1
  32. package/dist/MarkdownRenderer/streaming/useShallowMemo.d.ts +1 -0
  33. package/dist/MarkdownRenderer/streaming/useShallowMemo.js +36 -0
  34. package/dist/MarkdownRenderer/streaming/useStreamingMarkdownReact.js +6 -3
  35. package/dist/MarkdownRenderer/useStreaming.js +43 -41
  36. package/dist/Plugins/chart/components/ChartContainer/ChartErrorBoundary.d.ts +2 -0
  37. package/dist/TaskList/TaskList.js +25 -13
  38. package/dist/TaskList/constants.d.ts +1 -1
  39. package/dist/TaskList/constants.js +9 -4
  40. package/dist/TaskList/style.js +29 -11
  41. package/dist/ToolUseBarThink/index.d.ts +0 -23
  42. package/dist/ToolUseBarThink/index.js +178 -315
  43. package/dist/ToolUseBarThink/style.js +64 -48
  44. package/dist/Types/quicklink.d.ts +1 -1
  45. package/dist/Workspace/File/FileTree/FileTreeComponent.d.ts +4 -0
  46. package/dist/Workspace/File/FileTree/FileTreeComponent.js +283 -0
  47. package/dist/Workspace/File/FileTree/index.d.ts +2 -0
  48. package/dist/Workspace/File/FileTree/index.js +1 -0
  49. package/dist/Workspace/File/FileTree/style.d.ts +8 -0
  50. package/dist/Workspace/File/FileTree/style.js +80 -0
  51. package/dist/Workspace/File/index.d.ts +2 -1
  52. package/dist/Workspace/File/index.js +1 -0
  53. package/dist/Workspace/index.d.ts +4 -2
  54. package/dist/Workspace/index.js +73 -36
  55. package/dist/Workspace/types.d.ts +70 -2
  56. package/package.json +4 -4
@@ -0,0 +1,36 @@
1
+ /**
2
+ * 发送按钮默认色板:用 Ant Design token 的实色保证相对 colorBgContainer 的对比度,
3
+ * 随亮色 / 暗色主题切换。半透明 token 先与 colorBgContainer 叠算再比对比度、再混合。
4
+ */
5
+ export interface SendButtonPaletteToken {
6
+ colorPrimary: string;
7
+ colorBgContainer: string;
8
+ colorTextLightSolid: string;
9
+ colorTextTertiary: string;
10
+ colorFillTertiary: string;
11
+ colorText?: string;
12
+ }
13
+ /**
14
+ * 基于当前主题 token 生成默认可发送 / 未激活填充与图标色
15
+ */
16
+ export declare function getSendButtonPalette(token: SendButtonPaletteToken): {
17
+ readonly backgroundActive: string;
18
+ readonly backgroundMuted: string;
19
+ readonly iconActive: string;
20
+ readonly iconMuted: string;
21
+ };
22
+ export type SendButtonResolvedColors = {
23
+ backgroundActive: string;
24
+ backgroundMuted: string;
25
+ iconActive: string;
26
+ iconMuted: string;
27
+ };
28
+ /**
29
+ * 合并默认色板与用户 `colors`;与原先 background/backgroundHover、icon/iconHover 语义一致
30
+ */
31
+ export declare function resolveSendButtonDisplayColors(basePalette: SendButtonResolvedColors, colors: {
32
+ icon?: string;
33
+ iconHover?: string;
34
+ background?: string;
35
+ backgroundHover?: string;
36
+ } | undefined, token: SendButtonPaletteToken): SendButtonResolvedColors;
@@ -0,0 +1,247 @@
1
+ /**
2
+ * 发送按钮默认色板:用 Ant Design token 的实色保证相对 colorBgContainer 的对比度,
3
+ * 随亮色 / 暗色主题切换。半透明 token 先与 colorBgContainer 叠算再比对比度、再混合。
4
+ */ function _array_like_to_array(arr, len) {
5
+ if (len == null || len > arr.length) len = arr.length;
6
+ for(var i = 0, arr2 = new Array(len); i < len; i++)arr2[i] = arr[i];
7
+ return arr2;
8
+ }
9
+ function _array_with_holes(arr) {
10
+ if (Array.isArray(arr)) return arr;
11
+ }
12
+ function _iterable_to_array_limit(arr, i) {
13
+ var _i = arr == null ? null : typeof Symbol !== "undefined" && arr[Symbol.iterator] || arr["@@iterator"];
14
+ if (_i == null) return;
15
+ var _arr = [];
16
+ var _n = true;
17
+ var _d = false;
18
+ var _s, _e;
19
+ try {
20
+ for(_i = _i.call(arr); !(_n = (_s = _i.next()).done); _n = true){
21
+ _arr.push(_s.value);
22
+ if (i && _arr.length === i) break;
23
+ }
24
+ } catch (err) {
25
+ _d = true;
26
+ _e = err;
27
+ } finally{
28
+ try {
29
+ if (!_n && _i["return"] != null) _i["return"]();
30
+ } finally{
31
+ if (_d) throw _e;
32
+ }
33
+ }
34
+ return _arr;
35
+ }
36
+ function _non_iterable_rest() {
37
+ throw new TypeError("Invalid attempt to destructure non-iterable instance.\\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.");
38
+ }
39
+ function _sliced_to_array(arr, i) {
40
+ return _array_with_holes(arr) || _iterable_to_array_limit(arr, i) || _unsupported_iterable_to_array(arr, i) || _non_iterable_rest();
41
+ }
42
+ function _unsupported_iterable_to_array(o, minLen) {
43
+ if (!o) return;
44
+ if (typeof o === "string") return _array_like_to_array(o, minLen);
45
+ var n = Object.prototype.toString.call(o).slice(8, -1);
46
+ if (n === "Object" && o.constructor) n = o.constructor.name;
47
+ if (n === "Map" || n === "Set") return Array.from(n);
48
+ if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _array_like_to_array(o, minLen);
49
+ }
50
+ var SHORT_HEX = /^#([0-9a-f]{3})$/i;
51
+ var LONG_HEX6 = /^#([0-9a-f]{6})$/i;
52
+ var LONG_HEX8 = /^#([0-9a-f]{8})$/i;
53
+ var RGBA = /^rgba?\(\s*(\d{1,3})\s*,\s*(\d{1,3})\s*,\s*(\d{1,3})(?:\s*[,/]\s*([\d.]+))?\s*\)/i;
54
+ var clamp = function clamp(n, min, max) {
55
+ return Math.min(max, Math.max(min, n));
56
+ };
57
+ var compositeOn = function compositeOn(fr, fg, fb, a, br, bg, bb) {
58
+ var u = clamp(a, 0, 1);
59
+ return {
60
+ r: Math.round(fr * u + br * (1 - u)),
61
+ g: Math.round(fg * u + bg * (1 - u)),
62
+ b: Math.round(fb * u + bb * (1 - u))
63
+ };
64
+ };
65
+ /**
66
+ * 不透明色:#rgb #rrggbb、rgb(,,) 无 alpha
67
+ */ var parseOpaqueRgb = function parseOpaqueRgb(color) {
68
+ var t = color.trim();
69
+ var shortM = t.match(SHORT_HEX);
70
+ if (shortM) {
71
+ var _shortM__split = _sliced_to_array(shortM[1].split(''), 3), a = _shortM__split[0], b = _shortM__split[1], c = _shortM__split[2];
72
+ return {
73
+ r: parseInt(a + a, 16),
74
+ g: parseInt(b + b, 16),
75
+ b: parseInt(c + c, 16)
76
+ };
77
+ }
78
+ var long6 = t.match(LONG_HEX6);
79
+ if (long6) {
80
+ return {
81
+ r: parseInt(long6[1].slice(0, 2), 16),
82
+ g: parseInt(long6[1].slice(2, 4), 16),
83
+ b: parseInt(long6[1].slice(4, 6), 16)
84
+ };
85
+ }
86
+ var m = t.match(/^rgb\(\s*(\d{1,3})\s*,\s*(\d{1,3})\s*,\s*(\d{1,3})\s*\)/i);
87
+ if (m) {
88
+ return {
89
+ r: Number(m[1]),
90
+ g: Number(m[2]),
91
+ b: Number(m[3])
92
+ };
93
+ }
94
+ return null;
95
+ };
96
+ /**
97
+ * 任意色值在 `onBackground` 上呈现的有效 sRGB(含 rgba / 8 位 hex 叠色)
98
+ */ var toRgbOnBackground = function toRgbOnBackground(color, onBackground) {
99
+ var t = color.trim();
100
+ var bg = parseOpaqueRgb(onBackground);
101
+ if (!bg) {
102
+ return null;
103
+ }
104
+ var long8 = t.match(LONG_HEX8);
105
+ if (long8) {
106
+ var r = parseInt(long8[1].slice(0, 2), 16);
107
+ var g = parseInt(long8[1].slice(2, 4), 16);
108
+ var b = parseInt(long8[1].slice(4, 6), 16);
109
+ var a = parseInt(long8[1].slice(6, 8), 16) / 255;
110
+ return compositeOn(r, g, b, a, bg.r, bg.g, bg.b);
111
+ }
112
+ var rgbaM = t.match(RGBA);
113
+ if (rgbaM) {
114
+ var r1 = Number(rgbaM[1]);
115
+ var g1 = Number(rgbaM[2]);
116
+ var b1 = Number(rgbaM[3]);
117
+ var a1 = rgbaM[4] === undefined ? 1 : Number(rgbaM[4]);
118
+ if (a1 >= 1 - 1e-6) {
119
+ return {
120
+ r: r1,
121
+ g: g1,
122
+ b: b1
123
+ };
124
+ }
125
+ return compositeOn(r1, g1, b1, a1, bg.r, bg.g, bg.b);
126
+ }
127
+ return parseOpaqueRgb(t);
128
+ };
129
+ var toRgbString = function toRgbString(rgb) {
130
+ return "rgb(".concat(rgb.r, ",").concat(rgb.g, ",").concat(rgb.b, ")");
131
+ };
132
+ var relativeLuminance = function relativeLuminance(r, g, b) {
133
+ var _map = _sliced_to_array([
134
+ r,
135
+ g,
136
+ b
137
+ ].map(function(c) {
138
+ var s = c / 255;
139
+ return s <= 0.04045 ? s / 12.92 : Math.pow((s + 0.055) / 1.055, 2.4);
140
+ }), 3), rs = _map[0], gs = _map[1], bs = _map[2];
141
+ return 0.2126 * rs + 0.7152 * gs + 0.0722 * bs;
142
+ };
143
+ var contrastRatio = function contrastRatio(c1, c2) {
144
+ var a = toRgbOnBackground(c1, c2);
145
+ var b = toRgbOnBackground(c2, c2);
146
+ if (!a || !b) {
147
+ return null;
148
+ }
149
+ var l1 = relativeLuminance(a.r, a.g, a.b);
150
+ var l2 = relativeLuminance(b.r, b.g, b.b);
151
+ var L1 = Math.max(l1, l2);
152
+ var L2 = Math.min(l1, l2);
153
+ return (L1 + 0.05) / (L2 + 0.05);
154
+ };
155
+ /**
156
+ * 线性 sRGB 混合两色(先相对 `mixBase` 还原为实色),输出不透明 rgb()
157
+ */ var mixSrgb = function mixSrgb(fg, bg, t, mixBase) {
158
+ var a = toRgbOnBackground(fg, mixBase);
159
+ var b = toRgbOnBackground(bg, mixBase);
160
+ if (!a || !b) {
161
+ return fg;
162
+ }
163
+ var u = clamp(t, 0, 1);
164
+ var m = function m(x, y) {
165
+ return Math.round(x * u + y * (1 - u));
166
+ };
167
+ return toRgbString({
168
+ r: m(a.r, b.r),
169
+ g: m(a.g, b.g),
170
+ b: m(a.b, b.b)
171
+ });
172
+ };
173
+ var MIN_MUTED_ICON_CONTRAST = 2.4;
174
+ var MIN_MUTED_FILL_CONTRAST = 1.4;
175
+ var DEFAULT_LIGHT_SOLID = '#ffffff';
176
+ /**
177
+ * 基于当前主题 token 生成默认可发送 / 未激活填充与图标色
178
+ */ export function getSendButtonPalette(token) {
179
+ var colorBgContainer = token.colorBgContainer, colorPrimary = token.colorPrimary, colorTextLightSolid = token.colorTextLightSolid;
180
+ var textTertiary = token.colorTextTertiary;
181
+ var fillTertiary = token.colorFillTertiary;
182
+ var lightSolid = colorTextLightSolid || DEFAULT_LIGHT_SOLID;
183
+ var fillMuted = fillTertiary;
184
+ var cFill = contrastRatio(fillMuted, colorBgContainer);
185
+ for(var i = 0; i < 6 && cFill !== null && cFill < MIN_MUTED_FILL_CONTRAST; i += 1){
186
+ fillMuted = mixSrgb(colorPrimary, colorBgContainer, 0.1 + i * 0.06, colorBgContainer);
187
+ cFill = contrastRatio(fillMuted, colorBgContainer);
188
+ }
189
+ if (cFill === null) {
190
+ fillMuted = mixSrgb(colorPrimary, colorBgContainer, 0.1, colorBgContainer);
191
+ }
192
+ var iconMuted = textTertiary;
193
+ var cIcon = contrastRatio(iconMuted, colorBgContainer);
194
+ for(var j = 0; j < 6 && cIcon !== null && cIcon < MIN_MUTED_ICON_CONTRAST; j += 1){
195
+ var mixT = 0.55 - j * 0.08;
196
+ iconMuted = mixSrgb(colorPrimary, colorBgContainer, Math.max(0, mixT), colorBgContainer);
197
+ cIcon = contrastRatio(iconMuted, colorBgContainer);
198
+ }
199
+ if (cIcon === null) {
200
+ iconMuted = mixSrgb(colorPrimary, colorBgContainer, 0.45, colorBgContainer);
201
+ }
202
+ var fillFinal = toRgbOnBackground(fillMuted, colorBgContainer);
203
+ var iconFinal = toRgbOnBackground(iconMuted, colorBgContainer);
204
+ return {
205
+ backgroundActive: colorPrimary,
206
+ backgroundMuted: fillFinal ? toRgbString(fillFinal) : fillMuted,
207
+ iconActive: lightSolid,
208
+ iconMuted: iconFinal ? toRgbString(iconFinal) : iconMuted
209
+ };
210
+ }
211
+ var tuneFillTowardContainer = function tuneFillTowardContainer(source, colorBgContainer, hintPrimary) {
212
+ var fill = mixSrgb(source, colorBgContainer, 0.1, colorBgContainer);
213
+ var c = contrastRatio(fill, colorBgContainer);
214
+ for(var i = 0; i < 6 && c !== null && c < MIN_MUTED_FILL_CONTRAST; i += 1){
215
+ fill = mixSrgb(i % 2 === 0 ? hintPrimary : source, colorBgContainer, 0.12 + i * 0.05, colorBgContainer);
216
+ c = contrastRatio(fill, colorBgContainer);
217
+ }
218
+ var rgb = toRgbOnBackground(fill, colorBgContainer);
219
+ return rgb ? toRgbString(rgb) : fill;
220
+ };
221
+ var tuneIconTowardContainer = function tuneIconTowardContainer(source, colorBgContainer, hintPrimary) {
222
+ var icon = mixSrgb(source, colorBgContainer, 0.4, colorBgContainer);
223
+ var c = contrastRatio(icon, colorBgContainer);
224
+ for(var j = 0; j < 6 && c !== null && c < MIN_MUTED_ICON_CONTRAST; j += 1){
225
+ icon = mixSrgb(j % 2 === 0 ? hintPrimary : source, colorBgContainer, 0.5 - j * 0.07, colorBgContainer);
226
+ c = contrastRatio(icon, colorBgContainer);
227
+ }
228
+ var rgb = toRgbOnBackground(icon, colorBgContainer);
229
+ return rgb ? toRgbString(rgb) : icon;
230
+ };
231
+ /**
232
+ * 合并默认色板与用户 `colors`;与原先 background/backgroundHover、icon/iconHover 语义一致
233
+ */ export function resolveSendButtonDisplayColors(basePalette, colors, token) {
234
+ var _ref, _colors_backgroundHover, _ref1, _colors_iconHover;
235
+ if (!colors) {
236
+ return basePalette;
237
+ }
238
+ var colorBgContainer = token.colorBgContainer, colorPrimary = token.colorPrimary;
239
+ var backgroundActive = (_ref = (_colors_backgroundHover = colors.backgroundHover) !== null && _colors_backgroundHover !== void 0 ? _colors_backgroundHover : colors.background) !== null && _ref !== void 0 ? _ref : basePalette.backgroundActive;
240
+ var iconActive = (_ref1 = (_colors_iconHover = colors.iconHover) !== null && _colors_iconHover !== void 0 ? _colors_iconHover : colors.icon) !== null && _ref1 !== void 0 ? _ref1 : basePalette.iconActive;
241
+ return {
242
+ backgroundActive: backgroundActive,
243
+ backgroundMuted: colors.background ? tuneFillTowardContainer(colors.background, colorBgContainer, colorPrimary) : basePalette.backgroundMuted,
244
+ iconActive: iconActive,
245
+ iconMuted: colors.icon ? tuneIconTowardContainer(colors.icon, colorBgContainer, colorPrimary) : basePalette.iconMuted
246
+ };
247
+ }
@@ -62,7 +62,8 @@ var pauseIconRotate = new Keyframes('pauseIconRotate', {
62
62
  }
63
63
  });
64
64
  var genStyle = function genStyle(token) {
65
- return _define_property({}, token.componentCls, {
65
+ var _obj;
66
+ return _obj = {}, _define_property(_obj, token.componentCls, {
66
67
  fontSize: '32px',
67
68
  height: 32,
68
69
  display: 'flex',
@@ -70,10 +71,6 @@ var genStyle = function genStyle(token) {
70
71
  lineHeight: '32px',
71
72
  cursor: 'pointer',
72
73
  marginLeft: 4,
73
- '&&-disabled': {
74
- cursor: 'not-allowed',
75
- opacity: 1
76
- },
77
74
  // 旋转动画样式
78
75
  '.pause-icon-ring': {
79
76
  transition: 'transform 0.1s ',
@@ -83,7 +80,13 @@ var genStyle = function genStyle(token) {
83
80
  animationTimingFunction: 'linear',
84
81
  animationIterationCount: 'infinite'
85
82
  }
86
- });
83
+ }), // 使用完整 modifier 类名,避免嵌套 `&&-disabled` 与 BEM 类名拼接不一致导致 cursor 等未生效
84
+ _define_property(_obj, "".concat(token.componentCls, "-disabled"), {
85
+ cursor: 'not-allowed',
86
+ // StopIcon 等仍读语义变量:用 antd token 随亮色/暗色一致
87
+ '--color-primary-control-fill-primary': token.colorTextQuaternary,
88
+ '--color-gray-bg-card-white': token.colorBgContainer
89
+ }), _obj;
87
90
  };
88
91
  /**
89
92
  * Probubble
@@ -254,7 +254,9 @@ var genStyle = function genStyle(token) {
254
254
  borderRadius: 0
255
255
  },
256
256
  '&-tools-wrapper': _define_property({
257
- height: '32px',
257
+ // 使用 minHeight,避免在 border-box 下固定 height 与 paddingBottom
258
+ // 争用导致内容区 < 32px、Toggle 工具与发送区纵向错位
259
+ minHeight: '32px',
258
260
  backgroundColor: 'var(--color-gray-bg-card-white, #ffffff)',
259
261
  display: 'flex',
260
262
  boxSizing: 'border-box',
@@ -102,8 +102,7 @@ var extractText = function extractText1(children) {
102
102
  ]);
103
103
  var doneChunkStyle = useMemo(function() {
104
104
  return {
105
- display: 'inline-block',
106
- color: 'inherit'
105
+ display: 'contents'
107
106
  };
108
107
  }, []);
109
108
  return animComplete ? /*#__PURE__*/ React.createElement("span", {
@@ -89,6 +89,9 @@ var DEFAULT_BACKGROUND_BATCH_MULTIPLIER = 10;
89
89
  {
90
90
  /** SSE token 到达时调用——接收完整的 content 字符串 */ key: "push",
91
91
  value: function push(content) {
92
+ if (content.length < this.displayedLength) {
93
+ this.displayedLength = 0;
94
+ }
92
95
  this.fullContent = content;
93
96
  if (!this.options.animate) {
94
97
  this.displayedLength = content.length;
@@ -283,10 +283,10 @@ var SCHEMA_LANGUAGES = new Set([
283
283
  useEffect(function() {
284
284
  if (!streaming) {
285
285
  var _queueRef_current;
286
- setDisplayedContent(content || '');
287
286
  (_queueRef_current = queueRef.current) === null || _queueRef_current === void 0 ? void 0 : _queueRef_current.dispose();
288
287
  queueRef.current = null;
289
288
  queueOptsSigRef.current = '';
289
+ setDisplayedContent(content || '');
290
290
  return;
291
291
  }
292
292
  var sig = JSON.stringify(resolvedQueueOptions !== null && resolvedQueueOptions !== void 0 ? resolvedQueueOptions : {});
@@ -299,17 +299,13 @@ var SCHEMA_LANGUAGES = new Set([
299
299
  queueOptsSigRef.current = sig;
300
300
  }
301
301
  queueRef.current.push(content || '');
302
- }, [
303
- content,
304
- streaming,
305
- resolvedQueueOptions
306
- ]);
307
- // 流式完成时 flush 所有剩余内容
308
- useEffect(function() {
309
- if (isFinished && queueRef.current) {
302
+ if (isFinished) {
310
303
  queueRef.current.complete();
311
304
  }
312
305
  }, [
306
+ content,
307
+ streaming,
308
+ resolvedQueueOptions,
313
309
  isFinished
314
310
  ]);
315
311
  // 清理
@@ -320,15 +316,6 @@ var SCHEMA_LANGUAGES = new Set([
320
316
  queueRef.current = null;
321
317
  };
322
318
  }, []);
323
- // 非流式内容变化时同步
324
- useEffect(function() {
325
- if (!streaming) {
326
- setDisplayedContent(content || '');
327
- }
328
- }, [
329
- content,
330
- streaming
331
- ]);
332
319
  useEffect(function() {
333
320
  var notify = fncProps === null || fncProps === void 0 ? void 0 : fncProps.onFootnoteDefinitionChange;
334
321
  if (!notify) return;
@@ -45,11 +45,12 @@ declare const buildEditorAlignedComponents: (prefixCls: string, userComponents:
45
45
  span: (props: any) => React.ReactElement<any, string | React.JSXElementConstructor<any>>;
46
46
  section: (props: any) => React.ReactElement<any, string | React.JSXElementConstructor<any>>;
47
47
  think: (props: any) => React.FunctionComponentElement<import("../ToolUseBarThink").ToolUseBarThinkProps>;
48
+ thinking: (props: any) => React.FunctionComponentElement<import("../ToolUseBarThink").ToolUseBarThinkProps>;
48
49
  answer: (props: any) => React.ReactElement<any, string | React.JSXElementConstructor<any>>;
49
50
  };
50
51
  /** markdown 片段 → React 元素 */
51
52
  declare const renderMarkdownBlock: (blockContent: string, processor: Processor, components: Record<string, any>) => React.ReactNode;
52
- /** 按双换行拆块,尊重代码围栏边界 */
53
+ /** 按单空行拆块,保留围栏代码块、列表、blockquote、HTML 注释+表格、脚注定义的连续性 */
53
54
  declare const splitMarkdownBlocks: (content: string) => string[];
54
55
  export interface UseMarkdownToReactOptions {
55
56
  remarkPlugins?: MarkdownRemarkPlugin[];
@@ -141,6 +141,7 @@ import { parseChineseCurrencyToNumber } from "../Plugins/chart/utils";
141
141
  import { ToolUseBarThink } from "../ToolUseBarThink";
142
142
  import AnimationText from "./AnimationText";
143
143
  import { FncRefForMarkdown, extractFootnoteRefFromSupChildren } from "./FncRefForMarkdown";
144
+ import { INITIAL_FENCE_STATE, updateFenceStateForLine } from "./streaming/fenceTracker";
144
145
  import { StreamingAnimationContext } from "./StreamingAnimationContext";
145
146
  var INLINE_MATH_WITH_SINGLE_DOLLAR = {
146
147
  singleDollarTextMath: true
@@ -402,19 +403,20 @@ var extractChildrenText = function extractChildrenText1(children) {
402
403
  }
403
404
  return '';
404
405
  };
406
+ var THINK_BLOCK_STYLES = {
407
+ root: {
408
+ boxSizing: 'border-box',
409
+ maxWidth: '680px',
410
+ marginTop: 8
411
+ }
412
+ };
405
413
  /** <think> 标签 → ToolUseBarThink(MarkdownRenderer 无 Slate 上下文,直接渲染) */ var ThinkBlockRendererComponent = function ThinkBlockRendererComponent(props) {
406
414
  var children = props.children;
407
415
  var content = extractChildrenText(children);
408
416
  var isLoading = content.endsWith('...');
409
417
  return React.createElement(ToolUseBarThink, {
410
418
  testId: 'think-block-renderer',
411
- styles: {
412
- root: {
413
- boxSizing: 'border-box',
414
- maxWidth: '680px',
415
- marginTop: 8
416
- }
417
- },
419
+ styles: THINK_BLOCK_STYLES,
418
420
  toolName: isLoading ? '深度思考...' : '深度思考',
419
421
  thinkContent: content,
420
422
  status: isLoading ? 'loading' : 'success'
@@ -1183,6 +1185,7 @@ var extractChildrenText = function extractChildrenText1(children) {
1183
1185
  }));
1184
1186
  },
1185
1187
  think: ThinkBlockRendererComponent,
1188
+ thinking: ThinkBlockRendererComponent,
1186
1189
  answer: function answer(props) {
1187
1190
  var _node = props.node, children = props.children;
1188
1191
  return jsx(Fragment, {
@@ -1207,29 +1210,61 @@ var extractChildrenText = function extractChildrenText1(children) {
1207
1210
  return null;
1208
1211
  }
1209
1212
  };
1210
- /** 按双换行拆块,尊重代码围栏边界 */ var splitMarkdownBlocks = function splitMarkdownBlocks(content) {
1213
+ var LIST_ITEM_PATTERN = /^(\s*)([-+*]|\d+[.)]) /;
1214
+ var BLOCKQUOTE_PATTERN = /^\s*>/;
1215
+ var HTML_COMMENT_PATTERN = /^\s*<!--/;
1216
+ var FOOTNOTE_DEF_PATTERN = /^\s*\[\^/;
1217
+ /** 按单空行拆块,保留围栏代码块、列表、blockquote、HTML 注释+表格、脚注定义的连续性 */ var splitMarkdownBlocks = function splitMarkdownBlocks(content) {
1211
1218
  var lines = content.split('\n');
1212
1219
  var blocks = [];
1213
1220
  var current = [];
1214
- var inFence = false;
1221
+ var fenceState = _object_spread({}, INITIAL_FENCE_STATE);
1222
+ var inList = false;
1223
+ var inBlockquote = false;
1224
+ var pendingBlankLines = 0;
1225
+ var lastNonEmptyLine = function lastNonEmptyLine() {
1226
+ for(var i = current.length - 1; i >= 0; i--){
1227
+ if (current[i] !== '') return current[i];
1228
+ }
1229
+ return '';
1230
+ };
1215
1231
  var _iteratorNormalCompletion = true, _didIteratorError = false, _iteratorError = undefined;
1216
1232
  try {
1217
1233
  for(var _iterator = lines[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true){
1218
1234
  var line = _step.value;
1219
- var trimmed = line.trimStart();
1220
- if (trimmed.startsWith('```') || trimmed.startsWith('~~~')) {
1221
- inFence = !inFence;
1235
+ fenceState = updateFenceStateForLine(fenceState, line);
1236
+ if (fenceState.inFenced) {
1237
+ if (pendingBlankLines > 0) {
1238
+ for(var i = 0; i < pendingBlankLines; i++)current.push('');
1239
+ pendingBlankLines = 0;
1240
+ }
1241
+ current.push(line);
1242
+ continue;
1222
1243
  }
1223
- if (!inFence && line === '' && current.length > 0) {
1224
- var prev = current[current.length - 1];
1225
- if (prev === '') {
1226
- // 触发分割的是「第二个连续空行」,不应并入上一块末尾,否则与单块解析结果字符串不一致、缓存失效
1227
- var withoutTrailingBlank = current.slice(0, -1);
1228
- blocks.push(withoutTrailingBlank.join('\n'));
1244
+ if (line === '') {
1245
+ if (current.length > 0) {
1246
+ pendingBlankLines++;
1247
+ }
1248
+ continue;
1249
+ }
1250
+ if (pendingBlankLines > 0) {
1251
+ var nextIsListItem = LIST_ITEM_PATTERN.test(line);
1252
+ var nextIsBlockquote = BLOCKQUOTE_PATTERN.test(line);
1253
+ var nextIsContinuation = inList && (nextIsListItem || /^\s+\S/.test(line)) || inBlockquote && nextIsBlockquote;
1254
+ var prevIsHtmlComment = HTML_COMMENT_PATTERN.test(lastNonEmptyLine());
1255
+ var nextIsFootnoteDef = FOOTNOTE_DEF_PATTERN.test(line);
1256
+ if (current.length > 0 && !nextIsContinuation && !prevIsHtmlComment && !nextIsFootnoteDef) {
1257
+ blocks.push(current.join('\n'));
1229
1258
  current = [];
1230
- continue;
1259
+ inList = false;
1260
+ inBlockquote = false;
1261
+ } else {
1262
+ for(var i1 = 0; i1 < pendingBlankLines; i1++)current.push('');
1231
1263
  }
1264
+ pendingBlankLines = 0;
1232
1265
  }
1266
+ inList = LIST_ITEM_PATTERN.test(line) || inList && /^\s+\S/.test(line);
1267
+ inBlockquote = BLOCKQUOTE_PATTERN.test(line);
1233
1268
  current.push(line);
1234
1269
  }
1235
1270
  } catch (err) {
@@ -1249,6 +1284,9 @@ var extractChildrenText = function extractChildrenText1(children) {
1249
1284
  if (current.length > 0) {
1250
1285
  blocks.push(current.join('\n'));
1251
1286
  }
1287
+ if (blocks.length === 0) {
1288
+ blocks.push('');
1289
+ }
1252
1290
  return blocks;
1253
1291
  };
1254
1292
  export { buildEditorAlignedComponents, createHastProcessor, renderMarkdownBlock, splitMarkdownBlocks };
@@ -23,28 +23,32 @@ import { shouldReparseLastBlock } from "./lastBlockThrottle";
23
23
  lastParsedRef.current = null;
24
24
  }
25
25
  var comps = componentsRef.current;
26
- var cached = cacheRef.current.get(blockSource);
27
- if (cached && variant === 'sealed') return cached;
28
- if (variant === 'sealed' || !streaming) {
26
+ if (variant === 'sealed') {
27
+ var cached = cacheRef.current.get(blockSource);
28
+ if (cached) return cached;
29
29
  var el = renderMarkdownBlock(blockSource, processor, comps);
30
30
  cacheRef.current.set(blockSource, el);
31
- if (variant === 'tail') lastParsedRef.current = {
31
+ return el;
32
+ }
33
+ // tail 块:不写入 cacheRef,仅用 lastParsedRef
34
+ if (!streaming) {
35
+ var el1 = renderMarkdownBlock(blockSource, processor, comps);
36
+ lastParsedRef.current = {
32
37
  source: blockSource,
33
- node: el
38
+ node: el1
34
39
  };
35
- return el;
40
+ return el1;
36
41
  }
37
42
  var prev = lastParsedRef.current;
38
43
  if (prev && !shouldReparseLastBlock(prev.source, blockSource, true)) {
39
44
  return prev.node;
40
45
  }
41
- var el1 = renderMarkdownBlock(blockSource, processor, comps);
42
- cacheRef.current.set(blockSource, el1);
46
+ var el2 = renderMarkdownBlock(blockSource, processor, comps);
43
47
  lastParsedRef.current = {
44
48
  source: blockSource,
45
- node: el1
49
+ node: el2
46
50
  };
47
- return el1;
51
+ return el2;
48
52
  }, [
49
53
  variant,
50
54
  blockSource,
@@ -0,0 +1,7 @@
1
+ export interface FenceState {
2
+ inFenced: boolean;
3
+ fenceChar: string;
4
+ fenceLen: number;
5
+ }
6
+ export declare const INITIAL_FENCE_STATE: FenceState;
7
+ export declare const updateFenceStateForLine: (state: FenceState, line: string) => FenceState;
@@ -0,0 +1,28 @@
1
+ export var INITIAL_FENCE_STATE = {
2
+ inFenced: false,
3
+ fenceChar: '',
4
+ fenceLen: 0
5
+ };
6
+ export var updateFenceStateForLine = function updateFenceStateForLine(state, line) {
7
+ var trimmed = line.trimStart();
8
+ var match = trimmed.match(/^(`{3,}|~{3,})(.*)$/);
9
+ if (!match) return state;
10
+ var char = match[1][0];
11
+ var len = match[1].length;
12
+ var after = match[2];
13
+ if (!state.inFenced) {
14
+ return {
15
+ inFenced: true,
16
+ fenceChar: char,
17
+ fenceLen: len
18
+ };
19
+ }
20
+ if (char === state.fenceChar && len >= state.fenceLen && /^\s*$/.test(after)) {
21
+ return {
22
+ inFenced: false,
23
+ fenceChar: '',
24
+ fenceLen: 0
25
+ };
26
+ }
27
+ return state;
28
+ };
@@ -1,5 +1,6 @@
1
1
  var LAST_BLOCK_THROTTLE_CHARS = 20;
2
- var BLOCK_BOUNDARY_TRIGGERS = /[\n`|#>*\-!$[\]]/;
2
+ var BLOCK_BOUNDARY_TRIGGERS = /[\n`|#>*\-!~]/;
3
+ var INLINE_CONTEXT_TRIGGERS = /(?:^|\s)[$[]/;
3
4
  /**
4
5
  * 流式末块:是否应重新 parse(相对上一次已 parse 的源)。
5
6
  */ export var shouldReparseLastBlock = function shouldReparseLastBlock(prevParsedSource, newSource, streaming) {
@@ -10,5 +11,6 @@ var BLOCK_BOUNDARY_TRIGGERS = /[\n`|#>*\-!$[\]]/;
10
11
  var added = newSource.slice(prevParsedSource.length);
11
12
  if (added.length >= LAST_BLOCK_THROTTLE_CHARS) return true;
12
13
  if (BLOCK_BOUNDARY_TRIGGERS.test(added)) return true;
14
+ if (INLINE_CONTEXT_TRIGGERS.test(added)) return true;
13
15
  return false;
14
16
  };
@@ -0,0 +1 @@
1
+ export declare const useShallowMemo: <T extends Record<string, any> | undefined>(value: T) => T;