@burdenoff/fe-libs 2026.1004.4 → 2026.1004.5
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/i18nManifest.d.ts +10 -0
- package/dist/shared/assistant/i18nManifest.d.ts.map +1 -1
- package/dist/shared/assistant/i18nManifest.js +22 -12
- package/dist/shared/assistant/index.d.ts +3 -0
- package/dist/shared/assistant/index.d.ts.map +1 -1
- package/dist/shared/assistant/store.d.ts +10 -0
- package/dist/shared/assistant/store.d.ts.map +1 -1
- package/dist/shared/assistant/store.js +52 -44
- package/dist/shared/assistant/ui/AssistantChatArea.d.ts.map +1 -1
- package/dist/shared/assistant/ui/AssistantChatArea.js +761 -746
- package/dist/shared/assistant/ui/AssistantMoreMenu.d.ts.map +1 -1
- package/dist/shared/assistant/ui/AssistantMoreMenu.js +58 -56
- package/dist/shared/assistant/ui/AssistantSpeechProvider.d.ts.map +1 -1
- package/dist/shared/assistant/ui/AssistantSpeechProvider.js +106 -105
- package/dist/shared/assistant/ui/composer/AssistantVoiceGraceSelector.d.ts +20 -0
- package/dist/shared/assistant/ui/composer/AssistantVoiceGraceSelector.d.ts.map +1 -0
- package/dist/shared/assistant/ui/composer/AssistantVoiceGraceSelector.js +39 -0
- package/dist/shared/assistant/ui/useVoiceSession.d.ts +35 -2
- package/dist/shared/assistant/ui/useVoiceSession.d.ts.map +1 -1
- package/dist/shared/assistant/ui/useVoiceSession.js +232 -171
- package/dist/shared/assistant/ui/voice/AssistantVoiceSession.d.ts +15 -1
- package/dist/shared/assistant/ui/voice/AssistantVoiceSession.d.ts.map +1 -1
- package/dist/shared/assistant/ui/voice/AssistantVoiceSession.js +121 -101
- package/dist/shared/assistant/voice/handsFree.d.ts +160 -0
- package/dist/shared/assistant/voice/handsFree.d.ts.map +1 -0
- package/dist/shared/assistant/voice/handsFree.js +104 -0
- package/dist/shared/assistant/voice/supersededTurns.d.ts +29 -0
- package/dist/shared/assistant/voice/supersededTurns.d.ts.map +1 -0
- package/dist/shared/assistant/voice/supersededTurns.js +17 -0
- package/dist/shared/assistant/voice/useVoiceInput.d.ts +7 -0
- package/dist/shared/assistant/voice/useVoiceInput.d.ts.map +1 -1
- package/dist/shared/assistant/voice/useVoiceInput.js +13 -10
- package/dist/shared/assistant/voice/voiceSession.d.ts +64 -20
- package/dist/shared/assistant/voice/voiceSession.d.ts.map +1 -1
- package/dist/shared/assistant/voice/voiceSession.js +120 -67
- package/dist/shared-assistant.js +206 -203
- package/package.json +1 -1
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"AssistantVoiceGraceSelector.d.ts","sourceRoot":"","sources":["../../../../../src/shared/assistant/ui/composer/AssistantVoiceGraceSelector.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,EAAE,EAAE,MAAM,OAAO,CAAC;AAWhC;;;;;;;;;;;;;;;;GAgBG;AACH,eAAO,MAAM,2BAA2B,EAAE,EA8CzC,CAAC"}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import { isSpeechRecognitionSupported as e } from "../../voice/useVoiceInput.js";
|
|
2
|
+
import { useAssistantTr as t } from "../../i18n.js";
|
|
3
|
+
import { VOICE_GRACE_CHOICES_MS as n, resolveVoiceGraceMs as r } from "../../voice/handsFree.js";
|
|
4
|
+
import { useAssistantStore as i } from "../../store.js";
|
|
5
|
+
import { Timer as a } from "lucide-react";
|
|
6
|
+
import { jsx as o, jsxs as s } from "react/jsx-runtime";
|
|
7
|
+
//#region src/shared/assistant/ui/composer/AssistantVoiceGraceSelector.tsx
|
|
8
|
+
var c = () => {
|
|
9
|
+
let c = t(), l = i((e) => e.voiceGraceMs), u = i((e) => e.setVoiceGraceMs);
|
|
10
|
+
if (!e()) return null;
|
|
11
|
+
let d = r(l), f = (e) => e / 1e3;
|
|
12
|
+
return /* @__PURE__ */ s("label", {
|
|
13
|
+
className: "flex items-center gap-2.5 px-3 py-2 text-xs text-text-primary focus-within:ring-2 focus-within:ring-inset focus-within:ring-border-strong",
|
|
14
|
+
title: c("voice.graceHint", "How long the assistant waits in silence before it sends what you said. Start talking again and it carries on with the same message."),
|
|
15
|
+
"data-testid": "assistant-voice-grace",
|
|
16
|
+
children: [
|
|
17
|
+
/* @__PURE__ */ o(a, {
|
|
18
|
+
className: "size-3.5 flex-shrink-0 text-text-secondary",
|
|
19
|
+
"aria-hidden": "true"
|
|
20
|
+
}),
|
|
21
|
+
/* @__PURE__ */ o("span", {
|
|
22
|
+
className: "flex-1",
|
|
23
|
+
children: c("voice.graceLabel", "Wait after I stop talking")
|
|
24
|
+
}),
|
|
25
|
+
/* @__PURE__ */ o("select", {
|
|
26
|
+
value: d,
|
|
27
|
+
onChange: (e) => u(Number(e.target.value)),
|
|
28
|
+
className: "rounded-md border border-border-default bg-bg-surface px-1.5 py-1 text-xs text-text-primary focus:outline-none scheme-normal dark:scheme-dark [&_option]:bg-bg-surface [&_option]:text-text-primary",
|
|
29
|
+
"data-testid": "assistant-voice-grace-select",
|
|
30
|
+
children: n.map((e) => /* @__PURE__ */ o("option", {
|
|
31
|
+
value: e,
|
|
32
|
+
children: e === 2e3 ? c("voice.graceOptionDefault", "{{seconds}} seconds (default)", { seconds: f(e) }) : c("voice.graceOption", "{{seconds}} seconds", { seconds: f(e) })
|
|
33
|
+
}, e))
|
|
34
|
+
})
|
|
35
|
+
]
|
|
36
|
+
});
|
|
37
|
+
};
|
|
38
|
+
//#endregion
|
|
39
|
+
export { c as AssistantVoiceGraceSelector };
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { VoiceTurnTiming } from '../turnTimeline';
|
|
2
|
+
import { VoiceGraceMs } from '../voice/handsFree';
|
|
2
3
|
import { VoiceSessionSnapshot } from '../voice/voiceSession';
|
|
3
4
|
/**
|
|
4
5
|
* A problem worth TELLING the user about that does not warrant killing the
|
|
@@ -46,7 +47,14 @@ interface Options {
|
|
|
46
47
|
* When the speech that was submitted ended and when its correction grace
|
|
47
48
|
* ran out (BOFF-7801) — taken here because the turn has no id yet.
|
|
48
49
|
*/
|
|
49
|
-
timing: VoiceTurnTiming
|
|
50
|
+
timing: VoiceTurnTiming,
|
|
51
|
+
/**
|
|
52
|
+
* H2: facts about THIS turn the sender needs. `correction` is true when it
|
|
53
|
+
* is what the person said to correct a turn still being prepared: the
|
|
54
|
+
* sender must send it as the next message of the same conversation even
|
|
55
|
+
* though the superseded turn may not have let go yet.
|
|
56
|
+
*/
|
|
57
|
+
meta: VoiceSubmitMeta) => void;
|
|
50
58
|
/**
|
|
51
59
|
* Id + text of the newest assistant reply. A CHANGE of id is what advances
|
|
52
60
|
* the session out of `thinking` — the text alone is not enough, because two
|
|
@@ -58,6 +66,23 @@ interface Options {
|
|
|
58
66
|
} | null;
|
|
59
67
|
/** Language the user is speaking, so the recogniser is pointed correctly. */
|
|
60
68
|
language: string;
|
|
69
|
+
/**
|
|
70
|
+
* H1: the end-of-speech grace — 2 s (the default), 3 s or 5 s. The ONE value
|
|
71
|
+
* the submit timer waits (`planSubmitTimer`); anything else is the default.
|
|
72
|
+
*/
|
|
73
|
+
graceMs?: VoiceGraceMs | number;
|
|
74
|
+
/**
|
|
75
|
+
* H2: a correction was heard while a turn was still being prepared. Cancel
|
|
76
|
+
* that turn — abort it on the sandbox, record it as superseded
|
|
77
|
+
* (`markTurnSuperseded`), withdraw the proposals it made outdated. Called
|
|
78
|
+
* once per supersession, from an effect (never during a reduction).
|
|
79
|
+
*/
|
|
80
|
+
onSupersede?: () => void;
|
|
81
|
+
}
|
|
82
|
+
/** What `onSubmit` is told about the turn beyond its words (H2). */
|
|
83
|
+
export interface VoiceSubmitMeta {
|
|
84
|
+
/** The words are a correction of a turn that was superseded. */
|
|
85
|
+
correction: boolean;
|
|
61
86
|
}
|
|
62
87
|
/**
|
|
63
88
|
* Drives a live voice conversation (BOFF-7120).
|
|
@@ -73,7 +98,7 @@ interface Options {
|
|
|
73
98
|
* microphone's lifetime, and turning "auto-speak is currently on" back off again
|
|
74
99
|
* when the session ends.
|
|
75
100
|
*/
|
|
76
|
-
export declare function useVoiceSession({ onSubmit, latestReply, language }: Options): {
|
|
101
|
+
export declare function useVoiceSession({ onSubmit, latestReply, language, graceMs: graceChoice, onSupersede, }: Options): {
|
|
77
102
|
session: Readonly<VoiceSessionSnapshot>;
|
|
78
103
|
/** A recoverable problem worth showing, or null when all is well. */
|
|
79
104
|
notice: VoiceSessionNotice | null;
|
|
@@ -101,6 +126,10 @@ export declare function useVoiceSession({ onSubmit, latestReply, language }: Opt
|
|
|
101
126
|
interrupting: boolean;
|
|
102
127
|
/** Quiet has fallen and the correction window is running. */
|
|
103
128
|
awaitingEndpoint: boolean;
|
|
129
|
+
/** H1: "Let me finish" is on — nothing is sent until `imDone`. */
|
|
130
|
+
holding: boolean;
|
|
131
|
+
/** H2: what is being collected corrects a turn that was superseded. */
|
|
132
|
+
correcting: boolean;
|
|
104
133
|
/** Can a session be offered at all on this device? */
|
|
105
134
|
available: boolean;
|
|
106
135
|
start: () => void;
|
|
@@ -108,6 +137,10 @@ export declare function useVoiceSession({ onSubmit, latestReply, language }: Opt
|
|
|
108
137
|
isCurrentSession: (voiceSessionId: string) => boolean;
|
|
109
138
|
toggleMute: () => void;
|
|
110
139
|
interrupt: () => void;
|
|
140
|
+
/** H1: hold auto-submit until the person is done. */
|
|
141
|
+
letMeFinish: () => void;
|
|
142
|
+
/** H1: the person is done — send what was said now. */
|
|
143
|
+
imDone: () => void;
|
|
111
144
|
/** Say a line of the panel's own (BOFF-7803 FE9, `VoiceAnnouncement`). */
|
|
112
145
|
announce: (item: VoiceAnnouncement) => void;
|
|
113
146
|
/**
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useVoiceSession.d.ts","sourceRoot":"","sources":["../../../../src/shared/assistant/ui/useVoiceSession.ts"],"names":[],"mappings":"AAUA,OAAO,EAAe,KAAK,eAAe,EAAE,MAAM,iBAAiB,CAAC;AAIpE,OAAO,EAgBL,KAAK,oBAAoB,EAE1B,MAAM,uBAAuB,CAAC;AAsC/B;;;;;;;;GAQG;AACH,MAAM,MAAM,kBAAkB,GAC5B,SAAS,GAAG,eAAe,GAAG,eAAe,GAAG,oBAAoB,CAAC;AAEvE;;;;;;;;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,
|
|
1
|
+
{"version":3,"file":"useVoiceSession.d.ts","sourceRoot":"","sources":["../../../../src/shared/assistant/ui/useVoiceSession.ts"],"names":[],"mappings":"AAUA,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,GAC5B,SAAS,GAAG,eAAe,GAAG,eAAe,GAAG,oBAAoB,CAAC;AAEvE;;;;;;;;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;;;;;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,GACZ,EAAE,OAAO;;IAq4BJ,qEAAqE;;IAErE;;;;;;;OAOG;;IAEH,+DAA+D;;IAE/D;;;;;;;OAOG;;IAIH,0EAA0E;;IAE1E,6DAA6D;;IAE7D,kEAAkE;;IAElE,uEAAuE;;IAEvE,sDAAsD;;;;uCA1GvC,MAAM;;;IAiHrB,qDAAqD;;IAErD,uDAAuD;;IAEvD,0EAA0E;qBA7yB1C,iBAAiB;IA+yBjD;;;OAGG;+BA7zBuC,OAAO;IA+zBjD;;;OAGG;0BA5xBE,iBAAiB;EA2zB3B"}
|
|
@@ -1,176 +1,214 @@
|
|
|
1
1
|
import { useVoiceInput as e } from "../voice/useVoiceInput.js";
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
6
|
-
import {
|
|
7
|
-
import {
|
|
2
|
+
import { planSubmitTimer as t, resolveVoiceGraceMs as n } from "../voice/handsFree.js";
|
|
3
|
+
import { speechFeed as r } from "../speech/speechFeed.js";
|
|
4
|
+
import { INITIAL_SESSION as ee, INTERRUPT_MAX_MS as te, NOTHING_HEARD as i, advanceHeardClock as ne, isCapturing as a, isSubmittable as re, planListeningHold as ie, planReplyConsumption as ae, planVoiceAnnouncement as oe, shouldRecognise as se, spokenSoFar as o, voiceSessionReducer as ce } from "../voice/voiceSession.js";
|
|
5
|
+
import { isTurnSuperseded as s } from "../voice/supersededTurns.js";
|
|
6
|
+
import { captionChunks as le } from "../voice/speechPlayback.js";
|
|
7
|
+
import { turnClockMs as c } from "../turnTimeline.js";
|
|
8
|
+
import { useAssistantSpeech as ue } from "./AssistantSpeechProvider.js";
|
|
9
|
+
import { useCallback as l, useEffect as u, useLayoutEffect as de, useMemo as fe, useReducer as pe, useRef as d, useState as f } from "react";
|
|
8
10
|
//#region src/shared/assistant/ui/useVoiceSession.ts
|
|
9
|
-
var
|
|
10
|
-
function
|
|
11
|
-
let
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
}, [
|
|
15
|
-
let
|
|
16
|
-
|
|
17
|
-
let
|
|
18
|
-
|
|
19
|
-
}, []),
|
|
11
|
+
var me = 4e3, he = 2500, ge = 5e3, _e = 12e3, ve = "data:audio/wav;base64,UklGRiQAAABXQVZFZm10IBAAAAABAAEARKwAAIhYAQACABAAZGF0YQAAAAA=";
|
|
12
|
+
function ye({ onSubmit: ye, latestReply: p, language: be, graceMs: xe, onSupersede: m }) {
|
|
13
|
+
let h = n(xe), g = d(null), [_, v] = pe(l((e, t) => ce(e, t, g.current), []), ee), y = ue(), { setSessionSpeaking: b, setSessionMicOpen: x, speakingMessageId: S, stop: C } = y, w = d(y.toggle), T = y.toggle;
|
|
14
|
+
de(() => {
|
|
15
|
+
w.current = T;
|
|
16
|
+
}, [T]);
|
|
17
|
+
let E = d(null), D = d({}), O = d(i), k = d(null), A = d(!1), j = d(null), [M, N] = f(null), [P, F] = f(!1), [I, L] = f(!1), [R, z] = f(!1), B = d(_);
|
|
18
|
+
B.current = _;
|
|
19
|
+
let V = d([]), H = d(null), U = d(!1), W = l(() => {
|
|
20
|
+
V.current = [], H.current = null, U.current = !1;
|
|
21
|
+
}, []), G = l(() => {
|
|
20
22
|
for (;;) {
|
|
21
|
-
let e =
|
|
23
|
+
let e = V.current.shift();
|
|
22
24
|
if (!e) return !1;
|
|
23
25
|
if (!(e.stillWanted && !e.stillWanted())) {
|
|
24
|
-
|
|
26
|
+
H.current = e, g.current = g.current ? `${g.current} ${e.text}` : e.text;
|
|
25
27
|
try {
|
|
26
|
-
|
|
28
|
+
w.current(e.id, e.text, e.lang);
|
|
27
29
|
} catch {
|
|
28
|
-
|
|
30
|
+
H.current = null;
|
|
29
31
|
continue;
|
|
30
32
|
}
|
|
31
33
|
return !0;
|
|
32
34
|
}
|
|
33
35
|
}
|
|
34
|
-
}, []),
|
|
36
|
+
}, []), K = d(!1), q = l((e) => {
|
|
35
37
|
let t = ie({
|
|
36
38
|
requested: e,
|
|
37
|
-
held:
|
|
38
|
-
muted:
|
|
39
|
+
held: K.current,
|
|
40
|
+
muted: B.current.muted
|
|
39
41
|
});
|
|
40
|
-
|
|
42
|
+
K.current = t.held, t.mute !== null && v({
|
|
41
43
|
type: "mute",
|
|
42
44
|
muted: t.mute
|
|
43
45
|
});
|
|
44
|
-
}, []),
|
|
45
|
-
let t = oe(
|
|
46
|
-
t !== "drop" && (
|
|
47
|
-
}, []),
|
|
48
|
-
if (
|
|
49
|
-
|
|
46
|
+
}, []), J = l((e) => {
|
|
47
|
+
let t = oe(B.current);
|
|
48
|
+
t !== "drop" && (H.current?.id === e.id || V.current.some((t) => t.id === e.id) || (V.current.push(e), t === "start" && !U.current && (U.current = !0, v({ type: "announce" }))));
|
|
49
|
+
}, []), Se = l((e) => {
|
|
50
|
+
if (B.current.phase !== "thinking") {
|
|
51
|
+
J(e);
|
|
50
52
|
return;
|
|
51
53
|
}
|
|
52
|
-
|
|
53
|
-
}, [
|
|
54
|
-
|
|
55
|
-
if (
|
|
56
|
-
let e =
|
|
57
|
-
|
|
54
|
+
V.current.push(e), U.current = !0, v({ type: "answered-locally" });
|
|
55
|
+
}, [J]), Ce = d(p);
|
|
56
|
+
Ce.current = p, u(() => {
|
|
57
|
+
if (_.phase === "speaking") {
|
|
58
|
+
let e = j.current;
|
|
59
|
+
g.current = e && k.current === e.id && p?.id !== e.id ? e.text : p?.text ?? null;
|
|
58
60
|
return;
|
|
59
61
|
}
|
|
60
|
-
if (
|
|
62
|
+
if (g.current === null) return;
|
|
61
63
|
let e = setTimeout(() => {
|
|
62
|
-
|
|
63
|
-
},
|
|
64
|
+
g.current = null;
|
|
65
|
+
}, he);
|
|
64
66
|
return () => clearTimeout(e);
|
|
65
|
-
}, [
|
|
66
|
-
let
|
|
67
|
-
|
|
67
|
+
}, [_.phase, p]);
|
|
68
|
+
let Y = l((e, t) => {
|
|
69
|
+
v({
|
|
68
70
|
type: "speech",
|
|
69
71
|
transcript: e,
|
|
70
|
-
final: t
|
|
72
|
+
final: t,
|
|
73
|
+
at: Date.now()
|
|
71
74
|
});
|
|
72
|
-
}, []),
|
|
73
|
-
|
|
74
|
-
}, [
|
|
75
|
-
onFinalize:
|
|
76
|
-
language:
|
|
75
|
+
}, []), we = d(0), Te = l(() => {
|
|
76
|
+
W(), C(), we.current = Date.now(), F(!0), v({ type: "interrupt" });
|
|
77
|
+
}, [C, W]), X = e({
|
|
78
|
+
onFinalize: l((e) => Y(e, !0), [Y]),
|
|
79
|
+
language: be
|
|
77
80
|
});
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
}, [
|
|
81
|
-
|
|
82
|
-
let e =
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
81
|
+
u(() => {
|
|
82
|
+
X.interim && Y(X.interim, !1);
|
|
83
|
+
}, [X.interim, Y]), u(() => {
|
|
84
|
+
E.current && clearTimeout(E.current), L(!1), O.current = ne(O.current, _, c());
|
|
85
|
+
let e = t({
|
|
86
|
+
phase: _.phase,
|
|
87
|
+
muted: _.muted,
|
|
88
|
+
spoken: o(_),
|
|
89
|
+
holding: R,
|
|
90
|
+
graceMs: h
|
|
91
|
+
});
|
|
92
|
+
if (!e.arm) return;
|
|
93
|
+
let n = setTimeout(() => L(!0), Math.min(800, e.delayMs)), r = c();
|
|
94
|
+
return E.current = setTimeout(() => {
|
|
95
|
+
D.current = {
|
|
96
|
+
speechEnded: O.current.at ?? r,
|
|
97
|
+
graceStarted: r,
|
|
98
|
+
graceEnded: c()
|
|
99
|
+
}, v({
|
|
100
|
+
type: "silence",
|
|
101
|
+
at: Date.now()
|
|
102
|
+
});
|
|
103
|
+
}, e.delayMs), () => {
|
|
104
|
+
clearTimeout(n), E.current && clearTimeout(E.current);
|
|
91
105
|
};
|
|
92
|
-
}, [
|
|
93
|
-
|
|
94
|
-
|
|
106
|
+
}, [
|
|
107
|
+
_,
|
|
108
|
+
R,
|
|
109
|
+
h
|
|
110
|
+
]), u(() => {
|
|
111
|
+
(_.phase !== "listening" || _.muted) && z(!1);
|
|
112
|
+
}, [_.phase, _.muted]), u(() => {
|
|
113
|
+
if (!P) return;
|
|
114
|
+
let e = Date.now() - we.current, t = X.isListening ? Math.max(0, 500 - e) : Math.max(0, te - e), n = setTimeout(() => F(!1), t);
|
|
95
115
|
return () => clearTimeout(n);
|
|
96
|
-
}, [
|
|
97
|
-
let
|
|
98
|
-
|
|
99
|
-
if (
|
|
100
|
-
|
|
101
|
-
let e =
|
|
102
|
-
e &&
|
|
103
|
-
}, [
|
|
104
|
-
let e = ae(
|
|
105
|
-
e.claim && (
|
|
116
|
+
}, [P, X.isListening]);
|
|
117
|
+
let Ee = d("");
|
|
118
|
+
_.phase === "listening" && (Ee.current = o(_)), u(() => {
|
|
119
|
+
if (_.phase !== "thinking") return;
|
|
120
|
+
x(!1), W();
|
|
121
|
+
let e = Ee.current.trim();
|
|
122
|
+
e && ye(e, Z.current ?? `vs-orphan-${Date.now().toString(36)}`, D.current, { correction: B.current.correcting }), D.current = {}, O.current = i;
|
|
123
|
+
}, [_.phase]), u(() => {
|
|
124
|
+
let e = ae(p?.id, _.phase, k.current, s(p?.id));
|
|
125
|
+
e.claim && (k.current = p?.id ?? null, e.advance && p && v({
|
|
106
126
|
type: "reply",
|
|
107
|
-
text:
|
|
127
|
+
text: p.text
|
|
108
128
|
}));
|
|
109
|
-
}, [
|
|
110
|
-
if (
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
129
|
+
}, [p, _.phase]), u(() => {
|
|
130
|
+
if (S === null || _.phase !== "thinking" || k.current === S) return;
|
|
131
|
+
if (s(S)) {
|
|
132
|
+
C();
|
|
133
|
+
return;
|
|
134
|
+
}
|
|
135
|
+
let e = r.peek(S);
|
|
136
|
+
!e || e.channel !== "voice" || e.voiceSessionId === void 0 || e.voiceSessionId !== Z.current || (k.current = S, j.current = {
|
|
137
|
+
id: S,
|
|
114
138
|
text: e.text
|
|
115
|
-
},
|
|
139
|
+
}, v({
|
|
116
140
|
type: "reply-audio-started",
|
|
117
|
-
replyId:
|
|
141
|
+
replyId: S
|
|
118
142
|
}));
|
|
119
|
-
}, [
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
143
|
+
}, [
|
|
144
|
+
S,
|
|
145
|
+
_.phase,
|
|
146
|
+
C
|
|
147
|
+
]), u(() => {
|
|
148
|
+
let e = S !== null;
|
|
149
|
+
A.current && !e && (H.current = null, (B.current.phase !== "speaking" || !G()) && v({ type: "speech-ended" })), A.current = e;
|
|
150
|
+
}, [S, G]), u(() => {
|
|
151
|
+
_.phase !== "listening" && N((e) => e === "nothing-heard" ? null : e);
|
|
152
|
+
}, [_.phase]), u(() => {
|
|
153
|
+
if (_.phase !== "speaking" || S !== null) return;
|
|
126
154
|
let e = setTimeout(() => {
|
|
127
|
-
|
|
128
|
-
},
|
|
155
|
+
A.current || (W(), v({ type: "speech-ended" }));
|
|
156
|
+
}, me);
|
|
129
157
|
return () => clearTimeout(e);
|
|
130
158
|
}, [
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
])
|
|
135
|
-
|
|
136
|
-
|
|
159
|
+
_.phase,
|
|
160
|
+
S,
|
|
161
|
+
W
|
|
162
|
+
]);
|
|
163
|
+
let De = d(m);
|
|
164
|
+
De.current = m;
|
|
165
|
+
let Oe = d(0);
|
|
166
|
+
u(() => {
|
|
167
|
+
let e = _.superseded;
|
|
168
|
+
e !== Oe.current && (Oe.current = e, e !== 0 && (W(), C(), De.current?.()));
|
|
169
|
+
}, [
|
|
170
|
+
_.superseded,
|
|
171
|
+
W,
|
|
172
|
+
C
|
|
173
|
+
]), u(() => {
|
|
174
|
+
x(a(_)), se(_) ? X.isActive || X.start("auto") : X.isActive && X.stop();
|
|
137
175
|
}, [
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
]),
|
|
142
|
-
|
|
143
|
-
}, [
|
|
144
|
-
|
|
176
|
+
_,
|
|
177
|
+
X,
|
|
178
|
+
x
|
|
179
|
+
]), u(() => {
|
|
180
|
+
_.phase !== "speaking" || !U.current || (U.current = !1, G() || v({ type: "speech-ended" }));
|
|
181
|
+
}, [_.phase, G]), u(() => {
|
|
182
|
+
X.error === "not-allowed" || X.error === "audio-capture" ? v({
|
|
145
183
|
type: "fail",
|
|
146
184
|
error: "mic-denied"
|
|
147
|
-
}) :
|
|
185
|
+
}) : X.error === "language-not-supported" ? v({
|
|
148
186
|
type: "fail",
|
|
149
187
|
error: "no-speech-support"
|
|
150
|
-
}) :
|
|
151
|
-
}, [
|
|
152
|
-
|
|
153
|
-
}, [
|
|
154
|
-
if (
|
|
155
|
-
let e = setTimeout(() =>
|
|
188
|
+
}) : X.error === "network" ? N("network") : X.error === "unknown" && N("recognition-failed");
|
|
189
|
+
}, [X.error]), u(() => {
|
|
190
|
+
X.error !== null || !X.isListening || N((e) => e === "network" || e === "recognition-failed" ? null : e);
|
|
191
|
+
}, [X.error, X.isListening]), u(() => {
|
|
192
|
+
if (X.isListening && N((e) => e === "not-capturing" ? null : e), !a(_) || X.isListening) return;
|
|
193
|
+
let e = setTimeout(() => N("not-capturing"), ge);
|
|
156
194
|
return () => clearTimeout(e);
|
|
157
|
-
}, [
|
|
158
|
-
if (
|
|
159
|
-
let e = setTimeout(() =>
|
|
195
|
+
}, [_, X.isListening]), u(() => {
|
|
196
|
+
if (_.phase !== "listening" || _.muted || !X.isListening || o(_) !== "") return;
|
|
197
|
+
let e = setTimeout(() => N("nothing-heard"), _e);
|
|
160
198
|
return () => clearTimeout(e);
|
|
161
|
-
}, [
|
|
162
|
-
|
|
163
|
-
}, [
|
|
164
|
-
let Z =
|
|
165
|
-
if (
|
|
166
|
-
|
|
199
|
+
}, [_, X.isListening]), u(() => {
|
|
200
|
+
o(_) !== "" && N(null);
|
|
201
|
+
}, [_]);
|
|
202
|
+
let Z = d(null), Q = l(() => {
|
|
203
|
+
if (F(!1), L(!1), z(!1), W(), K.current = !1, !X.isSupported) {
|
|
204
|
+
v({
|
|
167
205
|
type: "fail",
|
|
168
206
|
error: "no-speech-support"
|
|
169
207
|
});
|
|
170
208
|
return;
|
|
171
209
|
}
|
|
172
|
-
if (
|
|
173
|
-
|
|
210
|
+
if (y.isBlocked) {
|
|
211
|
+
v({
|
|
174
212
|
type: "fail",
|
|
175
213
|
error: "no-voice-support"
|
|
176
214
|
});
|
|
@@ -185,67 +223,90 @@ function d({ onSubmit: d, latestReply: f, language: ve }) {
|
|
|
185
223
|
} catch {}
|
|
186
224
|
try {
|
|
187
225
|
if (typeof window < "u" && typeof window.Audio == "function") {
|
|
188
|
-
let e = new window.Audio(
|
|
226
|
+
let e = new window.Audio(ve);
|
|
189
227
|
e.volume = 0, e.play().catch(() => {});
|
|
190
228
|
}
|
|
191
229
|
} catch {}
|
|
192
|
-
|
|
230
|
+
b(!0), N(null), k.current = Ce.current?.id ?? null, j.current = null, Z.current = `vs-${Date.now().toString(36)}-${Math.random().toString(36).slice(2, 8)}`, v({ type: "start" });
|
|
193
231
|
}, [
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
]),
|
|
199
|
-
|
|
232
|
+
X.isSupported,
|
|
233
|
+
y.isBlocked,
|
|
234
|
+
b,
|
|
235
|
+
W
|
|
236
|
+
]), ke = l(() => {
|
|
237
|
+
F(!1), L(!1), z(!1), W(), K.current = !1, Z.current = null, v({ type: "end" }), C(), b(!1);
|
|
200
238
|
}, [
|
|
239
|
+
C,
|
|
201
240
|
b,
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
241
|
+
W
|
|
242
|
+
]), Ae = l((e) => Z.current === e, []), je = l(() => {
|
|
243
|
+
let e = B.current;
|
|
244
|
+
e.phase !== "listening" || e.muted || z(!0);
|
|
245
|
+
}, []), Me = l(() => {
|
|
246
|
+
z(!1);
|
|
247
|
+
let e = B.current;
|
|
248
|
+
if (e.phase !== "listening" || e.muted || !re(o(e))) return;
|
|
249
|
+
let t = c();
|
|
250
|
+
D.current = {
|
|
251
|
+
speechEnded: O.current.at ?? t,
|
|
252
|
+
graceStarted: t,
|
|
253
|
+
graceEnded: t
|
|
254
|
+
}, v({
|
|
255
|
+
type: "silence",
|
|
256
|
+
at: Date.now()
|
|
257
|
+
});
|
|
258
|
+
}, []), Ne = l(() => {
|
|
259
|
+
v({
|
|
206
260
|
type: "mute",
|
|
207
|
-
muted: !
|
|
261
|
+
muted: !B.current.muted
|
|
208
262
|
});
|
|
209
263
|
}, []);
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
}, [
|
|
213
|
-
let
|
|
214
|
-
return
|
|
215
|
-
session:
|
|
216
|
-
notice:
|
|
217
|
-
spokenChunks:
|
|
218
|
-
capturing:
|
|
219
|
-
active:
|
|
220
|
-
interrupting:
|
|
221
|
-
awaitingEndpoint:
|
|
222
|
-
|
|
264
|
+
u(() => () => {
|
|
265
|
+
b(!1), x(!1);
|
|
266
|
+
}, [b, x]);
|
|
267
|
+
let $ = le(y.spokenChunks, _.phase, S);
|
|
268
|
+
return fe(() => ({
|
|
269
|
+
session: _,
|
|
270
|
+
notice: M,
|
|
271
|
+
spokenChunks: $,
|
|
272
|
+
capturing: X.isListening,
|
|
273
|
+
active: _.phase !== "idle" && (_.phase !== "ended" || _.error !== null),
|
|
274
|
+
interrupting: P,
|
|
275
|
+
awaitingEndpoint: I,
|
|
276
|
+
holding: R,
|
|
277
|
+
correcting: _.correcting,
|
|
278
|
+
available: X.isSupported && !y.isBlocked,
|
|
223
279
|
start: Q,
|
|
224
|
-
end:
|
|
225
|
-
isCurrentSession:
|
|
226
|
-
toggleMute:
|
|
227
|
-
interrupt:
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
280
|
+
end: ke,
|
|
281
|
+
isCurrentSession: Ae,
|
|
282
|
+
toggleMute: Ne,
|
|
283
|
+
interrupt: Te,
|
|
284
|
+
letMeFinish: je,
|
|
285
|
+
imDone: Me,
|
|
286
|
+
announce: J,
|
|
287
|
+
holdListening: q,
|
|
288
|
+
answerLocally: Se
|
|
231
289
|
}), [
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
Q,
|
|
290
|
+
_,
|
|
291
|
+
M,
|
|
292
|
+
P,
|
|
293
|
+
I,
|
|
294
|
+
R,
|
|
295
|
+
X.isListening,
|
|
296
|
+
X.isSupported,
|
|
297
|
+
y.isBlocked,
|
|
241
298
|
$,
|
|
242
|
-
|
|
243
|
-
|
|
299
|
+
Q,
|
|
300
|
+
ke,
|
|
301
|
+
Ae,
|
|
302
|
+
Ne,
|
|
303
|
+
Te,
|
|
304
|
+
je,
|
|
305
|
+
Me,
|
|
244
306
|
J,
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
W
|
|
307
|
+
q,
|
|
308
|
+
Se
|
|
248
309
|
]);
|
|
249
310
|
}
|
|
250
311
|
//#endregion
|
|
251
|
-
export {
|
|
312
|
+
export { ye as useVoiceSession };
|
|
@@ -44,8 +44,22 @@ interface Props {
|
|
|
44
44
|
capturing?: boolean;
|
|
45
45
|
/** The user has cut the assistant off and capture has not resumed yet. */
|
|
46
46
|
interrupting?: boolean;
|
|
47
|
-
/** Quiet has fallen and the
|
|
47
|
+
/** Quiet has fallen and the correction window is running. */
|
|
48
48
|
awaitingEndpoint?: boolean;
|
|
49
|
+
/**
|
|
50
|
+
* ★ H1: "Let me finish" is on — nothing is sent until the person says they
|
|
51
|
+
* are done. The control swaps to "I'm done" while it is.
|
|
52
|
+
*/
|
|
53
|
+
holding?: boolean;
|
|
54
|
+
/**
|
|
55
|
+
* ★ H2: what is being heard corrects an answer that was still being
|
|
56
|
+
* prepared (it was cancelled when the person began to speak).
|
|
57
|
+
*/
|
|
58
|
+
correcting?: boolean;
|
|
59
|
+
/** Hold auto-send (H1). With `onImDone`, shows the control. */
|
|
60
|
+
onLetMeFinish?: () => void;
|
|
61
|
+
/** End the hold and send what was said now (H1). */
|
|
62
|
+
onImDone?: () => void;
|
|
49
63
|
/**
|
|
50
64
|
* ★ BOFF-7803 FE9: a change of this conversation waiting for its on-screen
|
|
51
65
|
* button. The thread's card is covered (and inert) while the session runs,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"AssistantVoiceSession.d.ts","sourceRoot":"","sources":["../../../../../src/shared/assistant/ui/voice/AssistantVoiceSession.tsx"],"names":[],"mappings":"AAAA,OAAO,EAKL,KAAK,EAAE,EACP,KAAK,SAAS,EACf,MAAM,OAAO,CAAC;AAIf,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,mBAAmB,CAAC;AAyB7D,OAAO,EAEL,KAAK,oBAAoB,EAC1B,MAAM,0BAA0B,CAAC;AAElC,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,oBAAoB,CAAC;AAC7D,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,4BAA4B,CAAC;AAEtE,gFAAgF;AAChF,MAAM,MAAM,SAAS,GAAG,MAAM,GAAG,OAAO,GAAG,MAAM,CAAC;AAElD,UAAU,KAAK;IACb,OAAO,EAAE,oBAAoB,CAAC;IAC9B,iEAAiE;IACjE,KAAK,CAAC,EAAE,aAAa,CAAC,mBAAmB,CAAC,CAAC;IAC3C,wCAAwC;IACxC,gBAAgB,CAAC,EAAE,MAAM,IAAI,CAAC;IAC9B,6EAA6E;IAC7E,gBAAgB,CAAC,EAAE,MAAM,IAAI,CAAC;IAC9B,uCAAuC;IACvC,WAAW,CAAC,EAAE,MAAM,IAAI,CAAC;IACzB,6EAA6E;IAC7E,MAAM,CAAC,EAAE,kBAAkB,GAAG,IAAI,CAAC;IACnC,gEAAgE;IAChE,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;IACtB,YAAY,EAAE,MAAM,IAAI,CAAC;IACzB;;;;;;OAMG;IACH,WAAW,CAAC,EAAE,mBAAmB,EAAE,CAAC;IACpC,aAAa,CAAC,EAAE,CAAC,KAAK,EAAE,QAAQ,GAAG,IAAI,KAAK,IAAI,CAAC;IACjD,kBAAkB,CAAC,EAAE,CAAC,EAAE,EAAE,MAAM,KAAK,IAAI,CAAC;IAC1C,iBAAiB,CAAC,EAAE,CAAC,EAAE,EAAE,MAAM,KAAK,IAAI,CAAC;IACzC,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB,0EAA0E;IAC1E,oBAAoB,CAAC,EAAE,MAAM,CAAC;IAC9B,4DAA4D;IAC5D,YAAY,CAAC,EAAE;QAAE,MAAM,EAAE,MAAM,EAAE,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,GAAG,IAAI,CAAC;IAC1D,KAAK,EAAE,MAAM,IAAI,CAAC;IAClB,mFAAmF;IACnF,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,0EAA0E;IAC1E,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB,
|
|
1
|
+
{"version":3,"file":"AssistantVoiceSession.d.ts","sourceRoot":"","sources":["../../../../../src/shared/assistant/ui/voice/AssistantVoiceSession.tsx"],"names":[],"mappings":"AAAA,OAAO,EAKL,KAAK,EAAE,EACP,KAAK,SAAS,EACf,MAAM,OAAO,CAAC;AAIf,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,mBAAmB,CAAC;AAyB7D,OAAO,EAEL,KAAK,oBAAoB,EAC1B,MAAM,0BAA0B,CAAC;AAElC,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,oBAAoB,CAAC;AAC7D,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,4BAA4B,CAAC;AAEtE,gFAAgF;AAChF,MAAM,MAAM,SAAS,GAAG,MAAM,GAAG,OAAO,GAAG,MAAM,CAAC;AAElD,UAAU,KAAK;IACb,OAAO,EAAE,oBAAoB,CAAC;IAC9B,iEAAiE;IACjE,KAAK,CAAC,EAAE,aAAa,CAAC,mBAAmB,CAAC,CAAC;IAC3C,wCAAwC;IACxC,gBAAgB,CAAC,EAAE,MAAM,IAAI,CAAC;IAC9B,6EAA6E;IAC7E,gBAAgB,CAAC,EAAE,MAAM,IAAI,CAAC;IAC9B,uCAAuC;IACvC,WAAW,CAAC,EAAE,MAAM,IAAI,CAAC;IACzB,6EAA6E;IAC7E,MAAM,CAAC,EAAE,kBAAkB,GAAG,IAAI,CAAC;IACnC,gEAAgE;IAChE,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;IACtB,YAAY,EAAE,MAAM,IAAI,CAAC;IACzB;;;;;;OAMG;IACH,WAAW,CAAC,EAAE,mBAAmB,EAAE,CAAC;IACpC,aAAa,CAAC,EAAE,CAAC,KAAK,EAAE,QAAQ,GAAG,IAAI,KAAK,IAAI,CAAC;IACjD,kBAAkB,CAAC,EAAE,CAAC,EAAE,EAAE,MAAM,KAAK,IAAI,CAAC;IAC1C,iBAAiB,CAAC,EAAE,CAAC,EAAE,EAAE,MAAM,KAAK,IAAI,CAAC;IACzC,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB,0EAA0E;IAC1E,oBAAoB,CAAC,EAAE,MAAM,CAAC;IAC9B,4DAA4D;IAC5D,YAAY,CAAC,EAAE;QAAE,MAAM,EAAE,MAAM,EAAE,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,GAAG,IAAI,CAAC;IAC1D,KAAK,EAAE,MAAM,IAAI,CAAC;IAClB,mFAAmF;IACnF,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,0EAA0E;IAC1E,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB,6DAA6D;IAC7D,gBAAgB,CAAC,EAAE,OAAO,CAAC;IAC3B;;;OAGG;IACH,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB;;;OAGG;IACH,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,+DAA+D;IAC/D,aAAa,CAAC,EAAE,MAAM,IAAI,CAAC;IAC3B,oDAAoD;IACpD,QAAQ,CAAC,EAAE,MAAM,IAAI,CAAC;IACtB;;;;;OAKG;IACH,YAAY,CAAC,EAAE;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,IAAI,CAAA;KAAE,GAAG,IAAI,CAAC;IAC5D,6EAA6E;IAC7E,YAAY,CAAC,EAAE;QACb,OAAO,EAAE,SAAS,CAAC;QACnB,UAAU,EAAE,MAAM,CAAC;QACnB,OAAO,EAAE,MAAM,IAAI,CAAC;KACrB,GAAG,IAAI,CAAC;CACV;AAED;;;;;;;;;;;;;;;;;;GAkBG;AACH,eAAO,MAAM,qBAAqB,EAAE,EAAE,CAAC,KAAK,CA+zB3C,CAAC"}
|