freesolo-flash 0.2.26__tar.gz → 0.2.30__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 (340) hide show
  1. freesolo_flash-0.2.30/.github/workflows/auto-rebake.yml +245 -0
  2. {freesolo_flash-0.2.26 → freesolo_flash-0.2.30}/.github/workflows/bake-kernel-cache.yml +95 -17
  3. {freesolo_flash-0.2.26 → freesolo_flash-0.2.30}/.github/workflows/worker-image.yml +36 -14
  4. {freesolo_flash-0.2.26 → freesolo_flash-0.2.30}/Dockerfile.worker +20 -4
  5. {freesolo_flash-0.2.26 → freesolo_flash-0.2.30}/PKG-INFO +1 -1
  6. {freesolo_flash-0.2.26 → freesolo_flash-0.2.30}/docker/Dockerfile.kernelcache +10 -0
  7. freesolo_flash-0.2.30/docker/Dockerfile.kernelcache.relayer +27 -0
  8. freesolo_flash-0.2.30/docker/kernel_fingerprint.py +245 -0
  9. {freesolo_flash-0.2.26 → freesolo_flash-0.2.30}/docs/cli-style/generate.py +3 -16
  10. {freesolo_flash-0.2.26 → freesolo_flash-0.2.30}/docs/cli-style/index.html +79 -131
  11. freesolo_flash-0.2.30/docs/cli-style/themed-errors.png +0 -0
  12. freesolo_flash-0.2.30/docs/cli-theme/README.md +32 -0
  13. freesolo_flash-0.2.30/docs/cli-theme/before-after-dark.png +0 -0
  14. freesolo_flash-0.2.30/docs/cli-theme/before-after-light.png +0 -0
  15. freesolo_flash-0.2.30/docs/cli-theme/gallery-dark.png +0 -0
  16. freesolo_flash-0.2.30/docs/cli-theme/gallery-light.png +0 -0
  17. freesolo_flash-0.2.30/docs/cli-theme/help-dark.png +0 -0
  18. freesolo_flash-0.2.30/docs/cli-theme/help-light.png +0 -0
  19. freesolo_flash-0.2.30/flash/__init__.py +13 -0
  20. freesolo_flash-0.2.30/flash/_channel.py +11 -0
  21. {freesolo_flash-0.2.26 → freesolo_flash-0.2.30}/flash/_fileio.py +4 -9
  22. {freesolo_flash-0.2.26 → freesolo_flash-0.2.30}/flash/_logging.py +4 -16
  23. {freesolo_flash-0.2.26 → freesolo_flash-0.2.30}/flash/_update_check.py +14 -82
  24. freesolo_flash-0.2.30/flash/catalog.py +264 -0
  25. freesolo_flash-0.2.30/flash/cli/__init__.py +440 -0
  26. {freesolo_flash-0.2.26 → freesolo_flash-0.2.30}/flash/cli/commands.py +47 -79
  27. {freesolo_flash-0.2.26 → freesolo_flash-0.2.30}/flash/cli/envpush.py +151 -42
  28. {freesolo_flash-0.2.26 → freesolo_flash-0.2.30}/flash/cli/render.py +193 -77
  29. {freesolo_flash-0.2.26 → freesolo_flash-0.2.30}/flash/cli/training_doc.py +7 -17
  30. {freesolo_flash-0.2.26 → freesolo_flash-0.2.30}/flash/client/config.py +3 -11
  31. {freesolo_flash-0.2.26 → freesolo_flash-0.2.30}/flash/client/http.py +82 -133
  32. {freesolo_flash-0.2.26 → freesolo_flash-0.2.30}/flash/client/runtime_secrets.py +3 -19
  33. {freesolo_flash-0.2.26 → freesolo_flash-0.2.30}/flash/client/specs.py +1 -5
  34. {freesolo_flash-0.2.26 → freesolo_flash-0.2.30}/flash/cost/__init__.py +1 -2
  35. {freesolo_flash-0.2.26 → freesolo_flash-0.2.30}/flash/cost/analytical.py +8 -13
  36. {freesolo_flash-0.2.26 → freesolo_flash-0.2.30}/flash/cost/facts.py +9 -32
  37. {freesolo_flash-0.2.26 → freesolo_flash-0.2.30}/flash/cost/spec.py +5 -7
  38. {freesolo_flash-0.2.26 → freesolo_flash-0.2.30}/flash/cost/types.py +1 -13
  39. freesolo_flash-0.2.30/flash/engine/__init__.py +1 -0
  40. {freesolo_flash-0.2.26 → freesolo_flash-0.2.30}/flash/engine/accounting.py +4 -8
  41. freesolo_flash-0.2.30/flash/engine/chalk_kernels.py +65 -0
  42. freesolo_flash-0.2.30/flash/engine/multiturn_rollout.py +598 -0
  43. freesolo_flash-0.2.30/flash/engine/recipe.py +53 -0
  44. freesolo_flash-0.2.30/flash/engine/vram.py +571 -0
  45. freesolo_flash-0.2.30/flash/engine/worker/__init__.py +417 -0
  46. freesolo_flash-0.2.30/flash/engine/worker/_pkg.py +24 -0
  47. freesolo_flash-0.2.30/flash/engine/worker/adapter.py +255 -0
  48. freesolo_flash-0.2.30/flash/engine/worker/decoding.py +69 -0
  49. {freesolo_flash-0.2.26 → freesolo_flash-0.2.30}/flash/engine/worker/finalize.py +1 -12
  50. freesolo_flash-0.2.30/flash/engine/worker/gpu_setup.py +158 -0
  51. freesolo_flash-0.2.30/flash/engine/worker/grpo.py +225 -0
  52. freesolo_flash-0.2.30/flash/engine/worker/heartbeat.py +240 -0
  53. freesolo_flash-0.2.30/flash/engine/worker/hf.py +477 -0
  54. {freesolo_flash-0.2.26 → freesolo_flash-0.2.30}/flash/engine/worker/kernel_warmup.py +104 -66
  55. {freesolo_flash-0.2.26 → freesolo_flash-0.2.30}/flash/engine/worker/lora.py +208 -236
  56. freesolo_flash-0.2.30/flash/engine/worker/packing.py +313 -0
  57. freesolo_flash-0.2.30/flash/engine/worker/perf/__init__.py +363 -0
  58. freesolo_flash-0.2.30/flash/engine/worker/perf/attn.py +107 -0
  59. {freesolo_flash-0.2.26 → freesolo_flash-0.2.30}/flash/engine/worker/perf/diagnostics.py +6 -20
  60. freesolo_flash-0.2.30/flash/engine/worker/perf/lifecycle.py +240 -0
  61. freesolo_flash-0.2.30/flash/engine/worker/perf/liger.py +49 -0
  62. freesolo_flash-0.2.30/flash/engine/worker/perf/loraplus.py +18 -0
  63. freesolo_flash-0.2.30/flash/engine/worker/perf/memory.py +128 -0
  64. freesolo_flash-0.2.30/flash/engine/worker/rl.py +767 -0
  65. freesolo_flash-0.2.30/flash/engine/worker/sft.py +532 -0
  66. freesolo_flash-0.2.30/flash/engine/worker/wandb_log.py +110 -0
  67. {freesolo_flash-0.2.26 → freesolo_flash-0.2.30}/flash/envs/adapter.py +257 -212
  68. {freesolo_flash-0.2.26 → freesolo_flash-0.2.30}/flash/envs/base.py +2 -7
  69. freesolo_flash-0.2.30/flash/envs/pull.py +215 -0
  70. freesolo_flash-0.2.30/flash/envs/registry.py +26 -0
  71. freesolo_flash-0.2.30/flash/providers/__init__.py +37 -0
  72. freesolo_flash-0.2.30/flash/providers/_auth.py +10 -0
  73. freesolo_flash-0.2.30/flash/providers/_http.py +166 -0
  74. {freesolo_flash-0.2.26 → freesolo_flash-0.2.30}/flash/providers/_instance.py +24 -162
  75. freesolo_flash-0.2.30/flash/providers/_instance_bootstrap.py +384 -0
  76. freesolo_flash-0.2.30/flash/providers/_poll.py +309 -0
  77. freesolo_flash-0.2.30/flash/providers/allocator.py +112 -0
  78. freesolo_flash-0.2.30/flash/providers/base.py +341 -0
  79. {freesolo_flash-0.2.26 → freesolo_flash-0.2.30}/flash/providers/lambdalabs/__init__.py +5 -36
  80. {freesolo_flash-0.2.26 → freesolo_flash-0.2.30}/flash/providers/lambdalabs/api.py +12 -73
  81. freesolo_flash-0.2.30/flash/providers/lambdalabs/auth.py +15 -0
  82. {freesolo_flash-0.2.26 → freesolo_flash-0.2.30}/flash/providers/lambdalabs/gpus.py +1 -6
  83. freesolo_flash-0.2.30/flash/providers/lambdalabs/jobs/__init__.py +617 -0
  84. {freesolo_flash-0.2.26 → freesolo_flash-0.2.30}/flash/providers/lambdalabs/jobs/builders.py +7 -25
  85. freesolo_flash-0.2.30/flash/providers/lambdalabs/preflight.py +15 -0
  86. {freesolo_flash-0.2.26 → freesolo_flash-0.2.30}/flash/providers/lambdalabs/pricing.py +2 -9
  87. {freesolo_flash-0.2.26 → freesolo_flash-0.2.30}/flash/providers/lambdalabs/train.py +1 -8
  88. freesolo_flash-0.2.30/flash/providers/preflight.py +65 -0
  89. freesolo_flash-0.2.30/flash/providers/realized.py +56 -0
  90. {freesolo_flash-0.2.26 → freesolo_flash-0.2.30}/flash/providers/runpod/__init__.py +12 -32
  91. freesolo_flash-0.2.30/flash/providers/runpod/api.py +212 -0
  92. freesolo_flash-0.2.30/flash/providers/runpod/auth.py +23 -0
  93. {freesolo_flash-0.2.26 → freesolo_flash-0.2.30}/flash/providers/runpod/cost.py +1 -6
  94. {freesolo_flash-0.2.26 → freesolo_flash-0.2.30}/flash/providers/runpod/gpus.py +1 -9
  95. freesolo_flash-0.2.30/flash/providers/runpod/jobs.py +801 -0
  96. freesolo_flash-0.2.30/flash/providers/runpod/keys.py +97 -0
  97. {freesolo_flash-0.2.26 → freesolo_flash-0.2.30}/flash/providers/runpod/preflight.py +1 -7
  98. {freesolo_flash-0.2.26 → freesolo_flash-0.2.30}/flash/providers/runpod/preload.py +38 -266
  99. {freesolo_flash-0.2.26 → freesolo_flash-0.2.30}/flash/providers/runpod/slots.py +2 -11
  100. freesolo_flash-0.2.30/flash/providers/runpod/train/__init__.py +62 -0
  101. freesolo_flash-0.2.30/flash/providers/runpod/train/deps.py +239 -0
  102. freesolo_flash-0.2.30/flash/providers/runpod/train/endpoints.py +616 -0
  103. freesolo_flash-0.2.30/flash/runner/__init__.py +525 -0
  104. {freesolo_flash-0.2.26 → freesolo_flash-0.2.30}/flash/runner/checkpoints.py +6 -6
  105. freesolo_flash-0.2.30/flash/runner/deploy.py +220 -0
  106. freesolo_flash-0.2.30/flash/runner/lifecycle.py +591 -0
  107. {freesolo_flash-0.2.26 → freesolo_flash-0.2.30}/flash/schema/__init__.py +21 -81
  108. {freesolo_flash-0.2.26 → freesolo_flash-0.2.30}/flash/schema/fields.py +11 -126
  109. freesolo_flash-0.2.30/flash/serve/deploy.py +309 -0
  110. freesolo_flash-0.2.30/flash/serve/export.py +107 -0
  111. {freesolo_flash-0.2.26 → freesolo_flash-0.2.30}/flash/serve/pricing.py +2 -7
  112. {freesolo_flash-0.2.26 → freesolo_flash-0.2.30}/flash/server/_deps.py +12 -12
  113. freesolo_flash-0.2.30/flash/server/_internal_client.py +58 -0
  114. freesolo_flash-0.2.30/flash/server/_locks.py +55 -0
  115. {freesolo_flash-0.2.26 → freesolo_flash-0.2.30}/flash/server/_runtime.py +75 -9
  116. {freesolo_flash-0.2.26 → freesolo_flash-0.2.30}/flash/server/app.py +15 -5
  117. freesolo_flash-0.2.30/flash/server/auth.py +206 -0
  118. {freesolo_flash-0.2.26 → freesolo_flash-0.2.30}/flash/server/billing.py +11 -39
  119. {freesolo_flash-0.2.26 → freesolo_flash-0.2.30}/flash/server/billing_retry.py +10 -9
  120. {freesolo_flash-0.2.26 → freesolo_flash-0.2.30}/flash/server/checkpoints.py +26 -36
  121. {freesolo_flash-0.2.26 → freesolo_flash-0.2.30}/flash/server/db.py +5 -31
  122. freesolo_flash-0.2.30/flash/server/environment_registry.py +104 -0
  123. freesolo_flash-0.2.30/flash/server/envs.py +603 -0
  124. {freesolo_flash-0.2.26 → freesolo_flash-0.2.30}/flash/server/reconcile.py +3 -4
  125. freesolo_flash-0.2.30/flash/server/repo_cleanup.py +296 -0
  126. freesolo_flash-0.2.30/flash/server/routes/__init__.py +1 -0
  127. freesolo_flash-0.2.30/flash/server/routes/envs.py +67 -0
  128. {freesolo_flash-0.2.26 → freesolo_flash-0.2.30}/flash/server/routes/meta.py +2 -0
  129. {freesolo_flash-0.2.26 → freesolo_flash-0.2.30}/flash/server/routes/runs.py +6 -38
  130. freesolo_flash-0.2.30/flash/server/routes/serving.py +332 -0
  131. {freesolo_flash-0.2.26 → freesolo_flash-0.2.30}/flash/server/run_registry.py +9 -22
  132. freesolo_flash-0.2.30/flash/spec.py +246 -0
  133. {freesolo_flash-0.2.26 → freesolo_flash-0.2.30}/pyproject.toml +2 -2
  134. {freesolo_flash-0.2.26 → freesolo_flash-0.2.30}/tests/conftest.py +11 -0
  135. {freesolo_flash-0.2.26 → freesolo_flash-0.2.30}/tests/test_agent_flash_cli_contract.py +2 -10
  136. {freesolo_flash-0.2.26 → freesolo_flash-0.2.30}/tests/test_algorithms.py +1 -0
  137. {freesolo_flash-0.2.26 → freesolo_flash-0.2.30}/tests/test_allocator.py +34 -2
  138. freesolo_flash-0.2.30/tests/test_b200_rollout_opt.py +144 -0
  139. {freesolo_flash-0.2.26 → freesolo_flash-0.2.30}/tests/test_backend_jobspec_contract.py +0 -2
  140. {freesolo_flash-0.2.26 → freesolo_flash-0.2.30}/tests/test_billing_retry.py +13 -59
  141. {freesolo_flash-0.2.26 → freesolo_flash-0.2.30}/tests/test_cancel_remote.py +102 -25
  142. {freesolo_flash-0.2.26 → freesolo_flash-0.2.30}/tests/test_catalog_consistency.py +9 -0
  143. {freesolo_flash-0.2.26 → freesolo_flash-0.2.30}/tests/test_checkpoints.py +159 -18
  144. {freesolo_flash-0.2.26 → freesolo_flash-0.2.30}/tests/test_cli_errors.py +4 -4
  145. {freesolo_flash-0.2.26 → freesolo_flash-0.2.30}/tests/test_cli_estimate.py +2 -10
  146. freesolo_flash-0.2.30/tests/test_cli_help.py +125 -0
  147. {freesolo_flash-0.2.26 → freesolo_flash-0.2.30}/tests/test_cli_managed.py +1 -1
  148. freesolo_flash-0.2.30/tests/test_cli_render_theme.py +412 -0
  149. {freesolo_flash-0.2.26 → freesolo_flash-0.2.30}/tests/test_client.py +52 -2
  150. {freesolo_flash-0.2.26 → freesolo_flash-0.2.30}/tests/test_client_server_integration.py +3 -1
  151. {freesolo_flash-0.2.26 → freesolo_flash-0.2.30}/tests/test_config_overrides.py +5 -3
  152. {freesolo_flash-0.2.26 → freesolo_flash-0.2.30}/tests/test_cost_analytical.py +10 -16
  153. {freesolo_flash-0.2.26 → freesolo_flash-0.2.30}/tests/test_disk_gb.py +1 -0
  154. freesolo_flash-0.2.30/tests/test_env_delete.py +116 -0
  155. freesolo_flash-0.2.30/tests/test_env_no_install.py +59 -0
  156. freesolo_flash-0.2.30/tests/test_env_publish.py +926 -0
  157. freesolo_flash-0.2.30/tests/test_env_pull.py +625 -0
  158. {freesolo_flash-0.2.26 → freesolo_flash-0.2.30}/tests/test_env_push.py +29 -0
  159. {freesolo_flash-0.2.26 → freesolo_flash-0.2.30}/tests/test_env_rate_limit_resolve.py +1 -1
  160. {freesolo_flash-0.2.26 → freesolo_flash-0.2.30}/tests/test_flash_mvp.py +1 -4
  161. {freesolo_flash-0.2.26 → freesolo_flash-0.2.30}/tests/test_flash_worker.py +55 -11
  162. freesolo_flash-0.2.30/tests/test_flashinfer_cache_dirs.py +54 -0
  163. {freesolo_flash-0.2.26 → freesolo_flash-0.2.30}/tests/test_github_urlopen_retry.py +75 -0
  164. {freesolo_flash-0.2.26 → freesolo_flash-0.2.30}/tests/test_gpus.py +3 -3
  165. {freesolo_flash-0.2.26 → freesolo_flash-0.2.30}/tests/test_grpo_params.py +122 -23
  166. freesolo_flash-0.2.30/tests/test_grpo_sleep_gate.py +223 -0
  167. freesolo_flash-0.2.30/tests/test_internal_client.py +30 -0
  168. {freesolo_flash-0.2.26 → freesolo_flash-0.2.30}/tests/test_jobs.py +276 -87
  169. {freesolo_flash-0.2.26 → freesolo_flash-0.2.30}/tests/test_kernel_cache.py +8 -14
  170. freesolo_flash-0.2.30/tests/test_kernel_fingerprint.py +132 -0
  171. freesolo_flash-0.2.30/tests/test_kv_util.py +153 -0
  172. {freesolo_flash-0.2.26 → freesolo_flash-0.2.30}/tests/test_lambda_runner.py +93 -13
  173. {freesolo_flash-0.2.26 → freesolo_flash-0.2.30}/tests/test_login_perms.py +15 -0
  174. {freesolo_flash-0.2.26 → freesolo_flash-0.2.30}/tests/test_mig_guard.py +9 -68
  175. {freesolo_flash-0.2.26 → freesolo_flash-0.2.30}/tests/test_multiturn_rollout.py +50 -0
  176. freesolo_flash-0.2.30/tests/test_oom_escalate_gpu.py +121 -0
  177. {freesolo_flash-0.2.26 → freesolo_flash-0.2.30}/tests/test_orchestrator_flash.py +5 -5
  178. {freesolo_flash-0.2.26 → freesolo_flash-0.2.30}/tests/test_poll_helpers.py +4 -8
  179. {freesolo_flash-0.2.26 → freesolo_flash-0.2.30}/tests/test_provider_routing.py +83 -3
  180. {freesolo_flash-0.2.26 → freesolo_flash-0.2.30}/tests/test_provider_teardown_robustness.py +0 -18
  181. freesolo_flash-0.2.30/tests/test_repo_cleanup.py +513 -0
  182. {freesolo_flash-0.2.26 → freesolo_flash-0.2.30}/tests/test_resolve_params_b.py +8 -6
  183. {freesolo_flash-0.2.26 → freesolo_flash-0.2.30}/tests/test_resume_on_retry.py +24 -8
  184. {freesolo_flash-0.2.26 → freesolo_flash-0.2.30}/tests/test_runmgmt.py +69 -4
  185. {freesolo_flash-0.2.26 → freesolo_flash-0.2.30}/tests/test_runpod_key_waterfall.py +32 -0
  186. {freesolo_flash-0.2.26 → freesolo_flash-0.2.30}/tests/test_serve.py +87 -25
  187. {freesolo_flash-0.2.26 → freesolo_flash-0.2.30}/tests/test_server_api.py +357 -33
  188. {freesolo_flash-0.2.26 → freesolo_flash-0.2.30}/tests/test_server_billing.py +14 -4
  189. {freesolo_flash-0.2.26 → freesolo_flash-0.2.30}/tests/test_server_db.py +3 -1
  190. {freesolo_flash-0.2.26 → freesolo_flash-0.2.30}/tests/test_serving_contract.py +14 -6
  191. freesolo_flash-0.2.30/tests/test_sft_gc_off.py +158 -0
  192. {freesolo_flash-0.2.26 → freesolo_flash-0.2.30}/tests/test_spec_and_validation.py +57 -19
  193. {freesolo_flash-0.2.26 → freesolo_flash-0.2.30}/tests/test_thinking_config.py +3 -0
  194. {freesolo_flash-0.2.26 → freesolo_flash-0.2.30}/tests/test_verifiers.py +158 -31
  195. freesolo_flash-0.2.30/tests/test_vl_warmstart_adapter_keys.py +296 -0
  196. freesolo_flash-0.2.30/tests/test_vl_warmstart_recombine.py +393 -0
  197. {freesolo_flash-0.2.26 → freesolo_flash-0.2.30}/tests/test_wandb_naming.py +2 -3
  198. {freesolo_flash-0.2.26 → freesolo_flash-0.2.30}/tests/test_warmstart_cross_repo.py +4 -4
  199. {freesolo_flash-0.2.26 → freesolo_flash-0.2.30}/tests/test_weight_cache.py +4 -4
  200. {freesolo_flash-0.2.26 → freesolo_flash-0.2.30}/tests/test_worker_hardexit.py +42 -0
  201. {freesolo_flash-0.2.26 → freesolo_flash-0.2.30}/tests/test_worker_stack.py +51 -16
  202. {freesolo_flash-0.2.26 → freesolo_flash-0.2.30}/uv.lock +1 -1
  203. freesolo_flash-0.2.26/flash/__init__.py +0 -29
  204. freesolo_flash-0.2.26/flash/_channel.py +0 -28
  205. freesolo_flash-0.2.26/flash/catalog.py +0 -324
  206. freesolo_flash-0.2.26/flash/cli/__init__.py +0 -261
  207. freesolo_flash-0.2.26/flash/engine/__init__.py +0 -6
  208. freesolo_flash-0.2.26/flash/engine/chalk_kernels.py +0 -111
  209. freesolo_flash-0.2.26/flash/engine/multiturn_rollout.py +0 -780
  210. freesolo_flash-0.2.26/flash/engine/recipe.py +0 -74
  211. freesolo_flash-0.2.26/flash/engine/vram.py +0 -636
  212. freesolo_flash-0.2.26/flash/engine/worker/__init__.py +0 -589
  213. freesolo_flash-0.2.26/flash/engine/worker/_pkg.py +0 -30
  214. freesolo_flash-0.2.26/flash/engine/worker/adapter.py +0 -222
  215. freesolo_flash-0.2.26/flash/engine/worker/decoding.py +0 -144
  216. freesolo_flash-0.2.26/flash/engine/worker/gpu_setup.py +0 -101
  217. freesolo_flash-0.2.26/flash/engine/worker/grpo.py +0 -297
  218. freesolo_flash-0.2.26/flash/engine/worker/heartbeat.py +0 -322
  219. freesolo_flash-0.2.26/flash/engine/worker/hf.py +0 -526
  220. freesolo_flash-0.2.26/flash/engine/worker/packing.py +0 -486
  221. freesolo_flash-0.2.26/flash/engine/worker/perf/__init__.py +0 -495
  222. freesolo_flash-0.2.26/flash/engine/worker/perf/attn.py +0 -176
  223. freesolo_flash-0.2.26/flash/engine/worker/perf/lifecycle.py +0 -274
  224. freesolo_flash-0.2.26/flash/engine/worker/perf/liger.py +0 -73
  225. freesolo_flash-0.2.26/flash/engine/worker/perf/loraplus.py +0 -40
  226. freesolo_flash-0.2.26/flash/engine/worker/perf/memory.py +0 -84
  227. freesolo_flash-0.2.26/flash/engine/worker/rl.py +0 -912
  228. freesolo_flash-0.2.26/flash/engine/worker/sft.py +0 -683
  229. freesolo_flash-0.2.26/flash/engine/worker/wandb_log.py +0 -145
  230. freesolo_flash-0.2.26/flash/envs/registry.py +0 -62
  231. freesolo_flash-0.2.26/flash/providers/__init__.py +0 -54
  232. freesolo_flash-0.2.26/flash/providers/_auth.py +0 -16
  233. freesolo_flash-0.2.26/flash/providers/_http.py +0 -230
  234. freesolo_flash-0.2.26/flash/providers/_instance_bootstrap.py +0 -515
  235. freesolo_flash-0.2.26/flash/providers/_poll.py +0 -444
  236. freesolo_flash-0.2.26/flash/providers/allocator.py +0 -165
  237. freesolo_flash-0.2.26/flash/providers/base.py +0 -442
  238. freesolo_flash-0.2.26/flash/providers/lambdalabs/auth.py +0 -18
  239. freesolo_flash-0.2.26/flash/providers/lambdalabs/jobs/__init__.py +0 -831
  240. freesolo_flash-0.2.26/flash/providers/lambdalabs/preflight.py +0 -27
  241. freesolo_flash-0.2.26/flash/providers/preflight.py +0 -92
  242. freesolo_flash-0.2.26/flash/providers/realized.py +0 -80
  243. freesolo_flash-0.2.26/flash/providers/runpod/api.py +0 -278
  244. freesolo_flash-0.2.26/flash/providers/runpod/auth.py +0 -37
  245. freesolo_flash-0.2.26/flash/providers/runpod/jobs.py +0 -1064
  246. freesolo_flash-0.2.26/flash/providers/runpod/keys.py +0 -145
  247. freesolo_flash-0.2.26/flash/providers/runpod/train/__init__.py +0 -101
  248. freesolo_flash-0.2.26/flash/providers/runpod/train/deps.py +0 -461
  249. freesolo_flash-0.2.26/flash/providers/runpod/train/endpoints.py +0 -830
  250. freesolo_flash-0.2.26/flash/runner/__init__.py +0 -811
  251. freesolo_flash-0.2.26/flash/runner/deploy.py +0 -422
  252. freesolo_flash-0.2.26/flash/runner/lifecycle.py +0 -682
  253. freesolo_flash-0.2.26/flash/serve/deploy.py +0 -332
  254. freesolo_flash-0.2.26/flash/serve/export.py +0 -176
  255. freesolo_flash-0.2.26/flash/server/_locks.py +0 -54
  256. freesolo_flash-0.2.26/flash/server/auth.py +0 -263
  257. freesolo_flash-0.2.26/flash/server/environment_registry.py +0 -102
  258. freesolo_flash-0.2.26/flash/server/envs.py +0 -350
  259. freesolo_flash-0.2.26/flash/server/routes/__init__.py +0 -6
  260. freesolo_flash-0.2.26/flash/server/routes/envs.py +0 -48
  261. freesolo_flash-0.2.26/flash/server/routes/serving.py +0 -427
  262. freesolo_flash-0.2.26/flash/spec.py +0 -334
  263. freesolo_flash-0.2.26/tests/test_cli_render_theme.py +0 -159
  264. freesolo_flash-0.2.26/tests/test_env_install.py +0 -43
  265. freesolo_flash-0.2.26/tests/test_env_publish.py +0 -522
  266. freesolo_flash-0.2.26/tests/test_grpo_sleep_gate.py +0 -97
  267. freesolo_flash-0.2.26/tests/test_kv_util.py +0 -75
  268. freesolo_flash-0.2.26/tests/test_vl_warmstart_adapter_keys.py +0 -581
  269. {freesolo_flash-0.2.26 → freesolo_flash-0.2.30}/.dockerignore +0 -0
  270. {freesolo_flash-0.2.26 → freesolo_flash-0.2.30}/.env.example +0 -0
  271. {freesolo_flash-0.2.26 → freesolo_flash-0.2.30}/.github/workflows/ci.yml +0 -0
  272. {freesolo_flash-0.2.26 → freesolo_flash-0.2.30}/.github/workflows/main-source-guard.yml +0 -0
  273. {freesolo_flash-0.2.26 → freesolo_flash-0.2.30}/.github/workflows/publish-dev.yml +0 -0
  274. {freesolo_flash-0.2.26 → freesolo_flash-0.2.30}/.github/workflows/publish-image.yml +0 -0
  275. {freesolo_flash-0.2.26 → freesolo_flash-0.2.30}/.github/workflows/publish.yml +0 -0
  276. {freesolo_flash-0.2.26 → freesolo_flash-0.2.30}/.github/workflows/version-parity.yml +0 -0
  277. {freesolo_flash-0.2.26 → freesolo_flash-0.2.30}/.gitignore +0 -0
  278. {freesolo_flash-0.2.26 → freesolo_flash-0.2.30}/Dockerfile +0 -0
  279. {freesolo_flash-0.2.26 → freesolo_flash-0.2.30}/LICENSE +0 -0
  280. {freesolo_flash-0.2.26 → freesolo_flash-0.2.30}/README.md +0 -0
  281. {freesolo_flash-0.2.26 → freesolo_flash-0.2.30}/build/kernel_cache/.gitignore +0 -0
  282. {freesolo_flash-0.2.26 → freesolo_flash-0.2.30}/build/kernel_cache/.keep +0 -0
  283. {freesolo_flash-0.2.26 → freesolo_flash-0.2.30}/docker/bake_kernel_cache.py +0 -0
  284. {freesolo_flash-0.2.26 → freesolo_flash-0.2.30}/docker/bake_pod_entry.py +0 -0
  285. {freesolo_flash-0.2.26 → freesolo_flash-0.2.30}/docker/make_rp_handler.py +0 -0
  286. {freesolo_flash-0.2.26 → freesolo_flash-0.2.30}/docs/cli-style/README.md +0 -0
  287. {freesolo_flash-0.2.26 → freesolo_flash-0.2.30}/docs/cli-style/preview.png +0 -0
  288. {freesolo_flash-0.2.26 → freesolo_flash-0.2.30}/docs/kernel-cache.md +0 -0
  289. {freesolo_flash-0.2.26 → freesolo_flash-0.2.30}/flash/cli/__main__.py +0 -0
  290. {freesolo_flash-0.2.26 → freesolo_flash-0.2.30}/flash/client/__init__.py +0 -0
  291. {freesolo_flash-0.2.26 → freesolo_flash-0.2.30}/flash/engine/worker/__main__.py +0 -0
  292. {freesolo_flash-0.2.26 → freesolo_flash-0.2.30}/flash/envs/__init__.py +0 -0
  293. {freesolo_flash-0.2.26 → freesolo_flash-0.2.30}/flash/providers/runpod/pricing.py +0 -0
  294. {freesolo_flash-0.2.26 → freesolo_flash-0.2.30}/flash/py.typed +0 -0
  295. {freesolo_flash-0.2.26 → freesolo_flash-0.2.30}/flash/serve/__init__.py +0 -0
  296. {freesolo_flash-0.2.26 → freesolo_flash-0.2.30}/flash/server/__init__.py +0 -0
  297. {freesolo_flash-0.2.26 → freesolo_flash-0.2.30}/flash/server/__main__.py +0 -0
  298. {freesolo_flash-0.2.26 → freesolo_flash-0.2.30}/infisical-entrypoint.sh +0 -0
  299. {freesolo_flash-0.2.26 → freesolo_flash-0.2.30}/scripts/build_dev_dist.py +0 -0
  300. {freesolo_flash-0.2.26 → freesolo_flash-0.2.30}/tests/__init__.py +0 -0
  301. {freesolo_flash-0.2.26 → freesolo_flash-0.2.30}/tests/_helpers/__init__.py +0 -0
  302. {freesolo_flash-0.2.26 → freesolo_flash-0.2.30}/tests/_helpers/runner.py +0 -0
  303. {freesolo_flash-0.2.26 → freesolo_flash-0.2.30}/tests/_helpers/specs.py +0 -0
  304. {freesolo_flash-0.2.26 → freesolo_flash-0.2.30}/tests/fixtures/math_eval.jsonl +0 -0
  305. {freesolo_flash-0.2.26 → freesolo_flash-0.2.30}/tests/fixtures/math_train.jsonl +0 -0
  306. {freesolo_flash-0.2.26 → freesolo_flash-0.2.30}/tests/live/__init__.py +0 -0
  307. {freesolo_flash-0.2.26 → freesolo_flash-0.2.30}/tests/live/conftest.py +0 -0
  308. {freesolo_flash-0.2.26 → freesolo_flash-0.2.30}/tests/live/test_lambda_live.py +0 -0
  309. {freesolo_flash-0.2.26 → freesolo_flash-0.2.30}/tests/live/test_runpod_live.py +0 -0
  310. {freesolo_flash-0.2.26 → freesolo_flash-0.2.30}/tests/test_chalk_kernels.py +0 -0
  311. {freesolo_flash-0.2.26 → freesolo_flash-0.2.30}/tests/test_cli_commands.py +0 -0
  312. {freesolo_flash-0.2.26 → freesolo_flash-0.2.30}/tests/test_cost_equation.py +0 -0
  313. {freesolo_flash-0.2.26 → freesolo_flash-0.2.30}/tests/test_cost_estimate.py +0 -0
  314. {freesolo_flash-0.2.26 → freesolo_flash-0.2.30}/tests/test_cost_hardware.py +0 -0
  315. {freesolo_flash-0.2.26 → freesolo_flash-0.2.30}/tests/test_cost_models.py +0 -0
  316. {freesolo_flash-0.2.26 → freesolo_flash-0.2.30}/tests/test_cost_rewards.py +0 -0
  317. {freesolo_flash-0.2.26 → freesolo_flash-0.2.30}/tests/test_dev_channel.py +0 -0
  318. {freesolo_flash-0.2.26 → freesolo_flash-0.2.30}/tests/test_endpoint_name.py +0 -0
  319. {freesolo_flash-0.2.26 → freesolo_flash-0.2.30}/tests/test_envs_coverage.py +0 -0
  320. {freesolo_flash-0.2.26 → freesolo_flash-0.2.30}/tests/test_export.py +0 -0
  321. {freesolo_flash-0.2.26 → freesolo_flash-0.2.30}/tests/test_grpo_mask_aware.py +0 -0
  322. {freesolo_flash-0.2.26 → freesolo_flash-0.2.30}/tests/test_idle_endpoint_reaper.py +0 -0
  323. {freesolo_flash-0.2.26 → freesolo_flash-0.2.30}/tests/test_logging.py +0 -0
  324. {freesolo_flash-0.2.26 → freesolo_flash-0.2.30}/tests/test_managed_hf_repo.py +0 -0
  325. {freesolo_flash-0.2.26 → freesolo_flash-0.2.30}/tests/test_metrics_schema_agent_contract.py +0 -0
  326. {freesolo_flash-0.2.26 → freesolo_flash-0.2.30}/tests/test_open_model_policy.py +0 -0
  327. {freesolo_flash-0.2.26 → freesolo_flash-0.2.30}/tests/test_packing.py +0 -0
  328. {freesolo_flash-0.2.26 → freesolo_flash-0.2.30}/tests/test_preflight.py +0 -0
  329. {freesolo_flash-0.2.26 → freesolo_flash-0.2.30}/tests/test_providers_symmetry.py +0 -0
  330. {freesolo_flash-0.2.26 → freesolo_flash-0.2.30}/tests/test_realized_cost.py +0 -0
  331. {freesolo_flash-0.2.26 → freesolo_flash-0.2.30}/tests/test_runpod_api_delete.py +0 -0
  332. {freesolo_flash-0.2.26 → freesolo_flash-0.2.30}/tests/test_runpod_key_fingerprint.py +0 -0
  333. {freesolo_flash-0.2.26 → freesolo_flash-0.2.30}/tests/test_runpod_slots.py +0 -0
  334. {freesolo_flash-0.2.26 → freesolo_flash-0.2.30}/tests/test_update_check.py +0 -0
  335. {freesolo_flash-0.2.26 → freesolo_flash-0.2.30}/tests/test_version.py +0 -0
  336. {freesolo_flash-0.2.26 → freesolo_flash-0.2.30}/tests/test_vl_weight_sync.py +0 -0
  337. {freesolo_flash-0.2.26 → freesolo_flash-0.2.30}/tests/test_worker_dryrun.py +0 -0
  338. {freesolo_flash-0.2.26 → freesolo_flash-0.2.30}/tests/test_worker_image.py +0 -0
  339. {freesolo_flash-0.2.26 → freesolo_flash-0.2.30}/tests/test_worker_init_heartbeat.py +0 -0
  340. {freesolo_flash-0.2.26 → freesolo_flash-0.2.30}/tests/test_worker_thinking.py +0 -0
