@siact/sime-x-vue 0.0.21 → 0.0.23

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.
@@ -1513,7 +1513,15 @@
1513
1513
  }
1514
1514
  };
1515
1515
  const test = () => {
1516
- aiChatbotX.speakText("你好,世界,今天是想起五天气横扫的缺点");
1516
+ [
1517
+ "1你好,世界,今天是想起五天气横扫的缺点",
1518
+ "2你好,世界,今天是想起五天气横扫的缺点",
1519
+ "3你好,世界,今天是想起五天气横扫的缺点"
1520
+ ].forEach((text, index) => {
1521
+ setTimeout(() => {
1522
+ aiChatbotX.speakText(text);
1523
+ }, index * 1e3);
1524
+ });
1517
1525
  };
1518
1526
  const test1 = () => {
1519
1527
  aiChatbotX.abortInvoke();
@@ -1679,7 +1687,7 @@
1679
1687
  }
1680
1688
  });
1681
1689
 
1682
- const commandTest = /* @__PURE__ */ _export_sfc(_sfc_main$2, [["__scopeId", "data-v-2d2cea1f"]]);
1690
+ const commandTest = /* @__PURE__ */ _export_sfc(_sfc_main$2, [["__scopeId", "data-v-36096054"]]);
1683
1691
 
1684
1692
  class CommandManager {
1685
1693
  commands = /* @__PURE__ */ new Map();
@@ -1923,6 +1931,37 @@
1923
1931
  console.error("[TTS] speak 失败:", err);
1924
1932
  }
1925
1933
  };
1934
+ const speakAndWait = async (text) => {
1935
+ const clean = normalizeSpeakText(text);
1936
+ if (!clean.trim()) return;
1937
+ hasPendingAudio.value = true;
1938
+ const ttsInst = await ensureInstance();
1939
+ if (!ttsInst) {
1940
+ hasPendingAudio.value = false;
1941
+ return;
1942
+ }
1943
+ return new Promise((resolve) => {
1944
+ let settled = false;
1945
+ const settle = () => {
1946
+ if (settled) return;
1947
+ settled = true;
1948
+ clearTimeout(safetyTimer);
1949
+ onQueueEmptyCb = null;
1950
+ resolve();
1951
+ };
1952
+ const safetyTimer = setTimeout(() => {
1953
+ console.warn("[TTS] speakAndWait 安全超时,强制 resolve");
1954
+ settle();
1955
+ }, 6e4);
1956
+ onQueueEmptyCb = settle;
1957
+ try {
1958
+ ttsInst.speak(clean);
1959
+ } catch (err) {
1960
+ console.error("[TTS] speak 失败:", err);
1961
+ settle();
1962
+ }
1963
+ });
1964
+ };
1926
1965
  const feed = (delta) => {
1927
1966
  sentenceBuffer += delta;
1928
1967
  while (true) {
@@ -1945,6 +1984,11 @@
1945
1984
  sentenceBuffer = "";
1946
1985
  isSpeaking.value = false;
1947
1986
  hasPendingAudio.value = false;
1987
+ if (onQueueEmptyCb) {
1988
+ const cb = onQueueEmptyCb;
1989
+ onQueueEmptyCb = null;
1990
+ cb();
1991
+ }
1948
1992
  if (instance) {
1949
1993
  try {
1950
1994
  instance.stop();
@@ -1977,6 +2021,7 @@
1977
2021
  hasPendingAudio,
1978
2022
  warmUpAudio,
1979
2023
  speak,
2024
+ speakAndWait,
1980
2025
  feed,
1981
2026
  flush,
1982
2027
  stop,
@@ -2278,8 +2323,10 @@
2278
2323
  bubbleSize: {},
2279
2324
  bubbleDismissDelay: {}
2280
2325
  },
2281
- setup(__props) {
2326
+ emits: ["wake-up"],
2327
+ setup(__props, { emit: __emit }) {
2282
2328
  const props = __props;
2329
+ const emit = __emit;
2283
2330
  const aiChatbotX = injectStrict(AiChatbotXKey);
2284
2331
  const getVoiceConfig = () => {
2285
2332
  if (props.voiceConfig) return props.voiceConfig;
@@ -2331,20 +2378,46 @@
2331
2378
  tts.stop();
2332
2379
  bubble.hide();
2333
2380
  };
2334
- const speakTextWithBubble = async (text) => {
2335
- bubble.open();
2336
- agent.currentTextContent.value = text;
2337
- try {
2338
- await tts.speak(text);
2339
- } finally {
2340
- bubble.scheduleDismiss();
2381
+ const speakQueue = [];
2382
+ let isProcessingSpeakQueue = false;
2383
+ const processSpeakQueue = async () => {
2384
+ if (isProcessingSpeakQueue) return;
2385
+ isProcessingSpeakQueue = true;
2386
+ tts.hasPendingAudio.value = true;
2387
+ while (speakQueue.length > 0) {
2388
+ const text = speakQueue.shift();
2389
+ bubble.open();
2390
+ agent.currentTextContent.value = text;
2391
+ try {
2392
+ await tts.speakAndWait(text);
2393
+ } catch (e) {
2394
+ console.error("[speakQueue] 播报失败:", e);
2395
+ }
2396
+ if (speakQueue.length > 0) {
2397
+ tts.hasPendingAudio.value = true;
2398
+ }
2399
+ }
2400
+ isProcessingSpeakQueue = false;
2401
+ tts.hasPendingAudio.value = false;
2402
+ bubble.scheduleDismiss();
2403
+ };
2404
+ const speakTextWithBubble = (text) => {
2405
+ speakQueue.push(text);
2406
+ if (!isProcessingSpeakQueue) {
2407
+ processSpeakQueue();
2341
2408
  }
2342
2409
  };
2410
+ const stopSpeak = () => {
2411
+ speakQueue.length = 0;
2412
+ isProcessingSpeakQueue = false;
2413
+ tts.stop();
2414
+ };
2343
2415
  const voice = useVoiceRecognition({
2344
2416
  modelPath: props.modelPath,
2345
2417
  wakeWords: props.wakeWords,
2346
2418
  getVoiceConfig,
2347
2419
  onWake: () => {
2420
+ emit("wake-up");
2348
2421
  interruptCurrentResponse();
2349
2422
  tts.warmUpAudio();
2350
2423
  const text = wakeResponses.value[Math.floor(Math.random() * wakeResponses.value.length)];
@@ -2369,7 +2442,7 @@
2369
2442
  agentInvoke: agent.invoke,
2370
2443
  agentAbort: agent.abort,
2371
2444
  speakText: speakTextWithBubble,
2372
- stopSpeak: tts.stop
2445
+ stopSpeak
2373
2446
  });
2374
2447
  vue.onBeforeUnmount(async () => {
2375
2448
  bubble.destroy();
@@ -2508,7 +2581,7 @@
2508
2581
  }
2509
2582
  });
2510
2583
 
2511
- const voiceAssistant = /* @__PURE__ */ _export_sfc(_sfc_main, [["__scopeId", "data-v-ac1884ea"]]);
2584
+ const voiceAssistant = /* @__PURE__ */ _export_sfc(_sfc_main, [["__scopeId", "data-v-177013f4"]]);
2512
2585
 
2513
2586
  var clientCommandKey = /* @__PURE__ */ ((clientCommandKey2) => {
2514
2587
  clientCommandKey2["SET_THEME"] = "SiMeAgent_setTheme";