@voicethere/agent 0.7.13 → 0.8.1
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 +14 -3
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/dist/runtime.d.ts +10 -0
- package/dist/runtime.d.ts.map +1 -1
- package/dist/runtime.js +28 -2
- package/dist/runtime.js.map +1 -1
- package/dist/templates/echo/agent.js +16 -5
- package/dist/templates/echo-dc/agent.js +1 -1
- package/dist/templates/game-sync/agent.js +162 -125
- package/dist/templates/recording-consent/agent.js +12 -12
- package/dist/templates/registry.d.ts +1 -1
- package/dist/templates/registry.d.ts.map +1 -1
- package/dist/templates/registry.js +42 -26
- package/dist/templates/registry.js.map +1 -1
- package/dist/templates/voice-showcase/agent.js +64 -25
- package/dist/templates/voice-starter/agent.js +1 -1
- package/dist/templates/webhooks/agent.js +2 -2
- package/dist/templates/webhooks-redis/agent.js +11 -4
- package/dist/templates/world-sync/agent.js +829 -0
- package/dist/templates/world-sync-binary/agent.js +1031 -0
- package/package.json +3 -2
- package/templates/README.md +41 -69
- package/templates/crash/README.md +13 -0
- package/templates/echo/README.md +13 -0
- package/templates/{echo.ts → echo/agent.ts} +4 -6
- package/templates/echo-dc/README.md +13 -0
- package/templates/{echo-dc.ts → echo-dc/agent.ts} +1 -1
- package/templates/echo-smoke/README.md +13 -0
- package/templates/game-sync/README.md +21 -0
- package/templates/{game-sync.ts → game-sync/agent.ts} +126 -94
- package/templates/{game-sync-redis.ts → game-sync/redis.ts} +4 -13
- package/templates/{game-sync-sim.ts → game-sync/sim.ts} +14 -7
- package/templates/{game-sync-world-layout.ts → game-sync/world-layout.ts} +72 -30
- package/templates/game-sync-smoke/README.md +13 -0
- package/templates/mix-smoke/README.md +13 -0
- package/templates/positional-tts/README.md +13 -0
- package/templates/recording-consent/README.md +13 -0
- package/templates/redis-sync/README.md +23 -0
- package/templates/redis-sync/agent.ts +72 -95
- package/templates/redis-sync/world-layout.ts +103 -26
- package/templates/spatial-showcase/README.md +13 -0
- package/templates/voice-showcase/README.md +13 -0
- package/templates/voice-showcase/agent.ts +3 -1
- package/templates/voice-showcase/conversation.ts +9 -5
- package/templates/voice-showcase/delivery.ts +40 -10
- package/templates/voice-starter/README.md +13 -0
- package/templates/webhooks/README.md +13 -0
- package/templates/{webhooks.ts → webhooks/agent.ts} +1 -1
- package/templates/webhooks-redis/README.md +13 -0
- package/templates/{webhooks-redis.ts → webhooks-redis/agent.ts} +9 -9
- package/templates/world-sync/README.md +20 -0
- package/templates/world-sync/agent.ts +62 -0
- package/templates/world-sync-binary/README.md +21 -0
- package/templates/world-sync-binary/agent.ts +107 -0
- package/templates/world-sync-binary/protocol.ts +281 -0
- /package/templates/{crash.ts → crash/agent.ts} +0 -0
- /package/templates/{echo-smoke.ts → echo-smoke/agent.ts} +0 -0
- /package/templates/{game-sync-protocol.ts → game-sync/protocol.ts} +0 -0
- /package/templates/{game-sync-smoke.ts → game-sync-smoke/agent.ts} +0 -0
- /package/templates/{mix-smoke.ts → mix-smoke/agent.ts} +0 -0
- /package/templates/{agent.ts → voice-starter/agent.ts} +0 -0
|
@@ -1,40 +1,56 @@
|
|
|
1
1
|
export const AGENT_TEMPLATES = [
|
|
2
2
|
{
|
|
3
3
|
id: "echo",
|
|
4
|
-
entry: "echo.ts",
|
|
4
|
+
entry: "echo/agent.ts",
|
|
5
5
|
kind: "product",
|
|
6
6
|
seedOnCreate: true,
|
|
7
7
|
description: "Full echo debug agent — voice finals and DataChannel chat with TTS playback.",
|
|
8
|
-
sourceFiles: ["echo.ts"],
|
|
8
|
+
sourceFiles: ["echo/agent.ts"],
|
|
9
9
|
},
|
|
10
10
|
{
|
|
11
11
|
id: "echo-dc",
|
|
12
|
-
entry: "echo-dc.ts",
|
|
12
|
+
entry: "echo-dc/agent.ts",
|
|
13
13
|
kind: "product",
|
|
14
14
|
seedOnCreate: true,
|
|
15
15
|
description: "Data-channel-only echo — relays speech events and chat without TTS.",
|
|
16
|
-
sourceFiles: ["echo-dc.ts"],
|
|
16
|
+
sourceFiles: ["echo-dc/agent.ts"],
|
|
17
17
|
},
|
|
18
18
|
{
|
|
19
19
|
id: "voice-starter",
|
|
20
|
-
entry: "agent.ts",
|
|
20
|
+
entry: "voice-starter/agent.ts",
|
|
21
21
|
kind: "product",
|
|
22
22
|
seedOnCreate: true,
|
|
23
23
|
description: "Voice starter covering every speech event — customize onUserSpeechFinal for your LLM.",
|
|
24
|
-
sourceFiles: ["agent.ts"],
|
|
24
|
+
sourceFiles: ["voice-starter/agent.ts"],
|
|
25
|
+
},
|
|
26
|
+
{
|
|
27
|
+
id: "world-sync",
|
|
28
|
+
entry: "world-sync/agent.ts",
|
|
29
|
+
kind: "product",
|
|
30
|
+
seedOnCreate: true,
|
|
31
|
+
description: "Single-agent JSON world sync — onDataChannelMessage pose updates, in-memory, no Redis.",
|
|
32
|
+
sourceFiles: ["world-sync/agent.ts"],
|
|
33
|
+
},
|
|
34
|
+
{
|
|
35
|
+
id: "world-sync-binary",
|
|
36
|
+
entry: "world-sync-binary/agent.ts",
|
|
37
|
+
kind: "product",
|
|
38
|
+
seedOnCreate: true,
|
|
39
|
+
description: "Single-agent binary world sync — onDataChannelBinary + sendBinaryToClient ArrayBuffer poses, no Redis.",
|
|
40
|
+
sourceFiles: ["world-sync-binary/agent.ts", "world-sync-binary/protocol.ts"],
|
|
25
41
|
},
|
|
26
42
|
{
|
|
27
43
|
id: "game-sync",
|
|
28
|
-
entry: "game-sync.ts",
|
|
44
|
+
entry: "game-sync/agent.ts",
|
|
29
45
|
kind: "product",
|
|
30
46
|
seedOnCreate: true,
|
|
31
|
-
description: "Authoritative multi-object sync
|
|
47
|
+
description: "Authoritative multi-object sync with binary world snapshots; uses Redis when AGENT_REDIS_URL is set.",
|
|
32
48
|
sourceFiles: [
|
|
33
|
-
"game-sync.ts",
|
|
34
|
-
"game-sync
|
|
35
|
-
"game-sync
|
|
36
|
-
"game-sync
|
|
37
|
-
"game-sync
|
|
49
|
+
"game-sync/agent.ts",
|
|
50
|
+
"game-sync/protocol.ts",
|
|
51
|
+
"game-sync/world-layout.ts",
|
|
52
|
+
"game-sync/sim.ts",
|
|
53
|
+
"game-sync/redis.ts",
|
|
38
54
|
],
|
|
39
55
|
npmDependencies: { ioredis: "^5.11.1" },
|
|
40
56
|
},
|
|
@@ -90,61 +106,61 @@ export const AGENT_TEMPLATES = [
|
|
|
90
106
|
},
|
|
91
107
|
{
|
|
92
108
|
id: "webhooks",
|
|
93
|
-
entry: "webhooks.ts",
|
|
109
|
+
entry: "webhooks/agent.ts",
|
|
94
110
|
kind: "product",
|
|
95
111
|
seedOnCreate: true,
|
|
96
112
|
description: "Inbound webhook handler — HMAC verify on raw body, then DataChannel + speak fan-out.",
|
|
97
|
-
sourceFiles: ["webhooks.ts"],
|
|
113
|
+
sourceFiles: ["webhooks/agent.ts"],
|
|
98
114
|
},
|
|
99
115
|
{
|
|
100
116
|
id: "webhooks-redis",
|
|
101
|
-
entry: "webhooks-redis.ts",
|
|
117
|
+
entry: "webhooks-redis/agent.ts",
|
|
102
118
|
kind: "product",
|
|
103
119
|
seedOnCreate: true,
|
|
104
120
|
description: "Webhook handler with Redis atomic shared counter plus DataChannel fan-out.",
|
|
105
|
-
sourceFiles: ["webhooks-redis.ts"],
|
|
121
|
+
sourceFiles: ["webhooks-redis/agent.ts"],
|
|
106
122
|
npmDependencies: { ioredis: "^5.11.1" },
|
|
107
123
|
},
|
|
108
124
|
{
|
|
109
125
|
id: "echo-smoke",
|
|
110
|
-
entry: "echo-smoke.ts",
|
|
126
|
+
entry: "echo-smoke/agent.ts",
|
|
111
127
|
kind: "e2e",
|
|
112
128
|
seedOnCreate: false,
|
|
113
129
|
description: "Minimal echo agent for e2e voice-smoke, agent-smoke, and cli-smoke uploads.",
|
|
114
|
-
sourceFiles: ["echo-smoke.ts"],
|
|
130
|
+
sourceFiles: ["echo-smoke/agent.ts"],
|
|
115
131
|
},
|
|
116
132
|
{
|
|
117
133
|
id: "crash",
|
|
118
|
-
entry: "crash.ts",
|
|
134
|
+
entry: "crash/agent.ts",
|
|
119
135
|
kind: "e2e",
|
|
120
136
|
seedOnCreate: false,
|
|
121
137
|
description: "Crash / echo agent for session-errors-smoke and agent-crash-policy smokes.",
|
|
122
|
-
sourceFiles: ["crash.ts"],
|
|
138
|
+
sourceFiles: ["crash/agent.ts"],
|
|
123
139
|
},
|
|
124
140
|
{
|
|
125
141
|
id: "game-sync-smoke",
|
|
126
|
-
entry: "game-sync-smoke.ts",
|
|
142
|
+
entry: "game-sync-smoke/agent.ts",
|
|
127
143
|
kind: "e2e",
|
|
128
144
|
seedOnCreate: false,
|
|
129
145
|
description: "Minimal data-channel agent for deploy-smoke, shared-child, and idle smokes.",
|
|
130
|
-
sourceFiles: ["game-sync-smoke.ts"],
|
|
146
|
+
sourceFiles: ["game-sync-smoke/agent.ts"],
|
|
131
147
|
},
|
|
132
148
|
{
|
|
133
149
|
id: "redis-sync",
|
|
134
150
|
entry: "redis-sync/agent.ts",
|
|
135
151
|
kind: "e2e",
|
|
136
152
|
seedOnCreate: false,
|
|
137
|
-
description: "Redis-backed world buffer sync for redis-sync-smoke
|
|
153
|
+
description: "Redis-backed world buffer sync for redis-sync-smoke — binary 12-byte position frames + project Redis.",
|
|
138
154
|
sourceFiles: ["redis-sync/agent.ts", "redis-sync/world-layout.ts"],
|
|
139
155
|
npmDependencies: { ioredis: "^5.11.1" },
|
|
140
156
|
},
|
|
141
157
|
{
|
|
142
158
|
id: "mix-smoke",
|
|
143
|
-
entry: "mix-smoke.ts",
|
|
159
|
+
entry: "mix-smoke/agent.ts",
|
|
144
160
|
kind: "e2e",
|
|
145
161
|
seedOnCreate: false,
|
|
146
162
|
description: "Positional mix DC commands for voice-data-mix-smoke (Voice+Data, shared child).",
|
|
147
|
-
sourceFiles: ["mix-smoke.ts"],
|
|
163
|
+
sourceFiles: ["mix-smoke/agent.ts"],
|
|
148
164
|
},
|
|
149
165
|
];
|
|
150
166
|
const TEMPLATE_BY_ID = new Map(AGENT_TEMPLATES.map((template) => [template.id, template]));
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"registry.js","sourceRoot":"","sources":["../../src/templates/registry.ts"],"names":[],"mappings":"AAgBA,MAAM,CAAC,MAAM,eAAe,GAAuC;IACjE;QACE,EAAE,EAAE,MAAM;QACV,KAAK,EAAE,
|
|
1
|
+
{"version":3,"file":"registry.js","sourceRoot":"","sources":["../../src/templates/registry.ts"],"names":[],"mappings":"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"}
|
|
@@ -723,6 +723,19 @@ function buildIdleEnv(sessionId) {
|
|
|
723
723
|
function speak(sessionId, text) {
|
|
724
724
|
sendParentMessage({ type: "speak", sessionId, text });
|
|
725
725
|
}
|
|
726
|
+
function speakAndChat(sessionId, text, options) {
|
|
727
|
+
const trimmed = text.trim();
|
|
728
|
+
if (!trimmed) {
|
|
729
|
+
return;
|
|
730
|
+
}
|
|
731
|
+
const payload = { type: "chat_reply", text: trimmed };
|
|
732
|
+
if (options?.stream) {
|
|
733
|
+
payload.stream = true;
|
|
734
|
+
payload.utteranceId = options.utteranceId ?? randomUUID();
|
|
735
|
+
}
|
|
736
|
+
sendToClient(sessionId, payload);
|
|
737
|
+
speak(sessionId, trimmed);
|
|
738
|
+
}
|
|
726
739
|
function sendToClient(sessionId, payload) {
|
|
727
740
|
sendParentMessage({ type: "send_to_client", sessionId, payload });
|
|
728
741
|
}
|
|
@@ -791,6 +804,9 @@ function parseChatText(message) {
|
|
|
791
804
|
return trimmed.length > 0 ? trimmed : null;
|
|
792
805
|
}
|
|
793
806
|
|
|
807
|
+
// templates/voice-showcase/conversation.ts
|
|
808
|
+
import { randomUUID as randomUUID2 } from "node:crypto";
|
|
809
|
+
|
|
794
810
|
// templates/voice-showcase/recipes.ts
|
|
795
811
|
var RECIPES = [
|
|
796
812
|
{
|
|
@@ -1134,10 +1150,11 @@ function buildMenuMessages() {
|
|
|
1134
1150
|
}
|
|
1135
1151
|
];
|
|
1136
1152
|
}
|
|
1137
|
-
function
|
|
1153
|
+
function speakAndChat2(text) {
|
|
1154
|
+
const utteranceId = randomUUID2();
|
|
1138
1155
|
return {
|
|
1139
1156
|
speakLines: [text],
|
|
1140
|
-
messages: [{ type: "chat_reply", text }]
|
|
1157
|
+
messages: [{ type: "chat_reply", text, stream: true, utteranceId }]
|
|
1141
1158
|
};
|
|
1142
1159
|
}
|
|
1143
1160
|
function isHumanEscalation(utterance) {
|
|
@@ -1214,15 +1231,15 @@ function transitionAfterName(state, name, declined) {
|
|
|
1214
1231
|
const lines = [];
|
|
1215
1232
|
const messages = [];
|
|
1216
1233
|
if (declined) {
|
|
1217
|
-
const decline =
|
|
1234
|
+
const decline = speakAndChat2(NAME_DECLINE_REPLY);
|
|
1218
1235
|
lines.push(...decline.speakLines);
|
|
1219
1236
|
messages.push(...decline.messages);
|
|
1220
1237
|
} else if (name) {
|
|
1221
|
-
const thanks =
|
|
1238
|
+
const thanks = speakAndChat2(`Great, thank you ${name}`);
|
|
1222
1239
|
lines.push(...thanks.speakLines);
|
|
1223
1240
|
messages.push(...thanks.messages);
|
|
1224
1241
|
}
|
|
1225
|
-
const hello =
|
|
1242
|
+
const hello = speakAndChat2(helloAfterName(next));
|
|
1226
1243
|
lines.push(...hello.speakLines);
|
|
1227
1244
|
messages.push(...hello.messages);
|
|
1228
1245
|
messages.push(...buildMenuMessages());
|
|
@@ -1281,7 +1298,7 @@ function formatCountingSpeech(n) {
|
|
|
1281
1298
|
return parts.join(", ");
|
|
1282
1299
|
}
|
|
1283
1300
|
function resendMenu(state) {
|
|
1284
|
-
const menu =
|
|
1301
|
+
const menu = speakAndChat2("Here is the menu again.");
|
|
1285
1302
|
return {
|
|
1286
1303
|
state: { ...state, phase: "awaitingMenuChoice" },
|
|
1287
1304
|
speakLines: menu.speakLines,
|
|
@@ -1289,7 +1306,7 @@ function resendMenu(state) {
|
|
|
1289
1306
|
};
|
|
1290
1307
|
}
|
|
1291
1308
|
function returnToMenu(state, line) {
|
|
1292
|
-
const spoken =
|
|
1309
|
+
const spoken = speakAndChat2(line);
|
|
1293
1310
|
return {
|
|
1294
1311
|
state: {
|
|
1295
1312
|
...state,
|
|
@@ -1309,7 +1326,7 @@ function handleUtterance(state, utterance) {
|
|
|
1309
1326
|
return { state, speakLines: [], messages: [] };
|
|
1310
1327
|
}
|
|
1311
1328
|
if (isHumanEscalation(text)) {
|
|
1312
|
-
const reply =
|
|
1329
|
+
const reply = speakAndChat2(HUMAN_ESCALATION_REPLY);
|
|
1313
1330
|
return {
|
|
1314
1331
|
state,
|
|
1315
1332
|
speakLines: reply.speakLines,
|
|
@@ -1338,7 +1355,7 @@ function handleUtterance(state, utterance) {
|
|
|
1338
1355
|
const choice = parseMenuChoice(text);
|
|
1339
1356
|
if (choice === "menu") return resendMenu(state);
|
|
1340
1357
|
if (choice === "weather") {
|
|
1341
|
-
const ask =
|
|
1358
|
+
const ask = speakAndChat2(
|
|
1342
1359
|
"Sure. Please tell me a city or ZIP code and the country."
|
|
1343
1360
|
);
|
|
1344
1361
|
return {
|
|
@@ -1354,7 +1371,7 @@ function handleUtterance(state, utterance) {
|
|
|
1354
1371
|
};
|
|
1355
1372
|
}
|
|
1356
1373
|
if (choice === "count") {
|
|
1357
|
-
const ask =
|
|
1374
|
+
const ask = speakAndChat2(
|
|
1358
1375
|
"Pick a number from 1 to 10 and I will count up to it."
|
|
1359
1376
|
);
|
|
1360
1377
|
return {
|
|
@@ -1368,7 +1385,7 @@ function handleUtterance(state, utterance) {
|
|
|
1368
1385
|
};
|
|
1369
1386
|
}
|
|
1370
1387
|
if (choice === "recipe") {
|
|
1371
|
-
const ask =
|
|
1388
|
+
const ask = speakAndChat2(
|
|
1372
1389
|
"What do you fancy? Try pasta, soup, breakfast, cookies, or salad."
|
|
1373
1390
|
);
|
|
1374
1391
|
return {
|
|
@@ -1381,7 +1398,7 @@ function handleUtterance(state, utterance) {
|
|
|
1381
1398
|
const fact = pickFunFact();
|
|
1382
1399
|
return returnToMenu(state, `Here is a fun fact. ${fact}`);
|
|
1383
1400
|
}
|
|
1384
|
-
const retry =
|
|
1401
|
+
const retry = speakAndChat2(
|
|
1385
1402
|
"I did not catch that. Pick 1 through 4 from the menu, or say weather, count, recipe, or fun fact."
|
|
1386
1403
|
);
|
|
1387
1404
|
return {
|
|
@@ -1402,7 +1419,7 @@ function handleUtterance(state, utterance) {
|
|
|
1402
1419
|
}
|
|
1403
1420
|
}
|
|
1404
1421
|
if (!city) {
|
|
1405
|
-
const ask =
|
|
1422
|
+
const ask = speakAndChat2(
|
|
1406
1423
|
"Please tell me a city or ZIP code and the country."
|
|
1407
1424
|
);
|
|
1408
1425
|
return {
|
|
@@ -1412,16 +1429,15 @@ function handleUtterance(state, utterance) {
|
|
|
1412
1429
|
};
|
|
1413
1430
|
}
|
|
1414
1431
|
if (!country) {
|
|
1432
|
+
const ask = speakAndChat2("Got it. Which country is that in?");
|
|
1415
1433
|
return {
|
|
1416
1434
|
state: {
|
|
1417
1435
|
...state,
|
|
1418
1436
|
phase: "weatherAwaitingLocation",
|
|
1419
1437
|
weatherCity: city
|
|
1420
1438
|
},
|
|
1421
|
-
speakLines:
|
|
1422
|
-
messages:
|
|
1423
|
-
{ type: "chat_reply", text: "Got it. Which country is that in?" }
|
|
1424
|
-
]
|
|
1439
|
+
speakLines: ask.speakLines,
|
|
1440
|
+
messages: ask.messages
|
|
1425
1441
|
};
|
|
1426
1442
|
}
|
|
1427
1443
|
return {
|
|
@@ -1438,7 +1454,7 @@ function handleUtterance(state, utterance) {
|
|
|
1438
1454
|
if (failures >= 2) {
|
|
1439
1455
|
return returnToMenu(state, "Sorry, I cannot do this.");
|
|
1440
1456
|
}
|
|
1441
|
-
const retry =
|
|
1457
|
+
const retry = speakAndChat2(
|
|
1442
1458
|
"I did not understand you. Please say a number from 1 to 10."
|
|
1443
1459
|
);
|
|
1444
1460
|
return {
|
|
@@ -1471,7 +1487,7 @@ function applyWeatherFailure(state) {
|
|
|
1471
1487
|
"Sorry, I could not look up the weather right now."
|
|
1472
1488
|
);
|
|
1473
1489
|
}
|
|
1474
|
-
const retry =
|
|
1490
|
+
const retry = speakAndChat2(
|
|
1475
1491
|
"I could not find that location. Please try again with a city or ZIP and country."
|
|
1476
1492
|
);
|
|
1477
1493
|
return {
|
|
@@ -1499,6 +1515,7 @@ async function resolveWeatherTurn(state, city, country, fetchFn) {
|
|
|
1499
1515
|
}
|
|
1500
1516
|
|
|
1501
1517
|
// templates/voice-showcase/delivery.ts
|
|
1518
|
+
import { randomUUID as randomUUID3 } from "node:crypto";
|
|
1502
1519
|
function spokenThenPlayOps(messages, speakLines) {
|
|
1503
1520
|
const ops = [];
|
|
1504
1521
|
for (const message of messages) {
|
|
@@ -1510,21 +1527,42 @@ function spokenThenPlayOps(messages, speakLines) {
|
|
|
1510
1527
|
return ops;
|
|
1511
1528
|
}
|
|
1512
1529
|
function greetingOps(sessionId, greeting) {
|
|
1530
|
+
const utteranceId = randomUUID3();
|
|
1513
1531
|
return spokenThenPlayOps(
|
|
1514
1532
|
[
|
|
1515
1533
|
{ type: "agent_event", event: "session_start", sessionId },
|
|
1516
|
-
{
|
|
1534
|
+
{
|
|
1535
|
+
type: "chat_reply",
|
|
1536
|
+
text: greeting,
|
|
1537
|
+
stream: true,
|
|
1538
|
+
utteranceId
|
|
1539
|
+
}
|
|
1517
1540
|
],
|
|
1518
1541
|
[greeting]
|
|
1519
1542
|
);
|
|
1520
1543
|
}
|
|
1521
1544
|
function applyOutboundOps(sessionId, ops, deps) {
|
|
1545
|
+
const spokenViaSpeakAndChat = /* @__PURE__ */ new Set();
|
|
1522
1546
|
for (const op of ops) {
|
|
1523
1547
|
if (op.kind === "send") {
|
|
1524
|
-
|
|
1525
|
-
|
|
1526
|
-
|
|
1548
|
+
const message = op.message;
|
|
1549
|
+
if (message.type === "chat_reply" && message.stream === true && message.text?.trim()) {
|
|
1550
|
+
const text = message.text.trim();
|
|
1551
|
+
deps.speakAndChat(sessionId, text, {
|
|
1552
|
+
stream: true,
|
|
1553
|
+
utteranceId: message.utteranceId
|
|
1554
|
+
});
|
|
1555
|
+
spokenViaSpeakAndChat.add(text);
|
|
1556
|
+
} else {
|
|
1557
|
+
deps.sendToClient(sessionId, message);
|
|
1558
|
+
}
|
|
1559
|
+
continue;
|
|
1560
|
+
}
|
|
1561
|
+
const playText = op.text.trim();
|
|
1562
|
+
if (spokenViaSpeakAndChat.has(playText)) {
|
|
1563
|
+
continue;
|
|
1527
1564
|
}
|
|
1565
|
+
deps.speak(sessionId, op.text);
|
|
1528
1566
|
}
|
|
1529
1567
|
}
|
|
1530
1568
|
|
|
@@ -1550,7 +1588,7 @@ function deliverSpokenThenPlay(sessionId, result) {
|
|
|
1550
1588
|
applyOutboundOps(
|
|
1551
1589
|
sessionId,
|
|
1552
1590
|
spokenThenPlayOps(result.messages, result.speakLines),
|
|
1553
|
-
{ sendToClient, speak }
|
|
1591
|
+
{ sendToClient, speak, speakAndChat }
|
|
1554
1592
|
);
|
|
1555
1593
|
}
|
|
1556
1594
|
async function applyTurn(sessionId, result) {
|
|
@@ -1576,7 +1614,8 @@ defineAgent({
|
|
|
1576
1614
|
sessions.set(sessionId, createInitialState());
|
|
1577
1615
|
applyOutboundOps(sessionId, greetingOps(sessionId, GREETING), {
|
|
1578
1616
|
sendToClient,
|
|
1579
|
-
speak
|
|
1617
|
+
speak,
|
|
1618
|
+
speakAndChat
|
|
1580
1619
|
});
|
|
1581
1620
|
agentLog("info", `voice-showcase session_start ${sessionId}`);
|
|
1582
1621
|
},
|
|
@@ -779,7 +779,7 @@ function agentLog(level, message, fieldsOrSessionId, sessionId) {
|
|
|
779
779
|
sendParentMessage(buildAgentLogPayload(level, message, fields, resolvedSessionId));
|
|
780
780
|
}
|
|
781
781
|
|
|
782
|
-
// templates/agent.ts
|
|
782
|
+
// templates/voice-starter/agent.ts
|
|
783
783
|
var peers = /* @__PURE__ */ new Map();
|
|
784
784
|
function peerState(sessionId) {
|
|
785
785
|
let state = peers.get(sessionId);
|
|
@@ -2,7 +2,7 @@ import { createRequire } from "node:module";
|
|
|
2
2
|
const require = createRequire(import.meta.url);
|
|
3
3
|
|
|
4
4
|
|
|
5
|
-
// templates/webhooks.ts
|
|
5
|
+
// templates/webhooks/agent.ts
|
|
6
6
|
import { createHmac, timingSafeEqual } from "node:crypto";
|
|
7
7
|
|
|
8
8
|
// dist/runtime.js
|
|
@@ -790,7 +790,7 @@ function agentLog(level, message, fieldsOrSessionId, sessionId) {
|
|
|
790
790
|
sendParentMessage(buildAgentLogPayload(level, message, fields, resolvedSessionId));
|
|
791
791
|
}
|
|
792
792
|
|
|
793
|
-
// templates/webhooks.ts
|
|
793
|
+
// templates/webhooks/agent.ts
|
|
794
794
|
var WEBHOOK_SIGNATURE_HEADER = "x-agent-webhook-signature";
|
|
795
795
|
var connectedSessions = /* @__PURE__ */ new Set();
|
|
796
796
|
function getHeaderCaseInsensitive(headers, name) {
|
|
@@ -10753,7 +10753,7 @@ var require_built3 = __commonJS({
|
|
|
10753
10753
|
}
|
|
10754
10754
|
});
|
|
10755
10755
|
|
|
10756
|
-
// templates/webhooks-redis.ts
|
|
10756
|
+
// templates/webhooks-redis/agent.ts
|
|
10757
10757
|
var import_ioredis = __toESM(require_built3(), 1);
|
|
10758
10758
|
import { createHmac, timingSafeEqual } from "node:crypto";
|
|
10759
10759
|
|
|
@@ -11539,7 +11539,7 @@ function agentLog(level, message, fieldsOrSessionId, sessionId) {
|
|
|
11539
11539
|
sendParentMessage(buildAgentLogPayload(level, message, fields, resolvedSessionId));
|
|
11540
11540
|
}
|
|
11541
11541
|
|
|
11542
|
-
// templates/webhooks-redis.ts
|
|
11542
|
+
// templates/webhooks-redis/agent.ts
|
|
11543
11543
|
var WEBHOOK_SIGNATURE_HEADER = "x-agent-webhook-signature";
|
|
11544
11544
|
var REDIS_COUNTER_KEY = "agent:webhook:event_count";
|
|
11545
11545
|
var LUA_INCREMENT_COUNTER = `
|
|
@@ -11582,7 +11582,7 @@ defineAgent({
|
|
|
11582
11582
|
);
|
|
11583
11583
|
return;
|
|
11584
11584
|
}
|
|
11585
|
-
redis = new import_ioredis.
|
|
11585
|
+
redis = new import_ioredis.Redis(redisUrl, {
|
|
11586
11586
|
maxRetriesPerRequest: 3,
|
|
11587
11587
|
lazyConnect: true
|
|
11588
11588
|
});
|
|
@@ -11614,7 +11614,11 @@ defineAgent({
|
|
|
11614
11614
|
}
|
|
11615
11615
|
let eventCount = null;
|
|
11616
11616
|
if (redis) {
|
|
11617
|
-
const result = await redis.eval(
|
|
11617
|
+
const result = await redis.eval(
|
|
11618
|
+
LUA_INCREMENT_COUNTER,
|
|
11619
|
+
1,
|
|
11620
|
+
REDIS_COUNTER_KEY
|
|
11621
|
+
);
|
|
11618
11622
|
eventCount = typeof result === "number" ? result : Number(result);
|
|
11619
11623
|
}
|
|
11620
11624
|
const sessionIds = ctx.sessionIds.length > 0 ? ctx.sessionIds : [...connectedSessions];
|
|
@@ -11641,3 +11645,6 @@ defineAgent({
|
|
|
11641
11645
|
);
|
|
11642
11646
|
}
|
|
11643
11647
|
});
|
|
11648
|
+
export {
|
|
11649
|
+
LUA_INCREMENT_COUNTER
|
|
11650
|
+
};
|