@@ -0,0 +1,245 @@
1
+ name: auto-rebake per-arch kernel cache
2
+
3
+ # Keeps the per-arch ghcr.io/freesolo-co/flash-worker:cu128-sm* images fresh whenever the :cu128 base
4
+ # is rebuilt. Each cu128-smXX is physically `FROM :cu128` + a baked mega-cache, so a new base leaves
5
+ # the per-arch tags pointing at the OLD base until rebaked. "Out of date" has two flavors, keyed off
6
+ # the fp_cache / fp_base labels worker-image.yml stamps on :cu128 (docker/kernel_fingerprint.py):
7
+ #
8
+ # * fp_cache changed -> the baked Triton/Inductor mega-cache is INVALID -> a real GPU re-warm is
9
+ # required (bake-kernel-cache.yml). PAID, and AUTO-fired by this detection (no manual approval) --
10
+ # fp_cache only moves on a deliberate toolchain bump, so spend stays tied to real need.
11
+ # * fp_cache same but fp_base changed -> the cache is still valid, the base just moved (FA wheel /
12
+ # causal-conv1d / rp_handler / a non-kernel dep) -> a FREE re-layer grafts the existing cache onto
13
+ # the fresh base (docker/Dockerfile.kernelcache.relayer), no GPU.
14
+ # * both same -> skip (this is the pure-flash-code case the old reminder over-fired on).
15
+ #
16
+ # The gate READS the published labels (authoritative for what was actually built, incl. a manual FA3
17
+ # override) rather than recomputing from the checkout, and aborts unless the base's revision label ==
18
+ # the build's head_sha (so a superseded base build or a `tag=...` dispatch that never touched :cu128
19
+ # can't trigger a stale rebake).
20
+
21
+ on:
22
+ workflow_run:
23
+ workflows: ["flash worker image"]
24
+ types: [completed]
25
+
26
+ permissions:
27
+ contents: read
28
+ packages: write
29
+ actions: read
30
+ issues: write
31
+
32
+ # Scope the group to the triggering base build's commit so a no-op completion (e.g. a tag=cu128-test
33
+ # worker-image run, whose head_sha differs) can't cancel an in-flight real bake. The revision guard
34
+ # already neutralizes superseded runs, so a global cancel-in-progress isn't needed.
35
+ concurrency:
36
+ group: auto-rebake-${{ github.event.workflow_run.head_sha }}
37
+ cancel-in-progress: true
38
+
39
+ env:
40
+ BASE: ghcr.io/freesolo-co/flash-worker:cu128
41
+
42
+ jobs:
43
+ gate:
44
+ if: github.event.workflow_run.conclusion == 'success'
45
+ runs-on: ubuntu-latest
46
+ outputs:
47
+ proceed: ${{ steps.base.outputs.proceed }}
48
+ relayer_sms: ${{ steps.classify.outputs.relayer_sms }}
49
+ gpu_sms: ${{ steps.classify.outputs.gpu_sms }}
50
+ fp_cache: ${{ steps.base.outputs.fp_cache }}
51
+ fp_base: ${{ steps.base.outputs.fp_base }}
52
+ base_ref: ${{ steps.base.outputs.base_ref }}
53
+ base_revision: ${{ steps.base.outputs.revision }}
54
+ steps:
55
+ - uses: actions/checkout@v6
56
+ with:
57
+ ref: ${{ github.event.workflow_run.head_sha }}
58
+
59
+ - name: Install crane
60
+ run: |
61
+ curl -sSL https://github.com/google/go-containerregistry/releases/download/v0.20.2/go-containerregistry_Linux_x86_64.tar.gz \
62
+ | sudo tar -xz -C /usr/local/bin crane
63
+ crane version
64
+
65
+ - name: Log in to GHCR
66
+ uses: docker/login-action@v3
67
+ with:
68
+ registry: ghcr.io
69
+ username: ${{ github.actor }}
70
+ password: ${{ secrets.GITHUB_TOKEN }}
71
+
72
+ - name: Read base labels
73
+ id: base
74
+ env:
75
+ HEAD_SHA: ${{ github.event.workflow_run.head_sha }}
76
+ run: |
77
+ # canonical digest ref (repo@sha256, no tag) so every tool (crane/docker/runpod) accepts it.
78
+ digest=$(crane digest "$BASE")
79
+ repo=${BASE%:*}
80
+ cfg=$(crane config "$repo@$digest")
81
+ fpc=$(echo "$cfg" | jq -r '.config.Labels["co.freesolo.flash.kernelcache.fp_cache"] // ""')
82
+ fpb=$(echo "$cfg" | jq -r '.config.Labels["co.freesolo.flash.kernelcache.fp_base"] // ""')
83
+ rev=$(echo "$cfg" | jq -r '.config.Labels["org.opencontainers.image.revision"] // ""')
84
+ echo "base_ref=$repo@$digest" >> "$GITHUB_OUTPUT"
85
+ echo "fp_cache=$fpc" >> "$GITHUB_OUTPUT"
86
+ echo "fp_base=$fpb" >> "$GITHUB_OUTPUT"
87
+ echo "revision=$rev" >> "$GITHUB_OUTPUT"
88
+ # Only proceed if this base IS the build that triggered us: its revision label must match the
89
+ # build's head_sha. Guards (a) a newer base that already superseded this run, and (b) a
90
+ # `tag=cu128-test` dispatch that never updated :cu128 (the workflow_run payload can't reveal
91
+ # the dispatch tag). An unlabeled base (pre-rollout) also no-ops here.
92
+ if [ -n "$fpc" ] && [ "$rev" = "$HEAD_SHA" ]; then
93
+ echo "proceed=true" >> "$GITHUB_OUTPUT"
94
+ echo "base $BASE@$digest is rev $rev (== head_sha) fp_cache=$fpc fp_base=$fpb"
95
+ else
96
+ echo "proceed=false" >> "$GITHUB_OUTPUT"
97
+ echo "::notice::auto-rebake no-op: base rev '$rev' != head_sha '$HEAD_SHA' (or base unlabeled)"
98
+ fi
99
+
100
+ - name: Classify arches
101
+ id: classify
102
+ if: steps.base.outputs.proceed == 'true'
103
+ env:
104
+ FP_CACHE: ${{ steps.base.outputs.fp_cache }}
105
+ FP_BASE: ${{ steps.base.outputs.fp_base }}
106
+ REV: ${{ steps.base.outputs.revision }}
107
+ run: |
108
+ # arch list is the single source of truth in deps.py (mirrored by the bake matrix; a test
109
+ # pins that mirror). textual parse -> no flash import / uv sync needed.
110
+ arches=$(python3 -c "import re,pathlib; t=pathlib.Path('flash/providers/runpod/train/deps.py').read_text(); m=re.search(r'BAKED_PER_SM_ARCHES\s*=\s*frozenset\(\{([^}]+)\}\)', t); print(' '.join(re.findall(r'sm\d+', m.group(1))))")
111
+ relayer=(); gpu=()
112
+ summary="| arch | published fp_cache | published fp_base | action |\n|---|---|---|---|\n"
113
+ for sm in $arches; do
114
+ img="ghcr.io/freesolo-co/flash-worker:cu128-$sm"
115
+ if cfg=$(crane config "$img" 2>/dev/null); then
116
+ pc=$(echo "$cfg" | jq -r '.config.Labels["co.freesolo.flash.kernelcache.fp_cache"] // ""')
117
+ pb=$(echo "$cfg" | jq -r '.config.Labels["co.freesolo.flash.kernelcache.fp_base"] // ""')
118
+ else
119
+ pc="(missing)"; pb="(missing)"
120
+ fi
121
+ if [ "$pc" != "$FP_CACHE" ]; then
122
+ gpu+=("$sm"); action="GPU re-warm (cache invalid)"
123
+ elif [ "$pb" != "$FP_BASE" ]; then
124
+ relayer+=("$sm"); action="re-layer (free)"
125
+ else
126
+ action="up to date"
127
+ fi
128
+ echo "$sm: pc=$pc pb=$pb -> $action"
129
+ summary="$summary| $sm | \`$pc\` | \`$pb\` | $action |\n"
130
+ done
131
+ if [ ${#relayer[@]} -gt 0 ]; then
132
+ relayer_json=$(printf '%s\n' "${relayer[@]}" | jq -R . | jq -cs .)
133
+ else
134
+ relayer_json='[]'
135
+ fi
136
+ gpu_csv=$(IFS=,; echo "${gpu[*]}")
137
+ echo "relayer_sms=$relayer_json" >> "$GITHUB_OUTPUT"
138
+ echo "gpu_sms=$gpu_csv" >> "$GITHUB_OUTPUT"
139
+ {
140
+ echo "### auto-rebake plan (base rev \`$REV\`, fp_cache \`$FP_CACHE\` fp_base \`$FP_BASE\`)"
141
+ echo ""
142
+ echo -e "$summary"
143
+ echo ""
144
+ echo "re-layer (free): \`$relayer_json\` | GPU re-warm (paid, auto-started): \`${gpu_csv:-none}\`"
145
+ } >> "$GITHUB_STEP_SUMMARY"
146
+
147
+ # FYI notification (not an action item -- the bake auto-runs). Keeps a heads-up + cost trail of
148
+ # which arches a paid GPU re-warm fired for.
149
+ - name: Notify GPU re-bake auto-started
150
+ if: steps.base.outputs.proceed == 'true' && steps.classify.outputs.gpu_sms != ''
151
+ env:
152
+ GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
153
+ GPU_SMS: ${{ steps.classify.outputs.gpu_sms }}
154
+ REV: ${{ steps.base.outputs.revision }}
155
+ RUN_URL: ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}
156
+ run: |
157
+ title="kernel-cache: per-arch GPU re-bake auto-started"
158
+ body=$(printf 'The kernel toolchain changed (fp_cache), so a PAID GPU re-warm auto-started for these per-arch images (no approval needed):\n\n- arches: `%s`\n- base rev: `%s`\n\nTrack it in the run: %s' "$GPU_SMS" "$REV" "$RUN_URL")
159
+ # best-effort: a labeling/permission hiccup must never fail the gate. self-heal the label so
160
+ # no manual setup is needed, then reuse one open issue (comment) instead of spamming new ones.
161
+ gh label create kernel-rebake-pending --color B60205 --description "per-arch kernel cache GPU re-bake auto-started" 2>/dev/null || true
162
+ existing=$(gh issue list --label kernel-rebake-pending --state open --json number -q '.[0].number' 2>/dev/null || true)
163
+ if [ -n "${existing:-}" ]; then
164
+ gh issue comment "$existing" --body "$body" || true
165
+ else
166
+ gh issue create --title "$title" --body "$body" --label kernel-rebake-pending \
167
+ || gh issue create --title "$title" --body "$body" || true
168
+ fi
169
+
170
+ # FREE path: graft the existing valid cache onto the fresh base, no GPU. Runs automatically.
171
+ relayer:
172
+ needs: gate
173
+ if: needs.gate.outputs.proceed == 'true' && needs.gate.outputs.relayer_sms != '[]' && needs.gate.outputs.relayer_sms != ''
174
+ runs-on: ubuntu-24.04-8core
175
+ strategy:
176
+ fail-fast: false
177
+ matrix:
178
+ sm: ${{ fromJson(needs.gate.outputs.relayer_sms || '[]') }}
179
+ env:
180
+ BASE_REF: ${{ needs.gate.outputs.base_ref }}
181
+ FP_CACHE: ${{ needs.gate.outputs.fp_cache }}
182
+ FP_BASE: ${{ needs.gate.outputs.fp_base }}
183
+ BASE_REVISION: ${{ needs.gate.outputs.base_revision }}
184
+ steps:
185
+ - uses: actions/checkout@v6
186
+ with:
187
+ ref: ${{ github.event.workflow_run.head_sha }}
188
+
189
+ # The graft pulls two ~20GB images (old per-arch tag + fresh base); reclaim runner disk first.
190
+ - name: Free disk space
191
+ run: |
192
+ sudo rm -rf /usr/share/dotnet /opt/ghc /usr/local/.ghcup \
193
+ /usr/local/lib/android /opt/hostedtoolcache /usr/share/swift \
194
+ /usr/local/share/boost /usr/local/lib/node_modules \
195
+ /usr/local/share/powershell /usr/share/miniconda || true
196
+ sudo apt-get clean || true
197
+ sudo docker image prune -af || true
198
+ df -h /
199
+
200
+ - uses: docker/setup-buildx-action@v3
201
+
202
+ - name: Log in to GHCR
203
+ uses: docker/login-action@v3
204
+ with:
205
+ registry: ghcr.io
206
+ username: ${{ github.actor }}
207
+ password: ${{ secrets.GITHUB_TOKEN }}
208
+
209
+ # Pin OLDCACHE by digest so a concurrent overwrite of the source tag can't graft a wrong cache.
210
+ - name: Resolve old per-arch cache digest
211
+ id: old
212
+ run: |
213
+ img="ghcr.io/freesolo-co/flash-worker:cu128-${{ matrix.sm }}"
214
+ digest=$(docker buildx imagetools inspect "$img" --format '{{.Manifest.Digest}}')
215
+ # canonical digest ref (repo@sha256, no tag) for the FROM in the relayer build.
216
+ echo "ref=${img%:*}@$digest" >> "$GITHUB_OUTPUT"
217
+
218
+ - name: Re-layer cache onto the fresh base (no GPU)
219
+ uses: docker/build-push-action@v6
220
+ with:
221
+ context: .
222
+ file: docker/Dockerfile.kernelcache.relayer
223
+ push: true
224
+ tags: ghcr.io/freesolo-co/flash-worker:cu128-${{ matrix.sm }}
225
+ provenance: false
226
+ build-args: |
227
+ BASE=${{ env.BASE_REF }}
228
+ OLDCACHE=${{ steps.old.outputs.ref }}
229
+ FP_CACHE=${{ env.FP_CACHE }}
230
+ FP_BASE=${{ env.FP_BASE }}
231
+ BASE_REVISION=${{ env.BASE_REVISION }}
232
+
233
+ # PAID path: re-warm the cache on a real GPU per arch. Runs automatically -- the fingerprint gate
234
+ # above is the only thing that decides it fires (only when fp_cache changed), so no manual approval.
235
+ gpu-warm:
236
+ needs: gate
237
+ if: needs.gate.outputs.proceed == 'true' && needs.gate.outputs.gpu_sms != ''
238
+ uses: ./.github/workflows/bake-kernel-cache.yml
239
+ with:
240
+ sms: ${{ needs.gate.outputs.gpu_sms }}
241
+ fp_cache: ${{ needs.gate.outputs.fp_cache }}
242
+ fp_base: ${{ needs.gate.outputs.fp_base }}
243
+ base_ref: ${{ needs.gate.outputs.base_ref }}
244
+ base_revision: ${{ needs.gate.outputs.base_revision }}
245
+ secrets: inherit
@@ -10,8 +10,12 @@ name: flash worker kernel-cache (per-arch)
10
10
  # Depends on the base ghcr.io/freesolo-co/flash-worker:cu128 image existing (worker-image.yml) — the
11
11
  # warmup runs INSIDE it so the cache matches the image's pinned torch/triton/fla/liger toolchain.
12
12
  #
13
- # Requires the RUNPOD_API_KEY repo secret (the warmup GPU pod) + the default GITHUB_TOKEN (GHCR push)
14
- # + HF_TOKEN (the temp dataset that ferries code + the cache artifact). Manual trigger; heavy + paid.
13
+ # Secrets: RUNPOD_API_KEY (the warmup GPU pod) + HF_TOKEN (the temp dataset that ferries code + the
14
+ # cache artifact) are native repo Actions secrets, synced from Infisical (prod:/flash-ci) by the
15
+ # github-ci-flash Secret Sync; the GHCR push uses the default GITHUB_TOKEN. Heavy + paid,
16
+ # but UNGATED: the fingerprint detection in auto-rebake.yml decides WHEN this runs (only on a real
17
+ # kernel-toolchain change), so there is no manual approval step. Invoked by hand (workflow_dispatch)
18
+ # OR automatically by auto-rebake.yml (workflow_call) when the kernel toolchain changed.
15
19
 
16
20
  on:
17
21
  workflow_dispatch:
@@ -20,12 +24,40 @@ on:
20
24
  description: "comma-separated sm list to bake; default is all validated arches"
21
25
  default: "sm80,sm86,sm89,sm90,sm120"
22
26
  required: false
27
+ # auto-rebake.yml calls this for the EXPENSIVE path (the cache is invalid and must be re-warmed on a
28
+ # real GPU). It passes the arch subset, the fingerprints to stamp, and a digest-pinned base so the
29
+ # warm runs inside the exact :cu128 the per-arch tag will sit on.
30
+ workflow_call:
31
+ inputs:
32
+ sms:
33
+ type: string
34
+ required: true
35
+ fp_cache:
36
+ type: string
37
+ required: false
38
+ default: ""
39
+ fp_base:
40
+ type: string
41
+ required: false
42
+ default: ""
43
+ base_ref:
44
+ type: string
45
+ required: false
46
+ default: "ghcr.io/freesolo-co/flash-worker:cu128"
47
+ base_revision:
48
+ type: string
49
+ required: false
50
+ default: ""
23
51
 
24
52
  permissions:
25
53
  contents: read
26
54
  packages: write
27
55
 
28
56
  jobs:
57
+ # Ungated: the PAID RunPod bake runs as soon as it's called/dispatched. The decision of WHEN to run
58
+ # lives in auto-rebake.yml's fingerprint gate (it only invokes this when fp_cache changed), so a
59
+ # second manual approval here would be redundant. Re-add an `approve` job with `environment: gpu-bake`
60
+ # (and `needs: approve`) if you ever want a human checkpoint back.
29
61
  bake:
30
62
  runs-on: ubuntu-24.04-8core
31
63
  strategy:
@@ -77,19 +109,63 @@ jobs:
77
109
  allowed_cuda: "13.0",
78
110
  }
79
111
  steps:
80
- - uses: actions/checkout@v6
81
-
82
- # skip arches not requested in the dispatch input
112
+ # Gate FIRST (no checkout needed) so skipped arches do no crane / checkout / build work.
83
113
  - name: Should bake ${{ matrix.sm }}?
84
114
  id: gate
85
115
  run: |
86
- req="${{ github.event.inputs.sms || 'sm80,sm86,sm89,sm90,sm120' }}"
116
+ req="${{ inputs.sms || 'sm80,sm86,sm89,sm90,sm120' }}"
87
117
  req="${req// /}" # tolerate spaces, e.g. "sm80, sm86"
88
118
  case ",$req," in
89
119
  *,${{ matrix.sm }},*) echo "run=true" >> "$GITHUB_OUTPUT" ;;
90
120
  *) echo "run=false" >> "$GITHUB_OUTPUT"; echo "skipping ${{ matrix.sm }}" ;;
91
121
  esac
92
122
 
123
+ - name: Install crane
124
+ if: steps.gate.outputs.run == 'true'
125
+ run: |
126
+ curl -sSL https://github.com/google/go-containerregistry/releases/download/v0.20.2/go-containerregistry_Linux_x86_64.tar.gz \
127
+ | sudo tar -xz -C /usr/local/bin crane
128
+ crane version
129
+
130
+ - name: Log in to GHCR
131
+ if: steps.gate.outputs.run == 'true'
132
+ uses: docker/login-action@v3
133
+ with:
134
+ registry: ghcr.io
135
+ username: ${{ github.actor }}
136
+ password: ${{ secrets.GITHUB_TOKEN }}
137
+
138
+ # Resolve the base + fingerprints BEFORE checkout, so the checkout (hence the warmed flash code)
139
+ # is pinned to the EXACT commit the base was built from. auto-rebake passes everything (fast path);
140
+ # a manual dispatch READS the labels off the published base, so the per-arch image always matches
141
+ # the base it extends (same source of truth as the gate) instead of recomputing from the checkout.
142
+ - name: Resolve base + fingerprints
143
+ id: base
144
+ if: steps.gate.outputs.run == 'true'
145
+ run: |
146
+ if [ -n "${{ inputs.fp_cache }}" ]; then
147
+ echo "ref=${{ inputs.base_ref }}" >> "$GITHUB_OUTPUT"
148
+ echo "fp_cache=${{ inputs.fp_cache }}" >> "$GITHUB_OUTPUT"
149
+ echo "fp_base=${{ inputs.fp_base }}" >> "$GITHUB_OUTPUT"
150
+ echo "revision=${{ inputs.base_revision }}" >> "$GITHUB_OUTPUT"
151
+ else
152
+ base="${{ inputs.base_ref || 'ghcr.io/freesolo-co/flash-worker:cu128' }}"
153
+ digest=$(crane digest "$base"); repo=${base%:*}
154
+ cfg=$(crane config "$repo@$digest")
155
+ echo "ref=$repo@$digest" >> "$GITHUB_OUTPUT"
156
+ echo "fp_cache=$(echo "$cfg" | jq -r '.config.Labels["co.freesolo.flash.kernelcache.fp_cache"] // ""')" >> "$GITHUB_OUTPUT"
157
+ echo "fp_base=$(echo "$cfg" | jq -r '.config.Labels["co.freesolo.flash.kernelcache.fp_base"] // ""')" >> "$GITHUB_OUTPUT"
158
+ echo "revision=$(echo "$cfg" | jq -r '.config.Labels["org.opencontainers.image.revision"] // ""')" >> "$GITHUB_OUTPUT"
159
+ fi
160
+
161
+ # Pin the checkout to the base's source commit so the warmed flash code matches the base exactly
162
+ # (the cache is content-keyed by the code that compiled it). Falls back to the event sha if the
163
+ # base predates the revision label.
164
+ - uses: actions/checkout@v6
165
+ if: steps.gate.outputs.run == 'true'
166
+ with:
167
+ ref: ${{ steps.base.outputs.revision || github.sha }}
168
+
93
169
  - name: Install uv
