agenta 0.32.0a1__py3-none-any.whl → 0.33.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 (80) hide show
  1. agenta/__init__.py +2 -0
  2. agenta/client/backend/__init__.py +39 -31
  3. agenta/client/backend/admin/__init__.py +1 -0
  4. agenta/client/backend/admin/client.py +576 -0
  5. agenta/client/backend/apps/client.py +450 -68
  6. agenta/client/backend/bases/client.py +10 -10
  7. agenta/client/backend/client.py +112 -122
  8. agenta/client/backend/containers/client.py +70 -28
  9. agenta/client/backend/core/http_client.py +3 -3
  10. agenta/client/backend/environments/client.py +8 -8
  11. agenta/client/backend/evaluations/client.py +46 -52
  12. agenta/client/backend/evaluators/client.py +32 -32
  13. agenta/client/backend/human_evaluations/__init__.py +1 -0
  14. agenta/client/backend/human_evaluations/client.py +1692 -0
  15. agenta/client/backend/observability/__init__.py +4 -0
  16. agenta/client/backend/observability/client.py +221 -744
  17. agenta/client/backend/testsets/client.py +38 -202
  18. agenta/client/backend/types/__init__.py +34 -28
  19. agenta/client/backend/types/account_response.py +24 -0
  20. agenta/client/backend/types/app_variant_revision.py +2 -1
  21. agenta/client/backend/types/{create_trace_response.py → delete_evaluation.py} +2 -3
  22. agenta/client/backend/types/{evaluation_scenario_score_update.py → legacy_scope_request.py} +2 -2
  23. agenta/client/backend/types/legacy_scopes_response.py +29 -0
  24. agenta/client/backend/types/{human_evaluation_update.py → legacy_user_request.py} +4 -4
  25. agenta/client/backend/types/{span_variant.py → legacy_user_response.py} +2 -4
  26. agenta/client/backend/types/organization_membership_request.py +25 -0
  27. agenta/client/backend/types/organization_request.py +23 -0
  28. agenta/client/backend/types/permission.py +4 -0
  29. agenta/client/backend/types/{llm_tokens.py → project_membership_request.py} +8 -5
  30. agenta/client/backend/types/project_request.py +26 -0
  31. agenta/client/backend/types/project_scope.py +29 -0
  32. agenta/client/backend/types/provider_kind.py +1 -1
  33. agenta/client/backend/types/reference.py +22 -0
  34. agenta/client/backend/types/role.py +15 -0
  35. agenta/client/backend/types/scopes_response_model.py +22 -0
  36. agenta/client/backend/types/score.py +1 -1
  37. agenta/client/backend/types/secret_response_dto.py +2 -2
  38. agenta/client/backend/types/user_request.py +22 -0
  39. agenta/client/backend/types/workspace_membership_request.py +26 -0
  40. agenta/client/backend/types/workspace_request.py +25 -0
  41. agenta/client/backend/variants/client.py +208 -42
  42. agenta/client/backend/vault/client.py +11 -9
  43. agenta/sdk/__init__.py +3 -0
  44. agenta/sdk/agenta_init.py +3 -1
  45. agenta/sdk/assets.py +4 -4
  46. agenta/sdk/decorators/routing.py +129 -23
  47. agenta/sdk/decorators/tracing.py +16 -4
  48. agenta/sdk/litellm/litellm.py +44 -8
  49. agenta/sdk/litellm/mockllm.py +2 -2
  50. agenta/sdk/litellm/mocks/__init__.py +9 -3
  51. agenta/sdk/managers/apps.py +64 -0
  52. agenta/sdk/managers/shared.py +2 -2
  53. agenta/sdk/middleware/auth.py +156 -53
  54. agenta/sdk/middleware/config.py +28 -16
  55. agenta/sdk/middleware/inline.py +1 -1
  56. agenta/sdk/middleware/mock.py +1 -1
  57. agenta/sdk/middleware/otel.py +1 -1
  58. agenta/sdk/middleware/vault.py +1 -1
  59. agenta/sdk/tracing/exporters.py +0 -1
  60. agenta/sdk/tracing/inline.py +26 -30
  61. agenta/sdk/types.py +12 -9
  62. {agenta-0.32.0a1.dist-info → agenta-0.33.0.dist-info}/METADATA +23 -20
  63. {agenta-0.32.0a1.dist-info → agenta-0.33.0.dist-info}/RECORD +69 -63
  64. agenta/client/backend/observability_v_1/__init__.py +0 -5
  65. agenta/client/backend/observability_v_1/client.py +0 -763
  66. agenta/client/backend/types/create_span.py +0 -45
  67. agenta/client/backend/types/human_evaluation_scenario_update.py +0 -30
  68. agenta/client/backend/types/new_human_evaluation.py +0 -27
  69. agenta/client/backend/types/outputs.py +0 -5
  70. agenta/client/backend/types/span.py +0 -42
  71. agenta/client/backend/types/span_detail.py +0 -44
  72. agenta/client/backend/types/span_status_code.py +0 -5
  73. agenta/client/backend/types/trace_detail.py +0 -44
  74. agenta/client/backend/types/with_pagination.py +0 -26
  75. /agenta/client/backend/{observability_v_1 → observability}/types/__init__.py +0 -0
  76. /agenta/client/backend/{observability_v_1 → observability}/types/format.py +0 -0
  77. /agenta/client/backend/{observability_v_1 → observability}/types/query_analytics_response.py +0 -0
  78. /agenta/client/backend/{observability_v_1 → observability}/types/query_traces_response.py +0 -0
  79. {agenta-0.32.0a1.dist-info → agenta-0.33.0.dist-info}/WHEEL +0 -0
  80. {agenta-0.32.0a1.dist-info → agenta-0.33.0.dist-info}/entry_points.txt +0 -0
