synth-ai 0.3.1.dev1__tar.gz → 0.3.1.dev3__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/PKG-INFO +154 -0
- synth_ai-0.3.1.dev3/README.md +74 -0
- {synth_ai-0.3.1.dev1 → synth_ai-0.3.1.dev3}/pyproject.toml +1 -1
- {synth_ai-0.3.1.dev1 → synth_ai-0.3.1.dev3}/synth_ai/cli/commands/smoke/core.py +1 -1
- {synth_ai-0.3.1.dev1 → synth_ai-0.3.1.dev3}/synth_ai/cli/demo_apps/crafter/grpo_crafter_task_app.py +1 -1
- {synth_ai-0.3.1.dev1 → synth_ai-0.3.1.dev3}/synth_ai/cli/demo_apps/demo_task_apps/crafter/grpo_crafter_task_app.py +1 -1
- {synth_ai-0.3.1.dev1 → synth_ai-0.3.1.dev3}/synth_ai/cli/demo_apps/demo_task_apps/math/modal_task_app.py +2 -5
- {synth_ai-0.3.1.dev1 → synth_ai-0.3.1.dev3}/synth_ai/cli/demo_apps/math/modal_task_app.py +2 -5
- {synth_ai-0.3.1.dev1 → synth_ai-0.3.1.dev3}/synth_ai/cli/infra/turso.py +1 -1
- {synth_ai-0.3.1.dev1 → synth_ai-0.3.1.dev3}/synth_ai/cli/lib/task_app_env.py +108 -0
- {synth_ai-0.3.1.dev1 → synth_ai-0.3.1.dev3}/synth_ai/cli/local/experiment_queue/tasks.py +1 -1
- {synth_ai-0.3.1.dev1 → synth_ai-0.3.1.dev3}/synth_ai/cli/local/session/client.py +5 -6
- {synth_ai-0.3.1.dev1 → synth_ai-0.3.1.dev3}/synth_ai/cli/task_apps/__init__.py +2 -1
- {synth_ai-0.3.1.dev1 → synth_ai-0.3.1.dev3}/synth_ai/cli/task_apps/commands.py +4 -2
- synth_ai-0.3.1.dev3/synth_ai/cli/turso.py +52 -0
- {synth_ai-0.3.1.dev1 → synth_ai-0.3.1.dev3}/synth_ai/core/tracing_v3/trace_utils.py +2 -2
- {synth_ai-0.3.1.dev1 → synth_ai-0.3.1.dev3}/synth_ai/core/tracing_v3/turso/daemon.py +26 -0
- {synth_ai-0.3.1.dev1 → synth_ai-0.3.1.dev3}/synth_ai/core/tracing_v3/turso/native_manager.py +5 -5
- {synth_ai-0.3.1.dev1 → synth_ai-0.3.1.dev3}/synth_ai/sdk/__init__.py +11 -6
- {synth_ai-0.3.1.dev1 → synth_ai-0.3.1.dev3}/synth_ai/sdk/api/train/configs/prompt_learning.py +1 -1
- {synth_ai-0.3.1.dev1 → synth_ai-0.3.1.dev3}/synth_ai/sdk/api/train/task_app.py +11 -1
- {synth_ai-0.3.1.dev1 → synth_ai-0.3.1.dev3}/synth_ai/sdk/api/train/validators.py +1 -1
- {synth_ai-0.3.1.dev1 → synth_ai-0.3.1.dev3}/synth_ai/sdk/learning/sft/client.py +26 -0
- {synth_ai-0.3.1.dev1 → synth_ai-0.3.1.dev3}/synth_ai/sdk/task/__init__.py +12 -0
- {synth_ai-0.3.1.dev1 → synth_ai-0.3.1.dev3}/synth_ai/sdk/task/apps/__init__.py +2 -2
- {synth_ai-0.3.1.dev1 → synth_ai-0.3.1.dev3}/synth_ai/sdk/task/datasets.py +2 -2
- synth_ai-0.3.1.dev3/synth_ai/sdk/task/in_process.py +876 -0
- synth_ai-0.3.1.dev3/synth_ai/sdk/task/in_process_runner.py +281 -0
- synth_ai-0.3.1.dev3/synth_ai.egg-info/PKG-INFO +154 -0
- {synth_ai-0.3.1.dev1 → synth_ai-0.3.1.dev3}/synth_ai.egg-info/SOURCES.txt +2 -0
- synth_ai-0.3.1.dev1/PKG-INFO +0 -404
- synth_ai-0.3.1.dev1/README.md +0 -324
- synth_ai-0.3.1.dev1/synth_ai/sdk/task/in_process.py +0 -477
- synth_ai-0.3.1.dev1/synth_ai.egg-info/PKG-INFO +0 -404
- {synth_ai-0.3.1.dev1 → synth_ai-0.3.1.dev3}/LICENSE +0 -0
- {synth_ai-0.3.1.dev1 → synth_ai-0.3.1.dev3}/MANIFEST.in +0 -0
- {synth_ai-0.3.1.dev1 → synth_ai-0.3.1.dev3}/setup.cfg +0 -0
- {synth_ai-0.3.1.dev1 → synth_ai-0.3.1.dev3}/synth_ai/__init__.py +0 -0
- {synth_ai-0.3.1.dev1 → synth_ai-0.3.1.dev3}/synth_ai/__main__.py +0 -0
- {synth_ai-0.3.1.dev1 → synth_ai-0.3.1.dev3}/synth_ai/cli/__init__.py +0 -0
- {synth_ai-0.3.1.dev1 → synth_ai-0.3.1.dev3}/synth_ai/cli/__main__.py +0 -0
- {synth_ai-0.3.1.dev1 → synth_ai-0.3.1.dev3}/synth_ai/cli/_internal/__init__.py +0 -0
- {synth_ai-0.3.1.dev1 → synth_ai-0.3.1.dev3}/synth_ai/cli/_internal/modal_wrapper.py +0 -0
- {synth_ai-0.3.1.dev1 → synth_ai-0.3.1.dev3}/synth_ai/cli/_internal/storage.py +0 -0
- {synth_ai-0.3.1.dev1 → synth_ai-0.3.1.dev3}/synth_ai/cli/_internal/typer_patch.py +0 -0
- {synth_ai-0.3.1.dev1 → synth_ai-0.3.1.dev3}/synth_ai/cli/_internal/validate_task_app.py +0 -0
- {synth_ai-0.3.1.dev1 → synth_ai-0.3.1.dev3}/synth_ai/cli/agents/__init__.py +0 -0
- {synth_ai-0.3.1.dev1 → synth_ai-0.3.1.dev3}/synth_ai/cli/agents/claude.py +0 -0
- {synth_ai-0.3.1.dev1 → synth_ai-0.3.1.dev3}/synth_ai/cli/agents/codex.py +0 -0
- {synth_ai-0.3.1.dev1 → synth_ai-0.3.1.dev3}/synth_ai/cli/agents/opencode.py +0 -0
- {synth_ai-0.3.1.dev1 → synth_ai-0.3.1.dev3}/synth_ai/cli/commands/__init__.py +0 -0
- {synth_ai-0.3.1.dev1 → synth_ai-0.3.1.dev3}/synth_ai/cli/commands/artifacts/__init__.py +0 -0
- {synth_ai-0.3.1.dev1 → synth_ai-0.3.1.dev3}/synth_ai/cli/commands/artifacts/client.py +0 -0
- {synth_ai-0.3.1.dev1 → synth_ai-0.3.1.dev3}/synth_ai/cli/commands/artifacts/config.py +0 -0
- {synth_ai-0.3.1.dev1 → synth_ai-0.3.1.dev3}/synth_ai/cli/commands/artifacts/core.py +0 -0
- {synth_ai-0.3.1.dev1 → synth_ai-0.3.1.dev3}/synth_ai/cli/commands/artifacts/download.py +0 -0
- {synth_ai-0.3.1.dev1 → synth_ai-0.3.1.dev3}/synth_ai/cli/commands/artifacts/export.py +0 -0
- {synth_ai-0.3.1.dev1 → synth_ai-0.3.1.dev3}/synth_ai/cli/commands/artifacts/list.py +0 -0
- {synth_ai-0.3.1.dev1 → synth_ai-0.3.1.dev3}/synth_ai/cli/commands/artifacts/parsing.py +0 -0
- {synth_ai-0.3.1.dev1 → synth_ai-0.3.1.dev3}/synth_ai/cli/commands/artifacts/show.py +0 -0
- {synth_ai-0.3.1.dev1 → synth_ai-0.3.1.dev3}/synth_ai/cli/commands/baseline/__init__.py +0 -0
- {synth_ai-0.3.1.dev1 → synth_ai-0.3.1.dev3}/synth_ai/cli/commands/baseline/core.py +0 -0
- {synth_ai-0.3.1.dev1 → synth_ai-0.3.1.dev3}/synth_ai/cli/commands/baseline/list.py +0 -0
- {synth_ai-0.3.1.dev1 → synth_ai-0.3.1.dev3}/synth_ai/cli/commands/demo/__init__.py +0 -0
- {synth_ai-0.3.1.dev1 → synth_ai-0.3.1.dev3}/synth_ai/cli/commands/demo/core.py +0 -0
- {synth_ai-0.3.1.dev1 → synth_ai-0.3.1.dev3}/synth_ai/cli/commands/eval/__init__.py +0 -0
- {synth_ai-0.3.1.dev1 → synth_ai-0.3.1.dev3}/synth_ai/cli/commands/eval/core.py +0 -0
- {synth_ai-0.3.1.dev1 → synth_ai-0.3.1.dev3}/synth_ai/cli/commands/eval/errors.py +0 -0
- {synth_ai-0.3.1.dev1 → synth_ai-0.3.1.dev3}/synth_ai/cli/commands/eval/validation.py +0 -0
- {synth_ai-0.3.1.dev1 → synth_ai-0.3.1.dev3}/synth_ai/cli/commands/filter/__init__.py +0 -0
- {synth_ai-0.3.1.dev1 → synth_ai-0.3.1.dev3}/synth_ai/cli/commands/filter/core.py +0 -0
- {synth_ai-0.3.1.dev1 → synth_ai-0.3.1.dev3}/synth_ai/cli/commands/filter/errors.py +0 -0
- {synth_ai-0.3.1.dev1 → synth_ai-0.3.1.dev3}/synth_ai/cli/commands/filter/validation.py +0 -0
- {synth_ai-0.3.1.dev1 → synth_ai-0.3.1.dev3}/synth_ai/cli/commands/help/__init__.py +0 -0
- {synth_ai-0.3.1.dev1 → synth_ai-0.3.1.dev3}/synth_ai/cli/commands/help/core.py +0 -0
- {synth_ai-0.3.1.dev1 → synth_ai-0.3.1.dev3}/synth_ai/cli/commands/scan/__init__.py +0 -0
- {synth_ai-0.3.1.dev1 → synth_ai-0.3.1.dev3}/synth_ai/cli/commands/scan/cloudflare_scanner.py +0 -0
- {synth_ai-0.3.1.dev1 → synth_ai-0.3.1.dev3}/synth_ai/cli/commands/scan/core.py +0 -0
- {synth_ai-0.3.1.dev1 → synth_ai-0.3.1.dev3}/synth_ai/cli/commands/scan/health_checker.py +0 -0
- {synth_ai-0.3.1.dev1 → synth_ai-0.3.1.dev3}/synth_ai/cli/commands/scan/local_scanner.py +0 -0
- {synth_ai-0.3.1.dev1 → synth_ai-0.3.1.dev3}/synth_ai/cli/commands/scan/models.py +0 -0
- {synth_ai-0.3.1.dev1 → synth_ai-0.3.1.dev3}/synth_ai/cli/commands/smoke/__init__.py +0 -0
- {synth_ai-0.3.1.dev1 → synth_ai-0.3.1.dev3}/synth_ai/cli/commands/status/__init__.py +0 -0
- {synth_ai-0.3.1.dev1 → synth_ai-0.3.1.dev3}/synth_ai/cli/commands/status/client.py +0 -0
- {synth_ai-0.3.1.dev1 → synth_ai-0.3.1.dev3}/synth_ai/cli/commands/status/config.py +0 -0
- {synth_ai-0.3.1.dev1 → synth_ai-0.3.1.dev3}/synth_ai/cli/commands/status/errors.py +0 -0
- {synth_ai-0.3.1.dev1 → synth_ai-0.3.1.dev3}/synth_ai/cli/commands/status/formatters.py +0 -0
- {synth_ai-0.3.1.dev1 → synth_ai-0.3.1.dev3}/synth_ai/cli/commands/status/subcommands/__init__.py +0 -0
- {synth_ai-0.3.1.dev1 → synth_ai-0.3.1.dev3}/synth_ai/cli/commands/status/subcommands/files.py +0 -0
- {synth_ai-0.3.1.dev1 → synth_ai-0.3.1.dev3}/synth_ai/cli/commands/status/subcommands/jobs.py +0 -0
- {synth_ai-0.3.1.dev1 → synth_ai-0.3.1.dev3}/synth_ai/cli/commands/status/subcommands/models.py +0 -0
- {synth_ai-0.3.1.dev1 → synth_ai-0.3.1.dev3}/synth_ai/cli/commands/status/subcommands/pricing.py +0 -0
- {synth_ai-0.3.1.dev1 → synth_ai-0.3.1.dev3}/synth_ai/cli/commands/status/subcommands/runs.py +0 -0
- {synth_ai-0.3.1.dev1 → synth_ai-0.3.1.dev3}/synth_ai/cli/commands/status/subcommands/session.py +0 -0
- {synth_ai-0.3.1.dev1 → synth_ai-0.3.1.dev3}/synth_ai/cli/commands/status/subcommands/summary.py +0 -0
- {synth_ai-0.3.1.dev1 → synth_ai-0.3.1.dev3}/synth_ai/cli/commands/status/subcommands/usage.py +0 -0
- {synth_ai-0.3.1.dev1 → synth_ai-0.3.1.dev3}/synth_ai/cli/commands/status/utils.py +0 -0
- {synth_ai-0.3.1.dev1 → synth_ai-0.3.1.dev3}/synth_ai/cli/commands/train/__init__.py +0 -0
- {synth_ai-0.3.1.dev1 → synth_ai-0.3.1.dev3}/synth_ai/cli/commands/train/core.py +0 -0
- {synth_ai-0.3.1.dev1 → synth_ai-0.3.1.dev3}/synth_ai/cli/commands/train/errors.py +0 -0
- {synth_ai-0.3.1.dev1 → synth_ai-0.3.1.dev3}/synth_ai/cli/commands/train/judge_schemas.py +0 -0
- {synth_ai-0.3.1.dev1 → synth_ai-0.3.1.dev3}/synth_ai/cli/commands/train/judge_validation.py +0 -0
- {synth_ai-0.3.1.dev1 → synth_ai-0.3.1.dev3}/synth_ai/cli/commands/train/validation.py +0 -0
- {synth_ai-0.3.1.dev1 → synth_ai-0.3.1.dev3}/synth_ai/cli/demo_apps/__init__.py +0 -0
- {synth_ai-0.3.1.dev1 → synth_ai-0.3.1.dev3}/synth_ai/cli/demo_apps/core/__init__.py +0 -0
- {synth_ai-0.3.1.dev1 → synth_ai-0.3.1.dev3}/synth_ai/cli/demo_apps/core/cli.py +0 -0
- {synth_ai-0.3.1.dev1 → synth_ai-0.3.1.dev3}/synth_ai/cli/demo_apps/crafter/__init__.py +0 -0
- {synth_ai-0.3.1.dev1 → synth_ai-0.3.1.dev3}/synth_ai/cli/demo_apps/crafter/crafter_fft_4b.toml +0 -0
- {synth_ai-0.3.1.dev1 → synth_ai-0.3.1.dev3}/synth_ai/cli/demo_apps/crafter/rl_from_base_qwen4b.toml +0 -0
- {synth_ai-0.3.1.dev1 → synth_ai-0.3.1.dev3}/synth_ai/cli/demo_apps/demo_registry.py +0 -0
- {synth_ai-0.3.1.dev1 → synth_ai-0.3.1.dev3}/synth_ai/cli/demo_apps/demo_task_apps/__init__.py +0 -0
- {synth_ai-0.3.1.dev1 → synth_ai-0.3.1.dev3}/synth_ai/cli/demo_apps/demo_task_apps/core.py +0 -0
- {synth_ai-0.3.1.dev1 → synth_ai-0.3.1.dev3}/synth_ai/cli/demo_apps/demo_task_apps/crafter/__init__.py +0 -0
- {synth_ai-0.3.1.dev1 → synth_ai-0.3.1.dev3}/synth_ai/cli/demo_apps/demo_task_apps/crafter/configs/crafter_fft_4b.toml +0 -0
- {synth_ai-0.3.1.dev1 → synth_ai-0.3.1.dev3}/synth_ai/cli/demo_apps/demo_task_apps/crafter/configs/rl_from_base_qwen4b.toml +0 -0
- {synth_ai-0.3.1.dev1 → synth_ai-0.3.1.dev3}/synth_ai/cli/demo_apps/demo_task_apps/math/__init__.py +0 -0
- {synth_ai-0.3.1.dev1 → synth_ai-0.3.1.dev3}/synth_ai/cli/demo_apps/demo_task_apps/math/_common.py +0 -0
- {synth_ai-0.3.1.dev1 → synth_ai-0.3.1.dev3}/synth_ai/cli/demo_apps/demo_task_apps/math/app.py +0 -0
- {synth_ai-0.3.1.dev1 → synth_ai-0.3.1.dev3}/synth_ai/cli/demo_apps/demo_task_apps/math/config.toml +0 -0
- {synth_ai-0.3.1.dev1 → synth_ai-0.3.1.dev3}/synth_ai/cli/demo_apps/demo_task_apps/math/deploy_modal.py +0 -0
- {synth_ai-0.3.1.dev1 → synth_ai-0.3.1.dev3}/synth_ai/cli/demo_apps/demo_task_apps/math/task_app_entry.py +0 -0
- {synth_ai-0.3.1.dev1 → synth_ai-0.3.1.dev3}/synth_ai/cli/demo_apps/math/__init__.py +0 -0
- {synth_ai-0.3.1.dev1 → synth_ai-0.3.1.dev3}/synth_ai/cli/demo_apps/math/_common.py +0 -0
- {synth_ai-0.3.1.dev1 → synth_ai-0.3.1.dev3}/synth_ai/cli/demo_apps/math/app.py +0 -0
- {synth_ai-0.3.1.dev1 → synth_ai-0.3.1.dev3}/synth_ai/cli/demo_apps/math/config.toml +0 -0
- {synth_ai-0.3.1.dev1 → synth_ai-0.3.1.dev3}/synth_ai/cli/demo_apps/math/deploy_modal.py +0 -0
- {synth_ai-0.3.1.dev1 → synth_ai-0.3.1.dev3}/synth_ai/cli/demo_apps/math/task_app_entry.py +0 -0
- {synth_ai-0.3.1.dev1 → synth_ai-0.3.1.dev3}/synth_ai/cli/demo_apps/mipro/main.py +0 -0
- {synth_ai-0.3.1.dev1 → synth_ai-0.3.1.dev3}/synth_ai/cli/demo_apps/mipro/task_app.py +0 -0
- {synth_ai-0.3.1.dev1 → synth_ai-0.3.1.dev3}/synth_ai/cli/demo_apps/mipro/train_cfg.toml +0 -0
- {synth_ai-0.3.1.dev1 → synth_ai-0.3.1.dev3}/synth_ai/cli/demos/__init__.py +0 -0
- {synth_ai-0.3.1.dev1 → synth_ai-0.3.1.dev3}/synth_ai/cli/demos/demo.py +0 -0
- {synth_ai-0.3.1.dev1 → synth_ai-0.3.1.dev3}/synth_ai/cli/demos/rl_demo.py +0 -0
- {synth_ai-0.3.1.dev1 → synth_ai-0.3.1.dev3}/synth_ai/cli/deploy.py +0 -0
- {synth_ai-0.3.1.dev1 → synth_ai-0.3.1.dev3}/synth_ai/cli/infra/__init__.py +0 -0
- {synth_ai-0.3.1.dev1 → synth_ai-0.3.1.dev3}/synth_ai/cli/infra/balance.py +0 -0
- {synth_ai-0.3.1.dev1 → synth_ai-0.3.1.dev3}/synth_ai/cli/infra/mcp.py +0 -0
- {synth_ai-0.3.1.dev1 → synth_ai-0.3.1.dev3}/synth_ai/cli/infra/modal_app.py +0 -0
- {synth_ai-0.3.1.dev1 → synth_ai-0.3.1.dev3}/synth_ai/cli/infra/setup.py +0 -0
- {synth_ai-0.3.1.dev1 → synth_ai-0.3.1.dev3}/synth_ai/cli/infra/status.py +0 -0
- {synth_ai-0.3.1.dev1 → synth_ai-0.3.1.dev3}/synth_ai/cli/lib/__init__.py +0 -0
- {synth_ai-0.3.1.dev1 → synth_ai-0.3.1.dev3}/synth_ai/cli/lib/agents.py +0 -0
- {synth_ai-0.3.1.dev1 → synth_ai-0.3.1.dev3}/synth_ai/cli/lib/apps/modal_app.py +0 -0
- {synth_ai-0.3.1.dev1 → synth_ai-0.3.1.dev3}/synth_ai/cli/lib/apps/task_app.py +0 -0
- {synth_ai-0.3.1.dev1 → synth_ai-0.3.1.dev3}/synth_ai/cli/lib/bin.py +0 -0
- {synth_ai-0.3.1.dev1 → synth_ai-0.3.1.dev3}/synth_ai/cli/lib/env.py +0 -0
- {synth_ai-0.3.1.dev1 → synth_ai-0.3.1.dev3}/synth_ai/cli/lib/errors.py +0 -0
- {synth_ai-0.3.1.dev1 → synth_ai-0.3.1.dev3}/synth_ai/cli/lib/modal.py +0 -0
- {synth_ai-0.3.1.dev1 → synth_ai-0.3.1.dev3}/synth_ai/cli/lib/plotting.py +0 -0
- {synth_ai-0.3.1.dev1 → synth_ai-0.3.1.dev3}/synth_ai/cli/lib/prompt_args.py +0 -0
- {synth_ai-0.3.1.dev1 → synth_ai-0.3.1.dev3}/synth_ai/cli/lib/prompts.py +0 -0
- {synth_ai-0.3.1.dev1 → synth_ai-0.3.1.dev3}/synth_ai/cli/lib/sqld.py +0 -0
- {synth_ai-0.3.1.dev1 → synth_ai-0.3.1.dev3}/synth_ai/cli/lib/task_app_discovery.py +0 -0
- {synth_ai-0.3.1.dev1 → synth_ai-0.3.1.dev3}/synth_ai/cli/lib/train_cfgs.py +0 -0
- {synth_ai-0.3.1.dev1 → synth_ai-0.3.1.dev3}/synth_ai/cli/lib/tunnel_records.py +0 -0
- {synth_ai-0.3.1.dev1 → synth_ai-0.3.1.dev3}/synth_ai/cli/local/__init__.py +0 -0
- {synth_ai-0.3.1.dev1 → synth_ai-0.3.1.dev3}/synth_ai/cli/local/experiment_queue/__init__.py +0 -0
- {synth_ai-0.3.1.dev1 → synth_ai-0.3.1.dev3}/synth_ai/cli/local/experiment_queue/api_schemas.py +0 -0
- {synth_ai-0.3.1.dev1 → synth_ai-0.3.1.dev3}/synth_ai/cli/local/experiment_queue/celery_app.py +0 -0
- {synth_ai-0.3.1.dev1 → synth_ai-0.3.1.dev3}/synth_ai/cli/local/experiment_queue/config.py +0 -0
- {synth_ai-0.3.1.dev1 → synth_ai-0.3.1.dev3}/synth_ai/cli/local/experiment_queue/config_utils.py +0 -0
- {synth_ai-0.3.1.dev1 → synth_ai-0.3.1.dev3}/synth_ai/cli/local/experiment_queue/database.py +0 -0
- {synth_ai-0.3.1.dev1 → synth_ai-0.3.1.dev3}/synth_ai/cli/local/experiment_queue/dispatcher.py +0 -0
- {synth_ai-0.3.1.dev1 → synth_ai-0.3.1.dev3}/synth_ai/cli/local/experiment_queue/models.py +0 -0
- {synth_ai-0.3.1.dev1 → synth_ai-0.3.1.dev3}/synth_ai/cli/local/experiment_queue/progress_info.py +0 -0
- {synth_ai-0.3.1.dev1 → synth_ai-0.3.1.dev3}/synth_ai/cli/local/experiment_queue/results.py +0 -0
- {synth_ai-0.3.1.dev1 → synth_ai-0.3.1.dev3}/synth_ai/cli/local/experiment_queue/schemas.py +0 -0
- {synth_ai-0.3.1.dev1 → synth_ai-0.3.1.dev3}/synth_ai/cli/local/experiment_queue/service.py +0 -0
- {synth_ai-0.3.1.dev1 → synth_ai-0.3.1.dev3}/synth_ai/cli/local/experiment_queue/status.py +0 -0
- {synth_ai-0.3.1.dev1 → synth_ai-0.3.1.dev3}/synth_ai/cli/local/experiment_queue/status_tracker.py +0 -0
- {synth_ai-0.3.1.dev1 → synth_ai-0.3.1.dev3}/synth_ai/cli/local/experiment_queue/trace_storage.py +0 -0
- {synth_ai-0.3.1.dev1 → synth_ai-0.3.1.dev3}/synth_ai/cli/local/experiment_queue/validation.py +0 -0
- {synth_ai-0.3.1.dev1 → synth_ai-0.3.1.dev3}/synth_ai/cli/local/session/__init__.py +0 -0
- {synth_ai-0.3.1.dev1 → synth_ai-0.3.1.dev3}/synth_ai/cli/local/session/constants.py +0 -0
- {synth_ai-0.3.1.dev1 → synth_ai-0.3.1.dev3}/synth_ai/cli/local/session/exceptions.py +0 -0
- {synth_ai-0.3.1.dev1 → synth_ai-0.3.1.dev3}/synth_ai/cli/local/session/manager.py +0 -0
- {synth_ai-0.3.1.dev1 → synth_ai-0.3.1.dev3}/synth_ai/cli/local/session/models.py +0 -0
- {synth_ai-0.3.1.dev1 → synth_ai-0.3.1.dev3}/synth_ai/cli/local/session/query.py +0 -0
- {synth_ai-0.3.1.dev1 → synth_ai-0.3.1.dev3}/synth_ai/cli/root.py +0 -0
- {synth_ai-0.3.1.dev1 → synth_ai-0.3.1.dev3}/synth_ai/cli/task_apps/deploy.py +0 -0
- {synth_ai-0.3.1.dev1 → synth_ai-0.3.1.dev3}/synth_ai/cli/task_apps/list.py +0 -0
- {synth_ai-0.3.1.dev1 → synth_ai-0.3.1.dev3}/synth_ai/cli/task_apps/main.py +0 -0
- {synth_ai-0.3.1.dev1 → synth_ai-0.3.1.dev3}/synth_ai/cli/task_apps/modal_serve.py +0 -0
- {synth_ai-0.3.1.dev1 → synth_ai-0.3.1.dev3}/synth_ai/cli/task_apps/serve.py +0 -0
- {synth_ai-0.3.1.dev1 → synth_ai-0.3.1.dev3}/synth_ai/cli/training/__init__.py +0 -0
- {synth_ai-0.3.1.dev1 → synth_ai-0.3.1.dev3}/synth_ai/cli/training/train.py +0 -0
- {synth_ai-0.3.1.dev1 → synth_ai-0.3.1.dev3}/synth_ai/cli/training/train_cfg.py +0 -0
- {synth_ai-0.3.1.dev1 → synth_ai-0.3.1.dev3}/synth_ai/cli/training/watch.py +0 -0
- {synth_ai-0.3.1.dev1 → synth_ai-0.3.1.dev3}/synth_ai/cli/utils/__init__.py +0 -0
- {synth_ai-0.3.1.dev1 → synth_ai-0.3.1.dev3}/synth_ai/cli/utils/experiments.py +0 -0
- {synth_ai-0.3.1.dev1 → synth_ai-0.3.1.dev3}/synth_ai/cli/utils/queue.py +0 -0
- {synth_ai-0.3.1.dev1 → synth_ai-0.3.1.dev3}/synth_ai/cli/utils/recent.py +0 -0
- {synth_ai-0.3.1.dev1 → synth_ai-0.3.1.dev3}/synth_ai/cli/utils/traces.py +0 -0
- {synth_ai-0.3.1.dev1 → synth_ai-0.3.1.dev3}/synth_ai/contracts/__init__.py +0 -0
- {synth_ai-0.3.1.dev1 → synth_ai-0.3.1.dev3}/synth_ai/core/__init__.py +0 -0
- {synth_ai-0.3.1.dev1 → synth_ai-0.3.1.dev3}/synth_ai/core/_utils/__init__.py +0 -0
- {synth_ai-0.3.1.dev1 → synth_ai-0.3.1.dev3}/synth_ai/core/_utils/base_url.py +0 -0
- {synth_ai-0.3.1.dev1 → synth_ai-0.3.1.dev3}/synth_ai/core/_utils/http.py +0 -0
- {synth_ai-0.3.1.dev1 → synth_ai-0.3.1.dev3}/synth_ai/core/_utils/prompts.py +0 -0
- {synth_ai-0.3.1.dev1 → synth_ai-0.3.1.dev3}/synth_ai/core/_utils/task_app_state.py +0 -0
- {synth_ai-0.3.1.dev1 → synth_ai-0.3.1.dev3}/synth_ai/core/_utils/user_config.py +0 -0
- {synth_ai-0.3.1.dev1 → synth_ai-0.3.1.dev3}/synth_ai/core/apps/__init__.py +0 -0
- {synth_ai-0.3.1.dev1 → synth_ai-0.3.1.dev3}/synth_ai/core/apps/common.py +0 -0
- {synth_ai-0.3.1.dev1 → synth_ai-0.3.1.dev3}/synth_ai/core/auth.py +0 -0
- {synth_ai-0.3.1.dev1 → synth_ai-0.3.1.dev3}/synth_ai/core/cfgs.py +0 -0
- {synth_ai-0.3.1.dev1 → synth_ai-0.3.1.dev3}/synth_ai/core/config/__init__.py +0 -0
- {synth_ai-0.3.1.dev1 → synth_ai-0.3.1.dev3}/synth_ai/core/config/base.py +0 -0
- {synth_ai-0.3.1.dev1 → synth_ai-0.3.1.dev3}/synth_ai/core/config/resolver.py +0 -0
- {synth_ai-0.3.1.dev1 → synth_ai-0.3.1.dev3}/synth_ai/core/env.py +0 -0
- {synth_ai-0.3.1.dev1 → synth_ai-0.3.1.dev3}/synth_ai/core/errors.py +0 -0
- {synth_ai-0.3.1.dev1 → synth_ai-0.3.1.dev3}/synth_ai/core/http.py +0 -0
- {synth_ai-0.3.1.dev1 → synth_ai-0.3.1.dev3}/synth_ai/core/integrations/__init__.py +0 -0
- {synth_ai-0.3.1.dev1 → synth_ai-0.3.1.dev3}/synth_ai/core/integrations/cloudflare.py +0 -0
- {synth_ai-0.3.1.dev1 → synth_ai-0.3.1.dev3}/synth_ai/core/integrations/mcp/__init__.py +0 -0
- {synth_ai-0.3.1.dev1 → synth_ai-0.3.1.dev3}/synth_ai/core/integrations/mcp/__main__.py +0 -0
- {synth_ai-0.3.1.dev1 → synth_ai-0.3.1.dev3}/synth_ai/core/integrations/mcp/claude.py +0 -0
- {synth_ai-0.3.1.dev1 → synth_ai-0.3.1.dev3}/synth_ai/core/integrations/mcp/main.py +0 -0
- {synth_ai-0.3.1.dev1 → synth_ai-0.3.1.dev3}/synth_ai/core/integrations/mcp/setup.py +0 -0
- {synth_ai-0.3.1.dev1 → synth_ai-0.3.1.dev3}/synth_ai/core/integrations/modal.py +0 -0
- {synth_ai-0.3.1.dev1 → synth_ai-0.3.1.dev3}/synth_ai/core/json.py +0 -0
- {synth_ai-0.3.1.dev1 → synth_ai-0.3.1.dev3}/synth_ai/core/log_filter.py +0 -0
- {synth_ai-0.3.1.dev1 → synth_ai-0.3.1.dev3}/synth_ai/core/logging.py +0 -0
- {synth_ai-0.3.1.dev1 → synth_ai-0.3.1.dev3}/synth_ai/core/paths.py +0 -0
- {synth_ai-0.3.1.dev1 → synth_ai-0.3.1.dev3}/synth_ai/core/pricing.py +0 -0
- {synth_ai-0.3.1.dev1 → synth_ai-0.3.1.dev3}/synth_ai/core/process.py +0 -0
- {synth_ai-0.3.1.dev1 → synth_ai-0.3.1.dev3}/synth_ai/core/ssl.py +0 -0
- {synth_ai-0.3.1.dev1 → synth_ai-0.3.1.dev3}/synth_ai/core/storage/__init__.py +0 -0
- {synth_ai-0.3.1.dev1 → synth_ai-0.3.1.dev3}/synth_ai/core/task_app_state.py +0 -0
- {synth_ai-0.3.1.dev1 → synth_ai-0.3.1.dev3}/synth_ai/core/telemetry.py +0 -0
- {synth_ai-0.3.1.dev1 → synth_ai-0.3.1.dev3}/synth_ai/core/tracing_v3/__init__.py +0 -0
- {synth_ai-0.3.1.dev1 → synth_ai-0.3.1.dev3}/synth_ai/core/tracing_v3/abstractions.py +0 -0
- {synth_ai-0.3.1.dev1 → synth_ai-0.3.1.dev3}/synth_ai/core/tracing_v3/config.py +0 -0
- {synth_ai-0.3.1.dev1 → synth_ai-0.3.1.dev3}/synth_ai/core/tracing_v3/constants.py +0 -0
- {synth_ai-0.3.1.dev1 → synth_ai-0.3.1.dev3}/synth_ai/core/tracing_v3/db_config.py +0 -0
- {synth_ai-0.3.1.dev1 → synth_ai-0.3.1.dev3}/synth_ai/core/tracing_v3/decorators.py +0 -0
- {synth_ai-0.3.1.dev1 → synth_ai-0.3.1.dev3}/synth_ai/core/tracing_v3/examples/basic_usage.py +0 -0
- {synth_ai-0.3.1.dev1 → synth_ai-0.3.1.dev3}/synth_ai/core/tracing_v3/hooks.py +0 -0
- {synth_ai-0.3.1.dev1 → synth_ai-0.3.1.dev3}/synth_ai/core/tracing_v3/llm_call_record_helpers.py +0 -0
- {synth_ai-0.3.1.dev1 → synth_ai-0.3.1.dev3}/synth_ai/core/tracing_v3/lm_call_record_abstractions.py +0 -0
- {synth_ai-0.3.1.dev1 → synth_ai-0.3.1.dev3}/synth_ai/core/tracing_v3/migration_helper.py +0 -0
- {synth_ai-0.3.1.dev1 → synth_ai-0.3.1.dev3}/synth_ai/core/tracing_v3/replica_sync.py +0 -0
- {synth_ai-0.3.1.dev1 → synth_ai-0.3.1.dev3}/synth_ai/core/tracing_v3/serialization.py +0 -0
- {synth_ai-0.3.1.dev1 → synth_ai-0.3.1.dev3}/synth_ai/core/tracing_v3/session_tracer.py +0 -0
- {synth_ai-0.3.1.dev1 → synth_ai-0.3.1.dev3}/synth_ai/core/tracing_v3/storage/__init__.py +0 -0
- {synth_ai-0.3.1.dev1 → synth_ai-0.3.1.dev3}/synth_ai/core/tracing_v3/storage/base.py +0 -0
- {synth_ai-0.3.1.dev1 → synth_ai-0.3.1.dev3}/synth_ai/core/tracing_v3/storage/config.py +0 -0
- {synth_ai-0.3.1.dev1 → synth_ai-0.3.1.dev3}/synth_ai/core/tracing_v3/storage/exceptions.py +0 -0
- {synth_ai-0.3.1.dev1 → synth_ai-0.3.1.dev3}/synth_ai/core/tracing_v3/storage/factory.py +0 -0
- {synth_ai-0.3.1.dev1 → synth_ai-0.3.1.dev3}/synth_ai/core/tracing_v3/storage/types.py +0 -0
- {synth_ai-0.3.1.dev1 → synth_ai-0.3.1.dev3}/synth_ai/core/tracing_v3/storage/utils.py +0 -0
- {synth_ai-0.3.1.dev1 → synth_ai-0.3.1.dev3}/synth_ai/core/tracing_v3/turso/__init__.py +0 -0
- {synth_ai-0.3.1.dev1 → synth_ai-0.3.1.dev3}/synth_ai/core/tracing_v3/turso/models.py +0 -0
- {synth_ai-0.3.1.dev1 → synth_ai-0.3.1.dev3}/synth_ai/core/tracing_v3/utils.py +0 -0
- {synth_ai-0.3.1.dev1 → synth_ai-0.3.1.dev3}/synth_ai/core/urls.py +0 -0
- {synth_ai-0.3.1.dev1 → synth_ai-0.3.1.dev3}/synth_ai/core/user_config.py +0 -0
- {synth_ai-0.3.1.dev1 → synth_ai-0.3.1.dev3}/synth_ai/core/uvicorn.py +0 -0
- {synth_ai-0.3.1.dev1 → synth_ai-0.3.1.dev3}/synth_ai/data/__init__.py +0 -0
- {synth_ai-0.3.1.dev1 → synth_ai-0.3.1.dev3}/synth_ai/data/enums.py +0 -0
- {synth_ai-0.3.1.dev1 → synth_ai-0.3.1.dev3}/synth_ai/data/rewards.py +0 -0
- {synth_ai-0.3.1.dev1 → synth_ai-0.3.1.dev3}/synth_ai/data/specs.py +0 -0
- {synth_ai-0.3.1.dev1 → synth_ai-0.3.1.dev3}/synth_ai/data/traces.py +0 -0
- {synth_ai-0.3.1.dev1 → synth_ai-0.3.1.dev3}/synth_ai/py.typed +0 -0
- {synth_ai-0.3.1.dev1 → synth_ai-0.3.1.dev3}/synth_ai/sdk/api/models/supported.py +0 -0
- {synth_ai-0.3.1.dev1 → synth_ai-0.3.1.dev3}/synth_ai/sdk/api/research_agent/__init__.py +0 -0
- {synth_ai-0.3.1.dev1 → synth_ai-0.3.1.dev3}/synth_ai/sdk/api/research_agent/cli.py +0 -0
- {synth_ai-0.3.1.dev1 → synth_ai-0.3.1.dev3}/synth_ai/sdk/api/research_agent/job.py +0 -0
- {synth_ai-0.3.1.dev1 → synth_ai-0.3.1.dev3}/synth_ai/sdk/api/train/__init__.py +0 -0
- {synth_ai-0.3.1.dev1 → synth_ai-0.3.1.dev3}/synth_ai/sdk/api/train/builders.py +0 -0
- {synth_ai-0.3.1.dev1 → synth_ai-0.3.1.dev3}/synth_ai/sdk/api/train/cli.py +0 -0
- {synth_ai-0.3.1.dev1 → synth_ai-0.3.1.dev3}/synth_ai/sdk/api/train/config_finder.py +0 -0
- {synth_ai-0.3.1.dev1 → synth_ai-0.3.1.dev3}/synth_ai/sdk/api/train/configs/__init__.py +0 -0
- {synth_ai-0.3.1.dev1 → synth_ai-0.3.1.dev3}/synth_ai/sdk/api/train/configs/rl.py +0 -0
- {synth_ai-0.3.1.dev1 → synth_ai-0.3.1.dev3}/synth_ai/sdk/api/train/configs/sft.py +0 -0
- {synth_ai-0.3.1.dev1 → synth_ai-0.3.1.dev3}/synth_ai/sdk/api/train/configs/shared.py +0 -0
- {synth_ai-0.3.1.dev1 → synth_ai-0.3.1.dev3}/synth_ai/sdk/api/train/env_resolver.py +0 -0
- {synth_ai-0.3.1.dev1 → synth_ai-0.3.1.dev3}/synth_ai/sdk/api/train/pollers.py +0 -0
- {synth_ai-0.3.1.dev1 → synth_ai-0.3.1.dev3}/synth_ai/sdk/api/train/prompt_learning.py +0 -0
- {synth_ai-0.3.1.dev1 → synth_ai-0.3.1.dev3}/synth_ai/sdk/api/train/rl.py +0 -0
- {synth_ai-0.3.1.dev1 → synth_ai-0.3.1.dev3}/synth_ai/sdk/api/train/sft.py +0 -0
- {synth_ai-0.3.1.dev1 → synth_ai-0.3.1.dev3}/synth_ai/sdk/api/train/summary.py +0 -0
- {synth_ai-0.3.1.dev1 → synth_ai-0.3.1.dev3}/synth_ai/sdk/api/train/supported_algos.py +0 -0
- {synth_ai-0.3.1.dev1 → synth_ai-0.3.1.dev3}/synth_ai/sdk/api/train/utils.py +0 -0
- {synth_ai-0.3.1.dev1 → synth_ai-0.3.1.dev3}/synth_ai/sdk/baseline/__init__.py +0 -0
- {synth_ai-0.3.1.dev1 → synth_ai-0.3.1.dev3}/synth_ai/sdk/baseline/config.py +0 -0
- {synth_ai-0.3.1.dev1 → synth_ai-0.3.1.dev3}/synth_ai/sdk/baseline/discovery.py +0 -0
- {synth_ai-0.3.1.dev1 → synth_ai-0.3.1.dev3}/synth_ai/sdk/baseline/execution.py +0 -0
- {synth_ai-0.3.1.dev1 → synth_ai-0.3.1.dev3}/synth_ai/sdk/inference/__init__.py +0 -0
- {synth_ai-0.3.1.dev1 → synth_ai-0.3.1.dev3}/synth_ai/sdk/inference/client.py +0 -0
- {synth_ai-0.3.1.dev1 → synth_ai-0.3.1.dev3}/synth_ai/sdk/jobs/__init__.py +0 -0
- {synth_ai-0.3.1.dev1 → synth_ai-0.3.1.dev3}/synth_ai/sdk/jobs/client.py +0 -0
- {synth_ai-0.3.1.dev1 → synth_ai-0.3.1.dev3}/synth_ai/sdk/judging/__init__.py +0 -0
- {synth_ai-0.3.1.dev1 → synth_ai-0.3.1.dev3}/synth_ai/sdk/judging/base.py +0 -0
- {synth_ai-0.3.1.dev1 → synth_ai-0.3.1.dev3}/synth_ai/sdk/judging/client.py +0 -0
- {synth_ai-0.3.1.dev1 → synth_ai-0.3.1.dev3}/synth_ai/sdk/judging/schemas.py +0 -0
- {synth_ai-0.3.1.dev1 → synth_ai-0.3.1.dev3}/synth_ai/sdk/judging/types.py +0 -0
- {synth_ai-0.3.1.dev1 → synth_ai-0.3.1.dev3}/synth_ai/sdk/learning/__init__.py +0 -0
- {synth_ai-0.3.1.dev1 → synth_ai-0.3.1.dev3}/synth_ai/sdk/learning/algorithms.py +0 -0
- {synth_ai-0.3.1.dev1 → synth_ai-0.3.1.dev3}/synth_ai/sdk/learning/client.py +0 -0
- {synth_ai-0.3.1.dev1 → synth_ai-0.3.1.dev3}/synth_ai/sdk/learning/config.py +0 -0
- {synth_ai-0.3.1.dev1 → synth_ai-0.3.1.dev3}/synth_ai/sdk/learning/constants.py +0 -0
- {synth_ai-0.3.1.dev1 → synth_ai-0.3.1.dev3}/synth_ai/sdk/learning/core.py +0 -0
- {synth_ai-0.3.1.dev1 → synth_ai-0.3.1.dev3}/synth_ai/sdk/learning/ft_client.py +0 -0
- {synth_ai-0.3.1.dev1 → synth_ai-0.3.1.dev3}/synth_ai/sdk/learning/gateway.py +0 -0
- {synth_ai-0.3.1.dev1 → synth_ai-0.3.1.dev3}/synth_ai/sdk/learning/health.py +0 -0
- {synth_ai-0.3.1.dev1 → synth_ai-0.3.1.dev3}/synth_ai/sdk/learning/jobs.py +0 -0
- {synth_ai-0.3.1.dev1 → synth_ai-0.3.1.dev3}/synth_ai/sdk/learning/prompt_extraction.py +0 -0
- {synth_ai-0.3.1.dev1 → synth_ai-0.3.1.dev3}/synth_ai/sdk/learning/prompt_learning_client.py +0 -0
- {synth_ai-0.3.1.dev1 → synth_ai-0.3.1.dev3}/synth_ai/sdk/learning/prompt_learning_types.py +0 -0
- {synth_ai-0.3.1.dev1 → synth_ai-0.3.1.dev3}/synth_ai/sdk/learning/rl/__init__.py +0 -0
- {synth_ai-0.3.1.dev1 → synth_ai-0.3.1.dev3}/synth_ai/sdk/learning/rl/client.py +0 -0
- {synth_ai-0.3.1.dev1 → synth_ai-0.3.1.dev3}/synth_ai/sdk/learning/rl/config.py +0 -0
- {synth_ai-0.3.1.dev1 → synth_ai-0.3.1.dev3}/synth_ai/sdk/learning/rl/contracts.py +0 -0
- {synth_ai-0.3.1.dev1 → synth_ai-0.3.1.dev3}/synth_ai/sdk/learning/rl/env_keys.py +0 -0
- {synth_ai-0.3.1.dev1 → synth_ai-0.3.1.dev3}/synth_ai/sdk/learning/rl/secrets.py +0 -0
- {synth_ai-0.3.1.dev1 → synth_ai-0.3.1.dev3}/synth_ai/sdk/learning/rl_client.py +0 -0
- {synth_ai-0.3.1.dev1 → synth_ai-0.3.1.dev3}/synth_ai/sdk/learning/sft/__init__.py +0 -0
- {synth_ai-0.3.1.dev1 → synth_ai-0.3.1.dev3}/synth_ai/sdk/learning/sft/config.py +0 -0
- {synth_ai-0.3.1.dev1 → synth_ai-0.3.1.dev3}/synth_ai/sdk/learning/sft/data.py +0 -0
- {synth_ai-0.3.1.dev1 → synth_ai-0.3.1.dev3}/synth_ai/sdk/learning/sse.py +0 -0
- {synth_ai-0.3.1.dev1 → synth_ai-0.3.1.dev3}/synth_ai/sdk/learning/validators.py +0 -0
- {synth_ai-0.3.1.dev1 → synth_ai-0.3.1.dev3}/synth_ai/sdk/research_agent/__init__.py +0 -0
- {synth_ai-0.3.1.dev1 → synth_ai-0.3.1.dev3}/synth_ai/sdk/research_agent/container_builder.py +0 -0
- {synth_ai-0.3.1.dev1 → synth_ai-0.3.1.dev3}/synth_ai/sdk/research_agent/container_spec.py +0 -0
- {synth_ai-0.3.1.dev1 → synth_ai-0.3.1.dev3}/synth_ai/sdk/research_agent/defaults.py +0 -0
- {synth_ai-0.3.1.dev1 → synth_ai-0.3.1.dev3}/synth_ai/sdk/research_agent/results_collector.py +0 -0
- {synth_ai-0.3.1.dev1 → synth_ai-0.3.1.dev3}/synth_ai/sdk/specs/__init__.py +0 -0
- {synth_ai-0.3.1.dev1 → synth_ai-0.3.1.dev3}/synth_ai/sdk/specs/dataclasses.py +0 -0
- {synth_ai-0.3.1.dev1 → synth_ai-0.3.1.dev3}/synth_ai/sdk/specs/loader.py +0 -0
- {synth_ai-0.3.1.dev1 → synth_ai-0.3.1.dev3}/synth_ai/sdk/specs/serializer.py +0 -0
- {synth_ai-0.3.1.dev1 → synth_ai-0.3.1.dev3}/synth_ai/sdk/specs/validation.py +0 -0
- {synth_ai-0.3.1.dev1 → synth_ai-0.3.1.dev3}/synth_ai/sdk/streaming/__init__.py +0 -0
- {synth_ai-0.3.1.dev1 → synth_ai-0.3.1.dev3}/synth_ai/sdk/streaming/config.py +0 -0
- {synth_ai-0.3.1.dev1 → synth_ai-0.3.1.dev3}/synth_ai/sdk/streaming/handlers.py +0 -0
- {synth_ai-0.3.1.dev1 → synth_ai-0.3.1.dev3}/synth_ai/sdk/streaming/streamer.py +0 -0
- {synth_ai-0.3.1.dev1 → synth_ai-0.3.1.dev3}/synth_ai/sdk/streaming/types.py +0 -0
- {synth_ai-0.3.1.dev1 → synth_ai-0.3.1.dev3}/synth_ai/sdk/task/auth.py +0 -0
- {synth_ai-0.3.1.dev1 → synth_ai-0.3.1.dev3}/synth_ai/sdk/task/client.py +0 -0
- {synth_ai-0.3.1.dev1 → synth_ai-0.3.1.dev3}/synth_ai/sdk/task/config.py +0 -0
- {synth_ai-0.3.1.dev1 → synth_ai-0.3.1.dev3}/synth_ai/sdk/task/contracts.py +0 -0
- {synth_ai-0.3.1.dev1 → synth_ai-0.3.1.dev3}/synth_ai/sdk/task/errors.py +0 -0
- {synth_ai-0.3.1.dev1 → synth_ai-0.3.1.dev3}/synth_ai/sdk/task/health.py +0 -0
- {synth_ai-0.3.1.dev1 → synth_ai-0.3.1.dev3}/synth_ai/sdk/task/inference_api.py +0 -0
- {synth_ai-0.3.1.dev1 → synth_ai-0.3.1.dev3}/synth_ai/sdk/task/json.py +0 -0
- {synth_ai-0.3.1.dev1 → synth_ai-0.3.1.dev3}/synth_ai/sdk/task/proxy.py +0 -0
- {synth_ai-0.3.1.dev1 → synth_ai-0.3.1.dev3}/synth_ai/sdk/task/rubrics/__init__.py +0 -0
- {synth_ai-0.3.1.dev1 → synth_ai-0.3.1.dev3}/synth_ai/sdk/task/rubrics/loaders.py +0 -0
- {synth_ai-0.3.1.dev1 → synth_ai-0.3.1.dev3}/synth_ai/sdk/task/rubrics/models.py +0 -0
- {synth_ai-0.3.1.dev1 → synth_ai-0.3.1.dev3}/synth_ai/sdk/task/rubrics/scoring.py +0 -0
- {synth_ai-0.3.1.dev1 → synth_ai-0.3.1.dev3}/synth_ai/sdk/task/rubrics/strict.py +0 -0
- {synth_ai-0.3.1.dev1 → synth_ai-0.3.1.dev3}/synth_ai/sdk/task/rubrics.py +0 -0
- {synth_ai-0.3.1.dev1 → synth_ai-0.3.1.dev3}/synth_ai/sdk/task/server.py +0 -0
- {synth_ai-0.3.1.dev1 → synth_ai-0.3.1.dev3}/synth_ai/sdk/task/trace_correlation_helpers.py +0 -0
- {synth_ai-0.3.1.dev1 → synth_ai-0.3.1.dev3}/synth_ai/sdk/task/tracing_utils.py +0 -0
- {synth_ai-0.3.1.dev1 → synth_ai-0.3.1.dev3}/synth_ai/sdk/task/validators.py +0 -0
- {synth_ai-0.3.1.dev1 → synth_ai-0.3.1.dev3}/synth_ai/sdk/task/vendors.py +0 -0
- {synth_ai-0.3.1.dev1 → synth_ai-0.3.1.dev3}/synth_ai/sdk/tracing/__init__.py +0 -0
- {synth_ai-0.3.1.dev1 → synth_ai-0.3.1.dev3}/synth_ai/sdk/training/__init__.py +0 -0
- {synth_ai-0.3.1.dev1 → synth_ai-0.3.1.dev3}/synth_ai/utils/__init__.py +0 -0
- {synth_ai-0.3.1.dev1 → synth_ai-0.3.1.dev3}/synth_ai.egg-info/dependency_links.txt +0 -0
- {synth_ai-0.3.1.dev1 → synth_ai-0.3.1.dev3}/synth_ai.egg-info/entry_points.txt +0 -0
- {synth_ai-0.3.1.dev1 → synth_ai-0.3.1.dev3}/synth_ai.egg-info/requires.txt +0 -0
- {synth_ai-0.3.1.dev1 → synth_ai-0.3.1.dev3}/synth_ai.egg-info/top_level.txt +0 -0
|
@@ -0,0 +1,154 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: synth-ai
|
|
3
|
+
Version: 0.3.1.dev3
|
|
4
|
+
Summary: Serverless Posttraining for Agents - Core AI functionality and tracing
|
|
5
|
+
Author-email: Synth AI <josh@usesynth.ai>
|
|
6
|
+
License-Expression: MIT
|
|
7
|
+
Project-URL: Homepage, https://github.com/synth-laboratories/synth-ai
|
|
8
|
+
Project-URL: Repository, https://github.com/synth-laboratories/synth-ai
|
|
9
|
+
Project-URL: Issues, https://github.com/synth-laboratories/synth-ai/issues
|
|
10
|
+
Requires-Python: >=3.11
|
|
11
|
+
Description-Content-Type: text/markdown
|
|
12
|
+
License-File: LICENSE
|
|
13
|
+
Requires-Dist: pydantic>=2.0.0
|
|
14
|
+
Requires-Dist: python-dotenv>=1.0.1
|
|
15
|
+
Requires-Dist: requests>=2.32.3
|
|
16
|
+
Requires-Dist: tqdm>=4.66.4
|
|
17
|
+
Requires-Dist: typing_extensions>=4.0.0
|
|
18
|
+
Requires-Dist: rich>=13.9.0
|
|
19
|
+
Requires-Dist: openai>=1.99.0
|
|
20
|
+
Requires-Dist: anthropic>=0.42.0
|
|
21
|
+
Requires-Dist: langfuse<3.0.0,>=2.53.9
|
|
22
|
+
Requires-Dist: opentelemetry-api>=1.26.0
|
|
23
|
+
Requires-Dist: opentelemetry-sdk>=1.26.0
|
|
24
|
+
Requires-Dist: groq>=0.30.0
|
|
25
|
+
Requires-Dist: google-genai>=1.26.0
|
|
26
|
+
Requires-Dist: together>=1.5.21
|
|
27
|
+
Requires-Dist: mistralai>=1.9.2
|
|
28
|
+
Requires-Dist: fastapi>=0.115.12
|
|
29
|
+
Requires-Dist: uvicorn>=0.34.2
|
|
30
|
+
Requires-Dist: numpy>=2.2.3
|
|
31
|
+
Requires-Dist: networkx>=3.4.2
|
|
32
|
+
Requires-Dist: sqlalchemy>=2.0.42
|
|
33
|
+
Requires-Dist: celery>=5.4.0
|
|
34
|
+
Requires-Dist: redis>=6.2.0
|
|
35
|
+
Requires-Dist: aiosqlite>=0.21.0
|
|
36
|
+
Requires-Dist: libsql>=0.1.8
|
|
37
|
+
Requires-Dist: pynacl>=1.5.0
|
|
38
|
+
Requires-Dist: click<8.2,>=8.1.7
|
|
39
|
+
Requires-Dist: aiohttp>=3.8.0
|
|
40
|
+
Requires-Dist: httpx>=0.28.1
|
|
41
|
+
Requires-Dist: modal<2.0.0,>=1.1.4
|
|
42
|
+
Requires-Dist: docker>=7.0.0
|
|
43
|
+
Requires-Dist: mcp>=1.21.0
|
|
44
|
+
Requires-Dist: ruff>=0.12.9
|
|
45
|
+
Requires-Dist: tomli_w>=1.0.0
|
|
46
|
+
Requires-Dist: dspy>=3.0.4
|
|
47
|
+
Requires-Dist: setuptools>=80.9.0
|
|
48
|
+
Requires-Dist: gymnasium>=0.26.2
|
|
49
|
+
Requires-Dist: gepa>=0.0.17
|
|
50
|
+
Requires-Dist: datasets>=4.0.0
|
|
51
|
+
Provides-Extra: dev
|
|
52
|
+
Requires-Dist: build>=1.2.2.post1; extra == "dev"
|
|
53
|
+
Requires-Dist: twine>=4.0.0; extra == "dev"
|
|
54
|
+
Requires-Dist: keyring>=24.0.0; extra == "dev"
|
|
55
|
+
Requires-Dist: pytest>=8.3.3; extra == "dev"
|
|
56
|
+
Requires-Dist: pytest-xdist>=3.6.1; extra == "dev"
|
|
57
|
+
Requires-Dist: pytest-timeout>=2.3.1; extra == "dev"
|
|
58
|
+
Requires-Dist: pytest-asyncio>=0.24.0; extra == "dev"
|
|
59
|
+
Requires-Dist: pytest-cov>=4.1.0; extra == "dev"
|
|
60
|
+
Requires-Dist: pyright>=1.1.350; extra == "dev"
|
|
61
|
+
Requires-Dist: coverage[toml]>=7.3.0; extra == "dev"
|
|
62
|
+
Requires-Dist: ruff>=0.1.0; extra == "dev"
|
|
63
|
+
Provides-Extra: research
|
|
64
|
+
Requires-Dist: crafter>=1.8.3; extra == "research"
|
|
65
|
+
Requires-Dist: datasets>=4.0.0; extra == "research"
|
|
66
|
+
Provides-Extra: swe
|
|
67
|
+
Requires-Dist: morphcloud>=0.1.3; extra == "swe"
|
|
68
|
+
Requires-Dist: swebench>=2.3.0; extra == "swe"
|
|
69
|
+
Provides-Extra: all
|
|
70
|
+
Requires-Dist: crafter>=1.8.3; extra == "all"
|
|
71
|
+
Requires-Dist: datasets>=4.0.0; extra == "all"
|
|
72
|
+
Requires-Dist: morphcloud>=0.1.3; extra == "all"
|
|
73
|
+
Requires-Dist: swebench>=2.3.0; extra == "all"
|
|
74
|
+
Requires-Dist: pyboy>=2.6.0; extra == "all"
|
|
75
|
+
Requires-Dist: transformers>=4.56.1; extra == "all"
|
|
76
|
+
Requires-Dist: redis>=6.2.0; extra == "all"
|
|
77
|
+
Provides-Extra: analytics
|
|
78
|
+
Requires-Dist: pandas>=2.2.3; extra == "analytics"
|
|
79
|
+
Dynamic: license-file
|
|
80
|
+
|
|
81
|
+
# Synth
|
|
82
|
+
|
|
83
|
+
[](https://www.python.org/)
|
|
84
|
+
[](https://pypi.org/project/synth-ai/)
|
|
85
|
+
[](LICENSE)
|
|
86
|
+

|
|
87
|
+

|
|
88
|
+
|
|
89
|
+
Serverless Posttraining APIs for Developers
|
|
90
|
+
|
|
91
|
+
<p align="center">
|
|
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">
|
|
96
|
+
</picture>
|
|
97
|
+
</p>
|
|
98
|
+
|
|
99
|
+
<p align="center">
|
|
100
|
+
<i>Average accuracy on <a href="https://arxiv.org/abs/2502.20315">LangProBe</a> prompt optimization benchmarks.</i>
|
|
101
|
+
</p>
|
|
102
|
+
|
|
103
|
+
## Highlights
|
|
104
|
+
|
|
105
|
+
- 🚀 Train across sft, RL, and prompt opt by standing up a single cloudflared Fastapi wrapper around your code. No production code churn.
|
|
106
|
+
- ⚡️ Parallelize training and achieve 80% GPU util. via PipelineRL
|
|
107
|
+
- 🗂️ Train prompts and models across multiple experiments
|
|
108
|
+
- 🛠️ Spin up experiment queues and datastores locally for dev work
|
|
109
|
+
- 🔩 Run serverless training via cli or programmatically
|
|
110
|
+
- 🏢 Scales gpu-based model training to 64 H100s seemlessly
|
|
111
|
+
- 💾 Use GEPA-calibrated judges for fast, accurate rubric scoring
|
|
112
|
+
- 🖥️ Supports HTTP-based training across all programming languages
|
|
113
|
+
- 🤖 CLI utilities tuned for use with Claude Code, Codex, Opencode
|
|
114
|
+
|
|
115
|
+
## Getting Started
|
|
116
|
+
|
|
117
|
+
```bash
|
|
118
|
+
# Use with OpenAI Codex
|
|
119
|
+
uvx synth-ai codex
|
|
120
|
+
```
|
|
121
|
+
|
|
122
|
+
```bash
|
|
123
|
+
# Use with Opencode
|
|
124
|
+
uvx synth-ai opencode
|
|
125
|
+
```
|
|
126
|
+
|
|
127
|
+
Synth is maintained by devs behind the [MIPROv2](https://scholar.google.com/citations?view_op=view_citation&hl=en&user=jauNVA8AAAAJ&citation_for_view=jauNVA8AAAAJ:u5HHmVD_uO8C) prompt optimizer.
|
|
128
|
+
|
|
129
|
+
## Documentation
|
|
130
|
+
|
|
131
|
+
Docs available at [docs.usesynth.ai](https://docs.usesynth.ai/overview).
|
|
132
|
+
|
|
133
|
+
## In-Process Runner (SDK)
|
|
134
|
+
|
|
135
|
+
Run GEPA/MIPRO/RL jobs against a tunneled task app without the CLI:
|
|
136
|
+
|
|
137
|
+
```python
|
|
138
|
+
import asyncio
|
|
139
|
+
import os
|
|
140
|
+
from synth_ai.sdk.task import run_in_process_job
|
|
141
|
+
|
|
142
|
+
result = asyncio.run(
|
|
143
|
+
run_in_process_job(
|
|
144
|
+
job_type="prompt_learning",
|
|
145
|
+
config_path="configs/style_matching_gepa.toml",
|
|
146
|
+
task_app_path="task_apps/style_matching_task_app.py",
|
|
147
|
+
overrides={"prompt_learning.gepa.rollout.budget": 4},
|
|
148
|
+
backend_url=os.getenv("TARGET_BACKEND_BASE_URL"), # resolves envs automatically
|
|
149
|
+
)
|
|
150
|
+
)
|
|
151
|
+
print(result.job_id, result.status.get("status"))
|
|
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.
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
# Synth
|
|
2
|
+
|
|
3
|
+
[](https://www.python.org/)
|
|
4
|
+
[](https://pypi.org/project/synth-ai/)
|
|
5
|
+
[](LICENSE)
|
|
6
|
+

|
|
7
|
+

|
|
8
|
+
|
|
9
|
+
Serverless Posttraining APIs for Developers
|
|
10
|
+
|
|
11
|
+
<p align="center">
|
|
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">
|
|
16
|
+
</picture>
|
|
17
|
+
</p>
|
|
18
|
+
|
|
19
|
+
<p align="center">
|
|
20
|
+
<i>Average accuracy on <a href="https://arxiv.org/abs/2502.20315">LangProBe</a> prompt optimization benchmarks.</i>
|
|
21
|
+
</p>
|
|
22
|
+
|
|
23
|
+
## Highlights
|
|
24
|
+
|
|
25
|
+
- 🚀 Train across sft, RL, and prompt opt by standing up a single cloudflared Fastapi wrapper around your code. No production code churn.
|
|
26
|
+
- ⚡️ Parallelize training and achieve 80% GPU util. via PipelineRL
|
|
27
|
+
- 🗂️ Train prompts and models across multiple experiments
|
|
28
|
+
- 🛠️ Spin up experiment queues and datastores locally for dev work
|
|
29
|
+
- 🔩 Run serverless training via cli or programmatically
|
|
30
|
+
- 🏢 Scales gpu-based model training to 64 H100s seemlessly
|
|
31
|
+
- 💾 Use GEPA-calibrated judges for fast, accurate rubric scoring
|
|
32
|
+
- 🖥️ Supports HTTP-based training across all programming languages
|
|
33
|
+
- 🤖 CLI utilities tuned for use with Claude Code, Codex, Opencode
|
|
34
|
+
|
|
35
|
+
## Getting Started
|
|
36
|
+
|
|
37
|
+
```bash
|
|
38
|
+
# Use with OpenAI Codex
|
|
39
|
+
uvx synth-ai codex
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
```bash
|
|
43
|
+
# Use with Opencode
|
|
44
|
+
uvx synth-ai opencode
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
Synth is maintained by devs behind the [MIPROv2](https://scholar.google.com/citations?view_op=view_citation&hl=en&user=jauNVA8AAAAJ&citation_for_view=jauNVA8AAAAJ:u5HHmVD_uO8C) prompt optimizer.
|
|
48
|
+
|
|
49
|
+
## Documentation
|
|
50
|
+
|
|
51
|
+
Docs available at [docs.usesynth.ai](https://docs.usesynth.ai/overview).
|
|
52
|
+
|
|
53
|
+
## In-Process Runner (SDK)
|
|
54
|
+
|
|
55
|
+
Run GEPA/MIPRO/RL jobs against a tunneled task app without the CLI:
|
|
56
|
+
|
|
57
|
+
```python
|
|
58
|
+
import asyncio
|
|
59
|
+
import os
|
|
60
|
+
from synth_ai.sdk.task import run_in_process_job
|
|
61
|
+
|
|
62
|
+
result = asyncio.run(
|
|
63
|
+
run_in_process_job(
|
|
64
|
+
job_type="prompt_learning",
|
|
65
|
+
config_path="configs/style_matching_gepa.toml",
|
|
66
|
+
task_app_path="task_apps/style_matching_task_app.py",
|
|
67
|
+
overrides={"prompt_learning.gepa.rollout.budget": 4},
|
|
68
|
+
backend_url=os.getenv("TARGET_BACKEND_BASE_URL"), # resolves envs automatically
|
|
69
|
+
)
|
|
70
|
+
)
|
|
71
|
+
print(result.job_id, result.status.get("status"))
|
|
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.
|
|
@@ -194,7 +194,7 @@ def _start_task_app_server(
|
|
|
194
194
|
|
|
195
195
|
# Resolve the synth-ai root directory
|
|
196
196
|
import synth_ai
|
|
197
|
-
synth_ai_root = Path(synth_ai.__file__).resolve().parent.parent
|
|
197
|
+
synth_ai_root = Path(synth_ai.__file__ or Path(__file__).resolve()).resolve().parent.parent
|
|
198
198
|
|
|
199
199
|
click.echo(f"[smoke] Starting task app '{task_app_name}' on port {port}...", err=True)
|
|
200
200
|
click.echo(f"[smoke] Command: {' '.join(cmd)}", err=True)
|
{synth_ai-0.3.1.dev1 → synth_ai-0.3.1.dev3}/synth_ai/cli/demo_apps/crafter/grpo_crafter_task_app.py
RENAMED
|
@@ -25,7 +25,7 @@ from synth_ai.sdk.task.server import TaskAppConfig, create_task_app, run_task_ap
|
|
|
25
25
|
def _load_build_config():
|
|
26
26
|
import synth_ai
|
|
27
27
|
|
|
28
|
-
synth_ai_path = Path(synth_ai.__file__).resolve().parent.parent
|
|
28
|
+
synth_ai_path = Path(synth_ai.__file__ or Path(__file__).resolve()).resolve().parent.parent
|
|
29
29
|
module_path = synth_ai_path / "examples" / "warming_up_to_rl" / "task_app" / "grpo_crafter.py"
|
|
30
30
|
|
|
31
31
|
if not module_path.exists():
|
|
@@ -33,7 +33,7 @@ def _load_build_config():
|
|
|
33
33
|
|
|
34
34
|
import synth_ai
|
|
35
35
|
|
|
36
|
-
synth_ai_path = Path(synth_ai.__file__).resolve().parent.parent
|
|
36
|
+
synth_ai_path = Path(synth_ai.__file__ or Path(__file__).resolve()).resolve().parent.parent
|
|
37
37
|
module_path = (
|
|
38
38
|
synth_ai_path / "examples" / "task_apps" / "crafter" / "task_app" / "grpo_crafter.py"
|
|
39
39
|
)
|
|
@@ -499,11 +499,8 @@ def fastapi_app():
|
|
|
499
499
|
seed_val = 0
|
|
500
500
|
if seed_val == 0:
|
|
501
501
|
try:
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
if isinstance(env_cfg, dict) and env_cfg.get("seed") is not None
|
|
505
|
-
else 0
|
|
506
|
-
)
|
|
502
|
+
raw_seed = env_cfg.get("seed") if isinstance(env_cfg, dict) else None
|
|
503
|
+
seed_val = int(raw_seed) if raw_seed is not None else 0
|
|
507
504
|
except Exception:
|
|
508
505
|
seed_val = 0
|
|
509
506
|
subject = (env_cfg.get("subject") if isinstance(env_cfg, dict) else None) or os.getenv(
|
|
@@ -487,11 +487,8 @@ def fastapi_app():
|
|
|
487
487
|
seed_val = 0
|
|
488
488
|
if seed_val == 0:
|
|
489
489
|
try:
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
if isinstance(env_cfg, dict) and env_cfg.get("seed") is not None
|
|
493
|
-
else 0
|
|
494
|
-
)
|
|
490
|
+
raw_seed = env_cfg.get("seed") if isinstance(env_cfg, dict) else None
|
|
491
|
+
seed_val = int(raw_seed) if raw_seed is not None else 0
|
|
495
492
|
except Exception:
|
|
496
493
|
seed_val = 0
|
|
497
494
|
subject = (env_cfg.get("subject") if isinstance(env_cfg, dict) else None) or os.getenv(
|
|
@@ -6,7 +6,7 @@ import subprocess
|
|
|
6
6
|
|
|
7
7
|
import click
|
|
8
8
|
|
|
9
|
-
from .root import SQLD_VERSION, find_sqld_binary, install_sqld # type: ignore[import-untyped]
|
|
9
|
+
from synth_ai.cli.root import SQLD_VERSION, find_sqld_binary, install_sqld # type: ignore[import-untyped]
|
|
10
10
|
|
|
11
11
|
|
|
12
12
|
def register(cli: click.Group) -> None:
|
|
@@ -1,4 +1,7 @@
|
|
|
1
1
|
import os
|
|
2
|
+
import re
|
|
3
|
+
from pathlib import Path
|
|
4
|
+
from typing import Dict
|
|
2
5
|
|
|
3
6
|
import click
|
|
4
7
|
|
|
@@ -13,8 +16,12 @@ __all__ = [
|
|
|
13
16
|
"ensure_env_credentials",
|
|
14
17
|
"ensure_port_free",
|
|
15
18
|
"preflight_env_key",
|
|
19
|
+
"interactive_fill_env",
|
|
20
|
+
"save_to_env_file",
|
|
16
21
|
]
|
|
17
22
|
|
|
23
|
+
_ENV_LINE = re.compile(r"^\s*(?:export\s+)?(?P<key>[A-Za-z0-9_]+)\s*=\s*(?P<value>.*)$")
|
|
24
|
+
|
|
18
25
|
|
|
19
26
|
def ensure_env_credentials(*, require_synth: bool = False, prompt: bool = True) -> None:
|
|
20
27
|
"""Ensure required API keys are present in the process environment."""
|
|
@@ -185,3 +192,104 @@ def preflight_env_key(*, crash_on_failure: bool = False) -> None:
|
|
|
185
192
|
if crash_on_failure:
|
|
186
193
|
raise click.ClickException(f"[CRITICAL] {message}") from exc
|
|
187
194
|
click.echo(f"[WARN] {message}; proceeding anyway")
|
|
195
|
+
|
|
196
|
+
|
|
197
|
+
def _parse_env_file(path: Path) -> dict[str, str]:
|
|
198
|
+
data: dict[str, str] = {}
|
|
199
|
+
try:
|
|
200
|
+
for line in path.read_text(encoding="utf-8").splitlines():
|
|
201
|
+
if not line or line.lstrip().startswith("#") or "=" not in line:
|
|
202
|
+
continue
|
|
203
|
+
key, value = line.split("=", 1)
|
|
204
|
+
data[key.strip()] = value.strip()
|
|
205
|
+
except FileNotFoundError:
|
|
206
|
+
pass
|
|
207
|
+
return data
|
|
208
|
+
|
|
209
|
+
|
|
210
|
+
def _merge_env_content(original: str, updates: Dict[str, str]) -> str:
|
|
211
|
+
"""Merge env updates into existing content while preserving comments/spacing."""
|
|
212
|
+
lines = original.splitlines(keepends=True)
|
|
213
|
+
seen: set[str] = set()
|
|
214
|
+
newline_default = "\n"
|
|
215
|
+
if lines and lines[-1].endswith("\r\n"):
|
|
216
|
+
newline_default = "\r\n"
|
|
217
|
+
|
|
218
|
+
merged: list[str] = []
|
|
219
|
+
for line in lines:
|
|
220
|
+
stripped = line.rstrip("\r\n")
|
|
221
|
+
m = _ENV_LINE.match(stripped)
|
|
222
|
+
key = m.group("key") if m else None
|
|
223
|
+
if key and key in updates and key not in seen:
|
|
224
|
+
end = "\r\n" if line.endswith("\r\n") else "\n"
|
|
225
|
+
merged.append(f"{key}={updates[key]}{end}")
|
|
226
|
+
seen.add(key)
|
|
227
|
+
else:
|
|
228
|
+
merged.append(line)
|
|
229
|
+
|
|
230
|
+
for key, val in updates.items():
|
|
231
|
+
if key not in seen:
|
|
232
|
+
merged.append(f"{key}={val}{newline_default}")
|
|
233
|
+
|
|
234
|
+
if merged and not merged[-1].endswith(("\n", "\r\n")):
|
|
235
|
+
merged[-1] = merged[-1] + newline_default
|
|
236
|
+
|
|
237
|
+
return "".join(merged)
|
|
238
|
+
|
|
239
|
+
|
|
240
|
+
def save_to_env_file(env_path: Path, key: str, value: str) -> Path:
|
|
241
|
+
"""Update a single key in .env preserving comments/formatting."""
|
|
242
|
+
existing = env_path.read_text(encoding="utf-8", errors="ignore") if env_path.exists() else ""
|
|
243
|
+
merged = _merge_env_content(existing, {key: value})
|
|
244
|
+
env_path.parent.mkdir(parents=True, exist_ok=True)
|
|
245
|
+
env_path.write_text(merged, encoding="utf-8")
|
|
246
|
+
return env_path
|
|
247
|
+
|
|
248
|
+
|
|
249
|
+
def interactive_fill_env(env_path: Path) -> Path | None:
|
|
250
|
+
"""Fill ENVIRONMENT_API_KEY/SYNTH_API_KEY/OPENAI_API_KEY while preserving file content."""
|
|
251
|
+
existing = _parse_env_file(env_path) if env_path.exists() else {}
|
|
252
|
+
|
|
253
|
+
def _prompt(label: str, *, default: str = "", required: bool) -> str | None:
|
|
254
|
+
while True:
|
|
255
|
+
try:
|
|
256
|
+
value = click.prompt(
|
|
257
|
+
label, default=default, show_default=bool(default) or not required
|
|
258
|
+
).strip()
|
|
259
|
+
except (click.Abort, EOFError, KeyboardInterrupt): # pragma: no cover - interactive paths
|
|
260
|
+
click.echo("Aborted env creation.")
|
|
261
|
+
return None
|
|
262
|
+
if value or not required:
|
|
263
|
+
return value
|
|
264
|
+
click.echo("This field is required.")
|
|
265
|
+
|
|
266
|
+
# Allow non-interactive tests to run; skip TTY enforcement.
|
|
267
|
+
env_api_key = _prompt(
|
|
268
|
+
"ENVIRONMENT_API_KEY",
|
|
269
|
+
default=existing.get("ENVIRONMENT_API_KEY", ""),
|
|
270
|
+
required=True,
|
|
271
|
+
)
|
|
272
|
+
if env_api_key is None:
|
|
273
|
+
return None
|
|
274
|
+
synth_key = _prompt(
|
|
275
|
+
"SYNTH_API_KEY (optional)",
|
|
276
|
+
default=existing.get("SYNTH_API_KEY", ""),
|
|
277
|
+
required=False,
|
|
278
|
+
) or ""
|
|
279
|
+
openai_key = _prompt(
|
|
280
|
+
"OPENAI_API_KEY (optional)",
|
|
281
|
+
default=existing.get("OPENAI_API_KEY", ""),
|
|
282
|
+
required=False,
|
|
283
|
+
) or ""
|
|
284
|
+
|
|
285
|
+
updates = {
|
|
286
|
+
"ENVIRONMENT_API_KEY": env_api_key,
|
|
287
|
+
"SYNTH_API_KEY": synth_key,
|
|
288
|
+
"OPENAI_API_KEY": openai_key,
|
|
289
|
+
}
|
|
290
|
+
|
|
291
|
+
content = env_path.read_text(encoding="utf-8", errors="ignore") if env_path.exists() else ""
|
|
292
|
+
merged = _merge_env_content(content, updates)
|
|
293
|
+
env_path.parent.mkdir(parents=True, exist_ok=True)
|
|
294
|
+
env_path.write_text(merged, encoding="utf-8")
|
|
295
|
+
return env_path
|
|
@@ -97,7 +97,7 @@ def _find_venv_python() -> str:
|
|
|
97
97
|
try:
|
|
98
98
|
import synth_ai
|
|
99
99
|
|
|
100
|
-
package_path = Path(synth_ai.__file__).parent.parent.parent
|
|
100
|
+
package_path = Path(synth_ai.__file__ or Path(__file__).resolve()).parent.parent.parent
|
|
101
101
|
pkg_venv = package_path / ".venv" / "bin" / "python"
|
|
102
102
|
if pkg_venv.exists() and os.access(pkg_venv, os.X_OK):
|
|
103
103
|
return str(pkg_venv)
|
|
@@ -4,7 +4,7 @@ from __future__ import annotations
|
|
|
4
4
|
|
|
5
5
|
from datetime import datetime
|
|
6
6
|
from decimal import Decimal
|
|
7
|
-
from typing import Any, Optional
|
|
7
|
+
from typing import Any, List, Optional
|
|
8
8
|
from uuid import UUID
|
|
9
9
|
|
|
10
10
|
from synth_ai.core.http import AsyncHttpClient, HTTPError
|
|
@@ -98,7 +98,7 @@ class AgentSessionClient:
|
|
|
98
98
|
async def create(
|
|
99
99
|
self,
|
|
100
100
|
org_id: Optional[UUID] = None,
|
|
101
|
-
limits: Optional[
|
|
101
|
+
limits: Optional[List[dict[str, Any]]] = None,
|
|
102
102
|
tracing_session_id: Optional[str] = None,
|
|
103
103
|
session_type: Optional[str] = None,
|
|
104
104
|
expires_at: Optional[datetime] = None,
|
|
@@ -295,7 +295,7 @@ class AgentSessionClient:
|
|
|
295
295
|
raise InvalidLimitError(str(e)) from e
|
|
296
296
|
raise
|
|
297
297
|
|
|
298
|
-
async def list_limits(self, session_id: str) ->
|
|
298
|
+
async def list_limits(self, session_id: str) -> List[AgentSessionLimit]:
|
|
299
299
|
"""Get all limits for a session."""
|
|
300
300
|
try:
|
|
301
301
|
async with self._http:
|
|
@@ -334,7 +334,7 @@ class AgentSessionClient:
|
|
|
334
334
|
status: Optional[str] = None,
|
|
335
335
|
limit: int = 100,
|
|
336
336
|
offset: int = 0,
|
|
337
|
-
) ->
|
|
337
|
+
) -> List[AgentSession]:
|
|
338
338
|
"""List sessions for the authenticated organization."""
|
|
339
339
|
params: dict[str, Any] = {"limit": limit, "offset": offset}
|
|
340
340
|
if status:
|
|
@@ -353,7 +353,7 @@ class AgentSessionClient:
|
|
|
353
353
|
metric_type: Optional[str] = None,
|
|
354
354
|
limit: int = 100,
|
|
355
355
|
offset: int = 0,
|
|
356
|
-
) ->
|
|
356
|
+
) -> List[SessionUsageRecord]:
|
|
357
357
|
"""Get usage records for a session."""
|
|
358
358
|
params: dict[str, Any] = {"limit": limit, "offset": offset}
|
|
359
359
|
if metric_type:
|
|
@@ -381,4 +381,3 @@ class AgentSessionClient:
|
|
|
381
381
|
if e.status == 404:
|
|
382
382
|
raise SessionNotFoundError(session_id) from e
|
|
383
383
|
raise
|
|
384
|
-
|
|
@@ -7,6 +7,7 @@ validation, and discovery.
|
|
|
7
7
|
from synth_ai.cli.task_apps.commands import (
|
|
8
8
|
AppChoice,
|
|
9
9
|
TaskAppEntryType,
|
|
10
|
+
_markov_message_from_dict,
|
|
10
11
|
register,
|
|
11
12
|
serve_command,
|
|
12
13
|
task_app_group,
|
|
@@ -21,5 +22,5 @@ __all__ = [
|
|
|
21
22
|
"task_app_group",
|
|
22
23
|
"serve_command",
|
|
23
24
|
"register",
|
|
25
|
+
"_markov_message_from_dict",
|
|
24
26
|
]
|
|
25
|
-
|
|
@@ -209,7 +209,9 @@ def _parse_datetime_for_trace(value: Any) -> datetime | None:
|
|
|
209
209
|
def _time_record_from_dict(payload: dict[str, Any] | None) -> TimeRecord:
|
|
210
210
|
payload = payload or {}
|
|
211
211
|
event_time = payload.get("event_time")
|
|
212
|
-
if
|
|
212
|
+
if event_time is None:
|
|
213
|
+
event_time = float(time.time())
|
|
214
|
+
elif not isinstance(event_time, int | float):
|
|
213
215
|
try:
|
|
214
216
|
event_time = float(event_time)
|
|
215
217
|
except Exception:
|
|
@@ -924,7 +926,7 @@ def _build_modal_config_from_ast(modal_call: ast.Call) -> ModalDeploymentConfigT
|
|
|
924
926
|
if isinstance(value_node, ast.List | ast.Tuple):
|
|
925
927
|
for elt in value_node.elts:
|
|
926
928
|
if isinstance(elt, ast.Constant):
|
|
927
|
-
packages.append(elt.value)
|
|
929
|
+
packages.append(str(elt.value))
|
|
928
930
|
kwargs[kw.arg] = tuple(packages)
|
|
929
931
|
elif kw.arg == "extra_local_dirs" and isinstance(kw.value, ast.List | ast.Tuple):
|
|
930
932
|
# Handle extra_local_dirs list/tuple of tuples
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
"""Backwards-compatible Turso CLI entry point.
|
|
2
|
+
|
|
3
|
+
This module re-exports the infra.turso helpers so existing imports
|
|
4
|
+
(`synth_ai.cli.turso`) continue to work for tests and downstream users.
|
|
5
|
+
It also proxies infra functions so monkeypatching works in tests.
|
|
6
|
+
"""
|
|
7
|
+
|
|
8
|
+
from __future__ import annotations
|
|
9
|
+
|
|
10
|
+
import synth_ai.cli.infra.turso as _infra_turso
|
|
11
|
+
from synth_ai.cli.infra.turso import turso # noqa: F401
|
|
12
|
+
from synth_ai.cli.root import SQLD_VERSION, find_sqld_binary, install_sqld # noqa: F401
|
|
13
|
+
|
|
14
|
+
_get_sqld_version_inner = _infra_turso._get_sqld_version
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
def _get_sqld_version(binary: str) -> str | None: # noqa: F401
|
|
18
|
+
"""Delegates to the original infra implementation (monkeypatchable)."""
|
|
19
|
+
return _get_sqld_version_inner(binary)
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
def _proxy_get_sqld_version(binary: str) -> str | None:
|
|
23
|
+
# Dynamic lookup so monkeypatching synth_ai.cli.turso._get_sqld_version is honored
|
|
24
|
+
import synth_ai.cli.turso as mod
|
|
25
|
+
|
|
26
|
+
return mod._get_sqld_version(binary)
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
def _proxy_find_sqld_binary() -> str | None:
|
|
30
|
+
import synth_ai.cli.turso as mod
|
|
31
|
+
|
|
32
|
+
return mod.find_sqld_binary()
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
def _proxy_install_sqld():
|
|
36
|
+
import synth_ai.cli.turso as mod
|
|
37
|
+
|
|
38
|
+
return mod.install_sqld()
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
# Point infra at proxies so tests that monkeypatch this module influence the CLI command.
|
|
42
|
+
_infra_turso._get_sqld_version = _proxy_get_sqld_version # type: ignore[assignment]
|
|
43
|
+
_infra_turso.find_sqld_binary = _proxy_find_sqld_binary # type: ignore[assignment]
|
|
44
|
+
_infra_turso.install_sqld = _proxy_install_sqld # type: ignore[assignment]
|
|
45
|
+
|
|
46
|
+
__all__ = [
|
|
47
|
+
"turso",
|
|
48
|
+
"_get_sqld_version",
|
|
49
|
+
"find_sqld_binary",
|
|
50
|
+
"install_sqld",
|
|
51
|
+
"SQLD_VERSION",
|
|
52
|
+
]
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
from __future__ import annotations
|
|
2
2
|
|
|
3
3
|
import json
|
|
4
|
+
import os
|
|
4
5
|
import sqlite3
|
|
5
6
|
from collections.abc import Sequence
|
|
6
7
|
from dataclasses import dataclass
|
|
@@ -9,7 +10,7 @@ from typing import Any
|
|
|
9
10
|
Row = sqlite3.Row
|
|
10
11
|
|
|
11
12
|
|
|
12
|
-
def connect(db_path: str | bytes |
|
|
13
|
+
def connect(db_path: str | bytes | os.PathLike[str] | os.PathLike[bytes]) -> sqlite3.Connection:
|
|
13
14
|
conn = sqlite3.connect(db_path)
|
|
14
15
|
conn.row_factory = sqlite3.Row
|
|
15
16
|
return conn
|
|
@@ -314,4 +315,3 @@ __all__ = [
|
|
|
314
315
|
"load_session_trace",
|
|
315
316
|
]
|
|
316
317
|
|
|
317
|
-
|
|
@@ -4,6 +4,7 @@ import logging
|
|
|
4
4
|
import os
|
|
5
5
|
import pathlib
|
|
6
6
|
import shutil
|
|
7
|
+
import socket
|
|
7
8
|
import subprocess
|
|
8
9
|
import sys
|
|
9
10
|
import time
|
|
@@ -124,6 +125,15 @@ class SqldDaemon:
|
|
|
124
125
|
if self.process and self.process.poll() is None:
|
|
125
126
|
return self.process
|
|
126
127
|
|
|
128
|
+
# Avoid port conflicts by selecting free ports when needed
|
|
129
|
+
if not self._port_available(self.hrana_port):
|
|
130
|
+
self.hrana_port = self._find_free_port()
|
|
131
|
+
if not self._port_available(self.http_port) or self.http_port == self.hrana_port:
|
|
132
|
+
self.http_port = self._find_free_port()
|
|
133
|
+
# Ensure distinct ports
|
|
134
|
+
if self.http_port == self.hrana_port:
|
|
135
|
+
self.http_port = self._find_free_port()
|
|
136
|
+
|
|
127
137
|
db_file = pathlib.Path(self.db_path).resolve()
|
|
128
138
|
db_file.parent.mkdir(parents=True, exist_ok=True)
|
|
129
139
|
|
|
@@ -174,6 +184,22 @@ class SqldDaemon:
|
|
|
174
184
|
|
|
175
185
|
raise TimeoutError(f"sqld daemon did not become ready within {timeout} seconds")
|
|
176
186
|
|
|
187
|
+
@staticmethod
|
|
188
|
+
def _port_available(port: int) -> bool:
|
|
189
|
+
with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
|
|
190
|
+
s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
|
|
191
|
+
try:
|
|
192
|
+
s.bind(("127.0.0.1", port))
|
|
193
|
+
return True
|
|
194
|
+
except OSError:
|
|
195
|
+
return False
|
|
196
|
+
|
|
197
|
+
@staticmethod
|
|
198
|
+
def _find_free_port() -> int:
|
|
199
|
+
with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
|
|
200
|
+
s.bind(("127.0.0.1", 0))
|
|
201
|
+
return s.getsockname()[1]
|
|
202
|
+
|
|
177
203
|
def stop(self, timeout: float = 5.0):
|
|
178
204
|
"""Stop the sqld daemon gracefully."""
|
|
179
205
|
if not self.process:
|