@voicethere/agent 0.8.0 → 0.8.2
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/README.md +10 -9
- package/dist/agent.js +45 -1
- package/dist/index.d.ts +2 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/dist/protocol.d.ts +36 -2
- package/dist/protocol.d.ts.map +1 -1
- package/dist/protocol.js.map +1 -1
- package/dist/runtime.d.ts +21 -1
- package/dist/runtime.d.ts.map +1 -1
- package/dist/runtime.js +112 -0
- package/dist/runtime.js.map +1 -1
- package/dist/templates/echo/agent.js +54 -5
- package/dist/templates/echo-dc/agent.js +39 -1
- package/dist/templates/game-sync/agent.js +39 -1
- package/dist/templates/positional-tts/agent.js +39 -1
- package/dist/templates/recording-consent/agent.js +51 -13
- package/dist/templates/spatial-showcase/agent.js +39 -1
- package/dist/templates/voice-showcase/agent.js +103 -26
- package/dist/templates/voice-starter/agent.js +39 -1
- package/dist/templates/webhooks/agent.js +39 -1
- package/dist/templates/webhooks-redis/agent.js +39 -1
- package/dist/templates/world-sync/agent.js +39 -1
- package/dist/templates/world-sync-binary/agent.js +39 -1
- package/package.json +1 -1
- package/templates/echo/agent.ts +3 -5
- package/templates/voice-showcase/agent.ts +3 -1
- package/templates/voice-showcase/conversation.ts +9 -5
- package/templates/voice-showcase/delivery.ts +40 -10
|
@@ -160,6 +160,12 @@ function isRecordingControlAckMessage(value) {
|
|
|
160
160
|
const msg = value;
|
|
161
161
|
return msg.type === "recording_control_ack" && typeof msg.requestId === "string";
|
|
162
162
|
}
|
|
163
|
+
function isConversationHistoryControlAckMessage(value) {
|
|
164
|
+
if (!value || typeof value !== "object")
|
|
165
|
+
return false;
|
|
166
|
+
const msg = value;
|
|
167
|
+
return msg.type === "conversation_history_control_ack" && typeof msg.requestId === "string";
|
|
168
|
+
}
|
|
163
169
|
function isMixControlAckMessage(value) {
|
|
164
170
|
if (!value || typeof value !== "object")
|
|
165
171
|
return false;
|
|
@@ -214,7 +220,7 @@ function isParentMessage(value) {
|
|
|
214
220
|
if (!value || typeof value !== "object")
|
|
215
221
|
return false;
|
|
216
222
|
const msg = value;
|
|
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";
|
|
223
|
+
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 === "conversation_history_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";
|
|
218
224
|
}
|
|
219
225
|
function isSessionScopedParentMessage(value) {
|
|
220
226
|
return isParentMessage(value) && !isWebhookMessage(value);
|
|
@@ -228,11 +234,13 @@ function parseDataChannelPayload(raw) {
|
|
|
228
234
|
}
|
|
229
235
|
var peerEnvBySessionId = /* @__PURE__ */ new Map();
|
|
230
236
|
var recordingAvailableBySessionId = /* @__PURE__ */ new Map();
|
|
237
|
+
var conversationHistoryAvailableBySessionId = /* @__PURE__ */ new Map();
|
|
231
238
|
var mixAvailableBySessionId = /* @__PURE__ */ new Map();
|
|
232
239
|
var ttsPoseAvailableBySessionId = /* @__PURE__ */ new Map();
|
|
233
240
|
var endedSessionIds = /* @__PURE__ */ new Set();
|
|
234
241
|
var PLAY_BYTES_MAX_DECODED_LENGTH = 64 * 1024;
|
|
235
242
|
var pendingRecordingAcks = /* @__PURE__ */ new Map();
|
|
243
|
+
var pendingConversationHistoryAcks = /* @__PURE__ */ new Map();
|
|
236
244
|
var pendingPlayAcks = /* @__PURE__ */ new Map();
|
|
237
245
|
var pendingPlayStatusAcks = /* @__PURE__ */ new Map();
|
|
238
246
|
var pendingPlayStopAcks = /* @__PURE__ */ new Map();
|
|
@@ -251,6 +259,18 @@ function handleRecordingControlAck(message) {
|
|
|
251
259
|
requestId: message.requestId
|
|
252
260
|
});
|
|
253
261
|
}
|
|
262
|
+
function handleConversationHistoryControlAck(message) {
|
|
263
|
+
const pending = pendingConversationHistoryAcks.get(message.requestId);
|
|
264
|
+
if (!pending)
|
|
265
|
+
return;
|
|
266
|
+
clearTimeout(pending.timer);
|
|
267
|
+
pendingConversationHistoryAcks.delete(message.requestId);
|
|
268
|
+
pending.resolve({
|
|
269
|
+
ok: message.ok,
|
|
270
|
+
reason: message.reason,
|
|
271
|
+
requestId: message.requestId
|
|
272
|
+
});
|
|
273
|
+
}
|
|
254
274
|
function handlePlayAck(message) {
|
|
255
275
|
const pending = pendingPlayAcks.get(message.requestId);
|
|
256
276
|
if (!pending)
|
|
@@ -338,6 +358,15 @@ function clearPendingRecordingAcksForSession(sessionId, reason) {
|
|
|
338
358
|
pending.resolve({ ok: false, reason, requestId });
|
|
339
359
|
}
|
|
340
360
|
}
|
|
361
|
+
function clearPendingConversationHistoryAcksForSession(sessionId, reason) {
|
|
362
|
+
for (const [requestId, pending] of pendingConversationHistoryAcks) {
|
|
363
|
+
if (pending.sessionId !== sessionId)
|
|
364
|
+
continue;
|
|
365
|
+
clearTimeout(pending.timer);
|
|
366
|
+
pendingConversationHistoryAcks.delete(requestId);
|
|
367
|
+
pending.resolve({ ok: false, reason, requestId });
|
|
368
|
+
}
|
|
369
|
+
}
|
|
341
370
|
var sessionExecutionContext = new AsyncLocalStorage();
|
|
342
371
|
var agentLogSessionContext = new AsyncLocalStorage();
|
|
343
372
|
var inboundQueueAuthority = null;
|
|
@@ -484,6 +513,7 @@ async function handleParentMessage(message, handlers) {
|
|
|
484
513
|
endedSessionIds.delete(message.sessionId);
|
|
485
514
|
peerEnvBySessionId.set(message.sessionId, message.env);
|
|
486
515
|
recordingAvailableBySessionId.set(message.sessionId, message.recordingAvailable ?? false);
|
|
516
|
+
conversationHistoryAvailableBySessionId.set(message.sessionId, message.conversationHistoryAvailable ?? false);
|
|
487
517
|
mixAvailableBySessionId.set(message.sessionId, message.mixAvailable ?? false);
|
|
488
518
|
ttsPoseAvailableBySessionId.set(message.sessionId, message.ttsPoseAvailable ?? false);
|
|
489
519
|
const sessionStartInitDelayMs = resolveSessionStartInitDelayMs();
|
|
@@ -494,6 +524,7 @@ async function handleParentMessage(message, handlers) {
|
|
|
494
524
|
sessionId: message.sessionId,
|
|
495
525
|
env: message.env,
|
|
496
526
|
recordingAvailable: message.recordingAvailable ?? false,
|
|
527
|
+
conversationHistoryAvailable: message.conversationHistoryAvailable ?? false,
|
|
497
528
|
mixAvailable: message.mixAvailable ?? false,
|
|
498
529
|
ttsPoseAvailable: message.ttsPoseAvailable ?? false
|
|
499
530
|
});
|
|
@@ -540,8 +571,10 @@ async function handleParentMessage(message, handlers) {
|
|
|
540
571
|
break;
|
|
541
572
|
case "session_end":
|
|
542
573
|
clearPendingRecordingAcksForSession(message.sessionId, "session_ended");
|
|
574
|
+
clearPendingConversationHistoryAcksForSession(message.sessionId, "session_ended");
|
|
543
575
|
peerEnvBySessionId.delete(message.sessionId);
|
|
544
576
|
recordingAvailableBySessionId.delete(message.sessionId);
|
|
577
|
+
conversationHistoryAvailableBySessionId.delete(message.sessionId);
|
|
545
578
|
mixAvailableBySessionId.delete(message.sessionId);
|
|
546
579
|
ttsPoseAvailableBySessionId.delete(message.sessionId);
|
|
547
580
|
await (handlers.onClientLeave ?? handlers.onSessionEnd)?.({
|
|
@@ -563,6 +596,10 @@ function defineAgent(handlers) {
|
|
|
563
596
|
handleRecordingControlAck(message);
|
|
564
597
|
return;
|
|
565
598
|
}
|
|
599
|
+
if (isConversationHistoryControlAckMessage(message)) {
|
|
600
|
+
handleConversationHistoryControlAck(message);
|
|
601
|
+
return;
|
|
602
|
+
}
|
|
566
603
|
if (isPlayAckMessage(message)) {
|
|
567
604
|
handlePlayAck(message);
|
|
568
605
|
return;
|
|
@@ -596,6 +633,7 @@ function defineAgent(handlers) {
|
|
|
596
633
|
if (message.type === "session_end") {
|
|
597
634
|
endedSessionIds.add(message.sessionId);
|
|
598
635
|
clearPendingRecordingAcksForSession(message.sessionId, "session_ended");
|
|
636
|
+
clearPendingConversationHistoryAcksForSession(message.sessionId, "session_ended");
|
|
599
637
|
inboundBySession.clear(message.sessionId);
|
|
600
638
|
}
|
|
601
639
|
if (message.type === "session_start") {
|
|
@@ -723,6 +761,19 @@ function buildIdleEnv(sessionId) {
|
|
|
723
761
|
function speak(sessionId, text) {
|
|
724
762
|
sendParentMessage({ type: "speak", sessionId, text });
|
|
725
763
|
}
|
|
764
|
+
function speakAndChat(sessionId, text, options) {
|
|
765
|
+
const trimmed = text.trim();
|
|
766
|
+
if (!trimmed) {
|
|
767
|
+
return;
|
|
768
|
+
}
|
|
769
|
+
const payload = { type: "chat_reply", text: trimmed };
|
|
770
|
+
if (options?.stream) {
|
|
771
|
+
payload.stream = true;
|
|
772
|
+
payload.utteranceId = options.utteranceId ?? randomUUID();
|
|
773
|
+
}
|
|
774
|
+
sendToClient(sessionId, payload);
|
|
775
|
+
speak(sessionId, trimmed);
|
|
776
|
+
}
|
|
726
777
|
function sendToClient(sessionId, payload) {
|
|
727
778
|
sendParentMessage({ type: "send_to_client", sessionId, payload });
|
|
728
779
|
}
|
|
@@ -791,6 +842,9 @@ function parseChatText(message) {
|
|
|
791
842
|
return trimmed.length > 0 ? trimmed : null;
|
|
792
843
|
}
|
|
793
844
|
|
|
845
|
+
// templates/voice-showcase/conversation.ts
|
|
846
|
+
import { randomUUID as randomUUID2 } from "node:crypto";
|
|
847
|
+
|
|
794
848
|
// templates/voice-showcase/recipes.ts
|
|
795
849
|
var RECIPES = [
|
|
796
850
|
{
|
|
@@ -1134,10 +1188,11 @@ function buildMenuMessages() {
|
|
|
1134
1188
|
}
|
|
1135
1189
|
];
|
|
1136
1190
|
}
|
|
1137
|
-
function
|
|
1191
|
+
function speakAndChat2(text) {
|
|
1192
|
+
const utteranceId = randomUUID2();
|
|
1138
1193
|
return {
|
|
1139
1194
|
speakLines: [text],
|
|
1140
|
-
messages: [{ type: "chat_reply", text }]
|
|
1195
|
+
messages: [{ type: "chat_reply", text, stream: true, utteranceId }]
|
|
1141
1196
|
};
|
|
1142
1197
|
}
|
|
1143
1198
|
function isHumanEscalation(utterance) {
|
|
@@ -1214,15 +1269,15 @@ function transitionAfterName(state, name, declined) {
|
|
|
1214
1269
|
const lines = [];
|
|
1215
1270
|
const messages = [];
|
|
1216
1271
|
if (declined) {
|
|
1217
|
-
const decline =
|
|
1272
|
+
const decline = speakAndChat2(NAME_DECLINE_REPLY);
|
|
1218
1273
|
lines.push(...decline.speakLines);
|
|
1219
1274
|
messages.push(...decline.messages);
|
|
1220
1275
|
} else if (name) {
|
|
1221
|
-
const thanks =
|
|
1276
|
+
const thanks = speakAndChat2(`Great, thank you ${name}`);
|
|
1222
1277
|
lines.push(...thanks.speakLines);
|
|
1223
1278
|
messages.push(...thanks.messages);
|
|
1224
1279
|
}
|
|
1225
|
-
const hello =
|
|
1280
|
+
const hello = speakAndChat2(helloAfterName(next));
|
|
1226
1281
|
lines.push(...hello.speakLines);
|
|
1227
1282
|
messages.push(...hello.messages);
|
|
1228
1283
|
messages.push(...buildMenuMessages());
|
|
@@ -1281,7 +1336,7 @@ function formatCountingSpeech(n) {
|
|
|
1281
1336
|
return parts.join(", ");
|
|
1282
1337
|
}
|
|
1283
1338
|
function resendMenu(state) {
|
|
1284
|
-
const menu =
|
|
1339
|
+
const menu = speakAndChat2("Here is the menu again.");
|
|
1285
1340
|
return {
|
|
1286
1341
|
state: { ...state, phase: "awaitingMenuChoice" },
|
|
1287
1342
|
speakLines: menu.speakLines,
|
|
@@ -1289,7 +1344,7 @@ function resendMenu(state) {
|
|
|
1289
1344
|
};
|
|
1290
1345
|
}
|
|
1291
1346
|
function returnToMenu(state, line) {
|
|
1292
|
-
const spoken =
|
|
1347
|
+
const spoken = speakAndChat2(line);
|
|
1293
1348
|
return {
|
|
1294
1349
|
state: {
|
|
1295
1350
|
...state,
|
|
@@ -1309,7 +1364,7 @@ function handleUtterance(state, utterance) {
|
|
|
1309
1364
|
return { state, speakLines: [], messages: [] };
|
|
1310
1365
|
}
|
|
1311
1366
|
if (isHumanEscalation(text)) {
|
|
1312
|
-
const reply =
|
|
1367
|
+
const reply = speakAndChat2(HUMAN_ESCALATION_REPLY);
|
|
1313
1368
|
return {
|
|
1314
1369
|
state,
|
|
1315
1370
|
speakLines: reply.speakLines,
|
|
@@ -1338,7 +1393,7 @@ function handleUtterance(state, utterance) {
|
|
|
1338
1393
|
const choice = parseMenuChoice(text);
|
|
1339
1394
|
if (choice === "menu") return resendMenu(state);
|
|
1340
1395
|
if (choice === "weather") {
|
|
1341
|
-
const ask =
|
|
1396
|
+
const ask = speakAndChat2(
|
|
1342
1397
|
"Sure. Please tell me a city or ZIP code and the country."
|
|
1343
1398
|
);
|
|
1344
1399
|
return {
|
|
@@ -1354,7 +1409,7 @@ function handleUtterance(state, utterance) {
|
|
|
1354
1409
|
};
|
|
1355
1410
|
}
|
|
1356
1411
|
if (choice === "count") {
|
|
1357
|
-
const ask =
|
|
1412
|
+
const ask = speakAndChat2(
|
|
1358
1413
|
"Pick a number from 1 to 10 and I will count up to it."
|
|
1359
1414
|
);
|
|
1360
1415
|
return {
|
|
@@ -1368,7 +1423,7 @@ function handleUtterance(state, utterance) {
|
|
|
1368
1423
|
};
|
|
1369
1424
|
}
|
|
1370
1425
|
if (choice === "recipe") {
|
|
1371
|
-
const ask =
|
|
1426
|
+
const ask = speakAndChat2(
|
|
1372
1427
|
"What do you fancy? Try pasta, soup, breakfast, cookies, or salad."
|
|
1373
1428
|
);
|
|
1374
1429
|
return {
|
|
@@ -1381,7 +1436,7 @@ function handleUtterance(state, utterance) {
|
|
|
1381
1436
|
const fact = pickFunFact();
|
|
1382
1437
|
return returnToMenu(state, `Here is a fun fact. ${fact}`);
|
|
1383
1438
|
}
|
|
1384
|
-
const retry =
|
|
1439
|
+
const retry = speakAndChat2(
|
|
1385
1440
|
"I did not catch that. Pick 1 through 4 from the menu, or say weather, count, recipe, or fun fact."
|
|
1386
1441
|
);
|
|
1387
1442
|
return {
|
|
@@ -1402,7 +1457,7 @@ function handleUtterance(state, utterance) {
|
|
|
1402
1457
|
}
|
|
1403
1458
|
}
|
|
1404
1459
|
if (!city) {
|
|
1405
|
-
const ask =
|
|
1460
|
+
const ask = speakAndChat2(
|
|
1406
1461
|
"Please tell me a city or ZIP code and the country."
|
|
1407
1462
|
);
|
|
1408
1463
|
return {
|
|
@@ -1412,16 +1467,15 @@ function handleUtterance(state, utterance) {
|
|
|
1412
1467
|
};
|
|
1413
1468
|
}
|
|
1414
1469
|
if (!country) {
|
|
1470
|
+
const ask = speakAndChat2("Got it. Which country is that in?");
|
|
1415
1471
|
return {
|
|
1416
1472
|
state: {
|
|
1417
1473
|
...state,
|
|
1418
1474
|
phase: "weatherAwaitingLocation",
|
|
1419
1475
|
weatherCity: city
|
|
1420
1476
|
},
|
|
1421
|
-
speakLines:
|
|
1422
|
-
messages:
|
|
1423
|
-
{ type: "chat_reply", text: "Got it. Which country is that in?" }
|
|
1424
|
-
]
|
|
1477
|
+
speakLines: ask.speakLines,
|
|
1478
|
+
messages: ask.messages
|
|
1425
1479
|
};
|
|
1426
1480
|
}
|
|
1427
1481
|
return {
|
|
@@ -1438,7 +1492,7 @@ function handleUtterance(state, utterance) {
|
|
|
1438
1492
|
if (failures >= 2) {
|
|
1439
1493
|
return returnToMenu(state, "Sorry, I cannot do this.");
|
|
1440
1494
|
}
|
|
1441
|
-
const retry =
|
|
1495
|
+
const retry = speakAndChat2(
|
|
1442
1496
|
"I did not understand you. Please say a number from 1 to 10."
|
|
1443
1497
|
);
|
|
1444
1498
|
return {
|
|
@@ -1471,7 +1525,7 @@ function applyWeatherFailure(state) {
|
|
|
1471
1525
|
"Sorry, I could not look up the weather right now."
|
|
1472
1526
|
);
|
|
1473
1527
|
}
|
|
1474
|
-
const retry =
|
|
1528
|
+
const retry = speakAndChat2(
|
|
1475
1529
|
"I could not find that location. Please try again with a city or ZIP and country."
|
|
1476
1530
|
);
|
|
1477
1531
|
return {
|
|
@@ -1499,6 +1553,7 @@ async function resolveWeatherTurn(state, city, country, fetchFn) {
|
|
|
1499
1553
|
}
|
|
1500
1554
|
|
|
1501
1555
|
// templates/voice-showcase/delivery.ts
|
|
1556
|
+
import { randomUUID as randomUUID3 } from "node:crypto";
|
|
1502
1557
|
function spokenThenPlayOps(messages, speakLines) {
|
|
1503
1558
|
const ops = [];
|
|
1504
1559
|
for (const message of messages) {
|
|
@@ -1510,21 +1565,42 @@ function spokenThenPlayOps(messages, speakLines) {
|
|
|
1510
1565
|
return ops;
|
|
1511
1566
|
}
|
|
1512
1567
|
function greetingOps(sessionId, greeting) {
|
|
1568
|
+
const utteranceId = randomUUID3();
|
|
1513
1569
|
return spokenThenPlayOps(
|
|
1514
1570
|
[
|
|
1515
1571
|
{ type: "agent_event", event: "session_start", sessionId },
|
|
1516
|
-
{
|
|
1572
|
+
{
|
|
1573
|
+
type: "chat_reply",
|
|
1574
|
+
text: greeting,
|
|
1575
|
+
stream: true,
|
|
1576
|
+
utteranceId
|
|
1577
|
+
}
|
|
1517
1578
|
],
|
|
1518
1579
|
[greeting]
|
|
1519
1580
|
);
|
|
1520
1581
|
}
|
|
1521
1582
|
function applyOutboundOps(sessionId, ops, deps) {
|
|
1583
|
+
const spokenViaSpeakAndChat = /* @__PURE__ */ new Set();
|
|
1522
1584
|
for (const op of ops) {
|
|
1523
1585
|
if (op.kind === "send") {
|
|
1524
|
-
|
|
1525
|
-
|
|
1526
|
-
|
|
1586
|
+
const message = op.message;
|
|
1587
|
+
if (message.type === "chat_reply" && message.stream === true && message.text?.trim()) {
|
|
1588
|
+
const text = message.text.trim();
|
|
1589
|
+
deps.speakAndChat(sessionId, text, {
|
|
1590
|
+
stream: true,
|
|
1591
|
+
utteranceId: message.utteranceId
|
|
1592
|
+
});
|
|
1593
|
+
spokenViaSpeakAndChat.add(text);
|
|
1594
|
+
} else {
|
|
1595
|
+
deps.sendToClient(sessionId, message);
|
|
1596
|
+
}
|
|
1597
|
+
continue;
|
|
1598
|
+
}
|
|
1599
|
+
const playText = op.text.trim();
|
|
1600
|
+
if (spokenViaSpeakAndChat.has(playText)) {
|
|
1601
|
+
continue;
|
|
1527
1602
|
}
|
|
1603
|
+
deps.speak(sessionId, op.text);
|
|
1528
1604
|
}
|
|
1529
1605
|
}
|
|
1530
1606
|
|
|
@@ -1550,7 +1626,7 @@ function deliverSpokenThenPlay(sessionId, result) {
|
|
|
1550
1626
|
applyOutboundOps(
|
|
1551
1627
|
sessionId,
|
|
1552
1628
|
spokenThenPlayOps(result.messages, result.speakLines),
|
|
1553
|
-
{ sendToClient, speak }
|
|
1629
|
+
{ sendToClient, speak, speakAndChat }
|
|
1554
1630
|
);
|
|
1555
1631
|
}
|
|
1556
1632
|
async function applyTurn(sessionId, result) {
|
|
@@ -1576,7 +1652,8 @@ defineAgent({
|
|
|
1576
1652
|
sessions.set(sessionId, createInitialState());
|
|
1577
1653
|
applyOutboundOps(sessionId, greetingOps(sessionId, GREETING), {
|
|
1578
1654
|
sendToClient,
|
|
1579
|
-
speak
|
|
1655
|
+
speak,
|
|
1656
|
+
speakAndChat
|
|
1580
1657
|
});
|
|
1581
1658
|
agentLog("info", `voice-showcase session_start ${sessionId}`);
|
|
1582
1659
|
},
|
|
@@ -160,6 +160,12 @@ function isRecordingControlAckMessage(value) {
|
|
|
160
160
|
const msg = value;
|
|
161
161
|
return msg.type === "recording_control_ack" && typeof msg.requestId === "string";
|
|
162
162
|
}
|
|
163
|
+
function isConversationHistoryControlAckMessage(value) {
|
|
164
|
+
if (!value || typeof value !== "object")
|
|
165
|
+
return false;
|
|
166
|
+
const msg = value;
|
|
167
|
+
return msg.type === "conversation_history_control_ack" && typeof msg.requestId === "string";
|
|
168
|
+
}
|
|
163
169
|
function isMixControlAckMessage(value) {
|
|
164
170
|
if (!value || typeof value !== "object")
|
|
165
171
|
return false;
|
|
@@ -214,7 +220,7 @@ function isParentMessage(value) {
|
|
|
214
220
|
if (!value || typeof value !== "object")
|
|
215
221
|
return false;
|
|
216
222
|
const msg = value;
|
|
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";
|
|
223
|
+
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 === "conversation_history_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";
|
|
218
224
|
}
|
|
219
225
|
function isSessionScopedParentMessage(value) {
|
|
220
226
|
return isParentMessage(value) && !isWebhookMessage(value);
|
|
@@ -228,11 +234,13 @@ function parseDataChannelPayload(raw) {
|
|
|
228
234
|
}
|
|
229
235
|
var peerEnvBySessionId = /* @__PURE__ */ new Map();
|
|
230
236
|
var recordingAvailableBySessionId = /* @__PURE__ */ new Map();
|
|
237
|
+
var conversationHistoryAvailableBySessionId = /* @__PURE__ */ new Map();
|
|
231
238
|
var mixAvailableBySessionId = /* @__PURE__ */ new Map();
|
|
232
239
|
var ttsPoseAvailableBySessionId = /* @__PURE__ */ new Map();
|
|
233
240
|
var endedSessionIds = /* @__PURE__ */ new Set();
|
|
234
241
|
var PLAY_BYTES_MAX_DECODED_LENGTH = 64 * 1024;
|
|
235
242
|
var pendingRecordingAcks = /* @__PURE__ */ new Map();
|
|
243
|
+
var pendingConversationHistoryAcks = /* @__PURE__ */ new Map();
|
|
236
244
|
var pendingPlayAcks = /* @__PURE__ */ new Map();
|
|
237
245
|
var pendingPlayStatusAcks = /* @__PURE__ */ new Map();
|
|
238
246
|
var pendingPlayStopAcks = /* @__PURE__ */ new Map();
|
|
@@ -251,6 +259,18 @@ function handleRecordingControlAck(message) {
|
|
|
251
259
|
requestId: message.requestId
|
|
252
260
|
});
|
|
253
261
|
}
|
|
262
|
+
function handleConversationHistoryControlAck(message) {
|
|
263
|
+
const pending = pendingConversationHistoryAcks.get(message.requestId);
|
|
264
|
+
if (!pending)
|
|
265
|
+
return;
|
|
266
|
+
clearTimeout(pending.timer);
|
|
267
|
+
pendingConversationHistoryAcks.delete(message.requestId);
|
|
268
|
+
pending.resolve({
|
|
269
|
+
ok: message.ok,
|
|
270
|
+
reason: message.reason,
|
|
271
|
+
requestId: message.requestId
|
|
272
|
+
});
|
|
273
|
+
}
|
|
254
274
|
function handlePlayAck(message) {
|
|
255
275
|
const pending = pendingPlayAcks.get(message.requestId);
|
|
256
276
|
if (!pending)
|
|
@@ -338,6 +358,15 @@ function clearPendingRecordingAcksForSession(sessionId, reason) {
|
|
|
338
358
|
pending.resolve({ ok: false, reason, requestId });
|
|
339
359
|
}
|
|
340
360
|
}
|
|
361
|
+
function clearPendingConversationHistoryAcksForSession(sessionId, reason) {
|
|
362
|
+
for (const [requestId, pending] of pendingConversationHistoryAcks) {
|
|
363
|
+
if (pending.sessionId !== sessionId)
|
|
364
|
+
continue;
|
|
365
|
+
clearTimeout(pending.timer);
|
|
366
|
+
pendingConversationHistoryAcks.delete(requestId);
|
|
367
|
+
pending.resolve({ ok: false, reason, requestId });
|
|
368
|
+
}
|
|
369
|
+
}
|
|
341
370
|
var sessionExecutionContext = new AsyncLocalStorage();
|
|
342
371
|
var agentLogSessionContext = new AsyncLocalStorage();
|
|
343
372
|
var inboundQueueAuthority = null;
|
|
@@ -484,6 +513,7 @@ async function handleParentMessage(message, handlers) {
|
|
|
484
513
|
endedSessionIds.delete(message.sessionId);
|
|
485
514
|
peerEnvBySessionId.set(message.sessionId, message.env);
|
|
486
515
|
recordingAvailableBySessionId.set(message.sessionId, message.recordingAvailable ?? false);
|
|
516
|
+
conversationHistoryAvailableBySessionId.set(message.sessionId, message.conversationHistoryAvailable ?? false);
|
|
487
517
|
mixAvailableBySessionId.set(message.sessionId, message.mixAvailable ?? false);
|
|
488
518
|
ttsPoseAvailableBySessionId.set(message.sessionId, message.ttsPoseAvailable ?? false);
|
|
489
519
|
const sessionStartInitDelayMs = resolveSessionStartInitDelayMs();
|
|
@@ -494,6 +524,7 @@ async function handleParentMessage(message, handlers) {
|
|
|
494
524
|
sessionId: message.sessionId,
|
|
495
525
|
env: message.env,
|
|
496
526
|
recordingAvailable: message.recordingAvailable ?? false,
|
|
527
|
+
conversationHistoryAvailable: message.conversationHistoryAvailable ?? false,
|
|
497
528
|
mixAvailable: message.mixAvailable ?? false,
|
|
498
529
|
ttsPoseAvailable: message.ttsPoseAvailable ?? false
|
|
499
530
|
});
|
|
@@ -540,8 +571,10 @@ async function handleParentMessage(message, handlers) {
|
|
|
540
571
|
break;
|
|
541
572
|
case "session_end":
|
|
542
573
|
clearPendingRecordingAcksForSession(message.sessionId, "session_ended");
|
|
574
|
+
clearPendingConversationHistoryAcksForSession(message.sessionId, "session_ended");
|
|
543
575
|
peerEnvBySessionId.delete(message.sessionId);
|
|
544
576
|
recordingAvailableBySessionId.delete(message.sessionId);
|
|
577
|
+
conversationHistoryAvailableBySessionId.delete(message.sessionId);
|
|
545
578
|
mixAvailableBySessionId.delete(message.sessionId);
|
|
546
579
|
ttsPoseAvailableBySessionId.delete(message.sessionId);
|
|
547
580
|
await (handlers.onClientLeave ?? handlers.onSessionEnd)?.({
|
|
@@ -563,6 +596,10 @@ function defineAgent(handlers) {
|
|
|
563
596
|
handleRecordingControlAck(message);
|
|
564
597
|
return;
|
|
565
598
|
}
|
|
599
|
+
if (isConversationHistoryControlAckMessage(message)) {
|
|
600
|
+
handleConversationHistoryControlAck(message);
|
|
601
|
+
return;
|
|
602
|
+
}
|
|
566
603
|
if (isPlayAckMessage(message)) {
|
|
567
604
|
handlePlayAck(message);
|
|
568
605
|
return;
|
|
@@ -596,6 +633,7 @@ function defineAgent(handlers) {
|
|
|
596
633
|
if (message.type === "session_end") {
|
|
597
634
|
endedSessionIds.add(message.sessionId);
|
|
598
635
|
clearPendingRecordingAcksForSession(message.sessionId, "session_ended");
|
|
636
|
+
clearPendingConversationHistoryAcksForSession(message.sessionId, "session_ended");
|
|
599
637
|
inboundBySession.clear(message.sessionId);
|
|
600
638
|
}
|
|
601
639
|
if (message.type === "session_start") {
|
|
@@ -163,6 +163,12 @@ function isRecordingControlAckMessage(value) {
|
|
|
163
163
|
const msg = value;
|
|
164
164
|
return msg.type === "recording_control_ack" && typeof msg.requestId === "string";
|
|
165
165
|
}
|
|
166
|
+
function isConversationHistoryControlAckMessage(value) {
|
|
167
|
+
if (!value || typeof value !== "object")
|
|
168
|
+
return false;
|
|
169
|
+
const msg = value;
|
|
170
|
+
return msg.type === "conversation_history_control_ack" && typeof msg.requestId === "string";
|
|
171
|
+
}
|
|
166
172
|
function isMixControlAckMessage(value) {
|
|
167
173
|
if (!value || typeof value !== "object")
|
|
168
174
|
return false;
|
|
@@ -217,7 +223,7 @@ function isParentMessage(value) {
|
|
|
217
223
|
if (!value || typeof value !== "object")
|
|
218
224
|
return false;
|
|
219
225
|
const msg = value;
|
|
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";
|
|
226
|
+
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 === "conversation_history_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";
|
|
221
227
|
}
|
|
222
228
|
function isSessionScopedParentMessage(value) {
|
|
223
229
|
return isParentMessage(value) && !isWebhookMessage(value);
|
|
@@ -231,11 +237,13 @@ function parseDataChannelPayload(raw) {
|
|
|
231
237
|
}
|
|
232
238
|
var peerEnvBySessionId = /* @__PURE__ */ new Map();
|
|
233
239
|
var recordingAvailableBySessionId = /* @__PURE__ */ new Map();
|
|
240
|
+
var conversationHistoryAvailableBySessionId = /* @__PURE__ */ new Map();
|
|
234
241
|
var mixAvailableBySessionId = /* @__PURE__ */ new Map();
|
|
235
242
|
var ttsPoseAvailableBySessionId = /* @__PURE__ */ new Map();
|
|
236
243
|
var endedSessionIds = /* @__PURE__ */ new Set();
|
|
237
244
|
var PLAY_BYTES_MAX_DECODED_LENGTH = 64 * 1024;
|
|
238
245
|
var pendingRecordingAcks = /* @__PURE__ */ new Map();
|
|
246
|
+
var pendingConversationHistoryAcks = /* @__PURE__ */ new Map();
|
|
239
247
|
var pendingPlayAcks = /* @__PURE__ */ new Map();
|
|
240
248
|
var pendingPlayStatusAcks = /* @__PURE__ */ new Map();
|
|
241
249
|
var pendingPlayStopAcks = /* @__PURE__ */ new Map();
|
|
@@ -254,6 +262,18 @@ function handleRecordingControlAck(message) {
|
|
|
254
262
|
requestId: message.requestId
|
|
255
263
|
});
|
|
256
264
|
}
|
|
265
|
+
function handleConversationHistoryControlAck(message) {
|
|
266
|
+
const pending = pendingConversationHistoryAcks.get(message.requestId);
|
|
267
|
+
if (!pending)
|
|
268
|
+
return;
|
|
269
|
+
clearTimeout(pending.timer);
|
|
270
|
+
pendingConversationHistoryAcks.delete(message.requestId);
|
|
271
|
+
pending.resolve({
|
|
272
|
+
ok: message.ok,
|
|
273
|
+
reason: message.reason,
|
|
274
|
+
requestId: message.requestId
|
|
275
|
+
});
|
|
276
|
+
}
|
|
257
277
|
function handlePlayAck(message) {
|
|
258
278
|
const pending = pendingPlayAcks.get(message.requestId);
|
|
259
279
|
if (!pending)
|
|
@@ -341,6 +361,15 @@ function clearPendingRecordingAcksForSession(sessionId, reason) {
|
|
|
341
361
|
pending.resolve({ ok: false, reason, requestId });
|
|
342
362
|
}
|
|
343
363
|
}
|
|
364
|
+
function clearPendingConversationHistoryAcksForSession(sessionId, reason) {
|
|
365
|
+
for (const [requestId, pending] of pendingConversationHistoryAcks) {
|
|
366
|
+
if (pending.sessionId !== sessionId)
|
|
367
|
+
continue;
|
|
368
|
+
clearTimeout(pending.timer);
|
|
369
|
+
pendingConversationHistoryAcks.delete(requestId);
|
|
370
|
+
pending.resolve({ ok: false, reason, requestId });
|
|
371
|
+
}
|
|
372
|
+
}
|
|
344
373
|
var sessionExecutionContext = new AsyncLocalStorage();
|
|
345
374
|
var agentLogSessionContext = new AsyncLocalStorage();
|
|
346
375
|
var inboundQueueAuthority = null;
|
|
@@ -487,6 +516,7 @@ async function handleParentMessage(message, handlers) {
|
|
|
487
516
|
endedSessionIds.delete(message.sessionId);
|
|
488
517
|
peerEnvBySessionId.set(message.sessionId, message.env);
|
|
489
518
|
recordingAvailableBySessionId.set(message.sessionId, message.recordingAvailable ?? false);
|
|
519
|
+
conversationHistoryAvailableBySessionId.set(message.sessionId, message.conversationHistoryAvailable ?? false);
|
|
490
520
|
mixAvailableBySessionId.set(message.sessionId, message.mixAvailable ?? false);
|
|
491
521
|
ttsPoseAvailableBySessionId.set(message.sessionId, message.ttsPoseAvailable ?? false);
|
|
492
522
|
const sessionStartInitDelayMs = resolveSessionStartInitDelayMs();
|
|
@@ -497,6 +527,7 @@ async function handleParentMessage(message, handlers) {
|
|
|
497
527
|
sessionId: message.sessionId,
|
|
498
528
|
env: message.env,
|
|
499
529
|
recordingAvailable: message.recordingAvailable ?? false,
|
|
530
|
+
conversationHistoryAvailable: message.conversationHistoryAvailable ?? false,
|
|
500
531
|
mixAvailable: message.mixAvailable ?? false,
|
|
501
532
|
ttsPoseAvailable: message.ttsPoseAvailable ?? false
|
|
502
533
|
});
|
|
@@ -543,8 +574,10 @@ async function handleParentMessage(message, handlers) {
|
|
|
543
574
|
break;
|
|
544
575
|
case "session_end":
|
|
545
576
|
clearPendingRecordingAcksForSession(message.sessionId, "session_ended");
|
|
577
|
+
clearPendingConversationHistoryAcksForSession(message.sessionId, "session_ended");
|
|
546
578
|
peerEnvBySessionId.delete(message.sessionId);
|
|
547
579
|
recordingAvailableBySessionId.delete(message.sessionId);
|
|
580
|
+
conversationHistoryAvailableBySessionId.delete(message.sessionId);
|
|
548
581
|
mixAvailableBySessionId.delete(message.sessionId);
|
|
549
582
|
ttsPoseAvailableBySessionId.delete(message.sessionId);
|
|
550
583
|
await (handlers.onClientLeave ?? handlers.onSessionEnd)?.({
|
|
@@ -566,6 +599,10 @@ function defineAgent(handlers) {
|
|
|
566
599
|
handleRecordingControlAck(message);
|
|
567
600
|
return;
|
|
568
601
|
}
|
|
602
|
+
if (isConversationHistoryControlAckMessage(message)) {
|
|
603
|
+
handleConversationHistoryControlAck(message);
|
|
604
|
+
return;
|
|
605
|
+
}
|
|
569
606
|
if (isPlayAckMessage(message)) {
|
|
570
607
|
handlePlayAck(message);
|
|
571
608
|
return;
|
|
@@ -599,6 +636,7 @@ function defineAgent(handlers) {
|
|
|
599
636
|
if (message.type === "session_end") {
|
|
600
637
|
endedSessionIds.add(message.sessionId);
|
|
601
638
|
clearPendingRecordingAcksForSession(message.sessionId, "session_ended");
|
|
639
|
+
clearPendingConversationHistoryAcksForSession(message.sessionId, "session_ended");
|
|
602
640
|
inboundBySession.clear(message.sessionId);
|
|
603
641
|
}
|
|
604
642
|
if (message.type === "session_start") {
|