@burdenoff/fe-libs 2026.1007.2 → 2026.1007.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/shared/assistant/i18nManifest.d.ts +3 -0
- package/dist/shared/assistant/i18nManifest.d.ts.map +1 -1
- package/dist/shared/assistant/i18nManifest.js +3 -0
- package/dist/shared/assistant/index.d.ts +2 -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 +19 -8
- package/dist/shared/assistant/ui/AssistantChatArea.d.ts.map +1 -1
- package/dist/shared/assistant/ui/AssistantChatArea.js +1070 -1067
- package/dist/shared/assistant/ui/useVoiceSession.d.ts +14 -1
- package/dist/shared/assistant/ui/useVoiceSession.d.ts.map +1 -1
- package/dist/shared/assistant/ui/useVoiceSession.js +241 -233
- package/dist/shared/assistant/ui/voice/AssistantVoiceSession.d.ts +7 -0
- package/dist/shared/assistant/ui/voice/AssistantVoiceSession.d.ts.map +1 -1
- package/dist/shared/assistant/ui/voice/AssistantVoiceSession.js +137 -130
- package/dist/shared/assistant/ui/voice/HandsFreePrivacyNotice.d.ts +27 -0
- package/dist/shared/assistant/ui/voice/HandsFreePrivacyNotice.d.ts.map +1 -0
- package/dist/shared/assistant/ui/voice/HandsFreePrivacyNotice.js +52 -0
- package/dist/shared/assistant/voice/handsfree/backendStreamTransport.d.ts +29 -6
- package/dist/shared/assistant/voice/handsfree/backendStreamTransport.d.ts.map +1 -1
- package/dist/shared/assistant/voice/handsfree/backendStreamTransport.js +138 -63
- package/dist/shared/assistant/voice/handsfree/handsFreeController.d.ts +7 -1
- package/dist/shared/assistant/voice/handsfree/handsFreeController.d.ts.map +1 -1
- package/dist/shared/assistant/voice/handsfree/handsFreeRuntime.d.ts +18 -10
- package/dist/shared/assistant/voice/handsfree/handsFreeRuntime.d.ts.map +1 -1
- package/dist/shared/assistant/voice/handsfree/handsFreeRuntime.js +46 -57
- package/dist/shared/assistant/voice/handsfree/streamingConfig.d.ts +103 -0
- package/dist/shared/assistant/voice/handsfree/streamingConfig.d.ts.map +1 -0
- package/dist/shared/assistant/voice/handsfree/streamingConfig.js +71 -0
- package/dist/shared/assistant/voice/handsfree/sttTransport.d.ts +12 -7
- package/dist/shared/assistant/voice/handsfree/sttTransport.d.ts.map +1 -1
- package/dist/shared/assistant/voice/handsfree/sttTransport.js +1 -1
- package/dist/shared/assistant/voice/handsfree/useHandsFreeInterrupt.d.ts +23 -1
- package/dist/shared/assistant/voice/handsfree/useHandsFreeInterrupt.d.ts.map +1 -1
- package/dist/shared/assistant/voice/handsfree/useHandsFreeInterrupt.js +63 -50
- package/dist/shared-assistant.js +189 -187
- package/package.json +3 -3
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { FC, ReactNode } from 'react';
|
|
2
2
|
import { AssistantAttachment } from '../../attachments';
|
|
3
|
+
import { HandsFreePrivacyNoticeActions } from '../../voice/handsfree/useHandsFreeInterrupt';
|
|
3
4
|
import { VoiceSessionSnapshot } from '../../voice/voiceSession';
|
|
4
5
|
import { VoiceSessionNotice } from '../useVoiceSession';
|
|
5
6
|
import { VoiceTranscriptTurn } from '../../voice/turnVisibility';
|
|
@@ -17,6 +18,12 @@ interface Props {
|
|
|
17
18
|
onInterrupt?: () => void;
|
|
18
19
|
/** A recoverable problem to surface. Null when the microphone is healthy. */
|
|
19
20
|
notice?: VoiceSessionNotice | null;
|
|
21
|
+
/**
|
|
22
|
+
* ★ BOFF-8613 H3: the backend speech stream's privacy notice, while it must
|
|
23
|
+
* be answered before the microphone opens. Null otherwise (always, unless an
|
|
24
|
+
* app configured the stream).
|
|
25
|
+
*/
|
|
26
|
+
privacyNotice?: HandsFreePrivacyNoticeActions | null;
|
|
20
27
|
/** The assistant's last reply, captioned while it is spoken. */
|
|
21
28
|
spoken: string | null;
|
|
22
29
|
onToggleMute: () => void;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"AssistantVoiceSession.d.ts","sourceRoot":"","sources":["../../../../../src/shared/assistant/ui/voice/AssistantVoiceSession.tsx"],"names":[],"mappings":"AAAA,OAAO,EAML,KAAK,EAAE,EACP,KAAK,SAAS,EACf,MAAM,OAAO,CAAC;AAMf,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,mBAAmB,CAAC;
|
|
1
|
+
{"version":3,"file":"AssistantVoiceSession.d.ts","sourceRoot":"","sources":["../../../../../src/shared/assistant/ui/voice/AssistantVoiceSession.tsx"],"names":[],"mappings":"AAAA,OAAO,EAML,KAAK,EAAE,EACP,KAAK,SAAS,EACf,MAAM,OAAO,CAAC;AAMf,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,mBAAmB,CAAC;AAS7D,OAAO,KAAK,EAAE,6BAA6B,EAAE,MAAM,6CAA6C,CAAC;AAqBjG,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;;;;OAIG;IACH,aAAa,CAAC,EAAE,6BAA6B,GAAG,IAAI,CAAC;IACrD,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,CA41B3C,CAAC"}
|
|
@@ -12,245 +12,252 @@ import { VoiceMiniController as ce } from "./VoiceMiniController.js";
|
|
|
12
12
|
import { VoiceStage as le } from "./VoiceStage.js";
|
|
13
13
|
import { VoiceTranscriptDrawer as ue } from "./VoiceTranscriptDrawer.js";
|
|
14
14
|
import { escapeBelongsToLayerAbove as de, voiceSessionEscapeAction as fe } from "./voiceSessionEscape.js";
|
|
15
|
-
import {
|
|
16
|
-
import {
|
|
15
|
+
import { HandsFreePrivacyNotice as pe } from "./HandsFreePrivacyNotice.js";
|
|
16
|
+
import { useCallback as s, useEffect as c, useMemo as me, useRef as l, useState as u } from "react";
|
|
17
|
+
import { Maximize2 as he, Minimize2 as ge, ScrollText as _e, X as d } from "lucide-react";
|
|
17
18
|
import { jsx as f, jsxs as p } from "react/jsx-runtime";
|
|
18
19
|
//#region src/shared/assistant/ui/voice/AssistantVoiceSession.tsx
|
|
19
|
-
var m = ({ session: m, turns:
|
|
20
|
-
let
|
|
21
|
-
t("assistant.transcript",
|
|
22
|
-
let
|
|
23
|
-
|
|
24
|
-
let
|
|
25
|
-
m.phase !== "listening" && m.phase !== "thinking" ||
|
|
26
|
-
}, [
|
|
27
|
-
|
|
28
|
-
}, []),
|
|
20
|
+
var m = ({ session: m, turns: be = [], onSaveTranscript: xe, onContinueInChat: Se, notice: h = null, privacyNotice: g = null, spoken: _, onInterrupt: Ce, onToggleMute: v, attachments: y = [], onAttachFiles: b, onRemoveAttachment: we, onRetryAttachment: Te, canAttachMore: Ee = !0, preparingAttachments: x = 0, spokenChunks: S = null, onEnd: C, capturing: De = !0, interrupting: Oe = !1, awaitingEndpoint: ke = !1, holding: w = !1, correcting: Ae = !1, onLetMeFinish: T, onImDone: E, proposalChip: D = null, proposalTray: O = null }) => {
|
|
21
|
+
let k = n(), { muted: A, error: j } = m, M = l(null), N = l(null), [P, F] = u("mini"), I = P === "full", L = P === "mini", R = P === "mini" ? "panel" : P === "panel" ? "full" : "mini", [z, B] = u(!1);
|
|
22
|
+
t("assistant.transcript", me(() => ({ run: () => z ? { status: "already" } : (B(!0), { status: "done" }) }), [z]));
|
|
23
|
+
let V = O !== null && !L, H = l(!1), U = l(v);
|
|
24
|
+
U.current = v;
|
|
25
|
+
let W = s(() => {
|
|
26
|
+
m.phase !== "listening" && m.phase !== "thinking" || A || H.current || o(m) || (H.current = !0, U.current());
|
|
27
|
+
}, [A, m]), G = s(() => {
|
|
28
|
+
H.current && (H.current = !1, U.current());
|
|
29
|
+
}, []), je = W;
|
|
29
30
|
c(() => {
|
|
30
31
|
let e = () => {
|
|
31
|
-
document.visibilityState === "hidden" ?
|
|
32
|
+
document.visibilityState === "hidden" ? W() : G();
|
|
32
33
|
};
|
|
33
34
|
return document.addEventListener("visibilitychange", e), () => document.removeEventListener("visibilitychange", e);
|
|
34
|
-
}, [
|
|
35
|
-
let e =
|
|
35
|
+
}, [W, G]), c(() => {
|
|
36
|
+
let e = G;
|
|
36
37
|
return window.addEventListener("focus", e), () => {
|
|
37
|
-
window.removeEventListener("focus", e),
|
|
38
|
+
window.removeEventListener("focus", e), H.current = !1;
|
|
38
39
|
};
|
|
39
40
|
}, []), c(() => {
|
|
40
|
-
|
|
41
|
-
}, []), e(
|
|
41
|
+
document.activeElement?.closest("[data-hands-free-notice]") || M.current?.focus();
|
|
42
|
+
}, []), e(N, { fallbackSelector: `[${ae}]` }), c(() => {
|
|
42
43
|
let e = (e) => {
|
|
43
44
|
if (e.key === "Escape") {
|
|
44
45
|
let t = fe({
|
|
45
46
|
defaultPrevented: e.defaultPrevented,
|
|
46
47
|
layerAbove: de({
|
|
47
48
|
target: e.target,
|
|
48
|
-
session:
|
|
49
|
+
session: N.current,
|
|
49
50
|
doc: document
|
|
50
51
|
}),
|
|
51
|
-
transcriptOpen:
|
|
52
|
+
transcriptOpen: z
|
|
52
53
|
});
|
|
53
54
|
if (t === "ignore") return;
|
|
54
|
-
e.preventDefault(), t === "close-transcript" ?
|
|
55
|
+
e.preventDefault(), t === "close-transcript" ? B(!1) : g ? g.decline() : V ? O?.onClose() : C();
|
|
55
56
|
return;
|
|
56
57
|
}
|
|
57
|
-
if (e.key !== "Tab" || !
|
|
58
|
-
let t = (
|
|
58
|
+
if (e.key !== "Tab" || !I) return;
|
|
59
|
+
let t = (z ? N.current?.querySelector("[data-testid=\"assistant-voice-transcript\"]") : N.current)?.querySelectorAll("button:not([disabled])");
|
|
59
60
|
if (!t || t.length === 0) return;
|
|
60
61
|
let n = t[0], r = t[t.length - 1];
|
|
61
62
|
!n || !r || (e.shiftKey && document.activeElement === n ? (e.preventDefault(), r.focus()) : !e.shiftKey && document.activeElement === r && (e.preventDefault(), n.focus()));
|
|
62
63
|
};
|
|
63
64
|
return window.addEventListener("keydown", e), () => window.removeEventListener("keydown", e);
|
|
64
65
|
}, [
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
66
|
+
C,
|
|
67
|
+
I,
|
|
68
|
+
z,
|
|
69
|
+
V,
|
|
70
|
+
O,
|
|
71
|
+
g
|
|
70
72
|
]);
|
|
71
|
-
let
|
|
72
|
-
letMeFinish:
|
|
73
|
-
imDone:
|
|
74
|
-
} : null,
|
|
73
|
+
let K = h !== null && j === null, q = o(m), J = T && E && m.phase === "listening" && !A && j === null ? {
|
|
74
|
+
letMeFinish: T,
|
|
75
|
+
imDone: E
|
|
76
|
+
} : null, Y = J !== null;
|
|
75
77
|
c(() => {
|
|
76
|
-
if (
|
|
78
|
+
if (Y) return;
|
|
77
79
|
let e = document.activeElement;
|
|
78
|
-
(!e || e === document.body) &&
|
|
79
|
-
}, [
|
|
80
|
-
let
|
|
80
|
+
(!e || e === document.body) && M.current?.focus();
|
|
81
|
+
}, [Y]);
|
|
82
|
+
let X = i({
|
|
81
83
|
snapshot: m,
|
|
82
|
-
capturing:
|
|
83
|
-
interrupting:
|
|
84
|
-
awaitingEndpoint:
|
|
85
|
-
}),
|
|
86
|
-
switch (
|
|
87
|
-
case "connecting": return
|
|
88
|
-
case "endpoint-grace": return
|
|
89
|
-
case "interrupting": return
|
|
90
|
-
case "thinking": return
|
|
91
|
-
case "speaking": return
|
|
84
|
+
capturing: De,
|
|
85
|
+
interrupting: Oe,
|
|
86
|
+
awaitingEndpoint: ke
|
|
87
|
+
}), Me = (() => {
|
|
88
|
+
switch (X) {
|
|
89
|
+
case "connecting": return k("voiceSession.connecting", "Starting the microphone…");
|
|
90
|
+
case "endpoint-grace": return k("voiceSession.endpointGrace", "Still listening — take your time");
|
|
91
|
+
case "interrupting": return k("voiceSession.interrupting", "Stopped — go ahead");
|
|
92
|
+
case "thinking": return k(a.key, a.fallback);
|
|
93
|
+
case "speaking": return k("voiceSession.speaking", "Speaking — tap to stop");
|
|
92
94
|
case "mic-error":
|
|
93
95
|
case "ended": return "";
|
|
94
|
-
case "listening": return
|
|
95
|
-
default: return
|
|
96
|
+
case "listening": return A ? k("voiceSession.muted", "Microphone off") : k("voiceSession.listening", "Listening…");
|
|
97
|
+
default: return X;
|
|
96
98
|
}
|
|
97
|
-
})(),
|
|
98
|
-
tr:
|
|
99
|
-
stage:
|
|
100
|
-
muted:
|
|
101
|
-
label:
|
|
102
|
-
}),
|
|
99
|
+
})(), Z = !A && (X === "listening" || X === "endpoint-grace"), Q = Z && w ? k("voiceSession.holding", "Take your time — tap “I’m done” when you finish") : Z && Ae ? k("voiceSession.correcting", "Stopped that answer — listening to your correction") : Me, $ = ne({
|
|
100
|
+
tr: k,
|
|
101
|
+
stage: X,
|
|
102
|
+
muted: A,
|
|
103
|
+
label: Q
|
|
104
|
+
}), Ne = te(Q, $), Pe = X === "thinking";
|
|
103
105
|
return /* @__PURE__ */ p("div", {
|
|
104
|
-
ref:
|
|
105
|
-
className: `flex flex-col items-center justify-between bg-bg-sunken ${
|
|
106
|
+
ref: N,
|
|
107
|
+
className: `flex flex-col items-center justify-between bg-bg-sunken ${P === "full" ? "fixed inset-x-0 bottom-0 top-14 z-[60] px-6 py-8" : P === "panel" ? "absolute inset-0 z-20 px-4 py-6" : "absolute inset-x-0 bottom-0 z-20 h-[11.25rem] border-t border-border-subtle px-3 py-3 shadow-lg"}`,
|
|
106
108
|
role: "dialog",
|
|
107
|
-
"aria-modal":
|
|
108
|
-
"aria-label":
|
|
109
|
+
"aria-modal": I || void 0,
|
|
110
|
+
"aria-label": k("voiceSession.title", "Voice conversation"),
|
|
109
111
|
"data-testid": "assistant-voice-session",
|
|
110
112
|
[oe]: "",
|
|
111
113
|
children: [
|
|
112
114
|
/* @__PURE__ */ p("button", {
|
|
113
|
-
ref:
|
|
115
|
+
ref: M,
|
|
114
116
|
type: "button",
|
|
115
|
-
onClick:
|
|
116
|
-
className: `absolute ${
|
|
117
|
-
title:
|
|
117
|
+
onClick: C,
|
|
118
|
+
className: `absolute ${I ? "right-6 top-6 h-14 gap-2 px-5 text-base" : L ? "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`,
|
|
119
|
+
title: k("voiceSession.end", "End the voice conversation"),
|
|
118
120
|
"data-testid": "assistant-voice-end",
|
|
119
121
|
children: [/* @__PURE__ */ f(d, {
|
|
120
|
-
className:
|
|
122
|
+
className: I ? "size-6" : L ? "size-4" : "size-5",
|
|
121
123
|
"aria-hidden": "true"
|
|
122
124
|
}), /* @__PURE__ */ f("span", {
|
|
123
|
-
className: `truncate whitespace-nowrap font-medium ${
|
|
124
|
-
children:
|
|
125
|
+
className: `truncate whitespace-nowrap font-medium ${L ? "max-w-[3.5rem] text-xs" : "max-w-[7rem]"}`,
|
|
126
|
+
children: k("voiceSession.endShort", "End")
|
|
125
127
|
})]
|
|
126
128
|
}),
|
|
127
129
|
/* @__PURE__ */ f("div", {
|
|
128
|
-
className: `flex flex-col items-center ${
|
|
129
|
-
children:
|
|
130
|
+
className: `flex flex-col items-center ${L ? "px-3" : `min-h-[1.5rem] ${K ? I ? "pt-14" : "pt-10" : ""}`}`,
|
|
131
|
+
children: K ? /* @__PURE__ */ f("p", {
|
|
130
132
|
className: "max-w-xs text-center text-xs text-status-warning",
|
|
131
133
|
"data-testid": "assistant-voice-notice",
|
|
132
|
-
children:
|
|
134
|
+
children: ve(h, k)
|
|
133
135
|
}) : null
|
|
134
136
|
}),
|
|
135
137
|
(() => {
|
|
136
138
|
let e = /* @__PURE__ */ f(se, {
|
|
137
139
|
session: m,
|
|
138
|
-
compact:
|
|
139
|
-
connecting:
|
|
140
|
-
onPress: r(
|
|
141
|
-
label: r(
|
|
142
|
-
}), t =
|
|
140
|
+
compact: L,
|
|
141
|
+
connecting: X === "connecting",
|
|
142
|
+
onPress: r(X) ? Ce : v,
|
|
143
|
+
label: r(X) ? k("voiceSession.interrupt", "Stop the assistant and speak") : A ? k("voiceSession.unmute", "Turn the microphone on") : k("voiceSession.mute", "Turn the microphone off")
|
|
144
|
+
}), t = J ? /* @__PURE__ */ f("button", {
|
|
143
145
|
type: "button",
|
|
144
|
-
onClick:
|
|
145
|
-
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 ${
|
|
146
|
-
title:
|
|
146
|
+
onClick: w ? J.imDone : J.letMeFinish,
|
|
147
|
+
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 ${L ? "h-7 px-3 text-xs" : I ? "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"}`,
|
|
148
|
+
title: w ? k("voiceSession.imDoneHint", "Send what you said now") : k("voiceSession.letMeFinishHint", "Pause sending until you tap “I’m done”"),
|
|
147
149
|
"data-testid": "assistant-voice-hold",
|
|
148
|
-
"data-holding":
|
|
149
|
-
children:
|
|
150
|
+
"data-holding": w ? "true" : "false",
|
|
151
|
+
children: w ? k("voiceSession.imDone", "I’m done") : k("voiceSession.letMeFinish", "Let me finish")
|
|
150
152
|
}) : null, n = t ? /* @__PURE__ */ p("div", {
|
|
151
153
|
className: "flex flex-col items-center gap-2",
|
|
152
154
|
children: [e, t]
|
|
153
|
-
}) : e, i = ee(
|
|
154
|
-
return
|
|
155
|
-
spokenChunks:
|
|
156
|
-
state:
|
|
155
|
+
}) : e, i = ee(X) ? _ : q || null, a = j === null ? null : ye(j, k);
|
|
156
|
+
return L ? /* @__PURE__ */ f(ce, {
|
|
157
|
+
spokenChunks: S,
|
|
158
|
+
state: X,
|
|
157
159
|
caption: i,
|
|
158
|
-
statusText:
|
|
159
|
-
statusSuffix:
|
|
160
|
-
rotateStatus:
|
|
160
|
+
statusText: Ne,
|
|
161
|
+
statusSuffix: $,
|
|
162
|
+
rotateStatus: Pe,
|
|
161
163
|
errorText: a,
|
|
162
164
|
control: n
|
|
163
165
|
}) : /* @__PURE__ */ f(le, {
|
|
164
|
-
state:
|
|
165
|
-
userCaption:
|
|
166
|
-
spokenChunks:
|
|
167
|
-
assistantCaption:
|
|
168
|
-
expanded:
|
|
169
|
-
statusText:
|
|
170
|
-
statusSuffix:
|
|
171
|
-
rotateStatus:
|
|
166
|
+
state: X,
|
|
167
|
+
userCaption: q || null,
|
|
168
|
+
spokenChunks: S,
|
|
169
|
+
assistantCaption: _,
|
|
170
|
+
expanded: I,
|
|
171
|
+
statusText: Ne,
|
|
172
|
+
statusSuffix: $,
|
|
173
|
+
rotateStatus: Pe,
|
|
172
174
|
errorText: a,
|
|
173
175
|
control: n
|
|
174
176
|
});
|
|
175
177
|
})(),
|
|
176
|
-
|
|
177
|
-
className:
|
|
178
|
+
D && !V ? /* @__PURE__ */ f("div", {
|
|
179
|
+
className: L ? "absolute left-20 right-36 top-2 flex justify-center" : `flex w-full justify-center ${I ? "max-w-[calc(100%-12rem)]" : "max-w-[calc(100%-8rem)]"}`,
|
|
178
180
|
children: /* @__PURE__ */ f("button", {
|
|
179
181
|
type: "button",
|
|
180
182
|
onClick: () => {
|
|
181
|
-
|
|
183
|
+
F("panel"), D.onOpen();
|
|
182
184
|
},
|
|
183
|
-
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 ${
|
|
185
|
+
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 ${L ? "h-8 px-3 text-xs" : "h-10 px-4 text-sm"}`,
|
|
184
186
|
"data-testid": "assistant-voice-proposal-chip",
|
|
185
|
-
children:
|
|
187
|
+
children: D.label
|
|
186
188
|
})
|
|
187
189
|
}) : null,
|
|
188
|
-
|
|
189
|
-
className: `absolute z-10 flex flex-col gap-2 overflow-y-auto rounded-lg border border-border-subtle bg-bg-elevated shadow-lg ${
|
|
190
|
+
O && V ? /* @__PURE__ */ p("div", {
|
|
191
|
+
className: `absolute z-10 flex flex-col gap-2 overflow-y-auto rounded-lg border border-border-subtle bg-bg-elevated shadow-lg ${I ? "inset-x-6 bottom-24 top-24 mx-auto max-w-xl p-4" : "inset-x-3 bottom-16 top-16 p-3"}`,
|
|
190
192
|
"data-testid": "assistant-voice-proposal-tray",
|
|
191
193
|
children: [/* @__PURE__ */ f("div", {
|
|
192
194
|
className: "flex justify-end",
|
|
193
195
|
children: /* @__PURE__ */ f("button", {
|
|
194
196
|
type: "button",
|
|
195
|
-
onClick:
|
|
197
|
+
onClick: O.onClose,
|
|
196
198
|
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",
|
|
197
|
-
"aria-label":
|
|
199
|
+
"aria-label": O.closeLabel,
|
|
198
200
|
"data-testid": "assistant-voice-proposal-tray-close",
|
|
199
201
|
children: /* @__PURE__ */ f(d, {
|
|
200
202
|
className: "size-4",
|
|
201
203
|
"aria-hidden": "true"
|
|
202
204
|
})
|
|
203
205
|
})
|
|
204
|
-
}),
|
|
206
|
+
}), O.content]
|
|
205
207
|
}) : null,
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
onContinueInChat: xe
|
|
208
|
+
g ? /* @__PURE__ */ f(pe, {
|
|
209
|
+
view: P,
|
|
210
|
+
onContinue: g.accept,
|
|
211
|
+
onNotNow: g.decline
|
|
211
212
|
}) : null,
|
|
212
|
-
|
|
213
|
-
|
|
213
|
+
z ? /* @__PURE__ */ f(ue, {
|
|
214
|
+
turns: be,
|
|
215
|
+
onClose: () => B(!1),
|
|
216
|
+
onSave: xe,
|
|
217
|
+
onContinueInChat: Se
|
|
218
|
+
}) : null,
|
|
219
|
+
b ? /* @__PURE__ */ f("div", {
|
|
220
|
+
className: `absolute ${I ? "left-6 top-6" : L ? "left-11 top-2" : "left-3 top-3"}`,
|
|
214
221
|
children: /* @__PURE__ */ f(re, {
|
|
215
222
|
onFiles: (e) => {
|
|
216
|
-
|
|
223
|
+
b(e), F((e) => e === "mini" ? "panel" : e);
|
|
217
224
|
},
|
|
218
|
-
onPickerOpen:
|
|
225
|
+
onPickerOpen: je,
|
|
219
226
|
direction: "down",
|
|
220
|
-
canAddMore:
|
|
227
|
+
canAddMore: Ee
|
|
221
228
|
})
|
|
222
229
|
}) : null,
|
|
223
|
-
(
|
|
224
|
-
className: `absolute ${
|
|
230
|
+
(y.length > 0 || x > 0) && !L ? /* @__PURE__ */ f("div", {
|
|
231
|
+
className: `absolute ${I ? "bottom-24 left-24 right-24" : "bottom-16 left-16 right-16"}`,
|
|
225
232
|
"data-testid": "assistant-voice-attachments",
|
|
226
233
|
children: /* @__PURE__ */ f(ie, {
|
|
227
|
-
attachments:
|
|
228
|
-
onRemove:
|
|
229
|
-
onRetry:
|
|
230
|
-
preparingCount:
|
|
234
|
+
attachments: y,
|
|
235
|
+
onRemove: we ?? (() => void 0),
|
|
236
|
+
onRetry: Te ?? (() => void 0),
|
|
237
|
+
preparingCount: x
|
|
231
238
|
})
|
|
232
239
|
}) : null,
|
|
233
240
|
/* @__PURE__ */ f("button", {
|
|
234
241
|
type: "button",
|
|
235
|
-
onClick: () =>
|
|
236
|
-
className: `absolute ${
|
|
237
|
-
"aria-pressed":
|
|
238
|
-
"aria-label":
|
|
242
|
+
onClick: () => B((e) => !e),
|
|
243
|
+
className: `absolute ${I ? "bottom-6 right-6 size-14" : L ? "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`,
|
|
244
|
+
"aria-pressed": z,
|
|
245
|
+
"aria-label": k("voiceSession.transcriptTitle", "Voice transcript"),
|
|
239
246
|
"data-testid": "assistant-voice-transcript-toggle",
|
|
240
|
-
children: /* @__PURE__ */ f(
|
|
247
|
+
children: /* @__PURE__ */ f(_e, { className: I ? "size-6" : L ? "size-4" : "size-5" })
|
|
241
248
|
}),
|
|
242
249
|
/* @__PURE__ */ f("button", {
|
|
243
250
|
type: "button",
|
|
244
|
-
onClick: () =>
|
|
245
|
-
className: `absolute ${
|
|
246
|
-
"aria-label":
|
|
251
|
+
onClick: () => F(R),
|
|
252
|
+
className: `absolute ${I ? "bottom-6 left-6 size-14" : L ? "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`,
|
|
253
|
+
"aria-label": R === "panel" ? k("voiceSession.expandPanel", "Show the conversation in the panel") : R === "full" ? k("voiceSession.expand", "Expand the conversation to full screen") : k("voiceSession.collapse", "Shrink to the compact controller"),
|
|
247
254
|
"data-testid": "assistant-voice-expand",
|
|
248
|
-
children:
|
|
255
|
+
children: I ? /* @__PURE__ */ f(ge, { className: "size-5" }) : /* @__PURE__ */ f(he, { className: L ? "size-4" : "size-5" })
|
|
249
256
|
})
|
|
250
257
|
]
|
|
251
258
|
});
|
|
252
259
|
};
|
|
253
|
-
function
|
|
260
|
+
function ve(e, t) {
|
|
254
261
|
switch (e) {
|
|
255
262
|
case "network": return t("voiceSession.noticeNetwork", "Speech recognition lost its connection. Check your network — it will retry.");
|
|
256
263
|
case "not-capturing": return t("voiceSession.noticeNotCapturing", "The microphone did not start. Check that this site is allowed to use it, then try again.");
|
|
@@ -261,7 +268,7 @@ function _e(e, t) {
|
|
|
261
268
|
default: return e;
|
|
262
269
|
}
|
|
263
270
|
}
|
|
264
|
-
function
|
|
271
|
+
function ye(e, t) {
|
|
265
272
|
switch (e) {
|
|
266
273
|
case "mic-denied": return t("voiceSession.micDenied", "Microphone access is blocked. Allow it in your browser settings to talk.");
|
|
267
274
|
case "no-speech-support": return t("voiceSession.noSpeechSupport", "This browser cannot listen. Try a different browser, or type instead.");
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { FC } from 'react';
|
|
2
|
+
import { VoiceView } from './AssistantVoiceSession';
|
|
3
|
+
/** Marks the notice, so the session does not move focus off it when they open together. */
|
|
4
|
+
export declare const HANDS_FREE_NOTICE_ATTR = "data-hands-free-notice";
|
|
5
|
+
interface Props {
|
|
6
|
+
/** Continue: remember the answer for this profile, then open the microphone. */
|
|
7
|
+
onContinue: () => void;
|
|
8
|
+
/** Not now: hands-free stays off for this conversation; tap-to-talk still works. */
|
|
9
|
+
onNotNow: () => void;
|
|
10
|
+
view: VoiceView;
|
|
11
|
+
}
|
|
12
|
+
/**
|
|
13
|
+
* The backend speech stream's privacy notice (BOFF-8613, H3).
|
|
14
|
+
*
|
|
15
|
+
* Shown inside the voice session BEFORE the microphone first opens on the
|
|
16
|
+
* backend stream, and only then: with that transport the person's voice leaves
|
|
17
|
+
* the device for Google Cloud Speech-to-Text, which neither the setting's
|
|
18
|
+
* tooltip (phones never show a `title`) nor anything else said.
|
|
19
|
+
*
|
|
20
|
+
* ★ A card with two real buttons, not a tooltip or a toast: it is visible on a
|
|
21
|
+
* phone in every size of the session (the docked strip included), it takes
|
|
22
|
+
* focus so a screen reader announces it, and nothing is captured until one of
|
|
23
|
+
* the buttons is pressed. Escape in the session answers "Not now".
|
|
24
|
+
*/
|
|
25
|
+
export declare const HandsFreePrivacyNotice: FC<Props>;
|
|
26
|
+
export {};
|
|
27
|
+
//# sourceMappingURL=HandsFreePrivacyNotice.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"HandsFreePrivacyNotice.d.ts","sourceRoot":"","sources":["../../../../../src/shared/assistant/ui/voice/HandsFreePrivacyNotice.tsx"],"names":[],"mappings":"AAAA,OAAO,EAA4B,KAAK,EAAE,EAAE,MAAM,OAAO,CAAC;AAE1D,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,yBAAyB,CAAC;AAEzD,2FAA2F;AAC3F,eAAO,MAAM,sBAAsB,2BAA2B,CAAC;AAE/D,UAAU,KAAK;IACb,gFAAgF;IAChF,UAAU,EAAE,MAAM,IAAI,CAAC;IACvB,oFAAoF;IACpF,QAAQ,EAAE,MAAM,IAAI,CAAC;IACrB,IAAI,EAAE,SAAS,CAAC;CACjB;AAED;;;;;;;;;;;;GAYG;AACH,eAAO,MAAM,sBAAsB,EAAE,EAAE,CAAC,KAAK,CA2E5C,CAAC"}
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import { useAssistantTr as e } from "../../i18n.js";
|
|
2
|
+
import { useEffect as t, useId as n, useRef as r } from "react";
|
|
3
|
+
import { jsx as i, jsxs as a } from "react/jsx-runtime";
|
|
4
|
+
//#region src/shared/assistant/ui/voice/HandsFreePrivacyNotice.tsx
|
|
5
|
+
var o = "data-hands-free-notice", s = ({ onContinue: o, onNotNow: s, view: c }) => {
|
|
6
|
+
let l = e(), u = n(), d = n(), f = r(null);
|
|
7
|
+
t(() => {
|
|
8
|
+
f.current?.focus();
|
|
9
|
+
}, []);
|
|
10
|
+
let p = c === "mini";
|
|
11
|
+
return /* @__PURE__ */ a("div", {
|
|
12
|
+
role: "dialog",
|
|
13
|
+
"aria-modal": "false",
|
|
14
|
+
"aria-labelledby": u,
|
|
15
|
+
"aria-describedby": d,
|
|
16
|
+
className: `absolute z-20 flex flex-col overflow-y-auto rounded-lg border border-border-subtle bg-bg-elevated text-text-primary shadow-lg ${p ? "inset-2 gap-1.5 p-2.5" : c === "full" ? "inset-x-6 top-24 mx-auto max-w-md gap-3 p-5" : "inset-x-3 top-16 gap-2 p-4"}`,
|
|
17
|
+
"data-testid": "assistant-voice-privacy-notice",
|
|
18
|
+
"data-hands-free-notice": "",
|
|
19
|
+
children: [
|
|
20
|
+
/* @__PURE__ */ i("p", {
|
|
21
|
+
id: u,
|
|
22
|
+
className: `font-medium ${p ? "text-xs" : "text-sm"}`,
|
|
23
|
+
children: l("voice.handsFreeLabel", "Hands-free interrupt (beta)")
|
|
24
|
+
}),
|
|
25
|
+
/* @__PURE__ */ i("p", {
|
|
26
|
+
id: d,
|
|
27
|
+
className: `text-text-secondary ${p ? "text-xs" : "text-sm"}`,
|
|
28
|
+
"data-testid": "assistant-voice-privacy-notice-body",
|
|
29
|
+
children: l("voiceSession.streamNoticeBody", "Your voice is sent to Google Cloud Speech-to-Text and processed in the EU. We don't store the audio.")
|
|
30
|
+
}),
|
|
31
|
+
/* @__PURE__ */ a("div", {
|
|
32
|
+
className: `flex flex-wrap justify-end ${p ? "gap-2" : "gap-3"}`,
|
|
33
|
+
children: [/* @__PURE__ */ i("button", {
|
|
34
|
+
type: "button",
|
|
35
|
+
onClick: s,
|
|
36
|
+
className: `flex items-center justify-center rounded-full border border-border-default bg-bg-elevated font-medium text-text-secondary transition-colors hover:bg-bg-sunken focus:outline-none focus-visible:ring-2 focus-visible:ring-border-strong ${p ? "h-7 px-3 text-xs" : "h-9 px-4 text-sm"}`,
|
|
37
|
+
"data-testid": "assistant-voice-privacy-notice-not-now",
|
|
38
|
+
children: l("voiceSession.streamNoticeNotNow", "Not now")
|
|
39
|
+
}), /* @__PURE__ */ i("button", {
|
|
40
|
+
ref: f,
|
|
41
|
+
type: "button",
|
|
42
|
+
onClick: o,
|
|
43
|
+
className: `flex items-center justify-center rounded-full border border-transparent bg-action-primary-bg font-medium text-action-primary-text transition-colors hover:opacity-90 focus:outline-none focus-visible:ring-2 focus-visible:ring-border-strong ${p ? "h-7 px-3 text-xs" : "h-9 px-4 text-sm"}`,
|
|
44
|
+
"data-testid": "assistant-voice-privacy-notice-continue",
|
|
45
|
+
children: l("voiceSession.streamNoticeContinue", "Continue")
|
|
46
|
+
})]
|
|
47
|
+
})
|
|
48
|
+
]
|
|
49
|
+
});
|
|
50
|
+
};
|
|
51
|
+
//#endregion
|
|
52
|
+
export { o as HANDS_FREE_NOTICE_ATTR, s as HandsFreePrivacyNotice };
|
|
@@ -12,15 +12,28 @@ export interface SocketHandlers {
|
|
|
12
12
|
close(code: number): void;
|
|
13
13
|
error(): void;
|
|
14
14
|
}
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
15
|
+
/** Where to connect and as whom, resolved for each connection. */
|
|
16
|
+
export interface StreamConnection {
|
|
17
|
+
url: string;
|
|
18
|
+
/** The bare access token, offered as `bearer.<token>`. */
|
|
19
|
+
token: string;
|
|
18
20
|
}
|
|
21
|
+
type IntervalHandle = ReturnType<typeof setInterval>;
|
|
19
22
|
export interface BackendStreamDeps {
|
|
20
|
-
|
|
23
|
+
/**
|
|
24
|
+
* The URL and the access token for one connection. `null`: there is no
|
|
25
|
+
* usable credential (an `auth` failure). A rejection: the route is not
|
|
26
|
+
* configured (an `unavailable` failure).
|
|
27
|
+
*/
|
|
28
|
+
resolveConnection: () => Promise<StreamConnection | null>;
|
|
21
29
|
createSocket: (url: string, protocols: string[]) => SocketLike;
|
|
22
|
-
/** Languages sent with each utterance
|
|
23
|
-
languages: (language: string) => string[];
|
|
30
|
+
/** Languages sent with each utterance, or null when the stream does not carry this one. */
|
|
31
|
+
languages: (language: string) => string[] | null;
|
|
32
|
+
/** Milliseconds between `{t:'ping'}` keep-alives. */
|
|
33
|
+
keepAliveMs?: number;
|
|
34
|
+
setInterval?: (fn: () => void, ms: number) => IntervalHandle;
|
|
35
|
+
clearInterval?: (handle: IntervalHandle) => void;
|
|
36
|
+
now?: () => number;
|
|
24
37
|
}
|
|
25
38
|
/** The gateway's frame cap is 8 KB; stay well under it. */
|
|
26
39
|
export declare const MAX_SEND_BYTES = 6400;
|
|
@@ -28,7 +41,17 @@ export declare const CLOSE_CODE_ERRORS: Readonly<Record<number, {
|
|
|
28
41
|
code: SttErrorCode;
|
|
29
42
|
retryable: boolean;
|
|
30
43
|
}>>;
|
|
44
|
+
/**
|
|
45
|
+
* Closes that end a healthy connection rather than refuse one: the gateway's
|
|
46
|
+
* session cap (1000), a pod going away (1001, 4503) and an idle close (4408).
|
|
47
|
+
* They reconnect, but only after a connection that stayed up `MIN_STABLE_MS`,
|
|
48
|
+
* so a server that accepts and immediately drops cannot cause a loop.
|
|
49
|
+
*/
|
|
50
|
+
export declare const RECONNECT_CLOSE_CODES: ReadonlySet<number>;
|
|
51
|
+
export declare const MIN_STABLE_MS = 5000;
|
|
52
|
+
export declare const KEEP_ALIVE_MS = 20000;
|
|
31
53
|
/** Concatenate frames into chunks of at most `MAX_SEND_BYTES`. */
|
|
32
54
|
export declare function chunkFrames(frames: readonly Int16Array[]): Int16Array[];
|
|
33
55
|
export declare function createBackendStreamTransport(deps: BackendStreamDeps): SttTransport;
|
|
56
|
+
export {};
|
|
34
57
|
//# sourceMappingURL=backendStreamTransport.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"backendStreamTransport.d.ts","sourceRoot":"","sources":["../../../../../src/shared/assistant/voice/handsfree/backendStreamTransport.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"backendStreamTransport.d.ts","sourceRoot":"","sources":["../../../../../src/shared/assistant/voice/handsfree/backendStreamTransport.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAuCG;AACH,OAAO,KAAK,EAEV,YAAY,EACZ,YAAY,EAEb,MAAM,gBAAgB,CAAC;AAGxB,uFAAuF;AACvF,MAAM,WAAW,UAAU;IACzB,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,IAAI,CAAC,IAAI,EAAE,MAAM,GAAG,eAAe,GAAG,eAAe,GAAG,IAAI,CAAC;IAC7D,KAAK,CAAC,IAAI,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B,MAAM,CAAC,QAAQ,EAAE,cAAc,GAAG,IAAI,CAAC;CACxC;AAED,MAAM,WAAW,cAAc;IAC7B,IAAI,IAAI,IAAI,CAAC;IACb,OAAO,CAAC,IAAI,EAAE,OAAO,GAAG,IAAI,CAAC;IAC7B,KAAK,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,KAAK,IAAI,IAAI,CAAC;CACf;AAED,kEAAkE;AAClE,MAAM,WAAW,gBAAgB;IAC/B,GAAG,EAAE,MAAM,CAAC;IACZ,0DAA0D;IAC1D,KAAK,EAAE,MAAM,CAAC;CACf;AAED,KAAK,cAAc,GAAG,UAAU,CAAC,OAAO,WAAW,CAAC,CAAC;AAErD,MAAM,WAAW,iBAAiB;IAChC;;;;OAIG;IACH,iBAAiB,EAAE,MAAM,OAAO,CAAC,gBAAgB,GAAG,IAAI,CAAC,CAAC;IAC1D,YAAY,EAAE,CAAC,GAAG,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,KAAK,UAAU,CAAC;IAC/D,2FAA2F;IAC3F,SAAS,EAAE,CAAC,QAAQ,EAAE,MAAM,KAAK,MAAM,EAAE,GAAG,IAAI,CAAC;IACjD,qDAAqD;IACrD,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,WAAW,CAAC,EAAE,CAAC,EAAE,EAAE,MAAM,IAAI,EAAE,EAAE,EAAE,MAAM,KAAK,cAAc,CAAC;IAC7D,aAAa,CAAC,EAAE,CAAC,MAAM,EAAE,cAAc,KAAK,IAAI,CAAC;IACjD,GAAG,CAAC,EAAE,MAAM,MAAM,CAAC;CACpB;AAED,2DAA2D;AAC3D,eAAO,MAAM,cAAc,OAAO,CAAC;AAGnC,eAAO,MAAM,iBAAiB,EAAE,QAAQ,CACtC,MAAM,CAAC,MAAM,EAAE;IAAE,IAAI,EAAE,YAAY,CAAC;IAAC,SAAS,EAAE,OAAO,CAAA;CAAE,CAAC,CAU3D,CAAC;AAEF;;;;;GAKG;AACH,eAAO,MAAM,qBAAqB,EAAE,WAAW,CAAC,MAAM,CAEpD,CAAC;AACH,eAAO,MAAM,aAAa,OAAQ,CAAC;AACnC,eAAO,MAAM,aAAa,QAAS,CAAC;AASpC,kEAAkE;AAClE,wBAAgB,WAAW,CAAC,MAAM,EAAE,SAAS,UAAU,EAAE,GAAG,UAAU,EAAE,CAgBvE;AAED,wBAAgB,4BAA4B,CAC1C,IAAI,EAAE,iBAAiB,GACtB,YAAY,CAqQd"}
|