agenta 0.27.0__py3-none-any.whl → 0.27.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 (68) hide show
  1. agenta/__init__.py +3 -22
  2. agenta/cli/helper.py +1 -5
  3. agenta/client/backend/__init__.py +0 -14
  4. agenta/client/backend/apps/client.py +20 -28
  5. agenta/client/backend/client.py +2 -25
  6. agenta/client/backend/containers/client.py +1 -5
  7. agenta/client/backend/core/__init__.py +1 -2
  8. agenta/client/backend/core/client_wrapper.py +6 -6
  9. agenta/client/backend/core/file.py +11 -33
  10. agenta/client/backend/core/http_client.py +18 -24
  11. agenta/client/backend/core/pydantic_utilities.py +29 -144
  12. agenta/client/backend/core/request_options.py +0 -3
  13. agenta/client/backend/core/serialization.py +42 -139
  14. agenta/client/backend/evaluations/client.py +2 -7
  15. agenta/client/backend/evaluators/client.py +1 -349
  16. agenta/client/backend/observability/client.py +2 -11
  17. agenta/client/backend/testsets/client.py +10 -10
  18. agenta/client/backend/types/__init__.py +0 -14
  19. agenta/client/backend/types/app.py +0 -1
  20. agenta/client/backend/types/app_variant_response.py +1 -3
  21. agenta/client/backend/types/create_span.py +2 -3
  22. agenta/client/backend/types/environment_output.py +0 -1
  23. agenta/client/backend/types/environment_output_extended.py +0 -1
  24. agenta/client/backend/types/evaluation.py +2 -1
  25. agenta/client/backend/types/evaluator.py +0 -2
  26. agenta/client/backend/types/evaluator_config.py +0 -1
  27. agenta/client/backend/types/human_evaluation.py +2 -1
  28. agenta/client/backend/types/llm_tokens.py +2 -2
  29. agenta/client/backend/types/span.py +0 -1
  30. agenta/client/backend/types/span_detail.py +1 -7
  31. agenta/client/backend/types/test_set_output_response.py +2 -5
  32. agenta/client/backend/types/trace_detail.py +1 -7
  33. agenta/client/backend/types/with_pagination.py +2 -4
  34. agenta/client/backend/variants/client.py +273 -1566
  35. agenta/docker/docker-assets/Dockerfile.cloud.template +1 -1
  36. agenta/sdk/__init__.py +5 -20
  37. agenta/sdk/agenta_init.py +26 -30
  38. agenta/sdk/config_manager.py +205 -0
  39. agenta/sdk/context/routing.py +5 -6
  40. agenta/sdk/decorators/routing.py +135 -142
  41. agenta/sdk/decorators/tracing.py +245 -206
  42. agenta/sdk/litellm/litellm.py +36 -47
  43. agenta/sdk/tracing/attributes.py +2 -7
  44. agenta/sdk/tracing/context.py +2 -5
  45. agenta/sdk/tracing/conventions.py +8 -10
  46. agenta/sdk/tracing/exporters.py +6 -15
  47. agenta/sdk/tracing/inline.py +98 -70
  48. agenta/sdk/tracing/processors.py +14 -55
  49. agenta/sdk/tracing/spans.py +4 -16
  50. agenta/sdk/tracing/tracing.py +50 -54
  51. agenta/sdk/types.py +2 -61
  52. agenta/sdk/utils/exceptions.py +1 -31
  53. {agenta-0.27.0.dist-info → agenta-0.27.0a1.dist-info}/METADATA +1 -1
  54. {agenta-0.27.0.dist-info → agenta-0.27.0a1.dist-info}/RECORD +56 -67
  55. agenta/client/backend/types/config_dto.py +0 -32
  56. agenta/client/backend/types/config_response_model.py +0 -32
  57. agenta/client/backend/types/evaluator_mapping_output_interface.py +0 -21
  58. agenta/client/backend/types/evaluator_output_interface.py +0 -21
  59. agenta/client/backend/types/lifecycle_dto.py +0 -24
  60. agenta/client/backend/types/reference_dto.py +0 -23
  61. agenta/client/backend/types/reference_request_model.py +0 -23
  62. agenta/sdk/managers/__init__.py +0 -6
  63. agenta/sdk/managers/config.py +0 -318
  64. agenta/sdk/managers/deployment.py +0 -45
  65. agenta/sdk/managers/shared.py +0 -639
  66. agenta/sdk/managers/variant.py +0 -182
  67. {agenta-0.27.0.dist-info → agenta-0.27.0a1.dist-info}/WHEEL +0 -0
  68. {agenta-0.27.0.dist-info → agenta-0.27.0a1.dist-info}/entry_points.txt +0 -0
