@memberjunction/ai-bridge-twilio 0.0.1 → 5.42.0
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 +106 -43
- package/dist/index.d.ts +5 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +12 -0
- package/dist/index.js.map +1 -0
- package/dist/register-native.d.ts +19 -0
- package/dist/register-native.d.ts.map +1 -0
- package/dist/register-native.js +34 -0
- package/dist/register-native.js.map +1 -0
- package/dist/twilio-bridge.d.ts +54 -0
- package/dist/twilio-bridge.d.ts.map +1 -0
- package/dist/twilio-bridge.js +75 -0
- package/dist/twilio-bridge.js.map +1 -0
- package/dist/twilio-call-sdk.d.ts +167 -0
- package/dist/twilio-call-sdk.d.ts.map +1 -0
- package/dist/twilio-call-sdk.js +156 -0
- package/dist/twilio-call-sdk.js.map +1 -0
- package/dist/twilio-native-call-sdk.d.ts +281 -0
- package/dist/twilio-native-call-sdk.d.ts.map +1 -0
- package/dist/twilio-native-call-sdk.js +313 -0
- package/dist/twilio-native-call-sdk.js.map +1 -0
- package/package.json +32 -7
|
@@ -0,0 +1,313 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview `TwilioNativeCallSdk` — a **real, two-way** {@link ITelephonyCallSdk} binding over the
|
|
3
|
+
* native **Twilio Programmable Voice + Media Streams** path. Unlike the shipped, unbound
|
|
4
|
+
* {@link import('./twilio-call-sdk.js').TwilioCallSdk} (every operation throws "bind the real Twilio
|
|
5
|
+
* client"), this adapter actually carries the call: {@link TwilioNativeCallSdk.sendAudioFrame} forwards
|
|
6
|
+
* the agent's synthesized PCM onto the call's Media-Streams websocket (the agent's **voice** on the
|
|
7
|
+
* call), inbound Media-Streams audio maps to the seam's audio-frame callback (what the agent **hears**),
|
|
8
|
+
* and DTMF / transfer / hangup actually reach the native client.
|
|
9
|
+
*
|
|
10
|
+
* ## Why a native binding
|
|
11
|
+
* A phone call is a single-leg, bidirectional audio source. The native Twilio path has two halves — a
|
|
12
|
+
* **REST API** (place / hang-up / transfer / send-DTMF) and a **Media Streams** websocket (bidirectional
|
|
13
|
+
* realtime audio + inbound DTMF events). This adapter sits over both so a single binding gives the agent
|
|
14
|
+
* full-duplex audio plus the call controls the telephony seam declares.
|
|
15
|
+
*
|
|
16
|
+
* ## The native module seam (no SDK types leak)
|
|
17
|
+
* The `twilio` SDK is NOT imported here. Deployments wrap the REST + Media-Streams plumbing behind the
|
|
18
|
+
* small structural {@link NativeCallModule} surface declared below, and this adapter depends ONLY on that
|
|
19
|
+
* surface — none of `twilio`'s real types leak into `@memberjunction/ai-bridge-twilio`. The module is
|
|
20
|
+
* loaded **lazily** behind an injectable {@link NativeModuleLoader} so the package builds and unit-tests
|
|
21
|
+
* with **no `twilio` install and no network**. Tests inject a fake module; production points
|
|
22
|
+
* {@link TwilioNativeSdkConfig.NativeModuleSpecifier} at the real adapter package/path.
|
|
23
|
+
*
|
|
24
|
+
* ## Auth (deployment responsibility)
|
|
25
|
+
* The native client authenticates with the Twilio **Account SID + Auth Token** (or API key/secret) and a
|
|
26
|
+
* resolved Media-Streams websocket URL. These resolve **upstream** (MJ credential system / provider
|
|
27
|
+
* `Configuration`) and are **never inlined** at a call site — {@link readNativeConfig} reads already-
|
|
28
|
+
* resolved values out of the loose `Configuration` map the engine passes at connect.
|
|
29
|
+
*
|
|
30
|
+
* @module @memberjunction/ai-bridge-twilio
|
|
31
|
+
* @author MemberJunction.com
|
|
32
|
+
* @see {@link ITelephonyCallSdk} — the platform-agnostic telephony seam this binds.
|
|
33
|
+
*/
|
|
34
|
+
import { LogError } from '@memberjunction/core';
|
|
35
|
+
/**
|
|
36
|
+
* Copies arbitrary PCM bytes into a standalone `ArrayBuffer`, never aliasing the caller's buffer window.
|
|
37
|
+
* A `Uint8Array` view may be a slice of a larger backing buffer (offset/length), so a naive `.buffer`
|
|
38
|
+
* grab would leak neighbouring audio; this copies exactly the view's bytes. Defined locally because the
|
|
39
|
+
* Twilio package has no shared coercion helper to reuse (unlike the Zoom package's RTMS binding).
|
|
40
|
+
*/
|
|
41
|
+
export function toArrayBuffer(data) {
|
|
42
|
+
if (data instanceof ArrayBuffer) {
|
|
43
|
+
return data.slice(0);
|
|
44
|
+
}
|
|
45
|
+
const copy = new Uint8Array(data.byteLength);
|
|
46
|
+
copy.set(data);
|
|
47
|
+
return copy.buffer;
|
|
48
|
+
}
|
|
49
|
+
/**
|
|
50
|
+
* **Pure mapping** of one native inbound audio frame onto the raw PCM `ArrayBuffer` the telephony seam's
|
|
51
|
+
* audio callback delivers. Copies the bytes (see {@link toArrayBuffer}). Isolated from I/O for direct
|
|
52
|
+
* unit testing. (The telephony seam carries no per-speaker label — a 1:1 call has one remote party.)
|
|
53
|
+
*/
|
|
54
|
+
export function mapNativeAudioFrame(frame) {
|
|
55
|
+
return toArrayBuffer(frame.data);
|
|
56
|
+
}
|
|
57
|
+
/** Structural guard: a value is a {@link NativeCallModule} when it exposes a `createClient` function. */
|
|
58
|
+
function isNativeModule(value) {
|
|
59
|
+
return (value != null &&
|
|
60
|
+
typeof value === 'object' &&
|
|
61
|
+
typeof value.createClient === 'function');
|
|
62
|
+
}
|
|
63
|
+
/** Unwraps a `{ default }` interop wrapper (CJS-with-default), returning the inner value or the input. */
|
|
64
|
+
function unwrapDefault(mod) {
|
|
65
|
+
if (mod && typeof mod === 'object' && 'default' in mod) {
|
|
66
|
+
const inner = mod.default;
|
|
67
|
+
if (isNativeModule(inner)) {
|
|
68
|
+
return inner;
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
return mod;
|
|
72
|
+
}
|
|
73
|
+
/**
|
|
74
|
+
* Lazily loads the native Twilio adapter at the given specifier (category: runtime plugin discovery from
|
|
75
|
+
* config — the adapter path is deployment-supplied and not known at build time, so a static import is
|
|
76
|
+
* impossible). Throws a precise, actionable error when it can't be loaded so a misconfigured deployment
|
|
77
|
+
* fails loudly, not silently.
|
|
78
|
+
*
|
|
79
|
+
* VERIFY against the native Twilio adapter: the module's default/namespace interop + that it exposes
|
|
80
|
+
* `createClient`.
|
|
81
|
+
*/
|
|
82
|
+
export const defaultNativeLoader = async (specifier) => {
|
|
83
|
+
try {
|
|
84
|
+
const mod = await import(/* @vite-ignore */ specifier);
|
|
85
|
+
const resolved = unwrapDefault(mod);
|
|
86
|
+
if (!isNativeModule(resolved)) {
|
|
87
|
+
throw new Error('resolved module has no createClient() factory');
|
|
88
|
+
}
|
|
89
|
+
return resolved;
|
|
90
|
+
}
|
|
91
|
+
catch (err) {
|
|
92
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
93
|
+
throw new Error(`TwilioNativeCallSdk could not load the native Twilio adapter at '${specifier}'. Build/install the ` +
|
|
94
|
+
'native Twilio Programmable Voice + Media Streams adapter (REST + websocket) and set ' +
|
|
95
|
+
`TwilioNativeSdkConfig.NativeModuleSpecifier to it. Underlying error: ${message}`);
|
|
96
|
+
}
|
|
97
|
+
};
|
|
98
|
+
/**
|
|
99
|
+
* A **real, two-way** {@link ITelephonyCallSdk} over the native Twilio Programmable Voice + Media Streams
|
|
100
|
+
* path.
|
|
101
|
+
*
|
|
102
|
+
* Gives the agent both **hearing** (inbound Media-Streams audio → the seam's audio callback) and a
|
|
103
|
+
* **voice** ({@link sendAudioFrame} → the native Media-Streams send path), plus working DTMF, transfer,
|
|
104
|
+
* and hangup. Construct via {@link BindTwilioNativeCall} (the factory the bridge's `SetSdkFactory` wants),
|
|
105
|
+
* not directly, so config resolution + the lazy loader wire consistently.
|
|
106
|
+
*
|
|
107
|
+
* The adapter tracks the active Call SID so per-call REST/websocket operations can be addressed, and
|
|
108
|
+
* re-registers any handlers the bridge set before the call existed once a call comes online.
|
|
109
|
+
*/
|
|
110
|
+
export class TwilioNativeCallSdk {
|
|
111
|
+
/**
|
|
112
|
+
* @param config Resolved credentials + stream URL + the native module specifier.
|
|
113
|
+
* @param loadModule The native-adapter loader (defaults to the lazy specifier loader).
|
|
114
|
+
*/
|
|
115
|
+
constructor(config, loadModule = defaultNativeLoader) {
|
|
116
|
+
/** The live native client once {@link dial}/{@link answer} brings a call online. */
|
|
117
|
+
this.client = null;
|
|
118
|
+
/** The active call's SID, so per-call operations can address it. */
|
|
119
|
+
this.activeCallId = null;
|
|
120
|
+
this.config = config;
|
|
121
|
+
this.loadModule = loadModule;
|
|
122
|
+
}
|
|
123
|
+
// ── ITelephonyCallSdk — lifecycle ────────────────────────────────────────────────
|
|
124
|
+
/**
|
|
125
|
+
* Loads the native adapter, constructs a client, wires its callbacks, and places the **outbound** call.
|
|
126
|
+
* Brings BOTH hearing and the agent's voice online. Resolves the platform-native Call SID.
|
|
127
|
+
*
|
|
128
|
+
* @param toNumber The destination phone number to dial.
|
|
129
|
+
* @param fromNumber The agent's caller-id / DID the call originates from.
|
|
130
|
+
* @param args Provider-specific dial parameters.
|
|
131
|
+
* @returns The Twilio Call SID for the placed call.
|
|
132
|
+
* @throws When the native module specifier is missing or the adapter can't be loaded.
|
|
133
|
+
*/
|
|
134
|
+
async dial(toNumber, fromNumber, args) {
|
|
135
|
+
const client = await this.ensureClient();
|
|
136
|
+
const callSid = await client.dial({ toNumber, fromNumber, extra: args });
|
|
137
|
+
this.bindCall(callSid);
|
|
138
|
+
return callSid;
|
|
139
|
+
}
|
|
140
|
+
/**
|
|
141
|
+
* Loads the native adapter, constructs a client, wires its callbacks, and **answers** an inbound call
|
|
142
|
+
* already delivered to the agent's number. Brings BOTH hearing and the agent's voice online.
|
|
143
|
+
*
|
|
144
|
+
* @param callId The platform-native identifier of the inbound call to answer.
|
|
145
|
+
* @throws When the native module specifier is missing or the adapter can't be loaded.
|
|
146
|
+
*/
|
|
147
|
+
async answer(callId) {
|
|
148
|
+
const client = await this.ensureClient();
|
|
149
|
+
await client.answer(callId);
|
|
150
|
+
this.bindCall(callId);
|
|
151
|
+
}
|
|
152
|
+
/**
|
|
153
|
+
* Hangs up the call via the native client and clears the active call. Tolerant of teardown errors.
|
|
154
|
+
*
|
|
155
|
+
* @param callId The platform-native identifier of the call to end.
|
|
156
|
+
*/
|
|
157
|
+
async hangup(callId) {
|
|
158
|
+
const client = this.client;
|
|
159
|
+
this.activeCallId = null;
|
|
160
|
+
if (client) {
|
|
161
|
+
try {
|
|
162
|
+
await client.hangup(callId);
|
|
163
|
+
}
|
|
164
|
+
catch (err) {
|
|
165
|
+
LogError(`[TwilioNativeCallSdk] hangup() failed: ${err instanceof Error ? err.message : String(err)}`);
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
// ── ITelephonyCallSdk — two-way audio (real) ─────────────────────────────────────
|
|
170
|
+
/**
|
|
171
|
+
* Sends one raw PCM frame as the agent's outbound voice into the call — **the agent's real voice on
|
|
172
|
+
* the call**, via the native Media-Streams send path. No-ops (without throwing) before a call exists
|
|
173
|
+
* so an early model frame never crashes the session.
|
|
174
|
+
*
|
|
175
|
+
* @param pcm The PCM audio bytes to speak into the call.
|
|
176
|
+
*/
|
|
177
|
+
sendAudioFrame(pcm) {
|
|
178
|
+
this.client?.sendAudioFrame(pcm);
|
|
179
|
+
}
|
|
180
|
+
/**
|
|
181
|
+
* Registers the inbound audio handler (the agent's hearing path). Wires it to the live client when a
|
|
182
|
+
* call already exists; otherwise it is (re-)registered at {@link bindCall} when the call comes online.
|
|
183
|
+
*
|
|
184
|
+
* @param cb Invoked with each inbound PCM audio frame.
|
|
185
|
+
*/
|
|
186
|
+
onAudioFrame(cb) {
|
|
187
|
+
this.audioHandler = cb;
|
|
188
|
+
this.client?.onAudioFrame((frame) => cb(mapNativeAudioFrame(frame)));
|
|
189
|
+
}
|
|
190
|
+
// ── ITelephonyCallSdk — DTMF, transfer (real) ────────────────────────────────────
|
|
191
|
+
/**
|
|
192
|
+
* Sends DTMF touch-tones on the call via the native client. No-ops (without throwing) before a call
|
|
193
|
+
* exists.
|
|
194
|
+
*
|
|
195
|
+
* @param digits The DTMF digit string to send.
|
|
196
|
+
*/
|
|
197
|
+
async sendDtmf(digits) {
|
|
198
|
+
await this.client?.sendDtmf(digits);
|
|
199
|
+
}
|
|
200
|
+
/**
|
|
201
|
+
* Registers the inbound DTMF handler. Wires it to the live client when a call already exists; otherwise
|
|
202
|
+
* it is (re-)registered at {@link bindCall} when the call comes online.
|
|
203
|
+
*
|
|
204
|
+
* @param cb Invoked with each received DTMF digit string.
|
|
205
|
+
*/
|
|
206
|
+
onDtmf(cb) {
|
|
207
|
+
this.dtmfHandler = cb;
|
|
208
|
+
this.client?.onDtmf(cb);
|
|
209
|
+
}
|
|
210
|
+
/**
|
|
211
|
+
* Transfers the live call to another party via the native client. No-ops (without throwing) before a
|
|
212
|
+
* call exists.
|
|
213
|
+
*
|
|
214
|
+
* @param callId The platform-native identifier of the call to transfer.
|
|
215
|
+
* @param toNumber The transfer destination.
|
|
216
|
+
*/
|
|
217
|
+
async transfer(callId, toNumber) {
|
|
218
|
+
await this.client?.transfer(callId, toNumber);
|
|
219
|
+
}
|
|
220
|
+
/**
|
|
221
|
+
* Registers the call-ended handler. Wires it to the live client when a call already exists; otherwise
|
|
222
|
+
* it is (re-)registered at {@link bindCall} when the call comes online.
|
|
223
|
+
*
|
|
224
|
+
* @param cb Invoked when the call ends.
|
|
225
|
+
*/
|
|
226
|
+
onCallEnded(cb) {
|
|
227
|
+
this.endedHandler = cb;
|
|
228
|
+
this.client?.onCallEnded(cb);
|
|
229
|
+
}
|
|
230
|
+
// ── internals ────────────────────────────────────────────────────────────────────
|
|
231
|
+
/**
|
|
232
|
+
* Lazily loads the native adapter and constructs the client (once), throwing an actionable error when
|
|
233
|
+
* the required {@link TwilioNativeSdkConfig.NativeModuleSpecifier} is absent.
|
|
234
|
+
*/
|
|
235
|
+
async ensureClient() {
|
|
236
|
+
if (this.client) {
|
|
237
|
+
return this.client;
|
|
238
|
+
}
|
|
239
|
+
const specifier = this.config.NativeModuleSpecifier;
|
|
240
|
+
if (!specifier) {
|
|
241
|
+
throw new Error('TwilioNativeCallSdk: no NativeModuleSpecifier configured. Set it to the native Twilio Programmable ' +
|
|
242
|
+
'Voice + Media Streams adapter (REST + websocket) in the session Configuration. See the README.');
|
|
243
|
+
}
|
|
244
|
+
const mod = await this.loadModule(specifier);
|
|
245
|
+
this.client = mod.createClient({
|
|
246
|
+
AccountSid: this.config.AccountSid,
|
|
247
|
+
AuthToken: this.config.AuthToken,
|
|
248
|
+
ApiKeySid: this.config.ApiKeySid,
|
|
249
|
+
ApiKeySecret: this.config.ApiKeySecret,
|
|
250
|
+
StreamUrl: this.config.StreamUrl,
|
|
251
|
+
});
|
|
252
|
+
return this.client;
|
|
253
|
+
}
|
|
254
|
+
/** Binds the active Call SID and (re-)registers any handlers the bridge set before the call existed. */
|
|
255
|
+
bindCall(callId) {
|
|
256
|
+
this.activeCallId = callId;
|
|
257
|
+
const client = this.client;
|
|
258
|
+
if (!client) {
|
|
259
|
+
return;
|
|
260
|
+
}
|
|
261
|
+
if (this.audioHandler) {
|
|
262
|
+
const cb = this.audioHandler;
|
|
263
|
+
client.onAudioFrame((frame) => cb(mapNativeAudioFrame(frame)));
|
|
264
|
+
}
|
|
265
|
+
if (this.dtmfHandler) {
|
|
266
|
+
client.onDtmf(this.dtmfHandler);
|
|
267
|
+
}
|
|
268
|
+
if (this.endedHandler) {
|
|
269
|
+
client.onCallEnded(this.endedHandler);
|
|
270
|
+
}
|
|
271
|
+
}
|
|
272
|
+
}
|
|
273
|
+
/**
|
|
274
|
+
* Builds the {@link import('@memberjunction/ai-bridge-base').TelephonyCallSdkFactory}-shaped factory that
|
|
275
|
+
* constructs a {@link TwilioNativeCallSdk} from the bridge's per-session `Configuration`. Pass the result
|
|
276
|
+
* to `TwilioBridge.SetSdkFactory(...)` so a deployment activates **two-way native Twilio audio** without
|
|
277
|
+
* code changes to the driver.
|
|
278
|
+
*
|
|
279
|
+
* Reads Twilio credentials + stream URL + the native module specifier out of the config map the engine
|
|
280
|
+
* passes at connect (credentials resolved upstream — **never inline secrets**).
|
|
281
|
+
*
|
|
282
|
+
* @example
|
|
283
|
+
* // Where bridge drivers are configured (creds already resolved from the MJ credential system):
|
|
284
|
+
* bridge.SetSdkFactory(BindTwilioNativeCall());
|
|
285
|
+
*
|
|
286
|
+
* @param loadModule Optional native-adapter loader override (tests inject a fake; production omits it).
|
|
287
|
+
* @returns A factory `(config) => TwilioNativeCallSdk`.
|
|
288
|
+
*/
|
|
289
|
+
export function BindTwilioNativeCall(loadModule = defaultNativeLoader) {
|
|
290
|
+
return (config) => new TwilioNativeCallSdk(readNativeConfig(config), loadModule);
|
|
291
|
+
}
|
|
292
|
+
/**
|
|
293
|
+
* Extracts a {@link TwilioNativeSdkConfig} from the engine's loosely-typed `Configuration` map without
|
|
294
|
+
* ever widening to `any`. Each field is read + type-checked individually so a malformed config yields a
|
|
295
|
+
* clean, partially-resolved object (and {@link TwilioNativeCallSdk} then throws a precise error if the
|
|
296
|
+
* required specifier is absent) rather than a half-typed blob.
|
|
297
|
+
*/
|
|
298
|
+
export function readNativeConfig(config) {
|
|
299
|
+
const cfg = config ?? {};
|
|
300
|
+
return {
|
|
301
|
+
AccountSid: readString(cfg.AccountSid),
|
|
302
|
+
AuthToken: readString(cfg.AuthToken),
|
|
303
|
+
ApiKeySid: readString(cfg.ApiKeySid),
|
|
304
|
+
ApiKeySecret: readString(cfg.ApiKeySecret),
|
|
305
|
+
StreamUrl: readString(cfg.StreamUrl),
|
|
306
|
+
NativeModuleSpecifier: readString(cfg.NativeModuleSpecifier),
|
|
307
|
+
};
|
|
308
|
+
}
|
|
309
|
+
/** Reads a value as a non-empty string, or `undefined`. */
|
|
310
|
+
function readString(value) {
|
|
311
|
+
return typeof value === 'string' && value.length > 0 ? value : undefined;
|
|
312
|
+
}
|
|
313
|
+
//# sourceMappingURL=twilio-native-call-sdk.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"twilio-native-call-sdk.js","sourceRoot":"","sources":["../src/twilio-native-call-sdk.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,10 +1,35 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@memberjunction/ai-bridge-twilio",
|
|
3
|
-
"
|
|
4
|
-
"
|
|
5
|
-
"
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
3
|
+
"type": "module",
|
|
4
|
+
"version": "5.42.0",
|
|
5
|
+
"description": "MemberJunction: Twilio Realtime Bridge driver (telephony). Connects the realtime agent engine to a phone call over Twilio Programmable Voice + Media Streams — outbound dial, inbound DID routing, single-party audio in/out, DTMF send/receive, and call transfer — via an injectable telephony call SDK seam. Audio only: no video, no screen, no Meeting Controls.",
|
|
6
|
+
"main": "dist/index.js",
|
|
7
|
+
"types": "dist/index.d.ts",
|
|
8
|
+
"files": [
|
|
9
|
+
"/dist"
|
|
10
|
+
],
|
|
11
|
+
"scripts": {
|
|
12
|
+
"start": "ts-node-dev src/index.ts",
|
|
13
|
+
"build": "tsc && tsc-alias -f",
|
|
14
|
+
"test": "vitest run",
|
|
15
|
+
"test:watch": "vitest"
|
|
16
|
+
},
|
|
17
|
+
"author": "MemberJunction.com",
|
|
18
|
+
"license": "ISC",
|
|
19
|
+
"dependencies": {
|
|
20
|
+
"@memberjunction/core": "5.42.0",
|
|
21
|
+
"@memberjunction/global": "5.42.0",
|
|
22
|
+
"@memberjunction/core-entities": "5.42.0",
|
|
23
|
+
"@memberjunction/ai-bridge-base": "5.42.0"
|
|
24
|
+
},
|
|
25
|
+
"devDependencies": {
|
|
26
|
+
"@types/node": "24.10.11",
|
|
27
|
+
"ts-node-dev": "^2.0.0",
|
|
28
|
+
"typescript": "^5.9.3",
|
|
29
|
+
"vitest": "^4.0.18"
|
|
30
|
+
},
|
|
31
|
+
"repository": {
|
|
32
|
+
"type": "git",
|
|
33
|
+
"url": "https://github.com/MemberJunction/MJ"
|
|
34
|
+
}
|
|
10
35
|
}
|