mtplx 2.7.0__tar.gz → 2.7.2__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (542) hide show
  1. {mtplx-2.7.0 → mtplx-2.7.2}/CHANGELOG.md +79 -0
  2. {mtplx-2.7.0 → mtplx-2.7.2}/PKG-INFO +1 -1
  3. {mtplx-2.7.0 → mtplx-2.7.2}/mtplx/backends/descriptors.py +4 -0
  4. {mtplx-2.7.0 → mtplx-2.7.2}/mtplx/cli.py +2 -1
  5. {mtplx-2.7.0 → mtplx-2.7.2}/mtplx/commands/forge.py +77 -0
  6. {mtplx-2.7.0 → mtplx-2.7.2}/mtplx/commands/public.py +5 -2
  7. {mtplx-2.7.0 → mtplx-2.7.2}/mtplx/diagnostics.py +5 -5
  8. {mtplx-2.7.0 → mtplx-2.7.2}/mtplx/hf_loader.py +6 -4
  9. {mtplx-2.7.0 → mtplx-2.7.2}/mtplx/model_catalog.py +18 -12
  10. {mtplx-2.7.0 → mtplx-2.7.2}/mtplx/profiles.py +3 -2
  11. mtplx-2.7.2/mtplx/reasoning_effort.py +37 -0
  12. {mtplx-2.7.0 → mtplx-2.7.2}/mtplx/server/openai.py +7 -16
  13. {mtplx-2.7.0 → mtplx-2.7.2}/mtplx/version.py +2 -2
  14. mtplx-2.7.2/mtplx/vision_graft.py +372 -0
  15. {mtplx-2.7.0 → mtplx-2.7.2}/mtplx.egg-info/PKG-INFO +1 -1
  16. {mtplx-2.7.0 → mtplx-2.7.2}/mtplx.egg-info/SOURCES.txt +3 -0
  17. {mtplx-2.7.0 → mtplx-2.7.2}/pyproject.toml +1 -1
  18. mtplx-2.7.2/scripts/graft_vision_tower.py +69 -0
  19. {mtplx-2.7.0 → mtplx-2.7.2}/scripts/pillar_gate_qa.py +16 -0
  20. {mtplx-2.7.0 → mtplx-2.7.2}/scripts/release_macos_v1.sh +7 -1
  21. {mtplx-2.7.0 → mtplx-2.7.2}/tests/test_artifacts.py +85 -0
  22. {mtplx-2.7.0 → mtplx-2.7.2}/tests/test_compressed_tensors.py +24 -0
  23. {mtplx-2.7.0 → mtplx-2.7.2}/tests/test_forge_cli.py +178 -0
  24. {mtplx-2.7.0 → mtplx-2.7.2}/tests/test_public_cli.py +25 -0
  25. {mtplx-2.7.0 → mtplx-2.7.2}/tests/test_qwen38_family.py +56 -0
  26. {mtplx-2.7.0 → mtplx-2.7.2}/tests/test_server_openai.py +20 -0
  27. {mtplx-2.7.0 → mtplx-2.7.2}/CITATION.cff +0 -0
  28. {mtplx-2.7.0 → mtplx-2.7.2}/LICENSE +0 -0
  29. {mtplx-2.7.0 → mtplx-2.7.2}/MANIFEST.in +0 -0
  30. {mtplx-2.7.0 → mtplx-2.7.2}/NOTICE +0 -0
  31. {mtplx-2.7.0 → mtplx-2.7.2}/README.md +0 -0
  32. {mtplx-2.7.0 → mtplx-2.7.2}/mtplx/__init__.py +0 -0
  33. {mtplx-2.7.0 → mtplx-2.7.2}/mtplx/a3b_compiled_target_prefix.py +0 -0
  34. {mtplx-2.7.0 → mtplx-2.7.2}/mtplx/a3b_mtp_batch.py +0 -0
  35. {mtplx-2.7.0 → mtplx-2.7.2}/mtplx/a3b_whole_moe.py +0 -0
  36. {mtplx-2.7.0 → mtplx-2.7.2}/mtplx/adaptive.py +0 -0
  37. {mtplx-2.7.0 → mtplx-2.7.2}/mtplx/app_settings.py +0 -0
  38. {mtplx-2.7.0 → mtplx-2.7.2}/mtplx/arrays_cache_patch.py +0 -0
  39. {mtplx-2.7.0 → mtplx-2.7.2}/mtplx/artifacts.py +0 -0
  40. {mtplx-2.7.0 → mtplx-2.7.2}/mtplx/attention_context.py +0 -0
  41. {mtplx-2.7.0 → mtplx-2.7.2}/mtplx/attention_split.py +0 -0
  42. {mtplx-2.7.0 → mtplx-2.7.2}/mtplx/backends/__init__.py +0 -0
  43. {mtplx-2.7.0 → mtplx-2.7.2}/mtplx/backends/deepseek_mtp.py +0 -0
  44. {mtplx-2.7.0 → mtplx-2.7.2}/mtplx/backends/gemma4_assistant.py +0 -0
  45. {mtplx-2.7.0 → mtplx-2.7.2}/mtplx/backends/glm_mtp.py +0 -0
  46. {mtplx-2.7.0 → mtplx-2.7.2}/mtplx/backends/hy_v3_mtp.py +0 -0
  47. {mtplx-2.7.0 → mtplx-2.7.2}/mtplx/backends/mimo_mtp.py +0 -0
  48. {mtplx-2.7.0 → mtplx-2.7.2}/mtplx/backends/nemotron_h_mtp.py +0 -0
  49. {mtplx-2.7.0 → mtplx-2.7.2}/mtplx/backends/qwen3_next.py +0 -0
  50. {mtplx-2.7.0 → mtplx-2.7.2}/mtplx/backends/registry.py +0 -0
  51. {mtplx-2.7.0 → mtplx-2.7.2}/mtplx/backends/step3p5_mtp.py +0 -0
  52. {mtplx-2.7.0 → mtplx-2.7.2}/mtplx/batched_decode.py +0 -0
  53. {mtplx-2.7.0 → mtplx-2.7.2}/mtplx/batching/__init__.py +0 -0
  54. {mtplx-2.7.0 → mtplx-2.7.2}/mtplx/batching/admission.py +0 -0
  55. {mtplx-2.7.0 → mtplx-2.7.2}/mtplx/batching/buckets.py +0 -0
  56. {mtplx-2.7.0 → mtplx-2.7.2}/mtplx/batching/scheduler.py +0 -0
  57. {mtplx-2.7.0 → mtplx-2.7.2}/mtplx/batching/state.py +0 -0
  58. {mtplx-2.7.0 → mtplx-2.7.2}/mtplx/benchmarks/__init__.py +0 -0
  59. {mtplx-2.7.0 → mtplx-2.7.2}/mtplx/benchmarks/code_eval.py +0 -0
  60. {mtplx-2.7.0 → mtplx-2.7.2}/mtplx/benchmarks/programming_prompts.py +0 -0
  61. {mtplx-2.7.0 → mtplx-2.7.2}/mtplx/benchmarks/prompts/aime_2026.jsonl +0 -0
  62. {mtplx-2.7.0 → mtplx-2.7.2}/mtplx/benchmarks/prompts/calibration_coding.jsonl +0 -0
  63. {mtplx-2.7.0 → mtplx-2.7.2}/mtplx/benchmarks/prompts/default.jsonl +0 -0
  64. {mtplx-2.7.0 → mtplx-2.7.2}/mtplx/benchmarks/prompts/flappy.jsonl +0 -0
  65. {mtplx-2.7.0 → mtplx-2.7.2}/mtplx/benchmarks/prompts/long_code.jsonl +0 -0
  66. {mtplx-2.7.0 → mtplx-2.7.2}/mtplx/benchmarks/prompts/long_code_uncapped.jsonl +0 -0
  67. {mtplx-2.7.0 → mtplx-2.7.2}/mtplx/benchmarks/prompts/python_modules_long.jsonl +0 -0
  68. {mtplx-2.7.0 → mtplx-2.7.2}/mtplx/benchmarks/runners/__init__.py +0 -0
  69. {mtplx-2.7.0 → mtplx-2.7.2}/mtplx/benchmarks/runners/aime.py +0 -0
  70. {mtplx-2.7.0 → mtplx-2.7.2}/mtplx/benchmarks/runners/batch_equivalence.py +0 -0
  71. {mtplx-2.7.0 → mtplx-2.7.2}/mtplx/benchmarks/runners/capture_commit_equivalence.py +0 -0
  72. {mtplx-2.7.0 → mtplx-2.7.2}/mtplx/benchmarks/runners/competitor_baselines.py +0 -0
  73. {mtplx-2.7.0 → mtplx-2.7.2}/mtplx/benchmarks/runners/contract_probe.py +0 -0
  74. {mtplx-2.7.0 → mtplx-2.7.2}/mtplx/benchmarks/runners/harness.py +0 -0
  75. {mtplx-2.7.0 → mtplx-2.7.2}/mtplx/benchmarks/runners/mtp1_gate.py +0 -0
  76. {mtplx-2.7.0 → mtplx-2.7.2}/mtplx/benchmarks/runners/mtp1_sampler_smoke.py +0 -0
  77. {mtplx-2.7.0 → mtplx-2.7.2}/mtplx/benchmarks/runners/mtp_adaptive.py +0 -0
  78. {mtplx-2.7.0 → mtplx-2.7.2}/mtplx/benchmarks/runners/mtp_chain_probe.py +0 -0
  79. {mtplx-2.7.0 → mtplx-2.7.2}/mtplx/benchmarks/runners/mtp_depth_grid.py +0 -0
  80. {mtplx-2.7.0 → mtplx-2.7.2}/mtplx/benchmarks/runners/mtp_depth_sweep.py +0 -0
  81. {mtplx-2.7.0 → mtplx-2.7.2}/mtplx/benchmarks/runners/mtp_tree_probe.py +0 -0
  82. {mtplx-2.7.0 → mtplx-2.7.2}/mtplx/benchmarks/runners/multi_qmv_probe.py +0 -0
  83. {mtplx-2.7.0 → mtplx-2.7.2}/mtplx/benchmarks/runners/preflight.py +0 -0
  84. {mtplx-2.7.0 → mtplx-2.7.2}/mtplx/benchmarks/runners/runtime_smoke.py +0 -0
  85. {mtplx-2.7.0 → mtplx-2.7.2}/mtplx/benchmarks/runners/session_bank.py +0 -0
  86. {mtplx-2.7.0 → mtplx-2.7.2}/mtplx/benchmarks/runners/truth.py +0 -0
  87. {mtplx-2.7.0 → mtplx-2.7.2}/mtplx/benchmarks/runners/verify_profile.py +0 -0
  88. {mtplx-2.7.0 → mtplx-2.7.2}/mtplx/benchmarks/runners/verify_qmm_probe.py +0 -0
  89. {mtplx-2.7.0 → mtplx-2.7.2}/mtplx/benchmarks/runners/verify_ratio.py +0 -0
  90. {mtplx-2.7.0 → mtplx-2.7.2}/mtplx/benchmarks/schema.py +0 -0
  91. {mtplx-2.7.0 → mtplx-2.7.2}/mtplx/benchmarks/validators/__init__.py +0 -0
  92. {mtplx-2.7.0 → mtplx-2.7.2}/mtplx/benchmarks/validators/aime.py +0 -0
  93. {mtplx-2.7.0 → mtplx-2.7.2}/mtplx/benchmarks/validators/basic.py +0 -0
  94. {mtplx-2.7.0 → mtplx-2.7.2}/mtplx/block_attention.py +0 -0
  95. {mtplx-2.7.0 → mtplx-2.7.2}/mtplx/cache_bank/__init__.py +0 -0
  96. {mtplx-2.7.0 → mtplx-2.7.2}/mtplx/cache_bank/codec.py +0 -0
  97. {mtplx-2.7.0 → mtplx-2.7.2}/mtplx/cache_bank/cold_tier.py +0 -0
  98. {mtplx-2.7.0 → mtplx-2.7.2}/mtplx/cache_state.py +0 -0
  99. {mtplx-2.7.0 → mtplx-2.7.2}/mtplx/chat_encode_cache.py +0 -0
  100. {mtplx-2.7.0 → mtplx-2.7.2}/mtplx/chat_encoding.py +0 -0
  101. {mtplx-2.7.0 → mtplx-2.7.2}/mtplx/commands/__init__.py +0 -0
  102. {mtplx-2.7.0 → mtplx-2.7.2}/mtplx/commands/forge_mixed_convert.py +0 -0
  103. {mtplx-2.7.0 → mtplx-2.7.2}/mtplx/compile_state.py +0 -0
  104. {mtplx-2.7.0 → mtplx-2.7.2}/mtplx/compiled_forward.py +0 -0
  105. {mtplx-2.7.0 → mtplx-2.7.2}/mtplx/compressed_tensors.py +0 -0
  106. {mtplx-2.7.0 → mtplx-2.7.2}/mtplx/config.py +0 -0
  107. {mtplx-2.7.0 → mtplx-2.7.2}/mtplx/constants.py +0 -0
  108. {mtplx-2.7.0 → mtplx-2.7.2}/mtplx/constrained.py +0 -0
  109. {mtplx-2.7.0 → mtplx-2.7.2}/mtplx/context_copy.py +0 -0
  110. {mtplx-2.7.0 → mtplx-2.7.2}/mtplx/correctors/__init__.py +0 -0
  111. {mtplx-2.7.0 → mtplx-2.7.2}/mtplx/correctors/diagonal_affine.py +0 -0
  112. {mtplx-2.7.0 → mtplx-2.7.2}/mtplx/correctors/low_rank.py +0 -0
  113. {mtplx-2.7.0 → mtplx-2.7.2}/mtplx/daemon_client.py +0 -0
  114. {mtplx-2.7.0 → mtplx-2.7.2}/mtplx/dashboard/__init__.py +0 -0
  115. {mtplx-2.7.0 → mtplx-2.7.2}/mtplx/dashboard/_static/assets/index-CRP90ECi.js +0 -0
  116. {mtplx-2.7.0 → mtplx-2.7.2}/mtplx/dashboard/_static/assets/index-DYvLRZ33.css +0 -0
  117. {mtplx-2.7.0 → mtplx-2.7.2}/mtplx/dashboard/_static/index.html +0 -0
  118. {mtplx-2.7.0 → mtplx-2.7.2}/mtplx/deepseek_mtp_patch.py +0 -0
  119. {mtplx-2.7.0 → mtplx-2.7.2}/mtplx/deepseek_v4_adaptive_width.py +0 -0
  120. {mtplx-2.7.0 → mtplx-2.7.2}/mtplx/deepseek_v4_attention_island.py +0 -0
  121. {mtplx-2.7.0 → mtplx-2.7.2}/mtplx/deepseek_v4_attn_proj_wide_m3.py +0 -0
  122. {mtplx-2.7.0 → mtplx-2.7.2}/mtplx/default_models.py +0 -0
  123. {mtplx-2.7.0 → mtplx-2.7.2}/mtplx/draft_lm_head.py +0 -0
  124. {mtplx-2.7.0 → mtplx-2.7.2}/mtplx/draft_sampling.py +0 -0
  125. {mtplx-2.7.0 → mtplx-2.7.2}/mtplx/engine_session.py +0 -0
  126. {mtplx-2.7.0 → mtplx-2.7.2}/mtplx/env.py +0 -0
  127. {mtplx-2.7.0 → mtplx-2.7.2}/mtplx/errors.py +0 -0
  128. {mtplx-2.7.0 → mtplx-2.7.2}/mtplx/expert_layout.py +0 -0
  129. {mtplx-2.7.0 → mtplx-2.7.2}/mtplx/fan_mode.py +0 -0
  130. {mtplx-2.7.0 → mtplx-2.7.2}/mtplx/fast_sampling.py +0 -0
  131. {mtplx-2.7.0 → mtplx-2.7.2}/mtplx/gdn_capture.py +0 -0
  132. {mtplx-2.7.0 → mtplx-2.7.2}/mtplx/gemma4_pair.py +0 -0
  133. {mtplx-2.7.0 → mtplx-2.7.2}/mtplx/generation.py +0 -0
  134. {mtplx-2.7.0 → mtplx-2.7.2}/mtplx/glm_mtp_patch.py +0 -0
  135. {mtplx-2.7.0 → mtplx-2.7.2}/mtplx/graphbank.py +0 -0
  136. {mtplx-2.7.0 → mtplx-2.7.2}/mtplx/hardware.py +0 -0
  137. {mtplx-2.7.0 → mtplx-2.7.2}/mtplx/hy_v3_mtp_patch.py +0 -0
  138. {mtplx-2.7.0 → mtplx-2.7.2}/mtplx/kernel_selfcheck.py +0 -0
  139. {mtplx-2.7.0 → mtplx-2.7.2}/mtplx/kernels/__init__.py +0 -0
  140. {mtplx-2.7.0 → mtplx-2.7.2}/mtplx/kernels/a3b_whole_moe.py +0 -0
  141. {mtplx-2.7.0 → mtplx-2.7.2}/mtplx/kernels/copy_leaf.py +0 -0
  142. {mtplx-2.7.0 → mtplx-2.7.2}/mtplx/kernels/fused_norm.py +0 -0
  143. {mtplx-2.7.0 → mtplx-2.7.2}/mtplx/kernels/gdn_blocked_prefill.py +0 -0
  144. {mtplx-2.7.0 → mtplx-2.7.2}/mtplx/kernels/gdn_tape_headquarter.py +0 -0
  145. {mtplx-2.7.0 → mtplx-2.7.2}/mtplx/kernels/laguna_decode.py +0 -0
  146. {mtplx-2.7.0 → mtplx-2.7.2}/mtplx/kernels/laguna_dense_mlp.py +0 -0
  147. {mtplx-2.7.0 → mtplx-2.7.2}/mtplx/kernels/laguna_gated_oproj.py +0 -0
  148. {mtplx-2.7.0 → mtplx-2.7.2}/mtplx/kernels/laguna_moe_combine.py +0 -0
  149. {mtplx-2.7.0 → mtplx-2.7.2}/mtplx/kernels/laguna_moe_gather_gemm.py +0 -0
  150. {mtplx-2.7.0 → mtplx-2.7.2}/mtplx/kernels/laguna_moe_merged.py +0 -0
  151. {mtplx-2.7.0 → mtplx-2.7.2}/mtplx/kernels/laguna_moe_shared.py +0 -0
  152. {mtplx-2.7.0 → mtplx-2.7.2}/mtplx/kernels/laguna_moe_swiglu.py +0 -0
  153. {mtplx-2.7.0 → mtplx-2.7.2}/mtplx/kernels/laguna_prefill_moe_combine.py +0 -0
  154. {mtplx-2.7.0 → mtplx-2.7.2}/mtplx/kernels/laguna_prefill_qk_rope.py +0 -0
  155. {mtplx-2.7.0 → mtplx-2.7.2}/mtplx/kernels/laguna_prefill_router.py +0 -0
  156. {mtplx-2.7.0 → mtplx-2.7.2}/mtplx/kernels/laguna_qk_rope_sliding.py +0 -0
  157. {mtplx-2.7.0 → mtplx-2.7.2}/mtplx/kernels/laguna_qk_yarn_full.py +0 -0
  158. {mtplx-2.7.0 → mtplx-2.7.2}/mtplx/kernels/laguna_qkvg_fused.py +0 -0
  159. {mtplx-2.7.0 → mtplx-2.7.2}/mtplx/kernels/laguna_residual_router.py +0 -0
  160. {mtplx-2.7.0 → mtplx-2.7.2}/mtplx/kernels/laguna_route_csort.py +0 -0
  161. {mtplx-2.7.0 → mtplx-2.7.2}/mtplx/kernels/laguna_router_topk.py +0 -0
  162. {mtplx-2.7.0 → mtplx-2.7.2}/mtplx/kernels/laguna_sdpa_2pass.py +0 -0
  163. {mtplx-2.7.0 → mtplx-2.7.2}/mtplx/kernels/laguna_sdpa_pair.py +0 -0
  164. {mtplx-2.7.0 → mtplx-2.7.2}/mtplx/kernels/laguna_steel_attn.py +0 -0
  165. {mtplx-2.7.0 → mtplx-2.7.2}/mtplx/kernels/lm_head_topk.py +0 -0
  166. {mtplx-2.7.0 → mtplx-2.7.2}/mtplx/kernels/logits_topk.py +0 -0
  167. {mtplx-2.7.0 → mtplx-2.7.2}/mtplx/kernels/native_gdn_tail.py +0 -0
  168. {mtplx-2.7.0 → mtplx-2.7.2}/mtplx/kernels/sdpa_2pass.py +0 -0
  169. {mtplx-2.7.0 → mtplx-2.7.2}/mtplx/kernels/sdpa_2pass_paged.py +0 -0
  170. {mtplx-2.7.0 → mtplx-2.7.2}/mtplx/kernels/sdpa_2pass_paged_q8.py +0 -0
  171. {mtplx-2.7.0 → mtplx-2.7.2}/mtplx/kernels/sdpa_gqa_packed.py +0 -0
  172. {mtplx-2.7.0 → mtplx-2.7.2}/mtplx/kernels/verify_mlp_fused.py +0 -0
  173. {mtplx-2.7.0 → mtplx-2.7.2}/mtplx/kpi/__init__.py +0 -0
  174. {mtplx-2.7.0 → mtplx-2.7.2}/mtplx/kpi/reference_vllm.py +0 -0
  175. {mtplx-2.7.0 → mtplx-2.7.2}/mtplx/kpi/runtime_kpis.py +0 -0
  176. {mtplx-2.7.0 → mtplx-2.7.2}/mtplx/kv_quant.py +0 -0
  177. {mtplx-2.7.0 → mtplx-2.7.2}/mtplx/laguna_alt_step.py +0 -0
  178. {mtplx-2.7.0 → mtplx-2.7.2}/mtplx/laguna_compiled_step.py +0 -0
  179. {mtplx-2.7.0 → mtplx-2.7.2}/mtplx/lfm2_fast.py +0 -0
  180. {mtplx-2.7.0 → mtplx-2.7.2}/mtplx/loop_guard.py +0 -0
  181. {mtplx-2.7.0 → mtplx-2.7.2}/mtplx/metadata_scrub.py +0 -0
  182. {mtplx-2.7.0 → mtplx-2.7.2}/mtplx/mimo_mtp_patch.py +0 -0
  183. {mtplx-2.7.0 → mtplx-2.7.2}/mtplx/model_scheduler.py +0 -0
  184. {mtplx-2.7.0 → mtplx-2.7.2}/mtplx/models/__init__.py +0 -0
  185. {mtplx-2.7.0 → mtplx-2.7.2}/mtplx/models/deepseek_v4.py +0 -0
  186. {mtplx-2.7.0 → mtplx-2.7.2}/mtplx/models/laguna.py +0 -0
  187. {mtplx-2.7.0 → mtplx-2.7.2}/mtplx/models/laguna_config.py +0 -0
  188. {mtplx-2.7.0 → mtplx-2.7.2}/mtplx/models/laguna_fused.py +0 -0
  189. {mtplx-2.7.0 → mtplx-2.7.2}/mtplx/moe_packed_projections.py +0 -0
  190. {mtplx-2.7.0 → mtplx-2.7.2}/mtplx/mtp_activation_stats.py +0 -0
  191. {mtplx-2.7.0 → mtplx-2.7.2}/mtplx/mtp_adapters.py +0 -0
  192. {mtplx-2.7.0 → mtplx-2.7.2}/mtplx/mtp_batch_numerics.py +0 -0
  193. {mtplx-2.7.0 → mtplx-2.7.2}/mtplx/mtp_patch.py +0 -0
  194. {mtplx-2.7.0 → mtplx-2.7.2}/mtplx/native_mlp.py +0 -0
  195. {mtplx-2.7.0 → mtplx-2.7.2}/mtplx/nax_verify.py +0 -0
  196. {mtplx-2.7.0 → mtplx-2.7.2}/mtplx/nemotron_h_mtp_patch.py +0 -0
  197. {mtplx-2.7.0 → mtplx-2.7.2}/mtplx/opencode.py +0 -0
  198. {mtplx-2.7.0 → mtplx-2.7.2}/mtplx/optimization_profiles.py +0 -0
  199. {mtplx-2.7.0 → mtplx-2.7.2}/mtplx/pi.py +0 -0
  200. {mtplx-2.7.0 → mtplx-2.7.2}/mtplx/prefill_bench.py +0 -0
  201. {mtplx-2.7.0 → mtplx-2.7.2}/mtplx/progress_heartbeat.py +0 -0
  202. {mtplx-2.7.0 → mtplx-2.7.2}/mtplx/proj_quant.py +0 -0
  203. {mtplx-2.7.0 → mtplx-2.7.2}/mtplx/proposal_reranker.py +0 -0
  204. {mtplx-2.7.0 → mtplx-2.7.2}/mtplx/qwen3_5_mtp_patch.py +0 -0
  205. {mtplx-2.7.0 → mtplx-2.7.2}/mtplx/qwen_row_owned_router.py +0 -0
  206. {mtplx-2.7.0 → mtplx-2.7.2}/mtplx/ragged_attention.py +0 -0
  207. {mtplx-2.7.0 → mtplx-2.7.2}/mtplx/ragged_kv_cache.py +0 -0
  208. {mtplx-2.7.0 → mtplx-2.7.2}/mtplx/reasoning_codecs.py +0 -0
  209. {mtplx-2.7.0 → mtplx-2.7.2}/mtplx/request_capture.py +0 -0
  210. {mtplx-2.7.0 → mtplx-2.7.2}/mtplx/retrieval.py +0 -0
  211. {mtplx-2.7.0 → mtplx-2.7.2}/mtplx/roofline_profile.py +0 -0
  212. {mtplx-2.7.0 → mtplx-2.7.2}/mtplx/runtime.py +0 -0
  213. {mtplx-2.7.0 → mtplx-2.7.2}/mtplx/runtime_options.py +0 -0
  214. {mtplx-2.7.0 → mtplx-2.7.2}/mtplx/sampling.py +0 -0
  215. {mtplx-2.7.0 → mtplx-2.7.2}/mtplx/server/__init__.py +0 -0
  216. {mtplx-2.7.0 → mtplx-2.7.2}/mtplx/server/dashboard_state.py +0 -0
  217. {mtplx-2.7.0 → mtplx-2.7.2}/mtplx/server/mtp_batch.py +0 -0
  218. {mtplx-2.7.0 → mtplx-2.7.2}/mtplx/server/omlx_bridge/__init__.py +0 -0
  219. {mtplx-2.7.0 → mtplx-2.7.2}/mtplx/server/omlx_bridge/adapter.py +0 -0
  220. {mtplx-2.7.0 → mtplx-2.7.2}/mtplx/server/omlx_bridge/thinking.py +0 -0
  221. {mtplx-2.7.0 → mtplx-2.7.2}/mtplx/server/omlx_bridge/tool_calling.py +0 -0
  222. {mtplx-2.7.0 → mtplx-2.7.2}/mtplx/server_urls.py +0 -0
  223. {mtplx-2.7.0 → mtplx-2.7.2}/mtplx/session_bank.py +0 -0
  224. {mtplx-2.7.0 → mtplx-2.7.2}/mtplx/speculative.py +0 -0
  225. {mtplx-2.7.0 → mtplx-2.7.2}/mtplx/step3p5_mtp_patch.py +0 -0
  226. {mtplx-2.7.0 → mtplx-2.7.2}/mtplx/swival.py +0 -0
  227. {mtplx-2.7.0 → mtplx-2.7.2}/mtplx/templates/qwen36_froggeric_v19/chat_template.jinja +0 -0
  228. {mtplx-2.7.0 → mtplx-2.7.2}/mtplx/templates/qwen36_froggeric_v21_3/chat_template.jinja +0 -0
  229. {mtplx-2.7.0 → mtplx-2.7.2}/mtplx/thermal.py +0 -0
  230. {mtplx-2.7.0 → mtplx-2.7.2}/mtplx/thermal_sidecar.py +0 -0
  231. {mtplx-2.7.0 → mtplx-2.7.2}/mtplx/thinking_guard.py +0 -0
  232. {mtplx-2.7.0 → mtplx-2.7.2}/mtplx/trace_parity.py +0 -0
  233. {mtplx-2.7.0 → mtplx-2.7.2}/mtplx/turboquant.py +0 -0
  234. {mtplx-2.7.0 → mtplx-2.7.2}/mtplx/ui/__init__.py +0 -0
  235. {mtplx-2.7.0 → mtplx-2.7.2}/mtplx/ui/banner.py +0 -0
  236. {mtplx-2.7.0 → mtplx-2.7.2}/mtplx/ui/chat_printer.py +0 -0
  237. {mtplx-2.7.0 → mtplx-2.7.2}/mtplx/ui/download_progress.py +0 -0
  238. {mtplx-2.7.0 → mtplx-2.7.2}/mtplx/ui/onboarding.py +0 -0
  239. {mtplx-2.7.0 → mtplx-2.7.2}/mtplx/ui/panels.py +0 -0
  240. {mtplx-2.7.0 → mtplx-2.7.2}/mtplx/ui/progress.py +0 -0
  241. {mtplx-2.7.0 → mtplx-2.7.2}/mtplx/vendored_arrays_cache.py +0 -0
  242. {mtplx-2.7.0 → mtplx-2.7.2}/mtplx/vendored_hy_v3.py +0 -0
  243. {mtplx-2.7.0 → mtplx-2.7.2}/mtplx/verify_kernels.py +0 -0
  244. {mtplx-2.7.0 → mtplx-2.7.2}/mtplx/verify_qmv.py +0 -0
  245. {mtplx-2.7.0 → mtplx-2.7.2}/mtplx/vision/__init__.py +0 -0
  246. {mtplx-2.7.0 → mtplx-2.7.2}/mtplx/vision/processing.py +0 -0
  247. {mtplx-2.7.0 → mtplx-2.7.2}/mtplx/vision/qwen3_vl_tower.py +0 -0
  248. {mtplx-2.7.0 → mtplx-2.7.2}/mtplx/vision/splice.py +0 -0
  249. {mtplx-2.7.0 → mtplx-2.7.2}/mtplx.egg-info/dependency_links.txt +0 -0
  250. {mtplx-2.7.0 → mtplx-2.7.2}/mtplx.egg-info/entry_points.txt +0 -0
  251. {mtplx-2.7.0 → mtplx-2.7.2}/mtplx.egg-info/requires.txt +0 -0
  252. {mtplx-2.7.0 → mtplx-2.7.2}/mtplx.egg-info/top_level.txt +0 -0
  253. {mtplx-2.7.0 → mtplx-2.7.2}/scripts/agent_user_path_qa.py +0 -0
  254. {mtplx-2.7.0 → mtplx-2.7.2}/scripts/aime_serve_gate.py +0 -0
  255. {mtplx-2.7.0 → mtplx-2.7.2}/scripts/aime_shape_memory_bench.py +0 -0
  256. {mtplx-2.7.0 → mtplx-2.7.2}/scripts/code_eval_gate.py +0 -0
  257. {mtplx-2.7.0 → mtplx-2.7.2}/scripts/collect_mtp_activation_stats.py +0 -0
  258. {mtplx-2.7.0 → mtplx-2.7.2}/scripts/collect_mtp_hidden_calib.py +0 -0
  259. {mtplx-2.7.0 → mtplx-2.7.2}/scripts/combine_mtp_adapters.py +0 -0
  260. {mtplx-2.7.0 → mtplx-2.7.2}/scripts/compiled_verify_exactness.py +0 -0
  261. {mtplx-2.7.0 → mtplx-2.7.2}/scripts/convert_step37_to_mtplx_step3p5.py +0 -0
  262. {mtplx-2.7.0 → mtplx-2.7.2}/scripts/deepseek_v4_adaptive_width_arms.sh +0 -0
  263. {mtplx-2.7.0 → mtplx-2.7.2}/scripts/deepseek_v4_adaptive_width_guarded.py +0 -0
  264. {mtplx-2.7.0 → mtplx-2.7.2}/scripts/deepseek_v4_attention_island_arms.sh +0 -0
  265. {mtplx-2.7.0 → mtplx-2.7.2}/scripts/deepseek_v4_attention_island_guarded.py +0 -0
  266. {mtplx-2.7.0 → mtplx-2.7.2}/scripts/deepseek_v4_attn_proj_wide_m3_arms.sh +0 -0
  267. {mtplx-2.7.0 → mtplx-2.7.2}/scripts/deepseek_v4_attn_proj_wide_m3_guarded.py +0 -0
  268. {mtplx-2.7.0 → mtplx-2.7.2}/scripts/deepseek_v4_build_mtp_model.py +0 -0
  269. {mtplx-2.7.0 → mtplx-2.7.2}/scripts/deepseek_v4_decode_verify.py +0 -0
  270. {mtplx-2.7.0 → mtplx-2.7.2}/scripts/deepseek_v4_dispatch_census.py +0 -0
  271. {mtplx-2.7.0 → mtplx-2.7.2}/scripts/deepseek_v4_guard_window.py +0 -0
  272. {mtplx-2.7.0 → mtplx-2.7.2}/scripts/deepseek_v4_logits_gate.py +0 -0
  273. {mtplx-2.7.0 → mtplx-2.7.2}/scripts/deepseek_v4_moe_tail_arms.sh +0 -0
  274. {mtplx-2.7.0 → mtplx-2.7.2}/scripts/deepseek_v4_moe_tail_gate.py +0 -0
  275. {mtplx-2.7.0 → mtplx-2.7.2}/scripts/deepseek_v4_moe_tail_guarded_bracket.py +0 -0
  276. {mtplx-2.7.0 → mtplx-2.7.2}/scripts/deepseek_v4_mtp_bind_check.py +0 -0
  277. {mtplx-2.7.0 → mtplx-2.7.2}/scripts/deepseek_v4_mtpk_bench.py +0 -0
  278. {mtplx-2.7.0 → mtplx-2.7.2}/scripts/deepseek_v4_op_census.py +0 -0
  279. {mtplx-2.7.0 → mtplx-2.7.2}/scripts/deepseek_v4_smoke_generate.py +0 -0
  280. {mtplx-2.7.0 → mtplx-2.7.2}/scripts/deepseek_v4_sparse_gate_probe.py +0 -0
  281. {mtplx-2.7.0 → mtplx-2.7.2}/scripts/deepseek_v4_validate_moe_tail_k3_bracket.py +0 -0
  282. {mtplx-2.7.0 → mtplx-2.7.2}/scripts/eval_mtp_corrector.py +0 -0
  283. {mtplx-2.7.0 → mtplx-2.7.2}/scripts/filter_mtp_adapter.py +0 -0
  284. {mtplx-2.7.0 → mtplx-2.7.2}/scripts/fp16_turbo_exactness_20260707.py +0 -0
  285. {mtplx-2.7.0 → mtplx-2.7.2}/scripts/fresh_venv_smoke.sh +0 -0
  286. {mtplx-2.7.0 → mtplx-2.7.2}/scripts/gauntlet_scoreboard.py +0 -0
  287. {mtplx-2.7.0 → mtplx-2.7.2}/scripts/hygiene_scan.sh +0 -0
  288. {mtplx-2.7.0 → mtplx-2.7.2}/scripts/install_macos.sh +0 -0
  289. {mtplx-2.7.0 → mtplx-2.7.2}/scripts/install_preview_global.sh +0 -0
  290. {mtplx-2.7.0 → mtplx-2.7.2}/scripts/kvcache_exactness_audit_20260703.py +0 -0
  291. {mtplx-2.7.0 → mtplx-2.7.2}/scripts/kvcache_soak_20260703.py +0 -0
  292. {mtplx-2.7.0 → mtplx-2.7.2}/scripts/kvcache_warm_probe_20260703.py +0 -0
  293. {mtplx-2.7.0 → mtplx-2.7.2}/scripts/make_fp16_precision_sibling.py +0 -0
  294. {mtplx-2.7.0 → mtplx-2.7.2}/scripts/midform_gate.py +0 -0
  295. {mtplx-2.7.0 → mtplx-2.7.2}/scripts/oc_tap.py +0 -0
  296. {mtplx-2.7.0 → mtplx-2.7.2}/scripts/oc_tap_diff.py +0 -0
  297. {mtplx-2.7.0 → mtplx-2.7.2}/scripts/ocspeed-20260703/abba_final.sh +0 -0
  298. {mtplx-2.7.0 → mtplx-2.7.2}/scripts/ocspeed-20260703/accept_depth_probe.py +0 -0
  299. {mtplx-2.7.0 → mtplx-2.7.2}/scripts/ocspeed-20260703/arm_runner.sh +0 -0
  300. {mtplx-2.7.0 → mtplx-2.7.2}/scripts/ocspeed-20260703/forward_depth_bisect.py +0 -0
  301. {mtplx-2.7.0 → mtplx-2.7.2}/scripts/ocspeed-20260703/longgen_probe.py +0 -0
  302. {mtplx-2.7.0 → mtplx-2.7.2}/scripts/ocspeed-20260703/loop_degradation_probe.py +0 -0
  303. {mtplx-2.7.0 → mtplx-2.7.2}/scripts/ocspeed-20260703/paired_longgen.sh +0 -0
  304. {mtplx-2.7.0 → mtplx-2.7.2}/scripts/ocspeed-20260703/sdpa_microbench.py +0 -0
  305. {mtplx-2.7.0 → mtplx-2.7.2}/scripts/ocspeed-20260703/snapshot_tail.py +0 -0
  306. {mtplx-2.7.0 → mtplx-2.7.2}/scripts/opencode_concurrency_qa.py +0 -0
  307. {mtplx-2.7.0 → mtplx-2.7.2}/scripts/phase0h_paged_verifier_exactness.py +0 -0
  308. {mtplx-2.7.0 → mtplx-2.7.2}/scripts/probe_mlx_pr3026_qsdpa.py +0 -0
  309. {mtplx-2.7.0 → mtplx-2.7.2}/scripts/probe_mx_compile_buckets.py +0 -0
  310. {mtplx-2.7.0 → mtplx-2.7.2}/scripts/probe_paged_gqa_sdpa_routes.py +0 -0
  311. {mtplx-2.7.0 → mtplx-2.7.2}/scripts/prodqa-20260703/candidate_truecold_20260703.py +0 -0
  312. {mtplx-2.7.0 → mtplx-2.7.2}/scripts/prodqa-20260703/cold_pair_recheck.py +0 -0
  313. {mtplx-2.7.0 → mtplx-2.7.2}/scripts/prodqa-20260703/competitors_20260703.sh +0 -0
  314. {mtplx-2.7.0 → mtplx-2.7.2}/scripts/prodqa-20260703/decode_gap_matrix.py +0 -0
  315. {mtplx-2.7.0 → mtplx-2.7.2}/scripts/prodqa-20260703/hermes_pty_driver.py +0 -0
  316. {mtplx-2.7.0 → mtplx-2.7.2}/scripts/prodqa-20260703/omlx_probe.py +0 -0
  317. {mtplx-2.7.0 → mtplx-2.7.2}/scripts/prodqa-20260703/pi_pty_driver.py +0 -0
  318. {mtplx-2.7.0 → mtplx-2.7.2}/scripts/prodqa-20260703/pillar_ab_20260703.py +0 -0
  319. {mtplx-2.7.0 → mtplx-2.7.2}/scripts/prodqa-20260703/tool_gauntlet_20260703.sh +0 -0
  320. {mtplx-2.7.0 → mtplx-2.7.2}/scripts/quality_fp16_parent_logitdiff_20260707.py +0 -0
  321. {mtplx-2.7.0 → mtplx-2.7.2}/scripts/qwen35b_mtp_batch_evalplus_guarded.py +0 -0
  322. {mtplx-2.7.0 → mtplx-2.7.2}/scripts/qwen35b_mtp_batch_numerics_attribution.py +0 -0
  323. {mtplx-2.7.0 → mtplx-2.7.2}/scripts/qwen35b_mtp_batch_numerics_guarded.py +0 -0
  324. {mtplx-2.7.0 → mtplx-2.7.2}/scripts/r1_chisquare_verifier_correctness.py +0 -0
  325. {mtplx-2.7.0 → mtplx-2.7.2}/scripts/run_context_degradation_diagnostics.py +0 -0
  326. {mtplx-2.7.0 → mtplx-2.7.2}/scripts/serve_openai_mtplx.py +0 -0
  327. {mtplx-2.7.0 → mtplx-2.7.2}/scripts/session_cache_followup_qa.py +0 -0
  328. {mtplx-2.7.0 → mtplx-2.7.2}/scripts/session_forensics.py +0 -0
  329. {mtplx-2.7.0 → mtplx-2.7.2}/scripts/sparkle_rehearsal_kit.sh +0 -0
  330. {mtplx-2.7.0 → mtplx-2.7.2}/scripts/step_acceptance.py +0 -0
  331. {mtplx-2.7.0 → mtplx-2.7.2}/scripts/step_smoke.py +0 -0
  332. {mtplx-2.7.0 → mtplx-2.7.2}/scripts/train_mtp_adapter_c4.py +0 -0
  333. {mtplx-2.7.0 → mtplx-2.7.2}/scripts/validate_step_mtp_injector.py +0 -0
  334. {mtplx-2.7.0 → mtplx-2.7.2}/scripts/walltime-lab/run_project.py +0 -0
  335. {mtplx-2.7.0 → mtplx-2.7.2}/setup.cfg +0 -0
  336. {mtplx-2.7.0 → mtplx-2.7.2}/tests/test_a3b_compiled_target_prefix.py +0 -0
  337. {mtplx-2.7.0 → mtplx-2.7.2}/tests/test_a3b_mtp_batch.py +0 -0
  338. {mtplx-2.7.0 → mtplx-2.7.2}/tests/test_a3b_mtp_batch_driver.py +0 -0
  339. {mtplx-2.7.0 → mtplx-2.7.2}/tests/test_a3b_whole_moe.py +0 -0
  340. {mtplx-2.7.0 → mtplx-2.7.2}/tests/test_adaptive.py +0 -0
  341. {mtplx-2.7.0 → mtplx-2.7.2}/tests/test_aime_serve_gate.py +0 -0
  342. {mtplx-2.7.0 → mtplx-2.7.2}/tests/test_app_cli_env_parity.py +0 -0
  343. {mtplx-2.7.0 → mtplx-2.7.2}/tests/test_ar_batch_penalties.py +0 -0
  344. {mtplx-2.7.0 → mtplx-2.7.2}/tests/test_arrays_cache_patch.py +0 -0
  345. {mtplx-2.7.0 → mtplx-2.7.2}/tests/test_attention_split.py +0 -0
  346. {mtplx-2.7.0 → mtplx-2.7.2}/tests/test_background_warmup.py +0 -0
  347. {mtplx-2.7.0 → mtplx-2.7.2}/tests/test_batched_decode.py +0 -0
  348. {mtplx-2.7.0 → mtplx-2.7.2}/tests/test_batching_foundation.py +0 -0
  349. {mtplx-2.7.0 → mtplx-2.7.2}/tests/test_bracket_tool_rescue.py +0 -0
  350. {mtplx-2.7.0 → mtplx-2.7.2}/tests/test_cache_bank.py +0 -0
  351. {mtplx-2.7.0 → mtplx-2.7.2}/tests/test_cache_state.py +0 -0
  352. {mtplx-2.7.0 → mtplx-2.7.2}/tests/test_chat_encode_cache.py +0 -0
  353. {mtplx-2.7.0 → mtplx-2.7.2}/tests/test_cli_parity_tools.py +0 -0
  354. {mtplx-2.7.0 → mtplx-2.7.2}/tests/test_client_controls_default.py +0 -0
  355. {mtplx-2.7.0 → mtplx-2.7.2}/tests/test_code_eval.py +0 -0
  356. {mtplx-2.7.0 → mtplx-2.7.2}/tests/test_code_eval_gate.py +0 -0
  357. {mtplx-2.7.0 → mtplx-2.7.2}/tests/test_cold_prefix_ram_shadow.py +0 -0
  358. {mtplx-2.7.0 → mtplx-2.7.2}/tests/test_cold_tier_disk_usage_scan.py +0 -0
  359. {mtplx-2.7.0 → mtplx-2.7.2}/tests/test_cold_tier_foreground_yield.py +0 -0
  360. {mtplx-2.7.0 → mtplx-2.7.2}/tests/test_cold_tier_min_useful_matched.py +0 -0
  361. {mtplx-2.7.0 → mtplx-2.7.2}/tests/test_cold_tier_write_budget.py +0 -0
  362. {mtplx-2.7.0 → mtplx-2.7.2}/tests/test_compile_state.py +0 -0
  363. {mtplx-2.7.0 → mtplx-2.7.2}/tests/test_compiled_ar_wiring.py +0 -0
  364. {mtplx-2.7.0 → mtplx-2.7.2}/tests/test_compiled_forward.py +0 -0
  365. {mtplx-2.7.0 → mtplx-2.7.2}/tests/test_config.py +0 -0
  366. {mtplx-2.7.0 → mtplx-2.7.2}/tests/test_config_profile_precedence.py +0 -0
  367. {mtplx-2.7.0 → mtplx-2.7.2}/tests/test_constrained.py +0 -0
  368. {mtplx-2.7.0 → mtplx-2.7.2}/tests/test_context_copy_stats.py +0 -0
  369. {mtplx-2.7.0 → mtplx-2.7.2}/tests/test_context_degradation_profiles.py +0 -0
  370. {mtplx-2.7.0 → mtplx-2.7.2}/tests/test_correctors.py +0 -0
  371. {mtplx-2.7.0 → mtplx-2.7.2}/tests/test_cost_depth_policy.py +0 -0
  372. {mtplx-2.7.0 → mtplx-2.7.2}/tests/test_daemon_client.py +0 -0
  373. {mtplx-2.7.0 → mtplx-2.7.2}/tests/test_dashboard_endpoints.py +0 -0
  374. {mtplx-2.7.0 → mtplx-2.7.2}/tests/test_deepseek_v4_adaptive_width_bracket.py +0 -0
  375. {mtplx-2.7.0 → mtplx-2.7.2}/tests/test_deepseek_v4_adaptive_width_policy.py +0 -0
  376. {mtplx-2.7.0 → mtplx-2.7.2}/tests/test_deepseek_v4_attention_island.py +0 -0
  377. {mtplx-2.7.0 → mtplx-2.7.2}/tests/test_deepseek_v4_attention_island_bracket.py +0 -0
  378. {mtplx-2.7.0 → mtplx-2.7.2}/tests/test_deepseek_v4_attn_proj_wide_m3.py +0 -0
  379. {mtplx-2.7.0 → mtplx-2.7.2}/tests/test_deepseek_v4_attn_proj_wide_m3_bracket.py +0 -0
  380. {mtplx-2.7.0 → mtplx-2.7.2}/tests/test_deepseek_v4_decode.py +0 -0
  381. {mtplx-2.7.0 → mtplx-2.7.2}/tests/test_deepseek_v4_dtypes.py +0 -0
  382. {mtplx-2.7.0 → mtplx-2.7.2}/tests/test_deepseek_v4_indexer.py +0 -0
  383. {mtplx-2.7.0 → mtplx-2.7.2}/tests/test_deepseek_v4_kernel_paths.py +0 -0
  384. {mtplx-2.7.0 → mtplx-2.7.2}/tests/test_deepseek_v4_loader.py +0 -0
  385. {mtplx-2.7.0 → mtplx-2.7.2}/tests/test_deepseek_v4_moe_tail.py +0 -0
  386. {mtplx-2.7.0 → mtplx-2.7.2}/tests/test_deepseek_v4_moe_tail_bracket.py +0 -0
  387. {mtplx-2.7.0 → mtplx-2.7.2}/tests/test_deepseek_v4_mtp.py +0 -0
  388. {mtplx-2.7.0 → mtplx-2.7.2}/tests/test_deepseek_v4_new_math.py +0 -0
  389. {mtplx-2.7.0 → mtplx-2.7.2}/tests/test_deepseek_v4_o_lora.py +0 -0
  390. {mtplx-2.7.0 → mtplx-2.7.2}/tests/test_deepseek_v4_parity.py +0 -0
  391. {mtplx-2.7.0 → mtplx-2.7.2}/tests/test_deepseek_v4_sinkhorn_kernel.py +0 -0
  392. {mtplx-2.7.0 → mtplx-2.7.2}/tests/test_deepseek_v4_spec.py +0 -0
  393. {mtplx-2.7.0 → mtplx-2.7.2}/tests/test_deepseek_v4_swiglu_clamp.py +0 -0
  394. {mtplx-2.7.0 → mtplx-2.7.2}/tests/test_default_models.py +0 -0
  395. {mtplx-2.7.0 → mtplx-2.7.2}/tests/test_device_draft_core.py +0 -0
  396. {mtplx-2.7.0 → mtplx-2.7.2}/tests/test_diagnostics.py +0 -0
  397. {mtplx-2.7.0 → mtplx-2.7.2}/tests/test_download_progress.py +0 -0
  398. {mtplx-2.7.0 → mtplx-2.7.2}/tests/test_draft_lm_head.py +0 -0
  399. {mtplx-2.7.0 → mtplx-2.7.2}/tests/test_endpoint_probe_hygiene.py +0 -0
  400. {mtplx-2.7.0 → mtplx-2.7.2}/tests/test_engine_session_concurrency.py +0 -0
  401. {mtplx-2.7.0 → mtplx-2.7.2}/tests/test_engine_session_env.py +0 -0
  402. {mtplx-2.7.0 → mtplx-2.7.2}/tests/test_env_flag_parsing.py +0 -0
  403. {mtplx-2.7.0 → mtplx-2.7.2}/tests/test_fast_sampling.py +0 -0
  404. {mtplx-2.7.0 → mtplx-2.7.2}/tests/test_forge_mixed_convert.py +0 -0
  405. {mtplx-2.7.0 → mtplx-2.7.2}/tests/test_gdn_blocked_prefill.py +0 -0
  406. {mtplx-2.7.0 → mtplx-2.7.2}/tests/test_gdn_boundary_retention.py +0 -0
  407. {mtplx-2.7.0 → mtplx-2.7.2}/tests/test_gdn_capture_rows.py +0 -0
  408. {mtplx-2.7.0 → mtplx-2.7.2}/tests/test_gdn_postconv_fusion.py +0 -0
  409. {mtplx-2.7.0 → mtplx-2.7.2}/tests/test_gdn_postconv_impl_gate.py +0 -0
  410. {mtplx-2.7.0 → mtplx-2.7.2}/tests/test_gdn_tape_headquarter.py +0 -0
  411. {mtplx-2.7.0 → mtplx-2.7.2}/tests/test_generation_store_on_prefill.py +0 -0
  412. {mtplx-2.7.0 → mtplx-2.7.2}/tests/test_generation_sustained.py +0 -0
  413. {mtplx-2.7.0 → mtplx-2.7.2}/tests/test_graphbank_compiled_verify.py +0 -0
  414. {mtplx-2.7.0 → mtplx-2.7.2}/tests/test_greedy_draft_coupling.py +0 -0
  415. {mtplx-2.7.0 → mtplx-2.7.2}/tests/test_hf_loader.py +0 -0
  416. {mtplx-2.7.0 → mtplx-2.7.2}/tests/test_hy_v3_mtp_backend.py +0 -0
  417. {mtplx-2.7.0 → mtplx-2.7.2}/tests/test_hy_v3_mtp_graft.py +0 -0
  418. {mtplx-2.7.0 → mtplx-2.7.2}/tests/test_hygiene_scan.py +0 -0
  419. {mtplx-2.7.0 → mtplx-2.7.2}/tests/test_idle_postcommit_subagent.py +0 -0
  420. {mtplx-2.7.0 → mtplx-2.7.2}/tests/test_kernel_selfcheck.py +0 -0
  421. {mtplx-2.7.0 → mtplx-2.7.2}/tests/test_laguna_alt_step.py +0 -0
  422. {mtplx-2.7.0 → mtplx-2.7.2}/tests/test_laguna_compiled_step.py +0 -0
  423. {mtplx-2.7.0 → mtplx-2.7.2}/tests/test_laguna_fused.py +0 -0
  424. {mtplx-2.7.0 → mtplx-2.7.2}/tests/test_laguna_model.py +0 -0
  425. {mtplx-2.7.0 → mtplx-2.7.2}/tests/test_laguna_steel_attn.py +0 -0
  426. {mtplx-2.7.0 → mtplx-2.7.2}/tests/test_lazy_snapshot_cow.py +0 -0
  427. {mtplx-2.7.0 → mtplx-2.7.2}/tests/test_lfm2_descriptor_resolution.py +0 -0
  428. {mtplx-2.7.0 → mtplx-2.7.2}/tests/test_lfm2_fast.py +0 -0
  429. {mtplx-2.7.0 → mtplx-2.7.2}/tests/test_loop_guard.py +0 -0
  430. {mtplx-2.7.0 → mtplx-2.7.2}/tests/test_max_idle_watchdog.py +0 -0
  431. {mtplx-2.7.0 → mtplx-2.7.2}/tests/test_max_lifecycle.py +0 -0
  432. {mtplx-2.7.0 → mtplx-2.7.2}/tests/test_memory_pressure_guard.py +0 -0
  433. {mtplx-2.7.0 → mtplx-2.7.2}/tests/test_metadata_scrub.py +0 -0
  434. {mtplx-2.7.0 → mtplx-2.7.2}/tests/test_metal_memory_caps.py +0 -0
  435. {mtplx-2.7.0 → mtplx-2.7.2}/tests/test_midform_gate.py +0 -0
  436. {mtplx-2.7.0 → mtplx-2.7.2}/tests/test_model_catalog.py +0 -0
  437. {mtplx-2.7.0 → mtplx-2.7.2}/tests/test_model_scheduler.py +0 -0
  438. {mtplx-2.7.0 → mtplx-2.7.2}/tests/test_model_scheduler_persistence.py +0 -0
  439. {mtplx-2.7.0 → mtplx-2.7.2}/tests/test_moe_force_unsorted.py +0 -0
  440. {mtplx-2.7.0 → mtplx-2.7.2}/tests/test_moe_packed_projections.py +0 -0
  441. {mtplx-2.7.0 → mtplx-2.7.2}/tests/test_mtp_activation_stats.py +0 -0
  442. {mtplx-2.7.0 → mtplx-2.7.2}/tests/test_mtp_adapters.py +0 -0
  443. {mtplx-2.7.0 → mtplx-2.7.2}/tests/test_mtp_alias_load_path.py +0 -0
  444. {mtplx-2.7.0 → mtplx-2.7.2}/tests/test_mtp_batch_numerics.py +0 -0
  445. {mtplx-2.7.0 → mtplx-2.7.2}/tests/test_mtp_batch_serving.py +0 -0
  446. {mtplx-2.7.0 → mtplx-2.7.2}/tests/test_mtp_depth_n.py +0 -0
  447. {mtplx-2.7.0 → mtplx-2.7.2}/tests/test_mtp_depth_sweep.py +0 -0
  448. {mtplx-2.7.0 → mtplx-2.7.2}/tests/test_mtp_patch.py +0 -0
  449. {mtplx-2.7.0 → mtplx-2.7.2}/tests/test_mtp_payload_guards.py +0 -0
  450. {mtplx-2.7.0 → mtplx-2.7.2}/tests/test_mtp_weightless_degrade.py +0 -0
  451. {mtplx-2.7.0 → mtplx-2.7.2}/tests/test_nax_verify.py +0 -0
  452. {mtplx-2.7.0 → mtplx-2.7.2}/tests/test_no_mlx_imports.py +0 -0
  453. {mtplx-2.7.0 → mtplx-2.7.2}/tests/test_omlx_bridge.py +0 -0
  454. {mtplx-2.7.0 → mtplx-2.7.2}/tests/test_onboarding.py +0 -0
  455. {mtplx-2.7.0 → mtplx-2.7.2}/tests/test_openai_bridge.py +0 -0
  456. {mtplx-2.7.0 → mtplx-2.7.2}/tests/test_opencode.py +0 -0
  457. {mtplx-2.7.0 → mtplx-2.7.2}/tests/test_optimization_profiles.py +0 -0
  458. {mtplx-2.7.0 → mtplx-2.7.2}/tests/test_orphan_tool_markup.py +0 -0
  459. {mtplx-2.7.0 → mtplx-2.7.2}/tests/test_passive_probe_telemetry.py +0 -0
  460. {mtplx-2.7.0 → mtplx-2.7.2}/tests/test_penalties.py +0 -0
  461. {mtplx-2.7.0 → mtplx-2.7.2}/tests/test_penalty_request_wiring.py +0 -0
  462. {mtplx-2.7.0 → mtplx-2.7.2}/tests/test_persistent_replay.py +0 -0
  463. {mtplx-2.7.0 → mtplx-2.7.2}/tests/test_phase0h_paged_verifier_exactness.py +0 -0
  464. {mtplx-2.7.0 → mtplx-2.7.2}/tests/test_policy_fingerprint_stability.py +0 -0
  465. {mtplx-2.7.0 → mtplx-2.7.2}/tests/test_postcommit_arrival_wait.py +0 -0
  466. {mtplx-2.7.0 → mtplx-2.7.2}/tests/test_postcommit_cross_session_yield.py +0 -0
  467. {mtplx-2.7.0 → mtplx-2.7.2}/tests/test_postcommit_prefix_reuse.py +0 -0
  468. {mtplx-2.7.0 → mtplx-2.7.2}/tests/test_postcommit_resolve_for_request.py +0 -0
  469. {mtplx-2.7.0 → mtplx-2.7.2}/tests/test_postcommit_tools_plumbing.py +0 -0
  470. {mtplx-2.7.0 → mtplx-2.7.2}/tests/test_postcommit_wait.py +0 -0
  471. {mtplx-2.7.0 → mtplx-2.7.2}/tests/test_postcommit_wait_integration.py +0 -0
  472. {mtplx-2.7.0 → mtplx-2.7.2}/tests/test_pre_first_token_telemetry.py +0 -0
  473. {mtplx-2.7.0 → mtplx-2.7.2}/tests/test_prefill_bench.py +0 -0
  474. {mtplx-2.7.0 → mtplx-2.7.2}/tests/test_prefill_chunk_defaults.py +0 -0
  475. {mtplx-2.7.0 → mtplx-2.7.2}/tests/test_prefill_tps_regression.py +0 -0
  476. {mtplx-2.7.0 → mtplx-2.7.2}/tests/test_profiles.py +0 -0
  477. {mtplx-2.7.0 → mtplx-2.7.2}/tests/test_proj_quant.py +0 -0
  478. {mtplx-2.7.0 → mtplx-2.7.2}/tests/test_prompt_encoding.py +0 -0
  479. {mtplx-2.7.0 → mtplx-2.7.2}/tests/test_qwen35b_mtp_batch_evalplus_guarded.py +0 -0
  480. {mtplx-2.7.0 → mtplx-2.7.2}/tests/test_qwen35b_mtp_batch_numerics_attribution.py +0 -0
  481. {mtplx-2.7.0 → mtplx-2.7.2}/tests/test_qwen35b_mtp_batch_numerics_guarded.py +0 -0
  482. {mtplx-2.7.0 → mtplx-2.7.2}/tests/test_qwen3_5_mtp_backend.py +0 -0
  483. {mtplx-2.7.0 → mtplx-2.7.2}/tests/test_qwen3_5_mtp_object_level.py +0 -0
  484. {mtplx-2.7.0 → mtplx-2.7.2}/tests/test_qwen_row_owned_router.py +0 -0
  485. {mtplx-2.7.0 → mtplx-2.7.2}/tests/test_ragged_kv_cache.py +0 -0
  486. {mtplx-2.7.0 → mtplx-2.7.2}/tests/test_reasoning_stream_split.py +0 -0
  487. {mtplx-2.7.0 → mtplx-2.7.2}/tests/test_request_capture.py +0 -0
  488. {mtplx-2.7.0 → mtplx-2.7.2}/tests/test_retrieval.py +0 -0
  489. {mtplx-2.7.0 → mtplx-2.7.2}/tests/test_runtime_deepseek_v4_o_lora.py +0 -0
  490. {mtplx-2.7.0 → mtplx-2.7.2}/tests/test_runtime_kpis.py +0 -0
  491. {mtplx-2.7.0 → mtplx-2.7.2}/tests/test_runtime_model_alias.py +0 -0
  492. {mtplx-2.7.0 → mtplx-2.7.2}/tests/test_sampling.py +0 -0
  493. {mtplx-2.7.0 → mtplx-2.7.2}/tests/test_scoped_reasoning_history.py +0 -0
  494. {mtplx-2.7.0 → mtplx-2.7.2}/tests/test_sdpa_gqa_packed.py +0 -0
  495. {mtplx-2.7.0 → mtplx-2.7.2}/tests/test_session_bank.py +0 -0
  496. {mtplx-2.7.0 → mtplx-2.7.2}/tests/test_session_bank_env_caps.py +0 -0
  497. {mtplx-2.7.0 → mtplx-2.7.2}/tests/test_session_bank_restore_aliasing.py +0 -0
  498. {mtplx-2.7.0 → mtplx-2.7.2}/tests/test_snapshot_free_rejection_repair.py +0 -0
  499. {mtplx-2.7.0 → mtplx-2.7.2}/tests/test_ssd_boundary_repersist.py +0 -0
  500. {mtplx-2.7.0 → mtplx-2.7.2}/tests/test_stable_prefix_boundary.py +0 -0
  501. {mtplx-2.7.0 → mtplx-2.7.2}/tests/test_stats_footer_scope.py +0 -0
  502. {mtplx-2.7.0 → mtplx-2.7.2}/tests/test_step3p5_mtp_patch.py +0 -0
  503. {mtplx-2.7.0 → mtplx-2.7.2}/tests/test_stream_guard_env.py +0 -0
  504. {mtplx-2.7.0 → mtplx-2.7.2}/tests/test_stream_stall_watchdog.py +0 -0
  505. {mtplx-2.7.0 → mtplx-2.7.2}/tests/test_sustained_long_context_qa.py +0 -0
  506. {mtplx-2.7.0 → mtplx-2.7.2}/tests/test_thermal.py +0 -0
  507. {mtplx-2.7.0 → mtplx-2.7.2}/tests/test_thermal_sidecar.py +0 -0
  508. {mtplx-2.7.0 → mtplx-2.7.2}/tests/test_thinking_guard.py +0 -0
  509. {mtplx-2.7.0 → mtplx-2.7.2}/tests/test_tool_aware_stream_translator.py +0 -0
  510. {mtplx-2.7.0 → mtplx-2.7.2}/tests/test_tool_call_hidden_guard_and_key_repair.py +0 -0
  511. {mtplx-2.7.0 → mtplx-2.7.2}/tests/test_tool_nested_args_streaming.py +0 -0
  512. {mtplx-2.7.0 → mtplx-2.7.2}/tests/test_trace_parity.py +0 -0
  513. {mtplx-2.7.0 → mtplx-2.7.2}/tests/test_turboquant.py +0 -0
  514. {mtplx-2.7.0 → mtplx-2.7.2}/tests/test_turboquant_fallback.py +0 -0
  515. {mtplx-2.7.0 → mtplx-2.7.2}/tests/test_ui_progress.py +0 -0
  516. {mtplx-2.7.0 → mtplx-2.7.2}/tests/test_validators.py +0 -0
  517. {mtplx-2.7.0 → mtplx-2.7.2}/tests/test_vision_restore_span_guard.py +0 -0
  518. {mtplx-2.7.0 → mtplx-2.7.2}/tests/test_vision_session_cache.py +0 -0
  519. {mtplx-2.7.0 → mtplx-2.7.2}/tests/test_vision_tower.py +0 -0
  520. {mtplx-2.7.0 → mtplx-2.7.2}/tests/test_vllm_reference.py +0 -0
  521. {mtplx-2.7.0 → mtplx-2.7.2}/vllm_metal/__init__.py +0 -0
  522. {mtplx-2.7.0 → mtplx-2.7.2}/vllm_metal/metal/README.md +0 -0
  523. {mtplx-2.7.0 → mtplx-2.7.2}/vllm_metal/metal/__init__.py +0 -0
  524. {mtplx-2.7.0 → mtplx-2.7.2}/vllm_metal/metal/build.py +0 -0
  525. {mtplx-2.7.0 → mtplx-2.7.2}/vllm_metal/metal/constants.py +0 -0
  526. {mtplx-2.7.0 → mtplx-2.7.2}/vllm_metal/metal/kernels_v1/copy_blocks.metal +0 -0
  527. {mtplx-2.7.0 → mtplx-2.7.2}/vllm_metal/metal/kernels_v1/float8.metal +0 -0
  528. {mtplx-2.7.0 → mtplx-2.7.2}/vllm_metal/metal/kernels_v1/gather_kv_cache.metal +0 -0
  529. {mtplx-2.7.0 → mtplx-2.7.2}/vllm_metal/metal/kernels_v1/kv_scale_update.metal +0 -0
  530. {mtplx-2.7.0 → mtplx-2.7.2}/vllm_metal/metal/kernels_v1/pagedattention.metal +0 -0
  531. {mtplx-2.7.0 → mtplx-2.7.2}/vllm_metal/metal/kernels_v1/reshape_and_cache.metal +0 -0
  532. {mtplx-2.7.0 → mtplx-2.7.2}/vllm_metal/metal/kernels_v1/utils.metal +0 -0
  533. {mtplx-2.7.0 → mtplx-2.7.2}/vllm_metal/metal/kernels_v2/copy_blocks.metal +0 -0
  534. {mtplx-2.7.0 → mtplx-2.7.2}/vllm_metal/metal/kernels_v2/float8.metal +0 -0
  535. {mtplx-2.7.0 → mtplx-2.7.2}/vllm_metal/metal/kernels_v2/gather_kv_cache.metal +0 -0
  536. {mtplx-2.7.0 → mtplx-2.7.2}/vllm_metal/metal/kernels_v2/gdn_linear_attention.metal +0 -0
  537. {mtplx-2.7.0 → mtplx-2.7.2}/vllm_metal/metal/kernels_v2/kv_scale_update.metal +0 -0
  538. {mtplx-2.7.0 → mtplx-2.7.2}/vllm_metal/metal/kernels_v2/pagedattention.metal +0 -0
  539. {mtplx-2.7.0 → mtplx-2.7.2}/vllm_metal/metal/kernels_v2/reshape_and_cache.metal +0 -0
  540. {mtplx-2.7.0 → mtplx-2.7.2}/vllm_metal/metal/kernels_v2/turboquant.metal +0 -0
  541. {mtplx-2.7.0 → mtplx-2.7.2}/vllm_metal/metal/kernels_v2/utils.metal +0 -0
  542. {mtplx-2.7.0 → mtplx-2.7.2}/vllm_metal/metal/paged_ops.cpp +0 -0
@@ -4,6 +4,83 @@ All notable user-facing changes to MTPLX. The format is based on
4
4
  [Keep a Changelog](https://keepachangelog.com/en/1.1.0/); versions follow
5
5
  [Semantic Versioning](https://semver.org/).
6
6
 
7
+ ## [2.7.2] - 2026-08-16
8
+
9
+ An emergency fix for `mtplx pull`: on 2.7.1 and older, re-pulling a repo that
10
+ changed upstream — such as the Qwen 3.8 repos re-published on 2026-08-15 with
11
+ their vision towers restored — can corrupt the local copy. Upgrade before
12
+ pulling.
13
+
14
+ ### Fixed
15
+
16
+ - **The Qwen 3.8 Hugging Face artifacts can see again (#263).** All six
17
+ published 3.8 repos (Bare Speed, Optimized Speed, Optimized Quality and
18
+ their FP16 siblings) shipped without their vision towers: the forge
19
+ `mlx_lm.convert` lane serializes only the text model, so the 333
20
+ `model.visual.*` tensors, `vision_config`, and the preprocessor sidecars
21
+ were silently dropped. The repos were re-published on 2026-08-15 with the
22
+ official bf16 tower grafted back as an index-registered
23
+ `model-vision.safetensors` (byte-for-byte from `Qwen/Qwen3.8-27B`; language
24
+ and MTP tensors untouched). Existing installs pick the delta up with
25
+ `mtplx pull`; images, `/health` `vision.enabled`, prompt caching with
26
+ images, and MTP decode were verified on all six builds. Thanks to
27
+ @kjellix for the report and the proven graft procedure.
28
+ - **Forge keeps vision towers from now on.** `mtplx forge build` grafts the
29
+ source's vision tower, `vision_config`, and preprocessor sidecars into the
30
+ converted artifact on every lane (`mtplx/vision_graft.py`), and fails
31
+ closed when a source that declares `vision_config` would produce a blind
32
+ artifact. A repair script for already-forged artifacts ships as
33
+ `scripts/graft_vision_tower.py`, and the pillar gate now asserts
34
+ `vision.enabled` before the vision-cache check so a blind build fails
35
+ loudly with the real cause.
36
+ - **`mtplx pull` no longer corrupts files that changed upstream (#258,
37
+ #234).** The
38
+ progress downloader treated a size-mismatched *complete* local file as a
39
+ resumable partial and byte-range-appended the remote tail onto the old
40
+ content — updating a repo in place (for example the restored 3.8 vision
41
+ indexes) corrupted `config.json` and `model.safetensors.index.json` and
42
+ left the local copy unloadable until re-downloaded. Stale files are now
43
+ discarded and re-fetched whole; genuine `*.incomplete` partials still
44
+ resume. **Users on ≤2.7.1 should upgrade before pulling repaired repos**;
45
+ a failed pull from an older build is recovered by deleting the corrupt
46
+ `config.json` + `model.safetensors.index.json` and pulling again.
47
+
48
+ ## [2.7.1] - 2026-08-15
49
+
50
+ Clears the 2.7.0 known-issues list: `xhigh` is now selectable everywhere it is
51
+ offered, and the app's KV cache quantization toggle reaches Qwen 3.8.
52
+
53
+ ### Fixed
54
+
55
+ - **`xhigh` no longer bounces back to `medium` in the app.** Choosing it in
56
+ Inference settings while the model was running, or running
57
+ `mtplx config set reasoning_effort xhigh`, was rejected: those two writing
58
+ surfaces carried their own hardcoded effort list that stopped at `high`,
59
+ while the request path already knew `xhigh`. Because the live-settings POST
60
+ is all-or-nothing, one unknown level threw away the whole payload and the
61
+ picker snapped back to the family default. All four writing surfaces
62
+ (serve/CLI `--reasoning-effort`, `mtplx config set`, the live-settings POST)
63
+ now read one shared vocabulary in `mtplx/reasoning_effort.py`, and narrowing
64
+ to what the loaded model actually supports stays where it belongs — the
65
+ family's own `effort_levels`.
66
+ - **The app's KV cache quantization toggle now applies to Qwen 3.8.** The
67
+ launch gate listed only `qwen3_5`/`qwen3_6`, so a 3.8 launch exported
68
+ nothing while Settings showed `q8`.
69
+ - **`mtplx doctor` names the model it actually checks** instead of hardcoding
70
+ the previous default, and turbo's profile note reports the real compiled
71
+ verify fence (32,768, raised from 12,288 in 2.7.0) rather than the stale one.
72
+ - **A built app can no longer rank below the release it supersedes.** Sparkle
73
+ orders updates by `CFBundleVersion` alone, and the number derived from the
74
+ version was narrow enough that 2.7.1 computed lower than the 2.7.0 that
75
+ shipped — so a fresh build offered 2.7.0 to itself as an update. The
76
+ derivation now has room for the whole version and the appcast reads its
77
+ number back off the built bundle instead of being told one separately.
78
+
79
+ ### Still open from 2.7.0
80
+
81
+ - With reasoning switched off in a plain chat with no tools, Qwen 3.8 can
82
+ still emit a stray tool call and cut the turn short. Keep thinking on.
83
+
7
84
  ## [2.7.0] - 2026-08-15
8
85
 
9
86
  Qwen3.8 support 🎉. Qwen3.8-27B came out on 2026-08-14; this release runs it
@@ -1338,6 +1415,8 @@ working as one product. Full notes:
1338
1415
  completions, and Anthropic `stop_sequences`) and `/v1/completions`
1339
1416
  streams tokens as they are generated with real finish reasons.
1340
1417
 
1418
+ [2.7.2]: https://github.com/youssofal/MTPLX/releases/tag/v2.7.2
1419
+ [2.7.1]: https://github.com/youssofal/MTPLX/releases/tag/v2.7.1
1341
1420
  [2.7.0]: https://github.com/youssofal/MTPLX/releases/tag/v2.7.0
1342
1421
  [2.6.0]: https://github.com/youssofal/MTPLX/releases/tag/v2.6.0
1343
1422
  [2.5.4]: https://github.com/youssofal/MTPLX/releases/tag/v2.5.4
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: mtplx
3
- Version: 2.7.0
3
+ Version: 2.7.2
4
4
  Summary: Native MTP speculative decoding for Qwen3-Next on Apple Silicon.
5
5
  Author-email: Youssof Altoukhi <business@youssofal.com>
6
6
  License-Expression: Apache-2.0
@@ -82,6 +82,10 @@ class ReasoningCodec:
82
82
  supported: bool = True
83
83
  modes: tuple[str, ...] = ("auto", "on", "off")
84
84
  history_policy: str = "preserve_when_enabled"
85
+ # Drawn from mtplx.reasoning_effort.REASONING_EFFORT_LEVELS: the app
86
+ # renders these verbatim, so a level outside that vocabulary is one the
87
+ # user can pick and no writing surface will accept
88
+ # (test_reasoning_effort_vocabulary_covers_every_family pins it).
85
89
  effort_levels: tuple[str, ...] = ()
86
90
  default_effort: str | None = None
87
91
 
@@ -23,6 +23,7 @@ from .profiles import (
23
23
  list_profiles,
24
24
  resolve_profile_name,
25
25
  )
26
+ from .reasoning_effort import REASONING_EFFORT_CHOICES
26
27
  from .runtime_options import canonicalize_flag_tokens, normalize_paged_kv_quantization
27
28
  from .version import DISPLAY_VERSION, __version__
28
29
 
@@ -573,7 +574,7 @@ def _add_reasoning_arg(
573
574
  def _add_reasoning_effort_arg(parser: argparse.ArgumentParser) -> None:
574
575
  parser.add_argument(
575
576
  "--reasoning-effort",
576
- choices=["auto", "low", "medium", "high", "xhigh"],
577
+ choices=list(REASONING_EFFORT_CHOICES),
577
578
  default="auto",
578
579
  help=(
579
580
  "Reasoning effort for models that expose levels, such as Qwen 3.8 "
@@ -1028,6 +1028,9 @@ def _cmd_build(args: Any) -> int:
1028
1028
  if _cancel_requested(args.run_id):
1029
1029
  raise ForgeError("forge cancelled", code=130)
1030
1030
 
1031
+ _ensure_vision_tower(source_path, destination)
1032
+ _validate_vision_payload(source_path, destination)
1033
+
1031
1034
  _calibrate_sidecar(
1032
1035
  source_path,
1033
1036
  destination,
@@ -1767,6 +1770,51 @@ def _validate_mtp_sidecar_payload(destination: Path) -> dict[str, Any] | None:
1767
1770
  return audit
1768
1771
 
1769
1772
 
1773
+ def _ensure_vision_tower(source: Path, destination: Path) -> None:
1774
+ """Restore the vision tower that text-only convert lanes drop.
1775
+
1776
+ ``mlx_lm.convert`` serializes only the text model, so multimodal sources
1777
+ lose their vision tensors, ``vision_config``, and preprocessor sidecars
1778
+ (issue #263). Graft them back from the source directory. A no-op for
1779
+ text-only sources and for lanes (mirror, compressed-tensors) that already
1780
+ preserved the tower.
1781
+ """
1782
+ if not source.is_dir():
1783
+ return
1784
+ from mtplx.vision_graft import VisionGraftError, graft_vision_tower
1785
+
1786
+ try:
1787
+ report = graft_vision_tower(source, destination, verify_load=True)
1788
+ except VisionGraftError as exc:
1789
+ raise ForgeError(f"vision tower graft failed: {exc}") from exc
1790
+ if report.get("status") == "grafted":
1791
+ _err(
1792
+ f"[forge] restored vision tower: {report.get('tensors')} tensors "
1793
+ f"({report.get('bytes')} bytes) in {report.get('vision_file')}"
1794
+ )
1795
+
1796
+
1797
+ def _validate_vision_payload(source: Path, destination: Path) -> None:
1798
+ """Fail closed when a multimodal source produced a blind artifact."""
1799
+ if not source.is_dir():
1800
+ return
1801
+ try:
1802
+ source_config = _load_json(source / "config.json")
1803
+ except Exception:
1804
+ return
1805
+ if not isinstance(source_config, dict) or not isinstance(
1806
+ source_config.get("vision_config"), dict
1807
+ ):
1808
+ return
1809
+ from mtplx.vision import vision_spec_for_model_dir
1810
+
1811
+ if vision_spec_for_model_dir(destination) is None:
1812
+ raise ForgeError(
1813
+ "source declares vision_config but the forged artifact resolves no "
1814
+ "vision tower; the convert lane dropped it (issue #263)"
1815
+ )
1816
+
1817
+
1770
1818
  def _audit_mtp_sidecar_payload(mtp_path: Path) -> dict[str, Any]:
1771
1819
  problems: list[str] = []
1772
1820
  try:
@@ -2922,6 +2970,9 @@ def _stamp_runtime_metadata(
2922
2970
  metadata["mtp_sidecar"] = inspection.mtp.sidecar_format
2923
2971
  else:
2924
2972
  metadata.setdefault("mtp_sidecar", "mtp.safetensors")
2973
+ vision_stamp = _vision_metadata_stamp(model_path)
2974
+ if vision_stamp is not None:
2975
+ metadata["vision"] = vision_stamp
2925
2976
  metadata["base_trunk"] = source_repo
2926
2977
  metadata.setdefault("artifact_role", "forge-local")
2927
2978
  metadata["forge_provenance"] = {
@@ -2939,6 +2990,32 @@ def _stamp_runtime_metadata(
2939
2990
  return metadata
2940
2991
 
2941
2992
 
2993
+ def _vision_metadata_stamp(model_path: Path) -> dict[str, Any] | None:
2994
+ """Provenance for artifacts that carry a vision tower, or None."""
2995
+ from mtplx.vision import resolve_vision_prefix
2996
+
2997
+ index_path = model_path / "model.safetensors.index.json"
2998
+ if not index_path.exists():
2999
+ return None
3000
+ try:
3001
+ index = _load_json(index_path)
3002
+ except Exception:
3003
+ return None
3004
+ weight_map = index.get("weight_map") if isinstance(index, dict) else None
3005
+ if not isinstance(weight_map, dict):
3006
+ return None
3007
+ prefix = resolve_vision_prefix(weight_map)
3008
+ if prefix is None:
3009
+ return None
3010
+ vision_keys = [key for key in weight_map if str(key).startswith(prefix)]
3011
+ shards = sorted({str(weight_map[key]) for key in vision_keys})
3012
+ return {
3013
+ "tensor_count": len(vision_keys),
3014
+ "prefix": prefix,
3015
+ "shards": shards,
3016
+ }
3017
+
3018
+
2942
3019
  def _speed_evidence(rows: list[dict[str, Any]]) -> dict[str, Any]:
2943
3020
  winner = _winning_row(rows)
2944
3021
  ar_row = next((row for row in rows if row.get("depth") == 0), None)
@@ -125,6 +125,7 @@ from mtplx.profiles import (
125
125
  restore_profile_env,
126
126
  runtime_env_with_contract_overrides,
127
127
  )
128
+ from mtplx.reasoning_effort import REASONING_EFFORT_CHOICES
128
129
  from mtplx.server_urls import (
129
130
  bind_label,
130
131
  connect_host_for_bind,
@@ -14347,8 +14348,10 @@ def cmd_config_public(args: Any) -> int:
14347
14348
  )
14348
14349
  if key == "reasoning" and value not in {"auto", "on", "off"}:
14349
14350
  raise SystemExit("reasoning must be auto, on, or off")
14350
- if key == "reasoning_effort" and value not in {"auto", "low", "medium", "high"}:
14351
- raise SystemExit("reasoning_effort must be auto, low, medium, or high")
14351
+ if key == "reasoning_effort" and value not in REASONING_EFFORT_CHOICES:
14352
+ raise SystemExit(
14353
+ "reasoning_effort must be " + ", ".join(REASONING_EFFORT_CHOICES)
14354
+ )
14352
14355
  if key in {
14353
14356
  "max_active_requests",
14354
14357
  "decode_batch_max",
@@ -26,7 +26,7 @@ from mtplx.profiles import DEFAULT_HF_MODEL_ID, DEFAULT_PROFILE_NAME
26
26
 
27
27
 
28
28
  GIB = 1024**3
29
- DEFAULT_SPEED_MODEL_SIZE_BYTES = 20_392_433_868 # Qwen3.8-27B Optimized Speed (Hub bytes)
29
+ DEFAULT_SPEED_MODEL_SIZE_BYTES = 21_313_949_792 # Qwen3.8-27B Optimized Speed (Hub bytes, incl. restored vision tower #263)
30
30
  MIN_RECOMMENDED_MEMORY_BYTES = 48 * GIB
31
31
  SUPPORT_MACOS_MAJOR = 14
32
32
  SUPPORT_PYTHON = (3, 11)
@@ -441,7 +441,7 @@ def build_diagnostic_checks(
441
441
  },
442
442
  "default model available in the HF cache or as the verified local startup model",
443
443
  model_cache_fix,
444
- "https://huggingface.co/Youssofal/Qwen3.6-27B-MTPLX-Optimized-Speed",
444
+ f"https://huggingface.co/{DEFAULT_HF_MODEL_ID}",
445
445
  f"mtplx pull {DEFAULT_HF_MODEL_ID}",
446
446
  )
447
447
  )
@@ -452,9 +452,9 @@ def build_diagnostic_checks(
452
452
  "fail" if stale else "pass",
453
453
  "error",
454
454
  DEFAULT_HF_MODEL_ID,
455
- "Youssofal/Qwen3.6-27B-MTPLX-Optimized-Speed",
455
+ "a published Youssofal/... repo (not a local mtplx/ or models/ path)",
456
456
  "Pull the default model, or pass --model to serve a different one.",
457
- "https://huggingface.co/Youssofal/Qwen3.6-27B-MTPLX-Optimized-Speed",
457
+ f"https://huggingface.co/{DEFAULT_HF_MODEL_ID}",
458
458
  f"mtplx pull {DEFAULT_HF_MODEL_ID}",
459
459
  )
460
460
  )
@@ -481,7 +481,7 @@ def build_diagnostic_checks(
481
481
  hf_observed,
482
482
  "default Hugging Face repo is reachable from this machine",
483
483
  "Check network/HF auth or verify the model repo is public.",
484
- "https://huggingface.co/Youssofal/Qwen3.6-27B-MTPLX-Optimized-Speed",
484
+ f"https://huggingface.co/{DEFAULT_HF_MODEL_ID}",
485
485
  f"mtplx pull {DEFAULT_HF_MODEL_ID}",
486
486
  )
487
487
  )
@@ -637,10 +637,12 @@ def _download_repo_file(
637
637
 
638
638
  partial = target.with_name(target.name + ".incomplete")
639
639
  if target.exists():
640
- if not partial.exists():
641
- target.replace(partial)
642
- else:
643
- target.unlink()
640
+ # A size-mismatched final file is a stale version of a file that
641
+ # changed upstream (e.g. a repaired index gaining vision entries),
642
+ # not an interrupted download. Resuming from it would append the
643
+ # remote tail onto old content and corrupt the file, so discard it.
644
+ # Only a leftover *.incomplete partial may be range-resumed.
645
+ target.unlink()
644
646
  existing = partial.stat().st_size if partial.exists() else 0
645
647
  if expected_size is not None and existing > expected_size:
646
648
  partial.unlink()
@@ -128,8 +128,9 @@ OFFICIAL_CATALOG: tuple[CatalogModel, ...] = (
128
128
  ),
129
129
  hf_model_id="Youssofal/Qwen3.8-27B-MTPLX-Bare-Speed",
130
130
  # Exact byte sum of the published HF repo files (2026-08-15 tree API;
131
- # three trunk shards + bf16 MTP sidecar + tokenizer + card).
132
- size_bytes=16_002_648_138,
131
+ # three trunk shards + bf16 MTP sidecar + restored bf16 vision tower
132
+ # (#263) + tokenizer + card).
133
+ size_bytes=16_924_164_062,
133
134
  # Measured 2026-08-14: request-log MLX high-water 19.6 GiB during
134
135
  # quiet-window 2.4k-context serving (boot + Flappy arms + rung).
135
136
  peak_memory_gib=20.0,
@@ -150,8 +151,9 @@ OFFICIAL_CATALOG: tuple[CatalogModel, ...] = (
150
151
  ),
151
152
  hf_model_id="Youssofal/Qwen3.8-27B-MTPLX-Optimized-Speed",
152
153
  # Exact byte sum of the published HF repo files (2026-08-15 tree API;
153
- # module_overrides recipe, 5.807 bits/weight, bf16 MTP sidecar).
154
- size_bytes=20_392_433_868,
154
+ # module_overrides recipe, 5.807 bits/weight, bf16 MTP sidecar,
155
+ # restored bf16 vision tower (#263)).
156
+ size_bytes=21_313_949_792,
155
157
  # Measured 2026-08-14: request-log MLX high-water 24.6 GiB during
156
158
  # quiet-window 2.4k-context serving (boot + Flappy arms + rung).
157
159
  peak_memory_gib=25.0,
@@ -169,8 +171,9 @@ OFFICIAL_CATALOG: tuple[CatalogModel, ...] = (
169
171
  "8-bit dynamic quant. Good coding speeds and perfect quality."
170
172
  ),
171
173
  hf_model_id="Youssofal/Qwen3.8-27B-MTPLX-Optimized-Quality",
172
- # Exact byte sum of the published HF repo files (2026-08-15 tree API).
173
- size_bytes=29_449_324_149,
174
+ # Exact byte sum of the published HF repo files (2026-08-15 tree API;
175
+ # includes the restored bf16 vision tower, #263).
176
+ size_bytes=30_370_840_073,
174
177
  # Measured 2026-08-14: request-log MLX high-water 32.9 GiB during
175
178
  # quiet-window 2.4k-context serving (boot + Flappy arms + rung).
176
179
  peak_memory_gib=33.0,
@@ -193,8 +196,9 @@ OFFICIAL_CATALOG: tuple[CatalogModel, ...] = (
193
196
  "coding tasks. FP16 build for M1 and M2 Macs."
194
197
  ),
195
198
  hf_model_id="Youssofal/Qwen3.8-27B-MTPLX-Bare-Speed-FP16",
196
- # Exact byte sum of the local sibling at build time (2026-08-15).
197
- size_bytes=16_003_127_584,
199
+ # Exact byte sum of the published HF repo files (2026-08-15 tree API;
200
+ # includes the restored bf16 vision tower, #263).
201
+ size_bytes=16_924_647_669,
198
202
  # Same packs and tensor bytes as the parent; peak carried over.
199
203
  peak_memory_gib=20.0,
200
204
  recommended_tiers=frozenset({LEGACY_TIER}),
@@ -213,8 +217,9 @@ OFFICIAL_CATALOG: tuple[CatalogModel, ...] = (
213
217
  "FP16 build for M1 and M2 Macs. Recommended."
214
218
  ),
215
219
  hf_model_id="Youssofal/Qwen3.8-27B-MTPLX-Optimized-Speed-FP16",
216
- # Exact byte sum of the local sibling at build time (2026-08-15).
217
- size_bytes=20_392_914_234,
220
+ # Exact byte sum of the published HF repo files (2026-08-15 tree API;
221
+ # includes the restored bf16 vision tower, #263).
222
+ size_bytes=21_314_434_309,
218
223
  # Same packs and tensor bytes as the parent; peak carried over.
219
224
  peak_memory_gib=25.0,
220
225
  recommended_tiers=frozenset({LEGACY_TIER}),
@@ -232,8 +237,9 @@ OFFICIAL_CATALOG: tuple[CatalogModel, ...] = (
232
237
  "FP16 build for M1 and M2 Macs."
233
238
  ),
234
239
  hf_model_id="Youssofal/Qwen3.8-27B-MTPLX-Optimized-Quality-FP16",
235
- # Exact byte sum of the local sibling at build time (2026-08-15).
236
- size_bytes=29_449_805_992,
240
+ # Exact byte sum of the published HF repo files (2026-08-15 tree API;
241
+ # includes the restored bf16 vision tower, #263).
242
+ size_bytes=30_371_326_040,
237
243
  # Same packs and tensor bytes as the parent; peak carried over.
238
244
  peak_memory_gib=33.0,
239
245
  recommended_tiers=frozenset({LEGACY_TIER}),
@@ -553,8 +553,9 @@ TURBO_PROFILE = RuntimeProfile(
553
553
  "4-bit and 8-bit affine models; 6-bit models silently run the "
554
554
  "stock path.",
555
555
  "Compiled verify engages on 4-bit and 8-bit affine trunks at "
556
- "contexts <= 12288 (parity2-validated on both); other "
557
- "quantizations/contexts run the eager verify path unchanged.",
556
+ "contexts <= 32768 (parity2-validated on both; fence raised from "
557
+ "12288 in 2.7.0); other quantizations/contexts run the eager verify "
558
+ "path unchanged.",
558
559
  "Measured 2026-07-02/03 on M5 Max chat lane (app-launch flags, "
559
560
  "thinking on): 27B Optimized-Speed 44.7 -> 58-60 tok/s (vk_k "
560
561
  "within ~2% of the retired dflash-port kernel both directions); "
@@ -0,0 +1,37 @@
1
+ """Canonical MTPLX reasoning-effort vocabulary shared by CLI and server code.
2
+
3
+ Each model family declares the subset it supports through its
4
+ ``ReasoningCodec.effort_levels``, and that subset is exactly what the app's
5
+ effort picker renders. Every *writing* surface — serve/CLI argparse,
6
+ ``mtplx config set``, and the live-settings POST — must therefore accept this
7
+ whole vocabulary and leave the per-family narrowing to the one place that
8
+ knows which model is loaded (``_reasoning_effort_for_state``).
9
+
10
+ Surfaces that inline their own list go stale the moment a family ships a new
11
+ level. That is how 2.7.0 shipped with Qwen 3.8's ``xhigh`` bouncing back to
12
+ ``medium``: the request path knew the level, the live-settings coercer did
13
+ not, and because that POST is all-or-nothing the app's whole settings payload
14
+ was rejected.
15
+ """
16
+
17
+ from __future__ import annotations
18
+
19
+ from typing import Any
20
+
21
+
22
+ # Ordered low to high.
23
+ REASONING_EFFORT_LEVELS = ("low", "medium", "high", "xhigh")
24
+ # "auto" is not a level; it means "use the loaded family's default_effort".
25
+ REASONING_EFFORT_AUTO = "auto"
26
+ REASONING_EFFORT_CHOICES = (REASONING_EFFORT_AUTO, *REASONING_EFFORT_LEVELS)
27
+
28
+
29
+ def normalize_reasoning_effort(
30
+ value: Any, *, default: str = REASONING_EFFORT_AUTO
31
+ ) -> str:
32
+ effort = str(value or default).strip().lower()
33
+ if effort not in REASONING_EFFORT_CHOICES:
34
+ raise ValueError(
35
+ "reasoning_effort must be one of: " + ", ".join(REASONING_EFFORT_CHOICES)
36
+ )
37
+ return effort
@@ -83,6 +83,7 @@ from mtplx.mtp_batch_numerics import (
83
83
  )
84
84
  from mtplx.backends.descriptors import (
85
85
  BackendDescriptor,
86
+ ReasoningCodec,
86
87
  assistant_target_distribution_choices,
87
88
  descriptor_for_backend_id,
88
89
  descriptor_for_model,
@@ -111,6 +112,10 @@ from mtplx.gemma4_pair import (
111
112
  resolve_gemma4_pair_paths,
112
113
  )
113
114
  from mtplx.model_scheduler import ModelWorkScheduler
115
+ from mtplx.reasoning_effort import (
116
+ REASONING_EFFORT_CHOICES,
117
+ normalize_reasoning_effort as _normalize_reasoning_effort,
118
+ )
114
119
  from mtplx.retrieval import RetrievalError, RetrievalTrustError
115
120
  from mtplx.sampling import SamplerConfig
116
121
  from mtplx.profiles import (
@@ -13286,12 +13291,7 @@ def _coerce_setting(name: str, value: Any) -> Any:
13286
13291
  )
13287
13292
  return text
13288
13293
  if name == "reasoning_effort":
13289
- text = str(value).strip().lower()
13290
- if text not in {"auto", "low", "medium", "high"}:
13291
- raise ValueError(
13292
- "reasoning_effort must be 'auto', 'low', 'medium', or 'high'"
13293
- )
13294
- return text
13294
+ return _normalize_reasoning_effort(value)
13295
13295
  return value
13296
13296
 
13297
13297
 
@@ -21727,15 +21727,6 @@ def _thinking_enabled_for_request(
21727
21727
  )
21728
21728
 
21729
21729
 
21730
- def _normalize_reasoning_effort(value: Any, *, default: str = "auto") -> str:
21731
- effort = str(value or default).strip().lower()
21732
- if effort not in {"auto", "low", "medium", "high", "xhigh"}:
21733
- raise ValueError(
21734
- "reasoning_effort must be one of: auto, low, medium, high, xhigh"
21735
- )
21736
- return effort
21737
-
21738
-
21739
21730
  def _reasoning_effort_for_state(
21740
21731
  state: ServerState,
21741
21732
  *,
@@ -29022,7 +29013,7 @@ def parse_args(argv: list[str] | None = None) -> argparse.Namespace:
29022
29013
  )
29023
29014
  parser.add_argument(
29024
29015
  "--reasoning-effort",
29025
- choices=["auto", "low", "medium", "high", "xhigh"],
29016
+ choices=list(REASONING_EFFORT_CHOICES),
29026
29017
  default="auto",
29027
29018
  help=(
29028
29019
  "Backend reasoning effort. Qwen 3.8 exposes xhigh/medium/low "
@@ -2,5 +2,5 @@
2
2
 
3
3
  from __future__ import annotations
4
4
 
5
- __version__ = "2.7.0"
6
- DISPLAY_VERSION = "2.7.0"
5
+ __version__ = "2.7.2"
6
+ DISPLAY_VERSION = "2.7.2"