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 CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "myagent-ai",
3
- "version": "1.9.3",
3
+ "version": "1.9.4",
4
4
  "description": "本地桌面端执行型AI助手 - Open Interpreter 风格 | Local Desktop Execution-Oriented AI Assistant",
5
5
  "main": "main.py",
6
6
  "bin": {
@@ -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
- msgParts.push({type: 'text', content: currentText});
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
- // Build backward-compat content from all parts + streaming text
954
- const allText = msgParts.filter(p => p.type === 'text').map(p => p.content).join('\n\n')
955
- + (currentText.trim() ? '\n\n' + currentText : '');
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 = msgParts.filter(p => p.type === 'text').map(p => p.content).join('\n\n') || '(无回复)';
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 = msgParts.filter(p => p.type === 'text').map(p => p.content).join('\n\n') || '';
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 (similar to thought_delta)
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
- state.messages[msgIdx].content = msgParts.filter(p => p.type === 'text').map(p => p.content).join('\n\n') || '(无回复)';
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
- state.messages[msgIdx].content = msgParts.filter(p => p.type === 'text').map(p => p.content).join('\n\n') || '(无回复)';
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 事件实时推送,无需再轮询