From a9e8c637917e980c68f0d93d361faab395b9ed13 Mon Sep 17 00:00:00 2001 From: Hermes Agent Date: Mon, 24 Aug 2026 22:02:48 +1000 Subject: [PATCH] fix: show endpoint model names and duplicate targets --- README.md | 2 +- dashboard/dist/index.js | 4 ++-- dashboard/manifest.json | 2 +- dashboard/plugin_api.py | 7 ++++++- plugin.yaml | 2 +- 5 files changed, 11 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index d772487..7281ae7 100644 --- a/README.md +++ b/README.md @@ -61,7 +61,7 @@ The dashboard now includes a connection panel in the header. Enter an Ollama bas The plugin probes the configured local endpoint and known Docker endpoints, and tests a configured remote endpoint. A successful connection reports the Ollama version and installed model count. The active local endpoint continues to drive chat, status, load, and runtime telemetry. A URL saved from the dashboard takes precedence over the initial `OLLAMA_HOST` environment fallback, so the field can correct or replace an inherited container setting. -When both local and remote endpoints are online, downloading or re-downloading a model opens a destination chooser. The selected target is recorded on the job and the pull is sent to that endpoint. Remote downloads do not alter the local installed-model inventory. +When both distinct local and remote endpoints are online, downloading or re-downloading a model opens a destination chooser. The selected target is recorded on the job and the pull is sent to that endpoint. Remote downloads do not alter the local installed-model inventory. The connection rows display the actual model names returned by each endpoint. If Local and Remote contain the same URL, the dashboard marks the duplicate and treats it as one download target; enter the actual second Ollama server URL to enable independent remote downloads. The plugin supports both deployment types: diff --git a/dashboard/dist/index.js b/dashboard/dist/index.js index 44fb68f..a576aed 100644 --- a/dashboard/dist/index.js +++ b/dashboard/dist/index.js @@ -74,7 +74,7 @@ h("div", { className: "ollama-connection-heading" }, h("div", null, h("strong", null, "Ollama connection"), h("small", null, ollama.containerized ? "Docker runtime · local and remote endpoints supported" : "Physical runtime · local and remote endpoints supported"))), h("div", { className: "ollama-connection-form" }, h("select", { className: "ollama-connection-role", value: role, onChange: function (event) { setRole(event.target.value); } }, h("option", { value: "local" }, "Local"), h("option", { value: "remote" }, "Remote")), h("input", { className: "ollama-connection-input", value: url, placeholder: "http://host-or-container:11434", onChange: function (event) { setUrl(event.target.value); } }), h(Button, { onClick: test, disabled: !url.trim() || !!busy }, busy === "test" ? "Testing…" : "Test"), h(Button, { onClick: save, disabled: !url.trim() || !!busy }, busy === "save" ? "Saving…" : "Save")), result && h("div", { className: "ollama-connection-result " + (result.error ? "error" : "ok") }, result.error || ((result.value && result.value.version) ? "Online · v" + result.value.version + " · " + (result.value.models || 0) + " models" : "Connection accepted")), - h("div", { className: "ollama-connection-list" }, rows.length ? rows.map(function (item) { return h("button", { type: "button", className: "ollama-connection-row", key: item.kind + ":" + item.url, onClick: function () { useDetected(item); } }, h("span", { className: "ollama-connection-dot " + (item.available ? "online" : "offline") }), h("span", null, h("strong", null, (item.kind || "local").toUpperCase(), " · ", item.label || item.url), h("small", null, item.url, item.available ? " · v" + item.version + " · " + item.models + " models" : " · unavailable"))); }) : h("small", null, "No endpoints detected yet. Enter an Ollama URL and test it.")) + h("div", { className: "ollama-connection-list" }, rows.length ? rows.map(function (item) { return h("button", { type: "button", className: "ollama-connection-row", key: item.kind + ":" + item.url, onClick: function () { useDetected(item); } }, h("span", { className: "ollama-connection-dot " + (item.available ? "online" : "offline") }), h("span", null, h("strong", null, (item.kind || "local").toUpperCase(), " · ", item.label || item.url), h("small", null, item.url, item.available ? " · v" + item.version + " · " + item.models + " models" + (item.model_names && item.model_names.length ? " · " + item.model_names.join(", ") : "") + (item.same_endpoint ? " · same endpoint as local" : "") : " · unavailable"))); }) : h("small", null, "No endpoints detected yet. Enter an Ollama URL and test it.")) ); } @@ -376,7 +376,7 @@ if (kind === "delete" && !window.confirm("Remove " + name + " from Ollama?")) return; if ((kind === "pull" || kind === "redownload") && !selectedTarget) { var availableTargets = (data && data.connections ? data.connections : []).filter(function (item) { return item.available && (item.kind === "local" || item.kind === "remote"); }); - var uniqueTargets = availableTargets.filter(function (item, index, rows) { return rows.findIndex(function (other) { return other.kind === item.kind; }) === index; }); + var uniqueTargets = availableTargets.filter(function (item, index, rows) { return rows.findIndex(function (other) { return other.kind === item.kind || other.url === item.url; }) === index; }); if (uniqueTargets.length > 1) { setTargetDialog({ kind: kind, name: name, targets: uniqueTargets }); return; } selectedTarget = uniqueTargets.length ? uniqueTargets[0].kind : "local"; } diff --git a/dashboard/manifest.json b/dashboard/manifest.json index 200f993..b67504e 100644 --- a/dashboard/manifest.json +++ b/dashboard/manifest.json @@ -3,7 +3,7 @@ "label": "Ollama Models", "description": "Inspect, manage, and chat with local Ollama models, including shared persistent conversations, performance metrics, images, PDFs, URLs, and live memory telemetry.", "icon": "Cpu", - "version": "1.5.7", + "version": "1.5.8", "tab": {"path": "/ollama-manager", "position": "after:models"}, "entry": "dist/index.js", "css": "dist/style.css", diff --git a/dashboard/plugin_api.py b/dashboard/plugin_api.py index 15e3753..066c532 100644 --- a/dashboard/plugin_api.py +++ b/dashboard/plugin_api.py @@ -333,7 +333,8 @@ def _probe_endpoint(url: str, timeout: int = 5) -> dict[str, Any]: version_payload = _json_request(url + "/api/version", timeout=timeout) tags_payload = _json_request(url + "/api/tags", timeout=timeout) models = tags_payload.get("models", []) - return {"available": True, "url": url, "version": str(version_payload.get("version") or "unknown"), "models": len(models) if isinstance(models, list) else 0} + model_names = [str(item.get("name") or item.get("model")) for item in models if isinstance(item, dict) and (item.get("name") or item.get("model"))] + return {"available": True, "url": url, "version": str(version_payload.get("version") or "unknown"), "models": len(model_names), "model_names": model_names[:100]} def _connection_snapshot() -> list[dict[str, Any]]: @@ -365,6 +366,10 @@ def _connection_snapshot() -> list[dict[str, Any]]: except Exception as exc: result = {"available": False, "kind": kind, "label": label, "url": normalized, "error": str(exc)[:240]} results.append(result) + local_urls = {row.get("url") for row in results if row.get("kind") == "local" and row.get("available")} + for row in results: + if row.get("kind") == "remote" and row.get("url") in local_urls: + row["same_endpoint"] = True return results diff --git a/plugin.yaml b/plugin.yaml index 28f6012..d901f70 100644 --- a/plugin.yaml +++ b/plugin.yaml @@ -1,5 +1,5 @@ name: ollama-manager -version: 1.5.7 +version: 1.5.8 description: Native dashboard manager and chat interface for local Ollama models, attachments, URLs, shared persistent conversations, performance metrics, and live runtime telemetry. auto_install_dependencies: true python_dependencies: