agentdial 1.0.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.
Files changed (97) hide show
  1. package/CHANGELOG.md +20 -0
  2. package/LICENSE +21 -0
  3. package/README.md +310 -0
  4. package/dist/adapters/discord.d.ts +24 -0
  5. package/dist/adapters/discord.d.ts.map +1 -0
  6. package/dist/adapters/discord.js +129 -0
  7. package/dist/adapters/discord.js.map +1 -0
  8. package/dist/adapters/email.d.ts +38 -0
  9. package/dist/adapters/email.d.ts.map +1 -0
  10. package/dist/adapters/email.js +187 -0
  11. package/dist/adapters/email.js.map +1 -0
  12. package/dist/adapters/index.d.ts +12 -0
  13. package/dist/adapters/index.d.ts.map +1 -0
  14. package/dist/adapters/index.js +36 -0
  15. package/dist/adapters/index.js.map +1 -0
  16. package/dist/adapters/slack.d.ts +27 -0
  17. package/dist/adapters/slack.d.ts.map +1 -0
  18. package/dist/adapters/slack.js +173 -0
  19. package/dist/adapters/slack.js.map +1 -0
  20. package/dist/adapters/telegram.d.ts +28 -0
  21. package/dist/adapters/telegram.d.ts.map +1 -0
  22. package/dist/adapters/telegram.js +155 -0
  23. package/dist/adapters/telegram.js.map +1 -0
  24. package/dist/adapters/twilio-sms.d.ts +36 -0
  25. package/dist/adapters/twilio-sms.d.ts.map +1 -0
  26. package/dist/adapters/twilio-sms.js +187 -0
  27. package/dist/adapters/twilio-sms.js.map +1 -0
  28. package/dist/adapters/twilio-whatsapp.d.ts +37 -0
  29. package/dist/adapters/twilio-whatsapp.d.ts.map +1 -0
  30. package/dist/adapters/twilio-whatsapp.js +188 -0
  31. package/dist/adapters/twilio-whatsapp.js.map +1 -0
  32. package/dist/adapters/types.d.ts +349 -0
  33. package/dist/adapters/types.d.ts.map +1 -0
  34. package/dist/adapters/types.js +82 -0
  35. package/dist/adapters/types.js.map +1 -0
  36. package/dist/adapters/voice.d.ts +54 -0
  37. package/dist/adapters/voice.d.ts.map +1 -0
  38. package/dist/adapters/voice.js +250 -0
  39. package/dist/adapters/voice.js.map +1 -0
  40. package/dist/commands/channels.d.ts +5 -0
  41. package/dist/commands/channels.d.ts.map +1 -0
  42. package/dist/commands/channels.js +188 -0
  43. package/dist/commands/channels.js.map +1 -0
  44. package/dist/commands/mcp-serve.d.ts +14 -0
  45. package/dist/commands/mcp-serve.d.ts.map +1 -0
  46. package/dist/commands/mcp-serve.js +479 -0
  47. package/dist/commands/mcp-serve.js.map +1 -0
  48. package/dist/commands/serve.d.ts +6 -0
  49. package/dist/commands/serve.d.ts.map +1 -0
  50. package/dist/commands/serve.js +128 -0
  51. package/dist/commands/serve.js.map +1 -0
  52. package/dist/commands/setup.d.ts +4 -0
  53. package/dist/commands/setup.d.ts.map +1 -0
  54. package/dist/commands/setup.js +174 -0
  55. package/dist/commands/setup.js.map +1 -0
  56. package/dist/commands/status.d.ts +4 -0
  57. package/dist/commands/status.d.ts.map +1 -0
  58. package/dist/commands/status.js +86 -0
  59. package/dist/commands/status.js.map +1 -0
  60. package/dist/commands/test.d.ts +5 -0
  61. package/dist/commands/test.d.ts.map +1 -0
  62. package/dist/commands/test.js +48 -0
  63. package/dist/commands/test.js.map +1 -0
  64. package/dist/commands/voice.d.ts +6 -0
  65. package/dist/commands/voice.d.ts.map +1 -0
  66. package/dist/commands/voice.js +192 -0
  67. package/dist/commands/voice.js.map +1 -0
  68. package/dist/index.d.ts +3 -0
  69. package/dist/index.d.ts.map +1 -0
  70. package/dist/index.js +119 -0
  71. package/dist/index.js.map +1 -0
  72. package/dist/lib/config.d.ts +7 -0
  73. package/dist/lib/config.d.ts.map +1 -0
  74. package/dist/lib/config.js +36 -0
  75. package/dist/lib/config.js.map +1 -0
  76. package/dist/lib/constants.d.ts +13 -0
  77. package/dist/lib/constants.d.ts.map +1 -0
  78. package/dist/lib/constants.js +52 -0
  79. package/dist/lib/constants.js.map +1 -0
  80. package/dist/lib/credentials.d.ts +7 -0
  81. package/dist/lib/credentials.d.ts.map +1 -0
  82. package/dist/lib/credentials.js +61 -0
  83. package/dist/lib/credentials.js.map +1 -0
  84. package/dist/lib/gateway.d.ts +27 -0
  85. package/dist/lib/gateway.d.ts.map +1 -0
  86. package/dist/lib/gateway.js +103 -0
  87. package/dist/lib/gateway.js.map +1 -0
  88. package/dist/lib/identity.d.ts +5 -0
  89. package/dist/lib/identity.d.ts.map +1 -0
  90. package/dist/lib/identity.js +36 -0
  91. package/dist/lib/identity.js.map +1 -0
  92. package/dist/lib/ui.d.ts +12 -0
  93. package/dist/lib/ui.d.ts.map +1 -0
  94. package/dist/lib/ui.js +91 -0
  95. package/dist/lib/ui.js.map +1 -0
  96. package/package.json +95 -0
  97. package/templates/IDENTITY.md +59 -0
