agenta 0.33.0a1__py3-none-any.whl → 0.33.0a3__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.
Potentially problematic release.
This version of agenta might be problematic. Click here for more details.
- agenta/__init__.py +2 -0
- agenta/client/backend/__init__.py +35 -23
- agenta/client/backend/admin/__init__.py +1 -0
- agenta/client/backend/admin/client.py +576 -0
- agenta/client/backend/apps/client.py +384 -2
- agenta/client/backend/client.py +22 -40
- agenta/client/backend/core/http_client.py +3 -3
- agenta/client/backend/evaluations/client.py +0 -6
- agenta/client/backend/human_evaluations/client.py +2 -6
- agenta/client/backend/observability/__init__.py +4 -0
- agenta/client/backend/observability/client.py +221 -744
- agenta/client/backend/testsets/client.py +16 -180
- agenta/client/backend/types/__init__.py +32 -22
- agenta/client/backend/types/account_response.py +24 -0
- agenta/client/backend/types/app_variant_revision.py +2 -1
- agenta/client/backend/types/{create_trace_response.py → legacy_scope_request.py} +3 -4
- agenta/client/backend/types/legacy_scopes_response.py +29 -0
- agenta/client/backend/types/{span_variant.py → legacy_user_request.py} +4 -5
- agenta/client/backend/types/{llm_tokens.py → legacy_user_response.py} +2 -4
- agenta/client/backend/types/{with_pagination.py → organization_membership_request.py} +6 -7
- agenta/client/backend/types/organization_request.py +23 -0
- agenta/client/backend/types/permission.py +4 -0
- agenta/client/backend/types/project_membership_request.py +26 -0
- agenta/client/backend/types/project_request.py +26 -0
- agenta/client/backend/types/project_scope.py +29 -0
- agenta/client/backend/types/provider_kind.py +1 -1
- agenta/client/backend/types/reference.py +22 -0
- agenta/client/backend/types/role.py +15 -0
- agenta/client/backend/types/scopes_response_model.py +22 -0
- agenta/client/backend/types/score.py +1 -1
- agenta/client/backend/types/secret_response_dto.py +2 -2
- agenta/client/backend/types/user_request.py +22 -0
- agenta/client/backend/types/workspace_membership_request.py +26 -0
- agenta/client/backend/types/workspace_request.py +25 -0
- agenta/client/backend/variants/client.py +166 -12
- agenta/client/backend/vault/client.py +11 -9
- agenta/sdk/__init__.py +3 -0
- agenta/sdk/agenta_init.py +3 -1
- agenta/sdk/decorators/routing.py +97 -13
- agenta/sdk/managers/apps.py +64 -0
- agenta/sdk/managers/shared.py +2 -2
- agenta/sdk/middleware/auth.py +156 -57
- agenta/sdk/middleware/config.py +18 -14
- agenta/sdk/middleware/inline.py +1 -1
- agenta/sdk/middleware/mock.py +1 -1
- agenta/sdk/middleware/otel.py +1 -1
- agenta/sdk/middleware/vault.py +1 -1
- {agenta-0.33.0a1.dist-info → agenta-0.33.0a3.dist-info}/METADATA +19 -14
- {agenta-0.33.0a1.dist-info → agenta-0.33.0a3.dist-info}/RECORD +55 -48
- agenta/client/backend/observability_v_1/__init__.py +0 -5
- agenta/client/backend/observability_v_1/client.py +0 -763
- agenta/client/backend/types/create_span.py +0 -45
- agenta/client/backend/types/outputs.py +0 -5
- agenta/client/backend/types/span.py +0 -42
- agenta/client/backend/types/span_detail.py +0 -44
- agenta/client/backend/types/span_status_code.py +0 -5
- agenta/client/backend/types/trace_detail.py +0 -44
- /agenta/client/backend/{observability_v_1 → observability}/types/__init__.py +0 -0
- /agenta/client/backend/{observability_v_1 → observability}/types/format.py +0 -0
- /agenta/client/backend/{observability_v_1 → observability}/types/query_analytics_response.py +0 -0
- /agenta/client/backend/{observability_v_1 → observability}/types/query_traces_response.py +0 -0
- {agenta-0.33.0a1.dist-info → agenta-0.33.0a3.dist-info}/WHEEL +0 -0
- {agenta-0.33.0a1.dist-info → agenta-0.33.0a3.dist-info}/entry_points.txt +0 -0
agenta/sdk/decorators/routing.py
CHANGED
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
from sre_parse import NOT_LITERAL_UNI_IGNORE
|
|
2
1
|
from typing import Type, Any, Callable, Dict, Optional, Tuple, List
|
|
3
2
|
from inspect import signature, iscoroutinefunction, Signature, Parameter
|
|
4
3
|
from functools import wraps
|
|
@@ -6,6 +5,7 @@ from traceback import format_exception
|
|
|
6
5
|
from asyncio import sleep
|
|
7
6
|
from uuid import UUID
|
|
8
7
|
from pydantic import BaseModel, HttpUrl, ValidationError
|
|
8
|
+
from os import environ
|
|
9
9
|
|
|
10
10
|
from fastapi import Body, FastAPI, HTTPException, Request
|
|
11
11
|
|
|
@@ -38,12 +38,18 @@ from agenta.sdk.types import (
|
|
|
38
38
|
|
|
39
39
|
import agenta as ag
|
|
40
40
|
|
|
41
|
-
|
|
42
|
-
app = FastAPI()
|
|
43
41
|
log.setLevel("DEBUG")
|
|
44
42
|
|
|
43
|
+
AGENTA_RUNTIME_PREFIX = environ.get("AGENTA_RUNTIME_PREFIX", "")
|
|
44
|
+
|
|
45
|
+
app = FastAPI(
|
|
46
|
+
docs_url=f"{AGENTA_RUNTIME_PREFIX}/docs", # Swagger UI
|
|
47
|
+
openapi_url=f"{AGENTA_RUNTIME_PREFIX}/openapi.json", # OpenAPI schema
|
|
48
|
+
)
|
|
49
|
+
|
|
50
|
+
app.include_router(router, prefix=AGENTA_RUNTIME_PREFIX)
|
|
45
51
|
|
|
46
|
-
|
|
52
|
+
log.error("Agenta - Runtime Prefix:" + AGENTA_RUNTIME_PREFIX)
|
|
47
53
|
|
|
48
54
|
|
|
49
55
|
class PathValidator(BaseModel):
|
|
@@ -114,13 +120,13 @@ class entrypoint:
|
|
|
114
120
|
routes = list()
|
|
115
121
|
|
|
116
122
|
_middleware = False
|
|
117
|
-
_run_path = "/run"
|
|
118
|
-
_test_path = "/test"
|
|
123
|
+
_run_path = f"{AGENTA_RUNTIME_PREFIX}/run"
|
|
124
|
+
_test_path = f"{AGENTA_RUNTIME_PREFIX}/test"
|
|
119
125
|
_config_key = "ag_config"
|
|
120
126
|
# LEGACY
|
|
121
|
-
_legacy_playground_run_path = "/playground/run"
|
|
122
|
-
_legacy_generate_path = "/generate"
|
|
123
|
-
_legacy_generate_deployed_path = "/generate_deployed"
|
|
127
|
+
_legacy_playground_run_path = f"{AGENTA_RUNTIME_PREFIX}/playground/run"
|
|
128
|
+
_legacy_generate_path = f"{AGENTA_RUNTIME_PREFIX}/generate"
|
|
129
|
+
_legacy_generate_deployed_path = f"{AGENTA_RUNTIME_PREFIX}/generate_deployed"
|
|
124
130
|
|
|
125
131
|
def __init__(
|
|
126
132
|
self,
|
|
@@ -269,17 +275,18 @@ class entrypoint:
|
|
|
269
275
|
)
|
|
270
276
|
# LEGACY
|
|
271
277
|
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
openapi_schema["agenta_sdk"] = {"version": get_current_version()}
|
|
278
|
+
openapi_schema = self.openapi()
|
|
279
|
+
|
|
275
280
|
for _route in entrypoint.routes:
|
|
276
281
|
if _route["config"] is not None:
|
|
277
282
|
self.override_config_in_schema(
|
|
278
283
|
openapi_schema=openapi_schema,
|
|
279
284
|
func_name=_route["func"],
|
|
280
|
-
endpoint=_route["endpoint"],
|
|
285
|
+
endpoint=_route["endpoint"].replace(AGENTA_RUNTIME_PREFIX, ""),
|
|
281
286
|
config=_route["config"],
|
|
282
287
|
)
|
|
288
|
+
|
|
289
|
+
app.openapi_schema = openapi_schema
|
|
283
290
|
### --------------- #
|
|
284
291
|
|
|
285
292
|
def parse_config(self) -> Tuple[Optional[Type[BaseModel]], Dict[str, Any]]:
|
|
@@ -566,6 +573,82 @@ class entrypoint:
|
|
|
566
573
|
)
|
|
567
574
|
)
|
|
568
575
|
|
|
576
|
+
def openapi(self):
|
|
577
|
+
app.openapi_schema = None # Forces FastAPI to re-generate the schema
|
|
578
|
+
|
|
579
|
+
openapi_schema = app.openapi()
|
|
580
|
+
|
|
581
|
+
# ✅ Fix paths by removing the prefix
|
|
582
|
+
updated_paths = {}
|
|
583
|
+
for path, methods in openapi_schema["paths"].items():
|
|
584
|
+
new_path = (
|
|
585
|
+
path[len(AGENTA_RUNTIME_PREFIX) :]
|
|
586
|
+
if path.startswith(AGENTA_RUNTIME_PREFIX)
|
|
587
|
+
else path
|
|
588
|
+
)
|
|
589
|
+
updated_paths[new_path] = methods
|
|
590
|
+
openapi_schema["paths"] = updated_paths # Replace paths
|
|
591
|
+
|
|
592
|
+
# ✅ Fix schema names and update `$ref` references
|
|
593
|
+
if "components" in openapi_schema and "schemas" in openapi_schema["components"]:
|
|
594
|
+
updated_schemas = {}
|
|
595
|
+
schema_name_map = {} # Map old schema names to new schema names
|
|
596
|
+
|
|
597
|
+
for schema_name, schema_value in openapi_schema["components"][
|
|
598
|
+
"schemas"
|
|
599
|
+
].items():
|
|
600
|
+
if AGENTA_RUNTIME_PREFIX and AGENTA_RUNTIME_PREFIX != "":
|
|
601
|
+
new_schema_name = schema_name.replace(
|
|
602
|
+
AGENTA_RUNTIME_PREFIX.lstrip("/").replace("/", "_") + "_", ""
|
|
603
|
+
).strip("_")
|
|
604
|
+
else:
|
|
605
|
+
new_schema_name = schema_name
|
|
606
|
+
updated_schemas[new_schema_name] = schema_value
|
|
607
|
+
schema_name_map[schema_name] = new_schema_name # Store mapping
|
|
608
|
+
|
|
609
|
+
# ✅ Fix `$ref` references
|
|
610
|
+
for path, methods in updated_paths.items():
|
|
611
|
+
for method in methods.values():
|
|
612
|
+
if "requestBody" in method and "content" in method["requestBody"]:
|
|
613
|
+
for content_type, content in method["requestBody"][
|
|
614
|
+
"content"
|
|
615
|
+
].items():
|
|
616
|
+
if "$ref" in content["schema"]:
|
|
617
|
+
old_ref = content["schema"]["$ref"]
|
|
618
|
+
schema_name = old_ref.split("/")[
|
|
619
|
+
-1
|
|
620
|
+
] # Extract schema name
|
|
621
|
+
if schema_name in schema_name_map:
|
|
622
|
+
content["schema"][
|
|
623
|
+
"$ref"
|
|
624
|
+
] = f"#/components/schemas/{schema_name_map[schema_name]}"
|
|
625
|
+
|
|
626
|
+
if "responses" in method:
|
|
627
|
+
for status_code, response in method["responses"].items():
|
|
628
|
+
if "content" in response:
|
|
629
|
+
for content_type, content in response[
|
|
630
|
+
"content"
|
|
631
|
+
].items():
|
|
632
|
+
if "$ref" in content["schema"]:
|
|
633
|
+
old_ref = content["schema"]["$ref"]
|
|
634
|
+
schema_name = old_ref.split("/")[
|
|
635
|
+
-1
|
|
636
|
+
] # Extract schema name
|
|
637
|
+
if schema_name in schema_name_map:
|
|
638
|
+
content["schema"][
|
|
639
|
+
"$ref"
|
|
640
|
+
] = f"#/components/schemas/{schema_name_map[schema_name]}"
|
|
641
|
+
|
|
642
|
+
# ✅ Update OpenAPI schema with fixed schemas
|
|
643
|
+
openapi_schema["components"]["schemas"] = updated_schemas
|
|
644
|
+
|
|
645
|
+
# ✅ Add Agenta SDK version info
|
|
646
|
+
openapi_schema["agenta_sdk"] = {"version": get_current_version()}
|
|
647
|
+
|
|
648
|
+
print(openapi_schema)
|
|
649
|
+
|
|
650
|
+
return openapi_schema
|
|
651
|
+
|
|
569
652
|
def override_config_in_schema(
|
|
570
653
|
self,
|
|
571
654
|
openapi_schema: dict,
|
|
@@ -575,6 +658,7 @@ class entrypoint:
|
|
|
575
658
|
):
|
|
576
659
|
"""Override config in OpenAPI schema to add agenta-specific metadata."""
|
|
577
660
|
endpoint = endpoint[1:].replace("/", "_")
|
|
661
|
+
|
|
578
662
|
schema_key = f"Body_{func_name}_{endpoint}_post"
|
|
579
663
|
schema_to_override = openapi_schema["components"]["schemas"][schema_key]
|
|
580
664
|
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
import logging
|
|
2
|
+
|
|
3
|
+
from agenta.sdk.utils.exceptions import handle_exceptions
|
|
4
|
+
|
|
5
|
+
import agenta as ag
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
logger = logging.getLogger(__name__)
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
class AppManager:
|
|
12
|
+
@classmethod
|
|
13
|
+
@handle_exceptions()
|
|
14
|
+
def create(cls, *, app_slug: str, template_key: str):
|
|
15
|
+
app_response = ag.api.apps.create_app(
|
|
16
|
+
app_name=app_slug, template_key=template_key
|
|
17
|
+
)
|
|
18
|
+
return app_response
|
|
19
|
+
|
|
20
|
+
@classmethod
|
|
21
|
+
@handle_exceptions()
|
|
22
|
+
async def acreate(cls, *, app_slug: str, template_key: str):
|
|
23
|
+
app_response = await ag.async_api.apps.create_app(
|
|
24
|
+
app_name=app_slug, template_key=template_key
|
|
25
|
+
)
|
|
26
|
+
return app_response
|
|
27
|
+
|
|
28
|
+
@classmethod
|
|
29
|
+
@handle_exceptions()
|
|
30
|
+
def list(cls):
|
|
31
|
+
apps_response = ag.api.apps.list_apps()
|
|
32
|
+
return apps_response
|
|
33
|
+
|
|
34
|
+
@classmethod
|
|
35
|
+
@handle_exceptions()
|
|
36
|
+
async def alist(cls):
|
|
37
|
+
apps_response = await ag.async_api.apps.list_apps()
|
|
38
|
+
return apps_response
|
|
39
|
+
|
|
40
|
+
@classmethod
|
|
41
|
+
@handle_exceptions()
|
|
42
|
+
def update(cls, *, app_id: str, app_slug: str):
|
|
43
|
+
app_response = ag.api.apps.update_app(app_id=app_id, app_name=app_slug)
|
|
44
|
+
return app_response
|
|
45
|
+
|
|
46
|
+
@classmethod
|
|
47
|
+
@handle_exceptions()
|
|
48
|
+
async def aupdate(cls, *, app_id: str, app_slug: str):
|
|
49
|
+
app_response = await ag.async_api.apps.update_app(
|
|
50
|
+
app_id=app_id, app_name=app_slug
|
|
51
|
+
)
|
|
52
|
+
return app_response
|
|
53
|
+
|
|
54
|
+
@classmethod
|
|
55
|
+
@handle_exceptions()
|
|
56
|
+
def delete(cls, *, app_id: str):
|
|
57
|
+
ag.api.apps.remove_app(app_id=app_id)
|
|
58
|
+
return None
|
|
59
|
+
|
|
60
|
+
@classmethod
|
|
61
|
+
@handle_exceptions()
|
|
62
|
+
async def adelete(cls, *, app_id: str):
|
|
63
|
+
await ag.async_api.apps.remove_app(app_id=app_id)
|
|
64
|
+
return None
|
agenta/sdk/managers/shared.py
CHANGED
|
@@ -505,12 +505,12 @@ class SharedManager:
|
|
|
505
505
|
slug=variant_slug,
|
|
506
506
|
version=None,
|
|
507
507
|
id=None,
|
|
508
|
-
),
|
|
508
|
+
).model_dump(),
|
|
509
509
|
application_ref=SharedManager._ref_or_none( # type: ignore # type: ignore
|
|
510
510
|
slug=app_slug,
|
|
511
511
|
version=None,
|
|
512
512
|
id=app_id,
|
|
513
|
-
),
|
|
513
|
+
).model_dump(),
|
|
514
514
|
)
|
|
515
515
|
)
|
|
516
516
|
|
agenta/sdk/middleware/auth.py
CHANGED
|
@@ -11,16 +11,16 @@ from fastapi.responses import JSONResponse
|
|
|
11
11
|
from agenta.sdk.middleware.cache import TTLLRUCache, CACHE_CAPACITY, CACHE_TTL
|
|
12
12
|
from agenta.sdk.utils.constants import TRUTHY
|
|
13
13
|
from agenta.sdk.utils.exceptions import display_exception
|
|
14
|
+
from agenta.sdk.utils.logging import log
|
|
14
15
|
|
|
15
16
|
import agenta as ag
|
|
16
17
|
|
|
18
|
+
AGENTA_RUNTIME_PREFIX = getenv("AGENTA_RUNTIME_PREFIX", "")
|
|
17
19
|
|
|
18
|
-
|
|
19
|
-
_CACHE_ENABLED = getenv("AGENTA_MIDDLEWARE_CACHE_ENABLED", "
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
)
|
|
23
|
-
_ALWAYS_ALLOW_LIST = ["/health"]
|
|
20
|
+
|
|
21
|
+
_CACHE_ENABLED = getenv("AGENTA_MIDDLEWARE_CACHE_ENABLED", "false").lower() in TRUTHY
|
|
22
|
+
|
|
23
|
+
_ALWAYS_ALLOW_LIST = [f"{AGENTA_RUNTIME_PREFIX}/health"]
|
|
24
24
|
|
|
25
25
|
_cache = TTLLRUCache(capacity=CACHE_CAPACITY, ttl=CACHE_TTL)
|
|
26
26
|
|
|
@@ -54,15 +54,49 @@ class AuthMiddleware(BaseHTTPMiddleware):
|
|
|
54
54
|
super().__init__(app)
|
|
55
55
|
|
|
56
56
|
self.host = ag.DEFAULT_AGENTA_SINGLETON_INSTANCE.host
|
|
57
|
-
self.resource_id =
|
|
58
|
-
ag.DEFAULT_AGENTA_SINGLETON_INSTANCE.service_id
|
|
59
|
-
if not _SHARED_SERVICE
|
|
60
|
-
else None
|
|
61
|
-
)
|
|
57
|
+
self.resource_id = ag.DEFAULT_AGENTA_SINGLETON_INSTANCE.service_id
|
|
62
58
|
|
|
63
59
|
async def dispatch(self, request: Request, call_next: Callable):
|
|
60
|
+
# Extract request details
|
|
61
|
+
host = request.client.host if request.client else "unknown"
|
|
62
|
+
path = request.url.path
|
|
63
|
+
query = dict(request.query_params)
|
|
64
|
+
headers = dict(request.headers)
|
|
65
|
+
|
|
66
|
+
import logging
|
|
67
|
+
import json
|
|
68
|
+
|
|
69
|
+
# Log the request details
|
|
70
|
+
logging.error(
|
|
71
|
+
json.dumps(
|
|
72
|
+
{
|
|
73
|
+
"host": host,
|
|
74
|
+
"method": request.method,
|
|
75
|
+
"path": path,
|
|
76
|
+
"query_params": query,
|
|
77
|
+
"headers": headers,
|
|
78
|
+
},
|
|
79
|
+
indent=2,
|
|
80
|
+
ensure_ascii=False,
|
|
81
|
+
)
|
|
82
|
+
)
|
|
83
|
+
|
|
84
|
+
print(
|
|
85
|
+
json.dumps(
|
|
86
|
+
{
|
|
87
|
+
"host": host,
|
|
88
|
+
"method": request.method,
|
|
89
|
+
"path": path,
|
|
90
|
+
"query_params": query,
|
|
91
|
+
"headers": headers,
|
|
92
|
+
},
|
|
93
|
+
indent=2,
|
|
94
|
+
ensure_ascii=False,
|
|
95
|
+
)
|
|
96
|
+
)
|
|
97
|
+
|
|
64
98
|
try:
|
|
65
|
-
if
|
|
99
|
+
if request.url.path in _ALWAYS_ALLOW_LIST:
|
|
66
100
|
request.state.auth = {}
|
|
67
101
|
|
|
68
102
|
else:
|
|
@@ -98,11 +132,10 @@ class AuthMiddleware(BaseHTTPMiddleware):
|
|
|
98
132
|
|
|
99
133
|
cookies = {"sAccessToken": access_token} if access_token else None
|
|
100
134
|
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
)
|
|
135
|
+
if not headers and not cookies:
|
|
136
|
+
log.debug("No auth header nor auth cookie found in the request")
|
|
137
|
+
|
|
138
|
+
baggage = request.state.otel["baggage"]
|
|
106
139
|
|
|
107
140
|
project_id = (
|
|
108
141
|
# CLEANEST
|
|
@@ -111,6 +144,9 @@ class AuthMiddleware(BaseHTTPMiddleware):
|
|
|
111
144
|
or request.query_params.get("project_id")
|
|
112
145
|
)
|
|
113
146
|
|
|
147
|
+
if not project_id:
|
|
148
|
+
log.debug("No project ID found in request")
|
|
149
|
+
|
|
114
150
|
params = {"action": "run_service", "resource_type": "service"}
|
|
115
151
|
|
|
116
152
|
if self.resource_id:
|
|
@@ -132,53 +168,116 @@ class AuthMiddleware(BaseHTTPMiddleware):
|
|
|
132
168
|
credentials = _cache.get(_hash)
|
|
133
169
|
|
|
134
170
|
if credentials:
|
|
171
|
+
log.debug("Using cached credentials")
|
|
135
172
|
return credentials
|
|
136
173
|
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
174
|
+
try:
|
|
175
|
+
async with httpx.AsyncClient() as client:
|
|
176
|
+
try:
|
|
177
|
+
response = await client.get(
|
|
178
|
+
f"{self.host}/api/permissions/verify",
|
|
179
|
+
headers=headers,
|
|
180
|
+
cookies=cookies,
|
|
181
|
+
params=params,
|
|
182
|
+
timeout=30.0,
|
|
183
|
+
)
|
|
184
|
+
except httpx.TimeoutException as exc:
|
|
185
|
+
log.debug(f"Timeout error while verify credentials: {exc}")
|
|
186
|
+
raise DenyException(
|
|
187
|
+
status_code=504,
|
|
188
|
+
content="Could not verify credentials: connection to {self.host} timed out. Please check your network connection.",
|
|
189
|
+
) from exc
|
|
190
|
+
except httpx.ConnectError as exc:
|
|
191
|
+
log.debug(f"Connection error while verify credentials: {exc}")
|
|
192
|
+
raise DenyException(
|
|
193
|
+
status_code=503,
|
|
194
|
+
content=f"Could not verify credentials: connection to {self.host} failed. Please check if agenta is available.",
|
|
195
|
+
) from exc
|
|
196
|
+
except httpx.NetworkError as exc:
|
|
197
|
+
log.debug(f"Network error while verify credentials: {exc}")
|
|
198
|
+
raise DenyException(
|
|
199
|
+
status_code=503,
|
|
200
|
+
content="Could not verify credentials: connection to {self.host} failed. Please check your network connection.",
|
|
201
|
+
) from exc
|
|
202
|
+
except httpx.HTTPError as exc:
|
|
203
|
+
log.debug(f"HTTP error while verify credentials: {exc}")
|
|
204
|
+
raise DenyException(
|
|
205
|
+
status_code=502,
|
|
206
|
+
content=f"Could not verify credentials: connection to {self.host} failed. Please check if agenta is available.",
|
|
207
|
+
) from exc
|
|
208
|
+
|
|
209
|
+
if response.status_code == 401:
|
|
210
|
+
log.debug("Agenta returned 401 - Invalid credentials")
|
|
211
|
+
raise DenyException(
|
|
212
|
+
status_code=401,
|
|
213
|
+
content="Invalid credentials. Please check your credentials or login again.",
|
|
214
|
+
)
|
|
215
|
+
elif response.status_code == 403:
|
|
216
|
+
log.debug("Agenta returned 403 - Permission denied")
|
|
217
|
+
raise DenyException(
|
|
218
|
+
status_code=403,
|
|
219
|
+
content="Permission denied. Please check your permissions or contact your administrator.",
|
|
220
|
+
)
|
|
221
|
+
elif response.status_code != 200:
|
|
222
|
+
log.debug(
|
|
223
|
+
f"Agenta returned {response.status_code} - Unexpected status code"
|
|
224
|
+
)
|
|
225
|
+
raise DenyException(
|
|
226
|
+
status_code=500,
|
|
227
|
+
content=f"Could no verify credentials: {self.host} returned unexpected status code {response.status_code}. Please try again later or contact support if the issue persists.",
|
|
228
|
+
)
|
|
229
|
+
|
|
230
|
+
try:
|
|
231
|
+
auth = response.json()
|
|
232
|
+
except ValueError as exc:
|
|
233
|
+
log.debug(f"Agenta returned invalid JSON response: {exc}")
|
|
234
|
+
raise DenyException(
|
|
235
|
+
status_code=500,
|
|
236
|
+
content=f"Could no verify credentials: {self.host} returned unexpected invalid JSON response. Please try again later or contact support if the issue persists.",
|
|
237
|
+
) from exc
|
|
238
|
+
|
|
239
|
+
if not isinstance(auth, dict):
|
|
240
|
+
log.debug(
|
|
241
|
+
f"Agenta returned invalid response format: {type(auth)}"
|
|
242
|
+
)
|
|
243
|
+
raise DenyException(
|
|
244
|
+
status_code=500,
|
|
245
|
+
content=f"Could no verify credentials: {self.host} returned unexpected invalid response format. Please try again later or contact support if the issue persists.",
|
|
246
|
+
)
|
|
247
|
+
|
|
248
|
+
effect = auth.get("effect")
|
|
249
|
+
if effect != "allow":
|
|
250
|
+
log.debug("Access denied by Agenta - effect: {effect}")
|
|
251
|
+
raise DenyException(
|
|
252
|
+
status_code=403,
|
|
253
|
+
content="Permission denied. Please check your permissions or contact your administrator.",
|
|
254
|
+
)
|
|
255
|
+
|
|
256
|
+
credentials = auth.get("credentials")
|
|
257
|
+
|
|
258
|
+
if not credentials:
|
|
259
|
+
log.debug("No credentials found in the response")
|
|
260
|
+
|
|
261
|
+
_cache.put(_hash, credentials)
|
|
162
262
|
|
|
163
|
-
|
|
164
|
-
raise DenyException(
|
|
165
|
-
status_code=403,
|
|
166
|
-
content="Service execution not allowed.",
|
|
167
|
-
)
|
|
168
|
-
|
|
169
|
-
credentials = auth.get("credentials")
|
|
170
|
-
|
|
171
|
-
_cache.put(_hash, credentials)
|
|
263
|
+
return credentials
|
|
172
264
|
|
|
173
|
-
|
|
265
|
+
except DenyException as deny:
|
|
266
|
+
raise deny
|
|
267
|
+
except Exception as exc: # pylint: disable=bare-except
|
|
268
|
+
log.debug(
|
|
269
|
+
f"Unexpected error while verifying credentials (remote): {exc}"
|
|
270
|
+
)
|
|
271
|
+
raise DenyException(
|
|
272
|
+
status_code=500,
|
|
273
|
+
content=f"Could no verify credentials: unexpected error - {str(exc)}. Please try again later or contact support if the issue persists.",
|
|
274
|
+
) from exc
|
|
174
275
|
|
|
175
276
|
except DenyException as deny:
|
|
176
277
|
raise deny
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
display_exception("Auth Middleware Exception (suppressed)")
|
|
180
|
-
|
|
278
|
+
except Exception as exc:
|
|
279
|
+
log.debug(f"Unexpected error while verifying credentials (local): {exc}")
|
|
181
280
|
raise DenyException(
|
|
182
281
|
status_code=500,
|
|
183
|
-
content="
|
|
282
|
+
content=f"Could no verify credentials: unexpected error - {str(exc)}. Please try again later or contact support if the issue persists.",
|
|
184
283
|
) from exc
|
agenta/sdk/middleware/config.py
CHANGED
|
@@ -17,7 +17,7 @@ from agenta.sdk.utils.exceptions import suppress
|
|
|
17
17
|
import agenta as ag
|
|
18
18
|
|
|
19
19
|
|
|
20
|
-
_CACHE_ENABLED = getenv("AGENTA_MIDDLEWARE_CACHE_ENABLED", "
|
|
20
|
+
_CACHE_ENABLED = getenv("AGENTA_MIDDLEWARE_CACHE_ENABLED", "false").lower() in TRUTHY
|
|
21
21
|
|
|
22
22
|
_cache = TTLLRUCache(capacity=CACHE_CAPACITY, ttl=CACHE_TTL)
|
|
23
23
|
|
|
@@ -92,7 +92,7 @@ class ConfigMiddleware(BaseHTTPMiddleware):
|
|
|
92
92
|
|
|
93
93
|
return parameters, references
|
|
94
94
|
|
|
95
|
-
config =
|
|
95
|
+
config = {}
|
|
96
96
|
async with httpx.AsyncClient() as client:
|
|
97
97
|
response = await client.post(
|
|
98
98
|
f"{self.host}/api/variants/configs/fetch",
|
|
@@ -100,21 +100,25 @@ class ConfigMiddleware(BaseHTTPMiddleware):
|
|
|
100
100
|
json=refs,
|
|
101
101
|
)
|
|
102
102
|
|
|
103
|
-
if response.status_code
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
config = response.json()
|
|
103
|
+
if response.status_code == 200:
|
|
104
|
+
config = response.json()
|
|
107
105
|
|
|
108
106
|
if not config:
|
|
109
|
-
|
|
107
|
+
config["application_ref"] = refs[
|
|
108
|
+
"application_ref"
|
|
109
|
+
] # by default, application_ref will always have an id
|
|
110
|
+
parameters = None
|
|
111
|
+
else:
|
|
112
|
+
parameters = config.get("params")
|
|
110
113
|
|
|
111
|
-
|
|
114
|
+
references = {}
|
|
112
115
|
|
|
113
|
-
|
|
116
|
+
ref_keys = ["application_ref"]
|
|
114
117
|
|
|
115
|
-
|
|
118
|
+
if config:
|
|
119
|
+
ref_keys.extend(["variant_ref", "environment_ref"])
|
|
116
120
|
|
|
117
|
-
for ref_key in
|
|
121
|
+
for ref_key in ref_keys:
|
|
118
122
|
refs = config.get(ref_key)
|
|
119
123
|
if refs:
|
|
120
124
|
ref_prefix = ref_key.split("_", maxsplit=1)[0]
|
|
@@ -133,7 +137,7 @@ class ConfigMiddleware(BaseHTTPMiddleware):
|
|
|
133
137
|
self,
|
|
134
138
|
request: Request,
|
|
135
139
|
) -> Optional[Reference]:
|
|
136
|
-
baggage = request.state.otel
|
|
140
|
+
baggage = request.state.otel["baggage"]
|
|
137
141
|
|
|
138
142
|
body = {}
|
|
139
143
|
try:
|
|
@@ -180,7 +184,7 @@ class ConfigMiddleware(BaseHTTPMiddleware):
|
|
|
180
184
|
self,
|
|
181
185
|
request: Request,
|
|
182
186
|
) -> Optional[Reference]:
|
|
183
|
-
baggage = request.state.otel
|
|
187
|
+
baggage = request.state.otel["baggage"]
|
|
184
188
|
|
|
185
189
|
body = {}
|
|
186
190
|
try:
|
|
@@ -223,7 +227,7 @@ class ConfigMiddleware(BaseHTTPMiddleware):
|
|
|
223
227
|
self,
|
|
224
228
|
request: Request,
|
|
225
229
|
) -> Optional[Reference]:
|
|
226
|
-
baggage = request.state.otel
|
|
230
|
+
baggage = request.state.otel["baggage"]
|
|
227
231
|
|
|
228
232
|
body = {}
|
|
229
233
|
try:
|
agenta/sdk/middleware/inline.py
CHANGED
agenta/sdk/middleware/mock.py
CHANGED
agenta/sdk/middleware/otel.py
CHANGED
|
@@ -13,7 +13,7 @@ class OTelMiddleware(BaseHTTPMiddleware):
|
|
|
13
13
|
super().__init__(app)
|
|
14
14
|
|
|
15
15
|
async def dispatch(self, request: Request, call_next: Callable):
|
|
16
|
-
request.state.otel = {}
|
|
16
|
+
request.state.otel = {"baggage": {}}
|
|
17
17
|
|
|
18
18
|
with suppress():
|
|
19
19
|
baggage = await self._get_baggage(request)
|
agenta/sdk/middleware/vault.py
CHANGED
|
@@ -24,7 +24,7 @@ for arg in ProviderKind.__args__: # type: ignore
|
|
|
24
24
|
if hasattr(arg, "__args__"):
|
|
25
25
|
_PROVIDER_KINDS.extend(arg.__args__)
|
|
26
26
|
|
|
27
|
-
_CACHE_ENABLED = getenv("AGENTA_MIDDLEWARE_CACHE_ENABLED", "
|
|
27
|
+
_CACHE_ENABLED = getenv("AGENTA_MIDDLEWARE_CACHE_ENABLED", "false").lower() in TRUTHY
|
|
28
28
|
|
|
29
29
|
_cache = TTLLRUCache(capacity=CACHE_CAPACITY, ttl=CACHE_TTL)
|
|
30
30
|
|