@burdenoff/fe-libs 2026.1014.4 → 2026.1015.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/shared/assistant/avatar/avatarPreferences.d.ts +61 -14
- package/dist/shared/assistant/avatar/avatarPreferences.js +54 -21
- package/dist/shared/assistant/avatar/live/LiveAvatarTabView.d.ts +33 -0
- package/dist/shared/assistant/avatar/live/LiveAvatarTabView.js +278 -0
- package/dist/shared/assistant/avatar/live/avatarSessionClient.d.ts +5 -0
- package/dist/shared/assistant/avatar/live/avatarSessionClient.js +25 -6
- package/dist/shared/assistant/avatar/live/avatarVoice.d.ts +43 -0
- package/dist/shared/assistant/avatar/live/avatarVoice.js +45 -0
- package/dist/shared/assistant/avatar/live/createLiveAvatarSeam.d.ts +21 -1
- package/dist/shared/assistant/avatar/live/createLiveAvatarSeam.js +74 -24
- package/dist/shared/assistant/avatar/live/liveAvatarController.d.ts +47 -8
- package/dist/shared/assistant/avatar/live/liveAvatarController.js +244 -161
- package/dist/shared/assistant/avatar/live/liveAvatarStatus.d.ts +2 -2
- package/dist/shared/assistant/avatar/live/liveAvatarStatus.js +11 -4
- package/dist/shared/assistant/avatar/useAvatarCopy.d.ts +52 -21
- package/dist/shared/assistant/avatar/useAvatarCopy.js +93 -48
- package/dist/shared/assistant/i18nManifest.d.ts +24 -2
- package/dist/shared/assistant/i18nManifest.js +24 -2
- package/dist/shared/assistant/index.d.ts +5 -0
- package/dist/shared/assistant/speech/hostedVoiceCatalogue.d.ts +19 -0
- package/dist/shared/assistant/speech/hostedVoiceCatalogue.js +25 -18
- package/dist/shared/assistant/ui/AIAssistantPanel.js +136 -103
- package/dist/shared/assistant/ui/AssistantAvatarTabs.d.ts +10 -0
- package/dist/shared/assistant/ui/AssistantAvatarTabs.js +48 -0
- package/dist/shared/assistant/ui/AssistantChatArea.js +1260 -1199
- package/dist/shared/assistant/ui/assistantLiveAvatarSeam.d.ts +165 -5
- package/dist/shared/assistant/ui/assistantLiveAvatarSeam.js +141 -59
- package/dist/shared/assistant/ui/avatar/AssistantAvatarTab.d.ts +13 -0
- package/dist/shared/assistant/ui/avatar/AssistantAvatarTab.js +70 -0
- package/dist/shared/assistant/ui/composer/AssistantComposer.d.ts +18 -0
- package/dist/shared/assistant/ui/composer/AssistantComposer.js +121 -102
- package/dist/shared/assistant/ui/composer/AssistantHandsFreeInterruptToggle.d.ts +9 -0
- package/dist/shared/assistant/ui/composer/AssistantHandsFreeInterruptToggle.js +28 -14
- package/dist/shared/assistant/ui/panelOverlays.d.ts +24 -3
- package/dist/shared/assistant/ui/panelOverlays.js +11 -10
- package/dist/shared/assistant/ui/useVoiceSession.js +234 -233
- package/dist/shared/assistant/ui/voice/AssistantVoiceSession.d.ts +6 -0
- package/dist/shared/assistant/ui/voice/AssistantVoiceSession.js +161 -149
- package/dist/shared/assistant/ui/voice/VoiceMiniController.js +7 -7
- package/dist/shared/assistant/ui/voice/VoiceStage.js +7 -7
- package/dist/shared/assistant/ui/voice/voiceStartGate.d.ts +57 -0
- package/dist/shared/assistant/ui/voice/voiceStartGate.js +9 -0
- package/dist/shared/assistant/voice/handsfree/handsFreeSetting.d.ts +7 -1
- package/dist/shared/assistant/voice/handsfree/handsFreeSetting.js +2 -2
- package/dist/shared-assistant.js +259 -254
- package/package.json +1 -1
|
@@ -1,284 +1,296 @@
|
|
|
1
1
|
import { useReturnFocus as e } from "../../../hooks/useReturnFocus.js";
|
|
2
2
|
import { useAssistantControl as t } from "../../appControls/useAssistantControl.js";
|
|
3
3
|
import { useAssistantTr as n } from "../../i18n.js";
|
|
4
|
-
import { micIsInterrupt as r, showsAssistantCaption as ee, voiceStageState as
|
|
5
|
-
import { VOICE_THINKING_LABEL as
|
|
6
|
-
import { spokenSoFar as
|
|
7
|
-
import {
|
|
8
|
-
import {
|
|
9
|
-
import {
|
|
10
|
-
import {
|
|
11
|
-
import {
|
|
12
|
-
import {
|
|
13
|
-
import {
|
|
14
|
-
import {
|
|
15
|
-
import {
|
|
16
|
-
import {
|
|
17
|
-
import {
|
|
18
|
-
import {
|
|
19
|
-
import {
|
|
4
|
+
import { micIsInterrupt as r, showsAssistantCaption as ee, voiceStageState as te } from "../../voice/voiceStageState.js";
|
|
5
|
+
import { VOICE_THINKING_LABEL as i, composeVoiceStatus as ne, voiceStatusSuffix as re } from "../../voice/voiceStatus.js";
|
|
6
|
+
import { spokenSoFar as ie } from "../../voice/voiceSession.js";
|
|
7
|
+
import { useAvatarCopy as ae } from "../../avatar/useAvatarCopy.js";
|
|
8
|
+
import { ASSISTANT_PANEL_ATTR as oe, ASSISTANT_VOICE_SESSION_ATTR as se } from "../panelOverlays.js";
|
|
9
|
+
import { useLiveAvatarHandsFreeGuard as ce, useLiveAvatarTab as le, useLiveAvatarVoiceView as ue } from "../assistantLiveAvatarSeam.js";
|
|
10
|
+
import { AssistantAttachmentButton as de } from "../composer/AssistantAttachmentButton.js";
|
|
11
|
+
import { AssistantAttachmentChips as fe } from "../composer/AssistantAttachmentChips.js";
|
|
12
|
+
import { AssistantVoiceOrb as pe } from "./AssistantVoiceOrb.js";
|
|
13
|
+
import { VoiceMiniController as me } from "./VoiceMiniController.js";
|
|
14
|
+
import { VoiceStage as he } from "./VoiceStage.js";
|
|
15
|
+
import { VoiceTranscriptDrawer as ge } from "./VoiceTranscriptDrawer.js";
|
|
16
|
+
import { escapeBelongsToLayerAbove as _e, voiceSessionEscapeAction as ve } from "./voiceSessionEscape.js";
|
|
17
|
+
import { HandsFreePrivacyNotice as ye } from "./HandsFreePrivacyNotice.js";
|
|
18
|
+
import { useCallback as a, useEffect as o, useMemo as be, useRef as s, useState as c } from "react";
|
|
19
|
+
import { Maximize2 as xe, Minimize2 as Se, ScrollText as Ce, X as l } from "lucide-react";
|
|
20
|
+
import { jsx as u, jsxs as d } from "react/jsx-runtime";
|
|
20
21
|
//#region src/shared/assistant/ui/voice/AssistantVoiceSession.tsx
|
|
21
|
-
var
|
|
22
|
-
let
|
|
23
|
-
|
|
24
|
-
let
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
22
|
+
var f = ({ session: f, turns: Te = [], onSaveTranscript: Ee, onContinueInChat: De, notice: m = null, privacyNotice: h = null, spoken: g, onInterrupt: Oe, onToggleMute: _, attachments: v = [], onAttachFiles: y, onRemoveAttachment: ke, onRetryAttachment: Ae, canAttachMore: je = !0, preparingAttachments: Me = 0, attachmentsLocked: b = !1, attachmentNotice: x = null, spokenChunks: S = null, onEnd: C, capturing: Ne = !0, interrupting: Pe = !1, awaitingEndpoint: Fe = !1, holding: w = !1, correcting: Ie = !1, onLetMeFinish: T, onImDone: E, proposalChip: D = null, proposalTray: O = null, renderAfterTurn: Le, onViewChange: k }) => {
|
|
23
|
+
let A = n(), { muted: j, error: M } = f, N = s(null), P = s(null), [F, I] = c("mini"), L = le().open, [Re, ze] = c(L);
|
|
24
|
+
Re !== L && (ze(L), L && F !== "mini" && I("mini"));
|
|
25
|
+
let R = ue(F, f.phase === "ended"), Be = ce();
|
|
26
|
+
o(() => {
|
|
27
|
+
k?.(R);
|
|
28
|
+
}, [k, R]);
|
|
29
|
+
let Ve = ae(), z = R === "full", B = R === "mini", V = R === "mini" ? "panel" : R === "panel" ? "full" : "mini", [H, U] = c(!1);
|
|
30
|
+
t("assistant.transcript", be(() => ({ run: () => H ? { status: "already" } : (U(!0), { status: "done" }) }), [H]));
|
|
31
|
+
let W = O !== null && !B, G = s(!1), K = s(_);
|
|
32
|
+
K.current = _;
|
|
33
|
+
let q = a(() => {
|
|
34
|
+
f.phase !== "listening" && f.phase !== "thinking" || j || G.current || ie(f) || (G.current = !0, K.current());
|
|
35
|
+
}, [j, f]), J = a(() => {
|
|
29
36
|
G.current && (G.current = !1, K.current());
|
|
30
|
-
}, []),
|
|
31
|
-
|
|
37
|
+
}, []), He = q;
|
|
38
|
+
o(() => {
|
|
32
39
|
let e = () => {
|
|
33
40
|
document.visibilityState === "hidden" ? q() : J();
|
|
34
41
|
};
|
|
35
42
|
return document.addEventListener("visibilitychange", e), () => document.removeEventListener("visibilitychange", e);
|
|
36
|
-
}, [q, J]),
|
|
43
|
+
}, [q, J]), o(() => {
|
|
37
44
|
let e = J;
|
|
38
45
|
return window.addEventListener("focus", e), () => {
|
|
39
46
|
window.removeEventListener("focus", e), G.current = !1;
|
|
40
47
|
};
|
|
41
|
-
}, []),
|
|
42
|
-
document.activeElement?.closest("[data-hands-free-notice]") ||
|
|
43
|
-
}, []), e(
|
|
48
|
+
}, []), o(() => {
|
|
49
|
+
document.activeElement?.closest("[data-hands-free-notice]") || N.current?.focus();
|
|
50
|
+
}, []), e(P, { fallbackSelector: `[${oe}]` }), o(() => {
|
|
44
51
|
let e = (e) => {
|
|
45
52
|
if (e.key === "Escape") {
|
|
46
|
-
let t =
|
|
53
|
+
let t = ve({
|
|
47
54
|
defaultPrevented: e.defaultPrevented,
|
|
48
|
-
layerAbove:
|
|
55
|
+
layerAbove: _e({
|
|
49
56
|
target: e.target,
|
|
50
|
-
session:
|
|
57
|
+
session: P.current,
|
|
51
58
|
doc: document
|
|
52
59
|
}),
|
|
53
60
|
transcriptOpen: H
|
|
54
61
|
});
|
|
55
62
|
if (t === "ignore") return;
|
|
56
|
-
e.preventDefault(), t === "close-transcript" ? U(!1) :
|
|
63
|
+
e.preventDefault(), t === "close-transcript" ? U(!1) : h ? h.decline() : W ? O?.onClose() : C();
|
|
57
64
|
return;
|
|
58
65
|
}
|
|
59
66
|
if (e.key !== "Tab" || !z) return;
|
|
60
|
-
let t = (H ?
|
|
67
|
+
let t = (H ? P.current?.querySelector("[data-testid=\"assistant-voice-transcript\"]") : P.current)?.querySelectorAll("button:not([disabled])");
|
|
61
68
|
if (!t || t.length === 0) return;
|
|
62
69
|
let n = t[0], r = t[t.length - 1];
|
|
63
70
|
!n || !r || (e.shiftKey && document.activeElement === n ? (e.preventDefault(), r.focus()) : !e.shiftKey && document.activeElement === r && (e.preventDefault(), n.focus()));
|
|
64
71
|
};
|
|
65
72
|
return window.addEventListener("keydown", e), () => window.removeEventListener("keydown", e);
|
|
66
73
|
}, [
|
|
67
|
-
|
|
74
|
+
C,
|
|
68
75
|
z,
|
|
69
76
|
H,
|
|
70
77
|
W,
|
|
71
|
-
|
|
72
|
-
|
|
78
|
+
O,
|
|
79
|
+
h
|
|
73
80
|
]);
|
|
74
|
-
let Y =
|
|
75
|
-
letMeFinish:
|
|
76
|
-
imDone:
|
|
77
|
-
} : null,
|
|
78
|
-
|
|
79
|
-
if (
|
|
81
|
+
let Y = m !== null && M === null, X = Be && m === null && M === null, Ue = ie(f), Z = T && E && f.phase === "listening" && !j && M === null ? {
|
|
82
|
+
letMeFinish: T,
|
|
83
|
+
imDone: E
|
|
84
|
+
} : null, We = Z !== null;
|
|
85
|
+
o(() => {
|
|
86
|
+
if (We) return;
|
|
80
87
|
let e = document.activeElement;
|
|
81
|
-
(!e || e === document.body) &&
|
|
82
|
-
}, [
|
|
83
|
-
let Q =
|
|
84
|
-
snapshot:
|
|
85
|
-
capturing:
|
|
86
|
-
interrupting:
|
|
87
|
-
awaitingEndpoint:
|
|
88
|
-
}),
|
|
88
|
+
(!e || e === document.body) && N.current?.focus();
|
|
89
|
+
}, [We]);
|
|
90
|
+
let Q = te({
|
|
91
|
+
snapshot: f,
|
|
92
|
+
capturing: Ne,
|
|
93
|
+
interrupting: Pe,
|
|
94
|
+
awaitingEndpoint: Fe
|
|
95
|
+
}), Ge = (() => {
|
|
89
96
|
switch (Q) {
|
|
90
|
-
case "connecting": return
|
|
91
|
-
case "endpoint-grace": return
|
|
92
|
-
case "interrupting": return
|
|
93
|
-
case "thinking": return
|
|
94
|
-
case "speaking": return
|
|
97
|
+
case "connecting": return A("voiceSession.connecting", "Starting the microphone…");
|
|
98
|
+
case "endpoint-grace": return A("voiceSession.endpointGrace", "Still listening — take your time");
|
|
99
|
+
case "interrupting": return A("voiceSession.interrupting", "Stopped — go ahead");
|
|
100
|
+
case "thinking": return A(i.key, i.fallback);
|
|
101
|
+
case "speaking": return A("voiceSession.speaking", "Speaking — tap to stop");
|
|
95
102
|
case "mic-error":
|
|
96
103
|
case "ended": return "";
|
|
97
|
-
case "listening": return
|
|
104
|
+
case "listening": return j ? A("voiceSession.muted", "Microphone off") : A("voiceSession.listening", "Listening…");
|
|
98
105
|
default: return Q;
|
|
99
106
|
}
|
|
100
|
-
})(),
|
|
101
|
-
tr:
|
|
107
|
+
})(), Ke = !j && (Q === "listening" || Q === "endpoint-grace"), qe = Ke && w ? A("voiceSession.holding", "Take your time — tap “I’m done” when you finish") : Ke && Ie ? A("voiceSession.correcting", "Stopped that answer — listening to your correction") : Ge, $ = re({
|
|
108
|
+
tr: A,
|
|
102
109
|
stage: Q,
|
|
103
|
-
muted:
|
|
104
|
-
label:
|
|
105
|
-
}),
|
|
106
|
-
return /* @__PURE__ */
|
|
107
|
-
ref:
|
|
110
|
+
muted: j,
|
|
111
|
+
label: qe
|
|
112
|
+
}), Je = ne(qe, $), Ye = Q === "thinking";
|
|
113
|
+
return /* @__PURE__ */ d("div", {
|
|
114
|
+
ref: P,
|
|
108
115
|
className: `flex flex-col items-center justify-between bg-bg-sunken ${R === "full" ? "fixed inset-x-0 bottom-0 top-14 z-[60] px-6 py-8" : R === "panel" ? "absolute inset-0 z-20 px-4 py-6" : "absolute inset-x-0 bottom-0 z-20 min-h-[11.25rem] border-t border-border-subtle px-3 py-3 shadow-lg"}`,
|
|
109
116
|
role: "dialog",
|
|
110
117
|
"aria-modal": z || void 0,
|
|
111
|
-
"aria-label":
|
|
118
|
+
"aria-label": A("voiceSession.title", "Voice conversation"),
|
|
112
119
|
"data-testid": "assistant-voice-session",
|
|
113
|
-
[
|
|
120
|
+
[se]: "",
|
|
114
121
|
children: [
|
|
115
|
-
/* @__PURE__ */
|
|
116
|
-
ref:
|
|
122
|
+
/* @__PURE__ */ d("button", {
|
|
123
|
+
ref: N,
|
|
117
124
|
type: "button",
|
|
118
|
-
onClick:
|
|
125
|
+
onClick: C,
|
|
119
126
|
className: `absolute ${z ? "right-6 top-6 h-14 gap-2 px-5 text-base" : B ? "right-12 top-2 h-8 gap-1.5 px-2.5 text-xs" : "right-3 top-3 h-11 gap-2 px-4 text-sm"} flex items-center justify-center rounded-full border border-border-default bg-bg-elevated text-text-secondary hover:bg-bg-sunken transition-colors focus:outline-none focus-visible:ring-2 focus-visible:ring-border-strong`,
|
|
120
|
-
title:
|
|
127
|
+
title: A("voiceSession.end", "End the voice conversation"),
|
|
121
128
|
"data-testid": "assistant-voice-end",
|
|
122
|
-
children: [/* @__PURE__ */
|
|
129
|
+
children: [/* @__PURE__ */ u(l, {
|
|
123
130
|
className: z ? "size-6" : B ? "size-4" : "size-5",
|
|
124
131
|
"aria-hidden": "true"
|
|
125
|
-
}), /* @__PURE__ */
|
|
132
|
+
}), /* @__PURE__ */ u("span", {
|
|
126
133
|
className: `truncate whitespace-nowrap font-medium ${B ? "max-w-[3.5rem] text-xs" : "max-w-[7rem]"}`,
|
|
127
|
-
children:
|
|
134
|
+
children: A("voiceSession.endShort", "End")
|
|
128
135
|
})]
|
|
129
136
|
}),
|
|
130
|
-
/* @__PURE__ */
|
|
131
|
-
className: `flex flex-col items-center ${B ? `px-3 ${Y ||
|
|
137
|
+
/* @__PURE__ */ d("div", {
|
|
138
|
+
className: `flex flex-col items-center ${B ? `px-3 ${Y || X || x ? "pt-9 pb-2" : ""}` : `min-h-[1.5rem] ${Y || X || x ? z ? "pt-14" : "pt-10" : ""}`}`,
|
|
132
139
|
children: [
|
|
133
|
-
Y ? /* @__PURE__ */
|
|
140
|
+
Y ? /* @__PURE__ */ u("p", {
|
|
134
141
|
className: "max-w-xs text-center text-xs text-status-warning",
|
|
135
142
|
"data-testid": "assistant-voice-notice",
|
|
136
|
-
children:
|
|
143
|
+
children: p(m, A)
|
|
137
144
|
}) : null,
|
|
138
|
-
/* @__PURE__ */
|
|
145
|
+
X ? /* @__PURE__ */ u("p", {
|
|
146
|
+
className: "max-w-xs text-center text-xs text-text-secondary",
|
|
147
|
+
"data-testid": "assistant-voice-avatar-hands-free",
|
|
148
|
+
children: Ve.handsFreeOff
|
|
149
|
+
}) : null,
|
|
150
|
+
/* @__PURE__ */ u("span", {
|
|
139
151
|
className: "sr-only start-0 top-0",
|
|
140
152
|
role: "status",
|
|
141
153
|
"aria-live": "polite",
|
|
142
154
|
"aria-atomic": "true",
|
|
143
155
|
"data-testid": "assistant-voice-notice-announced",
|
|
144
|
-
children: Y &&
|
|
156
|
+
children: Y && m === "reply-not-heard" ? p(m, A) : X ? Ve.handsFreeOff : null
|
|
145
157
|
}),
|
|
146
|
-
|
|
158
|
+
x ? /* @__PURE__ */ u("p", {
|
|
147
159
|
className: "max-w-xs text-center text-xs text-status-warning",
|
|
148
160
|
role: "status",
|
|
149
161
|
"aria-live": "polite",
|
|
150
162
|
"data-testid": "assistant-voice-attachment-notice",
|
|
151
|
-
children:
|
|
163
|
+
children: x
|
|
152
164
|
}) : null
|
|
153
165
|
]
|
|
154
166
|
}),
|
|
155
167
|
(() => {
|
|
156
|
-
let e = /* @__PURE__ */
|
|
157
|
-
session:
|
|
168
|
+
let e = /* @__PURE__ */ u(pe, {
|
|
169
|
+
session: f,
|
|
158
170
|
compact: B,
|
|
159
171
|
connecting: Q === "connecting",
|
|
160
|
-
onPress: r(Q) ?
|
|
161
|
-
label: r(Q) ?
|
|
162
|
-
}), t = Z ? /* @__PURE__ */
|
|
172
|
+
onPress: r(Q) ? Oe : _,
|
|
173
|
+
label: r(Q) ? A("voiceSession.interrupt", "Stop the assistant and speak") : j ? A("voiceSession.unmute", "Turn the microphone on") : A("voiceSession.mute", "Turn the microphone off")
|
|
174
|
+
}), t = Z ? /* @__PURE__ */ u("button", {
|
|
163
175
|
type: "button",
|
|
164
|
-
onClick:
|
|
165
|
-
className: `flex items-center justify-center rounded-full border font-medium transition-colors focus:outline-none focus-visible:ring-2 focus-visible:ring-border-strong ${B ? "h-7 px-3 text-xs" : z ? "h-11 px-6 text-base" : "h-9 px-4 text-sm"} ${
|
|
166
|
-
title:
|
|
176
|
+
onClick: w ? Z.imDone : Z.letMeFinish,
|
|
177
|
+
className: `flex items-center justify-center rounded-full border font-medium transition-colors focus:outline-none focus-visible:ring-2 focus-visible:ring-border-strong ${B ? "h-7 px-3 text-xs" : z ? "h-11 px-6 text-base" : "h-9 px-4 text-sm"} ${w ? "border-transparent bg-action-primary-bg text-action-primary-text hover:opacity-90" : "border-border-default bg-bg-elevated text-text-secondary hover:bg-bg-sunken"}`,
|
|
178
|
+
title: w ? A("voiceSession.imDoneHint", "Send what you said now") : A("voiceSession.letMeFinishHint", "Pause sending until you tap “I’m done”"),
|
|
167
179
|
"data-testid": "assistant-voice-hold",
|
|
168
|
-
"data-holding":
|
|
169
|
-
children:
|
|
170
|
-
}) : null, n = t ? /* @__PURE__ */
|
|
180
|
+
"data-holding": w ? "true" : "false",
|
|
181
|
+
children: w ? A("voiceSession.imDone", "I’m done") : A("voiceSession.letMeFinish", "Let me finish")
|
|
182
|
+
}) : null, n = t ? /* @__PURE__ */ d("div", {
|
|
171
183
|
className: "flex flex-col items-center gap-2",
|
|
172
184
|
children: [e, t]
|
|
173
|
-
}) : e,
|
|
174
|
-
return B ? /* @__PURE__ */
|
|
175
|
-
spokenChunks:
|
|
185
|
+
}) : e, te = ee(Q) ? g : Ue || null, i = M === null ? null : we(M, A);
|
|
186
|
+
return B ? /* @__PURE__ */ u(me, {
|
|
187
|
+
spokenChunks: S,
|
|
176
188
|
state: Q,
|
|
177
|
-
caption:
|
|
178
|
-
statusText:
|
|
189
|
+
caption: te,
|
|
190
|
+
statusText: Je,
|
|
179
191
|
statusSuffix: $,
|
|
180
|
-
rotateStatus:
|
|
181
|
-
errorText:
|
|
192
|
+
rotateStatus: Ye,
|
|
193
|
+
errorText: i,
|
|
182
194
|
control: n
|
|
183
|
-
}) : /* @__PURE__ */
|
|
195
|
+
}) : /* @__PURE__ */ u(he, {
|
|
184
196
|
state: Q,
|
|
185
|
-
userCaption:
|
|
186
|
-
spokenChunks:
|
|
187
|
-
assistantCaption:
|
|
197
|
+
userCaption: Ue || null,
|
|
198
|
+
spokenChunks: S,
|
|
199
|
+
assistantCaption: g,
|
|
188
200
|
expanded: z,
|
|
189
|
-
statusText:
|
|
201
|
+
statusText: Je,
|
|
190
202
|
statusSuffix: $,
|
|
191
|
-
rotateStatus:
|
|
192
|
-
errorText:
|
|
203
|
+
rotateStatus: Ye,
|
|
204
|
+
errorText: i,
|
|
193
205
|
control: n
|
|
194
206
|
});
|
|
195
207
|
})(),
|
|
196
|
-
|
|
208
|
+
D && !W ? /* @__PURE__ */ u("div", {
|
|
197
209
|
className: B ? "absolute left-20 right-36 top-2 flex justify-center" : `flex w-full justify-center ${z ? "max-w-[calc(100%-12rem)]" : "max-w-[calc(100%-8rem)]"}`,
|
|
198
|
-
children: /* @__PURE__ */
|
|
210
|
+
children: /* @__PURE__ */ u("button", {
|
|
199
211
|
type: "button",
|
|
200
212
|
onClick: () => {
|
|
201
|
-
|
|
213
|
+
I("panel"), D.onOpen();
|
|
202
214
|
},
|
|
203
215
|
className: `max-w-full truncate rounded-full border border-border-default bg-bg-elevated font-medium text-text-primary transition-colors hover:bg-bg-raised focus:outline-none focus-visible:ring-2 focus-visible:ring-border-strong ${B ? "h-8 px-3 text-xs" : "h-10 px-4 text-sm"}`,
|
|
204
216
|
"data-testid": "assistant-voice-proposal-chip",
|
|
205
|
-
children:
|
|
217
|
+
children: D.label
|
|
206
218
|
})
|
|
207
219
|
}) : null,
|
|
208
|
-
|
|
220
|
+
O && W ? /* @__PURE__ */ d("div", {
|
|
209
221
|
className: `absolute z-10 flex flex-col gap-2 overflow-y-auto rounded-lg border border-border-subtle bg-bg-elevated shadow-lg ${z ? "inset-x-6 bottom-24 top-24 mx-auto max-w-xl p-4" : "inset-x-3 bottom-16 top-16 p-3"}`,
|
|
210
222
|
"data-testid": "assistant-voice-proposal-tray",
|
|
211
|
-
children: [/* @__PURE__ */
|
|
223
|
+
children: [/* @__PURE__ */ u("div", {
|
|
212
224
|
className: "flex justify-end",
|
|
213
|
-
children: /* @__PURE__ */
|
|
225
|
+
children: /* @__PURE__ */ u("button", {
|
|
214
226
|
type: "button",
|
|
215
|
-
onClick:
|
|
227
|
+
onClick: O.onClose,
|
|
216
228
|
className: "flex size-8 items-center justify-center rounded-full text-text-secondary transition-colors hover:bg-bg-raised hover:text-text-primary focus:outline-none focus-visible:ring-2 focus-visible:ring-border-strong",
|
|
217
|
-
"aria-label":
|
|
229
|
+
"aria-label": O.closeLabel,
|
|
218
230
|
"data-testid": "assistant-voice-proposal-tray-close",
|
|
219
|
-
children: /* @__PURE__ */
|
|
231
|
+
children: /* @__PURE__ */ u(l, {
|
|
220
232
|
className: "size-4",
|
|
221
233
|
"aria-hidden": "true"
|
|
222
234
|
})
|
|
223
235
|
})
|
|
224
|
-
}),
|
|
236
|
+
}), O.content]
|
|
225
237
|
}) : null,
|
|
226
|
-
|
|
238
|
+
h ? /* @__PURE__ */ u(ye, {
|
|
227
239
|
view: R,
|
|
228
|
-
onContinue:
|
|
229
|
-
onNotNow:
|
|
240
|
+
onContinue: h.accept,
|
|
241
|
+
onNotNow: h.decline
|
|
230
242
|
}) : null,
|
|
231
|
-
H ? /* @__PURE__ */
|
|
232
|
-
turns:
|
|
243
|
+
H ? /* @__PURE__ */ u(ge, {
|
|
244
|
+
turns: Te,
|
|
233
245
|
onClose: () => U(!1),
|
|
234
|
-
onSave:
|
|
235
|
-
onContinueInChat:
|
|
236
|
-
renderAfterTurn:
|
|
246
|
+
onSave: Ee,
|
|
247
|
+
onContinueInChat: De,
|
|
248
|
+
renderAfterTurn: Le
|
|
237
249
|
}) : null,
|
|
238
|
-
|
|
250
|
+
y ? /* @__PURE__ */ u("div", {
|
|
239
251
|
className: `absolute ${z ? "left-6 top-6" : B ? "left-11 top-2" : "left-3 top-3"}`,
|
|
240
|
-
children: /* @__PURE__ */
|
|
252
|
+
children: /* @__PURE__ */ u(de, {
|
|
241
253
|
onFiles: (e) => {
|
|
242
|
-
|
|
254
|
+
y(e), I((e) => e === "mini" ? "panel" : e);
|
|
243
255
|
},
|
|
244
|
-
onPickerOpen:
|
|
256
|
+
onPickerOpen: He,
|
|
245
257
|
direction: "down",
|
|
246
|
-
canAddMore:
|
|
247
|
-
disabled:
|
|
258
|
+
canAddMore: je,
|
|
259
|
+
disabled: b
|
|
248
260
|
})
|
|
249
261
|
}) : null,
|
|
250
|
-
(
|
|
262
|
+
(v.length > 0 || Me > 0) && !B ? /* @__PURE__ */ u("div", {
|
|
251
263
|
className: `absolute ${z ? "bottom-24 left-24 right-24" : "bottom-16 left-16 right-16"}`,
|
|
252
264
|
"data-testid": "assistant-voice-attachments",
|
|
253
|
-
children: /* @__PURE__ */
|
|
254
|
-
attachments:
|
|
255
|
-
onRemove:
|
|
256
|
-
onRetry:
|
|
257
|
-
preparingCount:
|
|
258
|
-
disabled:
|
|
265
|
+
children: /* @__PURE__ */ u(fe, {
|
|
266
|
+
attachments: v,
|
|
267
|
+
onRemove: ke ?? (() => void 0),
|
|
268
|
+
onRetry: Ae ?? (() => void 0),
|
|
269
|
+
preparingCount: Me,
|
|
270
|
+
disabled: b
|
|
259
271
|
})
|
|
260
272
|
}) : null,
|
|
261
|
-
/* @__PURE__ */
|
|
273
|
+
/* @__PURE__ */ u("button", {
|
|
262
274
|
type: "button",
|
|
263
275
|
onClick: () => U((e) => !e),
|
|
264
276
|
className: `absolute ${z ? "bottom-6 right-6 size-14" : B ? "right-2 top-2 size-8" : "bottom-3 right-3 size-11"} flex items-center justify-center rounded-full bg-bg-elevated text-text-secondary transition-colors hover:bg-bg-raised hover:text-text-primary focus:outline-none focus-visible:ring-2 focus-visible:ring-border-strong`,
|
|
265
277
|
"aria-pressed": H,
|
|
266
|
-
"aria-label":
|
|
278
|
+
"aria-label": A("voiceSession.transcriptTitle", "Voice transcript"),
|
|
267
279
|
"data-testid": "assistant-voice-transcript-toggle",
|
|
268
|
-
children: /* @__PURE__ */
|
|
280
|
+
children: /* @__PURE__ */ u(Ce, { className: z ? "size-6" : B ? "size-4" : "size-5" })
|
|
269
281
|
}),
|
|
270
|
-
/* @__PURE__ */
|
|
282
|
+
/* @__PURE__ */ u("button", {
|
|
271
283
|
type: "button",
|
|
272
|
-
onClick: () =>
|
|
284
|
+
onClick: () => I(V),
|
|
273
285
|
className: `absolute ${z ? "bottom-6 left-6 size-14" : B ? "left-2 top-2 size-8" : "bottom-3 left-3 size-11"} flex items-center justify-center rounded-full bg-bg-elevated text-text-secondary transition-colors hover:bg-bg-raised hover:text-text-primary focus:outline-none focus-visible:ring-2 focus-visible:ring-border-strong`,
|
|
274
|
-
"aria-label": V === "panel" ?
|
|
286
|
+
"aria-label": V === "panel" ? A("voiceSession.expandPanel", "Show the conversation in the panel") : V === "full" ? A("voiceSession.expand", "Expand the conversation to full screen") : A("voiceSession.collapse", "Shrink to the compact controller"),
|
|
275
287
|
"data-testid": "assistant-voice-expand",
|
|
276
|
-
children: z ? /* @__PURE__ */
|
|
288
|
+
children: z ? /* @__PURE__ */ u(Se, { className: "size-5" }) : /* @__PURE__ */ u(xe, { className: B ? "size-4" : "size-5" })
|
|
277
289
|
})
|
|
278
290
|
]
|
|
279
291
|
});
|
|
280
292
|
};
|
|
281
|
-
function
|
|
293
|
+
function p(e, t) {
|
|
282
294
|
switch (e) {
|
|
283
295
|
case "network": return t("voiceSession.noticeNetwork", "Speech recognition lost its connection. Check your network — it will retry.");
|
|
284
296
|
case "not-capturing": return t("voiceSession.noticeNotCapturing", "The microphone did not start. Check that this site is allowed to use it, then try again.");
|
|
@@ -290,7 +302,7 @@ function h(e, t) {
|
|
|
290
302
|
default: return e;
|
|
291
303
|
}
|
|
292
304
|
}
|
|
293
|
-
function
|
|
305
|
+
function we(e, t) {
|
|
294
306
|
switch (e) {
|
|
295
307
|
case "mic-denied": return t("voiceSession.micDenied", "Microphone access is blocked. Allow it in your browser settings to talk.");
|
|
296
308
|
case "no-speech-support": return t("voiceSession.noSpeechSupport", "This browser cannot listen. Try a different browser, or type instead.");
|
|
@@ -299,4 +311,4 @@ function ye(e, t) {
|
|
|
299
311
|
}
|
|
300
312
|
}
|
|
301
313
|
//#endregion
|
|
302
|
-
export {
|
|
314
|
+
export { f as AssistantVoiceSession };
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import { showsAssistantCaption as e, waveformIsActive as t, waveformIsSettled as n } from "../../voice/voiceStageState.js";
|
|
2
2
|
import { showPreviousChunk as r } from "../../voice/miniCaptionBudget.js";
|
|
3
3
|
import { isAwaitingFirstChunk as i } from "../../voice/speechPlayback.js";
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
6
|
-
import {
|
|
4
|
+
import { LiveAvatarMiniIndicator as a, useLiveAvatarMiniIndicatorShown as o } from "../assistantLiveAvatarSeam.js";
|
|
5
|
+
import { VoiceWaveform as s } from "./VoiceWaveform.js";
|
|
6
|
+
import { VoiceStatusText as c } from "./VoiceStatusText.js";
|
|
7
7
|
import { Fragment as l, jsx as u, jsxs as d } from "react/jsx-runtime";
|
|
8
8
|
//#region src/shared/assistant/ui/voice/VoiceMiniController.tsx
|
|
9
9
|
var f = " self-stretch justify-end pb-8.5 [container-type:size] [@container_(min-height:4.0312rem)_and_(max-height:5.2343rem)]:[&>p[role=status]]:line-clamp-2 [@container_(max-height:4.0312rem)]:[&>p[role=status]]:line-clamp-1 [@container_(max-height:4.0312rem)]:[&>p[role=status]]:min-h-5 [@container_(max-height:5.2343rem)]:[&>p[role=status]>span:not(:last-child)]:sr-only", p = ({ state: p, caption: m, spokenChunks: h = null, statusText: g, statusSuffix: _, rotateStatus: v, control: y, errorText: b = null }) => {
|
|
@@ -14,14 +14,14 @@ var f = " self-stretch justify-end pb-8.5 [container-type:size] [@container_(min
|
|
|
14
14
|
"data-state": p,
|
|
15
15
|
children: [
|
|
16
16
|
/* @__PURE__ */ d("div", {
|
|
17
|
-
className: `flex min-w-0 flex-1 flex-col gap-1.5${
|
|
17
|
+
className: `flex min-w-0 flex-1 flex-col gap-1.5${o() ? f : ""}`,
|
|
18
18
|
children: [/* @__PURE__ */ d("div", {
|
|
19
19
|
className: "flex items-center gap-2",
|
|
20
|
-
children: [/* @__PURE__ */ u(
|
|
20
|
+
children: [/* @__PURE__ */ u(s, {
|
|
21
21
|
active: t(p),
|
|
22
22
|
settled: n(p),
|
|
23
23
|
tone: p === "speaking" ? "speaking" : "listening"
|
|
24
|
-
}), /* @__PURE__ */ u(
|
|
24
|
+
}), /* @__PURE__ */ u(c, {
|
|
25
25
|
className: "truncate text-xs text-text-muted",
|
|
26
26
|
status: g,
|
|
27
27
|
suffix: _,
|
|
@@ -58,7 +58,7 @@ var f = " self-stretch justify-end pb-8.5 [container-type:size] [@container_(min
|
|
|
58
58
|
className: "shrink-0",
|
|
59
59
|
children: y
|
|
60
60
|
}),
|
|
61
|
-
/* @__PURE__ */ u(
|
|
61
|
+
/* @__PURE__ */ u(a, {})
|
|
62
62
|
]
|
|
63
63
|
});
|
|
64
64
|
};
|
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
import { showsAssistantCaption as e, showsUserCaption as t, waveformIsActive as n, waveformIsSettled as r } from "../../voice/voiceStageState.js";
|
|
2
2
|
import { isAwaitingFirstChunk as i } from "../../voice/speechPlayback.js";
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
6
|
-
import {
|
|
3
|
+
import { useLiveAvatarStage as a } from "../assistantLiveAvatarSeam.js";
|
|
4
|
+
import { VoiceCaption as o } from "./VoiceCaption.js";
|
|
5
|
+
import { VoiceWaveform as s } from "./VoiceWaveform.js";
|
|
6
|
+
import { VoiceStatusText as c } from "./VoiceStatusText.js";
|
|
7
7
|
import { Fragment as l, jsx as u, jsxs as d } from "react/jsx-runtime";
|
|
8
8
|
//#region src/shared/assistant/ui/voice/VoiceStage.tsx
|
|
9
9
|
var f = ({ state: f, userCaption: p, assistantCaption: m, expanded: h, statusText: g, statusSuffix: _, rotateStatus: v, control: y, errorText: b = null, spokenChunks: x = null }) => {
|
|
10
|
-
let S =
|
|
10
|
+
let S = a(), C = e(f) && i(x), w = e(f) ? m : t(f) ? p : null, T = /* @__PURE__ */ u(s, {
|
|
11
11
|
active: n(f),
|
|
12
12
|
settled: r(f),
|
|
13
13
|
tone: f === "speaking" ? "speaking" : "listening",
|
|
@@ -22,7 +22,7 @@ var f = ({ state: f, userCaption: p, assistantCaption: m, expanded: h, statusTex
|
|
|
22
22
|
"data-testid": "assistant-voice-stage",
|
|
23
23
|
"data-state": f,
|
|
24
24
|
children: [
|
|
25
|
-
/* @__PURE__ */ u(
|
|
25
|
+
/* @__PURE__ */ u(c, {
|
|
26
26
|
className: [
|
|
27
27
|
"text-center text-text-muted",
|
|
28
28
|
h ? "text-base" : "text-sm",
|
|
@@ -46,7 +46,7 @@ var f = ({ state: f, userCaption: p, assistantCaption: m, expanded: h, statusTex
|
|
|
46
46
|
}), w ? /* @__PURE__ */ u("div", {
|
|
47
47
|
className: [h ? "mb-12 max-h-[46vh] w-full overflow-y-auto" : "mb-6 max-h-[38vh] w-full overflow-y-auto", C ? h ? "min-h-[4.875rem]" : "min-h-12" : ""].join(" "),
|
|
48
48
|
"data-caption-scroll": "",
|
|
49
|
-
children: /* @__PURE__ */ u(
|
|
49
|
+
children: /* @__PURE__ */ u(o, {
|
|
50
50
|
text: w,
|
|
51
51
|
role: e(f) ? "assistant" : "user",
|
|
52
52
|
spokenChunks: x,
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Whether a voice conversation can start now, and if not, why (BOFF-9341,
|
|
3
|
+
* critic #6).
|
|
4
|
+
*
|
|
5
|
+
* ★★ ONE check, the composer's FULL one. The composer offers its Voice button
|
|
6
|
+
* only where voice can work at all and the active mode takes it
|
|
7
|
+
* (`onStartVoiceSession`: `voiceSession.available && voiceAllowedInActiveMode`),
|
|
8
|
+
* disables it while the conversation cannot take a turn (its `disabled` and
|
|
9
|
+
* `readOnly`: a turn in flight, an approval being recorded, history loading,
|
|
10
|
+
* navigation busy, a read-only conversation) or while a Send saves its
|
|
11
|
+
* attachments (`committing`), and hides it while dictation holds the
|
|
12
|
+
* microphone. The Avatar tab's "Start a voice conversation" is the same
|
|
13
|
+
* conversation, so it asks exactly this: a button that skipped part of it
|
|
14
|
+
* could open a voice conversation the composer would have refused, or turn on
|
|
15
|
+
* a paid avatar in a mode (the write-capable `api-calls` one with no voice
|
|
16
|
+
* proposal bound to it) where nothing could ever be asked of it.
|
|
17
|
+
*
|
|
18
|
+
* Pure, so the rule is testable without a DOM; the chat area hands it the
|
|
19
|
+
* same expressions it hands the composer (`avatarTab.client.test.tsx` pins
|
|
20
|
+
* that).
|
|
21
|
+
*/
|
|
22
|
+
/** Why a voice conversation cannot start now, most lasting first. */
|
|
23
|
+
export type VoiceStartBlocker =
|
|
24
|
+
/** Nothing here can hold a voice conversation (no speech input, or nothing to speak the reply). */
|
|
25
|
+
"unavailable"
|
|
26
|
+
/** The active mode takes no voice (it writes, and no voice proposal is bound to it). */
|
|
27
|
+
| "mode"
|
|
28
|
+
/** This conversation takes no new turn at all. */
|
|
29
|
+
| "read-only"
|
|
30
|
+
/** Not now: a turn in flight, an approval being recorded, history loading, navigation busy. */
|
|
31
|
+
| "busy"
|
|
32
|
+
/** Not now: a Send is saving its attachments. */
|
|
33
|
+
| "committing"
|
|
34
|
+
/** Not now: dictation holds the microphone. */
|
|
35
|
+
| "dictating";
|
|
36
|
+
export interface VoiceStartGateInput {
|
|
37
|
+
/** `voiceSession.available`: speech in and out work here. */
|
|
38
|
+
readonly available: boolean;
|
|
39
|
+
/** `voiceAllowedInActiveMode`. */
|
|
40
|
+
readonly allowedInMode: boolean;
|
|
41
|
+
/** The conversation is read-only (the composer's `readOnly`). */
|
|
42
|
+
readonly readOnly: boolean;
|
|
43
|
+
/** The composer's `disabled`. */
|
|
44
|
+
readonly busy: boolean;
|
|
45
|
+
/** The composer is saving a Send's attachments. */
|
|
46
|
+
readonly committing: boolean;
|
|
47
|
+
/** Composer dictation is listening, or starting to. */
|
|
48
|
+
readonly dictating: boolean;
|
|
49
|
+
}
|
|
50
|
+
/** Null when a voice conversation can start now; else the first reason it cannot. */
|
|
51
|
+
export declare function voiceStartBlocker(input: VoiceStartGateInput): VoiceStartBlocker | null;
|
|
52
|
+
/**
|
|
53
|
+
* A reason nothing the person waits out will lift, here and now: voice cannot
|
|
54
|
+
* work, the mode refuses it, or the conversation takes nothing. The Avatar tab
|
|
55
|
+
* then still offers Turn on, and says that asking needs a voice conversation.
|
|
56
|
+
*/
|
|
57
|
+
export declare function voiceStartBlockerLasts(blocker: VoiceStartBlocker | null): boolean;
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
//#region src/shared/assistant/ui/voice/voiceStartGate.ts
|
|
2
|
+
function e(e) {
|
|
3
|
+
return e.available ? e.allowedInMode ? e.readOnly ? "read-only" : e.busy ? "busy" : e.committing ? "committing" : e.dictating ? "dictating" : null : "mode" : "unavailable";
|
|
4
|
+
}
|
|
5
|
+
function t(e) {
|
|
6
|
+
return e === "unavailable" || e === "mode" || e === "read-only";
|
|
7
|
+
}
|
|
8
|
+
//#endregion
|
|
9
|
+
export { e as voiceStartBlocker, t as voiceStartBlockerLasts };
|