freesolo-flash-dev 0.2.26__tar.gz → 0.2.28__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 (266) hide show
  1. freesolo_flash_dev-0.2.28/.github/workflows/auto-rebake.yml +245 -0
  2. freesolo_flash_dev-0.2.28/.github/workflows/bake-kernel-cache.yml +245 -0
  3. {freesolo_flash_dev-0.2.26 → freesolo_flash_dev-0.2.28}/.github/workflows/worker-image.yml +36 -14
  4. {freesolo_flash_dev-0.2.26 → freesolo_flash_dev-0.2.28}/PKG-INFO +1 -1
  5. {freesolo_flash_dev-0.2.26 → freesolo_flash_dev-0.2.28}/docker/Dockerfile.kernelcache +10 -0
  6. freesolo_flash_dev-0.2.28/docker/Dockerfile.kernelcache.relayer +27 -0
  7. freesolo_flash_dev-0.2.28/docker/kernel_fingerprint.py +245 -0
  8. {freesolo_flash_dev-0.2.26 → freesolo_flash_dev-0.2.28}/docs/cli-style/generate.py +3 -16
  9. {freesolo_flash_dev-0.2.26 → freesolo_flash_dev-0.2.28}/docs/cli-style/index.html +79 -131
  10. freesolo_flash_dev-0.2.28/docs/cli-style/themed-errors.png +0 -0
  11. freesolo_flash_dev-0.2.28/docs/cli-theme/README.md +32 -0
  12. freesolo_flash_dev-0.2.28/docs/cli-theme/before-after-dark.png +0 -0
  13. freesolo_flash_dev-0.2.28/docs/cli-theme/before-after-light.png +0 -0
  14. freesolo_flash_dev-0.2.28/docs/cli-theme/gallery-dark.png +0 -0
  15. freesolo_flash_dev-0.2.28/docs/cli-theme/gallery-light.png +0 -0
  16. freesolo_flash_dev-0.2.28/docs/cli-theme/help-dark.png +0 -0
  17. freesolo_flash_dev-0.2.28/docs/cli-theme/help-light.png +0 -0
  18. {freesolo_flash_dev-0.2.26 → freesolo_flash_dev-0.2.28}/flash/catalog.py +11 -4
  19. {freesolo_flash_dev-0.2.26 → freesolo_flash_dev-0.2.28}/flash/cli/__init__.py +163 -15
  20. {freesolo_flash_dev-0.2.26 → freesolo_flash_dev-0.2.28}/flash/cli/commands.py +42 -34
  21. {freesolo_flash_dev-0.2.26 → freesolo_flash_dev-0.2.28}/flash/cli/envpush.py +28 -39
  22. {freesolo_flash_dev-0.2.26 → freesolo_flash_dev-0.2.28}/flash/cli/render.py +169 -22
  23. {freesolo_flash_dev-0.2.26 → freesolo_flash_dev-0.2.28}/flash/cli/training_doc.py +6 -6
  24. {freesolo_flash_dev-0.2.26 → freesolo_flash_dev-0.2.28}/flash/cost/spec.py +5 -6
  25. {freesolo_flash_dev-0.2.26 → freesolo_flash_dev-0.2.28}/flash/engine/accounting.py +1 -1
  26. {freesolo_flash_dev-0.2.26 → freesolo_flash_dev-0.2.28}/flash/engine/vram.py +22 -19
  27. {freesolo_flash_dev-0.2.26 → freesolo_flash_dev-0.2.28}/flash/engine/worker/__init__.py +12 -2
  28. {freesolo_flash_dev-0.2.26 → freesolo_flash_dev-0.2.28}/flash/engine/worker/adapter.py +128 -28
  29. {freesolo_flash_dev-0.2.26 → freesolo_flash_dev-0.2.28}/flash/engine/worker/hf.py +41 -4
  30. {freesolo_flash_dev-0.2.26 → freesolo_flash_dev-0.2.28}/flash/engine/worker/lora.py +211 -0
  31. {freesolo_flash_dev-0.2.26 → freesolo_flash_dev-0.2.28}/flash/engine/worker/rl.py +39 -12
  32. {freesolo_flash_dev-0.2.26 → freesolo_flash_dev-0.2.28}/flash/engine/worker/wandb_log.py +2 -2
  33. {freesolo_flash_dev-0.2.26 → freesolo_flash_dev-0.2.28}/flash/envs/adapter.py +48 -9
  34. {freesolo_flash_dev-0.2.26 → freesolo_flash_dev-0.2.28}/flash/envs/registry.py +0 -25
  35. {freesolo_flash_dev-0.2.26 → freesolo_flash_dev-0.2.28}/flash/providers/_instance.py +1 -1
  36. {freesolo_flash_dev-0.2.26 → freesolo_flash_dev-0.2.28}/flash/providers/lambdalabs/__init__.py +1 -1
  37. {freesolo_flash_dev-0.2.26 → freesolo_flash_dev-0.2.28}/flash/providers/lambdalabs/jobs/__init__.py +2 -2
  38. {freesolo_flash_dev-0.2.26 → freesolo_flash_dev-0.2.28}/flash/providers/runpod/__init__.py +1 -1
  39. {freesolo_flash_dev-0.2.26 → freesolo_flash_dev-0.2.28}/flash/providers/runpod/jobs.py +1 -1
  40. {freesolo_flash_dev-0.2.26 → freesolo_flash_dev-0.2.28}/flash/providers/runpod/preload.py +2 -2
  41. {freesolo_flash_dev-0.2.26 → freesolo_flash_dev-0.2.28}/flash/providers/runpod/train/endpoints.py +2 -2
  42. {freesolo_flash_dev-0.2.26 → freesolo_flash_dev-0.2.28}/flash/runner/__init__.py +28 -22
  43. {freesolo_flash_dev-0.2.26 → freesolo_flash_dev-0.2.28}/flash/runner/checkpoints.py +5 -5
  44. {freesolo_flash_dev-0.2.26 → freesolo_flash_dev-0.2.28}/flash/runner/deploy.py +17 -113
  45. {freesolo_flash_dev-0.2.26 → freesolo_flash_dev-0.2.28}/flash/runner/lifecycle.py +35 -64
  46. {freesolo_flash_dev-0.2.26 → freesolo_flash_dev-0.2.28}/flash/schema/__init__.py +3 -7
  47. {freesolo_flash_dev-0.2.26 → freesolo_flash_dev-0.2.28}/flash/server/_runtime.py +0 -5
  48. {freesolo_flash_dev-0.2.26 → freesolo_flash_dev-0.2.28}/flash/server/app.py +1 -1
  49. {freesolo_flash_dev-0.2.26 → freesolo_flash_dev-0.2.28}/flash/server/checkpoints.py +35 -10
  50. {freesolo_flash_dev-0.2.26 → freesolo_flash_dev-0.2.28}/flash/server/run_registry.py +2 -4
  51. {freesolo_flash_dev-0.2.26 → freesolo_flash_dev-0.2.28}/flash/spec.py +7 -3
  52. {freesolo_flash_dev-0.2.26 → freesolo_flash_dev-0.2.28}/pyproject.toml +2 -2
  53. {freesolo_flash_dev-0.2.26 → freesolo_flash_dev-0.2.28}/tests/test_agent_flash_cli_contract.py +2 -10
  54. {freesolo_flash_dev-0.2.26 → freesolo_flash_dev-0.2.28}/tests/test_algorithms.py +1 -0
  55. {freesolo_flash_dev-0.2.26 → freesolo_flash_dev-0.2.28}/tests/test_allocator.py +34 -2
  56. {freesolo_flash_dev-0.2.26 → freesolo_flash_dev-0.2.28}/tests/test_backend_jobspec_contract.py +0 -2
  57. {freesolo_flash_dev-0.2.26 → freesolo_flash_dev-0.2.28}/tests/test_billing_retry.py +7 -58
  58. {freesolo_flash_dev-0.2.26 → freesolo_flash_dev-0.2.28}/tests/test_cancel_remote.py +23 -25
  59. {freesolo_flash_dev-0.2.26 → freesolo_flash_dev-0.2.28}/tests/test_catalog_consistency.py +9 -0
  60. {freesolo_flash_dev-0.2.26 → freesolo_flash_dev-0.2.28}/tests/test_checkpoints.py +113 -17
  61. {freesolo_flash_dev-0.2.26 → freesolo_flash_dev-0.2.28}/tests/test_cli_errors.py +4 -4
  62. {freesolo_flash_dev-0.2.26 → freesolo_flash_dev-0.2.28}/tests/test_cli_estimate.py +2 -10
  63. freesolo_flash_dev-0.2.28/tests/test_cli_help.py +96 -0
  64. {freesolo_flash_dev-0.2.26 → freesolo_flash_dev-0.2.28}/tests/test_cli_managed.py +1 -1
  65. freesolo_flash_dev-0.2.28/tests/test_cli_render_theme.py +388 -0
  66. {freesolo_flash_dev-0.2.26 → freesolo_flash_dev-0.2.28}/tests/test_client_server_integration.py +1 -1
  67. {freesolo_flash_dev-0.2.26 → freesolo_flash_dev-0.2.28}/tests/test_config_overrides.py +5 -3
  68. {freesolo_flash_dev-0.2.26 → freesolo_flash_dev-0.2.28}/tests/test_cost_analytical.py +0 -8
  69. {freesolo_flash_dev-0.2.26 → freesolo_flash_dev-0.2.28}/tests/test_disk_gb.py +1 -0
  70. freesolo_flash_dev-0.2.28/tests/test_env_no_install.py +59 -0
  71. {freesolo_flash_dev-0.2.26 → freesolo_flash_dev-0.2.28}/tests/test_env_publish.py +4 -5
  72. {freesolo_flash_dev-0.2.26 → freesolo_flash_dev-0.2.28}/tests/test_env_push.py +29 -0
  73. {freesolo_flash_dev-0.2.26 → freesolo_flash_dev-0.2.28}/tests/test_env_rate_limit_resolve.py +1 -1
  74. {freesolo_flash_dev-0.2.26 → freesolo_flash_dev-0.2.28}/tests/test_flash_mvp.py +1 -4
  75. {freesolo_flash_dev-0.2.26 → freesolo_flash_dev-0.2.28}/tests/test_flash_worker.py +6 -6
  76. {freesolo_flash_dev-0.2.26 → freesolo_flash_dev-0.2.28}/tests/test_gpus.py +3 -3
  77. {freesolo_flash_dev-0.2.26 → freesolo_flash_dev-0.2.28}/tests/test_grpo_params.py +18 -23
  78. {freesolo_flash_dev-0.2.26 → freesolo_flash_dev-0.2.28}/tests/test_grpo_sleep_gate.py +32 -0
  79. {freesolo_flash_dev-0.2.26 → freesolo_flash_dev-0.2.28}/tests/test_jobs.py +22 -69
  80. freesolo_flash_dev-0.2.28/tests/test_kernel_fingerprint.py +132 -0
  81. {freesolo_flash_dev-0.2.26 → freesolo_flash_dev-0.2.28}/tests/test_kv_util.py +36 -0
  82. {freesolo_flash_dev-0.2.26 → freesolo_flash_dev-0.2.28}/tests/test_lambda_runner.py +9 -9
  83. {freesolo_flash_dev-0.2.26 → freesolo_flash_dev-0.2.28}/tests/test_orchestrator_flash.py +5 -5
  84. {freesolo_flash_dev-0.2.26 → freesolo_flash_dev-0.2.28}/tests/test_provider_routing.py +2 -3
  85. {freesolo_flash_dev-0.2.26 → freesolo_flash_dev-0.2.28}/tests/test_resolve_params_b.py +8 -6
  86. {freesolo_flash_dev-0.2.26 → freesolo_flash_dev-0.2.28}/tests/test_resume_on_retry.py +3 -3
  87. {freesolo_flash_dev-0.2.26 → freesolo_flash_dev-0.2.28}/tests/test_runmgmt.py +66 -4
  88. {freesolo_flash_dev-0.2.26 → freesolo_flash_dev-0.2.28}/tests/test_server_api.py +12 -12
  89. {freesolo_flash_dev-0.2.26 → freesolo_flash_dev-0.2.28}/tests/test_server_billing.py +1 -1
  90. {freesolo_flash_dev-0.2.26 → freesolo_flash_dev-0.2.28}/tests/test_spec_and_validation.py +8 -8
  91. {freesolo_flash_dev-0.2.26 → freesolo_flash_dev-0.2.28}/tests/test_thinking_config.py +3 -0
  92. {freesolo_flash_dev-0.2.26 → freesolo_flash_dev-0.2.28}/tests/test_verifiers.py +86 -15
  93. {freesolo_flash_dev-0.2.26 → freesolo_flash_dev-0.2.28}/tests/test_vl_warmstart_adapter_keys.py +38 -0
  94. freesolo_flash_dev-0.2.28/tests/test_vl_warmstart_recombine.py +351 -0
  95. {freesolo_flash_dev-0.2.26 → freesolo_flash_dev-0.2.28}/tests/test_wandb_naming.py +2 -3
  96. {freesolo_flash_dev-0.2.26 → freesolo_flash_dev-0.2.28}/tests/test_warmstart_cross_repo.py +4 -4
  97. {freesolo_flash_dev-0.2.26 → freesolo_flash_dev-0.2.28}/tests/test_weight_cache.py +4 -4
  98. {freesolo_flash_dev-0.2.26 → freesolo_flash_dev-0.2.28}/uv.lock +1 -1
  99. freesolo_flash_dev-0.2.26/.github/workflows/bake-kernel-cache.yml +0 -154
  100. freesolo_flash_dev-0.2.26/tests/test_cli_render_theme.py +0 -159
  101. freesolo_flash_dev-0.2.26/tests/test_env_install.py +0 -43
  102. {freesolo_flash_dev-0.2.26 → freesolo_flash_dev-0.2.28}/.dockerignore +0 -0
  103. {freesolo_flash_dev-0.2.26 → freesolo_flash_dev-0.2.28}/.env.example +0 -0
  104. {freesolo_flash_dev-0.2.26 → freesolo_flash_dev-0.2.28}/.github/workflows/ci.yml +0 -0
  105. {freesolo_flash_dev-0.2.26 → freesolo_flash_dev-0.2.28}/.github/workflows/main-source-guard.yml +0 -0
  106. {freesolo_flash_dev-0.2.26 → freesolo_flash_dev-0.2.28}/.github/workflows/publish-dev.yml +0 -0
  107. {freesolo_flash_dev-0.2.26 → freesolo_flash_dev-0.2.28}/.github/workflows/publish-image.yml +0 -0
  108. {freesolo_flash_dev-0.2.26 → freesolo_flash_dev-0.2.28}/.github/workflows/publish.yml +0 -0
  109. {freesolo_flash_dev-0.2.26 → freesolo_flash_dev-0.2.28}/.github/workflows/version-parity.yml +0 -0
  110. {freesolo_flash_dev-0.2.26 → freesolo_flash_dev-0.2.28}/.gitignore +0 -0
  111. {freesolo_flash_dev-0.2.26 → freesolo_flash_dev-0.2.28}/Dockerfile +0 -0
  112. {freesolo_flash_dev-0.2.26 → freesolo_flash_dev-0.2.28}/Dockerfile.worker +0 -0
  113. {freesolo_flash_dev-0.2.26 → freesolo_flash_dev-0.2.28}/LICENSE +0 -0
  114. {freesolo_flash_dev-0.2.26 → freesolo_flash_dev-0.2.28}/README.md +0 -0
  115. {freesolo_flash_dev-0.2.26 → freesolo_flash_dev-0.2.28}/build/kernel_cache/.gitignore +0 -0
  116. {freesolo_flash_dev-0.2.26 → freesolo_flash_dev-0.2.28}/build/kernel_cache/.keep +0 -0
  117. {freesolo_flash_dev-0.2.26 → freesolo_flash_dev-0.2.28}/docker/bake_kernel_cache.py +0 -0
  118. {freesolo_flash_dev-0.2.26 → freesolo_flash_dev-0.2.28}/docker/bake_pod_entry.py +0 -0
  119. {freesolo_flash_dev-0.2.26 → freesolo_flash_dev-0.2.28}/docker/make_rp_handler.py +0 -0
  120. {freesolo_flash_dev-0.2.26 → freesolo_flash_dev-0.2.28}/docs/cli-style/README.md +0 -0
  121. {freesolo_flash_dev-0.2.26 → freesolo_flash_dev-0.2.28}/docs/cli-style/preview.png +0 -0
  122. {freesolo_flash_dev-0.2.26 → freesolo_flash_dev-0.2.28}/docs/kernel-cache.md +0 -0
  123. {freesolo_flash_dev-0.2.26 → freesolo_flash_dev-0.2.28}/flash/__init__.py +0 -0
  124. {freesolo_flash_dev-0.2.26 → freesolo_flash_dev-0.2.28}/flash/_channel.py +0 -0
  125. {freesolo_flash_dev-0.2.26 → freesolo_flash_dev-0.2.28}/flash/_fileio.py +0 -0
  126. {freesolo_flash_dev-0.2.26 → freesolo_flash_dev-0.2.28}/flash/_logging.py +0 -0
  127. {freesolo_flash_dev-0.2.26 → freesolo_flash_dev-0.2.28}/flash/_update_check.py +0 -0
  128. {freesolo_flash_dev-0.2.26 → freesolo_flash_dev-0.2.28}/flash/cli/__main__.py +0 -0
  129. {freesolo_flash_dev-0.2.26 → freesolo_flash_dev-0.2.28}/flash/client/__init__.py +0 -0
  130. {freesolo_flash_dev-0.2.26 → freesolo_flash_dev-0.2.28}/flash/client/config.py +0 -0
  131. {freesolo_flash_dev-0.2.26 → freesolo_flash_dev-0.2.28}/flash/client/http.py +0 -0
  132. {freesolo_flash_dev-0.2.26 → freesolo_flash_dev-0.2.28}/flash/client/runtime_secrets.py +0 -0
  133. {freesolo_flash_dev-0.2.26 → freesolo_flash_dev-0.2.28}/flash/client/specs.py +0 -0
  134. {freesolo_flash_dev-0.2.26 → freesolo_flash_dev-0.2.28}/flash/cost/__init__.py +0 -0
  135. {freesolo_flash_dev-0.2.26 → freesolo_flash_dev-0.2.28}/flash/cost/analytical.py +0 -0
  136. {freesolo_flash_dev-0.2.26 → freesolo_flash_dev-0.2.28}/flash/cost/facts.py +0 -0
  137. {freesolo_flash_dev-0.2.26 → freesolo_flash_dev-0.2.28}/flash/cost/types.py +0 -0
  138. {freesolo_flash_dev-0.2.26 → freesolo_flash_dev-0.2.28}/flash/engine/__init__.py +0 -0
  139. {freesolo_flash_dev-0.2.26 → freesolo_flash_dev-0.2.28}/flash/engine/chalk_kernels.py +0 -0
  140. {freesolo_flash_dev-0.2.26 → freesolo_flash_dev-0.2.28}/flash/engine/multiturn_rollout.py +0 -0
  141. {freesolo_flash_dev-0.2.26 → freesolo_flash_dev-0.2.28}/flash/engine/recipe.py +0 -0
  142. {freesolo_flash_dev-0.2.26 → freesolo_flash_dev-0.2.28}/flash/engine/worker/__main__.py +0 -0
  143. {freesolo_flash_dev-0.2.26 → freesolo_flash_dev-0.2.28}/flash/engine/worker/_pkg.py +0 -0
  144. {freesolo_flash_dev-0.2.26 → freesolo_flash_dev-0.2.28}/flash/engine/worker/decoding.py +0 -0
  145. {freesolo_flash_dev-0.2.26 → freesolo_flash_dev-0.2.28}/flash/engine/worker/finalize.py +0 -0
  146. {freesolo_flash_dev-0.2.26 → freesolo_flash_dev-0.2.28}/flash/engine/worker/gpu_setup.py +0 -0
  147. {freesolo_flash_dev-0.2.26 → freesolo_flash_dev-0.2.28}/flash/engine/worker/grpo.py +0 -0
  148. {freesolo_flash_dev-0.2.26 → freesolo_flash_dev-0.2.28}/flash/engine/worker/heartbeat.py +0 -0
  149. {freesolo_flash_dev-0.2.26 → freesolo_flash_dev-0.2.28}/flash/engine/worker/kernel_warmup.py +0 -0
  150. {freesolo_flash_dev-0.2.26 → freesolo_flash_dev-0.2.28}/flash/engine/worker/packing.py +0 -0
  151. {freesolo_flash_dev-0.2.26 → freesolo_flash_dev-0.2.28}/flash/engine/worker/perf/__init__.py +0 -0
  152. {freesolo_flash_dev-0.2.26 → freesolo_flash_dev-0.2.28}/flash/engine/worker/perf/attn.py +0 -0
  153. {freesolo_flash_dev-0.2.26 → freesolo_flash_dev-0.2.28}/flash/engine/worker/perf/diagnostics.py +0 -0
  154. {freesolo_flash_dev-0.2.26 → freesolo_flash_dev-0.2.28}/flash/engine/worker/perf/lifecycle.py +0 -0
  155. {freesolo_flash_dev-0.2.26 → freesolo_flash_dev-0.2.28}/flash/engine/worker/perf/liger.py +0 -0
  156. {freesolo_flash_dev-0.2.26 → freesolo_flash_dev-0.2.28}/flash/engine/worker/perf/loraplus.py +0 -0
  157. {freesolo_flash_dev-0.2.26 → freesolo_flash_dev-0.2.28}/flash/engine/worker/perf/memory.py +0 -0
  158. {freesolo_flash_dev-0.2.26 → freesolo_flash_dev-0.2.28}/flash/engine/worker/sft.py +0 -0
  159. {freesolo_flash_dev-0.2.26 → freesolo_flash_dev-0.2.28}/flash/envs/__init__.py +0 -0
  160. {freesolo_flash_dev-0.2.26 → freesolo_flash_dev-0.2.28}/flash/envs/base.py +0 -0
  161. {freesolo_flash_dev-0.2.26 → freesolo_flash_dev-0.2.28}/flash/providers/__init__.py +0 -0
  162. {freesolo_flash_dev-0.2.26 → freesolo_flash_dev-0.2.28}/flash/providers/_auth.py +0 -0
  163. {freesolo_flash_dev-0.2.26 → freesolo_flash_dev-0.2.28}/flash/providers/_http.py +0 -0
  164. {freesolo_flash_dev-0.2.26 → freesolo_flash_dev-0.2.28}/flash/providers/_instance_bootstrap.py +0 -0
  165. {freesolo_flash_dev-0.2.26 → freesolo_flash_dev-0.2.28}/flash/providers/_poll.py +0 -0
  166. {freesolo_flash_dev-0.2.26 → freesolo_flash_dev-0.2.28}/flash/providers/allocator.py +0 -0
  167. {freesolo_flash_dev-0.2.26 → freesolo_flash_dev-0.2.28}/flash/providers/base.py +0 -0
  168. {freesolo_flash_dev-0.2.26 → freesolo_flash_dev-0.2.28}/flash/providers/lambdalabs/api.py +0 -0
  169. {freesolo_flash_dev-0.2.26 → freesolo_flash_dev-0.2.28}/flash/providers/lambdalabs/auth.py +0 -0
  170. {freesolo_flash_dev-0.2.26 → freesolo_flash_dev-0.2.28}/flash/providers/lambdalabs/gpus.py +0 -0
  171. {freesolo_flash_dev-0.2.26 → freesolo_flash_dev-0.2.28}/flash/providers/lambdalabs/jobs/builders.py +0 -0
  172. {freesolo_flash_dev-0.2.26 → freesolo_flash_dev-0.2.28}/flash/providers/lambdalabs/preflight.py +0 -0
  173. {freesolo_flash_dev-0.2.26 → freesolo_flash_dev-0.2.28}/flash/providers/lambdalabs/pricing.py +0 -0
  174. {freesolo_flash_dev-0.2.26 → freesolo_flash_dev-0.2.28}/flash/providers/lambdalabs/train.py +0 -0
  175. {freesolo_flash_dev-0.2.26 → freesolo_flash_dev-0.2.28}/flash/providers/preflight.py +0 -0
  176. {freesolo_flash_dev-0.2.26 → freesolo_flash_dev-0.2.28}/flash/providers/realized.py +0 -0
  177. {freesolo_flash_dev-0.2.26 → freesolo_flash_dev-0.2.28}/flash/providers/runpod/api.py +0 -0
  178. {freesolo_flash_dev-0.2.26 → freesolo_flash_dev-0.2.28}/flash/providers/runpod/auth.py +0 -0
  179. {freesolo_flash_dev-0.2.26 → freesolo_flash_dev-0.2.28}/flash/providers/runpod/cost.py +0 -0
  180. {freesolo_flash_dev-0.2.26 → freesolo_flash_dev-0.2.28}/flash/providers/runpod/gpus.py +0 -0
  181. {freesolo_flash_dev-0.2.26 → freesolo_flash_dev-0.2.28}/flash/providers/runpod/keys.py +0 -0
  182. {freesolo_flash_dev-0.2.26 → freesolo_flash_dev-0.2.28}/flash/providers/runpod/preflight.py +0 -0
  183. {freesolo_flash_dev-0.2.26 → freesolo_flash_dev-0.2.28}/flash/providers/runpod/pricing.py +0 -0
  184. {freesolo_flash_dev-0.2.26 → freesolo_flash_dev-0.2.28}/flash/providers/runpod/slots.py +0 -0
  185. {freesolo_flash_dev-0.2.26 → freesolo_flash_dev-0.2.28}/flash/providers/runpod/train/__init__.py +0 -0
  186. {freesolo_flash_dev-0.2.26 → freesolo_flash_dev-0.2.28}/flash/providers/runpod/train/deps.py +0 -0
  187. {freesolo_flash_dev-0.2.26 → freesolo_flash_dev-0.2.28}/flash/py.typed +0 -0
  188. {freesolo_flash_dev-0.2.26 → freesolo_flash_dev-0.2.28}/flash/schema/fields.py +0 -0
  189. {freesolo_flash_dev-0.2.26 → freesolo_flash_dev-0.2.28}/flash/serve/__init__.py +0 -0
  190. {freesolo_flash_dev-0.2.26 → freesolo_flash_dev-0.2.28}/flash/serve/deploy.py +0 -0
  191. {freesolo_flash_dev-0.2.26 → freesolo_flash_dev-0.2.28}/flash/serve/export.py +0 -0
  192. {freesolo_flash_dev-0.2.26 → freesolo_flash_dev-0.2.28}/flash/serve/pricing.py +0 -0
  193. {freesolo_flash_dev-0.2.26 → freesolo_flash_dev-0.2.28}/flash/server/__init__.py +0 -0
  194. {freesolo_flash_dev-0.2.26 → freesolo_flash_dev-0.2.28}/flash/server/__main__.py +0 -0
  195. {freesolo_flash_dev-0.2.26 → freesolo_flash_dev-0.2.28}/flash/server/_deps.py +0 -0
  196. {freesolo_flash_dev-0.2.26 → freesolo_flash_dev-0.2.28}/flash/server/_locks.py +0 -0
  197. {freesolo_flash_dev-0.2.26 → freesolo_flash_dev-0.2.28}/flash/server/auth.py +0 -0
  198. {freesolo_flash_dev-0.2.26 → freesolo_flash_dev-0.2.28}/flash/server/billing.py +0 -0
  199. {freesolo_flash_dev-0.2.26 → freesolo_flash_dev-0.2.28}/flash/server/billing_retry.py +0 -0
  200. {freesolo_flash_dev-0.2.26 → freesolo_flash_dev-0.2.28}/flash/server/db.py +0 -0
  201. {freesolo_flash_dev-0.2.26 → freesolo_flash_dev-0.2.28}/flash/server/environment_registry.py +0 -0
  202. {freesolo_flash_dev-0.2.26 → freesolo_flash_dev-0.2.28}/flash/server/envs.py +0 -0
  203. {freesolo_flash_dev-0.2.26 → freesolo_flash_dev-0.2.28}/flash/server/reconcile.py +0 -0
  204. {freesolo_flash_dev-0.2.26 → freesolo_flash_dev-0.2.28}/flash/server/routes/__init__.py +0 -0
  205. {freesolo_flash_dev-0.2.26 → freesolo_flash_dev-0.2.28}/flash/server/routes/envs.py +0 -0
  206. {freesolo_flash_dev-0.2.26 → freesolo_flash_dev-0.2.28}/flash/server/routes/meta.py +0 -0
  207. {freesolo_flash_dev-0.2.26 → freesolo_flash_dev-0.2.28}/flash/server/routes/runs.py +0 -0
  208. {freesolo_flash_dev-0.2.26 → freesolo_flash_dev-0.2.28}/flash/server/routes/serving.py +0 -0
  209. {freesolo_flash_dev-0.2.26 → freesolo_flash_dev-0.2.28}/infisical-entrypoint.sh +0 -0
  210. {freesolo_flash_dev-0.2.26 → freesolo_flash_dev-0.2.28}/scripts/build_dev_dist.py +0 -0
  211. {freesolo_flash_dev-0.2.26 → freesolo_flash_dev-0.2.28}/tests/__init__.py +0 -0
  212. {freesolo_flash_dev-0.2.26 → freesolo_flash_dev-0.2.28}/tests/_helpers/__init__.py +0 -0
  213. {freesolo_flash_dev-0.2.26 → freesolo_flash_dev-0.2.28}/tests/_helpers/runner.py +0 -0
  214. {freesolo_flash_dev-0.2.26 → freesolo_flash_dev-0.2.28}/tests/_helpers/specs.py +0 -0
  215. {freesolo_flash_dev-0.2.26 → freesolo_flash_dev-0.2.28}/tests/conftest.py +0 -0
  216. {freesolo_flash_dev-0.2.26 → freesolo_flash_dev-0.2.28}/tests/fixtures/math_eval.jsonl +0 -0
  217. {freesolo_flash_dev-0.2.26 → freesolo_flash_dev-0.2.28}/tests/fixtures/math_train.jsonl +0 -0
  218. {freesolo_flash_dev-0.2.26 → freesolo_flash_dev-0.2.28}/tests/live/__init__.py +0 -0
  219. {freesolo_flash_dev-0.2.26 → freesolo_flash_dev-0.2.28}/tests/live/conftest.py +0 -0
  220. {freesolo_flash_dev-0.2.26 → freesolo_flash_dev-0.2.28}/tests/live/test_lambda_live.py +0 -0
  221. {freesolo_flash_dev-0.2.26 → freesolo_flash_dev-0.2.28}/tests/live/test_runpod_live.py +0 -0
  222. {freesolo_flash_dev-0.2.26 → freesolo_flash_dev-0.2.28}/tests/test_chalk_kernels.py +0 -0
  223. {freesolo_flash_dev-0.2.26 → freesolo_flash_dev-0.2.28}/tests/test_cli_commands.py +0 -0
  224. {freesolo_flash_dev-0.2.26 → freesolo_flash_dev-0.2.28}/tests/test_client.py +0 -0
  225. {freesolo_flash_dev-0.2.26 → freesolo_flash_dev-0.2.28}/tests/test_cost_equation.py +0 -0
  226. {freesolo_flash_dev-0.2.26 → freesolo_flash_dev-0.2.28}/tests/test_cost_estimate.py +0 -0
  227. {freesolo_flash_dev-0.2.26 → freesolo_flash_dev-0.2.28}/tests/test_cost_hardware.py +0 -0
  228. {freesolo_flash_dev-0.2.26 → freesolo_flash_dev-0.2.28}/tests/test_cost_models.py +0 -0
  229. {freesolo_flash_dev-0.2.26 → freesolo_flash_dev-0.2.28}/tests/test_cost_rewards.py +0 -0
  230. {freesolo_flash_dev-0.2.26 → freesolo_flash_dev-0.2.28}/tests/test_dev_channel.py +0 -0
  231. {freesolo_flash_dev-0.2.26 → freesolo_flash_dev-0.2.28}/tests/test_endpoint_name.py +0 -0
  232. {freesolo_flash_dev-0.2.26 → freesolo_flash_dev-0.2.28}/tests/test_envs_coverage.py +0 -0
  233. {freesolo_flash_dev-0.2.26 → freesolo_flash_dev-0.2.28}/tests/test_export.py +0 -0
  234. {freesolo_flash_dev-0.2.26 → freesolo_flash_dev-0.2.28}/tests/test_github_urlopen_retry.py +0 -0
  235. {freesolo_flash_dev-0.2.26 → freesolo_flash_dev-0.2.28}/tests/test_grpo_mask_aware.py +0 -0
  236. {freesolo_flash_dev-0.2.26 → freesolo_flash_dev-0.2.28}/tests/test_idle_endpoint_reaper.py +0 -0
  237. {freesolo_flash_dev-0.2.26 → freesolo_flash_dev-0.2.28}/tests/test_kernel_cache.py +0 -0
  238. {freesolo_flash_dev-0.2.26 → freesolo_flash_dev-0.2.28}/tests/test_logging.py +0 -0
  239. {freesolo_flash_dev-0.2.26 → freesolo_flash_dev-0.2.28}/tests/test_login_perms.py +0 -0
  240. {freesolo_flash_dev-0.2.26 → freesolo_flash_dev-0.2.28}/tests/test_managed_hf_repo.py +0 -0
  241. {freesolo_flash_dev-0.2.26 → freesolo_flash_dev-0.2.28}/tests/test_metrics_schema_agent_contract.py +0 -0
  242. {freesolo_flash_dev-0.2.26 → freesolo_flash_dev-0.2.28}/tests/test_mig_guard.py +0 -0
  243. {freesolo_flash_dev-0.2.26 → freesolo_flash_dev-0.2.28}/tests/test_multiturn_rollout.py +0 -0
  244. {freesolo_flash_dev-0.2.26 → freesolo_flash_dev-0.2.28}/tests/test_open_model_policy.py +0 -0
  245. {freesolo_flash_dev-0.2.26 → freesolo_flash_dev-0.2.28}/tests/test_packing.py +0 -0
  246. {freesolo_flash_dev-0.2.26 → freesolo_flash_dev-0.2.28}/tests/test_poll_helpers.py +0 -0
  247. {freesolo_flash_dev-0.2.26 → freesolo_flash_dev-0.2.28}/tests/test_preflight.py +0 -0
  248. {freesolo_flash_dev-0.2.26 → freesolo_flash_dev-0.2.28}/tests/test_provider_teardown_robustness.py +0 -0
  249. {freesolo_flash_dev-0.2.26 → freesolo_flash_dev-0.2.28}/tests/test_providers_symmetry.py +0 -0
  250. {freesolo_flash_dev-0.2.26 → freesolo_flash_dev-0.2.28}/tests/test_realized_cost.py +0 -0
  251. {freesolo_flash_dev-0.2.26 → freesolo_flash_dev-0.2.28}/tests/test_runpod_api_delete.py +0 -0
  252. {freesolo_flash_dev-0.2.26 → freesolo_flash_dev-0.2.28}/tests/test_runpod_key_fingerprint.py +0 -0
  253. {freesolo_flash_dev-0.2.26 → freesolo_flash_dev-0.2.28}/tests/test_runpod_key_waterfall.py +0 -0
  254. {freesolo_flash_dev-0.2.26 → freesolo_flash_dev-0.2.28}/tests/test_runpod_slots.py +0 -0
  255. {freesolo_flash_dev-0.2.26 → freesolo_flash_dev-0.2.28}/tests/test_serve.py +0 -0
  256. {freesolo_flash_dev-0.2.26 → freesolo_flash_dev-0.2.28}/tests/test_server_db.py +0 -0
  257. {freesolo_flash_dev-0.2.26 → freesolo_flash_dev-0.2.28}/tests/test_serving_contract.py +0 -0
  258. {freesolo_flash_dev-0.2.26 → freesolo_flash_dev-0.2.28}/tests/test_update_check.py +0 -0
  259. {freesolo_flash_dev-0.2.26 → freesolo_flash_dev-0.2.28}/tests/test_version.py +0 -0
  260. {freesolo_flash_dev-0.2.26 → freesolo_flash_dev-0.2.28}/tests/test_vl_weight_sync.py +0 -0
  261. {freesolo_flash_dev-0.2.26 → freesolo_flash_dev-0.2.28}/tests/test_worker_dryrun.py +0 -0
  262. {freesolo_flash_dev-0.2.26 → freesolo_flash_dev-0.2.28}/tests/test_worker_hardexit.py +0 -0
  263. {freesolo_flash_dev-0.2.26 → freesolo_flash_dev-0.2.28}/tests/test_worker_image.py +0 -0
  264. {freesolo_flash_dev-0.2.26 → freesolo_flash_dev-0.2.28}/tests/test_worker_init_heartbeat.py +0 -0
  265. {freesolo_flash_dev-0.2.26 → freesolo_flash_dev-0.2.28}/tests/test_worker_stack.py +0 -0
  266. {freesolo_flash_dev-0.2.26 → freesolo_flash_dev-0.2.28}/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
