pangea-sdk 6.6.0__tar.gz → 6.7.0__tar.gz

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.
Files changed (62) hide show
  1. {pangea_sdk-6.6.0 → pangea_sdk-6.7.0}/PKG-INFO +3 -3
  2. {pangea_sdk-6.6.0 → pangea_sdk-6.7.0}/pangea/__init__.py +1 -1
  3. {pangea_sdk-6.6.0 → pangea_sdk-6.7.0}/pangea/asyncio/services/ai_guard.py +81 -1
  4. {pangea_sdk-6.6.0 → pangea_sdk-6.7.0}/pangea/asyncio/services/prompt_guard.py +2 -1
  5. {pangea_sdk-6.6.0 → pangea_sdk-6.7.0}/pangea/services/ai_guard.py +210 -17
  6. {pangea_sdk-6.6.0 → pangea_sdk-6.7.0}/pangea/services/prompt_guard.py +9 -7
  7. {pangea_sdk-6.6.0 → pangea_sdk-6.7.0}/pyproject.toml +7 -7
  8. {pangea_sdk-6.6.0 → pangea_sdk-6.7.0}/README.md +0 -0
  9. {pangea_sdk-6.6.0 → pangea_sdk-6.7.0}/pangea/_constants.py +0 -0
  10. {pangea_sdk-6.6.0 → pangea_sdk-6.7.0}/pangea/_typing.py +0 -0
  11. {pangea_sdk-6.6.0 → pangea_sdk-6.7.0}/pangea/asyncio/__init__.py +0 -0
  12. {pangea_sdk-6.6.0 → pangea_sdk-6.7.0}/pangea/asyncio/file_uploader.py +0 -0
  13. {pangea_sdk-6.6.0 → pangea_sdk-6.7.0}/pangea/asyncio/request.py +0 -0
  14. {pangea_sdk-6.6.0 → pangea_sdk-6.7.0}/pangea/asyncio/services/__init__.py +0 -0
  15. {pangea_sdk-6.6.0 → pangea_sdk-6.7.0}/pangea/asyncio/services/audit.py +0 -0
  16. {pangea_sdk-6.6.0 → pangea_sdk-6.7.0}/pangea/asyncio/services/authn.py +0 -0
  17. {pangea_sdk-6.6.0 → pangea_sdk-6.7.0}/pangea/asyncio/services/authz.py +0 -0
  18. {pangea_sdk-6.6.0 → pangea_sdk-6.7.0}/pangea/asyncio/services/base.py +0 -0
  19. {pangea_sdk-6.6.0 → pangea_sdk-6.7.0}/pangea/asyncio/services/embargo.py +0 -0
  20. {pangea_sdk-6.6.0 → pangea_sdk-6.7.0}/pangea/asyncio/services/file_scan.py +0 -0
  21. {pangea_sdk-6.6.0 → pangea_sdk-6.7.0}/pangea/asyncio/services/intel.py +0 -0
  22. {pangea_sdk-6.6.0 → pangea_sdk-6.7.0}/pangea/asyncio/services/redact.py +0 -0
  23. {pangea_sdk-6.6.0 → pangea_sdk-6.7.0}/pangea/asyncio/services/sanitize.py +0 -0
  24. {pangea_sdk-6.6.0 → pangea_sdk-6.7.0}/pangea/asyncio/services/share.py +0 -0
  25. {pangea_sdk-6.6.0 → pangea_sdk-6.7.0}/pangea/asyncio/services/vault.py +0 -0
  26. {pangea_sdk-6.6.0 → pangea_sdk-6.7.0}/pangea/audit_logger.py +0 -0
  27. {pangea_sdk-6.6.0 → pangea_sdk-6.7.0}/pangea/config.py +0 -0
  28. {pangea_sdk-6.6.0 → pangea_sdk-6.7.0}/pangea/crypto/rsa.py +0 -0
  29. {pangea_sdk-6.6.0 → pangea_sdk-6.7.0}/pangea/deep_verify.py +0 -0
  30. {pangea_sdk-6.6.0 → pangea_sdk-6.7.0}/pangea/deprecated.py +0 -0
  31. {pangea_sdk-6.6.0 → pangea_sdk-6.7.0}/pangea/dump_audit.py +0 -0
  32. {pangea_sdk-6.6.0 → pangea_sdk-6.7.0}/pangea/exceptions.py +0 -0
  33. {pangea_sdk-6.6.0 → pangea_sdk-6.7.0}/pangea/file_uploader.py +0 -0
  34. {pangea_sdk-6.6.0 → pangea_sdk-6.7.0}/pangea/py.typed +0 -0
  35. {pangea_sdk-6.6.0 → pangea_sdk-6.7.0}/pangea/request.py +0 -0
  36. {pangea_sdk-6.6.0 → pangea_sdk-6.7.0}/pangea/response.py +0 -0
  37. {pangea_sdk-6.6.0 → pangea_sdk-6.7.0}/pangea/services/__init__.py +0 -0
  38. {pangea_sdk-6.6.0 → pangea_sdk-6.7.0}/pangea/services/audit/audit.py +0 -0
  39. {pangea_sdk-6.6.0 → pangea_sdk-6.7.0}/pangea/services/audit/exceptions.py +0 -0
  40. {pangea_sdk-6.6.0 → pangea_sdk-6.7.0}/pangea/services/audit/models.py +0 -0
  41. {pangea_sdk-6.6.0 → pangea_sdk-6.7.0}/pangea/services/audit/signing.py +0 -0
  42. {pangea_sdk-6.6.0 → pangea_sdk-6.7.0}/pangea/services/audit/util.py +0 -0
  43. {pangea_sdk-6.6.0 → pangea_sdk-6.7.0}/pangea/services/authn/authn.py +0 -0
  44. {pangea_sdk-6.6.0 → pangea_sdk-6.7.0}/pangea/services/authn/models.py +0 -0
  45. {pangea_sdk-6.6.0 → pangea_sdk-6.7.0}/pangea/services/authz.py +0 -0
  46. {pangea_sdk-6.6.0 → pangea_sdk-6.7.0}/pangea/services/base.py +0 -0
  47. {pangea_sdk-6.6.0 → pangea_sdk-6.7.0}/pangea/services/embargo.py +0 -0
  48. {pangea_sdk-6.6.0 → pangea_sdk-6.7.0}/pangea/services/file_scan.py +0 -0
  49. {pangea_sdk-6.6.0 → pangea_sdk-6.7.0}/pangea/services/intel.py +0 -0
  50. {pangea_sdk-6.6.0 → pangea_sdk-6.7.0}/pangea/services/redact.py +0 -0
  51. {pangea_sdk-6.6.0 → pangea_sdk-6.7.0}/pangea/services/sanitize.py +0 -0
  52. {pangea_sdk-6.6.0 → pangea_sdk-6.7.0}/pangea/services/share/file_format.py +0 -0
  53. {pangea_sdk-6.6.0 → pangea_sdk-6.7.0}/pangea/services/share/share.py +0 -0
  54. {pangea_sdk-6.6.0 → pangea_sdk-6.7.0}/pangea/services/vault/models/asymmetric.py +0 -0
  55. {pangea_sdk-6.6.0 → pangea_sdk-6.7.0}/pangea/services/vault/models/common.py +0 -0
  56. {pangea_sdk-6.6.0 → pangea_sdk-6.7.0}/pangea/services/vault/models/keys.py +0 -0
  57. {pangea_sdk-6.6.0 → pangea_sdk-6.7.0}/pangea/services/vault/models/secret.py +0 -0
  58. {pangea_sdk-6.6.0 → pangea_sdk-6.7.0}/pangea/services/vault/models/symmetric.py +0 -0
  59. {pangea_sdk-6.6.0 → pangea_sdk-6.7.0}/pangea/services/vault/vault.py +0 -0
  60. {pangea_sdk-6.6.0 → pangea_sdk-6.7.0}/pangea/tools.py +0 -0
  61. {pangea_sdk-6.6.0 → pangea_sdk-6.7.0}/pangea/utils.py +0 -0
  62. {pangea_sdk-6.6.0 → pangea_sdk-6.7.0}/pangea/verify_audit.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: pangea-sdk
