agenta 0.57.0__py3-none-any.whl → 0.65.0__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.
Files changed (267) hide show
  1. agenta/__init__.py +12 -3
  2. agenta/client/__init__.py +4 -4
  3. agenta/client/backend/__init__.py +4 -4
  4. agenta/client/backend/api_keys/client.py +2 -2
  5. agenta/client/backend/billing/client.py +2 -2
  6. agenta/client/backend/billing/raw_client.py +2 -2
  7. agenta/client/backend/client.py +56 -48
  8. agenta/client/backend/core/client_wrapper.py +2 -2
  9. agenta/client/backend/core/file.py +3 -1
  10. agenta/client/backend/core/http_client.py +3 -3
  11. agenta/client/backend/core/pydantic_utilities.py +13 -3
  12. agenta/client/backend/human_evaluations/client.py +2 -2
  13. agenta/client/backend/human_evaluations/raw_client.py +2 -2
  14. agenta/client/backend/organization/client.py +46 -34
  15. agenta/client/backend/organization/raw_client.py +32 -26
  16. agenta/client/backend/raw_client.py +26 -26
  17. agenta/client/backend/testsets/client.py +18 -18
  18. agenta/client/backend/testsets/raw_client.py +30 -30
  19. agenta/client/backend/types/__init__.py +4 -4
  20. agenta/client/backend/types/account_request.py +3 -1
  21. agenta/client/backend/types/account_response.py +3 -1
  22. agenta/client/backend/types/agenta_node_dto.py +3 -1
  23. agenta/client/backend/types/agenta_nodes_response.py +3 -1
  24. agenta/client/backend/types/agenta_root_dto.py +3 -1
  25. agenta/client/backend/types/agenta_roots_response.py +3 -1
  26. agenta/client/backend/types/agenta_tree_dto.py +3 -1
  27. agenta/client/backend/types/agenta_trees_response.py +3 -1
  28. agenta/client/backend/types/aggregated_result.py +3 -1
  29. agenta/client/backend/types/analytics_response.py +3 -1
  30. agenta/client/backend/types/annotation.py +6 -4
  31. agenta/client/backend/types/annotation_create.py +3 -1
  32. agenta/client/backend/types/annotation_edit.py +3 -1
  33. agenta/client/backend/types/annotation_link.py +3 -1
  34. agenta/client/backend/types/annotation_link_response.py +3 -1
  35. agenta/client/backend/types/annotation_query.py +3 -1
  36. agenta/client/backend/types/annotation_query_request.py +3 -1
  37. agenta/client/backend/types/annotation_reference.py +3 -1
  38. agenta/client/backend/types/annotation_references.py +3 -1
  39. agenta/client/backend/types/annotation_response.py +3 -1
  40. agenta/client/backend/types/annotations_response.py +3 -1
  41. agenta/client/backend/types/app.py +3 -1
  42. agenta/client/backend/types/app_variant_response.py +3 -1
  43. agenta/client/backend/types/app_variant_revision.py +3 -1
  44. agenta/client/backend/types/artifact.py +6 -4
  45. agenta/client/backend/types/base_output.py +3 -1
  46. agenta/client/backend/types/body_fetch_workflow_revision.py +3 -1
  47. agenta/client/backend/types/body_import_testset.py +3 -1
  48. agenta/client/backend/types/bucket_dto.py +3 -1
  49. agenta/client/backend/types/collect_status_response.py +3 -1
  50. agenta/client/backend/types/config_db.py +3 -1
  51. agenta/client/backend/types/config_dto.py +3 -1
  52. agenta/client/backend/types/config_response_model.py +3 -1
  53. agenta/client/backend/types/correct_answer.py +3 -1
  54. agenta/client/backend/types/create_app_output.py +3 -1
  55. agenta/client/backend/types/custom_model_settings_dto.py +3 -1
  56. agenta/client/backend/types/custom_provider_dto.py +3 -1
  57. agenta/client/backend/types/custom_provider_kind.py +1 -1
  58. agenta/client/backend/types/custom_provider_settings_dto.py +3 -1
  59. agenta/client/backend/types/delete_evaluation.py +3 -1
  60. agenta/client/backend/types/environment_output.py +3 -1
  61. agenta/client/backend/types/environment_output_extended.py +3 -1
  62. agenta/client/backend/types/environment_revision.py +3 -1
  63. agenta/client/backend/types/error.py +3 -1
  64. agenta/client/backend/types/evaluation.py +3 -1
  65. agenta/client/backend/types/evaluation_scenario.py +3 -1
  66. agenta/client/backend/types/evaluation_scenario_input.py +3 -1
  67. agenta/client/backend/types/evaluation_scenario_output.py +3 -1
  68. agenta/client/backend/types/evaluation_scenario_result.py +3 -1
  69. agenta/client/backend/types/evaluator.py +6 -4
  70. agenta/client/backend/types/evaluator_config.py +6 -4
  71. agenta/client/backend/types/evaluator_flags.py +3 -1
  72. agenta/client/backend/types/evaluator_mapping_output_interface.py +3 -1
  73. agenta/client/backend/types/evaluator_output_interface.py +3 -1
  74. agenta/client/backend/types/evaluator_query.py +3 -1
  75. agenta/client/backend/types/evaluator_query_request.py +3 -1
  76. agenta/client/backend/types/evaluator_request.py +3 -1
  77. agenta/client/backend/types/evaluator_response.py +3 -1
  78. agenta/client/backend/types/evaluators_response.py +3 -1
  79. agenta/client/backend/types/exception_dto.py +3 -1
  80. agenta/client/backend/types/extended_o_tel_tracing_response.py +3 -1
  81. agenta/client/backend/types/get_config_response.py +3 -1
  82. agenta/client/backend/types/header.py +3 -1
  83. agenta/client/backend/types/http_validation_error.py +3 -1
  84. agenta/client/backend/types/human_evaluation.py +3 -1
  85. agenta/client/backend/types/human_evaluation_scenario.py +3 -1
  86. agenta/client/backend/types/human_evaluation_scenario_input.py +3 -1
  87. agenta/client/backend/types/human_evaluation_scenario_output.py +3 -1
  88. agenta/client/backend/types/invite_request.py +3 -1
  89. agenta/client/backend/types/legacy_analytics_response.py +3 -1
  90. agenta/client/backend/types/legacy_data_point.py +3 -1
  91. agenta/client/backend/types/legacy_evaluator.py +3 -1
  92. agenta/client/backend/types/legacy_scope_request.py +3 -1
  93. agenta/client/backend/types/legacy_scopes_response.py +3 -1
  94. agenta/client/backend/types/legacy_subscription_request.py +3 -1
  95. agenta/client/backend/types/legacy_user_request.py +3 -1
  96. agenta/client/backend/types/legacy_user_response.py +3 -1
  97. agenta/client/backend/types/lifecycle_dto.py +3 -1
  98. agenta/client/backend/types/link_dto.py +3 -1
  99. agenta/client/backend/types/list_api_keys_response.py +3 -1
  100. agenta/client/backend/types/llm_run_rate_limit.py +3 -1
  101. agenta/client/backend/types/meta_request.py +3 -1
  102. agenta/client/backend/types/metrics_dto.py +3 -1
  103. agenta/client/backend/types/new_testset.py +3 -1
  104. agenta/client/backend/types/node_dto.py +3 -1
  105. agenta/client/backend/types/o_tel_context_dto.py +3 -1
  106. agenta/client/backend/types/o_tel_event.py +6 -4
  107. agenta/client/backend/types/o_tel_event_dto.py +3 -1
  108. agenta/client/backend/types/o_tel_extra_dto.py +3 -1
  109. agenta/client/backend/types/o_tel_flat_span.py +6 -4
  110. agenta/client/backend/types/o_tel_link.py +6 -4
  111. agenta/client/backend/types/o_tel_link_dto.py +3 -1
  112. agenta/client/backend/types/o_tel_links_response.py +3 -1
  113. agenta/client/backend/types/o_tel_span.py +1 -1
  114. agenta/client/backend/types/o_tel_span_dto.py +3 -1
  115. agenta/client/backend/types/o_tel_spans_tree.py +3 -1
  116. agenta/client/backend/types/o_tel_tracing_data_response.py +3 -1
  117. agenta/client/backend/types/o_tel_tracing_request.py +3 -1
  118. agenta/client/backend/types/o_tel_tracing_response.py +3 -1
  119. agenta/client/backend/types/organization.py +3 -1
  120. agenta/client/backend/types/organization_details.py +3 -1
  121. agenta/client/backend/types/organization_membership_request.py +3 -1
  122. agenta/client/backend/types/organization_output.py +3 -1
  123. agenta/client/backend/types/organization_request.py +3 -1
  124. agenta/client/backend/types/parent_dto.py +3 -1
  125. agenta/client/backend/types/project_membership_request.py +3 -1
  126. agenta/client/backend/types/project_request.py +3 -1
  127. agenta/client/backend/types/project_scope.py +3 -1
  128. agenta/client/backend/types/projects_response.py +4 -1
  129. agenta/client/backend/types/reference.py +6 -4
  130. agenta/client/backend/types/reference_dto.py +3 -1
  131. agenta/client/backend/types/reference_request_model.py +3 -1
  132. agenta/client/backend/types/result.py +3 -1
  133. agenta/client/backend/types/root_dto.py +3 -1
  134. agenta/client/backend/types/scopes_response_model.py +3 -1
  135. agenta/client/backend/types/secret_dto.py +3 -1
  136. agenta/client/backend/types/secret_response_dto.py +3 -1
  137. agenta/client/backend/types/simple_evaluation_output.py +3 -1
  138. agenta/client/backend/types/span_dto.py +6 -4
  139. agenta/client/backend/types/standard_provider_dto.py +3 -1
  140. agenta/client/backend/types/standard_provider_settings_dto.py +3 -1
  141. agenta/client/backend/types/status_dto.py +3 -1
  142. agenta/client/backend/types/tags_request.py +3 -1
  143. agenta/client/backend/types/testcase_response.py +6 -4
  144. agenta/client/backend/types/testset.py +6 -4
  145. agenta/client/backend/types/{test_set_output_response.py → testset_output_response.py} +4 -2
  146. agenta/client/backend/types/testset_request.py +3 -1
  147. agenta/client/backend/types/testset_response.py +3 -1
  148. agenta/client/backend/types/{test_set_simple_response.py → testset_simple_response.py} +4 -2
  149. agenta/client/backend/types/testsets_response.py +3 -1
  150. agenta/client/backend/types/time_dto.py +3 -1
  151. agenta/client/backend/types/tree_dto.py +3 -1
  152. agenta/client/backend/types/update_app_output.py +3 -1
  153. agenta/client/backend/types/user_request.py +3 -1
  154. agenta/client/backend/types/validation_error.py +3 -1
  155. agenta/client/backend/types/workflow_artifact.py +6 -4
  156. agenta/client/backend/types/workflow_data.py +3 -1
  157. agenta/client/backend/types/workflow_flags.py +3 -1
  158. agenta/client/backend/types/workflow_request.py +3 -1
  159. agenta/client/backend/types/workflow_response.py +3 -1
  160. agenta/client/backend/types/workflow_revision.py +6 -4
  161. agenta/client/backend/types/workflow_revision_request.py +3 -1
  162. agenta/client/backend/types/workflow_revision_response.py +3 -1
  163. agenta/client/backend/types/workflow_revisions_response.py +3 -1
  164. agenta/client/backend/types/workflow_variant.py +6 -4
  165. agenta/client/backend/types/workflow_variant_request.py +3 -1
  166. agenta/client/backend/types/workflow_variant_response.py +3 -1
  167. agenta/client/backend/types/workflow_variants_response.py +3 -1
  168. agenta/client/backend/types/workflows_response.py +3 -1
  169. agenta/client/backend/types/workspace.py +3 -1
  170. agenta/client/backend/types/workspace_member_response.py +3 -1
  171. agenta/client/backend/types/workspace_membership_request.py +3 -1
  172. agenta/client/backend/types/workspace_permission.py +3 -1
  173. agenta/client/backend/types/workspace_request.py +3 -1
  174. agenta/client/backend/types/workspace_response.py +3 -1
  175. agenta/client/backend/workspace/client.py +2 -2
  176. agenta/client/client.py +102 -88
  177. agenta/sdk/__init__.py +52 -3
  178. agenta/sdk/agenta_init.py +43 -16
  179. agenta/sdk/assets.py +22 -15
  180. agenta/sdk/context/serving.py +20 -8
  181. agenta/sdk/context/tracing.py +40 -22
  182. agenta/sdk/contexts/__init__.py +0 -0
  183. agenta/sdk/contexts/routing.py +38 -0
  184. agenta/sdk/contexts/running.py +57 -0
  185. agenta/sdk/contexts/tracing.py +86 -0
  186. agenta/sdk/decorators/__init__.py +1 -0
  187. agenta/sdk/decorators/routing.py +284 -0
  188. agenta/sdk/decorators/running.py +692 -98
  189. agenta/sdk/decorators/serving.py +20 -21
  190. agenta/sdk/decorators/tracing.py +176 -131
  191. agenta/sdk/engines/__init__.py +0 -0
  192. agenta/sdk/engines/running/__init__.py +0 -0
  193. agenta/sdk/engines/running/utils.py +17 -0
  194. agenta/sdk/engines/tracing/__init__.py +1 -0
  195. agenta/sdk/engines/tracing/attributes.py +185 -0
  196. agenta/sdk/engines/tracing/conventions.py +49 -0
  197. agenta/sdk/engines/tracing/exporters.py +130 -0
  198. agenta/sdk/engines/tracing/inline.py +1154 -0
  199. agenta/sdk/engines/tracing/processors.py +190 -0
  200. agenta/sdk/engines/tracing/propagation.py +102 -0
  201. agenta/sdk/engines/tracing/spans.py +136 -0
  202. agenta/sdk/engines/tracing/tracing.py +324 -0
  203. agenta/sdk/evaluations/__init__.py +2 -0
  204. agenta/sdk/evaluations/metrics.py +37 -0
  205. agenta/sdk/evaluations/preview/__init__.py +0 -0
  206. agenta/sdk/evaluations/preview/evaluate.py +765 -0
  207. agenta/sdk/evaluations/preview/utils.py +861 -0
  208. agenta/sdk/evaluations/results.py +66 -0
  209. agenta/sdk/evaluations/runs.py +152 -0
  210. agenta/sdk/evaluations/scenarios.py +48 -0
  211. agenta/sdk/litellm/litellm.py +12 -0
  212. agenta/sdk/litellm/mockllm.py +6 -8
  213. agenta/sdk/litellm/mocks/__init__.py +5 -5
  214. agenta/sdk/managers/applications.py +304 -0
  215. agenta/sdk/managers/config.py +2 -2
  216. agenta/sdk/managers/evaluations.py +0 -0
  217. agenta/sdk/managers/evaluators.py +303 -0
  218. agenta/sdk/managers/secrets.py +161 -24
  219. agenta/sdk/managers/shared.py +3 -1
  220. agenta/sdk/managers/testsets.py +441 -0
  221. agenta/sdk/managers/vault.py +3 -3
  222. agenta/sdk/middleware/auth.py +0 -176
  223. agenta/sdk/middleware/vault.py +203 -8
  224. agenta/sdk/middlewares/__init__.py +0 -0
  225. agenta/sdk/middlewares/routing/__init__.py +0 -0
  226. agenta/sdk/middlewares/routing/auth.py +263 -0
  227. agenta/sdk/middlewares/routing/cors.py +30 -0
  228. agenta/sdk/middlewares/routing/otel.py +29 -0
  229. agenta/sdk/middlewares/running/__init__.py +0 -0
  230. agenta/sdk/middlewares/running/normalizer.py +321 -0
  231. agenta/sdk/middlewares/running/resolver.py +161 -0
  232. agenta/sdk/middlewares/running/vault.py +140 -0
  233. agenta/sdk/models/__init__.py +0 -0
  234. agenta/sdk/models/blobs.py +33 -0
  235. agenta/sdk/models/evaluations.py +119 -0
  236. agenta/sdk/models/git.py +126 -0
  237. agenta/sdk/models/shared.py +167 -0
  238. agenta/sdk/models/testsets.py +163 -0
  239. agenta/sdk/models/tracing.py +202 -0
  240. agenta/sdk/models/workflows.py +753 -0
  241. agenta/sdk/tracing/exporters.py +67 -17
  242. agenta/sdk/tracing/processors.py +97 -0
  243. agenta/sdk/tracing/propagation.py +3 -1
  244. agenta/sdk/tracing/spans.py +4 -0
  245. agenta/sdk/tracing/tracing.py +13 -13
  246. agenta/sdk/types.py +211 -17
  247. agenta/sdk/utils/cache.py +1 -1
  248. agenta/sdk/utils/client.py +38 -0
  249. agenta/sdk/utils/helpers.py +13 -12
  250. agenta/sdk/utils/logging.py +18 -78
  251. agenta/sdk/utils/references.py +23 -0
  252. agenta/sdk/workflows/builtin.py +600 -0
  253. agenta/sdk/workflows/configurations.py +22 -0
  254. agenta/sdk/workflows/errors.py +292 -0
  255. agenta/sdk/workflows/handlers.py +1791 -0
  256. agenta/sdk/workflows/interfaces.py +948 -0
  257. agenta/sdk/workflows/sandbox.py +118 -0
  258. agenta/sdk/workflows/utils.py +303 -6
  259. {agenta-0.57.0.dist-info → agenta-0.65.0.dist-info}/METADATA +44 -47
  260. agenta-0.65.0.dist-info/RECORD +421 -0
  261. agenta/sdk/middleware/adapt.py +0 -253
  262. agenta/sdk/middleware/base.py +0 -40
  263. agenta/sdk/middleware/flags.py +0 -40
  264. agenta/sdk/workflows/types.py +0 -472
  265. agenta-0.57.0.dist-info/RECORD +0 -371
  266. /agenta/sdk/{workflows → engines/running}/registry.py +0 -0
  267. {agenta-0.57.0.dist-info → agenta-0.65.0.dist-info}/WHEEL +0 -0