@@ -0,0 +1 @@
1
+ {"version":3,"file":"telegram.js","sourceRoot":"","sources":["../../src/adapters/telegram.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,36 @@
1
+ import type { ChannelAdapter, ChannelConfig, ChannelStatus, GatewayMessage, GatewayResponse } from "./types.js";
2
+ interface TwilioMessagePayload {
3
+ MessageSid: string;
4
+ From: string;
5
+ Body: string;
6
+ NumMedia?: string;
7
+ [key: string]: string | undefined;
8
+ }
9
+ export declare class TwilioSmsAdapter implements ChannelAdapter {
10
+ readonly name: "sms";
11
+ readonly displayName = "SMS (Twilio)";
12
+ readonly free = false;
13
+ readonly cost = "$0.0079/msg";
14
+ readonly setupTime = "5 min";
15
+ private accountSid;
16
+ private authToken;
17
+ private phoneNumber;
18
+ private webhookUrl;
19
+ private messageHandler;
20
+ private connected;
21
+ private lastMessageTs;
22
+ setup(config: ChannelConfig): Promise<void>;
23
+ connect(): Promise<void>;
24
+ disconnect(): Promise<void>;
25
+ send(to: string, response: GatewayResponse): Promise<void>;
26
+ onMessage(handler: (msg: GatewayMessage) => Promise<GatewayResponse>): void;
27
+ /** Call this from your HTTP webhook handler with the parsed Twilio POST body. */
28
+ handleWebhook(payload: TwilioMessagePayload): Promise<string>;
29
+ test(): Promise<{
30
+ ok: boolean;
31
+ error?: string;
32
+ }>;
33
+ status(): Promise<ChannelStatus>;
34
+ }
35
+ export {};
36
+ //# sourceMappingURL=twilio-sms.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"twilio-sms.d.ts","sourceRoot":"","sources":["../../src/adapters/twilio-sms.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EACV,cAAc,EACd,aAAa,EACb,aAAa,EACb,cAAc,EACd,eAAe,EAChB,MAAM,YAAY,CAAC;AAEpB,UAAU,oBAAoB;IAC5B,UAAU,EAAE,MAAM,CAAC;IACnB,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAAC;CACnC;AAoCD,qBAAa,gBAAiB,YAAW,cAAc;IACrD,QAAQ,CAAC,IAAI,EAAG,KAAK,CAAU;IAC/B,QAAQ,CAAC,WAAW,kBAAkB;IACtC,QAAQ,CAAC,IAAI,SAAS;IACtB,QAAQ,CAAC,IAAI,iBAAiB;IAC9B,QAAQ,CAAC,SAAS,WAAW;IAE7B,OAAO,CAAC,UAAU,CAAM;IACxB,OAAO,CAAC,SAAS,CAAM;IACvB,OAAO,CAAC,WAAW,CAAM;IACzB,OAAO,CAAC,UAAU,CAAM;IACxB,OAAO,CAAC,cAAc,CAEN;IAChB,OAAO,CAAC,SAAS,CAAS;IAC1B,OAAO,CAAC,aAAa,CAAuB;IAEtC,KAAK,CAAC,MAAM,EAAE,aAAa,GAAG,OAAO,CAAC,IAAI,CAAC;IAyB3C,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC;IAqBxB,UAAU,IAAI,OAAO,CAAC,IAAI,CAAC;IAI3B,IAAI,CAAC,EAAE,EAAE,MAAM,EAAE,QAAQ,EAAE,eAAe,GAAG,OAAO,CAAC,IAAI,CAAC;IA8BhE,SAAS,CAAC,OAAO,EAAE,CAAC,GAAG,EAAE,cAAc,KAAK,OAAO,CAAC,eAAe,CAAC,GAAG,IAAI;IAI3E,iFAAiF;IAC3E,aAAa,CAAC,OAAO,EAAE,oBAAoB,GAAG,OAAO,CAAC,MAAM,CAAC;IAmB7D,IAAI,IAAI,OAAO,CAAC;QAAE,EAAE,EAAE,OAAO,CAAC;QAAC,KAAK,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;IAYhD,MAAM,IAAI,OAAO,CAAC,aAAa,CAAC;CAqBvC"}
@@ -0,0 +1,187 @@
1
+ import { getCredential } from "../lib/credentials.js";
2
+ function basicAuth(sid, token) {
3
+ return `Basic ${Buffer.from(`${sid}:${token}`).toString("base64")}`;
4
+ }
5
+ async function twilioFetch(sid, token, path, options = {}) {
6
+ const url = `https://api.twilio.com/2010-04-01/Accounts/${sid}${path}`;
7
+ const res = await fetch(url, {
8
+ ...options,
9
+ headers: {
10
+ Authorization: basicAuth(sid, token),
11
+ "Content-Type": "application/x-www-form-urlencoded",
12
+ ...options.headers,
13
+ },
14
+ });
15
+ if (!res.ok) {
16
+ const text = await res.text();
17
+ throw new Error(`Twilio API ${res.status}: ${text}`);
18
+ }
19
+ return res.json();
20
+ }
21
+ export class TwilioSmsAdapter {
22
+ name = "sms";
23
+ displayName = "SMS (Twilio)";
24
+ free = false;
25
+ cost = "$0.0079/msg";
26
+ setupTime = "5 min";
27
+ accountSid = "";
28
+ authToken = "";
29
+ phoneNumber = "";
30
+ webhookUrl = "";
31
+ messageHandler = null;
32
+ connected = false;
33
+ lastMessageTs = null;
34
+ async setup(config) {
35
+ this.accountSid =
36
+ config.credentials?.account_sid ??
37
+ (await getCredential("sms", "account_sid")) ??
38
+ "";
39
+ this.authToken =
40
+ config.credentials?.auth_token ??
41
+ (await getCredential("sms", "auth_token")) ??
42
+ "";
43
+ this.phoneNumber =
44
+ config.credentials?.phone_number ??
45
+ (await getCredential("sms", "phone_number")) ??
46
+ "";
47
+ this.webhookUrl = config.webhookUrl ?? "";
48
+ if (!this.accountSid || !this.authToken || !this.phoneNumber) {
49
+ throw new Error("Twilio SMS requires account_sid, auth_token, and phone_number");
50
+ }
51
+ // Validate credentials by fetching account info
52
+ await twilioFetch(this.accountSid, this.authToken, ".json");
53
+ }
54
+ async connect() {
55
+ // Webhook-based — no persistent connection needed.
56
+ // If webhookUrl is set, update the phone number's SMS URL.
57
+ if (this.webhookUrl) {
58
+ try {
59
+ const params = new URLSearchParams({
60
+ SmsUrl: this.webhookUrl,
61
+ SmsMethod: "POST",
62
+ });
63
+ await twilioFetch(this.accountSid, this.authToken, `/IncomingPhoneNumbers.json?PhoneNumber=${encodeURIComponent(this.phoneNumber)}`);
64
+ }
65
+ catch {
66
+ // Non-fatal — webhook can be configured manually in Twilio console
67
+ }
68
+ }
69
+ this.connected = true;
70
+ }
71
+ async disconnect() {
72
+ this.connected = false;
73
+ }
74
+ async send(to, response) {
75
+ let body = response.text;
76
+ if (response.cards?.length) {
77
+ for (const card of response.cards) {
78
+ body += `\n\n*${card.title}*`;
79
+ if (card.description)
80
+ body += `\n${card.description}`;
81
+ }
82
+ }
83
+ if (response.actions?.length) {
84
+ body += "\n\nOptions:";
85
+ for (const action of response.actions) {
86
+ body +=
87
+ action.type === "url"
88
+ ? `\n- ${action.label}: ${action.value}`
89
+ : `\n- Reply "${action.value}" for ${action.label}`;
90
+ }
91
+ }
92
+ const params = new URLSearchParams({
93
+ To: to,
94
+ From: this.phoneNumber,
95
+ Body: body,
96
+ });
97
+ await twilioFetch(this.accountSid, this.authToken, "/Messages.json", {
98
+ method: "POST",
99
+ body: params.toString(),
100
+ });
101
+ }
102
+ onMessage(handler) {
103
+ this.messageHandler = handler;
104
+ }
105
+ /** Call this from your HTTP webhook handler with the parsed Twilio POST body. */
106
+ async handleWebhook(payload) {
107
+ this.lastMessageTs = Date.now();
108
+ const msg = {
109
+ id: payload.MessageSid,
110
+ channel: "sms",
111
+ from: payload.From,
112
+ text: payload.Body ?? "",
113
+ timestamp: Date.now(),
114
+ attachments: parseMediaAttachments(payload),
115
+ };
116
+ if (!this.messageHandler) {
117
+ return "<Response><Message>No handler configured</Message></Response>";
118
+ }
119
+ const response = await this.messageHandler(msg);
120
+ return `<Response><Message>${escapeXml(response.text)}</Message></Response>`;
121
+ }
122
+ async test() {
123
+ try {
124
+ await twilioFetch(this.accountSid, this.authToken, ".json");
125
+ return { ok: true };
126
+ }
127
+ catch (err) {
128
+ return {
129
+ ok: false,
130
+ error: err instanceof Error ? err.message : "Unknown error",
131
+ };
132
+ }
133
+ }
134
+ async status() {
135
+ const start = Date.now();
136
+ try {
137
+ await twilioFetch(this.accountSid, this.authToken, ".json");
138
+ return {
139
+ channel: "sms",
140
+ connected: this.connected,
141
+ latencyMs: Date.now() - start,
142
+ lastMessage: this.lastMessageTs,
143
+ error: null,
144
+ };
145
+ }
146
+ catch (err) {
147
+ return {
148
+ channel: "sms",
149
+ connected: false,
150
+ latencyMs: Date.now() - start,
151
+ lastMessage: this.lastMessageTs,
152
+ error: err instanceof Error ? err.message : "Unknown error",
153
+ };
154
+ }
155
+ }
156
+ }
157
+ function parseMediaAttachments(payload) {
158
+ const count = parseInt(payload.NumMedia ?? "0", 10);
159
+ if (count === 0)
160
+ return undefined;
161
+ const attachments = [];
162
+ for (let i = 0; i < count; i++) {
163
+ const url = payload[`MediaUrl${i}`];
164
+ const mime = payload[`MediaContentType${i}`];
165
+ if (url) {
166
+ attachments.push({
167
+ type: mime?.startsWith("image/")
168
+ ? "image"
169
+ : mime?.startsWith("audio/")
170
+ ? "audio"
171
+ : mime?.startsWith("video/")
172
+ ? "video"
173
+ : "file",
174
+ url,
175
+ mimeType: mime ?? undefined,
176
+ });
177
+ }
178
+ }
179
+ return attachments.length > 0 ? attachments : undefined;
180
+ }
181
+ function escapeXml(text) {
182
+ return text
183
+ .replace(/&/g, "&amp;")
184
+ .replace(/</g, "&lt;")
185
+ .replace(/>/g, "&gt;");
186
+ }
187
+ //# sourceMappingURL=twilio-sms.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"twilio-sms.js","sourceRoot":"","sources":["../../src/adapters/twilio-sms.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,37 @@
1
+ import type { ChannelAdapter, ChannelConfig, ChannelStatus, GatewayMessage, GatewayResponse } from "./types.js";
2
+ interface WhatsAppWebhookPayload {
3
+ MessageSid: string;
4
+ From: string;
5
+ Body: string;
6
+ ProfileName?: string;
7
+ NumMedia?: string;
8
+ [key: string]: string | undefined;
9
+ }
10
+ export declare class TwilioWhatsAppAdapter implements ChannelAdapter {
11
+ readonly name: "whatsapp";
12
+ readonly displayName = "WhatsApp (Twilio)";
13
+ readonly free = false;
14
+ readonly cost = "$0.005/msg + Meta fees";
15
+ readonly setupTime = "10 min";
16
+ private accountSid;
17
+ private authToken;
18
+ private phoneNumber;
19
+ private webhookUrl;
20
+ private messageHandler;
21
+ private connected;
22
+ private lastMessageTs;
23
+ setup(config: ChannelConfig): Promise<void>;
24
+ connect(): Promise<void>;
25
+ disconnect(): Promise<void>;
26
+ send(to: string, response: GatewayResponse): Promise<void>;
27
+ onMessage(handler: (msg: GatewayMessage) => Promise<GatewayResponse>): void;
28
+ /** Call from HTTP webhook handler with parsed Twilio WhatsApp POST body. */
29
+ handleWebhook(payload: WhatsAppWebhookPayload): Promise<string>;
30
+ test(): Promise<{
31
+ ok: boolean;
32
+ error?: string;
33
+ }>;
34
+ status(): Promise<ChannelStatus>;
35
+ }
36
+ export {};
37
+ //# sourceMappingURL=twilio-whatsapp.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"twilio-whatsapp.d.ts","sourceRoot":"","sources":["../../src/adapters/twilio-whatsapp.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EACV,cAAc,EACd,aAAa,EACb,aAAa,EACb,cAAc,EACd,eAAe,EAChB,MAAM,YAAY,CAAC;AAEpB,UAAU,sBAAsB;IAC9B,UAAU,EAAE,MAAM,CAAC;IACnB,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAAC;CACnC;AA2CD,qBAAa,qBAAsB,YAAW,cAAc;IAC1D,QAAQ,CAAC,IAAI,EAAG,UAAU,CAAU;IACpC,QAAQ,CAAC,WAAW,uBAAuB;IAC3C,QAAQ,CAAC,IAAI,SAAS;IACtB,QAAQ,CAAC,IAAI,4BAA4B;IACzC,QAAQ,CAAC,SAAS,YAAY;IAE9B,OAAO,CAAC,UAAU,CAAM;IACxB,OAAO,CAAC,SAAS,CAAM;IACvB,OAAO,CAAC,WAAW,CAAM;IACzB,OAAO,CAAC,UAAU,CAAM;IACxB,OAAO,CAAC,cAAc,CAEN;IAChB,OAAO,CAAC,SAAS,CAAS;IAC1B,OAAO,CAAC,aAAa,CAAuB;IAEtC,KAAK,CAAC,MAAM,EAAE,aAAa,GAAG,OAAO,CAAC,IAAI,CAAC;IA6B3C,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC;IAMxB,UAAU,IAAI,OAAO,CAAC,IAAI,CAAC;IAI3B,IAAI,CAAC,EAAE,EAAE,MAAM,EAAE,QAAQ,EAAE,eAAe,GAAG,OAAO,CAAC,IAAI,CAAC;IA6BhE,SAAS,CAAC,OAAO,EAAE,CAAC,GAAG,EAAE,cAAc,KAAK,OAAO,CAAC,eAAe,CAAC,GAAG,IAAI;IAI3E,4EAA4E;IACtE,aAAa,CAAC,OAAO,EAAE,sBAAsB,GAAG,OAAO,CAAC,MAAM,CAAC;IAsB/D,IAAI,IAAI,OAAO,CAAC;QAAE,EAAE,EAAE,OAAO,CAAC;QAAC,KAAK,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;IAahD,MAAM,IAAI,OAAO,CAAC,aAAa,CAAC;CAqBvC"}
@@ -0,0 +1,188 @@
1
+ import { getCredential } from "../lib/credentials.js";
2
+ function basicAuth(sid, token) {
3
+ return `Basic ${Buffer.from(`${sid}:${token}`).toString("base64")}`;
4
+ }
5
+ async function twilioFetch(sid, token, path, options = {}) {
6
+ const url = `https://api.twilio.com/2010-04-01/Accounts/${sid}${path}`;
7
+ const res = await fetch(url, {
8
+ ...options,
9
+ headers: {
10
+ Authorization: basicAuth(sid, token),
11
+ "Content-Type": "application/x-www-form-urlencoded",
12
+ ...options.headers,
13
+ },
14
+ });
15
+ if (!res.ok) {
16
+ const text = await res.text();
17
+ throw new Error(`Twilio API ${res.status}: ${text}`);
18
+ }
19
+ return res.json();
20
+ }
21
+ function ensureWhatsAppPrefix(number) {
22
+ return number.startsWith("whatsapp:") ? number : `whatsapp:${number}`;
23
+ }
24
+ function stripWhatsAppPrefix(number) {
25
+ return number.startsWith("whatsapp:") ? number.slice(9) : number;
26
+ }
27
+ export class TwilioWhatsAppAdapter {
28
+ name = "whatsapp";
29
+ displayName = "WhatsApp (Twilio)";
30
+ free = false;
31
+ cost = "$0.005/msg + Meta fees";
32
+ setupTime = "10 min";
33
+ accountSid = "";
34
+ authToken = "";
35
+ phoneNumber = "";
36
+ webhookUrl = "";
37
+ messageHandler = null;
38
+ connected = false;
39
+ lastMessageTs = null;
40
+ async setup(config) {
41
+ // WhatsApp shares Twilio creds — check whatsapp first, fall back to sms
42
+ this.accountSid =
43
+ config.credentials?.account_sid ??
44
+ (await getCredential("whatsapp", "account_sid")) ??
45
+ (await getCredential("sms", "account_sid")) ??
46
+ "";
47
+ this.authToken =
48
+ config.credentials?.auth_token ??
49
+ (await getCredential("whatsapp", "auth_token")) ??
50
+ (await getCredential("sms", "auth_token")) ??
51
+ "";
52
+ this.phoneNumber =
53
+ config.credentials?.phone_number ??
54
+ (await getCredential("whatsapp", "phone_number")) ??
55
+ (await getCredential("sms", "phone_number")) ??
56
+ "";
57
+ this.webhookUrl = config.webhookUrl ?? "";
58
+ if (!this.accountSid || !this.authToken || !this.phoneNumber) {
59
+ throw new Error("Twilio WhatsApp requires account_sid, auth_token, and phone_number");
60
+ }
61
+ // Validate credentials
62
+ await twilioFetch(this.accountSid, this.authToken, ".json");
63
+ }
64
+ async connect() {
65
+ // WhatsApp is webhook-based through Twilio sandbox or production sender.
66
+ // Webhook URL is configured in the Twilio console or via API.
67
+ this.connected = true;
68
+ }
69
+ async disconnect() {
70
+ this.connected = false;
71
+ }
72
+ async send(to, response) {
73
+ let body = response.text;
74
+ if (response.cards?.length) {
75
+ for (const card of response.cards) {
76
+ body += `\n\n*${card.title}*`;
77
+ if (card.description)
78
+ body += `\n${card.description}`;
79
+ if (card.actions?.length) {
80
+ for (const action of card.actions) {
81
+ body +=
82
+ action.type === "url"
83
+ ? `\n${action.label}: ${action.value}`
84
+ : `\n> ${action.label}`;
85
+ }
86
+ }
87
+ }
88
+ }
89
+ const params = new URLSearchParams({
90
+ To: ensureWhatsAppPrefix(to),
91
+ From: ensureWhatsAppPrefix(this.phoneNumber),
92
+ Body: body,
93
+ });
94
+ await twilioFetch(this.accountSid, this.authToken, "/Messages.json", {
95
+ method: "POST",
96
+ body: params.toString(),
97
+ });
98
+ }
99
+ onMessage(handler) {
100
+ this.messageHandler = handler;
101
+ }
102
+ /** Call from HTTP webhook handler with parsed Twilio WhatsApp POST body. */
103
+ async handleWebhook(payload) {
104
+ this.lastMessageTs = Date.now();
105
+ const msg = {
106
+ id: payload.MessageSid,
107
+ channel: "whatsapp",
108
+ from: stripWhatsAppPrefix(payload.From),
109
+ text: payload.Body ?? "",
110
+ timestamp: Date.now(),
111
+ attachments: parseMediaAttachments(payload),
112
+ metadata: payload.ProfileName
113
+ ? { profileName: payload.ProfileName }
114
+ : undefined,
115
+ };
116
+ if (!this.messageHandler) {
117
+ return "<Response><Message>No handler configured</Message></Response>";
118
+ }
119
+ const response = await this.messageHandler(msg);
120
+ return `<Response><Message>${escapeXml(response.text)}</Message></Response>`;
121
+ }
122
+ async test() {
123
+ try {
124
+ await twilioFetch(this.accountSid, this.authToken, ".json");
125
+ // Verify the number can send WhatsApp by checking messaging service
126
+ return { ok: true };
127
+ }
128
+ catch (err) {
129
+ return {
130
+ ok: false,
131
+ error: err instanceof Error ? err.message : "Unknown error",
132
+ };
133
+ }
134
+ }
135
+ async status() {
136
+ const start = Date.now();
137
+ try {
138
+ await twilioFetch(this.accountSid, this.authToken, ".json");
139
+ return {
140
+ channel: "whatsapp",
141
+ connected: this.connected,
142
+ latencyMs: Date.now() - start,
143
+ lastMessage: this.lastMessageTs,
144
+ error: null,
145
+ };
146
+ }
147
+ catch (err) {
148
+ return {
149
+ channel: "whatsapp",
150
+ connected: false,
151
+ latencyMs: Date.now() - start,
152
+ lastMessage: this.lastMessageTs,
153
+ error: err instanceof Error ? err.message : "Unknown error",
154
+ };
155
+ }
156
+ }
157
+ }
158
+ function parseMediaAttachments(payload) {
159
+ const count = parseInt(payload.NumMedia ?? "0", 10);
160
+ if (count === 0)
161
+ return undefined;
162
+ const attachments = [];
163
+ for (let i = 0; i < count; i++) {
164
+ const url = payload[`MediaUrl${i}`];
165
+ const mime = payload[`MediaContentType${i}`];
166
+ if (url) {
167
+ attachments.push({
168
+ type: mime?.startsWith("image/")
169
+ ? "image"
170
+ : mime?.startsWith("audio/")
171
+ ? "audio"
172
+ : mime?.startsWith("video/")
173
+ ? "video"
174
+ : "file",
175
+ url,
176
+ mimeType: mime ?? undefined,
177
+ });
178
+ }
179
+ }
180
+ return attachments.length > 0 ? attachments : undefined;
181
+ }
182
+ function escapeXml(text) {
183
+ return text
184
+ .replace(/&/g, "&amp;")
185
+ .replace(/</g, "&lt;")
186
+ .replace(/>/g, "&gt;");
187
+ }
188
+ //# sourceMappingURL=twilio-whatsapp.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"twilio-whatsapp.js","sourceRoot":"","sources":["../../src/adapters/twilio-whatsapp.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,uBAAuB,CAAC;AAyBtD,SAAS,SAAS,CAAC,GAAW,EAAE,KAAa;IAC3C,OAAO,SAAS,MAAM,CAAC,IAAI,CAAC,GAAG,GAAG,IAAI,KAAK,EAAE,CAAC,CAAC,QAAQ,CAAC,QAAQ,CAAC,EAAE,CAAC;AACtE,CAAC;AAED,KAAK,UAAU,WAAW,CACxB,GAAW,EACX,KAAa,EACb,IAAY,EACZ,UAAuB,EAAE;IAEzB,MAAM,GAAG,GAAG,8CAA8C,GAAG,GAAG,IAAI,EAAE,CAAC;IACvE,MAAM,GAAG,GAAG,MAAM,KAAK,CAAC,GAAG,EAAE;QAC3B,GAAG,OAAO;QACV,OAAO,EAAE;YACP,aAAa,EAAE,SAAS,CAAC,GAAG,EAAE,KAAK,CAAC;YACpC,cAAc,EAAE,mCAAmC;YACnD,GAAG,OAAO,CAAC,OAAO;SACnB;KACF,CAAC,CAAC;IACH,IAAI,CAAC,GAAG,CAAC,EAAE,EAAE,CAAC;QACZ,MAAM,IAAI,GAAG,MAAM,GAAG,CAAC,IAAI,EAAE,CAAC;QAC9B,MAAM,IAAI,KAAK,CAAC,cAAc,GAAG,CAAC,MAAM,KAAK,IAAI,EAAE,CAAC,CAAC;IACvD,CAAC;IACD,OAAO,GAAG,CAAC,IAAI,EAAgC,CAAC;AAClD,CAAC;AAED,SAAS,oBAAoB,CAAC,MAAc;IAC1C,OAAO,MAAM,CAAC,UAAU,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,YAAY,MAAM,EAAE,CAAC;AACxE,CAAC;AAED,SAAS,mBAAmB,CAAC,MAAc;IACzC,OAAO,MAAM,CAAC,UAAU,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC;AACnE,CAAC;AAED,MAAM,OAAO,qBAAqB;IACvB,IAAI,GAAG,UAAmB,CAAC;IAC3B,WAAW,GAAG,mBAAmB,CAAC;IAClC,IAAI,GAAG,KAAK,CAAC;IACb,IAAI,GAAG,wBAAwB,CAAC;IAChC,SAAS,GAAG,QAAQ,CAAC;IAEtB,UAAU,GAAG,EAAE,CAAC;IAChB,SAAS,GAAG,EAAE,CAAC;IACf,WAAW,GAAG,EAAE,CAAC;IACjB,UAAU,GAAG,EAAE,CAAC;IAChB,cAAc,GAEX,IAAI,CAAC;IACR,SAAS,GAAG,KAAK,CAAC;IAClB,aAAa,GAAkB,IAAI,CAAC;IAE5C,KAAK,CAAC,KAAK,CAAC,MAAqB;QAC/B,wEAAwE;QACxE,IAAI,CAAC,UAAU;YACb,MAAM,CAAC,WAAW,EAAE,WAAW;gBAC/B,CAAC,MAAM,aAAa,CAAC,UAAU,EAAE,aAAa,CAAC,CAAC;gBAChD,CAAC,MAAM,aAAa,CAAC,KAAK,EAAE,aAAa,CAAC,CAAC;gBAC3C,EAAE,CAAC;QACL,IAAI,CAAC,SAAS;YACZ,MAAM,CAAC,WAAW,EAAE,UAAU;gBAC9B,CAAC,MAAM,aAAa,CAAC,UAAU,EAAE,YAAY,CAAC,CAAC;gBAC/C,CAAC,MAAM,aAAa,CAAC,KAAK,EAAE,YAAY,CAAC,CAAC;gBAC1C,EAAE,CAAC;QACL,IAAI,CAAC,WAAW;YACd,MAAM,CAAC,WAAW,EAAE,YAAY;gBAChC,CAAC,MAAM,aAAa,CAAC,UAAU,EAAE,cAAc,CAAC,CAAC;gBACjD,CAAC,MAAM,aAAa,CAAC,KAAK,EAAE,cAAc,CAAC,CAAC;gBAC5C,EAAE,CAAC;QACL,IAAI,CAAC,UAAU,GAAG,MAAM,CAAC,UAAU,IAAI,EAAE,CAAC;QAE1C,IAAI,CAAC,IAAI,CAAC,UAAU,IAAI,CAAC,IAAI,CAAC,SAAS,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE,CAAC;YAC7D,MAAM,IAAI,KAAK,CACb,oEAAoE,CACrE,CAAC;QACJ,CAAC;QAED,uBAAuB;QACvB,MAAM,WAAW,CAAC,IAAI,CAAC,UAAU,EAAE,IAAI,CAAC,SAAS,EAAE,OAAO,CAAC,CAAC;IAC9D,CAAC;IAED,KAAK,CAAC,OAAO;QACX,yEAAyE;QACzE,8DAA8D;QAC9D,IAAI,CAAC,SAAS,GAAG,IAAI,CAAC;IACxB,CAAC;IAED,KAAK,CAAC,UAAU;QACd,IAAI,CAAC,SAAS,GAAG,KAAK,CAAC;IACzB,CAAC;IAED,KAAK,CAAC,IAAI,CAAC,EAAU,EAAE,QAAyB;QAC9C,IAAI,IAAI,GAAG,QAAQ,CAAC,IAAI,CAAC;QACzB,IAAI,QAAQ,CAAC,KAAK,EAAE,MAAM,EAAE,CAAC;YAC3B,KAAK,MAAM,IAAI,IAAI,QAAQ,CAAC,KAAK,EAAE,CAAC;gBAClC,IAAI,IAAI,QAAQ,IAAI,CAAC,KAAK,GAAG,CAAC;gBAC9B,IAAI,IAAI,CAAC,WAAW;oBAAE,IAAI,IAAI,KAAK,IAAI,CAAC,WAAW,EAAE,CAAC;gBACtD,IAAI,IAAI,CAAC,OAAO,EAAE,MAAM,EAAE,CAAC;oBACzB,KAAK,MAAM,MAAM,IAAI,IAAI,CAAC,OAAO,EAAE,CAAC;wBAClC,IAAI;4BACF,MAAM,CAAC,IAAI,KAAK,KAAK;gCACnB,CAAC,CAAC,KAAK,MAAM,CAAC,KAAK,KAAK,MAAM,CAAC,KAAK,EAAE;gCACtC,CAAC,CAAC,OAAO,MAAM,CAAC,KAAK,EAAE,CAAC;oBAC9B,CAAC;gBACH,CAAC;YACH,CAAC;QACH,CAAC;QAED,MAAM,MAAM,GAAG,IAAI,eAAe,CAAC;YACjC,EAAE,EAAE,oBAAoB,CAAC,EAAE,CAAC;YAC5B,IAAI,EAAE,oBAAoB,CAAC,IAAI,CAAC,WAAW,CAAC;YAC5C,IAAI,EAAE,IAAI;SACX,CAAC,CAAC;QAEH,MAAM,WAAW,CAAC,IAAI,CAAC,UAAU,EAAE,IAAI,CAAC,SAAS,EAAE,gBAAgB,EAAE;YACnE,MAAM,EAAE,MAAM;YACd,IAAI,EAAE,MAAM,CAAC,QAAQ,EAAE;SACxB,CAAC,CAAC;IACL,CAAC;IAED,SAAS,CAAC,OAA0D;QAClE,IAAI,CAAC,cAAc,GAAG,OAAO,CAAC;IAChC,CAAC;IAED,4EAA4E;IAC5E,KAAK,CAAC,aAAa,CAAC,OAA+B;QACjD,IAAI,CAAC,aAAa,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;QAChC,MAAM,GAAG,GAAmB;YAC1B,EAAE,EAAE,OAAO,CAAC,UAAU;YACtB,OAAO,EAAE,UAAU;YACnB,IAAI,EAAE,mBAAmB,CAAC,OAAO,CAAC,IAAI,CAAC;YACvC,IAAI,EAAE,OAAO,CAAC,IAAI,IAAI,EAAE;YACxB,SAAS,EAAE,IAAI,CAAC,GAAG,EAAE;YACrB,WAAW,EAAE,qBAAqB,CAAC,OAAO,CAAC;YAC3C,QAAQ,EAAE,OAAO,CAAC,WAAW;gBAC3B,CAAC,CAAC,EAAE,WAAW,EAAE,OAAO,CAAC,WAAW,EAAE;gBACtC,CAAC,CAAC,SAAS;SACd,CAAC;QAEF,IAAI,CAAC,IAAI,CAAC,cAAc,EAAE,CAAC;YACzB,OAAO,+DAA+D,CAAC;QACzE,CAAC;QAED,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,cAAc,CAAC,GAAG,CAAC,CAAC;QAChD,OAAO,sBAAsB,SAAS,CAAC,QAAQ,CAAC,IAAI,CAAC,uBAAuB,CAAC;IAC/E,CAAC;IAED,KAAK,CAAC,IAAI;QACR,IAAI,CAAC;YACH,MAAM,WAAW,CAAC,IAAI,CAAC,UAAU,EAAE,IAAI,CAAC,SAAS,EAAE,OAAO,CAAC,CAAC;YAC5D,oEAAoE;YACpE,OAAO,EAAE,EAAE,EAAE,IAAI,EAAE,CAAC;QACtB,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,OAAO;gBACL,EAAE,EAAE,KAAK;gBACT,KAAK,EAAE,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,eAAe;aAC5D,CAAC;QACJ,CAAC;IACH,CAAC;IAED,KAAK,CAAC,MAAM;QACV,MAAM,KAAK,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;QACzB,IAAI,CAAC;YACH,MAAM,WAAW,CAAC,IAAI,CAAC,UAAU,EAAE,IAAI,CAAC,SAAS,EAAE,OAAO,CAAC,CAAC;YAC5D,OAAO;gBACL,OAAO,EAAE,UAAU;gBACnB,SAAS,EAAE,IAAI,CAAC,SAAS;gBACzB,SAAS,EAAE,IAAI,CAAC,GAAG,EAAE,GAAG,KAAK;gBAC7B,WAAW,EAAE,IAAI,CAAC,aAAa;gBAC/B,KAAK,EAAE,IAAI;aACZ,CAAC;QACJ,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,OAAO;gBACL,OAAO,EAAE,UAAU;gBACnB,SAAS,EAAE,KAAK;gBAChB,SAAS,EAAE,IAAI,CAAC,GAAG,EAAE,GAAG,KAAK;gBAC7B,WAAW,EAAE,IAAI,CAAC,aAAa;gBAC/B,KAAK,EAAE,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,eAAe;aAC5D,CAAC;QACJ,CAAC;IACH,CAAC;CACF;AAED,SAAS,qBAAqB,CAC5B,OAA+B;IAE/B,MAAM,KAAK,GAAG,QAAQ,CAAC,OAAO,CAAC,QAAQ,IAAI,GAAG,EAAE,EAAE,CAAC,CAAC;IACpD,IAAI,KAAK,KAAK,CAAC;QAAE,OAAO,SAAS,CAAC;IAClC,MAAM,WAAW,GAA+C,EAAE,CAAC;IACnE,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,KAAK,EAAE,CAAC,EAAE,EAAE,CAAC;QAC/B,MAAM,GAAG,GAAG,OAAO,CAAC,WAAW,CAAC,EAAE,CAAC,CAAC;QACpC,MAAM,IAAI,GAAG,OAAO,CAAC,mBAAmB,CAAC,EAAE,CAAC,CAAC;QAC7C,IAAI,GAAG,EAAE,CAAC;YACR,WAAW,CAAC,IAAI,CAAC;gBACf,IAAI,EAAE,IAAI,EAAE,UAAU,CAAC,QAAQ,CAAC;oBAC9B,CAAC,CAAC,OAAO;oBACT,CAAC,CAAC,IAAI,EAAE,UAAU,CAAC,QAAQ,CAAC;wBAC1B,CAAC,CAAC,OAAO;wBACT,CAAC,CAAC,IAAI,EAAE,UAAU,CAAC,QAAQ,CAAC;4BAC1B,CAAC,CAAC,OAAO;4BACT,CAAC,CAAC,MAAM;gBACd,GAAG;gBACH,QAAQ,EAAE,IAAI,IAAI,SAAS;aAC5B,CAAC,CAAC;QACL,CAAC;IACH,CAAC;IACD,OAAO,WAAW,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC,SAAS,CAAC;AAC1D,CAAC;AAED,SAAS,SAAS,CAAC,IAAY;IAC7B,OAAO,IAAI;SACR,OAAO,CAAC,IAAI,EAAE,OAAO,CAAC;SACtB,OAAO,CAAC,IAAI,EAAE,MAAM,CAAC;SACrB,OAAO,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC;AAC3B,CAAC"}