@burdenoff/fe-libs 2026.1014.5 → 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 +50 -21
- package/dist/shared/assistant/avatar/useAvatarCopy.js +93 -49
- package/dist/shared/assistant/i18nManifest.d.ts +23 -2
- package/dist/shared/assistant/i18nManifest.js +23 -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 +134 -101
- 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 +137 -5
- package/dist/shared/assistant/ui/assistantLiveAvatarSeam.js +114 -55
- 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/panelOverlays.d.ts +24 -3
- package/dist/shared/assistant/ui/panelOverlays.js +11 -10
- package/dist/shared/assistant/ui/voice/AssistantVoiceSession.d.ts +6 -0
- package/dist/shared/assistant/ui/voice/AssistantVoiceSession.js +172 -166
- 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.js +259 -254
- package/package.json +1 -1
|
@@ -1,290 +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 { useAvatarCopy as
|
|
8
|
-
import { ASSISTANT_PANEL_ATTR as
|
|
9
|
-
import { useLiveAvatarHandsFreeGuard as
|
|
10
|
-
import { AssistantAttachmentButton as
|
|
11
|
-
import { AssistantAttachmentChips as
|
|
12
|
-
import { AssistantVoiceOrb as
|
|
13
|
-
import { VoiceMiniController as
|
|
14
|
-
import { VoiceStage as
|
|
15
|
-
import { VoiceTranscriptDrawer as
|
|
16
|
-
import { escapeBelongsToLayerAbove as
|
|
17
|
-
import { HandsFreePrivacyNotice as
|
|
18
|
-
import { useCallback as
|
|
19
|
-
import { Maximize2 as
|
|
20
|
-
import { jsx as
|
|
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";
|
|
21
21
|
//#region src/shared/assistant/ui/voice/AssistantVoiceSession.tsx
|
|
22
|
-
var
|
|
23
|
-
let A = n(), { muted: j, error: M } =
|
|
24
|
-
|
|
25
|
-
let
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
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(() => {
|
|
36
|
+
G.current && (G.current = !1, K.current());
|
|
37
|
+
}, []), He = q;
|
|
38
|
+
o(() => {
|
|
33
39
|
let e = () => {
|
|
34
|
-
document.visibilityState === "hidden" ?
|
|
40
|
+
document.visibilityState === "hidden" ? q() : J();
|
|
35
41
|
};
|
|
36
42
|
return document.addEventListener("visibilitychange", e), () => document.removeEventListener("visibilitychange", e);
|
|
37
|
-
}, [
|
|
38
|
-
let e =
|
|
43
|
+
}, [q, J]), o(() => {
|
|
44
|
+
let e = J;
|
|
39
45
|
return window.addEventListener("focus", e), () => {
|
|
40
|
-
window.removeEventListener("focus", e),
|
|
46
|
+
window.removeEventListener("focus", e), G.current = !1;
|
|
41
47
|
};
|
|
42
|
-
}, []),
|
|
48
|
+
}, []), o(() => {
|
|
43
49
|
document.activeElement?.closest("[data-hands-free-notice]") || N.current?.focus();
|
|
44
|
-
}, []), e(P, { fallbackSelector: `[${
|
|
50
|
+
}, []), e(P, { fallbackSelector: `[${oe}]` }), o(() => {
|
|
45
51
|
let e = (e) => {
|
|
46
52
|
if (e.key === "Escape") {
|
|
47
|
-
let t =
|
|
53
|
+
let t = ve({
|
|
48
54
|
defaultPrevented: e.defaultPrevented,
|
|
49
|
-
layerAbove:
|
|
55
|
+
layerAbove: _e({
|
|
50
56
|
target: e.target,
|
|
51
57
|
session: P.current,
|
|
52
58
|
doc: document
|
|
53
59
|
}),
|
|
54
|
-
transcriptOpen:
|
|
60
|
+
transcriptOpen: H
|
|
55
61
|
});
|
|
56
62
|
if (t === "ignore") return;
|
|
57
|
-
e.preventDefault(), t === "close-transcript" ?
|
|
63
|
+
e.preventDefault(), t === "close-transcript" ? U(!1) : h ? h.decline() : W ? O?.onClose() : C();
|
|
58
64
|
return;
|
|
59
65
|
}
|
|
60
|
-
if (e.key !== "Tab" || !
|
|
61
|
-
let t = (
|
|
66
|
+
if (e.key !== "Tab" || !z) return;
|
|
67
|
+
let t = (H ? P.current?.querySelector("[data-testid=\"assistant-voice-transcript\"]") : P.current)?.querySelectorAll("button:not([disabled])");
|
|
62
68
|
if (!t || t.length === 0) return;
|
|
63
69
|
let n = t[0], r = t[t.length - 1];
|
|
64
70
|
!n || !r || (e.shiftKey && document.activeElement === n ? (e.preventDefault(), r.focus()) : !e.shiftKey && document.activeElement === r && (e.preventDefault(), n.focus()));
|
|
65
71
|
};
|
|
66
72
|
return window.addEventListener("keydown", e), () => window.removeEventListener("keydown", e);
|
|
67
73
|
}, [
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
74
|
+
C,
|
|
75
|
+
z,
|
|
76
|
+
H,
|
|
77
|
+
W,
|
|
78
|
+
O,
|
|
73
79
|
h
|
|
74
80
|
]);
|
|
75
|
-
let
|
|
76
|
-
letMeFinish:
|
|
77
|
-
imDone:
|
|
78
|
-
} : null,
|
|
79
|
-
|
|
80
|
-
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;
|
|
81
87
|
let e = document.activeElement;
|
|
82
88
|
(!e || e === document.body) && N.current?.focus();
|
|
83
|
-
}, [
|
|
84
|
-
let
|
|
85
|
-
snapshot:
|
|
86
|
-
capturing:
|
|
87
|
-
interrupting:
|
|
88
|
-
awaitingEndpoint:
|
|
89
|
-
}),
|
|
90
|
-
switch (
|
|
89
|
+
}, [We]);
|
|
90
|
+
let Q = te({
|
|
91
|
+
snapshot: f,
|
|
92
|
+
capturing: Ne,
|
|
93
|
+
interrupting: Pe,
|
|
94
|
+
awaitingEndpoint: Fe
|
|
95
|
+
}), Ge = (() => {
|
|
96
|
+
switch (Q) {
|
|
91
97
|
case "connecting": return A("voiceSession.connecting", "Starting the microphone…");
|
|
92
98
|
case "endpoint-grace": return A("voiceSession.endpointGrace", "Still listening — take your time");
|
|
93
99
|
case "interrupting": return A("voiceSession.interrupting", "Stopped — go ahead");
|
|
94
|
-
case "thinking": return A(
|
|
100
|
+
case "thinking": return A(i.key, i.fallback);
|
|
95
101
|
case "speaking": return A("voiceSession.speaking", "Speaking — tap to stop");
|
|
96
102
|
case "mic-error":
|
|
97
103
|
case "ended": return "";
|
|
98
104
|
case "listening": return j ? A("voiceSession.muted", "Microphone off") : A("voiceSession.listening", "Listening…");
|
|
99
|
-
default: return
|
|
105
|
+
default: return Q;
|
|
100
106
|
}
|
|
101
|
-
})(),
|
|
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({
|
|
102
108
|
tr: A,
|
|
103
|
-
stage:
|
|
109
|
+
stage: Q,
|
|
104
110
|
muted: j,
|
|
105
|
-
label:
|
|
106
|
-
}),
|
|
107
|
-
return /* @__PURE__ */
|
|
111
|
+
label: qe
|
|
112
|
+
}), Je = ne(qe, $), Ye = Q === "thinking";
|
|
113
|
+
return /* @__PURE__ */ d("div", {
|
|
108
114
|
ref: P,
|
|
109
|
-
className: `flex flex-col items-center justify-between bg-bg-sunken ${
|
|
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"}`,
|
|
110
116
|
role: "dialog",
|
|
111
|
-
"aria-modal":
|
|
117
|
+
"aria-modal": z || void 0,
|
|
112
118
|
"aria-label": A("voiceSession.title", "Voice conversation"),
|
|
113
119
|
"data-testid": "assistant-voice-session",
|
|
114
|
-
[
|
|
120
|
+
[se]: "",
|
|
115
121
|
children: [
|
|
116
|
-
/* @__PURE__ */
|
|
122
|
+
/* @__PURE__ */ d("button", {
|
|
117
123
|
ref: N,
|
|
118
124
|
type: "button",
|
|
119
|
-
onClick:
|
|
120
|
-
className: `absolute ${
|
|
125
|
+
onClick: C,
|
|
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`,
|
|
121
127
|
title: A("voiceSession.end", "End the voice conversation"),
|
|
122
128
|
"data-testid": "assistant-voice-end",
|
|
123
|
-
children: [/* @__PURE__ */
|
|
124
|
-
className:
|
|
129
|
+
children: [/* @__PURE__ */ u(l, {
|
|
130
|
+
className: z ? "size-6" : B ? "size-4" : "size-5",
|
|
125
131
|
"aria-hidden": "true"
|
|
126
|
-
}), /* @__PURE__ */
|
|
127
|
-
className: `truncate whitespace-nowrap font-medium ${
|
|
132
|
+
}), /* @__PURE__ */ u("span", {
|
|
133
|
+
className: `truncate whitespace-nowrap font-medium ${B ? "max-w-[3.5rem] text-xs" : "max-w-[7rem]"}`,
|
|
128
134
|
children: A("voiceSession.endShort", "End")
|
|
129
135
|
})]
|
|
130
136
|
}),
|
|
131
|
-
/* @__PURE__ */
|
|
132
|
-
className: `flex flex-col items-center ${
|
|
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" : ""}`}`,
|
|
133
139
|
children: [
|
|
134
|
-
|
|
140
|
+
Y ? /* @__PURE__ */ u("p", {
|
|
135
141
|
className: "max-w-xs text-center text-xs text-status-warning",
|
|
136
142
|
"data-testid": "assistant-voice-notice",
|
|
137
|
-
children:
|
|
143
|
+
children: p(m, A)
|
|
138
144
|
}) : null,
|
|
139
|
-
|
|
145
|
+
X ? /* @__PURE__ */ u("p", {
|
|
140
146
|
className: "max-w-xs text-center text-xs text-text-secondary",
|
|
141
147
|
"data-testid": "assistant-voice-avatar-hands-free",
|
|
142
|
-
children:
|
|
148
|
+
children: Ve.handsFreeOff
|
|
143
149
|
}) : null,
|
|
144
|
-
/* @__PURE__ */
|
|
150
|
+
/* @__PURE__ */ u("span", {
|
|
145
151
|
className: "sr-only start-0 top-0",
|
|
146
152
|
role: "status",
|
|
147
153
|
"aria-live": "polite",
|
|
148
154
|
"aria-atomic": "true",
|
|
149
155
|
"data-testid": "assistant-voice-notice-announced",
|
|
150
|
-
children:
|
|
156
|
+
children: Y && m === "reply-not-heard" ? p(m, A) : X ? Ve.handsFreeOff : null
|
|
151
157
|
}),
|
|
152
|
-
|
|
158
|
+
x ? /* @__PURE__ */ u("p", {
|
|
153
159
|
className: "max-w-xs text-center text-xs text-status-warning",
|
|
154
160
|
role: "status",
|
|
155
161
|
"aria-live": "polite",
|
|
156
162
|
"data-testid": "assistant-voice-attachment-notice",
|
|
157
|
-
children:
|
|
163
|
+
children: x
|
|
158
164
|
}) : null
|
|
159
165
|
]
|
|
160
166
|
}),
|
|
161
167
|
(() => {
|
|
162
|
-
let e = /* @__PURE__ */
|
|
163
|
-
session:
|
|
164
|
-
compact:
|
|
165
|
-
connecting:
|
|
166
|
-
onPress: r(
|
|
167
|
-
label: r(
|
|
168
|
-
}), t =
|
|
168
|
+
let e = /* @__PURE__ */ u(pe, {
|
|
169
|
+
session: f,
|
|
170
|
+
compact: B,
|
|
171
|
+
connecting: Q === "connecting",
|
|
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", {
|
|
169
175
|
type: "button",
|
|
170
|
-
onClick:
|
|
171
|
-
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 ${
|
|
172
|
-
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”"),
|
|
173
179
|
"data-testid": "assistant-voice-hold",
|
|
174
|
-
"data-holding":
|
|
175
|
-
children:
|
|
176
|
-
}) : 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", {
|
|
177
183
|
className: "flex flex-col items-center gap-2",
|
|
178
184
|
children: [e, t]
|
|
179
|
-
}) : e,
|
|
180
|
-
return
|
|
181
|
-
spokenChunks:
|
|
182
|
-
state:
|
|
183
|
-
caption:
|
|
184
|
-
statusText:
|
|
185
|
-
statusSuffix:
|
|
186
|
-
rotateStatus:
|
|
187
|
-
errorText:
|
|
185
|
+
}) : e, te = ee(Q) ? g : Ue || null, i = M === null ? null : we(M, A);
|
|
186
|
+
return B ? /* @__PURE__ */ u(me, {
|
|
187
|
+
spokenChunks: S,
|
|
188
|
+
state: Q,
|
|
189
|
+
caption: te,
|
|
190
|
+
statusText: Je,
|
|
191
|
+
statusSuffix: $,
|
|
192
|
+
rotateStatus: Ye,
|
|
193
|
+
errorText: i,
|
|
188
194
|
control: n
|
|
189
|
-
}) : /* @__PURE__ */
|
|
190
|
-
state:
|
|
191
|
-
userCaption:
|
|
192
|
-
spokenChunks:
|
|
195
|
+
}) : /* @__PURE__ */ u(he, {
|
|
196
|
+
state: Q,
|
|
197
|
+
userCaption: Ue || null,
|
|
198
|
+
spokenChunks: S,
|
|
193
199
|
assistantCaption: g,
|
|
194
|
-
expanded:
|
|
195
|
-
statusText:
|
|
196
|
-
statusSuffix:
|
|
197
|
-
rotateStatus:
|
|
198
|
-
errorText:
|
|
200
|
+
expanded: z,
|
|
201
|
+
statusText: Je,
|
|
202
|
+
statusSuffix: $,
|
|
203
|
+
rotateStatus: Ye,
|
|
204
|
+
errorText: i,
|
|
199
205
|
control: n
|
|
200
206
|
});
|
|
201
207
|
})(),
|
|
202
|
-
|
|
203
|
-
className:
|
|
204
|
-
children: /* @__PURE__ */
|
|
208
|
+
D && !W ? /* @__PURE__ */ u("div", {
|
|
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)]"}`,
|
|
210
|
+
children: /* @__PURE__ */ u("button", {
|
|
205
211
|
type: "button",
|
|
206
212
|
onClick: () => {
|
|
207
|
-
|
|
213
|
+
I("panel"), D.onOpen();
|
|
208
214
|
},
|
|
209
|
-
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 ${
|
|
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"}`,
|
|
210
216
|
"data-testid": "assistant-voice-proposal-chip",
|
|
211
|
-
children:
|
|
217
|
+
children: D.label
|
|
212
218
|
})
|
|
213
219
|
}) : null,
|
|
214
|
-
|
|
215
|
-
className: `absolute z-10 flex flex-col gap-2 overflow-y-auto rounded-lg border border-border-subtle bg-bg-elevated shadow-lg ${
|
|
220
|
+
O && W ? /* @__PURE__ */ d("div", {
|
|
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"}`,
|
|
216
222
|
"data-testid": "assistant-voice-proposal-tray",
|
|
217
|
-
children: [/* @__PURE__ */
|
|
223
|
+
children: [/* @__PURE__ */ u("div", {
|
|
218
224
|
className: "flex justify-end",
|
|
219
|
-
children: /* @__PURE__ */
|
|
225
|
+
children: /* @__PURE__ */ u("button", {
|
|
220
226
|
type: "button",
|
|
221
|
-
onClick:
|
|
227
|
+
onClick: O.onClose,
|
|
222
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",
|
|
223
|
-
"aria-label":
|
|
229
|
+
"aria-label": O.closeLabel,
|
|
224
230
|
"data-testid": "assistant-voice-proposal-tray-close",
|
|
225
|
-
children: /* @__PURE__ */
|
|
231
|
+
children: /* @__PURE__ */ u(l, {
|
|
226
232
|
className: "size-4",
|
|
227
233
|
"aria-hidden": "true"
|
|
228
234
|
})
|
|
229
235
|
})
|
|
230
|
-
}),
|
|
236
|
+
}), O.content]
|
|
231
237
|
}) : null,
|
|
232
|
-
h ? /* @__PURE__ */
|
|
233
|
-
view:
|
|
238
|
+
h ? /* @__PURE__ */ u(ye, {
|
|
239
|
+
view: R,
|
|
234
240
|
onContinue: h.accept,
|
|
235
241
|
onNotNow: h.decline
|
|
236
242
|
}) : null,
|
|
237
|
-
|
|
238
|
-
turns:
|
|
239
|
-
onClose: () =>
|
|
240
|
-
onSave:
|
|
241
|
-
onContinueInChat:
|
|
242
|
-
renderAfterTurn:
|
|
243
|
+
H ? /* @__PURE__ */ u(ge, {
|
|
244
|
+
turns: Te,
|
|
245
|
+
onClose: () => U(!1),
|
|
246
|
+
onSave: Ee,
|
|
247
|
+
onContinueInChat: De,
|
|
248
|
+
renderAfterTurn: Le
|
|
243
249
|
}) : null,
|
|
244
|
-
y ? /* @__PURE__ */
|
|
245
|
-
className: `absolute ${
|
|
246
|
-
children: /* @__PURE__ */
|
|
250
|
+
y ? /* @__PURE__ */ u("div", {
|
|
251
|
+
className: `absolute ${z ? "left-6 top-6" : B ? "left-11 top-2" : "left-3 top-3"}`,
|
|
252
|
+
children: /* @__PURE__ */ u(de, {
|
|
247
253
|
onFiles: (e) => {
|
|
248
|
-
y(e),
|
|
254
|
+
y(e), I((e) => e === "mini" ? "panel" : e);
|
|
249
255
|
},
|
|
250
|
-
onPickerOpen:
|
|
256
|
+
onPickerOpen: He,
|
|
251
257
|
direction: "down",
|
|
252
|
-
canAddMore:
|
|
253
|
-
disabled:
|
|
258
|
+
canAddMore: je,
|
|
259
|
+
disabled: b
|
|
254
260
|
})
|
|
255
261
|
}) : null,
|
|
256
|
-
(v.length > 0 ||
|
|
257
|
-
className: `absolute ${
|
|
262
|
+
(v.length > 0 || Me > 0) && !B ? /* @__PURE__ */ u("div", {
|
|
263
|
+
className: `absolute ${z ? "bottom-24 left-24 right-24" : "bottom-16 left-16 right-16"}`,
|
|
258
264
|
"data-testid": "assistant-voice-attachments",
|
|
259
|
-
children: /* @__PURE__ */
|
|
265
|
+
children: /* @__PURE__ */ u(fe, {
|
|
260
266
|
attachments: v,
|
|
261
|
-
onRemove:
|
|
262
|
-
onRetry:
|
|
263
|
-
preparingCount:
|
|
264
|
-
disabled:
|
|
267
|
+
onRemove: ke ?? (() => void 0),
|
|
268
|
+
onRetry: Ae ?? (() => void 0),
|
|
269
|
+
preparingCount: Me,
|
|
270
|
+
disabled: b
|
|
265
271
|
})
|
|
266
272
|
}) : null,
|
|
267
|
-
/* @__PURE__ */
|
|
273
|
+
/* @__PURE__ */ u("button", {
|
|
268
274
|
type: "button",
|
|
269
|
-
onClick: () =>
|
|
270
|
-
className: `absolute ${
|
|
271
|
-
"aria-pressed":
|
|
275
|
+
onClick: () => U((e) => !e),
|
|
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`,
|
|
277
|
+
"aria-pressed": H,
|
|
272
278
|
"aria-label": A("voiceSession.transcriptTitle", "Voice transcript"),
|
|
273
279
|
"data-testid": "assistant-voice-transcript-toggle",
|
|
274
|
-
children: /* @__PURE__ */
|
|
280
|
+
children: /* @__PURE__ */ u(Ce, { className: z ? "size-6" : B ? "size-4" : "size-5" })
|
|
275
281
|
}),
|
|
276
|
-
/* @__PURE__ */
|
|
282
|
+
/* @__PURE__ */ u("button", {
|
|
277
283
|
type: "button",
|
|
278
|
-
onClick: () =>
|
|
279
|
-
className: `absolute ${
|
|
280
|
-
"aria-label":
|
|
284
|
+
onClick: () => I(V),
|
|
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`,
|
|
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"),
|
|
281
287
|
"data-testid": "assistant-voice-expand",
|
|
282
|
-
children:
|
|
288
|
+
children: z ? /* @__PURE__ */ u(Se, { className: "size-5" }) : /* @__PURE__ */ u(xe, { className: B ? "size-4" : "size-5" })
|
|
283
289
|
})
|
|
284
290
|
]
|
|
285
291
|
});
|
|
286
292
|
};
|
|
287
|
-
function
|
|
293
|
+
function p(e, t) {
|
|
288
294
|
switch (e) {
|
|
289
295
|
case "network": return t("voiceSession.noticeNetwork", "Speech recognition lost its connection. Check your network — it will retry.");
|
|
290
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.");
|
|
@@ -296,7 +302,7 @@ function Se(e, t) {
|
|
|
296
302
|
default: return e;
|
|
297
303
|
}
|
|
298
304
|
}
|
|
299
|
-
function
|
|
305
|
+
function we(e, t) {
|
|
300
306
|
switch (e) {
|
|
301
307
|
case "mic-denied": return t("voiceSession.micDenied", "Microphone access is blocked. Allow it in your browser settings to talk.");
|
|
302
308
|
case "no-speech-support": return t("voiceSession.noSpeechSupport", "This browser cannot listen. Try a different browser, or type instead.");
|
|
@@ -305,4 +311,4 @@ function Ce(e, t) {
|
|
|
305
311
|
}
|
|
306
312
|
}
|
|
307
313
|
//#endregion
|
|
308
|
-
export {
|
|
314
|
+
export { f as AssistantVoiceSession };
|
|
@@ -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 };
|