server info handle multi-gpu

Signed-off-by: Vladimir Mandic <mandic00@live.com>
This commit is contained in:
Vladimir Mandic
2026-07-09 11:18:04 +02:00
parent b2e4221fd0
commit f4348bcb69
10 changed files with 37 additions and 24 deletions
+5 -1
View File
@@ -1,9 +1,12 @@
# Change Log for SD.Next
## Update for 2026-07-08
## Update for 2026-07-09
- **Features**
- log view copy server log and copy client log buttons
this copies current log to clipboard for easy sharing
- api add `/sdapi/v1/restart` endpoint
- load transformers from all-in-one safetensors
- **Fixes**
- huggingface: fix model access on windows
- lora: fix lora text-encoder loader
@@ -11,6 +14,7 @@
- api: validate swagger schema
- installer: handle detached branch on non-english setups
- fs: faster stat
- server-info: handle multiple gpus
## Update for 2026-07-07
+2 -1
View File
@@ -20,7 +20,8 @@
- Processing -> Video capabilities
- `RIFE` in processing
- `SeedVR2` in processing
- Video model loader: Add video models to Reference
- Video models: add to Reference
- Video models: support custom entries
- UI Lite vs Expert mode
- Auto handle scheduler `prediction_type`
- Cache models in memory
+1 -1
View File
@@ -58,7 +58,7 @@ class Api:
self.add_api_route("/sdapi/v1/restart", server.post_restart, methods=["POST"], status_code=204, tags=["Server"])
self.add_api_route("/sdapi/v1/memory", server.get_memory, methods=["GET"], response_model=models.ResMemory, tags=["Server"])
self.add_api_route("/sdapi/v1/cmd-flags", server.get_cmd_flags, methods=["GET"], response_model=models.FlagsModel, tags=["Server"])
self.add_api_route("/sdapi/v1/gpu", gpu.get_gpu, methods=["GET"], tags=["Server"])
self.add_api_route("/sdapi/v1/gpu", gpu.get_gpu, methods=["GET"], tags=["Server"], response_model=list[dict])
self.add_api_route("/sdapi/v1/gpu-smi", gpu.get_gpu_smi, methods=["GET"], response_model=list[models.ResGPU], tags=["Server"])
# core api using locking
+1 -6
View File
@@ -7,12 +7,7 @@ device = None
def get_gpu():
import installer
res = {}
if len(installer.gpu_info) == 1:
return installer.gpu_info[0]
for i, item in enumerate(installer.gpu_info):
res[i] = item
return res
return installer.gpu_info
def get_gpu_smi():
+6
View File
@@ -7,6 +7,7 @@ interface TokenResponse {
let user: string | undefined;
let token: string | undefined;
let baseURL: string | undefined;
export async function getToken(): Promise<{ user: string | undefined; token: string | undefined }> {
if (token === undefined || user === undefined) {
@@ -38,6 +39,11 @@ export async function authFetch(url: RequestInfo | URL, options: RequestInit = {
error('fetch', { status: res?.status || 503, url, user, token, error: err });
}
}
if (!baseURL) {
// baseURL = `${window.location.protocol}//${window.location.host}:${window.location.port}`;
baseURL = window.location.origin;
log('origin', baseURL);
}
return res;
}
window.authFetch = authFetch;
+12 -6
View File
@@ -9883,6 +9883,7 @@ window.xhrPost = xhrPost;
// ui/authWrap.ts
var user;
var token;
var baseURL;
async function getToken() {
if (token === void 0 || user === void 0) {
const res = await fetch(`${window.subpath}/token`);
@@ -9912,6 +9913,10 @@ async function authFetch(url2, options = {}) {
error("fetch", { status: res?.status || 503, url: url2, user, token, error: err });
}
}
if (!baseURL) {
baseURL = window.location.origin;
log("origin", baseURL);
}
return res;
}
window.authFetch = authFetch;
@@ -15947,6 +15952,7 @@ async function initStartup() {
window.subpath = window.opts.subpath;
window.api = `${window.subpath}/sdapi/v1`;
}
log("API", window.api);
startupPromises.push(initLogMonitor());
executeCallbacks(uiReadyCallbacks);
if (window.waitForUiReady) await window.waitForUiReady();
@@ -19127,12 +19133,12 @@ async function updateGPU() {
}
const gpuTbody = gpuTable.querySelector("tbody");
if (!gpuTbody) return;
for (const gpu of data) {
let rows = `<tr><td>GPU</td><td>${gpu.name}</td></tr>`;
for (const item of Object.entries(gpu.data)) rows += `<tr><td>${item[0]}</td><td>${item[1]}</td></tr>`;
gpuTbody.innerHTML = rows;
if (gpu.chart && gpu.chart.length === 2) updateGPUChart(gpu.chart[0], gpu.chart[1]);
}
let gpu = { data: {} };
if (Array.isArray(data) && data.length >= 2) gpu = data[0];
let rows = `<tr><td>GPU</td><td>${gpu.name || "unknown"}</td></tr>`;
for (const item of Object.entries(gpu.data)) rows += `<tr><td>${item[0]}</td><td>${item[1]}</td></tr>`;
gpuTbody.innerHTML = rows;
if (gpu.chart && gpu.chart.length === 2) updateGPUChart(gpu.chart[0], gpu.chart[1]);
gpuEl.style.display = "block";
} catch (e) {
error("updateGPU", e);
+2 -2
View File
File diff suppressed because one or more lines are too long
+6 -6
View File
@@ -56,12 +56,12 @@ async function updateGPU(): Promise<void> {
}
const gpuTbody = gpuTable.querySelector('tbody');
if (!gpuTbody) return;
for (const gpu of data) {
let rows = `<tr><td>GPU</td><td>${gpu.name}</td></tr>`;
for (const item of Object.entries(gpu.data)) rows += `<tr><td>${item[0]}</td><td>${item[1]}</td></tr>`;
gpuTbody.innerHTML = rows;
if (gpu.chart && gpu.chart.length === 2) updateGPUChart(gpu.chart[0], gpu.chart[1]);
}
let gpu = { data: {} } as GpuInfo;
if (Array.isArray(data) && data.length >= 2) gpu = data[0];
let rows = `<tr><td>GPU</td><td>${gpu.name || 'unknown'}</td></tr>`;
for (const item of Object.entries(gpu.data)) rows += `<tr><td>${item[0]}</td><td>${item[1]}</td></tr>`;
gpuTbody.innerHTML = rows;
if (gpu.chart && gpu.chart.length === 2) updateGPUChart(gpu.chart[0], gpu.chart[1]);
gpuEl.style.display = 'block';
} catch (e) {
error('updateGPU', e);
+1
View File
@@ -88,6 +88,7 @@ async function initStartup() {
window.subpath = window.opts.subpath;
window.api = `${window.subpath}/sdapi/v1`;
}
log('API', window.api);
startupPromises.push(initLogMonitor());