UNPKG

ruv-swarm

Version:

High-performance neural network swarm orchestration in WebAssembly

436 lines (365 loc) 14.5 kB
/** * WASM Bindings Loader * Properly loads WASM bindings with the correct import structure */ import { promises as fs } from 'node:fs'; import path from 'node:path'; import { fileURLToPath, pathToFileURL } from 'node:url'; // Get current directory const __filename = fileURLToPath(import.meta.url); const __dirname = path.dirname(__filename); // Global wasm instance for wasm-bindgen compatibility let globalWasm; // Create a proper WASM bindings loader that matches the expected import structure class WasmBindingsLoader { constructor() { this.initialized = false; this.exports = {}; this.memory = null; this.wasm = null; this.heap = new Array(128).fill(undefined); this.heap_next = this.heap.length; // Initialize heap with special values this.heap.push(undefined, null, true, false); } async initialize() { if (this.initialized) return this; try { // Paths to WASM files const wasmJsPath = path.join(__dirname, 'ruv_swarm_wasm.js'); const wasmBinaryPath = path.join(__dirname, 'ruv_swarm_wasm_bg.wasm'); // Check if files exist try { await fs.access(wasmJsPath); await fs.access(wasmBinaryPath); } catch (error) { console.warn(`WASM files not found: ${error.message}`); return this.initializePlaceholder(); } // Import the wasm-bindgen generated module const wasmJsUrl = pathToFileURL(wasmJsPath).href; const wasmModule = await import(wasmJsUrl); // Read the WASM binary directly const wasmBinary = await fs.readFile(wasmBinaryPath); // Initialize using the wasm-bindgen module with the binary data if (typeof wasmModule.__wbg_init === 'function') { // Pass the binary data in the expected format to avoid deprecation warning await wasmModule.__wbg_init({ module_or_path: wasmBinary.buffer }); } else if (typeof wasmModule.default === 'function') { await wasmModule.default({ module_or_path: wasmBinary.buffer }); } else if (typeof wasmModule.init === 'function') { await wasmModule.init(wasmBinary.buffer); } else if (typeof wasmModule.initSync === 'function') { // Some versions have a sync init wasmModule.initSync(wasmBinary.buffer); } else { // Fallback to manual instantiation const imports = wasmModule.__wbg_get_imports ? wasmModule.__wbg_get_imports() : this.createImports(); const { instance } = await WebAssembly.instantiate(wasmBinary, imports); // Call finalize if it exists if (wasmModule.__wbg_finalize_init) { wasmModule.__wbg_finalize_init(instance, wasmModule); } } // Copy all exports from the wasm module to this object for (const key in wasmModule) { if (key.startsWith('__wbg_')) continue; // Skip internal wasm-bindgen functions const value = wasmModule[key]; if (typeof value === 'function') { this[key] = value.bind(wasmModule); } else if (value !== undefined) { Object.defineProperty(this, key, { get: () => wasmModule[key], configurable: true }); } } // Store reference to the wasm module this.wasm = wasmModule.wasm || wasmModule; this.memory = wasmModule.memory || (wasmModule.wasm && wasmModule.wasm.memory); globalWasm = this.wasm; this.initialized = true; console.log('✅ WASM bindings loaded successfully (actual WASM)'); return this; } catch (error) { console.error('❌ Failed to initialize WASM bindings:', error); return this.initializePlaceholder(); } } // Create the imports object that the WASM module expects createImports() { const imports = {}; imports.wbg = {}; // Helper functions for memory management const getObject = (idx) => this.heap[idx]; const addHeapObject = (obj) => { if (this.heap_next === this.heap.length) this.heap.push(this.heap.length + 1); const idx = this.heap_next; this.heap_next = this.heap[idx]; this.heap[idx] = obj; return idx; }; // Drop an object from the heap const dropObject = (idx) => { if (idx < 36) return; this.heap[idx] = this.heap_next; this.heap_next = idx; }; // Take an object from the heap (and drop it) const takeObject = (idx) => { const ret = getObject(idx); dropObject(idx); return ret; }; // String handling for WASM const cachedTextDecoder = new TextDecoder('utf-8', { ignoreBOM: true, fatal: true }); let cachedUint8Memory0 = null; const getUint8Memory0 = () => { if (cachedUint8Memory0 === null || cachedUint8Memory0.byteLength === 0) { const wasm = globalWasm || this.wasm; if (wasm && wasm.memory) { cachedUint8Memory0 = new Uint8Array(wasm.memory.buffer); } else { cachedUint8Memory0 = new Uint8Array(1024); } } return cachedUint8Memory0; }; const getStringFromWasm0 = (ptr, len) => { ptr = ptr >>> 0; return cachedTextDecoder.decode(getUint8Memory0().subarray(ptr, ptr + len)); }; // Error handling function const handleError = (f, args) => { try { return f.apply(null, args); } catch (e) { if (this.wasm && this.wasm.__wbindgen_export_0) { this.wasm.__wbindgen_export_0(addHeapObject(e)); } throw e; } }; // Check if value is undefined or null const isLikeNone = (x) => x === undefined || x === null; // Add all the required import functions imports.wbg.__wbg_buffer_609cc3eee51ed158 = function(arg0) { return addHeapObject(getObject(arg0).buffer); }; imports.wbg.__wbg_call_672a4d21634d4a24 = function() { return handleError(function (arg0, arg1) { return addHeapObject(getObject(arg0).call(getObject(arg1))); }, arguments); }; imports.wbg.__wbg_error_524f506f44df1645 = function(arg0) { console.error(getObject(arg0)); }; imports.wbg.__wbg_error_7534b8e9a36f1ab4 = function(arg0, arg1) { var v0 = getStringFromWasm0(arg0, arg1).slice(); if (this.wasm && this.wasm.__wbindgen_export_1) { this.wasm.__wbindgen_export_1(arg0, arg1 * 1, 1); } console.error(v0); }.bind(this); imports.wbg.__wbg_from_2a5d3e218e67aa85 = function(arg0) { return addHeapObject(Array.from(getObject(arg0))); }; imports.wbg.__wbg_get_67b2ba62fc30de12 = function() { return handleError(function(arg0, arg1) { return addHeapObject(Reflect.get(getObject(arg0), getObject(arg1))); }, arguments); }; imports.wbg.__wbg_get_b9b93047fe3cf45b = function(arg0, arg1) { return addHeapObject(getObject(arg0)[arg1 >>> 0]); }; imports.wbg.__wbg_instanceof_Error_4d54113b22d20306 = function(arg0) { let result; try { result = getObject(arg0) instanceof Error; } catch { result = false; } return result; }; imports.wbg.__wbg_instanceof_Window_def73ea0955fc569 = function(arg0) { let result; try { result = getObject(arg0) instanceof Window; } catch (_) { result = false; } const ret = result; return ret; }; imports.wbg.__wbg_length_e2d2a49132c1b256 = function(arg0) { return getObject(arg0).length; }; imports.wbg.__wbg_log_c222819a41e063d3 = function(arg0) { console.log(getObject(arg0)); }; imports.wbg.__wbg_message_97a2af9b89d693a3 = function(arg0) { return addHeapObject(getObject(arg0).message); }; imports.wbg.__wbg_new_780abee5c1739fd7 = function(arg0) { try { return addHeapObject(new Function(getObject(arg0))); } catch (e) { console.error("Error creating function:", e); return addHeapObject(() => {}); } }; imports.wbg.__wbg_new_8a6f238a6ece86ea = function() { return addHeapObject(new Object()); }; imports.wbg.__wbg_newnoargs_105ed471475aaf50 = function(arg0, arg1) { try { const str = getStringFromWasm0(arg0, arg1); return addHeapObject(new Function(str)); } catch (e) { console.error("Error creating function:", e); return addHeapObject(() => {}); } }; imports.wbg.__wbg_newwithbyteoffsetandlength_e6b7e69acd4c7354 = function(arg0, arg1, arg2) { return addHeapObject(new Uint8Array(getObject(arg0), arg1 >>> 0, arg2 >>> 0)); }; imports.wbg.__wbg_now_807e54c39636c349 = function() { return Date.now(); }; imports.wbg.__wbg_random_3ad904d98382defe = function() { return Math.random(); }; imports.wbg.__wbg_static_accessor_GLOBAL_88a902d13a557d07 = function() { return addHeapObject(globalThis); }; imports.wbg.__wbg_static_accessor_GLOBAL_THIS_56578be7e9f832b0 = function() { return addHeapObject(globalThis); }; imports.wbg.__wbg_static_accessor_SELF_37c5d418e4bf5819 = function() { return addHeapObject(globalThis); }; imports.wbg.__wbg_static_accessor_WINDOW_5de37043a91a9c40 = function() { return addHeapObject(globalThis); }; imports.wbg.__wbg_warn_4ca3906c248c47c4 = function(arg0) { console.warn(getObject(arg0)); }; imports.wbg.__wbg_stack_0ed75d68575b0f3c = function(arg0, arg1) { const ret = getObject(arg1).stack; const ptr1 = this.wasm && this.wasm.__wbindgen_malloc ? this.wasm.__wbindgen_malloc(ret.length * 1, 1) : 0; const len1 = ret.length; if (ptr1 && getUint8Memory0()) { getUint8Memory0().subarray(ptr1, ptr1 + len1).set(new TextEncoder().encode(ret)); getUint8Memory0()[ptr1 + len1] = 0; } const dataView = new DataView(getUint8Memory0().buffer); dataView.setInt32(arg0 + 4 * 1, len1, true); dataView.setInt32(arg0 + 4 * 0, ptr1, true); }.bind(this); imports.wbg.__wbindgen_debug_string = function(arg0, arg1) { const obj = getObject(arg1); const debugStr = String(obj); const ptr = this.wasm && this.wasm.__wbindgen_malloc ? this.wasm.__wbindgen_malloc(debugStr.length * 1, 1) : 0; const len = debugStr.length; if (ptr && getUint8Memory0()) { getUint8Memory0().subarray(ptr, ptr + len).set(new TextEncoder().encode(debugStr)); getUint8Memory0()[ptr + len] = 0; } const dataView = new DataView(getUint8Memory0().buffer); dataView.setInt32(arg0 + 4 * 1, len, true); dataView.setInt32(arg0 + 4 * 0, ptr, true); }.bind(this); imports.wbg.__wbindgen_is_undefined = function(arg0) { return getObject(arg0) === undefined; }; imports.wbg.__wbindgen_memory = function() { const wasm = globalWasm || this.wasm; return addHeapObject(wasm.memory); }.bind(this); imports.wbg.__wbindgen_number_get = function(arg0, arg1) { const obj = getObject(arg1); const val = typeof(obj) === 'number' ? obj : undefined; if (!isLikeNone(val)) { getObject(arg0).value = val; return 1; } return 0; }; imports.wbg.__wbindgen_object_clone_ref = function(arg0) { return addHeapObject(getObject(arg0)); }; imports.wbg.__wbindgen_object_drop_ref = function(arg0) { takeObject(arg0); }; imports.wbg.__wbindgen_string_get = function(arg0, arg1) { const obj = getObject(arg1); const val = typeof(obj) === 'string' ? obj : undefined; if (!isLikeNone(val)) { const ptr = this.wasm && this.wasm.__wbindgen_malloc ? this.wasm.__wbindgen_malloc(val.length * 1, 1) : 0; const len = val.length; if (ptr && getUint8Memory0()) { getUint8Memory0().subarray(ptr, ptr + len).set(new TextEncoder().encode(val)); getUint8Memory0()[ptr + len] = 0; } const dataView = new DataView(getUint8Memory0().buffer); dataView.setInt32(arg0 + 4 * 1, len, true); dataView.setInt32(arg0 + 4 * 0, ptr, true); return 1; } return 0; }.bind(this); imports.wbg.__wbindgen_string_new = function(arg0, arg1) { const ret = getStringFromWasm0(arg0, arg1); return addHeapObject(ret); }; imports.wbg.__wbindgen_throw = function(arg0, arg1) { throw new Error(getStringFromWasm0(arg0, arg1)); }; return imports; } // Initialize placeholder functionality when actual WASM can't be loaded initializePlaceholder() { console.warn('⚠️ Using placeholder WASM functionality'); // Create placeholder memory this.memory = new WebAssembly.Memory({ initial: 1, maximum: 10 }); // Add placeholder functions this.addNeuralNetworkFunctions(); this.addForecastingFunctions(); this.initialized = true; return this; } // Add neural network specific functions addNeuralNetworkFunctions() { this.create_neural_network = (layers, neurons_per_layer) => { console.log(`Creating neural network with ${layers} layers and ${neurons_per_layer} neurons per layer`); return 1; // Network ID }; this.train_network = (network_id, data, epochs) => { console.log(`Training network ${network_id} for ${epochs} epochs`); return true; }; this.forward_pass = (network_id, input) => { console.log(`Forward pass on network ${network_id}`); return new Float32Array([0.5, 0.5, 0.5]); // Placeholder output }; } // Add forecasting specific functions addForecastingFunctions() { this.create_forecasting_model = (type) => { console.log(`Creating forecasting model of type ${type}`); return 1; // Model ID }; this.forecast = (model_id, data, horizon) => { console.log(`Forecasting with model ${model_id} for horizon ${horizon}`); return new Float32Array([0.1, 0.2, 0.3]); // Placeholder forecast }; } // Get total memory usage getTotalMemoryUsage() { if (!this.memory) return 0; return this.memory.buffer.byteLength; } } // Create singleton instance const loader = new WasmBindingsLoader(); export default loader;