@unif/react-native-chat-sdk 0.4.1 → 0.5.0

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 (100) hide show
  1. package/lib/commonjs/hooks/ChatProvider.js +6 -5
  2. package/lib/commonjs/hooks/ChatProvider.js.map +1 -1
  3. package/lib/commonjs/hooks/useXChat.js +3 -11
  4. package/lib/commonjs/hooks/useXChat.js.map +1 -1
  5. package/lib/commonjs/hooks/useXConversations.js +24 -4
  6. package/lib/commonjs/hooks/useXConversations.js.map +1 -1
  7. package/lib/commonjs/hooks/useXModel.js.map +1 -1
  8. package/lib/commonjs/index.js +19 -0
  9. package/lib/commonjs/index.js.map +1 -1
  10. package/lib/commonjs/providers/AbstractChatProvider.js.map +1 -1
  11. package/lib/commonjs/providers/DeepSeekChatProvider.js.map +1 -1
  12. package/lib/commonjs/providers/OpenAIChatProvider.js +1 -1
  13. package/lib/commonjs/providers/OpenAIChatProvider.js.map +1 -1
  14. package/lib/commonjs/stores/chatStore.js +19 -0
  15. package/lib/commonjs/stores/chatStore.js.map +1 -1
  16. package/lib/commonjs/stores/historyStore.js +26 -0
  17. package/lib/commonjs/stores/historyStore.js.map +1 -1
  18. package/lib/commonjs/tools/XRequest.js +1 -1
  19. package/lib/commonjs/tools/XRequest.js.map +1 -1
  20. package/lib/commonjs/tools/XStream.js +0 -1
  21. package/lib/commonjs/tools/XStream.js.map +1 -1
  22. package/lib/module/hooks/ChatProvider.js +6 -5
  23. package/lib/module/hooks/ChatProvider.js.map +1 -1
  24. package/lib/module/hooks/useXChat.js +5 -13
  25. package/lib/module/hooks/useXChat.js.map +1 -1
  26. package/lib/module/hooks/useXConversations.js +24 -4
  27. package/lib/module/hooks/useXConversations.js.map +1 -1
  28. package/lib/module/hooks/useXModel.js.map +1 -1
  29. package/lib/module/index.js +2 -0
  30. package/lib/module/index.js.map +1 -1
  31. package/lib/module/providers/AbstractChatProvider.js.map +1 -1
  32. package/lib/module/providers/DeepSeekChatProvider.js.map +1 -1
  33. package/lib/module/providers/OpenAIChatProvider.js +1 -1
  34. package/lib/module/providers/OpenAIChatProvider.js.map +1 -1
  35. package/lib/module/stores/chatStore.js +16 -0
  36. package/lib/module/stores/chatStore.js.map +1 -1
  37. package/lib/module/stores/historyStore.js +26 -0
  38. package/lib/module/stores/historyStore.js.map +1 -1
  39. package/lib/module/stores/modelStore.js.map +1 -1
  40. package/lib/module/stores/sessionStore.js.map +1 -1
  41. package/lib/module/tools/XRequest.js +1 -1
  42. package/lib/module/tools/XRequest.js.map +1 -1
  43. package/lib/module/tools/XStream.js +0 -1
  44. package/lib/module/tools/XStream.js.map +1 -1
  45. package/lib/typescript/commonjs/hooks/ChatProvider.d.ts +3 -2
  46. package/lib/typescript/commonjs/hooks/ChatProvider.d.ts.map +1 -1
  47. package/lib/typescript/commonjs/hooks/useXChat.d.ts +1 -2
  48. package/lib/typescript/commonjs/hooks/useXChat.d.ts.map +1 -1
  49. package/lib/typescript/commonjs/hooks/useXConversations.d.ts +3 -0
  50. package/lib/typescript/commonjs/hooks/useXConversations.d.ts.map +1 -1
  51. package/lib/typescript/commonjs/index.d.ts +3 -2
  52. package/lib/typescript/commonjs/index.d.ts.map +1 -1
  53. package/lib/typescript/commonjs/providers/AbstractChatProvider.d.ts.map +1 -1
  54. package/lib/typescript/commonjs/providers/DeepSeekChatProvider.d.ts.map +1 -1
  55. package/lib/typescript/commonjs/providers/OpenAIChatProvider.d.ts.map +1 -1
  56. package/lib/typescript/commonjs/stores/chatStore.d.ts +3 -0
  57. package/lib/typescript/commonjs/stores/chatStore.d.ts.map +1 -1
  58. package/lib/typescript/commonjs/stores/historyStore.d.ts +1 -0
  59. package/lib/typescript/commonjs/stores/historyStore.d.ts.map +1 -1
  60. package/lib/typescript/commonjs/tools/SSEParser.d.ts.map +1 -1
  61. package/lib/typescript/commonjs/tools/XStream.d.ts.map +1 -1
  62. package/lib/typescript/commonjs/types/provider.d.ts.map +1 -1
  63. package/lib/typescript/module/hooks/ChatProvider.d.ts +3 -2
  64. package/lib/typescript/module/hooks/ChatProvider.d.ts.map +1 -1
  65. package/lib/typescript/module/hooks/useXChat.d.ts +1 -2
  66. package/lib/typescript/module/hooks/useXChat.d.ts.map +1 -1
  67. package/lib/typescript/module/hooks/useXConversations.d.ts +3 -0
  68. package/lib/typescript/module/hooks/useXConversations.d.ts.map +1 -1
  69. package/lib/typescript/module/index.d.ts +3 -2
  70. package/lib/typescript/module/index.d.ts.map +1 -1
  71. package/lib/typescript/module/providers/AbstractChatProvider.d.ts.map +1 -1
  72. package/lib/typescript/module/providers/DeepSeekChatProvider.d.ts.map +1 -1
  73. package/lib/typescript/module/providers/OpenAIChatProvider.d.ts.map +1 -1
  74. package/lib/typescript/module/stores/chatStore.d.ts +3 -0
  75. package/lib/typescript/module/stores/chatStore.d.ts.map +1 -1
  76. package/lib/typescript/module/stores/historyStore.d.ts +1 -0
  77. package/lib/typescript/module/stores/historyStore.d.ts.map +1 -1
  78. package/lib/typescript/module/tools/SSEParser.d.ts.map +1 -1
  79. package/lib/typescript/module/tools/XStream.d.ts.map +1 -1
  80. package/lib/typescript/module/types/provider.d.ts.map +1 -1
  81. package/package.json +1 -1
  82. package/src/hooks/ChatProvider.tsx +24 -12
  83. package/src/hooks/useXChat.ts +11 -23
  84. package/src/hooks/useXConversations.ts +39 -10
  85. package/src/hooks/useXModel.ts +2 -2
  86. package/src/index.ts +31 -19
  87. package/src/providers/AbstractChatProvider.ts +7 -3
  88. package/src/providers/DeepSeekChatProvider.ts +4 -7
  89. package/src/providers/OpenAIChatProvider.ts +6 -6
  90. package/src/stores/chatStore.ts +29 -10
  91. package/src/stores/historyStore.ts +45 -8
  92. package/src/stores/modelStore.ts +1 -1
  93. package/src/stores/sessionStore.ts +1 -1
  94. package/src/tools/SSEParser.ts +1 -1
  95. package/src/tools/XRequest.ts +1 -1
  96. package/src/tools/XStream.ts +0 -1
  97. package/src/types/provider.ts +2 -2
  98. package/lib/commonjs/index.md +0 -188
  99. package/lib/module/index.md +0 -188
  100. package/src/index.md +0 -188
