freesolo-flash-dev 1.0.85__tar.gz → 1.0.87__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 (410) hide show
  1. {freesolo_flash_dev-1.0.85 → freesolo_flash_dev-1.0.87}/.env.example +34 -0
  2. {freesolo_flash_dev-1.0.85 → freesolo_flash_dev-1.0.87}/Dockerfile +13 -10
  3. {freesolo_flash_dev-1.0.85 → freesolo_flash_dev-1.0.87}/PKG-INFO +1 -1
  4. {freesolo_flash_dev-1.0.85 → freesolo_flash_dev-1.0.87}/SELF_HOSTING.md +33 -0
  5. freesolo_flash_dev-1.0.87/deploy/infisical/Dockerfile +46 -0
  6. freesolo_flash_dev-1.0.87/deploy/infisical/README.md +73 -0
  7. freesolo_flash_dev-1.0.87/deploy/infisical/entrypoint.sh +76 -0
  8. freesolo_flash_dev-1.0.87/flash/_logging.py +100 -0
  9. freesolo_flash_dev-1.0.87/flash/_paths.py +37 -0
  10. {freesolo_flash_dev-1.0.85 → freesolo_flash_dev-1.0.87}/flash/cli/TRAINING.md +3 -2
  11. {freesolo_flash_dev-1.0.85 → freesolo_flash_dev-1.0.87}/flash/cli/__init__.py +0 -4
  12. {freesolo_flash_dev-1.0.85 → freesolo_flash_dev-1.0.87}/flash/cli/env_setup.py +2 -1
  13. {freesolo_flash_dev-1.0.85 → freesolo_flash_dev-1.0.87}/flash/cli/render.py +1 -4
  14. {freesolo_flash_dev-1.0.85 → freesolo_flash_dev-1.0.87}/flash/client/config.py +7 -2
  15. {freesolo_flash_dev-1.0.85 → freesolo_flash_dev-1.0.87}/flash/engine/recipe.py +15 -0
  16. {freesolo_flash_dev-1.0.85 → freesolo_flash_dev-1.0.87}/flash/engine/worker/opd_train.py +42 -2
  17. {freesolo_flash_dev-1.0.85 → freesolo_flash_dev-1.0.87}/flash/engine/worker/perf/__init__.py +4 -9
  18. {freesolo_flash_dev-1.0.85 → freesolo_flash_dev-1.0.87}/flash/multimodal.py +7 -118
  19. {freesolo_flash_dev-1.0.85 → freesolo_flash_dev-1.0.87}/flash/providers/_worker.py +12 -22
  20. {freesolo_flash_dev-1.0.85 → freesolo_flash_dev-1.0.87}/flash/providers/lambdalabs/jobs/__init__.py +3 -8
  21. {freesolo_flash_dev-1.0.85 → freesolo_flash_dev-1.0.87}/flash/providers/runpod/jobs.py +2 -11
  22. {freesolo_flash_dev-1.0.85 → freesolo_flash_dev-1.0.87}/flash/providers/runpod/train/endpoints.py +6 -23
  23. {freesolo_flash_dev-1.0.85 → freesolo_flash_dev-1.0.87}/flash/runner/__init__.py +2 -1
  24. freesolo_flash_dev-1.0.87/flash/server/__main__.py +64 -0
  25. {freesolo_flash_dev-1.0.85 → freesolo_flash_dev-1.0.87}/flash/server/db.py +27 -3
  26. {freesolo_flash_dev-1.0.85 → freesolo_flash_dev-1.0.87}/flash/server/teacher_broker.py +1 -1
  27. {freesolo_flash_dev-1.0.85 → freesolo_flash_dev-1.0.87}/pyproject.toml +2 -2
  28. {freesolo_flash_dev-1.0.85 → freesolo_flash_dev-1.0.87}/tests/test_cli_render_coverage.py +2 -3
  29. {freesolo_flash_dev-1.0.85 → freesolo_flash_dev-1.0.87}/tests/test_cli_render_theme.py +2 -3
  30. freesolo_flash_dev-1.0.87/tests/test_config_env_vars.py +348 -0
  31. {freesolo_flash_dev-1.0.85 → freesolo_flash_dev-1.0.87}/tests/test_flash_worker.py +11 -16
  32. freesolo_flash_dev-1.0.87/tests/test_infisical_overlay.py +239 -0
  33. {freesolo_flash_dev-1.0.85 → freesolo_flash_dev-1.0.87}/tests/test_lambda_runner.py +0 -3
  34. {freesolo_flash_dev-1.0.85 → freesolo_flash_dev-1.0.87}/tests/test_multimodal_training.py +13 -121
  35. {freesolo_flash_dev-1.0.85 → freesolo_flash_dev-1.0.87}/tests/test_opd.py +8 -3
  36. {freesolo_flash_dev-1.0.85 → freesolo_flash_dev-1.0.87}/tests/test_opd_train.py +99 -0
  37. {freesolo_flash_dev-1.0.85 → freesolo_flash_dev-1.0.87}/tests/test_parasail_teacher.py +15 -4
  38. {freesolo_flash_dev-1.0.85 → freesolo_flash_dev-1.0.87}/tests/test_teacher_broker.py +17 -0
  39. {freesolo_flash_dev-1.0.85 → freesolo_flash_dev-1.0.87}/tests/test_worker_stack.py +8 -3
  40. {freesolo_flash_dev-1.0.85 → freesolo_flash_dev-1.0.87}/uv.lock +1 -1
  41. freesolo_flash_dev-1.0.85/flash/_logging.py +0 -37
  42. freesolo_flash_dev-1.0.85/flash/_update_check.py +0 -188
  43. freesolo_flash_dev-1.0.85/flash/server/__main__.py +0 -20
  44. freesolo_flash_dev-1.0.85/infisical-entrypoint.sh +0 -45
  45. freesolo_flash_dev-1.0.85/tests/test_update_check.py +0 -344
  46. {freesolo_flash_dev-1.0.85 → freesolo_flash_dev-1.0.87}/.dockerignore +0 -0
  47. {freesolo_flash_dev-1.0.85 → freesolo_flash_dev-1.0.87}/.github/ISSUE_TEMPLATE/bug_report.yml +0 -0
  48. {freesolo_flash_dev-1.0.85 → freesolo_flash_dev-1.0.87}/.github/ISSUE_TEMPLATE/config.yml +0 -0
  49. {freesolo_flash_dev-1.0.85 → freesolo_flash_dev-1.0.87}/.github/ISSUE_TEMPLATE/feature_request.yml +0 -0
  50. {freesolo_flash_dev-1.0.85 → freesolo_flash_dev-1.0.87}/.github/PULL_REQUEST_TEMPLATE.md +0 -0
  51. {freesolo_flash_dev-1.0.85 → freesolo_flash_dev-1.0.87}/.github/dependabot.yml +0 -0
  52. {freesolo_flash_dev-1.0.85 → freesolo_flash_dev-1.0.87}/.github/workflows/auto-rebake.yml +0 -0
  53. {freesolo_flash_dev-1.0.85 → freesolo_flash_dev-1.0.87}/.github/workflows/bake-kernel-cache.yml +0 -0
  54. {freesolo_flash_dev-1.0.85 → freesolo_flash_dev-1.0.87}/.github/workflows/ci.yml +0 -0
  55. {freesolo_flash_dev-1.0.85 → freesolo_flash_dev-1.0.87}/.github/workflows/main-source-guard.yml +0 -0
  56. {freesolo_flash_dev-1.0.85 → freesolo_flash_dev-1.0.87}/.github/workflows/notify-tests-repo.yml +0 -0
  57. {freesolo_flash_dev-1.0.85 → freesolo_flash_dev-1.0.87}/.github/workflows/publish-dev.yml +0 -0
  58. {freesolo_flash_dev-1.0.85 → freesolo_flash_dev-1.0.87}/.github/workflows/publish-image.yml +0 -0
  59. {freesolo_flash_dev-1.0.85 → freesolo_flash_dev-1.0.87}/.github/workflows/publish.yml +0 -0
  60. {freesolo_flash_dev-1.0.85 → freesolo_flash_dev-1.0.87}/.github/workflows/version-parity.yml +0 -0
  61. {freesolo_flash_dev-1.0.85 → freesolo_flash_dev-1.0.87}/.github/workflows/worker-image.yml +0 -0
  62. {freesolo_flash_dev-1.0.85 → freesolo_flash_dev-1.0.87}/.gitignore +0 -0
  63. {freesolo_flash_dev-1.0.85 → freesolo_flash_dev-1.0.87}/CODE_OF_CONDUCT.md +0 -0
  64. {freesolo_flash_dev-1.0.85 → freesolo_flash_dev-1.0.87}/CONTRIBUTING.md +0 -0
  65. {freesolo_flash_dev-1.0.85 → freesolo_flash_dev-1.0.87}/Dockerfile.worker +0 -0
  66. {freesolo_flash_dev-1.0.85 → freesolo_flash_dev-1.0.87}/LICENSE +0 -0
  67. {freesolo_flash_dev-1.0.85 → freesolo_flash_dev-1.0.87}/NOTICE +0 -0
  68. {freesolo_flash_dev-1.0.85 → freesolo_flash_dev-1.0.87}/README.md +0 -0
  69. {freesolo_flash_dev-1.0.85 → freesolo_flash_dev-1.0.87}/SECURITY.md +0 -0
  70. {freesolo_flash_dev-1.0.85 → freesolo_flash_dev-1.0.87}/build/kernel_cache/.gitignore +0 -0
  71. {freesolo_flash_dev-1.0.85 → freesolo_flash_dev-1.0.87}/build/kernel_cache/.keep +0 -0
  72. {freesolo_flash_dev-1.0.85 → freesolo_flash_dev-1.0.87}/docker/Dockerfile.kernelcache +0 -0
  73. {freesolo_flash_dev-1.0.85 → freesolo_flash_dev-1.0.87}/docker/Dockerfile.kernelcache.relayer +0 -0
  74. {freesolo_flash_dev-1.0.85 → freesolo_flash_dev-1.0.87}/docker/bake_kernel_cache.py +0 -0
  75. {freesolo_flash_dev-1.0.85 → freesolo_flash_dev-1.0.87}/docker/bake_pod_entry.py +0 -0
  76. {freesolo_flash_dev-1.0.85 → freesolo_flash_dev-1.0.87}/docker/kernel_fingerprint.py +0 -0
  77. {freesolo_flash_dev-1.0.85 → freesolo_flash_dev-1.0.87}/docker/make_rp_handler.py +0 -0
  78. {freesolo_flash_dev-1.0.85 → freesolo_flash_dev-1.0.87}/flash/__init__.py +0 -0
  79. {freesolo_flash_dev-1.0.85 → freesolo_flash_dev-1.0.87}/flash/_channel.py +0 -0
  80. {freesolo_flash_dev-1.0.85 → freesolo_flash_dev-1.0.87}/flash/_fileio.py +0 -0
  81. {freesolo_flash_dev-1.0.85 → freesolo_flash_dev-1.0.87}/flash/adapter_artifacts.py +0 -0
  82. {freesolo_flash_dev-1.0.85 → freesolo_flash_dev-1.0.87}/flash/catalog.py +0 -0
  83. {freesolo_flash_dev-1.0.85 → freesolo_flash_dev-1.0.87}/flash/cli/__main__.py +0 -0
  84. {freesolo_flash_dev-1.0.85 → freesolo_flash_dev-1.0.87}/flash/cli/_tty.py +0 -0
  85. {freesolo_flash_dev-1.0.85 → freesolo_flash_dev-1.0.87}/flash/cli/commands.py +0 -0
  86. {freesolo_flash_dev-1.0.85 → freesolo_flash_dev-1.0.87}/flash/cli/env_eval.py +0 -0
  87. {freesolo_flash_dev-1.0.85 → freesolo_flash_dev-1.0.87}/flash/cli/env_test.py +0 -0
  88. {freesolo_flash_dev-1.0.85 → freesolo_flash_dev-1.0.87}/flash/cli/envpush.py +0 -0
  89. {freesolo_flash_dev-1.0.85 → freesolo_flash_dev-1.0.87}/flash/cli/traces.py +0 -0
  90. {freesolo_flash_dev-1.0.85 → freesolo_flash_dev-1.0.87}/flash/cli/training_doc.py +0 -0
  91. {freesolo_flash_dev-1.0.85 → freesolo_flash_dev-1.0.87}/flash/client/__init__.py +0 -0
  92. {freesolo_flash_dev-1.0.85 → freesolo_flash_dev-1.0.87}/flash/client/http.py +0 -0
  93. {freesolo_flash_dev-1.0.85 → freesolo_flash_dev-1.0.87}/flash/client/runtime_secrets.py +0 -0
  94. {freesolo_flash_dev-1.0.85 → freesolo_flash_dev-1.0.87}/flash/client/specs.py +0 -0
  95. {freesolo_flash_dev-1.0.85 → freesolo_flash_dev-1.0.87}/flash/cost/__init__.py +0 -0
  96. {freesolo_flash_dev-1.0.85 → freesolo_flash_dev-1.0.87}/flash/cost/analytical.py +0 -0
  97. {freesolo_flash_dev-1.0.85 → freesolo_flash_dev-1.0.87}/flash/cost/facts.py +0 -0
  98. {freesolo_flash_dev-1.0.85 → freesolo_flash_dev-1.0.87}/flash/cost/spec.py +0 -0
  99. {freesolo_flash_dev-1.0.85 → freesolo_flash_dev-1.0.87}/flash/cost/types.py +0 -0
  100. {freesolo_flash_dev-1.0.85 → freesolo_flash_dev-1.0.87}/flash/diagnostics.py +0 -0
  101. {freesolo_flash_dev-1.0.85 → freesolo_flash_dev-1.0.87}/flash/engine/__init__.py +0 -0
  102. {freesolo_flash_dev-1.0.85 → freesolo_flash_dev-1.0.87}/flash/engine/accounting.py +0 -0
  103. {freesolo_flash_dev-1.0.85 → freesolo_flash_dev-1.0.87}/flash/engine/multiturn_reward_scoring.py +0 -0
  104. {freesolo_flash_dev-1.0.85 → freesolo_flash_dev-1.0.87}/flash/engine/reward_profile.py +0 -0
  105. {freesolo_flash_dev-1.0.85 → freesolo_flash_dev-1.0.87}/flash/engine/steps.py +0 -0
  106. {freesolo_flash_dev-1.0.85 → freesolo_flash_dev-1.0.87}/flash/engine/structured_outputs.py +0 -0
  107. {freesolo_flash_dev-1.0.85 → freesolo_flash_dev-1.0.87}/flash/engine/vram.py +0 -0
  108. {freesolo_flash_dev-1.0.85 → freesolo_flash_dev-1.0.87}/flash/engine/worker/__init__.py +0 -0
  109. {freesolo_flash_dev-1.0.85 → freesolo_flash_dev-1.0.87}/flash/engine/worker/__main__.py +0 -0
  110. {freesolo_flash_dev-1.0.85 → freesolo_flash_dev-1.0.87}/flash/engine/worker/_pkg.py +0 -0
  111. {freesolo_flash_dev-1.0.85 → freesolo_flash_dev-1.0.87}/flash/engine/worker/adapter.py +0 -0
  112. {freesolo_flash_dev-1.0.85 → freesolo_flash_dev-1.0.87}/flash/engine/worker/backend_common.py +0 -0
  113. {freesolo_flash_dev-1.0.85 → freesolo_flash_dev-1.0.87}/flash/engine/worker/decoding.py +0 -0
  114. {freesolo_flash_dev-1.0.85 → freesolo_flash_dev-1.0.87}/flash/engine/worker/finalize.py +0 -0
  115. {freesolo_flash_dev-1.0.85 → freesolo_flash_dev-1.0.87}/flash/engine/worker/grpo.py +0 -0
  116. {freesolo_flash_dev-1.0.85 → freesolo_flash_dev-1.0.87}/flash/engine/worker/grpo_multiturn.py +0 -0
  117. {freesolo_flash_dev-1.0.85 → freesolo_flash_dev-1.0.87}/flash/engine/worker/grpo_plugin.py +0 -0
  118. {freesolo_flash_dev-1.0.85 → freesolo_flash_dev-1.0.87}/flash/engine/worker/heartbeat.py +0 -0
  119. {freesolo_flash_dev-1.0.85 → freesolo_flash_dev-1.0.87}/flash/engine/worker/hf.py +0 -0
  120. {freesolo_flash_dev-1.0.85 → freesolo_flash_dev-1.0.87}/flash/engine/worker/kernel_warmup.py +0 -0
  121. {freesolo_flash_dev-1.0.85 → freesolo_flash_dev-1.0.87}/flash/engine/worker/lora.py +0 -0
  122. {freesolo_flash_dev-1.0.85 → freesolo_flash_dev-1.0.87}/flash/engine/worker/multiturn_glue.py +0 -0
  123. {freesolo_flash_dev-1.0.85 → freesolo_flash_dev-1.0.87}/flash/engine/worker/opd.py +0 -0
  124. {freesolo_flash_dev-1.0.85 → freesolo_flash_dev-1.0.87}/flash/engine/worker/opd_gkd.py +0 -0
  125. {freesolo_flash_dev-1.0.85 → freesolo_flash_dev-1.0.87}/flash/engine/worker/opd_multiturn.py +0 -0
  126. {freesolo_flash_dev-1.0.85 → freesolo_flash_dev-1.0.87}/flash/engine/worker/opd_plugin.py +0 -0
  127. {freesolo_flash_dev-1.0.85 → freesolo_flash_dev-1.0.87}/flash/engine/worker/opd_structured.py +0 -0
  128. {freesolo_flash_dev-1.0.85 → freesolo_flash_dev-1.0.87}/flash/engine/worker/packing.py +0 -0
  129. {freesolo_flash_dev-1.0.85 → freesolo_flash_dev-1.0.87}/flash/engine/worker/perf/attn.py +0 -0
  130. {freesolo_flash_dev-1.0.85 → freesolo_flash_dev-1.0.87}/flash/engine/worker/perf/diagnostics.py +0 -0
  131. {freesolo_flash_dev-1.0.85 → freesolo_flash_dev-1.0.87}/flash/engine/worker/perf/lifecycle.py +0 -0
  132. {freesolo_flash_dev-1.0.85 → freesolo_flash_dev-1.0.87}/flash/engine/worker/perf/liger.py +0 -0
  133. {freesolo_flash_dev-1.0.85 → freesolo_flash_dev-1.0.87}/flash/engine/worker/perf/loraplus.py +0 -0
  134. {freesolo_flash_dev-1.0.85 → freesolo_flash_dev-1.0.87}/flash/engine/worker/perf/memory.py +0 -0
  135. {freesolo_flash_dev-1.0.85 → freesolo_flash_dev-1.0.87}/flash/engine/worker/rl.py +0 -0
  136. {freesolo_flash_dev-1.0.85 → freesolo_flash_dev-1.0.87}/flash/engine/worker/rl_train.py +0 -0
  137. {freesolo_flash_dev-1.0.85 → freesolo_flash_dev-1.0.87}/flash/engine/worker/rng.py +0 -0
  138. {freesolo_flash_dev-1.0.85 → freesolo_flash_dev-1.0.87}/flash/engine/worker/rollout_samples.py +0 -0
  139. {freesolo_flash_dev-1.0.85 → freesolo_flash_dev-1.0.87}/flash/engine/worker/sft.py +0 -0
  140. {freesolo_flash_dev-1.0.85 → freesolo_flash_dev-1.0.87}/flash/engine/worker/sft_train.py +0 -0
  141. {freesolo_flash_dev-1.0.85 → freesolo_flash_dev-1.0.87}/flash/engine/worker/teacher.py +0 -0
  142. {freesolo_flash_dev-1.0.85 → freesolo_flash_dev-1.0.87}/flash/engine/worker/teacher_encoding.py +0 -0
  143. {freesolo_flash_dev-1.0.85 → freesolo_flash_dev-1.0.87}/flash/engine/worker/tokenizer_align.py +0 -0
  144. {freesolo_flash_dev-1.0.85 → freesolo_flash_dev-1.0.87}/flash/engine/worker/wandb_log.py +0 -0
  145. {freesolo_flash_dev-1.0.85 → freesolo_flash_dev-1.0.87}/flash/engine/worker_entrypoint.py +0 -0
  146. {freesolo_flash_dev-1.0.85 → freesolo_flash_dev-1.0.87}/flash/envs/__init__.py +0 -0
  147. {freesolo_flash_dev-1.0.85 → freesolo_flash_dev-1.0.87}/flash/envs/adapter.py +0 -0
  148. {freesolo_flash_dev-1.0.85 → freesolo_flash_dev-1.0.87}/flash/envs/archive.py +0 -0
  149. {freesolo_flash_dev-1.0.85 → freesolo_flash_dev-1.0.87}/flash/envs/archive_policy.py +0 -0
  150. {freesolo_flash_dev-1.0.85 → freesolo_flash_dev-1.0.87}/flash/envs/base.py +0 -0
  151. {freesolo_flash_dev-1.0.85 → freesolo_flash_dev-1.0.87}/flash/envs/evaluations.py +0 -0
  152. {freesolo_flash_dev-1.0.85 → freesolo_flash_dev-1.0.87}/flash/envs/loader.py +0 -0
  153. {freesolo_flash_dev-1.0.85 → freesolo_flash_dev-1.0.87}/flash/envs/pull.py +0 -0
  154. {freesolo_flash_dev-1.0.85 → freesolo_flash_dev-1.0.87}/flash/envs/registry.py +0 -0
  155. {freesolo_flash_dev-1.0.85 → freesolo_flash_dev-1.0.87}/flash/lora_rank.py +0 -0
  156. {freesolo_flash_dev-1.0.85 → freesolo_flash_dev-1.0.87}/flash/opd_limits.py +0 -0
  157. {freesolo_flash_dev-1.0.85 → freesolo_flash_dev-1.0.87}/flash/opd_retry_contract.py +0 -0
  158. {freesolo_flash_dev-1.0.85 → freesolo_flash_dev-1.0.87}/flash/opd_validation.py +0 -0
  159. {freesolo_flash_dev-1.0.85 → freesolo_flash_dev-1.0.87}/flash/providers/__init__.py +0 -0
  160. {freesolo_flash_dev-1.0.85 → freesolo_flash_dev-1.0.87}/flash/providers/_auth.py +0 -0
  161. {freesolo_flash_dev-1.0.85 → freesolo_flash_dev-1.0.87}/flash/providers/_deadline.py +0 -0
  162. {freesolo_flash_dev-1.0.85 → freesolo_flash_dev-1.0.87}/flash/providers/_hf_artifacts.py +0 -0
  163. {freesolo_flash_dev-1.0.85 → freesolo_flash_dev-1.0.87}/flash/providers/_hf_retry.py +0 -0
  164. {freesolo_flash_dev-1.0.85 → freesolo_flash_dev-1.0.87}/flash/providers/_http.py +0 -0
  165. {freesolo_flash_dev-1.0.85 → freesolo_flash_dev-1.0.87}/flash/providers/_instance.py +0 -0
  166. {freesolo_flash_dev-1.0.85 → freesolo_flash_dev-1.0.87}/flash/providers/_instance_bootstrap.py +0 -0
  167. {freesolo_flash_dev-1.0.85 → freesolo_flash_dev-1.0.87}/flash/providers/_instance_poll.py +0 -0
  168. {freesolo_flash_dev-1.0.85 → freesolo_flash_dev-1.0.87}/flash/providers/_instance_provider.py +0 -0
  169. {freesolo_flash_dev-1.0.85 → freesolo_flash_dev-1.0.87}/flash/providers/_poll.py +0 -0
  170. {freesolo_flash_dev-1.0.85 → freesolo_flash_dev-1.0.87}/flash/providers/allocator.py +0 -0
  171. {freesolo_flash_dev-1.0.85 → freesolo_flash_dev-1.0.87}/flash/providers/base.py +0 -0
  172. {freesolo_flash_dev-1.0.85 → freesolo_flash_dev-1.0.87}/flash/providers/lambdalabs/__init__.py +0 -0
  173. {freesolo_flash_dev-1.0.85 → freesolo_flash_dev-1.0.87}/flash/providers/lambdalabs/api.py +0 -0
  174. {freesolo_flash_dev-1.0.85 → freesolo_flash_dev-1.0.87}/flash/providers/lambdalabs/auth.py +0 -0
  175. {freesolo_flash_dev-1.0.85 → freesolo_flash_dev-1.0.87}/flash/providers/lambdalabs/gpus.py +0 -0
  176. {freesolo_flash_dev-1.0.85 → freesolo_flash_dev-1.0.87}/flash/providers/lambdalabs/jobs/builders.py +0 -0
  177. {freesolo_flash_dev-1.0.85 → freesolo_flash_dev-1.0.87}/flash/providers/lambdalabs/preflight.py +0 -0
  178. {freesolo_flash_dev-1.0.85 → freesolo_flash_dev-1.0.87}/flash/providers/lambdalabs/pricing.py +0 -0
  179. {freesolo_flash_dev-1.0.85 → freesolo_flash_dev-1.0.87}/flash/providers/preflight.py +0 -0
  180. {freesolo_flash_dev-1.0.85 → freesolo_flash_dev-1.0.87}/flash/providers/realized.py +0 -0
  181. {freesolo_flash_dev-1.0.85 → freesolo_flash_dev-1.0.87}/flash/providers/runpod/__init__.py +0 -0
  182. {freesolo_flash_dev-1.0.85 → freesolo_flash_dev-1.0.87}/flash/providers/runpod/api.py +0 -0
  183. {freesolo_flash_dev-1.0.85 → freesolo_flash_dev-1.0.87}/flash/providers/runpod/auth.py +0 -0
  184. {freesolo_flash_dev-1.0.85 → freesolo_flash_dev-1.0.87}/flash/providers/runpod/cost.py +0 -0
  185. {freesolo_flash_dev-1.0.85 → freesolo_flash_dev-1.0.87}/flash/providers/runpod/gpus.py +0 -0
  186. {freesolo_flash_dev-1.0.85 → freesolo_flash_dev-1.0.87}/flash/providers/runpod/keys.py +0 -0
  187. {freesolo_flash_dev-1.0.85 → freesolo_flash_dev-1.0.87}/flash/providers/runpod/preflight.py +0 -0
  188. {freesolo_flash_dev-1.0.85 → freesolo_flash_dev-1.0.87}/flash/providers/runpod/pricing.py +0 -0
  189. {freesolo_flash_dev-1.0.85 → freesolo_flash_dev-1.0.87}/flash/providers/runpod/slots.py +0 -0
  190. {freesolo_flash_dev-1.0.85 → freesolo_flash_dev-1.0.87}/flash/providers/runpod/train/__init__.py +0 -0
  191. {freesolo_flash_dev-1.0.85 → freesolo_flash_dev-1.0.87}/flash/providers/vast/__init__.py +0 -0
  192. {freesolo_flash_dev-1.0.85 → freesolo_flash_dev-1.0.87}/flash/providers/vast/api.py +0 -0
  193. {freesolo_flash_dev-1.0.85 → freesolo_flash_dev-1.0.87}/flash/providers/vast/auth.py +0 -0
  194. {freesolo_flash_dev-1.0.85 → freesolo_flash_dev-1.0.87}/flash/providers/vast/jobs/__init__.py +0 -0
  195. {freesolo_flash_dev-1.0.85 → freesolo_flash_dev-1.0.87}/flash/providers/vast/jobs/builders.py +0 -0
  196. {freesolo_flash_dev-1.0.85 → freesolo_flash_dev-1.0.87}/flash/providers/vast/preflight.py +0 -0
  197. {freesolo_flash_dev-1.0.85 → freesolo_flash_dev-1.0.87}/flash/providers/vast/pricing.py +0 -0
  198. {freesolo_flash_dev-1.0.85 → freesolo_flash_dev-1.0.87}/flash/providers/weight_cache_preload.py +0 -0
  199. {freesolo_flash_dev-1.0.85 → freesolo_flash_dev-1.0.87}/flash/py.typed +0 -0
  200. {freesolo_flash_dev-1.0.85 → freesolo_flash_dev-1.0.87}/flash/runner/checkpoints.py +0 -0
  201. {freesolo_flash_dev-1.0.85 → freesolo_flash_dev-1.0.87}/flash/runner/deploy.py +0 -0
  202. {freesolo_flash_dev-1.0.85 → freesolo_flash_dev-1.0.87}/flash/runner/lifecycle.py +0 -0
  203. {freesolo_flash_dev-1.0.85 → freesolo_flash_dev-1.0.87}/flash/runner/verified_revisions.py +0 -0
  204. {freesolo_flash_dev-1.0.85 → freesolo_flash_dev-1.0.87}/flash/schema/__init__.py +0 -0
  205. {freesolo_flash_dev-1.0.85 → freesolo_flash_dev-1.0.87}/flash/schema/fields.py +0 -0
  206. {freesolo_flash_dev-1.0.85 → freesolo_flash_dev-1.0.87}/flash/serve/__init__.py +0 -0
  207. {freesolo_flash_dev-1.0.85 → freesolo_flash_dev-1.0.87}/flash/serve/deploy.py +0 -0
  208. {freesolo_flash_dev-1.0.85 → freesolo_flash_dev-1.0.87}/flash/serve/export.py +0 -0
  209. {freesolo_flash_dev-1.0.85 → freesolo_flash_dev-1.0.87}/flash/serve/preflight.py +0 -0
  210. {freesolo_flash_dev-1.0.85 → freesolo_flash_dev-1.0.87}/flash/serve/pricing.py +0 -0
  211. {freesolo_flash_dev-1.0.85 → freesolo_flash_dev-1.0.87}/flash/serve/urls.py +0 -0
  212. {freesolo_flash_dev-1.0.85 → freesolo_flash_dev-1.0.87}/flash/server/__init__.py +0 -0
  213. {freesolo_flash_dev-1.0.85 → freesolo_flash_dev-1.0.87}/flash/server/_deps.py +0 -0
  214. {freesolo_flash_dev-1.0.85 → freesolo_flash_dev-1.0.87}/flash/server/_internal_client.py +0 -0
  215. {freesolo_flash_dev-1.0.85 → freesolo_flash_dev-1.0.87}/flash/server/_locks.py +0 -0
  216. {freesolo_flash_dev-1.0.85 → freesolo_flash_dev-1.0.87}/flash/server/_runtime.py +0 -0
  217. {freesolo_flash_dev-1.0.85 → freesolo_flash_dev-1.0.87}/flash/server/app.py +0 -0
  218. {freesolo_flash_dev-1.0.85 → freesolo_flash_dev-1.0.87}/flash/server/auth.py +0 -0
  219. {freesolo_flash_dev-1.0.85 → freesolo_flash_dev-1.0.87}/flash/server/billing.py +0 -0
  220. {freesolo_flash_dev-1.0.85 → freesolo_flash_dev-1.0.87}/flash/server/billing_retry.py +0 -0
  221. {freesolo_flash_dev-1.0.85 → freesolo_flash_dev-1.0.87}/flash/server/checkpoints.py +0 -0
  222. {freesolo_flash_dev-1.0.85 → freesolo_flash_dev-1.0.87}/flash/server/environment_registry.py +0 -0
  223. {freesolo_flash_dev-1.0.85 → freesolo_flash_dev-1.0.87}/flash/server/envs.py +0 -0
  224. {freesolo_flash_dev-1.0.85 → freesolo_flash_dev-1.0.87}/flash/server/projects.py +0 -0
  225. {freesolo_flash_dev-1.0.85 → freesolo_flash_dev-1.0.87}/flash/server/reconcile.py +0 -0
  226. {freesolo_flash_dev-1.0.85 → freesolo_flash_dev-1.0.87}/flash/server/repo_cleanup.py +0 -0
  227. {freesolo_flash_dev-1.0.85 → freesolo_flash_dev-1.0.87}/flash/server/routes/__init__.py +0 -0
  228. {freesolo_flash_dev-1.0.85 → freesolo_flash_dev-1.0.87}/flash/server/routes/envs.py +0 -0
  229. {freesolo_flash_dev-1.0.85 → freesolo_flash_dev-1.0.87}/flash/server/routes/meta.py +0 -0
  230. {freesolo_flash_dev-1.0.85 → freesolo_flash_dev-1.0.87}/flash/server/routes/runs.py +0 -0
  231. {freesolo_flash_dev-1.0.85 → freesolo_flash_dev-1.0.87}/flash/server/routes/serving.py +0 -0
  232. {freesolo_flash_dev-1.0.85 → freesolo_flash_dev-1.0.87}/flash/server/routes/teacher.py +0 -0
  233. {freesolo_flash_dev-1.0.85 → freesolo_flash_dev-1.0.87}/flash/server/run_registry.py +0 -0
  234. {freesolo_flash_dev-1.0.85 → freesolo_flash_dev-1.0.87}/flash/spec.py +0 -0
  235. {freesolo_flash_dev-1.0.85 → freesolo_flash_dev-1.0.87}/flash/thinking.py +0 -0
  236. {freesolo_flash_dev-1.0.85 → freesolo_flash_dev-1.0.87}/scripts/build_dev_dist.py +0 -0
  237. {freesolo_flash_dev-1.0.85 → freesolo_flash_dev-1.0.87}/scripts/scrub_history.sh +0 -0
  238. {freesolo_flash_dev-1.0.85 → freesolo_flash_dev-1.0.87}/tests/__init__.py +0 -0
  239. {freesolo_flash_dev-1.0.85 → freesolo_flash_dev-1.0.87}/tests/_helpers/__init__.py +0 -0
  240. {freesolo_flash_dev-1.0.85 → freesolo_flash_dev-1.0.87}/tests/_helpers/runner.py +0 -0
  241. {freesolo_flash_dev-1.0.85 → freesolo_flash_dev-1.0.87}/tests/_helpers/specs.py +0 -0
  242. {freesolo_flash_dev-1.0.85 → freesolo_flash_dev-1.0.87}/tests/_helpers/vast.py +0 -0
  243. {freesolo_flash_dev-1.0.85 → freesolo_flash_dev-1.0.87}/tests/conftest.py +0 -0
  244. {freesolo_flash_dev-1.0.85 → freesolo_flash_dev-1.0.87}/tests/fixtures/math_eval.jsonl +0 -0
  245. {freesolo_flash_dev-1.0.85 → freesolo_flash_dev-1.0.87}/tests/fixtures/math_train.jsonl +0 -0
  246. {freesolo_flash_dev-1.0.85 → freesolo_flash_dev-1.0.87}/tests/live/__init__.py +0 -0
  247. {freesolo_flash_dev-1.0.85 → freesolo_flash_dev-1.0.87}/tests/live/conftest.py +0 -0
  248. {freesolo_flash_dev-1.0.85 → freesolo_flash_dev-1.0.87}/tests/live/test_lambda_live.py +0 -0
  249. {freesolo_flash_dev-1.0.85 → freesolo_flash_dev-1.0.87}/tests/live/test_runpod_live.py +0 -0
  250. {freesolo_flash_dev-1.0.85 → freesolo_flash_dev-1.0.87}/tests/live/test_vast_live.py +0 -0
  251. {freesolo_flash_dev-1.0.85 → freesolo_flash_dev-1.0.87}/tests/test_accounting_coverage.py +0 -0
  252. {freesolo_flash_dev-1.0.85 → freesolo_flash_dev-1.0.87}/tests/test_agent_flash_cli_contract.py +0 -0
  253. {freesolo_flash_dev-1.0.85 → freesolo_flash_dev-1.0.87}/tests/test_algorithms.py +0 -0
  254. {freesolo_flash_dev-1.0.85 → freesolo_flash_dev-1.0.87}/tests/test_allocator.py +0 -0
  255. {freesolo_flash_dev-1.0.85 → freesolo_flash_dev-1.0.87}/tests/test_async_uploads.py +0 -0
  256. {freesolo_flash_dev-1.0.85 → freesolo_flash_dev-1.0.87}/tests/test_backend_common.py +0 -0
  257. {freesolo_flash_dev-1.0.85 → freesolo_flash_dev-1.0.87}/tests/test_backend_jobspec_contract.py +0 -0
  258. {freesolo_flash_dev-1.0.85 → freesolo_flash_dev-1.0.87}/tests/test_base_model_provenance.py +0 -0
  259. {freesolo_flash_dev-1.0.85 → freesolo_flash_dev-1.0.87}/tests/test_billing_retry.py +0 -0
  260. {freesolo_flash_dev-1.0.85 → freesolo_flash_dev-1.0.87}/tests/test_cancel_remote.py +0 -0
  261. {freesolo_flash_dev-1.0.85 → freesolo_flash_dev-1.0.87}/tests/test_catalog_consistency.py +0 -0
  262. {freesolo_flash_dev-1.0.85 → freesolo_flash_dev-1.0.87}/tests/test_charge_pricing.py +0 -0
  263. {freesolo_flash_dev-1.0.85 → freesolo_flash_dev-1.0.87}/tests/test_checkpoints.py +0 -0
  264. {freesolo_flash_dev-1.0.85 → freesolo_flash_dev-1.0.87}/tests/test_cli_commands.py +0 -0
  265. {freesolo_flash_dev-1.0.85 → freesolo_flash_dev-1.0.87}/tests/test_cli_commands_coverage.py +0 -0
  266. {freesolo_flash_dev-1.0.85 → freesolo_flash_dev-1.0.87}/tests/test_cli_credential_shadowing.py +0 -0
  267. {freesolo_flash_dev-1.0.85 → freesolo_flash_dev-1.0.87}/tests/test_cli_errors.py +0 -0
  268. {freesolo_flash_dev-1.0.85 → freesolo_flash_dev-1.0.87}/tests/test_cli_estimate.py +0 -0
  269. {freesolo_flash_dev-1.0.85 → freesolo_flash_dev-1.0.87}/tests/test_cli_gpus_flag.py +0 -0
  270. {freesolo_flash_dev-1.0.85 → freesolo_flash_dev-1.0.87}/tests/test_cli_help.py +0 -0
  271. {freesolo_flash_dev-1.0.85 → freesolo_flash_dev-1.0.87}/tests/test_cli_main_coverage.py +0 -0
  272. {freesolo_flash_dev-1.0.85 → freesolo_flash_dev-1.0.87}/tests/test_cli_managed.py +0 -0
  273. {freesolo_flash_dev-1.0.85 → freesolo_flash_dev-1.0.87}/tests/test_cli_traces.py +0 -0
  274. {freesolo_flash_dev-1.0.85 → freesolo_flash_dev-1.0.87}/tests/test_cli_wandb_warning.py +0 -0
  275. {freesolo_flash_dev-1.0.85 → freesolo_flash_dev-1.0.87}/tests/test_client.py +0 -0
  276. {freesolo_flash_dev-1.0.85 → freesolo_flash_dev-1.0.87}/tests/test_client_server_integration.py +0 -0
  277. {freesolo_flash_dev-1.0.85 → freesolo_flash_dev-1.0.87}/tests/test_client_stream_reads.py +0 -0
  278. {freesolo_flash_dev-1.0.85 → freesolo_flash_dev-1.0.87}/tests/test_config_overrides.py +0 -0
  279. {freesolo_flash_dev-1.0.85 → freesolo_flash_dev-1.0.87}/tests/test_controlled_experiment_repairs.py +0 -0
  280. {freesolo_flash_dev-1.0.85 → freesolo_flash_dev-1.0.87}/tests/test_cost_analytical.py +0 -0
  281. {freesolo_flash_dev-1.0.85 → freesolo_flash_dev-1.0.87}/tests/test_cost_equation.py +0 -0
  282. {freesolo_flash_dev-1.0.85 → freesolo_flash_dev-1.0.87}/tests/test_cost_estimate.py +0 -0
  283. {freesolo_flash_dev-1.0.85 → freesolo_flash_dev-1.0.87}/tests/test_cost_hardware.py +0 -0
  284. {freesolo_flash_dev-1.0.85 → freesolo_flash_dev-1.0.87}/tests/test_cost_models.py +0 -0
  285. {freesolo_flash_dev-1.0.85 → freesolo_flash_dev-1.0.87}/tests/test_cost_rewards.py +0 -0
  286. {freesolo_flash_dev-1.0.85 → freesolo_flash_dev-1.0.87}/tests/test_deploy_latency.py +0 -0
  287. {freesolo_flash_dev-1.0.85 → freesolo_flash_dev-1.0.87}/tests/test_dev_channel.py +0 -0
  288. {freesolo_flash_dev-1.0.85 → freesolo_flash_dev-1.0.87}/tests/test_disk_gb.py +0 -0
  289. {freesolo_flash_dev-1.0.85 → freesolo_flash_dev-1.0.87}/tests/test_endpoint_name.py +0 -0
  290. {freesolo_flash_dev-1.0.85 → freesolo_flash_dev-1.0.87}/tests/test_env_cache_evict.py +0 -0
  291. {freesolo_flash_dev-1.0.85 → freesolo_flash_dev-1.0.87}/tests/test_env_delete.py +0 -0
  292. {freesolo_flash_dev-1.0.85 → freesolo_flash_dev-1.0.87}/tests/test_env_download.py +0 -0
  293. {freesolo_flash_dev-1.0.85 → freesolo_flash_dev-1.0.87}/tests/test_env_download_api.py +0 -0
  294. {freesolo_flash_dev-1.0.85 → freesolo_flash_dev-1.0.87}/tests/test_env_evaluations.py +0 -0
  295. {freesolo_flash_dev-1.0.85 → freesolo_flash_dev-1.0.87}/tests/test_env_no_install.py +0 -0
  296. {freesolo_flash_dev-1.0.85 → freesolo_flash_dev-1.0.87}/tests/test_env_publish.py +0 -0
  297. {freesolo_flash_dev-1.0.85 → freesolo_flash_dev-1.0.87}/tests/test_env_pull.py +0 -0
  298. {freesolo_flash_dev-1.0.85 → freesolo_flash_dev-1.0.87}/tests/test_env_pull_coverage.py +0 -0
  299. {freesolo_flash_dev-1.0.85 → freesolo_flash_dev-1.0.87}/tests/test_env_pull_loader_coverage.py +0 -0
  300. {freesolo_flash_dev-1.0.85 → freesolo_flash_dev-1.0.87}/tests/test_env_pull_managed_control_plane.py +0 -0
  301. {freesolo_flash_dev-1.0.85 → freesolo_flash_dev-1.0.87}/tests/test_env_push.py +0 -0
  302. {freesolo_flash_dev-1.0.85 → freesolo_flash_dev-1.0.87}/tests/test_env_rate_limit_resolve.py +0 -0
  303. {freesolo_flash_dev-1.0.85 → freesolo_flash_dev-1.0.87}/tests/test_env_ref_pinning.py +0 -0
  304. {freesolo_flash_dev-1.0.85 → freesolo_flash_dev-1.0.87}/tests/test_env_test.py +0 -0
  305. {freesolo_flash_dev-1.0.85 → freesolo_flash_dev-1.0.87}/tests/test_envs_coverage.py +0 -0
  306. {freesolo_flash_dev-1.0.85 → freesolo_flash_dev-1.0.87}/tests/test_export.py +0 -0
  307. {freesolo_flash_dev-1.0.85 → freesolo_flash_dev-1.0.87}/tests/test_flash_mvp.py +0 -0
  308. {freesolo_flash_dev-1.0.85 → freesolo_flash_dev-1.0.87}/tests/test_flashinfer_cache_dirs.py +0 -0
  309. {freesolo_flash_dev-1.0.85 → freesolo_flash_dev-1.0.87}/tests/test_github_urlopen_retry.py +0 -0
  310. {freesolo_flash_dev-1.0.85 → freesolo_flash_dev-1.0.87}/tests/test_gpu_type_single_field.py +0 -0
  311. {freesolo_flash_dev-1.0.85 → freesolo_flash_dev-1.0.87}/tests/test_gpus.py +0 -0
  312. {freesolo_flash_dev-1.0.85 → freesolo_flash_dev-1.0.87}/tests/test_grpo_mask_aware.py +0 -0
  313. {freesolo_flash_dev-1.0.85 → freesolo_flash_dev-1.0.87}/tests/test_grpo_params.py +0 -0
  314. {freesolo_flash_dev-1.0.85 → freesolo_flash_dev-1.0.87}/tests/test_grpo_resident_sizing.py +0 -0
  315. {freesolo_flash_dev-1.0.85 → freesolo_flash_dev-1.0.87}/tests/test_grpo_reward_batching.py +0 -0
  316. {freesolo_flash_dev-1.0.85 → freesolo_flash_dev-1.0.87}/tests/test_health_liveness.py +0 -0
  317. {freesolo_flash_dev-1.0.85 → freesolo_flash_dev-1.0.87}/tests/test_hf_retry.py +0 -0
  318. {freesolo_flash_dev-1.0.85 → freesolo_flash_dev-1.0.87}/tests/test_idle_endpoint_reaper.py +0 -0
  319. {freesolo_flash_dev-1.0.85 → freesolo_flash_dev-1.0.87}/tests/test_instance_bootstrap_coverage.py +0 -0
  320. {freesolo_flash_dev-1.0.85 → freesolo_flash_dev-1.0.87}/tests/test_internal_client.py +0 -0
  321. {freesolo_flash_dev-1.0.85 → freesolo_flash_dev-1.0.87}/tests/test_jobs.py +0 -0
  322. {freesolo_flash_dev-1.0.85 → freesolo_flash_dev-1.0.87}/tests/test_kernel_cache.py +0 -0
  323. {freesolo_flash_dev-1.0.85 → freesolo_flash_dev-1.0.87}/tests/test_kernel_fingerprint.py +0 -0
  324. {freesolo_flash_dev-1.0.85 → freesolo_flash_dev-1.0.87}/tests/test_kv_util.py +0 -0
  325. {freesolo_flash_dev-1.0.85 → freesolo_flash_dev-1.0.87}/tests/test_lambda_api_coverage.py +0 -0
  326. {freesolo_flash_dev-1.0.85 → freesolo_flash_dev-1.0.87}/tests/test_logging.py +0 -0
  327. {freesolo_flash_dev-1.0.85 → freesolo_flash_dev-1.0.87}/tests/test_login_perms.py +0 -0
  328. {freesolo_flash_dev-1.0.85 → freesolo_flash_dev-1.0.87}/tests/test_lora_rank_coverage.py +0 -0
  329. {freesolo_flash_dev-1.0.85 → freesolo_flash_dev-1.0.87}/tests/test_lora_rank_preflight.py +0 -0
  330. {freesolo_flash_dev-1.0.85 → freesolo_flash_dev-1.0.87}/tests/test_managed_config_fields.py +0 -0
  331. {freesolo_flash_dev-1.0.85 → freesolo_flash_dev-1.0.87}/tests/test_managed_hf_repo.py +0 -0
  332. {freesolo_flash_dev-1.0.85 → freesolo_flash_dev-1.0.87}/tests/test_metrics_schema_agent_contract.py +0 -0
  333. {freesolo_flash_dev-1.0.85 → freesolo_flash_dev-1.0.87}/tests/test_mig_guard.py +0 -0
  334. {freesolo_flash_dev-1.0.85 → freesolo_flash_dev-1.0.87}/tests/test_multi_gpu_gate.py +0 -0
  335. {freesolo_flash_dev-1.0.85 → freesolo_flash_dev-1.0.87}/tests/test_multimodal_input_grads.py +0 -0
  336. {freesolo_flash_dev-1.0.85 → freesolo_flash_dev-1.0.87}/tests/test_named_reward_metrics.py +0 -0
  337. {freesolo_flash_dev-1.0.85 → freesolo_flash_dev-1.0.87}/tests/test_oom_escalate_gpu.py +0 -0
  338. {freesolo_flash_dev-1.0.85 → freesolo_flash_dev-1.0.87}/tests/test_opd_limits.py +0 -0
  339. {freesolo_flash_dev-1.0.85 → freesolo_flash_dev-1.0.87}/tests/test_opd_resume_safety.py +0 -0
  340. {freesolo_flash_dev-1.0.85 → freesolo_flash_dev-1.0.87}/tests/test_open_model_policy.py +0 -0
  341. {freesolo_flash_dev-1.0.85 → freesolo_flash_dev-1.0.87}/tests/test_orchestrator_flash.py +0 -0
  342. {freesolo_flash_dev-1.0.85 → freesolo_flash_dev-1.0.87}/tests/test_packing.py +0 -0
  343. {freesolo_flash_dev-1.0.85 → freesolo_flash_dev-1.0.87}/tests/test_packing_coverage.py +0 -0
  344. {freesolo_flash_dev-1.0.85 → freesolo_flash_dev-1.0.87}/tests/test_poll_helpers.py +0 -0
  345. {freesolo_flash_dev-1.0.85 → freesolo_flash_dev-1.0.87}/tests/test_preflight.py +0 -0
  346. {freesolo_flash_dev-1.0.85 → freesolo_flash_dev-1.0.87}/tests/test_projects.py +0 -0
  347. {freesolo_flash_dev-1.0.85 → freesolo_flash_dev-1.0.87}/tests/test_provider_preflight_coverage.py +0 -0
  348. {freesolo_flash_dev-1.0.85 → freesolo_flash_dev-1.0.87}/tests/test_provider_routing.py +0 -0
  349. {freesolo_flash_dev-1.0.85 → freesolo_flash_dev-1.0.87}/tests/test_provider_teardown_robustness.py +0 -0
  350. {freesolo_flash_dev-1.0.85 → freesolo_flash_dev-1.0.87}/tests/test_providers_symmetry.py +0 -0
  351. {freesolo_flash_dev-1.0.85 → freesolo_flash_dev-1.0.87}/tests/test_realized_cost.py +0 -0
  352. {freesolo_flash_dev-1.0.85 → freesolo_flash_dev-1.0.87}/tests/test_repo_cleanup.py +0 -0
  353. {freesolo_flash_dev-1.0.85 → freesolo_flash_dev-1.0.87}/tests/test_resolve_params_b.py +0 -0
  354. {freesolo_flash_dev-1.0.85 → freesolo_flash_dev-1.0.87}/tests/test_resume_on_retry.py +0 -0
  355. {freesolo_flash_dev-1.0.85 → freesolo_flash_dev-1.0.87}/tests/test_reward_profile.py +0 -0
  356. {freesolo_flash_dev-1.0.85 → freesolo_flash_dev-1.0.87}/tests/test_rl_train.py +0 -0
  357. {freesolo_flash_dev-1.0.85 → freesolo_flash_dev-1.0.87}/tests/test_rollout_samples.py +0 -0
  358. {freesolo_flash_dev-1.0.85 → freesolo_flash_dev-1.0.87}/tests/test_runmgmt.py +0 -0
  359. {freesolo_flash_dev-1.0.85 → freesolo_flash_dev-1.0.87}/tests/test_runpod_api_delete.py +0 -0
  360. {freesolo_flash_dev-1.0.85 → freesolo_flash_dev-1.0.87}/tests/test_runpod_key_fingerprint.py +0 -0
  361. {freesolo_flash_dev-1.0.85 → freesolo_flash_dev-1.0.87}/tests/test_runpod_key_waterfall.py +0 -0
  362. {freesolo_flash_dev-1.0.85 → freesolo_flash_dev-1.0.87}/tests/test_runpod_slots.py +0 -0
  363. {freesolo_flash_dev-1.0.85 → freesolo_flash_dev-1.0.87}/tests/test_serve.py +0 -0
  364. {freesolo_flash_dev-1.0.85 → freesolo_flash_dev-1.0.87}/tests/test_serve_reasoning_content.py +0 -0
  365. {freesolo_flash_dev-1.0.85 → freesolo_flash_dev-1.0.87}/tests/test_server_api.py +0 -0
  366. {freesolo_flash_dev-1.0.85 → freesolo_flash_dev-1.0.87}/tests/test_server_app_coverage.py +0 -0
  367. {freesolo_flash_dev-1.0.85 → freesolo_flash_dev-1.0.87}/tests/test_server_auth_singleflight.py +0 -0
  368. {freesolo_flash_dev-1.0.85 → freesolo_flash_dev-1.0.87}/tests/test_server_billing.py +0 -0
  369. {freesolo_flash_dev-1.0.85 → freesolo_flash_dev-1.0.87}/tests/test_server_checkpoints_coverage.py +0 -0
  370. {freesolo_flash_dev-1.0.85 → freesolo_flash_dev-1.0.87}/tests/test_server_db.py +0 -0
  371. {freesolo_flash_dev-1.0.85 → freesolo_flash_dev-1.0.87}/tests/test_server_envs_coverage.py +0 -0
  372. {freesolo_flash_dev-1.0.85 → freesolo_flash_dev-1.0.87}/tests/test_server_locks_coverage.py +0 -0
  373. {freesolo_flash_dev-1.0.85 → freesolo_flash_dev-1.0.87}/tests/test_server_standalone.py +0 -0
  374. {freesolo_flash_dev-1.0.85 → freesolo_flash_dev-1.0.87}/tests/test_serving_context_preflight.py +0 -0
  375. {freesolo_flash_dev-1.0.85 → freesolo_flash_dev-1.0.87}/tests/test_serving_contract.py +0 -0
  376. {freesolo_flash_dev-1.0.85 → freesolo_flash_dev-1.0.87}/tests/test_serving_pricing_coverage.py +0 -0
  377. {freesolo_flash_dev-1.0.85 → freesolo_flash_dev-1.0.87}/tests/test_serving_schema_coverage.py +0 -0
  378. {freesolo_flash_dev-1.0.85 → freesolo_flash_dev-1.0.87}/tests/test_sft_chunked_nll.py +0 -0
  379. {freesolo_flash_dev-1.0.85 → freesolo_flash_dev-1.0.87}/tests/test_sft_example_selection.py +0 -0
  380. {freesolo_flash_dev-1.0.85 → freesolo_flash_dev-1.0.87}/tests/test_sft_gc_off.py +0 -0
  381. {freesolo_flash_dev-1.0.85 → freesolo_flash_dev-1.0.87}/tests/test_sft_max_context.py +0 -0
  382. {freesolo_flash_dev-1.0.85 → freesolo_flash_dev-1.0.87}/tests/test_sft_train.py +0 -0
  383. {freesolo_flash_dev-1.0.85 → freesolo_flash_dev-1.0.87}/tests/test_spec_and_validation.py +0 -0
  384. {freesolo_flash_dev-1.0.85 → freesolo_flash_dev-1.0.87}/tests/test_step_metrics.py +0 -0
  385. {freesolo_flash_dev-1.0.85 → freesolo_flash_dev-1.0.87}/tests/test_structured_outputs.py +0 -0
  386. {freesolo_flash_dev-1.0.85 → freesolo_flash_dev-1.0.87}/tests/test_thinking_config.py +0 -0
  387. {freesolo_flash_dev-1.0.85 → freesolo_flash_dev-1.0.87}/tests/test_train_context_preflight.py +0 -0
  388. {freesolo_flash_dev-1.0.85 → freesolo_flash_dev-1.0.87}/tests/test_training_controls.py +0 -0
  389. {freesolo_flash_dev-1.0.85 → freesolo_flash_dev-1.0.87}/tests/test_vast_api.py +0 -0
  390. {freesolo_flash_dev-1.0.85 → freesolo_flash_dev-1.0.87}/tests/test_vast_api_coverage.py +0 -0
  391. {freesolo_flash_dev-1.0.85 → freesolo_flash_dev-1.0.87}/tests/test_vast_offers.py +0 -0
  392. {freesolo_flash_dev-1.0.85 → freesolo_flash_dev-1.0.87}/tests/test_vast_provider_coverage.py +0 -0
  393. {freesolo_flash_dev-1.0.85 → freesolo_flash_dev-1.0.87}/tests/test_vast_runner.py +0 -0
  394. {freesolo_flash_dev-1.0.85 → freesolo_flash_dev-1.0.87}/tests/test_verified_revisions.py +0 -0
  395. {freesolo_flash_dev-1.0.85 → freesolo_flash_dev-1.0.87}/tests/test_verifiers.py +0 -0
  396. {freesolo_flash_dev-1.0.85 → freesolo_flash_dev-1.0.87}/tests/test_version.py +0 -0
  397. {freesolo_flash_dev-1.0.85 → freesolo_flash_dev-1.0.87}/tests/test_vl_warmstart_adapter_keys.py +0 -0
  398. {freesolo_flash_dev-1.0.85 → freesolo_flash_dev-1.0.87}/tests/test_vram_architecture.py +0 -0
  399. {freesolo_flash_dev-1.0.85 → freesolo_flash_dev-1.0.87}/tests/test_wandb_link.py +0 -0
  400. {freesolo_flash_dev-1.0.85 → freesolo_flash_dev-1.0.87}/tests/test_wandb_log_coverage.py +0 -0
  401. {freesolo_flash_dev-1.0.85 → freesolo_flash_dev-1.0.87}/tests/test_wandb_naming.py +0 -0
  402. {freesolo_flash_dev-1.0.85 → freesolo_flash_dev-1.0.87}/tests/test_warmstart_adapter_download.py +0 -0
  403. {freesolo_flash_dev-1.0.85 → freesolo_flash_dev-1.0.87}/tests/test_warmstart_cross_repo.py +0 -0
  404. {freesolo_flash_dev-1.0.85 → freesolo_flash_dev-1.0.87}/tests/test_warmstart_error_attribution.py +0 -0
  405. {freesolo_flash_dev-1.0.85 → freesolo_flash_dev-1.0.87}/tests/test_weight_cache.py +0 -0
  406. {freesolo_flash_dev-1.0.85 → freesolo_flash_dev-1.0.87}/tests/test_worker_dryrun.py +0 -0
  407. {freesolo_flash_dev-1.0.85 → freesolo_flash_dev-1.0.87}/tests/test_worker_hardexit.py +0 -0
  408. {freesolo_flash_dev-1.0.85 → freesolo_flash_dev-1.0.87}/tests/test_worker_image.py +0 -0
  409. {freesolo_flash_dev-1.0.85 → freesolo_flash_dev-1.0.87}/tests/test_worker_init_heartbeat.py +0 -0
  410. {freesolo_flash_dev-1.0.85 → freesolo_flash_dev-1.0.87}/tests/test_worker_thinking.py +0 -0
