@estuary-ai/sdk 0.1.3 → 0.1.5

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.mjs CHANGED
@@ -3738,7 +3738,7 @@ var SocketManager = class extends TypedEventEmitter {
3738
3738
  // src/voice/voice-manager.ts
3739
3739
  async function createVoiceManager(transport, socketManager, sampleRate, logger) {
3740
3740
  if (transport === "websocket") {
3741
- const { WebSocketVoiceManager } = await import('./websocket-voice-A4CK3UTM.mjs');
3741
+ const { WebSocketVoiceManager } = await import('./websocket-voice-HYHCIYEW.mjs');
3742
3742
  return new WebSocketVoiceManager(socketManager, sampleRate, logger);
3743
3743
  }
3744
3744
  if (transport === "livekit") {
@@ -3747,7 +3747,7 @@ async function createVoiceManager(transport, socketManager, sampleRate, logger)
3747
3747
  return new LiveKitVoiceManager(socketManager, logger);
3748
3748
  } catch {
3749
3749
  logger.warn("livekit-client not installed, falling back to WebSocket voice");
3750
- const { WebSocketVoiceManager } = await import('./websocket-voice-A4CK3UTM.mjs');
3750
+ const { WebSocketVoiceManager } = await import('./websocket-voice-HYHCIYEW.mjs');
3751
3751
  return new WebSocketVoiceManager(socketManager, sampleRate, logger);
3752
3752
  }
3753
3753
  }
@@ -3756,7 +3756,7 @@ async function createVoiceManager(transport, socketManager, sampleRate, logger)
3756
3756
  const { LiveKitVoiceManager } = await import('./livekit-voice-H6WZ44LM.mjs');
3757
3757
  return new LiveKitVoiceManager(socketManager, logger);
3758
3758
  } catch {
3759
- const { WebSocketVoiceManager } = await import('./websocket-voice-A4CK3UTM.mjs');
3759
+ const { WebSocketVoiceManager } = await import('./websocket-voice-HYHCIYEW.mjs');
3760
3760
  return new WebSocketVoiceManager(socketManager, sampleRate, logger);
3761
3761
  }
3762
3762
  }
@@ -3989,6 +3989,51 @@ var Logger = class {
3989
3989
  }
3990
3990
  };
3991
3991
 
3992
+ // src/utils/action-parser.ts
3993
+ var ACTION_TAG_RE = /<action\s+([^>]*?)\/>/gi;
3994
+ var ATTR_RE = /(\w+)\s*=\s*"([^"]*)"|(\w+)\s*=\s*'([^']*)'/g;
3995
+ function parseAttributes(attrString) {
3996
+ const attrs = {};
3997
+ let match;
3998
+ while ((match = ATTR_RE.exec(attrString)) !== null) {
3999
+ const key = match[1] ?? match[3];
4000
+ const value2 = match[2] ?? match[4];
4001
+ attrs[key] = value2;
4002
+ }
4003
+ return attrs;
4004
+ }
4005
+ var StreamingActionParser = class {
4006
+ emittedCount = 0;
4007
+ /**
4008
+ * Parse the accumulated response text and return any new actions found
4009
+ * since the last call. Also returns the text with all action tags stripped.
4010
+ */
4011
+ parse(accumulatedText) {
4012
+ const allActions = [];
4013
+ let match;
4014
+ ACTION_TAG_RE.lastIndex = 0;
4015
+ while ((match = ACTION_TAG_RE.exec(accumulatedText)) !== null) {
4016
+ const attrs = parseAttributes(match[1]);
4017
+ const name = attrs.name;
4018
+ if (name) {
4019
+ delete attrs.name;
4020
+ allActions.push({ name, params: attrs });
4021
+ }
4022
+ }
4023
+ const newActions = allActions.slice(this.emittedCount);
4024
+ this.emittedCount = allActions.length;
4025
+ const cleanText = accumulatedText.replace(ACTION_TAG_RE, "").replace(/\s{2,}/g, " ").trim();
4026
+ return { actions: newActions, cleanText };
4027
+ }
4028
+ reset() {
4029
+ this.emittedCount = 0;
4030
+ }
4031
+ };
4032
+ function parseActions(text) {
4033
+ const parser = new StreamingActionParser();
4034
+ return parser.parse(text);
4035
+ }
4036
+
3992
4037
  // src/client.ts
3993
4038
  var DEFAULT_SAMPLE_RATE = 16e3;
