telnyx-mcp-server-fastmcp 0.1.3__py3-none-any.whl
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.
- telnyx_mcp_server/__init__.py +0 -0
- telnyx_mcp_server/__main__.py +23 -0
- telnyx_mcp_server/config.py +148 -0
- telnyx_mcp_server/mcp.py +148 -0
- telnyx_mcp_server/server.py +497 -0
- telnyx_mcp_server/telnyx/__init__.py +1 -0
- telnyx_mcp_server/telnyx/client.py +363 -0
- telnyx_mcp_server/telnyx/services/__init__.py +0 -0
- telnyx_mcp_server/telnyx/services/assistants.py +155 -0
- telnyx_mcp_server/telnyx/services/call_control.py +217 -0
- telnyx_mcp_server/telnyx/services/cloud_storage.py +289 -0
- telnyx_mcp_server/telnyx/services/connections.py +92 -0
- telnyx_mcp_server/telnyx/services/embeddings.py +52 -0
- telnyx_mcp_server/telnyx/services/messaging.py +93 -0
- telnyx_mcp_server/telnyx/services/messaging_profiles.py +196 -0
- telnyx_mcp_server/telnyx/services/numbers.py +193 -0
- telnyx_mcp_server/telnyx/services/secrets.py +74 -0
- telnyx_mcp_server/tools/__init__.py +126 -0
- telnyx_mcp_server/tools/assistants.py +313 -0
- telnyx_mcp_server/tools/call_control.py +242 -0
- telnyx_mcp_server/tools/cloud_storage.py +183 -0
- telnyx_mcp_server/tools/connections.py +78 -0
- telnyx_mcp_server/tools/embeddings.py +80 -0
- telnyx_mcp_server/tools/messaging.py +57 -0
- telnyx_mcp_server/tools/messaging_profiles.py +123 -0
- telnyx_mcp_server/tools/phone_numbers.py +161 -0
- telnyx_mcp_server/tools/secrets.py +75 -0
- telnyx_mcp_server/tools/sms_conversations.py +455 -0
- telnyx_mcp_server/tools/webhooks.py +111 -0
- telnyx_mcp_server/utils/__init__.py +0 -0
- telnyx_mcp_server/utils/error_handler.py +30 -0
- telnyx_mcp_server/utils/logger.py +32 -0
- telnyx_mcp_server/utils/service.py +33 -0
- telnyx_mcp_server/webhook/__init__.py +25 -0
- telnyx_mcp_server/webhook/handler.py +596 -0
- telnyx_mcp_server/webhook/server.py +369 -0
- telnyx_mcp_server_fastmcp-0.1.3.dist-info/METADATA +430 -0
- telnyx_mcp_server_fastmcp-0.1.3.dist-info/RECORD +40 -0
- telnyx_mcp_server_fastmcp-0.1.3.dist-info/WHEEL +4 -0
- telnyx_mcp_server_fastmcp-0.1.3.dist-info/entry_points.txt +3 -0
|
@@ -0,0 +1,363 @@
|
|
|
1
|
+
"""Telnyx API client."""
|
|
2
|
+
|
|
3
|
+
from typing import Any, Dict, Optional
|
|
4
|
+
|
|
5
|
+
import requests
|
|
6
|
+
|
|
7
|
+
from ..config import settings
|
|
8
|
+
from ..utils.logger import get_logger
|
|
9
|
+
|
|
10
|
+
logger = get_logger(__name__)
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
def mask_sensitive_data(data: Dict) -> Dict:
|
|
14
|
+
"""Mask sensitive data in dictionaries.
|
|
15
|
+
|
|
16
|
+
Args:
|
|
17
|
+
data: Dictionary potentially containing sensitive data
|
|
18
|
+
|
|
19
|
+
Returns:
|
|
20
|
+
Dict: Masked dictionary
|
|
21
|
+
"""
|
|
22
|
+
result = {}
|
|
23
|
+
|
|
24
|
+
for key, value in data.items():
|
|
25
|
+
# Mask sensitive keys
|
|
26
|
+
if any(
|
|
27
|
+
sensitive in key.lower()
|
|
28
|
+
for sensitive in ["key", "token", "auth", "password", "secret"]
|
|
29
|
+
):
|
|
30
|
+
if isinstance(value, str):
|
|
31
|
+
if len(value) > 8:
|
|
32
|
+
result[key] = f"{value[:5]}...{value[-3:]}"
|
|
33
|
+
else:
|
|
34
|
+
result[key] = "[REDACTED]"
|
|
35
|
+
else:
|
|
36
|
+
result[key] = "[REDACTED]"
|
|
37
|
+
# Handle nested dictionaries
|
|
38
|
+
elif isinstance(value, dict):
|
|
39
|
+
result[key] = mask_sensitive_data(value)
|
|
40
|
+
# Handle lists potentially containing dictionaries
|
|
41
|
+
elif isinstance(value, list):
|
|
42
|
+
if value and isinstance(value[0], dict):
|
|
43
|
+
result[key] = [
|
|
44
|
+
mask_sensitive_data(item)
|
|
45
|
+
if isinstance(item, dict)
|
|
46
|
+
else item
|
|
47
|
+
for item in value
|
|
48
|
+
]
|
|
49
|
+
else:
|
|
50
|
+
result[key] = value
|
|
51
|
+
else:
|
|
52
|
+
result[key] = value
|
|
53
|
+
|
|
54
|
+
return result
|
|
55
|
+
|
|
56
|
+
|
|
57
|
+
class TelnyxClient:
|
|
58
|
+
"""Telnyx API client."""
|
|
59
|
+
|
|
60
|
+
def __init__(
|
|
61
|
+
self,
|
|
62
|
+
api_key: Optional[str] = None,
|
|
63
|
+
base_url: Optional[str] = None,
|
|
64
|
+
headers: Optional[Dict[str, str]] = None,
|
|
65
|
+
):
|
|
66
|
+
"""Initialize the client.
|
|
67
|
+
|
|
68
|
+
Args:
|
|
69
|
+
api_key: Telnyx API key (optional if provided in headers)
|
|
70
|
+
base_url: Base URL for Telnyx API (optional)
|
|
71
|
+
headers: Optional headers dictionary containing authorization
|
|
72
|
+
"""
|
|
73
|
+
logger.debug("Initializing TelnyxClient")
|
|
74
|
+
self.api_key = api_key
|
|
75
|
+
|
|
76
|
+
# Extract API key from headers if available
|
|
77
|
+
if headers:
|
|
78
|
+
logger.debug("Headers provided, checking for authorization")
|
|
79
|
+
|
|
80
|
+
# Check Authorization header
|
|
81
|
+
if "authorization" in headers:
|
|
82
|
+
auth_header = headers.get("authorization", "")
|
|
83
|
+
|
|
84
|
+
# Extract token from Bearer header
|
|
85
|
+
if auth_header.lower().startswith("bearer "):
|
|
86
|
+
self.api_key = auth_header[7:] # Remove "Bearer " prefix
|
|
87
|
+
logger.debug(
|
|
88
|
+
"Got API key from Bearer authorization header"
|
|
89
|
+
)
|
|
90
|
+
else:
|
|
91
|
+
logger.debug("No API key in headers")
|
|
92
|
+
|
|
93
|
+
# Use the default API key from settings if none found
|
|
94
|
+
if not self.api_key:
|
|
95
|
+
logger.debug("Using default API key from settings")
|
|
96
|
+
self.api_key = settings.telnyx_api_key
|
|
97
|
+
|
|
98
|
+
# Log API key info (first few chars only for security)
|
|
99
|
+
if self.api_key:
|
|
100
|
+
masked_key = (
|
|
101
|
+
"NONE"
|
|
102
|
+
if not self.api_key
|
|
103
|
+
else f"{self.api_key[:5]}..."
|
|
104
|
+
if len(self.api_key) > 5
|
|
105
|
+
else "[REDACTED]"
|
|
106
|
+
)
|
|
107
|
+
logger.debug(f"API key (masked): {masked_key}")
|
|
108
|
+
else:
|
|
109
|
+
logger.warning("No API key available")
|
|
110
|
+
|
|
111
|
+
self.base_url = base_url or settings.telnyx_api_base_url
|
|
112
|
+
logger.debug(f"Using base URL: {self.base_url}")
|
|
113
|
+
|
|
114
|
+
self.session = requests.Session()
|
|
115
|
+
logger.debug("Created requests Session")
|
|
116
|
+
|
|
117
|
+
# Set up headers with authorization
|
|
118
|
+
header_dict = {
|
|
119
|
+
"Authorization": f"Bearer {self.api_key}",
|
|
120
|
+
"Content-Type": "application/json",
|
|
121
|
+
"Accept": "application/json",
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
logger.debug(f"Setting headers: {', '.join(header_dict.keys())}")
|
|
125
|
+
self.session.headers.update(header_dict)
|
|
126
|
+
logger.debug("TelnyxClient initialization complete")
|
|
127
|
+
|
|
128
|
+
def get(
|
|
129
|
+
self, path: str, params: Optional[Dict[str, Any]] = None
|
|
130
|
+
) -> Dict[str, Any]:
|
|
131
|
+
"""Make a GET request to the Telnyx API.
|
|
132
|
+
|
|
133
|
+
Args:
|
|
134
|
+
path: API path
|
|
135
|
+
params: Query parameters
|
|
136
|
+
|
|
137
|
+
Returns:
|
|
138
|
+
Dict[str, Any]: Response data
|
|
139
|
+
"""
|
|
140
|
+
url = f"{self.base_url}/{path.lstrip('/')}"
|
|
141
|
+
logger.info(f"TELNYX REQUEST: GET {url}")
|
|
142
|
+
logger.debug(f"TELNYX REQUEST PARAMS: {params}")
|
|
143
|
+
|
|
144
|
+
# Log masked headers at debug level
|
|
145
|
+
header_dict = dict(self.session.headers)
|
|
146
|
+
masked_headers = mask_sensitive_data(header_dict)
|
|
147
|
+
logger.debug(f"TELNYX REQUEST HEADERS: {masked_headers}")
|
|
148
|
+
|
|
149
|
+
try:
|
|
150
|
+
response = self.session.get(url, params=params)
|
|
151
|
+
logger.info(f"TELNYX RESPONSE STATUS: {response.status_code}")
|
|
152
|
+
logger.debug(f"TELNYX RESPONSE HEADERS: {dict(response.headers)}")
|
|
153
|
+
|
|
154
|
+
if response.status_code >= 400:
|
|
155
|
+
logger.error(f"TELNYX ERROR RESPONSE BODY: {response.text}")
|
|
156
|
+
else:
|
|
157
|
+
# Log a snippet of the successful response
|
|
158
|
+
try:
|
|
159
|
+
response_json = response.json()
|
|
160
|
+
# Log full response at debug level, truncated at info level
|
|
161
|
+
logger.debug(
|
|
162
|
+
f"TELNYX RESPONSE FULL: {mask_sensitive_data(response_json)}"
|
|
163
|
+
)
|
|
164
|
+
logger.info(
|
|
165
|
+
f"TELNYX RESPONSE PREVIEW: {str(response_json)[:200]}..."
|
|
166
|
+
)
|
|
167
|
+
except Exception as json_err:
|
|
168
|
+
logger.warning(
|
|
169
|
+
f"Could not parse response as JSON: {json_err}"
|
|
170
|
+
)
|
|
171
|
+
|
|
172
|
+
response.raise_for_status()
|
|
173
|
+
return response.json()
|
|
174
|
+
except Exception as e:
|
|
175
|
+
logger.error(f"TELNYX REQUEST ERROR: {str(e)}")
|
|
176
|
+
raise
|
|
177
|
+
|
|
178
|
+
def post(self, path: str, data: Dict[str, Any]) -> Dict[str, Any]:
|
|
179
|
+
"""Make a POST request to the Telnyx API.
|
|
180
|
+
|
|
181
|
+
Args:
|
|
182
|
+
path: API path
|
|
183
|
+
data: Request data
|
|
184
|
+
|
|
185
|
+
Returns:
|
|
186
|
+
Dict[str, Any]: Response data
|
|
187
|
+
"""
|
|
188
|
+
url = f"{self.base_url}/{path.lstrip('/')}"
|
|
189
|
+
logger.info(f"TELNYX REQUEST: POST {url}")
|
|
190
|
+
|
|
191
|
+
# Log request data at debug level with sensitive information masked
|
|
192
|
+
masked_data = mask_sensitive_data(data)
|
|
193
|
+
logger.debug(f"TELNYX REQUEST DATA: {masked_data}")
|
|
194
|
+
|
|
195
|
+
# Log masked headers at debug level
|
|
196
|
+
header_dict = dict(self.session.headers)
|
|
197
|
+
masked_headers = mask_sensitive_data(header_dict)
|
|
198
|
+
logger.debug(f"TELNYX REQUEST HEADERS: {masked_headers}")
|
|
199
|
+
|
|
200
|
+
try:
|
|
201
|
+
response = self.session.post(url, json=data)
|
|
202
|
+
logger.info(f"TELNYX RESPONSE STATUS: {response.status_code}")
|
|
203
|
+
logger.debug(f"TELNYX RESPONSE HEADERS: {dict(response.headers)}")
|
|
204
|
+
|
|
205
|
+
if response.status_code >= 400:
|
|
206
|
+
logger.error(f"TELNYX ERROR RESPONSE BODY: {response.text}")
|
|
207
|
+
else:
|
|
208
|
+
# Log a snippet of the successful response
|
|
209
|
+
try:
|
|
210
|
+
response_json = response.json()
|
|
211
|
+
# Log full response at debug level, truncated at info level
|
|
212
|
+
logger.debug(
|
|
213
|
+
f"TELNYX RESPONSE FULL: {mask_sensitive_data(response_json)}"
|
|
214
|
+
)
|
|
215
|
+
logger.info(
|
|
216
|
+
f"TELNYX RESPONSE PREVIEW: {str(response_json)[:200]}..."
|
|
217
|
+
)
|
|
218
|
+
except Exception as json_err:
|
|
219
|
+
logger.warning(
|
|
220
|
+
f"Could not parse response as JSON: {json_err}"
|
|
221
|
+
)
|
|
222
|
+
|
|
223
|
+
response.raise_for_status()
|
|
224
|
+
return response.json()
|
|
225
|
+
except Exception as e:
|
|
226
|
+
logger.error(f"TELNYX REQUEST ERROR: {str(e)}")
|
|
227
|
+
raise
|
|
228
|
+
|
|
229
|
+
def put(self, path: str, data: Dict[str, Any]) -> Dict[str, Any]:
|
|
230
|
+
"""Make a PUT request to the Telnyx API.
|
|
231
|
+
|
|
232
|
+
Args:
|
|
233
|
+
path: API path
|
|
234
|
+
data: Request data
|
|
235
|
+
|
|
236
|
+
Returns:
|
|
237
|
+
Dict[str, Any]: Response data
|
|
238
|
+
"""
|
|
239
|
+
url = f"{self.base_url}/{path.lstrip('/')}"
|
|
240
|
+
logger.info(f"TELNYX REQUEST: PUT {url}")
|
|
241
|
+
|
|
242
|
+
# Log request data at debug level with sensitive information masked
|
|
243
|
+
masked_data = mask_sensitive_data(data)
|
|
244
|
+
logger.debug(f"TELNYX REQUEST DATA: {masked_data}")
|
|
245
|
+
|
|
246
|
+
# Log masked headers at debug level
|
|
247
|
+
header_dict = dict(self.session.headers)
|
|
248
|
+
masked_headers = mask_sensitive_data(header_dict)
|
|
249
|
+
logger.debug(f"TELNYX REQUEST HEADERS: {masked_headers}")
|
|
250
|
+
|
|
251
|
+
try:
|
|
252
|
+
response = self.session.put(url, json=data)
|
|
253
|
+
logger.info(f"TELNYX RESPONSE STATUS: {response.status_code}")
|
|
254
|
+
logger.debug(f"TELNYX RESPONSE HEADERS: {dict(response.headers)}")
|
|
255
|
+
|
|
256
|
+
if response.status_code >= 400:
|
|
257
|
+
logger.error(f"TELNYX ERROR RESPONSE BODY: {response.text}")
|
|
258
|
+
else:
|
|
259
|
+
# Log a snippet of the successful response
|
|
260
|
+
try:
|
|
261
|
+
response_json = response.json()
|
|
262
|
+
# Log full response at debug level, truncated at info level
|
|
263
|
+
logger.debug(
|
|
264
|
+
f"TELNYX RESPONSE FULL: {mask_sensitive_data(response_json)}"
|
|
265
|
+
)
|
|
266
|
+
logger.info(
|
|
267
|
+
f"TELNYX RESPONSE PREVIEW: {str(response_json)[:200]}..."
|
|
268
|
+
)
|
|
269
|
+
except Exception as json_err:
|
|
270
|
+
logger.warning(
|
|
271
|
+
f"Could not parse response as JSON: {json_err}"
|
|
272
|
+
)
|
|
273
|
+
|
|
274
|
+
response.raise_for_status()
|
|
275
|
+
return response.json()
|
|
276
|
+
except Exception as e:
|
|
277
|
+
logger.error(f"TELNYX REQUEST ERROR: {str(e)}")
|
|
278
|
+
raise
|
|
279
|
+
|
|
280
|
+
def patch(self, path: str, data: Dict[str, Any]) -> Dict[str, Any]:
|
|
281
|
+
"""Make a PATCH request to the Telnyx API.
|
|
282
|
+
|
|
283
|
+
Args:
|
|
284
|
+
path: API path
|
|
285
|
+
data: Request data
|
|
286
|
+
|
|
287
|
+
Returns:
|
|
288
|
+
Dict[str, Any]: Response data
|
|
289
|
+
"""
|
|
290
|
+
url = f"{self.base_url}/{path.lstrip('/')}"
|
|
291
|
+
logger.info(f"TELNYX REQUEST: PATCH {url}")
|
|
292
|
+
|
|
293
|
+
# Log request data at debug level with sensitive information masked
|
|
294
|
+
masked_data = mask_sensitive_data(data)
|
|
295
|
+
logger.debug(f"TELNYX REQUEST DATA: {masked_data}")
|
|
296
|
+
|
|
297
|
+
# Log masked headers at debug level
|
|
298
|
+
header_dict = dict(self.session.headers)
|
|
299
|
+
masked_headers = mask_sensitive_data(header_dict)
|
|
300
|
+
logger.debug(f"TELNYX REQUEST HEADERS: {masked_headers}")
|
|
301
|
+
|
|
302
|
+
try:
|
|
303
|
+
response = self.session.patch(url, json=data)
|
|
304
|
+
logger.info(f"TELNYX RESPONSE STATUS: {response.status_code}")
|
|
305
|
+
logger.debug(f"TELNYX RESPONSE HEADERS: {dict(response.headers)}")
|
|
306
|
+
|
|
307
|
+
if response.status_code >= 400:
|
|
308
|
+
logger.error(f"TELNYX ERROR RESPONSE BODY: {response.text}")
|
|
309
|
+
else:
|
|
310
|
+
# Log a snippet of the successful response
|
|
311
|
+
try:
|
|
312
|
+
response_json = response.json()
|
|
313
|
+
# Log full response at debug level, truncated at info level
|
|
314
|
+
logger.debug(
|
|
315
|
+
f"TELNYX RESPONSE FULL: {mask_sensitive_data(response_json)}"
|
|
316
|
+
)
|
|
317
|
+
logger.info(
|
|
318
|
+
f"TELNYX RESPONSE PREVIEW: {str(response_json)[:200]}..."
|
|
319
|
+
)
|
|
320
|
+
except Exception as json_err:
|
|
321
|
+
logger.warning(
|
|
322
|
+
f"Could not parse response as JSON: {json_err}"
|
|
323
|
+
)
|
|
324
|
+
|
|
325
|
+
response.raise_for_status()
|
|
326
|
+
return response.json()
|
|
327
|
+
except Exception as e:
|
|
328
|
+
logger.error(f"TELNYX REQUEST ERROR: {str(e)}")
|
|
329
|
+
raise
|
|
330
|
+
|
|
331
|
+
def delete(self, path: str) -> Dict[str, Any]:
|
|
332
|
+
"""Make a DELETE request to the Telnyx API.
|
|
333
|
+
|
|
334
|
+
Args:
|
|
335
|
+
path: API path
|
|
336
|
+
|
|
337
|
+
Returns:
|
|
338
|
+
Dict[str, Any]: Response data
|
|
339
|
+
"""
|
|
340
|
+
url = f"{self.base_url}/{path.lstrip('/')}"
|
|
341
|
+
logger.info(f"TELNYX REQUEST: DELETE {url}")
|
|
342
|
+
|
|
343
|
+
# Log masked headers at debug level
|
|
344
|
+
header_dict = dict(self.session.headers)
|
|
345
|
+
masked_headers = mask_sensitive_data(header_dict)
|
|
346
|
+
logger.debug(f"TELNYX REQUEST HEADERS: {masked_headers}")
|
|
347
|
+
|
|
348
|
+
try:
|
|
349
|
+
response = self.session.delete(url)
|
|
350
|
+
logger.info(f"TELNYX RESPONSE STATUS: {response.status_code}")
|
|
351
|
+
logger.debug(f"TELNYX RESPONSE HEADERS: {dict(response.headers)}")
|
|
352
|
+
|
|
353
|
+
if response.status_code >= 400:
|
|
354
|
+
logger.error(f"TELNYX ERROR RESPONSE BODY: {response.text}")
|
|
355
|
+
|
|
356
|
+
response.raise_for_status()
|
|
357
|
+
# Handle empty responses
|
|
358
|
+
if not response.text:
|
|
359
|
+
return {}
|
|
360
|
+
return response.json()
|
|
361
|
+
except Exception as e:
|
|
362
|
+
logger.error(f"TELNYX REQUEST ERROR: {str(e)}")
|
|
363
|
+
raise
|
|
File without changes
|
|
@@ -0,0 +1,155 @@
|
|
|
1
|
+
"""Telnyx AI Assistants service."""
|
|
2
|
+
|
|
3
|
+
from typing import Any, Dict, Optional
|
|
4
|
+
|
|
5
|
+
from ..client import TelnyxClient
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
class AssistantsService:
|
|
9
|
+
"""Service for managing Telnyx AI Assistants."""
|
|
10
|
+
|
|
11
|
+
def __init__(self, client: TelnyxClient) -> None:
|
|
12
|
+
"""Initialize the service.
|
|
13
|
+
|
|
14
|
+
Args:
|
|
15
|
+
client: Telnyx API client
|
|
16
|
+
"""
|
|
17
|
+
self.client = client
|
|
18
|
+
|
|
19
|
+
def create_assistant(
|
|
20
|
+
self,
|
|
21
|
+
request: Dict[str, Any],
|
|
22
|
+
) -> Dict[str, Any]:
|
|
23
|
+
"""Create a new AI Assistant.
|
|
24
|
+
|
|
25
|
+
Args:
|
|
26
|
+
request: Assistant creation request data
|
|
27
|
+
|
|
28
|
+
Returns:
|
|
29
|
+
Dict[str, Any]: Created assistant data
|
|
30
|
+
"""
|
|
31
|
+
# Hard code voice settings and enabled features
|
|
32
|
+
request["voice_settings"] = {
|
|
33
|
+
"voice": "Telnyx.KokoroTTS.af_heart",
|
|
34
|
+
"api_key_ref": None,
|
|
35
|
+
}
|
|
36
|
+
request["enabled_features"] = ["telephony"]
|
|
37
|
+
|
|
38
|
+
response = self.client.post("/ai/assistants", data=request)
|
|
39
|
+
return response
|
|
40
|
+
|
|
41
|
+
def list_assistants(self) -> Dict[str, Any]:
|
|
42
|
+
"""List all AI Assistants.
|
|
43
|
+
|
|
44
|
+
Returns:
|
|
45
|
+
Dict[str, Any]: List of assistants
|
|
46
|
+
"""
|
|
47
|
+
response = self.client.get("/ai/assistants")
|
|
48
|
+
return response
|
|
49
|
+
|
|
50
|
+
def get_assistant(
|
|
51
|
+
self,
|
|
52
|
+
assistant_id: str,
|
|
53
|
+
fetch_dynamic_variables_from_webhook: Optional[bool] = None,
|
|
54
|
+
from_: Optional[str] = None,
|
|
55
|
+
to: Optional[str] = None,
|
|
56
|
+
call_control_id: Optional[str] = None,
|
|
57
|
+
) -> Dict[str, Any]:
|
|
58
|
+
"""Get an AI Assistant by ID.
|
|
59
|
+
|
|
60
|
+
Args:
|
|
61
|
+
assistant_id: Assistant ID
|
|
62
|
+
fetch_dynamic_variables_from_webhook: Whether to fetch dynamic variables from webhook
|
|
63
|
+
from_: From parameter for dynamic variables
|
|
64
|
+
to: To parameter for dynamic variables
|
|
65
|
+
call_control_id: Call control ID for dynamic variables
|
|
66
|
+
|
|
67
|
+
Returns:
|
|
68
|
+
Dict[str, Any]: Assistant data
|
|
69
|
+
"""
|
|
70
|
+
params: Dict[str, Any] = {}
|
|
71
|
+
if fetch_dynamic_variables_from_webhook is not None:
|
|
72
|
+
params["fetch_dynamic_variables_from_webhook"] = (
|
|
73
|
+
fetch_dynamic_variables_from_webhook
|
|
74
|
+
)
|
|
75
|
+
if from_ is not None:
|
|
76
|
+
params["from"] = from_
|
|
77
|
+
if to is not None:
|
|
78
|
+
params["to"] = to
|
|
79
|
+
if call_control_id is not None:
|
|
80
|
+
params["call_control_id"] = call_control_id
|
|
81
|
+
|
|
82
|
+
response = self.client.get(
|
|
83
|
+
f"/ai/assistants/{assistant_id}", params=params
|
|
84
|
+
)
|
|
85
|
+
return response
|
|
86
|
+
|
|
87
|
+
def update_assistant(
|
|
88
|
+
self,
|
|
89
|
+
assistant_id: str,
|
|
90
|
+
request: Dict[str, Any],
|
|
91
|
+
) -> Dict[str, Any]:
|
|
92
|
+
"""Update an AI Assistant.
|
|
93
|
+
|
|
94
|
+
Args:
|
|
95
|
+
assistant_id: Assistant ID
|
|
96
|
+
request: Assistant update request data
|
|
97
|
+
|
|
98
|
+
Returns:
|
|
99
|
+
Dict[str, Any]: Updated assistant data
|
|
100
|
+
"""
|
|
101
|
+
# Hard code voice settings and enabled features
|
|
102
|
+
if "voice_settings" in request:
|
|
103
|
+
del request["voice_settings"]
|
|
104
|
+
|
|
105
|
+
if "enabled_features" in request:
|
|
106
|
+
del request["enabled_features"]
|
|
107
|
+
|
|
108
|
+
response = self.client.post(
|
|
109
|
+
f"/ai/assistants/{assistant_id}",
|
|
110
|
+
data=request,
|
|
111
|
+
)
|
|
112
|
+
return response
|
|
113
|
+
|
|
114
|
+
def delete_assistant(self, assistant_id: str) -> Dict[str, Any]:
|
|
115
|
+
"""Delete an AI Assistant.
|
|
116
|
+
|
|
117
|
+
Args:
|
|
118
|
+
assistant_id: Assistant ID
|
|
119
|
+
|
|
120
|
+
Returns:
|
|
121
|
+
Dict[str, Any]: Deletion response containing id, object, and deleted status
|
|
122
|
+
"""
|
|
123
|
+
response = self.client.delete(f"/ai/assistants/{assistant_id}")
|
|
124
|
+
return response
|
|
125
|
+
|
|
126
|
+
def get_assistant_texml(self, assistant_id: str) -> str:
|
|
127
|
+
"""Get an assistant's TEXML by ID.
|
|
128
|
+
|
|
129
|
+
Args:
|
|
130
|
+
assistant_id: Assistant ID
|
|
131
|
+
|
|
132
|
+
Returns:
|
|
133
|
+
str: Assistant TEXML content
|
|
134
|
+
"""
|
|
135
|
+
response = self.client.get(f"/ai/assistants/{assistant_id}/texml")
|
|
136
|
+
return response
|
|
137
|
+
|
|
138
|
+
def start_assistant_call(
|
|
139
|
+
self, default_texml_app_id: str, to: str, from_: str
|
|
140
|
+
) -> Dict[str, Any]:
|
|
141
|
+
"""Start a call using the assistant's TeXML application.
|
|
142
|
+
|
|
143
|
+
Args:
|
|
144
|
+
default_texml_app_id: The assistant's default TeXML application ID
|
|
145
|
+
to: Destination number to call
|
|
146
|
+
from_: Source number to call from
|
|
147
|
+
|
|
148
|
+
Returns:
|
|
149
|
+
Dict[str, Any]: Response data
|
|
150
|
+
"""
|
|
151
|
+
data = {"To": to, "From": from_}
|
|
152
|
+
response = self.client.post(
|
|
153
|
+
f"/texml/calls/{default_texml_app_id}", data=data
|
|
154
|
+
)
|
|
155
|
+
return response
|