@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.
@@ -1309,54 +1309,14 @@ registerProcessor('audio_processor', AudioProcessor);
1309
1309
  * @returns {Promise<true>}
1310
1310
  */
1311
1311
  async requestPermission() {
1312
- const ensureUserMediaAccess = async () => {
1313
- const stream = await navigator.mediaDevices.getUserMedia({
1312
+ try {
1313
+ console.log('ensureUserMediaAccess');
1314
+ await navigator.mediaDevices.getUserMedia({
1314
1315
  audio: true,
1315
1316
  });
1316
- const tracks = stream.getTracks();
1317
- tracks.forEach((track) => track.stop());
1318
- };
1319
-
1320
- const permissionsUnsupported =
1321
- !navigator.permissions ||
1322
- typeof navigator.permissions.query !== 'function';
1323
-
1324
- if (permissionsUnsupported) {
1325
- try {
1326
- await ensureUserMediaAccess();
1327
- } catch (error) {
1328
- window.alert('You must grant microphone access to use this feature.');
1329
- throw error;
1330
- }
1331
- return true;
1332
- }
1333
-
1334
- try {
1335
- const permissionStatus = await navigator.permissions.query({
1336
- name: 'microphone',
1337
- });
1338
-
1339
- if (permissionStatus.state === 'denied') {
1340
- window.alert('You must grant microphone access to use this feature.');
1341
- return true;
1342
- }
1343
-
1344
- if (permissionStatus.state === 'prompt') {
1345
- try {
1346
- await ensureUserMediaAccess();
1347
- } catch (error) {
1348
- window.alert('You must grant microphone access to use this feature.');
1349
- throw error;
1350
- }
1351
- }
1352
- } catch (error) {
1353
- // Firefox rejects permissions.query with NotSupportedError – fall back to getUserMedia directly
1354
- try {
1355
- await ensureUserMediaAccess();
1356
- } catch (fallbackError) {
1357
- window.alert('You must grant microphone access to use this feature.');
1358
- throw fallbackError;
1359
- }
1317
+ } catch (fallbackError) {
1318
+ window.alert('You must grant microphone access to use this feature.');
1319
+ throw fallbackError;
1360
1320
  }
1361
1321
  return true;
1362
1322
  }
@@ -1373,10 +1333,9 @@ registerProcessor('audio_processor', AudioProcessor);
1373
1333
  throw new Error('Could not request user devices');
1374
1334
  }
1375
1335
  await this.requestPermission();
1336
+
1376
1337
  const devices = await navigator.mediaDevices.enumerateDevices();
1377
- const audioDevices = devices.filter(
1378
- (device) => device.kind === 'audioinput',
1379
- );
1338
+ const audioDevices = devices.filter((device) => device.kind === 'audioinput');
1380
1339
  const defaultDeviceIndex = audioDevices.findIndex(
1381
1340
  (device) => device.deviceId === 'default',
1382
1341
  );
@@ -3672,7 +3631,7 @@ registerProcessor('audio_processor', AudioProcessor);
3672
3631
  * @param {Object} options - Configuration options
3673
3632
  */
3674
3633
  constructor(options) {
3675
- var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p;
3634
+ var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q;
3676
3635
  this.deviceId = null;
3677
3636
  this.options = {
3678
3637
  agentId: options.agentId,
@@ -3684,13 +3643,14 @@ registerProcessor('audio_processor', AudioProcessor);
3684
3643
  onDisconnect: (_e = options.onDisconnect) !== null && _e !== void 0 ? _e : NOOP,
3685
3644
  onError: (_f = options.onError) !== null && _f !== void 0 ? _f : NOOP,
3686
3645
  onDeviceSwitched: (_g = options.onDeviceSwitched) !== null && _g !== void 0 ? _g : NOOP,
3687
- onDataMessage: (_h = options.onDataMessage) !== null && _h !== void 0 ? _h : NOOP,
3688
- onMessage: (_j = options.onMessage) !== null && _j !== void 0 ? _j : NOOP,
3689
- onUserAmplitudeChange: (_k = options.onUserAmplitudeChange) !== null && _k !== void 0 ? _k : NOOP,
3690
- onAgentAmplitudeChange: (_l = options.onAgentAmplitudeChange) !== null && _l !== void 0 ? _l : NOOP,
3691
- onStatusChange: (_m = options.onStatusChange) !== null && _m !== void 0 ? _m : NOOP,
3692
- onUserIsSpeakingChange: (_o = options.onUserIsSpeakingChange) !== null && _o !== void 0 ? _o : NOOP,
3693
- onMuteStateChange: (_p = options.onMuteStateChange) !== null && _p !== void 0 ? _p : NOOP,
3646
+ onDevicesChanged: (_h = options.onDevicesChanged) !== null && _h !== void 0 ? _h : NOOP,
3647
+ onDataMessage: (_j = options.onDataMessage) !== null && _j !== void 0 ? _j : NOOP,
3648
+ onMessage: (_k = options.onMessage) !== null && _k !== void 0 ? _k : NOOP,
3649
+ onUserAmplitudeChange: (_l = options.onUserAmplitudeChange) !== null && _l !== void 0 ? _l : NOOP,
3650
+ onAgentAmplitudeChange: (_m = options.onAgentAmplitudeChange) !== null && _m !== void 0 ? _m : NOOP,
3651
+ onStatusChange: (_o = options.onStatusChange) !== null && _o !== void 0 ? _o : NOOP,
3652
+ onUserIsSpeakingChange: (_p = options.onUserIsSpeakingChange) !== null && _p !== void 0 ? _p : NOOP,
3653
+ onMuteStateChange: (_q = options.onMuteStateChange) !== null && _q !== void 0 ? _q : NOOP,
3694
3654
  };
3695
3655
  this.AMPLITUDE_MONITORING_SAMPLE_RATE = 2;
3696
3656
  this._websocketUrl = DEFAULT_WS_URL;
@@ -4032,7 +3992,6 @@ registerProcessor('audio_processor', AudioProcessor);
4032
3992
  // Reset turn tracking for clean start
4033
3993
  this._resetTurnTracking();
4034
3994
  this._stopAmplitudeMonitoring();
4035
- this._setupDeviceChangeListener();
4036
3995
  // Get conversation key from server
4037
3996
  let authorizeSessionRequestBody = {
4038
3997
  agent_id: this.options.agentId,
@@ -4056,6 +4015,8 @@ registerProcessor('audio_processor', AudioProcessor);
4056
4015
  const authorizeSessionResponseBody = await authorizeSessionResponse.json();
4057
4016
  this.conversationId = authorizeSessionResponseBody.conversation_id; // Save the conversation_id for use in future reconnects
4058
4017
  this.options.conversationId = this.conversationId;
4018
+ await this.wavRecorder.requestPermission();
4019
+ this._setupDeviceChangeListener();
4059
4020
  // Connect WebSocket
4060
4021
  this.ws = new WebSocket(`${this._websocketUrl}?${new URLSearchParams({
4061
4022
  client_session_key: authorizeSessionResponseBody.client_session_key,
@@ -4108,7 +4069,6 @@ registerProcessor('audio_processor', AudioProcessor);
4108
4069
  console.error('Error connecting to Layercode agent:', error);
4109
4070
  this._setStatus('error');
4110
4071
  this.options.onError(error instanceof Error ? error : new Error(String(error)));
4111
- throw error;
4112
4072
  }
4113
4073
  }
4114
4074
  _resetTurnTracking() {
@@ -4136,6 +4096,13 @@ registerProcessor('audio_processor', AudioProcessor);
4136
4096
  getStream() {
4137
4097
  return this.wavRecorder.getStream();
4138
4098
  }
4099
+ /**
4100
+ * List all available audio input devices
4101
+ * @returns {Promise<Array<MediaDeviceInfo & {default: boolean}>>}
4102
+ */
4103
+ async listDevices() {
4104
+ return this.wavRecorder.listDevices();
4105
+ }
4139
4106
  /**
4140
4107
  * Switches the input device for the microphone and restarts recording
4141
4108
  * @param {string} deviceId - The deviceId of the new microphone
@@ -4228,6 +4195,8 @@ registerProcessor('audio_processor', AudioProcessor);
4228
4195
  if (!this.deviceChangeListener) {
4229
4196
  this.deviceChangeListener = async (devices) => {
4230
4197
  try {
4198
+ // Notify user that devices have changed
4199
+ this.options.onDevicesChanged(devices);
4231
4200
  const defaultDevice = devices.find((device) => device.default);
4232
4201
  const usingDefaultDevice = this.useSystemDefaultDevice;
4233
4202
  const previousDefaultDeviceKey = this.lastKnownSystemDefaultDeviceKey;