@ant-design/agentic-ui 2.30.20 → 2.30.22

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 (66) hide show
  1. package/dist/Bubble/MessagesContent/MarkdownPreview.js +6 -5
  2. package/dist/Bubble/OpenAIMessageBubble/index.d.ts +11 -0
  3. package/dist/Bubble/OpenAIMessageBubble/index.js +8 -0
  4. package/dist/Bubble/OpenAIMessageBubble/mapOllamaMessages.d.ts +7 -0
  5. package/dist/Bubble/OpenAIMessageBubble/mapOllamaMessages.js +136 -0
  6. package/dist/Bubble/OpenAIMessageBubble/mapOpenAIMessages.d.ts +8 -0
  7. package/dist/Bubble/OpenAIMessageBubble/mapOpenAIMessages.js +156 -0
  8. package/dist/Bubble/OpenAIMessageBubble/mapOpenClawMessages.d.ts +8 -0
  9. package/dist/Bubble/OpenAIMessageBubble/mapOpenClawMessages.js +127 -0
  10. package/dist/Bubble/OpenAIMessageBubble/normalizeOllamaMessages.d.ts +16 -0
  11. package/dist/Bubble/OpenAIMessageBubble/normalizeOllamaMessages.js +110 -0
  12. package/dist/Bubble/OpenAIMessageBubble/normalizeOpenClawMessages.d.ts +10 -0
  13. package/dist/Bubble/OpenAIMessageBubble/normalizeOpenClawMessages.js +61 -0
  14. package/dist/Bubble/OpenAIMessageBubble/ollamaTypes.d.ts +48 -0
  15. package/dist/Bubble/OpenAIMessageBubble/ollamaTypes.js +1 -0
  16. package/dist/Bubble/OpenAIMessageBubble/openClawTypes.d.ts +27 -0
  17. package/dist/Bubble/OpenAIMessageBubble/openClawTypes.js +1 -0
  18. package/dist/Bubble/OpenAIMessageBubble/types.d.ts +71 -0
  19. package/dist/Bubble/OpenAIMessageBubble/types.js +1 -0
  20. package/dist/Bubble/OpenAIMessageBubble/useOllamaMessageBubbleData.d.ts +7 -0
  21. package/dist/Bubble/OpenAIMessageBubble/useOllamaMessageBubbleData.js +23 -0
  22. package/dist/Bubble/OpenAIMessageBubble/useOpenAIMessageBubbleData.d.ts +6 -0
  23. package/dist/Bubble/OpenAIMessageBubble/useOpenAIMessageBubbleData.js +20 -0
  24. package/dist/Bubble/OpenAIMessageBubble/useOpenClawMessageBubbleData.d.ts +7 -0
  25. package/dist/Bubble/OpenAIMessageBubble/useOpenClawMessageBubbleData.js +22 -0
  26. package/dist/Bubble/index.d.ts +2 -0
  27. package/dist/Bubble/index.js +1 -0
  28. package/dist/MarkdownEditor/editor/Editor.js +24 -12
  29. package/dist/MarkdownEditor/editor/elements/Table/SimpleTable.js +5 -1
  30. package/dist/MarkdownEditor/editor/elements/Table/commands/tableCommands.js +24 -8
  31. package/dist/MarkdownEditor/editor/elements/index.js +18 -14
  32. package/dist/MarkdownEditor/editor/plugins/useKeyboard.js +17 -5
  33. package/dist/MarkdownEditor/editor/store.d.ts +12 -0
  34. package/dist/MarkdownEditor/editor/store.js +30 -5
  35. package/dist/MarkdownEditor/editor/tools/InsertAutocomplete.js +15 -11
  36. package/dist/MarkdownInputField/AttachmentButton/AttachmentFileList/AttachmentFileListItem.d.ts +1 -1
  37. package/dist/MarkdownInputField/AttachmentButton/AttachmentFileList/AttachmentFileListItem.js +4 -5
  38. package/dist/MarkdownInputField/AttachmentButton/AttachmentFileList/index.d.ts +1 -1
  39. package/dist/MarkdownInputField/AttachmentButton/index.d.ts +1 -1
  40. package/dist/MarkdownInputField/MarkdownInputField.js +6 -1
  41. package/dist/MarkdownInputField/hooks/useMarkdownInputFieldHandlers.js +6 -2
  42. package/dist/MarkdownInputField/hooks/useMarkdownInputFieldRefs.d.ts +1 -0
  43. package/dist/MarkdownInputField/hooks/useMarkdownInputFieldRefs.js +36 -5
  44. package/dist/MarkdownInputField/utils/renderHelpers.js +5 -0
  45. package/dist/MarkdownRenderer/FncRefForMarkdown.d.ts +24 -0
  46. package/dist/MarkdownRenderer/FncRefForMarkdown.js +65 -0
  47. package/dist/MarkdownRenderer/MarkdownRenderer.js +24 -9
  48. package/dist/MarkdownRenderer/extractFootnoteDefinitions.d.ts +13 -0
  49. package/dist/MarkdownRenderer/extractFootnoteDefinitions.js +40 -0
  50. package/dist/MarkdownRenderer/markdownReactShared.d.ts +4 -1
  51. package/dist/MarkdownRenderer/markdownReactShared.js +20 -10
  52. package/dist/MarkdownRenderer/renderers/CodeRenderer.d.ts +4 -1
  53. package/dist/MarkdownRenderer/renderers/CodeRenderer.js +27 -3
  54. package/dist/MarkdownRenderer/renderers/SchemaRenderer.d.ts +2 -0
  55. package/dist/MarkdownRenderer/renderers/SchemaRenderer.js +33 -5
  56. package/dist/MarkdownRenderer/streaming/useStreamingMarkdownReact.js +2 -1
  57. package/dist/MarkdownRenderer/types.d.ts +5 -9
  58. package/dist/MarkdownRenderer/useMarkdownToReact.js +1 -1
  59. package/dist/Plugins/mermaid/MermaidRendererImpl.js +481 -7
  60. package/dist/Plugins/mermaid/style.js +71 -22
  61. package/dist/Plugins/mermaid/useMermaidRender.d.ts +2 -1
  62. package/dist/Plugins/mermaid/useMermaidRender.js +41 -13
  63. package/dist/Plugins/mermaid/utils.d.ts +16 -0
  64. package/dist/Plugins/mermaid/utils.js +197 -5
  65. package/dist/Workspace/Browser/index.js +19 -1
  66. package/package.json +8 -7