94
170
  if: steps.gate.outputs.run == 'true'
95
171
  uses: astral-sh/setup-uv@v5
@@ -103,17 +179,24 @@ jobs:
103
179
  if: steps.gate.outputs.run == 'true'
104
180
  run: uv sync --extra server
105
181
 
182
+ # RUNPOD_API_KEY (the warmup GPU pod) + HF_TOKEN (the temp dataset that ferries code/cache) are
183
+ # native repo Actions secrets, synced from Infisical (prod:/flash-ci) by the github-ci-flash
184
+ # Secret Sync. No Infisical CLI/login at job time -- Infisical stays the source of truth and
185
+ # rotations propagate via the sync. FLASH_CHALK_SPEC isn't synced, so bake_kernel_cache.py uses
186
+ # the repo-default DEFAULT_CHALK_SPEC (the value the fingerprint hashed) automatically. BASE_IMAGE
187
+ # is digest-pinned so the warm runs inside the EXACT base the per-arch tag will sit on.
106
188
  - name: Warm kernels on a RunPod ${{ matrix.sm }} GPU -> build/kernel_cache
107
189
  if: steps.gate.outputs.run == 'true'
108
190
  env:
109
191
  RUNPOD_API_KEY: ${{ secrets.RUNPOD_API_KEY }}
