refactor memory to standalone config and unify plugin UI

Alessandro committed Feb 20, 2026 at 09:10 UTC 803248168ce53e9f2d0ac97026e274ad2d06e5c7
13 files changed +391 -330
plugins/example_agent/webui/config.html deleted
-14
@@ -1,14 +0,0 @@
1 -<!DOCTYPE html>
2 -<html lang="en">
3 -<head>
4 - <meta charset="UTF-8">
5 - <meta name="viewport" content="width=device-width, initial-scale=1.0">
6 - <title>Example Agent Configuration</title>
7 -</head>
8 -<body>
9 - <div class="container">
10 - <h1>Example Agent Plugin Configuration</h1>
11 - <p>This is a dummy configuration page for the example agent plugin.</p>
12 - </div>
13 -</body>
14 -</html>
plugins/memory/config.json new
+17
@@ -0,0 +1,17 @@
1 +{
2 + "memory_recall_enabled": true,
3 + "memory_recall_delayed": false,
4 + "memory_recall_interval": 3,
5 + "memory_recall_history_len": 10000,
6 + "memory_recall_memories_max_search": 12,
7 + "memory_recall_solutions_max_search": 8,
8 + "memory_recall_memories_max_result": 5,
9 + "memory_recall_solutions_max_result": 3,
10 + "memory_recall_similarity_threshold": 0.7,
11 + "memory_recall_query_prep": false,
12 + "memory_recall_post_filter": false,
13 + "memory_memorize_enabled": true,
14 + "memory_memorize_consolidation": true,
15 + "memory_memorize_replace_threshold": 0.9,
16 + "agent_memory_subdir": "default"
17 +}
plugins/memory/extensions/python/message_loop_prompts_after/_50_recall_memories.py
+3 -3
@@ -1,7 +1,7 @@
1 import asyncio
2 from python.helpers.extension import Extension
3 from agent import LoopData
4 -from python.helpers import dirty_json, errors, settings, log
4 +from python.helpers import dirty_json, errors, log, plugins
5
6 # Direct import - this extension lives inside the memory plugin
7 from plugins.memory.helpers.memory import Memory
@@ -25,7 +25,7 @@ class RecallMemories(Extension):
25
26 async def execute(self, loop_data: LoopData = LoopData(), **kwargs):
27
28 - set = settings.get_settings()
28 + set = plugins.get_plugin_config("memory")
29
30 # turned off in settings?
31 if not set["memory_recall_enabled"]:
@@ -63,7 +63,7 @@ class RecallMemories(Extension):
63 del extras["solutions"]
64
65
66 - set = settings.get_settings()
66 + set = plugins.get_plugin_config("memory")
67 # try:
68
69 # get system message and chat history for util llm
plugins/memory/extensions/python/message_loop_prompts_after/_91_recall_wait.py
+2 -2
@@ -1,12 +1,12 @@
1 from python.helpers.extension import Extension
2 from agent import LoopData
3 from plugins.memory.extensions.python.message_loop_prompts_after._50_recall_memories import DATA_NAME_TASK as DATA_NAME_TASK_MEMORIES, DATA_NAME_ITER as DATA_NAME_ITER_MEMORIES
4 -from python.helpers import settings
4 +from python.helpers import plugins
5
6 class RecallWait(Extension):
7 async def execute(self, loop_data: LoopData = LoopData(), **kwargs):
8
9 - set = settings.get_settings()
9 + set = plugins.get_plugin_config("memory")
10
11 task = self.agent.get_data(DATA_NAME_TASK_MEMORIES)
12 iter = self.agent.get_data(DATA_NAME_ITER_MEMORIES) or 0
plugins/memory/extensions/python/monologue_end/_50_memorize_fragments.py
+3 -3
@@ -1,5 +1,5 @@
1 import asyncio
2 -from python.helpers import settings, errors
2 +from python.helpers import errors, plugins
3 from python.helpers.extension import Extension
4 from python.helpers.dirty_json import DirtyJson
5 from agent import LoopData
@@ -16,7 +16,7 @@ class MemorizeMemories(Extension):
16 async def execute(self, loop_data: LoopData = LoopData(), **kwargs):
17 # try:
18
19 - set = settings.get_settings()
19 + set = plugins.get_plugin_config("memory")
20
21 if not set["memory_memorize_enabled"]:
22 return
@@ -36,7 +36,7 @@ class MemorizeMemories(Extension):
36 async def memorize(self, loop_data: LoopData, log_item: LogItem, **kwargs):
37
38 try:
39 - set = settings.get_settings()
39 + set = plugins.get_plugin_config("memory")
40
41 db = await Memory.get(self.agent)
42
plugins/memory/extensions/python/monologue_end/_51_memorize_solutions.py
+3 -3
@@ -1,5 +1,5 @@
1 import asyncio
2 -from python.helpers import settings, errors
2 +from python.helpers import errors, plugins
3 from python.helpers.extension import Extension
4 from python.helpers.dirty_json import DirtyJson
5 from agent import LoopData
@@ -15,7 +15,7 @@ class MemorizeSolutions(Extension):
15 async def execute(self, loop_data: LoopData = LoopData(), **kwargs):
16 # try:
17
18 - set = settings.get_settings()
18 + set = plugins.get_plugin_config("memory")
19
20 if not set["memory_memorize_enabled"]:
21 return
@@ -34,7 +34,7 @@ class MemorizeSolutions(Extension):
34
35 async def memorize(self, loop_data: LoopData, log_item: LogItem, **kwargs):
36 try:
37 - set = settings.get_settings()
37 + set = plugins.get_plugin_config("memory")
38
39 db = await Memory.get(self.agent)
40
plugins/memory/helpers/memory.py
+2 -2
@@ -23,7 +23,7 @@ import os, json
23 import numpy as np
24
25 from python.helpers.print_style import PrintStyle
26 -from python.helpers import files
26 +from python.helpers import files, plugins
27 from langchain_core.documents import Document
28 from . import knowledge_import
29 from python.helpers.log import Log, LogItem
@@ -530,7 +530,7 @@ def get_context_memory_subdir(context: AgentContext) -> str:
530 return memory_subdir
531
532 # no project, regular memory subdir
533 - return context.config.memory_subdir or "default"
533 + return plugins.get_plugin_config("memory").get("agent_memory_subdir", "default")
534
535
536 def get_existing_memory_subdirs() -> list[str]:
plugins/memory/webui/config.html
+251 -28
@@ -1,35 +1,258 @@
1 <html>
2 <head>
3 - <title>Memory Settings</title>
4 - <script type="module">
5 - import { store } from "/components/settings/settings-store.js";
6 - </script>
3 + <title>Memory</title>
4 </head>
5 +
6 <body>
9 - <!--
10 - This file surfaces the existing core memory settings inside the plugin settings modal.
11 - It sets saveMode='core' so the modal's Save button delegates to $store.settings.saveSettings().
12 - -->
13 - <div x-data
14 - x-init="
15 - $store.pluginSettings.saveMode = 'core';
16 - if ($store.settings && !$store.settings.settings) $store.settings.onOpen();
17 - ">
18 - <x-component path="settings/agent/memory.html"></x-component>
19 - </div>
20 -</body>
21 -</html>
22 -<!DOCTYPE html>
23 -<html lang="en">
24 -<head>
25 - <meta charset="UTF-8">
26 - <meta name="viewport" content="width=device-width, initial-scale=1.0">
27 - <title>Memory Configuration</title>
28 -</head>
29 -<body>
30 - <div class="container">
31 - <h1>Memory Plugin Configuration</h1>
32 - <p>This is a dummy configuration page for the memory plugin.</p>
7 + <div x-data>
8 + <template x-if="$store.pluginSettings.settings">
9 + <div>
10 + <div class="section-title">Memory</div>
11 + <div class="section-description">
12 + Configuration of A0's memory system. A0 memorizes and recalls memories automatically to help its
13 + context awareness.
14 + </div>
15 +
16 + <div class="field">
17 + <div class="field-label">
18 + <div class="field-title">Memory Subdirectory</div>
19 + <div class="field-description">
20 + Subdirectory of /memory folder to use for agent memory storage. Used to separate memory
21 + storage between different instances.
22 + </div>
23 + </div>
24 + <div class="field-control">
25 + <input type="text" x-model="$store.pluginSettings.settings.agent_memory_subdir" />
26 + </div>
27 + </div>
28 +
29 + <div class="field">
30 + <div class="field-label">
31 + <div class="field-title">Memory Dashboard</div>
32 + <div class="field-description">
33 + View and explore all stored memories in a table format with filtering and search
34 + capabilities.
35 + </div>
36 + </div>
37 + <div class="field-control">
38 + <button class="btn btn-field"
39 + @click="openModal('/plugins/memory/webui/memory-dashboard.html');">
40 + Open Dashboard
41 + </button>
42 + </div>
43 + </div>
44 +
45 + <div class="field">
46 + <div class="field-label">
47 + <div class="field-title">Memory auto-recall enabled</div>
48 + <div class="field-description">Agent Zero will automatically recall memories based on
49 + convesation context.</div>
50 + </div>
51 + <div class="field-control">
52 + <label class="toggle">
53 + <input type="checkbox" x-model="$store.pluginSettings.settings.memory_recall_enabled" />
54 + <span class="toggler"></span>
55 + </label>
56 + </div>
57 + </div>
58 +
59 + <div class="field">
60 + <div class="field-label">
61 + <div class="field-title">Memory auto-recall delayed</div>
62 + <div class="field-description">
63 + The agent will not wait for auto memory recall. Memories will be delivered one message
64 + later. This speeds up agent's response time but may result in less relevant first step.
65 + </div>
66 + </div>
67 + <div class="field-control">
68 + <label class="toggle">
69 + <input type="checkbox" x-model="$store.pluginSettings.settings.memory_recall_delayed" />
70 + <span class="toggler"></span>
71 + </label>
72 + </div>
73 + </div>
74 +
75 + <div class="field">
76 + <div class="field-label">
77 + <div class="field-title">Auto-recall AI query preparation</div>
78 + <div class="field-description">
79 + Enables vector DB query preparation from conversation context by utility LLM for
80 + auto-recall. Improves search quality, adds 1 utility LLM call per auto-recall.
81 + </div>
82 + </div>
83 + <div class="field-control">
84 + <label class="toggle">
85 + <input type="checkbox" x-model="$store.pluginSettings.settings.memory_recall_query_prep" />
86 + <span class="toggler"></span>
87 + </label>
88 + </div>
89 + </div>
90 +
91 + <div class="field">
92 + <div class="field-label">
93 + <div class="field-title">Auto-recall AI post-filtering</div>
94 + <div class="field-description">
95 + Enables memory relevance filtering by utility LLM for auto-recall. Improves search quality,
96 + adds 1 utility LLM call per auto-recall.
97 + </div>
98 + </div>
99 + <div class="field-control">
100 + <label class="toggle">
101 + <input type="checkbox"
102 + x-model="$store.pluginSettings.settings.memory_recall_post_filter" />
103 + <span class="toggler"></span>
104 + </label>
105 + </div>
106 + </div>
107 +
108 + <div class="field">
109 + <div class="field-label">
110 + <div class="field-title">Memory auto-recall interval</div>
111 + <div class="field-description">
112 + Memories are recalled after every user or superior agent message. During agent's monologue,
113 + memories are recalled every X turns based on this parameter.
114 + </div>
115 + </div>
116 + <div class="field-control">
117 + <input type="range" min="1" max="10" step="1"
118 + x-model.number="$store.pluginSettings.settings.memory_recall_interval" />
119 + <span class="range-value"
120 + x-text="$store.pluginSettings.settings.memory_recall_interval"></span>
121 + </div>
122 + </div>
123 +
124 + <div class="field">
125 + <div class="field-label">
126 + <div class="field-title">Memory auto-recall history length</div>
127 + <div class="field-description">
128 + The length of conversation history passed to memory recall LLM for context (in characters).
129 + </div>
130 + </div>
131 + <div class="field-control">
132 + <input type="number"
133 + x-model.number="$store.pluginSettings.settings.memory_recall_history_len" />
134 + </div>
135 + </div>
136 +
137 + <div class="field">
138 + <div class="field-label">
139 + <div class="field-title">Memory auto-recall similarity threshold</div>
140 + <div class="field-description">
141 + The threshold for similarity search in memory recall (0 = no similarity, 1 = exact match).
142 + </div>
143 + </div>
144 + <div class="field-control">
145 + <input type="range" min="0" max="1" step="0.01"
146 + x-model.number="$store.pluginSettings.settings.memory_recall_similarity_threshold" />
147 + <span class="range-value"
148 + x-text="$store.pluginSettings.settings.memory_recall_similarity_threshold"></span>
149 + </div>
150 + </div>
151 +
152 + <div class="field">
153 + <div class="field-label">
154 + <div class="field-title">Memory auto-recall max memories to search</div>
155 + <div class="field-description">
156 + The maximum number of memories returned by vector DB for further processing.
157 + </div>
158 + </div>
159 + <div class="field-control">
160 + <input type="number"
161 + x-model.number="$store.pluginSettings.settings.memory_recall_memories_max_search" />
162 + </div>
163 + </div>
164 +
165 + <div class="field">
166 + <div class="field-label">
167 + <div class="field-title">Memory auto-recall max memories to use</div>
168 + <div class="field-description">
169 + The maximum number of memories to inject into A0's context window.
170 + </div>
171 + </div>
172 + <div class="field-control">
173 + <input type="number"
174 + x-model.number="$store.pluginSettings.settings.memory_recall_memories_max_result" />
175 + </div>
176 + </div>
177 +
178 + <div class="field">
179 + <div class="field-label">
180 + <div class="field-title">Memory auto-recall max solutions to search</div>
181 + <div class="field-description">
182 + The maximum number of solutions returned by vector DB for further processing.
183 + </div>
184 + </div>
185 + <div class="field-control">
186 + <input type="number"
187 + x-model.number="$store.pluginSettings.settings.memory_recall_solutions_max_search" />
188 + </div>
189 + </div>
190 +
191 + <div class="field">
192 + <div class="field-label">
193 + <div class="field-title">Memory auto-recall max solutions to use</div>
194 + <div class="field-description">
195 + The maximum number of solutions to inject into A0's context window.
196 + </div>
197 + </div>
198 + <div class="field-control">
199 + <input type="number"
200 + x-model.number="$store.pluginSettings.settings.memory_recall_solutions_max_result" />
201 + </div>
202 + </div>
203 +
204 + <div class="field">
205 + <div class="field-label">
206 + <div class="field-title">Auto-memorize enabled</div>
207 + <div class="field-description">
208 + A0 will automatically memorize facts and solutions from conversation history.
209 + </div>
210 + </div>
211 + <div class="field-control">
212 + <label class="toggle">
213 + <input type="checkbox"
214 + x-model="$store.pluginSettings.settings.memory_memorize_enabled" />
215 + <span class="toggler"></span>
216 + </label>
217 + </div>
218 + </div>
219 +
220 + <div class="field">
221 + <div class="field-label">
222 + <div class="field-title">Auto-memorize AI consolidation</div>
223 + <div class="field-description">
224 + A0 will automatically consolidate similar memories using utility LLM. Improves memory quality
225 + over time, adds 2 utility LLM calls per memory.
226 + </div>
227 + </div>
228 + <div class="field-control">
229 + <label class="toggle">
230 + <input type="checkbox"
231 + x-model="$store.pluginSettings.settings.memory_memorize_consolidation" />
232 + <span class="toggler"></span>
233 + </label>
234 + </div>
235 + </div>
236 +
237 + <div class="field">
238 + <div class="field-label">
239 + <div class="field-title">Auto-memorize replacement threshold</div>
240 + <div class="field-description">
241 + Only applies when AI consolidation is disabled. Replaces previous similar memories with new
242 + ones based on this threshold. 0 = replace even if not similar at all, 1 = replace only if
243 + exact match.
244 + </div>
245 + </div>
246 + <div class="field-control">
247 + <input type="range" min="0" max="1" step="0.01"
248 + x-model.number="$store.pluginSettings.settings.memory_memorize_replace_threshold" />
249 + <span class="range-value"
250 + x-text="$store.pluginSettings.settings.memory_memorize_replace_threshold"></span>
251 + </div>
252 + </div>
253 + </div>
254 + </template>
255 </div>
256 </body>
257 +
258 </html>
webui/components/plugins/list/plugin-list.html
+3 -2
@@ -113,6 +113,7 @@
113 }
114
115 .nav-link {
116 + font-family: "Rubik", Arial, Helvetica, sans-serif;
117 border: 1px solid transparent;
118 border-top-left-radius: 4px;
119 border-top-right-radius: 4px;
@@ -183,9 +184,9 @@
184 align-items: center;
185 gap: 0.5rem;
186 padding-bottom: var(--spacing-sm);
186 - flex-wrap: wrap;
187 + flex-wrap: nowrap;
188 min-width: 0;
188 - flex: 0 1 11.5rem;
189 + flex: 0 0 auto;
190 max-width: 100%;
191 justify-content: flex-end;
192 }
webui/components/plugins/plugin-info.html
+4
@@ -63,6 +63,10 @@
63 </div>
64
65 <style>
66 + .plugin-info-view {
67 + padding: 1rem;
68 + }
69 +
70 .plugin-info-header {
71 display: flex;
72 flex-wrap: wrap;
webui/components/plugins/plugin-settings.html
+2 -2
@@ -76,8 +76,8 @@
76 </div>
77
78 <style>
79 - .plugin-settings-toolbar {
80 - margin-bottom: 1rem;
79 + .plugin-settings-toolbar, .plugin-settings-body {
80 + padding: 1rem;
81 }
82
83 .plugin-settings-toolbar-row {
webui/components/settings/agent/memory.html deleted
-234
@@ -1,234 +0,0 @@
1 -<html>
2 - <head>
3 - <title>Memory</title>
4 - </head>
5 -
6 - <body>
7 - <div x-data>
8 - <template x-if="$store.settings.settings">
9 - <div>
10 - <div class="section-title">Memory</div>
11 - <div class="section-description">
12 - Configuration of A0's memory system. A0 memorizes and recalls memories automatically to help its context awareness.
13 - </div>
14 -
15 - <div class="field">
16 - <div class="field-label">
17 - <div class="field-title">Memory Subdirectory</div>
18 - <div class="field-description">
19 - Subdirectory of /memory folder to use for agent memory storage. Used to separate memory storage between different instances.
20 - </div>
21 - </div>
22 - <div class="field-control">
23 - <input type="text" x-model="$store.settings.settings.agent_memory_subdir" />
24 - </div>
25 - </div>
26 -
27 - <div class="field">
28 - <div class="field-label">
29 - <div class="field-title">Memory Dashboard</div>
30 - <div class="field-description">
31 - View and explore all stored memories in a table format with filtering and search capabilities.
32 - </div>
33 - </div>
34 - <div class="field-control">
35 - <button
36 - class="btn btn-field"
37 - @click="openModal('../plugins/memory/webui/memory-dashboard.html');"
38 - >
39 - Open Dashboard
40 - </button>
41 - </div>
42 - </div>
43 -
44 - <div class="field">
45 - <div class="field-label">
46 - <div class="field-title">Memory auto-recall enabled</div>
47 - <div class="field-description">Agent Zero will automatically recall memories based on convesation context.</div>
48 - </div>
49 - <div class="field-control">
50 - <label class="toggle">
51 - <input type="checkbox" x-model="$store.settings.settings.memory_recall_enabled" />
52 - <span class="toggler"></span>
53 - </label>
54 - </div>
55 - </div>
56 -
57 - <div class="field">
58 - <div class="field-label">
59 - <div class="field-title">Memory auto-recall delayed</div>
60 - <div class="field-description">
61 - The agent will not wait for auto memory recall. Memories will be delivered one message later. This speeds up agent's response time but may result in less relevant first step.
62 - </div>
63 - </div>
64 - <div class="field-control">
65 - <label class="toggle">
66 - <input type="checkbox" x-model="$store.settings.settings.memory_recall_delayed" />
67 - <span class="toggler"></span>
68 - </label>
69 - </div>
70 - </div>
71 -
72 - <div class="field">
73 - <div class="field-label">
74 - <div class="field-title">Auto-recall AI query preparation</div>
75 - <div class="field-description">
76 - Enables vector DB query preparation from conversation context by utility LLM for auto-recall. Improves search quality, adds 1 utility LLM call per auto-recall.
77 - </div>
78 - </div>
79 - <div class="field-control">
80 - <label class="toggle">
81 - <input type="checkbox" x-model="$store.settings.settings.memory_recall_query_prep" />
82 - <span class="toggler"></span>
83 - </label>
84 - </div>
85 - </div>
86 -
87 - <div class="field">
88 - <div class="field-label">
89 - <div class="field-title">Auto-recall AI post-filtering</div>
90 - <div class="field-description">
91 - Enables memory relevance filtering by utility LLM for auto-recall. Improves search quality, adds 1 utility LLM call per auto-recall.
92 - </div>
93 - </div>
94 - <div class="field-control">
95 - <label class="toggle">
96 - <input type="checkbox" x-model="$store.settings.settings.memory_recall_post_filter" />
97 - <span class="toggler"></span>
98 - </label>
99 - </div>
100 - </div>
101 -
102 - <div class="field">
103 - <div class="field-label">
104 - <div class="field-title">Memory auto-recall interval</div>
105 - <div class="field-description">
106 - Memories are recalled after every user or superior agent message. During agent's monologue, memories are recalled every X turns based on this parameter.
107 - </div>
108 - </div>
109 - <div class="field-control">
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 -
115 - <div class="field">
116 - <div class="field-label">
117 - <div class="field-title">Memory auto-recall history length</div>
118 - <div class="field-description">
119 - The length of conversation history passed to memory recall LLM for context (in characters).
120 - </div>
121 - </div>
122 - <div class="field-control">
123 - <input type="number" x-model.number="$store.settings.settings.memory_recall_history_len" />
124 - </div>
125 - </div>
126 -
127 - <div class="field">
128 - <div class="field-label">
129 - <div class="field-title">Memory auto-recall similarity threshold</div>
130 - <div class="field-description">
131 - The threshold for similarity search in memory recall (0 = no similarity, 1 = exact match).
132 - </div>
133 - </div>
134 - <div class="field-control">
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 -
140 - <div class="field">
141 - <div class="field-label">
142 - <div class="field-title">Memory auto-recall max memories to search</div>
143 - <div class="field-description">
144 - The maximum number of memories returned by vector DB for further processing.
145 - </div>
146 - </div>
147 - <div class="field-control">
148 - <input type="number" x-model.number="$store.settings.settings.memory_recall_memories_max_search" />
149 - </div>
150 - </div>
151 -
152 - <div class="field">
153 - <div class="field-label">
154 - <div class="field-title">Memory auto-recall max memories to use</div>
155 - <div class="field-description">
156 - The maximum number of memories to inject into A0's context window.
157 - </div>
158 - </div>
159 - <div class="field-control">
160 - <input type="number" x-model.number="$store.settings.settings.memory_recall_memories_max_result" />
161 - </div>
162 - </div>
163 -
164 - <div class="field">
165 - <div class="field-label">
166 - <div class="field-title">Memory auto-recall max solutions to search</div>
167 - <div class="field-description">
168 - The maximum number of solutions returned by vector DB for further processing.
169 - </div>
170 - </div>
171 - <div class="field-control">
172 - <input type="number" x-model.number="$store.settings.settings.memory_recall_solutions_max_search" />
173 - </div>
174 - </div>
175 -
176 - <div class="field">
177 - <div class="field-label">
178 - <div class="field-title">Memory auto-recall max solutions to use</div>
179 - <div class="field-description">
180 - The maximum number of solutions to inject into A0's context window.
181 - </div>
182 - </div>
183 - <div class="field-control">
184 - <input type="number" x-model.number="$store.settings.settings.memory_recall_solutions_max_result" />
185 - </div>
186 - </div>
187 -
188 - <div class="field">
189 - <div class="field-label">
190 - <div class="field-title">Auto-memorize enabled</div>
191 - <div class="field-description">
192 - A0 will automatically memorize facts and solutions from conversation history.
193 - </div>
194 - </div>
195 - <div class="field-control">
196 - <label class="toggle">
197 - <input type="checkbox" x-model="$store.settings.settings.memory_memorize_enabled" />
198 - <span class="toggler"></span>
199 - </label>
200 - </div>
201 - </div>
202 -
203 - <div class="field">
204 - <div class="field-label">
205 - <div class="field-title">Auto-memorize AI consolidation</div>
206 - <div class="field-description">
207 - A0 will automatically consolidate similar memories using utility LLM. Improves memory quality over time, adds 2 utility LLM calls per memory.
208 - </div>
209 - </div>
210 - <div class="field-control">
211 - <label class="toggle">
212 - <input type="checkbox" x-model="$store.settings.settings.memory_memorize_consolidation" />
213 - <span class="toggler"></span>
214 - </label>
215 - </div>
216 - </div>
217 -
218 - <div class="field">
219 - <div class="field-label">
220 - <div class="field-title">Auto-memorize replacement threshold</div>
221 - <div class="field-description">
222 - Only applies when AI consolidation is disabled. Replaces previous similar memories with new ones based on this threshold. 0 = replace even if not similar at all, 1 = replace only if exact match.
223 - </div>
224 - </div>
225 - <div class="field-control">
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>
231 - </template>
232 - </div>
233 - </body>
234 -</html>
webui/components/settings/plugins/plugins-subsection.html
+101 -37
@@ -46,7 +46,7 @@
46 this.loading = false;
47 }
48 },
49 - async openSettings(plugin) {
49 + async openPluginConfig(plugin) {
50 if (!plugin?.name) return;
51 await Alpine.store('pluginSettings')?.open(plugin.name);
52 window.openModal?.('components/plugins/plugin-settings.html');
@@ -54,73 +54,137 @@
54 }" x-init="init()">
55
56 <template x-if="loading || plugins.length > 0">
57 - <div class="plugin-subsection-wrapper">
57 + <div>
58 <div class="section-title">Plugins</div>
59 <div class="section-description">
60 Plugin-specific settings for this tab.
61 </div>
62
63 - <div x-show="loading" class="plugin-subsection-loading">
64 - <span>Loading...</span>
63 + <div x-show="loading" class="loading">
64 + <span>Loading plugins...</span>
65 </div>
66
67 - <template x-for="plugin in plugins" :key="plugin.path || plugin.name">
68 - <div class="plugin-subsection-row">
69 - <div class="plugin-subsection-info">
70 - <span class="plugin-subsection-name" x-text="plugin.display_name || plugin.name"></span>
71 - <span class="plugin-subsection-desc" x-text="plugin.description"></span>
67 + <div class="plugins-list">
68 + <template x-for="plugin in plugins" :key="plugin.path || plugin.name">
69 + <div class="plugin-card">
70 + <div class="plugin-header">
71 + <div class="plugin-heading">
72 + <div class="plugin-title" x-text="plugin.display_name || plugin.name || '(unnamed plugin)'"></div>
73 + <code class="plugin-path" x-text="plugin.path"></code>
74 + </div>
75 + <div class="plugin-actions">
76 + <button type="button"
77 + class="button"
78 + title="Config"
79 + @click="openPluginConfig(plugin)">
80 + <span class="icon material-symbols-outlined">settings</span> Config
81 + </button>
82 + </div>
83 + </div>
84 + <div class="plugin-description" x-text="plugin.description || 'No description provided.'"></div>
85 </div>
73 - <button class="button" @click="openSettings(plugin)">
74 - <span class="icon material-symbols-outlined">settings</span>
75 - Settings
76 - </button>
77 - </div>
78 - </template>
86 + </template>
87 + </div>
88 </div>
89 </template>
90 </div>
91
92 <style>
84 - .plugin-subsection-wrapper {
85 - margin-top: 0.5rem;
93 + /* Reused styles from plugin-list.html for uniformity */
94 + .plugins-list {
95 + margin-top: 0.25rem;
96 }
97
88 - .plugin-subsection-loading {
89 - color: var(--color-text-secondary);
90 - font-size: var(--font-size-small);
91 - margin-top: 0.5rem;
98 + .plugin-card {
99 + border: 1px solid var(--color-border);
100 + border-radius: 4px;
101 + padding: 0.75rem;
102 + margin-top: 0.75rem;
103 + background: var(--color-bg-primary);
104 }
105
94 - .plugin-subsection-row {
106 + .plugin-header {
107 display: flex;
96 - align-items: center;
108 + align-items: flex-start;
109 justify-content: space-between;
110 gap: 1rem;
99 - padding: 0.6rem 0.75rem;
100 - border: 1px solid var(--color-border);
101 - border-radius: 4px;
102 - margin-top: 0.5rem;
103 - background: var(--color-bg-primary);
111 + flex-wrap: nowrap;
112 + min-width: 0;
113 }
114
106 - .plugin-subsection-info {
115 + .plugin-heading {
116 display: flex;
117 flex-direction: column;
109 - gap: 0.2rem;
118 min-width: 0;
119 + flex: 1 1 auto;
120 }
121
113 - .plugin-subsection-name {
122 + .plugin-title {
123 font-weight: 600;
115 - font-size: var(--font-size-normal);
124 + font-size: 1rem;
125 + min-width: 0;
126 + flex: 1 1 auto;
127 }
128
118 - .plugin-subsection-desc {
119 - font-size: var(--font-size-small);
129 + .plugin-actions {
130 + display: flex;
131 + align-items: center;
132 + gap: 0.5rem;
133 + padding-bottom: var(--spacing-sm);
134 + flex-wrap: nowrap;
135 + min-width: 0;
136 + flex: 0 0 auto;
137 + max-width: 100%;
138 + justify-content: flex-end;
139 + }
140 +
141 + .plugin-description {
142 + margin-top: 0.35rem;
143 color: var(--color-text-secondary);
121 - white-space: nowrap;
122 - overflow: hidden;
123 - text-overflow: ellipsis;
144 + font-size: var(--font-size-small);
145 + }
146 +
147 + .plugin-path {
148 + margin-top: 0.35rem;
149 + font-size: 0.85rem;
150 + color: var(--color-text-muted);
151 + min-width: 0;
152 + max-width: 100%;
153 + white-space: pre-wrap;
154 + word-break: break-word;
155 + overflow-wrap: anywhere;
156 + }
157 +
158 + .loading {
159 + width: 100%;
160 + text-align: center;
161 + margin-top: 0.75rem;
162 + margin-bottom: 0.75rem;
163 + color: var(--color-secondary);
164 + }
165 +
166 + @media (max-width: 640px) {
167 + .plugin-header {
168 + flex-direction: column;
169 + align-items: stretch;
170 + }
171 +
172 + .plugin-heading {
173 + width: 100%;
174 + flex: 0 0 auto;
175 + }
176 +
177 + .plugin-actions {
178 + width: 100%;
179 + justify-content: flex-start;
180 + padding-bottom: 0;
181 + flex-wrap: wrap;
182 + }
183 +
184 + .plugin-path {
185 + white-space: normal;
186 + word-break: break-word;
187 + }
188 }
189 </style>
190 </body>