@@ -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
+ )
45
49
 
46
- app.include_router(router, prefix="")
50
+ app.include_router(router, prefix=AGENTA_RUNTIME_PREFIX)
51
+
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,
@@ -142,8 +148,8 @@ class entrypoint:
142
148
  app.add_middleware(InlineMiddleware)
143
149
  app.add_middleware(VaultMiddleware)
144
150
  app.add_middleware(ConfigMiddleware)
145
- app.add_middleware(OTelMiddleware)
146
151
  app.add_middleware(AuthMiddleware)
152
+ app.add_middleware(OTelMiddleware)
147
153
  app.add_middleware(CORSMiddleware)
148
154
  ### ------------------ #
149
155
 
@@ -175,14 +181,22 @@ class entrypoint:
175
181
  self.update_run_wrapper_signature(wrapper=run_wrapper)
176
182
 
177
183
  run_route = f"{entrypoint._run_path}{route_path}"
178
- app.post(run_route, response_model=BaseResponse)(run_wrapper)
184
+ app.post(
185
+ run_route,
186
+ response_model=BaseResponse,
187
+ response_model_exclude_none=True,
188
+ )(run_wrapper)
179
189
 
180
190
  # LEGACY
181
191
  # TODO: Removing this implies breaking changes in :
182
192
  # - calls to /generate_deployed must be replaced with calls to /run
183
193
  if route_path == "":
184
194
  run_route = entrypoint._legacy_generate_deployed_path
185
- app.post(run_route, response_model=BaseResponse)(run_wrapper)
195
+ app.post(
196
+ run_route,
197
+ response_model=BaseResponse,
198
+ response_model_exclude_none=True,
199
+ )(run_wrapper)
186
200
  # LEGACY
187
201
  ### ----------- #
188
202
 
@@ -203,21 +217,33 @@ class entrypoint:
203
217
  self.update_test_wrapper_signature(wrapper=test_wrapper, config_instance=config)
204
218
 
205
219
  test_route = f"{entrypoint._test_path}{route_path}"
206
- app.post(test_route, response_model=BaseResponse)(test_wrapper)
220
+ app.post(
221
+ test_route,
222
+ response_model=BaseResponse,
223
+ response_model_exclude_none=True,
224
+ )(test_wrapper)
207
225
 
208
226
  # LEGACY
209
227
  # TODO: Removing this implies breaking changes in :
210
228
  # - calls to /generate must be replaced with calls to /test
211
229
  if route_path == "":
212
230
  test_route = entrypoint._legacy_generate_path
213
- app.post(test_route, response_model=BaseResponse)(test_wrapper)
231
+ app.post(
232
+ test_route,
233
+ response_model=BaseResponse,
234
+ response_model_exclude_none=True,
235
+ )(test_wrapper)
214
236
  # LEGACY
215
237
 
216
238
  # LEGACY
217
239
  # TODO: Removing this implies no breaking changes
218
240
  if route_path == "":
219
241
  test_route = entrypoint._legacy_playground_run_path