@@ -5,9 +5,9 @@
5
5
  * 额外处理 reasoning_content 字段(DeepSeek 的思考过程)→ 映射到 <think> 标签
6
6
  */
7
7
 
8
- import {OpenAIChatProvider} from './OpenAIChatProvider';
9
- import type {ChatMessage} from '../types/message';
10
- import type {SSEOutput} from '../types/provider';
8
+ import { OpenAIChatProvider } from './OpenAIChatProvider';
9
+ import type { ChatMessage } from '../types/message';
10
+ import type { SSEOutput } from '../types/provider';
11
11
 
12
12
  export interface DeepSeekChatProviderConfig {
13
13
  apiKey?: string;
@@ -71,10 +71,7 @@ export class DeepSeekChatProvider extends OpenAIChatProvider {
71
71
 
72
72
  if (content) {
73
73
  // 如果有未关闭的 think 标签,先关闭
74
- if (
75
- newText.includes('<think>') &&
76
- !newText.includes('</think>')
77
- ) {
74
+ if (newText.includes('<think>') && !newText.includes('</think>')) {
78
75
  newText += '</think>';
79
76
  }
80
77
  newText += content;
@@ -4,10 +4,10 @@
4
4
  * 兼容所有 OpenAI 标准 API(OpenAI、Azure、Moonshot、通义千问兼容模式等)
5
5
  */
6
6
 
7
- import {AbstractChatProvider} from './AbstractChatProvider';
8
- import {XRequest} from '../tools/XRequest';
9
- import type {ChatMessage, MessageStatus} from '../types/message';
10
- import type {RequestParams, SSEOutput} from '../types/provider';
7
+ import { AbstractChatProvider } from './AbstractChatProvider';
8
+ import { XRequest } from '../tools/XRequest';
9
+ import type { ChatMessage, MessageStatus } from '../types/message';
10
+ import type { RequestParams, SSEOutput } from '../types/provider';
11
11
 
12
12
  export interface OpenAIChatProviderConfig {
13
13
  baseURL: string;
@@ -30,7 +30,7 @@ export class OpenAIChatProvider extends AbstractChatProvider<
30
30
  constructor(config: OpenAIChatProviderConfig) {
31
31
  const headers: Record<string, string> = {};
32
32
  if (config.apiKey) {
33
- headers['Authorization'] = `Bearer ${config.apiKey}`;
33
+ headers.Authorization = `Bearer ${config.apiKey}`;
34
34
  }
35
35
 
36
36
  const request = new XRequest({
@@ -76,7 +76,7 @@ export class OpenAIChatProvider extends AbstractChatProvider<
76
76
  createdAt: new Date(),
77
77
  messageType: 'text',
78
78
  status: 'local' as MessageStatus,
79
- turnId: input.extra?.turnId as string ?? genId(),
79
+ turnId: (input.extra?.turnId as string) ?? genId(),
80
80
  };
81
81
  }
82
82
 
@@ -3,9 +3,9 @@
3
3
  * 内部 store,通过 useXChat hook 封装后对外暴露
4
4
  */
5
5
 
6
- import {create} from 'zustand';
7
- import type {ChatMessage} from '../types/message';
8
- import type {SuggestionItem} from '../types/sse';
6
+ import { create } from 'zustand';
7
+ import type { ChatMessage } from '../types/message';
8
+ import type { SuggestionItem } from '../types/sse';
9
9
 
10
10
  interface ChatState {
11
11
  messages: ChatMessage[];
@@ -15,18 +15,17 @@ interface ChatState {
15
15
  error: string | null;
16
16
 
17
17
  addMessage: (message: ChatMessage) => void;
18
- updateMessage: (id: string, updater: (msg: ChatMessage) => ChatMessage) => void;
18
+ updateMessage: (
19
+ id: string,
20
+ updater: (msg: ChatMessage) => ChatMessage
21
+ ) => void;
19
22
  upsertMessage: (message: ChatMessage) => void;
20
23
  setMessages: (
21
- messages:
22
- | ChatMessage[]
23
- | ((prev: ChatMessage[]) => ChatMessage[]),
24
+ messages: ChatMessage[] | ((prev: ChatMessage[]) => ChatMessage[])
24
25
  ) => void;
25
26
  setMessage: (
26
27
  id: string,
27
- partial:
28
- | Partial<ChatMessage>
29
- | ((msg: ChatMessage) => Partial<ChatMessage>),
28
+ partial: Partial<ChatMessage> | ((msg: ChatMessage) => Partial<ChatMessage>)
30
29
  ) => void;
31
30
  removeMessage: (id: string) => void;
32
31
  setSuggestions: (items: SuggestionItem[]) => void;
@@ -36,6 +35,26 @@ interface ChatState {
36
35
  loadSession: (messages: ChatMessage[]) => void;
37
36
  }
38
37
 
38
+ // 全局 store 管理器 — 多会话内存常驻
39
+ const chatStoreMap = new Map<string, ReturnType<typeof createChatStore>>();
40
+
41
+ export function getOrCreateChatStore(key: string) {
42
+ let store = chatStoreMap.get(key);
43
+ if (!store) {
44
+ store = createChatStore();
45
+ chatStoreMap.set(key, store);
46
+ }
47
+ return store;
48
+ }
49
+
50
+ export function deleteChatStore(key: string) {
51
+ chatStoreMap.delete(key);
52
+ }
53
+
54
+ export function getChatStoreMessages(key: string) {
55
+ return chatStoreMap.get(key)?.getState()?.messages;
56
+ }
57
+
39
58
  export const createChatStore = () =>
40
59
  create<ChatState>((set, get) => ({
41
60
  messages: [],
@@ -3,8 +3,8 @@
3
3
  * 使用 ChatStorage 抽象,不直接依赖 AsyncStorage
4
4
  */
5
5
 
6
- import type {ChatMessage} from '../types/message';
7
- import type {ChatStorage} from './storage';
6
+ import type { ChatMessage } from '../types/message';
7
+ import type { ChatStorage } from './storage';
8
8
 
9
9
  const MAX_SESSIONS = 50;
10
10
  const MESSAGE_KEY_PREFIX = 'chat-session-';
@@ -24,6 +24,11 @@ export interface HistoryStore {
24
24
  title: string,
25
25
  messages: ChatMessage[]
26
26
  ) => Promise<void>;
27
+ saveSession: (
28
+ id: string,
29
+ title: string,
30
+ messages: ChatMessage[]
31
+ ) => Promise<void>;
27
32
  loadSessionMessages: (id: string) => Promise<ChatMessage[]>;
28
33
  deleteSession: (id: string) => Promise<void>;
29
34
  clearAll: () => Promise<void>;
@@ -81,9 +86,43 @@ export function createHistoryStore(storage: ChatStorage): HistoryStore {
81
86
  if (sessions.length > MAX_SESSIONS) {
82
87
  const removed = sessions.splice(MAX_SESSIONS);
83
88
  await Promise.all(
84
- removed.map((s) =>
85
- storage.removeItem(`${MESSAGE_KEY_PREFIX}${s.id}`)
86
- )
89
+ removed.map((s) => storage.removeItem(`${MESSAGE_KEY_PREFIX}${s.id}`))
90
+ );
91
+ }
92
+
93
+ await saveIndex();
94
+ },
95
+
96
+ saveSession: async (id, title, messages) => {
97
+ await loadIndex();
98
+ if (messages.length === 0) return;
99
+
100
+ await storage.setItem(
101
+ `${MESSAGE_KEY_PREFIX}${id}`,
102
+ JSON.stringify(messages)
103
+ );
104
+
105
+ const lastMsg = messages[0];
106
+ const summary: SessionSummary = {
107
+ id,
108
+ title,
109
+ lastMessage: lastMsg?.text?.slice(0, 50) ?? '',
110
+ timestamp: Date.now(),
111
+ messageCount: messages.length,
112
+ };
113
+
114
+ const idx = sessions.findIndex((s) => s.id === id);
115
+ if (idx >= 0) {
116
+ sessions[idx] = summary;
117
+ } else {
118
+ sessions.unshift(summary);
119
+ }
120
+
121
+ // FIFO 淘汰
122
+ if (sessions.length > MAX_SESSIONS) {
123
+ const removed = sessions.splice(MAX_SESSIONS);
124
+ await Promise.all(
125
+ removed.map((s) => storage.removeItem(`${MESSAGE_KEY_PREFIX}${s.id}`))
87
126
  );
88
127
  }
89
128
 
@@ -106,9 +145,7 @@ export function createHistoryStore(storage: ChatStorage): HistoryStore {
106
145
  clearAll: async () => {
107
146
  await loadIndex();
108
147
  await Promise.all(
109
- sessions.map((s) =>
110
- storage.removeItem(`${MESSAGE_KEY_PREFIX}${s.id}`)
111
- )
148
+ sessions.map((s) => storage.removeItem(`${MESSAGE_KEY_PREFIX}${s.id}`))
112
149
  );
113
150
  sessions = [];
114
151
  await saveIndex();
@@ -3,7 +3,7 @@
3
3
  * 内部 store,通过 useXModel hook 封装后对外暴露
4
4
  */
5
5
 
6
- import {create} from 'zustand';
6
+ import { create } from 'zustand';
7
7
 
8
8
  interface ModelState {
9
9
  selectedModel: string;
@@ -3,7 +3,7 @@
3
3
  * 内部 store,通过 useXConversations hook 封装后对外暴露
4
4
  */
5
5
 
6
- import {create} from 'zustand';
6
+ import { create } from 'zustand';
7
7
 
8
8
  interface SessionState {
9
9
  sessionId: string;
@@ -5,7 +5,7 @@
5
5
  * - 每轮对话调用 reset() 重置
6
6
  */
7
7
 
8
- import type {SSEEnvelope} from '../types/sse';
8
+ import type { SSEEnvelope } from '../types/sse';
9
9
 
10
10
  export class SSEParser {
11
11
  private processedIds = new Set<string>();
@@ -57,7 +57,7 @@ export class XRequest {
57
57
  try {
58
58
  const token = await getToken();
59
59
  if (token) {
60
- reqHeaders['Authorization'] = `Bearer ${token}`;
60
+ reqHeaders.Authorization = `Bearer ${token}`;
61
61
  }
62
62
  } catch {
63
63
  // token 获取失败,继续无认证请求
@@ -61,7 +61,6 @@ export class XStream {
61
61
  console.log(TAG, '连接', url, `timeout=${timeout}ms`);
62
62
 
63
63
  // react-native-sse 动态 require,避免非 RN 环境报错
64
- // eslint-disable-next-line @typescript-eslint/no-var-requires
65
64
  const RNEventSource = require('react-native-sse').default;
66
65
 
67
66
  const es = new RNEventSource(url, {
@@ -3,8 +3,8 @@
3
3
  * 定义 ChatProvider ↔ useXChat 之间的数据契约
4
4
  */
5
5
 
6
- import type {ChatMessage} from './message';
7
- import type {SuggestionItem} from './sse';
6
+ import type { ChatMessage } from './message';
7
+ import type { SuggestionItem } from './sse';
8
8
 
9
9
  export interface RequestParams<T = ChatMessage> {
10
10
  message: T;
@@ -1,188 +0,0 @@
1
- ---
2
- title: SDK 概览
3
- nav:
4
- title: SDK
5
- path: /sdk
6
- ---
7
-
8
- # @unif/react-native-chat-sdk
9
-
10
- 聊天 SDK 包,提供 Provider 抽象、Hooks、状态管理和流式处理工具。
11
-
12
- ## 架构
13
-
14
- ```
15
- ┌─────────────────────────────────────────┐
16
- │ useXChat (Hook) │
17
- │ 组合 Provider + store,输出 messages │
18
- ├─────────────────────────────────────────┤
19
- │ ChatProvider 层 │
20
- │ AbstractChatProvider → OpenAI/DeepSeek │
21
- ├─────────────────────────────────────────┤
22
- │ 工具层 │
23
- │ XRequest → XStream → SSEParser │
24
- ├─────────────────────────────────────────┤
25
- │ 数据层 │
26
- │ chatStore / sessionStore / modelStore │
27
- └─────────────────────────────────────────┘
28
- ```
29
-
30
- ## 核心 Hooks
31
-
32
- ### useXChat — 聊天操作
33
-
34
- ```tsx
35
- import { useXChat, OpenAIChatProvider, XRequest } from '@unif/react-native-chat-sdk';
36
-
37
- const request = new XRequest({
38
- baseURL: 'https://api.openai.com',
39
- getToken: async () => 'sk-...',
40
- });
41
- const provider = new OpenAIChatProvider({ request, model: 'gpt-4o' });
42
-
43
- const { messages, requesting, onRequest, abort } = useXChat({ provider });
44
-
45
- // 发起请求
46
- onRequest({ message: { text: '你好' } });
47
-
48
- // 中止请求
49
- abort();
50
- ```
51
-
52
- **返回值:**
53
-
54
- | 属性 | 说明 | 类型 |
55
- |------|------|------|
56
- | messages | 可渲染消息列表 | `MessageInfo<Message>[]` |
57
- | requesting | 是否请求中 | `boolean` |
58
- | suggestions | 建议提示 | `SuggestionItem[]` |
59
- | onRequest | 发起请求 | `(input: Input) => void` |
60
- | abort | 中止请求 | `() => void` |
61
-
62
- ### useXConversations — 会话管理
63
-
64
- ```tsx
65
- import { useXConversations } from '@unif/react-native-chat-sdk';
66
- import AsyncStorage from '@react-native-async-storage/async-storage';
67
-
68
- const {
69
- sessions, activeId,
70
- switchSession, newSession, deleteSession,
71
- } = useXConversations({ storage: AsyncStorage });
72
- ```
73
-
74
- ### useXModel — 模型选择
75
-
76
- ```tsx
77
- import { useXModel } from '@unif/react-native-chat-sdk';
78
-
79
- const { selectedModel, setSelectedModel } = useXModel({
80
- models: [
81
- { id: 'gpt-4o', name: 'GPT-4o', desc: '最强模型' },
82
- { id: 'gpt-4o-mini', name: 'GPT-4o Mini', desc: '快速响应' },
83
- ],
84
- defaultModel: 'gpt-4o',
85
- });
86
- ```
87
-
88
- ## Provider 体系
89
-
90
- ### 内置 Provider
91
-
92
- | Provider | 说明 |
93
- |----------|------|
94
- | `OpenAIChatProvider` | 兼容 OpenAI API 格式(含 Azure、Moonshot、通义千问等) |
95
- | `DeepSeekChatProvider` | 继承 OpenAI,额外处理 `reasoning_content` 字段 |
96
-
97
- ### 自定义 Provider
98
-
99
- 继承 `AbstractChatProvider`,实现 3 个抽象方法:
100
-
101
- ```tsx
102
- import { AbstractChatProvider } from '@unif/react-native-chat-sdk';
103
-
104
- class MyProvider extends AbstractChatProvider {
105
- transformParams(input) {
106
- // 转换请求参数为你的 API 格式
107
- return { query: input.message.text, model: input.model };
108
- }
109
-
110
- transformLocalMessage(input) {
111
- // 创建本地用户消息
112
- return { id: generateId(), text: input.message.text, role: 'user', status: 'local', ... };
113
- }
114
-
115
- transformMessage(output, current) {
116
- // 解析流式响应,累积到 assistant 消息
117
- const data = JSON.parse(output.data);
118
- return { ...current, text: (current?.text || '') + data.content, status: 'updating' };
119
- }
120
- }
121
- ```
122
-
123
- ## 工具类
124
-
125
- ### XRequest
126
-
127
- 面向 LLM 的 HTTP 请求工具,内置 token 注入和 SSE 解析。
128
-
129
- ```tsx
130
- const request = new XRequest({
131
- baseURL: 'https://api.example.com',
132
- endpoint: '/v1/chat/completions',
133
- getToken: async () => await loadToken(),
134
- timeout: 120000,
135
- });
136
- ```
137
-
138
- ### XStream
139
-
140
- SSE 流适配器(RN 原生实现,基于 react-native-sse)。
141
-
142
- ### SSEParser
143
-
144
- SSE 解析器,提供 `event_id` 幂等去重和 `seq` 严格排序。
145
-
146
- ## ChatProvider — 全局模式
147
-
148
- ```tsx
149
- import { ChatProvider, useChatContext } from '@unif/react-native-chat-sdk';
150
-
151
- // 根组件
152
- <ChatProvider provider={provider} storage={AsyncStorage} models={MODELS}>
153
- <App />
154
- </ChatProvider>
155
-
156
- // 子组件
157
- const { messages, onRequest, sessions, selectedModel } = useChatContext();
158
- ```
159
-
160
- ## 类型定义
161
-
162
- ### ChatMessage
163
-
164
- ```typescript
165
- interface ChatMessage {
166
- id: string;
167
- text: string;
168
- role: 'user' | 'assistant' | 'system';
169
- createdAt: Date;
170
- messageType: 'text' | 'card' | 'system';
171
- status: 'local' | 'loading' | 'updating' | 'success' | 'error' | 'abort';
172
- cardType?: string;
173
- cardData?: { data: Record<string, unknown>; actions: string[] };
174
- turnId: string;
175
- extra?: Record<string, unknown>;
176
- }
177
- ```
178
-
179
- ### MessageInfo
180
-
181
- ```typescript
182
- interface MessageInfo<Message> {
183
- id: string;
184
- message: Message;
185
- status: MessageStatus;
186
- extra?: Record<string, unknown>;
187
- }
188
- ```
@@ -1,188 +0,0 @@
1
- ---
2
- title: SDK 概览
3
- nav:
4
- title: SDK
5
- path: /sdk
6
- ---
7
-
8
- # @unif/react-native-chat-sdk
9
-
10
- 聊天 SDK 包,提供 Provider 抽象、Hooks、状态管理和流式处理工具。
11
-
12
- ## 架构
13
-
14
- ```
15
- ┌─────────────────────────────────────────┐
16
- │ useXChat (Hook) │
17
- │ 组合 Provider + store,输出 messages │
18
- ├─────────────────────────────────────────┤
19
- │ ChatProvider 层 │
20
- │ AbstractChatProvider → OpenAI/DeepSeek │
21
- ├─────────────────────────────────────────┤
22
- │ 工具层 │
23
- │ XRequest → XStream → SSEParser │
24
- ├─────────────────────────────────────────┤
25
- │ 数据层 │
26
- │ chatStore / sessionStore / modelStore │
27
- └─────────────────────────────────────────┘
28
- ```
29
-
30
- ## 核心 Hooks
31
-
32
- ### useXChat — 聊天操作
33
-
34
- ```tsx
35
- import { useXChat, OpenAIChatProvider, XRequest } from '@unif/react-native-chat-sdk';
36
-
37
- const request = new XRequest({
38
- baseURL: 'https://api.openai.com',
39
- getToken: async () => 'sk-...',
40
- });
41
- const provider = new OpenAIChatProvider({ request, model: 'gpt-4o' });
42
-
43
- const { messages, requesting, onRequest, abort } = useXChat({ provider });
44
-
45
- // 发起请求
46
- onRequest({ message: { text: '你好' } });
47
-
48
- // 中止请求
49
- abort();
50
- ```
51
-
52
- **返回值:**
53
-
54
- | 属性 | 说明 | 类型 |
55
- |------|------|------|
56
- | messages | 可渲染消息列表 | `MessageInfo<Message>[]` |
57
- | requesting | 是否请求中 | `boolean` |
58
- | suggestions | 建议提示 | `SuggestionItem[]` |
59
- | onRequest | 发起请求 | `(input: Input) => void` |
60
- | abort | 中止请求 | `() => void` |
61
-
62
- ### useXConversations — 会话管理
63
-
64
- ```tsx
65
- import { useXConversations } from '@unif/react-native-chat-sdk';
66
- import AsyncStorage from '@react-native-async-storage/async-storage';
67
-
68
- const {
69
- sessions, activeId,
70
- switchSession, newSession, deleteSession,
71
- } = useXConversations({ storage: AsyncStorage });
72
- ```
73
-
74
- ### useXModel — 模型选择
75
-
76
- ```tsx
77
- import { useXModel } from '@unif/react-native-chat-sdk';
78
-
79
- const { selectedModel, setSelectedModel } = useXModel({
80
- models: [
81
- { id: 'gpt-4o', name: 'GPT-4o', desc: '最强模型' },
82
- { id: 'gpt-4o-mini', name: 'GPT-4o Mini', desc: '快速响应' },
83
- ],
84
- defaultModel: 'gpt-4o',
85
- });
86
- ```
87
-
88
- ## Provider 体系
89
-
90
- ### 内置 Provider
91
-
92
- | Provider | 说明 |
93
- |----------|------|
94
- | `OpenAIChatProvider` | 兼容 OpenAI API 格式(含 Azure、Moonshot、通义千问等) |
95
- | `DeepSeekChatProvider` | 继承 OpenAI,额外处理 `reasoning_content` 字段 |
96
-
97
- ### 自定义 Provider
98
-
99
- 继承 `AbstractChatProvider`,实现 3 个抽象方法:
100
-
101
- ```tsx
102
- import { AbstractChatProvider } from '@unif/react-native-chat-sdk';
103
-
104
- class MyProvider extends AbstractChatProvider {
105
- transformParams(input) {
106
- // 转换请求参数为你的 API 格式
107
- return { query: input.message.text, model: input.model };
108
- }
109
-
110
- transformLocalMessage(input) {
111
- // 创建本地用户消息
112
- return { id: generateId(), text: input.message.text, role: 'user', status: 'local', ... };
113
- }
114
-
115
- transformMessage(output, current) {
116
- // 解析流式响应,累积到 assistant 消息
117
- const data = JSON.parse(output.data);
118
- return { ...current, text: (current?.text || '') + data.content, status: 'updating' };
119
- }
120
- }
121
- ```
122
-
123
- ## 工具类
124
-
125
- ### XRequest
126
-
127
- 面向 LLM 的 HTTP 请求工具,内置 token 注入和 SSE 解析。
128
-
129
- ```tsx
130
- const request = new XRequest({
131
- baseURL: 'https://api.example.com',
132
- endpoint: '/v1/chat/completions',
133
- getToken: async () => await loadToken(),
134
- timeout: 120000,
135
- });
136
- ```
137
-
138
- ### XStream
139
-
140
- SSE 流适配器(RN 原生实现,基于 react-native-sse)。
141
-
142
- ### SSEParser
143
-
144
- SSE 解析器,提供 `event_id` 幂等去重和 `seq` 严格排序。
145
-
146
- ## ChatProvider — 全局模式
147
-
148
- ```tsx
149
- import { ChatProvider, useChatContext } from '@unif/react-native-chat-sdk';
150
-
151
- // 根组件
152
- <ChatProvider provider={provider} storage={AsyncStorage} models={MODELS}>
153
- <App />
154
- </ChatProvider>
155
-
156
- // 子组件
157
- const { messages, onRequest, sessions, selectedModel } = useChatContext();
158
- ```
159
-
160
- ## 类型定义
161
-
162
- ### ChatMessage
163
-
164
- ```typescript
165
- interface ChatMessage {
166
- id: string;
167
- text: string;
168
- role: 'user' | 'assistant' | 'system';
169
- createdAt: Date;
170
- messageType: 'text' | 'card' | 'system';
171
- status: 'local' | 'loading' | 'updating' | 'success' | 'error' | 'abort';
172
- cardType?: string;
173
- cardData?: { data: Record<string, unknown>; actions: string[] };
174
- turnId: string;
175
- extra?: Record<string, unknown>;
176
- }
177
- ```
178
-
179
- ### MessageInfo
180
-
181
- ```typescript
182
- interface MessageInfo<Message> {
183
- id: string;
184
- message: Message;
185
- status: MessageStatus;
186
- extra?: Record<string, unknown>;
187
- }
188
- ```