3
- Version: 6.6.0
3
+ Version: 6.7.0
4
4
  Summary: Pangea API SDK
5
5
  Keywords: Pangea,SDK,Audit
6
6
  Author: Glenn Gallien
@@ -9,10 +9,10 @@ License-Expression: MIT
9
9
  Classifier: Topic :: Software Development
10
10
  Classifier: Topic :: Software Development :: Libraries
11
11
  Requires-Dist: aiohttp>=3.12.15,<4.0.0
12
- Requires-Dist: cryptography>=45.0.6,<46.0.0
12
+ Requires-Dist: cryptography>=45.0.7,<46.0.0
13
13
  Requires-Dist: deprecated>=1.2.18,<2.0.0
14
14
  Requires-Dist: google-crc32c>=1.7.1,<2.0.0
15
- Requires-Dist: pydantic>=2.11.7,<3.0.0
15
+ Requires-Dist: pydantic>=2.11.9,<3.0.0
16
16
  Requires-Dist: python-dateutil>=2.9.0.post0,<3.0.0
17
17
  Requires-Dist: requests>=2.32.5,<3.0.0
18
18
  Requires-Dist: requests-toolbelt>=1.0.0,<2.0.0
@@ -1,4 +1,4 @@
1
- __version__ = "6.6.0"
1
+ __version__ = "6.7.0"
2
2
 
3
3
  from pangea.config import PangeaConfig
4
4
  from pangea.file_uploader import FileUploader
@@ -1,12 +1,16 @@
1
1
  from __future__ import annotations
2
2
 
3
- from collections.abc import Sequence
3
+ from collections.abc import Mapping, Sequence
4
4
  from typing import overload
5
5
 
6
+ from typing_extensions import Any, Literal
7
+
6
8
  from pangea.asyncio.services.base import ServiceBaseAsync
7
9
  from pangea.config import PangeaConfig
8
10
  from pangea.response import PangeaResponse
9
11
  from pangea.services.ai_guard import (
12
+ ExtraInfo,
13
+ GuardResult,
10
14
  LogFields,
11
15
  McpToolsMessage,
12
16
  Message,
@@ -194,3 +198,79 @@ class AIGuardAsync(ServiceBaseAsync):
194
198
  ) # type: ignore[assignment]
195
199
 
196
200
  return response
201
+
202
+ async def guard(
203
+ self,
204
+ input: Mapping[str, Any],
205
+ *,
206
+ recipe: str | None = None,
207
+ debug: bool | None = None,
208
+ overrides: Overrides | None = None,
209
+ app_id: str | None = None,
210
+ actor_id: str | None = None,
211
+ llm_provider: str | None = None,
212
+ model: str | None = None,
213
+ model_version: str | None = None,
214
+ request_token_count: int | None = None,
215
+ response_token_count: int | None = None,
216
+ source_ip: str | None = None,
217
+ source_location: str | None = None,
218
+ tenant_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,
221
+ extra_info: ExtraInfo | None = None,
222
+ count_tokens: bool | None = None,
223
+ ) -> PangeaResponse[GuardResult]:
224
+ """
225
+ Guard LLM input and output
226
+
227
+ Analyze and redact content to avoid manipulation of the model, addition
228
+ of malicious content, and other undesirable data transfers.
229
+
230
+ OperationId: ai_guard_post_v1_guard
231
+
232
+ Args:
233
+ input: 'messages' (required) contains Prompt content and role array
234
+ in JSON format. The `content` is the multimodal text or image
235
+ input that will be analyzed. Additional properties such as
236
+ 'tools' may be provided for analysis.
237
+ recipe: Recipe key of a configuration of data types and settings defined in the Pangea User Console. It specifies the rules that are to be applied to the text, such as defang malicious URLs.
238
+ debug: Setting this value to true will provide a detailed analysis of the text data
239
+ app_name: Name of source application.
240
+ llm_provider: Underlying LLM. Example: 'OpenAI'.
241
+ model: Model used to perform the event. Example: 'gpt'.
242
+ model_version: Model version used to perform the event. Example: '3.5'.
243
+ request_token_count: Number of tokens in the request.
244
+ response_token_count: Number of tokens in the response.
245
+ source_ip: IP address of user or app or agent.
246
+ source_location: Location of user or app or agent.
247
+ tenant_id: For gateway-like integrations with multi-tenant support.
248
+ event_type: (AIDR) Event Type.
249
+ collector_instance_id: (AIDR) collector instance id.
250
+ extra_info: (AIDR) Logging schema.
251
+ count_tokens: Provide input and output token count.
252
+ """
253
+ return await self.request.post(
254
+ "v1/guard",
255
+ GuardResult,
256
+ data={
257
+ "input": input,
258
+ "recipe": recipe,
259
+ "debug": debug,
260
+ "overrides": overrides,
261
+ "app_id": app_id,
262
+ "actor_id": actor_id,
263
+ "llm_provider": llm_provider,
264
+ "model": model,
265
+ "model_version": model_version,
266
+ "request_token_count": request_token_count,
267
+ "response_token_count": response_token_count,
268
+ "source_ip": source_ip,
269
+ "source_location": source_location,
270
+ "tenant_id": tenant_id,
271
+ "event_type": event_type,
272
+ "collector_instance_id": collector_instance_id,
273
+ "extra_info": extra_info,
274
+ "count_tokens": count_tokens,
275
+ },
276
+ )
@@ -2,6 +2,7 @@ from __future__ import annotations
2
2
 
