agentx-python 0.6.30__tar.gz → 0.6.32__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.
- {agentx_python-0.6.30 → agentx_python-0.6.32}/PKG-INFO +1 -1
- {agentx_python-0.6.30 → agentx_python-0.6.32}/agentx/evaluations/results.py +1 -2
- {agentx_python-0.6.30 → agentx_python-0.6.32}/agentx/evaluations/runner.py +0 -1
- {agentx_python-0.6.30 → agentx_python-0.6.32}/agentx/feedback.py +16 -0
- {agentx_python-0.6.30 → agentx_python-0.6.32}/agentx/monitor/client.py +11 -0
- {agentx_python-0.6.30 → agentx_python-0.6.32}/agentx/monitor/models.py +1 -2
- {agentx_python-0.6.30 → agentx_python-0.6.32}/agentx/monitor/profile.py +2 -4
- agentx_python-0.6.32/agentx/version.py +1 -0
- {agentx_python-0.6.30 → agentx_python-0.6.32}/agentx_python.egg-info/PKG-INFO +1 -1
- {agentx_python-0.6.30 → agentx_python-0.6.32}/agentx_python.egg-info/SOURCES.txt +0 -1
- agentx_python-0.6.30/agentx/evaluations/redaction.py +0 -57
- agentx_python-0.6.30/agentx/version.py +0 -1
- {agentx_python-0.6.30 → agentx_python-0.6.32}/LICENSE +0 -0
- {agentx_python-0.6.30 → agentx_python-0.6.32}/README.md +0 -0
- {agentx_python-0.6.30 → agentx_python-0.6.32}/agentx/__init__.py +0 -0
- {agentx_python-0.6.30 → agentx_python-0.6.32}/agentx/agentx.py +0 -0
- {agentx_python-0.6.30 → agentx_python-0.6.32}/agentx/cli.py +0 -0
- {agentx_python-0.6.30 → agentx_python-0.6.32}/agentx/evaluations/__init__.py +0 -0
- {agentx_python-0.6.30 → agentx_python-0.6.32}/agentx/evaluations/_term.py +0 -0
- {agentx_python-0.6.30 → agentx_python-0.6.32}/agentx/evaluations/adapters/__init__.py +0 -0
- {agentx_python-0.6.30 → agentx_python-0.6.32}/agentx/evaluations/adapters/http_endpoint.py +0 -0
- {agentx_python-0.6.30 → agentx_python-0.6.32}/agentx/evaluations/adapters/precomputed.py +0 -0
- {agentx_python-0.6.30 → agentx_python-0.6.32}/agentx/evaluations/adapters/raw.py +0 -0
- {agentx_python-0.6.30 → agentx_python-0.6.32}/agentx/evaluations/client.py +0 -0
- {agentx_python-0.6.30 → agentx_python-0.6.32}/agentx/evaluations/datasets.py +0 -0
- {agentx_python-0.6.30 → agentx_python-0.6.32}/agentx/evaluations/evaluation_settings.py +0 -0
- {agentx_python-0.6.30 → agentx_python-0.6.32}/agentx/evaluations/models.py +0 -0
- {agentx_python-0.6.30 → agentx_python-0.6.32}/agentx/evaluations/prompts.py +0 -0
- {agentx_python-0.6.30 → agentx_python-0.6.32}/agentx/evaluations/reporting.py +0 -0
- {agentx_python-0.6.30 → agentx_python-0.6.32}/agentx/evaluations/tool_schemas.py +0 -0
- {agentx_python-0.6.30 → agentx_python-0.6.32}/agentx/evaluations/tracing.py +0 -0
- {agentx_python-0.6.30 → agentx_python-0.6.32}/agentx/exceptions.py +0 -0
- {agentx_python-0.6.30 → agentx_python-0.6.32}/agentx/integrations/__init__.py +0 -0
- {agentx_python-0.6.30 → agentx_python-0.6.32}/agentx/integrations/_traced_call.py +0 -0
- {agentx_python-0.6.30 → agentx_python-0.6.32}/agentx/integrations/anthropic.py +0 -0
- {agentx_python-0.6.30 → agentx_python-0.6.32}/agentx/integrations/autogen.py +0 -0
- {agentx_python-0.6.30 → agentx_python-0.6.32}/agentx/integrations/crewai.py +0 -0
- {agentx_python-0.6.30 → agentx_python-0.6.32}/agentx/integrations/databricks.py +0 -0
- {agentx_python-0.6.30 → agentx_python-0.6.32}/agentx/integrations/google_adk.py +0 -0
- {agentx_python-0.6.30 → agentx_python-0.6.32}/agentx/integrations/google_genai.py +0 -0
- {agentx_python-0.6.30 → agentx_python-0.6.32}/agentx/integrations/langchain.py +0 -0
- {agentx_python-0.6.30 → agentx_python-0.6.32}/agentx/integrations/litellm.py +0 -0
- {agentx_python-0.6.30 → agentx_python-0.6.32}/agentx/integrations/llamaindex.py +0 -0
- {agentx_python-0.6.30 → agentx_python-0.6.32}/agentx/integrations/moveworks.py +0 -0
- {agentx_python-0.6.30 → agentx_python-0.6.32}/agentx/integrations/openai.py +0 -0
- {agentx_python-0.6.30 → agentx_python-0.6.32}/agentx/integrations/openai_agents.py +0 -0
- {agentx_python-0.6.30 → agentx_python-0.6.32}/agentx/monitor/__init__.py +0 -0
- {agentx_python-0.6.30 → agentx_python-0.6.32}/agentx/monitor/agents.py +0 -0
- {agentx_python-0.6.30 → agentx_python-0.6.32}/agentx/monitor/online_evaluators.py +0 -0
- {agentx_python-0.6.30 → agentx_python-0.6.32}/agentx/monitor/patterns.py +0 -0
- {agentx_python-0.6.30 → agentx_python-0.6.32}/agentx/monitor/sessions.py +0 -0
- {agentx_python-0.6.30 → agentx_python-0.6.32}/agentx/monitor/signals.py +0 -0
- {agentx_python-0.6.30 → agentx_python-0.6.32}/agentx/outcomes.py +0 -0
- {agentx_python-0.6.30 → agentx_python-0.6.32}/agentx/py.typed +0 -0
- {agentx_python-0.6.30 → agentx_python-0.6.32}/agentx/resources/__init__.py +0 -0
- {agentx_python-0.6.30 → agentx_python-0.6.32}/agentx/resources/agent.py +0 -0
- {agentx_python-0.6.30 → agentx_python-0.6.32}/agentx/resources/conversation.py +0 -0
- {agentx_python-0.6.30 → agentx_python-0.6.32}/agentx/resources/workforce.py +0 -0
- {agentx_python-0.6.30 → agentx_python-0.6.32}/agentx/tracing/__init__.py +0 -0
- {agentx_python-0.6.30 → agentx_python-0.6.32}/agentx/tracing/ci_types.py +0 -0
- {agentx_python-0.6.30 → agentx_python-0.6.32}/agentx/tracing/ingest_client.py +0 -0
- {agentx_python-0.6.30 → agentx_python-0.6.32}/agentx/tracing/tracer.py +0 -0
- {agentx_python-0.6.30 → agentx_python-0.6.32}/agentx/util.py +0 -0
- {agentx_python-0.6.30 → agentx_python-0.6.32}/agentx_python.egg-info/dependency_links.txt +0 -0
- {agentx_python-0.6.30 → agentx_python-0.6.32}/agentx_python.egg-info/entry_points.txt +0 -0
- {agentx_python-0.6.30 → agentx_python-0.6.32}/agentx_python.egg-info/not-zip-safe +0 -0
- {agentx_python-0.6.30 → agentx_python-0.6.32}/agentx_python.egg-info/requires.txt +0 -0
- {agentx_python-0.6.30 → agentx_python-0.6.32}/agentx_python.egg-info/top_level.txt +0 -0
- {agentx_python-0.6.30 → agentx_python-0.6.32}/setup.cfg +0 -0
- {agentx_python-0.6.30 → agentx_python-0.6.32}/setup.py +0 -0
- {agentx_python-0.6.30 → agentx_python-0.6.32}/tests/test_integration.py +0 -0
- {agentx_python-0.6.30 → agentx_python-0.6.32}/tests/test_integrations.py +0 -0
- {agentx_python-0.6.30 → agentx_python-0.6.32}/tests/test_selfhost_analysis_fallback.py +0 -0
- {agentx_python-0.6.30 → agentx_python-0.6.32}/tests/test_span_tree.py +0 -0
|
@@ -10,7 +10,6 @@ from agentx.evaluations.models import (
|
|
|
10
10
|
ResultTimings,
|
|
11
11
|
)
|
|
12
12
|
from agentx.evaluations.tracing import build_trace
|
|
13
|
-
from agentx.evaluations.redaction import redact_dict
|
|
14
13
|
|
|
15
14
|
|
|
16
15
|
def _to_int(value: Any) -> Optional[int]:
|
|
@@ -59,7 +58,7 @@ def normalize_result(
|
|
|
59
58
|
retrieval_context = raw.get("retrieval_context") or raw.get("retrievalContext")
|
|
60
59
|
meta_raw = raw.get("metadata")
|
|
61
60
|
if isinstance(meta_raw, dict):
|
|
62
|
-
metadata =
|
|
61
|
+
metadata = meta_raw
|
|
63
62
|
|
|
64
63
|
# Extract token counts - top-level keys take priority, fall back to metadata
|
|
65
64
|
input_tokens = _to_int(raw.get("input_tokens"))
|
|
@@ -21,7 +21,6 @@ from agentx.evaluations.models import (
|
|
|
21
21
|
ModelInfo,
|
|
22
22
|
Report,
|
|
23
23
|
)
|
|
24
|
-
from agentx.evaluations.redaction import redact_dict
|
|
25
24
|
from agentx.evaluations.reporting import print_report
|
|
26
25
|
from agentx.evaluations.results import normalize_result, normalize_error
|
|
27
26
|
from agentx.evaluations._term import (
|
|
@@ -74,3 +74,19 @@ class FeedbackClient:
|
|
|
74
74
|
raise AgentXFeedbackError(f"Failed to report feedback ({resp.status_code}): {detail}")
|
|
75
75
|
logger.info("Reported %s feedback on trace %s", rating, trace_id)
|
|
76
76
|
return resp.json().get("feedback", {})
|
|
77
|
+
|
|
78
|
+
def list(self, trace_id: str) -> list:
|
|
79
|
+
"""All votes recorded on one trace, oldest first (``GET /feedback/trace/:traceId``) -
|
|
80
|
+
the same rows the dashboard's trace dialog shows as up/down chips."""
|
|
81
|
+
resp = requests.get(
|
|
82
|
+
f"{api_base()}/feedback/trace/{trace_id}",
|
|
83
|
+
headers=get_headers(self._api_key),
|
|
84
|
+
timeout=10,
|
|
85
|
+
)
|
|
86
|
+
if resp.status_code >= 400:
|
|
87
|
+
try:
|
|
88
|
+
detail = resp.json().get("error", resp.reason)
|
|
89
|
+
except ValueError:
|
|
90
|
+
detail = resp.reason
|
|
91
|
+
raise AgentXFeedbackError(f"Failed to list feedback ({resp.status_code}): {detail}")
|
|
92
|
+
return resp.json().get("feedback", [])
|
|
@@ -198,6 +198,17 @@ class MonitorClient:
|
|
|
198
198
|
data = self._request("GET", f"/online-evaluators/{evaluator_id}/events", params=params)
|
|
199
199
|
return [OnlineEvaluatorEvent(**e) for e in data.get("events", [])]
|
|
200
200
|
|
|
201
|
+
# ------------------------------------------------------------------
|
|
202
|
+
# KPI endpoint
|
|
203
|
+
# ------------------------------------------------------------------
|
|
204
|
+
|
|
205
|
+
def kpis(self, window: str = "7d") -> dict:
|
|
206
|
+
"""Production health metrics over a window ("24h", "7d", or "30d") - the same numbers
|
|
207
|
+
the dashboard's Overview KPI strip shows: totalRuns, healthRate, failureRate,
|
|
208
|
+
downvoteRate (share of end-user votes that were "down"), toolFailureRate, p95LatencyMs,
|
|
209
|
+
plus deltas vs the prior window and the run-outcome breakdown."""
|
|
210
|
+
return self._request("GET", "/kpis", params={"window": window})
|
|
211
|
+
|
|
201
212
|
# ------------------------------------------------------------------
|
|
202
213
|
# Signal endpoints
|
|
203
214
|
# ------------------------------------------------------------------
|
|
@@ -122,7 +122,7 @@ class MonitorProfile(BaseModel):
|
|
|
122
122
|
``None`` from ``get()`` means this agent has never been configured and is running on
|
|
123
123
|
platform defaults (e.g. the built-in latency threshold defaults to 20000ms).
|
|
124
124
|
|
|
125
|
-
Self-host only: ``coverage_mode``/``sample_rate``/``retention_days
|
|
125
|
+
Self-host only: ``coverage_mode``/``sample_rate``/``retention_days``, and
|
|
126
126
|
``threshold_overrides["latencyMs"]`` are project-level defaults now (set once for every agent
|
|
127
127
|
via the dashboard's Platform Settings screen), not real per-agent settings - this model and
|
|
128
128
|
``update()`` still accept/return them for wire compatibility, but a self-host engine no longer
|
|
@@ -141,7 +141,6 @@ class MonitorProfile(BaseModel):
|
|
|
141
141
|
channels: List[str] = Field(default_factory=list)
|
|
142
142
|
threshold_overrides: Optional[Dict[str, Any]] = Field(default=None, alias="thresholdOverrides")
|
|
143
143
|
retention_days: int = Field(default=30, alias="retentionDays")
|
|
144
|
-
redaction_mode: str = Field(default="standard", alias="redactionMode")
|
|
145
144
|
approval_policy: Optional[Dict[str, str]] = Field(default=None, alias="approvalPolicy")
|
|
146
145
|
created_at: Optional[str] = Field(default=None, alias="createdAt")
|
|
147
146
|
updated_at: Optional[str] = Field(default=None, alias="updatedAt")
|
|
@@ -13,7 +13,7 @@ logger = logging.getLogger(__name__)
|
|
|
13
13
|
|
|
14
14
|
class MonitorProfileClient:
|
|
15
15
|
"""Thin wrapper surfaced as ``client.monitor.profile``: get/update a single agent's Monitor
|
|
16
|
-
coverage and detection settings (coverage mode, sample rate, retention,
|
|
16
|
+
coverage and detection settings (coverage mode, sample rate, retention, approval
|
|
17
17
|
policy, and threshold_overrides, e.g. the built-in "Latency regression" pattern's threshold).
|
|
18
18
|
|
|
19
19
|
Unlike patterns/signals, a profile is scoped to one agent per call, since that mirrors how
|
|
@@ -41,13 +41,12 @@ class MonitorProfileClient:
|
|
|
41
41
|
dataset_id: Optional[str] = None,
|
|
42
42
|
threshold_overrides: Optional[Dict[str, Any]] = None,
|
|
43
43
|
retention_days: Optional[int] = None,
|
|
44
|
-
redaction_mode: Optional[str] = None,
|
|
45
44
|
approval_policy: Optional[Dict[str, str]] = None,
|
|
46
45
|
) -> MonitorProfile:
|
|
47
46
|
"""Update (and enable, if not already) this agent's Monitor profile. Only fields passed
|
|
48
47
|
here are changed; everything else on the existing profile is left as is.
|
|
49
48
|
|
|
50
|
-
Self-host only: ``coverage_mode``/``sample_rate``/``retention_days
|
|
49
|
+
Self-host only: ``coverage_mode``/``sample_rate``/``retention_days``,
|
|
51
50
|
and ``threshold_overrides["latencyMs"]`` are project-level defaults now (see
|
|
52
51
|
``MonitorProfile``'s docstring) - set them via the dashboard's Platform Settings screen
|
|
53
52
|
instead, passing them here is accepted but has no effect. ``enabled``/
|
|
@@ -67,7 +66,6 @@ class MonitorProfileClient:
|
|
|
67
66
|
"datasetId": dataset_id,
|
|
68
67
|
"thresholdOverrides": threshold_overrides,
|
|
69
68
|
"retentionDays": retention_days,
|
|
70
|
-
"redactionMode": redaction_mode,
|
|
71
69
|
"approvalPolicy": approval_policy,
|
|
72
70
|
}
|
|
73
71
|
payload = {k: v for k, v in payload.items() if v is not None}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
VERSION = "0.6.32"
|
|
@@ -17,7 +17,6 @@ agentx/evaluations/datasets.py
|
|
|
17
17
|
agentx/evaluations/evaluation_settings.py
|
|
18
18
|
agentx/evaluations/models.py
|
|
19
19
|
agentx/evaluations/prompts.py
|
|
20
|
-
agentx/evaluations/redaction.py
|
|
21
20
|
agentx/evaluations/reporting.py
|
|
22
21
|
agentx/evaluations/results.py
|
|
23
22
|
agentx/evaluations/runner.py
|
|
@@ -1,57 +0,0 @@
|
|
|
1
|
-
from __future__ import annotations
|
|
2
|
-
|
|
3
|
-
import re
|
|
4
|
-
from typing import Any, Dict
|
|
5
|
-
|
|
6
|
-
# Patterns that look like secrets
|
|
7
|
-
_SECRET_PATTERNS = [
|
|
8
|
-
re.compile(r"sk-[A-Za-z0-9]{20,}"), # OpenAI / Anthropic style keys
|
|
9
|
-
re.compile(r"Bearer\s+[A-Za-z0-9\-._~+/]+=*", re.IGNORECASE),
|
|
10
|
-
re.compile(r"(?i)(password|passwd|secret|token|api[_-]?key)\s*[=:]\s*\S+"),
|
|
11
|
-
re.compile(r"[A-Za-z0-9+/]{40,}={0,2}"), # long base64-like strings
|
|
12
|
-
]
|
|
13
|
-
|
|
14
|
-
_REDACTED = "[REDACTED]"
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
def redact_string(value: str) -> str:
|
|
18
|
-
for pattern in _SECRET_PATTERNS:
|
|
19
|
-
value = pattern.sub(_REDACTED, value)
|
|
20
|
-
return value
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
def redact_dict(obj: Any, _depth: int = 0) -> Any:
|
|
24
|
-
if _depth > 10:
|
|
25
|
-
return obj
|
|
26
|
-
if isinstance(obj, dict):
|
|
27
|
-
return {k: _redact_value(k, v, _depth) for k, v in obj.items()}
|
|
28
|
-
if isinstance(obj, list):
|
|
29
|
-
return [redact_dict(item, _depth + 1) for item in obj]
|
|
30
|
-
if isinstance(obj, str):
|
|
31
|
-
return redact_string(obj)
|
|
32
|
-
return obj
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
_SENSITIVE_KEYS = {
|
|
36
|
-
"password",
|
|
37
|
-
"passwd",
|
|
38
|
-
"secret",
|
|
39
|
-
"token",
|
|
40
|
-
"api_key",
|
|
41
|
-
"apikey",
|
|
42
|
-
"authorization",
|
|
43
|
-
"auth",
|
|
44
|
-
"cookie",
|
|
45
|
-
"session",
|
|
46
|
-
"credential",
|
|
47
|
-
"private_key",
|
|
48
|
-
"privatekey",
|
|
49
|
-
"access_key",
|
|
50
|
-
"accesskey",
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
def _redact_value(key: str, value: Any, depth: int) -> Any:
|
|
55
|
-
if isinstance(key, str) and key.lower() in _SENSITIVE_KEYS:
|
|
56
|
-
return _REDACTED
|
|
57
|
-
return redact_dict(value, depth + 1)
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
VERSION = "0.6.30"
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|