@burdenoff/fe-libs 2026.1029.6 → 2026.1029.7

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.
Files changed (34) hide show
  1. package/dist/shared/assistant/index.d.ts +5 -0
  2. package/dist/shared/assistant/liveDeltas.d.ts +3 -0
  3. package/dist/shared/assistant/liveDeltas.js +17 -1
  4. package/dist/shared/assistant/liveOverlay.d.ts +4 -0
  5. package/dist/shared/assistant/liveOverlay.js +10 -1
  6. package/dist/shared/assistant/speech/appendSpeechQueue.d.ts +13 -0
  7. package/dist/shared/assistant/speech/appendSpeechQueue.js +75 -0
  8. package/dist/shared/assistant/speech/browserSpeechEngine.js +93 -46
  9. package/dist/shared/assistant/speech/hostedTtsSpeechEngine.js +173 -109
  10. package/dist/shared/assistant/speech/index.d.ts +1 -1
  11. package/dist/shared/assistant/speech/notifyCancellationSpeechEngine.js +53 -0
  12. package/dist/shared/assistant/speech/routingSpeechEngine.js +107 -23
  13. package/dist/shared/assistant/speech/speechFeed.d.ts +17 -2
  14. package/dist/shared/assistant/speech/speechFeed.js +35 -12
  15. package/dist/shared/assistant/speech/types.d.ts +20 -1
  16. package/dist/shared/assistant/turnTimeline.d.ts +3 -0
  17. package/dist/shared/assistant/turnTimeline.js +4 -1
  18. package/dist/shared/assistant/ui/AssistantChatArea.js +1410 -1393
  19. package/dist/shared/assistant/ui/AssistantSpeechProvider.js +351 -291
  20. package/dist/shared/assistant/ui/useVoiceSession.js +323 -288
  21. package/dist/shared/assistant/voice/livePhraseSpeech.d.ts +14 -0
  22. package/dist/shared/assistant/voice/livePhraseSpeech.js +72 -0
  23. package/dist/shared/assistant/voice/phraseGate.d.ts +11 -0
  24. package/dist/shared/assistant/voice/phraseGate.js +74 -0
  25. package/dist/shared/assistant/voice/phrasePlayback.d.ts +9 -0
  26. package/dist/shared/assistant/voice/phrasePlayback.js +78 -0
  27. package/dist/shared/assistant/voice/phraseSpeechConfig.d.ts +5 -0
  28. package/dist/shared/assistant/voice/phraseSpeechConfig.js +10 -0
  29. package/dist/shared/assistant/voice/speakableText.d.ts +1 -0
  30. package/dist/shared/assistant/voice/speakableText.js +1 -1
  31. package/dist/shared/assistant/voice/voiceSession.d.ts +5 -0
  32. package/dist/shared/assistant/voice/voiceSession.js +17 -1
  33. package/dist/shared-assistant.js +293 -288
  34. package/package.json +1 -1
@@ -3,27 +3,29 @@ import { useAssistantTr as t } from "../i18n.js";
3
3
  import { useAssistantStore as n } from "../store.js";
4
4
  import { isVoiceTurn as r } from "../voice/turnVisibility.js";
5
5
  import { HOSTED_VOICES as i } from "../speech/hostedVoiceCatalogue.js";
6
- import { VOICE_LIST_TIMEOUT_MS as a, languageDisplayName as o, selectVoiceForLocale as s, speechGate as ee, speechLangForLocale as c, voiceAvailability as te, voicesForLocale as l } from "../voice/speechVoices.js";
7
- import { getSpeechEngine as u, subscribeSpeechEngine as ne } from "../speech/createSpeechEngine.js";
8
- import { speechFeed as d } from "../speech/speechFeed.js";
9
- import { hasPendingReplyRequests as f, releaseReplyRequestsOutside as p, replyWantsAvatar as re, settleReplyRequest as m, subscribeReplyRequests as h } from "../speech/replySpeechRequests.js";
6
+ import { VOICE_LIST_TIMEOUT_MS as a, languageDisplayName as o, selectVoiceForLocale as s, speechGate as c, speechLangForLocale as l, voiceAvailability as ee, voicesForLocale as u } from "../voice/speechVoices.js";
7
+ import { getSpeechEngine as d, subscribeSpeechEngine as te } from "../speech/createSpeechEngine.js";
8
+ import { speechFeed as f } from "../speech/speechFeed.js";
9
+ import { hasPendingReplyRequests as ne, releaseReplyRequestsOutside as p, replyWantsAvatar as re, settleReplyRequest as m, subscribeReplyRequests as h } from "../speech/replySpeechRequests.js";
10
10
  import { isTurnSuperseded as g } from "../voice/supersededTurns.js";
11
11
  import { chunkForSpeech as ie, toSpeakableText as _ } from "../voice/speakableText.js";
12
12
  import { voicePreviewText as v } from "../voice/voicePreview.js";
