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.
Files changed (186) hide show
  1. mindroot/coreplugins/admin/__init__.py +3 -1
  2. mindroot/coreplugins/admin/agent_router.py +250 -7
  3. mindroot/coreplugins/admin/asset_manager.py +164 -0
  4. mindroot/coreplugins/admin/command_router.py +236 -1
  5. mindroot/coreplugins/admin/mcp_catalog_routes.py +156 -0
  6. mindroot/coreplugins/admin/mcp_publish_routes.py +450 -0
  7. mindroot/coreplugins/admin/mcp_registry_routes.py +495 -0
  8. mindroot/coreplugins/admin/mcp_routes.py +216 -0
  9. mindroot/coreplugins/admin/mod.py +62 -0
  10. mindroot/coreplugins/admin/oauth_callback_router.py +84 -0
  11. mindroot/coreplugins/admin/persona_handler.py +15 -6
  12. mindroot/coreplugins/admin/persona_router.py +158 -2
  13. mindroot/coreplugins/admin/plugin_manager.py +63 -0
  14. mindroot/coreplugins/admin/plugin_router.py +1 -1
  15. mindroot/coreplugins/admin/plugin_router_fixed.py +23 -0
  16. mindroot/coreplugins/admin/plugin_router_new_not_working.py +145 -0
  17. mindroot/coreplugins/admin/plugin_routes.py +114 -0
  18. mindroot/coreplugins/admin/registry_settings_routes.py +140 -0
  19. mindroot/coreplugins/admin/router.py +116 -15
  20. mindroot/coreplugins/admin/service_models.py +1 -1
  21. mindroot/coreplugins/admin/settings_router.py +1 -0
  22. mindroot/coreplugins/admin/static/css/admin-custom.css +357 -2
  23. mindroot/coreplugins/admin/static/css/dark.css +1 -0
  24. mindroot/coreplugins/admin/static/css/default.css +4 -0
  25. mindroot/coreplugins/admin/static/js/about-info.js +367 -0
  26. mindroot/coreplugins/admin/static/js/agent-form.js +83 -3
  27. mindroot/coreplugins/admin/static/js/api-key-script.js +307 -0
  28. mindroot/coreplugins/admin/static/js/mcp-manager.js +348 -0
  29. mindroot/coreplugins/admin/static/js/mcp-publisher.js +780 -0
  30. mindroot/coreplugins/admin/static/js/persona-editor.js +34 -5
  31. mindroot/coreplugins/admin/static/js/plugin-toggle.js +1 -1
  32. mindroot/coreplugins/admin/static/js/recommended-plugin-install.js +63 -0
  33. mindroot/coreplugins/admin/static/js/registry-auth-section.js +132 -0
  34. mindroot/coreplugins/admin/static/js/registry-manager-base.js +613 -0
  35. mindroot/coreplugins/admin/static/js/registry-manager-old.js +385 -0
  36. mindroot/coreplugins/admin/static/js/registry-manager-publish-old-delete.js +166 -0
  37. mindroot/coreplugins/admin/static/js/registry-manager.js +351 -0
  38. mindroot/coreplugins/admin/static/js/registry-publish-section.js +377 -0
  39. mindroot/coreplugins/admin/static/js/registry-search-section.js +400 -0
  40. mindroot/coreplugins/admin/static/js/registry-search-section.js.bak +3 -0
  41. mindroot/coreplugins/admin/static/js/registry-settings.js +69 -0
  42. mindroot/coreplugins/admin/static/js/registry-shared-services.js +857 -0
  43. mindroot/coreplugins/admin/static/js/registry-simple-sections.js +85 -0
  44. mindroot/coreplugins/admin/static/js/secure-widget-manager.js +438 -0
  45. mindroot/coreplugins/admin/static/logo.png +0 -0
  46. mindroot/coreplugins/admin/templates/admin.jinja2 +275 -110
  47. mindroot/coreplugins/agent/Assistant/agent.json +27 -11
  48. mindroot/coreplugins/agent/agent.py +2 -2
  49. mindroot/coreplugins/agent/command_parser.py +25 -10
  50. mindroot/coreplugins/agent/templates/system.jinja2 +0 -12
  51. mindroot/coreplugins/chat/__init__.py +4 -1
  52. mindroot/coreplugins/chat/router.py +132 -20
  53. mindroot/coreplugins/chat/router_dedup_patch.py +20 -0
  54. mindroot/coreplugins/chat/services.py +31 -1
  55. mindroot/coreplugins/chat/static/css/action-fix.css +32 -0
  56. mindroot/coreplugins/chat/static/css/admin-custom.css +5 -3
  57. mindroot/coreplugins/chat/static/css/dark.css +24 -3
  58. mindroot/coreplugins/chat/static/css/default.css +24 -3
  59. mindroot/coreplugins/chat/static/css/main.css +1 -0
  60. mindroot/coreplugins/chat/static/js/action.js +137 -60
  61. mindroot/coreplugins/chat/static/js/chat-history.js +3 -0
  62. mindroot/coreplugins/chat/static/js/chat.js +59 -16
  63. mindroot/coreplugins/chat/static/js/chat.js.diff +221 -0
  64. mindroot/coreplugins/chat/static/js/chatform.js +2 -2
  65. mindroot/coreplugins/chat/static/site.webmanifest +1 -1
  66. mindroot/coreplugins/chat/templates/chat.jinja2 +3 -3
  67. mindroot/coreplugins/chat/widget_manager.py +139 -0
  68. mindroot/coreplugins/chat/widget_routes.py +287 -0
  69. mindroot/coreplugins/check_list/inject/admin.jinja2 +1 -1
  70. mindroot/coreplugins/email/__init__.py +2 -0
  71. mindroot/coreplugins/email/email_provider.py +2 -2
  72. mindroot/coreplugins/email/mod.py +100 -0
  73. mindroot/coreplugins/email/services.py +5 -3
  74. mindroot/coreplugins/email/smtp_handler.py +9 -3
  75. mindroot/coreplugins/email/test_email_service.py +75 -0
  76. mindroot/coreplugins/env_manager/mod.py +61 -25
  77. mindroot/coreplugins/home/router.py +37 -2
  78. mindroot/coreplugins/home/static/imgs/logo.png +0 -0
  79. mindroot/coreplugins/home/static/imgs/logo.png.bak +0 -0
  80. mindroot/coreplugins/home/static/imgs/logo_teal.png +0 -0
  81. mindroot/coreplugins/home/static/imgs/logo_teal2.png +0 -0
  82. mindroot/coreplugins/home/static/imgs/logo_teal_detailed.png +0 -0
  83. mindroot/coreplugins/home/static/imgs/logo_teal_python.png +0 -0
  84. mindroot/coreplugins/home/templates/home.jinja2 +15 -6
  85. mindroot/coreplugins/index/handlers/plugin_ops.py +1 -1
  86. mindroot/coreplugins/index/indices/default/index.json +6 -6
  87. mindroot/coreplugins/jwt_auth/middleware.py +47 -1
  88. mindroot/coreplugins/jwt_auth/mod.py +40 -17
  89. mindroot/coreplugins/l8n/__init__.py +6 -0
  90. mindroot/coreplugins/l8n/debug_loader.py +85 -0
  91. mindroot/coreplugins/l8n/debug_middleware.py +74 -0
  92. mindroot/coreplugins/l8n/l8n_constants.py +19 -0
  93. mindroot/coreplugins/l8n/language_detection.py +183 -0
  94. mindroot/coreplugins/l8n/middleware.py +151 -0
  95. mindroot/coreplugins/l8n/mod.py +277 -0
  96. mindroot/coreplugins/l8n/monkey_patch_to_delete.py +186 -0
  97. mindroot/coreplugins/l8n/test_enhanced.py +298 -0
  98. mindroot/coreplugins/l8n/test_l8n.py +95 -0
  99. mindroot/coreplugins/l8n/test_l8n_standalone.py +251 -0
  100. mindroot/coreplugins/l8n/test_middleware.py +272 -0
  101. mindroot/coreplugins/l8n/utils.py +232 -0
  102. mindroot/coreplugins/mcp_/__init__.py +14 -0
  103. mindroot/coreplugins/mcp_/catalog_commands.py +328 -0
  104. mindroot/coreplugins/mcp_/catalog_manager.py +263 -0
  105. mindroot/coreplugins/mcp_/dynamic_commands.py +154 -0
  106. mindroot/coreplugins/mcp_/mcp_manager.py +1031 -0
  107. mindroot/coreplugins/mcp_/mod.py +367 -0
  108. mindroot/coreplugins/mcp_/oauth_storage.py +144 -0
  109. mindroot/coreplugins/mcp_/server_installer.py +79 -0
  110. mindroot/coreplugins/mcp_/setup.py +26 -0
  111. mindroot/coreplugins/mcp_/test_dynamic_commands.py +134 -0
  112. mindroot/coreplugins/mcp_/testmcpclient.py +92 -0
  113. mindroot/coreplugins/persona/mod.py +12 -7
  114. mindroot/coreplugins/signup/templates/signup.jinja2 +1 -1
  115. mindroot/coreplugins/subscriptions/__init__.py +1 -0
  116. mindroot/coreplugins/subscriptions/mod.py +14 -3
  117. mindroot/coreplugins/subscriptions/router.py +3 -0
  118. mindroot/coreplugins/user_service/__init__.py +1 -2
  119. mindroot/coreplugins/user_service/admin_init.py +1 -0
  120. mindroot/coreplugins/user_service/email_service.py +72 -17
  121. mindroot/coreplugins/user_service/mod.py +10 -2
  122. mindroot/coreplugins/user_service/password_reset_service.py +180 -27
  123. mindroot/coreplugins/user_service/router.py +84 -22
  124. mindroot/lib/auth/api_key.py +28 -0
  125. mindroot/lib/cli/plugins.py +94 -0
  126. mindroot/lib/plugins/default_plugin_manifest.json +20 -0
  127. mindroot/lib/plugins/installation.py +5 -5
  128. mindroot/lib/plugins/l8n_static_handler.py +225 -0
  129. mindroot/lib/plugins/loader.py +33 -3
  130. mindroot/lib/plugins/loader_with_l8n.py +281 -0
  131. mindroot/lib/plugins/manifest.py +238 -17
  132. mindroot/lib/providers/commands.py +3 -1
  133. mindroot/lib/route_decorators.py +5 -5
  134. mindroot/lib/templates.py +183 -11
  135. mindroot/lib/utils/merge_arrays.py +1 -1
  136. mindroot/migrate.py +49 -0
  137. mindroot/registry/data_access.py +1 -1
  138. mindroot/server.py +47 -13
  139. mindroot/server_missing_normal_args.py +197 -0
  140. mindroot/server_prev.py +173 -0
  141. {mindroot-9.2.0.dist-info → mindroot-9.5.0.dist-info}/METADATA +7 -2
  142. {mindroot-9.2.0.dist-info → mindroot-9.5.0.dist-info}/RECORD +147 -114
  143. mindroot/coreplugins/admin/static/favicon/about.txt +0 -6
  144. mindroot/coreplugins/admin/static/favicon/android-chrome-512x512.png +0 -0
  145. mindroot/coreplugins/admin/static/favicon/apple-touch-icon.png +0 -0
  146. mindroot/coreplugins/admin/static/favicon/favicon-16x16.png +0 -0
  147. mindroot/coreplugins/admin/static/favicon/favicon-32x32.png +0 -0
  148. mindroot/coreplugins/admin/static/favicon/favicon.ico +0 -0
  149. mindroot/coreplugins/admin/static/favicon/favicon_io (1)/about.txt +0 -6
  150. mindroot/coreplugins/admin/static/favicon/favicon_io (1)/android-chrome-192x192.png +0 -0
  151. mindroot/coreplugins/admin/static/favicon/favicon_io (1)/android-chrome-512x512.png +0 -0
  152. mindroot/coreplugins/admin/static/favicon/favicon_io (1)/apple-touch-icon.png +0 -0
  153. mindroot/coreplugins/admin/static/favicon/favicon_io (1)/favicon-16x16.png +0 -0
  154. mindroot/coreplugins/admin/static/favicon/favicon_io (1)/favicon-32x32.png +0 -0
  155. mindroot/coreplugins/admin/static/favicon/favicon_io (1)/favicon.ico +0 -0
  156. mindroot/coreplugins/admin/static/favicon/favicon_io (1)/site.webmanifest +0 -1
  157. mindroot/coreplugins/admin/static/favicon/logo.png +0 -0
  158. mindroot/coreplugins/admin/static/favicon/site.webmanifest +0 -1
  159. mindroot/coreplugins/admin/static/js/backup/agent-editor.js +0 -186
  160. mindroot/coreplugins/admin/static/js/backup/agent-form.js +0 -1133
  161. mindroot/coreplugins/admin/static/js/backup/agent-list.js +0 -94
  162. mindroot/coreplugins/chat/static/favicon/about.txt +0 -6
  163. mindroot/coreplugins/chat/static/favicon/android-chrome-192x192.png +0 -0
  164. mindroot/coreplugins/chat/static/favicon/android-chrome-512x512.png +0 -0
  165. mindroot/coreplugins/chat/static/favicon/apple-touch-icon.png +0 -0
  166. mindroot/coreplugins/chat/static/favicon/favicon-16x16.png +0 -0
  167. mindroot/coreplugins/chat/static/favicon/favicon-32x32.png +0 -0
  168. mindroot/coreplugins/chat/static/favicon/favicon.ico +0 -0
  169. mindroot/coreplugins/chat/static/favicon/favicon_io (1)/about.txt +0 -6
  170. mindroot/coreplugins/chat/static/favicon/favicon_io (1)/android-chrome-192x192.png +0 -0
  171. mindroot/coreplugins/chat/static/favicon/favicon_io (1)/android-chrome-512x512.png +0 -0
  172. mindroot/coreplugins/chat/static/favicon/favicon_io (1)/apple-touch-icon.png +0 -0
  173. mindroot/coreplugins/chat/static/favicon/favicon_io (1)/favicon-16x16.png +0 -0
  174. mindroot/coreplugins/chat/static/favicon/favicon_io (1)/favicon-32x32.png +0 -0
  175. mindroot/coreplugins/chat/static/favicon/favicon_io (1)/favicon.ico +0 -0
  176. mindroot/coreplugins/chat/static/favicon/favicon_io (1)/site.webmanifest +0 -1
  177. mindroot/coreplugins/chat/static/favicon/logo.png +0 -0
  178. mindroot/coreplugins/chat/static/favicon/site.webmanifest +0 -1
  179. mindroot/coreplugins/index/default.json +0 -76
  180. mindroot/coreplugins/user_service/file_trigger_service.py +0 -72
  181. mindroot/coreplugins/user_service/hooks.py +0 -23
  182. /mindroot/coreplugins/{admin/static/favicon/android-chrome-192x192.png → home/static/imgs/backuplogo.png} +0 -0
  183. {mindroot-9.2.0.dist-info → mindroot-9.5.0.dist-info}/WHEEL +0 -0
  184. {mindroot-9.2.0.dist-info → mindroot-9.5.0.dist-info}/entry_points.txt +0 -0
  185. {mindroot-9.2.0.dist-info → mindroot-9.5.0.dist-info}/licenses/LICENSE +0 -0
  186. {mindroot-9.2.0.dist-info → mindroot-9.5.0.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,307 @@
1
+ import { LitElement, html, css } from './lit-core.min.js';
2
+ import { BaseEl } from './base.js';
3
+ import showNotification from './notification.js';
4
+
5
+ class ApiKeyScript extends BaseEl {
6
+ static properties = {
7
+ agents: { type: Array },
8
+ apiKeys: { type: Array },
9
+ selectedAgent: { type: String },
10
+ domainName: { type: String },
11
+ apiKey: { type: String },
12
+ scriptContent: { type: String },
13
+ showPreview: { type: Boolean }
14
+ };
15
+
16
+ static styles = css`
17
+ /* This component's styles are mostly for the form, not the global preview */
18
+ :host {
19
+ display: block;
20
+ width: 100%;
21
+ height: 100%;
22
+ }
23
+ .api-key-script {
24
+ display: flex;
25
+ flex-direction: column;
26
+ width: 100%;
27
+ max-width: 1200px;
28
+ margin: 0 auto;
29
+ gap: 20px;
30
+ }
31
+ .section {
32
+ background: rgb(10, 10, 25);
33
+ border-radius: 8px;
34
+ padding: 1rem;
35
+ border: 1px solid rgba(255, 255, 255, 0.1);
36
+ }
37
+ .form-group {
38
+ margin-bottom: 15px;
39
+ }
40
+ .form-group label {
41
+ display: block;
42
+ margin-bottom: 5px;
43
+ color: #f0f0f0;
44
+ font-weight: 500;
45
+ }
46
+ input[type="text"],
47
+ select {
48
+ width: 100%;
49
+ padding: 8px 12px;
50
+ background: rgba(255, 255, 255, 0.05);
51
+ border: 1px solid rgba(255, 255, 255, 0.1);
52
+ border-radius: 6px;
53
+ color: #f0f0f0;
54
+ font-size: 0.95rem;
55
+ }
56
+ button {
57
+ background: #2196F3;
58
+ color: #fff;
59
+ border: none;
60
+ padding: 0.75rem 1.5rem;
61
+ border-radius: 4px;
62
+ cursor: pointer;
63
+ transition: background 0.2s;
64
+ margin-right: 10px;
65
+ }
66
+ button:hover {
67
+ background: #1976D2;
68
+ }
69
+ button.secondary {
70
+ background: #2a2a40;
71
+ border: 1px solid rgba(255, 255, 255, 0.1);
72
+ }
73
+ .script-preview {
74
+ background: rgba(0, 0, 0, 0.3);
75
+ border: 1px solid rgba(255, 255, 255, 0.1);
76
+ border-radius: 6px;
77
+ padding: 1rem;
78
+ font-family: 'Consolas', 'Monaco', 'Courier New', monospace;
79
+ font-size: 0.9rem;
80
+ color: #f0f0f0;
81
+ white-space: pre-wrap;
82
+ max-height: 400px;
83
+ overflow-y: auto;
84
+ }
85
+ .button-group {
86
+ display: flex;
87
+ gap: 10px;
88
+ margin-top: 15px;
89
+ }
90
+ .error {
91
+ color: #e57373;
92
+ font-size: 0.9rem;
93
+ margin-top: 5px;
94
+ }
95
+ `;
96
+
97
+ constructor() {
98
+ super();
99
+ this.agents = [];
100
+ this.apiKeys = [];
101
+ this.selectedAgent = '';
102
+ this.domainName = window.location.origin;
103
+ this.apiKey = '';
104
+ this.scriptContent = '';
105
+ this.showPreview = false;
106
+
107
+ this.fetchApiKeys();
108
+ this.fetchAgents();
109
+ }
110
+
111
+ disconnectedCallback() {
112
+ super.disconnectedCallback();
113
+ // Ensure preview elements are removed if the component is destroyed
114
+ this._removeGlobalPreview();
115
+ }
116
+
117
+ async fetchAgents() {
118
+ try {
119
+ const response = await fetch('/agents/local');
120
+ if (!response.ok) throw new Error('Failed to fetch agents');
121
+ this.agents = await response.json();
122
+ } catch (error) {
123
+ showNotification('error', `Error loading agents: ${error.message}`);
124
+ }
125
+ }
126
+
127
+ async fetchApiKeys() {
128
+ try {
129
+ const response = await fetch('/api_keys/list');
130
+ if (!response.ok) throw new Error('Failed to fetch API keys');
131
+ const result = await response.json();
132
+ this.apiKeys = result.data || [];
133
+ } catch (error) {
134
+ showNotification('error', `Error loading API keys: ${error.message}`);
135
+ }
136
+ }
137
+
138
+ handleInputChange(event) {
139
+ const { name, value } = event.target;
140
+ this[name] = value;
141
+ if (name === 'selectedAgent' || name === 'domainName' || name === 'apiKey') {
142
+ this.generateScript();
143
+ }
144
+ }
145
+
146
+ generateScript() {
147
+ if (!this.selectedAgent || !this.domainName || !this.apiKey) {
148
+ this.scriptContent = '';
149
+ return;
150
+ }
151
+ const config = {
152
+ agentName: this.selectedAgent,
153
+ apiKey: this.apiKey,
154
+ domain: this.domainName,
155
+ position: 'bottom-right'
156
+ };
157
+ const scriptBody = [
158
+ '(function() {',
159
+ ' const config = ' + JSON.stringify(config) + ';',
160
+ ' let iframeLoaded = false;',
161
+ ' function createChatIcon() {',
162
+ ' const icon = document.createElement("div");',
163
+ ' icon.id = "mindroot-chat-icon";',
164
+ ' icon.innerHTML = "💬";',
165
+ ' icon.style.cssText = "position: fixed; bottom: 20px; right: 20px; width: 60px; height: 60px; background: #2196F3; border-radius: 50%; display: flex; align-items: center; justify-content: center; cursor: pointer; box-shadow: 0 4px 12px rgba(0, 0, 0, 0.3); z-index: 10000; font-size: 24px; color: white; transition: all 0.3s ease;";',
166
+ ' icon.addEventListener("click", toggleChat);',
167
+ ' document.body.appendChild(icon);',
168
+ ' }',
169
+ ' function createChatIframe() {',
170
+ ' const container = document.createElement("div");',
171
+ ' container.id = "mindroot-chat-container";',
172
+ ' container.style.cssText = "position: fixed; bottom: 90px; right: 20px; width: 400px; height: 600px; background: white; border-radius: 12px; box-shadow: 0 8px 32px rgba(0, 0, 0, 0.3); z-index: 10001; display: none; overflow: hidden;";',
173
+ ' const iframe = document.createElement("iframe");',
174
+ ' iframe.style.cssText = "width: 100%; height: 100%; border: none; border-radius: 12px;";',
175
+ ' container.appendChild(iframe);',
176
+ ' document.body.appendChild(container);',
177
+ ' }',
178
+ ' function toggleChat() {',
179
+ ' const container = document.getElementById("mindroot-chat-container");',
180
+ ' const iframe = container.querySelector("iframe");',
181
+ ' if (!iframeLoaded) {',
182
+ ' iframe.src = `${config.domain}/agent/${config.agentName}?api_key=${config.apiKey}&embed=true`;',
183
+ ' iframeLoaded = true;',
184
+ ' }',
185
+ ' container.style.display = (container.style.display === "none" || !container.style.display) ? "block" : "none";',
186
+ ' }',
187
+ ' function init() {',
188
+ ' if (document.readyState === "loading") { document.addEventListener("DOMContentLoaded", function() { createChatIcon(); createChatIframe(); }); }',
189
+ ' else { createChatIcon(); createChatIframe(); }',
190
+ ' }',
191
+ ' init();',
192
+ '})();'
193
+ ].join('\n');
194
+ this.scriptContent = [
195
+ '<!-- MindRoot AI Chat Widget -->',
196
+ '<div id="mindroot-chat-widget"></div>',
197
+ '<script>',
198
+ scriptBody,
199
+ '</script>',
200
+ '<!-- End MindRoot AI Chat Widget -->'
201
+ ].join('\n');
202
+ }
203
+
204
+ togglePreview() {
205
+ this.showPreview = !this.showPreview;
206
+ if (this.showPreview) {
207
+ this._createGlobalPreview();
208
+ } else {
209
+ this._removeGlobalPreview();
210
+ }
211
+ }
212
+
213
+ _createGlobalPreview() {
214
+ this._removeGlobalPreview(); // Clean up any previous instances
215
+
216
+ const chatIcon = document.createElement('div');
217
+ chatIcon.id = 'mindroot-preview-chat-icon';
218
+ chatIcon.innerHTML = '<span class="material-icons">chat</span>';
219
+ chatIcon.style.cssText = 'position: fixed; bottom: 20px; right: 20px; width: 60px; height: 60px; background: #2196F3; border-radius: 50%; display: flex; align-items: center; justify-content: center; cursor: pointer; box-shadow: 0 4px 12px rgba(0, 0, 0, 0.3); z-index: 10000; color: white; font-size: 24px;';
220
+ chatIcon.addEventListener('click', () => this._togglePreviewChatWindow());
221
+ document.body.appendChild(chatIcon);
222
+ }
223
+
224
+ _togglePreviewChatWindow() {
225
+ let chatContainer = document.getElementById('mindroot-preview-chat-container');
226
+ if (!chatContainer) {
227
+ chatContainer = document.createElement('div');
228
+ chatContainer.id = 'mindroot-preview-chat-container';
229
+ chatContainer.style.cssText = 'position: fixed; bottom: 90px; right: 20px; width: 400px; height: 600px; background: white; border-radius: 12px; box-shadow: 0 8px 32px rgba(0, 0, 0, 0.3); z-index: 10001; display: block; overflow: hidden;';
230
+
231
+ const iframe = document.createElement('iframe');
232
+ iframe.style.cssText = 'width: 100%; height: 100%; border: none; border-radius: 12px;';
233
+ iframe.src = `${this.domainName}/agent/${this.selectedAgent}?api_key=${this.apiKey}&embed=true`;
234
+ chatContainer.appendChild(iframe);
235
+ document.body.appendChild(chatContainer);
236
+ } else {
237
+ chatContainer.style.display = chatContainer.style.display === 'none' ? 'block' : 'none';
238
+ }
239
+ }
240
+
241
+ _removeGlobalPreview() {
242
+ const chatIcon = document.getElementById('mindroot-preview-chat-icon');
243
+ if (chatIcon) chatIcon.remove();
244
+ const chatContainer = document.getElementById('mindroot-preview-chat-container');
245
+ if (chatContainer) chatContainer.remove();
246
+ }
247
+
248
+ _render() {
249
+ return html`
250
+ <div class="api-key-script">
251
+ <div class="section">
252
+ <h3>Chat Widget Generator</h3>
253
+ <p>Generate an embeddable chat widget script for your website.</p>
254
+
255
+ <div class="form-group">
256
+ <label for="selectedAgent">Select Agent:</label>
257
+ <select name="selectedAgent" @change=${this.handleInputChange} .value=${this.selectedAgent}>
258
+ <option value="">Choose an agent...</option>
259
+ ${this.agents.map(agent => html`<option value="${agent.name}">${agent.name}</option>`)}
260
+ </select>
261
+ </div>
262
+
263
+ <div class="form-group">
264
+ <label for="domainName">Domain Name:</label>
265
+ <input type="text" name="domainName" .value=${this.domainName} @input=${this.handleInputChange} placeholder="https://your-domain.com">
266
+ </div>
267
+
268
+ <div class="form-group">
269
+ <label for="apiKey">Select API Key:</label>
270
+ <select name="apiKey" @change=${this.handleInputChange} .value=${this.apiKey}>
271
+ <option value="">Choose an API key...</option>
272
+ ${this.apiKeys.map(key => html`<option value="${key.key}">${key.description || key.key.substring(0, 8)}...</option>`)}
273
+ </select>
274
+ ${!this.apiKey ? html`<div class="error">An API key is required.</div>` : ''}
275
+ </div>
276
+
277
+ <div class="button-group">
278
+ <button @click=${this.generateScript}>Generate Script</button>
279
+ <button class="secondary" @click=${this.togglePreview} ?disabled=${!this.scriptContent}>
280
+ ${this.showPreview ? 'Hide Preview' : 'Show Preview'}
281
+ </button>
282
+ </div>
283
+ </div>
284
+
285
+ ${this.scriptContent ? html`
286
+ <div class="section">
287
+ <h3>Generated Script</h3>
288
+ <div class="script-preview">${this.scriptContent}</div>
289
+ <div class="button-group">
290
+ <button @click=${() => this.copyScript()}>Copy Script</button>
291
+ <button class="secondary" @click=${() => this.saveScript()}>Download Script</button>
292
+ </div>
293
+ </div>
294
+ ` : ''}
295
+
296
+ ${this.showPreview ? html`
297
+ <div class="section">
298
+ <h3>Live Preview</h3>
299
+ <p>A live preview of the chat widget is now active on this page in the bottom-right corner. Click 'Hide Preview' to remove it.</p>
300
+ </div>
301
+ ` : ''}
302
+ </div>
303
+ `;
304
+ }
305
+ }
306
+
307
+ customElements.define('api-key-script', ApiKeyScript);
@@ -0,0 +1,348 @@
1
+ import { BaseEl } from '/admin/static/js/base.js';
2
+ import { html, css } from '/admin/static/js/lit-core.min.js';
3
+
4
+ class McpManager extends BaseEl {
5
+ static properties = {
6
+ servers: { type: Array },
7
+ catalog: { type: Object },
8
+ loading: { type: Boolean },
9
+ selectedTab: { type: String }
10
+ };
11
+
12
+ static styles = css`
13
+ :host {
14
+ display: block;
15
+ width: 100%;
16
+ height: 100%;
17
+ }
18
+
19
+ .mcp-manager {
20
+ display: flex;
21
+ flex-direction: column;
22
+ width: 100%;
23
+ max-width: 1200px;
24
+ margin: 0 auto;
25
+ gap: 20px;
26
+ }
27
+
28
+ .section {
29
+ background: rgb(10, 10, 25);
30
+ border-radius: 8px;
31
+ padding: 1rem;
32
+ border: 1px solid rgba(255, 255, 255, 0.1);
33
+ }
34
+
35
+ .tabs {
36
+ display: flex;
37
+ gap: 0.5rem;
38
+ margin-bottom: 1rem;
39
+ }
40
+
41
+ .tab {
42
+ padding: 0.5rem 1rem;
43
+ background: rgba(0, 0, 0, 0.2);
44
+ border: 1px solid rgba(255, 255, 255, 0.1);
45
+ border-radius: 4px;
46
+ cursor: pointer;
47
+ transition: background 0.2s;
48
+ color: #ccc;
49
+ }
50
+
51
+ .tab.active {
52
+ background: #4a9eff;
53
+ color: #fff;
54
+ }
55
+
56
+ .tab:hover {
57
+ background: rgba(74, 158, 255, 0.3);
58
+ }
59
+
60
+ .server-list {
61
+ display: grid;
62
+ gap: 1rem;
63
+ }
64
+
65
+ .server-item {
66
+ background: rgba(0, 0, 0, 0.2);
67
+ padding: 1rem;
68
+ border-radius: 4px;
69
+ border: 1px solid rgba(255, 255, 255, 0.1);
70
+ }
71
+
72
+ .server-header {
73
+ display: flex;
74
+ justify-content: space-between;
75
+ align-items: center;
76
+ margin-bottom: 0.5rem;
77
+ }
78
+
79
+ .server-name {
80
+ font-weight: bold;
81
+ color: #4a9eff;
82
+ }
83
+
84
+ .status-badge {
85
+ padding: 0.2rem 0.5rem;
86
+ border-radius: 3px;
87
+ font-size: 0.8rem;
88
+ text-transform: uppercase;
89
+ }
90
+
91
+ .status-badge.connected {
92
+ background: rgba(40, 167, 69, 0.2);
93
+ color: #28a745;
94
+ }
95
+
96
+ .status-badge.disconnected {
97
+ background: rgba(108, 117, 125, 0.2);
98
+ color: #6c757d;
99
+ }
100
+
101
+ .status-badge.error {
102
+ background: rgba(220, 53, 69, 0.2);
103
+ color: #dc3545;
104
+ }
105
+
106
+ .server-actions {
107
+ display: flex;
108
+ gap: 0.5rem;
109
+ margin-top: 1rem;
110
+ }
111
+
112
+ button {
113
+ background: #2a2a40;
114
+ color: #fff;
115
+ border: 1px solid rgba(255, 255, 255, 0.1);
116
+ padding: 0.5rem 1rem;
117
+ border-radius: 4px;
118
+ cursor: pointer;
119
+ transition: background 0.2s;
120
+ }
121
+
122
+ button:hover {
123
+ background: #3a3a50;
124
+ }
125
+
126
+ button.success {
127
+ background: #28a745;
128
+ }
129
+
130
+ button.success:hover {
131
+ background: #218838;
132
+ }
133
+
134
+ button.warning {
135
+ background: #ffc107;
136
+ color: #000;
137
+ }
138
+
139
+ button.warning:hover {
140
+ background: #e0a800;
141
+ }
142
+
143
+ button.danger {
144
+ background: #dc3545;
145
+ }
146
+
147
+ button.danger:hover {
148
+ background: #c82333;
149
+ }
150
+
151
+ .loading {
152
+ text-align: center;
153
+ color: #ccc;
154
+ padding: 2rem;
155
+ }
156
+ `;
157
+
158
+ constructor() {
159
+ super();
160
+ this.servers = [];
161
+ this.catalog = {};
162
+ this.loading = false;
163
+ this.selectedTab = 'servers';
164
+ this.loadServers();
165
+ }
166
+
167
+ async loadServers() {
168
+ this.loading = true;
169
+ try {
170
+ const response = await fetch('/admin/mcp/list');
171
+ if (response.ok) {
172
+ const data = await response.json();
173
+ this.servers = data.data || [];
174
+ }
175
+ } catch (error) {
176
+ console.error('Error loading MCP servers:', error);
177
+ }
178
+ this.loading = false;
179
+ }
180
+
181
+ async loadCatalog() {
182
+ this.loading = true;
183
+ try {
184
+ const response = await fetch('/admin/mcp/catalog');
185
+ if (response.ok) {
186
+ const data = await response.json();
187
+ this.catalog = data.data || {};
188
+ }
189
+ } catch (error) {
190
+ console.error('Error loading MCP catalog:', error);
191
+ }
192
+ this.loading = false;
193
+ }
194
+
195
+ async connectServer(serverName) {
196
+ try {
197
+ const response = await fetch('/admin/mcp/connect', {
198
+ method: 'POST',
199
+ headers: { 'Content-Type': 'application/json' },
200
+ body: JSON.stringify({ server_name: serverName })
201
+ });
202
+ if (response.ok) {
203
+ await this.loadServers();
204
+ }
205
+ } catch (error) {
206
+ console.error('Error connecting server:', error);
207
+ }
208
+ }
209
+
210
+ async disconnectServer(serverName) {
211
+ try {
212
+ const response = await fetch('/admin/mcp/disconnect', {
213
+ method: 'POST',
214
+ headers: { 'Content-Type': 'application/json' },
215
+ body: JSON.stringify({ server_name: serverName })
216
+ });
217
+ if (response.ok) {
218
+ await this.loadServers();
219
+ }
220
+ } catch (error) {
221
+ console.error('Error disconnecting server:', error);
222
+ }
223
+ }
224
+
225
+ async removeServer(serverName) {
226
+ if (!confirm(`Are you sure you want to remove the MCP server '${serverName}'?`)) return;
227
+
228
+ try {
229
+ const response = await fetch('/admin/mcp/remove', {
230
+ method: 'POST',
231
+ headers: { 'Content-Type': 'application/json' },
232
+ body: JSON.stringify({ server_name: serverName })
233
+ });
234
+ if (response.ok) {
235
+ await this.loadServers();
236
+ }
237
+ } catch (error) {
238
+ console.error('Error removing server:', error);
239
+ }
240
+ }
241
+
242
+ selectTab(tab) {
243
+ this.selectedTab = tab;
244
+ if (tab === 'catalog' && Object.keys(this.catalog).length === 0) {
245
+ this.loadCatalog();
246
+ }
247
+ }
248
+
249
+ _render() {
250
+ return html`
251
+ <div class="mcp-manager">
252
+ <div class="section">
253
+ <h3>MCP Server Management</h3>
254
+
255
+ <div class="tabs">
256
+ <div class="tab ${this.selectedTab === 'servers' ? 'active' : ''}"
257
+ @click=${() => this.selectTab('servers')}>Local Servers</div>
258
+ <div class="tab ${this.selectedTab === 'catalog' ? 'active' : ''}"
259
+ @click=${() => this.selectTab('catalog')}>Server Catalog</div>
260
+ </div>
261
+
262
+ ${this.loading ? html`<div class="loading">Loading...</div>` : ''}
263
+
264
+ ${this.selectedTab === 'servers' ? this.renderServers() : this.renderCatalog()}
265
+ </div>
266
+ </div>
267
+ `;
268
+ }
269
+
270
+ renderServers() {
271
+ if (this.servers.length === 0) {
272
+ return html`<p>No MCP servers configured. Use the catalog to install some.</p>`;
273
+ }
274
+
275
+ return html`
276
+ <div class="server-list">
277
+ ${this.servers.map(server => html`
278
+ <div class="server-item">
279
+ <div class="server-header">
280
+ <div class="server-name">${server.name}</div>
281
+ <div class="status-badge ${server.status}">${server.status}</div>
282
+ </div>
283
+ <div class="server-description">${server.description}</div>
284
+ <div class="server-meta">
285
+ <small>Transport: ${server.transport} | Command: ${server.command}</small>
286
+ </div>
287
+ <div class="server-actions">
288
+ ${server.status === 'connected'
289
+ ? html`<button class="warning" @click=${() => this.disconnectServer(server.name)}>Disconnect</button>`
290
+ : html`<button class="success" @click=${() => this.connectServer(server.name)}>Connect</button>`
291
+ }
292
+ <button class="danger" @click=${() => this.removeServer(server.name)}>Remove</button>
293
+ </div>
294
+ </div>
295
+ `)}
296
+ </div>
297
+ `;
298
+ }
299
+
300
+ renderCatalog() {
301
+ const servers = this.catalog.servers || {};
302
+ const serverList = Object.entries(servers);
303
+
304
+ if (serverList.length === 0) {
305
+ return html`<p>No servers in catalog. Loading...</p>`;
306
+ }
307
+
308
+ return html`
309
+ <div class="server-list">
310
+ ${serverList.map(([name, server]) => html`
311
+ <div class="server-item">
312
+ <div class="server-header">
313
+ <div class="server-name">${server.display_name || name}</div>
314
+ <div class="status-badge ${server.installed ? 'connected' : 'disconnected'}">
315
+ ${server.installed ? 'Installed' : 'Available'}
316
+ </div>
317
+ </div>
318
+ <div class="server-description">${server.description}</div>
319
+ <div class="server-actions">
320
+ ${server.installed
321
+ ? html`<button disabled>Already Installed</button>`
322
+ : html`<button class="success" @click=${() => this.installFromCatalog(name)}>Install</button>`
323
+ }
324
+ </div>
325
+ </div>
326
+ `)}
327
+ </div>
328
+ `;
329
+ }
330
+
331
+ async installFromCatalog(serverName) {
332
+ try {
333
+ const response = await fetch('/admin/mcp/catalog/install', {
334
+ method: 'POST',
335
+ headers: { 'Content-Type': 'application/json' },
336
+ body: JSON.stringify({ server_name: serverName })
337
+ });
338
+ if (response.ok) {
339
+ await this.loadServers();
340
+ await this.loadCatalog();
341
+ }
342
+ } catch (error) {
343
+ console.error('Error installing from catalog:', error);
344
+ }
345
+ }
346
+ }
347
+
348
+ customElements.define('mcp-manager', McpManager);