@kodelyth/voice-call 2026.5.39 → 2026.5.42

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 (137) hide show
  1. package/README.md +167 -0
  2. package/api.ts +16 -0
  3. package/cli-metadata.ts +10 -0
  4. package/config-api.ts +12 -0
  5. package/dist/api.js +2 -0
  6. package/dist/cli-metadata.js +12 -0
  7. package/dist/config-DAwbG2aw.js +621 -0
  8. package/dist/config-compat-BYfJ5ueI.js +129 -0
  9. package/dist/guarded-json-api-xAIbFPZh.js +591 -0
  10. package/dist/index.js +1341 -0
  11. package/dist/mock-jtSdKDQN.js +135 -0
  12. package/dist/plivo-L-JTeuEc.js +392 -0
  13. package/dist/realtime-handler-5pSItXxX.js +1227 -0
  14. package/dist/realtime-transcription.runtime-CAbQKwCN.js +2 -0
  15. package/dist/realtime-voice.runtime-vCpCAutg.js +2 -0
  16. package/dist/response-generator-B-MjbtsM.js +199 -0
  17. package/dist/runtime-api.js +6 -0
  18. package/dist/runtime-entry-ohPMJR46.js +3435 -0
  19. package/dist/runtime-entry.js +2 -0
  20. package/dist/setup-api.js +37 -0
  21. package/dist/telnyx-BWr9EZ4x.js +278 -0
  22. package/dist/twilio-D9B0zY1k.js +679 -0
  23. package/index.test.ts +1075 -0
  24. package/index.ts +863 -0
  25. package/klaw.plugin.json +30 -133
  26. package/package.json +3 -3
  27. package/runtime-api.ts +20 -0
  28. package/runtime-entry.ts +1 -0
  29. package/setup-api.ts +47 -0
  30. package/src/allowlist.test.ts +18 -0
  31. package/src/allowlist.ts +19 -0
  32. package/src/cli.test.ts +12 -0
  33. package/src/cli.ts +866 -0
  34. package/src/config-compat.test.ts +130 -0
  35. package/src/config-compat.ts +227 -0
  36. package/src/config.test.ts +542 -0
  37. package/src/config.ts +883 -0
  38. package/src/core-bridge.ts +14 -0
  39. package/src/deep-merge.test.ts +40 -0
  40. package/src/deep-merge.ts +23 -0
  41. package/src/gateway-continue-operation.ts +200 -0
  42. package/src/http-headers.test.ts +16 -0
  43. package/src/http-headers.ts +15 -0
  44. package/src/manager/context.ts +50 -0
  45. package/src/manager/events.test.ts +578 -0
  46. package/src/manager/events.ts +332 -0
  47. package/src/manager/lifecycle.ts +53 -0
  48. package/src/manager/lookup.test.ts +52 -0
  49. package/src/manager/lookup.ts +35 -0
  50. package/src/manager/outbound.test.ts +629 -0
  51. package/src/manager/outbound.ts +508 -0
  52. package/src/manager/state.ts +48 -0
  53. package/src/manager/store.ts +107 -0
  54. package/src/manager/timers.test.ts +127 -0
  55. package/src/manager/timers.ts +113 -0
  56. package/src/manager/twiml.test.ts +13 -0
  57. package/src/manager/twiml.ts +17 -0
  58. package/src/manager.closed-loop.test.ts +259 -0
  59. package/src/manager.inbound-allowlist.test.ts +183 -0
  60. package/src/manager.notify.test.ts +390 -0
  61. package/src/manager.restore.test.ts +310 -0
  62. package/src/manager.test-harness.ts +127 -0
  63. package/src/manager.ts +441 -0
  64. package/src/media-stream.test.ts +953 -0
  65. package/src/media-stream.ts +876 -0
  66. package/src/providers/base.ts +99 -0
  67. package/src/providers/mock.test.ts +86 -0
  68. package/src/providers/mock.ts +185 -0
  69. package/src/providers/plivo.test.ts +93 -0
  70. package/src/providers/plivo.ts +601 -0
  71. package/src/providers/shared/call-status.test.ts +24 -0
  72. package/src/providers/shared/call-status.ts +24 -0
  73. package/src/providers/shared/guarded-json-api.test.ts +127 -0
  74. package/src/providers/shared/guarded-json-api.ts +49 -0
  75. package/src/providers/telnyx.test.ts +489 -0
  76. package/src/providers/telnyx.ts +419 -0
  77. package/src/providers/twilio/api.test.ts +184 -0
  78. package/src/providers/twilio/api.ts +100 -0
  79. package/src/providers/twilio/twiml-policy.test.ts +84 -0
  80. package/src/providers/twilio/twiml-policy.ts +87 -0
  81. package/src/providers/twilio/webhook.ts +34 -0
  82. package/src/providers/twilio.test.ts +607 -0
  83. package/src/providers/twilio.ts +861 -0
  84. package/src/providers/twilio.types.ts +17 -0
  85. package/src/realtime-agent-context.test.ts +101 -0
  86. package/src/realtime-agent-context.ts +149 -0
  87. package/src/realtime-defaults.ts +3 -0
  88. package/src/realtime-fast-context.test.ts +74 -0
  89. package/src/realtime-fast-context.ts +27 -0
  90. package/src/realtime-transcription.runtime.ts +4 -0
  91. package/src/realtime-voice.runtime.ts +5 -0
  92. package/src/response-generator.test.ts +385 -0
  93. package/src/response-generator.ts +348 -0
  94. package/src/response-model.test.ts +71 -0
  95. package/src/response-model.ts +23 -0
  96. package/src/runtime.test.ts +625 -0
  97. package/src/runtime.ts +528 -0
  98. package/src/telephony-audio.test.ts +61 -0
  99. package/src/telephony-audio.ts +12 -0
  100. package/src/telephony-tts.test.ts +196 -0
  101. package/src/telephony-tts.ts +235 -0
  102. package/src/test-fixtures.ts +82 -0
  103. package/src/tts-provider-voice.test.ts +34 -0
  104. package/src/tts-provider-voice.ts +21 -0
  105. package/src/tunnel.test.ts +173 -0
  106. package/src/tunnel.ts +314 -0
  107. package/src/types.ts +311 -0
  108. package/src/utils.test.ts +17 -0
  109. package/src/utils.ts +14 -0
  110. package/src/voice-mapping.test.ts +32 -0
  111. package/src/voice-mapping.ts +65 -0
  112. package/src/webhook/realtime-audio-pacer.test.ts +146 -0
  113. package/src/webhook/realtime-audio-pacer.ts +204 -0
  114. package/src/webhook/realtime-handler.test.ts +1450 -0
  115. package/src/webhook/realtime-handler.ts +1382 -0
  116. package/src/webhook/stale-call-reaper.test.ts +89 -0
  117. package/src/webhook/stale-call-reaper.ts +38 -0
  118. package/src/webhook/stream-frame-adapter.test.ts +187 -0
  119. package/src/webhook/stream-frame-adapter.ts +219 -0
  120. package/src/webhook/tailscale.test.ts +216 -0
  121. package/src/webhook/tailscale.ts +129 -0
  122. package/src/webhook-exposure.test.ts +33 -0
  123. package/src/webhook-exposure.ts +84 -0
  124. package/src/webhook-security.test.ts +813 -0
  125. package/src/webhook-security.ts +982 -0
  126. package/src/webhook.hangup-once.lifecycle.test.ts +179 -0
  127. package/src/webhook.test.ts +1615 -0
  128. package/src/webhook.ts +933 -0
  129. package/src/webhook.types.ts +5 -0
  130. package/src/websocket-test-support.ts +72 -0
  131. package/tsconfig.json +16 -0
  132. package/api.js +0 -7
  133. package/cli-metadata.js +0 -7
  134. package/index.js +0 -7
  135. package/runtime-api.js +0 -7
  136. package/runtime-entry.js +0 -7
  137. package/setup-api.js +0 -7