110
192
  HF_TOKEN: ${{ secrets.HF_TOKEN }}
193
+ BASE_IMAGE: ${{ steps.base.outputs.ref }}
111
194
  run: |
112
195
  uv run python docker/bake_kernel_cache.py \
113
196
  --arch "${{ matrix.arch }}" --sm "${{ matrix.sm }}" \
114
197
  --gpu-type-id "${{ matrix.gpu_type_id }}" \
115
198
  --allowed-cuda "${{ matrix.allowed_cuda }}" \
116
- --image ghcr.io/freesolo-co/flash-worker:cu128 \
199
+ --image "$BASE_IMAGE" \
117
200
  --out build/kernel_cache
118
201
 
119
202
  - name: Free disk space
@@ -130,17 +213,9 @@ jobs:
130
213
  - uses: docker/setup-buildx-action@v3
131
214
  if: steps.gate.outputs.run == 'true'
132
215
 
133
- - name: Log in to GHCR
134
- if: steps.gate.outputs.run == 'true'
135
- uses: docker/login-action@v3
136
- with:
137
- registry: ghcr.io
138
- username: ${{ github.actor }}
139
- password: ${{ secrets.GITHUB_TOKEN }}
140
-
141
216
  # thin layer FROM the SAME base the warmup ran inside -> the cache toolchain always matches the
