@nxisai/nxis 2.2.3 → 2.2.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/build/nxis.js +1 -1
- package/build/webmcp/types.d.ts +9 -0
- package/build/webmcp.js +1 -1
- package/package.json +1 -1
- package/src/webmcp/register.ts +2 -0
- package/src/webmcp/types.ts +9 -0
package/build/nxis.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
!function(){const e={NXIS_API_HOST:"https://proxy.nxis.ai"};try{if(process)return process.env=Object.assign({},process.env),void Object.assign(process.env,e)}catch(e){}globalThis.process={env:e}}();class e extends Error{constructor(t){super(t),Object.setPrototypeOf(this,e.prototype)}}var t;!function(e){e[e.OK=0]="OK",e[e.INVALID_ARGUMENT=3]="INVALID_ARGUMENT",e[e.NOT_FOUND=5]="NOT_FOUND",e[e.PERMISSION_DENIED=7]="PERMISSION_DENIED",e[e.RESOURCE_EXHAUSTED=8]="RESOURCE_EXHAUSTED",e[e.INTERNAL=13]="INTERNAL",e[e.UNAUTHENTICATED=16]="UNAUTHENTICATED"}(t||(t={})),t.OK,t.INVALID_ARGUMENT,t.NOT_FOUND,t.PERMISSION_DENIED,t.RESOURCE_EXHAUSTED,t.INTERNAL,t.UNAUTHENTICATED;class n extends Error{constructor(e,t,o){super(o),this.code=e,this.httpStatus=t,this.name="ProxyError",Object.setPrototypeOf(this,n.prototype)}get isRetryable(){return this.code===t.RESOURCE_EXHAUSTED||this.code===t.INTERNAL}get isAuthError(){return this.code===t.UNAUTHENTICATED||this.code===t.PERMISSION_DENIED}static fromResponse(e,t){return new n(t.code,e,t.message)}}function o(e){return null===e?"null":Array.isArray(e)?"array":typeof e}function r(e,t){if(e===t)return!0;if(o(e)!==o(t))return!1;if(Array.isArray(e)&&Array.isArray(t))return e.length===t.length&&e.every((e,n)=>r(e,t[n]));if("object"===o(e)){const n=e,o=t,i=Object.keys(n);return i.length===Object.keys(o).length&&i.every(e=>r(n[e],o[e]))}return!1}function i(e,t,n="$"){if(!t||"object"!=typeof t)return[];const a=[];if(void 0===t.const||r(e,t.const)||a.push({path:n,message:`must equal const ${JSON.stringify(t.const)}`}),t.enum&&!t.enum.some(t=>r(e,t))&&a.push({path:n,message:`must be one of ${JSON.stringify(t.enum)}`}),void 0!==t.type){const r=Array.isArray(t.type)?t.type:[t.type];if(!r.some(t=>function(e,t){switch(t){case"object":return"object"===o(e);case"array":return Array.isArray(e);case"string":return"string"==typeof e;case"number":return"number"==typeof e&&Number.isFinite(e);case"integer":return"number"==typeof e&&Number.isInteger(e);case"boolean":return"boolean"==typeof e;case"null":return null===e;default:return!0}}(e,t)))return a.push({path:n,message:`expected type ${r.join(" | ")}, got ${o(e)}`}),a}if("string"==typeof e&&(void 0!==t.minLength&&e.length<t.minLength&&a.push({path:n,message:`must be at least ${t.minLength} characters`}),void 0!==t.maxLength&&e.length>t.maxLength&&a.push({path:n,message:`must be at most ${t.maxLength} characters`}),void 0!==t.pattern)){let o=null;try{o=new RegExp(t.pattern,"u")}catch{}o&&!o.test(e)&&a.push({path:n,message:`must match pattern ${t.pattern}`})}if("number"==typeof e&&(void 0!==t.minimum&&e<t.minimum&&a.push({path:n,message:`must be >= ${t.minimum}`}),void 0!==t.maximum&&e>t.maximum&&a.push({path:n,message:`must be <= ${t.maximum}`})),Array.isArray(e)&&(void 0!==t.minItems&&e.length<t.minItems&&a.push({path:n,message:`must have at least ${t.minItems} items`}),void 0!==t.maxItems&&e.length>t.maxItems&&a.push({path:n,message:`must have at most ${t.maxItems} items`}),t.items&&e.forEach((e,o)=>{a.push(...i(e,t.items,`${n}[${o}]`))})),"object"===o(e)&&!Array.isArray(e)&&null!==e){const o=e;for(const e of t.required??[])e in o||a.push({path:n,message:`missing required property "${e}"`});const r=t.properties??{};for(const[e,t]of Object.entries(r))e in o&&a.push(...i(o[e],t,`${n}.${e}`));if(!1===t.additionalProperties)for(const e of Object.keys(o))e in r||a.push({path:n,message:`unexpected property "${e}"`});else if(t.additionalProperties&&"object"==typeof t.additionalProperties)for(const e of Object.keys(o))e in r||a.push(...i(o[e],t.additionalProperties,`${n}.${e}`))}if(t.allOf)for(const o of t.allOf)a.push(...i(e,o,n));if(t.anyOf&&t.anyOf.length>0){t.anyOf.some(t=>0===i(e,t,n).length)||a.push({path:n,message:"does not match any schema in anyOf"})}if(t.oneOf&&t.oneOf.length>0){const o=t.oneOf.filter(t=>0===i(e,t,n).length).length;1!==o&&a.push({path:n,message:`must match exactly one schema in oneOf (matched ${o})`})}return a}var a,s,l,u,c,d,f=function(e,t,n,o){if("a"===n&&!o)throw new TypeError("Private accessor was defined without a getter");if("function"==typeof t?e!==t||!o:!t.has(e))throw new TypeError("Cannot read private member from an object whose class did not declare it");return"m"===n?o:"a"===n?o.call(e):o?o.value:t.get(e)},p=function(e,t,n,o,r){if("m"===o)throw new TypeError("Private method is not writable");if("a"===o&&!r)throw new TypeError("Private accessor was defined without a setter");if("function"==typeof t?e!==t||!r:!t.has(e))throw new TypeError("Cannot write private member to an object whose class did not declare it");return"a"===o?r.call(e,n):r?r.value=n:t.set(e,n),n};const m={type:"object"};function h(e,t){if("function"==typeof DOMException)return new DOMException(e,t);const n=new Error(e);return n.name=t,n}function v(e){if(!e||"object"!=typeof e)throw new TypeError("Tool descriptor must be an object.");if("string"!=typeof e.name||0===e.name.length)throw new TypeError("Tool descriptor requires a non-empty string 'name'.");if("string"!=typeof e.description)throw new TypeError(`Tool "${e.name}" requires a string 'description'.`);if("function"!=typeof e.execute)throw new TypeError(`Tool "${e.name}" requires an 'execute' function.`);if(void 0!==e.inputSchema&&"object"!=typeof e.inputSchema)throw new TypeError(`Tool "${e.name}": 'inputSchema' must be an object.`)}class g extends EventTarget{constructor(){super(...arguments),a.add(this),s.set(this,new Map),l.set(this,null),u.set(this,!1)}get ontoolchange(){return f(this,l,"f")}set ontoolchange(e){f(this,l,"f")&&this.removeEventListener("toolchange",f(this,l,"f")),p(this,l,"function"==typeof e?e:null,"f"),f(this,l,"f")&&this.addEventListener("toolchange",f(this,l,"f"))}registerTool(e,t={}){v(e);const{signal:n,exposedTo:o}=t;if(n?.aborted)return;f(this,a,"m",c).call(this,e.name);const r={tool:e,exposedTo:o?[...o]:void 0,pageLevel:!1};if(n){const t=()=>f(this,a,"m",c).call(this,e.name,r,!0);n.addEventListener("abort",t,{once:!0}),r.abortListener={signal:n,listener:t}}f(this,s,"f").set(e.name,r),f(this,a,"m",d).call(this)}provideContext(e={}){const t=e.tools??[];for(const e of t)v(e);if(new Set(t.map(e=>e.name)).size!==t.length)throw new TypeError("provideContext(): duplicate tool names in 'tools'.");for(const[e,t]of f(this,s,"f"))t.pageLevel&&f(this,a,"m",c).call(this,e);for(const e of t){if(f(this,s,"f").has(e.name))throw h(`provideContext(): tool "${e.name}" is already registered via registerTool().`,"InvalidStateError");f(this,s,"f").set(e.name,{tool:e,exposedTo:void 0,pageLevel:!0})}f(this,a,"m",d).call(this)}async getTools(e={}){e.fromOrigins;const t="undefined"!=typeof location?location.origin:void 0;return[...f(this,s,"f").values()].map(({tool:e})=>{const n={name:e.name,description:e.description,inputSchema:structuredClone(e.inputSchema??m)};return e.annotations&&(n.annotations=structuredClone(e.annotations)),t&&(n.origin=t),n})}async executeTool(e,t,n={}){const o=f(this,s,"f").get(e);if(!o)throw h(`No tool registered with name "${e}".`,"NotFoundError");if(n.signal?.aborted)throw h("Tool execution was aborted.","AbortError");let r;if(null==t||""===t)r={};else if("string"==typeof t)try{r=JSON.parse(t)}catch(t){throw new TypeError(`executeTool("${e}"): input is not valid JSON: ${t.message}`)}else r=t;if(null===r||"object"!=typeof r||Array.isArray(r))throw new TypeError(`executeTool("${e}"): input must be a JSON object.`);const a=i(r,o.tool.inputSchema??m);if(a.length>0){const t=a.map(e=>`${e.path}: ${e.message}`).join("; ");throw new TypeError(`executeTool("${e}"): invalid input — ${t}`)}const l=new AbortController,u=n.signal,c=()=>l.abort(u?.reason);u?.addEventListener("abort",c,{once:!0});try{const t=await o.tool.execute(r,{signal:l.signal,toolName:e});if(u?.aborted)throw h("Tool execution was aborted.","AbortError");return function(e){return null==e?{content:[]}:"string"==typeof e?{content:[{type:"text",text:e}]}:"object"==typeof e&&Array.isArray(e.content)?e:{content:[{type:"text",text:JSON.stringify(e)}]}}(t)}catch(e){if(u?.aborted||e instanceof Error&&"AbortError"===e.name)throw h("Tool execution was aborted.","AbortError");return function(e){return{isError:!0,content:[{type:"text",text:e instanceof Error?`${e.name}: ${e.message}`:String(e)}]}}(e)}finally{u?.removeEventListener("abort",c)}}unregisterTool(e){const t=f(this,a,"m",c).call(this,e);return t&&f(this,a,"m",d).call(this),t}clearContext(){if(0!==f(this,s,"f").size){for(const e of[...f(this,s,"f").keys()])f(this,a,"m",c).call(this,e);f(this,a,"m",d).call(this)}}}function y(e,t){Object.defineProperty(e,"modelContext",{value:t,writable:!1,enumerable:!0,configurable:!0})}s=new WeakMap,l=new WeakMap,u=new WeakMap,a=new WeakSet,c=function(e,t,n=!1){const o=f(this,s,"f").get(e);return!!o&&((!t||o===t)&&(o.abortListener&&o.abortListener.signal.removeEventListener("abort",o.abortListener.listener),f(this,s,"f").delete(e),n&&f(this,a,"m",d).call(this),!0))},d=function(){f(this,u,"f")||(p(this,u,!0,"f"),queueMicrotask(()=>{p(this,u,!1,"f"),this.dispatchEvent(new Event("toolchange"))}))};const w=["AskAction","SearchAction","SubscribeAction","RegisterAction","BuyAction","OrderAction","AddAction","ScheduleAction","ReserveAction","RsvpAction","ApplyAction","QuoteAction","DownloadAction","ReviewAction","CommentAction","TrackAction","CommunicateAction","InteractAction"];const b="https://nxis.ai/ns#";function E(e,t,n){var o;return null!==(o=e[t])&&void 0!==o?o:e[n]}function x(e,t){return E(e,t,"https://schema.org/"+t)}function A(e,t){const n=x(e,t);return"string"==typeof n?n:null}function N(e,t,n){const o=E(e,t,n);return Array.isArray(o)?o:[]}function $(e){if(Array.isArray(e)){const t=[];for(const n of e)t.push(...$(n));return t}if(e&&"object"==typeof e){const t=e;if(Array.isArray(t["@graph"])){const e=[];for(const n of t["@graph"])e.push(...$(n));return e}return[t]}return[]}function T(e){var t;if(!e||"object"!=typeof e)return null;const n=e,o="string"==typeof n["@type"]?n["@type"]:null;if(!o)return null;if(!o.endsWith("Action")&&!function(e){return w.includes(e)}(o))return null;const r="string"==typeof n["@id"]?n["@id"]:null,i=A(n,"name"),a=function(e){var t,n;if(!e||"object"!=typeof e)return null;const o=e,r=null!==(n=null===(t=A(o,"httpMethod"))||void 0===t?void 0:t.toUpperCase())&&void 0!==n?n:null;if(!r)return null;const i={"@type":"EntryPoint",httpMethod:r},a=A(o,"encodingType");null!==a&&(i.encodingType=a);const s=A(o,"urlTemplate");null!==s&&(i.urlTemplate=s);const l=E(o,"nxis:targetKind",b+"targetKind");"selfPage"!==l&&"clientSide"!==l||(i["nxis:targetKind"]=l);const u=E(o,"nxis:pageUrl",b+"pageUrl");"string"==typeof u&&(i["nxis:pageUrl"]=u);const c=E(o,"nxis:jsHandled",b+"jsHandled");!0===c&&(i["nxis:jsHandled"]=!0);return i}(x(n,"target"));if(!r||!i||!a)return null;const s=N(n,"nxis:input",b+"input").map(L).filter(e=>null!==e),l=null!==(t=A(n,"description"))&&void 0!==t?t:function(e,t,n){const o=e.replace(/^.*[/#]/,"").replace(/Action$/,"").toLowerCase(),r=n.map(e=>e.valueName).join(", ");if(0===n.length)return`Trigger the ${o} action "${t}".`;return`Fill the ${o} form "${t}" with fields: ${r}.`}(o,i,s);return{"@context":n["@context"],"@type":o,"@id":r,name:i,description:l,target:a,input:s.length>0?s:void 0,"nxis:extractedAt":E(n,"nxis:extractedAt",b+"extractedAt")}}function L(e){if(!e||"object"!=typeof e)return null;const t=e,n=A(t,"valueName");if(!n)return null;const o=E(t,"nxis:valueType",b+"valueType"),r={"@type":"PropertyValueSpecification",valueName:n,"nxis:valueType":"string"==typeof o?o:"string"},i=A(t,"description");null!==i&&(r.description=i),!0===x(t,"valueRequired")&&(r.valueRequired=!0);const a=A(t,"defaultValue");null!==a&&(r.defaultValue=a);const s=e=>{const n=x(t,e);return"number"==typeof n?n:null},l=s("valueMinLength");null!==l&&(r.valueMinLength=l);const u=s("valueMaxLength");null!==u&&(r.valueMaxLength=u);const c=s("minValue");null!==c&&(r.minValue=c);const d=s("maxValue");null!==d&&(r.maxValue=d);const f=s("stepValue");null!==f&&(r.stepValue=f);const p=A(t,"valuePattern");null!==p&&(r.valuePattern=p),!0===x(t,"multipleValues")&&(r.multipleValues=!0),!0===x(t,"readonlyValue")&&(r.readonlyValue=!0);const m=N(t,"nxis:valueOption",b+"valueOption");if(m.length>0){const e=m.filter(e=>e&&"object"==typeof e&&null!==A(e,"value")).map(e=>{var t;const n=e;return{"@type":"nxis:ValueOption",value:A(n,"value"),name:null!==(t=A(n,"name"))&&void 0!==t?t:void 0}});e.length>0&&(r["nxis:valueOption"]=e)}return r}function O(e){switch(e){case"string":case"date":case"file":default:return"string";case"number":return"number";case"integer":return"integer";case"boolean":return"boolean"}}function S(e){const t={type:O(e["nxis:valueType"])},n=function(e){if("date"===e)return"date"}(e["nxis:valueType"]);if(n&&(t.format=n),e.description&&(t.description=e.description),void 0!==e.defaultValue&&(t.default=function(e,t){switch(t){case"number":case"integer":{const t=Number(e);return isNaN(t)?e:t}case"boolean":return"true"===e||"1"===e;default:return e}}(e.defaultValue,e["nxis:valueType"])),void 0!==e.valueMinLength&&(t.minLength=e.valueMinLength),void 0!==e.valueMaxLength&&(t.maxLength=e.valueMaxLength),e.valuePattern){const n=e.valuePattern,o=n.startsWith("^")&&n.endsWith("$")?n:`^${n}$`;t.pattern=o}void 0!==e.minValue&&(t.minimum=e.minValue),void 0!==e.maxValue&&(t.maximum=e.maxValue),void 0!==e.stepValue&&(t.multipleOf=e.stepValue),e.readonlyValue&&(t.readOnly=!0);const o=e["nxis:valueOption"];if(o&&o.length>0){t.enum=o.map(e=>e.value);if(o.some(e=>void 0!==e.name&&e.name!==e.value)){const e=o.filter(e=>e.name&&e.name!==e.value).map(e=>`${e.value} = "${e.name}"`).join(", "),n=t.description?`${t.description}. `:"";t.description=`${n}Values: ${e}`}}return t}function k(e){const t=Array.from(document.querySelectorAll("form"));if(0===t.length)return null;const n=function(e){return e.input?e.input.map(e=>e.valueName):[]}(e);let o;if(o=!e.target.urlTemplate?t:function(e,t,n){const o=function(e){const t=e.replace(/\{[^}]*\}/g,"");try{return new URL(t,window.location.href)}catch(e){return null}}(t);return e.filter(e=>{if((e.method||"GET").toUpperCase()!==n.toUpperCase())return!1;if(!o)return!0;const t=function(e){const t=e.getAttribute("action");if(!t||"#"===t||t.startsWith("#")||""===t)return window.location.href.split("#")[0].split("?")[0];if(t.startsWith("javascript:"))return window.location.href.split("#")[0].split("?")[0];try{return new URL(t,window.location.href).href}catch(e){return t}}(e);return function(e,t){let n;try{n=new URL(e,window.location.href)}catch(e){return!1}if(n.origin!==t.origin)return!1;const o=n.pathname.replace(/\/+$/,""),r=t.pathname.replace(/\/+$/,"");return""===r||(o===r||o.startsWith(r+"/")||r.startsWith(o+"/"))}(t,o)})}(t,e.target.urlTemplate,e.target.httpMethod),0===o.length&&(o=t),1===o.length)return o[0];const r=o.map(e=>({form:e,controlNames:j(e)})).filter(({controlNames:e})=>n.every(t=>e.has(t)));return 0===r.length?(console.warn(`[nxis/webmcp] No field-set match for action "${e.name}". Expected fields: [${n.join(", ")}]. Falling back to first candidate.`),o[0]):1===r.length?r[0].form:(r.sort((e,t)=>e.controlNames.size-t.controlNames.size),r[0].controlNames.size===r[1].controlNames.size?(console.warn(`[nxis/webmcp] Ambiguous form match for action "${e.name}". ${r.length} forms have identical field sets. Returning null.`),null):r[0].form)}function j(e){const t=new Set,n=e.elements;for(let e=0;e<n.length;e++){const o=n[e];o.name&&t.add(o.name)}return t}function C(e,t){var n;return(null!==(n=e.input)&&void 0!==n?n:[]).map(e=>function(e,t){var n;const o=t=>({valueName:e.valueName,pvs:e,strategy:t}),r=function(e,t){const n=[],o=e.elements;for(let e=0;e<o.length;e++){const r=o[e];r.name===t&&n.push(r)}return n}(t,e.valueName),i=null!==(n=r[0])&&void 0!==n?n:null;if(!i)return o({kind:"skip",reason:`No control found with name="${e.valueName}"`});if(i instanceof HTMLInputElement&&"radio"===i.type){const t=r.filter(e=>e instanceof HTMLInputElement&&"radio"===e.type&&!e.disabled);return 0===t.length?o({kind:"skip",reason:`Radio group "${e.valueName}" has no enabled options`}):o({kind:"radio",name:e.valueName,elements:t})}if(i instanceof HTMLInputElement&&"checkbox"===i.type){const t=r.filter(e=>e instanceof HTMLInputElement&&"checkbox"===e.type&&!e.disabled);return 0===t.length?o({kind:"skip",reason:`Checkbox "${e.valueName}" is disabled`}):t.length>1?o({kind:"checkboxGroup",name:e.valueName,elements:t}):o({kind:"checked",element:t[0]})}if(!0===i.readOnly||null!==i.getAttribute("readonly"))return o({kind:"skip",reason:`Control "${e.valueName}" is readonly in the DOM`});if(i.disabled)return o({kind:"skip",reason:`Control "${e.valueName}" is disabled`});if(i instanceof HTMLSelectElement){const e=[];for(let t=0;t<i.options.length;t++){const n=i.options[t];n.value&&e.push(n.value)}return o(i.multiple?{kind:"multiSelect",element:i,allowedValues:e}:{kind:"select",element:i,allowedValues:e})}if(i instanceof HTMLTextAreaElement)return o({kind:"value",element:i});if(i instanceof HTMLInputElement)return o({kind:"value",element:i});return o({kind:"skip",reason:`Unsupported control type for "${e.valueName}"`})}(e,t))}async function I(e,t){var n,o;const r=function(e){const t=e.target["nxis:pageUrl"];if(!t)return null;try{const n=new URL(t),o=new URL(window.location.href);if(n.origin!==o.origin||n.pathname!==o.pathname)return`Action "${e.name}" was extracted from ${n.origin}${n.pathname} but the current page is ${o.origin}${o.pathname}. The form may have moved or changed.`}catch(e){return null}return null}(e),i=k(e);if(!i){const t=`Form not found for action "${e.name}". The page may have changed since the tool was registered.`,n={success:!1,submitted:!1,message:r?`Warning: ${r} ${t}`:t,filled:[],skipped:[]};return r&&(n.stale=!0),JSON.stringify(n)}const a=C(e,i),s=null!==(n=e.input)&&void 0!==n?n:[],l=[],u=[];let c=!1;for(const e of s)!e.valueRequired||void 0!==t[e.valueName]&&null!==t[e.valueName]||(c=!0,u.push({field:e.valueName,reason:`Required field '${e.valueName}' was not provided. Expected type: ${e["nxis:valueType"]}.`}));for(const e of a){const n=t[e.valueName];if(null==n){u.some(t=>t.field===e.valueName)||u.push({field:e.valueName,reason:"No value provided (optional field)."});continue}const o=R(e,n);!1===o.ok?u.push({field:e.valueName,reason:o.reason}):l.push(e.valueName)}await new Promise(e=>setTimeout(e,0));for(const e of a)if("value"===e.strategy.kind&&l.includes(e.valueName)){const n=e.strategy.element,r=_(null!==(o=t[e.valueName])&&void 0!==o?o:"");n.value!==r&&(u.push({field:e.valueName,reason:`Value was set to "${r}" but the DOM now shows "${n.value}". A framework may have reverted it.`}),l.splice(l.indexOf(e.valueName),1))}const d=l.length>0&&!c;let f=!1;d&&(f=function(e){try{return"function"==typeof e.requestSubmit?e.requestSubmit():e.submit(),!0}catch(e){return console.warn("[nxis/webmcp] Form submission failed:",e),!1}}(i));const p={success:d,submitted:f,message:M(l,u,f,r),filled:l,skipped:u};return r&&(p.stale=!0),JSON.stringify(p)}function M(e,t,n,o){const r=[];if(o&&r.push(`Warning: ${o}`),0===e.length&&0===t.length)return r.push("No fields were filled. Verify field names match the input schema."),r.join(" ");if(e.length>0&&r.push(`Filled ${e.length} field(s): ${e.join(", ")}.`),t.length>0){const e=t.map(e=>`${e.field} (${e.reason})`).join("; ");r.push(`Skipped ${t.length}: ${e}`)}return n?r.push("Form submitted."):e.length>0&&r.push("Form was NOT submitted due to missing required fields or fill errors."),r.join(" ")}function R(e,t){const{strategy:n}=e;switch(n.kind){case"skip":return{ok:!1,reason:n.reason};case"value":return function(e,t){var n;const o=null===(n=Object.getOwnPropertyDescriptor(e instanceof HTMLTextAreaElement?HTMLTextAreaElement.prototype:HTMLInputElement.prototype,"value"))||void 0===n?void 0:n.set;o?o.call(e,t):e.value=t;return e.dispatchEvent(new Event("input",{bubbles:!0})),e.dispatchEvent(new Event("change",{bubbles:!0})),{ok:!0}}(n.element,_(t));case"checked":return function(e,t){return e.checked=function(e){if("boolean"==typeof e)return e;if("number"==typeof e)return 0!==e;if("string"==typeof e){const t=e.trim().toLowerCase();return""!==t&&"false"!==t&&"0"!==t&&"off"!==t&&"no"!==t}return Boolean(e)}(t),e.dispatchEvent(new Event("change",{bubbles:!0})),{ok:!0}}(n.element,t);case"radio":return function(e,t){var n,o;const r=String(t),i=null!==(o=null!==(n=e.find(e=>e.value===r))&&void 0!==n?n:e.find(e=>e.value.toLowerCase()===r.toLowerCase()))&&void 0!==o?o:e.find(e=>function(e){var t;if(e.labels&&e.labels.length>0)return(null!==(t=e.labels[0].textContent)&&void 0!==t?t:"").trim();return e.value}(e).toLowerCase()===r.toLowerCase());if(!i){const t=e.map(e=>e.value).join(", ");return{ok:!1,reason:`Value "${r}" is not an allowed option for radio "${e[0].name}". Allowed: [${t}].`}}return i.checked=!0,i.dispatchEvent(new Event("input",{bubbles:!0})),i.dispatchEvent(new Event("change",{bubbles:!0})),{ok:!0}}(n.elements,t);case"checkboxGroup":return function(e,t){const n=(Array.isArray(t)?t:[t]).map(e=>String(e)),o=n.map(e=>e.toLowerCase());let r=!1;for(const t of e){const e=n.includes(t.value)||o.includes(t.value.toLowerCase());t.checked=e,e&&(r=!0),t.dispatchEvent(new Event("change",{bubbles:!0}))}if(!r){const t=e.map(e=>e.value).join(", ");return{ok:!1,reason:`None of [${n.join(", ")}] match checkbox group "${e[0].name}". Allowed: [${t}].`}}return{ok:!0}}(n.elements,t);case"select":return function(e,t,n){const o=U(e,t,n);if(null===o)return{ok:!1,reason:`Value "${t}" is not an allowed option for "${e.name}". Allowed: [${n.join(", ")}].`};return e.value=o,e.dispatchEvent(new Event("input",{bubbles:!0})),e.dispatchEvent(new Event("change",{bubbles:!0})),{ok:!0}}(n.element,String(t),n.allowedValues);case"multiSelect":return function(e,t,n){const o=(Array.isArray(t)?t:[t]).map(e=>String(e)),r=new Set,i=[];for(const t of o){const o=U(e,t,n);null===o?i.push(t):r.add(o)}if(0===r.size)return{ok:!1,reason:`None of [${o.join(", ")}] are allowed options for "${e.name}". Allowed: [${n.join(", ")}].`};for(const t of Array.from(e.options))t.selected=r.has(t.value);if(e.dispatchEvent(new Event("input",{bubbles:!0})),e.dispatchEvent(new Event("change",{bubbles:!0})),i.length>0)return{ok:!1,reason:`Selected [${Array.from(r).join(", ")}] but [${i.join(", ")}] are not allowed options for "${e.name}". Allowed: [${n.join(", ")}].`};return{ok:!0}}(n.element,t,n.allowedValues);default:return{ok:!1,reason:`Unsupported fill strategy for field "${e.valueName}".`}}}function _(e){return Array.isArray(e)?e.map(e=>String(e)).join(","):String(e)}function U(e,t,n){if(n.includes(t))return t;const o=n.find(e=>e.toLowerCase()===t.toLowerCase());if(o)return o;for(const n of Array.from(e.options))if(n.text.toLowerCase()===t.toLowerCase())return n.value;return null}function V(e){var t;const n=!1!==(null==e?void 0:e.observe),o=null!==(t=null==e?void 0:e.doc)&&void 0!==t?t:"undefined"!=typeof document?document:void 0;if(!o)return console.warn("[nxis/webmcp] No document available (not running in a browser). Tools will not be registered."),()=>{};!function(e={}){const{force:t=!1,installNavigatorAlias:n=!0}=e,o="undefined"!=typeof document&&document.modelContext||"undefined"!=typeof navigator&&navigator.modelContext||void 0;if(o&&!t)return o;const r=new g;"undefined"!=typeof document&&y(document,r),n&&"undefined"!=typeof navigator&&y(navigator,r)}();const r=function(e){var t,n;const o=null!==(n=null===(t=e.defaultView)||void 0===t?void 0:t.navigator)&&void 0!==n?n:"undefined"!=typeof navigator?navigator:void 0;return e.modelContext||(null==o?void 0:o.modelContext)||null}(o);if(!r)return console.warn("[nxis/webmcp] WebMCP API not available — document.modelContext is undefined. Tools will not be registered."),()=>{};const i=new AbortController;(null==e?void 0:e.signal)&&(e.signal.aborted?i.abort():e.signal.addEventListener("abort",()=>i.abort()));const a={ids:new Set,names:new Set};P(o,r,i,a);let s=null;return n&&(s=function(e,t,n,o){const r=new MutationObserver(r=>{(function(e){for(const t of e)for(const e of Array.from(t.addedNodes)){if(H(e))return!0;if(e instanceof Element&&e.querySelector('script[type="application/ld+json"]'))return!0}return!1})(r)&&P(e,t,n,o)});return n.signal.addEventListener("abort",()=>r.disconnect()),r.observe(e.documentElement,{childList:!0,subtree:!0}),r}(o,r,i,a)),()=>{i.abort(),s&&(s.disconnect(),s=null)}}function P(e,t,n,o){const r=function(e=("undefined"!=typeof document?document:void 0)){const t=[];if(!e)return t;const n=e.querySelectorAll('script[type="application/ld+json"]');for(const e of Array.from(n)){const n=e.textContent;if(!n)continue;let o;try{o=JSON.parse(n)}catch(e){continue}const r=$(o);for(const e of r){const n=T(e);n&&t.push(n)}}return t}(e);let i=0;for(const e of r)if(!o.ids.has(e["@id"]))try{D(e,t,n,o),o.ids.add(e["@id"]),i++}catch(t){console.warn(`[nxis/webmcp] Failed to register tool for action "${e.name}":`,t)}i>0&&console.info(`[nxis/webmcp] Registered ${i} tool(s) (${o.ids.size} total) from ${r.length} action(s).`)}function D(e,t,n,o){const r=function(e){var t;const n={},o=[],r=null!==(t=e.input)&&void 0!==t?t:[];for(const e of r){const t=S(e);if(e.multipleValues){const o={type:"array",items:t};void 0!==e.valueMinLength&&(o.minItems=e.valueMinLength,delete t.minLength),void 0!==e.valueMaxLength&&(o.maxItems=e.valueMaxLength,delete t.maxLength),e.description&&(o.description=e.description,delete t.description),n[e.valueName]=o}else n[e.valueName]=t;e.valueRequired&&o.push(e.valueName)}const i={type:"object",properties:n};return o.length>0&&(i.required=o),i}(e),i=function(e,t){if(!t.has(e))return e;for(let n=2;;n++){const o=`_${n}`,r=e.slice(0,64-o.length)+o;if(!t.has(r))return r}}(function(e){return e.toLowerCase().replace(/[\s-]+/g,"_").replace(/[^a-z0-9_]/g,"_").replace(/_+/g,"_").replace(/^_|_$/g,"").slice(0,64)||"unnamed_action"}(e.name),o.names);t.registerTool({name:i,description:e.description,inputSchema:r,annotations:{readOnlyHint:!1,untrustedContentHint:!0},execute:async t=>I(e,t)},{signal:n.signal}),o.names.add(i)}function H(e){return e instanceof HTMLScriptElement&&"application/ld+json"===e.type}function q(t){t instanceof e?console.warn(JSON.parse(t.message).message):console.error(`Unable to retrieve structured data for ${window.location.href}`)}!function(){var t,o;const r=window.__NXIS_CONFIG__,i=null!==(o=null===(t=null==r?void 0:r.webmcp)||void 0===t?void 0:t.mode)&&void 0!==o?o:"browser";if("ssr"===i)return void V();const a=process.env.NXIS_API_HOST,s=new Headers,l=new URL(`${a}/v1/nxis:inject`);l.search=function(e){var t,n;const o=new URLSearchParams;return(null===(t=e.organization_id)||void 0===t?void 0:t.value)&&o.append("organization_id",e.organization_id.value),(null===(n=e.site_id)||void 0===n?void 0:n.value)&&o.append("site_id",e.site_id.value),o.append("uri",e.uri.href),e.referrer&&o.append("referrer",e.referrer),o}({organization_id:{value:null==r?void 0:r.org_id},site_id:{value:null==r?void 0:r.site_id},uri:new URL(window.location.href),referrer:document.referrer}).toString(),(null==r?void 0:r.sub_id)&&s.set("X-NXIS-SUBSCRIPTION",r.sub_id),s.set("Content-Type","application/json"),s.set("User-Agent",navigator.userAgent),fetch(`${l}`,{headers:s}).then(t=>async function(t,o){const r=null!=o?o:"unknown";if(200===t.status){const n=await t.json();if((null==n?void 0:n.data)&&Object.keys(n.data).length>0)return n;throw new e(JSON.stringify({message:`No Nxis resource found for ${r}`}))}const i=await async function(e){try{return await e.json()}catch(e){return null}}(t);if(void 0!==(null==i?void 0:i.code)&&(null==i?void 0:i.message))throw n.fromResponse(t.status,i);switch(t.status){case 500:throw new n(13,500,"An internal server error occurred, please contact technical support.");case 502:throw new n(13,502,"An internal server error occurred, please contact technical support.");case 503:throw new n(8,503,"Service is temporarily unavailable, please try again later.");default:throw new n(13,t.status,`Unexpected response status: ${t.status}`)}}(t,window.location.href)).then(e=>{!function(e){if(e.data&&Object.keys(e.data).length>0){const t=document.createComment("Nxis.ai"),n=document.createComment("End Nxis.ai"),o=document.createElement("script");o.setAttribute("type","application/ld+json"),o.textContent=JSON.stringify(e.data),document.head.appendChild(o),o.before(t),o.after(n)}}(e),"browser"===i&&V()}).catch(q)}();
|
|
1
|
+
!function(){const e={NXIS_API_HOST:"https://proxy.nxis.ai"};try{if(process)return process.env=Object.assign({},process.env),void Object.assign(process.env,e)}catch(e){}globalThis.process={env:e}}();class e extends Error{constructor(t){super(t),Object.setPrototypeOf(this,e.prototype)}}var t;!function(e){e[e.OK=0]="OK",e[e.INVALID_ARGUMENT=3]="INVALID_ARGUMENT",e[e.NOT_FOUND=5]="NOT_FOUND",e[e.PERMISSION_DENIED=7]="PERMISSION_DENIED",e[e.RESOURCE_EXHAUSTED=8]="RESOURCE_EXHAUSTED",e[e.INTERNAL=13]="INTERNAL",e[e.UNAUTHENTICATED=16]="UNAUTHENTICATED"}(t||(t={})),t.OK,t.INVALID_ARGUMENT,t.NOT_FOUND,t.PERMISSION_DENIED,t.RESOURCE_EXHAUSTED,t.INTERNAL,t.UNAUTHENTICATED;class n extends Error{constructor(e,t,o){super(o),this.code=e,this.httpStatus=t,this.name="ProxyError",Object.setPrototypeOf(this,n.prototype)}get isRetryable(){return this.code===t.RESOURCE_EXHAUSTED||this.code===t.INTERNAL}get isAuthError(){return this.code===t.UNAUTHENTICATED||this.code===t.PERMISSION_DENIED}static fromResponse(e,t){return new n(t.code,e,t.message)}}function o(e){return null===e?"null":Array.isArray(e)?"array":typeof e}function r(e,t){if(e===t)return!0;if(o(e)!==o(t))return!1;if(Array.isArray(e)&&Array.isArray(t))return e.length===t.length&&e.every((e,n)=>r(e,t[n]));if("object"===o(e)){const n=e,o=t,i=Object.keys(n);return i.length===Object.keys(o).length&&i.every(e=>r(n[e],o[e]))}return!1}function i(e,t,n="$"){if(!t||"object"!=typeof t)return[];const a=[];if(void 0===t.const||r(e,t.const)||a.push({path:n,message:`must equal const ${JSON.stringify(t.const)}`}),t.enum&&!t.enum.some(t=>r(e,t))&&a.push({path:n,message:`must be one of ${JSON.stringify(t.enum)}`}),void 0!==t.type){const r=Array.isArray(t.type)?t.type:[t.type];if(!r.some(t=>function(e,t){switch(t){case"object":return"object"===o(e);case"array":return Array.isArray(e);case"string":return"string"==typeof e;case"number":return"number"==typeof e&&Number.isFinite(e);case"integer":return"number"==typeof e&&Number.isInteger(e);case"boolean":return"boolean"==typeof e;case"null":return null===e;default:return!0}}(e,t)))return a.push({path:n,message:`expected type ${r.join(" | ")}, got ${o(e)}`}),a}if("string"==typeof e&&(void 0!==t.minLength&&e.length<t.minLength&&a.push({path:n,message:`must be at least ${t.minLength} characters`}),void 0!==t.maxLength&&e.length>t.maxLength&&a.push({path:n,message:`must be at most ${t.maxLength} characters`}),void 0!==t.pattern)){let o=null;try{o=new RegExp(t.pattern,"u")}catch{}o&&!o.test(e)&&a.push({path:n,message:`must match pattern ${t.pattern}`})}if("number"==typeof e&&(void 0!==t.minimum&&e<t.minimum&&a.push({path:n,message:`must be >= ${t.minimum}`}),void 0!==t.maximum&&e>t.maximum&&a.push({path:n,message:`must be <= ${t.maximum}`})),Array.isArray(e)&&(void 0!==t.minItems&&e.length<t.minItems&&a.push({path:n,message:`must have at least ${t.minItems} items`}),void 0!==t.maxItems&&e.length>t.maxItems&&a.push({path:n,message:`must have at most ${t.maxItems} items`}),t.items&&e.forEach((e,o)=>{a.push(...i(e,t.items,`${n}[${o}]`))})),"object"===o(e)&&!Array.isArray(e)&&null!==e){const o=e;for(const e of t.required??[])e in o||a.push({path:n,message:`missing required property "${e}"`});const r=t.properties??{};for(const[e,t]of Object.entries(r))e in o&&a.push(...i(o[e],t,`${n}.${e}`));if(!1===t.additionalProperties)for(const e of Object.keys(o))e in r||a.push({path:n,message:`unexpected property "${e}"`});else if(t.additionalProperties&&"object"==typeof t.additionalProperties)for(const e of Object.keys(o))e in r||a.push(...i(o[e],t.additionalProperties,`${n}.${e}`))}if(t.allOf)for(const o of t.allOf)a.push(...i(e,o,n));if(t.anyOf&&t.anyOf.length>0){t.anyOf.some(t=>0===i(e,t,n).length)||a.push({path:n,message:"does not match any schema in anyOf"})}if(t.oneOf&&t.oneOf.length>0){const o=t.oneOf.filter(t=>0===i(e,t,n).length).length;1!==o&&a.push({path:n,message:`must match exactly one schema in oneOf (matched ${o})`})}return a}var a,s,l,u,c,d,f=function(e,t,n,o){if("a"===n&&!o)throw new TypeError("Private accessor was defined without a getter");if("function"==typeof t?e!==t||!o:!t.has(e))throw new TypeError("Cannot read private member from an object whose class did not declare it");return"m"===n?o:"a"===n?o.call(e):o?o.value:t.get(e)},p=function(e,t,n,o,r){if("m"===o)throw new TypeError("Private method is not writable");if("a"===o&&!r)throw new TypeError("Private accessor was defined without a setter");if("function"==typeof t?e!==t||!r:!t.has(e))throw new TypeError("Cannot write private member to an object whose class did not declare it");return"a"===o?r.call(e,n):r?r.value=n:t.set(e,n),n};const m={type:"object"};function h(e,t){if("function"==typeof DOMException)return new DOMException(e,t);const n=new Error(e);return n.name=t,n}function v(e){if(!e||"object"!=typeof e)throw new TypeError("Tool descriptor must be an object.");if("string"!=typeof e.name||0===e.name.length)throw new TypeError("Tool descriptor requires a non-empty string 'name'.");if("string"!=typeof e.description)throw new TypeError(`Tool "${e.name}" requires a string 'description'.`);if("function"!=typeof e.execute)throw new TypeError(`Tool "${e.name}" requires an 'execute' function.`);if(void 0!==e.inputSchema&&"object"!=typeof e.inputSchema)throw new TypeError(`Tool "${e.name}": 'inputSchema' must be an object.`)}class g extends EventTarget{constructor(){super(...arguments),a.add(this),s.set(this,new Map),l.set(this,null),u.set(this,!1)}get ontoolchange(){return f(this,l,"f")}set ontoolchange(e){f(this,l,"f")&&this.removeEventListener("toolchange",f(this,l,"f")),p(this,l,"function"==typeof e?e:null,"f"),f(this,l,"f")&&this.addEventListener("toolchange",f(this,l,"f"))}registerTool(e,t={}){v(e);const{signal:n,exposedTo:o}=t;if(n?.aborted)return;f(this,a,"m",c).call(this,e.name);const r={tool:e,exposedTo:o?[...o]:void 0,pageLevel:!1};if(n){const t=()=>f(this,a,"m",c).call(this,e.name,r,!0);n.addEventListener("abort",t,{once:!0}),r.abortListener={signal:n,listener:t}}f(this,s,"f").set(e.name,r),f(this,a,"m",d).call(this)}provideContext(e={}){const t=e.tools??[];for(const e of t)v(e);if(new Set(t.map(e=>e.name)).size!==t.length)throw new TypeError("provideContext(): duplicate tool names in 'tools'.");for(const[e,t]of f(this,s,"f"))t.pageLevel&&f(this,a,"m",c).call(this,e);for(const e of t){if(f(this,s,"f").has(e.name))throw h(`provideContext(): tool "${e.name}" is already registered via registerTool().`,"InvalidStateError");f(this,s,"f").set(e.name,{tool:e,exposedTo:void 0,pageLevel:!0})}f(this,a,"m",d).call(this)}async getTools(e={}){e.fromOrigins;const t="undefined"!=typeof location?location.origin:void 0;return[...f(this,s,"f").values()].map(({tool:e})=>{const n={name:e.name,description:e.description,inputSchema:structuredClone(e.inputSchema??m)};return e.annotations&&(n.annotations=structuredClone(e.annotations)),t&&(n.origin=t),n})}async executeTool(e,t,n={}){const o=f(this,s,"f").get(e);if(!o)throw h(`No tool registered with name "${e}".`,"NotFoundError");if(n.signal?.aborted)throw h("Tool execution was aborted.","AbortError");let r;if(null==t||""===t)r={};else if("string"==typeof t)try{r=JSON.parse(t)}catch(t){throw new TypeError(`executeTool("${e}"): input is not valid JSON: ${t.message}`)}else r=t;if(null===r||"object"!=typeof r||Array.isArray(r))throw new TypeError(`executeTool("${e}"): input must be a JSON object.`);const a=i(r,o.tool.inputSchema??m);if(a.length>0){const t=a.map(e=>`${e.path}: ${e.message}`).join("; ");throw new TypeError(`executeTool("${e}"): invalid input — ${t}`)}const l=new AbortController,u=n.signal,c=()=>l.abort(u?.reason);u?.addEventListener("abort",c,{once:!0});try{const t=await o.tool.execute(r,{signal:l.signal,toolName:e});if(u?.aborted)throw h("Tool execution was aborted.","AbortError");return function(e){return null==e?{content:[]}:"string"==typeof e?{content:[{type:"text",text:e}]}:"object"==typeof e&&Array.isArray(e.content)?e:{content:[{type:"text",text:JSON.stringify(e)}]}}(t)}catch(e){if(u?.aborted||e instanceof Error&&"AbortError"===e.name)throw h("Tool execution was aborted.","AbortError");return function(e){return{isError:!0,content:[{type:"text",text:e instanceof Error?`${e.name}: ${e.message}`:String(e)}]}}(e)}finally{u?.removeEventListener("abort",c)}}unregisterTool(e){const t=f(this,a,"m",c).call(this,e);return t&&f(this,a,"m",d).call(this),t}clearContext(){if(0!==f(this,s,"f").size){for(const e of[...f(this,s,"f").keys()])f(this,a,"m",c).call(this,e);f(this,a,"m",d).call(this)}}}function y(e,t){Object.defineProperty(e,"modelContext",{value:t,writable:!1,enumerable:!0,configurable:!0})}s=new WeakMap,l=new WeakMap,u=new WeakMap,a=new WeakSet,c=function(e,t,n=!1){const o=f(this,s,"f").get(e);return!!o&&((!t||o===t)&&(o.abortListener&&o.abortListener.signal.removeEventListener("abort",o.abortListener.listener),f(this,s,"f").delete(e),n&&f(this,a,"m",d).call(this),!0))},d=function(){f(this,u,"f")||(p(this,u,!0,"f"),queueMicrotask(()=>{p(this,u,!1,"f"),this.dispatchEvent(new Event("toolchange"))}))};const w=["AskAction","SearchAction","SubscribeAction","RegisterAction","BuyAction","OrderAction","AddAction","ScheduleAction","ReserveAction","RsvpAction","ApplyAction","QuoteAction","DownloadAction","ReviewAction","CommentAction","TrackAction","CommunicateAction","InteractAction"];const b="https://nxis.ai/ns#";function E(e,t,n){var o;return null!==(o=e[t])&&void 0!==o?o:e[n]}function x(e,t){return E(e,t,"https://schema.org/"+t)}function A(e,t){const n=x(e,t);return"string"==typeof n?n:null}function N(e,t,n){const o=E(e,t,n);return Array.isArray(o)?o:[]}function $(e){if(Array.isArray(e)){const t=[];for(const n of e)t.push(...$(n));return t}if(e&&"object"==typeof e){const t=e;if(Array.isArray(t["@graph"])){const e=[];for(const n of t["@graph"])e.push(...$(n));return e}return[t]}return[]}function T(e){var t;if(!e||"object"!=typeof e)return null;const n=e,o="string"==typeof n["@type"]?n["@type"]:null;if(!o)return null;if(!o.endsWith("Action")&&!function(e){return w.includes(e)}(o))return null;const r="string"==typeof n["@id"]?n["@id"]:null,i=A(n,"name"),a=function(e){var t,n;if(!e||"object"!=typeof e)return null;const o=e,r=null!==(n=null===(t=A(o,"httpMethod"))||void 0===t?void 0:t.toUpperCase())&&void 0!==n?n:null;if(!r)return null;const i={"@type":"EntryPoint",httpMethod:r},a=A(o,"encodingType");null!==a&&(i.encodingType=a);const s=A(o,"urlTemplate");null!==s&&(i.urlTemplate=s);const l=E(o,"nxis:targetKind",b+"targetKind");"selfPage"!==l&&"clientSide"!==l||(i["nxis:targetKind"]=l);const u=E(o,"nxis:pageUrl",b+"pageUrl");"string"==typeof u&&(i["nxis:pageUrl"]=u);const c=E(o,"nxis:jsHandled",b+"jsHandled");!0===c&&(i["nxis:jsHandled"]=!0);return i}(x(n,"target"));if(!r||!i||!a)return null;const s=N(n,"nxis:input",b+"input").map(L).filter(e=>null!==e),l=null!==(t=A(n,"description"))&&void 0!==t?t:function(e,t,n){const o=e.replace(/^.*[/#]/,"").replace(/Action$/,"").toLowerCase(),r=n.map(e=>e.valueName).join(", ");if(0===n.length)return`Trigger the ${o} action "${t}".`;return`Fill the ${o} form "${t}" with fields: ${r}.`}(o,i,s);return{"@context":n["@context"],"@type":o,"@id":r,name:i,description:l,target:a,input:s.length>0?s:void 0,"nxis:extractedAt":E(n,"nxis:extractedAt",b+"extractedAt")}}function L(e){if(!e||"object"!=typeof e)return null;const t=e,n=A(t,"valueName");if(!n)return null;const o=E(t,"nxis:valueType",b+"valueType"),r={"@type":"PropertyValueSpecification",valueName:n,"nxis:valueType":"string"==typeof o?o:"string"},i=A(t,"description");null!==i&&(r.description=i),!0===x(t,"valueRequired")&&(r.valueRequired=!0);const a=A(t,"defaultValue");null!==a&&(r.defaultValue=a);const s=e=>{const n=x(t,e);return"number"==typeof n?n:null},l=s("valueMinLength");null!==l&&(r.valueMinLength=l);const u=s("valueMaxLength");null!==u&&(r.valueMaxLength=u);const c=s("minValue");null!==c&&(r.minValue=c);const d=s("maxValue");null!==d&&(r.maxValue=d);const f=s("stepValue");null!==f&&(r.stepValue=f);const p=A(t,"valuePattern");null!==p&&(r.valuePattern=p),!0===x(t,"multipleValues")&&(r.multipleValues=!0),!0===x(t,"readonlyValue")&&(r.readonlyValue=!0);const m=N(t,"nxis:valueOption",b+"valueOption");if(m.length>0){const e=m.filter(e=>e&&"object"==typeof e&&null!==A(e,"value")).map(e=>{var t;const n=e;return{"@type":"nxis:ValueOption",value:A(n,"value"),name:null!==(t=A(n,"name"))&&void 0!==t?t:void 0}});e.length>0&&(r["nxis:valueOption"]=e)}return r}function O(e){switch(e){case"string":case"date":case"file":default:return"string";case"number":return"number";case"integer":return"integer";case"boolean":return"boolean"}}function S(e){const t={type:O(e["nxis:valueType"])},n=function(e){if("date"===e)return"date"}(e["nxis:valueType"]);if(n&&(t.format=n),e.description&&(t.description=e.description),void 0!==e.defaultValue&&(t.default=function(e,t){switch(t){case"number":case"integer":{const t=Number(e);return isNaN(t)?e:t}case"boolean":return"true"===e||"1"===e;default:return e}}(e.defaultValue,e["nxis:valueType"])),void 0!==e.valueMinLength&&(t.minLength=e.valueMinLength),void 0!==e.valueMaxLength&&(t.maxLength=e.valueMaxLength),e.valuePattern){const n=e.valuePattern,o=n.startsWith("^")&&n.endsWith("$")?n:`^${n}$`;t.pattern=o}void 0!==e.minValue&&(t.minimum=e.minValue),void 0!==e.maxValue&&(t.maximum=e.maxValue),void 0!==e.stepValue&&(t.multipleOf=e.stepValue),e.readonlyValue&&(t.readOnly=!0);const o=e["nxis:valueOption"];if(o&&o.length>0){t.enum=o.map(e=>e.value);if(o.some(e=>void 0!==e.name&&e.name!==e.value)){const e=o.filter(e=>e.name&&e.name!==e.value).map(e=>`${e.value} = "${e.name}"`).join(", "),n=t.description?`${t.description}. `:"";t.description=`${n}Values: ${e}`}}return t}function k(e){const t=Array.from(document.querySelectorAll("form"));if(0===t.length)return null;const n=function(e){return e.input?e.input.map(e=>e.valueName):[]}(e);let o;if(o=!e.target.urlTemplate?t:function(e,t,n){const o=function(e){const t=e.replace(/\{[^}]*\}/g,"");try{return new URL(t,window.location.href)}catch(e){return null}}(t);return e.filter(e=>{if((e.method||"GET").toUpperCase()!==n.toUpperCase())return!1;if(!o)return!0;const t=function(e){const t=e.getAttribute("action");if(!t||"#"===t||t.startsWith("#")||""===t)return window.location.href.split("#")[0].split("?")[0];if(t.startsWith("javascript:"))return window.location.href.split("#")[0].split("?")[0];try{return new URL(t,window.location.href).href}catch(e){return t}}(e);return function(e,t){let n;try{n=new URL(e,window.location.href)}catch(e){return!1}if(n.origin!==t.origin)return!1;const o=n.pathname.replace(/\/+$/,""),r=t.pathname.replace(/\/+$/,"");return""===r||(o===r||o.startsWith(r+"/")||r.startsWith(o+"/"))}(t,o)})}(t,e.target.urlTemplate,e.target.httpMethod),0===o.length&&(o=t),1===o.length)return o[0];const r=o.map(e=>({form:e,controlNames:j(e)})).filter(({controlNames:e})=>n.every(t=>e.has(t)));return 0===r.length?(console.warn(`[nxis/webmcp] No field-set match for action "${e.name}". Expected fields: [${n.join(", ")}]. Falling back to first candidate.`),o[0]):1===r.length?r[0].form:(r.sort((e,t)=>e.controlNames.size-t.controlNames.size),r[0].controlNames.size===r[1].controlNames.size?(console.warn(`[nxis/webmcp] Ambiguous form match for action "${e.name}". ${r.length} forms have identical field sets. Returning null.`),null):r[0].form)}function j(e){const t=new Set,n=e.elements;for(let e=0;e<n.length;e++){const o=n[e];o.name&&t.add(o.name)}return t}function C(e,t){var n;return(null!==(n=e.input)&&void 0!==n?n:[]).map(e=>function(e,t){var n;const o=t=>({valueName:e.valueName,pvs:e,strategy:t}),r=function(e,t){const n=[],o=e.elements;for(let e=0;e<o.length;e++){const r=o[e];r.name===t&&n.push(r)}return n}(t,e.valueName),i=null!==(n=r[0])&&void 0!==n?n:null;if(!i)return o({kind:"skip",reason:`No control found with name="${e.valueName}"`});if(i instanceof HTMLInputElement&&"radio"===i.type){const t=r.filter(e=>e instanceof HTMLInputElement&&"radio"===e.type&&!e.disabled);return 0===t.length?o({kind:"skip",reason:`Radio group "${e.valueName}" has no enabled options`}):o({kind:"radio",name:e.valueName,elements:t})}if(i instanceof HTMLInputElement&&"checkbox"===i.type){const t=r.filter(e=>e instanceof HTMLInputElement&&"checkbox"===e.type&&!e.disabled);return 0===t.length?o({kind:"skip",reason:`Checkbox "${e.valueName}" is disabled`}):t.length>1?o({kind:"checkboxGroup",name:e.valueName,elements:t}):o({kind:"checked",element:t[0]})}if(!0===i.readOnly||null!==i.getAttribute("readonly"))return o({kind:"skip",reason:`Control "${e.valueName}" is readonly in the DOM`});if(i.disabled)return o({kind:"skip",reason:`Control "${e.valueName}" is disabled`});if(i instanceof HTMLSelectElement){const e=[];for(let t=0;t<i.options.length;t++){const n=i.options[t];n.value&&e.push(n.value)}return o(i.multiple?{kind:"multiSelect",element:i,allowedValues:e}:{kind:"select",element:i,allowedValues:e})}if(i instanceof HTMLTextAreaElement)return o({kind:"value",element:i});if(i instanceof HTMLInputElement)return o({kind:"value",element:i});return o({kind:"skip",reason:`Unsupported control type for "${e.valueName}"`})}(e,t))}async function I(e,t){var n,o;const r=function(e){const t=e.target["nxis:pageUrl"];if(!t)return null;try{const n=new URL(t),o=new URL(window.location.href);if(n.origin!==o.origin||n.pathname!==o.pathname)return`Action "${e.name}" was extracted from ${n.origin}${n.pathname} but the current page is ${o.origin}${o.pathname}. The form may have moved or changed.`}catch(e){return null}return null}(e),i=k(e);if(!i){const t=`Form not found for action "${e.name}". The page may have changed since the tool was registered.`,n={success:!1,submitted:!1,message:r?`Warning: ${r} ${t}`:t,filled:[],skipped:[]};return r&&(n.stale=!0),JSON.stringify(n)}const a=C(e,i),s=null!==(n=e.input)&&void 0!==n?n:[],l=[],u=[];let c=!1;for(const e of s)!e.valueRequired||void 0!==t[e.valueName]&&null!==t[e.valueName]||(c=!0,u.push({field:e.valueName,reason:`Required field '${e.valueName}' was not provided. Expected type: ${e["nxis:valueType"]}.`}));for(const e of a){const n=t[e.valueName];if(null==n){u.some(t=>t.field===e.valueName)||u.push({field:e.valueName,reason:"No value provided (optional field)."});continue}const o=R(e,n);!1===o.ok?u.push({field:e.valueName,reason:o.reason}):l.push(e.valueName)}await new Promise(e=>setTimeout(e,0));for(const e of a)if("value"===e.strategy.kind&&l.includes(e.valueName)){const n=e.strategy.element,r=_(null!==(o=t[e.valueName])&&void 0!==o?o:"");n.value!==r&&(u.push({field:e.valueName,reason:`Value was set to "${r}" but the DOM now shows "${n.value}". A framework may have reverted it.`}),l.splice(l.indexOf(e.valueName),1))}const d=l.length>0&&!c;let f=!1;d&&(f=function(e){try{return"function"==typeof e.requestSubmit?e.requestSubmit():e.submit(),!0}catch(e){return console.warn("[nxis/webmcp] Form submission failed:",e),!1}}(i));const p={success:d,submitted:f,message:M(l,u,f,r),filled:l,skipped:u};return r&&(p.stale=!0),JSON.stringify(p)}function M(e,t,n,o){const r=[];if(o&&r.push(`Warning: ${o}`),0===e.length&&0===t.length)return r.push("No fields were filled. Verify field names match the input schema."),r.join(" ");if(e.length>0&&r.push(`Filled ${e.length} field(s): ${e.join(", ")}.`),t.length>0){const e=t.map(e=>`${e.field} (${e.reason})`).join("; ");r.push(`Skipped ${t.length}: ${e}`)}return n?r.push("Form submitted."):e.length>0&&r.push("Form was NOT submitted due to missing required fields or fill errors."),r.join(" ")}function R(e,t){const{strategy:n}=e;switch(n.kind){case"skip":return{ok:!1,reason:n.reason};case"value":return function(e,t){var n;const o=null===(n=Object.getOwnPropertyDescriptor(e instanceof HTMLTextAreaElement?HTMLTextAreaElement.prototype:HTMLInputElement.prototype,"value"))||void 0===n?void 0:n.set;o?o.call(e,t):e.value=t;return e.dispatchEvent(new Event("input",{bubbles:!0})),e.dispatchEvent(new Event("change",{bubbles:!0})),{ok:!0}}(n.element,_(t));case"checked":return function(e,t){return e.checked=function(e){if("boolean"==typeof e)return e;if("number"==typeof e)return 0!==e;if("string"==typeof e){const t=e.trim().toLowerCase();return""!==t&&"false"!==t&&"0"!==t&&"off"!==t&&"no"!==t}return Boolean(e)}(t),e.dispatchEvent(new Event("change",{bubbles:!0})),{ok:!0}}(n.element,t);case"radio":return function(e,t){var n,o;const r=String(t),i=null!==(o=null!==(n=e.find(e=>e.value===r))&&void 0!==n?n:e.find(e=>e.value.toLowerCase()===r.toLowerCase()))&&void 0!==o?o:e.find(e=>function(e){var t;if(e.labels&&e.labels.length>0)return(null!==(t=e.labels[0].textContent)&&void 0!==t?t:"").trim();return e.value}(e).toLowerCase()===r.toLowerCase());if(!i){const t=e.map(e=>e.value).join(", ");return{ok:!1,reason:`Value "${r}" is not an allowed option for radio "${e[0].name}". Allowed: [${t}].`}}return i.checked=!0,i.dispatchEvent(new Event("input",{bubbles:!0})),i.dispatchEvent(new Event("change",{bubbles:!0})),{ok:!0}}(n.elements,t);case"checkboxGroup":return function(e,t){const n=(Array.isArray(t)?t:[t]).map(e=>String(e)),o=n.map(e=>e.toLowerCase());let r=!1;for(const t of e){const e=n.includes(t.value)||o.includes(t.value.toLowerCase());t.checked=e,e&&(r=!0),t.dispatchEvent(new Event("change",{bubbles:!0}))}if(!r){const t=e.map(e=>e.value).join(", ");return{ok:!1,reason:`None of [${n.join(", ")}] match checkbox group "${e[0].name}". Allowed: [${t}].`}}return{ok:!0}}(n.elements,t);case"select":return function(e,t,n){const o=U(e,t,n);if(null===o)return{ok:!1,reason:`Value "${t}" is not an allowed option for "${e.name}". Allowed: [${n.join(", ")}].`};return e.value=o,e.dispatchEvent(new Event("input",{bubbles:!0})),e.dispatchEvent(new Event("change",{bubbles:!0})),{ok:!0}}(n.element,String(t),n.allowedValues);case"multiSelect":return function(e,t,n){const o=(Array.isArray(t)?t:[t]).map(e=>String(e)),r=new Set,i=[];for(const t of o){const o=U(e,t,n);null===o?i.push(t):r.add(o)}if(0===r.size)return{ok:!1,reason:`None of [${o.join(", ")}] are allowed options for "${e.name}". Allowed: [${n.join(", ")}].`};for(const t of Array.from(e.options))t.selected=r.has(t.value);if(e.dispatchEvent(new Event("input",{bubbles:!0})),e.dispatchEvent(new Event("change",{bubbles:!0})),i.length>0)return{ok:!1,reason:`Selected [${Array.from(r).join(", ")}] but [${i.join(", ")}] are not allowed options for "${e.name}". Allowed: [${n.join(", ")}].`};return{ok:!0}}(n.element,t,n.allowedValues);default:return{ok:!1,reason:`Unsupported fill strategy for field "${e.valueName}".`}}}function _(e){return Array.isArray(e)?e.map(e=>String(e)).join(","):String(e)}function U(e,t,n){if(n.includes(t))return t;const o=n.find(e=>e.toLowerCase()===t.toLowerCase());if(o)return o;for(const n of Array.from(e.options))if(n.text.toLowerCase()===t.toLowerCase())return n.value;return null}function V(e){var t;const n=!1!==(null==e?void 0:e.observe),o=null!==(t=null==e?void 0:e.doc)&&void 0!==t?t:"undefined"!=typeof document?document:void 0;if(!o)return console.warn("[nxis/webmcp] No document available (not running in a browser). Tools will not be registered."),()=>{};!function(e={}){const{force:t=!1,installNavigatorAlias:n=!0}=e,o="undefined"!=typeof document&&document.modelContext||"undefined"!=typeof navigator&&navigator.modelContext||void 0;if(o&&!t)return o;const r=new g;"undefined"!=typeof document&&y(document,r),n&&"undefined"!=typeof navigator&&y(navigator,r)}();const r=function(e){var t,n;const o=null!==(n=null===(t=e.defaultView)||void 0===t?void 0:t.navigator)&&void 0!==n?n:"undefined"!=typeof navigator?navigator:void 0;return e.modelContext||(null==o?void 0:o.modelContext)||null}(o);if(!r)return console.warn("[nxis/webmcp] WebMCP API not available — document.modelContext is undefined. Tools will not be registered."),()=>{};const i=new AbortController;(null==e?void 0:e.signal)&&(e.signal.aborted?i.abort():e.signal.addEventListener("abort",()=>i.abort()));const a={ids:new Set,names:new Set};P(o,r,i,a);let s=null;return n&&(s=function(e,t,n,o){const r=new MutationObserver(r=>{(function(e){for(const t of e)for(const e of Array.from(t.addedNodes)){if(H(e))return!0;if(e instanceof Element&&e.querySelector('script[type="application/ld+json"]'))return!0}return!1})(r)&&P(e,t,n,o)});return n.signal.addEventListener("abort",()=>r.disconnect()),r.observe(e.documentElement,{childList:!0,subtree:!0}),r}(o,r,i,a)),()=>{i.abort(),s&&(s.disconnect(),s=null)}}function P(e,t,n,o){const r=function(e=("undefined"!=typeof document?document:void 0)){const t=[];if(!e)return t;const n=e.querySelectorAll('script[type="application/ld+json"]');for(const e of Array.from(n)){const n=e.textContent;if(!n)continue;let o;try{o=JSON.parse(n)}catch(e){continue}const r=$(o);for(const e of r){const n=T(e);n&&t.push(n)}}return t}(e);let i=0;for(const e of r)if(!o.ids.has(e["@id"]))try{D(e,t,n,o),o.ids.add(e["@id"]),i++}catch(t){console.warn(`[nxis/webmcp] Failed to register tool for action "${e.name}":`,t)}i>0&&console.info(`[nxis/webmcp] Registered ${i} tool(s) (${o.ids.size} total) from ${r.length} action(s).`)}function D(e,t,n,o){const r=function(e){var t;const n={},o=[],r=null!==(t=e.input)&&void 0!==t?t:[];for(const e of r){const t=S(e);if(e.multipleValues){const o={type:"array",items:t};void 0!==e.valueMinLength&&(o.minItems=e.valueMinLength,delete t.minLength),void 0!==e.valueMaxLength&&(o.maxItems=e.valueMaxLength,delete t.maxLength),e.description&&(o.description=e.description,delete t.description),n[e.valueName]=o}else n[e.valueName]=t;e.valueRequired&&o.push(e.valueName)}const i={type:"object",properties:n};return o.length>0&&(i.required=o),i}(e),i=function(e,t){if(!t.has(e))return e;for(let n=2;;n++){const o=`_${n}`,r=e.slice(0,64-o.length)+o;if(!t.has(r))return r}}(function(e){return e.toLowerCase().replace(/[\s-]+/g,"_").replace(/[^a-z0-9_]/g,"_").replace(/_+/g,"_").replace(/^_|_$/g,"").slice(0,64)||"unnamed_action"}(e.name),o.names);t.registerTool({name:i,description:e.description,inputSchema:r,annotations:{readOnlyHint:!1,untrustedContentHint:!0,"ai.nxis/actionId":e["@id"]},execute:async t=>I(e,t)},{signal:n.signal}),o.names.add(i)}function H(e){return e instanceof HTMLScriptElement&&"application/ld+json"===e.type}function q(t){t instanceof e?console.warn(JSON.parse(t.message).message):console.error(`Unable to retrieve structured data for ${window.location.href}`)}!function(){var t,o;const r=window.__NXIS_CONFIG__,i=null!==(o=null===(t=null==r?void 0:r.webmcp)||void 0===t?void 0:t.mode)&&void 0!==o?o:"browser";if("ssr"===i)return void V();const a=process.env.NXIS_API_HOST,s=new Headers,l=new URL(`${a}/v1/nxis:inject`);l.search=function(e){var t,n;const o=new URLSearchParams;return(null===(t=e.organization_id)||void 0===t?void 0:t.value)&&o.append("organization_id",e.organization_id.value),(null===(n=e.site_id)||void 0===n?void 0:n.value)&&o.append("site_id",e.site_id.value),o.append("uri",e.uri.href),e.referrer&&o.append("referrer",e.referrer),o}({organization_id:{value:null==r?void 0:r.org_id},site_id:{value:null==r?void 0:r.site_id},uri:new URL(window.location.href),referrer:document.referrer}).toString(),(null==r?void 0:r.sub_id)&&s.set("X-NXIS-SUBSCRIPTION",r.sub_id),s.set("Content-Type","application/json"),s.set("User-Agent",navigator.userAgent),fetch(`${l}`,{headers:s}).then(t=>async function(t,o){const r=null!=o?o:"unknown";if(200===t.status){const n=await t.json();if((null==n?void 0:n.data)&&Object.keys(n.data).length>0)return n;throw new e(JSON.stringify({message:`No Nxis resource found for ${r}`}))}const i=await async function(e){try{return await e.json()}catch(e){return null}}(t);if(void 0!==(null==i?void 0:i.code)&&(null==i?void 0:i.message))throw n.fromResponse(t.status,i);switch(t.status){case 500:throw new n(13,500,"An internal server error occurred, please contact technical support.");case 502:throw new n(13,502,"An internal server error occurred, please contact technical support.");case 503:throw new n(8,503,"Service is temporarily unavailable, please try again later.");default:throw new n(13,t.status,`Unexpected response status: ${t.status}`)}}(t,window.location.href)).then(e=>{!function(e){if(e.data&&Object.keys(e.data).length>0){const t=document.createComment("Nxis.ai"),n=document.createComment("End Nxis.ai"),o=document.createElement("script");o.setAttribute("type","application/ld+json"),o.textContent=JSON.stringify(e.data),document.head.appendChild(o),o.before(t),o.after(n)}}(e),"browser"===i&&V()}).catch(q)}();
|
package/build/webmcp/types.d.ts
CHANGED
|
@@ -22,6 +22,15 @@ export interface ToolAnnotations {
|
|
|
22
22
|
* Always `true` for NxisAI tools — we infer from content we don't control.
|
|
23
23
|
*/
|
|
24
24
|
untrustedContentHint?: boolean;
|
|
25
|
+
/**
|
|
26
|
+
* The `@id` of the Action this tool was generated from.
|
|
27
|
+
*
|
|
28
|
+
* A tool's name comes from the action's name and may be suffixed to avoid a
|
|
29
|
+
* collision, so it does not identify the action on its own. A client holding
|
|
30
|
+
* the same action from elsewhere — the site's MCP server, say — matches the
|
|
31
|
+
* two by this.
|
|
32
|
+
*/
|
|
33
|
+
'ai.nxis/actionId'?: string;
|
|
25
34
|
}
|
|
26
35
|
/** The shape passed to `modelContext.registerTool()`. */
|
|
27
36
|
export interface ModelContextTool {
|
package/build/webmcp.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
function e(e){return null===e?"null":Array.isArray(e)?"array":typeof e}function t(n,o){if(n===o)return!0;if(e(n)!==e(o))return!1;if(Array.isArray(n)&&Array.isArray(o))return n.length===o.length&&n.every((e,n)=>t(e,o[n]));if("object"===e(n)){const e=n,r=o,i=Object.keys(e);return i.length===Object.keys(r).length&&i.every(n=>t(e[n],r[n]))}return!1}function n(o,r,i="$"){if(!r||"object"!=typeof r)return[];const a=[];if(void 0===r.const||t(o,r.const)||a.push({path:i,message:`must equal const ${JSON.stringify(r.const)}`}),r.enum&&!r.enum.some(e=>t(o,e))&&a.push({path:i,message:`must be one of ${JSON.stringify(r.enum)}`}),void 0!==r.type){const t=Array.isArray(r.type)?r.type:[r.type];if(!t.some(t=>function(t,n){switch(n){case"object":return"object"===e(t);case"array":return Array.isArray(t);case"string":return"string"==typeof t;case"number":return"number"==typeof t&&Number.isFinite(t);case"integer":return"number"==typeof t&&Number.isInteger(t);case"boolean":return"boolean"==typeof t;case"null":return null===t;default:return!0}}(o,t)))return a.push({path:i,message:`expected type ${t.join(" | ")}, got ${e(o)}`}),a}if("string"==typeof o&&(void 0!==r.minLength&&o.length<r.minLength&&a.push({path:i,message:`must be at least ${r.minLength} characters`}),void 0!==r.maxLength&&o.length>r.maxLength&&a.push({path:i,message:`must be at most ${r.maxLength} characters`}),void 0!==r.pattern)){let e=null;try{e=new RegExp(r.pattern,"u")}catch{}e&&!e.test(o)&&a.push({path:i,message:`must match pattern ${r.pattern}`})}if("number"==typeof o&&(void 0!==r.minimum&&o<r.minimum&&a.push({path:i,message:`must be >= ${r.minimum}`}),void 0!==r.maximum&&o>r.maximum&&a.push({path:i,message:`must be <= ${r.maximum}`})),Array.isArray(o)&&(void 0!==r.minItems&&o.length<r.minItems&&a.push({path:i,message:`must have at least ${r.minItems} items`}),void 0!==r.maxItems&&o.length>r.maxItems&&a.push({path:i,message:`must have at most ${r.maxItems} items`}),r.items&&o.forEach((e,t)=>{a.push(...n(e,r.items,`${i}[${t}]`))})),"object"===e(o)&&!Array.isArray(o)&&null!==o){const e=o;for(const t of r.required??[])t in e||a.push({path:i,message:`missing required property "${t}"`});const t=r.properties??{};for(const[o,r]of Object.entries(t))o in e&&a.push(...n(e[o],r,`${i}.${o}`));if(!1===r.additionalProperties)for(const n of Object.keys(e))n in t||a.push({path:i,message:`unexpected property "${n}"`});else if(r.additionalProperties&&"object"==typeof r.additionalProperties)for(const o of Object.keys(e))o in t||a.push(...n(e[o],r.additionalProperties,`${i}.${o}`))}if(r.allOf)for(const e of r.allOf)a.push(...n(o,e,i));if(r.anyOf&&r.anyOf.length>0){r.anyOf.some(e=>0===n(o,e,i).length)||a.push({path:i,message:"does not match any schema in anyOf"})}if(r.oneOf&&r.oneOf.length>0){const e=r.oneOf.filter(e=>0===n(o,e,i).length).length;1!==e&&a.push({path:i,message:`must match exactly one schema in oneOf (matched ${e})`})}return a}var o,r,i,a,s,l,u=function(e,t,n,o){if("a"===n&&!o)throw new TypeError("Private accessor was defined without a getter");if("function"==typeof t?e!==t||!o:!t.has(e))throw new TypeError("Cannot read private member from an object whose class did not declare it");return"m"===n?o:"a"===n?o.call(e):o?o.value:t.get(e)},c=function(e,t,n,o,r){if("m"===o)throw new TypeError("Private method is not writable");if("a"===o&&!r)throw new TypeError("Private accessor was defined without a setter");if("function"==typeof t?e!==t||!r:!t.has(e))throw new TypeError("Cannot write private member to an object whose class did not declare it");return"a"===o?r.call(e,n):r?r.value=n:t.set(e,n),n};const f={type:"object"};function d(e,t){if("function"==typeof DOMException)return new DOMException(e,t);const n=new Error(e);return n.name=t,n}function p(e){if(!e||"object"!=typeof e)throw new TypeError("Tool descriptor must be an object.");if("string"!=typeof e.name||0===e.name.length)throw new TypeError("Tool descriptor requires a non-empty string 'name'.");if("string"!=typeof e.description)throw new TypeError(`Tool "${e.name}" requires a string 'description'.`);if("function"!=typeof e.execute)throw new TypeError(`Tool "${e.name}" requires an 'execute' function.`);if(void 0!==e.inputSchema&&"object"!=typeof e.inputSchema)throw new TypeError(`Tool "${e.name}": 'inputSchema' must be an object.`)}class m extends EventTarget{constructor(){super(...arguments),o.add(this),r.set(this,new Map),i.set(this,null),a.set(this,!1)}get ontoolchange(){return u(this,i,"f")}set ontoolchange(e){u(this,i,"f")&&this.removeEventListener("toolchange",u(this,i,"f")),c(this,i,"function"==typeof e?e:null,"f"),u(this,i,"f")&&this.addEventListener("toolchange",u(this,i,"f"))}registerTool(e,t={}){p(e);const{signal:n,exposedTo:i}=t;if(n?.aborted)return;u(this,o,"m",s).call(this,e.name);const a={tool:e,exposedTo:i?[...i]:void 0,pageLevel:!1};if(n){const t=()=>u(this,o,"m",s).call(this,e.name,a,!0);n.addEventListener("abort",t,{once:!0}),a.abortListener={signal:n,listener:t}}u(this,r,"f").set(e.name,a),u(this,o,"m",l).call(this)}provideContext(e={}){const t=e.tools??[];for(const e of t)p(e);if(new Set(t.map(e=>e.name)).size!==t.length)throw new TypeError("provideContext(): duplicate tool names in 'tools'.");for(const[e,t]of u(this,r,"f"))t.pageLevel&&u(this,o,"m",s).call(this,e);for(const e of t){if(u(this,r,"f").has(e.name))throw d(`provideContext(): tool "${e.name}" is already registered via registerTool().`,"InvalidStateError");u(this,r,"f").set(e.name,{tool:e,exposedTo:void 0,pageLevel:!0})}u(this,o,"m",l).call(this)}async getTools(e={}){e.fromOrigins;const t="undefined"!=typeof location?location.origin:void 0;return[...u(this,r,"f").values()].map(({tool:e})=>{const n={name:e.name,description:e.description,inputSchema:structuredClone(e.inputSchema??f)};return e.annotations&&(n.annotations=structuredClone(e.annotations)),t&&(n.origin=t),n})}async executeTool(e,t,o={}){const i=u(this,r,"f").get(e);if(!i)throw d(`No tool registered with name "${e}".`,"NotFoundError");if(o.signal?.aborted)throw d("Tool execution was aborted.","AbortError");let a;if(null==t||""===t)a={};else if("string"==typeof t)try{a=JSON.parse(t)}catch(t){throw new TypeError(`executeTool("${e}"): input is not valid JSON: ${t.message}`)}else a=t;if(null===a||"object"!=typeof a||Array.isArray(a))throw new TypeError(`executeTool("${e}"): input must be a JSON object.`);const s=n(a,i.tool.inputSchema??f);if(s.length>0){const t=s.map(e=>`${e.path}: ${e.message}`).join("; ");throw new TypeError(`executeTool("${e}"): invalid input — ${t}`)}const l=new AbortController,c=o.signal,p=()=>l.abort(c?.reason);c?.addEventListener("abort",p,{once:!0});try{const t=await i.tool.execute(a,{signal:l.signal,toolName:e});if(c?.aborted)throw d("Tool execution was aborted.","AbortError");return function(e){return null==e?{content:[]}:"string"==typeof e?{content:[{type:"text",text:e}]}:"object"==typeof e&&Array.isArray(e.content)?e:{content:[{type:"text",text:JSON.stringify(e)}]}}(t)}catch(e){if(c?.aborted||e instanceof Error&&"AbortError"===e.name)throw d("Tool execution was aborted.","AbortError");return function(e){return{isError:!0,content:[{type:"text",text:e instanceof Error?`${e.name}: ${e.message}`:String(e)}]}}(e)}finally{c?.removeEventListener("abort",p)}}unregisterTool(e){const t=u(this,o,"m",s).call(this,e);return t&&u(this,o,"m",l).call(this),t}clearContext(){if(0!==u(this,r,"f").size){for(const e of[...u(this,r,"f").keys()])u(this,o,"m",s).call(this,e);u(this,o,"m",l).call(this)}}}function h(e,t){Object.defineProperty(e,"modelContext",{value:t,writable:!1,enumerable:!0,configurable:!0})}r=new WeakMap,i=new WeakMap,a=new WeakMap,o=new WeakSet,s=function(e,t,n=!1){const i=u(this,r,"f").get(e);return!!i&&((!t||i===t)&&(i.abortListener&&i.abortListener.signal.removeEventListener("abort",i.abortListener.listener),u(this,r,"f").delete(e),n&&u(this,o,"m",l).call(this),!0))},l=function(){u(this,a,"f")||(c(this,a,!0,"f"),queueMicrotask(()=>{c(this,a,!1,"f"),this.dispatchEvent(new Event("toolchange"))}))};const v=["AskAction","SearchAction","SubscribeAction","RegisterAction","BuyAction","OrderAction","AddAction","ScheduleAction","ReserveAction","RsvpAction","ApplyAction","QuoteAction","DownloadAction","ReviewAction","CommentAction","TrackAction","CommunicateAction","InteractAction"];function g(e){return v.includes(e)}const y="https://nxis.ai/ns#";function b(e,t,n){var o;return null!==(o=e[t])&&void 0!==o?o:e[n]}function w(e,t){return b(e,t,"https://schema.org/"+t)}function x(e,t){const n=w(e,t);return"string"==typeof n?n:null}function $(e,t,n){const o=b(e,t,n);return Array.isArray(o)?o:[]}function A(e=("undefined"!=typeof document?document:void 0)){const t=[];if(!e)return t;const n=e.querySelectorAll('script[type="application/ld+json"]');for(const e of Array.from(n)){const n=e.textContent;if(!n)continue;let o;try{o=JSON.parse(n)}catch(e){continue}const r=E(o);for(const e of r){const n=T(e);n&&t.push(n)}}return t}function E(e){if(Array.isArray(e)){const t=[];for(const n of e)t.push(...E(n));return t}if(e&&"object"==typeof e){const t=e;if(Array.isArray(t["@graph"])){const e=[];for(const n of t["@graph"])e.push(...E(n));return e}return[t]}return[]}function T(e){var t;if(!e||"object"!=typeof e)return null;const n=e,o="string"==typeof n["@type"]?n["@type"]:null;if(!o)return null;if(!o.endsWith("Action")&&!g(o))return null;const r="string"==typeof n["@id"]?n["@id"]:null,i=x(n,"name"),a=function(e){var t,n;if(!e||"object"!=typeof e)return null;const o=e,r=null!==(n=null===(t=x(o,"httpMethod"))||void 0===t?void 0:t.toUpperCase())&&void 0!==n?n:null;if(!r)return null;const i={"@type":"EntryPoint",httpMethod:r},a=x(o,"encodingType");null!==a&&(i.encodingType=a);const s=x(o,"urlTemplate");null!==s&&(i.urlTemplate=s);const l=b(o,"nxis:targetKind",y+"targetKind");"selfPage"!==l&&"clientSide"!==l||(i["nxis:targetKind"]=l);const u=b(o,"nxis:pageUrl",y+"pageUrl");"string"==typeof u&&(i["nxis:pageUrl"]=u);const c=b(o,"nxis:jsHandled",y+"jsHandled");!0===c&&(i["nxis:jsHandled"]=!0);return i}(w(n,"target"));if(!r||!i||!a)return null;const s=$(n,"nxis:input",y+"input").map(L).filter(e=>null!==e),l=null!==(t=x(n,"description"))&&void 0!==t?t:function(e,t,n){const o=e.replace(/^.*[/#]/,"").replace(/Action$/,"").toLowerCase(),r=n.map(e=>e.valueName).join(", ");if(0===n.length)return`Trigger the ${o} action "${t}".`;return`Fill the ${o} form "${t}" with fields: ${r}.`}(o,i,s);return{"@context":n["@context"],"@type":o,"@id":r,name:i,description:l,target:a,input:s.length>0?s:void 0,"nxis:extractedAt":b(n,"nxis:extractedAt",y+"extractedAt")}}function L(e){if(!e||"object"!=typeof e)return null;const t=e,n=x(t,"valueName");if(!n)return null;const o=b(t,"nxis:valueType",y+"valueType"),r={"@type":"PropertyValueSpecification",valueName:n,"nxis:valueType":"string"==typeof o?o:"string"},i=x(t,"description");null!==i&&(r.description=i),!0===w(t,"valueRequired")&&(r.valueRequired=!0);const a=x(t,"defaultValue");null!==a&&(r.defaultValue=a);const s=e=>{const n=w(t,e);return"number"==typeof n?n:null},l=s("valueMinLength");null!==l&&(r.valueMinLength=l);const u=s("valueMaxLength");null!==u&&(r.valueMaxLength=u);const c=s("minValue");null!==c&&(r.minValue=c);const f=s("maxValue");null!==f&&(r.maxValue=f);const d=s("stepValue");null!==d&&(r.stepValue=d);const p=x(t,"valuePattern");null!==p&&(r.valuePattern=p),!0===w(t,"multipleValues")&&(r.multipleValues=!0),!0===w(t,"readonlyValue")&&(r.readonlyValue=!0);const m=$(t,"nxis:valueOption",y+"valueOption");if(m.length>0){const e=m.filter(e=>e&&"object"==typeof e&&null!==x(e,"value")).map(e=>{var t;const n=e;return{"@type":"nxis:ValueOption",value:x(n,"value"),name:null!==(t=x(n,"name"))&&void 0!==t?t:void 0}});e.length>0&&(r["nxis:valueOption"]=e)}return r}function N(e){switch(e){case"string":case"date":case"file":default:return"string";case"number":return"number";case"integer":return"integer";case"boolean":return"boolean"}}function k(e){var t;const n={},o=[],r=null!==(t=e.input)&&void 0!==t?t:[];for(const e of r){const t=j(e);if(e.multipleValues){const o={type:"array",items:t};void 0!==e.valueMinLength&&(o.minItems=e.valueMinLength,delete t.minLength),void 0!==e.valueMaxLength&&(o.maxItems=e.valueMaxLength,delete t.maxLength),e.description&&(o.description=e.description,delete t.description),n[e.valueName]=o}else n[e.valueName]=t;e.valueRequired&&o.push(e.valueName)}const i={type:"object",properties:n};return o.length>0&&(i.required=o),i}function j(e){const t={type:N(e["nxis:valueType"])},n=function(e){if("date"===e)return"date"}(e["nxis:valueType"]);if(n&&(t.format=n),e.description&&(t.description=e.description),void 0!==e.defaultValue&&(t.default=function(e,t){switch(t){case"number":case"integer":{const t=Number(e);return isNaN(t)?e:t}case"boolean":return"true"===e||"1"===e;default:return e}}(e.defaultValue,e["nxis:valueType"])),void 0!==e.valueMinLength&&(t.minLength=e.valueMinLength),void 0!==e.valueMaxLength&&(t.maxLength=e.valueMaxLength),e.valuePattern){const n=e.valuePattern,o=n.startsWith("^")&&n.endsWith("$")?n:`^${n}$`;t.pattern=o}void 0!==e.minValue&&(t.minimum=e.minValue),void 0!==e.maxValue&&(t.maximum=e.maxValue),void 0!==e.stepValue&&(t.multipleOf=e.stepValue),e.readonlyValue&&(t.readOnly=!0);const o=e["nxis:valueOption"];if(o&&o.length>0){t.enum=o.map(e=>e.value);if(o.some(e=>void 0!==e.name&&e.name!==e.value)){const e=o.filter(e=>e.name&&e.name!==e.value).map(e=>`${e.value} = "${e.name}"`).join(", "),n=t.description?`${t.description}. `:"";t.description=`${n}Values: ${e}`}}return t}function S(e){const t=Array.from(document.querySelectorAll("form"));if(0===t.length)return null;const n=function(e){return e.input?e.input.map(e=>e.valueName):[]}(e);let o;if(o=!e.target.urlTemplate?t:function(e,t,n){const o=function(e){const t=e.replace(/\{[^}]*\}/g,"");try{return new URL(t,window.location.href)}catch(e){return null}}(t);return e.filter(e=>{if((e.method||"GET").toUpperCase()!==n.toUpperCase())return!1;if(!o)return!0;const t=function(e){const t=e.getAttribute("action");if(!t||"#"===t||t.startsWith("#")||""===t)return window.location.href.split("#")[0].split("?")[0];if(t.startsWith("javascript:"))return window.location.href.split("#")[0].split("?")[0];try{return new URL(t,window.location.href).href}catch(e){return t}}(e);return function(e,t){let n;try{n=new URL(e,window.location.href)}catch(e){return!1}if(n.origin!==t.origin)return!1;const o=n.pathname.replace(/\/+$/,""),r=t.pathname.replace(/\/+$/,"");return""===r||(o===r||o.startsWith(r+"/")||r.startsWith(o+"/"))}(t,o)})}(t,e.target.urlTemplate,e.target.httpMethod),0===o.length&&(o=t),1===o.length)return o[0];const r=o.map(e=>({form:e,controlNames:O(e)})).filter(({controlNames:e})=>n.every(t=>e.has(t)));return 0===r.length?(console.warn(`[nxis/webmcp] No field-set match for action "${e.name}". Expected fields: [${n.join(", ")}]. Falling back to first candidate.`),o[0]):1===r.length?r[0].form:(r.sort((e,t)=>e.controlNames.size-t.controlNames.size),r[0].controlNames.size===r[1].controlNames.size?(console.warn(`[nxis/webmcp] Ambiguous form match for action "${e.name}". ${r.length} forms have identical field sets. Returning null.`),null):r[0].form)}function O(e){const t=new Set,n=e.elements;for(let e=0;e<n.length;e++){const o=n[e];o.name&&t.add(o.name)}return t}function C(e,t){var n;return(null!==(n=e.input)&&void 0!==n?n:[]).map(e=>function(e,t){var n;const o=t=>({valueName:e.valueName,pvs:e,strategy:t}),r=function(e,t){const n=[],o=e.elements;for(let e=0;e<o.length;e++){const r=o[e];r.name===t&&n.push(r)}return n}(t,e.valueName),i=null!==(n=r[0])&&void 0!==n?n:null;if(!i)return o({kind:"skip",reason:`No control found with name="${e.valueName}"`});if(i instanceof HTMLInputElement&&"radio"===i.type){const t=r.filter(e=>e instanceof HTMLInputElement&&"radio"===e.type&&!e.disabled);return 0===t.length?o({kind:"skip",reason:`Radio group "${e.valueName}" has no enabled options`}):o({kind:"radio",name:e.valueName,elements:t})}if(i instanceof HTMLInputElement&&"checkbox"===i.type){const t=r.filter(e=>e instanceof HTMLInputElement&&"checkbox"===e.type&&!e.disabled);return 0===t.length?o({kind:"skip",reason:`Checkbox "${e.valueName}" is disabled`}):t.length>1?o({kind:"checkboxGroup",name:e.valueName,elements:t}):o({kind:"checked",element:t[0]})}if(!0===i.readOnly||null!==i.getAttribute("readonly"))return o({kind:"skip",reason:`Control "${e.valueName}" is readonly in the DOM`});if(i.disabled)return o({kind:"skip",reason:`Control "${e.valueName}" is disabled`});if(i instanceof HTMLSelectElement){const e=[];for(let t=0;t<i.options.length;t++){const n=i.options[t];n.value&&e.push(n.value)}return o(i.multiple?{kind:"multiSelect",element:i,allowedValues:e}:{kind:"select",element:i,allowedValues:e})}if(i instanceof HTMLTextAreaElement)return o({kind:"value",element:i});if(i instanceof HTMLInputElement)return o({kind:"value",element:i});return o({kind:"skip",reason:`Unsupported control type for "${e.valueName}"`})}(e,t))}async function M(e,t){var n,o;const r=function(e){const t=e.target["nxis:pageUrl"];if(!t)return null;try{const n=new URL(t),o=new URL(window.location.href);if(n.origin!==o.origin||n.pathname!==o.pathname)return`Action "${e.name}" was extracted from ${n.origin}${n.pathname} but the current page is ${o.origin}${o.pathname}. The form may have moved or changed.`}catch(e){return null}return null}(e),i=S(e);if(!i){const t=`Form not found for action "${e.name}". The page may have changed since the tool was registered.`,n={success:!1,submitted:!1,message:r?`Warning: ${r} ${t}`:t,filled:[],skipped:[]};return r&&(n.stale=!0),JSON.stringify(n)}const a=C(e,i),s=null!==(n=e.input)&&void 0!==n?n:[],l=[],u=[];let c=!1;for(const e of s)!e.valueRequired||void 0!==t[e.valueName]&&null!==t[e.valueName]||(c=!0,u.push({field:e.valueName,reason:`Required field '${e.valueName}' was not provided. Expected type: ${e["nxis:valueType"]}.`}));for(const e of a){const n=t[e.valueName];if(null==n){u.some(t=>t.field===e.valueName)||u.push({field:e.valueName,reason:"No value provided (optional field)."});continue}const o=q(e,n);!1===o.ok?u.push({field:e.valueName,reason:o.reason}):l.push(e.valueName)}await new Promise(e=>setTimeout(e,0));for(const e of a)if("value"===e.strategy.kind&&l.includes(e.valueName)){const n=e.strategy.element,r=P(null!==(o=t[e.valueName])&&void 0!==o?o:"");n.value!==r&&(u.push({field:e.valueName,reason:`Value was set to "${r}" but the DOM now shows "${n.value}". A framework may have reverted it.`}),l.splice(l.indexOf(e.valueName),1))}const f=l.length>0&&!c;let d=!1;f&&(d=function(e){try{return"function"==typeof e.requestSubmit?e.requestSubmit():e.submit(),!0}catch(e){return console.warn("[nxis/webmcp] Form submission failed:",e),!1}}(i));const p={success:f,submitted:d,message:V(l,u,d,r),filled:l,skipped:u};return r&&(p.stale=!0),JSON.stringify(p)}function V(e,t,n,o){const r=[];if(o&&r.push(`Warning: ${o}`),0===e.length&&0===t.length)return r.push("No fields were filled. Verify field names match the input schema."),r.join(" ");if(e.length>0&&r.push(`Filled ${e.length} field(s): ${e.join(", ")}.`),t.length>0){const e=t.map(e=>`${e.field} (${e.reason})`).join("; ");r.push(`Skipped ${t.length}: ${e}`)}return n?r.push("Form submitted."):e.length>0&&r.push("Form was NOT submitted due to missing required fields or fill errors."),r.join(" ")}function q(e,t){const{strategy:n}=e;switch(n.kind){case"skip":return{ok:!1,reason:n.reason};case"value":return function(e,t){var n;const o=null===(n=Object.getOwnPropertyDescriptor(e instanceof HTMLTextAreaElement?HTMLTextAreaElement.prototype:HTMLInputElement.prototype,"value"))||void 0===n?void 0:n.set;o?o.call(e,t):e.value=t;return e.dispatchEvent(new Event("input",{bubbles:!0})),e.dispatchEvent(new Event("change",{bubbles:!0})),{ok:!0}}(n.element,P(t));case"checked":return function(e,t){return e.checked=function(e){if("boolean"==typeof e)return e;if("number"==typeof e)return 0!==e;if("string"==typeof e){const t=e.trim().toLowerCase();return""!==t&&"false"!==t&&"0"!==t&&"off"!==t&&"no"!==t}return Boolean(e)}(t),e.dispatchEvent(new Event("change",{bubbles:!0})),{ok:!0}}(n.element,t);case"radio":return function(e,t){var n,o;const r=String(t),i=null!==(o=null!==(n=e.find(e=>e.value===r))&&void 0!==n?n:e.find(e=>e.value.toLowerCase()===r.toLowerCase()))&&void 0!==o?o:e.find(e=>function(e){var t;if(e.labels&&e.labels.length>0)return(null!==(t=e.labels[0].textContent)&&void 0!==t?t:"").trim();return e.value}(e).toLowerCase()===r.toLowerCase());if(!i){const t=e.map(e=>e.value).join(", ");return{ok:!1,reason:`Value "${r}" is not an allowed option for radio "${e[0].name}". Allowed: [${t}].`}}return i.checked=!0,i.dispatchEvent(new Event("input",{bubbles:!0})),i.dispatchEvent(new Event("change",{bubbles:!0})),{ok:!0}}(n.elements,t);case"checkboxGroup":return function(e,t){const n=(Array.isArray(t)?t:[t]).map(e=>String(e)),o=n.map(e=>e.toLowerCase());let r=!1;for(const t of e){const e=n.includes(t.value)||o.includes(t.value.toLowerCase());t.checked=e,e&&(r=!0),t.dispatchEvent(new Event("change",{bubbles:!0}))}if(!r){const t=e.map(e=>e.value).join(", ");return{ok:!1,reason:`None of [${n.join(", ")}] match checkbox group "${e[0].name}". Allowed: [${t}].`}}return{ok:!0}}(n.elements,t);case"select":return function(e,t,n){const o=I(e,t,n);if(null===o)return{ok:!1,reason:`Value "${t}" is not an allowed option for "${e.name}". Allowed: [${n.join(", ")}].`};return e.value=o,e.dispatchEvent(new Event("input",{bubbles:!0})),e.dispatchEvent(new Event("change",{bubbles:!0})),{ok:!0}}(n.element,String(t),n.allowedValues);case"multiSelect":return function(e,t,n){const o=(Array.isArray(t)?t:[t]).map(e=>String(e)),r=new Set,i=[];for(const t of o){const o=I(e,t,n);null===o?i.push(t):r.add(o)}if(0===r.size)return{ok:!1,reason:`None of [${o.join(", ")}] are allowed options for "${e.name}". Allowed: [${n.join(", ")}].`};for(const t of Array.from(e.options))t.selected=r.has(t.value);if(e.dispatchEvent(new Event("input",{bubbles:!0})),e.dispatchEvent(new Event("change",{bubbles:!0})),i.length>0)return{ok:!1,reason:`Selected [${Array.from(r).join(", ")}] but [${i.join(", ")}] are not allowed options for "${e.name}". Allowed: [${n.join(", ")}].`};return{ok:!0}}(n.element,t,n.allowedValues);default:return{ok:!1,reason:`Unsupported fill strategy for field "${e.valueName}".`}}}function P(e){return Array.isArray(e)?e.map(e=>String(e)).join(","):String(e)}function I(e,t,n){if(n.includes(t))return t;const o=n.find(e=>e.toLowerCase()===t.toLowerCase());if(o)return o;for(const n of Array.from(e.options))if(n.text.toLowerCase()===t.toLowerCase())return n.value;return null}function R(e){var t;const n=!1!==(null==e?void 0:e.observe),o=null!==(t=null==e?void 0:e.doc)&&void 0!==t?t:"undefined"!=typeof document?document:void 0;if(!o)return console.warn("[nxis/webmcp] No document available (not running in a browser). Tools will not be registered."),()=>{};!function(e={}){const{force:t=!1,installNavigatorAlias:n=!0}=e,o="undefined"!=typeof document&&document.modelContext||"undefined"!=typeof navigator&&navigator.modelContext||void 0;if(o&&!t)return o;const r=new m;"undefined"!=typeof document&&h(document,r),n&&"undefined"!=typeof navigator&&h(navigator,r)}();const r=function(e){var t,n;const o=null!==(n=null===(t=e.defaultView)||void 0===t?void 0:t.navigator)&&void 0!==n?n:"undefined"!=typeof navigator?navigator:void 0;return e.modelContext||(null==o?void 0:o.modelContext)||null}(o);if(!r)return console.warn("[nxis/webmcp] WebMCP API not available — document.modelContext is undefined. Tools will not be registered."),()=>{};const i=new AbortController;(null==e?void 0:e.signal)&&(e.signal.aborted?i.abort():e.signal.addEventListener("abort",()=>i.abort()));const a={ids:new Set,names:new Set};H(o,r,i,a);let s=null;return n&&(s=function(e,t,n,o){const r=new MutationObserver(r=>{(function(e){for(const t of e)for(const e of Array.from(t.addedNodes)){if(W(e))return!0;if(e instanceof Element&&e.querySelector('script[type="application/ld+json"]'))return!0}return!1})(r)&&H(e,t,n,o)});return n.signal.addEventListener("abort",()=>r.disconnect()),r.observe(e.documentElement,{childList:!0,subtree:!0}),r}(o,r,i,a)),()=>{i.abort(),s&&(s.disconnect(),s=null)}}function H(e,t,n,o){const r=A(e);let i=0;for(const e of r)if(!o.ids.has(e["@id"]))try{U(e,t,n,o),o.ids.add(e["@id"]),i++}catch(t){console.warn(`[nxis/webmcp] Failed to register tool for action "${e.name}":`,t)}i>0&&console.info(`[nxis/webmcp] Registered ${i} tool(s) (${o.ids.size} total) from ${r.length} action(s).`)}function U(e,t,n,o){const r=k(e),i=function(e,t){if(!t.has(e))return e;for(let n=2;;n++){const o=`_${n}`,r=e.slice(0,64-o.length)+o;if(!t.has(r))return r}}(function(e){return e.toLowerCase().replace(/[\s-]+/g,"_").replace(/[^a-z0-9_]/g,"_").replace(/_+/g,"_").replace(/^_|_$/g,"").slice(0,64)||"unnamed_action"}(e.name),o.names);t.registerTool({name:i,description:e.description,inputSchema:r,annotations:{readOnlyHint:!1,untrustedContentHint:!0},execute:async t=>M(e,t)},{signal:n.signal}),o.names.add(i)}function W(e){return e instanceof HTMLScriptElement&&"application/ld+json"===e.type}export{v as ACTION_SUBTYPES,k as buildInputSchema,g as isActionType,A as readActions,R as registerActions};
|
|
1
|
+
function e(e){return null===e?"null":Array.isArray(e)?"array":typeof e}function t(n,o){if(n===o)return!0;if(e(n)!==e(o))return!1;if(Array.isArray(n)&&Array.isArray(o))return n.length===o.length&&n.every((e,n)=>t(e,o[n]));if("object"===e(n)){const e=n,r=o,i=Object.keys(e);return i.length===Object.keys(r).length&&i.every(n=>t(e[n],r[n]))}return!1}function n(o,r,i="$"){if(!r||"object"!=typeof r)return[];const a=[];if(void 0===r.const||t(o,r.const)||a.push({path:i,message:`must equal const ${JSON.stringify(r.const)}`}),r.enum&&!r.enum.some(e=>t(o,e))&&a.push({path:i,message:`must be one of ${JSON.stringify(r.enum)}`}),void 0!==r.type){const t=Array.isArray(r.type)?r.type:[r.type];if(!t.some(t=>function(t,n){switch(n){case"object":return"object"===e(t);case"array":return Array.isArray(t);case"string":return"string"==typeof t;case"number":return"number"==typeof t&&Number.isFinite(t);case"integer":return"number"==typeof t&&Number.isInteger(t);case"boolean":return"boolean"==typeof t;case"null":return null===t;default:return!0}}(o,t)))return a.push({path:i,message:`expected type ${t.join(" | ")}, got ${e(o)}`}),a}if("string"==typeof o&&(void 0!==r.minLength&&o.length<r.minLength&&a.push({path:i,message:`must be at least ${r.minLength} characters`}),void 0!==r.maxLength&&o.length>r.maxLength&&a.push({path:i,message:`must be at most ${r.maxLength} characters`}),void 0!==r.pattern)){let e=null;try{e=new RegExp(r.pattern,"u")}catch{}e&&!e.test(o)&&a.push({path:i,message:`must match pattern ${r.pattern}`})}if("number"==typeof o&&(void 0!==r.minimum&&o<r.minimum&&a.push({path:i,message:`must be >= ${r.minimum}`}),void 0!==r.maximum&&o>r.maximum&&a.push({path:i,message:`must be <= ${r.maximum}`})),Array.isArray(o)&&(void 0!==r.minItems&&o.length<r.minItems&&a.push({path:i,message:`must have at least ${r.minItems} items`}),void 0!==r.maxItems&&o.length>r.maxItems&&a.push({path:i,message:`must have at most ${r.maxItems} items`}),r.items&&o.forEach((e,t)=>{a.push(...n(e,r.items,`${i}[${t}]`))})),"object"===e(o)&&!Array.isArray(o)&&null!==o){const e=o;for(const t of r.required??[])t in e||a.push({path:i,message:`missing required property "${t}"`});const t=r.properties??{};for(const[o,r]of Object.entries(t))o in e&&a.push(...n(e[o],r,`${i}.${o}`));if(!1===r.additionalProperties)for(const n of Object.keys(e))n in t||a.push({path:i,message:`unexpected property "${n}"`});else if(r.additionalProperties&&"object"==typeof r.additionalProperties)for(const o of Object.keys(e))o in t||a.push(...n(e[o],r.additionalProperties,`${i}.${o}`))}if(r.allOf)for(const e of r.allOf)a.push(...n(o,e,i));if(r.anyOf&&r.anyOf.length>0){r.anyOf.some(e=>0===n(o,e,i).length)||a.push({path:i,message:"does not match any schema in anyOf"})}if(r.oneOf&&r.oneOf.length>0){const e=r.oneOf.filter(e=>0===n(o,e,i).length).length;1!==e&&a.push({path:i,message:`must match exactly one schema in oneOf (matched ${e})`})}return a}var o,r,i,a,s,l,u=function(e,t,n,o){if("a"===n&&!o)throw new TypeError("Private accessor was defined without a getter");if("function"==typeof t?e!==t||!o:!t.has(e))throw new TypeError("Cannot read private member from an object whose class did not declare it");return"m"===n?o:"a"===n?o.call(e):o?o.value:t.get(e)},c=function(e,t,n,o,r){if("m"===o)throw new TypeError("Private method is not writable");if("a"===o&&!r)throw new TypeError("Private accessor was defined without a setter");if("function"==typeof t?e!==t||!r:!t.has(e))throw new TypeError("Cannot write private member to an object whose class did not declare it");return"a"===o?r.call(e,n):r?r.value=n:t.set(e,n),n};const f={type:"object"};function d(e,t){if("function"==typeof DOMException)return new DOMException(e,t);const n=new Error(e);return n.name=t,n}function p(e){if(!e||"object"!=typeof e)throw new TypeError("Tool descriptor must be an object.");if("string"!=typeof e.name||0===e.name.length)throw new TypeError("Tool descriptor requires a non-empty string 'name'.");if("string"!=typeof e.description)throw new TypeError(`Tool "${e.name}" requires a string 'description'.`);if("function"!=typeof e.execute)throw new TypeError(`Tool "${e.name}" requires an 'execute' function.`);if(void 0!==e.inputSchema&&"object"!=typeof e.inputSchema)throw new TypeError(`Tool "${e.name}": 'inputSchema' must be an object.`)}class m extends EventTarget{constructor(){super(...arguments),o.add(this),r.set(this,new Map),i.set(this,null),a.set(this,!1)}get ontoolchange(){return u(this,i,"f")}set ontoolchange(e){u(this,i,"f")&&this.removeEventListener("toolchange",u(this,i,"f")),c(this,i,"function"==typeof e?e:null,"f"),u(this,i,"f")&&this.addEventListener("toolchange",u(this,i,"f"))}registerTool(e,t={}){p(e);const{signal:n,exposedTo:i}=t;if(n?.aborted)return;u(this,o,"m",s).call(this,e.name);const a={tool:e,exposedTo:i?[...i]:void 0,pageLevel:!1};if(n){const t=()=>u(this,o,"m",s).call(this,e.name,a,!0);n.addEventListener("abort",t,{once:!0}),a.abortListener={signal:n,listener:t}}u(this,r,"f").set(e.name,a),u(this,o,"m",l).call(this)}provideContext(e={}){const t=e.tools??[];for(const e of t)p(e);if(new Set(t.map(e=>e.name)).size!==t.length)throw new TypeError("provideContext(): duplicate tool names in 'tools'.");for(const[e,t]of u(this,r,"f"))t.pageLevel&&u(this,o,"m",s).call(this,e);for(const e of t){if(u(this,r,"f").has(e.name))throw d(`provideContext(): tool "${e.name}" is already registered via registerTool().`,"InvalidStateError");u(this,r,"f").set(e.name,{tool:e,exposedTo:void 0,pageLevel:!0})}u(this,o,"m",l).call(this)}async getTools(e={}){e.fromOrigins;const t="undefined"!=typeof location?location.origin:void 0;return[...u(this,r,"f").values()].map(({tool:e})=>{const n={name:e.name,description:e.description,inputSchema:structuredClone(e.inputSchema??f)};return e.annotations&&(n.annotations=structuredClone(e.annotations)),t&&(n.origin=t),n})}async executeTool(e,t,o={}){const i=u(this,r,"f").get(e);if(!i)throw d(`No tool registered with name "${e}".`,"NotFoundError");if(o.signal?.aborted)throw d("Tool execution was aborted.","AbortError");let a;if(null==t||""===t)a={};else if("string"==typeof t)try{a=JSON.parse(t)}catch(t){throw new TypeError(`executeTool("${e}"): input is not valid JSON: ${t.message}`)}else a=t;if(null===a||"object"!=typeof a||Array.isArray(a))throw new TypeError(`executeTool("${e}"): input must be a JSON object.`);const s=n(a,i.tool.inputSchema??f);if(s.length>0){const t=s.map(e=>`${e.path}: ${e.message}`).join("; ");throw new TypeError(`executeTool("${e}"): invalid input — ${t}`)}const l=new AbortController,c=o.signal,p=()=>l.abort(c?.reason);c?.addEventListener("abort",p,{once:!0});try{const t=await i.tool.execute(a,{signal:l.signal,toolName:e});if(c?.aborted)throw d("Tool execution was aborted.","AbortError");return function(e){return null==e?{content:[]}:"string"==typeof e?{content:[{type:"text",text:e}]}:"object"==typeof e&&Array.isArray(e.content)?e:{content:[{type:"text",text:JSON.stringify(e)}]}}(t)}catch(e){if(c?.aborted||e instanceof Error&&"AbortError"===e.name)throw d("Tool execution was aborted.","AbortError");return function(e){return{isError:!0,content:[{type:"text",text:e instanceof Error?`${e.name}: ${e.message}`:String(e)}]}}(e)}finally{c?.removeEventListener("abort",p)}}unregisterTool(e){const t=u(this,o,"m",s).call(this,e);return t&&u(this,o,"m",l).call(this),t}clearContext(){if(0!==u(this,r,"f").size){for(const e of[...u(this,r,"f").keys()])u(this,o,"m",s).call(this,e);u(this,o,"m",l).call(this)}}}function h(e,t){Object.defineProperty(e,"modelContext",{value:t,writable:!1,enumerable:!0,configurable:!0})}r=new WeakMap,i=new WeakMap,a=new WeakMap,o=new WeakSet,s=function(e,t,n=!1){const i=u(this,r,"f").get(e);return!!i&&((!t||i===t)&&(i.abortListener&&i.abortListener.signal.removeEventListener("abort",i.abortListener.listener),u(this,r,"f").delete(e),n&&u(this,o,"m",l).call(this),!0))},l=function(){u(this,a,"f")||(c(this,a,!0,"f"),queueMicrotask(()=>{c(this,a,!1,"f"),this.dispatchEvent(new Event("toolchange"))}))};const v=["AskAction","SearchAction","SubscribeAction","RegisterAction","BuyAction","OrderAction","AddAction","ScheduleAction","ReserveAction","RsvpAction","ApplyAction","QuoteAction","DownloadAction","ReviewAction","CommentAction","TrackAction","CommunicateAction","InteractAction"];function g(e){return v.includes(e)}const y="https://nxis.ai/ns#";function b(e,t,n){var o;return null!==(o=e[t])&&void 0!==o?o:e[n]}function w(e,t){return b(e,t,"https://schema.org/"+t)}function x(e,t){const n=w(e,t);return"string"==typeof n?n:null}function $(e,t,n){const o=b(e,t,n);return Array.isArray(o)?o:[]}function A(e=("undefined"!=typeof document?document:void 0)){const t=[];if(!e)return t;const n=e.querySelectorAll('script[type="application/ld+json"]');for(const e of Array.from(n)){const n=e.textContent;if(!n)continue;let o;try{o=JSON.parse(n)}catch(e){continue}const r=E(o);for(const e of r){const n=T(e);n&&t.push(n)}}return t}function E(e){if(Array.isArray(e)){const t=[];for(const n of e)t.push(...E(n));return t}if(e&&"object"==typeof e){const t=e;if(Array.isArray(t["@graph"])){const e=[];for(const n of t["@graph"])e.push(...E(n));return e}return[t]}return[]}function T(e){var t;if(!e||"object"!=typeof e)return null;const n=e,o="string"==typeof n["@type"]?n["@type"]:null;if(!o)return null;if(!o.endsWith("Action")&&!g(o))return null;const r="string"==typeof n["@id"]?n["@id"]:null,i=x(n,"name"),a=function(e){var t,n;if(!e||"object"!=typeof e)return null;const o=e,r=null!==(n=null===(t=x(o,"httpMethod"))||void 0===t?void 0:t.toUpperCase())&&void 0!==n?n:null;if(!r)return null;const i={"@type":"EntryPoint",httpMethod:r},a=x(o,"encodingType");null!==a&&(i.encodingType=a);const s=x(o,"urlTemplate");null!==s&&(i.urlTemplate=s);const l=b(o,"nxis:targetKind",y+"targetKind");"selfPage"!==l&&"clientSide"!==l||(i["nxis:targetKind"]=l);const u=b(o,"nxis:pageUrl",y+"pageUrl");"string"==typeof u&&(i["nxis:pageUrl"]=u);const c=b(o,"nxis:jsHandled",y+"jsHandled");!0===c&&(i["nxis:jsHandled"]=!0);return i}(w(n,"target"));if(!r||!i||!a)return null;const s=$(n,"nxis:input",y+"input").map(L).filter(e=>null!==e),l=null!==(t=x(n,"description"))&&void 0!==t?t:function(e,t,n){const o=e.replace(/^.*[/#]/,"").replace(/Action$/,"").toLowerCase(),r=n.map(e=>e.valueName).join(", ");if(0===n.length)return`Trigger the ${o} action "${t}".`;return`Fill the ${o} form "${t}" with fields: ${r}.`}(o,i,s);return{"@context":n["@context"],"@type":o,"@id":r,name:i,description:l,target:a,input:s.length>0?s:void 0,"nxis:extractedAt":b(n,"nxis:extractedAt",y+"extractedAt")}}function L(e){if(!e||"object"!=typeof e)return null;const t=e,n=x(t,"valueName");if(!n)return null;const o=b(t,"nxis:valueType",y+"valueType"),r={"@type":"PropertyValueSpecification",valueName:n,"nxis:valueType":"string"==typeof o?o:"string"},i=x(t,"description");null!==i&&(r.description=i),!0===w(t,"valueRequired")&&(r.valueRequired=!0);const a=x(t,"defaultValue");null!==a&&(r.defaultValue=a);const s=e=>{const n=w(t,e);return"number"==typeof n?n:null},l=s("valueMinLength");null!==l&&(r.valueMinLength=l);const u=s("valueMaxLength");null!==u&&(r.valueMaxLength=u);const c=s("minValue");null!==c&&(r.minValue=c);const f=s("maxValue");null!==f&&(r.maxValue=f);const d=s("stepValue");null!==d&&(r.stepValue=d);const p=x(t,"valuePattern");null!==p&&(r.valuePattern=p),!0===w(t,"multipleValues")&&(r.multipleValues=!0),!0===w(t,"readonlyValue")&&(r.readonlyValue=!0);const m=$(t,"nxis:valueOption",y+"valueOption");if(m.length>0){const e=m.filter(e=>e&&"object"==typeof e&&null!==x(e,"value")).map(e=>{var t;const n=e;return{"@type":"nxis:ValueOption",value:x(n,"value"),name:null!==(t=x(n,"name"))&&void 0!==t?t:void 0}});e.length>0&&(r["nxis:valueOption"]=e)}return r}function N(e){switch(e){case"string":case"date":case"file":default:return"string";case"number":return"number";case"integer":return"integer";case"boolean":return"boolean"}}function k(e){var t;const n={},o=[],r=null!==(t=e.input)&&void 0!==t?t:[];for(const e of r){const t=j(e);if(e.multipleValues){const o={type:"array",items:t};void 0!==e.valueMinLength&&(o.minItems=e.valueMinLength,delete t.minLength),void 0!==e.valueMaxLength&&(o.maxItems=e.valueMaxLength,delete t.maxLength),e.description&&(o.description=e.description,delete t.description),n[e.valueName]=o}else n[e.valueName]=t;e.valueRequired&&o.push(e.valueName)}const i={type:"object",properties:n};return o.length>0&&(i.required=o),i}function j(e){const t={type:N(e["nxis:valueType"])},n=function(e){if("date"===e)return"date"}(e["nxis:valueType"]);if(n&&(t.format=n),e.description&&(t.description=e.description),void 0!==e.defaultValue&&(t.default=function(e,t){switch(t){case"number":case"integer":{const t=Number(e);return isNaN(t)?e:t}case"boolean":return"true"===e||"1"===e;default:return e}}(e.defaultValue,e["nxis:valueType"])),void 0!==e.valueMinLength&&(t.minLength=e.valueMinLength),void 0!==e.valueMaxLength&&(t.maxLength=e.valueMaxLength),e.valuePattern){const n=e.valuePattern,o=n.startsWith("^")&&n.endsWith("$")?n:`^${n}$`;t.pattern=o}void 0!==e.minValue&&(t.minimum=e.minValue),void 0!==e.maxValue&&(t.maximum=e.maxValue),void 0!==e.stepValue&&(t.multipleOf=e.stepValue),e.readonlyValue&&(t.readOnly=!0);const o=e["nxis:valueOption"];if(o&&o.length>0){t.enum=o.map(e=>e.value);if(o.some(e=>void 0!==e.name&&e.name!==e.value)){const e=o.filter(e=>e.name&&e.name!==e.value).map(e=>`${e.value} = "${e.name}"`).join(", "),n=t.description?`${t.description}. `:"";t.description=`${n}Values: ${e}`}}return t}function S(e){const t=Array.from(document.querySelectorAll("form"));if(0===t.length)return null;const n=function(e){return e.input?e.input.map(e=>e.valueName):[]}(e);let o;if(o=!e.target.urlTemplate?t:function(e,t,n){const o=function(e){const t=e.replace(/\{[^}]*\}/g,"");try{return new URL(t,window.location.href)}catch(e){return null}}(t);return e.filter(e=>{if((e.method||"GET").toUpperCase()!==n.toUpperCase())return!1;if(!o)return!0;const t=function(e){const t=e.getAttribute("action");if(!t||"#"===t||t.startsWith("#")||""===t)return window.location.href.split("#")[0].split("?")[0];if(t.startsWith("javascript:"))return window.location.href.split("#")[0].split("?")[0];try{return new URL(t,window.location.href).href}catch(e){return t}}(e);return function(e,t){let n;try{n=new URL(e,window.location.href)}catch(e){return!1}if(n.origin!==t.origin)return!1;const o=n.pathname.replace(/\/+$/,""),r=t.pathname.replace(/\/+$/,"");return""===r||(o===r||o.startsWith(r+"/")||r.startsWith(o+"/"))}(t,o)})}(t,e.target.urlTemplate,e.target.httpMethod),0===o.length&&(o=t),1===o.length)return o[0];const r=o.map(e=>({form:e,controlNames:O(e)})).filter(({controlNames:e})=>n.every(t=>e.has(t)));return 0===r.length?(console.warn(`[nxis/webmcp] No field-set match for action "${e.name}". Expected fields: [${n.join(", ")}]. Falling back to first candidate.`),o[0]):1===r.length?r[0].form:(r.sort((e,t)=>e.controlNames.size-t.controlNames.size),r[0].controlNames.size===r[1].controlNames.size?(console.warn(`[nxis/webmcp] Ambiguous form match for action "${e.name}". ${r.length} forms have identical field sets. Returning null.`),null):r[0].form)}function O(e){const t=new Set,n=e.elements;for(let e=0;e<n.length;e++){const o=n[e];o.name&&t.add(o.name)}return t}function C(e,t){var n;return(null!==(n=e.input)&&void 0!==n?n:[]).map(e=>function(e,t){var n;const o=t=>({valueName:e.valueName,pvs:e,strategy:t}),r=function(e,t){const n=[],o=e.elements;for(let e=0;e<o.length;e++){const r=o[e];r.name===t&&n.push(r)}return n}(t,e.valueName),i=null!==(n=r[0])&&void 0!==n?n:null;if(!i)return o({kind:"skip",reason:`No control found with name="${e.valueName}"`});if(i instanceof HTMLInputElement&&"radio"===i.type){const t=r.filter(e=>e instanceof HTMLInputElement&&"radio"===e.type&&!e.disabled);return 0===t.length?o({kind:"skip",reason:`Radio group "${e.valueName}" has no enabled options`}):o({kind:"radio",name:e.valueName,elements:t})}if(i instanceof HTMLInputElement&&"checkbox"===i.type){const t=r.filter(e=>e instanceof HTMLInputElement&&"checkbox"===e.type&&!e.disabled);return 0===t.length?o({kind:"skip",reason:`Checkbox "${e.valueName}" is disabled`}):t.length>1?o({kind:"checkboxGroup",name:e.valueName,elements:t}):o({kind:"checked",element:t[0]})}if(!0===i.readOnly||null!==i.getAttribute("readonly"))return o({kind:"skip",reason:`Control "${e.valueName}" is readonly in the DOM`});if(i.disabled)return o({kind:"skip",reason:`Control "${e.valueName}" is disabled`});if(i instanceof HTMLSelectElement){const e=[];for(let t=0;t<i.options.length;t++){const n=i.options[t];n.value&&e.push(n.value)}return o(i.multiple?{kind:"multiSelect",element:i,allowedValues:e}:{kind:"select",element:i,allowedValues:e})}if(i instanceof HTMLTextAreaElement)return o({kind:"value",element:i});if(i instanceof HTMLInputElement)return o({kind:"value",element:i});return o({kind:"skip",reason:`Unsupported control type for "${e.valueName}"`})}(e,t))}async function M(e,t){var n,o;const r=function(e){const t=e.target["nxis:pageUrl"];if(!t)return null;try{const n=new URL(t),o=new URL(window.location.href);if(n.origin!==o.origin||n.pathname!==o.pathname)return`Action "${e.name}" was extracted from ${n.origin}${n.pathname} but the current page is ${o.origin}${o.pathname}. The form may have moved or changed.`}catch(e){return null}return null}(e),i=S(e);if(!i){const t=`Form not found for action "${e.name}". The page may have changed since the tool was registered.`,n={success:!1,submitted:!1,message:r?`Warning: ${r} ${t}`:t,filled:[],skipped:[]};return r&&(n.stale=!0),JSON.stringify(n)}const a=C(e,i),s=null!==(n=e.input)&&void 0!==n?n:[],l=[],u=[];let c=!1;for(const e of s)!e.valueRequired||void 0!==t[e.valueName]&&null!==t[e.valueName]||(c=!0,u.push({field:e.valueName,reason:`Required field '${e.valueName}' was not provided. Expected type: ${e["nxis:valueType"]}.`}));for(const e of a){const n=t[e.valueName];if(null==n){u.some(t=>t.field===e.valueName)||u.push({field:e.valueName,reason:"No value provided (optional field)."});continue}const o=q(e,n);!1===o.ok?u.push({field:e.valueName,reason:o.reason}):l.push(e.valueName)}await new Promise(e=>setTimeout(e,0));for(const e of a)if("value"===e.strategy.kind&&l.includes(e.valueName)){const n=e.strategy.element,r=I(null!==(o=t[e.valueName])&&void 0!==o?o:"");n.value!==r&&(u.push({field:e.valueName,reason:`Value was set to "${r}" but the DOM now shows "${n.value}". A framework may have reverted it.`}),l.splice(l.indexOf(e.valueName),1))}const f=l.length>0&&!c;let d=!1;f&&(d=function(e){try{return"function"==typeof e.requestSubmit?e.requestSubmit():e.submit(),!0}catch(e){return console.warn("[nxis/webmcp] Form submission failed:",e),!1}}(i));const p={success:f,submitted:d,message:V(l,u,d,r),filled:l,skipped:u};return r&&(p.stale=!0),JSON.stringify(p)}function V(e,t,n,o){const r=[];if(o&&r.push(`Warning: ${o}`),0===e.length&&0===t.length)return r.push("No fields were filled. Verify field names match the input schema."),r.join(" ");if(e.length>0&&r.push(`Filled ${e.length} field(s): ${e.join(", ")}.`),t.length>0){const e=t.map(e=>`${e.field} (${e.reason})`).join("; ");r.push(`Skipped ${t.length}: ${e}`)}return n?r.push("Form submitted."):e.length>0&&r.push("Form was NOT submitted due to missing required fields or fill errors."),r.join(" ")}function q(e,t){const{strategy:n}=e;switch(n.kind){case"skip":return{ok:!1,reason:n.reason};case"value":return function(e,t){var n;const o=null===(n=Object.getOwnPropertyDescriptor(e instanceof HTMLTextAreaElement?HTMLTextAreaElement.prototype:HTMLInputElement.prototype,"value"))||void 0===n?void 0:n.set;o?o.call(e,t):e.value=t;return e.dispatchEvent(new Event("input",{bubbles:!0})),e.dispatchEvent(new Event("change",{bubbles:!0})),{ok:!0}}(n.element,I(t));case"checked":return function(e,t){return e.checked=function(e){if("boolean"==typeof e)return e;if("number"==typeof e)return 0!==e;if("string"==typeof e){const t=e.trim().toLowerCase();return""!==t&&"false"!==t&&"0"!==t&&"off"!==t&&"no"!==t}return Boolean(e)}(t),e.dispatchEvent(new Event("change",{bubbles:!0})),{ok:!0}}(n.element,t);case"radio":return function(e,t){var n,o;const r=String(t),i=null!==(o=null!==(n=e.find(e=>e.value===r))&&void 0!==n?n:e.find(e=>e.value.toLowerCase()===r.toLowerCase()))&&void 0!==o?o:e.find(e=>function(e){var t;if(e.labels&&e.labels.length>0)return(null!==(t=e.labels[0].textContent)&&void 0!==t?t:"").trim();return e.value}(e).toLowerCase()===r.toLowerCase());if(!i){const t=e.map(e=>e.value).join(", ");return{ok:!1,reason:`Value "${r}" is not an allowed option for radio "${e[0].name}". Allowed: [${t}].`}}return i.checked=!0,i.dispatchEvent(new Event("input",{bubbles:!0})),i.dispatchEvent(new Event("change",{bubbles:!0})),{ok:!0}}(n.elements,t);case"checkboxGroup":return function(e,t){const n=(Array.isArray(t)?t:[t]).map(e=>String(e)),o=n.map(e=>e.toLowerCase());let r=!1;for(const t of e){const e=n.includes(t.value)||o.includes(t.value.toLowerCase());t.checked=e,e&&(r=!0),t.dispatchEvent(new Event("change",{bubbles:!0}))}if(!r){const t=e.map(e=>e.value).join(", ");return{ok:!1,reason:`None of [${n.join(", ")}] match checkbox group "${e[0].name}". Allowed: [${t}].`}}return{ok:!0}}(n.elements,t);case"select":return function(e,t,n){const o=P(e,t,n);if(null===o)return{ok:!1,reason:`Value "${t}" is not an allowed option for "${e.name}". Allowed: [${n.join(", ")}].`};return e.value=o,e.dispatchEvent(new Event("input",{bubbles:!0})),e.dispatchEvent(new Event("change",{bubbles:!0})),{ok:!0}}(n.element,String(t),n.allowedValues);case"multiSelect":return function(e,t,n){const o=(Array.isArray(t)?t:[t]).map(e=>String(e)),r=new Set,i=[];for(const t of o){const o=P(e,t,n);null===o?i.push(t):r.add(o)}if(0===r.size)return{ok:!1,reason:`None of [${o.join(", ")}] are allowed options for "${e.name}". Allowed: [${n.join(", ")}].`};for(const t of Array.from(e.options))t.selected=r.has(t.value);if(e.dispatchEvent(new Event("input",{bubbles:!0})),e.dispatchEvent(new Event("change",{bubbles:!0})),i.length>0)return{ok:!1,reason:`Selected [${Array.from(r).join(", ")}] but [${i.join(", ")}] are not allowed options for "${e.name}". Allowed: [${n.join(", ")}].`};return{ok:!0}}(n.element,t,n.allowedValues);default:return{ok:!1,reason:`Unsupported fill strategy for field "${e.valueName}".`}}}function I(e){return Array.isArray(e)?e.map(e=>String(e)).join(","):String(e)}function P(e,t,n){if(n.includes(t))return t;const o=n.find(e=>e.toLowerCase()===t.toLowerCase());if(o)return o;for(const n of Array.from(e.options))if(n.text.toLowerCase()===t.toLowerCase())return n.value;return null}function R(e){var t;const n=!1!==(null==e?void 0:e.observe),o=null!==(t=null==e?void 0:e.doc)&&void 0!==t?t:"undefined"!=typeof document?document:void 0;if(!o)return console.warn("[nxis/webmcp] No document available (not running in a browser). Tools will not be registered."),()=>{};!function(e={}){const{force:t=!1,installNavigatorAlias:n=!0}=e,o="undefined"!=typeof document&&document.modelContext||"undefined"!=typeof navigator&&navigator.modelContext||void 0;if(o&&!t)return o;const r=new m;"undefined"!=typeof document&&h(document,r),n&&"undefined"!=typeof navigator&&h(navigator,r)}();const r=function(e){var t,n;const o=null!==(n=null===(t=e.defaultView)||void 0===t?void 0:t.navigator)&&void 0!==n?n:"undefined"!=typeof navigator?navigator:void 0;return e.modelContext||(null==o?void 0:o.modelContext)||null}(o);if(!r)return console.warn("[nxis/webmcp] WebMCP API not available — document.modelContext is undefined. Tools will not be registered."),()=>{};const i=new AbortController;(null==e?void 0:e.signal)&&(e.signal.aborted?i.abort():e.signal.addEventListener("abort",()=>i.abort()));const a={ids:new Set,names:new Set};H(o,r,i,a);let s=null;return n&&(s=function(e,t,n,o){const r=new MutationObserver(r=>{(function(e){for(const t of e)for(const e of Array.from(t.addedNodes)){if(W(e))return!0;if(e instanceof Element&&e.querySelector('script[type="application/ld+json"]'))return!0}return!1})(r)&&H(e,t,n,o)});return n.signal.addEventListener("abort",()=>r.disconnect()),r.observe(e.documentElement,{childList:!0,subtree:!0}),r}(o,r,i,a)),()=>{i.abort(),s&&(s.disconnect(),s=null)}}function H(e,t,n,o){const r=A(e);let i=0;for(const e of r)if(!o.ids.has(e["@id"]))try{U(e,t,n,o),o.ids.add(e["@id"]),i++}catch(t){console.warn(`[nxis/webmcp] Failed to register tool for action "${e.name}":`,t)}i>0&&console.info(`[nxis/webmcp] Registered ${i} tool(s) (${o.ids.size} total) from ${r.length} action(s).`)}function U(e,t,n,o){const r=k(e),i=function(e,t){if(!t.has(e))return e;for(let n=2;;n++){const o=`_${n}`,r=e.slice(0,64-o.length)+o;if(!t.has(r))return r}}(function(e){return e.toLowerCase().replace(/[\s-]+/g,"_").replace(/[^a-z0-9_]/g,"_").replace(/_+/g,"_").replace(/^_|_$/g,"").slice(0,64)||"unnamed_action"}(e.name),o.names);t.registerTool({name:i,description:e.description,inputSchema:r,annotations:{readOnlyHint:!1,untrustedContentHint:!0,"ai.nxis/actionId":e["@id"]},execute:async t=>M(e,t)},{signal:n.signal}),o.names.add(i)}function W(e){return e instanceof HTMLScriptElement&&"application/ld+json"===e.type}export{v as ACTION_SUBTYPES,k as buildInputSchema,g as isActionType,A as readActions,R as registerActions};
|
package/package.json
CHANGED
package/src/webmcp/register.ts
CHANGED
|
@@ -188,6 +188,8 @@ function registerSingleAction(
|
|
|
188
188
|
annotations: {
|
|
189
189
|
readOnlyHint: false,
|
|
190
190
|
untrustedContentHint: true,
|
|
191
|
+
// Which action this is, independent of the name it was given.
|
|
192
|
+
'ai.nxis/actionId': action['@id'],
|
|
191
193
|
},
|
|
192
194
|
execute: async (args: Record<string, unknown>) => {
|
|
193
195
|
return executeAction(action, args);
|
package/src/webmcp/types.ts
CHANGED
|
@@ -27,6 +27,15 @@ export interface ToolAnnotations {
|
|
|
27
27
|
* Always `true` for NxisAI tools — we infer from content we don't control.
|
|
28
28
|
*/
|
|
29
29
|
untrustedContentHint?: boolean;
|
|
30
|
+
/**
|
|
31
|
+
* The `@id` of the Action this tool was generated from.
|
|
32
|
+
*
|
|
33
|
+
* A tool's name comes from the action's name and may be suffixed to avoid a
|
|
34
|
+
* collision, so it does not identify the action on its own. A client holding
|
|
35
|
+
* the same action from elsewhere — the site's MCP server, say — matches the
|
|
36
|
+
* two by this.
|
|
37
|
+
*/
|
|
38
|
+
'ai.nxis/actionId'?: string;
|
|
30
39
|
}
|
|
31
40
|
|
|
32
41
|
/** The shape passed to `modelContext.registerTool()`. */
|