@@ -0,0 +1,38 @@
1
+ import requests
2
+
3
+ BASE_TIMEOUT = 10
4
+
5
+ from agenta.sdk.utils.logging import get_module_logger
6
+
7
+ import agenta as ag
8
+
9
+ log = get_module_logger(__name__)
10
+
11
+
12
+ def authed_api():
13
+ """
14
+ Preconfigured requests for authenticated endpoints (supports all methods).
15
+ """
16
+
17
+ api_url = ag.DEFAULT_AGENTA_SINGLETON_INSTANCE.api_url
18
+ api_key = ag.DEFAULT_AGENTA_SINGLETON_INSTANCE.api_key
19
+
20
+ if not api_url or not api_key:
21
+ log.error("Please call ag.init() first.")
22
+ log.error("And don't forget to set AGENTA_API_URL and AGENTA_API_KEY.")
23
+ raise ValueError("API URL and API Key must be set.")
24
+
25
+ def _request(method: str, endpoint: str, **kwargs):
26
+ url = f"{api_url}{endpoint}"
27
+ headers = kwargs.pop("headers", {})
28
+ headers.setdefault("Authorization", f"ApiKey {api_key}")
29
+
30
+ return requests.request(
31
+ method=method,
32
+ url=url,
33
+ headers=headers,
34
+ timeout=BASE_TIMEOUT,
35
+ **kwargs,
36
+ )
37
+
38
+ return _request
@@ -20,25 +20,26 @@ def parse_url(url: str) -> str:
20
20
  str: The parsed or rewritten URL suitable for the current environment and Docker network mode.
