@openclaw/voice-call 2026.3.13 → 2026.5.2-beta.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 (103) hide show
  1. package/README.md +27 -5
  2. package/api.ts +16 -0
  3. package/cli-metadata.ts +10 -0
  4. package/config-api.ts +12 -0
  5. package/index.test.ts +943 -0
  6. package/index.ts +379 -149
  7. package/openclaw.plugin.json +384 -157
  8. package/package.json +35 -5
  9. package/runtime-api.ts +20 -0
  10. package/runtime-entry.ts +1 -0
  11. package/setup-api.ts +47 -0
  12. package/src/allowlist.test.ts +18 -0
  13. package/src/cli.ts +533 -68
  14. package/src/config-compat.test.ts +120 -0
  15. package/src/config-compat.ts +227 -0
  16. package/src/config.test.ts +273 -12
  17. package/src/config.ts +355 -72
  18. package/src/core-bridge.ts +2 -147
  19. package/src/deep-merge.test.ts +40 -0
  20. package/src/gateway-continue-operation.ts +200 -0
  21. package/src/http-headers.ts +6 -3
  22. package/src/manager/context.ts +6 -5
  23. package/src/manager/events.test.ts +243 -19
  24. package/src/manager/events.ts +61 -31
  25. package/src/manager/lifecycle.ts +53 -0
  26. package/src/manager/lookup.test.ts +52 -0
  27. package/src/manager/outbound.test.ts +528 -0
  28. package/src/manager/outbound.ts +163 -57
  29. package/src/manager/store.ts +18 -6
  30. package/src/manager/timers.test.ts +129 -0
  31. package/src/manager/timers.ts +4 -3
  32. package/src/manager/twiml.test.ts +13 -0
  33. package/src/manager/twiml.ts +8 -0
  34. package/src/manager.closed-loop.test.ts +30 -12
  35. package/src/manager.inbound-allowlist.test.ts +77 -10
  36. package/src/manager.notify.test.ts +344 -20
  37. package/src/manager.restore.test.ts +95 -8
  38. package/src/manager.test-harness.ts +8 -6
  39. package/src/manager.ts +79 -5
  40. package/src/media-stream.test.ts +578 -81
  41. package/src/media-stream.ts +235 -54
  42. package/src/providers/base.ts +19 -0
  43. package/src/providers/mock.ts +7 -1
  44. package/src/providers/plivo.test.ts +50 -6
  45. package/src/providers/plivo.ts +14 -6
  46. package/src/providers/shared/call-status.ts +2 -1
  47. package/src/providers/shared/guarded-json-api.test.ts +106 -0
  48. package/src/providers/shared/guarded-json-api.ts +1 -1
  49. package/src/providers/telnyx.test.ts +178 -6
  50. package/src/providers/telnyx.ts +40 -3
  51. package/src/providers/twilio/api.test.ts +145 -0
  52. package/src/providers/twilio/api.ts +67 -16
  53. package/src/providers/twilio/twiml-policy.ts +6 -10
  54. package/src/providers/twilio/webhook.ts +1 -1
  55. package/src/providers/twilio.test.ts +425 -25
  56. package/src/providers/twilio.ts +230 -77
  57. package/src/providers/twilio.types.ts +17 -0
  58. package/src/realtime-defaults.ts +3 -0
  59. package/src/realtime-fast-context.test.ts +88 -0
  60. package/src/realtime-fast-context.ts +165 -0
  61. package/src/realtime-transcription.runtime.ts +4 -0
  62. package/src/realtime-voice.runtime.ts +5 -0
  63. package/src/response-generator.test.ts +321 -0
  64. package/src/response-generator.ts +213 -53
  65. package/src/response-model.test.ts +71 -0
  66. package/src/response-model.ts +23 -0
  67. package/src/runtime.test.ts +429 -0
  68. package/src/runtime.ts +270 -24
  69. package/src/telephony-audio.test.ts +61 -0
  70. package/src/telephony-audio.ts +1 -79
  71. package/src/telephony-tts.test.ts +133 -12
  72. package/src/telephony-tts.ts +155 -2
  73. package/src/test-fixtures.ts +28 -7
  74. package/src/tts-provider-voice.test.ts +34 -0
  75. package/src/tts-provider-voice.ts +21 -0
  76. package/src/tunnel.test.ts +166 -0
  77. package/src/tunnel.ts +1 -1
  78. package/src/types.ts +24 -37
  79. package/src/utils.test.ts +17 -0
  80. package/src/voice-mapping.test.ts +34 -0
  81. package/src/voice-mapping.ts +3 -2
  82. package/src/webhook/realtime-handler.test.ts +598 -0
  83. package/src/webhook/realtime-handler.ts +485 -0
  84. package/src/webhook/stale-call-reaper.test.ts +88 -0
  85. package/src/webhook/stale-call-reaper.ts +5 -0
  86. package/src/webhook/tailscale.test.ts +214 -0
  87. package/src/webhook/tailscale.ts +19 -5
  88. package/src/webhook-exposure.test.ts +33 -0
  89. package/src/webhook-exposure.ts +84 -0
  90. package/src/webhook-security.test.ts +172 -21
  91. package/src/webhook-security.ts +43 -29
  92. package/src/webhook.hangup-once.lifecycle.test.ts +135 -0
  93. package/src/webhook.test.ts +1145 -27
  94. package/src/webhook.ts +523 -102
  95. package/src/webhook.types.ts +5 -0
  96. package/src/websocket-test-support.ts +72 -0
  97. package/tsconfig.json +16 -0
  98. package/CHANGELOG.md +0 -121
  99. package/src/providers/index.ts +0 -10
  100. package/src/providers/stt-openai-realtime.test.ts +0 -42
  101. package/src/providers/stt-openai-realtime.ts +0 -311
  102. package/src/providers/tts-openai.test.ts +0 -43
  103. package/src/providers/tts-openai.ts +0 -221
