@unif/react-native-chat-sdk 0.1.0 → 0.1.2

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 (165) hide show
  1. package/README.md +252 -0
  2. package/lib/commonjs/hooks/ChatProvider.js +76 -0
  3. package/lib/commonjs/hooks/ChatProvider.js.map +1 -0
  4. package/lib/commonjs/hooks/useXChat.js +95 -0
  5. package/lib/commonjs/hooks/useXChat.js.map +1 -0
  6. package/lib/commonjs/hooks/useXConversations.js +69 -0
  7. package/lib/commonjs/hooks/useXConversations.js.map +1 -0
  8. package/lib/commonjs/hooks/useXModel.js +27 -0
  9. package/lib/commonjs/hooks/useXModel.js.map +1 -0
  10. package/lib/commonjs/index.js +82 -0
  11. package/lib/commonjs/index.js.map +1 -0
  12. package/lib/commonjs/index.md +188 -0
  13. package/lib/commonjs/package.json +1 -0
  14. package/lib/commonjs/providers/AbstractChatProvider.js +64 -0
  15. package/lib/commonjs/providers/AbstractChatProvider.js.map +1 -0
  16. package/lib/commonjs/providers/DeepSeekChatProvider.js +88 -0
  17. package/lib/commonjs/providers/DeepSeekChatProvider.js.map +1 -0
  18. package/lib/commonjs/providers/OpenAIChatProvider.js +114 -0
  19. package/lib/commonjs/providers/OpenAIChatProvider.js.map +1 -0
  20. package/lib/commonjs/stores/chatStore.js +65 -0
  21. package/lib/commonjs/stores/chatStore.js.map +1 -0
  22. package/lib/commonjs/stores/historyStore.js +79 -0
  23. package/lib/commonjs/stores/historyStore.js.map +1 -0
  24. package/lib/commonjs/stores/modelStore.js +20 -0
  25. package/lib/commonjs/stores/modelStore.js.map +1 -0
  26. package/lib/commonjs/stores/sessionStore.js +24 -0
  27. package/lib/commonjs/stores/sessionStore.js.map +1 -0
  28. package/lib/commonjs/stores/storage.js +2 -0
  29. package/lib/commonjs/stores/storage.js.map +1 -0
  30. package/lib/commonjs/tools/SSEParser.js +56 -0
  31. package/lib/commonjs/tools/SSEParser.js.map +1 -0
  32. package/lib/commonjs/tools/XRequest.js +87 -0
  33. package/lib/commonjs/tools/XRequest.js.map +1 -0
  34. package/lib/commonjs/tools/XStream.js +84 -0
  35. package/lib/commonjs/tools/XStream.js.map +1 -0
  36. package/lib/commonjs/types/message.js +2 -0
  37. package/lib/commonjs/types/message.js.map +1 -0
  38. package/lib/commonjs/types/provider.js +6 -0
  39. package/lib/commonjs/types/provider.js.map +1 -0
  40. package/lib/commonjs/types/sse.js +2 -0
  41. package/lib/commonjs/types/sse.js.map +1 -0
  42. package/lib/module/hooks/ChatProvider.js +70 -0
  43. package/lib/module/hooks/ChatProvider.js.map +1 -0
  44. package/lib/module/hooks/useXChat.js +91 -0
  45. package/lib/module/hooks/useXChat.js.map +1 -0
  46. package/lib/module/hooks/useXConversations.js +65 -0
  47. package/lib/module/hooks/useXConversations.js.map +1 -0
  48. package/lib/module/hooks/useXModel.js +23 -0
  49. package/lib/module/hooks/useXModel.js.map +1 -0
  50. package/lib/module/index.js +27 -0
  51. package/lib/module/index.js.map +1 -0
  52. package/lib/module/index.md +188 -0
  53. package/lib/module/package.json +1 -0
  54. package/lib/module/providers/AbstractChatProvider.js +59 -0
  55. package/lib/module/providers/AbstractChatProvider.js.map +1 -0
  56. package/lib/module/providers/DeepSeekChatProvider.js +83 -0
  57. package/lib/module/providers/DeepSeekChatProvider.js.map +1 -0
  58. package/lib/module/providers/OpenAIChatProvider.js +109 -0
  59. package/lib/module/providers/OpenAIChatProvider.js.map +1 -0
  60. package/lib/module/stores/chatStore.js +60 -0
  61. package/lib/module/stores/chatStore.js.map +1 -0
  62. package/lib/module/stores/historyStore.js +75 -0
  63. package/lib/module/stores/historyStore.js.map +1 -0
  64. package/lib/module/stores/modelStore.js +15 -0
  65. package/lib/module/stores/modelStore.js.map +1 -0
  66. package/lib/module/stores/sessionStore.js +19 -0
  67. package/lib/module/stores/sessionStore.js.map +1 -0
  68. package/lib/module/stores/storage.js +2 -0
  69. package/lib/module/stores/storage.js.map +1 -0
  70. package/lib/module/tools/SSEParser.js +51 -0
  71. package/lib/module/tools/SSEParser.js.map +1 -0
  72. package/lib/module/tools/XRequest.js +82 -0
  73. package/lib/module/tools/XRequest.js.map +1 -0
  74. package/lib/module/tools/XStream.js +79 -0
  75. package/lib/module/tools/XStream.js.map +1 -0
  76. package/lib/module/types/message.js +2 -0
  77. package/lib/module/types/message.js.map +1 -0
  78. package/lib/module/types/provider.js +4 -0
  79. package/lib/module/types/provider.js.map +1 -0
  80. package/lib/module/types/sse.js +2 -0
  81. package/lib/module/types/sse.js.map +1 -0
  82. package/lib/typescript/commonjs/hooks/ChatProvider.d.ts +50 -0
  83. package/lib/typescript/commonjs/hooks/ChatProvider.d.ts.map +1 -0
  84. package/lib/typescript/commonjs/hooks/useXChat.d.ts +36 -0
  85. package/lib/typescript/commonjs/hooks/useXChat.d.ts.map +1 -0
  86. package/lib/typescript/commonjs/hooks/useXConversations.d.ts +24 -0
  87. package/lib/typescript/commonjs/hooks/useXConversations.d.ts.map +1 -0
  88. package/lib/typescript/commonjs/hooks/useXModel.d.ts +18 -0
  89. package/lib/typescript/commonjs/hooks/useXModel.d.ts.map +1 -0
  90. package/lib/typescript/commonjs/index.d.ts +27 -0
  91. package/lib/typescript/commonjs/index.d.ts.map +1 -0
  92. package/lib/typescript/commonjs/package.json +1 -0
  93. package/lib/typescript/commonjs/providers/AbstractChatProvider.d.ts +38 -0
  94. package/lib/typescript/commonjs/providers/AbstractChatProvider.d.ts.map +1 -0
  95. package/lib/typescript/commonjs/providers/DeepSeekChatProvider.d.ts +23 -0
  96. package/lib/typescript/commonjs/providers/DeepSeekChatProvider.d.ts.map +1 -0
  97. package/lib/typescript/commonjs/providers/OpenAIChatProvider.d.ts +33 -0
  98. package/lib/typescript/commonjs/providers/OpenAIChatProvider.d.ts.map +1 -0
  99. package/lib/typescript/commonjs/stores/chatStore.d.ts +24 -0
  100. package/lib/typescript/commonjs/stores/chatStore.d.ts.map +1 -0
  101. package/lib/typescript/commonjs/stores/historyStore.d.ts +22 -0
  102. package/lib/typescript/commonjs/stores/historyStore.d.ts.map +1 -0
  103. package/lib/typescript/commonjs/stores/modelStore.d.ts +11 -0
  104. package/lib/typescript/commonjs/stores/modelStore.d.ts.map +1 -0
  105. package/lib/typescript/commonjs/stores/sessionStore.d.ts +13 -0
  106. package/lib/typescript/commonjs/stores/sessionStore.d.ts.map +1 -0
  107. package/lib/typescript/commonjs/stores/storage.d.ts +10 -0
  108. package/lib/typescript/commonjs/stores/storage.d.ts.map +1 -0
  109. package/lib/typescript/commonjs/tools/SSEParser.d.ts +19 -0
  110. package/lib/typescript/commonjs/tools/SSEParser.d.ts.map +1 -0
  111. package/lib/typescript/commonjs/tools/XRequest.d.ts +33 -0
  112. package/lib/typescript/commonjs/tools/XRequest.d.ts.map +1 -0
  113. package/lib/typescript/commonjs/tools/XStream.d.ts +34 -0
  114. package/lib/typescript/commonjs/tools/XStream.d.ts.map +1 -0
  115. package/lib/typescript/commonjs/types/message.d.ts +22 -0
  116. package/lib/typescript/commonjs/types/message.d.ts.map +1 -0
  117. package/lib/typescript/commonjs/types/provider.d.ts +23 -0
  118. package/lib/typescript/commonjs/types/provider.d.ts.map +1 -0
  119. package/lib/typescript/commonjs/types/sse.d.ts +63 -0
  120. package/lib/typescript/commonjs/types/sse.d.ts.map +1 -0
  121. package/lib/typescript/module/hooks/ChatProvider.d.ts +50 -0
  122. package/lib/typescript/module/hooks/ChatProvider.d.ts.map +1 -0
  123. package/lib/typescript/module/hooks/useXChat.d.ts +36 -0
  124. package/lib/typescript/module/hooks/useXChat.d.ts.map +1 -0
  125. package/lib/typescript/module/hooks/useXConversations.d.ts +24 -0
  126. package/lib/typescript/module/hooks/useXConversations.d.ts.map +1 -0
  127. package/lib/typescript/module/hooks/useXModel.d.ts +18 -0
  128. package/lib/typescript/module/hooks/useXModel.d.ts.map +1 -0
  129. package/lib/typescript/module/index.d.ts +27 -0
  130. package/lib/typescript/module/index.d.ts.map +1 -0
  131. package/lib/typescript/module/package.json +1 -0
  132. package/lib/typescript/module/providers/AbstractChatProvider.d.ts +38 -0
  133. package/lib/typescript/module/providers/AbstractChatProvider.d.ts.map +1 -0
  134. package/lib/typescript/module/providers/DeepSeekChatProvider.d.ts +23 -0
  135. package/lib/typescript/module/providers/DeepSeekChatProvider.d.ts.map +1 -0
  136. package/lib/typescript/module/providers/OpenAIChatProvider.d.ts +33 -0
  137. package/lib/typescript/module/providers/OpenAIChatProvider.d.ts.map +1 -0
  138. package/lib/typescript/module/stores/chatStore.d.ts +24 -0
  139. package/lib/typescript/module/stores/chatStore.d.ts.map +1 -0
  140. package/lib/typescript/module/stores/historyStore.d.ts +22 -0
  141. package/lib/typescript/module/stores/historyStore.d.ts.map +1 -0
  142. package/lib/typescript/module/stores/modelStore.d.ts +11 -0
  143. package/lib/typescript/module/stores/modelStore.d.ts.map +1 -0
  144. package/lib/typescript/module/stores/sessionStore.d.ts +13 -0
  145. package/lib/typescript/module/stores/sessionStore.d.ts.map +1 -0
  146. package/lib/typescript/module/stores/storage.d.ts +10 -0
  147. package/lib/typescript/module/stores/storage.d.ts.map +1 -0
  148. package/lib/typescript/module/tools/SSEParser.d.ts +19 -0
  149. package/lib/typescript/module/tools/SSEParser.d.ts.map +1 -0
  150. package/lib/typescript/module/tools/XRequest.d.ts +33 -0
  151. package/lib/typescript/module/tools/XRequest.d.ts.map +1 -0
  152. package/lib/typescript/module/tools/XStream.d.ts +34 -0
  153. package/lib/typescript/module/tools/XStream.d.ts.map +1 -0
  154. package/lib/typescript/module/types/message.d.ts +22 -0
  155. package/lib/typescript/module/types/message.d.ts.map +1 -0
  156. package/lib/typescript/module/types/provider.d.ts +23 -0
  157. package/lib/typescript/module/types/provider.d.ts.map +1 -0
  158. package/lib/typescript/module/types/sse.d.ts +63 -0
  159. package/lib/typescript/module/types/sse.d.ts.map +1 -0
  160. package/package.json +40 -8
  161. package/src/hooks/ChatProvider.tsx +5 -2
  162. package/src/hooks/useXChat.ts +37 -18
  163. package/src/index.ts +2 -1
  164. package/src/tools/XRequest.ts +12 -3
  165. package/src/types/provider.ts +2 -0