142
217
  # shipped image (rebuilding the full Dockerfile.worker from the checkout could drift from the
143
- # published base and bake a cache that silently won't load).
218
+ # published base and bake a cache that silently won't load). GHCR auth from the login step above.
144
219
  - name: Build + push baked per-sm image (thin layer on the warmed base)
145
220
  if: steps.gate.outputs.run == 'true'
146
221
  uses: docker/build-push-action@v6
@@ -151,4 +226,7 @@ jobs:
151
226
  tags: ghcr.io/freesolo-co/flash-worker:cu128-${{ matrix.sm }}
152
227
  provenance: false
153
228
  build-args: |
154
- BASE=ghcr.io/freesolo-co/flash-worker:cu128
229
+ BASE=${{ steps.base.outputs.ref }}
230
+ FP_CACHE=${{ steps.base.outputs.fp_cache }}
231
+ FP_BASE=${{ steps.base.outputs.fp_base }}
232
+ BASE_REVISION=${{ steps.base.outputs.revision }}
@@ -36,17 +36,40 @@ on:
36
36
  # so handler changes (e.g. the weight-cache preload branch) MUST rebuild the image. flash/**
37
37
  # covers the handler source (endpoints.py); the generator lives outside flash/, so watch it too.
38
38
  - docker/make_rp_handler.py