@@ -1,19 +1,17 @@
1
- from typing import Type, Any, Callable, Dict, Optional, Tuple, List
2
- from annotated_types import Ge, Le, Gt, Lt
3
- from pydantic import BaseModel, HttpUrl, ValidationError
4
- from json import dumps
5
- from inspect import signature, iscoroutinefunction, Signature, Parameter, _empty
6
- from argparse import ArgumentParser
7
- from functools import wraps
8
- from asyncio import sleep, get_event_loop
9
- from traceback import format_exc, format_exception
1
+ import json
2
+ import inspect
3
+ import argparse
4
+ import asyncio
5
+ import traceback
6
+ import functools
10
7
  from pathlib import Path
11
8
  from tempfile import NamedTemporaryFile
12
- from os import environ
13
-
9
+ from typing import Any, Callable, Dict, Optional, Tuple, List
14
10
  from fastapi.middleware.cors import CORSMiddleware
15
11
  from fastapi import Body, FastAPI, UploadFile, HTTPException
16
12
 
13
+ import agenta as ag
14
+
17
15
  from agenta.sdk.context.routing import routing_context_manager, routing_context
18
16
  from agenta.sdk.context.tracing import tracing_context
19
17
  from agenta.sdk.router import router as router
@@ -33,8 +31,16 @@ from agenta.sdk.types import (
33
31
  BaseResponse,
34
32
  BinaryParam,
35
33
  )
34
+ import pydantic
35
+
36
+ from pydantic import BaseModel
37
+ from typing import Type
38
+ from annotated_types import Ge, Le, Gt, Lt
39
+
40
+ from pydantic import BaseModel, HttpUrl
41
+
42
+ from traceback import format_exc
36
43
 
37
- import agenta as ag
38
44
 
39
45
  app = FastAPI()
40
46
 
@@ -124,12 +130,12 @@ class entrypoint:
124
130
  DEFAULT_PATH = "generate"
125
131
  PLAYGROUND_PATH = "/playground"
126
132
  RUN_PATH = "/run"
127
- func_signature = signature(func)
133
+ func_signature = inspect.signature(func)
128
134
  try:
129
135
  config = (
130
136
  config_schema() if config_schema else None
131
137
  ) # we initialize the config object to be able to use it
132
- except ValidationError as e:
138
+ except pydantic.ValidationError as e:
133
139
  raise ValueError(
134
140
  f"Error initializing config_schema. Please ensure all required fields have default values: {str(e)}"
135
141
  ) from e
@@ -144,7 +150,7 @@ class entrypoint:
144
150
  self.route_path = route_path
145
151
 
146
152
  ### --- Playground --- #
147
- @wraps(func)
153
+ @functools.wraps(func)
148
154
  async def wrapper(*args, **kwargs) -> Any:
149
155
  func_params, api_config_params = self.split_kwargs(kwargs, config_params)
150
156
  self.ingest_files(func_params, ingestible_files)
@@ -153,6 +159,7 @@ class entrypoint:
153
159
 
154
160
  with routing_context_manager(
155
161
  config=api_config_params,
162
+ environment="playground",
156
163
  ):
157
164
  entrypoint_result = await self.execute_function(
158
165
  func,
@@ -205,13 +212,11 @@ class entrypoint:
205
212
  )
206
213
  ### ---------------------------- #
207
214
 
208
- ### --- Deployed --- #
209
- @wraps(func)
215
+ ### --- Deployed / Published --- #
216
+ @functools.wraps(func)
210
217
  async def wrapper_deployed(*args, **kwargs) -> Any:
211
218
  func_params = {
212
- k: v
213
- for k, v in kwargs.items()
214
- if k not in ["config", "environment", "app"]
219
+ k: v for k, v in kwargs.items() if k not in ["config", "environment"]
215
220
  }
216
221
  if not config_schema:
217
222
  if "environment" in kwargs and kwargs["environment"] is not None:
@@ -221,19 +226,10 @@ class entrypoint:
221
226
  else:
222
227
  ag.config.pull(config_name="default")
223
228
 
224
- app_id = environ.get("AGENTA_APP_ID")
225
-
226
229
  with routing_context_manager(
227
- application={
228
- "id": app_id,
229
- "slug": kwargs["app"],
230
- },
231
- variant={
232
- "slug": kwargs.get("config"),
233
- },
234
- environment={
235
- "slug": kwargs.get("environment"),
236
- },
230
+ config=config_params,
231
+ variant=kwargs["config"],
232
+ environment=kwargs["environment"],
237
233
  ):
238
234
  entrypoint_result = await self.execute_function(
239
235
  func,
@@ -256,7 +252,7 @@ class entrypoint:
256
252
 
257
253
  route_deployed = f"{RUN_PATH}{route_path}"
258
254
  app.post(route_deployed, response_model=BaseResponse)(wrapper_deployed)
259
- ### ---------------- #
255
+ ### ---------------------------- #
260
256
 
261
257
  ### --- Update OpenAPI --- #
262
258
  app.openapi_schema = None # Forces FastAPI to re-generate the schema
@@ -287,8 +283,8 @@ class entrypoint:
287
283
 
288
284
  def extract_ingestible_files(
289
285
  self,
290
- func_signature: Signature,
291
- ) -> Dict[str, Parameter]:
286
+ func_signature: inspect.Signature,
287
+ ) -> Dict[str, inspect.Parameter]:
292
288
  """Extract parameters annotated as InFile from function signature."""
293
289
 
