@burdenoff/fe-libs 2026.907.2 → 2026.908.1
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/shared/assistant/ui/AssistantSpeechProvider.d.ts +15 -0
- package/dist/shared/assistant/ui/AssistantSpeechProvider.d.ts.map +1 -1
- package/dist/shared/assistant/ui/AssistantSpeechProvider.js +162 -157
- package/dist/shared/assistant/ui/useVoiceSession.d.ts.map +1 -1
- package/dist/shared/assistant/ui/useVoiceSession.js +77 -72
- package/package.json +1 -1
|
@@ -83,6 +83,21 @@ export interface AssistantSpeechContextValue {
|
|
|
83
83
|
*/
|
|
84
84
|
sessionSpeaking: boolean;
|
|
85
85
|
setSessionSpeaking: (enabled: boolean) => void;
|
|
86
|
+
/**
|
|
87
|
+
* Is the live session's MICROPHONE open right now?
|
|
88
|
+
*
|
|
89
|
+
* ★ Reported by `useVoiceSession` so the auto-speak subscription below can
|
|
90
|
+
* refuse to play audio into an open microphone. `sessionSpeaking` cannot
|
|
91
|
+
* answer this: it is session-scoped — set once on start and cleared on end —
|
|
92
|
+
* so it stays true for the whole conversation, including the `listening`
|
|
93
|
+
* phases between turns.
|
|
94
|
+
*
|
|
95
|
+
* Write-only by design, and deliberately NOT React state: nothing renders it,
|
|
96
|
+
* and making it state would re-render every speech consumer on each phase
|
|
97
|
+
* change AND re-subscribe the store listener mid-turn, which can drop the
|
|
98
|
+
* in-flight → complete edge the subscription exists to catch.
|
|
99
|
+
*/
|
|
100
|
+
setSessionMicOpen: (open: boolean) => void;
|
|
86
101
|
/** Play a short sample in a named voice. No model call, no message, no tokens. */
|
|
87
102
|
previewVoice: (voiceName: string) => void;
|
|
88
103
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"AssistantSpeechProvider.d.ts","sourceRoot":"","sources":["../../../../src/shared/assistant/ui/AssistantSpeechProvider.tsx"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AAEH,OAAO,EASL,KAAK,EAAE,EACP,KAAK,SAAS,EACf,MAAM,OAAO,CAAC;AAKf,OAAO,KAAK,EAAE,YAAY,EAAE,eAAe,EAAE,MAAM,WAAW,CAAC;AA2B/D,OAAO,EAQL,KAAK,iBAAiB,EACvB,MAAM,uBAAuB,CAAC;AAiB/B,MAAM,WAAW,2BAA2B;IAC1C,gFAAgF;IAChF,WAAW,EAAE,OAAO,CAAC;IACrB,YAAY,EAAE,iBAAiB,CAAC;IAChC;;;;OAIG;IACH,SAAS,EAAE,OAAO,CAAC;IACnB,6EAA6E;IAC7E,cAAc,EAAE,MAAM,GAAG,IAAI,CAAC;IAC9B;;;;;;OAMG;IACH,UAAU,EAAE,CAAC,SAAS,EAAE,MAAM,KAAK,MAAM,GAAG,IAAI,CAAC;IACjD;;;;OAIG;IACH,YAAY,EAAE,SAAS,eAAe,EAAE,CAAC;IACzC,8EAA8E;IAC9E;;;;;;OAMG;IACH,YAAY,EAAE;QAAE,MAAM,EAAE,MAAM,EAAE,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,GAAG,IAAI,CAAC;IACzD,eAAe,EAAE,MAAM,GAAG,IAAI,CAAC;IAC/B;;;;;;;;OAQG;IACH,kBAAkB,EAAE,MAAM,GAAG,IAAI,CAAC;IAClC,mEAAmE;IACnE,QAAQ,EAAE,CAAC,SAAS,EAAE,MAAM,GAAG,IAAI,KAAK,IAAI,CAAC;IAC7C,kDAAkD;IAClD,iBAAiB,EAAE,MAAM,GAAG,IAAI,CAAC;IACjC,UAAU,EAAE,CAAC,SAAS,EAAE,MAAM,KAAK,OAAO,CAAC;IAC3C;;;;;;;OAOG;IACH,MAAM,EAAE,CAAC,SAAS,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,UAAU,CAAC,EAAE,MAAM,KAAK,IAAI,CAAC;IAC3E,IAAI,EAAE,MAAM,IAAI,CAAC;IACjB,gBAAgB,EAAE,OAAO,CAAC;IAC1B,YAAY,EAAE,CAAC,OAAO,EAAE,OAAO,KAAK,IAAI,CAAC;IACzC;;;;;;;;;;;;;OAaG;IACH,eAAe,EAAE,OAAO,CAAC;IACzB,kBAAkB,EAAE,CAAC,OAAO,EAAE,OAAO,KAAK,IAAI,CAAC;IAC/C,kFAAkF;IAClF,YAAY,EAAE,CAAC,SAAS,EAAE,MAAM,KAAK,IAAI,CAAC;CAC3C;
|
|
1
|
+
{"version":3,"file":"AssistantSpeechProvider.d.ts","sourceRoot":"","sources":["../../../../src/shared/assistant/ui/AssistantSpeechProvider.tsx"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AAEH,OAAO,EASL,KAAK,EAAE,EACP,KAAK,SAAS,EACf,MAAM,OAAO,CAAC;AAKf,OAAO,KAAK,EAAE,YAAY,EAAE,eAAe,EAAE,MAAM,WAAW,CAAC;AA2B/D,OAAO,EAQL,KAAK,iBAAiB,EACvB,MAAM,uBAAuB,CAAC;AAiB/B,MAAM,WAAW,2BAA2B;IAC1C,gFAAgF;IAChF,WAAW,EAAE,OAAO,CAAC;IACrB,YAAY,EAAE,iBAAiB,CAAC;IAChC;;;;OAIG;IACH,SAAS,EAAE,OAAO,CAAC;IACnB,6EAA6E;IAC7E,cAAc,EAAE,MAAM,GAAG,IAAI,CAAC;IAC9B;;;;;;OAMG;IACH,UAAU,EAAE,CAAC,SAAS,EAAE,MAAM,KAAK,MAAM,GAAG,IAAI,CAAC;IACjD;;;;OAIG;IACH,YAAY,EAAE,SAAS,eAAe,EAAE,CAAC;IACzC,8EAA8E;IAC9E;;;;;;OAMG;IACH,YAAY,EAAE;QAAE,MAAM,EAAE,MAAM,EAAE,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,GAAG,IAAI,CAAC;IACzD,eAAe,EAAE,MAAM,GAAG,IAAI,CAAC;IAC/B;;;;;;;;OAQG;IACH,kBAAkB,EAAE,MAAM,GAAG,IAAI,CAAC;IAClC,mEAAmE;IACnE,QAAQ,EAAE,CAAC,SAAS,EAAE,MAAM,GAAG,IAAI,KAAK,IAAI,CAAC;IAC7C,kDAAkD;IAClD,iBAAiB,EAAE,MAAM,GAAG,IAAI,CAAC;IACjC,UAAU,EAAE,CAAC,SAAS,EAAE,MAAM,KAAK,OAAO,CAAC;IAC3C;;;;;;;OAOG;IACH,MAAM,EAAE,CAAC,SAAS,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,UAAU,CAAC,EAAE,MAAM,KAAK,IAAI,CAAC;IAC3E,IAAI,EAAE,MAAM,IAAI,CAAC;IACjB,gBAAgB,EAAE,OAAO,CAAC;IAC1B,YAAY,EAAE,CAAC,OAAO,EAAE,OAAO,KAAK,IAAI,CAAC;IACzC;;;;;;;;;;;;;OAaG;IACH,eAAe,EAAE,OAAO,CAAC;IACzB,kBAAkB,EAAE,CAAC,OAAO,EAAE,OAAO,KAAK,IAAI,CAAC;IAC/C;;;;;;;;;;;;;OAaG;IACH,iBAAiB,EAAE,CAAC,IAAI,EAAE,OAAO,KAAK,IAAI,CAAC;IAC3C,kFAAkF;IAClF,YAAY,EAAE,CAAC,SAAS,EAAE,MAAM,KAAK,IAAI,CAAC;CAC3C;AA4BD,wBAAgB,kBAAkB,IAAI,2BAA2B,CAEhE;AAED,UAAU,KAAK;IACb,QAAQ,EAAE,SAAS,CAAC;IACpB,0DAA0D;IAC1D,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB;;;;OAIG;IACH,MAAM,CAAC,EAAE,YAAY,CAAC;CACvB;AAED,eAAO,MAAM,uBAAuB,EAAE,EAAE,CAAC,KAAK,CAwyB7C,CAAC"}
|
|
@@ -9,15 +9,15 @@ import { resolveLanguagePair as te } from "../voice/languagePair.js";
|
|
|
9
9
|
import { useAssistantTr as ne } from "../i18n.js";
|
|
10
10
|
import { speechLabelsFor as re } from "../voice/speechLabels.js";
|
|
11
11
|
import { resolveSpeechLocale as ie } from "../voice/replyLanguage.js";
|
|
12
|
-
import { IDLE_PLAYBACK as ae, isSpeakingMessage as
|
|
13
|
-
import { useAssistantStore as
|
|
14
|
-
import { isTurnInFlight as
|
|
15
|
-
import { parseToolActivity as
|
|
12
|
+
import { IDLE_PLAYBACK as ae, isSpeakingMessage as oe, speechPlaybackReducer as se } from "../voice/speechPlayback.js";
|
|
13
|
+
import { useAssistantStore as p } from "../store.js";
|
|
14
|
+
import { isTurnInFlight as ce } from "../turnState.js";
|
|
15
|
+
import { parseToolActivity as le } from "./AssistantToolActivity.js";
|
|
16
16
|
import "../speech/index.js";
|
|
17
|
-
import { createContext as
|
|
18
|
-
import { jsx as
|
|
17
|
+
import { createContext as ue, useCallback as m, useContext as h, useEffect as g, useMemo as _, useReducer as de, useRef as v, useState as y } from "react";
|
|
18
|
+
import { jsx as fe } from "react/jsx-runtime";
|
|
19
19
|
//#region src/shared/assistant/ui/AssistantSpeechProvider.tsx
|
|
20
|
-
var
|
|
20
|
+
var pe = {
|
|
21
21
|
codeBlock: "",
|
|
22
22
|
image: "",
|
|
23
23
|
link: "",
|
|
@@ -26,7 +26,7 @@ var de = {
|
|
|
26
26
|
emailAt: "at",
|
|
27
27
|
emailDot: "dot",
|
|
28
28
|
nestedItem: ""
|
|
29
|
-
},
|
|
29
|
+
}, me = 4e3, b = ue({
|
|
30
30
|
isSupported: !1,
|
|
31
31
|
availability: "unsupported",
|
|
32
32
|
isBlocked: !0,
|
|
@@ -45,263 +45,268 @@ var de = {
|
|
|
45
45
|
setAutoSpeak: () => {},
|
|
46
46
|
sessionSpeaking: !1,
|
|
47
47
|
setSessionSpeaking: () => {},
|
|
48
|
+
setSessionMicOpen: () => {},
|
|
48
49
|
previewVoice: () => {}
|
|
49
50
|
});
|
|
50
|
-
function
|
|
51
|
-
return
|
|
51
|
+
function x() {
|
|
52
|
+
return h(b);
|
|
52
53
|
}
|
|
53
|
-
var
|
|
54
|
-
let
|
|
55
|
-
|
|
56
|
-
|
|
54
|
+
var S = ({ children: ue, visible: h = !0, engine: x = n() }) => {
|
|
55
|
+
let S = ne(), { locale: C } = e(), [w, T] = de(se, ae), [E, D] = y(() => x.listVoices()), [O, k] = y(!1), [A, j] = y(() => /* @__PURE__ */ new Map()), M = v(0), N = v(null);
|
|
56
|
+
g(() => () => {
|
|
57
|
+
N.current !== null && clearTimeout(N.current);
|
|
57
58
|
}, []);
|
|
58
|
-
let [
|
|
59
|
-
|
|
60
|
-
}, []),
|
|
61
|
-
|
|
62
|
-
|
|
59
|
+
let [P, F] = y(null), I = v(null), he = v(() => {}), L = m(() => {
|
|
60
|
+
I.current?.(), I.current = null;
|
|
61
|
+
}, []), R = p((e) => e.autoSpeakEnabled), z = p((e) => e.setAutoSpeak), [B, ge] = y(!1), V = v(!1), H = m((e) => {
|
|
62
|
+
V.current = e;
|
|
63
|
+
}, []), _e = p((e) => e.activeConversationId), U = _(() => x.isSupported(), [x]);
|
|
64
|
+
g(() => {
|
|
65
|
+
if (!U) return;
|
|
63
66
|
let e = () => {
|
|
64
|
-
|
|
67
|
+
D(x.listVoices()), j((e) => e.size === 0 ? e : /* @__PURE__ */ new Map());
|
|
65
68
|
};
|
|
66
|
-
return e(),
|
|
67
|
-
}, [
|
|
68
|
-
let
|
|
69
|
-
he,
|
|
70
|
-
ge,
|
|
71
|
-
T
|
|
72
|
-
]), q = K.code, J = g((e) => f(e)?.tag ?? s(e), []), ve = g((e) => f(e)?.rate ?? .9, []), Y = y(() => c(W, O, K.tag, A), [
|
|
69
|
+
return e(), x.subscribeVoices(e);
|
|
70
|
+
}, [x, U]);
|
|
71
|
+
let W = p((e) => e.assistantLanguage), ve = p((e) => e.replyLanguage), G = p((e) => e.preferredVoices), ye = p((e) => e.setPreferredVoice), K = _(() => te(W, ve, C).reply, [
|
|
73
72
|
W,
|
|
74
|
-
|
|
73
|
+
ve,
|
|
74
|
+
C
|
|
75
|
+
]), q = K.code, J = m((e) => f(e)?.tag ?? s(e), []), be = m((e) => f(e)?.rate ?? .9, []), Y = _(() => c(U, E, K.tag, O), [
|
|
76
|
+
U,
|
|
77
|
+
E,
|
|
75
78
|
K,
|
|
76
|
-
|
|
77
|
-
]),
|
|
78
|
-
codeBlock:
|
|
79
|
-
image:
|
|
80
|
-
link:
|
|
81
|
-
largeTable:
|
|
82
|
-
truncated:
|
|
83
|
-
nestedItem:
|
|
84
|
-
emailAt:
|
|
85
|
-
emailDot:
|
|
86
|
-
}), [
|
|
87
|
-
|
|
88
|
-
}, [
|
|
89
|
-
let t =
|
|
90
|
-
t && (X(),
|
|
79
|
+
O
|
|
80
|
+
]), xe = _(() => ({
|
|
81
|
+
codeBlock: S("speech.codeBlock", "Code block"),
|
|
82
|
+
image: S("speech.image", "image"),
|
|
83
|
+
link: S("speech.link", "link"),
|
|
84
|
+
largeTable: S("speech.largeTable", "Table with {{rows}} rows and {{columns}} columns"),
|
|
85
|
+
truncated: S("speech.truncated", "The rest of this message is not read aloud"),
|
|
86
|
+
nestedItem: S("speech.nestedItem", "Sub-item {{ordinal}}"),
|
|
87
|
+
emailAt: S("speech.emailAt", "at"),
|
|
88
|
+
emailDot: S("speech.emailDot", "dot")
|
|
89
|
+
}), [S]), X = m(() => {
|
|
90
|
+
L(), x.cancel(), T({ type: "stop" });
|
|
91
|
+
}, [L, x]), Se = m((e) => {
|
|
92
|
+
let t = x.listVoices().find((t) => t.name === e) ?? null;
|
|
93
|
+
t && (X(), x.speak([d(q)], {
|
|
91
94
|
voice: t,
|
|
92
95
|
lang: J(q)
|
|
93
96
|
}));
|
|
94
97
|
}, [
|
|
95
|
-
|
|
98
|
+
x,
|
|
96
99
|
q,
|
|
97
100
|
X,
|
|
98
101
|
J
|
|
99
|
-
]),
|
|
100
|
-
|
|
102
|
+
]), Z = m((e) => A.get(e) ?? null, [A]), Ce = m((e, t, n) => {
|
|
103
|
+
L();
|
|
101
104
|
let i = !1, a = () => {}, o = (r) => {
|
|
102
105
|
if (!i) {
|
|
103
|
-
if (i = !0,
|
|
104
|
-
|
|
106
|
+
if (i = !0, I.current = null, clearTimeout(s), a(), r.length === 0) {
|
|
107
|
+
k(!0);
|
|
105
108
|
return;
|
|
106
109
|
}
|
|
107
|
-
|
|
110
|
+
D(r), he.current(e, t, r, n);
|
|
108
111
|
}
|
|
109
|
-
}, s = setTimeout(() => o(
|
|
110
|
-
a =
|
|
111
|
-
i || (i = !0, clearTimeout(s), a(),
|
|
112
|
+
}, s = setTimeout(() => o(x.listVoices()), r);
|
|
113
|
+
a = x.subscribeVoices(() => o(x.listVoices())), I.current = () => {
|
|
114
|
+
i || (i = !0, clearTimeout(s), a(), I.current = null);
|
|
112
115
|
};
|
|
113
|
-
}, [
|
|
116
|
+
}, [L, x]), Q = m((e, t, n, r) => {
|
|
114
117
|
let s = n;
|
|
115
118
|
if (s.length === 0) {
|
|
116
|
-
let e =
|
|
117
|
-
e.length > 0 && (s = e,
|
|
119
|
+
let e = x.listVoices();
|
|
120
|
+
e.length > 0 && (s = e, D(e));
|
|
118
121
|
}
|
|
119
|
-
let l = J(r), u = o(c(!0, s, r,
|
|
122
|
+
let l = J(r), u = o(c(!0, s, r, O));
|
|
120
123
|
if (u === "block") {
|
|
121
|
-
let t =
|
|
122
|
-
|
|
124
|
+
let t = S("speech.noVoiceForReply", "This reply is in {{language}}, and no {{language}} voice is installed on this device.", { language: i(l, C) });
|
|
125
|
+
j((n) => new Map(n).set(e, t));
|
|
123
126
|
return;
|
|
124
127
|
}
|
|
125
128
|
if (u === "wait-for-voices") {
|
|
126
|
-
|
|
129
|
+
Ce(e, t, r);
|
|
127
130
|
return;
|
|
128
131
|
}
|
|
129
|
-
|
|
132
|
+
j((t) => {
|
|
130
133
|
if (!t.has(e)) return t;
|
|
131
134
|
let n = new Map(t);
|
|
132
135
|
return n.delete(e), n;
|
|
133
136
|
});
|
|
134
|
-
let d =
|
|
135
|
-
|
|
137
|
+
let d = M.current + 1;
|
|
138
|
+
M.current = d, T({
|
|
136
139
|
type: "start",
|
|
137
140
|
messageId: e,
|
|
138
141
|
requestId: d
|
|
139
142
|
});
|
|
140
143
|
let f = ee(t);
|
|
141
|
-
|
|
144
|
+
F({
|
|
142
145
|
requestId: d,
|
|
143
146
|
chunks: f,
|
|
144
147
|
index: -1
|
|
145
|
-
}),
|
|
146
|
-
|
|
147
|
-
},
|
|
148
|
+
}), N.current !== null && clearTimeout(N.current), N.current = setTimeout(() => {
|
|
149
|
+
F((e) => e?.requestId === d && e.index < 0 ? null : e);
|
|
150
|
+
}, me), x.speak(f, {
|
|
148
151
|
voice: a(s, l, G[r]),
|
|
149
152
|
lang: l,
|
|
150
|
-
rate:
|
|
153
|
+
rate: be(r)
|
|
151
154
|
}, {
|
|
152
155
|
onChunkStart: (e) => {
|
|
153
|
-
|
|
156
|
+
M.current === d && N.current !== null && (clearTimeout(N.current), N.current = null), F((t) => t?.requestId === d ? {
|
|
154
157
|
...t,
|
|
155
158
|
index: e
|
|
156
|
-
} :
|
|
159
|
+
} : M.current === d ? {
|
|
157
160
|
requestId: d,
|
|
158
161
|
chunks: f,
|
|
159
162
|
index: e
|
|
160
163
|
} : t);
|
|
161
164
|
},
|
|
162
|
-
onEnd: () =>
|
|
165
|
+
onEnd: () => T({
|
|
163
166
|
type: "finished",
|
|
164
167
|
requestId: d
|
|
165
168
|
}),
|
|
166
|
-
onError: () =>
|
|
169
|
+
onError: () => T({
|
|
167
170
|
type: "failed",
|
|
168
171
|
requestId: d
|
|
169
172
|
})
|
|
170
173
|
});
|
|
171
174
|
}, [
|
|
175
|
+
x,
|
|
172
176
|
C,
|
|
173
|
-
T,
|
|
174
177
|
G,
|
|
175
|
-
|
|
178
|
+
be,
|
|
176
179
|
J,
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
+
S,
|
|
181
|
+
O,
|
|
182
|
+
Ce
|
|
180
183
|
]);
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
}, [
|
|
184
|
-
let
|
|
185
|
-
if (!
|
|
186
|
-
let r = ie(u(t, { labels:
|
|
187
|
-
i &&
|
|
184
|
+
g(() => {
|
|
185
|
+
he.current = Q;
|
|
186
|
+
}, [Q]);
|
|
187
|
+
let $ = m((e, t, n) => {
|
|
188
|
+
if (!U) return;
|
|
189
|
+
let r = ie(u(t, { labels: pe }), n ?? q), i = u(t, { labels: re(r, xe) });
|
|
190
|
+
i && Q(e, i, E, r);
|
|
188
191
|
}, [
|
|
189
|
-
|
|
190
|
-
|
|
192
|
+
U,
|
|
193
|
+
xe,
|
|
191
194
|
q,
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
]),
|
|
195
|
-
if (
|
|
195
|
+
Q,
|
|
196
|
+
E
|
|
197
|
+
]), we = m((e, t, n) => {
|
|
198
|
+
if (oe(w, e)) {
|
|
196
199
|
X();
|
|
197
200
|
return;
|
|
198
201
|
}
|
|
199
|
-
|
|
202
|
+
$(e, t, n);
|
|
200
203
|
}, [
|
|
201
|
-
|
|
202
|
-
|
|
204
|
+
w,
|
|
205
|
+
$,
|
|
203
206
|
X
|
|
204
207
|
]);
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
}, [
|
|
208
|
-
X(),
|
|
209
|
-
}, [
|
|
210
|
-
|
|
211
|
-
}, [q, X]),
|
|
212
|
-
|
|
213
|
-
}, [
|
|
208
|
+
g(() => {
|
|
209
|
+
h || X();
|
|
210
|
+
}, [h, X]), g(() => {
|
|
211
|
+
X(), j(/* @__PURE__ */ new Map());
|
|
212
|
+
}, [_e, X]), g(() => {
|
|
213
|
+
j((e) => e.size === 0 ? e : /* @__PURE__ */ new Map()), X();
|
|
214
|
+
}, [q, X]), g(() => () => {
|
|
215
|
+
I.current?.(), I.current = null, x.cancel();
|
|
216
|
+
}, [x]), g(() => {
|
|
214
217
|
if (typeof window > "u") return;
|
|
215
|
-
let e = () =>
|
|
218
|
+
let e = () => x.cancel();
|
|
216
219
|
return window.addEventListener("pagehide", e), () => window.removeEventListener("pagehide", e);
|
|
217
|
-
}, [
|
|
218
|
-
if (typeof document > "u" || !
|
|
220
|
+
}, [x]), g(() => {
|
|
221
|
+
if (typeof document > "u" || !U) return;
|
|
219
222
|
let e = () => {
|
|
220
223
|
if (document.visibilityState !== "visible") return;
|
|
221
|
-
let e =
|
|
222
|
-
e.length > 0 &&
|
|
224
|
+
let e = x.listVoices();
|
|
225
|
+
e.length > 0 && L(), D(e), k(!1), j((e) => e.size === 0 ? e : /* @__PURE__ */ new Map());
|
|
223
226
|
};
|
|
224
227
|
return document.addEventListener("visibilitychange", e), window.addEventListener("focus", e), () => {
|
|
225
228
|
document.removeEventListener("visibilitychange", e), window.removeEventListener("focus", e);
|
|
226
229
|
};
|
|
227
230
|
}, [
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
+
L,
|
|
232
|
+
x,
|
|
233
|
+
U
|
|
231
234
|
]);
|
|
232
|
-
let
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
}, [
|
|
236
|
-
if (!(!
|
|
235
|
+
let Te = v($);
|
|
236
|
+
g(() => {
|
|
237
|
+
Te.current = $;
|
|
238
|
+
}, [$]), g(() => {
|
|
239
|
+
if (!(!R && !B || !h || !U)) return p.subscribe((e, n) => {
|
|
237
240
|
let r = e.activeConversationId;
|
|
238
241
|
if (!r || r !== n.activeConversationId) return;
|
|
239
242
|
let i = e.processingByConversationId[r], a = n.processingByConversationId[r];
|
|
240
|
-
if (i?.status !== "complete" || !
|
|
243
|
+
if (i?.status !== "complete" || !ce(a?.status)) return;
|
|
241
244
|
let o = i.messageId ?? a?.messageId ?? null;
|
|
242
245
|
if (!o) return;
|
|
243
246
|
let s = e.conversations.find((e) => e.id === r)?.messages.find((e) => e.id === o);
|
|
244
|
-
if (!s || s.role !== "assistant" || t(s) !==
|
|
245
|
-
let { text: c } =
|
|
246
|
-
c.trim() &&
|
|
247
|
+
if (!s || s.role !== "assistant" || t(s) !== B || V.current) return;
|
|
248
|
+
let { text: c } = le(s.content);
|
|
249
|
+
c.trim() && Te.current(o, c, s.metadata?.lang);
|
|
247
250
|
});
|
|
248
251
|
}, [
|
|
249
|
-
|
|
252
|
+
R,
|
|
253
|
+
B,
|
|
250
254
|
U,
|
|
251
|
-
|
|
252
|
-
_
|
|
255
|
+
h
|
|
253
256
|
]);
|
|
254
|
-
let
|
|
255
|
-
|
|
257
|
+
let Ee = _(() => l(E, K.tag), [E, K]), De = _(() => a(E, K.tag, G[q]), [
|
|
258
|
+
E,
|
|
256
259
|
K,
|
|
257
260
|
G,
|
|
258
261
|
q
|
|
259
|
-
]),
|
|
260
|
-
isSupported:
|
|
262
|
+
]), Oe = _(() => ({
|
|
263
|
+
isSupported: U,
|
|
261
264
|
availability: Y,
|
|
262
265
|
isBlocked: Y === "no-voices",
|
|
263
|
-
disabledReason: Y === "no-voices" ?
|
|
264
|
-
blockedFor:
|
|
265
|
-
voiceChoices:
|
|
266
|
-
spokenChunks:
|
|
267
|
-
chunks:
|
|
268
|
-
index:
|
|
266
|
+
disabledReason: Y === "no-voices" ? S("speech.noVoicesOnDevice", "This device has no speech voices installed. Add one in your device speech or accessibility settings.") : null,
|
|
267
|
+
blockedFor: Z,
|
|
268
|
+
voiceChoices: Ee,
|
|
269
|
+
spokenChunks: P ? {
|
|
270
|
+
chunks: P.chunks,
|
|
271
|
+
index: P.index
|
|
269
272
|
} : null,
|
|
270
|
-
activeVoiceName:
|
|
273
|
+
activeVoiceName: De?.name ?? null,
|
|
271
274
|
preferredVoiceName: G[q] ?? null,
|
|
272
|
-
setVoice: (e) =>
|
|
273
|
-
speakingMessageId:
|
|
274
|
-
isSpeaking: (e) =>
|
|
275
|
-
toggle:
|
|
275
|
+
setVoice: (e) => ye(q, e),
|
|
276
|
+
speakingMessageId: w.status === "speaking" ? w.messageId : null,
|
|
277
|
+
isSpeaking: (e) => oe(w, e),
|
|
278
|
+
toggle: we,
|
|
276
279
|
stop: X,
|
|
277
|
-
autoSpeakEnabled:
|
|
278
|
-
setAutoSpeak:
|
|
279
|
-
sessionSpeaking:
|
|
280
|
-
setSessionSpeaking:
|
|
281
|
-
|
|
280
|
+
autoSpeakEnabled: R,
|
|
281
|
+
setAutoSpeak: z,
|
|
282
|
+
sessionSpeaking: B,
|
|
283
|
+
setSessionSpeaking: ge,
|
|
284
|
+
setSessionMicOpen: H,
|
|
285
|
+
previewVoice: Se
|
|
282
286
|
}), [
|
|
283
|
-
|
|
287
|
+
U,
|
|
284
288
|
Y,
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
289
|
+
Z,
|
|
290
|
+
Ee,
|
|
291
|
+
De,
|
|
288
292
|
G,
|
|
289
|
-
|
|
293
|
+
ye,
|
|
290
294
|
q,
|
|
291
|
-
|
|
292
|
-
|
|
295
|
+
w,
|
|
296
|
+
we,
|
|
293
297
|
X,
|
|
294
|
-
|
|
298
|
+
R,
|
|
299
|
+
z,
|
|
300
|
+
B,
|
|
295
301
|
H,
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
I
|
|
302
|
+
Se,
|
|
303
|
+
S,
|
|
304
|
+
P
|
|
300
305
|
]);
|
|
301
|
-
return /* @__PURE__ */
|
|
302
|
-
value:
|
|
303
|
-
children:
|
|
306
|
+
return /* @__PURE__ */ fe(b.Provider, {
|
|
307
|
+
value: Oe,
|
|
308
|
+
children: ue
|
|
304
309
|
});
|
|
305
310
|
};
|
|
306
311
|
//#endregion
|
|
307
|
-
export {
|
|
312
|
+
export { S as AssistantSpeechProvider, x as useAssistantSpeech };
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useVoiceSession.d.ts","sourceRoot":"","sources":["../../../../src/shared/assistant/ui/useVoiceSession.ts"],"names":[],"mappings":"AAUA,OAAO,EAWL,KAAK,oBAAoB,EAE1B,MAAM,uBAAuB,CAAC;AAsC/B;;;;;;;;GAQG;AACH,MAAM,MAAM,kBAAkB,GAC1B,SAAS,GACT,eAAe,GACf,eAAe,GACf,oBAAoB,CAAC;AAMzB,UAAU,OAAO;IACf,+EAA+E;IAC/E;;;;;;;OAOG;IACH,QAAQ,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,cAAc,EAAE,MAAM,KAAK,IAAI,CAAC;IACzD;;;;OAIG;IACH,WAAW,EAAE;QAAE,EAAE,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,GAAG,IAAI,CAAC;IACjD,6EAA6E;IAC7E,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED;;;;;;;;;;;;;GAaG;AACH,wBAAgB,eAAe,CAAC,EAAE,QAAQ,EAAE,WAAW,EAAE,QAAQ,EAAE,EAAE,OAAO;;
|
|
1
|
+
{"version":3,"file":"useVoiceSession.d.ts","sourceRoot":"","sources":["../../../../src/shared/assistant/ui/useVoiceSession.ts"],"names":[],"mappings":"AAUA,OAAO,EAWL,KAAK,oBAAoB,EAE1B,MAAM,uBAAuB,CAAC;AAsC/B;;;;;;;;GAQG;AACH,MAAM,MAAM,kBAAkB,GAC1B,SAAS,GACT,eAAe,GACf,eAAe,GACf,oBAAoB,CAAC;AAMzB,UAAU,OAAO;IACf,+EAA+E;IAC/E;;;;;;;OAOG;IACH,QAAQ,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,cAAc,EAAE,MAAM,KAAK,IAAI,CAAC;IACzD;;;;OAIG;IACH,WAAW,EAAE;QAAE,EAAE,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,GAAG,IAAI,CAAC;IACjD,6EAA6E;IAC7E,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED;;;;;;;;;;;;;GAaG;AACH,wBAAgB,eAAe,CAAC,EAAE,QAAQ,EAAE,WAAW,EAAE,QAAQ,EAAE,EAAE,OAAO;;IAuiBtE,qEAAqE;;IAErE;;;;;;;OAOG;;;;;IAEH,+DAA+D;;IAE/D;;;;;;;OAOG;;IAIH,0EAA0E;;IAE1E,6DAA6D;;IAE7D,sDAAsD;;;;;;EA4B3D"}
|
|
@@ -5,10 +5,10 @@ import { useCallback as u, useEffect as d, useMemo as f, useReducer as p, useRef
|
|
|
5
5
|
//#region src/shared/assistant/ui/useVoiceSession.ts
|
|
6
6
|
var g = 4e3, _ = 2500, v = 5e3, y = 12e3, b = "data:audio/wav;base64,UklGRiQAAABXQVZFZm10IBAAAAABAAEARKwAAIhYAQACABAAZGF0YQAAAAA=";
|
|
7
7
|
function x({ onSubmit: x, latestReply: S, language: C }) {
|
|
8
|
-
let w = m(null), [T, E] = p(u((e, t) => c(e, t, w.current), []), t), D = l(), { setSessionSpeaking: O,
|
|
9
|
-
|
|
10
|
-
let
|
|
11
|
-
|
|
8
|
+
let w = m(null), [T, E] = p(u((e, t) => c(e, t, w.current), []), t), D = l(), { setSessionSpeaking: O, setSessionMicOpen: k, speakingMessageId: A, stop: j } = D, M = m(null), N = m(null), P = m(!1), [F, I] = h(null), [L, R] = h(!1), [z, B] = h(!1), V = m(T);
|
|
9
|
+
V.current = T;
|
|
10
|
+
let H = m(S);
|
|
11
|
+
H.current = S, d(() => {
|
|
12
12
|
if (T.phase === "speaking") {
|
|
13
13
|
w.current = S?.text ?? null;
|
|
14
14
|
return;
|
|
@@ -19,78 +19,83 @@ function x({ onSubmit: x, latestReply: S, language: C }) {
|
|
|
19
19
|
}, _);
|
|
20
20
|
return () => clearTimeout(e);
|
|
21
21
|
}, [T.phase, S]);
|
|
22
|
-
let
|
|
22
|
+
let U = u((e, t) => {
|
|
23
23
|
E({
|
|
24
24
|
type: "speech",
|
|
25
25
|
transcript: e,
|
|
26
26
|
final: t
|
|
27
27
|
});
|
|
28
|
-
}, []),
|
|
29
|
-
|
|
30
|
-
}, [
|
|
31
|
-
onFinalize: u((e) =>
|
|
28
|
+
}, []), W = m(0), G = u(() => {
|
|
29
|
+
j(), W.current = Date.now(), R(!0), E({ type: "interrupt" });
|
|
30
|
+
}, [j]), K = e({
|
|
31
|
+
onFinalize: u((e) => U(e, !0), [U]),
|
|
32
32
|
language: C
|
|
33
33
|
});
|
|
34
34
|
d(() => {
|
|
35
|
-
|
|
36
|
-
}, [
|
|
37
|
-
if (
|
|
38
|
-
let e = setTimeout(() =>
|
|
39
|
-
return
|
|
40
|
-
clearTimeout(e),
|
|
35
|
+
K.interim && U(K.interim, !1);
|
|
36
|
+
}, [K.interim, U]), d(() => {
|
|
37
|
+
if (M.current && clearTimeout(M.current), B(!1), T.phase !== "listening" || T.muted || !a(s(T))) return;
|
|
38
|
+
let e = setTimeout(() => B(!0), 800);
|
|
39
|
+
return M.current = setTimeout(() => E({ type: "silence" }), r), () => {
|
|
40
|
+
clearTimeout(e), M.current && clearTimeout(M.current);
|
|
41
41
|
};
|
|
42
42
|
}, [T]), d(() => {
|
|
43
|
-
if (!
|
|
44
|
-
let e = Date.now() -
|
|
43
|
+
if (!L) return;
|
|
44
|
+
let e = Date.now() - W.current, t = K.isListening ? Math.max(0, 500 - e) : Math.max(0, n - e), r = setTimeout(() => R(!1), t);
|
|
45
45
|
return () => clearTimeout(r);
|
|
46
|
-
}, [
|
|
47
|
-
let
|
|
48
|
-
T.phase === "listening" && (
|
|
46
|
+
}, [L, K.isListening]);
|
|
47
|
+
let q = m("");
|
|
48
|
+
T.phase === "listening" && (q.current = s(T)), d(() => {
|
|
49
49
|
if (T.phase !== "thinking") return;
|
|
50
|
-
let e =
|
|
51
|
-
e && x(e,
|
|
50
|
+
let e = q.current.trim();
|
|
51
|
+
e && x(e, J.current ?? `vs-orphan-${Date.now().toString(36)}`);
|
|
52
52
|
}, [T.phase]), d(() => {
|
|
53
|
-
let e = o(S?.id, T.phase,
|
|
54
|
-
e.claim && (
|
|
53
|
+
let e = o(S?.id, T.phase, N.current);
|
|
54
|
+
e.claim && (N.current = S?.id ?? null, e.advance && S && E({
|
|
55
55
|
type: "reply",
|
|
56
56
|
text: S.text
|
|
57
57
|
}));
|
|
58
58
|
}, [S, T.phase]), d(() => {
|
|
59
|
-
let e =
|
|
60
|
-
|
|
61
|
-
}, [
|
|
62
|
-
T.phase !== "listening" &&
|
|
59
|
+
let e = A !== null;
|
|
60
|
+
P.current && !e && E({ type: "speech-ended" }), P.current = e;
|
|
61
|
+
}, [A]), d(() => {
|
|
62
|
+
T.phase !== "listening" && I((e) => e === "nothing-heard" ? null : e);
|
|
63
63
|
}, [T.phase]), d(() => {
|
|
64
|
-
if (T.phase !== "speaking" ||
|
|
64
|
+
if (T.phase !== "speaking" || A !== null) return;
|
|
65
65
|
let e = setTimeout(() => {
|
|
66
|
-
|
|
66
|
+
P.current || E({ type: "speech-ended" });
|
|
67
67
|
}, g);
|
|
68
68
|
return () => clearTimeout(e);
|
|
69
|
-
}, [T.phase,
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
69
|
+
}, [T.phase, A]), d(() => {
|
|
70
|
+
let e = i(T);
|
|
71
|
+
k(e), e ? K.isActive || K.start() : K.isActive && K.stop();
|
|
72
|
+
}, [
|
|
73
|
+
T,
|
|
74
|
+
K,
|
|
75
|
+
k
|
|
76
|
+
]), d(() => {
|
|
77
|
+
K.error === "not-allowed" || K.error === "audio-capture" ? E({
|
|
73
78
|
type: "fail",
|
|
74
79
|
error: "mic-denied"
|
|
75
|
-
}) :
|
|
80
|
+
}) : K.error === "language-not-supported" ? E({
|
|
76
81
|
type: "fail",
|
|
77
82
|
error: "no-speech-support"
|
|
78
|
-
}) :
|
|
79
|
-
}, [
|
|
80
|
-
|
|
81
|
-
}, [
|
|
82
|
-
if (
|
|
83
|
-
let e = setTimeout(() =>
|
|
83
|
+
}) : K.error === "network" ? I("network") : K.error === "unknown" && I("recognition-failed");
|
|
84
|
+
}, [K.error]), d(() => {
|
|
85
|
+
K.error !== null || !K.isListening || I((e) => e === "network" || e === "recognition-failed" ? null : e);
|
|
86
|
+
}, [K.error, K.isListening]), d(() => {
|
|
87
|
+
if (K.isListening && I((e) => e === "not-capturing" ? null : e), !i(T) || K.isListening) return;
|
|
88
|
+
let e = setTimeout(() => I("not-capturing"), v);
|
|
84
89
|
return () => clearTimeout(e);
|
|
85
|
-
}, [T,
|
|
86
|
-
if (T.phase !== "listening" || T.muted || !
|
|
87
|
-
let e = setTimeout(() =>
|
|
90
|
+
}, [T, K.isListening]), d(() => {
|
|
91
|
+
if (T.phase !== "listening" || T.muted || !K.isListening || s(T) !== "") return;
|
|
92
|
+
let e = setTimeout(() => I("nothing-heard"), y);
|
|
88
93
|
return () => clearTimeout(e);
|
|
89
|
-
}, [T,
|
|
90
|
-
s(T) !== "" &&
|
|
94
|
+
}, [T, K.isListening]), d(() => {
|
|
95
|
+
s(T) !== "" && I(null);
|
|
91
96
|
}, [T]);
|
|
92
|
-
let
|
|
93
|
-
if (
|
|
97
|
+
let J = m(null), Y = u(() => {
|
|
98
|
+
if (R(!1), B(!1), !K.isSupported) {
|
|
94
99
|
E({
|
|
95
100
|
type: "fail",
|
|
96
101
|
error: "no-speech-support"
|
|
@@ -117,47 +122,47 @@ function x({ onSubmit: x, latestReply: S, language: C }) {
|
|
|
117
122
|
e.volume = 0, e.play().catch(() => {});
|
|
118
123
|
}
|
|
119
124
|
} catch {}
|
|
120
|
-
O(!0),
|
|
125
|
+
O(!0), I(null), N.current = H.current?.id ?? null, J.current = `vs-${Date.now().toString(36)}-${Math.random().toString(36).slice(2, 8)}`, E({ type: "start" });
|
|
121
126
|
}, [
|
|
122
|
-
|
|
127
|
+
K.isSupported,
|
|
123
128
|
D.isBlocked,
|
|
124
129
|
O
|
|
125
|
-
]),
|
|
126
|
-
|
|
127
|
-
}, [
|
|
130
|
+
]), X = u(() => {
|
|
131
|
+
R(!1), B(!1), J.current = null, E({ type: "end" }), j(), O(!1);
|
|
132
|
+
}, [j, O]), Z = u(() => {
|
|
128
133
|
E({
|
|
129
134
|
type: "mute",
|
|
130
|
-
muted: !
|
|
135
|
+
muted: !V.current.muted
|
|
131
136
|
});
|
|
132
137
|
}, []);
|
|
133
138
|
return d(() => () => {
|
|
134
|
-
O(!1);
|
|
135
|
-
}, [O]), f(() => ({
|
|
139
|
+
O(!1), k(!1);
|
|
140
|
+
}, [O, k]), f(() => ({
|
|
136
141
|
session: T,
|
|
137
|
-
notice:
|
|
142
|
+
notice: F,
|
|
138
143
|
spokenChunks: D.spokenChunks,
|
|
139
|
-
capturing:
|
|
144
|
+
capturing: K.isListening,
|
|
140
145
|
active: T.phase !== "idle" && (T.phase !== "ended" || T.error !== null),
|
|
141
|
-
interrupting:
|
|
142
|
-
awaitingEndpoint:
|
|
143
|
-
available:
|
|
144
|
-
start:
|
|
145
|
-
end:
|
|
146
|
-
toggleMute:
|
|
147
|
-
interrupt:
|
|
146
|
+
interrupting: L,
|
|
147
|
+
awaitingEndpoint: z,
|
|
148
|
+
available: K.isSupported && !D.isBlocked,
|
|
149
|
+
start: Y,
|
|
150
|
+
end: X,
|
|
151
|
+
toggleMute: Z,
|
|
152
|
+
interrupt: G
|
|
148
153
|
}), [
|
|
149
154
|
T,
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
+
F,
|
|
156
|
+
L,
|
|
157
|
+
z,
|
|
158
|
+
K.isListening,
|
|
159
|
+
K.isSupported,
|
|
155
160
|
D.isBlocked,
|
|
156
161
|
D.spokenChunks,
|
|
157
|
-
J,
|
|
158
162
|
Y,
|
|
159
163
|
X,
|
|
160
|
-
|
|
164
|
+
Z,
|
|
165
|
+
G
|
|
161
166
|
]);
|
|
162
167
|
}
|
|
163
168
|
//#endregion
|