@layercode/js-sdk 2.8.5 → 2.8.6
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.
|
@@ -5283,7 +5283,7 @@ class WavRecorder {
|
|
|
5283
5283
|
.join(',');
|
|
5284
5284
|
const cb = async () => {
|
|
5285
5285
|
let id = ++lastId;
|
|
5286
|
-
const devices = await this.listDevices();
|
|
5286
|
+
const devices = await this.listDevices({ requestPermission: false });
|
|
5287
5287
|
if (id === lastId) {
|
|
5288
5288
|
if (serializeDevices(lastDevices) !== serializeDevices(devices)) {
|
|
5289
5289
|
lastDevices = devices;
|
|
@@ -5336,14 +5336,22 @@ class WavRecorder {
|
|
|
5336
5336
|
}
|
|
5337
5337
|
|
|
5338
5338
|
/**
|
|
5339
|
-
* List all eligible devices for recording
|
|
5339
|
+
* List all eligible devices for recording.
|
|
5340
|
+
*
|
|
5341
|
+
* By default this will *not* request mic permission; labels may be empty until
|
|
5342
|
+
* the user has granted permission via begin()/getUserMedia.
|
|
5343
|
+
* Pass { requestPermission: true } to explicitly trigger a permission prompt.
|
|
5344
|
+
*
|
|
5345
|
+
* @param {{ requestPermission?: boolean }} [options]
|
|
5340
5346
|
* @returns {Promise<Array<MediaDeviceInfo & {default: boolean}>>}
|
|
5341
5347
|
*/
|
|
5342
|
-
async listDevices() {
|
|
5348
|
+
async listDevices({ requestPermission = false } = {}) {
|
|
5343
5349
|
if (!navigator.mediaDevices || !('enumerateDevices' in navigator.mediaDevices)) {
|
|
5344
5350
|
throw new Error('Could not request user devices');
|
|
5345
5351
|
}
|
|
5346
|
-
|
|
5352
|
+
if (requestPermission) {
|
|
5353
|
+
await this.requestPermission();
|
|
5354
|
+
}
|
|
5347
5355
|
|
|
5348
5356
|
const devices = await navigator.mediaDevices.enumerateDevices();
|
|
5349
5357
|
const audioDevices = devices.filter((device) => device.kind === 'audioinput');
|
|
@@ -5393,7 +5401,7 @@ class WavRecorder {
|
|
|
5393
5401
|
config.audio.deviceId = { exact: deviceId };
|
|
5394
5402
|
}
|
|
5395
5403
|
this.stream = await navigator.mediaDevices.getUserMedia(config);
|
|
5396
|
-
// Mark permission as granted so
|
|
5404
|
+
// Mark permission as granted so requestPermission() can skip expensive redundant getUserMedia calls
|
|
5397
5405
|
this._hasPermission = true;
|
|
5398
5406
|
} catch (err) {
|
|
5399
5407
|
throw err;
|
|
@@ -5746,6 +5754,29 @@ function arrayBufferToBase64(arrayBuffer) {
|
|
|
5746
5754
|
/* eslint-env browser */
|
|
5747
5755
|
// import { env as ortEnv } from 'onnxruntime-web';
|
|
5748
5756
|
// @ts-ignore - VAD package does not provide TypeScript types
|
|
5757
|
+
/**
|
|
5758
|
+
* Layercode Web SDK notes / gotchas
|
|
5759
|
+
*
|
|
5760
|
+
* Modes:
|
|
5761
|
+
* - audioInput=false => text-only mode. Do NOT touch getUserMedia or request mic permissions.
|
|
5762
|
+
* - audioInput=true => capture/send mic audio (may trigger permission prompt).
|
|
5763
|
+
* - audioOutput=false => do not play audio, but MUST still send
|
|
5764
|
+
* `trigger.response.audio.replay_finished` once per assistant turn so the server can advance.
|
|
5765
|
+
*
|
|
5766
|
+
* Transcription:
|
|
5767
|
+
* - trigger='push_to_talk' => no VAD; only send audio between triggerUserTurnStarted/Finished.
|
|
5768
|
+
* - trigger='automatic' => VAD drives userSpeaking + optional audio gating.
|
|
5769
|
+
*
|
|
5770
|
+
* Performance:
|
|
5771
|
+
* - Mobile browsers e.g. iOS Safari media APIs can be slow; avoid multiple sequential getUserMedia calls.
|
|
5772
|
+
* This file starts the recorder first, then sets up device listeners.
|
|
5773
|
+
*
|
|
5774
|
+
* Compatibility:
|
|
5775
|
+
* - This is consumed by the Layercode React SDK; treat public API/event shape changes as breaking.
|
|
5776
|
+
*
|
|
5777
|
+
* Assets:
|
|
5778
|
+
* - VAD/ORT assets are loaded from assets.layercode.com (Cloudflare).
|
|
5779
|
+
*/
|
|
5749
5780
|
const NOOP = () => { };
|
|
5750
5781
|
const DEFAULT_WS_URL = 'wss://api.layercode.com/v1/agents/web/websocket';
|
|
5751
5782
|
// SDK version - updated when publishing
|
|
@@ -5763,12 +5794,12 @@ const toLayercodeAudioInputDevice = (device) => {
|
|
|
5763
5794
|
}
|
|
5764
5795
|
return cloned;
|
|
5765
5796
|
};
|
|
5766
|
-
const listAudioInputDevices = async () => {
|
|
5797
|
+
const listAudioInputDevices = async (options = {}) => {
|
|
5767
5798
|
if (!hasMediaDevicesSupport()) {
|
|
5768
5799
|
throw new Error('Media devices are not available in this environment');
|
|
5769
5800
|
}
|
|
5770
5801
|
const recorder = new WavRecorder({ sampleRate: DEFAULT_RECORDER_SAMPLE_RATE });
|
|
5771
|
-
const devices = (await recorder.listDevices());
|
|
5802
|
+
const devices = (await recorder.listDevices({ requestPermission: Boolean(options.requestPermission) }));
|
|
5772
5803
|
return devices.map(toLayercodeAudioInputDevice);
|
|
5773
5804
|
};
|
|
5774
5805
|
const watchAudioInputDevices = (callback) => {
|
|
@@ -6711,8 +6742,8 @@ class LayercodeClient {
|
|
|
6711
6742
|
* List all available audio input devices
|
|
6712
6743
|
* @returns {Promise<Array<MediaDeviceInfo & {default: boolean}>>}
|
|
6713
6744
|
*/
|
|
6714
|
-
async listDevices() {
|
|
6715
|
-
return this.wavRecorder.listDevices();
|
|
6745
|
+
async listDevices(options) {
|
|
6746
|
+
return this.wavRecorder.listDevices(options);
|
|
6716
6747
|
}
|
|
6717
6748
|
/**
|
|
6718
6749
|
* Switches the input device for the microphone and restarts recording
|