13
- import { findAssistantLanguage as ae } from "../voice/languages.js";
14
- import { resolveLanguagePair as y } from "../voice/languagePair.js";
15
- import { speechLabelsFor as oe } from "../voice/speechLabels.js";
16
- import { resolveSpeechLocale as se } from "../voice/replyLanguage.js";
17
- import { IDLE_PLAYBACK as ce, isSpeakingMessage as le, publishedChunks as ue, speechPlaybackReducer as de } from "../voice/speechPlayback.js";
18
- import { isTurnInFlight as fe } from "../turnState.js";
19
- import { parseToolActivity as pe } from "./AssistantToolActivity.js";
13
+ import { findAssistantLanguage as y } from "../voice/languages.js";
14
+ import { resolveLanguagePair as b } from "../voice/languagePair.js";
15
+ import { speechLabelsFor as x } from "../voice/speechLabels.js";
16
+ import { resolveSpeechLocale as S } from "../voice/replyLanguage.js";
17
+ import { IDLE_PLAYBACK as ae, isSpeakingMessage as C, publishedChunks as oe, speechPlaybackReducer as se } from "../voice/speechPlayback.js";
18
+ import { isTurnInFlight as ce } from "../turnState.js";
19
+ import { parseToolActivity as le } from "./AssistantToolActivity.js";
20
20
  import "../speech/index.js";
21
- import { beginListenTurn as me, finishListenTurn as b, markTurn as he } from "../turnTimeline.js";
22
- import { registerTurnTimingPageExit as ge } from "../turnTimingReporter.js";
23
- import { createContext as _e, useCallback as x, useContext as ve, useEffect as S, useMemo as C, useReducer as ye, useRef as w, useState as T, useSyncExternalStore as be } from "react";
24
- import { jsx as xe } from "react/jsx-runtime";
21
+ import { createPhrasePlayback as ue } from "../voice/phrasePlayback.js";
22
+ import { phraseSpeechEnabled as de } from "../voice/phraseSpeechConfig.js";
23
+ import { beginListenTurn as fe, describeTurn as pe, finishListenTurn as w, markTurn as me } from "../turnTimeline.js";
24
+ import { registerTurnTimingPageExit as he } from "../turnTimingReporter.js";
25
+ import { createContext as ge, useCallback as T, useContext as _e, useEffect as E, useMemo as D, useReducer as ve, useRef as O, useState as k, useSyncExternalStore as ye } from "react";
26
+ import { jsx as be } from "react/jsx-runtime";
25
27
  //#region src/shared/assistant/ui/AssistantSpeechProvider.tsx
