mindroot 9.19.0__py3-none-any.whl → 9.21.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/jwt_auth/middleware.py +1 -1
- mindroot/docs/example_plugins/override_home/plugin_info.json +7 -0
- mindroot/docs/example_plugins/override_home/src/override_home/__init__.py +1 -0
- mindroot/docs/example_plugins/override_home/src/override_home/override/home.jinja2 +32 -0
- mindroot/docs/example_plugins/run_task/plugin_info.json +7 -0
- mindroot/docs/example_plugins/run_task/src/run_task/override/home.jinja2 +73 -0
- mindroot/lib/templates.py +61 -12
- {mindroot-9.19.0.dist-info → mindroot-9.21.0.dist-info}/METADATA +1 -1
- {mindroot-9.19.0.dist-info → mindroot-9.21.0.dist-info}/RECORD +13 -8
- {mindroot-9.19.0.dist-info → mindroot-9.21.0.dist-info}/WHEEL +0 -0
- {mindroot-9.19.0.dist-info → mindroot-9.21.0.dist-info}/entry_points.txt +0 -0
- {mindroot-9.19.0.dist-info → mindroot-9.21.0.dist-info}/licenses/LICENSE +0 -0
- {mindroot-9.19.0.dist-info → mindroot-9.21.0.dist-info}/top_level.txt +0 -0
|
@@ -166,7 +166,7 @@ async def middleware(request: Request, call_next):
|
|
|
166
166
|
status_code=403,
|
|
167
167
|
content={"detail": "Invalid API key"}
|
|
168
168
|
)
|
|
169
|
-
if request.url.path.startswith("/imgs/"):
|
|
169
|
+
if request.url.path.startswith("/imgs/") or request.ur.startswith("/manual/"):
|
|
170
170
|
return await call_next(request)
|
|
171
171
|
try:
|
|
172
172
|
path_parts = request.url.path.split('/')
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
#
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
{# assume-blank #}
|
|
2
|
+
<!DOCTYPE html>
|
|
3
|
+
<html lang="en">
|
|
4
|
+
<head>
|
|
5
|
+
<title>My Custom Home Page</title>
|
|
6
|
+
<style>
|
|
7
|
+
|
|
8
|
+
html, body, * {
|
|
9
|
+
color: white;
|
|
10
|
+
background: black;
|
|
11
|
+
font-family: 'Roboto', sans-serif;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
body {
|
|
15
|
+
/* Need to center our message nicely */
|
|
16
|
+
display: flex;
|
|
17
|
+
justify-content: center;
|
|
18
|
+
align-items: center;
|
|
19
|
+
/* also align vertically in viewport */
|
|
20
|
+
height: 100vh;
|
|
21
|
+
margin: 0;
|
|
22
|
+
text-align: center;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
</style>
|
|
26
|
+
|
|
27
|
+
</head>
|
|
28
|
+
<body>
|
|
29
|
+
All of the home page content blocks have been overridden.
|
|
30
|
+
|
|
31
|
+
</body>
|
|
32
|
+
</html>
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
{# assume-blank #}
|
|
2
|
+
<!DOCTYPE html>
|
|
3
|
+
<html lang="en">
|
|
4
|
+
<head>
|
|
5
|
+
<meta charset="UTF-8">
|
|
6
|
+
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
7
|
+
<title>Run Task</title>
|
|
8
|
+
|
|
9
|
+
<style>
|
|
10
|
+
|
|
11
|
+
html, body, * {
|
|
12
|
+
color: white;
|
|
13
|
+
background: black;
|
|
14
|
+
font-family: 'Roboto', sans-serif;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
body {
|
|
18
|
+
margin: 20px;
|
|
19
|
+
padding: 20px;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
.spinner {
|
|
23
|
+
border: 4px solid rgba(255, 255, 255, 0.3);
|
|
24
|
+
border-top: 4px solid white;
|
|
25
|
+
border-radius: 50%;
|
|
26
|
+
width: 24px;
|
|
27
|
+
height: 24px;
|
|
28
|
+
animation: spin 1s linear infinite;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
@keyframes spin {
|
|
32
|
+
0% { transform: rotate(0deg); }
|
|
33
|
+
100% { transform: rotate(360deg); }
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
div, textarea, button {
|
|
37
|
+
display: block;
|
|
38
|
+
margin-top: 20px;
|
|
39
|
+
margin-bottom: 20px;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
</style>
|
|
43
|
+
|
|
44
|
+
</head>
|
|
45
|
+
<body>
|
|
46
|
+
What should the agent display below?
|
|
47
|
+
<textarea id="task" rows="4" cols="50"></textarea>
|
|
48
|
+
|
|
49
|
+
<button id="go">Run Task</button>
|
|
50
|
+
|
|
51
|
+
<div id="spinner" class="spinner" style="display:none;"></div>
|
|
52
|
+
|
|
53
|
+
<div id="result"></div>
|
|
54
|
+
|
|
55
|
+
<script type="module">
|
|
56
|
+
import axios from 'https://cdn.skypack.dev/redaxios';
|
|
57
|
+
const $ = (id) => document.getElementById(id);
|
|
58
|
+
|
|
59
|
+
$('go').addEventListener('click', async () => {
|
|
60
|
+
const instructions = `Output ONLY html snippet to display "${$('task').value}" (be brief)`;
|
|
61
|
+
try {
|
|
62
|
+
$('spinner').style.display = 'block';
|
|
63
|
+
const {data: {results}} = await axios.post('/task/Assistant', { instructions });
|
|
64
|
+
$('spinner').style.display = 'none';
|
|
65
|
+
$('result').innerHTML = results;
|
|
66
|
+
} catch (error) {
|
|
67
|
+
alert('Error: ' + error.message);
|
|
68
|
+
}
|
|
69
|
+
});
|
|
70
|
+
|
|
71
|
+
</script>
|
|
72
|
+
</body>
|
|
73
|
+
</html>
|
mindroot/lib/templates.py
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import os
|
|
2
2
|
import logging
|
|
3
3
|
from jinja2 import Environment, FileSystemLoader, ChoiceLoader
|
|
4
|
+
import re
|
|
4
5
|
from .plugins import list_enabled, get_plugin_path
|
|
5
6
|
from .parent_templates import get_parent_templates_env
|
|
6
7
|
import traceback
|
|
@@ -227,6 +228,7 @@ async def find_parent_template(page_name, plugins):
|
|
|
227
228
|
return rel_path
|
|
228
229
|
return alt_path
|
|
229
230
|
return None
|
|
231
|
+
|
|
230
232
|
async def find_plugin_template(page_name, plugins):
|
|
231
233
|
"""Find a template in a plugin's templates directory.
|
|
232
234
|
|
|
@@ -306,9 +308,6 @@ async def load_plugin_templates(page_name, plugins):
|
|
|
306
308
|
#print(f"Found inject template at: {path}")
|
|
307
309
|
templates.append({'type': 'inject', 'template': env.from_string(content)})
|
|
308
310
|
break
|
|
309
|
-
#else:
|
|
310
|
-
#
|
|
311
|
-
# print(f"Inject template not found at: {path}")
|
|
312
311
|
|
|
313
312
|
# Check override templates
|
|
314
313
|
override_paths = [
|
|
@@ -323,8 +322,16 @@ async def load_plugin_templates(page_name, plugins):
|
|
|
323
322
|
# Load template content with translation support
|
|
324
323
|
content = load_template_with_translation(path)
|
|
325
324
|
if content:
|
|
326
|
-
#
|
|
327
|
-
|
|
325
|
+
# Detect top-of-file pragma to assume unspecified blocks are blank
|
|
326
|
+
# Accepted forms (case-insensitive):
|
|
327
|
+
# {# assume-blank #}, {# assume_blank #}, {# assume-blank: true #}, {# assume_blank: true #}
|
|
328
|
+
assume_blank = False
|
|
329
|
+
head = content[:2048]
|
|
330
|
+
pragma_re = re.compile(r"^\s*\{#\s*(assume[-_]blank)(?:\s*true)?\s*#\}\s*", re.IGNORECASE | re.MULTILINE)
|
|
331
|
+
if pragma_re.search(head):
|
|
332
|
+
assume_blank = True
|
|
333
|
+
content = pragma_re.sub("", content, count=1)
|
|
334
|
+
templates.append({'type': 'override', 'template': env.from_string(content), 'assume_blank': assume_blank})
|
|
328
335
|
break
|
|
329
336
|
|
|
330
337
|
except Exception as e:
|
|
@@ -332,7 +339,7 @@ async def load_plugin_templates(page_name, plugins):
|
|
|
332
339
|
continue
|
|
333
340
|
return templates
|
|
334
341
|
|
|
335
|
-
async def collect_content(template, blocks, template_type, data):
|
|
342
|
+
async def collect_content(template, blocks, template_type, data, assume_blank=False):
|
|
336
343
|
"""Collect content from child templates.
|
|
337
344
|
|
|
338
345
|
Args:
|
|
@@ -340,19 +347,30 @@ async def collect_content(template, blocks, template_type, data):
|
|
|
340
347
|
blocks (list): List of block names
|
|
341
348
|
template_type (str): Type of template ('inject' or 'override')
|
|
342
349
|
data (dict): Template context data
|
|
350
|
+
assume_blank (bool): If True and type is 'override', unspecified blocks are blanked
|
|
343
351
|
|
|
344
352
|
Returns:
|
|
345
353
|
dict: Collected content by block
|
|
346
354
|
"""
|
|
347
355
|
content = {block: {'inject': [], 'override': None} for block in blocks}
|
|
356
|
+
|
|
357
|
+
# Get blocks that are actually defined in this template
|
|
358
|
+
defined_blocks = set(template.blocks.keys())
|
|
359
|
+
|
|
348
360
|
for block in blocks:
|
|
349
|
-
if block in
|
|
361
|
+
if block in defined_blocks:
|
|
362
|
+
# Block is explicitly defined in the template
|
|
350
363
|
block_content = ''.join(template.blocks[block](template.new_context(data)))
|
|
351
|
-
|
|
364
|
+
|
|
352
365
|
if template_type == 'override':
|
|
353
366
|
content[block]['override'] = block_content
|
|
354
367
|
else:
|
|
355
368
|
content[block]['inject'].append(block_content)
|
|
369
|
+
elif template_type == 'override' and assume_blank:
|
|
370
|
+
# Block is NOT defined in override template, but assume_blank is True
|
|
371
|
+
# So we treat it as if it was defined but empty
|
|
372
|
+
content[block]['override'] = ''
|
|
373
|
+
|
|
356
374
|
return content
|
|
357
375
|
|
|
358
376
|
async def render_combined_template(page_name, plugins, context):
|
|
@@ -366,6 +384,35 @@ async def render_combined_template(page_name, plugins, context):
|
|
|
366
384
|
Returns:
|
|
367
385
|
str: Rendered HTML
|
|
368
386
|
"""
|
|
387
|
+
# Check for assume-blank pragma and render directly if found
|
|
388
|
+
for plugin in plugins:
|
|
389
|
+
plugin_path = get_plugin_path(plugin)
|
|
390
|
+
if not plugin_path:
|
|
391
|
+
continue
|
|
392
|
+
|
|
393
|
+
last_part = plugin_path.split('/')[-1]
|
|
394
|
+
override_paths = [
|
|
395
|
+
os.path.join(plugin_path, 'override', f'{page_name}.jinja2'),
|
|
396
|
+
os.path.join(plugin_path, 'src', plugin, 'override', f'{page_name}.jinja2'),
|
|
397
|
+
os.path.join(plugin_path, 'src', 'override', f'{page_name}.jinja2'),
|
|
398
|
+
os.path.join(plugin_path, 'src', last_part, 'override', f'{page_name}.jinja2')
|
|
399
|
+
]
|
|
400
|
+
|
|
401
|
+
for path in override_paths:
|
|
402
|
+
if os.path.exists(path):
|
|
403
|
+
content = load_template_with_translation(path)
|
|
404
|
+
if content:
|
|
405
|
+
# Check for assume-blank pragma
|
|
406
|
+
head = content[:2048]
|
|
407
|
+
pragma_re = re.compile(r"^\s*\{#\s*(assume[-_]blank)(?:\s*true)?\s*#\}\s*", re.IGNORECASE | re.MULTILINE)
|
|
408
|
+
if pragma_re.search(head):
|
|
409
|
+
# Found assume-blank! Just render this template directly
|
|
410
|
+
print(f"Found assume-blank pragma in {path}, rendering directly without parent")
|
|
411
|
+
content = pragma_re.sub("", content, count=1) # Remove pragma
|
|
412
|
+
template = env.from_string(content)
|
|
413
|
+
return template.render(**context) # Return early!
|
|
414
|
+
|
|
415
|
+
# If no assume-blank pragma found, continue with normal processing
|
|
369
416
|
# Load parent template with translation support
|
|
370
417
|
parent_template = None
|
|
371
418
|
parent_template_path = None
|
|
@@ -410,21 +457,23 @@ async def render_combined_template(page_name, plugins, context):
|
|
|
410
457
|
|
|
411
458
|
for child_template_info in child_templates:
|
|
412
459
|
print("calling collect_content")
|
|
460
|
+
# Pass assume_blank flag to collect_content
|
|
413
461
|
child_content = await collect_content(
|
|
414
462
|
child_template_info['template'],
|
|
415
463
|
parent_blocks,
|
|
416
464
|
child_template_info['type'],
|
|
417
|
-
context
|
|
465
|
+
context,
|
|
466
|
+
child_template_info.get('assume_blank', False)
|
|
418
467
|
)
|
|
419
468
|
for block, content in child_content.items():
|
|
420
|
-
if content['override']:
|
|
469
|
+
if content['override'] is not None: # Check for None specifically, empty string is valid
|
|
421
470
|
all_content[block]['override'] = content['override']
|
|
422
471
|
else:
|
|
423
472
|
all_content[block]['inject'].extend(content['inject'])
|
|
424
473
|
|
|
425
474
|
combined_template_str = '{% extends layout_template %}\n'
|
|
426
475
|
for block in all_content:
|
|
427
|
-
if all_content[block]['override']:
|
|
476
|
+
if all_content[block]['override'] is not None: # Check for None, empty string is valid override
|
|
428
477
|
combined_template_str += f'{{% block {block} %}}\n {{{{ combined_{block}_override|safe }}}}\n{{% endblock %}}\n'
|
|
429
478
|
else:
|
|
430
479
|
combined_template_str += f'{{% block {block} %}}\n {{{{ super() }}}}\n {{{{ combined_{block}_inject|safe }}}}\n{{% endblock %}}\n'
|
|
@@ -446,7 +495,7 @@ async def render_combined_template(page_name, plugins, context):
|
|
|
446
495
|
else:
|
|
447
496
|
combined_inject[f'combined_{block}_inject'] = ''
|
|
448
497
|
|
|
449
|
-
if 'override' in content and content['override']:
|
|
498
|
+
if 'override' in content and content['override'] is not None:
|
|
450
499
|
combined_override[f'combined_{block}_override'] = content['override']
|
|
451
500
|
|
|
452
501
|
print("in render combined, context is", context)
|
|
@@ -1702,7 +1702,7 @@ mindroot/coreplugins/index/static/js/lit-html/node/directives/until.js.map,sha25
|
|
|
1702
1702
|
mindroot/coreplugins/index/static/js/lit-html/node/directives/when.js,sha256=NLe0NJ-6jqjVDUrT_DzmSpREsRaLo1yarzdYcV_5xHY,181
|
|
1703
1703
|
mindroot/coreplugins/index/static/js/lit-html/node/directives/when.js.map,sha256=tOonih_-EaqrunhNGshA9xN--WIVdGikjg8MkVp0itQ,1534
|
|
1704
1704
|
mindroot/coreplugins/jwt_auth/__init__.py,sha256=qFCBnx0oAKTtMSXiPEa7VXOIlWDTU-5CY0XvodgSUlM,79
|
|
1705
|
-
mindroot/coreplugins/jwt_auth/middleware.py,sha256=
|
|
1705
|
+
mindroot/coreplugins/jwt_auth/middleware.py,sha256=Qo_VFxASF2cmgL7OFPtBMYFBYhFVRnqBlipad14uYf0,10917
|
|
1706
1706
|
mindroot/coreplugins/jwt_auth/mod.py,sha256=XqvAwBQVga-foEkziDJnQtISq1NwYcXXuvVRKeewfAQ,2070
|
|
1707
1707
|
mindroot/coreplugins/jwt_auth/role_checks.py,sha256=bruZIIBSOvXNWB1YZ2s5btrbbXNf18w6MdORpJByV60,1555
|
|
1708
1708
|
mindroot/coreplugins/jwt_auth/router.py,sha256=ecXYao_UG33UjQF15Hi-tf_X0eFsqLEldyqGpt7JNSw,1162
|
|
@@ -2175,6 +2175,11 @@ mindroot/docs/data/providers.json,sha256=FPmY5qVOrBy_Z4RgDJWQwLwxd-zWWI83nnAE6z5
|
|
|
2175
2175
|
mindroot/docs/data/agents/local/Assistant/agent.json,sha256=P4CaQpQaUTwx0PoyV9bCJHvfvANsFyBZlNcMtVlxM3M,1281
|
|
2176
2176
|
mindroot/docs/data/agents/local/SysAdmin/agent.json,sha256=wkZvJbqM153Gr0cnt531F_XndV5DXt6dkkYnXH6x91c,2864
|
|
2177
2177
|
mindroot/docs/data/mcp/servers.json,sha256=UrHgExs_P05yehMPSa-FDSGHmjCmYABJ5BdW0_SOXXY,174
|
|
2178
|
+
mindroot/docs/example_plugins/override_home/plugin_info.json,sha256=z0k6KgqfMbN5Oagfq0-PemvdsM91lHIFahL756_0jcY,157
|
|
2179
|
+
mindroot/docs/example_plugins/override_home/src/override_home/__init__.py,sha256=MsSFjiLMLJZ7QhUPpVBWKiyDnCzryquRyr329NoCACI,2
|
|
2180
|
+
mindroot/docs/example_plugins/override_home/src/override_home/override/home.jinja2,sha256=emyKqeNUxSH8YGUU4iLQM7xOBrJ4PvnZXgZ4lS7iw0s,513
|
|
2181
|
+
mindroot/docs/example_plugins/run_task/plugin_info.json,sha256=RxeUhDKG0M23MaxNmwiqE_NFjrohp8k8cxQBHfIhujM,195
|
|
2182
|
+
mindroot/docs/example_plugins/run_task/src/run_task/override/home.jinja2,sha256=AovNqm8NeUbZcGjldjaxqg-HqTfq7cHrE_ugYLevXCc,1535
|
|
2178
2183
|
mindroot/docs/personas/local/Assistant/avatar.png,sha256=AsT2_jjGpZvEhzTEwSVhEShSYaIBhcUDrlj_bAG_HVY,1169266
|
|
2179
2184
|
mindroot/docs/personas/local/Assistant/faceref.png,sha256=AsT2_jjGpZvEhzTEwSVhEShSYaIBhcUDrlj_bAG_HVY,1169266
|
|
2180
2185
|
mindroot/docs/personas/local/Assistant/persona.json,sha256=FFOTyWMozCPM62Dn7MXwZUJIoNRkKbEzvpH8q_YTDgs,437
|
|
@@ -2224,7 +2229,7 @@ mindroot/lib/plugins_install.py,sha256=CUDkdDhIKkwN3U1hfKaTq8QUwGApFrNKmt3iycZuT
|
|
|
2224
2229
|
mindroot/lib/route_decorators.py,sha256=d0sE6BnEolmSuwe3khenDmUiyeiPklNuaMFE6roH6sk,2206
|
|
2225
2230
|
mindroot/lib/session_files.py,sha256=yY8TKfJPGZoK4yAy3WbfrJ7I5xL6NfDJmIICH6qC7Bw,1167
|
|
2226
2231
|
mindroot/lib/streamcmd.py,sha256=f9n3OtryEkMbNNuFr5BAZn1EpSLUKuDZw-zpo97XxJk,4714
|
|
2227
|
-
mindroot/lib/templates.py,sha256=
|
|
2232
|
+
mindroot/lib/templates.py,sha256=JZZiEuD3jLeiXR1k8IUzBPolIcZ16Xb-dKdTYSIqHNw,25049
|
|
2228
2233
|
mindroot/lib/token_counter.py,sha256=6k6nq2oCjJ4XiWVp89vYEdMTmfRb4ejEcpjK-vXcI6w,7607
|
|
2229
2234
|
mindroot/lib/auth/__init__.py,sha256=5EZbCTcdlnTHYE0JNk8znWNSO7mOsokMOvRBjb5Mq-M,49
|
|
2230
2235
|
mindroot/lib/auth/api_key.py,sha256=jlihhB94rsNVcXS-Gqmh7ADMwUbgROA84zPW7aOkfJw,875
|
|
@@ -2268,9 +2273,9 @@ mindroot/protocols/services/stream_chat.py,sha256=fMnPfwaB5fdNMBLTEg8BXKAGvrELKH
|
|
|
2268
2273
|
mindroot/registry/__init__.py,sha256=40Xy9bmPHsgdIrOzbtBGzf4XMqXVi9P8oZTJhn0r654,151
|
|
2269
2274
|
mindroot/registry/component_manager.py,sha256=WZFNPg4SNvpqsM5NFiC2DpgmrJQCyR9cNhrCBpp30Qk,995
|
|
2270
2275
|
mindroot/registry/data_access.py,sha256=81In5TwETpaqnnY1_-tBQM7rfWvUxZUZkG7lEelRUfU,5321
|
|
2271
|
-
mindroot-9.
|
|
2272
|
-
mindroot-9.
|
|
2273
|
-
mindroot-9.
|
|
2274
|
-
mindroot-9.
|
|
2275
|
-
mindroot-9.
|
|
2276
|
-
mindroot-9.
|
|
2276
|
+
mindroot-9.21.0.dist-info/licenses/LICENSE,sha256=8plAmZh8y9ccuuqFFz4kp7G-cO_qsPgAOoHNvabSB4U,1070
|
|
2277
|
+
mindroot-9.21.0.dist-info/METADATA,sha256=mjUORZGKFy7pobyw5GmSCad2UfOM0kuqJDjmuel3OUc,1035
|
|
2278
|
+
mindroot-9.21.0.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
|
2279
|
+
mindroot-9.21.0.dist-info/entry_points.txt,sha256=0bpyjMccLttx6VcjDp6zfJPN0Kk0rffor6IdIbP0j4c,50
|
|
2280
|
+
mindroot-9.21.0.dist-info/top_level.txt,sha256=gwKm7DmNjhdrCJTYCrxa9Szne4lLpCtrEBltfsX-Mm8,9
|
|
2281
|
+
mindroot-9.21.0.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|