@infinilabs/chat-message 0.0.5 → 0.0.6

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.
package/README.md CHANGED
@@ -1,37 +1,84 @@
1
1
  # @infinilabs/chat-message
2
2
 
3
- A React component for rendering AI chat messages with support for streaming responses, thinking process, tool calls, and citations.
3
+ 一个用于渲染 AI 对话消息的 React 组件,支持流式响应、思考过程展示、工具调用、引用来源等完整的 AI 回答结构。
4
4
 
5
- ## Installation
5
+ > 组件已内置 Tailwind v4 样式注入和 `react-i18next` 配置,作为 UI 组件使用时只需要按本文档传入数据和 props 即可。
6
+
7
+ ## 安装
6
8
 
7
9
  ```bash
8
10
  pnpm install @infinilabs/chat-message
9
11
  ```
10
12
 
11
- ## Usage
13
+ ## 核心类型
14
+
15
+ `ChatMessage` 要求你传入一个 `IChatMessage`,其中 `_source` 中的字段会被用于驱动 UI。
16
+
17
+ ```ts
18
+ export interface ISource {
19
+ id?: string;
20
+ created?: string;
21
+ updated?: string;
22
+ status?: string;
23
+ session_id?: string;
24
+ type?: string; // 'user' | 'assistant' 等
25
+ message?: any; // 主消息内容(Markdown 文本)
26
+ attachments?: string[]; // 附件 ID 列表(由业务侧解析为明细)
27
+ title?: string;
28
+ question?: string; // 用户原始问题
29
+ details?: any[] | null; // 结构化步骤:query_intent / tools / fetch_source ...
30
+ assistant_id?: string; // 助手 ID(可用于从列表中查找)
31
+ assistant_item?: any; // 已经解析好的助手对象
32
+ [key: string]: any;
33
+ }
34
+
35
+ export interface IChatMessage {
36
+ _id?: string;
37
+ _source: ISource;
38
+ [key: string]: any;
39
+ }
40
+
41
+ export interface IChunkData {
42
+ session_id?: string;
43
+ message_id?: string;
44
+ message_type?: string;
45
+ reply_to_message?: string;
46
+ chunk_sequence?: number;
47
+ chunk_type?: string; // 'query_intent' | 'tools' | 'fetch_source' | 'pick_source' | 'deep_read' | 'think' | 'response'
48
+ message_chunk?: string; // 流式文本内容
49
+ [key: string]: any;
50
+ }
51
+ ```
52
+
53
+ 常见场景:
54
+
55
+ - 用户消息:`_source.type = 'user'`,主要使用 `question` / `message` / `attachments`。
56
+ - 助手消息:`_source.type = 'assistant'`,使用 `message` 作为最终回答文本,`details`/chunk 作为结构化步骤。
12
57
 
13
- ### Basic Rendering (Static Data)
58
+ ---
59
+
60
+ ## 基本用法(静态数据)
14
61
 
15
62
  ```tsx
16
63
  import { ChatMessage } from '@infinilabs/chat-message';
64
+ import type { IChatMessage } from '@infinilabs/chat-message';
17
65
 
18
- const message = {
66
+ const message: IChatMessage = {
19
67
  _id: '1',
20
68
  _source: {
21
69
  type: 'assistant',
22
70
  message: 'Hello! I am Coco AI.',
23
- // Pre-populated details for history
24
71
  details: [
25
- { type: 'think', description: 'Thinking process...' },
26
- { type: 'query_intent', payload: { ... } }
27
- ]
28
- }
72
+ { type: 'think', description: 'Thinking process...' },
73
+ { type: 'query_intent', payload: { /* ... */ } },
74
+ ],
75
+ },
29
76
  };
30
77
 
31
78
  function App() {
32
79
  return (
33
- <ChatMessage
34
- message={message}
80
+ <ChatMessage
81
+ message={message}
35
82
  locale="en"
36
83
  theme="light"
37
84
  />
@@ -39,26 +86,44 @@ function App() {
39
86
  }
40
87
  ```
41
88
 
42
- ### Streaming Responses (Real-time)
89
+ ---
43
90
 
