@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.
- package/lib/commonjs/hooks/ChatProvider.js +6 -5
- package/lib/commonjs/hooks/ChatProvider.js.map +1 -1
- package/lib/commonjs/hooks/useXChat.js +3 -11
- package/lib/commonjs/hooks/useXChat.js.map +1 -1
- package/lib/commonjs/hooks/useXConversations.js +24 -4
- package/lib/commonjs/hooks/useXConversations.js.map +1 -1
- package/lib/commonjs/hooks/useXModel.js.map +1 -1
- package/lib/commonjs/index.js +19 -0
- package/lib/commonjs/index.js.map +1 -1
- package/lib/commonjs/providers/AbstractChatProvider.js.map +1 -1
- package/lib/commonjs/providers/DeepSeekChatProvider.js.map +1 -1
- package/lib/commonjs/providers/OpenAIChatProvider.js +1 -1
- package/lib/commonjs/providers/OpenAIChatProvider.js.map +1 -1
- package/lib/commonjs/stores/chatStore.js +19 -0
- package/lib/commonjs/stores/chatStore.js.map +1 -1
- package/lib/commonjs/stores/historyStore.js +26 -0
- package/lib/commonjs/stores/historyStore.js.map +1 -1
- package/lib/commonjs/tools/XRequest.js +1 -1
- package/lib/commonjs/tools/XRequest.js.map +1 -1
- package/lib/commonjs/tools/XStream.js +0 -1
- package/lib/commonjs/tools/XStream.js.map +1 -1
- package/lib/module/hooks/ChatProvider.js +6 -5
- package/lib/module/hooks/ChatProvider.js.map +1 -1
- package/lib/module/hooks/useXChat.js +5 -13
- package/lib/module/hooks/useXChat.js.map +1 -1
- package/lib/module/hooks/useXConversations.js +24 -4
- package/lib/module/hooks/useXConversations.js.map +1 -1
- package/lib/module/hooks/useXModel.js.map +1 -1
- package/lib/module/index.js +2 -0
- package/lib/module/index.js.map +1 -1
- package/lib/module/providers/AbstractChatProvider.js.map +1 -1
- package/lib/module/providers/DeepSeekChatProvider.js.map +1 -1
- package/lib/module/providers/OpenAIChatProvider.js +1 -1
- package/lib/module/providers/OpenAIChatProvider.js.map +1 -1
- package/lib/module/stores/chatStore.js +16 -0
- package/lib/module/stores/chatStore.js.map +1 -1
- package/lib/module/stores/historyStore.js +26 -0
- package/lib/module/stores/historyStore.js.map +1 -1
- package/lib/module/stores/modelStore.js.map +1 -1
- package/lib/module/stores/sessionStore.js.map +1 -1
- package/lib/module/tools/XRequest.js +1 -1
- package/lib/module/tools/XRequest.js.map +1 -1
- package/lib/module/tools/XStream.js +0 -1
- package/lib/module/tools/XStream.js.map +1 -1
- package/lib/typescript/commonjs/hooks/ChatProvider.d.ts +3 -2
- package/lib/typescript/commonjs/hooks/ChatProvider.d.ts.map +1 -1
- package/lib/typescript/commonjs/hooks/useXChat.d.ts +1 -2
- package/lib/typescript/commonjs/hooks/useXChat.d.ts.map +1 -1
- package/lib/typescript/commonjs/hooks/useXConversations.d.ts +3 -0
- package/lib/typescript/commonjs/hooks/useXConversations.d.ts.map +1 -1
- package/lib/typescript/commonjs/index.d.ts +3 -2
- package/lib/typescript/commonjs/index.d.ts.map +1 -1
- package/lib/typescript/commonjs/providers/AbstractChatProvider.d.ts.map +1 -1
- package/lib/typescript/commonjs/providers/DeepSeekChatProvider.d.ts.map +1 -1
- package/lib/typescript/commonjs/providers/OpenAIChatProvider.d.ts.map +1 -1
- package/lib/typescript/commonjs/stores/chatStore.d.ts +3 -0
- package/lib/typescript/commonjs/stores/chatStore.d.ts.map +1 -1
- package/lib/typescript/commonjs/stores/historyStore.d.ts +1 -0
- package/lib/typescript/commonjs/stores/historyStore.d.ts.map +1 -1
- package/lib/typescript/commonjs/tools/SSEParser.d.ts.map +1 -1
- package/lib/typescript/commonjs/tools/XStream.d.ts.map +1 -1
- package/lib/typescript/commonjs/types/provider.d.ts.map +1 -1
- package/lib/typescript/module/hooks/ChatProvider.d.ts +3 -2
- package/lib/typescript/module/hooks/ChatProvider.d.ts.map +1 -1
- package/lib/typescript/module/hooks/useXChat.d.ts +1 -2
- package/lib/typescript/module/hooks/useXChat.d.ts.map +1 -1
- package/lib/typescript/module/hooks/useXConversations.d.ts +3 -0
- package/lib/typescript/module/hooks/useXConversations.d.ts.map +1 -1
- package/lib/typescript/module/index.d.ts +3 -2
- package/lib/typescript/module/index.d.ts.map +1 -1
- package/lib/typescript/module/providers/AbstractChatProvider.d.ts.map +1 -1
- package/lib/typescript/module/providers/DeepSeekChatProvider.d.ts.map +1 -1
- package/lib/typescript/module/providers/OpenAIChatProvider.d.ts.map +1 -1
- package/lib/typescript/module/stores/chatStore.d.ts +3 -0
- package/lib/typescript/module/stores/chatStore.d.ts.map +1 -1
- package/lib/typescript/module/stores/historyStore.d.ts +1 -0
- package/lib/typescript/module/stores/historyStore.d.ts.map +1 -1
- package/lib/typescript/module/tools/SSEParser.d.ts.map +1 -1
- package/lib/typescript/module/tools/XStream.d.ts.map +1 -1
- package/lib/typescript/module/types/provider.d.ts.map +1 -1
- package/package.json +1 -1
- package/src/hooks/ChatProvider.tsx +24 -12
- package/src/hooks/useXChat.ts +11 -23
- package/src/hooks/useXConversations.ts +39 -10
- package/src/hooks/useXModel.ts +2 -2
- package/src/index.ts +31 -19
- package/src/providers/AbstractChatProvider.ts +7 -3
- package/src/providers/DeepSeekChatProvider.ts +4 -7
- package/src/providers/OpenAIChatProvider.ts +6 -6
- package/src/stores/chatStore.ts +29 -10
- package/src/stores/historyStore.ts +45 -8
- package/src/stores/modelStore.ts +1 -1
- package/src/stores/sessionStore.ts +1 -1
- package/src/tools/SSEParser.ts +1 -1
- package/src/tools/XRequest.ts +1 -1
- package/src/tools/XStream.ts +0 -1
- package/src/types/provider.ts +2 -2
- package/lib/commonjs/index.md +0 -188
- package/lib/module/index.md +0 -188
- 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
|
|
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
|
|
package/src/stores/chatStore.ts
CHANGED
|
@@ -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: (
|
|
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
|
-
|
|
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();
|
package/src/stores/modelStore.ts
CHANGED
package/src/tools/SSEParser.ts
CHANGED
package/src/tools/XRequest.ts
CHANGED
package/src/tools/XStream.ts
CHANGED
|
@@ -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, {
|
package/src/types/provider.ts
CHANGED
|
@@ -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;
|
package/lib/commonjs/index.md
DELETED
|
@@ -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
|
-
```
|
package/lib/module/index.md
DELETED
|
@@ -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
|
-
```
|