class RunningModelsPage { constructor() { this.init(); } init() { document.getElementById("refresh-btn")?.addEventListener("click", () => { this.loadRunningModels(); }); this.loadRunningModels(); } async loadRunningModels() { const container = document.getElementById("running-models"); if (!container) { return; } container.innerHTML = `

Refreshing data...

`; try { const response = await fetch("/api/v1/models/running"); if (!response.ok) { throw new Error("Failed to load running models"); } const data = await response.json(); const models = data.models || []; this.renderStats(models); this.renderRunningModels(models); } catch (error) { container.innerHTML = `

Failed to load ollama ps output

`; this.renderStats([]); console.error(error); } } renderStats(models) { const runningCountEl = document.getElementById("running-count"); const vramTotalEl = document.getElementById("vram-total"); const lastRefreshEl = document.getElementById("last-refresh"); const totalVram = models.reduce((sum, model) => sum + (model.size_vram || 0), 0); if (runningCountEl) { runningCountEl.textContent = String(models.length); } if (vramTotalEl) { vramTotalEl.textContent = this.formatBytes(totalVram); } if (lastRefreshEl) { lastRefreshEl.textContent = new Date().toLocaleString("en-US"); } } renderRunningModels(models) { const container = document.getElementById("running-models"); if (!container) { return; } if (models.length === 0) { container.innerHTML = `

No models are currently loaded in memory.

`; return; } container.innerHTML = models .map((model) => this.renderModelCard(model)) .join(""); } renderModelCard(model) { const name = this.escapeHtml(model.name || "unknown"); const modelId = this.escapeHtml(model.model || "-"); const size = this.formatBytes(model.size || 0); const sizeVram = this.formatBytes(model.size_vram || 0); const processor = this.escapeHtml(model.details?.processor || "-"); const expiresAt = model.expires_at ? this.formatDateTime(model.expires_at) : "-"; return `

${name}

${modelId}

Ready

Model Size

${size}

VRAM Used

${sizeVram}

Processor

${processor}

Unload Time

${expiresAt}

`; } formatBytes(bytes) { if (!bytes || bytes <= 0) { return "0 B"; } const units = ["B", "KB", "MB", "GB", "TB"]; const index = Math.min(Math.floor(Math.log(bytes) / Math.log(1024)), units.length - 1); const value = bytes / Math.pow(1024, index); return `${value.toFixed(2)} ${units[index]}`; } formatDateTime(isoDate) { const date = new Date(isoDate); if (Number.isNaN(date.getTime())) { return "-"; } return date.toLocaleString("en-US", { year: "numeric", month: "short", day: "2-digit", hour: "2-digit", minute: "2-digit" }); } escapeHtml(text) { const div = document.createElement("div"); div.textContent = String(text); return div.innerHTML; } } document.addEventListener("DOMContentLoaded", () => { window.runningModelsPage = new RunningModelsPage(); });