@burdenoff/fe-libs 2026.1007.2 → 2026.1007.4

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 (38) hide show
  1. package/dist/shared/assistant/i18nManifest.d.ts +3 -0
  2. package/dist/shared/assistant/i18nManifest.d.ts.map +1 -1
  3. package/dist/shared/assistant/i18nManifest.js +3 -0
  4. package/dist/shared/assistant/index.d.ts +2 -0
  5. package/dist/shared/assistant/index.d.ts.map +1 -1
  6. package/dist/shared/assistant/store.d.ts +10 -0
  7. package/dist/shared/assistant/store.d.ts.map +1 -1
  8. package/dist/shared/assistant/store.js +19 -8
  9. package/dist/shared/assistant/ui/AssistantChatArea.d.ts.map +1 -1
  10. package/dist/shared/assistant/ui/AssistantChatArea.js +1070 -1067
  11. package/dist/shared/assistant/ui/useVoiceSession.d.ts +14 -1
  12. package/dist/shared/assistant/ui/useVoiceSession.d.ts.map +1 -1
  13. package/dist/shared/assistant/ui/useVoiceSession.js +241 -233
  14. package/dist/shared/assistant/ui/voice/AssistantVoiceSession.d.ts +7 -0
  15. package/dist/shared/assistant/ui/voice/AssistantVoiceSession.d.ts.map +1 -1
  16. package/dist/shared/assistant/ui/voice/AssistantVoiceSession.js +137 -130
  17. package/dist/shared/assistant/ui/voice/HandsFreePrivacyNotice.d.ts +27 -0
  18. package/dist/shared/assistant/ui/voice/HandsFreePrivacyNotice.d.ts.map +1 -0
  19. package/dist/shared/assistant/ui/voice/HandsFreePrivacyNotice.js +52 -0
  20. package/dist/shared/assistant/voice/handsfree/backendStreamTransport.d.ts +29 -6
  21. package/dist/shared/assistant/voice/handsfree/backendStreamTransport.d.ts.map +1 -1
  22. package/dist/shared/assistant/voice/handsfree/backendStreamTransport.js +138 -63
  23. package/dist/shared/assistant/voice/handsfree/handsFreeController.d.ts +7 -1
  24. package/dist/shared/assistant/voice/handsfree/handsFreeController.d.ts.map +1 -1
  25. package/dist/shared/assistant/voice/handsfree/handsFreeRuntime.d.ts +18 -10
  26. package/dist/shared/assistant/voice/handsfree/handsFreeRuntime.d.ts.map +1 -1
  27. package/dist/shared/assistant/voice/handsfree/handsFreeRuntime.js +46 -57
  28. package/dist/shared/assistant/voice/handsfree/streamingConfig.d.ts +103 -0
  29. package/dist/shared/assistant/voice/handsfree/streamingConfig.d.ts.map +1 -0
  30. package/dist/shared/assistant/voice/handsfree/streamingConfig.js +71 -0
  31. package/dist/shared/assistant/voice/handsfree/sttTransport.d.ts +12 -7
  32. package/dist/shared/assistant/voice/handsfree/sttTransport.d.ts.map +1 -1
  33. package/dist/shared/assistant/voice/handsfree/sttTransport.js +1 -1
  34. package/dist/shared/assistant/voice/handsfree/useHandsFreeInterrupt.d.ts +23 -1
  35. package/dist/shared/assistant/voice/handsfree/useHandsFreeInterrupt.d.ts.map +1 -1
  36. package/dist/shared/assistant/voice/handsfree/useHandsFreeInterrupt.js +63 -50
  37. package/dist/shared-assistant.js +189 -187
  38. package/package.json +3 -3