@@ -0,0 +1,61 @@
1
+ function _object_without_properties(source, excluded) {
2
+ if (source == null) return {};
3
+ var target = {}, sourceKeys, key, i;
4
+ if (typeof Reflect !== "undefined" && Reflect.ownKeys) {
5
+ sourceKeys = Reflect.ownKeys(source);
6
+ for(i = 0; i < sourceKeys.length; i++){
7
+ key = sourceKeys[i];
8
+ if (excluded.indexOf(key) >= 0) continue;
9
+ if (!Object.prototype.propertyIsEnumerable.call(source, key)) continue;
10
+ target[key] = source[key];
11
+ }
12
+ return target;
13
+ }
14
+ target = _object_without_properties_loose(source, excluded);
15
+ if (Object.getOwnPropertySymbols) {
16
+ sourceKeys = Object.getOwnPropertySymbols(source);
17
+ for(i = 0; i < sourceKeys.length; i++){
18
+ key = sourceKeys[i];
19
+ if (excluded.indexOf(key) >= 0) continue;
20
+ if (!Object.prototype.propertyIsEnumerable.call(source, key)) continue;
21
+ target[key] = source[key];
22
+ }
23
+ }
24
+ return target;
25
+ }
26
+ function _object_without_properties_loose(source, excluded) {
27
+ if (source == null) return {};
28
+ var target = {}, sourceKeys = Object.getOwnPropertyNames(source), key, i;
29
+ for(i = 0; i < sourceKeys.length; i++){
30
+ key = sourceKeys[i];
31
+ if (excluded.indexOf(key) >= 0) continue;
32
+ if (!Object.prototype.propertyIsEnumerable.call(source, key)) continue;
33
+ target[key] = source[key];
34
+ }
35
+ return target;
36
+ }
37
+ import { extractTextFromContent } from "./mapOpenAIMessages";
38
+ /**
39
+ * 将单条 OpenClaw 风格消息转为可与 {@link mapOpenAIMessagesToMessageBubbleData} 兼容的 OpenAI 形状(`toolResult` → `tool`)。
40
+ */ export function normalizeOpenClawMessageToOpenAI(msg) {
41
+ if (msg.role === 'toolResult') {
42
+ var m = msg;
43
+ var content = m.content === undefined || m.content === null ? '' : typeof m.content === 'string' ? m.content : extractTextFromContent(m.content);
44
+ return {
45
+ role: 'tool',
46
+ id: m.id,
47
+ name: m.name,
48
+ content: content,
49
+ tool_call_id: m.tool_call_id
50
+ };
51
+ }
52
+ var _ts = msg.timestamp, rest = _object_without_properties(msg, [
53
+ "timestamp"
54
+ ]);
55
+ return rest;
56
+ }
57
+ /**
58
+ * 批量将 OpenClaw transcript 消息转为 OpenAI Chat Completions 兼容结构
59
+ */ export function normalizeOpenClawMessagesToOpenAI(messages) {
60
+ return messages.map(normalizeOpenClawMessageToOpenAI);
61
+ }
@@ -0,0 +1,48 @@
1
+ import type { OpenAIMessagesMapOptions } from './types';
2
+ /**
3
+ * Ollama Chat API 中 ToolCall(见官方 OpenAPI `ToolCall`)
4
+ */
5
+ export interface OllamaToolCall {
6
+ function?: {
7
+ name: string;
8
+ description?: string;
9
+ arguments?: Record<string, unknown>;
10
+ };
11
+ /** 部分实现会带 id */
12
+ id?: string;
13
+ type?: string;
14
+ }
15
+ /**
16
+ * Ollama POST /api/chat 请求体中的单条 `messages[]`(见官方 `ChatMessage`)
17
+ */
18
+ export interface OllamaChatMessage {
19
+ role: 'system' | 'user' | 'assistant' | 'tool';
20
+ /** 流式片段可能为空字符串 */
21
+ content: string;
22
+ /** 客户端为稳定列表 key 可带 id */
23
+ id?: string;
24
+ /** 多模态:base64 图片列表 */
25
+ images?: string[];
26
+ /** assistant 上模型发起的工具调用 */
27
+ tool_calls?: OllamaToolCall[];
28
+ /** `think` 开启时的思考过程(流式或完整响应) */
29
+ thinking?: string;
30
+ /** `role: tool` 时常用,与 OpenAI 的 tool 名称对应 */
31
+ tool_name?: string;
32
+ tool_call_id?: string;
33
+ }
34
+ /** Ollama 映射选项 */
35
+ export interface OllamaMessagesMapOptions extends OpenAIMessagesMapOptions {
36
+ /**
37
+ * 为 true(默认)时,将 `thinking` 拼入展示用正文(映射后的 OpenAI assistant 文本)
38
+ */
39
+ appendThinkingToContent?: boolean;
40
+ /**
41
+ * 为 true(默认)时,若有 `images`,在正文中追加占位说明(不嵌入 base64)
42
+ */
43
+ appendImagesPlaceholder?: boolean;
44
+ /**
45
+ * 为 true(默认)时,在 `extra.ollama.raw` 保留原始 Ollama 消息
46
+ */
47
+ preserveOllamaRawInExtra?: boolean;
48
+ }
@@ -0,0 +1 @@
1
+ /** Ollama 映射选项 */ export { };
@@ -0,0 +1,27 @@
1
+ import type { OpenAIChatContentPart, OpenAIChatMessageAssistant, OpenAIChatMessageFunction, OpenAIChatMessageSystem, OpenAIChatMessageTool, OpenAIChatMessageUser, OpenAIMessagesMapOptions } from './types';
2
+ /**
3
+ * OpenClaw 会话 / transcript 常见字段:毫秒时间戳
4
+ */
5
+ export type OpenClawChatMeta = {
6
+ id?: string;
7
+ timestamp?: number;
8
+ name?: string;
9
+ };
10
+ /** OpenClaw transcript 中工具结果常用 `toolResult`,与 OpenAI 的 `tool` 对应 */
11
+ export interface OpenClawChatMessageToolResult extends OpenClawChatMeta {
12
+ role: 'toolResult';
13
+ content: string | OpenAIChatContentPart[] | null;
14
+ tool_call_id?: string;
15
+ }
16
+ export type OpenClawChatMessage = (OpenAIChatMessageSystem & OpenClawChatMeta) | (OpenAIChatMessageUser & OpenClawChatMeta) | (OpenAIChatMessageAssistant & OpenClawChatMeta) | (OpenAIChatMessageTool & OpenClawChatMeta) | (OpenAIChatMessageFunction & OpenClawChatMeta) | OpenClawChatMessageToolResult;
17
+ /** OpenClaw 映射选项(在 OpenAI 选项基础上增加 transcript 行为) */
18
+ export interface OpenClawMessagesMapOptions extends OpenAIMessagesMapOptions {
19
+ /**
20
+ * 为 true(默认)时,若消息含 `timestamp`(毫秒),写入 `createAt` / `updateAt`
21
+ */
22
+ useOpenClawTimestamps?: boolean;
23
+ /**
24
+ * 为 true(默认)时,在 `extra.openclaw.raw` 保留原始 OpenClaw 消息
25
+ */
26
+ preserveOpenClawRawInExtra?: boolean;
27
+ }
@@ -0,0 +1 @@
1
+ /** OpenClaw 映射选项(在 OpenAI 选项基础上增加 transcript 行为) */ export { };
@@ -0,0 +1,71 @@
1
+ import type { MessageBubbleData } from '../../Types/message';
2
+ import type { RoleType } from '../../Types/common';
3
+ /**
4
+ * OpenAI Chat Completions 风格的多段 content(与官方结构兼容,库内自建)
5
+ */
6
+ export interface OpenAIChatTextPart {
7
+ type: 'text';
8
+ text: string;
9
+ }
10
+ export interface OpenAIChatRefusalPart {
11
+ type?: 'refusal';
12
+ refusal?: string;
13
+ }
14
+ /** 多模态等其它 part 以弱类型保留 */
15
+ export interface OpenAIChatContentPartFallback {
16
+ type: string;
17
+ [key: string]: unknown;
18
+ }
19
+ export type OpenAIChatContentPart = OpenAIChatTextPart | OpenAIChatRefusalPart | OpenAIChatContentPartFallback;
20
+ export interface OpenAIChatMessageBase {
21
+ id?: string;
22
+ name?: string;
23
+ tool_calls?: unknown[];
24
+ function_call?: {
25
+ name?: string;
26
+ arguments?: string;
27
+ } | null;
28
+ }
29
+ export interface OpenAIChatMessageSystem extends OpenAIChatMessageBase {
30
+ role: 'system';
31
+ content: string | null;
32
+ }
33
+ export interface OpenAIChatMessageUser extends OpenAIChatMessageBase {
34
+ role: 'user';
35
+ content: string | OpenAIChatContentPart[] | null;
36
+ }
37
+ export interface OpenAIChatMessageAssistant extends OpenAIChatMessageBase {
38
+ role: 'assistant';
39
+ content: string | OpenAIChatContentPart[] | null;
40
+ tool_calls?: unknown[];
41
+ function_call?: OpenAIChatMessageBase['function_call'];
42
+ }
43
+ export interface OpenAIChatMessageTool extends OpenAIChatMessageBase {
44
+ role: 'tool';
45
+ content: string | null;
46
+ tool_call_id?: string;
47
+ }
48
+ export interface OpenAIChatMessageFunction extends OpenAIChatMessageBase {
49
+ role: 'function';
50
+ content: string | null;
51
+ name?: string;
52
+ }
53
+ export type OpenAIChatMessage = OpenAIChatMessageSystem | OpenAIChatMessageUser | OpenAIChatMessageAssistant | OpenAIChatMessageTool | OpenAIChatMessageFunction;
54
+ /** 单条映射覆盖 */
55
+ export type OpenAIMessagesMapMessage = (msg: OpenAIChatMessage, index: number, draft: MessageBubbleData) => MessageBubbleData;
56
+ export interface OpenAIMessagesMapOptions {
57
+ /** createAt / updateAt 基准(毫秒) */
58
+ baseTime?: number;
59
+ /** 第 i 条:createAt = baseTime + i * timeStepMs */
60
+ timeStepMs?: number;
61
+ /** 为 true 时最后一条的 updateAt 使用 Date.now()(流式可选) */
62
+ bumpUpdateAtOnLastMessage?: boolean;
63
+ /** 生成 MessageBubbleData.id,默认不用 content,避免 SSE 抖动 */
64
+ getMessageId?: (msg: OpenAIChatMessage, index: number) => string;
65
+ /** tool / function 行映射到的 RoleType */
66
+ toolRoleAs?: RoleType;
67
+ /** assistant 是否将 tool_calls 等拼入展示文案 */
68
+ appendToolCallsToContent?: boolean;
69
+ /** 在 extra.openai 中保留原始 role 与 raw */
70
+ preserveRawInExtra?: boolean;
71
+ }
@@ -0,0 +1 @@
1
+ export { };
@@ -0,0 +1,7 @@
1
+ import type { MessageBubbleData } from '../../Types/message';
2
+ import type { OpenAIMessagesMapMessage } from './types';
3
+ import type { OllamaChatMessage, OllamaMessagesMapOptions } from './ollamaTypes';
4
+ /**
5
+ * 将 Ollama `/api/chat` 的 messages 转为 MessageBubbleData[](与 {@link mapOllamaMessagesToMessageBubbleData} 一致,带 memo)。
6
+ */
7
+ export declare function useOllamaMessageBubbleData(messages: OllamaChatMessage[], mapOptions?: OllamaMessagesMapOptions, mapMessage?: OpenAIMessagesMapMessage): MessageBubbleData[];
@@ -0,0 +1,23 @@
1
+ import { useMemo } from "react";
2
+ import { mapOllamaMessagesToMessageBubbleData } from "./mapOllamaMessages";
3
+ /**
4
+ * 将 Ollama `/api/chat` 的 messages 转为 MessageBubbleData[](与 {@link mapOllamaMessagesToMessageBubbleData} 一致,带 memo)。
5
+ */ export function useOllamaMessageBubbleData(messages, mapOptions, mapMessage) {
6
+ var _ref = mapOptions !== null && mapOptions !== void 0 ? mapOptions : {}, baseTime = _ref.baseTime, timeStepMs = _ref.timeStepMs, bumpUpdateAtOnLastMessage = _ref.bumpUpdateAtOnLastMessage, getMessageId = _ref.getMessageId, toolRoleAs = _ref.toolRoleAs, appendToolCallsToContent = _ref.appendToolCallsToContent, preserveRawInExtra = _ref.preserveRawInExtra, appendThinkingToContent = _ref.appendThinkingToContent, appendImagesPlaceholder = _ref.appendImagesPlaceholder, preserveOllamaRawInExtra = _ref.preserveOllamaRawInExtra;
7
+ return useMemo(function() {
8
+ return mapOllamaMessagesToMessageBubbleData(messages, mapOptions, mapMessage);
9
+ }, [
10
+ messages,
11
+ baseTime,
12
+ timeStepMs,
13
+ bumpUpdateAtOnLastMessage,
14
+ getMessageId,
15
+ toolRoleAs,
16
+ appendToolCallsToContent,
17
+ preserveRawInExtra,
18
+ appendThinkingToContent,
19
+ appendImagesPlaceholder,
20
+ preserveOllamaRawInExtra,
21
+ mapMessage
22
+ ]);
23
+ }
@@ -0,0 +1,6 @@
1
+ import type { MessageBubbleData } from '../../Types/message';
2
+ import type { OpenAIChatMessage, OpenAIMessagesMapMessage, OpenAIMessagesMapOptions } from './types';
3
+ /**
4
+ * 将 OpenAI Chat Completions 风格的 messages 转为 MessageBubbleData[](与 {@link mapOpenAIMessagesToMessageBubbleData} 一致,带 memo)。
5
+ */
6
+ export declare function useOpenAIMessageBubbleData(messages: OpenAIChatMessage[], mapOptions?: OpenAIMessagesMapOptions, mapMessage?: OpenAIMessagesMapMessage): MessageBubbleData[];
@@ -0,0 +1,20 @@
1
+ import { useMemo } from "react";
2
+ import { mapOpenAIMessagesToMessageBubbleData } from "./mapOpenAIMessages";
3
+ /**
4
+ * 将 OpenAI Chat Completions 风格的 messages 转为 MessageBubbleData[](与 {@link mapOpenAIMessagesToMessageBubbleData} 一致,带 memo)。
5
+ */ export function useOpenAIMessageBubbleData(messages, mapOptions, mapMessage) {
6
+ var _ref = mapOptions !== null && mapOptions !== void 0 ? mapOptions : {}, baseTime = _ref.baseTime, timeStepMs = _ref.timeStepMs, bumpUpdateAtOnLastMessage = _ref.bumpUpdateAtOnLastMessage, getMessageId = _ref.getMessageId, toolRoleAs = _ref.toolRoleAs, appendToolCallsToContent = _ref.appendToolCallsToContent, preserveRawInExtra = _ref.preserveRawInExtra;
7
+ return useMemo(function() {
8
+ return mapOpenAIMessagesToMessageBubbleData(messages, mapOptions, mapMessage);
9
+ }, [
10
+ messages,
11
+ baseTime,
12
+ timeStepMs,
13
+ bumpUpdateAtOnLastMessage,
14
+ getMessageId,
15
+ toolRoleAs,
16
+ appendToolCallsToContent,
17
+ preserveRawInExtra,
18
+ mapMessage
19
+ ]);
20
+ }
@@ -0,0 +1,7 @@
1
+ import type { MessageBubbleData } from '../../Types/message';
2
+ import type { OpenAIMessagesMapMessage } from './types';
3
+ import type { OpenClawChatMessage, OpenClawMessagesMapOptions } from './openClawTypes';
4
+ /**
5
+ * 将 OpenClaw 会话 / transcript 风格的 messages 转为 MessageBubbleData[](与 {@link mapOpenClawMessagesToMessageBubbleData} 一致,带 memo)。
6
+ */
7
+ export declare function useOpenClawMessageBubbleData(messages: OpenClawChatMessage[], mapOptions?: OpenClawMessagesMapOptions, mapMessage?: OpenAIMessagesMapMessage): MessageBubbleData[];
@@ -0,0 +1,22 @@
1
+ import { useMemo } from "react";
2
+ import { mapOpenClawMessagesToMessageBubbleData } from "./mapOpenClawMessages";
3
+ /**
4
+ * 将 OpenClaw 会话 / transcript 风格的 messages 转为 MessageBubbleData[](与 {@link mapOpenClawMessagesToMessageBubbleData} 一致,带 memo)。
5
+ */ export function useOpenClawMessageBubbleData(messages, mapOptions, mapMessage) {
6
+ var _ref = mapOptions !== null && mapOptions !== void 0 ? mapOptions : {}, baseTime = _ref.baseTime, timeStepMs = _ref.timeStepMs, bumpUpdateAtOnLastMessage = _ref.bumpUpdateAtOnLastMessage, getMessageId = _ref.getMessageId, toolRoleAs = _ref.toolRoleAs, appendToolCallsToContent = _ref.appendToolCallsToContent, preserveRawInExtra = _ref.preserveRawInExtra, useOpenClawTimestamps = _ref.useOpenClawTimestamps, preserveOpenClawRawInExtra = _ref.preserveOpenClawRawInExtra;
7
+ return useMemo(function() {
8
+ return mapOpenClawMessagesToMessageBubbleData(messages, mapOptions, mapMessage);
9
+ }, [
10
+ messages,
11
+ baseTime,
12
+ timeStepMs,
13
+ bumpUpdateAtOnLastMessage,
14
+ getMessageId,
15
+ toolRoleAs,
16
+ appendToolCallsToContent,
17
+ preserveRawInExtra,
18
+ useOpenClawTimestamps,
19
+ preserveOpenClawRawInExtra,
20
+ mapMessage
21
+ ]);
22
+ }
@@ -14,3 +14,5 @@ export * from './type';
14
14
  export { UserBubble } from './UserBubble';