3994
4039
  var EstuaryClient = class extends TypedEventEmitter {
@@ -3999,6 +4044,7 @@ var EstuaryClient = class extends TypedEventEmitter {
3999
4044
  audioPlayer = null;
4000
4045
  _memory;
4001
4046
  _sessionInfo = null;
4047
+ actionParsers = /* @__PURE__ */ new Map();
4002
4048
  constructor(config) {
4003
4049
  super();
4004
4050
  this.config = config;
@@ -4050,6 +4096,9 @@ var EstuaryClient = class extends TypedEventEmitter {
4050
4096
  this.ensureConnected();
4051
4097
  this.socketManager.emitEvent("client_interrupt", { message_id: messageId });
4052
4098
  this.audioPlayer?.clear();
4099
+ if (this.config.suppressMicDuringPlayback) {
4100
+ this.voiceManager?.setSuppressed?.(false);
4101
+ }
4053
4102
  }
4054
4103
  /** Send a camera image for vision processing */
4055
4104
  sendCameraImage(imageBase64, mimeType, requestId, text) {
@@ -4088,9 +4137,15 @@ var EstuaryClient = class extends TypedEventEmitter {
4088
4137
  this.audioPlayer = new AudioPlayer(sampleRate, (event) => {
4089
4138
  if (event.type === "started") {
4090
4139
  this.emit("audioPlaybackStarted", event.messageId);
4140
+ if (this.config.suppressMicDuringPlayback) {
4141
+ this.voiceManager?.setSuppressed?.(true);
4142
+ }
4091
4143
  } else if (event.type === "complete") {
4092
4144
  this.emit("audioPlaybackComplete", event.messageId);
4093
4145
  this.notifyAudioPlaybackComplete(event.messageId);
4146
+ if (this.config.suppressMicDuringPlayback) {
4147
+ this.voiceManager?.setSuppressed?.(false);
4148
+ }
4094
4149
  }
4095
4150
  });
4096
4151
  }
@@ -4134,15 +4189,20 @@ var EstuaryClient = class extends TypedEventEmitter {
4134
4189
  });
4135
4190
  this.socketManager.on("disconnected", (reason) => {
4136
4191
  this._sessionInfo = null;
4192
+ this.actionParsers.clear();
4137
4193
  this.emit("disconnected", reason);
4138
4194
  });
4139
4195
  this.socketManager.on("reconnecting", (attempt) => this.emit("reconnecting", attempt));
4140
4196
  this.socketManager.on("connectionStateChanged", (state) => this.emit("connectionStateChanged", state));
4141
- this.socketManager.on("botResponse", (response) => this.emit("botResponse", response));
4197
+ this.socketManager.on("botResponse", (response) => this.handleBotResponse(response));
4142
4198
  this.socketManager.on("botVoice", (voice) => this.handleBotVoice(voice));
4143
4199
  this.socketManager.on("sttResponse", (response) => this.emit("sttResponse", response));
4144
4200
  this.socketManager.on("interrupt", (data) => {
4145
4201
  this.audioPlayer?.clear();
4202
+ this.actionParsers.clear();
4203
+ if (this.config.suppressMicDuringPlayback) {
4204
+ this.voiceManager?.setSuppressed?.(false);
4205
+ }
4146
4206
  this.emit("interrupt", data);
4147
4207
  });
4148
4208
  this.socketManager.on("error", (error) => this.emit("error", error));
@@ -4153,12 +4213,34 @@ var EstuaryClient = class extends TypedEventEmitter {
4153
4213
  this.socketManager.on("livekitDisconnected", () => this.emit("livekitDisconnected"));
4154
4214
  this.socketManager.on("memoryUpdated", (event) => this.emit("memoryUpdated", event));
4155
4215
  }
4216
+ handleBotResponse(response) {
4217
+ const { messageId } = response;
4218
+ if (!this.actionParsers.has(messageId)) {
4219
+ this.actionParsers.set(messageId, new StreamingActionParser());
4220
+ }
4221
+ const parser = this.actionParsers.get(messageId);
4222
+ const { actions, cleanText } = parser.parse(response.text);
4223
+ for (const action of actions) {
4224
+ this.emit("characterAction", {
4225
+ name: action.name,
4226
+ params: action.params,
4227
+ messageId
4228
+ });
4229
+ }
4230
+ this.emit("botResponse", {
4231
+ ...response,
4232
+ text: cleanText
4233
+ });
4234
+ if (response.isFinal) {
4235
+ this.actionParsers.delete(messageId);
4236
+ }
4237
+ }
4156
4238
  handleBotVoice(voice) {
4157
4239
  this.emit("botVoice", voice);
4158
4240
  this.audioPlayer?.enqueue(voice);
4159
4241
  }
4160
4242
  };
4161
4243
 
4162
- export { ConnectionState, EstuaryClient };
4244
+ export { ConnectionState, EstuaryClient, parseActions };
4163
4245
  //# sourceMappingURL=index.mjs.map
4164
4246
  //# sourceMappingURL=index.mjs.map