File size: 4,212 Bytes
7d4338a
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
<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;">
      <span class="material-symbols-outlined">error</span>
      <span x-text="error"></span>
    </div>

    <div x-show="loading" style="text-align:center; padding: 20px;">
      <span class="material-symbols-outlined spinning">progress_activity</span>
    </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="showKey ? 'text' : 'password'"
                   :value="$store.modelConfig.apiKeyValues[provider.value]"
                   :placeholder="provider.has_key ? '••••••••••••' : ''"
                   autocomplete="off"
                   @input="$store.modelConfig.setApiKeyValue(provider.value, $el.value)"
                   style="padding-right:32px;" />
            <span class="material-symbols-outlined eye-toggle"
                  @click="
                    showKey = !showKey;
                    if (showKey && !$store.modelConfig.apiKeyValues[provider.value] && provider.has_key) {
                      reveal(provider.value);
                    }
                  "
                  x-text="showKey ? 'visibility' : 'visibility_off'"></span>
          </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>