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.
- {dflash_console-0.3.249 → dflash_console-0.3.253}/PKG-INFO +3 -3
- {dflash_console-0.3.249 → dflash_console-0.3.253}/README.md +2 -2
- {dflash_console-0.3.249 → dflash_console-0.3.253}/api/app.py +2 -0
- {dflash_console-0.3.249 → dflash_console-0.3.253}/core/catalog_load.py +59 -6
- {dflash_console-0.3.249 → dflash_console-0.3.253}/core/embedding_server.py +9 -4
- dflash_console-0.3.253/core/gpu_process_memory_windows.py +262 -0
- {dflash_console-0.3.249 → dflash_console-0.3.253}/core/gpu_processes.py +288 -0
- dflash_console-0.3.253/core/model_presets.py +426 -0
- dflash_console-0.3.249/core/model_presets.py → dflash_console-0.3.253/core/model_presets.py.bak-e4b-mtp +423 -405
- {dflash_console-0.3.249 → dflash_console-0.3.253}/core/runtime.py +45 -10
- {dflash_console-0.3.249 → dflash_console-0.3.253}/core/server_boot.py +106 -13
- {dflash_console-0.3.249 → dflash_console-0.3.253}/core/version.py +1 -1
- {dflash_console-0.3.249 → dflash_console-0.3.253}/pyproject.toml +1 -1
- {dflash_console-0.3.249 → dflash_console-0.3.253}/static/css/dflash-console.css +11 -10
- {dflash_console-0.3.249 → dflash_console-0.3.253}/static/css/dflash-shell.css +38 -0
- {dflash_console-0.3.249 → dflash_console-0.3.253}/static/index.html +2 -2
- {dflash_console-0.3.249 → dflash_console-0.3.253}/static/js/download-queue.js +17 -8
- {dflash_console-0.3.249 → dflash_console-0.3.253}/static/js/model-search-live.js +17 -5
- {dflash_console-0.3.249 → dflash_console-0.3.253}/static/js/models-live.js +61 -34
- {dflash_console-0.3.249 → dflash_console-0.3.253}/static/js/server-live.js +183 -47
- {dflash_console-0.3.249 → dflash_console-0.3.253}/static/js/server-reload-watch.js +1 -1
- {dflash_console-0.3.249 → dflash_console-0.3.253}/static/js/status-feed.js +10 -2
- dflash_console-0.3.249/core/gpu_process_memory_windows.py +0 -155
- {dflash_console-0.3.249 → dflash_console-0.3.253}/.gitignore +0 -0
- {dflash_console-0.3.249 → dflash_console-0.3.253}/LICENSE +0 -0
- {dflash_console-0.3.249 → dflash_console-0.3.253}/NOTICE.md +0 -0
- {dflash_console-0.3.249 → dflash_console-0.3.253}/api/__init__.py +0 -0
- {dflash_console-0.3.249 → dflash_console-0.3.253}/api/gateway.py +0 -0
- {dflash_console-0.3.249 → dflash_console-0.3.253}/assets/dflash_console_logo.png +0 -0
- {dflash_console-0.3.249 → dflash_console-0.3.253}/assets/dflash_console_logo_only.png +0 -0
- {dflash_console-0.3.249 → dflash_console-0.3.253}/assets/dflash_console_logo_only2.png +0 -0
- {dflash_console-0.3.249 → dflash_console-0.3.253}/assets/dflash_console_logo_only_clear.png +0 -0
- {dflash_console-0.3.249 → dflash_console-0.3.253}/assets/dflash_txt_logo.png +0 -0
- {dflash_console-0.3.249 → dflash_console-0.3.253}/config.example.json +0 -0
- {dflash_console-0.3.249 → dflash_console-0.3.253}/core/__init__.py +0 -0
- {dflash_console-0.3.249 → dflash_console-0.3.253}/core/api_access_log.py +0 -0
- {dflash_console-0.3.249 → dflash_console-0.3.253}/core/api_catalog.py +0 -0
- {dflash_console-0.3.249 → dflash_console-0.3.253}/core/api_introspection.py +0 -0
- {dflash_console-0.3.249 → dflash_console-0.3.253}/core/api_providers.py +0 -0
- {dflash_console-0.3.249 → dflash_console-0.3.253}/core/auto_register.py +0 -0
- {dflash_console-0.3.249 → dflash_console-0.3.253}/core/chat_proxy.py +0 -0
- {dflash_console-0.3.249 → dflash_console-0.3.253}/core/chat_queue.py +0 -0
- {dflash_console-0.3.249 → dflash_console-0.3.253}/core/chat_ready.py +0 -0
- {dflash_console-0.3.249 → dflash_console-0.3.253}/core/chat_vision.py +0 -0
- {dflash_console-0.3.249 → dflash_console-0.3.253}/core/client_identity.py +0 -0
- {dflash_console-0.3.249 → dflash_console-0.3.253}/core/components_hub.py +0 -0
- {dflash_console-0.3.249 → dflash_console-0.3.253}/core/config.py +0 -0
- {dflash_console-0.3.249 → dflash_console-0.3.253}/core/dflash_generation.py +0 -0
- {dflash_console-0.3.249 → dflash_console-0.3.253}/core/diagnostics_bundle.py +0 -0
- {dflash_console-0.3.249 → dflash_console-0.3.253}/core/display_names.py +0 -0
- {dflash_console-0.3.249 → dflash_console-0.3.253}/core/engine_state.py +0 -0
- {dflash_console-0.3.249 → dflash_console-0.3.253}/core/freetoken_runtime_install.py +0 -0
- {dflash_console-0.3.249 → dflash_console-0.3.253}/core/fs_browse.py +0 -0
- {dflash_console-0.3.249 → dflash_console-0.3.253}/core/fs_reveal.py +0 -0
- {dflash_console-0.3.249 → dflash_console-0.3.253}/core/gateway_access_log.py +0 -0
- {dflash_console-0.3.249 → dflash_console-0.3.253}/core/gateway_routing.py +0 -0
- {dflash_console-0.3.249 → dflash_console-0.3.253}/core/gguf_meta.py +0 -0
- {dflash_console-0.3.249 → dflash_console-0.3.253}/core/gpu_devices.py +0 -0
- {dflash_console-0.3.249 → dflash_console-0.3.253}/core/gpu_policy.py +0 -0
- {dflash_console-0.3.249 → dflash_console-0.3.253}/core/gpu_relief.py +0 -0
- {dflash_console-0.3.249 → dflash_console-0.3.253}/core/hardware_apply.py +0 -0
- {dflash_console-0.3.249 → dflash_console-0.3.253}/core/hardware_info.py +0 -0
- {dflash_console-0.3.249 → dflash_console-0.3.253}/core/hf_catalog_cache.py +0 -0
- {dflash_console-0.3.249 → dflash_console-0.3.253}/core/hf_catalog_draft.py +0 -0
- {dflash_console-0.3.249 → dflash_console-0.3.253}/core/hf_catalog_index.py +0 -0
- {dflash_console-0.3.249 → dflash_console-0.3.253}/core/hf_catalog_recommend.py +0 -0
- {dflash_console-0.3.249 → dflash_console-0.3.253}/core/hf_engines.py +0 -0
- {dflash_console-0.3.249 → dflash_console-0.3.253}/core/hf_install.py +0 -0
- {dflash_console-0.3.249 → dflash_console-0.3.253}/core/hf_local_match.py +0 -0
- {dflash_console-0.3.249 → dflash_console-0.3.253}/core/hf_model_fit.py +0 -0
- {dflash_console-0.3.249 → dflash_console-0.3.253}/core/huggingface.py +0 -0
- {dflash_console-0.3.249 → dflash_console-0.3.253}/core/inference_stats.py +0 -0
- {dflash_console-0.3.249 → dflash_console-0.3.253}/core/library_import.py +0 -0
- {dflash_console-0.3.249 → dflash_console-0.3.253}/core/load_progress.py +0 -0
- {dflash_console-0.3.249 → dflash_console-0.3.253}/core/local_models.py +0 -0
- {dflash_console-0.3.249 → dflash_console-0.3.253}/core/log_utils.py +0 -0
- {dflash_console-0.3.249 → dflash_console-0.3.253}/core/memory_guardrails.py +0 -0
- {dflash_console-0.3.249 → dflash_console-0.3.253}/core/model_discovery.py +0 -0
- {dflash_console-0.3.249 → dflash_console-0.3.253}/core/model_paths.py +0 -0
- {dflash_console-0.3.249 → dflash_console-0.3.253}/core/model_runtime_policy.py +0 -0
- {dflash_console-0.3.249 → dflash_console-0.3.253}/core/model_stack.py +0 -0
- {dflash_console-0.3.249 → dflash_console-0.3.253}/core/net_listeners.py +0 -0
- {dflash_console-0.3.249 → dflash_console-0.3.253}/core/node_connect.py +0 -0
- {dflash_console-0.3.249 → dflash_console-0.3.253}/core/ocr_setup.py +0 -0
- {dflash_console-0.3.249 → dflash_console-0.3.253}/core/remote_nodes.py +0 -0
- {dflash_console-0.3.249 → dflash_console-0.3.253}/core/runtime_install_job.py +0 -0
- {dflash_console-0.3.249 → dflash_console-0.3.253}/core/runtime_recommendations.py +0 -0
- {dflash_console-0.3.249 → dflash_console-0.3.253}/core/runtimes/__init__.py +0 -0
- {dflash_console-0.3.249 → dflash_console-0.3.253}/core/runtimes/base.py +0 -0
- {dflash_console-0.3.249 → dflash_console-0.3.253}/core/runtimes/contention.py +0 -0
- {dflash_console-0.3.249 → dflash_console-0.3.253}/core/runtimes/faster_whisper.py +0 -0
- {dflash_console-0.3.249 → dflash_console-0.3.253}/core/runtimes/freetoken.py +0 -0
- {dflash_console-0.3.249 → dflash_console-0.3.253}/core/runtimes/noop.py +0 -0
- {dflash_console-0.3.249 → dflash_console-0.3.253}/core/runtimes/ollama.py +0 -0
- {dflash_console-0.3.249 → dflash_console-0.3.253}/core/runtimes/piper.py +0 -0
- {dflash_console-0.3.249 → dflash_console-0.3.253}/core/runtimes/registry.py +0 -0
- {dflash_console-0.3.249 → dflash_console-0.3.253}/core/runtimes/stt.py +0 -0
- {dflash_console-0.3.249 → dflash_console-0.3.253}/core/runtimes/transformers_hf.py +0 -0
- {dflash_console-0.3.249 → dflash_console-0.3.253}/core/runtimes/vibevoice.py +0 -0
- {dflash_console-0.3.249 → dflash_console-0.3.253}/core/runtimes/vllm.py +0 -0
- {dflash_console-0.3.249 → dflash_console-0.3.253}/core/setup.py +0 -0
- {dflash_console-0.3.249 → dflash_console-0.3.253}/core/stack_match.py +0 -0
- {dflash_console-0.3.249 → dflash_console-0.3.253}/core/status_report.py +0 -0
- {dflash_console-0.3.249 → dflash_console-0.3.253}/core/support_journal.py +0 -0
- {dflash_console-0.3.249 → dflash_console-0.3.253}/core/system_stats.py +0 -0
- {dflash_console-0.3.249 → dflash_console-0.3.253}/core/transformers_runtime_install.py +0 -0
- {dflash_console-0.3.249 → dflash_console-0.3.253}/core/vision_setup.py +0 -0
- {dflash_console-0.3.249 → dflash_console-0.3.253}/core/vllm_runtime_install.py +0 -0
- {dflash_console-0.3.249 → dflash_console-0.3.253}/dflash_cli/__init__.py +0 -0
- {dflash_console-0.3.249 → dflash_console-0.3.253}/dflash_cli/__main__.py +0 -0
- {dflash_console-0.3.249 → dflash_console-0.3.253}/dflash_cli/cli.py +0 -0
- {dflash_console-0.3.249 → dflash_console-0.3.253}/dflash_cli/commands.py +0 -0
- {dflash_console-0.3.249 → dflash_console-0.3.253}/dflash_cli/http.py +0 -0
- {dflash_console-0.3.249 → dflash_console-0.3.253}/dflash_cli/render.py +0 -0
- {dflash_console-0.3.249 → dflash_console-0.3.253}/dflash_cli/resolve.py +0 -0
- {dflash_console-0.3.249 → dflash_console-0.3.253}/dflash_cli/server_takeover.py +0 -0
- {dflash_console-0.3.249 → dflash_console-0.3.253}/docs/AGENT-PROMPT-CLIENT-IDENTITY.md +0 -0
- {dflash_console-0.3.249 → dflash_console-0.3.253}/docs/AGENT-PROMPT-DFLASH-TRANSLATION-PERF-AI-TOOLS.md +0 -0
- {dflash_console-0.3.249 → dflash_console-0.3.253}/docs/AGENT-PROMPT-TRANSLATEGEMMA-AI-TOOLS.md +0 -0
- {dflash_console-0.3.249 → dflash_console-0.3.253}/docs/ARCHITECTURE.md +0 -0
- {dflash_console-0.3.249 → dflash_console-0.3.253}/docs/BUG-REPORTS.md +0 -0
- {dflash_console-0.3.249 → dflash_console-0.3.253}/docs/CLI.md +0 -0
- {dflash_console-0.3.249 → dflash_console-0.3.253}/docs/CLIENT-IDENTITY.md +0 -0
- {dflash_console-0.3.249 → dflash_console-0.3.253}/docs/CURSOR.md +0 -0
- {dflash_console-0.3.249 → dflash_console-0.3.253}/docs/GOING-PUBLIC.md +0 -0
- {dflash_console-0.3.249 → dflash_console-0.3.253}/docs/LICENSING.md +0 -0
- {dflash_console-0.3.249 → dflash_console-0.3.253}/docs/LINUX-CLI.md +0 -0
- {dflash_console-0.3.249 → dflash_console-0.3.253}/docs/MULTI-MODAL-AGENT-PROMPT.md +0 -0
- {dflash_console-0.3.249 → dflash_console-0.3.253}/docs/MULTI-MODAL-RUNTIME-PLAN.md +0 -0
- {dflash_console-0.3.249 → dflash_console-0.3.253}/docs/PRODUCTION.md +0 -0
- {dflash_console-0.3.249 → dflash_console-0.3.253}/docs/RELEASING.md +0 -0
- {dflash_console-0.3.249 → dflash_console-0.3.253}/docs/STT-ENGINE-DECISION.md +0 -0
- {dflash_console-0.3.249 → dflash_console-0.3.253}/docs/USER-GUIDE.md +0 -0
- {dflash_console-0.3.249 → dflash_console-0.3.253}/docs/announcements/public-preview-v0.3.103.md +0 -0
- {dflash_console-0.3.249 → dflash_console-0.3.253}/docs/announcements/public-preview-v0.3.122.md +0 -0
- {dflash_console-0.3.249 → dflash_console-0.3.253}/docs/announcements/public-preview.md +0 -0
- {dflash_console-0.3.249 → dflash_console-0.3.253}/docs/automatic-updates.md +0 -0
- {dflash_console-0.3.249 → dflash_console-0.3.253}/docs/plans/shared-speak-stt-service.md +0 -0
- {dflash_console-0.3.249 → dflash_console-0.3.253}/docs/release-notes-0.3.103.md +0 -0
- {dflash_console-0.3.249 → dflash_console-0.3.253}/docs/release-notes-0.3.106.md +0 -0
- {dflash_console-0.3.249 → dflash_console-0.3.253}/docs/release-notes-0.3.117.md +0 -0
- {dflash_console-0.3.249 → dflash_console-0.3.253}/docs/release-notes-0.3.118.md +0 -0
- {dflash_console-0.3.249 → dflash_console-0.3.253}/docs/release-notes-0.3.119.md +0 -0
- {dflash_console-0.3.249 → dflash_console-0.3.253}/docs/release-notes-0.3.120.md +0 -0
- {dflash_console-0.3.249 → dflash_console-0.3.253}/docs/release-notes-0.3.121.md +0 -0
- {dflash_console-0.3.249 → dflash_console-0.3.253}/docs/release-notes-0.3.122.md +0 -0
- {dflash_console-0.3.249 → dflash_console-0.3.253}/docs/release-notes-0.3.123.md +0 -0
- {dflash_console-0.3.249 → dflash_console-0.3.253}/docs/release-notes-0.3.128.md +0 -0
- {dflash_console-0.3.249 → dflash_console-0.3.253}/docs/release-notes-0.3.129.md +0 -0
- {dflash_console-0.3.249 → dflash_console-0.3.253}/docs/release-notes-0.3.132.md +0 -0
- {dflash_console-0.3.249 → dflash_console-0.3.253}/docs/release-notes-0.3.133.md +0 -0
- {dflash_console-0.3.249 → dflash_console-0.3.253}/docs/release-notes-0.3.208.md +0 -0
- {dflash_console-0.3.249 → dflash_console-0.3.253}/docs/ui/README.md +0 -0
- {dflash_console-0.3.249 → dflash_console-0.3.253}/docs/ui/devices-view.md +0 -0
- {dflash_console-0.3.249 → dflash_console-0.3.253}/docs/ui/model-search.md +0 -0
- {dflash_console-0.3.249 → dflash_console-0.3.253}/docs/ui/models-view.md +0 -0
- {dflash_console-0.3.249 → dflash_console-0.3.253}/docs/ui/nodes-v1-plan.md +0 -0
- {dflash_console-0.3.249 → dflash_console-0.3.253}/docs/ui/settings-appearance.md +0 -0
- {dflash_console-0.3.249 → dflash_console-0.3.253}/docs/ui/settings-chat.md +0 -0
- {dflash_console-0.3.249 → dflash_console-0.3.253}/docs/ui/settings-developer.md +0 -0
- {dflash_console-0.3.249 → dflash_console-0.3.253}/docs/ui/settings-general.md +0 -0
- {dflash_console-0.3.249 → dflash_console-0.3.253}/docs/ui/settings-hardware.md +0 -0
- {dflash_console-0.3.249 → dflash_console-0.3.253}/docs/ui/settings-integrations.md +0 -0
- {dflash_console-0.3.249 → dflash_console-0.3.253}/docs/ui/settings-lm-link.md +0 -0
- {dflash_console-0.3.249 → dflash_console-0.3.253}/docs/ui/settings-model-defaults.md +0 -0
- {dflash_console-0.3.249 → dflash_console-0.3.253}/docs/ui/settings-runtime.md +0 -0
- {dflash_console-0.3.249 → dflash_console-0.3.253}/docs/ui/settings-runtimes.md +0 -0
- {dflash_console-0.3.249 → dflash_console-0.3.253}/static/app-functional.html +0 -0
- {dflash_console-0.3.249 → dflash_console-0.3.253}/static/css/dflash-console.css.bak-density +0 -0
- {dflash_console-0.3.249 → dflash_console-0.3.253}/static/css/dflash-shell.css.bak-density +0 -0
- {dflash_console-0.3.249 → dflash_console-0.3.253}/static/css/studio.css +0 -0
- {dflash_console-0.3.249 → dflash_console-0.3.253}/static/js/about-live.js +0 -0
- {dflash_console-0.3.249 → dflash_console-0.3.253}/static/js/app-settings-live.js +0 -0
- {dflash_console-0.3.249 → dflash_console-0.3.253}/static/js/app.js +0 -0
- {dflash_console-0.3.249 → dflash_console-0.3.253}/static/js/bug-report-live.js +0 -0
- {dflash_console-0.3.249 → dflash_console-0.3.253}/static/js/chat-live.js +0 -0
- {dflash_console-0.3.249 → dflash_console-0.3.253}/static/js/component-install-live.js +0 -0
- {dflash_console-0.3.249 → dflash_console-0.3.253}/static/js/console-api.js +0 -0
- {dflash_console-0.3.249 → dflash_console-0.3.253}/static/js/dashboard.js +0 -0
- {dflash_console-0.3.249 → dflash_console-0.3.253}/static/js/desktop-shell.js +0 -0
- {dflash_console-0.3.249 → dflash_console-0.3.253}/static/js/dflash-console-ui.js +0 -0
- {dflash_console-0.3.249 → dflash_console-0.3.253}/static/js/docs-live.js +0 -0
- {dflash_console-0.3.249 → dflash_console-0.3.253}/static/js/downloads-live.js +0 -0
- {dflash_console-0.3.249 → dflash_console-0.3.253}/static/js/library-browse-live.js +0 -0
- {dflash_console-0.3.249 → dflash_console-0.3.253}/static/js/library-scan-live.js +0 -0
- {dflash_console-0.3.249 → dflash_console-0.3.253}/static/js/library-type-options.js +0 -0
- {dflash_console-0.3.249 → dflash_console-0.3.253}/static/js/log-format.js +0 -0
- {dflash_console-0.3.249 → dflash_console-0.3.253}/static/js/model-card.js +0 -0
- {dflash_console-0.3.249 → dflash_console-0.3.253}/static/js/model-catalog-groups.js +0 -0
- {dflash_console-0.3.249 → dflash_console-0.3.253}/static/js/nodes-live.js +0 -0
- {dflash_console-0.3.249 → dflash_console-0.3.253}/static/js/runtime-recommendations.js +0 -0
- {dflash_console-0.3.249 → dflash_console-0.3.253}/static/js/runtime-steppers.js +0 -0
- {dflash_console-0.3.249 → dflash_console-0.3.253}/static/js/select-theme.js +0 -0
- {dflash_console-0.3.249 → dflash_console-0.3.253}/static/js/settings-live.js +0 -0
- {dflash_console-0.3.249 → dflash_console-0.3.253}/static/js/settings-live.js.api-providers-bak +0 -0
- {dflash_console-0.3.249 → dflash_console-0.3.253}/static/js/settings-live.js.pre-api-merge-bak +0 -0
- {dflash_console-0.3.249 → dflash_console-0.3.253}/static/js/setup-wizard-live.js +0 -0
- {dflash_console-0.3.249 → dflash_console-0.3.253}/static/js/speak-live.js +0 -0
- {dflash_console-0.3.249 → dflash_console-0.3.253}/static/js/stack-wizard.js +0 -0
- {dflash_console-0.3.249 → dflash_console-0.3.253}/static/js/sysbar-live.js +0 -0
- {dflash_console-0.3.249 → dflash_console-0.3.253}/static/js/table-column-resize.js +0 -0
- {dflash_console-0.3.249 → dflash_console-0.3.253}/static/js/ui-layout-prefs.js +0 -0
- {dflash_console-0.3.249 → dflash_console-0.3.253}/static/vendor/marked.min.js +0 -0
- {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.
|
|
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.
|
|
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.
|
|
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.
|
|
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.
|
|
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
|
-
|
|
261
|
-
if
|
|
262
|
-
server =
|
|
263
|
-
|
|
264
|
-
|
|
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
|
-
|
|
245
|
-
if
|
|
246
|
-
return {
|
|
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
|