dflash-console 0.3.249__tar.gz → 0.3.253__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 (204) hide show
  1. {dflash_console-0.3.249 → dflash_console-0.3.253}/PKG-INFO +3 -3
  2. {dflash_console-0.3.249 → dflash_console-0.3.253}/README.md +2 -2
  3. {dflash_console-0.3.249 → dflash_console-0.3.253}/api/app.py +2 -0
  4. {dflash_console-0.3.249 → dflash_console-0.3.253}/core/catalog_load.py +59 -6
  5. {dflash_console-0.3.249 → dflash_console-0.3.253}/core/embedding_server.py +9 -4
  6. dflash_console-0.3.253/core/gpu_process_memory_windows.py +262 -0
  7. {dflash_console-0.3.249 → dflash_console-0.3.253}/core/gpu_processes.py +288 -0
  8. dflash_console-0.3.253/core/model_presets.py +426 -0
  9. dflash_console-0.3.249/core/model_presets.py → dflash_console-0.3.253/core/model_presets.py.bak-e4b-mtp +423 -405
  10. {dflash_console-0.3.249 → dflash_console-0.3.253}/core/runtime.py +45 -10
  11. {dflash_console-0.3.249 → dflash_console-0.3.253}/core/server_boot.py +106 -13
  12. {dflash_console-0.3.249 → dflash_console-0.3.253}/core/version.py +1 -1
  13. {dflash_console-0.3.249 → dflash_console-0.3.253}/pyproject.toml +1 -1
  14. {dflash_console-0.3.249 → dflash_console-0.3.253}/static/css/dflash-console.css +11 -10
  15. {dflash_console-0.3.249 → dflash_console-0.3.253}/static/css/dflash-shell.css +38 -0
  16. {dflash_console-0.3.249 → dflash_console-0.3.253}/static/index.html +2 -2
  17. {dflash_console-0.3.249 → dflash_console-0.3.253}/static/js/download-queue.js +17 -8
  18. {dflash_console-0.3.249 → dflash_console-0.3.253}/static/js/model-search-live.js +17 -5
  19. {dflash_console-0.3.249 → dflash_console-0.3.253}/static/js/models-live.js +61 -34
  20. {dflash_console-0.3.249 → dflash_console-0.3.253}/static/js/server-live.js +183 -47
  21. {dflash_console-0.3.249 → dflash_console-0.3.253}/static/js/server-reload-watch.js +1 -1
  22. {dflash_console-0.3.249 → dflash_console-0.3.253}/static/js/status-feed.js +10 -2
  23. dflash_console-0.3.249/core/gpu_process_memory_windows.py +0 -155
  24. {dflash_console-0.3.249 → dflash_console-0.3.253}/.gitignore +0 -0
  25. {dflash_console-0.3.249 → dflash_console-0.3.253}/LICENSE +0 -0
  26. {dflash_console-0.3.249 → dflash_console-0.3.253}/NOTICE.md +0 -0
  27. {dflash_console-0.3.249 → dflash_console-0.3.253}/api/__init__.py +0 -0
  28. {dflash_console-0.3.249 → dflash_console-0.3.253}/api/gateway.py +0 -0
  29. {dflash_console-0.3.249 → dflash_console-0.3.253}/assets/dflash_console_logo.png +0 -0
  30. {dflash_console-0.3.249 → dflash_console-0.3.253}/assets/dflash_console_logo_only.png +0 -0
  31. {dflash_console-0.3.249 → dflash_console-0.3.253}/assets/dflash_console_logo_only2.png +0 -0
  32. {dflash_console-0.3.249 → dflash_console-0.3.253}/assets/dflash_console_logo_only_clear.png +0 -0
  33. {dflash_console-0.3.249 → dflash_console-0.3.253}/assets/dflash_txt_logo.png +0 -0
  34. {dflash_console-0.3.249 → dflash_console-0.3.253}/config.example.json +0 -0
  35. {dflash_console-0.3.249 → dflash_console-0.3.253}/core/__init__.py +0 -0
  36. {dflash_console-0.3.249 → dflash_console-0.3.253}/core/api_access_log.py +0 -0
  37. {dflash_console-0.3.249 → dflash_console-0.3.253}/core/api_catalog.py +0 -0
  38. {dflash_console-0.3.249 → dflash_console-0.3.253}/core/api_introspection.py +0 -0
  39. {dflash_console-0.3.249 → dflash_console-0.3.253}/core/api_providers.py +0 -0
  40. {dflash_console-0.3.249 → dflash_console-0.3.253}/core/auto_register.py +0 -0
  41. {dflash_console-0.3.249 → dflash_console-0.3.253}/core/chat_proxy.py +0 -0
  42. {dflash_console-0.3.249 → dflash_console-0.3.253}/core/chat_queue.py +0 -0
  43. {dflash_console-0.3.249 → dflash_console-0.3.253}/core/chat_ready.py +0 -0
  44. {dflash_console-0.3.249 → dflash_console-0.3.253}/core/chat_vision.py +0 -0
  45. {dflash_console-0.3.249 → dflash_console-0.3.253}/core/client_identity.py +0 -0
  46. {dflash_console-0.3.249 → dflash_console-0.3.253}/core/components_hub.py +0 -0
  47. {dflash_console-0.3.249 → dflash_console-0.3.253}/core/config.py +0 -0
  48. {dflash_console-0.3.249 → dflash_console-0.3.253}/core/dflash_generation.py +0 -0
  49. {dflash_console-0.3.249 → dflash_console-0.3.253}/core/diagnostics_bundle.py +0 -0
  50. {dflash_console-0.3.249 → dflash_console-0.3.253}/core/display_names.py +0 -0
  51. {dflash_console-0.3.249 → dflash_console-0.3.253}/core/engine_state.py +0 -0
  52. {dflash_console-0.3.249 → dflash_console-0.3.253}/core/freetoken_runtime_install.py +0 -0
  53. {dflash_console-0.3.249 → dflash_console-0.3.253}/core/fs_browse.py +0 -0
  54. {dflash_console-0.3.249 → dflash_console-0.3.253}/core/fs_reveal.py +0 -0
  55. {dflash_console-0.3.249 → dflash_console-0.3.253}/core/gateway_access_log.py +0 -0
  56. {dflash_console-0.3.249 → dflash_console-0.3.253}/core/gateway_routing.py +0 -0
  57. {dflash_console-0.3.249 → dflash_console-0.3.253}/core/gguf_meta.py +0 -0
  58. {dflash_console-0.3.249 → dflash_console-0.3.253}/core/gpu_devices.py +0 -0
  59. {dflash_console-0.3.249 → dflash_console-0.3.253}/core/gpu_policy.py +0 -0
  60. {dflash_console-0.3.249 → dflash_console-0.3.253}/core/gpu_relief.py +0 -0
  61. {dflash_console-0.3.249 → dflash_console-0.3.253}/core/hardware_apply.py +0 -0
  62. {dflash_console-0.3.249 → dflash_console-0.3.253}/core/hardware_info.py +0 -0
  63. {dflash_console-0.3.249 → dflash_console-0.3.253}/core/hf_catalog_cache.py +0 -0
  64. {dflash_console-0.3.249 → dflash_console-0.3.253}/core/hf_catalog_draft.py +0 -0
  65. {dflash_console-0.3.249 → dflash_console-0.3.253}/core/hf_catalog_index.py +0 -0
  66. {dflash_console-0.3.249 → dflash_console-0.3.253}/core/hf_catalog_recommend.py +0 -0
  67. {dflash_console-0.3.249 → dflash_console-0.3.253}/core/hf_engines.py +0 -0
  68. {dflash_console-0.3.249 → dflash_console-0.3.253}/core/hf_install.py +0 -0
  69. {dflash_console-0.3.249 → dflash_console-0.3.253}/core/hf_local_match.py +0 -0
  70. {dflash_console-0.3.249 → dflash_console-0.3.253}/core/hf_model_fit.py +0 -0
  71. {dflash_console-0.3.249 → dflash_console-0.3.253}/core/huggingface.py +0 -0
  72. {dflash_console-0.3.249 → dflash_console-0.3.253}/core/inference_stats.py +0 -0
  73. {dflash_console-0.3.249 → dflash_console-0.3.253}/core/library_import.py +0 -0
  74. {dflash_console-0.3.249 → dflash_console-0.3.253}/core/load_progress.py +0 -0
  75. {dflash_console-0.3.249 → dflash_console-0.3.253}/core/local_models.py +0 -0
  76. {dflash_console-0.3.249 → dflash_console-0.3.253}/core/log_utils.py +0 -0
  77. {dflash_console-0.3.249 → dflash_console-0.3.253}/core/memory_guardrails.py +0 -0
  78. {dflash_console-0.3.249 → dflash_console-0.3.253}/core/model_discovery.py +0 -0
  79. {dflash_console-0.3.249 → dflash_console-0.3.253}/core/model_paths.py +0 -0
  80. {dflash_console-0.3.249 → dflash_console-0.3.253}/core/model_runtime_policy.py +0 -0
  81. {dflash_console-0.3.249 → dflash_console-0.3.253}/core/model_stack.py +0 -0
  82. {dflash_console-0.3.249 → dflash_console-0.3.253}/core/net_listeners.py +0 -0
  83. {dflash_console-0.3.249 → dflash_console-0.3.253}/core/node_connect.py +0 -0
  84. {dflash_console-0.3.249 → dflash_console-0.3.253}/core/ocr_setup.py +0 -0
  85. {dflash_console-0.3.249 → dflash_console-0.3.253}/core/remote_nodes.py +0 -0
  86. {dflash_console-0.3.249 → dflash_console-0.3.253}/core/runtime_install_job.py +0 -0
  87. {dflash_console-0.3.249 → dflash_console-0.3.253}/core/runtime_recommendations.py +0 -0
  88. {dflash_console-0.3.249 → dflash_console-0.3.253}/core/runtimes/__init__.py +0 -0
  89. {dflash_console-0.3.249 → dflash_console-0.3.253}/core/runtimes/base.py +0 -0
  90. {dflash_console-0.3.249 → dflash_console-0.3.253}/core/runtimes/contention.py +0 -0
  91. {dflash_console-0.3.249 → dflash_console-0.3.253}/core/runtimes/faster_whisper.py +0 -0
  92. {dflash_console-0.3.249 → dflash_console-0.3.253}/core/runtimes/freetoken.py +0 -0
  93. {dflash_console-0.3.249 → dflash_console-0.3.253}/core/runtimes/noop.py +0 -0
  94. {dflash_console-0.3.249 → dflash_console-0.3.253}/core/runtimes/ollama.py +0 -0
  95. {dflash_console-0.3.249 → dflash_console-0.3.253}/core/runtimes/piper.py +0 -0
  96. {dflash_console-0.3.249 → dflash_console-0.3.253}/core/runtimes/registry.py +0 -0
  97. {dflash_console-0.3.249 → dflash_console-0.3.253}/core/runtimes/stt.py +0 -0
  98. {dflash_console-0.3.249 → dflash_console-0.3.253}/core/runtimes/transformers_hf.py +0 -0
  99. {dflash_console-0.3.249 → dflash_console-0.3.253}/core/runtimes/vibevoice.py +0 -0
  100. {dflash_console-0.3.249 → dflash_console-0.3.253}/core/runtimes/vllm.py +0 -0
  101. {dflash_console-0.3.249 → dflash_console-0.3.253}/core/setup.py +0 -0
  102. {dflash_console-0.3.249 → dflash_console-0.3.253}/core/stack_match.py +0 -0
  103. {dflash_console-0.3.249 → dflash_console-0.3.253}/core/status_report.py +0 -0
  104. {dflash_console-0.3.249 → dflash_console-0.3.253}/core/support_journal.py +0 -0
  105. {dflash_console-0.3.249 → dflash_console-0.3.253}/core/system_stats.py +0 -0
  106. {dflash_console-0.3.249 → dflash_console-0.3.253}/core/transformers_runtime_install.py +0 -0
  107. {dflash_console-0.3.249 → dflash_console-0.3.253}/core/vision_setup.py +0 -0
  108. {dflash_console-0.3.249 → dflash_console-0.3.253}/core/vllm_runtime_install.py +0 -0
  109. {dflash_console-0.3.249 → dflash_console-0.3.253}/dflash_cli/__init__.py +0 -0
  110. {dflash_console-0.3.249 → dflash_console-0.3.253}/dflash_cli/__main__.py +0 -0
  111. {dflash_console-0.3.249 → dflash_console-0.3.253}/dflash_cli/cli.py +0 -0
  112. {dflash_console-0.3.249 → dflash_console-0.3.253}/dflash_cli/commands.py +0 -0
  113. {dflash_console-0.3.249 → dflash_console-0.3.253}/dflash_cli/http.py +0 -0
  114. {dflash_console-0.3.249 → dflash_console-0.3.253}/dflash_cli/render.py +0 -0
  115. {dflash_console-0.3.249 → dflash_console-0.3.253}/dflash_cli/resolve.py +0 -0
  116. {dflash_console-0.3.249 → dflash_console-0.3.253}/dflash_cli/server_takeover.py +0 -0
  117. {dflash_console-0.3.249 → dflash_console-0.3.253}/docs/AGENT-PROMPT-CLIENT-IDENTITY.md +0 -0
  118. {dflash_console-0.3.249 → dflash_console-0.3.253}/docs/AGENT-PROMPT-DFLASH-TRANSLATION-PERF-AI-TOOLS.md +0 -0
  119. {dflash_console-0.3.249 → dflash_console-0.3.253}/docs/AGENT-PROMPT-TRANSLATEGEMMA-AI-TOOLS.md +0 -0
  120. {dflash_console-0.3.249 → dflash_console-0.3.253}/docs/ARCHITECTURE.md +0 -0
  121. {dflash_console-0.3.249 → dflash_console-0.3.253}/docs/BUG-REPORTS.md +0 -0
  122. {dflash_console-0.3.249 → dflash_console-0.3.253}/docs/CLI.md +0 -0
  123. {dflash_console-0.3.249 → dflash_console-0.3.253}/docs/CLIENT-IDENTITY.md +0 -0
  124. {dflash_console-0.3.249 → dflash_console-0.3.253}/docs/CURSOR.md +0 -0
  125. {dflash_console-0.3.249 → dflash_console-0.3.253}/docs/GOING-PUBLIC.md +0 -0
  126. {dflash_console-0.3.249 → dflash_console-0.3.253}/docs/LICENSING.md +0 -0
  127. {dflash_console-0.3.249 → dflash_console-0.3.253}/docs/LINUX-CLI.md +0 -0
  128. {dflash_console-0.3.249 → dflash_console-0.3.253}/docs/MULTI-MODAL-AGENT-PROMPT.md +0 -0
  129. {dflash_console-0.3.249 → dflash_console-0.3.253}/docs/MULTI-MODAL-RUNTIME-PLAN.md +0 -0
  130. {dflash_console-0.3.249 → dflash_console-0.3.253}/docs/PRODUCTION.md +0 -0
  131. {dflash_console-0.3.249 → dflash_console-0.3.253}/docs/RELEASING.md +0 -0
  132. {dflash_console-0.3.249 → dflash_console-0.3.253}/docs/STT-ENGINE-DECISION.md +0 -0
  133. {dflash_console-0.3.249 → dflash_console-0.3.253}/docs/USER-GUIDE.md +0 -0
  134. {dflash_console-0.3.249 → dflash_console-0.3.253}/docs/announcements/public-preview-v0.3.103.md +0 -0
  135. {dflash_console-0.3.249 → dflash_console-0.3.253}/docs/announcements/public-preview-v0.3.122.md +0 -0
  136. {dflash_console-0.3.249 → dflash_console-0.3.253}/docs/announcements/public-preview.md +0 -0
  137. {dflash_console-0.3.249 → dflash_console-0.3.253}/docs/automatic-updates.md +0 -0
  138. {dflash_console-0.3.249 → dflash_console-0.3.253}/docs/plans/shared-speak-stt-service.md +0 -0
  139. {dflash_console-0.3.249 → dflash_console-0.3.253}/docs/release-notes-0.3.103.md +0 -0
  140. {dflash_console-0.3.249 → dflash_console-0.3.253}/docs/release-notes-0.3.106.md +0 -0
  141. {dflash_console-0.3.249 → dflash_console-0.3.253}/docs/release-notes-0.3.117.md +0 -0
  142. {dflash_console-0.3.249 → dflash_console-0.3.253}/docs/release-notes-0.3.118.md +0 -0
  143. {dflash_console-0.3.249 → dflash_console-0.3.253}/docs/release-notes-0.3.119.md +0 -0
  144. {dflash_console-0.3.249 → dflash_console-0.3.253}/docs/release-notes-0.3.120.md +0 -0
  145. {dflash_console-0.3.249 → dflash_console-0.3.253}/docs/release-notes-0.3.121.md +0 -0
  146. {dflash_console-0.3.249 → dflash_console-0.3.253}/docs/release-notes-0.3.122.md +0 -0
  147. {dflash_console-0.3.249 → dflash_console-0.3.253}/docs/release-notes-0.3.123.md +0 -0
  148. {dflash_console-0.3.249 → dflash_console-0.3.253}/docs/release-notes-0.3.128.md +0 -0
  149. {dflash_console-0.3.249 → dflash_console-0.3.253}/docs/release-notes-0.3.129.md +0 -0
  150. {dflash_console-0.3.249 → dflash_console-0.3.253}/docs/release-notes-0.3.132.md +0 -0
  151. {dflash_console-0.3.249 → dflash_console-0.3.253}/docs/release-notes-0.3.133.md +0 -0
  152. {dflash_console-0.3.249 → dflash_console-0.3.253}/docs/release-notes-0.3.208.md +0 -0
  153. {dflash_console-0.3.249 → dflash_console-0.3.253}/docs/ui/README.md +0 -0
  154. {dflash_console-0.3.249 → dflash_console-0.3.253}/docs/ui/devices-view.md +0 -0
  155. {dflash_console-0.3.249 → dflash_console-0.3.253}/docs/ui/model-search.md +0 -0
  156. {dflash_console-0.3.249 → dflash_console-0.3.253}/docs/ui/models-view.md +0 -0
  157. {dflash_console-0.3.249 → dflash_console-0.3.253}/docs/ui/nodes-v1-plan.md +0 -0
  158. {dflash_console-0.3.249 → dflash_console-0.3.253}/docs/ui/settings-appearance.md +0 -0
  159. {dflash_console-0.3.249 → dflash_console-0.3.253}/docs/ui/settings-chat.md +0 -0
  160. {dflash_console-0.3.249 → dflash_console-0.3.253}/docs/ui/settings-developer.md +0 -0
  161. {dflash_console-0.3.249 → dflash_console-0.3.253}/docs/ui/settings-general.md +0 -0
  162. {dflash_console-0.3.249 → dflash_console-0.3.253}/docs/ui/settings-hardware.md +0 -0
  163. {dflash_console-0.3.249 → dflash_console-0.3.253}/docs/ui/settings-integrations.md +0 -0
  164. {dflash_console-0.3.249 → dflash_console-0.3.253}/docs/ui/settings-lm-link.md +0 -0
  165. {dflash_console-0.3.249 → dflash_console-0.3.253}/docs/ui/settings-model-defaults.md +0 -0
  166. {dflash_console-0.3.249 → dflash_console-0.3.253}/docs/ui/settings-runtime.md +0 -0
  167. {dflash_console-0.3.249 → dflash_console-0.3.253}/docs/ui/settings-runtimes.md +0 -0
  168. {dflash_console-0.3.249 → dflash_console-0.3.253}/static/app-functional.html +0 -0
  169. {dflash_console-0.3.249 → dflash_console-0.3.253}/static/css/dflash-console.css.bak-density +0 -0
  170. {dflash_console-0.3.249 → dflash_console-0.3.253}/static/css/dflash-shell.css.bak-density +0 -0
  171. {dflash_console-0.3.249 → dflash_console-0.3.253}/static/css/studio.css +0 -0
  172. {dflash_console-0.3.249 → dflash_console-0.3.253}/static/js/about-live.js +0 -0
  173. {dflash_console-0.3.249 → dflash_console-0.3.253}/static/js/app-settings-live.js +0 -0
  174. {dflash_console-0.3.249 → dflash_console-0.3.253}/static/js/app.js +0 -0
  175. {dflash_console-0.3.249 → dflash_console-0.3.253}/static/js/bug-report-live.js +0 -0
  176. {dflash_console-0.3.249 → dflash_console-0.3.253}/static/js/chat-live.js +0 -0
  177. {dflash_console-0.3.249 → dflash_console-0.3.253}/static/js/component-install-live.js +0 -0
  178. {dflash_console-0.3.249 → dflash_console-0.3.253}/static/js/console-api.js +0 -0
  179. {dflash_console-0.3.249 → dflash_console-0.3.253}/static/js/dashboard.js +0 -0
  180. {dflash_console-0.3.249 → dflash_console-0.3.253}/static/js/desktop-shell.js +0 -0
  181. {dflash_console-0.3.249 → dflash_console-0.3.253}/static/js/dflash-console-ui.js +0 -0
  182. {dflash_console-0.3.249 → dflash_console-0.3.253}/static/js/docs-live.js +0 -0
  183. {dflash_console-0.3.249 → dflash_console-0.3.253}/static/js/downloads-live.js +0 -0
  184. {dflash_console-0.3.249 → dflash_console-0.3.253}/static/js/library-browse-live.js +0 -0
  185. {dflash_console-0.3.249 → dflash_console-0.3.253}/static/js/library-scan-live.js +0 -0
  186. {dflash_console-0.3.249 → dflash_console-0.3.253}/static/js/library-type-options.js +0 -0
  187. {dflash_console-0.3.249 → dflash_console-0.3.253}/static/js/log-format.js +0 -0
  188. {dflash_console-0.3.249 → dflash_console-0.3.253}/static/js/model-card.js +0 -0
  189. {dflash_console-0.3.249 → dflash_console-0.3.253}/static/js/model-catalog-groups.js +0 -0
  190. {dflash_console-0.3.249 → dflash_console-0.3.253}/static/js/nodes-live.js +0 -0
  191. {dflash_console-0.3.249 → dflash_console-0.3.253}/static/js/runtime-recommendations.js +0 -0
  192. {dflash_console-0.3.249 → dflash_console-0.3.253}/static/js/runtime-steppers.js +0 -0
  193. {dflash_console-0.3.249 → dflash_console-0.3.253}/static/js/select-theme.js +0 -0
  194. {dflash_console-0.3.249 → dflash_console-0.3.253}/static/js/settings-live.js +0 -0
  195. {dflash_console-0.3.249 → dflash_console-0.3.253}/static/js/settings-live.js.api-providers-bak +0 -0
  196. {dflash_console-0.3.249 → dflash_console-0.3.253}/static/js/settings-live.js.pre-api-merge-bak +0 -0
  197. {dflash_console-0.3.249 → dflash_console-0.3.253}/static/js/setup-wizard-live.js +0 -0
  198. {dflash_console-0.3.249 → dflash_console-0.3.253}/static/js/speak-live.js +0 -0
  199. {dflash_console-0.3.249 → dflash_console-0.3.253}/static/js/stack-wizard.js +0 -0
  200. {dflash_console-0.3.249 → dflash_console-0.3.253}/static/js/sysbar-live.js +0 -0
  201. {dflash_console-0.3.249 → dflash_console-0.3.253}/static/js/table-column-resize.js +0 -0
  202. {dflash_console-0.3.249 → dflash_console-0.3.253}/static/js/ui-layout-prefs.js +0 -0
  203. {dflash_console-0.3.249 → dflash_console-0.3.253}/static/vendor/marked.min.js +0 -0
  204. {dflash_console-0.3.249 → dflash_console-0.3.253}/static/vendor/purify.min.js +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.5