@@ -66,6 +66,34 @@ FREESOLO_INTERNAL_KEY=
66
66
  # accepted unverified. Single tenant - see SELF_HOSTING.md before enabling.
67
67
  # FLASH_STANDALONE=1
68
68
 
69
+ # --- optional: deployment topology ---
70
+ # Where Flash keeps its local state: the saved login, the SQLite database, run records, and
71
+ # results. Defaults to ~/.flash (= /root/.flash for the container's default user, which is the
72
+ # path the Dockerfile declares as a VOLUME). Set this for a rootless container, a Kubernetes
73
+ # PVC, a read-only home directory, or a systemd unit with ProtectHome. Everything moves
74
+ # together, so point it at ONE durable location and mount a volume there.
75
+ # FLASH_DATA_DIR=/var/lib/flash
76
+ # Log verbosity for `flash-server`: DEBUG, INFO, WARNING, ERROR, CRITICAL. The server defaults
77
+ # to INFO -- provider resolution, capability revocation, reaper startup, and degraded-config
78
+ # warnings are all reported at INFO/WARNING. An unrecognized value falls back to the default
79
+ # rather than blocking startup.
80
+ # FLASH_LOG_LEVEL=INFO
81
+ # `text` (default) or `json`. JSON emits one object per line for a structured log sink. The
82
+ # same information is logged either way; only the punctuation differs.
83
+ # FLASH_LOG_FORMAT=text
84
+ # Bind address for `flash-server`. Defaults to 127.0.0.1; the container image passes 0.0.0.0
85
+ # explicitly. The --host and --port flags win over both of these.
86
+ # FLASH_SERVER_HOST=127.0.0.1
87
+ # Port for `flash-server`, default 8080. Must be 1-65535: an unusable value stops startup
88
+ # rather than silently binding the default, since a plane listening on the wrong port looks
89
+ # healthy and is unreachable.
90
+ # FLASH_SERVER_PORT=8080
91
+ # How long (seconds) to wait for a SQLite lock held by another writer, default 30. Raise it on
92
+ # networked storage, where a lock can be held far longer than on a local volume. This changes
93
+ # only patience: journal mode, synchronous, and foreign keys are correctness settings and are
94
+ # deliberately not configurable.
95
+ # FLASH_SQLITE_BUSY_TIMEOUT_SECONDS=30
96
+
69
97
  # --- optional ---
