@blueking/chat-x 0.0.45-beta.7 → 0.0.45-beta.8

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 (138) hide show
  1. package/README.md +1 -1
  2. package/dist/ag-ui/types/constants.d.ts +16 -0
  3. package/dist/ag-ui/types/contents.d.ts +2 -0
  4. package/dist/ag-ui/types/index.d.ts +2 -0
  5. package/dist/ag-ui/types/interrupt.d.ts +152 -0
  6. package/dist/ag-ui/types/messages.d.ts +2 -0
  7. package/dist/ag-ui/types/schema.d.ts +42 -0
  8. package/dist/components/ai-questions/questions-container.vue.d.ts +3 -0
  9. package/dist/components/ai-questions/selection-question.vue.d.ts +3 -0
  10. package/dist/components/chat-content/flow-agent-content/flow-agent-content.vue.d.ts +3 -0
  11. package/dist/components/chat-content/flow-agent-content/use-flow-agent.d.ts +4 -0
  12. package/dist/components/chat-content/flow-agent-content/use-flow-node-actions.d.ts +32 -0
  13. package/dist/components/chat-content/index.d.ts +2 -0
  14. package/dist/components/chat-input/ai-slash-input/command.d.ts +1 -2
  15. package/dist/components/chat-input/ai-slash-input/constants.d.ts +0 -4
  16. package/dist/components/chat-input/chat-input.vue.d.ts +14 -8
  17. package/dist/components/chat-input/input-attachment/input-attachment.vue.d.ts +1 -0
  18. package/dist/components/chat-input/input-info-alert.vue.d.ts +6 -0
  19. package/dist/components/chat-message/activity-message/activity-message.vue.d.ts +4 -1
  20. package/dist/components/chat-message/assistant-message/assistant-message.vue.d.ts +1 -1
  21. package/dist/components/chat-message/interrupt-message/index.d.ts +2 -0
  22. package/dist/components/chat-message/interrupt-message/interrupt-message.vue.d.ts +17 -0
  23. package/dist/components/chat-message/interrupt-message/tool-approval-card.vue.d.ts +9 -0
  24. package/dist/components/chat-message/interrupt-message/user-question/index.d.ts +5 -0
  25. package/dist/components/chat-message/interrupt-message/user-question/use-user-question.d.ts +35 -0
  26. package/dist/components/chat-message/interrupt-message/user-question/user-question-answered-card.vue.d.ts +25 -0
  27. package/dist/components/chat-message/interrupt-message/user-question/user-question-card.vue.d.ts +25 -0
  28. package/dist/components/chat-message/interrupt-message/user-question/user-question-choice.vue.d.ts +13 -0
  29. package/dist/components/chat-message/interrupt-message/user-question/user-question-option.vue.d.ts +17 -0
  30. package/dist/components/chat-message/message-container/message-container.vue.d.ts +14 -7
  31. package/dist/components/chat-message/message-render/message-render.vue.d.ts +4 -0
  32. package/dist/components/index.d.ts +3 -2
  33. package/dist/composables/use-global-config.d.ts +3 -0
  34. package/dist/composables/use-message-group.d.ts +2224 -355
  35. package/dist/icons/index.d.ts +1 -0
  36. package/dist/icons/interrupt.d.ts +24 -0
  37. package/dist/index.css +1 -1
  38. package/dist/index.js +2557 -1937
  39. package/dist/index.js.map +1 -1
  40. package/dist/lang/lang.d.ts +34 -2
  41. package/dist/mcp/generated/docs/activity-layout.md +138 -0
  42. package/dist/mcp/generated/docs/activity-message.md +21 -7
  43. package/dist/mcp/generated/docs/ai-image.md +9 -4
  44. package/dist/mcp/generated/docs/ai-loading.md +11 -6
  45. package/dist/mcp/generated/docs/ai-prompt-list.md +42 -0
  46. package/dist/mcp/generated/docs/ai-selection.md +10 -5
  47. package/dist/mcp/generated/docs/ai-slash-editor.md +43 -0
  48. package/dist/mcp/generated/docs/ai-slash-input.md +43 -0
  49. package/dist/mcp/generated/docs/ai-slash-menu.md +42 -0
  50. package/dist/mcp/generated/docs/animation-text.md +9 -4
  51. package/dist/mcp/generated/docs/assistant-message.md +10 -5
  52. package/dist/mcp/generated/docs/chat-container.md +173 -19
  53. package/dist/mcp/generated/docs/chat-input.md +78 -10
  54. package/dist/mcp/generated/docs/cite-content.md +8 -3
  55. package/dist/mcp/generated/docs/code-content.md +9 -4
  56. package/dist/mcp/generated/docs/common-error-content.md +10 -5
  57. package/dist/mcp/generated/docs/constants.md +68 -3
  58. package/dist/mcp/generated/docs/content-render.md +10 -5
  59. package/dist/mcp/generated/docs/delete-tool.md +9 -4
  60. package/dist/mcp/generated/docs/desc-panel.md +9 -4
  61. package/dist/mcp/generated/docs/detail-section.md +93 -0
  62. package/dist/mcp/generated/docs/execution-summary.md +10 -5
  63. package/dist/mcp/generated/docs/file-content.md +9 -4
  64. package/dist/mcp/generated/docs/file-upload-btn.md +10 -5
  65. package/dist/mcp/generated/docs/flow-agent-content.md +252 -0
  66. package/dist/mcp/generated/docs/flow-agent-node-detail.md +240 -0
  67. package/dist/mcp/generated/docs/highlight-keyword.md +10 -5
  68. package/dist/mcp/generated/docs/image-content.md +9 -4
  69. package/dist/mcp/generated/docs/image-preview-group.md +9 -4
  70. package/dist/mcp/generated/docs/image-preview.md +10 -5
  71. package/dist/mcp/generated/docs/info-message.md +7 -2
  72. package/dist/mcp/generated/docs/input-attachment.md +43 -0
  73. package/dist/mcp/generated/docs/input-info-alert.md +42 -0
  74. package/dist/mcp/generated/docs/interrupt-message.md +216 -0
  75. package/dist/mcp/generated/docs/interrupt.md +377 -0
  76. package/dist/mcp/generated/docs/key-value-content.md +9 -4
  77. package/dist/mcp/generated/docs/knowledge-rag-content.md +126 -0
  78. package/dist/mcp/generated/docs/latex-content.md +9 -4
  79. package/dist/mcp/generated/docs/loading-message.md +11 -6
  80. package/dist/mcp/generated/docs/markdown-container.md +1 -1
  81. package/dist/mcp/generated/docs/markdown-content.md +13 -8
  82. package/dist/mcp/generated/docs/markdown-latex.md +3 -3
  83. package/dist/mcp/generated/docs/markdown-mermaid.md +3 -3
  84. package/dist/mcp/generated/docs/mermaid-content.md +9 -4
  85. package/dist/mcp/generated/docs/message-container.md +74 -16
  86. package/dist/mcp/generated/docs/message-loading.md +120 -0
  87. package/dist/mcp/generated/docs/message-render.md +23 -11
  88. package/dist/mcp/generated/docs/message-tools.md +10 -5
  89. package/dist/mcp/generated/docs/messages.md +75 -11
  90. package/dist/mcp/generated/docs/overflow-tips.md +4 -4
  91. package/dist/mcp/generated/docs/preview-toolbar.md +42 -0
  92. package/dist/mcp/generated/docs/questions-container.md +88 -0
  93. package/dist/mcp/generated/docs/reasoning-message.md +10 -5
  94. package/dist/mcp/generated/docs/reference-content.md +10 -5
  95. package/dist/mcp/generated/docs/reference-doc-content.md +112 -0
  96. package/dist/mcp/generated/docs/schema.md +93 -0
  97. package/dist/mcp/generated/docs/scroll-btn.md +8 -3
  98. package/dist/mcp/generated/docs/selection-footer.md +9 -4
  99. package/dist/mcp/generated/docs/selection-question.md +91 -0
  100. package/dist/mcp/generated/docs/shortcut-btn.md +10 -5
  101. package/dist/mcp/generated/docs/shortcut-btns.md +10 -5
  102. package/dist/mcp/generated/docs/shortcut-render.md +10 -5
  103. package/dist/mcp/generated/docs/simple-table.md +103 -0
  104. package/dist/mcp/generated/docs/text-content.md +9 -4
  105. package/dist/mcp/generated/docs/theme.md +50 -4
  106. package/dist/mcp/generated/docs/tool-approval-card.md +164 -0
  107. package/dist/mcp/generated/docs/tool-btn.md +9 -4
  108. package/dist/mcp/generated/docs/tool-message.md +10 -5
  109. package/dist/mcp/generated/docs/toolcall-render.md +10 -5
  110. package/dist/mcp/generated/docs/use-animation-text.md +4 -4
  111. package/dist/mcp/generated/docs/use-clipboard.md +3 -3
  112. package/dist/mcp/generated/docs/use-command-selection.md +1 -1
  113. package/dist/mcp/generated/docs/use-custom-tab.md +1 -1
  114. package/dist/mcp/generated/docs/use-flow-node-actions.md +124 -0
  115. package/dist/mcp/generated/docs/use-full-screen.md +3 -3
  116. package/dist/mcp/generated/docs/use-global-config.md +20 -5
  117. package/dist/mcp/generated/docs/use-menu-keydown.md +1 -1
  118. package/dist/mcp/generated/docs/use-message-group.md +42 -10
  119. package/dist/mcp/generated/docs/use-observer-visible-list.md +1 -1
  120. package/dist/mcp/generated/docs/user-feedback.md +8 -3
  121. package/dist/mcp/generated/docs/user-message.md +18 -13
  122. package/dist/mcp/generated/docs/user-question-answered-card.md +106 -0
  123. package/dist/mcp/generated/docs/user-question-card.md +228 -0
  124. package/dist/mcp/generated/docs/user-question-choice.md +108 -0
  125. package/dist/mcp/generated/docs/user-question-option.md +42 -0
  126. package/dist/mcp/generated/docs/vnode-renderer.md +126 -0
  127. package/dist/mcp/generated/index.json +1105 -562
  128. package/dist/mcp/server.js +1 -1
  129. package/dist/mcp/server.js.map +1 -1
  130. package/dist/mcp/tools/list-components.d.ts +7 -6
  131. package/dist/mcp/tools/list-components.js +23 -29
  132. package/dist/mcp/tools/list-components.js.map +1 -1
  133. package/dist/mcp/tools/search-docs.js +1 -1
  134. package/dist/mcp/tools/search-docs.js.map +1 -1
  135. package/dist/mcp/utils/doc-loader.d.ts +1 -1
  136. package/dist/types/editor.d.ts +0 -1
  137. package/dist/utils/utils.d.ts +2 -2
  138. package/package.json +4 -3
