@framers/agentos 0.1.111 → 0.1.113

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 (119) hide show
  1. package/dist/api/strategies/debate.d.ts +12 -1
  2. package/dist/api/strategies/debate.d.ts.map +1 -1
  3. package/dist/api/strategies/debate.js +41 -5
  4. package/dist/api/strategies/debate.js.map +1 -1
  5. package/dist/api/strategies/hierarchical.d.ts +15 -1
  6. package/dist/api/strategies/hierarchical.d.ts.map +1 -1
  7. package/dist/api/strategies/hierarchical.js +51 -7
  8. package/dist/api/strategies/hierarchical.js.map +1 -1
  9. package/dist/api/strategies/index.d.ts +26 -4
  10. package/dist/api/strategies/index.d.ts.map +1 -1
  11. package/dist/api/strategies/index.js +26 -4
  12. package/dist/api/strategies/index.js.map +1 -1
  13. package/dist/api/strategies/parallel.d.ts +15 -4
  14. package/dist/api/strategies/parallel.d.ts.map +1 -1
  15. package/dist/api/strategies/parallel.js +53 -16
  16. package/dist/api/strategies/parallel.js.map +1 -1
  17. package/dist/api/strategies/review-loop.d.ts +15 -1
  18. package/dist/api/strategies/review-loop.d.ts.map +1 -1
  19. package/dist/api/strategies/review-loop.js +36 -10
  20. package/dist/api/strategies/review-loop.js.map +1 -1
  21. package/dist/api/strategies/sequential.d.ts +11 -1
  22. package/dist/api/strategies/sequential.d.ts.map +1 -1
  23. package/dist/api/strategies/sequential.js +39 -8
  24. package/dist/api/strategies/sequential.js.map +1 -1
  25. package/dist/api/strategies/shared.d.ts +71 -7
  26. package/dist/api/strategies/shared.d.ts.map +1 -1
  27. package/dist/api/strategies/shared.js +89 -10
  28. package/dist/api/strategies/shared.js.map +1 -1
  29. package/dist/api/types.d.ts +54 -1
  30. package/dist/api/types.d.ts.map +1 -1
  31. package/dist/api/types.js.map +1 -1
  32. package/dist/memory/facade/Memory.d.ts.map +1 -1
  33. package/dist/memory/facade/Memory.js +8 -0
  34. package/dist/memory/facade/Memory.js.map +1 -1
  35. package/dist/memory/facade/types.d.ts +10 -0
  36. package/dist/memory/facade/types.d.ts.map +1 -1
  37. package/dist/memory/index.d.ts +6 -0
  38. package/dist/memory/index.d.ts.map +1 -1
  39. package/dist/memory/index.js +5 -0
  40. package/dist/memory/index.js.map +1 -1
  41. package/dist/memory/observation/MemoryObserver.d.ts +63 -1
  42. package/dist/memory/observation/MemoryObserver.d.ts.map +1 -1
  43. package/dist/memory/observation/MemoryObserver.js +115 -4
  44. package/dist/memory/observation/MemoryObserver.js.map +1 -1
  45. package/dist/memory/observation/ObservationCompressor.d.ts +88 -0
  46. package/dist/memory/observation/ObservationCompressor.d.ts.map +1 -0
  47. package/dist/memory/observation/ObservationCompressor.js +207 -0
  48. package/dist/memory/observation/ObservationCompressor.js.map +1 -0
  49. package/dist/memory/observation/ObservationReflector.d.ts +82 -0
  50. package/dist/memory/observation/ObservationReflector.d.ts.map +1 -0
  51. package/dist/memory/observation/ObservationReflector.js +212 -0
  52. package/dist/memory/observation/ObservationReflector.js.map +1 -0
  53. package/dist/memory/observation/temporal.d.ts +54 -0
  54. package/dist/memory/observation/temporal.d.ts.map +1 -0
  55. package/dist/memory/observation/temporal.js +115 -0
  56. package/dist/memory/observation/temporal.js.map +1 -0
  57. package/dist/orchestration/builders/VoiceNodeBuilder.d.ts +82 -25
  58. package/dist/orchestration/builders/VoiceNodeBuilder.d.ts.map +1 -1
  59. package/dist/orchestration/builders/VoiceNodeBuilder.js +86 -26
  60. package/dist/orchestration/builders/VoiceNodeBuilder.js.map +1 -1
  61. package/dist/orchestration/events/GraphEvent.d.ts +67 -5
  62. package/dist/orchestration/events/GraphEvent.d.ts.map +1 -1
  63. package/dist/orchestration/events/GraphEvent.js.map +1 -1
  64. package/dist/orchestration/runtime/VoiceNodeExecutor.d.ts +102 -25
  65. package/dist/orchestration/runtime/VoiceNodeExecutor.d.ts.map +1 -1
  66. package/dist/orchestration/runtime/VoiceNodeExecutor.js +133 -38
  67. package/dist/orchestration/runtime/VoiceNodeExecutor.js.map +1 -1
  68. package/dist/orchestration/runtime/VoiceTransportAdapter.d.ts +94 -32
  69. package/dist/orchestration/runtime/VoiceTransportAdapter.d.ts.map +1 -1
  70. package/dist/orchestration/runtime/VoiceTransportAdapter.js +82 -28
  71. package/dist/orchestration/runtime/VoiceTransportAdapter.js.map +1 -1
  72. package/dist/orchestration/runtime/VoiceTurnCollector.d.ts +73 -20
  73. package/dist/orchestration/runtime/VoiceTurnCollector.d.ts.map +1 -1
  74. package/dist/orchestration/runtime/VoiceTurnCollector.js +84 -23
  75. package/dist/orchestration/runtime/VoiceTurnCollector.js.map +1 -1
  76. package/dist/voice/CallManager.d.ts.map +1 -1
  77. package/dist/voice/CallManager.js +9 -1
  78. package/dist/voice/CallManager.js.map +1 -1
  79. package/dist/voice/MediaStreamParser.d.ts +115 -6
  80. package/dist/voice/MediaStreamParser.d.ts.map +1 -1
  81. package/dist/voice/MediaStreamParser.js +44 -0
  82. package/dist/voice/MediaStreamParser.js.map +1 -1
  83. package/dist/voice/TelephonyStreamTransport.d.ts +112 -20
  84. package/dist/voice/TelephonyStreamTransport.d.ts.map +1 -1
  85. package/dist/voice/TelephonyStreamTransport.js +136 -30
  86. package/dist/voice/TelephonyStreamTransport.js.map +1 -1
  87. package/dist/voice/parsers/PlivoMediaStreamParser.d.ts +64 -6
  88. package/dist/voice/parsers/PlivoMediaStreamParser.d.ts.map +1 -1
  89. package/dist/voice/parsers/PlivoMediaStreamParser.js +67 -6
  90. package/dist/voice/parsers/PlivoMediaStreamParser.js.map +1 -1
  91. package/dist/voice/parsers/TelnyxMediaStreamParser.d.ts +55 -8
  92. package/dist/voice/parsers/TelnyxMediaStreamParser.d.ts.map +1 -1
  93. package/dist/voice/parsers/TelnyxMediaStreamParser.js +60 -9
  94. package/dist/voice/parsers/TelnyxMediaStreamParser.js.map +1 -1
  95. package/dist/voice/parsers/TwilioMediaStreamParser.d.ts +73 -11
  96. package/dist/voice/parsers/TwilioMediaStreamParser.d.ts.map +1 -1
  97. package/dist/voice/parsers/TwilioMediaStreamParser.js +81 -12
  98. package/dist/voice/parsers/TwilioMediaStreamParser.js.map +1 -1
  99. package/dist/voice/providers/plivo.d.ts +108 -12
  100. package/dist/voice/providers/plivo.d.ts.map +1 -1
  101. package/dist/voice/providers/plivo.js +106 -9
  102. package/dist/voice/providers/plivo.js.map +1 -1
  103. package/dist/voice/providers/telnyx.d.ts +110 -20
  104. package/dist/voice/providers/telnyx.d.ts.map +1 -1
  105. package/dist/voice/providers/telnyx.js +111 -20
  106. package/dist/voice/providers/telnyx.js.map +1 -1
  107. package/dist/voice/providers/twilio.d.ts +91 -13
  108. package/dist/voice/providers/twilio.d.ts.map +1 -1
  109. package/dist/voice/providers/twilio.js +94 -14
  110. package/dist/voice/providers/twilio.js.map +1 -1
  111. package/dist/voice/twiml.d.ts +70 -12
  112. package/dist/voice/twiml.d.ts.map +1 -1
  113. package/dist/voice/twiml.js +70 -12
  114. package/dist/voice/twiml.js.map +1 -1
  115. package/dist/voice/types.d.ts +142 -15
  116. package/dist/voice/types.d.ts.map +1 -1
  117. package/dist/voice/types.js +34 -3
  118. package/dist/voice/types.js.map +1 -1
  119. package/package.json +1 -1
