/** * OpsetChecker - Displays opset compatibility information for a loaded ONNX model * Shows current opset version, compares against standard versions, lists domains and custom operators. * Requirements: 22.1, 22.2, 22.3, 22.4, 22.5 */ class OpsetChecker { /** * Standard ONNX opset versions to compare against. * @type {number[]} */ static STANDARD_OPSETS = [7, 9, 11, 13, 15, 17, 18, 19, 20, 21]; /** * @param {string} containerId - ID of the container element */ constructor(containerId) { this._containerId = containerId; this._container = document.getElementById(containerId); this._data = null; if (!this._container) { console.warn(`[OpsetChecker] Container #${containerId} not found`); } this._setupEventListeners(); } // ─── Private ────────────────────────────────────────────────────────────── /** * Listen for model:loaded events to auto-update. */ _setupEventListeners() { if (window.EventBus && typeof CONFIG !== 'undefined' && CONFIG.EVENTS) { window.EventBus.on(CONFIG.EVENTS.MODEL_LOADED, (data) => { if (data && data.model) { const result = this.compute(data.model); this.render(result); } }); } } /** * Escape HTML special characters. * @param {string} str * @returns {string} */ _escapeHtml(str) { const div = document.createElement('div'); div.appendChild(document.createTextNode(String(str))); return div.innerHTML; } // ─── Public API ─────────────────────────────────────────────────────────── /** * Compute opset compatibility data from a parsed model. * @param {object} parsedModel * @returns {{ modelOpset: number, compatibility: Array<{version: number, compatible: boolean}>, domains: Array<{domain: string, version: number}>, customOperators: Array<{name: string, domain: string}>, allStandard: boolean }} */ compute(parsedModel) { const modelOpset = (parsedModel && parsedModel.metadata && parsedModel.metadata.opsetVersion) || 0; // Compare against standard opset versions // Compatible means the standard version >= model's opset (runtime can run the model) const compatibility = OpsetChecker.STANDARD_OPSETS.map((version) => ({ version, compatible: version >= modelOpset, })); // Extract all domains and versions from opset_import const opsetImport = (parsedModel && parsedModel.metadata && Array.isArray(parsedModel.metadata.opsetImport)) ? parsedModel.metadata.opsetImport : []; const domains = opsetImport.map((op) => ({ domain: op.domain || 'ai.onnx (default)', version: op.version || 0, })); // Find custom domain operators from graph nodes const nodes = (parsedModel && parsedModel.graph && parsedModel.graph.nodes) || []; const customOperators = []; const seen = new Set(); for (const node of nodes) { if (node.domain && node.domain !== '' && node.domain !== 'ai.onnx') { const key = `${node.domain}::${node.opType}`; if (!seen.has(key)) { seen.add(key); customOperators.push({ name: node.opType || 'Unknown', domain: node.domain }); } } } const allStandard = customOperators.length === 0; this._data = { modelOpset, compatibility, domains, customOperators, allStandard }; return this._data; } /** * Render the opset compatibility information into the container. * @param {{ modelOpset: number, compatibility: Array, domains: Array, customOperators: Array, allStandard: boolean }} data */ render(data) { if (!this._container) return; if (!data) { this._container.innerHTML = '

No opset information available.

'; return; } const { modelOpset, compatibility, domains, customOperators, allStandard } = data; let html = ''; // Current opset version html += `
Model Opset Version: ${modelOpset}
`; // Standard opset compatibility table html += `
Standard Opset Compatibility
`; for (const entry of compatibility) { const icon = entry.compatible ? 'fa-check-circle text-success' : 'fa-times-circle text-danger'; const label = entry.compatible ? 'Compatible' : 'Incompatible'; html += ` ${entry.version} `; } html += `
`; // Domains from opset_import if (domains.length > 0) { html += `
Opset Imports
`; for (const d of domains) { html += ` `; } html += `
Domain Version
${this._escapeHtml(d.domain)} ${d.version}
`; } // Custom domain operators if (allStandard) { html += `
All operators compatible with standard ONNX
`; } else { html += `
Custom Domain Operators
`; for (const op of customOperators) { html += ` `; } html += `
Operator Domain
${this._escapeHtml(op.name)} ${this._escapeHtml(op.domain)}
`; } this._container.innerHTML = html; } /** * Clear the display. */ clear() { this._data = null; if (!this._container) return; this._container.innerHTML = '

Select a model to view opset compatibility

'; } /** * Get the last computed data. * @returns {object|null} */ getData() { return this._data; } } window.OpsetChecker = OpsetChecker;