@openclaw/voice-call 2026.3.13 → 2026.5.1-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 +25 -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 +866 -0
  6. package/index.ts +353 -148
  7. package/openclaw.plugin.json +336 -157
  8. package/package.json +33 -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 +160 -12
  17. package/src/config.ts +243 -74
  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 +179 -19
  24. package/src/manager/events.ts +48 -30
  25. package/src/manager/lifecycle.ts +53 -0
  26. package/src/manager/lookup.test.ts +52 -0
  27. package/src/manager/outbound.test.ts +464 -0
  28. package/src/manager/outbound.ts +148 -55
  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 +277 -0
  64. package/src/response-generator.ts +186 -40
  65. package/src/response-model.test.ts +71 -0
  66. package/src/response-model.ts +23 -0
  67. package/src/runtime.test.ts +351 -0
  68. package/src/runtime.ts +254 -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 +26 -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 +513 -100
  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
package/setup-api.ts ADDED
@@ -0,0 +1,47 @@
1
+ import type { OpenClawConfig } from "openclaw/plugin-sdk/plugin-entry";
2
+ import { definePluginEntry } from "openclaw/plugin-sdk/plugin-entry";
3
+ import { isRecord } from "openclaw/plugin-sdk/text-runtime";
4
+ import { migrateVoiceCallLegacyConfigInput } from "./config-api.js";
5
+
6
+ function migrateVoiceCallPluginConfig(config: OpenClawConfig): {
7
+ config: OpenClawConfig;
8
+ changes: string[];
9
+ } | null {
10
+ const rawVoiceCallConfig = config.plugins?.entries?.["voice-call"]?.config;
11
+ if (!isRecord(rawVoiceCallConfig)) {
12
+ return null;
13
+ }
14
+ const migration = migrateVoiceCallLegacyConfigInput({
15
+ value: rawVoiceCallConfig,
16
+ configPathPrefix: "plugins.entries.voice-call.config",
17
+ });
18
+ if (migration.changes.length === 0) {
19
+ return null;
20
+ }
21
+ const plugins = structuredClone(config.plugins ?? {});
22
+ const entries = { ...plugins.entries };
23
+ const existingVoiceCallEntry = isRecord(entries["voice-call"])
24
+ ? (entries["voice-call"] as Record<string, unknown>)
25
+ : {};
26
+ entries["voice-call"] = {
27
+ ...existingVoiceCallEntry,
28
+ config: migration.config,
29
+ };
30
+ plugins.entries = entries;
31
+ return {
32
+ config: {
33
+ ...config,
34
+ plugins,
35
+ },
36
+ changes: migration.changes,
37
+ };
38
+ }
39
+
40
+ export default definePluginEntry({
41
+ id: "voice-call",
42
+ name: "Voice Call Setup",
43
+ description: "Lightweight Voice Call setup hooks",
44
+ register(api) {
45
+ api.registerConfigMigration((config) => migrateVoiceCallPluginConfig(config));
46
+ },
47
+ });
@@ -0,0 +1,18 @@
1
+ import { describe, expect, it } from "vitest";
2
+ import { isAllowlistedCaller, normalizePhoneNumber } from "./allowlist.js";
3
+
4
+ describe("voice-call allowlist", () => {
5
+ it("normalizes phone numbers by stripping non-digits", () => {
6
+ expect(normalizePhoneNumber("+1 (415) 555-0123")).toBe("14155550123");
7
+ expect(normalizePhoneNumber(" 020-7946-0958 ")).toBe("02079460958");
8
+ expect(normalizePhoneNumber("")).toBe("");
9
+ expect(normalizePhoneNumber()).toBe("");
10
+ });
11
+
12
+ it("matches normalized allowlist entries and rejects blank callers", () => {
13
+ expect(isAllowlistedCaller("14155550123", ["+1 (415) 555-0123", " 020-7946-0958 "])).toBe(true);
14
+ expect(isAllowlistedCaller("02079460958", ["+1 (415) 555-0123", " 020-7946-0958 "])).toBe(true);
15
+ expect(isAllowlistedCaller("", ["+1 (415) 555-0123"])).toBe(false);
16
+ expect(isAllowlistedCaller("14155550123", ["", "abc"])).toBe(false);
17
+ });
18
+ });