3
3
  from typing import TYPE_CHECKING
4
4
 
5
+ from pangea._typing import SequenceNotStr
5
6
  from pangea.asyncio.services.base import ServiceBaseAsync
6
7
  from pangea.config import PangeaConfig
7
8
  from pangea.services.prompt_guard import GuardResult, Message
@@ -58,7 +59,7 @@ class PromptGuardAsync(ServiceBaseAsync):
58
59
  self,
59
60
  messages: Iterable[Message],
60
61
  *,
61
- analyzers: Iterable[str] | None = None,
62
+ analyzers: SequenceNotStr[str] | None = None,
62
63
  classify: bool | None = None,
63
64
  ) -> PangeaResponse[GuardResult]:
64
65
  """
@@ -1,7 +1,9 @@
1
1
  from __future__ import annotations
2
2
 
3
- from collections.abc import Sequence
4
- from typing import Any, Generic, Literal, Optional, overload
3
+ from collections.abc import Mapping, Sequence
4
+ from typing import Annotated, Any, Generic, Literal, Optional, overload
5
+
6
+ from pydantic import BaseModel, ConfigDict, Field, RootModel
5
7
 
6
8
  from pangea._typing import T
7
9
  from pangea.config import PangeaConfig
@@ -280,26 +282,26 @@ class CodeDetectionResult(APIResponseModel):
280
282
  """The action taken by this Detector"""
281
283
 
282
284
 
283
- class TextGuardDetector(APIResponseModel, Generic[T]):
285
+ class GuardDetector(APIResponseModel, Generic[T]):
284
286
  detected: Optional[bool] = None
285
287
  data: Optional[T] = None
286
288
 
287
289
 
288
290
  class TextGuardDetectors(APIResponseModel):
289
- code_detection: Optional[TextGuardDetector[CodeDetectionResult]] = None
290
- competitors: Optional[TextGuardDetector[object]] = None
291
- custom_entity: Optional[TextGuardDetector[object]] = None
292
- gibberish: Optional[TextGuardDetector[object]] = None
293
- hardening: Optional[TextGuardDetector[object]] = None
294
- language_detection: Optional[TextGuardDetector[LanguageDetectionResult]] = None
295
- malicious_entity: Optional[TextGuardDetector[MaliciousEntityResult]] = None
296
- pii_entity: Optional[TextGuardDetector[PiiEntityResult]] = None
297
- profanity_and_toxicity: Optional[TextGuardDetector[object]] = None
298
- prompt_injection: Optional[TextGuardDetector[PromptInjectionResult]] = None
299
- secrets_detection: Optional[TextGuardDetector[SecretsEntityResult]] = None
300
- selfharm: Optional[TextGuardDetector[object]] = None
301
- sentiment: Optional[TextGuardDetector[object]] = None
302
- topic: Optional[TextGuardDetector[TopicDetectionResult]] = None
291
+ code_detection: Optional[GuardDetector[CodeDetectionResult]] = None
292
+ competitors: Optional[GuardDetector[object]] = None
293
+ custom_entity: Optional[GuardDetector[object]] = None
294
+ gibberish: Optional[GuardDetector[object]] = None
295
+ hardening: Optional[GuardDetector[object]] = None
296
+ language_detection: Optional[GuardDetector[LanguageDetectionResult]] = None
297
+ malicious_entity: Optional[GuardDetector[MaliciousEntityResult]] = None
298
+ pii_entity: Optional[GuardDetector[PiiEntityResult]] = None
299
+ profanity_and_toxicity: Optional[GuardDetector[object]] = None
300
+ prompt_injection: Optional[GuardDetector[PromptInjectionResult]] = None
301
+ secrets_detection: Optional[GuardDetector[SecretsEntityResult]] = None
302
+ selfharm: Optional[GuardDetector[object]] = None
303
+ sentiment: Optional[GuardDetector[object]] = None
304
+ topic: Optional[GuardDetector[TopicDetectionResult]] = None
303
305
 
304
306
 
305
307
  class PromptMessage(APIResponseModel):
@@ -336,6 +338,121 @@ class TextGuardResult(PangeaResponseResult):
336
338
  """Whether or not the original input was transformed."""
337
339
 
338
340
 
341
+ class Tool(RootModel[str]):
342
+ root: Annotated[str, Field(min_length=1)]
343
+ """Tool name"""
344
+
345
+
346
+ class McpTool(APIRequestModel):
347
+ server_name: Annotated[str, Field(min_length=1)]
348
+ """MCP server name"""
349
+
350
+ tools: Annotated[list[Tool], Field(min_length=1)]
351
+
352
+
353
+ class ExtraInfo(BaseModel):
354
+ """(AIDR) Logging schema."""
355
+
356
+ # Additional properties are allowed here.
357
+ model_config = ConfigDict(extra="allow")
358
+
359
+ app_name: Optional[str] = None
360
+ """Name of source application/agent."""
361
+
362
+ app_group: Optional[str] = None
363
+ """The group of source application/agent."""
364
+
365
+ app_version: Optional[str] = None
366
+ """Version of the source application/agent."""
367
+
368
+ actor_name: Optional[str] = None
369
+ """Name of subject actor/service account."""
370
+
371
+ actor_group: Optional[str] = None
372
+ """The group of subject actor."""
373
+
374
+ source_region: Optional[str] = None
375
+ """Geographic region or data center."""
376
+
377
+ sub_tenant: Optional[str] = None
378
+ """Sub tenant of the user or organization"""
379
+ mcp_tools: Optional[Sequence[McpTool]] = None
380
+
381
+ """Each item groups tools for a given MCP server."""
382
+
383
+
384
+ class AccessRuleResult(APIResponseModel):
385
+ """
386
+ Details about the evaluation of a single rule, including whether it matched,
387
+ the action to take, the rule name, and optional debugging information.
388
+ """
389
+
390
+ matched: bool
391
+ """Whether this rule's logic evaluated to true for the input."""
392
+
393
+ action: str
394
+ """
395
+ The action resulting from the rule evaluation. One of 'allowed', 'blocked',
396
+ or 'reported'.
397
+ """
398
+
399
+ name: str
400
+ """A human-readable name for the rule."""
401
+
402
+ logic: Optional[dict[str, Any]] = None
403
+ """The JSON logic expression evaluated for this rule."""
404
+
405
+ attributes: Optional[dict[str, Any]] = None
406
+ """The input attribute values that were available during rule evaluation."""
407
+
408
+
409
+ class GuardDetectors(APIResponseModel):
410
+ """Result of the recipe analyzing and input prompt."""
411
+
412
+ code: Optional[GuardDetector[CodeDetectionResult]] = None
413
+ competitors: Optional[GuardDetector[object]] = None
414
+ confidential_and_pii_entity: Optional[GuardDetector[PiiEntityResult]] = None
415
+ custom_entity: Optional[GuardDetector[object]] = None
416
+ language: Optional[GuardDetector[LanguageDetectionResult]] = None
417
+ malicious_entity: Optional[GuardDetector[MaliciousEntityResult]] = None
418
+ malicious_prompt: Optional[GuardDetector[PromptInjectionResult]] = None
419
+ prompt_hardening: Optional[GuardDetector[object]] = None
420
+ secret_and_key_entity: Optional[GuardDetector[SecretsEntityResult]] = None
421
+ topic: Optional[GuardDetector[TopicDetectionResult]] = None
422
+
423
+
424
+ class GuardResult(PangeaResponseResult):
425
+ output: Optional[dict[str, Any]] = None
426
+ """Updated structured prompt."""
427
+
428
+ blocked: Optional[bool] = None
429
+ """Whether or not the prompt triggered a block detection."""
430
+
431
+ transformed: Optional[bool] = None
432
+ """Whether or not the original input was transformed."""
433
+
434
+ recipe: Optional[str] = None
435
+ """The Recipe that was used."""
436
+
437
+ detectors: GuardDetectors
438
+ """Result of the recipe analyzing and input prompt."""
439
+
440
+ access_rules: Optional[dict[str, AccessRuleResult]] = None
441
+ """Result of the recipe evaluating configured rules"""
442
+
443
+ fpe_context: Optional[str] = None
444
+ """
445
+ If an FPE redaction method returned results, this will be the context passed
446
+ to unredact.
447
+ """
448
+
449
+ input_token_count: Optional[float] = None
450
+ """Number of tokens counted in the input"""
451
+
452
+ output_token_count: Optional[float] = None
453
+ """Number of tokens counted in the output"""
454
+
455
+
339
456
  class AIGuard(ServiceBase):
