@simulatte/doppler 0.1.0

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 (1182) hide show
  1. package/BRANDING.md +14 -0
  2. package/LICENSE +201 -0
  3. package/NOTICE +5 -0
  4. package/README.md +85 -0
  5. package/SECURITY.md +19 -0
  6. package/package.json +144 -0
  7. package/src/adapters/adapter-manager.d.ts +200 -0
  8. package/src/adapters/adapter-manager.js +509 -0
  9. package/src/adapters/adapter-manifest.d.ts +290 -0
  10. package/src/adapters/adapter-manifest.js +320 -0
  11. package/src/adapters/adapter-registry.d.ts +192 -0
  12. package/src/adapters/adapter-registry.js +466 -0
  13. package/src/adapters/index.d.ts +89 -0
  14. package/src/adapters/index.js +42 -0
  15. package/src/adapters/lora-loader.d.ts +105 -0
  16. package/src/adapters/lora-loader.js +397 -0
  17. package/src/bootstrap.d.ts +1 -0
  18. package/src/bootstrap.js +30 -0
  19. package/src/bridge/extension/background.d.ts +14 -0
  20. package/src/bridge/extension/background.js +168 -0
  21. package/src/bridge/extension/manifest.json +34 -0
  22. package/src/bridge/extension-client.d.ts +109 -0
  23. package/src/bridge/extension-client.js +369 -0
  24. package/src/bridge/index.d.ts +68 -0
  25. package/src/bridge/index.js +51 -0
  26. package/src/bridge/protocol.d.ts +96 -0
  27. package/src/bridge/protocol.js +130 -0
  28. package/src/browser/browser-converter.d.ts +71 -0
  29. package/src/browser/browser-converter.js +947 -0
  30. package/src/browser/file-picker.d.ts +63 -0
  31. package/src/browser/file-picker.js +275 -0
  32. package/src/browser/gguf-importer.d.ts +136 -0
  33. package/src/browser/gguf-importer.js +532 -0
  34. package/src/browser/gguf-parser-browser.d.ts +14 -0
  35. package/src/browser/gguf-parser-browser.js +17 -0
  36. package/src/browser/quantization.d.ts +69 -0
  37. package/src/browser/quantization.js +328 -0
  38. package/src/browser/safetensors-parser-browser.d.ts +193 -0
  39. package/src/browser/safetensors-parser-browser.js +264 -0
  40. package/src/browser/shard-io-browser.d.ts +57 -0
  41. package/src/browser/shard-io-browser.js +89 -0
  42. package/src/browser/tensor-source-download.d.ts +27 -0
  43. package/src/browser/tensor-source-download.js +239 -0
  44. package/src/browser/tensor-source-file.d.ts +26 -0
  45. package/src/browser/tensor-source-file.js +53 -0
  46. package/src/browser/tensor-source-http.d.ts +28 -0
  47. package/src/browser/tensor-source-http.js +126 -0
  48. package/src/client/doppler-provider/generation.d.ts +25 -0
  49. package/src/client/doppler-provider/generation.js +114 -0
  50. package/src/client/doppler-provider/index.d.ts +2 -0
  51. package/src/client/doppler-provider/index.js +3 -0
  52. package/src/client/doppler-provider/model-manager.d.ts +61 -0
  53. package/src/client/doppler-provider/model-manager.js +667 -0
  54. package/src/client/doppler-provider/provider.d.ts +5 -0
  55. package/src/client/doppler-provider/provider.js +102 -0
  56. package/src/client/doppler-provider/source-runtime.d.ts +22 -0
  57. package/src/client/doppler-provider/source-runtime.js +522 -0
  58. package/src/client/doppler-provider/types.d.ts +127 -0
  59. package/src/client/doppler-provider/types.js +17 -0
  60. package/src/client/doppler-provider.d.ts +46 -0
  61. package/src/client/doppler-provider.js +36 -0
  62. package/src/config/README.md +69 -0
  63. package/src/config/backward-registry-loader.d.ts +3 -0
  64. package/src/config/backward-registry-loader.js +8 -0
  65. package/src/config/index.d.ts +63 -0
  66. package/src/config/index.js +31 -0
  67. package/src/config/kernel-path-loader.d.ts +149 -0
  68. package/src/config/kernel-path-loader.js +534 -0
  69. package/src/config/kernels/backward-registry.json +99 -0
  70. package/src/config/kernels/kernel-ref-digests.d.ts +1 -0
  71. package/src/config/kernels/kernel-ref-digests.js +214 -0
  72. package/src/config/kernels/kernel-ref.d.ts +17 -0
  73. package/src/config/kernels/kernel-ref.js +75 -0
  74. package/src/config/kernels/moe/gpt-oss.paths.json +49 -0
  75. package/src/config/kernels/registry.d.ts +86 -0
  76. package/src/config/kernels/registry.js +103 -0
  77. package/src/config/kernels/registry.json +6771 -0
  78. package/src/config/loader.d.ts +57 -0
  79. package/src/config/loader.js +513 -0
  80. package/src/config/merge.d.ts +142 -0
  81. package/src/config/merge.js +389 -0
  82. package/src/config/param-categories.d.ts +17 -0
  83. package/src/config/param-categories.js +72 -0
  84. package/src/config/param-validator.d.ts +26 -0
  85. package/src/config/param-validator.js +235 -0
  86. package/src/config/platforms/amd-rdna3.json +16 -0
  87. package/src/config/platforms/apple-m1.json +16 -0
  88. package/src/config/platforms/apple-m2.json +16 -0
  89. package/src/config/platforms/apple-m3.json +16 -0
  90. package/src/config/platforms/generic.json +14 -0
  91. package/src/config/platforms/loader.d.ts +65 -0
  92. package/src/config/platforms/loader.js +153 -0
  93. package/src/config/platforms/nvidia-rtx30.json +16 -0
  94. package/src/config/platforms/nvidia-rtx40.json +16 -0
  95. package/src/config/presets/kernel-paths/embeddinggemma-f16-f32a.json +60 -0
  96. package/src/config/presets/kernel-paths/embeddinggemma-f32-f32a.json +60 -0
  97. package/src/config/presets/kernel-paths/embeddinggemma-q4k-dequant-f32a.json +60 -0
  98. package/src/config/presets/kernel-paths/gemma2-f16-f16a.json +61 -0
  99. package/src/config/presets/kernel-paths/gemma2-f16-f32a.json +60 -0
  100. package/src/config/presets/kernel-paths/gemma2-q4k-dequant-f16a.json +61 -0
  101. package/src/config/presets/kernel-paths/gemma2-q4k-dequant-f32a.json +60 -0
  102. package/src/config/presets/kernel-paths/gemma2-q4k-fused-f32a.json +57 -0
  103. package/src/config/presets/kernel-paths/gemma3-f16-fused-f16a-online.json +200 -0
  104. package/src/config/presets/kernel-paths/gemma3-f16-fused-f32a-online.json +223 -0
  105. package/src/config/presets/kernel-paths/gemma3-q4k-dequant-f16a-online.json +60 -0
  106. package/src/config/presets/kernel-paths/gemma3-q4k-dequant-f32a-online.json +61 -0
  107. package/src/config/presets/kernel-paths/gemma3-q4k-dequant-f32a.json +61 -0
  108. package/src/config/presets/kernel-paths/lfm2-q4k-dequant-f32a-online.json +61 -0
  109. package/src/config/presets/kernel-paths/registry.json +103 -0
  110. package/src/config/presets/models/deepseek.json +20 -0
  111. package/src/config/presets/models/diffusion.json +10 -0
  112. package/src/config/presets/models/embeddinggemma.json +74 -0
  113. package/src/config/presets/models/functiongemma.json +31 -0
  114. package/src/config/presets/models/gemma2.json +59 -0
  115. package/src/config/presets/models/gemma3.json +75 -0
  116. package/src/config/presets/models/gpt-oss.json +68 -0
  117. package/src/config/presets/models/kimi-k2.json +25 -0
  118. package/src/config/presets/models/lfm2.json +83 -0
  119. package/src/config/presets/models/llama3.json +40 -0
  120. package/src/config/presets/models/mamba.json +34 -0
  121. package/src/config/presets/models/mixtral.json +37 -0
  122. package/src/config/presets/models/modernbert.json +32 -0
  123. package/src/config/presets/models/qwen3.json +41 -0
  124. package/src/config/presets/models/transformer.json +73 -0
  125. package/src/config/presets/models/translategemma.json +30 -0
  126. package/src/config/presets/platforms/nvidia-gb200-8gpu.json +45 -0
  127. package/src/config/presets/platforms/nvidia-gb200-nvl72.json +45 -0
  128. package/src/config/presets/platforms/nvidia-gh200-nvl2.json +44 -0
  129. package/src/config/presets/platforms/nvidia-gh200.json +44 -0
  130. package/src/config/presets/runtime/compute/f16-activations.json +30 -0
  131. package/src/config/presets/runtime/compute/f16-batched.json +32 -0
  132. package/src/config/presets/runtime/default.json +101 -0
  133. package/src/config/presets/runtime/diagnostics/debug-logits.json +53 -0
  134. package/src/config/presets/runtime/experiments/bench/gemma3-bench-q4k.json +53 -0
  135. package/src/config/presets/runtime/experiments/debug/gemma3-debug-q4k.json +210 -0
  136. package/src/config/presets/runtime/experiments/verify/gemma3-verify.json +39 -0
  137. package/src/config/presets/runtime/kernels/dequant-f16-q4k.json +20 -0
  138. package/src/config/presets/runtime/kernels/dequant-f32-q4k.json +20 -0
  139. package/src/config/presets/runtime/kernels/fused-q4k.json +20 -0
  140. package/src/config/presets/runtime/kernels/safe-q4k.json +20 -0
  141. package/src/config/presets/runtime/model/gemma2-debug.json +77 -0
  142. package/src/config/presets/runtime/model/gemma2-pipeline-debug.json +66 -0
  143. package/src/config/presets/runtime/model/gemma2-pipeline.json +75 -0
  144. package/src/config/presets/runtime/model/gemma3-layer-probe.json +85 -0
  145. package/src/config/presets/runtime/modes/bench.json +37 -0
  146. package/src/config/presets/runtime/modes/debug.json +39 -0
  147. package/src/config/presets/runtime/modes/default.json +10 -0
  148. package/src/config/presets/runtime/modes/embedding-bench.json +28 -0
  149. package/src/config/presets/runtime/modes/embedding.json +54 -0
  150. package/src/config/presets/runtime/modes/low-memory.json +40 -0
  151. package/src/config/presets/runtime/modes/production.json +48 -0
  152. package/src/config/presets/runtime/modes/simulation.json +30 -0
  153. package/src/config/presets/runtime/modes/trace-layers.json +126 -0
  154. package/src/config/presets/runtime/platform/metal-apple-q4k.json +11 -0
  155. package/src/config/runtime-merge.d.ts +5 -0
  156. package/src/config/runtime-merge.js +21 -0
  157. package/src/config/runtime.d.ts +28 -0
  158. package/src/config/runtime.js +56 -0
  159. package/src/config/schema/adapter.schema.d.ts +53 -0
  160. package/src/config/schema/adapter.schema.js +60 -0
  161. package/src/config/schema/backward-registry.schema.d.ts +14 -0
  162. package/src/config/schema/backward-registry.schema.js +46 -0
  163. package/src/config/schema/benchmark.schema.d.ts +54 -0
  164. package/src/config/schema/benchmark.schema.js +74 -0
  165. package/src/config/schema/bridge.schema.d.ts +25 -0
  166. package/src/config/schema/bridge.schema.js +22 -0
  167. package/src/config/schema/buffer-pool.schema.d.ts +92 -0
  168. package/src/config/schema/buffer-pool.schema.js +50 -0
  169. package/src/config/schema/conversion.schema.d.ts +183 -0
  170. package/src/config/schema/conversion.schema.js +13 -0
  171. package/src/config/schema/converter.schema.d.ts +123 -0
  172. package/src/config/schema/converter.schema.js +136 -0
  173. package/src/config/schema/debug.schema.d.ts +245 -0
  174. package/src/config/schema/debug.schema.js +106 -0
  175. package/src/config/schema/diffusion.schema.d.ts +88 -0
  176. package/src/config/schema/diffusion.schema.js +62 -0
  177. package/src/config/schema/distill-training.schema.d.ts +48 -0
  178. package/src/config/schema/distill-training.schema.js +139 -0
  179. package/src/config/schema/distribution.schema.d.ts +155 -0
  180. package/src/config/schema/distribution.schema.js +81 -0
  181. package/src/config/schema/doppler.schema.d.ts +75 -0
  182. package/src/config/schema/doppler.schema.js +352 -0
  183. package/src/config/schema/ecosystem.schema.d.ts +255 -0
  184. package/src/config/schema/ecosystem.schema.js +534 -0
  185. package/src/config/schema/emulation.schema.d.ts +351 -0
  186. package/src/config/schema/emulation.schema.js +299 -0
  187. package/src/config/schema/energy.schema.d.ts +102 -0
  188. package/src/config/schema/energy.schema.js +72 -0
  189. package/src/config/schema/execution-v0.schema.d.ts +187 -0
  190. package/src/config/schema/execution-v0.schema.js +55 -0
  191. package/src/config/schema/gpu-cache.schema.d.ts +26 -0
  192. package/src/config/schema/gpu-cache.schema.js +8 -0
  193. package/src/config/schema/harness.schema.d.ts +32 -0
  194. package/src/config/schema/harness.schema.js +20 -0
  195. package/src/config/schema/hotswap.schema.d.ts +55 -0
  196. package/src/config/schema/hotswap.schema.js +18 -0
  197. package/src/config/schema/index.d.ts +863 -0
  198. package/src/config/schema/index.js +471 -0
  199. package/src/config/schema/inference-defaults.schema.d.ts +276 -0
  200. package/src/config/schema/inference-defaults.schema.js +185 -0
  201. package/src/config/schema/inference.schema.d.ts +289 -0
  202. package/src/config/schema/inference.schema.js +39 -0
  203. package/src/config/schema/intent-bundle.schema.d.ts +28 -0
  204. package/src/config/schema/intent-bundle.schema.js +12 -0
  205. package/src/config/schema/kernel-path.schema.d.ts +173 -0
  206. package/src/config/schema/kernel-path.schema.js +9 -0
  207. package/src/config/schema/kernel-registry.schema.d.ts +199 -0
  208. package/src/config/schema/kernel-registry.schema.js +46 -0
  209. package/src/config/schema/kernel-thresholds.schema.d.ts +302 -0
  210. package/src/config/schema/kernel-thresholds.schema.js +187 -0
  211. package/src/config/schema/kernel-warmup.schema.d.ts +19 -0
  212. package/src/config/schema/kernel-warmup.schema.js +5 -0
  213. package/src/config/schema/kvcache.schema.d.ts +131 -0
  214. package/src/config/schema/kvcache.schema.js +31 -0
  215. package/src/config/schema/loading.schema.d.ts +153 -0
  216. package/src/config/schema/loading.schema.js +84 -0
  217. package/src/config/schema/lora.schema.d.ts +12 -0
  218. package/src/config/schema/lora.schema.js +12 -0
  219. package/src/config/schema/manifest.schema.d.ts +500 -0
  220. package/src/config/schema/manifest.schema.js +130 -0
  221. package/src/config/schema/memory-limits.schema.d.ts +107 -0
  222. package/src/config/schema/memory-limits.schema.js +57 -0
  223. package/src/config/schema/moe.schema.d.ts +78 -0
  224. package/src/config/schema/moe.schema.js +31 -0
  225. package/src/config/schema/platform.schema.d.ts +121 -0
  226. package/src/config/schema/platform.schema.js +1 -0
  227. package/src/config/schema/preset.schema.d.ts +124 -0
  228. package/src/config/schema/preset.schema.js +1 -0
  229. package/src/config/schema/quantization-defaults.schema.d.ts +34 -0
  230. package/src/config/schema/quantization-defaults.schema.js +5 -0
  231. package/src/config/schema/quantization.schema.d.ts +10 -0
  232. package/src/config/schema/quantization.schema.js +33 -0
  233. package/src/config/schema/shared-runtime.schema.d.ts +75 -0
  234. package/src/config/schema/shared-runtime.schema.js +45 -0
  235. package/src/config/schema/speculative.schema.d.ts +21 -0
  236. package/src/config/schema/speculative.schema.js +11 -0
  237. package/src/config/schema/storage.schema.d.ts +123 -0
  238. package/src/config/schema/storage.schema.js +66 -0
  239. package/src/config/schema/tooling.schema.d.ts +29 -0
  240. package/src/config/schema/tooling.schema.js +12 -0
  241. package/src/config/schema/training-metrics.schema.d.ts +89 -0
  242. package/src/config/schema/training-metrics.schema.js +374 -0
  243. package/src/config/schema/training.schema.d.ts +88 -0
  244. package/src/config/schema/training.schema.js +106 -0
  245. package/src/config/schema/tuner.schema.d.ts +39 -0
  246. package/src/config/schema/tuner.schema.js +13 -0
  247. package/src/config/schema/ul-training.schema.d.ts +61 -0
  248. package/src/config/schema/ul-training.schema.js +140 -0
  249. package/src/config/schema/units.schema.d.ts +27 -0
  250. package/src/config/schema/units.schema.js +26 -0
  251. package/src/config/training-defaults.d.ts +24 -0
  252. package/src/config/training-defaults.js +91 -0
  253. package/src/converter/conversion-plan.d.ts +64 -0
  254. package/src/converter/conversion-plan.js +472 -0
  255. package/src/converter/core.d.ts +247 -0
  256. package/src/converter/core.js +1329 -0
  257. package/src/converter/execution-v0-manifest.d.ts +15 -0
  258. package/src/converter/execution-v0-manifest.js +146 -0
  259. package/src/converter/index.d.ts +98 -0
  260. package/src/converter/index.js +59 -0
  261. package/src/converter/manifest-inference.d.ts +20 -0
  262. package/src/converter/manifest-inference.js +492 -0
  263. package/src/converter/parsers/diffusion.d.ts +50 -0
  264. package/src/converter/parsers/diffusion.js +270 -0
  265. package/src/converter/parsers/gguf.d.ts +22 -0
  266. package/src/converter/parsers/gguf.js +46 -0
  267. package/src/converter/parsers/index.d.ts +21 -0
  268. package/src/converter/parsers/index.js +12 -0
  269. package/src/converter/parsers/transformer.d.ts +16 -0
  270. package/src/converter/parsers/transformer.js +25 -0
  271. package/src/converter/quantization-info.d.ts +37 -0
  272. package/src/converter/quantization-info.js +398 -0
  273. package/src/converter/quantizer.d.ts +96 -0
  274. package/src/converter/quantizer.js +422 -0
  275. package/src/converter/rope-config.d.ts +15 -0
  276. package/src/converter/rope-config.js +218 -0
  277. package/src/converter/shard-packer.d.ts +138 -0
  278. package/src/converter/shard-packer.js +422 -0
  279. package/src/converter/tokenizer-utils.d.ts +11 -0
  280. package/src/converter/tokenizer-utils.js +87 -0
  281. package/src/debug/config.d.ts +78 -0
  282. package/src/debug/config.js +235 -0
  283. package/src/debug/history.d.ts +65 -0
  284. package/src/debug/history.js +71 -0
  285. package/src/debug/index.d.ts +268 -0
  286. package/src/debug/index.js +192 -0
  287. package/src/debug/log.d.ts +46 -0
  288. package/src/debug/log.js +132 -0
  289. package/src/debug/perf.d.ts +33 -0
  290. package/src/debug/perf.js +51 -0
  291. package/src/debug/reference/README.md +114 -0
  292. package/src/debug/reference/hf_attn_debug.py +114 -0
  293. package/src/debug/reference/hf_embed_check.py +89 -0
  294. package/src/debug/reference/hf_layer_out.py +100 -0
  295. package/src/debug/reference/hf_rope_check.py +116 -0
  296. package/src/debug/reference/hf_weights.py +75 -0
  297. package/src/debug/signals.d.ts +63 -0
  298. package/src/debug/signals.js +33 -0
  299. package/src/debug/stats.d.ts +47 -0
  300. package/src/debug/stats.js +160 -0
  301. package/src/debug/tensor.d.ts +123 -0
  302. package/src/debug/tensor.js +257 -0
  303. package/src/debug/trace.d.ts +17 -0
  304. package/src/debug/trace.js +167 -0
  305. package/src/diffusion/image-regression.d.ts +31 -0
  306. package/src/diffusion/image-regression.js +107 -0
  307. package/src/diffusion/index.d.ts +8 -0
  308. package/src/diffusion/index.js +8 -0
  309. package/src/distribution/p2p-control-plane.d.ts +52 -0
  310. package/src/distribution/p2p-control-plane.js +232 -0
  311. package/src/distribution/p2p-observability.d.ts +116 -0
  312. package/src/distribution/p2p-observability.js +267 -0
  313. package/src/distribution/p2p-transport-contract.d.ts +57 -0
  314. package/src/distribution/p2p-transport-contract.js +310 -0
  315. package/src/distribution/p2p-webrtc-browser.d.ts +37 -0
  316. package/src/distribution/p2p-webrtc-browser.js +434 -0
  317. package/src/distribution/shard-delivery.d.ts +251 -0
  318. package/src/distribution/shard-delivery.js +2096 -0
  319. package/src/energy/index.d.ts +2 -0
  320. package/src/energy/index.js +2 -0
  321. package/src/errors/doppler-error.d.ts +21 -0
  322. package/src/errors/doppler-error.js +25 -0
  323. package/src/errors/index.d.ts +1 -0
  324. package/src/errors/index.js +1 -0
  325. package/src/formats/gguf/index.d.ts +8 -0
  326. package/src/formats/gguf/index.js +4 -0
  327. package/src/formats/gguf/types.d.ts +137 -0
  328. package/src/formats/gguf/types.js +443 -0
  329. package/src/formats/index.d.ts +51 -0
  330. package/src/formats/index.js +13 -0
  331. package/src/formats/rdrr/classification.d.ts +39 -0
  332. package/src/formats/rdrr/classification.js +275 -0
  333. package/src/formats/rdrr/groups.d.ts +27 -0
  334. package/src/formats/rdrr/groups.js +76 -0
  335. package/src/formats/rdrr/index.d.ts +25 -0
  336. package/src/formats/rdrr/index.js +19 -0
  337. package/src/formats/rdrr/manifest.d.ts +32 -0
  338. package/src/formats/rdrr/manifest.js +108 -0
  339. package/src/formats/rdrr/parsing.d.ts +23 -0
  340. package/src/formats/rdrr/parsing.js +101 -0
  341. package/src/formats/rdrr/tensor-config-validator.d.ts +42 -0
  342. package/src/formats/rdrr/tensor-config-validator.js +156 -0
  343. package/src/formats/rdrr/types.d.ts +200 -0
  344. package/src/formats/rdrr/types.js +16 -0
  345. package/src/formats/rdrr/validation.d.ts +9 -0
  346. package/src/formats/rdrr/validation.js +200 -0
  347. package/src/formats/safetensors/index.d.ts +8 -0
  348. package/src/formats/safetensors/index.js +4 -0
  349. package/src/formats/safetensors/types.d.ts +67 -0
  350. package/src/formats/safetensors/types.js +102 -0
  351. package/src/formats/tokenizer/index.d.ts +5 -0
  352. package/src/formats/tokenizer/index.js +3 -0
  353. package/src/formats/tokenizer/types.d.ts +9 -0
  354. package/src/formats/tokenizer/types.js +22 -0
  355. package/src/generation/index.d.ts +18 -0
  356. package/src/generation/index.js +12 -0
  357. package/src/gpu/command-recorder.d.ts +175 -0
  358. package/src/gpu/command-recorder.js +473 -0
  359. package/src/gpu/device.d.ts +141 -0
  360. package/src/gpu/device.js +350 -0
  361. package/src/gpu/kernel-runtime.d.ts +20 -0
  362. package/src/gpu/kernel-runtime.js +37 -0
  363. package/src/gpu/kernel-selection-cache.d.ts +13 -0
  364. package/src/gpu/kernel-selection-cache.js +13 -0
  365. package/src/gpu/kernel-selection-log.d.ts +12 -0
  366. package/src/gpu/kernel-selection-log.js +28 -0
  367. package/src/gpu/kernel-selector.d.ts +11 -0
  368. package/src/gpu/kernel-selector.js +10 -0
  369. package/src/gpu/kernel-tuner/benchmarks.d.ts +144 -0
  370. package/src/gpu/kernel-tuner/benchmarks.js +892 -0
  371. package/src/gpu/kernel-tuner/cache.d.ts +55 -0
  372. package/src/gpu/kernel-tuner/cache.js +66 -0
  373. package/src/gpu/kernel-tuner/index.d.ts +59 -0
  374. package/src/gpu/kernel-tuner/index.js +38 -0
  375. package/src/gpu/kernel-tuner/tuner.d.ts +82 -0
  376. package/src/gpu/kernel-tuner/tuner.js +229 -0
  377. package/src/gpu/kernel-tuner/types.d.ts +101 -0
  378. package/src/gpu/kernel-tuner/types.js +4 -0
  379. package/src/gpu/kernel-tuner.d.ts +33 -0
  380. package/src/gpu/kernel-tuner.js +12 -0
  381. package/src/gpu/kernels/README.md +127 -0
  382. package/src/gpu/kernels/attention.d.ts +236 -0
  383. package/src/gpu/kernels/attention.js +1359 -0
  384. package/src/gpu/kernels/attention.wgsl +249 -0
  385. package/src/gpu/kernels/attention_bdpa_decode_f16.wgsl +246 -0
  386. package/src/gpu/kernels/attention_decode.wgsl +233 -0
  387. package/src/gpu/kernels/attention_decode_chunked_f16.wgsl +183 -0
  388. package/src/gpu/kernels/attention_decode_chunked_f16kv.wgsl +208 -0
  389. package/src/gpu/kernels/attention_decode_f16.wgsl +202 -0
  390. package/src/gpu/kernels/attention_decode_f16kv.wgsl +224 -0
  391. package/src/gpu/kernels/attention_decode_online_f16.wgsl +223 -0
  392. package/src/gpu/kernels/attention_decode_online_f16kv.wgsl +225 -0
  393. package/src/gpu/kernels/attention_decode_optimized.wgsl +445 -0
  394. package/src/gpu/kernels/attention_decode_paged_f16.wgsl +172 -0
  395. package/src/gpu/kernels/attention_decode_paged_f16kv.wgsl +174 -0
  396. package/src/gpu/kernels/attention_decode_subgroup.wgsl +233 -0
  397. package/src/gpu/kernels/attention_decode_tiered_f16.wgsl +218 -0
  398. package/src/gpu/kernels/attention_decode_tiered_f16kv.wgsl +220 -0
  399. package/src/gpu/kernels/attention_decode_tiered_int4_f16kv.wgsl +242 -0
  400. package/src/gpu/kernels/attention_decode_tiered_int8_f16kv.wgsl +242 -0
  401. package/src/gpu/kernels/attention_f16.wgsl +214 -0
  402. package/src/gpu/kernels/attention_f16kv.wgsl +242 -0
  403. package/src/gpu/kernels/attention_small.wgsl +260 -0
  404. package/src/gpu/kernels/attention_small_f16.wgsl +240 -0
  405. package/src/gpu/kernels/attention_small_f16kv.wgsl +266 -0
  406. package/src/gpu/kernels/attention_streaming.wgsl +149 -0
  407. package/src/gpu/kernels/attention_streaming_f16.wgsl +147 -0
  408. package/src/gpu/kernels/attention_streaming_f16kv.wgsl +151 -0
  409. package/src/gpu/kernels/backward/adam.d.ts +28 -0
  410. package/src/gpu/kernels/backward/adam.js +199 -0
  411. package/src/gpu/kernels/backward/adam.wgsl +50 -0
  412. package/src/gpu/kernels/backward/attention_backward.d.ts +22 -0
  413. package/src/gpu/kernels/backward/attention_backward.js +276 -0
  414. package/src/gpu/kernels/backward/attention_backward.wgsl +49 -0
  415. package/src/gpu/kernels/backward/bias_add_backward.d.ts +17 -0
  416. package/src/gpu/kernels/backward/bias_add_backward.js +24 -0
  417. package/src/gpu/kernels/backward/bias_add_backward.wgsl +33 -0
  418. package/src/gpu/kernels/backward/conv2d_backward.d.ts +31 -0
  419. package/src/gpu/kernels/backward/conv2d_backward.js +135 -0
  420. package/src/gpu/kernels/backward/conv2d_backward_input.wgsl +83 -0
  421. package/src/gpu/kernels/backward/conv2d_backward_weight.wgsl +70 -0
  422. package/src/gpu/kernels/backward/cross_entropy_backward.d.ts +23 -0
  423. package/src/gpu/kernels/backward/cross_entropy_backward.js +29 -0
  424. package/src/gpu/kernels/backward/cross_entropy_backward.wgsl +39 -0
  425. package/src/gpu/kernels/backward/embed_backward.d.ts +29 -0
  426. package/src/gpu/kernels/backward/embed_backward.js +118 -0
  427. package/src/gpu/kernels/backward/embed_backward.wgsl +73 -0
  428. package/src/gpu/kernels/backward/gelu_backward.d.ts +16 -0
  429. package/src/gpu/kernels/backward/gelu_backward.js +39 -0
  430. package/src/gpu/kernels/backward/gelu_backward.wgsl +38 -0
  431. package/src/gpu/kernels/backward/groupnorm_backward.d.ts +24 -0
  432. package/src/gpu/kernels/backward/groupnorm_backward.js +29 -0
  433. package/src/gpu/kernels/backward/groupnorm_backward.wgsl +143 -0
  434. package/src/gpu/kernels/backward/index.d.ts +17 -0
  435. package/src/gpu/kernels/backward/index.js +23 -0
  436. package/src/gpu/kernels/backward/layernorm_backward.d.ts +22 -0
  437. package/src/gpu/kernels/backward/layernorm_backward.js +135 -0
  438. package/src/gpu/kernels/backward/layernorm_backward.wgsl +194 -0
  439. package/src/gpu/kernels/backward/matmul_backward.d.ts +32 -0
  440. package/src/gpu/kernels/backward/matmul_backward.js +124 -0
  441. package/src/gpu/kernels/backward/matmul_backward.wgsl +90 -0
  442. package/src/gpu/kernels/backward/matmul_transpose_a.wgsl +84 -0
  443. package/src/gpu/kernels/backward/pixel_shuffle_backward.d.ts +22 -0
  444. package/src/gpu/kernels/backward/pixel_shuffle_backward.js +30 -0
  445. package/src/gpu/kernels/backward/pixel_shuffle_backward.wgsl +54 -0
  446. package/src/gpu/kernels/backward/rmsnorm_backward.d.ts +24 -0
  447. package/src/gpu/kernels/backward/rmsnorm_backward.js +101 -0
  448. package/src/gpu/kernels/backward/rmsnorm_backward.wgsl +78 -0
  449. package/src/gpu/kernels/backward/rope_backward.d.ts +25 -0
  450. package/src/gpu/kernels/backward/rope_backward.js +109 -0
  451. package/src/gpu/kernels/backward/rope_backward.wgsl +59 -0
  452. package/src/gpu/kernels/backward/scale_backward.d.ts +16 -0
  453. package/src/gpu/kernels/backward/scale_backward.js +84 -0
  454. package/src/gpu/kernels/backward/scale_backward.wgsl +27 -0
  455. package/src/gpu/kernels/backward/silu_backward.d.ts +16 -0
  456. package/src/gpu/kernels/backward/silu_backward.js +39 -0
  457. package/src/gpu/kernels/backward/silu_backward.wgsl +31 -0
  458. package/src/gpu/kernels/backward/softmax_backward.d.ts +16 -0
  459. package/src/gpu/kernels/backward/softmax_backward.js +43 -0
  460. package/src/gpu/kernels/backward/softmax_backward.wgsl +44 -0
  461. package/src/gpu/kernels/backward/upsample2d_backward.d.ts +21 -0
  462. package/src/gpu/kernels/backward/upsample2d_backward.js +30 -0
  463. package/src/gpu/kernels/backward/upsample2d_backward.wgsl +59 -0
  464. package/src/gpu/kernels/backward/utils.d.ts +45 -0
  465. package/src/gpu/kernels/backward/utils.js +371 -0
  466. package/src/gpu/kernels/bf16_to_f16.wgsl +54 -0
  467. package/src/gpu/kernels/bf16_to_f32.wgsl +70 -0
  468. package/src/gpu/kernels/bias_add.wgsl +40 -0
  469. package/src/gpu/kernels/bias_add_f16.wgsl +44 -0
  470. package/src/gpu/kernels/cast.d.ts +67 -0
  471. package/src/gpu/kernels/cast.js +422 -0
  472. package/src/gpu/kernels/cast_f16_to_f32.wgsl +31 -0
  473. package/src/gpu/kernels/cast_f32_to_f16.wgsl +36 -0
  474. package/src/gpu/kernels/check-finiteness.d.ts +15 -0
  475. package/src/gpu/kernels/check-finiteness.js +149 -0
  476. package/src/gpu/kernels/check-stop.d.ts +31 -0
  477. package/src/gpu/kernels/check-stop.js +181 -0
  478. package/src/gpu/kernels/clamp.d.ts +22 -0
  479. package/src/gpu/kernels/clamp.js +42 -0
  480. package/src/gpu/kernels/clamp.wgsl +24 -0
  481. package/src/gpu/kernels/constants.d.ts +168 -0
  482. package/src/gpu/kernels/constants.js +129 -0
  483. package/src/gpu/kernels/conv2d.d.ts +34 -0
  484. package/src/gpu/kernels/conv2d.js +81 -0
  485. package/src/gpu/kernels/conv2d.wgsl +71 -0
  486. package/src/gpu/kernels/conv2d_f16.wgsl +73 -0
  487. package/src/gpu/kernels/cross_entropy_loss.d.ts +21 -0
  488. package/src/gpu/kernels/cross_entropy_loss.js +54 -0
  489. package/src/gpu/kernels/cross_entropy_loss.wgsl +39 -0
  490. package/src/gpu/kernels/dequant.d.ts +108 -0
  491. package/src/gpu/kernels/dequant.js +524 -0
  492. package/src/gpu/kernels/dequant_f16_out.wgsl +151 -0
  493. package/src/gpu/kernels/dequant_f16_out_vec4.wgsl +149 -0
  494. package/src/gpu/kernels/dequant_f16_rowwise.wgsl +139 -0
  495. package/src/gpu/kernels/dequant_f32_rowwise.wgsl +133 -0
  496. package/src/gpu/kernels/dequant_mxfp4.wgsl +120 -0
  497. package/src/gpu/kernels/dequant_mxfp4_expert.wgsl +129 -0
  498. package/src/gpu/kernels/dequant_mxfp4_expert_f16.wgsl +105 -0
  499. package/src/gpu/kernels/dequant_mxfp4_vec4.wgsl +116 -0
  500. package/src/gpu/kernels/dequant_q6k.wgsl +140 -0
  501. package/src/gpu/kernels/dequant_q8_0.wgsl +98 -0
  502. package/src/gpu/kernels/dequant_shared.wgsl +202 -0
  503. package/src/gpu/kernels/dequant_shared_vec4.wgsl +153 -0
  504. package/src/gpu/kernels/dequant_subgroup.wgsl +202 -0
  505. package/src/gpu/kernels/dispatch.d.ts +157 -0
  506. package/src/gpu/kernels/dispatch.js +235 -0
  507. package/src/gpu/kernels/energy.d.ts +131 -0
  508. package/src/gpu/kernels/energy.js +425 -0
  509. package/src/gpu/kernels/energy_eval.wgsl +26 -0
  510. package/src/gpu/kernels/energy_eval_f16.wgsl +30 -0
  511. package/src/gpu/kernels/energy_quintel_grad.wgsl +92 -0
  512. package/src/gpu/kernels/energy_quintel_grad_f16.wgsl +96 -0
  513. package/src/gpu/kernels/energy_quintel_reduce.wgsl +112 -0
  514. package/src/gpu/kernels/energy_quintel_reduce_f16.wgsl +116 -0
  515. package/src/gpu/kernels/energy_quintel_update.wgsl +92 -0
  516. package/src/gpu/kernels/energy_quintel_update_f16.wgsl +96 -0
  517. package/src/gpu/kernels/energy_update.wgsl +25 -0
  518. package/src/gpu/kernels/energy_update_f16.wgsl +30 -0
  519. package/src/gpu/kernels/feature-check.d.ts +42 -0
  520. package/src/gpu/kernels/feature-check.js +70 -0
  521. package/src/gpu/kernels/fused_ffn.d.ts +65 -0
  522. package/src/gpu/kernels/fused_ffn.js +318 -0
  523. package/src/gpu/kernels/fused_ffn.wgsl +420 -0
  524. package/src/gpu/kernels/fused_ffn_f16.wgsl +213 -0
  525. package/src/gpu/kernels/fused_ffn_q4k.wgsl +375 -0
  526. package/src/gpu/kernels/fused_matmul_q4.wgsl +404 -0
  527. package/src/gpu/kernels/fused_matmul_q4_batched.wgsl +194 -0
  528. package/src/gpu/kernels/fused_matmul_q4_batched_f16.wgsl +170 -0
  529. package/src/gpu/kernels/fused_matmul_q4_batched_f16a.wgsl +154 -0
  530. package/src/gpu/kernels/fused_matmul_q4_f16a.wgsl +219 -0
  531. package/src/gpu/kernels/fused_matmul_q4_multicol_f16.wgsl +216 -0
  532. package/src/gpu/kernels/fused_matmul_q4_multicol_f16a.wgsl +204 -0
  533. package/src/gpu/kernels/fused_matmul_residual.d.ts +46 -0
  534. package/src/gpu/kernels/fused_matmul_residual.js +152 -0
  535. package/src/gpu/kernels/fused_matmul_rmsnorm.d.ts +64 -0
  536. package/src/gpu/kernels/fused_matmul_rmsnorm.js +273 -0
  537. package/src/gpu/kernels/fused_matmul_rmsnorm.wgsl +324 -0
  538. package/src/gpu/kernels/fused_matmul_rmsnorm_f16.wgsl +303 -0
  539. package/src/gpu/kernels/fused_swiglu.wgsl +63 -0
  540. package/src/gpu/kernels/fused_swiglu_f16.wgsl +57 -0
  541. package/src/gpu/kernels/gather.d.ts +64 -0
  542. package/src/gpu/kernels/gather.js +119 -0
  543. package/src/gpu/kernels/gather.wgsl +61 -0
  544. package/src/gpu/kernels/gather_f16.wgsl +65 -0
  545. package/src/gpu/kernels/gather_f16_f16_out.wgsl +55 -0
  546. package/src/gpu/kernels/gather_f16_out.wgsl +55 -0
  547. package/src/gpu/kernels/gather_f16_vec4.wgsl +76 -0
  548. package/src/gpu/kernels/gather_f16_vec4_f16_out.wgsl +68 -0
  549. package/src/gpu/kernels/gather_vec4.wgsl +74 -0
  550. package/src/gpu/kernels/gather_vec4_f16_out.wgsl +68 -0
  551. package/src/gpu/kernels/gelu.d.ts +33 -0
  552. package/src/gpu/kernels/gelu.js +47 -0
  553. package/src/gpu/kernels/gelu.wgsl +64 -0
  554. package/src/gpu/kernels/gelu_f16.wgsl +66 -0
  555. package/src/gpu/kernels/gptoss_mxfp4_expert_fused.wgsl +127 -0
  556. package/src/gpu/kernels/gptoss_router_topk.wgsl +119 -0
  557. package/src/gpu/kernels/groupnorm.d.ts +31 -0
  558. package/src/gpu/kernels/groupnorm.js +91 -0
  559. package/src/gpu/kernels/groupnorm_apply.wgsl +41 -0
  560. package/src/gpu/kernels/groupnorm_apply_f16.wgsl +46 -0
  561. package/src/gpu/kernels/groupnorm_stats.wgsl +76 -0
  562. package/src/gpu/kernels/groupnorm_stats_f16.wgsl +79 -0
  563. package/src/gpu/kernels/index.d.ts +336 -0
  564. package/src/gpu/kernels/index.js +284 -0
  565. package/src/gpu/kernels/kernel-base.d.ts +33 -0
  566. package/src/gpu/kernels/kernel-base.js +46 -0
  567. package/src/gpu/kernels/kernel-configs.d.ts +65 -0
  568. package/src/gpu/kernels/kernel-configs.js +50 -0
  569. package/src/gpu/kernels/kernel-tuning.d.ts +42 -0
  570. package/src/gpu/kernels/kernel-tuning.js +149 -0
  571. package/src/gpu/kernels/kv-quantize.d.ts +37 -0
  572. package/src/gpu/kernels/kv-quantize.js +138 -0
  573. package/src/gpu/kernels/kv_quantize_int4.wgsl +119 -0
  574. package/src/gpu/kernels/kv_quantize_int8.wgsl +119 -0
  575. package/src/gpu/kernels/layernorm.d.ts +37 -0
  576. package/src/gpu/kernels/layernorm.js +80 -0
  577. package/src/gpu/kernels/layernorm.wgsl +121 -0
  578. package/src/gpu/kernels/layernorm_f16.wgsl +103 -0
  579. package/src/gpu/kernels/linear-attention-core.d.ts +39 -0
  580. package/src/gpu/kernels/linear-attention-core.js +535 -0
  581. package/src/gpu/kernels/logit-merge.d.ts +110 -0
  582. package/src/gpu/kernels/logit-merge.js +392 -0
  583. package/src/gpu/kernels/matmul-dispatch.d.ts +38 -0
  584. package/src/gpu/kernels/matmul-dispatch.js +155 -0
  585. package/src/gpu/kernels/matmul-selection.d.ts +87 -0
  586. package/src/gpu/kernels/matmul-selection.js +474 -0
  587. package/src/gpu/kernels/matmul.d.ts +109 -0
  588. package/src/gpu/kernels/matmul.js +271 -0
  589. package/src/gpu/kernels/matmul_f16.wgsl +170 -0
  590. package/src/gpu/kernels/matmul_f16_tiled.wgsl +165 -0
  591. package/src/gpu/kernels/matmul_f16w_f32a.wgsl +89 -0
  592. package/src/gpu/kernels/matmul_f16w_f32a_tiled.wgsl +154 -0
  593. package/src/gpu/kernels/matmul_f32.wgsl +100 -0
  594. package/src/gpu/kernels/matmul_gemv.wgsl +80 -0
  595. package/src/gpu/kernels/matmul_gemv_f16a.wgsl +81 -0
  596. package/src/gpu/kernels/matmul_gemv_residual.wgsl +119 -0
  597. package/src/gpu/kernels/matmul_gemv_residual_f16.wgsl +78 -0
  598. package/src/gpu/kernels/matmul_gemv_subgroup.wgsl +345 -0
  599. package/src/gpu/kernels/matmul_gemv_subgroup_f16a.wgsl +514 -0
  600. package/src/gpu/kernels/modulate.d.ts +29 -0
  601. package/src/gpu/kernels/modulate.js +49 -0
  602. package/src/gpu/kernels/modulate.wgsl +40 -0
  603. package/src/gpu/kernels/modulate_f16.wgsl +43 -0
  604. package/src/gpu/kernels/moe.d.ts +164 -0
  605. package/src/gpu/kernels/moe.js +496 -0
  606. package/src/gpu/kernels/moe_gather.wgsl +170 -0
  607. package/src/gpu/kernels/moe_gather_f16.wgsl +82 -0
  608. package/src/gpu/kernels/moe_gather_vec4.wgsl +74 -0
  609. package/src/gpu/kernels/moe_offsets.wgsl +48 -0
  610. package/src/gpu/kernels/pipeline-cache.d.ts +88 -0
  611. package/src/gpu/kernels/pipeline-cache.js +305 -0
  612. package/src/gpu/kernels/pixel_shuffle.d.ts +27 -0
  613. package/src/gpu/kernels/pixel_shuffle.js +49 -0
  614. package/src/gpu/kernels/pixel_shuffle.wgsl +44 -0
  615. package/src/gpu/kernels/pixel_shuffle_f16.wgsl +47 -0
  616. package/src/gpu/kernels/residual.d.ts +74 -0
  617. package/src/gpu/kernels/residual.js +127 -0
  618. package/src/gpu/kernels/residual.wgsl +53 -0
  619. package/src/gpu/kernels/residual_f16.wgsl +35 -0
  620. package/src/gpu/kernels/residual_f16_vec4.wgsl +47 -0
  621. package/src/gpu/kernels/residual_vec4.wgsl +46 -0
  622. package/src/gpu/kernels/rmsnorm.d.ts +53 -0
  623. package/src/gpu/kernels/rmsnorm.js +140 -0
  624. package/src/gpu/kernels/rmsnorm.wgsl +417 -0
  625. package/src/gpu/kernels/rmsnorm_f16.wgsl +164 -0
  626. package/src/gpu/kernels/rope.d.ts +48 -0
  627. package/src/gpu/kernels/rope.js +53 -0
  628. package/src/gpu/kernels/rope.wgsl +328 -0
  629. package/src/gpu/kernels/rope_f16.wgsl +271 -0
  630. package/src/gpu/kernels/rule-matcher.d.ts +30 -0
  631. package/src/gpu/kernels/rule-matcher.js +42 -0
  632. package/src/gpu/kernels/rule-registry.d.ts +7 -0
  633. package/src/gpu/kernels/rule-registry.js +41 -0
  634. package/src/gpu/kernels/sample.d.ts +75 -0
  635. package/src/gpu/kernels/sample.js +578 -0
  636. package/src/gpu/kernels/sample.wgsl +377 -0
  637. package/src/gpu/kernels/sample_f16.wgsl +331 -0
  638. package/src/gpu/kernels/scale.d.ts +35 -0
  639. package/src/gpu/kernels/scale.js +37 -0
  640. package/src/gpu/kernels/scale.wgsl +38 -0
  641. package/src/gpu/kernels/scatter_add.wgsl +88 -0
  642. package/src/gpu/kernels/scatter_add_dynamic.wgsl +59 -0
  643. package/src/gpu/kernels/scatter_add_dynamic_f16.wgsl +52 -0
  644. package/src/gpu/kernels/scatter_add_dynamic_f16_weights.wgsl +50 -0
  645. package/src/gpu/kernels/scatter_add_vec4.wgsl +70 -0
  646. package/src/gpu/kernels/shader-cache.d.ts +56 -0
  647. package/src/gpu/kernels/shader-cache.js +206 -0
  648. package/src/gpu/kernels/silu.d.ts +75 -0
  649. package/src/gpu/kernels/silu.js +340 -0
  650. package/src/gpu/kernels/silu.wgsl +99 -0
  651. package/src/gpu/kernels/silu_f16.wgsl +98 -0
  652. package/src/gpu/kernels/softmax.d.ts +57 -0
  653. package/src/gpu/kernels/softmax.js +106 -0
  654. package/src/gpu/kernels/softmax.wgsl +388 -0
  655. package/src/gpu/kernels/softmax_subgroup.wgsl +175 -0
  656. package/src/gpu/kernels/split_qkv.d.ts +51 -0
  657. package/src/gpu/kernels/split_qkv.js +41 -0
  658. package/src/gpu/kernels/split_qkv.wgsl +71 -0
  659. package/src/gpu/kernels/split_qkv_f16.wgsl +75 -0
  660. package/src/gpu/kernels/topk.wgsl +243 -0
  661. package/src/gpu/kernels/topk_f16.wgsl +108 -0
  662. package/src/gpu/kernels/topk_f16_weights.wgsl +101 -0
  663. package/src/gpu/kernels/transpose.d.ts +21 -0
  664. package/src/gpu/kernels/transpose.js +30 -0
  665. package/src/gpu/kernels/transpose.wgsl +32 -0
  666. package/src/gpu/kernels/types.d.ts +21 -0
  667. package/src/gpu/kernels/types.js +4 -0
  668. package/src/gpu/kernels/uniform-utils.d.ts +48 -0
  669. package/src/gpu/kernels/uniform-utils.js +94 -0
  670. package/src/gpu/kernels/upsample2d.d.ts +25 -0
  671. package/src/gpu/kernels/upsample2d.js +58 -0
  672. package/src/gpu/kernels/upsample2d.wgsl +37 -0
  673. package/src/gpu/kernels/upsample2d_f16.wgsl +41 -0
  674. package/src/gpu/kernels/utils.d.ts +106 -0
  675. package/src/gpu/kernels/utils.js +224 -0
  676. package/src/gpu/multi-model-recorder.d.ts +21 -0
  677. package/src/gpu/multi-model-recorder.js +31 -0
  678. package/src/gpu/partitioned-buffer-pool.d.ts +28 -0
  679. package/src/gpu/partitioned-buffer-pool.js +49 -0
  680. package/src/gpu/perf-guards.d.ts +25 -0
  681. package/src/gpu/perf-guards.js +140 -0
  682. package/src/gpu/profiler.d.ts +114 -0
  683. package/src/gpu/profiler.js +391 -0
  684. package/src/gpu/submit-tracker.d.ts +111 -0
  685. package/src/gpu/submit-tracker.js +229 -0
  686. package/src/gpu/tensor.d.ts +69 -0
  687. package/src/gpu/tensor.js +75 -0
  688. package/src/gpu/uniform-cache.d.ts +108 -0
  689. package/src/gpu/uniform-cache.js +242 -0
  690. package/src/gpu/weight-buffer.d.ts +115 -0
  691. package/src/gpu/weight-buffer.js +118 -0
  692. package/src/hotswap/intent-bundle.d.ts +37 -0
  693. package/src/hotswap/intent-bundle.js +123 -0
  694. package/src/hotswap/manifest.d.ts +33 -0
  695. package/src/hotswap/manifest.js +114 -0
  696. package/src/hotswap/runtime.d.ts +31 -0
  697. package/src/hotswap/runtime.js +128 -0
  698. package/src/index-browser.d.ts +47 -0
  699. package/src/index-browser.js +53 -0
  700. package/src/index-internal.d.ts +2 -0
  701. package/src/index-internal.js +2 -0
  702. package/src/index.d.ts +102 -0
  703. package/src/index.js +75 -0
  704. package/src/inference/README.md +593 -0
  705. package/src/inference/browser-harness.d.ts +234 -0
  706. package/src/inference/browser-harness.js +2665 -0
  707. package/src/inference/decode-buffers.d.ts +108 -0
  708. package/src/inference/decode-buffers.js +181 -0
  709. package/src/inference/decode-ring.d.ts +52 -0
  710. package/src/inference/decode-ring.js +273 -0
  711. package/src/inference/expert-router.d.ts +27 -0
  712. package/src/inference/expert-router.js +55 -0
  713. package/src/inference/functiongemma.d.ts +15 -0
  714. package/src/inference/functiongemma.js +1 -0
  715. package/src/inference/kv-cache/base.d.ts +150 -0
  716. package/src/inference/kv-cache/base.js +1037 -0
  717. package/src/inference/kv-cache/basis-decomposed-paged.d.ts +50 -0
  718. package/src/inference/kv-cache/basis-decomposed-paged.js +276 -0
  719. package/src/inference/kv-cache/index.d.ts +35 -0
  720. package/src/inference/kv-cache/index.js +20 -0
  721. package/src/inference/kv-cache/sliding-window.d.ts +72 -0
  722. package/src/inference/kv-cache/sliding-window.js +243 -0
  723. package/src/inference/kv-cache/tiered.d.ts +89 -0
  724. package/src/inference/kv-cache/tiered.js +574 -0
  725. package/src/inference/kv-cache/types.d.ts +188 -0
  726. package/src/inference/kv-cache/types.js +80 -0
  727. package/src/inference/kv-cache.d.ts +36 -0
  728. package/src/inference/kv-cache.js +18 -0
  729. package/src/inference/moe-router.d.ts +212 -0
  730. package/src/inference/moe-router.js +553 -0
  731. package/src/inference/multi-model-network.d.ts +139 -0
  732. package/src/inference/multi-model-network.js +769 -0
  733. package/src/inference/multi-pipeline-pool.d.ts +62 -0
  734. package/src/inference/multi-pipeline-pool.js +161 -0
  735. package/src/inference/network-evolution.d.ts +46 -0
  736. package/src/inference/network-evolution.js +80 -0
  737. package/src/inference/pipelines/context.d.ts +18 -0
  738. package/src/inference/pipelines/context.js +44 -0
  739. package/src/inference/pipelines/diffusion/helpers.d.ts +29 -0
  740. package/src/inference/pipelines/diffusion/helpers.js +112 -0
  741. package/src/inference/pipelines/diffusion/index.d.ts +3 -0
  742. package/src/inference/pipelines/diffusion/index.js +3 -0
  743. package/src/inference/pipelines/diffusion/init.d.ts +24 -0
  744. package/src/inference/pipelines/diffusion/init.js +124 -0
  745. package/src/inference/pipelines/diffusion/pipeline.d.ts +38 -0
  746. package/src/inference/pipelines/diffusion/pipeline.js +632 -0
  747. package/src/inference/pipelines/diffusion/scheduler.d.ts +19 -0
  748. package/src/inference/pipelines/diffusion/scheduler.js +65 -0
  749. package/src/inference/pipelines/diffusion/sd3-transformer.d.ts +20 -0
  750. package/src/inference/pipelines/diffusion/sd3-transformer.js +1194 -0
  751. package/src/inference/pipelines/diffusion/sd3-weights.d.ts +21 -0
  752. package/src/inference/pipelines/diffusion/sd3-weights.js +287 -0
  753. package/src/inference/pipelines/diffusion/text-encoder-gpu.d.ts +80 -0
  754. package/src/inference/pipelines/diffusion/text-encoder-gpu.js +935 -0
  755. package/src/inference/pipelines/diffusion/text-encoder.d.ts +29 -0
  756. package/src/inference/pipelines/diffusion/text-encoder.js +178 -0
  757. package/src/inference/pipelines/diffusion/types.d.ts +112 -0
  758. package/src/inference/pipelines/diffusion/types.js +1 -0
  759. package/src/inference/pipelines/diffusion/vae.d.ts +20 -0
  760. package/src/inference/pipelines/diffusion/vae.js +675 -0
  761. package/src/inference/pipelines/diffusion/weights.d.ts +40 -0
  762. package/src/inference/pipelines/diffusion/weights.js +150 -0
  763. package/src/inference/pipelines/dream/energy-head-pipeline.d.ts +29 -0
  764. package/src/inference/pipelines/dream/energy-head-pipeline.js +6 -0
  765. package/src/inference/pipelines/dream/pipeline.d.ts +17 -0
  766. package/src/inference/pipelines/dream/pipeline.js +8 -0
  767. package/src/inference/pipelines/energy/index.d.ts +1 -0
  768. package/src/inference/pipelines/energy/index.js +1 -0
  769. package/src/inference/pipelines/energy/pipeline.d.ts +27 -0
  770. package/src/inference/pipelines/energy/pipeline.js +680 -0
  771. package/src/inference/pipelines/energy/quintel.d.ts +87 -0
  772. package/src/inference/pipelines/energy/quintel.js +207 -0
  773. package/src/inference/pipelines/energy/types.d.ts +63 -0
  774. package/src/inference/pipelines/energy/types.js +1 -0
  775. package/src/inference/pipelines/energy-head/index.d.ts +6 -0
  776. package/src/inference/pipelines/energy-head/index.js +6 -0
  777. package/src/inference/pipelines/energy-head/row-head-pipeline.d.ts +103 -0
  778. package/src/inference/pipelines/energy-head/row-head-pipeline.js +487 -0
  779. package/src/inference/pipelines/factory.d.ts +10 -0
  780. package/src/inference/pipelines/factory.js +6 -0
  781. package/src/inference/pipelines/index.d.ts +22 -0
  782. package/src/inference/pipelines/index.js +19 -0
  783. package/src/inference/pipelines/registry.d.ts +15 -0
  784. package/src/inference/pipelines/registry.js +23 -0
  785. package/src/inference/pipelines/rng.d.ts +2 -0
  786. package/src/inference/pipelines/rng.js +17 -0
  787. package/src/inference/pipelines/structured/index.d.ts +8 -0
  788. package/src/inference/pipelines/structured/index.js +8 -0
  789. package/src/inference/pipelines/structured/json-head-pipeline.d.ts +58 -0
  790. package/src/inference/pipelines/structured/json-head-pipeline.js +181 -0
  791. package/src/inference/pipelines/text/attention/index.d.ts +24 -0
  792. package/src/inference/pipelines/text/attention/index.js +17 -0
  793. package/src/inference/pipelines/text/attention/projections.d.ts +101 -0
  794. package/src/inference/pipelines/text/attention/projections.js +435 -0
  795. package/src/inference/pipelines/text/attention/record.d.ts +36 -0
  796. package/src/inference/pipelines/text/attention/record.js +613 -0
  797. package/src/inference/pipelines/text/attention/run.d.ts +38 -0
  798. package/src/inference/pipelines/text/attention/run.js +826 -0
  799. package/src/inference/pipelines/text/attention/types.d.ts +98 -0
  800. package/src/inference/pipelines/text/attention/types.js +67 -0
  801. package/src/inference/pipelines/text/attention.d.ts +23 -0
  802. package/src/inference/pipelines/text/attention.js +12 -0
  803. package/src/inference/pipelines/text/bdpa-steamroller.d.ts +22 -0
  804. package/src/inference/pipelines/text/bdpa-steamroller.js +158 -0
  805. package/src/inference/pipelines/text/buffer-types.d.ts +7 -0
  806. package/src/inference/pipelines/text/buffer-types.js +4 -0
  807. package/src/inference/pipelines/text/chat-format.d.ts +46 -0
  808. package/src/inference/pipelines/text/chat-format.js +366 -0
  809. package/src/inference/pipelines/text/config.d.ts +235 -0
  810. package/src/inference/pipelines/text/config.js +623 -0
  811. package/src/inference/pipelines/text/debug-utils/config.d.ts +144 -0
  812. package/src/inference/pipelines/text/debug-utils/config.js +156 -0
  813. package/src/inference/pipelines/text/debug-utils/index.d.ts +53 -0
  814. package/src/inference/pipelines/text/debug-utils/index.js +44 -0
  815. package/src/inference/pipelines/text/debug-utils/logging.d.ts +106 -0
  816. package/src/inference/pipelines/text/debug-utils/logging.js +152 -0
  817. package/src/inference/pipelines/text/debug-utils/tensor.d.ts +119 -0
  818. package/src/inference/pipelines/text/debug-utils/tensor.js +268 -0
  819. package/src/inference/pipelines/text/debug-utils/utils.d.ts +77 -0
  820. package/src/inference/pipelines/text/debug-utils/utils.js +139 -0
  821. package/src/inference/pipelines/text/debug-utils.d.ts +42 -0
  822. package/src/inference/pipelines/text/debug-utils.js +34 -0
  823. package/src/inference/pipelines/text/embed.d.ts +67 -0
  824. package/src/inference/pipelines/text/embed.js +461 -0
  825. package/src/inference/pipelines/text/execution-plan.d.ts +116 -0
  826. package/src/inference/pipelines/text/execution-plan.js +314 -0
  827. package/src/inference/pipelines/text/execution-v0.d.ts +66 -0
  828. package/src/inference/pipelines/text/execution-v0.js +1139 -0
  829. package/src/inference/pipelines/text/ffn/dense.d.ts +40 -0
  830. package/src/inference/pipelines/text/ffn/dense.js +759 -0
  831. package/src/inference/pipelines/text/ffn/index.d.ts +23 -0
  832. package/src/inference/pipelines/text/ffn/index.js +16 -0
  833. package/src/inference/pipelines/text/ffn/moe.d.ts +21 -0
  834. package/src/inference/pipelines/text/ffn/moe.js +49 -0
  835. package/src/inference/pipelines/text/ffn/sandwich.d.ts +25 -0
  836. package/src/inference/pipelines/text/ffn/sandwich.js +196 -0
  837. package/src/inference/pipelines/text/ffn/standard.d.ts +23 -0
  838. package/src/inference/pipelines/text/ffn/standard.js +84 -0
  839. package/src/inference/pipelines/text/ffn/types.d.ts +30 -0
  840. package/src/inference/pipelines/text/ffn/types.js +25 -0
  841. package/src/inference/pipelines/text/ffn.d.ts +31 -0
  842. package/src/inference/pipelines/text/ffn.js +18 -0
  843. package/src/inference/pipelines/text/finiteness-guard-status.d.ts +11 -0
  844. package/src/inference/pipelines/text/finiteness-guard-status.js +21 -0
  845. package/src/inference/pipelines/text/finiteness-policy.d.ts +35 -0
  846. package/src/inference/pipelines/text/finiteness-policy.js +45 -0
  847. package/src/inference/pipelines/text/generator-helpers.d.ts +34 -0
  848. package/src/inference/pipelines/text/generator-helpers.js +175 -0
  849. package/src/inference/pipelines/text/generator-runtime.d.ts +93 -0
  850. package/src/inference/pipelines/text/generator-runtime.js +373 -0
  851. package/src/inference/pipelines/text/generator-steps.d.ts +75 -0
  852. package/src/inference/pipelines/text/generator-steps.js +1078 -0
  853. package/src/inference/pipelines/text/generator.d.ts +41 -0
  854. package/src/inference/pipelines/text/generator.js +1345 -0
  855. package/src/inference/pipelines/text/index.d.ts +5 -0
  856. package/src/inference/pipelines/text/index.js +6 -0
  857. package/src/inference/pipelines/text/init.d.ts +295 -0
  858. package/src/inference/pipelines/text/init.js +965 -0
  859. package/src/inference/pipelines/text/kernel-path-auto-select.d.ts +12 -0
  860. package/src/inference/pipelines/text/kernel-path-auto-select.js +90 -0
  861. package/src/inference/pipelines/text/kernel-trace.d.ts +150 -0
  862. package/src/inference/pipelines/text/kernel-trace.js +324 -0
  863. package/src/inference/pipelines/text/layer-plan.d.ts +65 -0
  864. package/src/inference/pipelines/text/layer-plan.js +249 -0
  865. package/src/inference/pipelines/text/layer.d.ts +56 -0
  866. package/src/inference/pipelines/text/layer.js +916 -0
  867. package/src/inference/pipelines/text/linear-attention.d.ts +94 -0
  868. package/src/inference/pipelines/text/linear-attention.js +803 -0
  869. package/src/inference/pipelines/text/logits/cpu.d.ts +81 -0
  870. package/src/inference/pipelines/text/logits/cpu.js +91 -0
  871. package/src/inference/pipelines/text/logits/gpu.d.ts +113 -0
  872. package/src/inference/pipelines/text/logits/gpu.js +406 -0
  873. package/src/inference/pipelines/text/logits/index.d.ts +57 -0
  874. package/src/inference/pipelines/text/logits/index.js +305 -0
  875. package/src/inference/pipelines/text/logits/types.d.ts +46 -0
  876. package/src/inference/pipelines/text/logits/types.js +4 -0
  877. package/src/inference/pipelines/text/logits/utils.d.ts +49 -0
  878. package/src/inference/pipelines/text/logits/utils.js +59 -0
  879. package/src/inference/pipelines/text/logits.d.ts +27 -0
  880. package/src/inference/pipelines/text/logits.js +16 -0
  881. package/src/inference/pipelines/text/lora-apply.d.ts +28 -0
  882. package/src/inference/pipelines/text/lora-apply.js +58 -0
  883. package/src/inference/pipelines/text/lora-types.d.ts +39 -0
  884. package/src/inference/pipelines/text/lora-types.js +18 -0
  885. package/src/inference/pipelines/text/lora.d.ts +18 -0
  886. package/src/inference/pipelines/text/lora.js +12 -0
  887. package/src/inference/pipelines/text/model-load.d.ts +58 -0
  888. package/src/inference/pipelines/text/model-load.js +561 -0
  889. package/src/inference/pipelines/text/moe-cache.d.ts +32 -0
  890. package/src/inference/pipelines/text/moe-cache.js +107 -0
  891. package/src/inference/pipelines/text/moe-cpu-gptoss.d.ts +9 -0
  892. package/src/inference/pipelines/text/moe-cpu-gptoss.js +110 -0
  893. package/src/inference/pipelines/text/moe-cpu.d.ts +13 -0
  894. package/src/inference/pipelines/text/moe-cpu.js +116 -0
  895. package/src/inference/pipelines/text/moe-gpu.d.ts +13 -0
  896. package/src/inference/pipelines/text/moe-gpu.js +611 -0
  897. package/src/inference/pipelines/text/moe-helpers.d.ts +12 -0
  898. package/src/inference/pipelines/text/moe-helpers.js +21 -0
  899. package/src/inference/pipelines/text/moe-impl.d.ts +117 -0
  900. package/src/inference/pipelines/text/moe-impl.js +9 -0
  901. package/src/inference/pipelines/text/moe-shape-validator.d.ts +31 -0
  902. package/src/inference/pipelines/text/moe-shape-validator.js +78 -0
  903. package/src/inference/pipelines/text/ops.d.ts +167 -0
  904. package/src/inference/pipelines/text/ops.js +367 -0
  905. package/src/inference/pipelines/text/probes.d.ts +31 -0
  906. package/src/inference/pipelines/text/probes.js +170 -0
  907. package/src/inference/pipelines/text/sampling.d.ts +54 -0
  908. package/src/inference/pipelines/text/sampling.js +203 -0
  909. package/src/inference/pipelines/text/state.d.ts +112 -0
  910. package/src/inference/pipelines/text/state.js +152 -0
  911. package/src/inference/pipelines/text/types.d.ts +627 -0
  912. package/src/inference/pipelines/text/types.js +4 -0
  913. package/src/inference/pipelines/text/weights.d.ts +110 -0
  914. package/src/inference/pipelines/text/weights.js +163 -0
  915. package/src/inference/pipelines/text.d.ts +157 -0
  916. package/src/inference/pipelines/text.js +586 -0
  917. package/src/inference/speculative.d.ts +239 -0
  918. package/src/inference/speculative.js +416 -0
  919. package/src/inference/test-harness.d.ts +178 -0
  920. package/src/inference/test-harness.js +349 -0
  921. package/src/inference/tokenizer.d.ts +77 -0
  922. package/src/inference/tokenizer.js +258 -0
  923. package/src/inference/tokenizers/base.d.ts +39 -0
  924. package/src/inference/tokenizers/base.js +69 -0
  925. package/src/inference/tokenizers/bpe.d.ts +27 -0
  926. package/src/inference/tokenizers/bpe.js +171 -0
  927. package/src/inference/tokenizers/bundled.d.ts +63 -0
  928. package/src/inference/tokenizers/bundled.js +866 -0
  929. package/src/inference/tokenizers/sentencepiece.d.ts +28 -0
  930. package/src/inference/tokenizers/sentencepiece.js +389 -0
  931. package/src/inference/tokenizers/types.d.ts +166 -0
  932. package/src/inference/tokenizers/types.js +7 -0
  933. package/src/loader/doppler-loader.d.ts +134 -0
  934. package/src/loader/doppler-loader.js +1036 -0
  935. package/src/loader/dtype-utils.d.ts +40 -0
  936. package/src/loader/dtype-utils.js +102 -0
  937. package/src/loader/embedding-loader.d.ts +56 -0
  938. package/src/loader/embedding-loader.js +207 -0
  939. package/src/loader/experts/expert-cache.d.ts +156 -0
  940. package/src/loader/experts/expert-cache.js +375 -0
  941. package/src/loader/experts/expert-loader.d.ts +108 -0
  942. package/src/loader/experts/expert-loader.js +384 -0
  943. package/src/loader/final-weights-loader.d.ts +68 -0
  944. package/src/loader/final-weights-loader.js +262 -0
  945. package/src/loader/index.d.ts +150 -0
  946. package/src/loader/index.js +124 -0
  947. package/src/loader/layer-loader.d.ts +63 -0
  948. package/src/loader/layer-loader.js +417 -0
  949. package/src/loader/loader-state.d.ts +51 -0
  950. package/src/loader/loader-state.js +142 -0
  951. package/src/loader/loader-types.d.ts +236 -0
  952. package/src/loader/loader-types.js +4 -0
  953. package/src/loader/manifest-config.d.ts +97 -0
  954. package/src/loader/manifest-config.js +132 -0
  955. package/src/loader/memory-monitor.d.ts +112 -0
  956. package/src/loader/memory-monitor.js +276 -0
  957. package/src/loader/multi-model-loader.d.ts +37 -0
  958. package/src/loader/multi-model-loader.js +87 -0
  959. package/src/loader/quantization-constants.d.ts +23 -0
  960. package/src/loader/quantization-constants.js +14 -0
  961. package/src/loader/shard-cache.d.ts +60 -0
  962. package/src/loader/shard-cache.js +568 -0
  963. package/src/loader/shard-resolver.d.ts +12 -0
  964. package/src/loader/shard-resolver.js +83 -0
  965. package/src/loader/tensors/tensor-loader.d.ts +154 -0
  966. package/src/loader/tensors/tensor-loader.js +427 -0
  967. package/src/loader/tensors/tensor-reader.d.ts +22 -0
  968. package/src/loader/tensors/tensor-reader.js +56 -0
  969. package/src/loader/tensors/tensor-role.d.ts +7 -0
  970. package/src/loader/tensors/tensor-role.js +12 -0
  971. package/src/loader/weight-downcast.d.ts +62 -0
  972. package/src/loader/weight-downcast.js +213 -0
  973. package/src/loader/weights.d.ts +22 -0
  974. package/src/loader/weights.js +4 -0
  975. package/src/memory/address-table.d.ts +104 -0
  976. package/src/memory/address-table.js +114 -0
  977. package/src/memory/buffer-pool.d.ts +196 -0
  978. package/src/memory/buffer-pool.js +756 -0
  979. package/src/memory/capability.d.ts +49 -0
  980. package/src/memory/capability.js +95 -0
  981. package/src/memory/heap-manager.d.ts +104 -0
  982. package/src/memory/heap-manager.js +264 -0
  983. package/src/memory/unified-detect.d.ts +59 -0
  984. package/src/memory/unified-detect.js +192 -0
  985. package/src/rules/converter/execution.rules.json +20 -0
  986. package/src/rules/converter/tensor-roles.rules.json +13 -0
  987. package/src/rules/converter/tokenizer.rules.json +7 -0
  988. package/src/rules/inference/attention.rules.json +54 -0
  989. package/src/rules/inference/config.rules.json +58 -0
  990. package/src/rules/inference/dtype.rules.json +94 -0
  991. package/src/rules/inference/execution.rules.json +45 -0
  992. package/src/rules/inference/ffn.rules.json +35 -0
  993. package/src/rules/inference/kernel-path.rules.json +76 -0
  994. package/src/rules/inference/layer-pattern.rules.json +16 -0
  995. package/src/rules/inference/layer.rules.json +7 -0
  996. package/src/rules/inference/moe.rules.json +48 -0
  997. package/src/rules/kernels/attention.rules.json +61 -0
  998. package/src/rules/kernels/conv2d.rules.json +6 -0
  999. package/src/rules/kernels/dequant.rules.json +58 -0
  1000. package/src/rules/kernels/energy.rules.json +22 -0
  1001. package/src/rules/kernels/fused-ffn.rules.json +13 -0
  1002. package/src/rules/kernels/fused-matmul-residual.rules.json +6 -0
  1003. package/src/rules/kernels/fused-matmul-rmsnorm.rules.json +8 -0
  1004. package/src/rules/kernels/gather.rules.json +12 -0
  1005. package/src/rules/kernels/gelu.rules.json +11 -0
  1006. package/src/rules/kernels/groupnorm.rules.json +10 -0
  1007. package/src/rules/kernels/kernel-validator.d.ts +24 -0
  1008. package/src/rules/kernels/kernel-validator.js +160 -0
  1009. package/src/rules/kernels/kv_quantize.rules.json +7 -0
  1010. package/src/rules/kernels/layernorm.rules.json +6 -0
  1011. package/src/rules/kernels/matmul.rules.json +60 -0
  1012. package/src/rules/kernels/modulate.rules.json +6 -0
  1013. package/src/rules/kernels/moe.rules.gptoss.json +105 -0
  1014. package/src/rules/kernels/moe.rules.json +11 -0
  1015. package/src/rules/kernels/pixel_shuffle.rules.json +6 -0
  1016. package/src/rules/kernels/residual.rules.json +12 -0
  1017. package/src/rules/kernels/rmsnorm.rules.json +11 -0
  1018. package/src/rules/kernels/rope.rules.json +6 -0
  1019. package/src/rules/kernels/sample.rules.json +6 -0
  1020. package/src/rules/kernels/scale.rules.json +6 -0
  1021. package/src/rules/kernels/silu.rules.json +21 -0
  1022. package/src/rules/kernels/softmax.rules.json +23 -0
  1023. package/src/rules/kernels/split-qkv.rules.json +6 -0
  1024. package/src/rules/kernels/upsample2d.rules.json +6 -0
  1025. package/src/rules/loader/tensor-loader.rules.json +15 -0
  1026. package/src/rules/loader/weights.rules.json +41 -0
  1027. package/src/rules/rule-registry.d.ts +48 -0
  1028. package/src/rules/rule-registry.js +177 -0
  1029. package/src/rules/tooling/command-runtime.rules.json +38 -0
  1030. package/src/storage/backends/idb-store.d.ts +52 -0
  1031. package/src/storage/backends/idb-store.js +590 -0
  1032. package/src/storage/backends/memory-store.d.ts +36 -0
  1033. package/src/storage/backends/memory-store.js +242 -0
  1034. package/src/storage/backends/opfs-store.d.ts +41 -0
  1035. package/src/storage/backends/opfs-store.js +429 -0
  1036. package/src/storage/blake3.d.ts +17 -0
  1037. package/src/storage/blake3.js +269 -0
  1038. package/src/storage/download-types.d.ts +157 -0
  1039. package/src/storage/download-types.js +48 -0
  1040. package/src/storage/downloader.d.ts +103 -0
  1041. package/src/storage/downloader.js +839 -0
  1042. package/src/storage/emulated-vram.d.ts +264 -0
  1043. package/src/storage/emulated-vram.js +576 -0
  1044. package/src/storage/export.d.ts +20 -0
  1045. package/src/storage/export.js +159 -0
  1046. package/src/storage/index.d.ts +253 -0
  1047. package/src/storage/index.js +185 -0
  1048. package/src/storage/inventory.d.ts +26 -0
  1049. package/src/storage/inventory.js +218 -0
  1050. package/src/storage/preflight.d.ts +144 -0
  1051. package/src/storage/preflight.js +294 -0
  1052. package/src/storage/quickstart-downloader.d.ts +154 -0
  1053. package/src/storage/quickstart-downloader.js +265 -0
  1054. package/src/storage/quota.d.ts +150 -0
  1055. package/src/storage/quota.js +304 -0
  1056. package/src/storage/registry.d.ts +28 -0
  1057. package/src/storage/registry.js +125 -0
  1058. package/src/storage/reports.d.ts +20 -0
  1059. package/src/storage/reports.js +94 -0
  1060. package/src/storage/shard-manager.d.ts +137 -0
  1061. package/src/storage/shard-manager.js +801 -0
  1062. package/src/sw.d.ts +1 -0
  1063. package/src/sw.js +187 -0
  1064. package/src/tooling/browser-command-runner.d.ts +28 -0
  1065. package/src/tooling/browser-command-runner.js +82 -0
  1066. package/src/tooling/command-api.d.ts +147 -0
  1067. package/src/tooling/command-api.js +523 -0
  1068. package/src/tooling/command-envelope.d.ts +81 -0
  1069. package/src/tooling/command-envelope.js +195 -0
  1070. package/src/tooling/command-runner-shared.d.ts +73 -0
  1071. package/src/tooling/command-runner-shared.js +146 -0
  1072. package/src/tooling/command-runner.html +45 -0
  1073. package/src/tooling/node-browser-command-runner.d.ts +30 -0
  1074. package/src/tooling/node-browser-command-runner.js +868 -0
  1075. package/src/tooling/node-command-runner.d.ts +36 -0
  1076. package/src/tooling/node-command-runner.js +127 -0
  1077. package/src/tooling/node-convert-worker-pool.d.ts +16 -0
  1078. package/src/tooling/node-convert-worker-pool.js +186 -0
  1079. package/src/tooling/node-convert-worker.d.ts +1 -0
  1080. package/src/tooling/node-convert-worker.js +60 -0
  1081. package/src/tooling/node-convert.d.ts +44 -0
  1082. package/src/tooling/node-converter.d.ts +1 -0
  1083. package/src/tooling/node-converter.js +1227 -0
  1084. package/src/tooling/node-file-fetch.d.ts +1 -0
  1085. package/src/tooling/node-file-fetch.js +38 -0
  1086. package/src/tooling/node-source-runtime.d.ts +19 -0
  1087. package/src/tooling/node-source-runtime.js +469 -0
  1088. package/src/tooling/node-webgpu.d.ts +6 -0
  1089. package/src/tooling/node-webgpu.js +321 -0
  1090. package/src/tooling/opfs-cache.d.ts +11 -0
  1091. package/src/tooling/opfs-cache.js +174 -0
  1092. package/src/tooling/source-runtime-bundle.d.ts +102 -0
  1093. package/src/tooling/source-runtime-bundle.js +484 -0
  1094. package/src/tooling-exports.browser.d.ts +7 -0
  1095. package/src/tooling-exports.browser.js +2 -0
  1096. package/src/tooling-exports.d.ts +22 -0
  1097. package/src/tooling-exports.js +7 -0
  1098. package/src/tooling-exports.shared.d.ts +105 -0
  1099. package/src/tooling-exports.shared.js +92 -0
  1100. package/src/training/README.md +153 -0
  1101. package/src/training/artifacts.d.ts +160 -0
  1102. package/src/training/artifacts.js +896 -0
  1103. package/src/training/attention-backward.d.ts +30 -0
  1104. package/src/training/attention-backward.js +217 -0
  1105. package/src/training/attention-forward.d.ts +22 -0
  1106. package/src/training/attention-forward.js +82 -0
  1107. package/src/training/autograd.d.ts +51 -0
  1108. package/src/training/autograd.js +380 -0
  1109. package/src/training/checkpoint.d.ts +31 -0
  1110. package/src/training/checkpoint.js +238 -0
  1111. package/src/training/clip.d.ts +9 -0
  1112. package/src/training/clip.js +54 -0
  1113. package/src/training/dataloader.d.ts +8 -0
  1114. package/src/training/dataloader.js +44 -0
  1115. package/src/training/datasets/index.d.ts +12 -0
  1116. package/src/training/datasets/index.js +6 -0
  1117. package/src/training/datasets/jsonl.d.ts +11 -0
  1118. package/src/training/datasets/jsonl.js +50 -0
  1119. package/src/training/datasets/reploid.d.ts +3 -0
  1120. package/src/training/datasets/reploid.js +36 -0
  1121. package/src/training/datasets/text-pairs.d.ts +21 -0
  1122. package/src/training/datasets/text-pairs.js +42 -0
  1123. package/src/training/datasets/token-batch.d.ts +21 -0
  1124. package/src/training/datasets/token-batch.js +40 -0
  1125. package/src/training/datasets/translation-pairs.d.ts +34 -0
  1126. package/src/training/datasets/translation-pairs.js +49 -0
  1127. package/src/training/export.d.ts +32 -0
  1128. package/src/training/export.js +112 -0
  1129. package/src/training/index.d.ts +52 -0
  1130. package/src/training/index.js +41 -0
  1131. package/src/training/lora.d.ts +19 -0
  1132. package/src/training/lora.js +57 -0
  1133. package/src/training/loss-scaling.d.ts +21 -0
  1134. package/src/training/loss-scaling.js +80 -0
  1135. package/src/training/loss.d.ts +10 -0
  1136. package/src/training/loss.js +41 -0
  1137. package/src/training/objectives/base.d.ts +58 -0
  1138. package/src/training/objectives/base.js +38 -0
  1139. package/src/training/objectives/cross_entropy.d.ts +18 -0
  1140. package/src/training/objectives/cross_entropy.js +37 -0
  1141. package/src/training/objectives/distill_kd.d.ts +16 -0
  1142. package/src/training/objectives/distill_kd.js +369 -0
  1143. package/src/training/objectives/distill_triplet.d.ts +16 -0
  1144. package/src/training/objectives/distill_triplet.js +412 -0
  1145. package/src/training/objectives/index.d.ts +12 -0
  1146. package/src/training/objectives/index.js +6 -0
  1147. package/src/training/objectives/ul_stage1_joint.d.ts +16 -0
  1148. package/src/training/objectives/ul_stage1_joint.js +188 -0
  1149. package/src/training/objectives/ul_stage2_base.d.ts +16 -0
  1150. package/src/training/objectives/ul_stage2_base.js +222 -0
  1151. package/src/training/optimizer.d.ts +22 -0
  1152. package/src/training/optimizer.js +115 -0
  1153. package/src/training/runner.d.ts +196 -0
  1154. package/src/training/runner.js +1194 -0
  1155. package/src/training/suite.d.ts +187 -0
  1156. package/src/training/suite.js +3156 -0
  1157. package/src/training/trainer.d.ts +89 -0
  1158. package/src/training/trainer.js +301 -0
  1159. package/src/training/ul_dataset.d.ts +47 -0
  1160. package/src/training/ul_dataset.js +153 -0
  1161. package/src/training/ul_schedule.d.ts +6 -0
  1162. package/src/training/ul_schedule.js +29 -0
  1163. package/src/types/chrome.d.ts +36 -0
  1164. package/src/types/chrome.js +1 -0
  1165. package/src/types/gpu.d.ts +185 -0
  1166. package/src/types/gpu.js +5 -0
  1167. package/src/types/index.d.ts +3 -0
  1168. package/src/types/index.js +3 -0
  1169. package/src/types/inference.d.ts +197 -0
  1170. package/src/types/inference.js +5 -0
  1171. package/src/types/model.d.ts +125 -0
  1172. package/src/types/model.js +5 -0
  1173. package/src/utils/index.d.ts +7 -0
  1174. package/src/utils/index.js +7 -0
  1175. package/src/utils/load-json.d.ts +5 -0
  1176. package/src/utils/load-json.js +23 -0
  1177. package/src/utils/plain-object.d.ts +1 -0
  1178. package/src/utils/plain-object.js +3 -0
  1179. package/src/utils/sha256.d.ts +4 -0
  1180. package/src/utils/sha256.js +135 -0
  1181. package/tools/convert-safetensors-node.js +180 -0
  1182. package/tools/doppler-cli.js +1170 -0
@@ -0,0 +1,2096 @@
1
+ import { log } from '../debug/index.js';
2
+ import {
3
+ computeHash,
4
+ createStreamingHasher,
5
+ createShardWriter,
6
+ deleteShard,
7
+ getShardStoredSize,
8
+ loadShard as loadShardFromStore,
9
+ shardExists,
10
+ streamShardRange,
11
+ } from '../storage/shard-manager.js';
12
+ import { ERROR_CODES, createDopplerError } from '../errors/doppler-error.js';
13
+ import { DEFAULT_DISTRIBUTION_CONFIG } from '../config/schema/distribution.schema.js';
14
+ import {
15
+ P2P_TRANSPORT_CONTRACT_VERSION,
16
+ P2P_TRANSPORT_ERROR_CODES,
17
+ assertSupportedP2PTransportContract,
18
+ createP2PTransportError,
19
+ normalizeP2PTransportError,
20
+ normalizeP2PTransportResult,
21
+ isP2PTransportRetryable,
22
+ } from './p2p-transport-contract.js';
23
+ import {
24
+ normalizeP2PControlPlaneConfig,
25
+ resolveP2PSessionToken,
26
+ evaluateP2PPolicyDecision,
27
+ } from './p2p-control-plane.js';
28
+ import { createBrowserWebRTCDataPlaneTransport } from './p2p-webrtc-browser.js';
29
+
30
+ const DISTRIBUTION_SOURCE_CACHE = 'cache';
31
+ const DISTRIBUTION_SOURCE_P2P = 'p2p';
32
+ const DISTRIBUTION_SOURCE_HTTP = 'http';
33
+ const DISTRIBUTION_DECISION_TRACE_SCHEMA_VERSION = 1;
34
+ const DISTRIBUTION_DELIVERY_METRICS_SCHEMA_VERSION = 1;
35
+ const DISTRIBUTION_DELIVERY_METRICS_EVENT_SCHEMA_VERSION = 1;
36
+
37
+ const DISTRIBUTION_SOURCES = Object.freeze(
38
+ [...DEFAULT_DISTRIBUTION_CONFIG.sourceOrder]
39
+ );
40
+ const DEFAULT_SOURCE_MATRIX = Object.freeze({
41
+ cache: { ...DEFAULT_DISTRIBUTION_CONFIG.sourceMatrix.cache },
42
+ p2p: { ...DEFAULT_DISTRIBUTION_CONFIG.sourceMatrix.p2p },
43
+ http: { ...DEFAULT_DISTRIBUTION_CONFIG.sourceMatrix.http },
44
+ });
45
+
46
+ const DEFAULT_P2P_TIMEOUT_MS = DEFAULT_DISTRIBUTION_CONFIG.p2p.timeoutMs;
47
+ const DEFAULT_P2P_MAX_RETRIES = DEFAULT_DISTRIBUTION_CONFIG.p2p.maxRetries;
48
+ const DEFAULT_P2P_RETRY_DELAY_MS = DEFAULT_DISTRIBUTION_CONFIG.p2p.retryDelayMs;
49
+ const DEFAULT_P2P_RATE_LIMIT_PER_MINUTE = DEFAULT_DISTRIBUTION_CONFIG.p2p.abuse.rateLimitPerMinute;
50
+ const DEFAULT_P2P_MAX_CONSECUTIVE_FAILURES = DEFAULT_DISTRIBUTION_CONFIG.p2p.abuse.maxConsecutiveFailures;
51
+ const DEFAULT_P2P_QUARANTINE_MS = DEFAULT_DISTRIBUTION_CONFIG.p2p.abuse.quarantineMs;
52
+ const DEFAULT_P2P_CONTROL_PLANE_TOKEN_REFRESH_SKEW_MS = DEFAULT_DISTRIBUTION_CONFIG.p2p.controlPlane.tokenRefreshSkewMs;
53
+
54
+ const inFlightDeliveries = new Map();
55
+ const p2pTransportPolicyState = new WeakMap();
56
+
57
+ function normalizeDistributionSourceOrder(rawSources = []) {
58
+ if (!Array.isArray(rawSources)) {
59
+ return [...DISTRIBUTION_SOURCES];
60
+ }
61
+
62
+ const normalized = [];
63
+ const seen = new Set();
64
+
65
+ for (const value of rawSources) {
66
+ const source = String(value || '').trim().toLowerCase();
67
+ if (!DISTRIBUTION_SOURCES.includes(source)) continue;
68
+ if (seen.has(source)) continue;
69
+ seen.add(source);
70
+ normalized.push(source);
71
+ }
72
+
73
+ return normalized.length > 0 ? normalized : [...DISTRIBUTION_SOURCES];
74
+ }
75
+
76
+ function normalizeInteger(value, fallback, allowZero = false) {
77
+ const parsed = Number(value);
78
+ const min = allowZero ? 0 : 1;
79
+ return Number.isFinite(parsed) && parsed >= min && Number.isInteger(parsed)
80
+ ? parsed
81
+ : fallback;
82
+ }
83
+
84
+ function normalizeContentEncodings(value) {
85
+ if (!value) return [];
86
+ return value
87
+ .split(',')
88
+ .map((entry) => entry.trim().toLowerCase())
89
+ .filter(Boolean);
90
+ }
91
+
92
+ function normalizeManifestVersionSet(value) {
93
+ if (value === undefined || value === null) return null;
94
+ const normalized = String(value).trim();
95
+ return normalized || null;
96
+ }
97
+
98
+ function normalizeSamplingRate(value, fallback = 1) {
99
+ const parsed = Number(value);
100
+ if (!Number.isFinite(parsed)) {
101
+ return fallback;
102
+ }
103
+ if (parsed <= 0) return 0;
104
+ if (parsed >= 1) return 1;
105
+ return parsed;
106
+ }
107
+
108
+ function normalizeOptionalToken(value) {
109
+ if (value === undefined || value === null) {
110
+ return null;
111
+ }
112
+ const normalized = String(value).trim();
113
+ return normalized || null;
114
+ }
115
+
116
+ function normalizeOptionalTimestamp(value) {
117
+ if (value === undefined || value === null) {
118
+ return null;
119
+ }
120
+ const parsed = Number(value);
121
+ if (!Number.isFinite(parsed) || parsed <= 0) {
122
+ return null;
123
+ }
124
+ return Math.floor(parsed);
125
+ }
126
+
127
+ function hashStringToUnitInterval(value) {
128
+ let hash = 2166136261;
129
+ for (let i = 0; i < value.length; i += 1) {
130
+ hash ^= value.charCodeAt(i);
131
+ hash = Math.imul(hash, 16777619);
132
+ }
133
+ return (hash >>> 0) / 4294967295;
134
+ }
135
+
136
+ function shouldEmitDecisionTrace(config, shardIndex, expectedManifestVersionSet, sourceOrder) {
137
+ if (config.enabled !== true) {
138
+ return false;
139
+ }
140
+ const samplingRate = normalizeSamplingRate(config.samplingRate, 1);
141
+ if (samplingRate >= 1) {
142
+ return true;
143
+ }
144
+ if (samplingRate <= 0) {
145
+ return false;
146
+ }
147
+ if (config.deterministic !== false) {
148
+ const seed = [
149
+ String(shardIndex),
150
+ normalizeManifestVersionSet(expectedManifestVersionSet) ?? '',
151
+ Array.isArray(sourceOrder) ? sourceOrder.join(',') : '',
152
+ ].join('|');
153
+ return hashStringToUnitInterval(seed) < samplingRate;
154
+ }
155
+ return Math.random() < samplingRate;
156
+ }
157
+
158
+ function createShardSizeMismatchError(message, details = {}) {
159
+ const error = createDopplerError(
160
+ ERROR_CODES.DISTRIBUTION_SHARD_SIZE_MISMATCH,
161
+ message
162
+ );
163
+ Object.assign(error, details);
164
+ return error;
165
+ }
166
+
167
+ function parseContentLengthHeader(response, shardIndex) {
168
+ const raw = response?.headers?.get?.('content-length');
169
+ if (raw == null || raw === '') return null;
170
+ const parsed = Number(raw);
171
+ if (!Number.isInteger(parsed) || parsed < 0) {
172
+ throw createShardSizeMismatchError(
173
+ `Invalid content-length header for shard ${shardIndex}: ${raw}`,
174
+ {
175
+ code: 'http_content_length_invalid',
176
+ headerValue: raw,
177
+ }
178
+ );
179
+ }
180
+ return parsed;
181
+ }
182
+
183
+ function parseContentRangeHeader(response, shardIndex) {
184
+ const raw = response?.headers?.get?.('content-range');
185
+ if (raw == null || raw.trim() === '') return null;
186
+ const match = /^bytes\s+(\d+)-(\d+)\/(\d+|\*)$/iu.exec(raw.trim());
187
+ if (!match) {
188
+ throw createShardSizeMismatchError(
189
+ `Invalid content-range header for shard ${shardIndex}: ${raw}`,
190
+ {
191
+ code: 'http_content_range_invalid',
192
+ headerValue: raw,
193
+ }
194
+ );
195
+ }
196
+ const start = Number(match[1]);
197
+ const end = Number(match[2]);
198
+ const total = match[3] === '*' ? null : Number(match[3]);
199
+ if (!Number.isInteger(start) || !Number.isInteger(end) || end < start) {
200
+ throw createShardSizeMismatchError(
201
+ `Invalid content-range byte span for shard ${shardIndex}: ${raw}`,
202
+ {
203
+ code: 'http_content_range_invalid_span',
204
+ headerValue: raw,
205
+ }
206
+ );
207
+ }
208
+ if (total != null && (!Number.isInteger(total) || total <= 0 || total <= end)) {
209
+ throw createShardSizeMismatchError(
210
+ `Invalid content-range total size for shard ${shardIndex}: ${raw}`,
211
+ {
212
+ code: 'http_content_range_invalid_total',
213
+ headerValue: raw,
214
+ }
215
+ );
216
+ }
217
+ return {
218
+ start,
219
+ end,
220
+ total,
221
+ length: end - start + 1,
222
+ };
223
+ }
224
+
225
+ function assertHttpResponseBoundaryHeaders(response, shardIndex, contentLength, contentRange) {
226
+ if (response.status === 206 && !contentRange) {
227
+ throw createShardSizeMismatchError(
228
+ `Shard ${shardIndex} returned HTTP 206 without content-range header.`,
229
+ {
230
+ code: 'http_content_range_missing',
231
+ }
232
+ );
233
+ }
234
+ if (contentRange && response.status !== 206) {
235
+ throw createShardSizeMismatchError(
236
+ `Shard ${shardIndex} returned content-range header with unexpected HTTP ${response.status}.`,
237
+ {
238
+ code: 'http_content_range_unexpected_status',
239
+ status: response.status,
240
+ }
241
+ );
242
+ }
243
+ if (
244
+ contentLength != null
245
+ && contentRange
246
+ && contentLength !== contentRange.length
247
+ ) {
248
+ throw createShardSizeMismatchError(
249
+ `Shard ${shardIndex} content-length/content-range mismatch: content-length=${contentLength}, range-length=${contentRange.length}.`,
250
+ {
251
+ code: 'http_header_length_mismatch',
252
+ contentLength,
253
+ contentRangeLength: contentRange.length,
254
+ }
255
+ );
256
+ }
257
+ }
258
+
259
+ function assertHttpResumeAlignment(
260
+ response,
261
+ shardIndex,
262
+ resumeOffset,
263
+ contentRange
264
+ ) {
265
+ if (!Number.isInteger(resumeOffset) || resumeOffset <= 0) {
266
+ return { resetState: false };
267
+ }
268
+ if (response.status === 200) {
269
+ return { resetState: true };
270
+ }
271
+ if (response.status !== 206 || !contentRange) {
272
+ throw createShardSizeMismatchError(
273
+ `Shard ${shardIndex} resume response mismatch: expected HTTP 206 with content-range for offset ${resumeOffset}, got HTTP ${response.status}.`,
274
+ {
275
+ code: 'http_resume_response_mismatch',
276
+ status: response.status,
277
+ resumeOffset,
278
+ }
279
+ );
280
+ }
281
+ if (contentRange.start !== resumeOffset) {
282
+ throw createShardSizeMismatchError(
283
+ `Shard ${shardIndex} resume content-range start mismatch: expected ${resumeOffset}, got ${contentRange.start}.`,
284
+ {
285
+ code: 'http_resume_offset_mismatch',
286
+ resumeOffset,
287
+ contentRangeStart: contentRange.start,
288
+ }
289
+ );
290
+ }
291
+ return { resetState: false };
292
+ }
293
+
294
+ function assertHttpPayloadBoundary(shardIndex, bytesReceived, contentLength, contentRange, expectedSize) {
295
+ if (contentLength != null && bytesReceived !== contentLength) {
296
+ throw createShardSizeMismatchError(
297
+ `Shard ${shardIndex} content-length mismatch: expected ${contentLength}, received ${bytesReceived}.`,
298
+ {
299
+ code: 'http_content_length_mismatch',
300
+ contentLength,
301
+ bytesReceived,
302
+ }
303
+ );
304
+ }
305
+ if (contentRange && bytesReceived !== contentRange.length) {
306
+ throw createShardSizeMismatchError(
307
+ `Shard ${shardIndex} content-range mismatch: expected ${contentRange.length} bytes, received ${bytesReceived}.`,
308
+ {
309
+ code: 'http_content_range_length_mismatch',
310
+ contentRangeLength: contentRange.length,
311
+ bytesReceived,
312
+ }
313
+ );
314
+ }
315
+ if (contentRange?.total != null && Number.isFinite(expectedSize)) {
316
+ const normalizedExpectedSize = Math.floor(expectedSize);
317
+ if (normalizedExpectedSize >= 0 && contentRange.total !== normalizedExpectedSize) {
318
+ throw createShardSizeMismatchError(
319
+ `Shard ${shardIndex} content-range total mismatch: expected ${normalizedExpectedSize}, got ${contentRange.total}.`,
320
+ {
321
+ code: 'http_content_range_total_mismatch',
322
+ expectedSize: normalizedExpectedSize,
323
+ contentRangeTotal: contentRange.total,
324
+ }
325
+ );
326
+ }
327
+ }
328
+ }
329
+
330
+ function assertP2PPayloadRangeStart(
331
+ shardIndex,
332
+ rangeStart,
333
+ expectedStart
334
+ ) {
335
+ if (rangeStart == null) {
336
+ return;
337
+ }
338
+ if (!Number.isInteger(rangeStart) || rangeStart < 0) {
339
+ throw createShardSizeMismatchError(
340
+ `Shard ${shardIndex} p2p payload rangeStart must be a non-negative integer.`,
341
+ {
342
+ code: 'p2p_range_start_invalid',
343
+ rangeStart,
344
+ }
345
+ );
346
+ }
347
+ if (rangeStart !== expectedStart) {
348
+ throw createShardSizeMismatchError(
349
+ `Shard ${shardIndex} p2p resume range mismatch: expected start ${expectedStart}, got ${rangeStart}.`,
350
+ {
351
+ code: 'p2p_resume_offset_mismatch',
352
+ expectedStart,
353
+ rangeStart,
354
+ }
355
+ );
356
+ }
357
+ }
358
+
359
+ function assertP2PTotalSize(shardIndex, totalSize, expectedSize) {
360
+ if (totalSize == null || !Number.isFinite(expectedSize)) {
361
+ return;
362
+ }
363
+ const normalizedExpectedSize = Math.floor(expectedSize);
364
+ if (totalSize !== normalizedExpectedSize) {
365
+ throw createShardSizeMismatchError(
366
+ `Shard ${shardIndex} p2p totalSize mismatch: expected ${normalizedExpectedSize}, got ${totalSize}.`,
367
+ {
368
+ code: 'p2p_total_size_mismatch',
369
+ expectedSize: normalizedExpectedSize,
370
+ totalSize,
371
+ }
372
+ );
373
+ }
374
+ }
375
+
376
+ function assertP2PPayloadBoundary(
377
+ shardIndex,
378
+ rangeStart,
379
+ payloadBytes,
380
+ totalSize,
381
+ writeToStore
382
+ ) {
383
+ if (totalSize == null) {
384
+ return;
385
+ }
386
+ if (!Number.isInteger(rangeStart) || rangeStart < 0) {
387
+ throw createShardSizeMismatchError(
388
+ `Shard ${shardIndex} p2p payload rangeStart must be a non-negative integer for boundary checks.`,
389
+ {
390
+ code: 'p2p_payload_range_start_invalid',
391
+ rangeStart,
392
+ }
393
+ );
394
+ }
395
+ if (!Number.isInteger(payloadBytes) || payloadBytes < 0) {
396
+ throw createShardSizeMismatchError(
397
+ `Shard ${shardIndex} p2p payload size must be a non-negative integer for boundary checks.`,
398
+ {
399
+ code: 'p2p_payload_size_invalid',
400
+ payloadBytes,
401
+ }
402
+ );
403
+ }
404
+ if (rangeStart + payloadBytes > totalSize) {
405
+ throw createShardSizeMismatchError(
406
+ `Shard ${shardIndex} p2p payload exceeds total size: start=${rangeStart}, bytes=${payloadBytes}, total=${totalSize}.`,
407
+ {
408
+ code: 'p2p_payload_exceeds_total',
409
+ rangeStart,
410
+ payloadBytes,
411
+ totalSize,
412
+ }
413
+ );
414
+ }
415
+ if (!writeToStore && rangeStart === 0 && payloadBytes !== totalSize) {
416
+ throw createShardSizeMismatchError(
417
+ `Shard ${shardIndex} p2p payload size mismatch: expected ${totalSize}, got ${payloadBytes}.`,
418
+ {
419
+ code: 'p2p_payload_size_mismatch',
420
+ payloadBytes,
421
+ totalSize,
422
+ }
423
+ );
424
+ }
425
+ }
426
+
427
+ function assertRequiredContentEncoding(response, requiredEncoding, context) {
428
+ if (!requiredEncoding) return;
429
+ const required = requiredEncoding.trim().toLowerCase();
430
+ if (!required) return;
431
+ const found = normalizeContentEncodings(response.headers.get('content-encoding'));
432
+ if (!found.includes(required)) {
433
+ const foundValue = found.length > 0 ? found.join(', ') : 'none';
434
+ throw new Error(`Missing required content-encoding "${required}" for ${context} (found: ${foundValue})`);
435
+ }
436
+ }
437
+
438
+ function buildShardUrl(baseUrl, shardInfo) {
439
+ const base = String(baseUrl || '').replace(/\/$/, '');
440
+ const filename = String(shardInfo?.filename || '').replace(/^\/+/, '');
441
+ return `${base}/${filename}`;
442
+ }
443
+
444
+ function bytesToHex(bytes) {
445
+ return Array.from(bytes)
446
+ .map((byte) => byte.toString(16).padStart(2, '0'))
447
+ .join('');
448
+ }
449
+
450
+ function normalizeP2PConfig(config = {}) {
451
+ const enabled = config?.enabled === true;
452
+ const rawTimeoutMs = config?.timeoutMs;
453
+ const rawMaxRetries = config?.maxRetries;
454
+ const rawRetryDelayMs = config?.retryDelayMs;
455
+ const rawSecurity = config?.security && typeof config.security === 'object'
456
+ ? config.security
457
+ : {};
458
+ const rawAbuse = config?.abuse && typeof config.abuse === 'object'
459
+ ? config.abuse
460
+ : {};
461
+ const rawControlPlane = config?.controlPlane && typeof config.controlPlane === 'object'
462
+ ? config.controlPlane
463
+ : {};
464
+ const rawWebRTC = config?.webrtc && typeof config.webrtc === 'object'
465
+ ? config.webrtc
466
+ : {};
467
+
468
+ let transport = config?.transport;
469
+ if (typeof transport !== 'function' && rawWebRTC.enabled === true) {
470
+ transport = createBrowserWebRTCDataPlaneTransport(rawWebRTC);
471
+ }
472
+ if (typeof transport !== 'function') {
473
+ transport = null;
474
+ }
475
+
476
+ const contractVersion = assertSupportedP2PTransportContract(
477
+ config?.contractVersion ?? P2P_TRANSPORT_CONTRACT_VERSION
478
+ );
479
+
480
+ return {
481
+ enabled,
482
+ timeoutMs: normalizeInteger(rawTimeoutMs, DEFAULT_P2P_TIMEOUT_MS),
483
+ maxRetries: normalizeInteger(rawMaxRetries, DEFAULT_P2P_MAX_RETRIES, true),
484
+ retryDelayMs: normalizeInteger(rawRetryDelayMs, DEFAULT_P2P_RETRY_DELAY_MS, true),
485
+ transport,
486
+ contractVersion,
487
+ controlPlane: normalizeP2PControlPlaneConfig({
488
+ ...DEFAULT_DISTRIBUTION_CONFIG.p2p.controlPlane,
489
+ ...rawControlPlane,
490
+ tokenRefreshSkewMs: normalizeInteger(
491
+ rawControlPlane.tokenRefreshSkewMs,
492
+ DEFAULT_P2P_CONTROL_PLANE_TOKEN_REFRESH_SKEW_MS,
493
+ true
494
+ ),
495
+ }),
496
+ security: {
497
+ requireSessionToken: rawSecurity.requireSessionToken === true,
498
+ sessionToken: normalizeOptionalToken(rawSecurity.sessionToken),
499
+ tokenExpiresAtMs: normalizeOptionalTimestamp(rawSecurity.tokenExpiresAtMs),
500
+ },
501
+ abuse: {
502
+ rateLimitPerMinute: normalizeInteger(
503
+ rawAbuse.rateLimitPerMinute,
504
+ DEFAULT_P2P_RATE_LIMIT_PER_MINUTE,
505
+ true
506
+ ),
507
+ maxConsecutiveFailures: normalizeInteger(
508
+ rawAbuse.maxConsecutiveFailures,
509
+ DEFAULT_P2P_MAX_CONSECUTIVE_FAILURES
510
+ ),
511
+ quarantineMs: normalizeInteger(
512
+ rawAbuse.quarantineMs,
513
+ DEFAULT_P2P_QUARANTINE_MS,
514
+ true
515
+ ),
516
+ },
517
+ };
518
+ }
519
+
520
+ function getP2PTransportPolicyState(transport) {
521
+ if (typeof transport !== 'function') {
522
+ return null;
523
+ }
524
+ let state = p2pTransportPolicyState.get(transport);
525
+ if (!state) {
526
+ state = {
527
+ requestTimestamps: [],
528
+ consecutiveFailures: 0,
529
+ quarantinedUntilMs: 0,
530
+ };
531
+ p2pTransportPolicyState.set(transport, state);
532
+ }
533
+ return state;
534
+ }
535
+
536
+ function createP2PPolicyDeniedError(message, details = {}) {
537
+ return createP2PTransportError(
538
+ P2P_TRANSPORT_ERROR_CODES.policyDenied,
539
+ message,
540
+ details,
541
+ false
542
+ );
543
+ }
544
+
545
+ function isSessionTokenExpiredOrExpiring(tokenExpiresAtMs, nowMs = Date.now(), skewMs = 0) {
546
+ if (!Number.isFinite(tokenExpiresAtMs)) {
547
+ return false;
548
+ }
549
+ const threshold = nowMs + Math.max(0, Math.floor(skewMs));
550
+ return threshold >= tokenExpiresAtMs;
551
+ }
552
+
553
+ function applyControlPlaneSessionUpdate(p2pConfig, sessionUpdate) {
554
+ if (!sessionUpdate || !p2pConfig?.security) {
555
+ return;
556
+ }
557
+ if (sessionUpdate.hasSessionToken === true) {
558
+ p2pConfig.security.sessionToken = normalizeOptionalToken(sessionUpdate.sessionToken);
559
+ }
560
+ if (sessionUpdate.hasTokenExpiresAtMs === true) {
561
+ p2pConfig.security.tokenExpiresAtMs = normalizeOptionalTimestamp(sessionUpdate.tokenExpiresAtMs);
562
+ }
563
+ }
564
+
565
+ async function refreshP2PSessionTokenFromControlPlane(p2pConfig, context, nowMs = Date.now()) {
566
+ const controlPlane = p2pConfig?.controlPlane;
567
+ if (!controlPlane?.enabled || typeof controlPlane.tokenProvider !== 'function') {
568
+ return;
569
+ }
570
+
571
+ const requiresSessionToken = p2pConfig?.security?.requireSessionToken === true;
572
+ const token = p2pConfig?.security?.sessionToken ?? null;
573
+ const tokenExpiresAtMs = p2pConfig?.security?.tokenExpiresAtMs ?? null;
574
+ let reason = null;
575
+
576
+ if (requiresSessionToken && !token) {
577
+ reason = 'missing';
578
+ } else if (isSessionTokenExpiredOrExpiring(tokenExpiresAtMs, nowMs, 0)) {
579
+ reason = 'expired';
580
+ } else if (
581
+ isSessionTokenExpiredOrExpiring(tokenExpiresAtMs, nowMs, controlPlane.tokenRefreshSkewMs)
582
+ ) {
583
+ reason = 'refresh';
584
+ }
585
+
586
+ if (!reason) {
587
+ return;
588
+ }
589
+
590
+ const sessionUpdate = await resolveP2PSessionToken(controlPlane, {
591
+ ...context,
592
+ reason,
593
+ nowMs,
594
+ currentSessionToken: token,
595
+ currentTokenExpiresAtMs: tokenExpiresAtMs,
596
+ });
597
+ applyControlPlaneSessionUpdate(p2pConfig, sessionUpdate);
598
+
599
+ if (requiresSessionToken && !p2pConfig.security.sessionToken) {
600
+ throw createP2PPolicyDeniedError(
601
+ `P2P shard ${context?.shardIndex} requires a session token from control plane.`,
602
+ {
603
+ shardIndex: context?.shardIndex ?? null,
604
+ policyReason: 'session_token_missing_after_refresh',
605
+ }
606
+ );
607
+ }
608
+ }
609
+
610
+ async function enforceP2PControlPlanePolicy(p2pConfig, context, nowMs = Date.now()) {
611
+ const controlPlane = p2pConfig?.controlPlane;
612
+ if (!controlPlane?.enabled || typeof controlPlane.policyEvaluator !== 'function') {
613
+ return;
614
+ }
615
+ const decision = await evaluateP2PPolicyDecision(controlPlane, {
616
+ ...context,
617
+ nowMs,
618
+ currentSessionToken: p2pConfig?.security?.sessionToken ?? null,
619
+ currentTokenExpiresAtMs: p2pConfig?.security?.tokenExpiresAtMs ?? null,
620
+ });
621
+ applyControlPlaneSessionUpdate(p2pConfig, decision.sessionUpdate);
622
+ if (decision.allow !== false) {
623
+ return;
624
+ }
625
+ throw createP2PPolicyDeniedError(
626
+ `P2P shard ${context?.shardIndex} denied by control-plane policy.`,
627
+ {
628
+ shardIndex: context?.shardIndex ?? null,
629
+ policyReason: decision.reason ?? 'policy_denied_control_plane',
630
+ controlPlaneMetadata: decision.metadata ?? null,
631
+ }
632
+ );
633
+ }
634
+
635
+ function enforceP2PSecurityAndAbusePolicy(p2pConfig, state, shardIndex, nowMs = Date.now()) {
636
+ const security = p2pConfig?.security ?? {};
637
+ const abuse = p2pConfig?.abuse ?? {};
638
+
639
+ if (security.requireSessionToken === true && !security.sessionToken) {
640
+ throw createP2PPolicyDeniedError(
641
+ `P2P shard ${shardIndex} requires a session token.`,
642
+ {
643
+ shardIndex,
644
+ policyReason: 'session_token_missing',
645
+ }
646
+ );
647
+ }
648
+ if (
649
+ Number.isFinite(security.tokenExpiresAtMs)
650
+ && nowMs >= security.tokenExpiresAtMs
651
+ ) {
652
+ throw createP2PPolicyDeniedError(
653
+ `P2P shard ${shardIndex} session token expired.`,
654
+ {
655
+ shardIndex,
656
+ policyReason: 'session_token_expired',
657
+ tokenExpiresAtMs: security.tokenExpiresAtMs,
658
+ }
659
+ );
660
+ }
661
+
662
+ if (!state) {
663
+ return;
664
+ }
665
+
666
+ if (Number.isFinite(state.quarantinedUntilMs) && nowMs < state.quarantinedUntilMs) {
667
+ throw createP2PPolicyDeniedError(
668
+ `P2P shard ${shardIndex} transport is quarantined.`,
669
+ {
670
+ shardIndex,
671
+ policyReason: 'transport_quarantined',
672
+ quarantinedUntilMs: state.quarantinedUntilMs,
673
+ }
674
+ );
675
+ }
676
+
677
+ const limit = Number.isFinite(abuse.rateLimitPerMinute)
678
+ ? Math.max(0, Math.floor(abuse.rateLimitPerMinute))
679
+ : 0;
680
+ if (limit > 0) {
681
+ const cutoff = nowMs - 60000;
682
+ state.requestTimestamps = state.requestTimestamps.filter((stamp) => stamp >= cutoff);
683
+ if (state.requestTimestamps.length >= limit) {
684
+ throw createP2PPolicyDeniedError(
685
+ `P2P shard ${shardIndex} transport rate limit exceeded.`,
686
+ {
687
+ shardIndex,
688
+ policyReason: 'rate_limited',
689
+ rateLimitPerMinute: limit,
690
+ }
691
+ );
692
+ }
693
+ state.requestTimestamps.push(nowMs);
694
+ }
695
+ }
696
+
697
+ function markP2PTransportSuccess(state) {
698
+ if (!state) {
699
+ return;
700
+ }
701
+ state.consecutiveFailures = 0;
702
+ state.quarantinedUntilMs = 0;
703
+ }
704
+
705
+ function markP2PTransportFailure(p2pConfig, state, normalizedError, nowMs = Date.now()) {
706
+ if (!state) {
707
+ return;
708
+ }
709
+ if (!normalizedError || normalizedError.code === P2P_TRANSPORT_ERROR_CODES.aborted) {
710
+ return;
711
+ }
712
+ const maxFailures = Number.isFinite(p2pConfig?.abuse?.maxConsecutiveFailures)
713
+ ? Math.max(1, Math.floor(p2pConfig.abuse.maxConsecutiveFailures))
714
+ : DEFAULT_P2P_MAX_CONSECUTIVE_FAILURES;
715
+ const quarantineMs = Number.isFinite(p2pConfig?.abuse?.quarantineMs)
716
+ ? Math.max(0, Math.floor(p2pConfig.abuse.quarantineMs))
717
+ : DEFAULT_P2P_QUARANTINE_MS;
718
+ state.consecutiveFailures += 1;
719
+ if (quarantineMs > 0 && state.consecutiveFailures >= maxFailures) {
720
+ state.quarantinedUntilMs = nowMs + quarantineMs;
721
+ }
722
+ }
723
+
724
+ function normalizeAntiRollbackConfig(config = {}) {
725
+ const antiRollback = config?.antiRollback && typeof config.antiRollback === 'object'
726
+ ? config.antiRollback
727
+ : {};
728
+ return {
729
+ enabled: antiRollback.enabled !== false,
730
+ requireExpectedHash: antiRollback.requireExpectedHash !== false,
731
+ requireExpectedSize: antiRollback.requireExpectedSize === true,
732
+ requireManifestVersionSet: antiRollback.requireManifestVersionSet !== false,
733
+ };
734
+ }
735
+
736
+ function normalizeDecisionTraceConfig(config = {}) {
737
+ const sourceDecision = config?.sourceDecision && typeof config.sourceDecision === 'object'
738
+ ? config.sourceDecision
739
+ : {};
740
+ const trace = sourceDecision.trace && typeof sourceDecision.trace === 'object'
741
+ ? sourceDecision.trace
742
+ : {};
743
+ return {
744
+ deterministic: sourceDecision.deterministic !== false,
745
+ enabled: trace.enabled === true,
746
+ includeSkippedSources: trace.includeSkippedSources !== false,
747
+ samplingRate: normalizeSamplingRate(trace.samplingRate, 1),
748
+ };
749
+ }
750
+
751
+ function normalizeSourceMatrix(config = {}) {
752
+ const matrix = config?.sourceMatrix && typeof config.sourceMatrix === 'object'
753
+ ? config.sourceMatrix
754
+ : {};
755
+ const defaultMatrix = DEFAULT_SOURCE_MATRIX;
756
+ const normalized = {};
757
+ for (const source of DISTRIBUTION_SOURCES) {
758
+ const entry = matrix[source] && typeof matrix[source] === 'object'
759
+ ? matrix[source]
760
+ : {};
761
+ normalized[source] = {
762
+ onHit: entry.onHit === 'return' ? 'return' : defaultMatrix[source].onHit,
763
+ onMiss: entry.onMiss === 'terminal' ? 'terminal' : 'next',
764
+ onFailure: entry.onFailure === 'terminal' ? 'terminal' : 'next',
765
+ };
766
+ }
767
+ return normalized;
768
+ }
769
+
770
+ function createDecisionTrace(order, plan, shardIndex, deterministic, expectedManifestVersionSet) {
771
+ return {
772
+ schemaVersion: DISTRIBUTION_DECISION_TRACE_SCHEMA_VERSION,
773
+ deterministic: deterministic === true,
774
+ shardIndex,
775
+ expectedManifestVersionSet: normalizeManifestVersionSet(expectedManifestVersionSet),
776
+ sourceOrder: [...order],
777
+ plan: plan.map((entry) => ({
778
+ source: entry.source,
779
+ enabled: entry.enabled,
780
+ reason: entry.reason,
781
+ })),
782
+ attempts: [],
783
+ };
784
+ }
785
+
786
+ function appendDecisionTraceAttempt(trace, entry) {
787
+ if (!trace) return;
788
+ trace.attempts.push({
789
+ source: entry.source,
790
+ status: entry.status,
791
+ reason: entry.reason ?? null,
792
+ code: entry.code ?? null,
793
+ message: entry.message ?? null,
794
+ durationMs: Number.isFinite(entry.durationMs) ? entry.durationMs : null,
795
+ bytes: Number.isFinite(entry.bytes) ? entry.bytes : null,
796
+ hash: typeof entry.hash === 'string' ? entry.hash : null,
797
+ path: typeof entry.path === 'string' ? entry.path : null,
798
+ manifestVersionSet: normalizeManifestVersionSet(entry.manifestVersionSet),
799
+ });
800
+ }
801
+
802
+ function attachDecisionTrace(result, trace) {
803
+ if (!trace) return result;
804
+ return {
805
+ ...result,
806
+ decisionTrace: trace,
807
+ };
808
+ }
809
+
810
+ function createSourceCounter() {
811
+ return {
812
+ cache: 0,
813
+ p2p: 0,
814
+ http: 0,
815
+ };
816
+ }
817
+
818
+ function createLatencySummary(durations) {
819
+ const values = durations.filter((value) => Number.isFinite(value));
820
+ if (values.length === 0) {
821
+ return {
822
+ count: 0,
823
+ min: null,
824
+ max: null,
825
+ avg: null,
826
+ };
827
+ }
828
+ let sum = 0;
829
+ let min = Number.POSITIVE_INFINITY;
830
+ let max = Number.NEGATIVE_INFINITY;
831
+ for (const value of values) {
832
+ sum += value;
833
+ if (value < min) min = value;
834
+ if (value > max) max = value;
835
+ }
836
+ return {
837
+ count: values.length,
838
+ min,
839
+ max,
840
+ avg: sum / values.length,
841
+ };
842
+ }
843
+
844
+ function appendAttemptLogAttempt(logEntries, entry) {
845
+ if (!Array.isArray(logEntries)) return;
846
+ logEntries.push({
847
+ source: entry.source,
848
+ status: entry.status,
849
+ code: entry.code ?? null,
850
+ durationMs: Number.isFinite(entry.durationMs) ? entry.durationMs : null,
851
+ writeDurationMs: Number.isFinite(entry.writeDurationMs) ? entry.writeDurationMs : null,
852
+ });
853
+ }
854
+
855
+ function createDeliveryMetrics(order, result, attempts, totalDurationMs) {
856
+ const sourceAttempts = createSourceCounter();
857
+ const retries = createSourceCounter();
858
+ const failureCodes = {};
859
+ const p2pDurations = [];
860
+ const httpDurations = [];
861
+ let storageWriteMs = Number.isFinite(result?.writeDurationMs) ? result.writeDurationMs : null;
862
+ let attemptCount = 0;
863
+ const attemptsBySource = createSourceCounter();
864
+
865
+ for (const attempt of attempts) {
866
+ if (attempt?.status !== 'success' && attempt?.status !== 'failed') {
867
+ continue;
868
+ }
869
+ attemptCount += 1;
870
+ const source = attempt?.source;
871
+ if (source === DISTRIBUTION_SOURCE_CACHE || source === DISTRIBUTION_SOURCE_P2P || source === DISTRIBUTION_SOURCE_HTTP) {
872
+ sourceAttempts[source] += 1;
873
+ attemptsBySource[source] += 1;
874
+ if (source === DISTRIBUTION_SOURCE_P2P && Number.isFinite(attempt.durationMs)) {
875
+ p2pDurations.push(attempt.durationMs);
876
+ }
877
+ if (source === DISTRIBUTION_SOURCE_HTTP && Number.isFinite(attempt.durationMs)) {
878
+ httpDurations.push(attempt.durationMs);
879
+ }
880
+ }
881
+ if (attempt.status === 'failed') {
882
+ const code = typeof attempt.code === 'string' && attempt.code
883
+ ? attempt.code
884
+ : 'unknown';
885
+ failureCodes[code] = (failureCodes[code] ?? 0) + 1;
886
+ }
887
+ if (storageWriteMs == null && Number.isFinite(attempt.writeDurationMs)) {
888
+ storageWriteMs = attempt.writeDurationMs;
889
+ }
890
+ }
891
+
892
+ for (const source of [DISTRIBUTION_SOURCE_CACHE, DISTRIBUTION_SOURCE_P2P, DISTRIBUTION_SOURCE_HTTP]) {
893
+ retries[source] = Math.max(0, attemptsBySource[source] - 1);
894
+ }
895
+
896
+ return {
897
+ schemaVersion: DISTRIBUTION_DELIVERY_METRICS_SCHEMA_VERSION,
898
+ totalDurationMs: Number.isFinite(totalDurationMs) ? totalDurationMs : 0,
899
+ sourceOrder: Array.isArray(order) ? [...order] : [...DISTRIBUTION_SOURCES],
900
+ successSource: result?.source ?? null,
901
+ attemptCount,
902
+ sourceAttempts,
903
+ retries,
904
+ failureCodes,
905
+ p2pRttMs: createLatencySummary(p2pDurations),
906
+ httpRttMs: createLatencySummary(httpDurations),
907
+ storageWriteMs,
908
+ };
909
+ }
910
+
911
+ async function emitDeliveryMetricsHook(hook, payload) {
912
+ if (typeof hook !== 'function') {
913
+ return;
914
+ }
915
+ try {
916
+ await hook(payload);
917
+ } catch (error) {
918
+ log.warn(
919
+ 'Distribution',
920
+ `delivery metrics hook failed: ${error?.message || String(error)}`
921
+ );
922
+ }
923
+ }
924
+
925
+ function assertExpectedHash(resultHash, expectedHash, shardIndex) {
926
+ if (!expectedHash) return;
927
+ if (!resultHash) {
928
+ const error = createDopplerError(
929
+ ERROR_CODES.DISTRIBUTION_SHARD_HASH_MISMATCH,
930
+ `Shard ${shardIndex} missing hash result`
931
+ );
932
+ error.code = 'hash_missing';
933
+ throw error;
934
+ }
935
+ if (resultHash !== expectedHash) {
936
+ const error = createDopplerError(
937
+ ERROR_CODES.DISTRIBUTION_SHARD_HASH_MISMATCH,
938
+ `Hash mismatch for shard ${shardIndex}: expected ${expectedHash}, got ${resultHash}`
939
+ );
940
+ error.code = 'hash_mismatch';
941
+ error.expectedHash = expectedHash;
942
+ error.actualHash = resultHash;
943
+ throw error;
944
+ }
945
+ }
946
+
947
+ function assertExpectedSize(bytes, expectedSize, shardIndex) {
948
+ if (!Number.isFinite(expectedSize)) return;
949
+ const expected = Math.floor(expectedSize);
950
+ const actual = Number.isFinite(bytes) ? Math.floor(bytes) : -1;
951
+ if (expected < 0 || actual < 0) return;
952
+ if (actual !== expected) {
953
+ const error = createDopplerError(
954
+ ERROR_CODES.DISTRIBUTION_SHARD_SIZE_MISMATCH,
955
+ `Size mismatch for shard ${shardIndex}: expected ${expected}, got ${actual}`
956
+ );
957
+ error.code = 'size_mismatch';
958
+ error.expectedSize = expected;
959
+ error.actualSize = actual;
960
+ throw error;
961
+ }
962
+ }
963
+
964
+ function assertExpectedManifestVersionSet(resultVersionSet, expectedVersionSet, shardIndex, source) {
965
+ const expected = normalizeManifestVersionSet(expectedVersionSet);
966
+ if (!expected) return;
967
+ const actual = normalizeManifestVersionSet(resultVersionSet);
968
+ if (!actual) {
969
+ const error = createDopplerError(
970
+ ERROR_CODES.DISTRIBUTION_SHARD_MANIFEST_VERSION_SET_MISMATCH,
971
+ `Shard ${shardIndex} source "${source}" missing manifestVersionSet while antiRollback.requireManifestVersionSet=true.`
972
+ );
973
+ error.code = 'manifest_version_set_missing';
974
+ error.expectedManifestVersionSet = expected;
975
+ error.actualManifestVersionSet = actual;
976
+ throw error;
977
+ }
978
+ if (actual !== expected) {
979
+ const error = createDopplerError(
980
+ ERROR_CODES.DISTRIBUTION_SHARD_MANIFEST_VERSION_SET_MISMATCH,
981
+ `Shard ${shardIndex} source "${source}" manifestVersionSet mismatch: expected ${expected}, got ${actual}`
982
+ );
983
+ error.code = 'manifest_version_set_mismatch';
984
+ error.expectedManifestVersionSet = expected;
985
+ error.actualManifestVersionSet = actual;
986
+ throw error;
987
+ }
988
+ }
989
+
990
+ function parseDownloadOptions(options = {}) {
991
+ return {
992
+ algorithm: options.algorithm,
993
+ onProgress: options.onProgress ?? null,
994
+ onDeliveryMetrics: options.onDeliveryMetrics ?? null,
995
+ signal: options.signal,
996
+ requiredEncoding: options.requiredEncoding ?? null,
997
+ writeToStore: options.writeToStore ?? false,
998
+ expectedHash: options.expectedHash ?? null,
999
+ expectedSize: Number.isFinite(options.expectedSize) ? Math.floor(options.expectedSize) : null,
1000
+ expectedManifestVersionSet: normalizeManifestVersionSet(options.expectedManifestVersionSet),
1001
+ maxRetries: options.maxRetries,
1002
+ initialRetryDelayMs: options.initialRetryDelayMs,
1003
+ maxRetryDelayMs: options.maxRetryDelayMs,
1004
+ };
1005
+ }
1006
+
1007
+ function createDeliveryKey(baseUrl, shardIndex, options, order, sourceMatrix) {
1008
+ return [
1009
+ String(baseUrl || ''),
1010
+ String(shardIndex),
1011
+ String(options.algorithm || ''),
1012
+ String(options.expectedHash || ''),
1013
+ String(options.expectedSize ?? ''),
1014
+ String(options.expectedManifestVersionSet ?? ''),
1015
+ JSON.stringify(sourceMatrix || null),
1016
+ String(options.writeToStore === true),
1017
+ order.join(','),
1018
+ ].join('|');
1019
+ }
1020
+
1021
+ function createAbortError(label = 'operation aborted') {
1022
+ const error = new Error(label);
1023
+ error.name = 'AbortError';
1024
+ return error;
1025
+ }
1026
+
1027
+ function awaitWithSignal(promise, signal, label) {
1028
+ if (!signal) return promise;
1029
+ if (signal.aborted) {
1030
+ return Promise.reject(createAbortError(label));
1031
+ }
1032
+ return new Promise((resolve, reject) => {
1033
+ const onAbort = () => reject(createAbortError(label));
1034
+ signal.addEventListener('abort', onAbort, { once: true });
1035
+ promise.then(
1036
+ (value) => {
1037
+ signal.removeEventListener('abort', onAbort);
1038
+ resolve(value);
1039
+ },
1040
+ (error) => {
1041
+ signal.removeEventListener('abort', onAbort);
1042
+ reject(error);
1043
+ }
1044
+ );
1045
+ });
1046
+ }
1047
+
1048
+ async function withTimeout(promise, timeoutMs, label = 'operation') {
1049
+ if (!timeoutMs || timeoutMs <= 0) {
1050
+ return promise;
1051
+ }
1052
+
1053
+ let timer;
1054
+ const timeout = new Promise((_, reject) => {
1055
+ timer = setTimeout(() => {
1056
+ const error = new Error(`${label} timed out after ${timeoutMs}ms`);
1057
+ error.name = 'TimeoutError';
1058
+ reject(error);
1059
+ }, timeoutMs);
1060
+ });
1061
+
1062
+ try {
1063
+ return await Promise.race([promise, timeout]);
1064
+ } finally {
1065
+ clearTimeout(timer);
1066
+ }
1067
+ }
1068
+
1069
+ export function resolveShardDeliveryPlan(options = {}) {
1070
+ const order = normalizeDistributionSourceOrder(options.sourceOrder);
1071
+ const plan = [];
1072
+ for (const source of order) {
1073
+ if (source === DISTRIBUTION_SOURCE_CACHE) {
1074
+ const enabled = options.enableSourceCache !== false;
1075
+ plan.push({
1076
+ source,
1077
+ enabled,
1078
+ reason: enabled ? 'enabled' : 'cache_disabled',
1079
+ });
1080
+ continue;
1081
+ }
1082
+ if (source === DISTRIBUTION_SOURCE_P2P) {
1083
+ const enabled = options.p2pEnabled === true && options.p2pTransportAvailable === true;
1084
+ let reason = 'enabled';
1085
+ if (options.p2pEnabled !== true) {
1086
+ reason = 'p2p_disabled';
1087
+ } else if (options.p2pTransportAvailable !== true) {
1088
+ reason = 'p2p_transport_unconfigured';
1089
+ }
1090
+ plan.push({ source, enabled, reason });
1091
+ continue;
1092
+ }
1093
+ if (source === DISTRIBUTION_SOURCE_HTTP) {
1094
+ const enabled = options.httpEnabled !== false;
1095
+ plan.push({
1096
+ source,
1097
+ enabled,
1098
+ reason: enabled ? 'enabled' : 'http_disabled',
1099
+ });
1100
+ continue;
1101
+ }
1102
+ }
1103
+ return { order, plan };
1104
+ }
1105
+
1106
+ async function seedHasherFromStoredPrefix(hasher, shardIndex, expectedPrefixBytes) {
1107
+ if (!Number.isInteger(expectedPrefixBytes) || expectedPrefixBytes <= 0) {
1108
+ return;
1109
+ }
1110
+ let hashedBytes = 0;
1111
+ for await (const chunk of streamShardRange(shardIndex, 0, expectedPrefixBytes)) {
1112
+ if (!chunk?.byteLength) continue;
1113
+ const remaining = expectedPrefixBytes - hashedBytes;
1114
+ if (remaining <= 0) break;
1115
+ const next = chunk.byteLength > remaining
1116
+ ? chunk.subarray(0, remaining)
1117
+ : chunk;
1118
+ hasher.update(next);
1119
+ hashedBytes += next.byteLength;
1120
+ if (hashedBytes >= expectedPrefixBytes) break;
1121
+ }
1122
+ if (hashedBytes !== expectedPrefixBytes) {
1123
+ throw createShardSizeMismatchError(
1124
+ `Shard ${shardIndex} stored resume prefix mismatch: expected ${expectedPrefixBytes} bytes, read ${hashedBytes}.`,
1125
+ {
1126
+ code: 'resume_state_prefix_mismatch',
1127
+ expectedPrefixBytes,
1128
+ actualPrefixBytes: hashedBytes,
1129
+ }
1130
+ );
1131
+ }
1132
+ }
1133
+
1134
+ async function resolvePersistedResumeOffset(writeToStore, shardIndex, expectedSize) {
1135
+ if (!writeToStore) return 0;
1136
+ const storedSize = await getShardStoredSize(shardIndex);
1137
+ const resumeOffset = Number.isFinite(storedSize)
1138
+ ? Math.max(0, Math.floor(storedSize))
1139
+ : 0;
1140
+ if (resumeOffset <= 0) return 0;
1141
+ if (Number.isFinite(expectedSize)) {
1142
+ const normalizedExpected = Math.max(0, Math.floor(expectedSize));
1143
+ if (resumeOffset > normalizedExpected) {
1144
+ throw createShardSizeMismatchError(
1145
+ `Shard ${shardIndex} stored resume bytes exceed expected size: stored=${resumeOffset}, expected=${normalizedExpected}.`,
1146
+ {
1147
+ code: 'resume_state_oversize',
1148
+ storedBytes: resumeOffset,
1149
+ expectedSize: normalizedExpected,
1150
+ }
1151
+ );
1152
+ }
1153
+ if (resumeOffset === normalizedExpected) {
1154
+ return 0;
1155
+ }
1156
+ }
1157
+ return resumeOffset;
1158
+ }
1159
+
1160
+ async function createHttpTransferState(writeToStore, shardIndex, algorithm, resumeOffset = 0) {
1161
+ const normalizedResumeOffset = Number.isInteger(resumeOffset) && resumeOffset > 0
1162
+ ? resumeOffset
1163
+ : 0;
1164
+ const hasher = await createStreamingHasher(algorithm);
1165
+ if (normalizedResumeOffset > 0) {
1166
+ await seedHasherFromStoredPrefix(hasher, shardIndex, normalizedResumeOffset);
1167
+ }
1168
+ return {
1169
+ hasher,
1170
+ chunks: writeToStore ? null : [],
1171
+ writer: writeToStore
1172
+ ? await createShardWriter(shardIndex, {
1173
+ append: normalizedResumeOffset > 0,
1174
+ expectedOffset: normalizedResumeOffset,
1175
+ })
1176
+ : null,
1177
+ writerClosed: false,
1178
+ receivedBytes: normalizedResumeOffset,
1179
+ writeDurationMs: 0,
1180
+ };
1181
+ }
1182
+
1183
+ async function resetHttpTransferState(state, writeToStore, shardIndex, algorithm) {
1184
+ await state.writer?.abort?.();
1185
+ state.hasher = await createStreamingHasher(algorithm);
1186
+ state.chunks = writeToStore ? null : [];
1187
+ state.writer = writeToStore ? await createShardWriter(shardIndex) : null;
1188
+ state.writerClosed = false;
1189
+ state.receivedBytes = 0;
1190
+ state.writeDurationMs = 0;
1191
+ }
1192
+
1193
+ async function appendHttpTransferChunk(state, chunk) {
1194
+ const bytes = chunk instanceof Uint8Array ? chunk : new Uint8Array(chunk);
1195
+ state.hasher.update(bytes);
1196
+ if (state.writer) {
1197
+ const writeStart = performance.now();
1198
+ await state.writer.write(bytes);
1199
+ state.writeDurationMs += performance.now() - writeStart;
1200
+ } else if (state.chunks) {
1201
+ state.chunks.push(bytes.slice(0));
1202
+ }
1203
+ state.receivedBytes += bytes.byteLength;
1204
+ }
1205
+
1206
+ async function finalizeHttpTransferState(state, startTime, shardIndex) {
1207
+ const hashBytes = await state.hasher.finalize();
1208
+ const hash = bytesToHex(hashBytes);
1209
+ if (state.writer) {
1210
+ const closeStart = performance.now();
1211
+ await state.writer.close();
1212
+ state.writerClosed = true;
1213
+ state.writeDurationMs += performance.now() - closeStart;
1214
+ const elapsed = (performance.now() - startTime) / 1000;
1215
+ const speed = elapsed > 0 ? state.receivedBytes / elapsed : 0;
1216
+ const speedDisplay = `${(speed / (1024 * 1024)).toFixed(2)}MB/s`;
1217
+ log.verbose(
1218
+ 'Distribution',
1219
+ `Shard ${shardIndex}: http stream (${state.receivedBytes} bytes, ${elapsed.toFixed(2)}s, ${speedDisplay})`
1220
+ );
1221
+ return {
1222
+ buffer: null,
1223
+ bytes: state.receivedBytes,
1224
+ hash,
1225
+ wrote: true,
1226
+ source: DISTRIBUTION_SOURCE_HTTP,
1227
+ path: 'http-stream-store',
1228
+ writeDurationMs: state.writeDurationMs,
1229
+ };
1230
+ }
1231
+
1232
+ const buffer = !state.chunks || state.chunks.length === 0
1233
+ ? new ArrayBuffer(0)
1234
+ : await new Blob(state.chunks).arrayBuffer();
1235
+ return {
1236
+ buffer,
1237
+ bytes: buffer.byteLength,
1238
+ hash,
1239
+ wrote: false,
1240
+ source: DISTRIBUTION_SOURCE_HTTP,
1241
+ path: 'http-stream-buffer',
1242
+ writeDurationMs: null,
1243
+ };
1244
+ }
1245
+
1246
+ async function abortHttpTransferState(state) {
1247
+ if (state.writer && !state.writerClosed) {
1248
+ await state.writer.abort?.();
1249
+ state.writerClosed = true;
1250
+ }
1251
+ }
1252
+
1253
+ async function persistHttpTransferState(state) {
1254
+ if (!state.writer || state.writerClosed) {
1255
+ return;
1256
+ }
1257
+ if (state.receivedBytes > 0) {
1258
+ const closeStart = performance.now();
1259
+ await state.writer.close();
1260
+ state.writerClosed = true;
1261
+ state.writeDurationMs += performance.now() - closeStart;
1262
+ return;
1263
+ }
1264
+ await state.writer.abort?.();
1265
+ state.writerClosed = true;
1266
+ }
1267
+
1268
+ async function clearPersistedShardState(shardIndex) {
1269
+ const deleted = await deleteShard(shardIndex);
1270
+ if (deleted) {
1271
+ return;
1272
+ }
1273
+ const writer = await createShardWriter(shardIndex, {
1274
+ append: false,
1275
+ expectedOffset: 0,
1276
+ });
1277
+ await writer.abort?.();
1278
+ }
1279
+
1280
+ async function downloadShardFromHttp(baseUrl, shardInfo, shardIndex, options = {}) {
1281
+ const {
1282
+ signal,
1283
+ algorithm,
1284
+ onProgress,
1285
+ requiredEncoding,
1286
+ writeToStore = false,
1287
+ } = options;
1288
+
1289
+ if (!algorithm) {
1290
+ throw new Error('Missing hash algorithm for shard download.');
1291
+ }
1292
+
1293
+ const startTime = performance.now();
1294
+ const url = buildShardUrl(baseUrl, shardInfo);
1295
+ let lastError;
1296
+ const maxRetries = normalizeInteger(options.maxRetries, 3, true);
1297
+ const initialRetryDelayMs = normalizeInteger(options.initialRetryDelayMs, 1000);
1298
+ const maxRetryDelayMs = normalizeInteger(options.maxRetryDelayMs, 30000);
1299
+ const progressTotalBytes = Number.isFinite(options.expectedSize)
1300
+ ? Math.floor(options.expectedSize)
1301
+ : (Number.isFinite(shardInfo?.size) ? Math.floor(shardInfo.size) : 0);
1302
+ let retryDelay = initialRetryDelayMs;
1303
+ const disablePersistedResume = options.__disablePersistedResume === true;
1304
+ let resumeOffset = 0;
1305
+ if (!disablePersistedResume) {
1306
+ try {
1307
+ resumeOffset = await resolvePersistedResumeOffset(
1308
+ writeToStore,
1309
+ shardIndex,
1310
+ options.expectedSize
1311
+ );
1312
+ } catch (error) {
1313
+ if (writeToStore && error?.code === 'resume_state_oversize') {
1314
+ await clearPersistedShardState(shardIndex);
1315
+ resumeOffset = 0;
1316
+ } else {
1317
+ throw error;
1318
+ }
1319
+ }
1320
+ }
1321
+ const startedWithResume = resumeOffset > 0;
1322
+ let transferState;
1323
+ try {
1324
+ transferState = await createHttpTransferState(
1325
+ writeToStore,
1326
+ shardIndex,
1327
+ algorithm,
1328
+ resumeOffset
1329
+ );
1330
+ } catch (error) {
1331
+ if (writeToStore && error?.code === 'resume_state_prefix_mismatch') {
1332
+ await clearPersistedShardState(shardIndex);
1333
+ resumeOffset = 0;
1334
+ transferState = await createHttpTransferState(
1335
+ writeToStore,
1336
+ shardIndex,
1337
+ algorithm,
1338
+ 0
1339
+ );
1340
+ } else {
1341
+ throw error;
1342
+ }
1343
+ }
1344
+
1345
+ for (let attempt = 0; attempt <= maxRetries; attempt += 1) {
1346
+ try {
1347
+ const resumeOffset = transferState.receivedBytes;
1348
+ const requestHeaders = resumeOffset > 0
1349
+ ? { range: `bytes=${resumeOffset}-` }
1350
+ : undefined;
1351
+ const response = await fetch(url, { signal, headers: requestHeaders });
1352
+ if (!response.ok) {
1353
+ const error = new Error(`HTTP ${response.status}: ${response.statusText}`);
1354
+ error.status = response.status;
1355
+ throw error;
1356
+ }
1357
+
1358
+ assertRequiredContentEncoding(response, requiredEncoding, `shard ${shardIndex}`);
1359
+ const contentLength = parseContentLengthHeader(response, shardIndex);
1360
+ const contentRange = parseContentRangeHeader(response, shardIndex);
1361
+ assertHttpResponseBoundaryHeaders(response, shardIndex, contentLength, contentRange);
1362
+ const { resetState } = assertHttpResumeAlignment(
1363
+ response,
1364
+ shardIndex,
1365
+ resumeOffset,
1366
+ contentRange
1367
+ );
1368
+ if (resetState) {
1369
+ await resetHttpTransferState(transferState, writeToStore, shardIndex, algorithm);
1370
+ }
1371
+
1372
+ if (!response.body) {
1373
+ const buffer = await response.arrayBuffer();
1374
+ assertHttpPayloadBoundary(
1375
+ shardIndex,
1376
+ buffer.byteLength,
1377
+ contentLength,
1378
+ contentRange,
1379
+ options.expectedSize
1380
+ );
1381
+ await appendHttpTransferChunk(transferState, new Uint8Array(buffer));
1382
+ const total = progressTotalBytes > 0 ? progressTotalBytes : transferState.receivedBytes;
1383
+ const percent = total > 0
1384
+ ? Math.min(100, Math.floor((transferState.receivedBytes / total) * 100))
1385
+ : 100;
1386
+ onProgress?.({
1387
+ shardIndex,
1388
+ receivedBytes: transferState.receivedBytes,
1389
+ totalBytes: total,
1390
+ percent,
1391
+ });
1392
+
1393
+ const finalized = await finalizeHttpTransferState(transferState, startTime, shardIndex);
1394
+ const result = {
1395
+ ...finalized,
1396
+ path: finalized.wrote ? finalized.path : 'http-blob',
1397
+ manifestVersionSet: options.expectedManifestVersionSet ?? null,
1398
+ };
1399
+ if (
1400
+ writeToStore
1401
+ && startedWithResume
1402
+ && options.__resumeRecoveryAttempted !== true
1403
+ && options.expectedHash
1404
+ && result.hash !== options.expectedHash
1405
+ ) {
1406
+ await clearPersistedShardState(shardIndex);
1407
+ return downloadShardFromHttp(baseUrl, shardInfo, shardIndex, {
1408
+ ...options,
1409
+ __disablePersistedResume: true,
1410
+ __resumeRecoveryAttempted: true,
1411
+ });
1412
+ }
1413
+ return result;
1414
+ }
1415
+
1416
+ const reader = response.body.getReader();
1417
+ let attemptBytes = 0;
1418
+
1419
+ try {
1420
+ while (true) {
1421
+ const { done, value } = await reader.read();
1422
+ if (done) break;
1423
+
1424
+ if (value?.length) {
1425
+ await appendHttpTransferChunk(transferState, value);
1426
+ attemptBytes += value.length;
1427
+ }
1428
+
1429
+ const total = progressTotalBytes > 0 ? progressTotalBytes : transferState.receivedBytes;
1430
+ onProgress?.({
1431
+ shardIndex,
1432
+ receivedBytes: transferState.receivedBytes,
1433
+ totalBytes: total,
1434
+ percent: total > 0 ? (transferState.receivedBytes / total) * 100 : 0,
1435
+ });
1436
+ }
1437
+
1438
+ assertHttpPayloadBoundary(
1439
+ shardIndex,
1440
+ attemptBytes,
1441
+ contentLength,
1442
+ contentRange,
1443
+ options.expectedSize
1444
+ );
1445
+ const finalized = await finalizeHttpTransferState(transferState, startTime, shardIndex);
1446
+ const result = {
1447
+ ...finalized,
1448
+ manifestVersionSet: options.expectedManifestVersionSet ?? null,
1449
+ };
1450
+ if (
1451
+ writeToStore
1452
+ && startedWithResume
1453
+ && options.__resumeRecoveryAttempted !== true
1454
+ && options.expectedHash
1455
+ && result.hash !== options.expectedHash
1456
+ ) {
1457
+ await clearPersistedShardState(shardIndex);
1458
+ return downloadShardFromHttp(baseUrl, shardInfo, shardIndex, {
1459
+ ...options,
1460
+ __disablePersistedResume: true,
1461
+ __resumeRecoveryAttempted: true,
1462
+ });
1463
+ }
1464
+ return result;
1465
+ } catch (error) {
1466
+ throw error;
1467
+ }
1468
+ } catch (error) {
1469
+ lastError = error;
1470
+
1471
+ if (error?.name === 'AbortError') {
1472
+ if (writeToStore) {
1473
+ await persistHttpTransferState(transferState);
1474
+ } else {
1475
+ await abortHttpTransferState(transferState);
1476
+ }
1477
+ throw error;
1478
+ }
1479
+
1480
+ if (Number.isInteger(error?.status) && error.status >= 400 && error.status < 500 && error.status !== 429) {
1481
+ await abortHttpTransferState(transferState);
1482
+ throw error;
1483
+ }
1484
+ if (typeof error?.code === 'string' && error.code.startsWith('http_')) {
1485
+ await abortHttpTransferState(transferState);
1486
+ throw error;
1487
+ }
1488
+
1489
+ if (attempt < maxRetries) {
1490
+ await new Promise((resolve) => setTimeout(resolve, retryDelay));
1491
+ retryDelay = Math.min(retryDelay * 2, maxRetryDelayMs);
1492
+ continue;
1493
+ }
1494
+
1495
+ if (writeToStore) {
1496
+ await persistHttpTransferState(transferState);
1497
+ } else {
1498
+ await abortHttpTransferState(transferState);
1499
+ }
1500
+ }
1501
+ }
1502
+
1503
+ if (writeToStore) {
1504
+ await persistHttpTransferState(transferState);
1505
+ } else {
1506
+ await abortHttpTransferState(transferState);
1507
+ }
1508
+ throw lastError;
1509
+ }
1510
+
1511
+ async function downloadShardFromP2P(shardIndex, shardInfo, p2pConfig, options = {}) {
1512
+ const transport = p2pConfig.transport;
1513
+ if (!p2pConfig.enabled || typeof transport !== 'function') {
1514
+ throw createP2PTransportError(
1515
+ P2P_TRANSPORT_ERROR_CODES.unconfigured,
1516
+ 'P2P transport is not configured',
1517
+ { shardIndex }
1518
+ );
1519
+ }
1520
+ const transportState = getP2PTransportPolicyState(transport);
1521
+
1522
+ const writeToStore = options.writeToStore === true;
1523
+ const algorithm = options.algorithm;
1524
+ if (writeToStore && !algorithm) {
1525
+ throw new Error(`Missing hash algorithm for shard ${shardIndex} p2p transfer.`);
1526
+ }
1527
+
1528
+ const expectedSize = Number.isFinite(options.expectedSize)
1529
+ ? Math.floor(options.expectedSize)
1530
+ : null;
1531
+ const disablePersistedResume = options.__disablePersistedResume === true;
1532
+ let seededResumeOffset = 0;
1533
+ let transferState = null;
1534
+ if (writeToStore) {
1535
+ if (!disablePersistedResume) {
1536
+ try {
1537
+ seededResumeOffset = await resolvePersistedResumeOffset(
1538
+ true,
1539
+ shardIndex,
1540
+ expectedSize
1541
+ );
1542
+ } catch (error) {
1543
+ if (error?.code === 'resume_state_oversize') {
1544
+ await clearPersistedShardState(shardIndex);
1545
+ seededResumeOffset = 0;
1546
+ } else {
1547
+ throw error;
1548
+ }
1549
+ }
1550
+ }
1551
+ try {
1552
+ transferState = await createHttpTransferState(
1553
+ true,
1554
+ shardIndex,
1555
+ algorithm,
1556
+ seededResumeOffset
1557
+ );
1558
+ } catch (error) {
1559
+ if (error?.code === 'resume_state_prefix_mismatch') {
1560
+ await clearPersistedShardState(shardIndex);
1561
+ seededResumeOffset = 0;
1562
+ transferState = await createHttpTransferState(true, shardIndex, algorithm, 0);
1563
+ } else {
1564
+ throw error;
1565
+ }
1566
+ }
1567
+ }
1568
+ const startedWithResume = writeToStore && seededResumeOffset > 0;
1569
+
1570
+ const startTime = performance.now();
1571
+ let lastError = null;
1572
+ const maxRetries = Math.max(0, p2pConfig.maxRetries);
1573
+ for (let attempt = 0; attempt <= maxRetries; attempt += 1) {
1574
+ try {
1575
+ const requestResumeOffset = transferState?.receivedBytes ?? 0;
1576
+ const nowMs = Date.now();
1577
+ const attemptContext = {
1578
+ shardIndex,
1579
+ attempt,
1580
+ maxRetries,
1581
+ resumeOffset: requestResumeOffset,
1582
+ expectedHash: options.expectedHash ?? null,
1583
+ expectedSize: options.expectedSize ?? null,
1584
+ expectedManifestVersionSet: options.expectedManifestVersionSet ?? null,
1585
+ };
1586
+ await refreshP2PSessionTokenFromControlPlane(
1587
+ p2pConfig,
1588
+ attemptContext,
1589
+ nowMs
1590
+ );
1591
+ await enforceP2PControlPlanePolicy(
1592
+ p2pConfig,
1593
+ attemptContext,
1594
+ nowMs
1595
+ );
1596
+ enforceP2PSecurityAndAbusePolicy(
1597
+ p2pConfig,
1598
+ transportState,
1599
+ shardIndex,
1600
+ nowMs
1601
+ );
1602
+ const transportResult = await withTimeout(
1603
+ transport({
1604
+ shardIndex,
1605
+ shardInfo,
1606
+ signal: options.signal,
1607
+ source: DISTRIBUTION_SOURCE_P2P,
1608
+ timeoutMs: p2pConfig.timeoutMs,
1609
+ contractVersion: p2pConfig.contractVersion,
1610
+ attempt,
1611
+ maxRetries,
1612
+ resumeOffset: requestResumeOffset,
1613
+ expectedHash: options.expectedHash ?? null,
1614
+ expectedSize: options.expectedSize ?? null,
1615
+ expectedManifestVersionSet: options.expectedManifestVersionSet ?? null,
1616
+ }),
1617
+ p2pConfig.timeoutMs,
1618
+ `P2P shard ${shardIndex}`
1619
+ );
1620
+ const payload = normalizeP2PTransportResult(
1621
+ transportResult,
1622
+ `P2P transport result for shard ${shardIndex}`
1623
+ );
1624
+ if (!payload) {
1625
+ throw createP2PTransportError(
1626
+ P2P_TRANSPORT_ERROR_CODES.payloadInvalid,
1627
+ `P2P transport returned empty payload for shard ${shardIndex}`,
1628
+ { shardIndex }
1629
+ );
1630
+ }
1631
+
1632
+ const payloadRangeStart = payload.rangeStart;
1633
+ const payloadTotalSize = payload.totalSize;
1634
+ assertP2PTotalSize(shardIndex, payloadTotalSize, expectedSize);
1635
+
1636
+ const onProgress = options.onProgress ?? null;
1637
+ const transferResult = await (async () => {
1638
+ if (!writeToStore) {
1639
+ assertP2PPayloadRangeStart(shardIndex, payloadRangeStart, 0);
1640
+ assertP2PPayloadBoundary(
1641
+ shardIndex,
1642
+ 0,
1643
+ payload.data.byteLength,
1644
+ payloadTotalSize,
1645
+ false
1646
+ );
1647
+ onProgress?.({
1648
+ shardIndex,
1649
+ receivedBytes: payload.data.byteLength,
1650
+ totalBytes: expectedSize ?? payloadTotalSize ?? payload.data.byteLength,
1651
+ percent: 100,
1652
+ });
1653
+ return {
1654
+ buffer: payload.data,
1655
+ bytes: payload.data.byteLength,
1656
+ source: DISTRIBUTION_SOURCE_P2P,
1657
+ path: 'p2p-transport',
1658
+ wrote: false,
1659
+ writeDurationMs: null,
1660
+ };
1661
+ }
1662
+
1663
+ let effectiveRangeStart = payloadRangeStart;
1664
+ if (effectiveRangeStart == null) {
1665
+ effectiveRangeStart = requestResumeOffset;
1666
+ }
1667
+ if (requestResumeOffset > 0 && effectiveRangeStart === 0) {
1668
+ await resetHttpTransferState(transferState, true, shardIndex, algorithm);
1669
+ } else {
1670
+ assertP2PPayloadRangeStart(
1671
+ shardIndex,
1672
+ effectiveRangeStart,
1673
+ transferState.receivedBytes
1674
+ );
1675
+ }
1676
+ assertP2PPayloadBoundary(
1677
+ shardIndex,
1678
+ effectiveRangeStart,
1679
+ payload.data.byteLength,
1680
+ payloadTotalSize,
1681
+ true
1682
+ );
1683
+ await appendHttpTransferChunk(transferState, new Uint8Array(payload.data));
1684
+ onProgress?.({
1685
+ shardIndex,
1686
+ receivedBytes: transferState.receivedBytes,
1687
+ totalBytes: expectedSize ?? payloadTotalSize ?? transferState.receivedBytes,
1688
+ percent: 100,
1689
+ });
1690
+ const finalized = await finalizeHttpTransferState(transferState, startTime, shardIndex);
1691
+ if (Number.isFinite(expectedSize)) {
1692
+ assertExpectedSize(finalized.bytes, expectedSize, shardIndex);
1693
+ } else if (Number.isInteger(payloadTotalSize)) {
1694
+ assertExpectedSize(finalized.bytes, payloadTotalSize, shardIndex);
1695
+ }
1696
+ return {
1697
+ ...finalized,
1698
+ source: DISTRIBUTION_SOURCE_P2P,
1699
+ path: 'p2p-stream-store',
1700
+ };
1701
+ })();
1702
+ const result = {
1703
+ ...transferResult,
1704
+ manifestVersionSet: normalizeManifestVersionSet(
1705
+ payload.manifestVersionSet ?? options.expectedManifestVersionSet
1706
+ ),
1707
+ };
1708
+ if (!result.hash && result.buffer instanceof ArrayBuffer) {
1709
+ result.hash = await computeHash(result.buffer, options.algorithm);
1710
+ }
1711
+ if (writeToStore) {
1712
+ try {
1713
+ assertExpectedManifestVersionSet(
1714
+ result.manifestVersionSet,
1715
+ options.expectedManifestVersionSet,
1716
+ shardIndex,
1717
+ DISTRIBUTION_SOURCE_P2P
1718
+ );
1719
+ if (Number.isFinite(expectedSize)) {
1720
+ assertExpectedSize(result.bytes, expectedSize, shardIndex);
1721
+ }
1722
+ if (options.expectedHash) {
1723
+ assertExpectedHash(result.hash, options.expectedHash, shardIndex);
1724
+ }
1725
+ } catch (verificationError) {
1726
+ await clearPersistedShardState(shardIndex);
1727
+ if (
1728
+ startedWithResume
1729
+ && options.__resumeRecoveryAttempted !== true
1730
+ && options.expectedHash
1731
+ && verificationError?.code === 'hash_mismatch'
1732
+ ) {
1733
+ return downloadShardFromP2P(shardIndex, shardInfo, p2pConfig, {
1734
+ ...options,
1735
+ __disablePersistedResume: true,
1736
+ __resumeRecoveryAttempted: true,
1737
+ });
1738
+ }
1739
+ throw verificationError;
1740
+ }
1741
+ }
1742
+ markP2PTransportSuccess(transportState);
1743
+ return result;
1744
+ } catch (error) {
1745
+ if (typeof error?.code === 'string' && error.code.startsWith('p2p_')) {
1746
+ if (writeToStore) {
1747
+ await clearPersistedShardState(shardIndex);
1748
+ }
1749
+ throw error;
1750
+ }
1751
+
1752
+ const normalized = normalizeP2PTransportError(error, {
1753
+ shardIndex,
1754
+ attempt,
1755
+ maxRetries,
1756
+ label: `P2P shard ${shardIndex}`,
1757
+ });
1758
+ lastError = normalized;
1759
+ markP2PTransportFailure(
1760
+ p2pConfig,
1761
+ transportState,
1762
+ normalized,
1763
+ Date.now()
1764
+ );
1765
+ if (normalized?.code === P2P_TRANSPORT_ERROR_CODES.aborted) {
1766
+ if (writeToStore) {
1767
+ await persistHttpTransferState(transferState);
1768
+ }
1769
+ const abortError = createAbortError(normalized.message || 'P2P transport aborted');
1770
+ throw abortError;
1771
+ }
1772
+ if (attempt < maxRetries && isP2PTransportRetryable(normalized)) {
1773
+ await new Promise((resolve) => setTimeout(resolve, p2pConfig.retryDelayMs));
1774
+ continue;
1775
+ }
1776
+ if (writeToStore) {
1777
+ await persistHttpTransferState(transferState);
1778
+ }
1779
+ throw normalized;
1780
+ }
1781
+ }
1782
+
1783
+ if (writeToStore) {
1784
+ await persistHttpTransferState(transferState);
1785
+ }
1786
+ throw lastError;
1787
+ }
1788
+
1789
+ async function executeDeliveryPlan(
1790
+ baseUrl,
1791
+ shardIndex,
1792
+ shardInfo,
1793
+ plan,
1794
+ p2p,
1795
+ options,
1796
+ trace,
1797
+ decisionTraceConfig,
1798
+ sourceMatrix,
1799
+ attemptLog
1800
+ ) {
1801
+ let lastError = null;
1802
+ const enabledSources = plan.filter((entry) => entry.enabled);
1803
+
1804
+ for (const step of plan) {
1805
+ if (!step.enabled) {
1806
+ if (decisionTraceConfig.includeSkippedSources === true) {
1807
+ appendDecisionTraceAttempt(trace, {
1808
+ source: step.source,
1809
+ status: 'skipped',
1810
+ reason: step.reason,
1811
+ });
1812
+ }
1813
+ appendAttemptLogAttempt(attemptLog, {
1814
+ source: step.source,
1815
+ status: 'skipped',
1816
+ });
1817
+ continue;
1818
+ }
1819
+
1820
+ const attemptStart = performance.now();
1821
+ try {
1822
+ let result = null;
1823
+ if (step.source === DISTRIBUTION_SOURCE_CACHE) {
1824
+ if (!(await shardExists(shardIndex))) {
1825
+ const cacheMiss = new Error(`Shard ${shardIndex} missing from local cache`);
1826
+ cacheMiss.code = 'cache_miss';
1827
+ throw cacheMiss;
1828
+ }
1829
+ const buffer = await loadShardFromStore(shardIndex, { verify: false });
1830
+ result = {
1831
+ buffer,
1832
+ bytes: buffer.byteLength,
1833
+ hash: await computeHash(buffer, options.algorithm),
1834
+ wrote: false,
1835
+ source: DISTRIBUTION_SOURCE_CACHE,
1836
+ path: 'cache',
1837
+ manifestVersionSet: options.expectedManifestVersionSet ?? null,
1838
+ writeDurationMs: null,
1839
+ };
1840
+ } else if (step.source === DISTRIBUTION_SOURCE_P2P) {
1841
+ result = await downloadShardFromP2P(shardIndex, shardInfo, p2p, options);
1842
+ if (!result.hash) {
1843
+ if (!(result.buffer instanceof ArrayBuffer)) {
1844
+ throw new Error(`Shard ${shardIndex} p2p result missing hash and buffer.`);
1845
+ }
1846
+ result.hash = await computeHash(result.buffer, options.algorithm);
1847
+ }
1848
+ } else if (step.source === DISTRIBUTION_SOURCE_HTTP) {
1849
+ result = await downloadShardFromHttp(baseUrl, shardInfo, shardIndex, { ...options });
1850
+ }
1851
+
1852
+ assertExpectedManifestVersionSet(
1853
+ result.manifestVersionSet,
1854
+ options.expectedManifestVersionSet,
1855
+ shardIndex,
1856
+ step.source
1857
+ );
1858
+ assertExpectedHash(result.hash, options.expectedHash, shardIndex);
1859
+ assertExpectedSize(result.bytes, options.expectedSize, shardIndex);
1860
+
1861
+ appendDecisionTraceAttempt(trace, {
1862
+ source: step.source,
1863
+ status: 'success',
1864
+ durationMs: performance.now() - attemptStart,
1865
+ bytes: result.bytes,
1866
+ hash: result.hash,
1867
+ path: result.path,
1868
+ manifestVersionSet: result.manifestVersionSet,
1869
+ });
1870
+ appendAttemptLogAttempt(attemptLog, {
1871
+ source: step.source,
1872
+ status: 'success',
1873
+ durationMs: performance.now() - attemptStart,
1874
+ writeDurationMs: result.writeDurationMs,
1875
+ });
1876
+ return result;
1877
+ } catch (error) {
1878
+ if (error?.name === 'AbortError') {
1879
+ throw error;
1880
+ }
1881
+ lastError = error;
1882
+ appendDecisionTraceAttempt(trace, {
1883
+ source: step.source,
1884
+ status: 'failed',
1885
+ reason: step.reason,
1886
+ code: error?.code || null,
1887
+ message: error?.message || String(error),
1888
+ durationMs: performance.now() - attemptStart,
1889
+ });
1890
+ appendAttemptLogAttempt(attemptLog, {
1891
+ source: step.source,
1892
+ status: 'failed',
1893
+ code: error?.code || null,
1894
+ durationMs: performance.now() - attemptStart,
1895
+ });
1896
+ const enabledIndex = enabledSources.findIndex((entry) => entry.source === step.source);
1897
+ const isLastEnabled = enabledIndex === enabledSources.length - 1;
1898
+ const transitionType = (
1899
+ error?.code === 'cache_miss'
1900
+ || error?.code === 'p2p_unconfigured'
1901
+ || error?.code === P2P_TRANSPORT_ERROR_CODES.unconfigured
1902
+ || error?.code === P2P_TRANSPORT_ERROR_CODES.unavailable
1903
+ )
1904
+ ? 'onMiss'
1905
+ : 'onFailure';
1906
+ const transition = sourceMatrix?.[step.source]?.[transitionType] || 'next';
1907
+ if (isLastEnabled || transition === 'terminal') {
1908
+ log.warn('Distribution', `All shard delivery sources failed for shard ${shardIndex}: ${error.message}`);
1909
+ throw error;
1910
+ }
1911
+ log.warn('Distribution', `Shard ${shardIndex} source "${step.source}" failed (${error.code || 'error'}): ${error.message}`);
1912
+ continue;
1913
+ }
1914
+ }
1915
+
1916
+ throw lastError || new Error(`No shard delivery source available for shard ${shardIndex}`);
1917
+ }
1918
+
1919
+ export async function downloadShard(
1920
+ baseUrl,
1921
+ shardIndex,
1922
+ shardInfo,
1923
+ options = {}
1924
+ ) {
1925
+ const {
1926
+ sourceOrder,
1927
+ distributionConfig = {},
1928
+ distribution = {},
1929
+ maxRetries,
1930
+ initialRetryDelayMs,
1931
+ maxRetryDelayMs,
1932
+ requiredEncoding,
1933
+ algorithm,
1934
+ signal,
1935
+ onProgress = null,
1936
+ onDeliveryMetrics = null,
1937
+ writeToStore = false,
1938
+ enableSourceCache = true,
1939
+ p2pTransport,
1940
+ expectedSize,
1941
+ } = options;
1942
+
1943
+ if (!algorithm) {
1944
+ throw new Error('Missing hash algorithm for shard download verification.');
1945
+ }
1946
+
1947
+ const activeConfig = {
1948
+ ...(distributionConfig || {}),
1949
+ ...distribution,
1950
+ sourceOrder: sourceOrder || distributionConfig?.sourceOrder || distributionConfig?.sources,
1951
+ };
1952
+
1953
+ const antiRollback = normalizeAntiRollbackConfig(activeConfig);
1954
+ const decisionTraceConfig = normalizeDecisionTraceConfig(activeConfig);
1955
+ const sourceMatrix = normalizeSourceMatrix(activeConfig);
1956
+ const order = normalizeDistributionSourceOrder(activeConfig.sourceOrder);
1957
+
1958
+ const p2p = normalizeP2PConfig({
1959
+ ...activeConfig.p2p,
1960
+ transport: activeConfig?.p2p?.transport || p2pTransport,
1961
+ });
1962
+
1963
+ const downloadOptions = parseDownloadOptions({
1964
+ ...options,
1965
+ algorithm,
1966
+ onProgress,
1967
+ onDeliveryMetrics,
1968
+ signal,
1969
+ requiredEncoding: requiredEncoding ?? activeConfig.requiredContentEncoding ?? null,
1970
+ expectedHash: options.expectedHash ?? shardInfo?.hash ?? activeConfig.expectedHash ?? null,
1971
+ expectedSize: expectedSize ?? shardInfo?.size ?? null,
1972
+ expectedManifestVersionSet: options.expectedManifestVersionSet ?? null,
1973
+ writeToStore,
1974
+ maxRetries: maxRetries ?? activeConfig.maxRetries,
1975
+ initialRetryDelayMs: initialRetryDelayMs ?? activeConfig.initialRetryDelayMs,
1976
+ maxRetryDelayMs: maxRetryDelayMs ?? activeConfig.maxRetryDelayMs,
1977
+ });
1978
+
1979
+ if (antiRollback.enabled && antiRollback.requireExpectedHash && !downloadOptions.expectedHash) {
1980
+ throw createDopplerError(
1981
+ ERROR_CODES.DISTRIBUTION_SHARD_HASH_MISMATCH,
1982
+ `Missing expected hash for shard ${shardIndex} while antiRollback.requireExpectedHash=true.`
1983
+ );
1984
+ }
1985
+
1986
+ if (
1987
+ antiRollback.enabled
1988
+ && antiRollback.requireExpectedSize
1989
+ && !Number.isFinite(downloadOptions.expectedSize)
1990
+ ) {
1991
+ throw createDopplerError(
1992
+ ERROR_CODES.DISTRIBUTION_SHARD_SIZE_MISMATCH,
1993
+ `Missing expected size for shard ${shardIndex} while antiRollback.requireExpectedSize=true.`
1994
+ );
1995
+ }
1996
+
1997
+ if (
1998
+ antiRollback.enabled
1999
+ && antiRollback.requireManifestVersionSet
2000
+ && !downloadOptions.expectedManifestVersionSet
2001
+ ) {
2002
+ throw createDopplerError(
2003
+ ERROR_CODES.DISTRIBUTION_SHARD_MANIFEST_VERSION_SET_MISMATCH,
2004
+ `Missing expected manifestVersionSet for shard ${shardIndex} while antiRollback.requireManifestVersionSet=true.`
2005
+ );
2006
+ }
2007
+
2008
+ const planResult = resolveShardDeliveryPlan({
2009
+ sourceOrder: order,
2010
+ enableSourceCache,
2011
+ p2pEnabled: p2p.enabled,
2012
+ p2pTransportAvailable: typeof p2p.transport === 'function',
2013
+ httpEnabled: true,
2014
+ });
2015
+
2016
+ const trace = decisionTraceConfig.enabled
2017
+ && shouldEmitDecisionTrace(
2018
+ decisionTraceConfig,
2019
+ shardIndex,
2020
+ downloadOptions.expectedManifestVersionSet,
2021
+ order
2022
+ )
2023
+ ? createDecisionTrace(
2024
+ order,
2025
+ planResult.plan,
2026
+ shardIndex,
2027
+ decisionTraceConfig.deterministic,
2028
+ downloadOptions.expectedManifestVersionSet
2029
+ )
2030
+ : null;
2031
+
2032
+ const dedupeKey = createDeliveryKey(baseUrl, shardIndex, downloadOptions, order, sourceMatrix);
2033
+ if (inFlightDeliveries.has(dedupeKey)) {
2034
+ return await awaitWithSignal(
2035
+ inFlightDeliveries.get(dedupeKey),
2036
+ signal,
2037
+ `Shard ${shardIndex} delivery aborted`
2038
+ );
2039
+ }
2040
+
2041
+ const deliveryPromise = (async () => {
2042
+ const deliveryStart = performance.now();
2043
+ const attemptLog = [];
2044
+ const result = await executeDeliveryPlan(
2045
+ baseUrl,
2046
+ shardIndex,
2047
+ shardInfo,
2048
+ planResult.plan,
2049
+ p2p,
2050
+ downloadOptions,
2051
+ trace,
2052
+ decisionTraceConfig,
2053
+ sourceMatrix,
2054
+ attemptLog
2055
+ );
2056
+ const metrics = createDeliveryMetrics(
2057
+ order,
2058
+ result,
2059
+ attemptLog,
2060
+ performance.now() - deliveryStart
2061
+ );
2062
+ const resultWithMetrics = {
2063
+ ...result,
2064
+ deliveryMetrics: metrics,
2065
+ };
2066
+ await emitDeliveryMetricsHook(downloadOptions.onDeliveryMetrics, {
2067
+ schemaVersion: DISTRIBUTION_DELIVERY_METRICS_EVENT_SCHEMA_VERSION,
2068
+ shardIndex,
2069
+ source: result.source ?? null,
2070
+ path: result.path ?? null,
2071
+ expectedManifestVersionSet: downloadOptions.expectedManifestVersionSet ?? null,
2072
+ deliveryMetrics: metrics,
2073
+ decisionTrace: trace ?? null,
2074
+ });
2075
+ return attachDecisionTrace(resultWithMetrics, trace);
2076
+ })();
2077
+
2078
+ inFlightDeliveries.set(dedupeKey, deliveryPromise);
2079
+ try {
2080
+ return await awaitWithSignal(
2081
+ deliveryPromise,
2082
+ signal,
2083
+ `Shard ${shardIndex} delivery aborted`
2084
+ );
2085
+ } finally {
2086
+ inFlightDeliveries.delete(dedupeKey);
2087
+ }
2088
+ }
2089
+
2090
+ export function getSourceOrder(config = {}) {
2091
+ return normalizeDistributionSourceOrder(config.sourceOrder || config.sources || DISTRIBUTION_SOURCES);
2092
+ }
2093
+
2094
+ export function getInFlightShardDeliveryCount() {
2095
+ return inFlightDeliveries.size;
2096
+ }