@estuary-ai/sdk 0.1.3 → 0.1.4

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 CHANGED
@@ -96,6 +96,14 @@ interface MemoryUpdatedEvent {
96
96
  newMemories: MemoryData[];
97
97
  timestamp: string;
98
98
  }
99
+ interface CharacterAction {
100
+ /** Action name (e.g., "follow_user", "sit", "look_at") */
101
+ name: string;
102
+ /** Action parameters as key-value pairs */
103
+ params: Record<string, string>;
104
+ /** Message ID of the bot response that contained this action */
105
+ messageId: string;
106
+ }
99
107
  type EstuaryEventMap = {
100
108
  connected: (session: SessionInfo) => void;
101
109
  disconnected: (reason: string) => void;
@@ -109,6 +117,7 @@ type EstuaryEventMap = {
109
117
  authError: (error: string) => void;
110
118
  quotaExceeded: (data: QuotaExceededData) => void;
111
119
  cameraCaptureRequest: (request: CameraCaptureRequest) => void;
120
+ characterAction: (action: CharacterAction) => void;
112
121
  voiceStarted: () => void;
113
122
  voiceStopped: () => void;
114
123
  livekitConnected: (room: string) => void;
@@ -229,6 +238,7 @@ declare class EstuaryClient extends TypedEventEmitter<EstuaryEventMap> {
229
238
  private audioPlayer;
230
239
  private _memory;
231
240
  private _sessionInfo;
241
+ private actionParsers;
232
242
  constructor(config: EstuaryConfig);
233
243
  /** Memory API client for querying memories, graphs, and facts */
234
244
  get memory(): MemoryClient;
@@ -266,6 +276,7 @@ declare class EstuaryClient extends TypedEventEmitter<EstuaryEventMap> {
266
276
  get isVoiceActive(): boolean;
267
277
  private ensureConnected;
268
278
  private forwardSocketEvents;
279
+ private handleBotResponse;
269
280
  private handleBotVoice;
270
281
  }
271
282
 
@@ -289,4 +300,23 @@ declare class EstuaryError extends Error {
289
300
  constructor(code: ErrorCode, message: string, details?: unknown);
290
301
  }
291
302
 
292
- export { type BotResponse, type BotVoice, type CameraCaptureRequest, ConnectionState, type CoreFactsResponse, ErrorCode, EstuaryClient, type EstuaryConfig, EstuaryError, type EstuaryEventMap, type InterruptData, type LiveKitTokenResponse, MemoryClient, type MemoryData, type MemoryGraphOptions, type MemoryGraphResponse, type MemoryListOptions, type MemoryListResponse, type MemorySearchOptions, type MemorySearchResponse, type MemoryStatsResponse, type MemoryTimelineOptions, type MemoryTimelineResponse, type MemoryUpdatedEvent, type QuotaExceededData, type SessionInfo, type SttResponse, type VoiceManager, type VoiceTransport };
303
+ /**
304
+ * Parses `<action name="..." .../>` XML tags from bot response text.
305
+ *
306
+ * Designed for streaming: call `parse()` with the accumulated text on each
307
+ * chunk and it returns only newly-discovered actions since the last call.
308
+ */
309
+ interface ParsedAction {
310
+ name: string;
311
+ params: Record<string, string>;
312
+ }
313
+ /**
314
+ * One-shot parse: extract all actions and return clean text.
315
+ * Useful for non-streaming contexts.
316
+ */
317
+ declare function parseActions(text: string): {
318
+ actions: ParsedAction[];
319
+ cleanText: string;
320
+ };
321
+
322
+ export { type BotResponse, type BotVoice, type CameraCaptureRequest, type CharacterAction, ConnectionState, type CoreFactsResponse, ErrorCode, EstuaryClient, type EstuaryConfig, EstuaryError, type EstuaryEventMap, type InterruptData, type LiveKitTokenResponse, MemoryClient, type MemoryData, type MemoryGraphOptions, type MemoryGraphResponse, type MemoryListOptions, type MemoryListResponse, type MemorySearchOptions, type MemorySearchResponse, type MemoryStatsResponse, type MemoryTimelineOptions, type MemoryTimelineResponse, type MemoryUpdatedEvent, type ParsedAction, type QuotaExceededData, type SessionInfo, type SttResponse, type VoiceManager, type VoiceTransport, parseActions };
package/dist/index.js CHANGED
@@ -9310,6 +9310,53 @@ var Logger = class {
9310
9310
 
9311
9311
  // src/client.ts
9312
9312
  init_errors();
9313
+
9314
+ // src/utils/action-parser.ts
9315
+ var ACTION_TAG_RE = /<action\s+([^>]*?)\/>/gi;
9316
+ var ATTR_RE = /(\w+)\s*=\s*"([^"]*)"|(\w+)\s*=\s*'([^']*)'/g;
9317
+ function parseAttributes(attrString) {
9318
+ const attrs = {};
9319
+ let match;
9320
+ while ((match = ATTR_RE.exec(attrString)) !== null) {
9321
+ const key = match[1] ?? match[3];
9322
+ const value2 = match[2] ?? match[4];
9323
+ attrs[key] = value2;
9324
+ }
9325
+ return attrs;
9326
+ }
9327
+ var StreamingActionParser = class {
9328
+ emittedCount = 0;
9329
+ /**
9330
+ * Parse the accumulated response text and return any new actions found
9331
+ * since the last call. Also returns the text with all action tags stripped.
9332
+ */
9333
+ parse(accumulatedText) {
9334
+ const allActions = [];
9335
+ let match;
9336
+ ACTION_TAG_RE.lastIndex = 0;
9337
+ while ((match = ACTION_TAG_RE.exec(accumulatedText)) !== null) {
9338
+ const attrs = parseAttributes(match[1]);
9339
+ const name = attrs.name;
9340
+ if (name) {
9341
+ delete attrs.name;
9342
+ allActions.push({ name, params: attrs });
9343
+ }
9344
+ }
9345
+ const newActions = allActions.slice(this.emittedCount);
9346
+ this.emittedCount = allActions.length;
9347
+ const cleanText = accumulatedText.replace(ACTION_TAG_RE, "").replace(/\s{2,}/g, " ").trim();
9348
+ return { actions: newActions, cleanText };
9349
+ }
9350
+ reset() {
9351
+ this.emittedCount = 0;
9352
+ }
9353
+ };
9354
+ function parseActions(text) {
9355
+ const parser = new StreamingActionParser();
9356
+ return parser.parse(text);
9357
+ }
9358
+
9359
+ // src/client.ts
9313
9360
  var DEFAULT_SAMPLE_RATE = 16e3;
9314
9361
  var EstuaryClient = class extends TypedEventEmitter {
9315
9362
  config;
@@ -9319,6 +9366,7 @@ var EstuaryClient = class extends TypedEventEmitter {
9319
9366
  audioPlayer = null;
9320
9367
  _memory;
9321
9368
  _sessionInfo = null;
9369
+ actionParsers = /* @__PURE__ */ new Map();
9322
9370
  constructor(config) {
9323
9371
  super();
9324
9372
  this.config = config;
@@ -9454,15 +9502,17 @@ var EstuaryClient = class extends TypedEventEmitter {
9454
9502
  });
9455
9503
  this.socketManager.on("disconnected", (reason) => {
9456
9504
  this._sessionInfo = null;
9505
+ this.actionParsers.clear();
9457
9506
  this.emit("disconnected", reason);
9458
9507
  });
9459
9508
  this.socketManager.on("reconnecting", (attempt) => this.emit("reconnecting", attempt));
9460
9509
  this.socketManager.on("connectionStateChanged", (state) => this.emit("connectionStateChanged", state));
9461
- this.socketManager.on("botResponse", (response) => this.emit("botResponse", response));
9510
+ this.socketManager.on("botResponse", (response) => this.handleBotResponse(response));
9462
9511
  this.socketManager.on("botVoice", (voice) => this.handleBotVoice(voice));
9463
9512
  this.socketManager.on("sttResponse", (response) => this.emit("sttResponse", response));
9464
9513
  this.socketManager.on("interrupt", (data) => {
9465
9514
  this.audioPlayer?.clear();
9515
+ this.actionParsers.clear();
9466
9516
  this.emit("interrupt", data);
9467
9517
  });
9468
9518
  this.socketManager.on("error", (error) => this.emit("error", error));
@@ -9473,6 +9523,28 @@ var EstuaryClient = class extends TypedEventEmitter {
9473
9523
  this.socketManager.on("livekitDisconnected", () => this.emit("livekitDisconnected"));
9474
9524
  this.socketManager.on("memoryUpdated", (event) => this.emit("memoryUpdated", event));
9475
9525
  }
9526
+ handleBotResponse(response) {
9527
+ const { messageId } = response;
9528
+ if (!this.actionParsers.has(messageId)) {
9529
+ this.actionParsers.set(messageId, new StreamingActionParser());
9530
+ }
9531
+ const parser = this.actionParsers.get(messageId);
9532
+ const { actions, cleanText } = parser.parse(response.text);
9533
+ for (const action of actions) {
9534
+ this.emit("characterAction", {
9535
+ name: action.name,
9536
+ params: action.params,
9537
+ messageId
9538
+ });
9539
+ }
9540
+ this.emit("botResponse", {
9541
+ ...response,
9542
+ text: cleanText
9543
+ });
9544
+ if (response.isFinal) {
9545
+ this.actionParsers.delete(messageId);
9546
+ }
9547
+ }
9476
9548
  handleBotVoice(voice) {
9477
9549
  this.emit("botVoice", voice);
9478
9550
  this.audioPlayer?.enqueue(voice);
@@ -9500,5 +9572,6 @@ xmlhttprequest-ssl/lib/XMLHttpRequest.js:
9500
9572
 
9501
9573
  exports.ConnectionState = ConnectionState;
9502
9574
  exports.EstuaryClient = EstuaryClient;
9575
+ exports.parseActions = parseActions;
9503
9576
  //# sourceMappingURL=index.js.map
9504
9577
  //# sourceMappingURL=index.js.map