@@ -0,0 +1,245 @@
1
+ name: flash worker kernel-cache (per-arch)
2
+
3
+ # Builds per-SM worker images with the compiled-kernel mega-cache baked in, killing the ~10-15 min
4
+ # first-use JIT on a cold worker (the regression #194 reintroduced). Each matrix leg:
5
+ # 1. offloads the warmup to a RunPod GPU of that arch (GH runners have none) -> build/kernel_cache,
6
+ # 2. docker build --build-arg BUILD_KERNEL_CACHE=true -> ghcr.io/freesolo-co/flash-worker:cu128-<sm>,
7
+ # 3. pushes it. Activate by setting FLASH_WORKER_IMAGE_PER_SM=1 on the control plane so the
8
+ # allocator selects the cu128-<sm> tag per GPU class (see flash/providers/runpod/train/deps.py).
9
+ #
10
+ # Depends on the base ghcr.io/freesolo-co/flash-worker:cu128 image existing (worker-image.yml) — the
11
+ # warmup runs INSIDE it so the cache matches the image's pinned torch/triton/fla/liger toolchain.
12
+ #
13
+ # Secrets: RUNPOD_API_KEY (the warmup GPU pod) + HF_TOKEN (the temp dataset that ferries code + the
14
+ # cache artifact) are pulled from Infisical (/flash, prod) via the bootstrap INFISICAL_CLIENT_ID /
15
+ # CLIENT_SECRET / PROJECT_ID repo secrets; 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.
19
+
20
+ on:
21
+ workflow_dispatch:
22
+ inputs:
23
+ sms:
24
+ description: "comma-separated sm list to bake; default is all validated arches"
25
+ default: "sm80,sm86,sm89,sm90,sm120"
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: ""
51
+
52
+ permissions:
53
+ contents: read
54
+ packages: write
55
+
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.
61
+ bake:
62
+ runs-on: ubuntu-24.04-8core
63
+ strategy:
64
+ fail-fast: false
65
+ matrix:
66
+ include:
67
+ - {
68
+ sm: sm80,
69
+ arch: "8.0",
70
+ gpu_type_id: "NVIDIA A100 80GB PCIe",
71
+ allowed_cuda: "",
72
+ }
73
+ - {
74
+ sm: sm86,
75
+ arch: "8.6",
76
+ gpu_type_id: "NVIDIA RTX A6000",
77
+ allowed_cuda: "",
78
+ }
79
+ - {
80
+ sm: sm89,
81
+ arch: "8.9",
82
+ gpu_type_id: "NVIDIA GeForce RTX 4090",
83
+ allowed_cuda: "",
84
+ }
85
+ - {
86
+ sm: sm90,
87
+ arch: "9.0",
88
+ gpu_type_id: "NVIDIA H100 80GB HBM3",
89
+ allowed_cuda: "",
90
+ }
91
+ # Blackwell needs CUDA-13 hosts to JIT its PTX (matches min_cuda_for in the provider). Bake
92
+ # sm120 on the RTX Pro 6000 (Server Edition): it's the same sm120 (cache is sm-keyed, so it's
93
+ # valid for RTX 5090 too) but has far better secure-cloud on-demand capacity -- the RTX 5090
94
+ # pool repeatedly returned "machine does not have the resources" at create_pod.
95
+ - {
96
+ sm: sm120,
97
+ arch: "12.0",
98
+ gpu_type_id: "NVIDIA RTX PRO 6000 Blackwell Server Edition",
99
+ allowed_cuda: "13.0",
100
+ }
101
+ # Datacenter Blackwell (sm100, distinct from the sm120 RTX Pro 6000). B200 has 180 GB and
102
+ # good secure-cloud capacity. CUDA-13 host like the other Blackwell parts. NOT in the default
103
+ # `sms` list yet (B200 is unvalidated) -- bake it explicitly via `sms=sm100` until a smoke
104
+ # passes, then add it to the default.
105
+ - {
106
+ sm: sm100,
107
+ arch: "10.0",
108
+ gpu_type_id: "NVIDIA B200",
109
+ allowed_cuda: "13.0",
110
+ }
111
+ steps:
112
+ # Gate FIRST (no checkout needed) so skipped arches do no crane / checkout / build work.
113
+ - name: Should bake ${{ matrix.sm }}?
114
+ id: gate
115
+ run: |
116
+ req="${{ inputs.sms || 'sm80,sm86,sm89,sm90,sm120' }}"
117
+ req="${req// /}" # tolerate spaces, e.g. "sm80, sm86"
118
+ case ",$req," in
119
+ *,${{ matrix.sm }},*) echo "run=true" >> "$GITHUB_OUTPUT" ;;
120
+ *) echo "run=false" >> "$GITHUB_OUTPUT"; echo "skipping ${{ matrix.sm }}" ;;
121
+ esac
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
+
169
+ - name: Install uv
170
+ if: steps.gate.outputs.run == 'true'
171
+ uses: astral-sh/setup-uv@v5
172
+ with:
173
+ # no cache: the post-run cache-prune calls `uv`, but the "Free disk space" step deletes
174
+ # /opt/hostedtoolcache (where setup-uv put uv), so the post step fails ("uv not found") and
175
+ # marks the whole job red even though the bake + push already succeeded.
176
+ enable-cache: false
177
+
178
+ - name: Sync deps (flash + runpod + hf)
179
+ if: steps.gate.outputs.run == 'true'
180
+ run: uv sync --extra server
181
+
182
+ - name: Install Infisical CLI
183
+ if: steps.gate.outputs.run == 'true'
184
+ run: |
185
+ curl -1sLf 'https://dl.cloudsmith.io/public/infisical/infisical-cli/setup.deb.sh' | sudo -E bash
186
+ sudo apt-get update && sudo apt-get install -y infisical
187
+
188
+ # RUNPOD_API_KEY + HF_TOKEN come from Infisical (/flash, prod) -- mirrors infisical-entrypoint.sh;
189
+ # the CLI takes the project UUID directly (the secrets-action wants a slug). `env -u
190
+ # FLASH_CHALK_SPEC` drops any chalk-spec override living in /flash so the bake always warms the
191
+ # repo-default chalk (the value the fingerprint hashed) -- otherwise the image could be warmed with
192
+ # one chalk and labeled with another. BASE_IMAGE is digest-pinned so the warm runs inside the EXACT
193
+ # base the per-arch tag will sit on.
194
+ - name: Warm kernels on a RunPod ${{ matrix.sm }} GPU -> build/kernel_cache
195
+ if: steps.gate.outputs.run == 'true'
196
+ env:
197
+ INFISICAL_CLIENT_ID: ${{ secrets.INFISICAL_CLIENT_ID }}
198
+ INFISICAL_CLIENT_SECRET: ${{ secrets.INFISICAL_CLIENT_SECRET }}
199
+ INFISICAL_PROJECT_ID: ${{ secrets.INFISICAL_PROJECT_ID }}
200
+ BASE_IMAGE: ${{ steps.base.outputs.ref }}
201
+ run: |
202
+ INFISICAL_TOKEN="$(infisical login --method=universal-auth \
203
+ --client-id="$INFISICAL_CLIENT_ID" --client-secret="$INFISICAL_CLIENT_SECRET" \
204
+ --silent --plain)"
205
+ export INFISICAL_TOKEN
206
+ infisical run --projectId "$INFISICAL_PROJECT_ID" --env prod --path /flash -- \
207
+ env -u FLASH_CHALK_SPEC \
208
+ uv run python docker/bake_kernel_cache.py \
209
+ --arch "${{ matrix.arch }}" --sm "${{ matrix.sm }}" \
210
+ --gpu-type-id "${{ matrix.gpu_type_id }}" \
211
+ --allowed-cuda "${{ matrix.allowed_cuda }}" \
212
+ --image "$BASE_IMAGE" \
213
+ --out build/kernel_cache
214
+
215
+ - name: Free disk space
216
+ if: steps.gate.outputs.run == 'true'
217
+ run: |
218
+ sudo rm -rf /usr/share/dotnet /opt/ghc /usr/local/.ghcup \
219
+ /usr/local/lib/android /opt/hostedtoolcache /usr/share/swift \
220
+ /usr/local/share/boost /usr/local/lib/node_modules \
221
+ /usr/local/share/powershell /usr/share/miniconda || true
222
+ sudo apt-get clean || true
223
+ sudo docker image prune -af || true
224
+ df -h /
225
+
226
+ - uses: docker/setup-buildx-action@v3
227
+ if: steps.gate.outputs.run == 'true'
228
+
229
+ # thin layer FROM the SAME base the warmup ran inside -> the cache toolchain always matches the
230
+ # shipped image (rebuilding the full Dockerfile.worker from the checkout could drift from the
231
+ # published base and bake a cache that silently won't load). GHCR auth from the login step above.
232
+ - name: Build + push baked per-sm image (thin layer on the warmed base)
233
+ if: steps.gate.outputs.run == 'true'
234
+ uses: docker/build-push-action@v6
235
+ with:
236
+ context: .
237
+ file: docker/Dockerfile.kernelcache
238
+ push: true
239
+ tags: ghcr.io/freesolo-co/flash-worker:cu128-${{ matrix.sm }}
240
+ provenance: false
241
+ build-args: |
242
+ BASE=${{ steps.base.outputs.ref }}
243
+ FP_CACHE=${{ steps.base.outputs.fp_cache }}
244
+ FP_BASE=${{ steps.base.outputs.fp_base }}
245
+ 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.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: freesolo-flash-dev
3
- Version: 0.2.26
3
+ Version: 0.2.28
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