@@ -2,8 +2,56 @@
2
2
  * @fileoverview Telnyx telephony provider for AgentOS voice calls.
3
3
  *
4
4
  * Implements {@link IVoiceCallProvider} using the Telnyx Call Control v2 API.
5
- * Webhook verification uses Ed25519 public key verification as specified in
6
- * the Telnyx security documentation.
5
+ *
6
+ * ## REST API contract
7
+ *
8
+ * | Operation | Method | Endpoint | Body format |
9
+ * |----------------|--------|------------------------------------------|-------------|
10
+ * | Initiate call | POST | `/v2/calls` | JSON |
11
+ * | Hangup call | POST | `/v2/calls/{id}/actions/hangup` | JSON |
12
+ * | Play TTS | POST | `/v2/calls/{id}/actions/speak` | JSON |
13
+ * | Start stream | POST | `/v2/calls/{id}/actions/streaming_start` | JSON |
14
+ *
15
+ * All requests use Bearer token authentication: `Authorization: Bearer {apiKey}`.
16
+ * Request bodies are JSON (unlike Twilio's form-encoded convention).
17
+ *
18
+ * ## Streaming after `call.answered`
19
+ *
20
+ * Telnyx requires a two-step flow for media streaming:
21
+ * 1. Initiate the call via `POST /v2/calls` with a `webhook_url`.
22
+ * 2. When the `call.answered` webhook fires, issue a separate
23
+ * `POST /v2/calls/{id}/actions/streaming_start` request with the
24
+ * WebSocket URL. This is handled by the CallManager, not by this provider.
25
+ *
26
+ * ## Webhook verification: Ed25519
27
+ *
28
+ * Telnyx signs webhooks using Ed25519 public key cryptography:
29
+ *
30
+ * 1. Telnyx generates a signed payload: `{timestamp}|{rawBody}`.
31
+ * 2. The signature is computed with the account's Ed25519 private key.
32
+ * 3. The public key is provided as a base64-encoded DER SPKI blob.
33
+ * 4. Headers: `X-Telnyx-Timestamp` (the timestamp) and
34
+ * `X-Telnyx-Signature-Ed25519` (base64-encoded Ed25519 signature).
35
+ * 5. Verification: decode the signature from base64, construct the payload
36
+ * string `{timestamp}|{body}`, and verify using `crypto.verify()` with
37
+ * the SPKI public key.
38
+ *
39
+ * When no public key is configured, verification is skipped (returns
40
+ * `valid: true`) to support development environments.
41
+ *
42
+ * ## Event mapping table (hangup_cause)
43
+ *
44
+ * | Telnyx `event_type` | `hangup_cause` | Normalised `kind` |
45
+ * |----------------------------------|---------------------------|----------------------|
46
+ * | `call.initiated` | -- | `call-ringing` |
47
+ * | `call.answered` | -- | `call-answered` |
48
+ * | `call.hangup` | `normal_clearing` | `call-hangup-user` |
49
+ * | `call.hangup` | `user_busy` | `call-hangup-user` |
50
+ * | `call.hangup` | `originator_cancel` | `call-hangup-user` |
51
+ * | `call.hangup` | (anything else) | `call-completed` |
52
+ * | `call.dtmf.received` | -- | `call-dtmf` |
53
+ * | `call.machine.detection.ended` | result=`machine` | `call-voicemail` |
54
+ * | `call.machine.detection.ended` | result=`human` | (no event) |
7
55
  *
8
56
  * @module @framers/agentos/voice/providers/telnyx
9
57
  */
@@ -29,7 +77,11 @@ import { randomUUID } from 'node:crypto';
29
77
  * ```
30
78
  */
31
79
  export class TelnyxVoiceProvider {
80
+ /**
81
+ * @param config - Telnyx credentials and optional overrides.
82
+ */
32
83
  constructor(config) {
84
+ /** Provider identifier, always `'telnyx'`. */
33
85
  this.name = 'telnyx';
34
86
  this.config = config;
35
87
  this.baseUrl = 'https://api.telnyx.com/v2';
@@ -40,14 +92,24 @@ export class TelnyxVoiceProvider {
40
92
  /**
41
93
  * Verify an incoming Telnyx webhook using Ed25519 signature verification.
42
94
  *
43
- * Telnyx signs `{timestamp}|{rawBody}` with the configured Ed25519 private key.
44
- * The matching public key is provided as a base64-encoded DER SPKI blob.
95
+ * ## Algorithm (step by step)
96
+ *
97
+ * 1. If no public key is configured, skip verification (return `valid: true`).
98
+ * This supports development environments without cryptographic setup.
99
+ * 2. Extract `X-Telnyx-Timestamp` and `X-Telnyx-Signature-Ed25519` headers.
100
+ * 3. Decode the signature from base64 into a raw byte Buffer.
101
+ * 4. Construct the signed payload: `"{timestamp}|{rawBody}"`.
102
+ * 5. Decode the SPKI public key from base64.
103
+ * 6. Call `crypto.verify(null, payload, { key, format: 'der', type: 'spki' }, signature)`.
104
+ * 7. Return the verification result.
45
105
  *
46
- * If no public key is configured, the check is skipped and `valid: true`
47
- * is returned so the provider can operate without cryptographic validation
48
- * during initial development.
106
+ * @param ctx - Raw webhook request context.
107
+ * @returns Verification result. Returns `{ valid: true }` when no public key
108
+ * is configured (development mode).
49
109
  */
50
110
  verifyWebhook(ctx) {
111
+ // Skip verification when no public key is configured -- allows
112
+ // development without needing to set up Ed25519 key pairs.
51
113
  if (!this.config.publicKey) {
52
114
  return { valid: true };
53
115
  }
@@ -57,9 +119,11 @@ export class TelnyxVoiceProvider {
57
119
  return { valid: false, error: 'Missing Telnyx signature headers' };
58
120
  }
59
121
  const signature = Buffer.from(sigHeader, 'base64');
122
+ // Telnyx signs the concatenation of timestamp, pipe separator, and raw body.
60
123
  const payload = Buffer.from(`${timestamp}|${ctx.body.toString()}`);
61
124
  try {
62
- const valid = verify(null, payload, {
125
+ const valid = verify(null, // Ed25519 does not use a separate hash algorithm parameter.
126
+ payload, {
63
127
  key: Buffer.from(this.config.publicKey, 'base64'),
64
128
  format: 'der',
65
129
  type: 'spki',
@@ -67,18 +131,27 @@ export class TelnyxVoiceProvider {
67
131
  return { valid };
68
132
  }
69
133
  catch {
134
+ // crypto.verify throws on malformed keys or invalid DER encoding.
70
135
  return { valid: false, error: 'Verification failed' };
71
136
  }
72
137
  }
73
138
  /**
74
139
  * Parse a Telnyx webhook JSON body into normalized {@link NormalizedCallEvent}s.
75
140
  *
76
- * Handles Telnyx Call Control event types:
77
- * - `call.initiated` `call-ringing`
78
- * - `call.answered` `call-answered`
79
- * - `call.hangup` → `call-completed` or `call-hangup-user` based on hangup_cause
80
- * - `call.dtmf.received` `call-dtmf`
81
- * - `call.machine.detection.ended` with `result === 'machine'` → `call-voicemail`
141
+ * Telnyx sends all webhook payloads as JSON with a `data.event_type`
142
+ * discriminant field. The `data.payload` object contains call-specific
143
+ * fields like `call_control_id`, `hangup_cause`, `digit`, and `result`.
144
+ *
145
+ * ## Hangup cause mapping
146
+ *
147
+ * Telnyx's `call.hangup` event includes a `hangup_cause` field that must
148
+ * be inspected to determine whether the user or the system terminated
149
+ * the call:
150
+ * - `normal_clearing` / `user_busy` / `originator_cancel` -> `call-hangup-user`
151
+ * - All other causes (e.g., `call_rejected`, `unallocated_number`) -> `call-completed`
152
+ *
153
+ * @param ctx - Raw webhook request context.
154
+ * @returns Parsed result containing zero or more normalized events.
82
155
  */
83
156
  parseWebhookEvent(ctx) {
84
157
  let parsed;
@@ -92,6 +165,7 @@ export class TelnyxVoiceProvider {
92
165
  const providerCallId = payload.call_control_id ?? '';
93
166
  const timestamp = Date.now();
94
167
  const events = [];
168
+ /** Helper: shared base fields with a unique event ID for idempotency. */
95
169
  const base = () => ({ eventId: randomUUID(), providerCallId, timestamp });
96
170
  switch (event_type) {
97
171
  case 'call.initiated':
@@ -101,7 +175,8 @@ export class TelnyxVoiceProvider {
101
175
  events.push({ ...base(), kind: 'call-answered' });
102
176
  break;
103
177
  case 'call.hangup': {
104
- // Distinguish user-initiated hangup from normal completion
178
+ // Distinguish user-initiated hangup from normal call completion
179
+ // by inspecting the hangup_cause field.
105
180
  const cause = payload.hangup_cause ?? '';
106
181
  const kind = cause === 'user_busy' || cause === 'normal_clearing' || cause === 'originator_cancel'
107
182
  ? 'call-hangup-user'
@@ -110,17 +185,19 @@ export class TelnyxVoiceProvider {
110
185
  break;
111
186
  }
112
187
  case 'call.dtmf.received': {
188
+ // DTMF arrives via webhook only (never over the media stream WebSocket).
113
189
  const digit = payload.digit ?? '';
114
190
  events.push({ ...base(), kind: 'call-dtmf', digit });
115
191
  break;
116
192
  }
117
193
  case 'call.machine.detection.ended':
194
+ // Only emit voicemail for machine detection; human detection is a no-op.
118
195
  if (payload.result === 'machine') {
119
196
  events.push({ ...base(), kind: 'call-voicemail' });
120
197
  }
121
198
  break;
122
199
  default:
123
- // Unrecognized event type emit nothing
200
+ // Unrecognized event type -- silently ignore for forward-compatibility.
124
201
  break;
125
202
  }
126
203
  return { events };
@@ -129,9 +206,15 @@ export class TelnyxVoiceProvider {
129
206
  /**
130
207
  * Initiate an outbound call via the Telnyx Call Control v2 API.
131
208
  *
132
- * POSTs to `/calls` with a JSON body. The `mediaStreamUrl` (if provided)
133
- * is stored internally for use after the call is answered — it is NOT sent
134
- * in the initial call creation request.
209
+ * POSTs to `/v2/calls` with a JSON body containing the `connection_id`,
210
+ * phone numbers, and webhook URL. The `mediaStreamUrl` (if provided) is
211
+ * stored internally for use after the call is answered -- it is NOT sent
212
+ * in the initial call creation request because Telnyx requires
213
+ * `streaming_start` to be issued as a separate action after `call.answered`.
214
+ *
215
+ * @param input - Call initiation parameters (from/to numbers, webhook URL).
216
+ * @returns Result containing the Telnyx `call_control_id` on success.
217
+ * @throws Never throws; returns `{ success: false, error: '...' }` on failure.
135
218
  */
136
219
  async initiateCall(input) {
137
220
  const url = `${this.baseUrl}/calls`;
@@ -157,6 +240,11 @@ export class TelnyxVoiceProvider {
157
240
  }
158
241
  /**
159
242
  * Hang up an active call via the Telnyx Call Control hangup action.
243
+ *
244
+ * POSTs an empty JSON body to `/v2/calls/{call_control_id}/actions/hangup`.
245
+ * Telnyx will terminate the call and fire a `call.hangup` webhook.
246
+ *
247
+ * @param input - Contains the Telnyx `call_control_id` to hang up.
160
248
  */
161
249
  async hangupCall(input) {
162
250
  const url = `${this.baseUrl}/calls/${input.providerCallId}/actions/hangup`;
@@ -172,7 +260,10 @@ export class TelnyxVoiceProvider {
172
260
  /**
173
261
  * Speak text into a live call using Telnyx's text-to-speech speak action.
174
262
  *
175
- * Defaults to `female` voice and `en-US` language when not specified.
263
+ * POSTs a JSON body to `/v2/calls/{id}/actions/speak` with the text
264
+ * `payload`, `voice` (default `'female'`), and `language` (default `'en-US'`).
265
+ *
266
+ * @param input - TTS parameters (text, optional voice, call ID).
176
267
  */
177
268
  async playTts(input) {
178
269
  const url = `${this.baseUrl}/calls/${input.providerCallId}/actions/speak`;
@@ -1 +1 @@
1
- {"version":3,"file":"telnyx.js","sourceRoot":"","sources":["../../../src/voice/providers/telnyx.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"telnyx.js","sourceRoot":"","sources":["../../../src/voice/providers/telnyx.ts"],"names":[],"mappings":"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"}
@@ -2,20 +2,60 @@
2
2
  * @fileoverview Twilio telephony provider for AgentOS voice calls.
3
3
  *
4
4
  * Implements {@link IVoiceCallProvider} using the Twilio REST API v2010-04-01.
5
- * Webhook verification uses HMAC-SHA1 per Twilio's security documentation.
5
+ *
6
+ * ## REST API contract
7
+ *
8
+ * | Operation | Method | Endpoint | Body format |
9
+ * |----------------|--------|---------------------------------------------------|-----------------|
10
+ * | Initiate call | POST | `/2010-04-01/Accounts/{sid}/Calls.json` | form-encoded |
11
+ * | Hangup call | POST | `/2010-04-01/Accounts/{sid}/Calls/{callSid}.json` | form-encoded |
12
+ * | Play TTS | POST | `/2010-04-01/Accounts/{sid}/Calls/{callSid}.json` | form-encoded |
13
+ *
14
+ * All requests use HTTP Basic authentication: `Authorization: Basic base64(accountSid:authToken)`.
15
+ * Request bodies are `application/x-www-form-urlencoded` (not JSON), which is
16
+ * Twilio's legacy convention for the 2010-04-01 API.
17
+ *
18
+ * ## Webhook verification: HMAC-SHA1
19
+ *
20
+ * Twilio signs every webhook request using HMAC-SHA1. The verification algorithm:
21
+ *
22
+ * 1. Start with the **full request URL** (including scheme, host, path, and any query string).
23
+ * 2. Parse the POST body as form-encoded key-value pairs.
24
+ * 3. Sort the parameters **alphabetically by key name**.
25
+ * 4. Concatenate each key+value pair (no separator) directly to the URL string.
26
+ * 5. Compute `HMAC-SHA1(authToken, concatenatedString)`.
27
+ * 6. Base64-encode the HMAC digest.
28
+ * 7. Compare the result with the `X-Twilio-Signature` request header.
29
+ *
30
+ * If the computed signature matches the header, the request is authentic.
31
+ *
32
+ * ## Event mapping table
33
+ *
34
+ * | Twilio `CallStatus` | Normalised `kind` |
35
+ * |---------------------|----------------------|
36
+ * | `ringing` | `call-ringing` |
37
+ * | `in-progress` | `call-answered` |
38
+ * | `completed` | `call-completed` |
39
+ * | `failed` | `call-failed` |
40
+ * | `busy` | `call-busy` |
41
+ * | `no-answer` | `call-no-answer` |
42
+ * | `canceled` | `call-hangup-user` |
43
+ * | (+ `Digits` param) | `call-dtmf` |
6
44
  *
7
45
  * @module @framers/agentos/voice/providers/twilio
8
46
  */
9
47
  import type { IVoiceCallProvider, InitiateCallInput, InitiateCallResult, HangupCallInput, PlayTtsInput } from '../IVoiceCallProvider.js';
10
48
  import type { WebhookContext, WebhookVerificationResult, WebhookParseResult } from '../types.js';
11
- /** Configuration for {@link TwilioVoiceProvider}. */
49
+ /**
50
+ * Configuration for {@link TwilioVoiceProvider}.
51
+ */
12
52
  export interface TwilioVoiceProviderConfig {
13
53
  /** Twilio Account SID (starts with "AC"). */
14
54
  accountSid: string;
15
- /** Twilio Auth Token. */
55
+ /** Twilio Auth Token (used for both API auth and webhook HMAC verification). */
16
56
  authToken: string;
17
57
  /**
18
- * Optional fetch override inject a mock in tests.
58
+ * Optional fetch implementation override -- inject a mock in tests.
19
59
  * Defaults to the global `fetch`.
20
60
  */
21
61
  fetchImpl?: typeof fetch;
@@ -35,44 +75,82 @@ export interface TwilioVoiceProviderConfig {
35
75
  * ```
36
76
  */
37
77
  export declare class TwilioVoiceProvider implements IVoiceCallProvider {
78
+ /** Provider identifier, always `'twilio'`. */
38
79
  readonly name: "twilio";
80
+ /** Immutable configuration snapshot. */
39
81
  private readonly config;
82
+ /** Base URL for the Twilio REST API (2010-04-01 version). */
40
83
  private readonly baseUrl;
84
+ /** Pre-computed `Authorization: Basic ...` header value. */
41
85
  private readonly authHeader;
86
+ /** HTTP fetch implementation (injectable for testing). */
42
87
  private readonly fetch;
88
+ /**
89
+ * @param config - Twilio credentials and optional overrides.
90
+ */
43
91
  constructor(config: TwilioVoiceProviderConfig);
44
92
  /**
45
93
  * Verify an incoming Twilio webhook request using HMAC-SHA1.
46
94
  *
47
- * Twilio constructs the signed data by appending all POST params (sorted
48
- * alphabetically) as key+value pairs directly to the full request URL.
95
+ * ## Algorithm (step by step)
96
+ *
97
+ * 1. Extract the `X-Twilio-Signature` header from the request.
98
+ * 2. Parse the request body as URL-encoded form data.
99
+ * 3. Sort all key-value pairs alphabetically by key.
100
+ * 4. Build the signed string: start with the full URL, then append each
101
+ * key + value (no delimiters between pairs).
102
+ * 5. Compute `HMAC-SHA1` of the signed string using the auth token as the key.
103
+ * 6. Base64-encode the digest and compare it to the header value.
104
+ *
105
+ * @param ctx - Raw webhook request context.
106
+ * @returns Verification result with `valid: true` if the signature matches.
49
107
  */
50
108
  verifyWebhook(ctx: WebhookContext): WebhookVerificationResult;
51
109
  /**
52
110
  * Parse a Twilio webhook body into normalized {@link NormalizedCallEvent}s.
53
111
  *
54
- * Handles call status transitions (ringing, in-progress, completed, failed,
55
- * busy, no-answer, canceled) and DTMF input.
112
+ * Twilio sends webhooks with a form-encoded body containing `CallSid`,
113
+ * `CallStatus`, and optionally `Digits` (for DTMF input from `<Gather>`).
114
+ * Each webhook may produce one or two events (status + optional DTMF).
115
+ *
116
+ * @param ctx - Raw webhook request context.
117
+ * @returns Parsed result containing zero or more normalized events.
56
118
  */
57
119
  parseWebhookEvent(ctx: WebhookContext): WebhookParseResult;
58
120
  /**
59
121
  * Initiate an outbound call via the Twilio Calls API.
60
122
  *
61
- * Posts to `/Accounts/{accountSid}/Calls.json` with form-encoded body.
62
- * All four status callback events (initiated, ringing, answered, completed)
63
- * are requested.
123
+ * Posts to `/Accounts/{accountSid}/Calls.json` with a **form-encoded** body
124
+ * (not JSON -- this is Twilio's 2010-era API convention). All four status
125
+ * callback events (`initiated`, `ringing`, `answered`, `completed`) are
126
+ * requested so the {@link CallManager} receives the full state progression.
127
+ *
128
+ * @param input - Call initiation parameters (from/to numbers, webhook URLs).
129
+ * @returns Result containing the Twilio `CallSid` on success.
130
+ * @throws Never throws; returns `{ success: false, error: '...' }` on failure.
64
131
  */
65
132
  initiateCall(input: InitiateCallInput): Promise<InitiateCallResult>;
66
133
  /**
67
- * Hang up an active call by posting `Status=completed`.
134
+ * Hang up an active call by POSTing `Status=completed`.
135
+ *
136
+ * Twilio uses the same Calls resource endpoint for both querying and
137
+ * modifying a call. Setting `Status=completed` instructs Twilio to
138
+ * immediately terminate the call.
139
+ *
140
+ * @param input - Contains the Twilio `CallSid` to hang up.
68
141
  */
69
142
  hangupCall(input: HangupCallInput): Promise<void>;
70
143
  /**
71
144
  * Inject TTS into a live call using a TwiML `<Say>` verb.
72
145
  *
73
- * Sends a `Twiml` parameter containing a minimal `<Response><Say>` document.
146
+ * Sends a `Twiml` form parameter containing a minimal `<Response><Say>`
147
+ * document. Twilio will parse the TwiML, synthesise the speech, and play
148
+ * it to the caller in real-time.
149
+ *
74
150
  * The optional `voice` attribute maps to Twilio's built-in voice names
75
151
  * (e.g., `alice`, `Polly.Joanna`).
152
+ *
153
+ * @param input - TTS parameters (text, voice, call ID).
76
154
  */
77
155
  playTts(input: PlayTtsInput): Promise<void>;
78
156
  }
@@ -1 +1 @@
1
- {"version":3,"file":"twilio.d.ts","sourceRoot":"","sources":["../../../src/voice/providers/twilio.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAKH,OAAO,KAAK,EACV,kBAAkB,EAClB,iBAAiB,EACjB,kBAAkB,EAClB,eAAe,EACf,YAAY,EACb,MAAM,0BAA0B,CAAC;AAElC,OAAO,KAAK,EACV,cAAc,EACd,yBAAyB,EACzB,kBAAkB,EAEnB,MAAM,aAAa,CAAC;AAMrB,qDAAqD;AACrD,MAAM,WAAW,yBAAyB;IACxC,6CAA6C;IAC7C,UAAU,EAAE,MAAM,CAAC;IACnB,yBAAyB;IACzB,SAAS,EAAE,MAAM,CAAC;IAClB;;;OAGG;IACH,SAAS,CAAC,EAAE,OAAO,KAAK,CAAC;CAC1B;AAMD;;;;;;;;;;;;;GAaG;AACH,qBAAa,mBAAoB,YAAW,kBAAkB;IAC5D,QAAQ,CAAC,IAAI,EAAG,QAAQ,CAAU;IAElC,OAAO,CAAC,QAAQ,CAAC,MAAM,CAA4B;IACnD,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAS;IACjC,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAS;IACpC,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAe;gBAEzB,MAAM,EAAE,yBAAyB;IAW7C;;;;;OAKG;IACH,aAAa,CAAC,GAAG,EAAE,cAAc,GAAG,yBAAyB;IAyB7D;;;;;OAKG;IACH,iBAAiB,CAAC,GAAG,EAAE,cAAc,GAAG,kBAAkB;IAyD1D;;;;;;OAMG;IACG,YAAY,CAAC,KAAK,EAAE,iBAAiB,GAAG,OAAO,CAAC,kBAAkB,CAAC;IAgCzE;;OAEG;IACG,UAAU,CAAC,KAAK,EAAE,eAAe,GAAG,OAAO,CAAC,IAAI,CAAC;IAavD;;;;;;OAMG;IACG,OAAO,CAAC,KAAK,EAAE,YAAY,GAAG,OAAO,CAAC,IAAI,CAAC;CAelD"}
1
+ {"version":3,"file":"twilio.d.ts","sourceRoot":"","sources":["../../../src/voice/providers/twilio.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6CG;AAKH,OAAO,KAAK,EACV,kBAAkB,EAClB,iBAAiB,EACjB,kBAAkB,EAClB,eAAe,EACf,YAAY,EACb,MAAM,0BAA0B,CAAC;AAElC,OAAO,KAAK,EACV,cAAc,EACd,yBAAyB,EACzB,kBAAkB,EAEnB,MAAM,aAAa,CAAC;AAMrB;;GAEG;AACH,MAAM,WAAW,yBAAyB;IACxC,6CAA6C;IAC7C,UAAU,EAAE,MAAM,CAAC;IACnB,gFAAgF;IAChF,SAAS,EAAE,MAAM,CAAC;IAClB;;;OAGG;IACH,SAAS,CAAC,EAAE,OAAO,KAAK,CAAC;CAC1B;AAMD;;;;;;;;;;;;;GAaG;AACH,qBAAa,mBAAoB,YAAW,kBAAkB;IAC5D,8CAA8C;IAC9C,QAAQ,CAAC,IAAI,EAAG,QAAQ,CAAU;IAElC,wCAAwC;IACxC,OAAO,CAAC,QAAQ,CAAC,MAAM,CAA4B;IAEnD,6DAA6D;IAC7D,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAS;IAEjC,4DAA4D;IAC5D,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAS;IAEpC,0DAA0D;IAC1D,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAe;IAErC;;OAEG;gBACS,MAAM,EAAE,yBAAyB;IAY7C;;;;;;;;;;;;;;;OAeG;IACH,aAAa,CAAC,GAAG,EAAE,cAAc,GAAG,yBAAyB;IA0B7D;;;;;;;;;OASG;IACH,iBAAiB,CAAC,GAAG,EAAE,cAAc,GAAG,kBAAkB;IA8D1D;;;;;;;;;;;OAWG;IACG,YAAY,CAAC,KAAK,EAAE,iBAAiB,GAAG,OAAO,CAAC,kBAAkB,CAAC;IAiCzE;;;;;;;;OAQG;IACG,UAAU,CAAC,KAAK,EAAE,eAAe,GAAG,OAAO,CAAC,IAAI,CAAC;IAavD;;;;;;;;;;;OAWG;IACG,OAAO,CAAC,KAAK,EAAE,YAAY,GAAG,OAAO,CAAC,IAAI,CAAC;CAelD"}
@@ -2,7 +2,45 @@
2
2
  * @fileoverview Twilio telephony provider for AgentOS voice calls.
3
3
  *
4
4
  * Implements {@link IVoiceCallProvider} using the Twilio REST API v2010-04-01.
5
- * Webhook verification uses HMAC-SHA1 per Twilio's security documentation.
5
+ *
6
+ * ## REST API contract
7
+ *
8
+ * | Operation | Method | Endpoint | Body format |
9
+ * |----------------|--------|---------------------------------------------------|-----------------|
10
+ * | Initiate call | POST | `/2010-04-01/Accounts/{sid}/Calls.json` | form-encoded |
11
+ * | Hangup call | POST | `/2010-04-01/Accounts/{sid}/Calls/{callSid}.json` | form-encoded |
12
+ * | Play TTS | POST | `/2010-04-01/Accounts/{sid}/Calls/{callSid}.json` | form-encoded |
13
+ *
14
+ * All requests use HTTP Basic authentication: `Authorization: Basic base64(accountSid:authToken)`.
15
+ * Request bodies are `application/x-www-form-urlencoded` (not JSON), which is
16
+ * Twilio's legacy convention for the 2010-04-01 API.
17
+ *
18
+ * ## Webhook verification: HMAC-SHA1
19
+ *
20
+ * Twilio signs every webhook request using HMAC-SHA1. The verification algorithm:
21
+ *
22
+ * 1. Start with the **full request URL** (including scheme, host, path, and any query string).
23
+ * 2. Parse the POST body as form-encoded key-value pairs.
24
+ * 3. Sort the parameters **alphabetically by key name**.
25
+ * 4. Concatenate each key+value pair (no separator) directly to the URL string.
26
+ * 5. Compute `HMAC-SHA1(authToken, concatenatedString)`.
27
+ * 6. Base64-encode the HMAC digest.
28
+ * 7. Compare the result with the `X-Twilio-Signature` request header.
29
+ *
30
+ * If the computed signature matches the header, the request is authentic.
31
+ *
32
+ * ## Event mapping table
33
+ *
34
+ * | Twilio `CallStatus` | Normalised `kind` |
35
+ * |---------------------|----------------------|
36
+ * | `ringing` | `call-ringing` |
37
+ * | `in-progress` | `call-answered` |
38
+ * | `completed` | `call-completed` |
39
+ * | `failed` | `call-failed` |
40
+ * | `busy` | `call-busy` |
41
+ * | `no-answer` | `call-no-answer` |
42
+ * | `canceled` | `call-hangup-user` |
43
+ * | (+ `Digits` param) | `call-dtmf` |
6
44
  *
7
45
  * @module @framers/agentos/voice/providers/twilio
8
46
  */
@@ -26,10 +64,15 @@ import { randomUUID } from 'node:crypto';
26
64
  * ```
27
65
  */
28
66
  export class TwilioVoiceProvider {
67
+ /**
68
+ * @param config - Twilio credentials and optional overrides.
69
+ */
29
70
  constructor(config) {
71
+ /** Provider identifier, always `'twilio'`. */
30
72
  this.name = 'twilio';
31
73
  this.config = config;
32
74
  this.baseUrl = 'https://api.twilio.com/2010-04-01';
75
+ // Twilio uses HTTP Basic auth with accountSid:authToken.
33
76
  this.authHeader =
34
77
  'Basic ' +
35
78
  Buffer.from(`${config.accountSid}:${config.authToken}`).toString('base64');
@@ -39,21 +82,32 @@ export class TwilioVoiceProvider {
39
82
  /**
40
83
  * Verify an incoming Twilio webhook request using HMAC-SHA1.
41
84
  *
42
- * Twilio constructs the signed data by appending all POST params (sorted
43
- * alphabetically) as key+value pairs directly to the full request URL.
85
+ * ## Algorithm (step by step)
86
+ *
87
+ * 1. Extract the `X-Twilio-Signature` header from the request.
88
+ * 2. Parse the request body as URL-encoded form data.
89
+ * 3. Sort all key-value pairs alphabetically by key.
90
+ * 4. Build the signed string: start with the full URL, then append each
91
+ * key + value (no delimiters between pairs).
92
+ * 5. Compute `HMAC-SHA1` of the signed string using the auth token as the key.
93
+ * 6. Base64-encode the digest and compare it to the header value.
94
+ *
95
+ * @param ctx - Raw webhook request context.
96
+ * @returns Verification result with `valid: true` if the signature matches.
44
97
  */
45
98
  verifyWebhook(ctx) {
46
99
  const signature = ctx.headers['x-twilio-signature'];
47
100
  if (!signature || Array.isArray(signature)) {
48
101
  return { valid: false, error: 'Missing x-twilio-signature header' };
49
102
  }
50
- // Build the signed data string
103
+ // Step 2-4: Parse form body, sort params, build signed data string.
51
104
  const bodyParams = new URLSearchParams(ctx.body.toString());
52
105
  const sorted = [...bodyParams.entries()].sort(([a], [b]) => a.localeCompare(b));
53
106
  let data = ctx.url;
54
107
  for (const [key, value] of sorted) {
55
108
  data += key + value;
56
109
  }
110
+ // Step 5-6: HMAC-SHA1 with auth token, compare base64 digest.
57
111
  const expected = createHmac('sha1', this.config.authToken)
58
112
  .update(data)
59
113
  .digest('base64');
@@ -66,8 +120,12 @@ export class TwilioVoiceProvider {
66
120
  /**
67
121
  * Parse a Twilio webhook body into normalized {@link NormalizedCallEvent}s.
68
122
  *
69
- * Handles call status transitions (ringing, in-progress, completed, failed,
70
- * busy, no-answer, canceled) and DTMF input.
123
+ * Twilio sends webhooks with a form-encoded body containing `CallSid`,
124
+ * `CallStatus`, and optionally `Digits` (for DTMF input from `<Gather>`).
125
+ * Each webhook may produce one or two events (status + optional DTMF).
126
+ *
127
+ * @param ctx - Raw webhook request context.
128
+ * @returns Parsed result containing zero or more normalized events.
71
129
  */
72
130
  parseWebhookEvent(ctx) {
73
131
  const params = new URLSearchParams(ctx.body.toString());
@@ -76,12 +134,13 @@ export class TwilioVoiceProvider {
76
134
  const digits = params.get('Digits');
77
135
  const timestamp = Date.now();
78
136
  const events = [];
79
- /** Helper: shared base fields. */
137
+ /** Helper: shared base fields with a unique event ID for idempotency. */
80
138
  const base = () => ({
81
139
  eventId: randomUUID(),
82
140
  providerCallId: callSid,
83
141
  timestamp,
84
142
  });
143
+ // Map Twilio CallStatus values to normalized event kinds.
85
144
  switch (callStatus) {
86
145
  case 'ringing':
87
146
  events.push({ ...base(), kind: 'call-ringing' });
@@ -102,13 +161,17 @@ export class TwilioVoiceProvider {
102
161
  events.push({ ...base(), kind: 'call-no-answer' });
103
162
  break;
104
163
  case 'canceled':
164
+ // Twilio uses "canceled" when the caller hangs up before the callee answers.
105
165
  events.push({ ...base(), kind: 'call-hangup-user' });
106
166
  break;
107
167
  default:
108
- // initiated / queued / etc. no normalized event emitted
168
+ // initiated / queued / etc. -- no normalized event emitted.
169
+ // These are transient Twilio-internal states that don't map to
170
+ // meaningful call lifecycle events.
109
171
  break;
110
172
  }
111
- // DTMF digit input
173
+ // DTMF digit input (from <Gather> TwiML verb callback).
174
+ // This can co-occur with a CallStatus update in the same webhook.
112
175
  if (digits != null && digits !== '') {
113
176
  events.push({
114
177
  ...base(),
@@ -122,12 +185,18 @@ export class TwilioVoiceProvider {
122
185
  /**
123
186
  * Initiate an outbound call via the Twilio Calls API.
124
187
  *
125
- * Posts to `/Accounts/{accountSid}/Calls.json` with form-encoded body.
126
- * All four status callback events (initiated, ringing, answered, completed)
127
- * are requested.
188
+ * Posts to `/Accounts/{accountSid}/Calls.json` with a **form-encoded** body
189
+ * (not JSON -- this is Twilio's 2010-era API convention). All four status
190
+ * callback events (`initiated`, `ringing`, `answered`, `completed`) are
191
+ * requested so the {@link CallManager} receives the full state progression.
192
+ *
193
+ * @param input - Call initiation parameters (from/to numbers, webhook URLs).
194
+ * @returns Result containing the Twilio `CallSid` on success.
195
+ * @throws Never throws; returns `{ success: false, error: '...' }` on failure.
128
196
  */
129
197
  async initiateCall(input) {
130
198
  const url = `${this.baseUrl}/Accounts/${this.config.accountSid}/Calls.json`;
199
+ // Build form-encoded body. Twilio expects this format, not JSON.
131
200
  const body = [
132
201
  `To=${encodeURIComponent(input.toNumber)}`,
133
202
  `From=${encodeURIComponent(input.fromNumber)}`,
@@ -154,7 +223,13 @@ export class TwilioVoiceProvider {
154
223
  return { providerCallId: data.sid, success: true };
155
224
  }
156
225
  /**
157
- * Hang up an active call by posting `Status=completed`.
226
+ * Hang up an active call by POSTing `Status=completed`.
227
+ *
228
+ * Twilio uses the same Calls resource endpoint for both querying and
229
+ * modifying a call. Setting `Status=completed` instructs Twilio to
230
+ * immediately terminate the call.
231
+ *
232
+ * @param input - Contains the Twilio `CallSid` to hang up.
158
233
  */
159
234
  async hangupCall(input) {
160
235
  const url = `${this.baseUrl}/Accounts/${this.config.accountSid}/Calls/${input.providerCallId}.json`;
@@ -170,9 +245,14 @@ export class TwilioVoiceProvider {
170
245
  /**
171
246
  * Inject TTS into a live call using a TwiML `<Say>` verb.
172
247
  *
173
- * Sends a `Twiml` parameter containing a minimal `<Response><Say>` document.
248
+ * Sends a `Twiml` form parameter containing a minimal `<Response><Say>`
249
+ * document. Twilio will parse the TwiML, synthesise the speech, and play
250
+ * it to the caller in real-time.
251
+ *
174
252
  * The optional `voice` attribute maps to Twilio's built-in voice names
175
253
  * (e.g., `alice`, `Polly.Joanna`).
254
+ *
255
+ * @param input - TTS parameters (text, voice, call ID).
176
256
  */
177
257
  async playTts(input) {
178
258
  const url = `${this.baseUrl}/Accounts/${this.config.accountSid}/Calls/${input.providerCallId}.json`;
@@ -1 +1 @@
1
- {"version":3,"file":"twilio.js","sourceRoot":"","sources":["../../../src/voice/providers/twilio.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"twilio.js","sourceRoot":"","sources":["../../../src/voice/providers/twilio.ts"],"names":[],"mappings":"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"}