@layercode/js-sdk 2.1.6 → 2.2.0
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/dist/layercode-js-sdk.esm.js +33 -60
- package/dist/layercode-js-sdk.esm.js.map +1 -1
- package/dist/layercode-js-sdk.min.js +33 -60
- package/dist/layercode-js-sdk.min.js.map +1 -1
- package/dist/types/index.d.ts +16 -0
- package/dist/types/interfaces.d.ts +6 -2
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -16,4 +16,4 @@ Or you can use a script tag in your HTML:
|
|
|
16
16
|
|
|
17
17
|
## Usage
|
|
18
18
|
|
|
19
|
-
Read the docs: [https://docs.layercode.com/sdk-reference/
|
|
19
|
+
Read the docs: [https://docs.layercode.com/sdk-reference/vanilla-js-sdk](https://docs.layercode.com/sdk-reference/vanilla-js-sdk)
|
|
@@ -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({
|
|
1308
|
-
audio: true,
|
|
1309
|
-
});
|
|
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
1306
|
try {
|
|
1329
|
-
|
|
1330
|
-
|
|
1307
|
+
console.log('ensureUserMediaAccess');
|
|
1308
|
+
await navigator.mediaDevices.getUserMedia({
|
|
1309
|
+
audio: true,
|
|
1331
1310
|
});
|
|
1332
|
-
|
|
1333
|
-
|
|
1334
|
-
|
|
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
|
);
|
|
@@ -3655,7 +3614,7 @@ function arrayBufferToBase64(arrayBuffer) {
|
|
|
3655
3614
|
const NOOP = () => { };
|
|
3656
3615
|
const DEFAULT_WS_URL = 'wss://api.layercode.com/v1/agents/web/websocket';
|
|
3657
3616
|
// SDK version - updated when publishing
|
|
3658
|
-
const SDK_VERSION = '2.
|
|
3617
|
+
const SDK_VERSION = '2.2.0';
|
|
3659
3618
|
/**
|
|
3660
3619
|
* @class LayercodeClient
|
|
3661
3620
|
* @classdesc Core client for Layercode audio agent that manages audio recording, WebSocket communication, and speech processing.
|
|
@@ -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
|
-
|
|
3682
|
-
|
|
3683
|
-
|
|
3684
|
-
|
|
3685
|
-
|
|
3686
|
-
|
|
3687
|
-
|
|
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;
|
|
@@ -3842,6 +3802,10 @@ class LayercodeClient {
|
|
|
3842
3802
|
this._wsSend({ type: 'trigger.turn.end', role: 'user' });
|
|
3843
3803
|
}
|
|
3844
3804
|
}
|
|
3805
|
+
async sendClientResponseText(text) {
|
|
3806
|
+
await this._clientInterruptAssistantReplay();
|
|
3807
|
+
this._wsSend({ type: 'client.response.text', content: text });
|
|
3808
|
+
}
|
|
3845
3809
|
/**
|
|
3846
3810
|
* Handles incoming WebSocket messages
|
|
3847
3811
|
* @param {MessageEvent} event - The WebSocket message event
|
|
@@ -4026,7 +3990,6 @@ class LayercodeClient {
|
|
|
4026
3990
|
// Reset turn tracking for clean start
|
|
4027
3991
|
this._resetTurnTracking();
|
|
4028
3992
|
this._stopAmplitudeMonitoring();
|
|
4029
|
-
this._setupDeviceChangeListener();
|
|
4030
3993
|
// Get conversation key from server
|
|
4031
3994
|
let authorizeSessionRequestBody = {
|
|
4032
3995
|
agent_id: this.options.agentId,
|
|
@@ -4050,6 +4013,8 @@ class LayercodeClient {
|
|
|
4050
4013
|
const authorizeSessionResponseBody = await authorizeSessionResponse.json();
|
|
4051
4014
|
this.conversationId = authorizeSessionResponseBody.conversation_id; // Save the conversation_id for use in future reconnects
|
|
4052
4015
|
this.options.conversationId = this.conversationId;
|
|
4016
|
+
await this.wavRecorder.requestPermission();
|
|
4017
|
+
this._setupDeviceChangeListener();
|
|
4053
4018
|
// Connect WebSocket
|
|
4054
4019
|
this.ws = new WebSocket(`${this._websocketUrl}?${new URLSearchParams({
|
|
4055
4020
|
client_session_key: authorizeSessionResponseBody.client_session_key,
|
|
@@ -4102,7 +4067,6 @@ class LayercodeClient {
|
|
|
4102
4067
|
console.error('Error connecting to Layercode agent:', error);
|
|
4103
4068
|
this._setStatus('error');
|
|
4104
4069
|
this.options.onError(error instanceof Error ? error : new Error(String(error)));
|
|
4105
|
-
throw error;
|
|
4106
4070
|
}
|
|
4107
4071
|
}
|
|
4108
4072
|
_resetTurnTracking() {
|
|
@@ -4130,6 +4094,13 @@ class LayercodeClient {
|
|
|
4130
4094
|
getStream() {
|
|
4131
4095
|
return this.wavRecorder.getStream();
|
|
4132
4096
|
}
|
|
4097
|
+
/**
|
|
4098
|
+
* List all available audio input devices
|
|
4099
|
+
* @returns {Promise<Array<MediaDeviceInfo & {default: boolean}>>}
|
|
4100
|
+
*/
|
|
4101
|
+
async listDevices() {
|
|
4102
|
+
return this.wavRecorder.listDevices();
|
|
4103
|
+
}
|
|
4133
4104
|
/**
|
|
4134
4105
|
* Switches the input device for the microphone and restarts recording
|
|
4135
4106
|
* @param {string} deviceId - The deviceId of the new microphone
|
|
@@ -4222,6 +4193,8 @@ class LayercodeClient {
|
|
|
4222
4193
|
if (!this.deviceChangeListener) {
|
|
4223
4194
|
this.deviceChangeListener = async (devices) => {
|
|
4224
4195
|
try {
|
|
4196
|
+
// Notify user that devices have changed
|
|
4197
|
+
this.options.onDevicesChanged(devices);
|
|
4225
4198
|
const defaultDevice = devices.find((device) => device.default);
|
|
4226
4199
|
const usingDefaultDevice = this.useSystemDefaultDevice;
|
|
4227
4200
|
const previousDefaultDeviceKey = this.lastKnownSystemDefaultDeviceKey;
|