@@ -147,65 +147,50 @@ function initCanvas() {
147147}
148148
149149// --- EVENT LISTENERS ---
150+ // --- EVENT LISTENERS (CLEAN & STABLE) ---
150151function initEventListeners ( ) {
151- // Theme Toggle
152- document . getElementById ( 'theme-toggle' ) . addEventListener ( 'click' , ( ) => {
152+ // 1. Theme Toggle
153+ const themeBtn = document . getElementById ( 'theme-toggle' ) ;
154+ if ( themeBtn ) themeBtn . addEventListener ( 'click' , ( ) => {
153155 document . body . classList . toggle ( 'light-theme' ) ;
154156 state . theme = document . body . classList . contains ( 'light-theme' ) ? 'light' : 'dark' ;
155157 } ) ;
156158
157- document . getElementById ( 'btn-execute-chain' ) . addEventListener ( 'click' , executeVisualChain ) ;
158- // Search (Cmd+K)
159+ // 2. Visual Chain Builder Bindings
160+ const execBtn = document . getElementById ( 'btn-execute-chain' ) ;
161+ if ( execBtn ) execBtn . addEventListener ( 'click' , executeVisualChain ) ;
162+
163+ const s1 = document . getElementById ( 'slot-1' ) ;
164+ const s2 = document . getElementById ( 'slot-2' ) ;
165+ const s3 = document . getElementById ( 'slot-3' ) ;
166+ if ( s1 ) s1 . onclick = ( ) => prepareSelection ( 1 ) ;
167+ if ( s2 ) s2 . onclick = ( ) => prepareSelection ( 2 ) ;
168+ if ( s3 ) s3 . onclick = ( ) => prepareSelection ( 3 ) ;
169+
170+ // 3. Search (Cmd+K)
159171 document . addEventListener ( 'keydown' , ( e ) => {
160172 if ( ( e . metaKey || e . ctrlKey ) && e . key === 'k' ) {
161173 e . preventDefault ( ) ;
162174 DOM . searchInp . focus ( ) ;
163175 }
164176 } ) ;
165-
166- DOM . searchInp . addEventListener ( 'input' , ( e ) => handleSearch ( e . target . value ) ) ;
167-
168- // Dock
169- document . getElementById ( 'cmd-deploy' ) . addEventListener ( 'click' , ( ) => DOM . modalDeploy . classList . remove ( 'hidden' ) ) ;
170- document . getElementById ( 'cmd-chain' ) . addEventListener ( 'click' , ( ) => DOM . modalChain . classList . remove ( 'hidden' ) ) ;
171- document . getElementById ( 'cmd-logs' ) . addEventListener ( 'click' , ( ) => DOM . panelLogs . classList . remove ( 'hidden' ) ) ;
172- document . getElementById ( 'cmd-restart' ) . addEventListener ( 'click' , ( ) => {
177+ if ( DOM . searchInp ) DOM . searchInp . addEventListener ( 'input' , ( e ) => handleSearch ( e . target . value ) ) ;
178+
179+ // 4. Dock Actions
180+ const cmdDeploy = document . getElementById ( 'cmd-deploy' ) ;
181+ const cmdChain = document . getElementById ( 'cmd-chain' ) ;
182+ const cmdLogs = document . getElementById ( 'cmd-logs' ) ;
183+ const cmdRestart = document . getElementById ( 'cmd-restart' ) ;
184+
185+ if ( cmdDeploy ) cmdDeploy . addEventListener ( 'click' , ( ) => DOM . modalDeploy . classList . remove ( 'hidden' ) ) ;
186+ if ( cmdChain ) cmdChain . addEventListener ( 'click' , ( ) => DOM . modalChain . classList . remove ( 'hidden' ) ) ;
187+ if ( cmdLogs ) cmdLogs . addEventListener ( 'click' , ( ) => DOM . panelLogs . classList . remove ( 'hidden' ) ) ;
188+ if ( cmdRestart ) cmdRestart . addEventListener ( 'click' , ( ) => {
173189 showToast ( 'Restarting network swarm...' , 'success' ) ;
174190 fetchRegistrySync ( ) ;
175191 } ) ;
176- document . getElementById ( 'cmd-kill-all' ) . addEventListener ( 'click' , ( ) => {
177- if ( ! confirm (
178- 'TERMINATE ALL NODES FROM US NEURAL MESH?\n' +
179- 'This action will disconnect all active agents.'
180- ) ) return ;
181-
182- // Animate each node out with stagger
183- const nodes = document . querySelectorAll ( '.agent-container' ) ;
184- nodes . forEach ( ( el , i ) => {
185- setTimeout ( ( ) => {
186- el . style . transition = 'all 0.4s cubic-bezier(0.2, 0.8, 0.2, 1)' ;
187- el . style . opacity = '0' ;
188- el . style . transform = 'scale(0) rotate(180deg)' ;
189- } , i * 80 ) ;
190- } ) ;
191-
192- // Clear state after animation
193- setTimeout ( ( ) => {
194- state . agents = [ ] ;
195- state . selectedAgentId = null ;
196- DOM . agentField . innerHTML = '' ;
197- updateStats ( {
198- latency : state . stats . latency ,
199- total : 0 ,
200- online : 0 ,
201- messages : state . stats . messages
202- } ) ;
203- closeTelemetry ( ) ;
204- showToast ( 'All nodes terminated from US Neural mesh.' , 'danger' ) ;
205- } , nodes . length * 80 + 400 ) ;
206- } ) ;
207192
208- // Close buttons
193+ // 5. Close buttons logic
209194 document . querySelectorAll ( '.btn-close' ) . forEach ( btn => {
210195 btn . addEventListener ( 'click' , ( e ) => {
211196 if ( btn . id === 'btn-close-telemetry' ) closeTelemetry ( ) ;
@@ -215,23 +200,12 @@ function initEventListeners() {
215200 } ) ;
216201 } ) ;
217202
218- // Context Menu hide
219- document . addEventListener ( 'click' , ( ) => DOM . ctxMenu . classList . add ( 'hidden' ) ) ;
220-
221- // Telemetry Actions
222- document . getElementById ( 'btn-ping-agent' ) . addEventListener ( 'click' , pingSelectedAgent ) ;
223- document . getElementById ( 'btn-send-payload' ) . addEventListener ( 'click' , sendPayloadToSelected ) ;
224- document . getElementById ( 'btn-terminate-node' ) . addEventListener ( 'click' , removeSelectedAgent ) ;
225-
226- // Deploy Submit
227- document . getElementById ( 'btn-submit-deploy' ) . addEventListener ( 'click' , deployNewAgent ) ;
228-
229- // Chain execution
230- document . getElementById ( 'btn-execute-chain' ) . addEventListener ( 'click' , ( ) => {
231- showToast ( 'Chain execution initiated...' , 'success' ) ;
232- document . getElementById ( 'chain-status' ) . textContent = 'Running...' ;
233- setTimeout ( ( ) => document . getElementById ( 'chain-status' ) . textContent = '240ms - Success' , 1500 ) ;
234- } ) ;
203+ // 6. Node Actions
204+ document . addEventListener ( 'click' , ( ) => { if ( DOM . ctxMenu ) DOM . ctxMenu . classList . add ( 'hidden' ) ; } ) ;
205+ if ( document . getElementById ( 'btn-ping-agent' ) ) document . getElementById ( 'btn-ping-agent' ) . addEventListener ( 'click' , pingSelectedAgent ) ;
206+ if ( document . getElementById ( 'btn-send-payload' ) ) document . getElementById ( 'btn-send-payload' ) . addEventListener ( 'click' , sendPayloadToSelected ) ;
207+ if ( document . getElementById ( 'btn-terminate-node' ) ) document . getElementById ( 'btn-terminate-node' ) . addEventListener ( 'click' , removeSelectedAgent ) ;
208+ if ( document . getElementById ( 'btn-submit-deploy' ) ) document . getElementById ( 'btn-submit-deploy' ) . addEventListener ( 'click' , deployNewAgent ) ;
235209}
236210
237211// --- API & DATA LAYER ---
@@ -242,9 +216,9 @@ async function apiFetch(endpoint, options = {}) {
242216
243217 // Try real API first with 2 second timeout
244218 try {
245- const timeoutId = setTimeout (
246- ( ) => controller . abort ( ) , 8000
247- ) ;
219+ const controller = new AbortController ( ) ;
220+ const timeoutId = setTimeout ( ( ) => controller . abort ( ) , 8000 ) ;
221+
248222 const res = await fetch (
249223 `${ CONFIG . API_BASE } ${ endpoint } ` ,
250224 { ...options , signal : controller . signal }
@@ -687,23 +661,24 @@ function updateCanvasUI() {
687661 el . addEventListener ( 'mouseenter' , ( e ) => showTooltip ( e , agent ) ) ;
688662 el . addEventListener ( 'mouseleave' , hideTooltip ) ;
689663
690- // Click Telemetry
664+
665+ // Click Telemetry OR Chain Selection
691666 el . addEventListener ( 'click' , ( e ) => {
692667 if ( activeSelectingSlot ) {
693- // Agar selection mode ON hai
694- const agent = state . agents . find ( a => a . agent_id === el . getAttribute ( 'data-id' ) ) ;
668+ const agentId = el . getAttribute ( 'data-id' ) ;
669+ const agent = state . agents . find ( a => a . agent_id === agentId ) ;
695670 chainSlots [ activeSelectingSlot ] = agent ;
696671
697- // UI update karo slot mein
698672 const slotEl = document . getElementById ( `slot-${ activeSelectingSlot } ` ) ;
699- slotEl . querySelector ( '.slot-text' ) . textContent = agent . name ;
700- slotEl . classList . add ( 'filled' ) ;
673+ if ( slotEl ) {
674+ slotEl . querySelector ( '.slot-text' ) . textContent = agent . name ;
675+ slotEl . classList . add ( 'filled' ) ;
676+ }
701677
702- activeSelectingSlot = null ; // Selection mode OFF
703- DOM . modalChain . classList . remove ( 'hidden' ) ; // Modal wapas dikhao
678+ activeSelectingSlot = null ;
679+ DOM . modalChain . classList . remove ( 'hidden' ) ;
704680 showToast ( "Agent linked to chain" , "success" ) ;
705681 } else {
706- // Normal behavior: Telemetry kholo
707682 openTelemetry ( agent . agent_id ) ;
708683 }
709684 } ) ;
@@ -1119,48 +1094,46 @@ function showToast(message, type = 'danger', duration = 3000) {
11191094 } , duration ) ;
11201095}
11211096
1122- // Function 1: Slot select karne ki taiyari
1097+ // ============================================
1098+ // VISUAL CHAIN BUILDER LOGIC
1099+ // ============================================
1100+ // --- CHAIN BUILDER LOGIC ---
1101+
11231102function prepareSelection ( slotId ) {
11241103 activeSelectingSlot = slotId ;
1125- DOM . modalChain . classList . add ( 'hidden' ) ; // Modal hide karo taaki user agent select kar sake
1126- showToast ( `Click an agent on the dashboard for Step ${ slotId } ` , "success" ) ;
1104+ if ( DOM . modalChain ) DOM . modalChain . classList . add ( 'hidden' ) ;
1105+ showToast ( `Click an agent for Step ${ slotId } ` , "success" ) ;
11271106}
11281107
1129- // Function 2: Execute Chain (Simulation + Canvas Particles)
11301108async function executeVisualChain ( ) {
1131- const payload = document . getElementById ( 'chain-payload' ) . value ;
1132- if ( ! chainSlots [ 1 ] || ! payload ) {
1133- showToast ( "Minimum 1 agent and input required" , "danger" ) ;
1109+ const payloadInput = document . getElementById ( 'chain-payload' ) ;
1110+ const statusEl = document . getElementById ( 'chain-status' ) ;
1111+
1112+ if ( ! chainSlots [ 1 ] || ! payloadInput || ! payloadInput . value ) {
1113+ showToast ( "Agent and input required" , "danger" ) ;
11341114 return ;
11351115 }
11361116
1137- const statusEl = document . getElementById ( 'chain-status' ) ;
11381117 statusEl . textContent = "🚀 Chain Initiated..." ;
11391118
11401119 for ( let i = 1 ; i <= 3 ; i ++ ) {
11411120 if ( ! chainSlots [ i ] ) break ;
1142-
11431121 const agent = chainSlots [ i ] ;
1144- statusEl . textContent = `📡 Step ${ i } : Processing at ${ agent . name } ...` ;
1122+ statusEl . textContent = `📡 Routing to ${ agent . name } ...` ;
11451123
1146- // Asli Magic: Canvas particle trigger karo
1147- // Ye existing connection logic ko use karega
11481124 state . activeConnections [ agent . agent_id ] = {
11491125 timestamp : performance . now ( ) ,
11501126 success : true
11511127 } ;
1152-
1153- await new Promise ( r => setTimeout ( r , 1500 ) ) ; // Delay for effect
1128+ await new Promise ( r => setTimeout ( r , 1500 ) ) ;
11541129 }
11551130
1156- statusEl . textContent = "✅ Chain Success (1120ms) " ;
1157- showToast ( "Global Workflow Completed" , "success" ) ;
1131+ statusEl . textContent = "✅ Chain Success" ;
1132+ showToast ( "Workflow Completed" , "success" ) ;
11581133 triggerCorePulse ( ) ;
1159- } el . addEventListener
1134+ }
11601135
1161- // ============================================
1162- // US NEURAL BOOT SEQUENCE
1163- // ============================================
1136+ // --- BOOT SEQUENCE ---
11641137
11651138function initBootSequence ( ) {
11661139 const boot = document . getElementById ( 'boot-screen' ) ;
@@ -1175,4 +1148,10 @@ function initBootSequence() {
11751148 } , 1400 ) ;
11761149}
11771150
1178- initBootSequence ( ) ;
1151+ document . addEventListener ( 'DOMContentLoaded' , ( ) => {
1152+ initCanvas ( ) ;
1153+ initEventListeners ( ) ;
1154+ fetchRegistrySync ( ) ;
1155+ setInterval ( fetchRegistrySync , CONFIG . POLL_INTERVAL ) ;
1156+ initBootSequence ( ) ; // ✅ Yahan rakho
1157+ } ) ;
0 commit comments