26
- var Se = {
28
+ var xe = {
27
29
  codeBlock: "",
28
30
  image: "",
29
31
  link: "",
@@ -32,30 +34,30 @@ var Se = {
32
34
  emailAt: "at",
33
35
  emailDot: "dot",
34
36
  nestedItem: ""
35
- }, Ce = 4e3, E = () => {}, we = {
36
- subscribe: () => E,
37
+ }, Se = 4e3, A = () => {}, Ce = {
38
+ subscribe: () => A,
37
39
  getSnapshot: () => !1
38
- }, Te = {
40
+ }, we = {
39
41
  subscribe: h,
40
- getSnapshot: f
42
+ getSnapshot: ne
41
43
  };
42
- function Ee(e, t) {
44
+ function Te(e, t) {
43
45
  return re(t) ? {
44
46
  ...e,
45
47
  autoSpeakEnabled: !0
46
48
  } : e;
47
49
  }
48
- function De(e, t) {
50
+ function Ee(e, t) {
49
51
  let n = e.activeConversationId;
50
52
  if (!n || n !== t.activeConversationId) return null;
51
53
  let r = e.processingByConversationId[n], i = t.processingByConversationId[n];
52
- if (r?.status !== "complete" || !fe(i?.status)) return null;
54
+ if (r?.status !== "complete" || !ce(i?.status)) return null;
53
55
  let a = r.messageId ?? i?.messageId ?? null;
54
56
  if (!a) return null;
55
57
  let o = e.conversations.find((e) => e.id === n)?.messages.find((e) => e.id === a);
56
58
  return o && o.role === "assistant" ? o : null;
57
59
  }
58
- var Oe = _e({
60
+ var De = ge({
59
61
  isSupported: !1,
60
62
  availability: "unsupported",
61
63
  isBlocked: !0,
@@ -80,404 +82,462 @@ var Oe = _e({
80
82
  speakFinishedReply: () => {},
81
83
  previewVoice: () => {}
82
84
  });
83
- function D() {
84
- return ve(Oe);
85
+ function j() {
86
+ return _e(De);
85
87
  }
86
- var O = ({ children: f, visible: h = !0, engine: _e }) => {
87
- let ve = be(ne, u, u), E = _e ?? ve, D = t(), { locale: O } = e(), [k, A] = ye(de, ce), [j, M] = T(() => E.listVoices()), [N, ke] = T(!1), [Ae, P] = T(() => /* @__PURE__ */ new Map()), [je, F] = T(() => /* @__PURE__ */ new Set()), [Me, Ne] = T(null), I = w(0), L = w(null), R = w(null), z = w(void 0), B = w(null), V = w(null);
88
- S(() => () => {
89
- V.current !== null && clearTimeout(V.current);
88
+ var M = ({ children: ne, visible: h = !0, engine: ge }) => {
89
+ let _e = ye(te, d, d), A = ge ?? _e, j = t(), { locale: M } = e(), [N, P] = ve(se, ae), [F, Oe] = k(() => A.listVoices()), [ke, Ae] = k(!1), [je, I] = k(() => /* @__PURE__ */ new Map()), [Me, Ne] = k(() => /* @__PURE__ */ new Set()), [Pe, Fe] = k(null), L = O(0), Ie = O(null), Le = O(null), R = O(void 0), z = O(null), B = O(null), V = O(/* @__PURE__ */ new Set()), H = O(null);
90
+ E(() => () => {
91
+ H.current !== null && clearTimeout(H.current);
90
92
  }, []);
91
- let [Pe, Fe] = T(null), H = w(null), Ie = w(() => {}), U = x(() => {
92
- H.current?.(), H.current = null;
93
- }, []), W = n((e) => e.autoSpeakEnabled), Le = n((e) => e.setAutoSpeak), [G, Re] = T(!1), ze = w(!1), Be = x((e) => {
94
- ze.current = e;
95
- }, []), Ve = n((e) => e.activeConversationId), K = C(() => E.isSupported(), [E]), He = E.wouldSpeakOnAvatar === void 0 ? we : Te, Ue = be(He.subscribe, He.getSnapshot, He.getSnapshot);
96
- S(() => {
97
- if (!K) return;
93
+ let [Re, ze] = k(null), U = O(null), Be = O(() => {}), W = T(() => {
94
+ U.current?.(), U.current = null;
95
+ }, []), G = n((e) => e.autoSpeakEnabled), Ve = n((e) => e.setAutoSpeak), [K, He] = k(!1), Ue = O(!1), We = T((e) => {
96
+ Ue.current = e;
97
+ }, []), Ge = n((e) => e.activeConversationId), q = D(() => A.isSupported(), [A]), Ke = A.wouldSpeakOnAvatar === void 0 ? Ce : we, qe = ye(Ke.subscribe, Ke.getSnapshot, Ke.getSnapshot);
98
+ E(() => {
99
+ if (!q) return;
98
100
  let e = () => {
99
- M(E.listVoices()), P((e) => e.size === 0 ? e : /* @__PURE__ */ new Map());
101
+ Oe(A.listVoices()), I((e) => e.size === 0 ? e : /* @__PURE__ */ new Map());
100
102
  };
101
- return e(), E.subscribeVoices(e);
102
- }, [E, K]);
103
- let We = n((e) => e.assistantLanguage), Ge = n((e) => e.replyLanguage), q = n((e) => e.preferredVoices), Ke = n((e) => e.setPreferredVoice), J = C(() => y(We, Ge, O).reply, [
104
- We,
105
- Ge,
106
- O
107
- ]), Y = J.code, qe = x((e) => ae(e)?.tag ?? c(e), []), Je = x((e) => ae(e)?.rate ?? .9, []), Ye = C(() => te(K, j, J.tag, N), [
108
- K,
109
- j,
110
- J,
111
- N
112
- ]), Xe = C(() => ({
113
- codeBlock: D("speech.codeBlock", "Code block"),
114
- image: D("speech.image", "image"),
115
- link: D("speech.link", "link"),
116
- largeTable: D("speech.largeTable", "Table with {{rows}} rows and {{columns}} columns"),
117
- truncated: D("speech.truncated", "The rest of this message is not read aloud"),
118
- nestedItem: D("speech.nestedItem", "Sub-item {{ordinal}}"),
119
- emailAt: D("speech.emailAt", "at"),
120
- emailDot: D("speech.emailDot", "dot")
121
- }), [D]), X = x(() => {
122
- U(), R.current = null, b(z.current, "stopped"), z.current = void 0, E.cancel(), m(L.current, "stopped"), A({ type: "stop" });
123
- }, [U, E]), Ze = x((e) => {
124
- let t = E.listVoices().find((t) => t.name === e) ?? null;
103
+ return e(), A.subscribeVoices(e);
104
+ }, [A, q]);
105
+ let Je = n((e) => e.assistantLanguage), Ye = n((e) => e.replyLanguage), J = n((e) => e.preferredVoices), Xe = n((e) => e.setPreferredVoice), Y = D(() => b(Je, Ye, M).reply, [
106
+ Je,
107
+ Ye,
108
+ M
109
+ ]), X = Y.code, Ze = T((e) => y(e)?.tag ?? l(e), []), Qe = T((e) => y(e)?.rate ?? .9, []), $e = D(() => ee(q, F, Y.tag, ke), [
110
+ q,
111
+ F,
112
+ Y,
113
+ ke
114
+ ]), et = D(() => ({
115
+ codeBlock: j("speech.codeBlock", "Code block"),
116
+ image: j("speech.image", "image"),
117
+ link: j("speech.link", "link"),
118
+ largeTable: j("speech.largeTable", "Table with {{rows}} rows and {{columns}} columns"),
119
+ truncated: j("speech.truncated", "The rest of this message is not read aloud"),
120
+ nestedItem: j("speech.nestedItem", "Sub-item {{ordinal}}"),
121
+ emailAt: j("speech.emailAt", "at"),
122
+ emailDot: j("speech.emailDot", "dot")
123
+ }), [j]), Z = T(() => {
124
+ let e = B.current;
125
+ if (e) try {
126
+ e.playback.cancel();
127
+ } finally {
128
+ e.notifyEnded();
129
+ }
130
+ }, []), Q = T(() => {
131
+ W(), Le.current = null, w(R.current, "stopped"), R.current = void 0, Z(), A.cancel(), m(Ie.current, "stopped"), P({ type: "stop" });
132
+ }, [
133
+ W,
134
+ Z,
135
+ A
136
+ ]), tt = T((e) => {
137
+ let t = A.listVoices().find((t) => t.name === e) ?? null;
125
138
  if (t) {
126
- X();
139
+ Q();
127
140
  try {
128
- E.speak([v(Y)], {
141
+ A.speak([v(X)], {
129
142
  voice: t,
130
- lang: qe(Y),
143
+ lang: Ze(X),
131
144
  fallback: !1
132
145
  });
133
146
  } catch {}
134
147
  }
135
148
  }, [
136
- E,
137
- Y,
149
+ A,
138
150
  X,
139
- qe
140
- ]), Qe = x((e) => Ae.get(e) ?? null, [Ae]), $e = x((e) => je.has(e) ? D("speech.deviceFallback", "Device voice used: the selected voice was unavailable.") : null, [je, D]), et = x((e, t, n, r, i) => {
141
- U();
142
- let o = !1, s = () => {}, ee = (a) => {
151
+ Q,
152
+ Ze
153
+ ]), nt = T((e) => je.get(e) ?? null, [je]), rt = T((e) => Me.has(e) ? j("speech.deviceFallback", "Device voice used: the selected voice was unavailable.") : null, [Me, j]), it = T((e, t, n, r, i) => {
154
+ W();
155
+ let o = !1, s = () => {}, c = (a) => {
143
156
  if (!o) {
144
- if (o = !0, H.current = null, clearTimeout(c), s(), a.length === 0) {
145
- ke(!0), m(e, "declined");
157
+ if (o = !0, U.current = null, clearTimeout(l), s(), a.length === 0) {
158
+ Ae(!0), m(e, "declined");
146
159
  return;
147
160
  }
148
- M(a), Ie.current(e, t, a, n, r, i);
161
+ Oe(a), Be.current(e, t, a, n, r, i);
149
162
  }
150
- }, c = setTimeout(() => ee(E.listVoices()), a);
151
- s = E.subscribeVoices(() => ee(E.listVoices())), H.current = () => {
152
- o || (o = !0, clearTimeout(c), s(), H.current = null, m(e, "stopped"));
163
+ }, l = setTimeout(() => c(A.listVoices()), a);
164
+ s = A.subscribeVoices(() => c(A.listVoices())), U.current = () => {
165
+ o || (o = !0, clearTimeout(l), s(), U.current = null, m(e, "stopped"));
153
166
  };
154
- }, [U, E]), tt = x((e, t, n, r, a = !1, c) => {
155
- let l = n;
156
- if (l.length === 0) {
157
- let e = E.listVoices();
158
- e.length > 0 && (l = e, M(e));
167
+ }, [W, A]), at = T((e, t, n, r, a = !1, l, u = !1) => {
168
+ let d = n;
169
+ if (d.length === 0) {
170
+ let e = A.listVoices();
171
+ e.length > 0 && (d = e, Oe(e));
159
172
  }
160
- let u = qe(r), ne = ee(te(!0, l, r, N));
173
+ let te = Ze(r), ne = c(ee(!0, d, r, ke));
161
174
  if (ne === "block") {
162
- let t = D("speech.noVoiceForReply", "This reply is in {{language}}, and no {{language}} voice is installed on this device.", { language: o(u, O) });
163
- P((n) => new Map(n).set(e, t)), m(e, "declined");
175
+ let t = j("speech.noVoiceForReply", "This reply is in {{language}}, and no {{language}} voice is installed on this device.", { language: o(te, M) });
176
+ I((n) => new Map(n).set(e, t)), m(e, "declined");
164
177
  return;
165
178
  }
179
+ if (u && (ne !== "speak" || !A.open)) return;
166
180
  if (ne === "wait-for-voices") {
167
- et(e, t, r, a, c);
181
+ it(e, t, r, a, l);
168
182
  return;
169
183
  }
170
- let d = {
171
- voice: s(l, u, q[r]),
172
- lang: u,
173
- rate: Je(r)
174
- }, f = rt.current;
175
- if (a && !f.autoSpeakEnabled && !f.sessionSpeaking && re(e)) {
176
- if (E.wouldSpeakOnAvatar?.(d) !== !0) {
184
+ let p = {
185
+ voice: s(d, te, J[r]),
186
+ lang: te,
187
+ rate: Qe(r)
188
+ }, h = ct.current;
189
+ if (a && !h.autoSpeakEnabled && !h.sessionSpeaking && re(e)) {
190
+ if (A.wouldSpeakOnAvatar?.(p) !== !0) {
177
191
  m(e, "declined");
178
192
  return;
179
193
  }
180
- d.avatarOnly = !0;
194
+ p.avatarOnly = !0;
181
195
  }
182
- P((t) => {
196
+ I((t) => {
183
197
  if (!t.has(e)) return t;
184
198
  let n = new Map(t);
185
199
  return n.delete(e), n;
186
200
  });
187
- let p = q[r], h = typeof p == "string" && i.some((e) => e.name === p) && !l.some((e) => e.name === p);
188
- F((t) => {
189
- if (t.has(e) === h) return t;
201
+ let g = J[r], _ = typeof g == "string" && i.some((e) => e.name === g) && !d.some((e) => e.name === g);
202
+ Ne((t) => {
203
+ if (t.has(e) === _) return t;
190
204
  let n = new Set(t);
191
- return h ? n.add(e) : n.delete(e), n;
192
- }), U();
193
- let g = I.current + 1;
194
- I.current = g, L.current !== e && m(L.current, "stopped"), L.current = e, m(e, "speaking"), A({
205
+ return _ ? n.add(e) : n.delete(e), n;
206
+ }), W(), Z();
207
+ let v = L.current + 1;
208
+ L.current = v, Ie.current !== e && m(Ie.current, "stopped"), Ie.current = e, m(e, "speaking"), P({
195
209
  type: "start",
196
210
  messageId: e,
197
- requestId: g
198
- }), R.current = a ? g : null, a && he(e, "ttsStarted"), b(z.current, "stopped");
199
- let _ = a ? void 0 : me(e);
200
- z.current = _;
201
- let v = c === void 0 ? ie(t) : ie(t, void 0, void 0, { firstChunkMaxChars: c });
202
- Fe({
203
- requestId: g,
204
- chunks: v,
211
+ requestId: v
212
+ }), Le.current = a ? v : null, a && me(e, "ttsStarted"), w(R.current, "stopped");
213
+ let y = a ? void 0 : fe(e);
214
+ R.current = y;
215
+ let b = l === void 0 ? ie(t) : ie(t, void 0, void 0, { firstChunkMaxChars: l });
216
+ ze({
217
+ requestId: v,
218
+ chunks: b,
205
219
  index: -1
206
- }), V.current !== null && clearTimeout(V.current), V.current = setTimeout(() => {
207
- Fe((e) => e?.requestId === g && e.index < 0 ? null : e);
208
- }, Ce);
209
- let ae = () => {
210
- b(_, "failed"), I.current === g && V.current !== null && (clearTimeout(V.current), V.current = null), m(e, "failed"), A({
220
+ }), H.current !== null && clearTimeout(H.current), H.current = setTimeout(() => {
221
+ u || ze((e) => e?.requestId === v && e.index < 0 ? null : e);
222
+ }, Se);
223
+ let x = !1, S = () => {
224
+ x || (x = !0, !(!u || L.current !== v) && (B.current = null, f.audio(e, "ended")));
225
+ }, ae = () => {
226
+ w(y, "failed"), S(), L.current === v && H.current !== null && (clearTimeout(H.current), H.current = null), m(e, "failed"), P({
211
227
  type: "failed",
212
- requestId: g
228
+ requestId: v
213
229
  });
214
- }, y = !1;
230
+ }, C = !1;
215
231
  try {
216
- E.speak(v, d, {
232
+ let n = {
217
233
  onStart: () => {
218
- I.current === g && b(_, "answered"), I.current === g && R.current === g && he(e, "firstAudio");
234
+ L.current === v && w(y, "answered"), L.current === v && Le.current === v && me(e, "firstAudio");
219
235
  },
220
- onChunkStart: (e) => {
221
- y = !0, I.current === g && V.current !== null && (clearTimeout(V.current), V.current = null), Fe((t) => t?.requestId === g ? {
222
- ...t,
223
- index: e
224
- } : I.current === g ? {
225
- requestId: g,
226
- chunks: v,
227
- index: e
228
- } : t);
236
+ onChunkStart: (t) => {
237
+ C = !0, u && L.current === v && (f.peek(e)?.final === !1 && pe(e, { spokeNarration: !0 }), f.audio(e, "started")), L.current === v && H.current !== null && (clearTimeout(H.current), H.current = null), ze((e) => e?.requestId === v ? {
238
+ ...e,
239
+ index: t
240
+ } : L.current === v ? {
241
+ requestId: v,
242
+ chunks: b,
243
+ index: t
244
+ } : e);
245
+ },
246
+ onPause: () => {
247
+ u && L.current === v && f.audio(e, "paused");
229
248
  },
230
249
  onDeviceFallback: () => {
231
- I.current === g && F((t) => t.has(e) ? t : new Set(t).add(e));
250
+ L.current === v && Ne((t) => t.has(e) ? t : new Set(t).add(e));
232
251
  },
233
252
  onEnd: () => {
234
- b(_, "stopped"), I.current === g && R.current === g && he(e, "audioEnded"), m(e, "spoken"), A({
253
+ w(y, "stopped"), S(), L.current === v && Le.current === v && me(e, "audioEnded"), m(e, "spoken"), P({
235
254
  type: "finished",
236
- requestId: g
255
+ requestId: v
237
256
  });
238
257
  },
239
258
  onError: (t) => {
240
- b(_, t === "cancelled" ? "stopped" : "failed"), !y && I.current === g && F((t) => {
259
+ w(y, t === "cancelled" ? "stopped" : "failed"), S(), !C && L.current === v && Ne((t) => {
241
260
  if (!t.has(e)) return t;
242
261
  let n = new Set(t);
243
262
  return n.delete(e), n;
244
- }), t === "output-not-cleared" && I.current === g && Ne({ messageId: e }), m(e, t === "output-not-cleared" ? "not-cleared" : t === "output-left" ? y ? "cut" : "declined" : t === "cancelled" ? "stopped" : "failed"), A({
263
+ }), t === "output-not-cleared" && L.current === v && Fe({ messageId: e }), m(e, t === "output-not-cleared" ? "not-cleared" : t === "output-left" ? C ? "cut" : "declined" : t === "cancelled" ? "stopped" : "failed"), P({
245
264
  type: "failed",
246
- requestId: g
265
+ requestId: v
247
266
  });
248
267
  }
249
- });
268
+ };
269
+ if (u && A.open) {
270
+ let i = A.open.bind(A);
271
+ f.audio(e, "queued");
272
+ let a = ue((e) => i(p, e), n, (e) => {
273
+ b = [...e], ze((e) => e?.requestId === v ? {
274
+ ...e,
275
+ chunks: b
276
+ } : e);
277
+ }, () => pe(e, { speechDivergence: !0 }));
278
+ x ? a.cancel() : (B.current = {
279
+ messageId: e,
280
+ requestId: v,
281
+ locale: r,
282
+ playback: a,
283
+ notifyEnded: S
284
+ }, a.append(t));
285
+ } else A.speak(b, p, n);
250
286
  } catch {
251
287
  ae();
252
288
  }
253
289
  }, [
254
- U,
255
- E,
256
- O,
257
- q,
258
- Je,
259
- qe,
260
- D,
261
- N,
262
- et
290
+ W,
291
+ Z,
292
+ A,
293
+ M,
294
+ J,
295
+ Qe,
296
+ Ze,
297
+ j,
298
+ ke,
299
+ it
263
300
  ]);
264
- S(() => {
265
- Ie.current = tt;
266
- }, [tt]);
267
- let Z = x((e, t, n, r) => {
268
- if (!K) return;
269
- let i = se(_(t, { labels: Se }), n ?? Y), a = _(t, { labels: oe(i, Xe) });
270
- a && tt(e, a, j, i, r?.auto === !0, r?.firstChunkMaxChars);
301
+ E(() => {
302
+ Be.current = at;
303
+ }, [at]);
304
+ let ot = T((e, t, n, r) => {
305
+ if (!q) return;
306
+ let i = S(_(t, { labels: xe }), n ?? X), a = _(t, { labels: x(i, et) });
307
+ a && at(e, a, F, i, r?.auto === !0, r?.firstChunkMaxChars, r?.phraseStream);
271
308
  }, [
272
- K,
273
- Xe,
274
- Y,
275
- tt,
276
- j
277
- ]), nt = x((e, t, n) => {
278
- if (le(k, e)) {
279
- X();
309
+ q,
310
+ et,
311
+ X,
312
+ at,
313
+ F
314
+ ]), st = T((e, t, n) => {
315
+ if (C(N, e)) {
316
+ Q();
280
317
  return;
281
318
  }
282
- Z(e, t, n);
319
+ ot(e, t, n);
283
320
  }, [
284
- k,
285
- Z,
286
- X
321
+ N,
322
+ ot,
323
+ Q
287
324
  ]);
288
- S(() => {
289
- h || X();
290
- }, [h, X]);
291
- let rt = w({
292
- autoSpeakEnabled: W,
293
- sessionSpeaking: G,
325
+ E(() => {
326
+ h || Q();
327
+ }, [h, Q]);
328
+ let ct = O({
329
+ autoSpeakEnabled: G,
330
+ sessionSpeaking: K,
294
331
  visible: h,
295
- isSupported: K
332
+ isSupported: q
296
333
  });
297
- S(() => {
298
- rt.current = {
299
- autoSpeakEnabled: W,
300
- sessionSpeaking: G,
334
+ E(() => {
335
+ ct.current = {
336
+ autoSpeakEnabled: G,
337
+ sessionSpeaking: K,
301
338
  visible: h,
302
- isSupported: K
339
+ isSupported: q
303
340
  };
304
341
  }, [
305
- W,
306
342
  G,
343
+ K,
307
344
  h,
308
- K
345
+ q
309
346
  ]);
310
- let it = w(null), at = w(null), ot = w(() => {});
311
- S(() => {
312
- X(), P(/* @__PURE__ */ new Map()), F(/* @__PURE__ */ new Set()), p(n.getState().activeConversationId), it.current = Ve;
313
- let e = at.current;
314
- at.current = null, e && e.conversationId === Ve && ot.current(e.conversationId, e.messageId);
315
- }, [Ve, X]), S(() => {
316
- P((e) => e.size === 0 ? e : /* @__PURE__ */ new Map()), X();
317
- }, [Y, X]), S(() => () => {
318
- H.current?.(), H.current = null, b(z.current, "stopped"), z.current = void 0, E.cancel();
319
- }, [E]), S(() => {
347
+ let lt = O(null), ut = O(null), dt = O(() => {});
348
+ E(() => {
349
+ Q(), V.current.clear(), I(/* @__PURE__ */ new Map()), Ne(/* @__PURE__ */ new Set()), p(n.getState().activeConversationId), lt.current = Ge;
350
+ let e = ut.current;
351
+ ut.current = null, e && e.conversationId === Ge && dt.current(e.conversationId, e.messageId);
352
+ }, [Ge, Q]), E(() => {
353
+ I((e) => e.size === 0 ? e : /* @__PURE__ */ new Map()), Q();
354
+ }, [X, Q]), E(() => () => {
355
+ U.current?.(), U.current = null, w(R.current, "stopped"), R.current = void 0, Z(), A.cancel();
356
+ }, [Z, A]), E(() => {
320
357
  if (typeof window > "u") return;
321
- let { settle: e, unregister: t } = ge(() => (b(z.current, "stopped"), z.current)), n = () => {
322
- e(), z.current = void 0, E.cancel();
358
+ let { settle: e, unregister: t } = he(() => (w(R.current, "stopped"), R.current)), n = () => {
359
+ e(), R.current = void 0, Z(), A.cancel();
323
360
  };
324
361
  return window.addEventListener("pagehide", n), () => {
325
362
  t(), window.removeEventListener("pagehide", n);
326
363
  };
327
- }, [E]), S(() => {
328
- if (typeof document > "u" || !K) return;
364
+ }, [Z, A]), E(() => {
365
+ if (typeof document > "u" || !q) return;
329
366
  let e = () => {
330
367
  if (document.visibilityState !== "visible") return;
331
- let e = E.listVoices();
332
- e.length > 0 && U(), M(e), ke(!1), P((e) => e.size === 0 ? e : /* @__PURE__ */ new Map());
368
+ let e = A.listVoices();
369
+ e.length > 0 && W(), Oe(e), Ae(!1), I((e) => e.size === 0 ? e : /* @__PURE__ */ new Map());
333
370
  };
334
371
  return document.addEventListener("visibilitychange", e), window.addEventListener("focus", e), () => {
335
372
  document.removeEventListener("visibilitychange", e), window.removeEventListener("focus", e);
336
373
  };
337
374
  }, [
338
- U,
339
- E,
340
- K
375
+ W,
376
+ A,
377
+ q
341
378
  ]);
342
- let st = w(Z);
343
- S(() => {
344
- st.current = Z;
345
- }, [Z]);
346
- let Q = x((e, t) => {
347
- if (r(e) !== t || g(e.id) || B.current?.messageId === e.id || ze.current) return;
348
- let { text: n } = pe(e.content);
379
+ let ft = O(ot);
380
+ E(() => {
381
+ ft.current = ot;
382
+ }, [ot]);
383
+ let $ = T((e, t) => {
384
+ if (r(e) !== t || g(e.id) || z.current?.messageId === e.id || Ue.current) return;
385
+ let { text: n } = le(e.content);
349
386
  if (n.trim()) try {
350
- st.current(e.id, n, e.metadata?.lang, { auto: !0 });
387
+ ft.current(e.id, n, e.metadata?.lang, { auto: !0 });
351
388
  } catch {}
352
- }, []), $ = x((e, t) => {
353
- if (e !== it.current) {
354
- n.getState().activeConversationId === e && (at.current = {
389
+ }, []), pt = T((e, t) => {
390
+ if (e !== lt.current) {
391
+ n.getState().activeConversationId === e && (ut.current = {
355
392
  conversationId: e,
356
393
  messageId: t
357
394
  });
358
395
  return;
359
396
  }
360
- let r = Ee(rt.current, t);
397
+ let r = Te(ct.current, t);
361
398
  if (!r.autoSpeakEnabled && !r.sessionSpeaking || !r.visible || !r.isSupported) return;
362
399
  let i = n.getState();
363
400
  if (i.activeConversationId !== e) return;
364
401
  let a = i.conversations.find((t) => t.id === e)?.messages.find((e) => e.id === t);
365
- !a || a.role !== "assistant" || Q(a, r.sessionSpeaking);
366
- }, [Q]);
367
- S(() => {
368
- ot.current = $;
369
- }, [$]), S(() => {
370
- if (!(!W && !G || !h || !K)) return n.subscribe((e, t) => {
402
+ !a || a.role !== "assistant" || $(a, r.sessionSpeaking);
403
+ }, [$]);
404
+ E(() => {
405
+ dt.current = pt;
406
+ }, [pt]), E(() => {
407
+ if (!(!G && !K || !h || !q)) return n.subscribe((e, t) => {
371
408
  let n = e.activeConversationId;
372
409
  if (!n || n !== t.activeConversationId) return;
373
410
  let r = e.processingByConversationId[n], i = t.processingByConversationId[n];
374
- if (r?.status !== "complete" || !fe(i?.status)) return;
411
+ if (r?.status !== "complete" || !ce(i?.status)) return;
375
412
  let a = r.messageId ?? i?.messageId ?? null;
376
413
  if (!a) return;
377
414
  let o = e.conversations.find((e) => e.id === n)?.messages.find((e) => e.id === a);
378
- !o || o.role !== "assistant" || Q(o, G);
415
+ !o || o.role !== "assistant" || $(o, K);
379
416
  });
380
417
  }, [
381
- W,
382
418
  G,
383
419
  K,
420
+ q,
384
421
  h,
385
- Q
386
- ]), S(() => {
387
- if (!(W || G || !Ue || !h || !K)) return n.subscribe((e, t) => {
388
- let n = De(e, t);
389
- !n || !re(n.id) || Q(n, !1);
422
+ $
423
+ ]), E(() => {
424
+ if (!(G || K || !qe || !h || !q)) return n.subscribe((e, t) => {
425
+ let n = Ee(e, t);
426
+ !n || !re(n.id) || $(n, !1);
390
427
  });
391
428
  }, [
392
- W,
393
429
  G,
394
- Ue,
395
430
  K,
431
+ qe,
432
+ q,
396
433
  h,
397
- Q
434
+ $
398
435
  ]);
399
- let ct = x((e) => {
436
+ let mt = T((e) => {
437
+ if (e.type === "audio") return;
438
+ if (e.type === "retract") {
439
+ B.current?.messageId === e.messageId && B.current.playback.retract();
440
+ return;
441
+ }
400
442
  if (e.type === "abort") {
401
- let t = B.current;
443
+ V.current.delete(e.messageId);
444
+ let t = z.current;
402
445
  if (!t || t.messageId !== e.messageId) return;
403
- B.current = null, (t.requestId === null ? t.waiting && H.current !== null : I.current === t.requestId) && X();
446
+ z.current = null, (t.requestId === null ? t.waiting && U.current !== null : L.current === t.requestId) && Q();
404
447
  return;
405
448
  }
406
- let { messageId: t, item: r } = e, i = Ee(rt.current, t);
407
- if (!i.autoSpeakEnabled && !i.sessionSpeaking || !i.visible || !i.isSupported || r.channel === "voice" !== i.sessionSpeaking || g(t) || ze.current || B.current?.messageId === t || n.getState().activeConversationId !== r.conversationId || it.current !== r.conversationId) return;
408
- let { text: a } = pe(r.text);
409
- if (!a.trim()) return;
410
- let o = I.current;
449
+ let { messageId: t, item: r } = e;
450
+ if (e.type === "append" && B.current?.messageId !== t) {
451
+ if (V.current.has(t)) return;
452
+ V.current.add(t);
453
+ }
454
+ let i = Te(ct.current, t);
455
+ if (!i.autoSpeakEnabled && !i.sessionSpeaking || !i.visible || !i.isSupported || r.channel === "voice" !== i.sessionSpeaking || g(t) || Ue.current || n.getState().activeConversationId !== r.conversationId || lt.current !== r.conversationId) return;
456
+ let a = B.current;
457
+ if (a?.messageId === t && a.requestId === L.current) {
458
+ let t = _(e.type === "append" ? e.phrases.join(" ") : le(r.text).text, { labels: x(a.locale, et) });
459
+ e.type === "append" ? a.playback.append(t) : a.playback.finish(t);
460
+ return;
461
+ }
462
+ if (z.current?.messageId === t || e.type === "append" && (!de() || !A.open || r.channel !== "voice")) return;
463
+ let { text: o } = le(e.type === "append" ? e.phrases.join(" ") : r.text);
464
+ if (!o.trim()) return;
465
+ let s = L.current;
411
466
  try {
412
- st.current(t, a, r.lang, {
467
+ ft.current(t, o, r.lang, {
413
468
  auto: !0,
414
- firstChunkMaxChars: 110
469
+ firstChunkMaxChars: 110,
470
+ phraseStream: e.type === "append"
415
471
  });
416
472
  } catch {}
417
- let s = I.current !== o;
418
- B.current = {
473
+ let c = L.current !== s;
474
+ e.type === "append" && !c || (V.current.delete(t), z.current = {
419
475
  messageId: t,
420
- requestId: s ? I.current : null,
421
- waiting: !s && H.current !== null
422
- };
423
- }, [X]);
424
- S(() => d.subscribe(ct), [ct]);
425
- let lt = C(() => l(j, J.tag), [j, J]), ut = C(() => s(j, J.tag, q[Y]), [
426
- j,
476
+ requestId: c ? L.current : null,
477
+ waiting: !c && U.current !== null
478
+ });
479
+ }, [
480
+ Q,
481
+ A,
482
+ et
483
+ ]);
484
+ E(() => f.subscribe(mt), [mt]);
485
+ let ht = D(() => u(F, Y.tag), [F, Y]), gt = D(() => s(F, Y.tag, J[X]), [
486
+ F,
487
+ Y,
427
488
  J,
428
- q,
429
- Y
430
- ]), dt = C(() => ({
431
- isSupported: K,
432
- availability: Ye,
433
- isBlocked: Ye === "no-voices",
434
- disabledReason: Ye === "no-voices" ? D("speech.noVoicesOnDevice", "This device has no speech voices installed. Add one in your device speech or accessibility settings.") : null,
435
- blockedFor: Qe,
436
- deviceFallbackFor: $e,
437
- voiceChoices: lt,
438
- spokenChunks: ue(k, Pe),
439
- activeVoiceName: ut?.name ?? null,
440
- preferredVoiceName: q[Y] ?? null,
441
- setVoice: (e) => Ke(Y, e),
442
- speakingMessageId: k.status === "speaking" ? k.messageId : null,
443
- outputNotCleared: Me,
444
- isSpeaking: (e) => le(k, e),
445
- toggle: nt,
446
- stop: X,
447
- autoSpeakEnabled: W,
448
- setAutoSpeak: Le,
449
- sessionSpeaking: G,
450
- setSessionSpeaking: Re,
451
- setSessionMicOpen: Be,
452
- speakFinishedReply: $,
453
- previewVoice: Ze
489
+ X
490
+ ]), _t = D(() => ({
491
+ isSupported: q,
492
+ availability: $e,
493
+ isBlocked: $e === "no-voices",
494
+ disabledReason: $e === "no-voices" ? j("speech.noVoicesOnDevice", "This device has no speech voices installed. Add one in your device speech or accessibility settings.") : null,
495
+ blockedFor: nt,
496
+ deviceFallbackFor: rt,
497
+ voiceChoices: ht,
498
+ spokenChunks: oe(N, Re),
499
+ activeVoiceName: gt?.name ?? null,
500
+ preferredVoiceName: J[X] ?? null,
501
+ setVoice: (e) => Xe(X, e),
502
+ speakingMessageId: N.status === "speaking" ? N.messageId : null,
503
+ outputNotCleared: Pe,
504
+ isSpeaking: (e) => C(N, e),
505
+ toggle: st,
506
+ stop: Q,
507
+ autoSpeakEnabled: G,
508
+ setAutoSpeak: Ve,
509
+ sessionSpeaking: K,
510
+ setSessionSpeaking: He,
511
+ setSessionMicOpen: We,
512
+ speakFinishedReply: pt,
513
+ previewVoice: tt
454
514
  }), [
455
- K,
456
- Ye,
457
- Qe,
458
- $e,
459
- lt,
460
- ut,
461
515
  q,
462
- Ke,
463
- Y,
464
- k,
465
- Me,
516
+ $e,
466
517
  nt,
518
+ rt,
519
+ ht,
520
+ gt,
521
+ J,
522
+ Xe,
467
523
  X,
468
- W,
469
- Le,
524
+ N,
525
+ Pe,
526
+ st,
527
+ Q,
470
528
  G,
471
- Be,
472
- $,
473
- Ze,
474
- D,
475
- Pe
529
+ Ve,
530
+ K,
531
+ We,
532
+ pt,
533
+ tt,
534
+ j,
535
+ Re
476
536
  ]);
477
- return /* @__PURE__ */ xe(Oe.Provider, {
478
- value: dt,
479
- children: f
537
+ return /* @__PURE__ */ be(De.Provider, {
538
+ value: _t,
539
+ children: ne
480
540
  });
481
541
  };
482
542
  //#endregion
483
- export { O as AssistantSpeechProvider, D as useAssistantSpeech };
543
+ export { M as AssistantSpeechProvider, j as useAssistantSpeech };