340
457
  """AI Guard service client.
341
458
 
@@ -514,6 +631,82 @@ class AIGuard(ServiceBase):
514
631
 
515
632
  return response
516
633
 
634
+ def guard(
635
+ self,
636
+ input: Mapping[str, Any],
637
+ *,
638
+ recipe: str | None = None,
639
+ debug: bool | None = None,
640
+ overrides: Overrides | None = None,
641
+ app_id: str | None = None,
642
+ actor_id: str | None = None,
643
+ llm_provider: str | None = None,
644
+ model: str | None = None,
645
+ model_version: str | None = None,
646
+ request_token_count: int | None = None,
647
+ response_token_count: int | None = None,
648
+ source_ip: str | None = None,
649
+ source_location: str | None = None,
650
+ tenant_id: str | None = None,
651
+ event_type: Literal["input", "output", "tool_input", "tool_output", "tool_listing"] | None = None,
652
+ collector_instance_id: str | None = None,
653
+ extra_info: ExtraInfo | None = None,
654
+ count_tokens: bool | None = None,
655
+ ) -> PangeaResponse[GuardResult]:
656
+ """
657
+ Guard LLM input and output
658
+
659
+ Analyze and redact content to avoid manipulation of the model, addition
660
+ of malicious content, and other undesirable data transfers.
661
+
662
+ OperationId: ai_guard_post_v1_guard
663
+
664
+ Args:
665
+ input: 'messages' (required) contains Prompt content and role array
666
+ in JSON format. The `content` is the multimodal text or image
667
+ input that will be analyzed. Additional properties such as
668
+ 'tools' may be provided for analysis.
669
+ recipe: Recipe key of a configuration of data types and settings defined in the Pangea User Console. It specifies the rules that are to be applied to the text, such as defang malicious URLs.
670
+ debug: Setting this value to true will provide a detailed analysis of the text data
671
+ app_name: Name of source application.
672
+ llm_provider: Underlying LLM. Example: 'OpenAI'.
673
+ model: Model used to perform the event. Example: 'gpt'.
674
+ model_version: Model version used to perform the event. Example: '3.5'.
675
+ request_token_count: Number of tokens in the request.
676
+ response_token_count: Number of tokens in the response.
677
+ source_ip: IP address of user or app or agent.
678
+ source_location: Location of user or app or agent.
679
+ tenant_id: For gateway-like integrations with multi-tenant support.
680
+ event_type: (AIDR) Event Type.
681
+ collector_instance_id: (AIDR) collector instance id.
682
+ extra_info: (AIDR) Logging schema.
683
+ count_tokens: Provide input and output token count.
684
+ """
685
+ return self.request.post(
686
+ "v1/guard",
687
+ GuardResult,
688
+ data={
689
+ "input": input,
690
+ "recipe": recipe,
691
+ "debug": debug,
692
+ "overrides": overrides,
693
+ "app_id": app_id,
694
+ "actor_id": actor_id,
695
+ "llm_provider": llm_provider,
696
+ "model": model,
697
+ "model_version": model_version,
698
+ "request_token_count": request_token_count,
699
+ "response_token_count": response_token_count,
700
+ "source_ip": source_ip,
701
+ "source_location": source_location,
702
+ "tenant_id": tenant_id,
703
+ "event_type": event_type,
704
+ "collector_instance_id": collector_instance_id,
705
+ "extra_info": extra_info,
706
+ "count_tokens": count_tokens,
707
+ },
708
+ )
709
+
517
710
 
518
711
  def get_relevant_content(
519
712
  messages: Sequence[Message | McpToolsMessage],
@@ -1,7 +1,10 @@
1
1
  from __future__ import annotations
2
2
 
3
- from typing import TYPE_CHECKING, Literal, Optional
3
+ from typing import TYPE_CHECKING, Annotated, Literal, Optional
4
4
 
5
+ from pydantic import Field
6
+
7
+ from pangea._typing import SequenceNotStr
5
8
  from pangea.config import PangeaConfig
6
9
  from pangea.response import APIRequestModel, APIResponseModel, PangeaResponse, PangeaResponseResult
7
10
  from pangea.services.base import ServiceBase
@@ -33,19 +36,18 @@ class GuardResult(PangeaResponseResult):
33
36
  detected: bool
34
37
  """Boolean response for if the prompt was considered malicious or not"""
35
38
 
39
+ analyzer: Optional[str] = None
40
+
36
41
  type: Optional[Literal["direct", "indirect", ""]] = None
37
42
  """Type of analysis, either direct or indirect"""
38
43
 
39
- analyzer: Optional[str] = None
40
- """Prompt Analyzers for identifying and rejecting properties of prompts"""
41
-
42
- confidence: float
44
+ confidence: Annotated[Optional[float], Field(ge=0.0, le=1.0)] = None
43
45
  """Percent of confidence in the detection result, ranging from 0 to 1"""
44
46
 
45
47
  info: Optional[str] = None
46
48
  """Extra information about the detection result"""
47
49
 
48
- classifications: list[Classification]
50
+ classifications: Optional[list[Classification]] = None
49
51
  """List of classification results with labels and confidence scores"""
50
52
 
51
53
 
@@ -92,7 +94,7 @@ class PromptGuard(ServiceBase):
92
94
  self,
93
95
  messages: Iterable[Message],
94
96
  *,
95
- analyzers: Iterable[str] | None = None,
97
+ analyzers: SequenceNotStr[str] | None = None,
96
98
  classify: bool | None = None,
97
99
  ) -> PangeaResponse[GuardResult]:
98
100
  """
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "pangea-sdk"
3
- version = "6.6.0"
3
+ version = "6.7.0"
4
4
  description = "Pangea API SDK"
