mindroot 9.3.0__py3-none-any.whl → 9.6.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 (183) 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 +105 -9
  14. mindroot/coreplugins/admin/plugin_router_fixed.py +23 -0
  15. mindroot/coreplugins/admin/plugin_router_new_not_working.py +145 -0
  16. mindroot/coreplugins/admin/plugin_routes.py +114 -0
  17. mindroot/coreplugins/admin/registry_settings_routes.py +140 -0
  18. mindroot/coreplugins/admin/router.py +116 -15
  19. mindroot/coreplugins/admin/service_models.py +1 -1
  20. mindroot/coreplugins/admin/settings_router.py +1 -0
  21. mindroot/coreplugins/admin/static/css/admin-custom.css +357 -2
  22. mindroot/coreplugins/admin/static/css/dark.css +1 -0
  23. mindroot/coreplugins/admin/static/css/default.css +4 -0
  24. mindroot/coreplugins/admin/static/js/about-info.js +367 -0
  25. mindroot/coreplugins/admin/static/js/agent-form.js +83 -3
  26. mindroot/coreplugins/admin/static/js/api-key-script.js +307 -0
  27. mindroot/coreplugins/admin/static/js/mcp-manager.js +348 -0
  28. mindroot/coreplugins/admin/static/js/mcp-publisher.js +780 -0
  29. mindroot/coreplugins/admin/static/js/persona-editor.js +34 -5
  30. mindroot/coreplugins/admin/static/js/plugin-toggle.js +1 -1
  31. mindroot/coreplugins/admin/static/js/recommended-plugin-install.js +63 -0
  32. mindroot/coreplugins/admin/static/js/registry-auth-section.js +132 -0
  33. mindroot/coreplugins/admin/static/js/registry-manager-base.js +613 -0
  34. mindroot/coreplugins/admin/static/js/registry-manager-publish-old-delete.js +166 -0
  35. mindroot/coreplugins/admin/static/js/registry-manager.js +351 -0
  36. mindroot/coreplugins/admin/static/js/registry-publish-section.js +377 -0
  37. mindroot/coreplugins/admin/static/js/registry-search-section.js +400 -0
  38. mindroot/coreplugins/admin/static/js/registry-search-section.js.bak +3 -0
  39. mindroot/coreplugins/admin/static/js/registry-settings.js +69 -0
  40. mindroot/coreplugins/admin/static/js/registry-shared-services.js +903 -0
  41. mindroot/coreplugins/admin/static/js/registry-simple-sections.js +85 -0
  42. mindroot/coreplugins/admin/static/js/secure-widget-manager.js +438 -0
  43. mindroot/coreplugins/admin/static/logo.png +0 -0
  44. mindroot/coreplugins/admin/templates/admin.jinja2 +275 -110
  45. mindroot/coreplugins/agent/Assistant/agent.json +27 -11
  46. mindroot/coreplugins/agent/agent.py +2 -2
  47. mindroot/coreplugins/agent/command_parser.py +25 -10
  48. mindroot/coreplugins/agent/templates/system.jinja2 +0 -12
  49. mindroot/coreplugins/chat/__init__.py +4 -1
  50. mindroot/coreplugins/chat/router.py +132 -20
  51. mindroot/coreplugins/chat/router_dedup_patch.py +20 -0
  52. mindroot/coreplugins/chat/services.py +31 -1
  53. mindroot/coreplugins/chat/static/css/action-fix.css +32 -0
  54. mindroot/coreplugins/chat/static/css/admin-custom.css +5 -3
  55. mindroot/coreplugins/chat/static/css/dark.css +24 -3
  56. mindroot/coreplugins/chat/static/css/default.css +24 -3
  57. mindroot/coreplugins/chat/static/css/main.css +1 -0
  58. mindroot/coreplugins/chat/static/js/action.js +137 -60
  59. mindroot/coreplugins/chat/static/js/chat-history.js +3 -0
  60. mindroot/coreplugins/chat/static/js/chat.js +59 -16
  61. mindroot/coreplugins/chat/static/js/chat.js.diff +221 -0
  62. mindroot/coreplugins/chat/static/js/chatform.js +2 -2
  63. mindroot/coreplugins/chat/static/site.webmanifest +1 -1
  64. mindroot/coreplugins/chat/templates/chat.jinja2 +3 -3
  65. mindroot/coreplugins/chat/widget_manager.py +139 -0
  66. mindroot/coreplugins/chat/widget_routes.py +287 -0
  67. mindroot/coreplugins/check_list/inject/admin.jinja2 +1 -1
  68. mindroot/coreplugins/email/__init__.py +2 -0
  69. mindroot/coreplugins/email/email_provider.py +2 -2
  70. mindroot/coreplugins/email/mod.py +100 -0
  71. mindroot/coreplugins/email/services.py +5 -3
  72. mindroot/coreplugins/email/smtp_handler.py +9 -3
  73. mindroot/coreplugins/email/test_email_service.py +75 -0
  74. mindroot/coreplugins/env_manager/mod.py +61 -25
  75. mindroot/coreplugins/home/router.py +37 -2
  76. mindroot/coreplugins/home/static/imgs/logo.png +0 -0
  77. mindroot/coreplugins/home/static/imgs/logo.png.bak +0 -0
  78. mindroot/coreplugins/home/static/imgs/logo_teal.png +0 -0
  79. mindroot/coreplugins/home/static/imgs/logo_teal2.png +0 -0
  80. mindroot/coreplugins/home/static/imgs/logo_teal_detailed.png +0 -0
  81. mindroot/coreplugins/home/static/imgs/logo_teal_python.png +0 -0
  82. mindroot/coreplugins/home/templates/home.jinja2 +15 -6
  83. mindroot/coreplugins/index/indices/default/index.json +39 -6
  84. mindroot/coreplugins/jwt_auth/middleware.py +47 -2
  85. mindroot/coreplugins/jwt_auth/mod.py +40 -17
  86. mindroot/coreplugins/l8n/__init__.py +6 -0
  87. mindroot/coreplugins/l8n/debug_loader.py +85 -0
  88. mindroot/coreplugins/l8n/debug_middleware.py +74 -0
  89. mindroot/coreplugins/l8n/l8n_constants.py +19 -0
  90. mindroot/coreplugins/l8n/language_detection.py +183 -0
  91. mindroot/coreplugins/l8n/middleware.py +151 -0
  92. mindroot/coreplugins/l8n/mod.py +277 -0
  93. mindroot/coreplugins/l8n/monkey_patch_to_delete.py +186 -0
  94. mindroot/coreplugins/l8n/test_enhanced.py +298 -0
  95. mindroot/coreplugins/l8n/test_l8n.py +95 -0
  96. mindroot/coreplugins/l8n/test_l8n_standalone.py +251 -0
  97. mindroot/coreplugins/l8n/test_middleware.py +272 -0
  98. mindroot/coreplugins/l8n/utils.py +232 -0
  99. mindroot/coreplugins/mcp_/__init__.py +14 -0
  100. mindroot/coreplugins/mcp_/catalog_commands.py +328 -0
  101. mindroot/coreplugins/mcp_/catalog_manager.py +263 -0
  102. mindroot/coreplugins/mcp_/dynamic_commands.py +154 -0
  103. mindroot/coreplugins/mcp_/mcp_manager.py +1031 -0
  104. mindroot/coreplugins/mcp_/mod.py +367 -0
  105. mindroot/coreplugins/mcp_/oauth_storage.py +144 -0
  106. mindroot/coreplugins/mcp_/server_installer.py +79 -0
  107. mindroot/coreplugins/mcp_/setup.py +26 -0
  108. mindroot/coreplugins/mcp_/test_dynamic_commands.py +134 -0
  109. mindroot/coreplugins/mcp_/testmcpclient.py +92 -0
  110. mindroot/coreplugins/persona/mod.py +12 -7
  111. mindroot/coreplugins/signup/templates/signup.jinja2 +1 -1
  112. mindroot/coreplugins/subscriptions/__init__.py +1 -0
  113. mindroot/coreplugins/subscriptions/mod.py +14 -3
  114. mindroot/coreplugins/subscriptions/router.py +3 -0
  115. mindroot/coreplugins/user_service/__init__.py +1 -2
  116. mindroot/coreplugins/user_service/admin_init.py +1 -0
  117. mindroot/coreplugins/user_service/email_service.py +72 -17
  118. mindroot/coreplugins/user_service/mod.py +10 -2
  119. mindroot/coreplugins/user_service/router.py +2 -0
  120. mindroot/lib/auth/api_key.py +28 -0
  121. mindroot/lib/cli/plugins.py +94 -0
  122. mindroot/lib/plugins/default_plugin_manifest.json +20 -0
  123. mindroot/lib/plugins/installation.py +5 -5
  124. mindroot/lib/plugins/l8n_static_handler.py +225 -0
  125. mindroot/lib/plugins/loader.py +33 -3
  126. mindroot/lib/plugins/loader_with_l8n.py +281 -0
  127. mindroot/lib/plugins/manifest.py +236 -24
  128. mindroot/lib/providers/commands.py +3 -1
  129. mindroot/lib/route_decorators.py +5 -5
  130. mindroot/lib/templates.py +183 -11
  131. mindroot/lib/utils/merge_arrays.py +1 -1
  132. mindroot/migrate.py +39 -20
  133. mindroot/registry/data_access.py +1 -1
  134. mindroot/server.py +42 -13
  135. mindroot/server_missing_normal_args.py +197 -0
  136. mindroot/server_prev.py +173 -0
  137. {mindroot-9.3.0.dist-info → mindroot-9.6.0.dist-info}/METADATA +7 -2
  138. {mindroot-9.3.0.dist-info → mindroot-9.6.0.dist-info}/RECORD +143 -113
  139. mindroot/coreplugins/admin/plugin_manager_backup.py +0 -615
  140. mindroot/coreplugins/admin/static/favicon/about.txt +0 -6
  141. mindroot/coreplugins/admin/static/favicon/android-chrome-512x512.png +0 -0
  142. mindroot/coreplugins/admin/static/favicon/apple-touch-icon.png +0 -0
  143. mindroot/coreplugins/admin/static/favicon/favicon-16x16.png +0 -0
  144. mindroot/coreplugins/admin/static/favicon/favicon-32x32.png +0 -0
  145. mindroot/coreplugins/admin/static/favicon/favicon.ico +0 -0
  146. mindroot/coreplugins/admin/static/favicon/favicon_io (1)/about.txt +0 -6
  147. mindroot/coreplugins/admin/static/favicon/favicon_io (1)/android-chrome-192x192.png +0 -0
  148. mindroot/coreplugins/admin/static/favicon/favicon_io (1)/android-chrome-512x512.png +0 -0
  149. mindroot/coreplugins/admin/static/favicon/favicon_io (1)/apple-touch-icon.png +0 -0
  150. mindroot/coreplugins/admin/static/favicon/favicon_io (1)/favicon-16x16.png +0 -0
  151. mindroot/coreplugins/admin/static/favicon/favicon_io (1)/favicon-32x32.png +0 -0
  152. mindroot/coreplugins/admin/static/favicon/favicon_io (1)/favicon.ico +0 -0
  153. mindroot/coreplugins/admin/static/favicon/favicon_io (1)/site.webmanifest +0 -1
  154. mindroot/coreplugins/admin/static/favicon/logo.png +0 -0
  155. mindroot/coreplugins/admin/static/favicon/site.webmanifest +0 -1
  156. mindroot/coreplugins/admin/static/js/backup/agent-editor.js +0 -186
  157. mindroot/coreplugins/admin/static/js/backup/agent-form.js +0 -1133
  158. mindroot/coreplugins/admin/static/js/backup/agent-list.js +0 -94
  159. mindroot/coreplugins/chat/static/favicon/about.txt +0 -6
  160. mindroot/coreplugins/chat/static/favicon/android-chrome-192x192.png +0 -0
  161. mindroot/coreplugins/chat/static/favicon/android-chrome-512x512.png +0 -0
  162. mindroot/coreplugins/chat/static/favicon/apple-touch-icon.png +0 -0
  163. mindroot/coreplugins/chat/static/favicon/favicon-16x16.png +0 -0
  164. mindroot/coreplugins/chat/static/favicon/favicon-32x32.png +0 -0
  165. mindroot/coreplugins/chat/static/favicon/favicon.ico +0 -0
  166. mindroot/coreplugins/chat/static/favicon/favicon_io (1)/about.txt +0 -6
  167. mindroot/coreplugins/chat/static/favicon/favicon_io (1)/android-chrome-192x192.png +0 -0
  168. mindroot/coreplugins/chat/static/favicon/favicon_io (1)/android-chrome-512x512.png +0 -0
  169. mindroot/coreplugins/chat/static/favicon/favicon_io (1)/apple-touch-icon.png +0 -0
  170. mindroot/coreplugins/chat/static/favicon/favicon_io (1)/favicon-16x16.png +0 -0
  171. mindroot/coreplugins/chat/static/favicon/favicon_io (1)/favicon-32x32.png +0 -0
  172. mindroot/coreplugins/chat/static/favicon/favicon_io (1)/favicon.ico +0 -0
  173. mindroot/coreplugins/chat/static/favicon/favicon_io (1)/site.webmanifest +0 -1
  174. mindroot/coreplugins/chat/static/favicon/logo.png +0 -0
  175. mindroot/coreplugins/chat/static/favicon/site.webmanifest +0 -1
  176. mindroot/coreplugins/index/default.json +0 -76
  177. mindroot/coreplugins/user_service/file_trigger_service.py +0 -12
  178. mindroot/coreplugins/user_service/hooks.py +0 -23
  179. /mindroot/coreplugins/{admin/static/favicon/android-chrome-192x192.png → home/static/imgs/backuplogo.png} +0 -0
  180. {mindroot-9.3.0.dist-info → mindroot-9.6.0.dist-info}/WHEEL +0 -0
  181. {mindroot-9.3.0.dist-info → mindroot-9.6.0.dist-info}/entry_points.txt +0 -0
  182. {mindroot-9.3.0.dist-info → mindroot-9.6.0.dist-info}/licenses/LICENSE +0 -0
  183. {mindroot-9.3.0.dist-info → mindroot-9.6.0.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,166 @@
1
+ // Additional methods for publishing functionality
2
+
3
+ export function addPublishMethods(RegistryManager) {
4
+ // Add publish tab to tabs
5
+ RegistryManager.prototype.renderTabsWithPublish = function() {
6
+ return `
7
+ <div class="tabs">
8
+ <div class="tab ${this.activeTab === 'search' ? 'active' : ''}"
9
+ onclick="this.activeTab = 'search'; this.requestUpdate();">Search</div>
10
+ ${this.isLoggedIn ? `
11
+ <div class="tab ${this.activeTab === 'publish' ? 'active' : ''}"
12
+ onclick="this.activeTab = 'publish'; this.requestUpdate();">Publish</div>
13
+ ` : ''}
14
+ <div class="tab ${this.activeTab === 'stats' ? 'active' : ''}"
15
+ onclick="this.activeTab = 'stats'; this.requestUpdate();">Stats</div>
16
+ </div>
17
+ `;
18
+ };
19
+
20
+ // Render publish content
21
+ RegistryManager.prototype.renderPublish = function() {
22
+ if (!this.isLoggedIn) {
23
+ return `
24
+ <div class="section">
25
+ <h3>Publish to Registry</h3>
26
+ <p>Please log in to publish content.</p>
27
+ </div>
28
+ `;
29
+ }
30
+
31
+ return `
32
+ <div class="section">
33
+ <h3>Publish Plugin</h3>
34
+ <div class="publish-form">
35
+ <input type="text" placeholder="Plugin Title" id="plugin-title">
36
+ <textarea placeholder="Description" id="plugin-description"></textarea>
37
+ <input type="text" placeholder="Version (e.g., 1.0.0)" id="plugin-version">
38
+ <input type="text" placeholder="GitHub URL (e.g., user/repo)" id="plugin-github">
39
+ <input type="text" placeholder="OR PyPI Module Name" id="plugin-pypi">
40
+ <input type="text" placeholder="Tags (comma separated)" id="plugin-tags">
41
+ <button class="primary" onclick="this.handlePublishPlugin()">Publish Plugin</button>
42
+ </div>
43
+ </div>
44
+
45
+ <div class="section">
46
+ <h3>Publish Agent</h3>
47
+ <div class="publish-form">
48
+ <select id="agent-select">
49
+ <option value="">Select an agent...</option>
50
+ ${this.localAgents.map(agent => `<option value="${agent.name}">${agent.name}</option>`).join('')}
51
+ </select>
52
+ <textarea placeholder="Description" id="agent-description"></textarea>
53
+ <input type="text" placeholder="Version (e.g., 1.0.0)" id="agent-version">
54
+ <input type="text" placeholder="Tags (comma separated)" id="agent-tags">
55
+ <button class="primary" onclick="this.handlePublishAgent()">Publish Agent</button>
56
+ </div>
57
+ </div>
58
+ `;
59
+ };
60
+
61
+ // Handle plugin publishing from GitHub
62
+ RegistryManager.prototype.handlePublishPluginFromGithub = async function() {
63
+ const repo = this.shadowRoot.getElementById('plugin-github-repo').value;
64
+ if (!repo || !repo.includes('/')) {
65
+ this.error = 'Please provide a valid GitHub repository (e.g., user/repo)';
66
+ this.requestUpdate();
67
+ return;
68
+ }
69
+
70
+ this.loading = true;
71
+ this.error = '';
72
+
73
+ try {
74
+ const response = await fetch('/admin/plugins/publish_from_github', {
75
+ method: 'POST',
76
+ headers: {
77
+ 'Content-Type': 'application/json',
78
+ 'Authorization': `Bearer ${this.authToken}`
79
+ },
80
+ body: JSON.stringify({ repo: repo })
81
+ });
82
+
83
+ if (response.ok) {
84
+ const result = await response.json();
85
+ this.error = result.message || 'Published successfully!';
86
+ this.shadowRoot.getElementById('plugin-github-repo').value = '';
87
+ setTimeout(() => { this.error = ''; this.requestUpdate(); }, 3000);
88
+ } else {
89
+ const errorData = await response.json();
90
+ this.error = errorData.detail || 'Publishing failed';
91
+ }
92
+ } catch (error) {
93
+ this.error = 'Network error: ' + error.message;
94
+ }
95
+
96
+ this.loading = false;
97
+ this.requestUpdate();
98
+ };
99
+
100
+ // Handle agent publishing
101
+ RegistryManager.prototype.handlePublishAgent = async function() {
102
+ const selectedAgent = this.shadowRoot.getElementById('agent-select').value;
103
+ const description = this.shadowRoot.getElementById('agent-description').value;
104
+ const version = this.shadowRoot.getElementById('agent-version').value;
105
+ const tags = this.shadowRoot.getElementById('agent-tags').value;
106
+
107
+ if (!selectedAgent || !description || !version) {
108
+ this.error = 'Please select an agent and fill in description and version';
109
+ this.requestUpdate();
110
+ return;
111
+ }
112
+
113
+ const agentData = this.localAgents.find(agent => agent.name === selectedAgent);
114
+ if (!agentData) {
115
+ this.error = 'Selected agent not found';
116
+ this.requestUpdate();
117
+ return;
118
+ }
119
+
120
+ const publishData = {
121
+ title: selectedAgent,
122
+ description: description,
123
+ category: 'agent',
124
+ content_type: 'mindroot_agent',
125
+ version: version,
126
+ data: agentData,
127
+ tags: tags ? tags.split(',').map(t => t.trim()) : []
128
+ };
129
+
130
+ await this.publishToRegistry(publishData);
131
+ };
132
+
133
+ // Publish to registry
134
+ RegistryManager.prototype.publishToRegistry = async function(publishData) {
135
+ this.loading = true;
136
+ this.error = '';
137
+
138
+ try {
139
+ const response = await fetch(`${this.registryUrl}/publish`, {
140
+ method: 'POST',
141
+ headers: {
142
+ 'Content-Type': 'application/json',
143
+ 'Authorization': `Bearer ${this.authToken}`
144
+ },
145
+ body: JSON.stringify(publishData)
146
+ });
147
+
148
+ if (response.ok) {
149
+ this.error = 'Published successfully!';
150
+ // Clear form fields
151
+ setTimeout(() => {
152
+ this.error = '';
153
+ this.requestUpdate();
154
+ }, 3000);
155
+ } else {
156
+ const errorData = await response.json();
157
+ this.error = errorData.detail || 'Publishing failed';
158
+ }
159
+ } catch (error) {
160
+ this.error = 'Network error: ' + error.message;
161
+ }
162
+
163
+ this.loading = false;
164
+ this.requestUpdate();
165
+ };
166
+ }
@@ -0,0 +1,351 @@
1
+ import { html } from '/admin/static/js/lit-core.min.js';
2
+ import { RegistryManagerBase } from './registry-manager-base.js';
3
+ import { RegistrySharedServices } from './registry-shared-services.js';
4
+ import { RegistryAuthSection } from './registry-auth-section.js';
5
+ import { RegistrySearchSection } from './registry-search-section.js';
6
+ import { RegistryPublishSection } from './registry-publish-section.js';
7
+ import { RegistrySimpleSections } from './registry-simple-sections.js';
8
+ import "./mcp-publisher.js";
9
+
10
+ class RegistryManager extends RegistryManagerBase {
11
+ constructor() {
12
+ super();
13
+ this.localMcpServers = [];
14
+ this.searchTimeout = null;
15
+ this.isSecretModalOpen = false;
16
+ this.serverForSecrets = null;
17
+ this.placeholderValues = {};
18
+ this.mcpInstallSecrets = {}; // New state for install-time secrets
19
+
20
+ // Initialize shared state
21
+ this.sharedState = {
22
+ authToken: this.authToken,
23
+ currentUser: this.currentUser,
24
+ isLoggedIn: this.isLoggedIn,
25
+ localContent: {},
26
+ loading: this.loading,
27
+ registryUrl: this.registryUrl,
28
+ localPlugins: this.localPlugins,
29
+ localAgents: this.localAgents
30
+ };
31
+
32
+ this.initializeModules();
33
+ }
34
+
35
+ initializeModules() {
36
+ // Initialize services first
37
+ this.services = new RegistrySharedServices(this.sharedState, this);
38
+
39
+ // Initialize sections
40
+ this.authSection = new RegistryAuthSection(this.sharedState, this);
41
+ this.searchSection = new RegistrySearchSection(this.sharedState, this);
42
+ this.publishSection = new RegistryPublishSection(this.sharedState, this);
43
+ this.simpleSections = new RegistrySimpleSections(this.sharedState, this);
44
+
45
+ // Set services reference for all sections
46
+ this.authSection.setServices(this.services);
47
+ this.searchSection.setServices(this.services);
48
+ this.publishSection.setServices(this.services);
49
+ this.simpleSections.setServices(this.services);
50
+
51
+ // Initialize data
52
+ this.services.checkAuthStatus();
53
+ this.services.loadStats();
54
+ this.services.loadLocalContent();
55
+ }
56
+
57
+ // Return true if an agent with this name is already present in localAgents
58
+ isAgentInstalled(name) {
59
+ return (this.localAgents || []).some(a => a.name === name);
60
+ }
61
+
62
+ // === MCP Server Management (kept in main component for now) ===
63
+
64
+ async toggleMcpServerConnection(serverName, connect) {
65
+ if (!connect) {
66
+ // Disconnecting doesn't require secrets, so proceed directly
67
+ return this.performConnectionToggle(serverName, false);
68
+ }
69
+
70
+ // Check for secrets from the inline form first
71
+ const inlineSecrets = this.mcpInstallSecrets[serverName];
72
+ const hasInlineSecrets = inlineSecrets && Object.keys(inlineSecrets).length > 0;
73
+
74
+ if (hasInlineSecrets) {
75
+ console.log(`[RegistryManager] Found inline secrets for ${serverName}, connecting directly.`);
76
+ return this.performConnectionToggle(serverName, true, inlineSecrets);
77
+ }
78
+
79
+ // Find the full server definition
80
+ const server = this.localMcpServers.find(s => s.name === serverName);
81
+ if (!server) {
82
+ this.showToast(`Error: Could not find local server definition for '${serverName}'.`, 'error');
83
+ return;
84
+ }
85
+
86
+ // Scan for placeholders
87
+ const configString = JSON.stringify(server);
88
+ const placeholderRegex = /<([A-Z0-9_]+)>|\${([A-Z0-9_]+)}/g;
89
+ const placeholders = new Set();
90
+ let match;
91
+ while ((match = placeholderRegex.exec(configString)) !== null) {
92
+ placeholders.add(match[1] || match[2]);
93
+ }
94
+
95
+ if (placeholders.size > 0) {
96
+ // Placeholders found, open modal to ask for secrets
97
+ this.serverForSecrets = { name: serverName, placeholders: Array.from(placeholders) };
98
+ this.placeholderValues = {};
99
+ this.isSecretModalOpen = true;
100
+ } else {
101
+ // No placeholders, connect directly
102
+ await this.performConnectionToggle(serverName, true);
103
+ }
104
+ }
105
+
106
+ async performConnectionToggle(serverName, connect, secrets = null) {
107
+ this.loading = true;
108
+ const action = connect ? 'connect' : 'disconnect';
109
+ try {
110
+ const response = await fetch(`/admin/mcp/${action}`, {
111
+ method: 'POST',
112
+ headers: { 'Content-Type': 'application/json' },
113
+ body: JSON.stringify({ server_name: serverName, secrets })
114
+ });
115
+ if (response.ok) {
116
+ this.showToast(`Server '${serverName}' ${action}ed successfully.`, 'success');
117
+ await this.services.loadLocalContent();
118
+ } else {
119
+ const err = await response.json();
120
+ throw new Error(err.detail || `Failed to ${action} server`);
121
+ }
122
+ } catch (error) {
123
+ this.showToast(`Error: ${error.message}`, 'error');
124
+ } finally {
125
+ this.loading = false;
126
+ }
127
+ }
128
+
129
+ async handleSecretSubmit() {
130
+ const { name } = this.serverForSecrets;
131
+ await this.performConnectionToggle(name, true, this.placeholderValues);
132
+ this.isSecretModalOpen = false;
133
+ this.serverForSecrets = null;
134
+ }
135
+
136
+ handleMcpInstallSecretChange(key, placeholder, value) {
137
+ console.log(`[RegistryManager] Secret input for key '${key}', placeholder '${placeholder}'`);
138
+ if (!this.mcpInstallSecrets[key]) {
139
+ this.mcpInstallSecrets[key] = {};
140
+ }
141
+ this.mcpInstallSecrets[key][placeholder] = value;
142
+ console.log('[RegistryManager] Current install secrets state:', JSON.stringify(this.mcpInstallSecrets));
143
+ }
144
+
145
+ async removeMcpServer(serverName) {
146
+ if (!confirm(`Are you sure you want to remove the MCP server '${serverName}'?`)) return;
147
+ this.loading = true;
148
+ try {
149
+ const response = await fetch('/admin/mcp/remove', {
150
+ method: 'POST',
151
+ headers: { 'Content-Type': 'application/json' },
152
+ body: JSON.stringify({ server_name: serverName })
153
+ });
154
+ if (response.ok) {
155
+ this.showToast(`Server '${serverName}' removed.`, 'success');
156
+ await this.services.loadLocalContent();
157
+ } else {
158
+ const err = await response.json();
159
+ throw new Error(err.detail || 'Failed to remove server');
160
+ }
161
+ } catch (error) {
162
+ this.showToast(`Error: ${error.message}`, 'error');
163
+ } finally {
164
+ this.loading = false;
165
+ }
166
+ }
167
+
168
+ // === Main Render Method ===
169
+
170
+ _render() {
171
+ return html`
172
+ <div class="registry-manager">
173
+ ${this.renderToasts()}
174
+ ${this.isSecretModalOpen ? this.renderSecretPromptModal() : ''}
175
+ ${this.authSection.renderHeader()}
176
+ ${this.renderTabs()}
177
+ ${this.renderContent()}
178
+ </div>
179
+ `;
180
+ }
181
+
182
+ renderSecretPromptModal() {
183
+ if (!this.serverForSecrets) return '';
184
+
185
+ return html`
186
+ <div class="modal-overlay">
187
+ <div class="modal-content">
188
+ <h3>Provide Secrets for ${this.serverForSecrets.name}</h3>
189
+ <p class="help-text">Enter the required values to connect. These are not stored.</p>
190
+ <div class="form-group">
191
+ ${this.serverForSecrets.placeholders.map(p => html`
192
+ <label for="secret-${p}">${p}</label>
193
+ <input type="password"
194
+ id="secret-${p}"
195
+ @input=${e => this.placeholderValues[p] = e.target.value}>
196
+ `)}
197
+ </div>
198
+ <div class="modal-actions">
199
+ <button @click=${() => this.isSecretModalOpen = false}>Cancel</button>
200
+ <button class="primary" @click=${this.handleSecretSubmit}>Connect</button>
201
+ </div>
202
+ </div>
203
+ </div>
204
+ `;
205
+ }
206
+
207
+ renderTabs() {
208
+ return html`
209
+ <div class="tabs">
210
+ <div class="tab ${this.activeTab === 'search' ? 'active' : ''}"
211
+ @click=${() => this.activeTab = 'search'}>Search</div>
212
+ <div class="tab ${this.activeTab === 'publish' ? 'active' : ''}"
213
+ @click=${() => this.activeTab = 'publish'}>Publish</div>
214
+ <div class="tab ${this.activeTab === 'stats' ? 'active' : ''}"
215
+ @click=${() => this.activeTab = 'stats'}>Stats</div>
216
+ <div class="tab ${this.activeTab === 'settings' ? 'active' : ''}"
217
+ @click=${() => this.activeTab = 'settings'}>Settings</div>
218
+ </div>
219
+ `;
220
+ }
221
+
222
+ renderContent() {
223
+ switch (this.activeTab) {
224
+ case 'search':
225
+ return this.searchSection.renderSearch();
226
+ case 'publish':
227
+ return this.publishSection.renderPublish();
228
+ case 'stats':
229
+ return this.simpleSections.renderStats();
230
+ case 'settings':
231
+ return this.simpleSections.renderSettings();
232
+ default:
233
+ return this.searchSection.renderSearch();
234
+ }
235
+ }
236
+
237
+ // === Legacy Methods (for backward compatibility) ===
238
+ // These delegate to the services
239
+
240
+ async checkAuthStatus() {
241
+ return this.services.checkAuthStatus();
242
+ }
243
+
244
+ async loadStats() {
245
+ return this.services.loadStats();
246
+ }
247
+
248
+ async loadLocalContent() {
249
+ return this.services.loadLocalContent();
250
+ }
251
+
252
+ async handleLogin() {
253
+ return this.authSection.handleLogin();
254
+ }
255
+
256
+ async login(username, password) {
257
+ return this.services.login(username, password);
258
+ }
259
+
260
+ async handleRegister() {
261
+ return this.authSection.handleRegister();
262
+ }
263
+
264
+ async register(username, email, password) {
265
+ return this.services.register(username, email, password);
266
+ }
267
+
268
+ toggleRegisterForm() {
269
+ return this.authSection.toggleRegisterForm();
270
+ }
271
+
272
+ logout() {
273
+ return this.authSection.logout();
274
+ }
275
+
276
+ async loadTopContent() {
277
+ return this.services.loadTopContent();
278
+ }
279
+
280
+ async search(query, category) {
281
+ return this.services.search(query, category);
282
+ }
283
+
284
+ handleSearchInput(e) {
285
+ return this.searchSection.handleSearchInput(e);
286
+ }
287
+
288
+ handleCategoryChange(category) {
289
+ return this.searchSection.handleCategoryChange(category);
290
+ }
291
+
292
+ async installFromRegistry(item) {
293
+ return this.services.installFromRegistry(item);
294
+ }
295
+
296
+ async installMcpServer(item) {
297
+ return this.services.installMcpServer(item);
298
+ }
299
+
300
+ async installOAuthMcpServer(item) {
301
+ return this.services.installOAuthMcpServer(item);
302
+ }
303
+
304
+ async installPlugin(item) {
305
+ return this.services.installPlugin(item);
306
+ }
307
+
308
+ async installAgent(item) {
309
+ return this.services.installAgent(item);
310
+ }
311
+
312
+ async handlePublishPluginFromGithub() {
313
+ return this.publishSection.handlePublishPluginFromGithub();
314
+ }
315
+
316
+ async refreshOwnershipCache() {
317
+ return this.services.refreshOwnershipCache();
318
+ }
319
+
320
+ async publishItem(item, type) {
321
+ return this.publishSection.publishItem(item, type);
322
+ }
323
+
324
+ async updateRegistryUrl(newUrl) {
325
+ return this.services.updateRegistryUrl(newUrl);
326
+ }
327
+
328
+ async testConnection() {
329
+ return this.services.testConnection();
330
+ }
331
+
332
+ // === Utility Methods ===
333
+
334
+ showSuccessMessage(message) {
335
+ this.error = '';
336
+ this.requestUpdate();
337
+
338
+ setTimeout(() => {
339
+ this.publishSuccess = '';
340
+ this.requestUpdate();
341
+ }, 5000);
342
+ }
343
+
344
+ showErrorMessage(message) {
345
+ this.error = message;
346
+ this.publishSuccess = '';
347
+ this.requestUpdate();
348
+ }
349
+ }
350
+
351
+ customElements.define('registry-manager', RegistryManager);