@voicethere/agent 0.7.11 → 0.7.13

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.
@@ -148,6 +148,12 @@ function isPlayStopAckMessage(value) {
148
148
  const msg = value;
149
149
  return msg.type === "play_stop_ack" && typeof msg.requestId === "string";
150
150
  }
151
+ function isPlayPoseAckMessage(value) {
152
+ if (!value || typeof value !== "object")
153
+ return false;
154
+ const msg = value;
155
+ return msg.type === "play_pose_ack" && typeof msg.requestId === "string";
156
+ }
151
157
  function isRecordingControlAckMessage(value) {
152
158
  if (!value || typeof value !== "object")
153
159
  return false;
@@ -208,7 +214,7 @@ function isParentMessage(value) {
208
214
  if (!value || typeof value !== "object")
209
215
  return false;
210
216
  const msg = value;
211
- return msg.type === "session_start" || msg.type === "speech_event" || msg.type === "session_end" || msg.type === "data_channel_message" || msg.type === "data_channel_binary" || msg.type === "idle_timeout" || msg.type === "recording_control_ack" || msg.type === "play_ack" || msg.type === "play_status_ack" || msg.type === "play_stop_ack" || msg.type === "mix_control_ack" || msg.type === "stt_control_ack" || msg.type === "webhook";
217
+ return msg.type === "session_start" || msg.type === "speech_event" || msg.type === "session_end" || msg.type === "data_channel_message" || msg.type === "data_channel_binary" || msg.type === "idle_timeout" || msg.type === "recording_control_ack" || msg.type === "play_ack" || msg.type === "play_status_ack" || msg.type === "play_stop_ack" || msg.type === "play_pose_ack" || msg.type === "mix_control_ack" || msg.type === "stt_control_ack" || msg.type === "webhook";
212
218
  }
213
219
  function isSessionScopedParentMessage(value) {
214
220
  return isParentMessage(value) && !isWebhookMessage(value);
@@ -230,6 +236,7 @@ var pendingRecordingAcks = /* @__PURE__ */ new Map();
230
236
  var pendingPlayAcks = /* @__PURE__ */ new Map();
231
237
  var pendingPlayStatusAcks = /* @__PURE__ */ new Map();
232
238
  var pendingPlayStopAcks = /* @__PURE__ */ new Map();
239
+ var pendingPlayPoseAcks = /* @__PURE__ */ new Map();
233
240
  var pendingMixAcks = /* @__PURE__ */ new Map();
234
241
  var pendingSttAcks = /* @__PURE__ */ new Map();
235
242
  function handleRecordingControlAck(message) {
@@ -284,6 +291,19 @@ function handlePlayStopAck(message) {
284
291
  requestId: message.requestId
285
292
  });
286
293
  }
294
+ function handlePlayPoseAck(message) {
295
+ const pending = pendingPlayPoseAcks.get(message.requestId);
296
+ if (!pending)
297
+ return;
298
+ clearTimeout(pending.timer);
299
+ pendingPlayPoseAcks.delete(message.requestId);
300
+ pending.resolve({
301
+ ok: message.ok,
302
+ playId: message.playId,
303
+ reason: message.reason,
304
+ requestId: message.requestId
305
+ });
306
+ }
287
307
  function handleMixControlAck(message) {
288
308
  const pending = pendingMixAcks.get(message.requestId);
289
309
  if (!pending)
@@ -369,7 +389,7 @@ function sendParentMessage(message) {
369
389
  process.send?.(message);
370
390
  return;
371
391
  }
372
- if (msgType === "play" || msgType === "play_status" || msgType === "play_stop") {
392
+ if (msgType === "play" || msgType === "play_status" || msgType === "play_stop" || msgType === "play_pose") {
373
393
  process.send?.(message);
374
394
  return;
375
395
  }
@@ -555,6 +575,10 @@ function defineAgent(handlers) {
555
575
  handlePlayStopAck(message);
556
576
  return;
557
577
  }
578
+ if (isPlayPoseAckMessage(message)) {
579
+ handlePlayPoseAck(message);
580
+ return;
581
+ }
558
582
  if (isMixControlAckMessage(message)) {
559
583
  handleMixControlAck(message);
560
584
  return;
@@ -148,6 +148,12 @@ function isPlayStopAckMessage(value) {
148
148
  const msg = value;
149
149
  return msg.type === "play_stop_ack" && typeof msg.requestId === "string";
150
150
  }
151
+ function isPlayPoseAckMessage(value) {
152
+ if (!value || typeof value !== "object")
153
+ return false;
154
+ const msg = value;
155
+ return msg.type === "play_pose_ack" && typeof msg.requestId === "string";
156
+ }
151
157
  function isRecordingControlAckMessage(value) {
152
158
  if (!value || typeof value !== "object")
153
159
  return false;
@@ -208,7 +214,7 @@ function isParentMessage(value) {
208
214
  if (!value || typeof value !== "object")
209
215
  return false;
210
216
  const msg = value;
211
- return msg.type === "session_start" || msg.type === "speech_event" || msg.type === "session_end" || msg.type === "data_channel_message" || msg.type === "data_channel_binary" || msg.type === "idle_timeout" || msg.type === "recording_control_ack" || msg.type === "play_ack" || msg.type === "play_status_ack" || msg.type === "play_stop_ack" || msg.type === "mix_control_ack" || msg.type === "stt_control_ack" || msg.type === "webhook";
217
+ return msg.type === "session_start" || msg.type === "speech_event" || msg.type === "session_end" || msg.type === "data_channel_message" || msg.type === "data_channel_binary" || msg.type === "idle_timeout" || msg.type === "recording_control_ack" || msg.type === "play_ack" || msg.type === "play_status_ack" || msg.type === "play_stop_ack" || msg.type === "play_pose_ack" || msg.type === "mix_control_ack" || msg.type === "stt_control_ack" || msg.type === "webhook";
212
218
  }
213
219
  function isSessionScopedParentMessage(value) {
214
220
  return isParentMessage(value) && !isWebhookMessage(value);
@@ -230,6 +236,7 @@ var pendingRecordingAcks = /* @__PURE__ */ new Map();
230
236
  var pendingPlayAcks = /* @__PURE__ */ new Map();
231
237
  var pendingPlayStatusAcks = /* @__PURE__ */ new Map();
232
238
  var pendingPlayStopAcks = /* @__PURE__ */ new Map();
239
+ var pendingPlayPoseAcks = /* @__PURE__ */ new Map();
233
240
  var pendingMixAcks = /* @__PURE__ */ new Map();
234
241
  var pendingSttAcks = /* @__PURE__ */ new Map();
235
242
  function handleRecordingControlAck(message) {
@@ -284,6 +291,19 @@ function handlePlayStopAck(message) {
284
291
  requestId: message.requestId
285
292
  });
286
293
  }
294
+ function handlePlayPoseAck(message) {
295
+ const pending = pendingPlayPoseAcks.get(message.requestId);
296
+ if (!pending)
297
+ return;
298
+ clearTimeout(pending.timer);
299
+ pendingPlayPoseAcks.delete(message.requestId);
300
+ pending.resolve({
301
+ ok: message.ok,
302
+ playId: message.playId,
303
+ reason: message.reason,
304
+ requestId: message.requestId
305
+ });
306
+ }
287
307
  function handleMixControlAck(message) {
288
308
  const pending = pendingMixAcks.get(message.requestId);
289
309
  if (!pending)
@@ -369,7 +389,7 @@ function sendParentMessage(message) {
369
389
  process.send?.(message);
370
390
  return;
371
391
  }
372
- if (msgType === "play" || msgType === "play_status" || msgType === "play_stop") {
392
+ if (msgType === "play" || msgType === "play_status" || msgType === "play_stop" || msgType === "play_pose") {
373
393
  process.send?.(message);
374
394
  return;
375
395
  }
@@ -555,6 +575,10 @@ function defineAgent(handlers) {
555
575
  handlePlayStopAck(message);
556
576
  return;
557
577
  }
578
+ if (isPlayPoseAckMessage(message)) {
579
+ handlePlayPoseAck(message);
580
+ return;
581
+ }
558
582
  if (isMixControlAckMessage(message)) {
559
583
  handleMixControlAck(message);
560
584
  return;
@@ -151,6 +151,12 @@ function isPlayStopAckMessage(value) {
151
151
  const msg = value;
152
152
  return msg.type === "play_stop_ack" && typeof msg.requestId === "string";
153
153
  }
154
+ function isPlayPoseAckMessage(value) {
155
+ if (!value || typeof value !== "object")
156
+ return false;
157
+ const msg = value;
158
+ return msg.type === "play_pose_ack" && typeof msg.requestId === "string";
159
+ }
154
160
  function isRecordingControlAckMessage(value) {
155
161
  if (!value || typeof value !== "object")
156
162
  return false;
@@ -211,7 +217,7 @@ function isParentMessage(value) {
211
217
  if (!value || typeof value !== "object")
212
218
  return false;
213
219
  const msg = value;
214
- return msg.type === "session_start" || msg.type === "speech_event" || msg.type === "session_end" || msg.type === "data_channel_message" || msg.type === "data_channel_binary" || msg.type === "idle_timeout" || msg.type === "recording_control_ack" || msg.type === "play_ack" || msg.type === "play_status_ack" || msg.type === "play_stop_ack" || msg.type === "mix_control_ack" || msg.type === "stt_control_ack" || msg.type === "webhook";
220
+ return msg.type === "session_start" || msg.type === "speech_event" || msg.type === "session_end" || msg.type === "data_channel_message" || msg.type === "data_channel_binary" || msg.type === "idle_timeout" || msg.type === "recording_control_ack" || msg.type === "play_ack" || msg.type === "play_status_ack" || msg.type === "play_stop_ack" || msg.type === "play_pose_ack" || msg.type === "mix_control_ack" || msg.type === "stt_control_ack" || msg.type === "webhook";
215
221
  }
216
222
  function isSessionScopedParentMessage(value) {
217
223
  return isParentMessage(value) && !isWebhookMessage(value);
@@ -233,6 +239,7 @@ var pendingRecordingAcks = /* @__PURE__ */ new Map();
233
239
  var pendingPlayAcks = /* @__PURE__ */ new Map();
234
240
  var pendingPlayStatusAcks = /* @__PURE__ */ new Map();
235
241
  var pendingPlayStopAcks = /* @__PURE__ */ new Map();
242
+ var pendingPlayPoseAcks = /* @__PURE__ */ new Map();
236
243
  var pendingMixAcks = /* @__PURE__ */ new Map();
237
244
  var pendingSttAcks = /* @__PURE__ */ new Map();
238
245
  function handleRecordingControlAck(message) {
@@ -287,6 +294,19 @@ function handlePlayStopAck(message) {
287
294
  requestId: message.requestId
288
295
  });
289
296
  }
297
+ function handlePlayPoseAck(message) {
298
+ const pending = pendingPlayPoseAcks.get(message.requestId);
299
+ if (!pending)
300
+ return;
301
+ clearTimeout(pending.timer);
302
+ pendingPlayPoseAcks.delete(message.requestId);
303
+ pending.resolve({
304
+ ok: message.ok,
305
+ playId: message.playId,
306
+ reason: message.reason,
307
+ requestId: message.requestId
308
+ });
309
+ }
290
310
  function handleMixControlAck(message) {
291
311
  const pending = pendingMixAcks.get(message.requestId);
292
312
  if (!pending)
@@ -372,7 +392,7 @@ function sendParentMessage(message) {
372
392
  process.send?.(message);
373
393
  return;
374
394
  }
375
- if (msgType === "play" || msgType === "play_status" || msgType === "play_stop") {
395
+ if (msgType === "play" || msgType === "play_status" || msgType === "play_stop" || msgType === "play_pose") {
376
396
  process.send?.(message);
377
397
  return;
378
398
  }
@@ -558,6 +578,10 @@ function defineAgent(handlers) {
558
578
  handlePlayStopAck(message);
559
579
  return;
560
580
  }
581
+ if (isPlayPoseAckMessage(message)) {
582
+ handlePlayPoseAck(message);
583
+ return;
584
+ }
561
585
  if (isMixControlAckMessage(message)) {
562
586
  handleMixControlAck(message);
563
587
  return;
@@ -10903,6 +10903,12 @@ function isPlayStopAckMessage(value) {
10903
10903
  const msg = value;
10904
10904
  return msg.type === "play_stop_ack" && typeof msg.requestId === "string";
10905
10905
  }
10906
+ function isPlayPoseAckMessage(value) {
10907
+ if (!value || typeof value !== "object")
10908
+ return false;
10909
+ const msg = value;
10910
+ return msg.type === "play_pose_ack" && typeof msg.requestId === "string";
10911
+ }
10906
10912
  function isRecordingControlAckMessage(value) {
10907
10913
  if (!value || typeof value !== "object")
10908
10914
  return false;
@@ -10963,7 +10969,7 @@ function isParentMessage(value) {
10963
10969
  if (!value || typeof value !== "object")
10964
10970
  return false;
10965
10971
  const msg = value;
10966
- return msg.type === "session_start" || msg.type === "speech_event" || msg.type === "session_end" || msg.type === "data_channel_message" || msg.type === "data_channel_binary" || msg.type === "idle_timeout" || msg.type === "recording_control_ack" || msg.type === "play_ack" || msg.type === "play_status_ack" || msg.type === "play_stop_ack" || msg.type === "mix_control_ack" || msg.type === "stt_control_ack" || msg.type === "webhook";
10972
+ return msg.type === "session_start" || msg.type === "speech_event" || msg.type === "session_end" || msg.type === "data_channel_message" || msg.type === "data_channel_binary" || msg.type === "idle_timeout" || msg.type === "recording_control_ack" || msg.type === "play_ack" || msg.type === "play_status_ack" || msg.type === "play_stop_ack" || msg.type === "play_pose_ack" || msg.type === "mix_control_ack" || msg.type === "stt_control_ack" || msg.type === "webhook";
10967
10973
  }
10968
10974
  function isSessionScopedParentMessage(value) {
10969
10975
  return isParentMessage(value) && !isWebhookMessage(value);
@@ -10985,6 +10991,7 @@ var pendingRecordingAcks = /* @__PURE__ */ new Map();
10985
10991
  var pendingPlayAcks = /* @__PURE__ */ new Map();
10986
10992
  var pendingPlayStatusAcks = /* @__PURE__ */ new Map();
10987
10993
  var pendingPlayStopAcks = /* @__PURE__ */ new Map();
10994
+ var pendingPlayPoseAcks = /* @__PURE__ */ new Map();
10988
10995
  var pendingMixAcks = /* @__PURE__ */ new Map();
10989
10996
  var pendingSttAcks = /* @__PURE__ */ new Map();
10990
10997
  function handleRecordingControlAck(message) {
@@ -11039,6 +11046,19 @@ function handlePlayStopAck(message) {
11039
11046
  requestId: message.requestId
11040
11047
  });
11041
11048
  }
11049
+ function handlePlayPoseAck(message) {
11050
+ const pending = pendingPlayPoseAcks.get(message.requestId);
11051
+ if (!pending)
11052
+ return;
11053
+ clearTimeout(pending.timer);
11054
+ pendingPlayPoseAcks.delete(message.requestId);
11055
+ pending.resolve({
11056
+ ok: message.ok,
11057
+ playId: message.playId,
11058
+ reason: message.reason,
11059
+ requestId: message.requestId
11060
+ });
11061
+ }
11042
11062
  function handleMixControlAck(message) {
11043
11063
  const pending = pendingMixAcks.get(message.requestId);
11044
11064
  if (!pending)
@@ -11124,7 +11144,7 @@ function sendParentMessage(message) {
11124
11144
  process.send?.(message);
11125
11145
  return;
11126
11146
  }
11127
- if (msgType === "play" || msgType === "play_status" || msgType === "play_stop") {
11147
+ if (msgType === "play" || msgType === "play_status" || msgType === "play_stop" || msgType === "play_pose") {
11128
11148
  process.send?.(message);
11129
11149
  return;
11130
11150
  }
@@ -11310,6 +11330,10 @@ function defineAgent(handlers) {
11310
11330
  handlePlayStopAck(message);
11311
11331
  return;
11312
11332
  }
11333
+ if (isPlayPoseAckMessage(message)) {
11334
+ handlePlayPoseAck(message);
11335
+ return;
11336
+ }
11313
11337
  if (isMixControlAckMessage(message)) {
11314
11338
  handleMixControlAck(message);
11315
11339
  return;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@voicethere/agent",
3
- "version": "0.7.11",
3
+ "version": "0.7.13",
4
4
  "description": "VoiceThere customer agent SDK — IPC types and runtime helpers for sandboxed child bundles",
5
5
  "type": "module",
6
6
  "exports": {
@@ -95,9 +95,9 @@
95
95
  "@node-webrtc-rust/sdk": ">=0.9.0"
96
96
  },
97
97
  "devDependencies": {
98
- "@node-webrtc-rust/helpers": "0.9.5",
99
- "@node-webrtc-rust/sdk": "0.9.5",
100
- "@node-webrtc-rust/signaling": "0.9.5",
98
+ "@node-webrtc-rust/helpers": "0.9.9",
99
+ "@node-webrtc-rust/sdk": "0.9.9",
100
+ "@node-webrtc-rust/signaling": "0.9.9",
101
101
  "@types/node": "22.20.1",
102
102
  "http-server": "14.1.1",
103
103
  "ioredis": "5.11.1",
@@ -15,10 +15,10 @@ import {
15
15
 
16
16
  ## Product vs e2e
17
17
 
18
- | Kind | Dashboard create | Prebuilt seed bundle | Typical consumer |
19
- | ----------- | -------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------ | ----------------------- |
18
+ | Kind | Dashboard create | Prebuilt seed bundle | Typical consumer |
19
+ | ----------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------ | ----------------------- |
20
20
  | **product** | Yes (`echo`, `echo-dc`, `voice-starter`, `game-sync`, `voice-showcase`, `recording-consent`, `positional-tts`, `spatial-showcase`, `webhooks`, `webhooks-redis`) | Yes — `dist/templates/<id>/agent.js` | Platform project create |
21
- | **e2e** | No | No — build from sources at test time | `voicethere/e2e` smokes |
21
+ | **e2e** | No | No — build from sources at test time | `voicethere/e2e` smokes |
22
22
 
23
23
  Product templates always set `seedOnCreate: true`. CI fails if a product template is missing its prebuilt bundle after `npm run build`.
24
24
 
@@ -83,17 +83,17 @@ Sources: `positional-tts/agent.ts` (defineAgent wiring), `positional-tts/orbit.t
83
83
 
84
84
  Spatial audio showcase for `/showcase` — one agent template with three demos selected by `{ type: "join", demo }` on the control DataChannel:
85
85
 
86
- | Demo | Behavior |
87
- | ---- | -------- |
88
- | `orbit` | TTS speaker orbits the listener (`setTtsPose`); `{ type: "orbit", action: "set" \| "say" }`; agent emits `{ type: "orbit_pose" }` |
89
- | `soundboard` | Positional clip pads — browser sends `clipId` only (never URLs); agent resolves against an allowlisted `assetOrigin` |
90
- | `proximity` | Shared mix room (`createMixGroup` + `setClientPose`); `{ type: "move" }`, `{ type: "mute_peer" }`; `{ type: "room_state" }` broadcast |
86
+ | Demo | Behavior |
87
+ | ------------ | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
88
+ | `orbit` | Looping sine tone + TTS orbit the listener (`setPlayPose` + `setTtsPose`); STT echo off; `{ type: "orbit", action: "set" \| "say" }`; agent emits `{ type: "orbit_pose" }` |
89
+ | `soundboard` | Positional clip pads — browser sends `clipId` only (never URLs); agent resolves against an allowlisted `assetOrigin` |
90
+ | `proximity` | Shared mix room (`createMixGroup` + `setClientPose`); `{ type: "move" }`, `{ type: "mute_peer" }`; `{ type: "room_state" }` broadcast |
91
91
 
92
92
  **Protocol:** inbound `join`, `orbit`, `pad`, `pad_stop`, `pad_status`, `move`, `mute_peer`, `leave`, `ping` — outbound `showcase_ack`, `orbit_pose`, `pad_progress`, `room_state`, `room_full`, `error`.
93
93
 
94
- **Limits:** `MAX_ROOM_PEERS = 8`, `MAX_ACTIVE_PLAYS = 4` per session. Clip ids: `chime`, `bell`, `laser`, `impact`, `footsteps`, `rain-loop`, `cafe-loop`, `jingle`.
94
+ **Limits:** `MAX_ROOM_PEERS = 8`, `MAX_ACTIVE_PLAYS = 12` per session. Clip ids: `chime`, `bell`, `laser`, `impact`, `footsteps`, `rain-loop`, `cafe-loop`, `jingle`.
95
95
 
96
- Sources: `spatial-showcase/agent.ts`, `protocol.ts`, `sounds.ts`, `room.ts`, `orbit.ts`.
96
+ Sources: `spatial-showcase/agent.ts`, `protocol.ts`, `sounds.ts`, `room.ts`, `orbit.ts`, `sine.ts`.
97
97
 
98
98
  ### `webhooks.ts` (`webhooks`)
99
99