@mujian/js-sdk 0.1.0-beta.1 → 0.1.0-beta.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.
|
@@ -4,13 +4,11 @@ export type { Message };
|
|
|
4
4
|
/**
|
|
5
5
|
* Use chat
|
|
6
6
|
* @param {object} body - The body of the chat.
|
|
7
|
-
* @param {function} onError - The function to call when an error occurs.
|
|
8
7
|
* @param {function} onFinish - The function to call when the chat is finished.
|
|
9
8
|
* @returns {UseChatReturn} The chat.
|
|
10
9
|
*/
|
|
11
10
|
export type UseChatProps = {
|
|
12
11
|
body?: object;
|
|
13
|
-
onError?: (e: unknown) => void;
|
|
14
12
|
onFinish?: (message: Message) => void;
|
|
15
13
|
/** 消息分页大小,不传时不分页 */
|
|
16
14
|
pageSize?: number;
|
|
@@ -37,7 +35,6 @@ export type UseChatProps = {
|
|
|
37
35
|
export type UseChatReturn = {
|
|
38
36
|
messages: Message[];
|
|
39
37
|
status: 'uninitialized' | 'ready' | 'streaming' | 'error';
|
|
40
|
-
error?: unknown;
|
|
41
38
|
/** 提交用户输入,让AI回答 */
|
|
42
39
|
append: (query: string) => Promise<void>;
|
|
43
40
|
/** 重新生成最后一条回答 */
|
|
@@ -54,6 +51,7 @@ export type UseChatReturn = {
|
|
|
54
51
|
deleteMessage: (messageId: string) => Promise<void>;
|
|
55
52
|
loadMoreMessage: () => Promise<void>;
|
|
56
53
|
messagesStatus: 'all-loaded' | 'loading' | 'has-more' | 'error';
|
|
54
|
+
refresh: () => Promise<void>;
|
|
57
55
|
};
|
|
58
56
|
/**
|
|
59
57
|
* Use chat common
|
|
@@ -67,7 +65,6 @@ export type UseChatCommon = {
|
|
|
67
65
|
* Use chat
|
|
68
66
|
* @param {UseChatProps} props - The props of the chat.
|
|
69
67
|
* @param {object} props.body - The body of the chat.
|
|
70
|
-
* @param {function} props.onError - The function to call when an error occurs.
|
|
71
68
|
* @param {function} props.onFinish - The function to call when the chat is finished.
|
|
72
69
|
* @param {number} props.pageSize - The page size of the chat.
|
|
73
70
|
* @returns {UseChatReturn} The chat.
|
|
@@ -78,4 +75,4 @@ export type UseChatCommon = {
|
|
|
78
75
|
* },
|
|
79
76
|
* });
|
|
80
77
|
*/
|
|
81
|
-
export declare const useChat: ({ body,
|
|
78
|
+
export declare const useChat: ({ body, onFinish, pageSize, }: UseChatProps) => UseChatReturn;
|
|
@@ -4,7 +4,6 @@ import type { UseChatCommon } from '..';
|
|
|
4
4
|
import type { Message } from '../message';
|
|
5
5
|
interface ChatStreamingProps {
|
|
6
6
|
common: UseChatCommon;
|
|
7
|
-
setError: (error: unknown) => void;
|
|
8
7
|
setMessages: Dispatch<SetStateAction<Message[]>>;
|
|
9
8
|
getMessages: () => Message[];
|
|
10
9
|
setInput: (input: string) => void;
|
|
@@ -12,7 +11,7 @@ interface ChatStreamingProps {
|
|
|
12
11
|
conversationVersion: RefObject<number>;
|
|
13
12
|
}
|
|
14
13
|
export declare const NOT_SAVED_MSG_ID_PREFIX = "not_saved";
|
|
15
|
-
export declare const useChatStreaming: ({ common,
|
|
14
|
+
export declare const useChatStreaming: ({ common, setMessages, getMessages, setInput, mujian, conversationVersion: conversationVersionRef, }: ChatStreamingProps) => {
|
|
16
15
|
chatStreaming: ({ query, regenerate, is_continue, conversationVersion, }: {
|
|
17
16
|
/** 用户输入 */
|
|
18
17
|
query?: string;
|
package/dist/react.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { useInfiniteScroll, useLatest, useRequest, useUnmount, useUpdateEffect } from "ahooks";
|
|
2
2
|
import react, { createContext, forwardRef, useCallback, useContext, useEffect, useRef, useState } from "react";
|
|
3
|
+
import { z } from "zod";
|
|
3
4
|
import { Fragment, jsx, jsxs } from "react/jsx-runtime";
|
|
4
5
|
import css_tools from "@adobe/css-tools";
|
|
5
6
|
import dompurify from "dompurify";
|
|
@@ -9,7 +10,6 @@ import postmate from "postmate";
|
|
|
9
10
|
import { Virtualizer } from "virtua";
|
|
10
11
|
import { get } from "lodash-es";
|
|
11
12
|
import { produce } from "immer";
|
|
12
|
-
import { z } from "zod";
|
|
13
13
|
const adjustIframeHeight = (iframeId)=>`
|
|
14
14
|
(function () {
|
|
15
15
|
let scheduled = false;
|
|
@@ -1119,13 +1119,6 @@ const errorMessages = [
|
|
|
1119
1119
|
function isNetworkError(message) {
|
|
1120
1120
|
return errorMessages.some((m)=>message.includes(m));
|
|
1121
1121
|
}
|
|
1122
|
-
class SendMessageError extends Error {
|
|
1123
|
-
constructor(message, cause){
|
|
1124
|
-
super(message);
|
|
1125
|
-
this.name = this.constructor.name;
|
|
1126
|
-
this.cause = cause;
|
|
1127
|
-
}
|
|
1128
|
-
}
|
|
1129
1122
|
async function* callSdk(mujian, content, type = 'generate', conversationVersion, assisMsgId) {
|
|
1130
1123
|
const queue = [];
|
|
1131
1124
|
let resolveWait = null;
|
|
@@ -1172,15 +1165,21 @@ async function* callSdk(mujian, content, type = 'generate', conversationVersion,
|
|
|
1172
1165
|
resolveWait = resolve;
|
|
1173
1166
|
});
|
|
1174
1167
|
}
|
|
1168
|
+
const errorSchema = z.object({
|
|
1169
|
+
message: z.string()
|
|
1170
|
+
});
|
|
1171
|
+
function isError(e) {
|
|
1172
|
+
const { success } = errorSchema.safeParse(e);
|
|
1173
|
+
return success;
|
|
1174
|
+
}
|
|
1175
1175
|
const NOT_SAVED_MSG_ID_PREFIX = 'not_saved';
|
|
1176
|
-
const useChatStreaming = ({ common,
|
|
1176
|
+
const useChatStreaming = ({ common, setMessages, getMessages, setInput, mujian, conversationVersion: conversationVersionRef })=>{
|
|
1177
1177
|
const { body } = common;
|
|
1178
1178
|
const [isStreaming, setIsStreaming] = useState(false);
|
|
1179
1179
|
const chatStreaming = useCallback(async ({ query, regenerate, is_continue, conversationVersion })=>{
|
|
1180
|
+
const backupMessages = getMessages();
|
|
1180
1181
|
try {
|
|
1181
|
-
setError(void 0);
|
|
1182
1182
|
setIsStreaming(true);
|
|
1183
|
-
const backupMessages = getMessages();
|
|
1184
1183
|
const userMessage = {
|
|
1185
1184
|
id: `${NOT_SAVED_MSG_ID_PREFIX}_user_${Date.now()}`,
|
|
1186
1185
|
isUser: true,
|
|
@@ -1204,12 +1203,14 @@ const useChatStreaming = ({ common, setError, setMessages, getMessages, setInput
|
|
|
1204
1203
|
isGenerating: true
|
|
1205
1204
|
};
|
|
1206
1205
|
if (regenerate) setMessages(produce((draft)=>{
|
|
1207
|
-
const lastMessage = draft
|
|
1206
|
+
const lastMessage = draft.at(-1);
|
|
1208
1207
|
lastMessage.activeSwipeId = lastMessage.swipes.length;
|
|
1209
1208
|
lastMessage.swipes.push({
|
|
1210
1209
|
content: ''
|
|
1211
1210
|
});
|
|
1212
1211
|
lastMessage.isGenerating = true;
|
|
1212
|
+
lastMessage.finishReason = void 0;
|
|
1213
|
+
lastMessage.error = void 0;
|
|
1213
1214
|
}));
|
|
1214
1215
|
else is_continue ? setMessages((prev)=>[
|
|
1215
1216
|
...prev,
|
|
@@ -1220,50 +1221,62 @@ const useChatStreaming = ({ common, setError, setMessages, getMessages, setInput
|
|
|
1220
1221
|
aiMessage
|
|
1221
1222
|
]);
|
|
1222
1223
|
const stream = callSdk(mujian, query || '', is_continue ? 'continue' : regenerate ? 'regenerate' : 'generate', conversationVersion);
|
|
1223
|
-
|
|
1224
|
-
|
|
1225
|
-
|
|
1226
|
-
if (
|
|
1227
|
-
if (!
|
|
1228
|
-
|
|
1229
|
-
|
|
1230
|
-
|
|
1231
|
-
|
|
1232
|
-
|
|
1233
|
-
|
|
1234
|
-
|
|
1235
|
-
|
|
1236
|
-
|
|
1237
|
-
|
|
1238
|
-
|
|
1239
|
-
|
|
1240
|
-
|
|
1241
|
-
|
|
1242
|
-
|
|
1243
|
-
|
|
1244
|
-
|
|
1245
|
-
|
|
1246
|
-
await new Promise((resolve)=>setTimeout(resolve, 10));
|
|
1247
|
-
}
|
|
1224
|
+
for await (const chunk of stream){
|
|
1225
|
+
if (!chunk) return;
|
|
1226
|
+
if ('meta' === chunk.type) {
|
|
1227
|
+
if (!regenerate) setMessages(produce((draft)=>{
|
|
1228
|
+
if (!is_continue) {
|
|
1229
|
+
const userMsg = draft[draft.length - 2];
|
|
1230
|
+
userMsg.id = chunk.userMsgId;
|
|
1231
|
+
}
|
|
1232
|
+
const lastMessage = draft[draft.length - 1];
|
|
1233
|
+
lastMessage.id = chunk.assisMsgId;
|
|
1234
|
+
}));
|
|
1235
|
+
conversationVersionRef.current = chunk.newConversationVersion;
|
|
1236
|
+
} else if ('data' === chunk.type) {
|
|
1237
|
+
setMessages(produce((draft)=>{
|
|
1238
|
+
const lastMessage = draft.at(-1);
|
|
1239
|
+
lastMessage.swipes[lastMessage.activeSwipeId] = {
|
|
1240
|
+
content: chunk.content,
|
|
1241
|
+
mjv: chunk.mjv
|
|
1242
|
+
};
|
|
1243
|
+
if (chunk.finishReason) lastMessage.finishReason = chunk.finishReason;
|
|
1244
|
+
if (chunk.error) lastMessage.error = chunk.error;
|
|
1245
|
+
}));
|
|
1246
|
+
await new Promise((resolve)=>setTimeout(resolve, 10));
|
|
1248
1247
|
}
|
|
1249
|
-
} catch (error) {
|
|
1250
|
-
Log.e('Stream error', error);
|
|
1251
|
-
if ('object' == typeof error && error && 'message' in error && 'string' == typeof error.message) if ('code' in error && 2011030001 === error.code) {
|
|
1252
|
-
setMessages(backupMessages);
|
|
1253
|
-
if (!regenerate && !is_continue && query) setInput(query);
|
|
1254
|
-
} else isNetworkError(error.message) ? setError(new SendMessageError('E_NETWORK_ERROR')) : setError(new SendMessageError(error.message));
|
|
1255
|
-
else setError(error);
|
|
1256
|
-
} finally{
|
|
1257
|
-
setMessages(produce((draft)=>{
|
|
1258
|
-
const lastMessage = draft[draft.length - 1];
|
|
1259
|
-
lastMessage.isGenerating = false;
|
|
1260
|
-
}));
|
|
1261
1248
|
}
|
|
1262
1249
|
} catch (error) {
|
|
1263
|
-
|
|
1264
|
-
|
|
1265
|
-
|
|
1250
|
+
Log.e('Stream error', error);
|
|
1251
|
+
setMessages(produce((draft)=>{
|
|
1252
|
+
const lastMessage = draft.at(-1);
|
|
1253
|
+
if (isError(error) && isNetworkError(error.message)) lastMessage.error = {
|
|
1254
|
+
code: -10000,
|
|
1255
|
+
message: 'E_NETWORK_ERROR'
|
|
1256
|
+
};
|
|
1257
|
+
else lastMessage.error = {
|
|
1258
|
+
code: 1000000005,
|
|
1259
|
+
message: String(error)
|
|
1260
|
+
};
|
|
1261
|
+
}));
|
|
1266
1262
|
} finally{
|
|
1263
|
+
setMessages(produce((draft)=>{
|
|
1264
|
+
const lastMessage = draft[draft.length - 1];
|
|
1265
|
+
lastMessage.isGenerating = false;
|
|
1266
|
+
if (lastMessage.error?.code === 2011030009) {
|
|
1267
|
+
const backup = backupMessages.find((m)=>m.id === lastMessage.id);
|
|
1268
|
+
if (backup) {
|
|
1269
|
+
lastMessage.swipes = backup.swipes;
|
|
1270
|
+
lastMessage.activeSwipeId = backup.activeSwipeId;
|
|
1271
|
+
} else {
|
|
1272
|
+
lastMessage.activeSwipeId -= 1;
|
|
1273
|
+
lastMessage.swipes.length = lastMessage.swipes.length - 1;
|
|
1274
|
+
}
|
|
1275
|
+
} else if (lastMessage.error?.code === 2011030001) {
|
|
1276
|
+
setMessages(backupMessages);
|
|
1277
|
+
query && setInput(query);
|
|
1278
|
+
}
|
|
1279
|
+
}));
|
|
1267
1280
|
setIsStreaming(false);
|
|
1268
1281
|
}
|
|
1269
1282
|
}, [
|
|
@@ -1288,8 +1301,17 @@ const useChatStreaming = ({ common, setError, setMessages, getMessages, setInput
|
|
|
1288
1301
|
}
|
|
1289
1302
|
} catch (error) {
|
|
1290
1303
|
Log.e('Stream error', error);
|
|
1291
|
-
|
|
1292
|
-
|
|
1304
|
+
setMessages(produce((draft)=>{
|
|
1305
|
+
const lastMessage = draft.at(-1);
|
|
1306
|
+
if (isError(error) && isNetworkError(error.message)) lastMessage.error = {
|
|
1307
|
+
code: -10000,
|
|
1308
|
+
message: 'E_NETWORK_ERROR'
|
|
1309
|
+
};
|
|
1310
|
+
else lastMessage.error = {
|
|
1311
|
+
code: 1000000005,
|
|
1312
|
+
message: String(error)
|
|
1313
|
+
};
|
|
1314
|
+
}));
|
|
1293
1315
|
} finally{
|
|
1294
1316
|
setMessages(produce((draft)=>{
|
|
1295
1317
|
const msg = draft.find((m)=>m.id === messageId);
|
|
@@ -1306,17 +1328,12 @@ const useChatStreaming = ({ common, setError, setMessages, getMessages, setInput
|
|
|
1306
1328
|
recoverStreaming
|
|
1307
1329
|
};
|
|
1308
1330
|
};
|
|
1309
|
-
const useChat = ({ body,
|
|
1310
|
-
const [error, _setError] = useState();
|
|
1331
|
+
const useChat = ({ body, onFinish, pageSize = 10 })=>{
|
|
1311
1332
|
const [input, setInput] = useState('');
|
|
1312
1333
|
const conversationVersion = useRef(0);
|
|
1313
1334
|
const mujian = useMujian();
|
|
1314
|
-
const setError = (error)=>{
|
|
1315
|
-
_setError(error);
|
|
1316
|
-
if (error) onError?.(error);
|
|
1317
|
-
};
|
|
1318
1335
|
const isLoadingMore = useRef(false);
|
|
1319
|
-
const { data, loadMoreAsync, loadingMore, loading, mutate, error: messageLoadError } = useInfiniteScroll(async (current)=>{
|
|
1336
|
+
const { data, loadMoreAsync, loadingMore, loading, mutate, error: messageLoadError, reloadAsync } = useInfiniteScroll(async (current)=>{
|
|
1320
1337
|
isLoadingMore.current = true;
|
|
1321
1338
|
if (current?.noMore) return {
|
|
1322
1339
|
noMore: true,
|
|
@@ -1338,6 +1355,9 @@ const useChat = ({ body, onError, onFinish, pageSize = 10 })=>{
|
|
|
1338
1355
|
}, {
|
|
1339
1356
|
direction: 'top'
|
|
1340
1357
|
});
|
|
1358
|
+
const refresh = async ()=>{
|
|
1359
|
+
await reloadAsync();
|
|
1360
|
+
};
|
|
1341
1361
|
const loadMoreMessage = async ()=>{
|
|
1342
1362
|
if (isLoadingMore.current) return;
|
|
1343
1363
|
try {
|
|
@@ -1367,7 +1387,6 @@ const useChat = ({ body, onError, onFinish, pageSize = 10 })=>{
|
|
|
1367
1387
|
common: {
|
|
1368
1388
|
body
|
|
1369
1389
|
},
|
|
1370
|
-
setError,
|
|
1371
1390
|
setMessages,
|
|
1372
1391
|
getMessages,
|
|
1373
1392
|
setInput,
|
|
@@ -1384,15 +1403,10 @@ const useChat = ({ body, onError, onFinish, pageSize = 10 })=>{
|
|
|
1384
1403
|
]);
|
|
1385
1404
|
const append = useCallback(async (query)=>{
|
|
1386
1405
|
if (isStreaming) throw new Error('useChat is streaming already.');
|
|
1387
|
-
|
|
1388
|
-
|
|
1389
|
-
|
|
1390
|
-
|
|
1391
|
-
});
|
|
1392
|
-
} catch (e) {
|
|
1393
|
-
setError(e);
|
|
1394
|
-
throw e;
|
|
1395
|
-
}
|
|
1406
|
+
await chatStreaming({
|
|
1407
|
+
query,
|
|
1408
|
+
conversationVersion: conversationVersion.current
|
|
1409
|
+
});
|
|
1396
1410
|
}, [
|
|
1397
1411
|
isStreaming,
|
|
1398
1412
|
chatStreaming
|
|
@@ -1400,17 +1414,12 @@ const useChat = ({ body, onError, onFinish, pageSize = 10 })=>{
|
|
|
1400
1414
|
const regenerate = useCallback(async ()=>{
|
|
1401
1415
|
if (isStreaming) throw new Error('useChat is streaming already.');
|
|
1402
1416
|
const lastMessage = messages.findLast((message)=>message.isUser);
|
|
1403
|
-
|
|
1404
|
-
|
|
1405
|
-
|
|
1406
|
-
|
|
1407
|
-
|
|
1408
|
-
|
|
1409
|
-
});
|
|
1410
|
-
} catch (e) {
|
|
1411
|
-
setError(e);
|
|
1412
|
-
throw e;
|
|
1413
|
-
}
|
|
1417
|
+
const query = lastMessage ? lastMessage.swipes[lastMessage.activeSwipeId].content : '';
|
|
1418
|
+
await chatStreaming({
|
|
1419
|
+
query,
|
|
1420
|
+
regenerate: true,
|
|
1421
|
+
conversationVersion: conversationVersion.current
|
|
1422
|
+
});
|
|
1414
1423
|
}, [
|
|
1415
1424
|
isStreaming,
|
|
1416
1425
|
messages,
|
|
@@ -1418,16 +1427,11 @@ const useChat = ({ body, onError, onFinish, pageSize = 10 })=>{
|
|
|
1418
1427
|
]);
|
|
1419
1428
|
const continueGenerate = useCallback(async ()=>{
|
|
1420
1429
|
if (isStreaming) throw new Error('useChat is streaming already.');
|
|
1421
|
-
|
|
1422
|
-
|
|
1423
|
-
|
|
1424
|
-
|
|
1425
|
-
|
|
1426
|
-
});
|
|
1427
|
-
} catch (e) {
|
|
1428
|
-
setError(e);
|
|
1429
|
-
throw e;
|
|
1430
|
-
}
|
|
1430
|
+
await chatStreaming({
|
|
1431
|
+
query: '',
|
|
1432
|
+
is_continue: true,
|
|
1433
|
+
conversationVersion: conversationVersion.current
|
|
1434
|
+
});
|
|
1431
1435
|
}, [
|
|
1432
1436
|
isStreaming,
|
|
1433
1437
|
chatStreaming
|
|
@@ -1439,10 +1443,10 @@ const useChat = ({ body, onError, onFinish, pageSize = 10 })=>{
|
|
|
1439
1443
|
};
|
|
1440
1444
|
const setSwipe = async (messageId, swipeId)=>{
|
|
1441
1445
|
if (swipeId < 0) return;
|
|
1442
|
-
setMessages((
|
|
1443
|
-
|
|
1444
|
-
|
|
1445
|
-
|
|
1446
|
+
setMessages(produce((draft)=>{
|
|
1447
|
+
const msg = draft.find((m)=>m.id === messageId);
|
|
1448
|
+
if (msg) msg.activeSwipeId = swipeId;
|
|
1449
|
+
}));
|
|
1446
1450
|
const resp = await mujian.ai.chat.message.swipe(messageId, swipeId);
|
|
1447
1451
|
const schema = z.object({
|
|
1448
1452
|
newConversationVersion: z.number()
|
|
@@ -1457,20 +1461,10 @@ const useChat = ({ body, onError, onFinish, pageSize = 10 })=>{
|
|
|
1457
1461
|
});
|
|
1458
1462
|
const { data, success } = schema.safeParse(resp);
|
|
1459
1463
|
if (success && data.newConversationVersion) conversationVersion.current = data.newConversationVersion;
|
|
1460
|
-
|
|
1461
|
-
const
|
|
1462
|
-
|
|
1463
|
-
|
|
1464
|
-
};
|
|
1465
|
-
if (!newMsg.isUser) {
|
|
1466
|
-
newMsg.swipes = [
|
|
1467
|
-
...newMsg.swipes
|
|
1468
|
-
];
|
|
1469
|
-
newMsg.swipes[newMsg.activeSwipeId].content = content;
|
|
1470
|
-
}
|
|
1471
|
-
return newMsg;
|
|
1472
|
-
};
|
|
1473
|
-
setMessages((prev)=>prev.map((msg)=>msg.id === messageId ? patchMessage(msg) : msg));
|
|
1464
|
+
setMessages(produce((draft)=>{
|
|
1465
|
+
const msg = draft.find((msg)=>msg.id === messageId);
|
|
1466
|
+
if (msg) msg.swipes[msg.activeSwipeId].content = content;
|
|
1467
|
+
}));
|
|
1474
1468
|
};
|
|
1475
1469
|
const deleteMessage = async (messageId)=>{
|
|
1476
1470
|
if (!messageId.startsWith(NOT_SAVED_MSG_ID_PREFIX)) try {
|
|
@@ -1492,11 +1486,9 @@ const useChat = ({ body, onError, onFinish, pageSize = 10 })=>{
|
|
|
1492
1486
|
stop,
|
|
1493
1487
|
messages: messages,
|
|
1494
1488
|
status: (()=>{
|
|
1495
|
-
if (error) return 'error';
|
|
1496
1489
|
if (isStreaming) return 'streaming';
|
|
1497
1490
|
return 'ready';
|
|
1498
1491
|
})(),
|
|
1499
|
-
error,
|
|
1500
1492
|
setMessages: setMessages,
|
|
1501
1493
|
input,
|
|
1502
1494
|
setInput,
|
|
@@ -1507,7 +1499,8 @@ const useChat = ({ body, onError, onFinish, pageSize = 10 })=>{
|
|
|
1507
1499
|
editMessage,
|
|
1508
1500
|
deleteMessage,
|
|
1509
1501
|
loadMoreMessage,
|
|
1510
|
-
messagesStatus: messageLoadError ? 'error' : loadingMore || loading ? 'loading' : data?.noMore ? 'all-loaded' : 'has-more'
|
|
1502
|
+
messagesStatus: messageLoadError ? 'error' : loadingMore || loading ? 'loading' : data?.noMore ? 'all-loaded' : 'has-more',
|
|
1503
|
+
refresh
|
|
1511
1504
|
};
|
|
1512
1505
|
};
|
|
1513
1506
|
export { MdRenderer, MujianProvider, MujianSpinner, Thread, useChat, useChatContext, useMjEngine, useMujian };
|