39
+ # The fp_cache/fp_base labels are computed by this script at build time, so a change to the
40
+ # fingerprint logic must rebuild :cu128 to re-stamp them (else auto-rebake never reclassifies).
41
+ - docker/kernel_fingerprint.py
39
42
 
40
43
  permissions:
41
44
  contents: read
42
45
  packages: write
43
46
 
47
+ # A newer base build supersedes an older one: cancel the in-flight run so auto-rebake (which triggers
48
+ # on this workflow's completion) only ever reasons about the latest :cu128. The tag is in the group so
49
+ # a non-prod `tag=cu128-test` dispatch can't cancel an in-flight prod `cu128` push on the same ref
50
+ # (which would leave :cu128 unpublished for that commit and auto-rebake blind to it).
51
+ concurrency:
52
+ group: worker-image-${{ github.ref }}-${{ github.event.inputs.tag || 'cu128' }}
53
+ cancel-in-progress: true
54
+
44
55
  jobs:
45
56
  build:
46
57
  runs-on: ubuntu-24.04-8core
58
+ # Single source for the FlashAttention wheels: used BOTH as build-args and as fingerprint inputs
59
+ # (so a wheel bump moves fp_base). Keep FA3_SPEC in sync with Dockerfile.worker's ARG default.
60
+ env:
61
+ FA2_SPEC: https://github.com/mjun0812/flash-attention-prebuild-wheels/releases/download/v0.9.0/flash_attn-2.8.3%2Bcu128torch2.10-cp312-cp312-linux_x86_64.whl
62
+ FA3_SPEC: ${{ github.event.inputs.flash_attn_3_spec || 'https://github.com/windreamer/flash-attention3-wheels/releases/download/2026.03.19-850211f/flash_attn_3-3.0.0%2B20260318.cu128torch2100cxx11abitrue.8afc61-cp39-abi3-linux_x86_64.whl' }}
47
63
  steps:
48
64
  - uses: actions/checkout@v6
49
65
 
66
+ # Compute the kernel-cache fingerprints (stdlib-only, no uv sync) and stamp them as labels on
67
+ # :cu128 below, so auto-rebake.yml can read what this base was built from. Fails the build if a
68
+ # pin can't be parsed -- a silent miss would let a stale per-arch cache ship as a cold-JIT.
69
+ - name: Compute kernel fingerprints
70
+ id: fp
71
+ run: python3 docker/kernel_fingerprint.py --format github --fa2-spec "$FA2_SPEC" --fa3-spec "$FA3_SPEC" >> "$GITHUB_OUTPUT"
72
+
50
73
  - name: Free disk space
51
74
  run: |
52
75
  sudo rm -rf /usr/share/dotnet /opt/ghc /usr/local/.ghcup \
@@ -77,21 +100,20 @@ jobs:
77
100
  # so a fork run must not push to its own owner namespace and leave the real image stale.
78
101
  tags: ghcr.io/freesolo-co/flash-worker:${{ github.event.inputs.tag || 'cu128' }}
79
102
  provenance: false
103
+ # Stamp the kernel-cache fingerprints + the source commit so auto-rebake.yml can read what
104
+ # this base was built from (docker/kernel_fingerprint.py is the source of truth).
105
+ labels: |
106
+ co.freesolo.flash.kernelcache.fp_cache=${{ steps.fp.outputs.fp_cache }}
107
+ co.freesolo.flash.kernelcache.fp_base=${{ steps.fp.outputs.fp_base }}
108
+ org.opencontainers.image.revision=${{ github.sha }}
80
109
  # Install a PREBUILT flash-attn wheel instead of compiling from source (a multi-arch
81
110
  # source compile is huge and OOM-kills the runner). The wheel matches the base exactly
82
- # (cu128 / torch2.10 / cp312).
111
+ # (cu128 / torch2.10 / cp312). FA specs come from the job-level env (single source).
83
112
  build-args: |
84
- FLASH_ATTN_SPEC=https://github.com/mjun0812/flash-attention-prebuild-wheels/releases/download/v0.9.0/flash_attn-2.8.3%2Bcu128torch2.10-cp312-cp312-linux_x86_64.whl
85
- FLASH_ATTN_3_SPEC=${{ github.event.inputs.flash_attn_3_spec || 'https://github.com/windreamer/flash-attention3-wheels/releases/download/2026.03.19-850211f/flash_attn_3-3.0.0%2B20260318.cu128torch2100cxx11abitrue.8afc61-cp39-abi3-linux_x86_64.whl' }}
113
+ FLASH_ATTN_SPEC=${{ env.FA2_SPEC }}
114
+ FLASH_ATTN_3_SPEC=${{ env.FA3_SPEC }}
86
115
 
