freesolo-flash-dev 1.1.68__tar.gz → 1.1.70__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (530) hide show
  1. {freesolo_flash_dev-1.1.68 → freesolo_flash_dev-1.1.70}/PKG-INFO +1 -1
  2. freesolo_flash_dev-1.1.70/flash/adapters/artifacts.py +141 -0
  3. {freesolo_flash_dev-1.1.68 → freesolo_flash_dev-1.1.70}/flash/adapters/lora_rank.py +31 -11
  4. {freesolo_flash_dev-1.1.68 → freesolo_flash_dev-1.1.70}/flash/cli/commands/env/eval.py +27 -36
  5. freesolo_flash_dev-1.1.70/flash/cli/commands/env/eval_args.py +43 -0
  6. {freesolo_flash_dev-1.1.68 → freesolo_flash_dev-1.1.70}/flash/cli/commands/env/retained.py +13 -3
  7. {freesolo_flash_dev-1.1.68 → freesolo_flash_dev-1.1.70}/flash/cli/commands/env/setup.py +9 -5
  8. {freesolo_flash_dev-1.1.68 → freesolo_flash_dev-1.1.70}/flash/engine/worker/__init__.py +5 -2
  9. {freesolo_flash_dev-1.1.68 → freesolo_flash_dev-1.1.70}/flash/engine/worker/io/hf.py +15 -5
  10. freesolo_flash_dev-1.1.70/flash/engine/worker/model/lora.py +118 -0
  11. {freesolo_flash_dev-1.1.68 → freesolo_flash_dev-1.1.70}/flash/engine/worker/sft_train.py +9 -1
  12. {freesolo_flash_dev-1.1.68 → freesolo_flash_dev-1.1.70}/flash/engine/worker/train/opd/multiturn_validation.py +8 -2
  13. {freesolo_flash_dev-1.1.68 → freesolo_flash_dev-1.1.70}/flash/envs/adapter.py +4 -0
  14. {freesolo_flash_dev-1.1.68 → freesolo_flash_dev-1.1.70}/flash/envs/identity.py +20 -2
  15. {freesolo_flash_dev-1.1.68 → freesolo_flash_dev-1.1.70}/flash/envs/loader.py +8 -2
  16. {freesolo_flash_dev-1.1.68 → freesolo_flash_dev-1.1.70}/flash/providers/artifacts/hf.py +31 -9
  17. {freesolo_flash_dev-1.1.68 → freesolo_flash_dev-1.1.70}/flash/runner/attempts.py +10 -4
  18. {freesolo_flash_dev-1.1.68 → freesolo_flash_dev-1.1.70}/flash/runner/results/checkpoints.py +9 -2
  19. {freesolo_flash_dev-1.1.68 → freesolo_flash_dev-1.1.70}/flash/runner/supervise/seed_submission.py +76 -5
  20. {freesolo_flash_dev-1.1.68 → freesolo_flash_dev-1.1.70}/flash/serve/adapter_check.py +22 -6
  21. {freesolo_flash_dev-1.1.68 → freesolo_flash_dev-1.1.70}/flash/serve/export.py +11 -4
  22. {freesolo_flash_dev-1.1.68 → freesolo_flash_dev-1.1.70}/flash/server/domain/envs.py +16 -2
  23. {freesolo_flash_dev-1.1.68 → freesolo_flash_dev-1.1.70}/flash/server/domain/projects.py +53 -6
  24. {freesolo_flash_dev-1.1.68 → freesolo_flash_dev-1.1.70}/flash/teacher/retry_contract.py +32 -2
  25. {freesolo_flash_dev-1.1.68 → freesolo_flash_dev-1.1.70}/pyproject.toml +2 -2
  26. freesolo_flash_dev-1.1.70/tests/test_adapter_shard_completeness.py +283 -0
  27. {freesolo_flash_dev-1.1.68 → freesolo_flash_dev-1.1.70}/tests/test_dev_channel.py +55 -0
  28. {freesolo_flash_dev-1.1.68 → freesolo_flash_dev-1.1.70}/tests/test_env_evaluations.py +48 -0
  29. {freesolo_flash_dev-1.1.68 → freesolo_flash_dev-1.1.70}/tests/test_env_list_hub.py +48 -0
  30. {freesolo_flash_dev-1.1.68 → freesolo_flash_dev-1.1.70}/tests/test_export.py +8 -0
  31. {freesolo_flash_dev-1.1.68 → freesolo_flash_dev-1.1.70}/tests/test_github_urlopen_retry.py +19 -7
  32. {freesolo_flash_dev-1.1.68 → freesolo_flash_dev-1.1.70}/tests/test_jobs.py +3 -0
  33. {freesolo_flash_dev-1.1.68 → freesolo_flash_dev-1.1.70}/tests/test_lora_rank_coverage.py +1 -1
  34. {freesolo_flash_dev-1.1.68 → freesolo_flash_dev-1.1.70}/tests/test_lora_rank_preflight.py +2 -2
  35. freesolo_flash_dev-1.1.70/tests/test_opd_multiturn_eos_boundary.py +75 -0
  36. {freesolo_flash_dev-1.1.68 → freesolo_flash_dev-1.1.70}/tests/test_opd_resume_safety.py +96 -2
  37. {freesolo_flash_dev-1.1.68 → freesolo_flash_dev-1.1.70}/tests/test_projects.py +73 -1
  38. {freesolo_flash_dev-1.1.68 → freesolo_flash_dev-1.1.70}/tests/test_sft_train.py +33 -1
  39. {freesolo_flash_dev-1.1.68 → freesolo_flash_dev-1.1.70}/uv.lock +1 -1
  40. freesolo_flash_dev-1.1.68/flash/adapters/artifacts.py +0 -55
  41. freesolo_flash_dev-1.1.68/flash/engine/worker/model/lora.py +0 -97
  42. {freesolo_flash_dev-1.1.68 → freesolo_flash_dev-1.1.70}/.dockerignore +0 -0
  43. {freesolo_flash_dev-1.1.68 → freesolo_flash_dev-1.1.70}/.env.example +0 -0
  44. {freesolo_flash_dev-1.1.68 → freesolo_flash_dev-1.1.70}/.github/CODEOWNERS +0 -0
  45. {freesolo_flash_dev-1.1.68 → freesolo_flash_dev-1.1.70}/.github/ISSUE_TEMPLATE/bug_report.yml +0 -0
  46. {freesolo_flash_dev-1.1.68 → freesolo_flash_dev-1.1.70}/.github/ISSUE_TEMPLATE/config.yml +0 -0
  47. {freesolo_flash_dev-1.1.68 → freesolo_flash_dev-1.1.70}/.github/ISSUE_TEMPLATE/feature_request.yml +0 -0
  48. {freesolo_flash_dev-1.1.68 → freesolo_flash_dev-1.1.70}/.github/PULL_REQUEST_TEMPLATE.md +0 -0
  49. {freesolo_flash_dev-1.1.68 → freesolo_flash_dev-1.1.70}/.github/dependabot.yml +0 -0
  50. {freesolo_flash_dev-1.1.68 → freesolo_flash_dev-1.1.70}/.github/workflows/auto-rebake.yml +0 -0
  51. {freesolo_flash_dev-1.1.68 → freesolo_flash_dev-1.1.70}/.github/workflows/bake-kernel-cache.yml +0 -0
  52. {freesolo_flash_dev-1.1.68 → freesolo_flash_dev-1.1.70}/.github/workflows/ci.yml +0 -0
  53. {freesolo_flash_dev-1.1.68 → freesolo_flash_dev-1.1.70}/.github/workflows/main-source-guard.yml +0 -0
  54. {freesolo_flash_dev-1.1.68 → freesolo_flash_dev-1.1.70}/.github/workflows/notify-tests-repo.yml +0 -0
  55. {freesolo_flash_dev-1.1.68 → freesolo_flash_dev-1.1.70}/.github/workflows/publish-dev.yml +0 -0
  56. {freesolo_flash_dev-1.1.68 → freesolo_flash_dev-1.1.70}/.github/workflows/publish-image.yml +0 -0
  57. {freesolo_flash_dev-1.1.68 → freesolo_flash_dev-1.1.70}/.github/workflows/publish.yml +0 -0
  58. {freesolo_flash_dev-1.1.68 → freesolo_flash_dev-1.1.70}/.github/workflows/version-parity.yml +0 -0
  59. {freesolo_flash_dev-1.1.68 → freesolo_flash_dev-1.1.70}/.github/workflows/worker-image.yml +0 -0
  60. {freesolo_flash_dev-1.1.68 → freesolo_flash_dev-1.1.70}/.gitignore +0 -0
  61. {freesolo_flash_dev-1.1.68 → freesolo_flash_dev-1.1.70}/CHANGELOG.md +0 -0
  62. {freesolo_flash_dev-1.1.68 → freesolo_flash_dev-1.1.70}/CODE_OF_CONDUCT.md +0 -0
  63. {freesolo_flash_dev-1.1.68 → freesolo_flash_dev-1.1.70}/CONTRIBUTING.md +0 -0
  64. {freesolo_flash_dev-1.1.68 → freesolo_flash_dev-1.1.70}/Dockerfile +0 -0
  65. {freesolo_flash_dev-1.1.68 → freesolo_flash_dev-1.1.70}/Dockerfile.worker +0 -0
  66. {freesolo_flash_dev-1.1.68 → freesolo_flash_dev-1.1.70}/LICENSE +0 -0
  67. {freesolo_flash_dev-1.1.68 → freesolo_flash_dev-1.1.70}/NOTICE +0 -0
  68. {freesolo_flash_dev-1.1.68 → freesolo_flash_dev-1.1.70}/README.md +0 -0
  69. {freesolo_flash_dev-1.1.68 → freesolo_flash_dev-1.1.70}/SECURITY.md +0 -0
  70. {freesolo_flash_dev-1.1.68 → freesolo_flash_dev-1.1.70}/SELF_HOSTING.md +0 -0
  71. {freesolo_flash_dev-1.1.68 → freesolo_flash_dev-1.1.70}/build/kernel_cache/.gitignore +0 -0
  72. {freesolo_flash_dev-1.1.68 → freesolo_flash_dev-1.1.70}/build/kernel_cache/.keep +0 -0
  73. {freesolo_flash_dev-1.1.68 → freesolo_flash_dev-1.1.70}/deploy/infisical/README.md +0 -0
  74. {freesolo_flash_dev-1.1.68 → freesolo_flash_dev-1.1.70}/deploy/infisical/entrypoint.sh +0 -0
  75. {freesolo_flash_dev-1.1.68 → freesolo_flash_dev-1.1.70}/docker/Dockerfile.kernelcache +0 -0
  76. {freesolo_flash_dev-1.1.68 → freesolo_flash_dev-1.1.70}/docker/Dockerfile.kernelcache.relayer +0 -0
  77. {freesolo_flash_dev-1.1.68 → freesolo_flash_dev-1.1.70}/docker/bake_kernel_cache.py +0 -0
  78. {freesolo_flash_dev-1.1.68 → freesolo_flash_dev-1.1.70}/docker/bake_pod_entry.py +0 -0
  79. {freesolo_flash_dev-1.1.68 → freesolo_flash_dev-1.1.70}/docker/extract_cudart_fix.py +0 -0
  80. {freesolo_flash_dev-1.1.68 → freesolo_flash_dev-1.1.70}/docker/kernel_fingerprint.py +0 -0
  81. {freesolo_flash_dev-1.1.68 → freesolo_flash_dev-1.1.70}/docker/make_rp_handler.py +0 -0
  82. {freesolo_flash_dev-1.1.68 → freesolo_flash_dev-1.1.70}/flash/__init__.py +0 -0
  83. {freesolo_flash_dev-1.1.68 → freesolo_flash_dev-1.1.70}/flash/_internal/__init__.py +0 -0
  84. {freesolo_flash_dev-1.1.68 → freesolo_flash_dev-1.1.70}/flash/_internal/channel.py +0 -0
  85. {freesolo_flash_dev-1.1.68 → freesolo_flash_dev-1.1.70}/flash/_internal/diagnostics.py +0 -0
  86. {freesolo_flash_dev-1.1.68 → freesolo_flash_dev-1.1.70}/flash/_internal/fileio.py +0 -0
  87. {freesolo_flash_dev-1.1.68 → freesolo_flash_dev-1.1.70}/flash/_internal/logging.py +0 -0
  88. {freesolo_flash_dev-1.1.68 → freesolo_flash_dev-1.1.70}/flash/_internal/paths.py +0 -0
  89. {freesolo_flash_dev-1.1.68 → freesolo_flash_dev-1.1.70}/flash/adapters/__init__.py +0 -0
  90. {freesolo_flash_dev-1.1.68 → freesolo_flash_dev-1.1.70}/flash/cli/__init__.py +0 -0
  91. {freesolo_flash_dev-1.1.68 → freesolo_flash_dev-1.1.70}/flash/cli/__main__.py +0 -0
  92. {freesolo_flash_dev-1.1.68 → freesolo_flash_dev-1.1.70}/flash/cli/commands/__init__.py +0 -0
  93. {freesolo_flash_dev-1.1.68 → freesolo_flash_dev-1.1.70}/flash/cli/commands/deploy.py +0 -0
  94. {freesolo_flash_dev-1.1.68 → freesolo_flash_dev-1.1.70}/flash/cli/commands/env/__init__.py +0 -0
  95. {freesolo_flash_dev-1.1.68 → freesolo_flash_dev-1.1.70}/flash/cli/commands/env/episode.py +0 -0
  96. {freesolo_flash_dev-1.1.68 → freesolo_flash_dev-1.1.70}/flash/cli/commands/env/imports.py +0 -0
  97. {freesolo_flash_dev-1.1.68 → freesolo_flash_dev-1.1.70}/flash/cli/commands/env/list.py +0 -0
  98. {freesolo_flash_dev-1.1.68 → freesolo_flash_dev-1.1.70}/flash/cli/commands/env/push.py +0 -0
  99. {freesolo_flash_dev-1.1.68 → freesolo_flash_dev-1.1.70}/flash/cli/commands/env/test.py +0 -0
  100. {freesolo_flash_dev-1.1.68 → freesolo_flash_dev-1.1.70}/flash/cli/commands/traces.py +0 -0
  101. {freesolo_flash_dev-1.1.68 → freesolo_flash_dev-1.1.70}/flash/cli/commands/train_cost.py +0 -0
  102. {freesolo_flash_dev-1.1.68 → freesolo_flash_dev-1.1.70}/flash/cli/scaffold/TRAINING.md +0 -0
  103. {freesolo_flash_dev-1.1.68 → freesolo_flash_dev-1.1.70}/flash/cli/scaffold/__init__.py +0 -0
  104. {freesolo_flash_dev-1.1.68 → freesolo_flash_dev-1.1.70}/flash/cli/ui/__init__.py +0 -0
  105. {freesolo_flash_dev-1.1.68 → freesolo_flash_dev-1.1.70}/flash/cli/ui/cost.py +0 -0
  106. {freesolo_flash_dev-1.1.68 → freesolo_flash_dev-1.1.70}/flash/cli/ui/env_panels.py +0 -0
  107. {freesolo_flash_dev-1.1.68 → freesolo_flash_dev-1.1.70}/flash/cli/ui/heartbeat.py +0 -0
  108. {freesolo_flash_dev-1.1.68 → freesolo_flash_dev-1.1.70}/flash/cli/ui/render.py +0 -0
  109. {freesolo_flash_dev-1.1.68 → freesolo_flash_dev-1.1.70}/flash/cli/ui/tables.py +0 -0
  110. {freesolo_flash_dev-1.1.68 → freesolo_flash_dev-1.1.70}/flash/cli/ui/tty.py +0 -0
  111. {freesolo_flash_dev-1.1.68 → freesolo_flash_dev-1.1.70}/flash/client/__init__.py +0 -0
  112. {freesolo_flash_dev-1.1.68 → freesolo_flash_dev-1.1.70}/flash/client/config.py +0 -0
  113. {freesolo_flash_dev-1.1.68 → freesolo_flash_dev-1.1.70}/flash/client/freesolo_api.py +0 -0
  114. {freesolo_flash_dev-1.1.68 → freesolo_flash_dev-1.1.70}/flash/client/http.py +0 -0
  115. {freesolo_flash_dev-1.1.68 → freesolo_flash_dev-1.1.70}/flash/client/runtime_secrets.py +0 -0
  116. {freesolo_flash_dev-1.1.68 → freesolo_flash_dev-1.1.70}/flash/client/shapes.py +0 -0
  117. {freesolo_flash_dev-1.1.68 → freesolo_flash_dev-1.1.70}/flash/client/specs.py +0 -0
  118. {freesolo_flash_dev-1.1.68 → freesolo_flash_dev-1.1.70}/flash/client/streaming.py +0 -0
  119. {freesolo_flash_dev-1.1.68 → freesolo_flash_dev-1.1.70}/flash/content/__init__.py +0 -0
  120. {freesolo_flash_dev-1.1.68 → freesolo_flash_dev-1.1.70}/flash/content/multimodal.py +0 -0
  121. {freesolo_flash_dev-1.1.68 → freesolo_flash_dev-1.1.70}/flash/content/structured_outputs.py +0 -0
  122. {freesolo_flash_dev-1.1.68 → freesolo_flash_dev-1.1.70}/flash/content/thinking.py +0 -0
  123. {freesolo_flash_dev-1.1.68 → freesolo_flash_dev-1.1.70}/flash/core/__init__.py +0 -0
  124. {freesolo_flash_dev-1.1.68 → freesolo_flash_dev-1.1.70}/flash/core/catalog.py +0 -0
  125. {freesolo_flash_dev-1.1.68 → freesolo_flash_dev-1.1.70}/flash/core/spec.py +0 -0
  126. {freesolo_flash_dev-1.1.68 → freesolo_flash_dev-1.1.70}/flash/cost/__init__.py +0 -0
  127. {freesolo_flash_dev-1.1.68 → freesolo_flash_dev-1.1.70}/flash/cost/analytical.py +0 -0
  128. {freesolo_flash_dev-1.1.68 → freesolo_flash_dev-1.1.70}/flash/cost/facts.py +0 -0
  129. {freesolo_flash_dev-1.1.68 → freesolo_flash_dev-1.1.70}/flash/cost/spec.py +0 -0
  130. {freesolo_flash_dev-1.1.68 → freesolo_flash_dev-1.1.70}/flash/cost/types.py +0 -0
  131. {freesolo_flash_dev-1.1.68 → freesolo_flash_dev-1.1.70}/flash/engine/__init__.py +0 -0
  132. {freesolo_flash_dev-1.1.68 → freesolo_flash_dev-1.1.70}/flash/engine/plan/__init__.py +0 -0
  133. {freesolo_flash_dev-1.1.68 → freesolo_flash_dev-1.1.70}/flash/engine/plan/kv_sizing.py +0 -0
  134. {freesolo_flash_dev-1.1.68 → freesolo_flash_dev-1.1.70}/flash/engine/plan/model_config_probe.py +0 -0
  135. {freesolo_flash_dev-1.1.68 → freesolo_flash_dev-1.1.70}/flash/engine/plan/recipe.py +0 -0
  136. {freesolo_flash_dev-1.1.68 → freesolo_flash_dev-1.1.70}/flash/engine/plan/steps.py +0 -0
  137. {freesolo_flash_dev-1.1.68 → freesolo_flash_dev-1.1.70}/flash/engine/plan/vram.py +0 -0
  138. {freesolo_flash_dev-1.1.68 → freesolo_flash_dev-1.1.70}/flash/engine/profiling/__init__.py +0 -0
  139. {freesolo_flash_dev-1.1.68 → freesolo_flash_dev-1.1.70}/flash/engine/profiling/dataset_profile.py +0 -0
  140. {freesolo_flash_dev-1.1.68 → freesolo_flash_dev-1.1.70}/flash/engine/profiling/reward_profile.py +0 -0
  141. {freesolo_flash_dev-1.1.68 → freesolo_flash_dev-1.1.70}/flash/engine/profiling/sft_workload.py +0 -0
  142. {freesolo_flash_dev-1.1.68 → freesolo_flash_dev-1.1.70}/flash/engine/profiling/tokenizer.py +0 -0
  143. {freesolo_flash_dev-1.1.68 → freesolo_flash_dev-1.1.70}/flash/engine/profiling/workload_profile.py +0 -0
  144. {freesolo_flash_dev-1.1.68 → freesolo_flash_dev-1.1.70}/flash/engine/result/__init__.py +0 -0
  145. {freesolo_flash_dev-1.1.68 → freesolo_flash_dev-1.1.70}/flash/engine/result/accounting.py +0 -0
  146. {freesolo_flash_dev-1.1.68 → freesolo_flash_dev-1.1.70}/flash/engine/result/rollout_samples.py +0 -0
  147. {freesolo_flash_dev-1.1.68 → freesolo_flash_dev-1.1.70}/flash/engine/worker/__main__.py +0 -0
  148. {freesolo_flash_dev-1.1.68 → freesolo_flash_dev-1.1.70}/flash/engine/worker/backend_common.py +0 -0
  149. {freesolo_flash_dev-1.1.68 → freesolo_flash_dev-1.1.70}/flash/engine/worker/entry/__init__.py +0 -0
  150. {freesolo_flash_dev-1.1.68 → freesolo_flash_dev-1.1.70}/flash/engine/worker/entry/opd.py +0 -0
  151. {freesolo_flash_dev-1.1.68 → freesolo_flash_dev-1.1.70}/flash/engine/worker/entry/rl.py +0 -0
  152. {freesolo_flash_dev-1.1.68 → freesolo_flash_dev-1.1.70}/flash/engine/worker/entry/sft.py +0 -0
  153. {freesolo_flash_dev-1.1.68 → freesolo_flash_dev-1.1.70}/flash/engine/worker/io/__init__.py +0 -0
  154. {freesolo_flash_dev-1.1.68 → freesolo_flash_dev-1.1.70}/flash/engine/worker/io/heartbeat.py +0 -0
  155. {freesolo_flash_dev-1.1.68 → freesolo_flash_dev-1.1.70}/flash/engine/worker/io/prefetch.py +0 -0
  156. {freesolo_flash_dev-1.1.68 → freesolo_flash_dev-1.1.70}/flash/engine/worker/io/wandb_log.py +0 -0
  157. {freesolo_flash_dev-1.1.68 → freesolo_flash_dev-1.1.70}/flash/engine/worker/model/__init__.py +0 -0
  158. {freesolo_flash_dev-1.1.68 → freesolo_flash_dev-1.1.70}/flash/engine/worker/model/adapter.py +0 -0
  159. {freesolo_flash_dev-1.1.68 → freesolo_flash_dev-1.1.70}/flash/engine/worker/model/decoding.py +0 -0
  160. {freesolo_flash_dev-1.1.68 → freesolo_flash_dev-1.1.70}/flash/engine/worker/model/packing.py +0 -0
  161. {freesolo_flash_dev-1.1.68 → freesolo_flash_dev-1.1.70}/flash/engine/worker/opd_train.py +0 -0
  162. {freesolo_flash_dev-1.1.68 → freesolo_flash_dev-1.1.70}/flash/engine/worker/opd_train_runner.py +0 -0
  163. {freesolo_flash_dev-1.1.68 → freesolo_flash_dev-1.1.70}/flash/engine/worker/perf/__init__.py +0 -0
  164. {freesolo_flash_dev-1.1.68 → freesolo_flash_dev-1.1.70}/flash/engine/worker/perf/diagnostics.py +0 -0
  165. {freesolo_flash_dev-1.1.68 → freesolo_flash_dev-1.1.70}/flash/engine/worker/perf/lifecycle.py +0 -0
  166. {freesolo_flash_dev-1.1.68 → freesolo_flash_dev-1.1.70}/flash/engine/worker/perf/liger.py +0 -0
  167. {freesolo_flash_dev-1.1.68 → freesolo_flash_dev-1.1.70}/flash/engine/worker/perf/memory.py +0 -0
  168. {freesolo_flash_dev-1.1.68 → freesolo_flash_dev-1.1.70}/flash/engine/worker/rl_train.py +0 -0
  169. {freesolo_flash_dev-1.1.68 → freesolo_flash_dev-1.1.70}/flash/engine/worker/rl_train_runner.py +0 -0
  170. {freesolo_flash_dev-1.1.68 → freesolo_flash_dev-1.1.70}/flash/engine/worker/runtime/__init__.py +0 -0
  171. {freesolo_flash_dev-1.1.68 → freesolo_flash_dev-1.1.70}/flash/engine/worker/runtime/kernel_warmup.py +0 -0
  172. {freesolo_flash_dev-1.1.68 → freesolo_flash_dev-1.1.70}/flash/engine/worker/runtime/pkg_proxy.py +0 -0
  173. {freesolo_flash_dev-1.1.68 → freesolo_flash_dev-1.1.70}/flash/engine/worker/runtime/rng.py +0 -0
  174. {freesolo_flash_dev-1.1.68 → freesolo_flash_dev-1.1.70}/flash/engine/worker/score_batcher.py +0 -0
  175. {freesolo_flash_dev-1.1.68 → freesolo_flash_dev-1.1.70}/flash/engine/worker/sft_train_runner.py +0 -0
  176. {freesolo_flash_dev-1.1.68 → freesolo_flash_dev-1.1.70}/flash/engine/worker/teacher/__init__.py +0 -0
  177. {freesolo_flash_dev-1.1.68 → freesolo_flash_dev-1.1.70}/flash/engine/worker/teacher/client.py +0 -0
  178. {freesolo_flash_dev-1.1.68 → freesolo_flash_dev-1.1.70}/flash/engine/worker/teacher/encoding.py +0 -0
  179. {freesolo_flash_dev-1.1.68 → freesolo_flash_dev-1.1.70}/flash/engine/worker/teacher/tokenizer_align.py +0 -0
  180. {freesolo_flash_dev-1.1.68 → freesolo_flash_dev-1.1.70}/flash/engine/worker/train/__init__.py +0 -0
  181. {freesolo_flash_dev-1.1.68 → freesolo_flash_dev-1.1.70}/flash/engine/worker/train/core/__init__.py +0 -0
  182. {freesolo_flash_dev-1.1.68 → freesolo_flash_dev-1.1.70}/flash/engine/worker/train/core/child/__init__.py +0 -0
  183. {freesolo_flash_dev-1.1.68 → freesolo_flash_dev-1.1.70}/flash/engine/worker/train/core/child/glue.py +0 -0
  184. {freesolo_flash_dev-1.1.68 → freesolo_flash_dev-1.1.70}/flash/engine/worker/train/finalize.py +0 -0
  185. {freesolo_flash_dev-1.1.68 → freesolo_flash_dev-1.1.70}/flash/engine/worker/train/opd/__init__.py +0 -0
  186. {freesolo_flash_dev-1.1.68 → freesolo_flash_dev-1.1.70}/flash/engine/worker/train/opd/batching.py +0 -0
  187. {freesolo_flash_dev-1.1.68 → freesolo_flash_dev-1.1.70}/flash/engine/worker/train/opd/bridge.py +0 -0
  188. {freesolo_flash_dev-1.1.68 → freesolo_flash_dev-1.1.70}/flash/engine/worker/train/opd/child/__init__.py +0 -0
  189. {freesolo_flash_dev-1.1.68 → freesolo_flash_dev-1.1.70}/flash/engine/worker/train/opd/child/bridge.py +0 -0
  190. {freesolo_flash_dev-1.1.68 → freesolo_flash_dev-1.1.70}/flash/engine/worker/train/opd/child/multiturn.py +0 -0
  191. {freesolo_flash_dev-1.1.68 → freesolo_flash_dev-1.1.70}/flash/engine/worker/train/opd/child/plugin.py +0 -0
  192. {freesolo_flash_dev-1.1.68 → freesolo_flash_dev-1.1.70}/flash/engine/worker/train/opd/child/structured.py +0 -0
  193. {freesolo_flash_dev-1.1.68 → freesolo_flash_dev-1.1.70}/flash/engine/worker/train/opd/failures.py +0 -0
  194. {freesolo_flash_dev-1.1.68 → freesolo_flash_dev-1.1.70}/flash/engine/worker/train/opd/gkd.py +0 -0
  195. {freesolo_flash_dev-1.1.68 → freesolo_flash_dev-1.1.70}/flash/engine/worker/train/opd/overrides.py +0 -0
  196. {freesolo_flash_dev-1.1.68 → freesolo_flash_dev-1.1.70}/flash/engine/worker/train/opd/prompts.py +0 -0
  197. {freesolo_flash_dev-1.1.68 → freesolo_flash_dev-1.1.70}/flash/engine/worker/train/opd/scoring.py +0 -0
  198. {freesolo_flash_dev-1.1.68 → freesolo_flash_dev-1.1.70}/flash/engine/worker/train/opd/validation.py +0 -0
  199. {freesolo_flash_dev-1.1.68 → freesolo_flash_dev-1.1.70}/flash/engine/worker/train/rl/__init__.py +0 -0
  200. {freesolo_flash_dev-1.1.68 → freesolo_flash_dev-1.1.70}/flash/engine/worker/train/rl/checkpoints.py +0 -0
  201. {freesolo_flash_dev-1.1.68 → freesolo_flash_dev-1.1.70}/flash/engine/worker/train/rl/child/__init__.py +0 -0
  202. {freesolo_flash_dev-1.1.68 → freesolo_flash_dev-1.1.70}/flash/engine/worker/train/rl/child/multiturn.py +0 -0
  203. {freesolo_flash_dev-1.1.68 → freesolo_flash_dev-1.1.70}/flash/engine/worker/train/rl/child/plugin.py +0 -0
  204. {freesolo_flash_dev-1.1.68 → freesolo_flash_dev-1.1.70}/flash/engine/worker/train/rl/config.py +0 -0
  205. {freesolo_flash_dev-1.1.68 → freesolo_flash_dev-1.1.70}/flash/engine/worker/train/rl/inputs.py +0 -0
  206. {freesolo_flash_dev-1.1.68 → freesolo_flash_dev-1.1.70}/flash/engine/worker/train/rl/multi_turn.py +0 -0
  207. {freesolo_flash_dev-1.1.68 → freesolo_flash_dev-1.1.70}/flash/engine/worker/train/rl/scoring.py +0 -0
  208. {freesolo_flash_dev-1.1.68 → freesolo_flash_dev-1.1.70}/flash/engine/worker/train/rl/shims.py +0 -0
  209. {freesolo_flash_dev-1.1.68 → freesolo_flash_dev-1.1.70}/flash/engine/worker/train/rl/single_turn.py +0 -0
  210. {freesolo_flash_dev-1.1.68 → freesolo_flash_dev-1.1.70}/flash/engine/worker/train/rl/verl_config.py +0 -0
  211. {freesolo_flash_dev-1.1.68 → freesolo_flash_dev-1.1.70}/flash/engine/worker/train/sft/__init__.py +0 -0
  212. {freesolo_flash_dev-1.1.68 → freesolo_flash_dev-1.1.70}/flash/engine/worker/train/sft/checkpoints.py +0 -0
  213. {freesolo_flash_dev-1.1.68 → freesolo_flash_dev-1.1.70}/flash/engine/worker/train/sft/config.py +0 -0
  214. {freesolo_flash_dev-1.1.68 → freesolo_flash_dev-1.1.70}/flash/engine/worker/verl/__init__.py +0 -0
  215. {freesolo_flash_dev-1.1.68 → freesolo_flash_dev-1.1.70}/flash/engine/worker/verl/capabilities.py +0 -0
  216. {freesolo_flash_dev-1.1.68 → freesolo_flash_dev-1.1.70}/flash/engine/worker/verl/checkpoints.py +0 -0
  217. {freesolo_flash_dev-1.1.68 → freesolo_flash_dev-1.1.70}/flash/engine/worker/verl/child_io.py +0 -0
  218. {freesolo_flash_dev-1.1.68 → freesolo_flash_dev-1.1.70}/flash/engine/worker/verl/diagnostics.py +0 -0
  219. {freesolo_flash_dev-1.1.68 → freesolo_flash_dev-1.1.70}/flash/engine/worker/verl/parallelism.py +0 -0
  220. {freesolo_flash_dev-1.1.68 → freesolo_flash_dev-1.1.70}/flash/engine/worker_entrypoint.py +0 -0
  221. {freesolo_flash_dev-1.1.68 → freesolo_flash_dev-1.1.70}/flash/envs/__init__.py +0 -0
  222. {freesolo_flash_dev-1.1.68 → freesolo_flash_dev-1.1.70}/flash/envs/base.py +0 -0
  223. {freesolo_flash_dev-1.1.68 → freesolo_flash_dev-1.1.70}/flash/envs/cache_security.py +0 -0
  224. {freesolo_flash_dev-1.1.68 → freesolo_flash_dev-1.1.70}/flash/envs/dataset_selection.py +0 -0
  225. {freesolo_flash_dev-1.1.68 → freesolo_flash_dev-1.1.70}/flash/envs/evaluations.py +0 -0
  226. {freesolo_flash_dev-1.1.68 → freesolo_flash_dev-1.1.70}/flash/envs/namespace_listing.py +0 -0
  227. {freesolo_flash_dev-1.1.68 → freesolo_flash_dev-1.1.70}/flash/envs/package/__init__.py +0 -0
  228. {freesolo_flash_dev-1.1.68 → freesolo_flash_dev-1.1.70}/flash/envs/package/limits.py +0 -0
  229. {freesolo_flash_dev-1.1.68 → freesolo_flash_dev-1.1.70}/flash/envs/package/unpack.py +0 -0
  230. {freesolo_flash_dev-1.1.68 → freesolo_flash_dev-1.1.70}/flash/envs/pull.py +0 -0
  231. {freesolo_flash_dev-1.1.68 → freesolo_flash_dev-1.1.70}/flash/providers/__init__.py +0 -0
  232. {freesolo_flash_dev-1.1.68 → freesolo_flash_dev-1.1.70}/flash/providers/_lifecycle/__init__.py +0 -0
  233. {freesolo_flash_dev-1.1.68 → freesolo_flash_dev-1.1.70}/flash/providers/_lifecycle/auth.py +0 -0
  234. {freesolo_flash_dev-1.1.68 → freesolo_flash_dev-1.1.70}/flash/providers/_lifecycle/bootstrap.py +0 -0
  235. {freesolo_flash_dev-1.1.68 → freesolo_flash_dev-1.1.70}/flash/providers/_lifecycle/bootstrap_pip.py +0 -0
  236. {freesolo_flash_dev-1.1.68 → freesolo_flash_dev-1.1.70}/flash/providers/_lifecycle/bootstrap_secrets.py +0 -0
  237. {freesolo_flash_dev-1.1.68 → freesolo_flash_dev-1.1.70}/flash/providers/_lifecycle/deadline.py +0 -0
  238. {freesolo_flash_dev-1.1.68 → freesolo_flash_dev-1.1.70}/flash/providers/_lifecycle/http.py +0 -0
  239. {freesolo_flash_dev-1.1.68 → freesolo_flash_dev-1.1.70}/flash/providers/_lifecycle/instance.py +0 -0
  240. {freesolo_flash_dev-1.1.68 → freesolo_flash_dev-1.1.70}/flash/providers/_lifecycle/poll.py +0 -0
  241. {freesolo_flash_dev-1.1.68 → freesolo_flash_dev-1.1.70}/flash/providers/_lifecycle/poll_instance.py +0 -0
  242. {freesolo_flash_dev-1.1.68 → freesolo_flash_dev-1.1.70}/flash/providers/_lifecycle/provider.py +0 -0
  243. {freesolo_flash_dev-1.1.68 → freesolo_flash_dev-1.1.70}/flash/providers/_lifecycle/worker.py +0 -0
  244. {freesolo_flash_dev-1.1.68 → freesolo_flash_dev-1.1.70}/flash/providers/allocator.py +0 -0
  245. {freesolo_flash_dev-1.1.68 → freesolo_flash_dev-1.1.70}/flash/providers/artifacts/__init__.py +0 -0
  246. {freesolo_flash_dev-1.1.68 → freesolo_flash_dev-1.1.70}/flash/providers/artifacts/preload_runpod.py +0 -0
  247. {freesolo_flash_dev-1.1.68 → freesolo_flash_dev-1.1.70}/flash/providers/artifacts/weight_cache.py +0 -0
  248. {freesolo_flash_dev-1.1.68 → freesolo_flash_dev-1.1.70}/flash/providers/base.py +0 -0
  249. {freesolo_flash_dev-1.1.68 → freesolo_flash_dev-1.1.70}/flash/providers/fit_errors.py +0 -0
  250. {freesolo_flash_dev-1.1.68 → freesolo_flash_dev-1.1.70}/flash/providers/lambda_/__init__.py +0 -0
  251. {freesolo_flash_dev-1.1.68 → freesolo_flash_dev-1.1.70}/flash/providers/lambda_/api.py +0 -0
  252. {freesolo_flash_dev-1.1.68 → freesolo_flash_dev-1.1.70}/flash/providers/lambda_/auth.py +0 -0
  253. {freesolo_flash_dev-1.1.68 → freesolo_flash_dev-1.1.70}/flash/providers/lambda_/gpus.py +0 -0
  254. {freesolo_flash_dev-1.1.68 → freesolo_flash_dev-1.1.70}/flash/providers/lambda_/jobs/__init__.py +0 -0
  255. {freesolo_flash_dev-1.1.68 → freesolo_flash_dev-1.1.70}/flash/providers/lambda_/jobs/builders.py +0 -0
  256. {freesolo_flash_dev-1.1.68 → freesolo_flash_dev-1.1.70}/flash/providers/lambda_/jobs/reap.py +0 -0
  257. {freesolo_flash_dev-1.1.68 → freesolo_flash_dev-1.1.70}/flash/providers/lambda_/preflight.py +0 -0
  258. {freesolo_flash_dev-1.1.68 → freesolo_flash_dev-1.1.70}/flash/providers/lambda_/pricing.py +0 -0
  259. {freesolo_flash_dev-1.1.68 → freesolo_flash_dev-1.1.70}/flash/providers/preflight.py +0 -0
  260. {freesolo_flash_dev-1.1.68 → freesolo_flash_dev-1.1.70}/flash/providers/realized.py +0 -0
  261. {freesolo_flash_dev-1.1.68 → freesolo_flash_dev-1.1.70}/flash/providers/runpod/__init__.py +0 -0
  262. {freesolo_flash_dev-1.1.68 → freesolo_flash_dev-1.1.70}/flash/providers/runpod/api.py +0 -0
  263. {freesolo_flash_dev-1.1.68 → freesolo_flash_dev-1.1.70}/flash/providers/runpod/auth.py +0 -0
  264. {freesolo_flash_dev-1.1.68 → freesolo_flash_dev-1.1.70}/flash/providers/runpod/cost.py +0 -0
  265. {freesolo_flash_dev-1.1.68 → freesolo_flash_dev-1.1.70}/flash/providers/runpod/gpus.py +0 -0
  266. {freesolo_flash_dev-1.1.68 → freesolo_flash_dev-1.1.70}/flash/providers/runpod/job_execution.py +0 -0
  267. {freesolo_flash_dev-1.1.68 → freesolo_flash_dev-1.1.70}/flash/providers/runpod/jobs.py +0 -0
  268. {freesolo_flash_dev-1.1.68 → freesolo_flash_dev-1.1.70}/flash/providers/runpod/preflight.py +0 -0
  269. {freesolo_flash_dev-1.1.68 → freesolo_flash_dev-1.1.70}/flash/providers/runpod/pricing.py +0 -0
  270. {freesolo_flash_dev-1.1.68 → freesolo_flash_dev-1.1.70}/flash/providers/runpod/resources.py +0 -0
  271. {freesolo_flash_dev-1.1.68 → freesolo_flash_dev-1.1.70}/flash/providers/runpod/serverless/__init__.py +0 -0
  272. {freesolo_flash_dev-1.1.68 → freesolo_flash_dev-1.1.70}/flash/providers/runpod/serverless/endpoints.py +0 -0
  273. {freesolo_flash_dev-1.1.68 → freesolo_flash_dev-1.1.70}/flash/providers/vast/__init__.py +0 -0
  274. {freesolo_flash_dev-1.1.68 → freesolo_flash_dev-1.1.70}/flash/providers/vast/api.py +0 -0
  275. {freesolo_flash_dev-1.1.68 → freesolo_flash_dev-1.1.70}/flash/providers/vast/auth.py +0 -0
  276. {freesolo_flash_dev-1.1.68 → freesolo_flash_dev-1.1.70}/flash/providers/vast/jobs/__init__.py +0 -0
  277. {freesolo_flash_dev-1.1.68 → freesolo_flash_dev-1.1.70}/flash/providers/vast/jobs/builders.py +0 -0
  278. {freesolo_flash_dev-1.1.68 → freesolo_flash_dev-1.1.70}/flash/providers/vast/preflight.py +0 -0
  279. {freesolo_flash_dev-1.1.68 → freesolo_flash_dev-1.1.70}/flash/providers/vast/pricing.py +0 -0
  280. {freesolo_flash_dev-1.1.68 → freesolo_flash_dev-1.1.70}/flash/py.typed +0 -0
  281. {freesolo_flash_dev-1.1.68 → freesolo_flash_dev-1.1.70}/flash/runner/__init__.py +0 -0
  282. {freesolo_flash_dev-1.1.68 → freesolo_flash_dev-1.1.70}/flash/runner/artifacts.py +0 -0
  283. {freesolo_flash_dev-1.1.68 → freesolo_flash_dev-1.1.70}/flash/runner/costs.py +0 -0
  284. {freesolo_flash_dev-1.1.68 → freesolo_flash_dev-1.1.70}/flash/runner/deadlines.py +0 -0
  285. {freesolo_flash_dev-1.1.68 → freesolo_flash_dev-1.1.70}/flash/runner/preparation.py +0 -0
  286. {freesolo_flash_dev-1.1.68 → freesolo_flash_dev-1.1.70}/flash/runner/reconciliation.py +0 -0
  287. {freesolo_flash_dev-1.1.68 → freesolo_flash_dev-1.1.70}/flash/runner/results/__init__.py +0 -0
  288. {freesolo_flash_dev-1.1.68 → freesolo_flash_dev-1.1.70}/flash/runner/results/verified_revisions.py +0 -0
  289. {freesolo_flash_dev-1.1.68 → freesolo_flash_dev-1.1.70}/flash/runner/status.py +0 -0
  290. {freesolo_flash_dev-1.1.68 → freesolo_flash_dev-1.1.70}/flash/runner/submit.py +0 -0
  291. {freesolo_flash_dev-1.1.68 → freesolo_flash_dev-1.1.70}/flash/runner/supervise/__init__.py +0 -0
  292. {freesolo_flash_dev-1.1.68 → freesolo_flash_dev-1.1.70}/flash/runner/supervise/attach.py +0 -0
  293. {freesolo_flash_dev-1.1.68 → freesolo_flash_dev-1.1.70}/flash/runner/supervise/deploy.py +0 -0
  294. {freesolo_flash_dev-1.1.68 → freesolo_flash_dev-1.1.70}/flash/runner/supervise/lifecycle.py +0 -0
  295. {freesolo_flash_dev-1.1.68 → freesolo_flash_dev-1.1.70}/flash/runner/supervise/recovery.py +0 -0
  296. {freesolo_flash_dev-1.1.68 → freesolo_flash_dev-1.1.70}/flash/runner/supervise/transitions.py +0 -0
  297. {freesolo_flash_dev-1.1.68 → freesolo_flash_dev-1.1.70}/flash/runner/weight_cache.py +0 -0
  298. {freesolo_flash_dev-1.1.68 → freesolo_flash_dev-1.1.70}/flash/schema/__init__.py +0 -0
  299. {freesolo_flash_dev-1.1.68 → freesolo_flash_dev-1.1.70}/flash/schema/fields.py +0 -0
  300. {freesolo_flash_dev-1.1.68 → freesolo_flash_dev-1.1.70}/flash/serve/__init__.py +0 -0
  301. {freesolo_flash_dev-1.1.68 → freesolo_flash_dev-1.1.70}/flash/serve/deploy.py +0 -0
  302. {freesolo_flash_dev-1.1.68 → freesolo_flash_dev-1.1.70}/flash/serve/errors.py +0 -0
  303. {freesolo_flash_dev-1.1.68 → freesolo_flash_dev-1.1.70}/flash/serve/preflight.py +0 -0
  304. {freesolo_flash_dev-1.1.68 → freesolo_flash_dev-1.1.70}/flash/serve/streaming.py +0 -0
  305. {freesolo_flash_dev-1.1.68 → freesolo_flash_dev-1.1.70}/flash/serve/thinking.py +0 -0
  306. {freesolo_flash_dev-1.1.68 → freesolo_flash_dev-1.1.70}/flash/serve/urls.py +0 -0
  307. {freesolo_flash_dev-1.1.68 → freesolo_flash_dev-1.1.70}/flash/server/__init__.py +0 -0
  308. {freesolo_flash_dev-1.1.68 → freesolo_flash_dev-1.1.70}/flash/server/__main__.py +0 -0
  309. {freesolo_flash_dev-1.1.68 → freesolo_flash_dev-1.1.70}/flash/server/app.py +0 -0
  310. {freesolo_flash_dev-1.1.68 → freesolo_flash_dev-1.1.70}/flash/server/billing/__init__.py +0 -0
  311. {freesolo_flash_dev-1.1.68 → freesolo_flash_dev-1.1.70}/flash/server/billing/charges.py +0 -0
  312. {freesolo_flash_dev-1.1.68 → freesolo_flash_dev-1.1.70}/flash/server/billing/retry.py +0 -0
  313. {freesolo_flash_dev-1.1.68 → freesolo_flash_dev-1.1.70}/flash/server/domain/__init__.py +0 -0
  314. {freesolo_flash_dev-1.1.68 → freesolo_flash_dev-1.1.70}/flash/server/domain/checkpoints.py +0 -0
  315. {freesolo_flash_dev-1.1.68 → freesolo_flash_dev-1.1.70}/flash/server/domain/environment_registry.py +0 -0
  316. {freesolo_flash_dev-1.1.68 → freesolo_flash_dev-1.1.70}/flash/server/domain/reconcile.py +0 -0
  317. {freesolo_flash_dev-1.1.68 → freesolo_flash_dev-1.1.70}/flash/server/domain/repo_cleanup.py +0 -0
  318. {freesolo_flash_dev-1.1.68 → freesolo_flash_dev-1.1.70}/flash/server/domain/run_registry.py +0 -0
  319. {freesolo_flash_dev-1.1.68 → freesolo_flash_dev-1.1.70}/flash/server/domain/teacher_broker.py +0 -0
  320. {freesolo_flash_dev-1.1.68 → freesolo_flash_dev-1.1.70}/flash/server/domain/teacher_errors.py +0 -0
  321. {freesolo_flash_dev-1.1.68 → freesolo_flash_dev-1.1.70}/flash/server/domain/teacher_requests.py +0 -0
  322. {freesolo_flash_dev-1.1.68 → freesolo_flash_dev-1.1.70}/flash/server/platform/__init__.py +0 -0
  323. {freesolo_flash_dev-1.1.68 → freesolo_flash_dev-1.1.70}/flash/server/platform/auth.py +0 -0
  324. {freesolo_flash_dev-1.1.68 → freesolo_flash_dev-1.1.70}/flash/server/platform/db.py +0 -0
  325. {freesolo_flash_dev-1.1.68 → freesolo_flash_dev-1.1.70}/flash/server/platform/deps.py +0 -0
  326. {freesolo_flash_dev-1.1.68 → freesolo_flash_dev-1.1.70}/flash/server/platform/internal_client.py +0 -0
  327. {freesolo_flash_dev-1.1.68 → freesolo_flash_dev-1.1.70}/flash/server/platform/locks.py +0 -0
  328. {freesolo_flash_dev-1.1.68 → freesolo_flash_dev-1.1.70}/flash/server/platform/runtime.py +0 -0
  329. {freesolo_flash_dev-1.1.68 → freesolo_flash_dev-1.1.70}/flash/server/routes/__init__.py +0 -0
  330. {freesolo_flash_dev-1.1.68 → freesolo_flash_dev-1.1.70}/flash/server/routes/envs.py +0 -0
  331. {freesolo_flash_dev-1.1.68 → freesolo_flash_dev-1.1.70}/flash/server/routes/meta.py +0 -0
  332. {freesolo_flash_dev-1.1.68 → freesolo_flash_dev-1.1.70}/flash/server/routes/runs.py +0 -0
  333. {freesolo_flash_dev-1.1.68 → freesolo_flash_dev-1.1.70}/flash/server/routes/serving.py +0 -0
  334. {freesolo_flash_dev-1.1.68 → freesolo_flash_dev-1.1.70}/flash/server/routes/serving_completion.py +0 -0
  335. {freesolo_flash_dev-1.1.68 → freesolo_flash_dev-1.1.70}/flash/server/routes/serving_revisions.py +0 -0
  336. {freesolo_flash_dev-1.1.68 → freesolo_flash_dev-1.1.70}/flash/server/routes/serving_smoke.py +0 -0
  337. {freesolo_flash_dev-1.1.68 → freesolo_flash_dev-1.1.70}/flash/server/routes/teacher.py +0 -0
  338. {freesolo_flash_dev-1.1.68 → freesolo_flash_dev-1.1.70}/flash/teacher/__init__.py +0 -0
  339. {freesolo_flash_dev-1.1.68 → freesolo_flash_dev-1.1.70}/flash/teacher/limits.py +0 -0
  340. {freesolo_flash_dev-1.1.68 → freesolo_flash_dev-1.1.70}/scripts/build_dev_dist.py +0 -0
  341. {freesolo_flash_dev-1.1.68 → freesolo_flash_dev-1.1.70}/scripts/check_file_size.py +0 -0
  342. {freesolo_flash_dev-1.1.68 → freesolo_flash_dev-1.1.70}/scripts/check_function_size.py +0 -0
  343. {freesolo_flash_dev-1.1.68 → freesolo_flash_dev-1.1.70}/scripts/check_verl_pin_exists.py +0 -0
  344. {freesolo_flash_dev-1.1.68 → freesolo_flash_dev-1.1.70}/scripts/scrub_history.sh +0 -0
  345. {freesolo_flash_dev-1.1.68 → freesolo_flash_dev-1.1.70}/tests/__init__.py +0 -0
  346. {freesolo_flash_dev-1.1.68 → freesolo_flash_dev-1.1.70}/tests/_helpers/__init__.py +0 -0
  347. {freesolo_flash_dev-1.1.68 → freesolo_flash_dev-1.1.70}/tests/_helpers/profile.py +0 -0
  348. {freesolo_flash_dev-1.1.68 → freesolo_flash_dev-1.1.70}/tests/_helpers/runner.py +0 -0
  349. {freesolo_flash_dev-1.1.68 → freesolo_flash_dev-1.1.70}/tests/_helpers/specs.py +0 -0
  350. {freesolo_flash_dev-1.1.68 → freesolo_flash_dev-1.1.70}/tests/_helpers/teacher.py +0 -0
  351. {freesolo_flash_dev-1.1.68 → freesolo_flash_dev-1.1.70}/tests/_helpers/vast.py +0 -0
  352. {freesolo_flash_dev-1.1.68 → freesolo_flash_dev-1.1.70}/tests/conftest.py +0 -0
  353. {freesolo_flash_dev-1.1.68 → freesolo_flash_dev-1.1.70}/tests/fixtures/math_eval.jsonl +0 -0
  354. {freesolo_flash_dev-1.1.68 → freesolo_flash_dev-1.1.70}/tests/fixtures/math_train.jsonl +0 -0
  355. {freesolo_flash_dev-1.1.68 → freesolo_flash_dev-1.1.70}/tests/live/__init__.py +0 -0
  356. {freesolo_flash_dev-1.1.68 → freesolo_flash_dev-1.1.70}/tests/live/conftest.py +0 -0
  357. {freesolo_flash_dev-1.1.68 → freesolo_flash_dev-1.1.70}/tests/live/test_lambda_live.py +0 -0
  358. {freesolo_flash_dev-1.1.68 → freesolo_flash_dev-1.1.70}/tests/live/test_runpod_live.py +0 -0
  359. {freesolo_flash_dev-1.1.68 → freesolo_flash_dev-1.1.70}/tests/live/test_vast_live.py +0 -0
  360. {freesolo_flash_dev-1.1.68 → freesolo_flash_dev-1.1.70}/tests/test_accounting_coverage.py +0 -0
  361. {freesolo_flash_dev-1.1.68 → freesolo_flash_dev-1.1.70}/tests/test_agent_flash_cli_contract.py +0 -0
  362. {freesolo_flash_dev-1.1.68 → freesolo_flash_dev-1.1.70}/tests/test_algorithms.py +0 -0
  363. {freesolo_flash_dev-1.1.68 → freesolo_flash_dev-1.1.70}/tests/test_allocator.py +0 -0
  364. {freesolo_flash_dev-1.1.68 → freesolo_flash_dev-1.1.70}/tests/test_backend_common.py +0 -0
  365. {freesolo_flash_dev-1.1.68 → freesolo_flash_dev-1.1.70}/tests/test_backend_jobspec_contract.py +0 -0
  366. {freesolo_flash_dev-1.1.68 → freesolo_flash_dev-1.1.70}/tests/test_bake_kernel_cache.py +0 -0
  367. {freesolo_flash_dev-1.1.68 → freesolo_flash_dev-1.1.70}/tests/test_base_model_provenance.py +0 -0
  368. {freesolo_flash_dev-1.1.68 → freesolo_flash_dev-1.1.70}/tests/test_billing_retry.py +0 -0
  369. {freesolo_flash_dev-1.1.68 → freesolo_flash_dev-1.1.70}/tests/test_build_context_contract.py +0 -0
  370. {freesolo_flash_dev-1.1.68 → freesolo_flash_dev-1.1.70}/tests/test_cancel_remote.py +0 -0
  371. {freesolo_flash_dev-1.1.68 → freesolo_flash_dev-1.1.70}/tests/test_catalog_consistency.py +0 -0
  372. {freesolo_flash_dev-1.1.68 → freesolo_flash_dev-1.1.70}/tests/test_catalog_only_models.py +0 -0
  373. {freesolo_flash_dev-1.1.68 → freesolo_flash_dev-1.1.70}/tests/test_charge_pricing.py +0 -0
  374. {freesolo_flash_dev-1.1.68 → freesolo_flash_dev-1.1.70}/tests/test_checkpoints.py +0 -0
  375. {freesolo_flash_dev-1.1.68 → freesolo_flash_dev-1.1.70}/tests/test_cli_commands.py +0 -0
  376. {freesolo_flash_dev-1.1.68 → freesolo_flash_dev-1.1.70}/tests/test_cli_commands_coverage.py +0 -0
  377. {freesolo_flash_dev-1.1.68 → freesolo_flash_dev-1.1.70}/tests/test_cli_credential_shadowing.py +0 -0
  378. {freesolo_flash_dev-1.1.68 → freesolo_flash_dev-1.1.70}/tests/test_cli_errors.py +0 -0
  379. {freesolo_flash_dev-1.1.68 → freesolo_flash_dev-1.1.70}/tests/test_cli_estimate.py +0 -0
  380. {freesolo_flash_dev-1.1.68 → freesolo_flash_dev-1.1.70}/tests/test_cli_gpus_flag.py +0 -0
  381. {freesolo_flash_dev-1.1.68 → freesolo_flash_dev-1.1.70}/tests/test_cli_help.py +0 -0
  382. {freesolo_flash_dev-1.1.68 → freesolo_flash_dev-1.1.70}/tests/test_cli_main_coverage.py +0 -0
  383. {freesolo_flash_dev-1.1.68 → freesolo_flash_dev-1.1.70}/tests/test_cli_managed.py +0 -0
  384. {freesolo_flash_dev-1.1.68 → freesolo_flash_dev-1.1.70}/tests/test_cli_render_coverage.py +0 -0
  385. {freesolo_flash_dev-1.1.68 → freesolo_flash_dev-1.1.70}/tests/test_cli_render_theme.py +0 -0
  386. {freesolo_flash_dev-1.1.68 → freesolo_flash_dev-1.1.70}/tests/test_cli_traces.py +0 -0
  387. {freesolo_flash_dev-1.1.68 → freesolo_flash_dev-1.1.70}/tests/test_cli_wandb_warning.py +0 -0
  388. {freesolo_flash_dev-1.1.68 → freesolo_flash_dev-1.1.70}/tests/test_client.py +0 -0
  389. {freesolo_flash_dev-1.1.68 → freesolo_flash_dev-1.1.70}/tests/test_client_import_purity.py +0 -0
  390. {freesolo_flash_dev-1.1.68 → freesolo_flash_dev-1.1.70}/tests/test_client_server_integration.py +0 -0
  391. {freesolo_flash_dev-1.1.68 → freesolo_flash_dev-1.1.70}/tests/test_client_stream_reads.py +0 -0
  392. {freesolo_flash_dev-1.1.68 → freesolo_flash_dev-1.1.70}/tests/test_config_env_vars.py +0 -0
  393. {freesolo_flash_dev-1.1.68 → freesolo_flash_dev-1.1.70}/tests/test_config_overrides.py +0 -0
  394. {freesolo_flash_dev-1.1.68 → freesolo_flash_dev-1.1.70}/tests/test_controlled_experiment_repairs.py +0 -0
  395. {freesolo_flash_dev-1.1.68 → freesolo_flash_dev-1.1.70}/tests/test_cost_analytical.py +0 -0
  396. {freesolo_flash_dev-1.1.68 → freesolo_flash_dev-1.1.70}/tests/test_cost_equation.py +0 -0
  397. {freesolo_flash_dev-1.1.68 → freesolo_flash_dev-1.1.70}/tests/test_cost_estimate.py +0 -0
  398. {freesolo_flash_dev-1.1.68 → freesolo_flash_dev-1.1.70}/tests/test_cost_hardware.py +0 -0
  399. {freesolo_flash_dev-1.1.68 → freesolo_flash_dev-1.1.70}/tests/test_cost_models.py +0 -0
  400. {freesolo_flash_dev-1.1.68 → freesolo_flash_dev-1.1.70}/tests/test_cost_rewards.py +0 -0
  401. {freesolo_flash_dev-1.1.68 → freesolo_flash_dev-1.1.70}/tests/test_dataset_profile.py +0 -0
  402. {freesolo_flash_dev-1.1.68 → freesolo_flash_dev-1.1.70}/tests/test_deploy_latency.py +0 -0
  403. {freesolo_flash_dev-1.1.68 → freesolo_flash_dev-1.1.70}/tests/test_disk_gb.py +0 -0
  404. {freesolo_flash_dev-1.1.68 → freesolo_flash_dev-1.1.70}/tests/test_endpoint_name.py +0 -0
  405. {freesolo_flash_dev-1.1.68 → freesolo_flash_dev-1.1.70}/tests/test_env_cache_evict.py +0 -0
  406. {freesolo_flash_dev-1.1.68 → freesolo_flash_dev-1.1.70}/tests/test_env_delete.py +0 -0
  407. {freesolo_flash_dev-1.1.68 → freesolo_flash_dev-1.1.70}/tests/test_env_download.py +0 -0
  408. {freesolo_flash_dev-1.1.68 → freesolo_flash_dev-1.1.70}/tests/test_env_download_api.py +0 -0
  409. {freesolo_flash_dev-1.1.68 → freesolo_flash_dev-1.1.70}/tests/test_env_list_api.py +0 -0
  410. {freesolo_flash_dev-1.1.68 → freesolo_flash_dev-1.1.70}/tests/test_env_list_cli.py +0 -0
  411. {freesolo_flash_dev-1.1.68 → freesolo_flash_dev-1.1.70}/tests/test_env_no_install.py +0 -0
  412. {freesolo_flash_dev-1.1.68 → freesolo_flash_dev-1.1.70}/tests/test_env_publish.py +0 -0
  413. {freesolo_flash_dev-1.1.68 → freesolo_flash_dev-1.1.70}/tests/test_env_pull.py +0 -0
  414. {freesolo_flash_dev-1.1.68 → freesolo_flash_dev-1.1.70}/tests/test_env_pull_coverage.py +0 -0
  415. {freesolo_flash_dev-1.1.68 → freesolo_flash_dev-1.1.70}/tests/test_env_pull_loader_coverage.py +0 -0
  416. {freesolo_flash_dev-1.1.68 → freesolo_flash_dev-1.1.70}/tests/test_env_pull_managed_control_plane.py +0 -0
  417. {freesolo_flash_dev-1.1.68 → freesolo_flash_dev-1.1.70}/tests/test_env_push.py +0 -0
  418. {freesolo_flash_dev-1.1.68 → freesolo_flash_dev-1.1.70}/tests/test_env_rate_limit_resolve.py +0 -0
  419. {freesolo_flash_dev-1.1.68 → freesolo_flash_dev-1.1.70}/tests/test_env_ref_pinning.py +0 -0
  420. {freesolo_flash_dev-1.1.68 → freesolo_flash_dev-1.1.70}/tests/test_env_test.py +0 -0
  421. {freesolo_flash_dev-1.1.68 → freesolo_flash_dev-1.1.70}/tests/test_envs_coverage.py +0 -0
  422. {freesolo_flash_dev-1.1.68 → freesolo_flash_dev-1.1.70}/tests/test_flash_mvp.py +0 -0
  423. {freesolo_flash_dev-1.1.68 → freesolo_flash_dev-1.1.70}/tests/test_flash_worker.py +0 -0
  424. {freesolo_flash_dev-1.1.68 → freesolo_flash_dev-1.1.70}/tests/test_flashinfer_cache_dirs.py +0 -0
  425. {freesolo_flash_dev-1.1.68 → freesolo_flash_dev-1.1.70}/tests/test_freesolo_api_transport.py +0 -0
  426. {freesolo_flash_dev-1.1.68 → freesolo_flash_dev-1.1.70}/tests/test_gpu_type_single_field.py +0 -0
  427. {freesolo_flash_dev-1.1.68 → freesolo_flash_dev-1.1.70}/tests/test_gpus.py +0 -0
  428. {freesolo_flash_dev-1.1.68 → freesolo_flash_dev-1.1.70}/tests/test_grpo_params.py +0 -0
  429. {freesolo_flash_dev-1.1.68 → freesolo_flash_dev-1.1.70}/tests/test_grpo_resident_sizing.py +0 -0
  430. {freesolo_flash_dev-1.1.68 → freesolo_flash_dev-1.1.70}/tests/test_grpo_reward_batching.py +0 -0
  431. {freesolo_flash_dev-1.1.68 → freesolo_flash_dev-1.1.70}/tests/test_health_liveness.py +0 -0
  432. {freesolo_flash_dev-1.1.68 → freesolo_flash_dev-1.1.70}/tests/test_hf_retry.py +0 -0
  433. {freesolo_flash_dev-1.1.68 → freesolo_flash_dev-1.1.70}/tests/test_idle_endpoint_reaper.py +0 -0
  434. {freesolo_flash_dev-1.1.68 → freesolo_flash_dev-1.1.70}/tests/test_infisical_secrets.py +0 -0
  435. {freesolo_flash_dev-1.1.68 → freesolo_flash_dev-1.1.70}/tests/test_instance_bootstrap_coverage.py +0 -0
  436. {freesolo_flash_dev-1.1.68 → freesolo_flash_dev-1.1.70}/tests/test_internal_client.py +0 -0
  437. {freesolo_flash_dev-1.1.68 → freesolo_flash_dev-1.1.70}/tests/test_kernel_cache.py +0 -0
  438. {freesolo_flash_dev-1.1.68 → freesolo_flash_dev-1.1.70}/tests/test_kernel_fingerprint.py +0 -0
  439. {freesolo_flash_dev-1.1.68 → freesolo_flash_dev-1.1.70}/tests/test_kv_util.py +0 -0
  440. {freesolo_flash_dev-1.1.68 → freesolo_flash_dev-1.1.70}/tests/test_lambda_api_coverage.py +0 -0
  441. {freesolo_flash_dev-1.1.68 → freesolo_flash_dev-1.1.70}/tests/test_lambda_runner.py +0 -0
  442. {freesolo_flash_dev-1.1.68 → freesolo_flash_dev-1.1.70}/tests/test_logging.py +0 -0
  443. {freesolo_flash_dev-1.1.68 → freesolo_flash_dev-1.1.70}/tests/test_login_perms.py +0 -0
  444. {freesolo_flash_dev-1.1.68 → freesolo_flash_dev-1.1.70}/tests/test_managed_config_fields.py +0 -0
  445. {freesolo_flash_dev-1.1.68 → freesolo_flash_dev-1.1.70}/tests/test_managed_hf_repo.py +0 -0
  446. {freesolo_flash_dev-1.1.68 → freesolo_flash_dev-1.1.70}/tests/test_metrics_schema_agent_contract.py +0 -0
  447. {freesolo_flash_dev-1.1.68 → freesolo_flash_dev-1.1.70}/tests/test_mig_guard.py +0 -0
  448. {freesolo_flash_dev-1.1.68 → freesolo_flash_dev-1.1.70}/tests/test_multi_gpu_gate.py +0 -0
  449. {freesolo_flash_dev-1.1.68 → freesolo_flash_dev-1.1.70}/tests/test_multimodal_training.py +0 -0
  450. {freesolo_flash_dev-1.1.68 → freesolo_flash_dev-1.1.70}/tests/test_named_reward_metrics.py +0 -0
  451. {freesolo_flash_dev-1.1.68 → freesolo_flash_dev-1.1.70}/tests/test_oom_escalate_gpu.py +0 -0
  452. {freesolo_flash_dev-1.1.68 → freesolo_flash_dev-1.1.70}/tests/test_opd.py +0 -0
  453. {freesolo_flash_dev-1.1.68 → freesolo_flash_dev-1.1.70}/tests/test_opd_limits.py +0 -0
  454. {freesolo_flash_dev-1.1.68 → freesolo_flash_dev-1.1.70}/tests/test_opd_train.py +0 -0
  455. {freesolo_flash_dev-1.1.68 → freesolo_flash_dev-1.1.70}/tests/test_orchestrator_flash.py +0 -0
  456. {freesolo_flash_dev-1.1.68 → freesolo_flash_dev-1.1.70}/tests/test_packing.py +0 -0
  457. {freesolo_flash_dev-1.1.68 → freesolo_flash_dev-1.1.70}/tests/test_packing_coverage.py +0 -0
  458. {freesolo_flash_dev-1.1.68 → freesolo_flash_dev-1.1.70}/tests/test_parasail_teacher.py +0 -0
  459. {freesolo_flash_dev-1.1.68 → freesolo_flash_dev-1.1.70}/tests/test_poll_helpers.py +0 -0
  460. {freesolo_flash_dev-1.1.68 → freesolo_flash_dev-1.1.70}/tests/test_preflight.py +0 -0
  461. {freesolo_flash_dev-1.1.68 → freesolo_flash_dev-1.1.70}/tests/test_provider_preflight_coverage.py +0 -0
  462. {freesolo_flash_dev-1.1.68 → freesolo_flash_dev-1.1.70}/tests/test_provider_routing.py +0 -0
  463. {freesolo_flash_dev-1.1.68 → freesolo_flash_dev-1.1.70}/tests/test_provider_teardown_robustness.py +0 -0
  464. {freesolo_flash_dev-1.1.68 → freesolo_flash_dev-1.1.70}/tests/test_providers_symmetry.py +0 -0
  465. {freesolo_flash_dev-1.1.68 → freesolo_flash_dev-1.1.70}/tests/test_realized_cost.py +0 -0
  466. {freesolo_flash_dev-1.1.68 → freesolo_flash_dev-1.1.70}/tests/test_repo_cleanup.py +0 -0
  467. {freesolo_flash_dev-1.1.68 → freesolo_flash_dev-1.1.70}/tests/test_resolve_params_b.py +0 -0
  468. {freesolo_flash_dev-1.1.68 → freesolo_flash_dev-1.1.70}/tests/test_resume_on_retry.py +0 -0
  469. {freesolo_flash_dev-1.1.68 → freesolo_flash_dev-1.1.70}/tests/test_reward_profile.py +0 -0
  470. {freesolo_flash_dev-1.1.68 → freesolo_flash_dev-1.1.70}/tests/test_rl_train.py +0 -0
  471. {freesolo_flash_dev-1.1.68 → freesolo_flash_dev-1.1.70}/tests/test_rollout_profile_quote.py +0 -0
  472. {freesolo_flash_dev-1.1.68 → freesolo_flash_dev-1.1.70}/tests/test_rollout_samples.py +0 -0
  473. {freesolo_flash_dev-1.1.68 → freesolo_flash_dev-1.1.70}/tests/test_rollout_workload_profile.py +0 -0
  474. {freesolo_flash_dev-1.1.68 → freesolo_flash_dev-1.1.70}/tests/test_runmgmt.py +0 -0
  475. {freesolo_flash_dev-1.1.68 → freesolo_flash_dev-1.1.70}/tests/test_runpod_api_delete.py +0 -0
  476. {freesolo_flash_dev-1.1.68 → freesolo_flash_dev-1.1.70}/tests/test_runpod_key_fingerprint.py +0 -0
  477. {freesolo_flash_dev-1.1.68 → freesolo_flash_dev-1.1.70}/tests/test_runpod_key_waterfall.py +0 -0
  478. {freesolo_flash_dev-1.1.68 → freesolo_flash_dev-1.1.70}/tests/test_serve.py +0 -0
  479. {freesolo_flash_dev-1.1.68 → freesolo_flash_dev-1.1.70}/tests/test_serve_reasoning_content.py +0 -0
  480. {freesolo_flash_dev-1.1.68 → freesolo_flash_dev-1.1.70}/tests/test_server_api.py +0 -0
  481. {freesolo_flash_dev-1.1.68 → freesolo_flash_dev-1.1.70}/tests/test_server_app_coverage.py +0 -0
  482. {freesolo_flash_dev-1.1.68 → freesolo_flash_dev-1.1.70}/tests/test_server_auth_singleflight.py +0 -0
  483. {freesolo_flash_dev-1.1.68 → freesolo_flash_dev-1.1.70}/tests/test_server_billing.py +0 -0
  484. {freesolo_flash_dev-1.1.68 → freesolo_flash_dev-1.1.70}/tests/test_server_checkpoints_coverage.py +0 -0
  485. {freesolo_flash_dev-1.1.68 → freesolo_flash_dev-1.1.70}/tests/test_server_db.py +0 -0
  486. {freesolo_flash_dev-1.1.68 → freesolo_flash_dev-1.1.70}/tests/test_server_envs_coverage.py +0 -0
  487. {freesolo_flash_dev-1.1.68 → freesolo_flash_dev-1.1.70}/tests/test_server_locks_coverage.py +0 -0
  488. {freesolo_flash_dev-1.1.68 → freesolo_flash_dev-1.1.70}/tests/test_server_standalone.py +0 -0
  489. {freesolo_flash_dev-1.1.68 → freesolo_flash_dev-1.1.70}/tests/test_serving_context_preflight.py +0 -0
  490. {freesolo_flash_dev-1.1.68 → freesolo_flash_dev-1.1.70}/tests/test_serving_contract.py +0 -0
  491. {freesolo_flash_dev-1.1.68 → freesolo_flash_dev-1.1.70}/tests/test_serving_schema_coverage.py +0 -0
  492. {freesolo_flash_dev-1.1.68 → freesolo_flash_dev-1.1.70}/tests/test_sft_chunked_nll.py +0 -0
  493. {freesolo_flash_dev-1.1.68 → freesolo_flash_dev-1.1.70}/tests/test_sft_example_selection.py +0 -0
  494. {freesolo_flash_dev-1.1.68 → freesolo_flash_dev-1.1.70}/tests/test_sft_gc_off.py +0 -0
  495. {freesolo_flash_dev-1.1.68 → freesolo_flash_dev-1.1.70}/tests/test_sft_max_context.py +0 -0
  496. {freesolo_flash_dev-1.1.68 → freesolo_flash_dev-1.1.70}/tests/test_sft_workload.py +0 -0
  497. {freesolo_flash_dev-1.1.68 → freesolo_flash_dev-1.1.70}/tests/test_spec_and_validation.py +0 -0
  498. {freesolo_flash_dev-1.1.68 → freesolo_flash_dev-1.1.70}/tests/test_step_floor.py +0 -0
  499. {freesolo_flash_dev-1.1.68 → freesolo_flash_dev-1.1.70}/tests/test_step_metrics.py +0 -0
  500. {freesolo_flash_dev-1.1.68 → freesolo_flash_dev-1.1.70}/tests/test_structured_outputs.py +0 -0
  501. {freesolo_flash_dev-1.1.68 → freesolo_flash_dev-1.1.70}/tests/test_teacher_broker.py +0 -0
  502. {freesolo_flash_dev-1.1.68 → freesolo_flash_dev-1.1.70}/tests/test_teacher_encoding_contract.py +0 -0
  503. {freesolo_flash_dev-1.1.68 → freesolo_flash_dev-1.1.70}/tests/test_thinking_config.py +0 -0
  504. {freesolo_flash_dev-1.1.68 → freesolo_flash_dev-1.1.70}/tests/test_train_context_preflight.py +0 -0
  505. {freesolo_flash_dev-1.1.68 → freesolo_flash_dev-1.1.70}/tests/test_training_controls.py +0 -0
  506. {freesolo_flash_dev-1.1.68 → freesolo_flash_dev-1.1.70}/tests/test_type_comment_prose.py +0 -0
  507. {freesolo_flash_dev-1.1.68 → freesolo_flash_dev-1.1.70}/tests/test_vast_api.py +0 -0
  508. {freesolo_flash_dev-1.1.68 → freesolo_flash_dev-1.1.70}/tests/test_vast_api_coverage.py +0 -0
  509. {freesolo_flash_dev-1.1.68 → freesolo_flash_dev-1.1.70}/tests/test_vast_offers.py +0 -0
  510. {freesolo_flash_dev-1.1.68 → freesolo_flash_dev-1.1.70}/tests/test_vast_provider_coverage.py +0 -0
  511. {freesolo_flash_dev-1.1.68 → freesolo_flash_dev-1.1.70}/tests/test_vast_runner.py +0 -0
  512. {freesolo_flash_dev-1.1.68 → freesolo_flash_dev-1.1.70}/tests/test_verified_revisions.py +0 -0
  513. {freesolo_flash_dev-1.1.68 → freesolo_flash_dev-1.1.70}/tests/test_verifiers.py +0 -0
  514. {freesolo_flash_dev-1.1.68 → freesolo_flash_dev-1.1.70}/tests/test_version.py +0 -0
  515. {freesolo_flash_dev-1.1.68 → freesolo_flash_dev-1.1.70}/tests/test_vl_warmstart_adapter_keys.py +0 -0
  516. {freesolo_flash_dev-1.1.68 → freesolo_flash_dev-1.1.70}/tests/test_vram_architecture.py +0 -0
  517. {freesolo_flash_dev-1.1.68 → freesolo_flash_dev-1.1.70}/tests/test_wandb_link.py +0 -0
  518. {freesolo_flash_dev-1.1.68 → freesolo_flash_dev-1.1.70}/tests/test_wandb_naming.py +0 -0
  519. {freesolo_flash_dev-1.1.68 → freesolo_flash_dev-1.1.70}/tests/test_warmstart_adapter_download.py +0 -0
  520. {freesolo_flash_dev-1.1.68 → freesolo_flash_dev-1.1.70}/tests/test_warmstart_cross_repo.py +0 -0
  521. {freesolo_flash_dev-1.1.68 → freesolo_flash_dev-1.1.70}/tests/test_warmstart_error_attribution.py +0 -0
  522. {freesolo_flash_dev-1.1.68 → freesolo_flash_dev-1.1.70}/tests/test_weight_cache.py +0 -0
  523. {freesolo_flash_dev-1.1.68 → freesolo_flash_dev-1.1.70}/tests/test_worker_dryrun.py +0 -0
  524. {freesolo_flash_dev-1.1.68 → freesolo_flash_dev-1.1.70}/tests/test_worker_hardexit.py +0 -0
  525. {freesolo_flash_dev-1.1.68 → freesolo_flash_dev-1.1.70}/tests/test_worker_image.py +0 -0
  526. {freesolo_flash_dev-1.1.68 → freesolo_flash_dev-1.1.70}/tests/test_worker_init_heartbeat.py +0 -0
  527. {freesolo_flash_dev-1.1.68 → freesolo_flash_dev-1.1.70}/tests/test_worker_stack.py +0 -0
  528. {freesolo_flash_dev-1.1.68 → freesolo_flash_dev-1.1.70}/tests/test_worker_thinking.py +0 -0
  529. {freesolo_flash_dev-1.1.68 → freesolo_flash_dev-1.1.70}/tests/test_workflow_contracts.py +0 -0
  530. {freesolo_flash_dev-1.1.68 → freesolo_flash_dev-1.1.70}/tests/test_workload_profile.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.5
