{% extends "base.html" %} {% block title %}supyagent — Models{% endblock %} {% block extra_css %} .key-input-wrap { display: flex; gap: 8px; align-items: center; margin-top: 8px; } .key-input-wrap input { flex: 1; } .provider-card { display: flex; justify-content: space-between; align-items: flex-start; padding: 14px 16px; border-bottom: 1px solid var(--border); } .provider-card:last-child { border-bottom: none; } .provider-name { font-weight: 600; font-size: 13px; } .provider-desc { font-size: 12px; color: var(--text-dim); margin-top: 2px; } .role-select { width: 100%; margin-top: 4px; } .add-model-form { display: flex; gap: 8px; margin-top: 12px; } .add-model-form input { flex: 1; } .security-note { font-size: 11px; color: var(--text-muted); margin-top: 12px; padding: 8px 12px; background: var(--bg); border-radius: 4px; border: 1px solid var(--border); } {% endblock %} {% block content %}
Manage API keys, registered models, and role assignments.
| Model | Provider | API Key | Roles | |
|---|---|---|---|---|
| Loading... | ||||
Agents reference roles instead of specific models. Assign a model to each role.
${k} `
).join(", ");
statusHtml = `missing: ${parts}`;
} else if (m.key_name) {
statusHtml = `missing: ${m.key_name} `;
} else {
statusHtml = `missing `;
}
} else if (vs.startsWith("error:")) {
statusHtml = `error `;
} else {
statusHtml = `unverified`;
}
const badges = [];
if (m.is_default) badges.push(`default`);
m.roles.forEach(r => badges.push(`${r}`));
return `
${detectedKey}`;
valueLabel.textContent = detectedKey;
envRow.classList.add("hidden");
prompt.dataset.keyName = detectedKey;
} else {
// Unknown provider — ask for both env var name and value
label.innerHTML = `${model} uses an unknown provider. What environment variable holds its API key?`;
valueLabel.textContent = "API Key value";
envRow.classList.remove("hidden");
document.getElementById("key-prompt-env-name").value = "";
prompt.dataset.keyName = "";
}
document.getElementById("key-prompt-value").value = "";
document.getElementById("key-prompt-value").focus();
}
async function savePromptedKey() {
const prompt = document.getElementById("add-model-key-prompt");
let keyName = prompt.dataset.keyName;
const value = document.getElementById("key-prompt-value").value.trim();
if (!keyName) {
keyName = document.getElementById("key-prompt-env-name").value.trim();
}
if (!keyName) {
toast("Enter an environment variable name", "error");
return;
}
if (!value) {
toast("Enter an API key value", "error");
return;
}
try {
await apiCall("POST", "/api/keys/set", { key_name: keyName, value });
toast(`Saved ${keyName}`);
const modelToVerify = pendingKeyModel;
dismissKeyPrompt();
await loadState();
// Auto-verify the model after saving its key
if (modelToVerify) {
await verifyModel(modelToVerify);
}
} catch (e) {
toast(`Error: ${e.message}`, "error");
}
}
function dismissKeyPrompt() {
document.getElementById("add-model-key-prompt").classList.add("hidden");
pendingKeyModel = null;
}
async function removeModel(model) {
try {
await apiCall("POST", "/api/models/remove", { model });
toast(`Removed ${model}`);
await loadState();
} catch (e) {
toast(`Error: ${e.message}`, "error");
}
}
async function setDefault(model) {
try {
await apiCall("POST", "/api/models/default", { model });
toast(`Default: ${model}`);
await loadState();
} catch (e) {
toast(`Error: ${e.message}`, "error");
}
}
function renderRoles() {
const grid = document.getElementById("roles-grid");
const roles = state.standard_roles || ["fast", "smart", "reasoning", "cheap"];
const models = state.models || [];
const descriptions = {
fast: "Quick responses, lower cost",
smart: "Best general-purpose model",
reasoning: "Complex problem solving",
cheap: "Lowest cost option",
};
grid.innerHTML = roles.map(role => {
const current = state.roles[role] || "";
const options = models.map(m =>
``
).join("");
return `