mindroot 9.2.0__py3-none-any.whl → 9.5.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.
- mindroot/coreplugins/admin/__init__.py +3 -1
- mindroot/coreplugins/admin/agent_router.py +250 -7
- mindroot/coreplugins/admin/asset_manager.py +164 -0
- mindroot/coreplugins/admin/command_router.py +236 -1
- mindroot/coreplugins/admin/mcp_catalog_routes.py +156 -0
- mindroot/coreplugins/admin/mcp_publish_routes.py +450 -0
- mindroot/coreplugins/admin/mcp_registry_routes.py +495 -0
- mindroot/coreplugins/admin/mcp_routes.py +216 -0
- mindroot/coreplugins/admin/mod.py +62 -0
- mindroot/coreplugins/admin/oauth_callback_router.py +84 -0
- mindroot/coreplugins/admin/persona_handler.py +15 -6
- mindroot/coreplugins/admin/persona_router.py +158 -2
- mindroot/coreplugins/admin/plugin_manager.py +63 -0
- mindroot/coreplugins/admin/plugin_router.py +1 -1
- mindroot/coreplugins/admin/plugin_router_fixed.py +23 -0
- mindroot/coreplugins/admin/plugin_router_new_not_working.py +145 -0
- mindroot/coreplugins/admin/plugin_routes.py +114 -0
- mindroot/coreplugins/admin/registry_settings_routes.py +140 -0
- mindroot/coreplugins/admin/router.py +116 -15
- mindroot/coreplugins/admin/service_models.py +1 -1
- mindroot/coreplugins/admin/settings_router.py +1 -0
- mindroot/coreplugins/admin/static/css/admin-custom.css +357 -2
- mindroot/coreplugins/admin/static/css/dark.css +1 -0
- mindroot/coreplugins/admin/static/css/default.css +4 -0
- mindroot/coreplugins/admin/static/js/about-info.js +367 -0
- mindroot/coreplugins/admin/static/js/agent-form.js +83 -3
- mindroot/coreplugins/admin/static/js/api-key-script.js +307 -0
- mindroot/coreplugins/admin/static/js/mcp-manager.js +348 -0
- mindroot/coreplugins/admin/static/js/mcp-publisher.js +780 -0
- mindroot/coreplugins/admin/static/js/persona-editor.js +34 -5
- mindroot/coreplugins/admin/static/js/plugin-toggle.js +1 -1
- mindroot/coreplugins/admin/static/js/recommended-plugin-install.js +63 -0
- mindroot/coreplugins/admin/static/js/registry-auth-section.js +132 -0
- mindroot/coreplugins/admin/static/js/registry-manager-base.js +613 -0
- mindroot/coreplugins/admin/static/js/registry-manager-old.js +385 -0
- mindroot/coreplugins/admin/static/js/registry-manager-publish-old-delete.js +166 -0
- mindroot/coreplugins/admin/static/js/registry-manager.js +351 -0
- mindroot/coreplugins/admin/static/js/registry-publish-section.js +377 -0
- mindroot/coreplugins/admin/static/js/registry-search-section.js +400 -0
- mindroot/coreplugins/admin/static/js/registry-search-section.js.bak +3 -0
- mindroot/coreplugins/admin/static/js/registry-settings.js +69 -0
- mindroot/coreplugins/admin/static/js/registry-shared-services.js +857 -0
- mindroot/coreplugins/admin/static/js/registry-simple-sections.js +85 -0
- mindroot/coreplugins/admin/static/js/secure-widget-manager.js +438 -0
- mindroot/coreplugins/admin/static/logo.png +0 -0
- mindroot/coreplugins/admin/templates/admin.jinja2 +275 -110
- mindroot/coreplugins/agent/Assistant/agent.json +27 -11
- mindroot/coreplugins/agent/agent.py +2 -2
- mindroot/coreplugins/agent/command_parser.py +25 -10
- mindroot/coreplugins/agent/templates/system.jinja2 +0 -12
- mindroot/coreplugins/chat/__init__.py +4 -1
- mindroot/coreplugins/chat/router.py +132 -20
- mindroot/coreplugins/chat/router_dedup_patch.py +20 -0
- mindroot/coreplugins/chat/services.py +31 -1
- mindroot/coreplugins/chat/static/css/action-fix.css +32 -0
- mindroot/coreplugins/chat/static/css/admin-custom.css +5 -3
- mindroot/coreplugins/chat/static/css/dark.css +24 -3
- mindroot/coreplugins/chat/static/css/default.css +24 -3
- mindroot/coreplugins/chat/static/css/main.css +1 -0
- mindroot/coreplugins/chat/static/js/action.js +137 -60
- mindroot/coreplugins/chat/static/js/chat-history.js +3 -0
- mindroot/coreplugins/chat/static/js/chat.js +59 -16
- mindroot/coreplugins/chat/static/js/chat.js.diff +221 -0
- mindroot/coreplugins/chat/static/js/chatform.js +2 -2
- mindroot/coreplugins/chat/static/site.webmanifest +1 -1
- mindroot/coreplugins/chat/templates/chat.jinja2 +3 -3
- mindroot/coreplugins/chat/widget_manager.py +139 -0
- mindroot/coreplugins/chat/widget_routes.py +287 -0
- mindroot/coreplugins/check_list/inject/admin.jinja2 +1 -1
- mindroot/coreplugins/email/__init__.py +2 -0
- mindroot/coreplugins/email/email_provider.py +2 -2
- mindroot/coreplugins/email/mod.py +100 -0
- mindroot/coreplugins/email/services.py +5 -3
- mindroot/coreplugins/email/smtp_handler.py +9 -3
- mindroot/coreplugins/email/test_email_service.py +75 -0
- mindroot/coreplugins/env_manager/mod.py +61 -25
- mindroot/coreplugins/home/router.py +37 -2
- mindroot/coreplugins/home/static/imgs/logo.png +0 -0
- mindroot/coreplugins/home/static/imgs/logo.png.bak +0 -0
- mindroot/coreplugins/home/static/imgs/logo_teal.png +0 -0
- mindroot/coreplugins/home/static/imgs/logo_teal2.png +0 -0
- mindroot/coreplugins/home/static/imgs/logo_teal_detailed.png +0 -0
- mindroot/coreplugins/home/static/imgs/logo_teal_python.png +0 -0
- mindroot/coreplugins/home/templates/home.jinja2 +15 -6
- mindroot/coreplugins/index/handlers/plugin_ops.py +1 -1
- mindroot/coreplugins/index/indices/default/index.json +6 -6
- mindroot/coreplugins/jwt_auth/middleware.py +47 -1
- mindroot/coreplugins/jwt_auth/mod.py +40 -17
- mindroot/coreplugins/l8n/__init__.py +6 -0
- mindroot/coreplugins/l8n/debug_loader.py +85 -0
- mindroot/coreplugins/l8n/debug_middleware.py +74 -0
- mindroot/coreplugins/l8n/l8n_constants.py +19 -0
- mindroot/coreplugins/l8n/language_detection.py +183 -0
- mindroot/coreplugins/l8n/middleware.py +151 -0
- mindroot/coreplugins/l8n/mod.py +277 -0
- mindroot/coreplugins/l8n/monkey_patch_to_delete.py +186 -0
- mindroot/coreplugins/l8n/test_enhanced.py +298 -0
- mindroot/coreplugins/l8n/test_l8n.py +95 -0
- mindroot/coreplugins/l8n/test_l8n_standalone.py +251 -0
- mindroot/coreplugins/l8n/test_middleware.py +272 -0
- mindroot/coreplugins/l8n/utils.py +232 -0
- mindroot/coreplugins/mcp_/__init__.py +14 -0
- mindroot/coreplugins/mcp_/catalog_commands.py +328 -0
- mindroot/coreplugins/mcp_/catalog_manager.py +263 -0
- mindroot/coreplugins/mcp_/dynamic_commands.py +154 -0
- mindroot/coreplugins/mcp_/mcp_manager.py +1031 -0
- mindroot/coreplugins/mcp_/mod.py +367 -0
- mindroot/coreplugins/mcp_/oauth_storage.py +144 -0
- mindroot/coreplugins/mcp_/server_installer.py +79 -0
- mindroot/coreplugins/mcp_/setup.py +26 -0
- mindroot/coreplugins/mcp_/test_dynamic_commands.py +134 -0
- mindroot/coreplugins/mcp_/testmcpclient.py +92 -0
- mindroot/coreplugins/persona/mod.py +12 -7
- mindroot/coreplugins/signup/templates/signup.jinja2 +1 -1
- mindroot/coreplugins/subscriptions/__init__.py +1 -0
- mindroot/coreplugins/subscriptions/mod.py +14 -3
- mindroot/coreplugins/subscriptions/router.py +3 -0
- mindroot/coreplugins/user_service/__init__.py +1 -2
- mindroot/coreplugins/user_service/admin_init.py +1 -0
- mindroot/coreplugins/user_service/email_service.py +72 -17
- mindroot/coreplugins/user_service/mod.py +10 -2
- mindroot/coreplugins/user_service/password_reset_service.py +180 -27
- mindroot/coreplugins/user_service/router.py +84 -22
- mindroot/lib/auth/api_key.py +28 -0
- mindroot/lib/cli/plugins.py +94 -0
- mindroot/lib/plugins/default_plugin_manifest.json +20 -0
- mindroot/lib/plugins/installation.py +5 -5
- mindroot/lib/plugins/l8n_static_handler.py +225 -0
- mindroot/lib/plugins/loader.py +33 -3
- mindroot/lib/plugins/loader_with_l8n.py +281 -0
- mindroot/lib/plugins/manifest.py +238 -17
- mindroot/lib/providers/commands.py +3 -1
- mindroot/lib/route_decorators.py +5 -5
- mindroot/lib/templates.py +183 -11
- mindroot/lib/utils/merge_arrays.py +1 -1
- mindroot/migrate.py +49 -0
- mindroot/registry/data_access.py +1 -1
- mindroot/server.py +47 -13
- mindroot/server_missing_normal_args.py +197 -0
- mindroot/server_prev.py +173 -0
- {mindroot-9.2.0.dist-info → mindroot-9.5.0.dist-info}/METADATA +7 -2
- {mindroot-9.2.0.dist-info → mindroot-9.5.0.dist-info}/RECORD +147 -114
- mindroot/coreplugins/admin/static/favicon/about.txt +0 -6
- mindroot/coreplugins/admin/static/favicon/android-chrome-512x512.png +0 -0
- mindroot/coreplugins/admin/static/favicon/apple-touch-icon.png +0 -0
- mindroot/coreplugins/admin/static/favicon/favicon-16x16.png +0 -0
- mindroot/coreplugins/admin/static/favicon/favicon-32x32.png +0 -0
- mindroot/coreplugins/admin/static/favicon/favicon.ico +0 -0
- mindroot/coreplugins/admin/static/favicon/favicon_io (1)/about.txt +0 -6
- mindroot/coreplugins/admin/static/favicon/favicon_io (1)/android-chrome-192x192.png +0 -0
- mindroot/coreplugins/admin/static/favicon/favicon_io (1)/android-chrome-512x512.png +0 -0
- mindroot/coreplugins/admin/static/favicon/favicon_io (1)/apple-touch-icon.png +0 -0
- mindroot/coreplugins/admin/static/favicon/favicon_io (1)/favicon-16x16.png +0 -0
- mindroot/coreplugins/admin/static/favicon/favicon_io (1)/favicon-32x32.png +0 -0
- mindroot/coreplugins/admin/static/favicon/favicon_io (1)/favicon.ico +0 -0
- mindroot/coreplugins/admin/static/favicon/favicon_io (1)/site.webmanifest +0 -1
- mindroot/coreplugins/admin/static/favicon/logo.png +0 -0
- mindroot/coreplugins/admin/static/favicon/site.webmanifest +0 -1
- mindroot/coreplugins/admin/static/js/backup/agent-editor.js +0 -186
- mindroot/coreplugins/admin/static/js/backup/agent-form.js +0 -1133
- mindroot/coreplugins/admin/static/js/backup/agent-list.js +0 -94
- mindroot/coreplugins/chat/static/favicon/about.txt +0 -6
- mindroot/coreplugins/chat/static/favicon/android-chrome-192x192.png +0 -0
- mindroot/coreplugins/chat/static/favicon/android-chrome-512x512.png +0 -0
- mindroot/coreplugins/chat/static/favicon/apple-touch-icon.png +0 -0
- mindroot/coreplugins/chat/static/favicon/favicon-16x16.png +0 -0
- mindroot/coreplugins/chat/static/favicon/favicon-32x32.png +0 -0
- mindroot/coreplugins/chat/static/favicon/favicon.ico +0 -0
- mindroot/coreplugins/chat/static/favicon/favicon_io (1)/about.txt +0 -6
- mindroot/coreplugins/chat/static/favicon/favicon_io (1)/android-chrome-192x192.png +0 -0
- mindroot/coreplugins/chat/static/favicon/favicon_io (1)/android-chrome-512x512.png +0 -0
- mindroot/coreplugins/chat/static/favicon/favicon_io (1)/apple-touch-icon.png +0 -0
- mindroot/coreplugins/chat/static/favicon/favicon_io (1)/favicon-16x16.png +0 -0
- mindroot/coreplugins/chat/static/favicon/favicon_io (1)/favicon-32x32.png +0 -0
- mindroot/coreplugins/chat/static/favicon/favicon_io (1)/favicon.ico +0 -0
- mindroot/coreplugins/chat/static/favicon/favicon_io (1)/site.webmanifest +0 -1
- mindroot/coreplugins/chat/static/favicon/logo.png +0 -0
- mindroot/coreplugins/chat/static/favicon/site.webmanifest +0 -1
- mindroot/coreplugins/index/default.json +0 -76
- mindroot/coreplugins/user_service/file_trigger_service.py +0 -72
- mindroot/coreplugins/user_service/hooks.py +0 -23
- /mindroot/coreplugins/{admin/static/favicon/android-chrome-192x192.png → home/static/imgs/backuplogo.png} +0 -0
- {mindroot-9.2.0.dist-info → mindroot-9.5.0.dist-info}/WHEEL +0 -0
- {mindroot-9.2.0.dist-info → mindroot-9.5.0.dist-info}/entry_points.txt +0 -0
- {mindroot-9.2.0.dist-info → mindroot-9.5.0.dist-info}/licenses/LICENSE +0 -0
- {mindroot-9.2.0.dist-info → mindroot-9.5.0.dist-info}/top_level.txt +0 -0
mindroot/server.py
CHANGED
|
@@ -8,12 +8,18 @@ from .lib.chatcontext import ChatContext
|
|
|
8
8
|
from .lib.providers.hooks import hook_manager
|
|
9
9
|
from .lib.utils.debug import debug_box
|
|
10
10
|
import asyncio
|
|
11
|
+
import sys
|
|
11
12
|
import uvicorn
|
|
12
13
|
from termcolor import colored
|
|
13
14
|
import socket
|
|
14
15
|
from fastapi.middleware.cors import CORSMiddleware
|
|
15
16
|
from starlette.middleware.base import BaseHTTPMiddleware
|
|
17
|
+
from .lib.cli.plugins import install_plugins_from_cli
|
|
16
18
|
from dotenv import load_dotenv
|
|
19
|
+
from .migrate import run_migrations
|
|
20
|
+
|
|
21
|
+
# import for file copy
|
|
22
|
+
from shutil import copyfile
|
|
17
23
|
|
|
18
24
|
# Load environment variables from .env file at the start
|
|
19
25
|
# Set override=True to make .env variables override existing environment variables
|
|
@@ -21,11 +27,25 @@ load_dotenv(override=True)
|
|
|
21
27
|
|
|
22
28
|
def parse_args():
|
|
23
29
|
import argparse
|
|
24
|
-
parser = argparse.ArgumentParser(description="Run the server")
|
|
30
|
+
parser = argparse.ArgumentParser(description="Run the MindRoot server or manage plugins.", allow_abbrev=False)
|
|
31
|
+
|
|
32
|
+
# Server arguments are top-level
|
|
25
33
|
parser.add_argument("-p", "--port", type=int, help="Port to run the server on")
|
|
26
|
-
# need to include optional admin-user and admin-password
|
|
27
34
|
parser.add_argument("-u", "--admin-user", type=str, help="Admin username")
|
|
28
35
|
parser.add_argument("-pw", "--admin-password", type=str, help="Admin password")
|
|
36
|
+
|
|
37
|
+
subparsers = parser.add_subparsers(dest='command', help='sub-command help')
|
|
38
|
+
|
|
39
|
+
# Explicit 'server' command for clarity in help, but it's the default action
|
|
40
|
+
server_parser = subparsers.add_parser('server', help='Run the web server (default action)')
|
|
41
|
+
|
|
42
|
+
# Plugin command group
|
|
43
|
+
plugin_parser = subparsers.add_parser('plugin', help='Manage plugins')
|
|
44
|
+
plugin_subparsers = plugin_parser.add_subparsers(dest='plugin_command', required=True)
|
|
45
|
+
install_parser = plugin_subparsers.add_parser('install', help='Install or update one or more plugins')
|
|
46
|
+
install_parser.add_argument('plugins', nargs='+', help='List of plugins to install (e.g., runvnc/plugin-name)')
|
|
47
|
+
install_parser.add_argument('--reinstall', action='store_true', help='Force reinstall of the plugin if it already exists.')
|
|
48
|
+
|
|
29
49
|
return parser.parse_args()
|
|
30
50
|
|
|
31
51
|
def get_project_root():
|
|
@@ -35,6 +55,7 @@ def get_project_root():
|
|
|
35
55
|
def create_directories():
|
|
36
56
|
root = get_project_root()
|
|
37
57
|
directories = [
|
|
58
|
+
"data",
|
|
38
59
|
"imgs",
|
|
39
60
|
"models",
|
|
40
61
|
"models/face",
|
|
@@ -66,10 +87,13 @@ async def setup_app_internal(app_):
|
|
|
66
87
|
app = app_
|
|
67
88
|
|
|
68
89
|
root = get_project_root()
|
|
90
|
+
source_root = Path(__file__).parent
|
|
69
91
|
await plugins.load(app=app)
|
|
70
92
|
app.mount("/static", StaticFiles(directory=str(root / "static"), follow_symlink=True), name="static")
|
|
71
93
|
app.mount("/imgs", StaticFiles(directory=str(root / "imgs"), follow_symlink=True), name="imgs")
|
|
72
|
-
|
|
94
|
+
if not os.path.exists(root / "imgs/logo.png"):
|
|
95
|
+
print(colored("No logo found, copying default logo from coreplugins", "yellow"))
|
|
96
|
+
copyfile(str(source_root / "coreplugins/home/static/imgs/logo.png"), str(root / "imgs/logo.png"))
|
|
73
97
|
return app
|
|
74
98
|
|
|
75
99
|
def is_port_in_use(port):
|
|
@@ -95,28 +119,38 @@ class HeaderMiddleware(BaseHTTPMiddleware):
|
|
|
95
119
|
|
|
96
120
|
# Add security headers
|
|
97
121
|
response.headers["X-Content-Type-Options"] = "nosniff"
|
|
98
|
-
|
|
122
|
+
|
|
123
|
+
#chat widgets don't work if we do this
|
|
124
|
+
if os.environ.get('MR_X_FRAME_SAMEORIGIN', 'false').lower() == 'true':
|
|
125
|
+
response.headers["X-Frame-Options"] = "SAMEORIGIN"
|
|
126
|
+
|
|
99
127
|
response.headers["X-XSS-Protection"] = "1; mode=block"
|
|
100
128
|
|
|
101
129
|
return response
|
|
102
130
|
|
|
103
131
|
def main():
|
|
104
132
|
global app
|
|
133
|
+
|
|
134
|
+
# Run migrations first, before anything else
|
|
135
|
+
run_migrations()
|
|
136
|
+
|
|
137
|
+
args = parse_args()
|
|
105
138
|
|
|
106
|
-
|
|
107
|
-
|
|
139
|
+
# If the command is 'plugin', handle it and exit.
|
|
140
|
+
if args.command == 'plugin':
|
|
141
|
+
if args.plugin_command == 'install':
|
|
142
|
+
asyncio.run(install_plugins_from_cli(args.plugins, reinstall=args.reinstall))
|
|
143
|
+
sys.exit(0)
|
|
144
|
+
|
|
145
|
+
# Default action: run the server. The server arguments are on the main 'args' object.
|
|
146
|
+
cmd_args = args
|
|
108
147
|
port = 8010
|
|
109
148
|
if cmd_args.port:
|
|
110
149
|
port = cmd_args.port
|
|
111
150
|
else:
|
|
112
|
-
cmd_args.port = port
|
|
113
|
-
|
|
114
|
-
app = FastAPI()
|
|
151
|
+
cmd_args.port = port
|
|
115
152
|
|
|
116
|
-
|
|
117
|
-
# CORSMiddleware,
|
|
118
|
-
# allow_origins=["*"] # This one line is all you need to allow all origins
|
|
119
|
-
#)
|
|
153
|
+
app = FastAPI()
|
|
120
154
|
|
|
121
155
|
app.state.cmd_args = cmd_args
|
|
122
156
|
|
|
@@ -0,0 +1,197 @@
|
|
|
1
|
+
from fastapi import FastAPI, Response, Request
|
|
2
|
+
from fastapi.staticfiles import StaticFiles
|
|
3
|
+
from fastapi.templating import Jinja2Templates
|
|
4
|
+
import os
|
|
5
|
+
from pathlib import Path
|
|
6
|
+
from .lib import plugins
|
|
7
|
+
from .lib.chatcontext import ChatContext
|
|
8
|
+
from .lib.providers.hooks import hook_manager
|
|
9
|
+
from .lib.utils.debug import debug_box
|
|
10
|
+
import asyncio
|
|
11
|
+
import uvicorn
|
|
12
|
+
import sys
|
|
13
|
+
from termcolor import colored
|
|
14
|
+
import socket
|
|
15
|
+
from fastapi.middleware.cors import CORSMiddleware
|
|
16
|
+
from starlette.middleware.base import BaseHTTPMiddleware
|
|
17
|
+
from .lib.cli.plugins import install_plugins_from_cli
|
|
18
|
+
from dotenv import load_dotenv
|
|
19
|
+
from .migrate import run_migrations
|
|
20
|
+
|
|
21
|
+
# import for file copy
|
|
22
|
+
from shutil import copyfile
|
|
23
|
+
|
|
24
|
+
# Load environment variables from .env file at the start
|
|
25
|
+
# Set override=True to make .env variables override existing environment variables
|
|
26
|
+
load_dotenv(override=True)
|
|
27
|
+
|
|
28
|
+
def parse_args():
|
|
29
|
+
import argparse
|
|
30
|
+
parser = argparse.ArgumentParser(description="Run the server")
|
|
31
|
+
subparsers = parser.add_subparsers(dest='command', help='sub-command help')
|
|
32
|
+
|
|
33
|
+
# Server command (default)
|
|
34
|
+
server_parser = subparsers.add_parser('server', help='Run the web server (default)')
|
|
35
|
+
server_parser.add_argument("-p", "--port", type=int, help="Port to run the server on")
|
|
36
|
+
server_parser.add_argument("-u", "--admin-user", type=str, help="Admin username")
|
|
37
|
+
server_parser.add_argument("-pw", "--admin-password", type=str, help="Admin password")
|
|
38
|
+
|
|
39
|
+
# Plugin command
|
|
40
|
+
plugin_parser = subparsers.add_parser('plugin', help='Manage plugins')
|
|
41
|
+
plugin_subparsers = plugin_parser.add_subparsers(dest='plugin_command', required=True)
|
|
42
|
+
install_parser = plugin_subparsers.add_parser('install', help='Install one or more plugins')
|
|
43
|
+
install_parser.add_argument('plugins', nargs='+', help='List of plugins to install (e.g., runvnc/plugin-name or pypi-package-name)')
|
|
44
|
+
|
|
45
|
+
return parser.parse_args()
|
|
46
|
+
|
|
47
|
+
def get_project_root():
|
|
48
|
+
return Path(os.getcwd())
|
|
49
|
+
#return Path(__file__).parent
|
|
50
|
+
|
|
51
|
+
def create_directories():
|
|
52
|
+
root = get_project_root()
|
|
53
|
+
directories = [
|
|
54
|
+
"data",
|
|
55
|
+
"imgs",
|
|
56
|
+
"models",
|
|
57
|
+
"models/face",
|
|
58
|
+
"models/llm",
|
|
59
|
+
"static/personas",
|
|
60
|
+
"personas",
|
|
61
|
+
"personas/local",
|
|
62
|
+
"personas/shared",
|
|
63
|
+
"data/sessions"
|
|
64
|
+
]
|
|
65
|
+
chatlog_dir = os.environ.get('CHATLOG_DIR', 'data/chat')
|
|
66
|
+
directories.append(chatlog_dir)
|
|
67
|
+
|
|
68
|
+
for directory in directories:
|
|
69
|
+
(root / directory).mkdir(parents=True, exist_ok=True)
|
|
70
|
+
|
|
71
|
+
create_directories()
|
|
72
|
+
|
|
73
|
+
import mimetypes
|
|
74
|
+
mimetypes.add_type('application/javascript', '.js')
|
|
75
|
+
mimetypes.add_type('text/css', '.css')
|
|
76
|
+
|
|
77
|
+
templates = None
|
|
78
|
+
app = None
|
|
79
|
+
failed_plugins = []
|
|
80
|
+
|
|
81
|
+
async def setup_app_internal(app_):
|
|
82
|
+
global app, templates
|
|
83
|
+
app = app_
|
|
84
|
+
|
|
85
|
+
root = get_project_root()
|
|
86
|
+
source_root = Path(__file__).parent
|
|
87
|
+
await plugins.load(app=app)
|
|
88
|
+
app.mount("/static", StaticFiles(directory=str(root / "static"), follow_symlink=True), name="static")
|
|
89
|
+
app.mount("/imgs", StaticFiles(directory=str(root / "imgs"), follow_symlink=True), name="imgs")
|
|
90
|
+
if not os.path.exists(root / "imgs/logo.png"):
|
|
91
|
+
print(colored("No logo found, copying default logo from coreplugins", "yellow"))
|
|
92
|
+
copyfile(str(source_root / "coreplugins/home/static/imgs/logo.png"), str(root / "imgs/logo.png"))
|
|
93
|
+
return app
|
|
94
|
+
|
|
95
|
+
def is_port_in_use(port):
|
|
96
|
+
with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
|
|
97
|
+
try:
|
|
98
|
+
s.bind(('0.0.0.0', port))
|
|
99
|
+
return False
|
|
100
|
+
except socket.error:
|
|
101
|
+
return True
|
|
102
|
+
|
|
103
|
+
def find_available_port(start_port=8010, max_attempts=100):
|
|
104
|
+
port = start_port
|
|
105
|
+
while port < start_port + max_attempts:
|
|
106
|
+
if not is_port_in_use(port):
|
|
107
|
+
return port
|
|
108
|
+
port += 1
|
|
109
|
+
raise RuntimeError(f"Could not find an available port after {max_attempts} attempts")
|
|
110
|
+
|
|
111
|
+
class HeaderMiddleware(BaseHTTPMiddleware):
|
|
112
|
+
async def dispatch(self, request: Request, call_next):
|
|
113
|
+
# First get the response from other middleware and routes
|
|
114
|
+
response = await call_next(request)
|
|
115
|
+
|
|
116
|
+
# Add security headers
|
|
117
|
+
response.headers["X-Content-Type-Options"] = "nosniff"
|
|
118
|
+
|
|
119
|
+
#chat widgets don't work if we do this
|
|
120
|
+
if os.environ.get('MR_X_FRAME_SAMEORIGIN', 'false').lower() == 'true':
|
|
121
|
+
response.headers["X-Frame-Options"] = "SAMEORIGIN"
|
|
122
|
+
|
|
123
|
+
response.headers["X-XSS-Protection"] = "1; mode=block"
|
|
124
|
+
|
|
125
|
+
return response
|
|
126
|
+
|
|
127
|
+
def main():
|
|
128
|
+
global app
|
|
129
|
+
|
|
130
|
+
# Run migrations first, before anything else
|
|
131
|
+
run_migrations()
|
|
132
|
+
|
|
133
|
+
args = parse_args()
|
|
134
|
+
|
|
135
|
+
# If no command is specified, default to 'server'
|
|
136
|
+
if args.command is None:
|
|
137
|
+
args.command = 'server'
|
|
138
|
+
|
|
139
|
+
if args.command == 'plugin' and args.plugin_command == 'install':
|
|
140
|
+
asyncio.run(install_plugins_from_cli(args.plugins))
|
|
141
|
+
sys.exit(0)
|
|
142
|
+
|
|
143
|
+
# Proceed with server startup
|
|
144
|
+
cmd_args = args
|
|
145
|
+
port = 8010
|
|
146
|
+
if cmd_args.port:
|
|
147
|
+
port = cmd_args.port
|
|
148
|
+
else:
|
|
149
|
+
# Add a default port to the args namespace if not provided
|
|
150
|
+
# to avoid AttributeError later.
|
|
151
|
+
setattr(cmd_args, 'port', port)
|
|
152
|
+
|
|
153
|
+
app = FastAPI()
|
|
154
|
+
|
|
155
|
+
#app.add_middleware(
|
|
156
|
+
# CORSMiddleware,
|
|
157
|
+
# allow_origins=["*"] # This one line is all you need to allow all origins
|
|
158
|
+
#)
|
|
159
|
+
|
|
160
|
+
app.state.cmd_args = cmd_args
|
|
161
|
+
|
|
162
|
+
debug_box("pre_load")
|
|
163
|
+
loop = asyncio.get_event_loop()
|
|
164
|
+
loop.run_until_complete(plugins.pre_load(app)) # middleware
|
|
165
|
+
|
|
166
|
+
debug_box("finished with pre_load, now calling uvicorn.run")
|
|
167
|
+
|
|
168
|
+
@app.on_event("startup")
|
|
169
|
+
async def setup_app():
|
|
170
|
+
global app
|
|
171
|
+
await setup_app_internal(app)
|
|
172
|
+
print(colored("Plugin setup complete", "green"))
|
|
173
|
+
|
|
174
|
+
@app.on_event("shutdown")
|
|
175
|
+
async def shutdown_event():
|
|
176
|
+
print("Shutting down MindRoot")
|
|
177
|
+
hook_manager.eject()
|
|
178
|
+
|
|
179
|
+
app.add_middleware(
|
|
180
|
+
CORSMiddleware,
|
|
181
|
+
allow_origins=["*"], # Replace with your specific origins for production
|
|
182
|
+
allow_credentials=True,
|
|
183
|
+
allow_methods=["*"], # Or specify: ["GET", "POST", "PUT", "DELETE", etc.]
|
|
184
|
+
allow_headers=["*"], # Or specify required headers
|
|
185
|
+
expose_headers=["*"] # Headers that browsers are allowed to access
|
|
186
|
+
)
|
|
187
|
+
|
|
188
|
+
app.add_middleware(HeaderMiddleware)
|
|
189
|
+
|
|
190
|
+
try:
|
|
191
|
+
print(colored(f"Starting server on port {port}", "green"))
|
|
192
|
+
uvicorn.run(app, host="0.0.0.0", port=port, lifespan="on", timeout_graceful_shutdown=2)
|
|
193
|
+
except Exception as e:
|
|
194
|
+
print(colored(f"Error starting server: {str(e)}", "red"))
|
|
195
|
+
|
|
196
|
+
if __name__ == "__main__":
|
|
197
|
+
main()
|
mindroot/server_prev.py
ADDED
|
@@ -0,0 +1,173 @@
|
|
|
1
|
+
from fastapi import FastAPI, Response, Request
|
|
2
|
+
from fastapi.staticfiles import StaticFiles
|
|
3
|
+
from fastapi.templating import Jinja2Templates
|
|
4
|
+
import os
|
|
5
|
+
from pathlib import Path
|
|
6
|
+
from .lib import plugins
|
|
7
|
+
from .lib.chatcontext import ChatContext
|
|
8
|
+
from .lib.providers.hooks import hook_manager
|
|
9
|
+
from .lib.utils.debug import debug_box
|
|
10
|
+
import asyncio
|
|
11
|
+
import uvicorn
|
|
12
|
+
from termcolor import colored
|
|
13
|
+
import socket
|
|
14
|
+
from fastapi.middleware.cors import CORSMiddleware
|
|
15
|
+
from starlette.middleware.base import BaseHTTPMiddleware
|
|
16
|
+
from dotenv import load_dotenv
|
|
17
|
+
from .migrate import run_migrations
|
|
18
|
+
|
|
19
|
+
# import for file copy
|
|
20
|
+
from shutil import copyfile
|
|
21
|
+
|
|
22
|
+
# Load environment variables from .env file at the start
|
|
23
|
+
# Set override=True to make .env variables override existing environment variables
|
|
24
|
+
load_dotenv(override=True)
|
|
25
|
+
|
|
26
|
+
def parse_args():
|
|
27
|
+
import argparse
|
|
28
|
+
parser = argparse.ArgumentParser(description="Run the server")
|
|
29
|
+
parser.add_argument("-p", "--port", type=int, help="Port to run the server on")
|
|
30
|
+
# need to include optional admin-user and admin-password
|
|
31
|
+
parser.add_argument("-u", "--admin-user", type=str, help="Admin username")
|
|
32
|
+
parser.add_argument("-pw", "--admin-password", type=str, help="Admin password")
|
|
33
|
+
return parser.parse_args()
|
|
34
|
+
|
|
35
|
+
def get_project_root():
|
|
36
|
+
return Path(os.getcwd())
|
|
37
|
+
#return Path(__file__).parent
|
|
38
|
+
|
|
39
|
+
def create_directories():
|
|
40
|
+
root = get_project_root()
|
|
41
|
+
directories = [
|
|
42
|
+
"data",
|
|
43
|
+
"imgs",
|
|
44
|
+
"models",
|
|
45
|
+
"models/face",
|
|
46
|
+
"models/llm",
|
|
47
|
+
"static/personas",
|
|
48
|
+
"personas",
|
|
49
|
+
"personas/local",
|
|
50
|
+
"personas/shared",
|
|
51
|
+
"data/sessions"
|
|
52
|
+
]
|
|
53
|
+
chatlog_dir = os.environ.get('CHATLOG_DIR', 'data/chat')
|
|
54
|
+
directories.append(chatlog_dir)
|
|
55
|
+
|
|
56
|
+
for directory in directories:
|
|
57
|
+
(root / directory).mkdir(parents=True, exist_ok=True)
|
|
58
|
+
|
|
59
|
+
create_directories()
|
|
60
|
+
|
|
61
|
+
import mimetypes
|
|
62
|
+
mimetypes.add_type('application/javascript', '.js')
|
|
63
|
+
mimetypes.add_type('text/css', '.css')
|
|
64
|
+
|
|
65
|
+
templates = None
|
|
66
|
+
app = None
|
|
67
|
+
failed_plugins = []
|
|
68
|
+
|
|
69
|
+
async def setup_app_internal(app_):
|
|
70
|
+
global app, templates
|
|
71
|
+
app = app_
|
|
72
|
+
|
|
73
|
+
root = get_project_root()
|
|
74
|
+
source_root = Path(__file__).parent
|
|
75
|
+
await plugins.load(app=app)
|
|
76
|
+
app.mount("/static", StaticFiles(directory=str(root / "static"), follow_symlink=True), name="static")
|
|
77
|
+
app.mount("/imgs", StaticFiles(directory=str(root / "imgs"), follow_symlink=True), name="imgs")
|
|
78
|
+
if not os.path.exists(root / "imgs/logo.png"):
|
|
79
|
+
print(colored("No logo found, copying default logo from coreplugins", "yellow"))
|
|
80
|
+
copyfile(str(source_root / "coreplugins/home/static/imgs/logo.png"), str(root / "imgs/logo.png"))
|
|
81
|
+
return app
|
|
82
|
+
|
|
83
|
+
def is_port_in_use(port):
|
|
84
|
+
with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
|
|
85
|
+
try:
|
|
86
|
+
s.bind(('0.0.0.0', port))
|
|
87
|
+
return False
|
|
88
|
+
except socket.error:
|
|
89
|
+
return True
|
|
90
|
+
|
|
91
|
+
def find_available_port(start_port=8010, max_attempts=100):
|
|
92
|
+
port = start_port
|
|
93
|
+
while port < start_port + max_attempts:
|
|
94
|
+
if not is_port_in_use(port):
|
|
95
|
+
return port
|
|
96
|
+
port += 1
|
|
97
|
+
raise RuntimeError(f"Could not find an available port after {max_attempts} attempts")
|
|
98
|
+
|
|
99
|
+
class HeaderMiddleware(BaseHTTPMiddleware):
|
|
100
|
+
async def dispatch(self, request: Request, call_next):
|
|
101
|
+
# First get the response from other middleware and routes
|
|
102
|
+
response = await call_next(request)
|
|
103
|
+
|
|
104
|
+
# Add security headers
|
|
105
|
+
response.headers["X-Content-Type-Options"] = "nosniff"
|
|
106
|
+
|
|
107
|
+
#chat widgets don't work if we do this
|
|
108
|
+
if os.environ.get('MR_X_FRAME_SAMEORIGIN', 'false').lower() == 'true':
|
|
109
|
+
response.headers["X-Frame-Options"] = "SAMEORIGIN"
|
|
110
|
+
|
|
111
|
+
response.headers["X-XSS-Protection"] = "1; mode=block"
|
|
112
|
+
|
|
113
|
+
return response
|
|
114
|
+
|
|
115
|
+
def main():
|
|
116
|
+
global app
|
|
117
|
+
|
|
118
|
+
# Run migrations first, before anything else
|
|
119
|
+
run_migrations()
|
|
120
|
+
|
|
121
|
+
cmd_args = parse_args()
|
|
122
|
+
# save ALL parsed args in app state
|
|
123
|
+
port = 8010
|
|
124
|
+
if cmd_args.port:
|
|
125
|
+
port = cmd_args.port
|
|
126
|
+
else:
|
|
127
|
+
cmd_args.port = port
|
|
128
|
+
|
|
129
|
+
app = FastAPI()
|
|
130
|
+
|
|
131
|
+
#app.add_middleware(
|
|
132
|
+
# CORSMiddleware,
|
|
133
|
+
# allow_origins=["*"] # This one line is all you need to allow all origins
|
|
134
|
+
#)
|
|
135
|
+
|
|
136
|
+
app.state.cmd_args = cmd_args
|
|
137
|
+
|
|
138
|
+
debug_box("pre_load")
|
|
139
|
+
loop = asyncio.get_event_loop()
|
|
140
|
+
loop.run_until_complete(plugins.pre_load(app)) # middleware
|
|
141
|
+
|
|
142
|
+
debug_box("finished with pre_load, now calling uvicorn.run")
|
|
143
|
+
|
|
144
|
+
@app.on_event("startup")
|
|
145
|
+
async def setup_app():
|
|
146
|
+
global app
|
|
147
|
+
await setup_app_internal(app)
|
|
148
|
+
print(colored("Plugin setup complete", "green"))
|
|
149
|
+
|
|
150
|
+
@app.on_event("shutdown")
|
|
151
|
+
async def shutdown_event():
|
|
152
|
+
print("Shutting down MindRoot")
|
|
153
|
+
hook_manager.eject()
|
|
154
|
+
|
|
155
|
+
app.add_middleware(
|
|
156
|
+
CORSMiddleware,
|
|
157
|
+
allow_origins=["*"], # Replace with your specific origins for production
|
|
158
|
+
allow_credentials=True,
|
|
159
|
+
allow_methods=["*"], # Or specify: ["GET", "POST", "PUT", "DELETE", etc.]
|
|
160
|
+
allow_headers=["*"], # Or specify required headers
|
|
161
|
+
expose_headers=["*"] # Headers that browsers are allowed to access
|
|
162
|
+
)
|
|
163
|
+
|
|
164
|
+
app.add_middleware(HeaderMiddleware)
|
|
165
|
+
|
|
166
|
+
try:
|
|
167
|
+
print(colored(f"Starting server on port {port}", "green"))
|
|
168
|
+
uvicorn.run(app, host="0.0.0.0", port=port, lifespan="on", timeout_graceful_shutdown=2)
|
|
169
|
+
except Exception as e:
|
|
170
|
+
print(colored(f"Error starting server: {str(e)}", "red"))
|
|
171
|
+
|
|
172
|
+
if __name__ == "__main__":
|
|
173
|
+
main()
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: mindroot
|
|
3
|
-
Version: 9.
|
|
3
|
+
Version: 9.5.0
|
|
4
4
|
Summary: MindRoot AI Agent Framework
|
|
5
5
|
Requires-Python: >=3.9
|
|
6
6
|
License-File: LICENSE
|
|
@@ -18,7 +18,6 @@ Requires-Dist: PyJWT
|
|
|
18
18
|
Requires-Dist: pluggy
|
|
19
19
|
Requires-Dist: sse_starlette
|
|
20
20
|
Requires-Dist: partial-json-parser
|
|
21
|
-
Requires-Dist: pydantic
|
|
22
21
|
Requires-Dist: setuptools
|
|
23
22
|
Requires-Dist: requests
|
|
24
23
|
Requires-Dist: aiohttp
|
|
@@ -33,4 +32,10 @@ Requires-Dist: python-dotenv
|
|
|
33
32
|
Requires-Dist: google-auth
|
|
34
33
|
Requires-Dist: google-auth-oauthlib
|
|
35
34
|
Requires-Dist: google-auth-httplib2
|
|
35
|
+
Requires-Dist: chardet
|
|
36
|
+
Requires-Dist: mcp>=1.12.3
|
|
37
|
+
Requires-Dist: httpx>=0.24.0
|
|
38
|
+
Requires-Dist: pydantic>=2.0.0
|
|
39
|
+
Requires-Dist: aiofiles>=23.0.0
|
|
40
|
+
Requires-Dist: uv>=0.7.0
|
|
36
41
|
Dynamic: license-file
|