@siact/sime-x-vue 0.0.8 → 0.0.9

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.
@@ -999,6 +999,7 @@
999
999
 
1000
1000
  function useTTS(getVoiceConfig) {
1001
1001
  const isSpeaking = vue.ref(false);
1002
+ const hasPendingAudio = vue.ref(false);
1002
1003
  let instance = null;
1003
1004
  let initPromise = null;
1004
1005
  let audioCtx = null;
@@ -1049,6 +1050,7 @@
1049
1050
  });
1050
1051
  tts.onQueueEmpty(() => {
1051
1052
  isSpeaking.value = false;
1053
+ hasPendingAudio.value = false;
1052
1054
  onQueueEmptyCb?.();
1053
1055
  });
1054
1056
  tts.onError((err) => {
@@ -1074,6 +1076,7 @@
1074
1076
  const speak = async (text) => {
1075
1077
  const clean = stripMarkdown(text);
1076
1078
  if (!clean.trim()) return;
1079
+ hasPendingAudio.value = true;
1077
1080
  const tts = await ensureInstance();
1078
1081
  if (!tts) return;
1079
1082
  try {
@@ -1100,6 +1103,7 @@
1100
1103
  const stop = () => {
1101
1104
  sentenceBuffer = "";
1102
1105
  isSpeaking.value = false;
1106
+ hasPendingAudio.value = false;
1103
1107
  if (instance) {
1104
1108
  try {
1105
1109
  instance.stop();
@@ -1129,6 +1133,7 @@
1129
1133
  };
1130
1134
  return {
1131
1135
  isSpeaking,
1136
+ hasPendingAudio,
1132
1137
  warmUpAudio,
1133
1138
  speak,
1134
1139
  feed,
@@ -1144,7 +1149,14 @@
1144
1149
  const fadingOut = vue.ref(false);
1145
1150
  const stackRef = vue.ref(null);
1146
1151
  let dismissTimer = null;
1147
- const show = vue.computed(() => visible.value && !fadingOut.value);
1152
+ const hasOpened = vue.ref(false);
1153
+ const isTTSActive = () => !!(options.isSpeaking?.value || options.hasPendingAudio?.value);
1154
+ const isBusy = () => !!(options.isInvoking?.value || isTTSActive());
1155
+ const show = vue.computed(() => {
1156
+ if (!hasOpened.value) return false;
1157
+ if (isTTSActive()) return true;
1158
+ return visible.value && !fadingOut.value;
1159
+ });
1148
1160
  const style = vue.computed(() => ({
1149
1161
  width: options.bubbleSize?.width || void 0,
1150
1162
  maxHeight: options.bubbleSize?.maxHeight || void 0
@@ -1153,6 +1165,7 @@
1153
1165
  cancelDismiss();
1154
1166
  fadingOut.value = false;
1155
1167
  visible.value = true;
1168
+ hasOpened.value = true;
1156
1169
  };
1157
1170
  const cancelDismiss = () => {
1158
1171
  if (dismissTimer) {
@@ -1162,21 +1175,39 @@
1162
1175
  };
1163
1176
  const scheduleDismiss = () => {
1164
1177
  cancelDismiss();
1165
- if (options.isSpeaking?.value) return;
1166
- if (options.isInvoking?.value) return;
1178
+ if (isBusy()) return;
1167
1179
  const delay = options.dismissDelay ?? 4e3;
1168
1180
  dismissTimer = setTimeout(() => {
1181
+ if (isBusy()) return;
1169
1182
  fadingOut.value = true;
1170
1183
  setTimeout(() => {
1184
+ if (isBusy()) {
1185
+ fadingOut.value = false;
1186
+ return;
1187
+ }
1171
1188
  visible.value = false;
1172
1189
  fadingOut.value = false;
1190
+ hasOpened.value = false;
1173
1191
  }, 400);
1174
1192
  }, delay);
1175
1193
  };
1194
+ const watchTTSRef = (ttsRef) => {
1195
+ vue.watch(ttsRef, (active) => {
1196
+ if (active && hasOpened.value) {
1197
+ cancelDismiss();
1198
+ if (fadingOut.value) fadingOut.value = false;
1199
+ } else if (!active && hasOpened.value && !isBusy()) {
1200
+ scheduleDismiss();
1201
+ }
1202
+ });
1203
+ };
1204
+ if (options.isSpeaking) watchTTSRef(options.isSpeaking);
1205
+ if (options.hasPendingAudio) watchTTSRef(options.hasPendingAudio);
1176
1206
  const hide = () => {
1177
1207
  cancelDismiss();
1178
1208
  fadingOut.value = false;
1179
1209
  visible.value = false;
1210
+ hasOpened.value = false;
1180
1211
  };
1181
1212
  const scrollToBottom = () => {
1182
1213
  vue.nextTick(() => {
@@ -1806,7 +1837,7 @@
1806
1837
  const processedToolResults = /* @__PURE__ */ new Set();
1807
1838
  abortController = new AbortController();
1808
1839
  const commands = await aiChatbotX.hostCommads();
1809
- const historyToSend = conversationHistory.value.length > 0 ? [...conversationHistory.value] : void 0;
1840
+ conversationHistory.value.length > 0 ? [...conversationHistory.value] : void 0;
1810
1841
  try {
1811
1842
  const response = await fetch(options.endpoint.value, {
1812
1843
  method: "POST",
@@ -1814,8 +1845,8 @@
1814
1845
  body: JSON.stringify({
1815
1846
  input: content,
1816
1847
  projectId: options.projectId || "",
1817
- commands: commands.length > 0 ? commands : void 0,
1818
- messages: historyToSend
1848
+ commands: commands.length > 0 ? commands : void 0
1849
+ // messages: historyToSend,
1819
1850
  }),
1820
1851
  signal: abortController.signal
1821
1852
  });
@@ -1994,7 +2025,7 @@
1994
2025
  const endpoint = vue.computed(() => {
1995
2026
  return props.invokeUrl || "http://localhost:3001/agent/zyy55sw40nrl801056m0o/stream-invoke";
1996
2027
  });
1997
- const wakeResponses = ["您好"];
2028
+ const wakeResponses = ["在呢"];
1998
2029
  const tts = useTTS(getVoiceConfig);
1999
2030
  const bubbleBridge = {
2000
2031
  open: () => {
@@ -2023,6 +2054,7 @@
2023
2054
  const bubble = useBubble({
2024
2055
  dismissDelay: props.bubbleDismissDelay,
2025
2056
  isSpeaking: tts.isSpeaking,
2057
+ hasPendingAudio: tts.hasPendingAudio,
2026
2058
  isInvoking: agent.isInvoking,
2027
2059
  bubbleSize: props.bubbleSize
2028
2060
  });
@@ -2030,11 +2062,6 @@
2030
2062
  bubbleBridge.scheduleDismiss = bubble.scheduleDismiss;
2031
2063
  bubbleBridge.scrollToBottom = bubble.scrollToBottom;
2032
2064
  const { show: showBubble, style: bubbleStyle, stackRef: bubbleStackRef } = bubble;
2033
- tts.setOnQueueEmpty(() => {
2034
- if (!agent.isInvoking.value) {
2035
- bubble.scheduleDismiss();
2036
- }
2037
- });
2038
2065
  const interruptCurrentResponse = () => {
2039
2066
  agent.abort();
2040
2067
  agent.resetState();
@@ -2059,7 +2086,7 @@
2059
2086
  tts.warmUpAudio();
2060
2087
  await voice.toggleVoiceMode(targetState);
2061
2088
  };
2062
- const { voiceStatus, transcriptionText, wakeAnimating } = voice;
2089
+ const { voiceStatus, transcriptionText, wakeAnimating, isTranscribing } = voice;
2063
2090
  const { isInvoking, currentTextContent, currentToolParts, executingTools, hasAnyContent, toolDisplayName } = agent;
2064
2091
  aiChatbotX?.registerVoiceMethods({
2065
2092
  start: () => toggleVoiceMode(true),
@@ -2168,7 +2195,7 @@
2168
2195
  default: vue.withCtx(() => [
2169
2196
  vue.unref(voiceStatus) === "listening" ? (vue.openBlock(), vue.createElementBlock("div", {
2170
2197
  key: 0,
2171
- class: vue.normalizeClass(["listening-badge", { "wake-active": vue.unref(wakeAnimating) }])
2198
+ class: vue.normalizeClass(["listening-badge", { "wake-active": vue.unref(wakeAnimating) || vue.unref(isTranscribing) || vue.unref(isInvoking) }])
2172
2199
  }, [..._cache[5] || (_cache[5] = [
2173
2200
  vue.createElementVNode("div", { class: "listening-waves" }, [
2174
2201
  vue.createElementVNode("div", { class: "wave wave-1" }),
@@ -2205,7 +2232,7 @@
2205
2232
  }
2206
2233
  });
2207
2234
 
2208
- const voiceAssistant = /* @__PURE__ */ _export_sfc(_sfc_main, [["__scopeId", "data-v-9e420a26"]]);
2235
+ const voiceAssistant = /* @__PURE__ */ _export_sfc(_sfc_main, [["__scopeId", "data-v-d81f42d8"]]);
2209
2236
 
2210
2237
  exports.AiChatbotProvider = _sfc_main$4;
2211
2238
  exports.AiChatbotVoiceAssistant = voiceAssistant;