trustmodel 3.3.0__tar.gz → 3.3.2__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 (45) hide show
  1. {trustmodel-3.3.0 → trustmodel-3.3.2}/PKG-INFO +1 -1
  2. {trustmodel-3.3.0 → trustmodel-3.3.2}/pyproject.toml +1 -1
  3. {trustmodel-3.3.0 → trustmodel-3.3.2}/src/trustmodel/__init__.py +6 -0
  4. {trustmodel-3.3.0 → trustmodel-3.3.2}/src/trustmodel/endpoints/agentcert.py +83 -5
  5. {trustmodel-3.3.0 → trustmodel-3.3.2}/src/trustmodel/endpoints/agentic.py +13 -0
  6. {trustmodel-3.3.0 → trustmodel-3.3.2}/src/trustmodel/exceptions.py +32 -1
  7. {trustmodel-3.3.0 → trustmodel-3.3.2}/.gitignore +0 -0
  8. {trustmodel-3.3.0 → trustmodel-3.3.2}/LICENSE +0 -0
  9. {trustmodel-3.3.0 → trustmodel-3.3.2}/README.md +0 -0
  10. {trustmodel-3.3.0 → trustmodel-3.3.2}/src/trustmodel/cli.py +0 -0
  11. {trustmodel-3.3.0 → trustmodel-3.3.2}/src/trustmodel/client.py +0 -0
  12. {trustmodel-3.3.0 → trustmodel-3.3.2}/src/trustmodel/compat.py +0 -0
  13. {trustmodel-3.3.0 → trustmodel-3.3.2}/src/trustmodel/endpoints/__init__.py +0 -0
  14. {trustmodel-3.3.0 → trustmodel-3.3.2}/src/trustmodel/endpoints/_runtime_transport.py +0 -0
  15. {trustmodel-3.3.0 → trustmodel-3.3.2}/src/trustmodel/endpoints/batch_jobs.py +0 -0
  16. {trustmodel-3.3.0 → trustmodel-3.3.2}/src/trustmodel/endpoints/config.py +0 -0
  17. {trustmodel-3.3.0 → trustmodel-3.3.2}/src/trustmodel/endpoints/credits.py +0 -0
  18. {trustmodel-3.3.0 → trustmodel-3.3.2}/src/trustmodel/endpoints/evaluations.py +0 -0
  19. {trustmodel-3.3.0 → trustmodel-3.3.2}/src/trustmodel/endpoints/frameworks.py +0 -0
  20. {trustmodel-3.3.0 → trustmodel-3.3.2}/src/trustmodel/endpoints/galileo.py +0 -0
  21. {trustmodel-3.3.0 → trustmodel-3.3.2}/src/trustmodel/endpoints/guardrails.py +0 -0
  22. {trustmodel-3.3.0 → trustmodel-3.3.2}/src/trustmodel/endpoints/mcp_scanner.py +0 -0
  23. {trustmodel-3.3.0 → trustmodel-3.3.2}/src/trustmodel/endpoints/models.py +0 -0
  24. {trustmodel-3.3.0 → trustmodel-3.3.2}/src/trustmodel/models/__init__.py +0 -0
  25. {trustmodel-3.3.0 → trustmodel-3.3.2}/src/trustmodel/models/agentcert.py +0 -0
  26. {trustmodel-3.3.0 → trustmodel-3.3.2}/src/trustmodel/models/agentic.py +0 -0
  27. {trustmodel-3.3.0 → trustmodel-3.3.2}/src/trustmodel/models/batch_job.py +0 -0
  28. {trustmodel-3.3.0 → trustmodel-3.3.2}/src/trustmodel/models/credits.py +0 -0
  29. {trustmodel-3.3.0 → trustmodel-3.3.2}/src/trustmodel/models/evaluation.py +0 -0
  30. {trustmodel-3.3.0 → trustmodel-3.3.2}/src/trustmodel/models/frameworks.py +0 -0
  31. {trustmodel-3.3.0 → trustmodel-3.3.2}/src/trustmodel/models/galileo.py +0 -0
  32. {trustmodel-3.3.0 → trustmodel-3.3.2}/src/trustmodel/models/guardrails.py +0 -0
  33. {trustmodel-3.3.0 → trustmodel-3.3.2}/src/trustmodel/models/mcp_scanner.py +0 -0
  34. {trustmodel-3.3.0 → trustmodel-3.3.2}/src/trustmodel/models/models.py +0 -0
  35. {trustmodel-3.3.0 → trustmodel-3.3.2}/src/trustmodel/models/oauth.py +0 -0
  36. {trustmodel-3.3.0 → trustmodel-3.3.2}/src/trustmodel/oauth/__init__.py +0 -0
  37. {trustmodel-3.3.0 → trustmodel-3.3.2}/src/trustmodel/oauth/auth.py +0 -0
  38. {trustmodel-3.3.0 → trustmodel-3.3.2}/src/trustmodel/oauth/scopes.py +0 -0
  39. {trustmodel-3.3.0 → trustmodel-3.3.2}/src/trustmodel/telemetry/__init__.py +0 -0
  40. {trustmodel-3.3.0 → trustmodel-3.3.2}/src/trustmodel/telemetry/_constants.py +0 -0
  41. {trustmodel-3.3.0 → trustmodel-3.3.2}/src/trustmodel/telemetry/_instrumentors.py +0 -0
  42. {trustmodel-3.3.0 → trustmodel-3.3.2}/src/trustmodel/telemetry/auto_init.py +0 -0
  43. {trustmodel-3.3.0 → trustmodel-3.3.2}/src/trustmodel/utils/__init__.py +0 -0
  44. {trustmodel-3.3.0 → trustmodel-3.3.2}/src/trustmodel/utils/validation.py +0 -0
  45. {trustmodel-3.3.0 → trustmodel-3.3.2}/src/trustmodel/utils/version.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: trustmodel
