freesolo-flash-dev 1.2.60__tar.gz → 1.2.61__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 (577) hide show
  1. {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/PKG-INFO +1 -1
  2. {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/content/multimodal.py +12 -3
  3. {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/engine/worker/backend_common.py +1 -0
  4. {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/engine/worker/train/core/child/glue.py +58 -3
  5. {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/engine/worker/train/opd/overrides.py +2 -26
  6. {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/engine/worker/train/rl/child/multiturn.py +26 -7
  7. {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/engine/worker/train/rl/multi_turn.py +82 -5
  8. {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/engine/worker/train/rl/verl_config.py +2 -0
  9. {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/engine/worker/verl/capabilities.py +10 -0
  10. {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/envs/adapter.py +7 -4
  11. {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/pyproject.toml +2 -2
  12. freesolo_flash_dev-1.2.61/tests/test_catalog_only_models.py +88 -0
  13. {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/tests/test_opd_train.py +4 -22
  14. {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/tests/test_rl_train.py +246 -1
  15. {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/tests/test_spec_and_validation.py +0 -11
  16. {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/tests/test_verifiers.py +48 -1
  17. {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/uv.lock +1 -1
  18. freesolo_flash_dev-1.2.60/tests/test_catalog_only_models.py +0 -357
  19. {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/.dockerignore +0 -0
  20. {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/.env.example +0 -0
  21. {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/.github/CODEOWNERS +0 -0
  22. {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/.github/ISSUE_TEMPLATE/bug_report.yml +0 -0
  23. {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/.github/ISSUE_TEMPLATE/config.yml +0 -0
  24. {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/.github/ISSUE_TEMPLATE/feature_request.yml +0 -0
  25. {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/.github/PULL_REQUEST_TEMPLATE.md +0 -0
  26. {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/.github/dependabot.yml +0 -0
  27. {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/.github/workflows/auto-rebake.yml +0 -0
  28. {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/.github/workflows/bake-kernel-cache.yml +0 -0
  29. {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/.github/workflows/ci.yml +0 -0
  30. {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/.github/workflows/main-source-guard.yml +0 -0
  31. {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/.github/workflows/notify-tests-repo.yml +0 -0
  32. {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/.github/workflows/publish-dev.yml +0 -0
  33. {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/.github/workflows/publish-image.yml +0 -0
  34. {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/.github/workflows/publish.yml +0 -0
  35. {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/.github/workflows/version-parity.yml +0 -0
  36. {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/.github/workflows/worker-image.yml +0 -0
  37. {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/.gitignore +0 -0
  38. {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/CHANGELOG.md +0 -0
  39. {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/CODE_OF_CONDUCT.md +0 -0
  40. {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/CONTRIBUTING.md +0 -0
  41. {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/Dockerfile +0 -0
  42. {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/Dockerfile.worker +0 -0
  43. {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/LICENSE +0 -0
  44. {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/NOTICE +0 -0
  45. {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/README.md +0 -0
  46. {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/SECURITY.md +0 -0
  47. {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/SELF_HOSTING.md +0 -0
  48. {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/build/kernel_cache/.gitignore +0 -0
  49. {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/build/kernel_cache/.keep +0 -0
  50. {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/deploy/infisical/README.md +0 -0
  51. {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/deploy/infisical/entrypoint.sh +0 -0
  52. {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/docker/Dockerfile.kernelcache +0 -0
  53. {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/docker/Dockerfile.kernelcache.relayer +0 -0
  54. {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/docker/bake_kernel_cache.py +0 -0
  55. {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/docker/bake_pod_entry.py +0 -0
  56. {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/docker/extract_cudart_fix.py +0 -0
  57. {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/docker/kernel_fingerprint.py +0 -0
  58. {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/docker/make_rp_handler.py +0 -0
  59. {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/__init__.py +0 -0
  60. {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/_internal/__init__.py +0 -0
  61. {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/_internal/channel.py +0 -0
  62. {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/_internal/diagnostics.py +0 -0
  63. {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/_internal/fileio.py +0 -0
  64. {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/_internal/logging.py +0 -0
  65. {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/_internal/paths.py +0 -0
  66. {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/adapters/__init__.py +0 -0
  67. {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/adapters/artifacts.py +0 -0
  68. {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/adapters/fused_experts.py +0 -0
  69. {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/adapters/lora_rank.py +0 -0
  70. {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/cli/__init__.py +0 -0
  71. {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/cli/__main__.py +0 -0
  72. {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/cli/commands/__init__.py +0 -0
  73. {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/cli/commands/deploy.py +0 -0
  74. {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/cli/commands/env/__init__.py +0 -0
  75. {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/cli/commands/env/episode.py +0 -0
  76. {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/cli/commands/env/eval.py +0 -0
  77. {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/cli/commands/env/eval_args.py +0 -0
  78. {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/cli/commands/env/imports.py +0 -0
  79. {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/cli/commands/env/list.py +0 -0
  80. {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/cli/commands/env/push.py +0 -0
  81. {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/cli/commands/env/retained.py +0 -0
  82. {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/cli/commands/env/setup.py +0 -0
  83. {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/cli/commands/env/test.py +0 -0
  84. {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/cli/commands/env/test_evaluations.py +0 -0
  85. {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/cli/commands/env/test_params.py +0 -0
  86. {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/cli/commands/env/test_warnings.py +0 -0
  87. {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/cli/commands/prompt_budget.py +0 -0
  88. {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/cli/commands/traces.py +0 -0
  89. {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/cli/commands/train_cost.py +0 -0
  90. {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/cli/scaffold/TRAINING.md +0 -0
  91. {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/cli/scaffold/__init__.py +0 -0
  92. {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/cli/ui/__init__.py +0 -0
  93. {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/cli/ui/cost.py +0 -0
  94. {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/cli/ui/env_panels.py +0 -0
  95. {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/cli/ui/heartbeat.py +0 -0
  96. {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/cli/ui/render.py +0 -0
  97. {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/cli/ui/tables.py +0 -0
  98. {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/cli/ui/tty.py +0 -0
  99. {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/client/__init__.py +0 -0
  100. {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/client/config.py +0 -0
  101. {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/client/freesolo_api.py +0 -0
  102. {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/client/http.py +0 -0
  103. {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/client/runtime_secrets.py +0 -0
  104. {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/client/shapes.py +0 -0
  105. {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/client/specs.py +0 -0
  106. {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/client/streaming.py +0 -0
  107. {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/content/__init__.py +0 -0
  108. {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/content/structured_outputs.py +0 -0
  109. {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/content/thinking.py +0 -0
  110. {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/core/__init__.py +0 -0
  111. {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/core/catalog.py +0 -0
  112. {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/core/spec.py +0 -0
  113. {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/core/spec_persistence.py +0 -0
  114. {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/cost/__init__.py +0 -0
  115. {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/cost/analytical.py +0 -0
  116. {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/cost/facts.py +0 -0
  117. {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/cost/spec.py +0 -0
  118. {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/cost/types.py +0 -0
  119. {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/engine/__init__.py +0 -0
  120. {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/engine/plan/__init__.py +0 -0
  121. {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/engine/plan/kv_sizing.py +0 -0
  122. {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/engine/plan/model_config_probe.py +0 -0
  123. {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/engine/plan/prompt_budget.py +0 -0
  124. {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/engine/plan/recipe.py +0 -0
  125. {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/engine/plan/steps.py +0 -0
  126. {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/engine/plan/vram.py +0 -0
  127. {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/engine/profiling/__init__.py +0 -0
  128. {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/engine/profiling/dataset_profile.py +0 -0
  129. {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/engine/profiling/reasoning_render.py +0 -0
  130. {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/engine/profiling/sft_workload.py +0 -0
  131. {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/engine/profiling/tokenizer.py +0 -0
  132. {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/engine/profiling/workload_profile.py +0 -0
  133. {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/engine/result/__init__.py +0 -0
  134. {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/engine/result/accounting.py +0 -0
  135. {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/engine/result/rollout_samples.py +0 -0
  136. {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/engine/worker/__init__.py +0 -0
  137. {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/engine/worker/__main__.py +0 -0
  138. {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/engine/worker/entry/__init__.py +0 -0
  139. {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/engine/worker/entry/opd.py +0 -0
  140. {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/engine/worker/entry/rl.py +0 -0
  141. {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/engine/worker/entry/sft.py +0 -0
  142. {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/engine/worker/io/__init__.py +0 -0
  143. {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/engine/worker/io/heartbeat.py +0 -0
  144. {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/engine/worker/io/hf.py +0 -0
  145. {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/engine/worker/io/prefetch.py +0 -0
  146. {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/engine/worker/io/wandb_log.py +0 -0
  147. {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/engine/worker/model/__init__.py +0 -0
  148. {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/engine/worker/model/adapter.py +0 -0
  149. {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/engine/worker/model/chatml_mask.py +0 -0
  150. {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/engine/worker/model/decoding.py +0 -0
  151. {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/engine/worker/model/lora.py +0 -0
  152. {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/engine/worker/model/packing.py +0 -0
  153. {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/engine/worker/opd_train.py +0 -0
  154. {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/engine/worker/opd_train_runner.py +0 -0
  155. {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/engine/worker/perf/__init__.py +0 -0
  156. {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/engine/worker/perf/diagnostics.py +0 -0
  157. {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/engine/worker/perf/lifecycle.py +0 -0
  158. {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/engine/worker/perf/liger.py +0 -0
  159. {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/engine/worker/perf/memory.py +0 -0
  160. {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/engine/worker/rl_train.py +0 -0
  161. {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/engine/worker/rl_train_runner.py +0 -0
  162. {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/engine/worker/runtime/__init__.py +0 -0
  163. {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/engine/worker/runtime/kernel_warmup.py +0 -0
  164. {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/engine/worker/runtime/pkg_proxy.py +0 -0
  165. {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/engine/worker/runtime/rng.py +0 -0
  166. {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/engine/worker/score_batcher.py +0 -0
  167. {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/engine/worker/sft_train.py +0 -0
  168. {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/engine/worker/sft_train_runner.py +0 -0
  169. {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/engine/worker/teacher/__init__.py +0 -0
  170. {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/engine/worker/teacher/client.py +0 -0
  171. {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/engine/worker/teacher/encoding.py +0 -0
  172. {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/engine/worker/teacher/tokenizer_align.py +0 -0
  173. {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/engine/worker/train/__init__.py +0 -0
  174. {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/engine/worker/train/core/__init__.py +0 -0
  175. {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/engine/worker/train/core/checkpoint_lifecycle.py +0 -0
  176. {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/engine/worker/train/core/child/__init__.py +0 -0
  177. {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/engine/worker/train/core/child/runtime.py +0 -0
  178. {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/engine/worker/train/core/step_timing.py +0 -0
  179. {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/engine/worker/train/finalize.py +0 -0
  180. {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/engine/worker/train/opd/__init__.py +0 -0
  181. {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/engine/worker/train/opd/batching.py +0 -0
  182. {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/engine/worker/train/opd/bridge.py +0 -0
  183. {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/engine/worker/train/opd/child/__init__.py +0 -0
  184. {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/engine/worker/train/opd/child/bridge.py +0 -0
  185. {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/engine/worker/train/opd/child/entry.py +0 -0
  186. {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/engine/worker/train/opd/child/multiturn.py +0 -0
  187. {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/engine/worker/train/opd/child/plugin.py +0 -0
  188. {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/engine/worker/train/opd/child/replay_guard.py +0 -0
  189. {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/engine/worker/train/opd/child/runtime.py +0 -0
  190. {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/engine/worker/train/opd/child/structured.py +0 -0
  191. {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/engine/worker/train/opd/failures.py +0 -0
  192. {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/engine/worker/train/opd/gkd.py +0 -0
  193. {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/engine/worker/train/opd/multiturn_validation.py +0 -0
  194. {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/engine/worker/train/opd/prompts.py +0 -0
  195. {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/engine/worker/train/opd/reporting.py +0 -0
  196. {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/engine/worker/train/opd/scoring.py +0 -0
  197. {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/engine/worker/train/opd/state.py +0 -0
  198. {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/engine/worker/train/opd/validation.py +0 -0
  199. {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/engine/worker/train/rl/__init__.py +0 -0
  200. {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/engine/worker/train/rl/checkpoints.py +0 -0
  201. {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/engine/worker/train/rl/child/__init__.py +0 -0
  202. {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/engine/worker/train/rl/child/entry.py +0 -0
  203. {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/engine/worker/train/rl/child/patches.py +0 -0
  204. {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/engine/worker/train/rl/child/plugin.py +0 -0
  205. {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/engine/worker/train/rl/config.py +0 -0
  206. {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/engine/worker/train/rl/inputs.py +0 -0
  207. {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/engine/worker/train/rl/reward_module.py +0 -0
  208. {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/engine/worker/train/rl/scoring.py +0 -0
  209. {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/engine/worker/train/rl/single_turn.py +0 -0
  210. {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/engine/worker/train/sft/__init__.py +0 -0
  211. {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/engine/worker/train/sft/checkpoints.py +0 -0
  212. {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/engine/worker/train/sft/child/entry.py +0 -0
  213. {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/engine/worker/train/sft/child/plugin.py +0 -0
  214. {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/engine/worker/train/sft/config.py +0 -0
  215. {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/engine/worker/verl/__init__.py +0 -0
  216. {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/engine/worker/verl/checkpoints.py +0 -0
  217. {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/engine/worker/verl/child_io.py +0 -0
  218. {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/engine/worker/verl/diagnostics.py +0 -0
  219. {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/engine/worker/verl/parallelism.py +0 -0
  220. {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/engine/worker/verl/parent_work.py +0 -0
  221. {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/engine/worker_entrypoint.py +0 -0
  222. {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/envs/__init__.py +0 -0
  223. {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/envs/base.py +0 -0
  224. {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/envs/cache_security.py +0 -0
  225. {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/envs/dataset_selection.py +0 -0
  226. {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/envs/evaluations.py +0 -0
  227. {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/envs/identity.py +0 -0
  228. {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/envs/loader.py +0 -0
  229. {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/envs/namespace_listing.py +0 -0
  230. {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/envs/package/__init__.py +0 -0
  231. {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/envs/package/limits.py +0 -0
  232. {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/envs/package/unpack.py +0 -0
  233. {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/envs/pull.py +0 -0
  234. {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/providers/__init__.py +0 -0
  235. {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/providers/_lifecycle/__init__.py +0 -0
  236. {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/providers/_lifecycle/auth.py +0 -0
  237. {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/providers/_lifecycle/bootstrap.py +0 -0
  238. {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/providers/_lifecycle/bootstrap_console.py +0 -0
  239. {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/providers/_lifecycle/bootstrap_pip.py +0 -0
  240. {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/providers/_lifecycle/bootstrap_secrets.py +0 -0
  241. {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/providers/_lifecycle/deadline.py +0 -0
  242. {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/providers/_lifecycle/host/__init__.py +0 -0
  243. {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/providers/_lifecycle/host/deadline_sleep.py +0 -0
  244. {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/providers/_lifecycle/host/failmark.py +0 -0
  245. {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/providers/_lifecycle/host/hostlog.py +0 -0
  246. {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/providers/_lifecycle/http.py +0 -0
  247. {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/providers/_lifecycle/instance.py +0 -0
  248. {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/providers/_lifecycle/poll.py +0 -0
  249. {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/providers/_lifecycle/poll_instance.py +0 -0
  250. {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/providers/_lifecycle/provider.py +0 -0
  251. {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/providers/_lifecycle/terminal_artifacts.py +0 -0
  252. {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/providers/_lifecycle/worker.py +0 -0
  253. {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/providers/allocator.py +0 -0
  254. {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/providers/artifacts/__init__.py +0 -0
  255. {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/providers/artifacts/hf.py +0 -0
  256. {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/providers/artifacts/preload_runpod.py +0 -0
  257. {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/providers/artifacts/weight_cache.py +0 -0
  258. {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/providers/base.py +0 -0
  259. {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/providers/fit_errors.py +0 -0
  260. {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/providers/lambda_/__init__.py +0 -0
  261. {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/providers/lambda_/api.py +0 -0
  262. {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/providers/lambda_/auth.py +0 -0
  263. {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/providers/lambda_/gpus.py +0 -0
  264. {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/providers/lambda_/jobs/__init__.py +0 -0
  265. {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/providers/lambda_/jobs/builders.py +0 -0
  266. {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/providers/lambda_/jobs/reap.py +0 -0
  267. {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/providers/lambda_/preflight.py +0 -0
  268. {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/providers/lambda_/pricing.py +0 -0
  269. {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/providers/preflight.py +0 -0
  270. {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/providers/realized.py +0 -0
  271. {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/providers/runpod/__init__.py +0 -0
  272. {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/providers/runpod/api.py +0 -0
  273. {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/providers/runpod/auth.py +0 -0
  274. {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/providers/runpod/cost.py +0 -0
  275. {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/providers/runpod/gpus.py +0 -0
  276. {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/providers/runpod/job_execution.py +0 -0
  277. {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/providers/runpod/jobs.py +0 -0
  278. {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/providers/runpod/preflight.py +0 -0
  279. {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/providers/runpod/pricing.py +0 -0
  280. {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/providers/runpod/resources.py +0 -0
  281. {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/providers/runpod/serverless/__init__.py +0 -0
  282. {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/providers/runpod/serverless/endpoints.py +0 -0
  283. {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/providers/sharding.py +0 -0
  284. {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/providers/vast/__init__.py +0 -0
  285. {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/providers/vast/api.py +0 -0
  286. {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/providers/vast/auth.py +0 -0
  287. {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/providers/vast/jobs/__init__.py +0 -0
  288. {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/providers/vast/jobs/builders.py +0 -0
  289. {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/providers/vast/preflight.py +0 -0
  290. {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/providers/vast/pricing.py +0 -0
  291. {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/py.typed +0 -0
  292. {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/runner/__init__.py +0 -0
  293. {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/runner/artifacts.py +0 -0
  294. {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/runner/attempts.py +0 -0
  295. {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/runner/costs.py +0 -0
  296. {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/runner/deadlines.py +0 -0
  297. {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/runner/preparation.py +0 -0
  298. {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/runner/reconciliation.py +0 -0
  299. {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/runner/results/__init__.py +0 -0
  300. {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/runner/results/checkpoints.py +0 -0
  301. {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/runner/results/verified_revisions.py +0 -0
  302. {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/runner/status.py +0 -0
  303. {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/runner/submit.py +0 -0
  304. {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/runner/supervise/__init__.py +0 -0
  305. {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/runner/supervise/attach.py +0 -0
  306. {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/runner/supervise/deploy.py +0 -0
  307. {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/runner/supervise/lifecycle.py +0 -0
  308. {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/runner/supervise/recovery.py +0 -0
  309. {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/runner/supervise/retry_decision.py +0 -0
  310. {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/runner/supervise/seed_submission.py +0 -0
  311. {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/runner/supervise/transitions.py +0 -0
  312. {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/runner/weight_cache.py +0 -0
  313. {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/runtime_capsule/__init__.py +0 -0
  314. {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/runtime_capsule/build.py +0 -0
  315. {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/runtime_capsule/manifest.py +0 -0
  316. {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/runtime_capsule/profiles.py +0 -0
  317. {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/schema/__init__.py +0 -0
  318. {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/schema/fields.py +0 -0
  319. {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/serve/__init__.py +0 -0
  320. {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/serve/adapter_check.py +0 -0
  321. {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/serve/deploy.py +0 -0
  322. {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/serve/errors.py +0 -0
  323. {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/serve/export.py +0 -0
  324. {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/serve/preflight.py +0 -0
  325. {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/serve/responses.py +0 -0
  326. {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/serve/streaming.py +0 -0
  327. {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/serve/thinking.py +0 -0
  328. {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/serve/urls.py +0 -0
  329. {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/server/__init__.py +0 -0
  330. {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/server/__main__.py +0 -0
  331. {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/server/app.py +0 -0
  332. {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/server/billing/__init__.py +0 -0
  333. {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/server/billing/charges.py +0 -0
  334. {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/server/billing/retry.py +0 -0
  335. {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/server/domain/__init__.py +0 -0
  336. {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/server/domain/checkpoints.py +0 -0
  337. {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/server/domain/environment_registry.py +0 -0
  338. {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/server/domain/envs.py +0 -0
  339. {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/server/domain/projects.py +0 -0
  340. {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/server/domain/reconcile.py +0 -0
  341. {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/server/domain/repo_cleanup.py +0 -0
  342. {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/server/domain/run_registry.py +0 -0
  343. {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/server/domain/teacher_broker.py +0 -0
  344. {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/server/domain/teacher_errors.py +0 -0
  345. {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/server/domain/teacher_requests.py +0 -0
  346. {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/server/platform/__init__.py +0 -0
  347. {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/server/platform/auth.py +0 -0
  348. {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/server/platform/db.py +0 -0
  349. {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/server/platform/deps.py +0 -0
  350. {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/server/platform/internal_client.py +0 -0
  351. {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/server/platform/locks.py +0 -0
  352. {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/server/platform/runtime.py +0 -0
  353. {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/server/routes/__init__.py +0 -0
  354. {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/server/routes/envs.py +0 -0
  355. {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/server/routes/meta.py +0 -0
  356. {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/server/routes/runs.py +0 -0
  357. {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/server/routes/serving.py +0 -0
  358. {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/server/routes/serving_completion.py +0 -0
  359. {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/server/routes/serving_revisions.py +0 -0
  360. {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/server/routes/serving_smoke.py +0 -0
  361. {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/server/routes/teacher.py +0 -0
  362. {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/teacher/__init__.py +0 -0
  363. {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/teacher/limits.py +0 -0
  364. {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/flash/teacher/retry_contract.py +0 -0
  365. {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/scripts/build_dev_dist.py +0 -0
  366. {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/scripts/check_file_size.py +0 -0
  367. {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/scripts/check_function_size.py +0 -0
  368. {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/scripts/check_verl_pin_exists.py +0 -0
  369. {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/scripts/scrub_history.sh +0 -0
  370. {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/tests/__init__.py +0 -0
  371. {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/tests/_helpers/__init__.py +0 -0
  372. {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/tests/_helpers/profile.py +0 -0
  373. {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/tests/_helpers/runner.py +0 -0
  374. {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/tests/_helpers/specs.py +0 -0
  375. {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/tests/_helpers/teacher.py +0 -0
  376. {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/tests/_helpers/vast.py +0 -0
  377. {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/tests/conftest.py +0 -0
  378. {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/tests/fixtures/math_eval.jsonl +0 -0
  379. {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/tests/fixtures/math_train.jsonl +0 -0
  380. {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/tests/live/__init__.py +0 -0
  381. {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/tests/live/conftest.py +0 -0
  382. {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/tests/live/test_lambda_live.py +0 -0
  383. {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/tests/live/test_runpod_live.py +0 -0
  384. {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/tests/live/test_sft_thinking_render_live.py +0 -0
  385. {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/tests/live/test_vast_live.py +0 -0
  386. {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/tests/test_accounting_coverage.py +0 -0
  387. {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/tests/test_adapter_shard_completeness.py +0 -0
  388. {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/tests/test_agent_flash_cli_contract.py +0 -0
  389. {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/tests/test_algorithms.py +0 -0
  390. {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/tests/test_allocator.py +0 -0
  391. {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/tests/test_backend_common.py +0 -0
  392. {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/tests/test_backend_jobspec_contract.py +0 -0
  393. {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/tests/test_bake_kernel_cache.py +0 -0
  394. {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/tests/test_base_model_provenance.py +0 -0
  395. {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/tests/test_billing_retry.py +0 -0
  396. {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/tests/test_build_context_contract.py +0 -0
  397. {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/tests/test_cancel_remote.py +0 -0
  398. {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/tests/test_catalog_consistency.py +0 -0
  399. {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/tests/test_charge_pricing.py +0 -0
  400. {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/tests/test_checkpoint_lifecycle.py +0 -0
  401. {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/tests/test_checkpoints.py +0 -0
  402. {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/tests/test_cli_commands.py +0 -0
  403. {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/tests/test_cli_commands_coverage.py +0 -0
  404. {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/tests/test_cli_credential_shadowing.py +0 -0
  405. {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/tests/test_cli_errors.py +0 -0
  406. {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/tests/test_cli_estimate.py +0 -0
  407. {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/tests/test_cli_gpus_flag.py +0 -0
  408. {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/tests/test_cli_help.py +0 -0
  409. {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/tests/test_cli_main_coverage.py +0 -0
  410. {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/tests/test_cli_managed.py +0 -0
  411. {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/tests/test_cli_render_coverage.py +0 -0
  412. {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/tests/test_cli_render_theme.py +0 -0
  413. {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/tests/test_cli_traces.py +0 -0
  414. {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/tests/test_cli_wandb_warning.py +0 -0
  415. {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/tests/test_client.py +0 -0
  416. {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/tests/test_client_import_purity.py +0 -0
  417. {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/tests/test_client_server_integration.py +0 -0
  418. {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/tests/test_client_stream_reads.py +0 -0
  419. {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/tests/test_config_env_vars.py +0 -0
  420. {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/tests/test_config_overrides.py +0 -0
  421. {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/tests/test_console_upload.py +0 -0
  422. {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/tests/test_controlled_experiment_repairs.py +0 -0
  423. {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/tests/test_cost_analytical.py +0 -0
  424. {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/tests/test_cost_equation.py +0 -0
  425. {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/tests/test_cost_estimate.py +0 -0
  426. {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/tests/test_cost_hardware.py +0 -0
  427. {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/tests/test_cost_models.py +0 -0
  428. {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/tests/test_dataset_profile.py +0 -0
  429. {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/tests/test_deploy_alias_move_warning.py +0 -0
  430. {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/tests/test_deploy_latency.py +0 -0
  431. {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/tests/test_dev_channel.py +0 -0
  432. {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/tests/test_disk_gb.py +0 -0
  433. {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/tests/test_endpoint_name.py +0 -0
  434. {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/tests/test_env_cache_evict.py +0 -0
  435. {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/tests/test_env_delete.py +0 -0
  436. {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/tests/test_env_download.py +0 -0
  437. {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/tests/test_env_download_api.py +0 -0
  438. {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/tests/test_env_evaluations.py +0 -0
  439. {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/tests/test_env_list_api.py +0 -0
  440. {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/tests/test_env_list_cli.py +0 -0
  441. {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/tests/test_env_list_hub.py +0 -0
  442. {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/tests/test_env_no_install.py +0 -0
  443. {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/tests/test_env_publish.py +0 -0
  444. {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/tests/test_env_pull.py +0 -0
  445. {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/tests/test_env_pull_coverage.py +0 -0
  446. {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/tests/test_env_pull_loader_coverage.py +0 -0
  447. {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/tests/test_env_pull_managed_control_plane.py +0 -0
  448. {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/tests/test_env_push.py +0 -0
  449. {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/tests/test_env_rate_limit_resolve.py +0 -0
  450. {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/tests/test_env_ref_pinning.py +0 -0
  451. {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/tests/test_env_test.py +0 -0
  452. {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/tests/test_envs_coverage.py +0 -0
  453. {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/tests/test_export.py +0 -0
  454. {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/tests/test_flash_mvp.py +0 -0
  455. {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/tests/test_flash_worker.py +0 -0
  456. {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/tests/test_flashinfer_cache_dirs.py +0 -0
  457. {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/tests/test_freesolo_api_transport.py +0 -0
  458. {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/tests/test_fused_expert_warmstart.py +0 -0
  459. {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/tests/test_github_urlopen_retry.py +0 -0
  460. {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/tests/test_gpu_type_single_field.py +0 -0
  461. {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/tests/test_gpus.py +0 -0
  462. {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/tests/test_grpo_params.py +0 -0
  463. {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/tests/test_grpo_resident_sizing.py +0 -0
  464. {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/tests/test_grpo_reward_batching.py +0 -0
  465. {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/tests/test_health_liveness.py +0 -0
  466. {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/tests/test_hf_retry.py +0 -0
  467. {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/tests/test_idle_endpoint_reaper.py +0 -0
  468. {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/tests/test_infisical_secrets.py +0 -0
  469. {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/tests/test_instance_bootstrap_coverage.py +0 -0
  470. {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/tests/test_internal_client.py +0 -0
  471. {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/tests/test_jobs.py +0 -0
  472. {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/tests/test_kernel_cache.py +0 -0
  473. {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/tests/test_kernel_fingerprint.py +0 -0
  474. {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/tests/test_kv_util.py +0 -0
  475. {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/tests/test_lambda_api_coverage.py +0 -0
  476. {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/tests/test_lambda_runner.py +0 -0
  477. {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/tests/test_logging.py +0 -0
  478. {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/tests/test_login_perms.py +0 -0
  479. {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/tests/test_lora_rank_coverage.py +0 -0
  480. {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/tests/test_lora_rank_preflight.py +0 -0
  481. {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/tests/test_managed_config_fields.py +0 -0
  482. {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/tests/test_managed_hf_repo.py +0 -0
  483. {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/tests/test_metrics_schema_agent_contract.py +0 -0
  484. {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/tests/test_mig_guard.py +0 -0
  485. {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/tests/test_multi_gpu_gate.py +0 -0
  486. {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/tests/test_multimodal_training.py +0 -0
  487. {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/tests/test_named_reward_metrics.py +0 -0
  488. {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/tests/test_oom_escalate_gpu.py +0 -0
  489. {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/tests/test_opd.py +0 -0
  490. {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/tests/test_opd_limits.py +0 -0
  491. {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/tests/test_opd_multiturn_eos_boundary.py +0 -0
  492. {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/tests/test_opd_multiturn_failure_exit.py +0 -0
  493. {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/tests/test_opd_replay_guard.py +0 -0
  494. {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/tests/test_opd_resume_safety.py +0 -0
  495. {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/tests/test_orchestrator_flash.py +0 -0
  496. {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/tests/test_packing.py +0 -0
  497. {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/tests/test_packing_coverage.py +0 -0
  498. {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/tests/test_parasail_teacher.py +0 -0
  499. {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/tests/test_persisted_spec_envelope.py +0 -0
  500. {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/tests/test_poll_helpers.py +0 -0
  501. {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/tests/test_preflight.py +0 -0
  502. {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/tests/test_projects.py +0 -0
  503. {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/tests/test_prompt_budget.py +0 -0
  504. {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/tests/test_provider_preflight_coverage.py +0 -0
  505. {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/tests/test_provider_routing.py +0 -0
  506. {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/tests/test_provider_teardown_robustness.py +0 -0
  507. {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/tests/test_providers_symmetry.py +0 -0
  508. {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/tests/test_realized_cost.py +0 -0
  509. {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/tests/test_repo_cleanup.py +0 -0
  510. {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/tests/test_resolve_params_b.py +0 -0
  511. {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/tests/test_resume_on_retry.py +0 -0
  512. {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/tests/test_rollout_samples.py +0 -0
  513. {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/tests/test_runmgmt.py +0 -0
  514. {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/tests/test_runpod_api_delete.py +0 -0
  515. {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/tests/test_runpod_key_fingerprint.py +0 -0
  516. {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/tests/test_runpod_key_waterfall.py +0 -0
  517. {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/tests/test_runtime_capsule.py +0 -0
  518. {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/tests/test_serve.py +0 -0
  519. {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/tests/test_serve_reasoning_content.py +0 -0
  520. {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/tests/test_server_api.py +0 -0
  521. {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/tests/test_server_app_coverage.py +0 -0
  522. {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/tests/test_server_auth_singleflight.py +0 -0
  523. {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/tests/test_server_billing.py +0 -0
  524. {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/tests/test_server_checkpoints_coverage.py +0 -0
  525. {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/tests/test_server_db.py +0 -0
  526. {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/tests/test_server_envs_coverage.py +0 -0
  527. {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/tests/test_server_locks_coverage.py +0 -0
  528. {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/tests/test_server_standalone.py +0 -0
  529. {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/tests/test_serving_context_preflight.py +0 -0
  530. {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/tests/test_serving_contract.py +0 -0
  531. {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/tests/test_serving_schema_coverage.py +0 -0
  532. {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/tests/test_sft_chunked_nll.py +0 -0
  533. {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/tests/test_sft_example_selection.py +0 -0
  534. {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/tests/test_sft_gc_off.py +0 -0
  535. {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/tests/test_sft_max_context.py +0 -0
  536. {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/tests/test_sft_startup_block.py +0 -0
  537. {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/tests/test_sft_train.py +0 -0
  538. {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/tests/test_sft_workload.py +0 -0
  539. {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/tests/test_spec_contract_bytes.py +0 -0
  540. {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/tests/test_step_floor.py +0 -0
  541. {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/tests/test_step_metrics.py +0 -0
  542. {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/tests/test_step_timing.py +0 -0
  543. {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/tests/test_structured_outputs.py +0 -0
  544. {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/tests/test_teacher_broker.py +0 -0
  545. {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/tests/test_teacher_encoding_contract.py +0 -0
  546. {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/tests/test_terminal_artifacts.py +0 -0
  547. {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/tests/test_thinking_config.py +0 -0
  548. {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/tests/test_train_context_preflight.py +0 -0
  549. {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/tests/test_training_controls.py +0 -0
  550. {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/tests/test_type_comment_prose.py +0 -0
  551. {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/tests/test_vast_api.py +0 -0
  552. {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/tests/test_vast_api_coverage.py +0 -0
  553. {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/tests/test_vast_offers.py +0 -0
  554. {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/tests/test_vast_provider_coverage.py +0 -0
  555. {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/tests/test_vast_runner.py +0 -0
  556. {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/tests/test_verified_revisions.py +0 -0
  557. {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/tests/test_verl_checkpoint_export.py +0 -0
  558. {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/tests/test_verl_child_plugins.py +0 -0
  559. {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/tests/test_verl_silence_watchdog.py +0 -0
  560. {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/tests/test_version.py +0 -0
  561. {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/tests/test_vl_warmstart_adapter_keys.py +0 -0
  562. {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/tests/test_vram_architecture.py +0 -0
  563. {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/tests/test_wandb_link.py +0 -0
  564. {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/tests/test_wandb_naming.py +0 -0
  565. {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/tests/test_warmstart_adapter_download.py +0 -0
  566. {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/tests/test_warmstart_cross_repo.py +0 -0
  567. {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/tests/test_warmstart_error_attribution.py +0 -0
  568. {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/tests/test_weight_cache.py +0 -0
  569. {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/tests/test_worker_dryrun.py +0 -0
  570. {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/tests/test_worker_hardexit.py +0 -0
  571. {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/tests/test_worker_image.py +0 -0
  572. {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/tests/test_worker_init_heartbeat.py +0 -0
  573. {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/tests/test_worker_stack.py +0 -0
  574. {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/tests/test_worker_thinking.py +0 -0
  575. {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/tests/test_workflow_contracts.py +0 -0
  576. {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/tests/test_workload_profile.py +0 -0
  577. {freesolo_flash_dev-1.2.60 → freesolo_flash_dev-1.2.61}/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.60
3
+ Version: 1.2.61
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
@@ -250,13 +250,22 @@ def record_has_images(record: dict, messages: list[dict] | None = None) -> bool:
250
250
  return True
251
251
  for message in messages or []:
252
252
  content = message.get("content") if isinstance(message, dict) else None
253
- if isinstance(content, list) and any(
254
- isinstance(block, dict) and block.get("type") in _IMAGE_BLOCK_TYPES for block in content
255
- ):
253
+ if content_has_images(content):
256
254
  return True
257
255
  return False
258
256
 
259
257
 
258
+ def content_has_images(content: object) -> bool:
259
+ """Whether one message's ``content`` carries an image block.
260
+
261
+ The single definition of "this message shows the model an image", so a path that cannot carry
262
+ media (the multi-turn GRPO bridge) recognises exactly what the paths that can do.
263
+ """
264
+ return isinstance(content, list) and any(
265
+ isinstance(block, dict) and block.get("type") in _IMAGE_BLOCK_TYPES for block in content
266
+ )
267
+
268
+
260
269
  def text_only_prompt_messages(messages: list[dict]) -> list[dict]:
261
270
  """Drop image content blocks while preserving the teacher's message order and text."""
262
271
  stripped: list[dict] = []
@@ -935,6 +935,7 @@ from flash.engine.worker.verl.capabilities import ( # noqa: E402,F401
935
935
  resolve_rollout_enforce_eager,
936
936
  resolve_verl_loggers,
937
937
  resolve_verl_python,
938
+ rollout_mm_processor_cache_overrides,
938
939
  rollout_resident_overrides,
939
940
  rollout_sleep_unsupported,
940
941
  strict_gdn_probe_module,
@@ -20,6 +20,12 @@ from uuid import uuid4
20
20
 
21
21
  _ALLOWED_MESSAGE_KEYS = frozenset({"role", "content"})
22
22
  _PROBE_PREFIX = "flash-env-glue-probe"
23
+ # the media block types verl's own dataset parser substitutes for a placeholder, and the exact set
24
+ # it then extracts (rl_dataset.py `_build_messages`: `<image>`/`<video>`/`<audio>` become blocks of
25
+ # the matching type, and `_process_multi_modal_info` returns images, videos, audios). duplicated
26
+ # here as literals rather than imported from flash.content.multimodal because this module is copied
27
+ # into the verl child, where flash is not importable -- see the module docstring.
28
+ _MEDIA_BLOCK_TYPES = frozenset({"image", "video", "audio"})
23
29
 
24
30
 
25
31
  def normalize_token_ids(value) -> list[int]:
@@ -39,8 +45,53 @@ def normalize_token_ids(value) -> list[int]:
39
45
  return [int(token_id.item() if hasattr(token_id, "item") else token_id) for token_id in value]
40
46
 
41
47
 
42
- def validate_transcript_messages(messages: list[dict], *, source: str) -> list[dict]:
43
- """require the exact role/content transcript shape the child rollout loops can represent."""
48
+ def content_block_text(content, *, source: str, position: int) -> str:
49
+ """flatten one openai-style content block list to the text the transcript represents.
50
+
51
+ an image-bearing prompt does NOT reach the child as a string. verl's RLHFDataset rewrites the
52
+ parquet's string content into blocks -- it splits on the `<image>` placeholder and replaces that
53
+ segment with an image block (rl_dataset.py `_build_messages`) -- so `raw_prompt` arrives as
54
+ [{"type": "image", ...}, {"type": "text", "text": ...}] for exactly the multimodal rows flash
55
+ writes. validating that shape as text-only would reject every image episode at turn one.
56
+
57
+ the media blocks are dropped rather than rendered here: they are carried separately, as decoded
58
+ pixels in `multi_modal_data`, and the prompt ids come from the chat template applied to the
59
+ ORIGINAL block list. this text view exists for the transcript and the inter-turn glue, which are
60
+ token-level text operations. a block whose type is neither text nor known media is an error
61
+ rather than a silent drop -- it would mean the model saw something this transcript cannot show.
62
+ """
63
+ parts = []
64
+ for block in content:
65
+ if not isinstance(block, dict):
66
+ raise ValueError(
67
+ f"{source} message {position} has a content block that is not an object"
68
+ )
69
+ block_type = block.get("type")
70
+ if block_type in _MEDIA_BLOCK_TYPES:
71
+ continue
72
+ if block_type != "text":
73
+ raise ValueError(
74
+ f"{source} message {position} has an unsupported content block type "
75
+ f"{block_type!r}; a multi-turn transcript can represent text and media blocks only"
76
+ )
77
+ text = block.get("text")
78
+ if not isinstance(text, str):
79
+ raise ValueError(f"{source} message {position} has a text block without text")
80
+ parts.append(text)
81
+ return "".join(parts)
82
+
83
+
84
+ def validate_transcript_messages(
85
+ messages: list[dict], *, source: str, allow_content_blocks: bool = False
86
+ ) -> list[dict]:
87
+ """require the exact role/content transcript shape the child rollout loops can represent.
88
+
89
+ ``allow_content_blocks`` flattens openai-style block lists to their text instead of rejecting
90
+ them. it is OFF by default and opted into only by a caller that has already extracted the media
91
+ out of the ORIGINAL blocks, because dropping to text is lossless only once the pixels are held
92
+ somewhere else. a caller that has not done that extraction must keep raising: silently training
93
+ on a caption whose image was discarded is the failure this default exists to prevent.
94
+ """
44
95
  if not isinstance(messages, list):
45
96
  raise ValueError(f"{source} messages must be a list")
46
97
  normalized = []
@@ -62,7 +113,11 @@ def validate_transcript_messages(messages: list[dict], *, source: str) -> list[d
62
113
  content = message.get("content")
63
114
  if not isinstance(role, str) or not role.strip():
64
115
  raise ValueError(f"{source} message {position} has an invalid role")
65
- if not isinstance(content, str):
116
+ if allow_content_blocks and isinstance(content, list):
117
+ # a multimodal prompt arrives as content BLOCKS, not a string; flatten to the text this
118
+ # transcript can represent. the media rides separately as decoded pixels.
119
+ content = content_block_text(content, source=source, position=position)
120
+ elif not isinstance(content, str):
66
121
  raise ValueError(f"{source} message {position} content must be text for multi-turn")
67
122
  normalized.append({"role": role, "content": content})
68
123
  return normalized
@@ -17,6 +17,7 @@ from flash.content.structured_outputs import reasoning_parser_for
17
17
  from flash.engine.worker.backend_common import (
18
18
  agent_loop_workers,
19
19
  ray_num_cpus,
20
+ rollout_mm_processor_cache_overrides,
20
21
  rollout_resident_overrides,
21
22
  shim_marker_file,
22
23
  trainer_dtype_overrides,
@@ -177,32 +178,7 @@ def _actor_rollout_overrides(config: dict, *, max_tokens: int) -> list[str]:
177
178
  if config.get("mm_encoder_attn_backend")
178
179
  else []
179
180
  ),
180
- # turn OFF vllm's multimodal processor cache. this is what makes image opd run at all.
181
- #
182
- # the cache is split across two processes. a SENDER half in the frontend replaces an image
183
- # it has already seen with just its hash; a RECEIVER half in the engine core is supposed to
184
- # still hold the item that hash names. correctness depends on the two halves staying
185
- # mirrored, and opd's rollout lifecycle breaks that: every sleep/pause reaches
186
- # `EngineCore._reset_caches()`, which clears the RECEIVER only. vllm says so in its own
187
- # source -- "we don't attempt to re-sync the internal caches (P0 sender, P1 receiver)".
188
- # the sender then keeps sending hash-only requests for images the receiver has dropped, and
189
- # each one dies on `assert mm_item is not None, f"Expected a cached item for {mm_hash=}"`.
190
- #
191
- # that assertion kills the request rather than the run, so the failure surfaces nowhere near
192
- # the cause: the rollouts come back EMPTY, and verl indexes [-1] into a zero-length reward
193
- # tensor, so the visible error is an IndexError with no mention of images.
194
- #
195
- # 0 is vllm's own disable value -- it assigns exactly this internally -- and it gates BOTH
196
- # halves, so no hash-only request can be constructed and there is nothing left to desync.
197
- # the cost is re-preprocessing a repeated image, which is the right trade: an opd rollout
198
- # batch is small and this is the difference between working and not.
199
- #
200
- # it stays unconditional, like `data.image_key` and `limit_images` above, because it is
201
- # inert on a text job -- with no mm items there is no cache to disable.
202
- #
203
- # `mm_processor_cache_gb`, NOT the older `disable_mm_preprocessor_cache`: that argument was
204
- # removed in vllm 0.13.0, and passing it now aborts server startup as an unknown cli flag.
205
- "+actor_rollout_ref.rollout.engine_kwargs.vllm.mm_processor_cache_gb=0",
181
+ *rollout_mm_processor_cache_overrides(),
206
182
  # keep the rollout engine RESIDENT for models whose vLLM wake/reload HANGS (catalog
207
183
  # sleep_unsupported), exactly as the grpo path does. opd is NOT exempt: main_ppo_sync calls
208
184
  # checkpoint_manager.sleep_replicas() during init_workers and again around validation, which
@@ -209,19 +209,41 @@ class _EpisodePrompt:
209
209
 
210
210
 
211
211
  async def _prepare_episode_prompt(loop_self, raw_prompt) -> _EpisodePrompt:
212
- """decode the prompt's media and apply the chat template, in that order."""
213
- multi_modal_data = await loop_self.process_multi_modal_info(raw_prompt)
212
+ """extract the media and render the ids from the ORIGINAL blocks, then validate the transcript.
213
+
214
+ ORDER MATTERS, which is why all three steps live in one function rather than as statements a
215
+ caller could reorder or forget. an image prompt does not arrive as text: verl's RLHFDataset
216
+ rewrites the parquet's string content into blocks, splitting on the `<image>` placeholder and
217
+ substituting an image block (rl_dataset.py `_build_messages`), so `raw_prompt` is
218
+ [{"type": "image", ...}, {"type": "text", ...}] for exactly the rows flash writes for a
219
+ multimodal job. the media has to come out of those ORIGINAL blocks first, or the pixels are gone
220
+ by the time the rollout asks for them -- and validating first would reject the block shape
221
+ outright, which is how multi-turn image rollouts died before the order was pinned here.
222
+
223
+ the media extraction and the chat template both read those original blocks: the pixels live in
224
+ the image/video/audio blocks, and the template needs them in place to emit the placeholder
225
+ tokens the decoded pixels expand into.
226
+
227
+ the validation is a GATE, not a value: this loop generates from `prompt_ids`, so the flattened
228
+ text is discarded. it still runs, because it is what rejects a transcript this loop cannot
229
+ represent (unsupported blocks, tool-call metadata) before the episode is paid for. blocks are
230
+ permitted in that check precisely because the steps above already hold the media and the
231
+ block-rendered ids.
232
+ """
233
+ messages = [dict(message) for message in raw_prompt]
234
+ multi_modal_data = await loop_self.process_multi_modal_info(messages)
214
235
  images = multi_modal_data.get("images")
215
236
  videos = multi_modal_data.get("videos")
216
237
  audios = multi_modal_data.get("audios")
217
238
  mm_processor_kwargs = loop_self._get_mm_processor_kwargs(audios)
218
239
  prompt_ids = await loop_self.apply_chat_template(
219
- raw_prompt,
240
+ messages,
220
241
  images=images,
221
242
  videos=videos,
222
243
  audios=audios,
223
244
  mm_processor_kwargs=mm_processor_kwargs,
224
245
  )
246
+ validate_transcript_messages(messages, source="initial prompt", allow_content_blocks=True)
225
247
  return _EpisodePrompt(multi_modal_data, mm_processor_kwargs, prompt_ids)
226
248
 
227
249
 
@@ -330,10 +352,7 @@ async def _grpo_run(
330
352
  agent_loop_output,
331
353
  **kwargs,
332
354
  ):
333
- raw_prompt = validate_transcript_messages(
334
- [dict(message) for message in kwargs["raw_prompt"]], source="initial prompt"
335
- )
336
- prompt = await _prepare_episode_prompt(self, raw_prompt)
355
+ prompt = await _prepare_episode_prompt(self, kwargs["raw_prompt"])
337
356
  prompt_ids = prompt.prompt_ids
338
357
  mm_processor_kwargs = prompt.mm_processor_kwargs
339
358
  settings = _EpisodeSettings()
@@ -19,6 +19,7 @@ import time
19
19
  from collections.abc import Callable
20
20
  from http.server import BaseHTTPRequestHandler
21
21
 
22
+ from flash.content.multimodal import content_has_images, message_content_text
22
23
  from flash.engine.worker.backend_common import BoundedThreadingHTTPServer
23
24
  from flash.engine.worker.score_batcher import ScoreBatcher
24
25
  from flash.engine.worker.train.rl.scoring import RolloutScoreRequest, score_rollouts
@@ -68,6 +69,17 @@ class _BadSession(_BadRequest, KeyError):
68
69
  return self.args[0] if self.args else ""
69
70
 
70
71
 
72
+ class _BadEnvReply(_BadRequest, ValueError):
73
+ """A reply the environment produced that this transcript cannot carry. Also a ValueError.
74
+
75
+ The property the handler splits on is PERMANENT versus TRANSIENT, and this is permanent: the
76
+ environment will produce the same unrepresentable block on every retry, so it belongs with the
77
+ deliberate rejections rather than with the capacity faults. A bare ValueError here would fall
78
+ to the 503 branch and tell the reader the bridge had a resource problem, when the fix is to
79
+ change the environment's reply -- the same misdirection the 400/503 split exists to prevent.
80
+ """
81
+
82
+
71
83
  def _request_field(payload: dict, key: str):
72
84
  """Read one required payload field, or reject the request.
73
85
 
@@ -104,6 +116,66 @@ def request_session_id(payload: dict) -> str:
104
116
  # and anything else reaching the handler is this side failing to serve a well-formed request.
105
117
  _BAD_REQUEST_ERRORS = (_BadRequest,)
106
118
 
119
+
120
+ def _reject_unrepresentable_reply_blocks(content: list) -> None:
121
+ """Refuse every reply block this transcript cannot carry, not just the image ones.
122
+
123
+ ``message_content_text`` keeps ``type == "text"`` blocks and joins them, which means any OTHER
124
+ block -- video, audio, a tool-use payload, a type this code has never heard of -- contributes
125
+ nothing and vanishes without a trace. that is the same silent corruption as the stringified
126
+ image: the environment intended the model to see something, the model never saw it, and every
127
+ metric still reports a healthy run. so the flattening below is only allowed to run once the
128
+ content is known to be text and nothing but text.
129
+ """
130
+ for position, block in enumerate(content):
131
+ if not isinstance(block, dict):
132
+ raise _BadEnvReply(
133
+ f"environment reply content block {position} must be an object, not "
134
+ f"{type(block).__name__}"
135
+ )
136
+ block_type = block.get("type")
137
+ if block_type != "text":
138
+ raise _BadEnvReply(
139
+ f"environment reply content block {position} has unsupported type {block_type!r}; "
140
+ "a multi-turn GRPO environment reply can carry text blocks only"
141
+ )
142
+ if not isinstance(block.get("text"), str):
143
+ raise _BadEnvReply(f"environment reply text block {position} is missing its text")
144
+
145
+
146
+ def _env_reply_message(message: dict) -> dict:
147
+ """one environment reply message, as the role/content text the child transcript can carry.
148
+
149
+ the adapter lets an environment return arbitrary message dicts from ``step_episode``, so a reply
150
+ may carry openai-style content BLOCKS rather than a string. ``str()`` on a block list does not
151
+ fail -- it produces the python repr, and the model then reads a literal
152
+ ``[{'type': 'image_url', ...}]`` as its prompt text while every metric reports a healthy run.
153
+
154
+ a block the transcript cannot represent is refused outright instead. the media a rollout
155
+ conditions on is fixed from the initial prompt (see ``_EpisodePrompt``), so a mid-episode image
156
+ cannot reach the engine no matter what this returns; stringifying it would train on the repr of
157
+ a dropped image, and dropping it would train on a turn the environment never wrote. refusing is
158
+ the interim contract until per-turn media is threaded into the rollout, and it is LOUD -- the
159
+ bridge turns a raise into a 400 that fails the episode -- because silence is the actual defect.
160
+ """
161
+ content = message.get("content")
162
+ if isinstance(content, list):
163
+ # images get their own message ahead of the generic guard: it is the one unsupported block
164
+ # with an action attached, so saying which one it is beats naming the type alone.
165
+ if content_has_images(content):
166
+ raise _BadEnvReply(
167
+ "environment reply carries an image block; multi-turn GRPO conditions every turn on "
168
+ "the media from the INITIAL prompt, so an image returned by step_episode cannot "
169
+ "reach the model. return text, or put the image in the initial prompt"
170
+ )
171
+ _reject_unrepresentable_reply_blocks(content)
172
+ # text-only blocks are a shape this transcript CAN represent exactly, so flatten them
173
+ # through the same definition of "the text of a message" the graders and reward path use.
174
+ return {"role": str(message.get("role", "")), "content": message_content_text(content)}
175
+ # unchanged for every non-block reply, which is what every existing multi-turn env returns.
176
+ return {"role": str(message.get("role", "")), "content": str(message.get("content", ""))}
177
+
178
+
107
179
  # size the listen backlog for the full prompts_per_step * group_size connection burst.
108
180
  # socketserver's default of 5 resets overflowed clients, and bridge_post intentionally does not retry.
109
181
  # a fixed backlog only moves the cliff; linux may clamp this value to somaxconn.
@@ -263,12 +335,17 @@ class MultiTurnBridge:
263
335
  return {"terminal": True, "messages": []}
264
336
  replies = self._env_call("env_reply", list(state.get("messages") or ()), state)
265
337
  terminal = bool(self._env_call("rollout_done", state, self._max_turns))
338
+ if terminal:
339
+ # nothing here is ever shown to the model: the child breaks on `terminal` BEFORE it
340
+ # reads `messages`. env_reply has already recorded these replies into the state that
341
+ # score_episodes reads, so the episode is scored on them either way. validating them
342
+ # for transcript representability would turn a completed episode whose env signed off
343
+ # with an image or a tool payload into a 400 with no reward -- refusing a turn the
344
+ # model was never going to see.
345
+ return {"terminal": True, "messages": []}
266
346
  return {
267
- "terminal": terminal,
268
- "messages": [
269
- {"role": str(message.get("role", "")), "content": str(message.get("content", ""))}
270
- for message in replies
271
- ],
347
+ "terminal": False,
348
+ "messages": [_env_reply_message(message) for message in replies],
272
349
  }
273
350
 
274
351
  def _score_batch(self, requests: list) -> list:
@@ -17,6 +17,7 @@ from flash.engine.profiling.sft_workload import _multimodal_messages_with_images
17
17
  from flash.engine.worker.backend_common import (
18
18
  agent_loop_workers,
19
19
  ray_num_cpus,
20
+ rollout_mm_processor_cache_overrides,
20
21
  rollout_resident_overrides,
21
22
  rollout_sleep_unsupported,
22
23
  trainer_dtype_overrides,
@@ -332,6 +333,7 @@ def _rollout_overrides(cfg: dict) -> list[str]:
332
333
  ),
333
334
  # safetensors load format is required for lora rollout on vllm.
334
335
  "actor_rollout_ref.rollout.load_format=safetensors",
336
+ *rollout_mm_processor_cache_overrides(),
335
337
  # keep the rollout engine RESIDENT for models whose vLLM wake/reload HANGS (catalog
336
338
  # sleep_unsupported). shared with the opd driver, which runs the same verl sleep path.
337
339
  *rollout_resident_overrides(bool(cfg.get("sleep_unsupported"))),
@@ -758,6 +758,16 @@ def rollout_resident_overrides(sleep_unsupported: bool) -> list[str]:
758
758
  ]
759
759
 
760
760
 
761
+ def rollout_mm_processor_cache_overrides() -> list[str]:
762
+ """disable vllm's split multimodal processor cache for every verl rollout.
763
+
764
+ verl sleep resets the engine-side receiver without resynchronizing the frontend sender, so a
765
+ repeated image can become a hash-only request for an item the receiver no longer holds. zero is
766
+ vllm's disable value for both halves and is inert when a rollout has no multimodal items.
767
+ """
768
+ return ["+actor_rollout_ref.rollout.engine_kwargs.vllm.mm_processor_cache_gb=0"]
769
+
770
+
761
771
  def trainer_dtype_overrides() -> list[str]:
762
772
  """verl overrides that store the frozen base in bf16 instead of verl's fp32 default.
763
773
 
@@ -665,13 +665,16 @@ class FreesoloEnvironment(BaseEnvironment):
665
665
  state["turn"] = int(state.get("turn", 0)) + 1
666
666
  if step.metadata:
667
667
  state.setdefault("step_metadata", []).append(step.metadata)
668
- replies = [dict(message) for message in step.messages]
669
- state.setdefault("messages", []).extend(replies)
670
- for message in replies:
668
+ replies = [deepcopy(dict(message)) for message in step.messages]
669
+ scored_replies = deepcopy(replies)
670
+ state.setdefault("messages", []).extend(scored_replies)
671
+ for message in scored_replies:
672
+ # score_episode receives a structural copy of the environment's raw chat content. the
673
+ # parent bridge flattens only the separate child-bound reply returned below.
671
674
  state.setdefault("turns", []).append(
672
675
  self._EnvironmentTurn(
673
676
  role=str(message.get("role", "")),
674
- content=str(message.get("content", "")),
677
+ content=deepcopy(message.get("content", "")),
675
678
  )
676
679
  )
677
680
  return replies
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "freesolo-flash-dev"
3
- version = "1.2.60"
3
+ version = "1.2.61"
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.60"
140
+ version = "1.2.61"
141
141
 
142
142
  [tool.pytest.ini_options]
143
143
  pythonpath = ["."]
@@ -0,0 +1,88 @@
1
+ """Only curated catalog models are trainable + VRAM estimator unit tests (CPU-only, no network).
2
+
3
+ Adding a model means forking Flash and adding a ModelInfo entry to flash/core/catalog.py. There is no
4
+ config key that accepts an uncataloged model: the rejection is catalog membership itself, so it
5
+ holds identically on a managed and a self-hosted plane.
6
+ """
7
+
8
+ from __future__ import annotations
9
+
10
+ import pytest
11
+
12
+ from flash.core.catalog import resolve_model
13
+ from flash.engine.plan.vram import estimate_vram_gb
14
+ from flash.providers.base import get_gpu_info
15
+ from flash.schema import ConfigError, spec_from_dict
16
+ from tests._helpers.specs import raw_spec as _raw
17
+
18
+
19
+ def test_an_uncataloged_model_is_rejected_with_the_fork_instruction():
20
+ # The error is the primary documentation for the new workflow -- it is what every rejected
21
+ # user sees, so it must name the concrete next step, not just refuse.
22
+ with pytest.raises(ValueError, match="unsupported model") as ei:
23
+ resolve_model("some-org/some-model", "sft")
24
+ message = str(ei.value)
25
+ assert "fork" in message.lower()
26
+ assert "flash/core/catalog.py" in message
27
+
28
+
29
+ def test_catalog_model_resolves_normally():
30
+ info = resolve_model("Qwen/Qwen3.5-4B", "grpo")
31
+ assert info.id == "Qwen/Qwen3.5-4B"
32
+
33
+
34
+ def test_the_parser_rejects_an_uncataloged_model_before_submit():
35
+ # Rejecting client-side means a fork with a new catalog entry works without touching the
36
+ # plane, and a typo fails locally instead of after a network round trip.
37
+ with pytest.raises(ConfigError) as ei:
38
+ spec_from_dict(_raw(model="acme/unlisted"))
39
+ assert "unsupported model" in str(ei.value)
40
+
41
+
42
+ def test_model_policy_is_no_longer_an_accepted_config_key():
43
+ # The key is gone, not merely ignored: a config carrying it must fail loudly rather than
44
+ # silently training something other than what it asked for.
45
+ with pytest.raises(ConfigError, match="unknown config key"):
46
+ spec_from_dict(_raw(model="Qwen/Qwen3.5-4B", model_policy="allow"))
47
+
48
+
49
+ def test_a_catalog_spec_round_trips_without_a_policy_field():
50
+ spec = spec_from_dict(_raw(model="Qwen/Qwen3.5-4B"))
51
+ payload = spec.to_dict()
52
+ assert "model_policy" not in payload
53
+ assert spec_from_dict(payload).model == "Qwen/Qwen3.5-4B"
54
+
55
+
56
+ # ---------------------------------------------------------------------------
57
+ # Estimator sanity: calibrated against catalog anchors
58
+ # ---------------------------------------------------------------------------
59
+ def _headroom(params_b: float, algo: str, quant: str, gpu: str) -> str:
60
+ """The advisory fits/tight/too_big banding, applied straight to the sizing equations.
61
+
62
+ The bands below calibrate live sizing decisions directly against managed GPU capacities.
63
+ """
64
+ est = estimate_vram_gb(params_b, algo, quant)
65
+ gpu_gb = get_gpu_info(gpu).vram_gb
66
+ if est > gpu_gb * 1.15:
67
+ return "too_big"
68
+ return "tight" if est > gpu_gb * 0.85 else "fits"
69
+
70
+
71
+ @pytest.mark.parametrize(
72
+ ("params_b", "algo", "quant", "gpu", "expected"),
73
+ [
74
+ (4.0, "grpo", "bf16", "RTX 5090", "fits"), # Qwen3-4B colocate on 32 GB (measured)
75
+ (4.0, "sft", "bf16", "RTX 4090", "fits"),
76
+ (9.65, "sft", "bf16", "RTX 5090", "tight"), # Qwen3.5-9B SFT real logits peak
77
+ (36.0, "sft", "bf16", "RTX 5090", "too_big"), # 72 GB of weights
78
+ (36.0, "grpo", "bf16", "RTX 5090", "too_big"), # 2 bf16 copies + KV >> 32 GB
79
+ ],
80
+ )
81
+ def test_estimator_anchors(params_b, algo, quant, gpu, expected):
82
+ # params_b is supplied directly, so this calibrates the SIZING EQUATIONS against known anchors
83
+ # and never resolves the id through the catalog.
84
+ assert _headroom(params_b, algo, quant, gpu) == expected
85
+
86
+
87
+ def test_grpo_needs_more_than_sft():
88
+ assert estimate_vram_gb(4.0, "grpo") > estimate_vram_gb(4.0, "sft")
@@ -21,7 +21,7 @@ from types import SimpleNamespace
21
21
 
22
22
  import pytest
23
23
 
24
- from flash.engine.worker import opd_train, rl_train, score_batcher
24
+ from flash.engine.worker import backend_common, opd_train, rl_train, score_batcher
25
25
  from flash.engine.worker.opd_train import (
26
26
  _OPD_PARQUET_WRITE_BATCH_ROWS,
27
27
  _BridgePrompt,
@@ -6064,27 +6064,9 @@ def test_opd_pins_the_blackwell_attention_backends_like_grpo_does():
6064
6064
  ), on
6065
6065
 
6066
6066
 
6067
- def test_opd_disables_the_vllm_multimodal_processor_cache():
6068
- """Image OPD does not run without this, and the failure it produces names neither images nor
6069
- the cache.
6070
-
6071
- vLLM splits the mm processor cache across two processes: the frontend SENDER replaces an image
6072
- it has seen before with just its hash, and the engine-core RECEIVER is supposed to still hold
6073
- the item. OPD's rollout lifecycle clears the receiver on every sleep/pause without clearing the
6074
- sender, so the sender keeps sending hashes for items the receiver dropped and each request dies
6075
- on `assert mm_item is not None`. That kills requests, not the run, so what surfaces is empty
6076
- rollouts and then an IndexError on a zero-length reward tensor.
6077
-
6078
- Asserted on the parsed VALUE rather than substring presence, because the two ways this
6079
- regresses are both silent: a nonzero size re-enables the cache, and the pre-0.13 flag name is
6080
- rejected by vLLM's arg parser at startup, long after the GPU is paid for.
6081
- """
6082
- emitted = build_opd_overrides(_config())
6083
- overrides = dict(value.split("=", 1) for value in emitted)
6084
- assert overrides["+actor_rollout_ref.rollout.engine_kwargs.vllm.mm_processor_cache_gb"] == "0"
6085
- # `disable_mm_preprocessor_cache` was REMOVED in vllm 0.13.0. it reads like the right knob and
6086
- # still appears in older verl examples, so pin it out rather than trusting review to catch it.
6087
- assert not any("disable_mm_preprocessor_cache" in override for override in emitted)
6067
+ def test_opd_unconditionally_disables_the_vllm_multimodal_processor_cache():
6068
+ overrides = build_opd_overrides(_config())
6069
+ assert set(backend_common.rollout_mm_processor_cache_overrides()) <= set(overrides)
6088
6070
 
6089
6071
 
6090
6072
  def test_both_ray_rollouts_pin_blackwell_attention_from_the_same_resolver():