@@ -0,0 +1,106 @@
1
+ <!-- AI SUMMARY -->
2
+ ## 快速了解
3
+
4
+ 在 UserQuestion resume 成功后回显用户回答或取消状态。 源码位置:src/components/chat-message/interrupt-message/user-question/user-question-answered-card.vue。
5
+
6
+ ### 关联组件
7
+ - **interrupt-message** — outcome.success 且 reason 为 UserQuestion 时挂载本组件
8
+ - **user-question-card** — 待回答面板,与本组件成对出现
9
+
10
+ ---
11
+ <!-- FULL DOC -->
12
+
13
+ # UserQuestionAnsweredCard 用户问题回答回显
14
+
15
+ > **能力域**:Agent 能力
16
+
17
+ ## 源码事实
18
+
19
+ - **源码位置**:`src/components/chat-message/interrupt-message/user-question/user-question-answered-card.vue`
20
+ - **能力说明**:在 UserQuestion resume 成功后回显用户回答或取消状态。
21
+
22
+ 由 [InterruptMessageRender](/components/agent/interrupt-message) 在 `content.outcome.type === 'success'` 且 `result.reason === InterruptReason.UserQuestion` 时渲染。默认逐条展示选择题答案;业务可通过 `#answer` slot 自定义回显形态(如自定义表单字段)。
23
+
24
+ ## 基础用法
25
+
26
+ ```vue
27
+ <template>
28
+ <UserQuestionAnsweredCard
29
+ :answers="answers"
30
+ status="resolved"
31
+ />
32
+ </template>
33
+
34
+ <script setup lang="ts">
35
+ import { UserQuestionAnsweredCard, type UserQuestionAnswerItem } from '@blueking/chat-x';
36
+
37
+ const answers: UserQuestionAnswerItem[] = [
38
+ {
39
+ question: '你希望采用哪种实现?',
40
+ multiSelect: false,
41
+ answer: [{ label: 'optimized', description: '优化版' }],
42
+ },
43
+ ];
44
+ </script>
45
+ ```
46
+
47
+ **渲染效果**
48
+
49
+ ## 已取消(跳过)
50
+
51
+ ```vue
52
+ <UserQuestionAnsweredCard
53
+ :answers="[]"
54
+ status="cancelled"
55
+ />
56
+ ```
57
+
58
+ **渲染效果**
59
+
60
+ ## 自定义回显(#answer slot)
61
+
62
+ 当待回答阶段使用了自定义 `#question` 表单时,可通过 `#answer` slot 自定义回显:
63
+
64
+ ```vue
65
+ <UserQuestionAnsweredCard
66
+ :answers="answers"
67
+ status="resolved"
68
+ >
69
+ <template #answer="{ item, index, status }">
70
+ <MyCustomAnswerView :data="item" :index="index" :status="status" />
71
+ </template>
72
+ </UserQuestionAnsweredCard>
73
+ ```
74
+
75
+ `InterruptMessageRender`、`MessageRender`、`MessageContainer` 提供 `#answeredQuestion` slot,参数与 `#answer` 一致,逐层透传至本组件。使用 `ChatContainer` 时若覆盖了 `#message` 插槽,需在自定义 `MessageRender` 中继续透传 `#answeredQuestion`。
76
+
77
+ ## API
78
+
79
+ ### Props
80
+
81
+ | 属性名 | 类型 | 默认值 | 说明 |
82
+ | ------- | ---------------------------- | ------------ | -------------------------------------- |
83
+ | answers | `UserQuestionAnswerItem[]` | — | **必填**,已回答内容列表 |
84
+ | status | `'resolved' \| 'cancelled'` | `'resolved'` | resume 状态:`resolved` 已回复,`cancelled` 已取消(跳过) |
85
+
86
+ ### Slots
87
+
88
+ | 插槽名 | 参数 | 说明 |
89
+ | ------ | ------------------------------------------------- | ------------------------------------------------------------ |
90
+ | answer | `{ item, index, status }` | 自定义单题回答回显;未覆盖时默认渲染 `answer[].description \|\| label` |
91
+
92
+ | 参数 | 类型 | 说明 |
93
+ | ------ | --------------------------------- | ------------------------ |
94
+ | item | `UserQuestionAnswerItem` | 当前题的回答数据 |
95
+ | index | `number` | 题目序号(从 0 开始) |
96
+ | status | `'resolved' \| 'cancelled'` | 与 Props.status 一致 |
97
+
98
+ ### Events / Expose
99
+
100
+ 无。
101
+
102
+ ## 关联文档
103
+
104
+ - [InterruptMessage 中断消息](/components/agent/interrupt-message)
105
+ - [UserQuestionCard 用户问题中断](/components/agent/user-question-card)
106
+ - [中断类型 Interrupt](../../types/interrupt.md)
@@ -0,0 +1,228 @@
1
+ <!-- AI SUMMARY -->
2
+ ## 快速了解
3
+
4
+ 渲染 UserQuestion 中断的待回答面板,支持单选、多选、Others 与跳过。 源码位置:src/components/chat-message/interrupt-message/user-question/user-question-card.vue。
5
+
6
+ ### 关联组件
7
+ - **interrupt-message** — outcome.success 时挂载 UserQuestionAnsweredCard 回显回答
8
+ - **chat-container** — 检测最近待回答 UserQuestion 并把 UserQuestionCard 放在输入区上方
9
+ - **interrupt** — 定义 UserQuestionInterrupt 与 UserQuestionResume 协议
10
+
11
+ ---
12
+ <!-- FULL DOC -->
13
+
14
+ # UserQuestionCard 用户问题中断
15
+ ## 源码事实
16
+
17
+ - **源码位置**:`src/components/chat-message/interrupt-message/user-question/user-question-card.vue`
18
+ - **能力域**:Agent 能力
19
+ - **能力说明**:渲染 UserQuestion 中断的待回答面板,支持单选、多选、Others 与跳过。
20
+
21
+ > **能力域**:Agent 能力
22
+
23
+ `UserQuestionCard` 用于渲染 `InterruptReason.UserQuestion`(`'aidev:user_question'`)中断。它通常由 `ChatContainer` 自动挂载到 `ChatInput` 上方,用户回答后通过 `onInterruptResume(payload, interrupt)` 回传 `UserQuestionResume`。
24
+
25
+ ## 交互能力
26
+
27
+ - **单选 / 多选**:每道题通过 `multiSelect` 控制选择行为;未传时不展示单选/多选标签,默认仍按单选处理。
28
+ - **Others 自由输入**:默认 [UserQuestionChoice](/components/agent/user-question-choice) 为每道题追加 `label: 'others'` 输入项,输入文本写入 `answer[].description`。
29
+ - **自定义作答形态**:通过 `#question` slot 可替换默认选择题,渲染任意表单;作答有效时调用 `setAnswer` 回传 `UserQuestionAnswerItem`,无效时传 `undefined`。
30
+ - **完成校验**:所有题目均已作答(`setAnswer` 收到有效答案)后才允许点击「完成」。
31
+ - **跳过**:点击「跳过」返回 `status: 'cancelled'` 与空 `answers`。
32
+ - **输入框发送**:存在待回答 UserQuestion 时,用户也可在 `ChatInput` 直接发送;`ChatContainer` 会调用 `onSendMessage` 并在第三参数附带与「跳过」等价的 skip `payload` 及 `interrupt`,输入框内容不会自动清空。
33
+
34
+ ## 数据协议
35
+
36
+ 待回答中断:
37
+
38
+ ```typescript
39
+ const interrupt = {
40
+ id: 'interrupt_user_question',
41
+ reason: InterruptReason.UserQuestion,
42
+ toolCallId: 'tool_call_user_question',
43
+ message: '请选择实现方案',
44
+ metadata: {
45
+ questions: [
46
+ {
47
+ header: '请选择实现方案',
48
+ multiSelect: false,
49
+ question: '你希望采用哪种冒泡排序实现?',
50
+ options: [
51
+ { label: 'basic', description: '基础冒泡排序' },
52
+ { label: 'optimized', description: '优化版冒泡排序' },
53
+ ],
54
+ },
55
+ ],
56
+ },
57
+ };
58
+ ```
59
+
60
+ 完成回答后生成的 resume:
61
+
62
+ ```typescript
63
+ const payload = {
64
+ interruptId: 'interrupt_user_question',
65
+ reason: InterruptReason.UserQuestion,
66
+ status: 'resolved',
67
+ payload: {
68
+ answers: [
69
+ {
70
+ question: '你希望采用哪种冒泡排序实现?',
71
+ multiSelect: false,
72
+ answer: [{ label: 'optimized', description: '优化版冒泡排序' }],
73
+ },
74
+ ],
75
+ },
76
+ };
77
+ ```
78
+
79
+ ## 基础用法
80
+
81
+ > 业务侧通常不直接使用本组件;推荐构造 `InterruptMessage` 后交给 `ChatContainer` / `MessageContainer` 渲染。下面示例用于说明组件 API 和 payload 形状。
82
+
83
+ ```vue
84
+ <template>
85
+ <UserQuestionCard
86
+ :interrupt="pendingInterrupt"
87
+ :on-resume="handleResume"
88
+ />
89
+ </template>
90
+
91
+ <script setup lang="ts">
92
+ import { InterruptReason, UserQuestionCard, type OnInterruptResume } from '@blueking/chat-x';
93
+
94
+ const pendingInterrupt = {
95
+ id: 'interrupt_user_question',
96
+ reason: InterruptReason.UserQuestion,
97
+ toolCallId: 'tool_call_user_question',
98
+ metadata: {
99
+ questions: [
100
+ {
101
+ header: '请选择实现方案',
102
+ multiSelect: false,
103
+ question: '你希望采用哪种实现?',
104
+ options: [{ label: 'basic', description: '基础冒泡排序' }],
105
+ },
106
+ ],
107
+ },
108
+ };
109
+
110
+ const handleResume: OnInterruptResume = async (payload, interrupt) => {
111
+ console.log(interrupt.id, payload);
112
+ };
113
+ </script>
114
+ ```
115
+
116
+ **渲染效果**
117
+
118
+ ## 已回答回显
119
+
120
+ `InterruptMessageRender` 在 `content.outcome.type === 'success'` 且 `content.result.reason === InterruptReason.UserQuestion` 时,会在会话内渲染 `UserQuestionAnsweredCard`。
121
+
122
+ ```vue
123
+ <UserQuestionAnsweredCard
124
+ :answers="answers"
125
+ status="resolved"
126
+ />
127
+ ```
128
+
129
+ **渲染效果**
130
+
131
+ ## ChatContainer 自动挂载
132
+
133
+ `ChatContainer` 内部通过 `useMessageGroup` 查找最近一条 `outcome.type === 'interrupt'` 的 `UserQuestion`,并在 `ChatInput` 的 `#interrupt` 插槽中渲染 `UserQuestionCard`:
134
+
135
+ ```vue
136
+ <ChatContainer
137
+ v-model="inputValue"
138
+ :messages="messages"
139
+ :on-interrupt-resume="handleResume"
140
+ :on-send-message="handleSendMessage"
141
+ />
142
+ ```
143
+
144
+ - 卡片内「完成 / 跳过」→ `onInterruptResume(payload, interrupt)`
145
+ - 输入框直接发送 → `onSendMessage(content, docSchema, { interrupt, payload })`,其中 `payload` 由 `buildSkipResumePayload(interrupt)` 生成(`status: 'cancelled'`)
146
+
147
+ ## 工具函数 buildSkipResumePayload
148
+
149
+ 从 `@blueking/chat-x` 导出,用于构造 UserQuestion 的 skip resume(与卡片「跳过」及输入框发送时容器注入的 `options.payload` 一致):
150
+
151
+ ```typescript
152
+ import { buildSkipResumePayload, InterruptReason } from '@blueking/chat-x';
153
+
154
+ const payload = buildSkipResumePayload(interrupt);
155
+ // {
156
+ // interruptId: interrupt.id,
157
+ // reason: InterruptReason.UserQuestion,
158
+ // status: 'cancelled',
159
+ // payload: { answers: [] },
160
+ // }
161
+ ```
162
+
163
+ ## 自定义题目渲染(#question slot)
164
+
165
+ 默认每道题由 [UserQuestionChoice](/components/agent/user-question-choice) 渲染;业务可覆盖 `#question` slot 接入自定义表单:
166
+
167
+ ```vue
168
+ <template>
169
+ <UserQuestionCard
170
+ :interrupt="pendingInterrupt"
171
+ :on-resume="handleResume"
172
+ >
173
+ <template #question="{ question, qIndex, answer, setAnswer, confirm }">
174
+ <!-- 自定义表单:作答有效时 setAnswer(answerItem),无效时 setAnswer(undefined) -->
175
+ <MyCustomForm
176
+ :model="question"
177
+ @change="setAnswer"
178
+ @submit="confirm"
179
+ />
180
+ </template>
181
+ </UserQuestionCard>
182
+ </template>
183
+ ```
184
+
185
+ `ChatContainer` 提供同名 `#interruptQuestion` slot,参数与 `#question` 一致,透传自输入区上方的 `UserQuestionCard`。
186
+
187
+ ## API
188
+
189
+ ### UserQuestionCard Props
190
+
191
+ | 属性名 | 类型 | 默认值 | 说明 |
192
+ | --------- | ----------------------- | ------ | -------------------------------------- |
193
+ | interrupt | `UserQuestionInterrupt` | — | **必填**,含 `metadata.questions` |
194
+ | onResume | `OnInterruptResume` | — | 完成 / 跳过时触发,签名为 `(payload, interrupt)` |
195
+
196
+ ### UserQuestionAnsweredCard Props
197
+
198
+ | 属性名 | 类型 | 默认值 | 说明 |
199
+ | ------- | ---------------------------- | ------------ | ---------------------------- |
200
+ | answers | `UserQuestionAnswerItem[]` | — | 已回答内容列表 |
201
+ | status | `'resolved' \| 'cancelled'` | `'resolved'` | 回显状态,决定展示已回复/已取消 |
202
+
203
+ ### UserQuestionCard Slots
204
+
205
+ | 插槽名 | 参数 | 说明 |
206
+ | -------- | ----------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------- |
207
+ | question | `{ question, qIndex, answer, setAnswer, confirm }` | 自定义单题渲染;未覆盖时回退 [UserQuestionChoice](/components/agent/user-question-choice) |
208
+
209
+ slot 参数说明:
210
+
211
+ | 参数 | 类型 | 说明 |
212
+ | ---------- | ------------------------------------------------- | ---------------------------------------------- |
213
+ | question | `UserQuestionItem` | 原始题目数据 |
214
+ | qIndex | `number` | 题目序号(从 0 开始) |
215
+ | answer | `UserQuestionAnswerItem \| undefined` | 当前题已组装答案,`undefined` 表示未作答 |
216
+ | setAnswer | `(answer: UserQuestionAnswerItem \| undefined) => void` | 写入/清空当前题答案 |
217
+ | confirm | `() => void` | 触发「完成」,等价点击底部完成按钮(需全部已答) |
218
+
219
+ ### Events / Expose
220
+
221
+ 无。
222
+
223
+ ## 关联文档
224
+
225
+ - [中断类型 Interrupt](../../types/interrupt.md)
226
+ - [UserQuestionChoice 选择题](/components/agent/user-question-choice)
227
+ - [InterruptMessage 中断消息](/components/agent/interrupt-message)
228
+ - [ChatContainer 聊天容器](/components/setup/chat-container)
@@ -0,0 +1,108 @@
1
+ <!-- AI SUMMARY -->
2
+ ## 快速了解
3
+
4
+ UserQuestionCard 默认的选择题渲染组件,封装单选/多选、Others 输入与答案组装。 源码位置:src/components/chat-message/interrupt-message/user-question/user-question-choice.vue。
5
+
6
+ ### 关联组件
7
+ - **user-question-card** — 默认通过
8
+ - **user-question-option** — 内部逐条渲染选项行
9
+ - **interrupt** — 答案结构遵循 UserQuestionAnswerItem
10
+
11
+ ---
12
+ <!-- FULL DOC -->
13
+
14
+ # UserQuestionChoice 用户问题选择题
15
+
16
+ > **能力域**:Agent 能力
17
+
18
+ ## 源码事实
19
+
20
+ - **源码位置**:`src/components/chat-message/interrupt-message/user-question/user-question-choice.vue`
21
+ - **能力说明**:封装 UserQuestion 的选择题交互,负责选项归一化、单选/多选切换、Others 输入校验与 `UserQuestionAnswerItem` 组装。
22
+
23
+ `UserQuestionChoice` 是 [UserQuestionCard](/components/agent/user-question-card) 在 `#question` slot 未覆盖时的**默认渲染**。业务侧也可单独使用,配合 `useUserQuestion` 的 `setAnswer` 接入自定义面板。
24
+
25
+ ## 交互能力
26
+
27
+ - **单选 / 多选**:由 `question.multiSelect` 控制;未传时不展示单选/多选标签,但仍按单选行为处理。
28
+ - **Others 自由输入**:前端自动在选项末尾追加 `label: 'others'` 输入项。
29
+ - **实时同步答案**:选择或输入变化时 emit `answer`;作答有效时回传已组装的 `UserQuestionAnswerItem`,无效时回传 `undefined`。
30
+ - **Enter 确认**:Others 输入框按 Enter 触发 `confirm`,等价于点击「完成」按钮(需上层已全部作答)。
31
+
32
+ ## 基础用法(单选)
33
+
34
+ ```vue
35
+ <template>
36
+ <UserQuestionChoice
37
+ :question="singleQuestion"
38
+ @answer="handleAnswer"
39
+ @confirm="handleConfirm"
40
+ />
41
+ </template>
42
+
43
+ <script setup lang="ts">
44
+ import { UserQuestionChoice, type UserQuestionAnswerItem } from '@blueking/chat-x';
45
+
46
+ const singleQuestion = {
47
+ header: '请选择实现方案',
48
+ multiSelect: false,
49
+ question: '你希望采用哪种冒泡排序实现?',
50
+ options: [
51
+ { label: 'basic', description: '基础冒泡排序' },
52
+ { label: 'optimized', description: '优化版冒泡排序' },
53
+ ],
54
+ };
55
+
56
+ const handleAnswer = (answer: UserQuestionAnswerItem | undefined) => {
57
+ console.log(answer);
58
+ };
59
+ </script>
60
+ ```
61
+
62
+ **渲染效果**
63
+
64
+ ## 多选
65
+
66
+ ```vue
67
+ <UserQuestionChoice
68
+ :question="multiQuestion"
69
+ @answer="handleAnswer"
70
+ />
71
+ ```
72
+
73
+ **渲染效果**
74
+
75
+ ## 在 UserQuestionCard 中使用
76
+
77
+ 通常无需直接使用本组件;`UserQuestionCard` 默认已在 `#question` slot 回退中挂载:
78
+
79
+ ```vue
80
+ <UserQuestionCard :interrupt="interrupt" :on-resume="handleResume" />
81
+ ```
82
+
83
+ 如需替换某一题的渲染,覆盖 `#question` slot 即可;未覆盖时仍回退到 `UserQuestionChoice`。
84
+
85
+ ## API
86
+
87
+ ### Props
88
+
89
+ | 属性名 | 类型 | 默认值 | 说明 |
90
+ | -------- | ------------------ | ------ | ---------------------------- |
91
+ | question | `UserQuestionItem` | — | **必填**,含 `options` 等字段 |
92
+
93
+ ### Events
94
+
95
+ | 事件名 | 参数 | 说明 |
96
+ | ------- | ----------------------------------------- | ------------------------------------------------------------ |
97
+ | answer | `(answer: UserQuestionAnswerItem \| undefined)` | 作答变化;有效时回传已组装答案,无效(未选/ Others 空)时 `undefined` |
98
+ | confirm | — | 用户在 Others 输入框按 Enter 时触发,上层可绑定「完成」逻辑 |
99
+
100
+ ### Slots / Expose
101
+
102
+ 无。
103
+
104
+ ## 关联文档
105
+
106
+ - [UserQuestionCard 用户问题中断](/components/agent/user-question-card)
107
+ - [UserQuestionOption 用户问题选项](/components/agent/user-question-option)
108
+ - [中断类型 Interrupt](../../types/interrupt.md)
@@ -0,0 +1,42 @@
1
+ <!-- AI SUMMARY -->
2
+ ## 快速了解
3
+
4
+ UserQuestionChoice 内部选项行,处理单选/多选状态和 Others 输入。 源码位置:src/components/chat-message/interrupt-message/user-question/user-question-option.vue。
5
+
6
+ ---
7
+ <!-- FULL DOC -->
8
+
9
+ # UserQuestionOption 用户问题选项
10
+
11
+ > **能力域**:Agent 能力
12
+
13
+ ## 源码事实
14
+
15
+ - **源码位置**:`src/components/chat-message/interrupt-message/user-question/user-question-option.vue`
16
+ - **能力说明**:UserQuestionChoice 内部选项行,处理单选/多选状态和 Others 输入。
17
+
18
+ ## API 摘要
19
+
20
+ ### Props
21
+
22
+ - `{ option: NormalizedUserQuestionOption; othersText?: string; selected: boolean; }`
23
+
24
+ ### Emits
25
+
26
+ - `{ (e: 'confirm'): void; (e: 'select'): void; (e: 'update:othersText', value: string): void; }`
27
+
28
+ ### Slots
29
+
30
+ - 无。
31
+
32
+ ### Expose
33
+
34
+ - 无。
35
+
36
+ ## 组件依赖
37
+
38
+ - 无组件依赖或仅依赖基础库。
39
+
40
+ ## 使用建议
41
+
42
+ - 优先通过 [UserQuestionChoice](/components/agent/user-question-choice) 或 [UserQuestionCard](/components/agent/user-question-card) 使用;直接使用前请确认 props 数据结构来自对应类型定义。
@@ -0,0 +1,126 @@
1
+ <!-- AI SUMMARY -->
2
+ ## 快速了解
3
+
4
+ 将 Markdown token 转成 VNode 的内部渲染桥。 源码位置:src/components/chat-content/vnode-renderer.ts。
5
+
6
+ ### 关联组件
7
+ - **markdown-content** — MarkdownContent 对普通 token 分组使用本组件渲染
8
+ - **code-content** — fence/code_block 代码块通常会被 MarkdownContent 提前分流到 CodeContent
9
+ - **mermaid-content** — mermaid 代码块通常会被 MarkdownContent 提前分流到 MermaidContent
10
+ - **image-content** — 图片 token 由 tokensToVNodes 转为 ImageContent
11
+
12
+ ---
13
+ <!-- FULL DOC -->
14
+
15
+ # VNodeRenderer VNode 渲染器
16
+
17
+ > **能力域**:辅助能力
18
+
19
+ `VNodeRenderer` 是 Markdown 渲染链路里的内部桥接组件。它接收 markdown-it 解析出的 `Token[]`,调用 `tokensToVNodes` 转成 Vue VNode,并返回渲染函数结果。
20
+
21
+ 通常不需要业务侧直接使用。完整 Markdown 内容请优先使用 [MarkdownContent](../rendering/markdown-content.md),它会先识别 Mermaid、LaTeX、代码块等特殊 token,再把普通 token 分组交给 `VNodeRenderer`。
22
+
23
+ ## 源码事实
24
+
25
+ - **源码位置**:`src/components/chat-content/vnode-renderer.ts`
26
+ - **能力说明**:将 Markdown token 转成 VNode 的内部渲染桥。
27
+
28
+ ## 核心能力
29
+
30
+ - **Token 到 VNode**:将 markdown-it 的 block、inline、text、link、image、html 等 token 转为 Vue VNode
31
+ - **稳定 key**:`tokensToVNodes` 基于 token 类型、标签和内容 hash 生成 key,降低流式渲染时 DOM 误复用风险
32
+ - **HTML 安全入口**:`options.html` 开启时可渲染 HTML token,实际安全过滤依赖 `options.sanitize`
33
+ - **渲染规则复用**:支持传入 markdown-it `renderer` 与 `mditOptions`,复用自定义 renderer rule
34
+ - **特殊 token 兜底**:图片 token 转成 `ImageContent`,链接自动补充 `target="_blank"` 与 `rel="noopener noreferrer"`
35
+
36
+ ## 基础用法
37
+
38
+ ```vue
39
+ <template>
40
+ <VNodeRenderer :tokens="tokens" />
41
+ </template>
42
+
43
+ <script setup lang="ts">
44
+ import MarkdownIt from '@blueking/chat-x/src/markdown-it/index';
45
+ import VNodeRenderer from '@blueking/chat-x/src/components/chat-content/vnode-renderer';
46
+
47
+ const md = new MarkdownIt();
48
+ const tokens = md.parse('这是一段 **加粗文本**。', {});
49
+ </script>
50
+ ```
51
+
52
+ **渲染效果**
53
+
54
+ ## 空 Tokens
55
+
56
+ `tokens` 为空数组时,`tokensToVNodes` 返回空数组,不渲染任何内容。
57
+
58
+ ## 与 MarkdownContent 的关系
59
+
60
+ `MarkdownContent` 会先按 token 类型分流,再将普通 token 交给 `VNodeRenderer`:
61
+
62
+ ```vue
63
+ <template v-else>
64
+ <VNodeRenderer
65
+ :options="vnodeOptions"
66
+ :tokens="groupedToken"
67
+ />
68
+ </template>
69
+ ```
70
+
71
+ 其中 `vnodeOptions` 会携带 HTML 净化函数、markdown-it renderer 和 parser options:
72
+
73
+ ```typescript
74
+ const vnodeOptions = {
75
+ html: true,
76
+ mditOptions: md.options,
77
+ renderer: md.renderer,
78
+ sanitize: (html: string) => dompurify.sanitize(html, domPurifyConfig),
79
+ };
80
+ ```
81
+
82
+ ## API
83
+
84
+ ### Props
85
+
86
+ | 属性名 | 类型 | 必填 | 默认值 | 说明 |
87
+ | ------- | --------------------- | ---- | ------ | ---------------------------- |
88
+ | tokens | `Token[]` | 是 | — | markdown-it token 数组 |
89
+ | options | `TokenToVNodeOptions` | 否 | `{}` | token 转 VNode 的渲染选项 |
90
+
91
+ ### Emits
92
+
93
+ - 无。
94
+
95
+ ### Slots
96
+
97
+ - 无。
98
+
99
+ ### Expose
100
+
101
+ - 无。
102
+
103
+ ## 类型定义
104
+
105
+ ```typescript
106
+ export interface TokenToVNodeOptions {
107
+ highlight?: ((str: string, lang: string, attrs?: unknown) => string) | null;
108
+ html?: boolean;
109
+ mditOptions?: Options;
110
+ renderer?: Renderer;
111
+ sanitize?: (html: string) => string;
112
+ }
113
+ ```
114
+
115
+ ## 使用建议
116
+
117
+ - 业务侧不要绕过 `MarkdownContent` 直接渲染完整 Markdown 字符串;`VNodeRenderer` 只接收已经解析好的 token。
118
+ - 如果启用 `options.html`,必须同步传入 `sanitize`,否则 HTML token 会直接进入 `innerHTML`。
119
+ - 特殊内容如代码块、Mermaid、LaTeX 推荐继续走 `MarkdownContent` 的分流逻辑。
120
+
121
+ ## 关联组件
122
+
123
+ - [MarkdownContent](../rendering/markdown-content.md) — Markdown 主渲染器。
124
+ - [CodeContent](../rendering/code-content.md) — 代码块渲染。
125
+ - [MermaidContent](../rendering/mermaid-content.md) — Mermaid 图表渲染。
126
+ - [ImageContent](../medias/image-content.md) — 图片 token 渲染。