@mujian/js-sdk 0.0.6-beta.mjv.68 → 0.1.0-beta.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/dist/events/index.d.ts +25 -5
- package/dist/index.d.ts +41 -2
- package/dist/index.js +143 -184
- package/dist/lite.d.ts +73 -0
- package/dist/lite.js +124 -0
- package/dist/modules/ai/chat/chat.d.ts +18 -26
- package/dist/modules/ai/chat/index.d.ts +1 -1
- package/dist/modules/ai/chat/message/index.d.ts +7 -16
- package/dist/modules/ai/chat/settings/index.d.ts +1 -2
- package/dist/modules/ai/chat/settings/persona.d.ts +0 -8
- package/dist/modules/ai/openai/chat.d.ts +0 -3
- package/dist/modules/ai/openai/completions.d.ts +0 -2
- package/dist/modules/ai/openai/images.d.ts +0 -2
- package/dist/modules/ai/openai/responses.d.ts +0 -2
- package/dist/modules/config.d.ts +17 -0
- package/dist/react/chat/useChat/index.d.ts +27 -5
- package/dist/react/chat/useChat/inner/chatStreaming.d.ts +8 -4
- package/dist/react/chat/useChat/inner/stream.d.ts +25 -2
- package/dist/react/chat/useChat/message.d.ts +27 -38
- package/dist/react/components/MdRenderer/index.d.ts +3 -2
- package/dist/react/components/MujianProvider/index.d.ts +4 -0
- package/dist/react/components/Thread/MessageItem.d.ts +6 -0
- package/dist/react/components/index.d.ts +1 -1
- package/dist/react/index.d.ts +1 -0
- package/dist/react/mjEngine/index.d.ts +48 -0
- package/dist/react.js +446 -343
- package/dist/types/index.d.ts +1 -0
- package/dist/umd/index.js +1 -791
- package/dist/umd/lite.js +2 -0
- package/dist/umd/lite.js.LICENSE.txt +7 -0
- package/dist/umd/react.css +1 -343
- package/dist/umd/react.js +95 -8807
- package/dist/umd/react.js.LICENSE.txt +1 -1
- package/dist/utils/is-network-error.d.ts +1 -0
- package/package.json +14 -6
- package/dist/modules/ai/chat/settings/model.d.ts +0 -24
package/dist/react.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { useInfiniteScroll, useLatest, useRequest, useUpdateEffect } from "ahooks";
|
|
1
|
+
import { useInfiniteScroll, useLatest, useRequest, useUnmount, useUpdateEffect } from "ahooks";
|
|
2
2
|
import react, { createContext, forwardRef, useCallback, useContext, useEffect, useRef, useState } from "react";
|
|
3
3
|
import { Fragment, jsx, jsxs } from "react/jsx-runtime";
|
|
4
4
|
import css_tools from "@adobe/css-tools";
|
|
@@ -7,6 +7,9 @@ import showdown from "showdown";
|
|
|
7
7
|
import { v4 } from "uuid";
|
|
8
8
|
import postmate from "postmate";
|
|
9
9
|
import { Virtualizer } from "virtua";
|
|
10
|
+
import { get } from "lodash-es";
|
|
11
|
+
import { produce } from "immer";
|
|
12
|
+
import { z } from "zod";
|
|
10
13
|
const adjustIframeHeight = (iframeId)=>`
|
|
11
14
|
(function () {
|
|
12
15
|
let scheduled = false;
|
|
@@ -404,7 +407,14 @@ function messageFormatting(mes, sanitizerOverrides = {}) {
|
|
|
404
407
|
});
|
|
405
408
|
return mes;
|
|
406
409
|
}
|
|
407
|
-
const
|
|
410
|
+
const loadingTranslates = {
|
|
411
|
+
'zh-hans': '加载中...',
|
|
412
|
+
'zh-hant': '載入中...',
|
|
413
|
+
en: 'Loading...',
|
|
414
|
+
ja: '読み込み中...',
|
|
415
|
+
th: 'กำลังโหลด...'
|
|
416
|
+
};
|
|
417
|
+
const MdRendererBase = ({ content, unsafe = false, extra = {}, lang })=>{
|
|
408
418
|
const containerRef = useRef(null);
|
|
409
419
|
const [iframeIdList, setIframeIdList] = useState([]);
|
|
410
420
|
useEffect(()=>{
|
|
@@ -421,16 +431,12 @@ const MdRendererBase = ({ content, unsafe = false, extra = {} })=>{
|
|
|
421
431
|
id
|
|
422
432
|
]);
|
|
423
433
|
const escapedSrcdoc = escapeHtmlAttribute(srcdoc);
|
|
434
|
+
const loadingText = loadingTranslates[lang ?? 'zh-hans'] || loadingTranslates['zh-hans'];
|
|
424
435
|
return `
|
|
425
436
|
<div class="MJ-iframe-container" id="${containerId}" style="display:flex;width:100%;height:100%;position:relative;">
|
|
426
437
|
<div class="spin-overlay" id="MJ-spin-${id}" style="width:100%;height:100%;position:absolute;top:0;left:0;z-index:1000;background-color:rgba(0,0,0,0.5);display:flex;justify-content:center;align-items:center;">
|
|
427
438
|
<div class="spin-inner wave-text" style="font-weight:500;font-size:16px;color:white;display:flex;justify-content:center;align-items:center;">
|
|
428
|
-
|
|
429
|
-
<span>载</span>
|
|
430
|
-
<span>中</span>
|
|
431
|
-
<span>.</span>
|
|
432
|
-
<span>.</span>
|
|
433
|
-
<span>.</span>
|
|
439
|
+
${loadingText.split('').map((t)=>`<span>${t}</span>`).join('')}
|
|
434
440
|
</div>
|
|
435
441
|
</div>
|
|
436
442
|
<iframe id="${iframeId}" class="w-full" sandbox="${unsafe ? "allow-scripts" : "allow-scripts allow-same-origin"}" loading="lazy"
|
|
@@ -509,6 +515,11 @@ var events_EVENT = /*#__PURE__*/ function(EVENT) {
|
|
|
509
515
|
EVENT["MUJIAN_AI_CHAT_MESSAGE_GET_ALL"] = "mujian:ai:chat:message:getAll";
|
|
510
516
|
EVENT["MUJIAN_AI_CHAT_MESSAGE_GET_PAGE"] = "mujian:ai:chat:message:getPage";
|
|
511
517
|
EVENT["MUJIAN_AI_CHAT_PROJECT_GET_INFO"] = "mujian:ai:chat:project:getInfo";
|
|
518
|
+
EVENT["MUJIAN_AI_CHAT_V2_COMPLETE"] = "mujian:ai:chat_v2:complete";
|
|
519
|
+
EVENT["MUJIAN_AI_CHAT_V2_RECOVER"] = "mujian:ai:chat_v2:recover";
|
|
520
|
+
EVENT["MUJIAN_AI_CHAT_V2_STOP"] = "mujian:ai:chat_v2:stop";
|
|
521
|
+
EVENT["MUJIAN_AI_CHAT_V2_MESSAGE_GET_PAGE"] = "mujian:ai:chat_v2:message:getPage";
|
|
522
|
+
EVENT["MUJIAN_AI_CHAT_V2_RENDER_MESSAGE"] = "mujian:ai:chat_v2:renderMessage";
|
|
512
523
|
EVENT["MUJIAN_AI_SETTINGS_PERSONA_GET_ACTIVE"] = "mujian:ai:settings:persona:getActive";
|
|
513
524
|
EVENT["MUJIAN_AI_SETTINGS_PERSONA_SET_ACTIVE"] = "mujian:ai:settings:persona:setActive";
|
|
514
525
|
EVENT["MUJIAN_AI_SETTINGS_MODEL_GET_ALL"] = "mujian:ai:settings:model:getAll";
|
|
@@ -517,87 +528,51 @@ var events_EVENT = /*#__PURE__*/ function(EVENT) {
|
|
|
517
528
|
EVENT["MUJIAN_AI_CHAT_MESSAGE_DELETE_ONE"] = "mujian:ai:chat:message:deleteOne";
|
|
518
529
|
EVENT["MUJIAN_AI_CHAT_MESSAGE_EDIT_ONE"] = "mujian:ai:chat:message:editOne";
|
|
519
530
|
EVENT["MUJIAN_AI_CHAT_MESSAGE_SWIPE"] = "mujian:ai:chat:message:swipe";
|
|
520
|
-
EVENT["MUJIAN_AI_CHAT_MESSAGE_GET_PROMPT"] = "mujian:ai:chat:message:getPrompt";
|
|
521
531
|
EVENT["MUJIAN_AI_OPENAI_IMAGES_GENERATE"] = "mujian:ai:openai:images:generate";
|
|
522
532
|
EVENT["MUJIAN_UTILS_CLIPBOARD_WRITE_TEXT"] = "mujian:utils:clipboard:writeText";
|
|
533
|
+
EVENT["MUJIAN_GET_CONFIG"] = "mujian:getConfig";
|
|
523
534
|
return EVENT;
|
|
524
535
|
}({});
|
|
525
|
-
function
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
let replyId;
|
|
530
|
-
return function(data) {
|
|
531
|
-
buffer += data;
|
|
532
|
-
const lines = buffer.split('\n');
|
|
533
|
-
buffer = lines.pop() || '';
|
|
534
|
-
for (const line of lines)if (line.startsWith('data: ')) try {
|
|
535
|
-
const parsedData = JSON.parse(line.slice(6));
|
|
536
|
-
if (parsedData.question_id) questionId = parsedData.question_id;
|
|
537
|
-
if (parsedData.reply_id) replyId = parsedData.reply_id;
|
|
538
|
-
if (parsedData.isFinished) return void onData({
|
|
539
|
-
isFinished: true,
|
|
540
|
-
deltaContent: '',
|
|
541
|
-
fullContent,
|
|
542
|
-
questionId,
|
|
543
|
-
replyId
|
|
544
|
-
});
|
|
545
|
-
const deltaContent = parsedData?.choices?.[0]?.delta?.content;
|
|
546
|
-
if (deltaContent?.length > 0) {
|
|
547
|
-
fullContent += deltaContent;
|
|
548
|
-
onData({
|
|
549
|
-
isFinished: false,
|
|
550
|
-
deltaContent: deltaContent,
|
|
551
|
-
fullContent,
|
|
552
|
-
questionId,
|
|
553
|
-
replyId
|
|
554
|
-
});
|
|
555
|
-
}
|
|
556
|
-
} catch (e) {
|
|
557
|
-
onData({
|
|
558
|
-
isFinished: true,
|
|
559
|
-
error: e,
|
|
560
|
-
deltaContent: '',
|
|
561
|
-
fullContent,
|
|
562
|
-
questionId,
|
|
563
|
-
replyId
|
|
564
|
-
});
|
|
565
|
-
return;
|
|
566
|
-
}
|
|
567
|
-
};
|
|
568
|
-
}
|
|
569
|
-
const chat_complete = async function(message, onData, signal, option = {}) {
|
|
570
|
-
await this.call(events_EVENT.MUJIAN_AI_CHAT_COMPLETE, {
|
|
571
|
-
content: message
|
|
536
|
+
const chat_complete = async function(message, conversationVersion, onData) {
|
|
537
|
+
await this.call(events_EVENT.MUJIAN_AI_CHAT_V2_COMPLETE, {
|
|
538
|
+
content: message,
|
|
539
|
+
conversationVersion
|
|
572
540
|
}, {
|
|
573
|
-
onData
|
|
574
|
-
signal
|
|
541
|
+
onData
|
|
575
542
|
});
|
|
576
543
|
};
|
|
577
|
-
const applyRegex = async function(props) {
|
|
578
|
-
return await this.call(events_EVENT.MUJIAN_AI_CHAT_APPLY_REGEX, props);
|
|
579
|
-
};
|
|
580
544
|
const renderMessage = async function(props) {
|
|
581
|
-
return await this.call(events_EVENT.
|
|
545
|
+
return await this.call(events_EVENT.MUJIAN_AI_CHAT_V2_RENDER_MESSAGE, props);
|
|
582
546
|
};
|
|
583
|
-
const continueComplete = async function(
|
|
584
|
-
return await this.call(events_EVENT.
|
|
585
|
-
isContinue: true
|
|
547
|
+
const continueComplete = async function(conversationVersion, onData) {
|
|
548
|
+
return await this.call(events_EVENT.MUJIAN_AI_CHAT_V2_COMPLETE, {
|
|
549
|
+
isContinue: true,
|
|
550
|
+
conversationVersion
|
|
586
551
|
}, {
|
|
587
|
-
onData
|
|
588
|
-
signal
|
|
552
|
+
onData
|
|
589
553
|
});
|
|
590
554
|
};
|
|
591
|
-
const chat_regenerate = async function(
|
|
592
|
-
return await this.call(events_EVENT.
|
|
593
|
-
isRegenerate: true
|
|
555
|
+
const chat_regenerate = async function(conversationVersion, onData) {
|
|
556
|
+
return await this.call(events_EVENT.MUJIAN_AI_CHAT_V2_COMPLETE, {
|
|
557
|
+
isRegenerate: true,
|
|
558
|
+
conversationVersion
|
|
594
559
|
}, {
|
|
595
|
-
onData
|
|
596
|
-
|
|
560
|
+
onData
|
|
561
|
+
});
|
|
562
|
+
};
|
|
563
|
+
const chat_stop = async function(conversationVersion, assisMsgId) {
|
|
564
|
+
return await this.call(events_EVENT.MUJIAN_AI_CHAT_V2_STOP, {
|
|
565
|
+
conversationVersion,
|
|
566
|
+
assisMsgId
|
|
597
567
|
});
|
|
598
568
|
};
|
|
599
|
-
const
|
|
600
|
-
return await this.call(events_EVENT.
|
|
569
|
+
const recover = async function(conversationVersion, assisMsgId, onData) {
|
|
570
|
+
return await this.call(events_EVENT.MUJIAN_AI_CHAT_V2_RECOVER, {
|
|
571
|
+
conversationVersion,
|
|
572
|
+
assisMsgId
|
|
573
|
+
}, {
|
|
574
|
+
onData
|
|
575
|
+
});
|
|
601
576
|
};
|
|
602
577
|
const messageDeleteOne = async function(messageId) {
|
|
603
578
|
return await this.call(events_EVENT.MUJIAN_AI_CHAT_MESSAGE_DELETE_ONE, {
|
|
@@ -616,13 +591,8 @@ const messageSwipe = async function(messageId, swipeId) {
|
|
|
616
591
|
swipeId
|
|
617
592
|
});
|
|
618
593
|
};
|
|
619
|
-
const getPrompt = async function(messageId) {
|
|
620
|
-
return await this.call(events_EVENT.MUJIAN_AI_CHAT_MESSAGE_GET_PROMPT, {
|
|
621
|
-
messageId
|
|
622
|
-
});
|
|
623
|
-
};
|
|
624
594
|
async function getPage(fromCursor, pageSize) {
|
|
625
|
-
return await this.call(events_EVENT.
|
|
595
|
+
return await this.call(events_EVENT.MUJIAN_AI_CHAT_V2_MESSAGE_GET_PAGE, {
|
|
626
596
|
fromCursor,
|
|
627
597
|
pageSize
|
|
628
598
|
});
|
|
@@ -633,22 +603,6 @@ const getInfo = async function() {
|
|
|
633
603
|
const getActive = async function() {
|
|
634
604
|
return await this.call(events_EVENT.MUJIAN_AI_SETTINGS_PERSONA_GET_ACTIVE);
|
|
635
605
|
};
|
|
636
|
-
const setActive = async function(personaId) {
|
|
637
|
-
return await this.call(events_EVENT.MUJIAN_AI_SETTINGS_PERSONA_SET_ACTIVE, {
|
|
638
|
-
personaId
|
|
639
|
-
});
|
|
640
|
-
};
|
|
641
|
-
const model_getActive = async function() {
|
|
642
|
-
return await this.call(events_EVENT.MUJIAN_AI_SETTINGS_MODEL_GET_ACTIVE);
|
|
643
|
-
};
|
|
644
|
-
const model_setActive = async function(modelId) {
|
|
645
|
-
return await this.call(events_EVENT.MUJIAN_AI_SETTINGS_MODEL_SET_ACTIVE, {
|
|
646
|
-
modelId
|
|
647
|
-
});
|
|
648
|
-
};
|
|
649
|
-
const model_getAll = async function() {
|
|
650
|
-
return await this.call(events_EVENT.MUJIAN_AI_SETTINGS_MODEL_GET_ALL);
|
|
651
|
-
};
|
|
652
606
|
const generate = async function(content) {
|
|
653
607
|
return await this.call(MujianSdk.EVENT.MUJIAN_AI_TEXT_GENERATE, {
|
|
654
608
|
content
|
|
@@ -700,6 +654,9 @@ const images_images = {
|
|
|
700
654
|
});
|
|
701
655
|
}
|
|
702
656
|
};
|
|
657
|
+
async function getConfig() {
|
|
658
|
+
return await this.call(events_EVENT.MUJIAN_GET_CONFIG);
|
|
659
|
+
}
|
|
703
660
|
const saveGame = async function() {};
|
|
704
661
|
const loadGame = async function() {};
|
|
705
662
|
async function writeText(text) {
|
|
@@ -718,48 +675,59 @@ class MujianSdk {
|
|
|
718
675
|
return this.ready;
|
|
719
676
|
}
|
|
720
677
|
pendingRequests = new Map();
|
|
678
|
+
_config;
|
|
679
|
+
get openapi() {
|
|
680
|
+
return this._config?.openapi;
|
|
681
|
+
}
|
|
682
|
+
initPromise = null;
|
|
721
683
|
async init() {
|
|
722
|
-
|
|
723
|
-
|
|
724
|
-
|
|
725
|
-
|
|
726
|
-
|
|
727
|
-
call
|
|
728
|
-
|
|
729
|
-
|
|
684
|
+
if (this.initPromise) return this.initPromise;
|
|
685
|
+
this.initPromise = (async ()=>{
|
|
686
|
+
const handshake = new postmate.Model({
|
|
687
|
+
reply: ({ id, complete, data, error })=>{
|
|
688
|
+
const call = this.pendingRequests.get(id);
|
|
689
|
+
if (!call) return;
|
|
690
|
+
if (error) {
|
|
691
|
+
call.reject(error);
|
|
692
|
+
this.pendingRequests.delete(id);
|
|
693
|
+
return;
|
|
694
|
+
}
|
|
695
|
+
call.onData?.(data);
|
|
696
|
+
if (complete) {
|
|
697
|
+
call.onComplete?.();
|
|
698
|
+
call.resolve(data);
|
|
699
|
+
this.pendingRequests.delete(id);
|
|
700
|
+
}
|
|
730
701
|
}
|
|
731
|
-
|
|
732
|
-
|
|
733
|
-
|
|
734
|
-
|
|
735
|
-
|
|
702
|
+
});
|
|
703
|
+
try {
|
|
704
|
+
const parent = await handshake;
|
|
705
|
+
this.ready = true;
|
|
706
|
+
this.parent = parent;
|
|
707
|
+
Log.i('mujian sdk client init');
|
|
708
|
+
await this.call(events_EVENT.MUJIAN_INIT);
|
|
709
|
+
const projectInfo = await this.ai.chat.project.getInfo();
|
|
710
|
+
if (projectInfo.config?.customCss) {
|
|
711
|
+
const style = document.createElement('style');
|
|
712
|
+
style.setAttribute('type', 'text/css');
|
|
713
|
+
style.setAttribute('id', 'mujian-custom-css');
|
|
714
|
+
style.textContent = projectInfo.config.customCss;
|
|
715
|
+
document.head.appendChild(style);
|
|
736
716
|
}
|
|
717
|
+
if (projectInfo.config?.customJs) {
|
|
718
|
+
const script = document.createElement("script");
|
|
719
|
+
script.setAttribute('type', "text/javascript");
|
|
720
|
+
script.setAttribute('id', 'mujian-custom-js');
|
|
721
|
+
script.textContent = projectInfo.config.customJs;
|
|
722
|
+
document.head.appendChild(script);
|
|
723
|
+
}
|
|
724
|
+
const config = await getConfig.call(this);
|
|
725
|
+
if (config) this._config = config;
|
|
726
|
+
} catch (error) {
|
|
727
|
+
Log.e('init error', error);
|
|
737
728
|
}
|
|
738
|
-
});
|
|
739
|
-
|
|
740
|
-
const parent = await handshake;
|
|
741
|
-
this.ready = true;
|
|
742
|
-
this.parent = parent;
|
|
743
|
-
Log.i('mujian sdk client init');
|
|
744
|
-
await this.call(events_EVENT.MUJIAN_INIT);
|
|
745
|
-
const projectInfo = await this.ai.chat.project.getInfo();
|
|
746
|
-
if (projectInfo.config?.customCss) {
|
|
747
|
-
const style = document.createElement('style');
|
|
748
|
-
style.setAttribute('type', 'text/css');
|
|
749
|
-
style.setAttribute('id', 'mujian-custom-css');
|
|
750
|
-
style.textContent = projectInfo.config.customCss;
|
|
751
|
-
document.head.appendChild(style);
|
|
752
|
-
}
|
|
753
|
-
if (projectInfo.config?.customJs) {
|
|
754
|
-
const script = document.createElement("script");
|
|
755
|
-
script.setAttribute('type', "text/javascript");
|
|
756
|
-
script.setAttribute('id', 'mujian-custom-js');
|
|
757
|
-
script.textContent = projectInfo.config.customJs;
|
|
758
|
-
document.head.appendChild(script);
|
|
759
|
-
}
|
|
760
|
-
} catch (error) {
|
|
761
|
-
Log.e('init error', error);
|
|
762
|
-
}
|
|
729
|
+
})();
|
|
730
|
+
return this.initPromise;
|
|
763
731
|
}
|
|
764
732
|
emit(event, data) {
|
|
765
733
|
if (!this.ready) throw new Error('Mujian is not initialized');
|
|
@@ -797,27 +765,20 @@ class MujianSdk {
|
|
|
797
765
|
getInfo: getInfo.bind(this)
|
|
798
766
|
},
|
|
799
767
|
settings: {
|
|
800
|
-
model: {
|
|
801
|
-
getAll: model_getAll.bind(this),
|
|
802
|
-
getActive: model_getActive.bind(this),
|
|
803
|
-
setActive: model_setActive.bind(this)
|
|
804
|
-
},
|
|
805
768
|
persona: {
|
|
806
|
-
getActive: getActive.bind(this)
|
|
807
|
-
setActive: setActive.bind(this)
|
|
769
|
+
getActive: getActive.bind(this)
|
|
808
770
|
}
|
|
809
771
|
},
|
|
810
772
|
complete: chat_complete.bind(this),
|
|
811
|
-
applyRegex: applyRegex.bind(this),
|
|
812
773
|
renderMessage: renderMessage.bind(this),
|
|
813
774
|
continue: continueComplete.bind(this),
|
|
814
775
|
regenerate: chat_regenerate.bind(this),
|
|
776
|
+
stop: chat_stop.bind(this),
|
|
777
|
+
recover: recover.bind(this),
|
|
815
778
|
message: {
|
|
816
|
-
getAll: getAll.bind(this),
|
|
817
779
|
deleteOne: messageDeleteOne.bind(this),
|
|
818
780
|
editOne: messageEditOne.bind(this),
|
|
819
781
|
swipe: messageSwipe.bind(this),
|
|
820
|
-
getPrompt: getPrompt.bind(this),
|
|
821
782
|
getPage: getPage.bind(this)
|
|
822
783
|
}
|
|
823
784
|
},
|
|
@@ -900,8 +861,10 @@ const MujianSpinner = ({ className, style })=>/*#__PURE__*/ jsxs(Fragment, {
|
|
|
900
861
|
]
|
|
901
862
|
});
|
|
902
863
|
const MujianContext = /*#__PURE__*/ createContext(null);
|
|
864
|
+
const ChatContext = /*#__PURE__*/ createContext(null);
|
|
903
865
|
const MujianProvider = ({ children, loadingComponent })=>{
|
|
904
866
|
const [mujian, setMujian] = useState(null);
|
|
867
|
+
const [messageTypeWritingCount, setMessageTypeWritingCount] = useState(0);
|
|
905
868
|
useEffect(()=>{
|
|
906
869
|
(async ()=>{
|
|
907
870
|
const mujian = MujianSdk.getInstance();
|
|
@@ -911,18 +874,26 @@ const MujianProvider = ({ children, loadingComponent })=>{
|
|
|
911
874
|
}, []);
|
|
912
875
|
return /*#__PURE__*/ jsx(MujianContext.Provider, {
|
|
913
876
|
value: mujian,
|
|
914
|
-
children:
|
|
915
|
-
|
|
916
|
-
|
|
917
|
-
|
|
918
|
-
|
|
919
|
-
|
|
920
|
-
alignItems: 'center'
|
|
877
|
+
children: /*#__PURE__*/ jsx(ChatContext.Provider, {
|
|
878
|
+
value: {
|
|
879
|
+
messageTypeWritingCount,
|
|
880
|
+
updateMessageTypeWritingCount (dir) {
|
|
881
|
+
setMessageTypeWritingCount((p)=>Math.max(p + ('add' === dir ? 1 : -1), 0));
|
|
882
|
+
}
|
|
921
883
|
},
|
|
922
|
-
children: /*#__PURE__*/ jsx(
|
|
884
|
+
children: mujian ? children : loadingComponent ?? /*#__PURE__*/ jsx("div", {
|
|
923
885
|
style: {
|
|
924
|
-
|
|
925
|
-
|
|
886
|
+
height: '100%',
|
|
887
|
+
width: '100%',
|
|
888
|
+
display: 'flex',
|
|
889
|
+
justifyContent: 'center',
|
|
890
|
+
alignItems: 'center'
|
|
891
|
+
},
|
|
892
|
+
children: /*#__PURE__*/ jsx(MujianSpinner, {
|
|
893
|
+
style: {
|
|
894
|
+
color: '#EC4342'
|
|
895
|
+
}
|
|
896
|
+
})
|
|
926
897
|
})
|
|
927
898
|
})
|
|
928
899
|
});
|
|
@@ -936,12 +907,86 @@ const useMujian = ()=>{
|
|
|
936
907
|
}
|
|
937
908
|
return mujian;
|
|
938
909
|
};
|
|
910
|
+
const useChatContext = ()=>{
|
|
911
|
+
const mujian = useContext(ChatContext);
|
|
912
|
+
if (!mujian) {
|
|
913
|
+
const message = 'Context is not initialized. Please check that useChatContext is called inside MujianProvider';
|
|
914
|
+
console.error(message);
|
|
915
|
+
throw new Error(message);
|
|
916
|
+
}
|
|
917
|
+
return mujian;
|
|
918
|
+
};
|
|
939
919
|
const MessageItem = (props)=>{
|
|
940
|
-
const { message, children, depth, index
|
|
920
|
+
const { message, children, depth, index, typingOpts = {
|
|
921
|
+
chunkSize: 2,
|
|
922
|
+
delay: 40
|
|
923
|
+
} } = props;
|
|
941
924
|
const mujian = useMujian();
|
|
925
|
+
const { updateMessageTypeWritingCount } = useChatContext();
|
|
926
|
+
const lastMessage = useLatest(message);
|
|
927
|
+
const [typeWritingPos, setTypeWritingPos] = useState(null);
|
|
928
|
+
const typeWritingIntervalId = useRef(null);
|
|
929
|
+
function stopTypeWriting() {
|
|
930
|
+
if (typeWritingIntervalId.current) {
|
|
931
|
+
clearTimeout(typeWritingIntervalId.current);
|
|
932
|
+
typeWritingIntervalId.current = null;
|
|
933
|
+
setTimeout(()=>{
|
|
934
|
+
updateMessageTypeWritingCount('sub');
|
|
935
|
+
});
|
|
936
|
+
}
|
|
937
|
+
}
|
|
938
|
+
function startTypeWriting() {
|
|
939
|
+
updateMessageTypeWritingCount('add');
|
|
940
|
+
stopTypeWriting();
|
|
941
|
+
let lastTimestamp = Date.now();
|
|
942
|
+
typeWritingIntervalId.current = setInterval(()=>{
|
|
943
|
+
function calcTimeFrames() {
|
|
944
|
+
const now = Date.now();
|
|
945
|
+
const deltaTime = now - lastTimestamp;
|
|
946
|
+
lastTimestamp = now;
|
|
947
|
+
return Math.round(deltaTime / typingOpts.delay);
|
|
948
|
+
}
|
|
949
|
+
setTypeWritingPos((p)=>{
|
|
950
|
+
const frames = calcTimeFrames();
|
|
951
|
+
const posIncrement = frames * typingOpts.chunkSize;
|
|
952
|
+
const message = lastMessage.current;
|
|
953
|
+
const content = message.swipes[message.activeSwipeId].content;
|
|
954
|
+
const maxPos = content.length;
|
|
955
|
+
const nextPos = Math.min((p || 0) + posIncrement, maxPos);
|
|
956
|
+
if (!message.isGenerating && maxPos === nextPos) {
|
|
957
|
+
stopTypeWriting();
|
|
958
|
+
return null;
|
|
959
|
+
}
|
|
960
|
+
return nextPos;
|
|
961
|
+
});
|
|
962
|
+
}, typingOpts.delay);
|
|
963
|
+
}
|
|
964
|
+
useUnmount(()=>{
|
|
965
|
+
stopTypeWriting();
|
|
966
|
+
});
|
|
967
|
+
useEffect(()=>{
|
|
968
|
+
if (message.isGenerating) {
|
|
969
|
+
const content = message.swipes[message.activeSwipeId].content;
|
|
970
|
+
setTypeWritingPos(content.length);
|
|
971
|
+
startTypeWriting();
|
|
972
|
+
}
|
|
973
|
+
}, [
|
|
974
|
+
message.isGenerating
|
|
975
|
+
]);
|
|
942
976
|
const { data: renderedMessage } = useRequest(async ()=>{
|
|
943
|
-
|
|
944
|
-
|
|
977
|
+
if (null !== typeWritingPos) {
|
|
978
|
+
const pos = typeWritingPos;
|
|
979
|
+
return {
|
|
980
|
+
...message,
|
|
981
|
+
swipes: message.swipes.map((s, i)=>{
|
|
982
|
+
if (i !== message.activeSwipeId) return s;
|
|
983
|
+
return {
|
|
984
|
+
...s,
|
|
985
|
+
content: s.content.slice(0, pos)
|
|
986
|
+
};
|
|
987
|
+
})
|
|
988
|
+
};
|
|
989
|
+
}
|
|
945
990
|
return await mujian.ai.chat.renderMessage({
|
|
946
991
|
message,
|
|
947
992
|
depth,
|
|
@@ -949,7 +994,8 @@ const MessageItem = (props)=>{
|
|
|
949
994
|
});
|
|
950
995
|
}, {
|
|
951
996
|
refreshDeps: [
|
|
952
|
-
message
|
|
997
|
+
message,
|
|
998
|
+
typeWritingPos
|
|
953
999
|
]
|
|
954
1000
|
});
|
|
955
1001
|
return children(renderedMessage || message, message);
|
|
@@ -971,28 +1017,116 @@ const Thread = {
|
|
|
971
1017
|
MessageItem: MessageItem,
|
|
972
1018
|
MessageList: MessageList
|
|
973
1019
|
};
|
|
974
|
-
|
|
975
|
-
|
|
976
|
-
|
|
977
|
-
|
|
978
|
-
|
|
1020
|
+
let $mj_ai_chat_complete;
|
|
1021
|
+
let $mj_ai_chat_project;
|
|
1022
|
+
let $mj_ai_chat_settings_persona;
|
|
1023
|
+
let $mj_ai_chat_setFirstMesIndex;
|
|
1024
|
+
let $mj_ai_chat_mjv_get;
|
|
1025
|
+
let $mj_ai_chat_mjv_getAll;
|
|
1026
|
+
const $mj_engine = {
|
|
1027
|
+
ai: {
|
|
1028
|
+
chat: {
|
|
1029
|
+
get complete () {
|
|
1030
|
+
return $mj_ai_chat_complete;
|
|
1031
|
+
},
|
|
1032
|
+
get project () {
|
|
1033
|
+
return $mj_ai_chat_project;
|
|
1034
|
+
},
|
|
1035
|
+
settings: {
|
|
1036
|
+
get persona () {
|
|
1037
|
+
return $mj_ai_chat_settings_persona;
|
|
1038
|
+
}
|
|
1039
|
+
},
|
|
1040
|
+
get setFirstMesIndex () {
|
|
1041
|
+
return $mj_ai_chat_setFirstMesIndex;
|
|
1042
|
+
}
|
|
1043
|
+
}
|
|
979
1044
|
}
|
|
980
|
-
}
|
|
981
|
-
|
|
982
|
-
|
|
983
|
-
|
|
984
|
-
|
|
985
|
-
|
|
1045
|
+
};
|
|
1046
|
+
window.$mj_engine = {
|
|
1047
|
+
...$mj_engine,
|
|
1048
|
+
bind ({ messageId, swipeId }) {
|
|
1049
|
+
return {
|
|
1050
|
+
ai: {
|
|
1051
|
+
chat: {
|
|
1052
|
+
mjv: {
|
|
1053
|
+
get (path) {
|
|
1054
|
+
return $mj_ai_chat_mjv_get?.(messageId, swipeId, path);
|
|
1055
|
+
},
|
|
1056
|
+
getAll () {
|
|
1057
|
+
return $mj_ai_chat_mjv_getAll?.(messageId, swipeId) ?? {};
|
|
1058
|
+
}
|
|
1059
|
+
},
|
|
1060
|
+
get complete () {
|
|
1061
|
+
return $mj_ai_chat_complete;
|
|
1062
|
+
},
|
|
1063
|
+
get project () {
|
|
1064
|
+
return $mj_ai_chat_project;
|
|
1065
|
+
},
|
|
1066
|
+
settings: {
|
|
1067
|
+
get persona () {
|
|
1068
|
+
return $mj_ai_chat_settings_persona;
|
|
1069
|
+
}
|
|
1070
|
+
},
|
|
1071
|
+
get setFirstMesIndex () {
|
|
1072
|
+
return $mj_ai_chat_setFirstMesIndex;
|
|
1073
|
+
}
|
|
1074
|
+
}
|
|
1075
|
+
}
|
|
1076
|
+
};
|
|
986
1077
|
}
|
|
1078
|
+
};
|
|
1079
|
+
function useMjEngine({ projectInfo, activePersona, onSend, messages, setSwipe }) {
|
|
1080
|
+
useEffect(()=>{
|
|
1081
|
+
$mj_ai_chat_project = projectInfo ?? void 0;
|
|
1082
|
+
$mj_ai_chat_settings_persona = activePersona ?? void 0;
|
|
1083
|
+
}, [
|
|
1084
|
+
projectInfo,
|
|
1085
|
+
activePersona
|
|
1086
|
+
]);
|
|
1087
|
+
useEffect(()=>{
|
|
1088
|
+
$mj_ai_chat_complete = async (message)=>{
|
|
1089
|
+
await onSend(message);
|
|
1090
|
+
};
|
|
1091
|
+
$mj_ai_chat_setFirstMesIndex = async (oneBasedIndex)=>{
|
|
1092
|
+
if (messages.length > 1) throw new Error('已有新消息,不允许切换开场白');
|
|
1093
|
+
if (0 === messages.length) throw new Error('断言失败:没有开场消息,无法切换开场白');
|
|
1094
|
+
const zeroBasedIndex = Math.floor(oneBasedIndex) - 1;
|
|
1095
|
+
const swipeLength = messages[0].swipes.length;
|
|
1096
|
+
if (zeroBasedIndex < 0 || zeroBasedIndex >= swipeLength) return;
|
|
1097
|
+
setSwipe(messages[0].id, zeroBasedIndex);
|
|
1098
|
+
};
|
|
1099
|
+
$mj_ai_chat_mjv_getAll = (messageId, swipeId)=>messages.find((m)=>m.id === messageId)?.swipes[swipeId]?.mjv?.value;
|
|
1100
|
+
$mj_ai_chat_mjv_get = (messageId, swipeId, path)=>{
|
|
1101
|
+
const mjv = $mj_ai_chat_mjv_getAll?.(messageId, swipeId);
|
|
1102
|
+
if (!mjv) return;
|
|
1103
|
+
return get(mjv, path);
|
|
1104
|
+
};
|
|
1105
|
+
}, [
|
|
1106
|
+
onSend,
|
|
1107
|
+
messages,
|
|
1108
|
+
setSwipe
|
|
1109
|
+
]);
|
|
1110
|
+
}
|
|
1111
|
+
const errorMessages = [
|
|
1112
|
+
'network error',
|
|
1113
|
+
'NetworkError when attempting to fetch resource.',
|
|
1114
|
+
'The Internet connection appears to be offline.',
|
|
1115
|
+
'Network request failed',
|
|
1116
|
+
'Load failed',
|
|
1117
|
+
'Failed to fetch'
|
|
1118
|
+
];
|
|
1119
|
+
function isNetworkError(message) {
|
|
1120
|
+
return errorMessages.some((m)=>message.includes(m));
|
|
987
1121
|
}
|
|
988
|
-
class
|
|
1122
|
+
class SendMessageError extends Error {
|
|
989
1123
|
constructor(message, cause){
|
|
990
1124
|
super(message);
|
|
991
1125
|
this.name = this.constructor.name;
|
|
992
1126
|
this.cause = cause;
|
|
993
1127
|
}
|
|
994
1128
|
}
|
|
995
|
-
async function* callSdk(mujian, content, type = 'generate',
|
|
1129
|
+
async function* callSdk(mujian, content, type = 'generate', conversationVersion, assisMsgId) {
|
|
996
1130
|
const queue = [];
|
|
997
1131
|
let resolveWait = null;
|
|
998
1132
|
let done = false;
|
|
@@ -1000,7 +1134,6 @@ async function* callSdk(mujian, content, type = 'generate', signal) {
|
|
|
1000
1134
|
try {
|
|
1001
1135
|
const onData = (data)=>{
|
|
1002
1136
|
if (error) return;
|
|
1003
|
-
if ('string' != typeof data) return;
|
|
1004
1137
|
queue.push(data);
|
|
1005
1138
|
if (resolveWait) {
|
|
1006
1139
|
resolveWait();
|
|
@@ -1021,9 +1154,13 @@ async function* callSdk(mujian, content, type = 'generate', signal) {
|
|
|
1021
1154
|
resolveWait = null;
|
|
1022
1155
|
}
|
|
1023
1156
|
};
|
|
1024
|
-
if ('generate' === type) mujian.ai.chat.complete(content,
|
|
1025
|
-
else if ('regenerate' === type) mujian.ai.chat.regenerate(
|
|
1026
|
-
else mujian.ai.chat.continue(
|
|
1157
|
+
if ('generate' === type) mujian.ai.chat.complete(content, conversationVersion, onData).then(then).catch(catcher);
|
|
1158
|
+
else if ('regenerate' === type) mujian.ai.chat.regenerate(conversationVersion, onData).then(then).catch(catcher);
|
|
1159
|
+
else if ('continue' === type) mujian.ai.chat.continue(conversationVersion, onData).then(then).catch(catcher);
|
|
1160
|
+
else {
|
|
1161
|
+
if (!assisMsgId) throw new Error('call recover without assisMsgId');
|
|
1162
|
+
mujian.ai.chat.recover(conversationVersion, assisMsgId, onData).then(then).catch(catcher);
|
|
1163
|
+
}
|
|
1027
1164
|
} catch (err) {
|
|
1028
1165
|
error = err;
|
|
1029
1166
|
done = true;
|
|
@@ -1036,56 +1173,44 @@ async function* callSdk(mujian, content, type = 'generate', signal) {
|
|
|
1036
1173
|
});
|
|
1037
1174
|
}
|
|
1038
1175
|
const NOT_SAVED_MSG_ID_PREFIX = 'not_saved';
|
|
1039
|
-
const
|
|
1040
|
-
哎呀,AI线路好像抽风了,重说一下试试吧~`;
|
|
1041
|
-
const useChatStreaming = ({ common, setError, setMessages, mujian })=>{
|
|
1176
|
+
const useChatStreaming = ({ common, setError, setMessages, getMessages, setInput, mujian, conversationVersion: conversationVersionRef })=>{
|
|
1042
1177
|
const { body } = common;
|
|
1043
1178
|
const [isStreaming, setIsStreaming] = useState(false);
|
|
1044
|
-
const chatStreaming = useCallback(async ({ query, regenerate, is_continue,
|
|
1179
|
+
const chatStreaming = useCallback(async ({ query, regenerate, is_continue, conversationVersion })=>{
|
|
1045
1180
|
try {
|
|
1046
1181
|
setError(void 0);
|
|
1047
1182
|
setIsStreaming(true);
|
|
1183
|
+
const backupMessages = getMessages();
|
|
1048
1184
|
const userMessage = {
|
|
1049
1185
|
id: `${NOT_SAVED_MSG_ID_PREFIX}_user_${Date.now()}`,
|
|
1050
|
-
|
|
1051
|
-
|
|
1052
|
-
|
|
1186
|
+
isUser: true,
|
|
1187
|
+
swipes: [
|
|
1188
|
+
{
|
|
1189
|
+
content: query ?? ''
|
|
1190
|
+
}
|
|
1191
|
+
],
|
|
1053
1192
|
activeSwipeId: 0,
|
|
1054
|
-
|
|
1055
|
-
sendAt: new Date(),
|
|
1056
|
-
swipeInfo: []
|
|
1193
|
+
isGenerating: false
|
|
1057
1194
|
};
|
|
1058
1195
|
const aiMessage = {
|
|
1059
1196
|
id: `${NOT_SAVED_MSG_ID_PREFIX}_assistant_${Date.now()}`,
|
|
1060
|
-
|
|
1061
|
-
role: 'assistant',
|
|
1197
|
+
isUser: false,
|
|
1062
1198
|
swipes: [
|
|
1063
|
-
|
|
1199
|
+
{
|
|
1200
|
+
content: ''
|
|
1201
|
+
}
|
|
1064
1202
|
],
|
|
1065
1203
|
activeSwipeId: 0,
|
|
1066
|
-
|
|
1067
|
-
sendAt: new Date(),
|
|
1068
|
-
swipeInfo: [
|
|
1069
|
-
{}
|
|
1070
|
-
]
|
|
1204
|
+
isGenerating: true
|
|
1071
1205
|
};
|
|
1072
|
-
if (regenerate) setMessages((
|
|
1073
|
-
const
|
|
1074
|
-
|
|
1075
|
-
|
|
1076
|
-
|
|
1077
|
-
|
|
1078
|
-
|
|
1079
|
-
|
|
1080
|
-
swipes: [
|
|
1081
|
-
...lastMessage.swipes,
|
|
1082
|
-
''
|
|
1083
|
-
],
|
|
1084
|
-
content: '',
|
|
1085
|
-
isStreaming: true
|
|
1086
|
-
};
|
|
1087
|
-
return newMessages;
|
|
1088
|
-
});
|
|
1206
|
+
if (regenerate) setMessages(produce((draft)=>{
|
|
1207
|
+
const lastMessage = draft[draft.length - 1];
|
|
1208
|
+
lastMessage.activeSwipeId = lastMessage.swipes.length;
|
|
1209
|
+
lastMessage.swipes.push({
|
|
1210
|
+
content: ''
|
|
1211
|
+
});
|
|
1212
|
+
lastMessage.isGenerating = true;
|
|
1213
|
+
}));
|
|
1089
1214
|
else is_continue ? setMessages((prev)=>[
|
|
1090
1215
|
...prev,
|
|
1091
1216
|
aiMessage
|
|
@@ -1094,111 +1219,45 @@ const useChatStreaming = ({ common, setError, setMessages, mujian })=>{
|
|
|
1094
1219
|
userMessage,
|
|
1095
1220
|
aiMessage
|
|
1096
1221
|
]);
|
|
1097
|
-
const stream = callSdk(mujian, query || '', is_continue ? 'continue' : regenerate ? 'regenerate' : 'generate',
|
|
1098
|
-
let buffer = '';
|
|
1099
|
-
let content = '';
|
|
1222
|
+
const stream = callSdk(mujian, query || '', is_continue ? 'continue' : regenerate ? 'regenerate' : 'generate', conversationVersion);
|
|
1100
1223
|
try {
|
|
1101
1224
|
for await (const chunk of stream){
|
|
1102
|
-
|
|
1103
|
-
|
|
1104
|
-
|
|
1105
|
-
|
|
1106
|
-
|
|
1107
|
-
|
|
1108
|
-
const parsedData = JSON.parse(data);
|
|
1109
|
-
if (regenerate || 'meta' !== parsedData.type) {
|
|
1110
|
-
if ('stream' === parsedData.type) {
|
|
1111
|
-
const partialContent = parsedData.choices[0].delta.content;
|
|
1112
|
-
parsedData.choices[0].delta.reasoning;
|
|
1113
|
-
content += partialContent;
|
|
1114
|
-
if (content || '' === content) {
|
|
1115
|
-
setMessages((prev)=>{
|
|
1116
|
-
const newMessages = [
|
|
1117
|
-
...prev
|
|
1118
|
-
];
|
|
1119
|
-
const lastMessage = newMessages[newMessages.length - 1];
|
|
1120
|
-
lastMessage.swipes[lastMessage.activeSwipeId] = content;
|
|
1121
|
-
newMessages[newMessages.length - 1] = {
|
|
1122
|
-
...lastMessage,
|
|
1123
|
-
content: content,
|
|
1124
|
-
isStreaming: true
|
|
1125
|
-
};
|
|
1126
|
-
return newMessages;
|
|
1127
|
-
});
|
|
1128
|
-
await new Promise((resolve)=>setTimeout(resolve, 10));
|
|
1129
|
-
} else {
|
|
1130
|
-
console.error('data', data);
|
|
1131
|
-
setError(new InvalidDeltaContentError(data));
|
|
1132
|
-
}
|
|
1133
|
-
} else if ('mjv' === parsedData.type) {
|
|
1134
|
-
const { value, delta, schema } = parsedData;
|
|
1135
|
-
setMessages((prev)=>{
|
|
1136
|
-
const newMessages = [
|
|
1137
|
-
...prev
|
|
1138
|
-
];
|
|
1139
|
-
const lastMessage = newMessages[newMessages.length - 1];
|
|
1140
|
-
const mjv = {
|
|
1141
|
-
value,
|
|
1142
|
-
delta,
|
|
1143
|
-
schema
|
|
1144
|
-
};
|
|
1145
|
-
const newSwipeInfo = lastMessage.swipeInfo;
|
|
1146
|
-
if (newSwipeInfo[lastMessage.activeSwipeId]) newSwipeInfo[lastMessage.activeSwipeId].mjv = mjv;
|
|
1147
|
-
else newSwipeInfo[lastMessage.activeSwipeId] = {
|
|
1148
|
-
mjv
|
|
1149
|
-
};
|
|
1150
|
-
newMessages[newMessages.length - 1] = {
|
|
1151
|
-
...lastMessage,
|
|
1152
|
-
swipeInfo: newSwipeInfo,
|
|
1153
|
-
mjv
|
|
1154
|
-
};
|
|
1155
|
-
return newMessages;
|
|
1156
|
-
});
|
|
1157
|
-
}
|
|
1158
|
-
} else {
|
|
1159
|
-
const { question_id, reply_id } = parsedData;
|
|
1160
|
-
setMessages((prev)=>{
|
|
1161
|
-
const newMessages = [
|
|
1162
|
-
...prev
|
|
1163
|
-
];
|
|
1164
|
-
if (question_id && !is_continue) newMessages[newMessages.length - 2].id = question_id;
|
|
1165
|
-
const lastMessage = newMessages[newMessages.length - 1];
|
|
1166
|
-
newMessages[newMessages.length - 1] = {
|
|
1167
|
-
...lastMessage,
|
|
1168
|
-
id: reply_id
|
|
1169
|
-
};
|
|
1170
|
-
return newMessages;
|
|
1171
|
-
});
|
|
1172
|
-
continue;
|
|
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;
|
|
1173
1231
|
}
|
|
1174
|
-
|
|
1175
|
-
|
|
1176
|
-
|
|
1177
|
-
|
|
1178
|
-
|
|
1179
|
-
|
|
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[draft.length - 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));
|
|
1180
1247
|
}
|
|
1181
1248
|
}
|
|
1182
1249
|
} catch (error) {
|
|
1183
1250
|
Log.e('Stream error', error);
|
|
1184
|
-
'object' == typeof error && error && 'message' in error && 'string' == typeof error.message
|
|
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);
|
|
1185
1256
|
} finally{
|
|
1186
|
-
|
|
1187
|
-
|
|
1188
|
-
|
|
1189
|
-
|
|
1190
|
-
];
|
|
1191
|
-
const lastMessage = {
|
|
1192
|
-
...newMessages[newMessages.length - 1],
|
|
1193
|
-
isStreaming: false
|
|
1194
|
-
};
|
|
1195
|
-
if (!lastMessage.swipes[lastMessage.activeSwipeId]) {
|
|
1196
|
-
lastMessage.swipes[lastMessage.activeSwipeId] = FALLBACK_MESSAGE;
|
|
1197
|
-
lastMessage.content = FALLBACK_MESSAGE;
|
|
1198
|
-
}
|
|
1199
|
-
newMessages[newMessages.length - 1] = lastMessage;
|
|
1200
|
-
return newMessages;
|
|
1201
|
-
});
|
|
1257
|
+
setMessages(produce((draft)=>{
|
|
1258
|
+
const lastMessage = draft[draft.length - 1];
|
|
1259
|
+
lastMessage.isGenerating = false;
|
|
1260
|
+
}));
|
|
1202
1261
|
}
|
|
1203
1262
|
} catch (error) {
|
|
1204
1263
|
console.error('Error:', error);
|
|
@@ -1211,15 +1270,48 @@ const useChatStreaming = ({ common, setError, setMessages, mujian })=>{
|
|
|
1211
1270
|
body,
|
|
1212
1271
|
mujian
|
|
1213
1272
|
]);
|
|
1273
|
+
const recoverStreaming = useCallback(async (messageId, conversationVersion)=>{
|
|
1274
|
+
const stream = callSdk(mujian, '', 'recover', conversationVersion, messageId);
|
|
1275
|
+
try {
|
|
1276
|
+
for await (const chunk of stream){
|
|
1277
|
+
if (!chunk) return;
|
|
1278
|
+
if ('data' === chunk.type) setMessages(produce((draft)=>{
|
|
1279
|
+
const msg = draft.find((m)=>m.id === messageId);
|
|
1280
|
+
if (!msg) return;
|
|
1281
|
+
msg.swipes[msg.activeSwipeId] = {
|
|
1282
|
+
content: chunk.content,
|
|
1283
|
+
mjv: chunk.mjv
|
|
1284
|
+
};
|
|
1285
|
+
if (chunk.finishReason) msg.finishReason = chunk.finishReason;
|
|
1286
|
+
if (chunk.error) msg.error = chunk.error;
|
|
1287
|
+
}));
|
|
1288
|
+
}
|
|
1289
|
+
} catch (error) {
|
|
1290
|
+
Log.e('Stream error', error);
|
|
1291
|
+
if ('object' == typeof error && error && 'message' in error && 'string' == typeof error.message) isNetworkError(error.message) ? setError(new SendMessageError('E_NETWORK_ERROR')) : setError(new SendMessageError(error.message));
|
|
1292
|
+
else setError(error);
|
|
1293
|
+
} finally{
|
|
1294
|
+
console.log('finally');
|
|
1295
|
+
setMessages(produce((draft)=>{
|
|
1296
|
+
const msg = draft.find((m)=>m.id === messageId);
|
|
1297
|
+
console.log('finally', msg);
|
|
1298
|
+
if (!msg) return;
|
|
1299
|
+
msg.isGenerating = false;
|
|
1300
|
+
}));
|
|
1301
|
+
}
|
|
1302
|
+
}, [
|
|
1303
|
+
mujian
|
|
1304
|
+
]);
|
|
1214
1305
|
return {
|
|
1215
1306
|
chatStreaming,
|
|
1216
|
-
isStreaming
|
|
1307
|
+
isStreaming,
|
|
1308
|
+
recoverStreaming
|
|
1217
1309
|
};
|
|
1218
1310
|
};
|
|
1219
|
-
const useChat = ({ body, onError, onFinish, pageSize })=>{
|
|
1311
|
+
const useChat = ({ body, onError, onFinish, pageSize = 10 })=>{
|
|
1220
1312
|
const [error, _setError] = useState();
|
|
1221
1313
|
const [input, setInput] = useState('');
|
|
1222
|
-
const
|
|
1314
|
+
const conversationVersion = useRef(0);
|
|
1223
1315
|
const mujian = useMujian();
|
|
1224
1316
|
const setError = (error)=>{
|
|
1225
1317
|
_setError(error);
|
|
@@ -1234,12 +1326,13 @@ const useChat = ({ body, onError, onFinish, pageSize })=>{
|
|
|
1234
1326
|
};
|
|
1235
1327
|
try {
|
|
1236
1328
|
const resp = await mujian.ai.chat.message.getPage(current?.cursor, pageSize);
|
|
1329
|
+
conversationVersion.current = resp.conversationVersion;
|
|
1330
|
+
const lastMessage = resp.messages.at(-1);
|
|
1331
|
+
console.log(lastMessage);
|
|
1332
|
+
if (lastMessage?.isGenerating) recoverStreaming(lastMessage.id, conversationVersion.current);
|
|
1237
1333
|
return {
|
|
1238
1334
|
cursor: resp.nextCursor,
|
|
1239
|
-
list: resp.messages
|
|
1240
|
-
...m,
|
|
1241
|
-
mjv: m.swipeInfo[m.activeSwipeId]?.mjv
|
|
1242
|
-
})),
|
|
1335
|
+
list: resp.messages,
|
|
1243
1336
|
noMore: !resp.nextCursor
|
|
1244
1337
|
};
|
|
1245
1338
|
} finally{
|
|
@@ -1270,13 +1363,19 @@ const useChat = ({ body, onError, onFinish, pageSize })=>{
|
|
|
1270
1363
|
list: newList
|
|
1271
1364
|
});
|
|
1272
1365
|
};
|
|
1273
|
-
const
|
|
1366
|
+
const getMessages = useCallback(()=>latestListRef.current, [
|
|
1367
|
+
latestListRef
|
|
1368
|
+
]);
|
|
1369
|
+
const { chatStreaming, isStreaming, recoverStreaming } = useChatStreaming({
|
|
1274
1370
|
common: {
|
|
1275
1371
|
body
|
|
1276
1372
|
},
|
|
1277
1373
|
setError,
|
|
1278
1374
|
setMessages,
|
|
1279
|
-
|
|
1375
|
+
getMessages,
|
|
1376
|
+
setInput,
|
|
1377
|
+
mujian,
|
|
1378
|
+
conversationVersion
|
|
1280
1379
|
});
|
|
1281
1380
|
useUpdateEffect(()=>{
|
|
1282
1381
|
if (!isStreaming) {
|
|
@@ -1288,18 +1387,14 @@ const useChat = ({ body, onError, onFinish, pageSize })=>{
|
|
|
1288
1387
|
]);
|
|
1289
1388
|
const append = useCallback(async (query)=>{
|
|
1290
1389
|
if (isStreaming) throw new Error('useChat is streaming already.');
|
|
1291
|
-
const controller = new AbortController();
|
|
1292
|
-
setAbortController(controller);
|
|
1293
1390
|
try {
|
|
1294
1391
|
await chatStreaming({
|
|
1295
1392
|
query,
|
|
1296
|
-
|
|
1393
|
+
conversationVersion: conversationVersion.current
|
|
1297
1394
|
});
|
|
1298
1395
|
} catch (e) {
|
|
1299
1396
|
setError(e);
|
|
1300
1397
|
throw e;
|
|
1301
|
-
} finally{
|
|
1302
|
-
setAbortController(void 0);
|
|
1303
1398
|
}
|
|
1304
1399
|
}, [
|
|
1305
1400
|
isStreaming,
|
|
@@ -1307,20 +1402,17 @@ const useChat = ({ body, onError, onFinish, pageSize })=>{
|
|
|
1307
1402
|
]);
|
|
1308
1403
|
const regenerate = useCallback(async ()=>{
|
|
1309
1404
|
if (isStreaming) throw new Error('useChat is streaming already.');
|
|
1310
|
-
const
|
|
1311
|
-
setAbortController(controller);
|
|
1312
|
-
const lastMessage = messages.findLast((message)=>'user' === message.role);
|
|
1405
|
+
const lastMessage = messages.findLast((message)=>message.isUser);
|
|
1313
1406
|
try {
|
|
1407
|
+
const query = lastMessage ? lastMessage.swipes[lastMessage.activeSwipeId].content : '';
|
|
1314
1408
|
await chatStreaming({
|
|
1315
|
-
query
|
|
1409
|
+
query,
|
|
1316
1410
|
regenerate: true,
|
|
1317
|
-
|
|
1411
|
+
conversationVersion: conversationVersion.current
|
|
1318
1412
|
});
|
|
1319
1413
|
} catch (e) {
|
|
1320
1414
|
setError(e);
|
|
1321
1415
|
throw e;
|
|
1322
|
-
} finally{
|
|
1323
|
-
setAbortController(void 0);
|
|
1324
1416
|
}
|
|
1325
1417
|
}, [
|
|
1326
1418
|
isStreaming,
|
|
@@ -1329,49 +1421,55 @@ const useChat = ({ body, onError, onFinish, pageSize })=>{
|
|
|
1329
1421
|
]);
|
|
1330
1422
|
const continueGenerate = useCallback(async ()=>{
|
|
1331
1423
|
if (isStreaming) throw new Error('useChat is streaming already.');
|
|
1332
|
-
const controller = new AbortController();
|
|
1333
|
-
setAbortController(controller);
|
|
1334
1424
|
try {
|
|
1335
1425
|
await chatStreaming({
|
|
1336
1426
|
query: '',
|
|
1337
1427
|
is_continue: true,
|
|
1338
|
-
|
|
1428
|
+
conversationVersion: conversationVersion.current
|
|
1339
1429
|
});
|
|
1340
1430
|
} catch (e) {
|
|
1341
1431
|
setError(e);
|
|
1342
1432
|
throw e;
|
|
1343
|
-
} finally{
|
|
1344
|
-
setAbortController(void 0);
|
|
1345
1433
|
}
|
|
1346
1434
|
}, [
|
|
1347
1435
|
isStreaming,
|
|
1348
1436
|
chatStreaming
|
|
1349
1437
|
]);
|
|
1350
1438
|
const stop = ()=>{
|
|
1351
|
-
|
|
1439
|
+
const assisMsgId = messages.at(-1)?.id;
|
|
1440
|
+
if (!assisMsgId) return;
|
|
1441
|
+
mujian.ai.chat.stop(conversationVersion.current, assisMsgId);
|
|
1352
1442
|
};
|
|
1353
1443
|
const setSwipe = async (messageId, swipeId)=>{
|
|
1354
1444
|
if (swipeId < 0) return;
|
|
1355
1445
|
setMessages((prev)=>prev.map((msg)=>msg.id === messageId && swipeId < msg.swipes.length ? {
|
|
1356
1446
|
...msg,
|
|
1357
|
-
activeSwipeId: swipeId
|
|
1358
|
-
content: msg.swipes[swipeId],
|
|
1359
|
-
mjv: msg.swipeInfo[swipeId]?.mjv
|
|
1447
|
+
activeSwipeId: swipeId
|
|
1360
1448
|
} : msg));
|
|
1361
|
-
await mujian.ai.chat.message.swipe(messageId, swipeId);
|
|
1449
|
+
const resp = await mujian.ai.chat.message.swipe(messageId, swipeId);
|
|
1450
|
+
const schema = z.object({
|
|
1451
|
+
newConversationVersion: z.number()
|
|
1452
|
+
});
|
|
1453
|
+
const { data, success } = schema.safeParse(resp);
|
|
1454
|
+
if (success && data.newConversationVersion) conversationVersion.current = data.newConversationVersion;
|
|
1362
1455
|
};
|
|
1363
1456
|
const editMessage = async (messageId, content)=>{
|
|
1364
|
-
await mujian.ai.chat.message.editOne(messageId, content);
|
|
1457
|
+
const resp = await mujian.ai.chat.message.editOne(messageId, content);
|
|
1458
|
+
const schema = z.object({
|
|
1459
|
+
newConversationVersion: z.number()
|
|
1460
|
+
});
|
|
1461
|
+
const { data, success } = schema.safeParse(resp);
|
|
1462
|
+
if (success && data.newConversationVersion) conversationVersion.current = data.newConversationVersion;
|
|
1365
1463
|
const patchMessage = (msg)=>{
|
|
1366
1464
|
const newMsg = {
|
|
1367
1465
|
...msg,
|
|
1368
1466
|
content
|
|
1369
1467
|
};
|
|
1370
|
-
if (
|
|
1468
|
+
if (!newMsg.isUser) {
|
|
1371
1469
|
newMsg.swipes = [
|
|
1372
1470
|
...newMsg.swipes
|
|
1373
1471
|
];
|
|
1374
|
-
newMsg.swipes[newMsg.activeSwipeId] = content;
|
|
1472
|
+
newMsg.swipes[newMsg.activeSwipeId].content = content;
|
|
1375
1473
|
}
|
|
1376
1474
|
return newMsg;
|
|
1377
1475
|
};
|
|
@@ -1379,7 +1477,12 @@ const useChat = ({ body, onError, onFinish, pageSize })=>{
|
|
|
1379
1477
|
};
|
|
1380
1478
|
const deleteMessage = async (messageId)=>{
|
|
1381
1479
|
if (!messageId.startsWith(NOT_SAVED_MSG_ID_PREFIX)) try {
|
|
1382
|
-
await mujian.ai.chat.message.deleteOne(messageId);
|
|
1480
|
+
const resp = await mujian.ai.chat.message.deleteOne(messageId);
|
|
1481
|
+
const schema = z.object({
|
|
1482
|
+
newConversationVersion: z.number()
|
|
1483
|
+
});
|
|
1484
|
+
const { data, success } = schema.safeParse(resp);
|
|
1485
|
+
if (success && data.newConversationVersion) conversationVersion.current = data.newConversationVersion;
|
|
1383
1486
|
} catch (e) {
|
|
1384
1487
|
if (e?.code !== 2011030004) throw e;
|
|
1385
1488
|
}
|
|
@@ -1410,4 +1513,4 @@ const useChat = ({ body, onError, onFinish, pageSize })=>{
|
|
|
1410
1513
|
messagesStatus: messageLoadError ? 'error' : loadingMore || loading ? 'loading' : data?.noMore ? 'all-loaded' : 'has-more'
|
|
1411
1514
|
};
|
|
1412
1515
|
};
|
|
1413
|
-
export { MdRenderer, MujianProvider, MujianSpinner, Thread, useChat, useMujian };
|
|
1516
|
+
export { MdRenderer, MujianProvider, MujianSpinner, Thread, useChat, useChatContext, useMjEngine, useMujian };
|