@@ -0,0 +1 @@
1
+ {"version":3,"file":"modelStore.d.ts","sourceRoot":"","sources":["../../../../src/stores/modelStore.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAIH,UAAU,UAAU;IAClB,aAAa,EAAE,MAAM,CAAC;IACtB,gBAAgB,EAAE,CAAC,EAAE,EAAE,MAAM,KAAK,IAAI,CAAC;CACxC;AAED,eAAO,MAAM,gBAAgB,GAAI,cAAc,MAAM,4EAIhD,CAAC"}
@@ -0,0 +1,13 @@
1
+ /**
2
+ * 会话状态管理(Zustand)
3
+ * 内部 store,通过 useXConversations hook 封装后对外暴露
4
+ */
5
+ interface SessionState {
6
+ sessionId: string;
7
+ sessionTitle: string;
8
+ setSessionId: (id: string) => void;
9
+ setSessionTitle: (title: string) => void;
10
+ }
11
+ export declare const createSessionStore: (generateId: () => string) => import("zustand").UseBoundStore<import("zustand").StoreApi<SessionState>>;
12
+ export {};
13
+ //# sourceMappingURL=sessionStore.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sessionStore.d.ts","sourceRoot":"","sources":["../../../../src/stores/sessionStore.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAIH,UAAU,YAAY;IACpB,SAAS,EAAE,MAAM,CAAC;IAClB,YAAY,EAAE,MAAM,CAAC;IACrB,YAAY,EAAE,CAAC,EAAE,EAAE,MAAM,KAAK,IAAI,CAAC;IACnC,eAAe,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;CAC1C;AAED,eAAO,MAAM,kBAAkB,GAAI,YAAY,MAAM,MAAM,8EAMtD,CAAC"}
@@ -0,0 +1,10 @@
1
+ /**
2
+ * ChatStorage — 存储抽象接口
3
+ * 不绑定 AsyncStorage,支持注入任意存储实现
4
+ */
5
+ export interface ChatStorage {
6
+ getItem: (key: string) => Promise<string | null>;
7
+ setItem: (key: string, value: string) => Promise<void>;
8
+ removeItem: (key: string) => Promise<void>;
9
+ }
10
+ //# sourceMappingURL=storage.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"storage.d.ts","sourceRoot":"","sources":["../../../../src/stores/storage.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,MAAM,WAAW,WAAW;IAC1B,OAAO,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAAC;IACjD,OAAO,EAAE,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IACvD,UAAU,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;CAC5C"}
@@ -0,0 +1,19 @@
1
+ /**
2
+ * SSE 解析器
3
+ * - event_id 幂等去重
4
+ * - seq 严格排序(乱序缓冲,顺序到达后 flush)
5
+ * - 每轮对话调用 reset() 重置
6
+ */
7
+ import type { SSEEnvelope } from '../types/sse';
8
+ export declare class SSEParser {
9
+ private processedIds;
10
+ private buffer;
11
+ private nextSeq;
12
+ reset(): void;
13
+ /**
14
+ * 解析原始 SSE data 字符串,返回按 seq 排序的事件数组
15
+ * 已处理的 event_id 会被自动跳过(幂等)
16
+ */
17
+ process(raw: string): SSEEnvelope[];
18
+ }
19
+ //# sourceMappingURL=SSEParser.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"SSEParser.d.ts","sourceRoot":"","sources":["../../../../src/tools/SSEParser.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,EAAC,WAAW,EAAC,MAAM,cAAc,CAAC;AAE9C,qBAAa,SAAS;IACpB,OAAO,CAAC,YAAY,CAAqB;IACzC,OAAO,CAAC,MAAM,CAAkC;IAChD,OAAO,CAAC,OAAO,CAAK;IAEpB,KAAK,IAAI,IAAI;IAMb;;;OAGG;IACH,OAAO,CAAC,GAAG,EAAE,MAAM,GAAG,WAAW,EAAE;CA2BpC"}
@@ -0,0 +1,33 @@
1
+ /**
2
+ * XRequest — 面向 LLM 的 HTTP 请求工具
3
+ *
4
+ * 组合 XStream + SSEParser 实现完整 SSE 请求链路
5
+ */
6
+ import type { SSEOutput } from '../types/provider';
7
+ export interface XRequestConfig {
8
+ baseURL: string;
9
+ endpoint?: string;
10
+ model?: string;
11
+ headers?: Record<string, string>;
12
+ timeout?: number;
13
+ getToken?: () => Promise<string | null>;
14
+ }
15
+ export interface XRequestCallbacks {
16
+ onStream?: (chunk: SSEOutput) => void;
17
+ onSuccess?: (message: string) => void;
18
+ onError?: (error: {
19
+ type: string;
20
+ message: string;
21
+ }) => void;
22
+ onAbort?: () => void;
23
+ }
24
+ export declare class XRequest {
25
+ private config;
26
+ private stream;
27
+ private parser;
28
+ constructor(config: XRequestConfig);
29
+ create(params: Record<string, unknown>, callbacks: XRequestCallbacks): Promise<void>;
30
+ abort(): void;
31
+ dispose(): void;
32
+ }
33
+ //# sourceMappingURL=XRequest.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"XRequest.d.ts","sourceRoot":"","sources":["../../../../src/tools/XRequest.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAIH,OAAO,KAAK,EAAC,SAAS,EAAC,MAAM,mBAAmB,CAAC;AAGjD,MAAM,WAAW,cAAc;IAC7B,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACjC,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,QAAQ,CAAC,EAAE,MAAM,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAAC;CACzC;AAED,MAAM,WAAW,iBAAiB;IAChC,QAAQ,CAAC,EAAE,CAAC,KAAK,EAAE,SAAS,KAAK,IAAI,CAAC;IACtC,SAAS,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,IAAI,CAAC;IACtC,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAA;KAAE,KAAK,IAAI,CAAC;IAC7D,OAAO,CAAC,EAAE,MAAM,IAAI,CAAC;CACtB;AAED,qBAAa,QAAQ;IACnB,OAAO,CAAC,MAAM,CAAiB;IAC/B,OAAO,CAAC,MAAM,CAAwB;IACtC,OAAO,CAAC,MAAM,CAAmB;gBAErB,MAAM,EAAE,cAAc;IAI5B,MAAM,CACV,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC/B,SAAS,EAAE,iBAAiB,GAC3B,OAAO,CAAC,IAAI,CAAC;IA0DhB,KAAK,IAAI,IAAI;IAOb,OAAO,IAAI,IAAI;CAGhB"}
@@ -0,0 +1,34 @@
1
+ /**
2
+ * XStream — SSE 流适配器(React Native 版本)
3
+ *
4
+ * 基于 react-native-sse 封装,支持 POST 方法 + 自定义请求体
5
+ */
6
+ import type { SSEOutput } from '../types/provider';
7
+ export interface XStreamConfig {
8
+ url: string;
9
+ method?: 'GET' | 'POST';
10
+ headers?: Record<string, string>;
11
+ body?: Record<string, unknown>;
12
+ timeout?: number;
13
+ transformStream?: (event: {
14
+ data: string;
15
+ event?: string;
16
+ }) => SSEOutput;
17
+ }
18
+ export interface XStreamCallbacks {
19
+ onMessage: (data: SSEOutput) => void;
20
+ onError?: (error: Error) => void;
21
+ onComplete?: () => void;
22
+ onOpen?: () => void;
23
+ }
24
+ export declare class XStream {
25
+ private config;
26
+ private es;
27
+ private timeoutTimer;
28
+ constructor(config: XStreamConfig);
29
+ connect(callbacks: XStreamCallbacks): void;
30
+ abort(): void;
31
+ dispose(): void;
32
+ private clearTimer;
33
+ }
34
+ //# sourceMappingURL=XStream.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"XStream.d.ts","sourceRoot":"","sources":["../../../../src/tools/XStream.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAGH,OAAO,KAAK,EAAC,SAAS,EAAC,MAAM,mBAAmB,CAAC;AAEjD,MAAM,WAAW,aAAa;IAC5B,GAAG,EAAE,MAAM,CAAC;IACZ,MAAM,CAAC,EAAE,KAAK,GAAG,MAAM,CAAC;IACxB,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACjC,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAC/B,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,eAAe,CAAC,EAAE,CAAC,KAAK,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,KAAK,CAAC,EAAE,MAAM,CAAA;KAAE,KAAK,SAAS,CAAC;CAC1E;AAED,MAAM,WAAW,gBAAgB;IAC/B,SAAS,EAAE,CAAC,IAAI,EAAE,SAAS,KAAK,IAAI,CAAC;IACrC,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,KAAK,KAAK,IAAI,CAAC;IACjC,UAAU,CAAC,EAAE,MAAM,IAAI,CAAC;IACxB,MAAM,CAAC,EAAE,MAAM,IAAI,CAAC;CACrB;AAUD,qBAAa,OAAO;IAClB,OAAO,CAAC,MAAM,CAAgB;IAC9B,OAAO,CAAC,EAAE,CAA4B;IACtC,OAAO,CAAC,YAAY,CAA8C;gBAEtD,MAAM,EAAE,aAAa;IAIjC,OAAO,CAAC,SAAS,EAAE,gBAAgB,GAAG,IAAI;IAmD1C,KAAK,IAAI,IAAI;IAQb,OAAO,IAAI,IAAI;IAIf,OAAO,CAAC,UAAU;CAMnB"}
@@ -0,0 +1,22 @@
1
+ /**
2
+ * Chat 消息类型定义
3
+ */
4
+ export type MessageRole = 'user' | 'assistant' | 'system';
5
+ export type MessageType = 'text' | 'card' | 'system';
6
+ export type MessageStatus = 'local' | 'loading' | 'updating' | 'success' | 'error' | 'abort';
7
+ export interface ChatMessage {
8
+ id: string;
9
+ text: string;
10
+ role: MessageRole;
11
+ createdAt: Date;
12
+ messageType: MessageType;
13
+ status: MessageStatus;
14
+ cardType?: string;
15
+ cardData?: {
16
+ data: Record<string, unknown>;
17
+ actions: string[];
18
+ };
19
+ turnId: string;
20
+ extra?: Record<string, unknown>;
21
+ }
22
+ //# sourceMappingURL=message.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"message.d.ts","sourceRoot":"","sources":["../../../../src/types/message.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,MAAM,MAAM,WAAW,GAAG,MAAM,GAAG,WAAW,GAAG,QAAQ,CAAC;AAC1D,MAAM,MAAM,WAAW,GAAG,MAAM,GAAG,MAAM,GAAG,QAAQ,CAAC;AACrD,MAAM,MAAM,aAAa,GACrB,OAAO,GACP,SAAS,GACT,UAAU,GACV,SAAS,GACT,OAAO,GACP,OAAO,CAAC;AAEZ,MAAM,WAAW,WAAW;IAC1B,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,WAAW,CAAC;IAClB,SAAS,EAAE,IAAI,CAAC;IAChB,WAAW,EAAE,WAAW,CAAC;IACzB,MAAM,EAAE,aAAa,CAAC;IACtB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,QAAQ,CAAC,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;QAAC,OAAO,EAAE,MAAM,EAAE,CAAA;KAAE,CAAC;IAChE,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CACjC"}
@@ -0,0 +1,23 @@
1
+ /**
2
+ * Provider 协议类型
3
+ * 定义 ChatProvider ↔ useXChat 之间的数据契约
4
+ */
5
+ import type { ChatMessage } from './message';
6
+ import type { SuggestionItem } from './sse';
7
+ export interface RequestParams<T = ChatMessage> {
8
+ message: T;
9
+ messages?: T[];
10
+ model?: string;
11
+ extra?: Record<string, unknown>;
12
+ }
13
+ export interface SSEOutput {
14
+ data: string;
15
+ event?: string;
16
+ }
17
+ export interface ProviderCallbacks<Message = ChatMessage> {
18
+ onUpdate: (message: Message) => void;
19
+ onSuccess: (message: Message) => void;
20
+ onError: (error: Error) => void;
21
+ onSuggestion?: (items: SuggestionItem[]) => void;
22
+ }
23
+ //# sourceMappingURL=provider.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"provider.d.ts","sourceRoot":"","sources":["../../../../src/types/provider.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,KAAK,EAAC,WAAW,EAAC,MAAM,WAAW,CAAC;AAC3C,OAAO,KAAK,EAAC,cAAc,EAAC,MAAM,OAAO,CAAC;AAE1C,MAAM,WAAW,aAAa,CAAC,CAAC,GAAG,WAAW;IAC5C,OAAO,EAAE,CAAC,CAAC;IACX,QAAQ,CAAC,EAAE,CAAC,EAAE,CAAC;IACf,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,KAAK,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CACjC;AAED,MAAM,WAAW,SAAS;IACxB,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,WAAW,iBAAiB,CAAC,OAAO,GAAG,WAAW;IACtD,QAAQ,EAAE,CAAC,OAAO,EAAE,OAAO,KAAK,IAAI,CAAC;IACrC,SAAS,EAAE,CAAC,OAAO,EAAE,OAAO,KAAK,IAAI,CAAC;IACtC,OAAO,EAAE,CAAC,KAAK,EAAE,KAAK,KAAK,IAAI,CAAC;IAChC,YAAY,CAAC,EAAE,CAAC,KAAK,EAAE,cAAc,EAAE,KAAK,IAAI,CAAC;CAClD"}
@@ -0,0 +1,63 @@
1
+ /**
2
+ * SSEEnvelope 协议类型定义
3
+ */
4
+ export type SSEEventType = 'text' | 'card_data' | 'suggestion' | 'error' | 'done';
5
+ export interface SSEEnvelopeBase {
6
+ event_id: string;
7
+ turn_id: string;
8
+ seq: number;
9
+ ts: string;
10
+ session_id: string;
11
+ }
12
+ export interface SSETextEvent extends SSEEnvelopeBase {
13
+ type: 'text';
14
+ payload: {
15
+ content: string;
16
+ };
17
+ }
18
+ export interface SSECardDataEvent extends SSEEnvelopeBase {
19
+ type: 'card_data';
20
+ payload: {
21
+ cardType: string;
22
+ payload: CardPayload;
23
+ };
24
+ }
25
+ export interface SSESuggestionEvent extends SSEEnvelopeBase {
26
+ type: 'suggestion';
27
+ payload: {
28
+ items: SuggestionItem[];
29
+ };
30
+ }
31
+ export interface SSEErrorEvent extends SSEEnvelopeBase {
32
+ type: 'error';
33
+ payload: {
34
+ code: string;
35
+ message: string;
36
+ retryable: boolean;
37
+ recover_actions?: ActionPayload[];
38
+ };
39
+ }
40
+ export interface SSEDoneEvent extends SSEEnvelopeBase {
41
+ type: 'done';
42
+ payload: {
43
+ messageId: string;
44
+ reason: 'ok' | 'abort' | 'error';
45
+ };
46
+ }
47
+ export type SSEEnvelope = SSETextEvent | SSECardDataEvent | SSESuggestionEvent | SSEErrorEvent | SSEDoneEvent;
48
+ export interface SuggestionItem {
49
+ id: string;
50
+ label: string;
51
+ action?: ActionPayload;
52
+ mode?: 'action' | 'input_focus';
53
+ }
54
+ export type ActionType = 'confirm_order' | 'select_product' | 'reorder' | 'add_product' | 'clear_draft' | 'push_dealer' | 'new_order' | 'view_detail' | 'add_to_order' | 'browse_products' | 'retry_order';
55
+ export interface ActionPayload {
56
+ type: ActionType;
57
+ payload?: Record<string, unknown>;
58
+ }
59
+ export interface CardPayload {
60
+ data: Record<string, unknown>;
61
+ actions: string[];
62
+ }
63
+ //# sourceMappingURL=sse.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sse.d.ts","sourceRoot":"","sources":["../../../../src/types/sse.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,MAAM,MAAM,YAAY,GACpB,MAAM,GACN,WAAW,GACX,YAAY,GACZ,OAAO,GACP,MAAM,CAAC;AAEX,MAAM,WAAW,eAAe;IAC9B,QAAQ,EAAE,MAAM,CAAC;IACjB,OAAO,EAAE,MAAM,CAAC;IAChB,GAAG,EAAE,MAAM,CAAC;IACZ,EAAE,EAAE,MAAM,CAAC;IACX,UAAU,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,YAAa,SAAQ,eAAe;IACnD,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE;QAAE,OAAO,EAAE,MAAM,CAAA;KAAE,CAAC;CAC9B;AAED,MAAM,WAAW,gBAAiB,SAAQ,eAAe;IACvD,IAAI,EAAE,WAAW,CAAC;IAClB,OAAO,EAAE;QACP,QAAQ,EAAE,MAAM,CAAC;QACjB,OAAO,EAAE,WAAW,CAAC;KACtB,CAAC;CACH;AAED,MAAM,WAAW,kBAAmB,SAAQ,eAAe;IACzD,IAAI,EAAE,YAAY,CAAC;IACnB,OAAO,EAAE;QACP,KAAK,EAAE,cAAc,EAAE,CAAC;KACzB,CAAC;CACH;AAED,MAAM,WAAW,aAAc,SAAQ,eAAe;IACpD,IAAI,EAAE,OAAO,CAAC;IACd,OAAO,EAAE;QACP,IAAI,EAAE,MAAM,CAAC;QACb,OAAO,EAAE,MAAM,CAAC;QAChB,SAAS,EAAE,OAAO,CAAC;QACnB,eAAe,CAAC,EAAE,aAAa,EAAE,CAAC;KACnC,CAAC;CACH;AAED,MAAM,WAAW,YAAa,SAAQ,eAAe;IACnD,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE;QACP,SAAS,EAAE,MAAM,CAAC;QAClB,MAAM,EAAE,IAAI,GAAG,OAAO,GAAG,OAAO,CAAC;KAClC,CAAC;CACH;AAED,MAAM,MAAM,WAAW,GACnB,YAAY,GACZ,gBAAgB,GAChB,kBAAkB,GAClB,aAAa,GACb,YAAY,CAAC;AAEjB,MAAM,WAAW,cAAc;IAC7B,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,CAAC,EAAE,aAAa,CAAC;IACvB,IAAI,CAAC,EAAE,QAAQ,GAAG,aAAa,CAAC;CACjC;AAED,MAAM,MAAM,UAAU,GAClB,eAAe,GACf,gBAAgB,GAChB,SAAS,GACT,aAAa,GACb,aAAa,GACb,aAAa,GACb,WAAW,GACX,aAAa,GACb,cAAc,GACd,iBAAiB,GACjB,aAAa,CAAC;AAElB,MAAM,WAAW,aAAa;IAC5B,IAAI,EAAE,UAAU,CAAC;IACjB,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CACnC;AAED,MAAM,WAAW,WAAW;IAC1B,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAC9B,OAAO,EAAE,MAAM,EAAE,CAAC;CACnB"}
package/package.json CHANGED
@@ -1,14 +1,24 @@
1
1
  {
2
2
  "name": "@unif/react-native-chat-sdk",
3
- "version": "0.1.0",
3
+ "version": "0.1.2",
4
4
  "description": "UNIF React Native Chat SDK — 流式通信、Provider、状态管理",
5
- "main": "./src/index.ts",
6
- "types": "./src/index.ts",
5
+ "main": "./lib/commonjs/index.js",
6
+ "module": "./lib/module/index.js",
7
+ "types": "./lib/typescript/commonjs/index.d.ts",
8
+ "react-native": "./src/index.ts",
9
+ "source": "./src/index.ts",
7
10
  "exports": {
8
11
  ".": {
9
12
  "source": "./src/index.ts",
10
- "types": "./src/index.ts",
11
- "default": "./src/index.ts"
13
+ "react-native": "./src/index.ts",
14
+ "import": {
15
+ "types": "./lib/typescript/module/index.d.ts",
16
+ "default": "./lib/module/index.js"
17
+ },
18
+ "require": {
19
+ "types": "./lib/typescript/commonjs/index.d.ts",
20
+ "default": "./lib/commonjs/index.js"
21
+ }
12
22
  },
13
23
  "./package.json": "./package.json"
14
24
  },
@@ -22,14 +32,25 @@
22
32
  "scripts": {
23
33
  "build": "bob build",
24
34
  "clean": "del-cli lib",
35
+ "prepublishOnly": "bob build",
25
36
  "typecheck": "tsc"
26
37
  },
27
- "keywords": ["react-native", "chat", "sdk", "sse", "streaming"],
38
+ "keywords": [
39
+ "react-native",
40
+ "chat",
41
+ "sdk",
42
+ "sse",
43
+ "streaming"
44
+ ],
28
45
  "author": "qq382724935 <liulijun@pec.com.cn>",
29
46
  "license": "MIT",
30
47
  "publishConfig": {
31
48
  "registry": "https://registry.npmjs.org/"
32
49
  },
50
+ "devDependencies": {
51
+ "react-native-sse": "^1.2.1",
52
+ "typescript": "^5.9.2"
53
+ },
33
54
  "dependencies": {
34
55
  "zustand": "^4.5.0"
35
56
  },
@@ -42,8 +63,19 @@
42
63
  "source": "src",
43
64
  "output": "lib",
44
65
  "targets": [
45
- ["module", { "esm": true }],
46
- ["typescript", { "project": "tsconfig.build.json" }]
66
+ "commonjs",
67
+ [
68
+ "module",
69
+ {
70
+ "esm": true
71
+ }
72
+ ],
73
+ [
74
+ "typescript",
75
+ {
76
+ "project": "tsconfig.build.json"
77
+ }
78
+ ]
47
79
  ]
48
80
  }
49
81
  }
