@voicethere/agent 0.5.6 → 0.7.0
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/agent.js +63 -2
- package/dist/index.d.ts +2 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -2
- package/dist/index.js.map +1 -1
- package/dist/protocol.d.ts +99 -2
- package/dist/protocol.d.ts.map +1 -1
- package/dist/protocol.js +4 -0
- package/dist/protocol.js.map +1 -1
- package/dist/runtime.d.ts +45 -1
- package/dist/runtime.d.ts.map +1 -1
- package/dist/runtime.js +230 -0
- package/dist/runtime.js.map +1 -1
- package/dist/templates/echo/agent.js +61 -2
- package/dist/templates/echo-dc/agent.js +61 -2
- package/dist/templates/game-sync/agent.js +125 -33
- package/dist/templates/index.d.ts +2 -0
- package/dist/templates/index.d.ts.map +1 -1
- package/dist/templates/index.js +14 -0
- package/dist/templates/index.js.map +1 -1
- package/dist/templates/positional-tts/agent.js +810 -0
- package/dist/templates/recording-consent/agent.js +61 -2
- package/dist/templates/registry.d.ts.map +1 -1
- package/dist/templates/registry.js +17 -0
- package/dist/templates/registry.js.map +1 -1
- package/dist/templates/voice-showcase/agent.js +102 -21
- package/dist/templates/voice-starter/agent.js +61 -2
- package/dist/templates/webhooks/agent.js +61 -2
- package/dist/templates/webhooks-redis/agent.js +61 -2
- package/package.json +10 -4
- package/templates/README.md +12 -6
- package/templates/game-sync-world-layout.ts +45 -0
- package/templates/game-sync.ts +39 -24
- package/templates/mix-smoke.ts +224 -0
- package/templates/positional-tts/agent.ts +115 -0
- package/templates/positional-tts/orbit.ts +11 -0
- package/templates/voice-showcase/agent.ts +21 -22
- package/templates/voice-showcase/delivery.ts +57 -0
|
@@ -136,6 +136,18 @@ function isRecordingControlAckMessage(value) {
|
|
|
136
136
|
const msg = value;
|
|
137
137
|
return msg.type === "recording_control_ack" && typeof msg.requestId === "string";
|
|
138
138
|
}
|
|
139
|
+
function isMixControlAckMessage(value) {
|
|
140
|
+
if (!value || typeof value !== "object")
|
|
141
|
+
return false;
|
|
142
|
+
const msg = value;
|
|
143
|
+
return msg.type === "mix_control_ack" && typeof msg.requestId === "string";
|
|
144
|
+
}
|
|
145
|
+
function isSttControlAckMessage(value) {
|
|
146
|
+
if (!value || typeof value !== "object")
|
|
147
|
+
return false;
|
|
148
|
+
const msg = value;
|
|
149
|
+
return msg.type === "stt_control_ack" && typeof msg.requestId === "string";
|
|
150
|
+
}
|
|
139
151
|
function isWebhookMessage(value) {
|
|
140
152
|
if (!value || typeof value !== "object")
|
|
141
153
|
return false;
|
|
@@ -178,7 +190,7 @@ function isParentMessage(value) {
|
|
|
178
190
|
if (!value || typeof value !== "object")
|
|
179
191
|
return false;
|
|
180
192
|
const msg = value;
|
|
181
|
-
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 === "webhook";
|
|
193
|
+
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 === "mix_control_ack" || msg.type === "stt_control_ack" || msg.type === "webhook";
|
|
182
194
|
}
|
|
183
195
|
function isSessionScopedParentMessage(value) {
|
|
184
196
|
return isParentMessage(value) && !isWebhookMessage(value);
|
|
@@ -192,9 +204,13 @@ function parseDataChannelPayload(raw) {
|
|
|
192
204
|
}
|
|
193
205
|
var peerEnvBySessionId = /* @__PURE__ */ new Map();
|
|
194
206
|
var recordingAvailableBySessionId = /* @__PURE__ */ new Map();
|
|
207
|
+
var mixAvailableBySessionId = /* @__PURE__ */ new Map();
|
|
208
|
+
var ttsPoseAvailableBySessionId = /* @__PURE__ */ new Map();
|
|
195
209
|
var endedSessionIds = /* @__PURE__ */ new Set();
|
|
196
210
|
var RECORDING_CONTROL_ACK_TIMEOUT_MS = 5e3;
|
|
197
211
|
var pendingRecordingAcks = /* @__PURE__ */ new Map();
|
|
212
|
+
var pendingMixAcks = /* @__PURE__ */ new Map();
|
|
213
|
+
var pendingSttAcks = /* @__PURE__ */ new Map();
|
|
198
214
|
function handleRecordingControlAck(message) {
|
|
199
215
|
const pending = pendingRecordingAcks.get(message.requestId);
|
|
200
216
|
if (!pending)
|
|
@@ -207,6 +223,30 @@ function handleRecordingControlAck(message) {
|
|
|
207
223
|
requestId: message.requestId
|
|
208
224
|
});
|
|
209
225
|
}
|
|
226
|
+
function handleMixControlAck(message) {
|
|
227
|
+
const pending = pendingMixAcks.get(message.requestId);
|
|
228
|
+
if (!pending)
|
|
229
|
+
return;
|
|
230
|
+
clearTimeout(pending.timer);
|
|
231
|
+
pendingMixAcks.delete(message.requestId);
|
|
232
|
+
pending.resolve({
|
|
233
|
+
ok: message.ok,
|
|
234
|
+
reason: message.reason,
|
|
235
|
+
requestId: message.requestId
|
|
236
|
+
});
|
|
237
|
+
}
|
|
238
|
+
function handleSttControlAck(message) {
|
|
239
|
+
const pending = pendingSttAcks.get(message.requestId);
|
|
240
|
+
if (!pending)
|
|
241
|
+
return;
|
|
242
|
+
clearTimeout(pending.timer);
|
|
243
|
+
pendingSttAcks.delete(message.requestId);
|
|
244
|
+
pending.resolve({
|
|
245
|
+
ok: message.ok,
|
|
246
|
+
reason: message.reason,
|
|
247
|
+
requestId: message.requestId
|
|
248
|
+
});
|
|
249
|
+
}
|
|
210
250
|
function clearPendingRecordingAcksForSession(sessionId, reason) {
|
|
211
251
|
for (const [requestId, pending] of pendingRecordingAcks) {
|
|
212
252
|
if (pending.sessionId !== sessionId)
|
|
@@ -265,6 +305,11 @@ function allowOutboundForSession(sessionId) {
|
|
|
265
305
|
return queue.isLive(sessionId);
|
|
266
306
|
}
|
|
267
307
|
function sendParentMessage(message) {
|
|
308
|
+
const msgType = message && typeof message === "object" && "type" in message ? message.type : void 0;
|
|
309
|
+
if (msgType === "mix_control" || msgType === "stt_control") {
|
|
310
|
+
process.send?.(message);
|
|
311
|
+
return;
|
|
312
|
+
}
|
|
268
313
|
const sessionId = message && typeof message === "object" && "sessionId" in message && typeof message.sessionId === "string" ? message.sessionId : void 0;
|
|
269
314
|
if (!allowOutboundForSession(sessionId))
|
|
270
315
|
return;
|
|
@@ -346,6 +391,8 @@ async function handleParentMessage(message, handlers) {
|
|
|
346
391
|
endedSessionIds.delete(message.sessionId);
|
|
347
392
|
peerEnvBySessionId.set(message.sessionId, message.env);
|
|
348
393
|
recordingAvailableBySessionId.set(message.sessionId, message.recordingAvailable ?? false);
|
|
394
|
+
mixAvailableBySessionId.set(message.sessionId, message.mixAvailable ?? false);
|
|
395
|
+
ttsPoseAvailableBySessionId.set(message.sessionId, message.ttsPoseAvailable ?? false);
|
|
349
396
|
const sessionStartInitDelayMs = resolveSessionStartInitDelayMs();
|
|
350
397
|
if (sessionStartInitDelayMs > 0) {
|
|
351
398
|
await new Promise((resolve) => setTimeout(resolve, sessionStartInitDelayMs));
|
|
@@ -353,7 +400,9 @@ async function handleParentMessage(message, handlers) {
|
|
|
353
400
|
await (handlers.onClientJoin ?? handlers.onSessionStart)?.({
|
|
354
401
|
sessionId: message.sessionId,
|
|
355
402
|
env: message.env,
|
|
356
|
-
recordingAvailable: message.recordingAvailable ?? false
|
|
403
|
+
recordingAvailable: message.recordingAvailable ?? false,
|
|
404
|
+
mixAvailable: message.mixAvailable ?? false,
|
|
405
|
+
ttsPoseAvailable: message.ttsPoseAvailable ?? false
|
|
357
406
|
});
|
|
358
407
|
sendParentMessage({
|
|
359
408
|
type: "session_start_ack",
|
|
@@ -391,6 +440,8 @@ async function handleParentMessage(message, handlers) {
|
|
|
391
440
|
clearPendingRecordingAcksForSession(message.sessionId, "session_ended");
|
|
392
441
|
peerEnvBySessionId.delete(message.sessionId);
|
|
393
442
|
recordingAvailableBySessionId.delete(message.sessionId);
|
|
443
|
+
mixAvailableBySessionId.delete(message.sessionId);
|
|
444
|
+
ttsPoseAvailableBySessionId.delete(message.sessionId);
|
|
394
445
|
await (handlers.onClientLeave ?? handlers.onSessionEnd)?.({
|
|
395
446
|
sessionId: message.sessionId
|
|
396
447
|
});
|
|
@@ -410,6 +461,14 @@ function defineAgent(handlers) {
|
|
|
410
461
|
handleRecordingControlAck(message);
|
|
411
462
|
return;
|
|
412
463
|
}
|
|
464
|
+
if (isMixControlAckMessage(message)) {
|
|
465
|
+
handleMixControlAck(message);
|
|
466
|
+
return;
|
|
467
|
+
}
|
|
468
|
+
if (isSttControlAckMessage(message)) {
|
|
469
|
+
handleSttControlAck(message);
|
|
470
|
+
return;
|
|
471
|
+
}
|
|
413
472
|
if (isWebhookMessage(message)) {
|
|
414
473
|
void agentStartReady.then(() => handleWebhookMessage(message, handlers));
|
|
415
474
|
return;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"registry.d.ts","sourceRoot":"","sources":["../../src/templates/registry.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,YAAY,GAAG,SAAS,GAAG,KAAK,CAAC;AAE7C,MAAM,WAAW,uBAAuB;IACtC,EAAE,EAAE,MAAM,CAAC;IACX,6EAA6E;IAC7E,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,YAAY,CAAC;IACnB,mFAAmF;IACnF,YAAY,EAAE,OAAO,CAAC;IACtB,WAAW,EAAE,MAAM,CAAC;IACpB,yEAAyE;IACzE,WAAW,EAAE,MAAM,EAAE,CAAC;CACvB;AAED,eAAO,MAAM,eAAe,EAAE,SAAS,uBAAuB,
|
|
1
|
+
{"version":3,"file":"registry.d.ts","sourceRoot":"","sources":["../../src/templates/registry.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,YAAY,GAAG,SAAS,GAAG,KAAK,CAAC;AAE7C,MAAM,WAAW,uBAAuB;IACtC,EAAE,EAAE,MAAM,CAAC;IACX,6EAA6E;IAC7E,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,YAAY,CAAC;IACnB,mFAAmF;IACnF,YAAY,EAAE,OAAO,CAAC;IACtB,WAAW,EAAE,MAAM,CAAC;IACpB,yEAAyE;IACzE,WAAW,EAAE,MAAM,EAAE,CAAC;CACvB;AAED,eAAO,MAAM,eAAe,EAAE,SAAS,uBAAuB,EA+IpD,CAAC;AAEX,MAAM,MAAM,eAAe,GAAG,CAAC,OAAO,eAAe,CAAC,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,CAAC;AAMrE,wBAAgB,iBAAiB,CAAC,EAAE,EAAE,MAAM,GAAG,EAAE,IAAI,eAAe,CAEnE;AAED,wBAAgB,eAAe,CAAC,EAAE,EAAE,MAAM,GAAG,uBAAuB,CAMnE;AAED,wBAAgB,yBAAyB,IAAI,uBAAuB,EAAE,CAErE"}
|
|
@@ -46,6 +46,7 @@ export const AGENT_TEMPLATES = [
|
|
|
46
46
|
sourceFiles: [
|
|
47
47
|
"voice-showcase/agent.ts",
|
|
48
48
|
"voice-showcase/conversation.ts",
|
|
49
|
+
"voice-showcase/delivery.ts",
|
|
49
50
|
"voice-showcase/weather.ts",
|
|
50
51
|
"voice-showcase/recipes.ts",
|
|
51
52
|
"voice-showcase/fun-facts.ts",
|
|
@@ -62,6 +63,14 @@ export const AGENT_TEMPLATES = [
|
|
|
62
63
|
"recording-consent/conversation.ts",
|
|
63
64
|
],
|
|
64
65
|
},
|
|
66
|
+
{
|
|
67
|
+
id: "positional-tts",
|
|
68
|
+
entry: "positional-tts/agent.ts",
|
|
69
|
+
kind: "product",
|
|
70
|
+
seedOnCreate: true,
|
|
71
|
+
description: "Voice+Data demo — TTS speaker orbits each listener with per-client setTtsPose.",
|
|
72
|
+
sourceFiles: ["positional-tts/agent.ts", "positional-tts/orbit.ts"],
|
|
73
|
+
},
|
|
65
74
|
{
|
|
66
75
|
id: "webhooks",
|
|
67
76
|
entry: "webhooks.ts",
|
|
@@ -110,6 +119,14 @@ export const AGENT_TEMPLATES = [
|
|
|
110
119
|
description: "Redis-backed world buffer sync for redis-sync-smoke (Advanced tier + project Redis).",
|
|
111
120
|
sourceFiles: ["redis-sync/agent.ts", "redis-sync/world-layout.ts"],
|
|
112
121
|
},
|
|
122
|
+
{
|
|
123
|
+
id: "mix-smoke",
|
|
124
|
+
entry: "mix-smoke.ts",
|
|
125
|
+
kind: "e2e",
|
|
126
|
+
seedOnCreate: false,
|
|
127
|
+
description: "Positional mix DC commands for voice-data-mix-smoke (Voice+Data, shared child).",
|
|
128
|
+
sourceFiles: ["mix-smoke.ts"],
|
|
129
|
+
},
|
|
113
130
|
];
|
|
114
131
|
const TEMPLATE_BY_ID = new Map(AGENT_TEMPLATES.map((template) => [template.id, template]));
|
|
115
132
|
export function isAgentTemplateId(id) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"registry.js","sourceRoot":"","sources":["../../src/templates/registry.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"registry.js","sourceRoot":"","sources":["../../src/templates/registry.ts"],"names":[],"mappings":"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"}
|
|
@@ -136,6 +136,18 @@ function isRecordingControlAckMessage(value) {
|
|
|
136
136
|
const msg = value;
|
|
137
137
|
return msg.type === "recording_control_ack" && typeof msg.requestId === "string";
|
|
138
138
|
}
|
|
139
|
+
function isMixControlAckMessage(value) {
|
|
140
|
+
if (!value || typeof value !== "object")
|
|
141
|
+
return false;
|
|
142
|
+
const msg = value;
|
|
143
|
+
return msg.type === "mix_control_ack" && typeof msg.requestId === "string";
|
|
144
|
+
}
|
|
145
|
+
function isSttControlAckMessage(value) {
|
|
146
|
+
if (!value || typeof value !== "object")
|
|
147
|
+
return false;
|
|
148
|
+
const msg = value;
|
|
149
|
+
return msg.type === "stt_control_ack" && typeof msg.requestId === "string";
|
|
150
|
+
}
|
|
139
151
|
function isWebhookMessage(value) {
|
|
140
152
|
if (!value || typeof value !== "object")
|
|
141
153
|
return false;
|
|
@@ -178,7 +190,7 @@ function isParentMessage(value) {
|
|
|
178
190
|
if (!value || typeof value !== "object")
|
|
179
191
|
return false;
|
|
180
192
|
const msg = value;
|
|
181
|
-
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 === "webhook";
|
|
193
|
+
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 === "mix_control_ack" || msg.type === "stt_control_ack" || msg.type === "webhook";
|
|
182
194
|
}
|
|
183
195
|
function isSessionScopedParentMessage(value) {
|
|
184
196
|
return isParentMessage(value) && !isWebhookMessage(value);
|
|
@@ -192,8 +204,12 @@ function parseDataChannelPayload(raw) {
|
|
|
192
204
|
}
|
|
193
205
|
var peerEnvBySessionId = /* @__PURE__ */ new Map();
|
|
194
206
|
var recordingAvailableBySessionId = /* @__PURE__ */ new Map();
|
|
207
|
+
var mixAvailableBySessionId = /* @__PURE__ */ new Map();
|
|
208
|
+
var ttsPoseAvailableBySessionId = /* @__PURE__ */ new Map();
|
|
195
209
|
var endedSessionIds = /* @__PURE__ */ new Set();
|
|
196
210
|
var pendingRecordingAcks = /* @__PURE__ */ new Map();
|
|
211
|
+
var pendingMixAcks = /* @__PURE__ */ new Map();
|
|
212
|
+
var pendingSttAcks = /* @__PURE__ */ new Map();
|
|
197
213
|
function handleRecordingControlAck(message) {
|
|
198
214
|
const pending = pendingRecordingAcks.get(message.requestId);
|
|
199
215
|
if (!pending)
|
|
@@ -206,6 +222,30 @@ function handleRecordingControlAck(message) {
|
|
|
206
222
|
requestId: message.requestId
|
|
207
223
|
});
|
|
208
224
|
}
|
|
225
|
+
function handleMixControlAck(message) {
|
|
226
|
+
const pending = pendingMixAcks.get(message.requestId);
|
|
227
|
+
if (!pending)
|
|
228
|
+
return;
|
|
229
|
+
clearTimeout(pending.timer);
|
|
230
|
+
pendingMixAcks.delete(message.requestId);
|
|
231
|
+
pending.resolve({
|
|
232
|
+
ok: message.ok,
|
|
233
|
+
reason: message.reason,
|
|
234
|
+
requestId: message.requestId
|
|
235
|
+
});
|
|
236
|
+
}
|
|
237
|
+
function handleSttControlAck(message) {
|
|
238
|
+
const pending = pendingSttAcks.get(message.requestId);
|
|
239
|
+
if (!pending)
|
|
240
|
+
return;
|
|
241
|
+
clearTimeout(pending.timer);
|
|
242
|
+
pendingSttAcks.delete(message.requestId);
|
|
243
|
+
pending.resolve({
|
|
244
|
+
ok: message.ok,
|
|
245
|
+
reason: message.reason,
|
|
246
|
+
requestId: message.requestId
|
|
247
|
+
});
|
|
248
|
+
}
|
|
209
249
|
function clearPendingRecordingAcksForSession(sessionId, reason) {
|
|
210
250
|
for (const [requestId, pending] of pendingRecordingAcks) {
|
|
211
251
|
if (pending.sessionId !== sessionId)
|
|
@@ -261,6 +301,11 @@ function allowOutboundForSession(sessionId) {
|
|
|
261
301
|
return queue.isLive(sessionId);
|
|
262
302
|
}
|
|
263
303
|
function sendParentMessage(message) {
|
|
304
|
+
const msgType = message && typeof message === "object" && "type" in message ? message.type : void 0;
|
|
305
|
+
if (msgType === "mix_control" || msgType === "stt_control") {
|
|
306
|
+
process.send?.(message);
|
|
307
|
+
return;
|
|
308
|
+
}
|
|
264
309
|
const sessionId = message && typeof message === "object" && "sessionId" in message && typeof message.sessionId === "string" ? message.sessionId : void 0;
|
|
265
310
|
if (!allowOutboundForSession(sessionId))
|
|
266
311
|
return;
|
|
@@ -342,6 +387,8 @@ async function handleParentMessage(message, handlers) {
|
|
|
342
387
|
endedSessionIds.delete(message.sessionId);
|
|
343
388
|
peerEnvBySessionId.set(message.sessionId, message.env);
|
|
344
389
|
recordingAvailableBySessionId.set(message.sessionId, message.recordingAvailable ?? false);
|
|
390
|
+
mixAvailableBySessionId.set(message.sessionId, message.mixAvailable ?? false);
|
|
391
|
+
ttsPoseAvailableBySessionId.set(message.sessionId, message.ttsPoseAvailable ?? false);
|
|
345
392
|
const sessionStartInitDelayMs = resolveSessionStartInitDelayMs();
|
|
346
393
|
if (sessionStartInitDelayMs > 0) {
|
|
347
394
|
await new Promise((resolve) => setTimeout(resolve, sessionStartInitDelayMs));
|
|
@@ -349,7 +396,9 @@ async function handleParentMessage(message, handlers) {
|
|
|
349
396
|
await (handlers.onClientJoin ?? handlers.onSessionStart)?.({
|
|
350
397
|
sessionId: message.sessionId,
|
|
351
398
|
env: message.env,
|
|
352
|
-
recordingAvailable: message.recordingAvailable ?? false
|
|
399
|
+
recordingAvailable: message.recordingAvailable ?? false,
|
|
400
|
+
mixAvailable: message.mixAvailable ?? false,
|
|
401
|
+
ttsPoseAvailable: message.ttsPoseAvailable ?? false
|
|
353
402
|
});
|
|
354
403
|
sendParentMessage({
|
|
355
404
|
type: "session_start_ack",
|
|
@@ -387,6 +436,8 @@ async function handleParentMessage(message, handlers) {
|
|
|
387
436
|
clearPendingRecordingAcksForSession(message.sessionId, "session_ended");
|
|
388
437
|
peerEnvBySessionId.delete(message.sessionId);
|
|
389
438
|
recordingAvailableBySessionId.delete(message.sessionId);
|
|
439
|
+
mixAvailableBySessionId.delete(message.sessionId);
|
|
440
|
+
ttsPoseAvailableBySessionId.delete(message.sessionId);
|
|
390
441
|
await (handlers.onClientLeave ?? handlers.onSessionEnd)?.({
|
|
391
442
|
sessionId: message.sessionId
|
|
392
443
|
});
|
|
@@ -406,6 +457,14 @@ function defineAgent(handlers) {
|
|
|
406
457
|
handleRecordingControlAck(message);
|
|
407
458
|
return;
|
|
408
459
|
}
|
|
460
|
+
if (isMixControlAckMessage(message)) {
|
|
461
|
+
handleMixControlAck(message);
|
|
462
|
+
return;
|
|
463
|
+
}
|
|
464
|
+
if (isSttControlAckMessage(message)) {
|
|
465
|
+
handleSttControlAck(message);
|
|
466
|
+
return;
|
|
467
|
+
}
|
|
409
468
|
if (isWebhookMessage(message)) {
|
|
410
469
|
void agentStartReady.then(() => handleWebhookMessage(message, handlers));
|
|
411
470
|
return;
|
|
@@ -1317,6 +1376,36 @@ async function resolveWeatherTurn(state, city, country, fetchFn) {
|
|
|
1317
1376
|
}
|
|
1318
1377
|
}
|
|
1319
1378
|
|
|
1379
|
+
// templates/voice-showcase/delivery.ts
|
|
1380
|
+
function spokenThenPlayOps(messages, speakLines) {
|
|
1381
|
+
const ops = [];
|
|
1382
|
+
for (const message of messages) {
|
|
1383
|
+
ops.push({ kind: "send", message });
|
|
1384
|
+
}
|
|
1385
|
+
for (const text of speakLines) {
|
|
1386
|
+
ops.push({ kind: "play", text });
|
|
1387
|
+
}
|
|
1388
|
+
return ops;
|
|
1389
|
+
}
|
|
1390
|
+
function greetingOps(sessionId, greeting) {
|
|
1391
|
+
return spokenThenPlayOps(
|
|
1392
|
+
[
|
|
1393
|
+
{ type: "agent_event", event: "session_start", sessionId },
|
|
1394
|
+
{ type: "chat_reply", text: greeting }
|
|
1395
|
+
],
|
|
1396
|
+
[greeting]
|
|
1397
|
+
);
|
|
1398
|
+
}
|
|
1399
|
+
function applyOutboundOps(sessionId, ops, deps) {
|
|
1400
|
+
for (const op of ops) {
|
|
1401
|
+
if (op.kind === "send") {
|
|
1402
|
+
deps.sendToClient(sessionId, op.message);
|
|
1403
|
+
} else {
|
|
1404
|
+
deps.speak(sessionId, op.text);
|
|
1405
|
+
}
|
|
1406
|
+
}
|
|
1407
|
+
}
|
|
1408
|
+
|
|
1320
1409
|
// templates/voice-showcase/agent.ts
|
|
1321
1410
|
var sessions = /* @__PURE__ */ new Map();
|
|
1322
1411
|
function getState(sessionId) {
|
|
@@ -1335,20 +1424,16 @@ function relaySpeechEvent(sessionId, event) {
|
|
|
1335
1424
|
raw: event
|
|
1336
1425
|
});
|
|
1337
1426
|
}
|
|
1338
|
-
function
|
|
1339
|
-
|
|
1340
|
-
|
|
1341
|
-
|
|
1342
|
-
}
|
|
1343
|
-
|
|
1344
|
-
for (const line of lines) {
|
|
1345
|
-
speak(sessionId, line);
|
|
1346
|
-
}
|
|
1427
|
+
function deliverSpokenThenPlay(sessionId, result) {
|
|
1428
|
+
applyOutboundOps(
|
|
1429
|
+
sessionId,
|
|
1430
|
+
spokenThenPlayOps(result.messages, result.speakLines),
|
|
1431
|
+
{ sendToClient, speak }
|
|
1432
|
+
);
|
|
1347
1433
|
}
|
|
1348
1434
|
async function applyTurn(sessionId, result) {
|
|
1349
1435
|
sessions.set(sessionId, result.state);
|
|
1350
|
-
|
|
1351
|
-
deliverMessages(sessionId, result.messages);
|
|
1436
|
+
deliverSpokenThenPlay(sessionId, result);
|
|
1352
1437
|
if (result.pendingWeather) {
|
|
1353
1438
|
const weatherResult = await resolveWeatherTurn(
|
|
1354
1439
|
result.state,
|
|
@@ -1356,8 +1441,7 @@ async function applyTurn(sessionId, result) {
|
|
|
1356
1441
|
result.pendingWeather.country
|
|
1357
1442
|
);
|
|
1358
1443
|
sessions.set(sessionId, weatherResult.state);
|
|
1359
|
-
|
|
1360
|
-
deliverMessages(sessionId, weatherResult.messages);
|
|
1444
|
+
deliverSpokenThenPlay(sessionId, weatherResult);
|
|
1361
1445
|
}
|
|
1362
1446
|
}
|
|
1363
1447
|
async function onUserText(sessionId, text) {
|
|
@@ -1368,13 +1452,10 @@ async function onUserText(sessionId, text) {
|
|
|
1368
1452
|
defineAgent({
|
|
1369
1453
|
onSessionStart({ sessionId }) {
|
|
1370
1454
|
sessions.set(sessionId, createInitialState());
|
|
1371
|
-
|
|
1372
|
-
|
|
1373
|
-
|
|
1374
|
-
sessionId
|
|
1455
|
+
applyOutboundOps(sessionId, greetingOps(sessionId, GREETING), {
|
|
1456
|
+
sendToClient,
|
|
1457
|
+
speak
|
|
1375
1458
|
});
|
|
1376
|
-
speak(sessionId, GREETING);
|
|
1377
|
-
sendToClient(sessionId, { type: "chat_reply", text: GREETING });
|
|
1378
1459
|
agentLog("info", `voice-showcase session_start ${sessionId}`);
|
|
1379
1460
|
},
|
|
1380
1461
|
onSpeechEvent({ sessionId }, event) {
|
|
@@ -136,6 +136,18 @@ function isRecordingControlAckMessage(value) {
|
|
|
136
136
|
const msg = value;
|
|
137
137
|
return msg.type === "recording_control_ack" && typeof msg.requestId === "string";
|
|
138
138
|
}
|
|
139
|
+
function isMixControlAckMessage(value) {
|
|
140
|
+
if (!value || typeof value !== "object")
|
|
141
|
+
return false;
|
|
142
|
+
const msg = value;
|
|
143
|
+
return msg.type === "mix_control_ack" && typeof msg.requestId === "string";
|
|
144
|
+
}
|
|
145
|
+
function isSttControlAckMessage(value) {
|
|
146
|
+
if (!value || typeof value !== "object")
|
|
147
|
+
return false;
|
|
148
|
+
const msg = value;
|
|
149
|
+
return msg.type === "stt_control_ack" && typeof msg.requestId === "string";
|
|
150
|
+
}
|
|
139
151
|
function isWebhookMessage(value) {
|
|
140
152
|
if (!value || typeof value !== "object")
|
|
141
153
|
return false;
|
|
@@ -178,7 +190,7 @@ function isParentMessage(value) {
|
|
|
178
190
|
if (!value || typeof value !== "object")
|
|
179
191
|
return false;
|
|
180
192
|
const msg = value;
|
|
181
|
-
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 === "webhook";
|
|
193
|
+
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 === "mix_control_ack" || msg.type === "stt_control_ack" || msg.type === "webhook";
|
|
182
194
|
}
|
|
183
195
|
function isSessionScopedParentMessage(value) {
|
|
184
196
|
return isParentMessage(value) && !isWebhookMessage(value);
|
|
@@ -192,8 +204,12 @@ function parseDataChannelPayload(raw) {
|
|
|
192
204
|
}
|
|
193
205
|
var peerEnvBySessionId = /* @__PURE__ */ new Map();
|
|
194
206
|
var recordingAvailableBySessionId = /* @__PURE__ */ new Map();
|
|
207
|
+
var mixAvailableBySessionId = /* @__PURE__ */ new Map();
|
|
208
|
+
var ttsPoseAvailableBySessionId = /* @__PURE__ */ new Map();
|
|
195
209
|
var endedSessionIds = /* @__PURE__ */ new Set();
|
|
196
210
|
var pendingRecordingAcks = /* @__PURE__ */ new Map();
|
|
211
|
+
var pendingMixAcks = /* @__PURE__ */ new Map();
|
|
212
|
+
var pendingSttAcks = /* @__PURE__ */ new Map();
|
|
197
213
|
function handleRecordingControlAck(message) {
|
|
198
214
|
const pending = pendingRecordingAcks.get(message.requestId);
|
|
199
215
|
if (!pending)
|
|
@@ -206,6 +222,30 @@ function handleRecordingControlAck(message) {
|
|
|
206
222
|
requestId: message.requestId
|
|
207
223
|
});
|
|
208
224
|
}
|
|
225
|
+
function handleMixControlAck(message) {
|
|
226
|
+
const pending = pendingMixAcks.get(message.requestId);
|
|
227
|
+
if (!pending)
|
|
228
|
+
return;
|
|
229
|
+
clearTimeout(pending.timer);
|
|
230
|
+
pendingMixAcks.delete(message.requestId);
|
|
231
|
+
pending.resolve({
|
|
232
|
+
ok: message.ok,
|
|
233
|
+
reason: message.reason,
|
|
234
|
+
requestId: message.requestId
|
|
235
|
+
});
|
|
236
|
+
}
|
|
237
|
+
function handleSttControlAck(message) {
|
|
238
|
+
const pending = pendingSttAcks.get(message.requestId);
|
|
239
|
+
if (!pending)
|
|
240
|
+
return;
|
|
241
|
+
clearTimeout(pending.timer);
|
|
242
|
+
pendingSttAcks.delete(message.requestId);
|
|
243
|
+
pending.resolve({
|
|
244
|
+
ok: message.ok,
|
|
245
|
+
reason: message.reason,
|
|
246
|
+
requestId: message.requestId
|
|
247
|
+
});
|
|
248
|
+
}
|
|
209
249
|
function clearPendingRecordingAcksForSession(sessionId, reason) {
|
|
210
250
|
for (const [requestId, pending] of pendingRecordingAcks) {
|
|
211
251
|
if (pending.sessionId !== sessionId)
|
|
@@ -261,6 +301,11 @@ function allowOutboundForSession(sessionId) {
|
|
|
261
301
|
return queue.isLive(sessionId);
|
|
262
302
|
}
|
|
263
303
|
function sendParentMessage(message) {
|
|
304
|
+
const msgType = message && typeof message === "object" && "type" in message ? message.type : void 0;
|
|
305
|
+
if (msgType === "mix_control" || msgType === "stt_control") {
|
|
306
|
+
process.send?.(message);
|
|
307
|
+
return;
|
|
308
|
+
}
|
|
264
309
|
const sessionId = message && typeof message === "object" && "sessionId" in message && typeof message.sessionId === "string" ? message.sessionId : void 0;
|
|
265
310
|
if (!allowOutboundForSession(sessionId))
|
|
266
311
|
return;
|
|
@@ -342,6 +387,8 @@ async function handleParentMessage(message, handlers) {
|
|
|
342
387
|
endedSessionIds.delete(message.sessionId);
|
|
343
388
|
peerEnvBySessionId.set(message.sessionId, message.env);
|
|
344
389
|
recordingAvailableBySessionId.set(message.sessionId, message.recordingAvailable ?? false);
|
|
390
|
+
mixAvailableBySessionId.set(message.sessionId, message.mixAvailable ?? false);
|
|
391
|
+
ttsPoseAvailableBySessionId.set(message.sessionId, message.ttsPoseAvailable ?? false);
|
|
345
392
|
const sessionStartInitDelayMs = resolveSessionStartInitDelayMs();
|
|
346
393
|
if (sessionStartInitDelayMs > 0) {
|
|
347
394
|
await new Promise((resolve) => setTimeout(resolve, sessionStartInitDelayMs));
|
|
@@ -349,7 +396,9 @@ async function handleParentMessage(message, handlers) {
|
|
|
349
396
|
await (handlers.onClientJoin ?? handlers.onSessionStart)?.({
|
|
350
397
|
sessionId: message.sessionId,
|
|
351
398
|
env: message.env,
|
|
352
|
-
recordingAvailable: message.recordingAvailable ?? false
|
|
399
|
+
recordingAvailable: message.recordingAvailable ?? false,
|
|
400
|
+
mixAvailable: message.mixAvailable ?? false,
|
|
401
|
+
ttsPoseAvailable: message.ttsPoseAvailable ?? false
|
|
353
402
|
});
|
|
354
403
|
sendParentMessage({
|
|
355
404
|
type: "session_start_ack",
|
|
@@ -387,6 +436,8 @@ async function handleParentMessage(message, handlers) {
|
|
|
387
436
|
clearPendingRecordingAcksForSession(message.sessionId, "session_ended");
|
|
388
437
|
peerEnvBySessionId.delete(message.sessionId);
|
|
389
438
|
recordingAvailableBySessionId.delete(message.sessionId);
|
|
439
|
+
mixAvailableBySessionId.delete(message.sessionId);
|
|
440
|
+
ttsPoseAvailableBySessionId.delete(message.sessionId);
|
|
390
441
|
await (handlers.onClientLeave ?? handlers.onSessionEnd)?.({
|
|
391
442
|
sessionId: message.sessionId
|
|
392
443
|
});
|
|
@@ -406,6 +457,14 @@ function defineAgent(handlers) {
|
|
|
406
457
|
handleRecordingControlAck(message);
|
|
407
458
|
return;
|
|
408
459
|
}
|
|
460
|
+
if (isMixControlAckMessage(message)) {
|
|
461
|
+
handleMixControlAck(message);
|
|
462
|
+
return;
|
|
463
|
+
}
|
|
464
|
+
if (isSttControlAckMessage(message)) {
|
|
465
|
+
handleSttControlAck(message);
|
|
466
|
+
return;
|
|
467
|
+
}
|
|
409
468
|
if (isWebhookMessage(message)) {
|
|
410
469
|
void agentStartReady.then(() => handleWebhookMessage(message, handlers));
|
|
411
470
|
return;
|
|
@@ -139,6 +139,18 @@ function isRecordingControlAckMessage(value) {
|
|
|
139
139
|
const msg = value;
|
|
140
140
|
return msg.type === "recording_control_ack" && typeof msg.requestId === "string";
|
|
141
141
|
}
|
|
142
|
+
function isMixControlAckMessage(value) {
|
|
143
|
+
if (!value || typeof value !== "object")
|
|
144
|
+
return false;
|
|
145
|
+
const msg = value;
|
|
146
|
+
return msg.type === "mix_control_ack" && typeof msg.requestId === "string";
|
|
147
|
+
}
|
|
148
|
+
function isSttControlAckMessage(value) {
|
|
149
|
+
if (!value || typeof value !== "object")
|
|
150
|
+
return false;
|
|
151
|
+
const msg = value;
|
|
152
|
+
return msg.type === "stt_control_ack" && typeof msg.requestId === "string";
|
|
153
|
+
}
|
|
142
154
|
function isWebhookMessage(value) {
|
|
143
155
|
if (!value || typeof value !== "object")
|
|
144
156
|
return false;
|
|
@@ -181,7 +193,7 @@ function isParentMessage(value) {
|
|
|
181
193
|
if (!value || typeof value !== "object")
|
|
182
194
|
return false;
|
|
183
195
|
const msg = value;
|
|
184
|
-
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 === "webhook";
|
|
196
|
+
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 === "mix_control_ack" || msg.type === "stt_control_ack" || msg.type === "webhook";
|
|
185
197
|
}
|
|
186
198
|
function isSessionScopedParentMessage(value) {
|
|
187
199
|
return isParentMessage(value) && !isWebhookMessage(value);
|
|
@@ -195,8 +207,12 @@ function parseDataChannelPayload(raw) {
|
|
|
195
207
|
}
|
|
196
208
|
var peerEnvBySessionId = /* @__PURE__ */ new Map();
|
|
197
209
|
var recordingAvailableBySessionId = /* @__PURE__ */ new Map();
|
|
210
|
+
var mixAvailableBySessionId = /* @__PURE__ */ new Map();
|
|
211
|
+
var ttsPoseAvailableBySessionId = /* @__PURE__ */ new Map();
|
|
198
212
|
var endedSessionIds = /* @__PURE__ */ new Set();
|
|
199
213
|
var pendingRecordingAcks = /* @__PURE__ */ new Map();
|
|
214
|
+
var pendingMixAcks = /* @__PURE__ */ new Map();
|
|
215
|
+
var pendingSttAcks = /* @__PURE__ */ new Map();
|
|
200
216
|
function handleRecordingControlAck(message) {
|
|
201
217
|
const pending = pendingRecordingAcks.get(message.requestId);
|
|
202
218
|
if (!pending)
|
|
@@ -209,6 +225,30 @@ function handleRecordingControlAck(message) {
|
|
|
209
225
|
requestId: message.requestId
|
|
210
226
|
});
|
|
211
227
|
}
|
|
228
|
+
function handleMixControlAck(message) {
|
|
229
|
+
const pending = pendingMixAcks.get(message.requestId);
|
|
230
|
+
if (!pending)
|
|
231
|
+
return;
|
|
232
|
+
clearTimeout(pending.timer);
|
|
233
|
+
pendingMixAcks.delete(message.requestId);
|
|
234
|
+
pending.resolve({
|
|
235
|
+
ok: message.ok,
|
|
236
|
+
reason: message.reason,
|
|
237
|
+
requestId: message.requestId
|
|
238
|
+
});
|
|
239
|
+
}
|
|
240
|
+
function handleSttControlAck(message) {
|
|
241
|
+
const pending = pendingSttAcks.get(message.requestId);
|
|
242
|
+
if (!pending)
|
|
243
|
+
return;
|
|
244
|
+
clearTimeout(pending.timer);
|
|
245
|
+
pendingSttAcks.delete(message.requestId);
|
|
246
|
+
pending.resolve({
|
|
247
|
+
ok: message.ok,
|
|
248
|
+
reason: message.reason,
|
|
249
|
+
requestId: message.requestId
|
|
250
|
+
});
|
|
251
|
+
}
|
|
212
252
|
function clearPendingRecordingAcksForSession(sessionId, reason) {
|
|
213
253
|
for (const [requestId, pending] of pendingRecordingAcks) {
|
|
214
254
|
if (pending.sessionId !== sessionId)
|
|
@@ -264,6 +304,11 @@ function allowOutboundForSession(sessionId) {
|
|
|
264
304
|
return queue.isLive(sessionId);
|
|
265
305
|
}
|
|
266
306
|
function sendParentMessage(message) {
|
|
307
|
+
const msgType = message && typeof message === "object" && "type" in message ? message.type : void 0;
|
|
308
|
+
if (msgType === "mix_control" || msgType === "stt_control") {
|
|
309
|
+
process.send?.(message);
|
|
310
|
+
return;
|
|
311
|
+
}
|
|
267
312
|
const sessionId = message && typeof message === "object" && "sessionId" in message && typeof message.sessionId === "string" ? message.sessionId : void 0;
|
|
268
313
|
if (!allowOutboundForSession(sessionId))
|
|
269
314
|
return;
|
|
@@ -345,6 +390,8 @@ async function handleParentMessage(message, handlers) {
|
|
|
345
390
|
endedSessionIds.delete(message.sessionId);
|
|
346
391
|
peerEnvBySessionId.set(message.sessionId, message.env);
|
|
347
392
|
recordingAvailableBySessionId.set(message.sessionId, message.recordingAvailable ?? false);
|
|
393
|
+
mixAvailableBySessionId.set(message.sessionId, message.mixAvailable ?? false);
|
|
394
|
+
ttsPoseAvailableBySessionId.set(message.sessionId, message.ttsPoseAvailable ?? false);
|
|
348
395
|
const sessionStartInitDelayMs = resolveSessionStartInitDelayMs();
|
|
349
396
|
if (sessionStartInitDelayMs > 0) {
|
|
350
397
|
await new Promise((resolve) => setTimeout(resolve, sessionStartInitDelayMs));
|
|
@@ -352,7 +399,9 @@ async function handleParentMessage(message, handlers) {
|
|
|
352
399
|
await (handlers.onClientJoin ?? handlers.onSessionStart)?.({
|
|
353
400
|
sessionId: message.sessionId,
|
|
354
401
|
env: message.env,
|
|
355
|
-
recordingAvailable: message.recordingAvailable ?? false
|
|
402
|
+
recordingAvailable: message.recordingAvailable ?? false,
|
|
403
|
+
mixAvailable: message.mixAvailable ?? false,
|
|
404
|
+
ttsPoseAvailable: message.ttsPoseAvailable ?? false
|
|
356
405
|
});
|
|
357
406
|
sendParentMessage({
|
|
358
407
|
type: "session_start_ack",
|
|
@@ -390,6 +439,8 @@ async function handleParentMessage(message, handlers) {
|
|
|
390
439
|
clearPendingRecordingAcksForSession(message.sessionId, "session_ended");
|
|
391
440
|
peerEnvBySessionId.delete(message.sessionId);
|
|
392
441
|
recordingAvailableBySessionId.delete(message.sessionId);
|
|
442
|
+
mixAvailableBySessionId.delete(message.sessionId);
|
|
443
|
+
ttsPoseAvailableBySessionId.delete(message.sessionId);
|
|
393
444
|
await (handlers.onClientLeave ?? handlers.onSessionEnd)?.({
|
|
394
445
|
sessionId: message.sessionId
|
|
395
446
|
});
|
|
@@ -409,6 +460,14 @@ function defineAgent(handlers) {
|
|
|
409
460
|
handleRecordingControlAck(message);
|
|
410
461
|
return;
|
|
411
462
|
}
|
|
463
|
+
if (isMixControlAckMessage(message)) {
|
|
464
|
+
handleMixControlAck(message);
|
|
465
|
+
return;
|
|
466
|
+
}
|
|
467
|
+
if (isSttControlAckMessage(message)) {
|
|
468
|
+
handleSttControlAck(message);
|
|
469
|
+
return;
|
|
470
|
+
}
|
|
412
471
|
if (isWebhookMessage(message)) {
|
|
413
472
|
void agentStartReady.then(() => handleWebhookMessage(message, handlers));
|
|
414
473
|
return;
|