@@ -1,5 +1,27 @@
1
1
  {
2
2
  "id": "voice-call",
3
+ "commandAliases": [{ "name": "voicecall" }],
4
+ "activation": {
5
+ "onStartup": true,
6
+ "onCommands": ["voicecall"]
7
+ },
8
+ "contracts": {
9
+ "tools": ["voice_call"]
10
+ },
11
+ "channelEnvVars": {
12
+ "voice-call": [
13
+ "TELNYX_API_KEY",
14
+ "TELNYX_CONNECTION_ID",
15
+ "TELNYX_PUBLIC_KEY",
16
+ "TWILIO_ACCOUNT_SID",
17
+ "TWILIO_AUTH_TOKEN",
18
+ "TWILIO_FROM_NUMBER",
19
+ "PLIVO_AUTH_ID",
20
+ "PLIVO_AUTH_TOKEN",
21
+ "NGROK_AUTHTOKEN",
22
+ "NGROK_DOMAIN"
23
+ ]
24
+ },
3
25
  "uiHints": {
4
26
  "provider": {
5
27
  "label": "Provider",
@@ -23,6 +45,11 @@
23
45
  "label": "Inbound Greeting",
24
46
  "advanced": true
25
47
  },
48
+ "numbers": {
49
+ "label": "Per-number Routing",
50
+ "help": "Inbound overrides keyed by dialed E.164 number.",
51
+ "advanced": true
52
+ },
26
53
  "telnyx.apiKey": {
27
54
  "label": "Telnyx API Key",
28
55
  "sensitive": true
@@ -86,52 +113,73 @@
86
113
  "label": "Enable Streaming",
87
114
  "advanced": true
88
115
  },
89
- "streaming.openaiApiKey": {
90
- "label": "OpenAI Realtime API Key",
91
- "sensitive": true,
116
+ "streaming.provider": {
117
+ "label": "Streaming Provider",
118
+ "help": "Uses the first registered realtime transcription provider when unset.",
92
119
  "advanced": true
93
120
  },
94
- "streaming.sttModel": {
95
- "label": "Realtime STT Model",
121
+ "streaming.providers": {
122
+ "label": "Streaming Provider Config",
96
123
  "advanced": true
97
124
  },
98
125
  "streaming.streamPath": {
99
126
  "label": "Media Stream Path",
100
127
  "advanced": true
101
128
  },
102
- "tts.provider": {
103
- "label": "TTS Provider Override",
104
- "help": "Deep-merges with messages.tts (Edge is ignored for calls).",
129
+ "realtime.enabled": {
130
+ "label": "Enable Realtime Voice",
105
131
  "advanced": true
106
132
  },
107
- "tts.openai.model": {
108
- "label": "OpenAI TTS Model",
133
+ "realtime.provider": {
134
+ "label": "Realtime Voice Provider",
135
+ "help": "Uses the first registered realtime voice provider when unset.",
109
136
  "advanced": true
110
137
  },
111
- "tts.openai.voice": {
112
- "label": "OpenAI TTS Voice",
138
+ "realtime.streamPath": {
139
+ "label": "Realtime Stream Path",
113
140
  "advanced": true
114
141
  },
115
- "tts.openai.apiKey": {
116
- "label": "OpenAI API Key",
117
- "sensitive": true,
142
+ "realtime.instructions": {
143
+ "label": "Realtime Instructions",
118
144
  "advanced": true
119
145
  },
120
- "tts.elevenlabs.modelId": {
121
- "label": "ElevenLabs Model ID",
146
+ "realtime.toolPolicy": {
147
+ "label": "Realtime Tool Policy",
148
+ "help": "Controls the shared openclaw_agent_consult tool.",
122
149
  "advanced": true
123
150
  },
124
- "tts.elevenlabs.voiceId": {
125
- "label": "ElevenLabs Voice ID",
151
+ "realtime.fastContext.enabled": {
152
+ "label": "Enable Fast Realtime Context",
153
+ "help": "Searches memory/session context before the full consult agent.",
126
154
  "advanced": true
127
155
  },
128
- "tts.elevenlabs.apiKey": {
129
- "label": "ElevenLabs API Key",
130
- "sensitive": true,
156
+ "realtime.fastContext.timeoutMs": {
157
+ "label": "Fast Context Timeout",
158
+ "advanced": true
159
+ },
160
+ "realtime.fastContext.maxResults": {
161
+ "label": "Fast Context Result Limit",
131
162
  "advanced": true
132
163
  },
133
- "tts.elevenlabs.baseUrl": {
134
- "label": "ElevenLabs Base URL",
164
+ "realtime.fastContext.sources": {
165
+ "label": "Fast Context Sources",
166
+ "advanced": true
167
+ },
168
+ "realtime.fastContext.fallbackToConsult": {
169
+ "label": "Fallback To Full Consult",
170
+ "advanced": true
171
+ },
172
+ "realtime.providers": {
173
+ "label": "Realtime Provider Config",
174
+ "advanced": true
175
+ },
176
+ "tts.provider": {
177
+ "label": "TTS Provider Override",
178
+ "help": "Deep-merges with messages.tts (Microsoft is ignored for calls).",
179
+ "advanced": true
180
+ },
181
+ "tts.providers": {
182
+ "label": "TTS Provider Config",
135
183
  "advanced": true
136
184
  },
137
185
  "publicUrl": {
@@ -146,8 +194,13 @@
146
194
  "label": "Call Log Store Path",
147
195
  "advanced": true
148
196
  },
197
+ "sessionScope": {
198
+ "label": "Session Scope",
199
+ "help": "Use per-phone to preserve caller memory across calls, or per-call to isolate every call into a fresh voice session."
200
+ },
149
201
  "responseModel": {
150
202
  "label": "Response Model",
203
+ "help": "Optional override. Falls back to the runtime default model when unset.",
151
204
  "advanced": true
152
205
  },
153
206
  "responseSystemPrompt": {
@@ -193,7 +246,7 @@
193
246
  "type": "string"
194
247
  },
195
248
  "authToken": {
196
- "type": "string"
249
+ "type": ["string", "object"]
197
250
  }
198
251
  }
199
252
  },
@@ -231,6 +284,38 @@
231
284
  "inboundGreeting": {
232
285
  "type": "string"
233
286
  },
287
+ "numbers": {
288
+ "type": "object",
289
+ "propertyNames": {
290
+ "pattern": "^\\+[1-9]\\d{1,14}$"
291
+ },
292
+ "additionalProperties": {
293
+ "type": "object",
294
+ "additionalProperties": false,
295
+ "properties": {
296
+ "inboundGreeting": {
297
+ "type": "string"
298
+ },
299
+ "tts": {
300
+ "$ref": "#/properties/tts"
301
+ },
302
+ "agentId": {
303
+ "type": "string",
304
+ "minLength": 1
305
+ },
306
+ "responseModel": {
307
+ "type": "string"
308
+ },
309
+ "responseSystemPrompt": {
310
+ "type": "string"
311
+ },
312
+ "responseTimeoutMs": {
313
+ "type": "integer",
314
+ "minimum": 1
315
+ }
316
+ }
317
+ }
318
+ },
234
319
  "outbound": {
235
320
  "type": "object",
236
321
  "additionalProperties": false,
@@ -345,28 +430,19 @@
345
430
  "enabled": {
346
431
  "type": "boolean"
347
432
  },
348
- "sttProvider": {
349
- "type": "string",
350
- "enum": ["openai-realtime"]
351
- },
352
- "openaiApiKey": {
353
- "type": "string"
354
- },
355
- "sttModel": {
433
+ "provider": {
356
434
  "type": "string"
357
435
  },
358
- "silenceDurationMs": {
359
- "type": "integer",
360
- "minimum": 1
361
- },
362
- "vadThreshold": {
363
- "type": "number",
364
- "minimum": 0,
365
- "maximum": 1
366
- },
367
436
  "streamPath": {
368
437
  "type": "string"
369
438
  },
439
+ "providers": {
440
+ "type": "object",
441
+ "additionalProperties": {
442
+ "type": "object",
443
+ "additionalProperties": true
444
+ }
445
+ },
370
446
  "preStartTimeoutMs": {
371
447
  "type": "integer",
372
448
  "minimum": 1
@@ -385,25 +461,110 @@
385
461
  }
386
462
  }
387
463
  },
388
- "publicUrl": {
389
- "type": "string"
390
- },
391
- "skipSignatureVerification": {
392
- "type": "boolean"
393
- },
394
- "stt": {
464
+ "realtime": {
395
465
  "type": "object",
396
466
  "additionalProperties": false,
397
467
  "properties": {
468
+ "enabled": {
469
+ "type": "boolean"
470
+ },
398
471
  "provider": {
399
- "type": "string",
400
- "enum": ["openai"]
472
+ "type": "string"
473
+ },
474
+ "streamPath": {
475
+ "type": "string"
401
476
  },
402
- "model": {
477
+ "instructions": {
403
478
  "type": "string"
479
+ },
480
+ "toolPolicy": {
481
+ "type": "string",
482
+ "enum": ["safe-read-only", "owner", "none"]
483
+ },
484
+ "tools": {
485
+ "type": "array",
486
+ "items": {
487
+ "type": "object",
488
+ "additionalProperties": false,
489
+ "properties": {
490
+ "type": {
491
+ "type": "string",
492
+ "enum": ["function"]
493
+ },
494
+ "name": {
495
+ "type": "string"
496
+ },
497
+ "description": {
498
+ "type": "string"
499
+ },
500
+ "parameters": {
501
+ "type": "object",
502
+ "additionalProperties": false,
503
+ "properties": {
504
+ "type": {
505
+ "type": "string",
506
+ "enum": ["object"]
507
+ },
508
+ "properties": {
509
+ "type": "object",
510
+ "additionalProperties": true
511
+ },
512
+ "required": {
513
+ "type": "array",
514
+ "items": {
515
+ "type": "string"
516
+ }
517
+ }
518
+ },
519
+ "required": ["type", "properties"]
520
+ }
521
+ },
522
+ "required": ["type", "name", "description", "parameters"]
523
+ }
524
+ },
525
+ "fastContext": {
526
+ "type": "object",
527
+ "additionalProperties": false,
528
+ "properties": {
529
+ "enabled": {
530
+ "type": "boolean"
531
+ },
532
+ "timeoutMs": {
533
+ "type": "number",
534
+ "minimum": 1
535
+ },
536
+ "maxResults": {
537
+ "type": "number",
538
+ "minimum": 1
539
+ },
540
+ "sources": {
541
+ "type": "array",
542
+ "minItems": 1,
543
+ "items": {
544
+ "type": "string",
545
+ "enum": ["memory", "sessions"]
546
+ }
547
+ },
548
+ "fallbackToConsult": {
549
+ "type": "boolean"
550
+ }
551
+ }
552
+ },
553
+ "providers": {
554
+ "type": "object",
555
+ "additionalProperties": {
556
+ "type": "object",
557
+ "additionalProperties": true
558
+ }
404
559
  }
405
560
  }
406
561
  },
562
+ "publicUrl": {
563
+ "type": "string"
564
+ },
565
+ "skipSignatureVerification": {
566
+ "type": "boolean"
567
+ },
407
568
  "tts": {
408
569
  "type": "object",
409
570
  "additionalProperties": false,
@@ -420,8 +581,7 @@
420
581
  "enum": ["final", "all"]
421
582
  },
422
583
  "provider": {
423
- "type": "string",
424
- "enum": ["openai", "elevenlabs", "edge"]
584
+ "type": "string"
425
585
  },
426
586
  "summaryModel": {
427
587
  "type": "string"
@@ -456,127 +616,179 @@
456
616
  }
457
617
  }
458
618
  },
459
- "elevenlabs": {
619
+ "providers": {
460
620
  "type": "object",
461
- "additionalProperties": false,
462
621
  "properties": {
463
- "apiKey": {
464
- "type": "string"
465
- },
466
- "baseUrl": {
467
- "type": "string"
468
- },
469
- "voiceId": {
470
- "type": "string"
471
- },
472
- "modelId": {
473
- "type": "string"
474
- },
475
- "seed": {
476
- "type": "integer",
477
- "minimum": 0,
478
- "maximum": 4294967295
479
- },
480
- "applyTextNormalization": {
481
- "type": "string",
482
- "enum": ["auto", "on", "off"]
483
- },
484
- "languageCode": {
485
- "type": "string"
486
- },
487
- "voiceSettings": {
622
+ "openai": {
488
623
  "type": "object",
489
624
  "additionalProperties": false,
490
625
  "properties": {
491
- "stability": {
492
- "type": "number",
493
- "minimum": 0,
494
- "maximum": 1
626
+ "apiKey": {
627
+ "type": ["string", "object"]
495
628
  },
496
- "similarityBoost": {
497
- "type": "number",
498
- "minimum": 0,
499
- "maximum": 1
629
+ "baseUrl": {
630
+ "type": "string"
500
631
  },
501
- "style": {
502
- "type": "number",
503
- "minimum": 0,
504
- "maximum": 1
632
+ "model": {
633
+ "type": "string"
505
634
  },
506
- "useSpeakerBoost": {
507
- "type": "boolean"
635
+ "voice": {
636
+ "type": "string"
508
637
  },
509
638
  "speed": {
510
639
  "type": "number",
511
- "minimum": 0.5,
512
- "maximum": 2
640
+ "minimum": 0.25,
641
+ "maximum": 4.0
642
+ },
643
+ "instructions": {
644
+ "type": "string"
513
645
  }
514
646
  }
515
- }
516
- }
517
- },
518
- "openai": {
519
- "type": "object",
520
- "additionalProperties": false,
521
- "properties": {
522
- "apiKey": {
523
- "type": "string"
524
- },
525
- "baseUrl": {
526
- "type": "string"
527
647
  },
528
- "model": {
529
- "type": "string"
530
- },
531
- "voice": {
532
- "type": "string"
648
+ "elevenlabs": {
649
+ "type": "object",
650
+ "additionalProperties": false,
651
+ "properties": {
652
+ "apiKey": {
653
+ "type": ["string", "object"]
654
+ },
655
+ "baseUrl": {
656
+ "type": "string"
657
+ },
658
+ "voiceId": {
659
+ "type": "string"
660
+ },
661
+ "modelId": {
662
+ "type": "string"
663
+ },
664
+ "seed": {
665
+ "type": "integer",
666
+ "minimum": 0,
667
+ "maximum": 4294967295
668
+ },
669
+ "applyTextNormalization": {
670
+ "type": "string",
671
+ "enum": ["auto", "on", "off"]
672
+ },
673
+ "languageCode": {
674
+ "type": "string"
675
+ },
676
+ "voiceSettings": {
677
+ "type": "object",
678
+ "additionalProperties": false,
679
+ "properties": {
680
+ "stability": {
681
+ "type": "number",
682
+ "minimum": 0,
683
+ "maximum": 1
684
+ },
685
+ "similarityBoost": {
686
+ "type": "number",
687
+ "minimum": 0,
688
+ "maximum": 1
689
+ },
690
+ "style": {
691
+ "type": "number",
692
+ "minimum": 0,
693
+ "maximum": 1
694
+ },
695
+ "useSpeakerBoost": {
696
+ "type": "boolean"
697
+ },
698
+ "speed": {
699
+ "type": "number",
700
+ "minimum": 0.5,
701
+ "maximum": 2
702
+ }
703
+ }
704
+ }
705
+ }
533
706
  },
534
- "speed": {
535
- "type": "number",
536
- "minimum": 0.25,
537
- "maximum": 4.0
707
+ "microsoft": {
708
+ "type": "object",
709
+ "additionalProperties": false,
710
+ "properties": {
711
+ "enabled": {
712
+ "type": "boolean"
713
+ },
714
+ "voice": {
715
+ "type": "string"
716
+ },
717
+ "lang": {
718
+ "type": "string"
719
+ },
720
+ "outputFormat": {
721
+ "type": "string"
722
+ },
723
+ "pitch": {
724
+ "type": "string"
725
+ },
726
+ "rate": {
727
+ "type": "string"
728
+ },
729
+ "volume": {
730
+ "type": "string"
731
+ },
732
+ "saveSubtitles": {
733
+ "type": "boolean"
734
+ },
735
+ "proxy": {
736
+ "type": "string"
737
+ },
738
+ "timeoutMs": {
739
+ "type": "integer",
740
+ "minimum": 1000,
741
+ "maximum": 120000
742
+ }
743
+ }
538
744
  },
539
- "instructions": {
540
- "type": "string"
745
+ "edge": {
746
+ "type": "object",
747
+ "additionalProperties": false,
748
+ "properties": {
749
+ "enabled": {
750
+ "type": "boolean"
751
+ },
752
+ "voice": {
753
+ "type": "string"
754
+ },
755
+ "lang": {
756
+ "type": "string"
757
+ },
758
+ "outputFormat": {
759
+ "type": "string"
760
+ },
761
+ "pitch": {
762
+ "type": "string"
763
+ },
764
+ "rate": {
765
+ "type": "string"
766
+ },
767
+ "volume": {
768
+ "type": "string"
769
+ },
770
+ "saveSubtitles": {
771
+ "type": "boolean"
772
+ },
773
+ "proxy": {
774
+ "type": "string"
775
+ },
776
+ "timeoutMs": {
777
+ "type": "integer",
778
+ "minimum": 1000,
779
+ "maximum": 120000
780
+ }
781
+ }
541
782
  }
542
- }
543
- },
544
- "edge": {
545
- "type": "object",
546
- "additionalProperties": false,
547
- "properties": {
548
- "enabled": {
549
- "type": "boolean"
550
- },
551
- "voice": {
552
- "type": "string"
553
- },
554
- "lang": {
555
- "type": "string"
556
- },
557
- "outputFormat": {
558
- "type": "string"
559
- },
560
- "pitch": {
561
- "type": "string"
562
- },
563
- "rate": {
564
- "type": "string"
565
- },
566
- "volume": {
567
- "type": "string"
568
- },
569
- "saveSubtitles": {
570
- "type": "boolean"
571
- },
572
- "proxy": {
573
- "type": "string"
783
+ },
784
+ "additionalProperties": {
785
+ "type": "object",
786
+ "properties": {
787
+ "apiKey": {
788
+ "type": ["string", "object"]
789
+ }
574
790
  },
575
- "timeoutMs": {
576
- "type": "integer",
577
- "minimum": 1000,
578
- "maximum": 120000
579
- }
791
+ "additionalProperties": true
580
792
  }
581
793
  },
582
794
  "prefsPath": {
@@ -596,6 +808,10 @@
596
808
  "store": {
597
809
  "type": "string"
598
810
  },
811
+ "sessionScope": {
812
+ "type": "string",
813
+ "enum": ["per-phone", "per-call"]
814
+ },
599
815
  "responseModel": {
600
816
  "type": "string"
601
817
  },
@@ -607,5 +823,16 @@
607
823
  "minimum": 1
608
824
  }
609
825
  }
826
+ },
827
+ "configContracts": {
828
+ "compatibilityMigrationPaths": ["plugins.entries.voice-call.config"],
829
+ "secretInputs": {
830
+ "paths": [
831
+ { "path": "twilio.authToken", "expected": "string" },
832
+ { "path": "realtime.providers.*.apiKey", "expected": "string" },
833
+ { "path": "streaming.providers.*.apiKey", "expected": "string" },
834
+ { "path": "tts.providers.*.apiKey", "expected": "string" }
835
+ ]
836
+ }
610
837
  }
611
838
  }