File size: 4,189 Bytes
57d4e72
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
136
<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>