@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,9 +1,18 @@
|
|
|
1
|
+
import { sttSubprotocols as e } from "./streamingConfig.js";
|
|
1
2
|
//#region src/shared/assistant/voice/handsfree/backendStreamTransport.ts
|
|
2
|
-
var
|
|
3
|
+
var t = 6400, n = 1, r = {
|
|
4
|
+
4400: {
|
|
5
|
+
code: "upstream",
|
|
6
|
+
retryable: !1
|
|
7
|
+
},
|
|
3
8
|
4401: {
|
|
4
9
|
code: "auth",
|
|
5
10
|
retryable: !1
|
|
6
11
|
},
|
|
12
|
+
4403: {
|
|
13
|
+
code: "auth",
|
|
14
|
+
retryable: !1
|
|
15
|
+
},
|
|
7
16
|
4408: {
|
|
8
17
|
code: "closed",
|
|
9
18
|
retryable: !0
|
|
@@ -19,107 +28,173 @@ var e = 6400, t = 1, n = {
|
|
|
19
28
|
4500: {
|
|
20
29
|
code: "upstream",
|
|
21
30
|
retryable: !0
|
|
31
|
+
},
|
|
32
|
+
4503: {
|
|
33
|
+
code: "upstream",
|
|
34
|
+
retryable: !0
|
|
22
35
|
}
|
|
23
|
-
},
|
|
24
|
-
|
|
25
|
-
|
|
36
|
+
}, i = new Set([
|
|
37
|
+
1e3,
|
|
38
|
+
1001,
|
|
39
|
+
4408,
|
|
40
|
+
4503
|
|
41
|
+
]), a = 5e3, o = 2e4, s = (e) => typeof e == "object" && e && !Array.isArray(e) ? e : null;
|
|
42
|
+
function c(e) {
|
|
43
|
+
let n = Math.floor(t / 2), r = [], i = [], a = () => {
|
|
26
44
|
i.length > 0 && r.push(Int16Array.from(i)), i = [];
|
|
27
45
|
};
|
|
28
|
-
for (let
|
|
46
|
+
for (let t of e) for (let e of t) i.push(e), i.length === n && a();
|
|
29
47
|
return a(), r;
|
|
30
48
|
}
|
|
31
|
-
function
|
|
32
|
-
let a =
|
|
33
|
-
|
|
49
|
+
function l(t) {
|
|
50
|
+
let a = t.now ?? (() => Date.now()), o = t.setInterval ?? ((e, t) => setInterval(e, t)), l = t.clearInterval ?? ((e) => clearInterval(e)), u = t.keepAliveMs ?? 2e4, d = null, f = null, p = "en-IN", m = null, h = null, g = null, _ = null, v = !1, y = !1, b = (e, t) => {
|
|
51
|
+
y || v || (y = !0, f?.onError({
|
|
34
52
|
code: e,
|
|
35
53
|
retryable: t
|
|
36
|
-
});
|
|
37
|
-
},
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
54
|
+
}));
|
|
55
|
+
}, x = (e) => {
|
|
56
|
+
d && d.readyState === n && d.send(e);
|
|
57
|
+
}, S = () => {
|
|
58
|
+
_ !== null && l(_), _ = null;
|
|
59
|
+
}, C = () => {
|
|
60
|
+
S(), _ = o(() => {
|
|
61
|
+
x(JSON.stringify({ t: "ping" }));
|
|
62
|
+
}, u);
|
|
63
|
+
}, w = (e) => {
|
|
64
|
+
h?.utteranceId === e && (h = null), g === e && (g = null);
|
|
65
|
+
}, T = (e) => {
|
|
66
|
+
if (typeof e != "string") return;
|
|
67
|
+
let t;
|
|
68
|
+
try {
|
|
69
|
+
t = s(JSON.parse(e));
|
|
70
|
+
} catch {
|
|
71
|
+
return;
|
|
72
|
+
}
|
|
73
|
+
if (t) {
|
|
74
|
+
if (t.t === "partial" || t.t === "final") {
|
|
75
|
+
if (typeof t.text != "string" || typeof t.utteranceId != "string" || typeof t.epoch != "number") return;
|
|
76
|
+
t.t === "final" && g === t.utteranceId && (g = null), f?.onTranscript({
|
|
77
|
+
text: t.text,
|
|
78
|
+
final: t.t === "final",
|
|
79
|
+
utteranceId: t.utteranceId,
|
|
80
|
+
epoch: t.epoch,
|
|
81
|
+
language: typeof t.lang == "string" ? t.lang : p
|
|
82
|
+
});
|
|
83
|
+
} else if (t.t === "done") typeof t.utteranceId == "string" && g === t.utteranceId && (g = null);
|
|
84
|
+
else if (t.t === "error") {
|
|
85
|
+
let e = t.code === "quota" ? "quota" : t.code === "auth" ? "auth" : "upstream", n = t.retryable === !0;
|
|
86
|
+
if (e === "upstream" && n && typeof t.utteranceId == "string") {
|
|
87
|
+
w(t.utteranceId);
|
|
88
|
+
return;
|
|
89
|
+
}
|
|
90
|
+
b(e, n);
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
}, E = () => new Promise((n) => {
|
|
94
|
+
let o = !1, s = (e) => {
|
|
95
|
+
o || (o = !0, n(e));
|
|
96
|
+
};
|
|
97
|
+
t.resolveConnection().then((n) => {
|
|
98
|
+
if (v) {
|
|
99
|
+
s(!1);
|
|
100
|
+
return;
|
|
101
|
+
}
|
|
102
|
+
if (n === null) {
|
|
103
|
+
b("auth", !1), s(!1);
|
|
104
|
+
return;
|
|
105
|
+
}
|
|
106
|
+
let o;
|
|
107
|
+
try {
|
|
108
|
+
o = t.createSocket(n.url, e(n.token));
|
|
109
|
+
} catch {
|
|
110
|
+
s(!1);
|
|
111
|
+
return;
|
|
112
|
+
}
|
|
113
|
+
d = o;
|
|
114
|
+
let c = null;
|
|
115
|
+
o.listen({
|
|
116
|
+
open: () => {
|
|
117
|
+
d === o && (c = a(), C(), s(!0));
|
|
47
118
|
},
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
let t;
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
119
|
+
error: () => s(!1),
|
|
120
|
+
close: (e) => {
|
|
121
|
+
let t = d === o;
|
|
122
|
+
if (t && (d = null, S()), s(!1), !t || v || c === null) return;
|
|
123
|
+
if (i.has(e) && a() - c >= 5e3) {
|
|
124
|
+
D();
|
|
54
125
|
return;
|
|
55
126
|
}
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
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
|
-
}
|
|
127
|
+
let n = r[e];
|
|
128
|
+
n ? b(n.code, n.retryable) : b("closed", !0);
|
|
129
|
+
},
|
|
130
|
+
message: T
|
|
67
131
|
});
|
|
68
132
|
}).catch(() => {
|
|
69
|
-
|
|
133
|
+
b("unavailable", !1), s(!1);
|
|
134
|
+
});
|
|
135
|
+
}), D = () => {
|
|
136
|
+
h = null, g = null;
|
|
137
|
+
let e = E();
|
|
138
|
+
m = e, e.then((t) => {
|
|
139
|
+
!t && m === e && b("unavailable", !1);
|
|
70
140
|
});
|
|
71
|
-
}), p = (e) => {
|
|
72
|
-
a && a.readyState === t && a.send(e);
|
|
73
141
|
};
|
|
74
142
|
return {
|
|
75
143
|
kind: "backend-stream",
|
|
76
144
|
recognitionOwner: "transport",
|
|
77
145
|
keepsOpeningWords: !0,
|
|
78
|
-
async start(e,
|
|
79
|
-
|
|
146
|
+
async start(e, n, r) {
|
|
147
|
+
if (f = r, p = n, v = !1, y = !1, t.languages(n) === null) {
|
|
148
|
+
b("unavailable", !1);
|
|
149
|
+
return;
|
|
150
|
+
}
|
|
151
|
+
let i = E();
|
|
152
|
+
m = i, !await i && m === i && b("unavailable", !1);
|
|
80
153
|
},
|
|
81
|
-
openUtterance(
|
|
82
|
-
|
|
83
|
-
utteranceId:
|
|
84
|
-
epoch:
|
|
154
|
+
openUtterance(e) {
|
|
155
|
+
h = {
|
|
156
|
+
utteranceId: e.utteranceId,
|
|
157
|
+
epoch: e.epoch
|
|
85
158
|
};
|
|
86
|
-
let n =
|
|
87
|
-
(
|
|
88
|
-
if (!
|
|
89
|
-
|
|
159
|
+
let n = e.preRoll;
|
|
160
|
+
(m ?? Promise.resolve(!1)).then((r) => {
|
|
161
|
+
if (!r || h?.utteranceId !== e.utteranceId) return;
|
|
162
|
+
let i = t.languages(p);
|
|
163
|
+
if (i !== null) {
|
|
164
|
+
x(JSON.stringify({
|
|
90
165
|
t: "config",
|
|
91
166
|
v: 1,
|
|
92
|
-
utteranceId:
|
|
93
|
-
epoch:
|
|
94
|
-
langs:
|
|
167
|
+
utteranceId: e.utteranceId,
|
|
168
|
+
epoch: e.epoch,
|
|
169
|
+
langs: i,
|
|
95
170
|
sampleRate: 16e3,
|
|
96
171
|
encoding: "s16le"
|
|
97
172
|
}));
|
|
98
|
-
for (let e of
|
|
173
|
+
for (let e of c(n)) x(e);
|
|
99
174
|
}
|
|
100
175
|
});
|
|
101
176
|
},
|
|
102
177
|
pushFrame(e) {
|
|
103
|
-
|
|
178
|
+
h && x(e);
|
|
104
179
|
},
|
|
105
180
|
closeUtterance(e) {
|
|
106
|
-
|
|
181
|
+
h?.utteranceId === e && (x(JSON.stringify({
|
|
107
182
|
t: "end",
|
|
108
183
|
utteranceId: e
|
|
109
|
-
})),
|
|
184
|
+
})), g = e, h = null);
|
|
110
185
|
},
|
|
111
186
|
cancelUtterance(e) {
|
|
112
|
-
if (
|
|
113
|
-
else if (
|
|
114
|
-
|
|
187
|
+
if (h?.utteranceId === e) h = null;
|
|
188
|
+
else if (g !== e) return;
|
|
189
|
+
g = null, x(JSON.stringify({
|
|
115
190
|
t: "cancel",
|
|
116
191
|
utteranceId: e
|
|
117
192
|
}));
|
|
118
193
|
},
|
|
119
194
|
stop() {
|
|
120
|
-
|
|
121
|
-
let e =
|
|
122
|
-
|
|
195
|
+
v = !0, h = null, g = null, S();
|
|
196
|
+
let e = d;
|
|
197
|
+
d = null, m = null;
|
|
123
198
|
try {
|
|
124
199
|
e?.close(1e3);
|
|
125
200
|
} catch {}
|
|
@@ -127,4 +202,4 @@ function a(e) {
|
|
|
127
202
|
};
|
|
128
203
|
}
|
|
129
204
|
//#endregion
|
|
130
|
-
export {
|
|
205
|
+
export { r as CLOSE_CODE_ERRORS, o as KEEP_ALIVE_MS, t as MAX_SEND_BYTES, a as MIN_STABLE_MS, i as RECONNECT_CLOSE_CODES, c as chunkFrames, l as createBackendStreamTransport };
|
|
@@ -4,7 +4,13 @@ import { MicCaptureHandle } from './micCapture';
|
|
|
4
4
|
import { PlaybackSource } from './playbackReference';
|
|
5
5
|
import { SttTransport } from './sttTransport';
|
|
6
6
|
import { VoiceSessionPhase } from '../voiceSession';
|
|
7
|
-
export type FallbackReason = "mic-denied" | "mic-unavailable" | "transport-unavailable" | "transport-auth" | "transport-quota" | "transport-upstream" | "phantom-barge-ins"
|
|
7
|
+
export type FallbackReason = "mic-denied" | "mic-unavailable" | "transport-unavailable" | "transport-auth" | "transport-quota" | "transport-upstream" | "phantom-barge-ins"
|
|
8
|
+
/**
|
|
9
|
+
* The person chose "Not now" on the backend stream's privacy notice. Raised
|
|
10
|
+
* by `useHandsFreeInterrupt`, never by the controller: the microphone was
|
|
11
|
+
* never opened.
|
|
12
|
+
*/
|
|
13
|
+
| "notice-declined";
|
|
8
14
|
export interface ControllerSession {
|
|
9
15
|
phase: VoiceSessionPhase;
|
|
10
16
|
muted: boolean;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"handsFreeController.d.ts","sourceRoot":"","sources":["../../../../../src/shared/assistant/voice/handsfree/handsFreeController.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AACH,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,kBAAkB,CAAC;AAE5D,OAAO,EAKL,KAAK,UAAU,EAChB,MAAM,WAAW,CAAC;AAEnB,OAAO,EAAmB,KAAK,gBAAgB,EAAE,MAAM,cAAc,CAAC;AACtE,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AAE1D,OAAO,KAAK,EAEV,YAAY,EAEb,MAAM,gBAAgB,CAAC;AAOxB,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,iBAAiB,CAAC;AAEzD,MAAM,MAAM,cAAc,GACtB,YAAY,GACZ,iBAAiB,GACjB,uBAAuB,GACvB,gBAAgB,GAChB,iBAAiB,GACjB,oBAAoB,GACpB,mBAAmB,CAAC;
|
|
1
|
+
{"version":3,"file":"handsFreeController.d.ts","sourceRoot":"","sources":["../../../../../src/shared/assistant/voice/handsfree/handsFreeController.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,15 +1,23 @@
|
|
|
1
|
+
import { SocketLike, StreamConnection } from './backendStreamTransport';
|
|
2
|
+
import { HandsFreeStreamingConfig } from './streamingConfig';
|
|
1
3
|
import { SttTransport, SttTransportKind, TransportChoice, TransportEnvironment } from './sttTransport';
|
|
2
|
-
/**
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
/** Configure (or, with `null`, clear) the backend-stream route. Nothing calls this today. */
|
|
9
|
-
export declare function configureHandsFreeStreaming(config: StreamingConfig | null): void;
|
|
10
|
-
export declare function readTransportEnvironment(): TransportEnvironment;
|
|
4
|
+
/**
|
|
5
|
+
* What this browser offers, for the person's input language (a tag such as
|
|
6
|
+
* `ta-IN`) and the app's streaming configuration (the registered one unless
|
|
7
|
+
* given).
|
|
8
|
+
*/
|
|
9
|
+
export declare function readTransportEnvironment(language: string, streaming?: HandsFreeStreamingConfig | null): TransportEnvironment;
|
|
11
10
|
/** Phones: the OS recogniser and a getUserMedia stream contend for the one microphone. */
|
|
12
11
|
export declare function isMobileUserAgent(userAgent: string): boolean;
|
|
13
|
-
export declare function chooseTransport(env
|
|
12
|
+
export declare function chooseTransport(env: TransportEnvironment): TransportChoice;
|
|
14
13
|
export declare function createRuntimeTransport(kind: SttTransportKind): SttTransport;
|
|
14
|
+
/**
|
|
15
|
+
* The configured URL and the signed-in person's token, read when each
|
|
16
|
+
* connection opens (a refreshed token is picked up). Rejects when the route is
|
|
17
|
+
* not configured or not switched on (only the test-only transport override can
|
|
18
|
+
* ask for it then); `null` when there is no usable token.
|
|
19
|
+
*/
|
|
20
|
+
export declare function resolveStreamConnection(): Promise<StreamConnection | null>;
|
|
21
|
+
/** The browser WebSocket behind `SocketLike`. */
|
|
22
|
+
export declare function openBrowserSocket(url: string, protocols: string[]): SocketLike;
|
|
15
23
|
//# sourceMappingURL=handsFreeRuntime.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"handsFreeRuntime.d.ts","sourceRoot":"","sources":["../../../../../src/shared/assistant/voice/handsfree/handsFreeRuntime.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"handsFreeRuntime.d.ts","sourceRoot":"","sources":["../../../../../src/shared/assistant/voice/handsfree/handsFreeRuntime.ts"],"names":[],"mappings":"AAUA,OAAO,EAEL,KAAK,UAAU,EACf,KAAK,gBAAgB,EACtB,MAAM,0BAA0B,CAAC;AAGlC,OAAO,EAGL,KAAK,wBAAwB,EAE9B,MAAM,mBAAmB,CAAC;AAC3B,OAAO,EAEL,KAAK,YAAY,EACjB,KAAK,gBAAgB,EACrB,KAAK,eAAe,EACpB,KAAK,oBAAoB,EAC1B,MAAM,gBAAgB,CAAC;AAkBxB;;;;GAIG;AACH,wBAAgB,wBAAwB,CACtC,QAAQ,EAAE,MAAM,EAChB,SAAS,GAAE,wBAAwB,GAAG,IAA+B,GACpE,oBAAoB,CAStB;AAED,0FAA0F;AAC1F,wBAAgB,iBAAiB,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAE5D;AAED,wBAAgB,eAAe,CAAC,GAAG,EAAE,oBAAoB,GAAG,eAAe,CAI1E;AAED,wBAAgB,sBAAsB,CAAC,IAAI,EAAE,gBAAgB,GAAG,YAAY,CAiB3E;AAED;;;;;GAKG;AACH,wBAAsB,uBAAuB,IAAI,OAAO,CAAC,gBAAgB,GAAG,IAAI,CAAC,CAOhF;AAED,iDAAiD;AACjD,wBAAgB,iBAAiB,CAAC,GAAG,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,GAAG,UAAU,CAgB9E"}
|
|
@@ -1,78 +1,67 @@
|
|
|
1
1
|
import { readTransportOverride as e } from "./handsFreeSetting.js";
|
|
2
2
|
import { createAudioTrackTransport as t } from "./audioTrackTransport.js";
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
6
|
-
import {
|
|
3
|
+
import { accessTokenFrom as n, readHandsFreeStreaming as r, streamLanguagesFor as i } from "./streamingConfig.js";
|
|
4
|
+
import { createBackendStreamTransport as a } from "./backendStreamTransport.js";
|
|
5
|
+
import { isMicCaptureSupported as o } from "./micCapture.js";
|
|
6
|
+
import { selectSttTransport as s } from "./sttTransport.js";
|
|
7
|
+
import { createWebSpeechTransport as c } from "./webSpeechTransport.js";
|
|
7
8
|
//#region src/shared/assistant/voice/handsfree/handsFreeRuntime.ts
|
|
8
|
-
|
|
9
|
-
function s(e) {
|
|
10
|
-
o = e;
|
|
11
|
-
}
|
|
12
|
-
function c() {
|
|
9
|
+
function l() {
|
|
13
10
|
if (typeof window > "u") return null;
|
|
14
11
|
let e = window.SpeechRecognition ?? window.webkitSpeechRecognition;
|
|
15
12
|
return typeof e == "function" ? e : null;
|
|
16
13
|
}
|
|
17
|
-
function
|
|
14
|
+
function u(e, t = r()) {
|
|
18
15
|
return {
|
|
19
16
|
userAgent: typeof navigator > "u" ? "" : navigator.userAgent,
|
|
20
|
-
hasSpeechRecognition:
|
|
21
|
-
hasAudioWorklet:
|
|
22
|
-
backendStreamEnabled:
|
|
23
|
-
backendStreamConfigured:
|
|
17
|
+
hasSpeechRecognition: l() !== null,
|
|
18
|
+
hasAudioWorklet: o(),
|
|
19
|
+
backendStreamEnabled: t?.enabled === !0,
|
|
20
|
+
backendStreamConfigured: t !== null,
|
|
21
|
+
backendStreamLanguage: i(e) !== null
|
|
24
22
|
};
|
|
25
23
|
}
|
|
26
|
-
function
|
|
24
|
+
function d(e) {
|
|
27
25
|
return /Android|iPhone|iPad|iPod|Mobile/.test(e);
|
|
28
26
|
}
|
|
29
|
-
function
|
|
27
|
+
function f(t) {
|
|
30
28
|
let n = e();
|
|
31
29
|
return n ? {
|
|
32
30
|
kind: n,
|
|
33
31
|
because: "test-override"
|
|
34
|
-
} :
|
|
32
|
+
} : s(t);
|
|
35
33
|
}
|
|
36
|
-
function
|
|
37
|
-
|
|
38
|
-
let e =
|
|
34
|
+
function p(e) {
|
|
35
|
+
return e === "audio-track" ? t({ createRecognition: () => {
|
|
36
|
+
let e = l();
|
|
39
37
|
return e ? new e() : null;
|
|
40
|
-
} })
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
listen(e) {
|
|
68
|
-
n.onopen = () => e.open(), n.onerror = () => e.error(), n.onclose = (t) => e.close(t.code), n.onmessage = (t) => e.message(t.data);
|
|
69
|
-
}
|
|
70
|
-
};
|
|
71
|
-
},
|
|
72
|
-
languages: (e) => e.toLowerCase().startsWith("en") ? [e] : [e, "en-IN"]
|
|
73
|
-
});
|
|
74
|
-
}
|
|
75
|
-
return a();
|
|
38
|
+
} }) : e === "backend-stream" ? a({
|
|
39
|
+
resolveConnection: m,
|
|
40
|
+
createSocket: h,
|
|
41
|
+
languages: i
|
|
42
|
+
}) : c();
|
|
43
|
+
}
|
|
44
|
+
async function m() {
|
|
45
|
+
let e = r();
|
|
46
|
+
if (e === null || !e.enabled) throw Error("hands-free streaming is not configured");
|
|
47
|
+
let t = n(await e.getAuthorization());
|
|
48
|
+
return t === null ? null : {
|
|
49
|
+
url: e.url,
|
|
50
|
+
token: t
|
|
51
|
+
};
|
|
52
|
+
}
|
|
53
|
+
function h(e, t) {
|
|
54
|
+
let n = new WebSocket(e, t);
|
|
55
|
+
return n.binaryType = "arraybuffer", {
|
|
56
|
+
get readyState() {
|
|
57
|
+
return n.readyState;
|
|
58
|
+
},
|
|
59
|
+
send: (e) => n.send(e),
|
|
60
|
+
close: (e) => n.close(e),
|
|
61
|
+
listen(e) {
|
|
62
|
+
n.onopen = () => e.open(), n.onerror = () => e.error(), n.onclose = (t) => e.close(t.code), n.onmessage = (t) => e.message(t.data);
|
|
63
|
+
}
|
|
64
|
+
};
|
|
76
65
|
}
|
|
77
66
|
//#endregion
|
|
78
|
-
export {
|
|
67
|
+
export { f as chooseTransport, p as createRuntimeTransport, d as isMobileUserAgent, h as openBrowserSocket, u as readTransportEnvironment, m as resolveStreamConnection };
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The backend-stream route's configuration (BOFF-8613, H3): where the gateway's
|
|
3
|
+
* streaming speech-to-text socket is, how the caller proves who they are, which
|
|
4
|
+
* languages it may carry, and which privacy notice the person has to see first.
|
|
5
|
+
*
|
|
6
|
+
* ★ INERT UNLESS AN APP CONFIGURES IT. Nothing in fe-libs calls
|
|
7
|
+
* `configureHandsFreeStreaming`; until a product does (and passes
|
|
8
|
+
* `enabled: true` with a usable URL) `selectSttTransport` never picks the
|
|
9
|
+
* backend stream, no notice is shown and no socket is opened. The rest of the
|
|
10
|
+
* hands-free feature behaves exactly as before.
|
|
11
|
+
*
|
|
12
|
+
* The gateway contract (`global-public-gateway` `src/stt-proxy.ts`):
|
|
13
|
+
* `GET wss://<gateway>/api/stt/v1/stream`, offered subprotocols
|
|
14
|
+
* `boff.stt.v1` and `bearer.<access token>`. The token travels in the
|
|
15
|
+
* `Sec-WebSocket-Protocol` header, never in the URL (ALB and CDN logs keep
|
|
16
|
+
* URLs), and the gateway removes it before the handshake completes. There is
|
|
17
|
+
* no ticket endpoint.
|
|
18
|
+
*
|
|
19
|
+
* Pure apart from the module-level registration: every helper here is a
|
|
20
|
+
* function of its arguments, so it is tested without a browser.
|
|
21
|
+
*/
|
|
22
|
+
/** The gateway route. */
|
|
23
|
+
export declare const STT_STREAM_PATH = "/api/stt/v1/stream";
|
|
24
|
+
/** The one subprotocol the gateway selects; offered next to `bearer.<token>`. */
|
|
25
|
+
export declare const STT_SUBPROTOCOL = "boff.stt.v1";
|
|
26
|
+
export declare const STT_BEARER_PREFIX = "bearer.";
|
|
27
|
+
/**
|
|
28
|
+
* The privacy notice the person accepts before the microphone first opens on
|
|
29
|
+
* the backend stream. The accepted VERSION is what is remembered, so a change
|
|
30
|
+
* of provider or processing region (which changes what the notice says) is a
|
|
31
|
+
* new version and asks again.
|
|
32
|
+
*/
|
|
33
|
+
export declare const HANDS_FREE_STREAM_NOTICE_VERSION = "google-stt-eu-1";
|
|
34
|
+
/** What an app passes. */
|
|
35
|
+
export interface HandsFreeStreamingOptions {
|
|
36
|
+
/** The app's switch for this environment. False: never selected. */
|
|
37
|
+
enabled: boolean;
|
|
38
|
+
/**
|
|
39
|
+
* The gateway's stream endpoint, `wss://<gateway>/api/stt/v1/stream`
|
|
40
|
+
* (`sttStreamUrlFromGateway` builds it from any gateway URL). An `https://`
|
|
41
|
+
* URL is accepted and converted. A URL that cannot be used leaves the stream
|
|
42
|
+
* unconfigured rather than half-working.
|
|
43
|
+
*/
|
|
44
|
+
url: string;
|
|
45
|
+
/**
|
|
46
|
+
* The signed-in person's access token, or `Bearer <token>`, read when each
|
|
47
|
+
* connection opens (so a refreshed token is used). `null`: not signed in, and
|
|
48
|
+
* the session falls back to the browser's recogniser.
|
|
49
|
+
*/
|
|
50
|
+
getAuthorization: () => string | null | Promise<string | null>;
|
|
51
|
+
}
|
|
52
|
+
/** The validated form the runtime uses. */
|
|
53
|
+
export interface HandsFreeStreamingConfig {
|
|
54
|
+
enabled: boolean;
|
|
55
|
+
url: string;
|
|
56
|
+
getAuthorization: () => string | null | Promise<string | null>;
|
|
57
|
+
}
|
|
58
|
+
/**
|
|
59
|
+
* The stream URL in its canonical form, or null when it cannot be used.
|
|
60
|
+
*
|
|
61
|
+
* - `https:` becomes `wss:`; `http:` becomes `ws:`;
|
|
62
|
+
* - plain `ws:` only on a loopback host (the token would otherwise travel in
|
|
63
|
+
* clear text);
|
|
64
|
+
* - an empty or root path becomes the gateway route; any other path is kept
|
|
65
|
+
* (a gateway mounted under a prefix);
|
|
66
|
+
* - a query string or fragment is refused: nothing about the caller belongs in
|
|
67
|
+
* a URL that access logs keep, and the gateway reads none.
|
|
68
|
+
*/
|
|
69
|
+
export declare function normalizeSttStreamUrl(raw: string): string | null;
|
|
70
|
+
/**
|
|
71
|
+
* The stream URL on the same host as any gateway URL an app already has, e.g.
|
|
72
|
+
* `https://alphagraphql.burdenoff.com/global/graphql` gives
|
|
73
|
+
* `wss://alphagraphql.burdenoff.com/api/stt/v1/stream`. Null when it cannot be
|
|
74
|
+
* used (see `normalizeSttStreamUrl`).
|
|
75
|
+
*/
|
|
76
|
+
export declare function sttStreamUrlFromGateway(gatewayUrl: string): string | null;
|
|
77
|
+
/**
|
|
78
|
+
* The bare token from `Bearer <token>` or `<token>`, or null when it is
|
|
79
|
+
* missing or could not travel as a subprotocol (the gateway would refuse it
|
|
80
|
+
* with 4400 anyway; refusing here keeps it off the wire).
|
|
81
|
+
*/
|
|
82
|
+
export declare function accessTokenFrom(authorization: string | null | undefined): string | null;
|
|
83
|
+
/** The subprotocols offered for one connection: ours, then the credential. */
|
|
84
|
+
export declare function sttSubprotocols(token: string): string[];
|
|
85
|
+
/**
|
|
86
|
+
* The language list sent with each utterance for the person's input language
|
|
87
|
+
* (a tag such as `ta-IN` or a bare code such as `ta`), or null when the backend
|
|
88
|
+
* stream does not carry that language.
|
|
89
|
+
*/
|
|
90
|
+
export declare function streamLanguagesFor(inputLanguage: string): string[] | null;
|
|
91
|
+
/**
|
|
92
|
+
* Configure (or, with `null`, clear) the backend-stream route. An app calls
|
|
93
|
+
* this once at start-up, for the environments where the operator has switched
|
|
94
|
+
* the gateway route on. Options with an unusable URL clear it.
|
|
95
|
+
*/
|
|
96
|
+
export declare function configureHandsFreeStreaming(options: HandsFreeStreamingOptions | null): void;
|
|
97
|
+
/** The current configuration, or null when the route is not configured. */
|
|
98
|
+
export declare function readHandsFreeStreaming(): HandsFreeStreamingConfig | null;
|
|
99
|
+
/** True when an app has switched the route on with a usable URL. */
|
|
100
|
+
export declare function isHandsFreeStreamingActive(): boolean;
|
|
101
|
+
/** Called after every `configureHandsFreeStreaming`. Returns the unsubscribe. */
|
|
102
|
+
export declare function subscribeHandsFreeStreaming(listener: () => void): () => void;
|
|
103
|
+
//# sourceMappingURL=streamingConfig.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"streamingConfig.d.ts","sourceRoot":"","sources":["../../../../../src/shared/assistant/voice/handsfree/streamingConfig.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;GAoBG;AAEH,yBAAyB;AACzB,eAAO,MAAM,eAAe,uBAAuB,CAAC;AACpD,iFAAiF;AACjF,eAAO,MAAM,eAAe,gBAAgB,CAAC;AAC7C,eAAO,MAAM,iBAAiB,YAAY,CAAC;AAoC3C;;;;;GAKG;AACH,eAAO,MAAM,gCAAgC,oBAAoB,CAAC;AAElE,0BAA0B;AAC1B,MAAM,WAAW,yBAAyB;IACxC,oEAAoE;IACpE,OAAO,EAAE,OAAO,CAAC;IACjB;;;;;OAKG;IACH,GAAG,EAAE,MAAM,CAAC;IACZ;;;;OAIG;IACH,gBAAgB,EAAE,MAAM,MAAM,GAAG,IAAI,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAAC;CAChE;AAED,2CAA2C;AAC3C,MAAM,WAAW,wBAAwB;IACvC,OAAO,EAAE,OAAO,CAAC;IACjB,GAAG,EAAE,MAAM,CAAC;IACZ,gBAAgB,EAAE,MAAM,MAAM,GAAG,IAAI,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAAC;CAChE;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,qBAAqB,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAyBhE;AAED;;;;;GAKG;AACH,wBAAgB,uBAAuB,CAAC,UAAU,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAQzE;AAED;;;;GAIG;AACH,wBAAgB,eAAe,CAC7B,aAAa,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,GACvC,MAAM,GAAG,IAAI,CAKf;AAED,8EAA8E;AAC9E,wBAAgB,eAAe,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,EAAE,CAEvD;AAED;;;;GAIG;AACH,wBAAgB,kBAAkB,CAAC,aAAa,EAAE,MAAM,GAAG,MAAM,EAAE,GAAG,IAAI,CAIzE;AAUD;;;;GAIG;AACH,wBAAgB,2BAA2B,CACzC,OAAO,EAAE,yBAAyB,GAAG,IAAI,GACxC,IAAI,CAeN;AAED,2EAA2E;AAC3E,wBAAgB,sBAAsB,IAAI,wBAAwB,GAAG,IAAI,CAExE;AAED,oEAAoE;AACpE,wBAAgB,0BAA0B,IAAI,OAAO,CAEpD;AAED,iFAAiF;AACjF,wBAAgB,2BAA2B,CAAC,QAAQ,EAAE,MAAM,IAAI,GAAG,MAAM,IAAI,CAK5E"}
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
//#region src/shared/assistant/voice/handsfree/streamingConfig.ts
|
|
2
|
+
var e = "/api/stt/v1/stream", t = "boff.stt.v1", n = "bearer.", r = /^[A-Za-z0-9._~-]+$/, i = 4096, a = new Set([
|
|
3
|
+
"localhost",
|
|
4
|
+
"127.0.0.1",
|
|
5
|
+
"[::1]"
|
|
6
|
+
]), o = {
|
|
7
|
+
en: ["en-IN"],
|
|
8
|
+
ta: ["ta-IN", "en-IN"],
|
|
9
|
+
hi: ["hi-IN", "en-IN"]
|
|
10
|
+
}, s = "google-stt-eu-1";
|
|
11
|
+
function c(t) {
|
|
12
|
+
if (typeof t != "string" || t.trim() === "") return null;
|
|
13
|
+
let n;
|
|
14
|
+
try {
|
|
15
|
+
n = new URL(t.trim());
|
|
16
|
+
} catch {
|
|
17
|
+
return null;
|
|
18
|
+
}
|
|
19
|
+
if (n.username !== "" || n.password !== "" || n.search !== "" || n.hash !== "") return null;
|
|
20
|
+
let r = n.protocol === "https:" ? "wss:" : n.protocol === "http:" ? "ws:" : n.protocol;
|
|
21
|
+
if (r !== "wss:" && r !== "ws:" || r === "ws:" && !a.has(n.hostname.toLowerCase())) return null;
|
|
22
|
+
let i = n.pathname === "" || n.pathname === "/" ? e : n.pathname;
|
|
23
|
+
return `${r}//${n.host}${i}`;
|
|
24
|
+
}
|
|
25
|
+
function l(t) {
|
|
26
|
+
let n;
|
|
27
|
+
try {
|
|
28
|
+
n = new URL(t);
|
|
29
|
+
} catch {
|
|
30
|
+
return null;
|
|
31
|
+
}
|
|
32
|
+
return c(`${n.protocol}//${n.host}${e}`);
|
|
33
|
+
}
|
|
34
|
+
function u(e) {
|
|
35
|
+
if (typeof e != "string") return null;
|
|
36
|
+
let t = e.trim().replace(/^bearer(?:\s+|$)/i, "");
|
|
37
|
+
return t === "" || t.length > i ? null : r.test(t) ? t : null;
|
|
38
|
+
}
|
|
39
|
+
function d(e) {
|
|
40
|
+
return [t, `${n}${e}`];
|
|
41
|
+
}
|
|
42
|
+
function f(e) {
|
|
43
|
+
let t = o[e.trim().toLowerCase().split(/[-_]/)[0] ?? ""];
|
|
44
|
+
return t ? [...t] : null;
|
|
45
|
+
}
|
|
46
|
+
var p = null, m = /* @__PURE__ */ new Set();
|
|
47
|
+
function h(e) {
|
|
48
|
+
if (e === null) p = null;
|
|
49
|
+
else {
|
|
50
|
+
let t = c(e.url);
|
|
51
|
+
p = t === null ? null : {
|
|
52
|
+
enabled: e.enabled === !0,
|
|
53
|
+
url: t,
|
|
54
|
+
getAuthorization: e.getAuthorization
|
|
55
|
+
};
|
|
56
|
+
}
|
|
57
|
+
for (let e of [...m]) e();
|
|
58
|
+
}
|
|
59
|
+
function g() {
|
|
60
|
+
return p;
|
|
61
|
+
}
|
|
62
|
+
function _() {
|
|
63
|
+
return p !== null && p.enabled;
|
|
64
|
+
}
|
|
65
|
+
function v(e) {
|
|
66
|
+
return m.add(e), () => {
|
|
67
|
+
m.delete(e);
|
|
68
|
+
};
|
|
69
|
+
}
|
|
70
|
+
//#endregion
|
|
71
|
+
export { s as HANDS_FREE_STREAM_NOTICE_VERSION, n as STT_BEARER_PREFIX, e as STT_STREAM_PATH, t as STT_SUBPROTOCOL, u as accessTokenFrom, h as configureHandsFreeStreaming, _ as isHandsFreeStreamingActive, c as normalizeSttStreamUrl, g as readHandsFreeStreaming, f as streamLanguagesFor, l as sttStreamUrlFromGateway, d as sttSubprotocols, v as subscribeHandsFreeStreaming };
|