87
- # The per-arch baked images (cu128-<sm>) are rebaked MANUALLY (bake-kernel-cache.yml). When this
88
- # rebuilds :cu128, those tags go stale -> prompt a rebake. Only when the cu128 tag was (re)built.
89
- - name: Remind to rebake per-SM kernel-cache images
90
- if: ${{ success() && (github.event.inputs.tag || 'cu128') == 'cu128' }}
91
- run: |
92
- echo "::warning title=Rebake per-SM images::A new :cu128 base was published. If FLASH_WORKER_IMAGE_PER_SM=1 is enabled, run bake-kernel-cache.yml to refresh cu128-sm{80,86,89,90,120}, else workers run stale baked deps."
93
- {
94
- echo "### ⚠️ Per-SM kernel-cache images may now be stale"
95
- echo ""
96
- echo "A fresh \`:cu128\` base was just published. If \`FLASH_WORKER_IMAGE_PER_SM=1\` is enabled, re-run **bake-kernel-cache.yml** to refresh the per-arch \`cu128-sm*\` tags, or workers will run the previous baked deps."
97
- } >> "$GITHUB_STEP_SUMMARY"
116
+ # When :cu128 is republished the per-arch cu128-sm* tags go stale. auto-rebake.yml now handles
117
+ # that automatically on this workflow's completion: a free re-layer when only the base moved, or
118
+ # a one-click GPU re-warm when the kernel toolchain changed (it reads the fp_cache/fp_base labels
119
+ # stamped above vs each published per-arch tag). The old manual reminder is gone.
@@ -25,9 +25,22 @@ ENV DEBIAN_FRONTEND=noninteractive \
25
25
  # JIT on a cold worker writes here too. These ENVs are always set (cheap); whether the dir is
26
26
  # pre-populated is what the opt-in bake controls. engine.worker._load_kernel_cache_if_present reads
27
27
  # /opt/flash/kernelcache at boot.
28
+ # FLASHINFER_CUBIN_DIR / FLASHINFER_CACHE_DIR / FLASHINFER_WORKSPACE_BASE: FlashInfer's attention-backend
29
+ # cubins (the Blackwell sm120 / B200 rollout attention backend) are NOT bundled in the wheel — flashinfer
30
+ # downloads them from NVIDIA Artifactory on first use. Bake the cubin store + JIT cache into the same
31
+ # persistent kernelcache tree so
32
+ # a baked/volume cache serves them and a cold worker never re-fetches from Artifactory (kernel_warmup
33
+ # also sets these). FLASHINFER_WORKSPACE_BASE is the var flashinfer 0.6.x actually reads to relocate the
34
+ # JIT host-wrapper cache (FLASHINFER_CACHE_DIR is a DERIVED constant there, not an env knob), so set it
35
+ # too — otherwise a B200 path that touches flashinfer before kernel_warmup runs lands the wrapper under
36
+ # the default home workspace and re-JITs instead of using the baked cache.
28
37
  ENV TRITON_CACHE_DIR=/opt/flash/kernelcache/triton \
29
- TORCHINDUCTOR_CACHE_DIR=/opt/flash/kernelcache/inductor
30
- RUN mkdir -p /opt/flash/kernelcache/triton /opt/flash/kernelcache/inductor
38
+ TORCHINDUCTOR_CACHE_DIR=/opt/flash/kernelcache/inductor \
39
+ FLASHINFER_CUBIN_DIR=/opt/flash/kernelcache/flashinfer_cubin \
40
+ FLASHINFER_CACHE_DIR=/opt/flash/kernelcache/flashinfer \
41
+ FLASHINFER_WORKSPACE_BASE=/opt/flash/kernelcache/flashinfer
42
+ RUN mkdir -p /opt/flash/kernelcache/triton /opt/flash/kernelcache/inductor \
43
+ /opt/flash/kernelcache/flashinfer_cubin /opt/flash/kernelcache/flashinfer
31
44
 
32
45
  # build-essential for Triton/Inductor (Liger) + any source builds; git for pip VCS installs.
33
46
  RUN apt-get update && apt-get install -y --no-install-recommends build-essential git curl \
@@ -39,6 +52,7 @@ RUN pip install --no-cache-dir \
39
52
  "trl>=1.6,<1.7" \
40
53
  "peft>=0.19" \
41
54
  "vllm==0.19.1" \
55
+ "flashinfer-python==0.6.6" \
42
56
  "bitsandbytes>=0.49" \
43
57
  "datasets>=4.7,<6" \
44
58
  "huggingface_hub>=0.25" \
@@ -187,10 +201,12 @@ fa_ok = False; \
187
201
  exec('try:\n import flash_attn\n fa_ok = True\nexcept Exception:\n fa_ok = False'); \
188
202
  fa3_ok = False; \
189
203
  exec('try:\n import flash_attn_interface\n fa3_ok = True\nexcept Exception:\n fa3_ok = False'); \
204
+ fi_ok = False; \
205
+ exec('try:\n import flashinfer\n fi_ok = True\nexcept Exception:\n fi_ok = False'); \
190
206
  cudnn = torch.backends.cudnn.version(); assert cudnn, 'cuDNN not compiled into torch'; \
191
207
  ver = lambda n: M.version(n); \
192
- print('worker stack OK | torch', torch.__version__, '| cudnn', cudnn, '| triton', triton.__version__, '| flash_attn', 'present' if fa_ok else 'ABSENT (SDPA fallback)', '| flash_attn_3', 'present (Hopper FA3)' if fa3_ok else 'ABSENT (SDPA on Hopper)'); \
193
- [print(' ', d, ver(d)) for d in ['transformers','trl','peft','vllm','datasets','huggingface-hub', \
208
+ print('worker stack OK | torch', torch.__version__, '| cudnn', cudnn, '| triton', triton.__version__, '| flash_attn', 'present' if fa_ok else 'ABSENT (SDPA fallback)', '| flash_attn_3', 'present (Hopper FA3)' if fa3_ok else 'ABSENT (SDPA on Hopper)', '| flashinfer', 'present (B200 MoE/attn)' if fi_ok else 'ABSENT (Triton fused-MoE fallback)'); \
209
+ [print(' ', d, ver(d)) for d in ['transformers','trl','peft','vllm','flashinfer-python','datasets','huggingface-hub', \
194
210
  'accelerate','wandb','liger-kernel','flash-linear-attention','bitsandbytes', \
195
211
  'hf-transfer','freesolo','runpod']]"
196
212
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: freesolo-flash
3
- Version: 0.2.26
3
+ Version: 0.2.30
4
4
  Summary: Flash — managed LoRA post-training (SFT/GRPO) 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
@@ -16,3 +16,13 @@ ENV TRITON_CACHE_DIR=/opt/flash/kernelcache/triton \
16
16
  TORCHINDUCTOR_CACHE_DIR=/opt/flash/kernelcache/inductor
17
17
 
18
18
  COPY build/kernel_cache/ /opt/flash/kernelcache/
19
+
20
+ # Fingerprint + base-revision stamps so auto-rebake.yml can read what this image was baked from and
21
+ # decide skip / re-layer / re-warm (docker/kernel_fingerprint.py is the source of truth for the
22
+ # values). Default to "unknown" so a hand build still works; CI always passes the real ones.
23
+ ARG FP_CACHE=unknown
24
+ ARG FP_BASE=unknown
25
+ ARG BASE_REVISION=unknown
26
+ LABEL co.freesolo.flash.kernelcache.fp_cache=$FP_CACHE \
27
+ co.freesolo.flash.kernelcache.fp_base=$FP_BASE \
28
+ org.opencontainers.image.revision=$BASE_REVISION
@@ -0,0 +1,27 @@
1
+ # Cheap per-arch RE-LAYER: graft the EXISTING baked mega-cache onto a freshly rebuilt :cu128 base,
2
+ # with NO GPU. Used by auto-rebake.yml when fp_cache is unchanged (the cache is still valid) but the
3
+ # base moved (fp_base changed) -- e.g. an FA2/FA3/causal-conv1d/rp_handler bump. The valid cache
4
+ # already lives inside the currently-published per-arch tag, so OLDCACHE IS the cache store; we just
5
+ # re-stack it on the new base. This is what makes a base-only change free (vs a paid GPU re-warm).
6
+ #
7
+ # BASE and OLDCACHE are passed DIGEST-PINNED by the gate so a concurrent base/tag overwrite can't
8
+ # graft the cache onto the wrong base.
9
+ ARG BASE=ghcr.io/freesolo-co/flash-worker:cu128
10
+ ARG OLDCACHE=ghcr.io/freesolo-co/flash-worker:cu128-sm89
11
+ FROM ${OLDCACHE} AS oldcache
12
+ FROM ${BASE}
13
+
14
+ # Match Dockerfile.worker / Dockerfile.kernelcache so the layer is self-contained even on an older base.
15
+ ENV TRITON_CACHE_DIR=/opt/flash/kernelcache/triton \
16
+ TORCHINDUCTOR_CACHE_DIR=/opt/flash/kernelcache/inductor
17
+
18
+ # Pull the warmed cache straight out of the old per-arch image -- no GPU, no external cache store.
19
+ COPY --from=oldcache /opt/flash/kernelcache /opt/flash/kernelcache
20
+
21
+ # Re-stamp with the CURRENT fingerprints (fp_cache unchanged, fp_base + revision are the new base's).
22
+ ARG FP_CACHE=unknown
23
+ ARG FP_BASE=unknown
24
+ ARG BASE_REVISION=unknown
25
+ LABEL co.freesolo.flash.kernelcache.fp_cache=$FP_CACHE \
26
+ co.freesolo.flash.kernelcache.fp_base=$FP_BASE \
27
+ org.opencontainers.image.revision=$BASE_REVISION