agenta 0.27.2a2__py3-none-any.whl → 0.27.4a0__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 (54) hide show
  1. agenta/client/backend/__init__.py +0 -63
  2. agenta/client/backend/client.py +22 -22
  3. agenta/client/backend/core/http_client.py +7 -15
  4. agenta/client/backend/observability/client.py +4 -4
  5. agenta/client/backend/types/__init__.py +0 -58
  6. agenta/client/backend/variants/client.py +16 -24
  7. agenta/sdk/__init__.py +0 -2
  8. agenta/sdk/agenta_init.py +7 -9
  9. agenta/sdk/decorators/routing.py +29 -5
  10. agenta/sdk/middleware/__init__.py +0 -0
  11. agenta/sdk/middleware/auth.py +136 -0
  12. agenta/sdk/middleware/cache.py +43 -0
  13. agenta/sdk/tracing/exporters.py +1 -1
  14. agenta/sdk/tracing/inline.py +140 -29
  15. agenta/sdk/tracing/processors.py +1 -1
  16. agenta/sdk/types.py +2 -5
  17. {agenta-0.27.2a2.dist-info → agenta-0.27.4a0.dist-info}/METADATA +1 -1
  18. {agenta-0.27.2a2.dist-info → agenta-0.27.4a0.dist-info}/RECORD +20 -51
  19. agenta/client/backend/observability_v_1/__init__.py +0 -5
  20. agenta/client/backend/observability_v_1/client.py +0 -560
  21. agenta/client/backend/observability_v_1/types/__init__.py +0 -6
  22. agenta/client/backend/observability_v_1/types/format.py +0 -5
  23. agenta/client/backend/observability_v_1/types/query_traces_response.py +0 -11
  24. agenta/client/backend/types/agenta_node_dto.py +0 -48
  25. agenta/client/backend/types/agenta_node_dto_nodes_value.py +0 -6
  26. agenta/client/backend/types/agenta_nodes_response.py +0 -30
  27. agenta/client/backend/types/agenta_root_dto.py +0 -30
  28. agenta/client/backend/types/agenta_roots_response.py +0 -30
  29. agenta/client/backend/types/agenta_tree_dto.py +0 -30
  30. agenta/client/backend/types/agenta_trees_response.py +0 -30
  31. agenta/client/backend/types/collect_status_response.py +0 -22
  32. agenta/client/backend/types/exception_dto.py +0 -26
  33. agenta/client/backend/types/link_dto.py +0 -24
  34. agenta/client/backend/types/node_dto.py +0 -24
  35. agenta/client/backend/types/node_type.py +0 -19
  36. agenta/client/backend/types/o_tel_context_dto.py +0 -22
  37. agenta/client/backend/types/o_tel_event_dto.py +0 -23
  38. agenta/client/backend/types/o_tel_extra_dto.py +0 -26
  39. agenta/client/backend/types/o_tel_link_dto.py +0 -23
  40. agenta/client/backend/types/o_tel_span_dto.py +0 -37
  41. agenta/client/backend/types/o_tel_span_kind.py +0 -15
  42. agenta/client/backend/types/o_tel_spans_response.py +0 -24
  43. agenta/client/backend/types/o_tel_status_code.py +0 -8
  44. agenta/client/backend/types/parent_dto.py +0 -21
  45. agenta/client/backend/types/root_dto.py +0 -21
  46. agenta/client/backend/types/span_dto.py +0 -54
  47. agenta/client/backend/types/span_dto_nodes_value.py +0 -9
  48. agenta/client/backend/types/status_code.py +0 -5
  49. agenta/client/backend/types/status_dto.py +0 -23
  50. agenta/client/backend/types/time_dto.py +0 -23
  51. agenta/client/backend/types/tree_dto.py +0 -23
  52. agenta/client/backend/types/tree_type.py +0 -5
  53. {agenta-0.27.2a2.dist-info → agenta-0.27.4a0.dist-info}/WHEEL +0 -0
  54. {agenta-0.27.2a2.dist-info → agenta-0.27.4a0.dist-info}/entry_points.txt +0 -0
agenta/sdk/agenta_init.py CHANGED
@@ -1,6 +1,6 @@
1
- import os
2
1
  import logging
3
2
  import toml
3
+ from os import getenv
4
4
  from typing import Optional
5
5
  from importlib.metadata import version
