@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
@@ -1 +1 @@
1
- {"version":3,"file":"TwilioMediaStreamParser.js","sourceRoot":"","sources":["../../../src/voice/parsers/TwilioMediaStreamParser.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"TwilioMediaStreamParser.js","sourceRoot":"","sources":["../../../src/voice/parsers/TwilioMediaStreamParser.ts"],"names":[],"mappings":"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"}
@@ -2,20 +2,78 @@
2
2
  * @fileoverview Plivo telephony provider for AgentOS voice calls.
3
3
  *
4
4
  * Implements {@link IVoiceCallProvider} using the Plivo Voice REST API v1.
5
- * Webhook verification uses HMAC-SHA256 with the v3 signature scheme.
5
+ *
6
+ * ## REST API contract
7
+ *
8
+ * | Operation | Method | Endpoint | Body format |
9
+ * |----------------|--------|----------------------------------------------|-------------|
10
+ * | Initiate call | POST | `/v1/Account/{authId}/Call/` | JSON |
11
+ * | Hangup call | DELETE | `/v1/Account/{authId}/Call/{callUuid}/` | (none) |
12
+ * | Play TTS | POST | `/v1/Account/{authId}/Call/{callUuid}/Speak/` | JSON |
13
+ *
14
+ * All requests use HTTP Basic authentication: `Authorization: Basic base64(authId:authToken)`.
15
+ *
16
+ * ### Hangup uses DELETE (not POST)
17
+ *
18
+ * Unlike Twilio (which POSTs `Status=completed`) and Telnyx (which POSTs to
19
+ * an `/actions/hangup` endpoint), Plivo uses the HTTP `DELETE` method on the
20
+ * Call resource to terminate an active call. This is a RESTful design choice
21
+ * where "deleting" the call resource means terminating the call.
22
+ *
23
+ * ## Webhook verification: HMAC-SHA256 + nonce (v3 scheme)
24
+ *
25
+ * Plivo's v3 webhook signature scheme:
26
+ *
27
+ * 1. Plivo generates a random `nonce` and includes it in the
28
+ * `X-Plivo-Signature-V3-Nonce` header.
29
+ * 2. The signed data is: `{fullRequestURL}{nonce}` (concatenated, no separator).
30
+ * 3. Compute `HMAC-SHA256(authToken, signedData)`.
31
+ * 4. Base64-encode the HMAC digest.
32
+ * 5. Compare the result with the `X-Plivo-Signature-V3` header.
33
+ *
34
+ * Note: Unlike Twilio's scheme, Plivo does NOT include the POST body in the
35
+ * signed data -- only the URL and nonce. The nonce prevents replay attacks.
36
+ *
37
+ * ## DTMF via `<GetDigits>` XML pattern
38
+ *
39
+ * Plivo delivers DTMF input through the `<GetDigits>` XML element callback,
40
+ * not through the media stream WebSocket. When a call executes:
41
+ *
42
+ * ```xml
43
+ * <GetDigits action="https://example.com/dtmf" method="POST" timeout="10">
44
+ * <Speak>Press 1 to confirm.</Speak>
45
+ * </GetDigits>
46
+ * ```
47
+ *
48
+ * Plivo POSTs the pressed digits to the `action` URL with a `Digits`
49
+ * parameter in the form-encoded body (e.g., `Digits=1&CallUUID=xxx`).
50
+ *
51
+ * ## Event mapping table
52
+ *
53
+ * | Plivo `CallStatus` | Normalised `kind` |
54
+ * |---------------------|----------------------|
55
+ * | `ringing` | `call-ringing` |
56
+ * | `in-progress` | `call-answered` |
57
+ * | `completed` | `call-completed` |
58
+ * | `busy` | `call-busy` |
59
+ * | `no-answer` | `call-no-answer` |
60
+ * | `failed` | `call-failed` |
61
+ * | (+ `Digits` param) | `call-dtmf` |
6
62
  *
7
63
  * @module @framers/agentos/voice/providers/plivo
8
64
  */
9
65
  import type { IVoiceCallProvider, InitiateCallInput, InitiateCallResult, HangupCallInput, PlayTtsInput } from '../IVoiceCallProvider.js';
10
66
  import type { WebhookContext, WebhookVerificationResult, WebhookParseResult } from '../types.js';
11
- /** Configuration for {@link PlivoVoiceProvider}. */
67
+ /**
68
+ * Configuration for {@link PlivoVoiceProvider}.
69
+ */
12
70
  export interface PlivoVoiceProviderConfig {
13
- /** Plivo Auth ID (account identifier). */
71
+ /** Plivo Auth ID (account identifier, used in API URLs and Basic auth). */
14
72
  authId: string;
15
- /** Plivo Auth Token. */
73
+ /** Plivo Auth Token (used for both API auth and webhook HMAC verification). */
16
74
  authToken: string;
17
75
  /**
18
- * Optional fetch override inject a mock in tests.
76
+ * Optional fetch implementation override -- inject a mock in tests.
19
77
  * Defaults to the global `fetch`.
20
78
  */
21
79
  fetchImpl?: typeof fetch;
@@ -35,42 +93,80 @@ export interface PlivoVoiceProviderConfig {
35
93
  * ```
36
94
  */
37
95
  export declare class PlivoVoiceProvider implements IVoiceCallProvider {
96
+ /** Provider identifier, always `'plivo'`. */
38
97
  readonly name: "plivo";
98
+ /** Immutable configuration snapshot. */
39
99
  private readonly config;
100
+ /** Base URL for the Plivo REST API v1. */
40
101
  private readonly baseUrl;
102
+ /** Pre-computed `Authorization: Basic ...` header value. */
41
103
  private readonly authHeader;
104
+ /** HTTP fetch implementation (injectable for testing). */
42
105
  private readonly fetch;
106
+ /**
107
+ * @param config - Plivo credentials and optional overrides.
108
+ */
43
109
  constructor(config: PlivoVoiceProviderConfig);
44
110
  /**
45
111
  * Verify an incoming Plivo webhook request using HMAC-SHA256 (v3 scheme).
46
112
  *
47
- * Plivo signs the concatenation of the full request URL and the nonce
48
- * header value. The resulting base64-encoded digest is compared against
49
- * the `x-plivo-signature-v3` header.
113
+ * ## Algorithm (step by step)
114
+ *
115
+ * 1. Extract the `X-Plivo-Signature-V3-Nonce` and `X-Plivo-Signature-V3` headers.
116
+ * 2. Build the signed data string: `{fullRequestURL}{nonce}`.
117
+ * Note: the POST body is NOT included in the signed data (unlike Twilio).
118
+ * 3. Compute `HMAC-SHA256(authToken, signedData)`.
119
+ * 4. Base64-encode the digest.
120
+ * 5. Compare with the `X-Plivo-Signature-V3` header.
121
+ *
122
+ * @param ctx - Raw webhook request context.
123
+ * @returns Verification result with `valid: true` if the signature matches.
50
124
  */
51
125
  verifyWebhook(ctx: WebhookContext): WebhookVerificationResult;
52
126
  /**
53
127
  * Parse a Plivo webhook body into normalized {@link NormalizedCallEvent}s.
54
128
  *
55
- * Supports both URL-encoded and JSON request bodies. Maps `CallStatus`
56
- * parameter values to call lifecycle events.
129
+ * Plivo sends most webhooks with URL-encoded bodies, but some callbacks
130
+ * may arrive as JSON. This parser handles both formats by inspecting
131
+ * whether the body starts with `{` (JSON) or not (form-encoded).
132
+ *
133
+ * Plivo uses two naming conventions for the same fields:
134
+ * - PascalCase (`CallUUID`, `CallStatus`, `Digits`) in URL callbacks.
135
+ * - snake_case (`call_uuid`, `call_status`) in some API responses.
136
+ * Both are checked for maximum compatibility.
137
+ *
138
+ * @param ctx - Raw webhook request context.
139
+ * @returns Parsed result containing zero or more normalized events.
57
140
  */
58
141
  parseWebhookEvent(ctx: WebhookContext): WebhookParseResult;
59
142
  /**
60
143
  * Initiate an outbound call via the Plivo Call API.
61
144
  *
62
- * POSTs a JSON body to `/Account/{authId}/Call/` with the caller, callee,
145
+ * POSTs a JSON body to `/v1/Account/{authId}/Call/` with the caller, callee,
63
146
  * and answer URL. Returns the `request_uuid` as the provider call ID.
147
+ *
148
+ * @param input - Call initiation parameters (from/to numbers, webhook URL).
149
+ * @returns Result containing the Plivo `request_uuid` on success.
150
+ * @throws Never throws; returns `{ success: false, error: '...' }` on failure.
64
151
  */
65
152
  initiateCall(input: InitiateCallInput): Promise<InitiateCallResult>;
66
153
  /**
67
154
  * Hang up an active call using the Plivo Call DELETE endpoint.
155
+ *
156
+ * Plivo uses HTTP `DELETE` to terminate a call (unlike Twilio's POST with
157
+ * `Status=completed` or Telnyx's POST to `/actions/hangup`). This is a
158
+ * RESTful convention where deleting the call resource ends the call.
159
+ *
160
+ * @param input - Contains the Plivo `call_uuid` to hang up.
68
161
  */
69
162
  hangupCall(input: HangupCallInput): Promise<void>;
70
163
  /**
71
164
  * Speak text into a live call using the Plivo Speak API.
72
165
  *
73
- * Defaults to `WOMAN` voice and `en-US` language when not specified.
166
+ * POSTs a JSON body to `/v1/Account/{authId}/Call/{callUuid}/Speak/`
167
+ * with the text, voice (default `'WOMAN'`), and language (default `'en-US'`).
168
+ *
169
+ * @param input - TTS parameters (text, optional voice, call ID).
74
170
  */
75
171
  playTts(input: PlayTtsInput): Promise<void>;
76
172
  }
@@ -1 +1 @@
1
- {"version":3,"file":"plivo.d.ts","sourceRoot":"","sources":["../../../src/voice/providers/plivo.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAIH,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,oDAAoD;AACpD,MAAM,WAAW,wBAAwB;IACvC,0CAA0C;IAC1C,MAAM,EAAE,MAAM,CAAC;IACf,wBAAwB;IACxB,SAAS,EAAE,MAAM,CAAC;IAClB;;;OAGG;IACH,SAAS,CAAC,EAAE,OAAO,KAAK,CAAC;CAC1B;AAMD;;;;;;;;;;;;;GAaG;AACH,qBAAa,kBAAmB,YAAW,kBAAkB;IAC3D,QAAQ,CAAC,IAAI,EAAG,OAAO,CAAU;IAEjC,OAAO,CAAC,QAAQ,CAAC,MAAM,CAA2B;IAClD,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAS;IACjC,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAS;IACpC,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAe;gBAEzB,MAAM,EAAE,wBAAwB;IAU5C;;;;;;OAMG;IACH,aAAa,CAAC,GAAG,EAAE,cAAc,GAAG,yBAAyB;IAkB7D;;;;;OAKG;IACH,iBAAiB,CAAC,GAAG,EAAE,cAAc,GAAG,kBAAkB;IA8D1D;;;;;OAKG;IACG,YAAY,CAAC,KAAK,EAAE,iBAAiB,GAAG,OAAO,CAAC,kBAAkB,CAAC;IA0BzE;;OAEG;IACG,UAAU,CAAC,KAAK,EAAE,eAAe,GAAG,OAAO,CAAC,IAAI,CAAC;IAWvD;;;;OAIG;IACG,OAAO,CAAC,KAAK,EAAE,YAAY,GAAG,OAAO,CAAC,IAAI,CAAC;CAgBlD"}
1
+ {"version":3,"file":"plivo.d.ts","sourceRoot":"","sources":["../../../src/voice/providers/plivo.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA+DG;AAIH,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,wBAAwB;IACvC,2EAA2E;IAC3E,MAAM,EAAE,MAAM,CAAC;IACf,+EAA+E;IAC/E,SAAS,EAAE,MAAM,CAAC;IAClB;;;OAGG;IACH,SAAS,CAAC,EAAE,OAAO,KAAK,CAAC;CAC1B;AAMD;;;;;;;;;;;;;GAaG;AACH,qBAAa,kBAAmB,YAAW,kBAAkB;IAC3D,6CAA6C;IAC7C,QAAQ,CAAC,IAAI,EAAG,OAAO,CAAU;IAEjC,wCAAwC;IACxC,OAAO,CAAC,QAAQ,CAAC,MAAM,CAA2B;IAElD,0CAA0C;IAC1C,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,wBAAwB;IAW5C;;;;;;;;;;;;;;OAcG;IACH,aAAa,CAAC,GAAG,EAAE,cAAc,GAAG,yBAAyB;IAoB7D;;;;;;;;;;;;;;OAcG;IACH,iBAAiB,CAAC,GAAG,EAAE,cAAc,GAAG,kBAAkB;IAkE1D;;;;;;;;;OASG;IACG,YAAY,CAAC,KAAK,EAAE,iBAAiB,GAAG,OAAO,CAAC,kBAAkB,CAAC;IA0BzE;;;;;;;;OAQG;IACG,UAAU,CAAC,KAAK,EAAE,eAAe,GAAG,OAAO,CAAC,IAAI,CAAC;IAWvD;;;;;;;OAOG;IACG,OAAO,CAAC,KAAK,EAAE,YAAY,GAAG,OAAO,CAAC,IAAI,CAAC;CAgBlD"}
@@ -2,7 +2,63 @@
2
2
  * @fileoverview Plivo telephony provider for AgentOS voice calls.
3
3
  *
4
4
  * Implements {@link IVoiceCallProvider} using the Plivo Voice REST API v1.
5
- * Webhook verification uses HMAC-SHA256 with the v3 signature scheme.
5
+ *
6
+ * ## REST API contract
7
+ *
8
+ * | Operation | Method | Endpoint | Body format |
9
+ * |----------------|--------|----------------------------------------------|-------------|
10
+ * | Initiate call | POST | `/v1/Account/{authId}/Call/` | JSON |
11
+ * | Hangup call | DELETE | `/v1/Account/{authId}/Call/{callUuid}/` | (none) |
12
+ * | Play TTS | POST | `/v1/Account/{authId}/Call/{callUuid}/Speak/` | JSON |
13
+ *
14
+ * All requests use HTTP Basic authentication: `Authorization: Basic base64(authId:authToken)`.
15
+ *
16
+ * ### Hangup uses DELETE (not POST)
17
+ *
18
+ * Unlike Twilio (which POSTs `Status=completed`) and Telnyx (which POSTs to
19
+ * an `/actions/hangup` endpoint), Plivo uses the HTTP `DELETE` method on the
20
+ * Call resource to terminate an active call. This is a RESTful design choice
21
+ * where "deleting" the call resource means terminating the call.
22
+ *
23
+ * ## Webhook verification: HMAC-SHA256 + nonce (v3 scheme)
24
+ *
25
+ * Plivo's v3 webhook signature scheme:
26
+ *
27
+ * 1. Plivo generates a random `nonce` and includes it in the
28
+ * `X-Plivo-Signature-V3-Nonce` header.
29
+ * 2. The signed data is: `{fullRequestURL}{nonce}` (concatenated, no separator).
30
+ * 3. Compute `HMAC-SHA256(authToken, signedData)`.
31
+ * 4. Base64-encode the HMAC digest.
32
+ * 5. Compare the result with the `X-Plivo-Signature-V3` header.
33
+ *
34
+ * Note: Unlike Twilio's scheme, Plivo does NOT include the POST body in the
35
+ * signed data -- only the URL and nonce. The nonce prevents replay attacks.
36
+ *
37
+ * ## DTMF via `<GetDigits>` XML pattern
38
+ *
39
+ * Plivo delivers DTMF input through the `<GetDigits>` XML element callback,
40
+ * not through the media stream WebSocket. When a call executes:
41
+ *
42
+ * ```xml
43
+ * <GetDigits action="https://example.com/dtmf" method="POST" timeout="10">
44
+ * <Speak>Press 1 to confirm.</Speak>
45
+ * </GetDigits>
46
+ * ```
47
+ *
48
+ * Plivo POSTs the pressed digits to the `action` URL with a `Digits`
49
+ * parameter in the form-encoded body (e.g., `Digits=1&CallUUID=xxx`).
50
+ *
51
+ * ## Event mapping table
52
+ *
53
+ * | Plivo `CallStatus` | Normalised `kind` |
54
+ * |---------------------|----------------------|
55
+ * | `ringing` | `call-ringing` |
56
+ * | `in-progress` | `call-answered` |
57
+ * | `completed` | `call-completed` |
58
+ * | `busy` | `call-busy` |
59
+ * | `no-answer` | `call-no-answer` |
60
+ * | `failed` | `call-failed` |
61
+ * | (+ `Digits` param) | `call-dtmf` |
6
62
  *
7
63
  * @module @framers/agentos/voice/providers/plivo
8
64
  */
@@ -25,10 +81,15 @@ import { createHmac, randomUUID } from 'node:crypto';
25
81
  * ```
26
82
  */
27
83
  export class PlivoVoiceProvider {
84
+ /**
85
+ * @param config - Plivo credentials and optional overrides.
86
+ */
28
87
  constructor(config) {
88
+ /** Provider identifier, always `'plivo'`. */
29
89
  this.name = 'plivo';
30
90
  this.config = config;
31
91
  this.baseUrl = 'https://api.plivo.com/v1';
92
+ // Plivo uses HTTP Basic auth with authId:authToken (similar to Twilio).
32
93
  this.authHeader =
33
94
  'Basic ' + Buffer.from(`${config.authId}:${config.authToken}`).toString('base64');
34
95
  this.fetch = config.fetchImpl ?? globalThis.fetch;
@@ -37,9 +98,17 @@ export class PlivoVoiceProvider {
37
98
  /**
38
99
  * Verify an incoming Plivo webhook request using HMAC-SHA256 (v3 scheme).
39
100
  *
40
- * Plivo signs the concatenation of the full request URL and the nonce
41
- * header value. The resulting base64-encoded digest is compared against
42
- * the `x-plivo-signature-v3` header.
101
+ * ## Algorithm (step by step)
102
+ *
103
+ * 1. Extract the `X-Plivo-Signature-V3-Nonce` and `X-Plivo-Signature-V3` headers.
104
+ * 2. Build the signed data string: `{fullRequestURL}{nonce}`.
105
+ * Note: the POST body is NOT included in the signed data (unlike Twilio).
106
+ * 3. Compute `HMAC-SHA256(authToken, signedData)`.
107
+ * 4. Base64-encode the digest.
108
+ * 5. Compare with the `X-Plivo-Signature-V3` header.
109
+ *
110
+ * @param ctx - Raw webhook request context.
111
+ * @returns Verification result with `valid: true` if the signature matches.
43
112
  */
44
113
  verifyWebhook(ctx) {
45
114
  const nonce = ctx.headers['x-plivo-signature-v3-nonce'];
@@ -47,6 +116,8 @@ export class PlivoVoiceProvider {
47
116
  if (Array.isArray(nonce) || Array.isArray(signature)) {
48
117
  return { valid: false, error: 'Duplicate Plivo signature headers' };
49
118
  }
119
+ // Use empty string as nonce fallback when header is missing --
120
+ // the HMAC will still compute but won't match the expected signature.
50
121
  const nonceStr = nonce ?? '';
51
122
  const data = ctx.url + nonceStr;
52
123
  const expected = createHmac('sha256', this.config.authToken)
@@ -58,8 +129,17 @@ export class PlivoVoiceProvider {
58
129
  /**
59
130
  * Parse a Plivo webhook body into normalized {@link NormalizedCallEvent}s.
60
131
  *
61
- * Supports both URL-encoded and JSON request bodies. Maps `CallStatus`
62
- * parameter values to call lifecycle events.
132
+ * Plivo sends most webhooks with URL-encoded bodies, but some callbacks
133
+ * may arrive as JSON. This parser handles both formats by inspecting
134
+ * whether the body starts with `{` (JSON) or not (form-encoded).
135
+ *
136
+ * Plivo uses two naming conventions for the same fields:
137
+ * - PascalCase (`CallUUID`, `CallStatus`, `Digits`) in URL callbacks.
138
+ * - snake_case (`call_uuid`, `call_status`) in some API responses.
139
+ * Both are checked for maximum compatibility.
140
+ *
141
+ * @param ctx - Raw webhook request context.
142
+ * @returns Parsed result containing zero or more normalized events.
63
143
  */
64
144
  parseWebhookEvent(ctx) {
65
145
  const body = ctx.body.toString();
@@ -77,16 +157,19 @@ export class PlivoVoiceProvider {
77
157
  catch {
78
158
  params = new URLSearchParams(body);
79
159
  }
160
+ // Support both PascalCase and snake_case field naming conventions.
80
161
  const callUuid = params.get('CallUUID') ?? params.get('call_uuid') ?? '';
81
162
  const callStatus = params.get('CallStatus') ?? params.get('call_status') ?? '';
82
163
  const digits = params.get('Digits');
83
164
  const timestamp = Date.now();
84
165
  const events = [];
166
+ /** Helper: shared base fields with a unique event ID for idempotency. */
85
167
  const base = () => ({
86
168
  eventId: randomUUID(),
87
169
  providerCallId: callUuid,
88
170
  timestamp,
89
171
  });
172
+ // Map Plivo CallStatus values to normalized event kinds.
90
173
  switch (callStatus) {
91
174
  case 'ringing':
92
175
  events.push({ ...base(), kind: 'call-ringing' });
@@ -107,9 +190,10 @@ export class PlivoVoiceProvider {
107
190
  events.push({ ...base(), kind: 'call-failed' });
108
191
  break;
109
192
  default:
110
- // initiated / queued / etc. no normalized event emitted
193
+ // initiated / queued / etc. -- no normalized event emitted.
111
194
  break;
112
195
  }
196
+ // DTMF digit input (from <GetDigits> XML element callback).
113
197
  if (digits != null && digits !== '') {
114
198
  events.push({ ...base(), kind: 'call-dtmf', digit: digits });
115
199
  }
@@ -119,8 +203,12 @@ export class PlivoVoiceProvider {
119
203
  /**
120
204
  * Initiate an outbound call via the Plivo Call API.
121
205
  *
122
- * POSTs a JSON body to `/Account/{authId}/Call/` with the caller, callee,
206
+ * POSTs a JSON body to `/v1/Account/{authId}/Call/` with the caller, callee,
123
207
  * and answer URL. Returns the `request_uuid` as the provider call ID.
208
+ *
209
+ * @param input - Call initiation parameters (from/to numbers, webhook URL).
210
+ * @returns Result containing the Plivo `request_uuid` on success.
211
+ * @throws Never throws; returns `{ success: false, error: '...' }` on failure.
124
212
  */
125
213
  async initiateCall(input) {
126
214
  const url = `${this.baseUrl}/Account/${this.config.authId}/Call/`;
@@ -146,6 +234,12 @@ export class PlivoVoiceProvider {
146
234
  }
147
235
  /**
148
236
  * Hang up an active call using the Plivo Call DELETE endpoint.
237
+ *
238
+ * Plivo uses HTTP `DELETE` to terminate a call (unlike Twilio's POST with
239
+ * `Status=completed` or Telnyx's POST to `/actions/hangup`). This is a
240
+ * RESTful convention where deleting the call resource ends the call.
241
+ *
242
+ * @param input - Contains the Plivo `call_uuid` to hang up.
149
243
  */
150
244
  async hangupCall(input) {
151
245
  const url = `${this.baseUrl}/Account/${this.config.authId}/Call/${input.providerCallId}/`;
@@ -159,7 +253,10 @@ export class PlivoVoiceProvider {
159
253
  /**
160
254
  * Speak text into a live call using the Plivo Speak API.
161
255
  *
162
- * Defaults to `WOMAN` voice and `en-US` language when not specified.
256
+ * POSTs a JSON body to `/v1/Account/{authId}/Call/{callUuid}/Speak/`
257
+ * with the text, voice (default `'WOMAN'`), and language (default `'en-US'`).
258
+ *
259
+ * @param input - TTS parameters (text, optional voice, call ID).
163
260
  */
164
261
  async playTts(input) {
165
262
  const url = `${this.baseUrl}/Account/${this.config.authId}/Call/${input.providerCallId}/Speak/`;
@@ -1 +1 @@
1
- {"version":3,"file":"plivo.js","sourceRoot":"","sources":["../../../src/voice/providers/plivo.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"plivo.js","sourceRoot":"","sources":["../../../src/voice/providers/plivo.ts"],"names":[],"mappings":"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"}
@@ -2,14 +2,64 @@
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
  */
10
58
  import type { IVoiceCallProvider, InitiateCallInput, InitiateCallResult, HangupCallInput, PlayTtsInput } from '../IVoiceCallProvider.js';
11
59
  import type { WebhookContext, WebhookVerificationResult, WebhookParseResult } from '../types.js';
12
- /** Configuration for {@link TelnyxVoiceProvider}. */
60
+ /**
61
+ * Configuration for {@link TelnyxVoiceProvider}.
62
+ */
13
63
  export interface TelnyxVoiceProviderConfig {
14
64
  /** Telnyx API key (starts with "KEY"). */
15
65
  apiKey: string;
@@ -17,11 +67,13 @@ export interface TelnyxVoiceProviderConfig {
17
67
  connectionId: string;
18
68
  /**
19
69
  * Base64-encoded DER-encoded SPKI Ed25519 public key for webhook verification.
20
- * When omitted, webhook verification is skipped.
70
+ *
71
+ * When omitted, webhook verification is skipped (always returns `valid: true`).
72
+ * This is acceptable for development but should always be set in production.
21
73
  */
22
74
  publicKey?: string;
23
75
  /**
24
- * Optional fetch override inject a mock in tests.
76
+ * Optional fetch implementation override -- inject a mock in tests.
25
77
  * Defaults to the global `fetch`.
26
78
  */
27
79
  fetchImpl?: typeof fetch;
@@ -43,50 +95,88 @@ export interface TelnyxVoiceProviderConfig {
43
95
  * ```
44
96
  */
45
97
  export declare class TelnyxVoiceProvider implements IVoiceCallProvider {
98
+ /** Provider identifier, always `'telnyx'`. */
46
99
  readonly name: "telnyx";
100
+ /** Immutable configuration snapshot. */
47
101
  private readonly config;
102
+ /** Base URL for the Telnyx v2 API. */
48
103
  private readonly baseUrl;
104
+ /** Pre-computed `Authorization: Bearer ...` header value. */
49
105
  private readonly authHeader;
106
+ /** HTTP fetch implementation (injectable for testing). */
50
107
  private readonly fetch;
108
+ /**
109
+ * @param config - Telnyx credentials and optional overrides.
110
+ */
51
111
  constructor(config: TelnyxVoiceProviderConfig);
52
112
  /**
53
113
  * Verify an incoming Telnyx webhook using Ed25519 signature verification.
54
114
  *
55
- * Telnyx signs `{timestamp}|{rawBody}` with the configured Ed25519 private key.
56
- * The matching public key is provided as a base64-encoded DER SPKI blob.
115
+ * ## Algorithm (step by step)
116
+ *
117
+ * 1. If no public key is configured, skip verification (return `valid: true`).
118
+ * This supports development environments without cryptographic setup.
119
+ * 2. Extract `X-Telnyx-Timestamp` and `X-Telnyx-Signature-Ed25519` headers.
120
+ * 3. Decode the signature from base64 into a raw byte Buffer.
121
+ * 4. Construct the signed payload: `"{timestamp}|{rawBody}"`.
122
+ * 5. Decode the SPKI public key from base64.
123
+ * 6. Call `crypto.verify(null, payload, { key, format: 'der', type: 'spki' }, signature)`.
124
+ * 7. Return the verification result.
57
125
  *
58
- * If no public key is configured, the check is skipped and `valid: true`
59
- * is returned so the provider can operate without cryptographic validation
60
- * during initial development.
126
+ * @param ctx - Raw webhook request context.
127
+ * @returns Verification result. Returns `{ valid: true }` when no public key
128
+ * is configured (development mode).
61
129
  */
62
130
  verifyWebhook(ctx: WebhookContext): WebhookVerificationResult;
63
131
  /**
64
132
  * Parse a Telnyx webhook JSON body into normalized {@link NormalizedCallEvent}s.
65
133
  *
66
- * Handles Telnyx Call Control event types:
67
- * - `call.initiated` `call-ringing`
68
- * - `call.answered` `call-answered`
69
- * - `call.hangup` → `call-completed` or `call-hangup-user` based on hangup_cause
70
- * - `call.dtmf.received` `call-dtmf`
71
- * - `call.machine.detection.ended` with `result === 'machine'` → `call-voicemail`
134
+ * Telnyx sends all webhook payloads as JSON with a `data.event_type`
135
+ * discriminant field. The `data.payload` object contains call-specific
136
+ * fields like `call_control_id`, `hangup_cause`, `digit`, and `result`.
137
+ *
138
+ * ## Hangup cause mapping
139
+ *
140
+ * Telnyx's `call.hangup` event includes a `hangup_cause` field that must
141
+ * be inspected to determine whether the user or the system terminated
142
+ * the call:
143
+ * - `normal_clearing` / `user_busy` / `originator_cancel` -> `call-hangup-user`
144
+ * - All other causes (e.g., `call_rejected`, `unallocated_number`) -> `call-completed`
145
+ *
146
+ * @param ctx - Raw webhook request context.
147
+ * @returns Parsed result containing zero or more normalized events.
72
148
  */
73
149
  parseWebhookEvent(ctx: WebhookContext): WebhookParseResult;
74
150
  /**
75
151
  * Initiate an outbound call via the Telnyx Call Control v2 API.
76
152
  *
77
- * POSTs to `/calls` with a JSON body. The `mediaStreamUrl` (if provided)
78
- * is stored internally for use after the call is answered — it is NOT sent
79
- * in the initial call creation request.
153
+ * POSTs to `/v2/calls` with a JSON body containing the `connection_id`,
154
+ * phone numbers, and webhook URL. The `mediaStreamUrl` (if provided) is
155
+ * stored internally for use after the call is answered -- it is NOT sent
156
+ * in the initial call creation request because Telnyx requires
157
+ * `streaming_start` to be issued as a separate action after `call.answered`.
158
+ *
159
+ * @param input - Call initiation parameters (from/to numbers, webhook URL).
160
+ * @returns Result containing the Telnyx `call_control_id` on success.
161
+ * @throws Never throws; returns `{ success: false, error: '...' }` on failure.
80
162
  */
81
163
  initiateCall(input: InitiateCallInput): Promise<InitiateCallResult>;
82
164
  /**
83
165
  * Hang up an active call via the Telnyx Call Control hangup action.
166
+ *
167
+ * POSTs an empty JSON body to `/v2/calls/{call_control_id}/actions/hangup`.
168
+ * Telnyx will terminate the call and fire a `call.hangup` webhook.
169
+ *
170
+ * @param input - Contains the Telnyx `call_control_id` to hang up.
84
171
  */
85
172
  hangupCall(input: HangupCallInput): Promise<void>;
86
173
  /**
87
174
  * Speak text into a live call using Telnyx's text-to-speech speak action.
88
175
  *
89
- * Defaults to `female` voice and `en-US` language when not specified.
176
+ * POSTs a JSON body to `/v2/calls/{id}/actions/speak` with the text
177
+ * `payload`, `voice` (default `'female'`), and `language` (default `'en-US'`).
178
+ *
179
+ * @param input - TTS parameters (text, optional voice, call ID).
90
180
  */
91
181
  playTts(input: PlayTtsInput): Promise<void>;
92
182
  }
@@ -1 +1 @@
1
- {"version":3,"file":"telnyx.d.ts","sourceRoot":"","sources":["../../../src/voice/providers/telnyx.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;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,0CAA0C;IAC1C,MAAM,EAAE,MAAM,CAAC;IACf,yDAAyD;IACzD,YAAY,EAAE,MAAM,CAAC;IACrB;;;OAGG;IACH,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB;;;OAGG;IACH,SAAS,CAAC,EAAE,OAAO,KAAK,CAAC;CAC1B;AAyBD;;;;;;;;;;;;;;;GAeG;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;IAS7C;;;;;;;;;OASG;IACH,aAAa,CAAC,GAAG,EAAE,cAAc,GAAG,yBAAyB;IAgC7D;;;;;;;;;OASG;IACH,iBAAiB,CAAC,GAAG,EAAE,cAAc,GAAG,kBAAkB;IAyD1D;;;;;;OAMG;IACG,YAAY,CAAC,KAAK,EAAE,iBAAiB,GAAG,OAAO,CAAC,kBAAkB,CAAC;IA0BzE;;OAEG;IACG,UAAU,CAAC,KAAK,EAAE,eAAe,GAAG,OAAO,CAAC,IAAI,CAAC;IAavD;;;;OAIG;IACG,OAAO,CAAC,KAAK,EAAE,YAAY,GAAG,OAAO,CAAC,IAAI,CAAC;CAgBlD"}
1
+ {"version":3,"file":"telnyx.d.ts","sourceRoot":"","sources":["../../../src/voice/providers/telnyx.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAwDG;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,0CAA0C;IAC1C,MAAM,EAAE,MAAM,CAAC;IACf,yDAAyD;IACzD,YAAY,EAAE,MAAM,CAAC;IACrB;;;;;OAKG;IACH,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB;;;OAGG;IACH,SAAS,CAAC,EAAE,OAAO,KAAK,CAAC;CAC1B;AAiCD;;;;;;;;;;;;;;;GAeG;AACH,qBAAa,mBAAoB,YAAW,kBAAkB;IAC5D,8CAA8C;IAC9C,QAAQ,CAAC,IAAI,EAAG,QAAQ,CAAU;IAElC,wCAAwC;IACxC,OAAO,CAAC,QAAQ,CAAC,MAAM,CAA4B;IAEnD,sCAAsC;IACtC,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAS;IAEjC,6DAA6D;IAC7D,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAS;IAEpC,0DAA0D;IAC1D,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAe;IAErC;;OAEG;gBACS,MAAM,EAAE,yBAAyB;IAS7C;;;;;;;;;;;;;;;;;OAiBG;IACH,aAAa,CAAC,GAAG,EAAE,cAAc,GAAG,yBAAyB;IAoC7D;;;;;;;;;;;;;;;;;OAiBG;IACH,iBAAiB,CAAC,GAAG,EAAE,cAAc,GAAG,kBAAkB;IA6D1D;;;;;;;;;;;;OAYG;IACG,YAAY,CAAC,KAAK,EAAE,iBAAiB,GAAG,OAAO,CAAC,kBAAkB,CAAC;IA0BzE;;;;;;;OAOG;IACG,UAAU,CAAC,KAAK,EAAE,eAAe,GAAG,OAAO,CAAC,IAAI,CAAC;IAavD;;;;;;;OAOG;IACG,OAAO,CAAC,KAAK,EAAE,YAAY,GAAG,OAAO,CAAC,IAAI,CAAC;CAgBlD"}