@estuary-ai/sdk 0.1.7 → 0.1.8
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 +40 -1
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +40 -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 {
|
|
@@ -3940,6 +3960,7 @@ var AudioPlayer = class {
|
|
|
3940
3960
|
return ctx;
|
|
3941
3961
|
}
|
|
3942
3962
|
playNext() {
|
|
3963
|
+
if (this._isCleared) return;
|
|
3943
3964
|
const ctx = this.getAudioContext();
|
|
3944
3965
|
if (!ctx || this.queue.length === 0) {
|
|
3945
3966
|
if (this.isPlaying && this.currentMessageId) {
|
|
@@ -3963,6 +3984,7 @@ var AudioPlayer = class {
|
|
|
3963
3984
|
source.connect(this.mediaStreamDest ?? ctx.destination);
|
|
3964
3985
|
this.currentSource = source;
|
|
3965
3986
|
source.onended = () => {
|
|
3987
|
+
if (this._isCleared) return;
|
|
3966
3988
|
this.currentSource = null;
|
|
3967
3989
|
this.playNext();
|
|
3968
3990
|
};
|
|
@@ -4071,6 +4093,7 @@ var EstuaryClient = class extends TypedEventEmitter {
|
|
|
4071
4093
|
_memory;
|
|
4072
4094
|
_sessionInfo = null;
|
|
4073
4095
|
actionParsers = /* @__PURE__ */ new Map();
|
|
4096
|
+
_hasAutoInterrupted = false;
|
|
4074
4097
|
constructor(config) {
|
|
4075
4098
|
super();
|
|
4076
4099
|
this.config = config;
|
|
@@ -4121,6 +4144,7 @@ var EstuaryClient = class extends TypedEventEmitter {
|
|
|
4121
4144
|
interrupt(messageId) {
|
|
4122
4145
|
this.ensureConnected();
|
|
4123
4146
|
this.socketManager.emitEvent("client_interrupt", { message_id: messageId });
|
|
4147
|
+
this.audioPlayer?.setInterruptedMessageId(messageId ?? this.audioPlayer.playingMessageId);
|
|
4124
4148
|
this.audioPlayer?.clear();
|
|
4125
4149
|
if (this.config.suppressMicDuringPlayback) {
|
|
4126
4150
|
this.voiceManager?.setSuppressed?.(false);
|
|
@@ -4162,6 +4186,7 @@ var EstuaryClient = class extends TypedEventEmitter {
|
|
|
4162
4186
|
if (!this.audioPlayer && typeof AudioContext !== "undefined") {
|
|
4163
4187
|
this.audioPlayer = new AudioPlayer(sampleRate, (event) => {
|
|
4164
4188
|
if (event.type === "started") {
|
|
4189
|
+
this._hasAutoInterrupted = false;
|
|
4165
4190
|
this.emit("audioPlaybackStarted", event.messageId);
|
|
4166
4191
|
if (this.config.suppressMicDuringPlayback) {
|
|
4167
4192
|
this.voiceManager?.setSuppressed?.(true);
|
|
@@ -4222,10 +4247,15 @@ var EstuaryClient = class extends TypedEventEmitter {
|
|
|
4222
4247
|
this.socketManager.on("connectionStateChanged", (state) => this.emit("connectionStateChanged", state));
|
|
4223
4248
|
this.socketManager.on("botResponse", (response) => this.handleBotResponse(response));
|
|
4224
4249
|
this.socketManager.on("botVoice", (voice) => this.handleBotVoice(voice));
|
|
4225
|
-
this.socketManager.on("sttResponse", (response) =>
|
|
4250
|
+
this.socketManager.on("sttResponse", (response) => {
|
|
4251
|
+
this.maybeAutoInterrupt(response);
|
|
4252
|
+
this.emit("sttResponse", response);
|
|
4253
|
+
});
|
|
4226
4254
|
this.socketManager.on("interrupt", (data) => {
|
|
4255
|
+
this.audioPlayer?.setInterruptedMessageId(data.messageId ?? null);
|
|
4227
4256
|
this.audioPlayer?.clear();
|
|
4228
4257
|
this.actionParsers.clear();
|
|
4258
|
+
this._hasAutoInterrupted = false;
|
|
4229
4259
|
if (this.config.suppressMicDuringPlayback) {
|
|
4230
4260
|
this.voiceManager?.setSuppressed?.(false);
|
|
4231
4261
|
}
|
|
@@ -4265,6 +4295,15 @@ var EstuaryClient = class extends TypedEventEmitter {
|
|
|
4265
4295
|
this.emit("botVoice", voice);
|
|
4266
4296
|
this.audioPlayer?.enqueue(voice);
|
|
4267
4297
|
}
|
|
4298
|
+
maybeAutoInterrupt(stt) {
|
|
4299
|
+
if ((this.config.autoInterruptOnSpeech ?? true) === false) return;
|
|
4300
|
+
if (this.config.suppressMicDuringPlayback) return;
|
|
4301
|
+
if (stt.isFinal) return;
|
|
4302
|
+
if (!this.audioPlayer?.playing) return;
|
|
4303
|
+
if (this._hasAutoInterrupted) return;
|
|
4304
|
+
this._hasAutoInterrupted = true;
|
|
4305
|
+
this.interrupt();
|
|
4306
|
+
}
|
|
4268
4307
|
};
|
|
4269
4308
|
|
|
4270
4309
|
export { ConnectionState, EstuaryClient, parseActions };
|