@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.
Files changed (64) hide show
  1. package/README.md +14 -3
  2. package/dist/index.d.ts +1 -1
  3. package/dist/index.d.ts.map +1 -1
  4. package/dist/index.js +1 -1
  5. package/dist/index.js.map +1 -1
  6. package/dist/runtime.d.ts +10 -0
  7. package/dist/runtime.d.ts.map +1 -1
  8. package/dist/runtime.js +28 -2
  9. package/dist/runtime.js.map +1 -1
  10. package/dist/templates/echo/agent.js +16 -5
  11. package/dist/templates/echo-dc/agent.js +1 -1
  12. package/dist/templates/game-sync/agent.js +162 -125
  13. package/dist/templates/recording-consent/agent.js +12 -12
  14. package/dist/templates/registry.d.ts +1 -1
  15. package/dist/templates/registry.d.ts.map +1 -1
  16. package/dist/templates/registry.js +42 -26
  17. package/dist/templates/registry.js.map +1 -1
  18. package/dist/templates/voice-showcase/agent.js +64 -25
  19. package/dist/templates/voice-starter/agent.js +1 -1
  20. package/dist/templates/webhooks/agent.js +2 -2
  21. package/dist/templates/webhooks-redis/agent.js +11 -4
  22. package/dist/templates/world-sync/agent.js +829 -0
  23. package/dist/templates/world-sync-binary/agent.js +1031 -0
  24. package/package.json +3 -2
  25. package/templates/README.md +41 -69
  26. package/templates/crash/README.md +13 -0
  27. package/templates/echo/README.md +13 -0
  28. package/templates/{echo.ts → echo/agent.ts} +4 -6
  29. package/templates/echo-dc/README.md +13 -0
  30. package/templates/{echo-dc.ts → echo-dc/agent.ts} +1 -1
  31. package/templates/echo-smoke/README.md +13 -0
  32. package/templates/game-sync/README.md +21 -0
  33. package/templates/{game-sync.ts → game-sync/agent.ts} +126 -94
  34. package/templates/{game-sync-redis.ts → game-sync/redis.ts} +4 -13
  35. package/templates/{game-sync-sim.ts → game-sync/sim.ts} +14 -7
  36. package/templates/{game-sync-world-layout.ts → game-sync/world-layout.ts} +72 -30
  37. package/templates/game-sync-smoke/README.md +13 -0
  38. package/templates/mix-smoke/README.md +13 -0
  39. package/templates/positional-tts/README.md +13 -0
  40. package/templates/recording-consent/README.md +13 -0
  41. package/templates/redis-sync/README.md +23 -0
  42. package/templates/redis-sync/agent.ts +72 -95
  43. package/templates/redis-sync/world-layout.ts +103 -26
  44. package/templates/spatial-showcase/README.md +13 -0
  45. package/templates/voice-showcase/README.md +13 -0
  46. package/templates/voice-showcase/agent.ts +3 -1
  47. package/templates/voice-showcase/conversation.ts +9 -5
  48. package/templates/voice-showcase/delivery.ts +40 -10
  49. package/templates/voice-starter/README.md +13 -0
  50. package/templates/webhooks/README.md +13 -0
  51. package/templates/{webhooks.ts → webhooks/agent.ts} +1 -1
  52. package/templates/webhooks-redis/README.md +13 -0
  53. package/templates/{webhooks-redis.ts → webhooks-redis/agent.ts} +9 -9
  54. package/templates/world-sync/README.md +20 -0
  55. package/templates/world-sync/agent.ts +62 -0
  56. package/templates/world-sync-binary/README.md +21 -0
  57. package/templates/world-sync-binary/agent.ts +107 -0
  58. package/templates/world-sync-binary/protocol.ts +281 -0
  59. /package/templates/{crash.ts → crash/agent.ts} +0 -0
  60. /package/templates/{echo-smoke.ts → echo-smoke/agent.ts} +0 -0
  61. /package/templates/{game-sync-protocol.ts → game-sync/protocol.ts} +0 -0
  62. /package/templates/{game-sync-smoke.ts → game-sync-smoke/agent.ts} +0 -0
  63. /package/templates/{mix-smoke.ts → mix-smoke/agent.ts} +0 -0
  64. /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 sample for real-time games and simulations.",
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-protocol.ts",
35
- "game-sync-world-layout.ts",
36
- "game-sync-sim.ts",
37
- "game-sync-redis.ts",
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 (Advanced tier + project Redis).",
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":"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"}
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 speakAndChat(text) {
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 = speakAndChat(NAME_DECLINE_REPLY);
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 = speakAndChat(`Great, thank you ${name}`);
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 = speakAndChat(helloAfterName(next));
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 = speakAndChat("Here is the menu again.");
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 = speakAndChat(line);
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 = speakAndChat(HUMAN_ESCALATION_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 = speakAndChat(
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 = speakAndChat(
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 = speakAndChat(
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 = speakAndChat(
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 = speakAndChat(
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: ["Got it. Which country is that in?"],
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 = speakAndChat(
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 = speakAndChat(
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
- { type: "chat_reply", text: greeting }
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
- deps.sendToClient(sessionId, op.message);
1525
- } else {
1526
- deps.speak(sessionId, op.text);
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.default(redisUrl, {
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(LUA_INCREMENT_COUNTER, 1, REDIS_COUNTER_KEY);
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
+ };