Settings polishing, logout button

frdel committed Feb 5, 2026 at 22:02 UTC 181135f58a4850d6fbb07aa5d5841bb021f1e1e2
34 files changed +256 -154
python/api/logout.py new
+15
@@ -0,0 +1,15 @@
1 +from python.helpers.api import ApiHandler, Request, session
2 +
3 +
4 +class ApiLogout(ApiHandler):
5 + @classmethod
6 + def requires_auth(cls) -> bool:
7 + return False
8 +
9 + async def process(self, input: dict, request: Request) -> dict:
10 + try:
11 + session.clear()
12 + except Exception:
13 + session.pop("authentication", None)
14 + session.pop("csrf_token", None)
15 + return {"ok": True}
run_ui.py
+1
@@ -218,6 +218,7 @@ async def serve_index():
218 version_time=gitinfo["commit_time"],
219 runtime_id=runtime.get_runtime_id(),
220 runtime_is_development=("true" if runtime.is_development() else "false"),
221 + logged_in=("true" if login.get_credentials_hash() else "false"),
222 )
223 return index
224
tests/test_settings_developer_sections.py
+1 -1
@@ -20,7 +20,7 @@ def test_websocket_harness_entrypoint_is_present_in_developer_settings_template(
20 content = dev_template_path.read_text(encoding="utf-8")
21 assert "websocket-tester.html" in content
22 assert "websocket-event-console.html" in content
23 - assert "!$store.settingsStore.additional?.is_dockerized" in content
23 + assert "!$store.settings.additional?.is_dockerized" in content
24
25
26 def test_websocket_harness_template_is_gated_by_runtime():
webui/components/settings/a2a/a2a-connection.html
+2 -2
@@ -11,7 +11,7 @@
11
12 <!-- API Token Information -->
13 <div x-data>
14 - <template x-if="$store.settingsStore.settings">
14 + <template x-if="$store.settings.settings">
15 <div style="background-color: var(--color-bg-secondary); border: 1px solid var(--color-border); border-radius: 6px; padding: 12px; margin: 16px 0;">
16 <h4 style="margin: 0 0 8px 0; color: var(--color-text-primary);">API Token Information</h4>
17 <p style="margin: 0 0 8px 0; color: var(--color-text-secondary); font-size: 14px;">
@@ -21,7 +21,7 @@
21 </p>
22 <div style="margin-top: 8px;">
23 <label style="display: block; margin-bottom: 4px; color: var(--color-text-secondary); font-size: 12px; font-weight: 600;">Token:</label>
24 - <input type="text" readonly x-model="$store.settingsStore.settings.mcp_server_token" style="width: 100%; padding: 6px 8px; background-color: var(--color-bg-primary); color: var(--color-text-primary); border: 1px solid var(--color-border); border-radius: 4px; font-family: monospace; font-size: 13px;" />
24 + <input type="text" readonly x-model="$store.settings.settings.mcp_server_token" style="width: 100%; padding: 6px 8px; background-color: var(--color-bg-primary); color: var(--color-text-primary); border: 1px solid var(--color-border); border-radius: 4px; font-family: monospace; font-size: 13px;" />
25 </div>
26 </div>
27 </template>
webui/components/settings/a2a/a2a-server.html
+1 -1
@@ -4,7 +4,7 @@
4 </head>
5
6 <body>
7 - <div x-data="{ get settings() { return $store.settingsStore.settings } }">
7 + <div x-data="{ get settings() { return $store.settings.settings } }">
8 <template x-if="settings">
9 <div>
10 <div class="section-title">A0 A2A Server</div>
webui/components/settings/agent/agent-settings.html
+1 -1
@@ -5,7 +5,7 @@
5
6 <body>
7 <div x-data>
8 - <template x-if="$store.settingsStore">
8 + <template x-if="$store.settings">
9 <div>
10 <nav>
11 <ul>
webui/components/settings/agent/agent.html
+7 -7
@@ -5,7 +5,7 @@
5
6 <body>
7 <div x-data>
8 - <template x-if="$store.settingsStore.settings">
8 + <template x-if="$store.settings.settings">
9 <div>
10 <div class="section-title">Agent Config</div>
11 <div class="section-description">
@@ -20,9 +20,9 @@
20 </div>
21 </div>
22 <div class="field-control">
23 - <select x-model="$store.settingsStore.settings.agent_profile">
24 - <template x-for="option in $store.settingsStore.additional?.agent_subdirs" :key="option.value">
25 - <option :value="option.value" :selected="option.value === $store.settingsStore.settings.agent_profile" x-text="option.label"></option>
23 + <select x-model="$store.settings.settings.agent_profile">
24 + <template x-for="option in $store.settings.additional?.agent_subdirs" :key="option.value">
25 + <option :value="option.value" :selected="option.value === $store.settings.settings.agent_profile" x-text="option.label"></option>
26 </template>
27 </select>
28 </div>
@@ -36,9 +36,9 @@
36 </div>
37 </div>
38 <div class="field-control">
39 - <select x-model="$store.settingsStore.settings.agent_knowledge_subdir">
40 - <template x-for="option in $store.settingsStore.additional?.knowledge_subdirs" :key="option.value">
41 - <option :value="option.value" :selected="option.value === $store.settingsStore.settings.agent_knowledge_subdir" x-text="option.label"></option>
39 + <select x-model="$store.settings.settings.agent_knowledge_subdir">
40 + <template x-for="option in $store.settings.additional?.knowledge_subdirs" :key="option.value">
41 + <option :value="option.value" :selected="option.value === $store.settings.settings.agent_knowledge_subdir" x-text="option.label"></option>
42 </template>
43 </select>
44 </div>
webui/components/settings/agent/browser_model.html
+26 -12
@@ -5,7 +5,7 @@
5
6 <body>
7 <div x-data>
8 - <template x-if="$store.settingsStore.settings">
8 + <template x-if="$store.settings.settings">
9 <div>
10 <div class="section-title">Web Browser Model</div>
11 <div class="section-description">
@@ -18,9 +18,9 @@
18 <div class="field-description">Select provider for web browser model used by Agent Zero</div>
19 </div>
20 <div class="field-control">
21 - <select x-model="$store.settingsStore.settings.browser_model_provider">
22 - <template x-for="option in $store.settingsStore.additional?.chat_providers" :key="option.value">
23 - <option :value="option.value" :selected="option.value === $store.settingsStore.settings.browser_model_provider" x-text="option.label"></option>
21 + <select x-model="$store.settings.settings.browser_model_provider">
22 + <template x-for="option in $store.settings.additional?.chat_providers" :key="option.value">
23 + <option :value="option.value" :selected="option.value === $store.settings.settings.browser_model_provider" x-text="option.label"></option>
24 </template>
25 </select>
26 </div>
@@ -32,7 +32,21 @@
32 <div class="field-description">Exact name of model from selected provider</div>
33 </div>
34 <div class="field-control">
35 - <input type="text" x-model="$store.settingsStore.settings.browser_model_name" />
35 + <input type="text" x-model="$store.settings.settings.browser_model_name" />
36 + </div>
37 + </div>
38 +
39 + <div class="field">
40 + <div class="field-label">
41 + <div class="field-title">API key</div>
42 + <div class="field-description">API key for the selected web browser model provider</div>
43 + </div>
44 + <div class="field-control">
45 + <input
46 + type="text"
47 + x-model="$store.settings.settings.api_keys[$store.settings.settings.browser_model_provider]"
48 + autocomplete="off"
49 + />
50 </div>
51 </div>
52
@@ -44,7 +58,7 @@
58 </div>
59 </div>
60 <div class="field-control">
47 - <input type="text" x-model="$store.settingsStore.settings.browser_model_api_base" />
61 + <input type="text" x-model="$store.settings.settings.browser_model_api_base" />
62 </div>
63 </div>
64
@@ -57,7 +71,7 @@
71 </div>
72 <div class="field-control">
73 <label class="toggle">
60 - <input type="checkbox" x-model="$store.settingsStore.settings.browser_model_vision" />
74 + <input type="checkbox" x-model="$store.settings.settings.browser_model_vision" />
75 <span class="toggler"></span>
76 </label>
77 </div>
@@ -71,7 +85,7 @@
85 </div>
86 </div>
87 <div class="field-control">
74 - <input type="number" x-model.number="$store.settingsStore.settings.browser_model_rl_requests" />
88 + <input type="number" x-model.number="$store.settings.settings.browser_model_rl_requests" />
89 </div>
90 </div>
91
@@ -83,7 +97,7 @@
97 </div>
98 </div>
99 <div class="field-control">
86 - <input type="number" x-model.number="$store.settingsStore.settings.browser_model_rl_input" />
100 + <input type="number" x-model.number="$store.settings.settings.browser_model_rl_input" />
101 </div>
102 </div>
103
@@ -95,7 +109,7 @@
109 </div>
110 </div>
111 <div class="field-control">
98 - <input type="number" x-model.number="$store.settingsStore.settings.browser_model_rl_output" />
112 + <input type="number" x-model.number="$store.settings.settings.browser_model_rl_output" />
113 </div>
114 </div>
115
@@ -107,7 +121,7 @@
121 </div>
122 </div>
123 <div class="field-control">
110 - <textarea x-model="$store.settingsStore.settings.browser_model_kwargs"></textarea>
124 + <textarea x-model="$store.settings.settings.browser_model_kwargs"></textarea>
125 </div>
126 </div>
127
@@ -119,7 +133,7 @@
133 </div>
134 </div>
135 <div class="field-control">
122 - <textarea x-model="$store.settingsStore.settings.browser_http_headers"></textarea>
136 + <textarea x-model="$store.settings.settings.browser_http_headers"></textarea>
137 </div>
138 </div>
139 </div>
webui/components/settings/agent/chat_model.html
+28 -14
@@ -5,7 +5,7 @@
5
6 <body>
7 <div x-data>
8 - <template x-if="$store.settingsStore.settings">
8 + <template x-if="$store.settings.settings">
9 <div>
10 <div class="section-title">Chat Model</div>
11 <div class="section-description">
@@ -18,9 +18,9 @@
18 <div class="field-description">Select provider for main chat model used by Agent Zero</div>
19 </div>
20 <div class="field-control">
21 - <select x-model="$store.settingsStore.settings.chat_model_provider">
22 - <template x-for="option in $store.settingsStore.additional?.chat_providers" :key="option.value">
23 - <option :value="option.value" :selected="option.value === $store.settingsStore.settings.chat_model_provider" x-text="option.label"></option>
21 + <select x-model="$store.settings.settings.chat_model_provider">
22 + <template x-for="option in $store.settings.additional?.chat_providers" :key="option.value">
23 + <option :value="option.value" :selected="option.value === $store.settings.settings.chat_model_provider" x-text="option.label"></option>
24 </template>
25 </select>
26 </div>
@@ -32,7 +32,21 @@
32 <div class="field-description">Exact name of model from selected provider</div>
33 </div>
34 <div class="field-control">
35 - <input type="text" x-model="$store.settingsStore.settings.chat_model_name" />
35 + <input type="text" x-model="$store.settings.settings.chat_model_name" />
36 + </div>
37 + </div>
38 +
39 + <div class="field">
40 + <div class="field-label">
41 + <div class="field-title">API key</div>
42 + <div class="field-description">API key for the selected chat model provider</div>
43 + </div>
44 + <div class="field-control">
45 + <input
46 + type="text"
47 + x-model="$store.settings.settings.api_keys[$store.settings.settings.chat_model_provider]"
48 + autocomplete="off"
49 + />
50 </div>
51 </div>
52
@@ -44,7 +58,7 @@
58 </div>
59 </div>
60 <div class="field-control">
47 - <input type="text" x-model="$store.settingsStore.settings.chat_model_api_base" />
61 + <input type="text" x-model="$store.settings.settings.chat_model_api_base" />
62 </div>
63 </div>
64
@@ -56,7 +70,7 @@
70 </div>
71 </div>
72 <div class="field-control">
59 - <input type="number" x-model.number="$store.settingsStore.settings.chat_model_ctx_length" />
73 + <input type="number" x-model.number="$store.settings.settings.chat_model_ctx_length" />
74 </div>
75 </div>
76
@@ -73,9 +87,9 @@
87 min="0.01"
88 max="1"
89 step="0.01"
76 - x-model.number="$store.settingsStore.settings.chat_model_ctx_history"
90 + x-model.number="$store.settings.settings.chat_model_ctx_history"
91 />
78 - <span class="range-value" x-text="$store.settingsStore.settings.chat_model_ctx_history"></span>
92 + <span class="range-value" x-text="$store.settings.settings.chat_model_ctx_history"></span>
93 </div>
94 </div>
95
@@ -88,7 +102,7 @@
102 </div>
103 <div class="field-control">
104 <label class="toggle">
91 - <input type="checkbox" x-model="$store.settingsStore.settings.chat_model_vision" />
105 + <input type="checkbox" x-model="$store.settings.settings.chat_model_vision" />
106 <span class="toggler"></span>
107 </label>
108 </div>
@@ -102,7 +116,7 @@
116 </div>
117 </div>
118 <div class="field-control">
105 - <input type="number" x-model.number="$store.settingsStore.settings.chat_model_rl_requests" />
119 + <input type="number" x-model.number="$store.settings.settings.chat_model_rl_requests" />
120 </div>
121 </div>
122
@@ -114,7 +128,7 @@
128 </div>
129 </div>
130 <div class="field-control">
117 - <input type="number" x-model.number="$store.settingsStore.settings.chat_model_rl_input" />
131 + <input type="number" x-model.number="$store.settings.settings.chat_model_rl_input" />
132 </div>
133 </div>
134
@@ -126,7 +140,7 @@
140 </div>
141 </div>
142 <div class="field-control">
129 - <input type="number" x-model.number="$store.settingsStore.settings.chat_model_rl_output" />
143 + <input type="number" x-model.number="$store.settings.settings.chat_model_rl_output" />
144 </div>
145 </div>
146
@@ -138,7 +152,7 @@
152 </div>
153 </div>
154 <div class="field-control">
141 - <textarea x-model="$store.settingsStore.settings.chat_model_kwargs"></textarea>
155 + <textarea x-model="$store.settings.settings.chat_model_kwargs"></textarea>
156 </div>
157 </div>
158 </div>
webui/components/settings/agent/embed_model.html
+23 -9
@@ -5,7 +5,7 @@
5
6 <body>
7 <div x-data>
8 - <template x-if="$store.settingsStore.settings">
8 + <template x-if="$store.settings.settings">
9 <div>
10 <div class="section-title">Embedding Model</div>
11 <div class="section-description">
@@ -18,9 +18,9 @@
18 <div class="field-description">Select provider for embedding model used by the framework</div>
19 </div>
20 <div class="field-control">
21 - <select x-model="$store.settingsStore.settings.embed_model_provider">
22 - <template x-for="option in $store.settingsStore.additional?.embedding_providers" :key="option.value">
23 - <option :value="option.value" :selected="option.value === $store.settingsStore.settings.embed_model_provider" x-text="option.label"></option>
21 + <select x-model="$store.settings.settings.embed_model_provider">
22 + <template x-for="option in $store.settings.additional?.embedding_providers" :key="option.value">
23 + <option :value="option.value" :selected="option.value === $store.settings.settings.embed_model_provider" x-text="option.label"></option>
24 </template>
25 </select>
26 </div>
@@ -32,7 +32,21 @@
32 <div class="field-description">Exact name of model from selected provider</div>
33 </div>
34 <div class="field-control">
35 - <input type="text" x-model="$store.settingsStore.settings.embed_model_name" />
35 + <input type="text" x-model="$store.settings.settings.embed_model_name" />
36 + </div>
37 + </div>
38 +
39 + <div class="field">
40 + <div class="field-label">
41 + <div class="field-title">API key</div>
42 + <div class="field-description">API key for the selected embedding model provider</div>
43 + </div>
44 + <div class="field-control">
45 + <input
46 + type="text"
47 + x-model="$store.settings.settings.api_keys[$store.settings.settings.embed_model_provider]"
48 + autocomplete="off"
49 + />
50 </div>
51 </div>
52
@@ -44,7 +58,7 @@
58 </div>
59 </div>
60 <div class="field-control">
47 - <input type="text" x-model="$store.settingsStore.settings.embed_model_api_base" />
61 + <input type="text" x-model="$store.settings.settings.embed_model_api_base" />
62 </div>
63 </div>
64
@@ -56,7 +70,7 @@
70 </div>
71 </div>
72 <div class="field-control">
59 - <input type="number" x-model.number="$store.settingsStore.settings.embed_model_rl_requests" />
73 + <input type="number" x-model.number="$store.settings.settings.embed_model_rl_requests" />
74 </div>
75 </div>
76
@@ -68,7 +82,7 @@
82 </div>
83 </div>
84 <div class="field-control">
71 - <input type="number" x-model.number="$store.settingsStore.settings.embed_model_rl_input" />
85 + <input type="number" x-model.number="$store.settings.settings.embed_model_rl_input" />
86 </div>
87 </div>
88
@@ -80,7 +94,7 @@
94 </div>
95 </div>
96 <div class="field-control">
83 - <textarea x-model="$store.settingsStore.settings.embed_model_kwargs"></textarea>
97 + <textarea x-model="$store.settings.settings.embed_model_kwargs"></textarea>
98 </div>
99 </div>
100 </div>
webui/components/settings/agent/memory.html
+19 -19
@@ -5,7 +5,7 @@
5
6 <body>
7 <div x-data>
8 - <template x-if="$store.settingsStore.settings">
8 + <template x-if="$store.settings.settings">
9 <div>
10 <div class="section-title">Memory</div>
11 <div class="section-description">
@@ -20,7 +20,7 @@
20 </div>
21 </div>
22 <div class="field-control">
23 - <input type="text" x-model="$store.settingsStore.settings.agent_memory_subdir" />
23 + <input type="text" x-model="$store.settings.settings.agent_memory_subdir" />
24 </div>
25 </div>
26
@@ -48,7 +48,7 @@
48 </div>
49 <div class="field-control">
50 <label class="toggle">
51 - <input type="checkbox" x-model="$store.settingsStore.settings.memory_recall_enabled" />
51 + <input type="checkbox" x-model="$store.settings.settings.memory_recall_enabled" />
52 <span class="toggler"></span>
53 </label>
54 </div>
@@ -63,7 +63,7 @@
63 </div>
64 <div class="field-control">
65 <label class="toggle">
66 - <input type="checkbox" x-model="$store.settingsStore.settings.memory_recall_delayed" />
66 + <input type="checkbox" x-model="$store.settings.settings.memory_recall_delayed" />
67 <span class="toggler"></span>
68 </label>
69 </div>
@@ -78,7 +78,7 @@
78 </div>
79 <div class="field-control">
80 <label class="toggle">
81 - <input type="checkbox" x-model="$store.settingsStore.settings.memory_recall_query_prep" />
81 + <input type="checkbox" x-model="$store.settings.settings.memory_recall_query_prep" />
82 <span class="toggler"></span>
83 </label>
84 </div>
@@ -93,7 +93,7 @@
93 </div>
94 <div class="field-control">
95 <label class="toggle">
96 - <input type="checkbox" x-model="$store.settingsStore.settings.memory_recall_post_filter" />
96 + <input type="checkbox" x-model="$store.settings.settings.memory_recall_post_filter" />
97 <span class="toggler"></span>
98 </label>
99 </div>
@@ -107,8 +107,8 @@
107 </div>
108 </div>
109 <div class="field-control">
110 - <input type="range" min="1" max="10" step="1" x-model.number="$store.settingsStore.settings.memory_recall_interval" />
111 - <span class="range-value" x-text="$store.settingsStore.settings.memory_recall_interval"></span>
110 + <input type="range" min="1" max="10" step="1" x-model.number="$store.settings.settings.memory_recall_interval" />
111 + <span class="range-value" x-text="$store.settings.settings.memory_recall_interval"></span>
112 </div>
113 </div>
114
@@ -120,7 +120,7 @@
120 </div>
121 </div>
122 <div class="field-control">
123 - <input type="number" x-model.number="$store.settingsStore.settings.memory_recall_history_len" />
123 + <input type="number" x-model.number="$store.settings.settings.memory_recall_history_len" />
124 </div>
125 </div>
126
@@ -132,8 +132,8 @@
132 </div>
133 </div>
134 <div class="field-control">
135 - <input type="range" min="0" max="1" step="0.01" x-model.number="$store.settingsStore.settings.memory_recall_similarity_threshold" />
136 - <span class="range-value" x-text="$store.settingsStore.settings.memory_recall_similarity_threshold"></span>
135 + <input type="range" min="0" max="1" step="0.01" x-model.number="$store.settings.settings.memory_recall_similarity_threshold" />
136 + <span class="range-value" x-text="$store.settings.settings.memory_recall_similarity_threshold"></span>
137 </div>
138 </div>
139
@@ -145,7 +145,7 @@
145 </div>
146 </div>
147 <div class="field-control">
148 - <input type="number" x-model.number="$store.settingsStore.settings.memory_recall_memories_max_search" />
148 + <input type="number" x-model.number="$store.settings.settings.memory_recall_memories_max_search" />
149 </div>
150 </div>
151
@@ -157,7 +157,7 @@
157 </div>
158 </div>
159 <div class="field-control">
160 - <input type="number" x-model.number="$store.settingsStore.settings.memory_recall_memories_max_result" />
160 + <input type="number" x-model.number="$store.settings.settings.memory_recall_memories_max_result" />
161 </div>
162 </div>
163
@@ -169,7 +169,7 @@
169 </div>
170 </div>
171 <div class="field-control">
172 - <input type="number" x-model.number="$store.settingsStore.settings.memory_recall_solutions_max_search" />
172 + <input type="number" x-model.number="$store.settings.settings.memory_recall_solutions_max_search" />
173 </div>
174 </div>
175
@@ -181,7 +181,7 @@
181 </div>
182 </div>
183 <div class="field-control">
184 - <input type="number" x-model.number="$store.settingsStore.settings.memory_recall_solutions_max_result" />
184 + <input type="number" x-model.number="$store.settings.settings.memory_recall_solutions_max_result" />
185 </div>
186 </div>
187
@@ -194,7 +194,7 @@
194 </div>
195 <div class="field-control">
196 <label class="toggle">
197 - <input type="checkbox" x-model="$store.settingsStore.settings.memory_memorize_enabled" />
197 + <input type="checkbox" x-model="$store.settings.settings.memory_memorize_enabled" />
198 <span class="toggler"></span>
199 </label>
200 </div>
@@ -209,7 +209,7 @@
209 </div>
210 <div class="field-control">
211 <label class="toggle">
212 - <input type="checkbox" x-model="$store.settingsStore.settings.memory_memorize_consolidation" />
212 + <input type="checkbox" x-model="$store.settings.settings.memory_memorize_consolidation" />
213 <span class="toggler"></span>
214 </label>
215 </div>
@@ -223,8 +223,8 @@
223 </div>
224 </div>
225 <div class="field-control">
226 - <input type="range" min="0" max="1" step="0.01" x-model.number="$store.settingsStore.settings.memory_memorize_replace_threshold" />
227 - <span class="range-value" x-text="$store.settingsStore.settings.memory_memorize_replace_threshold"></span>
226 + <input type="range" min="0" max="1" step="0.01" x-model.number="$store.settings.settings.memory_memorize_replace_threshold" />
227 + <span class="range-value" x-text="$store.settings.settings.memory_memorize_replace_threshold"></span>
228 </div>
229 </div>
230 </div>
webui/components/settings/agent/speech.html
+10 -10
@@ -5,7 +5,7 @@
5
6 <body>
7 <div x-data>
8 - <template x-if="$store.settingsStore.settings">
8 + <template x-if="$store.settings.settings">
9 <div>
10 <div class="section-title">Speech</div>
11 <div class="section-description">
@@ -28,9 +28,9 @@
28 <div class="field-description">Select the speech-to-text model size</div>
29 </div>
30 <div class="field-control">
31 - <select x-model="$store.settingsStore.settings.stt_model_size">
32 - <template x-for="option in $store.settingsStore.additional?.stt_models" :key="option.value">
33 - <option :value="option.value" :selected="option.value === $store.settingsStore.settings.stt_model_size" x-text="option.label"></option>
31 + <select x-model="$store.settings.settings.stt_model_size">
32 + <template x-for="option in $store.settings.additional?.stt_models" :key="option.value">
33 + <option :value="option.value" :selected="option.value === $store.settings.settings.stt_model_size" x-text="option.label"></option>
34 </template>
35 </select>
36 </div>
@@ -42,7 +42,7 @@
42 <div class="field-description">Language code (e.g. en, fr, it)</div>
43 </div>
44 <div class="field-control">
45 - <input type="text" x-model="$store.settingsStore.settings.stt_language" />
45 + <input type="text" x-model="$store.settings.settings.stt_language" />
46 </div>
47 </div>
48
@@ -52,8 +52,8 @@
52 <div class="field-description">Silence detection threshold. Lower values are more sensitive to noise.</div>
53 </div>
54 <div class="field-control">
55 - <input type="range" min="0" max="1" step="0.01" x-model.number="$store.settingsStore.settings.stt_silence_threshold" />
56 - <span class="range-value" x-text="$store.settingsStore.settings.stt_silence_threshold"></span>
55 + <input type="range" min="0" max="1" step="0.01" x-model.number="$store.settings.settings.stt_silence_threshold" />
56 + <span class="range-value" x-text="$store.settings.settings.stt_silence_threshold"></span>
57 </div>
58 </div>
59
@@ -63,7 +63,7 @@
63 <div class="field-description">Duration of silence before the system considers speaking to have ended.</div>
64 </div>
65 <div class="field-control">
66 - <input type="number" x-model.number="$store.settingsStore.settings.stt_silence_duration" />
66 + <input type="number" x-model.number="$store.settings.settings.stt_silence_duration" />
67 </div>
68 </div>
69
@@ -73,7 +73,7 @@
73 <div class="field-description">Duration of silence before the system closes the microphone.</div>
74 </div>
75 <div class="field-control">
76 - <input type="number" x-model.number="$store.settingsStore.settings.stt_waiting_timeout" />
76 + <input type="number" x-model.number="$store.settings.settings.stt_waiting_timeout" />
77 </div>
78 </div>
79
@@ -86,7 +86,7 @@
86 </div>
87 <div class="field-control">
88 <label class="toggle">
89 - <input type="checkbox" x-model="$store.settingsStore.settings.tts_kokoro" />
89 + <input type="checkbox" x-model="$store.settings.settings.tts_kokoro" />
90 <span class="toggler"></span>
91 </label>
92 </div>
webui/components/settings/agent/util_model.html
+24 -10
@@ -5,7 +5,7 @@
5
6 <body>
7 <div x-data>
8 - <template x-if="$store.settingsStore.settings">
8 + <template x-if="$store.settings.settings">
9 <div>
10 <div class="section-title">Utility model</div>
11 <div class="section-description">
@@ -18,9 +18,9 @@
18 <div class="field-description">Select provider for utility model used by the framework</div>
19 </div>
20 <div class="field-control">
21 - <select x-model="$store.settingsStore.settings.util_model_provider">
22 - <template x-for="option in $store.settingsStore.additional?.chat_providers" :key="option.value">
23 - <option :value="option.value" :selected="option.value === $store.settingsStore.settings.util_model_provider" x-text="option.label"></option>
21 + <select x-model="$store.settings.settings.util_model_provider">
22 + <template x-for="option in $store.settings.additional?.chat_providers" :key="option.value">
23 + <option :value="option.value" :selected="option.value === $store.settings.settings.util_model_provider" x-text="option.label"></option>
24 </template>
25 </select>
26 </div>
@@ -32,7 +32,21 @@
32 <div class="field-description">Exact name of model from selected provider</div>
33 </div>
34 <div class="field-control">
35 - <input type="text" x-model="$store.settingsStore.settings.util_model_name" />
35 + <input type="text" x-model="$store.settings.settings.util_model_name" />
36 + </div>
37 + </div>
38 +
39 + <div class="field">
40 + <div class="field-label">
41 + <div class="field-title">API key</div>
42 + <div class="field-description">API key for the selected utility model provider</div>
43 + </div>
44 + <div class="field-control">
45 + <input
46 + type="text"
47 + x-model="$store.settings.settings.api_keys[$store.settings.settings.util_model_provider]"
48 + autocomplete="off"
49 + />
50 </div>
51 </div>
52
@@ -44,7 +58,7 @@
58 </div>
59 </div>
60 <div class="field-control">
47 - <input type="text" x-model="$store.settingsStore.settings.util_model_api_base" />
61 + <input type="text" x-model="$store.settings.settings.util_model_api_base" />
62 </div>
63 </div>
64
@@ -56,7 +70,7 @@
70 </div>
71 </div>
72 <div class="field-control">
59 - <input type="number" x-model.number="$store.settingsStore.settings.util_model_rl_requests" />
73 + <input type="number" x-model.number="$store.settings.settings.util_model_rl_requests" />
74 </div>
75 </div>
76
@@ -68,7 +82,7 @@
82 </div>
83 </div>
84 <div class="field-control">
71 - <input type="number" x-model.number="$store.settingsStore.settings.util_model_rl_input" />
85 + <input type="number" x-model.number="$store.settings.settings.util_model_rl_input" />
86 </div>
87 </div>
88
@@ -80,7 +94,7 @@
94 </div>
95 </div>
96 <div class="field-control">
83 - <input type="number" x-model.number="$store.settingsStore.settings.util_model_rl_output" />
97 + <input type="number" x-model.number="$store.settings.settings.util_model_rl_output" />
98 </div>
99 </div>
100
@@ -92,7 +106,7 @@
106 </div>
107 </div>
108 <div class="field-control">
95 - <textarea x-model="$store.settingsStore.settings.util_model_kwargs"></textarea>
109 + <textarea x-model="$store.settings.settings.util_model_kwargs"></textarea>
110 </div>
111 </div>
112 </div>
webui/components/settings/backup/backup-settings.html
+1 -1
@@ -5,7 +5,7 @@
5
6 <body>
7 <div x-data>
8 - <template x-if="$store.settingsStore">
8 + <template x-if="$store.settings">
9 <div>
10 <nav>
11 <ul>
webui/components/settings/backup/backup_restore.html
+2 -2
@@ -21,7 +21,7 @@
21 <div class="field-control">
22 <button
23 class="btn btn-field"
24 - @click="$store.settingsStore.handleFieldButton({ id: 'backup_create' })"
24 + @click="$store.settings.handleFieldButton({ id: 'backup_create' })"
25 >
26 Create Backup
27 </button>
@@ -38,7 +38,7 @@
38 <div class="field-control">
39 <button
40 class="btn btn-field"
41 - @click="$store.settingsStore.handleFieldButton({ id: 'backup_restore' })"
41 + @click="$store.settings.handleFieldButton({ id: 'backup_restore' })"
42 >
43 Restore Backup
44 </button>
webui/components/settings/developer/dev.html
+16 -16
@@ -5,7 +5,7 @@
5
6 <body>
7 <div x-data>
8 - <template x-if="$store.settingsStore.settings">
8 + <template x-if="$store.settings.settings">
9 <div>
10 <div class="section-title">Development</div>
11 <div class="section-description">
@@ -20,15 +20,15 @@
20 </div>
21 </div>
22 <div class="field-control">
23 - <select x-model="$store.settingsStore.settings.shell_interface">
24 - <template x-for="option in $store.settingsStore.additional?.shell_interfaces" :key="option.value">
25 - <option :value="option.value" :selected="option.value === $store.settingsStore.settings.shell_interface" x-text="option.label"></option>
23 + <select x-model="$store.settings.settings.shell_interface">
24 + <template x-for="option in $store.settings.additional?.shell_interfaces" :key="option.value">
25 + <option :value="option.value" :selected="option.value === $store.settings.settings.shell_interface" x-text="option.label"></option>
26 </template>
27 </select>
28 </div>
29 </div>
30
31 - <template x-if="!$store.settingsStore.additional?.is_dockerized">
31 + <template x-if="!$store.settings.additional?.is_dockerized">
32 <div>
33 <div class="field">
34 <div class="field-label">
@@ -38,7 +38,7 @@
38 </div>
39 </div>
40 <div class="field-control">
41 - <input type="text" x-model="$store.settingsStore.settings.rfc_url" />
41 + <input type="text" x-model="$store.settings.settings.rfc_url" />
42 </div>
43 </div>
44 </div>
@@ -52,11 +52,11 @@
52 </div>
53 </div>
54 <div class="field-control">
55 - <input type="password" autocomplete="off" x-model="$store.settingsStore.settings.rfc_password" />
55 + <input type="password" autocomplete="off" x-model="$store.settings.settings.rfc_password" />
56 </div>
57 </div>
58
59 - <template x-if="!$store.settingsStore.additional?.is_dockerized">
59 + <template x-if="!$store.settings.additional?.is_dockerized">
60 <div>
61 <div class="field">
62 <div class="field-label">
@@ -64,7 +64,7 @@
64 <div class="field-description">HTTP port for dockerized instance of A0.</div>
65 </div>
66 <div class="field-control">
67 - <input type="number" x-model.number="$store.settingsStore.settings.rfc_port_http" />
67 + <input type="number" x-model.number="$store.settings.settings.rfc_port_http" />
68 </div>
69 </div>
70
@@ -74,7 +74,7 @@
74 <div class="field-description">SSH port for dockerized instance of A0.</div>
75 </div>
76 <div class="field-control">
77 - <input type="number" x-model.number="$store.settingsStore.settings.rfc_port_ssh" />
77 + <input type="number" x-model.number="$store.settings.settings.rfc_port_ssh" />
78 </div>
79 </div>
80 </div>
@@ -89,7 +89,7 @@
89 </div>
90 <div class="field-control">
91 <label class="toggle">
92 - <input type="checkbox" x-model="$store.settingsStore.settings.websocket_server_restart_enabled" />
92 + <input type="checkbox" x-model="$store.settings.settings.websocket_server_restart_enabled" />
93 <span class="toggler"></span>
94 </label>
95 </div>
@@ -102,9 +102,9 @@
102 Temporarily enable uvicorn access logs for debugging WebSocket transport issues (default off).
103 </div>
104 <template
105 - x-if="$store.settingsStore.additional?.runtime_settings &&
106 - $store.settingsStore.settings?.uvicorn_access_logs_enabled !==
107 - $store.settingsStore.additional.runtime_settings.uvicorn_access_logs_enabled"
105 + x-if="$store.settings.additional?.runtime_settings &&
106 + $store.settings.settings?.uvicorn_access_logs_enabled !==
107 + $store.settings.additional.runtime_settings.uvicorn_access_logs_enabled"
108 >
109 <div class="field-description">
110 Applies after backend restart.
@@ -113,13 +113,13 @@
113 </div>
114 <div class="field-control">
115 <label class="toggle">
116 - <input type="checkbox" x-model="$store.settingsStore.settings.uvicorn_access_logs_enabled" />
116 + <input type="checkbox" x-model="$store.settings.settings.uvicorn_access_logs_enabled" />
117 <span class="toggler"></span>
118 </label>
119 </div>
120 </div>
121
122 - <template x-if="!$store.settingsStore.additional?.is_dockerized">
122 + <template x-if="!$store.settings.additional?.is_dockerized">
123 <div>
124 <div class="section-title">Testing</div>
125 <div class="section-description">
webui/components/settings/developer/developer-settings.html
+1 -1
@@ -5,7 +5,7 @@
5
6 <body>
7 <div x-data>
8 - <template x-if="$store.settingsStore">
8 + <template x-if="$store.settings">
9 <div>
10 <nav>
11 <ul>
webui/components/settings/external/api_keys.html
+3 -3
@@ -5,7 +5,7 @@
5
6 <body>
7 <div x-data>
8 - <template x-if="$store.settingsStore.settings">
8 + <template x-if="$store.settings.settings">
9 <div>
10 <div class="section-title">API Keys</div>
11 <div class="section-description">
@@ -13,7 +13,7 @@
13 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>.
14 </div>
15
16 - <template x-for="provider in $store.settingsStore.apiKeyProviders" :key="provider.value">
16 + <template x-for="provider in $store.settings.apiKeyProviders" :key="provider.value">
17 <div class="field">
18 <div class="field-label">
19 <div class="field-title" x-text="provider.label"></div>
@@ -21,7 +21,7 @@
21 <div class="field-control">
22 <input
23 type="text"
24 - x-model="$store.settingsStore.settings.api_keys[provider.value]"
24 + x-model="$store.settings.settings.api_keys[provider.value]"
25 autocomplete="off"
26 />
27 </div>
webui/components/settings/external/auth.html
+2 -2
@@ -6,8 +6,8 @@
6 <body>
7 <div
8 x-data="{
9 - get settings() { return $store.settingsStore.settings },
10 - get additional() { return $store.settingsStore.additional || {} }
9 + get settings() { return $store.settings.settings },
10 + get additional() { return $store.settings.additional || {} }
11 }"
12 >
13 <template x-if="settings">
webui/components/settings/external/external-settings.html
+1 -1
@@ -5,7 +5,7 @@
5
6 <body>
7 <div x-data>
8 - <template x-if="$store.settingsStore">
8 + <template x-if="$store.settings">
9 <div>
10 <nav>
11 <ul>
webui/components/settings/external/external_api.html
+1 -1
@@ -21,7 +21,7 @@
21 <div class="field-control">
22 <button
23 class="btn btn-field"
24 - @click="$store.settingsStore.handleFieldButton({ id: 'external_api_examples' })"
24 + @click="$store.settings.handleFieldButton({ id: 'external_api_examples' })"
25 >
26 Show API Examples
27 </button>
webui/components/settings/external/litellm.html
+1 -1
@@ -4,7 +4,7 @@
4 </head>
5
6 <body>
7 - <div x-data="{ get settings() { return $store.settingsStore.settings } }">
7 + <div x-data="{ get settings() { return $store.settings.settings } }">
8 <template x-if="settings">
9 <div>
10 <div class="section-title">LiteLLM Global Settings</div>
webui/components/settings/external/secrets.html
+1 -1
@@ -4,7 +4,7 @@
4 </head>
5
6 <body>
7 - <div x-data="{ get settings() { return $store.settingsStore.settings } }">
7 + <div x-data="{ get settings() { return $store.settings.settings } }">
8 <template x-if="settings">
9 <div>
10 <div class="section-title">Secrets Management</div>
webui/components/settings/external/update_checker.html
+1 -1
@@ -4,7 +4,7 @@
4 </head>
5
6 <body>
7 - <div x-data="{ get settings() { return $store.settingsStore.settings } }">
7 + <div x-data="{ get settings() { return $store.settings.settings } }">
8 <template x-if="settings">
9 <div>
10 <div class="section-title">Update Checker</div>
webui/components/settings/mcp/mcp-settings.html
+1 -1
@@ -5,7 +5,7 @@
5
6 <body>
7 <div x-data>
8 - <template x-if="$store.settingsStore">
8 + <template x-if="$store.settings">
9 <div>
10 <nav>
11 <ul>
webui/components/settings/mcp/mcp_client.html
+2 -2
@@ -4,7 +4,7 @@
4 </head>
5
6 <body>
7 - <div x-data="{ get settings() { return $store.settingsStore.settings } }">
7 + <div x-data="{ get settings() { return $store.settings.settings } }">
8 <template x-if="settings">
9 <div>
10 <div class="section-title">External MCP Servers</div>
@@ -20,7 +20,7 @@
20 <div class="field-control">
21 <button
22 class="btn btn-field"
23 - @click="$store.settingsStore.handleFieldButton({ id: 'mcp_servers_config' })"
23 + @click="$store.settings.handleFieldButton({ id: 'mcp_servers_config' })"
24 >
25 Open
26 </button>
webui/components/settings/mcp/mcp_server.html
+1 -1
@@ -4,7 +4,7 @@
4 </head>
5
6 <body>
7 - <div x-data="{ get settings() { return $store.settingsStore.settings } }">
7 + <div x-data="{ get settings() { return $store.settings.settings } }">
8 <template x-if="settings">
9 <div>
10 <div class="section-title">A0 MCP Server</div>
webui/components/settings/mcp/server/example.html
+2 -2
@@ -12,7 +12,7 @@
12
13 <!-- API Token Information -->
14 <div x-data>
15 - <template x-if="$store.settingsStore.settings">
15 + <template x-if="$store.settings.settings">
16 <div style="background-color: var(--color-bg-secondary); border: 1px solid var(--color-border); border-radius: 6px; padding: 12px; margin: 16px 0;">
17 <h4 style="margin: 0 0 8px 0; color: var(--color-text-primary);">API Token Information</h4>
18 <p style="margin: 0 0 8px 0; color: var(--color-text-secondary); font-size: 14px;">
@@ -21,7 +21,7 @@
21 </p>
22 <div style="margin-top: 8px;">
23 <label style="display: block; margin-bottom: 4px; color: var(--color-text-secondary); font-size: 12px; font-weight: 600;">Token:</label>
24 - <input type="text" readonly x-model="$store.settingsStore.settings.mcp_server_token" style="width: 100%; padding: 6px 8px; background-color: var(--color-bg-primary); color: var(--color-text-primary); border: 1px solid var(--color-border); border-radius: 4px; font-family: monospace; font-size: 13px;" />
24 + <input type="text" readonly x-model="$store.settings.settings.mcp_server_token" style="width: 100%; padding: 6px 8px; background-color: var(--color-bg-primary); color: var(--color-text-primary); border: 1px solid var(--color-border); border-radius: 4px; font-family: monospace; font-size: 13px;" />
25 </div>
26 </div>
27 </template>
webui/components/settings/settings-store.js
+1 -1
@@ -168,7 +168,7 @@ const model = {
168 },
169 };
170
171 -const store = createStore("settingsStore", model);
171 +const store = createStore("settings", model);
172
173 export { store };
174
webui/components/settings/settings.html
+29 -29
@@ -9,86 +9,86 @@
9 </script>
10
11 <div x-data>
12 - <template x-if="$store.settingsStore">
13 - <div x-init="$store.settingsStore.onOpen()" x-destroy="$store.settingsStore.cleanup()">
12 + <template x-if="$store.settings">
13 + <div x-init="$store.settings.onOpen()" x-destroy="$store.settings.cleanup()">
14
15 <!-- Loading state -->
16 - <div x-show="$store.settingsStore.isLoading && !$store.settingsStore.settings" class="settings-loading">
16 + <div x-show="$store.settings.isLoading && !$store.settings.settings" class="settings-loading">
17 <span class="material-symbols-outlined spinning">progress_activity</span>
18 <span>Loading settings...</span>
19 </div>
20
21 <!-- Error state -->
22 - <div x-show="$store.settingsStore.error && !$store.settingsStore.settings" class="settings-error">
22 + <div x-show="$store.settings.error && !$store.settings.settings" class="settings-error">
23 <span class="material-symbols-outlined">error</span>
24 - <span x-text="$store.settingsStore.error"></span>
25 - <button class="btn btn-retry" @click="$store.settingsStore.onOpen()">Retry</button>
24 + <span x-text="$store.settings.error"></span>
25 + <button class="btn btn-retry" @click="$store.settings.onOpen()">Retry</button>
26 </div>
27
28 <!-- Settings content -->
29 - <div x-show="$store.settingsStore.settings" class="settings-content">
29 + <div x-show="$store.settings.settings" class="settings-content">
30 <!-- Tab Navigation -->
31 <div class="settings-tabs-container">
32 <div class="settings-tabs no-scrollbar">
33 <div class="settings-tab"
34 - :class="{'active': $store.settingsStore.activeTab === 'agent'}"
35 - @click="$store.settingsStore.switchTab('agent')"
34 + :class="{'active': $store.settings.activeTab === 'agent'}"
35 + @click="$store.settings.switchTab('agent')"
36 title="Agent Settings">Agent Settings</div>
37 <div class="settings-tab"
38 - :class="{'active': $store.settingsStore.activeTab === 'skills'}"
39 - @click="$store.settingsStore.switchTab('skills')"
38 + :class="{'active': $store.settings.activeTab === 'skills'}"
39 + @click="$store.settings.switchTab('skills')"
40 title="Skills">Skills</div>
41 <div class="settings-tab"
42 - :class="{'active': $store.settingsStore.activeTab === 'external'}"
43 - @click="$store.settingsStore.switchTab('external')"
42 + :class="{'active': $store.settings.activeTab === 'external'}"
43 + @click="$store.settings.switchTab('external')"
44 title="External Services">External Services</div>
45 <div class="settings-tab"
46 - :class="{'active': $store.settingsStore.activeTab === 'mcp'}"
47 - @click="$store.settingsStore.switchTab('mcp')"
46 + :class="{'active': $store.settings.activeTab === 'mcp'}"
47 + @click="$store.settings.switchTab('mcp')"
48 title="MCP">MCP/A2A</div>
49 <div class="settings-tab"
50 - :class="{'active': $store.settingsStore.activeTab === 'developer'}"
51 - @click="$store.settingsStore.switchTab('developer')"
50 + :class="{'active': $store.settings.activeTab === 'developer'}"
51 + @click="$store.settings.switchTab('developer')"
52 title="Developer">Developer</div>
53 <div class="settings-tab"
54 - :class="{'active': $store.settingsStore.activeTab === 'backup'}"
55 - @click="$store.settingsStore.switchTab('backup')"
54 + :class="{'active': $store.settings.activeTab === 'backup'}"
55 + @click="$store.settings.switchTab('backup')"
56 title="Backup & Restore">Backup & Restore</div>
57 </div>
58 </div>
59
60 <!-- Settings sections for agent, external, developer, mcp, backup tabs -->
61 <div id="settings-sections">
62 - <div x-show="$store.settingsStore.activeTab === 'agent'">
62 + <div x-show="$store.settings.activeTab === 'agent'">
63 <x-component path="settings/agent/agent-settings.html"></x-component>
64 </div>
65 - <div x-show="$store.settingsStore.activeTab === 'external'">
65 + <div x-show="$store.settings.activeTab === 'external'">
66 <x-component path="settings/external/external-settings.html"></x-component>
67 </div>
68 - <div x-show="$store.settingsStore.activeTab === 'mcp'">
68 + <div x-show="$store.settings.activeTab === 'mcp'">
69 <x-component path="settings/mcp/mcp-settings.html"></x-component>
70 </div>
71 - <div x-show="$store.settingsStore.activeTab === 'developer'">
71 + <div x-show="$store.settings.activeTab === 'developer'">
72 <x-component path="settings/developer/developer-settings.html"></x-component>
73 </div>
74 - <div x-show="$store.settingsStore.activeTab === 'backup'">
74 + <div x-show="$store.settings.activeTab === 'backup'">
75 <x-component path="settings/backup/backup-settings.html"></x-component>
76 </div>
77 - <div x-show="$store.settingsStore.activeTab === 'skills'">
77 + <div x-show="$store.settings.activeTab === 'skills'">
78 <x-component path="settings/skills/skills-settings.html"></x-component>
79 </div>
80 </div>
81 </div>
82
83 <!-- Footer -->
84 - <div class="modal-footer" data-modal-footer x-show="$store.settingsStore.settings">
84 + <div class="modal-footer" data-modal-footer x-show="$store.settings.settings">
85 <button class="btn btn-ok"
86 - @click="$store.settingsStore.saveAndClose()"
87 - :disabled="$store.settingsStore?.isLoading">
86 + @click="$store.settings.saveAndClose()"
87 + :disabled="$store.settings?.isLoading">
88 Save
89 </button>
90 <button class="btn btn-cancel"
91 - @click="$store.settingsStore.closeSettings()">
91 + @click="$store.settings.closeSettings()">
92 Cancel
93 </button>
94 </div>
webui/components/settings/skills/skills-settings.html
+1 -1
@@ -5,7 +5,7 @@
5
6 <body>
7 <div x-data>
8 - <template x-if="$store.settingsStore">
8 + <template x-if="$store.settings">
9 <div>
10 <nav>
11 <ul>
webui/components/sidebar/chats/chats-store.js
+24
@@ -1,4 +1,5 @@
1 import { createStore } from "/js/AlpineStore.js";
2 +import { callJsonApi } from "/js/api.js";
3 import {
4 sendJsonData,
5 getContext,
@@ -16,6 +17,7 @@ const model = {
17 contexts: [],
18 selected: "",
19 selectedContext: null,
20 + loggedIn: false,
21
22 // for convenience
23 getSelectedChatId() {
@@ -27,6 +29,7 @@ const model = {
29 },
30
31 init() {
32 + this.loggedIn = Boolean(window.runtimeInfo && window.runtimeInfo.loggedIn);
33 // Initialize from sessionStorage
34 const lastSelectedChat = sessionStorage.getItem("lastSelectedChat");
35 if (lastSelectedChat) {
@@ -336,6 +339,27 @@ const model = {
339 } catch (_e) {
340 // ignore
341 }
342 + },
343 +
344 + async logout() {
345 + try {
346 + await callJsonApi("/logout", {});
347 + } catch (_e) {
348 + // ignore
349 + }
350 +
351 + try {
352 + sessionStorage.removeItem("lastSelectedChat");
353 + sessionStorage.removeItem("lastSelectedTask");
354 + } catch (_e) {
355 + // ignore
356 + }
357 +
358 + try {
359 + window.location.reload();
360 + } catch (_e) {
361 + // ignore
362 + }
363 }
364 };
365
webui/components/sidebar/top-section/quick-actions.html
+5
@@ -94,6 +94,11 @@
94
95 <div class="dropdown-separator"></div>
96
97 + <button class="dropdown-item" @click="$confirmClick($event, () => { $store.chats.logout(); dropdownOpen = false })" :disabled="!$store.chats.loggedIn">
98 + <span class="material-symbols-outlined">logout</span>
99 + <span>Logout</span>
100 + </button>
101 +
102 <button class="dropdown-item" @click="$confirmClick($event, () => { $store.chats.restart(); dropdownOpen = false })">
103 <span class="material-symbols-outlined">restart_alt</span>
104 <span>Restart A0</span>
webui/index.html
+2 -1
@@ -67,7 +67,8 @@
67 globalThis.runtimeInfo = {
68 ...(globalThis.runtimeInfo || {}),
69 id: "{{runtime_id}}",
70 - isDevelopment: {{runtime_is_development}},
70 + isDevelopment: "{{runtime_is_development}}" === "true",
71 + loggedIn: "{{logged_in}}" === "true",
72 };
73 </script>
74 </head>