6
6
 
@@ -72,13 +72,13 @@ class AgentaSingleton:
72
72
 
73
73
  self.host = (
74
74
  host
75
- or os.environ.get("AGENTA_HOST")
75
+ or getenv("AGENTA_HOST")
76
76
  or config.get("backend_host")
77
77
  or config.get("host")
78
78
  or "https://cloud.agenta.ai"
79
79
  )
80
80
 
81
- self.app_id = app_id or config.get("app_id") or os.environ.get("AGENTA_APP_ID")
81
+ self.app_id = app_id or config.get("app_id") or getenv("AGENTA_APP_ID")
82
82
  # if not self.app_id:
83
83
  # raise ValueError(
84
84
  # "App ID must be specified. You can provide it in one of the following ways:\n"
@@ -87,9 +87,7 @@ class AgentaSingleton:
87
87
  # "3. As an environment variable 'AGENTA_APP_ID'."
88
88
  # )
89
89
 
90
- self.api_key = (
91
- api_key or os.environ.get("AGENTA_API_KEY") or config.get("api_key")
92
- )
90
+ self.api_key = api_key or getenv("AGENTA_API_KEY") or config.get("api_key")
93
91
 
94
92
  self.tracing = Tracing(
95
93
  url=f"{self.host}/api/observability/v1/otlp/traces", # type: ignore
@@ -103,15 +101,15 @@ class AgentaSingleton:
103
101
 
104
102
  self.api = AgentaApi(
105
103
  base_url=self.host + "/api",
106
- api_key=api_key if api_key else "",
104
+ api_key=self.api_key if self.api_key else "",
107
105
  )
108
106
 
109
107
  self.async_api = AsyncAgentaApi(
110
108
  base_url=self.host + "/api",
111
- api_key=api_key if api_key else "",
109
+ api_key=self.api_key if self.api_key else "",
112
110
  )
113
111
 
114
- self.base_id = os.environ.get("AGENTA_BASE_ID")
112
+ self.base_id = getenv("AGENTA_BASE_ID")
115
113
 
116
114
  self.config = Config(
117
115
  host=self.host,
@@ -14,9 +14,10 @@ from os import environ
14
14
  from fastapi.middleware.cors import CORSMiddleware
15
15
  from fastapi import Body, FastAPI, UploadFile, HTTPException
16
16
 
17
+ from agenta.sdk.middleware.auth import AuthorizationMiddleware
17
18
  from agenta.sdk.context.routing import routing_context_manager, routing_context
18
19
  from agenta.sdk.context.tracing import tracing_context
19
- from agenta.sdk.router import router as router
20
+ from agenta.sdk.router import router
20
21
  from agenta.sdk.utils.exceptions import suppress
21
22
  from agenta.sdk.utils.logging import log
22
23
  from agenta.sdk.types import (
@@ -50,6 +51,9 @@ app.add_middleware(
50
51
  allow_headers=["*"],
51
52
  )
52
53
 
54
+ _MIDDLEWARES = True
55
+
56
+
53
57
  app.include_router(router, prefix="")
54
58
 
55
59
 
@@ -121,6 +125,26 @@ class entrypoint:
121
125
  route_path="",
122
126
  config_schema: Optional[BaseModel] = None,
123
127
  ):
128
+ ### --- Update Middleware --- #
129
+ try:
130
+ global _MIDDLEWARES # pylint: disable=global-statement
131
+
132
+ if _MIDDLEWARES:
133
+ app.add_middleware(
134
+ AuthorizationMiddleware,
135
+ host=ag.DEFAULT_AGENTA_SINGLETON_INSTANCE.host,
136
+ resource_id=ag.DEFAULT_AGENTA_SINGLETON_INSTANCE.app_id,
137
+ resource_type="application",
138
+ )
139
+
140
+ _MIDDLEWARES = False
141
+
142
+ except: # pylint: disable=bare-except
143
+ log.error("------------------------------------")
144
+ log.error("Agenta SDK - failed to secure route: %s", route_path)
145
+ log.error("------------------------------------")
146
+ ### --- Update Middleware --- #
147
+
124
148
  DEFAULT_PATH = "generate"
125
149
  PLAYGROUND_PATH = "/playground"
126
150
  RUN_PATH = "/run"
@@ -226,7 +250,7 @@ class entrypoint:
226
250
  with routing_context_manager(
227
251
  application={
228
252
  "id": app_id,
229
- "slug": kwargs["app"],
253
+ "slug": kwargs.get("app"),
230
254
  },
231
255
  variant={
232
256
  "slug": kwargs.get("config"),
@@ -330,9 +354,9 @@ class entrypoint:
330
354
  *args,
331
355
  **func_params,
332
356
  ):
333
- log.info(f"---------------------------")
357
+ log.info("---------------------------")
334
358
  log.info(f"Agenta SDK - running route: {repr(self.route_path or '/')}")
335
- log.info(f"---------------------------")
359
+ log.info("---------------------------")
336
360
 
337
361
  tracing_context.set(routing_context.get())
338
362
 
@@ -362,7 +386,7 @@ class entrypoint:
362
386
  log.info(f"Agenta SDK - exiting with success: 200")
363
387
  log.info(f"----------------------------------")
364
388
 
365
- return BaseResponse(data=data, tree=trace)
389
+ return BaseResponse(data=data, trace=trace)
366
390
 
367
391
  def handle_failure(self, error: Exception):
368
392
  log.error("--------------------------------------------------")
File without changes
@@ -0,0 +1,136 @@
1
+ from typing import Callable, Optional
2
+ from os import environ
3
+ from uuid import UUID
4
+ from json import dumps
5
+ from traceback import format_exc
6
+
7
+ import httpx
8
+ from starlette.middleware.base import BaseHTTPMiddleware
9
+ from fastapi import FastAPI, Request, Response
10
+
11
+ from agenta.sdk.utils.logging import log
12
+ from agenta.sdk.middleware.cache import TTLLRUCache
13
+
14
+ AGENTA_SDK_AUTH_CACHE_CAPACITY = environ.get(
15
+ "AGENTA_SDK_AUTH_CACHE_CAPACITY",
16
+ 512,
17
+ )
18
+
19
+ AGENTA_SDK_AUTH_CACHE_TTL = environ.get(
20
+ "AGENTA_SDK_AUTH_CACHE_TTL",
21
+ 15 * 60, # 15 minutes
22
+ )
23
+
24
+ AGENTA_UNAUTHORIZED_EXECUTION_ALLOWED = str(
25
+ environ.get("AGENTA_UNAUTHORIZED_EXECUTION_ALLOWED", False)
26
+ ).lower() in ("true", "1", "t")
27
+
28
+
29
+ class Deny(Response):
30
+ def __init__(self) -> None:
31
+ super().__init__(status_code=401, content="Unauthorized")
32
+
33
+
34
+ cache = TTLLRUCache(
35
+ capacity=AGENTA_SDK_AUTH_CACHE_CAPACITY,
36
+ ttl=AGENTA_SDK_AUTH_CACHE_TTL,
37
+ )
38
+
39
+
40
+ class AuthorizationMiddleware(BaseHTTPMiddleware):
41
+ def __init__(
42
+ self,
43
+ app: FastAPI,
44
+ host: str,
45
+ resource_id: UUID,
46
+ resource_type: str,
47
+ ):
48
+ super().__init__(app)
49
+
50
+ self.host = host
51
+ self.resource_id = resource_id
52
+ self.resource_type = resource_type
53
+
54
+ async def dispatch(
55
+ self,
56
+ request: Request,
57
+ call_next: Callable,
58
+ project_id: Optional[UUID] = None,
59
+ ):
60
+ if AGENTA_UNAUTHORIZED_EXECUTION_ALLOWED:
61
+ return await call_next(request)
62
+
63
+ try:
64
+ authorization = (
65
+ request.headers.get("Authorization")
66
+ or request.headers.get("authorization")
67
+ or None
68
+ )
69
+
70
+ headers = {"Authorization": authorization} if authorization else None
71
+
72
+ cookies = {"sAccessToken": request.cookies.get("sAccessToken")}
73
+
74
+ params = {
75
+ "action": "run_service",
76
+ "resource_type": self.resource_type,
77
+ "resource_id": self.resource_id,
78
+ }
79
+
80
+ if project_id:
81
+ params["project_id"] = project_id
82
+
83
+ _hash = dumps(
84
+ {
85
+ "headers": headers,
86
+ "cookies": cookies,
87
+ "params": params,
88
+ },
89
+ sort_keys=True,
90
+ )
91
+
92
+ cached_policy = cache.get(_hash)
93
+
94
+ if not cached_policy:
95
+ async with httpx.AsyncClient() as client:
96
+ response = await client.get(
97
+ f"{self.host}/api/permissions/verify",
98
+ headers=headers,
99
+ cookies=cookies,
100
+ params=params,
101
+ )
102
+
103
+ if response.status_code != 200:
104
+ cache.put(_hash, {"effect": "deny"})
105
+ return Deny()
106
+
107
+ auth = response.json()
108
+
109
+ if auth.get("effect") != "allow":
110
+ cache.put(_hash, {"effect": "deny"})
111
+ return Deny()
112
+
113
+ cached_policy = {
114
+ "effect": "allow",
115
+ "credentials": auth.get("credentials"),
116
+ }
117
+
118
+ cache.put(_hash, cached_policy)
119
+
120
+ if cached_policy.get("effect") == "deny":
121
+ return Deny()
122
+
123
+ request.state.credentials = cached_policy.get("credentials")
124
+
125
+ print(f"credentials: {request.state.credentials}")
126
+
127
+ return await call_next(request)
128
+
129
+ except: # pylint: disable=bare-except
130
+ log.error("------------------------------------------------------")
131
+ log.error("Agenta SDK - handling auth middleware exception below:")
132
+ log.error("------------------------------------------------------")
133
+ log.error(format_exc().strip("\n"))
134
+ log.error("------------------------------------------------------")
135
+
136
+ return Deny()
@@ -0,0 +1,43 @@
1
+ from time import time
2
+ from collections import OrderedDict
3
+
4
+
5
+ class TTLLRUCache:
6
+ def __init__(self, capacity: int, ttl: int):
7
+ self.cache = OrderedDict()
8
+ self.capacity = capacity
9
+ self.ttl = ttl
10
+
11
+ def get(self, key):
12
+ # CACHE
13
+ if key not in self.cache:
14
+ return None
15
+
16
+ value, expiry = self.cache[key]
17
+ # -----
18
+
19
+ # TTL
20
+ if time() > expiry:
21
+ del self.cache[key]
22
+
23
+ return None
24
+ # ---
25
+
26
+ # LRU
27
+ self.cache.move_to_end(key)
28
+ # ---
29
+
30
+ return value
31
+
32
+ def put(self, key, value):
33
+ # CACHE
34
+ if key in self.cache:
35
+ del self.cache[key]
36
+ # CACHE & LRU
37
+ elif len(self.cache) >= self.capacity:
38
+ self.cache.popitem(last=False)
39
+ # -----------
40
+
41
+ # TTL
42
+ self.cache[key] = (value, time() + self.ttl)
43
+ # ---
@@ -58,7 +58,7 @@ class InlineTraceExporter(SpanExporter):
58
58
  return trace
59
59
 
60
60
 
61
- OTLPSpanExporter._MAX_RETRY_TIMEOUT = 2
61
+ OTLPSpanExporter._MAX_RETRY_TIMEOUT = 2 # pylint: disable=protected-access
62
62
 
63
63
  ConsoleExporter = ConsoleSpanExporter
64
64
  InlineExporter = InlineTraceExporter
@@ -903,9 +903,9 @@ def parse_to_agenta_span_dto(
903
903
  if span_dto.data:
904
904
  span_dto.data = _unmarshal_attributes(span_dto.data)
905
905
 
906
- if "outputs" in span_dto.data:
907
- if "__default__" in span_dto.data["outputs"]:
908
- span_dto.data["outputs"] = span_dto.data["outputs"]["__default__"]
906
+ # if "outputs" in span_dto.data:
907
+ # if "__default__" in span_dto.data["outputs"]:
908
+ # span_dto.data["outputs"] = span_dto.data["outputs"]["__default__"]
909
909
 
910
910
  # METRICS
911
911
  if span_dto.metrics:
@@ -934,17 +934,6 @@ def parse_to_agenta_span_dto(
934
934
  else:
935
935
  parse_to_agenta_span_dto(v)
936
936
 
937
- # MASK LINKS FOR NOW
938
- span_dto.links = None
939
- # ------------------
940
-
941
- # MASK LIFECYCLE FOR NOW
942
- # span_dto.lifecycle = None
943
- if span_dto.lifecycle:
944
- span_dto.lifecycle.updated_at = None
945
- span_dto.lifecycle.updated_by_id = None
946
- # ----------------------
947
-
948
937
  return span_dto
949
938
 
950
939
 
@@ -956,8 +945,6 @@ def parse_to_agenta_span_dto(
956
945
  from litellm import cost_calculator
957
946
  from opentelemetry.sdk.trace import ReadableSpan
958
947
 
959
- from agenta.sdk.types import AgentaNodeDto, AgentaNodesResponse
960
-
961
948
 
962
949
  def parse_inline_trace(
963
950
  spans: Dict[str, ReadableSpan],
@@ -1005,19 +992,51 @@ def parse_inline_trace(
1005
992
  ### services.observability.service.query() ###
1006
993
  ##############################################
1007
994
 
1008
- spans = [
1009
- loads(
1010
- span_dto.model_dump_json(
1011
- exclude_none=True,
1012
- exclude_defaults=True,
1013
- )
1014
- )
1015
- for span_dto in agenta_span_dtos
1016
- ]
1017
- inline_trace = AgentaNodesResponse(
1018
- version="1.0.0",
1019
- nodes=[AgentaNodeDto(**span) for span in spans],
1020
- ).model_dump(exclude_none=True, exclude_unset=True)
995
+ LEGACY = True
996
+ inline_trace = None
997
+
998
+ if LEGACY:
999
+ legacy_spans = [
1000
+ _parse_to_legacy_span(span_dto) for span_dto in span_idx.values()
1001
+ ]
1002
+
1003
+ root_span = agenta_span_dtos[0]
1004
+
1005
+ trace_id = root_span.root.id.hex
1006
+ latency = root_span.time.span / 1_000_000
1007
+ cost = root_span.metrics.get("acc", {}).get("costs", {}).get("total", 0.0)
1008
+ tokens = {
1009
+ "prompt_tokens": root_span.metrics.get("acc", {})
1010
+ .get("tokens", {})
1011
+ .get("prompt", 0),
1012
+ "completion_tokens": root_span.metrics.get("acc", {})
1013
+ .get("tokens", {})
1014
+ .get("completion", 0),
1015
+ "total_tokens": root_span.metrics.get("acc", {})
1016
+ .get("tokens", {})
1017
+ .get("total", 0),
1018
+ }
1019
+
1020
+ spans = [
1021
+ loads(span.model_dump_json(exclude_none=True)) for span in legacy_spans
1022
+ ]
1023
+
1024
+ inline_trace = {
1025
+ "trace_id": trace_id,
1026
+ "latency": latency,
1027
+ "cost": cost,
1028
+ "usage": tokens,
1029
+ "spans": spans,
1030
+ }
1031
+
1032
+ else:
1033
+ spans = [
1034
+ loads(span_dto.model_dump_json(exclude_none=True))
1035
+ for span_dto in agenta_span_dtos
1036
+ ]
1037
+
1038
+ inline_trace = spans # turn into Agenta Model ?
1039
+
1021
1040
  return inline_trace
1022
1041
 
1023
1042
 
@@ -1101,6 +1120,98 @@ class LlmTokens(BaseModel):
1101
1120
  total_tokens: Optional[int] = 0
1102
1121
 
1103
1122
 
1123
+ class CreateSpan(BaseModel):
1124
+ id: str
1125
+ app_id: str
1126
+ variant_id: Optional[str] = None
1127
+ variant_name: Optional[str] = None
1128
+ inputs: Optional[Dict[str, Optional[Any]]] = None
1129
+ internals: Optional[Dict[str, Optional[Any]]] = None
1130
+ outputs: Optional[Union[str, Dict[str, Optional[Any]], List[Any]]] = None
1131
+ config: Optional[Dict[str, Optional[Any]]] = None
1132
+ environment: Optional[str] = None
1133
+ tags: Optional[List[str]] = None
1134
+ token_consumption: Optional[int] = None
1135
+ name: str
1136
+ parent_span_id: Optional[str] = None
1137
+ attributes: Optional[Dict[str, Optional[Any]]] = None
1138
+ spankind: str
1139
+ status: str
1140
+ user: Optional[str] = None
1141
+ start_time: datetime
1142
+ end_time: datetime
1143
+ tokens: Optional[LlmTokens] = None
1144
+ cost: Optional[float] = None
1145
+
1146
+
1147
+ def _parse_to_legacy_span(span: SpanDTO) -> CreateSpan:
1148
+ attributes = None
1149
+ if span.otel:
1150
+ attributes = span.otel.attributes or {}
1151
+
1152
+ if span.otel.events:
1153
+ for event in span.otel.events:
1154
+ if event.name == "exception":
1155
+ attributes.update(**event.attributes)
1156
+
1157
+ legacy_span = CreateSpan(
1158
+ id=span.node.id.hex[:24],
1159
+ spankind=span.node.type,
1160
+ name=span.node.name,
1161
+ #
1162
+ status=span.status.code.name,
1163
+ #
1164
+ start_time=span.time.start,
1165
+ end_time=span.time.end,
1166
+ #
1167
+ parent_span_id=span.parent.id.hex[:24] if span.parent else None,
1168
+ #
1169
+ inputs=span.data.get("inputs") if span.data else {},
1170
+ internals=span.data.get("internals") if span.data else {},
1171
+ outputs=span.data.get("outputs") if span.data else {},
1172
+ #
1173
+ environment=span.meta.get("environment") if span.meta else None,
1174
+ config=span.meta.get("configuration") if span.meta else None,
1175
+ #
1176
+ tokens=(
1177
+ LlmTokens(
1178
+ prompt_tokens=span.metrics.get("acc", {})
1179
+ .get("tokens", {})
1180
+ .get("prompt", 0.0),
1181
+ completion_tokens=span.metrics.get("acc", {})
1182
+ .get("tokens", {})
1183
+ .get("completion", 0.0),
1184
+ total_tokens=span.metrics.get("acc", {})
1185
+ .get("tokens", {})
1186
+ .get("total", 0.0),
1187
+ )
1188
+ if span.metrics
1189
+ else None
1190
+ ),
1191
+ cost=(
1192
+ span.metrics.get("acc", {}).get("costs", {}).get("total", 0.0)
1193
+ if span.metrics
1194
+ else None
1195
+ ),
1196
+ #
1197
+ app_id=(
1198
+ span.refs.get("application", {}).get("id", "missing-app-id")
1199
+ if span.refs
1200
+ else "missing-app-id"
1201
+ ),
1202
+ #
1203
+ attributes=attributes,
1204
+ #
1205
+ variant_id=None,
1206
+ variant_name=None,
1207
+ tags=None,
1208
+ token_consumption=None,
1209
+ user=None,
1210
+ )
1211
+
1212
+ return legacy_span
1213
+
1214
+
1104
1215
  TYPES_WITH_COSTS = [
1105
1216
  "embedding",
1106
1217
  "query",
@@ -12,7 +12,7 @@ from opentelemetry.sdk.trace.export import (
12
12
 
13
13
  from agenta.sdk.utils.logging import log
14
14
 
15
- # LOAD CONTEXT, HERE
15
+ # LOAD CONTEXT, HERE !
16
16
 
17
17
 
18
18
  class TraceProcessor(BatchSpanProcessor):
agenta/sdk/types.py CHANGED
@@ -4,9 +4,6 @@ from typing import Dict, List, Optional, Any, Union
4
4
 
5
5
  from pydantic import ConfigDict, BaseModel, HttpUrl
6
6
 
7
- from agenta.client.backend.types.agenta_node_dto import AgentaNodeDto
8
- from agenta.client.backend.types.agenta_nodes_response import AgentaNodesResponse
9
-
10
7
 
11
8
  @dataclass
12
9
  class MultipleChoice:
@@ -26,9 +23,9 @@ class LLMTokenUsage(BaseModel):
26
23
 
27
24
 
28
25
  class BaseResponse(BaseModel):
29
- version: Optional[str] = "3.0"
26
+ version: Optional[str] = "2.0"
30
27
  data: Optional[Union[str, Dict[str, Any]]]
31
- tree: AgentaNodesResponse
28
+ trace: Optional[Dict[str, Any]]
32
29
 
33
30
 
34
31
  class DictInput(dict):
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: agenta
3
- Version: 0.27.2a2
3
+ Version: 0.27.4a0
4
4
  Summary: The SDK for agenta is an open-source LLMOps platform.
5
5
  Home-page: https://agenta.ai
6
6
  Keywords: LLMOps,LLM,evaluation,prompt engineering