@glassly/engine 0.3.2-beta.572 → 0.3.2-beta.602
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/README.md +1 -1
- package/build/engine.d.ts +15 -1
- package/build/engine.d.ts.map +1 -1
- package/build/engine.js +7 -3
- package/build/engine.js.map +1 -1
- package/build/facades/dev.d.ts +2 -2
- package/build/facades/dev.d.ts.map +1 -1
- package/build/facades/dev.js +2 -2
- package/build/facades/dev.js.map +1 -1
- package/build/facades/glasses.d.ts +20 -0
- package/build/facades/glasses.d.ts.map +1 -1
- package/build/facades/glasses.js +21 -0
- package/build/facades/glasses.js.map +1 -1
- package/build/facades/pairing.js +1 -1
- package/build/facades/pairing.js.map +1 -1
- package/build/facades/reports.js +2 -2
- package/build/facades/reports.js.map +1 -1
- package/build/facades/session.d.ts +1 -1
- package/build/facades/session.js +2 -2
- package/build/facades/session.js.map +1 -1
- package/build/generated/releaseMetadata.js +3 -3
- package/build/generated/releaseMetadata.js.map +1 -1
- package/build/index.d.ts +3 -1
- package/build/index.d.ts.map +1 -1
- package/build/index.js +3 -1
- package/build/index.js.map +1 -1
- package/build/runtime/bootstrap.d.ts +2 -2
- package/build/runtime/bootstrap.d.ts.map +1 -1
- package/build/runtime/bootstrap.js.map +1 -1
- package/build/services/CloudAudioSubscriptionSync.d.ts +2 -2
- package/build/services/CloudAudioSubscriptionSync.js +2 -2
- package/build/services/CloudAudioSubscriptionSync.js.map +1 -1
- package/build/services/CloudClientService.d.ts +2 -2
- package/build/services/CloudClientService.d.ts.map +1 -1
- package/build/services/CloudClientService.js +4 -4
- package/build/services/CloudClientService.js.map +1 -1
- package/build/services/CloudTranscriptE2EMetrics.d.ts +2 -2
- package/build/services/CloudTranscriptE2EMetrics.d.ts.map +1 -1
- package/build/services/CloudTranscriptE2EMetrics.js +3 -3
- package/build/services/CloudTranscriptE2EMetrics.js.map +1 -1
- package/build/services/DeviceEventRouter.d.ts.map +1 -1
- package/build/services/DeviceEventRouter.js +5 -0
- package/build/services/DeviceEventRouter.js.map +1 -1
- package/build/services/GestureDotsService.d.ts +9 -9
- package/build/services/GestureDotsService.d.ts.map +1 -1
- package/build/services/GestureDotsService.js +75 -50
- package/build/services/GestureDotsService.js.map +1 -1
- package/build/services/GlassesTouchInput.d.ts +1 -1
- package/build/services/GlassesTouchInput.d.ts.map +1 -1
- package/build/services/GlassesTouchInput.js +7 -4
- package/build/services/GlassesTouchInput.js.map +1 -1
- package/build/services/LocalMiniappRuntime.d.ts +1 -1
- package/build/services/LocalMiniappRuntime.d.ts.map +1 -1
- package/build/services/LocalMiniappRuntime.js +32 -8
- package/build/services/LocalMiniappRuntime.js.map +1 -1
- package/build/services/LocalSttFallbackCoordinator.d.ts +5 -2
- package/build/services/LocalSttFallbackCoordinator.d.ts.map +1 -1
- package/build/services/LocalSttFallbackCoordinator.js +7 -3
- package/build/services/LocalSttFallbackCoordinator.js.map +1 -1
- package/build/services/PhonePhotoCoordinator.d.ts +1 -1
- package/build/services/PhonePhotoCoordinator.js +4 -4
- package/build/services/PhonePhotoCoordinator.js.map +1 -1
- package/build/services/PhoneStreamCoordinator.d.ts +1 -1
- package/build/services/PhoneStreamCoordinator.js +1 -1
- package/build/services/PhoneStreamCoordinator.js.map +1 -1
- package/build/services/SupportProfileSync.d.ts +1 -1
- package/build/services/SupportProfileSync.js +2 -2
- package/build/services/SupportProfileSync.js.map +1 -1
- package/build/services/TranscriptionRouting.d.ts +6 -1
- package/build/services/TranscriptionRouting.d.ts.map +1 -1
- package/build/services/TranscriptionRouting.js +7 -3
- package/build/services/TranscriptionRouting.js.map +1 -1
- package/build/services/cloudStreamApi.d.ts +2 -2
- package/build/services/cloudStreamApi.js +2 -2
- package/build/services/cloudStreamApi.js.map +1 -1
- package/build/services/gestureDotGlyphs.d.ts +1 -1
- package/build/services/gestureDotGlyphs.d.ts.map +1 -1
- package/build/services/gestureDotGlyphs.js +5 -0
- package/build/services/gestureDotGlyphs.js.map +1 -1
- package/build/services/neuralBand/MetaAuth.d.ts +31 -0
- package/build/services/neuralBand/MetaAuth.d.ts.map +1 -0
- package/build/services/neuralBand/MetaAuth.js +161 -0
- package/build/services/neuralBand/MetaAuth.js.map +1 -0
- package/build/services/neuralBand/NeuralBandInput.d.ts +50 -0
- package/build/services/neuralBand/NeuralBandInput.d.ts.map +1 -0
- package/build/services/neuralBand/NeuralBandInput.js +114 -0
- package/build/services/neuralBand/NeuralBandInput.js.map +1 -0
- package/build/services/neuralBand/NeuralBandSettingsSync.d.ts +3 -0
- package/build/services/neuralBand/NeuralBandSettingsSync.d.ts.map +1 -0
- package/build/services/neuralBand/NeuralBandSettingsSync.js +52 -0
- package/build/services/neuralBand/NeuralBandSettingsSync.js.map +1 -0
- package/build/services/neuralBand/sha256.d.ts +7 -0
- package/build/services/neuralBand/sha256.d.ts.map +1 -0
- package/build/services/neuralBand/sha256.js +68 -0
- package/build/services/neuralBand/sha256.js.map +1 -0
- package/build/services/settingsBridge.d.ts +12 -4
- package/build/services/settingsBridge.d.ts.map +1 -1
- package/build/services/settingsBridge.js +13 -4
- package/build/services/settingsBridge.js.map +1 -1
- package/build/services/soniox/SonioxRealtimeClient.d.ts +2 -2
- package/build/services/soniox/SonioxRealtimeClient.js +2 -2
- package/build/services/soniox/SonioxRealtimeClient.js.map +1 -1
- package/build/services/soniox/SonioxTokenAssembler.d.ts +1 -1
- package/build/services/soniox/SonioxTokenAssembler.js +1 -1
- package/build/services/soniox/SonioxTokenAssembler.js.map +1 -1
- package/build/stores/cloudClientStatus.js +1 -1
- package/build/stores/cloudClientStatus.js.map +1 -1
- package/build/stores/settings.d.ts.map +1 -1
- package/build/stores/settings.js +25 -7
- package/build/stores/settings.js.map +1 -1
- package/build/types/enums.d.ts +2 -1
- package/build/types/enums.d.ts.map +1 -1
- package/build/types/enums.js +1 -0
- package/build/types/enums.js.map +1 -1
- package/build/utils/cloudClient/cloudSecureStore.js +2 -2
- package/build/utils/cloudClient/cloudSecureStore.js.map +1 -1
- package/package.json +7 -7
- package/src/engine.ts +7 -3
- package/src/facades/dev.ts +2 -2
- package/src/facades/glasses.ts +27 -0
- package/src/facades/pairing.ts +1 -1
- package/src/facades/reports.ts +2 -2
- package/src/facades/session.ts +2 -2
- package/src/generated/releaseMetadata.ts +3 -3
- package/src/index.ts +15 -1
- package/src/runtime/bootstrap.ts +2 -2
- package/src/services/CloudAudioSubscriptionSync.ts +2 -2
- package/src/services/CloudClientService.ts +4 -4
- package/src/services/CloudTranscriptE2EMetrics.ts +3 -3
- package/src/services/DeviceEventRouter.ts +5 -0
- package/src/services/GestureDotsService.ts +72 -49
- package/src/services/GlassesTouchInput.ts +13 -5
- package/src/services/LocalMiniappRuntime.ts +52 -24
- package/src/services/LocalSttFallbackCoordinator.ts +18 -4
- package/src/services/PhonePhotoCoordinator.ts +4 -4
- package/src/services/PhoneStreamCoordinator.ts +1 -1
- package/src/services/SupportProfileSync.ts +2 -2
- package/src/services/TranscriptionRouting.ts +12 -4
- package/src/services/cloudStreamApi.ts +3 -3
- package/src/services/gestureDotGlyphs.ts +6 -1
- package/src/services/neuralBand/MetaAuth.ts +192 -0
- package/src/services/neuralBand/NeuralBandInput.ts +148 -0
- package/src/services/neuralBand/NeuralBandSettingsSync.ts +63 -0
- package/src/services/neuralBand/sha256.ts +70 -0
- package/src/services/settingsBridge.ts +15 -4
- package/src/services/soniox/SonioxRealtimeClient.ts +2 -2
- package/src/services/soniox/SonioxTokenAssembler.ts +1 -1
- package/src/stores/cloudClientStatus.ts +1 -1
- package/src/stores/settings.ts +25 -7
- package/src/types/enums.ts +1 -0
- package/src/utils/cloudClient/cloudSecureStore.ts +2 -2
|
@@ -44,7 +44,7 @@ import overlayPages from "./pages/OverlayPages";
|
|
|
44
44
|
import dashboardOpenTrace from "./debug/DashboardOpenTrace";
|
|
45
45
|
import { isAppForegrounded, isPhoneActive, onAppForegroundChange, onPhoneActivityChange } from "./PhoneActivity";
|
|
46
46
|
import { installedNotificationApps } from "./PhoneNotificationsSync";
|
|
47
|
-
import { DERIVED_SETTINGS_KEYS, SETTINGS_BRIDGE_KEYS, isDerivedSettingsKey, ringBatteryFrom, selectSettingsBridgeKeys, validateSettingsSet, } from "./settingsBridge";
|
|
47
|
+
import { DERIVED_SETTINGS_KEYS, SETTINGS_BRIDGE_KEYS, input2dFrom, isDerivedSettingsKey, ringBatteryFrom, selectSettingsBridgeKeys, validateSettingsSet, } from "./settingsBridge";
|
|
48
48
|
import { mayUsePermission } from "./miniappPermissions";
|
|
49
49
|
import { activeDashboard, addDashboardApp, displayViewsFor, isDashboardApp, isOverlayApp, onOverlayAppsChange, removeDashboardApp, setOverlayViewer, } from "./pages/overlayApps";
|
|
50
50
|
import { pagesEligible } from "./pages/pageEligibility";
|
|
@@ -63,7 +63,7 @@ import { phonePhotoCoordinator } from "./PhonePhotoCoordinator";
|
|
|
63
63
|
import { phoneStreamCoordinator } from "./PhoneStreamCoordinator";
|
|
64
64
|
import { phoneVideoCoordinator } from "./PhoneVideoCoordinator";
|
|
65
65
|
import { runSentenceTtsPipeline } from "./SentenceTtsPipeline";
|
|
66
|
-
import { summarizeTranscriptionRoutes, transcriptionDeliveryRoute } from "./TranscriptionRouting";
|
|
66
|
+
import { summarizeTranscriptionRoutes, transcriptionDeliveryRoute, } from "./TranscriptionRouting";
|
|
67
67
|
import { prepareTtsSentences } from "./TtsTextSanitizer";
|
|
68
68
|
import { handleWifiAdbRequest } from "./WifiAdbRequest";
|
|
69
69
|
import { cloudClientService, setBlobNamespaceMigrator } from "./CloudClientService";
|
|
@@ -152,7 +152,7 @@ const MINIAPP_AUTH_REFRESH_MIN_DELAY_MS = 5_000;
|
|
|
152
152
|
// (e.g. the cloud client had not finished its first-boot Core token exchange
|
|
153
153
|
// when the miniapp connected). Exponential from base, capped, so a transient
|
|
154
154
|
// not-yet-connected client self-heals within seconds instead of needing a full
|
|
155
|
-
// manual Cloud
|
|
155
|
+
// manual Cloud reconnect.
|
|
156
156
|
const MINIAPP_AUTH_RETRY_BASE_MS = 1_000;
|
|
157
157
|
const MINIAPP_AUTH_RETRY_MAX_MS = 15_000;
|
|
158
158
|
const FOREGROUND_LIVENESS_PROBE_TIMEOUT_MS = 2_500;
|
|
@@ -835,6 +835,7 @@ class LocalMiniappRuntime {
|
|
|
835
835
|
subscriptions: new Set(),
|
|
836
836
|
forceLocalTranscriptionStreams: new Set(),
|
|
837
837
|
cloudTranscriptionStreams: new Set(),
|
|
838
|
+
noFallbackTranscriptionStreams: new Set(),
|
|
838
839
|
sendMessage: sendFn,
|
|
839
840
|
lastPongAt: Date.now(),
|
|
840
841
|
unansweredPingRounds: 0,
|
|
@@ -1538,7 +1539,7 @@ class LocalMiniappRuntime {
|
|
|
1538
1539
|
// right after app start. CONNECT_ACK already went out without auth; keep
|
|
1539
1540
|
// trying to mint (and re-drive on cloud-connect) so the app authenticates
|
|
1540
1541
|
// to its backend on its own, instead of staying dead until a full manual
|
|
1541
|
-
// Cloud
|
|
1542
|
+
// Cloud reconnect re-runs the whole handshake.
|
|
1542
1543
|
this.deliverInitialMiniappAuth(packageName, authPromise, 0);
|
|
1543
1544
|
}
|
|
1544
1545
|
this.sendCloudStatusToMiniapp(packageName);
|
|
@@ -1688,7 +1689,7 @@ class LocalMiniappRuntime {
|
|
|
1688
1689
|
* When the cloud client (re)connects, immediately re-attempt the initial mint
|
|
1689
1690
|
* for any handshook app still missing its token, instead of waiting out the
|
|
1690
1691
|
* backoff. This is what turns "scan a dev app before the cloud is ready" from
|
|
1691
|
-
* "dead until you manually reconnect Cloud
|
|
1692
|
+
* "dead until you manually reconnect Cloud" into "authenticates on its own
|
|
1692
1693
|
* the instant the connection comes up".
|
|
1693
1694
|
*/
|
|
1694
1695
|
redriveMiniappAuthDelivery() {
|
|
@@ -1798,6 +1799,7 @@ class LocalMiniappRuntime {
|
|
|
1798
1799
|
let requestedLocationRate = null;
|
|
1799
1800
|
const forceLocalTranscriptionStreams = new Set();
|
|
1800
1801
|
const cloudTranscriptionStreams = new Set();
|
|
1802
|
+
const noFallbackTranscriptionStreams = new Set();
|
|
1801
1803
|
const streams = rawStreams?.map((s) => {
|
|
1802
1804
|
if (typeof s === "object" && s !== null) {
|
|
1803
1805
|
if (s.stream === "location_stream") {
|
|
@@ -1811,6 +1813,8 @@ class LocalMiniappRuntime {
|
|
|
1811
1813
|
}
|
|
1812
1814
|
if (isSpeechTextStream(s.stream) && (s.forceLocal !== true || s.includeCloud === true)) {
|
|
1813
1815
|
cloudTranscriptionStreams.add(s.stream);
|
|
1816
|
+
if (s.localFallback === false)
|
|
1817
|
+
noFallbackTranscriptionStreams.add(s.stream);
|
|
1814
1818
|
}
|
|
1815
1819
|
return s.stream;
|
|
1816
1820
|
}
|
|
@@ -1875,6 +1879,7 @@ class LocalMiniappRuntime {
|
|
|
1875
1879
|
app.subscriptions = new Set(streams);
|
|
1876
1880
|
app.forceLocalTranscriptionStreams = new Set([...forceLocalTranscriptionStreams].filter((stream) => app.subscriptions.has(stream)));
|
|
1877
1881
|
app.cloudTranscriptionStreams = new Set([...cloudTranscriptionStreams].filter((stream) => app.subscriptions.has(stream)));
|
|
1882
|
+
app.noFallbackTranscriptionStreams = new Set([...noFallbackTranscriptionStreams].filter((stream) => app.subscriptions.has(stream)));
|
|
1878
1883
|
this.replaceStreamSubscribers(packageName, previousSubscriptions, app.subscriptions);
|
|
1879
1884
|
// The overlay app presents phone notifications on the glasses while it
|
|
1880
1885
|
// listens to them; recorded for every dashboard so the role can move.
|
|
@@ -2212,6 +2217,10 @@ class LocalMiniappRuntime {
|
|
|
2212
2217
|
return localDisplayManager.foregroundAppOnScreen();
|
|
2213
2218
|
case "ring_battery":
|
|
2214
2219
|
return ringBatteryFrom(useGlassesStore.getState());
|
|
2220
|
+
case "input_2d": {
|
|
2221
|
+
const controller = useSettingsStore.getState().getSetting(SETTINGS.default_controller.key);
|
|
2222
|
+
return input2dFrom(useGlassesStore.getState(), controller);
|
|
2223
|
+
}
|
|
2215
2224
|
}
|
|
2216
2225
|
}
|
|
2217
2226
|
handleSettingsGet(packageName, payload, requestId) {
|
|
@@ -2298,6 +2307,7 @@ class LocalMiniappRuntime {
|
|
|
2298
2307
|
useAppStatusStore.subscribe(pushDerived);
|
|
2299
2308
|
onOverlayAppsChange(pushDerived);
|
|
2300
2309
|
useGlassesStore.subscribe((s) => `${s.ringConnected}:${s.ringBatteryLevel}:${s.controllerConnected}:${s.controllerBatteryLevel}`, pushDerived);
|
|
2310
|
+
useSettingsStore.subscribe((s) => s.getSetting(SETTINGS.default_controller.key), pushDerived);
|
|
2301
2311
|
}
|
|
2302
2312
|
/**
|
|
2303
2313
|
* Native nav UI feed (display.sendNativeNav*). Gated on the device's nav
|
|
@@ -4245,6 +4255,7 @@ class LocalMiniappRuntime {
|
|
|
4245
4255
|
const previousSubscriptions = app.subscriptions;
|
|
4246
4256
|
app.subscriptions = new Set(streams);
|
|
4247
4257
|
app.forceLocalTranscriptionStreams.clear();
|
|
4258
|
+
app.noFallbackTranscriptionStreams.clear();
|
|
4248
4259
|
app.cloudTranscriptionStreams = new Set(streams.filter(isSpeechTextStream));
|
|
4249
4260
|
this.replaceStreamSubscribers(packageName, previousSubscriptions, app.subscriptions);
|
|
4250
4261
|
this.recomputeMicRequirements();
|
|
@@ -4310,6 +4321,7 @@ class LocalMiniappRuntime {
|
|
|
4310
4321
|
let transcriptionLang = null;
|
|
4311
4322
|
let forceLocalTranscriptionLang = null;
|
|
4312
4323
|
let hasForceLocalTranscription = false;
|
|
4324
|
+
let hasFallbackTranscription = false;
|
|
4313
4325
|
const localTranslations = [];
|
|
4314
4326
|
for (const [stream, subscribers] of this.activeStreamSubscribers()) {
|
|
4315
4327
|
if (subscribers.size === 0)
|
|
@@ -4340,6 +4352,8 @@ class LocalMiniappRuntime {
|
|
|
4340
4352
|
if (forceLocalTranscriptionLang === null)
|
|
4341
4353
|
forceLocalTranscriptionLang = language;
|
|
4342
4354
|
}
|
|
4355
|
+
if (routes.hasFallbackSubscriber)
|
|
4356
|
+
hasFallbackTranscription = true;
|
|
4343
4357
|
if (routes.hasCloudSubscriber)
|
|
4344
4358
|
cloudStreams.add(stream);
|
|
4345
4359
|
}
|
|
@@ -4351,7 +4365,7 @@ class LocalMiniappRuntime {
|
|
|
4351
4365
|
localTranslationService.setSubscriptions(translatesLocally);
|
|
4352
4366
|
const hasForceLocalTranslation = translatesLocally.some((sub) => sub.forceLocal);
|
|
4353
4367
|
const localSourceLang = translatesLocally.length > 0 ? sttModelManager.getBcp47ForLanguage() : null;
|
|
4354
|
-
localSttFallbackCoordinator.onSubscriptionChange(transcriptionLang !== null || localSourceLang !== null, forceLocalTranscriptionLang ?? transcriptionLang ?? localSourceLang, hasForceLocalTranscription || hasForceLocalTranslation);
|
|
4368
|
+
localSttFallbackCoordinator.onSubscriptionChange(transcriptionLang !== null || localSourceLang !== null, forceLocalTranscriptionLang ?? transcriptionLang ?? localSourceLang, hasForceLocalTranscription || hasForceLocalTranslation, hasFallbackTranscription || localSourceLang !== null);
|
|
4355
4369
|
// Mirror the same set as typed AudioSubscription[]. When Soniox-direct is
|
|
4356
4370
|
// enabled (user API key set), the DIRECT service serves the whole set and
|
|
4357
4371
|
// the cloud gets an EMPTY one — pushed as a real PUT, not skipped, so
|
|
@@ -4500,12 +4514,15 @@ class LocalMiniappRuntime {
|
|
|
4500
4514
|
return;
|
|
4501
4515
|
if (!q.blocked) {
|
|
4502
4516
|
this.lastSttQuotaNoticeAt = 0;
|
|
4503
|
-
void localSttFallbackCoordinator.onSttQuotaBlockedChange(false);
|
|
4517
|
+
void localSttFallbackCoordinator.onSttQuotaBlockedChange(false).then(() => this.broadcastCloudStatus());
|
|
4504
4518
|
this.onQuotaRestored?.("transcription");
|
|
4505
4519
|
return;
|
|
4506
4520
|
}
|
|
4507
4521
|
console.warn(`${LOG_TAG}: cloud transcription blocked by plan quota`);
|
|
4508
4522
|
void localSttFallbackCoordinator.onSttQuotaBlockedChange(true).then(() => {
|
|
4523
|
+
// Miniapps learn of the block through the status snapshot; the lens
|
|
4524
|
+
// notice below is for the wearer.
|
|
4525
|
+
this.broadcastCloudStatus();
|
|
4509
4526
|
const localSttActive = localSttFallbackCoordinator.isActive();
|
|
4510
4527
|
const now = Date.now();
|
|
4511
4528
|
if (now - this.lastSttQuotaNoticeAt >= STT_QUOTA_NOTICE_DEBOUNCE_MS) {
|
|
@@ -4721,6 +4738,7 @@ class LocalMiniappRuntime {
|
|
|
4721
4738
|
return {
|
|
4722
4739
|
status: base.status,
|
|
4723
4740
|
audioTransport: fallbackActive || sonioxDegraded ? "offline" : base.audioTransport,
|
|
4741
|
+
quotaBlocked: localSttFallbackCoordinator.isSttQuotaBlocked() ? ["transcription"] : [],
|
|
4724
4742
|
};
|
|
4725
4743
|
}
|
|
4726
4744
|
broadcastCloudStatus() {
|
|
@@ -4967,6 +4985,7 @@ class LocalMiniappRuntime {
|
|
|
4967
4985
|
return {
|
|
4968
4986
|
cloud: app?.cloudTranscriptionStreams.has(stream) === true,
|
|
4969
4987
|
forceLocal: app?.forceLocalTranscriptionStreams.has(stream) === true,
|
|
4988
|
+
localFallback: app?.noFallbackTranscriptionStreams.has(stream) !== true,
|
|
4970
4989
|
};
|
|
4971
4990
|
}
|
|
4972
4991
|
appTranslationRoutesForEvent(packageName, patterns) {
|
|
@@ -4979,10 +4998,15 @@ class LocalMiniappRuntime {
|
|
|
4979
4998
|
appTranscriptionRoutesForEvent(packageName, stream) {
|
|
4980
4999
|
const app = this.connectedApps.get(packageName);
|
|
4981
5000
|
const autoStream = `${MiniappStreamType.TRANSCRIPTION}:auto`;
|
|
5001
|
+
const cloudExact = app?.cloudTranscriptionStreams.has(stream) === true;
|
|
5002
|
+
const cloudAuto = app?.cloudTranscriptionStreams.has(autoStream) === true;
|
|
4982
5003
|
return {
|
|
4983
|
-
cloud:
|
|
5004
|
+
cloud: cloudExact || cloudAuto,
|
|
4984
5005
|
forceLocal: app?.forceLocalTranscriptionStreams.has(stream) === true ||
|
|
4985
5006
|
app?.forceLocalTranscriptionStreams.has(autoStream) === true,
|
|
5007
|
+
// Fallback stays accepted while any matching default subscription takes it.
|
|
5008
|
+
localFallback: (cloudExact && app?.noFallbackTranscriptionStreams.has(stream) !== true) ||
|
|
5009
|
+
(cloudAuto && app?.noFallbackTranscriptionStreams.has(autoStream) !== true),
|
|
4986
5010
|
};
|
|
4987
5011
|
}
|
|
4988
5012
|
/**
|