70
98
  # Server token for the environment repository. Without it, environments hosted in a
71
99
  # private GitHub repo cannot be fetched; environments in public GitHub repos still work,
@@ -94,3 +122,9 @@ FLASH_CONTROL_PANEL_URL=https://flash.example.com
94
122
  # URL here does not get you past the guard, it just produces the same error. Set it to
95
123
  # YOUR serving deployment; the managed plane gets the hosted URL from the code default.
96
124
  # FREESOLO_SERVING_URL=https://serving.example.internal
125
+ # Worker container image. Defaults to the published ghcr.io/freesolo-co/flash-worker tags
126
+ # (per-GPU-arch kernel-cache variants, falling back to the base :cu128). Point it at your
127
+ # own build to run a private worker; the CUDA driver floor still comes from the GPU class.
128
+ # FLASH_WORKER_IMAGE=ghcr.io/your-org/flash-worker:cu128
129
+ # Provider-side registry-credential id, required only when the image above is private.
130
+ # FLASH_WORKER_IMAGE_REGISTRY_AUTH=
@@ -5,9 +5,14 @@
5
5
  # -e RUNPOD_API_KEY=... -e HF_TOKEN=... \
6
6
  # -v flash-state:/root/.flash flash-control-plane
7
7
  #
8
- # All persistent state (key DB, run records, results) lives under ~/.flash (fixed paths,
9
- # = /root/.flash for the default root user) — mount a volume there. Run exactly ONE
10
- # container instance per state volume (state is local files + SQLite; no horizontal scaling).
8
+ # All persistent state (key DB, run records, results) lives under ~/.flash (= /root/.flash for
9
+ # the default root user) — mount a volume there. Run exactly ONE container instance per state
10
+ # volume (state is local files + SQLite; no horizontal scaling).
11
+ #
12
+ # FLASH_DATA_DIR moves that root. The VOLUME below names the DEFAULT path, and Docker cannot
13
+ # declare a volume at a path chosen at runtime, so a container that sets FLASH_DATA_DIR must
14
+ # also mount its own volume at the new location — otherwise state lands on the container's
15
+ # writable layer and disappears when the container is replaced.
11
16
 