3
- Version: 3.3.0
3
+ Version: 3.3.2
4
4
  Summary: Official Python SDK for TrustModel AI evaluation platform
5
5
  Project-URL: Homepage, https://trustmodel.ai
6
6
  Author-email: TrustModel <info@predixtions.com>
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
4
4
 
5
5
  [project]
6
6
  name = "trustmodel"
7
- version = "3.3.0"
7
+ version = "3.3.2"
8
8
  authors = [
9
9
  {name = "TrustModel", email = "info@predixtions.com"},
10
10
  ]
@@ -16,10 +16,13 @@ except ImportError:
16
16
 
17
17
  from .client import TrustModelClient
18
18
  from .exceptions import (
19
+ AgentCertInvalidRunTypeError,
20
+ AgentCertRunNotCompletedError,
19
21
  APIError,
20
22
  AuthenticationError,
21
23
  ConnectionValidationError,
22
24
  EdgeUnreachableError,
25
+ EvaluationNotFoundError,
23
26
  InsufficientCreditsError,
24
27
  RateLimitError,
25
28
  TrustModelError,
@@ -60,6 +63,9 @@ __all__ = [
60
63
  "InsufficientCreditsError",
61
64
  "ConnectionValidationError",
62
65
  "EdgeUnreachableError",
66
+ "EvaluationNotFoundError",
67
+ "AgentCertInvalidRunTypeError",
68
+ "AgentCertRunNotCompletedError",
63
69
  "Decision",
64
70
  "OAuthClientCredentials",
65
71
  "PKCEAuthorizationCode",
@@ -18,9 +18,14 @@ Contract: agentcert/docs/api-v0.md. Ticket: TRUS-1228 (EPIC TRUS-1219).
18
18
 
19
19
  from __future__ import annotations
20
20
 
21
- from typing import TYPE_CHECKING, Optional, Tuple
22
-
23
- from ..exceptions import APIError
21
+ from typing import TYPE_CHECKING, Any, Optional, Tuple
22
+
23
+ from ..exceptions import (
24
+ AgentCertInvalidRunTypeError,
25
+ AgentCertRunNotCompletedError,
26
+ APIError,
27
+ EvaluationNotFoundError,
28
+ )
24
29
  from ..models.agentcert import AgentCertificate, AgentCertVerification
25
30
 
26
31
  if TYPE_CHECKING:
@@ -37,6 +42,51 @@ _VERIFY_PATH = "/v1/verify/{agent}/"
37
42
  # a legitimate "not found" answer, surfaced as a result, not an exception.
38
43
  _NOT_FOUND_STATUS = 404
39
44
 
45
+ # TRUS-1643 — mint 400 error codes → typed exception class. Two body
46
+ # shapes exist in the wild:
47
+ # 1. Legacy handler-emitted: ``{"error": "...", "code": "issuance_failed"}``
48
+ # (from ``AgentCertView`` catching ``IssuanceError``).
49
+ # 2. DRF ValidationError-emitted (TRUS-1643): field-level shape —
50
+ # ``{"evaluation_run_id": ["..."], "code": ["invalid_run_type_for_agentcert"]}``.
51
+ # The gateway ``code`` is either a plain string or a single-element list;
52
+ # ``_extract_error_code`` normalises to a plain string so callers get a
53
+ # stable typed exception either way.
54
+ _MINT_ERROR_CODE_TO_EXC = {
55
+ "invalid_run_type_for_agentcert": AgentCertInvalidRunTypeError,
56
+ "run_not_completed_for_agentcert": AgentCertRunNotCompletedError,
57
+ "evaluation_run_not_found": EvaluationNotFoundError,
58
+ }
59
+
60
+
61
+ def _extract_error_code(exc: APIError) -> Optional[str]:
62
+ """Return the machine-parseable ``code`` from a mint 400 body, or None.
63
+
64
+ Handles both the legacy flat ``code`` string and the DRF-serializer
65
+ flattened ``code`` list. Falls back to ``exc.response`` when the
66
+ client-level ``exc.error_code`` didn't preserve the list shape.
67
+
68
+ Edge cases that intentionally return ``None`` (caller must fall
69
+ through to raising the plain ``APIError``):
70
+ * empty string ``""`` — degenerate legacy body
71
+ * ``[""]`` — degenerate DRF body
72
+ * ``[]`` / non-string first element — malformed body
73
+ None of the ``_MINT_ERROR_CODE_TO_EXC`` keys are empty, so a ``""``
74
+ lookup misses the routing table and falls through anyway.
75
+ """
76
+ # ``raw`` is typed ``Any`` because the two source shapes disagree:
77
+ # ``APIError.error_code`` is declared ``Optional[str]`` (legacy handler
78
+ # shape), but the DRF ValidationError body arrives with ``code`` as a
79
+ # single-element list. Both survive here — the isinstance checks below
80
+ # narrow at runtime.
81
+ raw: Any = exc.error_code
82
+ if raw is None and isinstance(exc.response, dict):
83
+ raw = exc.response.get("code")
84
+ if isinstance(raw, str) and raw:
85
+ return raw
86
+ if isinstance(raw, list) and raw and isinstance(raw[0], str):
87
+ return raw[0]
88
+ return None
89
+
40
90
 
41
91
  class AgentCertEndpoint:
42
92
  """Issue, verify, and certify AgentCerts. Mounted as ``client.agentcert``."""
@@ -58,6 +108,12 @@ class AgentCertEndpoint:
58
108
  Calls ``POST /sdk/v1/agentcert/issue/`` (the API-key-authed wrapper).
59
109
  The org is derived from the API key server-side.
60
110
 
111
+ **Eligible run types (TRUS-1643):** the eval run must be an
112
+ ``agent-evaluation-run`` or ``agentic-trace-run`` in ``completed``
113
+ status. Standard model evals, leaderboard runs, data-scan runs, and
114
+ RAG corpus runs are rejected with a stable 400 error code so callers
115
+ can route the user back to picking a compatible run.
116
+
61
117
  Args:
62
118
  ans_name: Agent Naming Service binding (e.g. ``helpbot.cisco.com``).
63
119
  evaluation_run_id: Source eval run id (must belong to the org).
@@ -71,7 +127,14 @@ class AgentCertEndpoint:
71
127
 
72
128
  Raises:
73
129
  ValueError: ``ans_name`` or ``evaluation_run_id`` missing.
74
- APIError: e.g. 400 issuance failed, 404 eval run not found/owned.
130
+ AgentCertInvalidRunTypeError: run's ``run_type`` isn't eligible
131
+ (TRUS-1643 — see the note above). Subclass of :class:`APIError`.
132
+ AgentCertRunNotCompletedError: run exists but hasn't reached
133
+ ``status=completed`` yet. Subclass of :class:`APIError`.
134
+ EvaluationNotFoundError: run id isn't visible in the caller's
135
+ org (or doesn't exist). Subclass of :class:`APIError`.
136
+ APIError: any other non-2xx (e.g. 400 issuance_failed,
137
+ 500 internal_issuance_error, 429).
75
138
  """
76
139
  if not ans_name:
77
140
  raise ValueError("agentcert.issue(): `ans_name` is required")
@@ -86,7 +149,22 @@ class AgentCertEndpoint:
86
149
  if validity_days is not None:
87
150
  data["validity_days"] = validity_days
88
151
 
89
- response = self._client.post(_ISSUE_PATH, data=data)
152
+ try:
153
+ response = self._client.post(_ISSUE_PATH, data=data)
154
+ except APIError as exc:
155
+ code = _extract_error_code(exc)
156
+ # ``exc_class`` (was ``typed`` — shadowed the ``typing`` module
157
+ # name and read poorly at a glance). None-safe: unknown / empty
158
+ # codes miss the routing table and fall through to ``raise``.
159
+ exc_class = _MINT_ERROR_CODE_TO_EXC.get(code or "")
160
+ if exc_class is not None:
161
+ raise exc_class(
162
+ exc.message,
163
+ status_code=exc.status_code,
164
+ response=exc.response,
165
+ error_code=code,
166
+ ) from exc
167
+ raise
90
168
  return AgentCertificate(**response)
91
169
 
92
170
  def verify(self, agent: str) -> AgentCertVerification:
@@ -115,6 +115,7 @@ class AgenticEndpoint:
115
115
  goal_achieved: Optional[bool] = None,
116
116
  frameworks: Optional[List[str]] = None,
117
117
  control_ids: Optional[List[str]] = None,
118
+ governed_agent: Optional[str] = None,
118
119
  ) -> AgenticEvaluation:
119
120
  """
120
121
  Evaluate an agent execution trace.
@@ -136,6 +137,13 @@ class AgenticEndpoint:
136
137
  control_ids: Optional list of control IDs to scope the compliance
137
138
  evaluation. Defaults server-side to all controls of the
138
139
  selected frameworks.
140
+ governed_agent: Optional GovernedAgent slug OR UUID to bind this
141
+ run to (TRUS-1640). When supplied, the resulting
142
+ ``ReportEvaluationRun`` is stamped with the FK so the agent's
143
+ badge / TrustScore history picks up this run. Must belong to
144
+ the caller's organization or the server returns HTTP 400
145
+ ``governed_agent_not_found``. When omitted, the run lands
146
+ standalone (pre-TRUS-1640 behavior).
139
147
 
140
148
  Returns:
141
149
  Evaluation creation response with run ID and status.
@@ -227,6 +235,11 @@ class AgenticEndpoint:
227
235
  eval_data["frameworks"] = frameworks
228
236
  if control_ids:
229
237
  eval_data["control_ids"] = control_ids
238
+ # TRUS-1640 — SDK peer of aurora-gateway PR #512. The BE resolves the
239
+ # supplied slug/UUID to a GovernedAgent and stamps the FK on create;
240
+ # omit when None so pre-1640 behavior (standalone runs) is preserved.
241
+ if governed_agent:
242
+ eval_data["governed_agent"] = governed_agent
230
243
 
231
244
  response = self._client.post("/sdk/v1/agentic/evaluate/", data=eval_data)
232
245
 
@@ -71,7 +71,38 @@ class ModelNotFoundError(APIError):
71
71
 
72
72
 
73
73
  class EvaluationNotFoundError(APIError):
74
- """Raised when a requested evaluation is not found."""
74
+ """Raised when a requested evaluation is not found.
75
+
76
+ TRUS-1643: also raised by ``client.agentcert.issue()`` when the mint
77
+ endpoint returns 400 with ``code=evaluation_run_not_found`` (i.e. the
78
+ run id exists globally but not in the caller's org).
79
+ """
80
+
81
+ pass
82
+
83
+
84
+ class AgentCertInvalidRunTypeError(APIError):
85
+ """Raised when ``client.agentcert.issue()`` targets a run whose ``run_type``
86
+ is not certifiable as an agent (TRUS-1643).
87
+
88
+ Only ``agent-evaluation-run`` and ``agentic-trace-run`` are accepted by
89
+ the mint endpoint; ``standard-run`` / ``leaderboard-run`` /
90
+ ``data-scan-run`` / ``rag-corpus-run`` all raise this error. Callers
91
+ should catch this to surface a "pick an Agent Evaluation run"
92
+ message rather than a generic 400.
93
+ """
94
+
95
+ pass
96
+
97
+
98
+ class AgentCertRunNotCompletedError(APIError):
99
+ """Raised when ``client.agentcert.issue()`` targets an eval run that has
100
+ not reached ``status=completed`` yet (TRUS-1643).
101
+
102
+ The mint endpoint requires a terminal-successful run so the score
103
+ snapshot is stable. Callers should wait for the run to complete (or
104
+ poll) before retrying.
105
+ """
75
106
 
76
107
  pass
77
108
 
File without changes
File without changes
File without changes