5
5
  authors = [
6
6
  {name = "Glenn Gallien", email = "glenn.gallien@pangea.cloud"}
@@ -15,10 +15,10 @@ classifiers = [
15
15
  requires-python = ">=3.9.2,<4.0.0"
16
16
  dependencies = [
17
17
  "aiohttp (>=3.12.15,<4.0.0)",
18
- "cryptography (>=45.0.6,<46.0.0)",
18
+ "cryptography (>=45.0.7,<46.0.0)",
19
19
  "deprecated (>=1.2.18,<2.0.0)",
20
20
  "google-crc32c (>=1.7.1,<2.0.0)",
21
- "pydantic (>=2.11.7,<3.0.0)",
21
+ "pydantic (>=2.11.9,<3.0.0)",
22
22
  "python-dateutil (>=2.9.0.post0,<3.0.0)",
23
23
  "requests (>=2.32.5,<3.0.0)",
24
24
  "requests-toolbelt (>=1.0.0,<2.0.0)",
@@ -32,15 +32,15 @@ repository = "https://github.com/pangeacyber/pangea-python"
32
32
  [dependency-groups]
33
33
  dev = [
34
34
  "docstring-parser ==0.17.0",
35
- "pytest-asyncio ==1.1.0",
35
+ "pytest-asyncio ==1.2.0",
36
36
  "pytest_httpserver ==1.1.3",
37
37
  "types-Deprecated ==1.2.15.20250304",
38
38
  "types-python-dateutil ==2.9.0.20250822",
39
- "types-requests ==2.32.4.20250809",
39
+ "types-requests ==2.32.4.20250913",
40
40
  ]
41
41
 
42
42
  [build-system]
43
- requires = ["uv_build==0.8.14"]
43
+ requires = ["uv_build==0.8.17"]
44
44
  build-backend = "uv_build"
45
45
 
46
46
  [tool.mypy]
@@ -54,7 +54,7 @@ warn_unused_ignores = true
54
54
  plugins = ['pydantic.mypy']
55
55
 
56
56
  [tool.pydantic-mypy]
57
- init_forbid_extra = true
57
+ init_forbid_extra = false
58
58
  init_typed = true
59
59
  warn_required_dynamic_aliases = true
60
60
 
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes