@layercode/js-sdk 2.1.6 → 2.1.7

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.
@@ -1303,54 +1303,14 @@ class WavRecorder {
1303
1303
  * @returns {Promise<true>}
1304
1304
  */
1305
1305
  async requestPermission() {
1306
- const ensureUserMediaAccess = async () => {
1307
- const stream = await navigator.mediaDevices.getUserMedia({
1306
+ try {
1307
+ console.log('ensureUserMediaAccess');
1308
+ await navigator.mediaDevices.getUserMedia({
1308
1309
  audio: true,
1309
1310
  });
1310
- const tracks = stream.getTracks();
1311
- tracks.forEach((track) => track.stop());
1312
- };
1313
-
1314
- const permissionsUnsupported =
1315
- !navigator.permissions ||
1316
- typeof navigator.permissions.query !== 'function';
1317
-
1318
- if (permissionsUnsupported) {
1319
- try {
1320
- await ensureUserMediaAccess();
1321
- } catch (error) {
1322
- window.alert('You must grant microphone access to use this feature.');
1323
- throw error;
1324
- }
1325
- return true;
1326
- }
1327
-
1328
- try {
1329
- const permissionStatus = await navigator.permissions.query({
1330
- name: 'microphone',
1331
- });
1332
-
1333
- if (permissionStatus.state === 'denied') {
1334
- window.alert('You must grant microphone access to use this feature.');
1335
- return true;
1336
- }
1337
-
1338
- if (permissionStatus.state === 'prompt') {
1339
- try {
1340
- await ensureUserMediaAccess();
1341
- } catch (error) {
1342
- window.alert('You must grant microphone access to use this feature.');
1343
- throw error;
1344
- }
1345
- }
1346
- } catch (error) {
1347
- // Firefox rejects permissions.query with NotSupportedError – fall back to getUserMedia directly
1348
- try {
1349
- await ensureUserMediaAccess();
1350
- } catch (fallbackError) {
1351
- window.alert('You must grant microphone access to use this feature.');
1352
- throw fallbackError;
1353
- }
1311
+ } catch (fallbackError) {
1312
+ window.alert('You must grant microphone access to use this feature.');
1313
+ throw fallbackError;
1354
1314
  }
1355
1315
  return true;
1356
1316
  }
@@ -1367,10 +1327,9 @@ class WavRecorder {
1367
1327
  throw new Error('Could not request user devices');
1368
1328
  }
1369
1329
  await this.requestPermission();
1330
+
1370
1331
  const devices = await navigator.mediaDevices.enumerateDevices();
1371
- const audioDevices = devices.filter(
1372
- (device) => device.kind === 'audioinput',
1373
- );
1332
+ const audioDevices = devices.filter((device) => device.kind === 'audioinput');
1374
1333
  const defaultDeviceIndex = audioDevices.findIndex(
1375
1334
  (device) => device.deviceId === 'default',
1376
1335
  );
@@ -3666,7 +3625,7 @@ class LayercodeClient {
3666
3625
  * @param {Object} options - Configuration options
3667
3626
  */
3668
3627
  constructor(options) {
3669
- var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p;
3628
+ var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q;
3670
3629
  this.deviceId = null;
3671
3630
  this.options = {
3672
3631
  agentId: options.agentId,
@@ -3678,13 +3637,14 @@ class LayercodeClient {
3678
3637
  onDisconnect: (_e = options.onDisconnect) !== null && _e !== void 0 ? _e : NOOP,
3679
3638
  onError: (_f = options.onError) !== null && _f !== void 0 ? _f : NOOP,
3680
3639
  onDeviceSwitched: (_g = options.onDeviceSwitched) !== null && _g !== void 0 ? _g : NOOP,
3681
- onDataMessage: (_h = options.onDataMessage) !== null && _h !== void 0 ? _h : NOOP,
3682
- onMessage: (_j = options.onMessage) !== null && _j !== void 0 ? _j : NOOP,
3683
- onUserAmplitudeChange: (_k = options.onUserAmplitudeChange) !== null && _k !== void 0 ? _k : NOOP,
3684
- onAgentAmplitudeChange: (_l = options.onAgentAmplitudeChange) !== null && _l !== void 0 ? _l : NOOP,
3685
- onStatusChange: (_m = options.onStatusChange) !== null && _m !== void 0 ? _m : NOOP,
3686
- onUserIsSpeakingChange: (_o = options.onUserIsSpeakingChange) !== null && _o !== void 0 ? _o : NOOP,
3687
- onMuteStateChange: (_p = options.onMuteStateChange) !== null && _p !== void 0 ? _p : NOOP,
3640
+ onDevicesChanged: (_h = options.onDevicesChanged) !== null && _h !== void 0 ? _h : NOOP,
3641
+ onDataMessage: (_j = options.onDataMessage) !== null && _j !== void 0 ? _j : NOOP,
3642
+ onMessage: (_k = options.onMessage) !== null && _k !== void 0 ? _k : NOOP,
3643
+ onUserAmplitudeChange: (_l = options.onUserAmplitudeChange) !== null && _l !== void 0 ? _l : NOOP,
3644
+ onAgentAmplitudeChange: (_m = options.onAgentAmplitudeChange) !== null && _m !== void 0 ? _m : NOOP,
3645
+ onStatusChange: (_o = options.onStatusChange) !== null && _o !== void 0 ? _o : NOOP,
3646
+ onUserIsSpeakingChange: (_p = options.onUserIsSpeakingChange) !== null && _p !== void 0 ? _p : NOOP,
3647
+ onMuteStateChange: (_q = options.onMuteStateChange) !== null && _q !== void 0 ? _q : NOOP,
3688
3648
  };
3689
3649
  this.AMPLITUDE_MONITORING_SAMPLE_RATE = 2;
3690
3650
  this._websocketUrl = DEFAULT_WS_URL;
@@ -4026,7 +3986,6 @@ class LayercodeClient {
4026
3986
  // Reset turn tracking for clean start
4027
3987
  this._resetTurnTracking();
4028
3988
  this._stopAmplitudeMonitoring();
4029
- this._setupDeviceChangeListener();
4030
3989
  // Get conversation key from server
4031
3990
  let authorizeSessionRequestBody = {
4032
3991
  agent_id: this.options.agentId,
@@ -4050,6 +4009,8 @@ class LayercodeClient {
4050
4009
  const authorizeSessionResponseBody = await authorizeSessionResponse.json();
4051
4010
  this.conversationId = authorizeSessionResponseBody.conversation_id; // Save the conversation_id for use in future reconnects
4052
4011
  this.options.conversationId = this.conversationId;
4012
+ await this.wavRecorder.requestPermission();
4013
+ this._setupDeviceChangeListener();
4053
4014
  // Connect WebSocket
4054
4015
  this.ws = new WebSocket(`${this._websocketUrl}?${new URLSearchParams({
4055
4016
  client_session_key: authorizeSessionResponseBody.client_session_key,
@@ -4102,7 +4063,6 @@ class LayercodeClient {
4102
4063
  console.error('Error connecting to Layercode agent:', error);
4103
4064
  this._setStatus('error');
4104
4065
  this.options.onError(error instanceof Error ? error : new Error(String(error)));
4105
- throw error;
4106
4066
  }
4107
4067
  }
4108
4068
  _resetTurnTracking() {
@@ -4130,6 +4090,13 @@ class LayercodeClient {
4130
4090
  getStream() {
4131
4091
  return this.wavRecorder.getStream();
4132
4092
  }
4093
+ /**
4094
+ * List all available audio input devices
4095
+ * @returns {Promise<Array<MediaDeviceInfo & {default: boolean}>>}
4096
+ */
4097
+ async listDevices() {
4098
+ return this.wavRecorder.listDevices();
4099
+ }
4133
4100
  /**
4134
4101
  * Switches the input device for the microphone and restarts recording
4135
4102
  * @param {string} deviceId - The deviceId of the new microphone
@@ -4222,6 +4189,8 @@ class LayercodeClient {
4222
4189
  if (!this.deviceChangeListener) {
4223
4190
  this.deviceChangeListener = async (devices) => {
4224
4191
  try {
4192
+ // Notify user that devices have changed
4193
+ this.options.onDevicesChanged(devices);
4225
4194
  const defaultDevice = devices.find((device) => device.default);
4226
4195
  const usingDefaultDevice = this.useSystemDefaultDevice;
4227
4196
  const previousDefaultDeviceKey = this.lastKnownSystemDefaultDeviceKey;