hypha-debugger 0.2.7 → 0.2.8
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.
|
@@ -52,7 +52,7 @@
|
|
|
52
52
|
\**************************************************************************/(e,t,n)=>{function r(e){return e instanceof Uint8Array?e:ArrayBuffer.isView(e)?new Uint8Array(e.buffer,e.byteOffset,e.byteLength):e instanceof ArrayBuffer?new Uint8Array(e):Uint8Array.from(e)}function o(e){if(e instanceof ArrayBuffer)return new DataView(e);var t=r(e);return new DataView(t.buffer,t.byteOffset,t.byteLength)}n.r(t),n.d(t,{createDataView:()=>o,ensureUint8Array:()=>r})},"./node_modules/@msgpack/msgpack/dist.es5+esm/utils/utf8.mjs":
|
|
53
53
|
/*!*******************************************************************!*\
|
|
54
54
|
!*** ./node_modules/@msgpack/msgpack/dist.es5+esm/utils/utf8.mjs ***!
|
|
55
|
-
\*******************************************************************/(e,t,n)=>{n.r(t),n.d(t,{TEXT_DECODER_THRESHOLD:()=>m,TEXT_ENCODER_THRESHOLD:()=>h,utf8Count:()=>c,utf8DecodeJs:()=>_,utf8DecodeTD:()=>g,utf8EncodeJs:()=>l,utf8EncodeTE:()=>u});var r,o,i,s=n(/*! ./int.mjs */"./node_modules/@msgpack/msgpack/dist.es5+esm/utils/int.mjs"),a=("undefined"==typeof process||"never"!==(null===(r=null===process||void 0===process?void 0:process.env)||void 0===r?void 0:r.TEXT_ENCODING))&&"undefined"!=typeof TextEncoder&&"undefined"!=typeof TextDecoder;function c(e){for(var t=e.length,n=0,r=0;r<t;){var o=e.charCodeAt(r++);if(4294967168&o)if(4294965248&o){if(o>=55296&&o<=56319&&r<t){var i=e.charCodeAt(r);56320==(64512&i)&&(++r,o=((1023&o)<<10)+(1023&i)+65536)}n+=4294901760&o?4:3}else n+=2;else n++}return n}function l(e,t,n){for(var r=e.length,o=n,i=0;i<r;){var s=e.charCodeAt(i++);if(4294967168&s){if(4294965248&s){if(s>=55296&&s<=56319&&i<r){var a=e.charCodeAt(i);56320==(64512&a)&&(++i,s=((1023&s)<<10)+(1023&a)+65536)}4294901760&s?(t[o++]=s>>18&7|240,t[o++]=s>>12&63|128,t[o++]=s>>6&63|128):(t[o++]=s>>12&15|224,t[o++]=s>>6&63|128)}else t[o++]=s>>6&31|192;t[o++]=63&s|128}else t[o++]=s}}var d=a?new TextEncoder:void 0,h=a?"undefined"!=typeof process&&"force"!==(null===(o=null===process||void 0===process?void 0:process.env)||void 0===o?void 0:o.TEXT_ENCODING)?200:0:s.UINT32_MAX,u=(null==d?void 0:d.encodeInto)?function(e,t,n){d.encodeInto(e,t.subarray(n))}:function(e,t,n){t.set(d.encode(e),n)},p=4096;function _(e,t,n){for(var r=t,o=r+n,i=[],s="";r<o;){var a=e[r++];if(128&a)if(192==(224&a)){var c=63&e[r++];i.push((31&a)<<6|c)}else if(224==(240&a)){c=63&e[r++];var l=63&e[r++];i.push((31&a)<<12|c<<6|l)}else if(240==(248&a)){var d=(7&a)<<18|(c=63&e[r++])<<12|(l=63&e[r++])<<6|63&e[r++];d>65535&&(d-=65536,i.push(d>>>10&1023|55296),d=56320|1023&d),i.push(d)}else i.push(a);else i.push(a);i.length>=p&&(s+=String.fromCharCode.apply(String,i),i.length=0)}return i.length>0&&(s+=String.fromCharCode.apply(String,i)),s}var f=a?new TextDecoder:null,m=a?"undefined"!=typeof process&&"force"!==(null===(i=null===process||void 0===process?void 0:process.env)||void 0===i?void 0:i.TEXT_DECODER)?200:0:s.UINT32_MAX;function g(e,t,n){var r=e.subarray(t,t+n);return f.decode(r)}}},__webpack_module_cache__={},inProgress,dataWebpackPrefix;function __webpack_require__(e){var t=__webpack_module_cache__[e];if(void 0!==t)return t.exports;var n=__webpack_module_cache__[e]={exports:{}};return __webpack_modules__[e](n,n.exports,__webpack_require__),n.exports}__webpack_require__.m=__webpack_modules__,__webpack_require__.d=(e,t)=>{for(var n in t)__webpack_require__.o(t,n)&&!__webpack_require__.o(e,n)&&Object.defineProperty(e,n,{enumerable:!0,get:t[n]})},__webpack_require__.f={},__webpack_require__.e=e=>Promise.all(Object.keys(__webpack_require__.f).reduce((t,n)=>(__webpack_require__.f[n](e,t),t),[])),__webpack_require__.u=e=>e+".hypha-rpc-websocket.js",__webpack_require__.g=function(){if("object"==typeof globalThis)return globalThis;try{return this||new Function("return this")()}catch(e){if("object"==typeof window)return window}}(),__webpack_require__.o=(e,t)=>Object.prototype.hasOwnProperty.call(e,t),inProgress={},dataWebpackPrefix="hyphaWebsocketClient:",__webpack_require__.l=(e,t,n,r)=>{if(inProgress[e])inProgress[e].push(t);else{var o,i;if(void 0!==n)for(var s=document.getElementsByTagName("script"),a=0;a<s.length;a++){var c=s[a];if(c.getAttribute("src")==e||c.getAttribute("data-webpack")==dataWebpackPrefix+n){o=c;break}}o||(i=!0,(o=document.createElement("script")).charset="utf-8",o.timeout=120,__webpack_require__.nc&&o.setAttribute("nonce",__webpack_require__.nc),o.setAttribute("data-webpack",dataWebpackPrefix+n),o.src=e),inProgress[e]=[t];var l=(t,n)=>{o.onerror=o.onload=null,clearTimeout(d);var r=inProgress[e];if(delete inProgress[e],o.parentNode&&o.parentNode.removeChild(o),r&&r.forEach(e=>e(n)),t)return t(n)},d=setTimeout(l.bind(null,void 0,{type:"timeout",target:o}),12e4);o.onerror=l.bind(null,o.onerror),o.onload=l.bind(null,o.onload),i&&document.head.appendChild(o)}},__webpack_require__.r=e=>{"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},(()=>{var e;__webpack_require__.g.importScripts&&(e=__webpack_require__.g.location+"");var t=__webpack_require__.g.document;if(!e&&t&&(t.currentScript&&(e=t.currentScript.src),!e)){var n=t.getElementsByTagName("script");if(n.length)for(var r=n.length-1;r>-1&&(!e||!/^http(s?):/.test(e));)e=n[r--].src}if(!e)throw new Error("Automatic publicPath is not supported in this browser");e=e.replace(/#.*$/,"").replace(/\?.*$/,"").replace(/\/[^\/]+$/,"/"),__webpack_require__.p=e})(),(()=>{var e={hyphaWebsocketClient:0};__webpack_require__.f.j=(t,n)=>{var r=__webpack_require__.o(e,t)?e[t]:void 0;if(0!==r)if(r)n.push(r[2]);else{var o=new Promise((n,o)=>r=e[t]=[n,o]);n.push(r[2]=o);var i=__webpack_require__.p+__webpack_require__.u(t),s=new Error;__webpack_require__.l(i,n=>{if(__webpack_require__.o(e,t)&&(0!==(r=e[t])&&(e[t]=void 0),r)){var o=n&&("load"===n.type?"missing":n.type),i=n&&n.target&&n.target.src;s.message="Loading chunk "+t+" failed.\n("+o+": "+i+")",s.name="ChunkLoadError",s.type=o,s.request=i,r[1](s)}},"chunk-"+t,t)}};var t=(t,n)=>{var r,o,[i,s,a]=n,c=0;if(i.some(t=>0!==e[t])){for(r in s)__webpack_require__.o(s,r)&&(__webpack_require__.m[r]=s[r]);a&&a(__webpack_require__)}for(t&&t(n);c<i.length;c++)o=i[c],__webpack_require__.o(e,o)&&e[o]&&e[o][0](),e[o]=0},n=
|
|
55
|
+
\*******************************************************************/(e,t,n)=>{n.r(t),n.d(t,{TEXT_DECODER_THRESHOLD:()=>m,TEXT_ENCODER_THRESHOLD:()=>h,utf8Count:()=>c,utf8DecodeJs:()=>_,utf8DecodeTD:()=>g,utf8EncodeJs:()=>l,utf8EncodeTE:()=>u});var r,o,i,s=n(/*! ./int.mjs */"./node_modules/@msgpack/msgpack/dist.es5+esm/utils/int.mjs"),a=("undefined"==typeof process||"never"!==(null===(r=null===process||void 0===process?void 0:process.env)||void 0===r?void 0:r.TEXT_ENCODING))&&"undefined"!=typeof TextEncoder&&"undefined"!=typeof TextDecoder;function c(e){for(var t=e.length,n=0,r=0;r<t;){var o=e.charCodeAt(r++);if(4294967168&o)if(4294965248&o){if(o>=55296&&o<=56319&&r<t){var i=e.charCodeAt(r);56320==(64512&i)&&(++r,o=((1023&o)<<10)+(1023&i)+65536)}n+=4294901760&o?4:3}else n+=2;else n++}return n}function l(e,t,n){for(var r=e.length,o=n,i=0;i<r;){var s=e.charCodeAt(i++);if(4294967168&s){if(4294965248&s){if(s>=55296&&s<=56319&&i<r){var a=e.charCodeAt(i);56320==(64512&a)&&(++i,s=((1023&s)<<10)+(1023&a)+65536)}4294901760&s?(t[o++]=s>>18&7|240,t[o++]=s>>12&63|128,t[o++]=s>>6&63|128):(t[o++]=s>>12&15|224,t[o++]=s>>6&63|128)}else t[o++]=s>>6&31|192;t[o++]=63&s|128}else t[o++]=s}}var d=a?new TextEncoder:void 0,h=a?"undefined"!=typeof process&&"force"!==(null===(o=null===process||void 0===process?void 0:process.env)||void 0===o?void 0:o.TEXT_ENCODING)?200:0:s.UINT32_MAX,u=(null==d?void 0:d.encodeInto)?function(e,t,n){d.encodeInto(e,t.subarray(n))}:function(e,t,n){t.set(d.encode(e),n)},p=4096;function _(e,t,n){for(var r=t,o=r+n,i=[],s="";r<o;){var a=e[r++];if(128&a)if(192==(224&a)){var c=63&e[r++];i.push((31&a)<<6|c)}else if(224==(240&a)){c=63&e[r++];var l=63&e[r++];i.push((31&a)<<12|c<<6|l)}else if(240==(248&a)){var d=(7&a)<<18|(c=63&e[r++])<<12|(l=63&e[r++])<<6|63&e[r++];d>65535&&(d-=65536,i.push(d>>>10&1023|55296),d=56320|1023&d),i.push(d)}else i.push(a);else i.push(a);i.length>=p&&(s+=String.fromCharCode.apply(String,i),i.length=0)}return i.length>0&&(s+=String.fromCharCode.apply(String,i)),s}var f=a?new TextDecoder:null,m=a?"undefined"!=typeof process&&"force"!==(null===(i=null===process||void 0===process?void 0:process.env)||void 0===i?void 0:i.TEXT_DECODER)?200:0:s.UINT32_MAX;function g(e,t,n){var r=e.subarray(t,t+n);return f.decode(r)}}},__webpack_module_cache__={},inProgress,dataWebpackPrefix;function __webpack_require__(e){var t=__webpack_module_cache__[e];if(void 0!==t)return t.exports;var n=__webpack_module_cache__[e]={exports:{}};return __webpack_modules__[e](n,n.exports,__webpack_require__),n.exports}__webpack_require__.m=__webpack_modules__,__webpack_require__.d=(e,t)=>{for(var n in t)__webpack_require__.o(t,n)&&!__webpack_require__.o(e,n)&&Object.defineProperty(e,n,{enumerable:!0,get:t[n]})},__webpack_require__.f={},__webpack_require__.e=e=>Promise.all(Object.keys(__webpack_require__.f).reduce((t,n)=>(__webpack_require__.f[n](e,t),t),[])),__webpack_require__.u=e=>e+".hypha-rpc-websocket.js",__webpack_require__.g=function(){if("object"==typeof globalThis)return globalThis;try{return this||new Function("return this")()}catch(e){if("object"==typeof window)return window}}(),__webpack_require__.o=(e,t)=>Object.prototype.hasOwnProperty.call(e,t),inProgress={},dataWebpackPrefix="hyphaWebsocketClient:",__webpack_require__.l=(e,t,n,r)=>{if(inProgress[e])inProgress[e].push(t);else{var o,i;if(void 0!==n)for(var s=document.getElementsByTagName("script"),a=0;a<s.length;a++){var c=s[a];if(c.getAttribute("src")==e||c.getAttribute("data-webpack")==dataWebpackPrefix+n){o=c;break}}o||(i=!0,(o=document.createElement("script")).charset="utf-8",o.timeout=120,__webpack_require__.nc&&o.setAttribute("nonce",__webpack_require__.nc),o.setAttribute("data-webpack",dataWebpackPrefix+n),o.src=e),inProgress[e]=[t];var l=(t,n)=>{o.onerror=o.onload=null,clearTimeout(d);var r=inProgress[e];if(delete inProgress[e],o.parentNode&&o.parentNode.removeChild(o),r&&r.forEach(e=>e(n)),t)return t(n)},d=setTimeout(l.bind(null,void 0,{type:"timeout",target:o}),12e4);o.onerror=l.bind(null,o.onerror),o.onload=l.bind(null,o.onload),i&&document.head.appendChild(o)}},__webpack_require__.r=e=>{"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},(()=>{var e;__webpack_require__.g.importScripts&&(e=__webpack_require__.g.location+"");var t=__webpack_require__.g.document;if(!e&&t&&(t.currentScript&&(e=t.currentScript.src),!e)){var n=t.getElementsByTagName("script");if(n.length)for(var r=n.length-1;r>-1&&(!e||!/^http(s?):/.test(e));)e=n[r--].src}if(!e)throw new Error("Automatic publicPath is not supported in this browser");e=e.replace(/#.*$/,"").replace(/\?.*$/,"").replace(/\/[^\/]+$/,"/"),__webpack_require__.p=e})(),(()=>{var e={hyphaWebsocketClient:0};__webpack_require__.f.j=(t,n)=>{var r=__webpack_require__.o(e,t)?e[t]:void 0;if(0!==r)if(r)n.push(r[2]);else{var o=new Promise((n,o)=>r=e[t]=[n,o]);n.push(r[2]=o);var i=__webpack_require__.p+__webpack_require__.u(t),s=new Error;__webpack_require__.l(i,n=>{if(__webpack_require__.o(e,t)&&(0!==(r=e[t])&&(e[t]=void 0),r)){var o=n&&("load"===n.type?"missing":n.type),i=n&&n.target&&n.target.src;s.message="Loading chunk "+t+" failed.\n("+o+": "+i+")",s.name="ChunkLoadError",s.type=o,s.request=i,r[1](s)}},"chunk-"+t,t)}};var t=(t,n)=>{var r,o,[i,s,a]=n,c=0;if(i.some(t=>0!==e[t])){for(r in s)__webpack_require__.o(s,r)&&(__webpack_require__.m[r]=s[r]);a&&a(__webpack_require__)}for(t&&t(n);c<i.length;c++)o=i[c],__webpack_require__.o(e,o)&&e[o]&&e[o][0](),e[o]=0},n=globalThis.webpackChunkhyphaWebsocketClient=globalThis.webpackChunkhyphaWebsocketClient||[];n.forEach(t.bind(null,0)),n.push=t.bind(null,n.push.bind(n))})();var __webpack_exports__={};
|
|
56
56
|
/*!*********************************!*\
|
|
57
57
|
!*** ./src/websocket-client.js ***!
|
|
58
58
|
\*********************************/__webpack_require__.r(__webpack_exports__),__webpack_require__.d(__webpack_exports__,{API_VERSION:()=>_rpc_js__WEBPACK_IMPORTED_MODULE_0__.API_VERSION,HTTPStreamingRPCConnection:()=>_http_client_js__WEBPACK_IMPORTED_MODULE_4__.HTTPStreamingRPCConnection,LocalWebSocket:()=>LocalWebSocket,RPC:()=>_rpc_js__WEBPACK_IMPORTED_MODULE_0__.RPC,connectToServer:()=>connectToServer,connectToServerHTTP:()=>_http_client_js__WEBPACK_IMPORTED_MODULE_4__.connectToServerHTTP,getRTCService:()=>_webrtc_client_js__WEBPACK_IMPORTED_MODULE_3__.getRTCService,getRemoteService:()=>getRemoteService,getRemoteServiceHTTP:()=>_http_client_js__WEBPACK_IMPORTED_MODULE_4__.getRemoteServiceHTTP,loadRequirements:()=>_utils_index_js__WEBPACK_IMPORTED_MODULE_1__.loadRequirements,login:()=>login,logout:()=>logout,normalizeServerUrlHTTP:()=>_http_client_js__WEBPACK_IMPORTED_MODULE_4__.normalizeServerUrl,registerRTCService:()=>_webrtc_client_js__WEBPACK_IMPORTED_MODULE_3__.registerRTCService,schemaFunction:()=>_utils_schema_js__WEBPACK_IMPORTED_MODULE_2__.schemaFunction,setupLocalClient:()=>setupLocalClient});var _rpc_js__WEBPACK_IMPORTED_MODULE_0__=__webpack_require__(/*! ./rpc.js */"./src/rpc.js"),_utils_index_js__WEBPACK_IMPORTED_MODULE_1__=__webpack_require__(/*! ./utils/index.js */"./src/utils/index.js"),_utils_schema_js__WEBPACK_IMPORTED_MODULE_2__=__webpack_require__(/*! ./utils/schema.js */"./src/utils/schema.js"),_webrtc_client_js__WEBPACK_IMPORTED_MODULE_3__=__webpack_require__(/*! ./webrtc-client.js */"./src/webrtc-client.js"),_http_client_js__WEBPACK_IMPORTED_MODULE_4__=__webpack_require__(/*! ./http-client.js */"./src/http-client.js");const MAX_RETRY=1e6;class WebsocketRPCConnection{constructor(e,t,n,r,o=null,i=60,s=null,a=7200,c=null){(0,_utils_index_js__WEBPACK_IMPORTED_MODULE_1__.assert)(e&&t,"server_url and client_id are required"),this._server_url=e,this._client_id=t,this._workspace=n,this._token=r,this._reconnection_token=o,this._websocket=null,this._handle_message=null,this._handle_connected=null,this._handle_disconnected=null,this._timeout=i,this._WebSocketClass=s||WebSocket,this._closed=!1,this._legacy_auth=null,this.connection_info=null,this._enable_reconnect=!1,this._token_refresh_interval=a,this.manager_id=null,this._refresh_token_task=null,this._reconnect_timeouts=new Set,this._additional_headers=c}_cleanup(){this._refresh_token_task&&(clearInterval(this._refresh_token_task),this._refresh_token_task=null);for(const e of this._reconnect_timeouts)clearTimeout(e);this._reconnect_timeouts.clear()}on_message(e){(0,_utils_index_js__WEBPACK_IMPORTED_MODULE_1__.assert)(e,"handler is required"),this._handle_message=e}on_connected(e){this._handle_connected=e}on_disconnected(e){this._handle_disconnected=e}async _attempt_connection(e,t=!0){return new Promise((n,r)=>{this._legacy_auth=!1;const o=new this._WebSocketClass(e);o.binaryType="arraybuffer",o.onopen=()=>{console.info("WebSocket connection established"),n(o)},o.onerror=e=>{console.error("WebSocket connection error:",e),r(new Error(`WebSocket connection error: ${e}`))},o.onclose=o=>{1003===o.code&&t?(console.info("Received 1003 error, attempting connection with query parameters."),this._legacy_auth=!0,this._attempt_connection_with_query_params(e).then(n).catch(r)):this._handle_disconnected&&this._handle_disconnected(o.reason)}})}async _attempt_connection_with_query_params(e){const t=[];this._client_id&&t.push(`client_id=${encodeURIComponent(this._client_id)}`),this._workspace&&t.push(`workspace=${encodeURIComponent(this._workspace)}`),this._token&&t.push(`token=${encodeURIComponent(this._token)}`),this._reconnection_token&&t.push(`reconnection_token=${encodeURIComponent(this._reconnection_token)}`);const n=e+(t.length>0?`?${t.join("&")}`:"");return await this._attempt_connection(n,!1)}_establish_connection(){return new Promise((e,t)=>{this._websocket.onmessage=n=>{const r=n.data,o=JSON.parse(r);if("connection_info"!=o.type){if("error"==o.type){const e="ConnectionAbortedError: "+o.message;return console.error("Failed to connect, "+e),void t(new Error(e))}return console.error("ConnectionAbortedError: Unexpected message received from the server:",r),void t(new Error("ConnectionAbortedError: Unexpected message received from the server"))}this.connection_info=o,this._workspace&&(0,_utils_index_js__WEBPACK_IMPORTED_MODULE_1__.assert)(this.connection_info.workspace===this._workspace,`Connected to the wrong workspace: ${this.connection_info.workspace}, expected: ${this._workspace}`),this.connection_info.reconnection_token&&(this._reconnection_token=this.connection_info.reconnection_token),this.connection_info.reconnection_token_life_time&&this._token_refresh_interval>this.connection_info.reconnection_token_life_time/1.5&&(console.warn(`Token refresh interval is too long (${this._token_refresh_interval}), setting it to 1.5 times of the token life time(${this.connection_info.reconnection_token_life_time}).`),this._token_refresh_interval=this.connection_info.reconnection_token_life_time/1.5),this.manager_id=this.connection_info.manager_id||null,console.log(`Successfully connected to the server, workspace: ${this.connection_info.workspace}, manager_id: ${this.manager_id}`),this.connection_info.announcement&&console.log(`${this.connection_info.announcement}`),e(this.connection_info)}})}async open(){console.log("Creating a new websocket connection to",this._server_url.split("?")[0]);try{if(this._websocket=await this._attempt_connection(this._server_url),this._legacy_auth)throw new Error("NotImplementedError: Legacy authentication is not supported");const e=JSON.stringify({client_id:this._client_id,workspace:this._workspace,token:this._token,reconnection_token:this._reconnection_token});return this._websocket.send(e),await(0,_utils_index_js__WEBPACK_IMPORTED_MODULE_1__.waitFor)(this._establish_connection(),this._timeout,"Failed to receive the first message from the server"),this._token_refresh_interval>0&&setTimeout(()=>{this._send_refresh_token(),this._refresh_token_task=setInterval(()=>{this._send_refresh_token()},1e3*this._token_refresh_interval)},2e3),this._enable_reconnect=!0,this._closed=!1,this._websocket.onmessage=e=>{if("string"==typeof e.data){const t=JSON.parse(e.data);"reconnection_token"===t.type?this._reconnection_token=t.reconnection_token:console.log("Received message from the server:",t)}else this._handle_message(e.data)},this._websocket.onerror=e=>{console.error("WebSocket connection error:",e),this._cleanup()},this._websocket.onclose=this._handle_close.bind(this),this._handle_connected&&this._handle_connected(this.connection_info),this.connection_info}catch(e){throw this._cleanup(),console.error("Failed to connect to",this._server_url.split("?")[0],e),e}}_send_refresh_token(){if(this._websocket&&this._websocket.readyState===WebSocket.OPEN){const e=JSON.stringify({type:"refresh_token"});this._websocket.send(e)}}_handle_close(e){if(!this._closed&&this._websocket&&this._websocket.readyState===WebSocket.CLOSED){if(this._cleanup(),this._enable_reconnect){[1e3,1001].includes(e.code)?console.warn(`Websocket connection closed gracefully by server (code: ${e.code}): ${e.reason} - attempting reconnect`):console.warn("Websocket connection closed unexpectedly (code: %s): %s",e.code,e.reason);let t=0;const n=1e3,r=6e4,o=.1,i=async()=>{if(this._closed)console.info("Connection was closed, stopping reconnection");else try{console.warn(`Reconnecting to ${this._server_url.split("?")[0]} (attempt #${t})`),await this.open(),await new Promise(e=>setTimeout(e,500)),console.warn(`Successfully reconnected to server ${this._server_url} (services re-registered)`)}catch(e){if(`${e}`.includes("ConnectionAbortedError:"))return console.warn("Server refused to reconnect:",e),this._closed=!0,void(this._handle_disconnected&&this._handle_disconnected(`Server refused reconnection: ${e}`));if(`${e}`.includes("NotImplementedError:"))return console.error(`${e}\nIt appears that you are trying to connect to a hypha server that is older than 0.20.0, please upgrade the hypha server or use the websocket client in imjoy-rpc(https://www.npmjs.com/package/imjoy-rpc) instead`),this._closed=!0,void(this._handle_disconnected&&this._handle_disconnected(`Server too old: ${e}`));"NetworkError"===e.name||e.message.includes("network")?console.error(`Network error during reconnection: ${e.message}`):"TimeoutError"===e.name||e.message.includes("timeout")?console.error(`Connection timeout during reconnection: ${e.message}`):console.error(`Unexpected error during reconnection: ${e.message}`);const s=Math.min(n*Math.pow(2,t),r),a=(2*Math.random()-1)*o*s,c=Math.max(100,s+a);console.debug(`Waiting ${(c/1e3).toFixed(2)}s before next reconnection attempt`);const l=setTimeout(async()=>{this._reconnect_timeouts.delete(l),this._websocket&&this._websocket.readyState===WebSocket.OPEN?console.info("Connection restored externally"):this._closed?console.info("Connection was closed, stopping reconnection"):(t+=1,t<MAX_RETRY?await i():(console.error(`Failed to reconnect after ${MAX_RETRY} attempts, giving up.`),this._closed=!0,this._handle_disconnected&&this._handle_disconnected("Max reconnection attempts exceeded")))},c);this._reconnect_timeouts.add(l)}};i()}}else this._cleanup(),this._handle_disconnected&&this._handle_disconnected(e.reason)}async emit_message(e){if(this._closed)throw new Error("Connection is closed");this._websocket&&this._websocket.readyState===WebSocket.OPEN||await this.open();try{this._websocket.send(e)}catch(e){throw console.error(`Failed to send data, error: ${e}`),e}}disconnect(e){this._closed=!0,this._websocket&&this._websocket.readyState!==WebSocket.CLOSED&&this._websocket.readyState!==WebSocket.CLOSING&&this._websocket.close(1e3,e),this._cleanup(),console.info(`WebSocket connection disconnected (${e})`)}}function normalizeServerUrl(e){if(!e)throw new Error("server_url is required");return e.startsWith("http://")?e=e.replace("http://","ws://").replace(/\/$/,"")+"/ws":e.startsWith("https://")&&(e=e.replace("https://","wss://").replace(/\/$/,"")+"/ws"),e}async function login(e){const t=e.login_service_id||"public/hypha-login",n=e.workspace,r=e.expires_in,o=e.login_timeout||60,i=e.login_callback,s=e.profile,a=e.additional_headers,c=e.transport||"websocket",l=await connectToServer({name:"initial login client",server_url:e.server_url,additional_headers:a,transport:c});try{const e=await l.getService(t);let a;return(0,_utils_index_js__WEBPACK_IMPORTED_MODULE_1__.assert)(e,`Failed to get the login service: ${t}`),a=n?await e.start({workspace:n,expires_in:r,_rkwargs:!0}):await e.start(),i?await i(a):console.log(`Please open your browser and login at ${a.login_url}`),await e.check(a.key,{timeout:o,profile:s,_rkwargs:!0})}catch(e){throw e}finally{await l.disconnect()}}async function logout(e){const t=e.login_service_id||"public/hypha-login",n=e.logout_callback,r=e.additional_headers,o=e.transport||"websocket",i=await connectToServer({name:"initial logout client",server_url:e.server_url,additional_headers:r,transport:o});try{const e=await i.getService(t);if((0,_utils_index_js__WEBPACK_IMPORTED_MODULE_1__.assert)(e,`Failed to get the login service: ${t}`),!e.logout)throw new Error("Logout is not supported by this server. Please upgrade the Hypha server to a version that supports logout.");const r=await e.logout({});return n?await n(r):console.log(`Please open your browser to logout at ${r.logout_url}`),r}catch(e){throw e}finally{await i.disconnect()}}async function webrtcGetService(e,t,n){const r=void 0!==(n=n||{}).webrtc?n.webrtc:"auto",o=n.webrtc_config;void 0!==n.webrtc&&delete n.webrtc,void 0!==n.webrtc_config&&delete n.webrtc_config,(0,_utils_index_js__WEBPACK_IMPORTED_MODULE_1__.assert)([void 0,!0,!1,"auto"].includes(r),"webrtc must be true, false or 'auto'");const i=await e.getService(t,n);if(!0===r||"auto"===r){if(i.id.includes(":")&&i.id.includes("/"))try{const t=i.id.split(":")[0].split("/"),r=t[t.length-1],s=`${t.slice(0,-1).join("/")}/${r}-rtc`,a=await(0,_webrtc_client_js__WEBPACK_IMPORTED_MODULE_3__.getRTCService)(e,s,o),c=await a.getService(i.id.split(":")[1],n);return c._webrtc=!0,c._peer=a,c._service=i,c}catch(e){console.warn("Failed to get webrtc service, using websocket connection",e)}if(!0===r)throw new Error("Failed to get the service via webrtc")}return i}async function connectToServer(e){if("http"===(e.transport||"websocket"))return await(0,_http_client_js__WEBPACK_IMPORTED_MODULE_4__.connectToServerHTTP)(e);e.server&&(e.server_url=e.server_url||e.server.url,e.WebSocketClass=e.WebSocketClass||e.server.WebSocketClass);let t=e.client_id;t||(t=(0,_utils_index_js__WEBPACK_IMPORTED_MODULE_1__.randId)(),e.client_id=t),0===Object.keys(e).length&&("undefined"!=typeof process&&process.env?(e.server_url=process.env.HYPHA_SERVER_URL,e.token=process.env.HYPHA_TOKEN,e.client_id=process.env.HYPHA_CLIENT_ID,e.workspace=process.env.HYPHA_WORKSPACE):"undefined"!=typeof self&&self.env?(e.server_url=self.env.HYPHA_SERVER_URL,e.token=self.env.HYPHA_TOKEN,e.client_id=self.env.HYPHA_CLIENT_ID,e.workspace=self.env.HYPHA_WORKSPACE):"undefined"!=typeof globalThis&&globalThis.env&&(e.server_url=globalThis.env.HYPHA_SERVER_URL,e.token=globalThis.env.HYPHA_TOKEN,e.client_id=globalThis.env.HYPHA_CLIENT_ID,e.workspace=globalThis.env.HYPHA_WORKSPACE));let n=normalizeServerUrl(e.server_url),r=new WebsocketRPCConnection(n,t,e.workspace,e.token,e.reconnection_token,e.method_timeout||60,e.WebSocketClass,e.token_refresh_interval,e.additional_headers);const o=await r.open();if((0,_utils_index_js__WEBPACK_IMPORTED_MODULE_1__.assert)(o,"Failed to connect to the server, no connection info obtained. This issue is most likely due to an outdated Hypha server version. Please use `imjoy-rpc` for compatibility, or upgrade the Hypha server to the latest version."),await new Promise(e=>setTimeout(e,100)),!r.manager_id){console.warn("Manager ID not set immediately, waiting...");const e=5e3,t=100,n=Date.now();for(;!r.manager_id&&Date.now()-n<e;)await new Promise(e=>setTimeout(e,t));if(!r.manager_id)throw console.error("Manager ID still not set after waiting"),new Error("Failed to get manager ID from server");console.info(`Manager ID set after waiting: ${r.manager_id}`)}if(e.workspace&&o.workspace!==e.workspace)throw new Error(`Connected to the wrong workspace: ${o.workspace}, expected: ${e.workspace}`);const i=o.workspace,s=new _rpc_js__WEBPACK_IMPORTED_MODULE_0__.RPC(r,{client_id:t,workspace:i,default_context:{connection_type:"websocket"},name:e.name,method_timeout:e.method_timeout,app_id:e.app_id,server_base_url:o.public_base_url,long_message_chunk_size:e.long_message_chunk_size});await s.waitFor("services_registered",e.method_timeout||120);const a=await s.get_manager_service({timeout:e.method_timeout,case_conversion:"camel",kwargs_expansion:e.kwargs_expansion||!1});if(a.rpc=s,o&&(a.config=Object.assign(a.config,o)),a.export=(0,_utils_schema_js__WEBPACK_IMPORTED_MODULE_2__.schemaFunction)(async function(t){t.id="default",t.name=t.name||e.name||t.id,t.description=t.description||e.description,await s.register_service(t,{overwrite:!0})},{name:"export",description:"Export the api.",parameters:{properties:{api:{description:"The api to export",type:"object"}},required:["api"],type:"object"}}),a.getApp=(0,_utils_schema_js__WEBPACK_IMPORTED_MODULE_2__.schemaFunction)(async function(e){return e=e||"*",(0,_utils_index_js__WEBPACK_IMPORTED_MODULE_1__.assert)(!e.includes(":"),"clientId should not contain ':'"),e.includes("/")||(e=o.workspace+"/"+e),(0,_utils_index_js__WEBPACK_IMPORTED_MODULE_1__.assert)(2===e.split("/").length,"clientId should match pattern workspace/clientId"),await a.getService(`${e}:default`)},{name:"getApp",description:"Get the app.",parameters:{properties:{clientId:{default:"*",description:"The clientId",type:"string"}},type:"object"}}),a.listApps=(0,_utils_schema_js__WEBPACK_IMPORTED_MODULE_2__.schemaFunction)(async function(e){e=e||i,(0,_utils_index_js__WEBPACK_IMPORTED_MODULE_1__.assert)(!e.includes(":"),"workspace should not contain ':'"),(0,_utils_index_js__WEBPACK_IMPORTED_MODULE_1__.assert)(!e.includes("/"),"workspace should not contain '/'");const t={workspace:e,service_id:"default"};return await a.listServices(t)},{name:"listApps",description:"List the apps.",parameters:{properties:{workspace:{default:i,description:"The workspace",type:"string"}},type:"object"}}),a.disconnect=(0,_utils_schema_js__WEBPACK_IMPORTED_MODULE_2__.schemaFunction)(s.disconnect.bind(s),{name:"disconnect",description:"Disconnect from the server.",parameters:{type:"object",properties:{},required:[]}}),a.registerCodec=(0,_utils_schema_js__WEBPACK_IMPORTED_MODULE_2__.schemaFunction)(s.register_codec.bind(s),{name:"registerCodec",description:"Register a codec for the webrtc connection",parameters:{type:"object",properties:{codec:{type:"object",description:"Codec to register",properties:{name:{type:"string"},type:{},encoder:{type:"function"},decoder:{type:"function"}}}}}}),a.emit=(0,_utils_schema_js__WEBPACK_IMPORTED_MODULE_2__.schemaFunction)(s.emit.bind(s),{name:"emit",description:"Emit a message.",parameters:{properties:{data:{description:"The data to emit",type:"object"}},required:["data"],type:"object"}}),a.on=(0,_utils_schema_js__WEBPACK_IMPORTED_MODULE_2__.schemaFunction)(s.on.bind(s),{name:"on",description:"Register a message handler.",parameters:{properties:{event:{description:"The event to listen to",type:"string"},handler:{description:"The handler function",type:"function"}},required:["event","handler"],type:"object"}}),a.off=(0,_utils_schema_js__WEBPACK_IMPORTED_MODULE_2__.schemaFunction)(s.off.bind(s),{name:"off",description:"Remove a message handler.",parameters:{properties:{event:{description:"The event to remove",type:"string"},handler:{description:"The handler function",type:"function"}},required:["event","handler"],type:"object"}}),a.once=(0,_utils_schema_js__WEBPACK_IMPORTED_MODULE_2__.schemaFunction)(s.once.bind(s),{name:"once",description:"Register a one-time message handler.",parameters:{properties:{event:{description:"The event to listen to",type:"string"},handler:{description:"The handler function",type:"function"}},required:["event","handler"],type:"object"}}),a.getServiceSchema=(0,_utils_schema_js__WEBPACK_IMPORTED_MODULE_2__.schemaFunction)(s.get_service_schema,{name:"getServiceSchema",description:"Get the service schema.",parameters:{properties:{service:{description:"The service to extract schema",type:"object"}},required:["service"],type:"object"}}),a.registerService=(0,_utils_schema_js__WEBPACK_IMPORTED_MODULE_2__.schemaFunction)(s.register_service.bind(s),{name:"registerService",description:"Register a service.",parameters:{properties:{service:{description:"The service to register",type:"object"},force:{default:!1,description:"Force to register the service",type:"boolean"}},required:["service"],type:"object"}}),a.unregisterService=(0,_utils_schema_js__WEBPACK_IMPORTED_MODULE_2__.schemaFunction)(s.unregister_service.bind(s),{name:"unregisterService",description:"Unregister a service.",parameters:{properties:{service:{description:"The service id to unregister",type:"string"},notify:{default:!0,description:"Notify the workspace manager",type:"boolean"}},required:["service"],type:"object"}}),r.manager_id&&s.on("force-exit",async e=>{e.from==="*/"+r.manager_id&&(console.log("Disconnecting from server, reason:",e.reason),await s.disconnect())}),e.webrtc){await(0,_webrtc_client_js__WEBPACK_IMPORTED_MODULE_3__.registerRTCService)(a,`${t}-rtc`,e.webrtc_config);const n=Object.assign({},a),r=n.getService.__schema__.description,o=n.getService.__schema__.parameters;a.getService=(0,_utils_schema_js__WEBPACK_IMPORTED_MODULE_2__.schemaFunction)(webrtcGetService.bind(null,n),{name:"getService",description:r,parameters:o}),a.getRTCService=(0,_utils_schema_js__WEBPACK_IMPORTED_MODULE_2__.schemaFunction)(_webrtc_client_js__WEBPACK_IMPORTED_MODULE_3__.getRTCService.bind(null,a),{name:"getRTCService",description:"Get the webrtc connection, returns a peer connection.",parameters:{properties:{config:{description:"The config for the webrtc service",type:"object"}},required:["config"],type:"object"}})}else{const e=a.getService;a.getService=(t,n)=>e(t,n=n||{}),a.getService.__schema__=e.__schema__}return a.registerProbes=(0,_utils_schema_js__WEBPACK_IMPORTED_MODULE_2__.schemaFunction)(async function(e){return e.id="probes",e.name="Probes",e.config={visibility:"public"},e.type="probes",e.description=`Probes Service, visit ${n}/${i}services/probes for the available probes.`,await a.registerService(e,{overwrite:!0})},{name:"registerProbes",description:"Register probes service",parameters:{properties:{probes:{description:"The probes to register, e.g. {'liveness': {'type': 'function', 'description': 'Check the liveness of the service'}}",type:"object"}},required:["probes"],type:"object"}}),a}async function getRemoteService(e,t={}){const{serverUrl:n,workspace:r,clientId:o,serviceId:i,appId:s}=(0,_utils_index_js__WEBPACK_IMPORTED_MODULE_1__.parseServiceUrl)(e),a=`${r}/${o}:${i}@${s}`;if(t.serverUrl&&t.serverUrl!==n)throw new Error("server_url in config does not match the server_url in the url");t.serverUrl=n;const c=await connectToServer(t);return await c.getService(a)}class LocalWebSocket{constructor(e,t,n){this.url=e,this.onopen=()=>{},this.onmessage=()=>{},this.onclose=()=>{},this.onerror=()=>{},this.client_id=t,this.workspace=n;const r="undefined"!=typeof window?window:self,o="undefined"!=typeof window;if(this.postMessage=e=>{o?window.parent.postMessage(e,"*"):self.postMessage(e)},this.readyState=WebSocket.CONNECTING,r.addEventListener("message",e=>{const{type:t,data:n,to:r}=e.data;if(r===this.client_id)switch(t){case"message":this.readyState===WebSocket.OPEN&&this.onmessage&&this.onmessage({data:n});break;case"connected":this.readyState=WebSocket.OPEN,this.onopen(e);break;case"closed":this.readyState=WebSocket.CLOSED,this.onclose(e)}},!1),!this.client_id)throw new Error("client_id is required");if(!this.workspace)throw new Error("workspace is required");this.postMessage({type:"connect",url:this.url,from:this.client_id,workspace:this.workspace})}send(e){this.readyState===WebSocket.OPEN&&this.postMessage({type:"message",data:e,from:this.client_id,workspace:this.workspace})}close(){this.readyState=WebSocket.CLOSING,this.postMessage({type:"close",from:this.client_id,workspace:this.workspace}),this.onclose()}addEventListener(e,t){"message"===e&&(this.onmessage=t),"open"===e&&(this.onopen=t),"close"===e&&(this.onclose=t),"error"===e&&(this.onerror=t)}}function setupLocalClient({enable_execution:enable_execution=!1,on_ready:on_ready=null}){return new Promise((resolve,reject)=>{const context="undefined"!=typeof window?window:self,isWindow="undefined"!=typeof window;context.addEventListener("message",event=>{const{type:type,server_url:server_url,workspace:workspace,client_id:client_id,token:token,method_timeout:method_timeout,name:name,config:config}=event.data;if("initializeHyphaClient"===type){if(!server_url||!workspace||!client_id)return void console.error("server_url, workspace, and client_id are required.");if(!server_url.startsWith("https://local-hypha-server:"))return void console.error("server_url should start with https://local-hypha-server:");class FixedLocalWebSocket extends LocalWebSocket{constructor(e){super(e,client_id,workspace)}}connectToServer({server_url:server_url,workspace:workspace,client_id:client_id,token:token,method_timeout:method_timeout,name:name,WebSocketClass:FixedLocalWebSocket}).then(async server=>{globalThis.api=server;try{if(isWindow&&enable_execution){function e(e){return new Promise((t,n)=>{const r=document.createElement("script");r.innerHTML=e.content,r.lang=e.lang,r.onload=()=>t(),r.onerror=e=>n(e),document.head.appendChild(r)})}if(config.styles&&config.styles.length>0)for(const t of config.styles){const n=document.createElement("style");n.innerHTML=t.content,n.lang=t.lang,document.head.appendChild(n)}if(config.links&&config.links.length>0)for(const r of config.links){const o=document.createElement("a");o.href=r.url,o.innerText=r.text,document.body.appendChild(o)}if(config.windows&&config.windows.length>0)for(const i of config.windows){document.body.innerHTML=i.content;break}if(config.scripts&&config.scripts.length>0)for(const s of config.scripts){if("javascript"!==s.lang)throw new Error("Only javascript scripts are supported");await e(s)}}else if(!isWindow&&enable_execution&&config.scripts&&config.scripts.length>0)for(const script of config.scripts){if("javascript"!==script.lang)throw new Error("Only javascript scripts are supported");eval(script.content)}on_ready&&await on_ready(server,config),resolve(server)}catch(a){reject(a)}})}},!1),isWindow?window.parent.postMessage({type:"hyphaClientReady"},"*"):self.postMessage({type:"hyphaClientReady"})})}return __webpack_exports__})(),module.exports=factory()}(hyphaRpcWebsocket$1)),hyphaRpcWebsocket$1.exports}function requireHyphaRpc(){return hasRequiredHyphaRpc?hyphaRpc$1:(hasRequiredHyphaRpc=1,hyphaRpc$1={hyphaWebsocketClient:requireHyphaRpcWebsocket()})}var hyphaRpcExports=requireHyphaRpc(),index=getDefaultExportFromCjs(hyphaRpcExports),hyphaRpc=_mergeNamespaces({__proto__:null,default:index},[hyphaRpcExports]);const overlayStyles="\n :host {\n all: initial;\n font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;\n }\n\n * {\n box-sizing: border-box;\n margin: 0;\n padding: 0;\n }\n\n .debugger-icon {\n width: 40px;\n height: 40px;\n border-radius: 50%;\n background: #4a90d9;\n color: white;\n display: flex;\n align-items: center;\n justify-content: center;\n cursor: pointer;\n box-shadow: 0 2px 8px rgba(0, 0, 0, 0.3);\n transition: transform 0.15s, background 0.15s;\n user-select: none;\n font-size: 18px;\n line-height: 1;\n }\n\n .debugger-icon:hover {\n transform: scale(1.1);\n background: #357abd;\n }\n\n .debugger-icon.connected {\n background: #27ae60;\n }\n\n .debugger-icon.error {\n background: #e74c3c;\n }\n\n .debugger-panel {\n display: none;\n width: 380px;\n max-height: 520px;\n background: #1e1e2e;\n color: #cdd6f4;\n border-radius: 8px;\n border: 1px solid #45475a;\n box-shadow: 0 8px 32px rgba(0, 0, 0, 0.5);\n overflow: hidden;\n flex-direction: column;\n position: absolute;\n bottom: 50px;\n right: 0;\n font-size: 13px;\n }\n\n .debugger-panel.open {\n display: flex;\n }\n\n .panel-header {\n background: #313244;\n padding: 8px 12px;\n display: flex;\n align-items: center;\n justify-content: space-between;\n cursor: default;\n border-bottom: 1px solid #45475a;\n font-weight: 600;\n font-size: 12px;\n letter-spacing: 0.3px;\n text-transform: uppercase;\n color: #a6adc8;\n }\n\n .panel-header .title {\n display: flex;\n align-items: center;\n gap: 6px;\n }\n\n .panel-header .close-btn {\n cursor: pointer;\n color: #6c7086;\n font-size: 16px;\n line-height: 1;\n padding: 2px 4px;\n border-radius: 3px;\n }\n\n .panel-header .close-btn:hover {\n color: #cdd6f4;\n background: #45475a;\n }\n\n .status-dot {\n width: 8px;\n height: 8px;\n border-radius: 50%;\n display: inline-block;\n background: #6c7086;\n }\n\n .status-dot.connected {\n background: #a6e3a1;\n }\n\n .status-dot.error {\n background: #f38ba8;\n }\n\n .panel-body {\n padding: 10px 12px;\n overflow-y: auto;\n flex: 1;\n max-height: 440px;\n }\n\n .info-row {\n display: flex;\n justify-content: space-between;\n padding: 4px 0;\n border-bottom: 1px solid #313244;\n font-size: 12px;\n }\n\n .info-row .label {\n color: #6c7086;\n }\n\n .info-row .value {\n color: #cdd6f4;\n text-align: right;\n word-break: break-all;\n max-width: 180px;\n font-family: 'SF Mono', Monaco, Consolas, monospace;\n font-size: 11px;\n }\n\n .instructions-section {\n margin-top: 8px;\n padding-top: 6px;\n border-top: 1px solid #313244;\n }\n\n .instructions-header {\n display: flex;\n align-items: center;\n justify-content: space-between;\n margin-bottom: 4px;\n }\n\n .url-label {\n font-size: 11px;\n color: #6c7086;\n text-transform: uppercase;\n letter-spacing: 0.5px;\n margin-bottom: 3px;\n }\n\n .instructions-block {\n font-family: 'SF Mono', Monaco, Consolas, monospace;\n font-size: 10px;\n color: #a6e3a1;\n background: #11111b;\n border: 1px solid #313244;\n border-radius: 4px;\n padding: 8px;\n white-space: pre-wrap;\n word-break: break-all;\n max-height: 200px;\n overflow-y: auto;\n line-height: 1.5;\n }\n\n .copy-btn {\n background: #45475a;\n color: #cdd6f4;\n border: none;\n border-radius: 3px;\n padding: 2px 8px;\n font-size: 10px;\n cursor: pointer;\n white-space: nowrap;\n flex-shrink: 0;\n }\n\n .copy-btn:hover {\n background: #585b70;\n }\n\n .log-section {\n margin-top: 8px;\n }\n\n .log-title {\n font-size: 11px;\n color: #6c7086;\n text-transform: uppercase;\n letter-spacing: 0.5px;\n margin-bottom: 4px;\n }\n\n .log-entry {\n font-family: 'SF Mono', Monaco, Consolas, monospace;\n font-size: 11px;\n padding: 3px 6px;\n border-radius: 3px;\n background: #313244;\n margin-bottom: 2px;\n color: #a6adc8;\n word-break: break-all;\n }\n\n .log-entry.call {\n border-left: 2px solid #89b4fa;\n }\n\n .log-entry.result {\n border-left: 2px solid #a6e3a1;\n }\n\n .log-entry.error {\n border-left: 2px solid #f38ba8;\n color: #f38ba8;\n }\n";class DebugOverlay{constructor(e){this.isOpen=!1,this.isDragging=!1,this.dragOffset={x:0,y:0},this.maxLogEntries=50,this.host=document.createElement("div"),this.host.id="hypha-debugger-host",Object.assign(this.host.style,{position:"fixed",bottom:"20px",right:"20px",zIndex:"2147483647",display:"flex",flexDirection:"column",alignItems:"flex-end"}),e?.position&&(this.host.style.bottom="auto",this.host.style.right="auto",this.host.style.left=e.position.x+"px",this.host.style.top=e.position.y+"px"),this.shadow=this.host.attachShadow({mode:"open"});const t=document.createElement("style");t.textContent=overlayStyles,this.shadow.appendChild(t);const n=document.createElement("div");n.style.position="relative",n.style.display="flex",n.style.flexDirection="column",n.style.alignItems="flex-end",this.panel=document.createElement("div"),this.panel.className="debugger-panel";const r=document.createElement("div");r.className="panel-header";const o=document.createElement("span");o.className="title",this.statusDot=document.createElement("span"),this.statusDot.className="status-dot",o.appendChild(this.statusDot),o.appendChild(document.createTextNode(" Hypha Debugger"));const i=document.createElement("span");i.className="close-btn",i.textContent="×",i.addEventListener("click",()=>this.toggle()),r.appendChild(o),r.appendChild(i);const s=document.createElement("div");s.className="panel-body",this.infoBody=document.createElement("div"),s.appendChild(this.infoBody);const a=document.createElement("div");a.className="log-section";const c=document.createElement("div");c.className="log-title",c.textContent="Remote Operations",this.logContainer=document.createElement("div"),a.appendChild(c),a.appendChild(this.logContainer),s.appendChild(a),this.panel.appendChild(r),this.panel.appendChild(s),this.icon=document.createElement("div"),this.icon.className="debugger-icon",this.icon.textContent="🐛",this.icon.addEventListener("click",e=>{this.isDragging||this.toggle()}),n.appendChild(this.panel),n.appendChild(this.icon),this.shadow.appendChild(n),document.documentElement.appendChild(this.host),this.setupDrag()}setupDrag(){let e=0,t=0,n=!1;this.icon.addEventListener("mousedown",r=>{e=r.clientX,t=r.clientY,n=!1;const o=this.host.getBoundingClientRect();this.dragOffset.x=r.clientX-o.left,this.dragOffset.y=r.clientY-o.top,r.preventDefault()}),document.addEventListener("mousemove",r=>{if(0===e&&0===t)return;const o=Math.abs(r.clientX-e),i=Math.abs(r.clientY-t);(o>3||i>3)&&(n=!0,this.isDragging=!0,this.host.style.left=r.clientX-this.dragOffset.x+"px",this.host.style.top=r.clientY-this.dragOffset.y+"px",this.host.style.right="auto",this.host.style.bottom="auto")}),document.addEventListener("mouseup",()=>{e=0,t=0,n&&setTimeout(()=>{this.isDragging=!1},50)})}toggle(){this.isOpen=!this.isOpen,this.panel.classList.toggle("open",this.isOpen)}setStatus(e){this.statusDot.className="status-dot",this.icon.className="debugger-icon","connected"===e?(this.statusDot.classList.add("connected"),this.icon.classList.add("connected")):"error"===e&&(this.statusDot.classList.add("error"),this.icon.classList.add("error"))}setInfo(e){this.infoBody.querySelectorAll(".info-row").forEach(e=>e.remove());const t=this.infoBody.firstChild;for(const[n,r]of Object.entries(e)){const e=document.createElement("div");e.className="info-row";const o=document.createElement("span");o.className="label",o.textContent=n;const i=document.createElement("span");i.className="value",i.textContent=r,i.title=r,e.appendChild(o),e.appendChild(i),this.infoBody.insertBefore(e,t)}}setInstructions(e){const t=this.infoBody.querySelector(".instructions-section");t&&t.remove();const n=document.createElement("div");n.className="instructions-section";const r=document.createElement("div");r.className="instructions-header";const o=document.createElement("span");o.className="url-label",o.textContent="Instructions";const i=document.createElement("button");i.className="copy-btn",i.textContent="Copy All",i.addEventListener("click",()=>{navigator.clipboard.writeText(e).then(()=>{i.textContent="Copied!",setTimeout(()=>{i.textContent="Copy All"},1500)})}),r.appendChild(o),r.appendChild(i),n.appendChild(r);const s=document.createElement("pre");s.className="instructions-block",s.textContent=e,n.appendChild(s),this.infoBody.appendChild(n)}addLog(e,t="call"){const n=document.createElement("div");for(n.className=`log-entry ${t}`,n.textContent=e,this.logContainer.appendChild(n);this.logContainer.children.length>this.maxLogEntries;)this.logContainer.removeChild(this.logContainer.firstChild);const r=this.panel.querySelector(".panel-body");r&&(r.scrollTop=r.scrollHeight)}destroy(){this.host.remove()}}const CURSOR_BORDER_SVG='<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100 100" fill="none"><g><path d="M 15 42 L 15 36.99 Q 15 31.99 23.7 31.99 L 28.05 31.99 Q 32.41 31.99 32.41 21.99 L 32.41 17 Q 32.41 12 41.09 16.95 L 76.31 37.05 Q 85 42 76.31 46.95 L 41.09 67.05 Q 32.41 72 32.41 62.01 L 32.41 57.01 Q 32.41 52.01 23.7 52.01 L 19.35 52.01 Q 15 52.01 15 47.01 Z" fill="none" stroke="currentColor" stroke-width="6" stroke-miterlimit="10"/></g></svg>',CURSOR_FILL_SVG='<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100 100"><g style="filter: drop-shadow(rgba(0, 0, 0, 0.3) 3px 4px 4px);"><path d="M 15 42 L 15 36.99 Q 15 31.99 23.7 31.99 L 28.05 31.99 Q 32.41 31.99 32.41 21.99 L 32.41 17 Q 32.41 12 41.09 16.95 L 76.31 37.05 Q 85 42 76.31 46.95 L 41.09 67.05 Q 32.41 72 32.41 62.01 L 32.41 57.01 Q 32.41 52.01 23.7 52.01 L 19.35 52.01 Q 15 52.01 15 47.01 Z" fill="#ffffff" stroke="none"/></g></svg>',CURSOR_CSS="\n .hypha-cursor {\n position: fixed;\n width: 50px;\n height: 50px;\n pointer-events: none;\n z-index: 2147483646;\n transition: opacity 0.2s;\n opacity: 0;\n }\n .hypha-cursor.visible {\n opacity: 1;\n }\n .hypha-cursor-border {\n position: absolute;\n width: 100%;\n height: 100%;\n background: linear-gradient(45deg, rgb(57, 182, 255), rgb(189, 69, 251));\n mask-image: var(--cursor-border);\n -webkit-mask-image: var(--cursor-border);\n mask-size: 100% 100%;\n -webkit-mask-size: 100% 100%;\n mask-repeat: no-repeat;\n -webkit-mask-repeat: no-repeat;\n transform-origin: center;\n transform: rotate(-135deg) scale(1.2);\n margin-left: -10px;\n margin-top: -14px;\n }\n .hypha-cursor-fill {\n position: absolute;\n width: 100%;\n height: 100%;\n background-image: var(--cursor-fill);\n background-size: 100% 100%;\n background-repeat: no-repeat;\n transform-origin: center;\n transform: rotate(-135deg) scale(1.2);\n margin-left: -10px;\n margin-top: -14px;\n }\n .hypha-cursor-ripple {\n position: absolute;\n width: 100%;\n height: 100%;\n pointer-events: none;\n margin-left: -50%;\n margin-top: -50%;\n }\n .hypha-cursor-ripple::after {\n content: '';\n opacity: 0;\n position: absolute;\n inset: 0;\n border: 3px solid rgba(57, 182, 255, 1);\n border-radius: 50%;\n }\n .hypha-cursor.clicking .hypha-cursor-ripple::after {\n animation: hypha-cursor-ripple 400ms ease-out forwards;\n }\n @keyframes hypha-cursor-ripple {\n 0% { transform: scale(0); opacity: 1; }\n 100% { transform: scale(2.5); opacity: 0; }\n }\n";class AICursor{constructor(){this.currentX=0,this.currentY=0,this.targetX=0,this.targetY=0,this.animating=!1,this.visible=!1,this.hideTimeout=null,this.container=document.createElement("div"),this.container.id="hypha-debugger-cursor",this.container.setAttribute("data-browser-use-ignore","true"),this.container.setAttribute("data-page-agent-ignore","true");const e=document.createElement("style");e.textContent=CURSOR_CSS,this.container.appendChild(e),this.cursor=document.createElement("div"),this.cursor.className="hypha-cursor";const t='url("data:image/svg+xml,'+encodeURIComponent(CURSOR_BORDER_SVG)+'")',n='url("data:image/svg+xml,'+encodeURIComponent(CURSOR_FILL_SVG)+'")';this.cursor.style.setProperty("--cursor-border",t),this.cursor.style.setProperty("--cursor-fill",n);const r=document.createElement("div");r.className="hypha-cursor-ripple",this.cursor.appendChild(r);const o=document.createElement("div");o.className="hypha-cursor-fill",this.cursor.appendChild(o);const i=document.createElement("div");i.className="hypha-cursor-border",this.cursor.appendChild(i),this.container.appendChild(this.cursor),document.body.appendChild(this.container),window.addEventListener("HyphaDebugger::MovePointerTo",e=>{const{x:t,y:n}=e.detail;this.moveTo(t,n)}),window.addEventListener("HyphaDebugger::ClickPointer",()=>{this.triggerClickAnimation()})}moveTo(e,t){this.targetX=e,this.targetY=t,this.visible||(this.visible=!0,this.currentX=e,this.currentY=t,this.cursor.style.left=`${e}px`,this.cursor.style.top=`${t}px`,this.cursor.classList.add("visible")),this.hideTimeout&&(clearTimeout(this.hideTimeout),this.hideTimeout=null),this.animating||(this.animating=!0,this.animateLoop())}animateLoop(){const e=this.targetX-this.currentX,t=this.targetY-this.currentY;Math.abs(e)>1||Math.abs(t)>1?(this.currentX+=.18*e,this.currentY+=.18*t,this.cursor.style.left=`${this.currentX}px`,this.cursor.style.top=`${this.currentY}px`,requestAnimationFrame(()=>this.animateLoop())):(this.currentX=this.targetX,this.currentY=this.targetY,this.cursor.style.left=`${this.currentX}px`,this.cursor.style.top=`${this.currentY}px`,this.animating=!1,this.hideTimeout=setTimeout(()=>{this.visible=!1,this.cursor.classList.remove("visible")},2e3))}triggerClickAnimation(){this.cursor.classList.remove("clicking"),this.cursor.offsetHeight,this.cursor.classList.add("clicking")}destroy(){this.hideTimeout&&clearTimeout(this.hideTimeout),this.container.remove()}}function detectFrameworks(){const e=[],t=window;if(t.__REACT_DEVTOOLS_GLOBAL_HOOK__?.renderers?.size>0)e.push("react");else{const t=document.querySelector("#root, #app, [data-reactroot]");if(t){Object.keys(t).some(e=>e.startsWith("__reactFiber$")||e.startsWith("__reactInternalInstance$"))&&e.push("react")}}if(t.__VUE__||t.__VUE_DEVTOOLS_GLOBAL_HOOK__)e.push("vue");else{const t=document.querySelector("[data-v-app], #app");t&&t.__vue_app__&&e.push("vue")}return(t.ng||document.querySelector("[ng-version]"))&&e.push("angular"),document.querySelector("[class*='svelte-']")&&e.push("svelte"),t.__NEXT_DATA__&&e.push("nextjs"),e}function collectPageInfo(){const e=performance.getEntriesByType("navigation")[0];return{url:window.location.href,title:document.title,viewport:{width:window.innerWidth,height:window.innerHeight},document_size:{width:document.documentElement.scrollWidth,height:document.documentElement.scrollHeight},user_agent:navigator.userAgent,timestamp:(new Date).toISOString(),cookies_enabled:navigator.cookieEnabled,language:navigator.language,platform:navigator.platform,online:navigator.onLine,performance:{load_time_ms:e?Math.round(e.loadEventEnd-e.startTime):null,dom_content_loaded_ms:e?Math.round(e.domContentLoadedEventEnd-e.startTime):null},frameworks:detectFrameworks()}}function getPageInfo(e,t,n){const r=collectPageInfo();if(e){const e=window.__HYPHA_DEBUGGER__?.consoleLogs??[],o=t??50;let i=n?e.filter(e=>e.level===n):e;r.console_logs=i.slice(-o)}return r}function getConsoleLogs(e){const t=window.__HYPHA_DEBUGGER__?.consoleLogs??[],n=e?.level,r=e?.limit??100;return(n?t.filter(e=>e.level===n):t).slice(-r)}function installConsoleCapture(e=500){var t;const n=(t=window).__HYPHA_DEBUGGER__??(t.__HYPHA_DEBUGGER__={});if(n.consoleInstalled)return;n.consoleLogs=[],n.consoleInstalled=!0;const r=["log","warn","error","info"];for(const t of r){const r=console[t].bind(console);console[t]=(...o)=>{const i=n.consoleLogs;i.push({level:t,message:o.map(e=>{try{return"string"==typeof e?e:JSON.stringify(e)}catch{return String(e)}}).join(" "),timestamp:(new Date).toISOString()}),i.length>e&&i.splice(0,i.length-e),r(...o)}}}function elementToInfo(e){const t=e.getBoundingClientRect(),n={};for(const t of Array.from(e.attributes))n[t.name]=t.value;return{tag:e.tagName.toLowerCase(),id:e.id,classes:Array.from(e.classList),text:(e.textContent??"").trim().slice(0,500),attributes:n,bounds:{x:Math.round(t.x),y:Math.round(t.y),width:Math.round(t.width),height:Math.round(t.height)},visible:t.width>0&&t.height>0&&"hidden"!==getComputedStyle(e).visibility&&"none"!==getComputedStyle(e).display,children_count:e.children.length}}function queryDom(e,t){t=t??20;const n=document.querySelectorAll(e),r=[];for(let e=0;e<Math.min(n.length,t);e++)r.push(elementToInfo(n[e]));return r}function clickElement$1(e){const t=document.querySelector(e);if(!t)return{success:!1,message:`No element found for selector: ${e}`};const n=t.getBoundingClientRect();return t.dispatchEvent(new MouseEvent("click",{bubbles:!0,cancelable:!0,view:window,clientX:n.left+n.width/2,clientY:n.top+n.height/2})),{success:!0,message:`Clicked element: ${e}`}}function fillInput(e,t){const n=document.querySelector(e);if(!n)return{success:!1,message:`No element found for selector: ${e}`};const r=n.tagName.toLowerCase();if("input"===r||"textarea"===r){const o=n,i="textarea"===r?HTMLTextAreaElement.prototype:HTMLInputElement.prototype,s=Object.getOwnPropertyDescriptor(i,"value")?.set;return s?s.call(o,t):o.value=t,o.dispatchEvent(new Event("input",{bubbles:!0})),o.dispatchEvent(new Event("change",{bubbles:!0})),{success:!0,message:`Filled ${e} with value`}}if("select"===r){const r=n,o=Object.getOwnPropertyDescriptor(HTMLSelectElement.prototype,"value")?.set;return o?o.call(r,t):r.value=t,r.dispatchEvent(new Event("change",{bubbles:!0})),{success:!0,message:`Set ${e} to ${t}`}}return{success:!1,message:`Element ${e} is not an input/textarea/select`}}function scrollTo(e){if("string"==typeof e){const t=document.querySelector(e);return t?(t.scrollIntoView({behavior:"smooth",block:"center"}),{success:!0,message:`Scrolled to ${e}`}):{success:!1,message:`No element found for selector: ${e}`}}return window.scrollTo({left:e.x,top:e.y,behavior:"smooth"}),{success:!0,message:`Scrolled to (${e.x}, ${e.y})`}}function getComputedStyles(e,t){const n=document.querySelector(e);if(!n)return{error:`No element found for selector: ${e}`};const r=getComputedStyle(n),o={},i=t??["display","position","width","height","color","background-color","font-size","font-family","margin","padding","border","opacity","visibility","overflow","z-index"];for(const e of i)o[e]=r.getPropertyValue(e);return o}function getElementBounds(e){const t=document.querySelector(e);if(!t)return{error:`No element found for selector: ${e}`};const n=t.getBoundingClientRect();return{bounds:{x:Math.round(n.x),y:Math.round(n.y),width:Math.round(n.width),height:Math.round(n.height)},visible:n.width>0&&n.height>0&&"hidden"!==getComputedStyle(t).visibility&&"none"!==getComputedStyle(t).display}}function getHtml(e,t,n){const r=t??!0,o=n??5e4,i=e?document.querySelector(e):document.documentElement;if(!i)return{error:`No element found for selector: ${e}`};const s=r?i.outerHTML:i.innerHTML,a=s.length>o;return{html:a?s.slice(0,o):s,length:s.length,truncated:a}}function resolveUrl(e,t){if(e.match(/^[a-z]+:\/\//i))return e;if(e.match(/^\/\//))return window.location.protocol+e;if(e.match(/^[a-z]+:/i))return e;const n=document.implementation.createHTMLDocument(),r=n.createElement("base"),o=n.createElement("a");return n.head.appendChild(r),n.body.appendChild(o),t&&(r.href=t),o.href=e,o.href}getPageInfo.__schema__={name:"getPageInfo",description:"Get information about the current web page including URL, title, viewport size, detected frameworks, and performance timing. Optionally include recent console logs.",parameters:{type:"object",properties:{include_logs:{type:"boolean",description:"If true, include recent console output in the response. Default: false."},log_limit:{type:"number",description:"Maximum number of console log entries to include (most recent). Default: 50."},log_level:{type:"string",description:'Filter console logs by level: "log", "warn", "error", "info". Omit for all levels.',enum:["log","warn","error","info"]}}}},getConsoleLogs.__schema__={name:"getConsoleLogs",description:"Retrieve captured console output (log, warn, error, info).",parameters:{type:"object",properties:{level:{type:"string",description:'Filter by log level: "log", "warn", "error", "info". Omit for all levels.',enum:["log","warn","error","info"]},limit:{type:"number",description:"Maximum number of log entries to return (most recent). Default: 100."}}}},queryDom.__schema__={name:"queryDom",description:"Query DOM elements by CSS selector. Returns tag, id, classes, text content, attributes, bounding rect, and visibility for each matching element.",parameters:{type:"object",properties:{selector:{type:"string",description:'CSS selector to query, e.g. "button.primary", "#app > div".'},limit:{type:"number",description:"Maximum number of elements to return. Default: 20."}},required:["selector"]}},clickElement$1.__schema__={name:"clickElement",description:"Click a DOM element matching the CSS selector.",parameters:{type:"object",properties:{selector:{type:"string",description:"CSS selector of the element to click."}},required:["selector"]}},fillInput.__schema__={name:"fillInput",description:"Set the value of an input, textarea, or select element. Works with React controlled components.",parameters:{type:"object",properties:{selector:{type:"string",description:"CSS selector of the input element."},value:{type:"string",description:"The value to set."}},required:["selector","value"]}},scrollTo.__schema__={name:"scrollTo",description:"Scroll to a DOM element (by CSS selector) or to an absolute position {x, y}.",parameters:{type:"object",properties:{target:{description:"CSS selector string to scroll to an element, or an object {x, y} for absolute scroll position."}},required:["target"]}},getComputedStyles.__schema__={name:"getComputedStyles",description:"Get computed CSS styles for an element.",parameters:{type:"object",properties:{selector:{type:"string",description:"CSS selector of the element."},properties:{type:"array",items:{type:"string"},description:'CSS property names to retrieve, e.g. ["color", "font-size"]. Omit for common defaults.'}},required:["selector"]}},getElementBounds.__schema__={name:"getElementBounds",description:"Get the bounding rectangle and visibility of a DOM element.",parameters:{type:"object",properties:{selector:{type:"string",description:"CSS selector of the element."}},required:["selector"]}},getHtml.__schema__={name:"getHtml",description:"Get the HTML content of the page or a specific element. Returns outerHTML by default. Useful for understanding page structure.",parameters:{type:"object",properties:{selector:{type:"string",description:"CSS selector of the element. Omit to get the full page HTML."},outer:{type:"boolean",description:"If true (default), return outerHTML (includes the element itself). If false, return innerHTML (children only)."},max_length:{type:"number",description:"Maximum character length of the returned HTML. Default: 50000. Result will be truncated if longer."}}}};const uuid=(()=>{let e=0;return()=>(e+=1,`u${`0000${(Math.random()*36**4|0).toString(36)}`.slice(-4)}${e}`)})();function toArray(e){const t=[];for(let n=0,r=e.length;n<r;n++)t.push(e[n]);return t}let styleProps=null;function getStyleProperties(e={}){return styleProps||(e.includeStyleProperties?(styleProps=e.includeStyleProperties,styleProps):(styleProps=toArray(window.getComputedStyle(document.documentElement)),styleProps))}function px(e,t){const n=(e.ownerDocument.defaultView||window).getComputedStyle(e).getPropertyValue(t);return n?parseFloat(n.replace("px","")):0}function getNodeWidth(e){const t=px(e,"border-left-width"),n=px(e,"border-right-width");return e.clientWidth+t+n}function getNodeHeight(e){const t=px(e,"border-top-width"),n=px(e,"border-bottom-width");return e.clientHeight+t+n}function getImageSize(e,t={}){return{width:t.width||getNodeWidth(e),height:t.height||getNodeHeight(e)}}function getPixelRatio(){let e,t;try{t=process}catch(e){}const n=t&&t.env?t.env.devicePixelRatio:null;return n&&(e=parseInt(n,10),Number.isNaN(e)&&(e=1)),e||window.devicePixelRatio||1}const canvasDimensionLimit=16384;function checkCanvasDimensions(e){(e.width>canvasDimensionLimit||e.height>canvasDimensionLimit)&&(e.width>canvasDimensionLimit&&e.height>canvasDimensionLimit?e.width>e.height?(e.height*=canvasDimensionLimit/e.width,e.width=canvasDimensionLimit):(e.width*=canvasDimensionLimit/e.height,e.height=canvasDimensionLimit):e.width>canvasDimensionLimit?(e.height*=canvasDimensionLimit/e.width,e.width=canvasDimensionLimit):(e.width*=canvasDimensionLimit/e.height,e.height=canvasDimensionLimit))}function createImage(e){return new Promise((t,n)=>{const r=new Image;r.onload=()=>{r.decode().then(()=>{requestAnimationFrame(()=>t(r))})},r.onerror=n,r.crossOrigin="anonymous",r.decoding="async",r.src=e})}async function svgToDataURL(e){return Promise.resolve().then(()=>(new XMLSerializer).serializeToString(e)).then(encodeURIComponent).then(e=>`data:image/svg+xml;charset=utf-8,${e}`)}async function nodeToDataURL(e,t,n){const r="http://www.w3.org/2000/svg",o=document.createElementNS(r,"svg"),i=document.createElementNS(r,"foreignObject");return o.setAttribute("width",`${t}`),o.setAttribute("height",`${n}`),o.setAttribute("viewBox",`0 0 ${t} ${n}`),i.setAttribute("width","100%"),i.setAttribute("height","100%"),i.setAttribute("x","0"),i.setAttribute("y","0"),i.setAttribute("externalResourcesRequired","true"),o.appendChild(i),i.appendChild(e),svgToDataURL(o)}const isInstanceOfElement=(e,t)=>{if(e instanceof t)return!0;const n=Object.getPrototypeOf(e);return null!==n&&(n.constructor.name===t.name||isInstanceOfElement(n,t))};function formatCSSText(e){const t=e.getPropertyValue("content");return`${e.cssText} content: '${t.replace(/'|"/g,"")}';`}function formatCSSProperties(e,t){return getStyleProperties(t).map(t=>`${t}: ${e.getPropertyValue(t)}${e.getPropertyPriority(t)?" !important":""};`).join(" ")}function getPseudoElementStyle(e,t,n,r){const o=`.${e}:${t}`,i=n.cssText?formatCSSText(n):formatCSSProperties(n,r);return document.createTextNode(`${o}{${i}}`)}function clonePseudoElement(e,t,n,r){const o=window.getComputedStyle(e,n),i=o.getPropertyValue("content");if(""===i||"none"===i)return;const s=uuid();try{t.className=`${t.className} ${s}`}catch(e){return}const a=document.createElement("style");a.appendChild(getPseudoElementStyle(s,n,o,r)),t.appendChild(a)}function clonePseudoElements(e,t,n){clonePseudoElement(e,t,":before",n),clonePseudoElement(e,t,":after",n)}const WOFF="application/font-woff",JPEG="image/jpeg",mimes={woff:WOFF,woff2:WOFF,ttf:"application/font-truetype",eot:"application/vnd.ms-fontobject",png:"image/png",jpg:JPEG,jpeg:JPEG,gif:"image/gif",tiff:"image/tiff",svg:"image/svg+xml",webp:"image/webp"};function getExtension(e){const t=/\.([^./]*?)$/g.exec(e);return t?t[1]:""}function getMimeType(e){const t=getExtension(e).toLowerCase();return mimes[t]||""}function getContentFromDataUrl(e){return e.split(/,/)[1]}function isDataUrl(e){return-1!==e.search(/^(data:)/)}function makeDataUrl(e,t){return`data:${t};base64,${e}`}async function fetchAsDataURL(e,t,n){const r=await fetch(e,t);if(404===r.status)throw new Error(`Resource "${r.url}" not found`);const o=await r.blob();return new Promise((e,t)=>{const i=new FileReader;i.onerror=t,i.onloadend=()=>{try{e(n({res:r,result:i.result}))}catch(e){t(e)}},i.readAsDataURL(o)})}const cache={};function getCacheKey(e,t,n){let r=e.replace(/\?.*/,"");return n&&(r=e),/ttf|otf|eot|woff2?/i.test(r)&&(r=r.replace(/.*\//,"")),t?`[${t}]${r}`:r}async function resourceToDataURL(e,t,n){const r=getCacheKey(e,t,n.includeQueryParams);if(null!=cache[r])return cache[r];let o;n.cacheBust&&(e+=(/\?/.test(e)?"&":"?")+(new Date).getTime());try{o=makeDataUrl(await fetchAsDataURL(e,n.fetchRequestInit,({res:e,result:n})=>(t||(t=e.headers.get("Content-Type")||""),getContentFromDataUrl(n))),t)}catch(t){o=n.imagePlaceholder||"";let r=`Failed to fetch resource: ${e}`;t&&(r="string"==typeof t?t:t.message),r&&console.warn(r)}return cache[r]=o,o}async function cloneCanvasElement(e){const t=e.toDataURL();return"data:,"===t?e.cloneNode(!1):createImage(t)}async function cloneVideoElement(e,t){if(e.currentSrc){const t=document.createElement("canvas"),n=t.getContext("2d");t.width=e.clientWidth,t.height=e.clientHeight,null==n||n.drawImage(e,0,0,t.width,t.height);return createImage(t.toDataURL())}const n=e.poster,r=getMimeType(n);return createImage(await resourceToDataURL(n,r,t))}async function cloneIFrameElement(e,t){var n;try{if(null===(n=null==e?void 0:e.contentDocument)||void 0===n?void 0:n.body)return await cloneNode(e.contentDocument.body,t,!0)}catch(e){}return e.cloneNode(!1)}async function cloneSingleNode(e,t){return isInstanceOfElement(e,HTMLCanvasElement)?cloneCanvasElement(e):isInstanceOfElement(e,HTMLVideoElement)?cloneVideoElement(e,t):isInstanceOfElement(e,HTMLIFrameElement)?cloneIFrameElement(e,t):e.cloneNode(isSVGElement(e))}const isSlotElement=e=>null!=e.tagName&&"SLOT"===e.tagName.toUpperCase(),isSVGElement=e=>null!=e.tagName&&"SVG"===e.tagName.toUpperCase();async function cloneChildren(e,t,n){var r,o;if(isSVGElement(t))return t;let i=[];return i=isSlotElement(e)&&e.assignedNodes?toArray(e.assignedNodes()):isInstanceOfElement(e,HTMLIFrameElement)&&(null===(r=e.contentDocument)||void 0===r?void 0:r.body)?toArray(e.contentDocument.body.childNodes):toArray((null!==(o=e.shadowRoot)&&void 0!==o?o:e).childNodes),0===i.length||isInstanceOfElement(e,HTMLVideoElement)||await i.reduce((e,r)=>e.then(()=>cloneNode(r,n)).then(e=>{e&&t.appendChild(e)}),Promise.resolve()),t}function cloneCSSStyle(e,t,n){const r=t.style;if(!r)return;const o=window.getComputedStyle(e);o.cssText?(r.cssText=o.cssText,r.transformOrigin=o.transformOrigin):getStyleProperties(n).forEach(n=>{let i=o.getPropertyValue(n);if("font-size"===n&&i.endsWith("px")){const e=Math.floor(parseFloat(i.substring(0,i.length-2)))-.1;i=`${e}px`}isInstanceOfElement(e,HTMLIFrameElement)&&"display"===n&&"inline"===i&&(i="block"),"d"===n&&t.getAttribute("d")&&(i=`path(${t.getAttribute("d")})`),r.setProperty(n,i,o.getPropertyPriority(n))})}function cloneInputValue(e,t){isInstanceOfElement(e,HTMLTextAreaElement)&&(t.innerHTML=e.value),isInstanceOfElement(e,HTMLInputElement)&&t.setAttribute("value",e.value)}function cloneSelectValue(e,t){if(isInstanceOfElement(e,HTMLSelectElement)){const n=t,r=Array.from(n.children).find(t=>e.value===t.getAttribute("value"));r&&r.setAttribute("selected","")}}function decorate(e,t,n){return isInstanceOfElement(t,Element)&&(cloneCSSStyle(e,t,n),clonePseudoElements(e,t,n),cloneInputValue(e,t),cloneSelectValue(e,t)),t}async function ensureSVGSymbols(e,t){const n=e.querySelectorAll?e.querySelectorAll("use"):[];if(0===n.length)return e;const r={};for(let o=0;o<n.length;o++){const i=n[o].getAttribute("xlink:href");if(i){const n=e.querySelector(i),o=document.querySelector(i);n||!o||r[i]||(r[i]=await cloneNode(o,t,!0))}}const o=Object.values(r);if(o.length){const t="http://www.w3.org/1999/xhtml",n=document.createElementNS(t,"svg");n.setAttribute("xmlns",t),n.style.position="absolute",n.style.width="0",n.style.height="0",n.style.overflow="hidden",n.style.display="none";const r=document.createElementNS(t,"defs");n.appendChild(r);for(let e=0;e<o.length;e++)r.appendChild(o[e]);e.appendChild(n)}return e}async function cloneNode(e,t,n){return n||!t.filter||t.filter(e)?Promise.resolve(e).then(e=>cloneSingleNode(e,t)).then(n=>cloneChildren(e,n,t)).then(n=>decorate(e,n,t)).then(e=>ensureSVGSymbols(e,t)):null}const URL_REGEX=/url\((['"]?)([^'"]+?)\1\)/g,URL_WITH_FORMAT_REGEX=/url\([^)]+\)\s*format\((["']?)([^"']+)\1\)/g,FONT_SRC_REGEX=/src:\s*(?:url\([^)]+\)\s*format\([^)]+\)[,;]\s*)+/g;function toRegex(e){const t=e.replace(/([.*+?^${}()|\[\]\/\\])/g,"\\$1");return new RegExp(`(url\\(['"]?)(${t})(['"]?\\))`,"g")}function parseURLs(e){const t=[];return e.replace(URL_REGEX,(e,n,r)=>(t.push(r),e)),t.filter(e=>!isDataUrl(e))}async function embed(e,t,n,r,o){try{const i=n?resolveUrl(t,n):t,s=getMimeType(t);let a;return o||(a=await resourceToDataURL(i,s,r)),e.replace(toRegex(t),`$1${a}$3`)}catch(e){}return e}function filterPreferredFontFormat(e,{preferredFontFormat:t}){return t?e.replace(FONT_SRC_REGEX,e=>{for(;;){const[n,,r]=URL_WITH_FORMAT_REGEX.exec(e)||[];if(!r)return"";if(r===t)return`src: ${n};`}}):e}function shouldEmbed(e){return-1!==e.search(URL_REGEX)}async function embedResources(e,t,n){if(!shouldEmbed(e))return e;const r=filterPreferredFontFormat(e,n);return parseURLs(r).reduce((e,r)=>e.then(e=>embed(e,r,t,n)),Promise.resolve(r))}async function embedProp(e,t,n){var r;const o=null===(r=t.style)||void 0===r?void 0:r.getPropertyValue(e);if(o){const r=await embedResources(o,null,n);return t.style.setProperty(e,r,t.style.getPropertyPriority(e)),!0}return!1}async function embedBackground(e,t){await embedProp("background",e,t)||await embedProp("background-image",e,t),await embedProp("mask",e,t)||await embedProp("-webkit-mask",e,t)||await embedProp("mask-image",e,t)||await embedProp("-webkit-mask-image",e,t)}async function embedImageNode(e,t){const n=isInstanceOfElement(e,HTMLImageElement);if((!n||isDataUrl(e.src))&&(!isInstanceOfElement(e,SVGImageElement)||isDataUrl(e.href.baseVal)))return;const r=n?e.src:e.href.baseVal,o=await resourceToDataURL(r,getMimeType(r),t);await new Promise((r,i)=>{e.onload=r,e.onerror=t.onImageErrorHandler?(...e)=>{try{r(t.onImageErrorHandler(...e))}catch(e){i(e)}}:i;const s=e;s.decode&&(s.decode=r),"lazy"===s.loading&&(s.loading="eager"),n?(e.srcset="",e.src=o):e.href.baseVal=o})}async function embedChildren(e,t){const n=toArray(e.childNodes).map(e=>embedImages(e,t));await Promise.all(n).then(()=>e)}async function embedImages(e,t){isInstanceOfElement(e,Element)&&(await embedBackground(e,t),await embedImageNode(e,t),await embedChildren(e,t))}function applyStyle(e,t){const{style:n}=e;t.backgroundColor&&(n.backgroundColor=t.backgroundColor),t.width&&(n.width=`${t.width}px`),t.height&&(n.height=`${t.height}px`);const r=t.style;return null!=r&&Object.keys(r).forEach(e=>{n[e]=r[e]}),e}const cssFetchCache={};async function fetchCSS(e){let t=cssFetchCache[e];if(null!=t)return t;const n=await fetch(e);return t={url:e,cssText:await n.text()},cssFetchCache[e]=t,t}async function embedFonts(e,t){let n=e.cssText;const r=/url\(["']?([^"')]+)["']?\)/g,o=(n.match(/url\([^)]+\)/g)||[]).map(async o=>{let i=o.replace(r,"$1");return i.startsWith("https://")||(i=new URL(i,e.url).href),fetchAsDataURL(i,t.fetchRequestInit,({result:e})=>(n=n.replace(o,`url(${e})`),[o,e]))});return Promise.all(o).then(()=>n)}function parseCSS(e){if(null==e)return[];const t=[];let n=e.replace(/(\/\*[\s\S]*?\*\/)/gi,"");const r=new RegExp("((@.*?keyframes [\\s\\S]*?){([\\s\\S]*?}\\s*?)})","gi");for(;;){const e=r.exec(n);if(null===e)break;t.push(e[0])}n=n.replace(r,"");const o=/@import[\s\S]*?url\([^)]*\)[\s\S]*?;/gi,i=new RegExp("((\\s*?(?:\\/\\*[\\s\\S]*?\\*\\/)?\\s*?@media[\\s\\S]*?){([\\s\\S]*?)}\\s*?})|(([\\s\\S]*?){([\\s\\S]*?)})","gi");for(;;){let e=o.exec(n);if(null===e){if(e=i.exec(n),null===e)break;o.lastIndex=i.lastIndex}else i.lastIndex=o.lastIndex;t.push(e[0])}return t}async function getCSSRules(e,t){const n=[],r=[];return e.forEach(n=>{if("cssRules"in n)try{toArray(n.cssRules||[]).forEach((e,o)=>{if(e.type===CSSRule.IMPORT_RULE){let i=o+1;const s=fetchCSS(e.href).then(e=>embedFonts(e,t)).then(e=>parseCSS(e).forEach(e=>{try{n.insertRule(e,e.startsWith("@import")?i+=1:n.cssRules.length)}catch(t){console.error("Error inserting rule from remote css",{rule:e,error:t})}})).catch(e=>{console.error("Error loading remote css",e.toString())});r.push(s)}})}catch(o){const i=e.find(e=>null==e.href)||document.styleSheets[0];null!=n.href&&r.push(fetchCSS(n.href).then(e=>embedFonts(e,t)).then(e=>parseCSS(e).forEach(e=>{i.insertRule(e,i.cssRules.length)})).catch(e=>{console.error("Error loading remote stylesheet",e)})),console.error("Error inlining remote css file",o)}}),Promise.all(r).then(()=>(e.forEach(e=>{if("cssRules"in e)try{toArray(e.cssRules||[]).forEach(e=>{n.push(e)})}catch(t){console.error(`Error while reading CSS rules from ${e.href}`,t)}}),n))}function getWebFontRules(e){return e.filter(e=>e.type===CSSRule.FONT_FACE_RULE).filter(e=>shouldEmbed(e.style.getPropertyValue("src")))}async function parseWebFontRules(e,t){if(null==e.ownerDocument)throw new Error("Provided element is not within a Document");const n=toArray(e.ownerDocument.styleSheets);return getWebFontRules(await getCSSRules(n,t))}function normalizeFontFamily(e){return e.trim().replace(/["']/g,"")}function getUsedFonts(e){const t=new Set;return function e(n){(n.style.fontFamily||getComputedStyle(n).fontFamily).split(",").forEach(e=>{t.add(normalizeFontFamily(e))}),Array.from(n.children).forEach(t=>{t instanceof HTMLElement&&e(t)})}(e),t}async function getWebFontCSS(e,t){const n=await parseWebFontRules(e,t),r=getUsedFonts(e);return(await Promise.all(n.filter(e=>r.has(normalizeFontFamily(e.style.fontFamily))).map(e=>{const n=e.parentStyleSheet?e.parentStyleSheet.href:null;return embedResources(e.cssText,n,t)}))).join("\n")}async function embedWebFonts(e,t){const n=null!=t.fontEmbedCSS?t.fontEmbedCSS:t.skipFonts?null:await getWebFontCSS(e,t);if(n){const t=document.createElement("style"),r=document.createTextNode(n);t.appendChild(r),e.firstChild?e.insertBefore(t,e.firstChild):e.appendChild(t)}}async function toSvg(e,t={}){const{width:n,height:r}=getImageSize(e,t),o=await cloneNode(e,t,!0);await embedWebFonts(o,t),await embedImages(o,t),applyStyle(o,t);return await nodeToDataURL(o,n,r)}async function toCanvas(e,t={}){const{width:n,height:r}=getImageSize(e,t),o=await toSvg(e,t),i=await createImage(o),s=document.createElement("canvas"),a=s.getContext("2d"),c=t.pixelRatio||getPixelRatio(),l=t.canvasWidth||n,d=t.canvasHeight||r;return s.width=l*c,s.height=d*c,t.skipAutoScale||checkCanvasDimensions(s),s.style.width=`${l}`,s.style.height=`${d}`,t.backgroundColor&&(a.fillStyle=t.backgroundColor,a.fillRect(0,0,s.width,s.height)),a.drawImage(i,0,0,s.width,s.height),s}async function toPng(e,t={}){return(await toCanvas(e,t)).toDataURL()}async function toJpeg(e,t={}){return(await toCanvas(e,t)).toDataURL("image/jpeg",t.quality||1)}function errorMessage(e){if(!e)return"Unknown error";if("string"==typeof e)return e;if(e.message)return e.message;if(e instanceof Event)return`Event: ${e.type}`;try{return JSON.stringify(e)}catch{return String(e)}}async function resizeDataUrl(e,t,n,r,o){return new Promise((i,s)=>{const a=new Image;a.onload=()=>{try{const e=a.naturalWidth,c=a.naturalHeight,l=Math.min(t/e,n/c,1),d=Math.max(1,Math.round(e*l)),h=Math.max(1,Math.round(c*l)),u=document.createElement("canvas");u.width=d,u.height=h;const p=u.getContext("2d");if(!p)return void s(new Error("Could not get 2D canvas context"));"jpeg"===r&&(p.fillStyle="#ffffff",p.fillRect(0,0,d,h)),p.drawImage(a,0,0,d,h);const _="jpeg"===r?"image/jpeg":"image/png",f=u.toDataURL(_,o);i({dataUrl:f,width:d,height:h})}catch(e){s(new Error(`Canvas resize failed: ${errorMessage(e)}`))}},a.onerror=e=>s(new Error("Failed to load captured image for resizing"+(e instanceof Event?` (${e.type})`:""))),a.src=e})}async function takeScreenshot(e,t,n,r,o,i){const s=t??"jpeg",a=n??.75,c=r??1024,l=o??1024,d=i??!1;let h;if(e){if(h=document.querySelector(e),!h)return{error:`No element found for selector: ${e}`}}else h=d?document.documentElement:document.body;try{const t=h,n=window.innerWidth,r=window.innerHeight,o={quality:a,pixelRatio:1,cacheBust:!0,skipAutoScale:!0,skipFonts:!0,imagePlaceholder:"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAQAAAC1HAwCAAAAC0lEQVR42mNkAAIAAAoAAv/lxKUAAAAASUVORK5CYII=",filter:e=>"hypha-debugger-host"!==e.id&&"hypha-debugger-cursor"!==e.id&&"playwright-highlight-container"!==e.id};e||d||(o.width=n,o.height=r);const i=async(e,n=15e3)=>{const r="jpeg"===s?toJpeg(t,e):toPng(t,e);return Promise.race([r,new Promise((e,t)=>setTimeout(()=>t(new Error(`Screenshot capture timed out after ${n}ms`)),n))])};let u;try{u=await i(o)}catch(e){try{const e={...o,filter:e=>{if(!o.filter(e))return!1;const t=e.tagName?.toLowerCase();return"img"!==t&&"picture"!==t&&"video"!==t}};u=await i(e,1e4)}catch(t){return{error:`Capture failed: ${errorMessage(e)} (retry without images also failed: ${errorMessage(t)})`}}}try{const e=await resizeDataUrl(u,c,l,s,a),t=Math.round(.75*e.dataUrl.length/1024);return{data:e.dataUrl,format:s,width:e.width,height:e.height,size_kb:t}}catch(e){const n=t.getBoundingClientRect(),r=Math.round(.75*u.length/1024);return{data:u,format:s,width:Math.round(n.width),height:Math.round(n.height),size_kb:r,warning:`Resize failed, returning original: ${errorMessage(e)}`}}}catch(e){return{error:`Screenshot failed: ${errorMessage(e)}`}}}function autoReturn(e){const t=e.trim();if(/\breturn\b/.test(t))return t;let n=t.split("\n").map(e=>e.trim()).filter(Boolean);if(1===n.length&&n[0].includes(";")&&(n=n[0].split(";").map(e=>e.trim()).filter(Boolean)),0===n.length)return t;const r=n[n.length-1];return/^(if|for|while|switch|try|class|function |const |let |var |import |export )/.test(r)?t:(n[n.length-1]="return ("+r.replace(/;$/,"")+");",n.join(";\n"))}async function executeScript(e,t){const n=t??1e4;try{let t,r=autoReturn(e);try{t=new Function("return (async () => {"+r+"})()")}catch{t=new Function("return (async () => {"+e+"})()")}const o=await Promise.race([t(),new Promise((e,t)=>setTimeout(()=>t(new Error("Execution timed out")),n))]);let i,s=typeof o;try{void 0===o?(i=null,s="undefined"):o instanceof HTMLElement?(i={tag:o.tagName.toLowerCase(),id:o.id,className:o.className,text:(o.textContent??"").trim().slice(0,500)},s="HTMLElement"):o instanceof NodeList||o instanceof HTMLCollection?(i=Array.from(o).map(e=>({tag:e.tagName?.toLowerCase(),id:e.id,text:(e.textContent??"").trim().slice(0,200)})),s="NodeList"):i=JSON.parse(JSON.stringify(o))}catch{i=String(o),s="string (serialized)"}return{result:i,type:s}}catch(e){return{error:`Execution error: ${e.message??e}`}}}takeScreenshot.__schema__={name:"takeScreenshot",description:"Capture a screenshot of the current viewport, a specific element, or the full page. Downscaled to fit within max_width × max_height (default 1024px) to keep the payload small enough for AI agents. Defaults to JPEG at 0.75 quality. Returns: { data: 'data:image/jpeg;base64,...', format, width, height, size_kb }. Note: the image is in the `data` field as a full data: URL — strip the `data:...;base64,` prefix before base64-decoding.",parameters:{type:"object",properties:{selector:{type:"string",description:"CSS selector of the element to capture. Omit to capture the viewport (or full page if full_page=true)."},format:{type:"string",enum:["png","jpeg"],description:'Image format. Default: "jpeg" (much smaller than PNG). Use "png" for sharp text.'},quality:{type:"number",description:"JPEG quality (0–1). Default: 0.75. Ignored for PNG. Lower = smaller payload."},max_width:{type:"number",description:"Maximum output width in pixels. Default: 1024. Image is scaled down preserving aspect ratio."},max_height:{type:"number",description:"Maximum output height in pixels. Default: 1024. Image is scaled down preserving aspect ratio."},full_page:{type:"boolean",description:"If true, capture the entire scrollable page instead of just the viewport. Default: false."}}}},executeScript.__schema__={name:"executeScript",description:'Execute arbitrary JavaScript code in the page context. Supports async/await. The last expression is auto-returned (no need for explicit "return"). Examples: "document.title", "document.querySelectorAll(\'a\').length", "await fetch(\'/api/data\').then(r => r.json())". Returns: { result, type } on success, or { error } on exception.',parameters:{type:"object",properties:{code:{type:"string",description:'JavaScript code to execute. The last expression is automatically returned. Examples: "document.title", "document.querySelector(\'h1\').textContent".'},timeout_ms:{type:"number",description:"Maximum execution time in milliseconds. Default: 10000."}},required:["code"]}};const STORAGE_KEY$1="__hypha_debugger_config__";function getScriptUrl(){try{const e=sessionStorage.getItem(STORAGE_KEY$1);if(e){const t=JSON.parse(e);if(t.script_url)return t.script_url}}catch{}return"https://cdn.jsdelivr.net/npm/hypha-debugger/dist/hypha-debugger.min.js"}function injectLoader(e,t){const n=`<script src="${t}"><\/script>`;return e.includes("</body>")?e.replace("</body>",n+"\n</body>"):e.includes("</html>")?e.replace("</html>",n+"\n</html>"):e+"\n"+n}function softReplace(e,t){const n=getScriptUrl();fetch(e,{credentials:"same-origin",cache:"reload"}).then(e=>{if(!e.ok)throw new Error(`HTTP ${e.status}`);if(!(e.headers.get("content-type")??"").includes("text/html"))throw new Error("Not HTML");return e.text()}).then(e=>{const r=injectLoader(e,n);if(document.open(),document.write(r),document.close(),t)try{history.pushState({},"",t)}catch{}}).catch(()=>{t?window.location.href=t:window.location.reload()})}function isSameOrigin(e){try{return new URL(e,location.href).origin===location.origin}catch{return!1}}let _interceptInstalled=!1;function installNavigationInterceptor(){if(_interceptInstalled)return()=>{};_interceptInstalled=!0;const e=e=>{if(e.defaultPrevented||0!==e.button)return;if(e.metaKey||e.ctrlKey||e.shiftKey||e.altKey)return;let t=null,n=e.target;for(;n;){if("A"===n.tagName){t=n;break}n=n.parentElement}if(!t)return;const r=t.href;if(!r)return;if(t.target&&"_self"!==t.target)return;if(t.hasAttribute("download"))return;if(r.startsWith("javascript:")||r.startsWith("mailto:")||r.startsWith("tel:"))return;try{const e=new URL(r,location.href);if(e.origin===location.origin&&e.pathname===location.pathname&&e.search===location.search&&e.hash!==location.hash)return}catch{return}if(!isSameOrigin(r))return;e.preventDefault();const o=new URL(r,location.href).href;softReplace(o,o)},t=e=>{if(e.defaultPrevented)return;const t=e.target;if("GET"!==(t.method||"GET").toUpperCase())return;const n=t.action||location.href;if(!isSameOrigin(n))return;const r=new FormData(t),o=new URL(n,location.href);for(const[e,t]of r.entries())"string"==typeof t&&o.searchParams.set(e,t);t.target&&"_self"!==t.target||(e.preventDefault(),softReplace(o.href,o.href))},n=()=>{softReplace(location.href)};return document.addEventListener("click",e,!0),document.addEventListener("submit",t,!0),window.addEventListener("popstate",n),()=>{document.removeEventListener("click",e,!0),document.removeEventListener("submit",t,!0),window.removeEventListener("popstate",n),_interceptInstalled=!1}}function navigate(e){try{const t=new URL(e,location.href);return t.origin===location.origin?(setTimeout(()=>softReplace(t.href,t.href),150),{success:!0,message:`Navigating to ${e} (debugger will auto-reconnect)`}):(window.location.href=e,{success:!0,message:`Navigating to ${e} (cross-origin, debugger will disconnect)`})}catch(e){return{success:!1,message:`Navigation failed: ${e.message??e}`}}}function goBack(){try{return window.history.back(),{success:!0,message:"Navigated back (debugger will auto-reconnect via popstate)"}}catch(e){return{success:!1,message:`Back navigation failed: ${e.message??e}`}}}function goForward(){try{return window.history.forward(),{success:!0,message:"Navigated forward (debugger will auto-reconnect via popstate)"}}catch(e){return{success:!1,message:`Forward navigation failed: ${e.message??e}`}}}function reload(){try{return setTimeout(()=>softReplace(location.href),150),{success:!0,message:"Reloading page (debugger will auto-reconnect)"}}catch(e){return{success:!1,message:`Reload failed: ${e.message??e}`}}}function getFiberFromDOM(e){const t=Object.keys(e).find(e=>e.startsWith("__reactFiber$")||e.startsWith("__reactInternalInstance$"));return t?e[t]:null}function findReactRoot(){const e=["#root","#app","#__next","[data-reactroot]","main","body"];for(const t of e){const e=document.querySelector(t);if(e&&getFiberFromDOM(e))return e}const t=document.createTreeWalker(document.body,NodeFilter.SHOW_ELEMENT,null);let n=t.currentNode;for(;n;){if(n instanceof Element&&getFiberFromDOM(n))return n;n=t.nextNode()}return null}function getComponentName(e){const{type:t}=e;if(!t)return"(unknown)";if("string"==typeof t)return t;if("function"==typeof t)return t.displayName||t.name||"Anonymous";if("object"==typeof t){if(t.displayName)return t.displayName;if(t.render)return t.render.displayName||t.render.name||"ForwardRef";if(t.type)return getComponentName({type:t.type});if("Symbol(react.memo)"===t.$$typeof?.toString())return`Memo(${getComponentName({type:t.type})})`}return"(unknown)"}function getFiberType(e){return 0===e.tag||11===e.tag||14===e.tag||15===e.tag?"function":1===e.tag?"class":5===e.tag||6===e.tag?"host":"other"}function safeSerialize(e,t=0,n=2){if(t>n)return"[max depth]";if(null==e)return e;if("function"==typeof e)return`[Function: ${e.name||"anonymous"}]`;if("object"!=typeof e)return e;if(e instanceof HTMLElement)return`[${e.tagName.toLowerCase()}#${e.id}]`;if(Array.isArray(e))return e.slice(0,10).map(e=>safeSerialize(e,t+1,n));const r={},o=Object.keys(e).slice(0,20);for(const i of o)if(!i.startsWith("_")&&!i.startsWith("$$"))try{r[i]=safeSerialize(e[i],t+1,n)}catch{r[i]="[unserializable]"}return r}function extractState(e){if(1===e.tag&&e.stateNode)return safeSerialize(e.stateNode.state);if(0===e.tag||11===e.tag||15===e.tag){const t=[];let n=e.memoizedState,r=0;for(;n&&r<20;)null!==n.queue&&void 0!==n.queue&&t.push(safeSerialize(n.memoizedState)),n=n.next,r++;return t.length>0?t:null}return null}function fiberToInfo(e,t,n){const r=getFiberType(e),o="function"===r||"class"===r,i={name:getComponentName(e),type:r,props:o?safeSerialize(e.memoizedProps):{},state:o?extractState(e):null,key:e.key,children:[]};if(t<n){let r=e.child;for(;r;){const e=fiberToInfo(r,t+1,n);e&&("host"!==e.type||e.children.length>0)&&i.children.push(e),r=r.sibling}}return i}function getReactTree(e,t){const n=t??5;let r,o;if(e){if(r=document.querySelector(e),o=e,!r)return{error:`No element found for selector: ${e}`}}else if(r=findReactRoot(),o=r?.tagName.toLowerCase()+(r?.id?"#"+r.id:"")||"(auto)",!r)return{error:"No React root found on this page. Tried #root, #app, #__next, [data-reactroot], main, body — none had React fibers. This page may not be a React app, or React may not have rendered yet. Pass an explicit `selector` if you know the mount point."};const i=getFiberFromDOM(r);if(!i)return{error:`No React fiber found on element "${o}". Is this a React app?`};let s=i;for(;s&&3===s.tag;)s=s.child;if(!s)return{error:"Could not find root React component fiber."};const a=fiberToInfo(s,0,n);return a||{error:"Could not build React component tree."}}function generateSkillMd(e,t){const n=["---","name: web-debugger","description: Remote web page debugger. Inspect DOM, take screenshots, execute JavaScript, fill forms, click elements, and navigate pages — all via HTTP API calls.","compatibility: Requires network access to the Hypha server. Works with any HTTP client (curl, fetch, Python requests).","metadata:",' version: "0.1"',' author: "hypha-debugger"',"---"].join("\n"),r=["","# Web Debugger Skill","","This skill allows you to remotely debug and interact with a web page through HTTP API endpoints.","Pick the approach that fits your task — they can be combined freely.","","## Approaches","","### execute_script — Run Arbitrary JavaScript","","The most versatile function. Use it to read/modify page state, call APIs, query the DOM,","or do anything JavaScript can do. The last expression is auto-returned (no need for `return`).","","```bash","# Read page state","curl -X POST '{SERVICE_URL}/execute_script' \\"," -H 'Content-Type: application/json' -d '{\"code\": \"document.title\"}'","","# Query DOM","curl -X POST '{SERVICE_URL}/execute_script' \\",' -H \'Content-Type: application/json\' -d \'{"code": "document.querySelector(\\"h1\\").textContent"}\'',"","# Call an API","curl -X POST '{SERVICE_URL}/execute_script' \\",' -H \'Content-Type: application/json\' -d \'{"code": "await fetch(\\"/api/data\\").then(r => r.json())"}\'',"","# Modify the page","curl -X POST '{SERVICE_URL}/execute_script' \\",' -H \'Content-Type: application/json\' -d \'{"code": "document.getElementById(\\"name\\").value = \\"Alice\\""}\'',"```","","### get_browser_state + Index-Based Interaction","","Best for UI interaction as a user would — clicking buttons, filling forms, selecting options.","All interactive elements are detected and indexed as `[0]`, `[1]`, `[2]`, etc.","","```bash","# Step 1: See all interactive elements","curl '{SERVICE_URL}/get_browser_state'","","# Step 2: Act by index","curl -X POST '{SERVICE_URL}/click_element_by_index' \\"," -H 'Content-Type: application/json' -d '{\"index\": 2}'","","curl -X POST '{SERVICE_URL}/input_text' \\",' -H \'Content-Type: application/json\' -d \'{"index": 1, "text": "hello world"}\'',"","curl -X POST '{SERVICE_URL}/select_option' \\",' -H \'Content-Type: application/json\' -d \'{"index": 3, "option_text": "French"}\'',"","curl -X POST '{SERVICE_URL}/scroll' \\"," -H 'Content-Type: application/json' -d '{\"direction\": \"down\"}'","","# Step 3: Verify visually","curl '{SERVICE_URL}/take_screenshot'","```","","### get_react_tree — Inspect React Components","","If the page uses React, inspect component names, props, state, and hooks:","```bash","curl '{SERVICE_URL}/get_react_tree'","```","","### CSS Selector-Based Functions","","Use CSS selectors directly when you know the element:","```bash","curl -X POST '{SERVICE_URL}/click_element' \\"," -H 'Content-Type: application/json' -d '{\"selector\": \"button.submit\"}'","","curl -X POST '{SERVICE_URL}/fill_input' \\",' -H \'Content-Type: application/json\' -d \'{"selector": "#email", "value": "user@example.com"}\'',"","curl -X POST '{SERVICE_URL}/query_dom' \\"," -H 'Content-Type: application/json' -d '{\"selector\": \".product-card\"}'","```","","## How to call functions","","All functions are available as HTTP endpoints. Replace `{SERVICE_URL}` with the actual service URL.","","- **GET** for functions with no required parameters","- **POST** with JSON body for functions with parameters","- Append `?_mode=last` to resolve the most recent instance (recommended after page reloads where the clientId changes)","","## Response format","","All functions return JSON. There are three patterns:","","**1. Data-returning functions** (e.g. `take_screenshot`, `get_page_info`, `execute_script`, `get_browser_state`, `get_html`, `get_react_tree`) return function-specific keys:","","- `take_screenshot` → `{data, format, width, height, size_kb}` where `data` is a `data:image/jpeg;base64,...` URL (note: field is `data`, not `screenshot` or `image`)","- `execute_script` → `{result, type}` (or `{error}` on exception)","- `get_browser_state` → `{url, title, header, content, footer, element_count}`","- `get_page_info` → `{url, title, viewport_width, viewport_height, ...}`","- `get_html` → `{html, length, truncated}`","","**2. Action functions** (e.g. `click_*`, `input_text`, `select_option`, `scroll`, `navigate`) return:","",'- `{success: true, message: "..."}` — action succeeded','- `{success: false, message: "..."}` — action failed (element not found, etc.)',"","**3. Errors from the Hypha gateway** (NOT from the service itself) return:","",'- `{success: false, detail: "..."}` — e.g. service not found, call timed out, disconnected. If you see this, the browser tab is probably closed or the debugger crashed.',""].join("\n"),o=["## Available Functions",""],i=Object.entries(e).filter(([e,t])=>t?.__schema__&&"get_skill_md"!==e);for(const[e,t]of i){const n=t.__schema__;o.push(`### \`${e}\``),o.push(""),o.push(n.description),o.push("");const r=n.parameters?.properties,i=n.parameters?.required??[];if(r&&Object.keys(r).length>0){o.push("**Parameters:**"),o.push(""),o.push("| Parameter | Type | Required | Description |"),o.push("|-----------|------|----------|-------------|");for(const[e,t]of Object.entries(r)){const n=i.includes(e);let r=t.type??"any";t.enum&&(r=t.enum.map(e=>`"${e}"`).join(" / ")),t.items&&(r=`${t.items.type}[]`);const s=(t.description??"").replace(/\|/g,"\\|");o.push(`| \`${e}\` | ${r} | ${n?"Yes":"No"} | ${s} |`)}if(o.push(""),i.length>0){const t={};for(const e of i){const n=r[e];t[e]="string"===n?.type?`<${e}>`:"number"===n?.type?"0":`<${e}>`}o.push("**Example:**"),o.push("```bash"),o.push(`curl -X POST '{SERVICE_URL}/${e}' \\`),o.push(" -H 'Content-Type: application/json' \\"),o.push(` -d '${JSON.stringify(t)}'`),o.push("```")}else o.push("**Example:**"),o.push("```bash"),o.push(`curl '{SERVICE_URL}/${e}'`),o.push("```")}else o.push("**Parameters:** None"),o.push(""),o.push("**Example:**"),o.push("```bash"),o.push(`curl '{SERVICE_URL}/${e}'`),o.push("```");o.push("")}const s=["## Tips","","- **`execute_script` is the most versatile** — use it for reading state, calling APIs, DOM queries, or anything not covered by other functions. The last expression is auto-returned. Returns `{result, type}`.","- **`get_browser_state` is the best way to see what's on the page** — it detects all interactive elements and shows them as indexed items.","- **After each action, call `get_browser_state` again** — element indices change when the DOM updates.","- **Use `take_screenshot`** to visually verify the page state. The image is returned in the `data` field as a `data:image/jpeg;base64,...` URL — strip the `data:...;base64,` prefix before decoding.","- **Use `remove_highlights`** before a screenshot for a clean view.","- **Use `scroll`** with an element index to scroll inside a specific container (e.g. a chat window, sidebar).","- **Use `get_page_info` with `include_logs=true`** to check for JavaScript errors or debug output.","- **Use `get_react_tree`** if the page uses React — it gives you component names, props, and state without needing DevTools.","- **Use `navigate`** to go to other pages — same-origin navigation auto-reconnects the debugger.",'- **If you get `{success: false, detail: "Service not found"}`** — the browser tab was closed or the debugger disconnected. The user needs to re-click the bookmarklet.',"- **Append `?_mode=last`** to the URL if the service clientId changed (e.g. after page reload) — resolves to the most recent instance.","- All POST endpoints accept JSON body with the parameter names as keys.",""].join("\n");return[n,r,o.join("\n"),s].join("\n")}function wrapFn(e){const t=e.__schema__,n=t?.parameters?.properties?Object.keys(t.parameters.properties):[];if(0===n.length)return e;const r=n.join(", "),o=n[0],i=new Function("fn","paramNames",`return async function(${r}) {\n // Detect kwargs-as-object: single argument that is a plain object\n if (arguments.length === 1 && ${o} != null && typeof ${o} === "object" && !Array.isArray(${o}) && !(${o} instanceof Date) && ${o}.constructor === Object) {\n var _kw = ${o};\n var _keys = Object.keys(_kw);\n // Empty object {} → call with no args (all defaults)\n if (_keys.length === 0) {\n return fn();\n }\n // Keys match schema params → destructure\n if (paramNames.indexOf(_keys[0]) !== -1) {\n var _args = paramNames.map(function(n) { return _kw[n]; });\n return fn.apply(null, _args);\n }\n }\n return fn(${r});\n }`)(e,n);return t&&(i.__schema__=t),i}navigate.__schema__={name:"navigate",description:"Navigate the browser to a new URL. For same-origin URLs, the debugger auto-reconnects. Cross-origin navigation will disconnect the debugger.",parameters:{type:"object",properties:{url:{type:"string",description:"The URL to navigate to."}},required:["url"]}},goBack.__schema__={name:"goBack",description:"Navigate back in browser history. The debugger auto-reconnects for same-origin pages.",parameters:{type:"object",properties:{}}},goForward.__schema__={name:"goForward",description:"Navigate forward in browser history. The debugger auto-reconnects for same-origin pages.",parameters:{type:"object",properties:{}}},reload.__schema__={name:"reload",description:"Reload the current page. The debugger auto-reconnects after reload using soft page replacement.",parameters:{type:"object",properties:{}}},getReactTree.__schema__={name:"getReactTree",description:"Inspect the React component tree. Returns component names, props, state (including hooks), and children hierarchy. When no selector is provided, auto-detects the React root by scanning common mount points (#root, #app, #__next, [data-reactroot], main, body) and then walking the DOM for any element with a React fiber attached.",parameters:{type:"object",properties:{selector:{type:"string",description:"CSS selector of the React root element. Omit for auto-detection."},max_depth:{type:"number",description:"Maximum depth to traverse the component tree. Default: 5."}}}};var domTree=(e={doHighlightElements:!0,focusHighlightIndex:-1,viewportExpansion:0,debugMode:!1,interactiveBlacklist:[],interactiveWhitelist:[],highlightOpacity:.1,highlightLabelOpacity:.5})=>{const{interactiveBlacklist:t,interactiveWhitelist:n,highlightOpacity:r,highlightLabelOpacity:o}=e,{doHighlightElements:i,focusHighlightIndex:s,viewportExpansion:a,debugMode:c}=e;let l=0;const d=new WeakMap;const h={boundingRects:new WeakMap,clientRects:new WeakMap,computedStyles:new WeakMap,clearCache:()=>{h.boundingRects=new WeakMap,h.clientRects=new WeakMap,h.computedStyles=new WeakMap}};function u(e){if(!e)return null;if(h.boundingRects.has(e))return h.boundingRects.get(e);const t=e.getBoundingClientRect();return t&&h.boundingRects.set(e,t),t}function p(e){if(!e)return null;if(h.computedStyles.has(e))return h.computedStyles.get(e);const t=window.getComputedStyle(e);return t&&h.computedStyles.set(e,t),t}const _={},f={current:0},m="playwright-highlight-container";function g(e,t,n=null){if(!e)return t;const i=[];let s=null,a=20,c=16,l=null;try{let d=document.getElementById(m);d||(d=document.createElement("div"),d.id=m,d.style.position="fixed",d.style.pointerEvents="none",d.style.top="0",d.style.left="0",d.style.width="100%",d.style.height="100%",d.style.zIndex="2147483640",d.style.backgroundColor="transparent",document.body.appendChild(d));const h=e.getClientRects();if(!h||0===h.length)return t;const u=["#FF0000","#00FF00","#0000FF","#FFA500","#800080","#008080","#FF69B4","#4B0082","#FF4500","#2E8B57","#DC143C","#4682B4"];let p=u[t%u.length];const _=p+Math.floor(255*r).toString(16).padStart(2,"0");p+=Math.floor(255*o).toString(16).padStart(2,"0");let f={x:0,y:0};if(n){const e=n.getBoundingClientRect();f.x=e.left,f.y=e.top}const g=document.createDocumentFragment();for(const e of h){if(0===e.width||0===e.height)continue;const t=document.createElement("div");t.style.position="fixed",t.style.border=`2px solid ${p}`,t.style.backgroundColor=_,t.style.pointerEvents="none",t.style.boxSizing="border-box";const n=e.top+f.y,r=e.left+f.x;t.style.top=`${n}px`,t.style.left=`${r}px`,t.style.width=`${e.width}px`,t.style.height=`${e.height}px`,g.appendChild(t),i.push({element:t,initialRect:e})}const y=h[0];s=document.createElement("div"),s.className="playwright-highlight-label",s.style.position="fixed",s.style.background=p,s.style.color="white",s.style.padding="1px 4px",s.style.borderRadius="4px",s.style.fontSize=`${Math.min(12,Math.max(8,y.height/2))}px`,s.textContent=t.toString(),a=s.offsetWidth>0?s.offsetWidth:a,c=s.offsetHeight>0?s.offsetHeight:c;const w=y.top+f.y,b=y.left+f.x;let v=w+2,E=b+y.width-a-2;(y.width<a+4||y.height<c+4)&&(v=w-c-2,E=b+y.width-a,E<f.x&&(E=b)),v=Math.max(0,Math.min(v,window.innerHeight-c)),E=Math.max(0,Math.min(E,window.innerWidth-a)),s.style.top=`${v}px`,s.style.left=`${E}px`,g.appendChild(s);const k=(e,t)=>{let n=0;return(...r)=>{const o=performance.now();if(!(o-n<t))return n=o,e(...r)}},x=k(()=>{const t=e.getClientRects();let r={x:0,y:0};if(n){const e=n.getBoundingClientRect();r.x=e.left,r.y=e.top}if(i.forEach((e,n)=>{if(n<t.length){const o=t[n],i=o.top+r.y,s=o.left+r.x;e.element.style.top=`${i}px`,e.element.style.left=`${s}px`,e.element.style.width=`${o.width}px`,e.element.style.height=`${o.height}px`,e.element.style.display=0===o.width||0===o.height?"none":"block"}else e.element.style.display="none"}),t.length<i.length)for(let e=t.length;e<i.length;e++)i[e].element.style.display="none";if(s&&t.length>0){const e=t[0],n=e.top+r.y,o=e.left+r.x;let i=n+2,l=o+e.width-a-2;(e.width<a+4||e.height<c+4)&&(i=n-c-2,l=o+e.width-a,l<r.x&&(l=o)),i=Math.max(0,Math.min(i,window.innerHeight-c)),l=Math.max(0,Math.min(l,window.innerWidth-a)),s.style.top=`${i}px`,s.style.left=`${l}px`,s.style.display="block"}else s&&(s.style.display="none")},16);return window.addEventListener("scroll",x,!0),window.addEventListener("resize",x),l=()=>{window.removeEventListener("scroll",x,!0),window.removeEventListener("resize",x),i.forEach(e=>e.element.remove()),s&&s.remove()},d.appendChild(g),t+1}finally{l&&(window._highlightCleanupFunctions=window._highlightCleanupFunctions||[]).push(l)}}function y(e){if(!e||e.nodeType!==Node.ELEMENT_NODE)return null;const t=p(e);if(!t)return null;const n=t.display;if("inline"===n||"inline-block"===n)return null;const r=t.overflowX,o=t.overflowY,i="auto"===r||"scroll"===r,s="auto"===o||"scroll"===o;if(!i&&!s)return null;const a=e.scrollWidth-e.clientWidth,c=e.scrollHeight-e.clientHeight;if(a<4&&c<4)return null;if(!s&&a<4)return null;if(!i&&c<4)return null;const l=e.scrollTop,h=e.scrollLeft,u={top:l,right:e.scrollWidth-e.clientWidth-e.scrollLeft,bottom:e.scrollHeight-e.clientHeight-e.scrollTop,left:h};return function(e,t){e&&e.nodeType===Node.ELEMENT_NODE&&d.set(e,{...d.get(e),...t})}(e,{scrollable:!0,scrollData:u}),u}function w(e){try{if(-1===a){const t=e.parentElement;if(!t)return!1;try{return t.checkVisibility({checkOpacity:!0,checkVisibilityCSS:!0})}catch(e){const n=window.getComputedStyle(t);return"none"!==n.display&&"hidden"!==n.visibility&&"0"!==n.opacity}}const t=document.createRange();t.selectNodeContents(e);const n=t.getClientRects();if(!n||0===n.length)return!1;let r=!1,o=!1;for(const e of n)if(e.width>0&&e.height>0&&(r=!0,!(e.bottom<-a||e.top>window.innerHeight+a||e.right<-a||e.left>window.innerWidth+a))){o=!0;break}if(!r||!o)return!1;const i=e.parentElement;if(!i)return!1;try{return i.checkVisibility({checkOpacity:!0,checkVisibilityCSS:!0})}catch(e){const t=window.getComputedStyle(i);return"none"!==t.display&&"hidden"!==t.visibility&&"0"!==t.opacity}}catch(e){return console.warn("Error checking text node visibility:",e),!1}}function b(e){const t=p(e);return e.offsetWidth>0&&e.offsetHeight>0&&"hidden"!==t?.visibility&&"none"!==t?.display}function v(e){if(!e||e.nodeType!==Node.ELEMENT_NODE)return!1;if(t.includes(e))return!1;if(n.includes(e))return!0;const r=e.tagName.toLowerCase(),o=p(e),i=new Set(["pointer","move","text","grab","grabbing","cell","copy","alias","all-scroll","col-resize","context-menu","crosshair","e-resize","ew-resize","help","n-resize","ne-resize","nesw-resize","ns-resize","nw-resize","nwse-resize","row-resize","s-resize","se-resize","sw-resize","vertical-text","w-resize","zoom-in","zoom-out"]),s=new Set(["not-allowed","no-drop","wait","progress","initial","inherit"]);let a=function(e){return"html"!==e.tagName.toLowerCase()&&!(!o?.cursor||!i.has(o.cursor))}(e);if(a)return!0;const c=new Set(["a","button","input","select","textarea","details","summary","label","option","optgroup","fieldset","legend"]),l=new Set(["disabled","readonly"]);if(c.has(r)){if(o?.cursor&&s.has(o.cursor))return!1;for(const t of l)if(e.hasAttribute(t)||"true"===e.getAttribute(t)||""===e.getAttribute(t))return!1;return!e.disabled&&(!e.readOnly&&!e.inert)}const d=e.getAttribute("role"),h=e.getAttribute("aria-role");if("true"===e.getAttribute("contenteditable")||e.isContentEditable)return!0;if(e.classList&&(e.classList.contains("button")||e.classList.contains("dropdown-toggle")||e.getAttribute("data-index")||"dropdown"===e.getAttribute("data-toggle")||"true"===e.getAttribute("aria-haspopup")))return!0;const u=new Set(["button","menu","menubar","menuitem","menuitemradio","menuitemcheckbox","radio","checkbox","tab","switch","slider","spinbutton","combobox","searchbox","textbox","listbox","option","scrollbar"]);if(c.has(r)||d&&u.has(d)||h&&u.has(h))return!0;try{if("function"==typeof getEventListeners){const t=getEventListeners(e),n=["click","mousedown","mouseup","dblclick"];for(const e of n)if(t[e]&&t[e].length>0)return!0}const t=e?.ownerDocument?.defaultView?.getEventListenersForNode||window.getEventListenersForNode;if("function"==typeof t){const n=t(e),r=["click","mousedown","mouseup","keydown","keyup","submit","change","input","focus","blur"];for(const e of r)for(const t of n)if(t.type===e)return!0}const n=["onclick","onmousedown","onmouseup","ondblclick"];for(const t of n)if(e.hasAttribute(t)||"function"==typeof e[t])return!0}catch(e){}return!!y(e)}function E(e){if(-1===a)return!0;const t=function(e){if(!e)return null;if(h.clientRects.has(e))return h.clientRects.get(e);const t=e.getClientRects();return t&&h.clientRects.set(e,t),t}(e);if(!t||0===t.length)return!1;let n=!1;for(const e of t)if(e.width>0&&e.height>0&&!(e.bottom<-a||e.top>window.innerHeight+a||e.right<-a||e.left>window.innerWidth+a)){n=!0;break}if(!n)return!1;if(e.ownerDocument!==window.document)return!0;let r=Array.from(t).find(e=>e.width>0&&e.height>0);if(!r)return!1;const o=e.getRootNode();if(o instanceof ShadowRoot){const t=r.left+r.width/2,n=r.top+r.height/2;try{const r=o.elementFromPoint(t,n);if(!r)return!1;let i=r;for(;i&&i!==o;){if(i===e)return!0;i=i.parentElement}return!1}catch(e){return!0}}return[{x:r.left+r.width/2,y:r.top+r.height/2},{x:r.left+5,y:r.top+5},{x:r.right-5,y:r.bottom-5}].some(({x:t,y:n})=>{try{const r=document.elementFromPoint(t,n);if(!r)return!1;let o=r;for(;o&&o!==document.documentElement;){if(o===e)return!0;o=o.parentElement}return!1}catch(e){return!0}})}const k=new Set(["a","button","input","select","textarea","summary","details","label","option"]),x=new Set(["button","link","menuitem","menuitemradio","menuitemcheckbox","radio","checkbox","tab","switch","slider","spinbutton","combobox","searchbox","textbox","listbox","option","scrollbar"]);function S(e){if(!e||e.nodeType!==Node.ELEMENT_NODE)return!1;const t=e.tagName.toLowerCase(),n=e.getAttribute("role");if("iframe"===t)return!0;if(k.has(t))return!0;if(n&&x.has(n))return!0;if(e.isContentEditable||"true"===e.getAttribute("contenteditable"))return!0;if(e.hasAttribute("data-testid")||e.hasAttribute("data-cy")||e.hasAttribute("data-test"))return!0;if(e.hasAttribute("onclick")||"function"==typeof e.onclick)return!0;try{const t=e?.ownerDocument?.defaultView?.getEventListenersForNode||window.getEventListenersForNode;if("function"==typeof t){const n=t(e),r=["click","mousedown","mouseup","keydown","keyup","submit","change","input","focus","blur"];for(const e of r)for(const t of n)if(t.type===e)return!0}if(["onmousedown","onmouseup","onkeydown","onkeyup","onsubmit","onchange","oninput","onfocus","onblur"].some(t=>e.hasAttribute(t)))return!0}catch(e){}return!!function(e){if(!e||e.nodeType!==Node.ELEMENT_NODE)return!1;if(!b(e))return!1;const t=e.hasAttribute("role")||e.hasAttribute("tabindex")||e.hasAttribute("onclick")||"function"==typeof e.onclick,n=/\b(btn|clickable|menu|item|entry|link)\b/i.test(e.className||""),r=Boolean(e.closest('button,a,[role="button"],.menu,.dropdown,.list,.toolbar')),o=[...e.children].some(b),i=e.parentElement&&e.parentElement.isSameNode(document.body);return(v(e)||t||n)&&o&&r&&!i}(e)}function T(e,t,n,r){if(!e.isInteractive)return!1;let o=!1;return o=!r||!!S(t),!(!o||(e.isInViewport=function(e,t){if(-1===t)return!0;const n=e.getClientRects();if(!n||0===n.length){const n=u(e);return!(!n||0===n.width||0===n.height||n.bottom<-t||n.top>window.innerHeight+t||n.right<-t||n.left>window.innerWidth+t)}for(const e of n)if(0!==e.width&&0!==e.height&&!(e.bottom<-t||e.top>window.innerHeight+t||e.right<-t||e.left>window.innerWidth+t))return!0;return!1}(t,a),!e.isInViewport&&-1!==a||(e.highlightIndex=l++,!i)))&&(s>=0?s===e.highlightIndex&&g(t,e.highlightIndex,n):g(t,e.highlightIndex,n),!0)}const C=function e(t,n=null,r=!1){if(!t||t.id===m||t.nodeType!==Node.ELEMENT_NODE&&t.nodeType!==Node.TEXT_NODE)return null;if(!t||t.id===m)return null;if("true"===t.dataset?.browserUseIgnore||"true"===t.dataset?.pageAgentIgnore)return null;if(t.getAttribute&&"true"===t.getAttribute("aria-hidden"))return null;if(t===document.body){const r={tagName:"body",attributes:{},xpath:"/body",children:[]};for(const o of t.childNodes){const t=e(o,n,!1);t&&r.children.push(t)}const o=""+f.current++;return _[o]=r,o}if(t.nodeType!==Node.ELEMENT_NODE&&t.nodeType!==Node.TEXT_NODE)return null;if(t.nodeType===Node.TEXT_NODE){const e=t.textContent?.trim();if(!e)return null;const n=t.parentElement;if(!n||"script"===n.tagName.toLowerCase())return null;const r=""+f.current++;return _[r]={type:"TEXT_NODE",text:e,isVisible:w(t)},r}if(t.nodeType===Node.ELEMENT_NODE&&!function(e){if(!e||!e.tagName)return!1;const t=new Set(["body","div","main","article","section","nav","header","footer"]),n=e.tagName.toLowerCase();return!!t.has(n)||!new Set(["svg","script","style","link","meta","noscript","template"]).has(n)}(t))return null;if(-1!==a&&!t.shadowRoot){const e=u(t),n=p(t),r=n&&("fixed"===n.position||"sticky"===n.position),o=t.offsetWidth>0||t.offsetHeight>0;if(!e||!r&&!o&&(e.bottom<-a||e.top>window.innerHeight+a||e.right<-a||e.left>window.innerWidth+a))return null}const o={tagName:t.tagName.toLowerCase(),attributes:{},children:[]};if(function(e){if(!e||e.nodeType!==Node.ELEMENT_NODE)return!1;const t=e.tagName.toLowerCase();return!!new Set(["a","button","input","select","textarea","details","summary","label"]).has(t)||(e.hasAttribute("onclick")||e.hasAttribute("role")||e.hasAttribute("tabindex")||e.hasAttribute("aria-")||e.hasAttribute("data-action")||"true"===e.getAttribute("contenteditable"))}(t)||"iframe"===t.tagName.toLowerCase()||"body"===t.tagName.toLowerCase()){const e=t.getAttributeNames?.()||[];for(const n of e){const e=t.getAttribute(n);o.attributes[n]=e}"input"!==t.tagName.toLowerCase()||"checkbox"!==t.type&&"radio"!==t.type||(o.attributes.checked=t.checked?"true":"false")}let i=!1;if(t.nodeType===Node.ELEMENT_NODE&&(o.isVisible=b(t),o.isVisible)){o.isTopElement=E(t);const e=t.getAttribute("role"),s="menu"===e||"menubar"===e||"listbox"===e;if((o.isTopElement||s)&&(o.isInteractive=v(t),i=T(o,t,n,r),o.ref=t,o.isInteractive&&0===Object.keys(o.attributes).length)){const e=t.getAttributeNames?.()||[];for(const n of e){const e=t.getAttribute(n);o.attributes[n]=e}}}if(t.tagName){const s=t.tagName.toLowerCase();if("iframe"===s)try{const n=t.contentDocument||t.contentWindow?.document;if(n)for(const r of n.childNodes){const n=e(r,t,!1);n&&o.children.push(n)}}catch(e){console.warn("Unable to access iframe:",e)}else if(t.isContentEditable||"true"===t.getAttribute("contenteditable")||"tinymce"===t.id||t.classList.contains("mce-content-body")||"body"===s&&t.getAttribute("data-id")?.startsWith("mce_"))for(const r of t.childNodes){const t=e(r,n,i);t&&o.children.push(t)}else{if(t.shadowRoot){o.shadowRoot=!0;for(const r of t.shadowRoot.childNodes){const t=e(r,n,i);t&&o.children.push(t)}}for(const s of t.childNodes){const t=e(s,n,i||r);t&&o.children.push(t)}}}if("a"===o.tagName&&0===o.children.length&&!o.attributes.href){const e=u(t);if(!(e&&e.width>0&&e.height>0||t.offsetWidth>0||t.offsetHeight>0))return null}o.extra=d.get(t)||null;const s=""+f.current++;return _[s]=o,s}(document.body);return h.clearCache(),{rootId:C,map:_}};const DEFAULT_VIEWPORT_EXPANSION=-1;function resolveViewportExpansion(e){return e??DEFAULT_VIEWPORT_EXPANSION}const newElementsCache=new WeakMap;function getFlatTree(e){const t=resolveViewportExpansion(e.viewportExpansion),n=[];for(const t of e.interactiveBlacklist||[])"function"==typeof t?n.push(t()):n.push(t);const r=[];for(const t of e.interactiveWhitelist||[])"function"==typeof t?r.push(t()):r.push(t);const o=domTree({doHighlightElements:!0,debugMode:!0,focusHighlightIndex:-1,viewportExpansion:t,interactiveBlacklist:n,interactiveWhitelist:r,highlightOpacity:e.highlightOpacity??0,highlightLabelOpacity:e.highlightLabelOpacity??.1});for(const e in o.map){const t=o.map[e];if(t.isInteractive&&t.ref){const e=t.ref;newElementsCache.has(e)||(newElementsCache.set(e,window.location.href),t.isNew=!0)}}return o}const globRegexCache=new Map;function globToRegex(e){let t=globRegexCache.get(e);if(!t){const n=e.replace(/[.+^${}()|[\]\\]/g,"\\$&");t=new RegExp(`^${n.replace(/\*/g,".*")}$`),globRegexCache.set(e,t)}return t}function matchAttributes(e,t){const n={};for(const r of t)if(r.includes("*")){const t=globToRegex(r);for(const r of Object.keys(e))t.test(r)&&e[r].trim()&&(n[r]=e[r].trim())}else{const t=e[r];t&&t.trim()&&(n[r]=t.trim())}return n}function flatTreeToString(e,t){const n=[...t||[],"title","type","checked","name","role","value","placeholder","data-date-format","alt","aria-label","aria-expanded","data-state","aria-checked","id","for","target","aria-haspopup","aria-controls","aria-owns","contenteditable"],r=t=>{const n=e.map[t];if(!n)return null;if("TEXT_NODE"===n.type){const e=n;return{type:"text",text:e.text,isVisible:e.isVisible,parent:null,children:[]}}{const e=n,t=[];if(e.children)for(const n of e.children){const e=r(n);e&&t.push(e)}return{type:"element",tagName:e.tagName,attributes:e.attributes??{},isVisible:e.isVisible??!1,isInteractive:e.isInteractive??!1,isTopElement:e.isTopElement??!1,isNew:e.isNew??!1,highlightIndex:e.highlightIndex,parent:null,children:t,extra:e.extra??{}}}},o=(e,t=null)=>{e.parent=t;for(const t of e.children)o(t,e)},i=r(e.rootId);if(!i)return"";o(i);const s=(e,t,r)=>{let o=t;const i="\t".repeat(t);if("element"===e.type){if(void 0!==e.highlightIndex){o+=1;const t=getAllTextTillNextClickableElement(e);let s="";if(n.length>0&&e.attributes){const r=matchAttributes(e.attributes,n),o=Object.keys(r);if(o.length>1){const e=new Set,t={};for(const n of o){const o=r[n];o.length>5&&(o in t?e.add(n):t[o]=n)}for(const t of e)delete r[t]}r.role===e.tagName&&delete r.role;const i=["aria-label","placeholder","title"];for(const e of i)r[e]&&r[e].toLowerCase().trim()===t.toLowerCase().trim()&&delete r[e];Object.keys(r).length>0&&(s=Object.entries(r).map(([e,t])=>`${e}=${((e,t)=>e.length>t?e.substring(0,t)+"...":e)(t,20)}`).join(" "))}let a=`${i}${e.isNew?`*[${e.highlightIndex}]`:`[${e.highlightIndex}]`}<${e.tagName??""}`;if(s&&(a+=` ${s}`),e.extra&&e.extra.scrollable){let t="";e.extra.scrollData?.left&&(t+=`left=${e.extra.scrollData.left}, `),e.extra.scrollData?.top&&(t+=`top=${e.extra.scrollData.top}, `),e.extra.scrollData?.right&&(t+=`right=${e.extra.scrollData.right}, `),e.extra.scrollData?.bottom&&(t+=`bottom=${e.extra.scrollData.bottom}`),a+=` data-scrollable="${t}"`}if(t){s||(a+=" "),a+=`>${t.trim()}`}else s||(a+=" ");a+=" />",r.push(a)}for(const t of e.children)s(t,o,r)}else if("text"===e.type){if((e=>{let t=e.parent;for(;t;){if("element"===t.type&&void 0!==t.highlightIndex)return!0;t=t.parent}return!1})(e))return;e.parent&&"element"===e.parent.type&&e.parent.isVisible&&e.parent.isTopElement&&r.push(`${i}${e.text??""}`)}},a=[];return s(i,0,a),a.join("\n")}const getAllTextTillNextClickableElement=(e,t=-1)=>{const n=[],r=(o,i)=>{if(!(-1!==t&&i>t||"element"===o.type&&o!==e&&void 0!==o.highlightIndex))if("text"===o.type&&o.text)n.push(o.text);else if("element"===o.type)for(const e of o.children)r(e,i+1)};return r(e,0),n.join("\n").trim()};function getSelectorMap(e){const t=new Map,n=Object.keys(e.map);for(const r of n){const n=e.map[r];n.isInteractive&&"number"==typeof n.highlightIndex&&t.set(n.highlightIndex,n)}return t}function getElementTextMap(e){const t=e.split("\n").map(e=>e.trim()).filter(e=>e.length>0),n=new Map;for(const e of t){const t=/^\[(\d+)\]<[^>]+>([^<]*)/.exec(e);if(t){const r=parseInt(t[1],10);n.set(r,e)}}return n}function cleanUpHighlights(){const e=window._highlightCleanupFunctions||[];for(const t of e)"function"==typeof t&&t();window._highlightCleanupFunctions=[]}async function waitFor(e){await new Promise(t=>setTimeout(t,1e3*e))}function getElementByIndex(e,t){const n=e.get(t);if(!n)throw new Error(`No interactive element found at index ${t}`);const r=n.ref;if(!r)throw new Error(`Element at index ${t} does not have a reference`);if(!(r instanceof HTMLElement))throw new Error(`Element at index ${t} is not an HTMLElement`);return r}let lastClickedElement=null;function blurLastClickedElement(){lastClickedElement&&(lastClickedElement.blur(),lastClickedElement.dispatchEvent(new MouseEvent("mouseout",{bubbles:!0,cancelable:!0})),lastClickedElement=null)}async function scrollIntoViewIfNeeded(e){const t=e.getBoundingClientRect();t.top>=0&&t.bottom<=window.innerHeight&&t.left>=0&&t.right<=window.innerWidth||(e.scrollIntoView({behavior:"smooth",block:"center",inline:"nearest"}),await waitFor(.4))}async function movePointerToElement(e){const t=e.getBoundingClientRect(),n=t.left+t.width/2,r=t.top+t.height/2;window.dispatchEvent(new CustomEvent("HyphaDebugger::MovePointerTo",{detail:{x:n,y:r}})),await waitFor(.3)}async function clickElement(e){blurLastClickedElement(),lastClickedElement=e,await scrollIntoViewIfNeeded(e),await movePointerToElement(e),window.dispatchEvent(new CustomEvent("HyphaDebugger::ClickPointer")),await waitFor(.05),e.dispatchEvent(new MouseEvent("mouseenter",{bubbles:!0,cancelable:!0})),e.dispatchEvent(new MouseEvent("mouseover",{bubbles:!0,cancelable:!0})),e.dispatchEvent(new MouseEvent("mousedown",{bubbles:!0,cancelable:!0})),e.focus(),e.dispatchEvent(new MouseEvent("mouseup",{bubbles:!0,cancelable:!0})),e.dispatchEvent(new MouseEvent("click",{bubbles:!0,cancelable:!0})),await waitFor(.2)}let _nativeInputValueSetter=null,_nativeTextAreaValueSetter=null;function getNativeInputValueSetter(){return _nativeInputValueSetter||(_nativeInputValueSetter=Object.getOwnPropertyDescriptor(window.HTMLInputElement.prototype,"value").set),_nativeInputValueSetter}function getNativeTextAreaValueSetter(){return _nativeTextAreaValueSetter||(_nativeTextAreaValueSetter=Object.getOwnPropertyDescriptor(window.HTMLTextAreaElement.prototype,"value").set),_nativeTextAreaValueSetter}async function inputTextElement(e,t){const n=e.isContentEditable;if(!(e instanceof HTMLInputElement||e instanceof HTMLTextAreaElement||n))throw new Error("Element is not an input, textarea, or contenteditable");await clickElement(e),n?(e.dispatchEvent(new InputEvent("beforeinput",{bubbles:!0,cancelable:!0,inputType:"deleteContent"}))&&(e.innerText="",e.dispatchEvent(new InputEvent("input",{bubbles:!0,inputType:"deleteContent"}))),e.dispatchEvent(new InputEvent("beforeinput",{bubbles:!0,cancelable:!0,inputType:"insertText",data:t}))&&(e.innerText=t,e.dispatchEvent(new InputEvent("input",{bubbles:!0,inputType:"insertText",data:t}))),e.dispatchEvent(new Event("change",{bubbles:!0})),e.blur()):e instanceof HTMLTextAreaElement?getNativeTextAreaValueSetter().call(e,t):getNativeInputValueSetter().call(e,t),n||e.dispatchEvent(new Event("input",{bubbles:!0})),await waitFor(.1),blurLastClickedElement()}async function selectOptionElement(e,t){if(!(e instanceof HTMLSelectElement))throw new Error("Element is not a select element");await scrollIntoViewIfNeeded(e);const n=e.getBoundingClientRect();window.dispatchEvent(new CustomEvent("HyphaDebugger::MovePointerTo",{detail:{x:n.left+n.width/2,y:n.top+n.height/2}})),await waitFor(.3),window.dispatchEvent(new CustomEvent("HyphaDebugger::ClickPointer"));const r=Array.from(e.options).find(e=>e.textContent?.trim()===t.trim());if(!r)throw new Error(`Option with text "${t}" not found in select element`);e.value=r.value,e.dispatchEvent(new Event("change",{bubbles:!0})),await waitFor(.1)}async function scrollVertically(e,t,n){if(n){let e=n,r=!1,o=null,i=0,s=0;const a=t;for(;e&&s<10;){const t=window.getComputedStyle(e),n=/(auto|scroll|overlay)/.test(t.overflowY),c=e.scrollHeight>e.clientHeight;if(n&&c){const t=e.scrollTop,n=e.scrollHeight-e.clientHeight;let s=a/3;s=s>0?Math.min(s,n-t):Math.max(s,-t),e.scrollTop=t+s;const c=e.scrollTop-t;if(Math.abs(c)>.5){r=!0,o=e,i=c;break}}if(e===document.body||e===document.documentElement)break;e=e.parentElement,s++}return r?`Scrolled container (${o?.tagName}) by ${i}px`:`No scrollable container found for element (${n.tagName})`}const r=t,o=e=>e&&/(auto|scroll|overlay)/.test(getComputedStyle(e).overflowY)&&e.scrollHeight>e.clientHeight&&(e=>e.clientHeight>=.5*window.innerHeight)(e);let i=document.activeElement;for(;i&&!o(i)&&i!==document.body;)i=i.parentElement;if(i=o(i)?i:Array.from(document.querySelectorAll("*")).find(o)||document.scrollingElement||document.documentElement,i===document.scrollingElement||i===document.documentElement||i===document.body){const e=window.scrollY;window.scrollBy(0,r);const t=window.scrollY,n=t-e;if(Math.abs(n)<1)return r>0?"Already at the bottom of the page.":"Already at the top of the page.";const o=document.documentElement.scrollHeight-window.innerHeight;return r>0&&t>=o-1?`Scrolled page by ${n}px. Reached the bottom.`:r<0&&t<=1?`Scrolled page by ${n}px. Reached the top.`:`Scrolled page by ${n}px.`}{const e=i.scrollTop,t=i.scrollHeight-i.clientHeight;i.scrollBy({top:r,behavior:"smooth"}),await waitFor(.1);const n=i.scrollTop,o=n-e;if(Math.abs(o)<1)return r>0?`Already at the bottom of container (${i.tagName}).`:`Already at the top of container (${i.tagName}).`;const s=r<0&&n<=1;return r>0&&n>=t-1?`Scrolled container (${i.tagName}) by ${o}px. Reached the bottom.`:s?`Scrolled container (${i.tagName}) by ${o}px. Reached the top.`:`Scrolled container (${i.tagName}) by ${o}px.`}}async function scrollHorizontally(e,t,n){if(n){let r=n,o=!1,i=null,s=0,a=0;const c=e?t:-t;for(;r&&a<10;){const e=window.getComputedStyle(r),t=/(auto|scroll|overlay)/.test(e.overflowX),n=r.scrollWidth>r.clientWidth;if(t&&n){const e=r.scrollLeft,t=r.scrollWidth-r.clientWidth;let n=c/3;n=n>0?Math.min(n,t-e):Math.max(n,-e),r.scrollLeft=e+n;const a=r.scrollLeft-e;if(Math.abs(a)>.5){o=!0,i=r,s=a;break}}if(r===document.body||r===document.documentElement)break;r=r.parentElement,a++}return o?`Scrolled container (${i?.tagName}) horizontally by ${s}px`:`No horizontally scrollable container found for element (${n.tagName})`}const r=e?t:-t,o=e=>e&&/(auto|scroll|overlay)/.test(getComputedStyle(e).overflowX)&&e.scrollWidth>e.clientWidth&&(e=>e.clientWidth>=.5*window.innerWidth)(e);let i=document.activeElement;for(;i&&!o(i)&&i!==document.body;)i=i.parentElement;if(i=o(i)?i:Array.from(document.querySelectorAll("*")).find(o)||document.scrollingElement||document.documentElement,i===document.scrollingElement||i===document.documentElement||i===document.body){const e=window.scrollX,t=document.documentElement.scrollWidth-window.innerWidth;window.scrollBy(r,0);const n=window.scrollX,o=n-e;if(Math.abs(o)<1)return r>0?"Already at the right edge of the page.":"Already at the left edge of the page.";return r>0&&n>=t-1?`Scrolled page by ${o}px. Reached the right edge.`:r<0&&n<=1?`Scrolled page by ${o}px. Reached the left edge.`:`Scrolled page horizontally by ${o}px.`}{const e=i.scrollLeft,t=i.scrollWidth-i.clientWidth;i.scrollBy({left:r,behavior:"smooth"}),await waitFor(.1);const n=i.scrollLeft,o=n-e;if(Math.abs(o)<1)return r>0?`Already at the right edge of container (${i.tagName}).`:`Already at the left edge of container (${i.tagName}).`;const s=r<0&&n<=1;return r>0&&n>=t-1?`Scrolled container (${i.tagName}) by ${o}px. Reached the right edge.`:s?`Scrolled container (${i.tagName}) by ${o}px. Reached the left edge.`:`Scrolled container (${i.tagName}) horizontally by ${o}px.`}}function getPageScrollInfo(){const e=window.innerWidth,t=window.innerHeight,n=Math.max(document.documentElement.scrollWidth,document.body.scrollWidth||0),r=Math.max(document.documentElement.scrollHeight,document.body.scrollHeight||0),o=window.scrollX||window.pageXOffset||document.documentElement.scrollLeft||0,i=window.scrollY||window.pageYOffset||document.documentElement.scrollTop||0,s=Math.max(0,r-(window.innerHeight+i)),a=Math.max(0,n-(window.innerWidth+o));return{viewport_width:e,viewport_height:t,page_width:n,page_height:r,scroll_x:o,scroll_y:i,pixels_above:i,pixels_below:s,pages_above:t>0?i/t:0,pages_below:t>0?s/t:0,total_pages:t>0?r/t:0,current_page_position:i/Math.max(1,r-t),pixels_left:o,pixels_right:a}}class PageController{constructor(e={}){this.flatTree=null,this.selectorMap=new Map,this.elementTextMap=new Map,this.simplifiedHTML="",this.isIndexed=!1,this.config=e}async getBrowserState(){const e=window.location.href,t=document.title,n=getPageScrollInfo(),r=resolveViewportExpansion(this.config.viewportExpansion);await this.updateTree();const o=this.simplifiedHTML;return{url:e,title:t,header:`${`Current Page: [${t}](${e})`}\n${`Page info: ${n.viewport_width}x${n.viewport_height}px viewport, ${n.page_width}x${n.page_height}px total, ${n.pages_above.toFixed(1)} pages above, ${n.pages_below.toFixed(1)} pages below, at ${(100*n.current_page_position).toFixed(0)}%`}\n\n${-1===r?"Interactive elements (full page):":"Interactive elements (viewport):"}\n\n${n.pixels_above>4&&-1!==r?`... ${n.pixels_above} pixels above - scroll to see more ...`:"[Start of page]"}`,content:o,footer:n.pixels_below>4&&-1!==r?`... ${n.pixels_below} pixels below - scroll to see more ...`:"[End of page]",element_count:this.selectorMap.size}}async updateTree(){return cleanUpHighlights(),this.flatTree=getFlatTree(this.config),this.simplifiedHTML=flatTreeToString(this.flatTree,this.config.includeAttributes),this.selectorMap.clear(),this.selectorMap=getSelectorMap(this.flatTree),this.elementTextMap.clear(),this.elementTextMap=getElementTextMap(this.simplifiedHTML),this.isIndexed=!0,this.simplifiedHTML}async cleanUpHighlights(){cleanUpHighlights()}assertIndexed(){if(!this.isIndexed)throw new Error("DOM tree not indexed yet. Call get_browser_state first.")}cleanUpAfterAction(){cleanUpHighlights()}async clickElement(e){try{this.assertIndexed();const t=getElementByIndex(this.selectorMap,e),n=this.elementTextMap.get(e);return this.cleanUpAfterAction(),await clickElement(t),t instanceof HTMLAnchorElement&&"_blank"===t.target?{success:!0,message:`Clicked element (${n??e}). Link opened in a new tab.`}:{success:!0,message:`Clicked element (${n??e}).`}}catch(e){return{success:!1,message:`Failed to click element: ${e}`}}}async inputText(e,t){try{this.assertIndexed();const n=getElementByIndex(this.selectorMap,e),r=this.elementTextMap.get(e);return this.cleanUpAfterAction(),await inputTextElement(n,t),{success:!0,message:`Input text "${t}" into element (${r??e}).`}}catch(e){return{success:!1,message:`Failed to input text: ${e}`}}}async selectOption(e,t){try{this.assertIndexed();const n=getElementByIndex(this.selectorMap,e),r=this.elementTextMap.get(e);return this.cleanUpAfterAction(),await selectOptionElement(n,t),{success:!0,message:`Selected option "${t}" in element (${r??e}).`}}catch(e){return{success:!1,message:`Failed to select option: ${e}`}}}async scroll(e){try{this.assertIndexed(),this.cleanUpAfterAction();const{direction:t,amount:n,index:r}=e,o=void 0!==r?getElementByIndex(this.selectorMap,r):null;let i;if("left"===t||"right"===t){const e=n??.8*window.innerWidth;i=await scrollHorizontally("right"===t,e,o)}else{const e=n??.8*window.innerHeight,r="down"===t?e:-e;i=await scrollVertically("down"===t,r,o)}return{success:!0,message:i}}catch(e){return{success:!1,message:`Failed to scroll: ${e}`}}}dispose(){cleanUpHighlights(),this.flatTree=null,this.selectorMap.clear(),this.elementTextMap.clear(),this.simplifiedHTML="",this.isIndexed=!1}}let controller=null;function getController(){return controller||(controller=new PageController({viewportExpansion:-1,highlightOpacity:.1,highlightLabelOpacity:.5})),controller}async function getBrowserState(e){const t=getController();void 0!==e&&(t.config.viewportExpansion=e?0:-1);return Promise.race([t.getBrowserState(),new Promise((e,t)=>setTimeout(()=>t(new Error("get_browser_state timed out after 15000ms (complex DOM or cross-origin iframes)")),15e3))])}async function clickElementByIndex(e){return getController().clickElement(e)}async function inputText(e,t){return getController().inputText(e,t)}async function selectOption(e,t){return getController().selectOption(e,t)}async function scroll(e,t,n){return getController().scroll({direction:e,amount:t,index:n})}async function removeHighlights(){return getController().cleanUpHighlights(),{success:!0,message:"Highlights removed."}}function disposeController(){controller&&(controller.dispose(),controller=null)}function randomHex(e=8){const t=new Uint8Array(e);return crypto.getRandomValues(t),Array.from(t,e=>e.toString(16).padStart(2,"0")).join("")}getBrowserState.__schema__={name:"getBrowserState",description:"Get the current page state with all interactive elements indexed as [0], [1], [2], etc. Returns a simplified HTML representation optimized for LLM consumption. Interactive elements (buttons, links, inputs, scrollable areas) are detected via smart heuristics (CSS cursor, ARIA roles, event listeners, tag names). Use the returned indices with click_element_by_index, input_text, select_option, or scroll. Call this first to understand the page before performing any actions.",parameters:{type:"object",properties:{viewport_only:{type:"boolean",description:"If true, only return elements visible in the current viewport. Default: false (full page)."}}}},clickElementByIndex.__schema__={name:"clickElementByIndex",description:"Click an interactive element by its numeric index from get_browser_state output. Simulates a full mouse event sequence (hover, mousedown, focus, mouseup, click) to trigger all event listeners including React/Vue handlers.",parameters:{type:"object",properties:{index:{type:"number",description:"The element index from get_browser_state (e.g. 0 for [0], 5 for [5])."}},required:["index"]}},inputText.__schema__={name:"inputText",description:"Type text into an input, textarea, or contenteditable element by its index. Replaces existing content. Works with React controlled components, contenteditable editors (LinkedIn, Quill), and native inputs.",parameters:{type:"object",properties:{index:{type:"number",description:"The element index from get_browser_state."},text:{type:"string",description:"The text to type into the element."}},required:["index","text"]}},selectOption.__schema__={name:"selectOption",description:"Select a dropdown option in a <select> element by its index and the visible option text.",parameters:{type:"object",properties:{index:{type:"number",description:"The <select> element index from get_browser_state."},option_text:{type:"string",description:"The visible text of the option to select (case-sensitive, trimmed)."}},required:["index","option_text"]}},scroll.__schema__={name:"scroll",description:"Scroll the page or a specific scrollable container. If index is provided, scrolls the nearest scrollable ancestor of that element. Otherwise scrolls the page or the largest scrollable container.",parameters:{type:"object",properties:{direction:{type:"string",enum:["up","down","left","right"],description:"Scroll direction."},amount:{type:"number",description:"Scroll amount in pixels. Default: ~80% of viewport height (vertical) or width (horizontal)."},index:{type:"number",description:"Optional element index. If provided, scrolls the nearest scrollable ancestor of this element."}},required:["direction"]}},removeHighlights.__schema__={name:"removeHighlights",description:"Remove all visual element index labels/highlights from the page. Useful after taking a screenshot if you want a clean view.",parameters:{type:"object",properties:{}}};const STORAGE_KEY="__hypha_debugger_config__";class HyphaDebugger{constructor(e){this.overlay=null,this.cursor=null,this.server=null,this.serviceInfo=null,this.boundBeforeUnload=null,this.cleanupInterceptor=null;const t=e.require_token??!1;let n=e.service_id??"web-debugger";e.service_id||(n=`web-debugger-${randomHex(16)}`);const r=e.visibility??(t?"protected":"unlisted");this.config={server_url:e.server_url,workspace:e.workspace??"",token:e.token??"",service_id:n,service_name:e.service_name??"Web Debugger",show_ui:e.show_ui??!0,visibility:r,require_token:t}}async start(){installConsoleCapture();const e=window;if(e.__HYPHA_DEBUGGER__?.instance)return console.warn("[hypha-debugger] Already running, returning existing session."),e.__HYPHA_DEBUGGER__.session;this.config.show_ui&&(this.overlay=new DebugOverlay,this.overlay.setStatus("disconnected"),this.overlay.setInfo({Status:"Connecting..."}),this.cursor=new AICursor);try{"function"!=typeof Promise.prototype.finally&&(Promise.prototype.finally=function(e){return this.then(t=>Promise.resolve(e()).then(()=>t),t=>Promise.resolve(e()).then(()=>{throw t}))});const t=this.getConnectToServer(),n={server_url:this.config.server_url};this.config.workspace&&(n.workspace=this.config.workspace),this.config.token&&(n.token=this.config.token);try{this.server=await t(n)}catch(e){if(!this.config.workspace)throw e;console.warn(`[hypha-debugger] Failed to rejoin workspace "${this.config.workspace}", getting a fresh one:`,e.message??e),this.server=await t({server_url:this.config.server_url})}this.serviceInfo=await this.server.registerService(this.buildServiceDefinition());const r=await this.updateSession();return this.overlay&&this.overlay.addLog("Service registered","result"),e.__HYPHA_DEBUGGER__=e.__HYPHA_DEBUGGER__??{},e.__HYPHA_DEBUGGER__.instance=this,this.saveConfigToStorage(),this.boundBeforeUnload=()=>this.saveConfigToStorage(),window.addEventListener("beforeunload",this.boundBeforeUnload),this.cleanupInterceptor=installNavigationInterceptor(),r}catch(e){throw console.error("[hypha-debugger] Failed to start:",e),this.overlay&&(this.overlay.setStatus("error"),this.overlay.setInfo({Status:"Error",Error:e.message??String(e)})),e}}async destroy(){this.boundBeforeUnload&&(window.removeEventListener("beforeunload",this.boundBeforeUnload),this.boundBeforeUnload=null),this.cleanupInterceptor&&(this.cleanupInterceptor(),this.cleanupInterceptor=null);try{this.serviceInfo&&this.server&&await this.server.unregisterService(this.serviceInfo.id)}catch{}try{sessionStorage.removeItem(STORAGE_KEY)}catch{}disposeController(),this.cursor?.destroy(),this.cursor=null,this.overlay?.destroy(),this.overlay=null;const e=window;e.__HYPHA_DEBUGGER__&&(delete e.__HYPHA_DEBUGGER__.instance,delete e.__HYPHA_DEBUGGER__.session)}saveConfigToStorage(){try{const e={server_url:this.config.server_url,workspace:this.server?.config?.workspace??this.config.workspace,service_id:this.config.service_id,service_name:this.config.service_name,show_ui:this.config.show_ui,visibility:this.config.visibility,require_token:this.config.require_token,script_url:this.detectScriptUrl()};sessionStorage.setItem(STORAGE_KEY,JSON.stringify(e))}catch{}}detectScriptUrl(){try{const e=document.querySelectorAll("script[src]");for(const t of Array.from(e))if(t.src&&t.src.includes("hypha-debugger"))return t.src}catch{}return"https://cdn.jsdelivr.net/npm/hypha-debugger/dist/hypha-debugger.min.js"}async updateSession(e){const t=this.serviceInfo?.id??this.config.service_id,n=this.buildServiceUrl(t),r=this.server.config?.workspace??"",o=this.config.require_token?await this.server.generateToken({expires_in:86400}):"";this.overlay&&(this.overlay.setStatus("connected"),this.overlay.setInfo({Status:"Connected",Server:this.config.server_url,...e}),this.overlay.setInstructions(this.buildInstructionBlock(n,o))),console.log(`[hypha-debugger] Service URL: ${n}`),o?(console.log(`[hypha-debugger] Token: ${o}`),console.log(`[hypha-debugger] Test:\n curl '${n}/get_page_info' -H 'Authorization: Bearer ${o}'`)):console.log(`[hypha-debugger] Test:\n curl '${n}/get_page_info'`);const i={service_id:t,workspace:r,server:this.server,service_url:n,token:o,destroy:()=>this.destroy()},s=window;return s.__HYPHA_DEBUGGER__=s.__HYPHA_DEBUGGER__??{},s.__HYPHA_DEBUGGER__.session=i,i}buildServiceUrl(e){const t=this.config.server_url.replace(/\/+$/,""),n=e.indexOf("/");if(-1!==n){const r=e.substring(0,n),o=e.substring(n+1),i=o.indexOf(":");return`${t}/${r}/services/${-1!==i?o.substring(i+1):o}`}return`${t}/services/${e}`}getHyphaModule(){if(hyphaRpcExports.connectToServer)return hyphaRpc;if(hyphaRpcExports.hyphaWebsocketClient?.connectToServer)return hyphaRpcExports.hyphaWebsocketClient;const e=window;if(e.hyphaWebsocketClient?.connectToServer)return e.hyphaWebsocketClient;throw new Error('hypha-rpc not found. Install it via npm or load it via: <script src="https://cdn.jsdelivr.net/npm/hypha-rpc@0.20.97/dist/hypha-rpc-websocket.min.js"><\/script>')}getConnectToServer(){return this.getHyphaModule().connectToServer}buildServiceDefinition(){return{id:this.config.service_id,name:this.config.service_name,type:"debugger",description:"Remote web page debugger. Allows inspecting DOM, taking screenshots, executing JavaScript, and interacting with the page.",config:{visibility:this.config.visibility},get_page_info:this.wrapFn(getPageInfo,"get_page_info"),get_html:this.wrapFn(getHtml,"get_html"),query_dom:this.wrapFn(queryDom,"query_dom"),click_element:this.wrapFn(clickElement$1,"click_element"),fill_input:this.wrapFn(fillInput,"fill_input"),scroll_to:this.wrapFn(scrollTo,"scroll_to"),take_screenshot:this.wrapFn(takeScreenshot,"take_screenshot"),execute_script:this.wrapFn(executeScript,"execute_script"),navigate:this.wrapFn(navigate,"navigate"),get_react_tree:this.wrapFn(getReactTree,"get_react_tree"),get_browser_state:this.wrapFn(getBrowserState,"get_browser_state"),click_element_by_index:this.wrapFn(clickElementByIndex,"click_element_by_index"),input_text:this.wrapFn(inputText,"input_text"),select_option:this.wrapFn(selectOption,"select_option"),scroll:this.wrapFn(scroll,"scroll"),remove_highlights:this.wrapFn(removeHighlights,"remove_highlights"),get_skill_md:this.wrapFn(this.createGetSkillMd(),"get_skill_md")}}createGetSkillMd(){const e=()=>{const e={},t={get_page_info:getPageInfo,get_html:getHtml,query_dom:queryDom,click_element:clickElement$1,fill_input:fillInput,scroll_to:scrollTo,take_screenshot:takeScreenshot,execute_script:executeScript,navigate:navigate,get_react_tree:getReactTree,get_browser_state:getBrowserState,click_element_by_index:clickElementByIndex,input_text:inputText,select_option:selectOption,scroll:scroll,remove_highlights:removeHighlights};for(const[n,r]of Object.entries(t))r.__schema__&&(e[n]=r);return!this.serviceInfo||this.buildServiceUrl(this.serviceInfo.id??this.config.service_id),generateSkillMd(e)};return e.__schema__={name:"getSkillMd",description:"Get the SKILL.md document describing all available debugger functions, their parameters, and usage examples. Follows the agentskills.io specification.",parameters:{type:"object",properties:{}}},e}buildInstructionBlock(e,t){const n=t?' -H "Authorization: Bearer $TOKEN"':"",r=["# Hypha Remote Debugger — Web Page","# A debugger is attached to a live web page.","# You can remotely inspect, interact with, and control this page via the HTTP API below.","#","# APPROACHES (pick what fits your task):","# - execute_script: Run arbitrary JS — fastest for reading/modifying page state, DOM queries, API calls","# - get_browser_state + click/input/select by index: Visual interaction with the page as a user would","# - get_html / query_dom: Read DOM structure with CSS selectors","# - get_react_tree: Inspect React component props, state, and hooks","# - take_screenshot: Visual verification of page state","#","# All POST endpoints accept JSON body with parameter names as keys.","",`SERVICE_URL="${e}"`];return t&&r.push(`TOKEN="${t}"`),r.push("","# Execute JavaScript (most versatile — read state, call APIs, modify DOM):",`curl -X POST "$SERVICE_URL/execute_script"${n} -H "Content-Type: application/json" -d '{"code": "document.title"}'`,"","# Smart DOM analysis (indexed interactive elements for click/type/select):",`curl "$SERVICE_URL/get_browser_state"${n}`,"","# Interact by element index:",`curl -X POST "$SERVICE_URL/click_element_by_index"${n} -H "Content-Type: application/json" -d '{"index": 3}'`,`curl -X POST "$SERVICE_URL/input_text"${n} -H "Content-Type: application/json" -d '{"index": 5, "text": "hello"}'`,"","# Screenshot + React inspection:",`curl "$SERVICE_URL/take_screenshot"${n}`,`curl "$SERVICE_URL/get_react_tree"${n}`,"","# Navigate (auto-reconnects for same-origin):",`curl -X POST "$SERVICE_URL/navigate"${n} -H "Content-Type: application/json" -d '{"url": "/other-page"}'`,"","# Full API docs:",`curl "$SERVICE_URL/get_skill_md"${n}`),r.join("\n")}wrapFn(e,t){const n=this,r=async(...r)=>{n.overlay?.addLog(`${t}(${n.summarizeArgs(r)})`,"call");try{const o=await e(...r);return o&&"object"==typeof o&&"error"in o?n.overlay?.addLog(`${t}: ${o.error}`,"error"):n.overlay?.addLog(`${t} -> OK`,"result"),o}catch(e){throw n.overlay?.addLog(`${t}: ${e.message}`,"error"),e}};return e.__schema__&&(r.__schema__=e.__schema__),wrapFn(r)}summarizeArgs(e){return 0===e.length?"":e.map(e=>"string"==typeof e?e.length>40?e.slice(0,40)+"...":e:"object"==typeof e&&null!==e?"{...}":String(e)).join(", ")}}async function startDebugger(e){return new HyphaDebugger(e).start()}function autoStart(){if("undefined"==typeof window||"undefined"==typeof document)return;if(window.__HYPHA_DEBUGGER__?.instance)return;try{const e=sessionStorage.getItem("__hypha_debugger_config__");if(e){const t=JSON.parse(e);if(t.server_url)return console.log("[hypha-debugger] Reconnecting from saved session..."),void startDebugger(t).catch(e=>{console.error("[hypha-debugger] Auto-reconnect failed:",e)})}}catch{}const e=document.querySelectorAll("script[src]");let t=null;for(const n of Array.from(e))if(n.src&&n.src.includes("hypha-debugger")){t=n;break}if(t?.hasAttribute("data-manual"))return;const n={server_url:t?.getAttribute("data-server-url")??"https://hypha.aicell.io"};t?.getAttribute("data-workspace")&&(n.workspace=t.getAttribute("data-workspace")),t?.getAttribute("data-token")&&(n.token=t.getAttribute("data-token")),t?.getAttribute("data-service-id")&&(n.service_id=t.getAttribute("data-service-id")),t?.hasAttribute("data-no-ui")&&(n.show_ui=!1),t?.hasAttribute("data-require-token")&&(n.require_token=!0),startDebugger(n).catch(e=>{console.error("[hypha-debugger] Auto-start failed:",e)})}"undefined"!=typeof window&&("loading"===document.readyState?document.addEventListener("DOMContentLoaded",autoStart):autoStart()),exports.AICursor=AICursor,exports.HyphaDebugger=HyphaDebugger,exports.PageController=PageController,exports.clickElement=clickElement$1,exports.clickElementByIndex=clickElementByIndex,exports.disposeController=disposeController,exports.executeScript=executeScript,exports.fillInput=fillInput,exports.generateSkillMd=generateSkillMd,exports.getBrowserState=getBrowserState,exports.getComputedStyles=getComputedStyles,exports.getConsoleLogs=getConsoleLogs,exports.getElementBounds=getElementBounds,exports.getHtml=getHtml,exports.getPageInfo=getPageInfo,exports.getReactTree=getReactTree,exports.goBack=goBack,exports.goForward=goForward,exports.inputText=inputText,exports.installConsoleCapture=installConsoleCapture,exports.installNavigationInterceptor=installNavigationInterceptor,exports.navigate=navigate,exports.queryDom=queryDom,exports.reload=reload,exports.removeHighlights=removeHighlights,exports.scroll=scroll,exports.scrollTo=scrollTo,exports.selectOption=selectOption,exports.softReplace=softReplace,exports.startDebugger=startDebugger,exports.takeScreenshot=takeScreenshot,exports.wrapFn=wrapFn});
|