agenta 0.12.3__py3-none-any.whl → 0.32.0a1__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.

Files changed (244) hide show
  1. agenta/__init__.py +64 -7
  2. agenta/cli/helper.py +7 -3
  3. agenta/cli/main.py +15 -50
  4. agenta/cli/variant_commands.py +50 -29
  5. agenta/client/Readme.md +72 -64
  6. agenta/client/api.py +2 -2
  7. agenta/client/backend/__init__.py +193 -22
  8. agenta/client/backend/access_control/__init__.py +1 -0
  9. agenta/client/backend/access_control/client.py +167 -0
  10. agenta/client/backend/apps/__init__.py +1 -0
  11. agenta/client/backend/apps/client.py +1691 -0
  12. agenta/client/backend/bases/__init__.py +1 -0
  13. agenta/client/backend/bases/client.py +190 -0
  14. agenta/client/backend/client.py +2508 -5712
  15. agenta/client/backend/configs/__init__.py +1 -0
  16. agenta/client/backend/configs/client.py +604 -0
  17. agenta/client/backend/containers/__init__.py +5 -0
  18. agenta/client/backend/containers/client.py +648 -0
  19. agenta/client/backend/containers/types/__init__.py +5 -0
  20. agenta/client/backend/{types → containers/types}/container_templates_response.py +1 -2
  21. agenta/client/backend/core/__init__.py +30 -0
  22. agenta/client/backend/core/client_wrapper.py +42 -9
  23. agenta/client/backend/core/file.py +70 -0
  24. agenta/client/backend/core/http_client.py +575 -0
  25. agenta/client/backend/core/jsonable_encoder.py +33 -39
  26. agenta/client/backend/core/pydantic_utilities.py +325 -0
  27. agenta/client/backend/core/query_encoder.py +60 -0
  28. agenta/client/backend/core/remove_none_from_dict.py +2 -2
  29. agenta/client/backend/core/request_options.py +35 -0
  30. agenta/client/backend/core/serialization.py +276 -0
  31. agenta/client/backend/environments/__init__.py +1 -0
  32. agenta/client/backend/environments/client.py +196 -0
  33. agenta/client/backend/evaluations/__init__.py +1 -0
  34. agenta/client/backend/evaluations/client.py +1469 -0
  35. agenta/client/backend/evaluators/__init__.py +1 -0
  36. agenta/client/backend/evaluators/client.py +1283 -0
  37. agenta/client/backend/observability/__init__.py +1 -0
  38. agenta/client/backend/observability/client.py +1286 -0
  39. agenta/client/backend/observability_v_1/__init__.py +5 -0
  40. agenta/client/backend/observability_v_1/client.py +763 -0
  41. agenta/client/backend/observability_v_1/types/__init__.py +7 -0
  42. agenta/client/backend/observability_v_1/types/format.py +5 -0
  43. agenta/client/backend/observability_v_1/types/query_analytics_response.py +7 -0
  44. agenta/client/backend/observability_v_1/types/query_traces_response.py +11 -0
  45. agenta/client/backend/scopes/__init__.py +1 -0
  46. agenta/client/backend/scopes/client.py +114 -0
  47. agenta/client/backend/testsets/__init__.py +1 -0
  48. agenta/client/backend/testsets/client.py +1284 -0
  49. agenta/client/backend/types/__init__.py +154 -26
  50. agenta/client/backend/types/agenta_node_dto.py +48 -0
  51. agenta/client/backend/types/agenta_node_dto_nodes_value.py +6 -0
  52. agenta/client/backend/types/agenta_nodes_response.py +30 -0
  53. agenta/client/backend/types/agenta_root_dto.py +30 -0
  54. agenta/client/backend/types/agenta_roots_response.py +30 -0
  55. agenta/client/backend/types/agenta_tree_dto.py +30 -0
  56. agenta/client/backend/types/agenta_trees_response.py +30 -0
  57. agenta/client/backend/types/aggregated_result.py +16 -31
  58. agenta/client/backend/types/aggregated_result_evaluator_config.py +8 -0
  59. agenta/client/backend/types/analytics_response.py +24 -0
  60. agenta/client/backend/types/app.py +17 -30
  61. agenta/client/backend/types/app_variant_response.py +36 -0
  62. agenta/client/backend/types/app_variant_revision.py +17 -32
  63. agenta/client/backend/types/base_output.py +13 -28
  64. agenta/client/backend/types/body_import_testset.py +15 -31
  65. agenta/client/backend/types/bucket_dto.py +26 -0
  66. agenta/client/backend/types/collect_status_response.py +22 -0
  67. agenta/client/backend/types/config_db.py +16 -31
  68. agenta/client/backend/types/config_dto.py +32 -0
  69. agenta/client/backend/types/config_response_model.py +32 -0
  70. agenta/client/backend/types/correct_answer.py +22 -0
  71. agenta/client/backend/types/create_app_output.py +13 -28
  72. agenta/client/backend/types/create_span.py +45 -0
  73. agenta/client/backend/types/create_trace_response.py +22 -0
  74. agenta/client/backend/types/docker_env_vars.py +13 -28
  75. agenta/client/backend/types/environment_output.py +22 -34
  76. agenta/client/backend/types/environment_output_extended.py +31 -0
  77. agenta/client/backend/types/environment_revision.py +26 -0
  78. agenta/client/backend/types/error.py +22 -0
  79. agenta/client/backend/types/evaluation.py +22 -33
  80. agenta/client/backend/types/evaluation_scenario.py +18 -33
  81. agenta/client/backend/types/evaluation_scenario_input.py +16 -31
  82. agenta/client/backend/types/evaluation_scenario_output.py +17 -30
  83. agenta/client/backend/types/evaluation_scenario_result.py +14 -29
  84. agenta/client/backend/types/evaluation_scenario_score_update.py +21 -0
  85. agenta/client/backend/types/evaluation_status_enum.py +11 -29
  86. agenta/client/backend/types/evaluation_type.py +3 -21
  87. agenta/client/backend/types/evaluator.py +20 -31
  88. agenta/client/backend/types/evaluator_config.py +21 -33
  89. agenta/client/backend/types/evaluator_mapping_output_interface.py +21 -0
  90. agenta/client/backend/types/evaluator_output_interface.py +21 -0
  91. agenta/client/backend/types/exception_dto.py +26 -0
  92. agenta/client/backend/types/get_config_response.py +23 -0
  93. agenta/client/backend/types/header_dto.py +22 -0
  94. agenta/client/backend/types/http_validation_error.py +14 -29
  95. agenta/client/backend/types/human_evaluation.py +18 -34
  96. agenta/client/backend/types/human_evaluation_scenario.py +22 -38
  97. agenta/client/backend/types/human_evaluation_scenario_input.py +13 -28
  98. agenta/client/backend/types/human_evaluation_scenario_output.py +13 -28
  99. agenta/client/backend/types/human_evaluation_scenario_update.py +30 -0
  100. agenta/client/backend/types/human_evaluation_update.py +22 -0
  101. agenta/client/backend/types/image.py +18 -32
  102. agenta/client/backend/types/invite_request.py +16 -30
  103. agenta/client/backend/types/legacy_analytics_response.py +29 -0
  104. agenta/client/backend/types/legacy_data_point.py +27 -0
  105. agenta/client/backend/types/lifecycle_dto.py +24 -0
  106. agenta/client/backend/types/link_dto.py +24 -0
  107. agenta/client/backend/types/list_api_keys_response.py +24 -0
  108. agenta/client/backend/types/llm_run_rate_limit.py +13 -28
  109. agenta/client/backend/types/llm_tokens.py +23 -0
  110. agenta/client/backend/types/metrics_dto.py +24 -0
  111. agenta/client/backend/types/new_human_evaluation.py +27 -0
  112. agenta/client/backend/types/new_testset.py +16 -31
  113. agenta/client/backend/types/node_dto.py +24 -0
  114. agenta/client/backend/types/node_type.py +19 -0
  115. agenta/client/backend/types/o_tel_context_dto.py +22 -0
  116. agenta/client/backend/types/o_tel_event_dto.py +23 -0
  117. agenta/client/backend/types/o_tel_extra_dto.py +26 -0
  118. agenta/client/backend/types/o_tel_link_dto.py +23 -0
  119. agenta/client/backend/types/o_tel_span_dto.py +37 -0
  120. agenta/client/backend/types/o_tel_span_kind.py +15 -0
  121. agenta/client/backend/types/o_tel_spans_response.py +24 -0
  122. agenta/client/backend/types/o_tel_status_code.py +8 -0
  123. agenta/client/backend/types/organization.py +22 -35
  124. agenta/client/backend/types/organization_output.py +13 -28
  125. agenta/client/backend/types/outputs.py +5 -0
  126. agenta/client/backend/types/parent_dto.py +21 -0
  127. agenta/client/backend/types/permission.py +41 -0
  128. agenta/client/backend/types/projects_response.py +28 -0
  129. agenta/client/backend/types/provider_key_dto.py +23 -0
  130. agenta/client/backend/types/provider_kind.py +21 -0
  131. agenta/client/backend/types/reference_dto.py +23 -0
  132. agenta/client/backend/types/reference_request_model.py +23 -0
  133. agenta/client/backend/types/result.py +18 -31
  134. agenta/client/backend/types/root_dto.py +21 -0
  135. agenta/client/backend/types/{human_evaluation_scenario_score.py → score.py} +1 -1
  136. agenta/client/backend/types/secret_dto.py +24 -0
  137. agenta/client/backend/types/{human_evaluation_scenario_update_score.py → secret_kind.py} +1 -1
  138. agenta/client/backend/types/secret_response_dto.py +27 -0
  139. agenta/client/backend/types/simple_evaluation_output.py +13 -28
  140. agenta/client/backend/types/span.py +39 -49
  141. agenta/client/backend/types/span_detail.py +44 -0
  142. agenta/client/backend/types/span_dto.py +54 -0
  143. agenta/client/backend/types/span_dto_nodes_value.py +9 -0
  144. agenta/client/backend/types/span_status_code.py +5 -0
  145. agenta/client/backend/types/span_variant.py +23 -0
  146. agenta/client/backend/types/status_code.py +5 -0
  147. agenta/client/backend/types/status_dto.py +23 -0
  148. agenta/client/backend/types/template.py +14 -29
  149. agenta/client/backend/types/template_image_info.py +21 -35
  150. agenta/client/backend/types/test_set_output_response.py +20 -33
  151. agenta/client/backend/types/test_set_simple_response.py +13 -28
  152. agenta/client/backend/types/time_dto.py +23 -0
  153. agenta/client/backend/types/trace_detail.py +44 -0
  154. agenta/client/backend/types/tree_dto.py +23 -0
  155. agenta/client/backend/types/tree_type.py +5 -0
  156. agenta/client/backend/types/update_app_output.py +22 -0
  157. agenta/client/backend/types/uri.py +13 -28
  158. agenta/client/backend/types/validation_error.py +13 -28
  159. agenta/client/backend/types/variant_action.py +14 -29
  160. agenta/client/backend/types/variant_action_enum.py +1 -19
  161. agenta/client/backend/types/with_pagination.py +26 -0
  162. agenta/client/backend/types/workspace_member_response.py +23 -0
  163. agenta/client/backend/types/workspace_permission.py +25 -0
  164. agenta/client/backend/types/workspace_response.py +29 -0
  165. agenta/client/backend/types/workspace_role.py +15 -0
  166. agenta/client/backend/types/workspace_role_response.py +23 -0
  167. agenta/client/backend/variants/__init__.py +5 -0
  168. agenta/client/backend/variants/client.py +2814 -0
  169. agenta/client/backend/variants/types/__init__.py +7 -0
  170. agenta/client/backend/variants/types/add_variant_from_base_and_config_response.py +8 -0
  171. agenta/client/backend/vault/__init__.py +1 -0
  172. agenta/client/backend/vault/client.py +685 -0
  173. agenta/client/client.py +1 -1
  174. agenta/config.py +0 -2
  175. agenta/config.toml +0 -1
  176. agenta/docker/docker-assets/Dockerfile.cloud.template +2 -1
  177. agenta/docker/docker-assets/Dockerfile.template +2 -1
  178. agenta/docker/docker_utils.py +11 -12
  179. agenta/sdk/__init__.py +58 -7
  180. agenta/sdk/agenta_init.py +182 -164
  181. agenta/sdk/assets.py +95 -0
  182. agenta/sdk/client.py +56 -0
  183. agenta/sdk/context/__init__.py +0 -0
  184. agenta/sdk/context/exporting.py +25 -0
  185. agenta/sdk/context/routing.py +27 -0
  186. agenta/sdk/context/tracing.py +28 -0
  187. agenta/sdk/decorators/__init__.py +0 -0
  188. agenta/sdk/decorators/routing.py +576 -0
  189. agenta/sdk/decorators/tracing.py +296 -0
  190. agenta/sdk/litellm/__init__.py +1 -0
  191. agenta/sdk/litellm/litellm.py +314 -0
  192. agenta/sdk/litellm/mockllm.py +27 -0
  193. agenta/sdk/litellm/mocks/__init__.py +26 -0
  194. agenta/sdk/managers/__init__.py +6 -0
  195. agenta/sdk/managers/config.py +208 -0
  196. agenta/sdk/managers/deployment.py +45 -0
  197. agenta/sdk/managers/secrets.py +38 -0
  198. agenta/sdk/managers/shared.py +639 -0
  199. agenta/sdk/managers/variant.py +182 -0
  200. agenta/sdk/managers/vault.py +16 -0
  201. agenta/sdk/middleware/__init__.py +0 -0
  202. agenta/sdk/middleware/auth.py +180 -0
  203. agenta/sdk/middleware/cache.py +47 -0
  204. agenta/sdk/middleware/config.py +255 -0
  205. agenta/sdk/middleware/cors.py +29 -0
  206. agenta/sdk/middleware/inline.py +38 -0
  207. agenta/sdk/middleware/mock.py +33 -0
  208. agenta/sdk/middleware/otel.py +40 -0
  209. agenta/sdk/middleware/vault.py +145 -0
  210. agenta/sdk/router.py +0 -7
  211. agenta/sdk/tracing/__init__.py +1 -0
  212. agenta/sdk/tracing/attributes.py +141 -0
  213. agenta/sdk/tracing/conventions.py +49 -0
  214. agenta/sdk/tracing/exporters.py +103 -0
  215. agenta/sdk/tracing/inline.py +1146 -0
  216. agenta/sdk/tracing/processors.py +121 -0
  217. agenta/sdk/tracing/spans.py +136 -0
  218. agenta/sdk/tracing/tracing.py +237 -0
  219. agenta/sdk/types.py +478 -74
  220. agenta/sdk/utils/__init__.py +0 -0
  221. agenta/sdk/utils/constants.py +1 -0
  222. agenta/sdk/utils/{helper/openai_cost.py → costs.py} +3 -0
  223. agenta/sdk/utils/exceptions.py +59 -0
  224. agenta/sdk/utils/globals.py +6 -10
  225. agenta/sdk/utils/helpers.py +8 -0
  226. agenta/sdk/utils/logging.py +21 -0
  227. agenta/sdk/utils/singleton.py +13 -0
  228. agenta/sdk/utils/timing.py +58 -0
  229. {agenta-0.12.3.dist-info → agenta-0.32.0a1.dist-info}/METADATA +98 -151
  230. agenta-0.32.0a1.dist-info/RECORD +263 -0
  231. {agenta-0.12.3.dist-info → agenta-0.32.0a1.dist-info}/WHEEL +1 -1
  232. agenta/client/backend/types/add_variant_from_base_and_config_response.py +0 -7
  233. agenta/client/backend/types/app_variant_output.py +0 -47
  234. agenta/client/backend/types/app_variant_output_extended.py +0 -50
  235. agenta/client/backend/types/delete_evaluation.py +0 -36
  236. agenta/client/backend/types/evaluation_webhook.py +0 -36
  237. agenta/client/backend/types/feedback.py +0 -40
  238. agenta/client/backend/types/get_config_reponse.py +0 -39
  239. agenta/client/backend/types/list_api_keys_output.py +0 -39
  240. agenta/client/backend/types/trace.py +0 -48
  241. agenta/sdk/agenta_decorator.py +0 -443
  242. agenta/sdk/context.py +0 -41
  243. agenta-0.12.3.dist-info/RECORD +0 -114
  244. {agenta-0.12.3.dist-info → agenta-0.32.0a1.dist-info}/entry_points.txt +0 -0