2
2
  Name: dflash-console
3
- Version: 0.3.249
3
+ Version: 0.3.253
4
4
  Summary: Local control panel and terminal CLI for DFlash stacks and local model runtimes
5
5
  Project-URL: Homepage, https://github.com/ilan4ever/Dflash-Console
6
6
  Project-URL: Repository, https://github.com/ilan4ever/Dflash-Console
@@ -674,7 +674,7 @@ from one UI, then talk to them through a single OpenAI-compatible port.
674
674
  > supported platform**; Linux and macOS are not supported or tested (see
675
675
  > [Platform support](#platform-support) below).
676
676
 
677
- **Developer:** ILAN AVIV · **UI:** [http://127.0.0.1:8900/](http://127.0.0.1:8900/) · **Version:** v0.3.249
677
+ **Developer:** ILAN AVIV · **UI:** [http://127.0.0.1:8900/](http://127.0.0.1:8900/) · **Version:** v0.3.253
678
678
 
679
679
  ## Download (Windows)
680
680
 
@@ -753,7 +753,7 @@ Typical first session:
753
753
  3. For a DFlash GGUF, right-click and **Find and attach draft** if you want speculative decoding.
754
754
  4. Chat in the **Playground**, or point any OpenAI client at `http://127.0.0.1:8001/v1` with optional `X-DFlash-Client: YourApp` so **Engines** shows who is using each model.
755
755
 
756
- ### Recent improvements (v0.3.249)
756
+ ### Recent improvements (v0.3.253)
757
757
 
758
758
  - **Model library** — loading clears when the model is on the GPU; Engine and GPU column headers stay visible
759
759
  - **Model catalog** — a pasted repo name with a trailing period still opens the real model, and shared shard names are no longer marked installed
@@ -8,7 +8,7 @@ from one UI, then talk to them through a single OpenAI-compatible port.
8
8
  > supported platform**; Linux and macOS are not supported or tested (see
9
9
  > [Platform support](#platform-support) below).
10
10
 
11
- **Developer:** ILAN AVIV · **UI:** [http://127.0.0.1:8900/](http://127.0.0.1:8900/) · **Version:** v0.3.249
11
+ **Developer:** ILAN AVIV · **UI:** [http://127.0.0.1:8900/](http://127.0.0.1:8900/) · **Version:** v0.3.253
12
12
 
13
13
  ## Download (Windows)
14
14
 
@@ -87,7 +87,7 @@ Typical first session:
87
87
  3. For a DFlash GGUF, right-click and **Find and attach draft** if you want speculative decoding.
88
88
  4. Chat in the **Playground**, or point any OpenAI client at `http://127.0.0.1:8001/v1` with optional `X-DFlash-Client: YourApp` so **Engines** shows who is using each model.
89
89
 
90
- ### Recent improvements (v0.3.249)
90
+ ### Recent improvements (v0.3.253)
91
91
 
92
92
  - **Model library** — loading clears when the model is on the GPU; Engine and GPU column headers stay visible
93
93
  - **Model catalog** — a pasted repo name with a trailing period still opens the real model, and shared shard names are no longer marked installed
@@ -2175,6 +2175,7 @@ async def servers_status(
2175
2175
  cached = _cached_status_payload(include_external)
2176
2176
  if cached is not None:
2177
2177
  cached = _merge_adapter_engine_rows(dict(cached))
2178
+ cached['boot_id'] = _BOOT_ID
2178
2179
  cached['stale'] = True
2179
2180
  snapshot_at = float(cached.get('updated_at') or 0.0)
2180
2181
  if snapshot_at:
@@ -2206,6 +2207,7 @@ async def servers_status(
2206
2207
 
2207
2208
  _write_engine_status_log(trace, build_ms)
2208
2209
  payload = _merge_adapter_engine_rows(payload)
2210
+ payload['boot_id'] = _BOOT_ID
2209
2211
  _store_status_payload(payload, include_external=include_external)
2210
2212
  return payload
2211
2213
 
@@ -19,7 +19,7 @@ from core.engine_state import note_engine_loaded, note_engine_on
19
19
  from core.gpu_devices import validate_gpu_device
20
20
  from core.local_models import list_local_models
21
21
  from core.memory_guardrails import assess_load
22
- from core.server_boot import load_server_checkpoint
22
+ from core.server_boot import checkpoint_already_loaded, find_target_loaded_elsewhere, load_server_checkpoint
23
23
 
24
24
 
25
25
  def _release_peer_llm_engines(keep: str) -> None:
@@ -257,11 +257,15 @@ def execute_catalog_load(
257
257
  if server is None:
258
258
  raise HTTPException(status_code=404, detail=f'unknown server_id: {server_id}')
259
259
  else:
260
- candidates = [s for s in list_servers(config) if s.get('enabled', True)]
261
- if modality == 'embedding':
262
- server = next((s for s in candidates if is_embedding_server(s)), None)
263
- else:
264
- server = next((s for s in candidates if not is_embedding_server(s)), None)
260
+ catalog_server_id = str(target.get('server_id') or '').strip()
261
+ if catalog_server_id:
262
+ server = get_server(config, catalog_server_id)
263
+ if server is None:
264
+ candidates = [s for s in list_servers(config) if s.get('enabled', True)]
265
+ if modality == 'embedding':
266
+ server = next((s for s in candidates if is_embedding_server(s)), None)
267
+ else:
268
+ server = next((s for s in candidates if not is_embedding_server(s)), None)
265
269
  if server is None:
266
270
  raise HTTPException(status_code=409, detail=f'no enabled server can run a {modality} model — pass server_id')
267
271
 
@@ -277,6 +281,55 @@ def execute_catalog_load(
277
281
  if inference_settings:
278
282
  candidate['inference_settings'] = normalize_inference_settings(inference_settings)
279
283
 
284
+ server_id_text = str(server.get('id') or '')
285
+ already = checkpoint_already_loaded(
286
+ candidate,
287
+ cfg=config,
288
+ model_path=resolved_path,
289
+ model_id=model_id,
290
+ )
291
+ if already:
292
+ note_engine_loaded(server_id_text, loaded_by=loaded_by)
293
+ model_name = str(already.get('model') or target.get('label') or 'Model')
294
+ return {
295
+ 'success': True,
296
+ 'modality': modality,
297
+ 'runtime_id': 'llama-server',
298
+ 'server_id': server_id_text,
299
+ 'loaded': True,
300
+ 'already_loaded': True,
301
+ 'path': resolved_path,
302
+ 'message': f'{model_name} is already loaded on this engine.',
303
+ 'how_to_use': f'POST /api/servers/{server_id_text}/v1/chat/completions',
304
+ **already,
305
+ }
306
+ elsewhere = find_target_loaded_elsewhere(
307
+ candidate,
308
+ cfg=config,
309
+ model_path=resolved_path,
310
+ exclude_server_id=server_id_text,
311
+ )
312
+ if elsewhere:
313
+ use_id = str(elsewhere.get('server_id') or '')
314
+ label = str(elsewhere.get('label') or use_id or 'another engine')
315
+ return {
316
+ 'success': True,
317
+ 'modality': modality,
318
+ 'runtime_id': 'llama-server',
319
+ 'server_id': use_id or server_id_text,
320
+ 'loaded': True,
321
+ 'already_loaded': True,
322
+ 'already_loaded_elsewhere': True,
323
+ 'path': resolved_path,
324
+ 'message': f'This model is already loaded on {label}.',
325
+ 'how_to_use': (
326
+ f'POST /api/servers/{use_id}/v1/chat/completions'
327
+ if use_id
328
+ else f'POST /api/servers/{server_id_text}/v1/chat/completions'
329
+ ),
330
+ **elsewhere,
331
+ }
332
+
280
333
  check = assess_load(candidate, cfg=config)
281
334
  if check.get('level') == 'block':
282
335
  raise HTTPException(status_code=400, detail=str(check.get('message') or 'insufficient VRAM'))
@@ -17,13 +17,13 @@ from core.gpu_devices import resolve_role_gpu_launch_params
17
17
  from core.log_utils import rotate_log
18
18
  from core.server_boot import (
19
19
  LOG_DIR,
20
+ _acquire_port_boot,
20
21
  _spawn_detached,
21
22
  _tcp_port_open,
22
23
  clear_server_tracking,
23
24
  forget_started_process,
24
25
  get_started_process,
25
26
  note_boot_cycle_end,
26
- port_lock_for,
27
27
  register_started_launch,
28
28
  terminate_process_tree,
29
29
  wait_for_port_closed,
@@ -241,9 +241,14 @@ def start_embedding_server(server: dict[str, Any], *, cfg: dict[str, Any] | None
241
241
  port = int(entry.get('port') or 0)
242
242
  if port <= 0 or not entry.get('id'):
243
243
  return {'success': False, 'error': 'invalid embedding server config'}
244
- lock = port_lock_for(port)
245
- if not lock.acquire(blocking=False):
246
- return {'success': False, 'error': 'boot already in progress', 'port': port}
244
+ acquired = _acquire_port_boot(port)
245
+ if acquired is None:
246
+ return {
247
+ 'success': False,
248
+ 'error': 'timed out waiting for the model server to finish starting',
249
+ 'port': port,
250
+ }
251
+ lock, _joined = acquired
247
252
  try:
248
253
  return _start_embedding_server_locked(entry, cfg=cfg)
249
254
  finally:
@@ -0,0 +1,262 @@
1
+ """Per-process GPU memory on Windows via WDDM performance counters."""
2
+
3
+ from __future__ import annotations
4
+
5
+ import json
6
+ import re
7
+ import subprocess
8
+ import sys
9
+ import threading
10
+ import time
11
+ from typing import Any
12
+
13
+ _CACHE: dict[str, Any] = {'at': 0.0, 'map': {}}
14
+ _CACHE_LOCK = threading.Lock()
15
+ _CACHE_TTL_SECONDS = 20.0
16
+ _MAX_PROCESS_BYTES = 64 * (1024 ** 3)
17
+
18
+ _ROW_RE = re.compile(
19
+ r'pid_(\d+)_luid_((?:0x)?[0-9a-f]+)_((?:0x)?[0-9a-f]+)_phys_(\d+)',
20
+ re.I,
21
+ )
22
+
23
+
24
+ def _subprocess_no_window_kwargs() -> dict[str, Any]:
25
+ if sys.platform == 'win32':
26
+ startupinfo = subprocess.STARTUPINFO()
27
+ startupinfo.dwFlags |= subprocess.STARTF_USESHOWWINDOW
28
+ flags = getattr(subprocess, 'CREATE_NO_WINDOW', 0)
29
+ return {'startupinfo': startupinfo, 'creationflags': flags}
30
+ return {}
31
+
32
+
33
+ def _fetch_windows_process_gpu_bytes() -> dict[tuple[int, str], int]:
34
+ # Keep the larger sample per process+adapter. Windows repeats the same
35
+ # allocation on several engine nodes (3D, copy, compute) and both boards
36
+ # report phys_0, so the adapter LUID is what separates the GPUs.
37
+ script = r"""
38
+ $rows = Get-CimInstance -Namespace root/cimv2 -ClassName Win32_PerfFormattedData_GPUPerformanceCounters_GPUProcessMemory -ErrorAction SilentlyContinue
39
+ $agg = @{}
40
+ foreach ($r in $rows) {
41
+ if ($r.Name -match 'pid_(\d+)_luid_((?:0x)?[0-9a-fA-F]+)_((?:0x)?[0-9a-fA-F]+)_phys_(\d+)') {
42
+ $procId = [int]$matches[1]
43
+ $luid = ($matches[2] + '_' + $matches[3]).ToLower()
44
+ $key = "$procId|$luid"
45
+ $bytes = [long]($r.DedicatedUsage)
46
+ if ($bytes -le 0) { $bytes = [long]($r.TotalCommitted) }
47
+ if ($bytes -le 0) { continue }
48
+ if (-not $agg.ContainsKey($key)) { $agg[$key] = [long]0 }
49
+ $current = [long]$agg[$key]
50
+ if ($bytes -gt $current) { $agg[$key] = $bytes }
51
+ }
52
+ }
53
+ $out = @()
54
+ foreach ($kv in $agg.GetEnumerator()) {
55
+ $parts = $kv.Key.Split('|')
56
+ $out += @{ pid = [int]$parts[0]; luid = [string]$parts[1]; bytes = [long]$kv.Value }
57
+ }
58
+ $out | ConvertTo-Json -Compress
59
+ """
60
+ try:
61
+ result = subprocess.run(
62
+ ['powershell', '-NoProfile', '-NonInteractive', '-WindowStyle', 'Hidden', '-Command', script],
63
+ capture_output=True,
64
+ text=True,
65
+ timeout=12,
66
+ check=False,
67
+ **_subprocess_no_window_kwargs(),
68
+ )
69
+ except Exception:
70
+ return {}
71
+ if result.returncode != 0 or not result.stdout.strip():
72
+ return {}
73
+ try:
74
+ payload = json.loads(result.stdout.strip())
75
+ except json.JSONDecodeError:
76
+ return {}
77
+ rows = payload if isinstance(payload, list) else [payload]
78
+ mapping: dict[tuple[int, str], int] = {}
79
+ for row in rows:
80
+ if not isinstance(row, dict):
81
+ continue
82
+ try:
83
+ pid = int(row.get('pid') or 0)
84
+ luid = str(row.get('luid') or '').strip().lower()
85
+ bytes_val = int(row.get('bytes') or 0)
86
+ except (TypeError, ValueError):
87
+ continue
88
+ if pid <= 0 or not luid or bytes_val <= 0 or bytes_val > _MAX_PROCESS_BYTES:
89
+ continue
90
+ key = (pid, luid)
91
+ prior = mapping.get(key, 0)
92
+ if bytes_val > prior:
93
+ mapping[key] = bytes_val
94
+ return mapping
95
+
96
+
97
+ def match_luids_to_gpus(
98
+ per_luid_bytes: dict[str, int],
99
+ gpus: list[dict[str, Any]] | None,
100
+ ) -> dict[str, int]:
101
+ """Pair adapter LUIDs with nvidia-smi GPU indexes.
102
+
103
+ Both adapters report ``phys_0``. The LUID whose dedicated total is closest
104
+ to a board's used memory is that board.
105
+ """
106
+ totals = {
107
+ str(luid).lower(): int(nbytes)
108
+ for luid, nbytes in (per_luid_bytes or {}).items()
109
+ if int(nbytes or 0) >= 64 * (1024 ** 2)
110
+ }
111
+ devices: list[tuple[int, int | None]] = []
112
+ for gpu in gpus or []:
113
+ if not isinstance(gpu, dict) or gpu.get('index') is None:
114
+ continue
115
+ try:
116
+ index = int(gpu.get('index'))
117
+ except (TypeError, ValueError):
118
+ continue
119
+ used = gpu.get('vram_used_gb')
120
+ used_bytes: int | None
121
+ try:
122
+ used_bytes = int(float(used) * (1024 ** 3)) if used is not None else None
123
+ except (TypeError, ValueError):
124
+ used_bytes = None
125
+ devices.append((index, used_bytes))
126
+ if not totals:
127
+ return {}
128
+ if len(devices) == 1:
129
+ only = devices[0][0]
130
+ return {luid: only for luid in totals}
131
+ remaining = list(devices)
132
+ assigned: dict[str, int] = {}
133
+ for luid, nbytes in sorted(totals.items(), key=lambda item: item[1], reverse=True):
134
+ if not remaining:
135
+ break
136
+ best_at = 0
137
+ best_err: int | None = None
138
+ for at, (index, used_bytes) in enumerate(remaining):
139
+ if used_bytes is None:
140
+ continue
141
+ err = abs(int(used_bytes) - int(nbytes))
142
+ if best_err is None or err < best_err:
143
+ best_err = err
144
+ best_at = at
145
+ if best_err is None:
146
+ best_at = 0
147
+ index, _used = remaining.pop(best_at)
148
+ assigned[luid] = index
149
+ return assigned
150
+
151
+
152
+ def _gpu_devices_for_luid_match() -> list[dict[str, Any]]:
153
+ try:
154
+ from core.gpu_devices import query_gpu_devices
155
+
156
+ devices = query_gpu_devices()
157
+ except Exception:
158
+ return []
159
+ return devices if isinstance(devices, list) else []
160
+
161
+
162
+ def _mapping_from_luid_rows(
163
+ per_pid_luid: dict[tuple[int, str], int],
164
+ gpus: list[dict[str, Any]] | None = None,
165
+ ) -> dict[tuple[int, int], int]:
166
+ per_luid: dict[str, int] = {}
167
+ for (_pid, luid), nbytes in per_pid_luid.items():
168
+ per_luid[luid] = per_luid.get(luid, 0) + int(nbytes)
169
+ assigned = match_luids_to_gpus(per_luid, gpus if gpus is not None else _gpu_devices_for_luid_match())
170
+ mapping: dict[tuple[int, int], int] = {}
171
+ for (pid, luid), nbytes in per_pid_luid.items():
172
+ gpu_index = assigned.get(luid)
173
+ if gpu_index is None:
174
+ continue
175
+ key = (int(pid), int(gpu_index))
176
+ mapping[key] = mapping.get(key, 0) + int(nbytes)
177
+ return mapping
178
+
179
+
180
+ def query_windows_process_gpu_bytes() -> dict[tuple[int, int], int]:
181
+ """Return {(pid, nvidia gpu index): dedicated_bytes}."""
182
+ if sys.platform != 'win32':
183
+ return {}
184
+ now = time.time()
185
+ cached_at = float(_CACHE.get('at') or 0.0)
186
+ cached_map = _CACHE.get('map')
187
+ if isinstance(cached_map, dict) and (now - cached_at) < _CACHE_TTL_SECONDS:
188
+ return dict(cached_map)
189
+ with _CACHE_LOCK:
190
+ now = time.time()
191
+ cached_at = float(_CACHE.get('at') or 0.0)
192
+ cached_map = _CACHE.get('map')
193
+ if isinstance(cached_map, dict) and (now - cached_at) < _CACHE_TTL_SECONDS:
194
+ return dict(cached_map)
195
+ per_pid_luid = _fetch_windows_process_gpu_bytes()
196
+ mapping = _mapping_from_luid_rows(per_pid_luid)
197
+ _CACHE['at'] = time.time()
198
+ _CACHE['map'] = dict(mapping)
199
+ return mapping
200
+
201
+
202
+ def process_vram_by_gpu(pid: int, mapping: dict[tuple[int, int], int] | None = None) -> dict[int, float]:
203
+ """Gigabytes of one process on each GPU. Empty when this PID has none."""
204
+ if pid <= 0:
205
+ return {}
206
+ data = mapping if mapping is not None else query_windows_process_gpu_bytes()
207
+ found: dict[int, float] = {}
208
+ for (proc_id, gpu_index), nbytes in data.items():
209
+ if int(proc_id) != int(pid) or int(nbytes) <= 0:
210
+ continue
211
+ gb = round(int(nbytes) / (1024 ** 3), 3)
212
+ if gb <= 0:
213
+ continue
214
+ found[int(gpu_index)] = round(found.get(int(gpu_index), 0.0) + gb, 3)
215
+ return found
216
+
217
+
218
+ def lookup_windows_process_vram_gb(
219
+ pid: int,
220
+ gpu_index: int,
221
+ mapping: dict[tuple[int, int], int] | None = None,
222
+ ) -> float | None:
223
+ """VRAM in GB for this process on this GPU only.
224
+
225
+ Memory on another board is not borrowed. That is what made the Titan's
226
+ usage show up as a 4090 number.
227
+ """
228
+ if pid <= 0:
229
+ return None
230
+ found = process_vram_by_gpu(pid, mapping)
231
+ gb = found.get(int(gpu_index))
232
+ return gb if gb and gb > 0 else None
233
+
234
+
235
+ def apply_windows_process_vram(processes: list[dict[str, Any]]) -> bool:
236
+ """Fill missing per-process VRAM on Windows. Returns True when any row was enriched."""
237
+ if sys.platform != 'win32' or not processes:
238
+ return False
239
+ mapping = query_windows_process_gpu_bytes()
240
+ if not mapping:
241
+ return False
242
+ enriched = False
243
+ for proc in processes:
244
+ if not isinstance(proc, dict):
245
+ continue
246
+ try:
247
+ pid = int(proc.get('pid') or 0)
248
+ gpu_index = int(proc.get('gpu_index') or 0)
249
+ except (TypeError, ValueError):
250
+ continue
251
+ if pid <= 0:
252
+ continue
253
+ if proc.get('vram_gb') is not None and float(proc.get('vram_gb') or 0) > 0:
254
+ continue
255
+ gb = lookup_windows_process_vram_gb(pid, gpu_index, mapping)
256
+ if gb is None:
257
+ continue
258
+ proc['vram_gb'] = gb
259
+ proc['vram_mb'] = round(gb * 1024, 1)
260
+ proc['vram_source'] = 'windows'
261
+ enriched = True
262
+ return enriched