mindroot 7.7.0__py3-none-any.whl → 8.2.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of mindroot might be problematic. Click here for more details.
- mindroot/coreplugins/admin/plugin_manager.py +126 -3
- mindroot/coreplugins/admin/plugin_manager_backup.py +615 -0
- mindroot/coreplugins/admin/router.py +3 -1
- mindroot/coreplugins/admin/server_router.py +8 -1
- mindroot/coreplugins/admin/static/js/plugin-advanced-install.js +83 -12
- mindroot/coreplugins/admin/static/js/plugin-index-browser.js +138 -10
- mindroot/coreplugins/admin/static/js/plugin-install-dialog.js +345 -0
- mindroot/coreplugins/admin/static/js/server-control.js +68 -6
- mindroot/coreplugins/agent/agent.py +4 -0
- mindroot/coreplugins/chat/models.py +0 -1
- mindroot/coreplugins/chat/router.py +31 -0
- mindroot/coreplugins/chat/services.py +24 -0
- mindroot/coreplugins/chat/static/css/dark.css +35 -0
- mindroot/coreplugins/chat/static/css/default.css +35 -0
- mindroot/coreplugins/chat/static/js/chatform.js +185 -0
- mindroot/coreplugins/env_manager/__init__.py +3 -0
- mindroot/coreplugins/env_manager/inject/admin.jinja2 +16 -0
- mindroot/coreplugins/env_manager/mod.py +228 -0
- mindroot/coreplugins/env_manager/router.py +40 -0
- mindroot/coreplugins/env_manager/static/css/env-manager.css +263 -0
- mindroot/coreplugins/env_manager/static/js/env-manager.js +380 -0
- mindroot/coreplugins/home/router.py +33 -2
- mindroot/coreplugins/home/static/css/enhanced.css +111 -5
- mindroot/coreplugins/home/templates/home.jinja2 +7 -4
- mindroot/lib/chatlog.py +5 -1
- mindroot/lib/streamcmd.py +139 -0
- mindroot/lib/templates.py +13 -2
- mindroot/server.py +12 -25
- mindroot-8.2.0.dist-info/METADATA +15 -0
- {mindroot-7.7.0.dist-info → mindroot-8.2.0.dist-info}/RECORD +34 -25
- {mindroot-7.7.0.dist-info → mindroot-8.2.0.dist-info}/WHEEL +1 -1
- mindroot-7.7.0.dist-info/METADATA +0 -310
- {mindroot-7.7.0.dist-info → mindroot-8.2.0.dist-info}/entry_points.txt +0 -0
- {mindroot-7.7.0.dist-info → mindroot-8.2.0.dist-info}/licenses/LICENSE +0 -0
- {mindroot-7.7.0.dist-info → mindroot-8.2.0.dist-info}/top_level.txt +0 -0
|
@@ -0,0 +1,380 @@
|
|
|
1
|
+
import { LitElement, html, css } from '/admin/static/js/lit-core.min.js';
|
|
2
|
+
import { BaseEl } from '/admin/static/js/base.js';
|
|
3
|
+
|
|
4
|
+
class EnvManager extends BaseEl {
|
|
5
|
+
static properties = {
|
|
6
|
+
pluginData: { type: Object },
|
|
7
|
+
loading: { type: Boolean },
|
|
8
|
+
editingVar: { type: String },
|
|
9
|
+
newVarName: { type: String },
|
|
10
|
+
newVarValue: { type: String },
|
|
11
|
+
showAddForm: { type: Boolean },
|
|
12
|
+
searchTerm: { type: String }
|
|
13
|
+
};
|
|
14
|
+
|
|
15
|
+
constructor() {
|
|
16
|
+
super();
|
|
17
|
+
this.pluginData = null;
|
|
18
|
+
this.loading = true;
|
|
19
|
+
this.editingVar = null;
|
|
20
|
+
this.newVarName = '';
|
|
21
|
+
this.newVarValue = '';
|
|
22
|
+
this.showAddForm = false;
|
|
23
|
+
this.searchTerm = '';
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
connectedCallback() {
|
|
27
|
+
super.connectedCallback();
|
|
28
|
+
this.fetchEnvVars();
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
async fetchEnvVars() {
|
|
32
|
+
this.loading = true;
|
|
33
|
+
try {
|
|
34
|
+
const response = await fetch('/env_vars/scan');
|
|
35
|
+
const result = await response.json();
|
|
36
|
+
if (result.success) {
|
|
37
|
+
this.pluginData = result.data;
|
|
38
|
+
} else {
|
|
39
|
+
console.error('Error fetching environment variables:', result.error);
|
|
40
|
+
}
|
|
41
|
+
} catch (error) {
|
|
42
|
+
console.error('Error fetching environment variables:', error);
|
|
43
|
+
} finally {
|
|
44
|
+
this.loading = false;
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
async updateEnvVar(varName, varValue) {
|
|
49
|
+
try {
|
|
50
|
+
const response = await fetch('/env_vars/update', {
|
|
51
|
+
method: 'POST',
|
|
52
|
+
headers: {
|
|
53
|
+
'Content-Type': 'application/json',
|
|
54
|
+
},
|
|
55
|
+
body: JSON.stringify({
|
|
56
|
+
var_name: varName,
|
|
57
|
+
var_value: varValue
|
|
58
|
+
})
|
|
59
|
+
});
|
|
60
|
+
|
|
61
|
+
const result = await response.json();
|
|
62
|
+
if (result.success) {
|
|
63
|
+
// Refresh the data
|
|
64
|
+
await this.fetchEnvVars();
|
|
65
|
+
return true;
|
|
66
|
+
} else {
|
|
67
|
+
console.error('Error updating environment variable:', result.message);
|
|
68
|
+
return false;
|
|
69
|
+
}
|
|
70
|
+
} catch (error) {
|
|
71
|
+
console.error('Error updating environment variable:', error);
|
|
72
|
+
return false;
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
handleEditClick(varName) {
|
|
77
|
+
this.editingVar = varName;
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
async handleSaveEdit(varName) {
|
|
81
|
+
const inputEl = this.shadowRoot.querySelector(`#edit-${varName}`);
|
|
82
|
+
if (inputEl) {
|
|
83
|
+
const newValue = inputEl.value;
|
|
84
|
+
const success = await this.updateEnvVar(varName, newValue);
|
|
85
|
+
if (success) {
|
|
86
|
+
this.editingVar = null;
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
handleCancelEdit() {
|
|
92
|
+
this.editingVar = null;
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
toggleAddForm() {
|
|
96
|
+
this.showAddForm = !this.showAddForm;
|
|
97
|
+
if (!this.showAddForm) {
|
|
98
|
+
this.newVarName = '';
|
|
99
|
+
this.newVarValue = '';
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
async handleAddVar() {
|
|
104
|
+
if (this.newVarName && this.newVarValue) {
|
|
105
|
+
const success = await this.updateEnvVar(this.newVarName, this.newVarValue);
|
|
106
|
+
if (success) {
|
|
107
|
+
this.newVarName = '';
|
|
108
|
+
this.newVarValue = '';
|
|
109
|
+
this.showAddForm = false;
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
handleSearchInput(e) {
|
|
115
|
+
this.searchTerm = e.target.value;
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
renderEnvironmentVars() {
|
|
119
|
+
if (!this.pluginData || !this.pluginData.current_env) {
|
|
120
|
+
return html`<div class="empty-state">No environment variables found</div>`;
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
const currentEnv = this.pluginData.current_env;
|
|
124
|
+
|
|
125
|
+
// Create a mapping of variable names to the plugins that reference them
|
|
126
|
+
const varsByPlugin = {};
|
|
127
|
+
const pluginsByVar = {};
|
|
128
|
+
|
|
129
|
+
for (const [pluginName, pluginInfo] of Object.entries(this.pluginData)) {
|
|
130
|
+
if (pluginName === 'current_env') continue;
|
|
131
|
+
|
|
132
|
+
for (const varName of pluginInfo.env_vars) {
|
|
133
|
+
if (!varsByPlugin[pluginName]) {
|
|
134
|
+
varsByPlugin[pluginName] = [];
|
|
135
|
+
}
|
|
136
|
+
varsByPlugin[pluginName].push(varName);
|
|
137
|
+
|
|
138
|
+
if (!pluginsByVar[varName]) {
|
|
139
|
+
pluginsByVar[varName] = [];
|
|
140
|
+
}
|
|
141
|
+
pluginsByVar[varName].push(pluginName);
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
// Group variables by plugin
|
|
146
|
+
const groupedByPlugin = {};
|
|
147
|
+
const multiPluginVars = [];
|
|
148
|
+
|
|
149
|
+
// First, identify variables referenced by multiple plugins
|
|
150
|
+
for (const [varName, plugins] of Object.entries(pluginsByVar)) {
|
|
151
|
+
if (plugins.length > 1) {
|
|
152
|
+
multiPluginVars.push({
|
|
153
|
+
varName,
|
|
154
|
+
varValue: currentEnv[varName],
|
|
155
|
+
plugins
|
|
156
|
+
});
|
|
157
|
+
} else {
|
|
158
|
+
// Single plugin variables
|
|
159
|
+
const plugin = plugins[0];
|
|
160
|
+
if (!groupedByPlugin[plugin]) {
|
|
161
|
+
groupedByPlugin[plugin] = [];
|
|
162
|
+
}
|
|
163
|
+
groupedByPlugin[plugin].push({
|
|
164
|
+
varName,
|
|
165
|
+
varValue: currentEnv[varName]
|
|
166
|
+
});
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
// Sort plugins alphabetically
|
|
171
|
+
const sortedPlugins = Object.keys(groupedByPlugin).sort();
|
|
172
|
+
|
|
173
|
+
// Sort multi-plugin variables by name
|
|
174
|
+
multiPluginVars.sort((a, b) => a.varName.localeCompare(b.varName));
|
|
175
|
+
|
|
176
|
+
// Apply search filter if needed
|
|
177
|
+
let filteredPlugins = sortedPlugins;
|
|
178
|
+
let filteredMultiVars = multiPluginVars;
|
|
179
|
+
|
|
180
|
+
if (this.searchTerm) {
|
|
181
|
+
const searchTerm = this.searchTerm.toLowerCase();
|
|
182
|
+
|
|
183
|
+
// Filter plugins and their variables
|
|
184
|
+
filteredPlugins = sortedPlugins.filter(plugin => {
|
|
185
|
+
// Check if plugin name matches
|
|
186
|
+
if (plugin.toLowerCase().includes(searchTerm)) return true;
|
|
187
|
+
|
|
188
|
+
// Check if any variable name matches
|
|
189
|
+
return groupedByPlugin[plugin].some(v =>
|
|
190
|
+
v.varName.toLowerCase().includes(searchTerm) ||
|
|
191
|
+
(v.varValue && v.varValue.toLowerCase().includes(searchTerm))
|
|
192
|
+
);
|
|
193
|
+
});
|
|
194
|
+
|
|
195
|
+
// For each plugin, filter its variables
|
|
196
|
+
for (const plugin of filteredPlugins) {
|
|
197
|
+
groupedByPlugin[plugin] = groupedByPlugin[plugin].filter(v =>
|
|
198
|
+
v.varName.toLowerCase().includes(searchTerm) ||
|
|
199
|
+
plugin.toLowerCase().includes(searchTerm) ||
|
|
200
|
+
(v.varValue && v.varValue.toLowerCase().includes(searchTerm))
|
|
201
|
+
);
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
// Filter multi-plugin variables
|
|
205
|
+
filteredMultiVars = multiPluginVars.filter(v =>
|
|
206
|
+
v.varName.toLowerCase().includes(searchTerm) ||
|
|
207
|
+
v.plugins.some(p => p.toLowerCase().includes(searchTerm)) ||
|
|
208
|
+
(v.varValue && v.varValue.toLowerCase().includes(searchTerm))
|
|
209
|
+
);
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
// Check if we have any results after filtering
|
|
213
|
+
const hasResults = filteredPlugins.some(p => groupedByPlugin[p].length > 0) || filteredMultiVars.length > 0;
|
|
214
|
+
|
|
215
|
+
if (!hasResults) {
|
|
216
|
+
return html`<div class="empty-state">No matching environment variables found</div>`;
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
return html`
|
|
220
|
+
<table class="env-table">
|
|
221
|
+
<thead>
|
|
222
|
+
<tr>
|
|
223
|
+
<th>Variable Name</th>
|
|
224
|
+
<th>Value</th>
|
|
225
|
+
<th>Actions</th>
|
|
226
|
+
</tr>
|
|
227
|
+
</thead>
|
|
228
|
+
<tbody>
|
|
229
|
+
${filteredPlugins.map(plugin => {
|
|
230
|
+
if (groupedByPlugin[plugin].length === 0) return '';
|
|
231
|
+
|
|
232
|
+
return html`
|
|
233
|
+
<tr class="plugin-header">
|
|
234
|
+
<td colspan="3" class="plugin-name">${plugin}</td>
|
|
235
|
+
</tr>
|
|
236
|
+
${groupedByPlugin[plugin].map(v => {
|
|
237
|
+
const { varName, varValue } = v;
|
|
238
|
+
const isMasked = varValue === '********';
|
|
239
|
+
|
|
240
|
+
return html`
|
|
241
|
+
<tr class="plugin-var">
|
|
242
|
+
<td><span class="var-name" title="${varName}">${varName}</span></td>
|
|
243
|
+
<td>
|
|
244
|
+
${this.editingVar === varName ?
|
|
245
|
+
html`
|
|
246
|
+
<div class="edit-form">
|
|
247
|
+
<input
|
|
248
|
+
id="edit-${varName}"
|
|
249
|
+
type="text"
|
|
250
|
+
value="${isMasked ? '' : varValue}"
|
|
251
|
+
placeholder="${isMasked ? 'Enter new value' : ''}">
|
|
252
|
+
</div>
|
|
253
|
+
` :
|
|
254
|
+
html`<span class="var-value ${isMasked ? 'masked' : ''}">${varValue}</span>`
|
|
255
|
+
}
|
|
256
|
+
</td>
|
|
257
|
+
<td>
|
|
258
|
+
<div class="actions">
|
|
259
|
+
${this.editingVar === varName ?
|
|
260
|
+
html`
|
|
261
|
+
<button class="small primary" @click=${() => this.handleSaveEdit(varName)}>Save</button>
|
|
262
|
+
<button class="small" @click=${this.handleCancelEdit}>Cancel</button>
|
|
263
|
+
` :
|
|
264
|
+
html`<button class="small" @click=${() => this.handleEditClick(varName)}>Edit</button>`
|
|
265
|
+
}
|
|
266
|
+
</div>
|
|
267
|
+
</td>
|
|
268
|
+
</tr>
|
|
269
|
+
`;
|
|
270
|
+
})}
|
|
271
|
+
`;
|
|
272
|
+
})}
|
|
273
|
+
|
|
274
|
+
${filteredMultiVars.length > 0 ? html`
|
|
275
|
+
<tr class="plugin-header">
|
|
276
|
+
<td colspan="3" class="plugin-name">Multiple Plugins</td>
|
|
277
|
+
</tr>
|
|
278
|
+
${filteredMultiVars.map(v => {
|
|
279
|
+
const { varName, varValue, plugins } = v;
|
|
280
|
+
const isMasked = varValue === '********';
|
|
281
|
+
|
|
282
|
+
return html`
|
|
283
|
+
<tr class="plugin-var">
|
|
284
|
+
<td>
|
|
285
|
+
<span class="var-name" title="${varName}">${varName}</span>
|
|
286
|
+
<div class="plugin-refs">
|
|
287
|
+
${plugins.map(p => html`<span class="plugin-tag">${p}</span>`)}
|
|
288
|
+
</div>
|
|
289
|
+
</td>
|
|
290
|
+
<td>
|
|
291
|
+
${this.editingVar === varName ?
|
|
292
|
+
html`
|
|
293
|
+
<div class="edit-form">
|
|
294
|
+
<input
|
|
295
|
+
id="edit-${varName}"
|
|
296
|
+
type="text"
|
|
297
|
+
value="${isMasked ? '' : varValue}"
|
|
298
|
+
placeholder="${isMasked ? 'Enter new value' : ''}">
|
|
299
|
+
</div>
|
|
300
|
+
` :
|
|
301
|
+
html`<span class="var-value ${isMasked ? 'masked' : ''}">${varValue}</span>`
|
|
302
|
+
}
|
|
303
|
+
</td>
|
|
304
|
+
<td>
|
|
305
|
+
<div class="actions">
|
|
306
|
+
${this.editingVar === varName ?
|
|
307
|
+
html`
|
|
308
|
+
<button class="small primary" @click=${() => this.handleSaveEdit(varName)}>Save</button>
|
|
309
|
+
<button class="small" @click=${this.handleCancelEdit}>Cancel</button>
|
|
310
|
+
` :
|
|
311
|
+
html`<button class="small" @click=${() => this.handleEditClick(varName)}>Edit</button>`
|
|
312
|
+
}
|
|
313
|
+
</div>
|
|
314
|
+
</td>
|
|
315
|
+
</tr>
|
|
316
|
+
`;
|
|
317
|
+
})}
|
|
318
|
+
` : ''}
|
|
319
|
+
</tbody>
|
|
320
|
+
</table>
|
|
321
|
+
`;
|
|
322
|
+
}
|
|
323
|
+
|
|
324
|
+
_render() {
|
|
325
|
+
return html`
|
|
326
|
+
<link rel="stylesheet" href="/env_manager/static/css/env-manager.css">
|
|
327
|
+
<div class="env-manager">
|
|
328
|
+
<div class="section">
|
|
329
|
+
<h3>
|
|
330
|
+
Environment Variables
|
|
331
|
+
<div class="controls">
|
|
332
|
+
<input
|
|
333
|
+
type="text"
|
|
334
|
+
class="search-box"
|
|
335
|
+
placeholder="Search..."
|
|
336
|
+
@input=${this.handleSearchInput}
|
|
337
|
+
.value=${this.searchTerm}>
|
|
338
|
+
<button @click=${this.toggleAddForm}>
|
|
339
|
+
${this.showAddForm ? 'Cancel' : 'Add Variable'}
|
|
340
|
+
</button>
|
|
341
|
+
</div>
|
|
342
|
+
</h3>
|
|
343
|
+
|
|
344
|
+
${this.loading ?
|
|
345
|
+
html`<div class="loading">Loading environment variables...</div>` :
|
|
346
|
+
html`
|
|
347
|
+
${this.showAddForm ?
|
|
348
|
+
html`
|
|
349
|
+
<div class="add-form">
|
|
350
|
+
<div class="form-row">
|
|
351
|
+
<input
|
|
352
|
+
type="text"
|
|
353
|
+
placeholder="Variable Name"
|
|
354
|
+
.value=${this.newVarName}
|
|
355
|
+
@input=${e => this.newVarName = e.target.value}>
|
|
356
|
+
</div>
|
|
357
|
+
<div class="form-row">
|
|
358
|
+
<input
|
|
359
|
+
type="text"
|
|
360
|
+
placeholder="Variable Value"
|
|
361
|
+
.value=${this.newVarValue}
|
|
362
|
+
@input=${e => this.newVarValue = e.target.value}>
|
|
363
|
+
</div>
|
|
364
|
+
<div class="form-actions">
|
|
365
|
+
<button class="primary" @click=${this.handleAddVar}>Add Variable</button>
|
|
366
|
+
</div>
|
|
367
|
+
</div>
|
|
368
|
+
` : ''
|
|
369
|
+
}
|
|
370
|
+
|
|
371
|
+
${this.renderEnvironmentVars()}
|
|
372
|
+
`
|
|
373
|
+
}
|
|
374
|
+
</div>
|
|
375
|
+
</div>
|
|
376
|
+
`;
|
|
377
|
+
}
|
|
378
|
+
}
|
|
379
|
+
|
|
380
|
+
customElements.define('env-manager', EnvManager);
|
|
@@ -4,6 +4,9 @@ from fastapi.templating import Jinja2Templates
|
|
|
4
4
|
from lib.templates import render
|
|
5
5
|
from lib.route_decorators import add_public_static
|
|
6
6
|
import os
|
|
7
|
+
import glob
|
|
8
|
+
from datetime import datetime
|
|
9
|
+
import time
|
|
7
10
|
|
|
8
11
|
router = APIRouter()
|
|
9
12
|
|
|
@@ -14,8 +17,36 @@ add_public_static('/home/static/')
|
|
|
14
17
|
|
|
15
18
|
@router.get("/", response_class=HTMLResponse)
|
|
16
19
|
async def home(request: Request):
|
|
17
|
-
|
|
20
|
+
# Get all agent directories
|
|
21
|
+
agent_dirs = [agent for agent in os.listdir("data/agents/local") if os.path.isdir(os.path.join("data/agents/local", agent))]
|
|
22
|
+
|
|
23
|
+
# Try to sort agents by last access time
|
|
24
|
+
agent_access_times = []
|
|
25
|
+
for agent in agent_dirs:
|
|
26
|
+
# Look for the most recent log file for this agent
|
|
27
|
+
log_pattern = f"data/chatlogs/{agent}_*.json"
|
|
28
|
+
log_files = glob.glob(log_pattern)
|
|
29
|
+
|
|
30
|
+
if log_files:
|
|
31
|
+
# Get the most recent log file's modification time
|
|
32
|
+
latest_log = max(log_files, key=os.path.getmtime)
|
|
33
|
+
mtime = os.path.getmtime(latest_log)
|
|
34
|
+
else:
|
|
35
|
+
# If no logs, use the agent.json file's modification time
|
|
36
|
+
agent_file = os.path.join("data/agents/local", agent, "agent.json")
|
|
37
|
+
if os.path.exists(agent_file):
|
|
38
|
+
mtime = os.path.getmtime(agent_file)
|
|
39
|
+
else:
|
|
40
|
+
mtime = 0 # Default to oldest if no file found
|
|
41
|
+
|
|
42
|
+
agent_access_times.append((agent, mtime))
|
|
43
|
+
|
|
44
|
+
# Sort by modification time (most recent first)
|
|
45
|
+
agent_access_times.sort(key=lambda x: x[1], reverse=True)
|
|
46
|
+
|
|
47
|
+
# Extract just the agent names in sorted order
|
|
48
|
+
agents = [agent for agent, _ in agent_access_times]
|
|
49
|
+
|
|
18
50
|
user = request.state.user
|
|
19
51
|
html = await render('home', {"user": user, "request": request, "agents": agents })
|
|
20
52
|
return HTMLResponse(html)
|
|
21
|
-
|
|
@@ -1,7 +1,8 @@
|
|
|
1
|
-
/* Enhanced styles for
|
|
1
|
+
/* Enhanced styles for MindRoot Agent Host */
|
|
2
2
|
|
|
3
3
|
.agent-container {
|
|
4
|
-
|
|
4
|
+
width: 90%; /* Use percentage instead of fixed width */
|
|
5
|
+
max-width: 2000px; /* Increased from 1200px for wider screens */
|
|
5
6
|
margin: 0 auto;
|
|
6
7
|
padding: 2rem;
|
|
7
8
|
}
|
|
@@ -9,6 +10,7 @@
|
|
|
9
10
|
.logo {
|
|
10
11
|
transition: transform 0.3s ease;
|
|
11
12
|
margin-bottom: 2rem;
|
|
13
|
+
max-width: 120px; /* Control logo size */
|
|
12
14
|
}
|
|
13
15
|
|
|
14
16
|
.logo:hover {
|
|
@@ -22,13 +24,15 @@ h1 {
|
|
|
22
24
|
background: linear-gradient(45deg, #6e8efb, #a777e3);
|
|
23
25
|
-webkit-background-clip: text;
|
|
24
26
|
-webkit-text-fill-color: transparent;
|
|
27
|
+
text-align: center;
|
|
25
28
|
}
|
|
26
29
|
|
|
27
30
|
.agent-list {
|
|
28
31
|
display: grid;
|
|
29
|
-
grid-template-columns: repeat(auto-fill, minmax(
|
|
32
|
+
grid-template-columns: repeat(auto-fill, minmax(220px, 1fr));
|
|
30
33
|
gap: 1.5rem;
|
|
31
34
|
margin-top: 2rem;
|
|
35
|
+
width: 100%;
|
|
32
36
|
}
|
|
33
37
|
|
|
34
38
|
.agent-link {
|
|
@@ -38,9 +42,12 @@ h1 {
|
|
|
38
42
|
transition: all 0.3s ease;
|
|
39
43
|
border: 1px solid rgba(255, 255, 255, 0.1);
|
|
40
44
|
display: flex;
|
|
45
|
+
flex-direction: column;
|
|
41
46
|
align-items: center;
|
|
47
|
+
text-align: center;
|
|
42
48
|
text-decoration: none;
|
|
43
49
|
color: inherit;
|
|
50
|
+
height: 100%;
|
|
44
51
|
}
|
|
45
52
|
|
|
46
53
|
.agent-link:hover {
|
|
@@ -54,13 +61,40 @@ h1 {
|
|
|
54
61
|
height: 8px;
|
|
55
62
|
border-radius: 50%;
|
|
56
63
|
background: #4CAF50;
|
|
57
|
-
margin-
|
|
64
|
+
margin-bottom: 8px;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
.agent-avatar {
|
|
68
|
+
width: 160px;
|
|
69
|
+
height: 160px;
|
|
70
|
+
border-radius: 50%;
|
|
71
|
+
object-fit: cover;
|
|
72
|
+
margin-bottom: 16px;
|
|
73
|
+
border: 2px solid rgba(255, 255, 255, 0.2);
|
|
74
|
+
transition: all 0.3s ease;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
.agent-link:hover .agent-avatar {
|
|
78
|
+
border-color: rgba(255, 255, 255, 0.5);
|
|
79
|
+
transform: scale(1.05);
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
.agent-info {
|
|
83
|
+
display: flex;
|
|
84
|
+
flex-direction: column;
|
|
85
|
+
align-items: center;
|
|
86
|
+
width: 100%;
|
|
58
87
|
}
|
|
59
88
|
|
|
60
89
|
.agent-name {
|
|
61
90
|
font-size: 1.2rem;
|
|
62
91
|
font-weight: 500;
|
|
63
92
|
letter-spacing: 0.5px;
|
|
93
|
+
word-break: keep-all;
|
|
94
|
+
max-width: 100%;
|
|
95
|
+
overflow-wrap: break-word;
|
|
96
|
+
line-height: 1.3;
|
|
97
|
+
white-space: normal;
|
|
64
98
|
}
|
|
65
99
|
|
|
66
100
|
.admin-link {
|
|
@@ -79,7 +113,7 @@ h1 {
|
|
|
79
113
|
}
|
|
80
114
|
|
|
81
115
|
.admin-link:visited {
|
|
82
|
-
|
|
116
|
+
color: #ddd;
|
|
83
117
|
}
|
|
84
118
|
|
|
85
119
|
h2 {
|
|
@@ -87,4 +121,76 @@ h2 {
|
|
|
87
121
|
font-weight: 500;
|
|
88
122
|
margin-bottom: 1.5rem;
|
|
89
123
|
color: rgba(255, 255, 255, 0.9);
|
|
124
|
+
text-align: center;
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
/* Responsive breakpoints */
|
|
128
|
+
|
|
129
|
+
/* Extra large screens */
|
|
130
|
+
@media (min-width: 1800px) {
|
|
131
|
+
.agent-list {
|
|
132
|
+
grid-template-columns: repeat(auto-fill, minmax(280px, 1fr));
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
.agent-container {
|
|
136
|
+
width: 85%;
|
|
137
|
+
max-width: 2400px;
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
/* Large screens */
|
|
142
|
+
@media (min-width: 1200px) and (max-width: 1799px) {
|
|
143
|
+
.agent-list {
|
|
144
|
+
grid-template-columns: repeat(auto-fill, minmax(250px, 1fr));
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
.agent-container {
|
|
148
|
+
width: 90%;
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
/* Medium screens */
|
|
153
|
+
@media (min-width: 768px) and (max-width: 1199px) {
|
|
154
|
+
.agent-list {
|
|
155
|
+
grid-template-columns: repeat(auto-fill, minmax(220px, 1fr));
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
.agent-avatar {
|
|
159
|
+
width: 140px;
|
|
160
|
+
height: 140px;
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
.agent-container {
|
|
164
|
+
width: 95%;
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
/* Small screens */
|
|
169
|
+
@media (max-width: 767px) {
|
|
170
|
+
.agent-list {
|
|
171
|
+
grid-template-columns: repeat(auto-fill, minmax(160px, 1fr));
|
|
172
|
+
gap: 1rem;
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
.agent-avatar {
|
|
176
|
+
width: 120px;
|
|
177
|
+
height: 120px;
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
.agent-name {
|
|
181
|
+
font-size: 1rem;
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
.agent-container {
|
|
185
|
+
width: 100%;
|
|
186
|
+
padding: 1rem;
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
h1 {
|
|
190
|
+
font-size: 2rem;
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
h2 {
|
|
194
|
+
font-size: 1.3rem;
|
|
195
|
+
}
|
|
90
196
|
}
|
|
@@ -10,6 +10,7 @@
|
|
|
10
10
|
{% block head_title %}
|
|
11
11
|
<title>MindRoot Agent Host</title>
|
|
12
12
|
{% endblock %}
|
|
13
|
+
|
|
13
14
|
{% block head_css %}
|
|
14
15
|
<link rel="stylesheet" href="/home/static/css/reset.css">
|
|
15
16
|
<link rel="stylesheet" href="/home/static/css/default.css">
|
|
@@ -51,9 +52,12 @@
|
|
|
51
52
|
|
|
52
53
|
<div class="agent-list" role="list">
|
|
53
54
|
{% for agent in agents %}
|
|
54
|
-
<a href="/agent/{{ agent }}" class="agent-link" role="listitem" target="_blank"
|
|
55
|
-
<
|
|
56
|
-
<
|
|
55
|
+
<a href="/agent/{{ agent }}" class="agent-link" role="listitem" target="_blank">
|
|
56
|
+
<img src="/chat/personas/{{ agent }}/avatar.png" alt="{{ agent }} avatar" class="agent-avatar" onerror="this.src='/chat/static/assistant.png'">
|
|
57
|
+
<div class="agent-info">
|
|
58
|
+
<span class="agent-status" aria-hidden="true"></span>
|
|
59
|
+
<span class="agent-name">{{ agent | replace('_', ' ') }}</span>
|
|
60
|
+
</div>
|
|
57
61
|
</a>
|
|
58
62
|
{% endfor %}
|
|
59
63
|
</div>
|
|
@@ -74,4 +78,3 @@
|
|
|
74
78
|
{% endblock %}
|
|
75
79
|
</body>
|
|
76
80
|
</html>
|
|
77
|
-
|
mindroot/lib/chatlog.py
CHANGED
|
@@ -70,7 +70,11 @@ class ChatLog:
|
|
|
70
70
|
except Exception as e:
|
|
71
71
|
# assume previous mesage was not a command, was a string
|
|
72
72
|
debug_box("4")
|
|
73
|
-
|
|
73
|
+
print("Could not combine commands, probably normal if user message and previous system output, assuming string", e)
|
|
74
|
+
if type(self.messages[-1]['content']) == str:
|
|
75
|
+
new_msg_text = self.messages[-1]['content'] + message['content'][0]['text']
|
|
76
|
+
else:
|
|
77
|
+
new_msg_text = self.messages[-1]['content'][0]['text'] + message['content'][0]['text']
|
|
74
78
|
self.messages.append({'role': message['role'], 'content': [{'type': 'text', 'text': new_msg_text}]})
|
|
75
79
|
#print('could not combine commands. probably normal if user message and previous system output', e)
|
|
76
80
|
#print(self.messages[-1])
|