@burdenoff/fe-libs 2026.1005.1 → 2026.1005.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (108) hide show
  1. package/dist/chrome/ContextSwitcher.d.ts +2 -0
  2. package/dist/chrome/ContextSwitcher.d.ts.map +1 -1
  3. package/dist/chrome/ContextSwitcher.js +70 -67
  4. package/dist/chrome/contextSwitcher/ProjectList.d.ts +1 -0
  5. package/dist/chrome/contextSwitcher/ProjectList.d.ts.map +1 -1
  6. package/dist/chrome/contextSwitcher/ProjectList.js +18 -5
  7. package/dist/node_modules/fflate/esm/browser.js +3 -3
  8. package/dist/node_modules/hast-util-to-jsx-runtime/lib/index.js +51 -51
  9. package/dist/node_modules/pdfjs-dist/build/pdf.js +2268 -1656
  10. package/dist/node_modules/pdfjs-dist/build/pdf.worker.min.js +8719 -7535
  11. package/dist/shared/assistant/attachments.js +1 -0
  12. package/dist/shared/assistant/i18nManifest.d.ts +4 -0
  13. package/dist/shared/assistant/i18nManifest.d.ts.map +1 -1
  14. package/dist/shared/assistant/i18nManifest.js +4 -0
  15. package/dist/shared/assistant/images.js +1 -1
  16. package/dist/shared/assistant/index.d.ts +16 -0
  17. package/dist/shared/assistant/index.d.ts.map +1 -1
  18. package/dist/shared/assistant/runtime.js +1 -0
  19. package/dist/shared/assistant/speech/browserSpeechEngine.d.ts.map +1 -1
  20. package/dist/shared/assistant/speech/browserSpeechEngine.js +46 -45
  21. package/dist/shared/assistant/speech/createSpeechEngine.js +1 -1
  22. package/dist/shared/assistant/speech/hostedTtsSpeechEngine.d.ts.map +1 -1
  23. package/dist/shared/assistant/speech/hostedTtsSpeechEngine.js +80 -79
  24. package/dist/shared/assistant/store.d.ts +3 -0
  25. package/dist/shared/assistant/store.d.ts.map +1 -1
  26. package/dist/shared/assistant/store.js +43 -35
  27. package/dist/shared/assistant/ui/AssistantChatArea.d.ts.map +1 -1
  28. package/dist/shared/assistant/ui/AssistantChatArea.js +1076 -1074
  29. package/dist/shared/assistant/ui/AssistantMoreMenu.d.ts.map +1 -1
  30. package/dist/shared/assistant/ui/AssistantMoreMenu.js +59 -57
  31. package/dist/shared/assistant/ui/composer/AssistantHandsFreeInterruptToggle.d.ts +17 -0
  32. package/dist/shared/assistant/ui/composer/AssistantHandsFreeInterruptToggle.d.ts.map +1 -0
  33. package/dist/shared/assistant/ui/composer/AssistantHandsFreeInterruptToggle.js +34 -0
  34. package/dist/shared/assistant/ui/useVoiceSession.d.ts +29 -2
  35. package/dist/shared/assistant/ui/useVoiceSession.d.ts.map +1 -1
  36. package/dist/shared/assistant/ui/useVoiceSession.js +247 -213
  37. package/dist/shared/assistant/ui/voice/AssistantVoiceSession.js +2 -0
  38. package/dist/shared/assistant/uiActions/deixis.js +1 -1
  39. package/dist/shared/assistant/voice/handsfree/audioTrackTransport.d.ts +33 -0
  40. package/dist/shared/assistant/voice/handsfree/audioTrackTransport.d.ts.map +1 -0
  41. package/dist/shared/assistant/voice/handsfree/audioTrackTransport.js +98 -0
  42. package/dist/shared/assistant/voice/handsfree/backendStreamTransport.d.ts +34 -0
  43. package/dist/shared/assistant/voice/handsfree/backendStreamTransport.d.ts.map +1 -0
  44. package/dist/shared/assistant/voice/handsfree/backendStreamTransport.js +130 -0
  45. package/dist/shared/assistant/voice/handsfree/bargeIn.d.ts +43 -0
  46. package/dist/shared/assistant/voice/handsfree/bargeIn.d.ts.map +1 -0
  47. package/dist/shared/assistant/voice/handsfree/bargeIn.js +32 -0
  48. package/dist/shared/assistant/voice/handsfree/captureWorklet.d.ts +47 -0
  49. package/dist/shared/assistant/voice/handsfree/captureWorklet.d.ts.map +1 -0
  50. package/dist/shared/assistant/voice/handsfree/captureWorklet.js +85 -0
  51. package/dist/shared/assistant/voice/handsfree/echoGate.d.ts +140 -0
  52. package/dist/shared/assistant/voice/handsfree/echoGate.d.ts.map +1 -0
  53. package/dist/shared/assistant/voice/handsfree/echoGate.js +198 -0
  54. package/dist/shared/assistant/voice/handsfree/handsFreeController.d.ts +77 -0
  55. package/dist/shared/assistant/voice/handsfree/handsFreeController.d.ts.map +1 -0
  56. package/dist/shared/assistant/voice/handsfree/handsFreeController.js +126 -0
  57. package/dist/shared/assistant/voice/handsfree/handsFreeRuntime.d.ts +15 -0
  58. package/dist/shared/assistant/voice/handsfree/handsFreeRuntime.d.ts.map +1 -0
  59. package/dist/shared/assistant/voice/handsfree/handsFreeRuntime.js +78 -0
  60. package/dist/shared/assistant/voice/handsfree/handsFreeSetting.d.ts +26 -0
  61. package/dist/shared/assistant/voice/handsfree/handsFreeSetting.d.ts.map +1 -0
  62. package/dist/shared/assistant/voice/handsfree/handsFreeSetting.js +25 -0
  63. package/dist/shared/assistant/voice/handsfree/micCapture.d.ts +21 -0
  64. package/dist/shared/assistant/voice/handsfree/micCapture.d.ts.map +1 -0
  65. package/dist/shared/assistant/voice/handsfree/micCapture.js +73 -0
  66. package/dist/shared/assistant/voice/handsfree/playbackReference.d.ts +38 -0
  67. package/dist/shared/assistant/voice/handsfree/playbackReference.d.ts.map +1 -0
  68. package/dist/shared/assistant/voice/handsfree/playbackReference.js +55 -0
  69. package/dist/shared/assistant/voice/handsfree/preRollRing.d.ts +32 -0
  70. package/dist/shared/assistant/voice/handsfree/preRollRing.d.ts.map +1 -0
  71. package/dist/shared/assistant/voice/handsfree/preRollRing.js +34 -0
  72. package/dist/shared/assistant/voice/handsfree/sttTransport.d.ts +94 -0
  73. package/dist/shared/assistant/voice/handsfree/sttTransport.d.ts.map +1 -0
  74. package/dist/shared/assistant/voice/handsfree/sttTransport.js +27 -0
  75. package/dist/shared/assistant/voice/handsfree/useHandsFreeInterrupt.d.ts +33 -0
  76. package/dist/shared/assistant/voice/handsfree/useHandsFreeInterrupt.d.ts.map +1 -0
  77. package/dist/shared/assistant/voice/handsfree/useHandsFreeInterrupt.js +70 -0
  78. package/dist/shared/assistant/voice/handsfree/vad.d.ts +55 -0
  79. package/dist/shared/assistant/voice/handsfree/vad.d.ts.map +1 -0
  80. package/dist/shared/assistant/voice/handsfree/vad.js +41 -0
  81. package/dist/shared/assistant/voice/handsfree/webSpeechTransport.d.ts +3 -0
  82. package/dist/shared/assistant/voice/handsfree/webSpeechTransport.d.ts.map +1 -0
  83. package/dist/shared/assistant/voice/handsfree/webSpeechTransport.js +16 -0
  84. package/dist/shared/assistant/voice/voiceSession.d.ts +9 -0
  85. package/dist/shared/assistant/voice/voiceSession.d.ts.map +1 -1
  86. package/dist/shared/assistant/voice/voiceSession.js +2 -2
  87. package/dist/shared/assistant/voice/voiceTranscript.js +14 -14
  88. package/dist/shared/config/gatewayUrls.js +2 -2
  89. package/dist/shared/graphql/workspaceToken.d.ts +1 -0
  90. package/dist/shared/graphql/workspaceToken.d.ts.map +1 -1
  91. package/dist/shared/graphql/workspaceToken.js +18 -14
  92. package/dist/shared/plugins/iframe-mount/client/message-bus.js +1 -0
  93. package/dist/shared/plugins/iframe-mount/client/rpc.js +1 -0
  94. package/dist/shared/providers/shell/ActiveContextProvider.d.ts.map +1 -1
  95. package/dist/shared/providers/shell/ActiveContextProvider.js +165 -144
  96. package/dist/shared/providers/shell/AuthTokenProvider.d.ts.map +1 -1
  97. package/dist/shared/providers/shell/AuthTokenProvider.js +51 -46
  98. package/dist/shared/providers/shell/WorkspaceWideSelection.d.ts +10 -0
  99. package/dist/shared/providers/shell/WorkspaceWideSelection.d.ts.map +1 -0
  100. package/dist/shared/providers/shell/WorkspaceWideSelection.js +37 -0
  101. package/dist/shared/providers/shell/index.d.ts +2 -0
  102. package/dist/shared/providers/shell/index.d.ts.map +1 -1
  103. package/dist/shared/tours/TourTooltip.js +8 -8
  104. package/dist/shared/utils/format.js +1 -1
  105. package/dist/shared/utils/gatewayFetchRewrite.js +1 -1
  106. package/dist/shared-assistant.js +218 -202
  107. package/dist/shared-providers-shell.js +25 -24
  108. package/package.json +18 -8