294
290
  return {
@@ -315,7 +311,7 @@ class entrypoint:
315
311
  def ingest_files(
316
312
  self,
317
313
  func_params: Dict[str, Any],
318
- ingestible_files: Dict[str, Parameter],
314
+ ingestible_files: Dict[str, inspect.Parameter],
319
315
  ) -> None:
320
316
  """Ingest files specified in function parameters."""
321
317
 
@@ -323,65 +319,6 @@ class entrypoint:
323
319
  if name in func_params and func_params[name] is not None:
324
320
  func_params[name] = self.ingest_file(func_params[name])
325
321
 
326
- async def execute_function(
327
- self,
328
- func: Callable[..., Any],
329
- inline_trace,
330
- *args,
331
- **func_params,
332
- ):
333
- log.info(f"---------------------------")
334
- log.info(f"Agenta SDK - running route: {repr(self.route_path or '/')}")
335
- log.info(f"---------------------------")
336
-
337
- tracing_context.set(routing_context.get())
338
-
339
- try:
340
- result = (
341
- await func(*args, **func_params["params"])
342
- if iscoroutinefunction(func)
343
- else func(*args, **func_params["params"])
344
- )
345
-
346
- return await self.handle_success(result, inline_trace)
347
-
348
- except Exception as error:
349
- self.handle_failure(error)
350
-
351
- async def handle_success(self, result: Any, inline_trace: bool):
352
- data = None
353
- trace = dict()
354
-
355
- with suppress():
356
- data = self.patch_result(result)
357
-
358
- if inline_trace:
359
- trace = await self.fetch_inline_trace(inline_trace)
360
-
361
- log.info(f"----------------------------------")
362
- log.info(f"Agenta SDK - exiting with success: 200")
363
- log.info(f"----------------------------------")
364
-
365
- return BaseResponse(data=data, trace=trace)
366
-
367
- def handle_failure(self, error: Exception):
368
- log.error("--------------------------------------------------")
369
- log.error("Agenta SDK - handling application exception below:")
370
- log.error("--------------------------------------------------")
371
- log.error(format_exc().strip("\n"))
372
- log.error("--------------------------------------------------")
373
-
374
- status_code = error.status_code if hasattr(error, "status_code") else 500
375
- message = str(error)
376
- stacktrace = format_exception(error, value=error, tb=error.__traceback__) # type: ignore
377
- detail = {"message": message, "stacktrace": stacktrace}
378
-
379
- log.error(f"----------------------------------")
380
- log.error(f"Agenta SDK - exiting with failure: {status_code}")
381
- log.error(f"----------------------------------")
382
-
383
- raise HTTPException(status_code=status_code, detail=detail)
384
-
385
322
  def patch_result(self, result: Any):
386
323
  """
387
324
  Patch the result to only include the message if the result is a FuncResponse-style dictionary with message, cost, and usage keys.
@@ -419,39 +356,92 @@ class entrypoint:
419
356
 
420
357
  return data
421
358
 
422
- async def fetch_inline_trace(self, inline_trace):
359
+ async def execute_function(
360
+ self,
361
+ func: Callable[..., Any],
362
+ inline_trace,
363
+ *args,
364
+ **func_params,
365
+ ):
366
+ log.info(f"---------------------------")
367
+ log.info(
368
+ f"Agenta SDK - running route: {repr(self.route_path if self.route_path != '' else '/')}"
369
+ )
370
+ log.info(f"---------------------------")
371
+
372
+ tracing_context.set(routing_context.get())
373
+
423
374
  WAIT_FOR_SPANS = True
424
375
  TIMEOUT = 1
425
376
  TIMESTEP = 0.1
426
377
  FINALSTEP = 0.001
427
378
  NOFSTEPS = TIMEOUT / TIMESTEP
428
379
 
429
- trace = None
380
+ data = None
381
+ trace = {}
430
382
 
431
- root_context: Dict[str, Any] = tracing_context.get().get("root")
383
+ try:
384
+ result = (
385
+ await func(*args, **func_params["params"])
386
+ if inspect.iscoroutinefunction(func)
387
+ else func(*args, **func_params["params"])
388
+ )
389
+ data = self.patch_result(result)
390
+ except Exception as e:
391
+ log.error("--------------------------------------------------")
392
+ log.error("Agenta SDK - handling application exception below:")
393
+ log.error("--------------------------------------------------")
394
+ log.error(format_exc().strip("\n"))
395
+ log.error("--------------------------------------------------")
396
+
397
+ self.handle_exception(e)
432
398
 
433
- trace_id = root_context.get("trace_id") if root_context else None
399
+ with suppress():
400
+ root_context: Dict[str, Any] = tracing_context.get().get("root")
434
401
 
435
- if trace_id is not None:
436
- if inline_trace:
437
- if WAIT_FOR_SPANS:
438
- remaining_steps = NOFSTEPS
402
+ trace_id = root_context.get("trace_id") if root_context else None
439
403
 
440
- while (
441
- not ag.tracing.is_inline_trace_ready(trace_id)
442
- and remaining_steps > 0
443
- ):
444
- await sleep(TIMESTEP)
404
+ if trace_id is not None:
405
+ if inline_trace:
406
+ if WAIT_FOR_SPANS:
407
+ remaining_steps = NOFSTEPS
445
408
 
446
- remaining_steps -= 1
409
+ while (
410
+ not ag.tracing.is_inline_trace_ready(trace_id)
411
+ and remaining_steps > 0
412
+ ):
413
+ await asyncio.sleep(TIMESTEP)
447
414
 
448
- await sleep(FINALSTEP)
415
+ remaining_steps -= 1
449
416
 
450
- trace = ag.tracing.get_inline_trace(trace_id)
451
- else:
452
- trace = {"trace_id": trace_id}
417
+ await asyncio.sleep(FINALSTEP)
418
+
419
+ trace = ag.tracing.get_inline_trace(trace_id)
420
+ else:
421
+ trace = {"trace_id": trace_id}
422
+
423
+ response = BaseResponse(data=data, trace=trace)
453
424
 
454
- return trace
425
+ log.info(f"----------------------------------")
426
+ log.info(f"Agenta SDK - exiting successfully: 200")
427
+ log.info(f"----------------------------------")
428
+
429
+ return response
430
+
431
+ def handle_exception(self, e: Exception):
432
+ status_code = e.status_code if hasattr(e, "status_code") else 500
433
+ message = str(e)
434
+ stacktrace = traceback.format_exception(e, value=e, tb=e.__traceback__) # type: ignore
435
+ detail = {"message": message, "stacktrace": stacktrace}
436
+
437
+ log.error(f"----------------------------------------")
438
+ log.error(f"Agenta SDK - exiting with HTTPException: {status_code}")
439
+ log.error(f"----------------------------------------")
440
+
441
+ raise HTTPException(
442
+ status_code=status_code,
443
+ detail=detail,
444
+ )
455
445
 
456
446
  def update_wrapper_signature(
457
447
  self, wrapper: Callable[..., Any], updated_params: List
@@ -461,25 +451,25 @@ class entrypoint:
461
451
 
462
452
  Args:
463
453
  wrapper (callable): A callable object, such as a function or a method, that requires a signature update.
464
- updated_params (List[Parameter]): A list of `Parameter` objects representing the updated parameters
454
+ updated_params (List[inspect.Parameter]): A list of `inspect.Parameter` objects representing the updated parameters
465
455
  for the wrapper function.
466
456
  """
467
457
 
468
- wrapper_signature = signature(wrapper)
458
+ wrapper_signature = inspect.signature(wrapper)
469
459
  wrapper_signature = wrapper_signature.replace(parameters=updated_params)
470
460
  wrapper.__signature__ = wrapper_signature # type: ignore
471
461
 
472
462
  def update_function_signature(
473
463
  self,
474
464
  wrapper: Callable[..., Any],
475
- func_signature: Signature,
465
+ func_signature: inspect.Signature,
476
466
  config_class: Type[BaseModel], # TODO: change to our type
477
467
  config_dict: Dict[str, Any],
478
- ingestible_files: Dict[str, Parameter],
468
+ ingestible_files: Dict[str, inspect.Parameter],
479
469
  ) -> None:
480
470
  """Update the function signature to include new parameters."""
481
471
 
482
- updated_params: List[Parameter] = []
472
+ updated_params: List[inspect.Parameter] = []
483
473
  if config_class:
484
474
  self.add_config_params_to_parser(updated_params, config_class)
485
475
  else:
@@ -490,21 +480,21 @@ class entrypoint:
490
480
  def update_deployed_function_signature(
491
481
  self,
492
482
  wrapper: Callable[..., Any],
493
- func_signature: Signature,
494
- ingestible_files: Dict[str, Parameter],
483
+ func_signature: inspect.Signature,
484
+ ingestible_files: Dict[str, inspect.Parameter],
495
485
  ) -> None:
496
486
  """Update the function signature to include new parameters."""
497
487
 
498
- updated_params: List[Parameter] = []
488
+ updated_params: List[inspect.Parameter] = []
499
489
  self.add_func_params_to_parser(updated_params, func_signature, ingestible_files)
500
490
  for param in [
501
491
  "config",
502
492
  "environment",
503
493
  ]: # we add the config and environment parameters
504
494
  updated_params.append(
505
- Parameter(
495
+ inspect.Parameter(
506
496
  name=param,
507
- kind=Parameter.KEYWORD_ONLY,
497
+ kind=inspect.Parameter.KEYWORD_ONLY,
508
498
  default=Body(None),
509
499
  annotation=str,
510
500
  )
@@ -518,9 +508,9 @@ class entrypoint:
518
508
  for name, field in config_class.__fields__.items():
519
509
  assert field.default is not None, f"Field {name} has no default value"
520
510
  updated_params.append(
521
- Parameter(
511
+ inspect.Parameter(
522
512
  name=name,
523
- kind=Parameter.KEYWORD_ONLY,
513
+ kind=inspect.Parameter.KEYWORD_ONLY,
524
514
  annotation=field.annotation.__name__,
525
515
  default=Body(field.default),
526
516
  )
@@ -535,9 +525,9 @@ class entrypoint:
535
525
  len(param.__class__.__bases__) == 1
536
526
  ), f"Inherited standard type of {param.__class__} needs to be one."
537
527
  updated_params.append(
538
- Parameter(
528
+ inspect.Parameter(
539
529
  name=name,
540
- kind=Parameter.KEYWORD_ONLY,
530
+ kind=inspect.Parameter.KEYWORD_ONLY,
541
531
  default=Body(param),
542
532
  annotation=param.__class__.__bases__[
543
533
  0
@@ -550,23 +540,23 @@ class entrypoint:
550
540
  def add_func_params_to_parser(
551
541
  self,
552
542
  updated_params: list,
553
- func_signature: Signature,
554
- ingestible_files: Dict[str, Parameter],
543
+ func_signature: inspect.Signature,
544
+ ingestible_files: Dict[str, inspect.Parameter],
555
545
  ) -> None:
556
546
  """Add function parameters to function signature."""
557
547
  for name, param in func_signature.parameters.items():
558
548
  if name in ingestible_files:
559
549
  updated_params.append(
560
- Parameter(name, param.kind, annotation=UploadFile)
550
+ inspect.Parameter(name, param.kind, annotation=UploadFile)
561
551
  )
562
552
  else:
563
553
  assert (
564
554
  len(param.default.__class__.__bases__) == 1
565
555
  ), f"Inherited standard type of {param.default.__class__} needs to be one."
566
556
  updated_params.append(
567
- Parameter(
557
+ inspect.Parameter(
568
558
  name,
569
- Parameter.KEYWORD_ONLY,
559
+ inspect.Parameter.KEYWORD_ONLY,
570
560
  default=Body(..., embed=True),
571
561
  annotation=param.default.__class__.__bases__[
572
562
  0
@@ -595,7 +585,7 @@ class entrypoint:
595
585
  def handle_terminal_run(
596
586
  self,
597
587
  func: Callable,
598
- func_params: Dict[str, Parameter],
588
+ func_params: Dict[str, inspect.Parameter],
599
589
  config_params: Dict[str, Any],
600
590
  ingestible_files: Dict,
601
591
  ):
@@ -609,7 +599,7 @@ class entrypoint:
609
599
  """
610
600
 
611
601
  # For required parameters, we add them as arguments
612
- parser = ArgumentParser()
602
+ parser = argparse.ArgumentParser()
613
603
  for name, param in func_params.items():
614
604
  if name in ingestible_files:
615
605
  parser.add_argument(name, type=str)
@@ -654,7 +644,7 @@ class entrypoint:
654
644
  }
655
645
  )
656
646
 
657
- loop = get_event_loop()
647
+ loop = asyncio.get_event_loop()
658
648
 
659
649
  with routing_context_manager(
660
650
  config=args_config_params,
@@ -684,13 +674,13 @@ class entrypoint:
684
674
  if SHOW_DATA:
685
675
  log.info(" ")
686
676
  log.info(f"data:")
687
- log.info(dumps(result.data, indent=2))
677
+ log.info(json.dumps(result.data, indent=2))
688
678
 
689
679
  if SHOW_TRACE:
690
680
  log.info(" ")
691
681
  log.info(f"trace:")
692
682
  log.info(f"----------------")
693
- log.info(dumps(result.trace.get("spans", []), indent=2))
683
+ log.info(json.dumps(result.trace.get("spans", []), indent=2))
694
684
  log.info(f"----------------")
695
685
 
696
686
  log.info("\n==========================\n")
@@ -900,7 +890,10 @@ class entrypoint:
900
890
  subschema["maximum"] = param_val.maxval # type: ignore
901
891
  subschema["default"] = param_val
902
892
 
903
- elif isinstance(param_val, Parameter) and param_val.annotation is DictInput:
893
+ elif (
894
+ isinstance(param_val, inspect.Parameter)
895
+ and param_val.annotation is DictInput
896
+ ):
904
897
  subschema = find_in_schema(
905
898
  param_val.annotation.__schema_type_properties__(),
906
899
  schema_to_override,
@@ -919,7 +912,7 @@ class entrypoint:
919
912
  subschema["default"] = param_val
920
913
 
921
914
  elif (
922
- isinstance(param_val, Parameter)
915
+ isinstance(param_val, inspect.Parameter)
923
916
  and param_val.annotation is MessagesInput
924
917
  ):
925
918
  subschema = find_in_schema(
@@ -931,7 +924,7 @@ class entrypoint:
931
924
  subschema["default"] = param_val.default
932
925
 
933
926
  elif (
934
- isinstance(param_val, Parameter)
927
+ isinstance(param_val, inspect.Parameter)
935
928
  and param_val.annotation is FileInputURL
936
929
  ):
937
930
  subschema = find_in_schema(
@@ -955,6 +948,6 @@ class entrypoint:
955
948
  "title": str(param_name).capitalize(),
956
949
  "type": get_type_from_param(param_val),
957
950
  }
958
- if param_val.default != _empty:
951
+ if param_val.default != inspect._empty:
959
952
  subschema["default"] = param_val.default # type: ignore
960
953
  schema_to_override[param_name] = subschema