44
- To stream AI responses (including thinking, tools, etc.), use the `ref` to push chunks directly to the component. This allows the component to manage internal loading states and data accumulation efficiently.
91
+ ## 流式响应(推荐)
92
+
93
+ 通过 `ref` 使用 `ChatMessageRef`,可以向组件推送分片(chunk),用于实时渲染思考过程、工具调用、引用来源和最终回答。
45
94
 
46
95
  ```tsx
47
96
  import { useRef } from 'react';
48
- import { ChatMessage, ChatMessageRef, IChatMessage } from '@infinilabs/chat-message';
97
+ import {
98
+ ChatMessage,
99
+ type ChatMessageRef,
100
+ type IChatMessage,
101
+ type IChunkData,
102
+ } from '@infinilabs/chat-message';
49
103
 
50
104
  function App() {
51
105
  const chatRef = useRef<ChatMessageRef>(null);
52
-
106
+
53
107
  const message: IChatMessage = {
54
108
  _id: 'streaming-msg',
55
- _source: { type: 'assistant', message: '', details: [] }
109
+ _source: { type: 'assistant', message: '', details: [] },
56
110
  };
57
111
 
58
112
  const handleStream = async () => {
113
+ // 开始新一轮回答前,清空内部状态
59
114
  chatRef.current?.reset();
60
- chatRef.current?.addChunk({ chunk_type: 'think', message_chunk: '...' });
61
- chatRef.current?.addChunk({ chunk_type: 'response', message_chunk: 'Hello world!' });
115
+
116
+ const thinkChunk: IChunkData = {
117
+ chunk_type: 'think',
118
+ message_chunk: 'Thinking...',
119
+ };
120
+ chatRef.current?.addChunk(thinkChunk);
121
+
122
+ const responseChunk: IChunkData = {
123
+ chunk_type: 'response',
124
+ message_chunk: 'Hello world!',
125
+ };
126
+ chatRef.current?.addChunk(responseChunk);
62
127
  };
63
128
 
64
129
  return (
@@ -71,15 +136,28 @@ function App() {
71
136
  }
72
137
  ```
73
138
 
74
- ### List Rendering with Streaming (Recommended)
139
+ ---
140
+
141
+ ## 列表渲染 + 流式响应
75
142
 
76
- When rendering a list of messages, attach the `ref` only to the last assistant message while streaming, and pass `isTyping` to that active message.
143
+ 在对话列表中,通常只对「最后一个正在生成的助手消息」挂 `ref` `isTyping`:
77
144
 
78
145
  ```tsx
79
146
  import { useRef } from 'react';
80
- import { ChatMessage, ChatMessageRef } from '@infinilabs/chat-message';
147
+ import {
148
+ ChatMessage,
149
+ type ChatMessageRef,
150
+ type IChatMessage,
151
+ } from '@infinilabs/chat-message';
152
+
153
+ interface MessagesListProps {
154
+ messages: IChatMessage[];
155
+ isTyping: boolean;
156
+ locale?: string;
157
+ theme?: 'light' | 'dark' | 'system';
158
+ }
81
159
 
82
- function MessagesList({ messages, isTyping, locale, theme }) {
160
+ function MessagesList({ messages, isTyping, locale, theme }: MessagesListProps) {
83
161
  const activeMessageRef = useRef<ChatMessageRef>(null);
84
162
 
85
163
  return (
@@ -88,6 +166,7 @@ function MessagesList({ messages, isTyping, locale, theme }) {
88
166
  const isLast = index === messages.length - 1;
89
167
  const isAssistant = msg._source.type === 'assistant';
90
168
  const shouldAttachRef = isLast && isAssistant && isTyping;
169
+
91
170
  return (
92
171
  <ChatMessage
93
172
  key={msg._id}
@@ -104,36 +183,102 @@ function MessagesList({ messages, isTyping, locale, theme }) {
104
183
  }
105
184
  ```
106
185
 