@@ -0,0 +1,38 @@
1
+ from typing import Callable
2
+
3
+ from starlette.middleware.base import BaseHTTPMiddleware
4
+ from fastapi import Request, FastAPI
5
+
6
+
7
+ from agenta.sdk.utils.exceptions import suppress
8
+
9
+ from agenta.sdk.utils.constants import TRUTHY
10
+
11
+
12
+ class InlineMiddleware(BaseHTTPMiddleware):
13
+ def __init__(self, app: FastAPI):
14
+ super().__init__(app)
15
+
16
+ async def dispatch(
17
+ self,
18
+ request: Request,
19
+ call_next: Callable,
20
+ ):
21
+ request.state.inline = False
22
+
23
+ with suppress():
24
+ baggage = request.state.otel.get("baggage") if request.state.otel else {}
25
+
26
+ inline = (
27
+ str(
28
+ # CLEANEST
29
+ baggage.get("inline")
30
+ # ALTERNATIVE
31
+ or request.query_params.get("inline")
32
+ )
33
+ in TRUTHY
34
+ )
35
+
36
+ request.state.inline = inline
37
+
38
+ return await call_next(request)
@@ -0,0 +1,33 @@
1
+ from typing import Callable
2
+
3
+ from starlette.middleware.base import BaseHTTPMiddleware
4
+ from fastapi import Request, FastAPI
5
+
6
+
7
+ from agenta.sdk.utils.exceptions import suppress
8
+
9
+
10
+ class MockMiddleware(BaseHTTPMiddleware):
11
+ def __init__(self, app: FastAPI):
12
+ super().__init__(app)
13
+
14
+ async def dispatch(
15
+ self,
16
+ request: Request,
17
+ call_next: Callable,
18
+ ):
19
+ request.state.mock = None
20
+
21
+ with suppress():
22
+ baggage = request.state.otel.get("baggage") if request.state.otel else {}
23
+
24
+ mock = (
25
+ # CLEANEST
26
+ baggage.get("mock")
27
+ # ALTERNATIVE
28
+ or request.query_params.get("mock")
29
+ )
30
+
31
+ request.state.mock = mock
32
+
33
+ return await call_next(request)
@@ -0,0 +1,40 @@
1
+ from typing import Callable
2
+
3
+ from starlette.middleware.base import BaseHTTPMiddleware
4
+ from fastapi import Request, FastAPI
5
+
6
+ from opentelemetry.baggage.propagation import W3CBaggagePropagator
7
+
8
+ from agenta.sdk.utils.exceptions import suppress
9
+
10
+
11
+ class OTelMiddleware(BaseHTTPMiddleware):
12
+ def __init__(self, app: FastAPI):
13
+ super().__init__(app)
14
+
15
+ async def dispatch(self, request: Request, call_next: Callable):
16
+ request.state.otel = {}
17
+
18
+ with suppress():
19
+ baggage = await self._get_baggage(request)
20
+
21
+ request.state.otel = {"baggage": baggage}
22
+
23
+ return await call_next(request)
24
+
25
+ async def _get_baggage(
26
+ self,
27
+ request,
28
+ ):
29
+ _baggage = {"baggage": request.headers.get("Baggage", "")}
30
+
31
+ context = W3CBaggagePropagator().extract(_baggage)
32
+
33
+ baggage = {}
34
+
35
+ if context:
36
+ for partial in context.values():
37
+ for key, value in partial.items():
38
+ baggage[key] = value
39
+
40
+ return baggage
@@ -0,0 +1,145 @@
1
+ from os import getenv
2
+ from json import dumps
3
+ from typing import Callable, Dict, Optional, List, Any, get_args
4
+
5
+ import httpx
6
+ from fastapi import FastAPI, Request
7
+ from starlette.middleware.base import BaseHTTPMiddleware
8
+
9
+ from agenta.sdk.utils.constants import TRUTHY
10
+ from agenta.client.backend.types.provider_kind import ProviderKind
11
+ from agenta.sdk.utils.exceptions import suppress, display_exception
12
+ from agenta.client.backend.types.secret_dto import SecretDto as SecretDTO
13
+ from agenta.client.backend.types.provider_key_dto import (
14
+ ProviderKeyDto as ProviderKeyDTO,
15
+ )
16
+ from agenta.sdk.middleware.cache import TTLLRUCache, CACHE_CAPACITY, CACHE_TTL
17
+
18
+ import agenta as ag
19
+
20
+
21
+ _PROVIDER_KINDS = []
22
+
23
+ for arg in ProviderKind.__args__: # type: ignore
24
+ if hasattr(arg, "__args__"):
25
+ _PROVIDER_KINDS.extend(arg.__args__)
26
+
27
+ _CACHE_ENABLED = getenv("AGENTA_MIDDLEWARE_CACHE_ENABLED", "true").lower() in TRUTHY
28
+
29
+ _cache = TTLLRUCache(capacity=CACHE_CAPACITY, ttl=CACHE_TTL)
30
+
31
+
32
+ class VaultMiddleware(BaseHTTPMiddleware):
33
+ def __init__(self, app: FastAPI):
34
+ super().__init__(app)
35
+
36
+ self.host = ag.DEFAULT_AGENTA_SINGLETON_INSTANCE.host
37
+
38
+ def _transform_secrets_response_to_secret_dto(
39
+ self, secrets_list: List[Dict[str, Any]]
40
+ ) -> List[Dict[str, Any]]:
41
+ secrets_dto_dict = [
42
+ {
43
+ "kind": secret.get("secret", {}).get("kind"),
44
+ "data": secret.get("secret", {}).get("data", {}),
45
+ }
46
+ for secret in secrets_list
47
+ ]
48
+ return secrets_dto_dict
49
+
50
+ async def dispatch(
51
+ self,
52
+ request: Request,
53
+ call_next: Callable,
54
+ ):
55
+ request.state.vault = {}
56
+
57
+ with suppress():
58
+ secrets = await self._get_secrets(request)
59
+
60
+ request.state.vault = {"secrets": secrets}
61
+
62
+ return await call_next(request)
63
+
64
+ async def _get_secrets(self, request: Request) -> Optional[Dict]:
65
+ credentials = request.state.auth.get("credentials")
66
+
67
+ headers = None
68
+ if credentials:
69
+ headers = {"Authorization": credentials}
70
+
71
+ _hash = dumps(
72
+ {
73
+ "headers": headers,
74
+ },
75
+ sort_keys=True,
76
+ )
77
+
78
+ if _CACHE_ENABLED:
79
+ secrets_cache = _cache.get(_hash)
80
+
81
+ if secrets_cache:
82
+ secrets = secrets_cache.get("secrets")
83
+
84
+ return secrets
85
+
86
+ local_secrets: List[SecretDTO] = []
87
+
88
+ try:
89
+ for provider_kind in _PROVIDER_KINDS:
90
+ provider = provider_kind
91
+ key_name = f"{provider.upper()}_API_KEY"
92
+ key = getenv(key_name)
93
+
94
+ if not key:
95
+ continue
96
+
97
+ secret = SecretDTO(
98
+ # kind=... # defaults to 'provider_kind'
99
+ data=ProviderKeyDTO(
100
+ provider=provider,
101
+ key=key,
102
+ ),
103
+ )
104
+
105
+ local_secrets.append(secret.model_dump())
106
+ except: # pylint: disable=bare-except
107
+ display_exception("Vault: Local Secrets Exception")
108
+
109
+ vault_secrets: List[SecretDTO] = []
110
+
111
+ try:
112
+ async with httpx.AsyncClient() as client:
113
+ response = await client.get(
114
+ f"{self.host}/api/vault/v1/secrets",
115
+ headers=headers,
116
+ )
117
+
118
+ if response.status_code != 200:
119
+ vault_secrets = []
120
+
121
+ else:
122
+ secrets = response.json()
123
+ vault_secrets = self._transform_secrets_response_to_secret_dto(
124
+ secrets
125
+ )
126
+ except: # pylint: disable=bare-except
127
+ display_exception("Vault: Vault Secrets Exception")
128
+
129
+ merged_secrets = {}
130
+
131
+ if local_secrets:
132
+ for secret in local_secrets:
133
+ provider = secret["data"]["provider"]
134
+ merged_secrets[provider] = secret
135
+
136
+ if vault_secrets:
137
+ for secret in vault_secrets:
138
+ provider = secret["data"]["provider"]
139
+ merged_secrets[provider] = secret
140
+
141
+ secrets = list(merged_secrets.values())
142
+
143
+ _cache.put(_hash, {"secrets": secrets})
144
+
145
+ return secrets
agenta/sdk/router.py CHANGED
@@ -1,15 +1,8 @@
1
1
  from fastapi import APIRouter
