|
1 | 1 | <!DOCTYPE html> |
2 | 2 | <html lang="en"> |
3 | 3 | <head> |
4 | | - <meta charset="UTF-8"> |
5 | | - <meta name="viewport" content="width=device-width, initial-scale=1.0"> |
6 | | - <meta http-equiv="Content-Security-Policy" content="default-src 'self'; script-src 'self' 'nonce-{{nonce}}' https://github.com; style-src 'self' 'unsafe-inline'; connect-src 'self' wss://webxos.netlify.app https://api.github.com; img-src 'self' data:;"> |
7 | | - <meta http-equiv="X-Frame-Options" content="DENY"> |
8 | | - <meta http-equiv="X-Content-Type-Options" content="nosniff"> |
9 | | - <meta http-equiv="Referrer-Policy" content="strict-origin-when-cross-origin"> |
10 | | - <title>Vial MCP Controller</title> |
11 | | - <link rel="manifest" href="/manifest.json"> |
12 | | - <link rel="stylesheet" href="/css/tailwind.min.css"> |
| 4 | + <meta charset="UTF-8"> |
| 5 | + <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no"> |
| 6 | + <title>Vial MCP (BETA)</title> |
| 7 | + <link rel="stylesheet" href="css/vial-mcp.css"> |
13 | 8 | </head> |
14 | | -<body class="bg-gray-100 font-sans"> |
15 | | - <div class="container mx-auto p-4"> |
16 | | - <h1 class="text-2xl font-bold mb-4">Vial MCP Controller</h1> |
17 | | - |
18 | | - <div class="mb-4"> |
19 | | - <p><strong>Status:</strong> <span id="status">Initializing</span></p> |
20 | | - <p><strong>Mode:</strong> <span id="mode">Initializing</span></p> |
21 | | - <p><strong>WebSocket:</strong> <span id="websocket-status">Disconnected</span></p> |
22 | | - <p><strong>Quantum Sync:</strong> <span id="quantum-status">Disconnected</span></p> |
23 | | - <p><strong>Wallet:</strong> <span id="wallet-status">Disabled</span></p> |
24 | | - <p><strong>Network:</strong> <span id="network-status">Checking...</span></p> |
25 | | - <p><strong>Sync Progress:</strong> <span id="sync-progress">No pending operations</span></p> |
26 | | - </div> |
27 | | - |
28 | | - <div class="mb-4"> |
29 | | - <p><strong>User ID:</strong> <span id="user-id">Not logged in</span></p> |
30 | | - <p><strong>Balance:</strong> <span id="balance">0 $WEBXOS</span></p> |
31 | | - <p><strong>Reputation:</strong> <span id="reputation">0</span></p> |
32 | | - <p><strong>Wallet Address:</strong> <span id="wallet-address">None</span></p> |
33 | | - </div> |
34 | | - |
35 | | - <div class="mb-4"> |
36 | | - <p><strong>Vial 1:</strong> <span id="vial1-status">Stopped (Balance: 0)</span></p> |
37 | | - <p><strong>Vial 2:</strong> <span id="vial2-status">Stopped (Balance: 0)</span></p> |
38 | | - <p><strong>Vial 3:</strong> <span id="vial3-status">Stopped (Balance: 0)</span></p> |
39 | | - <p><strong>Vial 4:</strong> <span id="vial4-status">Stopped (Balance: 0)</span></p> |
40 | | - </div> |
41 | | - |
42 | | - <div class="mb-4"> |
43 | | - <h2 class="text-xl font-bold mb-2">Two-Factor Authentication</h2> |
44 | | - <div id="2fa-setup" class="bg-white p-4 rounded shadow"> |
45 | | - <img id="2fa-qr-code" class="hidden" src="" alt="2FA QR Code"> |
46 | | - <input id="2fa-code" class="w-full p-2 border rounded mb-2" placeholder="Enter 2FA code"> |
47 | | - <button id="enable-2fa-btn" class="bg-blue-500 text-white px-4 py-2 rounded" disabled>Enable 2FA</button> |
48 | | - <button id="verify-2fa-btn" class="bg-green-500 text-white px-4 py-2 rounded" disabled>Verify 2FA</button> |
49 | | - </div> |
50 | | - </div> |
51 | | - |
52 | | - <div class="mb-4"> |
53 | | - <h2 class="text-xl font-bold mb-2">Transaction History</h2> |
54 | | - <div id="transaction-history" class="bg-white p-4 rounded shadow"></div> |
55 | | - </div> |
56 | | - |
57 | | - <div class="mb-4"> |
58 | | - <h2 class="text-xl font-bold mb-2">Security KPIs</h2> |
59 | | - <div id="kpi-dashboard" class="bg-white p-4 rounded shadow"> |
60 | | - <p><strong>Auth Success Rate:</strong> <span id="kpi-auth-success">N/A</span>%</p> |
61 | | - <p><strong>Auth Failures:</strong> <span id="kpi-auth-failures">N/A</span></p> |
62 | | - <p><strong>Active Sessions:</strong> <span id="kpi-sessions">N/A</span></p> |
63 | | - <p><strong>Anomalies Detected:</strong> <span id="kpi-anomalies">N/A</span></p> |
64 | | - </div> |
65 | | - </div> |
66 | | - |
67 | | - <div class="mb-4"> |
68 | | - <h2 class="text-xl font-bold mb-2">User Action History</h2> |
69 | | - <div id="action-history" class="bg-white p-4 rounded shadow"></div> |
70 | | - <div class="flex space-x-2"> |
71 | | - <button id="load-actions-btn" class="bg-blue-500 text-white px-4 py-2 rounded" disabled>Load Action History</button> |
72 | | - <button id="prev-page-btn" class="bg-gray-500 text-white px-4 py-2 rounded" disabled>Previous Page</button> |
73 | | - <button id="next-page-btn" class="bg-gray-500 text-white px-4 py-2 rounded" disabled>Next Page</button> |
74 | | - <span id="page-info" class="p-2">Page 1</span> |
75 | | - </div> |
76 | | - </div> |
77 | | - |
78 | | - <div class="mb-4"> |
79 | | - <textarea id="claude-code" class="w-full h-32 p-2 border rounded" placeholder="Enter Claude-generated code" disabled></textarea> |
80 | | - <textarea id="wallet-import" class="w-full h-32 p-2 border rounded" placeholder="Paste wallet markdown to import"></textarea> |
81 | | - <textarea id="agent-code" class="w-full h-32 p-2 border rounded" placeholder="Enter custom agent code for Git push"></textarea> |
82 | | - <input id="commit-message" class="w-full p-2 border rounded mb-2" placeholder="Enter Git commit message"> |
83 | | - <input id="cash-out-amount" class="w-full p-2 border rounded mb-2" placeholder="Enter cash-out amount ($WEBXOS)"> |
84 | | - <input id="cash-out-address" class="w-full p-2 border rounded mb-2" placeholder="Enter destination wallet address"> |
85 | | - <button id="execute-claude-btn" class="bg-indigo-500 text-white px-4 py-2 rounded" disabled>Execute Claude Code</button> |
86 | | - <button id="import-wallet-btn" class="bg-teal-500 text-white px-4 py-2 rounded">Import Wallet</button> |
87 | | - <button id="auth-btn" class="bg-blue-500 text-white px-4 py-2 rounded">Authenticate with GitHub</button> |
88 | | - <button id="logout-btn" class="bg-red-500 text-white px-4 py-2 rounded" disabled>Logout</button> |
89 | | - <button id="api-credentials-btn" class="bg-purple-500 text-white px-4 py-2 rounded" disabled>Generate API Credentials</button> |
90 | | - <button id="git-push-btn" class="bg-green-600 text-white px-4 py-2 rounded" disabled>Git Push Agent Code</button> |
91 | | - <button id="void-btn" class="bg-gray-500 text-white px-4 py-2 rounded">Void</button> |
92 | | - <button id="troubleshoot-btn" class="bg-yellow-500 text-white px-4 py-2 rounded">Troubleshoot</button> |
93 | | - <button id="quantum-link-btn" class="bg-purple-500 text-white px-4 py-2 rounded" disabled>Quantum Link</button> |
94 | | - <button id="export-btn" class="bg-green-500 text-white px-4 py-2 rounded" disabled>Export</button> |
95 | | - <button id="mine-btn" class="bg-orange-500 text-white px-4 py-2 rounded" disabled>Mine Vial</button> |
96 | | - <button id="cash-out-btn" class="bg-red-500 text-white px-4 py-2 rounded" disabled>Cash Out</button> |
97 | | - <button id="data-erasure-btn" class="bg-red-600 text-white px-4 py-2 rounded" disabled>Request Data Erasure</button> |
98 | | - </div> |
99 | | - |
100 | | - <div id="output" class="bg-white p-4 rounded shadow"></div> |
101 | | - </div> |
102 | | - |
103 | | - <script type="module" nonce="{{nonce}}" src="/js/auth_handler.js"></script> |
104 | | - <script type="module" nonce="{{nonce}}" src="/js/websocket_handler.js"></script> |
105 | | - <script type="module" nonce="{{nonce}}" src="/js/vial_controller.js"></script> |
106 | | - <script type="module" nonce="{{nonce}}"> |
107 | | - import { updateNetworkStatus } from '/js/vial_controller.js'; |
108 | | - import { wsHandler } from '/js/websocket_handler.js'; |
109 | | - |
110 | | - let currentPage = 1; |
111 | | - let totalPages = 1; |
112 | | - |
113 | | - updateNetworkStatus(); |
114 | | - window.addEventListener('online', updateNetworkStatus); |
115 | | - window.addEventListener('offline', updateNetworkStatus); |
116 | | - |
117 | | - document.addEventListener('auth-success', () => { |
118 | | - document.getElementById('execute-claude-btn').disabled = false; |
119 | | - document.getElementById('quantum-link-btn').disabled = !navigator.onLine; |
120 | | - document.getElementById('mine-btn').disabled = false; |
121 | | - document.getElementById('export-btn').disabled = !navigator.onLine; |
122 | | - document.getElementById('api-credentials-btn').disabled = !navigator.onLine; |
123 | | - document.getElementById('git-push-btn').disabled = !navigator.onLine; |
124 | | - document.getElementById('cash-out-btn').disabled = !navigator.onLine; |
125 | | - document.getElementById('logout-btn').disabled = false; |
126 | | - document.getElementById('data-erasure-btn').disabled = false; |
127 | | - document.getElementById('load-actions-btn').disabled = false; |
128 | | - document.getElementById('enable-2fa-btn').disabled = false; |
129 | | - }); |
130 | | - |
131 | | - async function loadActionHistory(page) { |
132 | | - const userId = document.getElementById('user-id').innerText; |
133 | | - if (userId === 'Not logged in') { |
134 | | - document.getElementById('output').innerText = 'Error: Please authenticate first'; |
135 | | - return; |
136 | | - } |
137 | | - try { |
138 | | - const accessToken = localStorage.getItem('access_token'); |
139 | | - const sessionId = document.cookie.match(/session_id=([^;]+)/)?.[1]; |
140 | | - const res = await fetch('https://webxos.netlify.app/mcp/execute', { |
141 | | - method: 'POST', |
142 | | - headers: { |
143 | | - 'Content-Type': 'application/json', |
144 | | - 'Authorization': `Bearer ${accessToken}`, |
145 | | - 'X-Session-ID': sessionId |
146 | | - }, |
147 | | - body: JSON.stringify({ |
148 | | - jsonrpc: '2.0', |
149 | | - method: 'security.getUserActions', |
150 | | - params: { user_id: userId, page, page_size: 50 }, |
151 | | - id: Math.floor(Math.random() * 1000) |
152 | | - }) |
153 | | - }); |
154 | | - const data = await res.json(); |
155 | | - if (data.error) throw new Error(data.error.message); |
156 | | - const actions = data.result.actions; |
157 | | - totalPages = data.result.total_pages; |
158 | | - currentPage = data.result.current_page; |
159 | | - const actionHistory = document.getElementById('action-history'); |
160 | | - actionHistory.innerHTML = actions.map(action => ` |
161 | | - <div class="p-2 border-b"> |
162 | | - <p><strong>Action:</strong> ${action.action}</p> |
163 | | - <p><strong>Details:</strong> ${JSON.stringify(action.details)}</p> |
164 | | - <p><strong>Timestamp:</strong> ${new Date(action.created_at).toLocaleString()}</p> |
165 | | - </div> |
166 | | - `).join(''); |
167 | | - document.getElementById('page-info').innerText = `Page ${currentPage}`; |
168 | | - document.getElementById('prev-page-btn').disabled = currentPage === 1; |
169 | | - document.getElementById('next-page-btn').disabled = currentPage === totalPages; |
170 | | - } catch (error) { |
171 | | - document.getElementById('output').innerText = `Error loading action history: ${error.message}`; |
172 | | - } |
173 | | - } |
174 | | - |
175 | | - document.getElementById('load-actions-btn').addEventListener('click', () => loadActionHistory(1)); |
176 | | - document.getElementById('prev-page-btn').addEventListener('click', () => { |
177 | | - if (currentPage > 1) loadActionHistory(currentPage - 1); |
178 | | - }); |
179 | | - document.getElementById('next-page-btn').addEventListener('click', () => { |
180 | | - if (currentPage < totalPages) loadActionHistory(currentPage + 1); |
181 | | - }); |
182 | | - |
183 | | - document.getElementById('logout-btn').addEventListener('click', async () => { |
184 | | - const userId = document.getElementById('user-id').innerText; |
185 | | - if (userId === 'Not logged in') { |
186 | | - document.getElementById('output').innerText = 'Error: Not authenticated'; |
187 | | - return; |
188 | | - } |
189 | | - try { |
190 | | - const accessToken = localStorage.getItem('access_token'); |
191 | | - const sessionId = document.cookie.match(/session_id=([^;]+)/)?.[1]; |
192 | | - const res = await fetch('https://webxos.netlify.app/mcp/execute', { |
193 | | - method: 'POST', |
194 | | - headers: { |
195 | | - 'Content-Type': 'application/json', |
196 | | - 'Authorization': `Bearer ${accessToken}`, |
197 | | - 'X-Session-ID': sessionId |
198 | | - }, |
199 | | - body: JSON.stringify({ |
200 | | - jsonrpc: '2.0', |
201 | | - method: 'auth.revokeToken', |
202 | | - params: { user_id: userId, access_token: accessToken }, |
203 | | - id: Math.floor(Math.random() * 1000) |
204 | | - }) |
205 | | - }); |
206 | | - const data = await res.json(); |
207 | | - if (data.error) throw new Error(data.error.message); |
208 | | - localStorage.removeItem('access_token'); |
209 | | - localStorage.removeItem('refresh_token'); |
210 | | - document.cookie = 'session_id=; Max-Age=0; path=/;'; |
211 | | - document.getElementById('user-id').innerText = 'Not logged in'; |
212 | | - document.getElementById('output').innerText = 'Logged out successfully'; |
213 | | - document.getElementById('execute-claude-btn').disabled = true; |
214 | | - document.getElementById('quantum-link-btn').disabled = true; |
215 | | - document.getElementById('mine-btn').disabled = true; |
216 | | - document.getElementById('export-btn').disabled = true; |
217 | | - document.getElementById('api-credentials-btn').disabled = true; |
218 | | - document.getElementById('git-push-btn').disabled = true; |
219 | | - document.getElementById('cash-out-btn').disabled = true; |
220 | | - document.getElementById('logout-btn').disabled = true; |
221 | | - document.getElementById('data-erasure-btn').disabled = true; |
222 | | - document.getElementById('load-actions-btn').disabled = true; |
223 | | - document.getElementById('enable-2fa-btn').disabled = true; |
224 | | - document.getElementById('verify-2fa-btn').disabled = true; |
225 | | - } catch (error) { |
226 | | - document.getElementById('output').innerText = `Logout error: ${error.message}`; |
227 | | - } |
228 | | - }); |
229 | | - |
230 | | - document.getElementById('data-erasure-btn').addEventListener('click', async () => { |
231 | | - const userId = document.getElementById('user-id').innerText; |
232 | | - if (userId === 'Not logged in') { |
233 | | - document.getElementById('output').innerText = 'Error: Please authenticate first'; |
234 | | - return; |
235 | | - } |
236 | | - if (!confirm('Are you sure you want to permanently delete all your data? This action cannot be undone.')) { |
237 | | - return; |
238 | | - } |
239 | | - try { |
240 | | - const accessToken = localStorage.getItem('access_token'); |
241 | | - const sessionId = document.cookie.match(/session_id=([^;]+)/)?.[1]; |
242 | | - const res = await fetch('https://webxos.netlify.app/privacy/erase', { |
243 | | - method: 'POST', |
244 | | - headers: { |
245 | | - 'Content-Type': 'application/json', |
246 | | - 'Authorization': `Bearer ${accessToken}`, |
247 | | - 'X-Session-ID': sessionId |
248 | | - }, |
249 | | - body: JSON.stringify({ user_id: userId }) |
250 | | - }); |
251 | | - const data = await res.json(); |
252 | | - if (res.status !== 200) throw new Error(data.detail || 'Data erasure failed'); |
253 | | - localStorage.removeItem('access_token'); |
254 | | - localStorage.removeItem('refresh_token'); |
255 | | - document.cookie = 'session_id=; Max-Age=0; path=/;'; |
256 | | - document.getElementById('user-id').innerText = 'Not logged in'; |
257 | | - document.getElementById('output').innerText = 'Data erasure request successful. All data deleted.'; |
258 | | - document.getElementById('execute-claude-btn').disabled = true; |
259 | | - document.getElementById('quantum-link-btn').disabled = true; |
260 | | - document.getElementById('mine-btn').disabled = true; |
261 | | - document.getElementById('export-btn').disabled = true; |
262 | | - document.getElementById('api-credentials-btn').disabled = true; |
263 | | - document.getElementById('git-push-btn').disabled = true; |
264 | | - document.getElementById('cash-out-btn').disabled = true; |
265 | | - document.getElementById('logout-btn').disabled = true; |
266 | | - document.getElementById('data-erasure-btn').disabled = true; |
267 | | - document.getElementById('load-actions-btn').disabled = true; |
268 | | - document.getElementById('enable-2fa-btn').disabled = true; |
269 | | - document.getElementById('verify-2fa-btn').disabled = true; |
270 | | - } catch (error) { |
271 | | - document.getElementById('output').innerText = `Data erasure error: ${error.message}`; |
272 | | - } |
273 | | - }); |
274 | | - |
275 | | - document.getElementById('enable-2fa-btn').addEventListener('click', async () => { |
276 | | - const userId = document.getElementById('user-id').innerText; |
277 | | - if (userId === 'Not logged in') { |
278 | | - document.getElementById('output').innerText = 'Error: Please authenticate first'; |
279 | | - return; |
280 | | - } |
281 | | - try { |
282 | | - const accessToken = localStorage.getItem('access_token'); |
283 | | - const sessionId = document.cookie.match(/session_id=([^;]+)/)?.[1]; |
284 | | - const res = await fetch('https://webxos.netlify.app/mcp/execute', { |
285 | | - method: 'POST', |
286 | | - headers: { |
287 | | - 'Content-Type': 'application/json', |
288 | | - 'Authorization': `Bearer ${accessToken}`, |
289 | | - 'X-Session-ID': sessionId |
290 | | - }, |
291 | | - body: JSON.stringify({ |
292 | | - jsonrpc: '2.0', |
293 | | - method: 'auth.enable2FA', |
294 | | - params: { user_id: userId }, |
295 | | - id: Math.floor(Math.random() * 1000) |
296 | | - }) |
297 | | - }); |
298 | | - const data = await res.json(); |
299 | | - if (data.error) throw new Error(data.error.message); |
300 | | - document.getElementById('2fa-qr-code').src = data.result.qr_code_url; |
301 | | - document.getElementById('2fa-qr-code').classList.remove('hidden'); |
302 | | - document.getElementById('verify-2fa-btn').disabled = false; |
303 | | - } catch (error) { |
304 | | - document.getElementById('output').innerText = `2FA setup error: ${error.message}`; |
305 | | - } |
306 | | - }); |
307 | | - |
308 | | - document.getElementById('verify-2fa-btn').addEventListener('click', async () => { |
309 | | - const userId = document.getElementById('user-id').innerText; |
310 | | - const totpCode = document.getElementById('2fa-code').value; |
311 | | - if (!totpCode) { |
312 | | - document.getElementById('output').innerText = 'Error: Please enter 2FA code'; |
313 | | - return; |
314 | | - } |
315 | | - try { |
316 | | - const accessToken = localStorage.getItem('access_token'); |
317 | | - const sessionId = document.cookie.match(/session_id=([^;]+)/)?.[1]; |
318 | | - const res = await fetch('https://webxos.netlify.app/mcp/execute', { |
319 | | - method: 'POST', |
320 | | - headers: { |
321 | | - 'Content-Type': 'application/json', |
322 | | - 'Authorization': `Bearer ${accessToken}`, |
323 | | - 'X-Session-ID': sessionId |
324 | | - }, |
325 | | - body: JSON.stringify({ |
326 | | - jsonrpc: '2.0', |
327 | | - method: 'auth.verify2FA', |
328 | | - params: { user_id: userId, totp_code: totpCode }, |
329 | | - id: Math.floor(Math.random() * 1000) |
330 | | - }) |
331 | | - }); |
332 | | - const data = await res.json(); |
333 | | - if (data.error) throw new Error(data.error.message); |
334 | | - document.getElementById('output').innerText = '2FA verified successfully'; |
335 | | - document.getElementById('2fa-qr-code').classList.add('hidden'); |
336 | | - document.getElementById('verify-2fa-btn').disabled = true; |
337 | | - } catch (error) { |
338 | | - document.getElementById('output').innerText = `2FA verification error: ${error.message}`; |
339 | | - } |
340 | | - }); |
341 | | - </script> |
| 9 | +<body> |
| 10 | + <h1>Vial MCP (BETA)</h1> |
| 11 | + <div id="console"> |
| 12 | + <p>Vial MCP Controller initialized. Use /help for API commands.</p> |
| 13 | + <p class="balance">$WEBXOS Balance: 0.0000 | Reputation: 0</p> |
| 14 | + </div> |
| 15 | + <div id="error-notification"></div> |
| 16 | + <div id="api-popup"> |
| 17 | + <h2>API Access Credentials</h2> |
| 18 | + <textarea id="api-input" readonly></textarea> |
| 19 | + <button id="api-generate">Generate New Credentials</button> |
| 20 | + <button id="api-close">Close</button> |
| 21 | + </div> |
| 22 | + <div class="button-group"> |
| 23 | + <button id="authButton">Authenticate</button> |
| 24 | + <button id="voidButton">Void</button> |
| 25 | + <button id="troubleshootButton">Troubleshoot</button> |
| 26 | + <button id="quantumLinkButton" disabled>Quantum Link</button> |
| 27 | + <button id="exportButton" disabled>Export</button> |
| 28 | + <button id="importButton" disabled>Import</button> |
| 29 | + <button id="apiAccessButton" disabled>API Access</button> |
| 30 | + </div> |
| 31 | + <textarea id="prompt-input" placeholder="Enter git commands for API (e.g., /prompt vial1 train dataset)..."></textarea> |
| 32 | + <div id="vial-status-bars"></div> |
| 33 | + <footer>WebXOS Vial MCP Controller | Testing Mode (BETA) | 2025 | v2.7 WARNING: $webxos token is still in development phase under MIT open source license. @WEBXOS will claim no fault for lose of tokens while using our software. For more info: webxos.netlify.app & github.com/webxos/webxos</footer> |
| 34 | + <input type="file" id="file-input" accept=".md"> |
| 35 | + <script src="js/vial-mcp.js"></script> |
342 | 36 | </body> |
343 | 37 | </html> |
0 commit comments