12
17
  FROM python:3.12-slim
13
18
 
@@ -15,10 +20,7 @@ WORKDIR /app
15
20
  COPY . .
16
21
  RUN apt-get update \
17
22
  && apt-get install -y --no-install-recommends ca-certificates git curl \
18
- && curl -1sLf 'https://artifacts-cli.infisical.com/setup.deb.sh' | bash \
19
- && apt-get update && apt-get install -y --no-install-recommends infisical \
20
- && rm -rf /var/lib/apt/lists/* \
21
- && chmod +x /app/infisical-entrypoint.sh
23
+ && rm -rf /var/lib/apt/lists/*
22
24
  RUN pip install --no-cache-dir ".[server]"
23
25
 
24
26
  VOLUME /root/.flash
@@ -31,7 +33,8 @@ EXPOSE 8080
31
33
  # bake-kernel-cache.yml so the -smXX tags don't ship stale deps (the worker-image build posts a
32
34
  # reminder).
33
35
 
34
- # secret injection wrapper: no-op passthrough unless INFISICAL_CLIENT_ID is set, else
35
- # `infisical login` (universal-auth) then `infisical run --path /flash` before the server.
36
- ENTRYPOINT ["/app/infisical-entrypoint.sh"]
36
+ # Secrets come from the container environment (-e, --env-file, or your orchestrator's secret
37
+ # store), so this image needs no secret-manager tooling baked in. Pulling secrets from a manager
38
+ # at container start is an opt-in overlay that wraps this image's entrypoint and inherits the CMD
39
+ # below -- see deploy/infisical/ for a working example.
37
40
  CMD ["python", "-m", "flash.server", "--host", "0.0.0.0", "--port", "8080"]
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: freesolo-flash-dev
3
- Version: 1.0.85
3
+ Version: 1.0.87
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
@@ -70,6 +70,39 @@ max_examples = 1000
70
70
  file, load it: `set -a && . ./.env && set +a && flash-server`, or
71
71
  `docker run --env-file .env ...`. Copy `.env.example` to start from a documented template.
72
72
 
73
+ The process environment is the only contract, so a Kubernetes Secret, systemd
74
+ `EnvironmentFile`, or any orchestrator's secret store works as-is. To pull secrets from a
75
+ secret manager at container start instead, wrap the image's entrypoint; `deploy/infisical/`
76
+ is a working example you can copy for another provider.
77
+
78
+ ### The state directory
79
+
80
+ Everything the plane persists locally - the SQLite database of keys and run ownership, run
81
+ records, results, and the CLI's saved login - lives under one root, `~/.flash` by default
82
+ (`/root/.flash` in the container). Set `FLASH_DATA_DIR` to move it somewhere a rootless
83
+ container, a mounted PVC, or a `ProtectHome` systemd unit can actually write:
84
+
85
+ ```bash
86
+ FLASH_DATA_DIR=/var/lib/flash
87
+ ```
88
+
89
+ Everything moves together, so back up or mount that one directory. In Docker, setting
90
+ `FLASH_DATA_DIR` also means mounting your own volume at the new path - the image's `VOLUME`
91
+ declaration names the default location, and state written anywhere else lands on the
92
+ container's writable layer and is lost when the container is replaced.
93
+
94
+ Run exactly **one** instance per state directory. State is local files plus SQLite; there is
95
+ no horizontal scaling. On networked storage, where a lock can be held far longer than on a
96
+ local disk, raise `FLASH_SQLITE_BUSY_TIMEOUT_SECONDS` (default 30).
97
+
98
+ ### Logs
99
+
100
+ `flash-server` logs at INFO. Provider resolution, capability revocation, reaper startup, and
101
+ degraded-configuration warnings are reported there and nowhere else, so that is the first
102
+ place to look when the plane misbehaves. `FLASH_LOG_LEVEL` turns it up (`DEBUG`) or down
103
+ (`WARNING`), and `FLASH_LOG_FORMAT=json` emits one JSON object per line for a structured log
104
+ sink.
105
+
73
106
  ## Environments
74
107
 
75
108
  An environment is the Python package defining your task - dataset, rollout, reward. Point
@@ -0,0 +1,46 @@
1
+ # OPT-IN Infisical overlay for the Flash control plane.
2
+ #
3
+ # Flash itself needs nothing from Infisical: it reads secrets from its process environment,
4
+ # so the base image already works with `docker run --env-file`, a kubernetes Secret, or any
5
+ # orchestrator's secret store. This overlay is for deployments that pull secrets from
6
+ # Infisical at container start instead. See README.md in this directory.
7
+ #
8
+ # Build it against a published tag:
9
+ #
10
+ # docker build -f deploy/infisical/Dockerfile \
11
+ # --build-arg FLASH_IMAGE=ghcr.io/freesolo-co/freesolo-flash:main \
12
+ # -t flash-control-plane-infisical .
13
+ #
14
+ # ...or against an image you just built yourself:
15
+ #
16
+ # docker build -t flash-control-plane .
17
+ # docker build -f deploy/infisical/Dockerfile \
18
+ # --build-arg FLASH_IMAGE=flash-control-plane -t flash-control-plane-infisical .
19
+ #
20
+ # The build context is the repository root (that is where entrypoint.sh is copied from).
21
+
22
+ ARG FLASH_IMAGE=ghcr.io/freesolo-co/freesolo-flash:main
23
+ FROM ${FLASH_IMAGE}
24
+
25
+ # The Infisical CLI comes from the vendor's apt repo, and is deliberately NOT installed by the
26
+ # base image: the published artifact ships no vendor secret tooling and no vendor apt source.
27
+ # (The base image's `COPY . .` does carry this directory's inert shell script, but nothing in
28
+ # the base image ever executes it.)
29
+ RUN apt-get update \
30
+ && apt-get install -y --no-install-recommends ca-certificates curl \
31
+ && curl -1sLf 'https://artifacts-cli.infisical.com/setup.deb.sh' | bash \
32
+ && apt-get update && apt-get install -y --no-install-recommends infisical \
33
+ && rm -rf /var/lib/apt/lists/*
34
+
35
+ COPY deploy/infisical/entrypoint.sh /usr/local/bin/flash-infisical-entrypoint
36
+ RUN chmod +x /usr/local/bin/flash-infisical-entrypoint
37
+
38
+ # No-op passthrough unless INFISICAL_CLIENT_ID is set, otherwise `infisical login`
39
+ # (universal-auth) then `infisical run` before the server.
40
+ ENTRYPOINT ["/usr/local/bin/flash-infisical-entrypoint"]
41
+
42
+ # CMD must be restated, and must stay in step with the base Dockerfile's CMD. Setting
43
+ # ENTRYPOINT in a DERIVED image resets the inherited CMD to null, so without this line the
44
+ # wrapper is handed no command at all and the container never starts the server. Do not
45
+ # "deduplicate" this by deleting it.
46
+ CMD ["python", "-m", "flash.server", "--host", "0.0.0.0", "--port", "8080"]
@@ -0,0 +1,73 @@
1
+ # Infisical secret injection (opt-in)
2
+
3
+ Flash reads its secrets from the **process environment**. That is the whole contract, and it is
4
+ all a deployment needs:
5
+
6
+ ```bash
7
+ docker run -p 8080:8080 --env-file .env -v flash-state:/root/.flash \
8
+ ghcr.io/freesolo-co/freesolo-flash:main
9
+ ```
10
+
11
+ Kubernetes Secrets, systemd `EnvironmentFile`, Docker secrets mounted into env, and every
12
+ orchestrator secret store already produce that environment. **If that covers you, ignore this
13
+ directory** — the published image has no Infisical CLI in it and does not need one.
14
+
15
+ This overlay is for deployments that instead fetch secrets from [Infisical](https://infisical.com)
16
+ at container start.
17
+
18
+ ## Using it
19
+
20
+ Build the overlay on top of a Flash image:
21
+
22
+ ```bash
23
+ docker build -f deploy/infisical/Dockerfile \
24
+ --build-arg FLASH_IMAGE=ghcr.io/freesolo-co/freesolo-flash:main \
25
+ -t flash-control-plane-infisical .
26
+ ```
27
+
28
+ Run it with a universal-auth machine identity:
29
+
30
+ ```bash
31
+ docker run -p 8080:8080 -v flash-state:/root/.flash \
32
+ -e INFISICAL_CLIENT_ID=... \
33
+ -e INFISICAL_CLIENT_SECRET=... \
34
+ -e INFISICAL_PROJECT_ID=... \
35
+ -e INFISICAL_PATH=/flash \
36
+ flash-control-plane-infisical
37
+ ```
38
+
39
+ The wrapper logs in, then execs `infisical run -- <the base image's CMD>`, so the server sees the
40
+ injected secrets as ordinary environment variables. It changes nothing about how Flash itself
41
+ resolves configuration.
42
+
43
+ You can also skip the overlay build and mount the script into the base image, provided the
44
+ `infisical` binary is available inside the container.
45
+
46
+ ## Configuration
47
+
48
+ | Variable | Required | Default | Purpose |
49
+ | ------------------------- | -------- | ------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
50
+ | `INFISICAL_CLIENT_ID` | yes | unset | Universal-auth machine identity. **Unset makes the wrapper a no-op passthrough**, so the container behaves exactly like the base image. |
51
+ | `INFISICAL_CLIENT_SECRET` | yes | unset | Machine identity secret. |
52
+ | `INFISICAL_PROJECT_ID` | yes | unset | Infisical project (workspace) id. |
53
+ | `INFISICAL_PATH` | yes | unset | Secret folder path for this service, e.g. `/flash`. |
54
+ | `INFISICAL_ENV` | no | `prod` | Environment slug. **A dev deployment that omits this loads production secrets.** |
55
+ | `INFISICAL_KEEP` | no | empty | Space-separated variable _names_ whose existing container values must win over the injected ones. `infisical run` overrides existing env, so these are re-applied after injection. Use it for values that are a property of where the container runs, like a `FREESOLO_BASE_URL` pointing at a service on the same Docker network. |
56
+
57
+ `INFISICAL_TOKEN` is minted by the wrapper at startup. Do not set it yourself.
58
+
59
+ A name listed in `INFISICAL_KEEP` that the container has **not** set is skipped, so the vault's
60
+ value survives — a typo there costs you an override, not a credential. Setting a name to an empty
61
+ string is treated as a deliberate choice and still wins over the vault. Entries must be shell
62
+ identifiers; anything else aborts startup rather than being evaluated.
63
+
64
+ ## Failure behaviour
65
+
66
+ The wrapper runs under `set -eu`: a failed login or a missing `INFISICAL_PROJECT_ID` /
67
+ `INFISICAL_PATH` aborts container start rather than silently booting a control plane with no
68
+ credentials. Flash's own startup preflight would reject that state anyway, but failing at the
69
+ wrapper keeps the cause in the first line of the container log.
70
+
71
+ Only `INFISICAL_CLIENT_ID` is checked for presence, because it is the switch. With it set and the
72
+ rest missing, you get a hard failure — which is the intended outcome, not a fallback to unset
73
+ secrets.
@@ -0,0 +1,76 @@
1
+ #!/bin/sh
2
+ # OPT-IN: wraps the flash control-plane command with infisical secret injection.
3
+ #
4
+ # The published image does NOT use this. Flash reads secrets from its process environment,
5
+ # so `docker run -e ... / --env-file`, a kubernetes Secret, or any orchestrator's secret
6
+ # store works with no wrapper at all. This file exists for deployments that pull secrets
7
+ # from Infisical at container start; see deploy/infisical/README.md to opt in.
8
+ #
9
+ # fallback-safe: if INFISICAL_CLIENT_ID is unset this is a no-op passthrough and the
10
+ # container behaves exactly as it does without the wrapper (reading its env_file / docker
11
+ # env). Once the bootstrap machine-identity creds are present, secrets are pulled from
12
+ # infisical at startup.
13
+ #
14
+ # expected env:
15
+ # INFISICAL_CLIENT_ID / INFISICAL_CLIENT_SECRET universal-auth machine identity creds
16
+ # INFISICAL_PROJECT_ID the infisical project (workspace) id
17
+ # INFISICAL_ENV env slug (prod | dev); default prod
18
+ # INFISICAL_PATH folder path for this service (e.g. /flash)
19
+ # INFISICAL_KEEP space-separated var names that must WIN over
20
+ # infisical (docker-network overrides). infisical
21
+ # run overrides existing env, so we re-apply these
22
+ # AFTER injection via `env K=V`.
23
+ set -eu
24
+
25
+ # `exec "$@"` with ZERO arguments is a no-op that FALLS THROUGH to the injection path below,
26
+ # where `set -u` then blames INFISICAL_CLIENT_ID for what is really a missing command. Setting
27
+ # ENTRYPOINT in a derived image resets the inherited CMD to null, so an overlay that forgets to
28
+ # restate CMD lands here. Fail with the actual cause instead.
29
+ if [ "$#" -eq 0 ]; then
30
+ echo "flash infisical entrypoint: no command given (the image's CMD is empty)" >&2
31
+ exit 2
32
+ fi
33
+
34
+ if [ -z "${INFISICAL_CLIENT_ID:-}" ]; then
35
+ exec "$@"
36
+ fi
37
+
38
+ INFISICAL_TOKEN="$(infisical login --method=universal-auth \
39
+ --client-id="$INFISICAL_CLIENT_ID" \
40
+ --client-secret="$INFISICAL_CLIENT_SECRET" \
41
+ --silent --plain)"
42
+ export INFISICAL_TOKEN
43
+
44
+ # Re-apply the docker-network overrides AFTER infisical injection so they win. infisical
45
+ # run overrides existing env, so we hand each KEEP var to `env` as its own quoted `K=V`
46
+ # argument — values that contain spaces or shell metacharacters survive intact. (Building
47
+ # an unquoted string and word-splitting it would corrupt such values, and a leading space
48
+ # would make `env` choke.) INFISICAL_KEEP itself is a whitespace-separated list of variable
49
+ # NAMES, so splitting *it* is intentional.
50
+ # shellcheck disable=SC2086
51
+ for k in ${INFISICAL_KEEP:-}; do
52
+ # These names are expanded inside `eval` below, so refuse anything that is not a shell
53
+ # identifier instead of executing it.
54
+ case $k in
55
+ [!A-Za-z_]* | *[!A-Za-z0-9_]*)
56
+ echo "flash infisical entrypoint: INFISICAL_KEEP entry is not a variable name: $k" >&2
57
+ exit 2
58
+ ;;
59
+ esac
60
+ # Only re-apply names the container actually SET. An unset name expands to nothing, and
61
+ # handing `env` a bare `K=` would overwrite the injected secret with an empty string --
62
+ # so a typo'd or absent KEEP entry would silently WIPE a credential rather than leave the
63
+ # vault's value alone. `${K+set}` distinguishes unset from set-but-empty, so an explicitly
64
+ # empty container value still wins (that is a deliberate choice by whoever wrote it).
65
+ eval "keep_is_set=\${$k+set}"
66
+ [ "${keep_is_set:-}" = set ] || continue
67
+ set -- "$k=$(eval "printf '%s' \"\${$k}\"")" "$@"
68
+ done
69
+ unset keep_is_set
70
+
71
+ exec infisical run \
72
+ --projectId "$INFISICAL_PROJECT_ID" \
73
+ --env "${INFISICAL_ENV:-prod}" \
74
+ --path "$INFISICAL_PATH" \
75
+ --silent \
76
+ -- env "$@"
@@ -0,0 +1,100 @@
1
+ """Package logging helpers."""
2
+
3
+ from __future__ import annotations
4
+
5
+ import json
6
+ import logging
7
+ import os
8
+
9
+ _ROOT_NAME = "flash"
10
+
11
+ LOG_LEVEL_ENV = "FLASH_LOG_LEVEL"
12
+ LOG_FORMAT_ENV = "FLASH_LOG_FORMAT"
13
+
14
+ _TEXT_FORMAT = "%(levelname)s %(name)s: %(message)s"
15
+
16
+
17
+ class _JsonFormatter(logging.Formatter):
18
+ """One JSON object per line, for deployments that ship logs to a structured sink.
19
+
20
+ This formats the SAME record the text formatter would, through the same
21
+ ``record.getMessage()`` path. Nothing is added to the payload that the text line does not
22
+ already carry, so choosing a format cannot change what ends up in the log -- only how it is
23
+ punctuated. Anything a caller must not log stays un-logged in both formats.
24
+ """
25
+
26
+ def format(self, record: logging.LogRecord) -> str:
27
+ payload = {
28
+ "level": record.levelname,
29
+ "logger": record.name,
30
+ "message": record.getMessage(),
31
+ }
32
+ if record.exc_info:
33
+ payload["exception"] = self.formatException(record.exc_info)
34
+ return json.dumps(payload, default=str)
35
+
36
+
37
+ def _resolve_level(verbosity: int, level: int | None, default_level: int) -> int:
38
+ """Explicit level wins, then -v flags, then FLASH_LOG_LEVEL, then the caller's default.
39
+
40
+ A caller that passed an explicit level or counted -v flags has said what it wants for this
41
+ invocation, so the environment does not override it. ``default_level`` is the opposite: it
42
+ is what the entrypoint would have used anyway, so an operator's FLASH_LOG_LEVEL beats it.
43
+ That ordering is what makes the variable useful -- the server defaults to INFO and can still
44
+ be turned down to WARNING or up to DEBUG without a code change.
45
+ """
46
+ if level is not None:
47
+ return level
48
+ if verbosity:
49
+ return {1: logging.INFO}.get(verbosity, logging.DEBUG)
50
+ configured = os.environ.get(LOG_LEVEL_ENV, "").strip().upper()
51
+ if configured:
52
+ # getLevelName maps a known name to its int; an unknown name comes back as the string
53
+ # "Level FOO", which is not an int -- so a typo falls back rather than raising at startup.
54
+ # A log level is not worth refusing to boot over.
55
+ resolved = logging.getLevelName(configured)
56
+ if isinstance(resolved, int):
57
+ return resolved
58
+ return default_level
59
+
60
+
61
+ def _resolve_formatter() -> logging.Formatter:
62
+ if os.environ.get(LOG_FORMAT_ENV, "").strip().lower() == "json":
63
+ return _JsonFormatter()
64
+ return logging.Formatter(_TEXT_FORMAT)
65
+
66
+
67
+ # NullHandler: keep library import silent; app opts in via configure_logging.
68
+ _root = logging.getLogger(_ROOT_NAME)
69
+ if not any(isinstance(h, logging.NullHandler) for h in _root.handlers):
70
+ _root.addHandler(logging.NullHandler())
71
+
72
+
73
+ def get_logger(name: str | None = None) -> logging.Logger:
74
+ """Return a logger under the ``flash`` namespace (e.g. ``get_logger(__name__)``)."""
75
+ if not name or name == _ROOT_NAME:
76
+ return logging.getLogger(_ROOT_NAME)
77
+ if name.startswith(_ROOT_NAME + "."):
78
+ return logging.getLogger(name)
79
+ return logging.getLogger(f"{_ROOT_NAME}.{name}")
80
+
81
+
82
+ def configure_logging(
83
+ verbosity: int = 0, level: int | None = None, default_level: int = logging.WARNING
84
+ ) -> None:
85
+ """Attach a console handler to the ``flash`` logger and set its level.
86
+
87
+ ``FLASH_LOG_LEVEL`` sets the level when the caller has not asked for a specific one, and
88
+ ``FLASH_LOG_FORMAT=json`` switches the console handler to one JSON object per line.
89
+ """
90
+ level = _resolve_level(verbosity, level, default_level)
91
+
92
+ logger = logging.getLogger(_ROOT_NAME)
93
+ logger.setLevel(level)
94
+ for h in [h for h in logger.handlers if getattr(h, "_flash_console", False)]:
95
+ logger.removeHandler(h)
96
+ handler = logging.StreamHandler()
97
+ handler.setLevel(level)
98
+ handler.setFormatter(_resolve_formatter())
99
+ handler._flash_console = True # type: ignore[attr-defined]
100
+ logger.addHandler(handler)
@@ -0,0 +1,37 @@
1
+ """The one place Flash decides where its local state lives.
2
+
3
+ Everything Flash persists on the machine it runs on -- the CLI's saved login, the control
4
+ plane's SQLite database, run records and results, and the RunPod SDK's resource registry --
5
+ hangs off a single root. ``FLASH_DATA_DIR`` moves that root; unset, it is ``~/.flash``, which
6
+ is where every one of those things already lived.
7
+
8
+ Why this module exists at all: four call sites used to spell ``~/.flash`` out for themselves.
9
+ Nothing kept them in agreement, so a deployment could only relocate state by editing Python in
10
+ four places and state could silently split if it edited three. Resolution is centralized here
11
+ so there is exactly one answer to "where does Flash keep its files".
12
+
13
+ The root is resolved per call rather than captured at import, because a process that sets the
14
+ variable after importing flash (tests, embedders) would otherwise get the old answer.
15
+ """
16
+
17
+ from __future__ import annotations
18
+
19
+ import os
20
+ from pathlib import Path
21
+
22
+ DATA_DIR_ENV = "FLASH_DATA_DIR"
23
+ DEFAULT_DATA_DIR_NAME = ".flash"
24
+
25
+
26
+ def data_dir() -> Path:
27
+ """The root under which Flash keeps its local state.
28
+
29
+ A relative ``FLASH_DATA_DIR`` is resolved against the current working directory, which makes
30
+ the path a process-lifetime-stable answer only if the process does not chdir. Absolute paths
31
+ are what a deployment should set; ``expanduser`` keeps ``~/...`` working for a human typing
32
+ it into a shell.
33
+ """
34
+ configured = os.environ.get(DATA_DIR_ENV, "").strip()
35
+ if configured:
36
+ return Path(configured).expanduser()
37
+ return Path.home() / DEFAULT_DATA_DIR_NAME
@@ -850,7 +850,7 @@ with no reward to design. It supports `epochs` like SFT/GRPO and produces a LoRA
850
850
 
851
851
  - **Pick the teacher with `[train] teacher_model`; the key stays managed.** The teacher defaults to
852
852
  the managed **GLM 5.2** and is selectable from a fixed, managed allow-list:
853
- `glm-5.2` (default), `kimi-k3`, or `qwen3.5-397b-a17b`. Every option is
853
+ `glm-5.2` (default), `kimi-k3`, `qwen3.5-397b-a17b`, or `deepseek-v4-pro`. Every option is
854
854
  a Parasail-hosted model reached through the control-plane broker, so there is nothing to export or
855
855
  declare. An opd run submits like any other, and a `PARASAIL_API_KEY` in your shell is ignored.
856
856
  Arbitrary bring-your-own teacher models or keys are not supported (the allow-list is curated to
@@ -886,7 +886,8 @@ max_examples = 2
886
886
  lora_rank = 32
887
887
  # teacher_model = "glm-5.2" # managed teacher to distil from; one of
888
888
  # # glm-5.2 (default) | kimi-k3 |
889
- # # qwen3.5-397b-a17b (key stays managed)
889
+ # # qwen3.5-397b-a17b | deepseek-v4-pro
890
+ # # (key stays managed)
890
891
  # kl_penalty_coef = 1.0 # reverse-KL scale
891
892
  ```
892
893
 
@@ -13,7 +13,6 @@ from typing import NoReturn
13
13
  from flash import __version__
14
14
  from flash._channel import CLI_NAME
15
15
  from flash._logging import configure_logging
16
- from flash._update_check import emit_update_notice, maybe_start_update_check
17
16
  from flash.catalog import ALGORITHMS
18
17
  from flash.cli import render
19
18
 
@@ -766,7 +765,6 @@ def main(argv: list[str] | None = None) -> int:
766
765
  args = parser.parse_args(argv)
767
766
  configure_logging(verbosity=getattr(args, "verbose", 0))
768
767
  debug = getattr(args, "debug", False)
769
- update_check = maybe_start_update_check()
770
768
  _warn_if_login_shadowed(args)
771
769
  try:
772
770
  return args.func(args)
@@ -798,5 +796,3 @@ def main(argv: list[str] | None = None) -> int:
798
796
  print(render.error(str(exc) or exc.__class__.__name__), file=sys.stderr)
799
797
  print(render.arrow(f"run `{cmd}` for the full traceback"), file=sys.stderr)
800
798
  return 1
801
- finally:
802
- emit_update_notice(update_check)
@@ -667,7 +667,8 @@ def cmd_env_setup(args) -> int:
667
667
  f"{max_examples_line}"
668
668
  "lora_rank = 32\n"
669
669
  '# teacher_model = "glm-5.2" # teacher: glm-5.2 (default) | kimi-k3 |\n'
670
- "# # qwen3.5-397b-a17b (key stays managed)\n"
670
+ "# # qwen3.5-397b-a17b | deepseek-v4-pro\n"
671
+ "# # (key stays managed)\n"
671
672
  "# GPU and HF artifacts are managed automatically by the platform: the GPU is\n"
672
673
  "# the cheapest fitting managed class, and artifacts live in a private environment-scoped repo.\n"
673
674
  )
@@ -195,10 +195,7 @@ def _truecolor() -> bool:
195
195
 
196
196
 
197
197
  def _theme() -> str:
198
- """Active theme: ``light`` or ``dark``. ``FLASH_THEME`` overrides; else inferred from ``COLORFGBG``."""
199
- forced = os.environ.get("FLASH_THEME", "").strip().lower()
200
- if forced in {"light", "dark"}:
201
- return forced
198
+ """Active theme: ``light`` or ``dark``, inferred from ``COLORFGBG`` (the terminal's own signal)."""
202
199
  fgbg = os.environ.get("COLORFGBG", "")
203
200
  if fgbg:
204
201
  try:
@@ -1,6 +1,7 @@
1
1
  """Client-side credential storage: Flash API key + control-plane URL.
2
2
 
3
- Stored in ``~/.flash/config.json`` (0600). ``FREESOLO_API_KEY`` / ``FLASH_API_URL`` override.
3
+ Stored in ``config.json`` (0600) under the Flash data dir, ``~/.flash`` unless
4
+ ``FLASH_DATA_DIR`` says otherwise. ``FREESOLO_API_KEY`` / ``FLASH_API_URL`` override.
4
5
  """
5
6
 
6
7
  from __future__ import annotations
@@ -10,6 +11,7 @@ from pathlib import Path
10
11
 
11
12
  from .._channel import CHANNEL, CLI_NAME
12
13
  from .._fileio import read_json_or_empty, secure_json_write
14
+ from .._paths import data_dir
13
15
 
14
16
  PROD_API_URL = "https://flash.freesolo.co"
15
17
  DEV_API_URL = "https://flash-dev.freesolo.co"
@@ -22,7 +24,10 @@ def default_api_url(channel: str = CHANNEL) -> str:
22
24
 
23
25
  DEFAULT_API_URL = default_api_url()
24
26
 
25
- CONFIG_DIR = Path.home() / ".flash"
27
+ # Resolved at import so the CLI reports one stable path for the life of a command: these appear
28
+ # in user-facing messages ("the login saved in ..."), and a value that changed between the read
29
+ # and the message would name a file the user was not told about.
30
+ CONFIG_DIR = data_dir()
26
31
  CONFIG_PATH = CONFIG_DIR / "config.json"
27
32
 
28
33
 
@@ -59,6 +59,21 @@ TEACHER_MODELS: dict[str, TeacherModel] = {
59
59
  ),
60
60
  ),
61
61
  ),
62
+ "deepseek-v4-pro": TeacherModel(
63
+ alias="deepseek-v4-pro",
64
+ model_id="parasail-deepseek-v4-pro",
65
+ display_name="DeepSeek V4 Pro",
66
+ usd_per_1m=(1.74, 3.48),
67
+ tokenizer_repo="deepseek-ai/DeepSeek-V4-Pro",
68
+ tokenizer_revision="b5968e9190ef611bbf34a7229255be88a0e937c1",
69
+ tokenizer_kind="tokenizer_json",
70
+ tokenizer_files=(
71
+ (
72
+ "tokenizer.json",
73
+ "8f9f37ca37fdc4f5fd36d5cf4d3b0e8392edb4e894fd10cc0d70b4957c8633cf",
74
+ ),
75
+ ),
76
+ ),
62
77
  "qwen3.5-397b-a17b": TeacherModel(
63
78
  alias="qwen3.5-397b-a17b",
64
79
  model_id="parasail-qwen35-397b-a17b",
@@ -2,6 +2,7 @@
2
2
 
3
3
  from __future__ import annotations
4
4
 
5
+ import contextlib
5
6
  import copy
6
7
  import hashlib
7
8
  import http.client
@@ -1817,11 +1818,50 @@ def _opd_multimodal_parquet_features():
1817
1818
  )
1818
1819
 
1819
1820
 
1821
+ # arrow expands every shared python reference into its own copy, and the opd row list is one
1822
+ # reference per prompt repeated across the whole horizon, so converting the rows in a single table
1823
+ # costs peak host ram proportional to horizon * prompts_per_step * prompt_bytes. that is the parent
1824
+ # worker's ram, not the gpu's, and the allocator sizes vram only -- a host-ram kill surfaces as a
1825
+ # generic child exit with oom:false. writing in fixed batches holds the peak flat instead
1826
+ # (measured: 24k rows of ~8k-token prompts, 6143 MB in one table vs 189 MB batched).
1827
+ _OPD_PARQUET_WRITE_BATCH_ROWS = 2000
1828
+
1829
+
1820
1830
  def _write_opd_parquet(rows: list[dict], path: str) -> None:
1821
- from datasets import Dataset
1831
+ import pyarrow as pa
1832
+ import pyarrow.parquet as pq
1822
1833
 
1834
+ if not rows:
1835
+ raise ValueError("refusing to write an empty OPD parquet")
1823
1836
  features = _opd_multimodal_parquet_features() if any("images" in row for row in rows) else None
1824
- Dataset.from_list(rows, features=features).to_parquet(path)
1837
+ # pin one schema for every batch. multimodal takes it from the declared features exactly as the
1838
+ # single-table write did; text infers it from the first batch so a later batch cannot silently
1839
+ # infer a different type and be rejected mid-file.
1840
+ schema = (
1841
+ features.arrow_schema
1842
+ if features is not None
1843
+ else pa.Table.from_pylist(rows[:_OPD_PARQUET_WRITE_BATCH_ROWS]).schema
1844
+ )
1845
+ # write to a sibling temp file and rename only once every batch landed. closing a partially
1846
+ # written ParquetWriter still emits a valid footer, so failing in place would leave a READABLE
1847
+ # short file at `path` -- a truncated horizon that trains silently instead of raising.
1848
+ partial = f"{path}.partial"
1849
+ try:
1850
+ writer = pq.ParquetWriter(partial, schema)
1851
+ try:
1852
+ for start in range(0, len(rows), _OPD_PARQUET_WRITE_BATCH_ROWS):
1853
+ writer.write_table(
1854
+ pa.Table.from_pylist(
1855
+ rows[start : start + _OPD_PARQUET_WRITE_BATCH_ROWS], schema=schema
1856
+ )
1857
+ )
1858
+ finally:
1859
+ writer.close()
1860
+ os.replace(partial, path)
1861
+ except BaseException:
1862
+ with contextlib.suppress(OSError):
1863
+ os.remove(partial)
1864
+ raise
1825
1865
 
1826
1866
 
1827
1867
  # the verl bridge stores the empty-alignment skip under its own internal key,