diff --git a/image/app/models.py b/image/app/models.py
index 22bd393..40e56ff 100644
--- a/image/app/models.py
+++ b/image/app/models.py
@@ -12,6 +12,7 @@ class ModelDef(BaseModel):
capabilities: list[str] = Field(default_factory=list)
expected_ready_seconds: int = 300
vllm_args: list[str] = Field(default_factory=list)
+ description: str | None = None
class Defaults(BaseModel):
diff --git a/image/app/static/app.js b/image/app/static/app.js
index 4d5c25d..2a2fa49 100644
--- a/image/app/static/app.js
+++ b/image/app/static/app.js
@@ -18,6 +18,16 @@ const state = {
const el = (sel) => document.querySelector(sel);
const $$ = (sel) => document.querySelectorAll(sel);
+function escapeHtml(s) {
+ if (s == null) return '';
+ return String(s)
+ .replaceAll('&', '&')
+ .replaceAll('<', '<')
+ .replaceAll('>', '>')
+ .replaceAll('"', '"')
+ .replaceAll("'", ''');
+}
+
async function fetchJSON(url, opts) {
const r = await fetch(url, opts);
if (!r.ok) {
@@ -38,14 +48,18 @@ function renderCards() {
const isActive = key === state.current_model_key;
const card = document.createElement('div');
card.className = 'card' + (isActive ? ' active' : '');
+ const desc = m.description
+ ? `
${escapeHtml(m.description)}
`
+ : '';
card.innerHTML = `
- ${m.display_name}
+ ${escapeHtml(m.display_name)}
${m.mode}
${m.size_gb} GB
- ${(m.capabilities || []).map(c => `${c}`).join('')}
+ ${(m.capabilities || []).map(c => `${escapeHtml(c)}`).join('')}
- ${m.repo}
+ ${desc}
+ ${escapeHtml(m.repo)}