fixing app logic and eventListeners in frontend
This commit is contained in:
parent
3585f90437
commit
26dcbf9c02
2 changed files with 92 additions and 72 deletions
23
router.py
23
router.py
|
|
@ -122,6 +122,20 @@ async def _ensure_success(resp: aiohttp.ClientResponse) -> None:
|
|||
if resp.status >= 400:
|
||||
text = await resp.text()
|
||||
raise HTTPException(status_code=resp.status, detail=text)
|
||||
|
||||
def is_ext_openai_endpoint(endpoint: str) -> bool:
|
||||
if "/v1" not in endpoint:
|
||||
return False
|
||||
|
||||
base_endpoint = endpoint.replace('/v1', '')
|
||||
if base_endpoint in config.endpoints:
|
||||
return False # It's Ollama's /v1
|
||||
|
||||
# Check for default Ollama port
|
||||
if ':11434' in endpoint:
|
||||
return False # It's Ollama
|
||||
|
||||
return True # It's an external OpenAI endpoint
|
||||
|
||||
class fetch:
|
||||
async def available_models(endpoint: str, api_key: Optional[str] = None) -> Set[str]:
|
||||
|
|
@ -508,8 +522,13 @@ async def choose_endpoint(model: str) -> str:
|
|||
# 6️⃣
|
||||
if not candidate_endpoints:
|
||||
if ":latest" in model: #ollama naming convention not applicable to openai
|
||||
model = model.split(":latest")
|
||||
model = model[0]
|
||||
model_without_latest = model.split(":latest")[0]
|
||||
candidate_endpoints = [
|
||||
ep for ep, models in zip(config.endpoints, advertised_sets)
|
||||
if model_without_latest in models and is_ext_openai_endpoint(ep)
|
||||
]
|
||||
if not candidate_endpoints:
|
||||
model = model + ":latest"
|
||||
candidate_endpoints = [
|
||||
ep for ep, models in zip(config.endpoints, advertised_sets)
|
||||
if model in models
|
||||
|
|
|
|||
|
|
@ -424,76 +424,6 @@
|
|||
});
|
||||
});
|
||||
|
||||
/* show logic */
|
||||
document.body.addEventListener("click", async (e) => {
|
||||
if (!e.target.matches(".show-link")) return;
|
||||
e.preventDefault();
|
||||
const model = e.target.dataset.model;
|
||||
try {
|
||||
const resp = await fetch(
|
||||
`/api/show?model=${encodeURIComponent(model)}`,
|
||||
{ method: "POST" },
|
||||
);
|
||||
if (!resp.ok)
|
||||
throw new Error(`Status ${resp.status}`);
|
||||
const data = await resp.json();
|
||||
document.getElementById("json-output").textContent =
|
||||
JSON.stringify(data, null, 2).replace(
|
||||
/\\n/g,
|
||||
"\n",
|
||||
);
|
||||
document.getElementById(
|
||||
"show-modal",
|
||||
).style.display = "flex";
|
||||
} catch (err) {
|
||||
console.error(err);
|
||||
alert(
|
||||
`Could not load model details: ${err.message}`,
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
/* pull logic */
|
||||
document
|
||||
.getElementById("pull-btn")
|
||||
.addEventListener("click", async () => {
|
||||
const model = document
|
||||
.getElementById("pull-model-input")
|
||||
.value.trim();
|
||||
const statusEl =
|
||||
document.getElementById("pull-status");
|
||||
if (!model) {
|
||||
alert("Please enter a model name.");
|
||||
return;
|
||||
}
|
||||
try {
|
||||
const resp = await fetch(
|
||||
`/api/pull?model=${encodeURIComponent(model)}`,
|
||||
{ method: "POST" },
|
||||
);
|
||||
if (!resp.ok)
|
||||
throw new Error(`Status ${resp.status}`);
|
||||
const data = await resp.json();
|
||||
statusEl.textContent = `✅ ${data.status}`;
|
||||
statusEl.style.color = "green";
|
||||
loadTags();
|
||||
} catch (err) {
|
||||
console.error(err);
|
||||
statusEl.textContent = `❌ ${err.message}`;
|
||||
statusEl.style.color = "red";
|
||||
}
|
||||
});
|
||||
|
||||
/* modal close */
|
||||
const modal = document.getElementById("show-modal");
|
||||
modal.addEventListener("click", (e) => {
|
||||
if (
|
||||
e.target === modal ||
|
||||
e.target.matches(".close-btn")
|
||||
) {
|
||||
modal.style.display = "none";
|
||||
}
|
||||
});
|
||||
} catch (e) {
|
||||
console.error(e);
|
||||
}
|
||||
|
|
@ -592,6 +522,77 @@
|
|||
loadUsage();
|
||||
setInterval(loadPS, 60_000);
|
||||
setInterval(loadEndpoints, 300_000);
|
||||
|
||||
/* show logic */
|
||||
document.body.addEventListener("click", async (e) => {
|
||||
if (!e.target.matches(".show-link")) return;
|
||||
e.preventDefault();
|
||||
const model = e.target.dataset.model;
|
||||
try {
|
||||
const resp = await fetch(
|
||||
`/api/show?model=${encodeURIComponent(model)}`,
|
||||
{ method: "POST" },
|
||||
);
|
||||
if (!resp.ok)
|
||||
throw new Error(`Status ${resp.status}`);
|
||||
const data = await resp.json();
|
||||
document.getElementById("json-output").textContent =
|
||||
JSON.stringify(data, null, 2).replace(
|
||||
/\\n/g,
|
||||
"\n",
|
||||
);
|
||||
document.getElementById(
|
||||
"show-modal",
|
||||
).style.display = "flex";
|
||||
} catch (err) {
|
||||
console.error(err);
|
||||
alert(
|
||||
`Could not load model details: ${err.message}`,
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
/* pull logic */
|
||||
document
|
||||
.getElementById("pull-btn")
|
||||
.addEventListener("click", async () => {
|
||||
const model = document
|
||||
.getElementById("pull-model-input")
|
||||
.value.trim();
|
||||
const statusEl =
|
||||
document.getElementById("pull-status");
|
||||
if (!model) {
|
||||
alert("Please enter a model name.");
|
||||
return;
|
||||
}
|
||||
try {
|
||||
const resp = await fetch(
|
||||
`/api/pull?model=${encodeURIComponent(model)}`,
|
||||
{ method: "POST" },
|
||||
);
|
||||
if (!resp.ok)
|
||||
throw new Error(`Status ${resp.status}`);
|
||||
const data = await resp.json();
|
||||
statusEl.textContent = `✅ ${data.status}`;
|
||||
statusEl.style.color = "green";
|
||||
loadTags();
|
||||
} catch (err) {
|
||||
console.error(err);
|
||||
statusEl.textContent = `❌ ${err.message}`;
|
||||
statusEl.style.color = "red";
|
||||
}
|
||||
});
|
||||
|
||||
/* modal close */
|
||||
const modal = document.getElementById("show-modal");
|
||||
modal.addEventListener("click", (e) => {
|
||||
if (
|
||||
e.target === modal ||
|
||||
e.target.matches(".close-btn")
|
||||
) {
|
||||
modal.style.display = "none";
|
||||
}
|
||||
});
|
||||
});
|
||||
</script>
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue