agenta 0.65.0__py3-none-any.whl → 0.70.1__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.
- agenta/__init__.py +66 -36
- agenta/client/backend/types/testset_output_response.py +1 -0
- agenta/sdk/agenta_init.py +90 -12
- agenta/sdk/assets.py +16 -10
- agenta/sdk/engines/tracing/tracing.py +2 -2
- agenta/sdk/evaluations/metrics.py +3 -3
- agenta/sdk/litellm/litellm.py +38 -30
- agenta/sdk/middleware/auth.py +19 -4
- agenta/sdk/middleware/otel.py +0 -3
- agenta/sdk/middleware/vault.py +20 -5
- agenta/sdk/middlewares/running/vault.py +1 -1
- agenta/sdk/models/evaluations.py +11 -3
- agenta/sdk/models/shared.py +1 -1
- agenta/sdk/tracing/exporters.py +1 -0
- agenta/sdk/tracing/processors.py +40 -37
- agenta/sdk/tracing/tracing.py +91 -2
- agenta/sdk/workflows/runners/__init__.py +3 -0
- agenta/sdk/workflows/runners/base.py +30 -0
- agenta/sdk/workflows/runners/daytona.py +268 -0
- agenta/sdk/workflows/runners/local.py +108 -0
- agenta/sdk/workflows/runners/registry.py +48 -0
- agenta/sdk/workflows/sandbox.py +18 -81
- {agenta-0.65.0.dist-info → agenta-0.70.1.dist-info}/METADATA +4 -2
- {agenta-0.65.0.dist-info → agenta-0.70.1.dist-info}/RECORD +25 -20
- {agenta-0.65.0.dist-info → agenta-0.70.1.dist-info}/WHEEL +0 -0
agenta/__init__.py
CHANGED
|
@@ -1,52 +1,50 @@
|
|
|
1
1
|
from typing import Any, Callable, Optional
|
|
2
2
|
|
|
3
|
-
from .sdk.utils.preinit import PreInitObject
|
|
4
|
-
|
|
5
|
-
from agenta.client import AgentaApi, AsyncAgentaApi
|
|
6
3
|
import agenta.client.backend.types as client_types # pylint: disable=wrong-import-order
|
|
4
|
+
from agenta.client import AgentaApi, AsyncAgentaApi
|
|
7
5
|
|
|
8
|
-
from .sdk
|
|
9
|
-
MCField,
|
|
10
|
-
DictInput,
|
|
11
|
-
MultipleChoice,
|
|
12
|
-
FloatParam,
|
|
13
|
-
IntParam,
|
|
14
|
-
MultipleChoiceParam,
|
|
15
|
-
GroupedMultipleChoiceParam,
|
|
16
|
-
MessagesInput,
|
|
17
|
-
TextParam,
|
|
18
|
-
FileInputURL,
|
|
19
|
-
BinaryParam,
|
|
20
|
-
Prompt,
|
|
21
|
-
PromptTemplate,
|
|
22
|
-
)
|
|
6
|
+
from .sdk import assets as assets
|
|
23
7
|
|
|
24
|
-
|
|
25
|
-
from .sdk
|
|
26
|
-
from .sdk
|
|
27
|
-
from .sdk.
|
|
28
|
-
from .sdk.
|
|
29
|
-
from .sdk.
|
|
8
|
+
# evaluations
|
|
9
|
+
from .sdk import testsets as testsets
|
|
10
|
+
from .sdk import tracer
|
|
11
|
+
from .sdk.agenta_init import AgentaSingleton, Config
|
|
12
|
+
from .sdk.agenta_init import init as _init
|
|
13
|
+
from .sdk.context.running import workflow_mode_enabled
|
|
30
14
|
from .sdk.decorators.running import (
|
|
31
|
-
workflow,
|
|
32
15
|
application,
|
|
33
16
|
evaluator,
|
|
17
|
+
workflow,
|
|
34
18
|
)
|
|
35
|
-
from .sdk.decorators.serving import
|
|
36
|
-
from .sdk.
|
|
19
|
+
from .sdk.decorators.serving import app, route
|
|
20
|
+
from .sdk.decorators.tracing import instrument
|
|
37
21
|
from .sdk.litellm import litellm as callbacks
|
|
38
22
|
from .sdk.managers.apps import AppManager
|
|
39
|
-
from .sdk.managers.vault import VaultManager
|
|
40
|
-
from .sdk.managers.secrets import SecretsManager
|
|
41
23
|
from .sdk.managers.config import ConfigManager
|
|
42
|
-
from .sdk.managers.variant import VariantManager
|
|
43
24
|
from .sdk.managers.deployment import DeploymentManager
|
|
44
|
-
from .sdk import
|
|
45
|
-
from .sdk import
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
from .sdk import
|
|
49
|
-
|
|
25
|
+
from .sdk.managers.secrets import SecretsManager
|
|
26
|
+
from .sdk.managers.variant import VariantManager
|
|
27
|
+
from .sdk.managers.vault import VaultManager
|
|
28
|
+
from .sdk.tracing import Tracing, get_tracer
|
|
29
|
+
from .sdk.tracing.conventions import Reference
|
|
30
|
+
from .sdk.types import (
|
|
31
|
+
BinaryParam,
|
|
32
|
+
DictInput,
|
|
33
|
+
FileInputURL,
|
|
34
|
+
FloatParam,
|
|
35
|
+
GroupedMultipleChoiceParam,
|
|
36
|
+
IntParam,
|
|
37
|
+
MCField,
|
|
38
|
+
MessagesInput,
|
|
39
|
+
MultipleChoice,
|
|
40
|
+
MultipleChoiceParam,
|
|
41
|
+
Prompt,
|
|
42
|
+
PromptTemplate,
|
|
43
|
+
TextParam,
|
|
44
|
+
)
|
|
45
|
+
from .sdk.utils.costs import calculate_token_usage
|
|
46
|
+
from .sdk.utils.logging import get_module_logger
|
|
47
|
+
from .sdk.utils.preinit import PreInitObject
|
|
50
48
|
|
|
51
49
|
config = PreInitObject("agenta.config", Config)
|
|
52
50
|
DEFAULT_AGENTA_SINGLETON_INSTANCE = AgentaSingleton()
|
|
@@ -88,3 +86,35 @@ def init(
|
|
|
88
86
|
|
|
89
87
|
tracing = DEFAULT_AGENTA_SINGLETON_INSTANCE.tracing # type: ignore
|
|
90
88
|
tracer = get_tracer(tracing)
|
|
89
|
+
|
|
90
|
+
|
|
91
|
+
def get_trace_url(trace_id: Optional[str] = None) -> str:
|
|
92
|
+
"""
|
|
93
|
+
Build a URL to view the current trace in the Agenta UI.
|
|
94
|
+
|
|
95
|
+
Automatically extracts the trace ID from the current tracing context.
|
|
96
|
+
Can also accept an explicit trace_id if needed.
|
|
97
|
+
|
|
98
|
+
Args:
|
|
99
|
+
trace_id: Optional trace ID (hex string format). If not provided,
|
|
100
|
+
it will be automatically extracted from the current trace context.
|
|
101
|
+
|
|
102
|
+
Returns:
|
|
103
|
+
The full URL to view the trace in the observability dashboard
|
|
104
|
+
|
|
105
|
+
Raises:
|
|
106
|
+
RuntimeError: If the SDK is not initialized, no active trace context exists,
|
|
107
|
+
or scope info cannot be fetched
|
|
108
|
+
|
|
109
|
+
Example:
|
|
110
|
+
>>> import agenta as ag
|
|
111
|
+
>>> ag.init(api_key="xxx")
|
|
112
|
+
>>>
|
|
113
|
+
>>> @ag.instrument()
|
|
114
|
+
>>> def my_function():
|
|
115
|
+
>>> # Get URL for the current trace
|
|
116
|
+
>>> url = ag.tracing.get_trace_url()
|
|
117
|
+
>>> print(url)
|
|
118
|
+
>>> return "result"
|
|
119
|
+
"""
|
|
120
|
+
return DEFAULT_AGENTA_SINGLETON_INSTANCE.tracing.get_trace_url(trace_id)
|
agenta/sdk/agenta_init.py
CHANGED
|
@@ -1,16 +1,15 @@
|
|
|
1
|
-
import toml
|
|
2
|
-
from os import getenv
|
|
3
|
-
from typing import Optional, Callable, Any
|
|
4
1
|
from importlib.metadata import version
|
|
2
|
+
from os import getenv
|
|
3
|
+
from typing import Any, Callable, Optional
|
|
5
4
|
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
from agenta.sdk.utils.logging import get_module_logger
|
|
5
|
+
import requests
|
|
6
|
+
import toml
|
|
9
7
|
from agenta.client.client import AgentaApi, AsyncAgentaApi
|
|
10
|
-
|
|
11
|
-
from agenta.sdk.tracing import Tracing
|
|
12
8
|
from agenta.sdk.contexts.routing import RoutingContext
|
|
13
|
-
|
|
9
|
+
from agenta.sdk.tracing import Tracing
|
|
10
|
+
from agenta.sdk.utils.globals import set_global
|
|
11
|
+
from agenta.sdk.utils.helpers import parse_url
|
|
12
|
+
from agenta.sdk.utils.logging import get_module_logger
|
|
14
13
|
|
|
15
14
|
log = get_module_logger(__name__)
|
|
16
15
|
|
|
@@ -19,6 +18,7 @@ class AgentaSingleton:
|
|
|
19
18
|
"""Singleton class to save all the "global variables" for the sdk."""
|
|
20
19
|
|
|
21
20
|
_instance = None
|
|
21
|
+
_initialized = False
|
|
22
22
|
config = None
|
|
23
23
|
tracing = None
|
|
24
24
|
|
|
@@ -26,6 +26,11 @@ class AgentaSingleton:
|
|
|
26
26
|
async_api = None
|
|
27
27
|
|
|
28
28
|
def __init__(self):
|
|
29
|
+
# Only initialize once
|
|
30
|
+
if AgentaSingleton._initialized:
|
|
31
|
+
return
|
|
32
|
+
|
|
33
|
+
AgentaSingleton._initialized = True
|
|
29
34
|
self.host = None
|
|
30
35
|
self.api_url = None
|
|
31
36
|
self.api_key = None
|
|
@@ -33,6 +38,11 @@ class AgentaSingleton:
|
|
|
33
38
|
self.scope_type = None
|
|
34
39
|
self.scope_id = None
|
|
35
40
|
|
|
41
|
+
# Cached scope information for URL building
|
|
42
|
+
self.organization_id: Optional[str] = None
|
|
43
|
+
self.workspace_id: Optional[str] = None
|
|
44
|
+
self.project_id: Optional[str] = None
|
|
45
|
+
|
|
36
46
|
def __new__(cls):
|
|
37
47
|
if not cls._instance:
|
|
38
48
|
cls._instance = super(AgentaSingleton, cls).__new__(cls)
|
|
@@ -70,7 +80,11 @@ class AgentaSingleton:
|
|
|
70
80
|
|
|
71
81
|
"""
|
|
72
82
|
|
|
73
|
-
|
|
83
|
+
# Idempotency check: if already initialized, skip re-initialization
|
|
84
|
+
if self.tracing and self.api and self.async_api:
|
|
85
|
+
return
|
|
86
|
+
|
|
87
|
+
log.info("Agenta - SDK ver: %s", version("agenta"))
|
|
74
88
|
|
|
75
89
|
config = {}
|
|
76
90
|
if config_fname:
|
|
@@ -100,7 +114,7 @@ class AgentaSingleton:
|
|
|
100
114
|
|
|
101
115
|
try:
|
|
102
116
|
assert _api_url and isinstance(_api_url, str), (
|
|
103
|
-
"API URL is required. Please
|
|
117
|
+
"API URL is required. Please set AGENTA_API_URL environment variable or pass api_url parameter in ag.init()."
|
|
104
118
|
)
|
|
105
119
|
self.host = _host
|
|
106
120
|
self.api_url = _api_url
|
|
@@ -118,7 +132,12 @@ class AgentaSingleton:
|
|
|
118
132
|
or None # NO FALLBACK
|
|
119
133
|
)
|
|
120
134
|
|
|
121
|
-
|
|
135
|
+
if self.api_key is None:
|
|
136
|
+
log.error(
|
|
137
|
+
"API key is required. Please set AGENTA_API_KEY environment variable or pass api_key parameter in ag.init()."
|
|
138
|
+
)
|
|
139
|
+
|
|
140
|
+
log.info("Agenta - API URL: %s", self.api_url)
|
|
122
141
|
|
|
123
142
|
self.scope_type = (
|
|
124
143
|
scope_type
|
|
@@ -159,6 +178,65 @@ class AgentaSingleton:
|
|
|
159
178
|
api_key=self.api_key,
|
|
160
179
|
)
|
|
161
180
|
|
|
181
|
+
# Reset cached scope info on re-init
|
|
182
|
+
self.organization_id = None
|
|
183
|
+
self.workspace_id = None
|
|
184
|
+
self.project_id = None
|
|
185
|
+
|
|
186
|
+
def resolve_scopes(self) -> Optional[tuple[str, str, str]]:
|
|
187
|
+
"""Fetch and cache workspace_id and project_id from the API."""
|
|
188
|
+
if (
|
|
189
|
+
self.organization_id is not None
|
|
190
|
+
and self.workspace_id is not None
|
|
191
|
+
and self.project_id is not None
|
|
192
|
+
):
|
|
193
|
+
return
|
|
194
|
+
|
|
195
|
+
if self.api_url is None or self.api_key is None:
|
|
196
|
+
log.error("API URL or API key is not set. Please call ag.init() first.")
|
|
197
|
+
return
|
|
198
|
+
|
|
199
|
+
try:
|
|
200
|
+
response = requests.get(
|
|
201
|
+
f"{self.api_url}/projects/current",
|
|
202
|
+
headers={"Authorization": f"ApiKey {self.api_key}"},
|
|
203
|
+
timeout=10,
|
|
204
|
+
)
|
|
205
|
+
response.raise_for_status()
|
|
206
|
+
|
|
207
|
+
project_info = response.json()
|
|
208
|
+
|
|
209
|
+
if not project_info:
|
|
210
|
+
log.error(
|
|
211
|
+
"No project context found. Please ensure your API key is valid."
|
|
212
|
+
)
|
|
213
|
+
|
|
214
|
+
self.organization_id = project_info.get("organization_id")
|
|
215
|
+
self.workspace_id = project_info.get("workspace_id")
|
|
216
|
+
self.project_id = project_info.get("project_id")
|
|
217
|
+
|
|
218
|
+
if (
|
|
219
|
+
not self.organization_id
|
|
220
|
+
and not self.workspace_id
|
|
221
|
+
or not self.project_id
|
|
222
|
+
):
|
|
223
|
+
log.error(
|
|
224
|
+
"Could not determine organization/workspace/project from API response."
|
|
225
|
+
)
|
|
226
|
+
|
|
227
|
+
except Exception as e:
|
|
228
|
+
log.error(f"Failed to fetch scope information: {e}")
|
|
229
|
+
return
|
|
230
|
+
|
|
231
|
+
if self.organization_id and self.workspace_id and self.project_id:
|
|
232
|
+
return (
|
|
233
|
+
self.organization_id,
|
|
234
|
+
self.workspace_id,
|
|
235
|
+
self.project_id,
|
|
236
|
+
)
|
|
237
|
+
|
|
238
|
+
return None
|
|
239
|
+
|
|
162
240
|
|
|
163
241
|
class Config:
|
|
164
242
|
def __init__(
|
agenta/sdk/assets.py
CHANGED
|
@@ -28,6 +28,7 @@ supported_llm_models = {
|
|
|
28
28
|
],
|
|
29
29
|
"gemini": [
|
|
30
30
|
"gemini/gemini-3-pro-preview",
|
|
31
|
+
"gemini/gemini-3-flash-preview",
|
|
31
32
|
"gemini/gemini-2.5-pro",
|
|
32
33
|
"gemini/gemini-2.5-pro-preview-05-06",
|
|
33
34
|
"gemini/gemini-2.5-flash",
|
|
@@ -64,21 +65,26 @@ supported_llm_models = {
|
|
|
64
65
|
"mistral/mistral-large-latest",
|
|
65
66
|
],
|
|
66
67
|
"openai": [
|
|
67
|
-
"gpt-5",
|
|
68
|
+
"gpt-5.2-pro",
|
|
69
|
+
"gpt-5.2-chat-latest",
|
|
70
|
+
"gpt-5.2",
|
|
71
|
+
"gpt-5.1-chat-latest",
|
|
68
72
|
"gpt-5.1",
|
|
69
|
-
"gpt-5-
|
|
73
|
+
"gpt-5-pro",
|
|
70
74
|
"gpt-5-nano",
|
|
75
|
+
"gpt-5-mini",
|
|
76
|
+
"gpt-5",
|
|
77
|
+
"o4-mini",
|
|
71
78
|
"gpt-4.5-preview",
|
|
72
|
-
"gpt-
|
|
73
|
-
"gpt-
|
|
74
|
-
"gpt-4",
|
|
75
|
-
"gpt-4o",
|
|
79
|
+
"gpt-4.1-nano",
|
|
80
|
+
"gpt-4.1-mini",
|
|
81
|
+
"gpt-4.1",
|
|
76
82
|
"gpt-4o-mini",
|
|
83
|
+
"gpt-4o",
|
|
77
84
|
"gpt-4-1106-preview",
|
|
78
|
-
"gpt-4
|
|
79
|
-
"gpt-
|
|
80
|
-
"gpt-
|
|
81
|
-
"o4-mini",
|
|
85
|
+
"gpt-4",
|
|
86
|
+
"gpt-3.5-turbo-1106",
|
|
87
|
+
"gpt-3.5-turbo",
|
|
82
88
|
],
|
|
83
89
|
"openrouter": [
|
|
84
90
|
"openrouter/qwen/qwen3-235b-a22b",
|
|
@@ -114,7 +114,7 @@ class Tracing(metaclass=Singleton):
|
|
|
114
114
|
|
|
115
115
|
# TRACE PROCESSORS -- OTLP
|
|
116
116
|
try:
|
|
117
|
-
log.info("Agenta -
|
|
117
|
+
log.info("Agenta - OTLP URL: %s", self.otlp_url)
|
|
118
118
|
|
|
119
119
|
_otlp = TraceProcessor(
|
|
120
120
|
OTLPExporter(
|
|
@@ -127,7 +127,7 @@ class Tracing(metaclass=Singleton):
|
|
|
127
127
|
|
|
128
128
|
self.tracer_provider.add_span_processor(_otlp)
|
|
129
129
|
except: # pylint: disable=bare-except
|
|
130
|
-
log.warning("Agenta -
|
|
130
|
+
log.warning("Agenta - OTLP unreachable, skipping exports.")
|
|
131
131
|
|
|
132
132
|
# GLOBAL TRACER PROVIDER -- INSTRUMENTATION LIBRARIES
|
|
133
133
|
set_tracer_provider(self.tracer_provider)
|
|
@@ -13,15 +13,15 @@ async def arefresh(
|
|
|
13
13
|
# timestamp: Optional[str] = None,
|
|
14
14
|
# interval: Optional[float] = None,
|
|
15
15
|
) -> EvaluationMetrics:
|
|
16
|
-
|
|
16
|
+
metrics = dict(
|
|
17
17
|
run_id=str(run_id),
|
|
18
18
|
scenario_id=str(scenario_id) if scenario_id else None,
|
|
19
19
|
)
|
|
20
20
|
|
|
21
21
|
response = authed_api()(
|
|
22
22
|
method="POST",
|
|
23
|
-
endpoint=
|
|
24
|
-
|
|
23
|
+
endpoint="/preview/evaluations/metrics/refresh",
|
|
24
|
+
json=dict(metrics=metrics),
|
|
25
25
|
)
|
|
26
26
|
|
|
27
27
|
try:
|
agenta/sdk/litellm/litellm.py
CHANGED
|
@@ -166,24 +166,27 @@ def litellm_handler():
|
|
|
166
166
|
namespace="metrics.unit.costs",
|
|
167
167
|
)
|
|
168
168
|
|
|
169
|
+
# Handle both dict and object attribute access for usage, and safely handle None
|
|
170
|
+
usage = getattr(response_obj, "usage", None)
|
|
171
|
+
if isinstance(usage, dict):
|
|
172
|
+
prompt_tokens = usage.get("prompt_tokens")
|
|
173
|
+
completion_tokens = usage.get("completion_tokens")
|
|
174
|
+
total_tokens = usage.get("total_tokens")
|
|
175
|
+
elif usage is not None:
|
|
176
|
+
prompt_tokens = getattr(usage, "prompt_tokens", None)
|
|
177
|
+
completion_tokens = getattr(usage, "completion_tokens", None)
|
|
178
|
+
total_tokens = getattr(usage, "total_tokens", None)
|
|
179
|
+
else:
|
|
180
|
+
prompt_tokens = completion_tokens = total_tokens = None
|
|
181
|
+
|
|
169
182
|
span.set_attributes(
|
|
170
183
|
attributes=(
|
|
171
184
|
{
|
|
172
|
-
"prompt": (
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
),
|
|
177
|
-
"completion": (
|
|
178
|
-
float(response_obj.usage.completion_tokens)
|
|
179
|
-
if response_obj.usage.completion_tokens
|
|
180
|
-
else None
|
|
181
|
-
),
|
|
182
|
-
"total": (
|
|
183
|
-
float(response_obj.usage.total_tokens)
|
|
184
|
-
if response_obj.usage.total_tokens
|
|
185
|
-
else None
|
|
186
|
-
),
|
|
185
|
+
"prompt": float(prompt_tokens) if prompt_tokens else None,
|
|
186
|
+
"completion": float(completion_tokens)
|
|
187
|
+
if completion_tokens
|
|
188
|
+
else None,
|
|
189
|
+
"total": float(total_tokens) if total_tokens else None,
|
|
187
190
|
}
|
|
188
191
|
),
|
|
189
192
|
namespace="metrics.unit.tokens",
|
|
@@ -300,24 +303,29 @@ def litellm_handler():
|
|
|
300
303
|
namespace="metrics.unit.costs",
|
|
301
304
|
)
|
|
302
305
|
|
|
306
|
+
# Handle both dict and object attribute access for usage
|
|
307
|
+
usage = getattr(response_obj, "usage", None)
|
|
308
|
+
if usage is None:
|
|
309
|
+
prompt_tokens = None
|
|
310
|
+
completion_tokens = None
|
|
311
|
+
total_tokens = None
|
|
312
|
+
elif isinstance(usage, dict):
|
|
313
|
+
prompt_tokens = usage.get("prompt_tokens")
|
|
314
|
+
completion_tokens = usage.get("completion_tokens")
|
|
315
|
+
total_tokens = usage.get("total_tokens")
|
|
316
|
+
else:
|
|
317
|
+
prompt_tokens = getattr(usage, "prompt_tokens", None)
|
|
318
|
+
completion_tokens = getattr(usage, "completion_tokens", None)
|
|
319
|
+
total_tokens = getattr(usage, "total_tokens", None)
|
|
320
|
+
|
|
303
321
|
span.set_attributes(
|
|
304
322
|
attributes=(
|
|
305
323
|
{
|
|
306
|
-
"prompt": (
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
),
|
|
311
|
-
"completion": (
|
|
312
|
-
float(response_obj.usage.completion_tokens)
|
|
313
|
-
if response_obj.usage.completion_tokens
|
|
314
|
-
else None
|
|
315
|
-
),
|
|
316
|
-
"total": (
|
|
317
|
-
float(response_obj.usage.total_tokens)
|
|
318
|
-
if response_obj.usage.total_tokens
|
|
319
|
-
else None
|
|
320
|
-
),
|
|
324
|
+
"prompt": float(prompt_tokens) if prompt_tokens else None,
|
|
325
|
+
"completion": float(completion_tokens)
|
|
326
|
+
if completion_tokens
|
|
327
|
+
else None,
|
|
328
|
+
"total": float(total_tokens) if total_tokens else None,
|
|
321
329
|
}
|
|
322
330
|
),
|
|
323
331
|
namespace="metrics.unit.tokens",
|
agenta/sdk/middleware/auth.py
CHANGED
|
@@ -17,14 +17,12 @@ import agenta as ag
|
|
|
17
17
|
|
|
18
18
|
log = get_module_logger(__name__)
|
|
19
19
|
|
|
20
|
-
AGENTA_RUNTIME_PREFIX = getenv("AGENTA_RUNTIME_PREFIX", "")
|
|
21
|
-
|
|
22
20
|
|
|
23
21
|
_CACHE_ENABLED = (
|
|
24
22
|
getenv("AGENTA_SERVICE_MIDDLEWARE_CACHE_ENABLED", "true").lower() in TRUTHY
|
|
25
23
|
)
|
|
26
24
|
|
|
27
|
-
_ALWAYS_ALLOW_LIST = [
|
|
25
|
+
_ALWAYS_ALLOW_LIST = ["/health"]
|
|
28
26
|
|
|
29
27
|
_cache = TTLLRUCache()
|
|
30
28
|
|
|
@@ -64,7 +62,7 @@ class AuthHTTPMiddleware(BaseHTTPMiddleware):
|
|
|
64
62
|
|
|
65
63
|
async def dispatch(self, request: Request, call_next: Callable):
|
|
66
64
|
try:
|
|
67
|
-
if request.url.path in _ALWAYS_ALLOW_LIST:
|
|
65
|
+
if _strip_service_prefix(request.url.path) in _ALWAYS_ALLOW_LIST:
|
|
68
66
|
request.state.auth = {}
|
|
69
67
|
|
|
70
68
|
else:
|
|
@@ -253,3 +251,20 @@ class AuthHTTPMiddleware(BaseHTTPMiddleware):
|
|
|
253
251
|
status_code=500,
|
|
254
252
|
content=f"Could not verify credentials: unexpected error - {str(exc)}. Please try again later or contact support if the issue persists.",
|
|
255
253
|
) from exc
|
|
254
|
+
|
|
255
|
+
|
|
256
|
+
def _strip_service_prefix(path: str) -> str:
|
|
257
|
+
if not path.startswith("/services/"):
|
|
258
|
+
return path
|
|
259
|
+
|
|
260
|
+
parts = path.split("/", 3)
|
|
261
|
+
if len(parts) < 4:
|
|
262
|
+
return "/"
|
|
263
|
+
|
|
264
|
+
service_name = parts[2]
|
|
265
|
+
remainder = parts[3]
|
|
266
|
+
|
|
267
|
+
if not service_name or not remainder or remainder.startswith("/"):
|
|
268
|
+
return path
|
|
269
|
+
|
|
270
|
+
return f"/{remainder}"
|
agenta/sdk/middleware/otel.py
CHANGED
|
@@ -3,9 +3,6 @@ from typing import Callable
|
|
|
3
3
|
from starlette.middleware.base import BaseHTTPMiddleware
|
|
4
4
|
from fastapi import Request, FastAPI
|
|
5
5
|
|
|
6
|
-
from opentelemetry.baggage.propagation import W3CBaggagePropagator
|
|
7
|
-
from opentelemetry.trace.propagation.tracecontext import TraceContextTextMapPropagator
|
|
8
|
-
|
|
9
6
|
from agenta.sdk.utils.exceptions import suppress
|
|
10
7
|
from agenta.sdk.tracing.propagation import extract
|
|
11
8
|
|
agenta/sdk/middleware/vault.py
CHANGED
|
@@ -21,11 +21,9 @@ import agenta as ag
|
|
|
21
21
|
log = get_module_logger(__name__)
|
|
22
22
|
|
|
23
23
|
|
|
24
|
-
AGENTA_RUNTIME_PREFIX = getenv("AGENTA_RUNTIME_PREFIX", "")
|
|
25
|
-
|
|
26
24
|
_ALWAYS_ALLOW_LIST = [
|
|
27
|
-
|
|
28
|
-
|
|
25
|
+
"/health",
|
|
26
|
+
"/openapi.json",
|
|
29
27
|
]
|
|
30
28
|
|
|
31
29
|
_PROVIDER_KINDS = [
|
|
@@ -116,7 +114,7 @@ class VaultMiddleware(BaseHTTPMiddleware):
|
|
|
116
114
|
allow_secrets = True
|
|
117
115
|
|
|
118
116
|
try:
|
|
119
|
-
if
|
|
117
|
+
if _strip_service_prefix(request.url.path) not in _ALWAYS_ALLOW_LIST:
|
|
120
118
|
await self._allow_local_secrets(credentials)
|
|
121
119
|
|
|
122
120
|
for provider_kind in _PROVIDER_KINDS:
|
|
@@ -331,3 +329,20 @@ class VaultMiddleware(BaseHTTPMiddleware):
|
|
|
331
329
|
status_code=500,
|
|
332
330
|
content=f"Could not verify credentials: unexpected error - {str(exc)}. Please try again later or contact support if the issue persists.",
|
|
333
331
|
) from exc
|
|
332
|
+
|
|
333
|
+
|
|
334
|
+
def _strip_service_prefix(path: str) -> str:
|
|
335
|
+
if not path.startswith("/services/"):
|
|
336
|
+
return path
|
|
337
|
+
|
|
338
|
+
parts = path.split("/", 3)
|
|
339
|
+
if len(parts) < 4:
|
|
340
|
+
return "/"
|
|
341
|
+
|
|
342
|
+
service_name = parts[2]
|
|
343
|
+
remainder = parts[3]
|
|
344
|
+
|
|
345
|
+
if not service_name or not remainder or remainder.startswith("/"):
|
|
346
|
+
return path
|
|
347
|
+
|
|
348
|
+
return f"/{remainder}"
|
|
@@ -127,7 +127,7 @@ class VaultMiddleware:
|
|
|
127
127
|
request: WorkflowServiceRequest,
|
|
128
128
|
call_next: Callable[[WorkflowServiceRequest], Any],
|
|
129
129
|
):
|
|
130
|
-
api_url =
|
|
130
|
+
api_url = ag.DEFAULT_AGENTA_SINGLETON_INSTANCE.api_url
|
|
131
131
|
|
|
132
132
|
with suppress():
|
|
133
133
|
ctx = RunningContext.get()
|
agenta/sdk/models/evaluations.py
CHANGED
|
@@ -53,9 +53,17 @@ class EvaluationStatus(str, Enum):
|
|
|
53
53
|
|
|
54
54
|
|
|
55
55
|
class EvaluationRunFlags(BaseModel):
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
56
|
+
is_live: bool = False # Indicates if the run has live queries
|
|
57
|
+
is_active: bool = False # Indicates if the run is currently active
|
|
58
|
+
is_closed: bool = False # Indicates if the run is modifiable
|
|
59
|
+
#
|
|
60
|
+
has_queries: bool = False # Indicates if the run has queries
|
|
61
|
+
has_testsets: bool = False # Indicates if the run has testsets
|
|
62
|
+
has_evaluators: bool = False # Indicates if the run has evaluators
|
|
63
|
+
#
|
|
64
|
+
has_custom: bool = False # Indicates if the run has custom evaluators
|
|
65
|
+
has_human: bool = False # Indicates if the run has human evaluators
|
|
66
|
+
has_auto: bool = False # Indicates if the run has auto evaluators
|
|
59
67
|
|
|
60
68
|
|
|
61
69
|
class SimpleEvaluationFlags(EvaluationRunFlags):
|
agenta/sdk/models/shared.py
CHANGED
agenta/sdk/tracing/exporters.py
CHANGED