21
21
  """
22
22
 
23
- # Normalize: remove trailing slash and /api suffix
24
23
  url = url.rstrip("/")
25
- if url.endswith("/api"):
26
- url = url[: -len("/api")]
27
24
 
28
- if "localhost" not in url:
25
+ if "localhost" not in url and "0.0.0.0" not in url:
29
26
  return url
30
27
 
31
- internal_url = os.getenv("AGENTA_API_INTERNAL_URL")
32
- if internal_url:
33
- return internal_url
34
-
35
28
  docker_network_mode = os.getenv("DOCKER_NETWORK_MODE")
36
29
 
37
30
  if docker_network_mode and docker_network_mode.lower() == "bridge":
38
- return url.replace("localhost", "host.docker.internal")
39
-
40
- if not docker_network_mode or docker_network_mode.lower() == "host":
31
+ return url.replace(
32
+ "localhost",
33
+ "host.docker.internal",
34
+ ).replace(
35
+ "0.0.0.0",
36
+ "host.docker.internal",
37
+ )
38
+
39
+ if (
40
+ not docker_network_mode
41
+ or (docker_network_mode and docker_network_mode.lower()) == "host"
42
+ ):
41
43
  return url
42
44
 
43
- # For any other network mode, return the URL unchanged
44
45
  return url
@@ -8,15 +8,6 @@ import logging
8
8
  import structlog
9
9
  from structlog.typing import EventDict, WrappedLogger, Processor
10
10
 
11
- # from datetime import datetime
12
- # from logging.handlers import RotatingFileHandler
13
-
14
- # from opentelemetry.trace import get_current_span
15
- # from opentelemetry._logs import set_logger_provider
16
- # from opentelemetry.sdk._logs import LoggingHandler, LoggerProvider
17
- # from opentelemetry.sdk._logs.export import BatchLogRecordProcessor
18
- # from opentelemetry.exporter.otlp.proto.http._log_exporter import OTLPLogExporter
19
-
20
11
  TRACE_LEVEL = 1
21
12
  logging.TRACE = TRACE_LEVEL
22
13
  logging.addLevelName(TRACE_LEVEL, "TRACE")
@@ -40,15 +31,6 @@ structlog.stdlib.BoundLogger.trace = bound_logger_trace
40
31
  AGENTA_LOG_CONSOLE_ENABLED = os.getenv("AGENTA_LOG_CONSOLE_ENABLED", "true") == "true"
41
32
  AGENTA_LOG_CONSOLE_LEVEL = os.getenv("AGENTA_LOG_CONSOLE_LEVEL", "TRACE").upper()
42
33
 
43
- # AGENTA_LOG_OTLP_ENABLED = os.getenv("AGENTA_LOG_OTLP_ENABLED", "false") == "true"
44
- # AGENTA_LOG_OTLP_LEVEL = os.getenv("AGENTA_LOG_OTLP_LEVEL", "INFO").upper()
45
-
46
- # AGENTA_LOG_FILE_ENABLED = os.getenv("AGENTA_LOG_FILE_ENABLED", "true") == "true"
47
- # AGENTA_LOG_FILE_LEVEL = os.getenv("AGENTA_LOG_FILE_LEVEL", "WARNING").upper()
48
- # AGENTA_LOG_FILE_BASE = os.getenv("AGENTA_LOG_FILE_PATH", "error")
49
- # LOG_FILE_DATE = datetime.utcnow().strftime("%Y-%m-%d")
50
- # AGENTA_LOG_FILE_PATH = f"{AGENTA_LOG_FILE_BASE}-{LOG_FILE_DATE}.log"
51
-
52
34
  # COLORS
53
35
  LEVEL_COLORS = {
54
36
  "TRACE": "\033[97m",
@@ -88,15 +70,6 @@ def process_positional_args(_, __, event_dict: EventDict) -> EventDict:
88
70
  return event_dict
89
71
 
90
72
 
91
- # def add_trace_context(_, __, event_dict: EventDict) -> EventDict:
92
- # span = get_current_span()
93
- # if span and span.get_span_context().is_valid:
94
- # ctx = span.get_span_context()
95
- # event_dict["TraceId"] = format(ctx.trace_id, "032x")
96
- # event_dict["SpanId"] = format(ctx.span_id, "016x")
97
- # return event_dict
98
-
99
-
100
73
  def add_logger_info(
101
74
  logger: WrappedLogger, method_name: str, event_dict: EventDict
102
75
  ) -> EventDict:
@@ -143,36 +116,9 @@ def colored_console_renderer() -> Processor:
143
116
  return render
144
117
 
145
118
 
146
- # def plain_renderer() -> Processor:
147
- # hidden = {
148
- # "SeverityText",
149
- # "SeverityNumber",
150
- # "MethodName",
151
- # "logger_factory",
152
- # "LoggerName",
153
- # "level",
154
- # }
155
-
156
- # def render(_, __, event_dict: EventDict) -> str:
157
- # ts = event_dict.pop("Timestamp", "")[:23] + "Z"
158
- # level = event_dict.get("level", "")
159
- # msg = event_dict.pop("event", "")
160
- # padded = f"[{level:<5}]"
161
- # logger = f"[{event_dict.pop('logger', '')}]"
162
- # extras = " ".join(f"{k}={v}" for k, v in event_dict.items() if k not in hidden)
163
- # return f"{ts} {padded} {msg} {logger} {extras}"
164
-
165
- # return render
166
-
167
-
168
- # def json_renderer() -> Processor:
169
- # return structlog.processors.JSONRenderer()
170
-
171
-
172
119
  SHARED_PROCESSORS: list[Processor] = [
173
120
  structlog.processors.TimeStamper(fmt="iso", utc=True, key="Timestamp"),
174
121
  process_positional_args,
175
- # add_trace_context,
176
122
  add_logger_info,
177
123
  structlog.processors.format_exc_info,
178
124
  structlog.processors.dict_tracebacks,
@@ -193,35 +139,29 @@ def create_struct_logger(
193
139
  )
194
140
 
195
141
 
142
+ # Guard against double initialization
143
+ _LOGGING_CONFIGURED = False
144
+
196
145
  # CONFIGURE HANDLERS AND STRUCTLOG LOGGERS
197
146
  handlers = []
198
147
  loggers = []
199
148
 
200
- if AGENTA_LOG_CONSOLE_ENABLED:
201
- h = logging.StreamHandler(sys.stdout)
202
- h.setLevel(getattr(logging, AGENTA_LOG_CONSOLE_LEVEL, TRACE_LEVEL))
203
- h.setFormatter(logging.Formatter("%(message)s"))
204
- logging.getLogger("console").addHandler(h)
205
- loggers.append(create_struct_logger([colored_console_renderer()], "console"))
149
+ if AGENTA_LOG_CONSOLE_ENABLED and not _LOGGING_CONFIGURED:
150
+ _LOGGING_CONFIGURED = True
151
+
152
+ # Check if console logger already has handlers (from OSS module)
153
+ console_logger = logging.getLogger("console")
206
154
 
207
- # if AGENTA_LOG_FILE_ENABLED:
208
- # h = RotatingFileHandler(AGENTA_LOG_FILE_PATH, maxBytes=10 * 1024 * 1024, backupCount=5)
209
- # h.setLevel(getattr(logging, AGENTA_LOG_FILE_LEVEL, logging.WARNING))
210
- # h.setFormatter(logging.Formatter("%(message)s"))
211
- # logging.getLogger("file").addHandler(h)
212
- # loggers.append(create_struct_logger([plain_renderer()], "file"))
213
-
214
- # if AGENTA_LOG_OTLP_ENABLED:
215
- # provider = LoggerProvider()
216
- # exporter = OTLPLogExporter()
217
- # provider.add_log_record_processor(BatchLogRecordProcessor(exporter))
218
- # set_logger_provider(provider)
219
- # h = LoggingHandler(
220
- # level=getattr(logging, AGENTA_LOG_OTLP_LEVEL, logging.INFO), logger_provider=provider
221
- # )
222
- # h.setFormatter(logging.Formatter("%(message)s"))
223
- # logging.getLogger("otel").addHandler(h)
224
- # loggers.append(create_struct_logger([json_renderer()], "otel"))
155
+ if not console_logger.handlers:
156
+ # Only add handler if it doesn't exist yet
157
+ h = logging.StreamHandler(sys.stdout)
158
+ h.setLevel(getattr(logging, AGENTA_LOG_CONSOLE_LEVEL, TRACE_LEVEL))
159
+ h.setFormatter(logging.Formatter("%(message)s"))
160
+ console_logger.addHandler(h)
161
+ console_logger.setLevel(TRACE_LEVEL)
162
+ console_logger.propagate = False
163
+
164
+ loggers.append(create_struct_logger([colored_console_renderer()], "console"))
225
165
 
226
166
 
227
167
  class MultiLogger:
@@ -0,0 +1,23 @@
1
+ from uuid import UUID
2
+ import re
3
+ import unicodedata
4
+
5
+
6
+ def get_slug_from_name_and_id(
7
+ name: str,
8
+ id: UUID, # pylint: disable=redefined-builtin
9
+ ) -> str:
10
+ # Normalize Unicode (e.g., é → e)
11
+ name = unicodedata.normalize("NFKD", name)
12
+ # Remove non-ASCII characters
13
+ name = name.encode("ascii", "ignore").decode("ascii")
14
+ # Lowercase and remove non-word characters except hyphens and spaces
15
+ name = re.sub(r"[^\w\s-]", "", name.lower())
16
+ # Replace any sequence of hyphens or whitespace with a single hyphen
17
+ name = re.sub(r"[-\s]+", "-", name)
18
+ # Trim leading/trailing hyphens
19
+ name = name.strip("-")
20
+ # Last 12 characters of the ID
21
+ slug = f"{name}-{id.hex[-12:]}"
22
+
23
+ return slug.lower()