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.
- {synth_ai-0.3.1.dev3/synth_ai.egg-info → synth_ai-0.3.2.dev2}/PKG-INFO +5 -7
- {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/README.md +4 -6
- {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/pyproject.toml +1 -1
- {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/cli/commands/baseline/core.py +5 -7
- {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/cli/commands/demo/core.py +1 -1
- {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/cli/commands/train/validation.py +11 -6
- {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/cli/demo_apps/core/cli.py +2 -2
- {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/cli/demos/rl_demo.py +1 -1
- {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/cli/deploy.py +14 -11
- {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/cli/infra/turso.py +5 -1
- {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/cli/lib/modal.py +1 -1
- {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/cli/lib/prompts.py +1 -1
- {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/cli/local/experiment_queue/config_utils.py +6 -2
- {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/cli/local/experiment_queue/schemas.py +3 -3
- {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/cli/utils/experiments.py +8 -8
- {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/core/cfgs.py +45 -46
- {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/core/config/resolver.py +4 -0
- {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/core/integrations/cloudflare.py +15 -4
- {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/core/integrations/modal.py +39 -40
- synth_ai-0.3.2.dev2/synth_ai/core/telemetry.py +282 -0
- {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/core/uvicorn.py +36 -29
- synth_ai-0.3.2.dev2/synth_ai/sdk/api/research_agent/__init__.py +86 -0
- {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/sdk/api/research_agent/cli.py +16 -3
- synth_ai-0.3.2.dev2/synth_ai/sdk/api/research_agent/config.py +357 -0
- {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/sdk/api/research_agent/job.py +273 -90
- {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/sdk/api/train/builders.py +7 -0
- {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/sdk/api/train/cli.py +41 -1
- {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/sdk/api/train/configs/prompt_learning.py +17 -5
- {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/sdk/api/train/env_resolver.py +9 -2
- {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/sdk/api/train/pollers.py +26 -3
- {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/sdk/api/train/prompt_learning.py +11 -5
- {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/sdk/api/train/rl.py +12 -6
- {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/sdk/api/train/sft.py +12 -6
- {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/sdk/api/train/utils.py +57 -23
- {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/sdk/api/train/validators.py +90 -23
- {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/sdk/baseline/discovery.py +3 -1
- {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/sdk/learning/prompt_learning_client.py +3 -1
- {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/sdk/streaming/handlers.py +88 -2
- {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/sdk/streaming/streamer.py +3 -0
- {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/sdk/task/__init__.py +14 -0
- {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/sdk/task/apps/__init__.py +1 -0
- {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/sdk/task/contracts.py +65 -3
- {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/sdk/task/in_process.py +214 -46
- {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/sdk/task/in_process_runner.py +10 -1
- {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/sdk/task/inference_api.py +92 -14
- {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/sdk/task/proxy.py +36 -0
- {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/sdk/task/server.py +18 -12
- {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/sdk/task/trace_correlation_helpers.py +178 -0
- {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2/synth_ai.egg-info}/PKG-INFO +5 -7
- {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai.egg-info/SOURCES.txt +1 -0
- synth_ai-0.3.1.dev3/synth_ai/core/telemetry.py +0 -219
- synth_ai-0.3.1.dev3/synth_ai/sdk/api/research_agent/__init__.py +0 -54
- {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/LICENSE +0 -0
- {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/MANIFEST.in +0 -0
- {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/setup.cfg +0 -0
- {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/__init__.py +0 -0
- {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/__main__.py +0 -0
- {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/cli/__init__.py +0 -0
- {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/cli/__main__.py +0 -0
- {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/cli/_internal/__init__.py +0 -0
- {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/cli/_internal/modal_wrapper.py +0 -0
- {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/cli/_internal/storage.py +0 -0
- {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/cli/_internal/typer_patch.py +0 -0
- {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/cli/_internal/validate_task_app.py +0 -0
- {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/cli/agents/__init__.py +0 -0
- {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/cli/agents/claude.py +0 -0
- {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/cli/agents/codex.py +0 -0
- {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/cli/agents/opencode.py +0 -0
- {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/cli/commands/__init__.py +0 -0
- {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/cli/commands/artifacts/__init__.py +0 -0
- {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/cli/commands/artifacts/client.py +0 -0
- {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/cli/commands/artifacts/config.py +0 -0
- {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/cli/commands/artifacts/core.py +0 -0
- {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/cli/commands/artifacts/download.py +0 -0
- {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/cli/commands/artifacts/export.py +0 -0
- {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/cli/commands/artifacts/list.py +0 -0
- {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/cli/commands/artifacts/parsing.py +0 -0
- {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/cli/commands/artifacts/show.py +0 -0
- {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/cli/commands/baseline/__init__.py +0 -0
- {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/cli/commands/baseline/list.py +0 -0
- {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/cli/commands/demo/__init__.py +0 -0
- {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/cli/commands/eval/__init__.py +0 -0
- {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/cli/commands/eval/core.py +0 -0
- {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/cli/commands/eval/errors.py +0 -0
- {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/cli/commands/eval/validation.py +0 -0
- {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/cli/commands/filter/__init__.py +0 -0
- {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/cli/commands/filter/core.py +0 -0
- {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/cli/commands/filter/errors.py +0 -0
- {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/cli/commands/filter/validation.py +0 -0
- {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/cli/commands/help/__init__.py +0 -0
- {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/cli/commands/help/core.py +0 -0
- {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/cli/commands/scan/__init__.py +0 -0
- {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/cli/commands/scan/cloudflare_scanner.py +0 -0
- {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/cli/commands/scan/core.py +0 -0
- {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/cli/commands/scan/health_checker.py +0 -0
- {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/cli/commands/scan/local_scanner.py +0 -0
- {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/cli/commands/scan/models.py +0 -0
- {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/cli/commands/smoke/__init__.py +0 -0
- {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/cli/commands/smoke/core.py +0 -0
- {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/cli/commands/status/__init__.py +0 -0
- {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/cli/commands/status/client.py +0 -0
- {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/cli/commands/status/config.py +0 -0
- {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/cli/commands/status/errors.py +0 -0
- {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/cli/commands/status/formatters.py +0 -0
- {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/cli/commands/status/subcommands/__init__.py +0 -0
- {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/cli/commands/status/subcommands/files.py +0 -0
- {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/cli/commands/status/subcommands/jobs.py +0 -0
- {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/cli/commands/status/subcommands/models.py +0 -0
- {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/cli/commands/status/subcommands/pricing.py +0 -0
- {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/cli/commands/status/subcommands/runs.py +0 -0
- {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/cli/commands/status/subcommands/session.py +0 -0
- {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/cli/commands/status/subcommands/summary.py +0 -0
- {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/cli/commands/status/subcommands/usage.py +0 -0
- {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/cli/commands/status/utils.py +0 -0
- {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/cli/commands/train/__init__.py +0 -0
- {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/cli/commands/train/core.py +0 -0
- {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/cli/commands/train/errors.py +0 -0
- {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/cli/commands/train/judge_schemas.py +0 -0
- {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/cli/commands/train/judge_validation.py +0 -0
- {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/cli/demo_apps/__init__.py +0 -0
- {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/cli/demo_apps/core/__init__.py +0 -0
- {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/cli/demo_apps/crafter/__init__.py +0 -0
- {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/cli/demo_apps/crafter/crafter_fft_4b.toml +0 -0
- {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
- {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
- {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/cli/demo_apps/demo_registry.py +0 -0
- {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/cli/demo_apps/demo_task_apps/__init__.py +0 -0
- {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/cli/demo_apps/demo_task_apps/core.py +0 -0
- {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
- {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
- {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
- {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
- {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
- {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
- {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
- {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
- {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
- {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
- {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
- {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/cli/demo_apps/math/__init__.py +0 -0
- {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/cli/demo_apps/math/_common.py +0 -0
- {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/cli/demo_apps/math/app.py +0 -0
- {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/cli/demo_apps/math/config.toml +0 -0
- {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/cli/demo_apps/math/deploy_modal.py +0 -0
- {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/cli/demo_apps/math/modal_task_app.py +0 -0
- {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/cli/demo_apps/math/task_app_entry.py +0 -0
- {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/cli/demo_apps/mipro/main.py +0 -0
- {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/cli/demo_apps/mipro/task_app.py +0 -0
- {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/cli/demo_apps/mipro/train_cfg.toml +0 -0
- {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/cli/demos/__init__.py +0 -0
- {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/cli/demos/demo.py +0 -0
- {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/cli/infra/__init__.py +0 -0
- {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/cli/infra/balance.py +0 -0
- {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/cli/infra/mcp.py +0 -0
- {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/cli/infra/modal_app.py +0 -0
- {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/cli/infra/setup.py +0 -0
- {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/cli/infra/status.py +0 -0
- {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/cli/lib/__init__.py +0 -0
- {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/cli/lib/agents.py +0 -0
- {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/cli/lib/apps/modal_app.py +0 -0
- {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/cli/lib/apps/task_app.py +0 -0
- {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/cli/lib/bin.py +0 -0
- {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/cli/lib/env.py +0 -0
- {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/cli/lib/errors.py +0 -0
- {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/cli/lib/plotting.py +0 -0
- {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/cli/lib/prompt_args.py +0 -0
- {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/cli/lib/sqld.py +0 -0
- {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/cli/lib/task_app_discovery.py +0 -0
- {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/cli/lib/task_app_env.py +0 -0
- {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/cli/lib/train_cfgs.py +0 -0
- {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/cli/lib/tunnel_records.py +0 -0
- {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/cli/local/__init__.py +0 -0
- {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/cli/local/experiment_queue/__init__.py +0 -0
- {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/cli/local/experiment_queue/api_schemas.py +0 -0
- {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/cli/local/experiment_queue/celery_app.py +0 -0
- {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/cli/local/experiment_queue/config.py +0 -0
- {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/cli/local/experiment_queue/database.py +0 -0
- {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/cli/local/experiment_queue/dispatcher.py +0 -0
- {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/cli/local/experiment_queue/models.py +0 -0
- {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/cli/local/experiment_queue/progress_info.py +0 -0
- {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/cli/local/experiment_queue/results.py +0 -0
- {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/cli/local/experiment_queue/service.py +0 -0
- {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/cli/local/experiment_queue/status.py +0 -0
- {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/cli/local/experiment_queue/status_tracker.py +0 -0
- {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/cli/local/experiment_queue/tasks.py +0 -0
- {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/cli/local/experiment_queue/trace_storage.py +0 -0
- {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/cli/local/experiment_queue/validation.py +0 -0
- {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/cli/local/session/__init__.py +0 -0
- {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/cli/local/session/client.py +0 -0
- {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/cli/local/session/constants.py +0 -0
- {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/cli/local/session/exceptions.py +0 -0
- {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/cli/local/session/manager.py +0 -0
- {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/cli/local/session/models.py +0 -0
- {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/cli/local/session/query.py +0 -0
- {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/cli/root.py +0 -0
- {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/cli/task_apps/__init__.py +0 -0
- {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/cli/task_apps/commands.py +0 -0
- {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/cli/task_apps/deploy.py +0 -0
- {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/cli/task_apps/list.py +0 -0
- {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/cli/task_apps/main.py +0 -0
- {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/cli/task_apps/modal_serve.py +0 -0
- {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/cli/task_apps/serve.py +0 -0
- {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/cli/training/__init__.py +0 -0
- {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/cli/training/train.py +0 -0
- {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/cli/training/train_cfg.py +0 -0
- {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/cli/training/watch.py +0 -0
- {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/cli/turso.py +0 -0
- {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/cli/utils/__init__.py +0 -0
- {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/cli/utils/queue.py +0 -0
- {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/cli/utils/recent.py +0 -0
- {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/cli/utils/traces.py +0 -0
- {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/contracts/__init__.py +0 -0
- {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/core/__init__.py +0 -0
- {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/core/_utils/__init__.py +0 -0
- {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/core/_utils/base_url.py +0 -0
- {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/core/_utils/http.py +0 -0
- {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/core/_utils/prompts.py +0 -0
- {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/core/_utils/task_app_state.py +0 -0
- {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/core/_utils/user_config.py +0 -0
- {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/core/apps/__init__.py +0 -0
- {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/core/apps/common.py +0 -0
- {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/core/auth.py +0 -0
- {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/core/config/__init__.py +0 -0
- {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/core/config/base.py +0 -0
- {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/core/env.py +0 -0
- {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/core/errors.py +0 -0
- {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/core/http.py +0 -0
- {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/core/integrations/__init__.py +0 -0
- {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/core/integrations/mcp/__init__.py +0 -0
- {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/core/integrations/mcp/__main__.py +0 -0
- {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/core/integrations/mcp/claude.py +0 -0
- {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/core/integrations/mcp/main.py +0 -0
- {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/core/integrations/mcp/setup.py +0 -0
- {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/core/json.py +0 -0
- {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/core/log_filter.py +0 -0
- {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/core/logging.py +0 -0
- {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/core/paths.py +0 -0
- {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/core/pricing.py +0 -0
- {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/core/process.py +0 -0
- {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/core/ssl.py +0 -0
- {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/core/storage/__init__.py +0 -0
- {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/core/task_app_state.py +0 -0
- {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/core/tracing_v3/__init__.py +0 -0
- {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/core/tracing_v3/abstractions.py +0 -0
- {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/core/tracing_v3/config.py +0 -0
- {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/core/tracing_v3/constants.py +0 -0
- {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/core/tracing_v3/db_config.py +0 -0
- {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/core/tracing_v3/decorators.py +0 -0
- {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/core/tracing_v3/examples/basic_usage.py +0 -0
- {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/core/tracing_v3/hooks.py +0 -0
- {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/core/tracing_v3/llm_call_record_helpers.py +0 -0
- {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/core/tracing_v3/lm_call_record_abstractions.py +0 -0
- {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/core/tracing_v3/migration_helper.py +0 -0
- {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/core/tracing_v3/replica_sync.py +0 -0
- {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/core/tracing_v3/serialization.py +0 -0
- {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/core/tracing_v3/session_tracer.py +0 -0
- {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/core/tracing_v3/storage/__init__.py +0 -0
- {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/core/tracing_v3/storage/base.py +0 -0
- {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/core/tracing_v3/storage/config.py +0 -0
- {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/core/tracing_v3/storage/exceptions.py +0 -0
- {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/core/tracing_v3/storage/factory.py +0 -0
- {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/core/tracing_v3/storage/types.py +0 -0
- {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/core/tracing_v3/storage/utils.py +0 -0
- {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/core/tracing_v3/trace_utils.py +0 -0
- {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/core/tracing_v3/turso/__init__.py +0 -0
- {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/core/tracing_v3/turso/daemon.py +0 -0
- {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/core/tracing_v3/turso/models.py +0 -0
- {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/core/tracing_v3/turso/native_manager.py +0 -0
- {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/core/tracing_v3/utils.py +0 -0
- {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/core/urls.py +0 -0
- {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/core/user_config.py +0 -0
- {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/data/__init__.py +0 -0
- {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/data/enums.py +0 -0
- {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/data/rewards.py +0 -0
- {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/data/specs.py +0 -0
- {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/data/traces.py +0 -0
- {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/py.typed +0 -0
- {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/sdk/__init__.py +0 -0
- {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/sdk/api/models/supported.py +0 -0
- {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/sdk/api/train/__init__.py +0 -0
- {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/sdk/api/train/config_finder.py +0 -0
- {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/sdk/api/train/configs/__init__.py +0 -0
- {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/sdk/api/train/configs/rl.py +0 -0
- {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/sdk/api/train/configs/sft.py +0 -0
- {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/sdk/api/train/configs/shared.py +0 -0
- {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/sdk/api/train/summary.py +0 -0
- {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/sdk/api/train/supported_algos.py +0 -0
- {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/sdk/api/train/task_app.py +0 -0
- {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/sdk/baseline/__init__.py +0 -0
- {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/sdk/baseline/config.py +0 -0
- {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/sdk/baseline/execution.py +0 -0
- {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/sdk/inference/__init__.py +0 -0
- {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/sdk/inference/client.py +0 -0
- {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/sdk/jobs/__init__.py +0 -0
- {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/sdk/jobs/client.py +0 -0
- {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/sdk/judging/__init__.py +0 -0
- {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/sdk/judging/base.py +0 -0
- {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/sdk/judging/client.py +0 -0
- {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/sdk/judging/schemas.py +0 -0
- {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/sdk/judging/types.py +0 -0
- {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/sdk/learning/__init__.py +0 -0
- {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/sdk/learning/algorithms.py +0 -0
- {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/sdk/learning/client.py +0 -0
- {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/sdk/learning/config.py +0 -0
- {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/sdk/learning/constants.py +0 -0
- {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/sdk/learning/core.py +0 -0
- {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/sdk/learning/ft_client.py +0 -0
- {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/sdk/learning/gateway.py +0 -0
- {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/sdk/learning/health.py +0 -0
- {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/sdk/learning/jobs.py +0 -0
- {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/sdk/learning/prompt_extraction.py +0 -0
- {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/sdk/learning/prompt_learning_types.py +0 -0
- {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/sdk/learning/rl/__init__.py +0 -0
- {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/sdk/learning/rl/client.py +0 -0
- {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/sdk/learning/rl/config.py +0 -0
- {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/sdk/learning/rl/contracts.py +0 -0
- {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/sdk/learning/rl/env_keys.py +0 -0
- {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/sdk/learning/rl/secrets.py +0 -0
- {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/sdk/learning/rl_client.py +0 -0
- {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/sdk/learning/sft/__init__.py +0 -0
- {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/sdk/learning/sft/client.py +0 -0
- {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/sdk/learning/sft/config.py +0 -0
- {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/sdk/learning/sft/data.py +0 -0
- {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/sdk/learning/sse.py +0 -0
- {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/sdk/learning/validators.py +0 -0
- {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/sdk/research_agent/__init__.py +0 -0
- {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/sdk/research_agent/container_builder.py +0 -0
- {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/sdk/research_agent/container_spec.py +0 -0
- {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/sdk/research_agent/defaults.py +0 -0
- {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/sdk/research_agent/results_collector.py +0 -0
- {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/sdk/specs/__init__.py +0 -0
- {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/sdk/specs/dataclasses.py +0 -0
- {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/sdk/specs/loader.py +0 -0
- {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/sdk/specs/serializer.py +0 -0
- {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/sdk/specs/validation.py +0 -0
- {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/sdk/streaming/__init__.py +0 -0
- {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/sdk/streaming/config.py +0 -0
- {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/sdk/streaming/types.py +0 -0
- {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/sdk/task/auth.py +0 -0
- {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/sdk/task/client.py +0 -0
- {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/sdk/task/config.py +0 -0
- {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/sdk/task/datasets.py +0 -0
- {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/sdk/task/errors.py +0 -0
- {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/sdk/task/health.py +0 -0
- {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/sdk/task/json.py +0 -0
- {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/sdk/task/rubrics/__init__.py +0 -0
- {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/sdk/task/rubrics/loaders.py +0 -0
- {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/sdk/task/rubrics/models.py +0 -0
- {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/sdk/task/rubrics/scoring.py +0 -0
- {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/sdk/task/rubrics/strict.py +0 -0
- {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/sdk/task/rubrics.py +0 -0
- {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/sdk/task/tracing_utils.py +0 -0
- {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/sdk/task/validators.py +0 -0
- {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/sdk/task/vendors.py +0 -0
- {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/sdk/tracing/__init__.py +0 -0
- {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/sdk/training/__init__.py +0 -0
- {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/utils/__init__.py +0 -0
- {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai.egg-info/dependency_links.txt +0 -0
- {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai.egg-info/entry_points.txt +0 -0
- {synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai.egg-info/requires.txt +0 -0
- {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.
|
|
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
|
-
|
|
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
|
-
|
|
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.
|
|
@@ -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,
|
|
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
|
-
|
|
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
|
|
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
|
-
|
|
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
|
-
|
|
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
|
|
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
|
|
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
|
|
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
|
-
|
|
204
|
-
|
|
205
|
-
|
|
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=
|
|
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
|
|
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
|
{synth_ai-0.3.1.dev3 → synth_ai-0.3.2.dev2}/synth_ai/cli/local/experiment_queue/config_utils.py
RENAMED
|
@@ -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
|
|
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
|
|
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
|
|
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.
|
|
94
|
-
"recent": [ExperimentSummary.
|
|
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.
|
|
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.
|
|
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.
|
|
161
|
-
payload["jobs"] = [ExperimentJobSummary.
|
|
162
|
-
payload["trials"] = [TrialSummary.
|
|
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.
|
|
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,
|
|
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
|
-
"
|
|
30
|
-
"trace":
|
|
31
|
-
"host":
|
|
32
|
-
"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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
"
|
|
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
|
-
|
|
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=
|
|
71
|
-
host=
|
|
72
|
-
port=
|
|
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
|
-
|
|
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
|
-
"
|
|
106
|
-
"
|
|
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
|
-
"
|
|
113
|
+
"modal_bin_path": str(modal_bin_path) if modal_bin_path else None,
|
|
111
114
|
}
|
|
112
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
159
|
-
|
|
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
|
-
|
|
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:
|