@estuary-ai/sdk 0.1.7 → 0.1.9
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/dist/index.d.mts +4 -0
- package/dist/index.js +42 -1
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +42 -1
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
package/dist/index.mjs
CHANGED
|
@@ -3871,11 +3871,30 @@ var AudioPlayer = class {
|
|
|
3871
3871
|
currentSource = null;
|
|
3872
3872
|
currentMessageId = null;
|
|
3873
3873
|
isPlaying = false;
|
|
3874
|
+
_isCleared = false;
|
|
3875
|
+
_interruptedMessageId = null;
|
|
3874
3876
|
constructor(sampleRate, onEvent) {
|
|
3875
3877
|
this.sampleRate = sampleRate;
|
|
3876
3878
|
this.onEvent = onEvent;
|
|
3877
3879
|
}
|
|
3880
|
+
/** Whether audio is currently playing */
|
|
3881
|
+
get playing() {
|
|
3882
|
+
return this.isPlaying;
|
|
3883
|
+
}
|
|
3884
|
+
/** The messageId of the currently playing audio, or null */
|
|
3885
|
+
get playingMessageId() {
|
|
3886
|
+
return this.currentMessageId;
|
|
3887
|
+
}
|
|
3888
|
+
/** Mark a messageId as interrupted so late-arriving chunks are dropped */
|
|
3889
|
+
setInterruptedMessageId(id) {
|
|
3890
|
+
this._interruptedMessageId = id;
|
|
3891
|
+
}
|
|
3878
3892
|
enqueue(voice) {
|
|
3893
|
+
if (voice.messageId === this._interruptedMessageId) return;
|
|
3894
|
+
if (this._interruptedMessageId && voice.messageId !== this._interruptedMessageId) {
|
|
3895
|
+
this._interruptedMessageId = null;
|
|
3896
|
+
}
|
|
3897
|
+
this._isCleared = false;
|
|
3879
3898
|
const ctx = this.getAudioContext();
|
|
3880
3899
|
if (!ctx) return;
|
|
3881
3900
|
const pcm16 = base64ToInt16Array(voice.audio);
|
|
@@ -3888,6 +3907,7 @@ var AudioPlayer = class {
|
|
|
3888
3907
|
}
|
|
3889
3908
|
}
|
|
3890
3909
|
clear() {
|
|
3910
|
+
this._isCleared = true;
|
|
3891
3911
|
this.queue.length = 0;
|
|
3892
3912
|
if (this.currentSource) {
|
|
3893
3913
|
try {
|
|
@@ -3897,6 +3917,7 @@ var AudioPlayer = class {
|
|
|
3897
3917
|
}
|
|
3898
3918
|
this.currentSource = null;
|
|
3899
3919
|
}
|
|
3920
|
+
if (this.audioElement) this.audioElement.muted = true;
|
|
3900
3921
|
this.isPlaying = false;
|
|
3901
3922
|
this.currentMessageId = null;
|
|
3902
3923
|
}
|
|
@@ -3940,6 +3961,7 @@ var AudioPlayer = class {
|
|
|
3940
3961
|
return ctx;
|
|
3941
3962
|
}
|
|
3942
3963
|
playNext() {
|
|
3964
|
+
if (this._isCleared) return;
|
|
3943
3965
|
const ctx = this.getAudioContext();
|
|
3944
3966
|
if (!ctx || this.queue.length === 0) {
|
|
3945
3967
|
if (this.isPlaying && this.currentMessageId) {
|
|
@@ -3963,9 +3985,11 @@ var AudioPlayer = class {
|
|
|
3963
3985
|
source.connect(this.mediaStreamDest ?? ctx.destination);
|
|
3964
3986
|
this.currentSource = source;
|
|
3965
3987
|
source.onended = () => {
|
|
3988
|
+
if (this._isCleared) return;
|
|
3966
3989
|
this.currentSource = null;
|
|
3967
3990
|
this.playNext();
|
|
3968
3991
|
};
|
|
3992
|
+
if (this.audioElement) this.audioElement.muted = false;
|
|
3969
3993
|
ctx.resume().catch(() => {
|
|
3970
3994
|
});
|
|
3971
3995
|
source.start();
|
|
@@ -4071,6 +4095,7 @@ var EstuaryClient = class extends TypedEventEmitter {
|
|
|
4071
4095
|
_memory;
|
|
4072
4096
|
_sessionInfo = null;
|
|
4073
4097
|
actionParsers = /* @__PURE__ */ new Map();
|
|
4098
|
+
_hasAutoInterrupted = false;
|
|
4074
4099
|
constructor(config) {
|
|
4075
4100
|
super();
|
|
4076
4101
|
this.config = config;
|
|
@@ -4121,6 +4146,7 @@ var EstuaryClient = class extends TypedEventEmitter {
|
|
|
4121
4146
|
interrupt(messageId) {
|
|
4122
4147
|
this.ensureConnected();
|
|
4123
4148
|
this.socketManager.emitEvent("client_interrupt", { message_id: messageId });
|
|
4149
|
+
this.audioPlayer?.setInterruptedMessageId(messageId ?? this.audioPlayer.playingMessageId);
|
|
4124
4150
|
this.audioPlayer?.clear();
|
|
4125
4151
|
if (this.config.suppressMicDuringPlayback) {
|
|
4126
4152
|
this.voiceManager?.setSuppressed?.(false);
|
|
@@ -4162,6 +4188,7 @@ var EstuaryClient = class extends TypedEventEmitter {
|
|
|
4162
4188
|
if (!this.audioPlayer && typeof AudioContext !== "undefined") {
|
|
4163
4189
|
this.audioPlayer = new AudioPlayer(sampleRate, (event) => {
|
|
4164
4190
|
if (event.type === "started") {
|
|
4191
|
+
this._hasAutoInterrupted = false;
|
|
4165
4192
|
this.emit("audioPlaybackStarted", event.messageId);
|
|
4166
4193
|
if (this.config.suppressMicDuringPlayback) {
|
|
4167
4194
|
this.voiceManager?.setSuppressed?.(true);
|
|
@@ -4222,10 +4249,15 @@ var EstuaryClient = class extends TypedEventEmitter {
|
|
|
4222
4249
|
this.socketManager.on("connectionStateChanged", (state) => this.emit("connectionStateChanged", state));
|
|
4223
4250
|
this.socketManager.on("botResponse", (response) => this.handleBotResponse(response));
|
|
4224
4251
|
this.socketManager.on("botVoice", (voice) => this.handleBotVoice(voice));
|
|
4225
|
-
this.socketManager.on("sttResponse", (response) =>
|
|
4252
|
+
this.socketManager.on("sttResponse", (response) => {
|
|
4253
|
+
this.maybeAutoInterrupt(response);
|
|
4254
|
+
this.emit("sttResponse", response);
|
|
4255
|
+
});
|
|
4226
4256
|
this.socketManager.on("interrupt", (data) => {
|
|
4257
|
+
this.audioPlayer?.setInterruptedMessageId(data.messageId ?? null);
|
|
4227
4258
|
this.audioPlayer?.clear();
|
|
4228
4259
|
this.actionParsers.clear();
|
|
4260
|
+
this._hasAutoInterrupted = false;
|
|
4229
4261
|
if (this.config.suppressMicDuringPlayback) {
|
|
4230
4262
|
this.voiceManager?.setSuppressed?.(false);
|
|
4231
4263
|
}
|
|
@@ -4265,6 +4297,15 @@ var EstuaryClient = class extends TypedEventEmitter {
|
|
|
4265
4297
|
this.emit("botVoice", voice);
|
|
4266
4298
|
this.audioPlayer?.enqueue(voice);
|
|
4267
4299
|
}
|
|
4300
|
+
maybeAutoInterrupt(stt) {
|
|
4301
|
+
if ((this.config.autoInterruptOnSpeech ?? true) === false) return;
|
|
4302
|
+
if (this.config.suppressMicDuringPlayback) return;
|
|
4303
|
+
if (stt.isFinal) return;
|
|
4304
|
+
if (!this.audioPlayer?.playing) return;
|
|
4305
|
+
if (this._hasAutoInterrupted) return;
|
|
4306
|
+
this._hasAutoInterrupted = true;
|
|
4307
|
+
this.interrupt();
|
|
4308
|
+
}
|
|
4268
4309
|
};
|
|
4269
4310
|
|
|
4270
4311
|
export { ConnectionState, EstuaryClient, parseActions };
|