@@ -0,0 +1,98 @@
1
+ //#region src/shared/assistant/voice/handsfree/audioTrackTransport.ts
2
+ var e = .3, t = 1500;
3
+ function n(t) {
4
+ let n = t.now ?? (() => Date.now()), r = null, i = null, a = null, o = null, s = "en-US", c = null, l = !1, u = null, d = 0, f = null, p = (e) => {
5
+ !i || !a || (i.gain.cancelScheduledValues(a.currentTime), i.gain.setTargetAtTime(e, a.currentTime, .005));
6
+ }, m = () => {
7
+ if (!l || !c) return;
8
+ let e = t.createRecognition();
9
+ if (!e) {
10
+ o?.onError({
11
+ code: "unavailable",
12
+ retryable: !1
13
+ });
14
+ return;
15
+ }
16
+ r = e, e.lang = s, e.continuous = !0, e.interimResults = !0, e.onresult = (e) => {
17
+ let t = u ?? (f && n() - d <= 1500 ? f : null);
18
+ if (t) for (let n = e.resultIndex; n < e.results.length; n += 1) {
19
+ let r = e.results[n], i = r?.[0]?.transcript?.trim() ?? "";
20
+ !r || !i || o?.onTranscript({
21
+ text: i,
22
+ final: r.isFinal,
23
+ utteranceId: t.utteranceId,
24
+ epoch: t.epoch,
25
+ language: s
26
+ });
27
+ }
28
+ }, e.onerror = (e) => {
29
+ (e.error === "not-allowed" || e.error === "service-not-allowed") && (l = !1, o?.onError({
30
+ code: "not-allowed",
31
+ retryable: !1
32
+ }));
33
+ }, e.onend = () => {
34
+ l && r === e && m();
35
+ };
36
+ try {
37
+ e.start(c);
38
+ } catch {
39
+ o?.onError({
40
+ code: "unavailable",
41
+ retryable: !1
42
+ });
43
+ }
44
+ };
45
+ return {
46
+ kind: "audio-track",
47
+ recognitionOwner: "transport",
48
+ keepsOpeningWords: !0,
49
+ async start(t, n, r) {
50
+ if (!t) {
51
+ r.onError({
52
+ code: "unavailable",
53
+ retryable: !1
54
+ });
55
+ return;
56
+ }
57
+ o = r, s = n, a = t.context;
58
+ let u = t.context.createDelay(1);
59
+ u.delayTime.value = e, i = t.context.createGain(), i.gain.value = 0;
60
+ let d = t.context.createMediaStreamDestination();
61
+ t.micSource.connect(u), u.connect(i), i.connect(d), c = d.stream.getAudioTracks()[0] ?? null, l = !0, m();
62
+ },
63
+ openUtterance(e) {
64
+ u = {
65
+ utteranceId: e.utteranceId,
66
+ epoch: e.epoch
67
+ }, f = u, p(1);
68
+ },
69
+ pushFrame() {},
70
+ closeUtterance(e) {
71
+ if (u?.utteranceId !== e) return;
72
+ d = n(), u = null;
73
+ let t = e;
74
+ setTimeout(() => {
75
+ u === null && f?.utteranceId === t && p(0);
76
+ }, 400);
77
+ },
78
+ cancelUtterance(e) {
79
+ u?.utteranceId === e && (u = null), f?.utteranceId === e && (f = null), p(0);
80
+ },
81
+ stop() {
82
+ l = !1, u = null, f = null;
83
+ let e = r;
84
+ if (r = null, e) {
85
+ e.onresult = null, e.onend = null, e.onerror = null;
86
+ try {
87
+ e.abort();
88
+ } catch {}
89
+ }
90
+ try {
91
+ i?.disconnect();
92
+ } catch {}
93
+ c?.stop(), c = null;
94
+ }
95
+ };
96
+ }
97
+ //#endregion
98
+ export { e as BRANCH_DELAY_S, t as TRAILING_RESULT_MS, n as createAudioTrackTransport };
@@ -0,0 +1,34 @@
1
+ import { SttErrorCode, SttTransport } from './sttTransport';
2
+ /** What the transport needs of a WebSocket; `handsFreeRuntime` adapts the real one. */
3
+ export interface SocketLike {
4
+ readonly readyState: number;
5
+ send(data: string | ArrayBufferLike | ArrayBufferView): void;
6
+ close(code?: number): void;
7
+ listen(handlers: SocketHandlers): void;
8
+ }
9
+ export interface SocketHandlers {
10
+ open(): void;
11
+ message(data: unknown): void;
12
+ close(code: number): void;
13
+ error(): void;
14
+ }
15
+ export interface StreamTicket {
16
+ ticket: string;
17
+ wsUrl: string;
18
+ }
19
+ export interface BackendStreamDeps {
20
+ fetchTicket: () => Promise<StreamTicket>;
21
+ createSocket: (url: string, protocols: string[]) => SocketLike;
22
+ /** Languages sent with each utterance: the user's input language, then en-IN. */
23
+ languages: (language: string) => string[];
24
+ }
25
+ /** The gateway's frame cap is 8 KB; stay well under it. */
26
+ export declare const MAX_SEND_BYTES = 6400;
27
+ export declare const CLOSE_CODE_ERRORS: Readonly<Record<number, {
28
+ code: SttErrorCode;
29
+ retryable: boolean;
30
+ }>>;
31
+ /** Concatenate frames into chunks of at most `MAX_SEND_BYTES`. */
32
+ export declare function chunkFrames(frames: readonly Int16Array[]): Int16Array[];
33
+ export declare function createBackendStreamTransport(deps: BackendStreamDeps): SttTransport;
34
+ //# sourceMappingURL=backendStreamTransport.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"backendStreamTransport.d.ts","sourceRoot":"","sources":["../../../../../src/shared/assistant/voice/handsfree/backendStreamTransport.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,OAAO,KAAK,EAEV,YAAY,EACZ,YAAY,EAEb,MAAM,gBAAgB,CAAC;AAExB,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,MAAM,WAAW,YAAY;IAC3B,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,MAAM,CAAC;CACf;AAED,MAAM,WAAW,iBAAiB;IAChC,WAAW,EAAE,MAAM,OAAO,CAAC,YAAY,CAAC,CAAC;IACzC,YAAY,EAAE,CAAC,GAAG,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,KAAK,UAAU,CAAC;IAC/D,iFAAiF;IACjF,SAAS,EAAE,CAAC,QAAQ,EAAE,MAAM,KAAK,MAAM,EAAE,CAAC;CAC3C;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,CAO3D,CAAC;AASF,kEAAkE;AAClE,wBAAgB,WAAW,CAAC,MAAM,EAAE,SAAS,UAAU,EAAE,GAAG,UAAU,EAAE,CAgBvE;AAED,wBAAgB,4BAA4B,CAC1C,IAAI,EAAE,iBAAiB,GACtB,YAAY,CAyId"}
@@ -0,0 +1,130 @@
1
+ //#region src/shared/assistant/voice/handsfree/backendStreamTransport.ts
2
+ var e = 6400, t = 1, n = {
3
+ 4401: {
4
+ code: "auth",
5
+ retryable: !1
6
+ },
7
+ 4408: {
8
+ code: "closed",
9
+ retryable: !0
10
+ },
11
+ 4413: {
12
+ code: "upstream",
13
+ retryable: !1
14
+ },
15
+ 4429: {
16
+ code: "quota",
17
+ retryable: !1
18
+ },
19
+ 4500: {
20
+ code: "upstream",
21
+ retryable: !0
22
+ }
23
+ }, r = (e) => typeof e == "object" && e && !Array.isArray(e) ? e : null;
24
+ function i(t) {
25
+ let n = Math.floor(e / 2), r = [], i = [], a = () => {
26
+ i.length > 0 && r.push(Int16Array.from(i)), i = [];
27
+ };
28
+ for (let e of t) for (let t of e) i.push(t), i.length === n && a();
29
+ return a(), r;
30
+ }
31
+ function a(e) {
32
+ let a = null, o = null, s = "en-IN", c = null, l = null, u = null, d = (e, t) => {
33
+ o?.onError({
34
+ code: e,
35
+ retryable: t
36
+ });
37
+ }, f = () => new Promise((t) => {
38
+ e.fetchTicket().then(({ ticket: i, wsUrl: c }) => {
39
+ let f = e.createSocket(c, [`bearer.${i}`]);
40
+ a = f, f.listen({
41
+ open: () => t(!0),
42
+ error: () => t(!1),
43
+ close: (e) => {
44
+ a === f && (a = null), t(!1);
45
+ let r = n[e];
46
+ r ? d(r.code, r.retryable) : l && d("closed", !0);
47
+ },
48
+ message: (e) => {
49
+ if (typeof e != "string") return;
50
+ let t;
51
+ try {
52
+ t = r(JSON.parse(e));
53
+ } catch {
54
+ return;
55
+ }
56
+ if (t) if (t.t === "partial" || t.t === "final") {
57
+ if (typeof t.text != "string" || typeof t.utteranceId != "string" || typeof t.epoch != "number") return;
58
+ t.t === "final" && u === t.utteranceId && (u = null), o?.onTranscript({
59
+ text: t.text,
60
+ final: t.t === "final",
61
+ utteranceId: t.utteranceId,
62
+ epoch: t.epoch,
63
+ language: typeof t.lang == "string" ? t.lang : s
64
+ });
65
+ } else t.t === "error" && d(t.code === "quota" ? "quota" : t.code === "auth" ? "auth" : "upstream", t.retryable === !0);
66
+ }
67
+ });
68
+ }).catch(() => {
69
+ d("auth", !1), t(!1);
70
+ });
71
+ }), p = (e) => {
72
+ a && a.readyState === t && a.send(e);
73
+ };
74
+ return {
75
+ kind: "backend-stream",
76
+ recognitionOwner: "transport",
77
+ keepsOpeningWords: !0,
78
+ async start(e, t, n) {
79
+ o = n, s = t, c = f(), await c || d("unavailable", !1);
80
+ },
81
+ openUtterance(t) {
82
+ l = {
83
+ utteranceId: t.utteranceId,
84
+ epoch: t.epoch
85
+ };
86
+ let n = t.preRoll;
87
+ (c ?? Promise.resolve(!1)).then((r) => {
88
+ if (!(!r || l?.utteranceId !== t.utteranceId)) {
89
+ p(JSON.stringify({
90
+ t: "config",
91
+ v: 1,
92
+ utteranceId: t.utteranceId,
93
+ epoch: t.epoch,
94
+ langs: e.languages(s),
95
+ sampleRate: 16e3,
96
+ encoding: "s16le"
97
+ }));
98
+ for (let e of i(n)) p(e);
99
+ }
100
+ });
101
+ },
102
+ pushFrame(e) {
103
+ l && p(e);
104
+ },
105
+ closeUtterance(e) {
106
+ l?.utteranceId === e && (p(JSON.stringify({
107
+ t: "end",
108
+ utteranceId: e
109
+ })), u = e, l = null);
110
+ },
111
+ cancelUtterance(e) {
112
+ if (l?.utteranceId === e) l = null;
113
+ else if (u !== e) return;
114
+ u = null, p(JSON.stringify({
115
+ t: "cancel",
116
+ utteranceId: e
117
+ }));
118
+ },
119
+ stop() {
120
+ l = null;
121
+ let e = a;
122
+ a = null, c = null;
123
+ try {
124
+ e?.close(1e3);
125
+ } catch {}
126
+ }
127
+ };
128
+ }
129
+ //#endregion
130
+ export { n as CLOSE_CODE_ERRORS, e as MAX_SEND_BYTES, i as chunkFrames, a as createBackendStreamTransport };
@@ -0,0 +1,43 @@
1
+ import { VoiceSessionPhase } from '../voiceSession';
2
+ export interface OnsetContext {
3
+ /** The viewer's "Hands-free interrupt (beta)" setting (or the test override). */
4
+ enabled: boolean;
5
+ muted: boolean;
6
+ phase: VoiceSessionPhase;
7
+ /** Sound from the assistant is coming out of the speaker right now. */
8
+ playbackAudible: boolean;
9
+ }
10
+ export type OnsetPlan = {
11
+ kind: "ignore";
12
+ reason: "disabled" | "muted" | "not-in-session";
13
+ } | {
14
+ kind: "open-utterance";
15
+ } | {
16
+ kind: "correction";
17
+ } | {
18
+ kind: "barge-in";
19
+ };
20
+ export declare function planOnset(context: OnsetContext): OnsetPlan;
21
+ /**
22
+ * Epoch guard. Every utterance opened at an onset gets a new epoch; every
23
+ * transcript carries the epoch of the utterance it came from. A transcript
24
+ * whose epoch is not the current one is a transport artifact (a late result of
25
+ * an utterance that was superseded) and is discarded BY EPOCH, never by looking
26
+ * at its words.
27
+ */
28
+ export interface EpochGuard {
29
+ current(): number;
30
+ /** A new utterance opened: everything older is stale from now on. */
31
+ open(): number;
32
+ accepts(epoch: number): boolean;
33
+ /** Session ended or muted: nothing in flight may be delivered. */
34
+ invalidate(): void;
35
+ }
36
+ export declare function createEpochGuard(): EpochGuard;
37
+ /** Nothing heard this long after a barge-in: show "say that again, or tap to replay". */
38
+ export declare const NOTHING_HEARD_MS = 1500;
39
+ /** Phantom barge-ins (nothing heard afterwards) in one session before falling back to tap-first. */
40
+ export declare const PHANTOM_BARGE_INS_BEFORE_FALLBACK = 3;
41
+ /** Whether a barge-in that produced no words counts against the session. */
42
+ export declare function shouldFallBackToTap(phantomBargeIns: number): boolean;
43
+ //# sourceMappingURL=bargeIn.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"bargeIn.d.ts","sourceRoot":"","sources":["../../../../../src/shared/assistant/voice/handsfree/bargeIn.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACH,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,iBAAiB,CAAC;AAEzD,MAAM,WAAW,YAAY;IAC3B,iFAAiF;IACjF,OAAO,EAAE,OAAO,CAAC;IACjB,KAAK,EAAE,OAAO,CAAC;IACf,KAAK,EAAE,iBAAiB,CAAC;IACzB,uEAAuE;IACvE,eAAe,EAAE,OAAO,CAAC;CAC1B;AAED,MAAM,MAAM,SAAS,GACjB;IAAE,IAAI,EAAE,QAAQ,CAAC;IAAC,MAAM,EAAE,UAAU,GAAG,OAAO,GAAG,gBAAgB,CAAA;CAAE,GACnE;IAAE,IAAI,EAAE,gBAAgB,CAAA;CAAE,GAC1B;IAAE,IAAI,EAAE,YAAY,CAAA;CAAE,GACtB;IAAE,IAAI,EAAE,UAAU,CAAA;CAAE,CAAC;AAEzB,wBAAgB,SAAS,CAAC,OAAO,EAAE,YAAY,GAAG,SAAS,CAU1D;AAED;;;;;;GAMG;AACH,MAAM,WAAW,UAAU;IACzB,OAAO,IAAI,MAAM,CAAC;IAClB,qEAAqE;IACrE,IAAI,IAAI,MAAM,CAAC;IACf,OAAO,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC;IAChC,kEAAkE;IAClE,UAAU,IAAI,IAAI,CAAC;CACpB;AAED,wBAAgB,gBAAgB,IAAI,UAAU,CAgB7C;AAED,yFAAyF;AACzF,eAAO,MAAM,gBAAgB,OAAO,CAAC;AACrC,oGAAoG;AACpG,eAAO,MAAM,iCAAiC,IAAI,CAAC;AAEnD,4EAA4E;AAC5E,wBAAgB,mBAAmB,CAAC,eAAe,EAAE,MAAM,GAAG,OAAO,CAEpE"}
@@ -0,0 +1,32 @@
1
+ //#region src/shared/assistant/voice/handsfree/bargeIn.ts
2
+ function e(e) {
3
+ return e.enabled ? e.muted ? {
4
+ kind: "ignore",
5
+ reason: "muted"
6
+ } : e.phase === "idle" || e.phase === "ended" ? {
7
+ kind: "ignore",
8
+ reason: "not-in-session"
9
+ } : e.phase === "speaking" || e.playbackAudible ? { kind: "barge-in" } : e.phase === "thinking" ? { kind: "correction" } : { kind: "open-utterance" } : {
10
+ kind: "ignore",
11
+ reason: "disabled"
12
+ };
13
+ }
14
+ function t() {
15
+ let e = 0, t = !0;
16
+ return {
17
+ current: () => e,
18
+ open() {
19
+ return e += 1, t = !0, e;
20
+ },
21
+ accepts: (n) => t && n === e,
22
+ invalidate() {
23
+ e += 1, t = !1;
24
+ }
25
+ };
26
+ }
27
+ var n = 1500, r = 3;
28
+ function i(e) {
29
+ return e >= 3;
30
+ }
31
+ //#endregion
32
+ export { n as NOTHING_HEARD_MS, r as PHANTOM_BARGE_INS_BEFORE_FALLBACK, t as createEpochGuard, e as planOnset, i as shouldFallBackToTap };
@@ -0,0 +1,47 @@
1
+ /**
2
+ * The AudioWorklet that turns the microphone into 16 kHz PCM (BOFF-8613, H3).
3
+ *
4
+ * A worklet module is loaded from a URL, and this package cannot assume a
5
+ * bundler that emits a second entry file for it, so the processor is a SOURCE
6
+ * STRING that `micCapture` loads through a Blob URL. It has no imports and no
7
+ * access to this file's scope; everything it needs is inside the string.
8
+ *
9
+ * What it does, per render quantum (128 samples at the device rate):
10
+ * - input 0 is the microphone, input 1 is the PLAYBACK REFERENCE bus (every
11
+ * sound the assistant makes is also sent there). Both are measured over the
12
+ * SAME samples, so the mic envelope and the reference envelope sit on one
13
+ * clock and only a fixed room lag separates them;
14
+ * - the microphone is decimated to 16 kHz with a windowed-sinc low-pass
15
+ * (cutoff 7.2 kHz). Forcing `sampleRate: 16000` on the context is not
16
+ * reliable across browsers, so the context runs at the device rate;
17
+ * - 320-sample (20 ms) frames are posted as s16le with their RMS (dBFS), zero-
18
+ * crossing rate and the reference RMS.
19
+ *
20
+ * The input buffer is preallocated; nothing is allocated per quantum.
21
+ *
22
+ * ★ The string is the SHIPPED code. The unit tests evaluate it with fake
23
+ * `AudioWorkletProcessor` / `registerProcessor` / `sampleRate` globals
24
+ * (`runCaptureWorkletForTest`) instead of testing a TypeScript copy of the
25
+ * maths, because a copy can be right while the string is wrong.
26
+ */
27
+ /** Samples per frame at 16 kHz: 20 ms. */
28
+ export declare const CAPTURE_FRAME_SAMPLES = 320;
29
+ export declare const CAPTURE_SAMPLE_RATE = 16000;
30
+ export declare const CAPTURE_FRAME_MS = 20;
31
+ export declare const CAPTURE_PROCESSOR_NAME = "boff-handsfree-capture";
32
+ /** What the worklet posts for each frame. */
33
+ export interface CaptureFrameMessage {
34
+ /** s16le mono 16 kHz, `CAPTURE_FRAME_SAMPLES` samples. */
35
+ pcm: ArrayBuffer;
36
+ /** Microphone level over the frame, dBFS. */
37
+ rmsDb: number;
38
+ /** Reference-bus level over the same samples, dBFS (about -90 when silent). */
39
+ refDb: number;
40
+ /** Zero crossings per sample. */
41
+ zcr: number;
42
+ /** AudioContext time at the end of the frame, seconds. */
43
+ ctxTime: number;
44
+ seq: number;
45
+ }
46
+ export declare const CAPTURE_WORKLET_SOURCE = "\n\"use strict\";\nconst FRAME = 320;\nclass BoffHandsfreeCapture extends AudioWorkletProcessor {\n constructor() {\n super();\n this.step = sampleRate / 16000;\n this.half = 6 * this.step;\n this.fc = 7200 / sampleRate;\n this.buf = new Float32Array(Math.ceil(this.half * 2) + 4096);\n this.len = 0;\n this.pos = 0;\n this.frame = new Float32Array(FRAME);\n this.n = 0;\n this.seq = 0;\n this.refEnergy = 0;\n this.refCount = 0;\n this.stopped = false;\n this.port.onmessage = (e) => { if (e.data && e.data.type === \"stop\") this.stopped = true; };\n }\n tap(d) {\n const x = 2 * this.fc * d;\n const s = x === 0 ? 1 : Math.sin(Math.PI * x) / (Math.PI * x);\n return 2 * this.fc * s * 0.5 * (1 + Math.cos(Math.PI * d / this.half));\n }\n emit() {\n const pcm = new Int16Array(FRAME);\n let energy = 0;\n let crossings = 0;\n for (let i = 0; i < FRAME; i++) {\n const v = Math.max(-1, Math.min(1, this.frame[i]));\n pcm[i] = Math.round(v * 32767);\n energy += v * v;\n if (i > 0 && (v >= 0) !== (this.frame[i - 1] >= 0)) crossings++;\n }\n const refMean = this.refCount > 0 ? this.refEnergy / this.refCount : 0;\n this.port.postMessage({\n pcm: pcm.buffer,\n rmsDb: 10 * Math.log10(energy / FRAME + 1e-9),\n refDb: 10 * Math.log10(refMean + 1e-9),\n zcr: crossings / FRAME,\n ctxTime: currentTime,\n seq: this.seq++,\n }, [pcm.buffer]);\n this.n = 0;\n this.refEnergy = 0;\n this.refCount = 0;\n }\n process(inputs) {\n if (this.stopped) return false;\n const mic = inputs[0] && inputs[0][0];\n if (!mic) return true;\n const ref = inputs[1] && inputs[1][0];\n if (ref) { for (let i = 0; i < ref.length; i++) this.refEnergy += ref[i] * ref[i]; }\n this.refCount += mic.length;\n if (this.len + mic.length > this.buf.length) {\n const grown = new Float32Array((this.len + mic.length) * 2);\n grown.set(this.buf.subarray(0, this.len));\n this.buf = grown;\n }\n this.buf.set(mic, this.len);\n this.len += mic.length;\n while (this.pos + this.half < this.len) {\n const from = Math.max(0, Math.ceil(this.pos - this.half));\n const to = Math.floor(this.pos + this.half);\n let acc = 0;\n for (let i = from; i <= to; i++) acc += this.buf[i] * this.tap(i - this.pos);\n this.frame[this.n++] = acc;\n this.pos += this.step;\n if (this.n === FRAME) this.emit();\n }\n const drop = Math.max(0, Math.floor(this.pos - this.half));\n if (drop > 0) {\n this.buf.copyWithin(0, drop, this.len);\n this.len -= drop;\n this.pos -= drop;\n }\n return true;\n }\n}\nregisterProcessor(\"boff-handsfree-capture\", BoffHandsfreeCapture);\n";
47
+ //# sourceMappingURL=captureWorklet.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"captureWorklet.d.ts","sourceRoot":"","sources":["../../../../../src/shared/assistant/voice/handsfree/captureWorklet.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AAEH,0CAA0C;AAC1C,eAAO,MAAM,qBAAqB,MAAM,CAAC;AACzC,eAAO,MAAM,mBAAmB,QAAQ,CAAC;AACzC,eAAO,MAAM,gBAAgB,KAAK,CAAC;AACnC,eAAO,MAAM,sBAAsB,2BAA2B,CAAC;AAE/D,6CAA6C;AAC7C,MAAM,WAAW,mBAAmB;IAClC,0DAA0D;IAC1D,GAAG,EAAE,WAAW,CAAC;IACjB,6CAA6C;IAC7C,KAAK,EAAE,MAAM,CAAC;IACd,+EAA+E;IAC/E,KAAK,EAAE,MAAM,CAAC;IACd,iCAAiC;IACjC,GAAG,EAAE,MAAM,CAAC;IACZ,0DAA0D;IAC1D,OAAO,EAAE,MAAM,CAAC;IAChB,GAAG,EAAE,MAAM,CAAC;CACb;AAED,eAAO,MAAM,sBAAsB,0tFAiFlC,CAAC"}
@@ -0,0 +1,85 @@
1
+ //#region src/shared/assistant/voice/handsfree/captureWorklet.ts
2
+ var e = 320, t = 16e3, n = 20, r = "boff-handsfree-capture", i = `
3
+ "use strict";
4
+ const FRAME = 320;
5
+ class BoffHandsfreeCapture extends AudioWorkletProcessor {
6
+ constructor() {
7
+ super();
8
+ this.step = sampleRate / ${t};
9
+ this.half = 6 * this.step;
10
+ this.fc = 7200 / sampleRate;
11
+ this.buf = new Float32Array(Math.ceil(this.half * 2) + 4096);
12
+ this.len = 0;
13
+ this.pos = 0;
14
+ this.frame = new Float32Array(FRAME);
15
+ this.n = 0;
16
+ this.seq = 0;
17
+ this.refEnergy = 0;
18
+ this.refCount = 0;
19
+ this.stopped = false;
20
+ this.port.onmessage = (e) => { if (e.data && e.data.type === "stop") this.stopped = true; };
21
+ }
22
+ tap(d) {
23
+ const x = 2 * this.fc * d;
24
+ const s = x === 0 ? 1 : Math.sin(Math.PI * x) / (Math.PI * x);
25
+ return 2 * this.fc * s * 0.5 * (1 + Math.cos(Math.PI * d / this.half));
26
+ }
27
+ emit() {
28
+ const pcm = new Int16Array(FRAME);
29
+ let energy = 0;
30
+ let crossings = 0;
31
+ for (let i = 0; i < FRAME; i++) {
32
+ const v = Math.max(-1, Math.min(1, this.frame[i]));
33
+ pcm[i] = Math.round(v * 32767);
34
+ energy += v * v;
35
+ if (i > 0 && (v >= 0) !== (this.frame[i - 1] >= 0)) crossings++;
36
+ }
37
+ const refMean = this.refCount > 0 ? this.refEnergy / this.refCount : 0;
38
+ this.port.postMessage({
39
+ pcm: pcm.buffer,
40
+ rmsDb: 10 * Math.log10(energy / FRAME + 1e-9),
41
+ refDb: 10 * Math.log10(refMean + 1e-9),
42
+ zcr: crossings / FRAME,
43
+ ctxTime: currentTime,
44
+ seq: this.seq++,
45
+ }, [pcm.buffer]);
46
+ this.n = 0;
47
+ this.refEnergy = 0;
48
+ this.refCount = 0;
49
+ }
50
+ process(inputs) {
51
+ if (this.stopped) return false;
52
+ const mic = inputs[0] && inputs[0][0];
53
+ if (!mic) return true;
54
+ const ref = inputs[1] && inputs[1][0];
55
+ if (ref) { for (let i = 0; i < ref.length; i++) this.refEnergy += ref[i] * ref[i]; }
56
+ this.refCount += mic.length;
57
+ if (this.len + mic.length > this.buf.length) {
58
+ const grown = new Float32Array((this.len + mic.length) * 2);
59
+ grown.set(this.buf.subarray(0, this.len));
60
+ this.buf = grown;
61
+ }
62
+ this.buf.set(mic, this.len);
63
+ this.len += mic.length;
64
+ while (this.pos + this.half < this.len) {
65
+ const from = Math.max(0, Math.ceil(this.pos - this.half));
66
+ const to = Math.floor(this.pos + this.half);
67
+ let acc = 0;
68
+ for (let i = from; i <= to; i++) acc += this.buf[i] * this.tap(i - this.pos);
69
+ this.frame[this.n++] = acc;
70
+ this.pos += this.step;
71
+ if (this.n === FRAME) this.emit();
72
+ }
73
+ const drop = Math.max(0, Math.floor(this.pos - this.half));
74
+ if (drop > 0) {
75
+ this.buf.copyWithin(0, drop, this.len);
76
+ this.len -= drop;
77
+ this.pos -= drop;
78
+ }
79
+ return true;
80
+ }
81
+ }
82
+ registerProcessor("${r}", BoffHandsfreeCapture);
83
+ `;
84
+ //#endregion
85
+ export { n as CAPTURE_FRAME_MS, e as CAPTURE_FRAME_SAMPLES, r as CAPTURE_PROCESSOR_NAME, t as CAPTURE_SAMPLE_RATE, i as CAPTURE_WORKLET_SOURCE };
@@ -0,0 +1,140 @@
1
+ /**
2
+ * The playback-reference echo gate (BOFF-8613, H3).
3
+ *
4
+ * Browser echo cancellation is best effort: it varies by handset, output route
5
+ * and volume. So the app adds its own ACOUSTIC evidence, and never decides by
6
+ * text: whether a stretch of audio is the user is settled BEFORE any transcript
7
+ * exists. (Dropping words because they resemble the assistant's sentence is
8
+ * what made "keep 50, not 15" vanish; a genuine correction that repeats the
9
+ * assistant's words or quantities must be kept.)
10
+ *
11
+ * ★ WHY COHERENCE AND NOT A LEVEL RATIO. The first version of this gate compared
12
+ * the microphone LEVEL with the assistant's level plus a calibrated offset. The
13
+ * headless-browser test showed why that cannot work with the processing the
14
+ * capture asks for: automatic gain control pumps a quiet echo up to the same
15
+ * loudness as a person (a -44 dBFS echo came back at -18 dBFS, the level of a
16
+ * real talker), so "louder than the expected echo" fired on the assistant's own
17
+ * voice. The ratio is not stable; the SHAPE is. An echo is a delayed copy of the
18
+ * reference: its loudness envelope rises and falls with the assistant's, one
19
+ * fixed room lag later, whatever gain the processing applied. A person talking
20
+ * over the assistant does not follow it.
21
+ *
22
+ * Per playback:
23
+ * 1. CALIBRATE the lag (0-500 ms) over the first second: the lag at which the
24
+ * mic envelope is most correlated with the reference envelope. Kept as a
25
+ * PRIOR, so the next reply is gated from its first frame. With no prior yet,
26
+ * onsets inside the first second of the very first reply cannot be
27
+ * attributed and are refused (fail closed: a false barge-in is the most
28
+ * visible failure, tap-to-interrupt is the fallback).
29
+ * 2. A frame is UNEXPLAINED by the reference when the correlation of the last
30
+ * `windowFrames` mic levels with the lagged reference levels is below
31
+ * `lowCorr`. The gate PASSES a frame after `lowRunFrames` consecutive
32
+ * unexplained frames (a single dip is not enough: echo-only audio dips to
33
+ * about 0.5 now and then). A reference that is silent over the window passes:
34
+ * there is no echo to confuse the user with. A reference that is audible but
35
+ * flat gives no shape to compare: refused.
36
+ * 3. With NO reference (the device `speechSynthesis` voice does not pass
37
+ * through the browser's output graph) nothing can be attributed: refused
38
+ * while it speaks. Tap-to-interrupt is the fallback there, and it is said so.
39
+ *
40
+ * Known limit, measured in the browser test and the design spike: this is
41
+ * envelope evidence, not an adaptive filter. A person who speaks in lock-step
42
+ * with the assistant's loudness pattern for a second is indistinguishable from
43
+ * an echo; the device kit is where handsets are measured.
44
+ */
45
+ export interface EchoGateParams {
46
+ /** Frames the coherence is measured over (12 x 20 ms = 240 ms). */
47
+ windowFrames: number;
48
+ /** Correlation below this is "not following the reference". */
49
+ lowCorr: number;
50
+ /** Consecutive unexplained frames before a frame passes. */
51
+ lowRunFrames: number;
52
+ /** The same, with a headset hint (the echo path is usually absent). */
53
+ headsetLowRunFrames: number;
54
+ /** Frames of evidence before the lag can be estimated (50 x 20 ms = 1 s). */
55
+ calibFrames: number;
56
+ /** Longest lag searched, in frames (25 x 20 ms = 500 ms). */
57
+ maxLagFrames: number;
58
+ /** The best lag must correlate at least this well to be believed. */
59
+ minCalibCorr: number;
60
+ /** Frames the gate stays armed after playback stops (the room tail and the lag). */
61
+ tailFrames: number;
62
+ /** Levels are clamped to [floorDb, 0] before comparing envelopes. */
63
+ floorDb: number;
64
+ /** A reference at or below this over the window is silence. */
65
+ referenceSilentDb: number;
66
+ /** Mic p90 at or below this while the reference plays means no echo path. */
67
+ quietMicDb: number;
68
+ /** Envelope standard deviation (dB) below which a signal is "flat". */
69
+ flatStdDb: number;
70
+ /**
71
+ * The room rings after the assistant stops, and gain control lifts that tail, so the
72
+ * echo of a word outlasts the word: the reference is compared with a copy that falls
73
+ * by at most this many dB per frame (a tail model), not with the bare envelope.
74
+ */
75
+ tailDecayDbPerFrame: number;
76
+ }
77
+ export declare const DEFAULT_ECHO_GATE_PARAMS: Readonly<EchoGateParams>;
78
+ export type GateReason = "no-playback" | "calibrating"
79
+ /** The assistant is on the device voice: no reference exists, so nothing can be attributed. */
80
+ | "no-reference" | "reference-silent"
81
+ /** No echo reaches the microphone (headphones, or a very good canceller). */
82
+ | "no-echo-path"
83
+ /** The microphone follows the reference: this is the assistant, not the user. */
84
+ | "follows-reference"
85
+ /** Audible reference without enough shape to compare. */
86
+ | "flat-reference"
87
+ /** The microphone does not follow the reference: this may be the user. */
88
+ | "uncorrelated";
89
+ export interface GateVerdict {
90
+ pass: boolean;
91
+ reason: GateReason;
92
+ /** Correlation of the last window with the lagged reference, when measured. */
93
+ coherence: number | null;
94
+ }
95
+ export declare class EchoGate {
96
+ private readonly params;
97
+ /** Clamped dBFS history, absolute index = `base` + position. */
98
+ private mic;
99
+ private ref;
100
+ /** `ref` with the room tail: falls by at most `tailDecayDbPerFrame` per frame. */
101
+ private tail;
102
+ private base;
103
+ private total;
104
+ private playing;
105
+ private hasReference;
106
+ private playStart;
107
+ private armedUntil;
108
+ private current;
109
+ private prior;
110
+ /** The reference plays but no echo reaches the microphone (this playback only). */
111
+ private noEchoPath;
112
+ private lowRun;
113
+ private headset;
114
+ constructor(params?: Partial<EchoGateParams>);
115
+ get isPlaying(): boolean;
116
+ /** True once a lag is known, i.e. the next reply is gated from its first frame. */
117
+ get hasPrior(): boolean;
118
+ /** What the last calibration found, for telemetry and the device kit. */
119
+ get calibration(): {
120
+ lagMs: number;
121
+ corr: number;
122
+ } | null;
123
+ setHeadset(headset: boolean): void;
124
+ /** The assistant started making sound. `withReference`: it passes through the reference bus. */
125
+ playbackStarted(withReference: boolean): void;
126
+ playbackStopped(): void;
127
+ /** Feed one frame; returns whether THIS frame may be the user's. */
128
+ pushFrame(micDb: number, refDb: number): GateVerdict;
129
+ private at;
130
+ /** The loudest of `array` over [absolute - span, absolute], ignoring what history no longer holds. */
131
+ private windowMax;
132
+ /** Correlation of mic[idx-w+1..idx] with the reference one lag earlier; null when history is short. */
133
+ private coherence;
134
+ /** Estimate the lag from the frames since playback began; sets `current` and `prior` when believable. */
135
+ private calibrate;
136
+ private trim;
137
+ /** Forget everything, including the prior (a new session, or the output route changed). */
138
+ reset(): void;
139
+ }
140
+ //# sourceMappingURL=echoGate.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"echoGate.d.ts","sourceRoot":"","sources":["../../../../../src/shared/assistant/voice/handsfree/echoGate.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2CG;AACH,MAAM,WAAW,cAAc;IAC7B,mEAAmE;IACnE,YAAY,EAAE,MAAM,CAAC;IACrB,+DAA+D;IAC/D,OAAO,EAAE,MAAM,CAAC;IAChB,4DAA4D;IAC5D,YAAY,EAAE,MAAM,CAAC;IACrB,uEAAuE;IACvE,mBAAmB,EAAE,MAAM,CAAC;IAC5B,6EAA6E;IAC7E,WAAW,EAAE,MAAM,CAAC;IACpB,6DAA6D;IAC7D,YAAY,EAAE,MAAM,CAAC;IACrB,qEAAqE;IACrE,YAAY,EAAE,MAAM,CAAC;IACrB,oFAAoF;IACpF,UAAU,EAAE,MAAM,CAAC;IACnB,qEAAqE;IACrE,OAAO,EAAE,MAAM,CAAC;IAChB,+DAA+D;IAC/D,iBAAiB,EAAE,MAAM,CAAC;IAC1B,6EAA6E;IAC7E,UAAU,EAAE,MAAM,CAAC;IACnB,uEAAuE;IACvE,SAAS,EAAE,MAAM,CAAC;IAClB;;;;OAIG;IACH,mBAAmB,EAAE,MAAM,CAAC;CAC7B;AAED,eAAO,MAAM,wBAAwB,EAAE,QAAQ,CAAC,cAAc,CAgB7D,CAAC;AAEF,MAAM,MAAM,UAAU,GAClB,aAAa,GACb,aAAa;AACf,+FAA+F;GAC7F,cAAc,GACd,kBAAkB;AACpB,6EAA6E;GAC3E,cAAc;AAChB,iFAAiF;GAC/E,mBAAmB;AACrB,yDAAyD;GACvD,gBAAgB;AAClB,0EAA0E;GACxE,cAAc,CAAC;AAEnB,MAAM,WAAW,WAAW;IAC1B,IAAI,EAAE,OAAO,CAAC;IACd,MAAM,EAAE,UAAU,CAAC;IACnB,+EAA+E;IAC/E,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;CAC1B;AAoDD,qBAAa,QAAQ;IACnB,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAiB;IACxC,gEAAgE;IAChE,OAAO,CAAC,GAAG,CAAgB;IAC3B,OAAO,CAAC,GAAG,CAAgB;IAC3B,kFAAkF;IAClF,OAAO,CAAC,IAAI,CAAgB;IAC5B,OAAO,CAAC,IAAI,CAAK;IACjB,OAAO,CAAC,KAAK,CAAK;IAElB,OAAO,CAAC,OAAO,CAAS;IACxB,OAAO,CAAC,YAAY,CAAQ;IAC5B,OAAO,CAAC,SAAS,CAAK;IACtB,OAAO,CAAC,UAAU,CAAM;IACxB,OAAO,CAAC,OAAO,CAA4B;IAC3C,OAAO,CAAC,KAAK,CAA4B;IACzC,mFAAmF;IACnF,OAAO,CAAC,UAAU,CAAS;IAC3B,OAAO,CAAC,MAAM,CAAK;IACnB,OAAO,CAAC,OAAO,CAAS;gBAEZ,MAAM,GAAE,OAAO,CAAC,cAAc,CAAM;IAIhD,IAAI,SAAS,IAAI,OAAO,CAEvB;IAED,mFAAmF;IACnF,IAAI,QAAQ,IAAI,OAAO,CAEtB;IAED,yEAAyE;IACzE,IAAI,WAAW,IAAI;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,GAAG,IAAI,CAGxD;IAED,UAAU,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI;IAIlC,gGAAgG;IAChG,eAAe,CAAC,aAAa,EAAE,OAAO,GAAG,IAAI;IAS7C,eAAe,IAAI,IAAI;IAMvB,oEAAoE;IACpE,SAAS,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,WAAW;IAiFpD,OAAO,CAAC,EAAE;IAIV,sGAAsG;IACtG,OAAO,CAAC,SAAS;IAajB,uGAAuG;IACvG,OAAO,CAAC,SAAS;IAkBjB,yGAAyG;IACzG,OAAO,CAAC,SAAS;IA6CjB,OAAO,CAAC,IAAI;IAQZ,2FAA2F;IAC3F,KAAK,IAAI,IAAI;CAad"}