107
- ## Props
108
-
109
- | Prop | Type | Default | Description |
110
- |------|------|---------|-------------|
111
- | `message` | `IChatMessage` | Required | The message object containing content and metadata. |
112
- | `isTyping` | `boolean` | `false` | Shows typing cursor/animation. |
113
- | `onResend` | `(value: string) => void` | - | Callback for resending a message (user messages). |
114
- | `hide_assistant` | `boolean` | `false` | Whether to hide the assistant avatar/name. |
115
- | `theme` | `'light' \| 'dark' \| 'system'` | - | Color theme. |
116
- | `locale` | `string` | - | Language code (e.g., 'en', 'zh'). |
117
- | `formatUrl` | `(data: IChunkData) => string` | - | Custom formatter for source URLs. |
118
- | `rootClassName` | `string` | - | Custom class for the root element. |
119
- | `actionClassName` | `string` | - | Custom class for the action buttons area. |
120
- | `actionIconSize` | `number` | - | Size of the action icons. |
121
- | `copyButtonId` | `string` | - | ID for the copy button (for tracking/testing). |
122
-
123
- ## Instance Methods (Ref)
124
-
125
- | Method | Type | Description |
126
- |--------|------|-------------|
127
- | `addChunk` | `(chunk: IChunkData) => void` | Feeds a new data chunk (think, tools, response, etc.) to the component. Automatically handles loading states and data merging. |
128
- | `reset` | `() => void` | Clears internal streaming state and resets loading indicators. |
129
-
130
- ## Features
131
-
132
- - **Internal State Management**: Automatically handles complex AI steps like `query_intent`, `tools`, `fetch_source`, `pick_source`, `deep_read`, and `think` via streaming chunks.
133
- - **Streaming Support**: Real-time rendering of content as it arrives using `addChunk`.
134
- - **Markdown Support**: Integrated with `@ant-design/x-markdown` for rich text rendering including code blocks and tables.
135
- - **Thinking Process**: Collapsible section for AI thought process.
136
- - **Tool Calls**: Visualizes tool execution steps.
137
- - **Citations**: Supports source citations.
138
- - **Theming**: Built-in light, dark, and system modes.
139
- - **I18n**: Built-in English and Chinese support.
186
+ ---
187
+
188
+ ## 组件 Props 说明
189
+
190
+ 实现位置:[components/index.tsx](file:///Users/rain9/infinilabs/ui-common/packages/ChatMessage/src/components/index.tsx)
191
+
192
+ ```ts
193
+ export interface ChatMessageProps {
194
+ message: IChatMessage;
195
+ isTyping?: boolean;
196
+ onResend?: (value: string) => void;
197
+ hide_assistant?: boolean;
198
+ rootClassName?: string;
199
+ actionClassName?: string;
200
+ actionIconSize?: number;
201
+ copyButtonId?: string;
202
+ formatUrl?: (data: IChunkData) => string;
203
+ theme?: 'light' | 'dark' | 'system';
204
+ locale?: string;
205
+ query_intent?: IChunkData;
206
+ tools?: IChunkData;
207
+ fetch_source?: IChunkData;
208
+ pick_source?: IChunkData;
209
+ deep_read?: IChunkData;
210
+ think?: IChunkData;
211
+ response?: IChunkData;
212
+ currentAssistant?: any;
213
+ assistantList?: any[];
214
+ }
215
+ ```
216
+
217
+ ### 必填 / 选填一览
218
+
219
+ | Prop | 是否必填 | 类型 | 默认值 | 说明 |
220
+ |--------------------|----------|--------------------------------|--------|------|
221
+ | `message` | 必填 | `IChatMessage` | - | 当前这条消息的数据,包含类型、文本、`details` 等。 |
222
+ | `isTyping` | 选填 | `boolean` | `false`| 是否处于「正在生成」状态,会显示打字光标等。 |
223
+ | `onResend` | 选填 | `(value: string) => void` | - | 重新发送按钮回调,一般传入原问题文本。 |
224
+ | `hide_assistant` | 选填 | `boolean` | `false`| 是否隐藏助手头像和名称。 |
225
+ | `theme` | 选填 | `'light' \| 'dark' \| 'system'`| - | 主题模式;`system` 会根据系统深浅色自动选择。 |
226
+ | `locale` | 选填 | `string` | - | 语言,例如 `'en'`、`'zh'`,改变时内部调用 `i18n.changeLanguage`。 |
227
+ | `formatUrl` | 选填 | `(data: IChunkData) => string` | - | 用于 `FetchSource` 中自定义文档链接 URL。 |
228
+ | `rootClassName` | 选填 | `string` | - | 外层根元素的额外 class,便于业务方统一调整样式。 |
229
+ | `actionClassName` | 选填 | `string` | - | 底部操作区(复制 / 点赞 / 重试)的外层 class。 |
230
+ | `actionIconSize` | 选填 | `number` | - | 操作区图标尺寸,默认使用内置大小。 |
231
+ | `copyButtonId` | 选填 | `string` | - | 复制按钮的 id,便于埋点或自动化测试。 |
232
+ | `query_intent` | 选填 | `IChunkData` | - | 「理解查询」阶段的流式分片,可不通过 `details` 而直接驱动 UI。 |
233
+ | `tools` | 选填 | `IChunkData` | - | 工具调用阶段分片。 |
234
+ | `fetch_source` | 选填 | `IChunkData` | - | 文档检索阶段分片。 |
235
+ | `pick_source` | 选填 | `IChunkData` | - | 已选来源分片。 |
236
+ | `deep_read` | 选填 | `IChunkData` | - | 深度阅读阶段分片。 |
237
+ | `think` | 选填 | `IChunkData` | - | 思考过程分片。 |
238
+ | `response` | 选填 | `IChunkData` | - | 回答正文分片;如果不使用流式,可以直接写在 `message._source.message`。 |
239
+ | `currentAssistant` | 选填 | `any` | - | 当前助手信息(包含名称、图标等),在无 `assistant_item` 时作为兜底。 |
240
+ | `assistantList` | 选填 | `any[]` | - | 所有助手列表,组件会根据 `assistant_id` 自动匹配出当前助手。 |
241
+
242
+ > 一般业务场景只需要关心:`message`、`isTyping`、`onResend`、`theme`、`locale`。
243
+ > 其余 props 用于更细粒度的流式控制、多助手匹配或接入已有平台数据。
244
+
245
+ ---
246
+
247
+ ## Ref 实例方法
248
+
249
+ 实现位置同样在 [components/index.tsx](file:///Users/rain9/infinilabs/ui-common/packages/ChatMessage/src/components/index.tsx)。
250
+
251
+ ```ts
252
+ export interface ChatMessageRef {
253
+ addChunk: (chunk: IChunkData) => void;
254
+ reset: () => void;
255
+ }
256
+ ```
257
+
258
+ | Method | 类型 | 说明 |
259
+ |-----------|-------------------------------|------|
260
+ | `addChunk`| `(chunk: IChunkData) => void` | 注入一条新的流式分片。根据 `chunk.chunk_type` 自动更新对应 UI 区块并控制加载状态。支持类型:`query_intent`、`tools`、`fetch_source`、`pick_source`、`deep_read`、`think`、`response`。 |
261
+ | `reset` | `() => void` | 清空内部所有分片状态,重置加载标记,通常在开始新一轮流式回答前调用。 |
262
+
263
+ ### 流式 chunk 行为说明(简要)
264
+
265
+ - `query_intent`:驱动顶部「理解查询」卡片,可附带 `suggestion` 字段,内部会把推荐问句传递给 `SuggestionList`。
266
+ - `tools`:展示调用工具的步骤和输入输出信息。
267
+ - `fetch_source`:展示检索到的文档列表和摘要。
268
+ - `pick_source`:展示已选中的引用来源。
269
+ - `deep_read`:展示正在阅读的文档进度。
270
+ - `think`:展示或折叠的思考过程内容。
271
+ - `response`:回答正文,会自动追加到已有内容中;当遇到 `<think>...</think>` 包裹内容时,会将其中内容视为 `think` 分片而不是回答文本。
272
+
273
+ ---
274
+
275
+ ## 功能概览
276
+
277
+ - 内部状态管理:自动处理 `query_intent`、`tools`、`fetch_source`、`pick_source`、`deep_read`、`think`、`response` 等复杂步骤。
278
+ - 流式渲染:支持通过 `addChunk` 实时推送分片,带打字动效。
279
+ - Markdown 支持:使用 `@ant-design/x-markdown` 渲染代码块、列表、表格等。
280
+ - 思考过程:可折叠的思考内容区域。
281
+ - 工具调用可视化:展示工具执行的过程和结果。
282
+ - 引用与来源:展示检索文档、选中来源等信息。
283
+ - 主题与暗色模式:内置 light / dark / system,组件内部已处理暗色配色。
284
+ - 国际化:内置中英文文案,支持通过 `locale` 切换。