@@ -37,8 +37,12 @@ interface ChatContextValue<Message = ChatMessage> {
37
37
  messages: MessageInfo<Message>[];
38
38
  requesting: boolean;
39
39
  suggestions: SuggestionItem[];
40
+ error: string | null;
40
41
  onRequest: (input: unknown) => void;
41
42
  abort: () => void;
43
+ resetChat: () => void;
44
+ loadSession: (messages: ChatMessage[]) => void;
45
+ clearError: () => void;
42
46
  // useXConversations
43
47
  sessions: SessionSummary[];
44
48
  activeId: string;
@@ -54,7 +58,6 @@ interface ChatContextValue<Message = ChatMessage> {
54
58
 
55
59
  const ChatContext = createContext<ChatContextValue | null>(null);
56
60
 
57
- // 内存存储 fallback(无 storage 时使用)
58
61
  const memoryStorage: ChatStorage = {
59
62
  _data: new Map<string, string>(),
60
63
  async getItem(key: string) {
@@ -104,7 +107,7 @@ export function ChatProvider<
104
107
 
105
108
  const model = useXModel({ models, defaultModel });
106
109
 
107
- const value: ChatContextValue<Message> = useMemo(
110
+ const value = useMemo(
108
111
  () => ({
109
112
  ...chat,
110
113
  ...conversations,
@@ -4,7 +4,7 @@
4
4
  * 消费 ChatProvider,输出可渲染的 messages 列表
5
5
  */
6
6
 
7
- import {useCallback, useEffect, useRef} from 'react';
7
+ import {useCallback, useEffect, useRef, useSyncExternalStore} from 'react';
8
8
  import {createChatStore} from '../stores/chatStore';
9
9
  import type {AbstractChatProvider} from '../providers/AbstractChatProvider';
10
10
  import type {ChatMessage, MessageStatus} from '../types/message';
@@ -36,13 +36,14 @@ export interface UseXChatReturn<
36
36
  messages: MessageInfo<Message>[];
37
37
  requesting: boolean;
38
38
  suggestions: SuggestionItem[];
39
+ error: string | null;
39
40
  onRequest: (input: Input) => void;
40
41
  abort: () => void;
42
+ resetChat: () => void;
43
+ loadSession: (messages: ChatMessage[]) => void;
44
+ clearError: () => void;
41
45
  }
42
46
 
43
- let _idCounter = 0;
44
- const defaultGenId = () => `xc-${Date.now()}-${++_idCounter}`;
45
-
46
47
  export function useXChat<
47
48
  Message = ChatMessage,
48
49
  Input = RequestParams<Message>,
@@ -50,32 +51,30 @@ export function useXChat<
50
51
  >(
51
52
  config: UseXChatConfig<Message, Input, Output>
52
53
  ): UseXChatReturn<Message, Input> {
53
- const { provider, generateId = defaultGenId } = config;
54
+ const { provider } = config;
54
55
 
55
56
  const storeRef = useRef(createChatStore());
56
57
  const store = storeRef.current;
57
58
 
58
- // 订阅 store 变化
59
- const state = store.getState();
60
-
61
- // 同步最新值(组件级别使用 zustand subscribe 或 useSyncExternalStore)
62
- // 简化实现:直接用 store.getState()
63
- const getState = useCallback(() => store.getState(), [store]);
59
+ // 使用 useSyncExternalStore 订阅 zustand store 变化
60
+ const state = useSyncExternalStore(
61
+ store.subscribe,
62
+ store.getState,
63
+ store.getState,
64
+ );
64
65
 
65
66
  const onRequest = useCallback(
66
67
  (input: Input) => {
67
- const s = getState();
68
- if (s.isRequesting) return; // 请求去重
68
+ const s = store.getState();
69
+ if (s.isRequesting) return;
69
70
 
70
71
  store.getState().setRequesting(true);
71
72
  store.getState().setError(null);
72
73
  store.getState().setSuggestions([]);
73
74
 
74
- // 添加用户本地消息
75
75
  const localMessage = provider.transformLocalMessage(input);
76
76
  store.getState().addMessage(localMessage as unknown as ChatMessage);
77
77
 
78
- // 发起请求
79
78
  provider.sendMessage(input, {
80
79
  onUpdate: (message) => {
81
80
  store
@@ -101,9 +100,12 @@ export function useXChat<
101
100
  .addMessage(fallbackMsg as unknown as ChatMessage);
102
101
  }
103
102
  },
103
+ onSuggestion: (items) => {
104
+ store.getState().setSuggestions(items);
105
+ },
104
106
  });
105
107
  },
106
- [provider, getState, store, config]
108
+ [provider, store, config]
107
109
  );
108
110
 
109
111
  const abort = useCallback(() => {
@@ -111,14 +113,27 @@ export function useXChat<
111
113
  store.getState().setRequesting(false);
112
114
  }, [provider, store]);
113
115
 
114
- // 清理
116
+ const resetChat = useCallback(() => {
117
+ store.getState().resetChat();
118
+ }, [store]);
119
+
120
+ const loadSession = useCallback(
121
+ (messages: ChatMessage[]) => {
122
+ store.getState().loadSession(messages);
123
+ },
124
+ [store]
125
+ );
126
+
127
+ const clearError = useCallback(() => {
128
+ store.getState().setError(null);
129
+ }, [store]);
130
+
115
131
  useEffect(() => {
116
132
  return () => {
117
133
  provider.abort();
118
134
  };
119
135
  }, [provider]);
120
136
 
121
- // 转换为 MessageInfo 格式
122
137
  const messages: MessageInfo<Message>[] = state.messages.map((m) => ({
123
138
  id: m.id,
124
139
  message: m as unknown as Message,
@@ -130,7 +145,11 @@ export function useXChat<
130
145
  messages,
131
146
  requesting: state.isRequesting,
132
147
  suggestions: state.suggestions,
148
+ error: state.error,
133
149
  onRequest,
134
150
  abort,
151
+ resetChat,
152
+ loadSession,
153
+ clearError,
135
154
  };
136
155
  }
package/src/index.ts CHANGED
@@ -20,6 +20,7 @@ export type {
20
20
  SSEErrorEvent,
21
21
  SSEDoneEvent,
22
22
  SSEEnvelope,
23
+ SuggestionItem,
23
24
  } from './types/sse';
24
25
 
25
26
  export type {
@@ -49,7 +50,7 @@ export type {ChatStorage} from './stores/storage';
49
50
 
50
51
  // Hooks
51
52
  export {useXChat} from './hooks/useXChat';
52
- export type {UseXChatConfig, MessageInfo} from './hooks/useXChat';
53
+ export type {UseXChatConfig, UseXChatReturn, MessageInfo} from './hooks/useXChat';
53
54
 
54
55
  export {useXConversations} from './hooks/useXConversations';
55
56
  export type {UseXConversationsOptions, SessionSummary} from './hooks/useXConversations';
@@ -7,6 +7,7 @@
7
7
  import {XStream} from './XStream';
8
8
  import {SSEParser} from './SSEParser';
9
9
  import type {SSEOutput} from '../types/provider';
10
+ import type {SSEEnvelope} from '../types/sse';
10
11
 
11
12
  export interface XRequestConfig {
12
13
  baseURL: string;
@@ -49,11 +50,12 @@ export class XRequest {
49
50
  } = this.config;
50
51
 
51
52
  // 注入 auth token
53
+ const reqHeaders = {...headers};
52
54
  if (getToken) {
53
55
  try {
54
56
  const token = await getToken();
55
57
  if (token) {
56
- headers['Authorization'] = `Bearer ${token}`;
58
+ reqHeaders['Authorization'] = `Bearer ${token}`;
57
59
  }
58
60
  } catch {
59
61
  // token 获取失败,继续无认证请求
@@ -65,14 +67,21 @@ export class XRequest {
65
67
  this.stream = new XStream({
66
68
  url,
67
69
  method: 'POST',
68
- headers,
70
+ headers: reqHeaders,
69
71
  body: params,
70
72
  timeout,
71
73
  });
72
74
 
73
75
  this.stream.connect({
74
76
  onMessage: (output: SSEOutput) => {
75
- callbacks.onStream?.(output);
77
+ // 通过 SSEParser 进行幂等去重和排序
78
+ const envelopes: SSEEnvelope[] = this.parser.process(output.data);
79
+ for (const envelope of envelopes) {
80
+ callbacks.onStream?.({
81
+ data: JSON.stringify(envelope),
82
+ event: envelope.type,
83
+ });
84
+ }
76
85
  },
77
86
  onError: (error: Error) => {
78
87
  callbacks.onError?.({
@@ -4,6 +4,7 @@
4
4
  */
5
5
 
6
6
  import type {ChatMessage} from './message';
7
+ import type {SuggestionItem} from './sse';
7
8
 
8
9
  export interface RequestParams<T = ChatMessage> {
9
10
  message: T;
@@ -21,4 +22,5 @@ export interface ProviderCallbacks<Message = ChatMessage> {
21
22
  onUpdate: (message: Message) => void;
22
23
  onSuccess: (message: Message) => void;
23
24
  onError: (error: Error) => void;
25
+ onSuggestion?: (items: SuggestionItem[]) => void;
24
26
  }