mail-swarms 1.3.2__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.
- mail/__init__.py +35 -0
- mail/api.py +1964 -0
- mail/cli.py +432 -0
- mail/client.py +1657 -0
- mail/config/__init__.py +8 -0
- mail/config/client.py +87 -0
- mail/config/server.py +165 -0
- mail/core/__init__.py +72 -0
- mail/core/actions.py +69 -0
- mail/core/agents.py +73 -0
- mail/core/message.py +366 -0
- mail/core/runtime.py +3537 -0
- mail/core/tasks.py +311 -0
- mail/core/tools.py +1206 -0
- mail/db/__init__.py +0 -0
- mail/db/init.py +182 -0
- mail/db/types.py +65 -0
- mail/db/utils.py +523 -0
- mail/examples/__init__.py +27 -0
- mail/examples/analyst_dummy/__init__.py +15 -0
- mail/examples/analyst_dummy/agent.py +136 -0
- mail/examples/analyst_dummy/prompts.py +44 -0
- mail/examples/consultant_dummy/__init__.py +15 -0
- mail/examples/consultant_dummy/agent.py +136 -0
- mail/examples/consultant_dummy/prompts.py +42 -0
- mail/examples/data_analysis/__init__.py +40 -0
- mail/examples/data_analysis/analyst/__init__.py +9 -0
- mail/examples/data_analysis/analyst/agent.py +67 -0
- mail/examples/data_analysis/analyst/prompts.py +53 -0
- mail/examples/data_analysis/processor/__init__.py +13 -0
- mail/examples/data_analysis/processor/actions.py +293 -0
- mail/examples/data_analysis/processor/agent.py +67 -0
- mail/examples/data_analysis/processor/prompts.py +48 -0
- mail/examples/data_analysis/reporter/__init__.py +10 -0
- mail/examples/data_analysis/reporter/actions.py +187 -0
- mail/examples/data_analysis/reporter/agent.py +67 -0
- mail/examples/data_analysis/reporter/prompts.py +49 -0
- mail/examples/data_analysis/statistics/__init__.py +18 -0
- mail/examples/data_analysis/statistics/actions.py +343 -0
- mail/examples/data_analysis/statistics/agent.py +67 -0
- mail/examples/data_analysis/statistics/prompts.py +60 -0
- mail/examples/mafia/__init__.py +0 -0
- mail/examples/mafia/game.py +1537 -0
- mail/examples/mafia/narrator_tools.py +396 -0
- mail/examples/mafia/personas.py +240 -0
- mail/examples/mafia/prompts.py +489 -0
- mail/examples/mafia/roles.py +147 -0
- mail/examples/mafia/spec.md +350 -0
- mail/examples/math_dummy/__init__.py +23 -0
- mail/examples/math_dummy/actions.py +252 -0
- mail/examples/math_dummy/agent.py +136 -0
- mail/examples/math_dummy/prompts.py +46 -0
- mail/examples/math_dummy/types.py +5 -0
- mail/examples/research/__init__.py +39 -0
- mail/examples/research/researcher/__init__.py +9 -0
- mail/examples/research/researcher/agent.py +67 -0
- mail/examples/research/researcher/prompts.py +54 -0
- mail/examples/research/searcher/__init__.py +10 -0
- mail/examples/research/searcher/actions.py +324 -0
- mail/examples/research/searcher/agent.py +67 -0
- mail/examples/research/searcher/prompts.py +53 -0
- mail/examples/research/summarizer/__init__.py +18 -0
- mail/examples/research/summarizer/actions.py +255 -0
- mail/examples/research/summarizer/agent.py +67 -0
- mail/examples/research/summarizer/prompts.py +55 -0
- mail/examples/research/verifier/__init__.py +10 -0
- mail/examples/research/verifier/actions.py +337 -0
- mail/examples/research/verifier/agent.py +67 -0
- mail/examples/research/verifier/prompts.py +52 -0
- mail/examples/supervisor/__init__.py +11 -0
- mail/examples/supervisor/agent.py +4 -0
- mail/examples/supervisor/prompts.py +93 -0
- mail/examples/support/__init__.py +33 -0
- mail/examples/support/classifier/__init__.py +10 -0
- mail/examples/support/classifier/actions.py +307 -0
- mail/examples/support/classifier/agent.py +68 -0
- mail/examples/support/classifier/prompts.py +56 -0
- mail/examples/support/coordinator/__init__.py +9 -0
- mail/examples/support/coordinator/agent.py +67 -0
- mail/examples/support/coordinator/prompts.py +48 -0
- mail/examples/support/faq/__init__.py +10 -0
- mail/examples/support/faq/actions.py +182 -0
- mail/examples/support/faq/agent.py +67 -0
- mail/examples/support/faq/prompts.py +42 -0
- mail/examples/support/sentiment/__init__.py +15 -0
- mail/examples/support/sentiment/actions.py +341 -0
- mail/examples/support/sentiment/agent.py +67 -0
- mail/examples/support/sentiment/prompts.py +54 -0
- mail/examples/weather_dummy/__init__.py +23 -0
- mail/examples/weather_dummy/actions.py +75 -0
- mail/examples/weather_dummy/agent.py +136 -0
- mail/examples/weather_dummy/prompts.py +35 -0
- mail/examples/weather_dummy/types.py +5 -0
- mail/factories/__init__.py +27 -0
- mail/factories/action.py +223 -0
- mail/factories/base.py +1531 -0
- mail/factories/supervisor.py +241 -0
- mail/net/__init__.py +7 -0
- mail/net/registry.py +712 -0
- mail/net/router.py +728 -0
- mail/net/server_utils.py +114 -0
- mail/net/types.py +247 -0
- mail/server.py +1605 -0
- mail/stdlib/__init__.py +0 -0
- mail/stdlib/anthropic/__init__.py +0 -0
- mail/stdlib/fs/__init__.py +15 -0
- mail/stdlib/fs/actions.py +209 -0
- mail/stdlib/http/__init__.py +19 -0
- mail/stdlib/http/actions.py +333 -0
- mail/stdlib/interswarm/__init__.py +11 -0
- mail/stdlib/interswarm/actions.py +208 -0
- mail/stdlib/mcp/__init__.py +19 -0
- mail/stdlib/mcp/actions.py +294 -0
- mail/stdlib/openai/__init__.py +13 -0
- mail/stdlib/openai/agents.py +451 -0
- mail/summarizer.py +234 -0
- mail/swarms_json/__init__.py +27 -0
- mail/swarms_json/types.py +87 -0
- mail/swarms_json/utils.py +255 -0
- mail/url_scheme.py +51 -0
- mail/utils/__init__.py +53 -0
- mail/utils/auth.py +194 -0
- mail/utils/context.py +17 -0
- mail/utils/logger.py +73 -0
- mail/utils/openai.py +212 -0
- mail/utils/parsing.py +89 -0
- mail/utils/serialize.py +292 -0
- mail/utils/store.py +49 -0
- mail/utils/string_builder.py +119 -0
- mail/utils/version.py +20 -0
- mail_swarms-1.3.2.dist-info/METADATA +237 -0
- mail_swarms-1.3.2.dist-info/RECORD +137 -0
- mail_swarms-1.3.2.dist-info/WHEEL +4 -0
- mail_swarms-1.3.2.dist-info/entry_points.txt +2 -0
- mail_swarms-1.3.2.dist-info/licenses/LICENSE +202 -0
- mail_swarms-1.3.2.dist-info/licenses/NOTICE +10 -0
- mail_swarms-1.3.2.dist-info/licenses/THIRD_PARTY_NOTICES.md +12334 -0
mail/stdlib/__init__.py
ADDED
|
File without changes
|
|
File without changes
|
|
@@ -0,0 +1,209 @@
|
|
|
1
|
+
# SPDX-License-Identifier: Apache-2.0
|
|
2
|
+
# Copyright (c) 2025 Addison Kline
|
|
3
|
+
|
|
4
|
+
from pathlib import Path
|
|
5
|
+
from typing import Any
|
|
6
|
+
|
|
7
|
+
from mail.api import action
|
|
8
|
+
|
|
9
|
+
FILE_READ_PARAMETERS = {
|
|
10
|
+
"type": "object",
|
|
11
|
+
"properties": {
|
|
12
|
+
"path": {
|
|
13
|
+
"type": "string",
|
|
14
|
+
"description": "The path to the file to read",
|
|
15
|
+
},
|
|
16
|
+
},
|
|
17
|
+
"required": ["path"],
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
@action(
|
|
22
|
+
name="read_file",
|
|
23
|
+
description="Read a file from the filesystem",
|
|
24
|
+
parameters=FILE_READ_PARAMETERS,
|
|
25
|
+
)
|
|
26
|
+
async def read_file(args: dict[str, Any]) -> str:
|
|
27
|
+
"""
|
|
28
|
+
Read a file from the filesystem.
|
|
29
|
+
"""
|
|
30
|
+
path = args.get("path")
|
|
31
|
+
|
|
32
|
+
if not isinstance(path, str):
|
|
33
|
+
return "Error: `path` must be a string"
|
|
34
|
+
|
|
35
|
+
target = Path(path)
|
|
36
|
+
if not target.exists():
|
|
37
|
+
return f"Error: file not found at {path}"
|
|
38
|
+
if not target.is_file():
|
|
39
|
+
return f"Error: {path} is not a file"
|
|
40
|
+
|
|
41
|
+
try:
|
|
42
|
+
return target.read_text()
|
|
43
|
+
except Exception as e:
|
|
44
|
+
return f"Error: {e}"
|
|
45
|
+
|
|
46
|
+
|
|
47
|
+
FILE_WRITE_PARAMETERS = {
|
|
48
|
+
"type": "object",
|
|
49
|
+
"properties": {
|
|
50
|
+
"path": {
|
|
51
|
+
"type": "string",
|
|
52
|
+
"description": "The path to the file to write to",
|
|
53
|
+
},
|
|
54
|
+
"content": {
|
|
55
|
+
"type": "string",
|
|
56
|
+
"description": "The content to write to the file",
|
|
57
|
+
},
|
|
58
|
+
},
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
|
|
62
|
+
@action(
|
|
63
|
+
name="write_file",
|
|
64
|
+
description="Write to a file on the filesystem",
|
|
65
|
+
parameters=FILE_WRITE_PARAMETERS,
|
|
66
|
+
)
|
|
67
|
+
async def write_file(args: dict[str, Any]) -> str:
|
|
68
|
+
"""
|
|
69
|
+
Write to a file on the filesystem.
|
|
70
|
+
"""
|
|
71
|
+
path = args.get("path")
|
|
72
|
+
content = args.get("content")
|
|
73
|
+
|
|
74
|
+
if not isinstance(path, str):
|
|
75
|
+
return "Error: `path` must be a string"
|
|
76
|
+
if not isinstance(content, str):
|
|
77
|
+
return "Error: `content` must be a string"
|
|
78
|
+
|
|
79
|
+
target = Path(path)
|
|
80
|
+
if not target.exists():
|
|
81
|
+
try:
|
|
82
|
+
target.parent.mkdir(parents=True, exist_ok=True)
|
|
83
|
+
target.write_text(content)
|
|
84
|
+
return f"successfully wrote to {path}"
|
|
85
|
+
except Exception as e:
|
|
86
|
+
return f"Error: {e}"
|
|
87
|
+
|
|
88
|
+
if not target.is_file():
|
|
89
|
+
return f"Error: {path} is not a file"
|
|
90
|
+
|
|
91
|
+
try:
|
|
92
|
+
target.write_text(content)
|
|
93
|
+
return f"successfully wrote to {path}"
|
|
94
|
+
except Exception as e:
|
|
95
|
+
return f"Error: {e}"
|
|
96
|
+
|
|
97
|
+
|
|
98
|
+
FILE_DELETE_PARAMETERS = {
|
|
99
|
+
"type": "object",
|
|
100
|
+
"properties": {
|
|
101
|
+
"path": {
|
|
102
|
+
"type": "string",
|
|
103
|
+
"description": "The path to the file to delete",
|
|
104
|
+
},
|
|
105
|
+
},
|
|
106
|
+
"required": ["path"],
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
|
|
110
|
+
@action(
|
|
111
|
+
name="delete_file",
|
|
112
|
+
description="Delete a file from the filesystem",
|
|
113
|
+
parameters=FILE_DELETE_PARAMETERS,
|
|
114
|
+
)
|
|
115
|
+
async def delete_file(args: dict[str, Any]) -> str:
|
|
116
|
+
"""
|
|
117
|
+
Delete a file from the filesystem.
|
|
118
|
+
"""
|
|
119
|
+
path = args.get("path")
|
|
120
|
+
if not isinstance(path, str):
|
|
121
|
+
return "Error: `path` must be a string"
|
|
122
|
+
|
|
123
|
+
target = Path(path)
|
|
124
|
+
if not target.exists():
|
|
125
|
+
return f"Error: file not found at {path}"
|
|
126
|
+
if not target.is_file():
|
|
127
|
+
return f"Error: {path} is not a file"
|
|
128
|
+
|
|
129
|
+
try:
|
|
130
|
+
target.unlink()
|
|
131
|
+
return f"successfully deleted {path}"
|
|
132
|
+
except Exception as e:
|
|
133
|
+
return f"Error: {e}"
|
|
134
|
+
|
|
135
|
+
|
|
136
|
+
DIR_CREATE_PARAMETERS = {
|
|
137
|
+
"type": "object",
|
|
138
|
+
"properties": {
|
|
139
|
+
"path": {
|
|
140
|
+
"type": "string",
|
|
141
|
+
"description": "The path to the directory to create",
|
|
142
|
+
},
|
|
143
|
+
},
|
|
144
|
+
"required": ["path"],
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
|
|
148
|
+
@action(
|
|
149
|
+
name="create_directory",
|
|
150
|
+
description="Create a directory on the filesystem",
|
|
151
|
+
parameters=DIR_CREATE_PARAMETERS,
|
|
152
|
+
)
|
|
153
|
+
async def create_directory(args: dict[str, Any]) -> str:
|
|
154
|
+
"""
|
|
155
|
+
Create a directory on the filesystem.
|
|
156
|
+
"""
|
|
157
|
+
path = args["path"]
|
|
158
|
+
if not isinstance(path, str):
|
|
159
|
+
return "Error: `path` must be a string"
|
|
160
|
+
|
|
161
|
+
target = Path(path)
|
|
162
|
+
if target.exists() and target.is_dir():
|
|
163
|
+
return f"Error: directory already exists at {path}"
|
|
164
|
+
if target.exists() and target.is_file():
|
|
165
|
+
return f"Error: {path} is a file, not a directory"
|
|
166
|
+
|
|
167
|
+
try:
|
|
168
|
+
target.mkdir(parents=True, exist_ok=False)
|
|
169
|
+
return f"successfully created directory at {path}"
|
|
170
|
+
except Exception as e:
|
|
171
|
+
return f"Error: {e}"
|
|
172
|
+
|
|
173
|
+
|
|
174
|
+
DIR_READ_PARAMETERS = {
|
|
175
|
+
"type": "object",
|
|
176
|
+
"properties": {
|
|
177
|
+
"path": {
|
|
178
|
+
"type": "string",
|
|
179
|
+
"description": "The path to the directory to read",
|
|
180
|
+
},
|
|
181
|
+
},
|
|
182
|
+
"required": ["path"],
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
|
|
186
|
+
@action(
|
|
187
|
+
name="read_directory",
|
|
188
|
+
description="Read a directory on the filesystem",
|
|
189
|
+
parameters=DIR_READ_PARAMETERS,
|
|
190
|
+
)
|
|
191
|
+
async def read_directory(args: dict[str, Any]) -> str:
|
|
192
|
+
"""
|
|
193
|
+
Read a directory on the filesystem.
|
|
194
|
+
"""
|
|
195
|
+
path = args.get("path")
|
|
196
|
+
if not isinstance(path, str):
|
|
197
|
+
return "Error: `path` must be a string"
|
|
198
|
+
|
|
199
|
+
target = Path(path)
|
|
200
|
+
if not target.exists():
|
|
201
|
+
return f"Error: directory not found at {path}"
|
|
202
|
+
if not target.is_dir():
|
|
203
|
+
return f"Error: {path} is not a directory"
|
|
204
|
+
|
|
205
|
+
try:
|
|
206
|
+
entries = sorted(target.iterdir(), key=lambda p: p.name)
|
|
207
|
+
return "\n".join(entry.name for entry in entries)
|
|
208
|
+
except Exception as e:
|
|
209
|
+
return f"Error: {e}"
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
from .actions import (
|
|
2
|
+
http_delete,
|
|
3
|
+
http_get,
|
|
4
|
+
http_head,
|
|
5
|
+
http_options,
|
|
6
|
+
http_patch,
|
|
7
|
+
http_post,
|
|
8
|
+
http_put,
|
|
9
|
+
)
|
|
10
|
+
|
|
11
|
+
__all__ = [
|
|
12
|
+
"http_get",
|
|
13
|
+
"http_post",
|
|
14
|
+
"http_put",
|
|
15
|
+
"http_delete",
|
|
16
|
+
"http_patch",
|
|
17
|
+
"http_head",
|
|
18
|
+
"http_options",
|
|
19
|
+
]
|
|
@@ -0,0 +1,333 @@
|
|
|
1
|
+
# SPDX-License-Identifier: Apache-2.0
|
|
2
|
+
# Copyright (c) 2025 Addison Kline
|
|
3
|
+
|
|
4
|
+
from typing import Any
|
|
5
|
+
|
|
6
|
+
import aiohttp
|
|
7
|
+
|
|
8
|
+
from mail import action
|
|
9
|
+
|
|
10
|
+
HTTP_GET_PARAMETERS = {
|
|
11
|
+
"type": "object",
|
|
12
|
+
"properties": {
|
|
13
|
+
"url": {
|
|
14
|
+
"type": "string",
|
|
15
|
+
"description": "The URL to GET.",
|
|
16
|
+
},
|
|
17
|
+
"headers": {
|
|
18
|
+
"type": "object",
|
|
19
|
+
"description": "The headers to send with the request.",
|
|
20
|
+
"optional": True,
|
|
21
|
+
},
|
|
22
|
+
},
|
|
23
|
+
"required": ["url"],
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
@action(
|
|
28
|
+
name="http_get",
|
|
29
|
+
description="Get a URL via HTTP.",
|
|
30
|
+
parameters=HTTP_GET_PARAMETERS,
|
|
31
|
+
)
|
|
32
|
+
async def http_get(args: dict[str, Any]) -> str:
|
|
33
|
+
"""
|
|
34
|
+
Get a URL via HTTP.
|
|
35
|
+
"""
|
|
36
|
+
url = args.get("url")
|
|
37
|
+
if url is None:
|
|
38
|
+
return "Error: `url` is required"
|
|
39
|
+
if not isinstance(url, str):
|
|
40
|
+
return "Error: `url` must be a string"
|
|
41
|
+
|
|
42
|
+
try:
|
|
43
|
+
async with aiohttp.ClientSession() as session:
|
|
44
|
+
async with session.get(url) as response:
|
|
45
|
+
return await response.text()
|
|
46
|
+
except Exception as e:
|
|
47
|
+
return f"Error: {e}"
|
|
48
|
+
|
|
49
|
+
|
|
50
|
+
HTTP_POST_PARAMETERS = {
|
|
51
|
+
"type": "object",
|
|
52
|
+
"properties": {
|
|
53
|
+
"url": {
|
|
54
|
+
"type": "string",
|
|
55
|
+
"description": "The URL to POST to.",
|
|
56
|
+
},
|
|
57
|
+
"headers": {
|
|
58
|
+
"type": "object",
|
|
59
|
+
"description": "The headers to send with the request.",
|
|
60
|
+
},
|
|
61
|
+
"body": {
|
|
62
|
+
"type": "object",
|
|
63
|
+
"description": "The body to send with the request.",
|
|
64
|
+
},
|
|
65
|
+
},
|
|
66
|
+
"required": ["url", "headers", "body"],
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
|
|
70
|
+
@action(
|
|
71
|
+
name="http_post",
|
|
72
|
+
description="Post to a URL via HTTP.",
|
|
73
|
+
parameters=HTTP_POST_PARAMETERS,
|
|
74
|
+
)
|
|
75
|
+
async def http_post(args: dict[str, Any]) -> str:
|
|
76
|
+
"""
|
|
77
|
+
Post to a URL via HTTP.
|
|
78
|
+
"""
|
|
79
|
+
url = args.get("url")
|
|
80
|
+
headers = args.get("headers")
|
|
81
|
+
body = args.get("body")
|
|
82
|
+
|
|
83
|
+
if url is None:
|
|
84
|
+
return "Error: `url` is required"
|
|
85
|
+
if headers is None:
|
|
86
|
+
return "Error: `headers` is required"
|
|
87
|
+
if body is None:
|
|
88
|
+
return "Error: `body` is required"
|
|
89
|
+
|
|
90
|
+
if not isinstance(url, str):
|
|
91
|
+
return "Error: `url` must be a string"
|
|
92
|
+
if not isinstance(headers, dict):
|
|
93
|
+
return "Error: `headers` must be a dictionary"
|
|
94
|
+
if not isinstance(body, dict):
|
|
95
|
+
return "Error: `body` must be a dictionary"
|
|
96
|
+
|
|
97
|
+
try:
|
|
98
|
+
async with aiohttp.ClientSession() as session:
|
|
99
|
+
async with session.post(url, headers=headers, json=body) as response:
|
|
100
|
+
return await response.text()
|
|
101
|
+
except Exception as e:
|
|
102
|
+
return f"Error: {e}"
|
|
103
|
+
|
|
104
|
+
|
|
105
|
+
HTTP_PUT_PARAMETERS = {
|
|
106
|
+
"type": "object",
|
|
107
|
+
"properties": {
|
|
108
|
+
"url": {
|
|
109
|
+
"type": "string",
|
|
110
|
+
"description": "The URL to PUT to.",
|
|
111
|
+
},
|
|
112
|
+
"headers": {
|
|
113
|
+
"type": "object",
|
|
114
|
+
"description": "The headers to send with the request.",
|
|
115
|
+
},
|
|
116
|
+
"body": {
|
|
117
|
+
"type": "object",
|
|
118
|
+
"description": "The body to send with the request.",
|
|
119
|
+
},
|
|
120
|
+
},
|
|
121
|
+
"required": ["url", "headers", "body"],
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
|
|
125
|
+
@action(
|
|
126
|
+
name="http_put",
|
|
127
|
+
description="Put to a URL via HTTP.",
|
|
128
|
+
parameters=HTTP_PUT_PARAMETERS,
|
|
129
|
+
)
|
|
130
|
+
async def http_put(args: dict[str, Any]) -> str:
|
|
131
|
+
"""
|
|
132
|
+
Put to a URL via HTTP.
|
|
133
|
+
"""
|
|
134
|
+
url = args.get("url")
|
|
135
|
+
headers = args.get("headers")
|
|
136
|
+
body = args.get("body")
|
|
137
|
+
|
|
138
|
+
if url is None:
|
|
139
|
+
return "Error: `url` is required"
|
|
140
|
+
if headers is None:
|
|
141
|
+
return "Error: `headers` is required"
|
|
142
|
+
if body is None:
|
|
143
|
+
return "Error: `body` is required"
|
|
144
|
+
|
|
145
|
+
if not isinstance(url, str):
|
|
146
|
+
return "Error: `url` must be a string"
|
|
147
|
+
if not isinstance(headers, dict):
|
|
148
|
+
return "Error: `headers` must be a dictionary"
|
|
149
|
+
if not isinstance(body, dict):
|
|
150
|
+
return "Error: `body` must be a dictionary"
|
|
151
|
+
|
|
152
|
+
try:
|
|
153
|
+
async with aiohttp.ClientSession() as session:
|
|
154
|
+
async with session.put(url, headers=headers, json=body) as response:
|
|
155
|
+
return await response.text()
|
|
156
|
+
except Exception as e:
|
|
157
|
+
return f"Error: {e}"
|
|
158
|
+
|
|
159
|
+
|
|
160
|
+
HTTP_DELETE_PARAMETERS = {
|
|
161
|
+
"type": "object",
|
|
162
|
+
"properties": {
|
|
163
|
+
"url": {
|
|
164
|
+
"type": "string",
|
|
165
|
+
"description": "The URL to DELETE.",
|
|
166
|
+
},
|
|
167
|
+
"headers": {
|
|
168
|
+
"type": "object",
|
|
169
|
+
"description": "The headers to send with the request.",
|
|
170
|
+
"optional": True,
|
|
171
|
+
},
|
|
172
|
+
},
|
|
173
|
+
"required": ["url"],
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
|
|
177
|
+
@action(
|
|
178
|
+
name="http_delete",
|
|
179
|
+
description="Delete a URL via HTTP.",
|
|
180
|
+
parameters=HTTP_DELETE_PARAMETERS,
|
|
181
|
+
)
|
|
182
|
+
async def http_delete(args: dict[str, Any]) -> str:
|
|
183
|
+
"""
|
|
184
|
+
Delete a URL via HTTP.
|
|
185
|
+
"""
|
|
186
|
+
url = args.get("url")
|
|
187
|
+
if url is None:
|
|
188
|
+
return "Error: `url` is required"
|
|
189
|
+
if not isinstance(url, str):
|
|
190
|
+
return "Error: `url` must be a string"
|
|
191
|
+
|
|
192
|
+
try:
|
|
193
|
+
async with aiohttp.ClientSession() as session:
|
|
194
|
+
async with session.delete(url) as response:
|
|
195
|
+
return await response.text()
|
|
196
|
+
except Exception as e:
|
|
197
|
+
return f"Error: {e}"
|
|
198
|
+
|
|
199
|
+
|
|
200
|
+
HTTP_PATCH_PARAMETERS = {
|
|
201
|
+
"type": "object",
|
|
202
|
+
"properties": {
|
|
203
|
+
"url": {
|
|
204
|
+
"type": "string",
|
|
205
|
+
"description": "The URL to PATCH.",
|
|
206
|
+
},
|
|
207
|
+
"headers": {
|
|
208
|
+
"type": "object",
|
|
209
|
+
"description": "The headers to send with the request.",
|
|
210
|
+
"optional": True,
|
|
211
|
+
},
|
|
212
|
+
"body": {
|
|
213
|
+
"type": "object",
|
|
214
|
+
"description": "The body to send with the request.",
|
|
215
|
+
},
|
|
216
|
+
},
|
|
217
|
+
"required": ["url", "body"],
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
|
|
221
|
+
@action(
|
|
222
|
+
name="http_patch",
|
|
223
|
+
description="Patch a URL via HTTP.",
|
|
224
|
+
parameters=HTTP_PATCH_PARAMETERS,
|
|
225
|
+
)
|
|
226
|
+
async def http_patch(args: dict[str, Any]) -> str:
|
|
227
|
+
"""
|
|
228
|
+
Patch a URL via HTTP.
|
|
229
|
+
"""
|
|
230
|
+
url = args.get("url")
|
|
231
|
+
headers = args.get("headers")
|
|
232
|
+
body = args.get("body")
|
|
233
|
+
|
|
234
|
+
if url is None:
|
|
235
|
+
return "Error: `url` is required"
|
|
236
|
+
if body is None:
|
|
237
|
+
return "Error: `body` is required"
|
|
238
|
+
|
|
239
|
+
if not isinstance(url, str):
|
|
240
|
+
return "Error: `url` must be a string"
|
|
241
|
+
if not isinstance(body, dict):
|
|
242
|
+
return "Error: `body` must be a dictionary"
|
|
243
|
+
|
|
244
|
+
try:
|
|
245
|
+
async with aiohttp.ClientSession() as session:
|
|
246
|
+
async with session.patch(url, headers=headers, json=body) as response:
|
|
247
|
+
return await response.text()
|
|
248
|
+
except Exception as e:
|
|
249
|
+
return f"Error: {e}"
|
|
250
|
+
|
|
251
|
+
|
|
252
|
+
HTTP_HEAD_PARAMETERS = {
|
|
253
|
+
"type": "object",
|
|
254
|
+
"properties": {
|
|
255
|
+
"url": {
|
|
256
|
+
"type": "string",
|
|
257
|
+
"description": "The URL to HEAD.",
|
|
258
|
+
},
|
|
259
|
+
"headers": {
|
|
260
|
+
"type": "object",
|
|
261
|
+
"description": "The headers to send with the request.",
|
|
262
|
+
"optional": True,
|
|
263
|
+
},
|
|
264
|
+
},
|
|
265
|
+
"required": ["url"],
|
|
266
|
+
}
|
|
267
|
+
|
|
268
|
+
|
|
269
|
+
@action(
|
|
270
|
+
name="http_head",
|
|
271
|
+
description="Head a URL via HTTP.",
|
|
272
|
+
parameters=HTTP_HEAD_PARAMETERS,
|
|
273
|
+
)
|
|
274
|
+
async def http_head(args: dict[str, Any]) -> str:
|
|
275
|
+
"""
|
|
276
|
+
Head a URL via HTTP.
|
|
277
|
+
"""
|
|
278
|
+
url = args.get("url")
|
|
279
|
+
headers = args.get("headers")
|
|
280
|
+
|
|
281
|
+
if url is None:
|
|
282
|
+
return "Error: `url` is required"
|
|
283
|
+
if not isinstance(url, str):
|
|
284
|
+
return "Error: `url` must be a string"
|
|
285
|
+
|
|
286
|
+
try:
|
|
287
|
+
async with aiohttp.ClientSession() as session:
|
|
288
|
+
async with session.head(url, headers=headers) as response:
|
|
289
|
+
return await response.text()
|
|
290
|
+
except Exception as e:
|
|
291
|
+
return f"Error: {e}"
|
|
292
|
+
|
|
293
|
+
|
|
294
|
+
HTTP_OPTIONS_PARAMETERS = {
|
|
295
|
+
"type": "object",
|
|
296
|
+
"properties": {
|
|
297
|
+
"url": {
|
|
298
|
+
"type": "string",
|
|
299
|
+
"description": "The URL to OPTIONS.",
|
|
300
|
+
},
|
|
301
|
+
"headers": {
|
|
302
|
+
"type": "object",
|
|
303
|
+
"description": "The headers to send with the request.",
|
|
304
|
+
"optional": True,
|
|
305
|
+
},
|
|
306
|
+
},
|
|
307
|
+
"required": ["url"],
|
|
308
|
+
}
|
|
309
|
+
|
|
310
|
+
|
|
311
|
+
@action(
|
|
312
|
+
name="http_options",
|
|
313
|
+
description="Options a URL via HTTP.",
|
|
314
|
+
parameters=HTTP_OPTIONS_PARAMETERS,
|
|
315
|
+
)
|
|
316
|
+
async def http_options(args: dict[str, Any]) -> str:
|
|
317
|
+
"""
|
|
318
|
+
Options a URL via HTTP.
|
|
319
|
+
"""
|
|
320
|
+
url = args.get("url")
|
|
321
|
+
headers = args.get("headers")
|
|
322
|
+
|
|
323
|
+
if url is None:
|
|
324
|
+
return "Error: `url` is required"
|
|
325
|
+
if not isinstance(url, str):
|
|
326
|
+
return "Error: `url` must be a string"
|
|
327
|
+
|
|
328
|
+
try:
|
|
329
|
+
async with aiohttp.ClientSession() as session:
|
|
330
|
+
async with session.options(url, headers=headers) as response:
|
|
331
|
+
return await response.text()
|
|
332
|
+
except Exception as e:
|
|
333
|
+
return f"Error: {e}"
|