pangea-sdk 6.5.0b1__py3-none-any.whl → 6.7.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.
pangea/__init__.py CHANGED
@@ -1,15 +1,7 @@
1
- __version__ = "6.5.0beta1"
1
+ __version__ = "6.7.0"
2
2
 
3
- from pangea.asyncio.request import PangeaRequestAsync
4
3
  from pangea.config import PangeaConfig
5
4
  from pangea.file_uploader import FileUploader
6
- from pangea.request import PangeaRequest
7
- from pangea.response import PangeaResponse
5
+ from pangea.response import PangeaResponse, PangeaResponseResult, TransferMethod
8
6
 
9
- __all__ = (
10
- "FileUploader",
11
- "PangeaConfig",
12
- "PangeaRequest",
13
- "PangeaRequestAsync",
14
- "PangeaResponse",
15
- )
7
+ __all__ = ("FileUploader", "PangeaConfig", "PangeaResponse", "PangeaResponseResult", "TransferMethod")
pangea/_constants.py ADDED
@@ -0,0 +1,4 @@
1
+ from __future__ import annotations
2
+
3
+ MAX_RETRY_DELAY = 8.0
4
+ RETRYABLE_HTTP_CODES = frozenset({500, 502, 503, 504})
pangea/_typing.py ADDED
@@ -0,0 +1,30 @@
1
+ from __future__ import annotations
2
+
3
+ from collections.abc import Iterator, Sequence
4
+
5
+ from typing_extensions import Any, Protocol, SupportsIndex, TypeVar, overload
6
+
7
+ T = TypeVar("T")
8
+ T_co = TypeVar("T_co", covariant=True)
9
+
10
+
11
+ class SequenceNotStr(Protocol[T_co]):
12
+ """Sequence-like object that isn't str or bytes."""
13
+
14
+ @overload
15
+ def __getitem__(self, index: SupportsIndex, /) -> T_co: ...
16
+
17
+ @overload
18
+ def __getitem__(self, index: slice, /) -> Sequence[T_co]: ...
19
+
20
+ def __contains__(self, value: object, /) -> bool: ...
21
+
22
+ def __len__(self) -> int: ...
23
+
24
+ def __iter__(self) -> Iterator[T_co]: ...
25
+
26
+ def index(self, value: Any, start: int = ..., stop: int = ..., /) -> int: ...
27
+
28
+ def count(self, value: Any, /) -> int: ...
29
+
30
+ def __reversed__(self) -> Iterator[T_co]: ...
@@ -1,2 +1,3 @@
1
- # ruff: noqa: F401
2
1
  from .file_uploader import FileUploaderAsync
2
+
3
+ __all__ = ("FileUploaderAsync",)
@@ -6,9 +6,10 @@ from __future__ import annotations
6
6
  import io
7
7
  import logging
8
8
 
9
+ from pangea import PangeaConfig, TransferMethod
9
10
  from pangea.asyncio.request import PangeaRequestAsync
10
- from pangea.request import PangeaConfig
11
- from pangea.response import TransferMethod
11
+
12
+ __all__ = ("FileUploaderAsync",)
12
13
 
13
14
 
14
15
  class FileUploaderAsync:
pangea/asyncio/request.py CHANGED
@@ -10,19 +10,23 @@ import asyncio
10
10
  import json
11
11
  import time
12
12
  from collections.abc import Iterable, Mapping
13
- from typing import Dict, List, Optional, Sequence, Tuple, Type, Union, cast, overload
13
+ from random import random
14
+ from typing import Dict, List, Optional, Sequence, Tuple, Type, Union, cast
14
15
 
15
16
  import aiohttp
16
17
  from aiohttp import FormData
17
- from pydantic import BaseModel, TypeAdapter
18
+ from pydantic import BaseModel
18
19
  from pydantic_core import to_jsonable_python
19
- from typing_extensions import Any, Literal, TypeAlias, TypeVar, override
20
+ from typing_extensions import Any, TypeAlias, TypeVar, override
20
21
 
21
22
  import pangea.exceptions as pe
23
+ from pangea._constants import MAX_RETRY_DELAY, RETRYABLE_HTTP_CODES
22
24
  from pangea.request import MultipartResponse, PangeaRequestBase
23
25
  from pangea.response import AttachedFile, PangeaResponse, PangeaResponseResult, ResponseStatus, TransferMethod
24
26
  from pangea.utils import default_encoder
25
27
 
28
+ __all__ = ("PangeaRequestAsync",)
29
+
26
30
  _FileName: TypeAlias = Union[str, None]
27
31
  _FileContent: TypeAlias = Union[str, bytes]
28
32
  _FileContentType: TypeAlias = str
@@ -50,24 +54,6 @@ class PangeaRequestAsync(PangeaRequestBase):
50
54
  be set in PangeaConfig.
51
55
  """
52
56
 
53
- async def delete(self, endpoint: str) -> None:
54
- """
55
- Makes a DELETE call to a Pangea endpoint.
56
-
57
- Args:
58
- endpoint: The Pangea API endpoint.
59
- """
60
-
61
- url = self._url(endpoint)
62
-
63
- self.logger.debug(
64
- json.dumps({"service": self.service, "action": "delete", "url": url}, default=default_encoder)
65
- )
66
-
67
- requests_response = await self._http_delete(url, headers=self._headers())
68
- await self._check_http_errors(requests_response)
69
-
70
- @overload
71
57
  async def post(
72
58
  self,
73
59
  endpoint: str,
@@ -76,60 +62,18 @@ class PangeaRequestAsync(PangeaRequestBase):
76
62
  files: Optional[List[Tuple]] = None,
77
63
  poll_result: bool = True,
78
64
  url: Optional[str] = None,
79
- *,
80
- pangea_response: Literal[True] = True,
81
65
  ) -> PangeaResponse[TResult]:
82
- """
83
- Makes a POST call to a Pangea Service endpoint.
66
+ """Makes the POST call to a Pangea Service endpoint.
84
67
 
85
68
  Args:
86
- endpoint: The Pangea Service API endpoint.
87
- data: The POST body payload object
69
+ endpoint(str): The Pangea Service API endpoint.
70
+ data(dict): The POST body payload object
88
71
 
89
72
  Returns:
90
73
  PangeaResponse which contains the response in its entirety and
91
74
  various properties to retrieve individual fields
92
75
  """
93
76
 
94
- @overload
95
- async def post(
96
- self,
97
- endpoint: str,
98
- result_class: Type[TResult],
99
- data: str | BaseModel | Mapping[str, Any] | None = None,
100
- files: Optional[List[Tuple]] = None,
101
- poll_result: bool = True,
102
- url: Optional[str] = None,
103
- *,
104
- pangea_response: Literal[False],
105
- ) -> TResult:
106
- """
107
- Makes a POST call to a Pangea Service endpoint.
108
-
109
- Args:
110
- endpoint: The Pangea Service API endpoint.
111
- data: The POST body payload object
112
- """
113
-
114
- async def post(
115
- self,
116
- endpoint: str,
117
- result_class: Type[TResult],
118
- data: str | BaseModel | Mapping[str, Any] | None = None,
119
- files: Optional[List[Tuple]] = None,
120
- poll_result: bool = True,
121
- url: Optional[str] = None,
122
- *,
123
- pangea_response: bool = True,
124
- ) -> PangeaResponse[TResult] | TResult:
125
- """
126
- Makes a POST call to a Pangea Service endpoint.
127
-
128
- Args:
129
- endpoint: The Pangea Service API endpoint.
130
- data: The POST body payload object
131
- """
132
-
133
77
  if isinstance(data, BaseModel):
134
78
  data = data.model_dump(exclude_none=True)
135
79
 
@@ -169,13 +113,9 @@ class PangeaRequestAsync(PangeaRequestBase):
169
113
 
170
114
  await self._check_http_errors(requests_response)