2
- from .context import get_contexts
3
2
 
4
3
  router = APIRouter()
5
4
 
6
5
 
7
- @router.get("/contexts/")
8
- def get_all_contexts():
9
- contexts = get_contexts()
10
- return {"contexts": contexts}
11
-
12
-
13
6
  @router.get("/health")
14
7
  def health():
15
8
  return {"status": "ok"}
@@ -0,0 +1 @@
1
+ from .tracing import Tracing, get_tracer
@@ -0,0 +1,141 @@
1
+ from json import loads, dumps
2
+ from typing import Optional, Union, Sequence, Any, Dict
3
+
4
+ Primitive = Union[str, int, float, bool, bytes]
5
+ PrimitivesSequence = Sequence[Primitive]
6
+ Attribute = Union[Primitive, PrimitivesSequence]
7
+
8
+
9
+ def _marshal(
10
+ unmarshalled: Dict[str, Any],
11
+ *,
12
+ parent_key: Optional[str] = "",
13
+ depth: Optional[int] = 0,
14
+ max_depth: Optional[int] = None,
15
+ ) -> Dict[str, Any]:
16
+ """
17
+ Marshals a dictionary of unmarshalled attributes into a flat dictionary
18
+
19
+ Example:
20
+ unmarshalled = {
21
+ "ag": {
22
+ "type": "tree",
23
+ "node": {
24
+ "name": "root",
25
+ "children": [
26
+ {
27
+ "name": "child1",
28
+ },
29
+ {
30
+ "name": "child2",
31
+ }
32
+ ]
33
+ }
34
+ }
35
+ }
36
+ marshalled = {
37
+ "ag.type": "tree",
38
+ "ag.node.name": "root",
39
+ "ag.node.children.0.name": "child1",
40
+ "ag.node.children.1.name": "child2"
41
+ }
42
+ """
43
+ marshalled = {}
44
+
45
+ # If max_depth is set and we've reached it,
46
+ # just return the unmarshalled attributes
47
+ if max_depth is not None and depth >= max_depth:
48
+ marshalled[parent_key] = unmarshalled
49
+ # MISSING ENCODING TO JSON IF NOT PRIMITIVE
50
+
51
+ return marshalled
52
+
53
+ # Otherwise,
54
+ # iterate over the unmarshalled attributes and marshall them
55
+ for key, value in unmarshalled.items():
56
+ child_key = f"{parent_key}.{key}" if parent_key else key
57
+
58
+ if isinstance(value, dict):
59
+ dict_key = child_key
60
+
61
+ marshalled.update(
62
+ _marshal(
63
+ value,
64
+ parent_key=dict_key,
65
+ depth=depth + 1,
66
+ max_depth=max_depth,
67
+ )
68
+ )
69
+ elif isinstance(value, list):
70
+ if max_depth is not None and depth + 1 >= max_depth:
71
+ marshalled[child_key] = value
72
+ # MISSING ENCODING TO JSON IF NOT PRIMITIVE
73
+ else:
74
+ for i, item in enumerate(value):
75
+ list_key = f"{child_key}.{i}"
76
+
77
+ if isinstance(item, (dict, list)):
78
+ marshalled.update(
79
+ _marshal(
80
+ item,
81
+ parent_key=list_key,
82
+ depth=depth + 1,
83
+ max_depth=max_depth,
84
+ )
85
+ )
86
+ else:
87
+ marshalled[list_key] = item
88
+ # MISSING ENCODING TO JSON IF NOT PRIMITIVE
89
+ else:
90
+ marshalled[child_key] = value
91
+ # MISSING ENCODING TO JSON IF NOT PRIMITIVE
92
+
93
+ return marshalled
94
+
95
+
96
+ def _encode_key(
97
+ namespace: Optional[str] = None,
98
+ key: str = "",
99
+ ) -> str:
100
+ if namespace is None:
101
+ return key
102
+
103
+ return f"ag.{namespace}.{key}"
104
+
105
+
106
+ def _encode_value(
107
+ value: Any,
108
+ ) -> Optional[Attribute]:
109
+ if value is None:
110
+ return None
111
+
112
+ if isinstance(value, (str, int, float, bool, bytes)):
113
+ return value
114
+
115
+ if isinstance(value, dict) or isinstance(value, list):
116
+ encoded = dumps(value)
117
+ value = "@ag.type=json:" + encoded
118
+ return value
119
+
120
+ return repr(value)
121
+
122
+
123
+ def serialize(
124
+ *,
125
+ namespace: str,
126
+ attributes: Dict[str, Any],
127
+ max_depth: Optional[int] = None,
128
+ ) -> Dict[str, str]:
129
+ if not isinstance(attributes, dict):
130
+ return {}
131
+
132
+ _attributes = {
133
+ k: v
134
+ for k, v in {
135
+ _encode_key(namespace, key): _encode_value(value)
136
+ for key, value in _marshal(attributes, max_depth=max_depth).items()
137
+ }.items()
138
+ if v is not None
139
+ }
140
+
141
+ return _attributes
@@ -0,0 +1,49 @@
1
+ from enum import Enum
2
+ from re import fullmatch
3
+
4
+ from opentelemetry.trace import SpanKind
5
+
6
+
7
+ class Reference(str, Enum):
8
+ #
9
+ VARIANT_ID = "variant.id"
10
+ VARIANT_SLUG = "variant.slug"
11
+ VARIANT_VERSION = "variant.version"
12
+ #
13
+ ENVIRONMENT_ID = "environment.id"
14
+ ENVIRONMENT_SLUG = "environment.slug"
15
+ ENVIRONMENT_VERSION = "environment.version"
16
+ #
17
+ APPLICATION_ID = "application.id"
18
+ APPLICATION_SLUG = "application.slug"
19
+ #
20
+
21
+
22
+ _PATTERN = r"[A-Za-z0-9._-]+"
23
+
24
+
25
+ def is_valid_attribute_key(
26
+ string: str,
27
+ ):
28
+ return bool(fullmatch(_PATTERN, string))
29
+
30
+
31
+ def parse_span_kind(type: str) -> SpanKind:
32
+ kind = SpanKind.INTERNAL
33
+ if type in [
34
+ "agent",
35
+ "chain",
36
+ "workflow",
37
+ ]:
38
+ kind = SpanKind.SERVER
39
+ elif type in [
40
+ "tool",
41
+ "embedding",
42
+ "query",
43
+ "completion",
44
+ "chat",
45
+ "rerank",
46
+ ]:
47
+ kind = SpanKind.CLIENT
48
+
49
+ return kind
@@ -0,0 +1,103 @@
1
+ from typing import Sequence, Dict, List
2
+
3
+ from opentelemetry.exporter.otlp.proto.http.trace_exporter import OTLPSpanExporter
4
+ from opentelemetry.sdk.trace.export import (
5
+ ConsoleSpanExporter,
6
+ SpanExporter,
7
+ SpanExportResult,
8
+ ReadableSpan,
9
+ )
10
+
11
+ from agenta.sdk.utils.exceptions import suppress
12
+ from agenta.sdk.context.exporting import (
13
+ exporting_context_manager,
14
+ exporting_context,
15
+ ExportingContext,
16
+ )
17
+
18
+
19
+ class InlineTraceExporter(SpanExporter):
20
+ def __init__(self, registry: Dict[str, List[ReadableSpan]]):
21
+ self._shutdown = False
22
+ self._registry = registry
23
+
24
+ def export(
25
+ self,
26
+ spans: Sequence[ReadableSpan],
27
+ ) -> SpanExportResult:
28
+ if self._shutdown:
29
+ return
30
+
31
+ with suppress():
32
+ for span in spans:
33
+ trace_id = span.get_span_context().trace_id
34
+
35
+ if trace_id not in self._registry:
36
+ self._registry[trace_id] = []
37
+
38
+ self._registry[trace_id].append(span)
39
+
40
+ def shutdown(self) -> None:
41
+ self._shutdown = True
42
+
43
+ def force_flush(self, timeout_millis: int = 30000) -> bool:
44
+ return True
45
+
46
+ def is_ready(
47
+ self,
48
+ trace_id: int,
49
+ ) -> bool:
50
+ is_ready = trace_id in self._registry
51
+
52
+ return is_ready
53
+
54
+ def fetch(
55
+ self,
56
+ trace_id: int,
57
+ ) -> List[ReadableSpan]:
58
+ trace = self._registry.get(trace_id, [])
59
+
60
+ if trace_id in self._registry:
61
+ del self._registry[trace_id]
62
+
63
+ return trace
64
+
65
+
66
+ class OTLPExporter(OTLPSpanExporter):
67
+ _MAX_RETRY_TIMEOUT = 2
68
+
69
+ def __init__(self, *args, credentials: Dict[int, str] = None, **kwargs):
70
+ super().__init__(*args, **kwargs)
71
+
72
+ self.credentials = credentials
73
+
74
+ def export(self, spans: Sequence[ReadableSpan]) -> SpanExportResult:
75
+ credentials = None
76
+
77
+ if self.credentials:
78
+ trace_ids = set(span.get_span_context().trace_id for span in spans)
79
+
80
+ if len(trace_ids) == 1:
81
+ trace_id = trace_ids.pop()
82
+
83
+ if trace_id in self.credentials:
84
+ credentials = self.credentials.pop(trace_id)
85
+
86
+ with exporting_context_manager(
87
+ context=ExportingContext(
88
+ credentials=credentials,
89
+ )
90
+ ):
91
+ return super().export(spans)
92
+
93
+ def _export(self, serialized_data: bytes):
94
+ credentials = exporting_context.get().credentials
95
+
96
+ if credentials:
97
+ self._session.headers.update({"Authorization": credentials})
98
+
99
+ return super()._export(serialized_data)
100
+
101
+
102
+ ConsoleExporter = ConsoleSpanExporter
103
+ InlineExporter = InlineTraceExporter