2
2
  Name: freesolo-flash-dev
3
- Version: 1.1.68
3
+ Version: 1.1.70
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
@@ -0,0 +1,141 @@
1
+ """Artifact filenames the worker writes and the control plane reads.
2
+
3
+ Every name here crosses a machine boundary: the worker uploads under it, the control plane fetches
4
+ by it, and the two never share a call stack to check. Spelling one on each side makes them agree by
5
+ coincidence, so they are defined once, here.
6
+ """
7
+
8
+ # The PEFT adapter weights file a deployable adapter must carry. Modern saves use safetensors,
9
+ # but older PEFT/default settings may emit adapter_model.bin.
10
+ ADAPTER_WEIGHT_FILES = ("adapter_model.safetensors", "adapter_model.bin")
11
+
12
+ # A PEFT save past its shard size splits the weights across `adapter_model-0000N-of-0000M.<ext>`
13
+ # beside an `adapter_model.<ext>.index.json` mapping every tensor key to the shard holding it.
14
+ ADAPTER_SHARD_PREFIX = "adapter_model-"
15
+ ADAPTER_WEIGHT_SUFFIXES = (".safetensors", ".bin")
16
+ ADAPTER_WEIGHT_INDEX_FILES = tuple(f"{name}.index.json" for name in ADAPTER_WEIGHT_FILES)
17
+
18
+
19
+ def is_adapter_weight_filename(filename: str) -> bool:
20
+ """True for every adapter weight file shape the pipeline accepts, single-file or sharded.
21
+
22
+ One predicate for the same reason the filenames above are defined once: serving validation and
23
+ the exporter never share a call stack, and each spelling the shapes for itself makes them agree
24
+ by coincidence. A disagreement fails silently, because validation accepts a shape the exporter
25
+ skips and the export then ships weights peft loads as a no-op.
26
+
27
+ Filename shape only. Whether a SET of these files is loadable is a different question, because a
28
+ lone shard is not: see :func:`has_loadable_adapter_weights`.
29
+ """
30
+ name = filename.rsplit("/", 1)[-1]
31
+ if name in ADAPTER_WEIGHT_FILES:
32
+ return True
33
+ return name.startswith(ADAPTER_SHARD_PREFIX) and name.endswith(ADAPTER_WEIGHT_SUFFIXES)
34
+
35
+
36
+ def loadable_adapter_weight_files(filenames) -> list[str]:
37
+ """The files peft would load out of ``filenames``, or ``[]`` when it could load none.
38
+
39
+ The set, not the filename, is what decides this, and the difference is the whole point. peft
40
+ binds one representation per suffix -- the single ``adapter_model.<ext>`` when present, otherwise
41
+ the shards -- and it discovers the sharded form ONLY through ``adapter_model.<ext>.index.json``.
42
+ A directory holding ``adapter_model-00001-of-00002.safetensors`` and no index therefore has no
43
+ loadable representation at all: nothing tells peft the sharded form exists, or which shards
44
+ complete it.
45
+
46
+ Accepting that orphan is what let an incomplete upload pass validation. Export then falls back to
47
+ shipping every matching shard when it finds no index, so deployment and export both "succeeded"
48
+ while producing weights peft loads as a no-op -- the silent-disagreement failure this module
49
+ exists to prevent, arriving one level up at the set instead of at the name.
50
+
51
+ A partial shard set is rejected for the same reason: the index names the complete set, so a
52
+ listing missing one of its members cannot be loaded either. Residue carrying a second shard total
53
+ also fails closed. Filenames cannot reveal which total the index references, and guessing risks
54
+ binding stale weights; cleaning the residue or re-uploading makes the representation decidable.
55
+
56
+ Returned in peft's own precedence order, so the caller that reads tensor keys reads exactly the
57
+ files the serving engine will.
58
+ """
59
+ names = {str(name).rsplit("/", 1)[-1] for name in filenames}
60
+ for suffix in ADAPTER_WEIGHT_SUFFIXES:
61
+ single = f"adapter_model{suffix}"
62
+ if single in names:
63
+ return [single]
64
+ referenced = _index_shard_names(names, suffix)
65
+ if referenced:
66
+ return sorted(referenced)
67
+ return []
68
+
69
+
70
+ def has_loadable_adapter_weights(filenames) -> bool:
71
+ """True when ``filenames`` holds weights peft can actually load."""
72
+ return bool(loadable_adapter_weight_files(filenames))
73
+
74
+
75
+ def _index_shard_names(names: set[str], suffix: str) -> set[str]:
76
+ """The shard names an index for ``suffix`` would have to be accompanied by, from names alone.
77
+
78
+ Derived from the ``adapter_model-{k}-of-{n}.<ext>`` convention rather than by reading the index
79
+ file, because every caller here works from a LISTING: serving validates against a remote repo
80
+ listing and the worker against a directory listing, and neither should have to download and
81
+ parse json to answer "is this set complete". The exporter, which already has the files locally,
82
+ still reads the real ``weight_map`` -- that is the authority on which shards are live.
83
+
84
+ Empty when no index is present, the sole candidate shard set is incomplete, or more than one
85
+ candidate total appears. The last case is genuinely undecidable from filenames alone: the index
86
+ names exactly one set but the listing cannot say which, so rejecting loudly is safer than silently
87
+ serving stale weights.
88
+ """
89
+ if f"adapter_model{suffix}.index.json" not in names:
90
+ return set()
91
+ totals = set()
92
+ oversized_total = False
93
+ for name in names:
94
+ if not name.startswith(ADAPTER_SHARD_PREFIX) or not name.endswith(suffix):
95
+ continue
96
+ stem = name[len(ADAPTER_SHARD_PREFIX) : -len(suffix)]
97
+ shard, sep, total = stem.partition("-of-")
98
+ if not (sep and shard.isdigit() and total.isdigit()):
99
+ continue
100
+ parsed_total = int(total)
101
+ if parsed_total <= 0:
102
+ continue
103
+ if parsed_total > len(names):
104
+ # this total cannot be complete, but it still proves the listing contains residue from a
105
+ # different save. keep that ambiguity evidence without materializing an unbounded set.
106
+ oversized_total = True
107
+ continue
108
+ totals.add((total, len(shard)))
109
+ if oversized_total or len(totals) != 1:
110
+ return set()
111
+ total, width = next(iter(totals))
112
+ candidate = {
113
+ f"{ADAPTER_SHARD_PREFIX}{index:0{width}d}-of-{total}{suffix}"
114
+ for index in range(1, int(total) + 1)
115
+ }
116
+ return candidate if candidate <= names else set()
117
+
118
+
119
+ # The largest attempt identity any artifact name may carry. An attempt number reaches a filename and
120
+ # an HF path, so it is bounded rather than merely nonnegative: an unbounded int would still format,
121
+ # and the resulting name is the one thing a later reader has to match exactly.
122
+ MAX_ATTEMPT_ID = (1 << 63) - 1
123
+
124
+
125
+ def attempt_scoped_artifact_name(kind: str, phase: str, attempt: int) -> str:
126
+ """The name of one per-phase, per-attempt worker text artifact.
127
+
128
+ The worker uploads these and the control plane reads them back, so the format is a contract
129
+ between two processes that never share a call stack. It lives here, beside the adapter filenames,
130
+ because a reader that spells the name for itself agrees with the writer only by coincidence --
131
+ and the failure is silent: a missing artifact reads as "the worker uploaded nothing", which is
132
+ exactly what it looks like when the worker crashed. That is the case these files exist to explain.
133
+
134
+ Attempt-scoped because ``hf_prefix()`` is per-RUN, not per-attempt: without the suffix a retry
135
+ would overwrite the attempt that actually reproduced the failure.
136
+ """
137
+ if isinstance(attempt, bool) or not isinstance(attempt, int):
138
+ raise ValueError("attempt must be a nonnegative integer")
139
+ if attempt < 0 or attempt > MAX_ATTEMPT_ID:
140
+ raise ValueError("attempt must be a bounded nonnegative integer")
141
+ return f"{kind}_{phase}_attempt{attempt}.txt"
@@ -189,8 +189,17 @@ def adapter_artifact_identity(
189
189
  token: str | None = None,
190
190
  revision: str | None = None,
191
191
  ) -> AdapterArtifactIdentity:
192
- """Bind adapter config semantics and one required weight object's immutable metadata."""
193
- from flash.adapters.artifacts import ADAPTER_WEIGHT_FILES
192
+ """Bind adapter config semantics and the required weight objects' immutable metadata.
193
+
194
+ Binds whatever peft would load, which for a save past its shard size is the complete
195
+ index-referenced shard set rather than a single file. Asking for the two single-file names by
196
+ path could not see a sharded adapter at all, so warm-starting from one failed here -- at
197
+ submission, before the worker that would have loaded it ever ran.
198
+
199
+ A single-file adapter's digest is unchanged by that: it still binds exactly its one name and
200
+ identity, so an in-flight run's stored identity still compares equal.
201
+ """
202
+ from flash.adapters.artifacts import loadable_adapter_weight_files
194
203
 
195
204
  resolved = resolve_adapter_ref(adapter_ref)
196
205
  if resolved is None:
@@ -198,26 +207,37 @@ def adapter_artifact_identity(
198
207
  repo, prefix = resolved
199
208
  config_bytes = _canonical_config_bytes(config)
200
209
  config_sha256 = hashlib.sha256(config_bytes).hexdigest()
201
- paths = [f"{prefix}/adapter/{name}" for name in ADAPTER_WEIGHT_FILES]
210
+ folder = f"{prefix}/adapter"
202
211
  try:
203
212
  from huggingface_hub import HfApi
204
213
 
205
- infos = HfApi(token=token).get_paths_info(
206
- repo, paths=paths, repo_type="dataset", revision=revision
214
+ infos = list(
215
+ HfApi(token=token).list_repo_tree(
216
+ repo_id=repo,
217
+ path_in_repo=folder,
218
+ repo_type="dataset",
219
+ recursive=False,
220
+ revision=revision,
221
+ )
207
222
  )
208
223
  except Exception as exc:
209
224
  raise ValueError("could not verify source adapter weight identity") from exc
210
225
  by_name = {str(getattr(info, "path", "")).rsplit("/", 1)[-1]: info for info in infos}
211
- selected = next((name for name in ADAPTER_WEIGHT_FILES if name in by_name), None)
212
- if selected is None:
226
+ selected = loadable_adapter_weight_files(by_name)
227
+ if not selected:
213
228
  raise ValueError("source adapter has no required weight file")
214
- weight_identity = _file_identity(by_name[selected])
215
- payload = f"v1\0{config_sha256}\0{selected}\0{weight_identity}".encode()
229
+ identities = [_file_identity(by_name[name]) for name in selected]
230
+ # every selected object, because a sharded adapter's content is the union of its shards: binding
231
+ # only the first would let a later attempt rewrite the rest and still compare equal.
232
+ bound = "\0".join(
233
+ f"{name}\0{identity}" for name, identity in zip(selected, identities, strict=True)
234
+ )
235
+ payload = f"v1\0{config_sha256}\0{bound}".encode()
216
236
  return AdapterArtifactIdentity(
217
237
  digest=hashlib.sha256(payload).hexdigest(),
218
238
  config_sha256=config_sha256,
219
- weight_filename=selected,
220
- weight_identity=weight_identity,
239
+ weight_filename=",".join(selected),
240
+ weight_identity=",".join(identities),
221
241
  )
222
242
 
223
243
 
@@ -2,8 +2,6 @@
2
2
 
3
3
  from __future__ import annotations
4
4
 
5
- import argparse
6
- import math
7
5
  import queue
8
6
  import tempfile
9
7
  import threading
@@ -12,6 +10,12 @@ from datetime import UTC, datetime
12
10
  from pathlib import Path
13
11
 
14
12
  from flash._internal.channel import CLI_NAME
13
+ from flash.cli.commands.env.eval_args import (
14
+ _MAX_CONCURRENCY,
15
+ bounded_concurrency,
16
+ finite_float,
17
+ positive_int,
18
+ )
15
19
  from flash.cli.commands.env.push import _err
16
20
  from flash.cli.commands.env.test import _env_params, _evaluation_example
17
21
  from flash.cli.ui import render
@@ -25,36 +29,6 @@ from flash.envs.evaluations import (
25
29
  validate_evaluation_cases,
26
30
  )
27
31
 
28
- _MAX_CONCURRENCY = 32
29
-
30
-
31
- def positive_int(value: str) -> int:
32
- parsed = int(value)
33
- if parsed < 1:
34
- raise argparse.ArgumentTypeError("must be at least 1")
35
- return parsed
36
-
37
-
38
- def finite_float(value: str) -> float:
39
- """A temperature the chat route will accept.
40
-
41
- Reject non-finite or negative values before they become one paid rejection per case.
42
- The nonnegative floor matches `flash/schema/__init__.py`.
43
- """
44
- parsed = float(value)
45
- if not math.isfinite(parsed):
46
- raise argparse.ArgumentTypeError(f"must be a finite number, got {value}")
47
- if parsed < 0.0:
48
- raise argparse.ArgumentTypeError(f"must be at least 0.0, got {value}")
49
- return parsed
50
-
51
-
52
- def bounded_concurrency(value: str) -> int:
53
- parsed = positive_int(value)
54
- if parsed > _MAX_CONCURRENCY:
55
- raise argparse.ArgumentTypeError(f"must be at most {_MAX_CONCURRENCY}")
56
- return parsed
57
-
58
32
 
59
33
  def _generation_error(case_id: str, message: str) -> EvalResult:
60
34
  return EvalResult(
@@ -159,13 +133,17 @@ def _scored_response(response: str, *, thinking: bool) -> str:
159
133
  """The response as a scorer should see it, matching what training grades.
160
134
 
161
135
  Strip reasoning only for `thinking` runs; raw reasoning mis-grades them, while unconditional
162
- stripping can truncate non-thinking answers that mention `<think>`.
136
+ stripping can truncate non-thinking answers that mention `<think>`. An already-structured value
137
+ passes through: re-deriving it from its own answer-only string destroys the raw and thinking
138
+ views only its producer had the generation to build.
163
139
  """
164
140
  if not thinking:
165
141
  return response
166
142
  from flash.content.thinking import strip_think, thinking_text
167
143
  from flash.envs.adapter import _ScoredResponseText
168
144
 
145
+ if isinstance(response, _ScoredResponseText):
146
+ return response
169
147
  answer = strip_think(response)
170
148
  return _ScoredResponseText(
171
149
  answer if isinstance(answer, str) else response,
@@ -194,22 +172,28 @@ def _score_case(
194
172
  `state_keyword` says which way that suite's signature can take it -- `**kwargs` and
195
173
  keyword-only scorers reject a third positional, `*args` scorers reject the keyword -- so the
196
174
  caller decides, having read the signature.
175
+
176
+ The scorer grades the stripped answer; the RESULT records the raw generation. Stripping for the
177
+ scorer must not shorten what is recorded, on the error path least of all -- a failed case is
178
+ when the reasoning that explains it matters most.
197
179
  """
180
+ recorded_response = response
198
181
  try:
199
182
  scored_text = _scored_response(response, thinking=thinking)
183
+ recorded_response = getattr(scored_text, "raw", response)
200
184
  if state is None:
201
185
  scored = suite.score(case, scored_text)
202
186
  elif state_keyword:
203
187
  scored = suite.score(case, scored_text, state=state)
204
188
  else:
205
189
  scored = suite.score(case, scored_text, state)
206
- return normalize_eval_result(case, response, scored, case_id=case_id)
190
+ return normalize_eval_result(case, recorded_response, scored, case_id=case_id)
207
191
  except (Exception, SystemExit) as exc:
208
192
  return EvalResult(
209
193
  case_id=case_id,
210
194
  passed=False,
211
195
  score=0.0,
212
- response=response,
196
+ response=recorded_response,
213
197
  error=f"scoring failed: {str(exc) or exc.__class__.__name__}",
214
198
  )
215
199
 
@@ -992,4 +976,11 @@ def cmd_env_eval(args) -> int:
992
976
  )
993
977
 
994
978
 
995
- __all__ = ["_MAX_CONCURRENCY", "bounded_concurrency", "cmd_env_eval", "positive_int"]
979
+ # re-exported from eval_args so `flash.cli` keeps importing the eval flag validators from here.
980
+ __all__ = [
981
+ "_MAX_CONCURRENCY",
982
+ "bounded_concurrency",
983
+ "cmd_env_eval",
984
+ "finite_float",
985
+ "positive_int",
986
+ ]
@@ -0,0 +1,43 @@
1
+ """argparse type validators for `flash env eval`.
2
+
3
+ Separated from `eval.py` so the evaluation driver stays under the file-size limit. These reject a
4
+ bad flag value at parse time, before the command spends anything: a temperature the chat route will
5
+ refuse costs one paid rejection per case if it is discovered case by case instead.
6
+ """
7
+
8
+ from __future__ import annotations
9
+
10
+ import argparse
11
+ import math
12
+
13
+ # ceiling on parallel model requests: enough to keep a deployment busy without opening so many
14
+ # connections that the suite is rate limited into slower wall-clock than a smaller fan-out.
15
+ _MAX_CONCURRENCY = 32
16
+
17
+
18
+ def positive_int(value: str) -> int:
19
+ parsed = int(value)
20
+ if parsed < 1:
21
+ raise argparse.ArgumentTypeError("must be at least 1")
22
+ return parsed
23
+
24
+
25
+ def finite_float(value: str) -> float:
26
+ """A temperature the chat route will accept.
27
+
28
+ Reject non-finite or negative values before they become one paid rejection per case.
29
+ The nonnegative floor matches `flash/schema/__init__.py`.
30
+ """
31
+ parsed = float(value)
32
+ if not math.isfinite(parsed):
33
+ raise argparse.ArgumentTypeError(f"must be a finite number, got {value}")
34
+ if parsed < 0.0:
35
+ raise argparse.ArgumentTypeError(f"must be at least 0.0, got {value}")
36
+ return parsed
37
+
38
+
39
+ def bounded_concurrency(value: str) -> int:
40
+ parsed = positive_int(value)
41
+ if parsed > _MAX_CONCURRENCY:
42
+ raise argparse.ArgumentTypeError(f"must be at most {_MAX_CONCURRENCY}")
43
+ return parsed
@@ -11,6 +11,8 @@ import tomllib
11
11
  from collections.abc import Callable
12
12
  from pathlib import Path
13
13
 
14
+ from flash._internal.channel import CLI_NAME
15
+
14
16
 
15
17
  def _text(path: Path) -> str:
16
18
  """The file's text, or "" if it cannot be decoded as UTF-8.
@@ -40,8 +42,15 @@ def _warn_if_retained_starter_files_describe_another_plane(
40
42
  Deliberately project-INDEPENDENT, unlike `_render_starter`, which interpolates the real uuid: a
41
43
  directory scaffolded under one project and rerun under another still holds the OLD uuid, so an
42
44
  interpolated marker would miss it. Match the project-invariant prefix instead.
45
+
46
+ CLI-name-independent for the same reason: the guidance names the executable the operator invoked
47
+ (`flash`, `flash-cli`, `python -m flash.cli`), so a scaffold written under the alias carries a
48
+ different command than one written under `flash`. Anchoring on `flash` would silently stop
49
+ recognising those files as hosted scaffolds -- the retained-file warning is the only thing that
50
+ tells the operator their guidance now describes the wrong plane, so it must not depend on which
51
+ entry point happened to write it.
43
52
  """
44
- push_marker = "`flash env push --project "
53
+ push_marker = "env push --project "
45
54
  # `_render_starter` writes DIFFERENT guidance into each file, so the reverse direction needs
46
55
  # both markers: matching only environment.py's would warn about that file while silently
47
56
  # keeping a stale evaluations.py beside it.
@@ -63,11 +72,12 @@ def _warn_if_retained_starter_files_describe_another_plane(
63
72
  warn(
64
73
  f"existing {names} document a self-hosted plane, but this one publishes to the managed "
65
74
  "hub; keeping the files unchanged. Their guidance to commit the environment to your own "
66
- "git repo does not apply here -- run `flash env push` and use the returned id instead"
75
+ f"git repo does not apply here -- run `{CLI_NAME} env push` and use the returned id "
76
+ "instead"
67
77
  )
68
78
  return
69
79
  warn(
70
- f"existing {names} still tell you to run `flash env push`, which this plane cannot do; "
80
+ f"existing {names} still tell you to run `{CLI_NAME} env push`, which this plane cannot do; "
71
81
  "keeping the files unchanged. Commit the environment to a git repo your plane can read and "
72
82
  "name it in [environment] id"
73
83
  )
@@ -396,19 +396,23 @@ def _require_setup_project(args) -> str:
396
396
  # Guidance the starter .py docstrings carry, per plane kind. The templates hold placeholders
397
397
  # rather than one plane's wording plus a rewrite pass: matching prose back out after rendering
398
398
  # breaks silently the moment a template is reworded.
399
+ # `CLI_NAME`, not a literal `flash`: the executable is `flash-cli` (or `python -m flash.cli`) when
400
+ # `flash` on PATH belongs to RunPod, and the terminal-facing output below already renders it that
401
+ # way. A generated file that says `flash env push` sends the user to the shadowing binary, which
402
+ # exits 0 without publishing anything -- so the instructions look followed and nothing happened.
399
403
  _HOSTED_GUIDANCE = {
400
404
  "ENVIRONMENT_GUIDANCE": (
401
405
  "upload with\n"
402
- "`flash env push --project PROJECT_UUID --name my-env .`.\n"
406
+ f"`{CLI_NAME} env push --project PROJECT_UUID --name my-env .`.\n"
403
407
  "\n"
404
408
  "A managed run should use the returned [environment] id from\n"
405
- "`flash env push --project PROJECT_UUID --name my-env .`."
409
+ f"`{CLI_NAME} env push --project PROJECT_UUID --name my-env .`."
406
410
  ),
407
411
  "EVALUATIONS_GUIDANCE": (
408
412
  "Publish this file beside environment.py with\n"
409
- "`flash env push --project PROJECT_UUID --name my-env .`, then run the suites against a\n"
410
- "model trained on it with `flash env eval TARGET`. The run names the published\n"
411
- "environment, so `env eval` takes no local path."
413
+ f"`{CLI_NAME} env push --project PROJECT_UUID --name my-env .`, then run the suites\n"
414
+ f"against a model trained on it with `{CLI_NAME} env eval TARGET`. The run names the\n"
415
+ "published environment, so `env eval` takes no local path."
412
416
  ),
413
417
  }
414
418
 
@@ -91,7 +91,7 @@ from flash.engine.worker.train.rl.config import (
91
91
  grpo_overrides,
92
92
  resolve_grpo_prompts_per_step,
93
93
  )
94
- from flash.envs.adapter import GitHubRateLimitError
94
+ from flash.envs.adapter import GitHubTransientError
95
95
  from flash.envs.base import load_environment
96
96
  from flash.teacher.retry_contract import OPD_RESUME_REVISION_ENV
97
97
 
@@ -213,7 +213,10 @@ def require_active_env():
213
213
 
214
214
 
215
215
  def _worker_failure_flags(exc: BaseException) -> dict[str, bool]:
216
- retriable = isinstance(exc, (RetriableInfraError, GitHubRateLimitError))
216
+ # GitHubTransientError covers both the quota case and GitHub being unreachable. The worker's
217
+ # answer to either is the same -- reschedule -- so it catches the base; only the control plane,
218
+ # which has a status code to report, distinguishes them.
219
+ retriable = isinstance(exc, (RetriableInfraError, GitHubTransientError))
217
220
  return {"retriable": retriable, "oom": (not retriable and is_cuda_oom(exc))}
218
221
 
219
222
 
@@ -14,7 +14,7 @@ import time
14
14
  from collections.abc import Callable
15
15
 
16
16
  from flash._internal.diagnostics import sanitize_diagnostic
17
- from flash.adapters.artifacts import ADAPTER_WEIGHT_FILES, attempt_scoped_artifact_name
17
+ from flash.adapters.artifacts import attempt_scoped_artifact_name, has_loadable_adapter_weights
18
18
  from flash.engine.profiling.tokenizer import ( # noqa: F401
19
19
  load_tokenizer,
20
20
  model_revision_kwargs,
@@ -324,10 +324,20 @@ _CHECKPOINT_TRAINER_STATE = (
324
324
 
325
325
 
326
326
  def _has_deployable_adapter(ckpt_dir: str) -> bool:
327
- """Return True if ckpt_dir has a loadable LoRA adapter (config + weights)."""
328
- return os.path.isfile(os.path.join(ckpt_dir, "adapter_config.json")) and any(
329
- os.path.isfile(os.path.join(ckpt_dir, w)) for w in ADAPTER_WEIGHT_FILES
330
- )
327
+ """Return True if ckpt_dir has a loadable LoRA adapter (config + weights).
328
+
329
+ Weights via the shared rule rather than the two single-file names, because a save past peft's
330
+ shard size writes ``adapter_model-0000N-of-0000M.<ext>`` plus an index instead. Spelling only the
331
+ single-file names here made this the strict side of a disagreement: serving and export accept the
332
+ sharded save, so a sharded per-step adapter was silently skipped -- or failed a required save --
333
+ for an artifact the rest of the pipeline would have deployed.
334
+ """
335
+ if not os.path.isfile(os.path.join(ckpt_dir, "adapter_config.json")):
336
+ return False
337
+ try:
338
+ return has_loadable_adapter_weights(os.listdir(ckpt_dir))
339
+ except OSError:
340
+ return False
331
341
 
332
342
 
333
343
  def _write_deployable_provenance(ckpt_dir: str) -> None:
@@ -0,0 +1,118 @@
1
+ """read adapter tensor keys from a downloaded adapter directory, without loading tensor data.
2
+
3
+ helpers must not import ``flash.engine.worker``. heavy dependencies remain lazy so this leaf
4
+ module has no package cycle or eager gpu stack import.
5
+ """
6
+
7
+ from __future__ import annotations
8
+
9
+ # A safetensors header is small even for huge models (a few hundred KB at most); 100 MB is a wildly
10
+ # generous ceiling that still refuses a corrupt/hostile file declaring a multi-GB header length
11
+ # before we allocate/read it.
12
+ _MAX_SAFETENSORS_HEADER_BYTES = 100 * 1024 * 1024
13
+
14
+
15
+ def _read_adapter_tensor_keys(adir: str) -> list[str] | None:
16
+ """return tensor key names from adapter weights without loading tensor data.
17
+
18
+ read only safetensors json headers or torch weights-only state-dict keys. return none if absent.
19
+
20
+ reads whatever peft would bind, which is not always one file: a save past peft's shard size
21
+ writes ``adapter_model-0000N-of-0000M.<ext>`` beside an index, and the keys then live spread
22
+ across the shards. reading only the two single-file names reported such an adapter as having no
23
+ keys at all, so ``_warmstart_adapter_is_loadable`` rejected a warm-start source that serving and
24
+ export both accept.
25
+ """
26
+ import os
27
+
28
+ from flash.adapters.artifacts import loadable_adapter_weight_files
29
+
30
+ try:
31
+ selected = loadable_adapter_weight_files(os.listdir(adir))
32
+ except OSError:
33
+ return None
34
+ if not selected:
35
+ return None
36
+ keys: list[str] = []
37
+ for name in selected:
38
+ path = os.path.join(adir, name)
39
+ if name.endswith(".safetensors"):
40
+ keys.extend(_read_safetensors_tensor_keys(path))
41
+ else:
42
+ keys.extend(_read_bin_tensor_keys(path))
43
+ return keys
44
+
45
+
46
+ def _read_safetensors_tensor_keys(st_path: str) -> list[str]:
47
+ """the tensor keys declared by one safetensors file's header."""
48
+ import json
49
+ import os
50
+ import struct
51
+
52
+ # safetensors layout: 8-byte LE header length, then the JSON header, then the tensor data.
53
+ # Bound the DECLARED header length against the real file size (and an absolute ceiling)
54
+ # BEFORE reading it, so a corrupt/hostile file can't trigger a huge allocation / long read.
55
+ file_size = os.path.getsize(st_path)
56
+ with open(st_path, "rb") as f:
57
+ len_bytes = f.read(8)
58
+ if len(len_bytes) < 8:
59
+ raise ValueError(f"{st_path}: too small to be a safetensors file")
60
+ (hdr_len,) = struct.unpack("<Q", len_bytes)
61
+ if hdr_len > file_size - 8 or hdr_len > _MAX_SAFETENSORS_HEADER_BYTES:
62
+ raise ValueError(
63
+ f"{st_path}: declared safetensors header length {hdr_len} is implausible "
64
+ f"(file is {file_size} bytes) — refusing to read a corrupt/oversized header"
65
+ )
66
+ header_bytes = f.read(hdr_len)
67
+ if len(header_bytes) < hdr_len:
68
+ raise ValueError(f"{st_path}: truncated safetensors header")
69
+ try:
70
+ header = json.loads(header_bytes)
71
+ except (json.JSONDecodeError, UnicodeDecodeError) as exc:
72
+ # A bare JSONDecodeError ("Expecting value: line 1 column 1") — or a
73
+ # UnicodeDecodeError from non-UTF8 header bytes — gives no clue WHICH adapter is
74
+ # corrupt. Re-raise with the file path so a bad download is diagnosable.
75
+ raise ValueError(
76
+ f"{st_path}: safetensors header is not valid JSON "
77
+ f"(corrupt or not a safetensors file): {exc}"
78
+ ) from exc
79
+ # The safetensors header MUST be a JSON object keyed by tensor name. A corrupt/hostile file
80
+ # could decode to a list/int/str, which would later blow up with a confusing TypeError
81
+ # downstream (substring search on a non-str). (JSON object keys are always str, so only the
82
+ # container type needs checking.) Reject a non-object header early with a clear message.
83
+ if not isinstance(header, dict):
84
+ raise ValueError(
85
+ f"{st_path}: safetensors header is not a JSON object "
86
+ "(corrupt or not a safetensors file)"
87
+ )
88
+ data_size = file_size - 8 - hdr_len
89
+ for key, tensor_info in header.items():
90
+ if key == "__metadata__":
91
+ continue
92
+ offsets = tensor_info.get("data_offsets") if isinstance(tensor_info, dict) else None
93
+ if (
94
+ not isinstance(offsets, list)
95
+ or len(offsets) != 2
96
+ or any(not isinstance(offset, int) or isinstance(offset, bool) for offset in offsets)
97
+ or offsets[0] < 0
98
+ or offsets[0] > offsets[1]
99
+ or offsets[1] > data_size
100
+ ):
101
+ raise ValueError(f"{st_path}: invalid or truncated tensor data for {key!r}")
102
+ return [k for k in header if k != "__metadata__"]
103
+
104
+
105
+ def _read_bin_tensor_keys(bin_path: str) -> list[str]:
106
+ """the tensor keys in one torch ``.bin`` adapter state dict, without loading tensor data."""
107
+ import torch
108
+
109
+ state = torch.load(bin_path, map_location="cpu", weights_only=True)
110
+ if not isinstance(state, dict):
111
+ raise ValueError(f"{bin_path}: expected a tensor state dict, got {type(state).__name__}")
112
+ bad = [k for k, v in state.items() if not isinstance(k, str) or not isinstance(v, torch.Tensor)]
113
+ if bad:
114
+ raise ValueError(
115
+ f"{bin_path}: contains non-tensor entries (e.g. {bad[:4]}); "
116
+ "expected a plain PEFT adapter state dict"
117
+ )
118
+ return list(state)
@@ -448,7 +448,15 @@ def _write_sft_result(options, data, model, child, progress, verified, outputs)
448
448
  # share of the batch, so a reader reconstructing the token budget off the request would
449
449
  # believe each rank held rows it never received.
450
450
  "per_device_train_batch_size": child.micro_batch,
451
- "gradient_accumulation_steps": math.ceil(model.train_batch_size / child.micro_batch),
451
+ # over one RANK'S share of the batch, not the global batch. `micro_batch` is already
452
+ # capped to `train_batch_size // world_size` (see `_resolve_sft_width_and_micro_batch`),
453
+ # so dividing the global batch by it was the sequence-parallel formula, where every rank
454
+ # sees the whole batch. under data parallelism it over-counts by the world size, and a
455
+ # reader reconstructing tokens as micro-batch x grad-accum x DP size lands world_size
456
+ # times too high.
457
+ "gradient_accumulation_steps": math.ceil(
458
+ (model.train_batch_size / max(1, child.world_size)) / child.micro_batch
459
+ ),
452
460
  # verl concatenates either way; the profile's mode records whether more than one
453
461
  # example was allowed to share a concatenated batch, which is what a reader of these
454
462
  # metrics needs in order to compare a run's step count against its row count.