daita-agents 0.1.0__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.
Potentially problematic release.
This version of daita-agents might be problematic. Click here for more details.
- daita/__init__.py +208 -0
- daita/agents/__init__.py +33 -0
- daita/agents/base.py +722 -0
- daita/agents/substrate.py +895 -0
- daita/cli/__init__.py +145 -0
- daita/cli/__main__.py +7 -0
- daita/cli/ascii_art.py +44 -0
- daita/cli/core/__init__.py +0 -0
- daita/cli/core/create.py +254 -0
- daita/cli/core/deploy.py +473 -0
- daita/cli/core/deployments.py +309 -0
- daita/cli/core/import_detector.py +219 -0
- daita/cli/core/init.py +382 -0
- daita/cli/core/logs.py +239 -0
- daita/cli/core/managed_deploy.py +709 -0
- daita/cli/core/run.py +648 -0
- daita/cli/core/status.py +421 -0
- daita/cli/core/test.py +239 -0
- daita/cli/core/webhooks.py +172 -0
- daita/cli/main.py +588 -0
- daita/cli/utils.py +541 -0
- daita/config/__init__.py +62 -0
- daita/config/base.py +159 -0
- daita/config/settings.py +184 -0
- daita/core/__init__.py +262 -0
- daita/core/decision_tracing.py +701 -0
- daita/core/exceptions.py +480 -0
- daita/core/focus.py +251 -0
- daita/core/interfaces.py +76 -0
- daita/core/plugin_tracing.py +550 -0
- daita/core/relay.py +695 -0
- daita/core/reliability.py +381 -0
- daita/core/scaling.py +444 -0
- daita/core/tools.py +402 -0
- daita/core/tracing.py +770 -0
- daita/core/workflow.py +1084 -0
- daita/display/__init__.py +1 -0
- daita/display/console.py +160 -0
- daita/execution/__init__.py +58 -0
- daita/execution/client.py +856 -0
- daita/execution/exceptions.py +92 -0
- daita/execution/models.py +317 -0
- daita/llm/__init__.py +60 -0
- daita/llm/anthropic.py +166 -0
- daita/llm/base.py +373 -0
- daita/llm/factory.py +101 -0
- daita/llm/gemini.py +152 -0
- daita/llm/grok.py +114 -0
- daita/llm/mock.py +135 -0
- daita/llm/openai.py +109 -0
- daita/plugins/__init__.py +141 -0
- daita/plugins/base.py +37 -0
- daita/plugins/base_db.py +167 -0
- daita/plugins/elasticsearch.py +844 -0
- daita/plugins/mcp.py +481 -0
- daita/plugins/mongodb.py +510 -0
- daita/plugins/mysql.py +351 -0
- daita/plugins/postgresql.py +331 -0
- daita/plugins/redis_messaging.py +500 -0
- daita/plugins/rest.py +529 -0
- daita/plugins/s3.py +761 -0
- daita/plugins/slack.py +729 -0
- daita/utils/__init__.py +18 -0
- daita_agents-0.1.0.dist-info/METADATA +350 -0
- daita_agents-0.1.0.dist-info/RECORD +69 -0
- daita_agents-0.1.0.dist-info/WHEEL +5 -0
- daita_agents-0.1.0.dist-info/entry_points.txt +2 -0
- daita_agents-0.1.0.dist-info/licenses/LICENSE +56 -0
- daita_agents-0.1.0.dist-info/top_level.txt +1 -0
daita/plugins/rest.py
ADDED
|
@@ -0,0 +1,529 @@
|
|
|
1
|
+
"""
|
|
2
|
+
REST API plugin for Daita Agents.
|
|
3
|
+
|
|
4
|
+
Simple REST API client - no over-engineering.
|
|
5
|
+
"""
|
|
6
|
+
import logging
|
|
7
|
+
import asyncio
|
|
8
|
+
from typing import Any, Dict, List, Optional, Union, TYPE_CHECKING
|
|
9
|
+
|
|
10
|
+
if TYPE_CHECKING:
|
|
11
|
+
from ..core.tools import AgentTool
|
|
12
|
+
|
|
13
|
+
logger = logging.getLogger(__name__)
|
|
14
|
+
|
|
15
|
+
class RESTPlugin:
|
|
16
|
+
"""
|
|
17
|
+
Simple REST API plugin for agents.
|
|
18
|
+
|
|
19
|
+
Just makes HTTP requests and handles responses. Nothing fancy.
|
|
20
|
+
"""
|
|
21
|
+
|
|
22
|
+
def __init__(
|
|
23
|
+
self,
|
|
24
|
+
base_url: str,
|
|
25
|
+
api_key: Optional[str] = None,
|
|
26
|
+
auth_header: str = "Authorization",
|
|
27
|
+
auth_prefix: str = "Bearer",
|
|
28
|
+
timeout: int = 30,
|
|
29
|
+
**kwargs
|
|
30
|
+
):
|
|
31
|
+
"""
|
|
32
|
+
Initialize REST API client.
|
|
33
|
+
|
|
34
|
+
Args:
|
|
35
|
+
base_url: Base URL for all requests
|
|
36
|
+
api_key: Optional API key for authentication
|
|
37
|
+
auth_header: Header name for authentication (default: "Authorization")
|
|
38
|
+
auth_prefix: Prefix for auth value (default: "Bearer")
|
|
39
|
+
timeout: Request timeout in seconds
|
|
40
|
+
**kwargs: Additional headers or configuration
|
|
41
|
+
"""
|
|
42
|
+
# Validate base_url
|
|
43
|
+
if not base_url or not base_url.strip():
|
|
44
|
+
raise ValueError("base_url cannot be empty or whitespace-only")
|
|
45
|
+
|
|
46
|
+
self.base_url = base_url.rstrip('/')
|
|
47
|
+
self.api_key = api_key
|
|
48
|
+
self.auth_header = auth_header
|
|
49
|
+
self.auth_prefix = auth_prefix
|
|
50
|
+
self.timeout = timeout
|
|
51
|
+
|
|
52
|
+
# Default headers
|
|
53
|
+
self.default_headers = {
|
|
54
|
+
'Content-Type': 'application/json',
|
|
55
|
+
'Accept': 'application/json',
|
|
56
|
+
**kwargs.get('headers', {})
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
# Add auth header if API key provided - fix spacing issue
|
|
60
|
+
if self.api_key:
|
|
61
|
+
if self.auth_prefix:
|
|
62
|
+
self.default_headers[self.auth_header] = f"{self.auth_prefix} {self.api_key}"
|
|
63
|
+
else:
|
|
64
|
+
self.default_headers[self.auth_header] = self.api_key
|
|
65
|
+
|
|
66
|
+
self._session = None
|
|
67
|
+
logger.debug(f"REST plugin configured for {self.base_url}")
|
|
68
|
+
|
|
69
|
+
async def connect(self):
|
|
70
|
+
"""Initialize HTTP session."""
|
|
71
|
+
if self._session is not None:
|
|
72
|
+
return # Already connected
|
|
73
|
+
|
|
74
|
+
try:
|
|
75
|
+
import aiohttp
|
|
76
|
+
|
|
77
|
+
timeout = aiohttp.ClientTimeout(total=self.timeout)
|
|
78
|
+
self._session = aiohttp.ClientSession(
|
|
79
|
+
headers=self.default_headers,
|
|
80
|
+
timeout=timeout
|
|
81
|
+
)
|
|
82
|
+
|
|
83
|
+
logger.info(f"Connected to REST API: {self.base_url}")
|
|
84
|
+
except ImportError:
|
|
85
|
+
raise RuntimeError("aiohttp not installed. Run: pip install aiohttp")
|
|
86
|
+
|
|
87
|
+
async def disconnect(self):
|
|
88
|
+
"""Close HTTP session."""
|
|
89
|
+
if self._session:
|
|
90
|
+
await self._session.close()
|
|
91
|
+
self._session = None
|
|
92
|
+
logger.info("Disconnected from REST API")
|
|
93
|
+
|
|
94
|
+
async def get(
|
|
95
|
+
self,
|
|
96
|
+
endpoint: str,
|
|
97
|
+
params: Optional[Dict[str, Any]] = None,
|
|
98
|
+
headers: Optional[Dict[str, str]] = None
|
|
99
|
+
) -> Dict[str, Any]:
|
|
100
|
+
"""
|
|
101
|
+
Make a GET request.
|
|
102
|
+
|
|
103
|
+
Args:
|
|
104
|
+
endpoint: API endpoint (without base URL)
|
|
105
|
+
params: Query parameters
|
|
106
|
+
headers: Additional headers for this request
|
|
107
|
+
|
|
108
|
+
Returns:
|
|
109
|
+
Response data as dictionary
|
|
110
|
+
|
|
111
|
+
Example:
|
|
112
|
+
data = await api.get("/users", params={"page": 1})
|
|
113
|
+
"""
|
|
114
|
+
return await self._request("GET", endpoint, params=params, headers=headers)
|
|
115
|
+
|
|
116
|
+
async def post(
|
|
117
|
+
self,
|
|
118
|
+
endpoint: str,
|
|
119
|
+
data: Optional[Dict[str, Any]] = None,
|
|
120
|
+
json_data: Optional[Dict[str, Any]] = None,
|
|
121
|
+
headers: Optional[Dict[str, str]] = None
|
|
122
|
+
) -> Dict[str, Any]:
|
|
123
|
+
"""
|
|
124
|
+
Make a POST request.
|
|
125
|
+
|
|
126
|
+
Args:
|
|
127
|
+
endpoint: API endpoint
|
|
128
|
+
data: Form data to send
|
|
129
|
+
json_data: JSON data to send (takes precedence over data)
|
|
130
|
+
headers: Additional headers
|
|
131
|
+
|
|
132
|
+
Returns:
|
|
133
|
+
Response data as dictionary
|
|
134
|
+
|
|
135
|
+
Example:
|
|
136
|
+
result = await api.post("/users", json_data={"name": "John", "email": "john@example.com"})
|
|
137
|
+
"""
|
|
138
|
+
return await self._request("POST", endpoint, data=data, json_data=json_data, headers=headers)
|
|
139
|
+
|
|
140
|
+
async def put(
|
|
141
|
+
self,
|
|
142
|
+
endpoint: str,
|
|
143
|
+
data: Optional[Dict[str, Any]] = None,
|
|
144
|
+
json_data: Optional[Dict[str, Any]] = None,
|
|
145
|
+
headers: Optional[Dict[str, str]] = None
|
|
146
|
+
) -> Dict[str, Any]:
|
|
147
|
+
"""
|
|
148
|
+
Make a PUT request.
|
|
149
|
+
|
|
150
|
+
Args:
|
|
151
|
+
endpoint: API endpoint
|
|
152
|
+
data: Form data to send
|
|
153
|
+
json_data: JSON data to send
|
|
154
|
+
headers: Additional headers
|
|
155
|
+
|
|
156
|
+
Returns:
|
|
157
|
+
Response data as dictionary
|
|
158
|
+
"""
|
|
159
|
+
return await self._request("PUT", endpoint, data=data, json_data=json_data, headers=headers)
|
|
160
|
+
|
|
161
|
+
async def patch(
|
|
162
|
+
self,
|
|
163
|
+
endpoint: str,
|
|
164
|
+
data: Optional[Dict[str, Any]] = None,
|
|
165
|
+
json_data: Optional[Dict[str, Any]] = None,
|
|
166
|
+
headers: Optional[Dict[str, str]] = None
|
|
167
|
+
) -> Dict[str, Any]:
|
|
168
|
+
"""
|
|
169
|
+
Make a PATCH request.
|
|
170
|
+
|
|
171
|
+
Args:
|
|
172
|
+
endpoint: API endpoint
|
|
173
|
+
data: Form data to send
|
|
174
|
+
json_data: JSON data to send
|
|
175
|
+
headers: Additional headers
|
|
176
|
+
|
|
177
|
+
Returns:
|
|
178
|
+
Response data as dictionary
|
|
179
|
+
"""
|
|
180
|
+
return await self._request("PATCH", endpoint, data=data, json_data=json_data, headers=headers)
|
|
181
|
+
|
|
182
|
+
async def delete(
|
|
183
|
+
self,
|
|
184
|
+
endpoint: str,
|
|
185
|
+
params: Optional[Dict[str, Any]] = None,
|
|
186
|
+
headers: Optional[Dict[str, str]] = None
|
|
187
|
+
) -> Dict[str, Any]:
|
|
188
|
+
"""
|
|
189
|
+
Make a DELETE request.
|
|
190
|
+
|
|
191
|
+
Args:
|
|
192
|
+
endpoint: API endpoint
|
|
193
|
+
params: Query parameters
|
|
194
|
+
headers: Additional headers
|
|
195
|
+
|
|
196
|
+
Returns:
|
|
197
|
+
Response data as dictionary
|
|
198
|
+
"""
|
|
199
|
+
return await self._request("DELETE", endpoint, params=params, headers=headers)
|
|
200
|
+
|
|
201
|
+
async def _request(
|
|
202
|
+
self,
|
|
203
|
+
method: str,
|
|
204
|
+
endpoint: str,
|
|
205
|
+
params: Optional[Dict[str, Any]] = None,
|
|
206
|
+
data: Optional[Dict[str, Any]] = None,
|
|
207
|
+
json_data: Optional[Dict[str, Any]] = None,
|
|
208
|
+
headers: Optional[Dict[str, str]] = None
|
|
209
|
+
) -> Dict[str, Any]:
|
|
210
|
+
"""
|
|
211
|
+
Make HTTP request with error handling.
|
|
212
|
+
|
|
213
|
+
Args:
|
|
214
|
+
method: HTTP method
|
|
215
|
+
endpoint: API endpoint
|
|
216
|
+
params: Query parameters
|
|
217
|
+
data: Form data
|
|
218
|
+
json_data: JSON data
|
|
219
|
+
headers: Additional headers
|
|
220
|
+
|
|
221
|
+
Returns:
|
|
222
|
+
Response data
|
|
223
|
+
"""
|
|
224
|
+
await self.connect()
|
|
225
|
+
|
|
226
|
+
# Build full URL
|
|
227
|
+
url = f"{self.base_url}/{endpoint.lstrip('/')}"
|
|
228
|
+
|
|
229
|
+
# Prepare request kwargs
|
|
230
|
+
request_kwargs = {
|
|
231
|
+
'params': params,
|
|
232
|
+
'headers': headers,
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
# Handle request body
|
|
236
|
+
if json_data is not None:
|
|
237
|
+
request_kwargs['json'] = json_data
|
|
238
|
+
elif data is not None:
|
|
239
|
+
request_kwargs['data'] = data
|
|
240
|
+
|
|
241
|
+
try:
|
|
242
|
+
async with self._session.request(method, url, **request_kwargs) as response:
|
|
243
|
+
|
|
244
|
+
# Log request
|
|
245
|
+
logger.debug(f"{method} {url} -> {response.status}")
|
|
246
|
+
|
|
247
|
+
# Handle different response types
|
|
248
|
+
content_type = response.headers.get('content-type', '')
|
|
249
|
+
|
|
250
|
+
# Check for errors
|
|
251
|
+
if response.status >= 400:
|
|
252
|
+
error_text = await response.text()
|
|
253
|
+
raise RuntimeError(f"HTTP {response.status}: {error_text}")
|
|
254
|
+
|
|
255
|
+
# Parse response based on content type
|
|
256
|
+
if 'application/json' in content_type:
|
|
257
|
+
return await response.json()
|
|
258
|
+
elif 'text/' in content_type:
|
|
259
|
+
text_content = await response.text()
|
|
260
|
+
return {'content': text_content, 'content_type': content_type}
|
|
261
|
+
else:
|
|
262
|
+
# Binary content
|
|
263
|
+
binary_content = await response.read()
|
|
264
|
+
return {
|
|
265
|
+
'content': binary_content,
|
|
266
|
+
'content_type': content_type,
|
|
267
|
+
'size': len(binary_content)
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
except Exception as e:
|
|
271
|
+
logger.error(f"REST request failed: {method} {url} - {str(e)}")
|
|
272
|
+
raise RuntimeError(f"REST request failed: {str(e)}")
|
|
273
|
+
|
|
274
|
+
async def upload_file(
|
|
275
|
+
self,
|
|
276
|
+
endpoint: str,
|
|
277
|
+
file_path: str,
|
|
278
|
+
field_name: str = "file",
|
|
279
|
+
additional_data: Optional[Dict[str, Any]] = None
|
|
280
|
+
) -> Dict[str, Any]:
|
|
281
|
+
"""
|
|
282
|
+
Upload a file.
|
|
283
|
+
|
|
284
|
+
Args:
|
|
285
|
+
endpoint: API endpoint
|
|
286
|
+
file_path: Path to file to upload
|
|
287
|
+
field_name: Form field name for the file
|
|
288
|
+
additional_data: Additional form data
|
|
289
|
+
|
|
290
|
+
Returns:
|
|
291
|
+
Response data
|
|
292
|
+
"""
|
|
293
|
+
import os
|
|
294
|
+
import aiohttp
|
|
295
|
+
|
|
296
|
+
await self.connect()
|
|
297
|
+
|
|
298
|
+
if not os.path.exists(file_path):
|
|
299
|
+
raise FileNotFoundError(f"File not found: {file_path}")
|
|
300
|
+
|
|
301
|
+
url = f"{self.base_url}/{endpoint.lstrip('/')}"
|
|
302
|
+
|
|
303
|
+
# Create form data
|
|
304
|
+
data = aiohttp.FormData()
|
|
305
|
+
|
|
306
|
+
# Add file
|
|
307
|
+
with open(file_path, 'rb') as f:
|
|
308
|
+
data.add_field(
|
|
309
|
+
field_name,
|
|
310
|
+
f,
|
|
311
|
+
filename=os.path.basename(file_path)
|
|
312
|
+
)
|
|
313
|
+
|
|
314
|
+
# Add additional form fields
|
|
315
|
+
if additional_data:
|
|
316
|
+
for key, value in additional_data.items():
|
|
317
|
+
data.add_field(key, str(value))
|
|
318
|
+
|
|
319
|
+
# Make request
|
|
320
|
+
async with self._session.post(url, data=data) as response:
|
|
321
|
+
if response.status >= 400:
|
|
322
|
+
error_text = await response.text()
|
|
323
|
+
raise RuntimeError(f"File upload failed ({response.status}): {error_text}")
|
|
324
|
+
|
|
325
|
+
content_type = response.headers.get('content-type', '')
|
|
326
|
+
if 'application/json' in content_type:
|
|
327
|
+
return await response.json()
|
|
328
|
+
else:
|
|
329
|
+
return {'content': await response.text()}
|
|
330
|
+
|
|
331
|
+
async def download_file(
|
|
332
|
+
self,
|
|
333
|
+
endpoint: str,
|
|
334
|
+
save_path: str,
|
|
335
|
+
params: Optional[Dict[str, Any]] = None
|
|
336
|
+
) -> str:
|
|
337
|
+
"""
|
|
338
|
+
Download a file.
|
|
339
|
+
|
|
340
|
+
Args:
|
|
341
|
+
endpoint: API endpoint
|
|
342
|
+
save_path: Where to save the file
|
|
343
|
+
params: Query parameters
|
|
344
|
+
|
|
345
|
+
Returns:
|
|
346
|
+
Path to downloaded file
|
|
347
|
+
"""
|
|
348
|
+
import os
|
|
349
|
+
|
|
350
|
+
await self.connect()
|
|
351
|
+
|
|
352
|
+
url = f"{self.base_url}/{endpoint.lstrip('/')}"
|
|
353
|
+
|
|
354
|
+
async with self._session.get(url, params=params) as response:
|
|
355
|
+
if response.status >= 400:
|
|
356
|
+
error_text = await response.text()
|
|
357
|
+
raise RuntimeError(f"File download failed ({response.status}): {error_text}")
|
|
358
|
+
|
|
359
|
+
# Ensure directory exists
|
|
360
|
+
os.makedirs(os.path.dirname(save_path), exist_ok=True)
|
|
361
|
+
|
|
362
|
+
# Write file
|
|
363
|
+
with open(save_path, 'wb') as f:
|
|
364
|
+
async for chunk in response.content.iter_chunked(8192):
|
|
365
|
+
f.write(chunk)
|
|
366
|
+
|
|
367
|
+
logger.info(f"Downloaded file to {save_path}")
|
|
368
|
+
return save_path
|
|
369
|
+
|
|
370
|
+
def get_tools(self) -> List['AgentTool']:
|
|
371
|
+
"""
|
|
372
|
+
Expose REST API operations as agent tools.
|
|
373
|
+
|
|
374
|
+
Returns:
|
|
375
|
+
List of AgentTool instances for REST API operations
|
|
376
|
+
"""
|
|
377
|
+
from ..core.tools import AgentTool
|
|
378
|
+
|
|
379
|
+
return [
|
|
380
|
+
AgentTool(
|
|
381
|
+
name="http_get",
|
|
382
|
+
description="Make an HTTP GET request to the REST API endpoint. Use for retrieving data.",
|
|
383
|
+
parameters={
|
|
384
|
+
"endpoint": {
|
|
385
|
+
"type": "string",
|
|
386
|
+
"description": "API endpoint path (without base URL, e.g., /users or /data/123)",
|
|
387
|
+
"required": True
|
|
388
|
+
},
|
|
389
|
+
"params": {
|
|
390
|
+
"type": "object",
|
|
391
|
+
"description": "Optional query parameters as key-value pairs",
|
|
392
|
+
"required": False
|
|
393
|
+
}
|
|
394
|
+
},
|
|
395
|
+
handler=self._tool_get,
|
|
396
|
+
category="api",
|
|
397
|
+
source="plugin",
|
|
398
|
+
plugin_name="REST",
|
|
399
|
+
timeout_seconds=60
|
|
400
|
+
),
|
|
401
|
+
AgentTool(
|
|
402
|
+
name="http_post",
|
|
403
|
+
description="Make an HTTP POST request to the REST API endpoint. Use for creating new resources.",
|
|
404
|
+
parameters={
|
|
405
|
+
"endpoint": {
|
|
406
|
+
"type": "string",
|
|
407
|
+
"description": "API endpoint path (without base URL)",
|
|
408
|
+
"required": True
|
|
409
|
+
},
|
|
410
|
+
"data": {
|
|
411
|
+
"type": "object",
|
|
412
|
+
"description": "JSON data to send in the request body",
|
|
413
|
+
"required": True
|
|
414
|
+
}
|
|
415
|
+
},
|
|
416
|
+
handler=self._tool_post,
|
|
417
|
+
category="api",
|
|
418
|
+
source="plugin",
|
|
419
|
+
plugin_name="REST",
|
|
420
|
+
timeout_seconds=60
|
|
421
|
+
),
|
|
422
|
+
AgentTool(
|
|
423
|
+
name="http_put",
|
|
424
|
+
description="Make an HTTP PUT request to the REST API endpoint. Use for updating existing resources.",
|
|
425
|
+
parameters={
|
|
426
|
+
"endpoint": {
|
|
427
|
+
"type": "string",
|
|
428
|
+
"description": "API endpoint path (without base URL)",
|
|
429
|
+
"required": True
|
|
430
|
+
},
|
|
431
|
+
"data": {
|
|
432
|
+
"type": "object",
|
|
433
|
+
"description": "JSON data to send in the request body",
|
|
434
|
+
"required": True
|
|
435
|
+
}
|
|
436
|
+
},
|
|
437
|
+
handler=self._tool_put,
|
|
438
|
+
category="api",
|
|
439
|
+
source="plugin",
|
|
440
|
+
plugin_name="REST",
|
|
441
|
+
timeout_seconds=60
|
|
442
|
+
),
|
|
443
|
+
AgentTool(
|
|
444
|
+
name="http_delete",
|
|
445
|
+
description="Make an HTTP DELETE request to the REST API endpoint. Use for deleting resources.",
|
|
446
|
+
parameters={
|
|
447
|
+
"endpoint": {
|
|
448
|
+
"type": "string",
|
|
449
|
+
"description": "API endpoint path (without base URL)",
|
|
450
|
+
"required": True
|
|
451
|
+
},
|
|
452
|
+
"params": {
|
|
453
|
+
"type": "object",
|
|
454
|
+
"description": "Optional query parameters",
|
|
455
|
+
"required": False
|
|
456
|
+
}
|
|
457
|
+
},
|
|
458
|
+
handler=self._tool_delete,
|
|
459
|
+
category="api",
|
|
460
|
+
source="plugin",
|
|
461
|
+
plugin_name="REST",
|
|
462
|
+
timeout_seconds=60
|
|
463
|
+
)
|
|
464
|
+
]
|
|
465
|
+
|
|
466
|
+
async def _tool_get(self, args: Dict[str, Any]) -> Dict[str, Any]:
|
|
467
|
+
"""Tool handler for http_get"""
|
|
468
|
+
endpoint = args.get("endpoint")
|
|
469
|
+
params = args.get("params")
|
|
470
|
+
|
|
471
|
+
result = await self.get(endpoint, params=params)
|
|
472
|
+
|
|
473
|
+
return {
|
|
474
|
+
"success": True,
|
|
475
|
+
"data": result,
|
|
476
|
+
"endpoint": endpoint
|
|
477
|
+
}
|
|
478
|
+
|
|
479
|
+
async def _tool_post(self, args: Dict[str, Any]) -> Dict[str, Any]:
|
|
480
|
+
"""Tool handler for http_post"""
|
|
481
|
+
endpoint = args.get("endpoint")
|
|
482
|
+
data = args.get("data")
|
|
483
|
+
|
|
484
|
+
result = await self.post(endpoint, json_data=data)
|
|
485
|
+
|
|
486
|
+
return {
|
|
487
|
+
"success": True,
|
|
488
|
+
"data": result,
|
|
489
|
+
"endpoint": endpoint
|
|
490
|
+
}
|
|
491
|
+
|
|
492
|
+
async def _tool_put(self, args: Dict[str, Any]) -> Dict[str, Any]:
|
|
493
|
+
"""Tool handler for http_put"""
|
|
494
|
+
endpoint = args.get("endpoint")
|
|
495
|
+
data = args.get("data")
|
|
496
|
+
|
|
497
|
+
result = await self.put(endpoint, json_data=data)
|
|
498
|
+
|
|
499
|
+
return {
|
|
500
|
+
"success": True,
|
|
501
|
+
"data": result,
|
|
502
|
+
"endpoint": endpoint
|
|
503
|
+
}
|
|
504
|
+
|
|
505
|
+
async def _tool_delete(self, args: Dict[str, Any]) -> Dict[str, Any]:
|
|
506
|
+
"""Tool handler for http_delete"""
|
|
507
|
+
endpoint = args.get("endpoint")
|
|
508
|
+
params = args.get("params")
|
|
509
|
+
|
|
510
|
+
result = await self.delete(endpoint, params=params)
|
|
511
|
+
|
|
512
|
+
return {
|
|
513
|
+
"success": True,
|
|
514
|
+
"data": result,
|
|
515
|
+
"endpoint": endpoint
|
|
516
|
+
}
|
|
517
|
+
|
|
518
|
+
# Context manager support
|
|
519
|
+
async def __aenter__(self):
|
|
520
|
+
await self.connect()
|
|
521
|
+
return self
|
|
522
|
+
|
|
523
|
+
async def __aexit__(self, exc_type, exc_val, exc_tb):
|
|
524
|
+
await self.disconnect()
|
|
525
|
+
|
|
526
|
+
|
|
527
|
+
def rest(**kwargs) -> RESTPlugin:
|
|
528
|
+
"""Create REST plugin with simplified interface."""
|
|
529
|
+
return RESTPlugin(**kwargs)
|