15
15
  /** Schema Editor 相关导出 */
16
16
  export * from './schema-editor';
17
+ /** OpenAI Chat messages → MessageBubbleData */
18
+ export * from './OpenAIMessageBubble';
@@ -12,3 +12,4 @@ export * from "./MessagesContent/BubbleContext";
12
12
  export * from "./type";
13
13
  export { UserBubble } from "./UserBubble";
14
14
  /** Schema Editor 相关导出 */ export * from "./schema-editor";
15
+ /** OpenAI Chat messages → MessageBubbleData */ export * from "./OpenAIMessageBubble";
@@ -633,10 +633,14 @@ var defaultAllowedTypes = [
633
633
  // 2. 检查目标元素是否可编辑,如果不可编辑,则从DOM选区中获取编辑器选区
634
634
  if (operationType === 'copy' && !hasEditableTarget(markdownEditorRef.current, event.target)) {
635
635
  var domSelection = window.getSelection();
636
- markdownEditorRef.current.selection = getSelectionFromDomSelection(markdownEditorRef.current, domSelection);
636
+ if (domSelection) {
637
+ markdownEditorRef.current.selection = getSelectionFromDomSelection(markdownEditorRef.current, domSelection);
638
+ }
637
639
  } else if (operationType === 'cut') {
638
640
  var domSelection1 = window.getSelection();
639
- markdownEditorRef.current.selection = getSelectionFromDomSelection(markdownEditorRef.current, domSelection1);
641
+ if (domSelection1) {
642
+ markdownEditorRef.current.selection = getSelectionFromDomSelection(markdownEditorRef.current, domSelection1);
643
+ }
640
644
  }
641
645
  // 如果无法获取选区,则直接返回
642
646
  if (!markdownEditorRef.current.selection) {
@@ -970,12 +974,16 @@ var defaultAllowedTypes = [
970
974
  var _markdownEditorRef_current_selection1;
971
975
  var node = Node.get(markdownEditorRef.current, ((_markdownEditorRef_current_selection1 = markdownEditorRef.current.selection) === null || _markdownEditorRef_current_selection1 === void 0 ? void 0 : _markdownEditorRef_current_selection1.focus.path) || []);
972
976
  if (node) {
973
- var dom = ReactEditor.toDOMNode(markdownEditorRef.current, node);
974
- if (dom) {
975
- var tagInput = dom.querySelector('[data-tag-popup-input]');
976
- if (tagInput) {
977
- tagInput.setAttribute('data-composition', '');
977
+ try {
978
+ var dom = ReactEditor.toDOMNode(markdownEditorRef.current, node);
979
+ if (dom) {
980
+ var tagInput = dom.querySelector('[data-tag-popup-input]');
981
+ if (tagInput) {
982
+ tagInput.setAttribute('data-composition', '');
983
+ }
978
984
  }
985
+ } catch (unused) {
986
+ // node may not be mounted yet; ignore
979
987
  }
980
988
  }
981
989
  }
@@ -1003,12 +1011,16 @@ var defaultAllowedTypes = [
1003
1011
  var _markdownEditorRef_current_selection1;
1004
1012
  var node = Node.get(markdownEditorRef.current, ((_markdownEditorRef_current_selection1 = markdownEditorRef.current.selection) === null || _markdownEditorRef_current_selection1 === void 0 ? void 0 : _markdownEditorRef_current_selection1.focus.path) || []);
1005
1013
  if (node) {
1006
- var dom = ReactEditor.toDOMNode(markdownEditorRef.current, node);
1007
- if (dom) {
1008
- var tagInput = dom.querySelector('[data-tag-popup-input]');
1009
- if (tagInput) {
1010
- tagInput.removeAttribute('data-composition');
1014
+ try {
1015
+ var dom = ReactEditor.toDOMNode(markdownEditorRef.current, node);
1016
+ if (dom) {
1017
+ var tagInput = dom.querySelector('[data-tag-popup-input]');
1018
+ if (tagInput) {
1019
+ tagInput.removeAttribute('data-composition');
1020
+ }
1011
1021
  }
1022
+ } catch (unused) {
1023
+ // node may have been unmounted during composition; ignore
1012
1024
  }
1013
1025
  }
1014
1026
  }
@@ -64,7 +64,11 @@ import { TablePropsProvider } from "./TableContext";
64
64
  var baseCls = getPrefixCls('agentic-md-editor-content-table');
65
65
  var editor = useSlate();
66
66
  var tablePath = useMemo(function() {
67
- return ReactEditor.findPath(editor, props.element);
67
+ try {
68
+ return ReactEditor.findPath(editor, props.element);
69
+ } catch (unused) {
70
+ return [];
71
+ }
68
72
  }, [
69
73
  props.element
70
74
  ]);
@@ -114,8 +114,12 @@ function forEachCellPath(editor, tablePath, callback) {
114
114
  }
115
115
  export function clearTableSelection(editor, tablePath) {
116
116
  forEachCellPath(editor, tablePath, function(_, cellNode) {
117
- var domNode = ReactEditor.toDOMNode(editor, cellNode);
118
- domNode === null || domNode === void 0 ? void 0 : domNode.removeAttribute('data-select');
117
+ try {
118
+ var domNode = ReactEditor.toDOMNode(editor, cellNode);
119
+ domNode === null || domNode === void 0 ? void 0 : domNode.removeAttribute('data-select');
120
+ } catch (unused) {
121
+ // cell may not be mounted yet
122
+ }
119
123
  });
120
124
  }
121
125
  export function selectTableRow(editor, tablePath, rowIndex) {
@@ -137,8 +141,12 @@ export function selectTableRow(editor, tablePath, rowIndex) {
137
141
  if (tableCellNode.type !== 'table-cell') {
138
142
  continue;
139
143
  }
140
- var domNode = ReactEditor.toDOMNode(editor, tableCellNode);
141
- domNode === null || domNode === void 0 ? void 0 : domNode.setAttribute('data-select', 'true');
144
+ try {
145
+ var domNode = ReactEditor.toDOMNode(editor, tableCellNode);
146
+ domNode === null || domNode === void 0 ? void 0 : domNode.setAttribute('data-select', 'true');
147
+ } catch (unused) {
148
+ // cell may not be mounted yet
149
+ }
142
150
  }
143
151
  }
144
152
  export function selectTableColumn(editor, tablePath, columnIndex) {
@@ -158,14 +166,22 @@ export function selectTableColumn(editor, tablePath, columnIndex) {
158
166
  if (tableCellNode.type !== 'table-cell') {
159
167
  continue;
160
168
  }
161
- var domNode = ReactEditor.toDOMNode(editor, tableCellNode);
162
- domNode === null || domNode === void 0 ? void 0 : domNode.setAttribute('data-select', 'true');
169
+ try {
170
+ var domNode = ReactEditor.toDOMNode(editor, tableCellNode);
171
+ domNode === null || domNode === void 0 ? void 0 : domNode.setAttribute('data-select', 'true');
172
+ } catch (unused) {
173
+ // cell may not be mounted yet
174
+ }
163
175
  }
164
176
  }
165
177
  export function selectWholeTable(editor, tablePath) {
166
178
  forEachCellPath(editor, tablePath, function(_, cellNode) {
167
- var domNode = ReactEditor.toDOMNode(editor, cellNode);
168
- domNode === null || domNode === void 0 ? void 0 : domNode.setAttribute('data-select', 'true');
179
+ try {
180
+ var domNode = ReactEditor.toDOMNode(editor, cellNode);
181
+ domNode === null || domNode === void 0 ? void 0 : domNode.setAttribute('data-select', 'true');
182
+ } catch (unused) {
183
+ // cell may not be mounted yet
184
+ }
169
185
  });
170
186
  }
171
187
  export function removeTableRow(editor, tablePath, rowIndex) {
@@ -387,20 +387,24 @@ var MLeafComponent = function MLeafComponent(props) {
387
387
  setTimeout(function() {
388
388
  if (!markdownEditorRef.current) return;
389
389
  if (!(path === null || path === void 0 ? void 0 : path.length)) return;
390
- var nextPath = Path.next(path);
391
- if (!Editor.hasPath(markdownEditorRef.current, nextPath)) {
392
- Transforms.insertNodes(markdownEditorRef.current, [
393
- {
394
- text: ' '
395
- }
396
- ], {
397
- select: true
398
- });
399
- } else {
400
- Transforms.select(markdownEditorRef.current, {
401
- anchor: Editor.end(markdownEditorRef.current, path),
402
- focus: Editor.end(markdownEditorRef.current, path)
403
- });
390
+ try {
391
+ var nextPath = Path.next(path);
392
+ if (!Editor.hasPath(markdownEditorRef.current, nextPath)) {
393
+ Transforms.insertNodes(markdownEditorRef.current, [
394
+ {
395
+ text: ' '
396
+ }
397
+ ], {
398
+ select: true
399
+ });
400
+ } else {
401
+ Transforms.select(markdownEditorRef.current, {
402
+ anchor: Editor.end(markdownEditorRef.current, path),
403
+ focus: Editor.end(markdownEditorRef.current, path)
404
+ });
405
+ }
406
+ } catch (unused) {
407
+ // path may have become stale after the timeout; ignore
404
408
  }
405
409
  }, 0);
406
410
  },
@@ -58,6 +58,19 @@ import { MatchKey } from "./hotKeyCommands/match";
58
58
  import { TabKey } from "./hotKeyCommands/tab";
59
59
  import { NativeTableKeyboard } from "../../utils/native-table";
60
60
  import { useEditorStore } from "../store";
61
+ // Block types where plain Enter must be handled by EnterKey (not Slate's default insertBreak
62
+ // and not the outer MarkdownInputField send handler). These are blocks where entering would
63
+ // incorrectly split the node into two nodes with Slate's default behavior.
64
+ var SPECIAL_ENTER_BLOCK_TYPES = new Set([
65
+ 'list-item',
66
+ 'code',
67
+ 'table-cell',
68
+ 'head',
69
+ 'blockquote',
70
+ 'card-before',
71
+ 'card-after',
72
+ 'break'
73
+ ]);
61
74
  /**
62
75
  * 键盘事件处理 Hook - 管理 Markdown 编辑器的所有键盘交互
63
76
  *
@@ -215,27 +228,26 @@ import { useEditorStore } from "../store";
215
228
  enter.run(e);
216
229
  return;
217
230
  }
218
- // Enter 键(无 Shift)处理:如果在列表项中,让 EnterKey 处理;否则由 MarkdownInputField 处理发送
231
+ // Enter 键(无 Shift)处理:如果在特殊块类型中(列表项、代码块等),让 EnterKey 处理;否则由 MarkdownInputField 处理发送
219
232
  if (e.key === 'Enter' && !(e.ctrlKey || e.metaKey) && !e.shiftKey) {
220
- // 检查当前是否在列表项中
221
233
  var selection1 = markdownEditorRef.current.selection;
222
234
  if (selection1 && Range.isCollapsed(selection1)) {
223
235
  var _Editor_nodes1 = _sliced_to_array(Editor.nodes(markdownEditorRef.current, {
224
236
  at: selection1.focus.path,
225
237
  match: function match(n) {
226
- return Element.isElement(n) && n.type === 'list-item';
238
+ return Element.isElement(n) && SPECIAL_ENTER_BLOCK_TYPES.has(n.type);
227
239
  },
228
240
  mode: 'lowest'
229
241
  }), 1), node1 = _Editor_nodes1[0];
230
242
  if (node1) {
231
- // 在列表项中,让 EnterKey 处理
243
+ // 在特殊块中,让 EnterKey 处理(如代码块插入换行、列表项创建新列表等)
232
244
  e.stopPropagation();
233
245
  e.preventDefault();
234
246
  enter.run(e);
235
247
  return;
236
248
  }
237
249
  }
238
- // 不在列表项中,让 MarkdownInputField 处理发送
250
+ // 不在特殊块中,让 MarkdownInputField 处理发送
239
251
  return;
240
252
  }
241
253
  var _Editor_nodes2 = _sliced_to_array(Editor.nodes(markdownEditorRef.current, {
@@ -203,6 +203,18 @@ export declare class EditorStore {
203
203
  * 取消当前正在进行的 setMDContent 操作
204
204
  */
205
205
  cancelSetMDContent(): void;
206
+ /**
207
+ * 安全地取消编辑器选区。
208
+ *
209
+ * ReactEditor.deselect() 内部调用 window.getSelection().removeAllRanges(),
210
+ * 当编辑器处于聚焦状态时,浏览器要求必须存在活跃选区才能操作,
211
+ * 否则抛出 InvalidStateError("Failed to execute 'collapseToEnd' on 'Selection'")。
212
+ *
213
+ * 双重防御策略:
214
+ * 1. isFocused 检查 —— 大多数情况下直接跳过(性能优先)
215
+ * 2. try-catch —— 覆盖 isFocused 与 deselect 之间的竞态窗口
216
+ */
217
+ private _safeDeselect;
206
218
  /**
207
219
  * 使用 requestAnimationFrame 分批解析和设置内容
208
220
  * 边解析边插入,实时显示内容
@@ -237,9 +237,13 @@ export var EditorStoreContext = createContext(null);
237
237
  value: function focus() {
238
238
  var editor = this._editor.current;
239
239
  try {
240
- // 1. 确保编辑器获得焦点
240
+ // 1. 确保编辑器获得焦点(异步,需要单独 try-catch 防止白屏)
241
241
  setTimeout(function() {
242
- return ReactEditor.focus(editor);
242
+ try {
243
+ ReactEditor.focus(editor);
244
+ } catch (e) {
245
+ console.error('ReactEditor.focus 失败:', e);
246
+ }
243
247
  }, 0);
244
248
  // 2. 处理空文档情况
245
249
  if (editor.children.length === 0) {
@@ -476,7 +480,7 @@ export var EditorStoreContext = createContext(null);
476
480
  var nodeList = parserMdToSchema(md, plugins).schema;
477
481
  this.setContent(nodeList);
478
482
  this._editor.current.children = nodeList;
479
- ReactEditor.deselect(this._editor.current);
483
+ this._safeDeselect();
480
484
  onProgress === null || onProgress === void 0 ? void 0 : onProgress(1);
481
485
  } catch (error) {
482
486
  console.error('Failed to set MD content:', error);
@@ -494,7 +498,7 @@ export var EditorStoreContext = createContext(null);
494
498
  if (allNodes.length > 0) {
495
499
  this.setContent(allNodes);
496
500
  this._editor.current.children = allNodes;
497
- ReactEditor.deselect(this._editor.current);
501
+ this._safeDeselect();
498
502
  }
499
503
  onProgress === null || onProgress === void 0 ? void 0 : onProgress(1);
500
504
  } catch (error) {
@@ -547,6 +551,27 @@ export var EditorStoreContext = createContext(null);
547
551
  }
548
552
  }
549
553
  },
554
+ {
555
+ key: "_safeDeselect",
556
+ value: /**
557
+ * 安全地取消编辑器选区。
558
+ *
559
+ * ReactEditor.deselect() 内部调用 window.getSelection().removeAllRanges(),
560
+ * 当编辑器处于聚焦状态时,浏览器要求必须存在活跃选区才能操作,
561
+ * 否则抛出 InvalidStateError("Failed to execute 'collapseToEnd' on 'Selection'")。
562
+ *
563
+ * 双重防御策略:
564
+ * 1. isFocused 检查 —— 大多数情况下直接跳过(性能优先)
565
+ * 2. try-catch —— 覆盖 isFocused 与 deselect 之间的竞态窗口
566
+ */ function _safeDeselect() {
567
+ if (ReactEditor.isFocused(this._editor.current)) return;
568
+ try {
569
+ ReactEditor.deselect(this._editor.current);
570
+ } catch (unused) {
571
+ // InvalidStateError:编辑器在 isFocused 检查与 deselect 调用之间获得了焦点,忽略即可
572
+ }
573
+ }
574
+ },
550
575
  {
551
576
  key: "_parseAndSetContentWithRAF",
552
577
  value: /**
@@ -634,7 +659,7 @@ export var EditorStoreContext = createContext(null);
634
659
  rafId = requestAnimationFrame(parseAndInsertNextBatch);
635
660
  } else {
636
661
  // 所有内容处理完成
637
- ReactEditor.deselect(_this._editor.current);
662
+ _this._safeDeselect();
638
663
  rafId = null;
639
664
  _this._currentAbortController = null;
640
665
  resolve();