freesolo-flash-dev 1.2.61__tar.gz → 1.2.63__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 (584) hide show
  1. {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/PKG-INFO +1 -1
  2. {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/content/multimodal.py +135 -19
  3. freesolo_flash_dev-1.2.63/flash/engine/huggingface.py +61 -0
  4. {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/engine/profiling/dataset_profile.py +4 -7
  5. freesolo_flash_dev-1.2.63/flash/engine/profiling/image_tokens.py +294 -0
  6. freesolo_flash_dev-1.2.63/flash/engine/profiling/sft_image_rows.py +226 -0
  7. {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/engine/profiling/sft_workload.py +144 -156
  8. {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/engine/profiling/tokenizer.py +1 -4
  9. {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/engine/worker/entry/sft.py +41 -2
  10. {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/engine/worker/io/prefetch.py +3 -37
  11. {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/engine/worker/model/chatml_mask.py +73 -42
  12. {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/engine/worker/train/opd/prompts.py +2 -2
  13. {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/engine/worker/train/rl/verl_config.py +2 -2
  14. {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/server/routes/runs.py +7 -5
  15. {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/pyproject.toml +2 -2
  16. freesolo_flash_dev-1.2.63/tests/capture_image_sft_processor_oracle.py +23 -0
  17. freesolo_flash_dev-1.2.63/tests/fixtures/image_sft_processor_oracle.json +1 -0
  18. {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/tests/test_controlled_experiment_repairs.py +4 -1
  19. {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/tests/test_dataset_profile.py +255 -11
  20. {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/tests/test_flash_worker.py +7 -5
  21. freesolo_flash_dev-1.2.63/tests/test_image_sft_markers.py +337 -0
  22. freesolo_flash_dev-1.2.63/tests/test_image_sft_processor_parity.py +549 -0
  23. freesolo_flash_dev-1.2.63/tests/test_image_tokens.py +464 -0
  24. {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/tests/test_multimodal_training.py +1 -1
  25. {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/tests/test_sft_train.py +97 -6
  26. {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/uv.lock +1 -1
  27. {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/.dockerignore +0 -0
  28. {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/.env.example +0 -0
  29. {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/.github/CODEOWNERS +0 -0
  30. {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/.github/ISSUE_TEMPLATE/bug_report.yml +0 -0
  31. {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/.github/ISSUE_TEMPLATE/config.yml +0 -0
  32. {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/.github/ISSUE_TEMPLATE/feature_request.yml +0 -0
  33. {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/.github/PULL_REQUEST_TEMPLATE.md +0 -0
  34. {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/.github/dependabot.yml +0 -0
  35. {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/.github/workflows/auto-rebake.yml +0 -0
  36. {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/.github/workflows/bake-kernel-cache.yml +0 -0
  37. {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/.github/workflows/ci.yml +0 -0
  38. {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/.github/workflows/main-source-guard.yml +0 -0
  39. {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/.github/workflows/notify-tests-repo.yml +0 -0
  40. {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/.github/workflows/publish-dev.yml +0 -0
  41. {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/.github/workflows/publish-image.yml +0 -0
  42. {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/.github/workflows/publish.yml +0 -0
  43. {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/.github/workflows/version-parity.yml +0 -0
  44. {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/.github/workflows/worker-image.yml +0 -0
  45. {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/.gitignore +0 -0
  46. {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/CHANGELOG.md +0 -0
  47. {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/CODE_OF_CONDUCT.md +0 -0
  48. {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/CONTRIBUTING.md +0 -0
  49. {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/Dockerfile +0 -0
  50. {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/Dockerfile.worker +0 -0
  51. {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/LICENSE +0 -0
  52. {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/NOTICE +0 -0
  53. {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/README.md +0 -0
  54. {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/SECURITY.md +0 -0
  55. {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/SELF_HOSTING.md +0 -0
  56. {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/build/kernel_cache/.gitignore +0 -0
  57. {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/build/kernel_cache/.keep +0 -0
  58. {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/deploy/infisical/README.md +0 -0
  59. {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/deploy/infisical/entrypoint.sh +0 -0
  60. {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/docker/Dockerfile.kernelcache +0 -0
  61. {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/docker/Dockerfile.kernelcache.relayer +0 -0
  62. {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/docker/bake_kernel_cache.py +0 -0
  63. {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/docker/bake_pod_entry.py +0 -0
  64. {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/docker/extract_cudart_fix.py +0 -0
  65. {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/docker/kernel_fingerprint.py +0 -0
  66. {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/docker/make_rp_handler.py +0 -0
  67. {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/__init__.py +0 -0
  68. {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/_internal/__init__.py +0 -0
  69. {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/_internal/channel.py +0 -0
  70. {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/_internal/diagnostics.py +0 -0
  71. {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/_internal/fileio.py +0 -0
  72. {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/_internal/logging.py +0 -0
  73. {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/_internal/paths.py +0 -0
  74. {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/adapters/__init__.py +0 -0
  75. {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/adapters/artifacts.py +0 -0
  76. {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/adapters/fused_experts.py +0 -0
  77. {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/adapters/lora_rank.py +0 -0
  78. {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/cli/__init__.py +0 -0
  79. {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/cli/__main__.py +0 -0
  80. {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/cli/commands/__init__.py +0 -0
  81. {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/cli/commands/deploy.py +0 -0
  82. {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/cli/commands/env/__init__.py +0 -0
  83. {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/cli/commands/env/episode.py +0 -0
  84. {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/cli/commands/env/eval.py +0 -0
  85. {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/cli/commands/env/eval_args.py +0 -0
  86. {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/cli/commands/env/imports.py +0 -0
  87. {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/cli/commands/env/list.py +0 -0
  88. {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/cli/commands/env/push.py +0 -0
  89. {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/cli/commands/env/retained.py +0 -0
  90. {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/cli/commands/env/setup.py +0 -0
  91. {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/cli/commands/env/test.py +0 -0
  92. {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/cli/commands/env/test_evaluations.py +0 -0
  93. {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/cli/commands/env/test_params.py +0 -0
  94. {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/cli/commands/env/test_warnings.py +0 -0
  95. {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/cli/commands/prompt_budget.py +0 -0
  96. {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/cli/commands/traces.py +0 -0
  97. {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/cli/commands/train_cost.py +0 -0
  98. {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/cli/scaffold/TRAINING.md +0 -0
  99. {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/cli/scaffold/__init__.py +0 -0
  100. {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/cli/ui/__init__.py +0 -0
  101. {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/cli/ui/cost.py +0 -0
  102. {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/cli/ui/env_panels.py +0 -0
  103. {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/cli/ui/heartbeat.py +0 -0
  104. {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/cli/ui/render.py +0 -0
  105. {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/cli/ui/tables.py +0 -0
  106. {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/cli/ui/tty.py +0 -0
  107. {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/client/__init__.py +0 -0
  108. {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/client/config.py +0 -0
  109. {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/client/freesolo_api.py +0 -0
  110. {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/client/http.py +0 -0
  111. {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/client/runtime_secrets.py +0 -0
  112. {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/client/shapes.py +0 -0
  113. {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/client/specs.py +0 -0
  114. {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/client/streaming.py +0 -0
  115. {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/content/__init__.py +0 -0
  116. {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/content/structured_outputs.py +0 -0
  117. {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/content/thinking.py +0 -0
  118. {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/core/__init__.py +0 -0
  119. {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/core/catalog.py +0 -0
  120. {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/core/spec.py +0 -0
  121. {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/core/spec_persistence.py +0 -0
  122. {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/cost/__init__.py +0 -0
  123. {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/cost/analytical.py +0 -0
  124. {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/cost/facts.py +0 -0
  125. {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/cost/spec.py +0 -0
  126. {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/cost/types.py +0 -0
  127. {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/engine/__init__.py +0 -0
  128. {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/engine/plan/__init__.py +0 -0
  129. {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/engine/plan/kv_sizing.py +0 -0
  130. {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/engine/plan/model_config_probe.py +0 -0
  131. {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/engine/plan/prompt_budget.py +0 -0
  132. {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/engine/plan/recipe.py +0 -0
  133. {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/engine/plan/steps.py +0 -0
  134. {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/engine/plan/vram.py +0 -0
  135. {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/engine/profiling/__init__.py +0 -0
  136. {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/engine/profiling/reasoning_render.py +0 -0
  137. {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/engine/profiling/workload_profile.py +0 -0
  138. {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/engine/result/__init__.py +0 -0
  139. {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/engine/result/accounting.py +0 -0
  140. {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/engine/result/rollout_samples.py +0 -0
  141. {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/engine/worker/__init__.py +0 -0
  142. {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/engine/worker/__main__.py +0 -0
  143. {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/engine/worker/backend_common.py +0 -0
  144. {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/engine/worker/entry/__init__.py +0 -0
  145. {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/engine/worker/entry/opd.py +0 -0
  146. {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/engine/worker/entry/rl.py +0 -0
  147. {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/engine/worker/io/__init__.py +0 -0
  148. {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/engine/worker/io/heartbeat.py +0 -0
  149. {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/engine/worker/io/hf.py +0 -0
  150. {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/engine/worker/io/wandb_log.py +0 -0
  151. {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/engine/worker/model/__init__.py +0 -0
  152. {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/engine/worker/model/adapter.py +0 -0
  153. {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/engine/worker/model/decoding.py +0 -0
  154. {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/engine/worker/model/lora.py +0 -0
  155. {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/engine/worker/model/packing.py +0 -0
  156. {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/engine/worker/opd_train.py +0 -0
  157. {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/engine/worker/opd_train_runner.py +0 -0
  158. {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/engine/worker/perf/__init__.py +0 -0
  159. {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/engine/worker/perf/diagnostics.py +0 -0
  160. {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/engine/worker/perf/lifecycle.py +0 -0
  161. {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/engine/worker/perf/liger.py +0 -0
  162. {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/engine/worker/perf/memory.py +0 -0
  163. {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/engine/worker/rl_train.py +0 -0
  164. {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/engine/worker/rl_train_runner.py +0 -0
  165. {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/engine/worker/runtime/__init__.py +0 -0
  166. {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/engine/worker/runtime/kernel_warmup.py +0 -0
  167. {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/engine/worker/runtime/pkg_proxy.py +0 -0
  168. {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/engine/worker/runtime/rng.py +0 -0
  169. {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/engine/worker/score_batcher.py +0 -0
  170. {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/engine/worker/sft_train.py +0 -0
  171. {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/engine/worker/sft_train_runner.py +0 -0
  172. {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/engine/worker/teacher/__init__.py +0 -0
  173. {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/engine/worker/teacher/client.py +0 -0
  174. {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/engine/worker/teacher/encoding.py +0 -0
  175. {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/engine/worker/teacher/tokenizer_align.py +0 -0
  176. {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/engine/worker/train/__init__.py +0 -0
  177. {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/engine/worker/train/core/__init__.py +0 -0
  178. {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/engine/worker/train/core/checkpoint_lifecycle.py +0 -0
  179. {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/engine/worker/train/core/child/__init__.py +0 -0
  180. {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/engine/worker/train/core/child/glue.py +0 -0
  181. {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/engine/worker/train/core/child/runtime.py +0 -0
  182. {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/engine/worker/train/core/step_timing.py +0 -0
  183. {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/engine/worker/train/finalize.py +0 -0
  184. {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/engine/worker/train/opd/__init__.py +0 -0
  185. {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/engine/worker/train/opd/batching.py +0 -0
  186. {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/engine/worker/train/opd/bridge.py +0 -0
  187. {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/engine/worker/train/opd/child/__init__.py +0 -0
  188. {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/engine/worker/train/opd/child/bridge.py +0 -0
  189. {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/engine/worker/train/opd/child/entry.py +0 -0
  190. {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/engine/worker/train/opd/child/multiturn.py +0 -0
  191. {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/engine/worker/train/opd/child/plugin.py +0 -0
  192. {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/engine/worker/train/opd/child/replay_guard.py +0 -0
  193. {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/engine/worker/train/opd/child/runtime.py +0 -0
  194. {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/engine/worker/train/opd/child/structured.py +0 -0
  195. {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/engine/worker/train/opd/failures.py +0 -0
  196. {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/engine/worker/train/opd/gkd.py +0 -0
  197. {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/engine/worker/train/opd/multiturn_validation.py +0 -0
  198. {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/engine/worker/train/opd/overrides.py +0 -0
  199. {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/engine/worker/train/opd/reporting.py +0 -0
  200. {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/engine/worker/train/opd/scoring.py +0 -0
  201. {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/engine/worker/train/opd/state.py +0 -0
  202. {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/engine/worker/train/opd/validation.py +0 -0
  203. {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/engine/worker/train/rl/__init__.py +0 -0
  204. {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/engine/worker/train/rl/checkpoints.py +0 -0
  205. {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/engine/worker/train/rl/child/__init__.py +0 -0
  206. {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/engine/worker/train/rl/child/entry.py +0 -0
  207. {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/engine/worker/train/rl/child/multiturn.py +0 -0
  208. {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/engine/worker/train/rl/child/patches.py +0 -0
  209. {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/engine/worker/train/rl/child/plugin.py +0 -0
  210. {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/engine/worker/train/rl/config.py +0 -0
  211. {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/engine/worker/train/rl/inputs.py +0 -0
  212. {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/engine/worker/train/rl/multi_turn.py +0 -0
  213. {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/engine/worker/train/rl/reward_module.py +0 -0
  214. {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/engine/worker/train/rl/scoring.py +0 -0
  215. {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/engine/worker/train/rl/single_turn.py +0 -0
  216. {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/engine/worker/train/sft/__init__.py +0 -0
  217. {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/engine/worker/train/sft/checkpoints.py +0 -0
  218. {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/engine/worker/train/sft/child/entry.py +0 -0
  219. {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/engine/worker/train/sft/child/plugin.py +0 -0
  220. {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/engine/worker/train/sft/config.py +0 -0
  221. {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/engine/worker/verl/__init__.py +0 -0
  222. {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/engine/worker/verl/capabilities.py +0 -0
  223. {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/engine/worker/verl/checkpoints.py +0 -0
  224. {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/engine/worker/verl/child_io.py +0 -0
  225. {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/engine/worker/verl/diagnostics.py +0 -0
  226. {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/engine/worker/verl/parallelism.py +0 -0
  227. {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/engine/worker/verl/parent_work.py +0 -0
  228. {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/engine/worker_entrypoint.py +0 -0
  229. {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/envs/__init__.py +0 -0
  230. {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/envs/adapter.py +0 -0
  231. {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/envs/base.py +0 -0
  232. {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/envs/cache_security.py +0 -0
  233. {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/envs/dataset_selection.py +0 -0
  234. {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/envs/evaluations.py +0 -0
  235. {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/envs/identity.py +0 -0
  236. {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/envs/loader.py +0 -0
  237. {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/envs/namespace_listing.py +0 -0
  238. {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/envs/package/__init__.py +0 -0
  239. {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/envs/package/limits.py +0 -0
  240. {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/envs/package/unpack.py +0 -0
  241. {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/envs/pull.py +0 -0
  242. {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/providers/__init__.py +0 -0
  243. {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/providers/_lifecycle/__init__.py +0 -0
  244. {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/providers/_lifecycle/auth.py +0 -0
  245. {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/providers/_lifecycle/bootstrap.py +0 -0
  246. {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/providers/_lifecycle/bootstrap_console.py +0 -0
  247. {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/providers/_lifecycle/bootstrap_pip.py +0 -0
  248. {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/providers/_lifecycle/bootstrap_secrets.py +0 -0
  249. {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/providers/_lifecycle/deadline.py +0 -0
  250. {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/providers/_lifecycle/host/__init__.py +0 -0
  251. {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/providers/_lifecycle/host/deadline_sleep.py +0 -0
  252. {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/providers/_lifecycle/host/failmark.py +0 -0
  253. {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/providers/_lifecycle/host/hostlog.py +0 -0
  254. {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/providers/_lifecycle/http.py +0 -0
  255. {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/providers/_lifecycle/instance.py +0 -0
  256. {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/providers/_lifecycle/poll.py +0 -0
  257. {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/providers/_lifecycle/poll_instance.py +0 -0
  258. {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/providers/_lifecycle/provider.py +0 -0
  259. {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/providers/_lifecycle/terminal_artifacts.py +0 -0
  260. {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/providers/_lifecycle/worker.py +0 -0
  261. {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/providers/allocator.py +0 -0
  262. {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/providers/artifacts/__init__.py +0 -0
  263. {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/providers/artifacts/hf.py +0 -0
  264. {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/providers/artifacts/preload_runpod.py +0 -0
  265. {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/providers/artifacts/weight_cache.py +0 -0
  266. {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/providers/base.py +0 -0
  267. {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/providers/fit_errors.py +0 -0
  268. {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/providers/lambda_/__init__.py +0 -0
  269. {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/providers/lambda_/api.py +0 -0
  270. {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/providers/lambda_/auth.py +0 -0
  271. {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/providers/lambda_/gpus.py +0 -0
  272. {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/providers/lambda_/jobs/__init__.py +0 -0
  273. {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/providers/lambda_/jobs/builders.py +0 -0
  274. {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/providers/lambda_/jobs/reap.py +0 -0
  275. {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/providers/lambda_/preflight.py +0 -0
  276. {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/providers/lambda_/pricing.py +0 -0
  277. {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/providers/preflight.py +0 -0
  278. {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/providers/realized.py +0 -0
  279. {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/providers/runpod/__init__.py +0 -0
  280. {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/providers/runpod/api.py +0 -0
  281. {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/providers/runpod/auth.py +0 -0
  282. {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/providers/runpod/cost.py +0 -0
  283. {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/providers/runpod/gpus.py +0 -0
  284. {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/providers/runpod/job_execution.py +0 -0
  285. {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/providers/runpod/jobs.py +0 -0
  286. {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/providers/runpod/preflight.py +0 -0
  287. {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/providers/runpod/pricing.py +0 -0
  288. {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/providers/runpod/resources.py +0 -0
  289. {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/providers/runpod/serverless/__init__.py +0 -0
  290. {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/providers/runpod/serverless/endpoints.py +0 -0
  291. {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/providers/sharding.py +0 -0
  292. {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/providers/vast/__init__.py +0 -0
  293. {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/providers/vast/api.py +0 -0
  294. {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/providers/vast/auth.py +0 -0
  295. {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/providers/vast/jobs/__init__.py +0 -0
  296. {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/providers/vast/jobs/builders.py +0 -0
  297. {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/providers/vast/preflight.py +0 -0
  298. {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/providers/vast/pricing.py +0 -0
  299. {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/py.typed +0 -0
  300. {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/runner/__init__.py +0 -0
  301. {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/runner/artifacts.py +0 -0
  302. {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/runner/attempts.py +0 -0
  303. {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/runner/costs.py +0 -0
  304. {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/runner/deadlines.py +0 -0
  305. {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/runner/preparation.py +0 -0
  306. {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/runner/reconciliation.py +0 -0
  307. {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/runner/results/__init__.py +0 -0
  308. {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/runner/results/checkpoints.py +0 -0
  309. {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/runner/results/verified_revisions.py +0 -0
  310. {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/runner/status.py +0 -0
  311. {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/runner/submit.py +0 -0
  312. {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/runner/supervise/__init__.py +0 -0
  313. {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/runner/supervise/attach.py +0 -0
  314. {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/runner/supervise/deploy.py +0 -0
  315. {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/runner/supervise/lifecycle.py +0 -0
  316. {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/runner/supervise/recovery.py +0 -0
  317. {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/runner/supervise/retry_decision.py +0 -0
  318. {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/runner/supervise/seed_submission.py +0 -0
  319. {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/runner/supervise/transitions.py +0 -0
  320. {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/runner/weight_cache.py +0 -0
  321. {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/runtime_capsule/__init__.py +0 -0
  322. {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/runtime_capsule/build.py +0 -0
  323. {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/runtime_capsule/manifest.py +0 -0
  324. {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/runtime_capsule/profiles.py +0 -0
  325. {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/schema/__init__.py +0 -0
  326. {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/schema/fields.py +0 -0
  327. {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/serve/__init__.py +0 -0
  328. {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/serve/adapter_check.py +0 -0
  329. {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/serve/deploy.py +0 -0
  330. {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/serve/errors.py +0 -0
  331. {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/serve/export.py +0 -0
  332. {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/serve/preflight.py +0 -0
  333. {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/serve/responses.py +0 -0
  334. {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/serve/streaming.py +0 -0
  335. {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/serve/thinking.py +0 -0
  336. {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/serve/urls.py +0 -0
  337. {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/server/__init__.py +0 -0
  338. {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/server/__main__.py +0 -0
  339. {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/server/app.py +0 -0
  340. {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/server/billing/__init__.py +0 -0
  341. {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/server/billing/charges.py +0 -0
  342. {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/server/billing/retry.py +0 -0
  343. {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/server/domain/__init__.py +0 -0
  344. {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/server/domain/checkpoints.py +0 -0
  345. {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/server/domain/environment_registry.py +0 -0
  346. {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/server/domain/envs.py +0 -0
  347. {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/server/domain/projects.py +0 -0
  348. {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/server/domain/reconcile.py +0 -0
  349. {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/server/domain/repo_cleanup.py +0 -0
  350. {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/server/domain/run_registry.py +0 -0
  351. {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/server/domain/teacher_broker.py +0 -0
  352. {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/server/domain/teacher_errors.py +0 -0
  353. {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/server/domain/teacher_requests.py +0 -0
  354. {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/server/platform/__init__.py +0 -0
  355. {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/server/platform/auth.py +0 -0
  356. {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/server/platform/db.py +0 -0
  357. {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/server/platform/deps.py +0 -0
  358. {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/server/platform/internal_client.py +0 -0
  359. {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/server/platform/locks.py +0 -0
  360. {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/server/platform/runtime.py +0 -0
  361. {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/server/routes/__init__.py +0 -0
  362. {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/server/routes/envs.py +0 -0
  363. {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/server/routes/meta.py +0 -0
  364. {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/server/routes/serving.py +0 -0
  365. {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/server/routes/serving_completion.py +0 -0
  366. {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/server/routes/serving_revisions.py +0 -0
  367. {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/server/routes/serving_smoke.py +0 -0
  368. {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/server/routes/teacher.py +0 -0
  369. {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/teacher/__init__.py +0 -0
  370. {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/teacher/limits.py +0 -0
  371. {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/flash/teacher/retry_contract.py +0 -0
  372. {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/scripts/build_dev_dist.py +0 -0
  373. {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/scripts/check_file_size.py +0 -0
  374. {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/scripts/check_function_size.py +0 -0
  375. {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/scripts/check_verl_pin_exists.py +0 -0
  376. {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/scripts/scrub_history.sh +0 -0
  377. {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/tests/__init__.py +0 -0
  378. {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/tests/_helpers/__init__.py +0 -0
  379. {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/tests/_helpers/profile.py +0 -0
  380. {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/tests/_helpers/runner.py +0 -0
  381. {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/tests/_helpers/specs.py +0 -0
  382. {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/tests/_helpers/teacher.py +0 -0
  383. {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/tests/_helpers/vast.py +0 -0
  384. {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/tests/conftest.py +0 -0
  385. {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/tests/fixtures/math_eval.jsonl +0 -0
  386. {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/tests/fixtures/math_train.jsonl +0 -0
  387. {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/tests/live/__init__.py +0 -0
  388. {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/tests/live/conftest.py +0 -0
  389. {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/tests/live/test_lambda_live.py +0 -0
  390. {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/tests/live/test_runpod_live.py +0 -0
  391. {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/tests/live/test_sft_thinking_render_live.py +0 -0
  392. {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/tests/live/test_vast_live.py +0 -0
  393. {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/tests/test_accounting_coverage.py +0 -0
  394. {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/tests/test_adapter_shard_completeness.py +0 -0
  395. {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/tests/test_agent_flash_cli_contract.py +0 -0
  396. {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/tests/test_algorithms.py +0 -0
  397. {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/tests/test_allocator.py +0 -0
  398. {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/tests/test_backend_common.py +0 -0
  399. {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/tests/test_backend_jobspec_contract.py +0 -0
  400. {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/tests/test_bake_kernel_cache.py +0 -0
  401. {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/tests/test_base_model_provenance.py +0 -0
  402. {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/tests/test_billing_retry.py +0 -0
  403. {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/tests/test_build_context_contract.py +0 -0
  404. {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/tests/test_cancel_remote.py +0 -0
  405. {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/tests/test_catalog_consistency.py +0 -0
  406. {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/tests/test_catalog_only_models.py +0 -0
  407. {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/tests/test_charge_pricing.py +0 -0
  408. {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/tests/test_checkpoint_lifecycle.py +0 -0
  409. {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/tests/test_checkpoints.py +0 -0
  410. {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/tests/test_cli_commands.py +0 -0
  411. {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/tests/test_cli_commands_coverage.py +0 -0
  412. {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/tests/test_cli_credential_shadowing.py +0 -0
  413. {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/tests/test_cli_errors.py +0 -0
  414. {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/tests/test_cli_estimate.py +0 -0
  415. {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/tests/test_cli_gpus_flag.py +0 -0
  416. {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/tests/test_cli_help.py +0 -0
  417. {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/tests/test_cli_main_coverage.py +0 -0
  418. {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/tests/test_cli_managed.py +0 -0
  419. {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/tests/test_cli_render_coverage.py +0 -0
  420. {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/tests/test_cli_render_theme.py +0 -0
  421. {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/tests/test_cli_traces.py +0 -0
  422. {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/tests/test_cli_wandb_warning.py +0 -0
  423. {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/tests/test_client.py +0 -0
  424. {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/tests/test_client_import_purity.py +0 -0
  425. {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/tests/test_client_server_integration.py +0 -0
  426. {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/tests/test_client_stream_reads.py +0 -0
  427. {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/tests/test_config_env_vars.py +0 -0
  428. {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/tests/test_config_overrides.py +0 -0
  429. {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/tests/test_console_upload.py +0 -0
  430. {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/tests/test_cost_analytical.py +0 -0
  431. {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/tests/test_cost_equation.py +0 -0
  432. {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/tests/test_cost_estimate.py +0 -0
  433. {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/tests/test_cost_hardware.py +0 -0
  434. {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/tests/test_cost_models.py +0 -0
  435. {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/tests/test_deploy_alias_move_warning.py +0 -0
  436. {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/tests/test_deploy_latency.py +0 -0
  437. {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/tests/test_dev_channel.py +0 -0
  438. {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/tests/test_disk_gb.py +0 -0
  439. {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/tests/test_endpoint_name.py +0 -0
  440. {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/tests/test_env_cache_evict.py +0 -0
  441. {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/tests/test_env_delete.py +0 -0
  442. {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/tests/test_env_download.py +0 -0
  443. {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/tests/test_env_download_api.py +0 -0
  444. {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/tests/test_env_evaluations.py +0 -0
  445. {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/tests/test_env_list_api.py +0 -0
  446. {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/tests/test_env_list_cli.py +0 -0
  447. {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/tests/test_env_list_hub.py +0 -0
  448. {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/tests/test_env_no_install.py +0 -0
  449. {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/tests/test_env_publish.py +0 -0
  450. {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/tests/test_env_pull.py +0 -0
  451. {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/tests/test_env_pull_coverage.py +0 -0
  452. {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/tests/test_env_pull_loader_coverage.py +0 -0
  453. {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/tests/test_env_pull_managed_control_plane.py +0 -0
  454. {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/tests/test_env_push.py +0 -0
  455. {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/tests/test_env_rate_limit_resolve.py +0 -0
  456. {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/tests/test_env_ref_pinning.py +0 -0
  457. {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/tests/test_env_test.py +0 -0
  458. {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/tests/test_envs_coverage.py +0 -0
  459. {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/tests/test_export.py +0 -0
  460. {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/tests/test_flash_mvp.py +0 -0
  461. {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/tests/test_flashinfer_cache_dirs.py +0 -0
  462. {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/tests/test_freesolo_api_transport.py +0 -0
  463. {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/tests/test_fused_expert_warmstart.py +0 -0
  464. {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/tests/test_github_urlopen_retry.py +0 -0
  465. {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/tests/test_gpu_type_single_field.py +0 -0
  466. {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/tests/test_gpus.py +0 -0
  467. {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/tests/test_grpo_params.py +0 -0
  468. {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/tests/test_grpo_resident_sizing.py +0 -0
  469. {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/tests/test_grpo_reward_batching.py +0 -0
  470. {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/tests/test_health_liveness.py +0 -0
  471. {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/tests/test_hf_retry.py +0 -0
  472. {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/tests/test_idle_endpoint_reaper.py +0 -0
  473. {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/tests/test_infisical_secrets.py +0 -0
  474. {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/tests/test_instance_bootstrap_coverage.py +0 -0
  475. {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/tests/test_internal_client.py +0 -0
  476. {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/tests/test_jobs.py +0 -0
  477. {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/tests/test_kernel_cache.py +0 -0
  478. {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/tests/test_kernel_fingerprint.py +0 -0
  479. {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/tests/test_kv_util.py +0 -0
  480. {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/tests/test_lambda_api_coverage.py +0 -0
  481. {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/tests/test_lambda_runner.py +0 -0
  482. {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/tests/test_logging.py +0 -0
  483. {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/tests/test_login_perms.py +0 -0
  484. {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/tests/test_lora_rank_coverage.py +0 -0
  485. {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/tests/test_lora_rank_preflight.py +0 -0
  486. {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/tests/test_managed_config_fields.py +0 -0
  487. {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/tests/test_managed_hf_repo.py +0 -0
  488. {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/tests/test_metrics_schema_agent_contract.py +0 -0
  489. {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/tests/test_mig_guard.py +0 -0
  490. {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/tests/test_multi_gpu_gate.py +0 -0
  491. {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/tests/test_named_reward_metrics.py +0 -0
  492. {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/tests/test_oom_escalate_gpu.py +0 -0
  493. {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/tests/test_opd.py +0 -0
  494. {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/tests/test_opd_limits.py +0 -0
  495. {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/tests/test_opd_multiturn_eos_boundary.py +0 -0
  496. {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/tests/test_opd_multiturn_failure_exit.py +0 -0
  497. {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/tests/test_opd_replay_guard.py +0 -0
  498. {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/tests/test_opd_resume_safety.py +0 -0
  499. {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/tests/test_opd_train.py +0 -0
  500. {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/tests/test_orchestrator_flash.py +0 -0
  501. {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/tests/test_packing.py +0 -0
  502. {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/tests/test_packing_coverage.py +0 -0
  503. {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/tests/test_parasail_teacher.py +0 -0
  504. {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/tests/test_persisted_spec_envelope.py +0 -0
  505. {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/tests/test_poll_helpers.py +0 -0
  506. {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/tests/test_preflight.py +0 -0
  507. {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/tests/test_projects.py +0 -0
  508. {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/tests/test_prompt_budget.py +0 -0
  509. {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/tests/test_provider_preflight_coverage.py +0 -0
  510. {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/tests/test_provider_routing.py +0 -0
  511. {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/tests/test_provider_teardown_robustness.py +0 -0
  512. {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/tests/test_providers_symmetry.py +0 -0
  513. {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/tests/test_realized_cost.py +0 -0
  514. {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/tests/test_repo_cleanup.py +0 -0
  515. {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/tests/test_resolve_params_b.py +0 -0
  516. {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/tests/test_resume_on_retry.py +0 -0
  517. {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/tests/test_rl_train.py +0 -0
  518. {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/tests/test_rollout_samples.py +0 -0
  519. {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/tests/test_runmgmt.py +0 -0
  520. {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/tests/test_runpod_api_delete.py +0 -0
  521. {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/tests/test_runpod_key_fingerprint.py +0 -0
  522. {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/tests/test_runpod_key_waterfall.py +0 -0
  523. {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/tests/test_runtime_capsule.py +0 -0
  524. {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/tests/test_serve.py +0 -0
  525. {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/tests/test_serve_reasoning_content.py +0 -0
  526. {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/tests/test_server_api.py +0 -0
  527. {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/tests/test_server_app_coverage.py +0 -0
  528. {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/tests/test_server_auth_singleflight.py +0 -0
  529. {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/tests/test_server_billing.py +0 -0
  530. {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/tests/test_server_checkpoints_coverage.py +0 -0
  531. {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/tests/test_server_db.py +0 -0
  532. {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/tests/test_server_envs_coverage.py +0 -0
  533. {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/tests/test_server_locks_coverage.py +0 -0
  534. {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/tests/test_server_standalone.py +0 -0
  535. {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/tests/test_serving_context_preflight.py +0 -0
  536. {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/tests/test_serving_contract.py +0 -0
  537. {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/tests/test_serving_schema_coverage.py +0 -0
  538. {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/tests/test_sft_chunked_nll.py +0 -0
  539. {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/tests/test_sft_example_selection.py +0 -0
  540. {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/tests/test_sft_gc_off.py +0 -0
  541. {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/tests/test_sft_max_context.py +0 -0
  542. {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/tests/test_sft_startup_block.py +0 -0
  543. {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/tests/test_sft_workload.py +0 -0
  544. {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/tests/test_spec_and_validation.py +0 -0
  545. {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/tests/test_spec_contract_bytes.py +0 -0
  546. {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/tests/test_step_floor.py +0 -0
  547. {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/tests/test_step_metrics.py +0 -0
  548. {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/tests/test_step_timing.py +0 -0
  549. {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/tests/test_structured_outputs.py +0 -0
  550. {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/tests/test_teacher_broker.py +0 -0
  551. {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/tests/test_teacher_encoding_contract.py +0 -0
  552. {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/tests/test_terminal_artifacts.py +0 -0
  553. {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/tests/test_thinking_config.py +0 -0
  554. {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/tests/test_train_context_preflight.py +0 -0
  555. {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/tests/test_training_controls.py +0 -0
  556. {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/tests/test_type_comment_prose.py +0 -0
  557. {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/tests/test_vast_api.py +0 -0
  558. {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/tests/test_vast_api_coverage.py +0 -0
  559. {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/tests/test_vast_offers.py +0 -0
  560. {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/tests/test_vast_provider_coverage.py +0 -0
  561. {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/tests/test_vast_runner.py +0 -0
  562. {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/tests/test_verified_revisions.py +0 -0
  563. {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/tests/test_verifiers.py +0 -0
  564. {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/tests/test_verl_checkpoint_export.py +0 -0
  565. {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/tests/test_verl_child_plugins.py +0 -0
  566. {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/tests/test_verl_silence_watchdog.py +0 -0
  567. {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/tests/test_version.py +0 -0
  568. {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/tests/test_vl_warmstart_adapter_keys.py +0 -0
  569. {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/tests/test_vram_architecture.py +0 -0
  570. {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/tests/test_wandb_link.py +0 -0
  571. {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/tests/test_wandb_naming.py +0 -0
  572. {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/tests/test_warmstart_adapter_download.py +0 -0
  573. {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/tests/test_warmstart_cross_repo.py +0 -0
  574. {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/tests/test_warmstart_error_attribution.py +0 -0
  575. {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/tests/test_weight_cache.py +0 -0
  576. {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/tests/test_worker_dryrun.py +0 -0
  577. {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/tests/test_worker_hardexit.py +0 -0
  578. {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/tests/test_worker_image.py +0 -0
  579. {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/tests/test_worker_init_heartbeat.py +0 -0
  580. {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/tests/test_worker_stack.py +0 -0
  581. {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/tests/test_worker_thinking.py +0 -0
  582. {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/tests/test_workflow_contracts.py +0 -0
  583. {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/tests/test_workload_profile.py +0 -0
  584. {freesolo_flash_dev-1.2.61 → freesolo_flash_dev-1.2.63}/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.61
3
+ Version: 1.2.63
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
@@ -9,6 +9,7 @@ import json
9
9
  import urllib.parse
10
10
  from dataclasses import dataclass
11
11
  from pathlib import Path
12
+ from typing import Any
12
13
 
13
14
  MAX_IMAGES_PER_EXAMPLE = 8
14
15
  MAX_IMAGE_SOURCE_BYTES = 20 * 1024 * 1024
@@ -140,20 +141,32 @@ def _validate_dimensions(width: int, height: int) -> int:
140
141
  return pixels * 3
141
142
 
142
143
 
143
- def _inspect_image_bytes(data: bytes) -> int:
144
+ def inspect_image_bytes(data: bytes) -> tuple[int, int, int]:
145
+ """Validate one image's header and return its (decoded_rgb_bytes, width, height).
146
+
147
+ Reads the header only: the pixels are not decoded here.
148
+ """
144
149
  try:
145
150
  from PIL import Image
146
151
  except ImportError as exc:
147
152
  raise RuntimeError("Pillow is required for multimodal image training") from exc
148
153
  try:
149
154
  with Image.open(io.BytesIO(data)) as image:
150
- return _validate_dimensions(image.width, image.height)
155
+ return (
156
+ _validate_dimensions(image.width, image.height),
157
+ image.width,
158
+ image.height,
159
+ )
151
160
  except ValueError:
152
161
  raise
153
162
  except Exception as exc:
154
163
  raise ValueError("image source is not a valid image") from exc
155
164
 
156
165
 
166
+ def _inspect_image_bytes(data: bytes) -> int:
167
+ return inspect_image_bytes(data)[0]
168
+
169
+
157
170
  def _pil_descriptor(image: object) -> str:
158
171
  width = int(getattr(image, "width", 0) or 0)
159
172
  height = int(getattr(image, "height", 0) or 0)
@@ -165,14 +178,26 @@ def _pil_descriptor(image: object) -> str:
165
178
  return _descriptor("bytes", base64.b64encode(data).decode("ascii"))
166
179
 
167
180
 
168
- def normalize_image_source(source: object, package_root: str | Path | None) -> str:
169
- """Convert one supported image source to an Arrow-safe descriptor."""
181
+ def normalize_image_source(
182
+ source: object,
183
+ package_root: str | Path | None,
184
+ *,
185
+ defer_validation: bool = False,
186
+ ) -> str:
187
+ """Convert one supported image source to an Arrow-safe descriptor.
188
+
189
+ ``defer_validation`` skips the per-source pixel inspection for EVERY source kind, for a caller
190
+ that validates the resulting descriptors itself. Profiling does exactly that, through one cached
191
+ pass that bounds total decode work; inspecting here as well would decode each image twice and
192
+ charge only some kinds to that budget. Every other caller validates eagerly.
193
+ """
170
194
  root = Path(package_root) if package_root is not None else None
171
195
  if isinstance(source, bytearray):
172
196
  source = bytes(source)
173
197
  if isinstance(source, bytes):
174
198
  _check_source_size(len(source))
175
- _inspect_image_bytes(source)
199
+ if not defer_validation:
200
+ _inspect_image_bytes(source)
176
201
  return _descriptor("bytes", base64.b64encode(source).decode("ascii"))
177
202
  if _is_pil_image(source):
178
203
  return _pil_descriptor(source)
@@ -183,7 +208,8 @@ def normalize_image_source(source: object, package_root: str | Path | None) -> s
183
208
  scheme = parsed.scheme.lower()
184
209
  if scheme == "data":
185
210
  data = _data_uri_bytes(value)
186
- _inspect_image_bytes(data)
211
+ if not defer_validation:
212
+ _inspect_image_bytes(data)
187
213
  return _descriptor("data_uri", value)
188
214
  if scheme in {"http", "https"}:
189
215
  # flash never fetches a user-supplied URL server-side. download the image ahead of time
@@ -198,8 +224,10 @@ def normalize_image_source(source: object, package_root: str | Path | None) -> s
198
224
  if scheme:
199
225
  raise ValueError(f"unsupported image URL scheme: {scheme}")
200
226
  path = _package_image_path(value, root)
201
- _inspect_image_bytes(path.read_bytes())
202
- return _descriptor("path", path.relative_to(root.resolve()).as_posix())
227
+ descriptor = _descriptor("path", path.relative_to(root.resolve()).as_posix())
228
+ if not defer_validation:
229
+ _inspect_image_bytes(path.read_bytes())
230
+ return descriptor
203
231
 
204
232
 
205
233
  def _image_source_from_block(block: dict) -> object | None:
@@ -284,7 +312,11 @@ def text_only_prompt_messages(messages: list[dict]) -> list[dict]:
284
312
  return stripped
285
313
 
286
314
 
287
- def _reject_literal_image_placeholder(text: str, message_index: int) -> None:
315
+ def _reject_literal_image_placeholder(
316
+ text: str,
317
+ message_index: int,
318
+ markers: tuple[str, ...] = (IMAGE_TEACHER_PLACEHOLDER, IMAGE_PAD_TOKEN),
319
+ ) -> None:
288
320
  """Reject prompt text that already contains a reserved image marker.
289
321
 
290
322
  two distinct markers, one reason. the rendered prompt marks image positions with
@@ -298,8 +330,12 @@ def _reject_literal_image_placeholder(text: str, message_index: int) -> None:
298
330
  contributes a run the renderer never produced -- and a run from text can make up for an image
299
331
  the provider silently dropped, which is exactly the failure the guard exists to catch. keeping
300
332
  it out of the source text is what makes "one run per image" mean what it says.
333
+
334
+ ``markers`` narrows the set for callers where only one of the two is live. local sft training
335
+ never renders the teacher placeholder, so a literal ``<|media_pad|>`` there is ordinary text
336
+ for a qwen tokenizer and rejecting it would be a false refusal.
301
337
  """
302
- for marker in (IMAGE_TEACHER_PLACEHOLDER, IMAGE_PAD_TOKEN):
338
+ for marker in markers:
303
339
  if marker in text:
304
340
  raise ValueError(
305
341
  f"message {message_index} text contains the reserved image marker "
@@ -364,8 +400,14 @@ def normalize_prompt_images(
364
400
  record: dict,
365
401
  messages: list[dict],
366
402
  package_root: str | Path | None,
403
+ *,
404
+ defer_validation: bool = False,
367
405
  ) -> NormalizedImages:
368
- """Normalize prompt image blocks and top-level fields without mutating the record."""
406
+ """Normalize prompt image blocks and top-level fields without mutating the record.
407
+
408
+ ``defer_validation`` is forwarded to :func:`normalize_image_source`; see it for when a caller
409
+ may skip the per-source pixel inspection.
410
+ """
369
411
  if not isinstance(messages, list) or not all(isinstance(message, dict) for message in messages):
370
412
  raise ValueError("prompt messages must be a list of message objects")
371
413
  pending = list(_top_level_sources(record))
@@ -381,14 +423,18 @@ def normalize_prompt_images(
381
423
  f"example contains {image_count} images, exceeding the "
382
424
  f"{MAX_IMAGES_PER_EXAMPLE}-image limit"
383
425
  )
384
- descriptor = normalize_image_source(source, package_root)
426
+ descriptor = normalize_image_source(
427
+ source,
428
+ package_root,
429
+ defer_validation=defer_validation,
430
+ )
385
431
  descriptor_bytes += _descriptor_size(descriptor)
386
432
  if descriptor_bytes > MAX_TOTAL_IMAGE_DESCRIPTOR_BYTES:
387
433
  raise ValueError(
388
434
  f"example encoded image descriptors total {descriptor_bytes} bytes, exceeding the "
389
435
  f"{MAX_TOTAL_IMAGE_DESCRIPTOR_BYTES}-byte limit"
390
436
  )
391
- source_bytes += descriptor_source_size(descriptor, package_root)
437
+ source_bytes += _descriptor_source_size(descriptor, package_root)
392
438
  if source_bytes > MAX_TOTAL_IMAGE_SOURCE_BYTES:
393
439
  raise ValueError(
394
440
  f"example image sources total {source_bytes} bytes, exceeding the "
@@ -465,10 +511,27 @@ def normalize_prompt_images(
465
511
  add_descriptor(source)
466
512
  image_blocks.append({"type": "image"})
467
513
  normalized[first_user]["content"] = [*content, *image_blocks]
514
+ # checked here, on the finished blocks, rather than inside the loop above: string content never
515
+ # enters that loop, and the top-level-image path appends to a message the loop already passed.
516
+ # this is the one point every shape has converged to the same form.
517
+ #
518
+ # the unit is a RUN of consecutive text blocks, not one block, for the reason the teacher
519
+ # renderer already documents: "<|image_" and "pad|>" are each harmless alone and only become
520
+ # the reserved marker once the template concatenates them. an image block ends a run, since the
521
+ # processor puts its own expansion there and user text cannot reach across it.
522
+ for message_index, message in enumerate(normalized):
523
+ text_run: list[str] = []
524
+ for block in message["content"]:
525
+ if block.get("type") == "text":
526
+ text_run.append(block["text"])
527
+ continue
528
+ _reject_literal_image_placeholder("".join(text_run), message_index, (IMAGE_PAD_TOKEN,))
529
+ text_run = []
530
+ _reject_literal_image_placeholder("".join(text_run), message_index, (IMAGE_PAD_TOKEN,))
468
531
  return NormalizedImages(normalized, descriptors)
469
532
 
470
533
 
471
- def descriptor_source_size(descriptor: str, package_root: str | Path | None) -> int:
534
+ def _descriptor_source_size(descriptor: str, package_root: str | Path | None) -> int:
472
535
  kind, value = _parse_descriptor(descriptor)
473
536
  if kind == "bytes":
474
537
  return len(base64.b64decode(value, validate=True))
@@ -481,7 +544,8 @@ def descriptor_source_size(descriptor: str, package_root: str | Path | None) ->
481
544
  raise ValueError("invalid internal image descriptor kind")
482
545
 
483
546
 
484
- def _read_descriptor_source(descriptor: str, package_root: str | Path | None) -> bytes:
547
+ def read_descriptor_source(descriptor: str, package_root: str | Path | None) -> bytes:
548
+ """Read one descriptor's raw source bytes under the per-source size limit."""
485
549
  kind, value = _parse_descriptor(descriptor)
486
550
  if kind == "bytes":
487
551
  try:
@@ -532,7 +596,7 @@ def image_descriptors_to_data_uris(
532
596
  source_bytes = 0
533
597
  decoded_bytes = 0
534
598
  for descriptor in descriptors:
535
- data = _read_descriptor_source(descriptor, package_root)
599
+ data = read_descriptor_source(descriptor, package_root)
536
600
  source_bytes += len(data)
537
601
  if source_bytes > MAX_TOTAL_IMAGE_SOURCE_BYTES:
538
602
  raise ValueError(
@@ -553,20 +617,65 @@ def _decode_image_bytes(data: bytes):
553
617
  from PIL import Image
554
618
  except ImportError as exc:
555
619
  raise RuntimeError("Pillow is required for multimodal image training") from exc
620
+ converted = None
556
621
  try:
557
622
  with Image.open(io.BytesIO(data)) as image:
558
623
  _validate_dimensions(image.width, image.height)
559
624
  image.load()
560
- return image.convert("RGB")
625
+ converted = image.convert("RGB")
626
+ converted.load()
627
+ return converted
561
628
  except ValueError:
629
+ if converted is not None:
630
+ converted.close()
562
631
  raise
563
632
  except Exception as exc:
633
+ if converted is not None:
634
+ converted.close()
564
635
  raise ValueError("image source is not a valid image") from exc
565
636
 
566
637
 
638
+ def messages_with_decoded_images(messages: list[dict], images: list[object]) -> list[dict]:
639
+ """Bind decoded images into a message list's image blocks, in order.
640
+
641
+ Shared by sft, opd, and grpo: each algorithm decodes the row's descriptors itself and then
642
+ needs the same binding into the chat-template input.
643
+ """
644
+ image_iter = iter(images)
645
+ prepared = []
646
+ for message in messages:
647
+ copied = dict(message)
648
+ content = copied.get("content")
649
+ if isinstance(content, list):
650
+ blocks = []
651
+ for block in content:
652
+ copied_block = dict(block)
653
+ if copied_block.get("type") == "image":
654
+ copied_block["image"] = next(image_iter)
655
+ blocks.append(copied_block)
656
+ copied["content"] = blocks
657
+ prepared.append(copied)
658
+ try:
659
+ next(image_iter)
660
+ except StopIteration:
661
+ return prepared
662
+ raise ValueError("unused decoded image while preparing multimodal sft tokens")
663
+
664
+
665
+ def decode_descriptor_pixels(data: bytes) -> None:
666
+ """Fully decode one image's pixels for validation, then release it.
667
+
668
+ Header inspection accepts an image whose pixel data is truncated or corrupt; only a full decode
669
+ finds that, and the caller wants the failure, not the image.
670
+ """
671
+ image = _decode_image_bytes(data)
672
+ image.close()
673
+
674
+
567
675
  def decode_image_descriptors(
568
676
  descriptors: list[str], package_root: str | Path | None
569
677
  ) -> list[object]:
678
+ """decode one row to fully loaded rgb images under aggregate limits."""
570
679
  if len(descriptors) > MAX_IMAGES_PER_EXAMPLE:
571
680
  raise ValueError(
572
681
  f"example contains {len(descriptors)} images, exceeding the {MAX_IMAGES_PER_EXAMPLE}-image limit"
@@ -575,7 +684,7 @@ def decode_image_descriptors(
575
684
  source_bytes = 0
576
685
  decoded_bytes = 0
577
686
  for descriptor in descriptors:
578
- data = _read_descriptor_source(descriptor, package_root)
687
+ data = read_descriptor_source(descriptor, package_root)
579
688
  source_bytes += len(data)
580
689
  if source_bytes > MAX_TOTAL_IMAGE_SOURCE_BYTES:
581
690
  raise ValueError(
@@ -587,7 +696,14 @@ def decode_image_descriptors(
587
696
  f"example decoded images exceed the {MAX_TOTAL_DECODED_BYTES}-byte limit"
588
697
  )
589
698
  prepared.append(data)
590
- return [_decode_image_bytes(data) for data in prepared]
699
+ images: list[Any] = []
700
+ try:
701
+ images.extend(_decode_image_bytes(data) for data in prepared)
702
+ except Exception:
703
+ for image in images:
704
+ image.close()
705
+ raise
706
+ return images
591
707
 
592
708
 
593
709
  def resolve_image_pad_token_id(processor, tok) -> int:
@@ -0,0 +1,61 @@
1
+ """hugging face helpers shared across control-plane and worker boundaries."""
2
+
3
+ from __future__ import annotations
4
+
5
+ from typing import TypedDict
6
+
7
+
8
+ class ModelRevisionKwargs(TypedDict, total=False):
9
+ revision: str
10
+
11
+
12
+ def model_revision_kwargs(revision: str = "") -> ModelRevisionKwargs:
13
+ """return the hub revision keyword for a nonempty pinned revision."""
14
+ return {"revision": revision} if revision else {}
15
+
16
+
17
+ def hub_error_transience(exc: BaseException) -> bool | None:
18
+ """classify known hub and transport failures, leaving unrelated errors unknown."""
19
+ import httpx
20
+ from huggingface_hub.errors import (
21
+ EntryNotFoundError,
22
+ GatedRepoError,
23
+ HfHubHTTPError,
24
+ LocalEntryNotFoundError,
25
+ RepositoryNotFoundError,
26
+ RevisionNotFoundError,
27
+ )
28
+ from requests.exceptions import ConnectionError as RequestsConnectionError
29
+ from requests.exceptions import RequestException
30
+ from requests.exceptions import Timeout as RequestsTimeout
31
+
32
+ if isinstance(exc, (RepositoryNotFoundError, RevisionNotFoundError, GatedRepoError)):
33
+ return False
34
+ if isinstance(exc, LocalEntryNotFoundError):
35
+ return True
36
+ if isinstance(exc, EntryNotFoundError):
37
+ return False
38
+ if isinstance(
39
+ exc,
40
+ (
41
+ RequestsConnectionError,
42
+ RequestsTimeout,
43
+ httpx.TimeoutException,
44
+ httpx.NetworkError,
45
+ httpx.RemoteProtocolError,
46
+ ),
47
+ ):
48
+ return True
49
+ if isinstance(exc, HfHubHTTPError):
50
+ response = getattr(exc, "response", None)
51
+ status = getattr(response, "status_code", None)
52
+ if status in {401, 403, 404}:
53
+ return False
54
+ return (
55
+ status is None
56
+ or status in {408, 425, 429}
57
+ or (isinstance(status, int) and 500 <= status <= 599)
58
+ )
59
+ if isinstance(exc, RequestException):
60
+ return False
61
+ return None
@@ -333,18 +333,15 @@ def profile_packaged_sft_dataset(
333
333
  package_root=base_dir,
334
334
  contract_text=_contract_text(base_dir, params),
335
335
  )
336
- from flash.content.multimodal import record_has_images
337
-
338
- if any(record_has_images(row, raw_environment.prompt_messages(row)) for row in rows):
339
- raise PackagedDatasetUnavailable(
340
- "image-bearing SFT datasets cannot be profiled on the torch-free control plane. "
341
- "Use text-only SFT records."
342
- )
343
336
  return prepare_sft_workload(
344
337
  spec,
345
338
  raw_environment,
346
339
  tokenizer_loader=tokenizer_loader,
347
340
  producer_version=producer_version,
341
+ # no torch here, so no VL processor: image rows are counted arithmetically from the
342
+ # published vision geometry rather than tokenized through the processor. see
343
+ # flash/engine/profiling/image_tokens.py.
344
+ require_processor=False,
348
345
  allow_packing=True,
349
346
  packing_support=packing_support,
350
347
  source_examples=source_examples,
@@ -0,0 +1,294 @@
1
+ """torch-free image token accounting for control-plane sft profiling.
2
+
3
+ one rendered image placeholder expands to the published vision grid size:
4
+
5
+ pad_run = (resized_h // patch_size) * (resized_w // patch_size) // merge_size**2
6
+
7
+ the upstream differential pins the resize policy, and pixels are fully loaded before quoting.
8
+ """
9
+
10
+ from __future__ import annotations
11
+
12
+ import json
13
+ import math
14
+ from dataclasses import dataclass, field
15
+ from pathlib import Path
16
+
17
+ from flash.content.multimodal import (
18
+ MAX_IMAGES_PER_EXAMPLE,
19
+ MAX_TOTAL_DECODED_BYTES,
20
+ MAX_TOTAL_IMAGE_SOURCE_BYTES,
21
+ decode_descriptor_pixels,
22
+ inspect_image_bytes,
23
+ read_descriptor_source,
24
+ )
25
+
26
+ # qwen VL publishes its pixel budget under `size`, older revisions under min_pixels/max_pixels.
27
+ # these defaults are the transformers fallbacks, used only when the config declares neither.
28
+ _DEFAULT_MIN_PIXELS = 56 * 56
29
+ _DEFAULT_MAX_PIXELS = 14 * 14 * 4 * 1280
30
+ # the same bound transformers enforces: beyond it smart_resize cannot hold the aspect ratio.
31
+ _MAX_ASPECT_RATIO = 200
32
+ # profile-wide unique full-decode work; per-row decoded bytes keep their separate bound.
33
+ MAX_PROFILE_DECODED_WORK_BYTES = MAX_TOTAL_DECODED_BYTES * MAX_IMAGES_PER_EXAMPLE
34
+
35
+
36
+ @dataclass(frozen=True)
37
+ class ImageDescriptorMetadata:
38
+ source_bytes: int
39
+ decoded_rgb_bytes: int
40
+ width: int
41
+ height: int
42
+
43
+
44
+ @dataclass
45
+ class ImageProfileValidationState:
46
+ """one profile's descriptor cache and cumulative decode budget.
47
+
48
+ a descriptor repeated across rows is validated and decoded ONCE; every occurrence still counts
49
+ toward the per-row limits below, so repetition cannot be used to smuggle a row past them.
50
+ """
51
+
52
+ descriptor_metadata: dict[str, ImageDescriptorMetadata] = field(default_factory=dict)
53
+ decoded_work_bytes: int = 0
54
+
55
+
56
+ def image_descriptor_metadata(
57
+ descriptors: list[str],
58
+ package_root: str | Path | None,
59
+ validation_state: ImageProfileValidationState,
60
+ *,
61
+ profile_decoded_work_limit: int,
62
+ ) -> list[ImageDescriptorMetadata]:
63
+ """return fully validated dimensions while bounding unique profile decode work."""
64
+ if len(descriptors) > MAX_IMAGES_PER_EXAMPLE:
65
+ raise ValueError(
66
+ f"example contains {len(descriptors)} images, exceeding the {MAX_IMAGES_PER_EXAMPLE}-image limit"
67
+ )
68
+ pending: dict[str, tuple[bytes, ImageDescriptorMetadata]] = {}
69
+ metadata = []
70
+ source_bytes = 0
71
+ decoded_bytes = 0
72
+ new_decoded_work = 0
73
+ for descriptor in descriptors:
74
+ item = validation_state.descriptor_metadata.get(descriptor)
75
+ if item is None:
76
+ prepared = pending.get(descriptor)
77
+ if prepared is None:
78
+ data = read_descriptor_source(descriptor, package_root)
79
+ decoded_rgb_bytes, width, height = inspect_image_bytes(data)
80
+ item = ImageDescriptorMetadata(
81
+ source_bytes=len(data),
82
+ decoded_rgb_bytes=decoded_rgb_bytes,
83
+ width=width,
84
+ height=height,
85
+ )
86
+ pending[descriptor] = data, item
87
+ new_decoded_work += item.decoded_rgb_bytes
88
+ else:
89
+ item = prepared[1]
90
+ metadata.append(item)
91
+ source_bytes += item.source_bytes
92
+ if source_bytes > MAX_TOTAL_IMAGE_SOURCE_BYTES:
93
+ raise ValueError(
94
+ f"example image sources exceed the {MAX_TOTAL_IMAGE_SOURCE_BYTES}-byte limit"
95
+ )
96
+ decoded_bytes += item.decoded_rgb_bytes
97
+ if decoded_bytes > MAX_TOTAL_DECODED_BYTES:
98
+ raise ValueError(
99
+ f"example decoded images exceed the {MAX_TOTAL_DECODED_BYTES}-byte limit"
100
+ )
101
+
102
+ prospective_decoded_work = validation_state.decoded_work_bytes + new_decoded_work
103
+ if prospective_decoded_work > profile_decoded_work_limit:
104
+ raise ValueError(
105
+ f"profile decoded image work exceeds the {profile_decoded_work_limit}-byte limit"
106
+ )
107
+
108
+ # fully decode each new descriptor before committing anything: a header that parses but whose
109
+ # pixels are corrupt must fail the row, and must leave neither the cache nor the budget touched.
110
+ for data, _item in pending.values():
111
+ decode_descriptor_pixels(data)
112
+ validation_state.descriptor_metadata.update(
113
+ {descriptor: item for descriptor, (_data, item) in pending.items()}
114
+ )
115
+ validation_state.decoded_work_bytes = prospective_decoded_work
116
+ return metadata
117
+
118
+
119
+ class ImageGeometryUnavailable(ValueError):
120
+ """the model's published preprocessor config does not describe its image geometry."""
121
+
122
+ def __init__(self, message: str, *, plane_fault: bool = False) -> None:
123
+ super().__init__(message)
124
+ self.plane_fault = plane_fault
125
+
126
+
127
+ @dataclass(frozen=True)
128
+ class ImageGeometry:
129
+ """the published vision geometry a checkpoint expands images with."""
130
+
131
+ patch_size: int
132
+ merge_size: int
133
+ min_pixels: int
134
+ max_pixels: int
135
+
136
+ @property
137
+ def factor(self) -> int:
138
+ return self.patch_size * self.merge_size
139
+
140
+
141
+ def smart_resize(
142
+ height: int, width: int, factor: int, min_pixels: int, max_pixels: int
143
+ ) -> tuple[int, int]:
144
+ """resize dimensions to the qwen vision factor and pixel budget."""
145
+ if height <= 0 or width <= 0:
146
+ raise ValueError("image width and height must be positive")
147
+ if max(height, width) / min(height, width) > _MAX_ASPECT_RATIO:
148
+ raise ValueError(
149
+ f"absolute aspect ratio must be smaller than {_MAX_ASPECT_RATIO}, "
150
+ f"got {max(height, width) / min(height, width)}"
151
+ )
152
+ h_bar = round(height / factor) * factor
153
+ w_bar = round(width / factor) * factor
154
+ if h_bar * w_bar > max_pixels:
155
+ beta = math.sqrt((height * width) / max_pixels)
156
+ h_bar = max(factor, math.floor(height / beta / factor) * factor)
157
+ w_bar = max(factor, math.floor(width / beta / factor) * factor)
158
+ elif h_bar * w_bar < min_pixels:
159
+ beta = math.sqrt(min_pixels / (height * width))
160
+ h_bar = math.ceil(height * beta / factor) * factor
161
+ w_bar = math.ceil(width * beta / factor) * factor
162
+ return h_bar, w_bar
163
+
164
+
165
+ def _positive_json_int(config: dict, field: str, *, required: bool = False) -> int | None:
166
+ if field not in config or config[field] is None:
167
+ if required:
168
+ raise ImageGeometryUnavailable(
169
+ f"preprocessor config must declare {field} as a positive JSON integer"
170
+ )
171
+ return None
172
+ value = config[field]
173
+ if type(value) is not int or value <= 0:
174
+ raise ImageGeometryUnavailable(
175
+ f"preprocessor config must declare {field} as a positive JSON integer"
176
+ )
177
+ return value
178
+
179
+
180
+ def geometry_from_preprocessor_config(config: object) -> ImageGeometry:
181
+ """read published patch, merge, and pixel-budget geometry."""
182
+ if not isinstance(config, dict):
183
+ raise ImageGeometryUnavailable("preprocessor config is not an object")
184
+ patch_size = _positive_json_int(config, "patch_size", required=True)
185
+ merge_size = _positive_json_int(config, "merge_size", required=True)
186
+ assert patch_size is not None
187
+ assert merge_size is not None
188
+ size_value = config.get("size")
189
+ if size_value is None:
190
+ size: dict = {}
191
+ elif isinstance(size_value, dict):
192
+ size = size_value
193
+ else:
194
+ raise ImageGeometryUnavailable("preprocessor config field size must be an object")
195
+ published_min = _positive_json_int(config, "min_pixels")
196
+ published_max = _positive_json_int(config, "max_pixels")
197
+ size_min = _positive_json_int(size, "shortest_edge")
198
+ size_max = _positive_json_int(size, "longest_edge")
199
+ min_pixels = published_min or size_min or _DEFAULT_MIN_PIXELS
200
+ max_pixels = published_max or size_max or _DEFAULT_MAX_PIXELS
201
+ if min_pixels > max_pixels:
202
+ raise ImageGeometryUnavailable(
203
+ f"preprocessor config declares min_pixels {min_pixels} above max_pixels {max_pixels}"
204
+ )
205
+ return ImageGeometry(
206
+ patch_size=patch_size,
207
+ merge_size=merge_size,
208
+ min_pixels=min_pixels,
209
+ max_pixels=max_pixels,
210
+ )
211
+
212
+
213
+ def load_image_geometry(model_id: str, revision: str = "") -> ImageGeometry:
214
+ """Fetch the model's published image geometry from the hub without importing torch."""
215
+ import os
216
+
217
+ from huggingface_hub import hf_hub_download
218
+
219
+ from flash.engine.huggingface import hub_error_transience, model_revision_kwargs
220
+
221
+ try:
222
+ path = hf_hub_download(
223
+ repo_id=model_id,
224
+ filename="preprocessor_config.json",
225
+ token=os.environ.get("HF_TOKEN"),
226
+ **model_revision_kwargs(revision),
227
+ )
228
+ with open(path, encoding="utf-8") as handle:
229
+ config = json.load(handle)
230
+ except ImageGeometryUnavailable:
231
+ raise
232
+ except Exception as exc:
233
+ transience = hub_error_transience(exc)
234
+ raise ImageGeometryUnavailable(
235
+ f"could not read the image geometry published by {model_id!r}; an image-bearing sft "
236
+ "dataset cannot be quoted without it",
237
+ # a downloaded local config that cannot be read is plane state, while generic worker
238
+ # prefetch os errors remain non-retriable at their caller boundary.
239
+ plane_fault=transience is True or (transience is None and isinstance(exc, OSError)),
240
+ ) from exc
241
+ return geometry_from_preprocessor_config(config)
242
+
243
+
244
+ def image_pad_tokens(width: int, height: int, geometry: ImageGeometry) -> int:
245
+ """The number of pad tokens one image of this size expands to."""
246
+ resized_h, resized_w = smart_resize(
247
+ height,
248
+ width,
249
+ geometry.factor,
250
+ geometry.min_pixels,
251
+ geometry.max_pixels,
252
+ )
253
+ patches = (resized_h // geometry.patch_size) * (resized_w // geometry.patch_size)
254
+ return patches // (geometry.merge_size * geometry.merge_size)
255
+
256
+
257
+ def descriptor_pad_tokens(
258
+ descriptors: list[str],
259
+ package_root: str | Path | None,
260
+ geometry: ImageGeometry,
261
+ validation_state: ImageProfileValidationState,
262
+ ) -> list[int]:
263
+ """return each descriptor occurrence's validated pad-token run length."""
264
+ metadata = image_descriptor_metadata(
265
+ descriptors,
266
+ package_root,
267
+ validation_state,
268
+ profile_decoded_work_limit=MAX_PROFILE_DECODED_WORK_BYTES,
269
+ )
270
+ return [image_pad_tokens(item.width, item.height, geometry) for item in metadata]
271
+
272
+
273
+ def expand_image_pad_runs(
274
+ input_ids: list[int], pad_token_id: int, pad_counts: list[int]
275
+ ) -> list[int]:
276
+ """expand each rendered image placeholder to its processor pad run."""
277
+ expanded: list[int] = []
278
+ seen = 0
279
+ for token_id in input_ids:
280
+ if token_id == pad_token_id:
281
+ if seen >= len(pad_counts):
282
+ raise ValueError(
283
+ "the rendered prompt contains more image placeholders than the example "
284
+ "supplied images"
285
+ )
286
+ expanded.extend([pad_token_id] * pad_counts[seen])
287
+ seen += 1
288
+ else:
289
+ expanded.append(token_id)
290
+ if seen != len(pad_counts):
291
+ raise ValueError(
292
+ f"the rendered prompt contains {seen} image placeholder(s), expected {len(pad_counts)}"
293
+ )
294
+ return expanded