mirror of
https://github.com/agent0ai/agent-zero.git
synced 2026-08-27 01:04:14 +00:00
Render API keys, access tokens, client secrets, and similar non-password credentials as masked text inputs so browsers do not offer to save them as passwords. Preserve readable placeholders and reveal controls while leaving genuine password fields unchanged.
135 lines
4.1 KiB
HTML
135 lines
4.1 KiB
HTML
<html>
|
|
<head>
|
|
<title>Manage API Keys</title>
|
|
</head>
|
|
|
|
<body>
|
|
<script type="module">
|
|
import { store } from "/plugins/_model_config/webui/model-config-store.js";
|
|
</script>
|
|
|
|
<div x-data>
|
|
<template x-if="$store.modelConfig">
|
|
<div x-data="{
|
|
loading: true,
|
|
saving: false,
|
|
error: '',
|
|
get hasChanges() {
|
|
const dirty = $store.modelConfig.apiKeyDirty;
|
|
return Object.keys(dirty).some((p) => dirty[p]);
|
|
},
|
|
async init() {
|
|
await $store.modelConfig.ensureLoaded();
|
|
$store.modelConfig.resetApiKeyDrafts();
|
|
await $store.modelConfig.refreshApiKeyStatus();
|
|
this.loading = false;
|
|
},
|
|
async reveal(provider) {
|
|
try {
|
|
await $store.modelConfig.revealApiKey(provider);
|
|
} catch (e) {
|
|
this.error = e?.message || 'Failed to reveal API key.';
|
|
}
|
|
},
|
|
async saveAndClose() {
|
|
this.saving = true;
|
|
this.error = '';
|
|
try {
|
|
await $store.modelConfig.persistAllDirtyApiKeys();
|
|
await $store.modelConfig.refreshApiKeyStatus();
|
|
window.closeModal?.();
|
|
} catch (e) {
|
|
this.error = e?.message || 'Failed to save API keys.';
|
|
} finally {
|
|
this.saving = false;
|
|
}
|
|
}
|
|
}"
|
|
x-init="init()">
|
|
|
|
<div class="api-keys-section">
|
|
<div class="section-title">API Keys</div>
|
|
<div class="section-description">
|
|
API keys for model providers and services used by Agent Zero. You can set multiple API keys separated by a comma (,). They will be used in round-robin fashion.<br>
|
|
For more information about Agent Zero Venice provider, see <a href="http://agent-zero.ai/?community/api-dashboard/about" target="_blank">Agent Zero Venice</a>.
|
|
</div>
|
|
|
|
<div x-show="error" class="plugin-settings-error" style="margin-top: 1rem;">
|
|
<x-icon name="error"></x-icon>
|
|
<span x-text="error"></span>
|
|
</div>
|
|
|
|
<div x-show="loading" style="text-align:center; padding: 20px;">
|
|
<x-icon class="spinning" name="progress_activity"></x-icon>
|
|
</div>
|
|
|
|
<div x-show="!loading">
|
|
<template x-for="provider in $store.modelConfig.allProviders" :key="provider.value">
|
|
<div class="field">
|
|
<div class="field-label">
|
|
<div class="field-title" x-text="provider.label"></div>
|
|
</div>
|
|
<div class="field-control" style="position:relative;" x-data="{ showKey: false }">
|
|
<input type="text"
|
|
:class="{ 'masked-text-input': !showKey }"
|
|
:value="$store.modelConfig.apiKeyValues[provider.value]"
|
|
:placeholder="provider.has_key ? '••••••••••••' : ''"
|
|
autocomplete="off"
|
|
@input="$store.modelConfig.setApiKeyValue(provider.value, $el.value)"
|
|
style="padding-right:32px;" />
|
|
<x-icon class="eye-toggle"
|
|
@click="
|
|
showKey = !showKey;
|
|
if (showKey && !$store.modelConfig.apiKeyValues[provider.value] && provider.has_key) {
|
|
reveal(provider.value);
|
|
}
|
|
"
|
|
:name="showKey ? 'visibility' : 'visibility_off'"></x-icon>
|
|
</div>
|
|
</div>
|
|
</template>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="modal-footer" data-modal-footer>
|
|
<button class="btn btn-ok"
|
|
@click="saveAndClose()"
|
|
:disabled="loading || saving || !hasChanges">
|
|
Save
|
|
</button>
|
|
<button class="btn btn-cancel"
|
|
@click="window.closeModal?.()"
|
|
:disabled="saving">
|
|
Close
|
|
</button>
|
|
</div>
|
|
</div>
|
|
</template>
|
|
</div>
|
|
|
|
<style>
|
|
.api-keys-section {
|
|
border: 1px solid var(--color-border);
|
|
border-radius: 8px;
|
|
padding: 16px;
|
|
}
|
|
.api-keys-section .section-title {
|
|
margin-top: 0;
|
|
}
|
|
.eye-toggle {
|
|
position: absolute;
|
|
right: 8px;
|
|
top: 50%;
|
|
transform: translateY(-50%);
|
|
font-size: 18px;
|
|
cursor: pointer;
|
|
user-select: none;
|
|
opacity: 0.6;
|
|
z-index: 1;
|
|
}
|
|
.eye-toggle:hover {
|
|
opacity: 1;
|
|
}
|
|
</style>
|
|
</body>
|
|
</html>
|