220
- app.post(test_route, response_model=BaseResponse)(test_wrapper)
242
+ app.post(
243
+ test_route,
244
+ response_model=BaseResponse,
245
+ response_model_exclude_none=True,
246
+ )(test_wrapper)
221
247
  # LEGACY
222
248
  ### ------------ #
223
249
 
@@ -249,17 +275,18 @@ class entrypoint:
249
275
  )
250
276
  # LEGACY
251
277
 
252
- app.openapi_schema = None # Forces FastAPI to re-generate the schema
253
- openapi_schema = app.openapi()
254
- openapi_schema["agenta_sdk"] = {"version": get_current_version()}
278
+ openapi_schema = self.openapi()
279
+
255
280
  for _route in entrypoint.routes:
256
281
  if _route["config"] is not None:
257
282
  self.override_config_in_schema(
258
283
  openapi_schema=openapi_schema,
259
284
  func_name=_route["func"],
260
- endpoint=_route["endpoint"],
285
+ endpoint=_route["endpoint"].replace(AGENTA_RUNTIME_PREFIX, ""),
261
286
  config=_route["config"],
262
287
  )
288
+
289
+ app.openapi_schema = openapi_schema
263
290
  ### --------------- #
264
291
 
265
292
  def parse_config(self) -> Tuple[Optional[Type[BaseModel]], Dict[str, Any]]:
@@ -369,7 +396,9 @@ class entrypoint:
369
396
  ):
370
397
  display_exception("Application Exception")
371
398
 
372
- status_code = 500
399
+ status_code = (
400
+ getattr(error, "status_code") if hasattr(error, "status_code") else 500
401
+ )
373
402
  stacktrace = format_exception(error, value=error, tb=error.__traceback__) # type: ignore
374
403
 
375
404
  raise HTTPException(
@@ -430,8 +459,8 @@ class entrypoint:
430
459
  link = context.link
431
460
 
432
461
  tree = None
433
- _tree_id = link.get("tree_id") if link else None # in int format
434
- tree_id = str(UUID(int=_tree_id)) if _tree_id else None # in uuid_as_str format
462
+ _tree_id = link.get("tree_id") if link else None # in int format
463
+ tree_id = str(UUID(int=_tree_id)) if _tree_id else None # in uuid_as_str format
435
464
 
436
465
  if _tree_id is not None:
437
466
  if inline:
@@ -544,6 +573,82 @@ class entrypoint:
544
573
  )
545
574
  )
546
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
+
547
652
  def override_config_in_schema(
548
653
  self,
549
654
  openapi_schema: dict,
@@ -553,6 +658,7 @@ class entrypoint:
553
658
  ):
554
659
  """Override config in OpenAPI schema to add agenta-specific metadata."""
555
660
  endpoint = endpoint[1:].replace("/", "_")
661
+
556
662
  schema_key = f"Body_{func_name}_{endpoint}_post"
557
663
  schema_to_override = openapi_schema["components"]["schemas"][schema_key]
558
664
 
@@ -560,7 +666,7 @@ class entrypoint:
560
666
  config_class_name = type(config).__name__
561
667
  config_schema = openapi_schema["components"]["schemas"][config_class_name]
562
668
  # Process each field in the config class
563
- for field_name, field in config.__class__.__fields__.items():
669
+ for field_name, field in config.__class__.model_fields.items():
564
670
  # Check if field has Annotated metadata for MultipleChoice
565
671
  if hasattr(field, "metadata") and field.metadata:
566
672
  for meta in field.metadata:
@@ -165,15 +165,27 @@ class instrument: # pylint: disable=invalid-name
165
165
  usage = {"total_tokens": usage}
166
166
 
167
167
  span.set_attributes(
168
- attributes={"total": cost},
168
+ attributes={"total": float(cost) if cost else None},
169
169
  namespace="metrics.unit.costs",
170
170
  )
171
171
  span.set_attributes(
172
172
  attributes=(
173
173
  {
174
- "prompt": usage.get("prompt_tokens", None),
175
- "completion": usage.get("completion_tokens", None),
176
- "total": usage.get("total_tokens", None),
174
+ "prompt": (
175
+ float(usage.get("prompt_tokens"))
176
+ if usage.get("prompt_tokens", None)
177
+ else None
178
+ ),
179
+ "completion": (
180
+ float(usage.get("completion_tokens"))
181
+ if usage.get("completion_tokens", None)
182
+ else None
183
+ ),
184
+ "total": (
185
+ float(usage.get("total_tokens", None))
186
+ if usage.get("total_tokens", None)
187
+ else None
188
+ ),
177
189
  }
178
190
  ),
179
191
  namespace="metrics.unit.tokens",
@@ -154,16 +154,34 @@ def litellm_handler():
154
154
  pass
155
155
 
156
156
  span.set_attributes(
157
- attributes={"total": kwargs.get("response_cost")},
157
+ attributes={
158
+ "total": (
159
+ float(kwargs.get("response_cost"))
160
+ if kwargs.get("response_cost")
161
+ else None
162
+ )
163
+ },
158
164
  namespace="metrics.unit.costs",
159
165
  )
160
166
 
161
167
  span.set_attributes(
162
168
  attributes=(
163
169
  {
164
- "prompt": response_obj.usage.prompt_tokens,
165
- "completion": response_obj.usage.completion_tokens,
166
- "total": response_obj.usage.total_tokens,
170
+ "prompt": (
171
+ float(response_obj.usage.prompt_tokens)
172
+ if response_obj.usage.prompt_tokens
173
+ else None
174
+ ),
175
+ "completion": (
176
+ float(response_obj.usage.completion_tokens)
177
+ if response_obj.usage.completion_tokens
178
+ else None
179
+ ),
180
+ "total": (
181
+ float(response_obj.usage.total_tokens)
182
+ if response_obj.usage.total_tokens
183
+ else None
184
+ ),
167
185
  }
168
186
  ),
169
187
  namespace="metrics.unit.tokens",
@@ -264,16 +282,34 @@ def litellm_handler():
264
282
  pass
265
283
 
266
284
  span.set_attributes(
267
- attributes={"total": kwargs.get("response_cost")},
285
+ attributes={
286
+ "total": (
287
+ float(kwargs.get("response_cost"))
288
+ if kwargs.get("response_cost")
289
+ else None
290
+ )
291
+ },
268
292
  namespace="metrics.unit.costs",
269
293
  )
270
294
 
271
295
  span.set_attributes(
272
296
  attributes=(
273
297
  {
274
- "prompt": response_obj.usage.prompt_tokens,
275
- "completion": response_obj.usage.completion_tokens,
276
- "total": response_obj.usage.total_tokens,
298
+ "prompt": (
299
+ float(response_obj.usage.prompt_tokens)
300
+ if response_obj.usage.prompt_tokens
301
+ else None
302
+ ),
303
+ "completion": (
304
+ float(response_obj.usage.completion_tokens)
305
+ if response_obj.usage.completion_tokens
306
+ else None
307
+ ),
308
+ "total": (
309
+ float(response_obj.usage.total_tokens)
310
+ if response_obj.usage.total_tokens
311
+ else None
312
+ ),
277
313
  }
278
314
  ),
279
315
  namespace="metrics.unit.tokens",
@@ -1,7 +1,7 @@
1
1
  from typing import Optional, Protocol, Any
2
2
 
3
- from agenta.sdk.context.routing import routing_context
4
3
  from agenta.sdk.litellm.mocks import MOCKS
4
+ from agenta.sdk.context.routing import routing_context
5
5
 
6
6
 
7
7
  class LitellmProtocol(Protocol):
@@ -19,7 +19,7 @@ async def acompletion(*args, **kwargs):
19
19
  if mock not in MOCKS:
20
20
  raise ValueError(f"Mock {mock} not found")
21
21
 
22
- return MOCKS[mock]
22
+ return MOCKS[mock](*args, **kwargs)
23
23
 
24
24
  if not litellm:
25
25
  raise ValueError("litellm not found")
@@ -1,3 +1,5 @@
1
+ from typing import Callable
2
+
1
3
  from pydantic import BaseModel
2
4
 
3
5
 
@@ -13,8 +15,8 @@ class MockResponseModel(BaseModel):
13
15
  choices: list[MockChoiceModel]
14
16
 
15
17
 
16
- MOCKS = {
17
- "hello": MockResponseModel(
18
+ def hello_mock_response(*args, **kwargs) -> MockResponseModel:
19
+ return MockResponseModel(
18
20
  choices=[
19
21
  MockChoiceModel(
20
22
  message=MockMessageModel(
@@ -22,5 +24,9 @@ MOCKS = {
22
24
  )
23
25
  )
24
26
  ],
25
- ),
27
+ )
28
+
29
+
30
+ MOCKS: dict[str, Callable[..., MockResponseModel]] = {
31
+ "hello": hello_mock_response,
26
32
  }
@@ -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
@@ -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