freesolo-flash-dev 1.2.96__tar.gz → 1.2.97__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.96 → freesolo_flash_dev-1.2.97}/PKG-INFO +1 -1
- {freesolo_flash_dev-1.2.96 → freesolo_flash_dev-1.2.97}/flash/cli/commands/__init__.py +30 -11
- {freesolo_flash_dev-1.2.96 → freesolo_flash_dev-1.2.97}/flash/cli/commands/train_cost.py +103 -6
- {freesolo_flash_dev-1.2.96 → freesolo_flash_dev-1.2.97}/flash/cli/commands/worker_output.py +20 -11
- {freesolo_flash_dev-1.2.96 → freesolo_flash_dev-1.2.97}/flash/envs/identity.py +10 -0
- {freesolo_flash_dev-1.2.96 → freesolo_flash_dev-1.2.97}/pyproject.toml +2 -2
- {freesolo_flash_dev-1.2.96 → freesolo_flash_dev-1.2.97}/tests/test_cli_commands.py +249 -10
- {freesolo_flash_dev-1.2.96 → freesolo_flash_dev-1.2.97}/tests/test_cli_commands_coverage.py +11 -3
- {freesolo_flash_dev-1.2.96 → freesolo_flash_dev-1.2.97}/tests/test_cli_estimate.py +85 -2
- {freesolo_flash_dev-1.2.96 → freesolo_flash_dev-1.2.97}/uv.lock +1 -1
- {freesolo_flash_dev-1.2.96 → freesolo_flash_dev-1.2.97}/.dockerignore +0 -0
- {freesolo_flash_dev-1.2.96 → freesolo_flash_dev-1.2.97}/.env.example +0 -0
- {freesolo_flash_dev-1.2.96 → freesolo_flash_dev-1.2.97}/.github/CODEOWNERS +0 -0
- {freesolo_flash_dev-1.2.96 → freesolo_flash_dev-1.2.97}/.github/ISSUE_TEMPLATE/bug_report.yml +0 -0
- {freesolo_flash_dev-1.2.96 → freesolo_flash_dev-1.2.97}/.github/ISSUE_TEMPLATE/config.yml +0 -0
- {freesolo_flash_dev-1.2.96 → freesolo_flash_dev-1.2.97}/.github/ISSUE_TEMPLATE/feature_request.yml +0 -0
- {freesolo_flash_dev-1.2.96 → freesolo_flash_dev-1.2.97}/.github/PULL_REQUEST_TEMPLATE.md +0 -0
- {freesolo_flash_dev-1.2.96 → freesolo_flash_dev-1.2.97}/.github/dependabot.yml +0 -0
- {freesolo_flash_dev-1.2.96 → freesolo_flash_dev-1.2.97}/.github/workflows/auto-rebake.yml +0 -0
- {freesolo_flash_dev-1.2.96 → freesolo_flash_dev-1.2.97}/.github/workflows/bake-kernel-cache.yml +0 -0
- {freesolo_flash_dev-1.2.96 → freesolo_flash_dev-1.2.97}/.github/workflows/ci.yml +0 -0
- {freesolo_flash_dev-1.2.96 → freesolo_flash_dev-1.2.97}/.github/workflows/dev-kernel-cache.yml +0 -0
- {freesolo_flash_dev-1.2.96 → freesolo_flash_dev-1.2.97}/.github/workflows/main-source-guard.yml +0 -0
- {freesolo_flash_dev-1.2.96 → freesolo_flash_dev-1.2.97}/.github/workflows/notify-tests-repo.yml +0 -0
- {freesolo_flash_dev-1.2.96 → freesolo_flash_dev-1.2.97}/.github/workflows/production-kernel-cache-ready.yml +0 -0
- {freesolo_flash_dev-1.2.96 → freesolo_flash_dev-1.2.97}/.github/workflows/publish-dev.yml +0 -0
- {freesolo_flash_dev-1.2.96 → freesolo_flash_dev-1.2.97}/.github/workflows/publish-image.yml +0 -0
- {freesolo_flash_dev-1.2.96 → freesolo_flash_dev-1.2.97}/.github/workflows/publish.yml +0 -0
- {freesolo_flash_dev-1.2.96 → freesolo_flash_dev-1.2.97}/.github/workflows/version-parity.yml +0 -0
- {freesolo_flash_dev-1.2.96 → freesolo_flash_dev-1.2.97}/.github/workflows/worker-image.yml +0 -0
- {freesolo_flash_dev-1.2.96 → freesolo_flash_dev-1.2.97}/.gitignore +0 -0
- {freesolo_flash_dev-1.2.96 → freesolo_flash_dev-1.2.97}/CHANGELOG.md +0 -0
- {freesolo_flash_dev-1.2.96 → freesolo_flash_dev-1.2.97}/CODE_OF_CONDUCT.md +0 -0
- {freesolo_flash_dev-1.2.96 → freesolo_flash_dev-1.2.97}/CONTRIBUTING.md +0 -0
- {freesolo_flash_dev-1.2.96 → freesolo_flash_dev-1.2.97}/Dockerfile +0 -0
- {freesolo_flash_dev-1.2.96 → freesolo_flash_dev-1.2.97}/Dockerfile.worker +0 -0
- {freesolo_flash_dev-1.2.96 → freesolo_flash_dev-1.2.97}/LICENSE +0 -0
- {freesolo_flash_dev-1.2.96 → freesolo_flash_dev-1.2.97}/NOTICE +0 -0
- {freesolo_flash_dev-1.2.96 → freesolo_flash_dev-1.2.97}/README.md +0 -0
- {freesolo_flash_dev-1.2.96 → freesolo_flash_dev-1.2.97}/SECURITY.md +0 -0
- {freesolo_flash_dev-1.2.96 → freesolo_flash_dev-1.2.97}/SELF_HOSTING.md +0 -0
- {freesolo_flash_dev-1.2.96 → freesolo_flash_dev-1.2.97}/build/kernel_cache/.gitignore +0 -0
- {freesolo_flash_dev-1.2.96 → freesolo_flash_dev-1.2.97}/build/kernel_cache/.keep +0 -0
- {freesolo_flash_dev-1.2.96 → freesolo_flash_dev-1.2.97}/deploy/infisical/README.md +0 -0
- {freesolo_flash_dev-1.2.96 → freesolo_flash_dev-1.2.97}/deploy/infisical/entrypoint.sh +0 -0
- {freesolo_flash_dev-1.2.96 → freesolo_flash_dev-1.2.97}/docker/Dockerfile.kernelcache +0 -0
- {freesolo_flash_dev-1.2.96 → freesolo_flash_dev-1.2.97}/docker/Dockerfile.kernelcache.relayer +0 -0
- {freesolo_flash_dev-1.2.96 → freesolo_flash_dev-1.2.97}/docker/bake_kernel_cache.py +0 -0
- {freesolo_flash_dev-1.2.96 → freesolo_flash_dev-1.2.97}/docker/bake_pod_entry.py +0 -0
- {freesolo_flash_dev-1.2.96 → freesolo_flash_dev-1.2.97}/docker/extract_cudart_fix.py +0 -0
- {freesolo_flash_dev-1.2.96 → freesolo_flash_dev-1.2.97}/docker/kernel_fingerprint.py +0 -0
- {freesolo_flash_dev-1.2.96 → freesolo_flash_dev-1.2.97}/docker/make_rp_handler.py +0 -0
- {freesolo_flash_dev-1.2.96 → freesolo_flash_dev-1.2.97}/flash/__init__.py +0 -0
- {freesolo_flash_dev-1.2.96 → freesolo_flash_dev-1.2.97}/flash/_internal/__init__.py +0 -0
- {freesolo_flash_dev-1.2.96 → freesolo_flash_dev-1.2.97}/flash/_internal/channel.py +0 -0
- {freesolo_flash_dev-1.2.96 → freesolo_flash_dev-1.2.97}/flash/_internal/diagnostics.py +0 -0
- {freesolo_flash_dev-1.2.96 → freesolo_flash_dev-1.2.97}/flash/_internal/fileio.py +0 -0
- {freesolo_flash_dev-1.2.96 → freesolo_flash_dev-1.2.97}/flash/_internal/logging.py +0 -0
- {freesolo_flash_dev-1.2.96 → freesolo_flash_dev-1.2.97}/flash/_internal/paths.py +0 -0
- {freesolo_flash_dev-1.2.96 → freesolo_flash_dev-1.2.97}/flash/adapters/__init__.py +0 -0
- {freesolo_flash_dev-1.2.96 → freesolo_flash_dev-1.2.97}/flash/adapters/artifacts.py +0 -0
- {freesolo_flash_dev-1.2.96 → freesolo_flash_dev-1.2.97}/flash/adapters/fused_experts.py +0 -0
- {freesolo_flash_dev-1.2.96 → freesolo_flash_dev-1.2.97}/flash/adapters/lora_rank.py +0 -0
- {freesolo_flash_dev-1.2.96 → freesolo_flash_dev-1.2.97}/flash/adapters/targets.py +0 -0
- {freesolo_flash_dev-1.2.96 → freesolo_flash_dev-1.2.97}/flash/cli/__init__.py +0 -0
- {freesolo_flash_dev-1.2.96 → freesolo_flash_dev-1.2.97}/flash/cli/__main__.py +0 -0
- {freesolo_flash_dev-1.2.96 → freesolo_flash_dev-1.2.97}/flash/cli/commands/deploy.py +0 -0
- {freesolo_flash_dev-1.2.96 → freesolo_flash_dev-1.2.97}/flash/cli/commands/env/__init__.py +0 -0
- {freesolo_flash_dev-1.2.96 → freesolo_flash_dev-1.2.97}/flash/cli/commands/env/episode.py +0 -0
- {freesolo_flash_dev-1.2.96 → freesolo_flash_dev-1.2.97}/flash/cli/commands/env/eval.py +0 -0
- {freesolo_flash_dev-1.2.96 → freesolo_flash_dev-1.2.97}/flash/cli/commands/env/eval_args.py +0 -0
- {freesolo_flash_dev-1.2.96 → freesolo_flash_dev-1.2.97}/flash/cli/commands/env/imports.py +0 -0
- {freesolo_flash_dev-1.2.96 → freesolo_flash_dev-1.2.97}/flash/cli/commands/env/list.py +0 -0
- {freesolo_flash_dev-1.2.96 → freesolo_flash_dev-1.2.97}/flash/cli/commands/env/push.py +0 -0
- {freesolo_flash_dev-1.2.96 → freesolo_flash_dev-1.2.97}/flash/cli/commands/env/retained.py +0 -0
- {freesolo_flash_dev-1.2.96 → freesolo_flash_dev-1.2.97}/flash/cli/commands/env/setup.py +0 -0
- {freesolo_flash_dev-1.2.96 → freesolo_flash_dev-1.2.97}/flash/cli/commands/env/setup_wandb.py +0 -0
- {freesolo_flash_dev-1.2.96 → freesolo_flash_dev-1.2.97}/flash/cli/commands/env/test.py +0 -0
- {freesolo_flash_dev-1.2.96 → freesolo_flash_dev-1.2.97}/flash/cli/commands/env/test_evaluations.py +0 -0
- {freesolo_flash_dev-1.2.96 → freesolo_flash_dev-1.2.97}/flash/cli/commands/env/test_params.py +0 -0
- {freesolo_flash_dev-1.2.96 → freesolo_flash_dev-1.2.97}/flash/cli/commands/env/test_warnings.py +0 -0
- {freesolo_flash_dev-1.2.96 → freesolo_flash_dev-1.2.97}/flash/cli/commands/prompt_budget.py +0 -0
- {freesolo_flash_dev-1.2.96 → freesolo_flash_dev-1.2.97}/flash/cli/commands/traces.py +0 -0
- {freesolo_flash_dev-1.2.96 → freesolo_flash_dev-1.2.97}/flash/cli/errors.py +0 -0
- {freesolo_flash_dev-1.2.96 → freesolo_flash_dev-1.2.97}/flash/cli/scaffold/TRAINING.md +0 -0
- {freesolo_flash_dev-1.2.96 → freesolo_flash_dev-1.2.97}/flash/cli/scaffold/__init__.py +0 -0
- {freesolo_flash_dev-1.2.96 → freesolo_flash_dev-1.2.97}/flash/cli/ui/__init__.py +0 -0
- {freesolo_flash_dev-1.2.96 → freesolo_flash_dev-1.2.97}/flash/cli/ui/cost.py +0 -0
- {freesolo_flash_dev-1.2.96 → freesolo_flash_dev-1.2.97}/flash/cli/ui/env_panels.py +0 -0
- {freesolo_flash_dev-1.2.96 → freesolo_flash_dev-1.2.97}/flash/cli/ui/heartbeat.py +0 -0
- {freesolo_flash_dev-1.2.96 → freesolo_flash_dev-1.2.97}/flash/cli/ui/render.py +0 -0
- {freesolo_flash_dev-1.2.96 → freesolo_flash_dev-1.2.97}/flash/cli/ui/tables.py +0 -0
- {freesolo_flash_dev-1.2.96 → freesolo_flash_dev-1.2.97}/flash/cli/ui/tty.py +0 -0
- {freesolo_flash_dev-1.2.96 → freesolo_flash_dev-1.2.97}/flash/client/__init__.py +0 -0
- {freesolo_flash_dev-1.2.96 → freesolo_flash_dev-1.2.97}/flash/client/config.py +0 -0
- {freesolo_flash_dev-1.2.96 → freesolo_flash_dev-1.2.97}/flash/client/freesolo_api.py +0 -0
- {freesolo_flash_dev-1.2.96 → freesolo_flash_dev-1.2.97}/flash/client/http.py +0 -0
- {freesolo_flash_dev-1.2.96 → freesolo_flash_dev-1.2.97}/flash/client/runtime_secrets.py +0 -0
- {freesolo_flash_dev-1.2.96 → freesolo_flash_dev-1.2.97}/flash/client/shapes.py +0 -0
- {freesolo_flash_dev-1.2.96 → freesolo_flash_dev-1.2.97}/flash/client/specs.py +0 -0
- {freesolo_flash_dev-1.2.96 → freesolo_flash_dev-1.2.97}/flash/client/streaming.py +0 -0
- {freesolo_flash_dev-1.2.96 → freesolo_flash_dev-1.2.97}/flash/content/__init__.py +0 -0
- {freesolo_flash_dev-1.2.96 → freesolo_flash_dev-1.2.97}/flash/content/image_descriptors.py +0 -0
- {freesolo_flash_dev-1.2.96 → freesolo_flash_dev-1.2.97}/flash/content/multimodal.py +0 -0
- {freesolo_flash_dev-1.2.96 → freesolo_flash_dev-1.2.97}/flash/content/structured_outputs.py +0 -0
- {freesolo_flash_dev-1.2.96 → freesolo_flash_dev-1.2.97}/flash/content/thinking.py +0 -0
- {freesolo_flash_dev-1.2.96 → freesolo_flash_dev-1.2.97}/flash/core/__init__.py +0 -0
- {freesolo_flash_dev-1.2.96 → freesolo_flash_dev-1.2.97}/flash/core/catalog.py +0 -0
- {freesolo_flash_dev-1.2.96 → freesolo_flash_dev-1.2.97}/flash/core/grpo.py +0 -0
- {freesolo_flash_dev-1.2.96 → freesolo_flash_dev-1.2.97}/flash/core/spec.py +0 -0
- {freesolo_flash_dev-1.2.96 → freesolo_flash_dev-1.2.97}/flash/core/spec_persistence.py +0 -0
- {freesolo_flash_dev-1.2.96 → freesolo_flash_dev-1.2.97}/flash/cost/__init__.py +0 -0
- {freesolo_flash_dev-1.2.96 → freesolo_flash_dev-1.2.97}/flash/cost/analytical.py +0 -0
- {freesolo_flash_dev-1.2.96 → freesolo_flash_dev-1.2.97}/flash/cost/facts.py +0 -0
- {freesolo_flash_dev-1.2.96 → freesolo_flash_dev-1.2.97}/flash/cost/spec.py +0 -0
- {freesolo_flash_dev-1.2.96 → freesolo_flash_dev-1.2.97}/flash/cost/types.py +0 -0
- {freesolo_flash_dev-1.2.96 → freesolo_flash_dev-1.2.97}/flash/engine/__init__.py +0 -0
- {freesolo_flash_dev-1.2.96 → freesolo_flash_dev-1.2.97}/flash/engine/huggingface.py +0 -0
- {freesolo_flash_dev-1.2.96 → freesolo_flash_dev-1.2.97}/flash/engine/plan/__init__.py +0 -0
- {freesolo_flash_dev-1.2.96 → freesolo_flash_dev-1.2.97}/flash/engine/plan/kv_sizing.py +0 -0
- {freesolo_flash_dev-1.2.96 → freesolo_flash_dev-1.2.97}/flash/engine/plan/model_config_probe.py +0 -0
- {freesolo_flash_dev-1.2.96 → freesolo_flash_dev-1.2.97}/flash/engine/plan/prompt_budget.py +0 -0
- {freesolo_flash_dev-1.2.96 → freesolo_flash_dev-1.2.97}/flash/engine/plan/recipe.py +0 -0
- {freesolo_flash_dev-1.2.96 → freesolo_flash_dev-1.2.97}/flash/engine/plan/steps.py +0 -0
- {freesolo_flash_dev-1.2.96 → freesolo_flash_dev-1.2.97}/flash/engine/plan/vram.py +0 -0
- {freesolo_flash_dev-1.2.96 → freesolo_flash_dev-1.2.97}/flash/engine/profiling/__init__.py +0 -0
- {freesolo_flash_dev-1.2.96 → freesolo_flash_dev-1.2.97}/flash/engine/profiling/dataset_profile.py +0 -0
- {freesolo_flash_dev-1.2.96 → freesolo_flash_dev-1.2.97}/flash/engine/profiling/image_tokens.py +0 -0
- {freesolo_flash_dev-1.2.96 → freesolo_flash_dev-1.2.97}/flash/engine/profiling/reasoning_render.py +0 -0
- {freesolo_flash_dev-1.2.96 → freesolo_flash_dev-1.2.97}/flash/engine/profiling/sft_image_rows.py +0 -0
- {freesolo_flash_dev-1.2.96 → freesolo_flash_dev-1.2.97}/flash/engine/profiling/sft_workload.py +0 -0
- {freesolo_flash_dev-1.2.96 → freesolo_flash_dev-1.2.97}/flash/engine/profiling/tokenizer.py +0 -0
- {freesolo_flash_dev-1.2.96 → freesolo_flash_dev-1.2.97}/flash/engine/profiling/workload_profile.py +0 -0
- {freesolo_flash_dev-1.2.96 → freesolo_flash_dev-1.2.97}/flash/engine/result/__init__.py +0 -0
- {freesolo_flash_dev-1.2.96 → freesolo_flash_dev-1.2.97}/flash/engine/result/accounting.py +0 -0
- {freesolo_flash_dev-1.2.96 → freesolo_flash_dev-1.2.97}/flash/engine/result/rollout_samples.py +0 -0
- {freesolo_flash_dev-1.2.96 → freesolo_flash_dev-1.2.97}/flash/engine/worker/__init__.py +0 -0
- {freesolo_flash_dev-1.2.96 → freesolo_flash_dev-1.2.97}/flash/engine/worker/__main__.py +0 -0
- {freesolo_flash_dev-1.2.96 → freesolo_flash_dev-1.2.97}/flash/engine/worker/backend_common.py +0 -0
- {freesolo_flash_dev-1.2.96 → freesolo_flash_dev-1.2.97}/flash/engine/worker/entry/__init__.py +0 -0
- {freesolo_flash_dev-1.2.96 → freesolo_flash_dev-1.2.97}/flash/engine/worker/entry/opd.py +0 -0
- {freesolo_flash_dev-1.2.96 → freesolo_flash_dev-1.2.97}/flash/engine/worker/entry/rl.py +0 -0
- {freesolo_flash_dev-1.2.96 → freesolo_flash_dev-1.2.97}/flash/engine/worker/entry/sft.py +0 -0
- {freesolo_flash_dev-1.2.96 → freesolo_flash_dev-1.2.97}/flash/engine/worker/io/__init__.py +0 -0
- {freesolo_flash_dev-1.2.96 → freesolo_flash_dev-1.2.97}/flash/engine/worker/io/heartbeat.py +0 -0
- {freesolo_flash_dev-1.2.96 → freesolo_flash_dev-1.2.97}/flash/engine/worker/io/hf.py +0 -0
- {freesolo_flash_dev-1.2.96 → freesolo_flash_dev-1.2.97}/flash/engine/worker/io/prefetch.py +0 -0
- {freesolo_flash_dev-1.2.96 → freesolo_flash_dev-1.2.97}/flash/engine/worker/io/wandb_log.py +0 -0
- {freesolo_flash_dev-1.2.96 → freesolo_flash_dev-1.2.97}/flash/engine/worker/model/__init__.py +0 -0
- {freesolo_flash_dev-1.2.96 → freesolo_flash_dev-1.2.97}/flash/engine/worker/model/adapter.py +0 -0
- {freesolo_flash_dev-1.2.96 → freesolo_flash_dev-1.2.97}/flash/engine/worker/model/chatml_mask.py +0 -0
- {freesolo_flash_dev-1.2.96 → freesolo_flash_dev-1.2.97}/flash/engine/worker/model/decoding.py +0 -0
- {freesolo_flash_dev-1.2.96 → freesolo_flash_dev-1.2.97}/flash/engine/worker/model/lora.py +0 -0
- {freesolo_flash_dev-1.2.96 → freesolo_flash_dev-1.2.97}/flash/engine/worker/model/packing.py +0 -0
- {freesolo_flash_dev-1.2.96 → freesolo_flash_dev-1.2.97}/flash/engine/worker/opd_train.py +0 -0
- {freesolo_flash_dev-1.2.96 → freesolo_flash_dev-1.2.97}/flash/engine/worker/opd_train_runner.py +0 -0
- {freesolo_flash_dev-1.2.96 → freesolo_flash_dev-1.2.97}/flash/engine/worker/perf/__init__.py +0 -0
- {freesolo_flash_dev-1.2.96 → freesolo_flash_dev-1.2.97}/flash/engine/worker/perf/diagnostics.py +0 -0
- {freesolo_flash_dev-1.2.96 → freesolo_flash_dev-1.2.97}/flash/engine/worker/perf/lifecycle.py +0 -0
- {freesolo_flash_dev-1.2.96 → freesolo_flash_dev-1.2.97}/flash/engine/worker/perf/liger.py +0 -0
- {freesolo_flash_dev-1.2.96 → freesolo_flash_dev-1.2.97}/flash/engine/worker/perf/memory.py +0 -0
- {freesolo_flash_dev-1.2.96 → freesolo_flash_dev-1.2.97}/flash/engine/worker/rl_train.py +0 -0
- {freesolo_flash_dev-1.2.96 → freesolo_flash_dev-1.2.97}/flash/engine/worker/rl_train_runner.py +0 -0
- {freesolo_flash_dev-1.2.96 → freesolo_flash_dev-1.2.97}/flash/engine/worker/runtime/__init__.py +0 -0
- {freesolo_flash_dev-1.2.96 → freesolo_flash_dev-1.2.97}/flash/engine/worker/runtime/kernel_warmup.py +0 -0
- {freesolo_flash_dev-1.2.96 → freesolo_flash_dev-1.2.97}/flash/engine/worker/runtime/pkg_proxy.py +0 -0
- {freesolo_flash_dev-1.2.96 → freesolo_flash_dev-1.2.97}/flash/engine/worker/runtime/rng.py +0 -0
- {freesolo_flash_dev-1.2.96 → freesolo_flash_dev-1.2.97}/flash/engine/worker/score_batcher.py +0 -0
- {freesolo_flash_dev-1.2.96 → freesolo_flash_dev-1.2.97}/flash/engine/worker/sft_train.py +0 -0
- {freesolo_flash_dev-1.2.96 → freesolo_flash_dev-1.2.97}/flash/engine/worker/sft_train_runner.py +0 -0
- {freesolo_flash_dev-1.2.96 → freesolo_flash_dev-1.2.97}/flash/engine/worker/teacher/__init__.py +0 -0
- {freesolo_flash_dev-1.2.96 → freesolo_flash_dev-1.2.97}/flash/engine/worker/teacher/client.py +0 -0
- {freesolo_flash_dev-1.2.96 → freesolo_flash_dev-1.2.97}/flash/engine/worker/teacher/encoding.py +0 -0
- {freesolo_flash_dev-1.2.96 → freesolo_flash_dev-1.2.97}/flash/engine/worker/teacher/tokenizer_align.py +0 -0
- {freesolo_flash_dev-1.2.96 → freesolo_flash_dev-1.2.97}/flash/engine/worker/train/__init__.py +0 -0
- {freesolo_flash_dev-1.2.96 → freesolo_flash_dev-1.2.97}/flash/engine/worker/train/core/__init__.py +0 -0
- {freesolo_flash_dev-1.2.96 → freesolo_flash_dev-1.2.97}/flash/engine/worker/train/core/checkpoint_lifecycle.py +0 -0
- {freesolo_flash_dev-1.2.96 → freesolo_flash_dev-1.2.97}/flash/engine/worker/train/core/child/__init__.py +0 -0
- {freesolo_flash_dev-1.2.96 → freesolo_flash_dev-1.2.97}/flash/engine/worker/train/core/child/glue.py +0 -0
- {freesolo_flash_dev-1.2.96 → freesolo_flash_dev-1.2.97}/flash/engine/worker/train/core/child/runtime.py +0 -0
- {freesolo_flash_dev-1.2.96 → freesolo_flash_dev-1.2.97}/flash/engine/worker/train/core/step_timing.py +0 -0
- {freesolo_flash_dev-1.2.96 → freesolo_flash_dev-1.2.97}/flash/engine/worker/train/finalize.py +0 -0
- {freesolo_flash_dev-1.2.96 → freesolo_flash_dev-1.2.97}/flash/engine/worker/train/opd/__init__.py +0 -0
- {freesolo_flash_dev-1.2.96 → freesolo_flash_dev-1.2.97}/flash/engine/worker/train/opd/batching.py +0 -0
- {freesolo_flash_dev-1.2.96 → freesolo_flash_dev-1.2.97}/flash/engine/worker/train/opd/bridge.py +0 -0
- {freesolo_flash_dev-1.2.96 → freesolo_flash_dev-1.2.97}/flash/engine/worker/train/opd/bridge_failures.py +0 -0
- {freesolo_flash_dev-1.2.96 → freesolo_flash_dev-1.2.97}/flash/engine/worker/train/opd/child/__init__.py +0 -0
- {freesolo_flash_dev-1.2.96 → freesolo_flash_dev-1.2.97}/flash/engine/worker/train/opd/child/bridge.py +0 -0
- {freesolo_flash_dev-1.2.96 → freesolo_flash_dev-1.2.97}/flash/engine/worker/train/opd/child/entry.py +0 -0
- {freesolo_flash_dev-1.2.96 → freesolo_flash_dev-1.2.97}/flash/engine/worker/train/opd/child/multiturn.py +0 -0
- {freesolo_flash_dev-1.2.96 → freesolo_flash_dev-1.2.97}/flash/engine/worker/train/opd/child/plugin.py +0 -0
- {freesolo_flash_dev-1.2.96 → freesolo_flash_dev-1.2.97}/flash/engine/worker/train/opd/child/replay_guard.py +0 -0
- {freesolo_flash_dev-1.2.96 → freesolo_flash_dev-1.2.97}/flash/engine/worker/train/opd/child/runtime.py +0 -0
- {freesolo_flash_dev-1.2.96 → freesolo_flash_dev-1.2.97}/flash/engine/worker/train/opd/child/structured.py +0 -0
- {freesolo_flash_dev-1.2.96 → freesolo_flash_dev-1.2.97}/flash/engine/worker/train/opd/failures.py +0 -0
- {freesolo_flash_dev-1.2.96 → freesolo_flash_dev-1.2.97}/flash/engine/worker/train/opd/gkd.py +0 -0
- {freesolo_flash_dev-1.2.96 → freesolo_flash_dev-1.2.97}/flash/engine/worker/train/opd/multiturn_media.py +0 -0
- {freesolo_flash_dev-1.2.96 → freesolo_flash_dev-1.2.97}/flash/engine/worker/train/opd/multiturn_validation.py +0 -0
- {freesolo_flash_dev-1.2.96 → freesolo_flash_dev-1.2.97}/flash/engine/worker/train/opd/overrides.py +0 -0
- {freesolo_flash_dev-1.2.96 → freesolo_flash_dev-1.2.97}/flash/engine/worker/train/opd/prompts.py +0 -0
- {freesolo_flash_dev-1.2.96 → freesolo_flash_dev-1.2.97}/flash/engine/worker/train/opd/reporting.py +0 -0
- {freesolo_flash_dev-1.2.96 → freesolo_flash_dev-1.2.97}/flash/engine/worker/train/opd/scoring.py +0 -0
- {freesolo_flash_dev-1.2.96 → freesolo_flash_dev-1.2.97}/flash/engine/worker/train/opd/state.py +0 -0
- {freesolo_flash_dev-1.2.96 → freesolo_flash_dev-1.2.97}/flash/engine/worker/train/opd/validation.py +0 -0
- {freesolo_flash_dev-1.2.96 → freesolo_flash_dev-1.2.97}/flash/engine/worker/train/rl/__init__.py +0 -0
- {freesolo_flash_dev-1.2.96 → freesolo_flash_dev-1.2.97}/flash/engine/worker/train/rl/checkpoints.py +0 -0
- {freesolo_flash_dev-1.2.96 → freesolo_flash_dev-1.2.97}/flash/engine/worker/train/rl/child/__init__.py +0 -0
- {freesolo_flash_dev-1.2.96 → freesolo_flash_dev-1.2.97}/flash/engine/worker/train/rl/child/entry.py +0 -0
- {freesolo_flash_dev-1.2.96 → freesolo_flash_dev-1.2.97}/flash/engine/worker/train/rl/child/multiturn.py +0 -0
- {freesolo_flash_dev-1.2.96 → freesolo_flash_dev-1.2.97}/flash/engine/worker/train/rl/child/patches.py +0 -0
- {freesolo_flash_dev-1.2.96 → freesolo_flash_dev-1.2.97}/flash/engine/worker/train/rl/child/plugin.py +0 -0
- {freesolo_flash_dev-1.2.96 → freesolo_flash_dev-1.2.97}/flash/engine/worker/train/rl/config.py +0 -0
- {freesolo_flash_dev-1.2.96 → freesolo_flash_dev-1.2.97}/flash/engine/worker/train/rl/identity.py +0 -0
- {freesolo_flash_dev-1.2.96 → freesolo_flash_dev-1.2.97}/flash/engine/worker/train/rl/inputs.py +0 -0
- {freesolo_flash_dev-1.2.96 → freesolo_flash_dev-1.2.97}/flash/engine/worker/train/rl/multi_turn.py +0 -0
- {freesolo_flash_dev-1.2.96 → freesolo_flash_dev-1.2.97}/flash/engine/worker/train/rl/reward_module.py +0 -0
- {freesolo_flash_dev-1.2.96 → freesolo_flash_dev-1.2.97}/flash/engine/worker/train/rl/scoring.py +0 -0
- {freesolo_flash_dev-1.2.96 → freesolo_flash_dev-1.2.97}/flash/engine/worker/train/rl/single_turn.py +0 -0
- {freesolo_flash_dev-1.2.96 → freesolo_flash_dev-1.2.97}/flash/engine/worker/train/rl/verl_config.py +0 -0
- {freesolo_flash_dev-1.2.96 → freesolo_flash_dev-1.2.97}/flash/engine/worker/train/sft/__init__.py +0 -0
- {freesolo_flash_dev-1.2.96 → freesolo_flash_dev-1.2.97}/flash/engine/worker/train/sft/checkpoints.py +0 -0
- {freesolo_flash_dev-1.2.96 → freesolo_flash_dev-1.2.97}/flash/engine/worker/train/sft/child/entry.py +0 -0
- {freesolo_flash_dev-1.2.96 → freesolo_flash_dev-1.2.97}/flash/engine/worker/train/sft/child/plugin.py +0 -0
- {freesolo_flash_dev-1.2.96 → freesolo_flash_dev-1.2.97}/flash/engine/worker/train/sft/config.py +0 -0
- {freesolo_flash_dev-1.2.96 → freesolo_flash_dev-1.2.97}/flash/engine/worker/verl/__init__.py +0 -0
- {freesolo_flash_dev-1.2.96 → freesolo_flash_dev-1.2.97}/flash/engine/worker/verl/capabilities.py +0 -0
- {freesolo_flash_dev-1.2.96 → freesolo_flash_dev-1.2.97}/flash/engine/worker/verl/checkpoints.py +0 -0
- {freesolo_flash_dev-1.2.96 → freesolo_flash_dev-1.2.97}/flash/engine/worker/verl/child_io.py +0 -0
- {freesolo_flash_dev-1.2.96 → freesolo_flash_dev-1.2.97}/flash/engine/worker/verl/diagnostics.py +0 -0
- {freesolo_flash_dev-1.2.96 → freesolo_flash_dev-1.2.97}/flash/engine/worker/verl/parallelism.py +0 -0
- {freesolo_flash_dev-1.2.96 → freesolo_flash_dev-1.2.97}/flash/engine/worker/verl/parent_work.py +0 -0
- {freesolo_flash_dev-1.2.96 → freesolo_flash_dev-1.2.97}/flash/engine/worker/verl/process_census.py +0 -0
- {freesolo_flash_dev-1.2.96 → freesolo_flash_dev-1.2.97}/flash/engine/worker_entrypoint.py +0 -0
- {freesolo_flash_dev-1.2.96 → freesolo_flash_dev-1.2.97}/flash/envs/__init__.py +0 -0
- {freesolo_flash_dev-1.2.96 → freesolo_flash_dev-1.2.97}/flash/envs/adapter.py +0 -0
- {freesolo_flash_dev-1.2.96 → freesolo_flash_dev-1.2.97}/flash/envs/base.py +0 -0
- {freesolo_flash_dev-1.2.96 → freesolo_flash_dev-1.2.97}/flash/envs/cache_security.py +0 -0
- {freesolo_flash_dev-1.2.96 → freesolo_flash_dev-1.2.97}/flash/envs/dataset_selection.py +0 -0
- {freesolo_flash_dev-1.2.96 → freesolo_flash_dev-1.2.97}/flash/envs/evaluations.py +0 -0
- {freesolo_flash_dev-1.2.96 → freesolo_flash_dev-1.2.97}/flash/envs/loader.py +0 -0
- {freesolo_flash_dev-1.2.96 → freesolo_flash_dev-1.2.97}/flash/envs/namespace_listing.py +0 -0
- {freesolo_flash_dev-1.2.96 → freesolo_flash_dev-1.2.97}/flash/envs/package/__init__.py +0 -0
- {freesolo_flash_dev-1.2.96 → freesolo_flash_dev-1.2.97}/flash/envs/package/direct_tokens.py +0 -0
- {freesolo_flash_dev-1.2.96 → freesolo_flash_dev-1.2.97}/flash/envs/package/limits.py +0 -0
- {freesolo_flash_dev-1.2.96 → freesolo_flash_dev-1.2.97}/flash/envs/package/unpack.py +0 -0
- {freesolo_flash_dev-1.2.96 → freesolo_flash_dev-1.2.97}/flash/envs/pull.py +0 -0
- {freesolo_flash_dev-1.2.96 → freesolo_flash_dev-1.2.97}/flash/envs/staged.py +0 -0
- {freesolo_flash_dev-1.2.96 → freesolo_flash_dev-1.2.97}/flash/providers/__init__.py +0 -0
- {freesolo_flash_dev-1.2.96 → freesolo_flash_dev-1.2.97}/flash/providers/_lifecycle/__init__.py +0 -0
- {freesolo_flash_dev-1.2.96 → freesolo_flash_dev-1.2.97}/flash/providers/_lifecycle/auth.py +0 -0
- {freesolo_flash_dev-1.2.96 → freesolo_flash_dev-1.2.97}/flash/providers/_lifecycle/bootstrap.py +0 -0
- {freesolo_flash_dev-1.2.96 → freesolo_flash_dev-1.2.97}/flash/providers/_lifecycle/bootstrap_console.py +0 -0
- {freesolo_flash_dev-1.2.96 → freesolo_flash_dev-1.2.97}/flash/providers/_lifecycle/bootstrap_pip.py +0 -0
- {freesolo_flash_dev-1.2.96 → freesolo_flash_dev-1.2.97}/flash/providers/_lifecycle/bootstrap_secrets.py +0 -0
- {freesolo_flash_dev-1.2.96 → freesolo_flash_dev-1.2.97}/flash/providers/_lifecycle/deadline.py +0 -0
- {freesolo_flash_dev-1.2.96 → freesolo_flash_dev-1.2.97}/flash/providers/_lifecycle/host/__init__.py +0 -0
- {freesolo_flash_dev-1.2.96 → freesolo_flash_dev-1.2.97}/flash/providers/_lifecycle/host/deadline_sleep.py +0 -0
- {freesolo_flash_dev-1.2.96 → freesolo_flash_dev-1.2.97}/flash/providers/_lifecycle/host/failmark.py +0 -0
- {freesolo_flash_dev-1.2.96 → freesolo_flash_dev-1.2.97}/flash/providers/_lifecycle/host/hostlog.py +0 -0
- {freesolo_flash_dev-1.2.96 → freesolo_flash_dev-1.2.97}/flash/providers/_lifecycle/http.py +0 -0
- {freesolo_flash_dev-1.2.96 → freesolo_flash_dev-1.2.97}/flash/providers/_lifecycle/instance.py +0 -0
- {freesolo_flash_dev-1.2.96 → freesolo_flash_dev-1.2.97}/flash/providers/_lifecycle/poll.py +0 -0
- {freesolo_flash_dev-1.2.96 → freesolo_flash_dev-1.2.97}/flash/providers/_lifecycle/poll_instance.py +0 -0
- {freesolo_flash_dev-1.2.96 → freesolo_flash_dev-1.2.97}/flash/providers/_lifecycle/provider.py +0 -0
- {freesolo_flash_dev-1.2.96 → freesolo_flash_dev-1.2.97}/flash/providers/_lifecycle/terminal_artifacts.py +0 -0
- {freesolo_flash_dev-1.2.96 → freesolo_flash_dev-1.2.97}/flash/providers/_lifecycle/worker.py +0 -0
- {freesolo_flash_dev-1.2.96 → freesolo_flash_dev-1.2.97}/flash/providers/allocator.py +0 -0
- {freesolo_flash_dev-1.2.96 → freesolo_flash_dev-1.2.97}/flash/providers/artifacts/__init__.py +0 -0
- {freesolo_flash_dev-1.2.96 → freesolo_flash_dev-1.2.97}/flash/providers/artifacts/hf.py +0 -0
- {freesolo_flash_dev-1.2.96 → freesolo_flash_dev-1.2.97}/flash/providers/artifacts/preload_runpod.py +0 -0
- {freesolo_flash_dev-1.2.96 → freesolo_flash_dev-1.2.97}/flash/providers/artifacts/weight_cache.py +0 -0
- {freesolo_flash_dev-1.2.96 → freesolo_flash_dev-1.2.97}/flash/providers/base.py +0 -0
- {freesolo_flash_dev-1.2.96 → freesolo_flash_dev-1.2.97}/flash/providers/fit_errors.py +0 -0
- {freesolo_flash_dev-1.2.96 → freesolo_flash_dev-1.2.97}/flash/providers/lambda_/__init__.py +0 -0
- {freesolo_flash_dev-1.2.96 → freesolo_flash_dev-1.2.97}/flash/providers/lambda_/api.py +0 -0
- {freesolo_flash_dev-1.2.96 → freesolo_flash_dev-1.2.97}/flash/providers/lambda_/auth.py +0 -0
- {freesolo_flash_dev-1.2.96 → freesolo_flash_dev-1.2.97}/flash/providers/lambda_/gpus.py +0 -0
- {freesolo_flash_dev-1.2.96 → freesolo_flash_dev-1.2.97}/flash/providers/lambda_/jobs/__init__.py +0 -0
- {freesolo_flash_dev-1.2.96 → freesolo_flash_dev-1.2.97}/flash/providers/lambda_/jobs/builders.py +0 -0
- {freesolo_flash_dev-1.2.96 → freesolo_flash_dev-1.2.97}/flash/providers/lambda_/jobs/reap.py +0 -0
- {freesolo_flash_dev-1.2.96 → freesolo_flash_dev-1.2.97}/flash/providers/lambda_/preflight.py +0 -0
- {freesolo_flash_dev-1.2.96 → freesolo_flash_dev-1.2.97}/flash/providers/lambda_/pricing.py +0 -0
- {freesolo_flash_dev-1.2.96 → freesolo_flash_dev-1.2.97}/flash/providers/preflight.py +0 -0
- {freesolo_flash_dev-1.2.96 → freesolo_flash_dev-1.2.97}/flash/providers/realized.py +0 -0
- {freesolo_flash_dev-1.2.96 → freesolo_flash_dev-1.2.97}/flash/providers/runpod/__init__.py +0 -0
- {freesolo_flash_dev-1.2.96 → freesolo_flash_dev-1.2.97}/flash/providers/runpod/api.py +0 -0
- {freesolo_flash_dev-1.2.96 → freesolo_flash_dev-1.2.97}/flash/providers/runpod/auth.py +0 -0
- {freesolo_flash_dev-1.2.96 → freesolo_flash_dev-1.2.97}/flash/providers/runpod/cost.py +0 -0
- {freesolo_flash_dev-1.2.96 → freesolo_flash_dev-1.2.97}/flash/providers/runpod/gpus.py +0 -0
- {freesolo_flash_dev-1.2.96 → freesolo_flash_dev-1.2.97}/flash/providers/runpod/job_execution.py +0 -0
- {freesolo_flash_dev-1.2.96 → freesolo_flash_dev-1.2.97}/flash/providers/runpod/jobs.py +0 -0
- {freesolo_flash_dev-1.2.96 → freesolo_flash_dev-1.2.97}/flash/providers/runpod/preflight.py +0 -0
- {freesolo_flash_dev-1.2.96 → freesolo_flash_dev-1.2.97}/flash/providers/runpod/pricing.py +0 -0
- {freesolo_flash_dev-1.2.96 → freesolo_flash_dev-1.2.97}/flash/providers/runpod/resources.py +0 -0
- {freesolo_flash_dev-1.2.96 → freesolo_flash_dev-1.2.97}/flash/providers/runpod/serverless/__init__.py +0 -0
- {freesolo_flash_dev-1.2.96 → freesolo_flash_dev-1.2.97}/flash/providers/runpod/serverless/endpoints.py +0 -0
- {freesolo_flash_dev-1.2.96 → freesolo_flash_dev-1.2.97}/flash/providers/sharding.py +0 -0
- {freesolo_flash_dev-1.2.96 → freesolo_flash_dev-1.2.97}/flash/providers/vast/__init__.py +0 -0
- {freesolo_flash_dev-1.2.96 → freesolo_flash_dev-1.2.97}/flash/providers/vast/api.py +0 -0
- {freesolo_flash_dev-1.2.96 → freesolo_flash_dev-1.2.97}/flash/providers/vast/auth.py +0 -0
- {freesolo_flash_dev-1.2.96 → freesolo_flash_dev-1.2.97}/flash/providers/vast/jobs/__init__.py +0 -0
- {freesolo_flash_dev-1.2.96 → freesolo_flash_dev-1.2.97}/flash/providers/vast/jobs/builders.py +0 -0
- {freesolo_flash_dev-1.2.96 → freesolo_flash_dev-1.2.97}/flash/providers/vast/preflight.py +0 -0
- {freesolo_flash_dev-1.2.96 → freesolo_flash_dev-1.2.97}/flash/providers/vast/pricing.py +0 -0
- {freesolo_flash_dev-1.2.96 → freesolo_flash_dev-1.2.97}/flash/py.typed +0 -0
- {freesolo_flash_dev-1.2.96 → freesolo_flash_dev-1.2.97}/flash/runner/__init__.py +0 -0
- {freesolo_flash_dev-1.2.96 → freesolo_flash_dev-1.2.97}/flash/runner/artifacts.py +0 -0
- {freesolo_flash_dev-1.2.96 → freesolo_flash_dev-1.2.97}/flash/runner/attempts.py +0 -0
- {freesolo_flash_dev-1.2.96 → freesolo_flash_dev-1.2.97}/flash/runner/costs.py +0 -0
- {freesolo_flash_dev-1.2.96 → freesolo_flash_dev-1.2.97}/flash/runner/deadlines.py +0 -0
- {freesolo_flash_dev-1.2.96 → freesolo_flash_dev-1.2.97}/flash/runner/preparation.py +0 -0
- {freesolo_flash_dev-1.2.96 → freesolo_flash_dev-1.2.97}/flash/runner/reconciliation.py +0 -0
- {freesolo_flash_dev-1.2.96 → freesolo_flash_dev-1.2.97}/flash/runner/results/__init__.py +0 -0
- {freesolo_flash_dev-1.2.96 → freesolo_flash_dev-1.2.97}/flash/runner/results/checkpoints.py +0 -0
- {freesolo_flash_dev-1.2.96 → freesolo_flash_dev-1.2.97}/flash/runner/results/verified_revisions.py +0 -0
- {freesolo_flash_dev-1.2.96 → freesolo_flash_dev-1.2.97}/flash/runner/status.py +0 -0
- {freesolo_flash_dev-1.2.96 → freesolo_flash_dev-1.2.97}/flash/runner/submit.py +0 -0
- {freesolo_flash_dev-1.2.96 → freesolo_flash_dev-1.2.97}/flash/runner/supervise/__init__.py +0 -0
- {freesolo_flash_dev-1.2.96 → freesolo_flash_dev-1.2.97}/flash/runner/supervise/attach.py +0 -0
- {freesolo_flash_dev-1.2.96 → freesolo_flash_dev-1.2.97}/flash/runner/supervise/deploy.py +0 -0
- {freesolo_flash_dev-1.2.96 → freesolo_flash_dev-1.2.97}/flash/runner/supervise/lifecycle.py +0 -0
- {freesolo_flash_dev-1.2.96 → freesolo_flash_dev-1.2.97}/flash/runner/supervise/recovery.py +0 -0
- {freesolo_flash_dev-1.2.96 → freesolo_flash_dev-1.2.97}/flash/runner/supervise/retry_decision.py +0 -0
- {freesolo_flash_dev-1.2.96 → freesolo_flash_dev-1.2.97}/flash/runner/supervise/seed_submission.py +0 -0
- {freesolo_flash_dev-1.2.96 → freesolo_flash_dev-1.2.97}/flash/runner/supervise/transitions.py +0 -0
- {freesolo_flash_dev-1.2.96 → freesolo_flash_dev-1.2.97}/flash/runner/weight_cache.py +0 -0
- {freesolo_flash_dev-1.2.96 → freesolo_flash_dev-1.2.97}/flash/runtime_capsule/__init__.py +0 -0
- {freesolo_flash_dev-1.2.96 → freesolo_flash_dev-1.2.97}/flash/runtime_capsule/build.py +0 -0
- {freesolo_flash_dev-1.2.96 → freesolo_flash_dev-1.2.97}/flash/runtime_capsule/manifest.py +0 -0
- {freesolo_flash_dev-1.2.96 → freesolo_flash_dev-1.2.97}/flash/runtime_capsule/profiles.py +0 -0
- {freesolo_flash_dev-1.2.96 → freesolo_flash_dev-1.2.97}/flash/schema/__init__.py +0 -0
- {freesolo_flash_dev-1.2.96 → freesolo_flash_dev-1.2.97}/flash/schema/fields.py +0 -0
- {freesolo_flash_dev-1.2.96 → freesolo_flash_dev-1.2.97}/flash/serve/__init__.py +0 -0
- {freesolo_flash_dev-1.2.96 → freesolo_flash_dev-1.2.97}/flash/serve/adapter_check.py +0 -0
- {freesolo_flash_dev-1.2.96 → freesolo_flash_dev-1.2.97}/flash/serve/deploy.py +0 -0
- {freesolo_flash_dev-1.2.96 → freesolo_flash_dev-1.2.97}/flash/serve/errors.py +0 -0
- {freesolo_flash_dev-1.2.96 → freesolo_flash_dev-1.2.97}/flash/serve/export.py +0 -0
- {freesolo_flash_dev-1.2.96 → freesolo_flash_dev-1.2.97}/flash/serve/preflight.py +0 -0
- {freesolo_flash_dev-1.2.96 → freesolo_flash_dev-1.2.97}/flash/serve/responses.py +0 -0
- {freesolo_flash_dev-1.2.96 → freesolo_flash_dev-1.2.97}/flash/serve/streaming.py +0 -0
- {freesolo_flash_dev-1.2.96 → freesolo_flash_dev-1.2.97}/flash/serve/thinking.py +0 -0
- {freesolo_flash_dev-1.2.96 → freesolo_flash_dev-1.2.97}/flash/serve/urls.py +0 -0
- {freesolo_flash_dev-1.2.96 → freesolo_flash_dev-1.2.97}/flash/server/__init__.py +0 -0
- {freesolo_flash_dev-1.2.96 → freesolo_flash_dev-1.2.97}/flash/server/__main__.py +0 -0
- {freesolo_flash_dev-1.2.96 → freesolo_flash_dev-1.2.97}/flash/server/app.py +0 -0
- {freesolo_flash_dev-1.2.96 → freesolo_flash_dev-1.2.97}/flash/server/billing/__init__.py +0 -0
- {freesolo_flash_dev-1.2.96 → freesolo_flash_dev-1.2.97}/flash/server/billing/charges.py +0 -0
- {freesolo_flash_dev-1.2.96 → freesolo_flash_dev-1.2.97}/flash/server/billing/retry.py +0 -0
- {freesolo_flash_dev-1.2.96 → freesolo_flash_dev-1.2.97}/flash/server/domain/__init__.py +0 -0
- {freesolo_flash_dev-1.2.96 → freesolo_flash_dev-1.2.97}/flash/server/domain/checkpoints.py +0 -0
- {freesolo_flash_dev-1.2.96 → freesolo_flash_dev-1.2.97}/flash/server/domain/environment_registry.py +0 -0
- {freesolo_flash_dev-1.2.96 → freesolo_flash_dev-1.2.97}/flash/server/domain/envs.py +0 -0
- {freesolo_flash_dev-1.2.96 → freesolo_flash_dev-1.2.97}/flash/server/domain/projects.py +0 -0
- {freesolo_flash_dev-1.2.96 → freesolo_flash_dev-1.2.97}/flash/server/domain/reconcile.py +0 -0
- {freesolo_flash_dev-1.2.96 → freesolo_flash_dev-1.2.97}/flash/server/domain/repo_cleanup.py +0 -0
- {freesolo_flash_dev-1.2.96 → freesolo_flash_dev-1.2.97}/flash/server/domain/run_registry.py +0 -0
- {freesolo_flash_dev-1.2.96 → freesolo_flash_dev-1.2.97}/flash/server/domain/teacher_broker.py +0 -0
- {freesolo_flash_dev-1.2.96 → freesolo_flash_dev-1.2.97}/flash/server/domain/teacher_errors.py +0 -0
- {freesolo_flash_dev-1.2.96 → freesolo_flash_dev-1.2.97}/flash/server/domain/teacher_requests.py +0 -0
- {freesolo_flash_dev-1.2.96 → freesolo_flash_dev-1.2.97}/flash/server/platform/__init__.py +0 -0
- {freesolo_flash_dev-1.2.96 → freesolo_flash_dev-1.2.97}/flash/server/platform/auth.py +0 -0
- {freesolo_flash_dev-1.2.96 → freesolo_flash_dev-1.2.97}/flash/server/platform/db.py +0 -0
- {freesolo_flash_dev-1.2.96 → freesolo_flash_dev-1.2.97}/flash/server/platform/deps.py +0 -0
- {freesolo_flash_dev-1.2.96 → freesolo_flash_dev-1.2.97}/flash/server/platform/internal_client.py +0 -0
- {freesolo_flash_dev-1.2.96 → freesolo_flash_dev-1.2.97}/flash/server/platform/locks.py +0 -0
- {freesolo_flash_dev-1.2.96 → freesolo_flash_dev-1.2.97}/flash/server/platform/runtime.py +0 -0
- {freesolo_flash_dev-1.2.96 → freesolo_flash_dev-1.2.97}/flash/server/routes/__init__.py +0 -0
- {freesolo_flash_dev-1.2.96 → freesolo_flash_dev-1.2.97}/flash/server/routes/envs.py +0 -0
- {freesolo_flash_dev-1.2.96 → freesolo_flash_dev-1.2.97}/flash/server/routes/meta.py +0 -0
- {freesolo_flash_dev-1.2.96 → freesolo_flash_dev-1.2.97}/flash/server/routes/runs.py +0 -0
- {freesolo_flash_dev-1.2.96 → freesolo_flash_dev-1.2.97}/flash/server/routes/serving.py +0 -0
- {freesolo_flash_dev-1.2.96 → freesolo_flash_dev-1.2.97}/flash/server/routes/serving_completion.py +0 -0
- {freesolo_flash_dev-1.2.96 → freesolo_flash_dev-1.2.97}/flash/server/routes/serving_revisions.py +0 -0
- {freesolo_flash_dev-1.2.96 → freesolo_flash_dev-1.2.97}/flash/server/routes/serving_smoke.py +0 -0
- {freesolo_flash_dev-1.2.96 → freesolo_flash_dev-1.2.97}/flash/server/routes/teacher.py +0 -0
- {freesolo_flash_dev-1.2.96 → freesolo_flash_dev-1.2.97}/flash/source_snapshot.py +0 -0
- {freesolo_flash_dev-1.2.96 → freesolo_flash_dev-1.2.97}/flash/teacher/__init__.py +0 -0
- {freesolo_flash_dev-1.2.96 → freesolo_flash_dev-1.2.97}/flash/teacher/limits.py +0 -0
- {freesolo_flash_dev-1.2.96 → freesolo_flash_dev-1.2.97}/flash/teacher/provider_status.py +0 -0
- {freesolo_flash_dev-1.2.96 → freesolo_flash_dev-1.2.97}/flash/teacher/retry_contract.py +0 -0
- {freesolo_flash_dev-1.2.96 → freesolo_flash_dev-1.2.97}/scripts/build_dev_dist.py +0 -0
- {freesolo_flash_dev-1.2.96 → freesolo_flash_dev-1.2.97}/scripts/check_file_size.py +0 -0
- {freesolo_flash_dev-1.2.96 → freesolo_flash_dev-1.2.97}/scripts/check_function_size.py +0 -0
- {freesolo_flash_dev-1.2.96 → freesolo_flash_dev-1.2.97}/scripts/check_rollout_identity_actor.py +0 -0
- {freesolo_flash_dev-1.2.96 → freesolo_flash_dev-1.2.97}/scripts/check_verl_pin_exists.py +0 -0
- {freesolo_flash_dev-1.2.96 → freesolo_flash_dev-1.2.97}/scripts/scrub_history.sh +0 -0
- {freesolo_flash_dev-1.2.96 → freesolo_flash_dev-1.2.97}/tests/__init__.py +0 -0
- {freesolo_flash_dev-1.2.96 → freesolo_flash_dev-1.2.97}/tests/_helpers/__init__.py +0 -0
- {freesolo_flash_dev-1.2.96 → freesolo_flash_dev-1.2.97}/tests/_helpers/profile.py +0 -0
- {freesolo_flash_dev-1.2.96 → freesolo_flash_dev-1.2.97}/tests/_helpers/runner.py +0 -0
- {freesolo_flash_dev-1.2.96 → freesolo_flash_dev-1.2.97}/tests/_helpers/source_snapshot.py +0 -0
- {freesolo_flash_dev-1.2.96 → freesolo_flash_dev-1.2.97}/tests/_helpers/specs.py +0 -0
- {freesolo_flash_dev-1.2.96 → freesolo_flash_dev-1.2.97}/tests/_helpers/teacher.py +0 -0
- {freesolo_flash_dev-1.2.96 → freesolo_flash_dev-1.2.97}/tests/_helpers/vast.py +0 -0
- {freesolo_flash_dev-1.2.96 → freesolo_flash_dev-1.2.97}/tests/capture_image_sft_processor_oracle.py +0 -0
- {freesolo_flash_dev-1.2.96 → freesolo_flash_dev-1.2.97}/tests/conftest.py +0 -0
- {freesolo_flash_dev-1.2.96 → freesolo_flash_dev-1.2.97}/tests/fixtures/image_sft_processor_oracle.json +0 -0
- {freesolo_flash_dev-1.2.96 → freesolo_flash_dev-1.2.97}/tests/fixtures/qwen35_08b_target_metadata.json +0 -0
- {freesolo_flash_dev-1.2.96 → freesolo_flash_dev-1.2.97}/tests/live/__init__.py +0 -0
- {freesolo_flash_dev-1.2.96 → freesolo_flash_dev-1.2.97}/tests/live/conftest.py +0 -0
- {freesolo_flash_dev-1.2.96 → freesolo_flash_dev-1.2.97}/tests/live/test_lambda_live.py +0 -0
- {freesolo_flash_dev-1.2.96 → freesolo_flash_dev-1.2.97}/tests/live/test_runpod_live.py +0 -0
- {freesolo_flash_dev-1.2.96 → freesolo_flash_dev-1.2.97}/tests/live/test_sft_thinking_render_live.py +0 -0
- {freesolo_flash_dev-1.2.96 → freesolo_flash_dev-1.2.97}/tests/live/test_vast_live.py +0 -0
- {freesolo_flash_dev-1.2.96 → freesolo_flash_dev-1.2.97}/tests/test_accounting_coverage.py +0 -0
- {freesolo_flash_dev-1.2.96 → freesolo_flash_dev-1.2.97}/tests/test_adapter_shard_completeness.py +0 -0
- {freesolo_flash_dev-1.2.96 → freesolo_flash_dev-1.2.97}/tests/test_agent_flash_cli_contract.py +0 -0
- {freesolo_flash_dev-1.2.96 → freesolo_flash_dev-1.2.97}/tests/test_algorithms.py +0 -0
- {freesolo_flash_dev-1.2.96 → freesolo_flash_dev-1.2.97}/tests/test_allocator.py +0 -0
- {freesolo_flash_dev-1.2.96 → freesolo_flash_dev-1.2.97}/tests/test_backend_common.py +0 -0
- {freesolo_flash_dev-1.2.96 → freesolo_flash_dev-1.2.97}/tests/test_backend_jobspec_contract.py +0 -0
- {freesolo_flash_dev-1.2.96 → freesolo_flash_dev-1.2.97}/tests/test_bake_kernel_cache.py +0 -0
- {freesolo_flash_dev-1.2.96 → freesolo_flash_dev-1.2.97}/tests/test_base_model_provenance.py +0 -0
- {freesolo_flash_dev-1.2.96 → freesolo_flash_dev-1.2.97}/tests/test_billing_retry.py +0 -0
- {freesolo_flash_dev-1.2.96 → freesolo_flash_dev-1.2.97}/tests/test_build_context_contract.py +0 -0
- {freesolo_flash_dev-1.2.96 → freesolo_flash_dev-1.2.97}/tests/test_cancel_remote.py +0 -0
- {freesolo_flash_dev-1.2.96 → freesolo_flash_dev-1.2.97}/tests/test_catalog_consistency.py +0 -0
- {freesolo_flash_dev-1.2.96 → freesolo_flash_dev-1.2.97}/tests/test_catalog_only_models.py +0 -0
- {freesolo_flash_dev-1.2.96 → freesolo_flash_dev-1.2.97}/tests/test_charge_pricing.py +0 -0
- {freesolo_flash_dev-1.2.96 → freesolo_flash_dev-1.2.97}/tests/test_checkpoint_lifecycle.py +0 -0
- {freesolo_flash_dev-1.2.96 → freesolo_flash_dev-1.2.97}/tests/test_checkpoints.py +0 -0
- {freesolo_flash_dev-1.2.96 → freesolo_flash_dev-1.2.97}/tests/test_cli_credential_shadowing.py +0 -0
- {freesolo_flash_dev-1.2.96 → freesolo_flash_dev-1.2.97}/tests/test_cli_errors.py +0 -0
- {freesolo_flash_dev-1.2.96 → freesolo_flash_dev-1.2.97}/tests/test_cli_gpus_flag.py +0 -0
- {freesolo_flash_dev-1.2.96 → freesolo_flash_dev-1.2.97}/tests/test_cli_help.py +0 -0
- {freesolo_flash_dev-1.2.96 → freesolo_flash_dev-1.2.97}/tests/test_cli_main_coverage.py +0 -0
- {freesolo_flash_dev-1.2.96 → freesolo_flash_dev-1.2.97}/tests/test_cli_managed.py +0 -0
- {freesolo_flash_dev-1.2.96 → freesolo_flash_dev-1.2.97}/tests/test_cli_render_coverage.py +0 -0
- {freesolo_flash_dev-1.2.96 → freesolo_flash_dev-1.2.97}/tests/test_cli_render_theme.py +0 -0
- {freesolo_flash_dev-1.2.96 → freesolo_flash_dev-1.2.97}/tests/test_cli_traces.py +0 -0
- {freesolo_flash_dev-1.2.96 → freesolo_flash_dev-1.2.97}/tests/test_cli_wandb_warning.py +0 -0
- {freesolo_flash_dev-1.2.96 → freesolo_flash_dev-1.2.97}/tests/test_client.py +0 -0
- {freesolo_flash_dev-1.2.96 → freesolo_flash_dev-1.2.97}/tests/test_client_import_purity.py +0 -0
- {freesolo_flash_dev-1.2.96 → freesolo_flash_dev-1.2.97}/tests/test_client_server_integration.py +0 -0
- {freesolo_flash_dev-1.2.96 → freesolo_flash_dev-1.2.97}/tests/test_client_stream_reads.py +0 -0
- {freesolo_flash_dev-1.2.96 → freesolo_flash_dev-1.2.97}/tests/test_config_env_vars.py +0 -0
- {freesolo_flash_dev-1.2.96 → freesolo_flash_dev-1.2.97}/tests/test_config_overrides.py +0 -0
- {freesolo_flash_dev-1.2.96 → freesolo_flash_dev-1.2.97}/tests/test_console_upload.py +0 -0
- {freesolo_flash_dev-1.2.96 → freesolo_flash_dev-1.2.97}/tests/test_controlled_experiment_repairs.py +0 -0
- {freesolo_flash_dev-1.2.96 → freesolo_flash_dev-1.2.97}/tests/test_cost_analytical.py +0 -0
- {freesolo_flash_dev-1.2.96 → freesolo_flash_dev-1.2.97}/tests/test_cost_equation.py +0 -0
- {freesolo_flash_dev-1.2.96 → freesolo_flash_dev-1.2.97}/tests/test_cost_estimate.py +0 -0
- {freesolo_flash_dev-1.2.96 → freesolo_flash_dev-1.2.97}/tests/test_cost_hardware.py +0 -0
- {freesolo_flash_dev-1.2.96 → freesolo_flash_dev-1.2.97}/tests/test_cost_models.py +0 -0
- {freesolo_flash_dev-1.2.96 → freesolo_flash_dev-1.2.97}/tests/test_dataset_profile.py +0 -0
- {freesolo_flash_dev-1.2.96 → freesolo_flash_dev-1.2.97}/tests/test_deploy_alias_move_warning.py +0 -0
- {freesolo_flash_dev-1.2.96 → freesolo_flash_dev-1.2.97}/tests/test_deploy_latency.py +0 -0
- {freesolo_flash_dev-1.2.96 → freesolo_flash_dev-1.2.97}/tests/test_dev_channel.py +0 -0
- {freesolo_flash_dev-1.2.96 → freesolo_flash_dev-1.2.97}/tests/test_disk_gb.py +0 -0
- {freesolo_flash_dev-1.2.96 → freesolo_flash_dev-1.2.97}/tests/test_endpoint_name.py +0 -0
- {freesolo_flash_dev-1.2.96 → freesolo_flash_dev-1.2.97}/tests/test_env_cache_evict.py +0 -0
- {freesolo_flash_dev-1.2.96 → freesolo_flash_dev-1.2.97}/tests/test_env_delete.py +0 -0
- {freesolo_flash_dev-1.2.96 → freesolo_flash_dev-1.2.97}/tests/test_env_download.py +0 -0
- {freesolo_flash_dev-1.2.96 → freesolo_flash_dev-1.2.97}/tests/test_env_download_api.py +0 -0
- {freesolo_flash_dev-1.2.96 → freesolo_flash_dev-1.2.97}/tests/test_env_evaluations.py +0 -0
- {freesolo_flash_dev-1.2.96 → freesolo_flash_dev-1.2.97}/tests/test_env_list_api.py +0 -0
- {freesolo_flash_dev-1.2.96 → freesolo_flash_dev-1.2.97}/tests/test_env_list_cli.py +0 -0
- {freesolo_flash_dev-1.2.96 → freesolo_flash_dev-1.2.97}/tests/test_env_list_hub.py +0 -0
- {freesolo_flash_dev-1.2.96 → freesolo_flash_dev-1.2.97}/tests/test_env_no_install.py +0 -0
- {freesolo_flash_dev-1.2.96 → freesolo_flash_dev-1.2.97}/tests/test_env_publish.py +0 -0
- {freesolo_flash_dev-1.2.96 → freesolo_flash_dev-1.2.97}/tests/test_env_pull.py +0 -0
- {freesolo_flash_dev-1.2.96 → freesolo_flash_dev-1.2.97}/tests/test_env_pull_coverage.py +0 -0
- {freesolo_flash_dev-1.2.96 → freesolo_flash_dev-1.2.97}/tests/test_env_pull_loader_coverage.py +0 -0
- {freesolo_flash_dev-1.2.96 → freesolo_flash_dev-1.2.97}/tests/test_env_pull_managed_control_plane.py +0 -0
- {freesolo_flash_dev-1.2.96 → freesolo_flash_dev-1.2.97}/tests/test_env_push.py +0 -0
- {freesolo_flash_dev-1.2.96 → freesolo_flash_dev-1.2.97}/tests/test_env_rate_limit_resolve.py +0 -0
- {freesolo_flash_dev-1.2.96 → freesolo_flash_dev-1.2.97}/tests/test_env_ref_pinning.py +0 -0
- {freesolo_flash_dev-1.2.96 → freesolo_flash_dev-1.2.97}/tests/test_env_test.py +0 -0
- {freesolo_flash_dev-1.2.96 → freesolo_flash_dev-1.2.97}/tests/test_envs_coverage.py +0 -0
- {freesolo_flash_dev-1.2.96 → freesolo_flash_dev-1.2.97}/tests/test_export.py +0 -0
- {freesolo_flash_dev-1.2.96 → freesolo_flash_dev-1.2.97}/tests/test_flash_mvp.py +0 -0
- {freesolo_flash_dev-1.2.96 → freesolo_flash_dev-1.2.97}/tests/test_flash_worker.py +0 -0
- {freesolo_flash_dev-1.2.96 → freesolo_flash_dev-1.2.97}/tests/test_flashinfer_cache_dirs.py +0 -0
- {freesolo_flash_dev-1.2.96 → freesolo_flash_dev-1.2.97}/tests/test_freesolo_api_transport.py +0 -0
- {freesolo_flash_dev-1.2.96 → freesolo_flash_dev-1.2.97}/tests/test_fused_expert_warmstart.py +0 -0
- {freesolo_flash_dev-1.2.96 → freesolo_flash_dev-1.2.97}/tests/test_github_urlopen_retry.py +0 -0
- {freesolo_flash_dev-1.2.96 → freesolo_flash_dev-1.2.97}/tests/test_gpu_type_single_field.py +0 -0
- {freesolo_flash_dev-1.2.96 → freesolo_flash_dev-1.2.97}/tests/test_gpus.py +0 -0
- {freesolo_flash_dev-1.2.96 → freesolo_flash_dev-1.2.97}/tests/test_grpo_params.py +0 -0
- {freesolo_flash_dev-1.2.96 → freesolo_flash_dev-1.2.97}/tests/test_grpo_process_census.py +0 -0
- {freesolo_flash_dev-1.2.96 → freesolo_flash_dev-1.2.97}/tests/test_grpo_resident_sizing.py +0 -0
- {freesolo_flash_dev-1.2.96 → freesolo_flash_dev-1.2.97}/tests/test_grpo_reward_batching.py +0 -0
- {freesolo_flash_dev-1.2.96 → freesolo_flash_dev-1.2.97}/tests/test_grpo_rollout_contract.py +0 -0
- {freesolo_flash_dev-1.2.96 → freesolo_flash_dev-1.2.97}/tests/test_grpo_rollout_identity.py +0 -0
- {freesolo_flash_dev-1.2.96 → freesolo_flash_dev-1.2.97}/tests/test_health_liveness.py +0 -0
- {freesolo_flash_dev-1.2.96 → freesolo_flash_dev-1.2.97}/tests/test_hf_retry.py +0 -0
- {freesolo_flash_dev-1.2.96 → freesolo_flash_dev-1.2.97}/tests/test_idle_endpoint_reaper.py +0 -0
- {freesolo_flash_dev-1.2.96 → freesolo_flash_dev-1.2.97}/tests/test_image_environment_capability.py +0 -0
- {freesolo_flash_dev-1.2.96 → freesolo_flash_dev-1.2.97}/tests/test_image_incremental_processor.py +0 -0
- {freesolo_flash_dev-1.2.96 → freesolo_flash_dev-1.2.97}/tests/test_image_sft_markers.py +0 -0
- {freesolo_flash_dev-1.2.96 → freesolo_flash_dev-1.2.97}/tests/test_image_sft_processor_parity.py +0 -0
- {freesolo_flash_dev-1.2.96 → freesolo_flash_dev-1.2.97}/tests/test_image_tokens.py +0 -0
- {freesolo_flash_dev-1.2.96 → freesolo_flash_dev-1.2.97}/tests/test_infisical_secrets.py +0 -0
- {freesolo_flash_dev-1.2.96 → freesolo_flash_dev-1.2.97}/tests/test_instance_bootstrap_coverage.py +0 -0
- {freesolo_flash_dev-1.2.96 → freesolo_flash_dev-1.2.97}/tests/test_internal_client.py +0 -0
- {freesolo_flash_dev-1.2.96 → freesolo_flash_dev-1.2.97}/tests/test_jobs.py +0 -0
- {freesolo_flash_dev-1.2.96 → freesolo_flash_dev-1.2.97}/tests/test_kernel_cache.py +0 -0
- {freesolo_flash_dev-1.2.96 → freesolo_flash_dev-1.2.97}/tests/test_kernel_fingerprint.py +0 -0
- {freesolo_flash_dev-1.2.96 → freesolo_flash_dev-1.2.97}/tests/test_kv_util.py +0 -0
- {freesolo_flash_dev-1.2.96 → freesolo_flash_dev-1.2.97}/tests/test_lambda_api_coverage.py +0 -0
- {freesolo_flash_dev-1.2.96 → freesolo_flash_dev-1.2.97}/tests/test_lambda_runner.py +0 -0
- {freesolo_flash_dev-1.2.96 → freesolo_flash_dev-1.2.97}/tests/test_logging.py +0 -0
- {freesolo_flash_dev-1.2.96 → freesolo_flash_dev-1.2.97}/tests/test_login_perms.py +0 -0
- {freesolo_flash_dev-1.2.96 → freesolo_flash_dev-1.2.97}/tests/test_lora_rank_coverage.py +0 -0
- {freesolo_flash_dev-1.2.96 → freesolo_flash_dev-1.2.97}/tests/test_lora_rank_nested_rung.py +0 -0
- {freesolo_flash_dev-1.2.96 → freesolo_flash_dev-1.2.97}/tests/test_lora_rank_preflight.py +0 -0
- {freesolo_flash_dev-1.2.96 → freesolo_flash_dev-1.2.97}/tests/test_lora_targeting.py +0 -0
- {freesolo_flash_dev-1.2.96 → freesolo_flash_dev-1.2.97}/tests/test_lora_targeting_pinned_verl.py +0 -0
- {freesolo_flash_dev-1.2.96 → freesolo_flash_dev-1.2.97}/tests/test_managed_config_fields.py +0 -0
- {freesolo_flash_dev-1.2.96 → freesolo_flash_dev-1.2.97}/tests/test_managed_hf_repo.py +0 -0
- {freesolo_flash_dev-1.2.96 → freesolo_flash_dev-1.2.97}/tests/test_metrics_schema_agent_contract.py +0 -0
- {freesolo_flash_dev-1.2.96 → freesolo_flash_dev-1.2.97}/tests/test_mig_guard.py +0 -0
- {freesolo_flash_dev-1.2.96 → freesolo_flash_dev-1.2.97}/tests/test_multi_gpu_gate.py +0 -0
- {freesolo_flash_dev-1.2.96 → freesolo_flash_dev-1.2.97}/tests/test_multimodal_training.py +0 -0
- {freesolo_flash_dev-1.2.96 → freesolo_flash_dev-1.2.97}/tests/test_named_reward_metrics.py +0 -0
- {freesolo_flash_dev-1.2.96 → freesolo_flash_dev-1.2.97}/tests/test_oom_escalate_gpu.py +0 -0
- {freesolo_flash_dev-1.2.96 → freesolo_flash_dev-1.2.97}/tests/test_opd.py +0 -0
- {freesolo_flash_dev-1.2.96 → freesolo_flash_dev-1.2.97}/tests/test_opd_limits.py +0 -0
- {freesolo_flash_dev-1.2.96 → freesolo_flash_dev-1.2.97}/tests/test_opd_multiturn_eos_boundary.py +0 -0
- {freesolo_flash_dev-1.2.96 → freesolo_flash_dev-1.2.97}/tests/test_opd_multiturn_failure_exit.py +0 -0
- {freesolo_flash_dev-1.2.96 → freesolo_flash_dev-1.2.97}/tests/test_opd_replay_guard.py +0 -0
- {freesolo_flash_dev-1.2.96 → freesolo_flash_dev-1.2.97}/tests/test_opd_resume_safety.py +0 -0
- {freesolo_flash_dev-1.2.96 → freesolo_flash_dev-1.2.97}/tests/test_opd_train.py +0 -0
- {freesolo_flash_dev-1.2.96 → freesolo_flash_dev-1.2.97}/tests/test_orchestrator_flash.py +0 -0
- {freesolo_flash_dev-1.2.96 → freesolo_flash_dev-1.2.97}/tests/test_packing.py +0 -0
- {freesolo_flash_dev-1.2.96 → freesolo_flash_dev-1.2.97}/tests/test_packing_coverage.py +0 -0
- {freesolo_flash_dev-1.2.96 → freesolo_flash_dev-1.2.97}/tests/test_parasail_teacher.py +0 -0
- {freesolo_flash_dev-1.2.96 → freesolo_flash_dev-1.2.97}/tests/test_persisted_spec_envelope.py +0 -0
- {freesolo_flash_dev-1.2.96 → freesolo_flash_dev-1.2.97}/tests/test_poll_helpers.py +0 -0
- {freesolo_flash_dev-1.2.96 → freesolo_flash_dev-1.2.97}/tests/test_preflight.py +0 -0
- {freesolo_flash_dev-1.2.96 → freesolo_flash_dev-1.2.97}/tests/test_projects.py +0 -0
- {freesolo_flash_dev-1.2.96 → freesolo_flash_dev-1.2.97}/tests/test_prompt_budget.py +0 -0
- {freesolo_flash_dev-1.2.96 → freesolo_flash_dev-1.2.97}/tests/test_provider_preflight_coverage.py +0 -0
- {freesolo_flash_dev-1.2.96 → freesolo_flash_dev-1.2.97}/tests/test_provider_routing.py +0 -0
- {freesolo_flash_dev-1.2.96 → freesolo_flash_dev-1.2.97}/tests/test_provider_teardown_robustness.py +0 -0
- {freesolo_flash_dev-1.2.96 → freesolo_flash_dev-1.2.97}/tests/test_providers_symmetry.py +0 -0
- {freesolo_flash_dev-1.2.96 → freesolo_flash_dev-1.2.97}/tests/test_realized_cost.py +0 -0
- {freesolo_flash_dev-1.2.96 → freesolo_flash_dev-1.2.97}/tests/test_repo_cleanup.py +0 -0
- {freesolo_flash_dev-1.2.96 → freesolo_flash_dev-1.2.97}/tests/test_resolve_params_b.py +0 -0
- {freesolo_flash_dev-1.2.96 → freesolo_flash_dev-1.2.97}/tests/test_resume_on_retry.py +0 -0
- {freesolo_flash_dev-1.2.96 → freesolo_flash_dev-1.2.97}/tests/test_rl_train.py +0 -0
- {freesolo_flash_dev-1.2.96 → freesolo_flash_dev-1.2.97}/tests/test_rollout_samples.py +0 -0
- {freesolo_flash_dev-1.2.96 → freesolo_flash_dev-1.2.97}/tests/test_runmgmt.py +0 -0
- {freesolo_flash_dev-1.2.96 → freesolo_flash_dev-1.2.97}/tests/test_runpod_api_delete.py +0 -0
- {freesolo_flash_dev-1.2.96 → freesolo_flash_dev-1.2.97}/tests/test_runpod_key_fingerprint.py +0 -0
- {freesolo_flash_dev-1.2.96 → freesolo_flash_dev-1.2.97}/tests/test_runpod_key_waterfall.py +0 -0
- {freesolo_flash_dev-1.2.96 → freesolo_flash_dev-1.2.97}/tests/test_runtime_capsule.py +0 -0
- {freesolo_flash_dev-1.2.96 → freesolo_flash_dev-1.2.97}/tests/test_serve.py +0 -0
- {freesolo_flash_dev-1.2.96 → freesolo_flash_dev-1.2.97}/tests/test_serve_reasoning_content.py +0 -0
- {freesolo_flash_dev-1.2.96 → freesolo_flash_dev-1.2.97}/tests/test_server_api.py +0 -0
- {freesolo_flash_dev-1.2.96 → freesolo_flash_dev-1.2.97}/tests/test_server_app_coverage.py +0 -0
- {freesolo_flash_dev-1.2.96 → freesolo_flash_dev-1.2.97}/tests/test_server_auth_singleflight.py +0 -0
- {freesolo_flash_dev-1.2.96 → freesolo_flash_dev-1.2.97}/tests/test_server_billing.py +0 -0
- {freesolo_flash_dev-1.2.96 → freesolo_flash_dev-1.2.97}/tests/test_server_checkpoints_coverage.py +0 -0
- {freesolo_flash_dev-1.2.96 → freesolo_flash_dev-1.2.97}/tests/test_server_db.py +0 -0
- {freesolo_flash_dev-1.2.96 → freesolo_flash_dev-1.2.97}/tests/test_server_envs_coverage.py +0 -0
- {freesolo_flash_dev-1.2.96 → freesolo_flash_dev-1.2.97}/tests/test_server_locks_coverage.py +0 -0
- {freesolo_flash_dev-1.2.96 → freesolo_flash_dev-1.2.97}/tests/test_server_standalone.py +0 -0
- {freesolo_flash_dev-1.2.96 → freesolo_flash_dev-1.2.97}/tests/test_serving_context_preflight.py +0 -0
- {freesolo_flash_dev-1.2.96 → freesolo_flash_dev-1.2.97}/tests/test_serving_contract.py +0 -0
- {freesolo_flash_dev-1.2.96 → freesolo_flash_dev-1.2.97}/tests/test_serving_schema_coverage.py +0 -0
- {freesolo_flash_dev-1.2.96 → freesolo_flash_dev-1.2.97}/tests/test_sft_chunked_nll.py +0 -0
- {freesolo_flash_dev-1.2.96 → freesolo_flash_dev-1.2.97}/tests/test_sft_example_selection.py +0 -0
- {freesolo_flash_dev-1.2.96 → freesolo_flash_dev-1.2.97}/tests/test_sft_gc_off.py +0 -0
- {freesolo_flash_dev-1.2.96 → freesolo_flash_dev-1.2.97}/tests/test_sft_max_context.py +0 -0
- {freesolo_flash_dev-1.2.96 → freesolo_flash_dev-1.2.97}/tests/test_sft_startup_block.py +0 -0
- {freesolo_flash_dev-1.2.96 → freesolo_flash_dev-1.2.97}/tests/test_sft_train.py +0 -0
- {freesolo_flash_dev-1.2.96 → freesolo_flash_dev-1.2.97}/tests/test_sft_workload.py +0 -0
- {freesolo_flash_dev-1.2.96 → freesolo_flash_dev-1.2.97}/tests/test_source_attestation_flow.py +0 -0
- {freesolo_flash_dev-1.2.96 → freesolo_flash_dev-1.2.97}/tests/test_source_snapshot.py +0 -0
- {freesolo_flash_dev-1.2.96 → freesolo_flash_dev-1.2.97}/tests/test_spec_and_validation.py +0 -0
- {freesolo_flash_dev-1.2.96 → freesolo_flash_dev-1.2.97}/tests/test_spec_contract_bytes.py +0 -0
- {freesolo_flash_dev-1.2.96 → freesolo_flash_dev-1.2.97}/tests/test_staged_environment.py +0 -0
- {freesolo_flash_dev-1.2.96 → freesolo_flash_dev-1.2.97}/tests/test_step_floor.py +0 -0
- {freesolo_flash_dev-1.2.96 → freesolo_flash_dev-1.2.97}/tests/test_step_metrics.py +0 -0
- {freesolo_flash_dev-1.2.96 → freesolo_flash_dev-1.2.97}/tests/test_step_timing.py +0 -0
- {freesolo_flash_dev-1.2.96 → freesolo_flash_dev-1.2.97}/tests/test_structured_outputs.py +0 -0
- {freesolo_flash_dev-1.2.96 → freesolo_flash_dev-1.2.97}/tests/test_teacher_broker.py +0 -0
- {freesolo_flash_dev-1.2.96 → freesolo_flash_dev-1.2.97}/tests/test_teacher_encoding_contract.py +0 -0
- {freesolo_flash_dev-1.2.96 → freesolo_flash_dev-1.2.97}/tests/test_terminal_artifacts.py +0 -0
- {freesolo_flash_dev-1.2.96 → freesolo_flash_dev-1.2.97}/tests/test_thinking_config.py +0 -0
- {freesolo_flash_dev-1.2.96 → freesolo_flash_dev-1.2.97}/tests/test_train_context_preflight.py +0 -0
- {freesolo_flash_dev-1.2.96 → freesolo_flash_dev-1.2.97}/tests/test_training_controls.py +0 -0
- {freesolo_flash_dev-1.2.96 → freesolo_flash_dev-1.2.97}/tests/test_type_comment_prose.py +0 -0
- {freesolo_flash_dev-1.2.96 → freesolo_flash_dev-1.2.97}/tests/test_vast_api.py +0 -0
- {freesolo_flash_dev-1.2.96 → freesolo_flash_dev-1.2.97}/tests/test_vast_api_coverage.py +0 -0
- {freesolo_flash_dev-1.2.96 → freesolo_flash_dev-1.2.97}/tests/test_vast_offers.py +0 -0
- {freesolo_flash_dev-1.2.96 → freesolo_flash_dev-1.2.97}/tests/test_vast_provider_coverage.py +0 -0
- {freesolo_flash_dev-1.2.96 → freesolo_flash_dev-1.2.97}/tests/test_vast_runner.py +0 -0
- {freesolo_flash_dev-1.2.96 → freesolo_flash_dev-1.2.97}/tests/test_verified_revisions.py +0 -0
- {freesolo_flash_dev-1.2.96 → freesolo_flash_dev-1.2.97}/tests/test_verifiers.py +0 -0
- {freesolo_flash_dev-1.2.96 → freesolo_flash_dev-1.2.97}/tests/test_verl_checkpoint_export.py +0 -0
- {freesolo_flash_dev-1.2.96 → freesolo_flash_dev-1.2.97}/tests/test_verl_child_plugins.py +0 -0
- {freesolo_flash_dev-1.2.96 → freesolo_flash_dev-1.2.97}/tests/test_verl_silence_watchdog.py +0 -0
- {freesolo_flash_dev-1.2.96 → freesolo_flash_dev-1.2.97}/tests/test_version.py +0 -0
- {freesolo_flash_dev-1.2.96 → freesolo_flash_dev-1.2.97}/tests/test_vl_warmstart_adapter_keys.py +0 -0
- {freesolo_flash_dev-1.2.96 → freesolo_flash_dev-1.2.97}/tests/test_vram_architecture.py +0 -0
- {freesolo_flash_dev-1.2.96 → freesolo_flash_dev-1.2.97}/tests/test_wandb_link.py +0 -0
- {freesolo_flash_dev-1.2.96 → freesolo_flash_dev-1.2.97}/tests/test_wandb_naming.py +0 -0
- {freesolo_flash_dev-1.2.96 → freesolo_flash_dev-1.2.97}/tests/test_warmstart_adapter_download.py +0 -0
- {freesolo_flash_dev-1.2.96 → freesolo_flash_dev-1.2.97}/tests/test_warmstart_cross_repo.py +0 -0
- {freesolo_flash_dev-1.2.96 → freesolo_flash_dev-1.2.97}/tests/test_warmstart_error_attribution.py +0 -0
- {freesolo_flash_dev-1.2.96 → freesolo_flash_dev-1.2.97}/tests/test_warmstart_image_adapters.py +0 -0
- {freesolo_flash_dev-1.2.96 → freesolo_flash_dev-1.2.97}/tests/test_weight_cache.py +0 -0
- {freesolo_flash_dev-1.2.96 → freesolo_flash_dev-1.2.97}/tests/test_worker_dryrun.py +0 -0
- {freesolo_flash_dev-1.2.96 → freesolo_flash_dev-1.2.97}/tests/test_worker_hardexit.py +0 -0
- {freesolo_flash_dev-1.2.96 → freesolo_flash_dev-1.2.97}/tests/test_worker_image.py +0 -0
- {freesolo_flash_dev-1.2.96 → freesolo_flash_dev-1.2.97}/tests/test_worker_init_heartbeat.py +0 -0
- {freesolo_flash_dev-1.2.96 → freesolo_flash_dev-1.2.97}/tests/test_worker_stack.py +0 -0
- {freesolo_flash_dev-1.2.96 → freesolo_flash_dev-1.2.97}/tests/test_worker_thinking.py +0 -0
- {freesolo_flash_dev-1.2.96 → freesolo_flash_dev-1.2.97}/tests/test_workflow_contracts.py +0 -0
- {freesolo_flash_dev-1.2.96 → freesolo_flash_dev-1.2.97}/tests/test_workload_profile.py +0 -0
- {freesolo_flash_dev-1.2.96 → freesolo_flash_dev-1.2.97}/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.97
|
|
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
|
|
@@ -7,6 +7,7 @@ import os
|
|
|
7
7
|
import sys
|
|
8
8
|
import time
|
|
9
9
|
import uuid
|
|
10
|
+
from typing import NamedTuple
|
|
10
11
|
|
|
11
12
|
from flash import __version__
|
|
12
13
|
from flash._internal.channel import BRAND_NAME, CLI_NAME
|
|
@@ -424,6 +425,8 @@ def cmd_train(args) -> int:
|
|
|
424
425
|
)
|
|
425
426
|
else:
|
|
426
427
|
print(json.dumps(status, indent=2))
|
|
428
|
+
if spec.algorithm == "sft":
|
|
429
|
+
_print_published_sft_environment_note(status, spec)
|
|
427
430
|
_print_unpacked_batch_warning(status, spec) # after the payload, so stdout stays parseable
|
|
428
431
|
print_status_prompt_budget_warning(status)
|
|
429
432
|
_print_reasoning_loss_warning(status)
|
|
@@ -599,12 +602,17 @@ def _log_follow_metric_rows(status: dict | None, seen_steps: set) -> list[str]:
|
|
|
599
602
|
return rows
|
|
600
603
|
|
|
601
604
|
|
|
602
|
-
|
|
603
|
-
|
|
605
|
+
class _LogPollResult(NamedTuple):
|
|
606
|
+
state: str
|
|
607
|
+
printed_any: bool
|
|
608
|
+
live_attempt: int | None
|
|
604
609
|
|
|
605
|
-
|
|
610
|
+
|
|
611
|
+
def _poll_logs(client: ApiClient, run_id: str, interval: float) -> _LogPollResult:
|
|
612
|
+
"""Stream logs until terminal and return the final state, output, and attempt snapshot."""
|
|
606
613
|
offset = 0
|
|
607
614
|
printed_any = False
|
|
615
|
+
attempt: int | None = None
|
|
608
616
|
last_progress: str | None = None
|
|
609
617
|
seen_metric_steps: set = set()
|
|
610
618
|
spinner = _LogFollowSpinner(run_id)
|
|
@@ -620,6 +628,7 @@ def _poll_logs(client: ApiClient, run_id: str, interval: float) -> tuple[str, bo
|
|
|
620
628
|
# from the run status endpoint. The log page's embedded state is only a fallback for
|
|
621
629
|
# older servers or test doubles.
|
|
622
630
|
status = client.get_run(run_id)
|
|
631
|
+
attempt = render.live_attempt(status) if isinstance(status, dict) else attempt
|
|
623
632
|
state, progress = _log_follow_progress(status, str(page.get("state") or ""))
|
|
624
633
|
metric_rows = _log_follow_metric_rows(status, seen_metric_steps)
|
|
625
634
|
if metric_rows:
|
|
@@ -628,7 +637,7 @@ def _poll_logs(client: ApiClient, run_id: str, interval: float) -> tuple[str, bo
|
|
|
628
637
|
print(row, file=sys.stderr, flush=True)
|
|
629
638
|
if state in _CLI_DONE_STATES:
|
|
630
639
|
spinner.clear()
|
|
631
|
-
return state, printed_any
|
|
640
|
+
return _LogPollResult(state, printed_any, attempt)
|
|
632
641
|
if not spinner.enabled and progress != last_progress:
|
|
633
642
|
print(f"status: {progress}", file=sys.stderr, flush=True)
|
|
634
643
|
last_progress = progress
|
|
@@ -677,12 +686,12 @@ def _print_detached_note(run_id: str) -> None:
|
|
|
677
686
|
def _follow_run(client: ApiClient, run_id: str) -> int:
|
|
678
687
|
"""Poll logs until the run reaches a terminal state, then print the final status."""
|
|
679
688
|
try:
|
|
680
|
-
|
|
689
|
+
result = _poll_logs(client, run_id, interval=2.0)
|
|
681
690
|
except KeyboardInterrupt:
|
|
682
691
|
_print_detached_note(run_id)
|
|
683
692
|
return 130
|
|
684
693
|
print(_render_status(client.get_run(run_id)))
|
|
685
|
-
return 0 if state in _OK_STATES else 1
|
|
694
|
+
return 0 if result.state in _OK_STATES else 1
|
|
686
695
|
|
|
687
696
|
|
|
688
697
|
def _follow_status(
|
|
@@ -710,16 +719,23 @@ def cmd_log(args) -> int:
|
|
|
710
719
|
client = client_from_config()
|
|
711
720
|
if getattr(args, "follow", False):
|
|
712
721
|
try:
|
|
713
|
-
|
|
722
|
+
result = _poll_logs(client, args.run_id, interval=2.0)
|
|
714
723
|
except KeyboardInterrupt:
|
|
715
724
|
_print_detached_note(args.run_id)
|
|
716
725
|
return 130
|
|
717
|
-
|
|
718
|
-
|
|
726
|
+
sections = _worker_sections(client, args.run_id)
|
|
727
|
+
_print_worker_output(
|
|
728
|
+
sections,
|
|
729
|
+
printed_any=result.printed_any,
|
|
730
|
+
current_attempt=result.live_attempt,
|
|
731
|
+
)
|
|
732
|
+
return 0 if result.state in _OK_STATES else 1
|
|
719
733
|
text = str(client.get_logs(args.run_id, offset=0).get("logs") or "")
|
|
720
734
|
if text:
|
|
721
735
|
print(text, end="" if text.endswith("\n") else "\n")
|
|
722
|
-
|
|
736
|
+
sections = _worker_sections(client, args.run_id)
|
|
737
|
+
attempt = _snapshot_live_attempt(client, args.run_id) if sections else None
|
|
738
|
+
_print_worker_output(sections, printed_any=bool(text), current_attempt=attempt)
|
|
723
739
|
return 0
|
|
724
740
|
|
|
725
741
|
|
|
@@ -953,6 +969,7 @@ from flash.cli.commands.train_cost import ( # noqa: E402,F401
|
|
|
953
969
|
_cmd_train_cost,
|
|
954
970
|
_cmd_train_cost_offline,
|
|
955
971
|
_cmd_train_cost_sft,
|
|
972
|
+
_print_published_sft_environment_note,
|
|
956
973
|
_print_reasoning_loss_warning,
|
|
957
974
|
_print_sft_cost,
|
|
958
975
|
_print_train_schema_compatibility,
|
|
@@ -961,9 +978,11 @@ from flash.cli.commands.train_cost import ( # noqa: E402,F401
|
|
|
961
978
|
_warn_if_wandb_requested_without_key,
|
|
962
979
|
)
|
|
963
980
|
|
|
964
|
-
# re-exported
|
|
981
|
+
# re-exported because cmd_log and focused cli tests address these through the command package.
|
|
965
982
|
from flash.cli.commands.worker_output import ( # noqa: E402,F401
|
|
966
983
|
_artifact_attempt,
|
|
967
984
|
_print_worker_output,
|
|
985
|
+
_snapshot_live_attempt,
|
|
968
986
|
_worker_section_name,
|
|
987
|
+
_worker_sections,
|
|
969
988
|
)
|
|
@@ -114,8 +114,19 @@ def _client_train_schema(authored_train_keys: frozenset[str]) -> dict:
|
|
|
114
114
|
}
|
|
115
115
|
|
|
116
116
|
|
|
117
|
+
def _has_inline_records(spec) -> bool:
|
|
118
|
+
"""Whether this config supplied its SFT rows inline rather than from the resolved package.
|
|
119
|
+
|
|
120
|
+
One predicate for every surface that attributes the counts -- the cost rows and the provenance
|
|
121
|
+
note sit within a few lines of each other, so disagreeing about where the data came from would
|
|
122
|
+
print two contradictory answers in one quote.
|
|
123
|
+
"""
|
|
124
|
+
params = getattr(getattr(spec, "environment", None), "params", None)
|
|
125
|
+
return isinstance(params, dict) and params.get("records") is not None
|
|
126
|
+
|
|
127
|
+
|
|
117
128
|
def _sft_cost_rows(spec, profile: dict) -> list[tuple[str, str | None]]:
|
|
118
|
-
"""Rows describing the packaged-dataset estimate behind an SFT quote.
|
|
129
|
+
"""Rows describing the published packaged-dataset estimate behind an SFT quote.
|
|
119
130
|
|
|
120
131
|
Only aggregates the server actually returned are shown. A field that is absent is dropped
|
|
121
132
|
rather than defaulted, so the panel never reports a count the profile did not compute.
|
|
@@ -125,19 +136,34 @@ def _sft_cost_rows(spec, profile: dict) -> list[tuple[str, str | None]]:
|
|
|
125
136
|
value = profile.get(key)
|
|
126
137
|
return value if isinstance(value, int) and not isinstance(value, bool) else None
|
|
127
138
|
|
|
139
|
+
def text(key: str) -> str:
|
|
140
|
+
value = profile.get(key)
|
|
141
|
+
return value.strip() if isinstance(value, str) else ""
|
|
142
|
+
|
|
128
143
|
steps = count("authoritative_steps")
|
|
144
|
+
source = count("source_examples")
|
|
129
145
|
retained, selected = count("retained_examples"), count("selected_examples")
|
|
130
146
|
dropped = count("dropped_examples")
|
|
131
147
|
compute, supervised = (
|
|
132
148
|
count("authoritative_compute_tokens"),
|
|
133
149
|
count("authoritative_supervised_tokens"),
|
|
134
150
|
)
|
|
135
|
-
packing =
|
|
136
|
-
architecture =
|
|
137
|
-
|
|
151
|
+
packing = text("packing_mode")
|
|
152
|
+
architecture = text("architecture_mode")
|
|
153
|
+
environment_id = text("environment_id")
|
|
154
|
+
environment_revision = text("environment_revision")
|
|
155
|
+
digest = text("content_digest")
|
|
156
|
+
# inline `[environment.params] records` supply the rows from the request body, so the resolved
|
|
157
|
+
# package contributed the environment but not the dataset. labelling those counts "published
|
|
158
|
+
# copy" names a source they did not come from. one adjective decides all three rows, so they
|
|
159
|
+
# cannot describe the same quote two different ways.
|
|
160
|
+
inline_records = _has_inline_records(spec)
|
|
161
|
+
origin = "inline records" if inline_records else "published copy"
|
|
162
|
+
resolved = "resolved" if inline_records else "published"
|
|
138
163
|
examples = None
|
|
139
164
|
if retained is not None and selected is not None:
|
|
140
|
-
examples = f"{retained:,} trained of {selected:,} selected"
|
|
165
|
+
examples = f"{retained:,} trained of {selected:,} selected from "
|
|
166
|
+
examples += f"{source:,} source rows in {origin}" if source is not None else origin
|
|
141
167
|
if dropped:
|
|
142
168
|
examples += f" ({dropped:,} dropped)"
|
|
143
169
|
tokens = None
|
|
@@ -147,10 +173,15 @@ def _sft_cost_rows(spec, profile: dict) -> list[tuple[str, str | None]]:
|
|
|
147
173
|
tokens += f", {supervised:,} supervised"
|
|
148
174
|
return [
|
|
149
175
|
("run", f"{spec.model} [SFT{f', {steps} steps' if steps is not None else ''}]"),
|
|
176
|
+
("env", f"{resolved} environment {environment_id}" if environment_id else None),
|
|
177
|
+
(
|
|
178
|
+
"revision",
|
|
179
|
+
f"{environment_revision[:12]} ({resolved} commit)" if environment_revision else None,
|
|
180
|
+
),
|
|
150
181
|
("workload", f"{packing} ({architecture})" if packing and architecture else None),
|
|
151
182
|
("examples", examples),
|
|
152
183
|
("tokens", tokens),
|
|
153
|
-
("
|
|
184
|
+
("digest", digest[:12] or None),
|
|
154
185
|
]
|
|
155
186
|
|
|
156
187
|
|
|
@@ -218,6 +249,71 @@ def _print_reasoning_loss_warning(status: object) -> None:
|
|
|
218
249
|
print(render.warn(message) if render.styled() else f"warning: {message}", file=sys.stderr)
|
|
219
250
|
|
|
220
251
|
|
|
252
|
+
def _print_published_sft_environment_note(status: object, spec) -> None:
|
|
253
|
+
"""Warn when SFT counts came from a published managed or GitHub environment."""
|
|
254
|
+
if _has_inline_records(spec):
|
|
255
|
+
return
|
|
256
|
+
|
|
257
|
+
profile = status.get("workload_profile") if isinstance(status, dict) else None
|
|
258
|
+
if not isinstance(profile, dict):
|
|
259
|
+
return
|
|
260
|
+
environment_id = profile.get("environment_id")
|
|
261
|
+
revision = profile.get("environment_revision")
|
|
262
|
+
if not isinstance(environment_id, str) or not environment_id.strip():
|
|
263
|
+
return
|
|
264
|
+
if not isinstance(revision, str) or not revision.strip():
|
|
265
|
+
return
|
|
266
|
+
|
|
267
|
+
environment_id = environment_id.strip()
|
|
268
|
+
advice = _republish_advice(environment_id)
|
|
269
|
+
if advice is None:
|
|
270
|
+
return
|
|
271
|
+
|
|
272
|
+
source = profile.get("source_examples")
|
|
273
|
+
source_suffix = (
|
|
274
|
+
f" ({source:,} source rows)"
|
|
275
|
+
if isinstance(source, int) and not isinstance(source, bool)
|
|
276
|
+
else ""
|
|
277
|
+
)
|
|
278
|
+
message = (
|
|
279
|
+
f"published environment: {environment_id} @ {revision.strip()[:12]}{source_suffix}. "
|
|
280
|
+
"SFT dataset counts come from this resolved published copy, not local files. "
|
|
281
|
+
f"{advice}"
|
|
282
|
+
)
|
|
283
|
+
print(render.note(message) if render.styled() else message, file=sys.stderr)
|
|
284
|
+
|
|
285
|
+
|
|
286
|
+
def _republish_advice(environment_id: str) -> str | None:
|
|
287
|
+
"""Return conditional remediation for a managed or GitHub environment id."""
|
|
288
|
+
from flash.envs.identity import (
|
|
289
|
+
canonical_managed_environment_slug,
|
|
290
|
+
github_environment_ref_is_pinned,
|
|
291
|
+
is_github_environment_ref,
|
|
292
|
+
)
|
|
293
|
+
|
|
294
|
+
prefix = "If you expected local dataset edits to be included, "
|
|
295
|
+
try:
|
|
296
|
+
managed_slug = canonical_managed_environment_slug(environment_id)
|
|
297
|
+
except ValueError:
|
|
298
|
+
return None
|
|
299
|
+
if managed_slug is not None:
|
|
300
|
+
return (
|
|
301
|
+
f"{prefix}run `{_commands().CLI_NAME} env push --name NAME "
|
|
302
|
+
"--project PROJECT_UUID [path]` again for this managed environment."
|
|
303
|
+
)
|
|
304
|
+
if not is_github_environment_ref(environment_id):
|
|
305
|
+
return None
|
|
306
|
+
if github_environment_ref_is_pinned(environment_id):
|
|
307
|
+
return (
|
|
308
|
+
f"{prefix}publish the new commit, then update [environment] id to the full new commit "
|
|
309
|
+
"SHA; the existing immutable SHA cannot move."
|
|
310
|
+
)
|
|
311
|
+
return (
|
|
312
|
+
f"{prefix}make the named remote branch or tag point at the new commit. A tag may instead "
|
|
313
|
+
"need a new tag and an updated [environment] id rather than moving the existing tag."
|
|
314
|
+
)
|
|
315
|
+
|
|
316
|
+
|
|
221
317
|
def _print_sft_cost(status: dict, spec) -> None:
|
|
222
318
|
total = status.get("estimated_cost_usd") if isinstance(status, dict) else None
|
|
223
319
|
if not isinstance(total, (int, float)) or isinstance(total, bool):
|
|
@@ -234,6 +330,7 @@ def _print_sft_cost(status: dict, spec) -> None:
|
|
|
234
330
|
if value is not None:
|
|
235
331
|
print(f"{key.ljust(8)}: {value}")
|
|
236
332
|
print(f"{'TOTAL'.ljust(8)}: ${float(total):.2f}")
|
|
333
|
+
_print_published_sft_environment_note(status, spec)
|
|
237
334
|
print(
|
|
238
335
|
"tokens, retained rows, truncation, and optimizer steps are estimated from packaged "
|
|
239
336
|
"input/output fields plus contract_text, contract_path, or TRAINING_CONTRACT.md. other "
|
|
@@ -17,8 +17,11 @@ import re
|
|
|
17
17
|
from typing import TYPE_CHECKING
|
|
18
18
|
|
|
19
19
|
from flash.cli.ui import render
|
|
20
|
+
from flash.client import ClientError
|
|
20
21
|
|
|
21
22
|
if TYPE_CHECKING:
|
|
23
|
+
from collections.abc import Mapping
|
|
24
|
+
|
|
22
25
|
from flash.client import ApiClient
|
|
23
26
|
|
|
24
27
|
|
|
@@ -42,18 +45,24 @@ def _worker_section_name(name: str, current_attempt: int | None) -> str:
|
|
|
42
45
|
return f"{name} (attempt={attempt}, current attempt)"
|
|
43
46
|
|
|
44
47
|
|
|
45
|
-
def
|
|
46
|
-
|
|
47
|
-
if
|
|
48
|
-
|
|
48
|
+
def _worker_sections(client: ApiClient, run_id: str) -> dict[str, str]:
|
|
49
|
+
"""Fetch only worker artifacts with printable text."""
|
|
50
|
+
return {name: text for name, text in (client.get_worker_output(run_id) or {}).items() if text}
|
|
51
|
+
|
|
52
|
+
|
|
53
|
+
def _snapshot_live_attempt(client: ApiClient, run_id: str) -> int | None:
|
|
54
|
+
"""Read the live attempt without letting a heading lookup hide diagnostic artifacts."""
|
|
49
55
|
try:
|
|
50
|
-
|
|
51
|
-
except
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
56
|
+
return render.live_attempt(client.get_run(run_id) or {})
|
|
57
|
+
except ClientError:
|
|
58
|
+
return None
|
|
59
|
+
|
|
60
|
+
|
|
61
|
+
def _print_worker_output(
|
|
62
|
+
sections: Mapping[str, str], *, printed_any: bool = False, current_attempt: int | None = None
|
|
63
|
+
) -> bool:
|
|
64
|
+
"""Print worker artifacts under headings naming the attempt that produced them."""
|
|
65
|
+
for name, text in sections.items():
|
|
57
66
|
# label provenance from the filename rather than letting the final section, which is merely
|
|
58
67
|
# the last one appended, read as the live attempt's output.
|
|
59
68
|
section_name = _worker_section_name(name, current_attempt)
|
|
@@ -255,3 +255,13 @@ def _is_safe_github_path_parts(parts: list[str] | tuple[str, ...]) -> bool:
|
|
|
255
255
|
def is_commit_sha(value: str) -> bool:
|
|
256
256
|
"""True when value is a full 40-hex-char git commit id (an immutable ref)."""
|
|
257
257
|
return _COMMIT_SHA_RE.fullmatch(value) is not None
|
|
258
|
+
|
|
259
|
+
|
|
260
|
+
def github_environment_ref_is_pinned(value: str) -> bool:
|
|
261
|
+
"""True when a ``github:`` environment id names an immutable commit.
|
|
262
|
+
|
|
263
|
+
Only the SHA case is decidable from the id. Branches and tags share one string shape, so callers
|
|
264
|
+
must give symbolic-ref advice that is valid for either rather than assuming the ref is movable.
|
|
265
|
+
"""
|
|
266
|
+
parsed = _parse_github_environment_ref(value)
|
|
267
|
+
return parsed is not None and is_commit_sha(parsed.ref)
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
[project]
|
|
2
2
|
name = "freesolo-flash-dev"
|
|
3
|
-
version = "1.2.
|
|
3
|
+
version = "1.2.97"
|
|
4
4
|
description ="Flash — managed LoRA post-training (SFT/GRPO/OPD) for Freesolo environments, driven by the `flash` CLI"
|
|
5
5
|
readme = "README.md"
|
|
6
6
|
# RunPod Flash supports Python 3.11-3.12 (not 3.13 yet).
|
|
@@ -137,7 +137,7 @@ artifacts = ["flash/py.typed"]
|
|
|
137
137
|
# auto-published by .github/workflows/publish-dev.yml: a push to `dev` whose version isn't yet on
|
|
138
138
|
# PyPI publishes it; pushes that don't change it find it already published and no-op. So cutting a
|
|
139
139
|
# dev-channel release = bump this (and [project].version) and merge to `dev`.
|
|
140
|
-
version = "1.2.
|
|
140
|
+
version = "1.2.97"
|
|
141
141
|
|
|
142
142
|
[tool.pytest.ini_options]
|
|
143
143
|
pythonpath = ["."]
|
|
@@ -1322,6 +1322,129 @@ def test_train_dry_run_keeps_compatibility_on_stderr(
|
|
|
1322
1322
|
assert call[1]["train"] == {"epochs": 1, "max_examples": 2}
|
|
1323
1323
|
|
|
1324
1324
|
|
|
1325
|
+
def test_train_dry_run_attributes_sft_counts_to_the_managed_environment(
|
|
1326
|
+
fake_client, tmp_path, capsys, monkeypatch
|
|
1327
|
+
) -> None:
|
|
1328
|
+
original_create_run = fake_client.create_run
|
|
1329
|
+
|
|
1330
|
+
def create_run_with_profile(*args, **kwargs):
|
|
1331
|
+
response = original_create_run(*args, **kwargs)
|
|
1332
|
+
response["workload_profile"] = {
|
|
1333
|
+
"environment_id": "owner/project/env",
|
|
1334
|
+
"environment_revision": "a" * 40,
|
|
1335
|
+
"source_examples": 125,
|
|
1336
|
+
}
|
|
1337
|
+
return response
|
|
1338
|
+
|
|
1339
|
+
monkeypatch.setattr(fake_client, "create_run", create_run_with_profile)
|
|
1340
|
+
|
|
1341
|
+
assert _run(["train", str(_train_config(tmp_path)), "--dry-run"]) == 0
|
|
1342
|
+
captured = capsys.readouterr()
|
|
1343
|
+
payload = json.loads(captured.out)
|
|
1344
|
+
|
|
1345
|
+
assert payload["workload_profile"]["environment_id"] == "owner/project/env"
|
|
1346
|
+
assert payload["workload_profile"]["environment_revision"] == "a" * 40
|
|
1347
|
+
assert (
|
|
1348
|
+
"published environment: owner/project/env @ aaaaaaaaaaaa (125 source rows)" in captured.err
|
|
1349
|
+
)
|
|
1350
|
+
assert "dataset counts come from this resolved published copy, not local files" in captured.err
|
|
1351
|
+
assert "If you expected local dataset edits to be included" in captured.err
|
|
1352
|
+
assert (
|
|
1353
|
+
"run `flash env push --name NAME --project PROJECT_UUID [path]` again for this managed "
|
|
1354
|
+
"environment"
|
|
1355
|
+
) in captured.err
|
|
1356
|
+
|
|
1357
|
+
|
|
1358
|
+
def test_train_dry_run_keeps_inline_records_off_the_published_environment_note(
|
|
1359
|
+
fake_client, tmp_path, capsys, monkeypatch
|
|
1360
|
+
) -> None:
|
|
1361
|
+
"""inline rows are already authoritative, so the published-copy warning does not apply."""
|
|
1362
|
+
original_create_run = fake_client.create_run
|
|
1363
|
+
|
|
1364
|
+
def create_run_with_profile(*args, **kwargs):
|
|
1365
|
+
response = original_create_run(*args, **kwargs)
|
|
1366
|
+
response["workload_profile"] = {
|
|
1367
|
+
"environment_id": "owner/project/env",
|
|
1368
|
+
"environment_revision": "a" * 40,
|
|
1369
|
+
"source_examples": 2,
|
|
1370
|
+
}
|
|
1371
|
+
return response
|
|
1372
|
+
|
|
1373
|
+
monkeypatch.setattr(fake_client, "create_run", create_run_with_profile)
|
|
1374
|
+
config = tmp_path / "inline.toml"
|
|
1375
|
+
config.write_text(
|
|
1376
|
+
'model = "Qwen/Qwen3.5-4B"\n'
|
|
1377
|
+
'project = "11111111-1111-4111-8111-111111111111"\n'
|
|
1378
|
+
'algorithm = "sft"\n'
|
|
1379
|
+
'[environment]\nid = "owner/project/env"\n'
|
|
1380
|
+
'[environment.params]\nrecords = [{ input = "a", output = "b" }]\n'
|
|
1381
|
+
"[train]\nepochs = 1\nmax_examples = 2\n"
|
|
1382
|
+
)
|
|
1383
|
+
|
|
1384
|
+
assert _run(["train", str(config), "--dry-run"]) == 0
|
|
1385
|
+
captured = capsys.readouterr()
|
|
1386
|
+
payload = json.loads(captured.out)
|
|
1387
|
+
|
|
1388
|
+
assert payload["workload_profile"]["source_examples"] == 2
|
|
1389
|
+
assert "published environment:" not in captured.err
|
|
1390
|
+
assert "SFT dataset counts come from" not in captured.err
|
|
1391
|
+
assert "env push" not in captured.err
|
|
1392
|
+
|
|
1393
|
+
|
|
1394
|
+
def test_inline_records_are_not_labelled_a_published_copy_in_cost_rows(monkeypatch) -> None:
|
|
1395
|
+
"""The cost panel and the provenance note sit within a few lines of each other.
|
|
1396
|
+
|
|
1397
|
+
If only the note learns that the rows came from the request body, the panel above it still
|
|
1398
|
+
reads "source rows in published copy" and the quote contradicts itself in one screen.
|
|
1399
|
+
"""
|
|
1400
|
+
from types import SimpleNamespace
|
|
1401
|
+
|
|
1402
|
+
from flash.cli.commands import train_cost
|
|
1403
|
+
|
|
1404
|
+
monkeypatch.setenv("FLASH_STYLE", "0")
|
|
1405
|
+
profile = {
|
|
1406
|
+
"environment_id": "owner/project/env",
|
|
1407
|
+
"environment_revision": "d" * 40,
|
|
1408
|
+
"source_examples": 9,
|
|
1409
|
+
"retained_examples": 8,
|
|
1410
|
+
"selected_examples": 9,
|
|
1411
|
+
}
|
|
1412
|
+
spec = SimpleNamespace(
|
|
1413
|
+
model="Qwen/Qwen3.5-4B",
|
|
1414
|
+
environment=SimpleNamespace(params={"records": [{"input": "x"}]}),
|
|
1415
|
+
)
|
|
1416
|
+
|
|
1417
|
+
rows = dict(train_cost._sft_cost_rows(spec, profile))
|
|
1418
|
+
|
|
1419
|
+
assert "inline records" in rows["examples"]
|
|
1420
|
+
assert "published copy" not in rows["examples"]
|
|
1421
|
+
assert rows["env"] == "resolved environment owner/project/env"
|
|
1422
|
+
assert "published" not in rows["revision"]
|
|
1423
|
+
|
|
1424
|
+
|
|
1425
|
+
def test_published_rows_keep_their_published_labels(monkeypatch) -> None:
|
|
1426
|
+
"""The inline branch must not relabel an ordinary published quote."""
|
|
1427
|
+
from types import SimpleNamespace
|
|
1428
|
+
|
|
1429
|
+
from flash.cli.commands import train_cost
|
|
1430
|
+
|
|
1431
|
+
monkeypatch.setenv("FLASH_STYLE", "0")
|
|
1432
|
+
profile = {
|
|
1433
|
+
"environment_id": "owner/project/env",
|
|
1434
|
+
"environment_revision": "e" * 40,
|
|
1435
|
+
"source_examples": 9,
|
|
1436
|
+
"retained_examples": 8,
|
|
1437
|
+
"selected_examples": 9,
|
|
1438
|
+
}
|
|
1439
|
+
spec = SimpleNamespace(model="Qwen/Qwen3.5-4B", environment=SimpleNamespace(params={}))
|
|
1440
|
+
|
|
1441
|
+
rows = dict(train_cost._sft_cost_rows(spec, profile))
|
|
1442
|
+
|
|
1443
|
+
assert "source rows in published copy" in rows["examples"]
|
|
1444
|
+
assert rows["env"] == "published environment owner/project/env"
|
|
1445
|
+
assert "(published commit)" in rows["revision"]
|
|
1446
|
+
|
|
1447
|
+
|
|
1325
1448
|
def test_train_dry_run_sends_declared_runtime_secrets(
|
|
1326
1449
|
fake_client, tmp_path, capsys, monkeypatch
|
|
1327
1450
|
) -> None:
|
|
@@ -1413,13 +1536,16 @@ def test_status_runs_and_log_command(fake_client, capsys, monkeypatch) -> None:
|
|
|
1413
1536
|
{"run_id": "flash-1", "state": "done"},
|
|
1414
1537
|
]
|
|
1415
1538
|
)
|
|
1416
|
-
monkeypatch.
|
|
1417
|
-
|
|
1418
|
-
|
|
1419
|
-
|
|
1420
|
-
"
|
|
1421
|
-
"
|
|
1422
|
-
|
|
1539
|
+
with monkeypatch.context() as patched:
|
|
1540
|
+
# scoped: this iterator holds exactly the two statuses this one assertion consumes, so
|
|
1541
|
+
# letting it stay installed would starve every later command of a status it needs.
|
|
1542
|
+
patched.setattr(fake_client, "get_run", lambda _run_id: next(statuses))
|
|
1543
|
+
patched.setattr(cli.commands.time, "sleep", lambda _seconds: None)
|
|
1544
|
+
assert _run(["runs", "status", "flash-1", "--follow", "--json"]) == 0
|
|
1545
|
+
assert [json.loads(line)["state"] for line in capsys.readouterr().out.splitlines()] == [
|
|
1546
|
+
"running",
|
|
1547
|
+
"done",
|
|
1548
|
+
]
|
|
1423
1549
|
|
|
1424
1550
|
assert _run(["runs", "log", "flash-1"]) == 0
|
|
1425
1551
|
out = capsys.readouterr().out
|
|
@@ -1483,6 +1609,104 @@ def test_log_labels_previous_attempt_artifacts_after_the_live_attempt_log(
|
|
|
1483
1609
|
assert 'HEARTBEAT {"stage":"rl_step","step":0,"attempt":0' in out
|
|
1484
1610
|
|
|
1485
1611
|
|
|
1612
|
+
def test_log_still_prints_artifacts_when_the_attempt_lookup_fails(
|
|
1613
|
+
fake_client, capsys, monkeypatch
|
|
1614
|
+
) -> None:
|
|
1615
|
+
"""A failed status read costs the heading, never the artifacts.
|
|
1616
|
+
|
|
1617
|
+
The artifacts hold the traceback the user ran this command to read. Losing them to a lookup
|
|
1618
|
+
that only decorates a section header would hide the failure behind an unrelated one.
|
|
1619
|
+
"""
|
|
1620
|
+
from flash.client import ClientError
|
|
1621
|
+
|
|
1622
|
+
def unavailable(_run_id):
|
|
1623
|
+
raise ClientError("freesolo is unreachable")
|
|
1624
|
+
|
|
1625
|
+
monkeypatch.setattr(fake_client, "get_run", unavailable)
|
|
1626
|
+
monkeypatch.setattr(
|
|
1627
|
+
fake_client,
|
|
1628
|
+
"get_worker_output",
|
|
1629
|
+
lambda _run_id: {"error_rl_attempt0.txt": "torch.OutOfMemoryError: CUDA OOM\n"},
|
|
1630
|
+
)
|
|
1631
|
+
|
|
1632
|
+
assert _run(["runs", "log", "flash-1"]) == 0
|
|
1633
|
+
out = capsys.readouterr().out
|
|
1634
|
+
assert "torch.OutOfMemoryError: CUDA OOM" in out
|
|
1635
|
+
# unlabelled against a live attempt, since none could be established -- but still attributed.
|
|
1636
|
+
assert "----- error_rl_attempt0.txt (attempt=0) -----" in out
|
|
1637
|
+
|
|
1638
|
+
|
|
1639
|
+
def test_log_reads_no_status_when_there_are_no_artifacts_to_label(
|
|
1640
|
+
fake_client, capsys, monkeypatch
|
|
1641
|
+
) -> None:
|
|
1642
|
+
"""The status only names a heading, so with no headings it is never worth a request."""
|
|
1643
|
+
calls: list[str] = []
|
|
1644
|
+
|
|
1645
|
+
def get_run(_run_id):
|
|
1646
|
+
calls.append("get_run")
|
|
1647
|
+
return {"run_id": "flash-1", "state": "running", "remote": {"attempt": 0}}
|
|
1648
|
+
|
|
1649
|
+
monkeypatch.setattr(fake_client, "get_run", get_run)
|
|
1650
|
+
monkeypatch.setattr(fake_client, "get_worker_output", lambda _run_id: {})
|
|
1651
|
+
|
|
1652
|
+
assert _run(["runs", "log", "flash-1"]) == 0
|
|
1653
|
+
capsys.readouterr()
|
|
1654
|
+
assert calls == []
|
|
1655
|
+
|
|
1656
|
+
|
|
1657
|
+
def test_log_reads_no_status_and_prints_nothing_when_all_artifacts_are_empty(
|
|
1658
|
+
fake_client, capsys, monkeypatch
|
|
1659
|
+
) -> None:
|
|
1660
|
+
"""Empty artifact values are not printable sections and must not trigger a status read."""
|
|
1661
|
+
fake_client.log_text = ""
|
|
1662
|
+
calls: list[str] = []
|
|
1663
|
+
|
|
1664
|
+
def get_run(_run_id):
|
|
1665
|
+
calls.append("get_run")
|
|
1666
|
+
return {"run_id": "flash-1", "state": "running", "remote": {"attempt": 1}}
|
|
1667
|
+
|
|
1668
|
+
monkeypatch.setattr(fake_client, "get_run", get_run)
|
|
1669
|
+
monkeypatch.setattr(
|
|
1670
|
+
fake_client,
|
|
1671
|
+
"get_worker_output",
|
|
1672
|
+
lambda _run_id: {
|
|
1673
|
+
"console_rl_attempt1.txt": "",
|
|
1674
|
+
"error_rl_attempt1.txt": "",
|
|
1675
|
+
},
|
|
1676
|
+
)
|
|
1677
|
+
|
|
1678
|
+
assert _run(["runs", "log", "flash-1"]) == 0
|
|
1679
|
+
captured = capsys.readouterr()
|
|
1680
|
+
assert captured.out == ""
|
|
1681
|
+
assert captured.err == ""
|
|
1682
|
+
assert calls == []
|
|
1683
|
+
|
|
1684
|
+
|
|
1685
|
+
def test_log_labels_artifacts_against_a_retry_that_starts_mid_command(
|
|
1686
|
+
fake_client, capsys, monkeypatch
|
|
1687
|
+
) -> None:
|
|
1688
|
+
"""Artifact acquisition must precede the status snapshot used for its heading."""
|
|
1689
|
+
events: list[str] = []
|
|
1690
|
+
|
|
1691
|
+
def get_worker_output(_run_id):
|
|
1692
|
+
events.append("artifacts")
|
|
1693
|
+
return {"error_rl_attempt0.txt": "torch.OutOfMemoryError: CUDA OOM\n"}
|
|
1694
|
+
|
|
1695
|
+
def get_run(_run_id):
|
|
1696
|
+
events.append("status")
|
|
1697
|
+
return {"run_id": "flash-1", "state": "running", "remote": {"attempt": 1}}
|
|
1698
|
+
|
|
1699
|
+
monkeypatch.setattr(fake_client, "get_worker_output", get_worker_output)
|
|
1700
|
+
monkeypatch.setattr(fake_client, "get_run", get_run)
|
|
1701
|
+
|
|
1702
|
+
assert _run(["runs", "log", "flash-1"]) == 0
|
|
1703
|
+
out = capsys.readouterr().out
|
|
1704
|
+
assert events == ["artifacts", "status"]
|
|
1705
|
+
assert (
|
|
1706
|
+
"----- error_rl_attempt0.txt (attempt=0, previous attempt; current attempt=1) -----" in out
|
|
1707
|
+
)
|
|
1708
|
+
|
|
1709
|
+
|
|
1486
1710
|
def test_log_prints_partial_log_line_with_newline(fake_client, capsys) -> None:
|
|
1487
1711
|
fake_client.log_text = "partial log line"
|
|
1488
1712
|
fake_client.get_worker_output = lambda run_id: {}
|
|
@@ -1624,7 +1848,7 @@ def test_follow_logs_shows_tty_spinner_while_waiting(monkeypatch, capsys) -> Non
|
|
|
1624
1848
|
monkeypatch.setattr(cli.commands.sys, "stderr", stderr)
|
|
1625
1849
|
monkeypatch.setattr(cli.commands.time, "sleep", lambda _seconds: None)
|
|
1626
1850
|
|
|
1627
|
-
state, printed_any = cli.commands._poll_logs(_WaitingClient(), "flash-spin", interval=0.2)
|
|
1851
|
+
state, printed_any, _ = cli.commands._poll_logs(_WaitingClient(), "flash-spin", interval=0.2)
|
|
1628
1852
|
|
|
1629
1853
|
assert state == "done"
|
|
1630
1854
|
assert printed_any is True
|
|
@@ -1635,6 +1859,21 @@ def test_follow_logs_shows_tty_spinner_while_waiting(monkeypatch, capsys) -> Non
|
|
|
1635
1859
|
assert err.endswith("\r")
|
|
1636
1860
|
|
|
1637
1861
|
|
|
1862
|
+
def test_poll_logs_returns_the_live_attempt_from_the_terminal_status(capsys) -> None:
|
|
1863
|
+
class _AttemptClient(_FakeClient):
|
|
1864
|
+
def get_logs(self, run_id: str, offset: int = 0) -> dict:
|
|
1865
|
+
return {"run_id": run_id, "logs": "", "offset": 0, "state": "done"}
|
|
1866
|
+
|
|
1867
|
+
def get_run(self, run_id: str) -> dict:
|
|
1868
|
+
return {"run_id": run_id, "state": "done", "remote": {"attempt": 1}}
|
|
1869
|
+
|
|
1870
|
+
result = cli.commands._poll_logs(_AttemptClient(), "flash-attempt", interval=0)
|
|
1871
|
+
|
|
1872
|
+
assert result == cli.commands._LogPollResult("done", False, 1)
|
|
1873
|
+
assert result.live_attempt == 1
|
|
1874
|
+
assert capsys.readouterr().out == ""
|
|
1875
|
+
|
|
1876
|
+
|
|
1638
1877
|
def test_follow_logs_uses_status_progress_when_log_tail_lags(monkeypatch, capsys) -> None:
|
|
1639
1878
|
class _TTYBuffer(io.StringIO):
|
|
1640
1879
|
def isatty(self) -> bool:
|
|
@@ -1671,7 +1910,7 @@ def test_follow_logs_uses_status_progress_when_log_tail_lags(monkeypatch, capsys
|
|
|
1671
1910
|
monkeypatch.setattr(cli.commands.sys, "stderr", stderr)
|
|
1672
1911
|
monkeypatch.setattr(cli.commands.time, "sleep", lambda _seconds: None)
|
|
1673
1912
|
|
|
1674
|
-
state, printed_any = cli.commands._poll_logs(_LaggingLogClient(), "flash-lag", interval=0.2)
|
|
1913
|
+
state, printed_any, _ = cli.commands._poll_logs(_LaggingLogClient(), "flash-lag", interval=0.2)
|
|
1675
1914
|
|
|
1676
1915
|
assert state == "done"
|
|
1677
1916
|
assert printed_any is False
|
|
@@ -1744,7 +1983,7 @@ def test_follow_logs_prints_heartbeat_metrics_once_per_step(monkeypatch, capsys)
|
|
|
1744
1983
|
|
|
1745
1984
|
monkeypatch.setattr(cli.commands.time, "sleep", lambda _seconds: None)
|
|
1746
1985
|
|
|
1747
|
-
state, printed_any = cli.commands._poll_logs(_MetricClient(), "flash-metrics", interval=0.2)
|
|
1986
|
+
state, printed_any, _ = cli.commands._poll_logs(_MetricClient(), "flash-metrics", interval=0.2)
|
|
1748
1987
|
|
|
1749
1988
|
assert state == "done"
|
|
1750
1989
|
assert printed_any is False
|