synth-ai 0.3.1.dev3__tar.gz → 0.3.2.dev2__tar.gz

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 (361) hide show
  1. {synth_ai-0.3.1.dev3/synth_ai.egg-info → synth_ai-0.3.2.dev2}/PKG-INFO +5 -7
  2. {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/README.md +4 -6
  3. {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/pyproject.toml +1 -1
  4. {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/cli/commands/baseline/core.py +5 -7
  5. {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/cli/commands/demo/core.py +1 -1
  6. {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/cli/commands/train/validation.py +11 -6
  7. {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/cli/demo_apps/core/cli.py +2 -2
  8. {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/cli/demos/rl_demo.py +1 -1
  9. {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/cli/deploy.py +14 -11
  10. {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/cli/infra/turso.py +5 -1
  11. {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/cli/lib/modal.py +1 -1
  12. {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/cli/lib/prompts.py +1 -1
  13. {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/cli/local/experiment_queue/config_utils.py +6 -2
  14. {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/cli/local/experiment_queue/schemas.py +3 -3
  15. {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/cli/utils/experiments.py +8 -8
  16. {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/core/cfgs.py +45 -46
  17. {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/core/config/resolver.py +4 -0
  18. {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/core/integrations/cloudflare.py +15 -4
  19. {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/core/integrations/modal.py +39 -40
  20. synth_ai-0.3.2.dev2/synth_ai/core/telemetry.py +282 -0
  21. {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/core/uvicorn.py +36 -29
  22. synth_ai-0.3.2.dev2/synth_ai/sdk/api/research_agent/__init__.py +86 -0
  23. {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/sdk/api/research_agent/cli.py +16 -3
  24. synth_ai-0.3.2.dev2/synth_ai/sdk/api/research_agent/config.py +357 -0
  25. {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/sdk/api/research_agent/job.py +273 -90
  26. {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/sdk/api/train/builders.py +7 -0
  27. {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/sdk/api/train/cli.py +41 -1
  28. {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/sdk/api/train/configs/prompt_learning.py +17 -5
  29. {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/sdk/api/train/env_resolver.py +9 -2
  30. {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/sdk/api/train/pollers.py +26 -3
  31. {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/sdk/api/train/prompt_learning.py +11 -5
  32. {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/sdk/api/train/rl.py +12 -6
  33. {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/sdk/api/train/sft.py +12 -6
  34. {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/sdk/api/train/utils.py +57 -23
  35. {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/sdk/api/train/validators.py +90 -23
  36. {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/sdk/baseline/discovery.py +3 -1
  37. {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/sdk/learning/prompt_learning_client.py +3 -1
  38. {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/sdk/streaming/handlers.py +88 -2
  39. {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/sdk/streaming/streamer.py +3 -0
  40. {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/sdk/task/__init__.py +14 -0
  41. {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/sdk/task/apps/__init__.py +1 -0
  42. {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/sdk/task/contracts.py +65 -3
  43. {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/sdk/task/in_process.py +214 -46
  44. {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/sdk/task/in_process_runner.py +10 -1
  45. {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/sdk/task/inference_api.py +92 -14
  46. {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/sdk/task/proxy.py +36 -0
  47. {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/sdk/task/server.py +18 -12
  48. {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/sdk/task/trace_correlation_helpers.py +178 -0
  49. {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2/synth_ai.egg-info}/PKG-INFO +5 -7
  50. {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai.egg-info/SOURCES.txt +1 -0
  51. synth_ai-0.3.1.dev3/synth_ai/core/telemetry.py +0 -219
  52. synth_ai-0.3.1.dev3/synth_ai/sdk/api/research_agent/__init__.py +0 -54
  53. {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/LICENSE +0 -0
  54. {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/MANIFEST.in +0 -0
  55. {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/setup.cfg +0 -0
  56. {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/__init__.py +0 -0
  57. {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/__main__.py +0 -0
  58. {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/cli/__init__.py +0 -0
  59. {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/cli/__main__.py +0 -0
  60. {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/cli/_internal/__init__.py +0 -0
  61. {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/cli/_internal/modal_wrapper.py +0 -0
  62. {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/cli/_internal/storage.py +0 -0
  63. {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/cli/_internal/typer_patch.py +0 -0
  64. {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/cli/_internal/validate_task_app.py +0 -0
  65. {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/cli/agents/__init__.py +0 -0
  66. {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/cli/agents/claude.py +0 -0
  67. {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/cli/agents/codex.py +0 -0
  68. {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/cli/agents/opencode.py +0 -0
  69. {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/cli/commands/__init__.py +0 -0
  70. {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/cli/commands/artifacts/__init__.py +0 -0
  71. {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/cli/commands/artifacts/client.py +0 -0
  72. {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/cli/commands/artifacts/config.py +0 -0
  73. {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/cli/commands/artifacts/core.py +0 -0
  74. {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/cli/commands/artifacts/download.py +0 -0
  75. {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/cli/commands/artifacts/export.py +0 -0
  76. {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/cli/commands/artifacts/list.py +0 -0
  77. {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/cli/commands/artifacts/parsing.py +0 -0
  78. {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/cli/commands/artifacts/show.py +0 -0
  79. {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/cli/commands/baseline/__init__.py +0 -0
  80. {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/cli/commands/baseline/list.py +0 -0
  81. {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/cli/commands/demo/__init__.py +0 -0
  82. {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/cli/commands/eval/__init__.py +0 -0
  83. {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/cli/commands/eval/core.py +0 -0
  84. {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/cli/commands/eval/errors.py +0 -0
  85. {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/cli/commands/eval/validation.py +0 -0
  86. {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/cli/commands/filter/__init__.py +0 -0
  87. {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/cli/commands/filter/core.py +0 -0
  88. {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/cli/commands/filter/errors.py +0 -0
  89. {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/cli/commands/filter/validation.py +0 -0
  90. {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/cli/commands/help/__init__.py +0 -0
  91. {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/cli/commands/help/core.py +0 -0
  92. {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/cli/commands/scan/__init__.py +0 -0
  93. {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/cli/commands/scan/cloudflare_scanner.py +0 -0
  94. {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/cli/commands/scan/core.py +0 -0
  95. {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/cli/commands/scan/health_checker.py +0 -0
  96. {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/cli/commands/scan/local_scanner.py +0 -0
  97. {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/cli/commands/scan/models.py +0 -0
  98. {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/cli/commands/smoke/__init__.py +0 -0
  99. {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/cli/commands/smoke/core.py +0 -0
  100. {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/cli/commands/status/__init__.py +0 -0
  101. {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/cli/commands/status/client.py +0 -0
  102. {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/cli/commands/status/config.py +0 -0
  103. {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/cli/commands/status/errors.py +0 -0
  104. {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/cli/commands/status/formatters.py +0 -0
  105. {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/cli/commands/status/subcommands/__init__.py +0 -0
  106. {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/cli/commands/status/subcommands/files.py +0 -0
  107. {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/cli/commands/status/subcommands/jobs.py +0 -0
  108. {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/cli/commands/status/subcommands/models.py +0 -0
  109. {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/cli/commands/status/subcommands/pricing.py +0 -0
  110. {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/cli/commands/status/subcommands/runs.py +0 -0
  111. {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/cli/commands/status/subcommands/session.py +0 -0
  112. {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/cli/commands/status/subcommands/summary.py +0 -0
  113. {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/cli/commands/status/subcommands/usage.py +0 -0
  114. {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/cli/commands/status/utils.py +0 -0
  115. {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/cli/commands/train/__init__.py +0 -0
  116. {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/cli/commands/train/core.py +0 -0
  117. {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/cli/commands/train/errors.py +0 -0
  118. {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/cli/commands/train/judge_schemas.py +0 -0
  119. {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/cli/commands/train/judge_validation.py +0 -0
  120. {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/cli/demo_apps/__init__.py +0 -0
  121. {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/cli/demo_apps/core/__init__.py +0 -0
  122. {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/cli/demo_apps/crafter/__init__.py +0 -0
  123. {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/cli/demo_apps/crafter/crafter_fft_4b.toml +0 -0
  124. {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/cli/demo_apps/crafter/grpo_crafter_task_app.py +0 -0
  125. {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/cli/demo_apps/crafter/rl_from_base_qwen4b.toml +0 -0
  126. {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/cli/demo_apps/demo_registry.py +0 -0
  127. {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/cli/demo_apps/demo_task_apps/__init__.py +0 -0
  128. {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/cli/demo_apps/demo_task_apps/core.py +0 -0
  129. {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/cli/demo_apps/demo_task_apps/crafter/__init__.py +0 -0
  130. {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/cli/demo_apps/demo_task_apps/crafter/configs/crafter_fft_4b.toml +0 -0
  131. {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/cli/demo_apps/demo_task_apps/crafter/configs/rl_from_base_qwen4b.toml +0 -0
  132. {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/cli/demo_apps/demo_task_apps/crafter/grpo_crafter_task_app.py +0 -0
  133. {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/cli/demo_apps/demo_task_apps/math/__init__.py +0 -0
  134. {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/cli/demo_apps/demo_task_apps/math/_common.py +0 -0
  135. {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/cli/demo_apps/demo_task_apps/math/app.py +0 -0
  136. {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/cli/demo_apps/demo_task_apps/math/config.toml +0 -0
  137. {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/cli/demo_apps/demo_task_apps/math/deploy_modal.py +0 -0
  138. {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/cli/demo_apps/demo_task_apps/math/modal_task_app.py +0 -0
  139. {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/cli/demo_apps/demo_task_apps/math/task_app_entry.py +0 -0
  140. {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/cli/demo_apps/math/__init__.py +0 -0
  141. {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/cli/demo_apps/math/_common.py +0 -0
  142. {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/cli/demo_apps/math/app.py +0 -0
  143. {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/cli/demo_apps/math/config.toml +0 -0
  144. {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/cli/demo_apps/math/deploy_modal.py +0 -0
  145. {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/cli/demo_apps/math/modal_task_app.py +0 -0
  146. {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/cli/demo_apps/math/task_app_entry.py +0 -0
  147. {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/cli/demo_apps/mipro/main.py +0 -0
  148. {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/cli/demo_apps/mipro/task_app.py +0 -0
  149. {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/cli/demo_apps/mipro/train_cfg.toml +0 -0
  150. {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/cli/demos/__init__.py +0 -0
  151. {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/cli/demos/demo.py +0 -0
  152. {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/cli/infra/__init__.py +0 -0
  153. {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/cli/infra/balance.py +0 -0
  154. {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/cli/infra/mcp.py +0 -0
  155. {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/cli/infra/modal_app.py +0 -0
  156. {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/cli/infra/setup.py +0 -0
  157. {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/cli/infra/status.py +0 -0
  158. {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/cli/lib/__init__.py +0 -0
  159. {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/cli/lib/agents.py +0 -0
  160. {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/cli/lib/apps/modal_app.py +0 -0
  161. {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/cli/lib/apps/task_app.py +0 -0
  162. {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/cli/lib/bin.py +0 -0
  163. {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/cli/lib/env.py +0 -0
  164. {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/cli/lib/errors.py +0 -0
  165. {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/cli/lib/plotting.py +0 -0
  166. {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/cli/lib/prompt_args.py +0 -0
  167. {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/cli/lib/sqld.py +0 -0
  168. {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/cli/lib/task_app_discovery.py +0 -0
  169. {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/cli/lib/task_app_env.py +0 -0
  170. {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/cli/lib/train_cfgs.py +0 -0
  171. {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/cli/lib/tunnel_records.py +0 -0
  172. {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/cli/local/__init__.py +0 -0
  173. {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/cli/local/experiment_queue/__init__.py +0 -0
  174. {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/cli/local/experiment_queue/api_schemas.py +0 -0
  175. {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/cli/local/experiment_queue/celery_app.py +0 -0
  176. {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/cli/local/experiment_queue/config.py +0 -0
  177. {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/cli/local/experiment_queue/database.py +0 -0
  178. {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/cli/local/experiment_queue/dispatcher.py +0 -0
  179. {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/cli/local/experiment_queue/models.py +0 -0
  180. {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/cli/local/experiment_queue/progress_info.py +0 -0
  181. {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/cli/local/experiment_queue/results.py +0 -0
  182. {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/cli/local/experiment_queue/service.py +0 -0
  183. {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/cli/local/experiment_queue/status.py +0 -0
  184. {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/cli/local/experiment_queue/status_tracker.py +0 -0
  185. {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/cli/local/experiment_queue/tasks.py +0 -0
  186. {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/cli/local/experiment_queue/trace_storage.py +0 -0
  187. {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/cli/local/experiment_queue/validation.py +0 -0
  188. {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/cli/local/session/__init__.py +0 -0
  189. {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/cli/local/session/client.py +0 -0
  190. {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/cli/local/session/constants.py +0 -0
  191. {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/cli/local/session/exceptions.py +0 -0
  192. {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/cli/local/session/manager.py +0 -0
  193. {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/cli/local/session/models.py +0 -0
  194. {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/cli/local/session/query.py +0 -0
  195. {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/cli/root.py +0 -0
  196. {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/cli/task_apps/__init__.py +0 -0
  197. {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/cli/task_apps/commands.py +0 -0
  198. {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/cli/task_apps/deploy.py +0 -0
  199. {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/cli/task_apps/list.py +0 -0
  200. {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/cli/task_apps/main.py +0 -0
  201. {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/cli/task_apps/modal_serve.py +0 -0
  202. {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/cli/task_apps/serve.py +0 -0
  203. {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/cli/training/__init__.py +0 -0
  204. {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/cli/training/train.py +0 -0
  205. {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/cli/training/train_cfg.py +0 -0
  206. {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/cli/training/watch.py +0 -0
  207. {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/cli/turso.py +0 -0
  208. {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/cli/utils/__init__.py +0 -0
  209. {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/cli/utils/queue.py +0 -0
  210. {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/cli/utils/recent.py +0 -0
  211. {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/cli/utils/traces.py +0 -0
  212. {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/contracts/__init__.py +0 -0
  213. {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/core/__init__.py +0 -0
  214. {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/core/_utils/__init__.py +0 -0
  215. {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/core/_utils/base_url.py +0 -0
  216. {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/core/_utils/http.py +0 -0
  217. {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/core/_utils/prompts.py +0 -0
  218. {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/core/_utils/task_app_state.py +0 -0
  219. {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/core/_utils/user_config.py +0 -0
  220. {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/core/apps/__init__.py +0 -0
  221. {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/core/apps/common.py +0 -0
  222. {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/core/auth.py +0 -0
  223. {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/core/config/__init__.py +0 -0
  224. {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/core/config/base.py +0 -0
  225. {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/core/env.py +0 -0
  226. {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/core/errors.py +0 -0
  227. {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/core/http.py +0 -0
  228. {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/core/integrations/__init__.py +0 -0
  229. {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/core/integrations/mcp/__init__.py +0 -0
  230. {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/core/integrations/mcp/__main__.py +0 -0
  231. {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/core/integrations/mcp/claude.py +0 -0
  232. {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/core/integrations/mcp/main.py +0 -0
  233. {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/core/integrations/mcp/setup.py +0 -0
  234. {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/core/json.py +0 -0
  235. {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/core/log_filter.py +0 -0
  236. {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/core/logging.py +0 -0
  237. {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/core/paths.py +0 -0
  238. {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/core/pricing.py +0 -0
  239. {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/core/process.py +0 -0
  240. {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/core/ssl.py +0 -0
  241. {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/core/storage/__init__.py +0 -0
  242. {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/core/task_app_state.py +0 -0
  243. {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/core/tracing_v3/__init__.py +0 -0
  244. {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/core/tracing_v3/abstractions.py +0 -0
  245. {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/core/tracing_v3/config.py +0 -0
  246. {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/core/tracing_v3/constants.py +0 -0
  247. {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/core/tracing_v3/db_config.py +0 -0
  248. {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/core/tracing_v3/decorators.py +0 -0
  249. {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/core/tracing_v3/examples/basic_usage.py +0 -0
  250. {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/core/tracing_v3/hooks.py +0 -0
  251. {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/core/tracing_v3/llm_call_record_helpers.py +0 -0
  252. {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/core/tracing_v3/lm_call_record_abstractions.py +0 -0
  253. {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/core/tracing_v3/migration_helper.py +0 -0
  254. {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/core/tracing_v3/replica_sync.py +0 -0
  255. {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/core/tracing_v3/serialization.py +0 -0
  256. {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/core/tracing_v3/session_tracer.py +0 -0
  257. {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/core/tracing_v3/storage/__init__.py +0 -0
  258. {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/core/tracing_v3/storage/base.py +0 -0
  259. {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/core/tracing_v3/storage/config.py +0 -0
  260. {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/core/tracing_v3/storage/exceptions.py +0 -0
  261. {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/core/tracing_v3/storage/factory.py +0 -0
  262. {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/core/tracing_v3/storage/types.py +0 -0
  263. {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/core/tracing_v3/storage/utils.py +0 -0
  264. {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/core/tracing_v3/trace_utils.py +0 -0
  265. {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/core/tracing_v3/turso/__init__.py +0 -0
  266. {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/core/tracing_v3/turso/daemon.py +0 -0
  267. {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/core/tracing_v3/turso/models.py +0 -0
  268. {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/core/tracing_v3/turso/native_manager.py +0 -0
  269. {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/core/tracing_v3/utils.py +0 -0
  270. {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/core/urls.py +0 -0
  271. {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/core/user_config.py +0 -0
  272. {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/data/__init__.py +0 -0
  273. {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/data/enums.py +0 -0
  274. {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/data/rewards.py +0 -0
  275. {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/data/specs.py +0 -0
  276. {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/data/traces.py +0 -0
  277. {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/py.typed +0 -0
  278. {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/sdk/__init__.py +0 -0
  279. {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/sdk/api/models/supported.py +0 -0
  280. {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/sdk/api/train/__init__.py +0 -0
  281. {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/sdk/api/train/config_finder.py +0 -0
  282. {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/sdk/api/train/configs/__init__.py +0 -0
  283. {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/sdk/api/train/configs/rl.py +0 -0
  284. {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/sdk/api/train/configs/sft.py +0 -0
  285. {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/sdk/api/train/configs/shared.py +0 -0
  286. {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/sdk/api/train/summary.py +0 -0
  287. {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/sdk/api/train/supported_algos.py +0 -0
  288. {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/sdk/api/train/task_app.py +0 -0
  289. {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/sdk/baseline/__init__.py +0 -0
  290. {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/sdk/baseline/config.py +0 -0
  291. {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/sdk/baseline/execution.py +0 -0
  292. {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/sdk/inference/__init__.py +0 -0
  293. {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/sdk/inference/client.py +0 -0
  294. {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/sdk/jobs/__init__.py +0 -0
  295. {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/sdk/jobs/client.py +0 -0
  296. {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/sdk/judging/__init__.py +0 -0
  297. {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/sdk/judging/base.py +0 -0
  298. {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/sdk/judging/client.py +0 -0
  299. {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/sdk/judging/schemas.py +0 -0
  300. {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/sdk/judging/types.py +0 -0
  301. {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/sdk/learning/__init__.py +0 -0
  302. {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/sdk/learning/algorithms.py +0 -0
  303. {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/sdk/learning/client.py +0 -0
  304. {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/sdk/learning/config.py +0 -0
  305. {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/sdk/learning/constants.py +0 -0
  306. {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/sdk/learning/core.py +0 -0
  307. {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/sdk/learning/ft_client.py +0 -0
  308. {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/sdk/learning/gateway.py +0 -0
  309. {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/sdk/learning/health.py +0 -0
  310. {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/sdk/learning/jobs.py +0 -0
  311. {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/sdk/learning/prompt_extraction.py +0 -0
  312. {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/sdk/learning/prompt_learning_types.py +0 -0
  313. {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/sdk/learning/rl/__init__.py +0 -0
  314. {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/sdk/learning/rl/client.py +0 -0
  315. {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/sdk/learning/rl/config.py +0 -0
  316. {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/sdk/learning/rl/contracts.py +0 -0
  317. {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/sdk/learning/rl/env_keys.py +0 -0
  318. {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/sdk/learning/rl/secrets.py +0 -0
  319. {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/sdk/learning/rl_client.py +0 -0
  320. {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/sdk/learning/sft/__init__.py +0 -0
  321. {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/sdk/learning/sft/client.py +0 -0
  322. {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/sdk/learning/sft/config.py +0 -0
  323. {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/sdk/learning/sft/data.py +0 -0
  324. {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/sdk/learning/sse.py +0 -0
  325. {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/sdk/learning/validators.py +0 -0
  326. {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/sdk/research_agent/__init__.py +0 -0
  327. {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/sdk/research_agent/container_builder.py +0 -0
  328. {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/sdk/research_agent/container_spec.py +0 -0
  329. {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/sdk/research_agent/defaults.py +0 -0
  330. {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/sdk/research_agent/results_collector.py +0 -0
  331. {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/sdk/specs/__init__.py +0 -0
  332. {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/sdk/specs/dataclasses.py +0 -0
  333. {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/sdk/specs/loader.py +0 -0
  334. {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/sdk/specs/serializer.py +0 -0
  335. {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/sdk/specs/validation.py +0 -0
  336. {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/sdk/streaming/__init__.py +0 -0
  337. {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/sdk/streaming/config.py +0 -0
  338. {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/sdk/streaming/types.py +0 -0
  339. {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/sdk/task/auth.py +0 -0
  340. {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/sdk/task/client.py +0 -0
  341. {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/sdk/task/config.py +0 -0
  342. {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/sdk/task/datasets.py +0 -0
  343. {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/sdk/task/errors.py +0 -0
  344. {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/sdk/task/health.py +0 -0
  345. {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/sdk/task/json.py +0 -0
  346. {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/sdk/task/rubrics/__init__.py +0 -0
  347. {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/sdk/task/rubrics/loaders.py +0 -0
  348. {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/sdk/task/rubrics/models.py +0 -0
  349. {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/sdk/task/rubrics/scoring.py +0 -0
  350. {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/sdk/task/rubrics/strict.py +0 -0
  351. {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/sdk/task/rubrics.py +0 -0
  352. {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/sdk/task/tracing_utils.py +0 -0
  353. {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/sdk/task/validators.py +0 -0
  354. {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/sdk/task/vendors.py +0 -0
  355. {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/sdk/tracing/__init__.py +0 -0
  356. {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/sdk/training/__init__.py +0 -0
  357. {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/utils/__init__.py +0 -0
  358. {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai.egg-info/dependency_links.txt +0 -0
  359. {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai.egg-info/entry_points.txt +0 -0
  360. {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai.egg-info/requires.txt +0 -0
  361. {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai.egg-info/top_level.txt +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: synth-ai
3
- Version: 0.3.1.dev3
3
+ Version: 0.3.2.dev2
4
4
  Summary: Serverless Posttraining for Agents - Core AI functionality and tracing
5
5
  Author-email: Synth AI <josh@usesynth.ai>
6
6
  License-Expression: MIT
@@ -90,9 +90,9 @@ Serverless Posttraining APIs for Developers
90
90
 
91
91
  <p align="center">
92
92
  <picture align="center">
93
- <source media="(prefers-color-scheme: dark)" srcset="https://raw.githubusercontent.com/synth-laboratories/synth-ai/main/langprobe_v2_dark.png">
94
- <source media="(prefers-color-scheme: light)" srcset="https://raw.githubusercontent.com/synth-laboratories/synth-ai/main/langprobe_v2_light.png">
95
- <img alt="Shows a bar chart comparing prompt optimization performance across Synth GEPA, Synth MIPRO, GEPA (lib), DSPy MIPRO, and DSPy GEPA with baseline vs optimized." src="https://raw.githubusercontent.com/synth-laboratories/synth-ai/main/langprobe_v2_light.png">
93
+ <source media="(prefers-color-scheme: dark)" srcset="https://raw.githubusercontent.com/synth-laboratories/synth-ai/main/assets/langprobe_v2_dark.png">
94
+ <source media="(prefers-color-scheme: light)" srcset="https://raw.githubusercontent.com/synth-laboratories/synth-ai/main/assets/langprobe_v2_light.png">
95
+ <img alt="Shows a bar chart comparing prompt optimization performance across Synth GEPA, Synth MIPRO, GEPA (lib), DSPy MIPRO, and DSPy GEPA with baseline vs optimized." src="https://raw.githubusercontent.com/synth-laboratories/synth-ai/main/assets/langprobe_v2_light.png">
96
96
  </picture>
97
97
  </p>
98
98
 
@@ -128,7 +128,7 @@ Synth is maintained by devs behind the [MIPROv2](https://scholar.google.com/cita
128
128
 
129
129
  ## Documentation
130
130
 
131
- Docs available at [docs.usesynth.ai](https://docs.usesynth.ai/overview).
131
+ **[docs.usesynth.ai](https://docs.usesynth.ai)**
132
132
 
133
133
  ## In-Process Runner (SDK)
134
134
 
@@ -150,5 +150,3 @@ result = asyncio.run(
150
150
  )
151
151
  print(result.job_id, result.status.get("status"))
152
152
  ```
153
-
154
- Env priority for the backend URL: `TARGET_BACKEND_BASE_URL` → `BACKEND_OVERRIDE` → `SYNTH_BACKEND_URL` → `BACKEND_BASE_URL` → `NEXT_PUBLIC_API_URL` → fallback to `get_backend_from_env()`. Required keys: `SYNTH_API_KEY`, `ENVIRONMENT_API_KEY`, plus any model keys used by your task app.
@@ -10,9 +10,9 @@ Serverless Posttraining APIs for Developers
10
10
 
11
11
  <p align="center">
12
12
  <picture align="center">
13
- <source media="(prefers-color-scheme: dark)" srcset="https://raw.githubusercontent.com/synth-laboratories/synth-ai/main/langprobe_v2_dark.png">
14
- <source media="(prefers-color-scheme: light)" srcset="https://raw.githubusercontent.com/synth-laboratories/synth-ai/main/langprobe_v2_light.png">
15
- <img alt="Shows a bar chart comparing prompt optimization performance across Synth GEPA, Synth MIPRO, GEPA (lib), DSPy MIPRO, and DSPy GEPA with baseline vs optimized." src="https://raw.githubusercontent.com/synth-laboratories/synth-ai/main/langprobe_v2_light.png">
13
+ <source media="(prefers-color-scheme: dark)" srcset="https://raw.githubusercontent.com/synth-laboratories/synth-ai/main/assets/langprobe_v2_dark.png">
14
+ <source media="(prefers-color-scheme: light)" srcset="https://raw.githubusercontent.com/synth-laboratories/synth-ai/main/assets/langprobe_v2_light.png">
15
+ <img alt="Shows a bar chart comparing prompt optimization performance across Synth GEPA, Synth MIPRO, GEPA (lib), DSPy MIPRO, and DSPy GEPA with baseline vs optimized." src="https://raw.githubusercontent.com/synth-laboratories/synth-ai/main/assets/langprobe_v2_light.png">
16
16
  </picture>
17
17
  </p>
18
18
 
@@ -48,7 +48,7 @@ Synth is maintained by devs behind the [MIPROv2](https://scholar.google.com/cita
48
48
 
49
49
  ## Documentation
50
50
 
51
- Docs available at [docs.usesynth.ai](https://docs.usesynth.ai/overview).
51
+ **[docs.usesynth.ai](https://docs.usesynth.ai)**
52
52
 
53
53
  ## In-Process Runner (SDK)
54
54
 
@@ -70,5 +70,3 @@ result = asyncio.run(
70
70
  )
71
71
  print(result.job_id, result.status.get("status"))
72
72
  ```
73
-
74
- Env priority for the backend URL: `TARGET_BACKEND_BASE_URL` → `BACKEND_OVERRIDE` → `SYNTH_BACKEND_URL` → `BACKEND_BASE_URL` → `NEXT_PUBLIC_API_URL` → fallback to `get_backend_from_env()`. Required keys: `SYNTH_API_KEY`, `ENVIRONMENT_API_KEY`, plus any model keys used by your task app.
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "synth-ai"
3
- version = "0.3.1.dev3"
3
+ version = "0.3.2.dev2"
4
4
  description = "Serverless Posttraining for Agents - Core AI functionality and tracing"
5
5
  authors = [{name = "Synth AI", email = "josh@usesynth.ai"}]
6
6
  license = "MIT"
@@ -37,7 +37,7 @@ class BaselineGroup(click.Group):
37
37
  ctx.meta['_original_args'] = args.copy() if isinstance(args, list) else list(args)
38
38
  return ctx
39
39
 
40
- def resolve_command(self, ctx: click.Context, args: list[str]) -> tuple[click.Command | None, str, list[str]]:
40
+ def resolve_command(self, ctx: click.Context, args: list[str]) -> tuple[str | None, click.Command | None, list[str]]:
41
41
  """Resolve command, checking if first arg is a subcommand or baseline_id."""
42
42
 
43
43
  # Check if first arg is a known subcommand
@@ -46,8 +46,7 @@ class BaselineGroup(click.Group):
46
46
  if first_arg in self.commands:
47
47
  # It's a known subcommand, let Click handle it normally
48
48
  cmd_name, cmd, remaining = super().resolve_command(ctx, args)
49
- # Click returns (name, cmd, args) but type checker expects (cmd, name, args)
50
- return cmd, cmd_name or "", remaining
49
+ return cmd_name, cmd, remaining
51
50
 
52
51
  # Not a subcommand - this means baseline_id is a positional argument
53
52
  # Store baseline_id in ctx for the callback to access
@@ -75,13 +74,12 @@ class BaselineGroup(click.Group):
75
74
  params=filtered_params,
76
75
  context_settings=self.context_settings,
77
76
  )
78
- return wrapper_cmd, "_baseline_wrapper", remaining_args
77
+ return "_baseline_wrapper", wrapper_cmd, remaining_args
79
78
 
80
79
  # No args or args start with --, so no baseline_id
81
80
  # Let Click handle it normally (will invoke main callback if invoke_without_command=True)
82
81
  cmd_name, cmd, remaining = super().resolve_command(ctx, args)
83
- # Click returns (name, cmd, args) but type checker expects (cmd, name, args)
84
- return cmd, cmd_name or "", remaining
82
+ return cmd_name, cmd, remaining
85
83
 
86
84
  def invoke(self, ctx: click.Context) -> Any:
87
85
  """Invoke command, handling baseline_id as positional arg."""
@@ -103,7 +101,7 @@ class BaselineGroup(click.Group):
103
101
  raise click.ClickException("Command callback is None")
104
102
  return ctx.invoke(self.callback, **ctx.params)
105
103
 
106
- cmd, cmd_name, resolved_args = self.resolve_command(ctx, full_args)
104
+ cmd_name, cmd, resolved_args = self.resolve_command(ctx, full_args)
107
105
 
108
106
  # Check if baseline_id was detected
109
107
  if 'baseline_id' in ctx.meta:
@@ -26,7 +26,7 @@ def _run_demo_command(func: Any, *args: Any, **kwargs: Any) -> None:
26
26
  try:
27
27
  result = func(*args, **kwargs)
28
28
  except SystemExit as exc: # pragma: no cover - defensive shim
29
- raise Exit(exc.code or 1) from exc
29
+ raise Exit(exc.code if isinstance(exc.code, int) else 1) from exc
30
30
 
31
31
  if result is None:
32
32
  return
@@ -6,6 +6,7 @@ from typing import Any
6
6
 
7
7
  from pydantic import ValidationError
8
8
 
9
+ from synth_ai.core.telemetry import log_info
9
10
  from synth_ai.sdk.api.train.configs.rl import RLConfig
10
11
  from synth_ai.sdk.api.train.configs.sft import SFTConfig
11
12
  from synth_ai.sdk.api.train.utils import load_toml
@@ -34,13 +35,13 @@ __all__ = [
34
35
 
35
36
  def validate_sft_config(config: MutableMapping[str, Any]) -> dict[str, Any]:
36
37
  """Validate SFT configuration from TOML.
37
-
38
+
38
39
  Args:
39
40
  config: Raw configuration dictionary from TOML
40
-
41
+
41
42
  Returns:
42
43
  Validated configuration dictionary
43
-
44
+
44
45
  Raises:
45
46
  InvalidSFTConfigError: If validation fails
46
47
  MissingAlgorithmError: If algorithm section is missing or invalid
@@ -48,6 +49,8 @@ def validate_sft_config(config: MutableMapping[str, Any]) -> dict[str, Any]:
48
49
  MissingDatasetError: If dataset path is not specified
49
50
  MissingComputeError: If compute section is missing required fields
50
51
  """
52
+ ctx: dict[str, Any] = {"config_keys": list(config.keys())[:10]}
53
+ log_info("validate_sft_config invoked", ctx=ctx)
51
54
  # Check for required top-level sections
52
55
  if "algorithm" not in config or not config["algorithm"]:
53
56
  raise MissingAlgorithmError(
@@ -130,19 +133,21 @@ def validate_sft_config(config: MutableMapping[str, Any]) -> dict[str, Any]:
130
133
 
131
134
  def validate_rl_config(config: MutableMapping[str, Any]) -> dict[str, Any]:
132
135
  """Validate RL configuration from TOML.
133
-
136
+
134
137
  Args:
135
138
  config: Raw configuration dictionary from TOML
136
-
139
+
137
140
  Returns:
138
141
  Validated configuration dictionary
139
-
142
+
140
143
  Raises:
141
144
  InvalidRLConfigError: If validation fails
142
145
  MissingAlgorithmError: If algorithm section is missing or invalid
143
146
  MissingModelError: If model is not specified
144
147
  MissingComputeError: If compute section is missing required fields
145
148
  """
149
+ ctx: dict[str, Any] = {"config_keys": list(config.keys())[:10]}
150
+ log_info("validate_rl_config invoked", ctx=ctx)
146
151
  # Check for required top-level sections
147
152
  if "algorithm" not in config or not config["algorithm"]:
148
153
  raise MissingAlgorithmError(
@@ -326,7 +326,7 @@ def _find_asgi_apps(root: Path) -> list[Path]:
326
326
  for dirpath, dirnames, filenames in os.walk(root):
327
327
  dirnames[:] = [d for d in dirnames if d not in skip_dirs]
328
328
  for name in filenames:
329
- if not name.endswith(".py"):
329
+ if not str(name).endswith(".py"):
330
330
  continue
331
331
  path = Path(dirpath) / name
332
332
  try:
@@ -384,7 +384,7 @@ def _find_vllm_tomls(root: Path) -> list[Path]:
384
384
  for dirpath, dirnames, filenames in os.walk(root):
385
385
  dirnames[:] = [d for d in dirnames if d not in skip_dirs]
386
386
  for name in filenames:
387
- if not name.endswith(".toml"):
387
+ if not str(name).endswith(".toml"):
388
388
  continue
389
389
  path = Path(dirpath) / name
390
390
  try:
@@ -30,7 +30,7 @@ def _run_demo_command(func, *args, **kwargs) -> None:
30
30
  try:
31
31
  result = func(*args, **kwargs)
32
32
  except SystemExit as exc: # pragma: no cover - defensive
33
- raise Exit(exc.code or 1) from exc
33
+ raise Exit(exc.code if isinstance(exc.code, int) else 1) from exc
34
34
 
35
35
  if result is None:
36
36
  return
@@ -1,6 +1,6 @@
1
1
  import asyncio
2
2
  from pathlib import Path
3
- from typing import Literal, TypeAlias, cast, get_args
3
+ from typing import Any, Literal, TypeAlias, cast, get_args
4
4
 
5
5
  import click
6
6
 
@@ -134,8 +134,13 @@ def deploy_cmd(
134
134
  task_app_path: Path | None,
135
135
  **kwargs
136
136
  ) -> None:
137
+ ctx: dict[str, Any] = {
138
+ "runtime": runtime,
139
+ "task_app_path": str(task_app_path),
140
+ **kwargs
141
+ }
137
142
  try:
138
- log_info("deploy command invoked", ctx={"runtime": runtime})
143
+ log_info("deploy command hit", ctx=ctx)
139
144
 
140
145
  if not task_app_path:
141
146
  available_task_apps = find_task_apps_in_cwd()
@@ -160,7 +165,7 @@ def deploy_cmd(
160
165
 
161
166
  match runtime:
162
167
  case "local":
163
- log_info("starting local deploy")
168
+ log_info("starting local deploy", ctx=ctx)
164
169
  deploy_app_uvicorn(
165
170
  LocalDeployCfg.create( # type: ignore[call-arg, arg-type]
166
171
  task_app_path=task_app_path,
@@ -171,7 +176,7 @@ def deploy_cmd(
171
176
  )
172
177
  )
173
178
  case "modal":
174
- log_info("starting modal deploy")
179
+ log_info("starting modal deploy", ctx=ctx)
175
180
  deploy_app_modal(ModalDeployCfg.create_from_kwargs(
176
181
  task_app_path=task_app_path,
177
182
  synth_api_key=synth_api_key,
@@ -179,6 +184,7 @@ def deploy_cmd(
179
184
  **kwargs
180
185
  ))
181
186
  case "tunnel":
187
+ log_info("starting tunnel deploy", ctx=ctx)
182
188
  tunnel_mode = kwargs.get("tunnel_mode", "managed")
183
189
  if tunnel_mode == "managed" and not synth_api_key:
184
190
  raise RuntimeError(
@@ -200,14 +206,11 @@ def deploy_cmd(
200
206
  ))
201
207
 
202
208
  except Exception as exc:
203
- log_error("deploy command failed", ctx={
204
- "runtime": runtime,
205
- "task_app": str(task_app_path),
206
- "error": type(exc).__name__,
207
- "error_message": str(exc)
208
- })
209
+ ctx["error"] = type(exc).__name__
210
+ ctx["error_message"] = str(exc)
211
+ log_error("deploy command failed", ctx=ctx)
209
212
  click.echo(f"{exc}", err=True)
210
213
 
211
214
  finally:
212
- log_info("deploy command completed", ctx={"runtime": runtime})
215
+ log_info("deploy command completed", ctx=ctx)
213
216
  flush_logger(0.5)
@@ -6,7 +6,11 @@ import subprocess
6
6
 
7
7
  import click
8
8
 
9
- from synth_ai.cli.root import SQLD_VERSION, find_sqld_binary, install_sqld # type: ignore[import-untyped]
9
+ from synth_ai.cli.root import ( # type: ignore[import-untyped]
10
+ SQLD_VERSION,
11
+ find_sqld_binary,
12
+ install_sqld,
13
+ )
10
14
 
11
15
 
12
16
  def register(cli: click.Group) -> None:
@@ -92,7 +92,7 @@ def find_asgi_apps(root: Path) -> list[Path]:
92
92
  for dirpath, dirnames, filenames in os.walk(root):
93
93
  dirnames[:] = [d for d in dirnames if d not in skip_dirs]
94
94
  for name in filenames:
95
- if not name.endswith(".py"):
95
+ if not str(name).endswith(".py"):
96
96
  continue
97
97
  path = Path(dirpath) / name
98
98
  try:
@@ -222,7 +222,7 @@ def prompt_for_path(
222
222
  click.echo(str(exc))
223
223
  continue
224
224
 
225
- result = converted if isinstance(converted, Path) else Path(converted)
225
+ result = converted if isinstance(converted, Path) else Path(str(converted) if isinstance(converted, bytes) else converted)
226
226
  if expected_suffix and result.suffix.lower() != expected_suffix:
227
227
  click.echo(f"Expected a {expected_suffix} file. Received: {result}")
228
228
  continue
@@ -10,6 +10,8 @@ from typing import Any, Mapping, MutableMapping
10
10
 
11
11
  import tomli_w
12
12
 
13
+ from synth_ai.core.telemetry import log_info
14
+
13
15
  from .validation import validate_path
14
16
 
15
17
 
@@ -176,14 +178,16 @@ def prepare_config_file(config_path: str | Path, overrides: Mapping[str, Any] |
176
178
  Args:
177
179
  config_path: Path to source TOML config file
178
180
  overrides: Optional dictionary of config overrides to apply
179
-
181
+
180
182
  Returns:
181
183
  PreparedConfig with the path to the merged TOML and resolved results_folder.
182
-
184
+
183
185
  Raises:
184
186
  AssertionError: If inputs are invalid
185
187
  FileNotFoundError: If config file doesn't exist
186
188
  """
189
+ ctx: dict[str, Any] = {"config_path": str(config_path), "has_overrides": overrides is not None}
190
+ log_info("prepare_config_file invoked", ctx=ctx)
187
191
  # Validate inputs
188
192
  assert config_path is not None, "config_path cannot be None"
189
193
  source_path = validate_path(config_path, "config_path", must_exist=True)
@@ -62,7 +62,7 @@ class ExperimentJobSummary(BaseModel):
62
62
  model_config = ConfigDict(from_attributes=True, use_enum_values=True)
63
63
 
64
64
  @classmethod
65
- def from_orm(cls, job: ExperimentJob) -> ExperimentJobSummary:
65
+ def from_job(cls, job: ExperimentJob) -> ExperimentJobSummary:
66
66
  return cls(
67
67
  job_id=job.job_id,
68
68
  job_type=ExperimentJobType(job.job_type),
@@ -88,7 +88,7 @@ class TrialSummary(BaseModel):
88
88
  model_config = ConfigDict(from_attributes=True, use_enum_values=True)
89
89
 
90
90
  @classmethod
91
- def from_orm(cls, trial: Trial) -> TrialSummary:
91
+ def from_trial(cls, trial: Trial) -> TrialSummary:
92
92
  return cls(
93
93
  trial_id=trial.trial_id,
94
94
  trial_number=trial.trial_number,
@@ -116,7 +116,7 @@ class ExperimentSummary(BaseModel):
116
116
  model_config = ConfigDict(from_attributes=True, use_enum_values=True)
117
117
 
118
118
  @classmethod
119
- def from_orm(cls, experiment: Experiment) -> ExperimentSummary:
119
+ def from_experiment(cls, experiment: Experiment) -> ExperimentSummary:
120
120
  return cls(
121
121
  experiment_id=experiment.experiment_id,
122
122
  name=experiment.name,
@@ -90,8 +90,8 @@ def experiments_cmd(
90
90
  )
91
91
  if as_json:
92
92
  payload = {
93
- "live": [ExperimentSummary.from_orm(exp).model_dump(mode="json") for exp in live],
94
- "recent": [ExperimentSummary.from_orm(exp).model_dump(mode="json") for exp in recent_data],
93
+ "live": [ExperimentSummary.from_experiment(exp).model_dump(mode="json") for exp in live],
94
+ "recent": [ExperimentSummary.from_experiment(exp).model_dump(mode="json") for exp in recent_data],
95
95
  }
96
96
  click.echo(json.dumps(payload, indent=2, default=str))
97
97
  else:
@@ -119,7 +119,7 @@ def experiment_submit(request: str, inline: bool) -> None:
119
119
 
120
120
  payload = _load_request_payload(request, inline=inline)
121
121
  experiment = create_experiment(payload)
122
- summary = ExperimentSummary.from_orm(experiment)
122
+ summary = ExperimentSummary.from_experiment(experiment)
123
123
  click.echo(f"Enqueued experiment {summary.experiment_id} ({summary.name}) with {summary.job_count} jobs.")
124
124
 
125
125
 
@@ -145,7 +145,7 @@ def experiment_list(
145
145
  include_live=True,
146
146
  )
147
147
  if as_json:
148
- payload = [ExperimentSummary.from_orm(exp).model_dump(mode="json") for exp in experiments]
148
+ payload = [ExperimentSummary.from_experiment(exp).model_dump(mode="json") for exp in experiments]
149
149
  click.echo(json.dumps(payload, indent=2, default=str))
150
150
  return
151
151
 
@@ -157,9 +157,9 @@ def _experiment_detail_json(experiment_id: str) -> str:
157
157
  experiment = fetch_experiment(experiment_id)
158
158
  if not experiment:
159
159
  raise click.ClickException(f"Experiment {experiment_id} not found.")
160
- payload = ExperimentSummary.from_orm(experiment).model_dump(mode="json")
161
- payload["jobs"] = [ExperimentJobSummary.from_orm(job).model_dump(mode="json") for job in experiment.jobs]
162
- payload["trials"] = [TrialSummary.from_orm(trial).model_dump(mode="json") for trial in experiment.trials]
160
+ payload = ExperimentSummary.from_experiment(experiment).model_dump(mode="json")
161
+ payload["jobs"] = [ExperimentJobSummary.from_job(job).model_dump(mode="json") for job in experiment.jobs]
162
+ payload["trials"] = [TrialSummary.from_trial(trial).model_dump(mode="json") for trial in experiment.trials]
163
163
  return json.dumps(payload, indent=2, default=str)
164
164
 
165
165
 
@@ -170,7 +170,7 @@ def _experiment_detail_console(experiment_id: str, *, console: Console | None =
170
170
  console = console or Console()
171
171
  if clear:
172
172
  console.clear()
173
- summary = ExperimentSummary.from_orm(experiment)
173
+ summary = ExperimentSummary.from_experiment(experiment)
174
174
  console.rule(f"[bold]Experiment {summary.experiment_id} — {summary.name}")
175
175
  console.print(f"Status: {summary.status.value}")
176
176
  console.print(f"Description: {summary.description or '-'}")
@@ -5,7 +5,7 @@ from typing import Any, Literal, Optional, cast
5
5
  from pydantic import BaseModel
6
6
 
7
7
  from synth_ai.core.paths import get_bin_path
8
- from synth_ai.core.telemetry import log_error, log_event
8
+ from synth_ai.core.telemetry import log_error, log_info
9
9
 
10
10
 
11
11
  class LocalDeployCfg(BaseModel):
@@ -25,13 +25,13 @@ class LocalDeployCfg(BaseModel):
25
25
  host: str = "127.0.0.1",
26
26
  port: int = 8000
27
27
  ) -> "LocalDeployCfg":
28
- ctx = {
29
- "task_app": str(task_app_path),
30
- "trace": bool(trace),
31
- "host": str(host),
32
- "port": int(port),
28
+ ctx: dict[str, Any] = {
29
+ "task_app_path": str(task_app_path),
30
+ "trace": trace,
31
+ "host": host,
32
+ "port": port,
33
33
  }
34
- log_event("info", "creating LocalDeployCfg", ctx=ctx)
34
+ log_info("creating LocalDeployCfg", ctx=ctx)
35
35
  try:
36
36
  cfg = cls(
37
37
  task_app_path=task_app_path,
@@ -40,10 +40,10 @@ class LocalDeployCfg(BaseModel):
40
40
  host=host,
41
41
  port=port,
42
42
  )
43
- log_event("info", "LocalDeployCfg created", ctx=ctx)
44
43
  return cfg
45
44
  except Exception as exc:
46
- log_error("LocalDeployCfg creation failed", ctx={**ctx, "error": type(exc).__name__})
45
+ ctx["error"] = type(exc).__name__
46
+ log_error("LocalDeployCfg creation failed", ctx=ctx)
47
47
  raise
48
48
 
49
49
  @classmethod
@@ -52,13 +52,16 @@ class LocalDeployCfg(BaseModel):
52
52
  data: dict[str, Any]
53
53
  ) -> "LocalDeployCfg":
54
54
  path = Path(data["task_app_path"])
55
- ctx = {
56
- "task_app": str(path),
57
- "trace": bool(data.get("trace", True)),
58
- "host": str(data.get("host", "127.0.0.1")),
59
- "port": int(data.get("port", 8000)),
55
+ trace = bool(data.get("trace", True))
56
+ host = str(data.get("host", "127.0.0.1"))
57
+ port = int(data.get("port", 8000))
58
+ ctx: dict[str, Any] = {
59
+ "task_app_path": str(path),
60
+ "trace": trace,
61
+ "host": host,
62
+ "port": port,
60
63
  }
61
- log_event("info", "creating LocalDeployCfg from dict", ctx=ctx)
64
+ log_info("creating LocalDeployCfg from dict", ctx=ctx)
62
65
  env_api_key = data.get("env_api_key")
63
66
  if not env_api_key or not isinstance(env_api_key, str):
64
67
  raise ValueError("env_api_key is required in local deploy configuration")
@@ -67,14 +70,14 @@ class LocalDeployCfg(BaseModel):
67
70
  cfg = cls(
68
71
  task_app_path=path,
69
72
  env_api_key=env_api_key,
70
- trace=bool(data.get("trace", True)),
71
- host=str(data.get("host", "127.0.0.1")),
72
- port=int(data.get("port", 8000)),
73
+ trace=trace,
74
+ host=host,
75
+ port=port,
73
76
  )
74
- log_event("info", "LocalDeployCfg from dict created", ctx=ctx)
75
77
  return cfg
76
78
  except (KeyError, TypeError, ValueError) as err:
77
- log_error("LocalDeployCfg from dict failed", ctx={**ctx, "error": type(err).__name__})
79
+ ctx["error"] = type(err).__name__
80
+ log_error("LocalDeployCfg from dict failed", ctx=ctx)
78
81
  raise ValueError(f"Invalid local deploy configuration: {err}") from err
79
82
 
80
83
 
@@ -101,19 +104,21 @@ class ModalDeployCfg(BaseModel):
101
104
  modal_app_name: Optional[str] = None,
102
105
  dry_run: bool = False,
103
106
  ) -> "ModalDeployCfg":
104
- ctx = {
105
- "task_app": str(task_app_path),
106
- "modal_app": str(modal_app_path),
107
+ ctx: dict[str, Any] = {
108
+ "task_app_path": str(task_app_path),
109
+ "modal_app_path": str(modal_app_path),
107
110
  "cmd_arg": cmd_arg,
108
111
  "dry_run": dry_run,
109
112
  "modal_app_name": modal_app_name,
110
- "modal_cli": str(modal_bin_path) if modal_bin_path else None,
113
+ "modal_bin_path": str(modal_bin_path) if modal_bin_path else None,
111
114
  }
112
- log_event("info", "creating ModalDeployCfg", ctx=ctx)
115
+ log_info("creating ModalDeployCfg", ctx=ctx)
113
116
  modal_bin_path = modal_bin_path or get_bin_path("modal")
114
117
  if modal_bin_path is None:
115
- log_error("ModalDeployCfg creation failed", ctx={**ctx, "error": "ModalCLINotFound"})
118
+ ctx["error"] = "ModalCLINotFound"
119
+ log_error("ModalDeployCfg creation failed", ctx=ctx)
116
120
  raise ValueError("Modal CLI not found; install `modal` or pass --modal-cli with its path.")
121
+ ctx["modal_bin_path"] = str(modal_bin_path)
117
122
  try:
118
123
  cfg = cls(
119
124
  task_app_path=task_app_path,
@@ -125,14 +130,17 @@ class ModalDeployCfg(BaseModel):
125
130
  modal_app_name=modal_app_name,
126
131
  dry_run=dry_run,
127
132
  )
128
- log_event("info", "ModalDeployCfg created", ctx=ctx)
129
133
  return cfg
130
134
  except Exception as exc:
131
- log_error("ModalDeployCfg creation failed", ctx={**ctx, "error": type(exc).__name__})
135
+ ctx["error"] = type(exc).__name__
136
+ log_error("ModalDeployCfg creation failed", ctx=ctx)
132
137
  raise
133
-
138
+
134
139
  @classmethod
135
140
  def create_from_kwargs(cls, **kwargs: Any) -> "ModalDeployCfg":
141
+ ctx: dict[str, Any] = {**kwargs}
142
+ log_info("creating ModalDeployCfg from kwargs", ctx=ctx)
143
+
136
144
  synth_api_key = kwargs.get("synth_api_key")
137
145
  if not synth_api_key or not isinstance(synth_api_key, str):
138
146
  raise ValueError("synth_api_key must be provided as a string")
@@ -146,19 +154,19 @@ class ModalDeployCfg(BaseModel):
146
154
 
147
155
  dry_run = bool(kwargs.get("dry_run", False))
148
156
  if dry_run and os.getenv("CTX") == "mcp":
149
- log_error("ModalDeployCfg create_from_kwargs blocked", ctx={"reason": "dry_run_mcp"})
157
+ ctx["error"] = "dry_run_mcp"
158
+ log_error("ModalDeployCfg create_from_kwargs blocked", ctx=ctx)
150
159
  raise ValueError("`synth-ai deploy --runtime modal --dry-run` cannot be used by MCP")
151
160
  if dry_run and cmd_arg == "serve":
152
- log_error("ModalDeployCfg create_from_kwargs blocked", ctx={"reason": "dry_run_serve"})
161
+ ctx["error"] = "dry_run_serve"
162
+ log_error("ModalDeployCfg create_from_kwargs blocked", ctx=ctx)
153
163
  raise ValueError("`synth-ai deploy --runtime modal --modal-mode serve` cannot be used with `--dry-run`")
154
164
 
155
165
  modal_bin_path_arg = kwargs.get("modal_cli")
156
166
  modal_bin_path = Path(str(modal_bin_path_arg)).expanduser() if modal_bin_path_arg else get_bin_path("modal")
157
167
  if modal_bin_path is None or not modal_bin_path.exists():
158
- log_error(
159
- "ModalDeployCfg create_from_kwargs failed",
160
- ctx={"error": "ModalCLINotFound", "provided_modal_cli": str(modal_bin_path_arg or "")},
161
- )
168
+ ctx["error"] = "ModalCLINotFound"
169
+ log_error("ModalDeployCfg create_from_kwargs failed", ctx=ctx)
162
170
  raise ValueError('Modal binary not found via shutil.which("modal"). Install `modal` or pass --modal-cli with its path.')
163
171
  modal_bin_path = modal_bin_path.resolve()
164
172
 
@@ -168,14 +176,6 @@ class ModalDeployCfg(BaseModel):
168
176
 
169
177
  literal_cmd = cast(Literal["deploy", "serve"], cmd_arg)
170
178
 
171
- ctx = {
172
- "task_app": str(kwargs.get("task_app_path")),
173
- "modal_app": str(kwargs.get("modal_app_path")),
174
- "cmd_arg": literal_cmd,
175
- "dry_run": dry_run,
176
- "modal_app_name": modal_app_name,
177
- "modal_cli": str(modal_bin_path) if modal_bin_path else None,
178
- }
179
179
  task_app_path = kwargs.get("task_app_path")
180
180
  modal_app_path = kwargs.get("modal_app")
181
181
 
@@ -189,7 +189,6 @@ class ModalDeployCfg(BaseModel):
189
189
  if not isinstance(modal_app_path, Path):
190
190
  modal_app_path = Path(modal_app_path)
191
191
 
192
- log_event("info", "creating ModalDeployCfg from kwargs", ctx=ctx)
193
192
  try:
194
193
  cfg = cls(
195
194
  task_app_path=task_app_path,
@@ -201,10 +200,10 @@ class ModalDeployCfg(BaseModel):
201
200
  modal_app_name=modal_app_name,
202
201
  dry_run=dry_run,
203
202
  )
204
- log_event("info", "ModalDeployCfg from kwargs created", ctx=ctx)
205
203
  return cfg
206
204
  except Exception as exc:
207
- log_error("ModalDeployCfg from kwargs failed", ctx={**ctx, "error": type(exc).__name__})
205
+ ctx["error"] = type(exc).__name__
206
+ log_error("ModalDeployCfg from kwargs failed", ctx=ctx)
208
207
  raise
209
208
 
210
209
 
@@ -4,6 +4,8 @@ from typing import Optional, overload
4
4
 
5
5
  import click
6
6
 
7
+ from synth_ai.core.telemetry import log_info
8
+
7
9
 
8
10
  def _get_required_value(*args, **kwargs):
9
11
  """Lazy import to avoid circular dependency."""
@@ -52,6 +54,8 @@ class ConfigResolver:
52
54
  docs_url: Optional[str] = None,
53
55
  ) -> Optional[str]:
54
56
  """Resolve value with CLI > ENV > CONFIG > DEFAULT precedence."""
57
+ ctx = {"name": name, "required": required, "has_cli": cli_value is not None, "has_env": env_value is not None}
58
+ log_info("ConfigResolver.resolve invoked", ctx=ctx)
55
59
 
56
60
  def _clean(value: Optional[str]) -> Optional[str]:
57
61
  if value is None: