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,400 @@
1
+ /**
2
+ * Registry Search Section
3
+ *
4
+ * Handles search UI, category filtering, and results display
5
+ * for the registry manager.
6
+ */
7
+
8
+ import { html } from '/admin/static/js/lit-core.min.js';
9
+
10
+ class RegistrySearchSection {
11
+ constructor(sharedState, mainComponent) {
12
+ this.state = sharedState;
13
+ this.main = mainComponent;
14
+ this.services = null; // Will be set by main component
15
+ this.searchTimeout = null;
16
+ }
17
+
18
+ setServices(services) {
19
+ this.services = services;
20
+ }
21
+
22
+ // === Event Handlers ===
23
+
24
+ handleSearchInput(e) {
25
+ this.main.searchQuery = e.target.value;
26
+
27
+ // Clear existing timeout
28
+ if (this.searchTimeout) {
29
+ clearTimeout(this.searchTimeout);
30
+ }
31
+
32
+ // Set new timeout for auto-search after 500ms of no typing
33
+ this.searchTimeout = setTimeout(() => {
34
+ this.services.search();
35
+ this.main.requestUpdate();
36
+ }, 500);
37
+ }
38
+
39
+ handleCategoryChange(category) {
40
+ this.main.selectedCategory = category;
41
+ this.services.search();
42
+ this.main.requestUpdate();
43
+ }
44
+
45
+ async loadTopContent() {
46
+ await this.services.loadTopContent();
47
+ this.main.requestUpdate();
48
+ }
49
+
50
+ async installFromRegistry(item) {
51
+ await this.services.installFromRegistry(item);
52
+ this.main.requestUpdate();
53
+ }
54
+
55
+ // === Helper Methods ===
56
+
57
+ getInstalledMcpServer(item) {
58
+ if (!this.main.localMcpServers || this.main.localMcpServers.length === 0) {
59
+ return null;
60
+ }
61
+ // Use a fuzzy match: check if the item's title contains the server's name.
62
+ // This handles cases where title is "Calculator Server" and name is "calculator".
63
+ const normalizedTitle = item.title.toLowerCase();
64
+ return this.main.localMcpServers.find(s =>
65
+ normalizedTitle.includes(s.name.toLowerCase())
66
+ );
67
+ }
68
+
69
+ // === Render Methods ===
70
+
71
+ renderSearch() {
72
+ return html`
73
+ <div class="section">
74
+ <h3>Registry Browser</h3>
75
+ ${this.renderSearchForm()}
76
+ ${this.renderSearchStatus()}
77
+ ${this.renderSearchResults()}
78
+ </div>
79
+ `;
80
+ }
81
+
82
+ renderSearchForm() {
83
+ return html`
84
+ <div class="search-form">
85
+ <div class="form-row">
86
+ <input type="text" placeholder="Search plugins and agents..."
87
+ .value=${this.main.searchQuery}
88
+ @input=${(e) => this.handleSearchInput(e)}>
89
+ </div>
90
+ ${this.renderCategoryTabs()}
91
+ </div>
92
+ `;
93
+ }
94
+
95
+ renderCategoryTabs() {
96
+ return html`
97
+ <div class="category-tabs">
98
+ <button class="category-tab ${this.main.selectedCategory === 'all' ? 'active' : ''}"
99
+ @click=${() => this.handleCategoryChange('all')}>
100
+ <span class="material-icons">apps</span>
101
+ All
102
+ </button>
103
+ <button class="category-tab ${this.main.selectedCategory === 'plugin' ? 'active' : ''}"
104
+ @click=${() => this.handleCategoryChange('plugin')}>
105
+ <span class="material-icons">extension</span>
106
+ Plugins
107
+ </button>
108
+ <button class="category-tab ${this.main.selectedCategory === 'agent' ? 'active' : ''}"
109
+ @click=${() => this.handleCategoryChange('agent')}>
110
+ <span class="material-icons">smart_toy</span>
111
+ Agents
112
+ </button>
113
+ <button class="category-tab ${this.main.selectedCategory === 'mcp_server' ? 'active' : ''}"
114
+ @click=${() => this.handleCategoryChange('mcp_server')}>
115
+ <span class="material-icons">dns</span>
116
+ MCP Servers
117
+ </button>
118
+ </div>
119
+ `;
120
+ }
121
+
122
+ renderSearchStatus() {
123
+ if (this.state.loading) {
124
+ return html`<div class="loading">Searching...</div>`;
125
+ }
126
+
127
+ if (this.main.error) {
128
+ return html`<div class="error">${this.main.error}</div>`;
129
+ }
130
+
131
+ return '';
132
+ }
133
+
134
+ renderSearchResults() {
135
+ return html`
136
+ <div class="search-results">
137
+ ${this.main.searchResults.length === 0 && !this.state.loading ? html`
138
+ <div class="no-results">
139
+ <p>No items found. Try adjusting your search terms or check your connection to the registry.</p>
140
+ <button @click=${() => this.loadTopContent()}>Load Popular Items</button>
141
+ </div>
142
+ ` : ''}
143
+ ${this.main.searchResults.map(item => this.renderSearchResult(item))}
144
+ </div>
145
+ `;
146
+ }
147
+
148
+ renderSearchResult(item) {
149
+ const installedServer = item.category === 'mcp_server' ? this.getInstalledMcpServer(item) : null;
150
+ const isInstalled = !!installedServer;
151
+
152
+ console.log('[SearchSection] Rendering item:', JSON.stringify(item, null, 2));
153
+
154
+ return html`
155
+ <div class="result-item">
156
+ ${this.renderResultAvatar(item)}
157
+ <div class="result-content">
158
+ ${this.renderSemanticBadge(item)}
159
+ ${this.renderResultHeader(item, item.data?.auth_type === 'oauth2')}
160
+ <p class="result-description">${item.description}</p>
161
+ ${this.renderResultMeta(item)}
162
+ ${this.renderResultTags(item)}
163
+ ${this.renderRemote(item)}
164
+ ${this.renderCommandArgs(item)}
165
+ ${this.renderMcpSecretsForm(item, isInstalled, installedServer)}
166
+ ${this.renderResultActions(item, installedServer)}
167
+ </div>
168
+ </div>
169
+ `;
170
+ }
171
+
172
+ renderCommandArgs(item) {
173
+ if (item?.data?.command) {
174
+ const argsString = item?.data?.args?.join(' ') || '';
175
+ const commandLine = `${item.data.command} ${argsString}`.trim();
176
+ if (commandLine.length === 0) return '';
177
+ return html`
178
+ <div class="command-args">
179
+ <strong>Command:</strong>
180
+ <pre><code class="command-line">${commandLine}</code></pre>
181
+ </div>
182
+ `;
183
+ }
184
+ }
185
+
186
+ renderRemote(item) {
187
+ if (item?.data?.url) {
188
+ return html`
189
+ <div class="key-details">${item.data.url}</div>
190
+ `
191
+ } else return '';
192
+ }
193
+
194
+ renderResultAvatar(item) {
195
+ if (item.category !== 'agent') return '';
196
+
197
+ const hasAssets = item.data?.persona_data?.persona_assets;
198
+ const hasHashes = item.data?.persona_data?.asset_hashes;
199
+
200
+ if (hasAssets && (hasAssets.faceref || hasAssets.avatar)) {
201
+ const asset = hasAssets.faceref || hasAssets.avatar;
202
+ return html`
203
+ <div class="result-avatar">
204
+ <img src="data:${asset.type};base64,${asset.data}"
205
+ alt="${item.title} avatar"
206
+ class="agent-avatar-large"
207
+ onerror="this.style.display='none'">
208
+ </div>
209
+ `;
210
+ } else if (hasHashes && (hasHashes.faceref || hasHashes.avatar)) {
211
+ const hash = hasHashes.faceref || hasHashes.avatar;
212
+ return html`
213
+ <div class="result-avatar">
214
+ <img src="${this.state.registryUrl}/assets/${hash}"
215
+ alt="${item.title} avatar"
216
+ class="agent-avatar-large"
217
+ onerror="this.style.display='none'">
218
+ </div>
219
+ `;
220
+ }
221
+
222
+ return '';
223
+ }
224
+
225
+ renderSemanticBadge(item) {
226
+ if (!item.is_semantic) return '';
227
+
228
+ return html`
229
+ <div class="semantic-badge">
230
+ <span class="material-icons">psychology</span>
231
+ Semantic Match ${item.distance_score ? `(${(1 - item.distance_score).toFixed(2)})` : ''}
232
+ </div>
233
+ `;
234
+ }
235
+
236
+ renderResultHeader(item, requiresOAuth) {
237
+ const hasAvatar = item.category === 'agent' &&
238
+ (item.data?.persona_data?.persona_assets?.faceref ||
239
+ item.data?.persona_data?.persona_assets?.avatar ||
240
+ item.data?.persona_data?.asset_hashes?.faceref ||
241
+ item.data?.persona_data?.asset_hashes?.avatar);
242
+
243
+ return html`
244
+ <div class="result-header">
245
+ ${hasAvatar ? html`
246
+ <div class="agent-name-with-face">${item.title}</div>
247
+ ` : html`
248
+ <h4 class="result-title">${item.title}</h4>
249
+ `}
250
+ <span class="result-version">v${item.version}</span>
251
+ ${requiresOAuth ? html`
252
+ <span class="oauth-badge" title="Requires OAuth 2.0 authentication">
253
+ <span class="material-icons">security</span>
254
+ OAuth 2.0
255
+ </span>
256
+ ` : ''}
257
+ </div>
258
+ `;
259
+ }
260
+
261
+ renderResultMeta(item) {
262
+ return html`
263
+ <div class="result-meta">
264
+ <span>Category: ${item.category}</span>
265
+ <span>Downloads: ${item.download_count || 0}</span>
266
+ <span>Rating: ${item.rating || 0}/5</span>
267
+ </div>
268
+ `;
269
+ }
270
+
271
+ renderResultTags(item) {
272
+ if (!item.tags || item.tags.length === 0) return '';
273
+
274
+ return html`
275
+ <div class="result-tags">
276
+ ${item.tags.map(tag => html`<span class="tag">${tag}</span>`)}
277
+ </div>
278
+ `;
279
+ }
280
+
281
+ renderResultActions(item, installedServer) {
282
+ const isMcp = item.category === 'mcp_server';
283
+ const isInstalled = !!installedServer;
284
+
285
+ return html`
286
+ <div class="result-actions">
287
+ ${isMcp ?
288
+ (isInstalled ?
289
+ this.renderInstalledMcpActions(installedServer) :
290
+ this.renderUninstalledMcpActions(item)
291
+ ) :
292
+ (this.state.localPlugins.some(p => p.name === item.title) ?
293
+ html`<div class="installed-badge"><span class="material-icons">check_circle</span> Installed</div>` :
294
+ html`<button class="success" @click=${() => this.installFromRegistry(item)} ?disabled=${this.state.loading}>Install</button>`
295
+ )
296
+ }
297
+ ${item.github_url ? html`
298
+ <a href="${item.github_url}" target="_blank">
299
+ <button>GitHub</button>
300
+ </a>
301
+ ` : ''}
302
+ </div>
303
+ `;
304
+ }
305
+
306
+ renderMcpSecretsForm(item, isInstalled, installedServer) {
307
+ try {
308
+ const isUninstalledLocal = !isInstalled && item.category === 'mcp_server' && item.data?.server_type === 'local';
309
+ const isInstalledLocal = isInstalled && installedServer && installedServer.status !== 'connected' && installedServer.server_type === 'local';
310
+
311
+ if (!isInstalled) { //!isUninstalledLocal && !isInstalledLocal) {
312
+
313
+ console.log('No env vars form because: ',{isUninstalledLocal, isInstalledLocal, item})
314
+ return '';
315
+ }
316
+ console.log("SearchSection] Rendering secrets form for item:", item.title)
317
+
318
+ //const configSource = isInstalledLocal ? installedServer : item.data;
319
+ const configSource = item.data;
320
+
321
+ const configString = JSON.stringify(configSource);
322
+ const placeholderRegex = /<([A-Z0-9_]+)>/g;
323
+ const placeholders = new Set();
324
+
325
+ if (configSource.env) {
326
+ Object.keys(configSource.env).forEach(key => placeholders.add(key));
327
+ }
328
+
329
+ let match;
330
+ while ((match = placeholderRegex.exec(configString)) !== null) {
331
+ placeholders.add(match[1]);
332
+ }
333
+
334
+ const requiredPlaceholders = Array.from(placeholders);
335
+ if (requiredPlaceholders.length === 0) return '';
336
+
337
+ const serverName = isInstalledLocal ? installedServer.name : item.title;
338
+ console.log(`[SearchSection] Rendering secrets form for '${serverName}' with placeholders:`, requiredPlaceholders);
339
+ return html`
340
+ <div class="mcp-secrets-form section" style="margin-top: 1rem; background: rgba(0,0,0,0.2);">
341
+ <h5 class="secrets-title">Required Environment Variables</h5>
342
+ <p class="help-text">Provide values to be used on ${isInstalledLocal ? 'connect' : 'install'}. These are not published.</p>
343
+ ${requiredPlaceholders.map(p => this.renderSecretInput(item, p, serverName))}
344
+ </div>
345
+ `;
346
+ } catch (error) {
347
+ console.error('[SearchSection] Error rendering MCP secrets form:', error);
348
+ return html``
349
+ //return html`<div class="error">Error loading secrets form. Please check the console.</div>`;
350
+ }
351
+ }
352
+
353
+ renderSecretInput(item, placeholder, serverName) {
354
+ const key = serverName || item.id;
355
+ const secretsForItem = this.main.mcpInstallSecrets[key] || {};
356
+ return html`
357
+ <div class="form-group secret-input-group">
358
+ <label for="secret-install-${item.id}-${placeholder}">${placeholder}</label>
359
+ <input type="password"
360
+ id="secret-install-${item.id}-${placeholder}"
361
+ .value=${secretsForItem[placeholder] || ''}
362
+ @input=${e => this.main.handleMcpInstallSecretChange(key, placeholder, e.target.value)} autocomplete="off">
363
+ </div>
364
+ `;
365
+ }
366
+
367
+ renderInstalledMcpActions(server) {
368
+ return html`
369
+ <div class="installed-badge">
370
+ <span class="material-icons">check_circle</span>
371
+ ${server.status === 'connected' ? 'Connected' : 'Installed'}
372
+ </div>
373
+ ${server.status === 'connected' ? html`
374
+ <button class="danger" @click=${() => this.main.toggleMcpServerConnection(server.name, false)} ?disabled=${this.state.loading}>
375
+ Disconnect
376
+ </button>
377
+ ` : html`
378
+ <button class="success" @click=${() => this.main.toggleMcpServerConnection(server.name, true)} ?disabled=${this.state.loading}>
379
+ Connect
380
+ </button>
381
+ `}
382
+ <button class="danger" @click=${() => this.main.removeMcpServer(server.name)} ?disabled=${this.state.loading}>
383
+ Remove
384
+ </button>
385
+ `;
386
+ }
387
+
388
+ renderUninstalledMcpActions(item) {
389
+ const requiresOAuth = item.data && item.data.auth_type === 'oauth2';
390
+ return html`
391
+ <button class="success"
392
+ @click=${() => this.installFromRegistry(item)}
393
+ ?disabled=${this.state.loading}>
394
+ ${requiresOAuth ? 'Connect' : 'Install'}
395
+ </button>
396
+ `;
397
+ }
398
+ }
399
+
400
+ export { RegistrySearchSection };
@@ -0,0 +1,3 @@
1
+ /**
2
+ Backup of registry-search-section.js created before modifications.
3
+ **/
@@ -0,0 +1,69 @@
1
+ // Registry Settings functionality
2
+ export class RegistrySettings {
3
+ constructor(component) {
4
+ this.component = component;
5
+ this.loadRegistryUrl();
6
+ }
7
+
8
+ loadRegistryUrl() {
9
+ // Load from localStorage, environment variable, or default
10
+ this.component.registryUrl = localStorage.getItem('registry_url') ||
11
+ window.MR_REGISTRY_URL ||
12
+ 'https://registry.mindroot.io';
13
+ }
14
+
15
+ updateRegistryUrl(newUrl) {
16
+ this.component.registryUrl = newUrl;
17
+ localStorage.setItem('registry_url', newUrl);
18
+ // Clear auth token when URL changes
19
+ this.component.logout();
20
+ // Reload stats with new URL
21
+ this.component.loadStats();
22
+ }
23
+
24
+ renderSettings() {
25
+ return `
26
+ <details class="settings-section">
27
+ <summary>
28
+ <span class="material-icons">settings</span>
29
+ <span>Settings</span>
30
+ </summary>
31
+ <div class="section">
32
+ <h4>Registry Configuration</h4>
33
+ <div class="form-row">
34
+ <label for="registry-url">Registry URL:</label>
35
+ <input type="url"
36
+ id="registry-url"
37
+ value="${this.component.registryUrl}"
38
+ placeholder="https://registry.mindroot.io">
39
+ <button onclick="registrySettings.handleUrlChange()">Update URL</button>
40
+ <button onclick="registrySettings.testConnection()">Test Connection</button>
41
+ </div>
42
+ <p class="help-text">
43
+ Default: https://registry.mindroot.io or MR_REGISTRY_URL environment variable
44
+ </p>
45
+ </div>
46
+ </details>
47
+ `;
48
+ }
49
+
50
+ handleUrlChange() {
51
+ const input = document.getElementById('registry-url');
52
+ if (input && input.value) {
53
+ this.updateRegistryUrl(input.value);
54
+ }
55
+ }
56
+
57
+ async testConnection() {
58
+ try {
59
+ const response = await fetch(`${this.component.registryUrl}/alive`);
60
+ if (response.ok) {
61
+ alert('Connection successful!');
62
+ } else {
63
+ alert('Connection failed: Server responded with status ' + response.status);
64
+ }
65
+ } catch (error) {
66
+ alert('Connection failed: ' + error.message);
67
+ }
68
+ }
69
+ }