freesolo-flash-dev 1.2.12__tar.gz → 1.2.13__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 (528) hide show
  1. {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/PKG-INFO +1 -1
  2. {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/flash/adapters/lora_rank.py +113 -2
  3. {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/flash/core/catalog.py +13 -0
  4. {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/flash/engine/worker/train/rl/child/multiturn.py +15 -3
  5. {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/flash/engine/worker/train/rl/multi_turn.py +103 -16
  6. {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/flash/engine/worker/train/rl/shims.py +15 -0
  7. {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/flash/serve/export.py +75 -0
  8. {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/flash/serve/preflight.py +37 -10
  9. {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/flash/server/routes/serving_smoke.py +9 -3
  10. {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/pyproject.toml +2 -2
  11. {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/tests/test_export.py +358 -0
  12. {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/tests/test_rl_train.py +199 -1
  13. {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/tests/test_server_envs_coverage.py +84 -13
  14. {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/uv.lock +1 -1
  15. {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/.dockerignore +0 -0
  16. {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/.env.example +0 -0
  17. {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/.github/CODEOWNERS +0 -0
  18. {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/.github/ISSUE_TEMPLATE/bug_report.yml +0 -0
  19. {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/.github/ISSUE_TEMPLATE/config.yml +0 -0
  20. {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/.github/ISSUE_TEMPLATE/feature_request.yml +0 -0
  21. {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/.github/PULL_REQUEST_TEMPLATE.md +0 -0
  22. {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/.github/dependabot.yml +0 -0
  23. {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/.github/workflows/auto-rebake.yml +0 -0
  24. {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/.github/workflows/bake-kernel-cache.yml +0 -0
  25. {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/.github/workflows/ci.yml +0 -0
  26. {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/.github/workflows/main-source-guard.yml +0 -0
  27. {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/.github/workflows/notify-tests-repo.yml +0 -0
  28. {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/.github/workflows/publish-dev.yml +0 -0
  29. {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/.github/workflows/publish-image.yml +0 -0
  30. {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/.github/workflows/publish.yml +0 -0
  31. {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/.github/workflows/version-parity.yml +0 -0
  32. {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/.github/workflows/worker-image.yml +0 -0
  33. {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/.gitignore +0 -0
  34. {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/CHANGELOG.md +0 -0
  35. {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/CODE_OF_CONDUCT.md +0 -0
  36. {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/CONTRIBUTING.md +0 -0
  37. {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/Dockerfile +0 -0
  38. {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/Dockerfile.worker +0 -0
  39. {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/LICENSE +0 -0
  40. {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/NOTICE +0 -0
  41. {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/README.md +0 -0
  42. {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/SECURITY.md +0 -0
  43. {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/SELF_HOSTING.md +0 -0
  44. {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/build/kernel_cache/.gitignore +0 -0
  45. {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/build/kernel_cache/.keep +0 -0
  46. {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/deploy/infisical/README.md +0 -0
  47. {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/deploy/infisical/entrypoint.sh +0 -0
  48. {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/docker/Dockerfile.kernelcache +0 -0
  49. {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/docker/Dockerfile.kernelcache.relayer +0 -0
  50. {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/docker/bake_kernel_cache.py +0 -0
  51. {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/docker/bake_pod_entry.py +0 -0
  52. {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/docker/extract_cudart_fix.py +0 -0
  53. {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/docker/kernel_fingerprint.py +0 -0
  54. {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/docker/make_rp_handler.py +0 -0
  55. {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/flash/__init__.py +0 -0
  56. {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/flash/_internal/__init__.py +0 -0
  57. {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/flash/_internal/channel.py +0 -0
  58. {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/flash/_internal/diagnostics.py +0 -0
  59. {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/flash/_internal/fileio.py +0 -0
  60. {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/flash/_internal/logging.py +0 -0
  61. {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/flash/_internal/paths.py +0 -0
  62. {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/flash/adapters/__init__.py +0 -0
  63. {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/flash/adapters/artifacts.py +0 -0
  64. {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/flash/cli/__init__.py +0 -0
  65. {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/flash/cli/__main__.py +0 -0
  66. {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/flash/cli/commands/__init__.py +0 -0
  67. {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/flash/cli/commands/deploy.py +0 -0
  68. {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/flash/cli/commands/env/__init__.py +0 -0
  69. {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/flash/cli/commands/env/episode.py +0 -0
  70. {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/flash/cli/commands/env/eval.py +0 -0
  71. {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/flash/cli/commands/env/eval_args.py +0 -0
  72. {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/flash/cli/commands/env/imports.py +0 -0
  73. {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/flash/cli/commands/env/list.py +0 -0
  74. {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/flash/cli/commands/env/push.py +0 -0
  75. {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/flash/cli/commands/env/retained.py +0 -0
  76. {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/flash/cli/commands/env/setup.py +0 -0
  77. {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/flash/cli/commands/env/test.py +0 -0
  78. {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/flash/cli/commands/env/test_evaluations.py +0 -0
  79. {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/flash/cli/commands/env/test_params.py +0 -0
  80. {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/flash/cli/commands/env/test_warnings.py +0 -0
  81. {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/flash/cli/commands/traces.py +0 -0
  82. {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/flash/cli/commands/train_cost.py +0 -0
  83. {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/flash/cli/scaffold/TRAINING.md +0 -0
  84. {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/flash/cli/scaffold/__init__.py +0 -0
  85. {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/flash/cli/ui/__init__.py +0 -0
  86. {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/flash/cli/ui/cost.py +0 -0
  87. {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/flash/cli/ui/env_panels.py +0 -0
  88. {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/flash/cli/ui/heartbeat.py +0 -0
  89. {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/flash/cli/ui/render.py +0 -0
  90. {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/flash/cli/ui/tables.py +0 -0
  91. {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/flash/cli/ui/tty.py +0 -0
  92. {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/flash/client/__init__.py +0 -0
  93. {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/flash/client/config.py +0 -0
  94. {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/flash/client/freesolo_api.py +0 -0
  95. {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/flash/client/http.py +0 -0
  96. {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/flash/client/runtime_secrets.py +0 -0
  97. {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/flash/client/shapes.py +0 -0
  98. {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/flash/client/specs.py +0 -0
  99. {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/flash/client/streaming.py +0 -0
  100. {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/flash/content/__init__.py +0 -0
  101. {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/flash/content/multimodal.py +0 -0
  102. {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/flash/content/structured_outputs.py +0 -0
  103. {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/flash/content/thinking.py +0 -0
  104. {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/flash/core/__init__.py +0 -0
  105. {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/flash/core/spec.py +0 -0
  106. {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/flash/cost/__init__.py +0 -0
  107. {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/flash/cost/analytical.py +0 -0
  108. {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/flash/cost/facts.py +0 -0
  109. {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/flash/cost/spec.py +0 -0
  110. {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/flash/cost/types.py +0 -0
  111. {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/flash/engine/__init__.py +0 -0
  112. {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/flash/engine/plan/__init__.py +0 -0
  113. {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/flash/engine/plan/kv_sizing.py +0 -0
  114. {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/flash/engine/plan/model_config_probe.py +0 -0
  115. {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/flash/engine/plan/recipe.py +0 -0
  116. {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/flash/engine/plan/steps.py +0 -0
  117. {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/flash/engine/plan/vram.py +0 -0
  118. {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/flash/engine/profiling/__init__.py +0 -0
  119. {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/flash/engine/profiling/dataset_profile.py +0 -0
  120. {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/flash/engine/profiling/sft_workload.py +0 -0
  121. {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/flash/engine/profiling/tokenizer.py +0 -0
  122. {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/flash/engine/profiling/workload_profile.py +0 -0
  123. {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/flash/engine/result/__init__.py +0 -0
  124. {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/flash/engine/result/accounting.py +0 -0
  125. {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/flash/engine/result/rollout_samples.py +0 -0
  126. {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/flash/engine/worker/__init__.py +0 -0
  127. {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/flash/engine/worker/__main__.py +0 -0
  128. {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/flash/engine/worker/backend_common.py +0 -0
  129. {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/flash/engine/worker/entry/__init__.py +0 -0
  130. {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/flash/engine/worker/entry/opd.py +0 -0
  131. {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/flash/engine/worker/entry/rl.py +0 -0
  132. {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/flash/engine/worker/entry/sft.py +0 -0
  133. {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/flash/engine/worker/io/__init__.py +0 -0
  134. {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/flash/engine/worker/io/heartbeat.py +0 -0
  135. {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/flash/engine/worker/io/hf.py +0 -0
  136. {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/flash/engine/worker/io/prefetch.py +0 -0
  137. {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/flash/engine/worker/io/wandb_log.py +0 -0
  138. {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/flash/engine/worker/model/__init__.py +0 -0
  139. {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/flash/engine/worker/model/adapter.py +0 -0
  140. {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/flash/engine/worker/model/decoding.py +0 -0
  141. {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/flash/engine/worker/model/lora.py +0 -0
  142. {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/flash/engine/worker/model/packing.py +0 -0
  143. {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/flash/engine/worker/opd_train.py +0 -0
  144. {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/flash/engine/worker/opd_train_runner.py +0 -0
  145. {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/flash/engine/worker/perf/__init__.py +0 -0
  146. {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/flash/engine/worker/perf/diagnostics.py +0 -0
  147. {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/flash/engine/worker/perf/lifecycle.py +0 -0
  148. {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/flash/engine/worker/perf/liger.py +0 -0
  149. {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/flash/engine/worker/perf/memory.py +0 -0
  150. {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/flash/engine/worker/rl_train.py +0 -0
  151. {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/flash/engine/worker/rl_train_runner.py +0 -0
  152. {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/flash/engine/worker/runtime/__init__.py +0 -0
  153. {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/flash/engine/worker/runtime/kernel_warmup.py +0 -0
  154. {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/flash/engine/worker/runtime/pkg_proxy.py +0 -0
  155. {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/flash/engine/worker/runtime/rng.py +0 -0
  156. {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/flash/engine/worker/score_batcher.py +0 -0
  157. {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/flash/engine/worker/sft_train.py +0 -0
  158. {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/flash/engine/worker/sft_train_runner.py +0 -0
  159. {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/flash/engine/worker/teacher/__init__.py +0 -0
  160. {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/flash/engine/worker/teacher/client.py +0 -0
  161. {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/flash/engine/worker/teacher/encoding.py +0 -0
  162. {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/flash/engine/worker/teacher/tokenizer_align.py +0 -0
  163. {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/flash/engine/worker/train/__init__.py +0 -0
  164. {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/flash/engine/worker/train/core/__init__.py +0 -0
  165. {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/flash/engine/worker/train/core/child/__init__.py +0 -0
  166. {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/flash/engine/worker/train/core/child/glue.py +0 -0
  167. {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/flash/engine/worker/train/finalize.py +0 -0
  168. {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/flash/engine/worker/train/opd/__init__.py +0 -0
  169. {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/flash/engine/worker/train/opd/batching.py +0 -0
  170. {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/flash/engine/worker/train/opd/bridge.py +0 -0
  171. {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/flash/engine/worker/train/opd/child/__init__.py +0 -0
  172. {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/flash/engine/worker/train/opd/child/bridge.py +0 -0
  173. {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/flash/engine/worker/train/opd/child/multiturn.py +0 -0
  174. {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/flash/engine/worker/train/opd/child/plugin.py +0 -0
  175. {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/flash/engine/worker/train/opd/child/structured.py +0 -0
  176. {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/flash/engine/worker/train/opd/failures.py +0 -0
  177. {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/flash/engine/worker/train/opd/gkd.py +0 -0
  178. {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/flash/engine/worker/train/opd/multiturn_validation.py +0 -0
  179. {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/flash/engine/worker/train/opd/overrides.py +0 -0
  180. {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/flash/engine/worker/train/opd/prompts.py +0 -0
  181. {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/flash/engine/worker/train/opd/scoring.py +0 -0
  182. {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/flash/engine/worker/train/opd/validation.py +0 -0
  183. {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/flash/engine/worker/train/rl/__init__.py +0 -0
  184. {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/flash/engine/worker/train/rl/checkpoints.py +0 -0
  185. {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/flash/engine/worker/train/rl/child/__init__.py +0 -0
  186. {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/flash/engine/worker/train/rl/child/plugin.py +0 -0
  187. {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/flash/engine/worker/train/rl/config.py +0 -0
  188. {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/flash/engine/worker/train/rl/inputs.py +0 -0
  189. {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/flash/engine/worker/train/rl/scoring.py +0 -0
  190. {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/flash/engine/worker/train/rl/single_turn.py +0 -0
  191. {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/flash/engine/worker/train/rl/verl_config.py +0 -0
  192. {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/flash/engine/worker/train/sft/__init__.py +0 -0
  193. {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/flash/engine/worker/train/sft/checkpoints.py +0 -0
  194. {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/flash/engine/worker/train/sft/config.py +0 -0
  195. {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/flash/engine/worker/verl/__init__.py +0 -0
  196. {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/flash/engine/worker/verl/capabilities.py +0 -0
  197. {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/flash/engine/worker/verl/checkpoints.py +0 -0
  198. {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/flash/engine/worker/verl/child_io.py +0 -0
  199. {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/flash/engine/worker/verl/diagnostics.py +0 -0
  200. {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/flash/engine/worker/verl/parallelism.py +0 -0
  201. {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/flash/engine/worker_entrypoint.py +0 -0
  202. {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/flash/envs/__init__.py +0 -0
  203. {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/flash/envs/adapter.py +0 -0
  204. {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/flash/envs/base.py +0 -0
  205. {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/flash/envs/cache_security.py +0 -0
  206. {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/flash/envs/dataset_selection.py +0 -0
  207. {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/flash/envs/evaluations.py +0 -0
  208. {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/flash/envs/identity.py +0 -0
  209. {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/flash/envs/loader.py +0 -0
  210. {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/flash/envs/namespace_listing.py +0 -0
  211. {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/flash/envs/package/__init__.py +0 -0
  212. {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/flash/envs/package/limits.py +0 -0
  213. {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/flash/envs/package/unpack.py +0 -0
  214. {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/flash/envs/pull.py +0 -0
  215. {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/flash/providers/__init__.py +0 -0
  216. {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/flash/providers/_lifecycle/__init__.py +0 -0
  217. {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/flash/providers/_lifecycle/auth.py +0 -0
  218. {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/flash/providers/_lifecycle/bootstrap.py +0 -0
  219. {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/flash/providers/_lifecycle/bootstrap_pip.py +0 -0
  220. {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/flash/providers/_lifecycle/bootstrap_secrets.py +0 -0
  221. {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/flash/providers/_lifecycle/deadline.py +0 -0
  222. {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/flash/providers/_lifecycle/http.py +0 -0
  223. {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/flash/providers/_lifecycle/instance.py +0 -0
  224. {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/flash/providers/_lifecycle/poll.py +0 -0
  225. {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/flash/providers/_lifecycle/poll_instance.py +0 -0
  226. {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/flash/providers/_lifecycle/provider.py +0 -0
  227. {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/flash/providers/_lifecycle/worker.py +0 -0
  228. {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/flash/providers/allocator.py +0 -0
  229. {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/flash/providers/artifacts/__init__.py +0 -0
  230. {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/flash/providers/artifacts/hf.py +0 -0
  231. {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/flash/providers/artifacts/preload_runpod.py +0 -0
  232. {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/flash/providers/artifacts/weight_cache.py +0 -0
  233. {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/flash/providers/base.py +0 -0
  234. {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/flash/providers/fit_errors.py +0 -0
  235. {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/flash/providers/lambda_/__init__.py +0 -0
  236. {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/flash/providers/lambda_/api.py +0 -0
  237. {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/flash/providers/lambda_/auth.py +0 -0
  238. {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/flash/providers/lambda_/gpus.py +0 -0
  239. {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/flash/providers/lambda_/jobs/__init__.py +0 -0
  240. {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/flash/providers/lambda_/jobs/builders.py +0 -0
  241. {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/flash/providers/lambda_/jobs/reap.py +0 -0
  242. {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/flash/providers/lambda_/preflight.py +0 -0
  243. {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/flash/providers/lambda_/pricing.py +0 -0
  244. {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/flash/providers/preflight.py +0 -0
  245. {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/flash/providers/realized.py +0 -0
  246. {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/flash/providers/runpod/__init__.py +0 -0
  247. {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/flash/providers/runpod/api.py +0 -0
  248. {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/flash/providers/runpod/auth.py +0 -0
  249. {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/flash/providers/runpod/cost.py +0 -0
  250. {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/flash/providers/runpod/gpus.py +0 -0
  251. {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/flash/providers/runpod/job_execution.py +0 -0
  252. {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/flash/providers/runpod/jobs.py +0 -0
  253. {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/flash/providers/runpod/preflight.py +0 -0
  254. {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/flash/providers/runpod/pricing.py +0 -0
  255. {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/flash/providers/runpod/resources.py +0 -0
  256. {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/flash/providers/runpod/serverless/__init__.py +0 -0
  257. {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/flash/providers/runpod/serverless/endpoints.py +0 -0
  258. {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/flash/providers/sharding.py +0 -0
  259. {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/flash/providers/vast/__init__.py +0 -0
  260. {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/flash/providers/vast/api.py +0 -0
  261. {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/flash/providers/vast/auth.py +0 -0
  262. {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/flash/providers/vast/jobs/__init__.py +0 -0
  263. {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/flash/providers/vast/jobs/builders.py +0 -0
  264. {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/flash/providers/vast/preflight.py +0 -0
  265. {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/flash/providers/vast/pricing.py +0 -0
  266. {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/flash/py.typed +0 -0
  267. {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/flash/runner/__init__.py +0 -0
  268. {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/flash/runner/artifacts.py +0 -0
  269. {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/flash/runner/attempts.py +0 -0
  270. {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/flash/runner/costs.py +0 -0
  271. {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/flash/runner/deadlines.py +0 -0
  272. {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/flash/runner/preparation.py +0 -0
  273. {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/flash/runner/reconciliation.py +0 -0
  274. {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/flash/runner/results/__init__.py +0 -0
  275. {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/flash/runner/results/checkpoints.py +0 -0
  276. {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/flash/runner/results/verified_revisions.py +0 -0
  277. {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/flash/runner/status.py +0 -0
  278. {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/flash/runner/submit.py +0 -0
  279. {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/flash/runner/supervise/__init__.py +0 -0
  280. {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/flash/runner/supervise/attach.py +0 -0
  281. {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/flash/runner/supervise/deploy.py +0 -0
  282. {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/flash/runner/supervise/lifecycle.py +0 -0
  283. {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/flash/runner/supervise/recovery.py +0 -0
  284. {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/flash/runner/supervise/seed_submission.py +0 -0
  285. {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/flash/runner/supervise/transitions.py +0 -0
  286. {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/flash/runner/weight_cache.py +0 -0
  287. {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/flash/schema/__init__.py +0 -0
  288. {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/flash/schema/fields.py +0 -0
  289. {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/flash/serve/__init__.py +0 -0
  290. {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/flash/serve/adapter_check.py +0 -0
  291. {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/flash/serve/deploy.py +0 -0
  292. {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/flash/serve/errors.py +0 -0
  293. {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/flash/serve/streaming.py +0 -0
  294. {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/flash/serve/thinking.py +0 -0
  295. {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/flash/serve/urls.py +0 -0
  296. {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/flash/server/__init__.py +0 -0
  297. {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/flash/server/__main__.py +0 -0
  298. {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/flash/server/app.py +0 -0
  299. {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/flash/server/billing/__init__.py +0 -0
  300. {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/flash/server/billing/charges.py +0 -0
  301. {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/flash/server/billing/retry.py +0 -0
  302. {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/flash/server/domain/__init__.py +0 -0
  303. {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/flash/server/domain/checkpoints.py +0 -0
  304. {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/flash/server/domain/environment_registry.py +0 -0
  305. {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/flash/server/domain/envs.py +0 -0
  306. {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/flash/server/domain/projects.py +0 -0
  307. {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/flash/server/domain/reconcile.py +0 -0
  308. {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/flash/server/domain/repo_cleanup.py +0 -0
  309. {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/flash/server/domain/run_registry.py +0 -0
  310. {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/flash/server/domain/teacher_broker.py +0 -0
  311. {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/flash/server/domain/teacher_errors.py +0 -0
  312. {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/flash/server/domain/teacher_requests.py +0 -0
  313. {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/flash/server/platform/__init__.py +0 -0
  314. {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/flash/server/platform/auth.py +0 -0
  315. {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/flash/server/platform/db.py +0 -0
  316. {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/flash/server/platform/deps.py +0 -0
  317. {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/flash/server/platform/internal_client.py +0 -0
  318. {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/flash/server/platform/locks.py +0 -0
  319. {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/flash/server/platform/runtime.py +0 -0
  320. {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/flash/server/routes/__init__.py +0 -0
  321. {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/flash/server/routes/envs.py +0 -0
  322. {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/flash/server/routes/meta.py +0 -0
  323. {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/flash/server/routes/runs.py +0 -0
  324. {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/flash/server/routes/serving.py +0 -0
  325. {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/flash/server/routes/serving_completion.py +0 -0
  326. {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/flash/server/routes/serving_revisions.py +0 -0
  327. {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/flash/server/routes/teacher.py +0 -0
  328. {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/flash/teacher/__init__.py +0 -0
  329. {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/flash/teacher/limits.py +0 -0
  330. {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/flash/teacher/retry_contract.py +0 -0
  331. {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/scripts/build_dev_dist.py +0 -0
  332. {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/scripts/check_file_size.py +0 -0
  333. {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/scripts/check_function_size.py +0 -0
  334. {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/scripts/check_verl_pin_exists.py +0 -0
  335. {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/scripts/scrub_history.sh +0 -0
  336. {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/tests/__init__.py +0 -0
  337. {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/tests/_helpers/__init__.py +0 -0
  338. {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/tests/_helpers/profile.py +0 -0
  339. {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/tests/_helpers/runner.py +0 -0
  340. {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/tests/_helpers/specs.py +0 -0
  341. {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/tests/_helpers/teacher.py +0 -0
  342. {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/tests/_helpers/vast.py +0 -0
  343. {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/tests/conftest.py +0 -0
  344. {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/tests/fixtures/math_eval.jsonl +0 -0
  345. {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/tests/fixtures/math_train.jsonl +0 -0
  346. {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/tests/live/__init__.py +0 -0
  347. {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/tests/live/conftest.py +0 -0
  348. {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/tests/live/test_lambda_live.py +0 -0
  349. {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/tests/live/test_runpod_live.py +0 -0
  350. {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/tests/live/test_vast_live.py +0 -0
  351. {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/tests/test_accounting_coverage.py +0 -0
  352. {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/tests/test_adapter_shard_completeness.py +0 -0
  353. {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/tests/test_agent_flash_cli_contract.py +0 -0
  354. {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/tests/test_algorithms.py +0 -0
  355. {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/tests/test_allocator.py +0 -0
  356. {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/tests/test_backend_common.py +0 -0
  357. {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/tests/test_backend_jobspec_contract.py +0 -0
  358. {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/tests/test_bake_kernel_cache.py +0 -0
  359. {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/tests/test_base_model_provenance.py +0 -0
  360. {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/tests/test_billing_retry.py +0 -0
  361. {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/tests/test_build_context_contract.py +0 -0
  362. {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/tests/test_cancel_remote.py +0 -0
  363. {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/tests/test_catalog_consistency.py +0 -0
  364. {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/tests/test_catalog_only_models.py +0 -0
  365. {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/tests/test_charge_pricing.py +0 -0
  366. {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/tests/test_checkpoints.py +0 -0
  367. {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/tests/test_cli_commands.py +0 -0
  368. {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/tests/test_cli_commands_coverage.py +0 -0
  369. {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/tests/test_cli_credential_shadowing.py +0 -0
  370. {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/tests/test_cli_errors.py +0 -0
  371. {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/tests/test_cli_estimate.py +0 -0
  372. {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/tests/test_cli_gpus_flag.py +0 -0
  373. {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/tests/test_cli_help.py +0 -0
  374. {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/tests/test_cli_main_coverage.py +0 -0
  375. {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/tests/test_cli_managed.py +0 -0
  376. {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/tests/test_cli_render_coverage.py +0 -0
  377. {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/tests/test_cli_render_theme.py +0 -0
  378. {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/tests/test_cli_traces.py +0 -0
  379. {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/tests/test_cli_wandb_warning.py +0 -0
  380. {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/tests/test_client.py +0 -0
  381. {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/tests/test_client_import_purity.py +0 -0
  382. {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/tests/test_client_server_integration.py +0 -0
  383. {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/tests/test_client_stream_reads.py +0 -0
  384. {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/tests/test_config_env_vars.py +0 -0
  385. {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/tests/test_config_overrides.py +0 -0
  386. {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/tests/test_controlled_experiment_repairs.py +0 -0
  387. {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/tests/test_cost_analytical.py +0 -0
  388. {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/tests/test_cost_equation.py +0 -0
  389. {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/tests/test_cost_estimate.py +0 -0
  390. {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/tests/test_cost_hardware.py +0 -0
  391. {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/tests/test_cost_models.py +0 -0
  392. {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/tests/test_dataset_profile.py +0 -0
  393. {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/tests/test_deploy_latency.py +0 -0
  394. {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/tests/test_dev_channel.py +0 -0
  395. {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/tests/test_disk_gb.py +0 -0
  396. {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/tests/test_endpoint_name.py +0 -0
  397. {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/tests/test_env_cache_evict.py +0 -0
  398. {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/tests/test_env_delete.py +0 -0
  399. {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/tests/test_env_download.py +0 -0
  400. {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/tests/test_env_download_api.py +0 -0
  401. {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/tests/test_env_evaluations.py +0 -0
  402. {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/tests/test_env_list_api.py +0 -0
  403. {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/tests/test_env_list_cli.py +0 -0
  404. {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/tests/test_env_list_hub.py +0 -0
  405. {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/tests/test_env_no_install.py +0 -0
  406. {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/tests/test_env_publish.py +0 -0
  407. {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/tests/test_env_pull.py +0 -0
  408. {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/tests/test_env_pull_coverage.py +0 -0
  409. {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/tests/test_env_pull_loader_coverage.py +0 -0
  410. {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/tests/test_env_pull_managed_control_plane.py +0 -0
  411. {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/tests/test_env_push.py +0 -0
  412. {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/tests/test_env_rate_limit_resolve.py +0 -0
  413. {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/tests/test_env_ref_pinning.py +0 -0
  414. {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/tests/test_env_test.py +0 -0
  415. {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/tests/test_envs_coverage.py +0 -0
  416. {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/tests/test_flash_mvp.py +0 -0
  417. {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/tests/test_flash_worker.py +0 -0
  418. {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/tests/test_flashinfer_cache_dirs.py +0 -0
  419. {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/tests/test_freesolo_api_transport.py +0 -0
  420. {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/tests/test_github_urlopen_retry.py +0 -0
  421. {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/tests/test_gpu_type_single_field.py +0 -0
  422. {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/tests/test_gpus.py +0 -0
  423. {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/tests/test_grpo_params.py +0 -0
  424. {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/tests/test_grpo_resident_sizing.py +0 -0
  425. {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/tests/test_grpo_reward_batching.py +0 -0
  426. {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/tests/test_health_liveness.py +0 -0
  427. {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/tests/test_hf_retry.py +0 -0
  428. {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/tests/test_idle_endpoint_reaper.py +0 -0
  429. {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/tests/test_infisical_secrets.py +0 -0
  430. {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/tests/test_instance_bootstrap_coverage.py +0 -0
  431. {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/tests/test_internal_client.py +0 -0
  432. {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/tests/test_jobs.py +0 -0
  433. {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/tests/test_kernel_cache.py +0 -0
  434. {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/tests/test_kernel_fingerprint.py +0 -0
  435. {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/tests/test_kv_util.py +0 -0
  436. {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/tests/test_lambda_api_coverage.py +0 -0
  437. {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/tests/test_lambda_runner.py +0 -0
  438. {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/tests/test_logging.py +0 -0
  439. {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/tests/test_login_perms.py +0 -0
  440. {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/tests/test_lora_rank_coverage.py +0 -0
  441. {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/tests/test_lora_rank_preflight.py +0 -0
  442. {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/tests/test_managed_config_fields.py +0 -0
  443. {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/tests/test_managed_hf_repo.py +0 -0
  444. {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/tests/test_metrics_schema_agent_contract.py +0 -0
  445. {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/tests/test_mig_guard.py +0 -0
  446. {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/tests/test_multi_gpu_gate.py +0 -0
  447. {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/tests/test_multimodal_training.py +0 -0
  448. {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/tests/test_named_reward_metrics.py +0 -0
  449. {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/tests/test_oom_escalate_gpu.py +0 -0
  450. {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/tests/test_opd.py +0 -0
  451. {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/tests/test_opd_limits.py +0 -0
  452. {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/tests/test_opd_multiturn_eos_boundary.py +0 -0
  453. {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/tests/test_opd_resume_safety.py +0 -0
  454. {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/tests/test_opd_train.py +0 -0
  455. {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/tests/test_orchestrator_flash.py +0 -0
  456. {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/tests/test_packing.py +0 -0
  457. {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/tests/test_packing_coverage.py +0 -0
  458. {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/tests/test_parasail_teacher.py +0 -0
  459. {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/tests/test_poll_helpers.py +0 -0
  460. {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/tests/test_preflight.py +0 -0
  461. {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/tests/test_projects.py +0 -0
  462. {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/tests/test_provider_preflight_coverage.py +0 -0
  463. {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/tests/test_provider_routing.py +0 -0
  464. {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/tests/test_provider_teardown_robustness.py +0 -0
  465. {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/tests/test_providers_symmetry.py +0 -0
  466. {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/tests/test_realized_cost.py +0 -0
  467. {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/tests/test_repo_cleanup.py +0 -0
  468. {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/tests/test_resolve_params_b.py +0 -0
  469. {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/tests/test_resume_on_retry.py +0 -0
  470. {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/tests/test_rollout_samples.py +0 -0
  471. {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/tests/test_runmgmt.py +0 -0
  472. {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/tests/test_runpod_api_delete.py +0 -0
  473. {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/tests/test_runpod_key_fingerprint.py +0 -0
  474. {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/tests/test_runpod_key_waterfall.py +0 -0
  475. {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/tests/test_serve.py +0 -0
  476. {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/tests/test_serve_reasoning_content.py +0 -0
  477. {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/tests/test_server_api.py +0 -0
  478. {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/tests/test_server_app_coverage.py +0 -0
  479. {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/tests/test_server_auth_singleflight.py +0 -0
  480. {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/tests/test_server_billing.py +0 -0
  481. {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/tests/test_server_checkpoints_coverage.py +0 -0
  482. {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/tests/test_server_db.py +0 -0
  483. {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/tests/test_server_locks_coverage.py +0 -0
  484. {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/tests/test_server_standalone.py +0 -0
  485. {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/tests/test_serving_context_preflight.py +0 -0
  486. {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/tests/test_serving_contract.py +0 -0
  487. {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/tests/test_serving_schema_coverage.py +0 -0
  488. {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/tests/test_sft_chunked_nll.py +0 -0
  489. {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/tests/test_sft_example_selection.py +0 -0
  490. {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/tests/test_sft_gc_off.py +0 -0
  491. {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/tests/test_sft_max_context.py +0 -0
  492. {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/tests/test_sft_train.py +0 -0
  493. {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/tests/test_sft_workload.py +0 -0
  494. {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/tests/test_spec_and_validation.py +0 -0
  495. {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/tests/test_step_floor.py +0 -0
  496. {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/tests/test_step_metrics.py +0 -0
  497. {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/tests/test_structured_outputs.py +0 -0
  498. {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/tests/test_teacher_broker.py +0 -0
  499. {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/tests/test_teacher_encoding_contract.py +0 -0
  500. {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/tests/test_thinking_config.py +0 -0
  501. {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/tests/test_train_context_preflight.py +0 -0
  502. {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/tests/test_training_controls.py +0 -0
  503. {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/tests/test_type_comment_prose.py +0 -0
  504. {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/tests/test_vast_api.py +0 -0
  505. {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/tests/test_vast_api_coverage.py +0 -0
  506. {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/tests/test_vast_offers.py +0 -0
  507. {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/tests/test_vast_provider_coverage.py +0 -0
  508. {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/tests/test_vast_runner.py +0 -0
  509. {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/tests/test_verified_revisions.py +0 -0
  510. {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/tests/test_verifiers.py +0 -0
  511. {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/tests/test_version.py +0 -0
  512. {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/tests/test_vl_warmstart_adapter_keys.py +0 -0
  513. {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/tests/test_vram_architecture.py +0 -0
  514. {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/tests/test_wandb_link.py +0 -0
  515. {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/tests/test_wandb_naming.py +0 -0
  516. {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/tests/test_warmstart_adapter_download.py +0 -0
  517. {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/tests/test_warmstart_cross_repo.py +0 -0
  518. {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/tests/test_warmstart_error_attribution.py +0 -0
  519. {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/tests/test_weight_cache.py +0 -0
  520. {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/tests/test_worker_dryrun.py +0 -0
  521. {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/tests/test_worker_hardexit.py +0 -0
  522. {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/tests/test_worker_image.py +0 -0
  523. {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/tests/test_worker_init_heartbeat.py +0 -0
  524. {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/tests/test_worker_stack.py +0 -0
  525. {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/tests/test_worker_thinking.py +0 -0
  526. {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/tests/test_workflow_contracts.py +0 -0
  527. {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/tests/test_workload_profile.py +0 -0
  528. {freesolo_flash_dev-1.2.12 → freesolo_flash_dev-1.2.13}/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.12
3
+ Version: 1.2.13
4
4
  Summary: Flash — managed LoRA post-training (SFT/GRPO/OPD) for Freesolo environments, driven by the `flash` CLI
5
5
  Project-URL: Homepage, https://github.com/freesolo-co/flash
6
6
  Project-URL: Repository, https://github.com/freesolo-co/flash
@@ -7,11 +7,11 @@ import json
7
7
  import math
8
8
  import re
9
9
  from collections.abc import Callable, Mapping
10
- from dataclasses import dataclass
10
+ from dataclasses import dataclass, field
11
11
  from decimal import Decimal, InvalidOperation
12
12
  from typing import TYPE_CHECKING, Any
13
13
 
14
- from flash.core.catalog import serving_context_cap, serving_lora_rank_cap
14
+ from flash.core.catalog import lora_expert_count, serving_context_cap, serving_lora_rank_cap
15
15
 
16
16
 
17
17
  class ServingPreflightError(ValueError):
@@ -279,6 +279,117 @@ def rank_from_adapter_config(config: Mapping[str, Any], *, source: str) -> int:
279
279
  )
280
280
 
281
281
 
282
+ _LORA_A_INFIX = ".lora_A."
283
+ _LORA_B_INFIX = ".lora_B."
284
+
285
+
286
+ @dataclass(frozen=True)
287
+ class DeclaredLoraRanks:
288
+ """The default rank, per-module overrides, and parameter-target module paths in a config."""
289
+
290
+ default: int | None = None
291
+ by_module: Mapping[str, int] = field(default_factory=dict)
292
+ stacked_rank_modules: tuple[str, ...] = ()
293
+ stacked_rank_multiplier: int | None = None
294
+
295
+ def __bool__(self) -> bool:
296
+ return self.default is not None or bool(self.by_module)
297
+
298
+
299
+ def declared_lora_ranks(config: Mapping[str, Any]) -> DeclaredLoraRanks:
300
+ """Read the per-module LoRA rank structure out of ``adapter_config.json``."""
301
+ if not isinstance(config, Mapping):
302
+ return DeclaredLoraRanks()
303
+ try:
304
+ default = _positive_int(config["r"], source="adapter_config.json", field="r")
305
+ except (KeyError, ValueError):
306
+ default = None
307
+
308
+ by_module: dict[str, int] = {}
309
+ pattern = config.get("rank_pattern")
310
+ if isinstance(pattern, Mapping):
311
+ for module, value in pattern.items():
312
+ try:
313
+ by_module[str(module)] = _positive_int(
314
+ value, source="adapter_config.json", field="rank_pattern"
315
+ )
316
+ except ValueError:
317
+ continue
318
+
319
+ stacked_rank_modules: list[str] = []
320
+ targets = config.get("target_parameters")
321
+ if isinstance(targets, list):
322
+ for target in targets:
323
+ if not isinstance(target, str):
324
+ continue
325
+ module, separator, _ = target.rpartition(".")
326
+ if separator and module:
327
+ stacked_rank_modules.append(module)
328
+
329
+ base_model = str(config.get("base_model_name_or_path") or "").strip()
330
+ return DeclaredLoraRanks(
331
+ default=default,
332
+ by_module=by_module,
333
+ stacked_rank_modules=tuple(stacked_rank_modules),
334
+ stacked_rank_multiplier=lora_expert_count(base_model),
335
+ )
336
+
337
+
338
+ def _rank_for_module(module_path: str, declared: DeclaredLoraRanks) -> int | None:
339
+ """Resolve a module's rank with PEFT's ordered, anchored ``rank_pattern`` matching."""
340
+ for module, rank in declared.by_module.items():
341
+ if not module:
342
+ continue
343
+ try:
344
+ # entries are regexes in PEFT, deliberately not escaped here either
345
+ if re.match(rf"(.*\.)?({module})$", module_path):
346
+ return rank
347
+ except re.error:
348
+ continue
349
+ return declared.default
350
+
351
+
352
+ def _module_uses_target_parameters(module_path: str, declared: DeclaredLoraRanks) -> bool:
353
+ """Whether this serialized module came from one of PEFT's targeted parameters."""
354
+ return any(
355
+ module_path == module or module_path.endswith(f".{module}")
356
+ for module in declared.stacked_rank_modules
357
+ )
358
+
359
+
360
+ def lora_tensor_rank_disagrees(key: str, shape: Any, declared: DeclaredLoraRanks) -> bool:
361
+ """Return whether a 2-D LoRA weight provably contradicts its configured rank.
362
+
363
+ Ordinary module weights carry exactly ``r`` on the LoRA axis. A 3-D parameter targeted through
364
+ PEFT's ``target_parameters`` serializes under its parent module and stacks every model expert on
365
+ that axis, so only that module may carry exactly ``r * num_experts``. The distinction must be per
366
+ module because one config may contain ordinary ``target_modules`` and fused parameters together.
367
+ """
368
+ if not declared:
369
+ return False
370
+ is_a = _LORA_A_INFIX in key
371
+ is_b = _LORA_B_INFIX in key
372
+ if is_a == is_b: # neither, or a key somehow claiming both
373
+ return False
374
+ if not isinstance(shape, (list, tuple)) or len(shape) != 2:
375
+ return False
376
+ dims = [d for d in shape if isinstance(d, int) and not isinstance(d, bool) and d > 0]
377
+ if len(dims) != 2:
378
+ return False
379
+
380
+ infix = _LORA_A_INFIX if is_a else _LORA_B_INFIX
381
+ module_path = key.partition(infix)[0]
382
+ rank = _rank_for_module(module_path, declared)
383
+ if rank is None:
384
+ return False
385
+ axis = dims[0] if is_a else dims[1]
386
+ if _module_uses_target_parameters(module_path, declared):
387
+ multiplier = declared.stacked_rank_multiplier
388
+ expected = rank * multiplier if multiplier is not None else rank
389
+ return axis != expected
390
+ return axis != rank
391
+
392
+
282
393
  def alpha_from_adapter_config(config: Mapping[str, Any], *, source: str) -> int:
283
394
  """Return the maximum LoRA alpha across default and per-module metadata."""
284
395
  return _max_adapter_value(
@@ -148,6 +148,9 @@ class ModelInfo:
148
148
  mamba_block_size: int = 0
149
149
  # grouped (in_features, out_features, count) for peft all-linear on the full loaded model.
150
150
  lora_target_shapes: tuple[tuple[int, int, int], ...] = ()
151
+ # fused routed experts stacked on the lora rank axis for target_parameters. zero means no
152
+ # catalog-backed stacked allowance; ordinary and unknown target parameters carry exactly r.
153
+ lora_expert_count: int = 0
151
154
 
152
155
  @property
153
156
  def is_moe(self) -> bool:
@@ -174,6 +177,7 @@ class ModelInfo:
174
177
  "linear_value_head_dim",
175
178
  "linear_conv_kernel_dim",
176
179
  "lora_target_shapes",
180
+ "lora_expert_count",
177
181
  ):
178
182
  data.pop(key, None)
179
183
  serving = data["serving"]
@@ -500,6 +504,7 @@ MODELS: dict[str, ModelInfo] = {
500
504
  (4608, 2048, 1),
501
505
  (4608, 4608, 1),
502
506
  ),
507
+ lora_expert_count=256,
503
508
  vocab_size=248_320,
504
509
  algos=ALGORITHMS,
505
510
  min_vram_gb=141,
@@ -569,6 +574,14 @@ def serving_lora_rank_cap(model: str | ModelInfo | None) -> int | None:
569
574
  return int(info.serving.max_lora_rank)
570
575
 
571
576
 
577
+ def lora_expert_count(model: str | ModelInfo | None) -> int | None:
578
+ """Return the exact fused-expert stack size for LoRA target parameters, when cataloged."""
579
+ info = _model_info_for_serving(model)
580
+ if info is None or info.lora_expert_count <= 0:
581
+ return None
582
+ return int(info.lora_expert_count)
583
+
584
+
572
585
  def serving_context_cap(model: str | ModelInfo | None) -> int | None:
573
586
  """Return the model's served ``max_model_len``, or None without a local serving entry.
574
587
 
@@ -62,11 +62,23 @@ def post_json(url: str, path: str, payload: dict) -> dict:
62
62
  with urllib.request.urlopen(request) as response:
63
63
  body = response.read()
64
64
  except urllib.error.HTTPError as error:
65
+ # decode inside the guard, raise outside it: `suppress(Exception)` around the raise as well
66
+ # swallowed the detail-bearing RuntimeError it was meant to let through, so the bridge's own
67
+ # error text ("can't start new thread") could never reach the user and every failure read as
68
+ # a bare "returned HTTP 400".
69
+ detail = None
65
70
  with contextlib.suppress(Exception):
66
- detail = json.loads(error.read().decode("utf-8"))["error"]
67
- raise RuntimeError(f"flash multi-turn bridge rejected {path}: {detail}") from error
71
+ detail = str(json.loads(error.read().decode("utf-8"))["error"])
72
+ # 5xx is the bridge failing to serve a valid request (resource exhaustion); 4xx is this
73
+ # request being rejected. naming which one it was stops a server fault from being read as a
74
+ # malformed payload.
75
+ fault = "could not serve" if error.code >= 500 else "rejected"
76
+ if detail:
77
+ raise RuntimeError(
78
+ f"flash multi-turn bridge {fault} {path} (HTTP {error.code}): {detail}"
79
+ ) from error
68
80
  raise RuntimeError(
69
- f"flash multi-turn bridge returned HTTP {error.code} for {path}"
81
+ f"flash multi-turn bridge {fault} {path}: HTTP {error.code} with no error detail"
70
82
  ) from error
71
83
  except (OSError, http.client.HTTPException) as error:
72
84
  raise RuntimeError(
@@ -39,6 +39,70 @@ _SINGLE_TURN_SCORE_BATCH_SIZE = 64
39
39
  _SINGLE_TURN_SCORE_FLUSH_WAIT_S = 0.1
40
40
  _SINGLE_TURN_SCORE_SHUTDOWN_WAIT_S = 5.0
41
41
 
42
+ # a body that could not be decoded at all: bad Content-Length, bad utf-8, or bad json.
43
+ _UNDECODABLE_BODY_ERRORS = (ValueError, TypeError, UnicodeDecodeError)
44
+
45
+
46
+ class _BadRequest(Exception):
47
+ """A request THIS BRIDGE is deliberately rejecting because the request itself is wrong.
48
+
49
+ Raised by the validating code rather than inferred from exception type at the handler, which
50
+ cannot distinguish the bridge rejecting a bad index from a user env raising IndexError inside
51
+ its own scoring -- and reporting the latter as a client error is the bug the 503 split fixes.
52
+ """
53
+
54
+
55
+ class _BadIndex(_BadRequest, IndexError):
56
+ """An index outside the dataset. Also an IndexError: that is what it genuinely is."""
57
+
58
+
59
+ class _BadSession(_BadRequest, KeyError):
60
+ """An unknown or duplicate session id. Also a KeyError, for the same reason.
61
+
62
+ ``KeyError.__str__`` reprs its argument, which would double-quote the message; this reports the
63
+ message as written so the client sees the same text every other rejection produces.
64
+ """
65
+
66
+ def __str__(self) -> str:
67
+ return self.args[0] if self.args else ""
68
+
69
+
70
+ def _request_field(payload: dict, key: str):
71
+ """Read one required payload field, or reject the request.
72
+
73
+ A decoded body that is not an object at all (``[]``, ``"x"``, ``3``) is a malformed request, so
74
+ it is rejected here rather than raising TypeError out of the subscript and reading as a fault.
75
+ """
76
+ if not isinstance(payload, dict):
77
+ raise _BadRequest(f"request body must be a json object, got {type(payload).__name__}")
78
+ try:
79
+ return payload[key]
80
+ except KeyError as exc:
81
+ raise _BadRequest(f"missing required field {key!r}") from exc
82
+
83
+
84
+ def request_int(payload: dict, key: str) -> int:
85
+ """Read one required integer payload field, or reject the request."""
86
+ value = _request_field(payload, key)
87
+ try:
88
+ return int(value)
89
+ # OverflowError: json decodes 1e309 to inf, and int(inf) overflows rather than ValueError-ing.
90
+ except (TypeError, ValueError, OverflowError) as exc:
91
+ raise _BadRequest(f"field {key!r} is not an integer: {value!r}") from exc
92
+
93
+
94
+ def request_session_id(payload: dict) -> str:
95
+ """Read the required session id, or reject the request."""
96
+ return str(_request_field(payload, "session_id"))
97
+
98
+
99
+ # ONLY the bridge's own deliberate rejections are client errors. classifying by exception TYPE
100
+ # instead cannot work: a user env raising IndexError/KeyError deep inside its own scoring would be
101
+ # reported as a malformed request -- the same "blame the caller for this side's failure" bug this
102
+ # module's 503 split exists to fix, one layer down. so the rejecting code raises _BadRequest itself
103
+ # and anything else reaching the handler is this side failing to serve a well-formed request.
104
+ _BAD_REQUEST_ERRORS = (_BadRequest,)
105
+
42
106
  # size the listen backlog for the full prompts_per_step * group_size connection burst.
43
107
  # socketserver's default of 5 resets overflowed clients, and bridge_post intentionally does not retry.
44
108
  # a fixed backlog only moves the cliff; linux may clamp this value to somaxconn.
@@ -113,10 +177,10 @@ class MultiTurnBridge:
113
177
  self._scorer.close(_MULTI_TURN_SCORE_SHUTDOWN_WAIT_S)
114
178
 
115
179
  def _session(self, payload: dict) -> dict:
116
- session_id = str(payload["session_id"])
180
+ session_id = request_session_id(payload)
117
181
  session = self._sessions.get(session_id)
118
182
  if session is None:
119
- raise KeyError(f"unknown multi-turn session {session_id}")
183
+ raise _BadSession(f"unknown multi-turn session {session_id}")
120
184
  # every touch renews the lease, so only a session nobody is driving can ever age out. all
121
185
  # callers already hold the lock.
122
186
  session["touched_at"] = time.monotonic()
@@ -137,12 +201,12 @@ class MultiTurnBridge:
137
201
  return stale
138
202
 
139
203
  def start(self, payload: dict) -> dict:
140
- index = int(payload["index"])
204
+ index = request_int(payload, "index")
141
205
  if index < 0 or index >= len(self._examples):
142
- raise IndexError(
206
+ raise _BadIndex(
143
207
  f"multi-turn example index {index} is outside [0, {len(self._examples)})"
144
208
  )
145
- session_id = str(payload["session_id"])
209
+ session_id = request_session_id(payload)
146
210
  example = self._examples[index]
147
211
  with self._lock:
148
212
  # swept here rather than on a timer thread: a session is only ever abandoned by an
@@ -150,7 +214,7 @@ class MultiTurnBridge:
150
214
  # exactly here. no extra thread, and nothing to shut down.
151
215
  reaped = self._reap_abandoned_sessions()
152
216
  if session_id in self._sessions:
153
- raise KeyError(f"duplicate multi-turn session {session_id}")
217
+ raise _BadSession(f"duplicate multi-turn session {session_id}")
154
218
  state = self._env.new_rollout_state(example)
155
219
  # new_rollout_state calls start_episode again after dataset preparation. adopt the dataset's
156
220
  # prompt so randomized envs do not generate for episode a and score episode b; keep the
@@ -216,7 +280,7 @@ class MultiTurnBridge:
216
280
  return score_rollouts(self._env, requests)
217
281
 
218
282
  def score(self, payload: dict) -> dict:
219
- turn_count = int(payload["turn_count"])
283
+ turn_count = request_int(payload, "turn_count")
220
284
  with self._lock:
221
285
  session = self._session(payload)
222
286
  state = session["state"]
@@ -282,7 +346,7 @@ class MultiTurnBridge:
282
346
 
283
347
  def close(self, payload: dict) -> dict:
284
348
  with self._lock:
285
- self._sessions.pop(str(payload["session_id"]), None)
349
+ self._sessions.pop(request_session_id(payload), None)
286
350
  return {"closed": True}
287
351
 
288
352
  def open_sessions(self) -> int:
@@ -371,9 +435,9 @@ def start_reward_server(
371
435
  )
372
436
 
373
437
  def _score_route(payload: dict) -> dict:
374
- index = int(payload["index"])
438
+ index = request_int(payload, "index")
375
439
  if index < 0 or index >= example_count:
376
- raise IndexError(f"reward example index {index} is outside [0, {example_count})")
440
+ raise _BadIndex(f"reward example index {index} is outside [0, {example_count})")
377
441
  solution_str = payload.get("solution_str", "")
378
442
  if score_batcher is not None:
379
443
  return {"score": float(score_batcher.submit((index, solution_str)))}
@@ -397,14 +461,37 @@ def start_reward_server(
397
461
  try:
398
462
  n = int(self.headers.get("Content-Length", "0"))
399
463
  payload = json.loads(self.rfile.read(n).decode("utf-8"))
400
- result = route(payload)
401
- except Exception as exc:
402
- print(f"[rl-verl] reward server request failed: {exc}", flush=True)
403
- body = json.dumps({"error": str(exc)}).encode()
404
- self.send_response(400)
464
+ except _UNDECODABLE_BODY_ERRORS as exc:
465
+ status = 400
466
+ detail = f"{type(exc).__name__}: {exc}"
405
467
  else:
468
+ try:
469
+ result = route(payload)
470
+ except _BAD_REQUEST_ERRORS as exc:
471
+ # the request itself is wrong: a malformed field, an index outside the dataset,
472
+ # or an unknown/duplicate session. no retry or capacity change makes it succeed.
473
+ # reported without the internal class name -- the message already says what is
474
+ # wrong, and "_BadIndex:" only names a private type the caller cannot act on.
475
+ status = 400
476
+ detail = str(exc)
477
+ except Exception as exc:
478
+ # the request was fine and this side could not serve it -- thread exhaustion
479
+ # ("can't start new thread") under rollout concurrency is the case that drove
480
+ # this split. 400 blamed the caller's payload and sent every reader to score
481
+ # code that cannot produce one, so a resource fault reads as a 5xx here.
482
+ status = 503
483
+ detail = f"{type(exc).__name__}: {exc}"
484
+ else:
485
+ status = 200
486
+ if status == 200:
406
487
  body = json.dumps(result).encode()
407
- self.send_response(200)
488
+ else:
489
+ print(
490
+ f"[rl-verl] reward server request failed ({status}) for {self.path}: {detail}",
491
+ flush=True,
492
+ )
493
+ body = json.dumps({"error": detail}).encode()
494
+ self.send_response(status)
408
495
  self.send_header("Content-Type", "application/json")
409
496
  self.send_header("Content-Length", str(len(body)))
410
497
  self.end_headers()
@@ -618,6 +618,21 @@ def render_reward_module(url_env: str = "FLASH_VERL_REWARD_URL") -> str:
618
618
  " with urllib.request.urlopen(req) as r:\n"
619
619
  " payload = json.loads(r.read().decode())\n"
620
620
  " return float(payload['score'])\n"
621
+ # HTTPError is a URLError subclass, so it must be handled FIRST or the bridge's own error
622
+ # text -- the reason the request failed, e.g. "can't start new thread" -- is dropped for a
623
+ # bare "HTTP Error 503: Service Unavailable" that names no cause.
624
+ " except urllib.error.HTTPError as exc:\n"
625
+ " detail = ''\n"
626
+ " try:\n"
627
+ " detail = str(json.loads(exc.read().decode())['error'])\n"
628
+ " except Exception:\n"
629
+ " detail = ''\n"
630
+ " fault = 'could not serve' if exc.code >= 500 else 'rejected'\n"
631
+ " if detail:\n"
632
+ " raise RuntimeError('flash reward bridge %s the request (HTTP %s): %s'\n"
633
+ " % (fault, exc.code, detail)) from exc\n"
634
+ " raise RuntimeError('flash reward bridge %s the request: HTTP %s with no error detail'\n"
635
+ " % (fault, exc.code)) from exc\n"
621
636
  " except urllib.error.URLError as exc:\n"
622
637
  " raise RuntimeError('flash reward bridge request failed: %s' % exc) from exc\n"
623
638
  " except Exception as exc:\n"
@@ -27,6 +27,11 @@ from flash.adapters.artifacts import (
27
27
  has_loadable_adapter_weights,
28
28
  is_adapter_weight_filename,
29
29
  )
30
+ from flash.adapters.lora_rank import (
31
+ DeclaredLoraRanks,
32
+ declared_lora_ranks,
33
+ lora_tensor_rank_disagrees,
34
+ )
30
35
  from flash.serve.deploy import ServingError
31
36
 
32
37
  logger = get_logger(__name__)
@@ -395,6 +400,9 @@ def _normalize_adapter_key_namespace(adapter_dir: Path) -> str:
395
400
  raise ValueError("no adapter_model weight file to normalize")
396
401
  if paths[0].name.endswith(".safetensors"):
397
402
  scans = [_scan_safetensors(path) for path in paths]
403
+ # before any rewrite: the shapes are what they are, and an adapter whose tensors contradict
404
+ # its own config is unloadable regardless of which key namespace it ends up in.
405
+ _verify_export_tensor_ranks(adapter_dir, scans)
398
406
  elif any(_bin_may_carry_infixed_keys(path) for path in paths):
399
407
  # one shard mentioning the infix commits every shard to a full scan. liveness and
400
408
  # post-rename collisions are properties of the union of the shards, so a shard that never
@@ -445,6 +453,9 @@ def _normalize_export_adapter_keys(adapter_dir: Path) -> str:
445
453
  """
446
454
  try:
447
455
  return _normalize_adapter_key_namespace(adapter_dir)
456
+ except _AdapterRankMismatch:
457
+ # a self-contradicting adapter, not an unreadable key namespace. reported as itself.
458
+ raise
448
459
  except Exception as exc:
449
460
  raise ServingError(
450
461
  f"could not normalize exported adapter keys ({exc}); refusing to export weights "
@@ -452,6 +463,70 @@ def _normalize_export_adapter_keys(adapter_dir: Path) -> str:
452
463
  ) from exc
453
464
 
454
465
 
466
+ class _AdapterRankMismatch(ValueError):
467
+ """The adapter's tensors contradict its own config, so it is unloadable as published.
468
+
469
+ Distinct from the errors `_normalize_export_adapter_keys` wraps: that wrapper reports a key
470
+ namespace it could not normalize, which is a different defect with a different remedy, and
471
+ letting this one be reported as that would send the user looking in the wrong place. A
472
+ ValueError so it reaches the export route as a 404 beside the sibling "no loadable LoRA
473
+ adapter" refusal, rather than as a 502 that blames the Hub for a bad artifact.
474
+ """
475
+
476
+
477
+ def _declared_export_ranks(adapter_dir: Path) -> DeclaredLoraRanks:
478
+ """The rank structure ``adapter_config.json`` declares, or an empty one we cannot judge from.
479
+
480
+ Empty rather than an error: a config carrying no readable rank is the pre-existing shape of
481
+ every fixture and of adapters PEFT wrote without one, and export has never required it. The
482
+ check below exists to catch a config and its tensors DISAGREEING, which needs both halves.
483
+ """
484
+ try:
485
+ config = json.loads((adapter_dir / "adapter_config.json").read_text(encoding="utf-8"))
486
+ except (OSError, UnicodeDecodeError, json.JSONDecodeError):
487
+ return DeclaredLoraRanks()
488
+ return declared_lora_ranks(config) if isinstance(config, dict) else DeclaredLoraRanks()
489
+
490
+
491
+ def _verify_export_tensor_ranks(adapter_dir: Path, scans: list[_WeightScan]) -> None:
492
+ """Refuse an export whose LoRA tensors do not carry the rank its config declares.
493
+
494
+ A serving engine sizes its LoRA slots from ``adapter_config.json`` and then binds the tensors,
495
+ so the two disagreeing is not a cosmetic metadata bug: it is an adapter that cannot be loaded.
496
+ That is not hypothetical -- a 35B MoE SFT run published `r: 32` beside expert tensors export
497
+ checked only for presence and key-namespace readability, so it succeeded and printed a Hub URL
498
+ while deploying the identical artifact failed. Export exiting 0 is what made a broken adapter
499
+ look like a finished deliverable.
500
+
501
+ `lora_tensor_rank_disagrees` resolves the rank PER MODULE the way PEFT does, so a
502
+ `rank_pattern` override is judged against its own rank rather than a summary of the config.
503
+
504
+ Only safetensors headers are read, because they carry shapes as metadata and are already parsed
505
+ here. A `.bin` would have to be loaded through torch, which the control plane does not install,
506
+ and paying that cost is not warranted for a representation the trainer no longer writes.
507
+ """
508
+ declared = _declared_export_ranks(adapter_dir)
509
+ if not declared:
510
+ return
511
+ mismatched = [
512
+ f"{key} has shape {descriptor.get('shape')}"
513
+ for scan in scans
514
+ for key, descriptor in (scan.header or {}).items()
515
+ if key != "__metadata__"
516
+ and isinstance(descriptor, dict)
517
+ and lora_tensor_rank_disagrees(key, descriptor.get("shape"), declared)
518
+ ]
519
+ if not mismatched:
520
+ return
521
+ shown = ", ".join(sorted(mismatched)[:3])
522
+ raise _AdapterRankMismatch(
523
+ f"adapter_config.json declares r={declared.default} but {len(mismatched)} LoRA tensor(s) "
524
+ f"do not carry the rank configured for their module (e.g. {shown}); a serving engine sizes "
525
+ "its LoRA slots from the config, so this adapter cannot be loaded and exporting it would "
526
+ "publish a broken artifact"
527
+ )
528
+
529
+
455
530
  def _rewrite_adapter_config_base_model(
456
531
  adapter_dir: Path, base_model: str, base_model_revision: str = ""
457
532
  ) -> bool:
@@ -18,6 +18,17 @@ from flash.engine.plan.vram import opd_completion_len
18
18
 
19
19
  SERVING_PROMPT_TOKEN_ALLOWANCE = 256
20
20
 
21
+ # ceiling on what one deployment smoke may generate, independent of whatever the run trains at.
22
+ # the smoke asks a fixed trivial question under a wall clock that must ALSO cover cold-starting the
23
+ # base model and loading the adapter, so a budget inherited from training spends that deadline on
24
+ # tokens nobody reads: an sft run raised to an 8192 context asked a thinking 27B for 8192 tokens and
25
+ # timed out the deployment. that also coupled the knobs the wrong way, since raising
26
+ # max_context_tokens to avoid training truncation made the run harder to deploy.
27
+ # sized at the largest thinking budget any algorithm resolves to by default, so no
28
+ # default-configured run is smoked at less than it is today, and a generation that still hits this
29
+ # has failed to answer a trivial prompt rather than run out of room.
30
+ SMOKE_COMPLETION_TOKEN_CEILING = 2048
31
+
21
32
 
22
33
  class ExternalSchemaReference(ValueError):
23
34
  def __init__(self, ref: str) -> None:
@@ -68,21 +79,15 @@ def validate_structured_output_patterns(constraint: dict) -> None:
68
79
  raise ValueError(f"{field} is invalid: {exc}") from exc
69
80
 
70
81
 
71
- def resolve_smoke_completion_tokens(spec: JobSpec) -> int:
72
- """Resolve the deployment smoke's completion budget for one generation.
73
-
74
- This sizes a single smoke request, not the run's training context. sft is the reason the two
75
- cannot share a number: an sft run has no completion budget of its own, because the worker trains
76
- one packed prompt+completion block bounded by ``max_context_tokens``.
77
- """
82
+ def _run_completion_budget(spec: JobSpec) -> int:
83
+ """The completion budget the run itself trains at, before the smoke's own ceiling applies."""
78
84
  explicit = spec.train.max_completion_tokens
79
85
  positive_explicit = int(explicit) if explicit is not None and int(explicit) > 0 else None
80
86
  if spec.algorithm == "opd":
81
87
  return opd_completion_len(positive_explicit, spec.thinking)
82
88
  if spec.algorithm == "sft":
83
- # SFT ignores max_completion_tokens, so mirror the worker: use explicit max_context_tokens with
84
- # the recipe fallback. do not subtract the smoke prompt; slight over-allocation is safe, while
85
- # under-allocation can reject a valid checkpoint. serving clamps the final request.
89
+ # SFT ignores max_completion_tokens, so mirror the worker: use explicit max_context_tokens
90
+ # with the recipe fallback.
86
91
  context = spec.train.max_context_tokens
87
92
  if context is not None and int(context) > 0:
88
93
  return int(context)
@@ -93,6 +98,28 @@ def resolve_smoke_completion_tokens(spec: JobSpec) -> int:
93
98
  return int(recipe.max_completion_len_thinking if spec.thinking else recipe.max_completion_len)
94
99
 
95
100
 
101
+ def resolve_smoke_completion_tokens(spec: JobSpec, *, constrained: bool = False) -> int:
102
+ """Resolve the deployment smoke's completion budget for one generation.
103
+
104
+ This sizes a single smoke request, not the run's training context, and the two are deliberately
105
+ decoupled: the smoke's question is fixed and trivial, so what a run trains at says nothing about
106
+ how many tokens answering it needs. Taking the run's number verbatim let a long training context
107
+ spend the smoke's whole wall-clock budget generating, which is why the ceiling exists.
108
+
109
+ A configured grammar is exempt. Deployment registers it as the adapter's serving default, so the
110
+ smoke generates under it too, and the shortest string it admits can exceed the ceiling -- a long
111
+ ``choice``, a fixed-repetition ``regex``, a schema with a large ``minLength``. Capping there
112
+ would truncate the only legal answer and reject an adapter that serves correctly. Deciding that
113
+ from the constraint needs the tokenizer and a minimum-length analysis of three grammar dialects,
114
+ so the run's own budget stands in for it: the run trains within that number, so it bounds the
115
+ grammar it was trained to satisfy.
116
+ """
117
+ budget = _run_completion_budget(spec)
118
+ if constrained:
119
+ return budget
120
+ return min(budget, SMOKE_COMPLETION_TOKEN_CEILING)
121
+
122
+
96
123
  def resolve_effective_completion_tokens(spec: JobSpec) -> int | None:
97
124
  """Resolve the completion budget the serving context guard must fit, if the run has one.
98
125
 
@@ -332,10 +332,16 @@ def _run_deployment_smoke(
332
332
  train = getattr(spec, "train", None)
333
333
  constraint = parse_structured_outputs(getattr(train, "structured_outputs", ""))
334
334
  max_tokens = 256
335
- # thinking spends tokens before content, so use the run's own completion budget regardless of
336
- # grammar; 256 tokens can truncate the think block and reject a healthy deployment.
335
+ # thinking spends tokens before content regardless of grammar, so 256 can truncate the think
336
+ # block and reject a healthy deployment. the resolver widens it to what the run reasons within,
337
+ # bounded by a smoke-specific ceiling -- this budget is spent from the same wall clock that must
338
+ # also cold-start the base model and load the adapter, so it cannot track the training context.
339
+ # a grammar lifts that ceiling: it is the adapter's serving default, so the smoke generates under
340
+ # it, and the shortest string it admits may be longer than the ceiling allows.
337
341
  if spec.thinking:
338
- max_tokens = max(256, resolve_smoke_completion_tokens(spec))
342
+ max_tokens = max(
343
+ 256, resolve_smoke_completion_tokens(spec, constrained=constraint is not None)
344
+ )
339
345
  serving_capacity = serving_completion_token_capacity(
340
346
  spec, prompt_allowance=SERVING_PROMPT_TOKEN_ALLOWANCE
341
347
  )
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "freesolo-flash-dev"
3
- version = "1.2.12"
3
+ version = "1.2.13"
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.12"
140
+ version = "1.2.13"
141
141
 
142
142
  [tool.pytest.ini_options]
143
143
  pythonpath = ["."]