freesolo-flash-dev 1.2.53__tar.gz → 1.2.58__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.
- {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.58}/PKG-INFO +1 -1
- {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.58}/flash/core/spec.py +4 -23
- freesolo_flash_dev-1.2.58/flash/core/spec_persistence.py +123 -0
- {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.58}/flash/runner/__init__.py +2 -13
- {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.58}/flash/runner/costs.py +2 -44
- {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.58}/flash/runner/preparation.py +8 -153
- {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.58}/flash/runner/status.py +4 -35
- {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.58}/flash/runner/submit.py +1 -19
- {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.58}/flash/schema/__init__.py +2 -6
- {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.58}/flash/serve/urls.py +1 -2
- {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.58}/flash/server/platform/runtime.py +3 -34
- {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.58}/pyproject.toml +2 -2
- {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.58}/tests/test_runmgmt.py +0 -65
- {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.58}/tests/test_server_api.py +1 -7
- {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.58}/tests/test_server_envs_coverage.py +0 -1
- {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.58}/tests/test_spec_and_validation.py +1 -465
- {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.58}/tests/test_spec_contract_bytes.py +0 -64
- {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.58}/tests/test_warmstart_cross_repo.py +3 -6
- {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.58}/uv.lock +1 -1
- freesolo_flash_dev-1.2.53/flash/core/spec_persistence.py +0 -227
- {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.58}/.dockerignore +0 -0
- {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.58}/.env.example +0 -0
- {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.58}/.github/CODEOWNERS +0 -0
- {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.58}/.github/ISSUE_TEMPLATE/bug_report.yml +0 -0
- {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.58}/.github/ISSUE_TEMPLATE/config.yml +0 -0
- {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.58}/.github/ISSUE_TEMPLATE/feature_request.yml +0 -0
- {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.58}/.github/PULL_REQUEST_TEMPLATE.md +0 -0
- {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.58}/.github/dependabot.yml +0 -0
- {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.58}/.github/workflows/auto-rebake.yml +0 -0
- {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.58}/.github/workflows/bake-kernel-cache.yml +0 -0
- {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.58}/.github/workflows/ci.yml +0 -0
- {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.58}/.github/workflows/main-source-guard.yml +0 -0
- {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.58}/.github/workflows/notify-tests-repo.yml +0 -0
- {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.58}/.github/workflows/publish-dev.yml +0 -0
- {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.58}/.github/workflows/publish-image.yml +0 -0
- {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.58}/.github/workflows/publish.yml +0 -0
- {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.58}/.github/workflows/version-parity.yml +0 -0
- {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.58}/.github/workflows/worker-image.yml +0 -0
- {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.58}/.gitignore +0 -0
- {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.58}/CHANGELOG.md +0 -0
- {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.58}/CODE_OF_CONDUCT.md +0 -0
- {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.58}/CONTRIBUTING.md +0 -0
- {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.58}/Dockerfile +0 -0
- {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.58}/Dockerfile.worker +0 -0
- {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.58}/LICENSE +0 -0
- {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.58}/NOTICE +0 -0
- {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.58}/README.md +0 -0
- {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.58}/SECURITY.md +0 -0
- {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.58}/SELF_HOSTING.md +0 -0
- {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.58}/build/kernel_cache/.gitignore +0 -0
- {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.58}/build/kernel_cache/.keep +0 -0
- {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.58}/deploy/infisical/README.md +0 -0
- {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.58}/deploy/infisical/entrypoint.sh +0 -0
- {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.58}/docker/Dockerfile.kernelcache +0 -0
- {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.58}/docker/Dockerfile.kernelcache.relayer +0 -0
- {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.58}/docker/bake_kernel_cache.py +0 -0
- {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.58}/docker/bake_pod_entry.py +0 -0
- {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.58}/docker/extract_cudart_fix.py +0 -0
- {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.58}/docker/kernel_fingerprint.py +0 -0
- {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.58}/docker/make_rp_handler.py +0 -0
- {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.58}/flash/__init__.py +0 -0
- {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.58}/flash/_internal/__init__.py +0 -0
- {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.58}/flash/_internal/channel.py +0 -0
- {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.58}/flash/_internal/diagnostics.py +0 -0
- {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.58}/flash/_internal/fileio.py +0 -0
- {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.58}/flash/_internal/logging.py +0 -0
- {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.58}/flash/_internal/paths.py +0 -0
- {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.58}/flash/adapters/__init__.py +0 -0
- {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.58}/flash/adapters/artifacts.py +0 -0
- {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.58}/flash/adapters/fused_experts.py +0 -0
- {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.58}/flash/adapters/lora_rank.py +0 -0
- {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.58}/flash/cli/__init__.py +0 -0
- {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.58}/flash/cli/__main__.py +0 -0
- {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.58}/flash/cli/commands/__init__.py +0 -0
- {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.58}/flash/cli/commands/deploy.py +0 -0
- {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.58}/flash/cli/commands/env/__init__.py +0 -0
- {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.58}/flash/cli/commands/env/episode.py +0 -0
- {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.58}/flash/cli/commands/env/eval.py +0 -0
- {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.58}/flash/cli/commands/env/eval_args.py +0 -0
- {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.58}/flash/cli/commands/env/imports.py +0 -0
- {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.58}/flash/cli/commands/env/list.py +0 -0
- {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.58}/flash/cli/commands/env/push.py +0 -0
- {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.58}/flash/cli/commands/env/retained.py +0 -0
- {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.58}/flash/cli/commands/env/setup.py +0 -0
- {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.58}/flash/cli/commands/env/test.py +0 -0
- {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.58}/flash/cli/commands/env/test_evaluations.py +0 -0
- {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.58}/flash/cli/commands/env/test_params.py +0 -0
- {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.58}/flash/cli/commands/env/test_warnings.py +0 -0
- {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.58}/flash/cli/commands/prompt_budget.py +0 -0
- {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.58}/flash/cli/commands/traces.py +0 -0
- {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.58}/flash/cli/commands/train_cost.py +0 -0
- {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.58}/flash/cli/scaffold/TRAINING.md +0 -0
- {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.58}/flash/cli/scaffold/__init__.py +0 -0
- {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.58}/flash/cli/ui/__init__.py +0 -0
- {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.58}/flash/cli/ui/cost.py +0 -0
- {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.58}/flash/cli/ui/env_panels.py +0 -0
- {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.58}/flash/cli/ui/heartbeat.py +0 -0
- {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.58}/flash/cli/ui/render.py +0 -0
- {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.58}/flash/cli/ui/tables.py +0 -0
- {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.58}/flash/cli/ui/tty.py +0 -0
- {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.58}/flash/client/__init__.py +0 -0
- {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.58}/flash/client/config.py +0 -0
- {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.58}/flash/client/freesolo_api.py +0 -0
- {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.58}/flash/client/http.py +0 -0
- {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.58}/flash/client/runtime_secrets.py +0 -0
- {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.58}/flash/client/shapes.py +0 -0
- {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.58}/flash/client/specs.py +0 -0
- {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.58}/flash/client/streaming.py +0 -0
- {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.58}/flash/content/__init__.py +0 -0
- {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.58}/flash/content/multimodal.py +0 -0
- {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.58}/flash/content/structured_outputs.py +0 -0
- {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.58}/flash/content/thinking.py +0 -0
- {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.58}/flash/core/__init__.py +0 -0
- {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.58}/flash/core/catalog.py +0 -0
- {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.58}/flash/cost/__init__.py +0 -0
- {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.58}/flash/cost/analytical.py +0 -0
- {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.58}/flash/cost/facts.py +0 -0
- {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.58}/flash/cost/spec.py +0 -0
- {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.58}/flash/cost/types.py +0 -0
- {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.58}/flash/engine/__init__.py +0 -0
- {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.58}/flash/engine/plan/__init__.py +0 -0
- {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.58}/flash/engine/plan/kv_sizing.py +0 -0
- {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.58}/flash/engine/plan/model_config_probe.py +0 -0
- {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.58}/flash/engine/plan/prompt_budget.py +0 -0
- {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.58}/flash/engine/plan/recipe.py +0 -0
- {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.58}/flash/engine/plan/steps.py +0 -0
- {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.58}/flash/engine/plan/vram.py +0 -0
- {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.58}/flash/engine/profiling/__init__.py +0 -0
- {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.58}/flash/engine/profiling/dataset_profile.py +0 -0
- {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.58}/flash/engine/profiling/reasoning_render.py +0 -0
- {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.58}/flash/engine/profiling/sft_workload.py +0 -0
- {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.58}/flash/engine/profiling/tokenizer.py +0 -0
- {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.58}/flash/engine/profiling/workload_profile.py +0 -0
- {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.58}/flash/engine/result/__init__.py +0 -0
- {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.58}/flash/engine/result/accounting.py +0 -0
- {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.58}/flash/engine/result/rollout_samples.py +0 -0
- {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.58}/flash/engine/worker/__init__.py +0 -0
- {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.58}/flash/engine/worker/__main__.py +0 -0
- {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.58}/flash/engine/worker/backend_common.py +0 -0
- {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.58}/flash/engine/worker/entry/__init__.py +0 -0
- {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.58}/flash/engine/worker/entry/opd.py +0 -0
- {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.58}/flash/engine/worker/entry/rl.py +0 -0
- {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.58}/flash/engine/worker/entry/sft.py +0 -0
- {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.58}/flash/engine/worker/io/__init__.py +0 -0
- {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.58}/flash/engine/worker/io/heartbeat.py +0 -0
- {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.58}/flash/engine/worker/io/hf.py +0 -0
- {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.58}/flash/engine/worker/io/prefetch.py +0 -0
- {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.58}/flash/engine/worker/io/wandb_log.py +0 -0
- {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.58}/flash/engine/worker/model/__init__.py +0 -0
- {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.58}/flash/engine/worker/model/adapter.py +0 -0
- {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.58}/flash/engine/worker/model/chatml_mask.py +0 -0
- {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.58}/flash/engine/worker/model/decoding.py +0 -0
- {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.58}/flash/engine/worker/model/lora.py +0 -0
- {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.58}/flash/engine/worker/model/packing.py +0 -0
- {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.58}/flash/engine/worker/opd_train.py +0 -0
- {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.58}/flash/engine/worker/opd_train_runner.py +0 -0
- {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.58}/flash/engine/worker/perf/__init__.py +0 -0
- {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.58}/flash/engine/worker/perf/diagnostics.py +0 -0
- {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.58}/flash/engine/worker/perf/lifecycle.py +0 -0
- {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.58}/flash/engine/worker/perf/liger.py +0 -0
- {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.58}/flash/engine/worker/perf/memory.py +0 -0
- {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.58}/flash/engine/worker/rl_train.py +0 -0
- {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.58}/flash/engine/worker/rl_train_runner.py +0 -0
- {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.58}/flash/engine/worker/runtime/__init__.py +0 -0
- {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.58}/flash/engine/worker/runtime/kernel_warmup.py +0 -0
- {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.58}/flash/engine/worker/runtime/pkg_proxy.py +0 -0
- {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.58}/flash/engine/worker/runtime/rng.py +0 -0
- {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.58}/flash/engine/worker/score_batcher.py +0 -0
- {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.58}/flash/engine/worker/sft_train.py +0 -0
- {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.58}/flash/engine/worker/sft_train_runner.py +0 -0
- {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.58}/flash/engine/worker/teacher/__init__.py +0 -0
- {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.58}/flash/engine/worker/teacher/client.py +0 -0
- {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.58}/flash/engine/worker/teacher/encoding.py +0 -0
- {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.58}/flash/engine/worker/teacher/tokenizer_align.py +0 -0
- {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.58}/flash/engine/worker/train/__init__.py +0 -0
- {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.58}/flash/engine/worker/train/core/__init__.py +0 -0
- {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.58}/flash/engine/worker/train/core/checkpoint_lifecycle.py +0 -0
- {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.58}/flash/engine/worker/train/core/child/__init__.py +0 -0
- {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.58}/flash/engine/worker/train/core/child/glue.py +0 -0
- {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.58}/flash/engine/worker/train/core/child/runtime.py +0 -0
- {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.58}/flash/engine/worker/train/core/step_timing.py +0 -0
- {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.58}/flash/engine/worker/train/finalize.py +0 -0
- {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.58}/flash/engine/worker/train/opd/__init__.py +0 -0
- {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.58}/flash/engine/worker/train/opd/batching.py +0 -0
- {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.58}/flash/engine/worker/train/opd/bridge.py +0 -0
- {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.58}/flash/engine/worker/train/opd/child/__init__.py +0 -0
- {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.58}/flash/engine/worker/train/opd/child/bridge.py +0 -0
- {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.58}/flash/engine/worker/train/opd/child/entry.py +0 -0
- {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.58}/flash/engine/worker/train/opd/child/multiturn.py +0 -0
- {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.58}/flash/engine/worker/train/opd/child/plugin.py +0 -0
- {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.58}/flash/engine/worker/train/opd/child/replay_guard.py +0 -0
- {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.58}/flash/engine/worker/train/opd/child/runtime.py +0 -0
- {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.58}/flash/engine/worker/train/opd/child/structured.py +0 -0
- {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.58}/flash/engine/worker/train/opd/failures.py +0 -0
- {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.58}/flash/engine/worker/train/opd/gkd.py +0 -0
- {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.58}/flash/engine/worker/train/opd/multiturn_validation.py +0 -0
- {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.58}/flash/engine/worker/train/opd/overrides.py +0 -0
- {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.58}/flash/engine/worker/train/opd/prompts.py +0 -0
- {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.58}/flash/engine/worker/train/opd/reporting.py +0 -0
- {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.58}/flash/engine/worker/train/opd/scoring.py +0 -0
- {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.58}/flash/engine/worker/train/opd/state.py +0 -0
- {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.58}/flash/engine/worker/train/opd/validation.py +0 -0
- {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.58}/flash/engine/worker/train/rl/__init__.py +0 -0
- {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.58}/flash/engine/worker/train/rl/checkpoints.py +0 -0
- {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.58}/flash/engine/worker/train/rl/child/__init__.py +0 -0
- {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.58}/flash/engine/worker/train/rl/child/entry.py +0 -0
- {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.58}/flash/engine/worker/train/rl/child/multiturn.py +0 -0
- {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.58}/flash/engine/worker/train/rl/child/patches.py +0 -0
- {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.58}/flash/engine/worker/train/rl/child/plugin.py +0 -0
- {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.58}/flash/engine/worker/train/rl/config.py +0 -0
- {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.58}/flash/engine/worker/train/rl/inputs.py +0 -0
- {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.58}/flash/engine/worker/train/rl/multi_turn.py +0 -0
- {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.58}/flash/engine/worker/train/rl/reward_module.py +0 -0
- {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.58}/flash/engine/worker/train/rl/scoring.py +0 -0
- {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.58}/flash/engine/worker/train/rl/single_turn.py +0 -0
- {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.58}/flash/engine/worker/train/rl/verl_config.py +0 -0
- {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.58}/flash/engine/worker/train/sft/__init__.py +0 -0
- {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.58}/flash/engine/worker/train/sft/checkpoints.py +0 -0
- {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.58}/flash/engine/worker/train/sft/child/entry.py +0 -0
- {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.58}/flash/engine/worker/train/sft/child/plugin.py +0 -0
- {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.58}/flash/engine/worker/train/sft/config.py +0 -0
- {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.58}/flash/engine/worker/verl/__init__.py +0 -0
- {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.58}/flash/engine/worker/verl/capabilities.py +0 -0
- {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.58}/flash/engine/worker/verl/checkpoints.py +0 -0
- {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.58}/flash/engine/worker/verl/child_io.py +0 -0
- {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.58}/flash/engine/worker/verl/diagnostics.py +0 -0
- {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.58}/flash/engine/worker/verl/parallelism.py +0 -0
- {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.58}/flash/engine/worker/verl/parent_work.py +0 -0
- {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.58}/flash/engine/worker_entrypoint.py +0 -0
- {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.58}/flash/envs/__init__.py +0 -0
- {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.58}/flash/envs/adapter.py +0 -0
- {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.58}/flash/envs/base.py +0 -0
- {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.58}/flash/envs/cache_security.py +0 -0
- {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.58}/flash/envs/dataset_selection.py +0 -0
- {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.58}/flash/envs/evaluations.py +0 -0
- {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.58}/flash/envs/identity.py +0 -0
- {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.58}/flash/envs/loader.py +0 -0
- {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.58}/flash/envs/namespace_listing.py +0 -0
- {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.58}/flash/envs/package/__init__.py +0 -0
- {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.58}/flash/envs/package/limits.py +0 -0
- {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.58}/flash/envs/package/unpack.py +0 -0
- {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.58}/flash/envs/pull.py +0 -0
- {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.58}/flash/providers/__init__.py +0 -0
- {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.58}/flash/providers/_lifecycle/__init__.py +0 -0
- {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.58}/flash/providers/_lifecycle/auth.py +0 -0
- {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.58}/flash/providers/_lifecycle/bootstrap.py +0 -0
- {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.58}/flash/providers/_lifecycle/bootstrap_console.py +0 -0
- {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.58}/flash/providers/_lifecycle/bootstrap_pip.py +0 -0
- {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.58}/flash/providers/_lifecycle/bootstrap_secrets.py +0 -0
- {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.58}/flash/providers/_lifecycle/deadline.py +0 -0
- {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.58}/flash/providers/_lifecycle/host/__init__.py +0 -0
- {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.58}/flash/providers/_lifecycle/host/deadline_sleep.py +0 -0
- {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.58}/flash/providers/_lifecycle/host/failmark.py +0 -0
- {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.58}/flash/providers/_lifecycle/host/hostlog.py +0 -0
- {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.58}/flash/providers/_lifecycle/http.py +0 -0
- {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.58}/flash/providers/_lifecycle/instance.py +0 -0
- {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.58}/flash/providers/_lifecycle/poll.py +0 -0
- {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.58}/flash/providers/_lifecycle/poll_instance.py +0 -0
- {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.58}/flash/providers/_lifecycle/provider.py +0 -0
- {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.58}/flash/providers/_lifecycle/terminal_artifacts.py +0 -0
- {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.58}/flash/providers/_lifecycle/worker.py +0 -0
- {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.58}/flash/providers/allocator.py +0 -0
- {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.58}/flash/providers/artifacts/__init__.py +0 -0
- {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.58}/flash/providers/artifacts/hf.py +0 -0
- {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.58}/flash/providers/artifacts/preload_runpod.py +0 -0
- {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.58}/flash/providers/artifacts/weight_cache.py +0 -0
- {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.58}/flash/providers/base.py +0 -0
- {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.58}/flash/providers/fit_errors.py +0 -0
- {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.58}/flash/providers/lambda_/__init__.py +0 -0
- {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.58}/flash/providers/lambda_/api.py +0 -0
- {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.58}/flash/providers/lambda_/auth.py +0 -0
- {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.58}/flash/providers/lambda_/gpus.py +0 -0
- {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.58}/flash/providers/lambda_/jobs/__init__.py +0 -0
- {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.58}/flash/providers/lambda_/jobs/builders.py +0 -0
- {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.58}/flash/providers/lambda_/jobs/reap.py +0 -0
- {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.58}/flash/providers/lambda_/preflight.py +0 -0
- {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.58}/flash/providers/lambda_/pricing.py +0 -0
- {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.58}/flash/providers/preflight.py +0 -0
- {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.58}/flash/providers/realized.py +0 -0
- {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.58}/flash/providers/runpod/__init__.py +0 -0
- {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.58}/flash/providers/runpod/api.py +0 -0
- {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.58}/flash/providers/runpod/auth.py +0 -0
- {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.58}/flash/providers/runpod/cost.py +0 -0
- {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.58}/flash/providers/runpod/gpus.py +0 -0
- {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.58}/flash/providers/runpod/job_execution.py +0 -0
- {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.58}/flash/providers/runpod/jobs.py +0 -0
- {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.58}/flash/providers/runpod/preflight.py +0 -0
- {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.58}/flash/providers/runpod/pricing.py +0 -0
- {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.58}/flash/providers/runpod/resources.py +0 -0
- {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.58}/flash/providers/runpod/serverless/__init__.py +0 -0
- {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.58}/flash/providers/runpod/serverless/endpoints.py +0 -0
- {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.58}/flash/providers/sharding.py +0 -0
- {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.58}/flash/providers/vast/__init__.py +0 -0
- {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.58}/flash/providers/vast/api.py +0 -0
- {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.58}/flash/providers/vast/auth.py +0 -0
- {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.58}/flash/providers/vast/jobs/__init__.py +0 -0
- {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.58}/flash/providers/vast/jobs/builders.py +0 -0
- {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.58}/flash/providers/vast/preflight.py +0 -0
- {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.58}/flash/providers/vast/pricing.py +0 -0
- {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.58}/flash/py.typed +0 -0
- {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.58}/flash/runner/artifacts.py +0 -0
- {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.58}/flash/runner/attempts.py +0 -0
- {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.58}/flash/runner/deadlines.py +0 -0
- {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.58}/flash/runner/reconciliation.py +0 -0
- {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.58}/flash/runner/results/__init__.py +0 -0
- {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.58}/flash/runner/results/checkpoints.py +0 -0
- {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.58}/flash/runner/results/verified_revisions.py +0 -0
- {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.58}/flash/runner/supervise/__init__.py +0 -0
- {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.58}/flash/runner/supervise/attach.py +0 -0
- {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.58}/flash/runner/supervise/deploy.py +0 -0
- {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.58}/flash/runner/supervise/lifecycle.py +0 -0
- {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.58}/flash/runner/supervise/recovery.py +0 -0
- {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.58}/flash/runner/supervise/retry_decision.py +0 -0
- {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.58}/flash/runner/supervise/seed_submission.py +0 -0
- {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.58}/flash/runner/supervise/transitions.py +0 -0
- {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.58}/flash/runner/weight_cache.py +0 -0
- {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.58}/flash/runtime_capsule/__init__.py +0 -0
- {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.58}/flash/runtime_capsule/build.py +0 -0
- {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.58}/flash/runtime_capsule/manifest.py +0 -0
- {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.58}/flash/runtime_capsule/profiles.py +0 -0
- {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.58}/flash/schema/fields.py +0 -0
- {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.58}/flash/serve/__init__.py +0 -0
- {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.58}/flash/serve/adapter_check.py +0 -0
- {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.58}/flash/serve/deploy.py +0 -0
- {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.58}/flash/serve/errors.py +0 -0
- {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.58}/flash/serve/export.py +0 -0
- {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.58}/flash/serve/preflight.py +0 -0
- {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.58}/flash/serve/responses.py +0 -0
- {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.58}/flash/serve/streaming.py +0 -0
- {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.58}/flash/serve/thinking.py +0 -0
- {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.58}/flash/server/__init__.py +0 -0
- {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.58}/flash/server/__main__.py +0 -0
- {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.58}/flash/server/app.py +0 -0
- {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.58}/flash/server/billing/__init__.py +0 -0
- {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.58}/flash/server/billing/charges.py +0 -0
- {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.58}/flash/server/billing/retry.py +0 -0
- {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.58}/flash/server/domain/__init__.py +0 -0
- {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.58}/flash/server/domain/checkpoints.py +0 -0
- {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.58}/flash/server/domain/environment_registry.py +0 -0
- {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.58}/flash/server/domain/envs.py +0 -0
- {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.58}/flash/server/domain/projects.py +0 -0
- {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.58}/flash/server/domain/reconcile.py +0 -0
- {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.58}/flash/server/domain/repo_cleanup.py +0 -0
- {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.58}/flash/server/domain/run_registry.py +0 -0
- {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.58}/flash/server/domain/teacher_broker.py +0 -0
- {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.58}/flash/server/domain/teacher_errors.py +0 -0
- {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.58}/flash/server/domain/teacher_requests.py +0 -0
- {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.58}/flash/server/platform/__init__.py +0 -0
- {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.58}/flash/server/platform/auth.py +0 -0
- {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.58}/flash/server/platform/db.py +0 -0
- {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.58}/flash/server/platform/deps.py +0 -0
- {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.58}/flash/server/platform/internal_client.py +0 -0
- {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.58}/flash/server/platform/locks.py +0 -0
- {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.58}/flash/server/routes/__init__.py +0 -0
- {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.58}/flash/server/routes/envs.py +0 -0
- {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.58}/flash/server/routes/meta.py +0 -0
- {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.58}/flash/server/routes/runs.py +0 -0
- {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.58}/flash/server/routes/serving.py +0 -0
- {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.58}/flash/server/routes/serving_completion.py +0 -0
- {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.58}/flash/server/routes/serving_revisions.py +0 -0
- {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.58}/flash/server/routes/serving_smoke.py +0 -0
- {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.58}/flash/server/routes/teacher.py +0 -0
- {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.58}/flash/teacher/__init__.py +0 -0
- {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.58}/flash/teacher/limits.py +0 -0
- {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.58}/flash/teacher/retry_contract.py +0 -0
- {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.58}/scripts/build_dev_dist.py +0 -0
- {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.58}/scripts/check_file_size.py +0 -0
- {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.58}/scripts/check_function_size.py +0 -0
- {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.58}/scripts/check_verl_pin_exists.py +0 -0
- {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.58}/scripts/scrub_history.sh +0 -0
- {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.58}/tests/__init__.py +0 -0
- {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.58}/tests/_helpers/__init__.py +0 -0
- {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.58}/tests/_helpers/profile.py +0 -0
- {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.58}/tests/_helpers/runner.py +0 -0
- {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.58}/tests/_helpers/specs.py +0 -0
- {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.58}/tests/_helpers/teacher.py +0 -0
- {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.58}/tests/_helpers/vast.py +0 -0
- {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.58}/tests/conftest.py +0 -0
- {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.58}/tests/fixtures/math_eval.jsonl +0 -0
- {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.58}/tests/fixtures/math_train.jsonl +0 -0
- {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.58}/tests/live/__init__.py +0 -0
- {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.58}/tests/live/conftest.py +0 -0
- {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.58}/tests/live/test_lambda_live.py +0 -0
- {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.58}/tests/live/test_runpod_live.py +0 -0
- {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.58}/tests/live/test_sft_thinking_render_live.py +0 -0
- {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.58}/tests/live/test_vast_live.py +0 -0
- {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.58}/tests/test_accounting_coverage.py +0 -0
- {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.58}/tests/test_adapter_shard_completeness.py +0 -0
- {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.58}/tests/test_agent_flash_cli_contract.py +0 -0
- {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.58}/tests/test_algorithms.py +0 -0
- {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.58}/tests/test_allocator.py +0 -0
- {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.58}/tests/test_backend_common.py +0 -0
- {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.58}/tests/test_backend_jobspec_contract.py +0 -0
- {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.58}/tests/test_bake_kernel_cache.py +0 -0
- {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.58}/tests/test_base_model_provenance.py +0 -0
- {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.58}/tests/test_billing_retry.py +0 -0
- {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.58}/tests/test_build_context_contract.py +0 -0
- {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.58}/tests/test_cancel_remote.py +0 -0
- {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.58}/tests/test_catalog_consistency.py +0 -0
- {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.58}/tests/test_catalog_only_models.py +0 -0
- {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.58}/tests/test_charge_pricing.py +0 -0
- {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.58}/tests/test_checkpoint_lifecycle.py +0 -0
- {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.58}/tests/test_checkpoints.py +0 -0
- {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.58}/tests/test_cli_commands.py +0 -0
- {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.58}/tests/test_cli_commands_coverage.py +0 -0
- {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.58}/tests/test_cli_credential_shadowing.py +0 -0
- {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.58}/tests/test_cli_errors.py +0 -0
- {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.58}/tests/test_cli_estimate.py +0 -0
- {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.58}/tests/test_cli_gpus_flag.py +0 -0
- {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.58}/tests/test_cli_help.py +0 -0
- {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.58}/tests/test_cli_main_coverage.py +0 -0
- {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.58}/tests/test_cli_managed.py +0 -0
- {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.58}/tests/test_cli_render_coverage.py +0 -0
- {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.58}/tests/test_cli_render_theme.py +0 -0
- {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.58}/tests/test_cli_traces.py +0 -0
- {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.58}/tests/test_cli_wandb_warning.py +0 -0
- {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.58}/tests/test_client.py +0 -0
- {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.58}/tests/test_client_import_purity.py +0 -0
- {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.58}/tests/test_client_server_integration.py +0 -0
- {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.58}/tests/test_client_stream_reads.py +0 -0
- {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.58}/tests/test_config_env_vars.py +0 -0
- {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.58}/tests/test_config_overrides.py +0 -0
- {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.58}/tests/test_console_upload.py +0 -0
- {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.58}/tests/test_controlled_experiment_repairs.py +0 -0
- {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.58}/tests/test_cost_analytical.py +0 -0
- {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.58}/tests/test_cost_equation.py +0 -0
- {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.58}/tests/test_cost_estimate.py +0 -0
- {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.58}/tests/test_cost_hardware.py +0 -0
- {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.58}/tests/test_cost_models.py +0 -0
- {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.58}/tests/test_dataset_profile.py +0 -0
- {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.58}/tests/test_deploy_alias_move_warning.py +0 -0
- {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.58}/tests/test_deploy_latency.py +0 -0
- {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.58}/tests/test_dev_channel.py +0 -0
- {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.58}/tests/test_disk_gb.py +0 -0
- {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.58}/tests/test_endpoint_name.py +0 -0
- {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.58}/tests/test_env_cache_evict.py +0 -0
- {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.58}/tests/test_env_delete.py +0 -0
- {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.58}/tests/test_env_download.py +0 -0
- {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.58}/tests/test_env_download_api.py +0 -0
- {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.58}/tests/test_env_evaluations.py +0 -0
- {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.58}/tests/test_env_list_api.py +0 -0
- {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.58}/tests/test_env_list_cli.py +0 -0
- {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.58}/tests/test_env_list_hub.py +0 -0
- {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.58}/tests/test_env_no_install.py +0 -0
- {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.58}/tests/test_env_publish.py +0 -0
- {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.58}/tests/test_env_pull.py +0 -0
- {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.58}/tests/test_env_pull_coverage.py +0 -0
- {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.58}/tests/test_env_pull_loader_coverage.py +0 -0
- {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.58}/tests/test_env_pull_managed_control_plane.py +0 -0
- {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.58}/tests/test_env_push.py +0 -0
- {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.58}/tests/test_env_rate_limit_resolve.py +0 -0
- {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.58}/tests/test_env_ref_pinning.py +0 -0
- {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.58}/tests/test_env_test.py +0 -0
- {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.58}/tests/test_envs_coverage.py +0 -0
- {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.58}/tests/test_export.py +0 -0
- {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.58}/tests/test_flash_mvp.py +0 -0
- {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.58}/tests/test_flash_worker.py +0 -0
- {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.58}/tests/test_flashinfer_cache_dirs.py +0 -0
- {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.58}/tests/test_freesolo_api_transport.py +0 -0
- {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.58}/tests/test_fused_expert_warmstart.py +0 -0
- {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.58}/tests/test_github_urlopen_retry.py +0 -0
- {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.58}/tests/test_gpu_type_single_field.py +0 -0
- {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.58}/tests/test_gpus.py +0 -0
- {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.58}/tests/test_grpo_params.py +0 -0
- {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.58}/tests/test_grpo_resident_sizing.py +0 -0
- {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.58}/tests/test_grpo_reward_batching.py +0 -0
- {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.58}/tests/test_health_liveness.py +0 -0
- {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.58}/tests/test_hf_retry.py +0 -0
- {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.58}/tests/test_idle_endpoint_reaper.py +0 -0
- {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.58}/tests/test_infisical_secrets.py +0 -0
- {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.58}/tests/test_instance_bootstrap_coverage.py +0 -0
- {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.58}/tests/test_internal_client.py +0 -0
- {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.58}/tests/test_jobs.py +0 -0
- {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.58}/tests/test_kernel_cache.py +0 -0
- {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.58}/tests/test_kernel_fingerprint.py +0 -0
- {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.58}/tests/test_kv_util.py +0 -0
- {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.58}/tests/test_lambda_api_coverage.py +0 -0
- {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.58}/tests/test_lambda_runner.py +0 -0
- {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.58}/tests/test_logging.py +0 -0
- {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.58}/tests/test_login_perms.py +0 -0
- {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.58}/tests/test_lora_rank_coverage.py +0 -0
- {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.58}/tests/test_lora_rank_preflight.py +0 -0
- {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.58}/tests/test_managed_config_fields.py +0 -0
- {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.58}/tests/test_managed_hf_repo.py +0 -0
- {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.58}/tests/test_metrics_schema_agent_contract.py +0 -0
- {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.58}/tests/test_mig_guard.py +0 -0
- {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.58}/tests/test_multi_gpu_gate.py +0 -0
- {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.58}/tests/test_multimodal_training.py +0 -0
- {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.58}/tests/test_named_reward_metrics.py +0 -0
- {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.58}/tests/test_oom_escalate_gpu.py +0 -0
- {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.58}/tests/test_opd.py +0 -0
- {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.58}/tests/test_opd_limits.py +0 -0
- {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.58}/tests/test_opd_multiturn_eos_boundary.py +0 -0
- {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.58}/tests/test_opd_multiturn_failure_exit.py +0 -0
- {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.58}/tests/test_opd_replay_guard.py +0 -0
- {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.58}/tests/test_opd_resume_safety.py +0 -0
- {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.58}/tests/test_opd_train.py +0 -0
- {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.58}/tests/test_orchestrator_flash.py +0 -0
- {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.58}/tests/test_packing.py +0 -0
- {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.58}/tests/test_packing_coverage.py +0 -0
- {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.58}/tests/test_parasail_teacher.py +0 -0
- {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.58}/tests/test_poll_helpers.py +0 -0
- {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.58}/tests/test_preflight.py +0 -0
- {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.58}/tests/test_projects.py +0 -0
- {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.58}/tests/test_prompt_budget.py +0 -0
- {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.58}/tests/test_provider_preflight_coverage.py +0 -0
- {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.58}/tests/test_provider_routing.py +0 -0
- {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.58}/tests/test_provider_teardown_robustness.py +0 -0
- {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.58}/tests/test_providers_symmetry.py +0 -0
- {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.58}/tests/test_realized_cost.py +0 -0
- {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.58}/tests/test_repo_cleanup.py +0 -0
- {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.58}/tests/test_resolve_params_b.py +0 -0
- {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.58}/tests/test_resume_on_retry.py +0 -0
- {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.58}/tests/test_rl_train.py +0 -0
- {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.58}/tests/test_rollout_samples.py +0 -0
- {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.58}/tests/test_runpod_api_delete.py +0 -0
- {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.58}/tests/test_runpod_key_fingerprint.py +0 -0
- {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.58}/tests/test_runpod_key_waterfall.py +0 -0
- {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.58}/tests/test_runtime_capsule.py +0 -0
- {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.58}/tests/test_serve.py +0 -0
- {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.58}/tests/test_serve_reasoning_content.py +0 -0
- {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.58}/tests/test_server_app_coverage.py +0 -0
- {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.58}/tests/test_server_auth_singleflight.py +0 -0
- {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.58}/tests/test_server_billing.py +0 -0
- {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.58}/tests/test_server_checkpoints_coverage.py +0 -0
- {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.58}/tests/test_server_db.py +0 -0
- {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.58}/tests/test_server_locks_coverage.py +0 -0
- {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.58}/tests/test_server_standalone.py +0 -0
- {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.58}/tests/test_serving_context_preflight.py +0 -0
- {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.58}/tests/test_serving_contract.py +0 -0
- {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.58}/tests/test_serving_schema_coverage.py +0 -0
- {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.58}/tests/test_sft_chunked_nll.py +0 -0
- {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.58}/tests/test_sft_example_selection.py +0 -0
- {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.58}/tests/test_sft_gc_off.py +0 -0
- {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.58}/tests/test_sft_max_context.py +0 -0
- {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.58}/tests/test_sft_startup_block.py +0 -0
- {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.58}/tests/test_sft_train.py +0 -0
- {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.58}/tests/test_sft_workload.py +0 -0
- {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.58}/tests/test_step_floor.py +0 -0
- {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.58}/tests/test_step_metrics.py +0 -0
- {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.58}/tests/test_step_timing.py +0 -0
- {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.58}/tests/test_structured_outputs.py +0 -0
- {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.58}/tests/test_teacher_broker.py +0 -0
- {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.58}/tests/test_teacher_encoding_contract.py +0 -0
- {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.58}/tests/test_terminal_artifacts.py +0 -0
- {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.58}/tests/test_thinking_config.py +0 -0
- {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.58}/tests/test_train_context_preflight.py +0 -0
- {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.58}/tests/test_training_controls.py +0 -0
- {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.58}/tests/test_type_comment_prose.py +0 -0
- {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.58}/tests/test_vast_api.py +0 -0
- {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.58}/tests/test_vast_api_coverage.py +0 -0
- {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.58}/tests/test_vast_offers.py +0 -0
- {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.58}/tests/test_vast_provider_coverage.py +0 -0
- {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.58}/tests/test_vast_runner.py +0 -0
- {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.58}/tests/test_verified_revisions.py +0 -0
- {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.58}/tests/test_verifiers.py +0 -0
- {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.58}/tests/test_verl_checkpoint_export.py +0 -0
- {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.58}/tests/test_verl_child_plugins.py +0 -0
- {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.58}/tests/test_verl_silence_watchdog.py +0 -0
- {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.58}/tests/test_version.py +0 -0
- {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.58}/tests/test_vl_warmstart_adapter_keys.py +0 -0
- {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.58}/tests/test_vram_architecture.py +0 -0
- {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.58}/tests/test_wandb_link.py +0 -0
- {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.58}/tests/test_wandb_naming.py +0 -0
- {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.58}/tests/test_warmstart_adapter_download.py +0 -0
- {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.58}/tests/test_warmstart_error_attribution.py +0 -0
- {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.58}/tests/test_weight_cache.py +0 -0
- {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.58}/tests/test_worker_dryrun.py +0 -0
- {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.58}/tests/test_worker_hardexit.py +0 -0
- {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.58}/tests/test_worker_image.py +0 -0
- {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.58}/tests/test_worker_init_heartbeat.py +0 -0
- {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.58}/tests/test_worker_stack.py +0 -0
- {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.58}/tests/test_worker_thinking.py +0 -0
- {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.58}/tests/test_workflow_contracts.py +0 -0
- {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.58}/tests/test_workload_profile.py +0 -0
- {freesolo_flash_dev-1.2.53 → freesolo_flash_dev-1.2.58}/tests/test_zero2_sharding_gate.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.5
|
|
2
2
|
Name: freesolo-flash-dev
|
|
3
|
-
Version: 1.2.
|
|
3
|
+
Version: 1.2.58
|
|
4
4
|
Summary: Flash — managed LoRA post-training (SFT/GRPO/OPD) for Freesolo environments, driven by the `flash` CLI
|
|
5
5
|
Project-URL: Homepage, https://github.com/freesolo-co/flash
|
|
6
6
|
Project-URL: Repository, https://github.com/freesolo-co/flash
|
|
@@ -27,19 +27,7 @@ from uuid import UUID
|
|
|
27
27
|
|
|
28
28
|
from flash._internal.diagnostics import SECRET_ENV_KEYS_ENV
|
|
29
29
|
from flash.core.catalog import DEFAULT_MODEL, normalize_algorithm
|
|
30
|
-
|
|
31
|
-
# `DROPPED_TOP_LEVEL_KEYS` keeps its historical private alias rather than being renamed at its 5 call
|
|
32
|
-
# sites: `flash.runner` re-exports it as a package attribute and `preparation.py` reads it back through
|
|
33
|
-
# `_runner()`, which is the seam the tests patch. Renaming it is a separate change from moving it, and
|
|
34
|
-
# doing both at once would put a live recovery path's patch points inside a refactor whose whole claim
|
|
35
|
-
# is that nothing behavioral moved.
|
|
36
|
-
from flash.core.spec_persistence import (
|
|
37
|
-
DROPPED_TOP_LEVEL_KEYS as _DROPPED_TOP_LEVEL_KEYS,
|
|
38
|
-
)
|
|
39
30
|
from flash.core.spec_persistence import (
|
|
40
|
-
REMOVED_PERSISTED_TRAIN_KEYS,
|
|
41
|
-
announce_dropped_keys,
|
|
42
|
-
migrated_optimizer_batch,
|
|
43
31
|
opt_float,
|
|
44
32
|
opt_int,
|
|
45
33
|
str_tuple,
|
|
@@ -654,10 +642,9 @@ class JobSpec:
|
|
|
654
642
|
if not isinstance(data, dict):
|
|
655
643
|
raise TypeError("job spec must be an object")
|
|
656
644
|
allowed_top_level = {item.name for item in fields(cls)}
|
|
657
|
-
unknown_top_level = sorted(set(data) - allowed_top_level
|
|
645
|
+
unknown_top_level = sorted(set(data) - allowed_top_level)
|
|
658
646
|
if unknown_top_level:
|
|
659
647
|
raise ValueError(f"job spec has unknown key(s): {', '.join(unknown_top_level)}")
|
|
660
|
-
announce_dropped_keys(data)
|
|
661
648
|
env = data.get("environment") or {}
|
|
662
649
|
# Reject stale payloads carrying a local `path`; worker only runs published env ids.
|
|
663
650
|
if isinstance(env, dict) and env.get("path"):
|
|
@@ -665,12 +652,7 @@ class JobSpec:
|
|
|
665
652
|
"local environment paths are no longer supported; the worker only runs "
|
|
666
653
|
"published Freesolo environment ids"
|
|
667
654
|
)
|
|
668
|
-
train = validated_section(
|
|
669
|
-
data,
|
|
670
|
-
"train",
|
|
671
|
-
{item.name for item in fields(TrainSpec)},
|
|
672
|
-
removed=REMOVED_PERSISTED_TRAIN_KEYS,
|
|
673
|
-
)
|
|
655
|
+
train = validated_section(data, "train", {item.name for item in fields(TrainSpec)})
|
|
674
656
|
gpu = validated_section(data, "gpu", {item.name for item in fields(GpuSpec)})
|
|
675
657
|
gpu_type, gpu_type_fallbacks = _parse_persisted_gpu_types(gpu)
|
|
676
658
|
provider, providers = validated_persisted_providers(gpu, gpu_type, gpu_type_fallbacks)
|
|
@@ -679,9 +661,8 @@ class JobSpec:
|
|
|
679
661
|
raise TypeError("project must be a string")
|
|
680
662
|
project = require_project_id(project_raw) if project_raw.strip() else ""
|
|
681
663
|
algorithm = normalize_algorithm(data.get("algorithm", cls.algorithm))
|
|
682
|
-
|
|
683
|
-
|
|
684
|
-
batch_size, prompts_per_step = migrated_optimizer_batch(train, algorithm)
|
|
664
|
+
batch_size = opt_int(train.get("batch_size"))
|
|
665
|
+
prompts_per_step = opt_int(train.get("prompts_per_step"))
|
|
685
666
|
return cls(
|
|
686
667
|
model=data.get("model", cls.model),
|
|
687
668
|
model_revision=_model_revision(data.get("model_revision", cls.model_revision)),
|
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
"""Decoding rules for PERSISTED job-spec records, as distinct from authored configuration.
|
|
2
|
+
|
|
3
|
+
`JobSpec` serves four different contracts, and this module owns exactly one of them: reading back
|
|
4
|
+
bytes that were already written to `~/.flash/runs/<run_id>.json`. That is not the same job as
|
|
5
|
+
validating a config a user just wrote, and the two must not be confused:
|
|
6
|
+
|
|
7
|
+
- authored configuration is parsed by `flash.schema.spec_from_dict`, which is STRICT. an unknown key
|
|
8
|
+
is a typo in a file the author can still fix, so it fails loudly.
|
|
9
|
+
- a persisted record is parsed by `JobSpec.from_dict`, which applies the looser scalar coercions
|
|
10
|
+
here. It reads a record this build wrote, in this build's shape; an unknown key is fatal in both.
|
|
11
|
+
|
|
12
|
+
Serialized-byte warning: `flash/runner/preparation.py::_preparation_digest` sha256-hashes the
|
|
13
|
+
canonical JSON of `to_dict()` and `to_internal_dict()` output. Key ORDER is safe there
|
|
14
|
+
(`sort_keys=True`), but key PRESENCE is not -- adding, dropping, or renaming a key in a decode path
|
|
15
|
+
changes the digest and fails integrity validation for a run whose snapshot was already written.
|
|
16
|
+
|
|
17
|
+
These functions take plain dicts and return plain dicts and scalars. That is the rule that keeps the
|
|
18
|
+
module importable by `spec.py` rather than the other way round, and it is why `validated_section`
|
|
19
|
+
takes its allowed-key set as an argument instead of reading `fields(TrainSpec)` itself.
|
|
20
|
+
|
|
21
|
+
What is deliberately NOT here: `_coerce_wandb` and `_parse_persisted_gpu_types` are also called only
|
|
22
|
+
from `JobSpec.from_dict`, so they belong to this contract by usage -- but they construct `WandbSpec`
|
|
23
|
+
and reach `_validated_gpu_type`, which `__post_init__` needs too. Moving them would make this module
|
|
24
|
+
import the dataclasses that import it. The boundary is therefore drawn at "persisted-decoding logic
|
|
25
|
+
that does not depend on the spec types themselves".
|
|
26
|
+
"""
|
|
27
|
+
|
|
28
|
+
from __future__ import annotations
|
|
29
|
+
|
|
30
|
+
from typing import Any
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
def validated_section(data: dict[str, Any], name: str, allowed: set[str]) -> dict[str, Any]:
|
|
34
|
+
"""Read one nested block (``[train]``, ``[gpu]``) of a persisted record, rejecting unknown keys.
|
|
35
|
+
|
|
36
|
+
A missing block and an explicit null are the same state -- both mean "authored nothing" -- so both
|
|
37
|
+
normalize to empty rather than one of them raising. An unknown key is fatal.
|
|
38
|
+
"""
|
|
39
|
+
section = data.get(name)
|
|
40
|
+
if section is None:
|
|
41
|
+
section = {}
|
|
42
|
+
if not isinstance(section, dict):
|
|
43
|
+
raise TypeError(f"{name} must be an object")
|
|
44
|
+
unknown = sorted(set(section) - allowed)
|
|
45
|
+
if unknown:
|
|
46
|
+
raise ValueError(f"{name} has unknown key(s): {', '.join(unknown)}")
|
|
47
|
+
return section
|
|
48
|
+
|
|
49
|
+
|
|
50
|
+
def validated_persisted_providers(
|
|
51
|
+
gpu: dict[str, Any], gpu_type: str, gpu_type_fallbacks: tuple[str, ...]
|
|
52
|
+
) -> tuple[str, tuple[str, ...]]:
|
|
53
|
+
"""``(provider, providers)`` from a persisted ``[gpu]`` block, cross-checked against its classes.
|
|
54
|
+
|
|
55
|
+
``GpuSpec.__post_init__`` runs the same both-set check but cannot replace this one: ``allow_empty``
|
|
56
|
+
here keys off whether the record CARRIED a ``providers`` key, and that presence is exactly what the
|
|
57
|
+
dataclass has already lost by the time it validates. An explicitly empty preference and an absent
|
|
58
|
+
one are different states in a stored record.
|
|
59
|
+
"""
|
|
60
|
+
from flash.providers import PROVIDER_NAMES, validated_provider_preferences
|
|
61
|
+
|
|
62
|
+
provider = gpu.get("provider", "")
|
|
63
|
+
if not isinstance(provider, str):
|
|
64
|
+
raise TypeError("gpu.provider must be a string")
|
|
65
|
+
provider = provider.strip().lower()
|
|
66
|
+
providers = validated_provider_preferences(
|
|
67
|
+
gpu.get("providers", ()), allow_empty="providers" not in gpu
|
|
68
|
+
)
|
|
69
|
+
if provider and providers:
|
|
70
|
+
raise ValueError("gpu.provider and gpu.providers cannot both be set")
|
|
71
|
+
if provider or providers or gpu_type:
|
|
72
|
+
from flash.providers.base import providers_for
|
|
73
|
+
|
|
74
|
+
if provider and provider not in PROVIDER_NAMES:
|
|
75
|
+
raise ValueError(f"unknown gpu.provider {provider!r}")
|
|
76
|
+
# a hard provider pin must carry every acceptable class. provider preferences stay soft: an
|
|
77
|
+
# ineligible named provider contributes no candidate, while eligible named or unnamed
|
|
78
|
+
# configured providers remain available for failover.
|
|
79
|
+
for candidate in (gpu_type, *gpu_type_fallbacks):
|
|
80
|
+
if candidate and provider and provider not in providers_for(candidate):
|
|
81
|
+
raise ValueError(
|
|
82
|
+
f"gpu.provider {provider!r} cannot provision gpu.type {candidate!r}"
|
|
83
|
+
)
|
|
84
|
+
return provider, providers
|
|
85
|
+
|
|
86
|
+
|
|
87
|
+
def str_tuple(value: Any) -> tuple[str, ...]:
|
|
88
|
+
"""Normalize a string-or-list knob to a tuple of strings; a bare string is one element, not iterated."""
|
|
89
|
+
if value is None:
|
|
90
|
+
return ()
|
|
91
|
+
if isinstance(value, str):
|
|
92
|
+
return (value,) if value else ()
|
|
93
|
+
return tuple(s for s in (str(x) for x in value) if s)
|
|
94
|
+
|
|
95
|
+
|
|
96
|
+
def volume_gb(value: Any, default: int = 100) -> int:
|
|
97
|
+
"""Parse volume size in GB; non-positive / non-numeric / missing values return default."""
|
|
98
|
+
if isinstance(value, bool):
|
|
99
|
+
# bool is an int subclass; reject to avoid int(True)==1 becoming a 1 GB volume.
|
|
100
|
+
return default
|
|
101
|
+
try:
|
|
102
|
+
gb = int(value)
|
|
103
|
+
except (TypeError, ValueError):
|
|
104
|
+
return default
|
|
105
|
+
return gb if gb > 0 else default
|
|
106
|
+
|
|
107
|
+
|
|
108
|
+
def opt_int(value: Any) -> int | None:
|
|
109
|
+
"""Parse optional int; rejects bools (bool is int subclass — int(True)==1 is a footgun)."""
|
|
110
|
+
if value is None:
|
|
111
|
+
return None
|
|
112
|
+
if isinstance(value, bool):
|
|
113
|
+
raise TypeError(f"expected a number, got bool {value!r}")
|
|
114
|
+
return int(value)
|
|
115
|
+
|
|
116
|
+
|
|
117
|
+
def opt_float(value: Any) -> float | None:
|
|
118
|
+
"""Parse optional float; rejects bools (mirrors ``opt_int``)."""
|
|
119
|
+
if value is None:
|
|
120
|
+
return None
|
|
121
|
+
if isinstance(value, bool):
|
|
122
|
+
raise TypeError(f"expected a number, got bool {value!r}")
|
|
123
|
+
return float(value)
|
|
@@ -28,7 +28,6 @@ from flash.adapters.artifacts import MAX_ATTEMPT_ID as MAX_ATTEMPT_ID
|
|
|
28
28
|
# moved code reads them back through it. an autofix that drops them breaks those tests.
|
|
29
29
|
from flash.core.catalog import ModelInfo, resolve_model # noqa: F401
|
|
30
30
|
from flash.core.spec import ( # noqa: F401
|
|
31
|
-
_DROPPED_TOP_LEVEL_KEYS,
|
|
32
31
|
MANAGED_GPU_KEYS,
|
|
33
32
|
TRAINER_BACKEND,
|
|
34
33
|
GpuSpec,
|
|
@@ -124,19 +123,11 @@ def _adapter_ref_for_status(status: RunStatus) -> str | None:
|
|
|
124
123
|
raw_worker = (status.effective_preparation or {}).get("worker_spec")
|
|
125
124
|
if not raw_worker:
|
|
126
125
|
return None
|
|
127
|
-
# a workload-profile run recorded before #1095 removed the profile job has a managed hf_repo but
|
|
128
|
-
# never produced an adapter. its worker payload still carries the marker, which JobSpec.from_dict
|
|
129
|
-
# now drops, so read it off the raw record rather than reviving the field.
|
|
130
|
-
if isinstance(raw_worker, dict) and raw_worker.get("workload_profile_kind"):
|
|
131
|
-
return None
|
|
132
126
|
try:
|
|
133
127
|
spec = _internal_spec_from_status(status)
|
|
134
128
|
except Exception:
|
|
135
|
-
#
|
|
136
|
-
#
|
|
137
|
-
# is strict, so parsing raises -- and one such record would 500 the whole runs list. same
|
|
138
|
-
# operational tolerance as _runstatus_from_json: the record stays readable, it just shows no
|
|
139
|
-
# adapter ref (its spec cannot name one we could resolve).
|
|
129
|
+
# an unparseable stored spec must not 500 the whole runs list: the record stays readable, it
|
|
130
|
+
# just shows no adapter ref (its spec cannot name one we could resolve).
|
|
140
131
|
return None
|
|
141
132
|
if not spec.train.hf_repo:
|
|
142
133
|
return None
|
|
@@ -805,13 +796,11 @@ from flash.runner.preparation import ( # noqa: E402,F401
|
|
|
805
796
|
_preparation_digest,
|
|
806
797
|
_prepare_init_from_adapter,
|
|
807
798
|
_prepare_init_from_adapter_inner,
|
|
808
|
-
_prepared_before_public_alpha,
|
|
809
799
|
_profile_producer_version,
|
|
810
800
|
_require_pinned_profile_environment,
|
|
811
801
|
_require_sft_workload_profile,
|
|
812
802
|
_require_supported_adapter_continuation,
|
|
813
803
|
_resolve_model_revision,
|
|
814
|
-
_stored_rollout_batch_spelling,
|
|
815
804
|
_validate_effective_spec,
|
|
816
805
|
_warmstart_source_is_authorized,
|
|
817
806
|
)
|
|
@@ -88,47 +88,6 @@ def _spec_pinned_to_horizon(spec, steps: int):
|
|
|
88
88
|
return _replace(spec, train=_replace(spec.train, max_steps=max(1, int(steps))))
|
|
89
89
|
|
|
90
90
|
|
|
91
|
-
def _spec_with_legacy_pool_horizon(spec):
|
|
92
|
-
"""``spec`` with a legacy ``[environment.params] max_examples`` restated as ``[train]``, for PRORATION ONLY.
|
|
93
|
-
|
|
94
|
-
A run accepted before flash stopped reading that key was quoted from it, and cancelling it now
|
|
95
|
-
has to answer "what fraction of the accepted work happened" -- a question about the OLD work
|
|
96
|
-
model, not about what flash would quote today. Without this the full-work reprice raises (no
|
|
97
|
-
stated pool) while the partial pins ``max_steps`` and prices the uncapped batch, so the fraction
|
|
98
|
-
dies and the charge falls through to the quote cap: a legacy 10-step run cancelled after ONE
|
|
99
|
-
step bills 100% of its quote instead of 10%.
|
|
100
|
-
|
|
101
|
-
Restating it under ``[train]`` reproduces the horizon the accepted quote was computed from,
|
|
102
|
-
which is exactly what the ratio needs. Safe here in a way it is not at submit: both sides of
|
|
103
|
-
``partial / full`` are repriced through this same shape, so the value only ever sets a fraction
|
|
104
|
-
between two numbers that share it -- it never becomes a price a customer is quoted, and the
|
|
105
|
-
result stays capped by the quote they accepted. Specs that state ``[train] max_examples`` or
|
|
106
|
-
``max_steps`` already have a horizon and are returned untouched.
|
|
107
|
-
"""
|
|
108
|
-
from dataclasses import replace as _replace
|
|
109
|
-
|
|
110
|
-
if getattr(spec, "algorithm", "") not in ("grpo", "opd"):
|
|
111
|
-
return spec
|
|
112
|
-
train = getattr(spec, "train", None)
|
|
113
|
-
if train is None or int(getattr(train, "max_examples", 0) or 0) > 0:
|
|
114
|
-
return spec
|
|
115
|
-
if int(getattr(train, "max_steps", 0) or 0) > 0:
|
|
116
|
-
return spec
|
|
117
|
-
params = getattr(getattr(spec, "environment", None), "params", {}) or {}
|
|
118
|
-
if not isinstance(params, dict):
|
|
119
|
-
return spec
|
|
120
|
-
try:
|
|
121
|
-
legacy_pool = int(params.get("max_examples") or 0)
|
|
122
|
-
except (TypeError, ValueError, OverflowError):
|
|
123
|
-
# same unreadable-value cases _env_max_examples guarded: `int(inf)` raises OverflowError,
|
|
124
|
-
# `int(nan)` ValueError. an unreadable pool is no horizon, so leave the spec alone and let
|
|
125
|
-
# the caller's own unpriceable-fraction branch handle it.
|
|
126
|
-
return spec
|
|
127
|
-
if legacy_pool <= 0:
|
|
128
|
-
return spec
|
|
129
|
-
return _replace(spec, train=_replace(train, max_examples=legacy_pool))
|
|
130
|
-
|
|
131
|
-
|
|
132
91
|
def charge_usd_for_spec(
|
|
133
92
|
spec,
|
|
134
93
|
*,
|
|
@@ -303,9 +262,8 @@ def cancelled_charge_usd(
|
|
|
303
262
|
# billing retry predicate (cost_usd > 0) can never settle, silently stranding the run
|
|
304
263
|
# unbilled, so the fallback propagates and the caller records the pricing failure.
|
|
305
264
|
return float(fallback)
|
|
306
|
-
prorated_spec = _spec_with_legacy_pool_horizon(spec)
|
|
307
265
|
partial = runner.charge_usd_for_spec(
|
|
308
|
-
|
|
266
|
+
spec,
|
|
309
267
|
steps=n,
|
|
310
268
|
fallback=float("nan"),
|
|
311
269
|
provider=provider,
|
|
@@ -313,7 +271,7 @@ def cancelled_charge_usd(
|
|
|
313
271
|
gpu_count=gpu_count,
|
|
314
272
|
)
|
|
315
273
|
full = runner.charge_usd_for_spec(
|
|
316
|
-
|
|
274
|
+
spec,
|
|
317
275
|
fallback=float("nan"),
|
|
318
276
|
provider=provider,
|
|
319
277
|
gpu_type=gpu_type,
|
|
@@ -16,9 +16,7 @@ import json
|
|
|
16
16
|
import os
|
|
17
17
|
import re
|
|
18
18
|
from dataclasses import replace
|
|
19
|
-
from typing import Any
|
|
20
19
|
|
|
21
|
-
from flash.core.catalog import normalize_algorithm, samples_on_policy
|
|
22
20
|
from flash.core.spec import JobSpec
|
|
23
21
|
|
|
24
22
|
|
|
@@ -298,129 +296,17 @@ def _mark_warmstart_source(worker_spec: JobSpec, child_run_id: str) -> None:
|
|
|
298
296
|
)
|
|
299
297
|
|
|
300
298
|
|
|
301
|
-
def _prepared_before_public_alpha(raw_public: object) -> bool:
|
|
302
|
-
"""True when this run's PERSISTED public spec predates ``lora_alpha`` becoming authorable.
|
|
303
|
-
|
|
304
|
-
The discriminator is the stored bytes, not this build's serialization: a snapshot prepared
|
|
305
|
-
before the change hashed a public spec with no alpha key, and its digest can only be reproduced
|
|
306
|
-
the same way. status.spec is never rewritten, so this answer is stable for the run's life.
|
|
307
|
-
|
|
308
|
-
A warm-start spec is excluded even though it also omits alpha -- to_dict() strips rank and alpha
|
|
309
|
-
for those in every version, so absence there says nothing about when the run was prepared, and
|
|
310
|
-
treating it as legacy would drop a binding that costs nothing to keep.
|
|
311
|
-
"""
|
|
312
|
-
if not isinstance(raw_public, dict):
|
|
313
|
-
return False
|
|
314
|
-
train = raw_public.get("train")
|
|
315
|
-
if not isinstance(train, dict) or "lora_alpha" in train:
|
|
316
|
-
return False
|
|
317
|
-
return not train.get("init_from_adapter")
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
_ROLLOUT_BATCH_KEYS = ("batch_size", "prompts_per_step")
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
def _stored_rollout_batch_spelling(raw_spec: object) -> dict[str, Any] | None:
|
|
324
|
-
"""How a PERSISTED rollout spec spelled its optimizer batch, or None if it is not one.
|
|
325
|
-
|
|
326
|
-
Same discriminator style as ``_prepared_before_public_alpha``: the answer comes from the stored
|
|
327
|
-
bytes, which are never rewritten, so it is stable for the run's life.
|
|
328
|
-
|
|
329
|
-
``JobSpec.from_dict`` MOVES the pre-1.1.43 ``batch_size`` onto ``prompts_per_step`` when
|
|
330
|
-
reparsing, so rehashing a persisted spec with today's parse can produce different bytes than
|
|
331
|
-
were hashed at persist time -- failing integrity validation for exactly the warm-start grpo/opd
|
|
332
|
-
runs this migration exists to rescue.
|
|
333
|
-
|
|
334
|
-
Both keys are reported, rather than just the value there is to migrate. Reporting only the
|
|
335
|
-
latter conflates snapshots that have nothing to move but still change shape: a mixed-version
|
|
336
|
-
payload storing both names (the migration drops the old one, so the stored ``batch_size`` still
|
|
337
|
-
has to be rehashed), one whose legacy value is non-positive (discarded by the parser), and a
|
|
338
|
-
modern payload (nothing to do). Replaying the stored spelling covers all of them uniformly.
|
|
339
|
-
|
|
340
|
-
A key merely holding null reports None; a key genuinely OMITTED is omitted from the reading too,
|
|
341
|
-
because the two hash differently. Every digest is taken over a serialized ``JobSpec``, which
|
|
342
|
-
emits both names, so a null was really hashed as null -- while 1.1.40 predates
|
|
343
|
-
``prompts_per_step`` entirely and hashed no such key. Each half's reading therefore carries its
|
|
344
|
-
OWN absence rather than sharing one flag: after a re-persist the worker half is rewritten in the
|
|
345
|
-
modern shape while ``status.spec`` keeps the legacy one, so the halves genuinely disagree about
|
|
346
|
-
which keys exist and a single flag would misdescribe one of them.
|
|
347
|
-
|
|
348
|
-
This is not a way to forge a batch: the replayed values are the STORED ones, and the digest they
|
|
349
|
-
are compared against was computed over the ORIGINAL ones, so any tampering still mismatches.
|
|
350
|
-
|
|
351
|
-
Only a rollout algorithm is eligible: for sft ``batch_size`` is the current, un-migrated name,
|
|
352
|
-
which ``from_dict`` leaves alone.
|
|
353
|
-
"""
|
|
354
|
-
if not isinstance(raw_spec, dict):
|
|
355
|
-
return None
|
|
356
|
-
if not samples_on_policy(normalize_algorithm(str(raw_spec.get("algorithm") or ""))):
|
|
357
|
-
return None
|
|
358
|
-
train = raw_spec.get("train")
|
|
359
|
-
if not isinstance(train, dict):
|
|
360
|
-
return None
|
|
361
|
-
stored = {key: train.get(key) for key in _ROLLOUT_BATCH_KEYS}
|
|
362
|
-
# the 1.1.40 shape, read off the bytes themselves: it carried the old name and no new one.
|
|
363
|
-
# a payload omitting BOTH says nothing about when it was written, and the serializer always
|
|
364
|
-
# emits both -- so treating that as absence would drop a key that WAS hashed.
|
|
365
|
-
if "batch_size" in train and "prompts_per_step" not in train:
|
|
366
|
-
del stored["prompts_per_step"]
|
|
367
|
-
return stored
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
def _restore_rollout_batch_spelling(payload: dict, stored: dict | None) -> None:
|
|
371
|
-
"""Put the optimizer-batch keys back exactly as the stored payload hashed them.
|
|
372
|
-
|
|
373
|
-
A key absent from ``stored`` was absent from the hashed bytes, so it is removed rather than
|
|
374
|
-
written -- that is the 1.1.40 shape, which predates ``prompts_per_step``.
|
|
375
|
-
"""
|
|
376
|
-
if stored is None:
|
|
377
|
-
return
|
|
378
|
-
train = payload.get("train")
|
|
379
|
-
if not isinstance(train, dict):
|
|
380
|
-
return
|
|
381
|
-
for key in _ROLLOUT_BATCH_KEYS:
|
|
382
|
-
if key in stored:
|
|
383
|
-
train[key] = stored[key]
|
|
384
|
-
else:
|
|
385
|
-
train.pop(key, None)
|
|
386
|
-
|
|
387
|
-
|
|
388
299
|
def _preparation_digest(
|
|
389
300
|
public_spec: JobSpec,
|
|
390
301
|
worker_spec: JobSpec,
|
|
391
302
|
adapter_identity: dict | None,
|
|
392
|
-
*,
|
|
393
|
-
legacy_keys: dict | None = None,
|
|
394
|
-
legacy_public_keys: dict | None = None,
|
|
395
|
-
legacy_public_alpha: bool = False,
|
|
396
|
-
stored_rollout_batch: dict | None = None,
|
|
397
|
-
stored_public_rollout_batch: dict | None = None,
|
|
398
303
|
) -> str:
|
|
399
304
|
worker_payload = worker_spec.to_internal_dict()
|
|
400
305
|
public_payload = public_spec.to_dict()
|
|
401
|
-
#
|
|
402
|
-
# MOVES it when reparsing a persisted spec. Rehash under the spelling the snapshot actually
|
|
403
|
-
# stored -- including a key it did not have -- so a spec written before or across the rename
|
|
404
|
-
# still reproduces its digest. Same reason as the omissions and restorations below.
|
|
405
|
-
#
|
|
406
|
-
# Each half is restored from ITS OWN stored payload, exactly like legacy_keys vs
|
|
407
|
-
# legacy_public_keys below. Feeding the worker's spelling to both would overwrite whatever the
|
|
408
|
-
# public payload held before hashing -- and since the parse DROPS a superseded `batch_size`,
|
|
409
|
-
# `_validate_effective_spec` cannot see it either, so a tampered public value would be erased
|
|
410
|
-
# rather than caught. The two halves legitimately differ (the public spec is a stripped view),
|
|
411
|
-
# so they cannot share one reading -- including which keys they carry at all, which is why each
|
|
412
|
-
# reading holds its own absence instead of a shared flag. Re-persisting rewrites the worker half
|
|
413
|
-
# in the modern shape and leaves `status.spec` legacy, so from then on the halves disagree.
|
|
414
|
-
_restore_rollout_batch_spelling(worker_payload, stored_rollout_batch)
|
|
415
|
-
_restore_rollout_batch_spelling(public_payload, stored_public_rollout_batch)
|
|
416
|
-
# ``[environment] pip`` became user-authorable, so to_dict() now emits it where it used to be
|
|
417
|
-
# stripped, and a pre-upgrade snapshot hashed an environment with no pip key at all. Dropping it
|
|
418
|
-
# when empty reproduces those bytes without needing to know when the run was prepared: absent
|
|
419
|
-
# and empty are the same install, so they must hash alike. An authored pip is non-empty and
|
|
420
|
-
# stays bound, so tampering with the persisted value is still caught.
|
|
306
|
+
# absent and empty pip are the same install, so they must hash alike.
|
|
421
307
|
if not public_payload["environment"].get("pip"):
|
|
422
308
|
public_payload["environment"].pop("pip", None)
|
|
423
|
-
# omit empty fields so
|
|
309
|
+
# omit empty managed fields so the hashed payload carries only what the run actually set.
|
|
424
310
|
for key in (
|
|
425
311
|
"model_revision_auto",
|
|
426
312
|
"gpu_count_auto",
|
|
@@ -430,34 +316,6 @@ def _preparation_digest(
|
|
|
430
316
|
):
|
|
431
317
|
if not worker_payload.get(key):
|
|
432
318
|
worker_payload.pop(key, None)
|
|
433
|
-
# Restore since-removed keys the STORED payload carried, for the same reason as the omissions
|
|
434
|
-
# above: the digest has to reproduce the bytes that were hashed, not today's serialization. A
|
|
435
|
-
# pre-upgrade snapshot hashed `model_policy` in (to_internal_dict was asdict, so it emitted the
|
|
436
|
-
# defaulted value), and the field no longer exists -- so rehashing without it mismatches and a
|
|
437
|
-
# still-valid warm-start or workload-profile run fails integrity validation on recovery. Only
|
|
438
|
-
# keys registered as historical public removals are honoured. Any field the dataclass still
|
|
439
|
-
# defines already comes from worker_spec, so replaying its identical stored value cannot forge it.
|
|
440
|
-
for key, value in (legacy_keys or {}).items():
|
|
441
|
-
if key in _runner()._DROPPED_TOP_LEVEL_KEYS:
|
|
442
|
-
worker_payload[key] = value
|
|
443
|
-
# a dropped key that was USER-AUTHORABLE was hashed on the public side too, not just the worker
|
|
444
|
-
# side. model_policy never was, so restoring only the worker payload was enough for it;
|
|
445
|
-
# model_revision and worker_env were, so a pre-upgrade public_spec carried them and the digest
|
|
446
|
-
# cannot reproduce without them.
|
|
447
|
-
for key, value in (legacy_public_keys or {}).items():
|
|
448
|
-
if key in _runner()._DROPPED_TOP_LEVEL_KEYS:
|
|
449
|
-
public_payload[key] = value
|
|
450
|
-
# ``lora_alpha`` became user-authorable, so to_dict() now emits it for non-warm-start runs. A
|
|
451
|
-
# snapshot prepared BEFORE that change hashed a public spec without alpha, so rehashing it with
|
|
452
|
-
# alpha would fail a still-valid run's integrity check on recovery -- same reason as the
|
|
453
|
-
# omissions and restorations above. That omission is scoped to those legacy snapshots only: a
|
|
454
|
-
# digest created from here on binds the public alpha, so tampering with the persisted public
|
|
455
|
-
# value is caught. Without that binding the two halves can disagree silently, because
|
|
456
|
-
# _runner()._validate_effective_spec() excludes lora_alpha from its structural comparison (the worker's
|
|
457
|
-
# warm-start-inherited alpha legitimately differs from the public one), leaving the digest as
|
|
458
|
-
# the only thing that could cover it.
|
|
459
|
-
if legacy_public_alpha:
|
|
460
|
-
public_payload["train"].pop("lora_alpha", None)
|
|
461
319
|
payload = {
|
|
462
320
|
"version": 1,
|
|
463
321
|
"public_spec": public_payload,
|
|
@@ -488,15 +346,12 @@ def _validate_effective_spec(public_spec: JobSpec, worker_spec: JobSpec) -> None
|
|
|
488
346
|
"workload_profile",
|
|
489
347
|
):
|
|
490
348
|
effective[managed_top] = public.get(managed_top)
|
|
491
|
-
# the pin value is stripped from
|
|
492
|
-
#
|
|
493
|
-
#
|
|
494
|
-
#
|
|
495
|
-
#
|
|
496
|
-
|
|
497
|
-
worker_spec.model_revision_auto or public.get("train", {}).get("init_from_adapter")
|
|
498
|
-
):
|
|
499
|
-
effective["model_revision"] = public.get("model_revision")
|
|
349
|
+
# the pin value is stripped from EVERY public spec (`to_dict` drops it), so the worker half
|
|
350
|
+
# legitimately carries a revision the public half cannot: a runner-assigned pin, or an authored
|
|
351
|
+
# pin a warm-start child inherited. the asymmetry is therefore unconditional and excluded here.
|
|
352
|
+
# it stays digest-protected: the auto marker triggers digest verification, and every warm start
|
|
353
|
+
# verifies its complete preparation snapshot.
|
|
354
|
+
effective["model_revision"] = public.get("model_revision")
|
|
500
355
|
public_train = dict(public["train"])
|
|
501
356
|
effective_train = dict(effective["train"])
|
|
502
357
|
public_ref = public_train.get("init_from_adapter") or ""
|
|
@@ -18,7 +18,7 @@ import os
|
|
|
18
18
|
import time
|
|
19
19
|
|
|
20
20
|
import flash.runner as runner
|
|
21
|
-
from flash.core.spec import
|
|
21
|
+
from flash.core.spec import JobSpec
|
|
22
22
|
from flash.runner import RunStatus
|
|
23
23
|
|
|
24
24
|
# every other collaborator is reached through `runner.` rather than bound here. `RUNS_DIR`,
|
|
@@ -68,20 +68,6 @@ def effective_spec_from_status(status: RunStatus, *, verify_source: bool = False
|
|
|
68
68
|
runner._validate_effective_spec(public_spec, worker_spec)
|
|
69
69
|
expected = snapshot.get("adapter_identity")
|
|
70
70
|
stored_digest = snapshot.get("preparation_digest")
|
|
71
|
-
# A pre-upgrade snapshot hashed since-removed keys into its digest, and `worker_spec` no longer
|
|
72
|
-
# carries them -- so reproducing that digest needs the values the STORED payload holds.
|
|
73
|
-
legacy_keys = {k: raw_worker[k] for k in _DROPPED_TOP_LEVEL_KEYS if k in raw_worker}
|
|
74
|
-
raw_public = status.spec if isinstance(status.spec, dict) else {}
|
|
75
|
-
legacy_public_keys = {k: raw_public[k] for k in _DROPPED_TOP_LEVEL_KEYS if k in raw_public}
|
|
76
|
-
legacy_public_alpha = runner._prepared_before_public_alpha(raw_public)
|
|
77
|
-
# the rollout optimizer batch was renamed, and `from_dict` moves it -- so a snapshot has to be
|
|
78
|
-
# rehashed under the spelling it actually stored, including a key it did not carry. Each half is
|
|
79
|
-
# read from its OWN payload, like legacy_keys/legacy_public_keys above: reusing the worker's
|
|
80
|
-
# reading for the public half would overwrite the stored public value before hashing, and the
|
|
81
|
-
# parse drops a superseded `batch_size` so `_validate_effective_spec` cannot see it either --
|
|
82
|
-
# which would leave a tampered public batch neither bound nor compared.
|
|
83
|
-
stored_rollout_batch = runner._stored_rollout_batch_spelling(raw_worker)
|
|
84
|
-
stored_public_rollout_batch = runner._stored_rollout_batch_spelling(raw_public)
|
|
85
71
|
has_workload_profile = bool(
|
|
86
72
|
worker_spec.workload_profile_input_digest or worker_spec.workload_profile
|
|
87
73
|
)
|
|
@@ -109,17 +95,7 @@ def effective_spec_from_status(status: RunStatus, *, verify_source: bool = False
|
|
|
109
95
|
# the geometry cap still constrain.
|
|
110
96
|
if (has_workload_profile or worker_spec.model_revision_auto) and (
|
|
111
97
|
not isinstance(stored_digest, str)
|
|
112
|
-
or stored_digest
|
|
113
|
-
!= runner._preparation_digest(
|
|
114
|
-
public_spec,
|
|
115
|
-
worker_spec,
|
|
116
|
-
expected,
|
|
117
|
-
legacy_keys=legacy_keys,
|
|
118
|
-
legacy_public_keys=legacy_public_keys,
|
|
119
|
-
legacy_public_alpha=legacy_public_alpha,
|
|
120
|
-
stored_rollout_batch=stored_rollout_batch,
|
|
121
|
-
stored_public_rollout_batch=stored_public_rollout_batch,
|
|
122
|
-
)
|
|
98
|
+
or stored_digest != runner._preparation_digest(public_spec, worker_spec, expected)
|
|
123
99
|
):
|
|
124
100
|
raise ValueError("persisted effective preparation failed integrity validation")
|
|
125
101
|
if public_spec.train.init_from_adapter:
|
|
@@ -129,14 +105,7 @@ def effective_spec_from_status(status: RunStatus, *, verify_source: bool = False
|
|
|
129
105
|
"because its original artifact identity is unavailable"
|
|
130
106
|
)
|
|
131
107
|
if not isinstance(stored_digest, str) or stored_digest != runner._preparation_digest(
|
|
132
|
-
public_spec,
|
|
133
|
-
worker_spec,
|
|
134
|
-
expected,
|
|
135
|
-
legacy_keys=legacy_keys,
|
|
136
|
-
legacy_public_keys=legacy_public_keys,
|
|
137
|
-
legacy_public_alpha=legacy_public_alpha,
|
|
138
|
-
stored_rollout_batch=stored_rollout_batch,
|
|
139
|
-
stored_public_rollout_batch=stored_public_rollout_batch,
|
|
108
|
+
public_spec, worker_spec, expected
|
|
140
109
|
):
|
|
141
110
|
raise ValueError("persisted effective preparation failed integrity validation")
|
|
142
111
|
if verify_source and public_spec.train.init_from_adapter:
|
|
@@ -372,7 +341,7 @@ def _update(run_id: str, state: str, *, allow_from_terminal: bool = False, **upd
|
|
|
372
341
|
status.state = state
|
|
373
342
|
status.updated_at = time.time()
|
|
374
343
|
if state in runner.TERMINAL_STATES and status.finished_at is None:
|
|
375
|
-
#
|
|
344
|
+
# an already-terminal run keeps its teardown time: backfill from prior updated_at.
|
|
376
345
|
status.finished_at = prev_updated_at if was_terminal else status.updated_at
|
|
377
346
|
for key, value in updates.items():
|
|
378
347
|
setattr(status, key, value)
|
|
@@ -203,30 +203,12 @@ def _persist_effective_worker_spec(
|
|
|
203
203
|
adapter_identity = None
|
|
204
204
|
_reject_managed_volume_removal(snapshot, worker_spec)
|
|
205
205
|
_runner()._validate_effective_spec(public_spec, worker_spec)
|
|
206
|
-
# status.spec is never rewritten, so a pre-upgrade run keeps its dropped keys for life and every
|
|
207
|
-
# later read rehashes with them restored. re-persisting (quote refresh, realloc) has to hash the
|
|
208
|
-
# same way or the digest it writes now is one the next integrity check cannot reproduce.
|
|
209
|
-
raw_public = status.spec if isinstance(status.spec, dict) else {}
|
|
210
|
-
legacy_public_keys = {
|
|
211
|
-
k: raw_public[k] for k in _runner()._DROPPED_TOP_LEVEL_KEYS if k in raw_public
|
|
212
|
-
}
|
|
213
|
-
# same reason for the rollout optimizer batch: `status.spec` is never rewritten, so a legacy
|
|
214
|
-
# grpo/opd run keeps the old spelling for life and every read replays it. Hashing without that
|
|
215
|
-
# replay writes a digest the next integrity check cannot reproduce, so the run recovers until
|
|
216
|
-
# its first quote refresh or realloc and fails afterwards. Only the public half needs this --
|
|
217
|
-
# the worker half is rewritten right here, so its stored bytes already match what is hashed.
|
|
218
|
-
stored_public_rollout_batch = _runner()._stored_rollout_batch_spelling(raw_public)
|
|
219
206
|
effective_preparation = {
|
|
220
207
|
"worker_spec": worker_spec.to_internal_dict(),
|
|
221
208
|
"workload_profile": worker_spec.workload_profile or None,
|
|
222
209
|
"adapter_identity": adapter_identity,
|
|
223
210
|
"preparation_digest": _runner()._preparation_digest(
|
|
224
|
-
public_spec,
|
|
225
|
-
worker_spec,
|
|
226
|
-
adapter_identity,
|
|
227
|
-
legacy_public_keys=legacy_public_keys,
|
|
228
|
-
legacy_public_alpha=_runner()._prepared_before_public_alpha(raw_public),
|
|
229
|
-
stored_public_rollout_batch=stored_public_rollout_batch,
|
|
211
|
+
public_spec, worker_spec, adapter_identity
|
|
230
212
|
),
|
|
231
213
|
"backend": _runner().TRAINER_BACKEND,
|
|
232
214
|
}
|
|
@@ -244,8 +244,7 @@ _TOP_LEVEL_KEYS = frozenset(
|
|
|
244
244
|
)
|
|
245
245
|
# keys that WERE user-authorable and are now rejected with their own targeted error. they are absent
|
|
246
246
|
# from _TOP_LEVEL_KEYS, so the unknown-key check below would otherwise report them as a typo and bury
|
|
247
|
-
# the explanation of why they went away.
|
|
248
|
-
# about tolerating removed keys on READ so persisted records still parse and rehash.
|
|
247
|
+
# the explanation of why they went away.
|
|
249
248
|
_REMOVED_TOP_LEVEL_KEYS = frozenset({"model_revision"})
|
|
250
249
|
# runner-assigned [gpu] fields (MANAGED_GPU_KEYS, single-sourced in flash.core.spec) are excluded from the
|
|
251
250
|
# user-facing surface. GpuSpec still carries them so the internal JobSpec.from_dict round trip
|
|
@@ -331,10 +330,7 @@ def _validate_top_level(
|
|
|
331
330
|
raw: dict[str, Any], project_required: bool
|
|
332
331
|
) -> tuple[str, str, str, str, bool]:
|
|
333
332
|
"""Validate the top-level config section."""
|
|
334
|
-
|
|
335
|
-
# released clients serialize an unpinned spec as model_revision="". tolerate that legacy wire
|
|
336
|
-
# artifact, including whitespace-only strings, while continuing to reject every authored pin.
|
|
337
|
-
if "model_revision" in raw and (not isinstance(revision_raw, str) or revision_raw.strip()):
|
|
333
|
+
if "model_revision" in raw:
|
|
338
334
|
raise ConfigError(
|
|
339
335
|
"config key `model_revision` was removed because Flash-managed serving loads a "
|
|
340
336
|
"pre-quantized FP8 checkpoint resolved per base model, so it cannot honor an arbitrary "
|
|
@@ -83,9 +83,8 @@ def openai_base_url(control_url: str) -> str:
|
|
|
83
83
|
|
|
84
84
|
|
|
85
85
|
def public_deployment(deployment: dict) -> dict:
|
|
86
|
-
"""Return a public copy without private rollback state
|
|
86
|
+
"""Return a public copy without private rollback state."""
|
|
87
87
|
out = dict(deployment)
|
|
88
88
|
out.pop("previous_deployment", None)
|
|
89
89
|
out.pop("verification_generation", None)
|
|
90
|
-
out.pop("url", None)
|
|
91
90
|
return out
|