rossum-mcp 0.3.4__py3-none-any.whl → 0.4.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.
- rossum_mcp/__init__.py +1 -1
- rossum_mcp/server.py +4 -0
- rossum_mcp/tools/__init__.py +14 -0
- rossum_mcp/tools/annotations.py +123 -86
- rossum_mcp/tools/base.py +22 -0
- rossum_mcp/tools/catalog.py +169 -0
- rossum_mcp/tools/discovery.py +36 -0
- rossum_mcp/tools/document_relations.py +1 -3
- rossum_mcp/tools/email_templates.py +131 -0
- rossum_mcp/tools/engines.py +106 -77
- rossum_mcp/tools/hooks.py +228 -150
- rossum_mcp/tools/queues.py +244 -85
- rossum_mcp/tools/relations.py +3 -7
- rossum_mcp/tools/rules.py +28 -17
- rossum_mcp/tools/schemas.py +505 -105
- rossum_mcp/tools/users.py +51 -27
- rossum_mcp/tools/workspaces.py +47 -37
- {rossum_mcp-0.3.4.dist-info → rossum_mcp-0.4.0.dist-info}/METADATA +370 -12
- rossum_mcp-0.4.0.dist-info/RECORD +24 -0
- rossum_mcp-0.3.4.dist-info/RECORD +0 -21
- {rossum_mcp-0.3.4.dist-info → rossum_mcp-0.4.0.dist-info}/WHEEL +0 -0
- {rossum_mcp-0.3.4.dist-info → rossum_mcp-0.4.0.dist-info}/entry_points.txt +0 -0
- {rossum_mcp-0.3.4.dist-info → rossum_mcp-0.4.0.dist-info}/top_level.txt +0 -0
rossum_mcp/tools/hooks.py
CHANGED
|
@@ -6,13 +6,9 @@ import logging
|
|
|
6
6
|
from dataclasses import dataclass
|
|
7
7
|
from typing import TYPE_CHECKING, Annotated, Any, Literal
|
|
8
8
|
|
|
9
|
-
from rossum_api.models.hook import
|
|
10
|
-
Hook,
|
|
11
|
-
HookRunData,
|
|
12
|
-
HookType,
|
|
13
|
-
)
|
|
9
|
+
from rossum_api.models.hook import Hook, HookRunData, HookType
|
|
14
10
|
|
|
15
|
-
from rossum_mcp.tools.base import is_read_write_mode
|
|
11
|
+
from rossum_mcp.tools.base import TRUNCATED_MARKER, is_read_write_mode
|
|
16
12
|
|
|
17
13
|
if TYPE_CHECKING:
|
|
18
14
|
from fastmcp import FastMCP
|
|
@@ -43,15 +39,213 @@ class HookTemplate:
|
|
|
43
39
|
use_token_owner: bool
|
|
44
40
|
|
|
45
41
|
|
|
46
|
-
def
|
|
42
|
+
async def _get_hook(client: AsyncRossumAPIClient, hook_id: int) -> Hook:
|
|
43
|
+
hook: Hook = await client.retrieve_hook(hook_id)
|
|
44
|
+
return hook
|
|
45
|
+
|
|
46
|
+
|
|
47
|
+
async def _list_hooks(
|
|
48
|
+
client: AsyncRossumAPIClient,
|
|
49
|
+
queue_id: int | None = None,
|
|
50
|
+
active: bool | None = None,
|
|
51
|
+
first_n: int | None = None,
|
|
52
|
+
) -> list[Hook]:
|
|
53
|
+
filters: dict = {}
|
|
54
|
+
if queue_id is not None:
|
|
55
|
+
filters["queue"] = queue_id
|
|
56
|
+
if active is not None:
|
|
57
|
+
filters["active"] = active
|
|
58
|
+
|
|
59
|
+
if first_n is not None:
|
|
60
|
+
hooks_iter = client.list_hooks(**filters)
|
|
61
|
+
hooks_list: list[Hook] = []
|
|
62
|
+
n = 0
|
|
63
|
+
while n < first_n:
|
|
64
|
+
hooks_list.append(await anext(hooks_iter))
|
|
65
|
+
n += 1
|
|
66
|
+
else:
|
|
67
|
+
hooks_list = [hook async for hook in client.list_hooks(**filters)]
|
|
68
|
+
|
|
69
|
+
return hooks_list
|
|
70
|
+
|
|
71
|
+
|
|
72
|
+
async def _create_hook(
|
|
73
|
+
client: AsyncRossumAPIClient,
|
|
74
|
+
name: str,
|
|
75
|
+
type: HookType,
|
|
76
|
+
queues: list[str] | None = None,
|
|
77
|
+
events: list[str] | None = None,
|
|
78
|
+
config: dict | None = None,
|
|
79
|
+
settings: dict | None = None,
|
|
80
|
+
secret: str | None = None,
|
|
81
|
+
) -> Hook | dict:
|
|
82
|
+
if not is_read_write_mode():
|
|
83
|
+
return {"error": "create_hook is not available in read-only mode"}
|
|
84
|
+
|
|
85
|
+
hook_data: dict[str, Any] = {"name": name, "type": type, "sideload": ["schemas"]}
|
|
86
|
+
|
|
87
|
+
if queues is not None:
|
|
88
|
+
hook_data["queues"] = queues
|
|
89
|
+
if events is not None:
|
|
90
|
+
hook_data["events"] = events
|
|
91
|
+
if config is None:
|
|
92
|
+
config = {}
|
|
93
|
+
if type == "function" and "source" in config:
|
|
94
|
+
config["function"] = config.pop("source")
|
|
95
|
+
if type == "function" and "runtime" not in config:
|
|
96
|
+
config["runtime"] = "python3.12"
|
|
97
|
+
if "timeout_s" in config and config["timeout_s"] > 60:
|
|
98
|
+
config["timeout_s"] = 60
|
|
99
|
+
hook_data["config"] = config
|
|
100
|
+
if settings is not None:
|
|
101
|
+
hook_data["settings"] = settings
|
|
102
|
+
if secret is not None:
|
|
103
|
+
hook_data["secret"] = secret
|
|
104
|
+
|
|
105
|
+
hook: Hook = await client.create_new_hook(hook_data)
|
|
106
|
+
return hook
|
|
107
|
+
|
|
108
|
+
|
|
109
|
+
async def _update_hook(
|
|
110
|
+
client: AsyncRossumAPIClient,
|
|
111
|
+
hook_id: int,
|
|
112
|
+
name: str | None = None,
|
|
113
|
+
queues: list[str] | None = None,
|
|
114
|
+
events: list[str] | None = None,
|
|
115
|
+
config: dict | None = None,
|
|
116
|
+
settings: dict | None = None,
|
|
117
|
+
active: bool | None = None,
|
|
118
|
+
) -> Hook | dict:
|
|
119
|
+
if not is_read_write_mode():
|
|
120
|
+
return {"error": "update_hook is not available in read-only mode"}
|
|
121
|
+
|
|
122
|
+
logger.debug(f"Updating hook: hook_id={hook_id}")
|
|
123
|
+
|
|
124
|
+
existing_hook: Hook = await client.retrieve_hook(hook_id)
|
|
125
|
+
hook_data: dict[str, Any] = {
|
|
126
|
+
"name": existing_hook.name,
|
|
127
|
+
"queues": existing_hook.queues,
|
|
128
|
+
"events": list(existing_hook.events),
|
|
129
|
+
"config": dict(existing_hook.config) if existing_hook.config else {},
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
if name is not None:
|
|
133
|
+
hook_data["name"] = name
|
|
134
|
+
if queues is not None:
|
|
135
|
+
hook_data["queues"] = queues
|
|
136
|
+
if events is not None:
|
|
137
|
+
hook_data["events"] = events
|
|
138
|
+
if config is not None:
|
|
139
|
+
hook_data["config"] = config
|
|
140
|
+
if settings is not None:
|
|
141
|
+
hook_data["settings"] = settings
|
|
142
|
+
if active is not None:
|
|
143
|
+
hook_data["active"] = active
|
|
144
|
+
|
|
145
|
+
updated_hook: Hook = await client.update_part_hook(hook_id, hook_data)
|
|
146
|
+
return updated_hook
|
|
147
|
+
|
|
148
|
+
|
|
149
|
+
async def _list_hook_logs(
|
|
150
|
+
client: AsyncRossumAPIClient,
|
|
151
|
+
hook_id: int | None = None,
|
|
152
|
+
queue_id: int | None = None,
|
|
153
|
+
annotation_id: int | None = None,
|
|
154
|
+
email_id: int | None = None,
|
|
155
|
+
log_level: Literal["INFO", "ERROR", "WARNING"] | None = None,
|
|
156
|
+
status: str | None = None,
|
|
157
|
+
status_code: int | None = None,
|
|
158
|
+
request_id: str | None = None,
|
|
159
|
+
timestamp_before: Timestamp | None = None,
|
|
160
|
+
timestamp_after: Timestamp | None = None,
|
|
161
|
+
start_before: Timestamp | None = None,
|
|
162
|
+
start_after: Timestamp | None = None,
|
|
163
|
+
end_before: Timestamp | None = None,
|
|
164
|
+
end_after: Timestamp | None = None,
|
|
165
|
+
search: str | None = None,
|
|
166
|
+
page_size: int | None = None,
|
|
167
|
+
) -> list[HookRunData]:
|
|
168
|
+
filter_mapping: dict[str, Any] = {
|
|
169
|
+
"hook": hook_id,
|
|
170
|
+
"queue": queue_id,
|
|
171
|
+
"annotation": annotation_id,
|
|
172
|
+
"email": email_id,
|
|
173
|
+
"log_level": log_level,
|
|
174
|
+
"status": status,
|
|
175
|
+
"status_code": status_code,
|
|
176
|
+
"request_id": request_id,
|
|
177
|
+
"timestamp_before": timestamp_before,
|
|
178
|
+
"timestamp_after": timestamp_after,
|
|
179
|
+
"start_before": start_before,
|
|
180
|
+
"start_after": start_after,
|
|
181
|
+
"end_before": end_before,
|
|
182
|
+
"end_after": end_after,
|
|
183
|
+
"search": search,
|
|
184
|
+
"page_size": page_size,
|
|
185
|
+
}
|
|
186
|
+
filters = {k: v for k, v in filter_mapping.items() if v is not None}
|
|
187
|
+
|
|
188
|
+
return [log async for log in client.list_hook_run_data(**filters)]
|
|
189
|
+
|
|
190
|
+
|
|
191
|
+
async def _list_hook_templates(client: AsyncRossumAPIClient) -> list[HookTemplate]:
|
|
192
|
+
templates: list[HookTemplate] = []
|
|
193
|
+
async for item in client.request_paginated("hook_templates"):
|
|
194
|
+
url = item["url"]
|
|
195
|
+
templates.append(
|
|
196
|
+
HookTemplate(
|
|
197
|
+
id=int(url.split("/")[-1]),
|
|
198
|
+
url=url,
|
|
199
|
+
name=item["name"],
|
|
200
|
+
description=item.get("description", ""),
|
|
201
|
+
type=item["type"],
|
|
202
|
+
events=[],
|
|
203
|
+
config={},
|
|
204
|
+
settings_schema=item.get("settings_schema"),
|
|
205
|
+
guide=TRUNCATED_MARKER,
|
|
206
|
+
use_token_owner=item.get("use_token_owner", False),
|
|
207
|
+
)
|
|
208
|
+
)
|
|
209
|
+
return templates
|
|
210
|
+
|
|
211
|
+
|
|
212
|
+
async def _create_hook_from_template(
|
|
213
|
+
client: AsyncRossumAPIClient,
|
|
214
|
+
name: str,
|
|
215
|
+
hook_template_id: int,
|
|
216
|
+
queues: list[str],
|
|
217
|
+
events: list[str] | None = None,
|
|
218
|
+
token_owner: str | None = None,
|
|
219
|
+
) -> Hook | dict:
|
|
220
|
+
if not is_read_write_mode():
|
|
221
|
+
return {"error": "create_hook_from_template is not available in read-only mode"}
|
|
222
|
+
|
|
223
|
+
logger.debug(f"Creating hook from template: name={name}, template_id={hook_template_id}")
|
|
224
|
+
|
|
225
|
+
hook_template_url = f"{client._http_client.base_url.rstrip('/')}/hook_templates/{hook_template_id}"
|
|
226
|
+
|
|
227
|
+
hook_data: dict[str, Any] = {"name": name, "hook_template": hook_template_url, "queues": queues}
|
|
228
|
+
if events is not None:
|
|
229
|
+
hook_data["events"] = events
|
|
230
|
+
if token_owner is not None:
|
|
231
|
+
hook_data["token_owner"] = token_owner
|
|
232
|
+
|
|
233
|
+
result = await client._http_client.request_json("POST", "hooks/create", json=hook_data)
|
|
234
|
+
|
|
235
|
+
if hook_id := result.get("id"):
|
|
236
|
+
hook: Hook = await client.retrieve_hook(hook_id)
|
|
237
|
+
return hook
|
|
238
|
+
return {"error": "Hook wasn't likely created. Hook ID not available."}
|
|
239
|
+
|
|
240
|
+
|
|
241
|
+
def register_hook_tools(mcp: FastMCP, client: AsyncRossumAPIClient) -> None:
|
|
47
242
|
"""Register hook-related tools with the FastMCP server."""
|
|
48
243
|
|
|
49
244
|
@mcp.tool(
|
|
50
245
|
description="Retrieve a single hook by ID. Use list_hooks first to get all hooks for a queue - only use get_hook if you need additional details for a specific hook not returned by list_hooks. For Python-based function hooks, the source code is accessible via hook.config['code']."
|
|
51
246
|
)
|
|
52
247
|
async def get_hook(hook_id: int) -> Hook:
|
|
53
|
-
|
|
54
|
-
return hook
|
|
248
|
+
return await _get_hook(client, hook_id)
|
|
55
249
|
|
|
56
250
|
@mcp.tool(
|
|
57
251
|
description="List all hooks/extensions for a queue. ALWAYS use this first when you need information about hooks on a queue - it returns complete hook details including code, config, and settings in a single call. Only use get_hook afterward if you need details not present in the list response. For Python-based function hooks, the source code is accessible via hook.config['code']."
|
|
@@ -59,26 +253,8 @@ def register_hook_tools(mcp: FastMCP, client: AsyncRossumAPIClient) -> None: #
|
|
|
59
253
|
async def list_hooks(
|
|
60
254
|
queue_id: int | None = None, active: bool | None = None, first_n: int | None = None
|
|
61
255
|
) -> list[Hook]:
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
filters["queue"] = queue_id
|
|
65
|
-
if active is not None:
|
|
66
|
-
filters["active"] = active
|
|
67
|
-
|
|
68
|
-
if first_n is not None:
|
|
69
|
-
hooks_iter = client.list_hooks(**filters)
|
|
70
|
-
hooks_list: list[Hook] = []
|
|
71
|
-
n = 0
|
|
72
|
-
while n < first_n:
|
|
73
|
-
hooks_list.append(await anext(hooks_iter))
|
|
74
|
-
n += 1
|
|
75
|
-
else:
|
|
76
|
-
hooks_list = [hook async for hook in client.list_hooks(**filters)]
|
|
77
|
-
|
|
78
|
-
return hooks_list
|
|
79
|
-
|
|
80
|
-
# NOTE: We explicitly document token_owner restrictions in the tool description because
|
|
81
|
-
# Sonnet 4.5 respects tool descriptions more reliably than instructions in system prompts.
|
|
256
|
+
return await _list_hooks(client, queue_id, active, first_n)
|
|
257
|
+
|
|
82
258
|
@mcp.tool(
|
|
83
259
|
description="Create a new hook. If token_owner is provided, organization_group_admin users CANNOT be used (API will reject)."
|
|
84
260
|
)
|
|
@@ -91,31 +267,7 @@ def register_hook_tools(mcp: FastMCP, client: AsyncRossumAPIClient) -> None: #
|
|
|
91
267
|
settings: dict | None = None,
|
|
92
268
|
secret: str | None = None,
|
|
93
269
|
) -> Hook | dict:
|
|
94
|
-
|
|
95
|
-
return {"error": "create_hook is not available in read-only mode"}
|
|
96
|
-
|
|
97
|
-
hook_data: dict[str, Any] = {"name": name, "type": type, "sideload": ["schemas"]}
|
|
98
|
-
|
|
99
|
-
if queues is not None:
|
|
100
|
-
hook_data["queues"] = queues
|
|
101
|
-
if events is not None:
|
|
102
|
-
hook_data["events"] = events
|
|
103
|
-
if config is None:
|
|
104
|
-
config = {}
|
|
105
|
-
if type == "function" and "source" in config:
|
|
106
|
-
config["function"] = config.pop("source")
|
|
107
|
-
if type == "function" and "runtime" not in config:
|
|
108
|
-
config["runtime"] = "python3.12"
|
|
109
|
-
if "timeout_s" in config and config["timeout_s"] > 60:
|
|
110
|
-
config["timeout_s"] = 60
|
|
111
|
-
hook_data["config"] = config
|
|
112
|
-
if settings is not None:
|
|
113
|
-
hook_data["settings"] = settings
|
|
114
|
-
if secret is not None:
|
|
115
|
-
hook_data["secret"] = secret
|
|
116
|
-
|
|
117
|
-
hook: Hook = await client.create_new_hook(hook_data)
|
|
118
|
-
return hook
|
|
270
|
+
return await _create_hook(client, name, type, queues, events, config, settings, secret)
|
|
119
271
|
|
|
120
272
|
@mcp.tool(
|
|
121
273
|
description="Update an existing hook. Use this to modify hook properties like name, queues, config, events, or settings. Only provide the fields you want to change - other fields will remain unchanged."
|
|
@@ -129,36 +281,7 @@ def register_hook_tools(mcp: FastMCP, client: AsyncRossumAPIClient) -> None: #
|
|
|
129
281
|
settings: dict | None = None,
|
|
130
282
|
active: bool | None = None,
|
|
131
283
|
) -> Hook | dict:
|
|
132
|
-
|
|
133
|
-
return {"error": "update_hook is not available in read-only mode"}
|
|
134
|
-
|
|
135
|
-
logger.debug(f"Updating hook: hook_id={hook_id}")
|
|
136
|
-
|
|
137
|
-
# Fetch existing hook data first (PUT requires all fields)
|
|
138
|
-
existing_hook: Hook = await client.retrieve_hook(hook_id)
|
|
139
|
-
hook_data: dict[str, Any] = {
|
|
140
|
-
"name": existing_hook.name,
|
|
141
|
-
"queues": existing_hook.queues,
|
|
142
|
-
"events": list(existing_hook.events),
|
|
143
|
-
"config": dict(existing_hook.config) if existing_hook.config else {},
|
|
144
|
-
}
|
|
145
|
-
|
|
146
|
-
# Override with provided values
|
|
147
|
-
if name is not None:
|
|
148
|
-
hook_data["name"] = name
|
|
149
|
-
if queues is not None:
|
|
150
|
-
hook_data["queues"] = queues
|
|
151
|
-
if events is not None:
|
|
152
|
-
hook_data["events"] = events
|
|
153
|
-
if config is not None:
|
|
154
|
-
hook_data["config"] = config
|
|
155
|
-
if settings is not None:
|
|
156
|
-
hook_data["settings"] = settings
|
|
157
|
-
if active is not None:
|
|
158
|
-
hook_data["active"] = active
|
|
159
|
-
|
|
160
|
-
updated_hook: Hook = await client.update_part_hook(hook_id, hook_data)
|
|
161
|
-
return updated_hook
|
|
284
|
+
return await _update_hook(client, hook_id, name, queues, events, config, settings, active)
|
|
162
285
|
|
|
163
286
|
@mcp.tool(
|
|
164
287
|
description="List hook execution logs. Use this to debug hook executions, monitor performance, and troubleshoot errors. Logs are retained for 7 days. Returns at most 100 logs per call."
|
|
@@ -181,57 +304,32 @@ def register_hook_tools(mcp: FastMCP, client: AsyncRossumAPIClient) -> None: #
|
|
|
181
304
|
search: str | None = None,
|
|
182
305
|
page_size: int | None = None,
|
|
183
306
|
) -> list[HookRunData]:
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
# list_hook_run_data is available from ds-feat-hook-logs branch
|
|
205
|
-
return [
|
|
206
|
-
log
|
|
207
|
-
async for log in client.list_hook_run_data(**filters) # type: ignore[attr-defined]
|
|
208
|
-
]
|
|
307
|
+
return await _list_hook_logs(
|
|
308
|
+
client,
|
|
309
|
+
hook_id,
|
|
310
|
+
queue_id,
|
|
311
|
+
annotation_id,
|
|
312
|
+
email_id,
|
|
313
|
+
log_level,
|
|
314
|
+
status,
|
|
315
|
+
status_code,
|
|
316
|
+
request_id,
|
|
317
|
+
timestamp_before,
|
|
318
|
+
timestamp_after,
|
|
319
|
+
start_before,
|
|
320
|
+
start_after,
|
|
321
|
+
end_before,
|
|
322
|
+
end_after,
|
|
323
|
+
search,
|
|
324
|
+
page_size,
|
|
325
|
+
)
|
|
209
326
|
|
|
210
327
|
@mcp.tool(
|
|
211
328
|
description="List available hook templates from Rossum Store. Hook templates provide pre-built extension configurations (e.g., data validation, field mapping, notifications) that can be used to quickly create hooks instead of writing code from scratch. Use list_hook_templates first to find a suitable template, then use create_hook_from_template to create a hook based on that template."
|
|
212
329
|
)
|
|
213
330
|
async def list_hook_templates() -> list[HookTemplate]:
|
|
214
|
-
|
|
215
|
-
async for item in client.request_paginated("hook_templates"):
|
|
216
|
-
url = item["url"]
|
|
217
|
-
templates.append(
|
|
218
|
-
HookTemplate(
|
|
219
|
-
id=int(url.split("/")[-1]),
|
|
220
|
-
url=url,
|
|
221
|
-
name=item["name"],
|
|
222
|
-
description=item.get("description", ""),
|
|
223
|
-
type=item["type"],
|
|
224
|
-
events=[],
|
|
225
|
-
config={},
|
|
226
|
-
settings_schema=item.get("settings_schema"),
|
|
227
|
-
guide="<truncated>",
|
|
228
|
-
use_token_owner=item.get("use_token_owner", False),
|
|
229
|
-
)
|
|
230
|
-
)
|
|
231
|
-
return templates
|
|
331
|
+
return await _list_hook_templates(client)
|
|
232
332
|
|
|
233
|
-
# NOTE: We explicitly document token_owner restrictions in the tool description because
|
|
234
|
-
# Sonnet 4.5 respects tool descriptions more reliably than instructions in system prompts.
|
|
235
333
|
@mcp.tool(
|
|
236
334
|
description="Create a hook from a Rossum Store template. Uses pre-built configurations from the Rossum Store. The 'events' parameter is optional and can override template defaults. If the template has 'use_token_owner=True', a valid 'token_owner' user URL is required - use list_users to find one. CRITICAL RESTRICTION: organization_group_admin users are FORBIDDEN as token_owner - the API returns HTTP 400 error."
|
|
237
335
|
)
|
|
@@ -242,24 +340,4 @@ def register_hook_tools(mcp: FastMCP, client: AsyncRossumAPIClient) -> None: #
|
|
|
242
340
|
events: list[str] | None = None,
|
|
243
341
|
token_owner: str | None = None,
|
|
244
342
|
) -> Hook | dict:
|
|
245
|
-
|
|
246
|
-
return {"error": "create_hook_from_template is not available in read-only mode"}
|
|
247
|
-
|
|
248
|
-
logger.debug(f"Creating hook from template: name={name}, template_id={hook_template_id}")
|
|
249
|
-
|
|
250
|
-
# Build the hook template URL and fetch template to get its config
|
|
251
|
-
hook_template_url = f"{client._http_client.base_url.rstrip('/')}/hook_templates/{hook_template_id}"
|
|
252
|
-
|
|
253
|
-
hook_data: dict[str, Any] = {"name": name, "hook_template": hook_template_url, "queues": queues}
|
|
254
|
-
if events is not None:
|
|
255
|
-
hook_data["events"] = events
|
|
256
|
-
if token_owner is not None:
|
|
257
|
-
hook_data["token_owner"] = token_owner
|
|
258
|
-
|
|
259
|
-
result = await client._http_client.request_json("POST", "hooks/create", json=hook_data)
|
|
260
|
-
|
|
261
|
-
# Return the created hook
|
|
262
|
-
if hook_id := result.get("id"):
|
|
263
|
-
hook: Hook = await client.retrieve_hook(hook_id)
|
|
264
|
-
return hook
|
|
265
|
-
return {"error": "Hook wasn't likely created. Hook ID not available."}
|
|
343
|
+
return await _create_hook_from_template(client, name, hook_template_id, queues, events, token_owner)
|