171
115
 
172
- if not pangea_response:
173
- type_adapter = TypeAdapter(result_class)
174
- return type_adapter.validate_python(await requests_response.json())
175
-
176
116
  if "multipart/form-data" in requests_response.headers.get("content-type", ""):
177
117
  multipart_response = await self._process_multipart_response(requests_response)
178
- pangea_response_obj: PangeaResponse = PangeaResponse(
118
+ pangea_response: PangeaResponse = PangeaResponse(
179
119
  requests_response,
180
120
  result_class=result_class,
181
121
  json=multipart_response.pangea_json,
@@ -188,110 +128,49 @@ class PangeaRequestAsync(PangeaRequestBase):
188
128
  json.dumps({"service": self.service, "action": "post", "url": url, "response": json_resp})
189
129
  )
190
130
 
191
- pangea_response_obj = PangeaResponse(requests_response, result_class=result_class, json=json_resp)
131
+ pangea_response = PangeaResponse(requests_response, result_class=result_class, json=json_resp)
192
132
  except aiohttp.ContentTypeError as e:
193
133
  raise pe.PangeaException(
194
134
  f"Failed to decode json response. {e}. Body: {await requests_response.text()}"
195
135
  ) from e
196
136
 
197
137
  if poll_result:
198
- pangea_response_obj = await self._handle_queued_result(pangea_response_obj)
138
+ pangea_response = await self._handle_queued_result(pangea_response)
199
139
 
200
- return self._check_response(pangea_response_obj)
140
+ return self._check_response(pangea_response)
201
141
 
202
- @overload
203
- async def get(
204
- self,
205
- path: str,
206
- result_class: Type[TResult],
207
- check_response: bool = True,
208
- *,
209
- params: (
210
- Mapping[str | bytes | int | float, str | bytes | int | float | Iterable[str | bytes | int | float] | None]
211
- | None
212
- ) = None,
213
- pangea_response: Literal[True] = True,
214
- ) -> PangeaResponse[TResult]:
215
- """
216
- Makes the GET call to a Pangea Service endpoint.
142
+ async def get(self, path: str, result_class: Type[TResult], check_response: bool = True) -> PangeaResponse[TResult]:
143
+ """Makes the GET call to a Pangea Service endpoint.
217
144
 
218
145
  Args:
219
- path: Additional URL path
220
- params: Dictionary of querystring data to attach to the request
146
+ endpoint(str): The Pangea Service API endpoint.
147
+ path(str): Additional URL path
221
148
 
222
149
  Returns:
223
150
  PangeaResponse which contains the response in its entirety and
224
151
  various properties to retrieve individual fields
225
152
  """
226
153
 
227
- @overload
228
- async def get(
229
- self,
230
- path: str,
231
- result_class: Type[TResult],
232
- check_response: bool = True,
233
- *,
234
- params: (
235
- Mapping[str | bytes | int | float, str | bytes | int | float | Iterable[str | bytes | int | float] | None]
236
- | None
237
- ) = None,
238
- pangea_response: Literal[False] = False,
239
- ) -> TResult:
240
- """
241
- Makes the GET call to a Pangea Service endpoint.
242
-
243
- Args:
244
- path: Additional URL path
245
- params: Dictionary of querystring data to attach to the request
246
- """
247
-
248
- async def get(
249
- self,
250
- path: str,
251
- result_class: Type[TResult],
252
- check_response: bool = True,
253
- *,
254
- params: (
255
- Mapping[str | bytes | int | float, str | bytes | int | float | Iterable[str | bytes | int | float] | None]
256
- | None
257
- ) = None,
258
- pangea_response: bool = True,
259
- ) -> PangeaResponse[TResult] | TResult:
260
- """
261
- Makes the GET call to a Pangea Service endpoint.
262
-
263
- Args:
264
- path: Additional URL path
265
- params: Dictionary of querystring data to attach to the request
266
- pangea_response: Whether or not the response body follows Pangea's
267
- standard response schema
268
- """
269
-
270
154
  url = self._url(path)
271
155
  self.logger.debug(json.dumps({"service": self.service, "action": "get", "url": url}))
272
156
 
273
- async with self.session.get(url, params=params, headers=self._headers()) as requests_response:
157
+ async with self.session.get(url, headers=self._headers()) as requests_response:
274
158
  await self._check_http_errors(requests_response)
275
-
276
- if not pangea_response:
277
- type_adapter = TypeAdapter(result_class)
278
- return type_adapter.validate_python(await requests_response.json())
279
-
280
- pangea_response_obj = PangeaResponse(
159
+ pangea_response = PangeaResponse(
281
160
  requests_response, result_class=result_class, json=await requests_response.json()
282
161
  )
283
162
 
284
163
  self.logger.debug(
285
164
  json.dumps(
286
- {"service": self.service, "action": "get", "url": url, "response": pangea_response_obj.json},
165
+ {"service": self.service, "action": "get", "url": url, "response": pangea_response.json},
287
166
  default=default_encoder,
288
167
  )
289
168
  )
290
169
 
291
170
  if check_response is False:
292
- return pangea_response_obj
171
+ return pangea_response
293
172
 
294
- return self._check_response(pangea_response_obj)
173
+ return self._check_response(pangea_response)
295
174
 
296
175
  async def _check_http_errors(self, resp: aiohttp.ClientResponse):
297
176
  if resp.status == 503:
@@ -425,14 +304,6 @@ class PangeaRequestAsync(PangeaRequestBase):
425
304
  attached_files = await self._get_attached_files(multipart_reader)
426
305
  return MultipartResponse(pangea_json, attached_files) # type: ignore[arg-type]
427
306
 
428
- async def _http_delete(
429
- self,
430
- url: str,
431
- *,
432
- headers: Mapping[str, str | bytes | None] = {},
433
- ) -> aiohttp.ClientResponse:
434
- return await self.session.delete(url, headers=headers)
435
-
436
307
  async def _http_post(
437
308
  self,
438
309
  url: str,
@@ -595,13 +466,46 @@ class PangeaRequestAsync(PangeaRequestBase):
595
466
 
596
467
  @override
597
468
  def _init_session(self) -> aiohttp.ClientSession:
598
- # retry_config = Retry(
599
- # total=self.config.request_retries,
600
- # backoff_factor=self.config.request_backoff,
601
- # status_forcelist=[500, 502, 503, 504],
602
- # )
603
- # adapter = HTTPAdapter(max_retries=retry_config)
604
- # TODO: Add retry config
605
-
606
- session = aiohttp.ClientSession()
607
- return session
469
+ return aiohttp.ClientSession(middlewares=[self._retry_middleware])
470
+
471
+ def _calculate_retry_timeout(self, remaining_retries: int) -> float:
472
+ max_retries = self.config.request_retries
473
+ nb_retries = min(max_retries - remaining_retries, 1000)
474
+ sleep_seconds = min(self.config.request_backoff * pow(2.0, nb_retries), MAX_RETRY_DELAY)
475
+ jitter = 1 - 0.25 * random()
476
+ timeout = sleep_seconds * jitter
477
+ return max(timeout, 0)
478
+
479
+ async def _retry_middleware(
480
+ self, request: aiohttp.ClientRequest, handler: aiohttp.ClientHandlerType
481
+ ) -> aiohttp.ClientResponse:
482
+ max_retries = self.config.request_retries
483
+ request_ids = set[str]()
484
+ retries_taken = 0
485
+ for retries_taken in range(max_retries + 1):
486
+ remaining_retries = max_retries - retries_taken
487
+
488
+ if len(request_ids) > 0:
489
+ request.headers["X-Pangea-Retried-Request-Ids"] = ",".join(request_ids)
490
+
491
+ response = await handler(request)
492
+
493
+ request_id = response.headers.get("x-request-id")
494
+ if request_id:
495
+ request_ids.add(request_id)
496
+
497
+ if not response.ok and remaining_retries > 0 and self._should_retry(response):
498
+ await self._sleep_for_retry(retries_taken=retries_taken, max_retries=max_retries)
499
+ continue
500
+
501
+ break
502
+
503
+ return response
504
+
505
+ def _should_retry(self, response: aiohttp.ClientResponse) -> bool:
506
+ return response.status in RETRYABLE_HTTP_CODES
507
+
508
+ async def _sleep_for_retry(self, *, retries_taken: int, max_retries: int) -> None:
509
+ remaining_retries = max_retries - retries_taken
510
+ timeout = self._calculate_retry_timeout(remaining_retries)
511
+ await asyncio.sleep(timeout)
@@ -1,5 +1,3 @@
1
- # ruff: noqa: F401
2
-
3
1
  from .ai_guard import AIGuardAsync
4
2
  from .audit import AuditAsync
5
3
  from .authn import AuthNAsync
@@ -7,9 +5,27 @@ from .authz import AuthZAsync
7
5
  from .embargo import EmbargoAsync
8
6
  from .file_scan import FileScanAsync
9
7
  from .intel import DomainIntelAsync, FileIntelAsync, IpIntelAsync, UrlIntelAsync, UserIntelAsync
10
- from .management import ManagementAsync
11
8
  from .prompt_guard import PromptGuardAsync
12
9
  from .redact import RedactAsync
13
10
  from .sanitize import SanitizeAsync
14
11
  from .share import ShareAsync
15
12
  from .vault import VaultAsync
13
+
14
+ __all__ = (
15
+ "AIGuardAsync",
16
+ "AuditAsync",
17
+ "AuthNAsync",
18
+ "AuthZAsync",
19
+ "DomainIntelAsync",
20
+ "EmbargoAsync",
21
+ "FileIntelAsync",
22
+ "FileScanAsync",
23
+ "IpIntelAsync",
24
+ "PromptGuardAsync",
25
+ "RedactAsync",
26
+ "SanitizeAsync",
27
+ "ShareAsync",
28
+ "UrlIntelAsync",
29
+ "UserIntelAsync",
30
+ "VaultAsync",
31
+ )
@@ -1,30 +1,25 @@
1
1
  from __future__ import annotations
2
2
 
3
3
  from collections.abc import Mapping, Sequence
4
- from typing import Any, overload
4
+ from typing import overload
5
5
 
6
- from typing_extensions import Literal, TypeVar
6
+ from typing_extensions import Any, Literal
7
7
 
8
8
  from pangea.asyncio.services.base import ServiceBaseAsync
9
9
  from pangea.config import PangeaConfig
10
10
  from pangea.response import PangeaResponse
11
11
  from pangea.services.ai_guard import (
12
- AuditDataActivityConfig,
13
- ConnectionsConfig,
14
12
  ExtraInfo,
15
13
  GuardResult,
16
14
  LogFields,
15
+ McpToolsMessage,
17
16
  Message,
18
17
  Overrides,
19
- RecipeConfig,
20
- ServiceConfig,
21
- ServiceConfigFilter,
22
- ServiceConfigsPage,
23
18
  TextGuardResult,
19
+ get_relevant_content,
20
+ patch_messages,
24
21
  )
25
22
 
26
- _T = TypeVar("_T")
27
-
28
23
 
29
24
  class AIGuardAsync(ServiceBaseAsync):
30
25
  """AI Guard service client.
@@ -100,11 +95,12 @@ class AIGuardAsync(ServiceBaseAsync):
100
95
  async def guard_text(
101
96
  self,
102
97
  *,
103
- messages: Sequence[Message],
98
+ messages: Sequence[Message | McpToolsMessage],
104
99
  recipe: str | None = None,
105
100
  debug: bool | None = None,
106
101
  overrides: Overrides | None = None,
107
102
  log_fields: LogFields | None = None,
103
+ only_relevant_content: bool = False,
108
104
  ) -> PangeaResponse[TextGuardResult]:
109
105
  """
110
106
  Guard LLM input and output text
@@ -127,6 +123,8 @@ class AIGuardAsync(ServiceBaseAsync):
127
123
  recipe: Recipe key of a configuration of data types and settings
128
124
  defined in the Pangea User Console. It specifies the rules that
129
125
  are to be applied to the text, such as defang malicious URLs.
126
+ only_relevant_content: Whether or not to only send relevant content
127
+ to AI Guard.
130
128
 
131
129
  Examples:
132
130
  response = await ai_guard.guard_text(messages=[Message(role="user", content="hello world")])
@@ -136,11 +134,12 @@ class AIGuardAsync(ServiceBaseAsync):
136
134
  self,
137
135
  text: str | None = None,
138
136
  *,
139
- messages: Sequence[Message] | None = None,
137
+ messages: Sequence[Message | McpToolsMessage] | None = None,
140
138
  recipe: str | None = None,
141
139
  debug: bool | None = None,
142
140
  overrides: Overrides | None = None,
143
141
  log_fields: LogFields | None = None,
142
+ only_relevant_content: bool = False,
144
143
  ) -> PangeaResponse[TextGuardResult]:
145
144
  """
146
145
  Guard LLM input and output text
@@ -166,6 +165,8 @@ class AIGuardAsync(ServiceBaseAsync):
166
165
  recipe: Recipe key of a configuration of data types and settings
167
166
  defined in the Pangea User Console. It specifies the rules that
168
167
  are to be applied to the text, such as defang malicious URLs.
168
+ only_relevant_content: Whether or not to only send relevant content
169
+ to AI Guard.
169
170
 
170
171
  Examples:
171
172
  response = await ai_guard.guard_text("text")
@@ -174,7 +175,11 @@ class AIGuardAsync(ServiceBaseAsync):
174
175
  if text is not None and messages is not None:
175
176
  raise ValueError("Exactly one of `text` or `messages` must be given")
176
177
 
177
- return await self.request.post(
178
+ if only_relevant_content and messages is not None:
179
+ original_messages = messages
180
+ messages, original_indices = get_relevant_content(messages)
181
+
182
+ response = await self.request.post(
178
183
  "v1/text/guard",
179
184
  TextGuardResult,
180
185
  data={
@@ -187,6 +192,13 @@ class AIGuardAsync(ServiceBaseAsync):
187
192
  },
188
193
  )
189
194
 
195
+ if only_relevant_content and response.result and response.result.prompt_messages:
196
+ response.result.prompt_messages = patch_messages(
197
+ original_messages, original_indices, response.result.prompt_messages
198
+ ) # type: ignore[assignment]
199
+
200
+ return response
201
+
190
202
  async def guard(
191
203
  self,
192
204
  input: Mapping[str, Any],
@@ -204,8 +216,8 @@ class AIGuardAsync(ServiceBaseAsync):
204
216
  source_ip: str | None = None,
205
217
  source_location: str | None = None,
206
218
  tenant_id: str | None = None,
207
- event_type: Literal["input", "output"] | None = None,
208
- sensor_instance_id: str | None = None,
219
+ event_type: Literal["input", "output", "tool_input", "tool_output", "tool_listing"] | None = None,
220
+ collector_instance_id: str | None = None,
209
221
  extra_info: ExtraInfo | None = None,
210
222
  count_tokens: bool | None = None,
211
223
  ) -> PangeaResponse[GuardResult]:
@@ -215,7 +227,7 @@ class AIGuardAsync(ServiceBaseAsync):
215
227
  Analyze and redact content to avoid manipulation of the model, addition
216
228
  of malicious content, and other undesirable data transfers.
217
229
 
218
- OperationId: ai_guard_post_v1beta_guard
230
+ OperationId: ai_guard_post_v1_guard
219
231
 
220
232
  Args:
221
233
  input: 'messages' (required) contains Prompt content and role array
@@ -234,12 +246,12 @@ class AIGuardAsync(ServiceBaseAsync):
234
246
  source_location: Location of user or app or agent.
235
247
  tenant_id: For gateway-like integrations with multi-tenant support.
236
248
  event_type: (AIDR) Event Type.
237
- sensor_instance_id: (AIDR) sensor instance id.
249
+ collector_instance_id: (AIDR) collector instance id.
238
250
  extra_info: (AIDR) Logging schema.
239
251
  count_tokens: Provide input and output token count.
240
252
  """
241
253
  return await self.request.post(
242
- "v1beta/guard",
254
+ "v1/guard",
243
255
  GuardResult,
244
256
  data={
245
257
  "input": input,
@@ -257,86 +269,8 @@ class AIGuardAsync(ServiceBaseAsync):
257
269
  "source_location": source_location,
258
270
  "tenant_id": tenant_id,
259
271
  "event_type": event_type,
260
- "sensor_instance_id": sensor_instance_id,
272
+ "collector_instance_id": collector_instance_id,
261
273
  "extra_info": extra_info,
262
274
  "count_tokens": count_tokens,
263
275
  },
264
276
  )
265
-
266
- async def get_service_config(self, id: str) -> PangeaResponse[ServiceConfig]:
267
- """
268
- OperationId: ai_guard_post_v1beta_config
269
- """
270
- return await self.request.post("v1beta/config", data={"id": id}, result_class=ServiceConfig)
271
-
272
- async def create_service_config(
273
- self,
274
- name: str,
275
- *,
276
- id: str | None = None,
277
- audit_data_activity: AuditDataActivityConfig | None = None,
278
- connections: ConnectionsConfig | None = None,
279
- recipes: Mapping[str, RecipeConfig] | None = None,
280
- ) -> PangeaResponse[ServiceConfig]:
281
- """
282
- OperationId: ai_guard_post_v1beta_config_create
283
- """
284
- return await self.request.post(
285
- "v1beta/config/create",
286
- data={
287
- "name": name,
288
- "id": id,
289
- "audit_data_activity": audit_data_activity,
290
- "connections": connections,
291
- "recipes": recipes,
292
- },
293
- result_class=ServiceConfig,
294
- )
295
-
296
- async def update_service_config(
297
- self,
298
- id: str,
299
- name: str,
300
- *,
301
- audit_data_activity: AuditDataActivityConfig | None = None,
302
- connections: ConnectionsConfig | None = None,
303
- recipes: Mapping[str, RecipeConfig] | None = None,
304
- ) -> PangeaResponse[ServiceConfig]:
305
- """
306
- OperationId: ai_guard_post_v1beta_config_update
307
- """
308
- return await self.request.post(
309
- "v1beta/config/update",
310
- data={
311
- "id": id,
312
- "name": name,
313
- "audit_data_activity": audit_data_activity,
314
- "connections": connections,
315
- "recipes": recipes,
316
- },
317
- result_class=ServiceConfig,
318
- )
319
-
320
- async def delete_service_config(self, id: str) -> PangeaResponse[ServiceConfig]:
321
- """
322
- OperationId: ai_guard_post_v1beta_config_delete
323
- """
324
- return await self.request.post("v1beta/config/delete", data={"id": id}, result_class=ServiceConfig)
325
-
326
- async def list_service_configs(
327
- self,
328
- *,
329
- filter: ServiceConfigFilter | None = None,
330
- last: str | None = None,
331
- order: Literal["asc", "desc"] | None = None,
332
- order_by: Literal["id", "created_at", "updated_at"] | None = None,
333
- size: int | None = None,
334
- ) -> PangeaResponse[ServiceConfigsPage]:
335
- """
336
- OperationId: ai_guard_post_v1beta_config_list
337
- """
338
- return await self.request.post(
339
- "v1beta/config/list",
340
- data={"filter": filter, "last": last, "order": order, "order_by": order_by, "size": size},
341
- result_class=ServiceConfigsPage,
342
- )