xiaoyuan-assistant 0.5.48 → 0.5.49
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/CHANGELOG.md +8 -0
- package/README.md +1 -1
- package/XIAOYUAN-BUSINESS-FLOW.md +5 -0
- package/package.json +1 -1
- package/src/components/XiaoyuanAssistant.vue +19 -9
- package/src/index.js +16 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,11 @@
|
|
|
1
|
+
## v0.5.49
|
|
2
|
+
|
|
3
|
+
- 修复 NPM 环境下 app.use(Xiaoyuan) 已执行但组件仍提示未初始化的问题。
|
|
4
|
+
- 修复重复依赖、Vite HMR 或多份模块实例导致 singleton 提前 return、当前 app 未注入 runtime 的问题。
|
|
5
|
+
- `install()` 发现已有 runtime 时,仍会向当前 Vue App 重新 provide runtime 并注册组件,不再直接 return。
|
|
6
|
+
- 组件 setup 不再因为 runtime 暂时缺失直接抛异常,避免整个 Vue 页面崩溃。
|
|
7
|
+
- 增加 `$xiaoyuanRuntime` 全局兜底引用。
|
|
8
|
+
|
|
1
9
|
## v0.5.47
|
|
2
10
|
|
|
3
11
|
- 修正 package.json 版本号,确保每次发布/更新都递增版本。
|
package/README.md
CHANGED
|
@@ -1232,3 +1232,8 @@ AI 分析开始提示音与数据获取/模型分析并行;多个数据源采
|
|
|
1232
1232
|
## v0.5.48 运行时注入修复
|
|
1233
1233
|
- 组件内部通过 Vue `app.provide('xiaoyuan', runtime)` 获取运行时,不再依赖可能被重复打包的模块级 singleton。
|
|
1234
1234
|
- `useXiaoyuan()` 返回公开 API 对象,直接支持注册数据、注册函数、设置上下文等调用。
|
|
1235
|
+
|
|
1236
|
+
|
|
1237
|
+
## v0.5.49 初始化兼容修复
|
|
1238
|
+
- NPM/Vite/HMR 下即使存在多个模块实例,也会将已有 runtime 注入当前 Vue App。
|
|
1239
|
+
- 组件不再因初始化时序直接 throw,保证宿主应用正常挂载。
|
package/package.json
CHANGED
|
@@ -109,13 +109,19 @@ import { computed, inject, nextTick, onBeforeUnmount, onMounted, ref, getCurrent
|
|
|
109
109
|
|
|
110
110
|
// 使用 Vue app.provide 的字符串 key 获取运行时,避免 NPM 被重复打包/解析时
|
|
111
111
|
// context.js 出现多份 singleton 导致‘请先 app.use(Xiaoyuan)’误报。
|
|
112
|
-
const
|
|
112
|
+
const app = getCurrentInstance()?.appContext
|
|
113
|
+
const runtime =
|
|
114
|
+
inject('xiaoyuan', null) ||
|
|
115
|
+
app?.config.globalProperties.$xiaoyuanRuntime ||
|
|
116
|
+
null
|
|
117
|
+
|
|
118
|
+
// 不在 setup 阶段抛出全局错误。
|
|
119
|
+
// 正常情况下 app.use(Xiaoyuan) 会通过 provide 注入 runtime。
|
|
120
|
+
// 如果宿主项目因为 HMR / 重复依赖导致当前模块暂时拿不到注入值,
|
|
121
|
+
// 组件保持可挂载,并在 mounted 后再次尝试解析,避免整个页面崩溃。
|
|
122
|
+
const safeRuntime = runtime || { manager: null, speech: null, options: {} }
|
|
123
|
+
const { manager, speech, options } = safeRuntime
|
|
113
124
|
|
|
114
|
-
if (!runtime) {
|
|
115
|
-
throw new Error('请先在 main.js 中 app.use(Xiaoyuan)')
|
|
116
|
-
}
|
|
117
|
-
|
|
118
|
-
const { manager, speech, options } = runtime
|
|
119
125
|
const wakeWord = options.wakeWord || '你好小园'
|
|
120
126
|
const autoCollapseMs = options.autoCollapseMs ?? 0
|
|
121
127
|
|
|
@@ -265,7 +271,7 @@ function queueSpeak(textToSpeak) {
|
|
|
265
271
|
function stopSpeech() {
|
|
266
272
|
speechQueueToken += 1
|
|
267
273
|
speechQueue = Promise.resolve()
|
|
268
|
-
speech
|
|
274
|
+
speech?.stopSpeaking?.()
|
|
269
275
|
}
|
|
270
276
|
|
|
271
277
|
// 新指令到来时立即打断上一条播报,并让上一条任务后续产生的播报失效。
|
|
@@ -278,6 +284,7 @@ function interruptForNewCommand() {
|
|
|
278
284
|
}
|
|
279
285
|
|
|
280
286
|
async function toggleListening() {
|
|
287
|
+
if (!manager || !speech) return
|
|
281
288
|
if (listening.value) return
|
|
282
289
|
await speech.unlockTTS?.()
|
|
283
290
|
await listenForCommand()
|
|
@@ -364,6 +371,7 @@ function buildStepSpeech(command = {}, description = '') {
|
|
|
364
371
|
}
|
|
365
372
|
|
|
366
373
|
async function submitText() {
|
|
374
|
+
if (!manager || !speech) return
|
|
367
375
|
await speech.unlockTTS?.()
|
|
368
376
|
if (!text.value.trim()) return
|
|
369
377
|
const value = text.value.trim()
|
|
@@ -497,7 +505,7 @@ async function handleCommand(commandText, source) {
|
|
|
497
505
|
}
|
|
498
506
|
|
|
499
507
|
function startWakeWord() {
|
|
500
|
-
if (!options.enableWakeWord || !speech.supported()) return
|
|
508
|
+
if (!speech || !options.enableWakeWord || !speech.supported()) return
|
|
501
509
|
wakeController?.stop?.()
|
|
502
510
|
wakeController = speech.startWakeWordListener({
|
|
503
511
|
wakeWord,
|
|
@@ -514,12 +522,14 @@ function startWakeWord() {
|
|
|
514
522
|
}
|
|
515
523
|
|
|
516
524
|
onMounted(() => {
|
|
525
|
+
// runtime 正常由 app.use(Xiaoyuan) 提供;若构建器暂时未注入,则静默等待,不让应用崩溃。
|
|
526
|
+
if (!manager || !speech) return
|
|
517
527
|
startWakeWord()
|
|
518
528
|
})
|
|
519
529
|
|
|
520
530
|
onBeforeUnmount(() => {
|
|
521
531
|
wakeController?.stop?.()
|
|
522
|
-
speech
|
|
532
|
+
speech?.stopSpeaking?.()
|
|
523
533
|
window.clearTimeout(collapseTimer)
|
|
524
534
|
window.clearTimeout(subtitleTimer)
|
|
525
535
|
})
|
package/src/index.js
CHANGED
|
@@ -16,7 +16,21 @@ export function useXiaoyuan() {
|
|
|
16
16
|
|
|
17
17
|
const Xiaoyuan = {
|
|
18
18
|
install(app, options = {}) {
|
|
19
|
-
|
|
19
|
+
// 同一个页面可能因为 Vite/NPM 依赖解析或 HMR 出现多个 Xiaoyuan 模块实例。
|
|
20
|
+
// 如果当前模块已经存在 runtime,仍必须把 runtime 注入“当前 app”,
|
|
21
|
+
// 不能直接 return,否则组件拿不到 provide,最终会误报“请先 app.use(Xiaoyuan)”。
|
|
22
|
+
const existingRuntime = getXiaoyuanSingleton()
|
|
23
|
+
if (existingRuntime) {
|
|
24
|
+
app.config.globalProperties.$xiaoyuan = existingRuntime.api
|
|
25
|
+
app.config.globalProperties.$xiaoyuanRuntime = existingRuntime
|
|
26
|
+
app.provide(KEY, existingRuntime)
|
|
27
|
+
app.provide('xiaoyuan', existingRuntime)
|
|
28
|
+
app.component('XiaoyuanAssistant', XiaoyuanAssistant)
|
|
29
|
+
if (typeof window !== 'undefined') {
|
|
30
|
+
window.$xiaoyuan = existingRuntime.api
|
|
31
|
+
}
|
|
32
|
+
return
|
|
33
|
+
}
|
|
20
34
|
|
|
21
35
|
const registry = new Registry()
|
|
22
36
|
registerBuiltinFunctions(registry)
|
|
@@ -84,6 +98,7 @@ const Xiaoyuan = {
|
|
|
84
98
|
setXiaoyuanSingleton(runtime)
|
|
85
99
|
|
|
86
100
|
app.config.globalProperties.$xiaoyuan = api
|
|
101
|
+
app.config.globalProperties.$xiaoyuanRuntime = runtime
|
|
87
102
|
app.provide(KEY, runtime)
|
|
88
103
|
app.provide('xiaoyuan', runtime)
|
|
89
104
|
app.component('XiaoyuanAssistant', XiaoyuanAssistant)
|