@@ -80,6 +80,13 @@ interface Options {
80
80
  * OFF; with it off nothing of the hands-free capture exists at runtime.
81
81
  */
82
82
  handsFreeInterrupt?: boolean;
83
+ /**
84
+ * H3 backend stream: the privacy-notice version this profile accepted
85
+ * (`handsFreeStreamNoticeAccepted` in the store), or null.
86
+ */
87
+ handsFreeStreamNoticeAccepted?: string | null;
88
+ /** H3 backend stream: the person pressed Continue on the notice `version`. */
89
+ onAcceptHandsFreeStreamNotice?: (version: string) => void;
83
90
  /**
84
91
  * H3: the user's voice started while the assistant was answering. The audio
85
92
  * is already stopped and the session is back to `listening`; the owner of the
@@ -114,7 +121,7 @@ export interface VoiceSubmitMeta {
114
121
  * microphone's lifetime, and turning "auto-speak is currently on" back off again
115
122
  * when the session ends.
116
123
  */
117
- export declare function useVoiceSession({ onSubmit, latestReply, language, graceMs: graceChoice, onSupersede, handsFreeInterrupt, onBargeIn, }: Options): {
124
+ export declare function useVoiceSession({ onSubmit, latestReply, language, graceMs: graceChoice, onSupersede, handsFreeInterrupt, handsFreeStreamNoticeAccepted, onAcceptHandsFreeStreamNotice, onBargeIn, }: Options): {
118
125
  session: Readonly<VoiceSessionSnapshot>;
119
126
  /** A recoverable problem worth showing, or null when all is well. */
120
127
  notice: VoiceSessionNotice | null;
@@ -156,6 +163,12 @@ export declare function useVoiceSession({ onSubmit, latestReply, language, grace
156
163
  nothingHeard: boolean;
157
164
  transportKind: import('..').SttTransportKind | null;
158
165
  fallbackReason: import('..').FallbackReason | null;
166
+ /**
167
+ * Non-null while the backend stream's privacy notice must be answered
168
+ * before the microphone opens: Continue (`accept`) or Not now
169
+ * (`decline`).
170
+ */
171
+ privacyNotice: import('..').HandsFreePrivacyNoticeActions | null;
159
172
  };
160
173
  /** Can a session be offered at all on this device? */
161
174
  available: boolean;
@@ -1 +1 @@
1
- {"version":3,"file":"useVoiceSession.d.ts","sourceRoot":"","sources":["../../../../src/shared/assistant/ui/useVoiceSession.ts"],"names":[],"mappings":"AAgBA,OAAO,EAAe,KAAK,eAAe,EAAE,MAAM,iBAAiB,CAAC;AAIpE,OAAO,EAGL,KAAK,YAAY,EAClB,MAAM,oBAAoB,CAAC;AAE5B,OAAO,EAgBL,KAAK,oBAAoB,EAE1B,MAAM,uBAAuB,CAAC;AAsC/B;;;;;;;;GAQG;AACH,MAAM,MAAM,kBAAkB,GAC1B,SAAS,GACT,eAAe,GACf,eAAe,GACf,oBAAoB;AACtB,oFAAoF;GAClF,0BAA0B;AAC5B,qFAAqF;GACnF,qBAAqB,CAAC;AAE1B;;;;;;;;GAQG;AACH,MAAM,WAAW,iBAAiB;IAChC,iFAAiF;IACjF,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,+DAA+D;IAC/D,IAAI,CAAC,EAAE,MAAM,CAAC;IACd;;;OAGG;IACH,WAAW,CAAC,EAAE,MAAM,OAAO,CAAC;CAC7B;AAMD,UAAU,OAAO;IACf,+EAA+E;IAC/E;;;;;;;OAOG;IACH,QAAQ,EAAE,CACR,IAAI,EAAE,MAAM,EACZ,cAAc,EAAE,MAAM;IACtB;;;OAGG;IACH,MAAM,EAAE,eAAe;IACvB;;;;;OAKG;IACH,IAAI,EAAE,eAAe,KAClB,IAAI,CAAC;IACV;;;;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;IACjB;;;OAGG;IACH,OAAO,CAAC,EAAE,YAAY,GAAG,MAAM,CAAC;IAChC;;;OAGG;IACH,kBAAkB,CAAC,EAAE,OAAO,CAAC;IAC7B;;;;;OAKG;IACH,SAAS,CAAC,EAAE,MAAM,IAAI,CAAC;IACvB;;;;;OAKG;IACH,WAAW,CAAC,EAAE,MAAM,IAAI,CAAC;CAC1B;AAED,oEAAoE;AACpE,MAAM,WAAW,eAAe;IAC9B,gEAAgE;IAChE,UAAU,EAAE,OAAO,CAAC;CACrB;AAED;;;;;;;;;;;;;GAaG;AACH,wBAAgB,eAAe,CAAC,EAC9B,QAAQ,EACR,WAAW,EACX,QAAQ,EACR,OAAO,EAAE,WAAW,EACpB,WAAW,EACX,kBAAkB,EAClB,SAAS,GACV,EAAE,OAAO;;IA48BJ,qEAAqE;;IAQrE;;;;;;;OAOG;;IAEH,+DAA+D;;IAE/D;;;;;;;OAOG;;IAIH,0EAA0E;;IAE1E,6DAA6D;;IAE7D,kEAAkE;;IAElE,uEAAuE;;IAEvE;;;;OAIG;;;;;;;IAOH,sDAAsD;;;;uCA3HvC,MAAM;;;IAkIrB,qDAAqD;;IAErD,uDAAuD;;IAEvD,0EAA0E;qBAr4B1C,iBAAiB;IAu4BjD;;;OAGG;+BAr5BuC,OAAO;IAu5BjD;;;OAGG;0BAp3BE,iBAAiB;EAu5B3B"}
1
+ {"version":3,"file":"useVoiceSession.d.ts","sourceRoot":"","sources":["../../../../src/shared/assistant/ui/useVoiceSession.ts"],"names":[],"mappings":"AAgBA,OAAO,EAAe,KAAK,eAAe,EAAE,MAAM,iBAAiB,CAAC;AAIpE,OAAO,EAGL,KAAK,YAAY,EAClB,MAAM,oBAAoB,CAAC;AAE5B,OAAO,EAgBL,KAAK,oBAAoB,EAE1B,MAAM,uBAAuB,CAAC;AAsC/B;;;;;;;;GAQG;AACH,MAAM,MAAM,kBAAkB,GAC1B,SAAS,GACT,eAAe,GACf,eAAe,GACf,oBAAoB;AACtB,oFAAoF;GAClF,0BAA0B;AAC5B,qFAAqF;GACnF,qBAAqB,CAAC;AAE1B;;;;;;;;GAQG;AACH,MAAM,WAAW,iBAAiB;IAChC,iFAAiF;IACjF,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,+DAA+D;IAC/D,IAAI,CAAC,EAAE,MAAM,CAAC;IACd;;;OAGG;IACH,WAAW,CAAC,EAAE,MAAM,OAAO,CAAC;CAC7B;AAMD,UAAU,OAAO;IACf,+EAA+E;IAC/E;;;;;;;OAOG;IACH,QAAQ,EAAE,CACR,IAAI,EAAE,MAAM,EACZ,cAAc,EAAE,MAAM;IACtB;;;OAGG;IACH,MAAM,EAAE,eAAe;IACvB;;;;;OAKG;IACH,IAAI,EAAE,eAAe,KAClB,IAAI,CAAC;IACV;;;;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;IACjB;;;OAGG;IACH,OAAO,CAAC,EAAE,YAAY,GAAG,MAAM,CAAC;IAChC;;;OAGG;IACH,kBAAkB,CAAC,EAAE,OAAO,CAAC;IAC7B;;;OAGG;IACH,6BAA6B,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC9C,8EAA8E;IAC9E,6BAA6B,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,IAAI,CAAC;IAC1D;;;;;OAKG;IACH,SAAS,CAAC,EAAE,MAAM,IAAI,CAAC;IACvB;;;;;OAKG;IACH,WAAW,CAAC,EAAE,MAAM,IAAI,CAAC;CAC1B;AAED,oEAAoE;AACpE,MAAM,WAAW,eAAe;IAC9B,gEAAgE;IAChE,UAAU,EAAE,OAAO,CAAC;CACrB;AAED;;;;;;;;;;;;;GAaG;AACH,wBAAgB,eAAe,CAAC,EAC9B,QAAQ,EACR,WAAW,EACX,QAAQ,EACR,OAAO,EAAE,WAAW,EACpB,WAAW,EACX,kBAAkB,EAClB,6BAA6B,EAC7B,6BAA6B,EAC7B,SAAS,GACV,EAAE,OAAO;;IAk9BJ,qEAAqE;;IAWrE;;;;;;;OAOG;;IAEH,+DAA+D;;IAE/D;;;;;;;OAOG;;IAIH,0EAA0E;;IAE1E,6DAA6D;;IAE7D,kEAAkE;;IAElE,uEAAuE;;IAEvE;;;;OAIG;;;;;;QAMD;;;;WAIG;;;IAGL,sDAAsD;;;;uCApIvC,MAAM;;;IA2IrB,qDAAqD;;IAErD,uDAAuD;;IAEvD,0EAA0E;qBAp5B1C,iBAAiB;IAs5BjD;;;OAGG;+BAp6BuC,OAAO;IAs6BjD;;;OAGG;0BAn4BE,iBAAiB;EAu6B3B"}
@@ -3,239 +3,245 @@ import { planSubmitTimer as t, resolveVoiceGraceMs as n } from "../voice/handsFr
3
3
  import { readHandsFreeOverride as r, resolveHandsFreeEnabled as ee } from "../voice/handsfree/handsFreeSetting.js";
4
4
  import { silencePlaybackReference as te } from "../voice/handsfree/playbackReference.js";
5
5
  import { speechFeed as ne } from "../speech/speechFeed.js";
6
- import { INITIAL_SESSION as re, INTERRUPT_MAX_MS as ie, NOTHING_HEARD as ae, advanceHeardClock as oe, isCapturing as se, isSubmittable as ce, planListeningHold as le, planReplyConsumption as ue, planVoiceAnnouncement as de, shouldRecognise as fe, spokenSoFar as i, voiceSessionReducer as pe } from "../voice/voiceSession.js";
7
- import { useHandsFreeInterrupt as me } from "../voice/handsfree/useHandsFreeInterrupt.js";
8
- import { isTurnSuperseded as a } from "../voice/supersededTurns.js";
9
- import { captionChunks as he } from "../voice/speechPlayback.js";
10
- import { turnClockMs as o } from "../turnTimeline.js";
11
- import { useAssistantSpeech as ge } from "./AssistantSpeechProvider.js";
12
- import { useCallback as s, useEffect as c, useLayoutEffect as _e, useMemo as ve, useReducer as ye, useRef as l, useState as u } from "react";
6
+ import { INITIAL_SESSION as re, INTERRUPT_MAX_MS as ie, NOTHING_HEARD as ae, advanceHeardClock as oe, isCapturing as i, isSubmittable as se, planListeningHold as ce, planReplyConsumption as le, planVoiceAnnouncement as ue, shouldRecognise as de, spokenSoFar as a, voiceSessionReducer as fe } from "../voice/voiceSession.js";
7
+ import { useHandsFreeInterrupt as pe } from "../voice/handsfree/useHandsFreeInterrupt.js";
8
+ import { isTurnSuperseded as o } from "../voice/supersededTurns.js";
9
+ import { captionChunks as me } from "../voice/speechPlayback.js";
10
+ import { turnClockMs as s } from "../turnTimeline.js";
11
+ import { useAssistantSpeech as he } from "./AssistantSpeechProvider.js";
12
+ import { useCallback as c, useEffect as l, useLayoutEffect as ge, useMemo as _e, useReducer as ve, useRef as u, useState as d } from "react";
13
13
  //#region src/shared/assistant/ui/useVoiceSession.ts
14
- var be = 4e3, xe = 2500, Se = 5e3, Ce = 12e3, we = "data:audio/wav;base64,UklGRiQAAABXQVZFZm10IBAAAAABAAEARKwAAIhYAQACABAAZGF0YQAAAAA=";
15
- function d({ onSubmit: d, latestReply: f, language: p, graceMs: Te, onSupersede: Ee, handsFreeInterrupt: De, onBargeIn: Oe }) {
16
- let ke = n(Te), m = l(null), [h, g] = ye(s((e, t) => pe(e, t, m.current), []), re), _ = ge(), { setSessionSpeaking: v, setSessionMicOpen: y, speakingMessageId: b, stop: x } = _, S = l(_.toggle), C = _.toggle;
17
- _e(() => {
18
- S.current = C;
19
- }, [C]);
20
- let w = l(null), T = l({}), E = l(ae), D = l(null), O = l(!1), k = l(null), [A, j] = u(null), [M, N] = u(!1), [P, F] = u(!1), [I, L] = u(!1), R = l(h);
21
- R.current = h;
22
- let z = l([]), B = l(null), V = l(!1), H = s(() => {
23
- z.current = [], B.current = null, V.current = !1;
24
- }, []), U = s(() => {
14
+ var ye = 4e3, be = 2500, xe = 5e3, Se = 12e3, Ce = "data:audio/wav;base64,UklGRiQAAABXQVZFZm10IBAAAAABAAEARKwAAIhYAQACABAAZGF0YQAAAAA=";
15
+ function we({ onSubmit: we, latestReply: f, language: p, graceMs: Te, onSupersede: Ee, handsFreeInterrupt: De, handsFreeStreamNoticeAccepted: Oe, onAcceptHandsFreeStreamNotice: ke, onBargeIn: m }) {
16
+ let h = n(Te), g = u(null), [_, v] = ve(c((e, t) => fe(e, t, g.current), []), re), y = he(), { setSessionSpeaking: b, setSessionMicOpen: x, speakingMessageId: S, stop: C } = y, w = u(y.toggle), T = y.toggle;
17
+ ge(() => {
18
+ w.current = T;
19
+ }, [T]);
20
+ let E = u(null), D = u({}), O = u(ae), k = u(null), A = u(!1), j = u(null), [M, N] = d(null), [P, F] = d(!1), [Ae, I] = d(!1), [L, R] = d(!1), z = u(_);
21
+ z.current = _;
22
+ let B = u([]), V = u(null), H = u(!1), U = c(() => {
23
+ B.current = [], V.current = null, H.current = !1;
24
+ }, []), W = c(() => {
25
25
  for (;;) {
26
- let e = z.current.shift();
26
+ let e = B.current.shift();
27
27
  if (!e) return !1;
28
28
  if (!(e.stillWanted && !e.stillWanted())) {
29
- B.current = e, m.current = m.current ? `${m.current} ${e.text}` : e.text;
29
+ V.current = e, g.current = g.current ? `${g.current} ${e.text}` : e.text;
30
30
  try {
31
- S.current(e.id, e.text, e.lang);
31
+ w.current(e.id, e.text, e.lang);
32
32
  } catch {
33
- B.current = null;
33
+ V.current = null;
34
34
  continue;
35
35
  }
36
36
  return !0;
37
37
  }
38
38
  }
39
- }, []), W = l(!1), Ae = s((e) => {
40
- let t = le({
39
+ }, []), G = u(!1), je = c((e) => {
40
+ let t = ce({
41
41
  requested: e,
42
- held: W.current,
43
- muted: R.current.muted
42
+ held: G.current,
43
+ muted: z.current.muted
44
44
  });
45
- W.current = t.held, t.mute !== null && g({
45
+ G.current = t.held, t.mute !== null && v({
46
46
  type: "mute",
47
47
  muted: t.mute
48
48
  });
49
- }, []), G = s((e) => {
50
- let t = de(R.current);
51
- t !== "drop" && (B.current?.id === e.id || z.current.some((t) => t.id === e.id) || (z.current.push(e), t === "start" && !V.current && (V.current = !0, g({ type: "announce" }))));
52
- }, []), je = s((e) => {
53
- if (R.current.phase !== "thinking") {
54
- G(e);
49
+ }, []), K = c((e) => {
50
+ let t = ue(z.current);
51
+ t !== "drop" && (V.current?.id === e.id || B.current.some((t) => t.id === e.id) || (B.current.push(e), t === "start" && !H.current && (H.current = !0, v({ type: "announce" }))));
52
+ }, []), Me = c((e) => {
53
+ if (z.current.phase !== "thinking") {
54
+ K(e);
55
55
  return;
56
56
  }
57
- z.current.push(e), V.current = !0, g({ type: "answered-locally" });
58
- }, [G]), Me = l(f);
59
- Me.current = f, c(() => {
60
- if (h.phase === "speaking") {
61
- let e = k.current;
62
- m.current = e && D.current === e.id && f?.id !== e.id ? e.text : f?.text ?? null;
57
+ B.current.push(e), H.current = !0, v({ type: "answered-locally" });
58
+ }, [K]), Ne = u(f);
59
+ Ne.current = f, l(() => {
60
+ if (_.phase === "speaking") {
61
+ let e = j.current;
62
+ g.current = e && k.current === e.id && f?.id !== e.id ? e.text : f?.text ?? null;
63
63
  return;
64
64
  }
65
- if (m.current === null) return;
65
+ if (g.current === null) return;
66
66
  let e = setTimeout(() => {
67
- m.current = null;
68
- }, xe);
67
+ g.current = null;
68
+ }, be);
69
69
  return () => clearTimeout(e);
70
- }, [h.phase, f]);
71
- let K = l(p);
72
- K.current = p;
73
- let q = s((e, t) => {
74
- g({
70
+ }, [_.phase, f]);
71
+ let q = u(p);
72
+ q.current = p;
73
+ let J = c((e, t) => {
74
+ v({
75
75
  type: "speech",
76
76
  transcript: e,
77
77
  final: t,
78
78
  at: Date.now(),
79
- language: K.current
79
+ language: q.current
80
80
  });
81
- }, []), Ne = s((e, t, n) => {
82
- g({
81
+ }, []), Pe = c((e, t, n) => {
82
+ v({
83
83
  type: "speech",
84
84
  transcript: e,
85
85
  final: t,
86
86
  at: Date.now(),
87
- language: n ?? K.current,
87
+ language: n ?? q.current,
88
88
  gated: !0
89
89
  });
90
- }, []), J = l(0), Pe = s(() => {
91
- H(), x(), J.current = Date.now(), N(!0), g({ type: "interrupt" });
92
- }, [x, H]), Y = e({
93
- onFinalize: s((e) => q(e, !0), [q]),
90
+ }, []), Y = u(0), Fe = c(() => {
91
+ U(), C(), Y.current = Date.now(), F(!0), v({ type: "interrupt" });
92
+ }, [C, U]), X = e({
93
+ onFinalize: c((e) => J(e, !0), [J]),
94
94
  language: p
95
- }), Fe = l(Oe);
96
- Fe.current = Oe;
97
- let Ie = s(() => {
98
- H(), te(), x(), J.current = Date.now(), N(!0), g({ type: "interrupt" }), Fe.current?.();
99
- }, [x, H]), X = me({
95
+ }), Ie = u(m);
96
+ Ie.current = m;
97
+ let Le = c(() => {
98
+ U(), te(), C(), Y.current = Date.now(), F(!0), v({ type: "interrupt" }), Ie.current?.();
99
+ }, [C, U]), Z = pe({
100
100
  enabled: ee(De, r()),
101
- phase: h.phase,
102
- muted: h.muted,
101
+ phase: _.phase,
102
+ muted: _.muted,
103
103
  language: p,
104
- onBargeIn: Ie,
105
- onTranscript: Ne
106
- }), Z = Y.isListening || X.suppressWebSpeech && X.mode === "active";
107
- c(() => {
108
- Y.interim && q(Y.interim, !1);
109
- }, [Y.interim, q]), c(() => {
110
- w.current && clearTimeout(w.current), F(!1), E.current = oe(E.current, h, o());
104
+ streamNoticeAccepted: Oe ?? null,
105
+ onAcceptStreamNotice: ke,
106
+ onBargeIn: Le,
107
+ onTranscript: Pe
108
+ }), Re = Z.mode === "notice", Q = X.isListening || Z.suppressWebSpeech && Z.mode === "active";
109
+ l(() => {
110
+ X.interim && J(X.interim, !1);
111
+ }, [X.interim, J]), l(() => {
112
+ E.current && clearTimeout(E.current), I(!1), O.current = oe(O.current, _, s());
111
113
  let e = t({
112
- phase: h.phase,
113
- muted: h.muted,
114
- spoken: i(h),
115
- holding: I,
116
- graceMs: ke
114
+ phase: _.phase,
115
+ muted: _.muted,
116
+ spoken: a(_),
117
+ holding: L,
118
+ graceMs: h
117
119
  });
118
120
  if (!e.arm) return;
119
- let n = setTimeout(() => F(!0), Math.min(800, e.delayMs)), r = o();
120
- return w.current = setTimeout(() => {
121
- T.current = {
122
- speechEnded: E.current.at ?? r,
121
+ let n = setTimeout(() => I(!0), Math.min(800, e.delayMs)), r = s();
122
+ return E.current = setTimeout(() => {
123
+ D.current = {
124
+ speechEnded: O.current.at ?? r,
123
125
  graceStarted: r,
124
- graceEnded: o()
125
- }, g({
126
+ graceEnded: s()
127
+ }, v({
126
128
  type: "silence",
127
129
  at: Date.now()
128
130
  });
129
131
  }, e.delayMs), () => {
130
- clearTimeout(n), w.current && clearTimeout(w.current);
132
+ clearTimeout(n), E.current && clearTimeout(E.current);
131
133
  };
132
134
  }, [
133
- h,
134
- I,
135
- ke
136
- ]), c(() => {
137
- (h.phase !== "listening" || h.muted) && L(!1);
138
- }, [h.phase, h.muted]), c(() => {
139
- if (!M) return;
140
- let e = Date.now() - J.current, t = Z ? Math.max(0, 500 - e) : Math.max(0, ie - e), n = setTimeout(() => N(!1), t);
135
+ _,
136
+ L,
137
+ h
138
+ ]), l(() => {
139
+ (_.phase !== "listening" || _.muted) && R(!1);
140
+ }, [_.phase, _.muted]), l(() => {
141
+ if (!P) return;
142
+ let e = Date.now() - Y.current, t = Q ? Math.max(0, 500 - e) : Math.max(0, ie - e), n = setTimeout(() => F(!1), t);
141
143
  return () => clearTimeout(n);
142
- }, [M, Z]);
143
- let Le = l("");
144
- h.phase === "listening" && (Le.current = i(h)), c(() => {
145
- if (h.phase !== "thinking") return;
146
- y(!1), H();
147
- let e = Le.current.trim();
148
- e && d(e, Q.current ?? `vs-orphan-${Date.now().toString(36)}`, T.current, { correction: R.current.correcting }), T.current = {}, E.current = ae;
149
- }, [h.phase]), c(() => {
150
- let e = ue(f?.id, h.phase, D.current, a(f?.id));
151
- e.claim && (D.current = f?.id ?? null, e.advance && f && g({
144
+ }, [P, Q]);
145
+ let ze = u("");
146
+ _.phase === "listening" && (ze.current = a(_)), l(() => {
147
+ if (_.phase !== "thinking") return;
148
+ x(!1), U();
149
+ let e = ze.current.trim();
150
+ e && we(e, $.current ?? `vs-orphan-${Date.now().toString(36)}`, D.current, { correction: z.current.correcting }), D.current = {}, O.current = ae;
151
+ }, [_.phase]), l(() => {
152
+ let e = le(f?.id, _.phase, k.current, o(f?.id));
153
+ e.claim && (k.current = f?.id ?? null, e.advance && f && v({
152
154
  type: "reply",
153
155
  text: f.text
154
156
  }));
155
- }, [f, h.phase]), c(() => {
156
- if (b === null || h.phase !== "thinking" || D.current === b) return;
157
- if (a(b)) {
158
- x();
157
+ }, [f, _.phase]), l(() => {
158
+ if (S === null || _.phase !== "thinking" || k.current === S) return;
159
+ if (o(S)) {
160
+ C();
159
161
  return;
160
162
  }
161
- let e = ne.peek(b);
162
- !e || e.channel !== "voice" || e.voiceSessionId === void 0 || e.voiceSessionId !== Q.current || (D.current = b, k.current = {
163
- id: b,
163
+ let e = ne.peek(S);
164
+ !e || e.channel !== "voice" || e.voiceSessionId === void 0 || e.voiceSessionId !== $.current || (k.current = S, j.current = {
165
+ id: S,
164
166
  text: e.text
165
- }, g({
167
+ }, v({
166
168
  type: "reply-audio-started",
167
- replyId: b
169
+ replyId: S
168
170
  }));
169
171
  }, [
170
- b,
171
- h.phase,
172
- x
173
- ]), c(() => {
174
- let e = b !== null;
175
- O.current && !e && (B.current = null, (R.current.phase !== "speaking" || !U()) && g({ type: "speech-ended" })), O.current = e;
176
- }, [b, U]), c(() => {
177
- h.phase !== "listening" && j((e) => e === "nothing-heard" ? null : e);
178
- }, [h.phase]), c(() => {
179
- if (h.phase !== "speaking" || b !== null) return;
172
+ S,
173
+ _.phase,
174
+ C
175
+ ]), l(() => {
176
+ let e = S !== null;
177
+ A.current && !e && (V.current = null, (z.current.phase !== "speaking" || !W()) && v({ type: "speech-ended" })), A.current = e;
178
+ }, [S, W]), l(() => {
179
+ _.phase !== "listening" && N((e) => e === "nothing-heard" ? null : e);
180
+ }, [_.phase]), l(() => {
181
+ if (_.phase !== "speaking" || S !== null) return;
180
182
  let e = setTimeout(() => {
181
- O.current || (H(), g({ type: "speech-ended" }));
182
- }, be);
183
+ A.current || (U(), v({ type: "speech-ended" }));
184
+ }, ye);
183
185
  return () => clearTimeout(e);
184
186
  }, [
185
- h.phase,
186
- b,
187
- H
187
+ _.phase,
188
+ S,
189
+ U
188
190
  ]);
189
- let Re = l(Ee);
190
- Re.current = Ee;
191
- let ze = l(0);
192
- c(() => {
193
- let e = h.superseded;
194
- e !== ze.current && (ze.current = e, e !== 0 && (H(), x(), Re.current?.()));
191
+ let Be = u(Ee);
192
+ Be.current = Ee;
193
+ let Ve = u(0);
194
+ l(() => {
195
+ let e = _.superseded;
196
+ e !== Ve.current && (Ve.current = e, e !== 0 && (U(), C(), Be.current?.()));
195
197
  }, [
196
- h.superseded,
197
- H,
198
- x
199
- ]), c(() => {
200
- y(se(h)), fe(h) && !X.suppressWebSpeech ? Y.isActive || Y.start("auto") : Y.isActive && Y.stop();
198
+ _.superseded,
199
+ U,
200
+ C
201
+ ]), l(() => {
202
+ x(i(_)), de(_) && !Z.suppressWebSpeech ? X.isActive || X.start("auto") : X.isActive && X.stop();
201
203
  }, [
202
- h,
203
- Y,
204
- y,
205
- X.suppressWebSpeech
206
- ]), c(() => {
207
- h.phase !== "speaking" || !V.current || (V.current = !1, U() || g({ type: "speech-ended" }));
208
- }, [h.phase, U]), c(() => {
209
- Y.error === "not-allowed" || Y.error === "audio-capture" ? g({
204
+ _,
205
+ X,
206
+ x,
207
+ Z.suppressWebSpeech
208
+ ]), l(() => {
209
+ _.phase !== "speaking" || !H.current || (H.current = !1, W() || v({ type: "speech-ended" }));
210
+ }, [_.phase, W]), l(() => {
211
+ X.error === "not-allowed" || X.error === "audio-capture" ? v({
210
212
  type: "fail",
211
213
  error: "mic-denied"
212
- }) : Y.error === "language-not-supported" ? g({
214
+ }) : X.error === "language-not-supported" ? v({
213
215
  type: "fail",
214
216
  error: "no-speech-support"
215
- }) : Y.error === "network" ? j("network") : Y.error === "unknown" && j("recognition-failed");
216
- }, [Y.error]), c(() => {
217
- Y.error !== null || !Z || j((e) => e === "network" || e === "recognition-failed" ? null : e);
218
- }, [Y.error, Z]), c(() => {
219
- if (Z && j((e) => e === "not-capturing" ? null : e), !se(h) || Z) return;
220
- let e = setTimeout(() => j("not-capturing"), Se);
217
+ }) : X.error === "network" ? N("network") : X.error === "unknown" && N("recognition-failed");
218
+ }, [X.error]), l(() => {
219
+ X.error !== null || !Q || N((e) => e === "network" || e === "recognition-failed" ? null : e);
220
+ }, [X.error, Q]), l(() => {
221
+ if (Q && N((e) => e === "not-capturing" ? null : e), !i(_) || Q || Re) return;
222
+ let e = setTimeout(() => N("not-capturing"), xe);
221
223
  return () => clearTimeout(e);
222
- }, [h, Z]), c(() => {
223
- if (h.phase !== "listening" || h.muted || !Z || i(h) !== "") return;
224
- let e = setTimeout(() => j("nothing-heard"), Ce);
224
+ }, [
225
+ _,
226
+ Q,
227
+ Re
228
+ ]), l(() => {
229
+ if (_.phase !== "listening" || _.muted || !Q || a(_) !== "") return;
230
+ let e = setTimeout(() => N("nothing-heard"), Se);
225
231
  return () => clearTimeout(e);
226
- }, [h, Z]), c(() => {
227
- i(h) !== "" && j(null);
228
- }, [h]);
229
- let Q = l(null), Be = s(() => {
230
- if (N(!1), F(!1), L(!1), H(), W.current = !1, !Y.isSupported) {
231
- g({
232
+ }, [_, Q]), l(() => {
233
+ a(_) !== "" && N(null);
234
+ }, [_]);
235
+ let $ = u(null), He = c(() => {
236
+ if (F(!1), I(!1), R(!1), U(), G.current = !1, !X.isSupported) {
237
+ v({
232
238
  type: "fail",
233
239
  error: "no-speech-support"
234
240
  });
235
241
  return;
236
242
  }
237
- if (_.isBlocked) {
238
- g({
243
+ if (y.isBlocked) {
244
+ v({
239
245
  type: "fail",
240
246
  error: "no-voice-support"
241
247
  });
@@ -250,100 +256,102 @@ function d({ onSubmit: d, latestReply: f, language: p, graceMs: Te, onSupersede:
250
256
  } catch {}
251
257
  try {
252
258
  if (typeof window < "u" && typeof window.Audio == "function") {
253
- let e = new window.Audio(we);
259
+ let e = new window.Audio(Ce);
254
260
  e.volume = 0, e.play().catch(() => {});
255
261
  }
256
262
  } catch {}
257
- v(!0), j(null), D.current = Me.current?.id ?? null, k.current = null, Q.current = `vs-${Date.now().toString(36)}-${Math.random().toString(36).slice(2, 8)}`, g({ type: "start" });
263
+ b(!0), N(null), k.current = Ne.current?.id ?? null, j.current = null, $.current = `vs-${Date.now().toString(36)}-${Math.random().toString(36).slice(2, 8)}`, v({ type: "start" });
258
264
  }, [
259
- Y.isSupported,
260
- _.isBlocked,
261
- v,
262
- H
263
- ]), Ve = s(() => {
264
- N(!1), F(!1), L(!1), H(), W.current = !1, Q.current = null, g({ type: "end" }), x(), v(!1);
265
+ X.isSupported,
266
+ y.isBlocked,
267
+ b,
268
+ U
269
+ ]), Ue = c(() => {
270
+ F(!1), I(!1), R(!1), U(), G.current = !1, $.current = null, v({ type: "end" }), C(), b(!1);
265
271
  }, [
266
- x,
267
- v,
268
- H
269
- ]), He = s((e) => Q.current === e, []), Ue = s(() => {
270
- let e = R.current;
271
- e.phase !== "listening" || e.muted || L(!0);
272
- }, []), We = s(() => {
273
- L(!1);
274
- let e = R.current;
275
- if (e.phase !== "listening" || e.muted || !ce(i(e))) return;
276
- let t = o();
277
- T.current = {
278
- speechEnded: E.current.at ?? t,
272
+ C,
273
+ b,
274
+ U
275
+ ]), We = c((e) => $.current === e, []), Ge = c(() => {
276
+ let e = z.current;
277
+ e.phase !== "listening" || e.muted || R(!0);
278
+ }, []), Ke = c(() => {
279
+ R(!1);
280
+ let e = z.current;
281
+ if (e.phase !== "listening" || e.muted || !se(a(e))) return;
282
+ let t = s();
283
+ D.current = {
284
+ speechEnded: O.current.at ?? t,
279
285
  graceStarted: t,
280
286
  graceEnded: t
281
- }, g({
287
+ }, v({
282
288
  type: "silence",
283
289
  at: Date.now()
284
290
  });
285
- }, []), Ge = s(() => {
286
- g({
291
+ }, []), qe = c(() => {
292
+ v({
287
293
  type: "mute",
288
- muted: !R.current.muted
294
+ muted: !z.current.muted
289
295
  });
290
296
  }, []);
291
- c(() => () => {
292
- v(!1), y(!1);
293
- }, [v, y]);
294
- let $ = he(_.spokenChunks, h.phase, b);
295
- return ve(() => ({
296
- session: h,
297
- notice: A ?? (X.fallbackReason === null ? X.nothingHeard ? "hands-free-nothing-heard" : null : "hands-free-fallback"),
298
- spokenChunks: $,
299
- capturing: Z,
300
- active: h.phase !== "idle" && (h.phase !== "ended" || h.error !== null),
301
- interrupting: M,
302
- awaitingEndpoint: P,
303
- holding: I,
304
- correcting: h.correcting,
297
+ l(() => () => {
298
+ b(!1), x(!1);
299
+ }, [b, x]);
300
+ let Je = me(y.spokenChunks, _.phase, S);
301
+ return _e(() => ({
302
+ session: _,
303
+ notice: M ?? (Z.fallbackReason !== null && Z.fallbackReason !== "notice-declined" ? "hands-free-fallback" : Z.nothingHeard ? "hands-free-nothing-heard" : null),
304
+ spokenChunks: Je,
305
+ capturing: Q,
306
+ active: _.phase !== "idle" && (_.phase !== "ended" || _.error !== null),
307
+ interrupting: P,
308
+ awaitingEndpoint: Ae,
309
+ holding: L,
310
+ correcting: _.correcting,
305
311
  handsFree: {
306
- mode: X.mode,
307
- nothingHeard: X.nothingHeard,
308
- transportKind: X.transportKind,
309
- fallbackReason: X.fallbackReason
312
+ mode: Z.mode,
313
+ nothingHeard: Z.nothingHeard,
314
+ transportKind: Z.transportKind,
315
+ fallbackReason: Z.fallbackReason,
316
+ privacyNotice: Z.privacyNotice
310
317
  },
311
- available: Y.isSupported && !_.isBlocked,
312
- start: Be,
313
- end: Ve,
314
- isCurrentSession: He,
315
- toggleMute: Ge,
316
- interrupt: Pe,
317
- letMeFinish: Ue,
318
- imDone: We,
319
- announce: G,
320
- holdListening: Ae,
321
- answerLocally: je
318
+ available: X.isSupported && !y.isBlocked,
319
+ start: He,
320
+ end: Ue,
321
+ isCurrentSession: We,
322
+ toggleMute: qe,
323
+ interrupt: Fe,
324
+ letMeFinish: Ge,
325
+ imDone: Ke,
326
+ announce: K,
327
+ holdListening: je,
328
+ answerLocally: Me
322
329
  }), [
323
- h,
324
- A,
330
+ _,
325
331
  M,
326
332
  P,
327
- I,
328
- Z,
329
- X.mode,
330
- X.nothingHeard,
331
- X.transportKind,
332
- X.fallbackReason,
333
- Y.isSupported,
334
- _.isBlocked,
335
- $,
336
- Be,
337
- Ve,
333
+ Ae,
334
+ L,
335
+ Q,
336
+ Z.mode,
337
+ Z.nothingHeard,
338
+ Z.transportKind,
339
+ Z.fallbackReason,
340
+ Z.privacyNotice,
341
+ X.isSupported,
342
+ y.isBlocked,
343
+ Je,
338
344
  He,
339
- Ge,
340
- Pe,
341
345
  Ue,
342
346
  We,
343
- G,
344
- Ae,
345
- je
347
+ qe,
348
+ Fe,
349
+ Ge,
350
+ Ke,
351
+ K,
352
+ je,
353
+ Me
346
354
  ]);
347
355
  }
348
356
  //#endregion
349
- export { d as useVoiceSession };
357
+ export { we as useVoiceSession };