myagent-ai 1.9.3 → 1.9.4
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/package.json +1 -1
- package/web/ui/chat/flow_engine.js +64 -12
package/package.json
CHANGED
|
@@ -814,6 +814,31 @@ function showToolResultModal(msgIndex, eventId) {
|
|
|
814
814
|
document.body.appendChild(overlay);
|
|
815
815
|
}
|
|
816
816
|
|
|
817
|
+
// ══════════════════════════════════════════════════════
|
|
818
|
+
// ── V2 Content Assembler (V2 内容组装) ──
|
|
819
|
+
// ══════════════════════════════════════════════════════
|
|
820
|
+
|
|
821
|
+
function _assembleV2Content(msg, msgParts) {
|
|
822
|
+
// Priority 1: V2 reasoning text (user-facing response from v2_reasoning events)
|
|
823
|
+
if (msg._v2Reasoning && msg._v2Reasoning.trim()) {
|
|
824
|
+
return msg._v2Reasoning.trim();
|
|
825
|
+
}
|
|
826
|
+
// Priority 2: V2 ask user text
|
|
827
|
+
if (msg._askUser && msg._askUser.trim()) {
|
|
828
|
+
return msg._askUser.trim();
|
|
829
|
+
}
|
|
830
|
+
// Priority 3: V1 text parts (backward compat — non-V2 mode)
|
|
831
|
+
var textParts = msgParts.filter(function(p) { return p.type === 'text'; });
|
|
832
|
+
if (textParts.length > 0) {
|
|
833
|
+
return textParts.map(function(p) { return p.content; }).join('\n\n');
|
|
834
|
+
}
|
|
835
|
+
// Priority 4: raw content from message (server-stored response)
|
|
836
|
+
if (msg.content && msg.content.trim() && msg.content !== '(无回复)') {
|
|
837
|
+
return msg.content.trim();
|
|
838
|
+
}
|
|
839
|
+
return '(无回复)';
|
|
840
|
+
}
|
|
841
|
+
|
|
817
842
|
// ══════════════════════════════════════════════════════
|
|
818
843
|
// ── Send Message (核心 SSE 流式消息发送) ──
|
|
819
844
|
// ══════════════════════════════════════════════════════
|
|
@@ -904,10 +929,17 @@ async function sendMessage() {
|
|
|
904
929
|
let msgIdx = state.messages.length;
|
|
905
930
|
let sessionIdReceived = sessionId;
|
|
906
931
|
let fullThought = '';
|
|
932
|
+
let _isV2Mode = false; // Track whether V2 structured output events are received
|
|
933
|
+
let _v2RawXml = ''; // In V2 mode, accumulate raw XML from text_delta separately
|
|
934
|
+
let _v2ReasoningText = ''; // Accumulated V2 reasoning text for content
|
|
907
935
|
|
|
908
936
|
function flushCurrentText() {
|
|
909
937
|
if (currentText.trim()) {
|
|
910
|
-
|
|
938
|
+
// In V2 mode, text_delta contains raw XML — do NOT add to msgParts as user-facing text
|
|
939
|
+
if (!_isV2Mode) {
|
|
940
|
+
msgParts.push({type: 'text', content: currentText});
|
|
941
|
+
}
|
|
942
|
+
// Always accumulate for backward compat content field
|
|
911
943
|
}
|
|
912
944
|
currentText = '';
|
|
913
945
|
}
|
|
@@ -950,12 +982,16 @@ async function sendMessage() {
|
|
|
950
982
|
} else if (evt.type === 'text_delta') {
|
|
951
983
|
// Incremental streaming token
|
|
952
984
|
currentText += evt.content;
|
|
953
|
-
|
|
954
|
-
|
|
955
|
-
|
|
985
|
+
if (_isV2Mode) {
|
|
986
|
+
// In V2 mode, text_delta contains raw XML — store separately, not as user-facing content
|
|
987
|
+
_v2RawXml = currentText;
|
|
988
|
+
// Show V2 reasoning text as streaming content (if available)
|
|
989
|
+
state.messages[msgIdx]._streamingText = _v2ReasoningText || '';
|
|
990
|
+
} else {
|
|
991
|
+
// V1 mode: text_delta IS the user-facing content
|
|
992
|
+
state.messages[msgIdx]._streamingText = currentText;
|
|
993
|
+
}
|
|
956
994
|
state.messages[msgIdx].parts = [...msgParts];
|
|
957
|
-
state.messages[msgIdx]._streamingText = currentText;
|
|
958
|
-
state.messages[msgIdx].content = allText;
|
|
959
995
|
throttledStreamUpdate(msgIdx);
|
|
960
996
|
// ── 分段流式 TTS:推送增量文本 ──
|
|
961
997
|
if (ttsManager.enabled && !ttsManager._streamActive) {
|
|
@@ -982,7 +1018,7 @@ async function sendMessage() {
|
|
|
982
1018
|
if (state.messages[msgIdx]) {
|
|
983
1019
|
state.messages[msgIdx].streaming = false;
|
|
984
1020
|
state.messages[msgIdx].parts = [...msgParts];
|
|
985
|
-
state.messages[msgIdx].content =
|
|
1021
|
+
state.messages[msgIdx].content = _assembleV2Content(state.messages[msgIdx], msgParts);
|
|
986
1022
|
state.messages[msgIdx]._streamingText = '';
|
|
987
1023
|
if (allExecEvents.length > 0) state.messages[msgIdx].exec_events = [...allExecEvents];
|
|
988
1024
|
}
|
|
@@ -1000,7 +1036,7 @@ async function sendMessage() {
|
|
|
1000
1036
|
flushCurrentText();
|
|
1001
1037
|
state.messages[msgIdx].parts = [...msgParts];
|
|
1002
1038
|
state.messages[msgIdx]._streamingText = '';
|
|
1003
|
-
state.messages[msgIdx].content =
|
|
1039
|
+
state.messages[msgIdx].content = _assembleV2Content(state.messages[msgIdx], msgParts);
|
|
1004
1040
|
throttledStreamUpdate(msgIdx);
|
|
1005
1041
|
// 停止当前轮次的 TTS 播放,防止旧迭代语音与新迭代语音互相打断
|
|
1006
1042
|
if (ttsManager.enabled && ttsManager._streamActive) {
|
|
@@ -1041,7 +1077,10 @@ async function sendMessage() {
|
|
|
1041
1077
|
}
|
|
1042
1078
|
}
|
|
1043
1079
|
}
|
|
1044
|
-
// V2 Structured Output Events
|
|
1080
|
+
// V2 Structured Output Events — mark V2 mode
|
|
1081
|
+
} else if (evt.type === 'v2_context') {
|
|
1082
|
+
// V2 context event — confirms we're in V2 mode
|
|
1083
|
+
_isV2Mode = true;
|
|
1045
1084
|
} else if (evt.type === 'v2_output_parsed') {
|
|
1046
1085
|
// LLM output was parsed into structured format
|
|
1047
1086
|
// evt.data contains: {usersays_correct, task_plan, tools_to_call, remember, recall, ask_user, finish}
|
|
@@ -1120,11 +1159,22 @@ async function sendMessage() {
|
|
|
1120
1159
|
state.messages[msgIdx]._memorySaved = (state.messages[msgIdx]._memorySaved || '') +
|
|
1121
1160
|
(evt.content ? evt.content.substring(0, 100) : '');
|
|
1122
1161
|
} else if (evt.type === 'v2_reasoning') {
|
|
1123
|
-
// V2 reasoning text from model
|
|
1162
|
+
// V2 reasoning text from model — this IS the user-facing content in V2 mode
|
|
1124
1163
|
if (!state.messages[msgIdx]._v2Reasoning) {
|
|
1125
1164
|
state.messages[msgIdx]._v2Reasoning = '';
|
|
1126
1165
|
}
|
|
1166
|
+
// Add separator between multiple reasoning events (e.g., beforecalltext + final text)
|
|
1167
|
+
if (state.messages[msgIdx]._v2Reasoning.length > 0 && evt.content) {
|
|
1168
|
+
state.messages[msgIdx]._v2Reasoning += '\n\n';
|
|
1169
|
+
}
|
|
1127
1170
|
state.messages[msgIdx]._v2Reasoning += evt.content;
|
|
1171
|
+
_v2ReasoningText = state.messages[msgIdx]._v2Reasoning;
|
|
1172
|
+
// In V2 mode, update streaming text to show reasoning content
|
|
1173
|
+
if (_isV2Mode) {
|
|
1174
|
+
state.messages[msgIdx]._streamingText = _v2ReasoningText;
|
|
1175
|
+
// Also update content for real-time display
|
|
1176
|
+
state.messages[msgIdx].content = _v2ReasoningText;
|
|
1177
|
+
}
|
|
1128
1178
|
throttledStreamUpdate(msgIdx);
|
|
1129
1179
|
} else if (evt.type === 'done') {
|
|
1130
1180
|
flushCurrentText();
|
|
@@ -1135,7 +1185,8 @@ async function sendMessage() {
|
|
|
1135
1185
|
state.messages[msgIdx].parts = [...msgParts];
|
|
1136
1186
|
state.messages[msgIdx]._streamingText = '';
|
|
1137
1187
|
state.messages[msgIdx].exec_events = [...allExecEvents];
|
|
1138
|
-
|
|
1188
|
+
// Assemble final content: prefer V2 reasoning/ask text over raw XML
|
|
1189
|
+
state.messages[msgIdx].content = _assembleV2Content(state.messages[msgIdx], msgParts);
|
|
1139
1190
|
} else if (evt.type === 'reasoning_delta') {
|
|
1140
1191
|
// 模型推理过程增量文本(OpenAI o1/o3/DeepSeek-R1 等推理模型)
|
|
1141
1192
|
if (!state.messages[msgIdx].reasoning) state.messages[msgIdx].reasoning = '';
|
|
@@ -1164,7 +1215,8 @@ async function sendMessage() {
|
|
|
1164
1215
|
state.messages[msgIdx].parts = [...msgParts];
|
|
1165
1216
|
state.messages[msgIdx]._streamingText = '';
|
|
1166
1217
|
state.messages[msgIdx].exec_events = allExecEvents;
|
|
1167
|
-
|
|
1218
|
+
// Assemble final content: prefer V2 reasoning/ask text over raw XML
|
|
1219
|
+
state.messages[msgIdx].content = _assembleV2Content(state.messages[msgIdx], msgParts);
|
|
1168
1220
|
}
|
|
1169
1221
|
|
|
1170
1222
|
// Task list 已通过 SSE task_list_update 事件实时推送,无需再轮询
|