1(function () { 2 var runtime = { 3 checkedAt: new Date().toISOString(), 4 crossOriginIsolated: typeof self !== 'undefined' ? !!self.crossOriginIsolated : false, 5 documentModelContext: typeof document !== 'undefined' ? typeof document.modelContext : 'unavailable', 6 navigatorModelContext: typeof navigator !== 'undefined' ? typeof navigator.modelContext : 'unavailable', 7 runtimeAvailable: false, 8 using: '', 9 registeredTools: [], 10 registrationErrors: [], 11 providedContext: false, 12 reason: '' 13 }; 14 15 window.ConversionAgentDiscoveryWebMCPRuntime = runtime; 16 window.ConversionAgentDiscoveryWebMCPProbe = function () { 17 return JSON.parse(JSON.stringify(runtime)); 18 }; 19 20 function cleanText(value) { 21 return String(value || '').replace(/\s+/g, ' ').trim(); 22 } 23 24 function cssString(value) { 25 return String(value || '').replace(/\\/g, '\\\\').replace(/"/g, '\\"'); 26 } 27 28 function humanizeIdentifier(value) { 29 var text = String(value || '') 30 .replace(/^form_fields\[/, '') 31 .replace(/\]$/, '') 32 .replace(/^fields\[/, '') 33 .replace(/^field_/, 'field ') 34 .replace(/[_-]+/g, ' '); 35 36 if (/g recaptcha response/i.test(text) || /recaptcha/i.test(text)) { 37 return 'reCAPTCHA response token'; 38 } 39 40 text = cleanText(text); 41 if (!text) { 42 return ''; 43 } 44 45 return text.charAt(0).toUpperCase() + text.slice(1); 46 } 47 48 function fieldLabelText(field, form) { 49 var label = cleanText(field.getAttribute('aria-label')) || cleanText(field.getAttribute('title')); 50 var id = field.getAttribute('id'); 51 var placeholder = cleanText(field.getAttribute('placeholder')); 52 var name = field.getAttribute('name'); 53 54 if (!label && id) { 55 var localLabel = form.querySelector('label[for="' + cssString(id) + '"]'); 56 if (localLabel) { 57 label = cleanText(localLabel.textContent); 58 } 59 } 60 61 return label || placeholder || humanizeIdentifier(name) || humanizeIdentifier(id); 62 } 63 64 function describeDeclarativeFormFields() { 65 if (typeof document === 'undefined') { 66 return; 67 } 68 69 var forms = document.querySelectorAll('form[toolname][tooldescription]'); 70 Array.prototype.forEach.call(forms, function (form) { 71 var fields = form.querySelectorAll('input:not([type="hidden"]), textarea, select'); 72 Array.prototype.forEach.call(fields, function (field) { 73 if (field.disabled) { 74 return; 75 } 76 77 var description = fieldLabelText(field, form); 78 if (!description) { 79 return; 80 } 81 82 if (!cleanText(field.getAttribute('aria-label')) && !cleanText(field.getAttribute('aria-labelledby'))) { 83 field.setAttribute('aria-label', description); 84 } 85 if (!cleanText(field.getAttribute('title'))) { 86 field.setAttribute('title', description); 87 } 88 if (!cleanText(field.getAttribute('toolparamdescription'))) { 89 field.setAttribute('toolparamdescription', description); 90 } 91 }); 92 }); 93 } 94 95 function observeDeclarativeForms() { 96 describeDeclarativeFormFields(); 97 if (typeof document === 'undefined' || typeof MutationObserver !== 'function' || !document.documentElement) { 98 return; 99 } 100 101 var observer = new MutationObserver(function () { 102 describeDeclarativeFormFields(); 103 }); 104 observer.observe(document.documentElement, { childList: true, subtree: true }); 105 106 if (document.readyState === 'loading') { 107 document.addEventListener('DOMContentLoaded', describeDeclarativeFormFields, { once: true }); 108 } 109 } 110 111 observeDeclarativeForms(); 112 113 var documentModelContext = typeof document !== 'undefined' ? document.modelContext : null; 114 var navigatorModelContext = typeof navigator !== 'undefined' ? navigator.modelContext : null; 115 var modelContext = documentModelContext || navigatorModelContext; 116 if (!modelContext) { 117 runtime.reason = 'No browser modelContext API is available. Use a WebMCP-capable Chrome build or origin trial.'; 118 return; 119 } 120 121 runtime.runtimeAvailable = true; 122 runtime.using = documentModelContext ? 'document.modelContext' : 'navigator.modelContext'; 123 124 var config = window.ConversionAgentDiscoveryWebMCP || {}; 125 if (!config.endpoints) { 126 runtime.reason = 'Missing ConversionAgentDiscoveryWebMCP endpoints config.'; 127 return; 128 } 129 130 function withParams(url, params) { 131 var next = new URL(url, window.location.origin);
132 Object.keys(params || {}).forEach(function (key) { 133 var value = params[key]; 134 if (value !== undefined && value !== null && value !== '') { 135 next.searchParams.set(key, String(value)); 136 } 137 }); 138 return next.toString(); 139 } 140 141 async function getJson(url, params) { 142 var response = await fetch(withParams(url, params || {}), { 143 method: 'GET', 144 credentials: 'same-origin', 145 headers: { Accept: 'application/json' } 146 }); 147 var body = await response.json().catch(function () { 148 return {}; 149 }); 150 if (!response.ok) { 151 return { error: body.message || (config.messages && config.messages.request_failed) || String(response.status), status: response.status }; 152 } 153 return body; 154 } 155 156 var tools = (config.tools || []).map(function (tool) { 157 return Object.assign({}, tool, { 158 execute: function (input) { 159 return getJson(config.endpoints[tool.endpoint], input || {}); 160 }, 161 annotations: Object.assign({ readOnlyHint: true }, tool.annotations || {}) 162 }); 163 }); 164 165 if (typeof modelContext.registerTool === 'function') { 166 Promise.all(tools.map(function (tool) { 167 return Promise.resolve() 168 .then(function () { 169 return modelContext.registerTool(tool); 170 }) 171 .then(function () { 172 runtime.registeredTools.push(tool.name); 173 }) 174 .catch(function (error) { 175 runtime.registrationErrors.push({ 176 tool: tool.name, 177 message: error && error.message ? error.message : String(error) 178 }); 179 }); 180 })).then(function () { 181 runtime.reason = runtime.registrationErrors.length ? 'Some WebMCP tools failed to register.' : 'WebMCP tools registered.'; 182 }); 183 runtime.reason = 'WebMCP tool registration started.'; 184 return; 185 } 186 187 if (typeof modelContext.provideContext === 'function') { 188 try { 189 modelContext.provideContext({ tools: tools }); 190 runtime.providedContext = true; 191 runtime.registeredTools = tools.map(function (tool) { 192 return tool.name; 193 }); 194 runtime.reason = 'WebMCP context provided through legacy provideContext.'; 195 } catch (error) { 196 runtime.registrationErrors.push({ 197 tool: 'provideContext', 198 message: error && error.message ? error.message : String(error) 199 }); 200 runtime.reason = 'Legacy WebMCP context registration failed.'; 201 } 202 return; 203 } 204 205 runtime.reason = 'modelContext exists but no supported registration API was found.'; 206})();
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.