@smartspace/chat-ui 1.14.4-pr.453.43dda12 → 1.14.4-pr.453.d6dd83a
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/index.d.ts +9 -7
- package/dist/index.js +39 -6
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.d.ts
CHANGED
|
@@ -127,8 +127,8 @@ type UseDictationOptions = {
|
|
|
127
127
|
onInterim?: (text: string) => void;
|
|
128
128
|
/**
|
|
129
129
|
* Hard stop, so a forgotten mic can't run for an hour. Keep it under the
|
|
130
|
-
* token's ~10 minute life: the token is
|
|
131
|
-
*
|
|
130
|
+
* token's ~10 minute life: the token is never refreshed once the session is
|
|
131
|
+
* running, so a longer cap would end the session on an auth failure.
|
|
132
132
|
*/
|
|
133
133
|
maxDurationMs?: number;
|
|
134
134
|
/** Stop after this long without any speech. */
|
|
@@ -136,7 +136,7 @@ type UseDictationOptions = {
|
|
|
136
136
|
};
|
|
137
137
|
/**
|
|
138
138
|
* Streams microphone audio to Azure AI Speech and hands back recognised
|
|
139
|
-
* phrases. Owns the whole session: mic permission + stream,
|
|
139
|
+
* phrases. Owns the whole session: mic permission + stream, SDK loading,
|
|
140
140
|
* recogniser lifecycle, idle/max timers, and teardown on stop or unmount.
|
|
141
141
|
* Interim (not yet final) text goes to `onInterim` for display only; only final
|
|
142
142
|
* phrases reach `onPhrase`.
|
|
@@ -481,10 +481,12 @@ interface ChatService {
|
|
|
481
481
|
* Speech-to-text (composer dictation). Both are optional so existing
|
|
482
482
|
* service implementations keep compiling — the composer renders a
|
|
483
483
|
* microphone only when both are provided AND the config says enabled.
|
|
484
|
-
* `getSpeechConfig` is read once per session. `getSpeechToken` is called
|
|
485
|
-
*
|
|
486
|
-
*
|
|
487
|
-
*
|
|
484
|
+
* `getSpeechConfig` is read once per session. `getSpeechToken` is called
|
|
485
|
+
* when a dictation session starts (in parallel with the mic permission
|
|
486
|
+
* prompt — and again if that token aged out while the prompt sat open). The
|
|
487
|
+
* token is handed to the SDK as-is and never refreshed mid-session, so a
|
|
488
|
+
* session is capped to stay inside its life. No caching wanted: a stale
|
|
489
|
+
* token cannot be renewed.
|
|
488
490
|
*/
|
|
489
491
|
getSpeechConfig?(): Promise<SpeechConfig>;
|
|
490
492
|
getSpeechToken?(): Promise<SpeechToken>;
|
package/dist/index.js
CHANGED
|
@@ -2557,6 +2557,17 @@ var MarkdownEditor = forwardRef((props, ref) => {
|
|
|
2557
2557
|
});
|
|
2558
2558
|
MarkdownEditor.displayName = "MarkdownEditor";
|
|
2559
2559
|
var TOKEN_EXPIRY_MARGIN_MS = 15e3;
|
|
2560
|
+
var STALE_TOKEN_FLOOR_MS = 6e4;
|
|
2561
|
+
function kickOff(fn) {
|
|
2562
|
+
let promise;
|
|
2563
|
+
try {
|
|
2564
|
+
promise = Promise.resolve(fn());
|
|
2565
|
+
} catch (e) {
|
|
2566
|
+
promise = Promise.reject(e);
|
|
2567
|
+
}
|
|
2568
|
+
promise.catch(() => void 0);
|
|
2569
|
+
return promise;
|
|
2570
|
+
}
|
|
2560
2571
|
var isSupported = () => typeof window !== "undefined" && window.isSecureContext && !!navigator.mediaDevices?.getUserMedia;
|
|
2561
2572
|
function classifyTokenFailure(error) {
|
|
2562
2573
|
const code3 = error?.code;
|
|
@@ -2588,6 +2599,18 @@ function useDictation({
|
|
|
2588
2599
|
const clearInterim = useCallback(() => onInterimRef.current?.(""), []);
|
|
2589
2600
|
const supported = isSupported();
|
|
2590
2601
|
const available = supported && !!region && !!getToken;
|
|
2602
|
+
useEffect(() => {
|
|
2603
|
+
if (!available) return;
|
|
2604
|
+
const nav = navigator;
|
|
2605
|
+
if (nav.connection?.saveData) return;
|
|
2606
|
+
const warm = () => void kickOff(() => import('microsoft-cognitiveservices-speech-sdk'));
|
|
2607
|
+
if (typeof window.requestIdleCallback === "function") {
|
|
2608
|
+
const id2 = window.requestIdleCallback(warm, { timeout: 2e3 });
|
|
2609
|
+
return () => window.cancelIdleCallback(id2);
|
|
2610
|
+
}
|
|
2611
|
+
const id = window.setTimeout(warm, 1500);
|
|
2612
|
+
return () => window.clearTimeout(id);
|
|
2613
|
+
}, [available]);
|
|
2591
2614
|
const stop = useCallback(() => {
|
|
2592
2615
|
generationRef.current += 1;
|
|
2593
2616
|
const session = sessionRef.current;
|
|
@@ -2609,15 +2632,22 @@ function useDictation({
|
|
|
2609
2632
|
const superseded = () => generationRef.current !== generation;
|
|
2610
2633
|
setError(null);
|
|
2611
2634
|
setState("starting");
|
|
2612
|
-
|
|
2613
|
-
|
|
2614
|
-
stream = await navigator.mediaDevices.getUserMedia({
|
|
2635
|
+
const streamPromise = kickOff(
|
|
2636
|
+
() => navigator.mediaDevices.getUserMedia({
|
|
2615
2637
|
audio: {
|
|
2616
2638
|
echoCancellation: true,
|
|
2617
2639
|
noiseSuppression: true,
|
|
2618
2640
|
autoGainControl: true
|
|
2619
2641
|
}
|
|
2620
|
-
})
|
|
2642
|
+
})
|
|
2643
|
+
);
|
|
2644
|
+
const tokenPromise = kickOff(getToken);
|
|
2645
|
+
const sdkPromise = kickOff(
|
|
2646
|
+
() => import('microsoft-cognitiveservices-speech-sdk')
|
|
2647
|
+
);
|
|
2648
|
+
let stream;
|
|
2649
|
+
try {
|
|
2650
|
+
stream = await streamPromise;
|
|
2621
2651
|
} catch (e) {
|
|
2622
2652
|
if (superseded()) return;
|
|
2623
2653
|
const name = e?.name;
|
|
@@ -2633,7 +2663,10 @@ function useDictation({
|
|
|
2633
2663
|
}
|
|
2634
2664
|
let token;
|
|
2635
2665
|
try {
|
|
2636
|
-
token = await
|
|
2666
|
+
token = await tokenPromise;
|
|
2667
|
+
if (Date.parse(token.expiresOn) - Date.now() < STALE_TOKEN_FLOOR_MS) {
|
|
2668
|
+
token = await getToken();
|
|
2669
|
+
}
|
|
2637
2670
|
} catch (e) {
|
|
2638
2671
|
stream.getTracks().forEach((t) => t.stop());
|
|
2639
2672
|
if (superseded()) return;
|
|
@@ -2648,7 +2681,7 @@ function useDictation({
|
|
|
2648
2681
|
let recognizer = null;
|
|
2649
2682
|
let published = null;
|
|
2650
2683
|
try {
|
|
2651
|
-
const sdk = await
|
|
2684
|
+
const sdk = await sdkPromise;
|
|
2652
2685
|
if (superseded()) {
|
|
2653
2686
|
stream.getTracks().forEach((t) => t.stop());
|
|
2654
2687
|
return;
|