package/README.md ADDED
@@ -0,0 +1,167 @@
1
+ # @klaw/voice-call
2
+
3
+ Official Voice Call plugin for **Klaw**.
4
+
5
+ Providers:
6
+
7
+ - **Twilio** (Programmable Voice + Media Streams)
8
+ - **Telnyx** (Call Control v2)
9
+ - **Plivo** (Voice API + XML transfer + GetInput speech)
10
+ - **Mock** (dev/no network)
11
+
12
+ Docs: `https://klaw.kodelyth.com/plugins/voice-call`
13
+ Plugin system: `https://klaw.kodelyth.com/plugin`
14
+
15
+ ## Install (local dev)
16
+
17
+ ### Option A: install via Klaw (recommended)
18
+
19
+ ```bash
20
+ klaw plugins install @klaw/voice-call
21
+ ```
22
+
23
+ Restart the Gateway afterwards.
24
+
25
+ ### Option B: copy into your global extensions folder (dev)
26
+
27
+ ```bash
28
+ PLUGIN_HOME=~/.klaw/extensions
29
+ mkdir -p "$PLUGIN_HOME"
30
+ cp -R <local-plugin-checkout> "$PLUGIN_HOME/voice-call"
31
+ cd "$PLUGIN_HOME/voice-call" && pnpm install
32
+ ```
33
+
34
+ ## Config
35
+
36
+ Put under `plugins.entries.voice-call.config`:
37
+
38
+ ```json5
39
+ {
40
+ provider: "twilio", // or "telnyx" | "plivo" | "mock"
41
+ fromNumber: "+15550001234",
42
+ toNumber: "+15550005678",
43
+ sessionScope: "per-phone", // or "per-call"
44
+
45
+ twilio: {
46
+ accountSid: "ACxxxxxxxx",
47
+ authToken: "your_token",
48
+ },
49
+
50
+ telnyx: {
51
+ apiKey: "KEYxxxx",
52
+ connectionId: "CONNxxxx",
53
+ // Telnyx webhook public key from the Telnyx Mission Control Portal
54
+ // (Base64 string; can also be set via TELNYX_PUBLIC_KEY).
55
+ publicKey: "...",
56
+ },
57
+
58
+ plivo: {
59
+ authId: "MAxxxxxxxxxxxxxxxxxxxx",
60
+ authToken: "your_token",
61
+ },
62
+
63
+ // Webhook server
64
+ serve: {
65
+ port: 3334,
66
+ path: "/voice/webhook",
67
+ },
68
+
69
+ // Public exposure (pick one):
70
+ // publicUrl: "https://example.ngrok.app/voice/webhook",
71
+ // tunnel: { provider: "ngrok" },
72
+ // tailscale: { mode: "funnel", path: "/voice/webhook" }
73
+
74
+ outbound: {
75
+ defaultMode: "notify", // or "conversation"
76
+ },
77
+
78
+ // Optional response agent workspace. Defaults to "main".
79
+ agentId: "main",
80
+
81
+ streaming: {
82
+ enabled: true,
83
+ // optional; if omitted, Voice Call picks the first registered
84
+ // realtime-transcription provider by autoSelectOrder
85
+ provider: "<realtime-transcription-provider-id>",
86
+ streamPath: "/voice/stream",
87
+ providers: {
88
+ "<realtime-transcription-provider-id>": {
89
+ // provider-owned options
90
+ },
91
+ },
92
+ preStartTimeoutMs: 5000,
93
+ maxPendingConnections: 32,
94
+ maxPendingConnectionsPerIp: 4,
95
+ maxConnections: 128,
96
+ },
97
+ }
98
+ ```
99
+
100
+ Notes:
101
+
102
+ - Twilio/Telnyx/Plivo require a **publicly reachable** webhook URL.
103
+ - `mock` is a local dev provider (no network calls).
104
+ - Telnyx requires `telnyx.publicKey` (or `TELNYX_PUBLIC_KEY`) unless `skipSignatureVerification` is true.
105
+ - If older configs still use `provider: "log"`, `twilio.from`, or legacy `streaming.*` OpenAI keys, run `klaw doctor --fix` to rewrite them.
106
+ - advanced webhook, streaming, and tunnel notes: `https://klaw.kodelyth.com/plugins/voice-call`
107
+ - `responseModel` is optional. When unset, voice responses use the runtime default model.
108
+ - `sessionScope` defaults to `per-phone`, preserving caller memory across calls. Use `per-call` for reception, booking, IVR, and bridge flows where each carrier call should start fresh.
109
+ - `realtime.consultThinkingLevel` is optional. When set, it overrides the thinking level used by the model behind realtime `klaw_agent_consult` calls.
110
+ - `realtime.consultFastMode` is optional. When set, it toggles fast mode for realtime `klaw_agent_consult` calls.
111
+
112
+ ## Stale call reaper
113
+
114
+ See the plugin docs for recommended ranges and production examples:
115
+ `https://klaw.kodelyth.com/plugins/voice-call#stale-call-reaper`
116
+
117
+ ## TTS for calls
118
+
119
+ Voice Call uses the core `messages.tts` configuration for
120
+ streaming speech on calls. Override examples and provider caveats live here:
121
+ `https://klaw.kodelyth.com/plugins/voice-call#tts-for-calls`
122
+
123
+ ## CLI
124
+
125
+ ```bash
126
+ klaw voicecall call --to "+15555550123" --message "Hello from Klaw"
127
+ klaw voicecall continue --call-id <id> --message "Any questions?"
128
+ klaw voicecall speak --call-id <id> --message "One moment"
129
+ klaw voicecall end --call-id <id>
130
+ klaw voicecall status --json
131
+ klaw voicecall status --call-id <id>
132
+ klaw voicecall tail
133
+ klaw voicecall expose --mode funnel
134
+ ```
135
+
136
+ ## Tool
137
+
138
+ Tool name: `voice_call`
139
+
140
+ Actions:
141
+
142
+ - `initiate_call` (message, to?, mode?)
143
+ - `continue_call` (callId, message)
144
+ - `speak_to_user` (callId, message)
145
+ - `end_call` (callId)
146
+ - `get_status` (callId)
147
+
148
+ ## Gateway RPC
149
+
150
+ - `voicecall.initiate` (to?, message, mode?)
151
+ - `voicecall.continue` (callId, message)
152
+ - `voicecall.speak` (callId, message)
153
+ - `voicecall.end` (callId)
154
+ - `voicecall.status` (callId)
155
+
156
+ ## Notes
157
+
158
+ - Uses webhook signature verification for Twilio/Telnyx/Plivo.
159
+ - Adds replay protection for Twilio and Plivo webhooks (valid duplicate callbacks are ignored safely).
160
+ - Twilio speech turns include a per-turn token so stale/replayed callbacks cannot complete a newer turn.
161
+ - `responseModel` / `responseSystemPrompt` control AI auto-responses.
162
+ - Voice-call auto-responses enforce a spoken JSON contract (`{"spoken":"..."}`) and filter reasoning/meta output before playback.
163
+ - While a Twilio stream is active, playback does not fall back to TwiML `<Say>`; stream-TTS failures fail the playback request.
164
+ - Outbound conversation calls suppress barge-in only while the initial greeting is actively speaking, then re-enable normal interruption.
165
+ - Twilio stream disconnect auto-end uses a short grace window so quick reconnects do not end the call.
166
+ - Realtime provider selection is generic. Configure `streaming.provider` / `realtime.provider` and put provider-owned options under `providers.<id>`.
167
+ - Runtime fallback still accepts the old voice-call keys for now, but migration is a doctor step and the compat shim is scheduled to go away in a future release.
package/api.ts ADDED
@@ -0,0 +1,16 @@
1
+ export {
2
+ definePluginEntry,
3
+ fetchWithSsrFGuard,
4
+ type GatewayRequestHandlerOptions,
5
+ isBlockedHostnameOrIp,
6
+ isRequestBodyLimitError,
7
+ type KlawPluginApi,
8
+ readRequestBodyWithLimit,
9
+ requestBodyErrorToText,
10
+ type SessionEntry,
11
+ sleep,
12
+ TtsAutoSchema,
13
+ TtsConfigSchema,
14
+ TtsModeSchema,
15
+ TtsProviderSchema,
16
+ } from "./runtime-api.js";
@@ -0,0 +1,10 @@
1
+ import { definePluginEntry } from "klaw/plugin-sdk/plugin-entry";
2
+
3
+ export default definePluginEntry({
4
+ id: "voice-call",
5
+ name: "Voice Call",
6
+ description: "Voice call channel plugin",
7
+ register(api) {
8
+ api.registerCli(() => {}, { commands: ["voicecall"] });
9
+ },
10
+ });
package/config-api.ts ADDED
@@ -0,0 +1,12 @@
1
+ // Narrow barrel for config compatibility helpers consumed outside the plugin.
2
+ // Keep this separate from api.ts so config migration code does not pull in the
3
+ // full runtime-oriented voice-call surface.
4
+
5
+ export {
6
+ VOICE_CALL_LEGACY_CONFIG_REMOVAL_VERSION,
7
+ collectVoiceCallLegacyConfigIssues,
8
+ formatVoiceCallLegacyConfigWarnings,
9
+ migrateVoiceCallLegacyConfigInput,
10
+ normalizeVoiceCallLegacyConfigInput,
11
+ parseVoiceCallPluginConfig,
12
+ } from "./src/config-compat.js";
package/dist/api.js ADDED
@@ -0,0 +1,2 @@
1
+ import { TtsAutoSchema, TtsConfigSchema, TtsModeSchema, TtsProviderSchema, definePluginEntry, fetchWithSsrFGuard, isBlockedHostnameOrIp, isRequestBodyLimitError, readRequestBodyWithLimit, requestBodyErrorToText, sleep } from "./runtime-api.js";
2
+ export { TtsAutoSchema, TtsConfigSchema, TtsModeSchema, TtsProviderSchema, definePluginEntry, fetchWithSsrFGuard, isBlockedHostnameOrIp, isRequestBodyLimitError, readRequestBodyWithLimit, requestBodyErrorToText, sleep };
@@ -0,0 +1,12 @@
1
+ import { definePluginEntry } from "klaw/plugin-sdk/plugin-entry";
2
+ //#region extensions/voice-call/cli-metadata.ts
3
+ var cli_metadata_default = definePluginEntry({
4
+ id: "voice-call",
5
+ name: "Voice Call",
6
+ description: "Voice call channel plugin",
7
+ register(api) {
8
+ api.registerCli(() => {}, { commands: ["voicecall"] });
9
+ }
10
+ });
11
+ //#endregion
12
+ export { cli_metadata_default as default };