@@ -76,6 +76,8 @@ let wallet = { address: null, balance: 0, hash: null };
7676let lastLogMessage = null ;
7777let lastLogTime = 0 ;
7878let lastLogId = 0 ;
79+ let toolboxClient = null ;
80+ let toolboxTools = null ;
7981
8082// UUID generator
8183function generateUUID ( ) {
@@ -137,7 +139,7 @@ function parseMarkdownForTraining(mdContent) {
137139// Simulate blockchain transaction
138140async function addToBlockchain ( type , data ) {
139141 if ( isOffline && type !== 'train' && type !== 'import' && type !== 'export' ) {
140- return null ; // Skip blockchain in offline mode for non-training actions
142+ return null ;
141143 }
142144 const timestamp = new Date ( ) . toISOString ( ) ;
143145 const prevHash = blockchain . length ? blockchain [ blockchain . length - 1 ] . hash : '0' . repeat ( 64 ) ;
@@ -201,8 +203,8 @@ function updateVialStatusBars() {
201203 vial . latency = isOffline ? 0 : Math . floor ( Math . random ( ) * ( 200 - 50 + 1 ) ) + 50 ;
202204 } ) ;
203205 vialStatusBars . innerHTML = vials . map ( vial => {
204- const mode = vial . isTraining ? 'Training' : ( isOffline ? 'Offline (Wallet Disabled)' : ' Online') ;
205- const statusClass = vial . isTraining ? 'training' : ( isOffline ? 'offline-grey' : ' online') ;
206+ const mode = vial . isTraining ? 'Training' : ( isOffline ? 'Offline (Wallet Disabled)' : ( toolboxClient ? 'GenAI' : ' Online') ) ;
207+ const statusClass = vial . isTraining ? 'training' : ( isOffline ? 'offline-grey' : ( toolboxClient ? 'genai' : ' online') ) ;
206208 const fillClass = vial . status === 'running' ? statusClass : '' ;
207209 return `
208210 <div class="progress-container">
@@ -253,14 +255,13 @@ async function startTokenEarning() {
253255 } ) ;
254256 wallet . hash = blockHash ;
255257 logEvent ( 'token' , `Earned 1 $WEBXOS | Reputation: ${ reputation } | Block: ${ blockHash . slice ( 0 , 8 ) } ...` , { wallet : wallet . address } ) ;
256- logEvent ( 'token' , `Earned 1 $WEBXOS | Reputation: ${ reputation } | Block: ${ blockHash . slice ( 0 , 8 ) } ...` , { wallet : wallet . address } ) ;
257258 updateBalanceDisplay ( ) ;
258259 } , 10000 ) ;
259260}
260261
261262// Disable functions on auth loss or offline mode
262263function disableFunctions ( ) {
263- const buttons = [ 'quantumLinkButton' , 'exportButton' , 'importButton' ] ;
264+ const buttons = [ 'quantumLinkButton' , 'exportButton' , 'importButton' , 'googleGenAIButton' ] ;
264265 if ( isOffline ) buttons . push ( 'apiAccessButton' ) ;
265266 buttons . forEach ( id => {
266267 const btn = document . getElementById ( id ) ;
@@ -276,6 +277,57 @@ function disableFunctions() {
276277 }
277278}
278279
280+ // Initialize Google GenAI Toolbox client
281+ async function initializeToolboxClient ( ) {
282+ if ( isOffline ) {
283+ logEvent ( 'error' , 'Google GenAI Toolbox cannot be initialized in offline mode.' , { } ) ;
284+ return ;
285+ }
286+ if ( ! isAuthenticated ) {
287+ logEvent ( 'error' , 'Authentication required to initialize Google GenAI Toolbox.' , { } ) ;
288+ return ;
289+ }
290+ try {
291+ const response = await axios . get ( 'http://127.0.0.1:5000/mcp/toolsets' , {
292+ headers : { 'Authorization' : `Bearer ${ apiCredentials . key } ` }
293+ } ) ;
294+ toolboxTools = response . data . tools ;
295+ toolboxClient = { url : 'http://127.0.0.1:5000' , tools : toolboxTools } ;
296+ const googleGenAIButton = document . getElementById ( 'googleGenAIButton' ) ;
297+ if ( googleGenAIButton ) {
298+ googleGenAIButton . disabled = false ;
299+ googleGenAIButton . classList . add ( 'active-genai' ) ;
300+ }
301+ document . body . classList . add ( 'genai-glow' ) ;
302+ document . getElementById ( 'console' ) . classList . add ( 'active-genai' ) ;
303+ logEvent ( 'genai' , 'Google GenAI Toolbox initialized. Available tools: ' + toolboxTools . map ( t => t . name ) . join ( ', ' ) , { } ) ;
304+ updateVialStatusBars ( ) ;
305+ } catch ( error ) {
306+ logEvent ( 'error' , `Failed to initialize Google GenAI Toolbox: ${ error . message } ` , { error } ) ;
307+ showErrorNotification ( 'Failed to connect to Google GenAI Toolbox server.' ) ;
308+ }
309+ }
310+
311+ // Execute GenAI tool
312+ async function executeGenAITool ( toolName , params ) {
313+ if ( ! toolboxClient ) {
314+ logEvent ( 'error' , 'Google GenAI Toolbox not initialized.' , { } ) ;
315+ return null ;
316+ }
317+ try {
318+ const response = await axios . post ( `${ toolboxClient . url } /mcp/tools/${ toolName } /execute` , { parameters : params } , {
319+ headers : { 'Authorization' : `Bearer ${ apiCredentials . key } ` }
320+ } ) ;
321+ const blockHash = await addToBlockchain ( 'genai_tool' , { toolName, params, result : response . data } ) ;
322+ logEvent ( 'genai' , `Executed tool ${ toolName } : ${ JSON . stringify ( response . data ) } | Block: ${ blockHash . slice ( 0 , 8 ) } ...` , { toolName, params } ) ;
323+ return response . data ;
324+ } catch ( error ) {
325+ logEvent ( 'error' , `Failed to execute tool ${ toolName } : ${ error . message } ` , { error } ) ;
326+ showErrorNotification ( `Tool execution failed: ${ error . message } ` ) ;
327+ return null ;
328+ }
329+ }
330+
279331// Authenticate
280332async function authenticate ( ) {
281333 const isOnline = confirm ( 'Authenticate in online mode? Cancel for offline mode.' ) ;
@@ -286,7 +338,7 @@ async function authenticate() {
286338 wallet = { address : isOffline ? null : generateUUID ( ) , balance : 0 , hash : isOffline ? null : await sha256 ( agenticNetworkId ) } ;
287339 reputation = 0 ;
288340 blockchain = [ ] ;
289- apiCredentials = { key : null , secret : null } ;
341+ apiCredentials = { key : isOffline ? null : generateUUID ( ) , secret : isOffline ? null : generateUUID ( ) } ;
290342 isAuthenticated = true ;
291343 await addToBlockchain ( 'auth' , { wallet : wallet . address , networkId : agenticNetworkId } ) ;
292344 vials . forEach ( ( vial , i ) => {
@@ -295,7 +347,7 @@ async function authenticate() {
295347 } ) ;
296348 const authButton = document . getElementById ( 'authButton' ) ;
297349 if ( authButton ) authButton . classList . add ( 'active-monitor' ) ;
298- [ 'quantumLinkButton' , 'exportButton' , 'importButton' ] . forEach ( id => {
350+ [ 'quantumLinkButton' , 'exportButton' , 'importButton' , 'googleGenAIButton' ] . forEach ( id => {
299351 const btn = document . getElementById ( id ) ;
300352 if ( btn ) btn . disabled = false ;
301353 } ) ;
@@ -309,6 +361,185 @@ async function authenticate() {
309361 updateBalanceDisplay ( ) ;
310362}
311363
364+ // Handle Git and GenAI commands
365+ async function handleGitCommand ( input ) {
366+ const sanitizedInput = sanitizeInput ( input . trim ( ) ) ;
367+ if ( ! sanitizedInput ) return ;
368+ logEvent ( 'command' , sanitizedInput ) ;
369+ const parts = sanitizedInput . split ( ' ' ) ;
370+ const command = parts [ 0 ] . toLowerCase ( ) ;
371+
372+ if ( command === '/genai' && parts . length > 1 ) {
373+ if ( ! toolboxClient ) {
374+ logEvent ( 'error' , 'Google GenAI Toolbox not initialized. Click "Google GenAI" button to initialize.' , { } ) ;
375+ return ;
376+ }
377+ const toolName = parts [ 1 ] ;
378+ const params = parts . slice ( 2 ) ;
379+ const tool = toolboxTools . find ( t => t . name === toolName ) ;
380+ if ( ! tool ) {
381+ logEvent ( 'error' , `Tool ${ toolName } not found. Available tools: ${ toolboxTools . map ( t => t . name ) . join ( ', ' ) } ` , { } ) ;
382+ return ;
383+ }
384+ const result = await executeGenAITool ( toolName , params ) ;
385+ if ( result ) {
386+ logEvent ( 'genai' , `Tool ${ toolName } result: ${ JSON . stringify ( result ) } ` , { toolName, params } ) ;
387+ }
388+ } else if ( command === '/help' ) {
389+ const helpText = `
390+ Available commands:
391+ /prompt vial[1-4] train <dataset> - Train a vial
392+ /genai <tool_name> <params> - Execute Google GenAI tool (e.g., /genai search-hotels-by-name Marriott)
393+ /status - Check vial statuses
394+ /auth - Re-authenticate
395+ ` ;
396+ logEvent ( 'info' , helpText . replace ( / \n / g, '<br>' ) , { } ) ;
397+ } else {
398+ logEvent ( 'error' , `Unknown command: ${ sanitizedInput } . Use /help for available commands.` , { } ) ;
399+ }
400+ }
401+
402+ // Void vials
403+ async function voidVials ( ) {
404+ if ( ! isAuthenticated ) {
405+ logEvent ( 'error' , 'Authentication required to void vials.' , { } ) ;
406+ return ;
407+ }
408+ vials . forEach ( vial => {
409+ vial . status = 'stopped' ;
410+ vial . isTraining = false ;
411+ vial . tasks = [ ] ;
412+ vial . trainingData = [ ] ;
413+ } ) ;
414+ await addToBlockchain ( 'void' , { vials : vials . map ( v => v . id ) } ) ;
415+ logEvent ( 'system' , 'All vials voided.' , { } ) ;
416+ updateVialStatusBars ( ) ;
417+ }
418+
419+ // Troubleshoot
420+ async function troubleshoot ( ) {
421+ if ( ! isAuthenticated ) {
422+ logEvent ( 'error' , 'Authentication required to troubleshoot.' , { } ) ;
423+ return ;
424+ }
425+ const issues = [ ] ;
426+ vials . forEach ( vial => {
427+ if ( vial . status === 'stopped' && vial . tasks . length > 0 ) {
428+ issues . push ( `${ vial . id } : Stopped but has pending tasks.` ) ;
429+ }
430+ if ( vial . latency > 200 ) {
431+ issues . push ( `${ vial . id } : High latency detected (${ vial . latency } ms).` ) ;
432+ }
433+ } ) ;
434+ if ( toolboxClient ) {
435+ try {
436+ await axios . get ( `${ toolboxClient . url } /health` , {
437+ headers : { 'Authorization' : `Bearer ${ apiCredentials . key } ` }
438+ } ) ;
439+ logEvent ( 'genai' , 'Google GenAI Toolbox server health: OK' , { } ) ;
440+ } catch ( error ) {
441+ issues . push ( `Google GenAI Toolbox server: Unhealthy (${ error . message } )` ) ;
442+ }
443+ }
444+ if ( issues . length === 0 ) {
445+ logEvent ( 'system' , 'No issues detected.' , { } ) ;
446+ } else {
447+ issues . forEach ( issue => logEvent ( 'error' , issue , { } ) ) ;
448+ }
449+ updateVialStatusBars ( ) ;
450+ }
451+
452+ // Quantum link
453+ async function quantumLink ( ) {
454+ if ( ! isAuthenticated ) {
455+ logEvent ( 'error' , 'Authentication required for quantum link.' , { } ) ;
456+ return ;
457+ }
458+ vials . forEach ( vial => {
459+ vial . quantumState = { qubits : [ Math . random ( ) , Math . random ( ) ] , entanglement : 'linked' } ;
460+ } ) ;
461+ const blockHash = await addToBlockchain ( 'quantum_link' , { vials : vials . map ( v => v . id ) } ) ;
462+ logEvent ( 'system' , `Quantum link established. Block: ${ blockHash . slice ( 0 , 8 ) } ...` , { } ) ;
463+ }
464+
465+ // Export vials
466+ async function exportVials ( ) {
467+ if ( ! isAuthenticated ) {
468+ logEvent ( 'error' , 'Authentication required to export vials.' , { } ) ;
469+ return ;
470+ }
471+ const exportData = {
472+ vials : vials . map ( vial => ( {
473+ id : vial . id ,
474+ code : vial . code ,
475+ status : vial . status ,
476+ wallet : vial . wallet ,
477+ quantumState : vial . quantumState
478+ } ) ) ,
479+ blockchain : blockchain . slice ( - 10 )
480+ } ;
481+ const blob = new Blob ( [ JSON . stringify ( exportData , null , 2 ) ] , { type : 'application/json' } ) ;
482+ const url = URL . createObjectURL ( blob ) ;
483+ const a = document . createElement ( 'a' ) ;
484+ a . href = url ;
485+ a . download = 'vial-mcp-export.json' ;
486+ a . click ( ) ;
487+ URL . revokeObjectURL ( url ) ;
488+ logEvent ( 'system' , 'Vials exported successfully.' , { } ) ;
489+ }
490+
491+ // Import file
492+ async function importFile ( event ) {
493+ if ( ! isAuthenticated ) {
494+ logEvent ( 'error' , 'Authentication required to import files.' , { } ) ;
495+ return ;
496+ }
497+ const file = event . target . files [ 0 ] ;
498+ if ( ! file ) return ;
499+ const reader = new FileReader ( ) ;
500+ reader . onload = async ( e ) => {
501+ const content = e . target . result ;
502+ if ( ! validateMarkdown ( content ) ) {
503+ logEvent ( 'error' , 'Invalid .md file format.' , { } ) ;
504+ return ;
505+ }
506+ const { tasks, parameters } = parseMarkdownForTraining ( content ) ;
507+ vials . forEach ( vial => {
508+ vial . tasks = tasks ;
509+ vial . config = parameters ;
510+ } ) ;
511+ const blockHash = await addToBlockchain ( 'import' , { tasks, parameters } ) ;
512+ logEvent ( 'system' , `Imported tasks and parameters. Block: ${ blockHash . slice ( 0 , 8 ) } ...` , { tasks, parameters } ) ;
513+ updateVialStatusBars ( ) ;
514+ } ;
515+ reader . readAsText ( file ) ;
516+ }
517+
518+ // Show API popup
519+ function showApiPopup ( ) {
520+ if ( ! isAuthenticated || isOffline ) {
521+ logEvent ( 'error' , 'Authentication required and online mode needed for API access.' , { } ) ;
522+ return ;
523+ }
524+ const apiInput = document . getElementById ( 'api-input' ) ;
525+ const apiPopup = document . getElementById ( 'api-popup' ) ;
526+ apiInput . value = JSON . stringify ( apiCredentials , null , 2 ) ;
527+ apiPopup . classList . add ( 'visible' ) ;
528+ }
529+
530+ // Generate API credentials
531+ async function generateApiCredentials ( ) {
532+ if ( ! isAuthenticated || isOffline ) {
533+ logEvent ( 'error' , 'Authentication required and online mode needed for API credentials.' , { } ) ;
534+ return ;
535+ }
536+ apiCredentials = { key : generateUUID ( ) , secret : generateUUID ( ) } ;
537+ const blockHash = await addToBlockchain ( 'api_credentials' , { key : apiCredentials . key } ) ;
538+ const apiInput = document . getElementById ( 'api-input' ) ;
539+ apiInput . value = JSON . stringify ( apiCredentials , null , 2 ) ;
540+ logEvent ( 'system' , `New API credentials generated. Block: ${ blockHash . slice ( 0 , 8 ) } ...` , { } ) ;
541+ }
542+
312543// Initialize
313544document . addEventListener ( 'DOMContentLoaded' , ( ) => {
314545 updateVialStatusBars ( ) ;
@@ -321,6 +552,7 @@ document.addEventListener('DOMContentLoaded', () => {
321552 exportButton : document . getElementById ( 'exportButton' ) ,
322553 importButton : document . getElementById ( 'importButton' ) ,
323554 apiAccessButton : document . getElementById ( 'apiAccessButton' ) ,
555+ googleGenAIButton : document . getElementById ( 'googleGenAIButton' ) ,
324556 apiSubmit : document . getElementById ( 'api-generate' ) ,
325557 apiClose : document . getElementById ( 'api-close' ) ,
326558 fileInput : document . getElementById ( 'file-input' ) ,
@@ -334,6 +566,7 @@ document.addEventListener('DOMContentLoaded', () => {
334566 elements . exportButton . addEventListener ( 'click' , exportVials ) ;
335567 elements . importButton . addEventListener ( 'click' , ( ) => elements . fileInput . click ( ) ) ;
336568 elements . apiAccessButton . addEventListener ( 'click' , showApiPopup ) ;
569+ elements . googleGenAIButton . addEventListener ( 'click' , initializeToolboxClient ) ;
337570 elements . apiSubmit . addEventListener ( 'click' , generateApiCredentials ) ;
338571 elements . apiClose . addEventListener ( 'click' , ( ) => {
339572 const apiPopup = document . getElementById ( 'api-popup' ) ;
@@ -352,6 +585,3 @@ document.addEventListener('DOMContentLoaded', () => {
352585
353586 logEvent ( 'system' , 'Vial MCP Controller initialized. Use /help for API commands.' , { } ) ;
354587} , { once : true } ) ;
355- < / script >
356- </ body >
357- < / h t m l >
0 commit comments