@siact/sime-x-vue 0.0.2 → 0.0.3
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/sime-x-vue.mjs +59 -144
- package/dist/sime-x-vue.mjs.map +1 -1
- package/dist/sime-x-vue.umd.js +58 -143
- package/dist/sime-x-vue.umd.js.map +1 -1
- package/dist/style.css +127 -75
- package/package.json +1 -1
- package/types/components/sime-x.vue.d.ts +2 -0
package/dist/sime-x-vue.mjs
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { inject, defineComponent, shallowRef, provide, renderSlot, computed, openBlock, createBlock, Transition, withCtx, createElementBlock, normalizeClass, createElementVNode, toDisplayString, createVNode, createCommentVNode, ref, onBeforeUnmount, reactive, watch, normalizeStyle, withModifiers, nextTick } from 'vue';
|
|
2
2
|
import { HostBridge } from '@siact/sime-bridge';
|
|
3
|
-
import { WakeWordDetectorStandalone
|
|
3
|
+
import { WakeWordDetectorStandalone } from 'web-voice-kit';
|
|
4
4
|
|
|
5
5
|
const AiChatbotXKey = Symbol("sime-x");
|
|
6
6
|
function injectStrict(key, defaultValue, treatDefaultAsFactory) {
|
|
@@ -317,30 +317,26 @@ const ensureMicrophonePermission = async () => {
|
|
|
317
317
|
const _hoisted_1 = ["data-theme"];
|
|
318
318
|
const _hoisted_2 = { class: "fab-avatar-wrapper" };
|
|
319
319
|
const _hoisted_3 = ["src"];
|
|
320
|
-
const _hoisted_4 = {
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
};
|
|
324
|
-
const
|
|
325
|
-
const
|
|
326
|
-
const
|
|
327
|
-
const _hoisted_8 = { class: "title" };
|
|
328
|
-
const _hoisted_9 = { class: "actions" };
|
|
329
|
-
const _hoisted_10 = ["title"];
|
|
330
|
-
const _hoisted_11 = {
|
|
320
|
+
const _hoisted_4 = { class: "header-left" };
|
|
321
|
+
const _hoisted_5 = { class: "logo-icon" };
|
|
322
|
+
const _hoisted_6 = ["src"];
|
|
323
|
+
const _hoisted_7 = { class: "title" };
|
|
324
|
+
const _hoisted_8 = { class: "actions" };
|
|
325
|
+
const _hoisted_9 = ["title"];
|
|
326
|
+
const _hoisted_10 = {
|
|
331
327
|
key: 0,
|
|
332
328
|
class: "voice-indicator"
|
|
333
329
|
};
|
|
330
|
+
const _hoisted_11 = ["title"];
|
|
334
331
|
const _hoisted_12 = ["title"];
|
|
335
|
-
const _hoisted_13 =
|
|
336
|
-
const _hoisted_14 = {
|
|
332
|
+
const _hoisted_13 = {
|
|
337
333
|
width: "16",
|
|
338
334
|
height: "16",
|
|
339
335
|
viewBox: "0 0 24 24",
|
|
340
336
|
fill: "none"
|
|
341
337
|
};
|
|
342
|
-
const
|
|
343
|
-
const
|
|
338
|
+
const _hoisted_14 = ["d"];
|
|
339
|
+
const _hoisted_15 = ["src"];
|
|
344
340
|
const _sfc_main = /* @__PURE__ */ defineComponent({
|
|
345
341
|
__name: "sime-x",
|
|
346
342
|
props: {
|
|
@@ -352,13 +348,15 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
|
|
|
352
348
|
wakeWords: {},
|
|
353
349
|
modelPath: {}
|
|
354
350
|
},
|
|
355
|
-
emits: ["start-transcribing", "stop-transcribing"],
|
|
351
|
+
emits: ["start-transcribing", "stop-transcribing", "wakeUp"],
|
|
356
352
|
setup(__props, { emit: __emit }) {
|
|
357
353
|
const props = __props;
|
|
358
354
|
const emit = __emit;
|
|
359
355
|
const aiChatbotX = injectStrict(AiChatbotXKey);
|
|
360
356
|
const chatbotUrl = ref("");
|
|
361
357
|
const voiceStatus = ref("standby");
|
|
358
|
+
const wakeAnimating = ref(false);
|
|
359
|
+
const wakeResponses = ["在呢", "在的", "我在", "您好", "在呢,请说"];
|
|
362
360
|
const transcriptionText = ref("");
|
|
363
361
|
const isTranscribing = ref(false);
|
|
364
362
|
const isProcessing = ref(false);
|
|
@@ -367,7 +365,6 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
|
|
|
367
365
|
const fabRef = ref(null);
|
|
368
366
|
const positionReady = ref(false);
|
|
369
367
|
let detector = null;
|
|
370
|
-
let transcriber = null;
|
|
371
368
|
const isInitializing = ref(false);
|
|
372
369
|
const initError = ref("");
|
|
373
370
|
const getSystemTheme = () => {
|
|
@@ -429,10 +426,15 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
|
|
|
429
426
|
detector.setWakeWords(wakeWords);
|
|
430
427
|
detector.onWake(() => {
|
|
431
428
|
console.log("[VoiceDetector] 检测到唤醒词");
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
429
|
+
wakeAnimating.value = true;
|
|
430
|
+
playWakeResponse();
|
|
431
|
+
emit("wakeUp", true);
|
|
432
|
+
aiChatbotX.weak();
|
|
433
|
+
aiChatbotX.openDialog();
|
|
434
|
+
setTimeout(() => {
|
|
435
|
+
wakeAnimating.value = false;
|
|
436
|
+
}, 1500);
|
|
437
|
+
voiceStatus.value = "listening";
|
|
436
438
|
});
|
|
437
439
|
detector.onError((error) => {
|
|
438
440
|
console.error("[VoiceDetector] 错误:", error);
|
|
@@ -460,110 +462,30 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
|
|
|
460
462
|
isInitializing.value = false;
|
|
461
463
|
}
|
|
462
464
|
};
|
|
463
|
-
|
|
464
|
-
if (transcriber) return;
|
|
465
|
+
const playWakeResponse = () => {
|
|
465
466
|
try {
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
initError.value = "未配置语音配置";
|
|
469
|
-
voiceStatus.value = "standby";
|
|
470
|
-
isTranscribing.value = false;
|
|
467
|
+
if (typeof window === "undefined" || !window.speechSynthesis) {
|
|
468
|
+
console.warn("[TTS] SpeechSynthesis API 不可用");
|
|
471
469
|
return;
|
|
472
470
|
}
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
});
|
|
487
|
-
transcriber.onAutoStop(async () => {
|
|
488
|
-
console.log("[Transcriber] Auto Stop");
|
|
489
|
-
const currentText = transcriptionText.value;
|
|
490
|
-
await stopTranscribing();
|
|
491
|
-
if (!currentText || !currentText.trim()) {
|
|
492
|
-
console.log("[Transcriber] No transcription text, returning to listening");
|
|
493
|
-
transcriptionText.value = "";
|
|
494
|
-
voiceStatus.value = "listening";
|
|
495
|
-
return;
|
|
496
|
-
}
|
|
497
|
-
isProcessing.value = true;
|
|
498
|
-
transcriptionText.value = currentText;
|
|
499
|
-
try {
|
|
500
|
-
const commands = await aiChatbotX.hostCommads();
|
|
501
|
-
const result = await aiChatbotX.recognition(currentText, commands);
|
|
502
|
-
if (result?.data?.intent === "command" && result?.data?.matchedCommands) {
|
|
503
|
-
const matchedCommands = result.data.matchedCommands;
|
|
504
|
-
for (const cmd of matchedCommands) {
|
|
505
|
-
try {
|
|
506
|
-
const args = cmd.parameters ? Object.values(cmd.parameters) : [];
|
|
507
|
-
const cmdResult = await aiChatbotX.executeCommand(cmd.name, args);
|
|
508
|
-
console.log(`Command ${cmd.name} executed successfully:`, cmdResult);
|
|
509
|
-
} catch (error) {
|
|
510
|
-
console.error(`Failed to execute command ${cmd.name}:`, error);
|
|
511
|
-
}
|
|
512
|
-
}
|
|
513
|
-
} else {
|
|
514
|
-
aiChatbotX.appendMessage(currentText);
|
|
515
|
-
toggleDialog(true);
|
|
516
|
-
}
|
|
517
|
-
} finally {
|
|
518
|
-
isProcessing.value = false;
|
|
519
|
-
transcriptionText.value = "";
|
|
520
|
-
voiceStatus.value = "listening";
|
|
521
|
-
}
|
|
522
|
-
});
|
|
523
|
-
transcriber.onError((error) => {
|
|
524
|
-
console.error("[Transcriber] Error:", error);
|
|
525
|
-
stopTranscribing();
|
|
526
|
-
transcriptionText.value = "转写错误";
|
|
527
|
-
setTimeout(() => {
|
|
528
|
-
transcriptionText.value = "";
|
|
529
|
-
voiceStatus.value = "listening";
|
|
530
|
-
}, 2e3);
|
|
531
|
-
});
|
|
532
|
-
console.log("[Transcriber] 初始化成功");
|
|
533
|
-
} catch (error) {
|
|
534
|
-
console.error("[Transcriber] 初始化失败:", error);
|
|
535
|
-
voiceStatus.value = "standby";
|
|
536
|
-
initError.value = error instanceof Error ? error.message : "转写初始化失败";
|
|
537
|
-
}
|
|
538
|
-
}
|
|
539
|
-
const startTranscribing = async () => {
|
|
540
|
-
if (!transcriber) {
|
|
541
|
-
initTranscriber();
|
|
542
|
-
if (!transcriber) return;
|
|
543
|
-
}
|
|
544
|
-
try {
|
|
545
|
-
emit("start-transcribing");
|
|
546
|
-
await transcriber.start();
|
|
547
|
-
isTranscribing.value = true;
|
|
548
|
-
transcriptionText.value = "";
|
|
471
|
+
const text = wakeResponses[Math.floor(Math.random() * wakeResponses.length)];
|
|
472
|
+
const utterance = new SpeechSynthesisUtterance(text);
|
|
473
|
+
utterance.lang = "zh-CN";
|
|
474
|
+
utterance.rate = 1;
|
|
475
|
+
utterance.pitch = 0.8;
|
|
476
|
+
utterance.volume = 0.9;
|
|
477
|
+
const voices = window.speechSynthesis.getVoices();
|
|
478
|
+
const maleVoice = voices.find((v) => v.lang.startsWith("zh") && /male|男/i.test(v.name));
|
|
479
|
+
const zhVoice = maleVoice || voices.find((v) => v.lang.startsWith("zh"));
|
|
480
|
+
if (zhVoice) {
|
|
481
|
+
utterance.voice = zhVoice;
|
|
482
|
+
}
|
|
483
|
+
window.speechSynthesis.speak(utterance);
|
|
549
484
|
} catch (error) {
|
|
550
|
-
console.error("[
|
|
551
|
-
transcriptionText.value = "转写启动失败";
|
|
552
|
-
setTimeout(() => {
|
|
553
|
-
transcriptionText.value = "";
|
|
554
|
-
}, 2e3);
|
|
485
|
+
console.error("[TTS] 播报失败:", error);
|
|
555
486
|
}
|
|
556
487
|
};
|
|
557
488
|
const stopTranscribing = async () => {
|
|
558
|
-
if (transcriber && transcriber.isActive()) {
|
|
559
|
-
try {
|
|
560
|
-
await transcriber.stop();
|
|
561
|
-
isTranscribing.value = false;
|
|
562
|
-
emit("stop-transcribing");
|
|
563
|
-
} catch (error) {
|
|
564
|
-
console.error("[Transcriber] 停止失败:", error);
|
|
565
|
-
}
|
|
566
|
-
}
|
|
567
489
|
};
|
|
568
490
|
const toggleVoiceMode = async (targetState) => {
|
|
569
491
|
const permission = await ensureMicrophonePermission();
|
|
@@ -756,16 +678,6 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
|
|
|
756
678
|
console.error("[VoiceDetector] 清理失败:", error);
|
|
757
679
|
}
|
|
758
680
|
}
|
|
759
|
-
if (transcriber) {
|
|
760
|
-
try {
|
|
761
|
-
if (transcriber.isActive()) {
|
|
762
|
-
await transcriber.stop();
|
|
763
|
-
}
|
|
764
|
-
transcriber = null;
|
|
765
|
-
} catch (error) {
|
|
766
|
-
console.error("[Transcriber] 清理失败:", error);
|
|
767
|
-
}
|
|
768
|
-
}
|
|
769
681
|
});
|
|
770
682
|
aiChatbotX?.registerVoiceMethods({
|
|
771
683
|
start: () => toggleVoiceMode(true),
|
|
@@ -810,7 +722,10 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
|
|
|
810
722
|
}, null, 12, _hoisted_3),
|
|
811
723
|
createVNode(Transition, { name: "indicator-fade" }, {
|
|
812
724
|
default: withCtx(() => [
|
|
813
|
-
voiceStatus.value === "listening" ? (openBlock(), createElementBlock("div",
|
|
725
|
+
voiceStatus.value === "listening" ? (openBlock(), createElementBlock("div", {
|
|
726
|
+
key: 0,
|
|
727
|
+
class: normalizeClass(["listening-badge", { "wake-active": wakeAnimating.value }])
|
|
728
|
+
}, [..._cache[3] || (_cache[3] = [
|
|
814
729
|
createElementVNode("div", { class: "listening-waves" }, [
|
|
815
730
|
createElementVNode("div", { class: "wave wave-1" }),
|
|
816
731
|
createElementVNode("div", { class: "wave wave-2" }),
|
|
@@ -835,7 +750,7 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
|
|
|
835
750
|
})
|
|
836
751
|
])
|
|
837
752
|
], -1)
|
|
838
|
-
])])) : createCommentVNode("", true)
|
|
753
|
+
])], 2)) : createCommentVNode("", true)
|
|
839
754
|
]),
|
|
840
755
|
_: 1
|
|
841
756
|
})
|
|
@@ -869,17 +784,17 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
|
|
|
869
784
|
class: "x-dialog-header",
|
|
870
785
|
onMousedown: withModifiers(startDrag, ["stop"])
|
|
871
786
|
}, [
|
|
872
|
-
createElementVNode("div",
|
|
873
|
-
createElementVNode("div",
|
|
787
|
+
createElementVNode("div", _hoisted_4, [
|
|
788
|
+
createElementVNode("div", _hoisted_5, [
|
|
874
789
|
createElementVNode("img", {
|
|
875
790
|
src: __props.xLogo ? __props.xLogo : "/sime.png",
|
|
876
791
|
alt: "assistant",
|
|
877
792
|
class: "logo"
|
|
878
|
-
}, null, 8,
|
|
793
|
+
}, null, 8, _hoisted_6)
|
|
879
794
|
]),
|
|
880
|
-
createElementVNode("span",
|
|
795
|
+
createElementVNode("span", _hoisted_7, toDisplayString(__props.xTitle), 1)
|
|
881
796
|
]),
|
|
882
|
-
createElementVNode("div",
|
|
797
|
+
createElementVNode("div", _hoisted_8, [
|
|
883
798
|
createElementVNode("button", {
|
|
884
799
|
class: "action-btn theme-btn",
|
|
885
800
|
title: "开启新对话",
|
|
@@ -943,8 +858,8 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
|
|
|
943
858
|
"stroke-linejoin": "round"
|
|
944
859
|
})
|
|
945
860
|
], -1)),
|
|
946
|
-
voiceStatus.value !== "standby" ? (openBlock(), createElementBlock("span",
|
|
947
|
-
], 10,
|
|
861
|
+
voiceStatus.value !== "standby" ? (openBlock(), createElementBlock("span", _hoisted_10)) : createCommentVNode("", true)
|
|
862
|
+
], 10, _hoisted_9),
|
|
948
863
|
createElementVNode("button", {
|
|
949
864
|
class: "action-btn theme-btn",
|
|
950
865
|
onClick: withModifiers(cycleTheme, ["stop"]),
|
|
@@ -968,22 +883,22 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
|
|
|
968
883
|
fill: "currentColor"
|
|
969
884
|
})
|
|
970
885
|
], -1)
|
|
971
|
-
])], 8,
|
|
886
|
+
])], 8, _hoisted_11),
|
|
972
887
|
createElementVNode("button", {
|
|
973
888
|
class: "action-btn collapse-btn",
|
|
974
889
|
onClick: withModifiers(toggleCollapse, ["stop"]),
|
|
975
890
|
title: isCollapsed.value ? "展开" : "折叠"
|
|
976
891
|
}, [
|
|
977
|
-
(openBlock(), createElementBlock("svg",
|
|
892
|
+
(openBlock(), createElementBlock("svg", _hoisted_13, [
|
|
978
893
|
createElementVNode("path", {
|
|
979
894
|
d: isCollapsed.value ? "M18 15L12 9L6 15" : "M6 9L12 15L18 9",
|
|
980
895
|
stroke: "currentColor",
|
|
981
896
|
"stroke-width": "2",
|
|
982
897
|
"stroke-linecap": "round",
|
|
983
898
|
"stroke-linejoin": "round"
|
|
984
|
-
}, null, 8,
|
|
899
|
+
}, null, 8, _hoisted_14)
|
|
985
900
|
]))
|
|
986
|
-
], 8,
|
|
901
|
+
], 8, _hoisted_12),
|
|
987
902
|
createElementVNode("button", {
|
|
988
903
|
class: "action-btn minimize-btn",
|
|
989
904
|
onClick: _cache[2] || (_cache[2] = withModifiers(($event) => toggleDialog(false), ["stop"])),
|
|
@@ -1016,7 +931,7 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
|
|
|
1016
931
|
allow: "microphone",
|
|
1017
932
|
frameborder: "0",
|
|
1018
933
|
onLoad: handleIframeLoad
|
|
1019
|
-
}, null, 40,
|
|
934
|
+
}, null, 40, _hoisted_15)
|
|
1020
935
|
], 6)
|
|
1021
936
|
], 38)
|
|
1022
937
|
]),
|
|
@@ -1027,7 +942,7 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
|
|
|
1027
942
|
}
|
|
1028
943
|
});
|
|
1029
944
|
|
|
1030
|
-
const simeX = /* @__PURE__ */ _export_sfc(_sfc_main, [["__scopeId", "data-v-
|
|
945
|
+
const simeX = /* @__PURE__ */ _export_sfc(_sfc_main, [["__scopeId", "data-v-732b3a72"]]);
|
|
1031
946
|
|
|
1032
947
|
export { _sfc_main$3 as AiChatbotProvider, simeX as AiChatbotX, AiChatbotXKey, clientCommandKey, injectStrict };
|
|
1033
948
|
//# sourceMappingURL=sime-x-vue.mjs.map
|