@auticlabs/bulut 1.4.0 → 1.4.1

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.
@@ -1 +1 @@
1
- {"version":3,"file":"embed.cjs","sources":["../node_modules/preact/dist/preact.module.js","../node_modules/preact/jsx-runtime/dist/jsxRuntime.module.js","../node_modules/preact/hooks/dist/hooks.module.js","../src/styles/constants.ts","../src/assets.ts","../src/assets/icons/hand-raised.svg?raw","../src/assets/icons/microphone-outline.svg?raw","../src/assets/icons/stop-outline.svg?raw","../src/assets/icons/x-mark.svg?raw","../src/components/SvgIcon.tsx","../src/components/ChatButton.tsx","../src/agent/context.ts","../src/agent/contextConfig.ts","../src/agent/tools.ts","../src/api/client.ts","../src/audio/sfxManager.ts","../src/assets/sfx/sent.mp3","../src/assets/sfx/thinking.mp3","../src/assets/sfx/tool_call.mp3","../src/assets/sfx/completed.mp3","../src/components/ChatWindow.tsx","../src/assets/icons/bulut_logo.svg?raw","../src/assets/icons/arrow-path.svg?raw","../src/assets/icons/cursor-arrow-rays.svg?raw","../src/assets/icons/map.svg?raw","../src/assets/icons/queue-list.svg?raw","../src/assets/icons/command-line.svg?raw","../src/assets/icons/face-smile.svg?raw","../src/index.tsx"],"sourcesContent":["var n,l,u,t,i,o,r,e,f,c,s,a,h,p={},v=[],y=/acit|ex(?:s|g|n|p|$)|rph|grid|ows|mnc|ntw|ine[ch]|zoo|^ord|itera/i,d=Array.isArray;function w(n,l){for(var u in l)n[u]=l[u];return n}function g(n){n&&n.parentNode&&n.parentNode.removeChild(n)}function _(l,u,t){var i,o,r,e={};for(r in u)\"key\"==r?i=u[r]:\"ref\"==r?o=u[r]:e[r]=u[r];if(arguments.length>2&&(e.children=arguments.length>3?n.call(arguments,2):t),\"function\"==typeof l&&null!=l.defaultProps)for(r in l.defaultProps)void 0===e[r]&&(e[r]=l.defaultProps[r]);return m(l,e,i,o,null)}function m(n,t,i,o,r){var e={type:n,props:t,key:i,ref:o,__k:null,__:null,__b:0,__e:null,__c:null,constructor:void 0,__v:null==r?++u:r,__i:-1,__u:0};return null==r&&null!=l.vnode&&l.vnode(e),e}function b(){return{current:null}}function k(n){return n.children}function x(n,l){this.props=n,this.context=l}function S(n,l){if(null==l)return n.__?S(n.__,n.__i+1):null;for(var u;l<n.__k.length;l++)if(null!=(u=n.__k[l])&&null!=u.__e)return u.__e;return\"function\"==typeof n.type?S(n):null}function C(n){var l,u;if(null!=(n=n.__)&&null!=n.__c){for(n.__e=n.__c.base=null,l=0;l<n.__k.length;l++)if(null!=(u=n.__k[l])&&null!=u.__e){n.__e=n.__c.base=u.__e;break}return C(n)}}function M(n){(!n.__d&&(n.__d=!0)&&i.push(n)&&!$.__r++||o!=l.debounceRendering)&&((o=l.debounceRendering)||r)($)}function $(){for(var n,u,t,o,r,f,c,s=1;i.length;)i.length>s&&i.sort(e),n=i.shift(),s=i.length,n.__d&&(t=void 0,o=void 0,r=(o=(u=n).__v).__e,f=[],c=[],u.__P&&((t=w({},o)).__v=o.__v+1,l.vnode&&l.vnode(t),O(u.__P,t,o,u.__n,u.__P.namespaceURI,32&o.__u?[r]:null,f,null==r?S(o):r,!!(32&o.__u),c),t.__v=o.__v,t.__.__k[t.__i]=t,N(f,t,c),o.__e=o.__=null,t.__e!=r&&C(t)));$.__r=0}function I(n,l,u,t,i,o,r,e,f,c,s){var a,h,y,d,w,g,_,m=t&&t.__k||v,b=l.length;for(f=P(u,l,m,f,b),a=0;a<b;a++)null!=(y=u.__k[a])&&(h=-1==y.__i?p:m[y.__i]||p,y.__i=a,g=O(n,y,h,i,o,r,e,f,c,s),d=y.__e,y.ref&&h.ref!=y.ref&&(h.ref&&B(h.ref,null,y),s.push(y.ref,y.__c||d,y)),null==w&&null!=d&&(w=d),(_=!!(4&y.__u))||h.__k===y.__k?f=A(y,f,n,_):\"function\"==typeof y.type&&void 0!==g?f=g:d&&(f=d.nextSibling),y.__u&=-7);return u.__e=w,f}function P(n,l,u,t,i){var o,r,e,f,c,s=u.length,a=s,h=0;for(n.__k=new Array(i),o=0;o<i;o++)null!=(r=l[o])&&\"boolean\"!=typeof r&&\"function\"!=typeof r?(\"string\"==typeof r||\"number\"==typeof r||\"bigint\"==typeof r||r.constructor==String?r=n.__k[o]=m(null,r,null,null,null):d(r)?r=n.__k[o]=m(k,{children:r},null,null,null):void 0===r.constructor&&r.__b>0?r=n.__k[o]=m(r.type,r.props,r.key,r.ref?r.ref:null,r.__v):n.__k[o]=r,f=o+h,r.__=n,r.__b=n.__b+1,e=null,-1!=(c=r.__i=L(r,u,f,a))&&(a--,(e=u[c])&&(e.__u|=2)),null==e||null==e.__v?(-1==c&&(i>s?h--:i<s&&h++),\"function\"!=typeof r.type&&(r.__u|=4)):c!=f&&(c==f-1?h--:c==f+1?h++:(c>f?h--:h++,r.__u|=4))):n.__k[o]=null;if(a)for(o=0;o<s;o++)null!=(e=u[o])&&0==(2&e.__u)&&(e.__e==t&&(t=S(e)),D(e,e));return t}function A(n,l,u,t){var i,o;if(\"function\"==typeof n.type){for(i=n.__k,o=0;i&&o<i.length;o++)i[o]&&(i[o].__=n,l=A(i[o],l,u,t));return l}n.__e!=l&&(t&&(l&&n.type&&!l.parentNode&&(l=S(n)),u.insertBefore(n.__e,l||null)),l=n.__e);do{l=l&&l.nextSibling}while(null!=l&&8==l.nodeType);return l}function H(n,l){return l=l||[],null==n||\"boolean\"==typeof n||(d(n)?n.some(function(n){H(n,l)}):l.push(n)),l}function L(n,l,u,t){var i,o,r,e=n.key,f=n.type,c=l[u],s=null!=c&&0==(2&c.__u);if(null===c&&null==e||s&&e==c.key&&f==c.type)return u;if(t>(s?1:0))for(i=u-1,o=u+1;i>=0||o<l.length;)if(null!=(c=l[r=i>=0?i--:o++])&&0==(2&c.__u)&&e==c.key&&f==c.type)return r;return-1}function T(n,l,u){\"-\"==l[0]?n.setProperty(l,null==u?\"\":u):n[l]=null==u?\"\":\"number\"!=typeof u||y.test(l)?u:u+\"px\"}function j(n,l,u,t,i){var o,r;n:if(\"style\"==l)if(\"string\"==typeof u)n.style.cssText=u;else{if(\"string\"==typeof t&&(n.style.cssText=t=\"\"),t)for(l in t)u&&l in u||T(n.style,l,\"\");if(u)for(l in u)t&&u[l]==t[l]||T(n.style,l,u[l])}else if(\"o\"==l[0]&&\"n\"==l[1])o=l!=(l=l.replace(f,\"$1\")),r=l.toLowerCase(),l=r in n||\"onFocusOut\"==l||\"onFocusIn\"==l?r.slice(2):l.slice(2),n.l||(n.l={}),n.l[l+o]=u,u?t?u.u=t.u:(u.u=c,n.addEventListener(l,o?a:s,o)):n.removeEventListener(l,o?a:s,o);else{if(\"http://www.w3.org/2000/svg\"==i)l=l.replace(/xlink(H|:h)/,\"h\").replace(/sName$/,\"s\");else if(\"width\"!=l&&\"height\"!=l&&\"href\"!=l&&\"list\"!=l&&\"form\"!=l&&\"tabIndex\"!=l&&\"download\"!=l&&\"rowSpan\"!=l&&\"colSpan\"!=l&&\"role\"!=l&&\"popover\"!=l&&l in n)try{n[l]=null==u?\"\":u;break n}catch(n){}\"function\"==typeof u||(null==u||!1===u&&\"-\"!=l[4]?n.removeAttribute(l):n.setAttribute(l,\"popover\"==l&&1==u?\"\":u))}}function F(n){return function(u){if(this.l){var t=this.l[u.type+n];if(null==u.t)u.t=c++;else if(u.t<t.u)return;return t(l.event?l.event(u):u)}}}function O(n,u,t,i,o,r,e,f,c,s){var a,h,p,v,y,_,m,b,S,C,M,$,P,A,H,L,T,j=u.type;if(void 0!==u.constructor)return null;128&t.__u&&(c=!!(32&t.__u),r=[f=u.__e=t.__e]),(a=l.__b)&&a(u);n:if(\"function\"==typeof j)try{if(b=u.props,S=\"prototype\"in j&&j.prototype.render,C=(a=j.contextType)&&i[a.__c],M=a?C?C.props.value:a.__:i,t.__c?m=(h=u.__c=t.__c).__=h.__E:(S?u.__c=h=new j(b,M):(u.__c=h=new x(b,M),h.constructor=j,h.render=E),C&&C.sub(h),h.state||(h.state={}),h.__n=i,p=h.__d=!0,h.__h=[],h._sb=[]),S&&null==h.__s&&(h.__s=h.state),S&&null!=j.getDerivedStateFromProps&&(h.__s==h.state&&(h.__s=w({},h.__s)),w(h.__s,j.getDerivedStateFromProps(b,h.__s))),v=h.props,y=h.state,h.__v=u,p)S&&null==j.getDerivedStateFromProps&&null!=h.componentWillMount&&h.componentWillMount(),S&&null!=h.componentDidMount&&h.__h.push(h.componentDidMount);else{if(S&&null==j.getDerivedStateFromProps&&b!==v&&null!=h.componentWillReceiveProps&&h.componentWillReceiveProps(b,M),u.__v==t.__v||!h.__e&&null!=h.shouldComponentUpdate&&!1===h.shouldComponentUpdate(b,h.__s,M)){for(u.__v!=t.__v&&(h.props=b,h.state=h.__s,h.__d=!1),u.__e=t.__e,u.__k=t.__k,u.__k.some(function(n){n&&(n.__=u)}),$=0;$<h._sb.length;$++)h.__h.push(h._sb[$]);h._sb=[],h.__h.length&&e.push(h);break n}null!=h.componentWillUpdate&&h.componentWillUpdate(b,h.__s,M),S&&null!=h.componentDidUpdate&&h.__h.push(function(){h.componentDidUpdate(v,y,_)})}if(h.context=M,h.props=b,h.__P=n,h.__e=!1,P=l.__r,A=0,S){for(h.state=h.__s,h.__d=!1,P&&P(u),a=h.render(h.props,h.state,h.context),H=0;H<h._sb.length;H++)h.__h.push(h._sb[H]);h._sb=[]}else do{h.__d=!1,P&&P(u),a=h.render(h.props,h.state,h.context),h.state=h.__s}while(h.__d&&++A<25);h.state=h.__s,null!=h.getChildContext&&(i=w(w({},i),h.getChildContext())),S&&!p&&null!=h.getSnapshotBeforeUpdate&&(_=h.getSnapshotBeforeUpdate(v,y)),L=a,null!=a&&a.type===k&&null==a.key&&(L=V(a.props.children)),f=I(n,d(L)?L:[L],u,t,i,o,r,e,f,c,s),h.base=u.__e,u.__u&=-161,h.__h.length&&e.push(h),m&&(h.__E=h.__=null)}catch(n){if(u.__v=null,c||null!=r)if(n.then){for(u.__u|=c?160:128;f&&8==f.nodeType&&f.nextSibling;)f=f.nextSibling;r[r.indexOf(f)]=null,u.__e=f}else{for(T=r.length;T--;)g(r[T]);z(u)}else u.__e=t.__e,u.__k=t.__k,n.then||z(u);l.__e(n,u,t)}else null==r&&u.__v==t.__v?(u.__k=t.__k,u.__e=t.__e):f=u.__e=q(t.__e,u,t,i,o,r,e,c,s);return(a=l.diffed)&&a(u),128&u.__u?void 0:f}function z(n){n&&n.__c&&(n.__c.__e=!0),n&&n.__k&&n.__k.forEach(z)}function N(n,u,t){for(var i=0;i<t.length;i++)B(t[i],t[++i],t[++i]);l.__c&&l.__c(u,n),n.some(function(u){try{n=u.__h,u.__h=[],n.some(function(n){n.call(u)})}catch(n){l.__e(n,u.__v)}})}function V(n){return\"object\"!=typeof n||null==n||n.__b&&n.__b>0?n:d(n)?n.map(V):w({},n)}function q(u,t,i,o,r,e,f,c,s){var a,h,v,y,w,_,m,b=i.props||p,k=t.props,x=t.type;if(\"svg\"==x?r=\"http://www.w3.org/2000/svg\":\"math\"==x?r=\"http://www.w3.org/1998/Math/MathML\":r||(r=\"http://www.w3.org/1999/xhtml\"),null!=e)for(a=0;a<e.length;a++)if((w=e[a])&&\"setAttribute\"in w==!!x&&(x?w.localName==x:3==w.nodeType)){u=w,e[a]=null;break}if(null==u){if(null==x)return document.createTextNode(k);u=document.createElementNS(r,x,k.is&&k),c&&(l.__m&&l.__m(t,e),c=!1),e=null}if(null==x)b===k||c&&u.data==k||(u.data=k);else{if(e=e&&n.call(u.childNodes),!c&&null!=e)for(b={},a=0;a<u.attributes.length;a++)b[(w=u.attributes[a]).name]=w.value;for(a in b)if(w=b[a],\"children\"==a);else if(\"dangerouslySetInnerHTML\"==a)v=w;else if(!(a in k)){if(\"value\"==a&&\"defaultValue\"in k||\"checked\"==a&&\"defaultChecked\"in k)continue;j(u,a,null,w,r)}for(a in k)w=k[a],\"children\"==a?y=w:\"dangerouslySetInnerHTML\"==a?h=w:\"value\"==a?_=w:\"checked\"==a?m=w:c&&\"function\"!=typeof w||b[a]===w||j(u,a,w,b[a],r);if(h)c||v&&(h.__html==v.__html||h.__html==u.innerHTML)||(u.innerHTML=h.__html),t.__k=[];else if(v&&(u.innerHTML=\"\"),I(\"template\"==t.type?u.content:u,d(y)?y:[y],t,i,o,\"foreignObject\"==x?\"http://www.w3.org/1999/xhtml\":r,e,f,e?e[0]:i.__k&&S(i,0),c,s),null!=e)for(a=e.length;a--;)g(e[a]);c||(a=\"value\",\"progress\"==x&&null==_?u.removeAttribute(\"value\"):null!=_&&(_!==u[a]||\"progress\"==x&&!_||\"option\"==x&&_!=b[a])&&j(u,a,_,b[a],r),a=\"checked\",null!=m&&m!=u[a]&&j(u,a,m,b[a],r))}return u}function B(n,u,t){try{if(\"function\"==typeof n){var i=\"function\"==typeof n.__u;i&&n.__u(),i&&null==u||(n.__u=n(u))}else n.current=u}catch(n){l.__e(n,t)}}function D(n,u,t){var i,o;if(l.unmount&&l.unmount(n),(i=n.ref)&&(i.current&&i.current!=n.__e||B(i,null,u)),null!=(i=n.__c)){if(i.componentWillUnmount)try{i.componentWillUnmount()}catch(n){l.__e(n,u)}i.base=i.__P=null}if(i=n.__k)for(o=0;o<i.length;o++)i[o]&&D(i[o],u,t||\"function\"!=typeof n.type);t||g(n.__e),n.__c=n.__=n.__e=void 0}function E(n,l,u){return this.constructor(n,u)}function G(u,t,i){var o,r,e,f;t==document&&(t=document.documentElement),l.__&&l.__(u,t),r=(o=\"function\"==typeof i)?null:i&&i.__k||t.__k,e=[],f=[],O(t,u=(!o&&i||t).__k=_(k,null,[u]),r||p,p,t.namespaceURI,!o&&i?[i]:r?null:t.firstChild?n.call(t.childNodes):null,e,!o&&i?i:r?r.__e:t.firstChild,o,f),N(e,u,f)}function J(n,l){G(n,l,J)}function K(l,u,t){var i,o,r,e,f=w({},l.props);for(r in l.type&&l.type.defaultProps&&(e=l.type.defaultProps),u)\"key\"==r?i=u[r]:\"ref\"==r?o=u[r]:f[r]=void 0===u[r]&&null!=e?e[r]:u[r];return arguments.length>2&&(f.children=arguments.length>3?n.call(arguments,2):t),m(l.type,f,i||l.key,o||l.ref,null)}function Q(n){function l(n){var u,t;return this.getChildContext||(u=new Set,(t={})[l.__c]=this,this.getChildContext=function(){return t},this.componentWillUnmount=function(){u=null},this.shouldComponentUpdate=function(n){this.props.value!=n.value&&u.forEach(function(n){n.__e=!0,M(n)})},this.sub=function(n){u.add(n);var l=n.componentWillUnmount;n.componentWillUnmount=function(){u&&u.delete(n),l&&l.call(n)}}),n.children}return l.__c=\"__cC\"+h++,l.__=n,l.Provider=l.__l=(l.Consumer=function(n,l){return n.children(l)}).contextType=l,l}n=v.slice,l={__e:function(n,l,u,t){for(var i,o,r;l=l.__;)if((i=l.__c)&&!i.__)try{if((o=i.constructor)&&null!=o.getDerivedStateFromError&&(i.setState(o.getDerivedStateFromError(n)),r=i.__d),null!=i.componentDidCatch&&(i.componentDidCatch(n,t||{}),r=i.__d),r)return i.__E=i}catch(l){n=l}throw n}},u=0,t=function(n){return null!=n&&void 0===n.constructor},x.prototype.setState=function(n,l){var u;u=null!=this.__s&&this.__s!=this.state?this.__s:this.__s=w({},this.state),\"function\"==typeof n&&(n=n(w({},u),this.props)),n&&w(u,n),null!=n&&this.__v&&(l&&this._sb.push(l),M(this))},x.prototype.forceUpdate=function(n){this.__v&&(this.__e=!0,n&&this.__h.push(n),M(this))},x.prototype.render=k,i=[],r=\"function\"==typeof Promise?Promise.prototype.then.bind(Promise.resolve()):setTimeout,e=function(n,l){return n.__v.__b-l.__v.__b},$.__r=0,f=/(PointerCapture)$|Capture$/i,c=0,s=F(!1),a=F(!0),h=0;export{x as Component,k as Fragment,K as cloneElement,Q as createContext,_ as createElement,b as createRef,_ as h,J as hydrate,t as isValidElement,l as options,G as render,H as toChildArray};\n//# sourceMappingURL=preact.module.js.map\n","import{options as r,Fragment as e}from\"preact\";export{Fragment}from\"preact\";var t=/[\"&<]/;function n(r){if(0===r.length||!1===t.test(r))return r;for(var e=0,n=0,o=\"\",f=\"\";n<r.length;n++){switch(r.charCodeAt(n)){case 34:f=\"&quot;\";break;case 38:f=\"&amp;\";break;case 60:f=\"&lt;\";break;default:continue}n!==e&&(o+=r.slice(e,n)),o+=f,e=n+1}return n!==e&&(o+=r.slice(e,n)),o}var o=/acit|ex(?:s|g|n|p|$)|rph|grid|ows|mnc|ntw|ine[ch]|zoo|^ord|itera/i,f=0,i=Array.isArray;function u(e,t,n,o,i,u){t||(t={});var a,c,p=t;if(\"ref\"in p)for(c in p={},t)\"ref\"==c?a=t[c]:p[c]=t[c];var l={type:e,props:p,key:n,ref:a,__k:null,__:null,__b:0,__e:null,__c:null,constructor:void 0,__v:--f,__i:-1,__u:0,__source:i,__self:u};if(\"function\"==typeof e&&(a=e.defaultProps))for(c in a)void 0===p[c]&&(p[c]=a[c]);return r.vnode&&r.vnode(l),l}function a(r){var t=u(e,{tpl:r,exprs:[].slice.call(arguments,1)});return t.key=t.__v,t}var c={},p=/[A-Z]/g;function l(e,t){if(r.attr){var f=r.attr(e,t);if(\"string\"==typeof f)return f}if(t=function(r){return null!==r&&\"object\"==typeof r&&\"function\"==typeof r.valueOf?r.valueOf():r}(t),\"ref\"===e||\"key\"===e)return\"\";if(\"style\"===e&&\"object\"==typeof t){var i=\"\";for(var u in t){var a=t[u];if(null!=a&&\"\"!==a){var l=\"-\"==u[0]?u:c[u]||(c[u]=u.replace(p,\"-$&\").toLowerCase()),s=\";\";\"number\"!=typeof a||l.startsWith(\"--\")||o.test(l)||(s=\"px;\"),i=i+l+\":\"+a+s}}return e+'=\"'+n(i)+'\"'}return null==t||!1===t||\"function\"==typeof t||\"object\"==typeof t?\"\":!0===t?e:e+'=\"'+n(\"\"+t)+'\"'}function s(r){if(null==r||\"boolean\"==typeof r||\"function\"==typeof r)return null;if(\"object\"==typeof r){if(void 0===r.constructor)return r;if(i(r)){for(var e=0;e<r.length;e++)r[e]=s(r[e]);return r}}return n(\"\"+r)}export{u as jsx,l as jsxAttr,u as jsxDEV,s as jsxEscape,a as jsxTemplate,u as jsxs};\n//# sourceMappingURL=jsxRuntime.module.js.map\n","import{options as n}from\"preact\";var t,r,u,i,o=0,f=[],c=n,e=c.__b,a=c.__r,v=c.diffed,l=c.__c,m=c.unmount,s=c.__;function p(n,t){c.__h&&c.__h(r,n,o||t),o=0;var u=r.__H||(r.__H={__:[],__h:[]});return n>=u.__.length&&u.__.push({}),u.__[n]}function d(n){return o=1,h(D,n)}function h(n,u,i){var o=p(t++,2);if(o.t=n,!o.__c&&(o.__=[i?i(u):D(void 0,u),function(n){var t=o.__N?o.__N[0]:o.__[0],r=o.t(t,n);t!==r&&(o.__N=[r,o.__[1]],o.__c.setState({}))}],o.__c=r,!r.__f)){var f=function(n,t,r){if(!o.__c.__H)return!0;var u=o.__c.__H.__.filter(function(n){return!!n.__c});if(u.every(function(n){return!n.__N}))return!c||c.call(this,n,t,r);var i=o.__c.props!==n;return u.forEach(function(n){if(n.__N){var t=n.__[0];n.__=n.__N,n.__N=void 0,t!==n.__[0]&&(i=!0)}}),c&&c.call(this,n,t,r)||i};r.__f=!0;var c=r.shouldComponentUpdate,e=r.componentWillUpdate;r.componentWillUpdate=function(n,t,r){if(this.__e){var u=c;c=void 0,f(n,t,r),c=u}e&&e.call(this,n,t,r)},r.shouldComponentUpdate=f}return o.__N||o.__}function y(n,u){var i=p(t++,3);!c.__s&&C(i.__H,u)&&(i.__=n,i.u=u,r.__H.__h.push(i))}function _(n,u){var i=p(t++,4);!c.__s&&C(i.__H,u)&&(i.__=n,i.u=u,r.__h.push(i))}function A(n){return o=5,T(function(){return{current:n}},[])}function F(n,t,r){o=6,_(function(){if(\"function\"==typeof n){var r=n(t());return function(){n(null),r&&\"function\"==typeof r&&r()}}if(n)return n.current=t(),function(){return n.current=null}},null==r?r:r.concat(n))}function T(n,r){var u=p(t++,7);return C(u.__H,r)&&(u.__=n(),u.__H=r,u.__h=n),u.__}function q(n,t){return o=8,T(function(){return n},t)}function x(n){var u=r.context[n.__c],i=p(t++,9);return i.c=n,u?(null==i.__&&(i.__=!0,u.sub(r)),u.props.value):n.__}function P(n,t){c.useDebugValue&&c.useDebugValue(t?t(n):n)}function b(n){var u=p(t++,10),i=d();return u.__=n,r.componentDidCatch||(r.componentDidCatch=function(n,t){u.__&&u.__(n,t),i[1](n)}),[i[0],function(){i[1](void 0)}]}function g(){var n=p(t++,11);if(!n.__){for(var u=r.__v;null!==u&&!u.__m&&null!==u.__;)u=u.__;var i=u.__m||(u.__m=[0,0]);n.__=\"P\"+i[0]+\"-\"+i[1]++}return n.__}function j(){for(var n;n=f.shift();)if(n.__P&&n.__H)try{n.__H.__h.forEach(z),n.__H.__h.forEach(B),n.__H.__h=[]}catch(t){n.__H.__h=[],c.__e(t,n.__v)}}c.__b=function(n){r=null,e&&e(n)},c.__=function(n,t){n&&t.__k&&t.__k.__m&&(n.__m=t.__k.__m),s&&s(n,t)},c.__r=function(n){a&&a(n),t=0;var i=(r=n.__c).__H;i&&(u===r?(i.__h=[],r.__h=[],i.__.forEach(function(n){n.__N&&(n.__=n.__N),n.u=n.__N=void 0})):(i.__h.forEach(z),i.__h.forEach(B),i.__h=[],t=0)),u=r},c.diffed=function(n){v&&v(n);var t=n.__c;t&&t.__H&&(t.__H.__h.length&&(1!==f.push(t)&&i===c.requestAnimationFrame||((i=c.requestAnimationFrame)||w)(j)),t.__H.__.forEach(function(n){n.u&&(n.__H=n.u),n.u=void 0})),u=r=null},c.__c=function(n,t){t.some(function(n){try{n.__h.forEach(z),n.__h=n.__h.filter(function(n){return!n.__||B(n)})}catch(r){t.some(function(n){n.__h&&(n.__h=[])}),t=[],c.__e(r,n.__v)}}),l&&l(n,t)},c.unmount=function(n){m&&m(n);var t,r=n.__c;r&&r.__H&&(r.__H.__.forEach(function(n){try{z(n)}catch(n){t=n}}),r.__H=void 0,t&&c.__e(t,r.__v))};var k=\"function\"==typeof requestAnimationFrame;function w(n){var t,r=function(){clearTimeout(u),k&&cancelAnimationFrame(t),setTimeout(n)},u=setTimeout(r,35);k&&(t=requestAnimationFrame(r))}function z(n){var t=r,u=n.__c;\"function\"==typeof u&&(n.__c=void 0,u()),r=t}function B(n){var t=r;n.__c=n.__(),r=t}function C(n,t){return!n||n.length!==t.length||t.some(function(t,r){return t!==n[r]})}function D(n,t){return\"function\"==typeof t?t(n):t}export{q as useCallback,x as useContext,P as useDebugValue,y as useEffect,b as useErrorBoundary,g as useId,F as useImperativeHandle,_ as useLayoutEffect,T as useMemo,h as useReducer,A as useRef,d as useState};\n//# sourceMappingURL=hooks.module.js.map\n","// Widget dimensions\r\nexport const BUTTON_SIZE = 60;\r\nexport const WINDOW_WIDTH = 350;\r\nexport const WINDOW_HEIGHT = 500;\r\n\r\n// Positioning\r\nexport const POSITION_BOTTOM = 20;\r\nexport const POSITION_RIGHT = 20;\r\n\r\n// Colors — initial values match the backend ProjectSettings default.\r\n// applyTheme() in index.tsx overrides primary/primaryHover/messageUser\r\n// with the remote config value before the widget renders.\r\nexport const COLORS = {\r\n primary: \"#6C03C1\",\r\n primaryHover: \"#5b02a4\",\r\n background: \"#ffffff\",\r\n text: \"hsla(215, 100%, 5%, 1)\",\r\n textSecondary: \"hsla(215, 100%, 5%, 1)\",\r\n border: \"#e5e7eb\",\r\n messageBot: \"\",\r\n messageUser: \"#6C03C1\",\r\n messageUserText: \"#ffffff\",\r\n};\r\n\r\nconst normalizeHexColor = (hex: string): string => {\r\n const trimmed = hex.trim();\r\n if (!/^#([0-9a-fA-F]{3}|[0-9a-fA-F]{6})$/.test(trimmed)) {\r\n return \"hsla(215, 100%, 5%, 1)\";\r\n }\r\n if (trimmed.length === 4) {\r\n const r = trimmed[1];\r\n const g = trimmed[2];\r\n const b = trimmed[3];\r\n return `#${r}${r}${g}${g}${b}${b}`;\r\n }\r\n return trimmed;\r\n};\r\n\r\nexport const getContrastIconFilter = (backgroundHex: string): string => {\r\n const hex = normalizeHexColor(backgroundHex).slice(1);\r\n const r = parseInt(hex.slice(0, 2), 16);\r\n const g = parseInt(hex.slice(2, 4), 16);\r\n const b = parseInt(hex.slice(4, 6), 16);\r\n\r\n // Relative luminance approximation for quick contrast choice.\r\n const luminance = (0.299 * r + 0.587 * g + 0.114 * b) / 255;\r\n return luminance > 0.62 ? \"brightness(0) invert(0)\" : \"brightness(0) invert(1)\";\r\n};\r\n\r\n// Border radius\r\nexport const BORDER_RADIUS = {\r\n button: '50%',\r\n window: '17px',\r\n message: '10px'\r\n};\r\n\r\n// Shadows\r\nexport const SHADOW = \"0 0 15px hsla(215, 100%, 5%, 0.15)\";\r\n\r\n// Transitions\r\nexport const TRANSITIONS = {\r\n fast: '150ms ease-in-out',\r\n medium: '250ms ease-in-out'\r\n};\r\n","import microphoneIcon from \"./assets/icons/microphone.svg?inline\";\r\nimport microphoneIconRaw from \"./assets/icons/microphone.svg?raw\";\r\nimport restartIcon from \"./assets/icons/restart.svg?inline\";\r\nimport restartIconRaw from \"./assets/icons/restart.svg?raw\";\r\nimport closeIcon from \"./assets/icons/close.svg?inline\";\r\nimport closeIconRaw from \"./assets/icons/close.svg?raw\";\r\nimport stopIcon from \"./assets/icons/stop.svg?inline\";\r\nimport stopIconRaw from \"./assets/icons/stop.svg?raw\";\r\nimport arrowPathIconRaw from \"./assets/icons/arrow-path.svg?raw\";\r\nimport commandLineIconRaw from \"./assets/icons/command-line.svg?raw\";\r\nimport cursorArrowRaysIconRaw from \"./assets/icons/cursor-arrow-rays.svg?raw\";\r\nimport faceSmileIconRaw from \"./assets/icons/face-smile.svg?raw\";\r\nimport handRaisedIconRaw from \"./assets/icons/hand-raised.svg?raw\";\r\nimport mapIconRaw from \"./assets/icons/map.svg?raw\";\r\nimport microphoneOutlineIconRaw from \"./assets/icons/microphone-outline.svg?raw\";\r\nimport queueListIconRaw from \"./assets/icons/queue-list.svg?raw\";\r\nimport stopOutlineIconRaw from \"./assets/icons/stop-outline.svg?raw\";\r\nimport xMarkIconRaw from \"./assets/icons/x-mark.svg?raw\";\r\nimport bulutLogo from \"./assets/icons/bulut_logo.svg\";\r\nimport bulutLogoRaw from \"./assets/icons/bulut_logo.svg?raw\";\r\nimport sentSfx from \"./assets/sfx/sent.mp3\";\r\nimport thinkingSfx from \"./assets/sfx/thinking.mp3\";\r\nimport toolCallSfx from \"./assets/sfx/tool_call.mp3\";\r\nimport completedSfx from \"./assets/sfx/completed.mp3\";\r\n\r\nexport const microphoneIconUrl = microphoneIcon;\r\nexport const microphoneIconContent = microphoneIconRaw;\r\nexport const restartIconUrl = restartIcon;\r\nexport const restartIconContent = restartIconRaw;\r\nexport const closeIconUrl = closeIcon;\r\nexport const closeIconContent = closeIconRaw;\r\nexport const stopIconUrl = stopIcon;\r\nexport const stopIconContent = stopIconRaw;\r\nexport const arrowPathIconContent = arrowPathIconRaw;\r\nexport const commandLineIconContent = commandLineIconRaw;\r\nexport const cursorArrowRaysIconContent = cursorArrowRaysIconRaw;\r\nexport const faceSmileIconContent = faceSmileIconRaw;\r\nexport const handRaisedIconContent = handRaisedIconRaw;\r\nexport const mapIconContent = mapIconRaw;\r\nexport const microphoneOutlineIconContent = microphoneOutlineIconRaw;\r\nexport const queueListIconContent = queueListIconRaw;\r\nexport const stopOutlineIconContent = stopOutlineIconRaw;\r\nexport const xMarkIconContent = xMarkIconRaw;\r\nexport const logoUrl = bulutLogo;\r\nexport const logoContent = bulutLogoRaw;\r\nexport const sentSfxUrl = sentSfx;\r\nexport const thinkingSfxUrl = thinkingSfx;\r\nexport const toolCallSfxUrl = toolCallSfx;\r\nexport const completedSfxUrl = completedSfx;\r\n","export default \"<svg xmlns=\\\"http://www.w3.org/2000/svg\\\" fill=\\\"none\\\" viewBox=\\\"0 0 24 24\\\" stroke-width=\\\"1.5\\\" stroke=\\\"currentColor\\\">\\r\\n <path stroke-linecap=\\\"round\\\" stroke-linejoin=\\\"round\\\" d=\\\"M10.05 4.575a1.575 1.575 0 1 0-3.15 0v3m3.15-3v-1.5a1.575 1.575 0 0 1 3.15 0v1.5m-3.15 0 .075 5.925m3.075.75V4.575m0 0a1.575 1.575 0 0 1 3.15 0V15M6.9 7.575a1.575 1.575 0 1 0-3.15 0v8.175a6.75 6.75 0 0 0 6.75 6.75h2.018a5.25 5.25 0 0 0 3.712-1.538l1.732-1.732a5.25 5.25 0 0 0 1.538-3.712l.003-2.024a.668.668 0 0 1 .198-.471 1.575 1.575 0 1 0-2.228-2.228 3.818 3.818 0 0 0-1.12 2.687M6.9 7.575V12m6.27 4.318A4.49 4.49 0 0 1 16.35 15m.002 0h-.002\\\" />\\r\\n</svg>\\r\\n\"","export default \"<svg xmlns=\\\"http://www.w3.org/2000/svg\\\" fill=\\\"none\\\" viewBox=\\\"0 0 24 24\\\" stroke-width=\\\"1.5\\\" stroke=\\\"currentColor\\\">\\r\\n <path stroke-linecap=\\\"round\\\" stroke-linejoin=\\\"round\\\" d=\\\"M12 18.75a6 6 0 0 0 6-6v-1.5m-6 7.5a6 6 0 0 1-6-6v-1.5m6 7.5v3.75m-3.75 0h7.5M12 15.75a3 3 0 0 1-3-3V4.5a3 3 0 1 1 6 0v8.25a3 3 0 0 1-3 3Z\\\" />\\r\\n</svg>\\r\\n\"","export default \"<svg xmlns=\\\"http://www.w3.org/2000/svg\\\" fill=\\\"none\\\" viewBox=\\\"0 0 24 24\\\" stroke-width=\\\"1.5\\\" stroke=\\\"currentColor\\\">\\r\\n <path stroke-linecap=\\\"round\\\" stroke-linejoin=\\\"round\\\" d=\\\"M5.25 7.5A2.25 2.25 0 0 1 7.5 5.25h9a2.25 2.25 0 0 1 2.25 2.25v9a2.25 2.25 0 0 1-2.25 2.25h-9a2.25 2.25 0 0 1-2.25-2.25v-9Z\\\" />\\r\\n</svg>\\r\\n\"","export default \"<svg xmlns=\\\"http://www.w3.org/2000/svg\\\" fill=\\\"none\\\" viewBox=\\\"0 0 24 24\\\" stroke-width=\\\"1.5\\\" stroke=\\\"currentColor\\\">\\r\\n <path stroke-linecap=\\\"round\\\" stroke-linejoin=\\\"round\\\" d=\\\"M6 18 18 6M6 6l12 12\\\" />\\r\\n</svg>\\r\\n\"","\r\nimport type { CSSProperties, JSX } from \"preact\";\r\nimport { useMemo } from \"preact/hooks\";\r\n\r\nexport type SvgIconProps = Omit<JSX.IntrinsicElements[\"svg\"], \"style\"> & {\r\n src: string;\r\n title?: string;\r\n /**\r\n * If true, replaces fill and stroke attributes with \"currentColor\" in the inner SVG content.\r\n * Default: true\r\n */\r\n stripColors?: boolean;\r\n style?: CSSProperties;\r\n // Explicitly add common props to ensure destructuring works smoothly\r\n className?: string;\r\n fill?: string;\r\n stroke?: string;\r\n strokeWidth?: string | number;\r\n width?: string | number;\r\n height?: string | number;\r\n};\r\n\r\nexport function SvgIcon({\r\n src,\r\n width,\r\n height,\r\n title,\r\n stripColors = true,\r\n className,\r\n style,\r\n fill,\r\n stroke,\r\n strokeWidth,\r\n ...props\r\n}: SvgIconProps) {\r\n const { viewBox, content } = useMemo(() => {\r\n if (!src) return { viewBox: \"0 0 24 24\", content: \"\" };\r\n\r\n const trimmedSrc = src.trim();\r\n // Extract viewBox\r\n const viewBoxMatch = trimmedSrc.match(/viewBox=\"([^\"]*)\"/);\r\n const viewBox = viewBoxMatch ? viewBoxMatch[1] : \"0 0 24 24\";\r\n\r\n // Extract inner content by removing the outer <svg> wrapper\r\n // We remove the opening <svg ...> tag and the closing </svg> tag only.\r\n let content = trimmedSrc.replace(/^<svg[^>]*>/i, \"\").replace(/<\\/svg>\\s*$/i, \"\");\r\n\r\n return { viewBox, content };\r\n }, [src]);\r\n\r\n const cleanContent = useMemo(() => {\r\n if (!content) return \"\";\r\n let nextContent = content;\r\n\r\n if (stripColors) {\r\n // Force inner nodes to use props instead of hardcoded SVG values.\r\n const fillValue = fill !== undefined ? fill : \"none\";\r\n const strokeValue = stroke !== undefined ? stroke : \"currentColor\";\r\n nextContent = nextContent\r\n .replace(/fill=\"[^\"]*\"/gi, `fill=\"${fillValue}\"`)\r\n .replace(/stroke=\"[^\"]*\"/gi, `stroke=\"${strokeValue}\"`);\r\n }\r\n\r\n if (strokeWidth !== undefined) {\r\n const strokeWidthValue = String(strokeWidth);\r\n nextContent = /stroke-width=\"[^\"]*\"/i.test(nextContent)\r\n ? nextContent.replace(/stroke-width=\"[^\"]*\"/gi, `stroke-width=\"${strokeWidthValue}\"`)\r\n : nextContent.replace(\r\n /<(path|circle|ellipse|line|polyline|polygon|rect)\\b/gi,\r\n `<$1 stroke-width=\"${strokeWidthValue}\"`,\r\n );\r\n }\r\n\r\n return nextContent;\r\n }, [content, stripColors, fill, stroke, strokeWidth]);\r\n\r\n return (\r\n <svg\r\n viewBox={viewBox}\r\n width={width}\r\n height={height}\r\n className={className}\r\n style={{\r\n display: \"inline-block\",\r\n verticalAlign: \"middle\",\r\n flexShrink: 0,\r\n fill: \"none\",\r\n stroke: \"currentColor\",\r\n ...style,\r\n }}\r\n xmlns=\"http://www.w3.org/2000/svg\"\r\n {...props}\r\n dangerouslySetInnerHTML={{ __html: cleanContent }}\r\n >\r\n {title && <title>{title}</title>}\r\n </svg>\r\n );\r\n}\r\n","import {\r\n BUTTON_SIZE,\r\n POSITION_BOTTOM,\r\n POSITION_RIGHT,\r\n COLORS,\r\n SHADOW,\r\n TRANSITIONS,\r\n BORDER_RADIUS,\r\n} from \"../styles/constants\";\r\nimport {\r\n microphoneOutlineIconContent,\r\n stopOutlineIconContent,\r\n xMarkIconContent,\r\n} from \"../assets\";\r\nimport { SvgIcon } from \"./SvgIcon\";\r\n\r\ninterface ChatButtonProps {\r\n onMicClick: () => void;\r\n onCancelRecording: () => void;\r\n onStopTask: () => void;\r\n isRecording: boolean;\r\n isBusy: boolean;\r\n accessibilityMode?: boolean;\r\n showBubble: boolean;\r\n onBubbleClick: () => void;\r\n previewMessage: string | null;\r\n onPreviewClick: () => void;\r\n onPreviewClose: () => void;\r\n}\r\n\r\nexport const ChatButton = ({\r\n onMicClick,\r\n onCancelRecording,\r\n onStopTask,\r\n isRecording,\r\n isBusy,\r\n accessibilityMode = false,\r\n showBubble,\r\n onBubbleClick,\r\n previewMessage,\r\n onPreviewClick,\r\n onPreviewClose,\r\n}: ChatButtonProps) => {\r\n const bgColor = COLORS.primary;\r\n const popupBoxShadow = accessibilityMode\r\n ? `inset 0 0 0 2px ${COLORS.primary}, ${SHADOW}`\r\n : SHADOW;\r\n\r\n const containerStyle: { [key: string]: string } = {\r\n position: \"fixed\",\r\n right: `${POSITION_RIGHT}px`,\r\n bottom: `${POSITION_BOTTOM}px`,\r\n display: \"flex\",\r\n flexDirection: \"column\",\r\n alignItems: \"flex-end\",\r\n gap: \"8px\",\r\n zIndex: \"9999\",\r\n fontFamily: \"\\\"Geist\\\", sans-serif\",\r\n };\r\n\r\n const controlsRowStyle: { [key: string]: string } = {\r\n display: \"flex\",\r\n alignItems: \"center\",\r\n gap: \"10px\",\r\n };\r\n\r\n const buttonStyle: { [key: string]: string } = {\r\n width: `${BUTTON_SIZE}px`,\r\n height: `${BUTTON_SIZE}px`,\r\n minWidth: `${BUTTON_SIZE}px`,\r\n minHeight: `${BUTTON_SIZE}px`,\r\n borderRadius: BORDER_RADIUS.button,\r\n backgroundColor: bgColor,\r\n color: \"#ffffff\",\r\n border: \"none\",\r\n cursor: \"pointer\",\r\n display: \"flex\",\r\n alignItems: \"center\",\r\n justifyContent: \"center\",\r\n transition: `background-color ${TRANSITIONS.fast}, transform ${TRANSITIONS.fast}`,\r\n position: \"relative\",\r\n flexShrink: \"0\",\r\n };\r\n\r\n const iconStyle: { [key: string]: string } = {\r\n width: \"24px\",\r\n height: \"24px\",\r\n display: \"block\",\r\n };\r\n\r\n const showStopButton = isBusy && !isRecording;\r\n const mainIconSrc = showStopButton ? stopOutlineIconContent : isRecording ? xMarkIconContent : microphoneOutlineIconContent;\r\n\r\n const handleClick = () => {\r\n if (showStopButton) {\r\n onStopTask();\r\n } else if (isRecording) {\r\n onCancelRecording();\r\n } else {\r\n onMicClick();\r\n }\r\n };\r\n\r\n // Shared close button style\r\n const closeBtnStyle: { [key: string]: string } = {\r\n position: \"absolute\",\r\n top: \"6px\",\r\n right: \"6px\",\r\n width: \"20px\",\r\n height: \"20px\",\r\n borderRadius: \"50%\",\r\n border: \"none\",\r\n background: \"transparent\",\r\n cursor: \"pointer\",\r\n display: \"flex\",\r\n alignItems: \"center\",\r\n justifyContent: \"center\",\r\n fontSize: \"12px\",\r\n lineHeight: \"1\",\r\n color: COLORS.text,\r\n padding: \"0\",\r\n };\r\n\r\n const renderPopup = (\r\n content: preact.ComponentChildren,\r\n onClick: () => void,\r\n onClose: (() => void) | null,\r\n extraClass: string,\r\n scrollable: boolean,\r\n ) => (\r\n <div\r\n className={`bulut-popup ${extraClass}`}\r\n style={{ cursor: \"pointer\" }}\r\n onClick={onClick}\r\n >\r\n {/* Close button */}\r\n {onClose && (\r\n <button\r\n type=\"button\"\r\n style={closeBtnStyle}\r\n onClick={(e) => {\r\n e.stopPropagation();\r\n onClose();\r\n }}\r\n aria-label=\"Kapat\"\r\n >\r\n <SvgIcon src={xMarkIconContent} aria-hidden=\"true\" width={16} height={16} />\r\n </button>\r\n )}\r\n\r\n {/* Text content */}\r\n <div\r\n style={{\r\n paddingRight: onClose ? \"22px\" : \"0\",\r\n wordBreak: \"break-word\",\r\n ...(scrollable ? { maxHeight: \"96px\", overflowY: \"auto\" } : {}),\r\n }}\r\n >\r\n {content}\r\n </div>\r\n </div>\r\n );\r\n\r\n return (\r\n <>\r\n <style>{`\r\n @import url('https://fonts.googleapis.com/css2?family=Geist:wght@100..900&display=swap');\r\n\r\n .bulut-popup {\r\n background: #ffffff;\r\n color: ${COLORS.text};\r\n padding: 10px 14px;\r\n border-radius: 12px;\r\n font-size: 14px;\r\n line-height: 1.4;\r\n position: relative;\r\n overflow: visible;\r\n box-shadow: ${popupBoxShadow};\r\n }\r\n .bulut-popup-bubble {\r\n animation: bulut-bubbleIn 400ms ease-out;\r\n }\r\n .bulut-popup-preview {\r\n animation: bulut-popIn ${TRANSITIONS.medium};\r\n }\r\n\r\n /* Desktop: limit width, lean to right */\r\n .bulut-popup {\r\n max-width: 320px;\r\n }\r\n\r\n /* Mobile: full-width layout with popup filling remaining space */\r\n @media (max-width: 600px) {\r\n .bulut-fab-container:has(.bulut-popup) {\r\n left: 16px !important;\r\n right: 16px !important;\r\n }\r\n .bulut-fab-container:has(.bulut-popup) .bulut-controls-row {\r\n width: 100%;\r\n }\r\n .bulut-popup {\r\n flex: 1;\r\n min-width: 0;\r\n max-width: none;\r\n }\r\n }\r\n\r\n @keyframes bulut-popIn {\r\n from { opacity: 0; transform: translateX(10px); }\r\n to { opacity: 1; transform: translateX(0); }\r\n }\r\n @keyframes bulut-bubbleIn {\r\n 0% { opacity: 0; transform: translateX(10px) scale(0.95); }\r\n 60% { opacity: 1; transform: translateX(-4px) scale(1.02); }\r\n 100% { opacity: 1; transform: translateX(0) scale(1); }\r\n }\r\n @keyframes bulut-badgeIn {\r\n from { opacity: 0; transform: translateY(-4px); }\r\n to { opacity: 1; transform: translateY(0); }\r\n }\r\n `}</style>\r\n\r\n <div className=\"bulut-fab-container\" style={containerStyle}>\r\n <div className=\"bulut-controls-row\" style={controlsRowStyle}>\r\n {/* Welcome bubble */}\r\n {showBubble &&\r\n !isRecording &&\r\n !previewMessage &&\r\n renderPopup(\r\n \"Destek lazımsa hemen konuşmaya başlayabiliriz!\",\r\n onBubbleClick,\r\n null,\r\n \"bulut-popup-bubble\",\r\n false,\r\n )}\r\n\r\n {/* New-message preview */}\r\n {previewMessage &&\r\n renderPopup(\r\n previewMessage,\r\n onPreviewClick,\r\n onPreviewClose,\r\n \"bulut-popup-preview\",\r\n true,\r\n )}\r\n\r\n {/* Main mic / cancel button */}\r\n <button\r\n style={buttonStyle}\r\n onClick={handleClick}\r\n onMouseEnter={(e) => {\r\n Object.assign(e.currentTarget.style, {\r\n backgroundColor: COLORS.primaryHover,\r\n transform: \"scale(1.05)\",\r\n });\r\n }}\r\n onMouseLeave={(e) => {\r\n Object.assign(e.currentTarget.style, {\r\n transform: \"scale(1)\",\r\n });\r\n }}\r\n aria-label={showStopButton ? \"Görevi durdur\" : isRecording ? \"Kaydı iptal et\" : \"Konuşmaya başla\"}\r\n >\r\n <SvgIcon\r\n src={mainIconSrc}\r\n aria-hidden=\"true\"\r\n style={iconStyle}\r\n />\r\n </button>\r\n </div>\r\n </div>\r\n </>\r\n );\r\n};\r\n","export interface PageContext {\r\n links: string[];\r\n interactables: string[];\r\n summary: string;\r\n elementMap: Map<number, Element>;\r\n}\r\n\r\nexport interface CachedPageContextEntry {\r\n url: string;\r\n summary: string;\r\n links: string[];\r\n interactables: string[];\r\n capturedAt: number;\r\n version: number;\r\n}\r\n\r\ninterface InteractableCandidate {\r\n id: number;\r\n line: string;\r\n score: number;\r\n order: number;\r\n element: Element;\r\n}\r\n\r\nimport {\r\n MAX_LINKS,\r\n MAX_INTERACTABLES,\r\n MAX_HEADINGS,\r\n MAX_TEXT_SNIPPETS,\r\n MAX_CACHED_PAGES,\r\n MAX_PAGE_SCAN_ELEMENTS,\r\n} from \"./contextConfig\";\r\n\r\nexport const PAGE_CONTEXT_CACHE_VERSION = 4;\r\nexport const PAGE_CONTEXT_CACHE_KEY = \"auticbot_page_context_cache_v4\";\r\n\r\nconst NON_CONTENT_TAGS = new Set([\r\n \"script\",\r\n \"style\",\r\n \"noscript\",\r\n \"template\",\r\n \"link\",\r\n \"meta\",\r\n]);\r\n\r\n/** SVG drawing primitives — never useful as standalone interactables. */\r\nconst SVG_INTERNAL_TAGS = new Set([\r\n \"path\",\r\n \"circle\",\r\n \"line\",\r\n \"rect\",\r\n \"polygon\",\r\n \"polyline\",\r\n \"ellipse\",\r\n \"g\",\r\n \"use\",\r\n \"defs\",\r\n \"clippath\",\r\n \"mask\",\r\n \"symbol\",\r\n \"lineargradient\",\r\n \"radialgradient\",\r\n \"stop\",\r\n \"text\",\r\n \"tspan\",\r\n]);\r\n\r\nconst NATIVE_INTERACTIVE_TAGS = new Set([\r\n \"a\",\r\n \"button\",\r\n \"input\",\r\n \"textarea\",\r\n \"select\",\r\n \"summary\",\r\n \"details\",\r\n \"option\",\r\n]);\r\n\r\nconst INTERACTIVE_ROLES = new Set([\r\n \"button\",\r\n \"link\",\r\n \"tab\",\r\n \"menuitem\",\r\n \"option\",\r\n \"checkbox\",\r\n \"radio\",\r\n \"switch\",\r\n \"combobox\",\r\n \"textbox\",\r\n \"searchbox\",\r\n \"slider\",\r\n \"spinbutton\",\r\n \"treeitem\",\r\n]);\r\n\r\nconst pageContextCache = new Map<string, CachedPageContextEntry>();\r\nlet cacheHydrated = false;\r\n\r\n/**\r\n * Live element map — maps numeric IDs to DOM elements.\r\n * Rebuilt on every page context scan; NOT serialised to cache.\r\n */\r\nlet liveElementMap = new Map<number, Element>();\r\n\r\n/** Look up a DOM element by its semantic-map ID. */\r\nexport const getElementById = (id: number): Element | undefined =>\r\n liveElementMap.get(id);\r\n\r\nconst normalizeWhitespace = (value: string): string =>\r\n value.replace(/\\s+/g, \" \").trim();\r\n\r\nconst canonicalUrl = (rawUrl: string): string => {\r\n try {\r\n return new URL(rawUrl, rawUrl).href;\r\n } catch {\r\n return rawUrl;\r\n }\r\n};\r\n\r\nconst isCacheEntry = (value: unknown): value is CachedPageContextEntry => {\r\n if (typeof value !== \"object\" || value === null) {\r\n return false;\r\n }\r\n\r\n const obj = value as Record<string, unknown>;\r\n return (\r\n typeof obj.url === \"string\" &&\r\n typeof obj.summary === \"string\" &&\r\n Array.isArray(obj.links) &&\r\n Array.isArray(obj.interactables) &&\r\n typeof obj.capturedAt === \"number\" &&\r\n typeof obj.version === \"number\"\r\n );\r\n};\r\n\r\nconst parseTabIndex = (value: string | null): number | null => {\r\n if (value === null) {\r\n return null;\r\n }\r\n\r\n const parsed = Number.parseInt(value, 10);\r\n return Number.isNaN(parsed) ? null : parsed;\r\n};\r\n\r\nconst getPrimaryRole = (element: Element): string => {\r\n const rawRole = normalizeWhitespace(element.getAttribute(\"role\") || \"\")\r\n .toLowerCase()\r\n .split(\" \")[0];\r\n return rawRole || \"\";\r\n};\r\n\r\nconst hydrateCacheFromStorage = (): void => {\r\n if (cacheHydrated || typeof sessionStorage === \"undefined\") {\r\n return;\r\n }\r\n\r\n cacheHydrated = true;\r\n\r\n try {\r\n const raw = sessionStorage.getItem(PAGE_CONTEXT_CACHE_KEY);\r\n if (!raw) {\r\n return;\r\n }\r\n\r\n const parsed = JSON.parse(raw);\r\n if (!Array.isArray(parsed)) {\r\n return;\r\n }\r\n\r\n for (const value of parsed) {\r\n if (!isCacheEntry(value)) {\r\n continue;\r\n }\r\n if (value.version !== PAGE_CONTEXT_CACHE_VERSION) {\r\n continue;\r\n }\r\n pageContextCache.set(value.url, value);\r\n }\r\n if (pageContextCache.size > 0) {\r\n console.info(\r\n `[Autic] context cache restored entries=${pageContextCache.size}`,\r\n );\r\n }\r\n } catch (error) {\r\n console.warn(\"[Autic] context cache restore failed\", error);\r\n }\r\n};\r\n\r\nconst persistCacheToStorage = (): void => {\r\n if (typeof sessionStorage === \"undefined\") {\r\n return;\r\n }\r\n\r\n try {\r\n const serialized = JSON.stringify(\r\n Array.from(pageContextCache.values()).sort(\r\n (a, b) => a.capturedAt - b.capturedAt,\r\n ),\r\n );\r\n sessionStorage.setItem(PAGE_CONTEXT_CACHE_KEY, serialized);\r\n } catch (error) {\r\n console.warn(\"[Autic] context cache persist failed\", error);\r\n }\r\n};\r\n\r\nconst pruneOldestCacheEntries = (): void => {\r\n if (pageContextCache.size <= MAX_CACHED_PAGES) {\r\n return;\r\n }\r\n\r\n const sorted = Array.from(pageContextCache.values()).sort(\r\n (a, b) => a.capturedAt - b.capturedAt,\r\n );\r\n const overflow = sorted.length - MAX_CACHED_PAGES;\r\n for (let i = 0; i < overflow; i += 1) {\r\n pageContextCache.delete(sorted[i].url);\r\n }\r\n};\r\n\r\nconst buildSummaryWithHistory = (\r\n current: CachedPageContextEntry,\r\n): string => {\r\n const recentPages = Array.from(pageContextCache.values())\r\n .filter((entry) => entry.url !== current.url)\r\n .sort((a, b) => b.capturedAt - a.capturedAt)\r\n .slice(0, 3);\r\n\r\n if (recentPages.length === 0) {\r\n return current.summary;\r\n }\r\n\r\n const historySection = [\r\n \"Recent Page Memory:\",\r\n ...recentPages.map((entry) => {\r\n const compactSummary = normalizeWhitespace(entry.summary);\r\n return `- ${entry.url} :: ${compactSummary}`;\r\n }),\r\n ].join(\"\\n\");\r\n\r\n return `${current.summary}\\n\\n${historySection}`;\r\n};\r\n\r\nconst isVisible = (element: Element): boolean => {\r\n if (element.getAttribute(\"aria-hidden\") === \"true\") {\r\n return false;\r\n }\r\n\r\n if (element instanceof HTMLElement && element.hidden) {\r\n return false;\r\n }\r\n\r\n const style = window.getComputedStyle(element);\r\n if (style.display === \"none\" || style.visibility === \"hidden\") {\r\n return false;\r\n }\r\n\r\n const rect = element.getBoundingClientRect();\r\n return rect.width > 0 && rect.height > 0;\r\n};\r\n\r\n/**\r\n * Returns true if the element is nested inside an interactive parent\r\n * (e.g. a `<span>` or `<img>` inside a `<button>` or `<a>`).\r\n * This prevents listing child fragments of an already-listed interactable.\r\n */\r\nconst hasInteractiveAncestor = (element: Element): boolean => {\r\n let parent = element.parentElement;\r\n while (parent && parent !== document.body) {\r\n const parentTag = parent.tagName.toLowerCase();\r\n if (NATIVE_INTERACTIVE_TAGS.has(parentTag)) return true;\r\n const parentRole = getPrimaryRole(parent);\r\n if (INTERACTIVE_ROLES.has(parentRole)) return true;\r\n parent = parent.parentElement;\r\n }\r\n return false;\r\n};\r\n\r\nconst toAbsoluteUrl = (href: string): string => {\r\n try {\r\n return new URL(href, window.location.href).href;\r\n } catch {\r\n return href;\r\n }\r\n};\r\n\r\nconst getElementLabel = (element: Element): string => {\r\n const text = normalizeWhitespace(\r\n (element instanceof HTMLElement ? element.innerText : element.textContent) ||\r\n \"\",\r\n ).substring(0, 80);\r\n const ariaLabel = normalizeWhitespace(element.getAttribute(\"aria-label\") || \"\");\r\n const title = normalizeWhitespace(element.getAttribute(\"title\") || \"\");\r\n const placeholder = normalizeWhitespace(\r\n element.getAttribute(\"placeholder\") || \"\",\r\n );\r\n const name = normalizeWhitespace(element.getAttribute(\"name\") || \"\");\r\n const value =\r\n element instanceof HTMLInputElement ||\r\n element instanceof HTMLTextAreaElement ||\r\n element instanceof HTMLButtonElement\r\n ? normalizeWhitespace(element.value || \"\")\r\n : \"\";\r\n\r\n const label =\r\n text || ariaLabel || title || placeholder || value || name || \"\";\r\n\r\n const tag = element.tagName.toLowerCase();\r\n\r\n // Images: prefer alt text, fall back to src filename\r\n if (tag === \"img\") {\r\n const alt = normalizeWhitespace(element.getAttribute(\"alt\") || \"\");\r\n if (alt) return alt;\r\n const src = element.getAttribute(\"src\") || \"\";\r\n const filename = src.split(\"/\").pop()?.split(\"?\")[0] || \"\";\r\n return filename ? `img: ${filename}` : compactOuterHtml(element);\r\n }\r\n\r\n if (tag === \"svg\") {\r\n return ariaLabel || title || \"icon\";\r\n }\r\n\r\n if (tag === \"input\") {\r\n const inputType = element.getAttribute(\"type\") || \"text\";\r\n const currentValue = element instanceof HTMLInputElement ? element.value : \"\";\r\n const valueNote = currentValue ? ` val=\"${currentValue.substring(0, 40)}\"` : \"\";\r\n return `${inputType} ${label || \"input\"}${valueNote}`;\r\n }\r\n\r\n if (tag === \"textarea\") {\r\n const currentValue = element instanceof HTMLTextAreaElement ? element.value : \"\";\r\n const valueNote = currentValue ? ` val=\"${currentValue.substring(0, 40)}\"` : \"\";\r\n return `textarea ${label || \"textarea\"}${valueNote}`;\r\n }\r\n\r\n if (tag === \"select\") {\r\n const selectEl = element as HTMLSelectElement;\r\n const selectedText = selectEl.selectedOptions?.[0]?.textContent?.trim() || \"\";\r\n const valueNote = selectedText ? ` val=\"${selectedText}\"` : \"\";\r\n return `select ${label || \"select\"}${valueNote}`;\r\n }\r\n\r\n if (label) return label;\r\n\r\n // Fallback: compact outerHTML snippet so the agent can still identify the element\r\n return compactOuterHtml(element);\r\n};\r\n\r\n/** Return a trimmed, single-line outerHTML (opening tag + short text), max 90 chars. */\r\nconst compactOuterHtml = (element: Element): string => {\r\n const html = element.outerHTML || \"\";\r\n // Take only the opening tag + a little content\r\n const closeIdx = html.indexOf(\">\");\r\n if (closeIdx === -1) return html.substring(0, 90);\r\n const snippet = html.substring(0, Math.min(closeIdx + 30, 90)).replace(/\\s+/g, \" \").trim();\r\n return snippet || \"untitled\";\r\n};\r\n\r\n// ── Semantic element description ────────────────────────────────────\r\n\r\nconst describeElementType = (element: Element): string => {\r\n const tag = element.tagName.toLowerCase();\r\n const role = getPrimaryRole(element);\r\n\r\n // Role-based override\r\n if (role === \"button\" || tag === \"button\") return \"Button\";\r\n if (role === \"link\" || tag === \"a\") return \"Link\";\r\n if (role === \"tab\") return \"Tab\";\r\n if (role === \"menuitem\") return \"MenuItem\";\r\n if (role === \"checkbox\" || (tag === \"input\" && element.getAttribute(\"type\") === \"checkbox\")) return \"Checkbox\";\r\n if (role === \"radio\" || (tag === \"input\" && element.getAttribute(\"type\") === \"radio\")) return \"Radio\";\r\n if (role === \"switch\") return \"Switch\";\r\n if (role === \"combobox\" || tag === \"select\") return \"Select\";\r\n if (role === \"textbox\" || tag === \"textarea\") return \"TextArea\";\r\n if (role === \"searchbox\") return \"SearchBox\";\r\n if (role === \"slider\" || (tag === \"input\" && element.getAttribute(\"type\") === \"range\")) return \"Slider\";\r\n if (role === \"spinbutton\") return \"SpinButton\";\r\n if (role === \"option\" || tag === \"option\") return \"Option\";\r\n if (role === \"treeitem\") return \"TreeItem\";\r\n if (tag === \"input\") {\r\n const t = element.getAttribute(\"type\") || \"text\";\r\n return `Input[${t}]`;\r\n }\r\n if (tag === \"summary\") return \"Summary\";\r\n if (tag === \"details\") return \"Details\";\r\n if (element.getAttribute(\"contenteditable\") === \"true\") return \"Editable\";\r\n\r\n // Generic interactive\r\n return role ? `${role[0].toUpperCase()}${role.slice(1)}` : `<${tag}>`;\r\n};\r\n\r\nconst getElementState = (element: Element): string[] => {\r\n const states: string[] = [];\r\n\r\n const pressed = element.getAttribute(\"aria-pressed\");\r\n if (pressed === \"true\") states.push(\"Pressed\");\r\n else if (pressed === \"false\") states.push(\"Not pressed\");\r\n\r\n const expanded = element.getAttribute(\"aria-expanded\");\r\n if (expanded === \"true\") states.push(\"Expanded\");\r\n else if (expanded === \"false\") states.push(\"Collapsed\");\r\n\r\n const selected = element.getAttribute(\"aria-selected\");\r\n if (selected === \"true\") states.push(\"Selected\");\r\n\r\n if (element instanceof HTMLInputElement) {\r\n if (element.type === \"checkbox\" || element.type === \"radio\") {\r\n states.push(element.checked ? \"Checked\" : \"Unchecked\");\r\n }\r\n }\r\n\r\n if (element.hasAttribute(\"disabled\") || element.getAttribute(\"aria-disabled\") === \"true\") {\r\n states.push(\"Disabled\");\r\n }\r\n\r\n return states;\r\n};\r\n\r\ninterface SemanticScanResult {\r\n links: string[];\r\n interactables: string[];\r\n elementMap: Map<number, Element>;\r\n}\r\n\r\n/**\r\n * Scan the DOM and build a semantic element map.\r\n *\r\n * Every interactive element gets a numeric ID. The LLM uses these IDs\r\n * with `interact(id=N)` instead of fragile CSS selectors.\r\n */\r\nconst collectSemanticElements = (): SemanticScanResult => {\r\n const allElements = Array.from(document.querySelectorAll(\"*\"));\r\n const sampledElements = allElements.slice(0, MAX_PAGE_SCAN_ELEMENTS);\r\n\r\n const links: string[] = [];\r\n const linkSet = new Set<string>();\r\n const candidates: InteractableCandidate[] = [];\r\n const elementMap = new Map<number, Element>();\r\n let idCounter = 1;\r\n\r\n for (let order = 0; order < sampledElements.length; order += 1) {\r\n const element = sampledElements[order];\r\n const tag = element.tagName.toLowerCase();\r\n\r\n if (NON_CONTENT_TAGS.has(tag)) continue;\r\n if (SVG_INTERNAL_TAGS.has(tag)) continue;\r\n if (!isVisible(element)) continue;\r\n\r\n const role = getPrimaryRole(element);\r\n const style = window.getComputedStyle(element);\r\n const href = element.getAttribute(\"href\");\r\n const isNativeInteractive = NATIVE_INTERACTIVE_TAGS.has(tag) && (tag !== \"a\" || Boolean(href));\r\n const isRoleInteractive = INTERACTIVE_ROLES.has(role);\r\n const tabIndex = parseTabIndex(element.getAttribute(\"tabindex\"));\r\n const hasTabStop = tabIndex !== null && tabIndex >= 0;\r\n const hasPointerCursor = style.cursor === \"pointer\";\r\n const isContentEditable = element.getAttribute(\"contenteditable\") === \"true\";\r\n const isDisabled =\r\n element.hasAttribute(\"disabled\") ||\r\n element.getAttribute(\"aria-disabled\") === \"true\";\r\n\r\n // ── Links ───────────────────────────────────────────────────\r\n if (\r\n tag === \"a\" &&\r\n href &&\r\n !href.startsWith(\"#\") &&\r\n !href.startsWith(\"javascript:\")\r\n ) {\r\n const absoluteHref = toAbsoluteUrl(href);\r\n const label = getElementLabel(element) || absoluteHref;\r\n const id = idCounter++;\r\n const line = `- [${id}] ${label} -> ${absoluteHref}`;\r\n\r\n if (!linkSet.has(absoluteHref)) {\r\n linkSet.add(absoluteHref);\r\n links.push(line);\r\n elementMap.set(id, element);\r\n }\r\n }\r\n\r\n // ── Interactables ───────────────────────────────────────────\r\n const hasInteractionSignals =\r\n isNativeInteractive ||\r\n isRoleInteractive ||\r\n isContentEditable ||\r\n hasTabStop ||\r\n hasPointerCursor;\r\n\r\n if (!hasInteractionSignals || isDisabled) continue;\r\n\r\n // Skip children nested inside an already-interactive parent\r\n // (e.g. <span> or <img> inside a <button> or <a>)\r\n if (hasInteractiveAncestor(element)) continue;\r\n\r\n const id = idCounter++;\r\n elementMap.set(id, element);\r\n\r\n const elType = describeElementType(element);\r\n const label = getElementLabel(element);\r\n const stateTokens = getElementState(element);\r\n const statePart = stateTokens.length > 0 ? ` (${stateTokens.join(\", \")})` : \"\";\r\n const line = `- [${id}] ${elType}: \"${label}\"${statePart}`;\r\n\r\n const score =\r\n (isNativeInteractive ? 5 : 0) +\r\n (isRoleInteractive ? 4 : 0) +\r\n (hasTabStop ? 2 : 0) +\r\n (hasPointerCursor ? 2 : 0) +\r\n (isContentEditable ? 2 : 0);\r\n\r\n candidates.push({ id, line, score, order, element });\r\n }\r\n\r\n const interactables = candidates\r\n .sort((a, b) => b.score - a.score || a.order - b.order)\r\n .slice(0, MAX_INTERACTABLES)\r\n .map((c) => c.line);\r\n\r\n return {\r\n links: links.slice(0, MAX_LINKS),\r\n interactables,\r\n elementMap,\r\n };\r\n};\r\n\r\nconst collectTextSnippets = (): string[] => {\r\n const root =\r\n document.querySelector(\"main, article, [role='main']\") ?? document.body;\r\n const snippets: string[] = [];\r\n const seen = new Set<string>();\r\n\r\n const candidates = Array.from(root.querySelectorAll(\"p, li, h1, h2, h3\"));\r\n for (const node of candidates) {\r\n if (!isVisible(node)) continue;\r\n\r\n const text = normalizeWhitespace(node.textContent || \"\");\r\n if (!text || text.length < 20) continue;\r\n if (seen.has(text)) continue;\r\n\r\n seen.add(text);\r\n snippets.push(`- ${text}`);\r\n if (snippets.length >= MAX_TEXT_SNIPPETS) break;\r\n }\r\n\r\n return snippets;\r\n};\r\n\r\nconst formatSection = (title: string, lines: string[]): string => {\r\n if (lines.length === 0) return `${title}:\\n- none`;\r\n return `${title}:\\n${lines.join(\"\\n\")}`;\r\n};\r\n\r\nexport const buildPageContextSummary = (\r\n url: string,\r\n title: string,\r\n lang: string,\r\n headings: string[],\r\n links: string[],\r\n interactables: string[],\r\n textSnippets: string[],\r\n): string => {\r\n const sections = [\r\n formatSection(\"Page\", [\r\n `- URL: ${url || \"unknown\"}`,\r\n `- Title: ${title || \"unknown\"}`,\r\n `- Lang: ${lang || \"unknown\"}`,\r\n ]),\r\n formatSection(\"Headings\", headings),\r\n formatSection(\"Content Snippets\", textSnippets),\r\n formatSection(\"Links\", links),\r\n formatSection(\"Interactive Elements\", interactables),\r\n ];\r\n\r\n return sections.join(\"\\n\\n\");\r\n};\r\n\r\nexport const clearPageContextCache = (): void => {\r\n pageContextCache.clear();\r\n cacheHydrated = false;\r\n if (typeof sessionStorage !== \"undefined\") {\r\n sessionStorage.removeItem(PAGE_CONTEXT_CACHE_KEY);\r\n }\r\n};\r\n\r\nexport const getCachedPageContexts = (): CachedPageContextEntry[] => {\r\n hydrateCacheFromStorage();\r\n return Array.from(pageContextCache.values()).sort(\r\n (a, b) => b.capturedAt - a.capturedAt,\r\n );\r\n};\r\n\r\nexport const invalidateCurrentPageContext = (): void => {\r\n if (typeof window === \"undefined\") return;\r\n const url = canonicalUrl(window.location.href);\r\n pageContextCache.delete(url);\r\n persistCacheToStorage();\r\n};\r\n\r\nexport const getPageContext = (forceRefresh: boolean = false): PageContext => {\r\n if (typeof window === \"undefined\" || typeof document === \"undefined\") {\r\n return {\r\n links: [],\r\n interactables: [],\r\n summary: \"\",\r\n elementMap: new Map(),\r\n };\r\n }\r\n\r\n hydrateCacheFromStorage();\r\n const url = canonicalUrl(window.location.href);\r\n\r\n // Always rebuild the live element map (it holds DOM references)\r\n const scan = collectSemanticElements();\r\n liveElementMap = scan.elementMap;\r\n\r\n if (!forceRefresh) {\r\n const cached = pageContextCache.get(url);\r\n if (cached) {\r\n console.info(`[Autic] context cache hit url=${url}`);\r\n return {\r\n links: cached.links,\r\n interactables: cached.interactables,\r\n summary: buildSummaryWithHistory(cached),\r\n elementMap: liveElementMap,\r\n };\r\n }\r\n }\r\n\r\n console.info(`[Autic] context cache miss url=${url}`);\r\n\r\n const headings = Array.from(document.querySelectorAll(\"h1, h2, h3\"))\r\n .filter((element) => isVisible(element))\r\n .map((element) =>\r\n `- ${normalizeWhitespace(element.textContent || \"\")}`,\r\n )\r\n .filter((line) => line !== \"- \")\r\n .slice(0, MAX_HEADINGS);\r\n\r\n const summary = buildPageContextSummary(\r\n url,\r\n document.title,\r\n document.documentElement.lang,\r\n headings,\r\n scan.links,\r\n scan.interactables,\r\n collectTextSnippets(),\r\n );\r\n\r\n const entry: CachedPageContextEntry = {\r\n url,\r\n summary,\r\n links: scan.links,\r\n interactables: scan.interactables,\r\n capturedAt: Date.now(),\r\n version: PAGE_CONTEXT_CACHE_VERSION,\r\n };\r\n\r\n pageContextCache.set(url, entry);\r\n pruneOldestCacheEntries();\r\n persistCacheToStorage();\r\n console.info(\r\n `[Autic] context cache stored url=${url} size=${pageContextCache.size}`,\r\n );\r\n\r\n return {\r\n links: entry.links,\r\n interactables: entry.interactables,\r\n summary: buildSummaryWithHistory(entry),\r\n elementMap: liveElementMap,\r\n };\r\n};\r\n","/**\r\n * Tunable parameters for page context collection.\r\n *\r\n * Adjust these values to control how much information the agent receives\r\n * about the current page. Lower values reduce token usage (and latency);\r\n * higher values give the LLM more detail to work with.\r\n */\r\n\r\n/** Maximum number of links to include in the context. */\r\nexport const MAX_LINKS = 120;\r\n\r\n/** Maximum number of interactable elements to include. */\r\nexport const MAX_INTERACTABLES = 2000;\r\n\r\n/** Maximum number of headings (h1-h3) to include. */\r\nexport const MAX_HEADINGS = 100;\r\n\r\n/** Maximum number of main-content text snippets. */\r\nexport const MAX_TEXT_SNIPPETS = 30;\r\n\r\n/** Maximum number of pages kept in the in-memory context cache. */\r\nexport const MAX_CACHED_PAGES = 25;\r\n\r\n/** Maximum number of DOM elements scanned per page. */\r\nexport const MAX_PAGE_SCAN_ELEMENTS = 10000;\r\n","import { getPageContext, getElementById, invalidateCurrentPageContext } from \"./context\";\r\nimport { COLORS } from \"../styles/constants\";\r\n\r\nconst AGENT_CURSOR_ID = \"auticbot-agent-cursor\";\r\nexport const CURSOR_MOVE_DURATION_MS = 900;\r\nexport const SCROLL_DURATION_MS = 900;\r\nconst CURSOR_EASING = \"cubic-bezier(0.4, 0, 0.2, 1)\";\r\nconst CURSOR_HOVER_RADIUS_PX = 14;\r\nconst CURSOR_DIAMETER_PX = 25;\r\n\r\n// ── Pending Agent Resume State (survives page reloads) ──────────────\r\n\r\nconst RESUME_STORAGE_KEY = \"bulut_agent_resume\";\r\nconst RESUME_TTL_MS = 5 * 60_000; // 5 minutes (matches chat history TTL)\r\n\r\nexport interface PendingAgentResume {\r\n sessionId: string;\r\n projectId: string;\r\n model: string;\r\n voice: string;\r\n accessibilityMode: boolean;\r\n pendingToolCalls: Array<{\r\n call_id: string;\r\n tool: string;\r\n args: Record<string, unknown>;\r\n }>;\r\n completedResults: Array<{ call_id: string; result: string }>;\r\n accumulatedDelta?: string;\r\n savedAt: number;\r\n}\r\n\r\nexport const savePendingAgentResume = (\r\n state: Omit<PendingAgentResume, \"savedAt\">,\r\n): void => {\r\n if (typeof localStorage === \"undefined\") return;\r\n try {\r\n localStorage.setItem(\r\n RESUME_STORAGE_KEY,\r\n JSON.stringify({ ...state, savedAt: Date.now() }),\r\n );\r\n } catch {\r\n // localStorage may be full or blocked\r\n }\r\n};\r\n\r\nexport const getPendingAgentResume = (): PendingAgentResume | null => {\r\n if (typeof localStorage === \"undefined\") return null;\r\n const raw = localStorage.getItem(RESUME_STORAGE_KEY);\r\n if (!raw) return null;\r\n try {\r\n const parsed = JSON.parse(raw) as PendingAgentResume;\r\n if (Date.now() - parsed.savedAt > RESUME_TTL_MS) {\r\n clearPendingAgentResume();\r\n return null;\r\n }\r\n return parsed;\r\n } catch {\r\n clearPendingAgentResume();\r\n return null;\r\n }\r\n};\r\n\r\nexport const clearPendingAgentResume = (): void => {\r\n if (typeof localStorage === \"undefined\") return;\r\n localStorage.removeItem(RESUME_STORAGE_KEY);\r\n};\r\n\r\ntype InteractAction = \"move\" | \"click\" | \"type\" | \"submit\";\r\n\r\ninterface InteractToolCall {\r\n tool: \"interact\";\r\n action: InteractAction;\r\n id?: number;\r\n selector?: string;\r\n text?: string;\r\n x?: number;\r\n y?: number;\r\n}\r\n\r\ninterface NavigateToolCall {\r\n tool: \"navigate\";\r\n url: string;\r\n}\r\n\r\ninterface GetPageContextToolCall {\r\n tool: \"getPageContext\";\r\n}\r\n\r\ninterface ScrollToolCall {\r\n tool: \"scroll\";\r\n id?: number;\r\n selector?: string;\r\n}\r\n\r\nexport type AgentToolCall =\r\n | InteractToolCall\r\n | NavigateToolCall\r\n | GetPageContextToolCall\r\n | ScrollToolCall;\r\n\r\nexport interface ParsedAgentResponse {\r\n reply: string;\r\n toolCalls: AgentToolCall[];\r\n}\r\n\r\ninterface JsonObject {\r\n [key: string]: unknown;\r\n}\r\n\r\ninterface ResolvedTarget {\r\n element?: HTMLElement;\r\n x: number;\r\n y: number;\r\n}\r\n\r\nconst isObject = (value: unknown): value is JsonObject =>\r\n typeof value === \"object\" && value !== null && !Array.isArray(value);\r\n\r\nconst asString = (value: unknown): string | undefined =>\r\n typeof value === \"string\" && value.trim() ? value.trim() : undefined;\r\n\r\nconst asNumber = (value: unknown): number | undefined =>\r\n typeof value === \"number\" && Number.isFinite(value) ? value : undefined;\r\n\r\nconst extractJsonCandidate = (raw: string): string => {\r\n const trimmed = raw.trim();\r\n const fencedMatch = trimmed.match(/```(?:json)?\\s*([\\s\\S]*?)\\s*```/i);\r\n if (fencedMatch?.[1]) {\r\n return fencedMatch[1].trim();\r\n }\r\n return trimmed;\r\n};\r\n\r\nconst extractFirstJsonObject = (input: string): string | null => {\r\n const start = input.indexOf(\"{\");\r\n if (start < 0) {\r\n return null;\r\n }\r\n\r\n let depth = 0;\r\n let inString = false;\r\n let isEscaped = false;\r\n\r\n for (let i = start; i < input.length; i += 1) {\r\n const char = input[i];\r\n\r\n if (inString) {\r\n if (isEscaped) {\r\n isEscaped = false;\r\n } else if (char === \"\\\\\") {\r\n isEscaped = true;\r\n } else if (char === '\"') {\r\n inString = false;\r\n }\r\n continue;\r\n }\r\n\r\n if (char === '\"') {\r\n inString = true;\r\n continue;\r\n }\r\n\r\n if (char === \"{\") {\r\n depth += 1;\r\n continue;\r\n }\r\n\r\n if (char === \"}\") {\r\n depth -= 1;\r\n if (depth === 0) {\r\n return input.slice(start, i + 1);\r\n }\r\n }\r\n }\r\n\r\n return null;\r\n};\r\n\r\nconst parseJsonFromRaw = (raw: string): unknown => {\r\n const candidate = extractJsonCandidate(raw);\r\n try {\r\n return JSON.parse(candidate);\r\n } catch {\r\n const objectCandidate = extractFirstJsonObject(candidate);\r\n if (!objectCandidate) {\r\n return null;\r\n }\r\n try {\r\n return JSON.parse(objectCandidate);\r\n } catch {\r\n return null;\r\n }\r\n }\r\n};\r\n\r\nconst sanitizeToolCalls = (value: unknown): AgentToolCall[] => {\r\n if (!Array.isArray(value)) {\r\n return [];\r\n }\r\n\r\n const toolCalls: AgentToolCall[] = [];\r\n\r\n for (const item of value) {\r\n if (!isObject(item)) {\r\n continue;\r\n }\r\n\r\n if (item.tool === \"interact\") {\r\n const action = asString(item.action) as InteractAction | undefined;\r\n if (!action || ![\"move\", \"click\", \"type\", \"submit\"].includes(action)) {\r\n continue;\r\n }\r\n\r\n toolCalls.push({\r\n tool: \"interact\",\r\n action,\r\n id: asNumber(item.id),\r\n selector: asString(item.selector),\r\n text: typeof item.text === \"string\" ? item.text : undefined,\r\n x: asNumber(item.x),\r\n y: asNumber(item.y),\r\n });\r\n continue;\r\n }\r\n\r\n if (item.tool === \"navigate\") {\r\n const url = asString(item.url);\r\n if (!url) {\r\n continue;\r\n }\r\n\r\n toolCalls.push({\r\n tool: \"navigate\",\r\n url,\r\n });\r\n continue;\r\n }\r\n\r\n if (item.tool === \"getPageContext\") {\r\n toolCalls.push({\r\n tool: \"getPageContext\",\r\n });\r\n continue;\r\n }\r\n\r\n if (item.tool === \"scroll\") {\r\n const id = asNumber(item.id);\r\n const selector = asString(item.selector);\r\n if (!id && !selector) {\r\n continue;\r\n }\r\n\r\n toolCalls.push({\r\n tool: \"scroll\",\r\n id,\r\n selector,\r\n });\r\n }\r\n }\r\n\r\n return toolCalls;\r\n};\r\n\r\nexport const parseAgentResponse = (raw: string): ParsedAgentResponse => {\r\n const parsed = parseJsonFromRaw(raw);\r\n if (!isObject(parsed)) {\r\n return {\r\n reply: raw.trim(),\r\n toolCalls: [],\r\n };\r\n }\r\n\r\n const reply = asString(parsed.reply) || \"\";\r\n const toolCalls = sanitizeToolCalls(parsed.tool_calls ?? parsed.toolCalls);\r\n\r\n return {\r\n reply,\r\n toolCalls,\r\n };\r\n};\r\n\r\nexport const clamp = (value: number, min: number, max: number): number =>\r\n Math.min(max, Math.max(min, value));\r\n\r\nexport const easeInOutCubic = (progress: number): number => {\r\n if (progress < 0.5) {\r\n return 4 * progress * progress * progress;\r\n }\r\n return 1 - Math.pow(-2 * progress + 2, 3) / 2;\r\n};\r\n\r\nexport const easeInOutSine = (progress: number): number =>\r\n -(Math.cos(Math.PI * progress) - 1) / 2;\r\n\r\nexport const isRectOutsideViewport = (\r\n rect: Pick<DOMRect, \"top\" | \"bottom\">,\r\n viewportHeight: number,\r\n): boolean => rect.top < 0 || rect.bottom > viewportHeight;\r\n\r\nexport const computeCenteredScrollTop = (\r\n currentScrollY: number,\r\n rectTop: number,\r\n rectHeight: number,\r\n viewportHeight: number,\r\n maxScrollTop: number,\r\n): number => {\r\n const desired =\r\n currentScrollY + rectTop - (viewportHeight / 2 - rectHeight / 2);\r\n return clamp(desired, 0, Math.max(0, maxScrollTop));\r\n};\r\n\r\nexport const animateWindowScrollTo = async (\r\n targetY: number,\r\n durationMs: number = SCROLL_DURATION_MS,\r\n): Promise<void> => {\r\n if (typeof window === \"undefined\") {\r\n return;\r\n }\r\n\r\n const startY = window.scrollY;\r\n const delta = targetY - startY;\r\n if (Math.abs(delta) < 1) {\r\n return;\r\n }\r\n\r\n await new Promise<void>((resolve) => {\r\n const raf =\r\n window.requestAnimationFrame ||\r\n ((callback: FrameRequestCallback) => window.setTimeout(() => callback(performance.now()), 16));\r\n\r\n const startTime = performance.now();\r\n\r\n const step = (now: number) => {\r\n const elapsed = now - startTime;\r\n const progress = clamp(elapsed / durationMs, 0, 1);\r\n const eased = easeInOutSine(progress);\r\n window.scrollTo(0, startY + delta * eased);\r\n\r\n if (progress < 1) {\r\n raf(step);\r\n } else {\r\n resolve();\r\n }\r\n };\r\n\r\n raf(step);\r\n });\r\n};\r\n\r\nconst setCursorPosition = (cursor: HTMLElement, x: number, y: number) => {\r\n cursor.style.left = `${x}px`;\r\n cursor.style.top = `${y}px`;\r\n};\r\n\r\nconst getCursorPosition = (cursor: HTMLElement): { x: number; y: number } => ({\r\n x: Number.parseFloat(cursor.style.left) || 0,\r\n y: Number.parseFloat(cursor.style.top) || 0,\r\n});\r\n\r\nconst setCursorVisibility = (cursor: HTMLElement, visible: boolean) => {\r\n cursor.style.opacity = visible ? \"1\" : \"0\";\r\n};\r\n\r\nconst isVisibleElement = (element: HTMLElement): boolean => {\r\n const style = window.getComputedStyle(element);\r\n return style.display !== \"none\" && style.visibility !== \"hidden\" && style.opacity !== \"0\";\r\n};\r\n\r\nconst getBulutShadowRoots = (): ShadowRoot[] => {\r\n const roots: ShadowRoot[] = [];\r\n\r\n const defaultHost = document.getElementById(\"bulut-container\");\r\n if (defaultHost?.shadowRoot) {\r\n roots.push(defaultHost.shadowRoot);\r\n }\r\n\r\n const allElements = document.querySelectorAll<HTMLElement>(\"*\");\r\n for (const el of allElements) {\r\n if (!el.shadowRoot) {\r\n continue;\r\n }\r\n if (!roots.includes(el.shadowRoot)) {\r\n roots.push(el.shadowRoot);\r\n }\r\n }\r\n\r\n return roots;\r\n};\r\n\r\nconst findAgentUiAnchorElement = (): HTMLElement | null => {\r\n const roots = getBulutShadowRoots();\r\n\r\n for (const root of roots) {\r\n const panel = root.querySelector<HTMLElement>(\".bulut-chat-window\");\r\n if (panel && isVisibleElement(panel)) {\r\n return panel;\r\n }\r\n }\r\n\r\n for (const root of roots) {\r\n const button = root.querySelector<HTMLElement>(\".bulut-fab-container\");\r\n if (button && isVisibleElement(button)) {\r\n return button;\r\n }\r\n }\r\n\r\n return null;\r\n};\r\n\r\nconst getAgentWindowTopLeft = (): { x: number; y: number } => {\r\n const anchor = findAgentUiAnchorElement();\r\n if (!anchor) {\r\n return {\r\n x: CURSOR_DIAMETER_PX / 2,\r\n y: CURSOR_DIAMETER_PX / 2,\r\n };\r\n }\r\n\r\n const rect = anchor.getBoundingClientRect();\r\n return {\r\n x: rect.left + window.scrollX + CURSOR_DIAMETER_PX / 2,\r\n y: rect.top + window.scrollY + CURSOR_DIAMETER_PX / 2,\r\n };\r\n};\r\n\r\nexport const hideAgentCursor = (): void => {\r\n if (typeof document === \"undefined\" || typeof window === \"undefined\") {\r\n return;\r\n }\r\n\r\n const cursor = document.getElementById(AGENT_CURSOR_ID);\r\n if (!(cursor instanceof HTMLElement)) {\r\n return;\r\n }\r\n\r\n setCursorVisibility(cursor, false);\r\n};\r\n\r\nlet cursorHoverTrackingInitialized = false;\r\nconst initializeCursorHoverTracking = () => {\r\n if (cursorHoverTrackingInitialized) {\r\n return;\r\n }\r\n cursorHoverTrackingInitialized = true;\r\n\r\n document.addEventListener(\"mousemove\", (event) => {\r\n const cursor = document.getElementById(AGENT_CURSOR_ID);\r\n if (!(cursor instanceof HTMLElement)) {\r\n return;\r\n }\r\n\r\n if (cursor.style.opacity !== \"1\") {\r\n return;\r\n }\r\n\r\n const { x, y } = getCursorPosition(cursor);\r\n const pointerX = event.pageX;\r\n const pointerY = event.pageY;\r\n const distance = Math.hypot(pointerX - x, pointerY - y);\r\n\r\n if (distance <= CURSOR_HOVER_RADIUS_PX) {\r\n setCursorVisibility(cursor, false);\r\n }\r\n });\r\n};\r\n\r\nconst ensureCursor = (): HTMLElement => {\r\n const existing = document.getElementById(AGENT_CURSOR_ID);\r\n if (existing) {\r\n // Keep cursor color in sync with the current theme\r\n existing.style.background = COLORS.primary;\r\n initializeCursorHoverTracking();\r\n return existing as HTMLElement;\r\n }\r\n\r\n const cursor = document.createElement(\"div\");\r\n cursor.id = AGENT_CURSOR_ID;\r\n cursor.style.position = \"absolute\";\r\n const startPosition = getAgentWindowTopLeft();\r\n cursor.style.left = `${startPosition.x}px`;\r\n cursor.style.top = `${startPosition.y}px`;\r\n cursor.style.opacity = \"0\";\r\n const width = CURSOR_DIAMETER_PX;\r\n cursor.style.width = `${width}px`;\r\n cursor.style.height = `${width}px`;\r\n cursor.style.borderRadius = \"50%\";\r\n const baseColor = COLORS.primary;\r\n cursor.style.background = baseColor;\r\n const border = 25 * 16 / 100;\r\n cursor.style.border = `${border}px solid #ffffff`;\r\n cursor.style.boxShadow = \"0px 0px 10px rgba(0, 11, 26, 0.5)\";\r\n cursor.style.boxSizing = \"border-box\";\r\n cursor.style.zIndex = \"2147483647\";\r\n cursor.style.pointerEvents = \"none\";\r\n cursor.style.transform = \"translate(-50%, -50%)\";\r\n cursor.style.transition = `left ${CURSOR_MOVE_DURATION_MS}ms ${CURSOR_EASING}, top ${CURSOR_MOVE_DURATION_MS}ms ${CURSOR_EASING}, opacity 150ms ease-out`;\r\n document.body.appendChild(cursor);\r\n initializeCursorHoverTracking();\r\n console.info(`[Autic] cursor created color=${baseColor} duration=${CURSOR_MOVE_DURATION_MS}ms`);\r\n return cursor;\r\n};\r\n\r\nconst waitForNextAnimationFrame = async (): Promise<void> => {\r\n const raf =\r\n window.requestAnimationFrame ||\r\n ((callback: FrameRequestCallback) => window.setTimeout(() => callback(performance.now()), 16));\r\n await new Promise<void>((resolve) => {\r\n raf(() => resolve());\r\n });\r\n};\r\n\r\nconst moveCursor = async (x: number, y: number) => {\r\n const cursor = ensureCursor();\r\n if (cursor.dataset.transitionReady !== \"true\") {\r\n cursor.dataset.transitionReady = \"true\";\r\n await waitForNextAnimationFrame();\r\n }\r\n\r\n const isAlreadyVisible = cursor.style.opacity === \"1\";\r\n\r\n if (!isAlreadyVisible) {\r\n // First appearance: start from agent window top-left\r\n const startPosition = getAgentWindowTopLeft();\r\n setCursorVisibility(cursor, true);\r\n setCursorPosition(cursor, startPosition.x, startPosition.y);\r\n await new Promise((resolve) => setTimeout(resolve, CURSOR_MOVE_DURATION_MS));\r\n }\r\n\r\n // Animate from current position via CSS transition\r\n setCursorVisibility(cursor, true);\r\n setCursorPosition(cursor, x, y);\r\n await new Promise((resolve) => setTimeout(resolve, CURSOR_MOVE_DURATION_MS));\r\n};\r\n\r\nconst getElementCenter = (element: HTMLElement): { x: number; y: number } => {\r\n const rect = element.getBoundingClientRect();\r\n return {\r\n x: rect.left + window.scrollX + rect.width / 2,\r\n y: rect.top + window.scrollY + rect.height / 2,\r\n };\r\n};\r\n\r\nconst CONTAINS_SELECTOR_PATTERN = /^(.*?):contains\\((['\"])(.*?)\\2\\)\\s*$/;\r\n\r\nconst findElementBySelector = (selector: string): Element | null => {\r\n try {\r\n return document.querySelector(selector);\r\n } catch (error) {\r\n const containsMatch = selector.match(CONTAINS_SELECTOR_PATTERN);\r\n if (!containsMatch) {\r\n console.warn(`AuticBot selector invalid: ${selector}`, error);\r\n return null;\r\n }\r\n\r\n const baseSelector = containsMatch[1]?.trim() || \"*\";\r\n const expectedText = containsMatch[3]?.trim() || \"\";\r\n if (!expectedText) {\r\n console.warn(`AuticBot selector contains empty text: ${selector}`);\r\n return null;\r\n }\r\n\r\n try {\r\n const candidates = document.querySelectorAll(baseSelector);\r\n for (const candidate of candidates) {\r\n if (candidate.textContent?.includes(expectedText)) {\r\n return candidate;\r\n }\r\n }\r\n return null;\r\n } catch (fallbackError) {\r\n console.warn(`AuticBot selector fallback invalid: ${selector}`, fallbackError);\r\n return null;\r\n }\r\n }\r\n};\r\n\r\nconst resolveTarget = (call: InteractToolCall): ResolvedTarget | null => {\r\n // 1. Try resolving by semantic ID from the element map\r\n if (typeof call.id === \"number\") {\r\n const mapped = getElementById(call.id);\r\n if (mapped instanceof HTMLElement) {\r\n const center = getElementCenter(mapped);\r\n return { element: mapped, x: center.x, y: center.y };\r\n }\r\n console.warn(`AuticBot interact: element id=${call.id} not found in map`);\r\n }\r\n\r\n // 2. Fallback to CSS selector\r\n if (call.selector) {\r\n const selected = findElementBySelector(call.selector);\r\n\r\n if (selected instanceof HTMLElement) {\r\n const center = getElementCenter(selected);\r\n return {\r\n element: selected,\r\n x: center.x,\r\n y: center.y,\r\n };\r\n }\r\n console.warn(`AuticBot interact: selector not found: ${call.selector}`);\r\n }\r\n\r\n if (typeof call.x === \"number\" && typeof call.y === \"number\") {\r\n return {\r\n x: call.x,\r\n y: call.y,\r\n };\r\n }\r\n\r\n console.warn(\"AuticBot interact: missing target id, selector or coordinates.\", call);\r\n return null;\r\n};\r\n\r\nconst dispatchMouseEvent = (\r\n element: HTMLElement,\r\n type: string,\r\n x: number,\r\n y: number,\r\n) => {\r\n element.dispatchEvent(\r\n new MouseEvent(type, {\r\n bubbles: true,\r\n cancelable: true,\r\n view: window,\r\n clientX: x - window.scrollX,\r\n clientY: y - window.scrollY,\r\n }),\r\n );\r\n};\r\n\r\nconst setNativeInputLikeValue = (\r\n element: HTMLInputElement | HTMLTextAreaElement,\r\n text: string,\r\n) => {\r\n const prototype =\r\n element instanceof HTMLTextAreaElement\r\n ? HTMLTextAreaElement.prototype\r\n : HTMLInputElement.prototype;\r\n const descriptor = Object.getOwnPropertyDescriptor(prototype, \"value\");\r\n if (descriptor?.set) {\r\n descriptor.set.call(element, text);\r\n } else {\r\n element.value = text;\r\n }\r\n\r\n // Keep both current and default values aligned so client re-focus\r\n // does not appear to \"erase\" tool-filled form fields.\r\n element.defaultValue = text;\r\n element.setAttribute(\"value\", text);\r\n};\r\n\r\nconst typeIntoElement = (element: HTMLElement, text: string) => {\r\n if (element instanceof HTMLInputElement || element instanceof HTMLTextAreaElement) {\r\n element.focus();\r\n setNativeInputLikeValue(element, text);\r\n element.dispatchEvent(new Event(\"input\", { bubbles: true }));\r\n element.dispatchEvent(new Event(\"change\", { bubbles: true }));\r\n return;\r\n }\r\n\r\n if (element.isContentEditable) {\r\n element.focus();\r\n element.textContent = text;\r\n element.dispatchEvent(new Event(\"input\", { bubbles: true }));\r\n return;\r\n }\r\n\r\n console.warn(\r\n \"AuticBot interact: type action requires input, textarea, or contenteditable target.\",\r\n );\r\n};\r\n\r\nconst submitElement = (element: HTMLElement) => {\r\n if (element.tagName === \"FORM\") {\r\n (element as HTMLFormElement).requestSubmit();\r\n return;\r\n }\r\n\r\n if (element.tagName === \"BUTTON\" && (element as HTMLButtonElement).form) {\r\n (element as HTMLButtonElement).form?.requestSubmit();\r\n return;\r\n }\r\n\r\n const parentForm = element.closest(\"form\");\r\n if (parentForm) {\r\n parentForm.requestSubmit();\r\n return;\r\n }\r\n\r\n console.warn(\"AuticBot interact: submit action requires a form target.\");\r\n};\r\n\r\nconst slowScrollElementIntoView = async (element: HTMLElement): Promise<void> => {\r\n await slowScrollElementIntoViewWithMode(element, false);\r\n};\r\n\r\nconst slowScrollElementIntoViewWithMode = async (\r\n element: HTMLElement,\r\n forceCenter: boolean,\r\n): Promise<void> => {\r\n const rect = element.getBoundingClientRect();\r\n const viewportHeight = window.innerHeight;\r\n\r\n if (!forceCenter && !isRectOutsideViewport(rect, viewportHeight)) {\r\n return;\r\n }\r\n\r\n const maxScrollTop = Math.max(\r\n 0,\r\n Math.max(document.body.scrollHeight, document.documentElement.scrollHeight) - viewportHeight,\r\n );\r\n const targetY = computeCenteredScrollTop(\r\n window.scrollY,\r\n rect.top,\r\n rect.height,\r\n viewportHeight,\r\n maxScrollTop,\r\n );\r\n\r\n await animateWindowScrollTo(targetY, SCROLL_DURATION_MS);\r\n};\r\n\r\nconst executeScroll = async (call: ScrollToolCall) => {\r\n const selected =\r\n (typeof call.id === \"number\" ? getElementById(call.id) : null) ??\r\n (call.selector ? findElementBySelector(call.selector) : null);\r\n\r\n if (!(selected instanceof HTMLElement)) {\r\n console.warn(`AuticBot scroll: target not found (id=${call.id}, selector=${call.selector})`);\r\n return;\r\n }\r\n\r\n await slowScrollElementIntoViewWithMode(selected, true);\r\n const center = getElementCenter(selected);\r\n await moveCursor(center.x, center.y);\r\n};\r\n\r\nconst executeInteract = async (call: InteractToolCall) => {\r\n const target = resolveTarget(call);\r\n if (!target) {\r\n return;\r\n }\r\n\r\n if (call.action === \"click\" && target.element) {\r\n await slowScrollElementIntoView(target.element);\r\n const center = getElementCenter(target.element);\r\n target.x = center.x;\r\n target.y = center.y;\r\n }\r\n\r\n await moveCursor(target.x, target.y);\r\n\r\n if (call.action === \"move\") {\r\n return;\r\n }\r\n\r\n if (!target.element) {\r\n console.warn(\"AuticBot interact: target element not available for action.\", call.action);\r\n return;\r\n }\r\n\r\n if (call.action === \"click\") {\r\n dispatchMouseEvent(target.element, \"pointerdown\", target.x, target.y);\r\n dispatchMouseEvent(target.element, \"mousedown\", target.x, target.y);\r\n dispatchMouseEvent(target.element, \"pointerup\", target.x, target.y);\r\n dispatchMouseEvent(target.element, \"mouseup\", target.x, target.y);\r\n target.element.click();\r\n // Invalidate context cache — page state likely changed after click\r\n invalidateCurrentPageContext();\r\n return;\r\n }\r\n\r\n if (call.action === \"type\") {\r\n typeIntoElement(target.element, call.text ?? \"\");\r\n // Invalidate context cache — form state changed\r\n invalidateCurrentPageContext();\r\n return;\r\n }\r\n\r\n submitElement(target.element);\r\n // Invalidate context cache — form submission may change page\r\n invalidateCurrentPageContext();\r\n};\r\n\r\nconst isSamePageNavigation = (targetUrl: string): boolean => {\r\n try {\r\n const current = new URL(window.location.href);\r\n const target = new URL(targetUrl);\r\n return current.origin === target.origin && current.pathname === target.pathname;\r\n } catch {\r\n return false;\r\n }\r\n};\r\n\r\n/**\r\n * Find the best matching link element for a target URL.\r\n * Supports exact href match, partial path/query/hash match,\r\n * and text-content match for framework <Link> components.\r\n */\r\nconst findMatchingLinkForTarget = (targetUrl: string): HTMLElement | null => {\r\n let parsedTarget: URL | null = null;\r\n try {\r\n parsedTarget = new URL(targetUrl, window.location.href);\r\n } catch {\r\n // will fall through to text-based matching\r\n }\r\n\r\n const allLinks = Array.from(\r\n document.querySelectorAll('a[href], [role=\"link\"][href], [data-href]'),\r\n ) as HTMLElement[];\r\n\r\n // 1. Exact href match\r\n for (const el of allLinks) {\r\n if (el instanceof HTMLAnchorElement && el.href === parsedTarget?.href) {\r\n return el;\r\n }\r\n }\r\n\r\n if (parsedTarget) {\r\n // 2. Match by pathname + search + hash (ignoring origin)\r\n for (const el of allLinks) {\r\n if (!(el instanceof HTMLAnchorElement)) continue;\r\n try {\r\n const elUrl = new URL(el.href, window.location.href);\r\n if (\r\n elUrl.pathname === parsedTarget.pathname &&\r\n elUrl.search === parsedTarget.search &&\r\n elUrl.hash === parsedTarget.hash\r\n ) {\r\n return el;\r\n }\r\n } catch {\r\n continue;\r\n }\r\n }\r\n\r\n // 3. Match by pathname only (query/hash may differ)\r\n for (const el of allLinks) {\r\n if (!(el instanceof HTMLAnchorElement)) continue;\r\n try {\r\n const elUrl = new URL(el.href, window.location.href);\r\n if (elUrl.pathname === parsedTarget.pathname) {\r\n return el;\r\n }\r\n } catch {\r\n continue;\r\n }\r\n }\r\n\r\n // 4. Partial href attribute match (covers relative paths, query strings)\r\n const rawUrl = targetUrl.replace(/^\\//, \"\");\r\n for (const el of allLinks) {\r\n const href = el.getAttribute(\"href\") || el.getAttribute(\"data-href\") || \"\";\r\n if (href && (href === targetUrl || href === rawUrl || href === `/${rawUrl}`)) {\r\n return el;\r\n }\r\n }\r\n }\r\n\r\n // 5. Text-content match (for framework <Link> or <button> navigations)\r\n const urlSegments = targetUrl\r\n .replace(/^https?:\\/\\/[^/]+/, \"\")\r\n .replace(/[?#].*$/, \"\")\r\n .split(\"/\")\r\n .filter(Boolean);\r\n const lastSegment = urlSegments[urlSegments.length - 1] || \"\";\r\n\r\n if (lastSegment) {\r\n // Also search query param values (e.g., ?tab=interact → \"interact\")\r\n let searchTerms = [lastSegment];\r\n if (parsedTarget) {\r\n for (const [, value] of parsedTarget.searchParams.entries()) {\r\n if (value) searchTerms.push(value);\r\n }\r\n if (parsedTarget.hash) {\r\n searchTerms.push(parsedTarget.hash.replace(/^#/, \"\"));\r\n }\r\n }\r\n searchTerms = searchTerms.map((t) => t.toLowerCase());\r\n\r\n // Look across all clickable elements\r\n const clickables = Array.from(\r\n document.querySelectorAll(\r\n 'a, button, [role=\"link\"], [role=\"tab\"], [role=\"button\"], [data-tab], [onclick]',\r\n ),\r\n ) as HTMLElement[];\r\n\r\n for (const el of clickables) {\r\n const text = (el.textContent || \"\").trim().toLowerCase();\r\n const ariaLabel = (el.getAttribute(\"aria-label\") || \"\").toLowerCase();\r\n const dataTab = (el.getAttribute(\"data-tab\") || \"\").toLowerCase();\r\n for (const term of searchTerms) {\r\n if (\r\n text === term ||\r\n ariaLabel === term ||\r\n dataTab === term ||\r\n text.includes(term)\r\n ) {\r\n return el;\r\n }\r\n }\r\n }\r\n }\r\n\r\n return null;\r\n};\r\n\r\nconst executeNavigate = async (call: NavigateToolCall): Promise<boolean> => {\r\n try {\r\n const targetUrl = call.url;\r\n let resolvedUrl: string;\r\n try {\r\n resolvedUrl = new URL(targetUrl, window.location.href).href;\r\n } catch {\r\n resolvedUrl = targetUrl;\r\n }\r\n\r\n const matchingElement = findMatchingLinkForTarget(targetUrl);\r\n\r\n if (matchingElement) {\r\n console.log(\"AuticBot navigate: clicking element\", resolvedUrl, matchingElement.tagName);\r\n await slowScrollElementIntoView(matchingElement);\r\n\r\n const center = getElementCenter(matchingElement);\r\n await moveCursor(center.x, center.y);\r\n\r\n matchingElement.dispatchEvent(new MouseEvent(\"pointerdown\", { bubbles: true, view: window }));\r\n matchingElement.dispatchEvent(new MouseEvent(\"mousedown\", { bubbles: true, view: window }));\r\n matchingElement.dispatchEvent(new MouseEvent(\"pointerup\", { bubbles: true, view: window }));\r\n matchingElement.dispatchEvent(new MouseEvent(\"mouseup\", { bubbles: true, view: window }));\r\n matchingElement.click();\r\n\r\n return !isSamePageNavigation(resolvedUrl);\r\n }\r\n\r\n // 6. Fallback: direct browser navigation (query param, hash, or full URL)\r\n console.log(\"AuticBot navigate: no matching element found, using direct navigation\", resolvedUrl);\r\n\r\n // Hash-only navigation\r\n try {\r\n const parsed = new URL(resolvedUrl);\r\n if (\r\n parsed.origin === window.location.origin &&\r\n parsed.pathname === window.location.pathname &&\r\n parsed.hash\r\n ) {\r\n window.location.hash = parsed.hash;\r\n return false;\r\n }\r\n } catch { /* continue */ }\r\n\r\n // Query-param or same-origin navigation via History API\r\n try {\r\n const parsed = new URL(resolvedUrl);\r\n if (parsed.origin === window.location.origin) {\r\n // Use pushState + popstate to trigger SPA routers\r\n const newPath = parsed.pathname + parsed.search + parsed.hash;\r\n window.history.pushState({}, \"\", newPath);\r\n window.dispatchEvent(new PopStateEvent(\"popstate\", { state: {} }));\r\n return false;\r\n }\r\n } catch { /* continue */ }\r\n\r\n // Cross-origin: full page navigation\r\n window.location.href = resolvedUrl;\r\n return true;\r\n } catch (error) {\r\n console.warn(\"AuticBot navigate: error\", call.url, error);\r\n return false;\r\n }\r\n};\r\n\r\nconst executeGetPageContext = async () => {\r\n const context = getPageContext();\r\n console.info(\r\n `[Autic] getPageContext tool executed links=${context.links.length} interactables=${context.interactables.length} summary_len=${context.summary.length}`,\r\n );\r\n};\r\n\r\nexport const executeToolCalls = async (toolCalls: AgentToolCall[]) => {\r\n for (const toolCall of toolCalls) {\r\n if (toolCall.tool === \"interact\") {\r\n await executeInteract(toolCall);\r\n continue;\r\n }\r\n\r\n if (toolCall.tool === \"scroll\") {\r\n await executeScroll(toolCall);\r\n continue;\r\n }\r\n\r\n if (toolCall.tool === \"getPageContext\") {\r\n await executeGetPageContext();\r\n continue;\r\n }\r\n\r\n if (toolCall.tool === \"navigate\") {\r\n const terminalNavigation = await executeNavigate(toolCall);\r\n if (terminalNavigation) {\r\n break;\r\n }\r\n }\r\n }\r\n};\r\n\r\n// ── Agent-mode tool execution (returns results) ─────────────────────\r\n\r\nexport type ToolCallWithId = AgentToolCall & {\r\n call_id: string;\r\n};\r\n\r\nexport interface ToolCallResult {\r\n call_id: string;\r\n result: string;\r\n}\r\n\r\n/**\r\n * Execute a single tool call and return a result string.\r\n * Used by the agent loop to feed results back into the LLM.\r\n */\r\nexport const executeSingleToolCall = async (\r\n call: ToolCallWithId,\r\n): Promise<ToolCallResult> => {\r\n const callId = call.call_id;\r\n try {\r\n if (call.tool === \"interact\") {\r\n await executeInteract(call);\r\n return {\r\n call_id: callId,\r\n result: `Etkileşim başarılı: ${call.action}`,\r\n };\r\n }\r\n\r\n if (call.tool === \"scroll\") {\r\n await executeScroll(call);\r\n return {\r\n call_id: callId,\r\n result: \"Öğeye kaydırma başarılı.\",\r\n };\r\n }\r\n\r\n if (call.tool === \"getPageContext\") {\r\n const context = getPageContext(true);\r\n return {\r\n call_id: callId,\r\n result: context.summary,\r\n };\r\n }\r\n\r\n if (call.tool === \"navigate\") {\r\n await executeNavigate(call);\r\n // Wait for navigation / SPA routing to settle\r\n await new Promise((resolve) => setTimeout(resolve, 1500));\r\n const context = getPageContext();\r\n return {\r\n call_id: callId,\r\n result: `Navigasyon tamamlandı. Şu anki sayfa: ${window.location.href}\\nSayfa bağlamı: ${context.summary}`,\r\n };\r\n }\r\n\r\n return { call_id: callId, result: \"Bilinmeyen araç.\" };\r\n } catch (error) {\r\n const msg = error instanceof Error ? error.message : String(error);\r\n console.warn(`[Autic] Tool execution error: ${call.tool}`, error);\r\n return { call_id: callId, result: `Hata: ${msg}` };\r\n }\r\n};\r\n","import {\r\n savePendingAgentResume,\r\n clearPendingAgentResume,\r\n hideAgentCursor,\r\n type PendingAgentResume,\r\n} from \"../agent/tools\";\r\n\r\nexport type ChatRole = \"system\" | \"user\" | \"assistant\";\r\n\r\nexport interface ChatMessage {\r\n role: ChatRole;\r\n content: string;\r\n}\r\n\r\ninterface ApiErrorBody {\r\n detail?: string;\r\n error?: string;\r\n message?: string;\r\n}\r\n\r\ninterface SseEventPayload {\r\n type?: string;\r\n session_id?: string;\r\n user_text?: string;\r\n assistant_text?: string;\r\n delta?: string;\r\n audio?: string;\r\n format?: string;\r\n mime_type?: string;\r\n sample_rate?: number;\r\n error?: string;\r\n}\r\n\r\ninterface TtsWsEventPayload {\r\n type?: string;\r\n request_id?: string;\r\n seq?: number;\r\n audio?: string;\r\n format?: string;\r\n mime_type?: string;\r\n sample_rate?: number;\r\n error?: string;\r\n retryable?: boolean;\r\n last_seq?: number;\r\n}\r\n\r\ninterface SttWsEventPayload {\r\n type?: string;\r\n session_id?: string;\r\n seq?: number;\r\n text?: string;\r\n error?: string;\r\n retryable?: boolean;\r\n}\r\n\r\nexport type AudioStreamState = \"rendering\" | \"playing\" | \"done\" | \"fallback\";\r\nexport const TTS_WS_RETRY_DELAYS_MS = [250, 750, 1500];\r\n\r\nconst BULUT_AUDIO_STOP_EVENT = \"bulut:audio-stop\";\r\nconst activeAudioElements = new Set<HTMLAudioElement>();\r\nlet audioPlaybackGeneration = 0;\r\n\r\nconst normalizeBaseUrl = (baseUrl: string): string => {\r\n const trimmed = baseUrl.trim().replace(/\\/+$/, \"\");\r\n if (/^https?:\\/\\//i.test(trimmed)) {\r\n return trimmed;\r\n }\r\n // Treat host-only values like \"api.bulut.lu\" as HTTPS absolute URLs.\r\n return `https://${trimmed}`;\r\n};\r\nconst toWebSocketUrl = (baseUrl: string, path: string): string => {\r\n const normalized = normalizeBaseUrl(baseUrl);\r\n const url = new URL(normalized);\r\n url.protocol = url.protocol === \"https:\" ? \"wss:\" : \"ws:\";\r\n url.pathname = `${url.pathname.replace(/\\/$/, \"\")}${path}`;\r\n url.search = \"\";\r\n url.hash = \"\";\r\n return url.toString();\r\n};\r\n\r\nconst createRequestId = (): string => {\r\n if (typeof crypto !== \"undefined\" && \"randomUUID\" in crypto) {\r\n return crypto.randomUUID();\r\n }\r\n return `tts-${Date.now()}-${Math.random().toString(16).slice(2)}`;\r\n};\r\n\r\nexport const parseTtsWsEventPayload = (\r\n value: unknown,\r\n): TtsWsEventPayload | null => {\r\n try {\r\n if (typeof value !== \"string\") {\r\n return null;\r\n }\r\n return JSON.parse(value) as TtsWsEventPayload;\r\n } catch {\r\n return null;\r\n }\r\n};\r\n\r\nexport const parseSttWsEventPayload = (\r\n value: unknown,\r\n): SttWsEventPayload | null => {\r\n try {\r\n if (typeof value !== \"string\") {\r\n return null;\r\n }\r\n return JSON.parse(value) as SttWsEventPayload;\r\n } catch {\r\n return null;\r\n }\r\n};\r\n\r\nexport const shouldAcceptAudioSeq = (\r\n incomingSeq: number,\r\n highestSeqSeen: number,\r\n): boolean => incomingSeq > highestSeqSeen;\r\n\r\nexport const shouldFallbackToSse = (error: unknown): boolean => {\r\n if (typeof error === \"object\" && error !== null && \"retryable\" in error) {\r\n return Boolean((error as { retryable?: boolean }).retryable);\r\n }\r\n return true;\r\n};\r\n\r\nconst parseErrorBody = async (response: Response): Promise<string> => {\r\n try {\r\n const data = (await response.json()) as ApiErrorBody;\r\n const detail = data.detail;\r\n if (typeof detail === \"string\") return detail;\r\n if (detail && typeof detail === \"object\") return JSON.stringify(detail);\r\n return data.error || data.message || response.statusText;\r\n } catch {\r\n return response.statusText;\r\n }\r\n};\r\n\r\nconst sleep = (ms: number): Promise<void> =>\r\n new Promise((resolve) => {\r\n setTimeout(resolve, ms);\r\n });\r\n\r\nconst registerActiveAudioElement = (audioElement: HTMLAudioElement): void => {\r\n activeAudioElements.add(audioElement);\r\n};\r\n\r\nconst unregisterActiveAudioElement = (audioElement: HTMLAudioElement): void => {\r\n activeAudioElements.delete(audioElement);\r\n};\r\n\r\nconst wasPlaybackStoppedAfter = (generationAtStart: number): boolean =>\r\n audioPlaybackGeneration !== generationAtStart;\r\n\r\nexport const getAudioPlaybackGeneration = (): number => audioPlaybackGeneration;\r\n\r\nexport const stopActiveAudioPlayback = (): void => {\r\n audioPlaybackGeneration += 1;\r\n const active = Array.from(activeAudioElements);\r\n for (const audioElement of active) {\r\n try {\r\n audioElement.dispatchEvent(new Event(BULUT_AUDIO_STOP_EVENT));\r\n audioElement.pause();\r\n audioElement.removeAttribute(\"src\");\r\n audioElement.load();\r\n } catch {\r\n // Ignore playback stop errors.\r\n }\r\n }\r\n};\r\n\r\nexport const base64ToUint8Array = (base64: string): Uint8Array<ArrayBuffer> => {\r\n // Strip potential data URI prefix if present\r\n const cleanBase64 = base64.replace(/^data:audio\\/\\w+;base64,/, \"\");\r\n const binaryString = atob(cleanBase64);\r\n const bytes = new Uint8Array(binaryString.length) as Uint8Array<ArrayBuffer>;\r\n for (let i = 0; i < binaryString.length; i += 1) {\r\n bytes[i] = binaryString.charCodeAt(i);\r\n }\r\n return bytes;\r\n};\r\n\r\nconst blobToBase64 = async (blob: Blob): Promise<string> => {\r\n const bytes = new Uint8Array(await blob.arrayBuffer());\r\n const chunkSize = 0x8000;\r\n let binary = \"\";\r\n for (let i = 0; i < bytes.length; i += chunkSize) {\r\n binary += String.fromCharCode(...bytes.subarray(i, i + chunkSize));\r\n }\r\n return btoa(binary);\r\n};\r\n\r\nconst createWavHeader = (\r\n length: number,\r\n sampleRate: number = 16000,\r\n): Uint8Array<ArrayBuffer> => {\r\n const buffer = new ArrayBuffer(44);\r\n const view = new DataView(buffer);\r\n const channels = 1;\r\n\r\n // RIFF chunk descriptor\r\n view.setUint32(0, 0x52494646, false); // \"RIFF\"\r\n view.setUint32(4, 36 + length, true); // file length - 8\r\n view.setUint32(8, 0x57415645, false); // \"WAVE\"\r\n\r\n // fmt sub-chunk\r\n view.setUint32(12, 0x666d7420, false); // \"fmt \"\r\n view.setUint32(16, 16, true); // Subchunk1Size (16 for PCM)\r\n view.setUint16(20, 1, true); // AudioFormat (1 for PCM)\r\n view.setUint16(22, channels, true); // NumChannels\r\n view.setUint32(24, sampleRate, true); // SampleRate\r\n view.setUint32(28, sampleRate * channels * 2, true); // ByteRate\r\n view.setUint16(32, channels * 2, true); // BlockAlign\r\n view.setUint16(34, 16, true); // BitsPerSample\r\n\r\n // data sub-chunk\r\n view.setUint32(36, 0x64617461, false); // \"data\"\r\n view.setUint32(40, length, true); // Subchunk2Size\r\n\r\n return new Uint8Array(buffer) as Uint8Array<ArrayBuffer>;\r\n};\r\nconst waitForPlaybackEnd = async (\r\n audioElement: HTMLAudioElement,\r\n): Promise<void> => {\r\n if (audioElement.ended) {\r\n return;\r\n }\r\n\r\n await new Promise<void>((resolve, reject) => {\r\n const watchdog = window.setInterval(() => {\r\n if (!audioElement.ended) {\r\n console.info(\"[Bulut] playback watchdog: still playing...\");\r\n }\r\n }, 30000);\r\n\r\n const onEnded = () => {\r\n cleanup();\r\n resolve();\r\n };\r\n\r\n const onError = () => {\r\n cleanup();\r\n reject(new Error(\"Ses oynatma hatası oluştu.\"));\r\n };\r\n\r\n const onForcedStop = () => {\r\n cleanup();\r\n resolve();\r\n };\r\n\r\n const cleanup = () => {\r\n window.clearInterval(watchdog);\r\n audioElement.removeEventListener(\"ended\", onEnded);\r\n audioElement.removeEventListener(\"error\", onError);\r\n audioElement.removeEventListener(BULUT_AUDIO_STOP_EVENT, onForcedStop);\r\n };\r\n\r\n audioElement.addEventListener(\"ended\", onEnded);\r\n audioElement.addEventListener(\"error\", onError);\r\n audioElement.addEventListener(BULUT_AUDIO_STOP_EVENT, onForcedStop);\r\n });\r\n};\r\n\r\n\r\n\r\nconst playBufferedAudio = async (\r\n chunks: Uint8Array<ArrayBuffer>[],\r\n mimeType: string,\r\n sampleRate: number = 16000,\r\n onAudioStateChange?: (state: AudioStreamState) => void,\r\n): Promise<void> => {\r\n const playbackGeneration = getAudioPlaybackGeneration();\r\n if (chunks.length === 0) {\r\n onAudioStateChange?.(\"done\");\r\n return;\r\n }\r\n\r\n if (wasPlaybackStoppedAfter(playbackGeneration)) {\r\n onAudioStateChange?.(\"done\");\r\n return;\r\n }\r\n\r\n // Debug info\r\n const totalBytes = chunks.reduce((acc, c) => acc + c.byteLength, 0);\r\n console.log(`[Bulut] Playing buffered audio: ${chunks.length} chunks, ${totalBytes} bytes, type=${mimeType}`);\r\n\r\n onAudioStateChange?.(\"fallback\");\r\n\r\n const blobParts: ArrayBuffer[] = chunks.map((chunk) => {\r\n const copied = new Uint8Array(chunk.byteLength) as Uint8Array<ArrayBuffer>;\r\n copied.set(chunk);\r\n return copied.buffer;\r\n });\r\n\r\n // Verify magic numbers and detect MIME type\r\n let detectedMime = mimeType;\r\n if (chunks.length > 0 && chunks[0].length >= 4) {\r\n const header = Array.from(chunks[0].slice(0, 4))\r\n .map(b => b.toString(16).padStart(2, '0').toUpperCase())\r\n .join(' ');\r\n console.log(`[Bulut] Audio header (hex): ${header}`);\r\n\r\n // Magic number detection\r\n if (header.startsWith(\"49 44 33\")) { // ID3\r\n detectedMime = \"audio/mpeg\";\r\n } else if (header.startsWith(\"FF F3\") || header.startsWith(\"FF F2\")) { // MP3 Sync\r\n detectedMime = \"audio/mpeg\";\r\n } else if (header.startsWith(\"52 49 46 46\")) { // RIFF (WAV)\r\n detectedMime = \"audio/wav\";\r\n } else if (header.startsWith(\"1A 45 DF A3\")) { // EBML (WebM)\r\n detectedMime = \"audio/webm\";\r\n }\r\n }\r\n\r\n // Ensure valid MIME type\r\n // Ensure valid MIME type or wrap raw PCM\r\n let safeMimeType = detectedMime && detectedMime.includes(\"/\") ? detectedMime : \"audio/mpeg\";\r\n let finalBlobParts: BlobPart[] = blobParts;\r\n\r\n if (mimeType === \"audio/pcm\") {\r\n // Wrap raw PCM in WAV container\r\n const totalLength = chunks.reduce((acc, c) => acc + c.byteLength, 0);\r\n const header = createWavHeader(totalLength, sampleRate);\r\n finalBlobParts = [header.buffer, ...blobParts];\r\n safeMimeType = \"audio/wav\";\r\n console.log(`[Bulut] Wrapped raw PCM in WAV (rate=${sampleRate})`);\r\n }\r\n\r\n console.log(`[Bulut] Creating blob with type: ${safeMimeType} (original: ${mimeType})`);\r\n const blob = new Blob(finalBlobParts, { type: safeMimeType });\r\n\r\n const audioElement = new Audio();\r\n const objectUrl = URL.createObjectURL(blob);\r\n\r\n try {\r\n registerActiveAudioElement(audioElement);\r\n\r\n audioElement.preload = \"auto\";\r\n audioElement.autoplay = true;\r\n // Some browsers need this\r\n audioElement.setAttribute(\"playsinline\", \"true\");\r\n audioElement.src = objectUrl;\r\n\r\n if (wasPlaybackStoppedAfter(playbackGeneration)) {\r\n onAudioStateChange?.(\"done\");\r\n return;\r\n }\r\n\r\n await audioElement.play();\r\n onAudioStateChange?.(\"playing\");\r\n await waitForPlaybackEnd(audioElement);\r\n onAudioStateChange?.(\"done\");\r\n } catch (err) {\r\n console.error(`[Bulut] Playback failed: ${err}`, { mimeType: safeMimeType, size: blob.size });\r\n onAudioStateChange?.(\"done\"); // Signal done to unblock UI even on error\r\n throw err;\r\n } finally {\r\n unregisterActiveAudioElement(audioElement);\r\n audioElement.pause();\r\n audioElement.removeAttribute(\"src\");\r\n audioElement.load();\r\n URL.revokeObjectURL(objectUrl);\r\n }\r\n};\r\n\r\nexport interface StreamController {\r\n stop: () => void;\r\n done: Promise<void>;\r\n}\r\n\r\nexport const parseSseEventPayload = (eventBlock: string): SseEventPayload | null => {\r\n const dataLines = eventBlock\r\n .split(/\\r?\\n/)\r\n .map((line) => line.trim())\r\n .filter((line) => line.startsWith(\"data:\"))\r\n .map((line) => line.slice(5).trimStart());\r\n\r\n if (dataLines.length === 0) {\r\n return null;\r\n }\r\n\r\n const dataStr = dataLines.join(\"\\n\");\r\n if (dataStr === \"[DONE]\") {\r\n return { type: \"done\" };\r\n }\r\n\r\n try {\r\n return JSON.parse(dataStr) as SseEventPayload;\r\n } catch (error) {\r\n console.warn(\"Error parsing SSE chunk:\", error);\r\n return null;\r\n }\r\n};\r\n\r\nexport const isAudioSsePayload = (\r\n payload: SseEventPayload,\r\n): payload is SseEventPayload & { audio: string } =>\r\n typeof payload.audio === \"string\" &&\r\n (payload.type === undefined || payload.type === \"audio\");\r\n\r\n// ── Separated Endpoint Helpers ──────────────────────────────────────\r\n\r\nexport async function transcribeAudio(\r\n baseUrl: string,\r\n file: File,\r\n projectId: string,\r\n sessionId: string | null,\r\n language: string,\r\n onRequestSent?: () => void,\r\n): Promise<{ text: string; session_id: string }> {\r\n const url = `${normalizeBaseUrl(baseUrl)}/chat/stt`;\r\n const formData = new FormData();\r\n formData.append(\"file\", file);\r\n formData.append(\"project_id\", projectId);\r\n if (sessionId) formData.append(\"session_id\", sessionId);\r\n formData.append(\"language\", language);\r\n\r\n const responsePromise = fetch(url, { method: \"POST\", body: formData });\r\n onRequestSent?.();\r\n const response = await responsePromise;\r\n if (!response.ok) {\r\n throw new Error(await parseErrorBody(response));\r\n }\r\n return response.json();\r\n}\r\n\r\nexport interface SttWsResult {\r\n text: string;\r\n session_id: string;\r\n}\r\n\r\nexport interface SttWsEvents {\r\n onRequestSent?: () => void;\r\n onSessionId?: (sessionId: string) => void;\r\n onPartial?: (payload: { seq: number; text: string }) => void;\r\n}\r\n\r\nexport interface SttWsController {\r\n pushChunk: (chunk: Blob) => Promise<void>;\r\n stop: () => Promise<SttWsResult>;\r\n cancel: () => void;\r\n}\r\n\r\nexport const startSttWebSocketStream = (\r\n baseUrl: string,\r\n config: {\r\n projectId: string;\r\n sessionId: string | null;\r\n language?: string;\r\n mimeType?: string;\r\n },\r\n events: SttWsEvents = {},\r\n): SttWsController => {\r\n const wsUrl = toWebSocketUrl(baseUrl, \"/chat/stt/ws\");\r\n console.info(\"[Bulut] STT WS connecting to\", wsUrl);\r\n const socket = new WebSocket(wsUrl);\r\n let seq = 0;\r\n let finalText = \"\";\r\n let finalSessionId = config.sessionId || \"\";\r\n let stopped = false;\r\n let settled = false;\r\n // All chunk sends and the final stop are chained through sendQueue\r\n // so the \"stop\" message always follows all enqueued chunks.\r\n let sendQueue: Promise<void> = Promise.resolve();\r\n\r\n let resolveStart: (() => void) | null = null;\r\n let rejectStart: ((error: Error & { retryable?: boolean }) => void) | null = null;\r\n const startPromise = new Promise<void>((resolve, reject) => {\r\n resolveStart = resolve;\r\n rejectStart = reject;\r\n });\r\n\r\n let resolveDone: ((result: SttWsResult) => void) | null = null;\r\n let rejectDone: ((error: Error & { retryable?: boolean }) => void) | null = null;\r\n const donePromise = new Promise<SttWsResult>((resolve, reject) => {\r\n resolveDone = resolve;\r\n rejectDone = reject;\r\n });\r\n\r\n const rejectAll = (error: Error & { retryable?: boolean }) => {\r\n if (settled) return;\r\n settled = true;\r\n console.warn(\"[Bulut] STT WS rejected:\", error.message);\r\n rejectStart?.(error);\r\n rejectDone?.(error);\r\n };\r\n\r\n const resolveDoneIfPossible = () => {\r\n if (settled) return;\r\n if (!finalText.trim() || !finalSessionId) return;\r\n settled = true;\r\n resolveStart?.();\r\n resolveDone?.({\r\n text: finalText.trim(),\r\n session_id: finalSessionId,\r\n });\r\n };\r\n\r\n socket.onopen = () => {\r\n console.info(\"[Bulut] STT WS connected, sending start\");\r\n events.onRequestSent?.();\r\n socket.send(\r\n JSON.stringify({\r\n type: \"start\",\r\n project_id: config.projectId,\r\n session_id: config.sessionId || undefined,\r\n language: config.language || \"tr\",\r\n mime_type: config.mimeType || \"audio/webm\",\r\n }),\r\n );\r\n };\r\n\r\n socket.onmessage = (event) => {\r\n const payload = parseSttWsEventPayload(String(event.data));\r\n if (!payload) return;\r\n\r\n if (payload.type === \"start_ack\" && typeof payload.session_id === \"string\") {\r\n console.info(\"[Bulut] STT WS start_ack received, session:\", payload.session_id);\r\n finalSessionId = payload.session_id;\r\n events.onSessionId?.(payload.session_id);\r\n resolveStart?.();\r\n return;\r\n }\r\n\r\n if (payload.type === \"partial\" && typeof payload.text === \"string\") {\r\n events.onPartial?.({\r\n seq: typeof payload.seq === \"number\" ? payload.seq : 0,\r\n text: payload.text,\r\n });\r\n return;\r\n }\r\n\r\n if (payload.type === \"final\" && typeof payload.text === \"string\") {\r\n console.info(\"[Bulut] STT WS final text received:\", payload.text.slice(0, 80));\r\n finalText = payload.text;\r\n if (typeof payload.session_id === \"string\") {\r\n finalSessionId = payload.session_id;\r\n events.onSessionId?.(payload.session_id);\r\n }\r\n return;\r\n }\r\n\r\n if (payload.type === \"done\") {\r\n console.info(\"[Bulut] STT WS done\");\r\n resolveDoneIfPossible();\r\n socket.close();\r\n return;\r\n }\r\n\r\n if (payload.type === \"error\") {\r\n console.error(\"[Bulut] STT WS server error:\", payload.error);\r\n const err = buildError(payload.error || \"stt_ws_error\", payload.retryable !== false);\r\n rejectAll(err);\r\n socket.close();\r\n }\r\n };\r\n\r\n socket.onerror = (ev) => {\r\n console.error(\"[Bulut] STT WS transport error\", ev);\r\n rejectAll(buildError(\"stt_ws_transport_error\", true));\r\n };\r\n\r\n socket.onclose = (ev) => {\r\n console.info(\"[Bulut] STT WS closed code=%d reason=%s\", ev.code, ev.reason);\r\n if (settled) return;\r\n if (finalText && finalSessionId) {\r\n resolveDoneIfPossible();\r\n return;\r\n }\r\n rejectAll(buildError(\"stt_ws_closed_before_done\", true));\r\n };\r\n\r\n return {\r\n pushChunk: (chunk: Blob): Promise<void> => {\r\n if (stopped || chunk.size === 0) return Promise.resolve();\r\n // Chain the entire operation (wait for connection, base64-encode,\r\n // send) into sendQueue so that a later stop() is guaranteed to\r\n // follow all previously-enqueued chunks.\r\n sendQueue = sendQueue.then(async () => {\r\n if (stopped) return;\r\n await startPromise;\r\n if (stopped) return;\r\n const audio = await blobToBase64(chunk);\r\n seq += 1;\r\n if (stopped || socket.readyState !== WebSocket.OPEN) return;\r\n console.debug(\"[Bulut] STT WS sending chunk seq=%d size=%d\", seq, chunk.size);\r\n socket.send(JSON.stringify({ type: \"chunk\", seq, audio }));\r\n });\r\n return sendQueue;\r\n },\r\n stop: (): Promise<SttWsResult> => {\r\n console.info(\"[Bulut] STT WS stop requested, draining %d pending chunks\", seq);\r\n // Chain after all pending pushChunk operations so the server\r\n // always receives every chunk before the stop message.\r\n sendQueue = sendQueue.then(async () => {\r\n await startPromise;\r\n if (stopped) return;\r\n if (socket.readyState === WebSocket.OPEN) {\r\n console.info(\"[Bulut] STT WS sending stop after seq=%d\", seq);\r\n socket.send(JSON.stringify({ type: \"stop\" }));\r\n }\r\n });\r\n return donePromise;\r\n },\r\n cancel: () => {\r\n stopped = true;\r\n try {\r\n socket.close();\r\n } catch {\r\n // no-op\r\n }\r\n },\r\n };\r\n};\r\n\r\ninterface TtsCollectResult {\r\n chunks: Uint8Array<ArrayBuffer>[];\r\n mimeType: string;\r\n sampleRate: number;\r\n}\r\n\r\nconst buildError = (message: string, retryable: boolean = true): Error & { retryable: boolean } => {\r\n const error = new Error(message) as Error & { retryable: boolean };\r\n error.retryable = retryable;\r\n return error;\r\n};\r\n\r\nconst collectTtsViaSse = async (\r\n baseUrl: string,\r\n assistantText: string,\r\n voice: string,\r\n accessibilityMode: boolean,\r\n isStopped: () => boolean,\r\n setReader: (reader: ReadableStreamDefaultReader<Uint8Array> | undefined) => void,\r\n): Promise<TtsCollectResult> => {\r\n const ttsFormData = new FormData();\r\n ttsFormData.append(\"text\", assistantText);\r\n ttsFormData.append(\"voice\", voice);\r\n ttsFormData.append(\"accessibility_mode\", String(accessibilityMode));\r\n\r\n const ttsResponse = await fetch(`${normalizeBaseUrl(baseUrl)}/chat/tts`, {\r\n method: \"POST\",\r\n body: ttsFormData,\r\n });\r\n\r\n if (!ttsResponse.ok) {\r\n throw buildError(await parseErrorBody(ttsResponse), false);\r\n }\r\n\r\n const reader = ttsResponse.body?.getReader();\r\n if (!reader) {\r\n throw buildError(\"TTS response body is not readable\", false);\r\n }\r\n\r\n setReader(reader);\r\n\r\n const chunks: Uint8Array<ArrayBuffer>[] = [];\r\n let mimeType = \"audio/mpeg\";\r\n let sampleRate = 16000;\r\n const decoder = new TextDecoder();\r\n let buffer = \"\";\r\n\r\n while (true) {\r\n if (isStopped()) {\r\n break;\r\n }\r\n\r\n const { done, value } = await reader.read();\r\n if (done) {\r\n break;\r\n }\r\n\r\n buffer += decoder.decode(value, { stream: true });\r\n const blocks = buffer.split(/\\r?\\n\\r?\\n/);\r\n buffer = blocks.pop() || \"\";\r\n\r\n for (const block of blocks) {\r\n const payload = parseSseEventPayload(block);\r\n if (!payload) {\r\n continue;\r\n }\r\n\r\n if (isAudioSsePayload(payload)) {\r\n const format = payload.format || \"mp3\";\r\n mimeType = payload.mime_type || (format === \"webm\" ? \"audio/webm\" : \"audio/mpeg\");\r\n chunks.push(base64ToUint8Array(payload.audio));\r\n if (payload.sample_rate) {\r\n sampleRate = payload.sample_rate;\r\n }\r\n }\r\n }\r\n }\r\n\r\n reader.releaseLock();\r\n setReader(undefined);\r\n\r\n return { chunks, mimeType, sampleRate };\r\n};\r\n\r\nconst collectTtsViaWebSocket = async (\r\n baseUrl: string,\r\n assistantText: string,\r\n voice: string,\r\n accessibilityMode: boolean,\r\n isStopped: () => boolean,\r\n setSocket: (socket: WebSocket | null) => void,\r\n onFirstBatchReady?: (batch: TtsCollectResult) => void,\r\n): Promise<TtsCollectResult> => {\r\n const wsUrl = toWebSocketUrl(baseUrl, \"/chat/tts/ws\");\r\n const requestId = createRequestId();\r\n const chunks: Uint8Array<ArrayBuffer>[] = [];\r\n let mimeType = \"audio/mpeg\";\r\n let sampleRate = 16000;\r\n let highestSeqSeen = 0;\r\n\r\n // Streaming: fire first batch of chunks to the caller early\r\n let firstBatchFired = false;\r\n let firstBatchTimer: ReturnType<typeof setTimeout> | null = null;\r\n const FIRST_BATCH_DELAY_MS = 250;\r\n\r\n const fireFirstBatch = () => {\r\n if (firstBatchFired || !onFirstBatchReady || chunks.length === 0) return;\r\n firstBatchFired = true;\r\n if (firstBatchTimer) { clearTimeout(firstBatchTimer); firstBatchTimer = null; }\r\n const batch = chunks.splice(0);\r\n onFirstBatchReady({ chunks: batch, mimeType, sampleRate });\r\n };\r\n\r\n const connectOnce = (): Promise<void> =>\r\n new Promise((resolve, reject) => {\r\n if (isStopped()) {\r\n reject(buildError(\"stream_stopped\", false));\r\n return;\r\n }\r\n\r\n let done = false;\r\n let finalError: (Error & { retryable?: boolean }) | null = null;\r\n const socket = new WebSocket(wsUrl);\r\n setSocket(socket);\r\n\r\n const finalize = (\r\n mode: \"resolve\" | \"reject\",\r\n error?: Error & { retryable?: boolean },\r\n ) => {\r\n socket.onopen = null;\r\n socket.onmessage = null;\r\n socket.onerror = null;\r\n socket.onclose = null;\r\n setSocket(null);\r\n if (mode === \"resolve\") {\r\n resolve();\r\n return;\r\n }\r\n reject(error || buildError(\"tts_ws_closed\", true));\r\n };\r\n\r\n socket.onopen = () => {\r\n console.info(\r\n `[Bulut] TTS WS connected request_id=${requestId} resume_seq=${highestSeqSeen}`,\r\n );\r\n socket.send(\r\n JSON.stringify({\r\n type: \"start\",\r\n request_id: requestId,\r\n text: assistantText,\r\n voice,\r\n accessibility_mode: accessibilityMode,\r\n last_seq: highestSeqSeen,\r\n }),\r\n );\r\n };\r\n\r\n socket.onmessage = (event) => {\r\n const payload = parseTtsWsEventPayload(String(event.data));\r\n if (!payload) {\r\n console.warn(\"[Bulut] TTS WS invalid JSON payload\");\r\n return;\r\n }\r\n\r\n if (payload.type === \"audio\" && typeof payload.audio === \"string\") {\r\n const seq = typeof payload.seq === \"number\" ? payload.seq : 0;\r\n if (shouldAcceptAudioSeq(seq, highestSeqSeen)) {\r\n chunks.push(base64ToUint8Array(payload.audio));\r\n highestSeqSeen = seq;\r\n if (payload.mime_type) {\r\n mimeType = payload.mime_type;\r\n }\r\n if (typeof payload.sample_rate === \"number\") {\r\n sampleRate = payload.sample_rate;\r\n }\r\n\r\n // Schedule first-batch flush for streaming playback\r\n if (onFirstBatchReady && !firstBatchFired) {\r\n if (firstBatchTimer) clearTimeout(firstBatchTimer);\r\n firstBatchTimer = setTimeout(fireFirstBatch, FIRST_BATCH_DELAY_MS);\r\n }\r\n } else {\r\n console.info(\r\n `[Bulut] TTS WS duplicate chunk ignored request_id=${requestId} seq=${seq} seen=${highestSeqSeen}`,\r\n );\r\n }\r\n\r\n if (socket.readyState === WebSocket.OPEN) {\r\n socket.send(\r\n JSON.stringify({\r\n type: \"ack\",\r\n request_id: requestId,\r\n last_seq: highestSeqSeen,\r\n }),\r\n );\r\n }\r\n return;\r\n }\r\n\r\n if (payload.type === \"done\") {\r\n // Flush first batch if not yet fired (short text = all chunks in one batch)\r\n if (onFirstBatchReady && !firstBatchFired) {\r\n fireFirstBatch();\r\n }\r\n\r\n const streamLastSeq =\r\n typeof payload.last_seq === \"number\" ? payload.last_seq : highestSeqSeen;\r\n if (streamLastSeq > highestSeqSeen) {\r\n finalError = buildError(\"tts_ws_sequence_gap\", true);\r\n done = false;\r\n socket.close();\r\n return;\r\n }\r\n done = true;\r\n socket.close();\r\n return;\r\n }\r\n\r\n if (payload.type === \"error\") {\r\n finalError = buildError(payload.error || \"tts_ws_error\", payload.retryable !== false);\r\n done = false;\r\n socket.close();\r\n }\r\n };\r\n\r\n socket.onerror = () => {\r\n if (!finalError) {\r\n finalError = buildError(\"tts_ws_transport_error\", true);\r\n }\r\n };\r\n\r\n socket.onclose = () => {\r\n if (isStopped()) {\r\n finalize(\"reject\", buildError(\"stream_stopped\", false));\r\n return;\r\n }\r\n if (done) {\r\n finalize(\"resolve\");\r\n return;\r\n }\r\n finalize(\"reject\", finalError || buildError(\"tts_ws_closed_before_done\", true));\r\n };\r\n });\r\n\r\n for (let attempt = 0; attempt <= TTS_WS_RETRY_DELAYS_MS.length; attempt += 1) {\r\n if (attempt > 0) {\r\n const delay = TTS_WS_RETRY_DELAYS_MS[attempt - 1];\r\n console.warn(\r\n `[Bulut] TTS WS retry attempt=${attempt} delay_ms=${delay} last_seq=${highestSeqSeen}`,\r\n );\r\n await sleep(delay);\r\n }\r\n\r\n try {\r\n await connectOnce();\r\n return { chunks, mimeType, sampleRate };\r\n } catch (error) {\r\n const retryable =\r\n shouldFallbackToSse(error);\r\n const message = error instanceof Error ? error.message : String(error);\r\n console.warn(\r\n `[Bulut] TTS WS attempt failed attempt=${attempt} retryable=${retryable} error=${message}`,\r\n );\r\n if (!retryable || attempt === TTS_WS_RETRY_DELAYS_MS.length) {\r\n throw error;\r\n }\r\n }\r\n }\r\n\r\n throw buildError(\"tts_ws_exhausted\", true);\r\n};\r\n\r\n/**\r\n * Collect TTS audio via WebSocket (with SSE fallback) and play it.\r\n *\r\n * Uses streaming playback: the first batch of audio chunks starts\r\n * playing immediately while remaining chunks are still being received.\r\n * This dramatically reduces perceived latency, especially for longer\r\n * text where the backend pipelines synthesis sentence-by-sentence.\r\n */\r\nconst collectAndPlayTtsStreamed = async (\r\n baseUrl: string,\r\n text: string,\r\n voice: string,\r\n accessibilityMode: boolean,\r\n isStopped: () => boolean,\r\n setSocket: (socket: WebSocket | null) => void,\r\n setReader: (reader: ReadableStreamDefaultReader<Uint8Array> | undefined) => void,\r\n onAudioStateChange?: (state: AudioStreamState) => void,\r\n): Promise<void> => {\r\n const trimmed = text.trim();\r\n if (!trimmed) { onAudioStateChange?.(\"done\"); return; }\r\n\r\n const playbackGen = getAudioPlaybackGeneration();\r\n if (wasPlaybackStoppedAfter(playbackGen)) {\r\n onAudioStateChange?.(\"done\");\r\n return;\r\n }\r\n\r\n onAudioStateChange?.(\"rendering\");\r\n\r\n let firstBatchPlayPromise: Promise<void> | null = null;\r\n let ttsResult: TtsCollectResult;\r\n\r\n try {\r\n ttsResult = await collectTtsViaWebSocket(\r\n baseUrl, trimmed, voice, accessibilityMode,\r\n isStopped, setSocket,\r\n // Streaming: start playing the first batch immediately\r\n (firstBatch) => {\r\n if (wasPlaybackStoppedAfter(playbackGen) || isStopped()) return;\r\n if (firstBatch.chunks.length === 0) return;\r\n firstBatchPlayPromise = playBufferedAudio(\r\n firstBatch.chunks, firstBatch.mimeType, firstBatch.sampleRate,\r\n (state) => {\r\n // Forward playing state, but suppress \"done\" since more may follow\r\n if (state !== \"done\") onAudioStateChange?.(state);\r\n },\r\n ).catch(err => console.warn(\"[Bulut] first batch playback error\", err));\r\n },\r\n );\r\n } catch (wsErr) {\r\n // If first batch was already playing, accept partial audio\r\n if (firstBatchPlayPromise) {\r\n await firstBatchPlayPromise;\r\n onAudioStateChange?.(\"done\");\r\n return;\r\n }\r\n // Otherwise fall back to SSE (non-streaming, collect-then-play)\r\n if (isStopped()) { onAudioStateChange?.(\"done\"); return; }\r\n console.warn(\r\n `[Bulut] TTS WS failed, falling back to SSE: ${wsErr instanceof Error ? wsErr.message : String(wsErr)}`,\r\n );\r\n ttsResult = await collectTtsViaSse(\r\n baseUrl, trimmed, voice, accessibilityMode,\r\n isStopped, setReader,\r\n );\r\n }\r\n\r\n if (isStopped() || wasPlaybackStoppedAfter(playbackGen)) {\r\n onAudioStateChange?.(\"done\");\r\n return;\r\n }\r\n\r\n // Wait for first batch to finish playing\r\n if (firstBatchPlayPromise) {\r\n await firstBatchPlayPromise;\r\n }\r\n\r\n // Play remaining chunks (if any)\r\n if (ttsResult.chunks.length > 0) {\r\n await playBufferedAudio(\r\n ttsResult.chunks, ttsResult.mimeType, ttsResult.sampleRate,\r\n onAudioStateChange,\r\n );\r\n } else {\r\n onAudioStateChange?.(\"done\");\r\n }\r\n};\r\n\r\n// ── Agent-mode Types ────────────────────────────────────────────────\r\n\r\nexport interface AgentToolCallInfo {\r\n call_id: string;\r\n tool: string;\r\n args: Record<string, unknown>;\r\n}\r\n\r\nexport interface AgentVoiceChatEvents {\r\n onSttRequestSent?: () => void;\r\n onTranscription?: (data: {\r\n session_id: string;\r\n user_text: string;\r\n }) => void;\r\n onAssistantDelta?: (delta: string) => void;\r\n onAssistantDone?: (assistantText: string, expectsReply?: boolean) => void;\r\n onAudioStateChange?: (state: AudioStreamState) => void;\r\n onError?: (error: string) => void;\r\n /** Called when the agent requests tool execution on the frontend. */\r\n onToolCalls?: (calls: AgentToolCallInfo[]) => void;\r\n /** Called after each tool has been executed with the result. */\r\n onToolResult?: (callId: string, toolName: string, result: string) => void;\r\n /** Called at the start of each agent iteration. */\r\n onIteration?: (iteration: number, maxIterations: number) => void;\r\n /** Called when the backend confirms / creates a session ID. */\r\n onSessionId?: (sessionId: string) => void;\r\n /**\r\n * Called when the agent emits a reply text followed by tool calls.\r\n * This text is spoken aloud before the tools run so the user hears\r\n * every piece of the conversation, not just the final reply.\r\n */\r\n onIntermediateReply?: (text: string) => void;\r\n}\r\n\r\n/**\r\n * Standalone TTS helper: synthesize + play a text snippet.\r\n * Uses WebSocket TTS with SSE fallback, same as the main stream functions.\r\n */\r\nexport const speakText = async (\r\n baseUrl: string,\r\n text: string,\r\n voice: string,\r\n accessibilityMode: boolean,\r\n onAudioStateChange?: (state: AudioStreamState) => void,\r\n): Promise<void> => {\r\n const trimmed = text.trim();\r\n if (!trimmed) return;\r\n console.info(`[Bulut] speakText start (${trimmed.length} chars)`);\r\n await collectAndPlayTtsStreamed(\r\n baseUrl, trimmed, voice, accessibilityMode,\r\n () => false,\r\n () => {},\r\n () => {},\r\n onAudioStateChange,\r\n );\r\n};\r\n\r\n// ── Agent Voice Chat Stream (STT → Agent WS → TTS) ─────────────────\r\n\r\nexport const agentVoiceChatStream = (\r\n baseUrl: string,\r\n audioFile: File,\r\n projectId: string,\r\n sessionId: string | null,\r\n config: {\r\n model: string;\r\n voice: string;\r\n pageContext?: string;\r\n accessibilityMode?: boolean;\r\n },\r\n events: AgentVoiceChatEvents,\r\n executeTool: (call: AgentToolCallInfo) => Promise<{ call_id: string; result: string }>,\r\n): StreamController => {\r\n let isStopped = false;\r\n let activeSocket: WebSocket | null = null;\r\n let activeReader: ReadableStreamDefaultReader<Uint8Array> | undefined;\r\n let errorEmitted = false;\r\n\r\n const donePromise = new Promise<void>(async (resolve, reject) => {\r\n try {\r\n // ── 1. STT ────────────────────────────────────────────────\r\n if (isStopped) return resolve();\r\n const sttResult = await transcribeAudio(\r\n baseUrl,\r\n audioFile,\r\n projectId,\r\n sessionId,\r\n \"tr\",\r\n events.onSttRequestSent,\r\n );\r\n\r\n const currentSessionId = sttResult.session_id;\r\n let effectiveSessionId = currentSessionId;\r\n const userText = sttResult.text;\r\n\r\n events.onTranscription?.({\r\n session_id: currentSessionId,\r\n user_text: userText,\r\n });\r\n\r\n if (isStopped) return resolve();\r\n\r\n // ── 2. Agent loop via WebSocket ───────────────────────────\r\n const assistantText = await new Promise<string>((agentResolve, agentReject) => {\r\n if (isStopped) { agentResolve(\"\"); return; }\r\n\r\n const wsUrl = toWebSocketUrl(baseUrl, \"/chat/agent/ws\");\r\n const socket = new WebSocket(wsUrl);\r\n activeSocket = socket;\r\n\r\n let finalReply = \"\";\r\n let resolved = false;\r\n let accumulatedDelta = \"\";\r\n let allIntermediateText = \"\";\r\n\r\n const finish = (reply: string) => {\r\n if (resolved) return;\r\n resolved = true;\r\n agentResolve(reply);\r\n };\r\n\r\n const fail = (error: Error) => {\r\n if (resolved) return;\r\n resolved = true;\r\n agentReject(error);\r\n };\r\n\r\n socket.onopen = () => {\r\n console.info(\"[Bulut] Agent WS connected\");\r\n socket.send(JSON.stringify({\r\n type: \"start\",\r\n project_id: projectId,\r\n session_id: currentSessionId,\r\n user_text: userText,\r\n model: config.model,\r\n page_context: config.pageContext,\r\n accessibility_mode: config.accessibilityMode,\r\n }));\r\n };\r\n\r\n socket.onmessage = async (event) => {\r\n let data: Record<string, unknown>;\r\n try {\r\n data = JSON.parse(String(event.data));\r\n } catch {\r\n console.warn(\"[Bulut] Agent WS invalid JSON\");\r\n return;\r\n }\r\n\r\n const msgType = data.type as string;\r\n\r\n if (msgType === \"session\" && typeof data.session_id === \"string\") {\r\n effectiveSessionId = data.session_id as string;\r\n events.onSessionId?.(effectiveSessionId);\r\n return;\r\n }\r\n\r\n if (msgType === \"iteration\") {\r\n events.onIteration?.(\r\n data.iteration as number,\r\n data.max_iterations as number,\r\n );\r\n return;\r\n }\r\n\r\n if (msgType === \"reply_delta\" && typeof data.delta === \"string\") {\r\n accumulatedDelta += data.delta;\r\n events.onAssistantDelta?.(data.delta);\r\n return;\r\n }\r\n\r\n if (msgType === \"tool_calls\" && Array.isArray(data.calls)) {\r\n const calls = data.calls as AgentToolCallInfo[];\r\n\r\n // Speak accumulated text before running tools\r\n if (accumulatedDelta.trim()) {\r\n events.onIntermediateReply?.(accumulatedDelta.trim());\r\n allIntermediateText += accumulatedDelta;\r\n }\r\n accumulatedDelta = \"\";\r\n\r\n events.onToolCalls?.(calls);\r\n\r\n const results: { call_id: string; result: string }[] = [];\r\n for (const call of calls) {\r\n // Save resume state before navigate in case of full-page reload\r\n const isNavigate = call.tool === \"navigate\";\r\n if (isNavigate) {\r\n savePendingAgentResume({\r\n sessionId: effectiveSessionId,\r\n projectId,\r\n model: config.model,\r\n voice: config.voice,\r\n accessibilityMode: Boolean(config.accessibilityMode),\r\n pendingToolCalls: calls.map((c) => ({\r\n call_id: c.call_id,\r\n tool: c.tool,\r\n args: c.args,\r\n })),\r\n completedResults: [...results],\r\n accumulatedDelta: allIntermediateText || undefined,\r\n });\r\n }\r\n\r\n const result = await executeTool(call);\r\n\r\n // If we reach here, no full-page reload happened\r\n if (isNavigate) {\r\n clearPendingAgentResume();\r\n }\r\n\r\n events.onToolResult?.(call.call_id, call.tool, result.result);\r\n results.push(result);\r\n }\r\n\r\n if (socket.readyState === WebSocket.OPEN) {\r\n socket.send(JSON.stringify({\r\n type: \"tool_results\",\r\n results,\r\n }));\r\n }\r\n return;\r\n }\r\n\r\n if (msgType === \"agent_done\") {\r\n finalReply = (data.final_reply as string) || \"\";\r\n const replyExpectsReply = data.expects_reply !== false;\r\n events.onAssistantDone?.(finalReply, replyExpectsReply);\r\n if (typeof data.session_id === \"string\") {\r\n events.onSessionId?.(data.session_id as string);\r\n }\r\n finish(finalReply);\r\n return;\r\n }\r\n\r\n if (msgType === \"error\") {\r\n const errMsg = (data.error as string) || \"Agent error\";\r\n errorEmitted = true;\r\n events.onError?.(errMsg);\r\n fail(new Error(errMsg));\r\n return;\r\n }\r\n };\r\n\r\n socket.onerror = () => {\r\n console.error(\"[Bulut] Agent WS error\");\r\n errorEmitted = true;\r\n events.onError?.(\"Agent WebSocket connection error\");\r\n fail(new Error(\"Agent WebSocket connection error\"));\r\n };\r\n\r\n socket.onclose = () => {\r\n console.info(\"[Bulut] Agent WS closed\");\r\n finish(finalReply);\r\n };\r\n });\r\n\r\n activeSocket = null;\r\n\r\n // ── 3. TTS ────────────────────────────────────────────────\r\n if (isStopped || !assistantText) {\r\n if (!isStopped) {\r\n hideAgentCursor();\r\n }\r\n return resolve();\r\n }\r\n\r\n console.info(\r\n `[Bulut] TTS start mode=agent voice=${config.voice}`,\r\n );\r\n\r\n hideAgentCursor();\r\n await collectAndPlayTtsStreamed(\r\n baseUrl, assistantText, config.voice, Boolean(config.accessibilityMode),\r\n () => isStopped,\r\n (socket) => { activeSocket = socket; },\r\n (reader) => { activeReader = reader; },\r\n events.onAudioStateChange,\r\n );\r\n\r\n resolve();\r\n } catch (err) {\r\n // Only emit onError if it hasn't been emitted already by the WS handler\r\n if (!errorEmitted) {\r\n const msg = err instanceof Error ? err.message : String(err);\r\n events.onError?.(msg);\r\n }\r\n reject(err);\r\n } finally {\r\n activeReader?.cancel().catch(() => { });\r\n if (activeSocket && activeSocket.readyState <= WebSocket.OPEN) {\r\n activeSocket.close();\r\n }\r\n activeSocket = null;\r\n }\r\n });\r\n\r\n return {\r\n stop: () => {\r\n isStopped = true;\r\n stopActiveAudioPlayback();\r\n if (activeReader) {\r\n activeReader.cancel().catch(() => { });\r\n }\r\n if (activeSocket && activeSocket.readyState <= WebSocket.OPEN) {\r\n activeSocket.close();\r\n }\r\n },\r\n done: donePromise,\r\n };\r\n};\r\n\r\n// ── Agent Text Chat Stream (no STT, Agent WS → TTS) ────────────────\r\n\r\nexport const agentTextChatStream = (\r\n baseUrl: string,\r\n userText: string,\r\n projectId: string,\r\n sessionId: string | null,\r\n config: {\r\n model: string;\r\n voice: string;\r\n pageContext?: string;\r\n accessibilityMode?: boolean;\r\n },\r\n events: AgentVoiceChatEvents,\r\n executeTool: (call: AgentToolCallInfo) => Promise<{ call_id: string; result: string }>,\r\n): StreamController => {\r\n let isStopped = false;\r\n let activeSocket: WebSocket | null = null;\r\n let activeReader: ReadableStreamDefaultReader<Uint8Array> | undefined;\r\n let errorEmitted = false;\r\n\r\n const donePromise = new Promise<void>(async (resolve, reject) => {\r\n try {\r\n if (isStopped) return resolve();\r\n\r\n // ── 1. Agent loop via WebSocket ───────────────────────────\r\n const assistantText = await new Promise<string>((agentResolve, agentReject) => {\r\n if (isStopped) { agentResolve(\"\"); return; }\r\n\r\n const wsUrl = toWebSocketUrl(baseUrl, \"/chat/agent/ws\");\r\n const socket = new WebSocket(wsUrl);\r\n activeSocket = socket;\r\n\r\n let finalReply = \"\";\r\n let resolved = false;\r\n let effectiveSessionId = sessionId || \"\";\r\n let accumulatedDelta = \"\";\r\n let allIntermediateText = \"\";\r\n\r\n const finish = (reply: string) => {\r\n if (resolved) return;\r\n resolved = true;\r\n agentResolve(reply);\r\n };\r\n\r\n const fail = (error: Error) => {\r\n if (resolved) return;\r\n resolved = true;\r\n agentReject(error);\r\n };\r\n\r\n socket.onopen = () => {\r\n socket.send(JSON.stringify({\r\n type: \"start\",\r\n project_id: projectId,\r\n session_id: sessionId,\r\n user_text: userText,\r\n model: config.model,\r\n page_context: config.pageContext,\r\n accessibility_mode: config.accessibilityMode,\r\n }));\r\n };\r\n\r\n socket.onmessage = async (event) => {\r\n let data: Record<string, unknown>;\r\n try {\r\n data = JSON.parse(String(event.data));\r\n } catch { return; }\r\n\r\n const msgType = data.type as string;\r\n\r\n if (msgType === \"session\" && typeof data.session_id === \"string\") {\r\n effectiveSessionId = data.session_id as string;\r\n events.onSessionId?.(effectiveSessionId);\r\n return;\r\n }\r\n\r\n if (msgType === \"iteration\") {\r\n events.onIteration?.(\r\n data.iteration as number,\r\n data.max_iterations as number,\r\n );\r\n return;\r\n }\r\n\r\n if (msgType === \"reply_delta\" && typeof data.delta === \"string\") {\r\n accumulatedDelta += data.delta;\r\n events.onAssistantDelta?.(data.delta);\r\n return;\r\n }\r\n\r\n if (msgType === \"tool_calls\" && Array.isArray(data.calls)) {\r\n const calls = data.calls as AgentToolCallInfo[];\r\n\r\n // Speak accumulated text before running tools\r\n if (accumulatedDelta.trim()) {\r\n events.onIntermediateReply?.(accumulatedDelta.trim());\r\n allIntermediateText += accumulatedDelta;\r\n }\r\n accumulatedDelta = \"\";\r\n\r\n events.onToolCalls?.(calls);\r\n\r\n const results: { call_id: string; result: string }[] = [];\r\n for (const call of calls) {\r\n const isNavigate = call.tool === \"navigate\";\r\n if (isNavigate) {\r\n savePendingAgentResume({\r\n sessionId: effectiveSessionId,\r\n projectId,\r\n model: config.model,\r\n voice: config.voice,\r\n accessibilityMode: Boolean(config.accessibilityMode),\r\n pendingToolCalls: calls.map((c) => ({\r\n call_id: c.call_id,\r\n tool: c.tool,\r\n args: c.args,\r\n })),\r\n completedResults: [...results],\r\n accumulatedDelta: allIntermediateText || undefined,\r\n });\r\n }\r\n\r\n const result = await executeTool(call);\r\n\r\n if (isNavigate) {\r\n clearPendingAgentResume();\r\n }\r\n\r\n events.onToolResult?.(call.call_id, call.tool, result.result);\r\n results.push(result);\r\n }\r\n\r\n if (socket.readyState === WebSocket.OPEN) {\r\n socket.send(JSON.stringify({\r\n type: \"tool_results\",\r\n results,\r\n }));\r\n }\r\n return;\r\n }\r\n\r\n if (msgType === \"agent_done\") {\r\n finalReply = (data.final_reply as string) || \"\";\r\n const replyExpectsReply = data.expects_reply !== false;\r\n events.onAssistantDone?.(finalReply, replyExpectsReply);\r\n if (typeof data.session_id === \"string\") {\r\n events.onSessionId?.(data.session_id as string);\r\n }\r\n finish(finalReply);\r\n return;\r\n }\r\n\r\n if (msgType === \"error\") {\r\n const errMsg = (data.error as string) || \"Agent error\";\r\n errorEmitted = true;\r\n events.onError?.(errMsg);\r\n fail(new Error(errMsg));\r\n return;\r\n }\r\n };\r\n\r\n socket.onerror = () => {\r\n errorEmitted = true;\r\n events.onError?.(\"Agent WebSocket error\");\r\n fail(new Error(\"Agent WebSocket error\"));\r\n };\r\n socket.onclose = () => finish(finalReply);\r\n });\r\n\r\n activeSocket = null;\r\n\r\n // ── 2. TTS ────────────────────────────────────────────────\r\n if (isStopped || !assistantText) {\r\n if (!isStopped) {\r\n hideAgentCursor();\r\n }\r\n return resolve();\r\n }\r\n\r\n hideAgentCursor();\r\n await collectAndPlayTtsStreamed(\r\n baseUrl, assistantText, config.voice, Boolean(config.accessibilityMode),\r\n () => isStopped,\r\n (socket) => { activeSocket = socket; },\r\n (reader) => { activeReader = reader; },\r\n events.onAudioStateChange,\r\n );\r\n\r\n resolve();\r\n } catch (err) {\r\n if (!errorEmitted) {\r\n const msg = err instanceof Error ? err.message : String(err);\r\n events.onError?.(msg);\r\n }\r\n reject(err);\r\n } finally {\r\n activeReader?.cancel().catch(() => { });\r\n if (activeSocket && activeSocket.readyState <= WebSocket.OPEN) {\r\n activeSocket.close();\r\n }\r\n activeSocket = null;\r\n }\r\n });\r\n\r\n return {\r\n stop: () => {\r\n isStopped = true;\r\n stopActiveAudioPlayback();\r\n if (activeReader) activeReader.cancel().catch(() => { });\r\n if (activeSocket && activeSocket.readyState <= WebSocket.OPEN) {\r\n activeSocket.close();\r\n }\r\n },\r\n done: donePromise,\r\n };\r\n};\r\n\r\n// ── Agent Resume Stream (after page navigation reload) ──────────────\r\n//\r\n// When a navigate tool causes a full-page reload, the agent WS is lost.\r\n// This function opens a new WS with {type: \"resume\"}, sends the\r\n// completed tool results (including the navigate result with the new\r\n// page context), and continues the agent loop from where it left off.\r\n\r\nexport const agentResumeStream = (\r\n baseUrl: string,\r\n resumeState: PendingAgentResume,\r\n pageContext: string,\r\n events: AgentVoiceChatEvents,\r\n executeTool: (call: AgentToolCallInfo) => Promise<{ call_id: string; result: string }>,\r\n): StreamController => {\r\n let isStopped = false;\r\n let activeSocket: WebSocket | null = null;\r\n let activeReader: ReadableStreamDefaultReader<Uint8Array> | undefined;\r\n let errorEmitted = false;\r\n\r\n // Build tool results for the calls that were pending when the page reloaded.\r\n // Navigate results include the new page context; other tools that couldn't\r\n // execute get a descriptive skip message.\r\n const allResults = [...resumeState.completedResults];\r\n for (const tc of resumeState.pendingToolCalls) {\r\n if (allResults.some((r) => r.call_id === tc.call_id)) continue;\r\n if (tc.tool === \"navigate\") {\r\n allResults.push({\r\n call_id: tc.call_id,\r\n result: `Navigasyon tamamlandı. Şu anki sayfa: ${typeof window !== \"undefined\" ? window.location.href : \"\"}\\nSayfa bağlamı: ${pageContext}`,\r\n });\r\n } else {\r\n allResults.push({\r\n call_id: tc.call_id,\r\n result: \"Sayfa yeniden yüklendi, bu araç çalıştırılamadı.\",\r\n });\r\n }\r\n }\r\n\r\n const donePromise = new Promise<void>(async (resolve, reject) => {\r\n try {\r\n if (isStopped) return resolve();\r\n\r\n let effectiveSessionId = resumeState.sessionId;\r\n\r\n const assistantText = await new Promise<string>((agentResolve, agentReject) => {\r\n if (isStopped) { agentResolve(\"\"); return; }\r\n\r\n const wsUrl = toWebSocketUrl(baseUrl, \"/chat/agent/ws\");\r\n const socket = new WebSocket(wsUrl);\r\n activeSocket = socket;\r\n\r\n let finalReply = \"\";\r\n let resolved = false;\r\n let accumulatedDelta = \"\";\r\n let allIntermediateText = \"\";\r\n\r\n const finish = (reply: string) => {\r\n if (resolved) return;\r\n resolved = true;\r\n agentResolve(reply);\r\n };\r\n\r\n const fail = (error: Error) => {\r\n if (resolved) return;\r\n resolved = true;\r\n agentReject(error);\r\n };\r\n\r\n socket.onopen = () => {\r\n console.info(\"[Bulut] Agent WS resume connected\");\r\n socket.send(JSON.stringify({\r\n type: \"resume\",\r\n project_id: resumeState.projectId,\r\n session_id: resumeState.sessionId,\r\n model: resumeState.model,\r\n page_context: pageContext,\r\n accessibility_mode: resumeState.accessibilityMode,\r\n accumulated_delta: resumeState.accumulatedDelta || \"\",\r\n pending_tool_calls: resumeState.pendingToolCalls,\r\n tool_results: allResults,\r\n }));\r\n };\r\n\r\n socket.onmessage = async (event) => {\r\n let data: Record<string, unknown>;\r\n try {\r\n data = JSON.parse(String(event.data));\r\n } catch { return; }\r\n\r\n const msgType = data.type as string;\r\n\r\n if (msgType === \"session\" && typeof data.session_id === \"string\") {\r\n effectiveSessionId = data.session_id as string;\r\n events.onSessionId?.(effectiveSessionId);\r\n return;\r\n }\r\n\r\n if (msgType === \"iteration\") {\r\n events.onIteration?.(\r\n data.iteration as number,\r\n data.max_iterations as number,\r\n );\r\n return;\r\n }\r\n\r\n if (msgType === \"reply_delta\" && typeof data.delta === \"string\") {\r\n accumulatedDelta += data.delta;\r\n events.onAssistantDelta?.(data.delta);\r\n return;\r\n }\r\n\r\n if (msgType === \"tool_calls\" && Array.isArray(data.calls)) {\r\n const calls = data.calls as AgentToolCallInfo[];\r\n\r\n // Speak accumulated text before running tools\r\n if (accumulatedDelta.trim()) {\r\n events.onIntermediateReply?.(accumulatedDelta.trim());\r\n allIntermediateText += accumulatedDelta;\r\n }\r\n accumulatedDelta = \"\";\r\n\r\n events.onToolCalls?.(calls);\r\n\r\n const results: { call_id: string; result: string }[] = [];\r\n for (const call of calls) {\r\n const isNavigate = call.tool === \"navigate\";\r\n if (isNavigate) {\r\n savePendingAgentResume({\r\n sessionId: effectiveSessionId,\r\n projectId: resumeState.projectId,\r\n model: resumeState.model,\r\n voice: resumeState.voice,\r\n accessibilityMode: resumeState.accessibilityMode,\r\n pendingToolCalls: calls.map((c) => ({\r\n call_id: c.call_id,\r\n tool: c.tool,\r\n args: c.args,\r\n })),\r\n completedResults: [...results],\r\n accumulatedDelta: allIntermediateText || undefined,\r\n });\r\n }\r\n\r\n const result = await executeTool(call);\r\n\r\n if (isNavigate) {\r\n clearPendingAgentResume();\r\n }\r\n\r\n events.onToolResult?.(call.call_id, call.tool, result.result);\r\n results.push(result);\r\n }\r\n\r\n if (socket.readyState === WebSocket.OPEN) {\r\n socket.send(JSON.stringify({ type: \"tool_results\", results }));\r\n }\r\n return;\r\n }\r\n\r\n if (msgType === \"agent_done\") {\r\n finalReply = (data.final_reply as string) || \"\";\r\n const replyExpectsReply = data.expects_reply !== false;\r\n events.onAssistantDone?.(finalReply, replyExpectsReply);\r\n if (typeof data.session_id === \"string\") {\r\n events.onSessionId?.(data.session_id as string);\r\n }\r\n finish(finalReply);\r\n return;\r\n }\r\n\r\n if (msgType === \"error\") {\r\n const errMsg = (data.error as string) || \"Agent error\";\r\n errorEmitted = true;\r\n events.onError?.(errMsg);\r\n fail(new Error(errMsg));\r\n return;\r\n }\r\n };\r\n\r\n socket.onerror = () => {\r\n errorEmitted = true;\r\n events.onError?.(\"Agent WebSocket error\");\r\n fail(new Error(\"Agent WebSocket error\"));\r\n };\r\n\r\n socket.onclose = () => finish(finalReply);\r\n });\r\n\r\n activeSocket = null;\r\n\r\n // ── TTS ────────────────────────────────────────────────\r\n if (isStopped || !assistantText) {\r\n if (!isStopped) {\r\n hideAgentCursor();\r\n }\r\n return resolve();\r\n }\r\n\r\n console.info(`[Bulut] TTS start mode=resume voice=${resumeState.voice}`);\r\n hideAgentCursor();\r\n await collectAndPlayTtsStreamed(\r\n baseUrl, assistantText, resumeState.voice, Boolean(resumeState.accessibilityMode),\r\n () => isStopped,\r\n (socket) => { activeSocket = socket; },\r\n (reader) => { activeReader = reader; },\r\n events.onAudioStateChange,\r\n );\r\n\r\n resolve();\r\n } catch (err) {\r\n if (!errorEmitted) {\r\n const msg = err instanceof Error ? err.message : String(err);\r\n events.onError?.(msg);\r\n }\r\n reject(err);\r\n } finally {\r\n activeReader?.cancel().catch(() => { });\r\n if (activeSocket && activeSocket.readyState <= WebSocket.OPEN) {\r\n activeSocket.close();\r\n }\r\n activeSocket = null;\r\n }\r\n });\r\n\r\n return {\r\n stop: () => {\r\n isStopped = true;\r\n stopActiveAudioPlayback();\r\n if (activeReader) activeReader.cancel().catch(() => { });\r\n if (activeSocket && activeSocket.readyState <= WebSocket.OPEN) {\r\n activeSocket.close();\r\n }\r\n },\r\n done: donePromise,\r\n };\r\n};\r\n","import {\r\n completedSfxUrl,\r\n sentSfxUrl,\r\n thinkingSfxUrl,\r\n toolCallSfxUrl,\r\n} from \"../assets\";\r\n\r\nexport type SfxName = \"sent\" | \"thinking\" | \"toolCall\" | \"completed\";\r\n\r\nconst SFX_SOURCES: Record<SfxName, string> = {\r\n sent: sentSfxUrl,\r\n thinking: thinkingSfxUrl,\r\n toolCall: toolCallSfxUrl,\r\n completed: completedSfxUrl,\r\n};\r\n\r\nconst SFX_VOLUME = 0.5;\r\n\r\nclass SfxManager {\r\n private queue: SfxName[] = [];\r\n private active = false;\r\n\r\n private playNow(name: SfxName): Promise<void> {\r\n return new Promise((resolve) => {\r\n if (typeof window === \"undefined\") {\r\n resolve();\r\n return;\r\n }\r\n\r\n const audio = new Audio(SFX_SOURCES[name]);\r\n audio.preload = \"auto\";\r\n audio.volume = SFX_VOLUME;\r\n\r\n let settled = false;\r\n const finalize = () => {\r\n if (settled) return;\r\n settled = true;\r\n audio.onended = null;\r\n audio.onerror = null;\r\n resolve();\r\n };\r\n\r\n audio.onended = finalize;\r\n audio.onerror = finalize;\r\n void audio.play().catch(() => finalize());\r\n });\r\n }\r\n\r\n private async drain(): Promise<void> {\r\n if (this.active) return;\r\n this.active = true;\r\n try {\r\n while (this.queue.length > 0) {\r\n const next = this.queue.shift();\r\n if (!next) continue;\r\n await this.playNow(next);\r\n }\r\n } finally {\r\n this.active = false;\r\n }\r\n }\r\n\r\n playCue(name: SfxName): void {\r\n if (typeof window === \"undefined\") return;\r\n this.queue.push(name);\r\n if (!this.active) {\r\n void this.drain();\r\n }\r\n }\r\n}\r\n\r\nconst sfxManager = new SfxManager();\r\n\r\nexport const playCue = (name: SfxName): void => {\r\n sfxManager.playCue(name);\r\n};\r\n","export default \"data:audio/mpeg;base64,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\"","export default \"data:audio/mpeg;base64,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VVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVQ==\"","export default \"data:audio/mpeg;base64,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qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqgU7bdtbNa5MIRBHgnj4UR9JwIgVBwG4sGQ6iUOI9A8D4gD+UB2EkchSQR4JZYNzUyKpeTJzhe5G6uhMjIwPOFopGnGihQsgHRJAooSJEExgcJJAooD/+rJs9RAqj/URY7JpgTYKAAANIAAAAQAAAaQAAAAgAAA0gAAABIWQTUkROElmHxaqlm7Oz/9nzZqWcuLUkicacUfCakiJxZZlwtGjSini42af/s7P3dtyppyij0FopETgMDMJoLRJGlFHmWpJE4sukDVJVUxBTUUzLjk5LjVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVU=\"","export default \"data:audio/mpeg;base64,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BpGoUioUhyHQcjkOIhCCIQkg1EYApIxw2dKsgSFBRY7KF9qKJlrzBofwHJWHEHg1GskL2IUxVHoaRPKh2w3AlLxBIIwjQThaxUZGCNA3myVKnEbD2UScIrTc0hRFSim+MkJEMh44vC5KlhkaDxdSdJrFSxxeE4XSqyy8Jw33Jf/6smxwIbyA+HBovGsrZIgAAA0gAAABFwmixmwxKYgAADSAAAAEk0Dbmma1Emo9lEQli6+eTKIhEQfOqTqKypYZOqL1dKlhkZKLwnSaxUZKI0E4WsVKnEbD3SvFUpueyiVUhvySEiKnDi/9pov9VVNvpoqVTEFNRTMuOTkuNVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVf/6smw7EwAP8AAAaQAAAAgAAA0gAAABAAABpAAAACAAADSAAAAETEFNRTMuOTkuNVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVTEFNRTMuOTkuNVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVQ==\"","import { useEffect, useLayoutEffect, useRef, useState } from \"preact/hooks\";\r\nimport type { JSX } from \"preact\";\r\nimport type { BulutRuntimeConfig } from \"../index\";\r\nimport {\r\n agentTextChatStream,\r\n agentVoiceChatStream,\r\n agentResumeStream,\r\n startSttWebSocketStream,\r\n stopActiveAudioPlayback,\r\n speakText,\r\n type AudioStreamState,\r\n type StreamController,\r\n type AgentToolCallInfo,\r\n type SttWsController,\r\n} from \"../api/client\";\r\nimport {\r\n executeSingleToolCall,\r\n parseAgentResponse,\r\n getPendingAgentResume,\r\n clearPendingAgentResume,\r\n type ToolCallWithId,\r\n} from \"../agent/tools\";\r\nimport { getPageContext } from \"../agent/context\";\r\nimport {\r\n WINDOW_WIDTH,\r\n WINDOW_HEIGHT,\r\n POSITION_BOTTOM,\r\n POSITION_RIGHT,\r\n COLORS,\r\n TRANSITIONS,\r\n BORDER_RADIUS,\r\n SHADOW,\r\n} from \"../styles/constants\";\r\nimport {\r\n logoContent,\r\n arrowPathIconContent,\r\n commandLineIconContent,\r\n cursorArrowRaysIconContent,\r\n faceSmileIconContent,\r\n handRaisedIconContent,\r\n mapIconContent,\r\n microphoneOutlineIconContent,\r\n queueListIconContent,\r\n stopOutlineIconContent,\r\n xMarkIconContent,\r\n} from \"../assets\";\r\nimport { StreamingJsonParser } from \"../utils/streamingJson\";\r\nimport { playCue, type SfxName } from \"../audio/sfxManager\";\r\nimport { SvgIcon } from \"./SvgIcon\";\r\n\r\nexport interface ChatWindowHandle {\r\n startRecording: () => void;\r\n cancelRecording: () => void;\r\n stopTask: () => void;\r\n}\r\n\r\ninterface ChatWindowProps {\r\n onClose: () => void;\r\n config: BulutRuntimeConfig;\r\n accessibilityMode?: boolean;\r\n onAccessibilityToggle?: () => void;\r\n hidden?: boolean;\r\n actionsRef?: { current: ChatWindowHandle | null };\r\n onRecordingChange?: (recording: boolean) => void;\r\n onBusyChange?: (busy: boolean) => void;\r\n onPreviewChange?: (text: string | null) => void;\r\n}\r\n\r\ninterface Message {\r\n id: number;\r\n text: string;\r\n isUser: boolean;\r\n /** \"message\" (default) | \"tool\" for tool call indicators */\r\n type?: \"message\" | \"tool\";\r\n toolKind?: \"context\" | \"cursor\" | \"scroll\" | \"navigate\" | \"form\" | \"interact\" | \"unknown\";\r\n toolLabel?: string;\r\n toolCount?: number;\r\n}\r\n\r\ntype RecordingMode = \"vad\" | \"press\";\r\n\r\ntype StorageLike = {\r\n removeItem: (key: string) => void;\r\n};\r\n\r\nconst STORAGE_KEY = \"bulut_chat_history\";\r\nconst TIMESTAMP_KEY = \"bulut_chat_timestamp\";\r\nconst SESSION_ID_KEY = \"bulut_session_id\";\r\nconst TTL_MS = 5 * 60 * 1000;\r\nconst VAD_THRESHOLD = 0.06;\r\nconst SILENCE_DURATION_MS = 500;\r\nconst ACCESSIBILITY_MIN_SPEECH_DURATION_MS = 1500;\r\nexport const HOLD_THRESHOLD_MS = 250;\r\n\r\nconst STATUS_LABELS = {\r\n ready: \"Hazır\",\r\n loading: \"Bir saniye\",\r\n micInitializing: \"Mikrofonu hazırlıyorum\",\r\n listening: \"Sizi dinliyorum\",\r\n accessibilityActive: \"Erişilebilirlik Aktif\",\r\n transcribing: \"Düşünüyorum\",\r\n thinking: \"Düşünüyorum\",\r\n playingAudio: \".\",\r\n runningTools: \"Siteyle ilgileniyorum\",\r\n} as const;\r\n\r\nexport const getGreetingText = (agentName: string): string =>\r\n `Merhaba, ben ${agentName}. Bu web sayfasında neler yapalım?`;\r\n\r\nexport interface StatusFlags {\r\n isBusy: boolean;\r\n isRecording: boolean;\r\n isTranscribing: boolean;\r\n isThinking: boolean;\r\n isRenderingAudio: boolean;\r\n isPlayingAudio: boolean;\r\n isRunningTools: boolean;\r\n}\r\n\r\nexport const resolveStatusText = (flags: StatusFlags): string => {\r\n if (flags.isRecording) return STATUS_LABELS.listening;\r\n if (flags.isRunningTools) return STATUS_LABELS.runningTools;\r\n if (flags.isPlayingAudio) return STATUS_LABELS.playingAudio;\r\n if (flags.isThinking) return STATUS_LABELS.thinking;\r\n if (flags.isTranscribing) return STATUS_LABELS.transcribing;\r\n if (flags.isBusy) return STATUS_LABELS.loading;\r\n return STATUS_LABELS.ready;\r\n};\r\n\r\nexport const hasActiveStatus = (\r\n flags: StatusFlags,\r\n statusOverride: string | null,\r\n): boolean =>\r\n Boolean(\r\n statusOverride\r\n || flags.isBusy\r\n || flags.isRecording\r\n || flags.isTranscribing\r\n || flags.isThinking\r\n || flags.isRenderingAudio\r\n || flags.isPlayingAudio\r\n || flags.isRunningTools,\r\n );\r\n\r\nexport const formatDurationMs = (durationMs: number): string => {\r\n const totalSeconds = Math.max(0, Math.floor(durationMs / 1000));\r\n const minutes = Math.floor(totalSeconds / 60)\r\n .toString()\r\n .padStart(2, \"0\");\r\n const seconds = (totalSeconds % 60).toString().padStart(2, \"0\");\r\n return `${minutes}:${seconds}`;\r\n};\r\n\r\nexport const classifyMicGesture = (\r\n durationMs: number,\r\n thresholdMs: number = HOLD_THRESHOLD_MS,\r\n): \"tap\" | \"hold\" => (durationMs >= thresholdMs ? \"hold\" : \"tap\");\r\n\r\nexport const createInitialMessages = (agentName: string): Message[] => [\r\n {\r\n id: 1,\r\n text: getGreetingText(agentName),\r\n isUser: false,\r\n },\r\n];\r\n\r\nexport const clearPersistedChatState = (storage: StorageLike | null): void => {\r\n if (!storage) {\r\n return;\r\n }\r\n\r\n storage.removeItem(STORAGE_KEY);\r\n storage.removeItem(TIMESTAMP_KEY);\r\n storage.removeItem(SESSION_ID_KEY);\r\n};\r\n\r\nexport const scrollElementToBottom = (\r\n element: { scrollTop: number; scrollHeight: number } | null,\r\n): void => {\r\n if (!element) {\r\n return;\r\n }\r\n\r\n element.scrollTop = element.scrollHeight;\r\n};\r\n\r\nconst normalizeError = (error: unknown) => {\r\n if (error instanceof Error) {\r\n return error.message;\r\n }\r\n return \"Bilinmeyen hata\";\r\n};\r\n\r\nconst getNextMessageId = (messages: Message[]): number => {\r\n const maxId = messages.reduce((acc, message) => Math.max(acc, message.id), 0);\r\n return maxId + 1;\r\n};\r\n\r\nexport interface AssistantPayloadResolution {\r\n displayText: string;\r\n toolCalls: ReturnType<typeof parseAgentResponse>[\"toolCalls\"];\r\n}\r\n\r\nexport const resolveAssistantPayload = (\r\n assistantText: string,\r\n): AssistantPayloadResolution => {\r\n const parsed = parseAgentResponse(assistantText);\r\n return {\r\n displayText: parsed.reply || assistantText,\r\n toolCalls: parsed.toolCalls,\r\n };\r\n};\r\n\r\nexport const shouldAutoListenAfterAudio = (\r\n accessibilityMode: boolean,\r\n expectsReply: boolean,\r\n isRecording: boolean,\r\n isBusy: boolean,\r\n): boolean => (accessibilityMode || expectsReply) && !isRecording && !isBusy;\r\n\r\nexport const shouldAcceptVadSpeech = (\r\n speechDurationMs: number,\r\n enforceMinSpeechDuration: boolean,\r\n minSpeechDurationMs: number = ACCESSIBILITY_MIN_SPEECH_DURATION_MS,\r\n): boolean => !enforceMinSpeechDuration || speechDurationMs >= minSpeechDurationMs;\r\n\r\ninterface ToolIndicatorMessage {\r\n text: string;\r\n kind: \"context\" | \"cursor\" | \"scroll\" | \"navigate\" | \"form\" | \"interact\" | \"unknown\";\r\n}\r\n\r\nconst getToolIndicatorMessage = (\r\n call: AgentToolCallInfo,\r\n): ToolIndicatorMessage => {\r\n if (call.tool === \"getPageContext\") {\r\n return { text: \"Algılama\", kind: \"context\" };\r\n }\r\n if (call.tool === \"scroll\") {\r\n return { text: \"Kaydırma\", kind: \"scroll\" };\r\n }\r\n if (call.tool === \"navigate\") {\r\n const url = typeof call.args.url === \"string\" ? call.args.url.trim() : \"\";\r\n return {\r\n text: url ? `Sayfa Geçişi: ${url}` : \"Sayfa Geçişi\",\r\n kind: \"navigate\",\r\n };\r\n }\r\n if (call.tool === \"interact\" && call.args.action === \"move\") {\r\n return { text: \"Serbest İmleç\", kind: \"cursor\" };\r\n }\r\n if (call.tool === \"interact\" && call.args.action === \"type\") {\r\n return { text: \"Form Doldurma\", kind: \"form\" };\r\n }\r\n if (call.tool === \"interact\" && call.args.action === \"submit\") {\r\n return { text: \"Form Gönderme\", kind: \"form\" };\r\n }\r\n if (call.tool === \"interact\" && call.args.action === \"click\") {\r\n return { text: \"Tıklama\", kind: \"interact\" };\r\n }\r\n if (call.tool === \"interact\") {\r\n return { text: \"Etkileşim\", kind: \"interact\" };\r\n }\r\n return {\r\n text: call.tool || \"Araç\",\r\n kind: \"unknown\",\r\n };\r\n};\r\n\r\nexport const ChatWindow = ({\r\n onClose,\r\n config,\r\n accessibilityMode = false,\r\n onAccessibilityToggle,\r\n hidden = false,\r\n actionsRef,\r\n onRecordingChange,\r\n onBusyChange,\r\n onPreviewChange,\r\n}: ChatWindowProps) => {\r\n const [messages, setMessages] = useState<Message[]>(() => {\r\n if (typeof localStorage !== \"undefined\") {\r\n const saved = localStorage.getItem(STORAGE_KEY);\r\n const timestamp = localStorage.getItem(TIMESTAMP_KEY);\r\n\r\n if (saved && timestamp) {\r\n const timePassed = Date.now() - parseInt(timestamp, 10);\r\n if (timePassed < TTL_MS) {\r\n try {\r\n return JSON.parse(saved) as Message[];\r\n } catch {\r\n // Ignore parse error and continue with default.\r\n }\r\n } else {\r\n clearPersistedChatState(localStorage);\r\n }\r\n }\r\n }\r\n\r\n return createInitialMessages(config.agentName);\r\n });\r\n\r\n const [isBusy, setIsBusy] = useState(false);\r\n const [isRecording, setIsRecording] = useState(false);\r\n const [isTranscribing, setIsTranscribing] = useState(false);\r\n const [isThinking, setIsThinking] = useState(false);\r\n const [isRenderingAudio, setIsRenderingAudio] = useState(false);\r\n const [isPlayingAudio, setIsPlayingAudio] = useState(false);\r\n const [isRunningTools, setIsRunningTools] = useState(false);\r\n const [isMicPending, setIsMicPending] = useState(false);\r\n const [recordingDurationMs, setRecordingDurationMs] = useState(0);\r\n const [statusOverride, setStatusOverride] = useState<string | null>(null);\r\n const statusFlags: StatusFlags = {\r\n isBusy,\r\n isRecording,\r\n isTranscribing,\r\n isThinking,\r\n isRenderingAudio,\r\n isPlayingAudio,\r\n isRunningTools,\r\n };\r\n const resolvedStatusText = resolveStatusText(statusFlags);\r\n const showStatus = hasActiveStatus(statusFlags, statusOverride);\r\n const statusText = showStatus ? (statusOverride ?? resolvedStatusText) : STATUS_LABELS.ready;\r\n\r\n const isBusyRef = useRef(isBusy);\r\n const isRecordingRef = useRef(isRecording);\r\n\r\n const nextMessageIdRef = useRef(getNextMessageId(messages));\r\n const recorderRef = useRef<MediaRecorder | null>(null);\r\n const streamRef = useRef<MediaStream | null>(null);\r\n const audioChunksRef = useRef<BlobPart[]>([]);\r\n const activeStreamControllerRef = useRef<StreamController | null>(null);\r\n const sessionIdRef = useRef<string | null>(\r\n typeof localStorage !== \"undefined\"\r\n ? (() => {\r\n const ts = localStorage.getItem(TIMESTAMP_KEY);\r\n if (ts && Date.now() - parseInt(ts, 10) < TTL_MS) {\r\n return localStorage.getItem(SESSION_ID_KEY);\r\n }\r\n return null;\r\n })()\r\n : null,\r\n );\r\n\r\n const silenceStartRef = useRef<number | null>(null);\r\n const vadIntervalRef = useRef<number | null>(null);\r\n const audioContextRef = useRef<AudioContext | null>(null);\r\n const sourceRef = useRef<MediaStreamAudioSourceNode | null>(null);\r\n\r\n const discardNextRecordingRef = useRef(false);\r\n\r\n const micPressStartRef = useRef<number | null>(null);\r\n const micHoldTimeoutRef = useRef<number | null>(null);\r\n const micHoldTriggeredRef = useRef(false);\r\n const recordingModeRef = useRef<RecordingMode | null>(null);\r\n const pendingStopAfterStartRef = useRef(false);\r\n const startRecordingPendingRef = useRef(false);\r\n\r\n const assistantMessageIdRef = useRef<number | null>(null);\r\n const assistantTextBufferRef = useRef(\"\");\r\n const transcriptionReceivedRef = useRef(false);\r\n const assistantDoneReceivedRef = useRef(false);\r\n\r\n const recordingStartedAtRef = useRef<number | null>(null);\r\n const recordingTimerIntervalRef = useRef<number | null>(null);\r\n\r\n const messagesContainerRef = useRef<HTMLDivElement | null>(null);\r\n const messagesContentRef = useRef<HTMLDivElement | null>(null);\r\n\r\n const pendingUserTextRef = useRef<string | null>(null);\r\n const pendingAssistantTextRef = useRef<string>(\"\");\r\n const streamingJsonParserRef = useRef<StreamingJsonParser | null>(null);\r\n const awaitingAssistantResponseRef = useRef(false);\r\n const activeSttWsRef = useRef<SttWsController | null>(null);\r\n const liveTranscriptionMessageIdRef = useRef<number | null>(null);\r\n const liveTranscriptionTextRef = useRef(\"\");\r\n const autoListenSuppressedRef = useRef(false);\r\n const expectsReplyRef = useRef(true);\r\n const requestEpochRef = useRef(0);\r\n const sttSendCuePlayedRef = useRef(false);\r\n\r\n useEffect(() => {\r\n isBusyRef.current = isBusy;\r\n }, [isBusy]);\r\n\r\n useEffect(() => {\r\n isRecordingRef.current = isRecording;\r\n }, [isRecording]);\r\n\r\n // Report state changes to parent\r\n useEffect(() => { onRecordingChange?.(isRecording); }, [isRecording]);\r\n useEffect(() => { onBusyChange?.(isBusy); }, [isBusy]);\r\n\r\n // Derive and report preview text to parent\r\n useEffect(() => {\r\n if (!onPreviewChange) return;\r\n if (isRecording) {\r\n onPreviewChange(statusOverride ?? STATUS_LABELS.listening);\r\n return;\r\n }\r\n // When audio is rendering/playing, show the actual message text\r\n if (isRenderingAudio || isPlayingAudio) {\r\n const lastAssistant = [...messages].reverse().find(m => !m.isUser && m.type !== \"tool\");\r\n onPreviewChange(lastAssistant?.text ?? getGreetingText(config.agentName));\r\n return;\r\n }\r\n if (showStatus) {\r\n const st = statusOverride ?? resolveStatusText({\r\n isBusy,\r\n isRecording,\r\n isTranscribing,\r\n isThinking,\r\n isRenderingAudio,\r\n isPlayingAudio,\r\n isRunningTools,\r\n });\r\n onPreviewChange(st);\r\n return;\r\n }\r\n // Show last assistant message (or greeting)\r\n const lastAssistant = [...messages].reverse().find(m => !m.isUser && m.type !== \"tool\");\r\n onPreviewChange(lastAssistant?.text ?? getGreetingText(config.agentName));\r\n }, [\r\n isRecording,\r\n isBusy,\r\n isTranscribing,\r\n isThinking,\r\n isRunningTools,\r\n isPlayingAudio,\r\n isRenderingAudio,\r\n statusOverride,\r\n showStatus,\r\n messages,\r\n ]);\r\n\r\n const playSfx = (name: SfxName) => {\r\n playCue(name);\r\n };\r\n\r\n const beginRequestEpoch = () => {\r\n requestEpochRef.current += 1;\r\n return requestEpochRef.current;\r\n };\r\n\r\n const invalidateRequestEpoch = () => {\r\n requestEpochRef.current += 1;\r\n };\r\n\r\n const isCurrentRequestEpoch = (epoch: number): boolean =>\r\n requestEpochRef.current === epoch;\r\n\r\n const playSttSentCueOnce = () => {\r\n if (sttSendCuePlayedRef.current) {\r\n return;\r\n }\r\n sttSendCuePlayedRef.current = true;\r\n playSfx(\"sent\");\r\n };\r\n\r\n useEffect(() => {\r\n if (typeof localStorage !== \"undefined\") {\r\n localStorage.setItem(STORAGE_KEY, JSON.stringify(messages));\r\n localStorage.setItem(TIMESTAMP_KEY, Date.now().toString());\r\n }\r\n }, [messages]);\r\n\r\n const scrollMessagesToBottom = () => {\r\n scrollElementToBottom(messagesContainerRef.current);\r\n };\r\n\r\n useLayoutEffect(() => {\r\n scrollMessagesToBottom();\r\n }, [messages, statusText, isBusy, isRecording]);\r\n\r\n useEffect(() => {\r\n const content = messagesContentRef.current;\r\n if (!content || typeof ResizeObserver === \"undefined\") {\r\n return;\r\n }\r\n\r\n const observer = new ResizeObserver(() => {\r\n scrollMessagesToBottom();\r\n });\r\n\r\n observer.observe(content);\r\n return () => observer.disconnect();\r\n }, []);\r\n\r\n const stopRecordingTimer = () => {\r\n if (recordingTimerIntervalRef.current !== null) {\r\n window.clearInterval(recordingTimerIntervalRef.current);\r\n recordingTimerIntervalRef.current = null;\r\n }\r\n recordingStartedAtRef.current = null;\r\n };\r\n\r\n const startRecordingTimer = () => {\r\n stopRecordingTimer();\r\n recordingStartedAtRef.current = Date.now();\r\n setRecordingDurationMs(0);\r\n\r\n recordingTimerIntervalRef.current = window.setInterval(() => {\r\n const startedAt = recordingStartedAtRef.current;\r\n if (startedAt === null) {\r\n setRecordingDurationMs(0);\r\n return;\r\n }\r\n setRecordingDurationMs(Date.now() - startedAt);\r\n }, 200);\r\n };\r\n\r\n const resetProcessingFlags = () => {\r\n setIsTranscribing(false);\r\n setIsThinking(false);\r\n setIsRenderingAudio(false);\r\n setIsPlayingAudio(false);\r\n setIsRunningTools(false);\r\n setStatusOverride(null);\r\n assistantMessageIdRef.current = null;\r\n assistantTextBufferRef.current = \"\";\r\n transcriptionReceivedRef.current = false;\r\n assistantDoneReceivedRef.current = false;\r\n awaitingAssistantResponseRef.current = false;\r\n pendingUserTextRef.current = null;\r\n pendingAssistantTextRef.current = \"\";\r\n };\r\n\r\n const clearMicHoldTimeout = () => {\r\n if (micHoldTimeoutRef.current !== null) {\r\n window.clearTimeout(micHoldTimeoutRef.current);\r\n micHoldTimeoutRef.current = null;\r\n }\r\n };\r\n\r\n const cleanupVAD = () => {\r\n if (vadIntervalRef.current !== null) {\r\n clearInterval(vadIntervalRef.current);\r\n vadIntervalRef.current = null;\r\n }\r\n\r\n if (sourceRef.current) {\r\n sourceRef.current.disconnect();\r\n sourceRef.current = null;\r\n }\r\n\r\n if (audioContextRef.current) {\r\n audioContextRef.current.close().catch(() => {});\r\n audioContextRef.current = null;\r\n }\r\n\r\n silenceStartRef.current = null;\r\n };\r\n\r\n const stopStreamTracks = () => {\r\n if (!streamRef.current) {\r\n return;\r\n }\r\n\r\n streamRef.current.getTracks().forEach((track) => track.stop());\r\n streamRef.current = null;\r\n };\r\n\r\n const stopActiveStream = () => {\r\n if (!activeStreamControllerRef.current) {\r\n return;\r\n }\r\n\r\n activeStreamControllerRef.current.stop();\r\n activeStreamControllerRef.current = null;\r\n };\r\n\r\n const cancelActiveSttWs = () => {\r\n const activeSttWs = activeSttWsRef.current;\r\n activeSttWsRef.current = null;\r\n activeSttWs?.cancel();\r\n liveTranscriptionMessageIdRef.current = null;\r\n liveTranscriptionTextRef.current = \"\";\r\n };\r\n\r\n useEffect(\r\n () => () => {\r\n invalidateRequestEpoch();\r\n clearMicHoldTimeout();\r\n pendingStopAfterStartRef.current = false;\r\n\r\n stopActiveStream();\r\n stopActiveAudioPlayback();\r\n cancelActiveSttWs();\r\n cleanupVAD();\r\n stopStreamTracks();\r\n stopRecordingTimer();\r\n\r\n const recorder = recorderRef.current;\r\n if (recorder) {\r\n recorder.ondataavailable = null;\r\n recorder.onstop = null;\r\n recorder.onerror = null;\r\n if (recorder.state !== \"inactive\") {\r\n recorder.stop();\r\n }\r\n recorderRef.current = null;\r\n }\r\n\r\n cancelActiveSttWs();\r\n },\r\n [],\r\n );\r\n\r\n // ── Resume agent loop after full-page navigation ────────────────\r\n useEffect(() => {\r\n const resumeState = getPendingAgentResume();\r\n if (!resumeState) return;\r\n\r\n clearPendingAgentResume();\r\n console.info(\"[Bulut] Resuming agent after navigation\");\r\n\r\n // Restore session ID from resume state\r\n if (resumeState.sessionId) {\r\n sessionIdRef.current = resumeState.sessionId;\r\n if (typeof localStorage !== \"undefined\") {\r\n localStorage.setItem(SESSION_ID_KEY, resumeState.sessionId);\r\n }\r\n }\r\n\r\n const requestEpoch = beginRequestEpoch();\r\n setIsBusy(true);\r\n isBusyRef.current = true;\r\n setIsRunningTools(true);\r\n setStatusOverride(STATUS_LABELS.thinking);\r\n\r\n const freshPageContext = getPageContext().summary;\r\n\r\n const resumeToolExec = async (\r\n call: AgentToolCallInfo,\r\n ): Promise<{ call_id: string; result: string }> => {\r\n const toolCall: ToolCallWithId = {\r\n tool: call.tool as \"navigate\" | \"getPageContext\" | \"interact\" | \"scroll\",\r\n call_id: call.call_id,\r\n ...call.args,\r\n } as ToolCallWithId;\r\n return executeSingleToolCall(toolCall);\r\n };\r\n\r\n const controller = agentResumeStream(\r\n config.backendBaseUrl,\r\n resumeState,\r\n freshPageContext,\r\n {\r\n onSessionId: (sid) => {\r\n if (!isCurrentRequestEpoch(requestEpoch)) return;\r\n if (sid && sid !== sessionIdRef.current) {\r\n sessionIdRef.current = sid;\r\n if (typeof localStorage !== \"undefined\") {\r\n localStorage.setItem(SESSION_ID_KEY, sid);\r\n }\r\n }\r\n },\r\n onAssistantDelta: (delta) => {\r\n if (!isCurrentRequestEpoch(requestEpoch)) return;\r\n setIsRunningTools(false);\r\n setIsThinking(true);\r\n setStatusOverride(null);\r\n\r\n pendingAssistantTextRef.current += delta;\r\n\r\n if (assistantMessageIdRef.current === null) {\r\n assistantMessageIdRef.current = appendMessage(\r\n pendingAssistantTextRef.current,\r\n false,\r\n );\r\n } else {\r\n updateMessageText(\r\n assistantMessageIdRef.current,\r\n pendingAssistantTextRef.current,\r\n );\r\n }\r\n },\r\n onAssistantDone: (assistantText, expectsReply) => {\r\n if (!isCurrentRequestEpoch(requestEpoch)) return;\r\n playSfx(\"completed\");\r\n expectsReplyRef.current = expectsReply !== false;\r\n setStatusOverride(null);\r\n setIsThinking(false);\r\n setIsRenderingAudio(true);\r\n\r\n const finalDisplayText =\r\n assistantText || pendingAssistantTextRef.current;\r\n pendingAssistantTextRef.current = finalDisplayText;\r\n\r\n if (assistantMessageIdRef.current !== null) {\r\n updateMessageText(\r\n assistantMessageIdRef.current,\r\n finalDisplayText,\r\n );\r\n } else {\r\n assistantMessageIdRef.current = appendMessage(\r\n finalDisplayText,\r\n false,\r\n );\r\n }\r\n },\r\n onIntermediateReply: (text) => {\r\n if (!isCurrentRequestEpoch(requestEpoch)) return;\r\n void speakText(\r\n config.backendBaseUrl, text, config.voice,\r\n accessibilityMode, (state) => handleAudioStateChange(state, requestEpoch),\r\n ).catch((err) => console.warn(\"[Bulut] intermediate TTS failed\", err));\r\n },\r\n onToolCalls: (calls) => {\r\n if (!isCurrentRequestEpoch(requestEpoch)) return;\r\n if (calls.length > 0) {\r\n playSfx(\"toolCall\");\r\n }\r\n setIsRunningTools(true);\r\n setStatusOverride(STATUS_LABELS.runningTools);\r\n appendToolIndicatorMessages(calls);\r\n\r\n assistantMessageIdRef.current = null;\r\n pendingAssistantTextRef.current = \"\";\r\n },\r\n onToolResult: () => {},\r\n onIteration: () => {\r\n if (!isCurrentRequestEpoch(requestEpoch)) return;\r\n playSfx(\"thinking\");\r\n setIsThinking(true);\r\n setStatusOverride(STATUS_LABELS.thinking);\r\n },\r\n onAudioStateChange: (state) => {\r\n handleAudioStateChange(state, requestEpoch);\r\n },\r\n onError: (err) => {\r\n if (!isCurrentRequestEpoch(requestEpoch)) return;\r\n setStatusOverride(null);\r\n appendMessage(`Hata: ${err}`, false);\r\n },\r\n },\r\n resumeToolExec,\r\n );\r\n\r\n activeStreamControllerRef.current = controller;\r\n\r\n controller.done\r\n .catch(() => {})\r\n .finally(() => {\r\n if (!isCurrentRequestEpoch(requestEpoch)) return;\r\n setIsBusy(false);\r\n isBusyRef.current = false;\r\n setIsRunningTools(false);\r\n setIsThinking(false);\r\n setIsRenderingAudio(false);\r\n setIsPlayingAudio(false);\r\n setStatusOverride(null);\r\n pendingAssistantTextRef.current = \"\";\r\n assistantMessageIdRef.current = null;\r\n activeStreamControllerRef.current = null;\r\n\r\n if (\r\n !autoListenSuppressedRef.current &&\r\n shouldAutoListenAfterAudio(\r\n accessibilityMode,\r\n expectsReplyRef.current,\r\n isRecordingRef.current,\r\n false,\r\n )\r\n ) {\r\n void startRecording(\"vad\");\r\n }\r\n // Reset for next turn\r\n expectsReplyRef.current = true;\r\n });\r\n }, []); // eslint-disable-line react-hooks/exhaustive-deps\r\n\r\n const appendMessage = (\r\n text: string,\r\n isUser: boolean,\r\n options?: {\r\n type?: \"message\" | \"tool\";\r\n toolKind?: Message[\"toolKind\"];\r\n toolLabel?: string;\r\n toolCount?: number;\r\n },\r\n ): number => {\r\n const id = nextMessageIdRef.current++;\r\n setMessages((previous) => [\r\n ...previous,\r\n {\r\n id,\r\n text,\r\n isUser,\r\n type: options?.type,\r\n toolKind: options?.toolKind,\r\n toolLabel: options?.toolLabel,\r\n toolCount: options?.toolCount,\r\n },\r\n ]);\r\n return id;\r\n };\r\n\r\n const appendToolIndicatorMessages = (calls: AgentToolCallInfo[]) => {\r\n setMessages((previous) => {\r\n const next = [...previous];\r\n\r\n for (const call of calls) {\r\n const indicator = getToolIndicatorMessage(call);\r\n const last = next[next.length - 1];\r\n const previousToolText = typeof last?.text === \"string\"\r\n ? last.text.replace(/\\s+\\(\\d+\\)$/, \"\")\r\n : \"\";\r\n\r\n if (\r\n last\r\n && !last.isUser\r\n && last.type === \"tool\"\r\n && previousToolText === indicator.text\r\n ) {\r\n const extractedCount = Number.parseInt(\r\n (last.text.match(/\\((\\d+)\\)\\s*$/)?.[1] ?? \"1\"),\r\n 10,\r\n );\r\n const safeCurrentCount = Number.isFinite(extractedCount) ? extractedCount : 1;\r\n const nextCount = safeCurrentCount + 1;\r\n const baseLabel = previousToolText || indicator.text;\r\n next[next.length - 1] = {\r\n ...last,\r\n toolLabel: baseLabel,\r\n toolCount: nextCount,\r\n text: `${baseLabel} (${nextCount})`,\r\n };\r\n continue;\r\n }\r\n\r\n const id = nextMessageIdRef.current++;\r\n next.push({\r\n id,\r\n text: indicator.text,\r\n isUser: false,\r\n type: \"tool\",\r\n toolKind: indicator.kind,\r\n toolLabel: indicator.text,\r\n toolCount: 1,\r\n });\r\n }\r\n\r\n // Force-persist messages to localStorage immediately so they\r\n // survive a full-page navigate that may happen next frame.\r\n if (typeof localStorage !== \"undefined\") {\r\n try {\r\n localStorage.setItem(STORAGE_KEY, JSON.stringify(next));\r\n localStorage.setItem(TIMESTAMP_KEY, Date.now().toString());\r\n } catch { /* ignore full/blocked storage */ }\r\n }\r\n\r\n return next;\r\n });\r\n };\r\n\r\n const updateMessageText = (id: number, text: string) => {\r\n setMessages((previous) =>\r\n previous.map((message) =>\r\n message.id === id ? { ...message, text } : message,\r\n ),\r\n );\r\n };\r\n\r\n const upsertLiveUserTranscription = (text: string) => {\r\n const normalized = text.trim();\r\n if (!normalized) {\r\n return;\r\n }\r\n liveTranscriptionTextRef.current = normalized;\r\n if (liveTranscriptionMessageIdRef.current === null) {\r\n liveTranscriptionMessageIdRef.current = appendMessage(normalized, true);\r\n return;\r\n }\r\n updateMessageText(liveTranscriptionMessageIdRef.current, normalized);\r\n };\r\n\r\n const clearLiveUserTranscriptionState = () => {\r\n liveTranscriptionMessageIdRef.current = null;\r\n liveTranscriptionTextRef.current = \"\";\r\n };\r\n\r\n const handleAudioStateChange = (state: AudioStreamState, requestEpoch?: number) => {\r\n if (typeof requestEpoch === \"number\" && !isCurrentRequestEpoch(requestEpoch)) {\r\n return;\r\n }\r\n\r\n if (state === \"rendering\") {\r\n setIsRenderingAudio(true);\r\n setIsPlayingAudio(false);\r\n return;\r\n }\r\n\r\n if (state === \"playing\") {\r\n setIsRenderingAudio(false);\r\n setIsPlayingAudio(true);\r\n return;\r\n }\r\n\r\n if (state === \"fallback\") {\r\n setIsRenderingAudio(true);\r\n setIsPlayingAudio(false);\r\n return;\r\n }\r\n\r\n if (state === \"done\") {\r\n setIsRenderingAudio(false);\r\n setIsPlayingAudio(false);\r\n return;\r\n }\r\n\r\n setIsRenderingAudio(false);\r\n setIsPlayingAudio(false);\r\n };\r\n\r\n const finalizeStreamCycle = (requestEpoch?: number) => {\r\n if (typeof requestEpoch === \"number\" && !isCurrentRequestEpoch(requestEpoch)) {\r\n return;\r\n }\r\n\r\n awaitingAssistantResponseRef.current = false;\r\n setStatusOverride(null);\r\n setIsBusy(false);\r\n isBusyRef.current = false;\r\n setIsTranscribing(false);\r\n setIsThinking(false);\r\n setIsRenderingAudio(false);\r\n setIsPlayingAudio(false);\r\n setIsRunningTools(false);\r\n pendingUserTextRef.current = null;\r\n pendingAssistantTextRef.current = \"\";\r\n assistantMessageIdRef.current = null;\r\n if (activeStreamControllerRef.current) {\r\n activeStreamControllerRef.current = null;\r\n }\r\n if (\r\n !autoListenSuppressedRef.current &&\r\n shouldAutoListenAfterAudio(\r\n accessibilityMode,\r\n expectsReplyRef.current,\r\n isRecordingRef.current,\r\n false,\r\n )\r\n ) {\r\n console.info(\"[Bulut] chat-window auto-listen trigger after stream completion\");\r\n void startRecording(\"vad\");\r\n }\r\n // Reset for next turn\r\n expectsReplyRef.current = true;\r\n };\r\n\r\n const runAgentForUserText = async (userText: string) => {\r\n if (!config.projectId) {\r\n appendMessage(\"Hata: Project ID yapılandırılmamış.\", false);\r\n return;\r\n }\r\n\r\n const normalizedUserText = userText.trim();\r\n if (!normalizedUserText) {\r\n appendMessage(\"Ses kaydı metne dönüştürülemedi. Lütfen tekrar deneyin.\", false);\r\n return;\r\n }\r\n\r\n const requestEpoch = beginRequestEpoch();\r\n setIsBusy(true);\r\n isBusyRef.current = true;\r\n setIsTranscribing(false);\r\n setIsThinking(true);\r\n setIsRenderingAudio(false);\r\n setIsPlayingAudio(false);\r\n setIsRunningTools(false);\r\n setStatusOverride(STATUS_LABELS.thinking);\r\n awaitingAssistantResponseRef.current = true;\r\n\r\n try {\r\n pendingUserTextRef.current = normalizedUserText;\r\n upsertLiveUserTranscription(normalizedUserText);\r\n clearLiveUserTranscriptionState();\r\n\r\n stopActiveStream();\r\n const pageContext = getPageContext().summary;\r\n\r\n const handleToolExecution = async (\r\n call: AgentToolCallInfo,\r\n ): Promise<{ call_id: string; result: string }> => {\r\n const toolCall: ToolCallWithId = {\r\n tool: call.tool as\r\n | \"navigate\"\r\n | \"getPageContext\"\r\n | \"interact\"\r\n | \"scroll\",\r\n call_id: call.call_id,\r\n ...call.args,\r\n } as ToolCallWithId;\r\n return executeSingleToolCall(toolCall);\r\n };\r\n\r\n const controller = agentTextChatStream(\r\n config.backendBaseUrl,\r\n normalizedUserText,\r\n config.projectId,\r\n sessionIdRef.current,\r\n {\r\n model: config.model,\r\n voice: config.voice,\r\n pageContext,\r\n accessibilityMode,\r\n },\r\n {\r\n onSessionId: (sid) => {\r\n if (!isCurrentRequestEpoch(requestEpoch)) return;\r\n if (sid && sid !== sessionIdRef.current) {\r\n sessionIdRef.current = sid;\r\n if (typeof localStorage !== \"undefined\") {\r\n localStorage.setItem(SESSION_ID_KEY, sid);\r\n }\r\n }\r\n },\r\n onAssistantDelta: (delta) => {\r\n if (!isCurrentRequestEpoch(requestEpoch)) return;\r\n setIsTranscribing(false);\r\n setIsThinking(true);\r\n setIsRunningTools(false);\r\n if (awaitingAssistantResponseRef.current) {\r\n awaitingAssistantResponseRef.current = false;\r\n setStatusOverride(null);\r\n }\r\n\r\n pendingAssistantTextRef.current += delta;\r\n\r\n if (assistantMessageIdRef.current === null) {\r\n assistantMessageIdRef.current = appendMessage(\r\n pendingAssistantTextRef.current,\r\n false,\r\n );\r\n } else {\r\n updateMessageText(\r\n assistantMessageIdRef.current,\r\n pendingAssistantTextRef.current,\r\n );\r\n }\r\n },\r\n onAssistantDone: (assistantText, expectsReply) => {\r\n if (!isCurrentRequestEpoch(requestEpoch)) return;\r\n playSfx(\"completed\");\r\n expectsReplyRef.current = expectsReply !== false;\r\n awaitingAssistantResponseRef.current = false;\r\n setStatusOverride(null);\r\n setIsThinking(false);\r\n setIsRenderingAudio(true);\r\n\r\n const finalDisplayText = assistantText || pendingAssistantTextRef.current;\r\n pendingAssistantTextRef.current = finalDisplayText;\r\n\r\n if (assistantMessageIdRef.current !== null) {\r\n updateMessageText(\r\n assistantMessageIdRef.current,\r\n finalDisplayText,\r\n );\r\n } else {\r\n assistantMessageIdRef.current = appendMessage(\r\n finalDisplayText,\r\n false,\r\n );\r\n }\r\n },\r\n onIntermediateReply: (text) => {\r\n if (!isCurrentRequestEpoch(requestEpoch)) return;\r\n void speakText(\r\n config.backendBaseUrl, text, config.voice,\r\n accessibilityMode, (state) => handleAudioStateChange(state, requestEpoch),\r\n ).catch((err) => console.warn(\"[Bulut] intermediate TTS failed\", err));\r\n },\r\n onToolCalls: (calls) => {\r\n if (!isCurrentRequestEpoch(requestEpoch)) return;\r\n if (calls.length > 0) {\r\n playSfx(\"toolCall\");\r\n }\r\n setIsRunningTools(true);\r\n setStatusOverride(STATUS_LABELS.runningTools);\r\n appendToolIndicatorMessages(calls);\r\n\r\n assistantMessageIdRef.current = null;\r\n pendingAssistantTextRef.current = \"\";\r\n },\r\n onToolResult: () => {},\r\n onIteration: () => {\r\n if (!isCurrentRequestEpoch(requestEpoch)) return;\r\n playSfx(\"thinking\");\r\n setIsThinking(true);\r\n setStatusOverride(STATUS_LABELS.thinking);\r\n },\r\n onAudioStateChange: (state) => {\r\n handleAudioStateChange(state, requestEpoch);\r\n },\r\n onError: (err) => {\r\n if (!isCurrentRequestEpoch(requestEpoch)) return;\r\n awaitingAssistantResponseRef.current = false;\r\n setStatusOverride(null);\r\n appendMessage(`Hata: ${err}`, false);\r\n },\r\n },\r\n handleToolExecution,\r\n );\r\n\r\n activeStreamControllerRef.current = controller;\r\n await controller.done;\r\n } catch (error) {\r\n if (!isCurrentRequestEpoch(requestEpoch)) return;\r\n awaitingAssistantResponseRef.current = false;\r\n setStatusOverride(null);\r\n if (error instanceof Error) {\r\n appendMessage(`Hata: ${error.message}`, false);\r\n }\r\n } finally {\r\n finalizeStreamCycle(requestEpoch);\r\n }\r\n };\r\n\r\n const handleAudioBlob = async (blob: Blob) => {\r\n if (!config.projectId) {\r\n appendMessage(\"Hata: Project ID yapılandırılmamış.\", false);\r\n return;\r\n }\r\n\r\n const requestEpoch = beginRequestEpoch();\r\n setIsBusy(true);\r\n isBusyRef.current = true;\r\n setIsTranscribing(true);\r\n setIsThinking(false);\r\n setIsRenderingAudio(false);\r\n setIsPlayingAudio(false);\r\n setIsRunningTools(false);\r\n resetProcessingFlags(); // Start fresh\r\n setStatusOverride(STATUS_LABELS.thinking);\r\n awaitingAssistantResponseRef.current = true;\r\n\r\n try {\r\n const fileType = blob.type || \"audio/webm\";\r\n const extension = fileType.includes(\"ogg\")\r\n ? \"ogg\"\r\n : fileType.includes(\"wav\")\r\n ? \"wav\"\r\n : fileType.includes(\"mpeg\") || fileType.includes(\"mp3\")\r\n ? \"mp3\"\r\n : \"webm\";\r\n const file = new File([blob], `voice-input.${extension}`, {\r\n type: fileType,\r\n });\r\n\r\n stopActiveStream();\r\n\r\n const pageContext = getPageContext().summary;\r\n\r\n // Helper: bridge an AgentToolCallInfo to a ToolCallWithId\r\n const handleToolExecution = async (\r\n call: AgentToolCallInfo,\r\n ): Promise<{ call_id: string; result: string }> => {\r\n const toolCall: ToolCallWithId = {\r\n tool: call.tool as\r\n | \"navigate\"\r\n | \"getPageContext\"\r\n | \"interact\"\r\n | \"scroll\",\r\n call_id: call.call_id,\r\n ...call.args,\r\n } as ToolCallWithId;\r\n return executeSingleToolCall(toolCall);\r\n };\r\n\r\n const controller = agentVoiceChatStream(\r\n config.backendBaseUrl,\r\n file,\r\n config.projectId,\r\n sessionIdRef.current,\r\n {\r\n model: config.model,\r\n voice: config.voice,\r\n pageContext,\r\n accessibilityMode,\r\n },\r\n {\r\n onSttRequestSent: () => {\r\n if (!isCurrentRequestEpoch(requestEpoch)) return;\r\n playSttSentCueOnce();\r\n },\r\n onTranscription: (data) => {\r\n if (!isCurrentRequestEpoch(requestEpoch)) return;\r\n if (data.session_id && data.session_id !== sessionIdRef.current) {\r\n sessionIdRef.current = data.session_id;\r\n if (typeof localStorage !== \"undefined\") {\r\n localStorage.setItem(SESSION_ID_KEY, data.session_id);\r\n }\r\n }\r\n\r\n const normalized = data.user_text.trim();\r\n if (normalized) {\r\n const previousUserText = pendingUserTextRef.current;\r\n pendingUserTextRef.current = normalized;\r\n if (liveTranscriptionMessageIdRef.current !== null) {\r\n updateMessageText(liveTranscriptionMessageIdRef.current, normalized);\r\n clearLiveUserTranscriptionState();\r\n } else if (previousUserText !== normalized) {\r\n appendMessage(normalized, true);\r\n }\r\n }\r\n\r\n setIsTranscribing(false);\r\n setIsThinking(true);\r\n setStatusOverride(STATUS_LABELS.thinking);\r\n },\r\n onSessionId: (sid) => {\r\n if (!isCurrentRequestEpoch(requestEpoch)) return;\r\n if (sid && sid !== sessionIdRef.current) {\r\n sessionIdRef.current = sid;\r\n if (typeof localStorage !== \"undefined\") {\r\n localStorage.setItem(SESSION_ID_KEY, sid);\r\n }\r\n }\r\n },\r\n onAssistantDelta: (delta) => {\r\n if (!isCurrentRequestEpoch(requestEpoch)) return;\r\n setIsTranscribing(false);\r\n setIsThinking(true);\r\n setIsRunningTools(false);\r\n if (awaitingAssistantResponseRef.current) {\r\n awaitingAssistantResponseRef.current = false;\r\n setStatusOverride(null);\r\n }\r\n\r\n // Agent returns plain text (not JSON), stream it directly\r\n pendingAssistantTextRef.current += delta;\r\n\r\n if (assistantMessageIdRef.current === null) {\r\n assistantMessageIdRef.current = appendMessage(\r\n pendingAssistantTextRef.current,\r\n false,\r\n );\r\n } else {\r\n updateMessageText(\r\n assistantMessageIdRef.current,\r\n pendingAssistantTextRef.current,\r\n );\r\n }\r\n },\r\n onAssistantDone: (assistantText, expectsReply) => {\r\n if (!isCurrentRequestEpoch(requestEpoch)) return;\r\n playSfx(\"completed\");\r\n expectsReplyRef.current = expectsReply !== false;\r\n awaitingAssistantResponseRef.current = false;\r\n setStatusOverride(null);\r\n setIsThinking(false);\r\n setIsRenderingAudio(true);\r\n\r\n const finalDisplayText =\r\n assistantText || pendingAssistantTextRef.current;\r\n\r\n streamingJsonParserRef.current = null;\r\n pendingAssistantTextRef.current = finalDisplayText;\r\n\r\n if (assistantMessageIdRef.current !== null) {\r\n updateMessageText(\r\n assistantMessageIdRef.current,\r\n finalDisplayText,\r\n );\r\n } else {\r\n assistantMessageIdRef.current = appendMessage(\r\n finalDisplayText,\r\n false,\r\n );\r\n }\r\n },\r\n onIntermediateReply: (text) => {\r\n if (!isCurrentRequestEpoch(requestEpoch)) return;\r\n void speakText(\r\n config.backendBaseUrl, text, config.voice,\r\n accessibilityMode, (state) => handleAudioStateChange(state, requestEpoch),\r\n ).catch((err) => console.warn(\"[Bulut] intermediate TTS failed\", err));\r\n },\r\n onToolCalls: (calls) => {\r\n if (!isCurrentRequestEpoch(requestEpoch)) return;\r\n if (calls.length > 0) {\r\n playSfx(\"toolCall\");\r\n }\r\n setIsRunningTools(true);\r\n setStatusOverride(STATUS_LABELS.runningTools);\r\n appendToolIndicatorMessages(calls);\r\n assistantMessageIdRef.current = null;\r\n pendingAssistantTextRef.current = \"\";\r\n },\r\n onToolResult: (_callId, _toolName, _result) => {\r\n // Tool result sent back to agent automatically.\r\n // Could display detailed result here if needed.\r\n },\r\n onIteration: (_iteration, _maxIterations) => {\r\n if (!isCurrentRequestEpoch(requestEpoch)) return;\r\n // Agent started a new reasoning iteration\r\n playSfx(\"thinking\");\r\n setIsThinking(true);\r\n setStatusOverride(STATUS_LABELS.thinking);\r\n },\r\n onAudioStateChange: (state) => {\r\n handleAudioStateChange(state, requestEpoch);\r\n },\r\n onError: (err) => {\r\n if (!isCurrentRequestEpoch(requestEpoch)) return;\r\n awaitingAssistantResponseRef.current = false;\r\n setStatusOverride(null);\r\n appendMessage(`Hata: ${err}`, false);\r\n },\r\n },\r\n handleToolExecution,\r\n );\r\n\r\n activeStreamControllerRef.current = controller;\r\n await controller.done;\r\n\r\n // Safety: Ensure messages are flushed if not already\r\n // (e.g. if audio 'done' event didn't fire for some reason or there was no audio)\r\n /* if (pendingUserTextRef.current || pendingAssistantTextRef.current) {\r\n // flushPendingMessages(); // Removed as we stream now\r\n } */\r\n } catch (error) {\r\n if (!isCurrentRequestEpoch(requestEpoch)) return;\r\n // Error already shown via onError callback — don't duplicate\r\n awaitingAssistantResponseRef.current = false;\r\n setStatusOverride(null);\r\n } finally {\r\n finalizeStreamCycle(requestEpoch);\r\n }\r\n };\r\n\r\n const stopRecording = (options?: { discard?: boolean }) => {\r\n const recorder = recorderRef.current;\r\n if (!recorder || recorder.state === \"inactive\") {\r\n return;\r\n }\r\n\r\n if (options?.discard) {\r\n discardNextRecordingRef.current = true;\r\n }\r\n\r\n cleanupVAD();\r\n recorder.stop();\r\n };\r\n\r\n const setupVAD = (stream: MediaStream, recorder: MediaRecorder) => {\r\n const AudioCtx =\r\n window.AudioContext ||\r\n (window as Window & { webkitAudioContext?: typeof AudioContext })\r\n .webkitAudioContext;\r\n\r\n if (!AudioCtx) {\r\n return;\r\n }\r\n\r\n const context = new AudioCtx();\r\n audioContextRef.current = context;\r\n\r\n const analyser = context.createAnalyser();\r\n analyser.fftSize = 256;\r\n\r\n const source = context.createMediaStreamSource(stream);\r\n sourceRef.current = source;\r\n source.connect(analyser);\r\n\r\n const dataArray = new Uint8Array(analyser.frequencyBinCount);\r\n silenceStartRef.current = null;\r\n let speechDetected = false;\r\n let speechStartedAt: number | null = null;\r\n const enforceMinSpeechDuration = accessibilityMode;\r\n\r\n vadIntervalRef.current = window.setInterval(() => {\r\n if (!isRecordingRef.current || recorder.state === \"inactive\") {\r\n cleanupVAD();\r\n return;\r\n }\r\n\r\n analyser.getByteFrequencyData(dataArray);\r\n\r\n let sum = 0;\r\n for (const value of dataArray) {\r\n sum += value;\r\n }\r\n const average = sum / dataArray.length;\r\n const volume = average / 255;\r\n\r\n if (volume < VAD_THRESHOLD) {\r\n if (!speechDetected) {\r\n speechStartedAt = null;\r\n silenceStartRef.current = null;\r\n return;\r\n }\r\n\r\n if (silenceStartRef.current === null) {\r\n silenceStartRef.current = Date.now();\r\n return;\r\n }\r\n\r\n const silenceDuration = Date.now() - silenceStartRef.current;\r\n if (speechDetected && silenceDuration > SILENCE_DURATION_MS) {\r\n stopRecording();\r\n }\r\n return;\r\n }\r\n\r\n silenceStartRef.current = null;\r\n if (speechStartedAt === null) {\r\n speechStartedAt = Date.now();\r\n }\r\n\r\n if (!speechDetected) {\r\n const speechDuration = Date.now() - speechStartedAt;\r\n if (shouldAcceptVadSpeech(speechDuration, enforceMinSpeechDuration)) {\r\n speechDetected = true;\r\n if (enforceMinSpeechDuration) {\r\n setStatusOverride(STATUS_LABELS.listening);\r\n }\r\n }\r\n }\r\n }, 50);\r\n };\r\n\r\n const startRecording = async (mode: RecordingMode) => {\r\n if (\r\n isBusyRef.current ||\r\n isRecordingRef.current ||\r\n startRecordingPendingRef.current\r\n ) {\r\n return;\r\n }\r\n\r\n setStatusOverride(STATUS_LABELS.micInitializing);\r\n setIsMicPending(true);\r\n\r\n if (!navigator.mediaDevices?.getUserMedia) {\r\n setStatusOverride(null);\r\n setIsMicPending(false);\r\n appendMessage(\"Bu tarayıcıda mikrofon kullanılamıyor.\", false);\r\n return;\r\n }\r\n\r\n if (typeof MediaRecorder === \"undefined\") {\r\n setStatusOverride(null);\r\n setIsMicPending(false);\r\n appendMessage(\"Bu tarayıcıda MediaRecorder desteklenmiyor.\", false);\r\n return;\r\n }\r\n\r\n startRecordingPendingRef.current = true;\r\n\r\n try {\r\n const stream = await navigator.mediaDevices.getUserMedia({ audio: true });\r\n streamRef.current = stream;\r\n\r\n // Use low bitrate for speech — opus handles voice well at 16-24 kbps\r\n // and produces ~4-5x smaller payloads, speeding up the upload to fal.\r\n const recorderOptions: MediaRecorderOptions = {\r\n audioBitsPerSecond: 16_000,\r\n };\r\n\r\n // Prefer opus-in-ogg (smaller container) → opus-in-webm → browser default\r\n const preferredMimeTypes = [\r\n \"audio/ogg;codecs=opus\",\r\n \"audio/webm;codecs=opus\",\r\n \"audio/webm\",\r\n ];\r\n for (const mime of preferredMimeTypes) {\r\n if (MediaRecorder.isTypeSupported(mime)) {\r\n recorderOptions.mimeType = mime;\r\n break;\r\n }\r\n }\r\n\r\n const recorder = new MediaRecorder(stream, recorderOptions);\r\n recorderRef.current = recorder;\r\n audioChunksRef.current = [];\r\n clearLiveUserTranscriptionState();\r\n sttSendCuePlayedRef.current = false;\r\n\r\n const sttMimeType = (recorder.mimeType || recorderOptions.mimeType || \"audio/webm\")\r\n .split(\";\")[0]\r\n .trim() || \"audio/webm\";\r\n\r\n const sttWsController = startSttWebSocketStream(\r\n config.backendBaseUrl,\r\n {\r\n projectId: config.projectId,\r\n sessionId: sessionIdRef.current,\r\n language: \"tr\",\r\n mimeType: sttMimeType,\r\n },\r\n {\r\n onSessionId: (sid) => {\r\n if (!sid || sid === sessionIdRef.current) {\r\n return;\r\n }\r\n sessionIdRef.current = sid;\r\n if (typeof localStorage !== \"undefined\") {\r\n localStorage.setItem(SESSION_ID_KEY, sid);\r\n }\r\n },\r\n onPartial: ({ text }) => {\r\n if (!text.trim()) {\r\n return;\r\n }\r\n upsertLiveUserTranscription(text);\r\n },\r\n },\r\n );\r\n activeSttWsRef.current = sttWsController;\r\n\r\n recorder.ondataavailable = (event) => {\r\n if (event.data.size > 0) {\r\n audioChunksRef.current.push(event.data);\r\n if (activeSttWsRef.current) {\r\n void activeSttWsRef.current.pushChunk(event.data).catch((error) => {\r\n console.warn(\r\n `[Bulut] STT WS chunk send failed: ${error instanceof Error ? error.message : String(error)}`,\r\n );\r\n });\r\n }\r\n }\r\n };\r\n\r\n recorder.onerror = () => {\r\n appendMessage(\"Mikrofon kaydı sırasında bir hata oluştu.\", false);\r\n };\r\n\r\n recorder.onstop = async () => {\r\n setIsRecording(false);\r\n isRecordingRef.current = false;\r\n recordingModeRef.current = null;\r\n stopRecordingTimer();\r\n\r\n cleanupVAD();\r\n stopStreamTracks();\r\n\r\n const shouldDiscard = discardNextRecordingRef.current;\r\n discardNextRecordingRef.current = false;\r\n\r\n const blob = new Blob(audioChunksRef.current, {\r\n type: recorder.mimeType || \"audio/webm\",\r\n });\r\n audioChunksRef.current = [];\r\n\r\n const currentSttWs = activeSttWsRef.current;\r\n activeSttWsRef.current = null;\r\n\r\n if (shouldDiscard) {\r\n currentSttWs?.cancel();\r\n clearLiveUserTranscriptionState();\r\n setStatusOverride(null);\r\n return;\r\n }\r\n\r\n if (blob.size === 0) {\r\n currentSttWs?.cancel();\r\n clearLiveUserTranscriptionState();\r\n setStatusOverride(null);\r\n appendMessage(\"Ses kaydı alınamadı. Lütfen tekrar deneyin.\", false);\r\n return;\r\n }\r\n\r\n setIsTranscribing(true);\r\n setStatusOverride(STATUS_LABELS.transcribing);\r\n\r\n try {\r\n if (currentSttWs) {\r\n playSttSentCueOnce();\r\n const sttResult = await currentSttWs.stop();\r\n if (sttResult.session_id && sttResult.session_id !== sessionIdRef.current) {\r\n sessionIdRef.current = sttResult.session_id;\r\n if (typeof localStorage !== \"undefined\") {\r\n localStorage.setItem(SESSION_ID_KEY, sttResult.session_id);\r\n }\r\n }\r\n if (sttResult.text.trim()) {\r\n upsertLiveUserTranscription(sttResult.text);\r\n setStatusOverride(STATUS_LABELS.thinking);\r\n await runAgentForUserText(sttResult.text);\r\n return;\r\n }\r\n }\r\n } catch (error) {\r\n console.warn(\r\n `[Bulut] STT WS finalization failed, falling back to HTTP POST /chat/stt: ${error instanceof Error ? error.message : String(error)}`,\r\n );\r\n } finally {\r\n clearLiveUserTranscriptionState();\r\n }\r\n\r\n console.info(\"[Bulut] Using HTTP POST fallback for STT (streaming WS did not succeed)\");\r\n setStatusOverride(STATUS_LABELS.thinking);\r\n await handleAudioBlob(blob);\r\n };\r\n\r\n if (mode === \"vad\") {\r\n setupVAD(stream, recorder);\r\n }\r\n\r\n recorder.start(200);\r\n recordingModeRef.current = mode;\r\n setIsRecording(true);\r\n isRecordingRef.current = true;\r\n startRecordingTimer();\r\n\r\n setStatusOverride(\r\n accessibilityMode && mode === \"vad\"\r\n ? STATUS_LABELS.accessibilityActive\r\n : STATUS_LABELS.listening,\r\n );\r\n\r\n if (pendingStopAfterStartRef.current) {\r\n pendingStopAfterStartRef.current = false;\r\n stopRecording();\r\n }\r\n } catch (error) {\r\n const errMsg = normalizeError(error);\r\n if (errMsg.toLowerCase().includes(\"permission\") || errMsg.toLowerCase().includes(\"denied\")) {\r\n autoListenSuppressedRef.current = true;\r\n }\r\n cancelActiveSttWs();\r\n setStatusOverride(null);\r\n appendMessage(`Mikrofon hatası: ${errMsg}`, false);\r\n cleanupVAD();\r\n stopStreamTracks();\r\n pendingStopAfterStartRef.current = false;\r\n setIsRecording(false);\r\n isRecordingRef.current = false;\r\n stopRecordingTimer();\r\n } finally {\r\n if (!isRecordingRef.current && !isBusyRef.current) {\r\n setStatusOverride(null);\r\n }\r\n startRecordingPendingRef.current = false;\r\n setIsMicPending(false);\r\n }\r\n };\r\n\r\n const resetMicGesture = () => {\r\n micPressStartRef.current = null;\r\n micHoldTriggeredRef.current = false;\r\n clearMicHoldTimeout();\r\n };\r\n\r\n const handleMicPointerDown = (\r\n event: JSX.TargetedPointerEvent<HTMLButtonElement>,\r\n ) => {\r\n event.preventDefault();\r\n\r\n if (isBusyRef.current) {\r\n return;\r\n }\r\n\r\n if (isRecordingRef.current) {\r\n // In VAD mode, tapping the button cancels; in press mode, it sends\r\n if (recordingModeRef.current === \"vad\") {\r\n stopRecording({ discard: true });\r\n } else {\r\n stopRecording();\r\n }\r\n return;\r\n }\r\n\r\n micPressStartRef.current = Date.now();\r\n micHoldTriggeredRef.current = false;\r\n clearMicHoldTimeout();\r\n\r\n if (event.currentTarget.setPointerCapture) {\r\n try {\r\n event.currentTarget.setPointerCapture(event.pointerId);\r\n } catch {\r\n // No-op.\r\n }\r\n }\r\n\r\n micHoldTimeoutRef.current = window.setTimeout(() => {\r\n if (\r\n micPressStartRef.current === null ||\r\n isBusyRef.current ||\r\n isRecordingRef.current\r\n ) {\r\n return;\r\n }\r\n\r\n micHoldTriggeredRef.current = true;\r\n void startRecording(\"press\");\r\n }, HOLD_THRESHOLD_MS);\r\n };\r\n\r\n const handleMicPointerUp = (\r\n event: JSX.TargetedPointerEvent<HTMLButtonElement>,\r\n ) => {\r\n event.preventDefault();\r\n\r\n if (event.currentTarget.releasePointerCapture) {\r\n try {\r\n event.currentTarget.releasePointerCapture(event.pointerId);\r\n } catch {\r\n // No-op.\r\n }\r\n }\r\n\r\n const startedAt = micPressStartRef.current;\r\n const wasHold = micHoldTriggeredRef.current;\r\n resetMicGesture();\r\n\r\n if (startedAt === null) {\r\n return;\r\n }\r\n\r\n if (wasHold) {\r\n if (isRecordingRef.current) {\r\n stopRecording();\r\n } else if (startRecordingPendingRef.current) {\r\n pendingStopAfterStartRef.current = true;\r\n }\r\n return;\r\n }\r\n\r\n const duration = Date.now() - startedAt;\r\n if (classifyMicGesture(duration) === \"tap\") {\r\n void startRecording(\"vad\");\r\n }\r\n };\r\n\r\n const handleMicPointerCancel = (\r\n event: JSX.TargetedPointerEvent<HTMLButtonElement>,\r\n ) => {\r\n handleMicPointerUp(event);\r\n };\r\n\r\n const handleRestart = () => {\r\n invalidateRequestEpoch();\r\n sttSendCuePlayedRef.current = false;\r\n resetMicGesture();\r\n pendingStopAfterStartRef.current = false;\r\n\r\n stopActiveStream();\r\n stopActiveAudioPlayback();\r\n cancelActiveSttWs();\r\n\r\n if (recorderRef.current && recorderRef.current.state !== \"inactive\") {\r\n stopRecording({ discard: true });\r\n } else {\r\n discardNextRecordingRef.current = false;\r\n cleanupVAD();\r\n stopStreamTracks();\r\n }\r\n\r\n stopRecordingTimer();\r\n setRecordingDurationMs(0);\r\n\r\n clearPersistedChatState(\r\n typeof localStorage !== \"undefined\" ? localStorage : null,\r\n );\r\n\r\n sessionIdRef.current = null;\r\n const initialMessages = createInitialMessages(config.agentName);\r\n nextMessageIdRef.current = getNextMessageId(initialMessages);\r\n setMessages(initialMessages);\r\n\r\n setIsBusy(false);\r\n isBusyRef.current = false;\r\n setIsRecording(false);\r\n isRecordingRef.current = false;\r\n resetProcessingFlags();\r\n };\r\n\r\n // Auto-listen when accessibility mode is activated (initial trigger)\r\n useEffect(() => {\r\n if (!accessibilityMode || autoListenSuppressedRef.current) return;\r\n const timer = window.setTimeout(() => {\r\n if (!isRecordingRef.current && !isBusyRef.current && !startRecordingPendingRef.current && !autoListenSuppressedRef.current) {\r\n void startRecording(\"vad\");\r\n }\r\n }, 500);\r\n return () => window.clearTimeout(timer);\r\n }, [accessibilityMode]); // eslint-disable-line react-hooks/exhaustive-deps\r\n\r\n const stopTask = () => {\r\n invalidateRequestEpoch();\r\n sttSendCuePlayedRef.current = false;\r\n stopActiveStream();\r\n stopActiveAudioPlayback();\r\n cancelActiveSttWs();\r\n stopRecording({ discard: true });\r\n cleanupVAD();\r\n stopStreamTracks();\r\n resetProcessingFlags();\r\n setIsBusy(false);\r\n isBusyRef.current = false;\r\n };\r\n\r\n // Expose recording actions to parent via actionsRef\r\n if (actionsRef) {\r\n actionsRef.current = {\r\n startRecording: () => {\r\n autoListenSuppressedRef.current = false;\r\n void startRecording(\"vad\");\r\n },\r\n cancelRecording: () => {\r\n stopActiveAudioPlayback();\r\n cancelActiveSttWs();\r\n const recorder = recorderRef.current;\r\n if (recorder && recorder.state !== \"inactive\") {\r\n stopRecording({ discard: true });\r\n } else {\r\n cleanupVAD();\r\n stopStreamTracks();\r\n }\r\n },\r\n stopTask,\r\n };\r\n }\r\n\r\n const windowStyle: { [key: string]: string } = {\r\n position: \"fixed\",\r\n bottom: `${POSITION_BOTTOM}px`,\r\n right: `${POSITION_RIGHT}px`,\r\n width: `${WINDOW_WIDTH}px`,\r\n maxHeight: `${WINDOW_HEIGHT}px`,\r\n backgroundColor: \"hsla(0, 0%, 100%, 1)\",\r\n borderRadius: BORDER_RADIUS.window,\r\n display: hidden ? \"none\" : \"flex\",\r\n flexDirection: \"column\",\r\n overflow: \"hidden\",\r\n zIndex: \"10000\",\r\n animation: hidden ? \"none\" : `slideIn ${TRANSITIONS.medium}`,\r\n boxShadow: accessibilityMode\r\n ? `inset 0 0 0 2px ${COLORS.primary}, ${SHADOW}`\r\n : SHADOW,\r\n fontFamily: \"\\\"Geist\\\", sans-serif\",\r\n };\r\n\r\n const headerStyle: { [key: string]: string } = {\r\n padding: \"14px 16px\",\r\n display: \"flex\",\r\n justifyContent: \"space-between\",\r\n alignItems: \"center\",\r\n };\r\n\r\n const headerActionsStyle: { [key: string]: string } = {\r\n display: \"flex\",\r\n alignItems: \"center\",\r\n gap: \"6px\",\r\n };\r\n\r\n const headerButtonStyle: { [key: string]: string } = {\r\n background: \"none\",\r\n border: \"none\",\r\n cursor: \"pointer\",\r\n padding: \"4px\",\r\n borderRadius: \"6px\",\r\n color: COLORS.text,\r\n display: \"flex\",\r\n alignItems: \"center\",\r\n justifyContent: \"center\",\r\n transition: `color ${TRANSITIONS.fast}, background-color ${TRANSITIONS.fast}`,\r\n };\r\n\r\n const messagesContainerStyle: { [key: string]: string } = {\r\n padding: \"0px 16px\",\r\n overflowY: \"auto\",\r\n flex: \"1\",\r\n minHeight: \"0\",\r\n };\r\n\r\n const messagesListStyle: { [key: string]: string } = {\r\n display: \"flex\",\r\n flexDirection: \"column\",\r\n gap: \"16px\",\r\n };\r\n\r\n const messageStyle = (isUser: boolean): JSX.CSSProperties => ({\r\n maxWidth: \"84%\",\r\n padding: isUser ? \"9px 14px\" : \"0px 0px\",\r\n borderRadius: BORDER_RADIUS.message,\r\n fontSize: \"14px\",\r\n lineHeight: \"140%\",\r\n wordWrap: \"break-word\",\r\n whiteSpace: \"pre-wrap\",\r\n alignSelf: isUser ? \"flex-end\" : \"flex-start\",\r\n backgroundColor: isUser ? COLORS.messageUser : \"\",\r\n color: isUser ? COLORS.messageUserText : \"hsla(215, 100%, 5%, 1)\",\r\n });\r\n\r\n const resolveToolIconSrc = (kind: Message[\"toolKind\"]): string => {\r\n if (kind === \"cursor\") {\r\n return cursorArrowRaysIconContent;\r\n }\r\n if (kind === \"scroll\") {\r\n return handRaisedIconContent;\r\n }\r\n if (kind === \"navigate\") {\r\n return mapIconContent;\r\n }\r\n if (kind === \"form\") {\r\n return queueListIconContent;\r\n }\r\n if (kind === \"interact\") {\r\n return handRaisedIconContent;\r\n }\r\n if (kind === \"unknown\") {\r\n return commandLineIconContent;\r\n }\r\n return faceSmileIconContent;\r\n };\r\n\r\n const footerStyle: { [key: string]: string } = {\r\n padding: \"10px 12px\",\r\n display: \"flex\",\r\n alignItems: \"center\",\r\n justifyContent: \"space-between\",\r\n gap: \"8px\",\r\n };\r\n\r\n const statusPanelStyle: { [key: string]: string } = {\r\n flex: \"1\",\r\n minHeight: \"34px\",\r\n borderRadius: \"10px\",\r\n color: COLORS.text,\r\n fontSize: \"14px\",\r\n display: \"flex\",\r\n alignItems: \"center\",\r\n padding: \"0 10px\",\r\n whiteSpace: \"nowrap\",\r\n overflow: \"hidden\",\r\n textOverflow: \"ellipsis\",\r\n opacity: \"0.7\",\r\n };\r\n\r\n const footerActionsStyle: { [key: string]: string } = {\r\n display: \"flex\",\r\n alignItems: \"center\",\r\n gap: \"8px\",\r\n flexShrink: \"0\",\r\n };\r\n\r\n const recordingTimerStyle: { [key: string]: string } = {\r\n minWidth: \"46px\",\r\n fontSize: \"12px\",\r\n fontWeight: \"700\",\r\n color: COLORS.text,\r\n textAlign: \"right\",\r\n };\r\n\r\n const micFooterButtonStyle: { [key: string]: string } = {\r\n width: \"37px\",\r\n height: \"37px\",\r\n borderRadius: \"999px\",\r\n background: \"transparent\",\r\n display: \"flex\",\r\n alignItems: \"center\",\r\n justifyContent: \"center\",\r\n cursor: \"pointer\",\r\n color: \"#ffffff\",\r\n border: \"1px solid hsla(215, 100%, 5%, 0.5)\",\r\n transition: `transform ${TRANSITIONS.fast}`,\r\n };\r\n\r\n const isVadRecording = isRecording && recordingModeRef.current === \"vad\";\r\n const showStopButton = isBusy && !isRecording;\r\n const hideMicButton = isMicPending && !isRecording;\r\n const disableMicControl = isBusy;\r\n\r\n return (\r\n <div className=\"bulut-chat-window\" style={windowStyle}>\r\n <style>{`\r\n @keyframes slideIn {\r\n from {\r\n opacity: 0;\r\n transform: translateY(10px);\r\n }\r\n to {\r\n opacity: 1;\r\n transform: translateY(0);\r\n }\r\n }\r\n\r\n .bulut-header-btn:hover:not(:disabled) {\r\n color: ${COLORS.text};\r\n }\r\n\r\n .bulut-footer-btn:hover:not(:disabled) {\r\n transform: scale(1.04);\r\n }\r\n\r\n .bulut-header-btn:disabled,\r\n .bulut-footer-btn:disabled {\r\n cursor: not-allowed;\r\n opacity: 0.5;\r\n transform: none;\r\n }\r\n\r\n @keyframes bulut-dots {\r\n 0% { content: '.'; }\r\n 33% { content: '..'; }\r\n 66% { content: '...'; }\r\n }\r\n\r\n .bulut-status-dots::after {\r\n content: '.';\r\n animation: bulut-dots 1.2s steps(1) infinite;\r\n display: inline-block;\r\n min-width: 12px;\r\n text-align: left;\r\n }\r\n\r\n /* Mobile: full-screen chat window */\r\n @media (max-width: 600px) {\r\n .bulut-chat-window {\r\n top: 0 !important;\r\n left: 0 !important;\r\n right: 0 !important;\r\n bottom: 0 !important;\r\n width: 100% !important;\r\n max-height: 100% !important;\r\n height: 100% !important;\r\n border-radius: 0 !important;\r\n }\r\n .bulut-close-btn {\r\n width: 40px !important;\r\n height: 40px !important;\r\n padding: 8px !important;\r\n }\r\n .bulut-close-btn svg {\r\n width: 26px !important;\r\n height: 26px !important;\r\n }\r\n }\r\n `}</style>\r\n\r\n <div style={headerStyle}>\r\n <SvgIcon\r\n src={logoContent}\r\n title=\"Bulut Logo\"\r\n style={{ maxWidth: \"80px\", height: \"auto\" }}\r\n stripColors={false}\r\n />\r\n <div style={headerActionsStyle}>\r\n <button\r\n type=\"button\"\r\n className=\"bulut-header-btn\"\r\n style={headerButtonStyle}\r\n onClick={handleRestart}\r\n aria-label=\"Sohbeti yeniden başlat\"\r\n title=\"Sohbeti yeniden başlat\"\r\n >\r\n <SvgIcon src={arrowPathIconContent} aria-hidden=\"true\" width={22} height={22} />\r\n </button>\r\n\r\n <button\r\n type=\"button\"\r\n className=\"bulut-header-btn bulut-close-btn\"\r\n style={{\r\n ...headerButtonStyle,\r\n display: \"flex\",\r\n alignItems: \"center\",\r\n justifyContent: \"center\",\r\n }}\r\n onClick={onClose}\r\n aria-label=\"Sohbeti kapat\"\r\n title=\"Sohbeti kapat\"\r\n >\r\n <SvgIcon src={xMarkIconContent} aria-hidden=\"true\" width={22} height={22} />\r\n </button>\r\n </div>\r\n </div>\r\n\r\n <div style={messagesContainerStyle} ref={messagesContainerRef}>\r\n <div style={messagesListStyle} ref={messagesContentRef}>\r\n {messages.map((message) => {\r\n if (message.type === \"tool\") {\r\n const toolIconSrc = resolveToolIconSrc(message.toolKind);\r\n return (\r\n <div\r\n key={message.id}\r\n style={{\r\n ...messageStyle(false),\r\n opacity: \"0.7\",\r\n display: \"flex\",\r\n alignItems: \"center\",\r\n gap: \"8px\",\r\n }}\r\n >\r\n <SvgIcon\r\n src={toolIconSrc}\r\n aria-hidden=\"true\"\r\n width={20}\r\n height={20}\r\n style={{ flexShrink: 0 }}\r\n />\r\n <span>{message.text}</span>\r\n </div>\r\n );\r\n }\r\n\r\n return (\r\n <div key={message.id} style={messageStyle(message.isUser)}>\r\n {message.text}\r\n </div>\r\n );\r\n })}\r\n </div>\r\n </div>\r\n\r\n <div style={footerStyle}>\r\n <div style={{ ...statusPanelStyle, transition: \"opacity 0.2s ease-out\" }}>\r\n {showStatus ? (\r\n <span className=\"bulut-status-dots\" title={statusText}>\r\n {statusText}\r\n </span>\r\n ) : onAccessibilityToggle ? (\r\n <div\r\n style={{\r\n display: \"flex\",\r\n alignItems: \"center\",\r\n gap: \"8px\",\r\n }}\r\n >\r\n <span\r\n style={{\r\n fontSize: \"12px\",\r\n opacity: \"0.6\",\r\n whiteSpace: \"nowrap\",\r\n }}\r\n >\r\n Erişilebilirlik\r\n </span>\r\n <button\r\n type=\"button\"\r\n onClick={onAccessibilityToggle}\r\n aria-label={\r\n accessibilityMode\r\n ? \"Erişilebilirlik modunu kapat\"\r\n : \"Erişilebilirlik modunu aç\"\r\n }\r\n style={{\r\n width: \"36px\",\r\n height: \"20px\",\r\n borderRadius: \"10px\",\r\n border: \"none\",\r\n cursor: \"pointer\",\r\n padding: \"2px\",\r\n display: \"flex\",\r\n alignItems: \"center\",\r\n backgroundColor: accessibilityMode\r\n ? COLORS.primary\r\n : \"hsla(215, 10%, 75%, 1)\",\r\n transition: `background-color ${TRANSITIONS.fast}`,\r\n flexShrink: \"0\",\r\n }}\r\n >\r\n <span\r\n style={{\r\n width: \"16px\",\r\n height: \"16px\",\r\n borderRadius: \"50%\",\r\n backgroundColor: \"#ffffff\",\r\n display: \"block\",\r\n transition: `transform ${TRANSITIONS.fast}`,\r\n transform: accessibilityMode\r\n ? \"translateX(16px)\"\r\n : \"translateX(0)\",\r\n boxShadow: \"0 1px 3px rgba(0,0,0,0.2)\",\r\n }}\r\n />\r\n </button>\r\n </div>\r\n ) : null}\r\n </div>\r\n\r\n <div style={footerActionsStyle}>\r\n {isRecording ? (\r\n <span style={recordingTimerStyle}>\r\n {formatDurationMs(recordingDurationMs)}\r\n </span>\r\n ) : null}\r\n {showStopButton ? (\r\n <button\r\n type=\"button\"\r\n className=\"bulut-footer-btn\"\r\n style={micFooterButtonStyle}\r\n onClick={stopTask}\r\n aria-label=\"Görevi durdur\"\r\n title=\"Görevi durdur\"\r\n >\r\n <SvgIcon\r\n src={stopOutlineIconContent}\r\n aria-hidden=\"true\"\r\n width={22}\r\n height={22}\r\n style={{ color: \"hsla(215, 100%, 5%, 1)\" }}\r\n />\r\n </button>\r\n ) : hideMicButton ? null : (\r\n <button\r\n type=\"button\"\r\n className=\"bulut-footer-btn\"\r\n style={micFooterButtonStyle}\r\n onPointerDown={handleMicPointerDown}\r\n onPointerUp={handleMicPointerUp}\r\n onPointerCancel={handleMicPointerCancel}\r\n disabled={disableMicControl}\r\n aria-label={isVadRecording ? \"Kaydı iptal et\" : isRecording ? \"Kaydı durdur\" : \"Kaydı başlat\"}\r\n title={\r\n isVadRecording\r\n ? \"Kaydı iptal et\"\r\n : isRecording\r\n ? \"Kaydı durdur\"\r\n : \"Dokun: VAD, Basılı tut: bırakınca gönder\"\r\n }\r\n >\r\n {isVadRecording ? (\r\n <SvgIcon\r\n src={xMarkIconContent}\r\n aria-hidden=\"true\"\r\n width={22}\r\n height={22}\r\n style={{ color: \"hsla(215, 100%, 5%, 1)\"}}\r\n />\r\n ) : (\r\n <SvgIcon\r\n src={microphoneOutlineIconContent}\r\n aria-hidden=\"true\"\r\n width={22}\r\n height={22}\r\n style={{ color: \"hsla(215, 100%, 5%, 1)\" }}\r\n />\r\n )}\r\n </button>\r\n )}\r\n </div>\r\n </div>\r\n </div>\r\n );\r\n};\r\n","export default \"<svg width=\\\"2420\\\" height=\\\"438\\\" viewBox=\\\"0 0 2420 438\\\" fill=\\\"none\\\" xmlns=\\\"http://www.w3.org/2000/svg\\\">\\r\\n<path d=\\\"M251.823 0C313.458 0 366.34 37.767 388.932 91.5918C409.253 75.8883 434.678 66.5567 462.264 66.5566C528.885 66.5567 582.893 120.989 582.893 188.134C582.893 188.786 582.885 189.436 582.875 190.086C648.144 193.552 700 247.572 700 313.704C700 382.074 644.575 437.5 576.204 437.5H123.796C55.4255 437.5 7.42386e-05 382.074 0 313.704C0 250.475 47.4025 198.32 108.608 190.833C104.967 177.844 103.019 164.138 103.019 149.975C103.019 67.1461 169.641 0.000357483 251.823 0ZM234.696 141.93C218.117 134.066 199 146.158 199 164.507C199 174.32 204.744 183.225 213.684 187.271L336.761 242.985C337.971 243.533 338.748 244.738 338.748 246.066C338.748 247.394 337.971 248.6 336.761 249.147L213.684 304.861C204.744 308.908 199 317.812 199 327.625C199 345.974 218.117 358.066 234.696 350.202L364.672 288.554C375.142 283.588 381.815 273.036 381.815 261.448V230.684C381.815 219.096 375.142 208.544 364.672 203.578L234.696 141.93ZM413.877 296.146C402.078 296.146 392.513 305.711 392.513 317.511C392.513 329.31 402.078 338.875 413.877 338.875H526.636C538.435 338.875 548 329.31 548 317.511C548 305.711 538.435 296.146 526.636 296.146H413.877Z\\\" fill=\\\"#000B1A\\\"/>\\r\\n<path d=\\\"M2420 424.954H2343.35C2307.08 424.954 2278.64 416.094 2258.04 398.373C2237.43 380.652 2227.13 352.216 2227.13 313.065V55.2871H2319.86V302.556C2319.86 318.217 2323.15 328.726 2329.75 334.083C2336.75 339.028 2348.29 341.501 2364.36 341.501H2420V424.954ZM2420 191.903H2178.29V115.25H2420V191.903Z\\\" fill=\\\"#000B1A\\\"/>\\r\\n<path d=\\\"M1923.18 431.136C1894.33 431.136 1870.22 425.779 1850.85 415.064C1831.89 403.937 1817.68 389.101 1808.2 370.555C1799.13 352.01 1794.6 331.198 1794.6 308.12V115.25H1887.32V277.211C1887.32 301.938 1893.3 320.071 1905.25 331.61C1917.2 342.738 1937.81 348.301 1967.07 348.301C1997.56 348.301 2018.79 342.325 2030.74 330.374C2043.1 318.011 2049.28 298.641 2049.28 272.266L2061.03 271.648L2067.83 330.374H2050.52C2048.05 347.683 2041.87 363.962 2031.98 379.21C2022.5 394.458 2008.69 407.028 1990.56 416.918C1972.84 426.397 1950.38 431.136 1923.18 431.136ZM2142.01 424.955H2055.47V329.138L2049.28 326.047V115.25H2142.01V424.955Z\\\" fill=\\\"#000B1A\\\"/>\\r\\n<path d=\\\"M1734.32 424.955H1641.59V10.7793H1734.32V424.955Z\\\" fill=\\\"#000B1A\\\"/>\\r\\n<path d=\\\"M1362.98 431.136C1334.13 431.136 1310.03 425.779 1290.66 415.064C1271.7 403.937 1257.48 389.101 1248 370.555C1238.94 352.01 1234.4 331.198 1234.4 308.12V115.25H1327.13V277.211C1327.13 301.938 1333.1 320.071 1345.06 331.61C1357.01 342.738 1377.61 348.301 1406.87 348.301C1437.37 348.301 1458.59 342.325 1470.54 330.374C1482.91 318.011 1489.09 298.641 1489.09 272.266L1500.83 271.648L1507.63 330.374H1490.33C1487.85 347.683 1481.67 363.962 1471.78 379.21C1462.3 394.458 1448.5 407.028 1430.36 416.918C1412.64 426.397 1390.18 431.136 1362.98 431.136ZM1581.82 424.955H1495.27V329.138L1489.09 326.047V115.25H1581.82V424.955Z\\\" fill=\\\"#000B1A\\\"/>\\r\\n<path d=\\\"M1035.12 431.137C999.27 431.137 971.04 423.513 950.434 408.264C930.241 392.604 917.259 369.526 911.49 339.029H894.181L900.981 272.266H912.726C912.726 289.987 916.023 304.411 922.617 315.538C929.623 326.253 939.719 334.084 952.907 339.029C966.507 343.974 983.198 346.447 1002.98 346.447C1023.17 346.447 1039.66 343.974 1052.43 339.029C1065.21 334.084 1074.69 326.047 1080.87 314.92C1087.05 303.793 1090.14 288.957 1090.14 270.412C1090.14 251.042 1087.05 236 1080.87 225.285C1074.69 214.158 1065.21 206.122 1052.43 201.177C1039.66 196.231 1023.38 193.758 1003.6 193.758C973.513 193.758 950.847 199.322 935.598 210.449C920.35 221.576 912.726 240.533 912.726 267.321H900.981V197.467H917.671C923.029 171.504 935.392 150.28 954.762 133.796C974.543 117.311 1002.77 109.069 1039.45 109.069C1070.36 109.069 1096.53 115.663 1117.96 128.85C1139.39 142.038 1155.67 160.789 1166.79 185.104C1178.33 209.007 1184.1 237.443 1184.1 270.412C1184.1 302.969 1178.33 331.405 1166.79 355.72C1155.67 379.622 1138.98 398.168 1116.72 411.355C1094.47 424.543 1067.27 431.137 1035.12 431.137ZM905.926 424.955H820V10.7793H912.726V325.429L905.926 333.465V424.955Z\\\" fill=\\\"#000B1A\\\"/>\\r\\n</svg>\\r\\n\"","export default \"<svg xmlns=\\\"http://www.w3.org/2000/svg\\\" fill=\\\"none\\\" viewBox=\\\"0 0 24 24\\\" stroke-width=\\\"1.5\\\" stroke=\\\"currentColor\\\">\\r\\n <path stroke-linecap=\\\"round\\\" stroke-linejoin=\\\"round\\\" d=\\\"M16.023 9.348h4.992v-.001M2.985 19.644v-4.992m0 0h4.992m-4.993 0 3.181 3.183a8.25 8.25 0 0 0 13.803-3.7M4.031 9.865a8.25 8.25 0 0 1 13.803-3.7l3.181 3.182m0-4.991v4.99\\\" />\\r\\n</svg>\\r\\n\"","export default \"<svg xmlns=\\\"http://www.w3.org/2000/svg\\\" fill=\\\"none\\\" viewBox=\\\"0 0 24 24\\\" stroke-width=\\\"1.5\\\" stroke=\\\"currentColor\\\">\\r\\n <path stroke-linecap=\\\"round\\\" stroke-linejoin=\\\"round\\\" d=\\\"M15.042 21.672 13.684 16.6m0 0-2.51 2.225.569-9.47 5.227 7.917-3.286-.672ZM12 2.25V4.5m5.834.166-1.591 1.591M20.25 10.5H18M7.757 14.743l-1.59 1.59M6 10.5H3.75m4.007-4.243-1.59-1.59\\\" />\\r\\n</svg>\\r\\n\"","export default \"<svg xmlns=\\\"http://www.w3.org/2000/svg\\\" fill=\\\"none\\\" viewBox=\\\"0 0 24 24\\\" stroke-width=\\\"1.5\\\" stroke=\\\"currentColor\\\">\\r\\n <path stroke-linecap=\\\"round\\\" stroke-linejoin=\\\"round\\\" d=\\\"M9 6.75V15m6-6v8.25m.503 3.498 4.875-2.437c.381-.19.622-.58.622-1.006V4.82c0-.836-.88-1.38-1.628-1.006l-3.869 1.934c-.317.159-.69.159-1.006 0L9.503 3.252a1.125 1.125 0 0 0-1.006 0L3.622 5.689C3.24 5.88 3 6.27 3 6.695V19.18c0 .836.88 1.38 1.628 1.006l3.869-1.934c.317-.159.69-.159 1.006 0l4.994 2.497c.317.158.69.158 1.006 0Z\\\" />\\r\\n</svg>\\r\\n\"","export default \"<svg xmlns=\\\"http://www.w3.org/2000/svg\\\" fill=\\\"none\\\" viewBox=\\\"0 0 24 24\\\" stroke-width=\\\"1.5\\\" stroke=\\\"currentColor\\\">\\r\\n <path stroke-linecap=\\\"round\\\" stroke-linejoin=\\\"round\\\" d=\\\"M3.75 12h16.5m-16.5 3.75h16.5M3.75 19.5h16.5M5.625 4.5h12.75a1.875 1.875 0 0 1 0 3.75H5.625a1.875 1.875 0 0 1 0-3.75Z\\\" />\\r\\n</svg>\\r\\n\"","export default \"<svg xmlns=\\\"http://www.w3.org/2000/svg\\\" fill=\\\"none\\\" viewBox=\\\"0 0 24 24\\\" stroke-width=\\\"1.5\\\" stroke=\\\"currentColor\\\">\\r\\n <path stroke-linecap=\\\"round\\\" stroke-linejoin=\\\"round\\\" d=\\\"m6.75 7.5 3 2.25-3 2.25m4.5 0h3m-9 8.25h13.5A2.25 2.25 0 0 0 21 18V6a2.25 2.25 0 0 0-2.25-2.25H5.25A2.25 2.25 0 0 0 3 6v12a2.25 2.25 0 0 0 2.25 2.25Z\\\" />\\r\\n</svg>\\r\\n\"","export default \"<svg xmlns=\\\"http://www.w3.org/2000/svg\\\" fill=\\\"none\\\" viewBox=\\\"0 0 24 24\\\" stroke-width=\\\"1.5\\\" stroke=\\\"currentColor\\\">\\r\\n <path stroke-linecap=\\\"round\\\" stroke-linejoin=\\\"round\\\" d=\\\"M15.182 15.182a4.5 4.5 0 0 1-6.364 0M21 12a9 9 0 1 1-18 0 9 9 0 0 1 18 0ZM9.75 9.75c0 .414-.168.75-.375.75S9 10.164 9 9.75 9.168 9 9.375 9s.375.336.375.75Zm-.375 0h.008v.015h-.008V9.75Zm5.625 0c0 .414-.168.75-.375.75s-.375-.336-.375-.75.168-.75.375-.75.375.336.375.75Zm-.375 0h.008v.015h-.008V9.75Z\\\" />\\r\\n</svg>\\r\\n\"","import { useState, useEffect, useRef, useCallback } from \"preact/hooks\";\r\nimport \"./globals.css\";\r\nimport { render } from \"preact\";\r\nimport { ChatButton } from \"./components/ChatButton\";\r\nimport {\r\n ChatWindow,\r\n type ChatWindowHandle,\r\n} from \"./components/ChatWindow\";\r\nimport { COLORS } from \"./styles/constants\";\r\n\r\nexport type BulutVoice = \"alloy\" | \"zeynep\" | \"ali\";\r\n\r\nexport interface BulutOptions {\r\n containerId?: string;\r\n backendBaseUrl?: string;\r\n projectId?: string;\r\n}\r\n\r\nexport interface BulutRuntimeConfig {\r\n backendBaseUrl: string;\r\n projectId: string;\r\n model: string;\r\n voice: BulutVoice;\r\n baseColor: string;\r\n agentName: string;\r\n}\r\n\r\n/** Default LLM model — keep in sync with backend config.DEFAULT_LLM_MODEL */\r\nconst DEFAULT_LLM_MODEL = \"x-ai/grok-4.1-fast\";\r\n\r\nconst DEFAULT_AGENT_NAME = \"Bulut\";\r\n\r\nconst DEFAULT_CONFIG: BulutRuntimeConfig = {\r\n backendBaseUrl: \"https://api.bulut.lu\",\r\n projectId: \"\", // Must be provided\r\n model: DEFAULT_LLM_MODEL,\r\n voice: \"alloy\",\r\n baseColor: COLORS.primary,\r\n agentName: DEFAULT_AGENT_NAME,\r\n};\r\n\r\nconst isValidHexColor = (value: string): boolean =>\r\n /^#([0-9a-fA-F]{3}|[0-9a-fA-F]{6})$/.test(value);\r\n\r\nconst normalizeHexColor = (value: string): string => {\r\n const trimmed = value.trim();\r\n if (!isValidHexColor(trimmed)) {\r\n return DEFAULT_CONFIG.baseColor;\r\n }\r\n if (trimmed.length === 4) {\r\n const r = trimmed[1];\r\n const g = trimmed[2];\r\n const b = trimmed[3];\r\n return `#${r}${r}${g}${g}${b}${b}`.toLowerCase();\r\n }\r\n return trimmed.toLowerCase();\r\n};\r\n\r\nconst shadeHexColor = (hexColor: string, amount: number): string => {\r\n const normalized = normalizeHexColor(hexColor);\r\n const raw = normalized.slice(1);\r\n const toChannel = (start: number): number => parseInt(raw.slice(start, start + 2), 16);\r\n const clamp = (value: number): number => Math.max(0, Math.min(255, Math.round(value)));\r\n const adjust = (channel: number): number =>\r\n amount < 0 ? channel * (1 + amount) : channel + (255 - channel) * amount;\r\n const toHex = (channel: number): string => clamp(channel).toString(16).padStart(2, \"0\");\r\n\r\n const r = adjust(toChannel(0));\r\n const g = adjust(toChannel(2));\r\n const b = adjust(toChannel(4));\r\n\r\n return `#${toHex(r)}${toHex(g)}${toHex(b)}`;\r\n};\r\n\r\nconst applyTheme = (baseColor: string): void => {\r\n const normalized = normalizeHexColor(baseColor);\r\n COLORS.primary = normalized;\r\n COLORS.primaryHover = shadeHexColor(normalized, -0.15);\r\n COLORS.messageUser = normalized;\r\n};\r\n\r\ninterface RemoteProjectConfig {\r\n base_color: string;\r\n model: string;\r\n agent_name: string;\r\n voice: string;\r\n}\r\n\r\nconst fetchRemoteConfig = async (\r\n baseUrl: string,\r\n projectId: string,\r\n): Promise<RemoteProjectConfig | null> => {\r\n try {\r\n const url = baseUrl.replace(/\\/+$/, \"\");\r\n const res = await fetch(`${url}/projects/${projectId}/config`);\r\n if (!res.ok) return null;\r\n return (await res.json()) as RemoteProjectConfig;\r\n } catch {\r\n return null;\r\n }\r\n};\r\n\r\nconst resolveRuntimeConfig = (\r\n options: BulutOptions,\r\n): BulutRuntimeConfig => ({\r\n backendBaseUrl: options.backendBaseUrl || DEFAULT_CONFIG.backendBaseUrl,\r\n projectId: options.projectId || DEFAULT_CONFIG.projectId,\r\n model: DEFAULT_CONFIG.model,\r\n voice: DEFAULT_CONFIG.voice,\r\n baseColor: DEFAULT_CONFIG.baseColor,\r\n agentName: DEFAULT_CONFIG.agentName,\r\n});\r\n\r\ninterface BulutWidgetProps {\r\n config: BulutRuntimeConfig;\r\n}\r\n\r\nconst ACCESSIBILITY_MODE_KEY = \"bulut_accessibility_mode_enabled\";\r\nconst GEIST_FONT_FAMILY = \"Geist\";\r\nconst GEIST_STYLESHEET_ID = \"bulut-geist-font-stylesheet\";\r\nconst GEIST_STYLESHEET_URL =\r\n \"https://fonts.googleapis.com/css2?family=Geist:wght@100..900&display=swap\";\r\n\r\nconst ensureGeistStylesheet = (): void => {\r\n if (typeof document === \"undefined\") {\r\n return;\r\n }\r\n if (document.getElementById(GEIST_STYLESHEET_ID)) {\r\n return;\r\n }\r\n const link = document.createElement(\"link\");\r\n link.id = GEIST_STYLESHEET_ID;\r\n link.rel = \"stylesheet\";\r\n link.href = GEIST_STYLESHEET_URL;\r\n document.head.appendChild(link);\r\n};\r\n\r\nconst BulutWidget = ({ config }: BulutWidgetProps) => {\r\n // Live config that merges remote settings over initial config\r\n const [liveConfig, setLiveConfig] = useState<BulutRuntimeConfig>(config);\r\n const [configReady, setConfigReady] = useState(false);\r\n\r\n // Fetch remote project config on mount — widget stays hidden until done\r\n useEffect(() => {\r\n if (!config.projectId) {\r\n setConfigReady(true);\r\n return;\r\n }\r\n let cancelled = false;\r\n\r\n fetchRemoteConfig(config.backendBaseUrl, config.projectId).then((remote) => {\r\n if (cancelled) return;\r\n if (remote) {\r\n const merged: BulutRuntimeConfig = {\r\n ...config,\r\n baseColor: normalizeHexColor(remote.base_color || config.baseColor),\r\n model: remote.model || config.model,\r\n agentName: remote.agent_name || config.agentName,\r\n voice: (\r\n remote.voice === \"alloy\" || remote.voice === \"zeynep\" || remote.voice === \"ali\"\r\n ? remote.voice\r\n : config.voice\r\n ) as BulutVoice,\r\n };\r\n applyTheme(merged.baseColor);\r\n setLiveConfig(merged);\r\n }\r\n setConfigReady(true);\r\n });\r\n\r\n return () => { cancelled = true; };\r\n }, [config]);\r\n\r\n // Check localStorage for persisted state\r\n const [isOpen, setIsOpen] = useState(() => {\r\n if (typeof localStorage !== \"undefined\") {\r\n return localStorage.getItem(\"bulut_panel_open\") === \"true\";\r\n }\r\n return false;\r\n });\r\n\r\n const [showBubble, setShowBubble] = useState(false);\r\n const [isAccessibilityEnabled, setIsAccessibilityEnabled] = useState(() => {\r\n if (typeof localStorage === \"undefined\") {\r\n return false;\r\n }\r\n return localStorage.getItem(ACCESSIBILITY_MODE_KEY) === \"true\";\r\n });\r\n\r\n // State reported by ChatWindow\r\n const [isRecording, setIsRecording] = useState(false);\r\n const [isBusy, setIsBusy] = useState(false);\r\n const [previewMessage, setPreviewMessage] = useState<string | null>(null);\r\n const [previewDismissed, setPreviewDismissed] = useState(false);\r\n\r\n // Ref for delegating recording to ChatWindow\r\n const chatActionsRef = useRef<ChatWindowHandle | null>(null);\r\n\r\n const handlePreviewChange = useCallback((text: string | null) => {\r\n setPreviewMessage(text);\r\n if (text !== null) setPreviewDismissed(false);\r\n }, []);\r\n\r\n // Show welcome bubble once for 5 seconds\r\n useEffect(() => {\r\n if (isAccessibilityEnabled) {\r\n setShowBubble(false);\r\n return;\r\n }\r\n if (isOpen) return;\r\n if (typeof localStorage !== \"undefined\") {\r\n if (localStorage.getItem(\"bulut_bubble_shown\") === \"true\") return;\r\n }\r\n\r\n setShowBubble(true);\r\n const timer = setTimeout(() => {\r\n setShowBubble(false);\r\n if (typeof localStorage !== \"undefined\") {\r\n localStorage.setItem(\"bulut_bubble_shown\", \"true\");\r\n }\r\n }, 5000);\r\n return () => clearTimeout(timer);\r\n }, [isOpen, isAccessibilityEnabled]);\r\n\r\n const toggleWidget = () => {\r\n const newState = !isOpen;\r\n setIsOpen(newState);\r\n setShowBubble(false);\r\n if (typeof localStorage !== \"undefined\") {\r\n localStorage.setItem(\"bulut_panel_open\", String(newState));\r\n }\r\n };\r\n\r\n const toggleAccessibilityMode = () => {\r\n const next = !isAccessibilityEnabled;\r\n setIsAccessibilityEnabled(next);\r\n if (typeof localStorage !== \"undefined\") {\r\n localStorage.setItem(ACCESSIBILITY_MODE_KEY, String(next));\r\n }\r\n console.info(`[Bulut] accessibility mode toggled enabled=${next}`);\r\n };\r\n\r\n const handleClose = () => {\r\n setIsOpen(false);\r\n if (typeof localStorage !== \"undefined\") {\r\n localStorage.setItem(\"bulut_panel_open\", \"false\");\r\n }\r\n console.info(\"Bulut chat window closed.\");\r\n };\r\n\r\n // Close on escape key\r\n useEffect(() => {\r\n const handleEscape = (e: KeyboardEvent) => {\r\n if (e.key === \"Escape\" && isOpen) {\r\n setIsOpen(false);\r\n if (typeof localStorage !== \"undefined\") {\r\n localStorage.setItem(\"bulut_panel_open\", \"false\");\r\n }\r\n }\r\n };\r\n\r\n document.addEventListener(\"keydown\", handleEscape);\r\n return () => document.removeEventListener(\"keydown\", handleEscape);\r\n }, [isOpen]);\r\n\r\n if (!configReady) return null;\r\n\r\n return (\r\n <>\r\n {!isOpen && (\r\n <ChatButton\r\n onMicClick={() => chatActionsRef.current?.startRecording()}\r\n onCancelRecording={() => chatActionsRef.current?.cancelRecording()}\r\n onStopTask={() => chatActionsRef.current?.stopTask()}\r\n isRecording={isRecording}\r\n isBusy={isBusy}\r\n accessibilityMode={isAccessibilityEnabled}\r\n showBubble={showBubble}\r\n onBubbleClick={() => {\r\n setShowBubble(false);\r\n toggleWidget();\r\n }}\r\n previewMessage={previewDismissed ? null : previewMessage}\r\n onPreviewClick={() => toggleWidget()}\r\n onPreviewClose={() => setPreviewDismissed(true)}\r\n />\r\n )}\r\n <ChatWindow\r\n onClose={handleClose}\r\n config={liveConfig}\r\n accessibilityMode={isAccessibilityEnabled}\r\n onAccessibilityToggle={toggleAccessibilityMode}\r\n hidden={!isOpen}\r\n actionsRef={chatActionsRef}\r\n onRecordingChange={setIsRecording}\r\n onBusyChange={setIsBusy}\r\n onPreviewChange={handlePreviewChange}\r\n />\r\n </>\r\n );\r\n};\r\n\r\nconst SHADOW_STYLE = `\r\n :host {\r\n all: initial;\r\n contain: layout style paint;\r\n font-family: \"${GEIST_FONT_FAMILY}\", sans-serif;\r\n color: hsla(215, 100%, 5%, 1);\r\n font-size: 16px;\r\n line-height: 1.4;\r\n -webkit-font-smoothing: antialiased;\r\n text-rendering: optimizeLegibility;\r\n }\r\n\r\n #bulut-shadow-mount {\r\n all: initial;\r\n color: inherit;\r\n font-family: \"${GEIST_FONT_FAMILY}\", sans-serif;\r\n font-size: inherit;\r\n line-height: inherit;\r\n }\r\n\r\n #bulut-shadow-mount * {\r\n font-family: \"${GEIST_FONT_FAMILY}\", sans-serif !important;\r\n color: inherit;\r\n }\r\n\r\n #bulut-shadow-mount *, #bulut-shadow-mount *::before, #bulut-shadow-mount *::after {\r\n box-sizing: border-box;\r\n }\r\n`;\r\n\r\n// Container host for the widget\r\nlet widgetContainer: HTMLElement | null = null;\r\nlet widgetMountNode: HTMLElement | null = null;\r\nlet createdContainer = false;\r\nlet isInitialized = false;\r\n\r\n/**\r\n * Initialize the Bulut chat widget\r\n * @param options - Optional configuration options\r\n */\r\nexport const init = (options: BulutOptions = {}) => {\r\n if (isInitialized) {\r\n console.warn(\"Bulut is already initialized\");\r\n return;\r\n }\r\n\r\n ensureGeistStylesheet();\r\n\r\n const runtimeConfig = resolveRuntimeConfig(options);\r\n applyTheme(runtimeConfig.baseColor);\r\n\r\n // Create or find container\r\n if (options.containerId) {\r\n widgetContainer = document.getElementById(options.containerId);\r\n createdContainer = false;\r\n } else {\r\n widgetContainer = document.createElement(\"div\");\r\n widgetContainer.id = \"bulut-container\";\r\n document.body.appendChild(widgetContainer);\r\n createdContainer = true;\r\n }\r\n\r\n if (!widgetContainer) {\r\n console.error(\"Bulut: Container not found\");\r\n return;\r\n }\r\n\r\n const shadowRoot = widgetContainer.shadowRoot || widgetContainer.attachShadow({ mode: \"open\" });\r\n shadowRoot.replaceChildren();\r\n\r\n const style = document.createElement(\"style\");\r\n style.textContent = SHADOW_STYLE;\r\n\r\n const mountNode = document.createElement(\"div\");\r\n mountNode.id = \"bulut-shadow-mount\";\r\n\r\n shadowRoot.append(style, mountNode);\r\n widgetMountNode = mountNode;\r\n\r\n // Render the widget\r\n render(<BulutWidget config={runtimeConfig} />, mountNode);\r\n isInitialized = true;\r\n\r\n console.log(\"Bulut initialized successfully\");\r\n};\r\n\r\n/**\r\n * Destroy the Bulut widget\r\n */\r\nexport const destroy = () => {\r\n if (!isInitialized) {\r\n return;\r\n }\r\n\r\n if (widgetMountNode) {\r\n render(null, widgetMountNode);\r\n widgetMountNode = null;\r\n }\r\n\r\n if (widgetContainer && createdContainer) {\r\n document.body.removeChild(widgetContainer);\r\n }\r\n\r\n widgetContainer = null;\r\n createdContainer = false;\r\n isInitialized = false;\r\n console.log(\"Bulut destroyed\");\r\n};\r\n\r\n/**\r\n * Check if the widget is initialized\r\n */\r\nexport const isReady = () => isInitialized;\r\n\r\nconst Bulut = {\r\n init,\r\n destroy,\r\n isReady,\r\n};\r\n\r\nif (typeof window !== \"undefined\") {\r\n (window as Window & { Bulut?: typeof Bulut }).Bulut = Bulut;\r\n}\r\n\r\n// Export the main widget component for advanced usage\r\nexport { BulutWidget };\r\n\r\n// Export components for custom implementations\r\nexport { ChatButton, ChatWindow };\r\n\r\nexport default Bulut;\r\n"],"names":["n","l","u","i","o","r","e","f","c","s","a","p","v","y","d","Array","isArray","w","g","parentNode","removeChild","m","t","type","props","key","ref","__k","__","__b","__e","__c","constructor","__v","__i","__u","vnode","k","children","x","this","context","S","length","C","base","M","__d","push","$","__r","debounceRendering","sort","shift","__P","O","__n","namespaceURI","N","I","h","_","b","String","L","D","P","B","A","nextSibling","insertBefore","nodeType","T","setProperty","test","j","style","cssText","replace","toLowerCase","slice","addEventListener","removeEventListener","removeAttribute","setAttribute","F","event","H","prototype","render","contextType","value","__E","E","sub","state","__h","_sb","__s","getDerivedStateFromProps","componentWillMount","componentDidMount","componentWillReceiveProps","shouldComponentUpdate","some","componentWillUpdate","componentDidUpdate","getChildContext","getSnapshotBeforeUpdate","V","then","indexOf","z","localName","document","createTextNode","createElementNS","is","__m","data","call","childNodes","attributes","name","__html","innerHTML","content","q","diffed","forEach","map","current","unmount","componentWillUnmount","G","documentElement","arguments","defaultProps","firstChild","getDerivedStateFromError","setState","componentDidCatch","forceUpdate","Promise","bind","resolve","setTimeout","__source","__self","__H","__N","__f","filter","every","requestAnimationFrame","clearTimeout","cancelAnimationFrame","COLORS","primary","primaryHover","text","messageUser","messageUserText","BORDER_RADIUS","SHADOW","TRANSITIONS","handRaisedIconContent","microphoneOutlineIconContent","stopOutlineIconContent","xMarkIconContent","SvgIcon","src","width","height","title","stripColors","className","fill","stroke","strokeWidth","viewBox","useMemo","trimmedSrc","trim","viewBoxMatch","match","jsx","display","verticalAlign","flexShrink","xmlns","dangerouslySetInnerHTML","nextContent","fillValue","strokeValue","strokeWidthValue","ChatButton","onMicClick","onCancelRecording","onStopTask","isRecording","isBusy","accessibilityMode","showBubble","onBubbleClick","previewMessage","onPreviewClick","onPreviewClose","bgColor","popupBoxShadow","containerStyle","position","right","bottom","flexDirection","alignItems","gap","zIndex","fontFamily","buttonStyle","minWidth","minHeight","borderRadius","backgroundColor","color","border","cursor","justifyContent","transition","showStopButton","mainIconSrc","closeBtnStyle","top","background","fontSize","lineHeight","padding","renderPopup","onClick","onClose","extraClass","scrollable","jsxs","stopPropagation","paddingRight","wordBreak","maxHeight","overflowY","Fragment","onMouseEnter","Object","assign","currentTarget","transform","onMouseLeave","PAGE_CONTEXT_CACHE_KEY","NON_CONTENT_TAGS","Set","SVG_INTERNAL_TAGS","NATIVE_INTERACTIVE_TAGS","INTERACTIVE_ROLES","pageContextCache","Map","cacheHydrated","liveElementMap","getElementById","id","get","normalizeWhitespace","canonicalUrl","rawUrl","URL","href","isCacheEntry","obj","url","summary","links","interactables","capturedAt","version","parseTabIndex","parsed","Number","parseInt","isNaN","getPrimaryRole","element","getAttribute","split","persistCacheToStorage","sessionStorage","serialized","JSON","stringify","from","values","setItem","error","console","warn","buildSummaryWithHistory","recentPages","entry","historySection","compactSummary","join","isVisible","HTMLElement","hidden","window","getComputedStyle","visibility","rect","getBoundingClientRect","hasInteractiveAncestor","parent","parentElement","body","parentTag","tagName","has","parentRole","toAbsoluteUrl","location","getElementLabel","innerText","textContent","substring","ariaLabel","placeholder","HTMLInputElement","HTMLTextAreaElement","HTMLButtonElement","label","tag","alt","filename","pop","compactOuterHtml","inputType","currentValue","selectEl","selectedText","selectedOptions","html","outerHTML","closeIdx","Math","min","describeElementType","role","toUpperCase","getElementState","states","pressed","expanded","checked","hasAttribute","formatSection","lines","invalidateCurrentPageContext","delete","getPageContext","forceRefresh","elementMap","raw","getItem","parse","set","size","info","hydrateCacheFromStorage","scan","sampledElements","querySelectorAll","linkSet","candidates","idCounter","order","isNativeInteractive","Boolean","isRoleInteractive","tabIndex","hasTabStop","hasPointerCursor","isContentEditable","isDisabled","startsWith","absoluteHref","line","add","elType","stateTokens","score","collectSemanticElements","cached","headings","lang","textSnippets","buildPageContextSummary","root","querySelector","snippets","seen","node","collectTextSnippets","Date","now","sorted","overflow","pruneOldestCacheEntries","AGENT_CURSOR_ID","CURSOR_MOVE_DURATION_MS","CURSOR_EASING","RESUME_STORAGE_KEY","savePendingAgentResume","localStorage","savedAt","clearPendingAgentResume","removeItem","clamp","max","animateWindowScrollTo","async","targetY","durationMs","startY","scrollY","delta","abs","raf","callback","performance","startTime","step","progress","eased","cos","PI","easeInOutSine","scrollTo","setCursorPosition","left","setCursorVisibility","visible","opacity","isVisibleElement","findAgentUiAnchorElement","roots","defaultHost","shadowRoot","allElements","el","includes","getBulutShadowRoots","panel","button","getAgentWindowTopLeft","anchor","CURSOR_DIAMETER_PX","scrollX","hideAgentCursor","cursorHoverTrackingInitialized","initializeCursorHoverTracking","parseFloat","getCursorPosition","pointerX","pageX","pointerY","pageY","hypot","moveCursor","existing","createElement","startPosition","baseColor","boxShadow","boxSizing","pointerEvents","appendChild","ensureCursor","dataset","transitionReady","waitForNextAnimationFrame","getElementCenter","CONTAINS_SELECTOR_PATTERN","findElementBySelector","selector","containsMatch","baseSelector","expectedText","candidate","fallbackError","dispatchMouseEvent","dispatchEvent","MouseEvent","bubbles","cancelable","view","clientX","clientY","typeIntoElement","focus","descriptor","getOwnPropertyDescriptor","defaultValue","setNativeInputLikeValue","Event","slowScrollElementIntoView","slowScrollElementIntoViewWithMode","forceCenter","viewportHeight","innerHeight","isRectOutsideViewport","maxScrollTop","scrollHeight","currentScrollY","rectTop","rectHeight","computeCenteredScrollTop","executeInteract","target","mapped","center","selected","resolveTarget","action","click","requestSubmit","form","parentForm","closest","submitElement","executeNavigate","targetUrl","resolvedUrl","matchingElement","parsedTarget","allLinks","HTMLAnchorElement","elUrl","pathname","search","hash","urlSegments","lastSegment","searchTerms","searchParams","entries","clickables","dataTab","term","findMatchingLinkForTarget","log","origin","isSamePageNavigation","newPath","history","pushState","PopStateEvent","executeSingleToolCall","callId","call_id","tool","result","executeScroll","msg","Error","message","TTS_WS_RETRY_DELAYS_MS","BULUT_AUDIO_STOP_EVENT","activeAudioElements","audioPlaybackGeneration","normalizeBaseUrl","baseUrl","trimmed","toWebSocketUrl","path","normalized","protocol","toString","shouldFallbackToSse","retryable","parseErrorBody","response","json","detail","statusText","sleep","ms","wasPlaybackStoppedAfter","generationAtStart","getAudioPlaybackGeneration","stopActiveAudioPlayback","active","audioElement","pause","load","base64ToUint8Array","base64","cleanBase64","binaryString","atob","bytes","Uint8Array","charCodeAt","playBufferedAudio","chunks","mimeType","sampleRate","onAudioStateChange","playbackGeneration","totalBytes","reduce","acc","byteLength","blobParts","chunk","copied","buffer","detectedMime","header","padStart","safeMimeType","finalBlobParts","ArrayBuffer","DataView","setUint32","setUint16","channels","createWavHeader","blob","Blob","Audio","objectUrl","createObjectURL","registerActiveAudioElement","preload","autoplay","play","ended","reject","watchdog","setInterval","onEnded","cleanup","onError","onForcedStop","clearInterval","waitForPlaybackEnd","err","unregisterActiveAudioElement","revokeObjectURL","parseSseEventPayload","eventBlock","dataLines","trimStart","dataStr","isAudioSsePayload","payload","audio","startSttWebSocketStream","config","events","wsUrl","socket","WebSocket","seq","finalText","finalSessionId","sessionId","stopped","settled","sendQueue","resolveStart","rejectStart","startPromise","resolveDone","rejectDone","donePromise","rejectAll","resolveDoneIfPossible","session_id","onopen","onRequestSent","send","project_id","projectId","language","mime_type","onmessage","parseSttWsEventPayload","onSessionId","close","buildError","onPartial","onerror","ev","onclose","code","reason","pushChunk","arrayBuffer","binary","fromCharCode","subarray","btoa","blobToBase64","readyState","OPEN","debug","stop","cancel","collectTtsViaWebSocket","assistantText","voice","isStopped","setSocket","onFirstBatchReady","requestId","crypto","randomUUID","random","highestSeqSeen","firstBatchFired","firstBatchTimer","fireFirstBatch","batch","splice","connectOnce","done","finalError","finalize","mode","request_id","accessibility_mode","last_seq","parseTtsWsEventPayload","incomingSeq","shouldAcceptAudioSeq","sample_rate","attempt","delay","collectAndPlayTtsStreamed","setReader","playbackGen","ttsResult","firstBatchPlayPromise","firstBatch","catch","wsErr","ttsFormData","FormData","append","ttsResponse","fetch","method","ok","reader","getReader","decoder","TextDecoder","read","decode","stream","blocks","block","format","releaseLock","collectTtsViaSse","speakText","agentVoiceChatStream","audioFile","executeTool","activeReader","activeSocket","errorEmitted","sttResult","file","formData","responsePromise","transcribeAudio","onSttRequestSent","currentSessionId","effectiveSessionId","userText","onTranscription","user_text","agentResolve","agentReject","finalReply","resolved","accumulatedDelta","allIntermediateText","finish","reply","fail","model","page_context","pageContext","msgType","onAssistantDelta","calls","onIntermediateReply","onToolCalls","results","isNavigate","pendingToolCalls","args","completedResults","onToolResult","final_reply","replyExpectsReply","expects_reply","onAssistantDone","errMsg","onIteration","iteration","max_iterations","SFX_SOURCES","sent","thinking","toolCall","completed","sfxManager","queue","playNow","volume","onended","drain","next","playCue","STORAGE_KEY","TIMESTAMP_KEY","SESSION_ID_KEY","TTL_MS","STATUS_LABELS","getGreetingText","agentName","resolveStatusText","flags","isRunningTools","isPlayingAudio","isThinking","isTranscribing","formatDurationMs","totalSeconds","floor","createInitialMessages","isUser","clearPersistedChatState","storage","getNextMessageId","messages","shouldAutoListenAfterAudio","expectsReply","getToolIndicatorMessage","kind","ChatWindow","onAccessibilityToggle","actionsRef","onRecordingChange","onBusyChange","onPreviewChange","setMessages","useState","saved","timestamp","setIsBusy","setIsRecording","setIsTranscribing","setIsThinking","isRenderingAudio","setIsRenderingAudio","setIsPlayingAudio","setIsRunningTools","isMicPending","setIsMicPending","recordingDurationMs","setRecordingDurationMs","statusOverride","setStatusOverride","statusFlags","resolvedStatusText","showStatus","hasActiveStatus","isBusyRef","useRef","isRecordingRef","nextMessageIdRef","recorderRef","streamRef","audioChunksRef","activeStreamControllerRef","sessionIdRef","ts","silenceStartRef","vadIntervalRef","audioContextRef","sourceRef","discardNextRecordingRef","micPressStartRef","micHoldTimeoutRef","micHoldTriggeredRef","recordingModeRef","pendingStopAfterStartRef","startRecordingPendingRef","assistantMessageIdRef","assistantTextBufferRef","transcriptionReceivedRef","assistantDoneReceivedRef","recordingStartedAtRef","recordingTimerIntervalRef","messagesContainerRef","messagesContentRef","pendingUserTextRef","pendingAssistantTextRef","streamingJsonParserRef","awaitingAssistantResponseRef","activeSttWsRef","liveTranscriptionMessageIdRef","liveTranscriptionTextRef","autoListenSuppressedRef","expectsReplyRef","requestEpochRef","sttSendCuePlayedRef","useEffect","lastAssistant","reverse","find","st","playSfx","beginRequestEpoch","invalidateRequestEpoch","isCurrentRequestEpoch","epoch","playSttSentCueOnce","scrollMessagesToBottom","scrollTop","ResizeObserver","observer","observe","disconnect","stopRecordingTimer","resetProcessingFlags","clearMicHoldTimeout","cleanupVAD","stopStreamTracks","getTracks","track","stopActiveStream","cancelActiveSttWs","activeSttWs","recorder","ondataavailable","onstop","resumeState","getPendingAgentResume","requestEpoch","freshPageContext","controller","allResults","tc","accumulated_delta","pending_tool_calls","tool_results","agentResumeStream","backendBaseUrl","sid","appendMessage","updateMessageText","finalDisplayText","handleAudioStateChange","appendToolIndicatorMessages","finally","startRecording","options","previous","toolKind","toolLabel","toolCount","indicator","last","previousToolText","extractedCount","nextCount","isFinite","baseLabel","upsertLiveUserTranscription","clearLiveUserTranscriptionState","finalizeStreamCycle","runAgentForUserText","normalizedUserText","handleToolExecution","agentTextChatStream","stopRecording","discard","navigator","mediaDevices","getUserMedia","MediaRecorder","recorderOptions","audioBitsPerSecond","preferredMimeTypes","mime","isTypeSupported","sttMimeType","sttWsController","shouldDiscard","currentSttWs","fileType","extension","File","previousUserText","_callId","_toolName","_result","_iteration","_maxIterations","handleAudioBlob","AudioCtx","AudioContext","webkitAudioContext","analyser","createAnalyser","fftSize","source","createMediaStreamSource","connect","dataArray","frequencyBinCount","speechDetected","speechStartedAt","enforceMinSpeechDuration","getByteFrequencyData","sum","silenceDuration","speechDurationMs","minSpeechDurationMs","shouldAcceptVadSpeech","setupVAD","start","startedAt","normalizeError","resetMicGesture","handleMicPointerUp","preventDefault","releasePointerCapture","pointerId","wasHold","thresholdMs","classifyMicGesture","timer","stopTask","cancelRecording","windowStyle","animation","headerButtonStyle","messageStyle","maxWidth","wordWrap","whiteSpace","alignSelf","statusPanelStyle","flex","textOverflow","recordingTimerStyle","fontWeight","textAlign","micFooterButtonStyle","isVadRecording","hideMicButton","disableMicControl","initialMessages","toolIconSrc","onPointerDown","setPointerCapture","onPointerUp","onPointerCancel","disabled","DEFAULT_CONFIG","normalizeHexColor","isValidHexColor","shadeHexColor","hexColor","amount","toChannel","adjust","channel","toHex","round","applyTheme","ACCESSIBILITY_MODE_KEY","GEIST_FONT_FAMILY","GEIST_STYLESHEET_ID","BulutWidget","liveConfig","setLiveConfig","configReady","setConfigReady","cancelled","res","fetchRemoteConfig","remote","merged","base_color","agent_name","isOpen","setIsOpen","setShowBubble","isAccessibilityEnabled","setIsAccessibilityEnabled","setPreviewMessage","previewDismissed","setPreviewDismissed","chatActionsRef","handlePreviewChange","toggleWidget","newState","handleEscape","SHADOW_STYLE","widgetContainer","widgetMountNode","createdContainer","isInitialized","init","link","rel","head","ensureGeistStylesheet","runtimeConfig","resolveRuntimeConfig","containerId","attachShadow","replaceChildren","mountNode","destroy","isReady","Bulut"],"mappings":"4GAAG,IAACA,EAAEC,EAAEC,EAAIC,EAAEC,EAAEC,EAAEC,EAAEC,EAAEC,EAAEC,EAAEC,EAAIC,EAAE,CAAA,EAAGC,EAAE,GAAGC,EAAE,oEAAoEC,EAAEC,MAAMC,QAAQ,SAASC,EAAEjB,EAAEC,GAAG,IAAA,IAAQC,KAAKD,EAAED,EAAEE,GAAGD,EAAEC,GAAG,OAAOF,CAAC,CAAC,SAASkB,EAAElB,GAAGA,GAAGA,EAAEmB,YAAYnB,EAAEmB,WAAWC,YAAYpB,EAAE,CAAsS,SAASqB,EAAErB,EAAEsB,EAAEnB,EAAEC,EAAEC,GAAG,IAAIC,EAAE,CAACiB,KAAKvB,EAAEwB,MAAMF,EAAEG,IAAItB,EAAEuB,IAAItB,EAAEuB,IAAI,KAAKC,GAAG,KAAKC,IAAI,EAAEC,IAAI,KAAKC,IAAI,KAAKC,mBAAmBC,IAAI,MAAM5B,IAAIH,EAAEG,EAAE6B,KAAI,EAAGC,IAAI,GAAG,OAAO,MAAM9B,GAAG,MAAMJ,EAAEmC,OAAOnC,EAAEmC,MAAM9B,GAAGA,CAAC,CAAmC,SAAS+B,EAAErC,GAAG,OAAOA,EAAEsC,QAAQ,CAAC,SAASC,EAAEvC,EAAEC,GAAGuC,KAAKhB,MAAMxB,EAAEwC,KAAKC,QAAQxC,CAAC,CAAC,SAASyC,EAAE1C,EAAEC,GAAG,GAAG,MAAMA,EAAE,OAAOD,EAAE4B,GAAGc,EAAE1C,EAAE4B,GAAG5B,EAAEkC,IAAI,GAAG,KAAK,IAAA,IAAQhC,EAAED,EAAED,EAAE2B,IAAIgB,OAAO1C,IAAI,GAAG,OAAOC,EAAEF,EAAE2B,IAAI1B,KAAK,MAAMC,EAAE4B,WAAW5B,EAAE4B,IAAI,MAAM,mBAAmB9B,EAAEuB,KAAKmB,EAAE1C,GAAG,IAAI,CAAC,SAAS4C,EAAE5C,GAAG,IAAIC,EAAEC,EAAE,GAAG,OAAOF,EAAEA,EAAE4B,KAAK,MAAM5B,EAAE+B,IAAI,CAAC,IAAI/B,EAAE8B,IAAI9B,EAAE+B,IAAIc,KAAK,KAAK5C,EAAE,EAAEA,EAAED,EAAE2B,IAAIgB,OAAO1C,IAAI,GAAG,OAAOC,EAAEF,EAAE2B,IAAI1B,KAAK,MAAMC,EAAE4B,IAAI,CAAC9B,EAAE8B,IAAI9B,EAAE+B,IAAIc,KAAK3C,EAAE4B,IAAI,KAAK,CAAC,OAAOc,EAAE5C,EAAE,CAAC,CAAC,SAAS8C,EAAE9C,KAAKA,EAAE+C,MAAM/C,EAAE+C,KAAI,IAAK5C,EAAE6C,KAAKhD,KAAKiD,EAAEC,OAAO9C,GAAGH,EAAEkD,sBAAsB/C,EAAEH,EAAEkD,oBAAoB9C,GAAG4C,EAAE,CAAC,SAASA,IAAI,IAAA,IAAQjD,EAAEE,EAAEoB,EAAElB,EAAEC,EAAEE,EAAEC,EAAEC,EAAE,EAAEN,EAAEwC,QAAQxC,EAAEwC,OAAOlC,GAAGN,EAAEiD,KAAK9C,GAAGN,EAAEG,EAAEkD,QAAQ5C,EAAEN,EAAEwC,OAAO3C,EAAE+C,MAAMzB,SAASlB,OAAE,EAAOC,GAAGD,GAAGF,EAAEF,GAAGiC,KAAKH,IAAIvB,EAAE,GAAGC,EAAE,GAAGN,EAAEoD,OAAOhC,EAAEL,EAAE,GAAGb,IAAI6B,IAAI7B,EAAE6B,IAAI,EAAEhC,EAAEmC,OAAOnC,EAAEmC,MAAMd,GAAGiC,EAAErD,EAAEoD,IAAIhC,EAAElB,EAAEF,EAAEsD,IAAItD,EAAEoD,IAAIG,aAAa,GAAGrD,EAAE+B,IAAI,CAAC9B,GAAG,KAAKE,EAAE,MAAMF,EAAEqC,EAAEtC,GAAGC,KAAK,GAAGD,EAAE+B,KAAK3B,GAAGc,EAAEW,IAAI7B,EAAE6B,IAAIX,EAAEM,GAAGD,IAAIL,EAAEY,KAAKZ,EAAEoC,EAAEnD,EAAEe,EAAEd,GAAGJ,EAAE0B,IAAI1B,EAAEwB,GAAG,KAAKN,EAAEQ,KAAKzB,GAAGuC,EAAEtB,KAAK2B,EAAEC,IAAI,CAAC,CAAC,SAASS,EAAE3D,EAAEC,EAAEC,EAAEoB,EAAEnB,EAAEC,EAAEC,EAAEC,EAAEC,EAAEC,EAAEC,GAAG,IAAIC,EAAEkD,EAAE/C,EAAEC,EAAEG,EAAEC,EAAE2C,EAAExC,EAAEC,GAAGA,EAAEK,KAAKf,EAAEkD,EAAE7D,EAAE0C,OAAO,IAAIpC,EAAyV,SAAWP,EAAEC,EAAEC,EAAEoB,EAAEnB,GAAG,IAAIC,EAAEC,EAAEC,EAAEC,EAAEC,EAAEC,EAAEP,EAAEyC,OAAOjC,EAAED,EAAEmD,EAAE,EAAE,IAAI5D,EAAE2B,IAAI,IAAIZ,MAAMZ,GAAGC,EAAE,EAAEA,EAAED,EAAEC,IAAI,OAAOC,EAAEJ,EAAEG,KAAK,kBAAkBC,GAAG,mBAAmBA,GAAG,iBAAiBA,GAAG,iBAAiBA,GAAG,iBAAiBA,GAAGA,EAAE2B,aAAa+B,OAAO1D,EAAEL,EAAE2B,IAAIvB,GAAGiB,EAAE,KAAKhB,EAAE,KAAK,KAAK,MAAMS,EAAET,GAAGA,EAAEL,EAAE2B,IAAIvB,GAAGiB,EAAEgB,EAAE,CAACC,SAASjC,GAAG,KAAK,KAAK,WAAM,IAASA,EAAE2B,aAAa3B,EAAEwB,IAAI,EAAExB,EAAEL,EAAE2B,IAAIvB,GAAGiB,EAAEhB,EAAEkB,KAAKlB,EAAEmB,MAAMnB,EAAEoB,IAAIpB,EAAEqB,IAAIrB,EAAEqB,IAAI,KAAKrB,EAAE4B,KAAKjC,EAAE2B,IAAIvB,GAAGC,EAAEE,EAAEH,EAAEwD,EAAEvD,EAAEuB,GAAG5B,EAAEK,EAAEwB,IAAI7B,EAAE6B,IAAI,EAAEvB,EAAE,MAAK,IAAKE,EAAEH,EAAE6B,IAAI8B,EAAE3D,EAAEH,EAAEK,EAAEG,MAAMA,KAAKJ,EAAEJ,EAAEM,MAAMF,EAAE6B,KAAK,IAAI,MAAM7B,GAAG,MAAMA,EAAE2B,MAAK,GAAIzB,IAAIL,EAAEM,EAAEmD,IAAIzD,EAAEM,GAAGmD,KAAK,mBAAmBvD,EAAEkB,OAAOlB,EAAE8B,KAAK,IAAI3B,GAAGD,IAAIC,GAAGD,EAAE,EAAEqD,IAAIpD,GAAGD,EAAE,EAAEqD,KAAKpD,EAAED,EAAEqD,IAAIA,IAAIvD,EAAE8B,KAAK,KAAKnC,EAAE2B,IAAIvB,GAAG,KAAK,GAAGM,EAAE,IAAIN,EAAE,EAAEA,EAAEK,EAAEL,IAAI,OAAOE,EAAEJ,EAAEE,OAAS,EAAEE,EAAE6B,OAAO7B,EAAEwB,KAAKR,IAAIA,EAAEoB,EAAEpC,IAAI2D,EAAE3D,EAAEA,IAAI,OAAOgB,CAAC,CAAjkC4C,CAAEhE,EAAED,EAAEoB,EAAEd,EAAEuD,GAAGpD,EAAE,EAAEA,EAAEoD,EAAEpD,IAAI,OAAOG,EAAEX,EAAEyB,IAAIjB,MAAMkD,GAAE,GAAI/C,EAAEqB,IAAIvB,EAAEU,EAAER,EAAEqB,MAAMvB,EAAEE,EAAEqB,IAAIxB,EAAEQ,EAAEqC,EAAEvD,EAAEa,EAAE+C,EAAEzD,EAAEC,EAAEC,EAAEC,EAAEC,EAAEC,EAAEC,GAAGK,EAAED,EAAEiB,IAAIjB,EAAEa,KAAKkC,EAAElC,KAAKb,EAAEa,MAAMkC,EAAElC,KAAKyC,EAAEP,EAAElC,IAAI,KAAKb,GAAGJ,EAAEuC,KAAKnC,EAAEa,IAAIb,EAAEkB,KAAKjB,EAAED,IAAI,MAAMI,GAAG,MAAMH,IAAIG,EAAEH,IAAI+C,KAAK,EAAEhD,EAAEsB,OAAOyB,EAAEjC,MAAMd,EAAEc,IAAIpB,EAAE6D,EAAEvD,EAAEN,EAAEP,EAAE6D,GAAG,mBAAmBhD,EAAEU,WAAM,IAASL,EAAEX,EAAEW,EAAEJ,IAAIP,EAAEO,EAAEuD,aAAaxD,EAAEsB,MAAK,GAAI,OAAOjC,EAAE4B,IAAIb,EAAEV,CAAC,CAA4uB,SAAS6D,EAAEpE,EAAEC,EAAEC,EAAEoB,GAAG,IAAInB,EAAEC,EAAE,GAAG,mBAAmBJ,EAAEuB,KAAK,CAAC,IAAIpB,EAAEH,EAAE2B,IAAIvB,EAAE,EAAED,GAAGC,EAAED,EAAEwC,OAAOvC,IAAID,EAAEC,KAAKD,EAAEC,GAAGwB,GAAG5B,EAAEC,EAAEmE,EAAEjE,EAAEC,GAAGH,EAAEC,EAAEoB,IAAI,OAAOrB,CAAC,CAACD,EAAE8B,KAAK7B,IAAIqB,IAAIrB,GAAGD,EAAEuB,OAAOtB,EAAEkB,aAAalB,EAAEyC,EAAE1C,IAAIE,EAAEoE,aAAatE,EAAE8B,IAAI7B,GAAG,OAAOA,EAAED,EAAE8B,KAAK,GAAG7B,EAAEA,GAAGA,EAAEoE,kBAAkB,MAAMpE,GAAG,GAAGA,EAAEsE,UAAU,OAAOtE,CAAC,CAA6G,SAAS+D,EAAEhE,EAAEC,EAAEC,EAAEoB,GAAG,IAAInB,EAAEC,EAAEC,EAAEC,EAAEN,EAAEyB,IAAIlB,EAAEP,EAAEuB,KAAKf,EAAEP,EAAEC,GAAGO,EAAE,MAAMD,KAAO,EAAEA,EAAE2B,KAAK,GAAG,OAAO3B,GAAG,MAAMF,GAAGG,GAAGH,GAAGE,EAAEiB,KAAKlB,GAAGC,EAAEe,KAAK,OAAOrB,EAAE,GAAGoB,GAAGb,EAAE,EAAE,GAAG,IAAIN,EAAED,EAAE,EAAEE,EAAEF,EAAE,EAAEC,GAAG,GAAGC,EAAEH,EAAE0C,QAAQ,GAAG,OAAOnC,EAAEP,EAAEI,EAAEF,GAAG,EAAEA,IAAIC,SAAW,EAAEI,EAAE2B,MAAM7B,GAAGE,EAAEiB,KAAKlB,GAAGC,EAAEe,KAAK,OAAOlB,EAAE,QAAQ,CAAC,SAASmE,EAAExE,EAAEC,EAAEC,GAAG,KAAKD,EAAE,GAAGD,EAAEyE,YAAYxE,EAAE,MAAMC,EAAE,GAAGA,GAAGF,EAAEC,GAAG,MAAMC,EAAE,GAAG,iBAAiBA,GAAGW,EAAE6D,KAAKzE,GAAGC,EAAEA,EAAE,IAAI,CAAC,SAASyE,EAAE3E,EAAEC,EAAEC,EAAEoB,EAAEnB,GAAG,IAAIC,EAAEC,EAAEL,EAAE,GAAG,SAASC,EAAE,GAAG,iBAAiBC,EAAEF,EAAE4E,MAAMC,QAAQ3E,MAAM,CAAC,GAAG,iBAAiBoB,IAAItB,EAAE4E,MAAMC,QAAQvD,EAAE,IAAIA,EAAE,IAAIrB,KAAKqB,EAAEpB,GAAGD,KAAKC,GAAGsE,EAAExE,EAAE4E,MAAM3E,EAAE,IAAI,GAAGC,EAAE,IAAID,KAAKC,EAAEoB,GAAGpB,EAAED,IAAIqB,EAAErB,IAAIuE,EAAExE,EAAE4E,MAAM3E,EAAEC,EAAED,GAAG,MAAA,GAAS,KAAKA,EAAE,IAAI,KAAKA,EAAE,GAAGG,EAAEH,IAAIA,EAAEA,EAAE6E,QAAQvE,EAAE,OAAOF,EAAEJ,EAAE8E,cAAc9E,EAAEI,KAAKL,GAAG,cAAcC,GAAG,aAAaA,EAAEI,EAAE2E,MAAM,GAAG/E,EAAE+E,MAAM,GAAGhF,EAAEC,IAAID,EAAEC,EAAE,IAAID,EAAEC,EAAEA,EAAEG,GAAGF,EAAEA,EAAEoB,EAAEpB,EAAEA,EAAEoB,EAAEpB,GAAGA,EAAEA,EAAEM,EAAER,EAAEiF,iBAAiBhF,EAAEG,EAAEM,EAAED,EAAEL,IAAIJ,EAAEkF,oBAAoBjF,EAAEG,EAAEM,EAAED,EAAEL,OAAO,CAAC,GAAG,8BAA8BD,EAAEF,EAAEA,EAAE6E,QAAQ,cAAc,KAAKA,QAAQ,SAAS,UAAG,GAAU,SAAS7E,GAAG,UAAUA,GAAG,QAAQA,GAAG,QAAQA,GAAG,QAAQA,GAAG,YAAYA,GAAG,YAAYA,GAAG,WAAWA,GAAG,WAAWA,GAAG,QAAQA,GAAG,WAAWA,GAAGA,KAAKD,EAAE,IAAIA,EAAEC,GAAG,MAAMC,EAAE,GAAGA,EAAE,MAAMF,CAAC,OAAOA,GAAG,CAAC,mBAAmBE,IAAI,MAAMA,IAAG,IAAKA,GAAG,KAAKD,EAAE,GAAGD,EAAEmF,gBAAgBlF,GAAGD,EAAEoF,aAAanF,EAAE,WAAWA,GAAG,GAAGC,EAAE,GAAGA,GAAG,CAAC,CAAC,SAASmF,EAAErF,GAAG,OAAO,SAASE,GAAG,GAAGsC,KAAKvC,EAAE,CAAC,IAAIqB,EAAEkB,KAAKvC,EAAEC,EAAEqB,KAAKvB,GAAG,GAAG,MAAME,EAAEoB,EAAEpB,EAAEoB,EAAEd,SAAAA,GAAYN,EAAEoB,EAAEA,EAAEpB,EAAE,OAAO,OAAOoB,EAAErB,EAAEqF,MAAMrF,EAAEqF,MAAMpF,GAAGA,EAAE,CAAC,CAAC,CAAC,SAASqD,EAAEvD,EAAEE,EAAEoB,EAAEnB,EAAEC,EAAEC,EAAEC,EAAEC,EAAEC,EAAEC,GAAG,IAAIC,EAAEkD,EAAEjD,EAAEC,EAAEC,EAAEgD,EAAExC,EAAEyC,EAAEpB,EAAEE,EAAEE,EAAEG,EAAEiB,EAAEE,EAAEmB,EAAEvB,EAAEQ,EAAEG,EAAEzE,EAAEqB,KAAK,QAAG,IAASrB,EAAE8B,YAAY,OAAO,KAAK,IAAIV,EAAEa,MAAM3B,KAAK,GAAGc,EAAEa,KAAK9B,EAAE,CAACE,EAAEL,EAAE4B,IAAIR,EAAEQ,OAAOpB,EAAET,EAAE4B,MAAMnB,EAAER,GAAGF,EAAE,GAAG,mBAAmB2E,EAAE,IAAI,GAAGb,EAAE5D,EAAEsB,MAAMkB,EAAE,cAAciC,GAAGA,EAAEa,UAAUC,OAAO7C,GAAGlC,EAAEiE,EAAEe,cAAcvF,EAAEO,EAAEqB,KAAKe,EAAEpC,EAAEkC,EAAEA,EAAEpB,MAAMmE,MAAMjF,EAAEkB,GAAGzB,EAAEmB,EAAES,IAAIV,GAAGuC,EAAE1D,EAAE6B,IAAIT,EAAES,KAAKH,GAAGgC,EAAEgC,KAAKlD,EAAExC,EAAE6B,IAAI6B,EAAE,IAAIe,EAAEb,EAAEhB,IAAI5C,EAAE6B,IAAI6B,EAAE,IAAIrB,EAAEuB,EAAEhB,GAAGc,EAAE5B,YAAY2C,EAAEf,EAAE6B,OAAOI,GAAGjD,GAAGA,EAAEkD,IAAIlC,GAAGA,EAAEmC,QAAQnC,EAAEmC,MAAM,CAAA,GAAInC,EAAEJ,IAAIrD,EAAEQ,EAAEiD,EAAEb,KAAI,EAAGa,EAAEoC,IAAI,GAAGpC,EAAEqC,IAAI,IAAIvD,GAAG,MAAMkB,EAAEsC,MAAMtC,EAAEsC,IAAItC,EAAEmC,OAAOrD,GAAG,MAAMiC,EAAEwB,2BAA2BvC,EAAEsC,KAAKtC,EAAEmC,QAAQnC,EAAEsC,IAAIjF,EAAE,CAAA,EAAG2C,EAAEsC,MAAMjF,EAAE2C,EAAEsC,IAAIvB,EAAEwB,yBAAyBrC,EAAEF,EAAEsC,OAAOtF,EAAEgD,EAAEpC,MAAMX,EAAE+C,EAAEmC,MAAMnC,EAAE3B,IAAI/B,EAAES,EAAE+B,GAAG,MAAMiC,EAAEwB,0BAA0B,MAAMvC,EAAEwC,oBAAoBxC,EAAEwC,qBAAqB1D,GAAG,MAAMkB,EAAEyC,mBAAmBzC,EAAEoC,IAAIhD,KAAKY,EAAEyC,uBAAuB,CAAC,GAAG3D,GAAG,MAAMiC,EAAEwB,0BAA0BrC,IAAIlD,GAAG,MAAMgD,EAAE0C,2BAA2B1C,EAAE0C,0BAA0BxC,EAAEhB,GAAG5C,EAAE+B,KAAKX,EAAEW,MAAM2B,EAAE9B,KAAK,MAAM8B,EAAE2C,wBAAuB,IAAK3C,EAAE2C,sBAAsBzC,EAAEF,EAAEsC,IAAIpD,GAAG,CAAC,IAAI5C,EAAE+B,KAAKX,EAAEW,MAAM2B,EAAEpC,MAAMsC,EAAEF,EAAEmC,MAAMnC,EAAEsC,IAAItC,EAAEb,KAAI,GAAI7C,EAAE4B,IAAIR,EAAEQ,IAAI5B,EAAEyB,IAAIL,EAAEK,IAAIzB,EAAEyB,IAAI6E,KAAK,SAASxG,GAAGA,IAAIA,EAAE4B,GAAG1B,EAAE,GAAG+C,EAAE,EAAEA,EAAEW,EAAEqC,IAAItD,OAAOM,IAAIW,EAAEoC,IAAIhD,KAAKY,EAAEqC,IAAIhD,IAAIW,EAAEqC,IAAI,GAAGrC,EAAEoC,IAAIrD,QAAQrC,EAAE0C,KAAKY,GAAG,MAAM5D,CAAC,CAAC,MAAM4D,EAAE6C,qBAAqB7C,EAAE6C,oBAAoB3C,EAAEF,EAAEsC,IAAIpD,GAAGJ,GAAG,MAAMkB,EAAE8C,oBAAoB9C,EAAEoC,IAAIhD,KAAK,WAAWY,EAAE8C,mBAAmB9F,EAAEC,EAAEgD,EAAE,EAAE,CAAC,GAAGD,EAAEnB,QAAQK,EAAEc,EAAEpC,MAAMsC,EAAEF,EAAEN,IAAItD,EAAE4D,EAAE9B,KAAI,EAAGoC,EAAEjE,EAAEiD,IAAIkB,EAAE,EAAE1B,EAAE,CAAC,IAAIkB,EAAEmC,MAAMnC,EAAEsC,IAAItC,EAAEb,KAAI,EAAGmB,GAAGA,EAAEhE,GAAGQ,EAAEkD,EAAE6B,OAAO7B,EAAEpC,MAAMoC,EAAEmC,MAAMnC,EAAEnB,SAAS8C,EAAE,EAAEA,EAAE3B,EAAEqC,IAAItD,OAAO4C,IAAI3B,EAAEoC,IAAIhD,KAAKY,EAAEqC,IAAIV,IAAI3B,EAAEqC,IAAI,EAAE,MAAM,GAAGrC,EAAEb,KAAI,EAAGmB,GAAGA,EAAEhE,GAAGQ,EAAEkD,EAAE6B,OAAO7B,EAAEpC,MAAMoC,EAAEmC,MAAMnC,EAAEnB,SAASmB,EAAEmC,MAAMnC,EAAEsC,UAAUtC,EAAEb,OAAOqB,EAAE,IAAIR,EAAEmC,MAAMnC,EAAEsC,IAAI,MAAMtC,EAAE+C,kBAAkBxG,EAAEc,EAAEA,EAAE,CAAA,EAAGd,GAAGyD,EAAE+C,oBAAoBjE,IAAI/B,GAAG,MAAMiD,EAAEgD,0BAA0B/C,EAAED,EAAEgD,wBAAwBhG,EAAEC,IAAImD,EAAEtD,EAAE,MAAMA,GAAGA,EAAEa,OAAOc,GAAG,MAAM3B,EAAEe,MAAMuC,EAAE6C,EAAEnG,EAAEc,MAAMc,WAAW/B,EAAEoD,EAAE3D,EAAEc,EAAEkD,GAAGA,EAAE,CAACA,GAAG9D,EAAEoB,EAAEnB,EAAEC,EAAEC,EAAEC,EAAEC,EAAEC,EAAEC,GAAGmD,EAAEf,KAAK3C,EAAE4B,IAAI5B,EAAEiC,UAAUyB,EAAEoC,IAAIrD,QAAQrC,EAAE0C,KAAKY,GAAGvC,IAAIuC,EAAEgC,IAAIhC,EAAEhC,GAAG,KAAK,OAAO5B,GAAG,GAAGE,EAAE+B,IAAI,KAAKzB,GAAG,MAAMH,EAAE,GAAGL,EAAE8G,KAAK,CAAC,IAAI5G,EAAEiC,KAAK3B,EAAE,IAAI,IAAID,GAAG,GAAGA,EAAEgE,UAAUhE,EAAE8D,aAAa9D,EAAEA,EAAE8D,YAAYhE,EAAEA,EAAE0G,QAAQxG,IAAI,KAAKL,EAAE4B,IAAIvB,CAAC,KAAK,CAAC,IAAIiE,EAAEnE,EAAEsC,OAAO6B,KAAKtD,EAAEb,EAAEmE,IAAIwC,EAAE9G,EAAE,MAAMA,EAAE4B,IAAIR,EAAEQ,IAAI5B,EAAEyB,IAAIL,EAAEK,IAAI3B,EAAE8G,MAAME,EAAE9G,GAAGD,EAAE6B,IAAI9B,EAAEE,EAAEoB,EAAE,MAAM,MAAMjB,GAAGH,EAAE+B,KAAKX,EAAEW,KAAK/B,EAAEyB,IAAIL,EAAEK,IAAIzB,EAAE4B,IAAIR,EAAEQ,KAAKvB,EAAEL,EAAE4B,IAA0Z,SAAW5B,EAAEoB,EAAEnB,EAAEC,EAAEC,EAAEC,EAAEC,EAAEC,EAAEC,GAAG,IAAIC,EAAEkD,EAAEhD,EAAEC,EAAEI,EAAE4C,EAAExC,EAAEyC,EAAE3D,EAAEqB,OAAOb,EAAE0B,EAAEf,EAAEE,MAAMe,EAAEjB,EAAEC,KAAK,GAAG,OAAOgB,EAAElC,EAAE,6BAA6B,QAAQkC,EAAElC,EAAE,qCAAqCA,IAAIA,EAAE,gCAAgC,MAAMC,EAAE,IAAII,EAAE,EAAEA,EAAEJ,EAAEqC,OAAOjC,IAAI,IAAIO,EAAEX,EAAEI,KAAK,iBAAiBO,KAAKsB,IAAIA,EAAEtB,EAAEgG,WAAW1E,EAAE,GAAGtB,EAAEsD,UAAU,CAACrE,EAAEe,EAAEX,EAAEI,GAAG,KAAK,KAAK,CAAC,GAAG,MAAMR,EAAE,CAAC,GAAG,MAAMqC,EAAE,OAAO2E,SAASC,eAAe9E,GAAGnC,EAAEgH,SAASE,gBAAgB/G,EAAEkC,EAAEF,EAAEgF,IAAIhF,GAAG7B,IAAIP,EAAEqH,KAAKrH,EAAEqH,IAAIhG,EAAEhB,GAAGE,GAAE,GAAIF,EAAE,IAAI,CAAC,GAAG,MAAMiC,EAAEuB,IAAIzB,GAAG7B,GAAGN,EAAEqH,MAAMlF,IAAInC,EAAEqH,KAAKlF,OAAO,CAAC,GAAG/B,EAAEA,GAAGN,EAAEwH,KAAKtH,EAAEuH,aAAajH,GAAG,MAAMF,EAAE,IAAIwD,EAAE,GAAGpD,EAAE,EAAEA,EAAER,EAAEwH,WAAW/E,OAAOjC,IAAIoD,GAAG7C,EAAEf,EAAEwH,WAAWhH,IAAIiH,MAAM1G,EAAE0E,MAAM,IAAIjF,KAAKoD,EAAE,GAAG7C,EAAE6C,EAAEpD,GAAG,YAAYA,QAAE,GAAS,2BAA2BA,EAAEE,EAAEK,OAAA,KAAYP,KAAK2B,GAAG,CAAC,GAAG,SAAS3B,GAAG,iBAAiB2B,GAAG,WAAW3B,GAAG,mBAAmB2B,EAAE,SAASsC,EAAEzE,EAAEQ,EAAE,KAAKO,EAAEZ,EAAE,CAAC,IAAIK,KAAK2B,EAAEpB,EAAEoB,EAAE3B,GAAG,YAAYA,EAAEG,EAAEI,EAAE,2BAA2BP,EAAEkD,EAAE3C,EAAE,SAASP,EAAEmD,EAAE5C,EAAE,WAAWP,EAAEW,EAAEJ,EAAET,GAAG,mBAAmBS,GAAG6C,EAAEpD,KAAKO,GAAG0D,EAAEzE,EAAEQ,EAAEO,EAAE6C,EAAEpD,GAAGL,GAAG,GAAGuD,EAAEpD,GAAGI,IAAIgD,EAAEgE,QAAQhH,EAAEgH,QAAQhE,EAAEgE,QAAQ1H,EAAE2H,aAAa3H,EAAE2H,UAAUjE,EAAEgE,QAAQtG,EAAEK,IAAI,WAAWf,IAAIV,EAAE2H,UAAU,IAAIlE,EAAE,YAAYrC,EAAEC,KAAKrB,EAAE4H,QAAQ5H,EAAEY,EAAED,GAAGA,EAAE,CAACA,GAAGS,EAAEnB,EAAEC,EAAE,iBAAiBmC,EAAE,+BAA+BlC,EAAEC,EAAEC,EAAED,EAAEA,EAAE,GAAGH,EAAEwB,KAAKe,EAAEvC,EAAE,GAAGK,EAAEC,GAAG,MAAMH,EAAE,IAAII,EAAEJ,EAAEqC,OAAOjC,KAAKQ,EAAEZ,EAAEI,IAAIF,IAAIE,EAAE,QAAQ,YAAY6B,GAAG,MAAMsB,EAAE3D,EAAEiF,gBAAgB,SAAS,MAAMtB,IAAIA,IAAI3D,EAAEQ,IAAI,YAAY6B,IAAIsB,GAAG,UAAUtB,GAAGsB,GAAGC,EAAEpD,KAAKiE,EAAEzE,EAAEQ,EAAEmD,EAAEC,EAAEpD,GAAGL,GAAGK,EAAE,UAAU,MAAMW,GAAGA,GAAGnB,EAAEQ,IAAIiE,EAAEzE,EAAEQ,EAAEW,EAAEyC,EAAEpD,GAAGL,GAAG,CAAC,OAAOH,CAAC,CAAn0D6H,CAAEzG,EAAEQ,IAAI5B,EAAEoB,EAAEnB,EAAEC,EAAEC,EAAEC,EAAEE,EAAEC,GAAG,OAAOC,EAAET,EAAE+H,SAAStH,EAAER,GAAG,IAAIA,EAAEiC,SAAI,EAAO5B,CAAC,CAAC,SAASyG,EAAEhH,GAAGA,GAAGA,EAAE+B,MAAM/B,EAAE+B,IAAID,KAAI,GAAI9B,GAAGA,EAAE2B,KAAK3B,EAAE2B,IAAIsG,QAAQjB,EAAE,CAAC,SAAStD,EAAE1D,EAAEE,EAAEoB,GAAG,IAAA,IAAQnB,EAAE,EAAEA,EAAEmB,EAAEqB,OAAOxC,IAAIgE,EAAE7C,EAAEnB,GAAGmB,IAAInB,GAAGmB,IAAInB,IAAIF,EAAE8B,KAAK9B,EAAE8B,IAAI7B,EAAEF,GAAGA,EAAEwG,KAAK,SAAStG,GAAG,IAAIF,EAAEE,EAAE8F,IAAI9F,EAAE8F,IAAI,GAAGhG,EAAEwG,KAAK,SAASxG,GAAGA,EAAEwH,KAAKtH,EAAE,EAAE,OAAOF,GAAGC,EAAE6B,IAAI9B,EAAEE,EAAE+B,IAAI,CAAC,EAAE,CAAC,SAAS4E,EAAE7G,GAAG,MAAM,iBAAiBA,GAAG,MAAMA,GAAGA,EAAE6B,KAAK7B,EAAE6B,IAAI,EAAE7B,EAAEc,EAAEd,GAAGA,EAAEkI,IAAIrB,GAAG5F,EAAE,CAAA,EAAGjB,EAAE,CAA+6C,SAASmE,EAAEnE,EAAEE,EAAEoB,GAAG,IAAI,GAAG,mBAAmBtB,EAAE,CAAC,IAAIG,EAAE,mBAAmBH,EAAEmC,IAAIhC,GAAGH,EAAEmC,MAAMhC,GAAG,MAAMD,IAAIF,EAAEmC,IAAInC,EAAEE,GAAG,MAAMF,EAAEmI,QAAQjI,CAAC,OAAOF,GAAGC,EAAE6B,IAAI9B,EAAEsB,EAAE,CAAC,CAAC,SAAS2C,EAAEjE,EAAEE,EAAEoB,GAAG,IAAInB,EAAEC,EAAE,GAAGH,EAAEmI,SAASnI,EAAEmI,QAAQpI,IAAIG,EAAEH,EAAE0B,OAAOvB,EAAEgI,SAAShI,EAAEgI,SAASnI,EAAE8B,KAAKqC,EAAEhE,EAAE,KAAKD,IAAI,OAAOC,EAAEH,EAAE+B,KAAK,CAAC,GAAG5B,EAAEkI,qBAAqB,IAAIlI,EAAEkI,sBAAsB,OAAOrI,GAAGC,EAAE6B,IAAI9B,EAAEE,EAAE,CAACC,EAAE0C,KAAK1C,EAAEmD,IAAI,IAAI,CAAC,GAAGnD,EAAEH,EAAE2B,IAAI,IAAIvB,EAAE,EAAEA,EAAED,EAAEwC,OAAOvC,IAAID,EAAEC,IAAI6D,EAAE9D,EAAEC,GAAGF,EAAEoB,GAAG,mBAAmBtB,EAAEuB,MAAMD,GAAGJ,EAAElB,EAAE8B,KAAK9B,EAAE+B,IAAI/B,EAAE4B,GAAG5B,EAAE8B,SAAI,CAAM,CAAC,SAAS+D,EAAE7F,EAAEC,EAAEC,GAAG,OAAOsC,KAAKR,YAAYhC,EAAEE,EAAE,CAAC,SAASoI,EAAEpI,EAAEoB,EAAEnB,GAAG,IAAME,EAAEC,EAAEC,EAAEe,GAAG4F,WAAW5F,EAAE4F,SAASqB,iBAAiBtI,EAAE2B,IAAI3B,EAAE2B,GAAG1B,EAAEoB,GAAGjB,GAAK,EAAsB,KAAeiB,EAAEK,IAAIrB,EAAE,GAAGC,EAAE,GAAGgD,EAAEjC,EAAEpB,EAAUoB,EAAGK,IAAjhS,SAAW1B,EAAEC,EAAEoB,GAAG,IAAInB,EAAEC,EAAEC,EAAEC,EAAE,GAAG,IAAID,KAAKH,EAAE,OAAOG,EAAEF,EAAED,EAAEG,GAAG,OAAOA,EAAED,EAAEF,EAAEG,GAAGC,EAAED,GAAGH,EAAEG,GAAG,GAAGmI,UAAU7F,OAAO,IAAIrC,EAAEgC,SAASkG,UAAU7F,OAAO,EAAE3C,EAAEwH,KAAKgB,UAAU,GAAGlH,GAAG,mBAAmBrB,GAAG,MAAMA,EAAEwI,aAAa,IAAIpI,KAAKJ,EAAEwI,kBAAa,IAASnI,EAAED,KAAKC,EAAED,GAAGJ,EAAEwI,aAAapI,IAAI,OAAOgB,EAAEpB,EAAEK,EAAEH,EAAEC,EAAE,KAAK,CAAivRyD,CAAExB,EAAE,KAAK,CAACnC,IAAIG,GAAGM,EAAEA,EAAEW,EAAEmC,aAAuBpD,EAAE,KAAKiB,EAAEoH,WAAW1I,EAAEwH,KAAKlG,EAAEmG,YAAY,KAAKnH,EAAUD,EAAEA,EAAEyB,IAAIR,EAAEoH,WAA1L,MAAuMnI,GAAGmD,EAAEpD,EAAEJ,EAAEK,EAAE,CAAy1BP,EAAEY,EAAEoE,MAAM/E,EAAE,CAAC6B,IAAI,SAAS9B,EAAEC,EAAEC,EAAEoB,GAAG,IAAA,IAAQnB,EAAEC,EAAEC,EAAEJ,EAAEA,EAAE2B,IAAI,IAAIzB,EAAEF,EAAE8B,OAAO5B,EAAEyB,GAAG,IAAI,IAAIxB,EAAED,EAAE6B,cAAc,MAAM5B,EAAEuI,2BAA2BxI,EAAEyI,SAASxI,EAAEuI,yBAAyB3I,IAAIK,EAAEF,EAAE4C,KAAK,MAAM5C,EAAE0I,oBAAoB1I,EAAE0I,kBAAkB7I,EAAEsB,GAAG,CAAA,GAAIjB,EAAEF,EAAE4C,KAAK1C,EAAE,OAAOF,EAAEyF,IAAIzF,CAAC,OAAOF,GAAGD,EAAEC,CAAC,CAAC,MAAMD,CAAC,GAAGE,EAAE,EAAwDqC,EAAEiD,UAAUoD,SAAS,SAAS5I,EAAEC,GAAG,IAAIC,EAAEA,EAAE,MAAMsC,KAAK0D,KAAK1D,KAAK0D,KAAK1D,KAAKuD,MAAMvD,KAAK0D,IAAI1D,KAAK0D,IAAIjF,EAAE,CAAA,EAAGuB,KAAKuD,OAAO,mBAAmB/F,IAAIA,EAAEA,EAAEiB,EAAE,CAAA,EAAGf,GAAGsC,KAAKhB,QAAQxB,GAAGiB,EAAEf,EAAEF,GAAG,MAAMA,GAAGwC,KAAKP,MAAMhC,GAAGuC,KAAKyD,IAAIjD,KAAK/C,GAAG6C,EAAEN,MAAM,EAAED,EAAEiD,UAAUsD,YAAY,SAAS9I,GAAGwC,KAAKP,MAAMO,KAAKV,KAAI,EAAG9B,GAAGwC,KAAKwD,IAAIhD,KAAKhD,GAAG8C,EAAEN,MAAM,EAAED,EAAEiD,UAAUC,OAAOpD,EAAElC,EAAE,GAAGE,EAAE,mBAAmB0I,QAAQA,QAAQvD,UAAUsB,KAAKkC,KAAKD,QAAQE,WAAWC,WAAW5I,EAAE,SAASN,EAAEC,GAAG,OAAOD,EAAEiC,IAAIJ,IAAI5B,EAAEgC,IAAIJ,GAAG,EAAEoB,EAAEC,IAAI,EAAE3C,EAAE,8BAA8BC,EAAE,EAAEC,EAAE4E,GAAE,GAAI3E,EAAE2E,GAAE,GCA1tV,IAAuE9E,EAAE,EAAkB,SAASL,EAAEI,EAAEgB,EAAEtB,EAAEI,EAAED,EAAED,GAAGoB,IAAIA,EAAE,IAAI,IAAIZ,EAAEF,EAAEG,EAAEW,EAAE,GAAG,QAAQX,EAAE,IAAIH,KAAKG,EAAE,CAAA,EAAGW,EAAE,OAAOd,EAAEE,EAAEY,EAAEd,GAAGG,EAAEH,GAAGc,EAAEd,GAAG,IAAIP,EAAE,CAACsB,KAAKjB,EAAEkB,MAAMb,EAAEc,IAAIzB,EAAE0B,IAAIhB,EAAEiB,IAAI,KAAKC,GAAG,KAAKC,IAAI,EAAEC,IAAI,KAAKC,IAAI,KAAKC,iBAAY,EAAOC,MAAM1B,EAAE2B,KAAI,EAAGC,IAAI,EAAEgH,SAAShJ,EAAEiJ,OAAOlJ,GAAG,GAAG,mBAAmBI,IAAII,EAAEJ,EAAEmI,cAAc,IAAIjI,KAAKE,OAAE,IAASC,EAAEH,KAAKG,EAAEH,GAAGE,EAAEF,IAAI,OAAOH,EAAE+B,OAAO/B,EAAE+B,MAAMnC,GAAGA,CAAC,CCA1wB,IAAIqB,EAAEjB,EAAEH,EAAEC,EAAEC,EAAE,EAAEG,EAAE,GAAGC,EAAER,EAAEM,EAAEE,EAAEqB,IAAInB,EAAEF,EAAE0C,IAAItC,EAAEJ,EAAEwH,OAAO/H,EAAEO,EAAEuB,IAAIV,EAAEb,EAAE4H,QAAQ3H,EAAED,EAAEoB,GAAG,SAASjB,EAAEX,EAAEsB,GAAGd,EAAEwF,KAAKxF,EAAEwF,IAAI3F,EAAEL,EAAEI,GAAGkB,GAAGlB,EAAE,EAAE,IAAIF,EAAEG,EAAEgJ,MAAMhJ,EAAEgJ,IAAI,CAACzH,GAAG,GAAGoE,IAAI,KAAK,OAAOhG,GAAGE,EAAE0B,GAAGe,QAAQzC,EAAE0B,GAAGoB,KAAK,CAAA,GAAI9C,EAAE0B,GAAG5B,EAAE,CAAC,SAASc,GAAEd,GAAG,OAAOI,EAAE,EAAS,SAAWJ,EAAEE,GAAK,IAAIE,EAAEO,EAAEW,IAAI,GAAG,GAAGlB,EAAEkB,EAAEtB,GAAGI,EAAE2B,MAAM3B,EAAEwB,GAAG,CAAQqC,QAAE,EAAO/D,GAAG,SAASF,GAAG,IAAIsB,EAAElB,EAAEkJ,IAAIlJ,EAAEkJ,IAAI,GAAGlJ,EAAEwB,GAAG,GAAGvB,EAAED,EAAEkB,EAAEA,EAAEtB,GAAGsB,IAAIjB,IAAID,EAAEkJ,IAAI,CAACjJ,EAAED,EAAEwB,GAAG,IAAIxB,EAAE2B,IAAI6G,SAAS,CAAA,GAAI,GAAGxI,EAAE2B,IAAI1B,GAAGA,EAAEkJ,KAAK,CAAC,IAAIhJ,EAAE,SAASP,EAAEsB,EAAEjB,GAAG,IAAID,EAAE2B,IAAIsH,IAAI,OAAM,EAAG,IAAInJ,EAAEE,EAAE2B,IAAIsH,IAAIzH,GAAG4H,OAAO,SAASxJ,GAAG,QAAQA,EAAE+B,GAAG,GAAG,GAAG7B,EAAEuJ,MAAM,SAASzJ,GAAG,OAAOA,EAAEsJ,GAAG,GAAG,OAAO9I,GAAGA,EAAEgH,KAAKhF,KAAKxC,EAAEsB,EAAEjB,GAAG,IAAIF,EAAEC,EAAE2B,IAAIP,QAAQxB,EAAE,OAAOE,EAAE+H,QAAQ,SAASjI,GAAG,GAAGA,EAAEsJ,IAAI,CAAC,IAAIhI,EAAEtB,EAAE4B,GAAG,GAAG5B,EAAE4B,GAAG5B,EAAEsJ,IAAItJ,EAAEsJ,SAAI,EAAOhI,IAAItB,EAAE4B,GAAG,KAAKzB,GAAE,EAAG,CAAC,GAAGK,GAAGA,EAAEgH,KAAKhF,KAAKxC,EAAEsB,EAAEjB,IAAIF,CAAC,EAAEE,EAAEkJ,KAAI,EAAG,IAAI/I,EAAEH,EAAEkG,sBAAsBjG,EAAED,EAAEoG,oBAAoBpG,EAAEoG,oBAAoB,SAASzG,EAAEsB,EAAEjB,GAAG,GAAGmC,KAAKV,IAAI,CAAC,IAAI5B,EAAEM,EAAEA,OAAE,EAAOD,EAAEP,EAAEsB,EAAEjB,GAAGG,EAAEN,CAAC,CAACI,GAAGA,EAAEkH,KAAKhF,KAAKxC,EAAEsB,EAAEjB,EAAE,EAAEA,EAAEkG,sBAAsBhG,CAAC,CAAC,OAAOH,EAAEkJ,KAAKlJ,EAAEwB,EAAE,CAArtBgC,CAAEK,GAAEjE,EAAE,CAAgtB,SAASa,GAAEb,EAAEE,GAAG,IAAIC,EAAEQ,EAAEW,IAAI,IAAId,EAAE0F,KAAKtD,GAAEzC,EAAEkJ,IAAInJ,KAAKC,EAAEyB,GAAG5B,EAAEG,EAAED,EAAEA,EAAEG,EAAEgJ,IAAIrD,IAAIhD,KAAK7C,GAAG,CAAiF,SAASiE,GAAEpE,GAAG,OAAOI,EAAE,EAAEoE,GAAE,WAAW,MAAM,CAAC2D,QAAQnI,EAAE,EAAE,GAAG,CAAsN,SAASwE,GAAExE,EAAEK,GAAG,IAAIH,EAAES,EAAEW,IAAI,GAAG,OAAOsB,GAAE1C,EAAEmJ,IAAIhJ,KAAKH,EAAE0B,GAAG5B,IAAIE,EAAEmJ,IAAIhJ,EAAEH,EAAE8F,IAAIhG,GAAGE,EAAE0B,EAAE,CAAqiB,SAAS+C,KAAI,IAAA,IAAQ3E,EAAEA,EAAEO,EAAE8C,YAAYrD,EAAEsD,KAAKtD,EAAEqJ,IAAI,IAAIrJ,EAAEqJ,IAAIrD,IAAIiC,QAAQjB,IAAGhH,EAAEqJ,IAAIrD,IAAIiC,QAAQ9D,IAAGnE,EAAEqJ,IAAIrD,IAAI,EAAE,OAAO1E,GAAGtB,EAAEqJ,IAAIrD,IAAI,GAAGxF,EAAEsB,IAAIR,EAAEtB,EAAEiC,IAAI,CAAC,CAACzB,EAAEqB,IAAI,SAAS7B,GAAGK,EAAE,KAAKC,GAAGA,EAAEN,EAAE,EAAEQ,EAAEoB,GAAG,SAAS5B,EAAEsB,GAAGtB,GAAGsB,EAAEK,KAAKL,EAAEK,IAAI2F,MAAMtH,EAAEsH,IAAIhG,EAAEK,IAAI2F,KAAK7G,GAAGA,EAAET,EAAEsB,EAAE,EAAEd,EAAE0C,IAAI,SAASlD,GAAGU,GAAGA,EAAEV,GAAGsB,EAAE,EAAE,IAAInB,GAAGE,EAAEL,EAAE+B,KAAKsH,IAAIlJ,IAAID,IAAIG,GAAGF,EAAE6F,IAAI,GAAG3F,EAAE2F,IAAI,GAAG7F,EAAEyB,GAAGqG,QAAQ,SAASjI,GAAGA,EAAEsJ,MAAMtJ,EAAE4B,GAAG5B,EAAEsJ,KAAKtJ,EAAEE,EAAEF,EAAEsJ,SAAI,CAAM,KAAKnJ,EAAE6F,IAAIiC,QAAQjB,IAAG7G,EAAE6F,IAAIiC,QAAQ9D,IAAGhE,EAAE6F,IAAI,GAAG1E,EAAE,IAAIpB,EAAEG,CAAC,EAAEG,EAAEwH,OAAO,SAAShI,GAAGY,GAAGA,EAAEZ,GAAG,IAAIsB,EAAEtB,EAAE+B,IAAIT,GAAGA,EAAE+H,MAAM/H,EAAE+H,IAAIrD,IAAIrD,SAAS,IAAIpC,EAAEyC,KAAK1B,IAAInB,IAAIK,EAAEkJ,yBAAyBvJ,EAAEK,EAAEkJ,wBAAwBzI,IAAG0D,KAAIrD,EAAE+H,IAAIzH,GAAGqG,QAAQ,SAASjI,GAAGA,EAAEE,IAAIF,EAAEqJ,IAAIrJ,EAAEE,GAAGF,EAAEE,OAAE,CAAM,IAAIA,EAAEG,EAAE,IAAI,EAAEG,EAAEuB,IAAI,SAAS/B,EAAEsB,GAAGA,EAAEkF,KAAK,SAASxG,GAAG,IAAIA,EAAEgG,IAAIiC,QAAQjB,IAAGhH,EAAEgG,IAAIhG,EAAEgG,IAAIwD,OAAO,SAASxJ,GAAG,OAAOA,EAAE4B,IAAIuC,GAAEnE,EAAE,EAAE,OAAOK,GAAGiB,EAAEkF,KAAK,SAASxG,GAAGA,EAAEgG,MAAMhG,EAAEgG,IAAI,GAAG,GAAG1E,EAAE,GAAGd,EAAEsB,IAAIzB,EAAEL,EAAEiC,IAAI,CAAC,GAAGhC,GAAGA,EAAED,EAAEsB,EAAE,EAAEd,EAAE4H,QAAQ,SAASpI,GAAGqB,GAAGA,EAAErB,GAAG,IAAIsB,EAAEjB,EAAEL,EAAE+B,IAAI1B,GAAGA,EAAEgJ,MAAMhJ,EAAEgJ,IAAIzH,GAAGqG,QAAQ,SAASjI,GAAG,IAAIgH,GAAEhH,EAAE,OAAOA,GAAGsB,EAAEtB,CAAC,CAAC,GAAGK,EAAEgJ,SAAI,EAAO/H,GAAGd,EAAEsB,IAAIR,EAAEjB,EAAE4B,KAAK,EAAE,IAAII,GAAE,mBAAmBqH,sBAAsB,SAASzI,GAAEjB,GAAG,IAAIsB,EAAEjB,EAAE,WAAWsJ,aAAazJ,GAAGmC,IAAGuH,qBAAqBtI,GAAG4H,WAAWlJ,EAAE,EAAEE,EAAEgJ,WAAW7I,EAAE,IAAIgC,KAAIf,EAAEoI,sBAAsBrJ,GAAG,CAAC,SAAS2G,GAAEhH,GAAG,IAAIsB,EAAEjB,EAAEH,EAAEF,EAAE+B,IAAI,mBAAmB7B,IAAIF,EAAE+B,SAAI,EAAO7B,KAAKG,EAAEiB,CAAC,CAAC,SAAS6C,GAAEnE,GAAG,IAAIsB,EAAEjB,EAAEL,EAAE+B,IAAI/B,EAAE4B,KAAKvB,EAAEiB,CAAC,CAAC,SAASsB,GAAE5C,EAAEsB,GAAG,OAAOtB,GAAGA,EAAE2C,SAASrB,EAAEqB,QAAQrB,EAAEkF,KAAK,SAASlF,EAAEjB,GAAG,OAAOiB,IAAItB,EAAEK,EAAE,EAAE,CAAC,SAAS4D,GAAEjE,EAAEsB,GAAG,MAAM,mBAAmBA,EAAEA,EAAEtB,GAAGsB,CAAC,CCCt6G,MAWMuI,GAAS,CACpBC,QAAS,UACTC,aAAc,UAEdC,KAAM,yBAINC,YAAa,UACbC,gBAAiB,WA6BNC,GACH,MADGA,GAEH,OAFGA,GAGF,OAIEC,GAAS,qCAGTC,GACL,oBADKA,GAEH,oBCzBGC,GCrCE,goBDuCFC,GEvCE,8UFyCFC,GGzCE,+TH0CFC,GI1CE,wNCsBR,SAASC,IAAQC,IACpBA,EAAAC,MACAA,EAAAC,OACAA,EAAAC,MACAA,EAAAC,YACAA,GAAc,EAAAC,UACdA,EAAApG,MACAA,EAAAqG,KACAA,EAAAC,OACAA,EAAAC,YACAA,KACG3J,IAEH,MAAM4J,QAAEA,EAAAtD,QAASA,GAAYuD,GAAQ,KACjC,IAAKV,EAAK,MAAO,CAAES,QAAS,YAAatD,QAAS,IAElD,MAAMwD,EAAaX,EAAIY,OAEjBC,EAAeF,EAAWG,MAAM,qBAOtC,MAAO,CAAEL,QANOI,EAAeA,EAAa,GAAK,YAM/B1D,QAFJwD,EAAWxG,QAAQ,eAAgB,IAAIA,QAAQ,eAAgB,MAG9E,CAAC6F,IA4BJ,OACIe,EAAC,MAAA,CACGN,UACAR,QACAC,SACAG,YACApG,MAAO,CACH+G,QAAS,eACTC,cAAe,SACfC,WAAY,EACZZ,KAAM,OACNC,OAAQ,kBACLtG,GAEPkH,MAAM,gCACFtK,EACJuK,wBAAyB,CAAEnE,OA1CdyD,GAAQ,KACzB,IAAKvD,EAAS,MAAO,GACrB,IAAIkE,EAAclE,EAElB,GAAIiD,EAAa,CAEb,MAAMkB,OAAqB,IAAThB,EAAqBA,EAAO,OACxCiB,OAAyB,IAAXhB,EAAuBA,EAAS,eACpDc,EAAcA,EACTlH,QAAQ,iBAAkB,SAASmH,MACnCnH,QAAQ,mBAAoB,WAAWoH,KAChD,CAEA,QAAoB,IAAhBf,EAA2B,CAC3B,MAAMgB,EAAmBpI,OAAOoH,GAChCa,EAAc,wBAAwBtH,KAAKsH,GACrCA,EAAYlH,QAAQ,yBAA0B,iBAAiBqH,MAC/DH,EAAYlH,QACV,wDACA,qBAAqBqH,KAEjC,CAEA,OAAOH,GACR,CAAClE,EAASiD,EAAaE,EAAMC,EAAQC,KAoB/B7I,SAAAwI,GAASY,EAAC,QAAA,CAAOpJ,SAAAwI,KAG9B,CCnEO,MAAMsB,GAAa,EACxBC,aACAC,oBACAC,aACAC,cACAC,SACAC,qBAAoB,EACpBC,aACAC,gBACAC,iBACAC,iBACAC,qBAEA,MAAMC,EAAUnD,GAAOC,QACjBmD,EAAiBP,EACnB,mBAAmB7C,GAAOC,YAAYM,KACtCA,GAEE8C,EAA4C,CAChDC,SAAU,QACVC,MAAO,OACPC,OAAQ,OACR1B,QAAS,OACT2B,cAAe,SACfC,WAAY,WACZC,IAAK,MACLC,OAAQ,OACRC,WAAY,uBASRC,EAAyC,CAC7C/C,MAAO,OACPC,OAAQ,OACR+C,SAAU,OACVC,UAAW,OACXC,aAAc3D,GACd4D,gBAAiBf,EACjBgB,MAAO,UACPC,OAAQ,OACRC,OAAQ,UACRvC,QAAS,OACT4B,WAAY,SACZY,eAAgB,SAChBC,WAAY,oBAAoB/D,iBAA+BA,KAC/D8C,SAAU,WACVtB,WAAY,KASRwC,EAAiB5B,IAAWD,EAC5B8B,EAAcD,EAAiB7D,GAAyBgC,EAAc/B,GAAmBF,GAazFgE,EAA2C,CAC/CpB,SAAU,WACVqB,IAAK,MACLpB,MAAO,MACPxC,MAAO,OACPC,OAAQ,OACRiD,aAAc,MACdG,OAAQ,OACRQ,WAAY,cACZP,OAAQ,UACRvC,QAAS,OACT4B,WAAY,SACZY,eAAgB,SAChBO,SAAU,OACVC,WAAY,IACZX,MAAOnE,GAAOG,KACd4E,QAAS,KAGLC,EAAc,CAClB/G,EACAgH,EACAC,EACAC,EACAC,IAEAC,EAAC,MAAA,CACClE,UAAW,eAAegE,IAC1BpK,MAAO,CAAEsJ,OAAQ,WACjBY,UAGCxM,SAAA,CAAAyM,GACCrD,EAAC,SAAA,CACCnK,KAAK,SACLqD,MAAO2J,EACPO,QAAUxO,IACRA,EAAE6O,kBACFJ,KAEF,aAAW,QAEXzM,SAAAoJ,EAAChB,IAAQC,IAAKF,GAAkB,cAAY,OAAOG,MAAO,GAAIC,OAAQ,OAK1Ea,EAAC,MAAA,CACC9G,MAAO,CACLwK,aAAcL,EAAU,OAAS,IACjCM,UAAW,gBACPJ,EAAa,CAAEK,UAAW,OAAQC,UAAW,QAAW,CAAA,GAG7DjN,SAAAwF,OAKP,OACEoH,EAAAM,EAAA,CACElN,SAAA,CAAAoJ,EAAC,QAAA,CAAOpJ,SAAA,mLAKKuH,GAAOG,qNAOFiD,kLAMW5C,usCAuC7BqB,EAAC,MAAA,CAAIV,UAAU,sBAAsBpG,MAAOsI,EAC1C5K,SAAA4M,EAAC,MAAA,CAAIlE,UAAU,qBAAqBpG,MAnKU,CAClD+G,QAAS,OACT4B,WAAY,SACZC,IAAK,QAkKElL,SAAA,CAAAqK,IACEH,IACAK,GACDgC,EACE,iDACAjC,EACA,KACA,sBACA,GAIHC,GACCgC,EACEhC,EACAC,EACAC,EACA,uBACA,GAIJrB,EAAC,SAAA,CACC9G,MAAO+I,EACPmB,QA5JU,KACdT,EACF9B,IACSC,EACTF,IAEAD,KAuJMoD,aAAenP,IACboP,OAAOC,OAAOrP,EAAEsP,cAAchL,MAAO,CACnCmJ,gBAAiBlE,GAAOE,aACxB8F,UAAW,iBAGfC,aAAexP,IACboP,OAAOC,OAAOrP,EAAEsP,cAAchL,MAAO,CACnCiL,UAAW,cAGf,aAAYxB,EAAiB,gBAAkB7B,EAAc,iBAAmB,kBAEhFlK,SAAAoJ,EAAChB,GAAA,CACCC,IAAK2D,EACL,cAAY,OACZ1J,MAtLiC,CAC3CgG,MAAO,OACPC,OAAQ,OACRc,QAAS,sBCrDAoE,GAAyB,iCAEhCC,OAAuBC,IAAI,CAC/B,SACA,QACA,WACA,WACA,OACA,SAIIC,OAAwBD,IAAI,CAChC,OACA,SACA,OACA,OACA,UACA,WACA,UACA,IACA,MACA,OACA,WACA,OACA,SACA,iBACA,iBACA,OACA,OACA,UAGIE,OAA8BF,IAAI,CACtC,IACA,SACA,QACA,WACA,SACA,UACA,UACA,WAGIG,OAAwBH,IAAI,CAChC,SACA,OACA,MACA,WACA,SACA,WACA,QACA,SACA,WACA,UACA,YACA,SACA,aACA,aAGII,OAAuBC,IAC7B,IAAIC,IAAgB,EAMhBC,OAAqBF,IAGlB,MAAMG,GAAkBC,GAC7BF,GAAeG,IAAID,GAEfE,GAAuBjL,GAC3BA,EAAMb,QAAQ,OAAQ,KAAKyG,OAEvBsF,GAAgBC,IACpB,IACE,OAAO,IAAIC,IAAID,EAAQA,GAAQE,IACjC,CAAA,MACE,OAAOF,CACT,GAGIG,GAAgBtL,IACpB,GAAqB,iBAAVA,GAAgC,OAAVA,EAC/B,OAAO,EAGT,MAAMuL,EAAMvL,EACZ,MACqB,iBAAZuL,EAAIC,KACY,iBAAhBD,EAAIE,SACXrQ,MAAMC,QAAQkQ,EAAIG,QAClBtQ,MAAMC,QAAQkQ,EAAII,gBACQ,iBAAnBJ,EAAIK,YACY,iBAAhBL,EAAIM,SAITC,GAAiB9L,IACrB,GAAc,OAAVA,EACF,OAAO,KAGT,MAAM+L,EAASC,OAAOC,SAASjM,EAAO,IACtC,OAAOgM,OAAOE,MAAMH,GAAU,KAAOA,GAGjCI,GAAkBC,GACNnB,GAAoBmB,EAAQC,aAAa,SAAW,IACjEjN,cACAkN,MAAM,KAAK,IACI,GAwCdC,GAAwB,KAC5B,GAA8B,oBAAnBC,eAIX,IACE,MAAMC,EAAaC,KAAKC,UACtBvR,MAAMwR,KAAKlC,GAAiBmC,UAAUpP,KACpC,CAAC1C,EAAGoD,IAAMpD,EAAE6Q,WAAazN,EAAEyN,aAG/BY,eAAeM,QAAQ1C,GAAwBqC,EACjD,OAASM,GACPC,QAAQC,KAAK,uCAAwCF,EACvD,GAiBIG,GACJ1K,IAEA,MAAM2K,EAAc/R,MAAMwR,KAAKlC,GAAiBmC,UAC7ChJ,OAAQuJ,GAAUA,EAAM5B,MAAQhJ,EAAQgJ,KACxC/N,KAAK,CAAC1C,EAAGoD,IAAMA,EAAEyN,WAAa7Q,EAAE6Q,YAChCvM,MAAM,EAAG,GAEZ,GAA2B,IAAvB8N,EAAYnQ,OACd,OAAOwF,EAAQiJ,QAGjB,MAAM4B,EAAiB,CACrB,yBACGF,EAAY5K,IAAK6K,IAClB,MAAME,EAAiBrC,GAAoBmC,EAAM3B,SACjD,MAAO,KAAK2B,EAAM5B,UAAU8B,OAE9BC,KAAK,MAEP,MAAO,GAAG/K,EAAQiJ,cAAc4B,KAG5BG,GAAapB,IACjB,GAA4C,SAAxCA,EAAQC,aAAa,eACvB,OAAO,EAGT,GAAID,aAAmBqB,aAAerB,EAAQsB,OAC5C,OAAO,EAGT,MAAMzO,EAAQ0O,OAAOC,iBAAiBxB,GACtC,GAAsB,SAAlBnN,EAAM+G,SAA2C,WAArB/G,EAAM4O,WACpC,OAAO,EAGT,MAAMC,EAAO1B,EAAQ2B,wBACrB,OAAOD,EAAK7I,MAAQ,GAAK6I,EAAK5I,OAAS,GAQnC8I,GAA0B5B,IAC9B,IAAI6B,EAAS7B,EAAQ8B,cACrB,KAAOD,GAAUA,IAAW1M,SAAS4M,MAAM,CACzC,MAAMC,EAAYH,EAAOI,QAAQjP,cACjC,GAAIoL,GAAwB8D,IAAIF,GAAY,OAAO,EACnD,MAAMG,EAAapC,GAAe8B,GAClC,GAAIxD,GAAkB6D,IAAIC,GAAa,OAAO,EAC9CN,EAASA,EAAOC,aAClB,CACA,OAAO,GAGHM,GAAiBnD,IACrB,IACE,OAAO,IAAID,IAAIC,EAAMsC,OAAOc,SAASpD,MAAMA,IAC7C,CAAA,MACE,OAAOA,CACT,GAGIqD,GAAmBtC,IACvB,MAAM/H,EAAO4G,IACVmB,aAAmBqB,YAAcrB,EAAQuC,UAAYvC,EAAQwC,cAC5D,IACFC,UAAU,EAAG,IACTC,EAAY7D,GAAoBmB,EAAQC,aAAa,eAAiB,IACtElH,EAAQ8F,GAAoBmB,EAAQC,aAAa,UAAY,IAC7D0C,EAAc9D,GAClBmB,EAAQC,aAAa,gBAAkB,IAEnCrK,EAAOiJ,GAAoBmB,EAAQC,aAAa,SAAW,IAC3DrM,EACJoM,aAAmB4C,kBACnB5C,aAAmB6C,qBACnB7C,aAAmB8C,kBACfjE,GAAoBmB,EAAQpM,OAAS,IACrC,GAEAmP,EACJ9K,GAAQyK,GAAa3J,GAAS4J,GAAe/O,GAASgC,GAAQ,GAE1DoN,EAAMhD,EAAQiC,QAAQjP,cAG5B,GAAY,QAARgQ,EAAe,CACjB,MAAMC,EAAMpE,GAAoBmB,EAAQC,aAAa,QAAU,IAC/D,GAAIgD,EAAK,OAAOA,EAChB,MAAMrK,EAAMoH,EAAQC,aAAa,QAAU,GACrCiD,EAAWtK,EAAIsH,MAAM,KAAKiD,OAAOjD,MAAM,KAAK,IAAM,GACxD,OAAOgD,EAAW,QAAQA,IAAaE,GAAiBpD,EAC1D,CAEA,GAAY,QAARgD,EACF,OAAON,GAAa3J,GAAS,OAG/B,GAAY,UAARiK,EAAiB,CACnB,MAAMK,EAAYrD,EAAQC,aAAa,SAAW,OAC5CqD,EAAetD,aAAmB4C,iBAAmB5C,EAAQpM,MAAQ,GAE3E,MAAO,GAAGyP,KAAaN,GAAS,UADdO,EAAe,SAASA,EAAab,UAAU,EAAG,OAAS,IAE/E,CAEA,GAAY,aAARO,EAAoB,CACtB,MAAMM,EAAetD,aAAmB6C,oBAAsB7C,EAAQpM,MAAQ,GAE9E,MAAO,YAAYmP,GAAS,aADVO,EAAe,SAASA,EAAab,UAAU,EAAG,OAAS,IAE/E,CAEA,GAAY,WAARO,EAAkB,CACpB,MAAMO,EAAWvD,EACXwD,EAAeD,EAASE,kBAAkB,IAAIjB,aAAahJ,QAAU,GAE3E,MAAO,UAAUuJ,GAAS,WADRS,EAAe,SAASA,KAAkB,IAE9D,CAEA,OAAIT,GAGGK,GAAiBpD,IAIpBoD,GAAoBpD,IACxB,MAAM0D,EAAO1D,EAAQ2D,WAAa,GAE5BC,EAAWF,EAAK1O,QAAQ,KAC9B,IAAiB,IAAb4O,EAAiB,OAAOF,EAAKjB,UAAU,EAAG,IAE9C,OADgBiB,EAAKjB,UAAU,EAAGoB,KAAKC,IAAIF,EAAW,GAAI,KAAK7Q,QAAQ,OAAQ,KAAKyG,QAClE,YAKduK,GAAuB/D,IAC3B,MAAMgD,EAAMhD,EAAQiC,QAAQjP,cACtBgR,EAAOjE,GAAeC,GAG5B,GAAa,WAATgE,GAA6B,WAARhB,EAAkB,MAAO,SAClD,GAAa,SAATgB,GAA2B,MAARhB,EAAa,MAAO,OAC3C,GAAa,QAATgB,EAAgB,MAAO,MAC3B,GAAa,aAATA,EAAqB,MAAO,WAChC,GAAa,aAATA,GAAgC,UAARhB,GAAoD,aAAjChD,EAAQC,aAAa,QAAyB,MAAO,WACpG,GAAa,UAAT+D,GAA6B,UAARhB,GAAoD,UAAjChD,EAAQC,aAAa,QAAsB,MAAO,QAC9F,GAAa,WAAT+D,EAAmB,MAAO,SAC9B,GAAa,aAATA,GAA+B,WAARhB,EAAkB,MAAO,SACpD,GAAa,YAATgB,GAA8B,aAARhB,EAAoB,MAAO,WACrD,GAAa,cAATgB,EAAsB,MAAO,YACjC,GAAa,WAATA,GAA8B,UAARhB,GAAoD,UAAjChD,EAAQC,aAAa,QAAsB,MAAO,SAC/F,GAAa,eAAT+D,EAAuB,MAAO,aAClC,GAAa,WAATA,GAA6B,WAARhB,EAAkB,MAAO,SAClD,GAAa,aAATgB,EAAqB,MAAO,WAChC,GAAY,UAARhB,EAAiB,CAEnB,MAAO,SADGhD,EAAQC,aAAa,SAAW,SAE5C,CACA,MAAY,YAAR+C,EAA0B,UAClB,YAARA,EAA0B,UACkB,SAA5ChD,EAAQC,aAAa,mBAAsC,WAGxD+D,EAAO,GAAGA,EAAK,GAAGC,gBAAgBD,EAAK/Q,MAAM,KAAO,IAAI+P,MAG3DkB,GAAmBlE,IACvB,MAAMmE,EAAmB,GAEnBC,EAAUpE,EAAQC,aAAa,gBACrB,SAAZmE,EAAoBD,EAAOlT,KAAK,WACf,UAAZmT,GAAqBD,EAAOlT,KAAK,eAE1C,MAAMoT,EAAWrE,EAAQC,aAAa,iBACrB,SAAboE,EAAqBF,EAAOlT,KAAK,YACf,UAAboT,GAAsBF,EAAOlT,KAAK,aAe3C,MAZiB,SADA+O,EAAQC,aAAa,kBACbkE,EAAOlT,KAAK,YAEjC+O,aAAmB4C,mBACA,aAAjB5C,EAAQxQ,MAAwC,UAAjBwQ,EAAQxQ,MACzC2U,EAAOlT,KAAK+O,EAAQsE,QAAU,UAAY,eAI1CtE,EAAQuE,aAAa,aAAyD,SAA1CvE,EAAQC,aAAa,mBAC3DkE,EAAOlT,KAAK,YAGPkT,GAoIHK,GAAgB,CAACzL,EAAe0L,IACf,IAAjBA,EAAM7T,OAAqB,GAAGmI,aAC3B,GAAGA,OAAW0L,EAAMtD,KAAK,QA0CrBuD,GAA+B,KAC1C,GAAsB,oBAAXnD,OAAwB,OACnC,MAAMnC,EAAMN,GAAayC,OAAOc,SAASpD,MACzCX,GAAiBqG,OAAOvF,GACxBe,MAGWyE,GAAiB,CAACC,GAAwB,KACrD,GAAsB,oBAAXtD,QAA8C,oBAAbpM,SAC1C,MAAO,CACLmK,MAAO,GACPC,cAAe,GACfF,QAAS,GACTyF,eAAgBvG,KApcU,MAC9B,IAAIC,IAA2C,oBAAnB4B,eAA5B,CAIA5B,IAAgB,EAEhB,IACE,MAAMuG,EAAM3E,eAAe4E,QAAQhH,IACnC,IAAK+G,EACH,OAGF,MAAMpF,EAASW,KAAK2E,MAAMF,GAC1B,IAAK/V,MAAMC,QAAQ0Q,GACjB,OAGF,IAAA,MAAW/L,KAAS+L,EACbT,GAAatL,IAzIkB,IA4IhCA,EAAM6L,SAGVnB,GAAiB4G,IAAItR,EAAMwL,IAAKxL,GAE9B0K,GAAiB6G,KAAO,GAC1BvE,QAAQwE,KACN,0CAA0C9G,GAAiB6G,OAGjE,OAASxE,GACPC,QAAQC,KAAK,uCAAwCF,EACvD,CA/BA,GAqcA0E,GACA,MAAMjG,EAAMN,GAAayC,OAAOc,SAASpD,MAGnCqG,EAtLwB,MAC9B,MACMC,EADcvW,MAAMwR,KAAKrL,SAASqQ,iBAAiB,MACrBvS,MAAM,ECvZN,KDyZ9BqM,EAAkB,GAClBmG,MAAcvH,IACdwH,EAAsC,GACtCZ,MAAiBvG,IACvB,IAAIoH,EAAY,EAEhB,IAAA,IAASC,EAAQ,EAAGA,EAAQL,EAAgB3U,OAAQgV,GAAS,EAAG,CAC9D,MAAM5F,EAAUuF,EAAgBK,GAC1B5C,EAAMhD,EAAQiC,QAAQjP,cAE5B,GAAIiL,GAAiBiE,IAAIc,GAAM,SAC/B,GAAI7E,GAAkB+D,IAAIc,GAAM,SAChC,IAAK5B,GAAUpB,GAAU,SAEzB,MAAMgE,EAAOjE,GAAeC,GACtBnN,EAAQ0O,OAAOC,iBAAiBxB,GAChCf,EAAOe,EAAQC,aAAa,QAC5B4F,EAAsBzH,GAAwB8D,IAAIc,KAAiB,MAARA,GAAe8C,QAAQ7G,IAClF8G,EAAoB1H,GAAkB6D,IAAI8B,GAC1CgC,EAAWtG,GAAcM,EAAQC,aAAa,aAC9CgG,EAA0B,OAAbD,GAAqBA,GAAY,EAC9CE,EAAoC,YAAjBrT,EAAMsJ,OACzBgK,EAAgE,SAA5CnG,EAAQC,aAAa,mBACzCmG,EACJpG,EAAQuE,aAAa,aACqB,SAA1CvE,EAAQC,aAAa,iBAGvB,GACU,MAAR+C,GACA/D,IACCA,EAAKoH,WAAW,OAChBpH,EAAKoH,WAAW,eACjB,CACA,MAAMC,EAAelE,GAAcnD,GAE7BN,EAAKgH,IACLY,EAAO,MAAM5H,MAFL2D,GAAgBtC,IAAYsG,QAEJA,IAEjCb,EAAQvD,IAAIoE,KACfb,EAAQe,IAAIF,GACZhH,EAAMrO,KAAKsV,GACXzB,EAAWI,IAAIvG,EAAIqB,GAEvB,CAUA,KANE6F,GACAE,GACAI,GACAF,GACAC,IAE4BE,EAAY,SAI1C,GAAIxE,GAAuB5B,GAAU,SAErC,MAAMrB,EAAKgH,IACXb,EAAWI,IAAIvG,EAAIqB,GAEnB,MAAMyG,EAAS1C,GAAoB/D,GAC7B+C,EAAQT,GAAgBtC,GACxB0G,EAAcxC,GAAgBlE,GAE9BuG,EAAO,MAAM5H,MAAO8H,OAAY1D,KADpB2D,EAAY9V,OAAS,EAAI,KAAK8V,EAAYvF,KAAK,SAAW,KAGtEwF,GACHd,EAAsB,EAAI,IAC1BE,EAAoB,EAAI,IACxBE,EAAa,EAAI,IACjBC,EAAmB,EAAI,IACvBC,EAAoB,EAAI,GAE3BT,EAAWzU,KAAK,CAAE0N,KAAI4H,OAAMI,QAAOf,QAAO5F,WAC5C,CAEA,MAAMT,EAAgBmG,EACnBrU,KAAK,CAAC1C,EAAGoD,IAAMA,EAAE4U,MAAQhY,EAAEgY,OAAShY,EAAEiX,MAAQ7T,EAAE6T,OAChD3S,MAAM,ECtfsB,KDuf5BkD,IAAK1H,GAAMA,EAAE8X,MAEhB,MAAO,CACLjH,MAAOA,EAAMrM,MAAM,EC7fE,KD8frBsM,gBACAuF,eA2FW8B,GAGb,GAFAnI,GAAiB6G,EAAKR,YAEjBD,EAAc,CACjB,MAAMgC,EAASvI,GAAiBM,IAAIQ,GACpC,GAAIyH,EAEF,OADAjG,QAAQwE,KAAK,iCAAiChG,KACvC,CACLE,MAAOuH,EAAOvH,MACdC,cAAesH,EAAOtH,cACtBF,QAASyB,GAAwB+F,GACjC/B,WAAYrG,GAGlB,CAEAmC,QAAQwE,KAAK,kCAAkChG,KAE/C,MAAM0H,EAAW9X,MAAMwR,KAAKrL,SAASqQ,iBAAiB,eACnD/N,OAAQuI,GAAYoB,GAAUpB,IAC9B7J,IAAK6J,GACJ,KAAKnB,GAAoBmB,EAAQwC,aAAe,OAEjD/K,OAAQ8O,GAAkB,OAATA,GACjBtT,MAAM,EC5mBiB,KD8mBpBoM,EAtF+B,EACrCD,EACArG,EACAgO,EACAD,EACAxH,EACAC,EACAyH,IAEiB,CACfxC,GAAc,OAAQ,CACpB,UAAUpF,GAAO,YACjB,YAAYrG,GAAS,YACrB,WAAWgO,GAAQ,cAErBvC,GAAc,WAAYsC,GAC1BtC,GAAc,mBAAoBwC,GAClCxC,GAAc,QAASlF,GACvBkF,GAAc,uBAAwBjF,IAGxB4B,KAAK,QAiEL8F,CACd7H,EACAjK,SAAS4D,MACT5D,SAASqB,gBAAgBuQ,KACzBD,EACAxB,EAAKhG,MACLgG,EAAK/F,cAvHmB,MAC1B,MAAM2H,EACJ/R,SAASgS,cAAc,iCAAmChS,SAAS4M,KAC/DqF,EAAqB,GACrBC,MAAWnJ,IAEXwH,EAAa1W,MAAMwR,KAAK0G,EAAK1B,iBAAiB,sBACpD,IAAA,MAAW8B,KAAQ5B,EAAY,CAC7B,IAAKtE,GAAUkG,GAAO,SAEtB,MAAMrP,EAAO4G,GAAoByI,EAAK9E,aAAe,IACrD,GAAKvK,KAAQA,EAAKrH,OAAS,MACvByW,EAAKnF,IAAIjK,KAEboP,EAAKb,IAAIvO,GACTmP,EAASnW,KAAK,KAAKgH,KACfmP,EAASxW,QC1gBgB,ID0gBa,KAC5C,CAEA,OAAOwW,GAqGLG,IAGIvG,EAAgC,CACpC5B,MACAC,UACAC,MAAOgG,EAAKhG,MACZC,cAAe+F,EAAK/F,cACpBC,WAAYgI,KAAKC,MACjBhI,QA5mBsC,GAsnBxC,OAPAnB,GAAiB4G,IAAI9F,EAAK4B,GAncI,MAC9B,GAAI1C,GAAiB6G,MCzLS,GD0L5B,OAGF,MAAMuC,EAAS1Y,MAAMwR,KAAKlC,GAAiBmC,UAAUpP,KACnD,CAAC1C,EAAGoD,IAAMpD,EAAE6Q,WAAazN,EAAEyN,YAEvBmI,EAAWD,EAAO9W,OChMM,GDiM9B,IAAA,IAASxC,EAAI,EAAGA,EAAIuZ,EAAUvZ,GAAK,EACjCkQ,GAAiBqG,OAAO+C,EAAOtZ,GAAGgR,MA0bpCwI,GACAzH,KACAS,QAAQwE,KACN,oCAAoChG,UAAYd,GAAiB6G,QAG5D,CACL7F,MAAO0B,EAAM1B,MACbC,cAAeyB,EAAMzB,cACrBF,QAASyB,GAAwBE,GACjC8D,WAAYrG,KExpBVoJ,GAAkB,wBACXC,GAA0B,IAEjCC,GAAgB,+BAMhBC,GAAqB,qBAmBdC,GACXjU,IAEA,GAA4B,oBAAjBkU,aACX,IACEA,aAAaxH,QACXsH,GACA1H,KAAKC,UAAU,IAAKvM,EAAOmU,QAASX,KAAKC,QAE7C,CAAA,MAEA,GAoBWW,GAA0B,KACT,oBAAjBF,cACXA,aAAaG,WAAWL,KAyNbM,GAAQ,CAAC1U,EAAekQ,EAAayE,IAChD1E,KAAKC,IAAIyE,EAAK1E,KAAK0E,IAAIzE,EAAKlQ,IA6BjB4U,GAAwBC,MACnCC,EACAC,EApTgC,OAsThC,GAAsB,oBAAXpH,OACT,OAGF,MAAMqH,EAASrH,OAAOsH,QAChBC,EAAQJ,EAAUE,EACpB/E,KAAKkF,IAAID,GAAS,SAIhB,IAAI9R,QAAeE,IACvB,MAAM8R,EACJzH,OAAO5J,uBAAA,CACLsR,GAAmC1H,OAAOpK,WAAW,IAAM8R,EAASC,YAAYzB,OAAQ,KAEtF0B,EAAYD,YAAYzB,MAExB2B,EAAQ3B,IACZ,MACM4B,EAAWf,IADDb,EAAM0B,GACWR,EAAY,EAAG,GAC1CW,EA5CiB,CAACD,KAC1BxF,KAAK0F,IAAI1F,KAAK2F,GAAKH,GAAY,GAAK,EA2CpBI,CAAcJ,GAC5B9H,OAAOmI,SAAS,EAAGd,EAASE,EAAQQ,GAEhCD,EAAW,EACbL,EAAII,GAEJlS,KAIJ8R,EAAII,MAIFO,GAAoB,CAACxN,EAAqB3L,EAAW1B,KACzDqN,EAAOtJ,MAAM+W,KAAO,GAAGpZ,MACvB2L,EAAOtJ,MAAM4J,IAAM,GAAG3N,OAQlB+a,GAAsB,CAAC1N,EAAqB2N,KAChD3N,EAAOtJ,MAAMkX,QAAUD,EAAU,IAAM,KAGnCE,GAAoBhK,IACxB,MAAMnN,EAAQ0O,OAAOC,iBAAiBxB,GACtC,MAAyB,SAAlBnN,EAAM+G,SAA2C,WAArB/G,EAAM4O,YAA6C,MAAlB5O,EAAMkX,SAwBtEE,GAA2B,KAC/B,MAAMC,EAtBoB,MAC1B,MAAMA,EAAsB,GAEtBC,EAAchV,SAASuJ,eAAe,mBACxCyL,GAAaC,YACfF,EAAMjZ,KAAKkZ,EAAYC,YAGzB,MAAMC,EAAclV,SAASqQ,iBAA8B,KAC3D,IAAA,MAAW8E,KAAMD,EACVC,EAAGF,aAGHF,EAAMK,SAASD,EAAGF,aACrBF,EAAMjZ,KAAKqZ,EAAGF,aAIlB,OAAOF,GAIOM,GAEd,IAAA,MAAWtD,KAAQgD,EAAO,CACxB,MAAMO,EAAQvD,EAAKC,cAA2B,sBAC9C,GAAIsD,GAAST,GAAiBS,GAC5B,OAAOA,CAEX,CAEA,IAAA,MAAWvD,KAAQgD,EAAO,CACxB,MAAMQ,EAASxD,EAAKC,cAA2B,wBAC/C,GAAIuD,GAAUV,GAAiBU,GAC7B,OAAOA,CAEX,CAEA,OAAO,MAGHC,GAAwB,KAC5B,MAAMC,EAASX,KACf,IAAKW,EACH,MAAO,CACLpa,EAAGqa,KACH/b,EAAG+b,MAIP,MAAMnJ,EAAOkJ,EAAOjJ,wBACpB,MAAO,CACLnR,EAAGkR,EAAKkI,KAAOrI,OAAOuJ,QAAUD,KAChC/b,EAAG4S,EAAKjF,IAAM8E,OAAOsH,QAAUgC,OAItBE,GAAkB,KAC7B,GAAwB,oBAAb5V,UAA8C,oBAAXoM,OAC5C,OAGF,MAAMpF,EAAShH,SAASuJ,eAAemJ,IACjC1L,aAAkBkF,aAIxBwI,GAAoB1N,GAAQ,IAG9B,IAAI6O,IAAiC,EACrC,MAAMC,GAAgC,KAChCD,KAGJA,IAAiC,EAEjC7V,SAASjC,iBAAiB,YAAcK,IACtC,MAAM4I,EAAShH,SAASuJ,eAAemJ,IACvC,KAAM1L,aAAkBkF,aACtB,OAGF,GAA6B,MAAzBlF,EAAOtJ,MAAMkX,QACf,OAGF,MAAQvZ,EAAAA,EAAG1B,EAAAA,GArGW,CAACqN,IAAA,CACzB3L,EAAGoP,OAAOsL,WAAW/O,EAAOtJ,MAAM+W,OAAS,EAC3C9a,EAAG8Q,OAAOsL,WAAW/O,EAAOtJ,MAAM4J,MAAQ,IAmGvB0O,CAAkBhP,GAC7BiP,EAAW7X,EAAM8X,MACjBC,EAAW/X,EAAMgY,MACN1H,KAAK2H,MAAMJ,EAAW5a,EAAG8a,EAAWxc,IAnc1B,IAsczB+a,GAAoB1N,GAAQ,OAkD5BsP,GAAahD,MAAOjY,EAAW1B,KACnC,MAAMqN,EA9Ca,MACnB,MAAMuP,EAAWvW,SAASuJ,eAAemJ,IACzC,GAAI6D,EAIF,OAFAA,EAAS7Y,MAAM6J,WAAa5E,GAAOC,QACnCkT,KACOS,EAGT,MAAMvP,EAAShH,SAASwW,cAAc,OACtCxP,EAAOwC,GAAKkJ,GACZ1L,EAAOtJ,MAAMuI,SAAW,WACxB,MAAMwQ,EAAgBjB,KACtBxO,EAAOtJ,MAAM+W,KAAO,GAAGgC,EAAcpb,MACrC2L,EAAOtJ,MAAM4J,IAAM,GAAGmP,EAAc9c,MACpCqN,EAAOtJ,MAAMkX,QAAU,IAEvB5N,EAAOtJ,MAAMgG,MAAQ,OACrBsD,EAAOtJ,MAAMiG,OAAS,OACtBqD,EAAOtJ,MAAMkJ,aAAe,MAC5B,MAAM8P,EAAY/T,GAAOC,QAazB,OAZAoE,EAAOtJ,MAAM6J,WAAamP,EAE1B1P,EAAOtJ,MAAMqJ,OAAS,oBACtBC,EAAOtJ,MAAMiZ,UAAY,oCACzB3P,EAAOtJ,MAAMkZ,UAAY,aACzB5P,EAAOtJ,MAAM6I,OAAS,aACtBS,EAAOtJ,MAAMmZ,cAAgB,OAC7B7P,EAAOtJ,MAAMiL,UAAY,wBACzB3B,EAAOtJ,MAAMwJ,WAAa,cAAqC0L,iBAAmDA,6BAClH5S,SAAS4M,KAAKkK,YAAY9P,GAC1B8O,KACArK,QAAQwE,KAAK,gCAAgCyG,oBACtC1P,GAaQ+P,GACwB,SAAnC/P,EAAOgQ,QAAQC,kBACjBjQ,EAAOgQ,QAAQC,gBAAkB,YAZH3D,WAChC,MAAMO,EACJzH,OAAO5J,uBAAA,CACLsR,GAAmC1H,OAAOpK,WAAW,IAAM8R,EAASC,YAAYzB,OAAQ,WACtF,IAAIzQ,QAAeE,IACvB8R,EAAI,IAAM9R,QAQJmV,IAKR,KAFkD,MAAzBlQ,EAAOtJ,MAAMkX,SAEf,CAErB,MAAM6B,EAAgBjB,KACtBd,GAAoB1N,GAAQ,GAC5BwN,GAAkBxN,EAAQyP,EAAcpb,EAAGob,EAAc9c,SACnD,IAAIkI,QAASE,GAAYC,WAAWD,EAAS4Q,IACrD,CAGA+B,GAAoB1N,GAAQ,GAC5BwN,GAAkBxN,EAAQ3L,EAAG1B,SACvB,IAAIkI,QAASE,GAAYC,WAAWD,EAAS4Q,MAG/CwE,GAAoBtM,IACxB,MAAM0B,EAAO1B,EAAQ2B,wBACrB,MAAO,CACLnR,EAAGkR,EAAKkI,KAAOrI,OAAOuJ,QAAUpJ,EAAK7I,MAAQ,EAC7C/J,EAAG4S,EAAKjF,IAAM8E,OAAOsH,QAAUnH,EAAK5I,OAAS,IAI3CyT,GAA4B,uCAE5BC,GAAyBC,IAC7B,IACE,OAAOtX,SAASgS,cAAcsF,EAChC,OAAS9L,GACP,MAAM+L,EAAgBD,EAAS/S,MAAM6S,IACrC,IAAKG,EAEH,OADA9L,QAAQC,KAAK,8BAA8B4L,IAAY9L,GAChD,KAGT,MAAMgM,EAAeD,EAAc,IAAIlT,QAAU,IAC3CoT,EAAeF,EAAc,IAAIlT,QAAU,GACjD,IAAKoT,EAEH,OADAhM,QAAQC,KAAK,0CAA0C4L,KAChD,KAGT,IACE,MAAM/G,EAAavQ,SAASqQ,iBAAiBmH,GAC7C,IAAA,MAAWE,KAAanH,EACtB,GAAImH,EAAUrK,aAAa+H,SAASqC,GAClC,OAAOC,EAGX,OAAO,IACT,OAASC,GAEP,OADAlM,QAAQC,KAAK,uCAAuC4L,IAAYK,GACzD,IACT,CACF,GAwCIC,GAAqB,CACzB/M,EACAxQ,EACAgB,EACA1B,KAEAkR,EAAQgN,cACN,IAAIC,WAAWzd,EAAM,CACnB0d,SAAS,EACTC,YAAY,EACZC,KAAM7L,OACN8L,QAAS7c,EAAI+Q,OAAOuJ,QACpBwC,QAASxe,EAAIyS,OAAOsH,YA0BpB0E,GAAkB,CAACvN,EAAsB/H,IACzC+H,aAAmB4C,kBAAoB5C,aAAmB6C,qBAC5D7C,EAAQwN,QAvBoB,EAC9BxN,EACA/H,KAEA,MAAMxE,EACJuM,aAAmB6C,oBACfA,oBAAoBpP,UACpBmP,iBAAiBnP,UACjBga,EAAa9P,OAAO+P,yBAAyBja,EAAW,SAC1Dga,GAAYvI,IACduI,EAAWvI,IAAIzP,KAAKuK,EAAS/H,GAE7B+H,EAAQpM,MAAQqE,EAKlB+H,EAAQ2N,aAAe1V,EACvB+H,EAAQ3M,aAAa,QAAS4E,IAM5B2V,CAAwB5N,EAAS/H,GACjC+H,EAAQgN,cAAc,IAAIa,MAAM,QAAS,CAAEX,SAAS,UACpDlN,EAAQgN,cAAc,IAAIa,MAAM,SAAU,CAAEX,SAAS,MAInDlN,EAAQmG,mBACVnG,EAAQwN,QACRxN,EAAQwC,YAAcvK,OACtB+H,EAAQgN,cAAc,IAAIa,MAAM,QAAS,CAAEX,SAAS,WAItDtM,QAAQC,KACN,uFAwBEiN,GAA4BrF,MAAOzI,UACjC+N,GAAkC/N,GAAS,IAG7C+N,GAAoCtF,MACxCzI,EACAgO,KAEA,MAAMtM,EAAO1B,EAAQ2B,wBACfsM,EAAiB1M,OAAO2M,YAE9B,IAAKF,IAzZ8B,EACnCtM,EACAuM,IACYvM,EAAKjF,IAAM,GAAKiF,EAAKpG,OAAS2S,EAsZrBE,CAAsBzM,EAAMuM,GAC/C,OAGF,MAAMG,EAAevK,KAAK0E,IACxB,EACA1E,KAAK0E,IAAIpT,SAAS4M,KAAKsM,aAAclZ,SAASqB,gBAAgB6X,cAAgBJ,GAE1EvF,EA5ZgC,EACtC4F,EACAC,EACAC,EACAP,EACAG,IAIO9F,GADLgG,EAAiBC,GAAWN,EAAiB,EAAIO,EAAa,GAC1C,EAAG3K,KAAK0E,IAAI,EAAG6F,IAmZrBK,CACdlN,OAAOsH,QACPnH,EAAKjF,IACLiF,EAAK5I,OACLmV,EACAG,SAGI5F,GAAsBE,EA1sBI,MA4tB5BgG,GAAkBjG,MAAOhT,IAC7B,MAAMkZ,EAlKc,CAAClZ,IAErB,GAAuB,iBAAZA,EAAKkJ,GAAiB,CAC/B,MAAMiQ,EAASlQ,GAAejJ,EAAKkJ,IACnC,GAAIiQ,aAAkBvN,YAAa,CACjC,MAAMwN,EAASvC,GAAiBsC,GAChC,MAAO,CAAE5O,QAAS4O,EAAQpe,EAAGqe,EAAOre,EAAG1B,EAAG+f,EAAO/f,EACnD,CACA8R,QAAQC,KAAK,iCAAiCpL,EAAKkJ,sBACrD,CAGA,GAAIlJ,EAAKgX,SAAU,CACjB,MAAMqC,EAAWtC,GAAsB/W,EAAKgX,UAE5C,GAAIqC,aAAoBzN,YAAa,CACnC,MAAMwN,EAASvC,GAAiBwC,GAChC,MAAO,CACL9O,QAAS8O,EACTte,EAAGqe,EAAOre,EACV1B,EAAG+f,EAAO/f,EAEd,CACA8R,QAAQC,KAAK,0CAA0CpL,EAAKgX,WAC9D,CAEA,MAAsB,iBAAXhX,EAAKjF,GAAoC,iBAAXiF,EAAK3G,EACrC,CACL0B,EAAGiF,EAAKjF,EACR1B,EAAG2G,EAAK3G,IAIZ8R,QAAQC,KAAK,iEAAkEpL,GACxE,OAgIQsZ,CAActZ,GAC7B,GAAKkZ,EAAL,CAIA,GAAoB,UAAhBlZ,EAAKuZ,QAAsBL,EAAO3O,QAAS,OACvC8N,GAA0Ba,EAAO3O,SACvC,MAAM6O,EAASvC,GAAiBqC,EAAO3O,SACvC2O,EAAOne,EAAIqe,EAAOre,EAClBme,EAAO7f,EAAI+f,EAAO/f,CACpB,CAIA,SAFM2c,GAAWkD,EAAOne,EAAGme,EAAO7f,GAEd,SAAhB2G,EAAKuZ,OAIT,GAAKL,EAAO3O,QAAZ,CAKA,GAAoB,UAAhBvK,EAAKuZ,OAQP,OAPAjC,GAAmB4B,EAAO3O,QAAS,cAAe2O,EAAOne,EAAGme,EAAO7f,GACnEie,GAAmB4B,EAAO3O,QAAS,YAAa2O,EAAOne,EAAGme,EAAO7f,GACjEie,GAAmB4B,EAAO3O,QAAS,YAAa2O,EAAOne,EAAGme,EAAO7f,GACjEie,GAAmB4B,EAAO3O,QAAS,UAAW2O,EAAOne,EAAGme,EAAO7f,GAC/D6f,EAAO3O,QAAQiP,aAEfvK,KAIF,GAAoB,SAAhBjP,EAAKuZ,OAIP,OAHAzB,GAAgBoB,EAAO3O,QAASvK,EAAKwC,MAAQ,SAE7CyM,KAvGkB,CAAC1E,IACrB,GAAwB,SAApBA,EAAQiC,QAEV,YADCjC,EAA4BkP,gBAI/B,GAAwB,WAApBlP,EAAQiC,SAAyBjC,EAA8BmP,KAEjE,YADCnP,EAA8BmP,MAAMD,gBAIvC,MAAME,EAAapP,EAAQqP,QAAQ,QAC/BD,EACFA,EAAWF,gBAIbtO,QAAQC,KAAK,6DA0FbyO,CAAcX,EAAO3O,SAErB0E,IAtBA,MAFE9D,QAAQC,KAAK,8DAA+DpL,EAAKuZ,OAhBnF,GAsKIO,GAAkB9G,MAAOhT,IAC7B,IACE,MAAM+Z,EAAY/Z,EAAK2J,IACvB,IAAIqQ,EACJ,IACEA,EAAc,IAAIzQ,IAAIwQ,EAAWjO,OAAOc,SAASpD,MAAMA,IACzD,CAAA,MACEwQ,EAAcD,CAChB,CAEA,MAAME,EAtHwB,CAACF,IACjC,IAAIG,EAA2B,KAC/B,IACEA,EAAe,IAAI3Q,IAAIwQ,EAAWjO,OAAOc,SAASpD,KACpD,CAAA,MAEA,CAEA,MAAM2Q,EAAW5gB,MAAMwR,KACrBrL,SAASqQ,iBAAiB,8CAI5B,IAAA,MAAW8E,KAAMsF,EACf,GAAItF,aAAcuF,mBAAqBvF,EAAGrL,OAAS0Q,GAAc1Q,KAC/D,OAAOqL,EAIX,GAAIqF,EAAc,CAEhB,IAAA,MAAWrF,KAAMsF,EACf,GAAMtF,aAAcuF,kBACpB,IACE,MAAMC,EAAQ,IAAI9Q,IAAIsL,EAAGrL,KAAMsC,OAAOc,SAASpD,MAC/C,GACE6Q,EAAMC,WAAaJ,EAAaI,UAChCD,EAAME,SAAWL,EAAaK,QAC9BF,EAAMG,OAASN,EAAaM,KAE5B,OAAO3F,CAEX,CAAA,MACE,QACF,CAIF,IAAA,MAAWA,KAAMsF,EACf,GAAMtF,aAAcuF,kBACpB,IAEE,GADc,IAAI7Q,IAAIsL,EAAGrL,KAAMsC,OAAOc,SAASpD,MACrC8Q,WAAaJ,EAAaI,SAClC,OAAOzF,CAEX,CAAA,MACE,QACF,CAIF,MAAMvL,EAASyQ,EAAUzc,QAAQ,MAAO,IACxC,IAAA,MAAWuX,KAAMsF,EAAU,CACzB,MAAM3Q,EAAOqL,EAAGrK,aAAa,SAAWqK,EAAGrK,aAAa,cAAgB,GACxE,GAAIhB,IAASA,IAASuQ,GAAavQ,IAASF,GAAUE,IAAS,IAAIF,KACjE,OAAOuL,CAEX,CACF,CAGA,MAAM4F,EAAcV,EACjBzc,QAAQ,oBAAqB,IAC7BA,QAAQ,UAAW,IACnBmN,MAAM,KACNzI,OAAOqO,SACJqK,EAAcD,EAAYA,EAAYtf,OAAS,IAAM,GAE3D,GAAIuf,EAAa,CAEf,IAAIC,EAAc,CAACD,GACnB,GAAIR,EAAc,CAChB,IAAA,MAAW,CAAG/b,KAAU+b,EAAaU,aAAaC,UAC5C1c,GAAOwc,EAAYnf,KAAK2C,GAE1B+b,EAAaM,MACfG,EAAYnf,KAAK0e,EAAaM,KAAKld,QAAQ,KAAM,IAErD,CACAqd,EAAcA,EAAYja,IAAK5G,GAAMA,EAAEyD,eAGvC,MAAMud,EAAavhB,MAAMwR,KACvBrL,SAASqQ,iBACP,mFAIJ,IAAA,MAAW8E,KAAMiG,EAAY,CAC3B,MAAMtY,GAAQqS,EAAG9H,aAAe,IAAIhJ,OAAOxG,cACrC0P,GAAa4H,EAAGrK,aAAa,eAAiB,IAAIjN,cAClDwd,GAAWlG,EAAGrK,aAAa,aAAe,IAAIjN,cACpD,IAAA,MAAWyd,KAAQL,EACjB,GACEnY,IAASwY,GACT/N,IAAc+N,GACdD,IAAYC,GACZxY,EAAKsS,SAASkG,GAEd,OAAOnG,CAGb,CACF,CAEA,OAAO,MAamBoG,CAA0BlB,GAElD,GAAIE,EAAiB,CACnB9O,QAAQ+P,IAAI,sCAAuClB,EAAaC,EAAgBzN,eAC1E6L,GAA0B4B,GAEhC,MAAMb,EAASvC,GAAiBoD,GAShC,aARMjE,GAAWoD,EAAOre,EAAGqe,EAAO/f,GAElC4gB,EAAgB1C,cAAc,IAAIC,WAAW,cAAe,CAAEC,SAAS,EAAME,KAAM7L,UACnFmO,EAAgB1C,cAAc,IAAIC,WAAW,YAAa,CAAEC,SAAS,EAAME,KAAM7L,UACjFmO,EAAgB1C,cAAc,IAAIC,WAAW,YAAa,CAAEC,SAAS,EAAME,KAAM7L,UACjFmO,EAAgB1C,cAAc,IAAIC,WAAW,UAAW,CAAEC,SAAS,EAAME,KAAM7L,UAC/EmO,EAAgBT,SAlJO,CAACO,IAC5B,IACE,MAAMpZ,EAAU,IAAI4I,IAAIuC,OAAOc,SAASpD,MAClC0P,EAAS,IAAI3P,IAAIwQ,GACvB,OAAOpZ,EAAQwa,SAAWjC,EAAOiC,QAAUxa,EAAQ2Z,WAAapB,EAAOoB,QACzE,CAAA,MACE,OAAO,CACT,GA6IYc,CAAqBpB,EAC/B,CAGA7O,QAAQ+P,IAAI,wEAAyElB,GAGrF,IACE,MAAM9P,EAAS,IAAIX,IAAIyQ,GACvB,GACE9P,EAAOiR,SAAWrP,OAAOc,SAASuO,QAClCjR,EAAOoQ,WAAaxO,OAAOc,SAAS0N,UACpCpQ,EAAOsQ,KAGP,OADA1O,OAAOc,SAAS4N,KAAOtQ,EAAOsQ,MACvB,CAEX,CAAA,MAAyB,CAGzB,IACE,MAAMtQ,EAAS,IAAIX,IAAIyQ,GACvB,GAAI9P,EAAOiR,SAAWrP,OAAOc,SAASuO,OAAQ,CAE5C,MAAME,EAAUnR,EAAOoQ,SAAWpQ,EAAOqQ,OAASrQ,EAAOsQ,KAGzD,OAFA1O,OAAOwP,QAAQC,UAAU,CAAA,EAAI,GAAIF,GACjCvP,OAAOyL,cAAc,IAAIiE,cAAc,WAAY,CAAEjd,MAAO,CAAA,MACrD,CACT,CACF,CAAA,MAAyB,CAIzB,OADAuN,OAAOc,SAASpD,KAAOwQ,GAChB,CACT,OAAS9O,GAEP,OADAC,QAAQC,KAAK,2BAA4BpL,EAAK2J,IAAKuB,IAC5C,CACT,GAmDWuQ,GAAwBzI,MACnChT,IAEA,MAAM0b,EAAS1b,EAAK2b,QACpB,IACE,GAAkB,aAAd3b,EAAK4b,KAEP,aADM3C,GAAgBjZ,GACf,CACL2b,QAASD,EACTG,OAAQ,uBAAuB7b,EAAKuZ,UAIxC,GAAkB,WAAdvZ,EAAK4b,KAEP,YAzTgB5I,OAAOhT,IAC3B,MAAMqZ,GACgB,iBAAZrZ,EAAKkJ,GAAkBD,GAAejJ,EAAKkJ,IAAM,QACxDlJ,EAAKgX,SAAWD,GAAsB/W,EAAKgX,UAAY,MAE1D,KAAMqC,aAAoBzN,aAExB,YADAT,QAAQC,KAAK,yCAAyCpL,EAAKkJ,gBAAgBlJ,EAAKgX,mBAI5EsB,GAAkCe,GAAU,GAClD,MAAMD,EAASvC,GAAiBwC,SAC1BrD,GAAWoD,EAAOre,EAAGqe,EAAO/f,IA4SxByiB,CAAc9b,GACb,CACL2b,QAASD,EACTG,OAAQ,4BAIZ,GAAkB,mBAAd7b,EAAK4b,KAA2B,CAElC,MAAO,CACLD,QAASD,EACTG,OAHc1M,IAAe,GAGbvF,QAEpB,CAEA,GAAkB,aAAd5J,EAAK4b,KAAqB,OACtB9B,GAAgB9Z,SAEhB,IAAIuB,QAASE,GAAYC,WAAWD,EAAS,OACnD,MAAMxG,EAAUkU,KAChB,MAAO,CACLwM,QAASD,EACTG,OAAQ,yCAAyC/P,OAAOc,SAASpD,wBAAwBvO,EAAQ2O,UAErG,CAEA,MAAO,CAAE+R,QAASD,EAAQG,OAAQ,mBACpC,OAAS3Q,GACP,MAAM6Q,EAAM7Q,aAAiB8Q,MAAQ9Q,EAAM+Q,QAAU1f,OAAO2O,GAE5D,OADAC,QAAQC,KAAK,iCAAiCpL,EAAK4b,OAAQ1Q,GACpD,CAAEyQ,QAASD,EAAQG,OAAQ,SAASE,IAC7C,GCj/BWG,GAAyB,CAAC,IAAK,IAAK,MAE3CC,GAAyB,mBACzBC,OAA0B3T,IAChC,IAAI4T,GAA0B,EAE9B,MAAMC,GAAoBC,IACxB,MAAMC,EAAUD,EAAQxY,OAAOzG,QAAQ,OAAQ,IAC/C,MAAI,gBAAgBJ,KAAKsf,GAChBA,EAGF,WAAWA,KAEdC,GAAiB,CAACF,EAAiBG,KACvC,MAAMC,EAAaL,GAAiBC,GAC9B5S,EAAM,IAAIJ,IAAIoT,GAKpB,OAJAhT,EAAIiT,SAA4B,WAAjBjT,EAAIiT,SAAwB,OAAS,MACpDjT,EAAI2Q,SAAW,GAAG3Q,EAAI2Q,SAAShd,QAAQ,MAAO,MAAMof,IACpD/S,EAAI4Q,OAAS,GACb5Q,EAAI6Q,KAAO,GACJ7Q,EAAIkT,YAyCAC,GAAuB5R,GACb,iBAAVA,GAAgC,OAAVA,KAAkB,cAAeA,IACzDmF,QAASnF,EAAkC6R,WAKhDC,GAAiBhK,MAAOiK,IAC5B,IACE,MAAMld,QAAckd,EAASC,OACvBC,EAASpd,EAAKod,OACpB,MAAsB,iBAAXA,EAA4BA,EACnCA,GAA4B,iBAAXA,EAA4BtS,KAAKC,UAAUqS,GACzDpd,EAAKmL,OAASnL,EAAKkc,SAAWgB,EAASG,UAChD,CAAA,MACE,OAAOH,EAASG,UAClB,GAGIC,GAASC,GACb,IAAI/b,QAASE,IACXC,WAAWD,EAAS6b,KAWlBC,GAA2BC,GAC/BnB,KAA4BmB,EAEjBC,GAA6B,IAAcpB,GAE3CqB,GAA0B,KACrCrB,IAA2B,EAC3B,MAAMsB,EAASpkB,MAAMwR,KAAKqR,IAC1B,IAAA,MAAWwB,KAAgBD,EACzB,IACEC,EAAarG,cAAc,IAAIa,MAAM+D,KACrCyB,EAAaC,QACbD,EAAajgB,gBAAgB,OAC7BigB,EAAaE,MACf,CAAA,MAEA,GAISC,GAAsBC,IAEjC,MAAMC,EAAcD,EAAO1gB,QAAQ,2BAA4B,IACzD4gB,EAAeC,KAAKF,GACpBG,EAAQ,IAAIC,WAAWH,EAAa/iB,QAC1C,IAAA,IAASxC,EAAI,EAAGA,EAAIulB,EAAa/iB,OAAQxC,GAAK,EAC5CylB,EAAMzlB,GAAKulB,EAAaI,WAAW3lB,GAErC,OAAOylB,GAsFHG,GAAoBvL,MACxBwL,EACAC,EACAC,EAAqB,KACrBC,KAEA,MAAMC,EAAqBnB,KAC3B,GAAsB,IAAlBe,EAAOrjB,OAET,YADAwjB,IAAqB,QAIvB,GAAIpB,GAAwBqB,GAE1B,YADAD,IAAqB,QAKvB,MAAME,EAAaL,EAAOM,OAAO,CAACC,EAAK/lB,IAAM+lB,EAAM/lB,EAAEgmB,WAAY,GACjE7T,QAAQ+P,IAAI,mCAAmCsD,EAAOrjB,kBAAkB0jB,iBAA0BJ,KAElGE,IAAqB,YAErB,MAAMM,EAA2BT,EAAO9d,IAAKwe,IAC3C,MAAMC,EAAS,IAAId,WAAWa,EAAMF,YAEpC,OADAG,EAAO1P,IAAIyP,GACJC,EAAOC,SAIhB,IAAIC,EAAeZ,EACnB,GAAID,EAAOrjB,OAAS,GAAKqjB,EAAO,GAAGrjB,QAAU,EAAG,CAC9C,MAAMmkB,EAAS/lB,MAAMwR,KAAKyT,EAAO,GAAGhhB,MAAM,EAAG,IAC1CkD,OAASpE,EAAEugB,SAAS,IAAI0C,SAAS,EAAG,KAAK/Q,eACzC9C,KAAK,KACRP,QAAQ+P,IAAI,+BAA+BoE,KAGvCA,EAAO1O,WAAW,aAEX0O,EAAO1O,WAAW,UAAY0O,EAAO1O,WAAW,SADzDyO,EAAe,aAGNC,EAAO1O,WAAW,eAC3ByO,EAAe,YACNC,EAAO1O,WAAW,iBAC3ByO,EAAe,aAEnB,CAIA,IAAIG,EAAeH,GAAgBA,EAAavK,SAAS,KAAOuK,EAAe,aAC3EI,EAA6BR,EAEjC,GAAiB,cAAbR,EAA0B,CAE5B,MACMa,EAlIc,EACtBnkB,EACAujB,EAAqB,QAErB,MAAMU,EAAS,IAAIM,YAAY,IACzB/H,EAAO,IAAIgI,SAASP,GAsB1B,OAlBAzH,EAAKiI,UAAU,EAAG,YAAY,GAC9BjI,EAAKiI,UAAU,EAAG,GAAKzkB,GAAQ,GAC/Bwc,EAAKiI,UAAU,EAAG,YAAY,GAG9BjI,EAAKiI,UAAU,GAAI,YAAY,GAC/BjI,EAAKiI,UAAU,GAAI,IAAI,GACvBjI,EAAKkI,UAAU,GAAI,GAAG,GACtBlI,EAAKkI,UAAU,GAXE,GAWY,GAC7BlI,EAAKiI,UAAU,GAAIlB,GAAY,GAC/B/G,EAAKiI,UAAU,GAbE,EAaElB,EAAwB,GAAG,GAC9C/G,EAAKkI,UAAU,GAAIC,GAAc,GACjCnI,EAAKkI,UAAU,GAAI,IAAI,GAGvBlI,EAAKiI,UAAU,GAAI,YAAY,GAC/BjI,EAAKiI,UAAU,GAAIzkB,GAAQ,GAEpB,IAAIkjB,WAAWe,IAuGLW,CADKvB,EAAOM,OAAO,CAACC,EAAK/lB,IAAM+lB,EAAM/lB,EAAEgmB,WAAY,GACtBN,GAC5Ce,EAAiB,CAACH,EAAOF,UAAWH,GACpCO,EAAe,YACfrU,QAAQ+P,IAAI,wCAAwCwD,KACtD,CAEAvT,QAAQ+P,IAAI,oCAAoCsE,gBAA2Bf,MAC3E,MAAMuB,EAAO,IAAIC,KAAKR,EAAgB,CAAE1lB,KAAMylB,IAExC5B,EAAe,IAAIsC,MACnBC,EAAY5W,IAAI6W,gBAAgBJ,GAEtC,IASE,GAxM+B,CAACpC,IAClCxB,GAAoBrL,IAAI6M,IA+LtByC,CAA2BzC,GAE3BA,EAAa0C,QAAU,OACvB1C,EAAa2C,UAAW,EAExB3C,EAAahgB,aAAa,cAAe,QACzCggB,EAAaza,IAAMgd,EAEf5C,GAAwBqB,GAE1B,YADAD,IAAqB,cAIjBf,EAAa4C,OACnB7B,IAAqB,gBAhIE3L,OACzB4K,IAEIA,EAAa6C,aAIX,IAAIlf,QAAc,CAACE,EAASif,KAChC,MAAMC,EAAW7U,OAAO8U,YAAY,KAC7BhD,EAAa6C,OAChBtV,QAAQwE,KAAK,gDAEd,KAEGkR,EAAU,KACdC,IACArf,KAGIsf,EAAU,KACdD,IACAJ,EAAO,IAAI1E,MAAM,gCAGbgF,EAAe,KACnBF,IACArf,KAGIqf,EAAU,KACdhV,OAAOmV,cAAcN,GACrB/C,EAAalgB,oBAAoB,QAASmjB,GAC1CjD,EAAalgB,oBAAoB,QAASqjB,GAC1CnD,EAAalgB,oBAAoBye,GAAwB6E,IAG3DpD,EAAangB,iBAAiB,QAASojB,GACvCjD,EAAangB,iBAAiB,QAASsjB,GACvCnD,EAAangB,iBAAiB0e,GAAwB6E,MA2FhDE,CAAmBtD,GACzBe,IAAqB,OACvB,OAASwC,GAGP,MAFAhW,QAAQD,MAAM,4BAA4BiW,IAAO,CAAE1C,SAAUe,EAAc9P,KAAMsQ,EAAKtQ,OACtFiP,IAAqB,QACfwC,CACR,CAAA,QAjNmC,CAACvD,IACpCxB,GAAoBlN,OAAO0O,IAiNzBwD,CAA6BxD,GAC7BA,EAAaC,QACbD,EAAajgB,gBAAgB,OAC7BigB,EAAaE,OACbvU,IAAI8X,gBAAgBlB,EACtB,GAQWmB,GAAwBC,IACnC,MAAMC,EAAYD,EACf9W,MAAM,SACN/J,IAAKoQ,GAASA,EAAK/M,QACnB/B,OAAQ8O,GAASA,EAAKF,WAAW,UACjClQ,IAAKoQ,GAASA,EAAKtT,MAAM,GAAGikB,aAE/B,GAAyB,IAArBD,EAAUrmB,OACZ,OAAO,KAGT,MAAMumB,EAAUF,EAAU9V,KAAK,MAC/B,GAAgB,WAAZgW,EACF,MAAO,CAAE3nB,KAAM,QAGjB,IACE,OAAO8Q,KAAK2E,MAAMkS,EACpB,OAASxW,GAEP,OADAC,QAAQC,KAAK,2BAA4BF,GAClC,IACT,GAGWyW,GACXC,GAEyB,iBAAlBA,EAAQC,aACG,IAAjBD,EAAQ7nB,MAAuC,UAAjB6nB,EAAQ7nB,MA6ClC,MAAM+nB,GAA0B,CACrCvF,EACAwF,EAMAC,EAAsB,CAAA,KAEtB,MAAMC,EAAQxF,GAAeF,EAAS,gBACtCpR,QAAQwE,KAAK,+BAAgCsS,GAC7C,MAAMC,EAAS,IAAIC,UAAUF,GAC7B,IAAIG,EAAM,EACNC,EAAY,GACZC,EAAiBP,EAAOQ,WAAa,GACrCC,GAAU,EACVC,GAAU,EAGVC,EAA2BnhB,QAAQE,UAEnCkhB,EAAoC,KACpCC,EAAyE,KAC7E,MAAMC,EAAe,IAAIthB,QAAc,CAACE,EAASif,KAC/CiC,EAAelhB,EACfmhB,EAAclC,IAGhB,IAAIoC,EAAsD,KACtDC,EAAwE,KAC5E,MAAMC,EAAc,IAAIzhB,QAAqB,CAACE,EAASif,KACrDoC,EAAcrhB,EACdshB,EAAarC,IAGTuC,EAAa/X,IACbuX,IACJA,GAAU,EACVtX,QAAQC,KAAK,2BAA4BF,EAAM+Q,SAC/C2G,IAAc1X,GACd6X,IAAa7X,KAGTgY,EAAwB,KACxBT,GACCJ,EAAUte,QAAWue,IAC1BG,GAAU,EACVE,MACAG,IAAc,CACZtgB,KAAM6f,EAAUte,OAChBof,WAAYb,MA8EhB,OA1EAJ,EAAOkB,OAAS,KACdjY,QAAQwE,KAAK,2CACbqS,EAAOqB,kBACPnB,EAAOoB,KACLzY,KAAKC,UAAU,CACb/Q,KAAM,QACNwpB,WAAYxB,EAAOyB,UACnBL,WAAYpB,EAAOQ,gBAAa,EAChCkB,SAAU1B,EAAO0B,UAAY,KAC7BC,UAAW3B,EAAOtD,UAAY,iBAKpCyD,EAAOyB,UAAa7lB,IAClB,MAAM8jB,EA5Z4B,CACpCzjB,IAEA,IACE,MAAqB,iBAAVA,EACF,KAEF0M,KAAK2E,MAAMrR,EACpB,CAAA,MACE,OAAO,IACT,GAkZkBylB,CAAuBrnB,OAAOuB,EAAMiC,OACpD,GAAK6hB,EAAL,CAEA,GAAqB,cAAjBA,EAAQ7nB,MAAsD,iBAAvB6nB,EAAQuB,WAKjD,OAJAhY,QAAQwE,KAAK,8CAA+CiS,EAAQuB,YACpEb,EAAiBV,EAAQuB,WACzBnB,EAAO6B,cAAcjC,EAAQuB,iBAC7BR,MAIF,GAAqB,YAAjBf,EAAQ7nB,MAA8C,iBAAjB6nB,EAAQpf,KAAjD,CAQA,GAAqB,UAAjBof,EAAQ7nB,MAA4C,iBAAjB6nB,EAAQpf,KAO7C,OANA2I,QAAQwE,KAAK,sCAAuCiS,EAAQpf,KAAKhF,MAAM,EAAG,KAC1E6kB,EAAYT,EAAQpf,UACc,iBAAvBof,EAAQuB,aACjBb,EAAiBV,EAAQuB,WACzBnB,EAAO6B,cAAcjC,EAAQuB,cAKjC,GAAqB,SAAjBvB,EAAQ7nB,KAIV,OAHAoR,QAAQwE,KAAK,uBACbuT,SACAhB,EAAO4B,QAIT,GAAqB,UAAjBlC,EAAQ7nB,KAAkB,CAC5BoR,QAAQD,MAAM,+BAAgC0W,EAAQ1W,OACtD,MAAMiW,EAAM4C,GAAWnC,EAAQ1W,OAAS,gBAAsC,IAAtB0W,EAAQ7E,WAChEkG,EAAU9B,GACVe,EAAO4B,OACT,CAxBA,MALE9B,EAAOgC,YAAY,CACjB5B,IAA4B,iBAAhBR,EAAQQ,IAAmBR,EAAQQ,IAAM,EACrD5f,KAAMof,EAAQpf,MAbJ,GA2ChB0f,EAAO+B,QAAWC,IAChB/Y,QAAQD,MAAM,iCAAkCgZ,GAChDjB,EAAUc,GAAW,0BAA0B,KAGjD7B,EAAOiC,QAAWD,IAChB/Y,QAAQwE,KAAK,0CAA2CuU,EAAGE,KAAMF,EAAGG,QAChE5B,IACAJ,GAAaC,EACfY,IAGFD,EAAUc,GAAW,6BAA6B,MAG7C,CACLO,UAAYpF,GACNsD,GAA0B,IAAftD,EAAMxP,KAAmBnO,QAAQE,WAIhDihB,EAAYA,EAAUpjB,KAAK0T,UACzB,GAAIwP,EAAS,OAEb,SADMK,EACFL,EAAS,OACb,MAAMX,OAhZO7O,OAAOgN,IAC1B,MAAM5B,EAAQ,IAAIC,iBAAiB2B,EAAKuE,eAExC,IAAIC,EAAS,GACb,IAAA,IAAS7rB,EAAI,EAAGA,EAAIylB,EAAMjjB,OAAQxC,GAFhB,MAGhB6rB,GAAUjoB,OAAOkoB,gBAAgBrG,EAAMsG,SAAS/rB,EAAGA,EAHnC,QAKlB,OAAOgsB,KAAKH,IAyYcI,CAAa1F,GACjCkD,GAAO,EACHI,GAAWN,EAAO2C,aAAe1C,UAAU2C,OAC/C3Z,QAAQ4Z,MAAM,8CAA+C3C,EAAKlD,EAAMxP,MACxEwS,EAAOoB,KAAKzY,KAAKC,UAAU,CAAE/Q,KAAM,QAASqoB,MAAKP,cAE5Ca,GAETsC,KAAM,KACJ7Z,QAAQwE,KAAK,4DAA6DyS,GAG1EM,EAAYA,EAAUpjB,KAAK0T,gBACnB6P,EACFL,GACAN,EAAO2C,aAAe1C,UAAU2C,OAClC3Z,QAAQwE,KAAK,2CAA4CyS,GACzDF,EAAOoB,KAAKzY,KAAKC,UAAU,CAAE/Q,KAAM,aAGhCipB,GAETiC,OAAQ,KACNzC,GAAU,EACV,IACEN,EAAO4B,OACT,CAAA,MAEA,KAWAC,GAAa,CAAC9H,EAAiBc,GAAqB,KACxD,MAAM7R,EAAQ,IAAI8Q,MAAMC,GAExB,OADA/Q,EAAM6R,UAAYA,EACX7R,GA2EHga,GAAyBlS,MAC7BuJ,EACA4I,EACAC,EACAlgB,EACAmgB,EACAC,EACAC,KAEA,MAAMtD,EAAQxF,GAAeF,EAAS,gBAChCiJ,EAnnBgB,oBAAXC,QAA0B,eAAgBA,OAC5CA,OAAOC,aAET,OAAO3T,KAAKC,SAAS5D,KAAKuX,SAAS9I,SAAS,IAAIrf,MAAM,KAinBvDghB,EAAoC,GAC1C,IAAIC,EAAW,aACXC,EAAa,KACbkH,EAAiB,EAGjBC,GAAkB,EAClBC,EAAwD,KAC5D,MAEMC,EAAiB,KACrB,GAAIF,IAAoBN,GAAuC,IAAlB/G,EAAOrjB,OAAc,OAClE0qB,GAAkB,EACdC,IAAmB3jB,aAAa2jB,GAAkBA,EAAkB,MACxE,MAAME,EAAQxH,EAAOyH,OAAO,GAC5BV,EAAkB,CAAE/G,OAAQwH,EAAOvH,WAAUC,gBAGzCwH,EAAc,IAClB,IAAI3kB,QAAQ,CAACE,EAASif,KACpB,GAAI2E,IAEF,YADA3E,EAAOqD,GAAW,kBAAkB,IAItC,IAAIoC,GAAO,EACPC,EAAuD,KAC3D,MAAMlE,EAAS,IAAIC,UAAUF,GAC7BqD,EAAUpD,GAEV,MAAMmE,EAAW,CACfC,EACApb,KAEAgX,EAAOkB,OAAS,KAChBlB,EAAOyB,UAAY,KACnBzB,EAAO+B,QAAU,KACjB/B,EAAOiC,QAAU,KACjBmB,EAAU,MACG,YAATgB,EAIJ5F,EAAOxV,GAAS6Y,GAAW,iBAAiB,IAH1CtiB,KAMJygB,EAAOkB,OAAS,KACdjY,QAAQwE,KACN,uCAAuC6V,gBAAwBI,KAEjE1D,EAAOoB,KACLzY,KAAKC,UAAU,CACb/Q,KAAM,QACNwsB,WAAYf,EACZhjB,KAAM2iB,EACNC,QACAoB,mBAAoBthB,EACpBuhB,SAAUb,MAKhB1D,EAAOyB,UAAa7lB,IAClB,MAAM8jB,EA7qBwB,CACpCzjB,IAEA,IACE,MAAqB,iBAAVA,EACF,KAEF0M,KAAK2E,MAAMrR,EACpB,CAAA,MACE,OAAO,IACT,GAmqBsBuoB,CAAuBnqB,OAAOuB,EAAMiC,OACpD,GAAK6hB,EAAL,CAKA,GAAqB,UAAjBA,EAAQ7nB,MAA6C,iBAAlB6nB,EAAQC,MAAoB,CACjE,MAAMO,EAA6B,iBAAhBR,EAAQQ,IAAmBR,EAAQQ,IAAM,EA+B5D,MAzrB0B,EAClCuE,EACAf,IACYe,EAAcf,EAwpBdgB,CAAqBxE,EAAKwD,IAC5BpH,EAAOhjB,KAAKuiB,GAAmB6D,EAAQC,QACvC+D,EAAiBxD,EACbR,EAAQ8B,YACVjF,EAAWmD,EAAQ8B,WAEc,iBAAxB9B,EAAQiF,cACjBnI,EAAakD,EAAQiF,aAInBtB,IAAsBM,IACpBC,gBAA8BA,GAClCA,EAAkBpkB,WAAWqkB,EA5EZ,OA+EnB5a,QAAQwE,KACN,qDAAqD6V,SAAiBpD,UAAYwD,UAIlF1D,EAAO2C,aAAe1C,UAAU2C,MAClC5C,EAAOoB,KACLzY,KAAKC,UAAU,CACb/Q,KAAM,MACNwsB,WAAYf,EACZiB,SAAUb,KAKlB,CAEA,GAAqB,SAAjBhE,EAAQ7nB,KAAiB,CAEvBwrB,IAAsBM,GACxBE,IAKF,OAD8B,iBAArBnE,EAAQ6E,SAAwB7E,EAAQ6E,SAAWb,GACxCA,GAClBQ,EAAarC,GAAW,uBAAuB,GAC/CoC,GAAO,OACPjE,EAAO4B,UAGTqC,GAAO,OACPjE,EAAO4B,QAET,CAEqB,UAAjBlC,EAAQ7nB,OACVqsB,EAAarC,GAAWnC,EAAQ1W,OAAS,gBAAsC,IAAtB0W,EAAQ7E,WACjEoJ,GAAO,EACPjE,EAAO4B,QA3DT,MAFE3Y,QAAQC,KAAK,wCAiEjB8W,EAAO+B,QAAU,KACVmC,IACHA,EAAarC,GAAW,0BAA0B,KAItD7B,EAAOiC,QAAU,KACXkB,IACFgB,EAAS,SAAUtC,GAAW,kBAAkB,IAG9CoC,EACFE,EAAS,WAGXA,EAAS,SAAUD,GAAcrC,GAAW,6BAA6B,OAI/E,IAAA,IAAS+C,EAAU,EAAGA,GAAW5K,GAAuB/gB,OAAQ2rB,GAAW,EAAG,CAC5E,GAAIA,EAAU,EAAG,CACf,MAAMC,EAAQ7K,GAAuB4K,EAAU,GAC/C3b,QAAQC,KACN,gCAAgC0b,cAAoBC,cAAkBnB,WAElEvI,GAAM0J,EACd,CAEA,IAEE,aADMb,IACC,CAAE1H,SAAQC,WAAUC,aAC7B,OAASxT,GACP,MAAM6R,EACJD,GAAoB5R,GAChB+Q,EAAU/Q,aAAiB8Q,MAAQ9Q,EAAM+Q,QAAU1f,OAAO2O,GAIhE,GAHAC,QAAQC,KACN,yCAAyC0b,eAAqB/J,WAAmBd,MAE9Ec,GAAa+J,IAAY5K,GAAuB/gB,OACnD,MAAM+P,CAEV,CACF,CAEA,MAAM6Y,GAAW,oBAAoB,IAWjCiD,GAA4BhU,MAChCuJ,EACA/Z,EACA4iB,EACAlgB,EACAmgB,EACAC,EACA2B,EACAtI,KAEA,MAAMnC,EAAUha,EAAKuB,OACrB,IAAKyY,EAAyC,YAA9BmC,IAAqB,QAErC,MAAMuI,EAAczJ,KACpB,GAAIF,GAAwB2J,GAE1B,YADAvI,IAAqB,QAIvBA,IAAqB,aAErB,IACIwI,EADAC,EAA8C,KAGlD,IACED,QAAkBjC,GAChB3I,EAASC,EAAS4I,EAAOlgB,EACzBmgB,EAAWC,EAEV+B,IACK9J,GAAwB2J,IAAgB7B,KACX,IAA7BgC,EAAW7I,OAAOrjB,SACtBisB,EAAwB7I,GACtB8I,EAAW7I,OAAQ6I,EAAW5I,SAAU4I,EAAW3I,WAClDngB,IAEe,SAAVA,GAAkBogB,IAAqBpgB,KAE7C+oB,MAAMnG,GAAOhW,QAAQC,KAAK,qCAAsC+V,MAGxE,OAASoG,GAEP,GAAIH,EAGF,aAFMA,OACNzI,IAAqB,QAIvB,GAAI0G,IAA6C,YAA9B1G,IAAqB,QACxCxT,QAAQC,KACN,+CAA+Cmc,aAAiBvL,MAAQuL,EAAMtL,QAAU1f,OAAOgrB,MAEjGJ,OAjUqBnU,OACvBuJ,EACA4I,EACAC,EACAlgB,EACAmgB,EACA4B,KAEA,MAAMO,EAAc,IAAIC,SACxBD,EAAYE,OAAO,OAAQvC,GAC3BqC,EAAYE,OAAO,QAAStC,GAC5BoC,EAAYE,OAAO,qBAAsBnrB,OAAO2I,IAEhD,MAAMyiB,QAAoBC,MAAM,GAAGtL,GAAiBC,cAAqB,CACvEsL,OAAQ,OACRvb,KAAMkb,IAGR,IAAKG,EAAYG,GACf,MAAM/D,SAAiB/G,GAAe2K,IAAc,GAGtD,MAAMI,EAASJ,EAAYrb,MAAM0b,YACjC,IAAKD,EACH,MAAMhE,GAAW,qCAAqC,GAGxDkD,EAAUc,GAEV,MAAMvJ,EAAoC,GAC1C,IAAIC,EAAW,aACXC,EAAa,KACjB,MAAMuJ,EAAU,IAAIC,YACpB,IAAI9I,EAAS,GAEb,MACMiG,KADO,CAKX,MAAMc,KAAEA,EAAAhoB,MAAMA,SAAgB4pB,EAAOI,OACrC,GAAIhC,EACF,MAGF/G,GAAU6I,EAAQG,OAAOjqB,EAAO,CAAEkqB,QAAQ,IAC1C,MAAMC,EAASlJ,EAAO3U,MAAM,cAC5B2U,EAASkJ,EAAO5a,OAAS,GAEzB,IAAA,MAAW6a,KAASD,EAAQ,CAC1B,MAAM1G,EAAUN,GAAqBiH,GACrC,GAAK3G,GAIDD,GAAkBC,GAAU,CAC9B,MAAM4G,EAAS5G,EAAQ4G,QAAU,MACjC/J,EAAWmD,EAAQ8B,YAAyB,SAAX8E,EAAoB,aAAe,cACpEhK,EAAOhjB,KAAKuiB,GAAmB6D,EAAQC,QACnCD,EAAQiF,cACVnI,EAAakD,EAAQiF,YAEzB,CACF,CACF,CAKA,OAHAkB,EAAOU,cACPxB,OAAU,GAEH,CAAEzI,SAAQC,WAAUC,eA4PPgK,CAChBnM,EAASC,EAAS4I,EAAOlgB,EACzBmgB,EAAW4B,EAEf,CAEI5B,KAAe9H,GAAwB2J,GACzCvI,IAAqB,SAKnByI,SACIA,EAIJD,EAAU3I,OAAOrjB,OAAS,QACtBojB,GACJ4I,EAAU3I,OAAQ2I,EAAU1I,SAAU0I,EAAUzI,WAChDC,GAGFA,IAAqB,UA0CZgK,GAAY3V,MACvBuJ,EACA/Z,EACA4iB,EACAlgB,EACAyZ,KAEA,MAAMnC,EAAUha,EAAKuB,OAChByY,IACLrR,QAAQwE,KAAK,4BAA4B6M,EAAQrhB,uBAC3C6rB,GACJzK,EAASC,EAAS4I,EAAOlgB,EACzB,KAAM,EACN,OACA,OACAyZ,KAMSiK,GAAuB,CAClCrM,EACAsM,EACArF,EACAjB,EACAR,EAMAC,EACA8G,KAEA,IAEIC,EAFA1D,GAAY,EACZ2D,EAAiC,KAEjCC,GAAe,EAEnB,MAAMjG,EAAc,IAAIzhB,QAAcyR,MAAOvR,EAASif,KACpD,IAEE,GAAI2E,SAAkB5jB,IACtB,MAAMynB,QA/oBZlW,eACEuJ,EACA4M,EACA3F,EACAjB,EACAkB,EACAJ,GAEA,MAAM1Z,EAAM,GAAG2S,GAAiBC,cAC1B6M,EAAW,IAAI3B,SACrB2B,EAAS1B,OAAO,OAAQyB,GACxBC,EAAS1B,OAAO,aAAclE,GAC1BjB,GAAW6G,EAAS1B,OAAO,aAAcnF,GAC7C6G,EAAS1B,OAAO,WAAYjE,GAE5B,MAAM4F,EAAkBzB,MAAMje,EAAK,CAAEke,OAAQ,OAAQvb,KAAM8c,IAC3D/F,MACA,MAAMpG,QAAiBoM,EACvB,IAAKpM,EAAS6K,GACZ,MAAM,IAAI9L,YAAYgB,GAAeC,IAEvC,OAAOA,EAASC,MAClB,CAynB8BoM,CACtB/M,EACAsM,EACArF,EACAjB,EACA,KACAP,EAAOuH,kBAGHC,EAAmBN,EAAU/F,WACnC,IAAIsG,EAAqBD,EACzB,MAAME,EAAWR,EAAU1mB,KAO3B,GALAwf,EAAO2H,kBAAkB,CACvBxG,WAAYqG,EACZI,UAAWF,IAGTrE,SAAkB5jB,IAGtB,MAAM0jB,QAAsB,IAAI5jB,QAAgB,CAACsoB,EAAcC,KAC7D,GAAIzE,EAA+B,YAAlBwE,EAAa,IAE9B,MAAM5H,EAAQxF,GAAeF,EAAS,kBAChC2F,EAAS,IAAIC,UAAUF,GAC7B+G,EAAe9G,EAEf,IAAI6H,EAAa,GACbC,GAAW,EACXC,EAAmB,GACnBC,EAAsB,GAE1B,MAAMC,EAAUC,IACVJ,IACJA,GAAW,EACXH,EAAaO,KAGTC,EAAQnf,IACR8e,IACJA,GAAW,EACXF,EAAY5e,KAGdgX,EAAOkB,OAAS,KACdjY,QAAQwE,KAAK,8BACbuS,EAAOoB,KAAKzY,KAAKC,UAAU,CACzB/Q,KAAM,QACNwpB,WAAYC,EACZL,WAAYqG,EACZI,UAAWF,EACXY,MAAOvI,EAAOuI,MACdC,aAAcxI,EAAOyI,YACrBhE,mBAAoBzE,EAAO7c,sBAI/Bgd,EAAOyB,UAAY3Q,MAAOlV,IACxB,IAAIiC,EACJ,IACEA,EAAO8K,KAAK2E,MAAMjT,OAAOuB,EAAMiC,MACjC,CAAA,MAEE,YADAoL,QAAQC,KAAK,gCAEf,CAEA,MAAMqf,EAAU1qB,EAAKhG,KAErB,GAAgB,YAAZ0wB,GAAoD,iBAApB1qB,EAAKojB,WAGvC,OAFAsG,EAAqB1pB,EAAKojB,gBAC1BnB,EAAO6B,cAAc4F,GAIvB,GAAgB,cAAZgB,EAAJ,CAQA,GAAgB,gBAAZA,GAAmD,iBAAf1qB,EAAKsT,MAG3C,OAFA4W,GAAoBlqB,EAAKsT,WACzB2O,EAAO0I,mBAAmB3qB,EAAKsT,OAIjC,GAAgB,eAAZoX,GAA4BlxB,MAAMC,QAAQuG,EAAK4qB,OAAQ,CACzD,MAAMA,EAAQ5qB,EAAK4qB,MAGfV,EAAiBlmB,SACnBie,EAAO4I,sBAAsBX,EAAiBlmB,QAC9CmmB,GAAuBD,GAEzBA,EAAmB,GAEnBjI,EAAO6I,cAAcF,GAErB,MAAMG,EAAiD,GACvD,IAAA,MAAW9qB,KAAQ2qB,EAAO,CAExB,MAAMI,EAA2B,aAAd/qB,EAAK4b,KACpBmP,GACFvY,GAAuB,CACrB+P,UAAWkH,EACXjG,YACA8G,MAAOvI,EAAOuI,MACdlF,MAAOrD,EAAOqD,MACdlgB,kBAAmBmL,QAAQ0R,EAAO7c,mBAClC8lB,iBAAkBL,EAAMjqB,IAAK1H,IAAAA,CAC3B2iB,QAAS3iB,EAAE2iB,QACXC,KAAM5iB,EAAE4iB,KACRqP,KAAMjyB,EAAEiyB,QAEVC,iBAAkB,IAAIJ,GACtBb,iBAAkBC,QAAuB,IAI7C,MAAMrO,QAAeiN,EAAY9oB,GAG7B+qB,GACFpY,KAGFqP,EAAOmJ,eAAenrB,EAAK2b,QAAS3b,EAAK4b,KAAMC,EAAOA,QACtDiP,EAAQtvB,KAAKqgB,EACf,CAQA,YANIqG,EAAO2C,aAAe1C,UAAU2C,MAClC5C,EAAOoB,KAAKzY,KAAKC,UAAU,CACzB/Q,KAAM,eACN+wB,aAIN,CAEA,GAAgB,eAAZL,EAA0B,CAC5BV,EAAchqB,EAAKqrB,aAA0B,GAC7C,MAAMC,GAA2C,IAAvBtrB,EAAKurB,cAM/B,OALAtJ,EAAOuJ,kBAAkBxB,EAAYsB,GACN,iBAApBtrB,EAAKojB,YACdnB,EAAO6B,cAAc9jB,EAAKojB,iBAE5BgH,EAAOJ,EAET,CAEA,GAAgB,UAAZU,EAAqB,CACvB,MAAMe,EAAUzrB,EAAKmL,OAAoB,cAIzC,OAHA+d,GAAe,EACfjH,EAAOjB,UAAUyK,QACjBnB,EAAK,IAAIrO,MAAMwP,GAEjB,CA9EA,MALExJ,EAAOyJ,cACL1rB,EAAK2rB,UACL3rB,EAAK4rB,iBAoFXzJ,EAAO+B,QAAU,KACf9Y,QAAQD,MAAM,0BACd+d,GAAe,EACfjH,EAAOjB,UAAU,oCACjBsJ,EAAK,IAAIrO,MAAM,sCAGjBkG,EAAOiC,QAAU,KACfhZ,QAAQwE,KAAK,2BACbwa,EAAOJ,MAOX,GAHAf,EAAe,KAGX3D,IAAcF,EAIhB,OAHKE,GACH/P,KAEK7T,IAGT0J,QAAQwE,KACN,sCAAsCoS,EAAOqD,SAG/C9P,WACM0R,GACJzK,EAAS4I,EAAepD,EAAOqD,MAAO/U,QAAQ0R,EAAO7c,mBACrD,IAAMmgB,EACLnD,IAAa8G,EAAe9G,GAC5B6F,IAAagB,EAAehB,GAC7B/F,EAAOrD,oBAGTld,GACF,OAAS0f,GAEP,IAAK8H,EAAc,CACjB,MAAMlN,EAAMoF,aAAenF,MAAQmF,EAAIlF,QAAU1f,OAAO4kB,GACxDa,EAAOjB,UAAUhF,EACnB,CACA2E,EAAOS,EACT,CAAA,QACE4H,GAAc9D,SAASqC,MAAM,QACzB0B,GAAgBA,EAAanE,YAAc1C,UAAU2C,MACvDkE,EAAalF,QAEfkF,EAAe,IACjB,IAGF,MAAO,CACLhE,KAAM,KACJK,GAAY,EACZ3H,KACIqL,GACFA,EAAa9D,SAASqC,MAAM,QAE1B0B,GAAgBA,EAAanE,YAAc1C,UAAU2C,MACvDkE,EAAalF,SAGjBqC,KAAMnD,ICzvCJ4I,GAAuC,CAC3CC,KCVa,s7gBDWbC,SEXa,8n+BFYbC,SGZa,s7gBHabC,UIba,+n+BJuEf,MAAMC,GAAa,IArDnB,MACUC,MAAmB,GACnBvO,QAAS,EAET,OAAAwO,CAAQhsB,GACd,OAAO,IAAIoB,QAASE,IAClB,GAAsB,oBAAXqK,OAET,YADArK,IAIF,MAAMogB,EAAQ,IAAI3B,MAAM0L,GAAYzrB,IACpC0hB,EAAMvB,QAAU,OAChBuB,EAAMuK,OAfO,GAiBb,IAAI3J,GAAU,EACd,MAAM4D,EAAW,KACX5D,IACJA,GAAU,EACVZ,EAAMwK,QAAU,KAChBxK,EAAMoC,QAAU,KAChBxiB,MAGFogB,EAAMwK,QAAUhG,EAChBxE,EAAMoC,QAAUoC,EACXxE,EAAMrB,OAAO8G,MAAM,IAAMjB,MAElC,CAEA,WAAciG,GACZ,IAAItxB,KAAK2iB,OAAT,CACA3iB,KAAK2iB,QAAS,EACd,IACE,KAAO3iB,KAAKkxB,MAAM/wB,OAAS,GAAG,CAC5B,MAAMoxB,EAAOvxB,KAAKkxB,MAAMrwB,QACnB0wB,SACCvxB,KAAKmxB,QAAQI,EACrB,CACF,CAAA,QACEvxB,KAAK2iB,QAAS,CAChB,CAViB,CAWnB,CAEA,OAAA6O,CAAQrsB,GACgB,oBAAX2L,SACX9Q,KAAKkxB,MAAM1wB,KAAK2E,GACXnF,KAAK2iB,QACH3iB,KAAKsxB,QAEd,GKiBIG,GAAc,qBACdC,GAAgB,uBAChBC,GAAiB,mBACjBC,GAAS,IAMTC,GACG,QADHA,GAEK,aAFLA,GAGa,yBAHbA,GAIO,kBAJPA,GAKiB,wBALjBA,GAMU,cANVA,GAOM,cAPNA,GAQU,IARVA,GASU,wBAGHC,GAAmBC,GAC9B,gBAAgBA,sCAYLC,GAAqBC,GAC5BA,EAAMjoB,YAAoB6nB,GAC1BI,EAAMC,eAAuBL,GAC7BI,EAAME,eAAuBN,GAC7BI,EAAMG,WAAmBP,GACzBI,EAAMI,eAAuBR,GAC7BI,EAAMhoB,OAAe4nB,GAClBA,GAkBIS,GAAoBpa,IAC/B,MAAMqa,EAAenf,KAAK0E,IAAI,EAAG1E,KAAKof,MAAMta,EAAa,MAKzD,MAAO,GAJS9E,KAAKof,MAAMD,EAAe,IACvC1Q,WACA0C,SAAS,EAAG,SACEgO,EAAe,IAAI1Q,WAAW0C,SAAS,EAAG,QAShDkO,GAAyBV,GAAiC,CACrE,CACE7jB,GAAI,EACJ1G,KAAMsqB,GAAgBC,GACtBW,QAAQ,IAICC,GAA2BC,IACjCA,IAILA,EAAQhb,WAAW6Z,IACnBmB,EAAQhb,WAAW8Z,IACnBkB,EAAQhb,WAAW+Z,MAoBfkB,GAAoBC,GACVA,EAAShP,OAAO,CAACC,EAAK9C,IAAY7N,KAAK0E,IAAIiM,EAAK9C,EAAQ/S,IAAK,GAC5D,EAkBJ6kB,GAA6B,CACxC7oB,EACA8oB,EACAhpB,EACAC,KACaC,GAAqB8oB,KAAkBhpB,IAAe,EAa/DipB,GACJjuB,IAEA,GAAkB,mBAAdA,EAAK4b,KACP,MAAO,CAAEpZ,KAAM,WAAY0rB,KAAM,WAEnC,GAAkB,WAAdluB,EAAK4b,KACP,MAAO,CAAEpZ,KAAM,WAAY0rB,KAAM,UAEnC,GAAkB,aAAdluB,EAAK4b,KAAqB,CAC5B,MAAMjS,EAA+B,iBAAlB3J,EAAKirB,KAAKthB,IAAmB3J,EAAKirB,KAAKthB,IAAI5F,OAAS,GACvE,MAAO,CACLvB,KAAMmH,EAAM,iBAAiBA,IAAQ,eACrCukB,KAAM,WAEV,CACA,MAAkB,aAAdluB,EAAK4b,MAA4C,SAArB5b,EAAKirB,KAAK1R,OACjC,CAAE/W,KAAM,gBAAiB0rB,KAAM,UAEtB,aAAdluB,EAAK4b,MAA4C,SAArB5b,EAAKirB,KAAK1R,OACjC,CAAE/W,KAAM,gBAAiB0rB,KAAM,QAEtB,aAAdluB,EAAK4b,MAA4C,WAArB5b,EAAKirB,KAAK1R,OACjC,CAAE/W,KAAM,gBAAiB0rB,KAAM,QAEtB,aAAdluB,EAAK4b,MAA4C,UAArB5b,EAAKirB,KAAK1R,OACjC,CAAE/W,KAAM,UAAW0rB,KAAM,YAEhB,aAAdluB,EAAK4b,KACA,CAAEpZ,KAAM,YAAa0rB,KAAM,YAE7B,CACL1rB,KAAMxC,EAAK4b,MAAQ,OACnBsS,KAAM,YAIGC,GAAa,EACxB5mB,UACAwa,SACA7c,qBAAoB,EACpBkpB,wBACAviB,UAAS,EACTwiB,aACAC,oBACAC,eACAC,sBAEA,MAAOV,EAAUW,GAAeC,GAAoB,KAClD,GAA4B,oBAAjBjc,aAA8B,CACvC,MAAMkc,EAAQlc,aAAalD,QAAQkd,IAC7BmC,EAAYnc,aAAalD,QAAQmd,IAEvC,GAAIiC,GAASC,EAAW,CAEtB,GADmB7c,KAAKC,MAAQ5H,SAASwkB,EAAW,IACnChC,GACf,IACE,OAAO/hB,KAAK2E,MAAMmf,EACpB,CAAA,MAEA,MAEAhB,GAAwBlb,aAE5B,CACF,CAEA,OAAOgb,GAAsB1L,EAAOgL,cAG/B9nB,EAAQ4pB,GAAaH,IAAS,IAC9B1pB,EAAa8pB,GAAkBJ,IAAS,IACxCrB,EAAgB0B,GAAqBL,IAAS,IAC9CtB,EAAY4B,GAAiBN,IAAS,IACtCO,EAAkBC,GAAuBR,IAAS,IAClDvB,EAAgBgC,GAAqBT,IAAS,IAC9CxB,EAAgBkC,GAAqBV,IAAS,IAC9CW,EAAcC,GAAmBZ,IAAS,IAC1Ca,EAAqBC,GAA0Bd,GAAS,IACxDe,EAAgBC,GAAqBhB,GAAwB,MAC9DiB,EAA2B,CAC/B1qB,SACAD,cACAqoB,iBACAD,aACA6B,mBACA9B,iBACAD,kBAEI0C,EAAqB5C,GAAkB2C,GACvCE,EAhMuB,EAC7B5C,EACAwC,IAEApf,QACEof,GACGxC,EAAMhoB,QACNgoB,EAAMjoB,aACNioB,EAAMI,gBACNJ,EAAMG,YACNH,EAAMgC,kBACNhC,EAAME,gBACNF,EAAMC,gBAoLQ4C,CAAgBH,EAAaF,GAC1CrS,EAAayS,EAAcJ,GAAkBG,EAAsB/C,GAEnEkD,EAAYC,GAAO/qB,GACnBgrB,EAAiBD,GAAOhrB,GAExBkrB,EAAmBF,GAAOnC,GAAiBC,IAC3CqC,EAAcH,GAA6B,MAC3CI,EAAYJ,GAA2B,MACvCK,EAAiBL,GAAmB,IACpCM,EAA4BN,GAAgC,MAC5DO,EAAeP,GACK,oBAAjBvd,aAAiB,MAElB,MAAM+d,EAAK/d,aAAalD,QAAQmd,IAChC,OAAI8D,GAAMze,KAAKC,MAAQ5H,SAASomB,EAAI,IAAM5D,GACjCna,aAAalD,QAAQod,IAEvB,MANW,GAQpB,MAGA8D,EAAkBT,GAAsB,MACxCU,EAAiBV,GAAsB,MACvCW,EAAkBX,GAA4B,MAC9CY,EAAYZ,GAA0C,MAEtDa,EAA0Bb,IAAO,GAEjCc,EAAmBd,GAAsB,MACzCe,GAAoBf,GAAsB,MAC1CgB,GAAsBhB,IAAO,GAC7BiB,GAAmBjB,GAA6B,MAChDkB,GAA2BlB,IAAO,GAClCmB,GAA2BnB,IAAO,GAElCoB,GAAwBpB,GAAsB,MAC9CqB,GAAyBrB,GAAO,IAChCsB,GAA2BtB,IAAO,GAClCuB,GAA2BvB,IAAO,GAElCwB,GAAwBxB,GAAsB,MAC9CyB,GAA4BzB,GAAsB,MAElD0B,GAAuB1B,GAA8B,MACrD2B,GAAqB3B,GAA8B,MAEnD4B,GAAqB5B,GAAsB,MAC3C6B,GAA0B7B,GAAe,IACzC8B,GAAyB9B,GAAmC,MAC5D+B,GAA+B/B,IAAO,GACtCgC,GAAiBhC,GAA+B,MAChDiC,GAAgCjC,GAAsB,MACtDkC,GAA2BlC,GAAO,IAClCmC,GAA0BnC,IAAO,GACjCoC,GAAkBpC,IAAO,GACzBqC,GAAkBrC,GAAO,GACzBsC,GAAsBtC,IAAO,GAEnCuC,GAAU,KACRxC,EAAUpvB,QAAUsE,GACnB,CAACA,IAEJstB,GAAU,KACRtC,EAAetvB,QAAUqE,GACxB,CAACA,IAGJutB,GAAU,KAAQjE,IAAoBtpB,IAAiB,CAACA,IACxDutB,GAAU,KAAQhE,IAAetpB,IAAY,CAACA,IAG9CstB,GAAU,KACR,IAAK/D,EAAiB,OACtB,GAAIxpB,EAEF,YADAwpB,EAAgBiB,GAAkB5C,IAIpC,GAAIoC,GAAoB9B,EAAgB,CACtC,MAAMqF,EAAgB,IAAI1E,GAAU2E,UAAUC,KAAK74B,IAAMA,EAAE6zB,QAAqB,SAAX7zB,EAAEE,MAEvE,YADAy0B,EAAgBgE,GAAehwB,MAAQsqB,GAAgB/K,EAAOgL,WAEhE,CACA,GAAI8C,EAAY,CACd,MAAM8C,EAAKlD,GAAkBzC,GAAkB,CAC7C/nB,SACAD,cACAqoB,iBACAD,aAEAD,iBACAD,mBAGF,YADAsB,EAAgBmE,EAElB,CAEA,MAAMH,EAAgB,IAAI1E,GAAU2E,UAAUC,KAAK74B,IAAMA,EAAE6zB,QAAqB,SAAX7zB,EAAEE,MACvEy0B,EAAgBgE,GAAehwB,MAAQsqB,GAAgB/K,EAAOgL,aAC7D,CACD/nB,EACAC,EACAooB,EACAD,EACAF,EACAC,EACA8B,EACAQ,EACAI,EACA/B,IAGF,MAAM8E,GAAWzyB,IL1WI,CAACA,IACtB8rB,GAAWO,QAAQrsB,IK0WjBqsB,CAAQrsB,IAGJ0yB,GAAoB,KACxBR,GAAgB1xB,SAAW,EACpB0xB,GAAgB1xB,SAGnBmyB,GAAyB,KAC7BT,GAAgB1xB,SAAW,GAGvBoyB,GAAyBC,GAC7BX,GAAgB1xB,UAAYqyB,EAExBC,GAAqB,KACrBX,GAAoB3xB,UAGxB2xB,GAAoB3xB,SAAU,EAC9BiyB,GAAQ,UAGVL,GAAU,KACoB,oBAAjB9f,eACTA,aAAaxH,QAAQwhB,GAAa5hB,KAAKC,UAAUgjB,IACjDrb,aAAaxH,QAAQyhB,GAAe3a,KAAKC,MAAM6K,cAEhD,CAACiR,IAEJ,MAAMoF,GAAyB,KAlSI,IACnC3oB,KAkSwBmnB,GAAqB/wB,WA5R7C4J,EAAQ4oB,UAAY5oB,EAAQqO,elBvLihC,IAAWpgB,GAAEE,GAAOC,GAATH,GkBsdxiC,KACd06B,MlBvdwjCx6B,GkBwdvjC,CAACo1B,EAAU1Q,EAAYnY,EAAQD,GlBxd+hCrM,GAAEQ,EAAEW,IAAI,IAAId,EAAE0F,KAAKtD,GAAEzC,GAAEkJ,IAAInJ,MAAKC,GAAEyB,GAAG5B,GAAEG,GAAED,EAAEA,GAAEG,EAAE2F,IAAIhD,KAAK7C,KkB0dznC45B,GAAU,KACR,MAAMjyB,EAAUqxB,GAAmBhxB,QACnC,IAAKL,GAAqC,oBAAnB8yB,eACrB,OAGF,MAAMC,EAAW,IAAID,eAAe,KAClCF,OAIF,OADAG,EAASC,QAAQhzB,GACV,IAAM+yB,EAASE,cACrB,IAEH,MAAMC,GAAqB,KACiB,OAAtC/B,GAA0B9wB,UAC5BmL,OAAOmV,cAAcwQ,GAA0B9wB,SAC/C8wB,GAA0B9wB,QAAU,MAEtC6wB,GAAsB7wB,QAAU,MAkB5B8yB,GAAuB,KAC3B1E,GAAkB,GAClBC,GAAc,GACdE,GAAoB,GACpBC,GAAkB,GAClBC,GAAkB,GAClBM,EAAkB,MAClB0B,GAAsBzwB,QAAU,KAChC0wB,GAAuB1wB,QAAU,GACjC2wB,GAAyB3wB,SAAU,EACnC4wB,GAAyB5wB,SAAU,EACnCoxB,GAA6BpxB,SAAU,EACvCixB,GAAmBjxB,QAAU,KAC7BkxB,GAAwBlxB,QAAU,IAG9B+yB,GAAsB,KACQ,OAA9B3C,GAAkBpwB,UACpBmL,OAAO3J,aAAa4uB,GAAkBpwB,SACtCowB,GAAkBpwB,QAAU,OAI1BgzB,GAAa,KACc,OAA3BjD,EAAe/vB,UACjBsgB,cAAcyP,EAAe/vB,SAC7B+vB,EAAe/vB,QAAU,MAGvBiwB,EAAUjwB,UACZiwB,EAAUjwB,QAAQ4yB,aAClB3C,EAAUjwB,QAAU,MAGlBgwB,EAAgBhwB,UAClBgwB,EAAgBhwB,QAAQmjB,QAAQwD,MAAM,QACtCqJ,EAAgBhwB,QAAU,MAG5B8vB,EAAgB9vB,QAAU,MAGtBizB,GAAmB,KAClBxD,EAAUzvB,UAIfyvB,EAAUzvB,QAAQkzB,YAAYpzB,QAASqzB,GAAUA,EAAM9O,QACvDoL,EAAUzvB,QAAU,OAGhBozB,GAAmB,KAClBzD,EAA0B3vB,UAI/B2vB,EAA0B3vB,QAAQqkB,OAClCsL,EAA0B3vB,QAAU,OAGhCqzB,GAAoB,KACxB,MAAMC,EAAcjC,GAAerxB,QACnCqxB,GAAerxB,QAAU,KACzBszB,GAAahP,SACbgN,GAA8BtxB,QAAU,KACxCuxB,GAAyBvxB,QAAU,IAGrC4xB,GACE,IAAM,KACJO,KACAY,KACAxC,GAAyBvwB,SAAU,EAEnCozB,KACArW,KACAsW,KACAL,KACAC,KACAJ,KAEA,MAAMU,EAAW/D,EAAYxvB,QACzBuzB,IACFA,EAASC,gBAAkB,KAC3BD,EAASE,OAAS,KAClBF,EAASjQ,QAAU,KACI,aAAnBiQ,EAAS31B,OACX21B,EAASlP,OAEXmL,EAAYxvB,QAAU,MAGxBqzB,MAEF,IAIFzB,GAAU,KACR,MAAM8B,EPrjB2B,MACnC,GAA4B,oBAAjB5hB,aAA8B,OAAO,KAChD,MAAMnD,EAAMmD,aAAalD,QAAQgD,IACjC,IAAKjD,EAAK,OAAO,KACjB,IACE,MAAMpF,EAASW,KAAK2E,MAAMF,GAC1B,OAAIyC,KAAKC,MAAQ9H,EAAOwI,QAtCN,KAuChBC,KACO,MAEFzI,CACT,CAAA,MAEE,OADAyI,KACO,IACT,GOuiBsB2hB,GACpB,IAAKD,EAAa,OAElB1hB,KACAxH,QAAQwE,KAAK,2CAGT0kB,EAAY9R,YACdgO,EAAa5vB,QAAU0zB,EAAY9R,UACP,oBAAjB9P,cACTA,aAAaxH,QAAQ0hB,GAAgB0H,EAAY9R,YAIrD,MAAMgS,EAAe1B,KACrBhE,GAAU,GACVkB,EAAUpvB,SAAU,EACpByuB,GAAkB,GAClBM,EAAkB7C,IAElB,MAAM2H,EAAmBrlB,KAAiBvF,QAapC6qB,ENo2BuB,EAC/BlY,EACA8X,EACA7J,EACAxI,EACA8G,KAEA,IAEIC,EAFA1D,GAAY,EACZ2D,EAAiC,KAEjCC,GAAe,EAKnB,MAAMyL,EAAa,IAAIL,EAAYnJ,kBACnC,IAAA,MAAWyJ,KAAMN,EAAYrJ,iBACvB0J,EAAW11B,KAAMnG,GAAMA,EAAE8iB,UAAYgZ,EAAGhZ,WAC5B,aAAZgZ,EAAG/Y,KACL8Y,EAAWl5B,KAAK,CACdmgB,QAASgZ,EAAGhZ,QACZE,OAAQ,yCAA2D,oBAAX/P,OAAyBA,OAAOc,SAASpD,KAAO,sBAAsBghB,MAGhIkK,EAAWl5B,KAAK,CACdmgB,QAASgZ,EAAGhZ,QACZE,OAAQ,sDA+Ld,MAAO,CACLmJ,KAAM,KACJK,GAAY,EACZ3H,KACIqL,GAAcA,EAAa9D,SAASqC,MAAM,QAC1C0B,GAAgBA,EAAanE,YAAc1C,UAAU2C,MACvDkE,EAAalF,SAGjBqC,KAnMkB,IAAI5kB,QAAcyR,MAAOvR,EAASif,KACpD,IACE,GAAI2E,SAAkB5jB,IAEtB,IAAIgoB,EAAqB4K,EAAY9R,UAErC,MAAM4C,QAAsB,IAAI5jB,QAAgB,CAACsoB,EAAcC,KAC7D,GAAIzE,EAA+B,YAAlBwE,EAAa,IAE9B,MAAM5H,EAAQxF,GAAeF,EAAS,kBAChC2F,EAAS,IAAIC,UAAUF,GAC7B+G,EAAe9G,EAEf,IAAI6H,EAAa,GACbC,GAAW,EACXC,EAAmB,GACnBC,EAAsB,GAE1B,MAAMC,EAAUC,IACVJ,IACJA,GAAW,EACXH,EAAaO,KAGTC,EAAQnf,IACR8e,IACJA,GAAW,EACXF,EAAY5e,KAGdgX,EAAOkB,OAAS,KACdjY,QAAQwE,KAAK,qCACbuS,EAAOoB,KAAKzY,KAAKC,UAAU,CACzB/Q,KAAM,SACNwpB,WAAY8Q,EAAY7Q,UACxBL,WAAYkR,EAAY9R,UACxB+H,MAAO+J,EAAY/J,MACnBC,aAAcC,EACdhE,mBAAoB6N,EAAYnvB,kBAChC0vB,kBAAmBP,EAAYpK,kBAAoB,GACnD4K,mBAAoBR,EAAYrJ,iBAChC8J,aAAcJ,MAIlBxS,EAAOyB,UAAY3Q,MAAOlV,IACxB,IAAIiC,EACJ,IACEA,EAAO8K,KAAK2E,MAAMjT,OAAOuB,EAAMiC,MACjC,CAAA,MAAU,MAAQ,CAElB,MAAM0qB,EAAU1qB,EAAKhG,KAErB,GAAgB,YAAZ0wB,GAAoD,iBAApB1qB,EAAKojB,WAGvC,OAFAsG,EAAqB1pB,EAAKojB,gBAC1BnB,EAAO6B,cAAc4F,GAIvB,GAAgB,cAAZgB,EAAJ,CAQA,GAAgB,gBAAZA,GAAmD,iBAAf1qB,EAAKsT,MAG3C,OAFA4W,GAAoBlqB,EAAKsT,WACzB2O,EAAO0I,mBAAmB3qB,EAAKsT,OAIjC,GAAgB,eAAZoX,GAA4BlxB,MAAMC,QAAQuG,EAAK4qB,OAAQ,CACzD,MAAMA,EAAQ5qB,EAAK4qB,MAGfV,EAAiBlmB,SACnBie,EAAO4I,sBAAsBX,EAAiBlmB,QAC9CmmB,GAAuBD,GAEzBA,EAAmB,GAEnBjI,EAAO6I,cAAcF,GAErB,MAAMG,EAAiD,GACvD,IAAA,MAAW9qB,KAAQ2qB,EAAO,CACxB,MAAMI,EAA2B,aAAd/qB,EAAK4b,KACpBmP,GACFvY,GAAuB,CACrB+P,UAAWkH,EACXjG,UAAW6Q,EAAY7Q,UACvB8G,MAAO+J,EAAY/J,MACnBlF,MAAOiP,EAAYjP,MACnBlgB,kBAAmBmvB,EAAYnvB,kBAC/B8lB,iBAAkBL,EAAMjqB,IAAK1H,IAAAA,CAC3B2iB,QAAS3iB,EAAE2iB,QACXC,KAAM5iB,EAAE4iB,KACRqP,KAAMjyB,EAAEiyB,QAEVC,iBAAkB,IAAIJ,GACtBb,iBAAkBC,QAAuB,IAI7C,MAAMrO,QAAeiN,EAAY9oB,GAE7B+qB,GACFpY,KAGFqP,EAAOmJ,eAAenrB,EAAK2b,QAAS3b,EAAK4b,KAAMC,EAAOA,QACtDiP,EAAQtvB,KAAKqgB,EACf,CAKA,YAHIqG,EAAO2C,aAAe1C,UAAU2C,MAClC5C,EAAOoB,KAAKzY,KAAKC,UAAU,CAAE/Q,KAAM,eAAgB+wB,aAGvD,CAEA,GAAgB,eAAZL,EAA0B,CAC5BV,EAAchqB,EAAKqrB,aAA0B,GAC7C,MAAMC,GAA2C,IAAvBtrB,EAAKurB,cAM/B,OALAtJ,EAAOuJ,kBAAkBxB,EAAYsB,GACN,iBAApBtrB,EAAKojB,YACdnB,EAAO6B,cAAc9jB,EAAKojB,iBAE5BgH,EAAOJ,EAET,CAEA,GAAgB,UAAZU,EAAqB,CACvB,MAAMe,EAAUzrB,EAAKmL,OAAoB,cAIzC,OAHA+d,GAAe,EACfjH,EAAOjB,UAAUyK,QACjBnB,EAAK,IAAIrO,MAAMwP,GAEjB,CAzEA,MALExJ,EAAOyJ,cACL1rB,EAAK2rB,UACL3rB,EAAK4rB,iBA+EXzJ,EAAO+B,QAAU,KACfgF,GAAe,EACfjH,EAAOjB,UAAU,yBACjBsJ,EAAK,IAAIrO,MAAM,2BAGjBkG,EAAOiC,QAAU,IAAMgG,EAAOJ,KAMhC,GAHAf,EAAe,KAGX3D,IAAcF,EAIhB,OAHKE,GACH/P,KAEK7T,IAGT0J,QAAQwE,KAAK,uCAAuC0kB,EAAYjP,SAChE9P,WACM0R,GACJzK,EAAS4I,EAAekP,EAAYjP,MAAO/U,QAAQgkB,EAAYnvB,mBAC/D,IAAMmgB,EACLnD,IAAa8G,EAAe9G,GAC5B6F,IAAagB,EAAehB,GAC7B/F,EAAOrD,oBAGTld,GACF,OAAS0f,GACP,IAAK8H,EAAc,CACjB,MAAMlN,EAAMoF,aAAenF,MAAQmF,EAAIlF,QAAU1f,OAAO4kB,GACxDa,EAAOjB,UAAUhF,EACnB,CACA2E,EAAOS,EACT,CAAA,QACE4H,GAAc9D,SAASqC,MAAM,QACzB0B,GAAgBA,EAAanE,YAAc1C,UAAU2C,MACvDkE,EAAalF,QAEfkF,EAAe,IACjB,MM1jCmB+L,CACjBhT,EAAOiT,eACPX,EACAG,EACA,CACE3Q,YAAcoR,IACPlC,GAAsBwB,IACvBU,GAAOA,IAAQ1E,EAAa5vB,UAC9B4vB,EAAa5vB,QAAUs0B,EACK,oBAAjBxiB,cACTA,aAAaxH,QAAQ0hB,GAAgBsI,KAI3CvK,iBAAmBrX,IACZ0f,GAAsBwB,KAC3BnF,GAAkB,GAClBJ,GAAc,GACdU,EAAkB,MAElBmC,GAAwBlxB,SAAW0S,EAEG,OAAlC+d,GAAsBzwB,QACxBywB,GAAsBzwB,QAAUu0B,GAC9BrD,GAAwBlxB,SACxB,GAGFw0B,GACE/D,GAAsBzwB,QACtBkxB,GAAwBlxB,WAI9B4qB,gBAAiB,CAACpG,EAAe6I,KAC/B,IAAK+E,GAAsBwB,GAAe,OAC1C3B,GAAQ,aACRR,GAAgBzxB,SAA2B,IAAjBqtB,EAC1B0B,EAAkB,MAClBV,GAAc,GACdE,GAAoB,GAEpB,MAAMkG,EACJjQ,GAAiB0M,GAAwBlxB,QAC3CkxB,GAAwBlxB,QAAUy0B,EAEI,OAAlChE,GAAsBzwB,QACxBw0B,GACE/D,GAAsBzwB,QACtBy0B,GAGFhE,GAAsBzwB,QAAUu0B,GAC9BE,GACA,IAINxK,oBAAsBpoB,IACfuwB,GAAsBwB,IACtB5L,GACH5G,EAAOiT,eAAgBxyB,EAAMuf,EAAOqD,MACpClgB,EAAoB3G,GAAU82B,GAAuB92B,EAAOg2B,IAC5DjN,MAAOnG,GAAQhW,QAAQC,KAAK,kCAAmC+V,KAEnE0J,YAAcF,IACPoI,GAAsBwB,KACvB5J,EAAMxvB,OAAS,GACjBy3B,GAAQ,YAEVxD,GAAkB,GAClBM,EAAkB7C,IAClByI,GAA4B3K,GAE5ByG,GAAsBzwB,QAAU,KAChCkxB,GAAwBlxB,QAAU,KAEpCwqB,aAAc,OACdM,YAAa,KACNsH,GAAsBwB,KAC3B3B,GAAQ,YACR5D,GAAc,GACdU,EAAkB7C,MAEpBlO,mBAAqBpgB,IACnB82B,GAAuB92B,EAAOg2B,IAEhCxT,QAAUI,IACH4R,GAAsBwB,KAC3B7E,EAAkB,MAClBwF,GAAc,SAAS/T,KAAO,MArGbnO,MACrBhT,IAEA,MAAM+rB,EAA2B,CAC/BnQ,KAAM5b,EAAK4b,KACXD,QAAS3b,EAAK2b,WACX3b,EAAKirB,MAEV,OAAOxP,GAAsBsQ,KAmG/BuE,EAA0B3vB,QAAU8zB,EAEpCA,EAAWtO,KACRmB,MAAM,QACNiO,QAAQ,KACFxC,GAAsBwB,KAC3B1F,GAAU,GACVkB,EAAUpvB,SAAU,EACpByuB,GAAkB,GAClBJ,GAAc,GACdE,GAAoB,GACpBC,GAAkB,GAClBO,EAAkB,MAClBmC,GAAwBlxB,QAAU,GAClCywB,GAAsBzwB,QAAU,KAChC2vB,EAA0B3vB,QAAU,MAGjCwxB,GAAwBxxB,SACzBotB,GACE7oB,EACAktB,GAAgBzxB,QAChBsvB,EAAetvB,UAIZ60B,GAAe,OAGtBpD,GAAgBzxB,SAAU,MAE7B,IAEH,MAAMu0B,GAAgB,CACpB1yB,EACAkrB,EACA+H,KAOA,MAAMvsB,EAAKgnB,EAAiBvvB,UAa5B,OAZA8tB,EAAaiH,GAAa,IACrBA,EACH,CACExsB,KACA1G,OACAkrB,SACA3zB,KAAM07B,GAAS17B,KACf47B,SAAUF,GAASE,SACnBC,UAAWH,GAASG,UACpBC,UAAWJ,GAASI,aAGjB3sB,GAGHosB,GAA+B3K,IACnC8D,EAAaiH,IACX,MAAMnJ,EAAO,IAAImJ,GAEjB,IAAA,MAAW11B,KAAQ2qB,EAAO,CACxB,MAAMmL,EAAY7H,GAAwBjuB,GACpC+1B,EAAOxJ,EAAKA,EAAKpxB,OAAS,GAC1B66B,EAAyC,iBAAfD,GAAMvzB,KAClCuzB,EAAKvzB,KAAKlF,QAAQ,cAAe,IACjC,GAEJ,GACEy4B,IACIA,EAAKrI,QACQ,SAAdqI,EAAKh8B,MACLi8B,IAAqBF,EAAUtzB,KAClC,CACA,MAAMyzB,EAAiB9rB,OAAOC,SAC3B2rB,EAAKvzB,KAAKyB,MAAM,mBAAmB,IAAM,IAC1C,IAGIiyB,GADmB/rB,OAAOgsB,SAASF,GAAkBA,EAAiB,GACvC,EAC/BG,EAAYJ,GAAoBF,EAAUtzB,KAChD+pB,EAAKA,EAAKpxB,OAAS,GAAK,IACnB46B,EACHH,UAAWQ,EACXP,UAAWK,EACX1zB,KAAM,GAAG4zB,MAAcF,MAEzB,QACF,CAEA,MAAMhtB,EAAKgnB,EAAiBvvB,UAC5B4rB,EAAK/wB,KAAK,CACR0N,KACA1G,KAAMszB,EAAUtzB,KAChBkrB,QAAQ,EACR3zB,KAAM,OACN47B,SAAUG,EAAU5H,KACpB0H,UAAWE,EAAUtzB,KACrBqzB,UAAW,GAEf,CAIA,GAA4B,oBAAjBpjB,aACT,IACEA,aAAaxH,QAAQwhB,GAAa5hB,KAAKC,UAAUyhB,IACjD9Z,aAAaxH,QAAQyhB,GAAe3a,KAAKC,MAAM6K,WACjD,CAAA,MAA4C,CAG9C,OAAO0P,KAIL4I,GAAoB,CAACjsB,EAAY1G,KACrCisB,EAAaiH,GACXA,EAASh1B,IAAKub,GACZA,EAAQ/S,KAAOA,EAAK,IAAK+S,EAASzZ,QAASyZ,KAK3Coa,GAA+B7zB,IACnC,MAAMma,EAAana,EAAKuB,OACnB4Y,IAGLuV,GAAyBvxB,QAAUgc,EACW,OAA1CsV,GAA8BtxB,QAIlCw0B,GAAkBlD,GAA8BtxB,QAASgc,GAHvDsV,GAA8BtxB,QAAUu0B,GAAcvY,GAAY,KAMhE2Z,GAAkC,KACtCrE,GAA8BtxB,QAAU,KACxCuxB,GAAyBvxB,QAAU,IAG/B00B,GAAyB,CAAC92B,EAAyBg2B,KACvD,GAA4B,iBAAjBA,GAA8BxB,GAAsBwB,GAA/D,CAIA,GAAc,cAAVh2B,EAGF,OAFA2wB,GAAoB,QACpBC,GAAkB,GAIpB,GAAc,YAAV5wB,EAGF,OAFA2wB,GAAoB,QACpBC,GAAkB,GAIpB,GAAc,aAAV5wB,EAGF,OAFA2wB,GAAoB,QACpBC,GAAkB,GAIpB,GAAc,SAAV5wB,EAGF,OAFA2wB,GAAoB,QACpBC,GAAkB,GAIpBD,GAAoB,GACpBC,GAAkB,EA3BlB,GA8BIoH,GAAuBhC,KACC,iBAAjBA,GAA8BxB,GAAsBwB,MAI/DxC,GAA6BpxB,SAAU,EACvC+uB,EAAkB,MAClBb,GAAU,GACVkB,EAAUpvB,SAAU,EACpBouB,GAAkB,GAClBC,GAAc,GACdE,GAAoB,GACpBC,GAAkB,GAClBC,GAAkB,GAClBwC,GAAmBjxB,QAAU,KAC7BkxB,GAAwBlxB,QAAU,GAClCywB,GAAsBzwB,QAAU,KAC5B2vB,EAA0B3vB,UAC5B2vB,EAA0B3vB,QAAU,OAGnCwxB,GAAwBxxB,SACzBotB,GACE7oB,EACAktB,GAAgBzxB,QAChBsvB,EAAetvB,WAIjBwK,QAAQwE,KAAK,mEACR6lB,GAAe,QAGtBpD,GAAgBzxB,SAAU,IAGtB61B,GAAsBxjB,MAAO0W,IACjC,IAAK3H,EAAOyB,UAEV,YADA0R,GAAc,uCAAuC,GAIvD,MAAMuB,EAAqB/M,EAAS3lB,OACpC,IAAK0yB,EAEH,YADAvB,GAAc,2DAA2D,GAI3E,MAAMX,EAAe1B,KACrBhE,GAAU,GACVkB,EAAUpvB,SAAU,EACpBouB,GAAkB,GAClBC,GAAc,GACdE,GAAoB,GACpBC,GAAkB,GAClBC,GAAkB,GAClBM,EAAkB7C,IAClBkF,GAA6BpxB,SAAU,EAEvC,IACEixB,GAAmBjxB,QAAU81B,EAC7BJ,GAA4BI,GAC5BH,KAEAvC,KACA,MAAMvJ,EAAcrb,KAAiBvF,QAE/B8sB,EAAsB1jB,MAC1BhT,IAEA,MAAM+rB,EAA2B,CAC/BnQ,KAAM5b,EAAK4b,KAKXD,QAAS3b,EAAK2b,WACX3b,EAAKirB,MAEV,OAAOxP,GAAsBsQ,IAGzB0I,ENmSuB,EACjClY,EACAmN,EACAlG,EACAjB,EACAR,EAMAC,EACA8G,KAEA,IAEIC,EAFA1D,GAAY,EACZ2D,EAAiC,KAEjCC,GAAe,EA0LnB,MAAO,CACLjE,KAAM,KACJK,GAAY,EACZ3H,KACIqL,GAAcA,EAAa9D,SAASqC,MAAM,QAC1C0B,GAAgBA,EAAanE,YAAc1C,UAAU2C,MACvDkE,EAAalF,SAGjBqC,KAjMkB,IAAI5kB,QAAcyR,MAAOvR,EAASif,KACpD,IACE,GAAI2E,SAAkB5jB,IAGtB,MAAM0jB,QAAsB,IAAI5jB,QAAgB,CAACsoB,EAAcC,KAC7D,GAAIzE,EAA+B,YAAlBwE,EAAa,IAE9B,MAAM5H,EAAQxF,GAAeF,EAAS,kBAChC2F,EAAS,IAAIC,UAAUF,GAC7B+G,EAAe9G,EAEf,IAAI6H,EAAa,GACbC,GAAW,EACXP,EAAqBlH,GAAa,GAClC0H,EAAmB,GACnBC,EAAsB,GAE1B,MAAMC,EAAUC,IACVJ,IACJA,GAAW,EACXH,EAAaO,KAGTC,EAAQnf,IACR8e,IACJA,GAAW,EACXF,EAAY5e,KAGdgX,EAAOkB,OAAS,KACdlB,EAAOoB,KAAKzY,KAAKC,UAAU,CACzB/Q,KAAM,QACNwpB,WAAYC,EACZL,WAAYZ,EACZqH,UAAWF,EACXY,MAAOvI,EAAOuI,MACdC,aAAcxI,EAAOyI,YACrBhE,mBAAoBzE,EAAO7c,sBAI/Bgd,EAAOyB,UAAY3Q,MAAOlV,IACxB,IAAIiC,EACJ,IACEA,EAAO8K,KAAK2E,MAAMjT,OAAOuB,EAAMiC,MACjC,CAAA,MAAU,MAAQ,CAElB,MAAM0qB,EAAU1qB,EAAKhG,KAErB,GAAgB,YAAZ0wB,GAAoD,iBAApB1qB,EAAKojB,WAGvC,OAFAsG,EAAqB1pB,EAAKojB,gBAC1BnB,EAAO6B,cAAc4F,GAIvB,GAAgB,cAAZgB,EAAJ,CAQA,GAAgB,gBAAZA,GAAmD,iBAAf1qB,EAAKsT,MAG3C,OAFA4W,GAAoBlqB,EAAKsT,WACzB2O,EAAO0I,mBAAmB3qB,EAAKsT,OAIjC,GAAgB,eAAZoX,GAA4BlxB,MAAMC,QAAQuG,EAAK4qB,OAAQ,CACzD,MAAMA,EAAQ5qB,EAAK4qB,MAGfV,EAAiBlmB,SACnBie,EAAO4I,sBAAsBX,EAAiBlmB,QAC9CmmB,GAAuBD,GAEzBA,EAAmB,GAEnBjI,EAAO6I,cAAcF,GAErB,MAAMG,EAAiD,GACvD,IAAA,MAAW9qB,KAAQ2qB,EAAO,CACxB,MAAMI,EAA2B,aAAd/qB,EAAK4b,KACpBmP,GACFvY,GAAuB,CACrB+P,UAAWkH,EACXjG,YACA8G,MAAOvI,EAAOuI,MACdlF,MAAOrD,EAAOqD,MACdlgB,kBAAmBmL,QAAQ0R,EAAO7c,mBAClC8lB,iBAAkBL,EAAMjqB,IAAK1H,IAAAA,CAC3B2iB,QAAS3iB,EAAE2iB,QACXC,KAAM5iB,EAAE4iB,KACRqP,KAAMjyB,EAAEiyB,QAEVC,iBAAkB,IAAIJ,GACtBb,iBAAkBC,QAAuB,IAI7C,MAAMrO,QAAeiN,EAAY9oB,GAE7B+qB,GACFpY,KAGFqP,EAAOmJ,eAAenrB,EAAK2b,QAAS3b,EAAK4b,KAAMC,EAAOA,QACtDiP,EAAQtvB,KAAKqgB,EACf,CAQA,YANIqG,EAAO2C,aAAe1C,UAAU2C,MAClC5C,EAAOoB,KAAKzY,KAAKC,UAAU,CACzB/Q,KAAM,eACN+wB,aAIN,CAEA,GAAgB,eAAZL,EAA0B,CAC5BV,EAAchqB,EAAKqrB,aAA0B,GAC7C,MAAMC,GAA2C,IAAvBtrB,EAAKurB,cAM/B,OALAtJ,EAAOuJ,kBAAkBxB,EAAYsB,GACN,iBAApBtrB,EAAKojB,YACdnB,EAAO6B,cAAc9jB,EAAKojB,iBAE5BgH,EAAOJ,EAET,CAEA,GAAgB,UAAZU,EAAqB,CACvB,MAAMe,EAAUzrB,EAAKmL,OAAoB,cAIzC,OAHA+d,GAAe,EACfjH,EAAOjB,UAAUyK,QACjBnB,EAAK,IAAIrO,MAAMwP,GAEjB,CA5EA,MALExJ,EAAOyJ,cACL1rB,EAAK2rB,UACL3rB,EAAK4rB,iBAkFXzJ,EAAO+B,QAAU,KACfgF,GAAe,EACfjH,EAAOjB,UAAU,yBACjBsJ,EAAK,IAAIrO,MAAM,2BAEjBkG,EAAOiC,QAAU,IAAMgG,EAAOJ,KAMhC,GAHAf,EAAe,KAGX3D,IAAcF,EAIhB,OAHKE,GACH/P,KAEK7T,IAGT6T,WACM0R,GACJzK,EAAS4I,EAAepD,EAAOqD,MAAO/U,QAAQ0R,EAAO7c,mBACrD,IAAMmgB,EACLnD,IAAa8G,EAAe9G,GAC5B6F,IAAagB,EAAehB,GAC7B/F,EAAOrD,oBAGTld,GACF,OAAS0f,GACP,IAAK8H,EAAc,CACjB,MAAMlN,EAAMoF,aAAenF,MAAQmF,EAAIlF,QAAU1f,OAAO4kB,GACxDa,EAAOjB,UAAUhF,EACnB,CACA2E,EAAOS,EACT,CAAA,QACE4H,GAAc9D,SAASqC,MAAM,QACzB0B,GAAgBA,EAAanE,YAAc1C,UAAU2C,MACvDkE,EAAalF,QAEfkF,EAAe,IACjB,MM3eqB2N,CACjB5U,EAAOiT,eACPyB,EACA1U,EAAOyB,UACP+M,EAAa5vB,QACb,CACE2pB,MAAOvI,EAAOuI,MACdlF,MAAOrD,EAAOqD,MACdoF,cACAtlB,qBAEF,CACE2e,YAAcoR,IACPlC,GAAsBwB,IACvBU,GAAOA,IAAQ1E,EAAa5vB,UAC9B4vB,EAAa5vB,QAAUs0B,EACK,oBAAjBxiB,cACTA,aAAaxH,QAAQ0hB,GAAgBsI,KAI3CvK,iBAAmBrX,IACZ0f,GAAsBwB,KAC3BxF,GAAkB,GAClBC,GAAc,GACdI,GAAkB,GACd2C,GAA6BpxB,UAC/BoxB,GAA6BpxB,SAAU,EACvC+uB,EAAkB,OAGpBmC,GAAwBlxB,SAAW0S,EAEG,OAAlC+d,GAAsBzwB,QACxBywB,GAAsBzwB,QAAUu0B,GAC9BrD,GAAwBlxB,SACxB,GAGFw0B,GACE/D,GAAsBzwB,QACtBkxB,GAAwBlxB,WAI9B4qB,gBAAiB,CAACpG,EAAe6I,KAC/B,IAAK+E,GAAsBwB,GAAe,OAC1C3B,GAAQ,aACRR,GAAgBzxB,SAA2B,IAAjBqtB,EAC1B+D,GAA6BpxB,SAAU,EACvC+uB,EAAkB,MAClBV,GAAc,GACdE,GAAoB,GAEpB,MAAMkG,EAAmBjQ,GAAiB0M,GAAwBlxB,QAClEkxB,GAAwBlxB,QAAUy0B,EAEI,OAAlChE,GAAsBzwB,QACxBw0B,GACE/D,GAAsBzwB,QACtBy0B,GAGFhE,GAAsBzwB,QAAUu0B,GAC9BE,GACA,IAINxK,oBAAsBpoB,IACfuwB,GAAsBwB,IACtB5L,GACH5G,EAAOiT,eAAgBxyB,EAAMuf,EAAOqD,MACpClgB,EAAoB3G,GAAU82B,GAAuB92B,EAAOg2B,IAC5DjN,MAAOnG,GAAQhW,QAAQC,KAAK,kCAAmC+V,KAEnE0J,YAAcF,IACPoI,GAAsBwB,KACvB5J,EAAMxvB,OAAS,GACjBy3B,GAAQ,YAEVxD,GAAkB,GAClBM,EAAkB7C,IAClByI,GAA4B3K,GAE5ByG,GAAsBzwB,QAAU,KAChCkxB,GAAwBlxB,QAAU,KAEpCwqB,aAAc,OACdM,YAAa,KACNsH,GAAsBwB,KAC3B3B,GAAQ,YACR5D,GAAc,GACdU,EAAkB7C,MAEpBlO,mBAAqBpgB,IACnB82B,GAAuB92B,EAAOg2B,IAEhCxT,QAAUI,IACH4R,GAAsBwB,KAC3BxC,GAA6BpxB,SAAU,EACvC+uB,EAAkB,MAClBwF,GAAc,SAAS/T,KAAO,MAGlCuV,GAGFpG,EAA0B3vB,QAAU8zB,QAC9BA,EAAWtO,IACnB,OAASjb,GACP,IAAK6nB,GAAsBwB,GAAe,OAC1CxC,GAA6BpxB,SAAU,EACvC+uB,EAAkB,MACdxkB,aAAiB8Q,OACnBkZ,GAAc,SAAShqB,EAAM+Q,WAAW,EAE5C,CAAA,QACEsa,GAAoBhC,EACtB,GAwNIqC,GAAiBnB,IACrB,MAAMvB,EAAW/D,EAAYxvB,QACxBuzB,GAA+B,aAAnBA,EAAS31B,QAItBk3B,GAASoB,UACXhG,EAAwBlwB,SAAU,GAGpCgzB,KACAO,EAASlP,SAgFLwQ,GAAiBxiB,MAAOsT,IAC5B,KACEyJ,EAAUpvB,SACVsvB,EAAetvB,SACfwwB,GAAyBxwB,SAH3B,CAWA,GAHA+uB,EAAkB7C,IAClByC,GAAgB,IAEXwH,UAAUC,cAAcC,aAI3B,OAHAtH,EAAkB,MAClBJ,GAAgB,QAChB4F,GAAc,0CAA0C,GAI1D,GAA6B,oBAAlB+B,cAIT,OAHAvH,EAAkB,MAClBJ,GAAgB,QAChB4F,GAAc,+CAA+C,GAI/D/D,GAAyBxwB,SAAU,EAEnC,IACE,MAAM0nB,QAAeyO,UAAUC,aAAaC,aAAa,CAAEnV,OAAO,IAClEuO,EAAUzvB,QAAU0nB,EAIpB,MAAM6O,EAAwC,CAC5CC,mBAAoB,MAIhBC,EAAqB,CACzB,wBACA,yBACA,cAEF,IAAA,MAAWC,KAAQD,EACjB,GAAIH,cAAcK,gBAAgBD,GAAO,CACvCH,EAAgBzY,SAAW4Y,EAC3B,KACF,CAGF,MAAMnD,EAAW,IAAI+C,cAAc5O,EAAQ6O,GAC3C/G,EAAYxvB,QAAUuzB,EACtB7D,EAAe1vB,QAAU,GACzB21B,KACAhE,GAAoB3xB,SAAU,EAE9B,MAAM42B,GAAerD,EAASzV,UAAYyY,EAAgBzY,UAAY,cACnEhU,MAAM,KAAK,GACX1G,QAAU,aAEPyzB,EAAkB1V,GACtBC,EAAOiT,eACP,CACExR,UAAWzB,EAAOyB,UAClBjB,UAAWgO,EAAa5vB,QACxB8iB,SAAU,KACVhF,SAAU8Y,GAEZ,CACE1T,YAAcoR,IACPA,GAAOA,IAAQ1E,EAAa5vB,UAGjC4vB,EAAa5vB,QAAUs0B,EACK,oBAAjBxiB,cACTA,aAAaxH,QAAQ0hB,GAAgBsI,KAGzCjR,UAAW,EAAGxhB,WACPA,EAAKuB,QAGVsyB,GAA4B7zB,MAIlCwvB,GAAerxB,QAAU62B,EAEzBtD,EAASC,gBAAmBr2B,IACtBA,EAAMiC,KAAK2P,KAAO,IACpB2gB,EAAe1vB,QAAQnF,KAAKsC,EAAMiC,MAC9BiyB,GAAerxB,SACZqxB,GAAerxB,QAAQ2jB,UAAUxmB,EAAMiC,MAAMunB,MAAOpc,IACvDC,QAAQC,KACN,qCAAqCF,aAAiB8Q,MAAQ9Q,EAAM+Q,QAAU1f,OAAO2O,UAO/FgpB,EAASjQ,QAAU,KACjBiR,GAAc,6CAA6C,IAG7DhB,EAASE,OAASphB,UAChB8b,GAAe,GACfmB,EAAetvB,SAAU,EACzBswB,GAAiBtwB,QAAU,KAC3B6yB,KAEAG,KACAC,KAEA,MAAM6D,EAAgB5G,EAAwBlwB,QAC9CkwB,EAAwBlwB,SAAU,EAElC,MAAMqf,EAAO,IAAIC,KAAKoQ,EAAe1vB,QAAS,CAC5C5G,KAAMm6B,EAASzV,UAAY,eAE7B4R,EAAe1vB,QAAU,GAEzB,MAAM+2B,EAAe1F,GAAerxB,QAGpC,GAFAqxB,GAAerxB,QAAU,KAErB82B,EAIF,OAHAC,GAAczS,SACdqR,UACA5G,EAAkB,MAIpB,GAAkB,IAAd1P,EAAKtQ,KAKP,OAJAgoB,GAAczS,SACdqR,KACA5G,EAAkB,WAClBwF,GAAc,+CAA+C,GAI/DnG,GAAkB,GAClBW,EAAkB7C,IAElB,IACE,GAAI6K,EAAc,CAChBzE,KACA,MAAM/J,QAAkBwO,EAAa1S,OAOrC,GANIkE,EAAU/F,YAAc+F,EAAU/F,aAAeoN,EAAa5vB,UAChE4vB,EAAa5vB,QAAUuoB,EAAU/F,WACL,oBAAjB1Q,cACTA,aAAaxH,QAAQ0hB,GAAgBzD,EAAU/F,aAG/C+F,EAAU1mB,KAAKuB,OAIjB,OAHAsyB,GAA4BnN,EAAU1mB,MACtCktB,EAAkB7C,eACZ2J,GAAoBtN,EAAU1mB,MAGxC,CACF,OAAS0I,GACPC,QAAQC,KACN,4EAA4EF,aAAiB8Q,MAAQ9Q,EAAM+Q,QAAU1f,OAAO2O,KAEhI,CAAA,QACEorB,IACF,CAEAnrB,QAAQwE,KAAK,2EACb+f,EAAkB7C,SA1dA7Z,OAAOgN,IAC7B,IAAK+B,EAAOyB,UAEV,YADA0R,GAAc,uCAAuC,GAIvD,MAAMX,EAAe1B,KACrBhE,GAAU,GACVkB,EAAUpvB,SAAU,EACpBouB,GAAkB,GAClBC,GAAc,GACdE,GAAoB,GACpBC,GAAkB,GAClBC,GAAkB,GAClBqE,KACA/D,EAAkB7C,IAClBkF,GAA6BpxB,SAAU,EAEvC,IACE,MAAMg3B,EAAW3X,EAAKjmB,MAAQ,aACxB69B,EAAYD,EAAS7iB,SAAS,OAChC,MACA6iB,EAAS7iB,SAAS,OAChB,MACA6iB,EAAS7iB,SAAS,SAAW6iB,EAAS7iB,SAAS,OAC7C,MACA,OACFqU,EAAO,IAAI0O,KAAK,CAAC7X,GAAO,eAAe4X,IAAa,CACxD79B,KAAM49B,IAGR5D,KAEA,MAAMvJ,EAAcrb,KAAiBvF,QAG/B8sB,EAAsB1jB,MAC1BhT,IAEA,MAAM+rB,EAA2B,CAC/BnQ,KAAM5b,EAAK4b,KAKXD,QAAS3b,EAAK2b,WACX3b,EAAKirB,MAEV,OAAOxP,GAAsBsQ,IAGzB0I,EAAa7L,GACjB7G,EAAOiT,eACP7L,EACApH,EAAOyB,UACP+M,EAAa5vB,QACb,CACE2pB,MAAOvI,EAAOuI,MACdlF,MAAOrD,EAAOqD,MACdoF,cACAtlB,qBAEF,CACEqkB,iBAAkB,KACXwJ,GAAsBwB,IAC3BtB,MAEFtJ,gBAAkB5pB,IAChB,IAAKgzB,GAAsBwB,GAAe,OACtCx0B,EAAKojB,YAAcpjB,EAAKojB,aAAeoN,EAAa5vB,UACtD4vB,EAAa5vB,QAAUZ,EAAKojB,WACA,oBAAjB1Q,cACTA,aAAaxH,QAAQ0hB,GAAgB5sB,EAAKojB,aAI9C,MAAMxG,EAAa5c,EAAK6pB,UAAU7lB,OAClC,GAAI4Y,EAAY,CACd,MAAMmb,EAAmBlG,GAAmBjxB,QAC5CixB,GAAmBjxB,QAAUgc,EACiB,OAA1CsV,GAA8BtxB,SAChCw0B,GAAkBlD,GAA8BtxB,QAASgc,GACzD2Z,MACSwB,IAAqBnb,GAC9BuY,GAAcvY,GAAY,EAE9B,CAEAoS,GAAkB,GAClBC,GAAc,GACdU,EAAkB7C,KAEpBhJ,YAAcoR,IACPlC,GAAsBwB,IACvBU,GAAOA,IAAQ1E,EAAa5vB,UAC9B4vB,EAAa5vB,QAAUs0B,EACK,oBAAjBxiB,cACTA,aAAaxH,QAAQ0hB,GAAgBsI,KAI3CvK,iBAAmBrX,IACZ0f,GAAsBwB,KAC3BxF,GAAkB,GAClBC,GAAc,GACdI,GAAkB,GACd2C,GAA6BpxB,UAC/BoxB,GAA6BpxB,SAAU,EACvC+uB,EAAkB,OAIpBmC,GAAwBlxB,SAAW0S,EAEG,OAAlC+d,GAAsBzwB,QACxBywB,GAAsBzwB,QAAUu0B,GAC9BrD,GAAwBlxB,SACxB,GAGFw0B,GACE/D,GAAsBzwB,QACtBkxB,GAAwBlxB,WAI9B4qB,gBAAiB,CAACpG,EAAe6I,KAC/B,IAAK+E,GAAsBwB,GAAe,OAC1C3B,GAAQ,aACRR,GAAgBzxB,SAA2B,IAAjBqtB,EAC1B+D,GAA6BpxB,SAAU,EACvC+uB,EAAkB,MAClBV,GAAc,GACdE,GAAoB,GAEpB,MAAMkG,EACJjQ,GAAiB0M,GAAwBlxB,QAE3CmxB,GAAuBnxB,QAAU,KACjCkxB,GAAwBlxB,QAAUy0B,EAEI,OAAlChE,GAAsBzwB,QACxBw0B,GACE/D,GAAsBzwB,QACtBy0B,GAGFhE,GAAsBzwB,QAAUu0B,GAC9BE,GACA,IAINxK,oBAAsBpoB,IACfuwB,GAAsBwB,IACtB5L,GACH5G,EAAOiT,eAAgBxyB,EAAMuf,EAAOqD,MACpClgB,EAAoB3G,GAAU82B,GAAuB92B,EAAOg2B,IAC5DjN,MAAOnG,GAAQhW,QAAQC,KAAK,kCAAmC+V,KAEnE0J,YAAcF,IACPoI,GAAsBwB,KACvB5J,EAAMxvB,OAAS,GACjBy3B,GAAQ,YAEVxD,GAAkB,GAClBM,EAAkB7C,IAClByI,GAA4B3K,GAC5ByG,GAAsBzwB,QAAU,KAChCkxB,GAAwBlxB,QAAU,KAEpCwqB,aAAc,CAAC4M,EAASC,EAAWC,OAInCxM,YAAa,CAACyM,EAAYC,KACnBpF,GAAsBwB,KAE3B3B,GAAQ,YACR5D,GAAc,GACdU,EAAkB7C,MAEpBlO,mBAAqBpgB,IACnB82B,GAAuB92B,EAAOg2B,IAEhCxT,QAAUI,IACH4R,GAAsBwB,KAC3BxC,GAA6BpxB,SAAU,EACvC+uB,EAAkB,MAClBwF,GAAc,SAAS/T,KAAO,MAGlCuV,GAGFpG,EAA0B3vB,QAAU8zB,QAC9BA,EAAWtO,IAOnB,OAASjb,GACP,IAAK6nB,GAAsBwB,GAAe,OAE1CxC,GAA6BpxB,SAAU,EACvC+uB,EAAkB,KACpB,CAAA,QACE6G,GAAoBhC,EACtB,GAyQU6D,CAAgBpY,IAGX,QAATsG,GA3PS,EAAC+B,EAAqB6L,KACrC,MAAMmE,EACJvsB,OAAOwsB,cACNxsB,OACEysB,mBAEL,IAAKF,EACH,OAGF,MAAMp9B,EAAU,IAAIo9B,EACpB1H,EAAgBhwB,QAAU1F,EAE1B,MAAMu9B,EAAWv9B,EAAQw9B,iBACzBD,EAASE,QAAU,IAEnB,MAAMC,EAAS19B,EAAQ29B,wBAAwBvQ,GAC/CuI,EAAUjwB,QAAUg4B,EACpBA,EAAOE,QAAQL,GAEf,MAAMM,EAAY,IAAIza,WAAWma,EAASO,mBAC1CtI,EAAgB9vB,QAAU,KAC1B,IAAIq4B,GAAiB,EACjBC,EAAiC,KACrC,MAAMC,EAA2Bh0B,EAEjCwrB,EAAe/vB,QAAUmL,OAAO8U,YAAY,KAC1C,IAAKqP,EAAetvB,SAA8B,aAAnBuzB,EAAS31B,MAEtC,YADAo1B,KAIF6E,EAASW,qBAAqBL,GAE9B,IAAIM,EAAM,EACV,IAAA,MAAWj7B,KAAS26B,EAClBM,GAAOj7B,EAKT,GAHgBi7B,EAAMN,EAAU39B,OACP,IAhxCT,IAkxCY,CAC1B,IAAK69B,EAGH,OAFAC,EAAkB,UAClBxI,EAAgB9vB,QAAU,MAI5B,GAAgC,OAA5B8vB,EAAgB9vB,QAElB,YADA8vB,EAAgB9vB,QAAUoR,KAAKC,OAIjC,MAAMqnB,EAAkBtnB,KAAKC,MAAQye,EAAgB9vB,QAIrD,YAHIq4B,GAAkBK,EA9xCF,KA+xClBzC,KAGJ,CAEAnG,EAAgB9vB,QAAU,KACF,OAApBs4B,IACFA,EAAkBlnB,KAAKC,OAGpBgnB,GAvqC0B,EACnCM,EACAJ,EACAK,EApI2C,QAqI9BL,GAA4BI,GAAoBC,EAqqCnDC,CADmBznB,KAAKC,MAAQinB,EACMC,KACxCF,GAAiB,EACbE,GACFxJ,EAAkB7C,MAIvB,KAkLC4M,CAASpR,EAAQ6L,GAGnBA,EAASwF,MAAM,KACfzI,GAAiBtwB,QAAU2lB,EAC3BwI,GAAe,GACfmB,EAAetvB,SAAU,EAnlC3B6yB,KACAhC,GAAsB7wB,QAAUoR,KAAKC,MACrCwd,EAAuB,GAEvBiC,GAA0B9wB,QAAUmL,OAAO8U,YAAY,KACrD,MAAM+Y,EAAYnI,GAAsB7wB,QAKxC6uB,EAJkB,OAAdmK,EAImB5nB,KAAKC,MAAQ2nB,EAHX,IAIxB,KA2kCDjK,EACExqB,GAA8B,QAATohB,EACjBuG,GACAA,IAGFqE,GAAyBvwB,UAC3BuwB,GAAyBvwB,SAAU,EACnCi2B,KAEJ,OAAS1rB,GACP,MAAMsgB,EAx5CW,CAACtgB,GAClBA,aAAiB8Q,MACZ9Q,EAAM+Q,QAER,kBAo5CY2d,CAAe1uB,IAC1BsgB,EAAOjuB,cAAcuX,SAAS,eAAiB0W,EAAOjuB,cAAcuX,SAAS,aAC/Eqd,GAAwBxxB,SAAU,GAEpCqzB,KACAtE,EAAkB,MAClBwF,GAAc,oBAAoB1J,KAAU,GAC5CmI,KACAC,KACA1C,GAAyBvwB,SAAU,EACnCmuB,GAAe,GACfmB,EAAetvB,SAAU,EACzB6yB,IACF,CAAA,QACOvD,EAAetvB,SAAYovB,EAAUpvB,SACxC+uB,EAAkB,MAEpByB,GAAyBxwB,SAAU,EACnC2uB,GAAgB,EAClB,CA/MA,GAkNIuK,GAAkB,KACtB/I,EAAiBnwB,QAAU,KAC3BqwB,GAAoBrwB,SAAU,EAC9B+yB,MAgDIoG,GACJh8B,IAIA,GAFAA,EAAMi8B,iBAEFj8B,EAAMsK,cAAc4xB,sBACtB,IACEl8B,EAAMsK,cAAc4xB,sBAAsBl8B,EAAMm8B,UAClD,CAAA,MAEA,CAGF,MAAMN,EAAY7I,EAAiBnwB,QAC7Bu5B,EAAUlJ,GAAoBrwB,QAGpC,GAFAk5B,KAEkB,OAAdF,EACF,OAGF,GAAIO,EAMF,YALIjK,EAAetvB,QACjBi2B,KACSzF,GAAyBxwB,UAClCuwB,GAAyBvwB,SAAU,IAMF,QAjiDP,EAChCuS,EACAinB,EA/D+B,MAgEXjnB,GAAcinB,EAAc,OAAS,MA8hDnDC,CADaroB,KAAKC,MAAQ2nB,IAEvBnE,GAAe,QAgDxBjD,GAAU,KACR,IAAKrtB,GAAqBitB,GAAwBxxB,QAAS,OAC3D,MAAM05B,EAAQvuB,OAAOpK,WAAW,KACzBuuB,EAAetvB,SAAYovB,EAAUpvB,SAAYwwB,GAAyBxwB,SAAYwxB,GAAwBxxB,SAC5G60B,GAAe,QAErB,KACH,MAAO,IAAM1pB,OAAO3J,aAAak4B,IAChC,CAACn1B,IAEJ,MAAMo1B,GAAW,KACfxH,KACAR,GAAoB3xB,SAAU,EAC9BozB,KACArW,KACAsW,KACA4C,GAAc,CAAEC,SAAS,IACzBlD,KACAC,KACAH,KACA5E,GAAU,GACVkB,EAAUpvB,SAAU,GAIlB0tB,IACFA,EAAW1tB,QAAU,CACnB60B,eAAgB,KACdrD,GAAwBxxB,SAAU,EAC7B60B,GAAe,QAEtB+E,gBAAiB,KACf7c,KACAsW,KACA,MAAME,EAAW/D,EAAYxvB,QACzBuzB,GAA+B,aAAnBA,EAAS31B,MACvBq4B,GAAc,CAAEC,SAAS,KAEzBlD,KACAC,OAGJ0G,cAIJ,MAAME,GAAyC,CAC7C70B,SAAU,QACVE,OAAQ,OACRD,MAAO,OACPxC,MAAO,QACP0E,UAAW,QACXvB,gBAAiB,uBACjBD,aAAc3D,GACdwB,QAAS0H,EAAS,OAAS,OAC3B/F,cAAe,SACfoM,SAAU,SACVjM,OAAQ,QACRw0B,UAAW5uB,EAAS,OAAS,WAAWhJ,KACxCwT,UAAWnR,EACP,mBAAmB7C,GAAOC,YAAYM,KACtCA,GACJsD,WAAY,uBAgBRw0B,GAA+C,CACnDzzB,WAAY,OACZR,OAAQ,OACRC,OAAQ,UACRU,QAAS,MACTd,aAAc,MACdE,MAAOnE,GAAOG,KACd2B,QAAS,OACT4B,WAAY,SACZY,eAAgB,SAChBC,WAAY,SAAS/D,wBAAsCA,MAgBvD83B,GAAgBjN,IAAA,CACpBkN,SAAU,MACVxzB,QAASsmB,EAAS,WAAa,UAC/BpnB,aAAc3D,GACduE,SAAU,OACVC,WAAY,OACZ0zB,SAAU,aACVC,WAAY,WACZC,UAAWrN,EAAS,WAAa,aACjCnnB,gBAAiBmnB,EAASrrB,GAAOI,YAAc,GAC/C+D,MAAOknB,EAASrrB,GAAOK,gBAAkB,2BAiCrCs4B,GAA8C,CAClDC,KAAM,IACN50B,UAAW,OACXC,aAAc,OACdE,MAAOnE,GAAOG,KACd0E,SAAU,OACV/C,QAAS,OACT4B,WAAY,SACZqB,QAAS,SACT0zB,WAAY,SACZ5oB,SAAU,SACVgpB,aAAc,WACd5mB,QAAS,OAUL6mB,GAAiD,CACrD/0B,SAAU,OACVc,SAAU,OACVk0B,WAAY,MACZ50B,MAAOnE,GAAOG,KACd64B,UAAW,SAGPC,GAAkD,CACtDl4B,MAAO,OACPC,OAAQ,OACRiD,aAAc,QACdW,WAAY,cACZ9C,QAAS,OACT4B,WAAY,SACZY,eAAgB,SAChBD,OAAQ,UACRF,MAAO,UACPC,OAAQ,qCACRG,WAAY,aAAa/D,MAGrB04B,GAAiBv2B,GAA4C,QAA7BisB,GAAiBtwB,QACjDkG,GAAiB5B,IAAWD,EAC5Bw2B,GAAgBnM,IAAiBrqB,EACjCy2B,GAAoBx2B,EAE1B,SACG,MAAA,CAAIzB,UAAU,oBAAoBpG,MAAOo9B,GACxC1/B,SAAA,CAAAoJ,EAAC,QAAA,CAAOpJ,SAAA,kTAaKuH,GAAOG,22CAoDpBkF,EAAC,MAAA,CAAItK,MAtMsC,CAC7CgK,QAAS,YACTjD,QAAS,OACTwC,eAAgB,gBAChBZ,WAAY,UAmMRjL,SAAA,CAAAoJ,EAAChB,GAAA,CACCC,ICp/DK,yiIDq/DLG,MAAM,aACNlG,MAAO,CAAEw9B,SAAU,OAAQv3B,OAAQ,QACnCE,aAAa,IAEfmE,EAAC,MAAA,CAAItK,MAtM2C,CACpD+G,QAAS,OACT4B,WAAY,SACZC,IAAK,OAoMClL,SAAA,CAAAoJ,EAAC,SAAA,CACCnK,KAAK,SACLyJ,UAAU,mBACVpG,MAAOs9B,GACPpzB,QAzTY,KACpBwrB,KACAR,GAAoB3xB,SAAU,EAC9Bk5B,KACA3I,GAAyBvwB,SAAU,EAEnCozB,KACArW,KACAsW,KAEI7D,EAAYxvB,SAAyC,aAA9BwvB,EAAYxvB,QAAQpC,MAC7Cq4B,GAAc,CAAEC,SAAS,KAEzBhG,EAAwBlwB,SAAU,EAClCgzB,KACAC,MAGFJ,KACAhE,EAAuB,GAEvB7B,GAC0B,oBAAjBlb,aAA+BA,aAAe,MAGvD8d,EAAa5vB,QAAU,KACvB,MAAM+6B,EAAkBjO,GAAsB1L,EAAOgL,WACrDmD,EAAiBvvB,QAAUktB,GAAiB6N,GAC5CjN,EAAYiN,GAEZ7M,GAAU,GACVkB,EAAUpvB,SAAU,EACpBmuB,GAAe,GACfmB,EAAetvB,SAAU,EACzB8yB,MAwRQ,aAAW,yBACXnwB,MAAM,yBAENxI,SAAAoJ,EAAChB,IAAQC,IElgEN,2WFkgEiC,cAAY,OAAOC,MAAO,GAAIC,OAAQ,OAG5Ea,EAAC,SAAA,CACCnK,KAAK,SACLyJ,UAAU,mCACVpG,MAAO,IACFs9B,GACHv2B,QAAS,OACT4B,WAAY,SACZY,eAAgB,UAElBW,QAASC,EACT,aAAW,gBACXjE,MAAM,gBAENxI,SAAAoJ,EAAChB,IAAQC,IAAKF,GAAkB,cAAY,OAAOG,MAAO,GAAIC,OAAQ,eAK3E,MAAA,CAAIjG,MAjNiD,CACxDgK,QAAS,WACTW,UAAW,OACXkzB,KAAM,IACN50B,UAAW,KA6M2BnM,IAAKw3B,GACvC52B,SAAAoJ,EAAC,MAAA,CAAI9G,MA3M0C,CACnD+G,QAAS,OACT2B,cAAe,SACfE,IAAK,QAwM8B9L,IAAKy3B,GACjC72B,SAAAgzB,EAASptB,IAAKub,IACb,GAAqB,SAAjBA,EAAQliB,KAAiB,CAC3B,MAAM4hC,EA1LH,YADazN,EA2LuBjS,EAAQ0Z,UG3hE9C,wXHo2DE,WAATzH,EACKprB,GAEI,aAATorB,EIv2DO,wgBJ02DE,SAATA,EK12DO,yTL62DE,aAATA,EACKprB,GAEI,YAATorB,EMh3DO,yVCAA,8eP4hED,OACExmB,EAAC,MAAA,CAECtK,MAAO,IACFu9B,IAAa,GAChBrmB,QAAS,MACTnQ,QAAS,OACT4B,WAAY,SACZC,IAAK,OAGPlL,SAAA,CAAAoJ,EAAChB,GAAA,CACCC,IAAKw4B,EACL,cAAY,OACZv4B,MAAO,GACPC,OAAQ,GACRjG,MAAO,CAAEiH,WAAY,OAEtB,OAAA,CAAMvJ,SAAAmhB,EAAQzZ,SAhBVyZ,EAAQ/S,GAmBnB,CAjNiB,IAACglB,EAmNlB,OACEhqB,EAAC,MAAA,CAAqB9G,MAAOu9B,GAAa1e,EAAQyR,QAC/C5yB,SAAAmhB,EAAQzZ,MADDyZ,EAAQ/S,UAQ1BxB,EAAC,MAAA,CAAItK,MAtMsC,CAC7CgK,QAAS,YACTjD,QAAS,OACT4B,WAAY,SACZY,eAAgB,gBAChBX,IAAK,OAkMDlL,SAAA,CAAAoJ,EAAC,OAAI9G,MAAO,IAAK49B,GAAkBp0B,WAAY,yBAC5C9L,SAAA+0B,EACC3rB,EAAC,QAAKV,UAAU,oBAAoBF,MAAO8Z,EACxCtiB,SAAAsiB,IAEDgR,EACF1mB,EAAC,MAAA,CACCtK,MAAO,CACL+G,QAAS,OACT4B,WAAY,SACZC,IAAK,OAGPlL,SAAA,CAAAoJ,EAAC,OAAA,CACC9G,MAAO,CACL8J,SAAU,OACVoN,QAAS,MACTwmB,WAAY,UAEfhgC,SAAA,oBAGDoJ,EAAC,SAAA,CACCnK,KAAK,SACLuN,QAAS8mB,EACT,aACElpB,EACI,+BACA,4BAEN9H,MAAO,CACLgG,MAAO,OACPC,OAAQ,OACRiD,aAAc,OACdG,OAAQ,OACRC,OAAQ,UACRU,QAAS,MACTjD,QAAS,OACT4B,WAAY,SACZQ,gBAAiBrB,EACb7C,GAAOC,QACP,yBACJsE,WAAY,oBAAoB/D,KAChCwB,WAAY,KAGdvJ,SAAAoJ,EAAC,OAAA,CACC9G,MAAO,CACLgG,MAAO,OACPC,OAAQ,OACRiD,aAAc,MACdC,gBAAiB,UACjBpC,QAAS,QACTyC,WAAY,aAAa/D,KACzBwF,UAAWnD,EACP,mBACA,gBACJmR,UAAW,oCAKjB,OAGN3O,EAAC,MAAA,CAAItK,MAjP2C,CACpD+G,QAAS,OACT4B,WAAY,SACZC,IAAK,MACL3B,WAAY,KA8OLvJ,SAAA,CAAAkK,IACE,OAAA,CAAK5H,MAAO+9B,GACVrgC,SAAAwyB,GAAiBiC,KAElB,KACH1oB,GACC3C,EAAC,SAAA,CACCnK,KAAK,SACLyJ,UAAU,mBACVpG,MAAOk+B,GACPh0B,QAASgzB,GACT,aAAW,gBACXh3B,MAAM,gBAENxI,SAAAoJ,EAAChB,GAAA,CACCC,IAAKH,GACL,cAAY,OACZI,MAAO,GACPC,OAAQ,GACRjG,MAAO,CAAEoJ,MAAO,8BAGlBg1B,GAAgB,KAClBt3B,EAAC,SAAA,CACCnK,KAAK,SACLyJ,UAAU,mBACVpG,MAAOk+B,GACPM,cA3iBV99B,IAIA,GAFAA,EAAMi8B,kBAEFhK,EAAUpvB,QAId,GAAIsvB,EAAetvB,QAEgB,QAA7BswB,GAAiBtwB,QACnBi2B,GAAc,CAAEC,SAAS,IAEzBD,SALJ,CAcA,GAJA9F,EAAiBnwB,QAAUoR,KAAKC,MAChCgf,GAAoBrwB,SAAU,EAC9B+yB,KAEI51B,EAAMsK,cAAcyzB,kBACtB,IACE/9B,EAAMsK,cAAcyzB,kBAAkB/9B,EAAMm8B,UAC9C,CAAA,MAEA,CAGFlJ,GAAkBpwB,QAAUmL,OAAOpK,WAAW,KAEb,OAA7BovB,EAAiBnwB,SACjBovB,EAAUpvB,SACVsvB,EAAetvB,UAKjBqwB,GAAoBrwB,SAAU,EACzB60B,GAAe,WA3jDO,IAmiD7B,GA4hBUsG,YAAahC,GACbiC,gBA5dVj+B,IAEAg8B,GAAmBh8B,IA2dTk+B,SAAUP,GACV,aAAYF,GAAiB,iBAAmBv2B,EAAc,eAAiB,eAC/E1B,MACEi4B,GACI,iBACAv2B,EACE,eACA,2CAGPlK,SACCoJ,EAAChB,GADFq4B,GACE,CACCp4B,IAAKF,GACL,cAAY,OACZG,MAAO,GACPC,OAAQ,GACRjG,MAAO,CAAEoJ,MAAO,2BAGjB,CACCrD,IAAKJ,GACL,cAAY,OACZK,MAAO,GACPC,OAAQ,GACRjG,MAAO,CAAEoJ,MAAO,wCQrpE5By1B,GAAqC,CACzCjH,eAAgB,uBAChBxR,UAAW,GACX8G,MAPwB,qBAQxBlF,MAAO,QACPhP,UAAW/T,GAAOC,QAClByqB,UARyB,SAcrBmP,GAAqB/9B,IACzB,MAAMqe,EAAUre,EAAM4F,OACtB,IALsB,CAAC5F,GACvB,qCAAqCjB,KAAKiB,GAIrCg+B,CAAgB3f,GACnB,OAAOyf,GAAe7lB,UAExB,GAAuB,IAAnBoG,EAAQrhB,OAAc,CACxB,MAAMtC,EAAI2jB,EAAQ,GACZ9iB,EAAI8iB,EAAQ,GACZlgB,EAAIkgB,EAAQ,GAClB,MAAO,IAAI3jB,IAAIA,IAAIa,IAAIA,IAAI4C,IAAIA,IAAIiB,aACrC,CACA,OAAOif,EAAQjf,eAGX6+B,GAAgB,CAACC,EAAkBC,KACvC,MACMhtB,EADa4sB,GAAkBG,GACd7+B,MAAM,GACvB++B,EAAa7C,GAA0BtvB,SAASkF,EAAI9R,MAAMk8B,EAAOA,EAAQ,GAAI,IAE7E8C,EAAUC,GACDA,GAAW,EAAIH,GACxBI,EAASD,IAA4B5pB,OAH5B1U,EAGkCs+B,EAHRruB,KAAK0E,IAAI,EAAG1E,KAAKC,IAAI,IAAKD,KAAKuuB,MAAMx+B,MAGpB0e,SAAS,IAAI0C,SAAS,EAAG,KAHrE,IAACphB,GAKTtF,EAAI2jC,EAAOD,EAAU,IACrB7iC,EAAI8iC,EAAOD,EAAU,IACrBjgC,EAAIkgC,EAAOD,EAAU,IAE3B,MAAO,IAAIG,EAAM7jC,KAAK6jC,EAAMhjC,KAAKgjC,EAAMpgC,MAGnCsgC,GAAcxmB,IAClB,MAAMuG,EAAauf,GAAkB9lB,GACrC/T,GAAOC,QAAUqa,EACjBta,GAAOE,aAAe65B,GAAczf,GAAY,KAChDta,GAAOI,YAAcka,GAuCjBkgB,GAAyB,mCACzBC,GAAoB,QACpBC,GAAsB,8BAkBtBC,GAAc,EAAGjb,aAErB,MAAOkb,EAAYC,GAAiBxO,GAA6B3M,IAC1Dob,EAAaC,GAAkB1O,IAAS,GAG/C6D,GAAU,KACR,IAAKxQ,EAAOyB,UAEV,YADA4Z,GAAe,GAGjB,IAAIC,GAAY,EAsBhB,MAlFsBrqB,OACxBuJ,EACAiH,KAEA,IACE,MAAM7Z,EAAM4S,EAAQjf,QAAQ,OAAQ,IAC9BggC,QAAY1V,MAAM,GAAGje,cAAgB6Z,YAC3C,OAAK8Z,EAAIxV,SACKwV,EAAIpgB,OADE,IAEtB,CAAA,MACE,OAAO,IACT,GAmDEqgB,CAAkBxb,EAAOiT,eAAgBjT,EAAOyB,WAAWlkB,KAAMk+B,IAC/D,IAAIH,EAAJ,CACA,GAAIG,EAAQ,CACV,MAAMC,EAA6B,IAC9B1b,EACH3L,UAAW8lB,GAAkBsB,EAAOE,YAAc3b,EAAO3L,WACzDkU,MAAOkT,EAAOlT,OAASvI,EAAOuI,MAC9ByC,UAAWyQ,EAAOG,YAAc5b,EAAOgL,UACvC3H,MACmB,UAAjBoY,EAAOpY,OAAsC,WAAjBoY,EAAOpY,OAAuC,QAAjBoY,EAAOpY,MAC5DoY,EAAOpY,MACPrD,EAAOqD,OAGfwX,GAAWa,EAAOrnB,WAClB8mB,EAAcO,EAChB,CACAL,GAAe,EAhBA,IAmBV,KAAQC,GAAY,IAC1B,CAACtb,IAGJ,MAAO6b,EAAQC,GAAanP,GAAS,IACP,oBAAjBjc,cAC2C,SAA7CA,aAAalD,QAAQ,sBAKzBpK,EAAY24B,GAAiBpP,IAAS,IACtCqP,EAAwBC,GAA6BtP,GAAS,IACvC,oBAAjBjc,cAG6C,SAAjDA,aAAalD,QAAQstB,MAIvB73B,EAAa8pB,GAAkBJ,IAAS,IACxCzpB,EAAQ4pB,GAAaH,IAAS,IAC9BrpB,EAAgB44B,GAAqBvP,GAAwB,OAC7DwP,EAAkBC,GAAuBzP,IAAS,GAGnD0P,EAAiBpO,GAAgC,MAEjDqO,G1BtMs+C7lC,E0BsMn8CgK,IACvCy7B,EAAkBz7B,GACL,OAATA,GAAe27B,GAAoB,I1BxM+8CvlC,EAAE,EAAEoE,GAAE,WAAW,OAAOxE,CAAC,E0ByM9gD,K1BzM89C,IAAWA,E0B4M5+C+5B,GAAU,KACR,GAAIwL,EAEF,YADAD,GAAc,GAGhB,GAAIF,EAAQ,OACZ,GAA4B,oBAAjBnrB,cAC0C,SAA/CA,aAAalD,QAAQ,sBAAkC,OAG7DuuB,GAAc,GACd,MAAMzD,EAAQ34B,WAAW,KACvBo8B,GAAc,GACc,oBAAjBrrB,cACTA,aAAaxH,QAAQ,qBAAsB,SAE5C,KACH,MAAO,IAAM9I,aAAak4B,IACzB,CAACuD,EAAQG,IAEZ,MAAMO,EAAe,KACnB,MAAMC,GAAYX,EAClBC,EAAUU,GACVT,GAAc,GACc,oBAAjBrrB,cACTA,aAAaxH,QAAQ,mBAAoB1O,OAAOgiC,KAoCpD,OAdAhM,GAAU,KACR,MAAMiM,EAAgB1lC,IACN,WAAVA,EAAEmB,KAAoB2jC,IACxBC,GAAU,GACkB,oBAAjBprB,cACTA,aAAaxH,QAAQ,mBAAoB,WAM/C,OADAvL,SAASjC,iBAAiB,UAAW+gC,GAC9B,IAAM9+B,SAAShC,oBAAoB,UAAW8gC,IACpD,CAACZ,IAECT,EAGHz1B,EAAAM,EAAA,CACGlN,SAAA,EAAC8iC,GACA15B,EAACU,GAAA,CACCC,WAAY,IAAMu5B,EAAez9B,SAAS60B,iBAC1C1wB,kBAAmB,IAAMs5B,EAAez9B,SAAS45B,kBACjDx1B,WAAY,IAAMq5B,EAAez9B,SAAS25B,WAC1Ct1B,cACAC,SACAC,kBAAmB64B,EACnB54B,aACAC,cAAe,KACb04B,GAAc,GACdQ,KAEFj5B,eAAgB64B,EAAmB,KAAO74B,EAC1CC,eAAgB,IAAMg5B,IACtB/4B,eAAgB,IAAM44B,GAAoB,KAG9Cj6B,EAACiqB,GAAA,CACC5mB,QA9Cc,KAClBs2B,GAAU,GACkB,oBAAjBprB,cACTA,aAAaxH,QAAQ,mBAAoB,SAE3CE,QAAQwE,KAAK,8BA0CToS,OAAQkb,EACR/3B,kBAAmB64B,EACnB3P,sBA1D0B,KAC9B,MAAM7B,GAAQwR,EACdC,EAA0BzR,GACE,oBAAjB9Z,cACTA,aAAaxH,QAAQ4xB,GAAwBtgC,OAAOgwB,IAEtDphB,QAAQwE,KAAK,8CAA8C4c,MAqDvD1gB,QAAS+xB,EACTvP,WAAY+P,EACZ9P,kBAAmBQ,EACnBP,aAAcM,EACdL,gBAAiB6P,OA/BE,MAqCrBI,GAAe,uFAID3B,mRAWAA,6HAMAA,sLAUpB,IAAI4B,GAAsC,KACtCC,GAAsC,KACtCC,IAAmB,EACnBC,IAAgB,EAMb,MAAMC,GAAO,CAACrJ,EAAwB,MAC3C,GAAIoJ,GAEF,YADA1zB,QAAQC,KAAK,gCA7Na,MAC5B,GAAwB,oBAAb1L,SACT,OAEF,GAAIA,SAASuJ,eAAe8zB,IAC1B,OAEF,MAAMgC,EAAOr/B,SAASwW,cAAc,QACpC6oB,EAAK71B,GAAK6zB,GACVgC,EAAKC,IAAM,aACXD,EAAKv1B,KAZL,4EAaA9J,SAASu/B,KAAKzoB,YAAYuoB,IAsN1BG,GAEA,MAAMC,EAxPqB,CAC3B1J,IAAA,CAEAT,eAAgBS,EAAQT,gBAAkBiH,GAAejH,eACzDxR,UAAWiS,EAAQjS,WAAayY,GAAezY,UAC/C8G,MAAO2R,GAAe3R,MACtBlF,MAAO6W,GAAe7W,MACtBhP,UAAW6lB,GAAe7lB,UAC1B2W,UAAWkP,GAAelP,YAgPJqS,CAAqB3J,GAc3C,GAbAmH,GAAWuC,EAAc/oB,WAGrBqf,EAAQ4J,aACVX,GAAkBh/B,SAASuJ,eAAewsB,EAAQ4J,aAClDT,IAAmB,IAEnBF,GAAkBh/B,SAASwW,cAAc,OACzCwoB,GAAgBx1B,GAAK,kBACrBxJ,SAAS4M,KAAKkK,YAAYkoB,IAC1BE,IAAmB,IAGhBF,GAEH,YADAvzB,QAAQD,MAAM,8BAIhB,MAAMyJ,EAAa+pB,GAAgB/pB,YAAc+pB,GAAgBY,aAAa,CAAEhZ,KAAM,SACtF3R,EAAW4qB,kBAEX,MAAMniC,EAAQsC,SAASwW,cAAc,SACrC9Y,EAAM2P,YAAc0xB,GAEpB,MAAMe,EAAY9/B,SAASwW,cAAc,OACzCspB,EAAUt2B,GAAK,qBAEfyL,EAAW+S,OAAOtqB,EAAOoiC,GACzBb,GAAkBa,EAGlBvhC,IAAQ++B,GAAA,CAAYjb,OAAQod,IAAmBK,GAC/CX,IAAgB,EAEhB1zB,QAAQ+P,IAAI,mCAMDukB,GAAU,KAChBZ,KAIDF,KACF1gC,EAAO,KAAM0gC,IACbA,GAAkB,MAGhBD,IAAmBE,IACrBl/B,SAAS4M,KAAK1S,YAAY8kC,IAG5BA,GAAkB,KAClBE,IAAmB,EACnBC,IAAgB,EAChB1zB,QAAQ+P,IAAI,qBAMDwkB,GAAU,IAAMb,GAEvBc,GAAQ,CACZb,QACAW,WACAC,YAGoB,oBAAX5zB,SACRA,OAA6C6zB,MAAQA","x_google_ignoreList":[0,1,2]}
1
+ {"version":3,"file":"embed.cjs","sources":["../node_modules/preact/dist/preact.module.js","../node_modules/preact/jsx-runtime/dist/jsxRuntime.module.js","../node_modules/preact/hooks/dist/hooks.module.js","../src/styles/constants.ts","../src/assets.ts","../src/assets/icons/hand-raised.svg?raw","../src/assets/icons/microphone-outline.svg?raw","../src/assets/icons/stop-outline.svg?raw","../src/assets/icons/x-mark.svg?raw","../src/components/SvgIcon.tsx","../src/components/ChatButton.tsx","../src/agent/context.ts","../src/agent/contextConfig.ts","../src/agent/tools.ts","../src/api/client.ts","../src/audio/sfxManager.ts","../src/assets/sfx/sent.mp3","../src/assets/sfx/thinking.mp3","../src/assets/sfx/tool_call.mp3","../src/assets/sfx/completed.mp3","../src/components/ChatWindow.tsx","../src/assets/icons/bulut_logo.svg?raw","../src/assets/icons/arrow-path.svg?raw","../src/assets/icons/cursor-arrow-rays.svg?raw","../src/assets/icons/map.svg?raw","../src/assets/icons/queue-list.svg?raw","../src/assets/icons/command-line.svg?raw","../src/assets/icons/face-smile.svg?raw","../src/index.tsx"],"sourcesContent":["var n,l,u,t,i,o,r,e,f,c,s,a,h,p={},v=[],y=/acit|ex(?:s|g|n|p|$)|rph|grid|ows|mnc|ntw|ine[ch]|zoo|^ord|itera/i,d=Array.isArray;function w(n,l){for(var u in l)n[u]=l[u];return n}function g(n){n&&n.parentNode&&n.parentNode.removeChild(n)}function _(l,u,t){var i,o,r,e={};for(r in u)\"key\"==r?i=u[r]:\"ref\"==r?o=u[r]:e[r]=u[r];if(arguments.length>2&&(e.children=arguments.length>3?n.call(arguments,2):t),\"function\"==typeof l&&null!=l.defaultProps)for(r in l.defaultProps)void 0===e[r]&&(e[r]=l.defaultProps[r]);return m(l,e,i,o,null)}function m(n,t,i,o,r){var e={type:n,props:t,key:i,ref:o,__k:null,__:null,__b:0,__e:null,__c:null,constructor:void 0,__v:null==r?++u:r,__i:-1,__u:0};return null==r&&null!=l.vnode&&l.vnode(e),e}function b(){return{current:null}}function k(n){return n.children}function x(n,l){this.props=n,this.context=l}function S(n,l){if(null==l)return n.__?S(n.__,n.__i+1):null;for(var u;l<n.__k.length;l++)if(null!=(u=n.__k[l])&&null!=u.__e)return u.__e;return\"function\"==typeof n.type?S(n):null}function C(n){var l,u;if(null!=(n=n.__)&&null!=n.__c){for(n.__e=n.__c.base=null,l=0;l<n.__k.length;l++)if(null!=(u=n.__k[l])&&null!=u.__e){n.__e=n.__c.base=u.__e;break}return C(n)}}function M(n){(!n.__d&&(n.__d=!0)&&i.push(n)&&!$.__r++||o!=l.debounceRendering)&&((o=l.debounceRendering)||r)($)}function $(){for(var n,u,t,o,r,f,c,s=1;i.length;)i.length>s&&i.sort(e),n=i.shift(),s=i.length,n.__d&&(t=void 0,o=void 0,r=(o=(u=n).__v).__e,f=[],c=[],u.__P&&((t=w({},o)).__v=o.__v+1,l.vnode&&l.vnode(t),O(u.__P,t,o,u.__n,u.__P.namespaceURI,32&o.__u?[r]:null,f,null==r?S(o):r,!!(32&o.__u),c),t.__v=o.__v,t.__.__k[t.__i]=t,N(f,t,c),o.__e=o.__=null,t.__e!=r&&C(t)));$.__r=0}function I(n,l,u,t,i,o,r,e,f,c,s){var a,h,y,d,w,g,_,m=t&&t.__k||v,b=l.length;for(f=P(u,l,m,f,b),a=0;a<b;a++)null!=(y=u.__k[a])&&(h=-1==y.__i?p:m[y.__i]||p,y.__i=a,g=O(n,y,h,i,o,r,e,f,c,s),d=y.__e,y.ref&&h.ref!=y.ref&&(h.ref&&B(h.ref,null,y),s.push(y.ref,y.__c||d,y)),null==w&&null!=d&&(w=d),(_=!!(4&y.__u))||h.__k===y.__k?f=A(y,f,n,_):\"function\"==typeof y.type&&void 0!==g?f=g:d&&(f=d.nextSibling),y.__u&=-7);return u.__e=w,f}function P(n,l,u,t,i){var o,r,e,f,c,s=u.length,a=s,h=0;for(n.__k=new Array(i),o=0;o<i;o++)null!=(r=l[o])&&\"boolean\"!=typeof r&&\"function\"!=typeof r?(\"string\"==typeof r||\"number\"==typeof r||\"bigint\"==typeof r||r.constructor==String?r=n.__k[o]=m(null,r,null,null,null):d(r)?r=n.__k[o]=m(k,{children:r},null,null,null):void 0===r.constructor&&r.__b>0?r=n.__k[o]=m(r.type,r.props,r.key,r.ref?r.ref:null,r.__v):n.__k[o]=r,f=o+h,r.__=n,r.__b=n.__b+1,e=null,-1!=(c=r.__i=L(r,u,f,a))&&(a--,(e=u[c])&&(e.__u|=2)),null==e||null==e.__v?(-1==c&&(i>s?h--:i<s&&h++),\"function\"!=typeof r.type&&(r.__u|=4)):c!=f&&(c==f-1?h--:c==f+1?h++:(c>f?h--:h++,r.__u|=4))):n.__k[o]=null;if(a)for(o=0;o<s;o++)null!=(e=u[o])&&0==(2&e.__u)&&(e.__e==t&&(t=S(e)),D(e,e));return t}function A(n,l,u,t){var i,o;if(\"function\"==typeof n.type){for(i=n.__k,o=0;i&&o<i.length;o++)i[o]&&(i[o].__=n,l=A(i[o],l,u,t));return l}n.__e!=l&&(t&&(l&&n.type&&!l.parentNode&&(l=S(n)),u.insertBefore(n.__e,l||null)),l=n.__e);do{l=l&&l.nextSibling}while(null!=l&&8==l.nodeType);return l}function H(n,l){return l=l||[],null==n||\"boolean\"==typeof n||(d(n)?n.some(function(n){H(n,l)}):l.push(n)),l}function L(n,l,u,t){var i,o,r,e=n.key,f=n.type,c=l[u],s=null!=c&&0==(2&c.__u);if(null===c&&null==e||s&&e==c.key&&f==c.type)return u;if(t>(s?1:0))for(i=u-1,o=u+1;i>=0||o<l.length;)if(null!=(c=l[r=i>=0?i--:o++])&&0==(2&c.__u)&&e==c.key&&f==c.type)return r;return-1}function T(n,l,u){\"-\"==l[0]?n.setProperty(l,null==u?\"\":u):n[l]=null==u?\"\":\"number\"!=typeof u||y.test(l)?u:u+\"px\"}function j(n,l,u,t,i){var o,r;n:if(\"style\"==l)if(\"string\"==typeof u)n.style.cssText=u;else{if(\"string\"==typeof t&&(n.style.cssText=t=\"\"),t)for(l in t)u&&l in u||T(n.style,l,\"\");if(u)for(l in u)t&&u[l]==t[l]||T(n.style,l,u[l])}else if(\"o\"==l[0]&&\"n\"==l[1])o=l!=(l=l.replace(f,\"$1\")),r=l.toLowerCase(),l=r in n||\"onFocusOut\"==l||\"onFocusIn\"==l?r.slice(2):l.slice(2),n.l||(n.l={}),n.l[l+o]=u,u?t?u.u=t.u:(u.u=c,n.addEventListener(l,o?a:s,o)):n.removeEventListener(l,o?a:s,o);else{if(\"http://www.w3.org/2000/svg\"==i)l=l.replace(/xlink(H|:h)/,\"h\").replace(/sName$/,\"s\");else if(\"width\"!=l&&\"height\"!=l&&\"href\"!=l&&\"list\"!=l&&\"form\"!=l&&\"tabIndex\"!=l&&\"download\"!=l&&\"rowSpan\"!=l&&\"colSpan\"!=l&&\"role\"!=l&&\"popover\"!=l&&l in n)try{n[l]=null==u?\"\":u;break n}catch(n){}\"function\"==typeof u||(null==u||!1===u&&\"-\"!=l[4]?n.removeAttribute(l):n.setAttribute(l,\"popover\"==l&&1==u?\"\":u))}}function F(n){return function(u){if(this.l){var t=this.l[u.type+n];if(null==u.t)u.t=c++;else if(u.t<t.u)return;return t(l.event?l.event(u):u)}}}function O(n,u,t,i,o,r,e,f,c,s){var a,h,p,v,y,_,m,b,S,C,M,$,P,A,H,L,T,j=u.type;if(void 0!==u.constructor)return null;128&t.__u&&(c=!!(32&t.__u),r=[f=u.__e=t.__e]),(a=l.__b)&&a(u);n:if(\"function\"==typeof j)try{if(b=u.props,S=\"prototype\"in j&&j.prototype.render,C=(a=j.contextType)&&i[a.__c],M=a?C?C.props.value:a.__:i,t.__c?m=(h=u.__c=t.__c).__=h.__E:(S?u.__c=h=new j(b,M):(u.__c=h=new x(b,M),h.constructor=j,h.render=E),C&&C.sub(h),h.state||(h.state={}),h.__n=i,p=h.__d=!0,h.__h=[],h._sb=[]),S&&null==h.__s&&(h.__s=h.state),S&&null!=j.getDerivedStateFromProps&&(h.__s==h.state&&(h.__s=w({},h.__s)),w(h.__s,j.getDerivedStateFromProps(b,h.__s))),v=h.props,y=h.state,h.__v=u,p)S&&null==j.getDerivedStateFromProps&&null!=h.componentWillMount&&h.componentWillMount(),S&&null!=h.componentDidMount&&h.__h.push(h.componentDidMount);else{if(S&&null==j.getDerivedStateFromProps&&b!==v&&null!=h.componentWillReceiveProps&&h.componentWillReceiveProps(b,M),u.__v==t.__v||!h.__e&&null!=h.shouldComponentUpdate&&!1===h.shouldComponentUpdate(b,h.__s,M)){for(u.__v!=t.__v&&(h.props=b,h.state=h.__s,h.__d=!1),u.__e=t.__e,u.__k=t.__k,u.__k.some(function(n){n&&(n.__=u)}),$=0;$<h._sb.length;$++)h.__h.push(h._sb[$]);h._sb=[],h.__h.length&&e.push(h);break n}null!=h.componentWillUpdate&&h.componentWillUpdate(b,h.__s,M),S&&null!=h.componentDidUpdate&&h.__h.push(function(){h.componentDidUpdate(v,y,_)})}if(h.context=M,h.props=b,h.__P=n,h.__e=!1,P=l.__r,A=0,S){for(h.state=h.__s,h.__d=!1,P&&P(u),a=h.render(h.props,h.state,h.context),H=0;H<h._sb.length;H++)h.__h.push(h._sb[H]);h._sb=[]}else do{h.__d=!1,P&&P(u),a=h.render(h.props,h.state,h.context),h.state=h.__s}while(h.__d&&++A<25);h.state=h.__s,null!=h.getChildContext&&(i=w(w({},i),h.getChildContext())),S&&!p&&null!=h.getSnapshotBeforeUpdate&&(_=h.getSnapshotBeforeUpdate(v,y)),L=a,null!=a&&a.type===k&&null==a.key&&(L=V(a.props.children)),f=I(n,d(L)?L:[L],u,t,i,o,r,e,f,c,s),h.base=u.__e,u.__u&=-161,h.__h.length&&e.push(h),m&&(h.__E=h.__=null)}catch(n){if(u.__v=null,c||null!=r)if(n.then){for(u.__u|=c?160:128;f&&8==f.nodeType&&f.nextSibling;)f=f.nextSibling;r[r.indexOf(f)]=null,u.__e=f}else{for(T=r.length;T--;)g(r[T]);z(u)}else u.__e=t.__e,u.__k=t.__k,n.then||z(u);l.__e(n,u,t)}else null==r&&u.__v==t.__v?(u.__k=t.__k,u.__e=t.__e):f=u.__e=q(t.__e,u,t,i,o,r,e,c,s);return(a=l.diffed)&&a(u),128&u.__u?void 0:f}function z(n){n&&n.__c&&(n.__c.__e=!0),n&&n.__k&&n.__k.forEach(z)}function N(n,u,t){for(var i=0;i<t.length;i++)B(t[i],t[++i],t[++i]);l.__c&&l.__c(u,n),n.some(function(u){try{n=u.__h,u.__h=[],n.some(function(n){n.call(u)})}catch(n){l.__e(n,u.__v)}})}function V(n){return\"object\"!=typeof n||null==n||n.__b&&n.__b>0?n:d(n)?n.map(V):w({},n)}function q(u,t,i,o,r,e,f,c,s){var a,h,v,y,w,_,m,b=i.props||p,k=t.props,x=t.type;if(\"svg\"==x?r=\"http://www.w3.org/2000/svg\":\"math\"==x?r=\"http://www.w3.org/1998/Math/MathML\":r||(r=\"http://www.w3.org/1999/xhtml\"),null!=e)for(a=0;a<e.length;a++)if((w=e[a])&&\"setAttribute\"in w==!!x&&(x?w.localName==x:3==w.nodeType)){u=w,e[a]=null;break}if(null==u){if(null==x)return document.createTextNode(k);u=document.createElementNS(r,x,k.is&&k),c&&(l.__m&&l.__m(t,e),c=!1),e=null}if(null==x)b===k||c&&u.data==k||(u.data=k);else{if(e=e&&n.call(u.childNodes),!c&&null!=e)for(b={},a=0;a<u.attributes.length;a++)b[(w=u.attributes[a]).name]=w.value;for(a in b)if(w=b[a],\"children\"==a);else if(\"dangerouslySetInnerHTML\"==a)v=w;else if(!(a in k)){if(\"value\"==a&&\"defaultValue\"in k||\"checked\"==a&&\"defaultChecked\"in k)continue;j(u,a,null,w,r)}for(a in k)w=k[a],\"children\"==a?y=w:\"dangerouslySetInnerHTML\"==a?h=w:\"value\"==a?_=w:\"checked\"==a?m=w:c&&\"function\"!=typeof w||b[a]===w||j(u,a,w,b[a],r);if(h)c||v&&(h.__html==v.__html||h.__html==u.innerHTML)||(u.innerHTML=h.__html),t.__k=[];else if(v&&(u.innerHTML=\"\"),I(\"template\"==t.type?u.content:u,d(y)?y:[y],t,i,o,\"foreignObject\"==x?\"http://www.w3.org/1999/xhtml\":r,e,f,e?e[0]:i.__k&&S(i,0),c,s),null!=e)for(a=e.length;a--;)g(e[a]);c||(a=\"value\",\"progress\"==x&&null==_?u.removeAttribute(\"value\"):null!=_&&(_!==u[a]||\"progress\"==x&&!_||\"option\"==x&&_!=b[a])&&j(u,a,_,b[a],r),a=\"checked\",null!=m&&m!=u[a]&&j(u,a,m,b[a],r))}return u}function B(n,u,t){try{if(\"function\"==typeof n){var i=\"function\"==typeof n.__u;i&&n.__u(),i&&null==u||(n.__u=n(u))}else n.current=u}catch(n){l.__e(n,t)}}function D(n,u,t){var i,o;if(l.unmount&&l.unmount(n),(i=n.ref)&&(i.current&&i.current!=n.__e||B(i,null,u)),null!=(i=n.__c)){if(i.componentWillUnmount)try{i.componentWillUnmount()}catch(n){l.__e(n,u)}i.base=i.__P=null}if(i=n.__k)for(o=0;o<i.length;o++)i[o]&&D(i[o],u,t||\"function\"!=typeof n.type);t||g(n.__e),n.__c=n.__=n.__e=void 0}function E(n,l,u){return this.constructor(n,u)}function G(u,t,i){var o,r,e,f;t==document&&(t=document.documentElement),l.__&&l.__(u,t),r=(o=\"function\"==typeof i)?null:i&&i.__k||t.__k,e=[],f=[],O(t,u=(!o&&i||t).__k=_(k,null,[u]),r||p,p,t.namespaceURI,!o&&i?[i]:r?null:t.firstChild?n.call(t.childNodes):null,e,!o&&i?i:r?r.__e:t.firstChild,o,f),N(e,u,f)}function J(n,l){G(n,l,J)}function K(l,u,t){var i,o,r,e,f=w({},l.props);for(r in l.type&&l.type.defaultProps&&(e=l.type.defaultProps),u)\"key\"==r?i=u[r]:\"ref\"==r?o=u[r]:f[r]=void 0===u[r]&&null!=e?e[r]:u[r];return arguments.length>2&&(f.children=arguments.length>3?n.call(arguments,2):t),m(l.type,f,i||l.key,o||l.ref,null)}function Q(n){function l(n){var u,t;return this.getChildContext||(u=new Set,(t={})[l.__c]=this,this.getChildContext=function(){return t},this.componentWillUnmount=function(){u=null},this.shouldComponentUpdate=function(n){this.props.value!=n.value&&u.forEach(function(n){n.__e=!0,M(n)})},this.sub=function(n){u.add(n);var l=n.componentWillUnmount;n.componentWillUnmount=function(){u&&u.delete(n),l&&l.call(n)}}),n.children}return l.__c=\"__cC\"+h++,l.__=n,l.Provider=l.__l=(l.Consumer=function(n,l){return n.children(l)}).contextType=l,l}n=v.slice,l={__e:function(n,l,u,t){for(var i,o,r;l=l.__;)if((i=l.__c)&&!i.__)try{if((o=i.constructor)&&null!=o.getDerivedStateFromError&&(i.setState(o.getDerivedStateFromError(n)),r=i.__d),null!=i.componentDidCatch&&(i.componentDidCatch(n,t||{}),r=i.__d),r)return i.__E=i}catch(l){n=l}throw n}},u=0,t=function(n){return null!=n&&void 0===n.constructor},x.prototype.setState=function(n,l){var u;u=null!=this.__s&&this.__s!=this.state?this.__s:this.__s=w({},this.state),\"function\"==typeof n&&(n=n(w({},u),this.props)),n&&w(u,n),null!=n&&this.__v&&(l&&this._sb.push(l),M(this))},x.prototype.forceUpdate=function(n){this.__v&&(this.__e=!0,n&&this.__h.push(n),M(this))},x.prototype.render=k,i=[],r=\"function\"==typeof Promise?Promise.prototype.then.bind(Promise.resolve()):setTimeout,e=function(n,l){return n.__v.__b-l.__v.__b},$.__r=0,f=/(PointerCapture)$|Capture$/i,c=0,s=F(!1),a=F(!0),h=0;export{x as Component,k as Fragment,K as cloneElement,Q as createContext,_ as createElement,b as createRef,_ as h,J as hydrate,t as isValidElement,l as options,G as render,H as toChildArray};\n//# sourceMappingURL=preact.module.js.map\n","import{options as r,Fragment as e}from\"preact\";export{Fragment}from\"preact\";var t=/[\"&<]/;function n(r){if(0===r.length||!1===t.test(r))return r;for(var e=0,n=0,o=\"\",f=\"\";n<r.length;n++){switch(r.charCodeAt(n)){case 34:f=\"&quot;\";break;case 38:f=\"&amp;\";break;case 60:f=\"&lt;\";break;default:continue}n!==e&&(o+=r.slice(e,n)),o+=f,e=n+1}return n!==e&&(o+=r.slice(e,n)),o}var o=/acit|ex(?:s|g|n|p|$)|rph|grid|ows|mnc|ntw|ine[ch]|zoo|^ord|itera/i,f=0,i=Array.isArray;function u(e,t,n,o,i,u){t||(t={});var a,c,p=t;if(\"ref\"in p)for(c in p={},t)\"ref\"==c?a=t[c]:p[c]=t[c];var l={type:e,props:p,key:n,ref:a,__k:null,__:null,__b:0,__e:null,__c:null,constructor:void 0,__v:--f,__i:-1,__u:0,__source:i,__self:u};if(\"function\"==typeof e&&(a=e.defaultProps))for(c in a)void 0===p[c]&&(p[c]=a[c]);return r.vnode&&r.vnode(l),l}function a(r){var t=u(e,{tpl:r,exprs:[].slice.call(arguments,1)});return t.key=t.__v,t}var c={},p=/[A-Z]/g;function l(e,t){if(r.attr){var f=r.attr(e,t);if(\"string\"==typeof f)return f}if(t=function(r){return null!==r&&\"object\"==typeof r&&\"function\"==typeof r.valueOf?r.valueOf():r}(t),\"ref\"===e||\"key\"===e)return\"\";if(\"style\"===e&&\"object\"==typeof t){var i=\"\";for(var u in t){var a=t[u];if(null!=a&&\"\"!==a){var l=\"-\"==u[0]?u:c[u]||(c[u]=u.replace(p,\"-$&\").toLowerCase()),s=\";\";\"number\"!=typeof a||l.startsWith(\"--\")||o.test(l)||(s=\"px;\"),i=i+l+\":\"+a+s}}return e+'=\"'+n(i)+'\"'}return null==t||!1===t||\"function\"==typeof t||\"object\"==typeof t?\"\":!0===t?e:e+'=\"'+n(\"\"+t)+'\"'}function s(r){if(null==r||\"boolean\"==typeof r||\"function\"==typeof r)return null;if(\"object\"==typeof r){if(void 0===r.constructor)return r;if(i(r)){for(var e=0;e<r.length;e++)r[e]=s(r[e]);return r}}return n(\"\"+r)}export{u as jsx,l as jsxAttr,u as jsxDEV,s as jsxEscape,a as jsxTemplate,u as jsxs};\n//# sourceMappingURL=jsxRuntime.module.js.map\n","import{options as n}from\"preact\";var t,r,u,i,o=0,f=[],c=n,e=c.__b,a=c.__r,v=c.diffed,l=c.__c,m=c.unmount,s=c.__;function p(n,t){c.__h&&c.__h(r,n,o||t),o=0;var u=r.__H||(r.__H={__:[],__h:[]});return n>=u.__.length&&u.__.push({}),u.__[n]}function d(n){return o=1,h(D,n)}function h(n,u,i){var o=p(t++,2);if(o.t=n,!o.__c&&(o.__=[i?i(u):D(void 0,u),function(n){var t=o.__N?o.__N[0]:o.__[0],r=o.t(t,n);t!==r&&(o.__N=[r,o.__[1]],o.__c.setState({}))}],o.__c=r,!r.__f)){var f=function(n,t,r){if(!o.__c.__H)return!0;var u=o.__c.__H.__.filter(function(n){return!!n.__c});if(u.every(function(n){return!n.__N}))return!c||c.call(this,n,t,r);var i=o.__c.props!==n;return u.forEach(function(n){if(n.__N){var t=n.__[0];n.__=n.__N,n.__N=void 0,t!==n.__[0]&&(i=!0)}}),c&&c.call(this,n,t,r)||i};r.__f=!0;var c=r.shouldComponentUpdate,e=r.componentWillUpdate;r.componentWillUpdate=function(n,t,r){if(this.__e){var u=c;c=void 0,f(n,t,r),c=u}e&&e.call(this,n,t,r)},r.shouldComponentUpdate=f}return o.__N||o.__}function y(n,u){var i=p(t++,3);!c.__s&&C(i.__H,u)&&(i.__=n,i.u=u,r.__H.__h.push(i))}function _(n,u){var i=p(t++,4);!c.__s&&C(i.__H,u)&&(i.__=n,i.u=u,r.__h.push(i))}function A(n){return o=5,T(function(){return{current:n}},[])}function F(n,t,r){o=6,_(function(){if(\"function\"==typeof n){var r=n(t());return function(){n(null),r&&\"function\"==typeof r&&r()}}if(n)return n.current=t(),function(){return n.current=null}},null==r?r:r.concat(n))}function T(n,r){var u=p(t++,7);return C(u.__H,r)&&(u.__=n(),u.__H=r,u.__h=n),u.__}function q(n,t){return o=8,T(function(){return n},t)}function x(n){var u=r.context[n.__c],i=p(t++,9);return i.c=n,u?(null==i.__&&(i.__=!0,u.sub(r)),u.props.value):n.__}function P(n,t){c.useDebugValue&&c.useDebugValue(t?t(n):n)}function b(n){var u=p(t++,10),i=d();return u.__=n,r.componentDidCatch||(r.componentDidCatch=function(n,t){u.__&&u.__(n,t),i[1](n)}),[i[0],function(){i[1](void 0)}]}function g(){var n=p(t++,11);if(!n.__){for(var u=r.__v;null!==u&&!u.__m&&null!==u.__;)u=u.__;var i=u.__m||(u.__m=[0,0]);n.__=\"P\"+i[0]+\"-\"+i[1]++}return n.__}function j(){for(var n;n=f.shift();)if(n.__P&&n.__H)try{n.__H.__h.forEach(z),n.__H.__h.forEach(B),n.__H.__h=[]}catch(t){n.__H.__h=[],c.__e(t,n.__v)}}c.__b=function(n){r=null,e&&e(n)},c.__=function(n,t){n&&t.__k&&t.__k.__m&&(n.__m=t.__k.__m),s&&s(n,t)},c.__r=function(n){a&&a(n),t=0;var i=(r=n.__c).__H;i&&(u===r?(i.__h=[],r.__h=[],i.__.forEach(function(n){n.__N&&(n.__=n.__N),n.u=n.__N=void 0})):(i.__h.forEach(z),i.__h.forEach(B),i.__h=[],t=0)),u=r},c.diffed=function(n){v&&v(n);var t=n.__c;t&&t.__H&&(t.__H.__h.length&&(1!==f.push(t)&&i===c.requestAnimationFrame||((i=c.requestAnimationFrame)||w)(j)),t.__H.__.forEach(function(n){n.u&&(n.__H=n.u),n.u=void 0})),u=r=null},c.__c=function(n,t){t.some(function(n){try{n.__h.forEach(z),n.__h=n.__h.filter(function(n){return!n.__||B(n)})}catch(r){t.some(function(n){n.__h&&(n.__h=[])}),t=[],c.__e(r,n.__v)}}),l&&l(n,t)},c.unmount=function(n){m&&m(n);var t,r=n.__c;r&&r.__H&&(r.__H.__.forEach(function(n){try{z(n)}catch(n){t=n}}),r.__H=void 0,t&&c.__e(t,r.__v))};var k=\"function\"==typeof requestAnimationFrame;function w(n){var t,r=function(){clearTimeout(u),k&&cancelAnimationFrame(t),setTimeout(n)},u=setTimeout(r,35);k&&(t=requestAnimationFrame(r))}function z(n){var t=r,u=n.__c;\"function\"==typeof u&&(n.__c=void 0,u()),r=t}function B(n){var t=r;n.__c=n.__(),r=t}function C(n,t){return!n||n.length!==t.length||t.some(function(t,r){return t!==n[r]})}function D(n,t){return\"function\"==typeof t?t(n):t}export{q as useCallback,x as useContext,P as useDebugValue,y as useEffect,b as useErrorBoundary,g as useId,F as useImperativeHandle,_ as useLayoutEffect,T as useMemo,h as useReducer,A as useRef,d as useState};\n//# sourceMappingURL=hooks.module.js.map\n","// Widget dimensions\r\nexport const BUTTON_SIZE = 60;\r\nexport const WINDOW_WIDTH = 350;\r\nexport const WINDOW_HEIGHT = 500;\r\n\r\n// Positioning\r\nexport const POSITION_BOTTOM = 20;\r\nexport const POSITION_RIGHT = 20;\r\n\r\n// Colors — initial values match the backend ProjectSettings default.\r\n// applyTheme() in index.tsx overrides primary/primaryHover/messageUser\r\n// with the remote config value before the widget renders.\r\nexport const COLORS = {\r\n primary: \"#6C03C1\",\r\n primaryHover: \"#5b02a4\",\r\n background: \"#ffffff\",\r\n text: \"hsla(215, 100%, 5%, 1)\",\r\n textSecondary: \"hsla(215, 100%, 5%, 1)\",\r\n border: \"#e5e7eb\",\r\n messageBot: \"\",\r\n messageUser: \"#6C03C1\",\r\n messageUserText: \"#ffffff\",\r\n};\r\n\r\nconst normalizeHexColor = (hex: string): string => {\r\n const trimmed = hex.trim();\r\n if (!/^#([0-9a-fA-F]{3}|[0-9a-fA-F]{6})$/.test(trimmed)) {\r\n return \"hsla(215, 100%, 5%, 1)\";\r\n }\r\n if (trimmed.length === 4) {\r\n const r = trimmed[1];\r\n const g = trimmed[2];\r\n const b = trimmed[3];\r\n return `#${r}${r}${g}${g}${b}${b}`;\r\n }\r\n return trimmed;\r\n};\r\n\r\nexport const getContrastIconFilter = (backgroundHex: string): string => {\r\n const hex = normalizeHexColor(backgroundHex).slice(1);\r\n const r = parseInt(hex.slice(0, 2), 16);\r\n const g = parseInt(hex.slice(2, 4), 16);\r\n const b = parseInt(hex.slice(4, 6), 16);\r\n\r\n // Relative luminance approximation for quick contrast choice.\r\n const luminance = (0.299 * r + 0.587 * g + 0.114 * b) / 255;\r\n return luminance > 0.62 ? \"brightness(0) invert(0)\" : \"brightness(0) invert(1)\";\r\n};\r\n\r\n// Border radius\r\nexport const BORDER_RADIUS = {\r\n button: '50%',\r\n window: '17px',\r\n message: '10px'\r\n};\r\n\r\n// Shadows\r\nexport const SHADOW = \"0 0 15px hsla(215, 100%, 5%, 0.15)\";\r\n\r\n// Transitions\r\nexport const TRANSITIONS = {\r\n fast: '150ms ease-in-out',\r\n medium: '250ms ease-in-out'\r\n};\r\n","import microphoneIcon from \"./assets/icons/microphone.svg?inline\";\r\nimport microphoneIconRaw from \"./assets/icons/microphone.svg?raw\";\r\nimport restartIcon from \"./assets/icons/restart.svg?inline\";\r\nimport restartIconRaw from \"./assets/icons/restart.svg?raw\";\r\nimport closeIcon from \"./assets/icons/close.svg?inline\";\r\nimport closeIconRaw from \"./assets/icons/close.svg?raw\";\r\nimport stopIcon from \"./assets/icons/stop.svg?inline\";\r\nimport stopIconRaw from \"./assets/icons/stop.svg?raw\";\r\nimport arrowPathIconRaw from \"./assets/icons/arrow-path.svg?raw\";\r\nimport commandLineIconRaw from \"./assets/icons/command-line.svg?raw\";\r\nimport cursorArrowRaysIconRaw from \"./assets/icons/cursor-arrow-rays.svg?raw\";\r\nimport faceSmileIconRaw from \"./assets/icons/face-smile.svg?raw\";\r\nimport handRaisedIconRaw from \"./assets/icons/hand-raised.svg?raw\";\r\nimport mapIconRaw from \"./assets/icons/map.svg?raw\";\r\nimport microphoneOutlineIconRaw from \"./assets/icons/microphone-outline.svg?raw\";\r\nimport queueListIconRaw from \"./assets/icons/queue-list.svg?raw\";\r\nimport stopOutlineIconRaw from \"./assets/icons/stop-outline.svg?raw\";\r\nimport xMarkIconRaw from \"./assets/icons/x-mark.svg?raw\";\r\nimport bulutLogo from \"./assets/icons/bulut_logo.svg\";\r\nimport bulutLogoRaw from \"./assets/icons/bulut_logo.svg?raw\";\r\nimport sentSfx from \"./assets/sfx/sent.mp3\";\r\nimport thinkingSfx from \"./assets/sfx/thinking.mp3\";\r\nimport toolCallSfx from \"./assets/sfx/tool_call.mp3\";\r\nimport completedSfx from \"./assets/sfx/completed.mp3\";\r\n\r\nexport const microphoneIconUrl = microphoneIcon;\r\nexport const microphoneIconContent = microphoneIconRaw;\r\nexport const restartIconUrl = restartIcon;\r\nexport const restartIconContent = restartIconRaw;\r\nexport const closeIconUrl = closeIcon;\r\nexport const closeIconContent = closeIconRaw;\r\nexport const stopIconUrl = stopIcon;\r\nexport const stopIconContent = stopIconRaw;\r\nexport const arrowPathIconContent = arrowPathIconRaw;\r\nexport const commandLineIconContent = commandLineIconRaw;\r\nexport const cursorArrowRaysIconContent = cursorArrowRaysIconRaw;\r\nexport const faceSmileIconContent = faceSmileIconRaw;\r\nexport const handRaisedIconContent = handRaisedIconRaw;\r\nexport const mapIconContent = mapIconRaw;\r\nexport const microphoneOutlineIconContent = microphoneOutlineIconRaw;\r\nexport const queueListIconContent = queueListIconRaw;\r\nexport const stopOutlineIconContent = stopOutlineIconRaw;\r\nexport const xMarkIconContent = xMarkIconRaw;\r\nexport const logoUrl = bulutLogo;\r\nexport const logoContent = bulutLogoRaw;\r\nexport const sentSfxUrl = sentSfx;\r\nexport const thinkingSfxUrl = thinkingSfx;\r\nexport const toolCallSfxUrl = toolCallSfx;\r\nexport const completedSfxUrl = completedSfx;\r\n","export default \"<svg xmlns=\\\"http://www.w3.org/2000/svg\\\" fill=\\\"none\\\" viewBox=\\\"0 0 24 24\\\" stroke-width=\\\"1.5\\\" stroke=\\\"currentColor\\\">\\r\\n <path stroke-linecap=\\\"round\\\" stroke-linejoin=\\\"round\\\" d=\\\"M10.05 4.575a1.575 1.575 0 1 0-3.15 0v3m3.15-3v-1.5a1.575 1.575 0 0 1 3.15 0v1.5m-3.15 0 .075 5.925m3.075.75V4.575m0 0a1.575 1.575 0 0 1 3.15 0V15M6.9 7.575a1.575 1.575 0 1 0-3.15 0v8.175a6.75 6.75 0 0 0 6.75 6.75h2.018a5.25 5.25 0 0 0 3.712-1.538l1.732-1.732a5.25 5.25 0 0 0 1.538-3.712l.003-2.024a.668.668 0 0 1 .198-.471 1.575 1.575 0 1 0-2.228-2.228 3.818 3.818 0 0 0-1.12 2.687M6.9 7.575V12m6.27 4.318A4.49 4.49 0 0 1 16.35 15m.002 0h-.002\\\" />\\r\\n</svg>\\r\\n\"","export default \"<svg xmlns=\\\"http://www.w3.org/2000/svg\\\" fill=\\\"none\\\" viewBox=\\\"0 0 24 24\\\" stroke-width=\\\"1.5\\\" stroke=\\\"currentColor\\\">\\r\\n <path stroke-linecap=\\\"round\\\" stroke-linejoin=\\\"round\\\" d=\\\"M12 18.75a6 6 0 0 0 6-6v-1.5m-6 7.5a6 6 0 0 1-6-6v-1.5m6 7.5v3.75m-3.75 0h7.5M12 15.75a3 3 0 0 1-3-3V4.5a3 3 0 1 1 6 0v8.25a3 3 0 0 1-3 3Z\\\" />\\r\\n</svg>\\r\\n\"","export default \"<svg xmlns=\\\"http://www.w3.org/2000/svg\\\" fill=\\\"none\\\" viewBox=\\\"0 0 24 24\\\" stroke-width=\\\"1.5\\\" stroke=\\\"currentColor\\\">\\r\\n <path stroke-linecap=\\\"round\\\" stroke-linejoin=\\\"round\\\" d=\\\"M5.25 7.5A2.25 2.25 0 0 1 7.5 5.25h9a2.25 2.25 0 0 1 2.25 2.25v9a2.25 2.25 0 0 1-2.25 2.25h-9a2.25 2.25 0 0 1-2.25-2.25v-9Z\\\" />\\r\\n</svg>\\r\\n\"","export default \"<svg xmlns=\\\"http://www.w3.org/2000/svg\\\" fill=\\\"none\\\" viewBox=\\\"0 0 24 24\\\" stroke-width=\\\"1.5\\\" stroke=\\\"currentColor\\\">\\r\\n <path stroke-linecap=\\\"round\\\" stroke-linejoin=\\\"round\\\" d=\\\"M6 18 18 6M6 6l12 12\\\" />\\r\\n</svg>\\r\\n\"","\r\nimport type { CSSProperties, JSX } from \"preact\";\r\nimport { useMemo } from \"preact/hooks\";\r\n\r\nexport type SvgIconProps = Omit<JSX.IntrinsicElements[\"svg\"], \"style\"> & {\r\n src: string;\r\n title?: string;\r\n /**\r\n * If true, replaces fill and stroke attributes with \"currentColor\" in the inner SVG content.\r\n * Default: true\r\n */\r\n stripColors?: boolean;\r\n style?: CSSProperties;\r\n // Explicitly add common props to ensure destructuring works smoothly\r\n className?: string;\r\n fill?: string;\r\n stroke?: string;\r\n strokeWidth?: string | number;\r\n width?: string | number;\r\n height?: string | number;\r\n};\r\n\r\nexport function SvgIcon({\r\n src,\r\n width,\r\n height,\r\n title,\r\n stripColors = true,\r\n className,\r\n style,\r\n fill,\r\n stroke,\r\n strokeWidth,\r\n ...props\r\n}: SvgIconProps) {\r\n const { viewBox, content } = useMemo(() => {\r\n if (!src) return { viewBox: \"0 0 24 24\", content: \"\" };\r\n\r\n const trimmedSrc = src.trim();\r\n // Extract viewBox\r\n const viewBoxMatch = trimmedSrc.match(/viewBox=\"([^\"]*)\"/);\r\n const viewBox = viewBoxMatch ? viewBoxMatch[1] : \"0 0 24 24\";\r\n\r\n // Extract inner content by removing the outer <svg> wrapper\r\n // We remove the opening <svg ...> tag and the closing </svg> tag only.\r\n let content = trimmedSrc.replace(/^<svg[^>]*>/i, \"\").replace(/<\\/svg>\\s*$/i, \"\");\r\n\r\n return { viewBox, content };\r\n }, [src]);\r\n\r\n const cleanContent = useMemo(() => {\r\n if (!content) return \"\";\r\n let nextContent = content;\r\n\r\n if (stripColors) {\r\n // Force inner nodes to use props instead of hardcoded SVG values.\r\n const fillValue = fill !== undefined ? fill : \"none\";\r\n const strokeValue = stroke !== undefined ? stroke : \"currentColor\";\r\n nextContent = nextContent\r\n .replace(/fill=\"[^\"]*\"/gi, `fill=\"${fillValue}\"`)\r\n .replace(/stroke=\"[^\"]*\"/gi, `stroke=\"${strokeValue}\"`);\r\n }\r\n\r\n if (strokeWidth !== undefined) {\r\n const strokeWidthValue = String(strokeWidth);\r\n nextContent = /stroke-width=\"[^\"]*\"/i.test(nextContent)\r\n ? nextContent.replace(/stroke-width=\"[^\"]*\"/gi, `stroke-width=\"${strokeWidthValue}\"`)\r\n : nextContent.replace(\r\n /<(path|circle|ellipse|line|polyline|polygon|rect)\\b/gi,\r\n `<$1 stroke-width=\"${strokeWidthValue}\"`,\r\n );\r\n }\r\n\r\n return nextContent;\r\n }, [content, stripColors, fill, stroke, strokeWidth]);\r\n\r\n return (\r\n <svg\r\n viewBox={viewBox}\r\n width={width}\r\n height={height}\r\n className={className}\r\n style={{\r\n display: \"inline-block\",\r\n verticalAlign: \"middle\",\r\n flexShrink: 0,\r\n fill: \"none\",\r\n stroke: \"currentColor\",\r\n ...style,\r\n }}\r\n xmlns=\"http://www.w3.org/2000/svg\"\r\n {...props}\r\n dangerouslySetInnerHTML={{ __html: cleanContent }}\r\n >\r\n {title && <title>{title}</title>}\r\n </svg>\r\n );\r\n}\r\n","import {\r\n BUTTON_SIZE,\r\n POSITION_BOTTOM,\r\n POSITION_RIGHT,\r\n COLORS,\r\n SHADOW,\r\n TRANSITIONS,\r\n BORDER_RADIUS,\r\n} from \"../styles/constants\";\r\nimport {\r\n microphoneOutlineIconContent,\r\n stopOutlineIconContent,\r\n xMarkIconContent,\r\n} from \"../assets\";\r\nimport { SvgIcon } from \"./SvgIcon\";\r\n\r\ninterface ChatButtonProps {\r\n onMicClick: () => void;\r\n onCancelRecording: () => void;\r\n onStopTask: () => void;\r\n isRecording: boolean;\r\n isBusy: boolean;\r\n accessibilityMode?: boolean;\r\n showBubble: boolean;\r\n onBubbleClick: () => void;\r\n previewMessage: string | null;\r\n onPreviewClick: () => void;\r\n onPreviewClose: () => void;\r\n}\r\n\r\nexport const ChatButton = ({\r\n onMicClick,\r\n onCancelRecording,\r\n onStopTask,\r\n isRecording,\r\n isBusy,\r\n accessibilityMode = false,\r\n showBubble,\r\n onBubbleClick,\r\n previewMessage,\r\n onPreviewClick,\r\n onPreviewClose,\r\n}: ChatButtonProps) => {\r\n const bgColor = COLORS.primary;\r\n const popupBoxShadow = accessibilityMode\r\n ? `inset 0 0 0 2px ${COLORS.primary}, ${SHADOW}`\r\n : SHADOW;\r\n\r\n const containerStyle: { [key: string]: string } = {\r\n position: \"fixed\",\r\n right: `${POSITION_RIGHT}px`,\r\n bottom: `${POSITION_BOTTOM}px`,\r\n display: \"flex\",\r\n flexDirection: \"column\",\r\n alignItems: \"flex-end\",\r\n gap: \"8px\",\r\n zIndex: \"9999\",\r\n fontFamily: \"\\\"Geist\\\", sans-serif\",\r\n };\r\n\r\n const controlsRowStyle: { [key: string]: string } = {\r\n display: \"flex\",\r\n alignItems: \"center\",\r\n gap: \"10px\",\r\n };\r\n\r\n const buttonStyle: { [key: string]: string } = {\r\n width: `${BUTTON_SIZE}px`,\r\n height: `${BUTTON_SIZE}px`,\r\n minWidth: `${BUTTON_SIZE}px`,\r\n minHeight: `${BUTTON_SIZE}px`,\r\n borderRadius: BORDER_RADIUS.button,\r\n backgroundColor: bgColor,\r\n color: \"#ffffff\",\r\n border: \"none\",\r\n cursor: \"pointer\",\r\n display: \"flex\",\r\n alignItems: \"center\",\r\n justifyContent: \"center\",\r\n transition: `background-color ${TRANSITIONS.fast}, transform ${TRANSITIONS.fast}`,\r\n position: \"relative\",\r\n flexShrink: \"0\",\r\n };\r\n\r\n const iconStyle: { [key: string]: string } = {\r\n width: \"24px\",\r\n height: \"24px\",\r\n display: \"block\",\r\n };\r\n\r\n const showStopButton = isBusy && !isRecording;\r\n const mainIconSrc = showStopButton ? stopOutlineIconContent : isRecording ? xMarkIconContent : microphoneOutlineIconContent;\r\n\r\n const handleClick = () => {\r\n if (showStopButton) {\r\n onStopTask();\r\n } else if (isRecording) {\r\n onCancelRecording();\r\n } else {\r\n onMicClick();\r\n }\r\n };\r\n\r\n // Shared close button style\r\n const closeBtnStyle: { [key: string]: string } = {\r\n position: \"absolute\",\r\n top: \"6px\",\r\n right: \"6px\",\r\n width: \"20px\",\r\n height: \"20px\",\r\n borderRadius: \"50%\",\r\n border: \"none\",\r\n background: \"transparent\",\r\n cursor: \"pointer\",\r\n display: \"flex\",\r\n alignItems: \"center\",\r\n justifyContent: \"center\",\r\n fontSize: \"12px\",\r\n lineHeight: \"1\",\r\n color: COLORS.text,\r\n padding: \"0\",\r\n };\r\n\r\n const renderPopup = (\r\n content: preact.ComponentChildren,\r\n onClick: () => void,\r\n onClose: (() => void) | null,\r\n extraClass: string,\r\n scrollable: boolean,\r\n ) => (\r\n <div\r\n className={`bulut-popup ${extraClass}`}\r\n style={{ cursor: \"pointer\" }}\r\n onClick={onClick}\r\n >\r\n {/* Close button */}\r\n {onClose && (\r\n <button\r\n type=\"button\"\r\n style={closeBtnStyle}\r\n onClick={(e) => {\r\n e.stopPropagation();\r\n onClose();\r\n }}\r\n aria-label=\"Kapat\"\r\n >\r\n <SvgIcon src={xMarkIconContent} aria-hidden=\"true\" width={16} height={16} />\r\n </button>\r\n )}\r\n\r\n {/* Text content */}\r\n <div\r\n style={{\r\n paddingRight: onClose ? \"22px\" : \"0\",\r\n wordBreak: \"break-word\",\r\n ...(scrollable ? { maxHeight: \"96px\", overflowY: \"auto\" } : {}),\r\n }}\r\n >\r\n {content}\r\n </div>\r\n </div>\r\n );\r\n\r\n return (\r\n <>\r\n <style>{`\r\n @import url('https://fonts.googleapis.com/css2?family=Geist:wght@100..900&display=swap');\r\n\r\n .bulut-popup {\r\n background: #ffffff;\r\n color: ${COLORS.text};\r\n padding: 10px 14px;\r\n border-radius: 12px;\r\n font-size: 14px;\r\n line-height: 1.4;\r\n position: relative;\r\n overflow: visible;\r\n box-shadow: ${popupBoxShadow};\r\n }\r\n .bulut-popup-bubble {\r\n animation: bulut-bubbleIn 400ms ease-out;\r\n }\r\n .bulut-popup-preview {\r\n animation: bulut-popIn ${TRANSITIONS.medium};\r\n }\r\n\r\n /* Desktop: limit width, lean to right */\r\n .bulut-popup {\r\n max-width: 320px;\r\n }\r\n\r\n /* Mobile: full-width layout with popup filling remaining space */\r\n @media (max-width: 600px) {\r\n .bulut-fab-container:has(.bulut-popup) {\r\n left: 16px !important;\r\n right: 16px !important;\r\n }\r\n .bulut-fab-container:has(.bulut-popup) .bulut-controls-row {\r\n width: 100%;\r\n }\r\n .bulut-popup {\r\n flex: 1;\r\n min-width: 0;\r\n max-width: none;\r\n }\r\n }\r\n\r\n @keyframes bulut-popIn {\r\n from { opacity: 0; transform: translateX(10px); }\r\n to { opacity: 1; transform: translateX(0); }\r\n }\r\n @keyframes bulut-bubbleIn {\r\n 0% { opacity: 0; transform: translateX(10px) scale(0.95); }\r\n 60% { opacity: 1; transform: translateX(-4px) scale(1.02); }\r\n 100% { opacity: 1; transform: translateX(0) scale(1); }\r\n }\r\n @keyframes bulut-badgeIn {\r\n from { opacity: 0; transform: translateY(-4px); }\r\n to { opacity: 1; transform: translateY(0); }\r\n }\r\n `}</style>\r\n\r\n <div className=\"bulut-fab-container\" style={containerStyle}>\r\n <div className=\"bulut-controls-row\" style={controlsRowStyle}>\r\n {/* Welcome bubble */}\r\n {showBubble &&\r\n !isRecording &&\r\n !previewMessage &&\r\n renderPopup(\r\n \"Destek lazımsa hemen konuşmaya başlayabiliriz!\",\r\n onBubbleClick,\r\n null,\r\n \"bulut-popup-bubble\",\r\n false,\r\n )}\r\n\r\n {/* New-message preview */}\r\n {previewMessage &&\r\n renderPopup(\r\n previewMessage,\r\n onPreviewClick,\r\n onPreviewClose,\r\n \"bulut-popup-preview\",\r\n true,\r\n )}\r\n\r\n {/* Main mic / cancel button */}\r\n <button\r\n style={buttonStyle}\r\n onClick={handleClick}\r\n onMouseEnter={(e) => {\r\n Object.assign(e.currentTarget.style, {\r\n backgroundColor: COLORS.primaryHover,\r\n transform: \"scale(1.05)\",\r\n });\r\n }}\r\n onMouseLeave={(e) => {\r\n Object.assign(e.currentTarget.style, {\r\n transform: \"scale(1)\",\r\n });\r\n }}\r\n aria-label={showStopButton ? \"Görevi durdur\" : isRecording ? \"Kaydı iptal et\" : \"Konuşmaya başla\"}\r\n >\r\n <SvgIcon\r\n src={mainIconSrc}\r\n aria-hidden=\"true\"\r\n style={iconStyle}\r\n />\r\n </button>\r\n </div>\r\n </div>\r\n </>\r\n );\r\n};\r\n","export interface PageContext {\r\n links: string[];\r\n interactables: string[];\r\n summary: string;\r\n elementMap: Map<number, Element>;\r\n}\r\n\r\nexport interface CachedPageContextEntry {\r\n url: string;\r\n summary: string;\r\n links: string[];\r\n interactables: string[];\r\n capturedAt: number;\r\n version: number;\r\n}\r\n\r\ninterface InteractableCandidate {\r\n id: number;\r\n line: string;\r\n score: number;\r\n order: number;\r\n element: Element;\r\n}\r\n\r\nimport {\r\n MAX_LINKS,\r\n MAX_INTERACTABLES,\r\n MAX_HEADINGS,\r\n MAX_TEXT_SNIPPETS,\r\n MAX_CACHED_PAGES,\r\n MAX_PAGE_SCAN_ELEMENTS,\r\n} from \"./contextConfig\";\r\n\r\nexport const PAGE_CONTEXT_CACHE_VERSION = 4;\r\nexport const PAGE_CONTEXT_CACHE_KEY = \"auticbot_page_context_cache_v4\";\r\n\r\nconst NON_CONTENT_TAGS = new Set([\r\n \"script\",\r\n \"style\",\r\n \"noscript\",\r\n \"template\",\r\n \"link\",\r\n \"meta\",\r\n]);\r\n\r\n/** SVG drawing primitives — never useful as standalone interactables. */\r\nconst SVG_INTERNAL_TAGS = new Set([\r\n \"path\",\r\n \"circle\",\r\n \"line\",\r\n \"rect\",\r\n \"polygon\",\r\n \"polyline\",\r\n \"ellipse\",\r\n \"g\",\r\n \"use\",\r\n \"defs\",\r\n \"clippath\",\r\n \"mask\",\r\n \"symbol\",\r\n \"lineargradient\",\r\n \"radialgradient\",\r\n \"stop\",\r\n \"text\",\r\n \"tspan\",\r\n]);\r\n\r\nconst NATIVE_INTERACTIVE_TAGS = new Set([\r\n \"a\",\r\n \"button\",\r\n \"input\",\r\n \"textarea\",\r\n \"select\",\r\n \"summary\",\r\n \"details\",\r\n \"option\",\r\n]);\r\n\r\nconst INTERACTIVE_ROLES = new Set([\r\n \"button\",\r\n \"link\",\r\n \"tab\",\r\n \"menuitem\",\r\n \"option\",\r\n \"checkbox\",\r\n \"radio\",\r\n \"switch\",\r\n \"combobox\",\r\n \"textbox\",\r\n \"searchbox\",\r\n \"slider\",\r\n \"spinbutton\",\r\n \"treeitem\",\r\n]);\r\n\r\nconst pageContextCache = new Map<string, CachedPageContextEntry>();\r\nlet cacheHydrated = false;\r\n\r\n/**\r\n * Live element map — maps numeric IDs to DOM elements.\r\n * Rebuilt on every page context scan; NOT serialised to cache.\r\n */\r\nlet liveElementMap = new Map<number, Element>();\r\n\r\n/** Look up a DOM element by its semantic-map ID. */\r\nexport const getElementById = (id: number): Element | undefined =>\r\n liveElementMap.get(id);\r\n\r\nconst normalizeWhitespace = (value: string): string =>\r\n value.replace(/\\s+/g, \" \").trim();\r\n\r\nconst canonicalUrl = (rawUrl: string): string => {\r\n try {\r\n return new URL(rawUrl, rawUrl).href;\r\n } catch {\r\n return rawUrl;\r\n }\r\n};\r\n\r\nconst isCacheEntry = (value: unknown): value is CachedPageContextEntry => {\r\n if (typeof value !== \"object\" || value === null) {\r\n return false;\r\n }\r\n\r\n const obj = value as Record<string, unknown>;\r\n return (\r\n typeof obj.url === \"string\" &&\r\n typeof obj.summary === \"string\" &&\r\n Array.isArray(obj.links) &&\r\n Array.isArray(obj.interactables) &&\r\n typeof obj.capturedAt === \"number\" &&\r\n typeof obj.version === \"number\"\r\n );\r\n};\r\n\r\nconst parseTabIndex = (value: string | null): number | null => {\r\n if (value === null) {\r\n return null;\r\n }\r\n\r\n const parsed = Number.parseInt(value, 10);\r\n return Number.isNaN(parsed) ? null : parsed;\r\n};\r\n\r\nconst getPrimaryRole = (element: Element): string => {\r\n const rawRole = normalizeWhitespace(element.getAttribute(\"role\") || \"\")\r\n .toLowerCase()\r\n .split(\" \")[0];\r\n return rawRole || \"\";\r\n};\r\n\r\nconst hydrateCacheFromStorage = (): void => {\r\n if (cacheHydrated || typeof sessionStorage === \"undefined\") {\r\n return;\r\n }\r\n\r\n cacheHydrated = true;\r\n\r\n try {\r\n const raw = sessionStorage.getItem(PAGE_CONTEXT_CACHE_KEY);\r\n if (!raw) {\r\n return;\r\n }\r\n\r\n const parsed = JSON.parse(raw);\r\n if (!Array.isArray(parsed)) {\r\n return;\r\n }\r\n\r\n for (const value of parsed) {\r\n if (!isCacheEntry(value)) {\r\n continue;\r\n }\r\n if (value.version !== PAGE_CONTEXT_CACHE_VERSION) {\r\n continue;\r\n }\r\n pageContextCache.set(value.url, value);\r\n }\r\n if (pageContextCache.size > 0) {\r\n console.info(\r\n `[Autic] context cache restored entries=${pageContextCache.size}`,\r\n );\r\n }\r\n } catch (error) {\r\n console.warn(\"[Autic] context cache restore failed\", error);\r\n }\r\n};\r\n\r\nconst persistCacheToStorage = (): void => {\r\n if (typeof sessionStorage === \"undefined\") {\r\n return;\r\n }\r\n\r\n try {\r\n const serialized = JSON.stringify(\r\n Array.from(pageContextCache.values()).sort(\r\n (a, b) => a.capturedAt - b.capturedAt,\r\n ),\r\n );\r\n sessionStorage.setItem(PAGE_CONTEXT_CACHE_KEY, serialized);\r\n } catch (error) {\r\n console.warn(\"[Autic] context cache persist failed\", error);\r\n }\r\n};\r\n\r\nconst pruneOldestCacheEntries = (): void => {\r\n if (pageContextCache.size <= MAX_CACHED_PAGES) {\r\n return;\r\n }\r\n\r\n const sorted = Array.from(pageContextCache.values()).sort(\r\n (a, b) => a.capturedAt - b.capturedAt,\r\n );\r\n const overflow = sorted.length - MAX_CACHED_PAGES;\r\n for (let i = 0; i < overflow; i += 1) {\r\n pageContextCache.delete(sorted[i].url);\r\n }\r\n};\r\n\r\nconst buildSummaryWithHistory = (\r\n current: CachedPageContextEntry,\r\n): string => {\r\n const recentPages = Array.from(pageContextCache.values())\r\n .filter((entry) => entry.url !== current.url)\r\n .sort((a, b) => b.capturedAt - a.capturedAt)\r\n .slice(0, 3);\r\n\r\n if (recentPages.length === 0) {\r\n return current.summary;\r\n }\r\n\r\n const historySection = [\r\n \"Recent Page Memory:\",\r\n ...recentPages.map((entry) => {\r\n const compactSummary = normalizeWhitespace(entry.summary);\r\n return `- ${entry.url} :: ${compactSummary}`;\r\n }),\r\n ].join(\"\\n\");\r\n\r\n return `${current.summary}\\n\\n${historySection}`;\r\n};\r\n\r\nconst isVisible = (element: Element): boolean => {\r\n if (element.getAttribute(\"aria-hidden\") === \"true\") {\r\n return false;\r\n }\r\n\r\n if (element instanceof HTMLElement && element.hidden) {\r\n return false;\r\n }\r\n\r\n const style = window.getComputedStyle(element);\r\n if (style.display === \"none\" || style.visibility === \"hidden\") {\r\n return false;\r\n }\r\n\r\n const rect = element.getBoundingClientRect();\r\n return rect.width > 0 && rect.height > 0;\r\n};\r\n\r\n/**\r\n * Returns true if the element is nested inside an interactive parent\r\n * (e.g. a `<span>` or `<img>` inside a `<button>` or `<a>`).\r\n * This prevents listing child fragments of an already-listed interactable.\r\n */\r\nconst hasInteractiveAncestor = (element: Element): boolean => {\r\n let parent = element.parentElement;\r\n while (parent && parent !== document.body) {\r\n const parentTag = parent.tagName.toLowerCase();\r\n if (NATIVE_INTERACTIVE_TAGS.has(parentTag)) return true;\r\n const parentRole = getPrimaryRole(parent);\r\n if (INTERACTIVE_ROLES.has(parentRole)) return true;\r\n parent = parent.parentElement;\r\n }\r\n return false;\r\n};\r\n\r\nconst toAbsoluteUrl = (href: string): string => {\r\n try {\r\n return new URL(href, window.location.href).href;\r\n } catch {\r\n return href;\r\n }\r\n};\r\n\r\nconst getElementLabel = (element: Element): string => {\r\n const text = normalizeWhitespace(\r\n (element instanceof HTMLElement ? element.innerText : element.textContent) ||\r\n \"\",\r\n ).substring(0, 80);\r\n const ariaLabel = normalizeWhitespace(element.getAttribute(\"aria-label\") || \"\");\r\n const title = normalizeWhitespace(element.getAttribute(\"title\") || \"\");\r\n const placeholder = normalizeWhitespace(\r\n element.getAttribute(\"placeholder\") || \"\",\r\n );\r\n const name = normalizeWhitespace(element.getAttribute(\"name\") || \"\");\r\n const value =\r\n element instanceof HTMLInputElement ||\r\n element instanceof HTMLTextAreaElement ||\r\n element instanceof HTMLButtonElement\r\n ? normalizeWhitespace(element.value || \"\")\r\n : \"\";\r\n\r\n const label =\r\n text || ariaLabel || title || placeholder || value || name || \"\";\r\n\r\n const tag = element.tagName.toLowerCase();\r\n\r\n // Images: prefer alt text, fall back to src filename\r\n if (tag === \"img\") {\r\n const alt = normalizeWhitespace(element.getAttribute(\"alt\") || \"\");\r\n if (alt) return alt;\r\n const src = element.getAttribute(\"src\") || \"\";\r\n const filename = src.split(\"/\").pop()?.split(\"?\")[0] || \"\";\r\n return filename ? `img: ${filename}` : compactOuterHtml(element);\r\n }\r\n\r\n if (tag === \"svg\") {\r\n return ariaLabel || title || \"icon\";\r\n }\r\n\r\n if (tag === \"input\") {\r\n const inputType = element.getAttribute(\"type\") || \"text\";\r\n const currentValue = element instanceof HTMLInputElement ? element.value : \"\";\r\n const valueNote = currentValue ? ` val=\"${currentValue.substring(0, 40)}\"` : \"\";\r\n return `${inputType} ${label || \"input\"}${valueNote}`;\r\n }\r\n\r\n if (tag === \"textarea\") {\r\n const currentValue = element instanceof HTMLTextAreaElement ? element.value : \"\";\r\n const valueNote = currentValue ? ` val=\"${currentValue.substring(0, 40)}\"` : \"\";\r\n return `textarea ${label || \"textarea\"}${valueNote}`;\r\n }\r\n\r\n if (tag === \"select\") {\r\n const selectEl = element as HTMLSelectElement;\r\n const selectedText = selectEl.selectedOptions?.[0]?.textContent?.trim() || \"\";\r\n const valueNote = selectedText ? ` val=\"${selectedText}\"` : \"\";\r\n return `select ${label || \"select\"}${valueNote}`;\r\n }\r\n\r\n if (label) return label;\r\n\r\n // Fallback: compact outerHTML snippet so the agent can still identify the element\r\n return compactOuterHtml(element);\r\n};\r\n\r\n/** Return a trimmed, single-line outerHTML (opening tag + short text), max 90 chars. */\r\nconst compactOuterHtml = (element: Element): string => {\r\n const html = element.outerHTML || \"\";\r\n // Take only the opening tag + a little content\r\n const closeIdx = html.indexOf(\">\");\r\n if (closeIdx === -1) return html.substring(0, 90);\r\n const snippet = html.substring(0, Math.min(closeIdx + 30, 90)).replace(/\\s+/g, \" \").trim();\r\n return snippet || \"untitled\";\r\n};\r\n\r\n// ── Semantic element description ────────────────────────────────────\r\n\r\nconst describeElementType = (element: Element): string => {\r\n const tag = element.tagName.toLowerCase();\r\n const role = getPrimaryRole(element);\r\n\r\n // Role-based override\r\n if (role === \"button\" || tag === \"button\") return \"Button\";\r\n if (role === \"link\" || tag === \"a\") return \"Link\";\r\n if (role === \"tab\") return \"Tab\";\r\n if (role === \"menuitem\") return \"MenuItem\";\r\n if (role === \"checkbox\" || (tag === \"input\" && element.getAttribute(\"type\") === \"checkbox\")) return \"Checkbox\";\r\n if (role === \"radio\" || (tag === \"input\" && element.getAttribute(\"type\") === \"radio\")) return \"Radio\";\r\n if (role === \"switch\") return \"Switch\";\r\n if (role === \"combobox\" || tag === \"select\") return \"Select\";\r\n if (role === \"textbox\" || tag === \"textarea\") return \"TextArea\";\r\n if (role === \"searchbox\") return \"SearchBox\";\r\n if (role === \"slider\" || (tag === \"input\" && element.getAttribute(\"type\") === \"range\")) return \"Slider\";\r\n if (role === \"spinbutton\") return \"SpinButton\";\r\n if (role === \"option\" || tag === \"option\") return \"Option\";\r\n if (role === \"treeitem\") return \"TreeItem\";\r\n if (tag === \"input\") {\r\n const t = element.getAttribute(\"type\") || \"text\";\r\n return `Input[${t}]`;\r\n }\r\n if (tag === \"summary\") return \"Summary\";\r\n if (tag === \"details\") return \"Details\";\r\n if (element.getAttribute(\"contenteditable\") === \"true\") return \"Editable\";\r\n\r\n // Generic interactive\r\n return role ? `${role[0].toUpperCase()}${role.slice(1)}` : `<${tag}>`;\r\n};\r\n\r\nconst getElementState = (element: Element): string[] => {\r\n const states: string[] = [];\r\n\r\n const pressed = element.getAttribute(\"aria-pressed\");\r\n if (pressed === \"true\") states.push(\"Pressed\");\r\n else if (pressed === \"false\") states.push(\"Not pressed\");\r\n\r\n const expanded = element.getAttribute(\"aria-expanded\");\r\n if (expanded === \"true\") states.push(\"Expanded\");\r\n else if (expanded === \"false\") states.push(\"Collapsed\");\r\n\r\n const selected = element.getAttribute(\"aria-selected\");\r\n if (selected === \"true\") states.push(\"Selected\");\r\n\r\n if (element instanceof HTMLInputElement) {\r\n if (element.type === \"checkbox\" || element.type === \"radio\") {\r\n states.push(element.checked ? \"Checked\" : \"Unchecked\");\r\n }\r\n }\r\n\r\n if (element.hasAttribute(\"disabled\") || element.getAttribute(\"aria-disabled\") === \"true\") {\r\n states.push(\"Disabled\");\r\n }\r\n\r\n return states;\r\n};\r\n\r\ninterface SemanticScanResult {\r\n links: string[];\r\n interactables: string[];\r\n elementMap: Map<number, Element>;\r\n}\r\n\r\n/**\r\n * Scan the DOM and build a semantic element map.\r\n *\r\n * Every interactive element gets a numeric ID. The LLM uses these IDs\r\n * with `interact(id=N)` instead of fragile CSS selectors.\r\n */\r\nconst collectSemanticElements = (): SemanticScanResult => {\r\n const allElements = Array.from(document.querySelectorAll(\"*\"));\r\n const sampledElements = allElements.slice(0, MAX_PAGE_SCAN_ELEMENTS);\r\n\r\n const links: string[] = [];\r\n const linkSet = new Set<string>();\r\n const candidates: InteractableCandidate[] = [];\r\n const elementMap = new Map<number, Element>();\r\n let idCounter = 1;\r\n\r\n for (let order = 0; order < sampledElements.length; order += 1) {\r\n const element = sampledElements[order];\r\n const tag = element.tagName.toLowerCase();\r\n\r\n if (NON_CONTENT_TAGS.has(tag)) continue;\r\n if (SVG_INTERNAL_TAGS.has(tag)) continue;\r\n if (!isVisible(element)) continue;\r\n\r\n const role = getPrimaryRole(element);\r\n const style = window.getComputedStyle(element);\r\n const href = element.getAttribute(\"href\");\r\n const isNativeInteractive = NATIVE_INTERACTIVE_TAGS.has(tag) && (tag !== \"a\" || Boolean(href));\r\n const isRoleInteractive = INTERACTIVE_ROLES.has(role);\r\n const tabIndex = parseTabIndex(element.getAttribute(\"tabindex\"));\r\n const hasTabStop = tabIndex !== null && tabIndex >= 0;\r\n const hasPointerCursor = style.cursor === \"pointer\";\r\n const isContentEditable = element.getAttribute(\"contenteditable\") === \"true\";\r\n const isDisabled =\r\n element.hasAttribute(\"disabled\") ||\r\n element.getAttribute(\"aria-disabled\") === \"true\";\r\n\r\n // ── Links ───────────────────────────────────────────────────\r\n if (\r\n tag === \"a\" &&\r\n href &&\r\n !href.startsWith(\"#\") &&\r\n !href.startsWith(\"javascript:\")\r\n ) {\r\n const absoluteHref = toAbsoluteUrl(href);\r\n const label = getElementLabel(element) || absoluteHref;\r\n const id = idCounter++;\r\n const line = `- [${id}] ${label} -> ${absoluteHref}`;\r\n\r\n if (!linkSet.has(absoluteHref)) {\r\n linkSet.add(absoluteHref);\r\n links.push(line);\r\n elementMap.set(id, element);\r\n }\r\n }\r\n\r\n // ── Interactables ───────────────────────────────────────────\r\n const hasInteractionSignals =\r\n isNativeInteractive ||\r\n isRoleInteractive ||\r\n isContentEditable ||\r\n hasTabStop ||\r\n hasPointerCursor;\r\n\r\n if (!hasInteractionSignals || isDisabled) continue;\r\n\r\n // Skip children nested inside an already-interactive parent\r\n // (e.g. <span> or <img> inside a <button> or <a>)\r\n if (hasInteractiveAncestor(element)) continue;\r\n\r\n const id = idCounter++;\r\n elementMap.set(id, element);\r\n\r\n const elType = describeElementType(element);\r\n const label = getElementLabel(element);\r\n const stateTokens = getElementState(element);\r\n const statePart = stateTokens.length > 0 ? ` (${stateTokens.join(\", \")})` : \"\";\r\n const line = `- [${id}] ${elType}: \"${label}\"${statePart}`;\r\n\r\n const score =\r\n (isNativeInteractive ? 5 : 0) +\r\n (isRoleInteractive ? 4 : 0) +\r\n (hasTabStop ? 2 : 0) +\r\n (hasPointerCursor ? 2 : 0) +\r\n (isContentEditable ? 2 : 0);\r\n\r\n candidates.push({ id, line, score, order, element });\r\n }\r\n\r\n const interactables = candidates\r\n .sort((a, b) => b.score - a.score || a.order - b.order)\r\n .slice(0, MAX_INTERACTABLES)\r\n .map((c) => c.line);\r\n\r\n return {\r\n links: links.slice(0, MAX_LINKS),\r\n interactables,\r\n elementMap,\r\n };\r\n};\r\n\r\nconst TEXT_CONTENT_SELECTOR = [\r\n \"p\", \"li\", \"h1\", \"h2\", \"h3\", \"h4\", \"h5\", \"h6\",\r\n \"blockquote\", \"figcaption\", \"dd\", \"dt\", \"td\", \"th\",\r\n \"pre\", \"label\", \"caption\",\r\n].join(\", \");\r\n\r\n/**\r\n * Check if an element has meaningful direct text content\r\n * (text nodes that aren't just whitespace).\r\n */\r\nconst hasDirectText = (element: Element): boolean => {\r\n for (const child of Array.from(element.childNodes)) {\r\n if (child.nodeType === Node.TEXT_NODE) {\r\n const trimmed = (child.textContent || \"\").trim();\r\n if (trimmed.length >= 10) return true;\r\n }\r\n }\r\n return false;\r\n};\r\n\r\nconst collectTextSnippets = (): string[] => {\r\n const root =\r\n document.querySelector(\"main, article, [role='main']\") ?? document.body;\r\n const snippets: string[] = [];\r\n const seen = new Set<string>();\r\n\r\n const addSnippet = (raw: string): boolean => {\r\n if (!raw || raw.length < 15) return false;\r\n const text = raw.length > 300 ? raw.substring(0, 300) + \"…\" : raw;\r\n if (seen.has(text)) return false;\r\n seen.add(text);\r\n snippets.push(`- ${text}`);\r\n return snippets.length >= MAX_TEXT_SNIPPETS;\r\n };\r\n\r\n // Pass 1: semantic text elements (p, li, headings, etc.)\r\n const candidates = Array.from(root.querySelectorAll(TEXT_CONTENT_SELECTOR));\r\n for (const node of candidates) {\r\n if (!isVisible(node)) continue;\r\n const raw = normalizeWhitespace(node.textContent || \"\");\r\n if (addSnippet(raw)) return snippets;\r\n }\r\n\r\n // Pass 2: generic containers (div, span, section, etc.) that hold\r\n // direct text not already captured by semantic tags above.\r\n const genericContainers = Array.from(\r\n root.querySelectorAll(\"div, span, section, article, aside, header, footer\"),\r\n );\r\n for (const node of genericContainers) {\r\n if (!isVisible(node)) continue;\r\n // Only include elements whose own direct child text nodes are meaningful,\r\n // to avoid duplicating text already captured from nested semantic tags.\r\n if (!hasDirectText(node)) continue;\r\n const raw = normalizeWhitespace(node.textContent || \"\");\r\n if (addSnippet(raw)) return snippets;\r\n }\r\n\r\n return snippets;\r\n};\r\n\r\nconst formatSection = (title: string, lines: string[]): string => {\r\n if (lines.length === 0) return `${title}:\\n- none`;\r\n return `${title}:\\n${lines.join(\"\\n\")}`;\r\n};\r\n\r\nexport const buildPageContextSummary = (\r\n url: string,\r\n title: string,\r\n lang: string,\r\n headings: string[],\r\n links: string[],\r\n interactables: string[],\r\n textSnippets: string[],\r\n): string => {\r\n const sections = [\r\n formatSection(\"Page\", [\r\n `- URL: ${url || \"unknown\"}`,\r\n `- Title: ${title || \"unknown\"}`,\r\n `- Lang: ${lang || \"unknown\"}`,\r\n ]),\r\n formatSection(\"Headings\", headings),\r\n formatSection(\"Content Snippets\", textSnippets),\r\n formatSection(\"Links\", links),\r\n formatSection(\"Interactive Elements\", interactables),\r\n ];\r\n\r\n return sections.join(\"\\n\\n\");\r\n};\r\n\r\nexport const clearPageContextCache = (): void => {\r\n pageContextCache.clear();\r\n cacheHydrated = false;\r\n if (typeof sessionStorage !== \"undefined\") {\r\n sessionStorage.removeItem(PAGE_CONTEXT_CACHE_KEY);\r\n }\r\n};\r\n\r\nexport const getCachedPageContexts = (): CachedPageContextEntry[] => {\r\n hydrateCacheFromStorage();\r\n return Array.from(pageContextCache.values()).sort(\r\n (a, b) => b.capturedAt - a.capturedAt,\r\n );\r\n};\r\n\r\nexport const invalidateCurrentPageContext = (): void => {\r\n if (typeof window === \"undefined\") return;\r\n const url = canonicalUrl(window.location.href);\r\n pageContextCache.delete(url);\r\n persistCacheToStorage();\r\n};\r\n\r\nexport const getPageContext = (forceRefresh: boolean = false): PageContext => {\r\n if (typeof window === \"undefined\" || typeof document === \"undefined\") {\r\n return {\r\n links: [],\r\n interactables: [],\r\n summary: \"\",\r\n elementMap: new Map(),\r\n };\r\n }\r\n\r\n hydrateCacheFromStorage();\r\n const url = canonicalUrl(window.location.href);\r\n\r\n // Always rebuild the live element map (it holds DOM references)\r\n const scan = collectSemanticElements();\r\n liveElementMap = scan.elementMap;\r\n\r\n if (!forceRefresh) {\r\n const cached = pageContextCache.get(url);\r\n if (cached) {\r\n console.info(`[Autic] context cache hit url=${url}`);\r\n return {\r\n links: cached.links,\r\n interactables: cached.interactables,\r\n summary: buildSummaryWithHistory(cached),\r\n elementMap: liveElementMap,\r\n };\r\n }\r\n }\r\n\r\n console.info(`[Autic] context cache miss url=${url}`);\r\n\r\n const headings = Array.from(document.querySelectorAll(\"h1, h2, h3\"))\r\n .filter((element) => isVisible(element))\r\n .map((element) =>\r\n `- ${normalizeWhitespace(element.textContent || \"\")}`,\r\n )\r\n .filter((line) => line !== \"- \")\r\n .slice(0, MAX_HEADINGS);\r\n\r\n const summary = buildPageContextSummary(\r\n url,\r\n document.title,\r\n document.documentElement.lang,\r\n headings,\r\n scan.links,\r\n scan.interactables,\r\n collectTextSnippets(),\r\n );\r\n\r\n const entry: CachedPageContextEntry = {\r\n url,\r\n summary,\r\n links: scan.links,\r\n interactables: scan.interactables,\r\n capturedAt: Date.now(),\r\n version: PAGE_CONTEXT_CACHE_VERSION,\r\n };\r\n\r\n pageContextCache.set(url, entry);\r\n pruneOldestCacheEntries();\r\n persistCacheToStorage();\r\n console.info(\r\n `[Autic] context cache stored url=${url} size=${pageContextCache.size}`,\r\n );\r\n\r\n return {\r\n links: entry.links,\r\n interactables: entry.interactables,\r\n summary: buildSummaryWithHistory(entry),\r\n elementMap: liveElementMap,\r\n };\r\n};\r\n","/**\r\n * Tunable parameters for page context collection.\r\n *\r\n * Adjust these values to control how much information the agent receives\r\n * about the current page. Lower values reduce token usage (and latency);\r\n * higher values give the LLM more detail to work with.\r\n */\r\n\r\n/** Maximum number of links to include in the context. */\r\nexport const MAX_LINKS = 120;\r\n\r\n/** Maximum number of interactable elements to include. */\r\nexport const MAX_INTERACTABLES = 2000;\r\n\r\n/** Maximum number of headings (h1-h3) to include. */\r\nexport const MAX_HEADINGS = 100;\r\n\r\n/** Maximum number of main-content text snippets. */\r\nexport const MAX_TEXT_SNIPPETS = 30;\r\n\r\n/** Maximum number of pages kept in the in-memory context cache. */\r\nexport const MAX_CACHED_PAGES = 25;\r\n\r\n/** Maximum number of DOM elements scanned per page. */\r\nexport const MAX_PAGE_SCAN_ELEMENTS = 10000;\r\n","import { getPageContext, getElementById, invalidateCurrentPageContext } from \"./context\";\r\nimport { COLORS } from \"../styles/constants\";\r\n\r\nconst AGENT_CURSOR_ID = \"auticbot-agent-cursor\";\r\nexport const CURSOR_MOVE_DURATION_MS = 900;\r\nexport const SCROLL_DURATION_MS = 900;\r\nconst CURSOR_EASING = \"cubic-bezier(0.4, 0, 0.2, 1)\";\r\nconst CURSOR_HOVER_RADIUS_PX = 14;\r\nconst CURSOR_DIAMETER_PX = 25;\r\n\r\n// ── Pending Agent Resume State (survives page reloads) ──────────────\r\n\r\nconst RESUME_STORAGE_KEY = \"bulut_agent_resume\";\r\nconst RESUME_TTL_MS = 5 * 60_000; // 5 minutes (matches chat history TTL)\r\n\r\nexport interface PendingAgentResume {\r\n sessionId: string;\r\n projectId: string;\r\n model: string;\r\n voice: string;\r\n accessibilityMode: boolean;\r\n pendingToolCalls: Array<{\r\n call_id: string;\r\n tool: string;\r\n args: Record<string, unknown>;\r\n }>;\r\n completedResults: Array<{ call_id: string; result: string }>;\r\n accumulatedDelta?: string;\r\n savedAt: number;\r\n}\r\n\r\nexport const savePendingAgentResume = (\r\n state: Omit<PendingAgentResume, \"savedAt\">,\r\n): void => {\r\n if (typeof localStorage === \"undefined\") return;\r\n try {\r\n localStorage.setItem(\r\n RESUME_STORAGE_KEY,\r\n JSON.stringify({ ...state, savedAt: Date.now() }),\r\n );\r\n } catch {\r\n // localStorage may be full or blocked\r\n }\r\n};\r\n\r\nexport const getPendingAgentResume = (): PendingAgentResume | null => {\r\n if (typeof localStorage === \"undefined\") return null;\r\n const raw = localStorage.getItem(RESUME_STORAGE_KEY);\r\n if (!raw) return null;\r\n try {\r\n const parsed = JSON.parse(raw) as PendingAgentResume;\r\n if (Date.now() - parsed.savedAt > RESUME_TTL_MS) {\r\n clearPendingAgentResume();\r\n return null;\r\n }\r\n return parsed;\r\n } catch {\r\n clearPendingAgentResume();\r\n return null;\r\n }\r\n};\r\n\r\nexport const clearPendingAgentResume = (): void => {\r\n if (typeof localStorage === \"undefined\") return;\r\n localStorage.removeItem(RESUME_STORAGE_KEY);\r\n};\r\n\r\ntype InteractAction = \"move\" | \"click\" | \"type\" | \"submit\";\r\n\r\ninterface InteractToolCall {\r\n tool: \"interact\";\r\n action: InteractAction;\r\n id?: number;\r\n selector?: string;\r\n text?: string;\r\n x?: number;\r\n y?: number;\r\n}\r\n\r\ninterface NavigateToolCall {\r\n tool: \"navigate\";\r\n url: string;\r\n}\r\n\r\ninterface GetPageContextToolCall {\r\n tool: \"getPageContext\";\r\n}\r\n\r\ninterface ScrollToolCall {\r\n tool: \"scroll\";\r\n id?: number;\r\n selector?: string;\r\n}\r\n\r\nexport type AgentToolCall =\r\n | InteractToolCall\r\n | NavigateToolCall\r\n | GetPageContextToolCall\r\n | ScrollToolCall;\r\n\r\nexport interface ParsedAgentResponse {\r\n reply: string;\r\n toolCalls: AgentToolCall[];\r\n}\r\n\r\ninterface JsonObject {\r\n [key: string]: unknown;\r\n}\r\n\r\ninterface ResolvedTarget {\r\n element?: HTMLElement;\r\n x: number;\r\n y: number;\r\n}\r\n\r\nconst isObject = (value: unknown): value is JsonObject =>\r\n typeof value === \"object\" && value !== null && !Array.isArray(value);\r\n\r\nconst asString = (value: unknown): string | undefined =>\r\n typeof value === \"string\" && value.trim() ? value.trim() : undefined;\r\n\r\nconst asNumber = (value: unknown): number | undefined =>\r\n typeof value === \"number\" && Number.isFinite(value) ? value : undefined;\r\n\r\nconst extractJsonCandidate = (raw: string): string => {\r\n const trimmed = raw.trim();\r\n const fencedMatch = trimmed.match(/```(?:json)?\\s*([\\s\\S]*?)\\s*```/i);\r\n if (fencedMatch?.[1]) {\r\n return fencedMatch[1].trim();\r\n }\r\n return trimmed;\r\n};\r\n\r\nconst extractFirstJsonObject = (input: string): string | null => {\r\n const start = input.indexOf(\"{\");\r\n if (start < 0) {\r\n return null;\r\n }\r\n\r\n let depth = 0;\r\n let inString = false;\r\n let isEscaped = false;\r\n\r\n for (let i = start; i < input.length; i += 1) {\r\n const char = input[i];\r\n\r\n if (inString) {\r\n if (isEscaped) {\r\n isEscaped = false;\r\n } else if (char === \"\\\\\") {\r\n isEscaped = true;\r\n } else if (char === '\"') {\r\n inString = false;\r\n }\r\n continue;\r\n }\r\n\r\n if (char === '\"') {\r\n inString = true;\r\n continue;\r\n }\r\n\r\n if (char === \"{\") {\r\n depth += 1;\r\n continue;\r\n }\r\n\r\n if (char === \"}\") {\r\n depth -= 1;\r\n if (depth === 0) {\r\n return input.slice(start, i + 1);\r\n }\r\n }\r\n }\r\n\r\n return null;\r\n};\r\n\r\nconst parseJsonFromRaw = (raw: string): unknown => {\r\n const candidate = extractJsonCandidate(raw);\r\n try {\r\n return JSON.parse(candidate);\r\n } catch {\r\n const objectCandidate = extractFirstJsonObject(candidate);\r\n if (!objectCandidate) {\r\n return null;\r\n }\r\n try {\r\n return JSON.parse(objectCandidate);\r\n } catch {\r\n return null;\r\n }\r\n }\r\n};\r\n\r\nconst sanitizeToolCalls = (value: unknown): AgentToolCall[] => {\r\n if (!Array.isArray(value)) {\r\n return [];\r\n }\r\n\r\n const toolCalls: AgentToolCall[] = [];\r\n\r\n for (const item of value) {\r\n if (!isObject(item)) {\r\n continue;\r\n }\r\n\r\n if (item.tool === \"interact\") {\r\n const action = asString(item.action) as InteractAction | undefined;\r\n if (!action || ![\"move\", \"click\", \"type\", \"submit\"].includes(action)) {\r\n continue;\r\n }\r\n\r\n toolCalls.push({\r\n tool: \"interact\",\r\n action,\r\n id: asNumber(item.id),\r\n selector: asString(item.selector),\r\n text: typeof item.text === \"string\" ? item.text : undefined,\r\n x: asNumber(item.x),\r\n y: asNumber(item.y),\r\n });\r\n continue;\r\n }\r\n\r\n if (item.tool === \"navigate\") {\r\n const url = asString(item.url);\r\n if (!url) {\r\n continue;\r\n }\r\n\r\n toolCalls.push({\r\n tool: \"navigate\",\r\n url,\r\n });\r\n continue;\r\n }\r\n\r\n if (item.tool === \"getPageContext\") {\r\n toolCalls.push({\r\n tool: \"getPageContext\",\r\n });\r\n continue;\r\n }\r\n\r\n if (item.tool === \"scroll\") {\r\n const id = asNumber(item.id);\r\n const selector = asString(item.selector);\r\n if (!id && !selector) {\r\n continue;\r\n }\r\n\r\n toolCalls.push({\r\n tool: \"scroll\",\r\n id,\r\n selector,\r\n });\r\n }\r\n }\r\n\r\n return toolCalls;\r\n};\r\n\r\nexport const parseAgentResponse = (raw: string): ParsedAgentResponse => {\r\n const parsed = parseJsonFromRaw(raw);\r\n if (!isObject(parsed)) {\r\n return {\r\n reply: raw.trim(),\r\n toolCalls: [],\r\n };\r\n }\r\n\r\n const reply = asString(parsed.reply) || \"\";\r\n const toolCalls = sanitizeToolCalls(parsed.tool_calls ?? parsed.toolCalls);\r\n\r\n return {\r\n reply,\r\n toolCalls,\r\n };\r\n};\r\n\r\nexport const clamp = (value: number, min: number, max: number): number =>\r\n Math.min(max, Math.max(min, value));\r\n\r\nexport const easeInOutCubic = (progress: number): number => {\r\n if (progress < 0.5) {\r\n return 4 * progress * progress * progress;\r\n }\r\n return 1 - Math.pow(-2 * progress + 2, 3) / 2;\r\n};\r\n\r\nexport const easeInOutSine = (progress: number): number =>\r\n -(Math.cos(Math.PI * progress) - 1) / 2;\r\n\r\nexport const isRectOutsideViewport = (\r\n rect: Pick<DOMRect, \"top\" | \"bottom\">,\r\n viewportHeight: number,\r\n): boolean => rect.top < 0 || rect.bottom > viewportHeight;\r\n\r\nexport const computeCenteredScrollTop = (\r\n currentScrollY: number,\r\n rectTop: number,\r\n rectHeight: number,\r\n viewportHeight: number,\r\n maxScrollTop: number,\r\n): number => {\r\n const desired =\r\n currentScrollY + rectTop - (viewportHeight / 2 - rectHeight / 2);\r\n return clamp(desired, 0, Math.max(0, maxScrollTop));\r\n};\r\n\r\nexport const animateWindowScrollTo = async (\r\n targetY: number,\r\n durationMs: number = SCROLL_DURATION_MS,\r\n): Promise<void> => {\r\n if (typeof window === \"undefined\") {\r\n return;\r\n }\r\n\r\n const startY = window.scrollY;\r\n const delta = targetY - startY;\r\n if (Math.abs(delta) < 1) {\r\n return;\r\n }\r\n\r\n await new Promise<void>((resolve) => {\r\n const raf =\r\n window.requestAnimationFrame ||\r\n ((callback: FrameRequestCallback) => window.setTimeout(() => callback(performance.now()), 16));\r\n\r\n const startTime = performance.now();\r\n\r\n const step = (now: number) => {\r\n const elapsed = now - startTime;\r\n const progress = clamp(elapsed / durationMs, 0, 1);\r\n const eased = easeInOutSine(progress);\r\n window.scrollTo(0, startY + delta * eased);\r\n\r\n if (progress < 1) {\r\n raf(step);\r\n } else {\r\n resolve();\r\n }\r\n };\r\n\r\n raf(step);\r\n });\r\n};\r\n\r\nconst setCursorPosition = (cursor: HTMLElement, x: number, y: number) => {\r\n cursor.style.left = `${x}px`;\r\n cursor.style.top = `${y}px`;\r\n};\r\n\r\nconst getCursorPosition = (cursor: HTMLElement): { x: number; y: number } => ({\r\n x: Number.parseFloat(cursor.style.left) || 0,\r\n y: Number.parseFloat(cursor.style.top) || 0,\r\n});\r\n\r\nconst setCursorVisibility = (cursor: HTMLElement, visible: boolean) => {\r\n cursor.style.opacity = visible ? \"1\" : \"0\";\r\n};\r\n\r\nconst isVisibleElement = (element: HTMLElement): boolean => {\r\n const style = window.getComputedStyle(element);\r\n return style.display !== \"none\" && style.visibility !== \"hidden\" && style.opacity !== \"0\";\r\n};\r\n\r\nconst getBulutShadowRoots = (): ShadowRoot[] => {\r\n const roots: ShadowRoot[] = [];\r\n\r\n const defaultHost = document.getElementById(\"bulut-container\");\r\n if (defaultHost?.shadowRoot) {\r\n roots.push(defaultHost.shadowRoot);\r\n }\r\n\r\n const allElements = document.querySelectorAll<HTMLElement>(\"*\");\r\n for (const el of allElements) {\r\n if (!el.shadowRoot) {\r\n continue;\r\n }\r\n if (!roots.includes(el.shadowRoot)) {\r\n roots.push(el.shadowRoot);\r\n }\r\n }\r\n\r\n return roots;\r\n};\r\n\r\nconst findAgentUiAnchorElement = (): HTMLElement | null => {\r\n const roots = getBulutShadowRoots();\r\n\r\n for (const root of roots) {\r\n const panel = root.querySelector<HTMLElement>(\".bulut-chat-window\");\r\n if (panel && isVisibleElement(panel)) {\r\n return panel;\r\n }\r\n }\r\n\r\n for (const root of roots) {\r\n const button = root.querySelector<HTMLElement>(\".bulut-fab-container\");\r\n if (button && isVisibleElement(button)) {\r\n return button;\r\n }\r\n }\r\n\r\n return null;\r\n};\r\n\r\nconst getAgentWindowTopLeft = (): { x: number; y: number } => {\r\n const anchor = findAgentUiAnchorElement();\r\n if (!anchor) {\r\n return {\r\n x: CURSOR_DIAMETER_PX / 2,\r\n y: CURSOR_DIAMETER_PX / 2,\r\n };\r\n }\r\n\r\n const rect = anchor.getBoundingClientRect();\r\n return {\r\n x: rect.left + window.scrollX + CURSOR_DIAMETER_PX / 2,\r\n y: rect.top + window.scrollY + CURSOR_DIAMETER_PX / 2,\r\n };\r\n};\r\n\r\nexport const hideAgentCursor = (): void => {\r\n if (typeof document === \"undefined\" || typeof window === \"undefined\") {\r\n return;\r\n }\r\n\r\n const cursor = document.getElementById(AGENT_CURSOR_ID);\r\n if (!(cursor instanceof HTMLElement)) {\r\n return;\r\n }\r\n\r\n setCursorVisibility(cursor, false);\r\n};\r\n\r\nlet cursorHoverTrackingInitialized = false;\r\nconst initializeCursorHoverTracking = () => {\r\n if (cursorHoverTrackingInitialized) {\r\n return;\r\n }\r\n cursorHoverTrackingInitialized = true;\r\n\r\n document.addEventListener(\"mousemove\", (event) => {\r\n const cursor = document.getElementById(AGENT_CURSOR_ID);\r\n if (!(cursor instanceof HTMLElement)) {\r\n return;\r\n }\r\n\r\n if (cursor.style.opacity !== \"1\") {\r\n return;\r\n }\r\n\r\n const { x, y } = getCursorPosition(cursor);\r\n const pointerX = event.pageX;\r\n const pointerY = event.pageY;\r\n const distance = Math.hypot(pointerX - x, pointerY - y);\r\n\r\n if (distance <= CURSOR_HOVER_RADIUS_PX) {\r\n setCursorVisibility(cursor, false);\r\n }\r\n });\r\n};\r\n\r\nconst ensureCursor = (): HTMLElement => {\r\n const existing = document.getElementById(AGENT_CURSOR_ID);\r\n if (existing) {\r\n // Keep cursor color in sync with the current theme\r\n existing.style.background = COLORS.primary;\r\n initializeCursorHoverTracking();\r\n return existing as HTMLElement;\r\n }\r\n\r\n const cursor = document.createElement(\"div\");\r\n cursor.id = AGENT_CURSOR_ID;\r\n cursor.style.position = \"absolute\";\r\n const startPosition = getAgentWindowTopLeft();\r\n cursor.style.left = `${startPosition.x}px`;\r\n cursor.style.top = `${startPosition.y}px`;\r\n cursor.style.opacity = \"0\";\r\n const width = CURSOR_DIAMETER_PX;\r\n cursor.style.width = `${width}px`;\r\n cursor.style.height = `${width}px`;\r\n cursor.style.borderRadius = \"50%\";\r\n const baseColor = COLORS.primary;\r\n cursor.style.background = baseColor;\r\n const border = 25 * 16 / 100;\r\n cursor.style.border = `${border}px solid #ffffff`;\r\n cursor.style.boxShadow = \"0px 0px 10px rgba(0, 11, 26, 0.5)\";\r\n cursor.style.boxSizing = \"border-box\";\r\n cursor.style.zIndex = \"2147483647\";\r\n cursor.style.pointerEvents = \"none\";\r\n cursor.style.transform = \"translate(-50%, -50%)\";\r\n cursor.style.transition = `left ${CURSOR_MOVE_DURATION_MS}ms ${CURSOR_EASING}, top ${CURSOR_MOVE_DURATION_MS}ms ${CURSOR_EASING}, opacity 150ms ease-out`;\r\n document.body.appendChild(cursor);\r\n initializeCursorHoverTracking();\r\n console.info(`[Autic] cursor created color=${baseColor} duration=${CURSOR_MOVE_DURATION_MS}ms`);\r\n return cursor;\r\n};\r\n\r\nconst waitForNextAnimationFrame = async (): Promise<void> => {\r\n const raf =\r\n window.requestAnimationFrame ||\r\n ((callback: FrameRequestCallback) => window.setTimeout(() => callback(performance.now()), 16));\r\n await new Promise<void>((resolve) => {\r\n raf(() => resolve());\r\n });\r\n};\r\n\r\nconst moveCursor = async (x: number, y: number) => {\r\n const cursor = ensureCursor();\r\n if (cursor.dataset.transitionReady !== \"true\") {\r\n cursor.dataset.transitionReady = \"true\";\r\n await waitForNextAnimationFrame();\r\n }\r\n\r\n const isAlreadyVisible = cursor.style.opacity === \"1\";\r\n\r\n if (!isAlreadyVisible) {\r\n // First appearance: start from agent window top-left\r\n const startPosition = getAgentWindowTopLeft();\r\n setCursorVisibility(cursor, true);\r\n setCursorPosition(cursor, startPosition.x, startPosition.y);\r\n await new Promise((resolve) => setTimeout(resolve, CURSOR_MOVE_DURATION_MS));\r\n }\r\n\r\n // Animate from current position via CSS transition\r\n setCursorVisibility(cursor, true);\r\n setCursorPosition(cursor, x, y);\r\n await new Promise((resolve) => setTimeout(resolve, CURSOR_MOVE_DURATION_MS));\r\n};\r\n\r\nconst getElementCenter = (element: HTMLElement): { x: number; y: number } => {\r\n const rect = element.getBoundingClientRect();\r\n return {\r\n x: rect.left + window.scrollX + rect.width / 2,\r\n y: rect.top + window.scrollY + rect.height / 2,\r\n };\r\n};\r\n\r\nconst CONTAINS_SELECTOR_PATTERN = /^(.*?):contains\\((['\"])(.*?)\\2\\)\\s*$/;\r\n\r\nconst findElementBySelector = (selector: string): Element | null => {\r\n try {\r\n return document.querySelector(selector);\r\n } catch (error) {\r\n const containsMatch = selector.match(CONTAINS_SELECTOR_PATTERN);\r\n if (!containsMatch) {\r\n console.warn(`AuticBot selector invalid: ${selector}`, error);\r\n return null;\r\n }\r\n\r\n const baseSelector = containsMatch[1]?.trim() || \"*\";\r\n const expectedText = containsMatch[3]?.trim() || \"\";\r\n if (!expectedText) {\r\n console.warn(`AuticBot selector contains empty text: ${selector}`);\r\n return null;\r\n }\r\n\r\n try {\r\n const candidates = document.querySelectorAll(baseSelector);\r\n for (const candidate of candidates) {\r\n if (candidate.textContent?.includes(expectedText)) {\r\n return candidate;\r\n }\r\n }\r\n return null;\r\n } catch (fallbackError) {\r\n console.warn(`AuticBot selector fallback invalid: ${selector}`, fallbackError);\r\n return null;\r\n }\r\n }\r\n};\r\n\r\nconst resolveTarget = (call: InteractToolCall): ResolvedTarget | null => {\r\n // 1. Try resolving by semantic ID from the element map\r\n if (typeof call.id === \"number\") {\r\n const mapped = getElementById(call.id);\r\n if (mapped instanceof HTMLElement) {\r\n const center = getElementCenter(mapped);\r\n return { element: mapped, x: center.x, y: center.y };\r\n }\r\n console.warn(`AuticBot interact: element id=${call.id} not found in map`);\r\n }\r\n\r\n // 2. Fallback to CSS selector\r\n if (call.selector) {\r\n const selected = findElementBySelector(call.selector);\r\n\r\n if (selected instanceof HTMLElement) {\r\n const center = getElementCenter(selected);\r\n return {\r\n element: selected,\r\n x: center.x,\r\n y: center.y,\r\n };\r\n }\r\n console.warn(`AuticBot interact: selector not found: ${call.selector}`);\r\n }\r\n\r\n if (typeof call.x === \"number\" && typeof call.y === \"number\") {\r\n return {\r\n x: call.x,\r\n y: call.y,\r\n };\r\n }\r\n\r\n console.warn(\"AuticBot interact: missing target id, selector or coordinates.\", call);\r\n return null;\r\n};\r\n\r\nconst dispatchMouseEvent = (\r\n element: HTMLElement,\r\n type: string,\r\n x: number,\r\n y: number,\r\n) => {\r\n element.dispatchEvent(\r\n new MouseEvent(type, {\r\n bubbles: true,\r\n cancelable: true,\r\n view: window,\r\n clientX: x - window.scrollX,\r\n clientY: y - window.scrollY,\r\n }),\r\n );\r\n};\r\n\r\nconst setNativeInputLikeValue = (\r\n element: HTMLInputElement | HTMLTextAreaElement,\r\n text: string,\r\n) => {\r\n const prototype =\r\n element instanceof HTMLTextAreaElement\r\n ? HTMLTextAreaElement.prototype\r\n : HTMLInputElement.prototype;\r\n const descriptor = Object.getOwnPropertyDescriptor(prototype, \"value\");\r\n if (descriptor?.set) {\r\n descriptor.set.call(element, text);\r\n } else {\r\n element.value = text;\r\n }\r\n\r\n // Keep both current and default values aligned so client re-focus\r\n // does not appear to \"erase\" tool-filled form fields.\r\n element.defaultValue = text;\r\n element.setAttribute(\"value\", text);\r\n};\r\n\r\nconst typeIntoElement = (element: HTMLElement, text: string) => {\r\n if (element instanceof HTMLInputElement || element instanceof HTMLTextAreaElement) {\r\n element.focus();\r\n setNativeInputLikeValue(element, text);\r\n element.dispatchEvent(new Event(\"input\", { bubbles: true }));\r\n element.dispatchEvent(new Event(\"change\", { bubbles: true }));\r\n return;\r\n }\r\n\r\n if (element.isContentEditable) {\r\n element.focus();\r\n element.textContent = text;\r\n element.dispatchEvent(new Event(\"input\", { bubbles: true }));\r\n return;\r\n }\r\n\r\n console.warn(\r\n \"AuticBot interact: type action requires input, textarea, or contenteditable target.\",\r\n );\r\n};\r\n\r\nconst submitElement = (element: HTMLElement) => {\r\n if (element.tagName === \"FORM\") {\r\n (element as HTMLFormElement).requestSubmit();\r\n return;\r\n }\r\n\r\n if (element.tagName === \"BUTTON\" && (element as HTMLButtonElement).form) {\r\n (element as HTMLButtonElement).form?.requestSubmit();\r\n return;\r\n }\r\n\r\n const parentForm = element.closest(\"form\");\r\n if (parentForm) {\r\n parentForm.requestSubmit();\r\n return;\r\n }\r\n\r\n console.warn(\"AuticBot interact: submit action requires a form target.\");\r\n};\r\n\r\nconst slowScrollElementIntoView = async (element: HTMLElement): Promise<void> => {\r\n await slowScrollElementIntoViewWithMode(element, false);\r\n};\r\n\r\nconst slowScrollElementIntoViewWithMode = async (\r\n element: HTMLElement,\r\n forceCenter: boolean,\r\n): Promise<void> => {\r\n const rect = element.getBoundingClientRect();\r\n const viewportHeight = window.innerHeight;\r\n\r\n if (!forceCenter && !isRectOutsideViewport(rect, viewportHeight)) {\r\n return;\r\n }\r\n\r\n const maxScrollTop = Math.max(\r\n 0,\r\n Math.max(document.body.scrollHeight, document.documentElement.scrollHeight) - viewportHeight,\r\n );\r\n const targetY = computeCenteredScrollTop(\r\n window.scrollY,\r\n rect.top,\r\n rect.height,\r\n viewportHeight,\r\n maxScrollTop,\r\n );\r\n\r\n await animateWindowScrollTo(targetY, SCROLL_DURATION_MS);\r\n};\r\n\r\nconst executeScroll = async (call: ScrollToolCall) => {\r\n const selected =\r\n (typeof call.id === \"number\" ? getElementById(call.id) : null) ??\r\n (call.selector ? findElementBySelector(call.selector) : null);\r\n\r\n if (!(selected instanceof HTMLElement)) {\r\n console.warn(`AuticBot scroll: target not found (id=${call.id}, selector=${call.selector})`);\r\n return;\r\n }\r\n\r\n await slowScrollElementIntoViewWithMode(selected, true);\r\n const center = getElementCenter(selected);\r\n await moveCursor(center.x, center.y);\r\n};\r\n\r\nconst executeInteract = async (call: InteractToolCall) => {\r\n const target = resolveTarget(call);\r\n if (!target) {\r\n return;\r\n }\r\n\r\n if (call.action === \"click\" && target.element) {\r\n await slowScrollElementIntoView(target.element);\r\n const center = getElementCenter(target.element);\r\n target.x = center.x;\r\n target.y = center.y;\r\n }\r\n\r\n await moveCursor(target.x, target.y);\r\n\r\n if (call.action === \"move\") {\r\n return;\r\n }\r\n\r\n if (!target.element) {\r\n console.warn(\"AuticBot interact: target element not available for action.\", call.action);\r\n return;\r\n }\r\n\r\n if (call.action === \"click\") {\r\n dispatchMouseEvent(target.element, \"pointerdown\", target.x, target.y);\r\n dispatchMouseEvent(target.element, \"mousedown\", target.x, target.y);\r\n dispatchMouseEvent(target.element, \"pointerup\", target.x, target.y);\r\n dispatchMouseEvent(target.element, \"mouseup\", target.x, target.y);\r\n target.element.click();\r\n // Invalidate context cache — page state likely changed after click\r\n invalidateCurrentPageContext();\r\n return;\r\n }\r\n\r\n if (call.action === \"type\") {\r\n typeIntoElement(target.element, call.text ?? \"\");\r\n // Invalidate context cache — form state changed\r\n invalidateCurrentPageContext();\r\n return;\r\n }\r\n\r\n submitElement(target.element);\r\n // Invalidate context cache — form submission may change page\r\n invalidateCurrentPageContext();\r\n};\r\n\r\nconst isSamePageNavigation = (targetUrl: string): boolean => {\r\n try {\r\n const current = new URL(window.location.href);\r\n const target = new URL(targetUrl);\r\n return current.origin === target.origin && current.pathname === target.pathname;\r\n } catch {\r\n return false;\r\n }\r\n};\r\n\r\n/**\r\n * Find the best matching link element for a target URL.\r\n * Supports exact href match, partial path/query/hash match,\r\n * and text-content match for framework <Link> components.\r\n */\r\nconst findMatchingLinkForTarget = (targetUrl: string): HTMLElement | null => {\r\n let parsedTarget: URL | null = null;\r\n try {\r\n parsedTarget = new URL(targetUrl, window.location.href);\r\n } catch {\r\n // will fall through to text-based matching\r\n }\r\n\r\n const allLinks = Array.from(\r\n document.querySelectorAll('a[href], [role=\"link\"][href], [data-href]'),\r\n ) as HTMLElement[];\r\n\r\n // 1. Exact href match\r\n for (const el of allLinks) {\r\n if (el instanceof HTMLAnchorElement && el.href === parsedTarget?.href) {\r\n return el;\r\n }\r\n }\r\n\r\n if (parsedTarget) {\r\n // 2. Match by pathname + search + hash (ignoring origin)\r\n for (const el of allLinks) {\r\n if (!(el instanceof HTMLAnchorElement)) continue;\r\n try {\r\n const elUrl = new URL(el.href, window.location.href);\r\n if (\r\n elUrl.pathname === parsedTarget.pathname &&\r\n elUrl.search === parsedTarget.search &&\r\n elUrl.hash === parsedTarget.hash\r\n ) {\r\n return el;\r\n }\r\n } catch {\r\n continue;\r\n }\r\n }\r\n\r\n // 3. Match by pathname only (query/hash may differ)\r\n for (const el of allLinks) {\r\n if (!(el instanceof HTMLAnchorElement)) continue;\r\n try {\r\n const elUrl = new URL(el.href, window.location.href);\r\n if (elUrl.pathname === parsedTarget.pathname) {\r\n return el;\r\n }\r\n } catch {\r\n continue;\r\n }\r\n }\r\n\r\n // 4. Partial href attribute match (covers relative paths, query strings)\r\n const rawUrl = targetUrl.replace(/^\\//, \"\");\r\n for (const el of allLinks) {\r\n const href = el.getAttribute(\"href\") || el.getAttribute(\"data-href\") || \"\";\r\n if (href && (href === targetUrl || href === rawUrl || href === `/${rawUrl}`)) {\r\n return el;\r\n }\r\n }\r\n }\r\n\r\n // 5. Text-content match (for framework <Link> or <button> navigations)\r\n const urlSegments = targetUrl\r\n .replace(/^https?:\\/\\/[^/]+/, \"\")\r\n .replace(/[?#].*$/, \"\")\r\n .split(\"/\")\r\n .filter(Boolean);\r\n const lastSegment = urlSegments[urlSegments.length - 1] || \"\";\r\n\r\n if (lastSegment) {\r\n // Also search query param values (e.g., ?tab=interact → \"interact\")\r\n let searchTerms = [lastSegment];\r\n if (parsedTarget) {\r\n for (const [, value] of parsedTarget.searchParams.entries()) {\r\n if (value) searchTerms.push(value);\r\n }\r\n if (parsedTarget.hash) {\r\n searchTerms.push(parsedTarget.hash.replace(/^#/, \"\"));\r\n }\r\n }\r\n searchTerms = searchTerms.map((t) => t.toLowerCase());\r\n\r\n // Look across all clickable elements\r\n const clickables = Array.from(\r\n document.querySelectorAll(\r\n 'a, button, [role=\"link\"], [role=\"tab\"], [role=\"button\"], [data-tab], [onclick]',\r\n ),\r\n ) as HTMLElement[];\r\n\r\n for (const el of clickables) {\r\n const text = (el.textContent || \"\").trim().toLowerCase();\r\n const ariaLabel = (el.getAttribute(\"aria-label\") || \"\").toLowerCase();\r\n const dataTab = (el.getAttribute(\"data-tab\") || \"\").toLowerCase();\r\n for (const term of searchTerms) {\r\n if (\r\n text === term ||\r\n ariaLabel === term ||\r\n dataTab === term ||\r\n text.includes(term)\r\n ) {\r\n return el;\r\n }\r\n }\r\n }\r\n }\r\n\r\n return null;\r\n};\r\n\r\nconst executeNavigate = async (call: NavigateToolCall): Promise<boolean> => {\r\n try {\r\n const targetUrl = call.url;\r\n let resolvedUrl: string;\r\n try {\r\n resolvedUrl = new URL(targetUrl, window.location.href).href;\r\n } catch {\r\n resolvedUrl = targetUrl;\r\n }\r\n\r\n const matchingElement = findMatchingLinkForTarget(targetUrl);\r\n\r\n if (matchingElement) {\r\n console.log(\"AuticBot navigate: clicking element\", resolvedUrl, matchingElement.tagName);\r\n await slowScrollElementIntoView(matchingElement);\r\n\r\n const center = getElementCenter(matchingElement);\r\n await moveCursor(center.x, center.y);\r\n\r\n matchingElement.dispatchEvent(new MouseEvent(\"pointerdown\", { bubbles: true, view: window }));\r\n matchingElement.dispatchEvent(new MouseEvent(\"mousedown\", { bubbles: true, view: window }));\r\n matchingElement.dispatchEvent(new MouseEvent(\"pointerup\", { bubbles: true, view: window }));\r\n matchingElement.dispatchEvent(new MouseEvent(\"mouseup\", { bubbles: true, view: window }));\r\n matchingElement.click();\r\n\r\n return !isSamePageNavigation(resolvedUrl);\r\n }\r\n\r\n // 6. Fallback: direct browser navigation (query param, hash, or full URL)\r\n console.log(\"AuticBot navigate: no matching element found, using direct navigation\", resolvedUrl);\r\n\r\n // Hash-only navigation\r\n try {\r\n const parsed = new URL(resolvedUrl);\r\n if (\r\n parsed.origin === window.location.origin &&\r\n parsed.pathname === window.location.pathname &&\r\n parsed.hash\r\n ) {\r\n window.location.hash = parsed.hash;\r\n return false;\r\n }\r\n } catch { /* continue */ }\r\n\r\n // Query-param or same-origin navigation via History API\r\n try {\r\n const parsed = new URL(resolvedUrl);\r\n if (parsed.origin === window.location.origin) {\r\n // Use pushState + popstate to trigger SPA routers\r\n const newPath = parsed.pathname + parsed.search + parsed.hash;\r\n window.history.pushState({}, \"\", newPath);\r\n window.dispatchEvent(new PopStateEvent(\"popstate\", { state: {} }));\r\n return false;\r\n }\r\n } catch { /* continue */ }\r\n\r\n // Cross-origin: full page navigation\r\n window.location.href = resolvedUrl;\r\n return true;\r\n } catch (error) {\r\n console.warn(\"AuticBot navigate: error\", call.url, error);\r\n return false;\r\n }\r\n};\r\n\r\nconst executeGetPageContext = async () => {\r\n const context = getPageContext();\r\n console.info(\r\n `[Autic] getPageContext tool executed links=${context.links.length} interactables=${context.interactables.length} summary_len=${context.summary.length}`,\r\n );\r\n};\r\n\r\nexport const executeToolCalls = async (toolCalls: AgentToolCall[]) => {\r\n for (const toolCall of toolCalls) {\r\n if (toolCall.tool === \"interact\") {\r\n await executeInteract(toolCall);\r\n continue;\r\n }\r\n\r\n if (toolCall.tool === \"scroll\") {\r\n await executeScroll(toolCall);\r\n continue;\r\n }\r\n\r\n if (toolCall.tool === \"getPageContext\") {\r\n await executeGetPageContext();\r\n continue;\r\n }\r\n\r\n if (toolCall.tool === \"navigate\") {\r\n const terminalNavigation = await executeNavigate(toolCall);\r\n if (terminalNavigation) {\r\n break;\r\n }\r\n }\r\n }\r\n};\r\n\r\n// ── Agent-mode tool execution (returns results) ─────────────────────\r\n\r\nexport type ToolCallWithId = AgentToolCall & {\r\n call_id: string;\r\n};\r\n\r\nexport interface ToolCallResult {\r\n call_id: string;\r\n result: string;\r\n}\r\n\r\n/**\r\n * Execute a single tool call and return a result string.\r\n * Used by the agent loop to feed results back into the LLM.\r\n */\r\nexport const executeSingleToolCall = async (\r\n call: ToolCallWithId,\r\n): Promise<ToolCallResult> => {\r\n const callId = call.call_id;\r\n try {\r\n if (call.tool === \"interact\") {\r\n await executeInteract(call);\r\n return {\r\n call_id: callId,\r\n result: `Etkileşim başarılı: ${call.action}`,\r\n };\r\n }\r\n\r\n if (call.tool === \"scroll\") {\r\n await executeScroll(call);\r\n return {\r\n call_id: callId,\r\n result: \"Öğeye kaydırma başarılı.\",\r\n };\r\n }\r\n\r\n if (call.tool === \"getPageContext\") {\r\n const context = getPageContext(true);\r\n return {\r\n call_id: callId,\r\n result: context.summary,\r\n };\r\n }\r\n\r\n if (call.tool === \"navigate\") {\r\n await executeNavigate(call);\r\n // Wait for navigation / SPA routing to settle\r\n await new Promise((resolve) => setTimeout(resolve, 1500));\r\n const context = getPageContext();\r\n return {\r\n call_id: callId,\r\n result: `Navigasyon tamamlandı. Şu anki sayfa: ${window.location.href}\\nSayfa bağlamı: ${context.summary}`,\r\n };\r\n }\r\n\r\n return { call_id: callId, result: \"Bilinmeyen araç.\" };\r\n } catch (error) {\r\n const msg = error instanceof Error ? error.message : String(error);\r\n console.warn(`[Autic] Tool execution error: ${call.tool}`, error);\r\n return { call_id: callId, result: `Hata: ${msg}` };\r\n }\r\n};\r\n","import {\r\n savePendingAgentResume,\r\n clearPendingAgentResume,\r\n hideAgentCursor,\r\n type PendingAgentResume,\r\n} from \"../agent/tools\";\r\n\r\nexport type ChatRole = \"system\" | \"user\" | \"assistant\";\r\n\r\nexport interface ChatMessage {\r\n role: ChatRole;\r\n content: string;\r\n}\r\n\r\ninterface ApiErrorBody {\r\n detail?: string;\r\n error?: string;\r\n message?: string;\r\n}\r\n\r\ninterface SseEventPayload {\r\n type?: string;\r\n session_id?: string;\r\n user_text?: string;\r\n assistant_text?: string;\r\n delta?: string;\r\n audio?: string;\r\n format?: string;\r\n mime_type?: string;\r\n sample_rate?: number;\r\n error?: string;\r\n}\r\n\r\ninterface TtsWsEventPayload {\r\n type?: string;\r\n request_id?: string;\r\n seq?: number;\r\n audio?: string;\r\n format?: string;\r\n mime_type?: string;\r\n sample_rate?: number;\r\n error?: string;\r\n retryable?: boolean;\r\n last_seq?: number;\r\n}\r\n\r\ninterface SttWsEventPayload {\r\n type?: string;\r\n session_id?: string;\r\n seq?: number;\r\n text?: string;\r\n error?: string;\r\n retryable?: boolean;\r\n}\r\n\r\nexport type AudioStreamState = \"rendering\" | \"playing\" | \"done\" | \"fallback\";\r\nexport const TTS_WS_RETRY_DELAYS_MS = [250, 750, 1500];\r\n\r\nconst BULUT_AUDIO_STOP_EVENT = \"bulut:audio-stop\";\r\nconst activeAudioElements = new Set<HTMLAudioElement>();\r\nlet audioPlaybackGeneration = 0;\r\n\r\nconst normalizeBaseUrl = (baseUrl: string): string => {\r\n const trimmed = baseUrl.trim().replace(/\\/+$/, \"\");\r\n if (/^https?:\\/\\//i.test(trimmed)) {\r\n return trimmed;\r\n }\r\n // Treat host-only values like \"api.bulut.lu\" as HTTPS absolute URLs.\r\n return `https://${trimmed}`;\r\n};\r\nconst toWebSocketUrl = (baseUrl: string, path: string): string => {\r\n const normalized = normalizeBaseUrl(baseUrl);\r\n const url = new URL(normalized);\r\n url.protocol = url.protocol === \"https:\" ? \"wss:\" : \"ws:\";\r\n url.pathname = `${url.pathname.replace(/\\/$/, \"\")}${path}`;\r\n url.search = \"\";\r\n url.hash = \"\";\r\n return url.toString();\r\n};\r\n\r\nconst createRequestId = (): string => {\r\n if (typeof crypto !== \"undefined\" && \"randomUUID\" in crypto) {\r\n return crypto.randomUUID();\r\n }\r\n return `tts-${Date.now()}-${Math.random().toString(16).slice(2)}`;\r\n};\r\n\r\nexport const parseTtsWsEventPayload = (\r\n value: unknown,\r\n): TtsWsEventPayload | null => {\r\n try {\r\n if (typeof value !== \"string\") {\r\n return null;\r\n }\r\n return JSON.parse(value) as TtsWsEventPayload;\r\n } catch {\r\n return null;\r\n }\r\n};\r\n\r\nexport const parseSttWsEventPayload = (\r\n value: unknown,\r\n): SttWsEventPayload | null => {\r\n try {\r\n if (typeof value !== \"string\") {\r\n return null;\r\n }\r\n return JSON.parse(value) as SttWsEventPayload;\r\n } catch {\r\n return null;\r\n }\r\n};\r\n\r\nexport const shouldAcceptAudioSeq = (\r\n incomingSeq: number,\r\n highestSeqSeen: number,\r\n): boolean => incomingSeq > highestSeqSeen;\r\n\r\nexport const shouldFallbackToSse = (error: unknown): boolean => {\r\n if (typeof error === \"object\" && error !== null && \"retryable\" in error) {\r\n return Boolean((error as { retryable?: boolean }).retryable);\r\n }\r\n return true;\r\n};\r\n\r\nconst parseErrorBody = async (response: Response): Promise<string> => {\r\n try {\r\n const data = (await response.json()) as ApiErrorBody;\r\n const detail = data.detail;\r\n if (typeof detail === \"string\") return detail;\r\n if (detail && typeof detail === \"object\") return JSON.stringify(detail);\r\n return data.error || data.message || response.statusText;\r\n } catch {\r\n return response.statusText;\r\n }\r\n};\r\n\r\nconst sleep = (ms: number): Promise<void> =>\r\n new Promise((resolve) => {\r\n setTimeout(resolve, ms);\r\n });\r\n\r\nconst registerActiveAudioElement = (audioElement: HTMLAudioElement): void => {\r\n activeAudioElements.add(audioElement);\r\n};\r\n\r\nconst unregisterActiveAudioElement = (audioElement: HTMLAudioElement): void => {\r\n activeAudioElements.delete(audioElement);\r\n};\r\n\r\nconst wasPlaybackStoppedAfter = (generationAtStart: number): boolean =>\r\n audioPlaybackGeneration !== generationAtStart;\r\n\r\nexport const getAudioPlaybackGeneration = (): number => audioPlaybackGeneration;\r\n\r\nexport const stopActiveAudioPlayback = (): void => {\r\n audioPlaybackGeneration += 1;\r\n const active = Array.from(activeAudioElements);\r\n for (const audioElement of active) {\r\n try {\r\n audioElement.dispatchEvent(new Event(BULUT_AUDIO_STOP_EVENT));\r\n audioElement.pause();\r\n audioElement.removeAttribute(\"src\");\r\n audioElement.load();\r\n } catch {\r\n // Ignore playback stop errors.\r\n }\r\n }\r\n};\r\n\r\nexport const base64ToUint8Array = (base64: string): Uint8Array<ArrayBuffer> => {\r\n // Strip potential data URI prefix if present\r\n const cleanBase64 = base64.replace(/^data:audio\\/\\w+;base64,/, \"\");\r\n const binaryString = atob(cleanBase64);\r\n const bytes = new Uint8Array(binaryString.length) as Uint8Array<ArrayBuffer>;\r\n for (let i = 0; i < binaryString.length; i += 1) {\r\n bytes[i] = binaryString.charCodeAt(i);\r\n }\r\n return bytes;\r\n};\r\n\r\nconst blobToBase64 = async (blob: Blob): Promise<string> => {\r\n const bytes = new Uint8Array(await blob.arrayBuffer());\r\n const chunkSize = 0x8000;\r\n let binary = \"\";\r\n for (let i = 0; i < bytes.length; i += chunkSize) {\r\n binary += String.fromCharCode(...bytes.subarray(i, i + chunkSize));\r\n }\r\n return btoa(binary);\r\n};\r\n\r\nconst createWavHeader = (\r\n length: number,\r\n sampleRate: number = 16000,\r\n): Uint8Array<ArrayBuffer> => {\r\n const buffer = new ArrayBuffer(44);\r\n const view = new DataView(buffer);\r\n const channels = 1;\r\n\r\n // RIFF chunk descriptor\r\n view.setUint32(0, 0x52494646, false); // \"RIFF\"\r\n view.setUint32(4, 36 + length, true); // file length - 8\r\n view.setUint32(8, 0x57415645, false); // \"WAVE\"\r\n\r\n // fmt sub-chunk\r\n view.setUint32(12, 0x666d7420, false); // \"fmt \"\r\n view.setUint32(16, 16, true); // Subchunk1Size (16 for PCM)\r\n view.setUint16(20, 1, true); // AudioFormat (1 for PCM)\r\n view.setUint16(22, channels, true); // NumChannels\r\n view.setUint32(24, sampleRate, true); // SampleRate\r\n view.setUint32(28, sampleRate * channels * 2, true); // ByteRate\r\n view.setUint16(32, channels * 2, true); // BlockAlign\r\n view.setUint16(34, 16, true); // BitsPerSample\r\n\r\n // data sub-chunk\r\n view.setUint32(36, 0x64617461, false); // \"data\"\r\n view.setUint32(40, length, true); // Subchunk2Size\r\n\r\n return new Uint8Array(buffer) as Uint8Array<ArrayBuffer>;\r\n};\r\nconst waitForPlaybackEnd = async (\r\n audioElement: HTMLAudioElement,\r\n): Promise<void> => {\r\n if (audioElement.ended) {\r\n return;\r\n }\r\n\r\n await new Promise<void>((resolve, reject) => {\r\n const watchdog = window.setInterval(() => {\r\n if (!audioElement.ended) {\r\n console.info(\"[Bulut] playback watchdog: still playing...\");\r\n }\r\n }, 30000);\r\n\r\n const onEnded = () => {\r\n cleanup();\r\n resolve();\r\n };\r\n\r\n const onError = () => {\r\n cleanup();\r\n reject(new Error(\"Ses oynatma hatası oluştu.\"));\r\n };\r\n\r\n const onForcedStop = () => {\r\n cleanup();\r\n resolve();\r\n };\r\n\r\n const cleanup = () => {\r\n window.clearInterval(watchdog);\r\n audioElement.removeEventListener(\"ended\", onEnded);\r\n audioElement.removeEventListener(\"error\", onError);\r\n audioElement.removeEventListener(BULUT_AUDIO_STOP_EVENT, onForcedStop);\r\n };\r\n\r\n audioElement.addEventListener(\"ended\", onEnded);\r\n audioElement.addEventListener(\"error\", onError);\r\n audioElement.addEventListener(BULUT_AUDIO_STOP_EVENT, onForcedStop);\r\n });\r\n};\r\n\r\n\r\n\r\nconst playBufferedAudio = async (\r\n chunks: Uint8Array<ArrayBuffer>[],\r\n mimeType: string,\r\n sampleRate: number = 16000,\r\n onAudioStateChange?: (state: AudioStreamState) => void,\r\n): Promise<void> => {\r\n const playbackGeneration = getAudioPlaybackGeneration();\r\n if (chunks.length === 0) {\r\n onAudioStateChange?.(\"done\");\r\n return;\r\n }\r\n\r\n if (wasPlaybackStoppedAfter(playbackGeneration)) {\r\n onAudioStateChange?.(\"done\");\r\n return;\r\n }\r\n\r\n // Debug info\r\n const totalBytes = chunks.reduce((acc, c) => acc + c.byteLength, 0);\r\n console.log(`[Bulut] Playing buffered audio: ${chunks.length} chunks, ${totalBytes} bytes, type=${mimeType}`);\r\n\r\n onAudioStateChange?.(\"fallback\");\r\n\r\n const blobParts: ArrayBuffer[] = chunks.map((chunk) => {\r\n const copied = new Uint8Array(chunk.byteLength) as Uint8Array<ArrayBuffer>;\r\n copied.set(chunk);\r\n return copied.buffer;\r\n });\r\n\r\n // Verify magic numbers and detect MIME type\r\n let detectedMime = mimeType;\r\n if (chunks.length > 0 && chunks[0].length >= 4) {\r\n const header = Array.from(chunks[0].slice(0, 4))\r\n .map(b => b.toString(16).padStart(2, '0').toUpperCase())\r\n .join(' ');\r\n console.log(`[Bulut] Audio header (hex): ${header}`);\r\n\r\n // Magic number detection\r\n if (header.startsWith(\"49 44 33\")) { // ID3\r\n detectedMime = \"audio/mpeg\";\r\n } else if (header.startsWith(\"FF F3\") || header.startsWith(\"FF F2\")) { // MP3 Sync\r\n detectedMime = \"audio/mpeg\";\r\n } else if (header.startsWith(\"52 49 46 46\")) { // RIFF (WAV)\r\n detectedMime = \"audio/wav\";\r\n } else if (header.startsWith(\"1A 45 DF A3\")) { // EBML (WebM)\r\n detectedMime = \"audio/webm\";\r\n }\r\n }\r\n\r\n // Ensure valid MIME type\r\n // Ensure valid MIME type or wrap raw PCM\r\n let safeMimeType = detectedMime && detectedMime.includes(\"/\") ? detectedMime : \"audio/mpeg\";\r\n let finalBlobParts: BlobPart[] = blobParts;\r\n\r\n if (mimeType === \"audio/pcm\") {\r\n // Wrap raw PCM in WAV container\r\n const totalLength = chunks.reduce((acc, c) => acc + c.byteLength, 0);\r\n const header = createWavHeader(totalLength, sampleRate);\r\n finalBlobParts = [header.buffer, ...blobParts];\r\n safeMimeType = \"audio/wav\";\r\n console.log(`[Bulut] Wrapped raw PCM in WAV (rate=${sampleRate})`);\r\n }\r\n\r\n console.log(`[Bulut] Creating blob with type: ${safeMimeType} (original: ${mimeType})`);\r\n const blob = new Blob(finalBlobParts, { type: safeMimeType });\r\n\r\n const audioElement = new Audio();\r\n const objectUrl = URL.createObjectURL(blob);\r\n\r\n try {\r\n registerActiveAudioElement(audioElement);\r\n\r\n audioElement.preload = \"auto\";\r\n audioElement.autoplay = true;\r\n // Some browsers need this\r\n audioElement.setAttribute(\"playsinline\", \"true\");\r\n audioElement.src = objectUrl;\r\n\r\n if (wasPlaybackStoppedAfter(playbackGeneration)) {\r\n onAudioStateChange?.(\"done\");\r\n return;\r\n }\r\n\r\n await audioElement.play();\r\n onAudioStateChange?.(\"playing\");\r\n await waitForPlaybackEnd(audioElement);\r\n onAudioStateChange?.(\"done\");\r\n } catch (err) {\r\n console.error(`[Bulut] Playback failed: ${err}`, { mimeType: safeMimeType, size: blob.size });\r\n onAudioStateChange?.(\"done\"); // Signal done to unblock UI even on error\r\n throw err;\r\n } finally {\r\n unregisterActiveAudioElement(audioElement);\r\n audioElement.pause();\r\n audioElement.removeAttribute(\"src\");\r\n audioElement.load();\r\n URL.revokeObjectURL(objectUrl);\r\n }\r\n};\r\n\r\nexport interface StreamController {\r\n stop: () => void;\r\n done: Promise<void>;\r\n}\r\n\r\nexport const parseSseEventPayload = (eventBlock: string): SseEventPayload | null => {\r\n const dataLines = eventBlock\r\n .split(/\\r?\\n/)\r\n .map((line) => line.trim())\r\n .filter((line) => line.startsWith(\"data:\"))\r\n .map((line) => line.slice(5).trimStart());\r\n\r\n if (dataLines.length === 0) {\r\n return null;\r\n }\r\n\r\n const dataStr = dataLines.join(\"\\n\");\r\n if (dataStr === \"[DONE]\") {\r\n return { type: \"done\" };\r\n }\r\n\r\n try {\r\n return JSON.parse(dataStr) as SseEventPayload;\r\n } catch (error) {\r\n console.warn(\"Error parsing SSE chunk:\", error);\r\n return null;\r\n }\r\n};\r\n\r\nexport const isAudioSsePayload = (\r\n payload: SseEventPayload,\r\n): payload is SseEventPayload & { audio: string } =>\r\n typeof payload.audio === \"string\" &&\r\n (payload.type === undefined || payload.type === \"audio\");\r\n\r\n// ── Separated Endpoint Helpers ──────────────────────────────────────\r\n\r\nexport async function transcribeAudio(\r\n baseUrl: string,\r\n file: File,\r\n projectId: string,\r\n sessionId: string | null,\r\n language: string,\r\n onRequestSent?: () => void,\r\n): Promise<{ text: string; session_id: string }> {\r\n const url = `${normalizeBaseUrl(baseUrl)}/chat/stt`;\r\n const formData = new FormData();\r\n formData.append(\"file\", file);\r\n formData.append(\"project_id\", projectId);\r\n if (sessionId) formData.append(\"session_id\", sessionId);\r\n formData.append(\"language\", language);\r\n\r\n const responsePromise = fetch(url, { method: \"POST\", body: formData });\r\n onRequestSent?.();\r\n const response = await responsePromise;\r\n if (!response.ok) {\r\n throw new Error(await parseErrorBody(response));\r\n }\r\n return response.json();\r\n}\r\n\r\nexport interface SttWsResult {\r\n text: string;\r\n session_id: string;\r\n}\r\n\r\nexport interface SttWsEvents {\r\n onRequestSent?: () => void;\r\n onSessionId?: (sessionId: string) => void;\r\n onPartial?: (payload: { seq: number; text: string }) => void;\r\n}\r\n\r\nexport interface SttWsController {\r\n pushChunk: (chunk: Blob) => Promise<void>;\r\n stop: () => Promise<SttWsResult>;\r\n cancel: () => void;\r\n}\r\n\r\nexport const startSttWebSocketStream = (\r\n baseUrl: string,\r\n config: {\r\n projectId: string;\r\n sessionId: string | null;\r\n language?: string;\r\n mimeType?: string;\r\n },\r\n events: SttWsEvents = {},\r\n): SttWsController => {\r\n const wsUrl = toWebSocketUrl(baseUrl, \"/chat/stt/ws\");\r\n console.info(\"[Bulut] STT WS connecting to\", wsUrl);\r\n const socket = new WebSocket(wsUrl);\r\n let seq = 0;\r\n let finalText = \"\";\r\n let finalSessionId = config.sessionId || \"\";\r\n let stopped = false;\r\n let settled = false;\r\n // All chunk sends and the final stop are chained through sendQueue\r\n // so the \"stop\" message always follows all enqueued chunks.\r\n let sendQueue: Promise<void> = Promise.resolve();\r\n\r\n let resolveStart: (() => void) | null = null;\r\n let rejectStart: ((error: Error & { retryable?: boolean }) => void) | null = null;\r\n const startPromise = new Promise<void>((resolve, reject) => {\r\n resolveStart = resolve;\r\n rejectStart = reject;\r\n });\r\n\r\n let resolveDone: ((result: SttWsResult) => void) | null = null;\r\n let rejectDone: ((error: Error & { retryable?: boolean }) => void) | null = null;\r\n const donePromise = new Promise<SttWsResult>((resolve, reject) => {\r\n resolveDone = resolve;\r\n rejectDone = reject;\r\n });\r\n\r\n const rejectAll = (error: Error & { retryable?: boolean }) => {\r\n if (settled) return;\r\n settled = true;\r\n console.warn(\"[Bulut] STT WS rejected:\", error.message);\r\n rejectStart?.(error);\r\n rejectDone?.(error);\r\n };\r\n\r\n const resolveDoneIfPossible = () => {\r\n if (settled) return;\r\n if (!finalText.trim() || !finalSessionId) return;\r\n settled = true;\r\n resolveStart?.();\r\n resolveDone?.({\r\n text: finalText.trim(),\r\n session_id: finalSessionId,\r\n });\r\n };\r\n\r\n socket.onopen = () => {\r\n console.info(\"[Bulut] STT WS connected, sending start\");\r\n events.onRequestSent?.();\r\n socket.send(\r\n JSON.stringify({\r\n type: \"start\",\r\n project_id: config.projectId,\r\n session_id: config.sessionId || undefined,\r\n language: config.language || \"tr\",\r\n mime_type: config.mimeType || \"audio/webm\",\r\n }),\r\n );\r\n };\r\n\r\n socket.onmessage = (event) => {\r\n const payload = parseSttWsEventPayload(String(event.data));\r\n if (!payload) return;\r\n\r\n if (payload.type === \"start_ack\" && typeof payload.session_id === \"string\") {\r\n console.info(\"[Bulut] STT WS start_ack received, session:\", payload.session_id);\r\n finalSessionId = payload.session_id;\r\n events.onSessionId?.(payload.session_id);\r\n resolveStart?.();\r\n return;\r\n }\r\n\r\n if (payload.type === \"partial\" && typeof payload.text === \"string\") {\r\n events.onPartial?.({\r\n seq: typeof payload.seq === \"number\" ? payload.seq : 0,\r\n text: payload.text,\r\n });\r\n return;\r\n }\r\n\r\n if (payload.type === \"final\" && typeof payload.text === \"string\") {\r\n console.info(\"[Bulut] STT WS final text received:\", payload.text.slice(0, 80));\r\n finalText = payload.text;\r\n if (typeof payload.session_id === \"string\") {\r\n finalSessionId = payload.session_id;\r\n events.onSessionId?.(payload.session_id);\r\n }\r\n return;\r\n }\r\n\r\n if (payload.type === \"done\") {\r\n console.info(\"[Bulut] STT WS done\");\r\n resolveDoneIfPossible();\r\n socket.close();\r\n return;\r\n }\r\n\r\n if (payload.type === \"error\") {\r\n console.error(\"[Bulut] STT WS server error:\", payload.error);\r\n const err = buildError(payload.error || \"stt_ws_error\", payload.retryable !== false);\r\n rejectAll(err);\r\n socket.close();\r\n }\r\n };\r\n\r\n socket.onerror = (ev) => {\r\n console.error(\"[Bulut] STT WS transport error\", ev);\r\n rejectAll(buildError(\"stt_ws_transport_error\", true));\r\n };\r\n\r\n socket.onclose = (ev) => {\r\n console.info(\"[Bulut] STT WS closed code=%d reason=%s\", ev.code, ev.reason);\r\n if (settled) return;\r\n if (finalText && finalSessionId) {\r\n resolveDoneIfPossible();\r\n return;\r\n }\r\n rejectAll(buildError(\"stt_ws_closed_before_done\", true));\r\n };\r\n\r\n return {\r\n pushChunk: (chunk: Blob): Promise<void> => {\r\n if (stopped || chunk.size === 0) return Promise.resolve();\r\n // Chain the entire operation (wait for connection, base64-encode,\r\n // send) into sendQueue so that a later stop() is guaranteed to\r\n // follow all previously-enqueued chunks.\r\n sendQueue = sendQueue.then(async () => {\r\n if (stopped) return;\r\n await startPromise;\r\n if (stopped) return;\r\n const audio = await blobToBase64(chunk);\r\n seq += 1;\r\n if (stopped || socket.readyState !== WebSocket.OPEN) return;\r\n console.debug(\"[Bulut] STT WS sending chunk seq=%d size=%d\", seq, chunk.size);\r\n socket.send(JSON.stringify({ type: \"chunk\", seq, audio }));\r\n });\r\n return sendQueue;\r\n },\r\n stop: (): Promise<SttWsResult> => {\r\n console.info(\"[Bulut] STT WS stop requested, draining %d pending chunks\", seq);\r\n // Chain after all pending pushChunk operations so the server\r\n // always receives every chunk before the stop message.\r\n sendQueue = sendQueue.then(async () => {\r\n await startPromise;\r\n if (stopped) return;\r\n if (socket.readyState === WebSocket.OPEN) {\r\n console.info(\"[Bulut] STT WS sending stop after seq=%d\", seq);\r\n socket.send(JSON.stringify({ type: \"stop\" }));\r\n }\r\n });\r\n return donePromise;\r\n },\r\n cancel: () => {\r\n stopped = true;\r\n try {\r\n socket.close();\r\n } catch {\r\n // no-op\r\n }\r\n },\r\n };\r\n};\r\n\r\ninterface TtsCollectResult {\r\n chunks: Uint8Array<ArrayBuffer>[];\r\n mimeType: string;\r\n sampleRate: number;\r\n}\r\n\r\nconst buildError = (message: string, retryable: boolean = true): Error & { retryable: boolean } => {\r\n const error = new Error(message) as Error & { retryable: boolean };\r\n error.retryable = retryable;\r\n return error;\r\n};\r\n\r\nconst collectTtsViaSse = async (\r\n baseUrl: string,\r\n assistantText: string,\r\n voice: string,\r\n accessibilityMode: boolean,\r\n isStopped: () => boolean,\r\n setReader: (reader: ReadableStreamDefaultReader<Uint8Array> | undefined) => void,\r\n): Promise<TtsCollectResult> => {\r\n const ttsFormData = new FormData();\r\n ttsFormData.append(\"text\", assistantText);\r\n ttsFormData.append(\"voice\", voice);\r\n ttsFormData.append(\"accessibility_mode\", String(accessibilityMode));\r\n\r\n const ttsResponse = await fetch(`${normalizeBaseUrl(baseUrl)}/chat/tts`, {\r\n method: \"POST\",\r\n body: ttsFormData,\r\n });\r\n\r\n if (!ttsResponse.ok) {\r\n throw buildError(await parseErrorBody(ttsResponse), false);\r\n }\r\n\r\n const reader = ttsResponse.body?.getReader();\r\n if (!reader) {\r\n throw buildError(\"TTS response body is not readable\", false);\r\n }\r\n\r\n setReader(reader);\r\n\r\n const chunks: Uint8Array<ArrayBuffer>[] = [];\r\n let mimeType = \"audio/mpeg\";\r\n let sampleRate = 16000;\r\n const decoder = new TextDecoder();\r\n let buffer = \"\";\r\n\r\n while (true) {\r\n if (isStopped()) {\r\n break;\r\n }\r\n\r\n const { done, value } = await reader.read();\r\n if (done) {\r\n break;\r\n }\r\n\r\n buffer += decoder.decode(value, { stream: true });\r\n const blocks = buffer.split(/\\r?\\n\\r?\\n/);\r\n buffer = blocks.pop() || \"\";\r\n\r\n for (const block of blocks) {\r\n const payload = parseSseEventPayload(block);\r\n if (!payload) {\r\n continue;\r\n }\r\n\r\n if (isAudioSsePayload(payload)) {\r\n const format = payload.format || \"mp3\";\r\n mimeType = payload.mime_type || (format === \"webm\" ? \"audio/webm\" : \"audio/mpeg\");\r\n chunks.push(base64ToUint8Array(payload.audio));\r\n if (payload.sample_rate) {\r\n sampleRate = payload.sample_rate;\r\n }\r\n }\r\n }\r\n }\r\n\r\n reader.releaseLock();\r\n setReader(undefined);\r\n\r\n return { chunks, mimeType, sampleRate };\r\n};\r\n\r\nconst collectTtsViaWebSocket = async (\r\n baseUrl: string,\r\n assistantText: string,\r\n voice: string,\r\n accessibilityMode: boolean,\r\n isStopped: () => boolean,\r\n setSocket: (socket: WebSocket | null) => void,\r\n onFirstBatchReady?: (batch: TtsCollectResult) => void,\r\n): Promise<TtsCollectResult> => {\r\n const wsUrl = toWebSocketUrl(baseUrl, \"/chat/tts/ws\");\r\n const requestId = createRequestId();\r\n const chunks: Uint8Array<ArrayBuffer>[] = [];\r\n let mimeType = \"audio/mpeg\";\r\n let sampleRate = 16000;\r\n let highestSeqSeen = 0;\r\n\r\n // Streaming: fire first batch of chunks to the caller early\r\n let firstBatchFired = false;\r\n let firstBatchTimer: ReturnType<typeof setTimeout> | null = null;\r\n const FIRST_BATCH_DELAY_MS = 250;\r\n\r\n const fireFirstBatch = () => {\r\n if (firstBatchFired || !onFirstBatchReady || chunks.length === 0) return;\r\n firstBatchFired = true;\r\n if (firstBatchTimer) { clearTimeout(firstBatchTimer); firstBatchTimer = null; }\r\n const batch = chunks.splice(0);\r\n onFirstBatchReady({ chunks: batch, mimeType, sampleRate });\r\n };\r\n\r\n const connectOnce = (): Promise<void> =>\r\n new Promise((resolve, reject) => {\r\n if (isStopped()) {\r\n reject(buildError(\"stream_stopped\", false));\r\n return;\r\n }\r\n\r\n let done = false;\r\n let finalError: (Error & { retryable?: boolean }) | null = null;\r\n const socket = new WebSocket(wsUrl);\r\n setSocket(socket);\r\n\r\n const finalize = (\r\n mode: \"resolve\" | \"reject\",\r\n error?: Error & { retryable?: boolean },\r\n ) => {\r\n socket.onopen = null;\r\n socket.onmessage = null;\r\n socket.onerror = null;\r\n socket.onclose = null;\r\n setSocket(null);\r\n if (mode === \"resolve\") {\r\n resolve();\r\n return;\r\n }\r\n reject(error || buildError(\"tts_ws_closed\", true));\r\n };\r\n\r\n socket.onopen = () => {\r\n console.info(\r\n `[Bulut] TTS WS connected request_id=${requestId} resume_seq=${highestSeqSeen}`,\r\n );\r\n socket.send(\r\n JSON.stringify({\r\n type: \"start\",\r\n request_id: requestId,\r\n text: assistantText,\r\n voice,\r\n accessibility_mode: accessibilityMode,\r\n last_seq: highestSeqSeen,\r\n }),\r\n );\r\n };\r\n\r\n socket.onmessage = (event) => {\r\n const payload = parseTtsWsEventPayload(String(event.data));\r\n if (!payload) {\r\n console.warn(\"[Bulut] TTS WS invalid JSON payload\");\r\n return;\r\n }\r\n\r\n if (payload.type === \"audio\" && typeof payload.audio === \"string\") {\r\n const seq = typeof payload.seq === \"number\" ? payload.seq : 0;\r\n if (shouldAcceptAudioSeq(seq, highestSeqSeen)) {\r\n chunks.push(base64ToUint8Array(payload.audio));\r\n highestSeqSeen = seq;\r\n if (payload.mime_type) {\r\n mimeType = payload.mime_type;\r\n }\r\n if (typeof payload.sample_rate === \"number\") {\r\n sampleRate = payload.sample_rate;\r\n }\r\n\r\n // Schedule first-batch flush for streaming playback\r\n if (onFirstBatchReady && !firstBatchFired) {\r\n if (firstBatchTimer) clearTimeout(firstBatchTimer);\r\n firstBatchTimer = setTimeout(fireFirstBatch, FIRST_BATCH_DELAY_MS);\r\n }\r\n } else {\r\n console.info(\r\n `[Bulut] TTS WS duplicate chunk ignored request_id=${requestId} seq=${seq} seen=${highestSeqSeen}`,\r\n );\r\n }\r\n\r\n if (socket.readyState === WebSocket.OPEN) {\r\n socket.send(\r\n JSON.stringify({\r\n type: \"ack\",\r\n request_id: requestId,\r\n last_seq: highestSeqSeen,\r\n }),\r\n );\r\n }\r\n return;\r\n }\r\n\r\n if (payload.type === \"done\") {\r\n // Flush first batch if not yet fired (short text = all chunks in one batch)\r\n if (onFirstBatchReady && !firstBatchFired) {\r\n fireFirstBatch();\r\n }\r\n\r\n const streamLastSeq =\r\n typeof payload.last_seq === \"number\" ? payload.last_seq : highestSeqSeen;\r\n if (streamLastSeq > highestSeqSeen) {\r\n finalError = buildError(\"tts_ws_sequence_gap\", true);\r\n done = false;\r\n socket.close();\r\n return;\r\n }\r\n done = true;\r\n socket.close();\r\n return;\r\n }\r\n\r\n if (payload.type === \"error\") {\r\n finalError = buildError(payload.error || \"tts_ws_error\", payload.retryable !== false);\r\n done = false;\r\n socket.close();\r\n }\r\n };\r\n\r\n socket.onerror = () => {\r\n if (!finalError) {\r\n finalError = buildError(\"tts_ws_transport_error\", true);\r\n }\r\n };\r\n\r\n socket.onclose = () => {\r\n if (isStopped()) {\r\n finalize(\"reject\", buildError(\"stream_stopped\", false));\r\n return;\r\n }\r\n if (done) {\r\n finalize(\"resolve\");\r\n return;\r\n }\r\n finalize(\"reject\", finalError || buildError(\"tts_ws_closed_before_done\", true));\r\n };\r\n });\r\n\r\n for (let attempt = 0; attempt <= TTS_WS_RETRY_DELAYS_MS.length; attempt += 1) {\r\n if (attempt > 0) {\r\n const delay = TTS_WS_RETRY_DELAYS_MS[attempt - 1];\r\n console.warn(\r\n `[Bulut] TTS WS retry attempt=${attempt} delay_ms=${delay} last_seq=${highestSeqSeen}`,\r\n );\r\n await sleep(delay);\r\n }\r\n\r\n try {\r\n await connectOnce();\r\n return { chunks, mimeType, sampleRate };\r\n } catch (error) {\r\n const retryable =\r\n shouldFallbackToSse(error);\r\n const message = error instanceof Error ? error.message : String(error);\r\n console.warn(\r\n `[Bulut] TTS WS attempt failed attempt=${attempt} retryable=${retryable} error=${message}`,\r\n );\r\n if (!retryable || attempt === TTS_WS_RETRY_DELAYS_MS.length) {\r\n throw error;\r\n }\r\n }\r\n }\r\n\r\n throw buildError(\"tts_ws_exhausted\", true);\r\n};\r\n\r\n/**\r\n * Collect TTS audio via WebSocket (with SSE fallback) and play it.\r\n *\r\n * Uses streaming playback: the first batch of audio chunks starts\r\n * playing immediately while remaining chunks are still being received.\r\n * This dramatically reduces perceived latency, especially for longer\r\n * text where the backend pipelines synthesis sentence-by-sentence.\r\n */\r\nconst collectAndPlayTtsStreamed = async (\r\n baseUrl: string,\r\n text: string,\r\n voice: string,\r\n accessibilityMode: boolean,\r\n isStopped: () => boolean,\r\n setSocket: (socket: WebSocket | null) => void,\r\n setReader: (reader: ReadableStreamDefaultReader<Uint8Array> | undefined) => void,\r\n onAudioStateChange?: (state: AudioStreamState) => void,\r\n): Promise<void> => {\r\n const trimmed = text.trim();\r\n if (!trimmed) { onAudioStateChange?.(\"done\"); return; }\r\n\r\n const playbackGen = getAudioPlaybackGeneration();\r\n if (wasPlaybackStoppedAfter(playbackGen)) {\r\n onAudioStateChange?.(\"done\");\r\n return;\r\n }\r\n\r\n onAudioStateChange?.(\"rendering\");\r\n\r\n let firstBatchPlayPromise: Promise<void> | null = null;\r\n let ttsResult: TtsCollectResult;\r\n\r\n try {\r\n ttsResult = await collectTtsViaWebSocket(\r\n baseUrl, trimmed, voice, accessibilityMode,\r\n isStopped, setSocket,\r\n // Streaming: start playing the first batch immediately\r\n (firstBatch) => {\r\n if (wasPlaybackStoppedAfter(playbackGen) || isStopped()) return;\r\n if (firstBatch.chunks.length === 0) return;\r\n firstBatchPlayPromise = playBufferedAudio(\r\n firstBatch.chunks, firstBatch.mimeType, firstBatch.sampleRate,\r\n (state) => {\r\n // Forward playing state, but suppress \"done\" since more may follow\r\n if (state !== \"done\") onAudioStateChange?.(state);\r\n },\r\n ).catch(err => console.warn(\"[Bulut] first batch playback error\", err));\r\n },\r\n );\r\n } catch (wsErr) {\r\n // If first batch was already playing, accept partial audio\r\n if (firstBatchPlayPromise) {\r\n await firstBatchPlayPromise;\r\n onAudioStateChange?.(\"done\");\r\n return;\r\n }\r\n // Otherwise fall back to SSE (non-streaming, collect-then-play)\r\n if (isStopped()) { onAudioStateChange?.(\"done\"); return; }\r\n console.warn(\r\n `[Bulut] TTS WS failed, falling back to SSE: ${wsErr instanceof Error ? wsErr.message : String(wsErr)}`,\r\n );\r\n ttsResult = await collectTtsViaSse(\r\n baseUrl, trimmed, voice, accessibilityMode,\r\n isStopped, setReader,\r\n );\r\n }\r\n\r\n if (isStopped() || wasPlaybackStoppedAfter(playbackGen)) {\r\n onAudioStateChange?.(\"done\");\r\n return;\r\n }\r\n\r\n // Wait for first batch to finish playing\r\n if (firstBatchPlayPromise) {\r\n await firstBatchPlayPromise;\r\n }\r\n\r\n // Play remaining chunks (if any)\r\n if (ttsResult.chunks.length > 0) {\r\n await playBufferedAudio(\r\n ttsResult.chunks, ttsResult.mimeType, ttsResult.sampleRate,\r\n onAudioStateChange,\r\n );\r\n } else {\r\n onAudioStateChange?.(\"done\");\r\n }\r\n};\r\n\r\n// ── Agent-mode Types ────────────────────────────────────────────────\r\n\r\nexport interface AgentToolCallInfo {\r\n call_id: string;\r\n tool: string;\r\n args: Record<string, unknown>;\r\n}\r\n\r\nexport interface AgentVoiceChatEvents {\r\n onSttRequestSent?: () => void;\r\n onTranscription?: (data: {\r\n session_id: string;\r\n user_text: string;\r\n }) => void;\r\n onAssistantDelta?: (delta: string) => void;\r\n onAssistantDone?: (assistantText: string, expectsReply?: boolean) => void;\r\n onAudioStateChange?: (state: AudioStreamState) => void;\r\n onError?: (error: string) => void;\r\n /** Called when the agent requests tool execution on the frontend. */\r\n onToolCalls?: (calls: AgentToolCallInfo[]) => void;\r\n /** Called after each tool has been executed with the result. */\r\n onToolResult?: (callId: string, toolName: string, result: string) => void;\r\n /** Called at the start of each agent iteration. */\r\n onIteration?: (iteration: number, maxIterations: number) => void;\r\n /** Called when the backend confirms / creates a session ID. */\r\n onSessionId?: (sessionId: string) => void;\r\n /**\r\n * Called when the agent emits a reply text followed by tool calls.\r\n * This text is spoken aloud before the tools run so the user hears\r\n * every piece of the conversation, not just the final reply.\r\n */\r\n onIntermediateReply?: (text: string) => void;\r\n}\r\n\r\n/**\r\n * Standalone TTS helper: synthesize + play a text snippet.\r\n * Uses WebSocket TTS with SSE fallback, same as the main stream functions.\r\n */\r\nexport const speakText = async (\r\n baseUrl: string,\r\n text: string,\r\n voice: string,\r\n accessibilityMode: boolean,\r\n onAudioStateChange?: (state: AudioStreamState) => void,\r\n): Promise<void> => {\r\n const trimmed = text.trim();\r\n if (!trimmed) return;\r\n console.info(`[Bulut] speakText start (${trimmed.length} chars)`);\r\n await collectAndPlayTtsStreamed(\r\n baseUrl, trimmed, voice, accessibilityMode,\r\n () => false,\r\n () => {},\r\n () => {},\r\n onAudioStateChange,\r\n );\r\n};\r\n\r\n// ── Agent Voice Chat Stream (STT → Agent WS → TTS) ─────────────────\r\n\r\nexport const agentVoiceChatStream = (\r\n baseUrl: string,\r\n audioFile: File,\r\n projectId: string,\r\n sessionId: string | null,\r\n config: {\r\n model: string;\r\n voice: string;\r\n pageContext?: string;\r\n accessibilityMode?: boolean;\r\n },\r\n events: AgentVoiceChatEvents,\r\n executeTool: (call: AgentToolCallInfo) => Promise<{ call_id: string; result: string }>,\r\n): StreamController => {\r\n let isStopped = false;\r\n let activeSocket: WebSocket | null = null;\r\n let activeReader: ReadableStreamDefaultReader<Uint8Array> | undefined;\r\n let errorEmitted = false;\r\n\r\n const donePromise = new Promise<void>(async (resolve, reject) => {\r\n try {\r\n // ── 1. STT ────────────────────────────────────────────────\r\n if (isStopped) return resolve();\r\n const sttResult = await transcribeAudio(\r\n baseUrl,\r\n audioFile,\r\n projectId,\r\n sessionId,\r\n \"tr\",\r\n events.onSttRequestSent,\r\n );\r\n\r\n const currentSessionId = sttResult.session_id;\r\n let effectiveSessionId = currentSessionId;\r\n const userText = sttResult.text;\r\n\r\n events.onTranscription?.({\r\n session_id: currentSessionId,\r\n user_text: userText,\r\n });\r\n\r\n if (isStopped) return resolve();\r\n\r\n // ── 2. Agent loop via WebSocket ───────────────────────────\r\n const assistantText = await new Promise<string>((agentResolve, agentReject) => {\r\n if (isStopped) { agentResolve(\"\"); return; }\r\n\r\n const wsUrl = toWebSocketUrl(baseUrl, \"/chat/agent/ws\");\r\n const socket = new WebSocket(wsUrl);\r\n activeSocket = socket;\r\n\r\n let finalReply = \"\";\r\n let resolved = false;\r\n let accumulatedDelta = \"\";\r\n let allIntermediateText = \"\";\r\n\r\n const finish = (reply: string) => {\r\n if (resolved) return;\r\n resolved = true;\r\n agentResolve(reply);\r\n };\r\n\r\n const fail = (error: Error) => {\r\n if (resolved) return;\r\n resolved = true;\r\n agentReject(error);\r\n };\r\n\r\n socket.onopen = () => {\r\n console.info(\"[Bulut] Agent WS connected\");\r\n socket.send(JSON.stringify({\r\n type: \"start\",\r\n project_id: projectId,\r\n session_id: currentSessionId,\r\n user_text: userText,\r\n model: config.model,\r\n page_context: config.pageContext,\r\n accessibility_mode: config.accessibilityMode,\r\n }));\r\n };\r\n\r\n socket.onmessage = async (event) => {\r\n let data: Record<string, unknown>;\r\n try {\r\n data = JSON.parse(String(event.data));\r\n } catch {\r\n console.warn(\"[Bulut] Agent WS invalid JSON\");\r\n return;\r\n }\r\n\r\n const msgType = data.type as string;\r\n\r\n if (msgType === \"session\" && typeof data.session_id === \"string\") {\r\n effectiveSessionId = data.session_id as string;\r\n events.onSessionId?.(effectiveSessionId);\r\n return;\r\n }\r\n\r\n if (msgType === \"iteration\") {\r\n events.onIteration?.(\r\n data.iteration as number,\r\n data.max_iterations as number,\r\n );\r\n return;\r\n }\r\n\r\n if (msgType === \"reply_delta\" && typeof data.delta === \"string\") {\r\n accumulatedDelta += data.delta;\r\n events.onAssistantDelta?.(data.delta);\r\n return;\r\n }\r\n\r\n if (msgType === \"tool_calls\" && Array.isArray(data.calls)) {\r\n const calls = data.calls as AgentToolCallInfo[];\r\n\r\n // Speak accumulated text before running tools\r\n if (accumulatedDelta.trim()) {\r\n events.onIntermediateReply?.(accumulatedDelta.trim());\r\n allIntermediateText += accumulatedDelta;\r\n }\r\n accumulatedDelta = \"\";\r\n\r\n events.onToolCalls?.(calls);\r\n\r\n const results: { call_id: string; result: string }[] = [];\r\n for (const call of calls) {\r\n // Save resume state before navigate in case of full-page reload\r\n const isNavigate = call.tool === \"navigate\";\r\n if (isNavigate) {\r\n savePendingAgentResume({\r\n sessionId: effectiveSessionId,\r\n projectId,\r\n model: config.model,\r\n voice: config.voice,\r\n accessibilityMode: Boolean(config.accessibilityMode),\r\n pendingToolCalls: calls.map((c) => ({\r\n call_id: c.call_id,\r\n tool: c.tool,\r\n args: c.args,\r\n })),\r\n completedResults: [...results],\r\n accumulatedDelta: allIntermediateText || undefined,\r\n });\r\n }\r\n\r\n const result = await executeTool(call);\r\n\r\n // If we reach here, no full-page reload happened\r\n if (isNavigate) {\r\n clearPendingAgentResume();\r\n }\r\n\r\n events.onToolResult?.(call.call_id, call.tool, result.result);\r\n results.push(result);\r\n }\r\n\r\n if (socket.readyState === WebSocket.OPEN) {\r\n socket.send(JSON.stringify({\r\n type: \"tool_results\",\r\n results,\r\n }));\r\n }\r\n return;\r\n }\r\n\r\n if (msgType === \"agent_done\") {\r\n finalReply = (data.final_reply as string) || \"\";\r\n const replyExpectsReply = data.expects_reply !== false;\r\n events.onAssistantDone?.(finalReply, replyExpectsReply);\r\n if (typeof data.session_id === \"string\") {\r\n events.onSessionId?.(data.session_id as string);\r\n }\r\n finish(finalReply);\r\n return;\r\n }\r\n\r\n if (msgType === \"error\") {\r\n const errMsg = (data.error as string) || \"Agent error\";\r\n errorEmitted = true;\r\n events.onError?.(errMsg);\r\n fail(new Error(errMsg));\r\n return;\r\n }\r\n };\r\n\r\n socket.onerror = () => {\r\n console.error(\"[Bulut] Agent WS error\");\r\n errorEmitted = true;\r\n events.onError?.(\"Agent WebSocket connection error\");\r\n fail(new Error(\"Agent WebSocket connection error\"));\r\n };\r\n\r\n socket.onclose = () => {\r\n console.info(\"[Bulut] Agent WS closed\");\r\n finish(finalReply);\r\n };\r\n });\r\n\r\n activeSocket = null;\r\n\r\n // ── 3. TTS ────────────────────────────────────────────────\r\n if (isStopped || !assistantText) {\r\n if (!isStopped) {\r\n hideAgentCursor();\r\n }\r\n return resolve();\r\n }\r\n\r\n console.info(\r\n `[Bulut] TTS start mode=agent voice=${config.voice}`,\r\n );\r\n\r\n hideAgentCursor();\r\n await collectAndPlayTtsStreamed(\r\n baseUrl, assistantText, config.voice, Boolean(config.accessibilityMode),\r\n () => isStopped,\r\n (socket) => { activeSocket = socket; },\r\n (reader) => { activeReader = reader; },\r\n events.onAudioStateChange,\r\n );\r\n\r\n resolve();\r\n } catch (err) {\r\n // Only emit onError if it hasn't been emitted already by the WS handler\r\n if (!errorEmitted) {\r\n const msg = err instanceof Error ? err.message : String(err);\r\n events.onError?.(msg);\r\n }\r\n reject(err);\r\n } finally {\r\n activeReader?.cancel().catch(() => { });\r\n if (activeSocket && activeSocket.readyState <= WebSocket.OPEN) {\r\n activeSocket.close();\r\n }\r\n activeSocket = null;\r\n }\r\n });\r\n\r\n return {\r\n stop: () => {\r\n isStopped = true;\r\n stopActiveAudioPlayback();\r\n if (activeReader) {\r\n activeReader.cancel().catch(() => { });\r\n }\r\n if (activeSocket && activeSocket.readyState <= WebSocket.OPEN) {\r\n activeSocket.close();\r\n }\r\n },\r\n done: donePromise,\r\n };\r\n};\r\n\r\n// ── Agent Text Chat Stream (no STT, Agent WS → TTS) ────────────────\r\n\r\nexport const agentTextChatStream = (\r\n baseUrl: string,\r\n userText: string,\r\n projectId: string,\r\n sessionId: string | null,\r\n config: {\r\n model: string;\r\n voice: string;\r\n pageContext?: string;\r\n accessibilityMode?: boolean;\r\n },\r\n events: AgentVoiceChatEvents,\r\n executeTool: (call: AgentToolCallInfo) => Promise<{ call_id: string; result: string }>,\r\n): StreamController => {\r\n let isStopped = false;\r\n let activeSocket: WebSocket | null = null;\r\n let activeReader: ReadableStreamDefaultReader<Uint8Array> | undefined;\r\n let errorEmitted = false;\r\n\r\n const donePromise = new Promise<void>(async (resolve, reject) => {\r\n try {\r\n if (isStopped) return resolve();\r\n\r\n // ── 1. Agent loop via WebSocket ───────────────────────────\r\n const assistantText = await new Promise<string>((agentResolve, agentReject) => {\r\n if (isStopped) { agentResolve(\"\"); return; }\r\n\r\n const wsUrl = toWebSocketUrl(baseUrl, \"/chat/agent/ws\");\r\n const socket = new WebSocket(wsUrl);\r\n activeSocket = socket;\r\n\r\n let finalReply = \"\";\r\n let resolved = false;\r\n let effectiveSessionId = sessionId || \"\";\r\n let accumulatedDelta = \"\";\r\n let allIntermediateText = \"\";\r\n\r\n const finish = (reply: string) => {\r\n if (resolved) return;\r\n resolved = true;\r\n agentResolve(reply);\r\n };\r\n\r\n const fail = (error: Error) => {\r\n if (resolved) return;\r\n resolved = true;\r\n agentReject(error);\r\n };\r\n\r\n socket.onopen = () => {\r\n socket.send(JSON.stringify({\r\n type: \"start\",\r\n project_id: projectId,\r\n session_id: sessionId,\r\n user_text: userText,\r\n model: config.model,\r\n page_context: config.pageContext,\r\n accessibility_mode: config.accessibilityMode,\r\n }));\r\n };\r\n\r\n socket.onmessage = async (event) => {\r\n let data: Record<string, unknown>;\r\n try {\r\n data = JSON.parse(String(event.data));\r\n } catch { return; }\r\n\r\n const msgType = data.type as string;\r\n\r\n if (msgType === \"session\" && typeof data.session_id === \"string\") {\r\n effectiveSessionId = data.session_id as string;\r\n events.onSessionId?.(effectiveSessionId);\r\n return;\r\n }\r\n\r\n if (msgType === \"iteration\") {\r\n events.onIteration?.(\r\n data.iteration as number,\r\n data.max_iterations as number,\r\n );\r\n return;\r\n }\r\n\r\n if (msgType === \"reply_delta\" && typeof data.delta === \"string\") {\r\n accumulatedDelta += data.delta;\r\n events.onAssistantDelta?.(data.delta);\r\n return;\r\n }\r\n\r\n if (msgType === \"tool_calls\" && Array.isArray(data.calls)) {\r\n const calls = data.calls as AgentToolCallInfo[];\r\n\r\n // Speak accumulated text before running tools\r\n if (accumulatedDelta.trim()) {\r\n events.onIntermediateReply?.(accumulatedDelta.trim());\r\n allIntermediateText += accumulatedDelta;\r\n }\r\n accumulatedDelta = \"\";\r\n\r\n events.onToolCalls?.(calls);\r\n\r\n const results: { call_id: string; result: string }[] = [];\r\n for (const call of calls) {\r\n const isNavigate = call.tool === \"navigate\";\r\n if (isNavigate) {\r\n savePendingAgentResume({\r\n sessionId: effectiveSessionId,\r\n projectId,\r\n model: config.model,\r\n voice: config.voice,\r\n accessibilityMode: Boolean(config.accessibilityMode),\r\n pendingToolCalls: calls.map((c) => ({\r\n call_id: c.call_id,\r\n tool: c.tool,\r\n args: c.args,\r\n })),\r\n completedResults: [...results],\r\n accumulatedDelta: allIntermediateText || undefined,\r\n });\r\n }\r\n\r\n const result = await executeTool(call);\r\n\r\n if (isNavigate) {\r\n clearPendingAgentResume();\r\n }\r\n\r\n events.onToolResult?.(call.call_id, call.tool, result.result);\r\n results.push(result);\r\n }\r\n\r\n if (socket.readyState === WebSocket.OPEN) {\r\n socket.send(JSON.stringify({\r\n type: \"tool_results\",\r\n results,\r\n }));\r\n }\r\n return;\r\n }\r\n\r\n if (msgType === \"agent_done\") {\r\n finalReply = (data.final_reply as string) || \"\";\r\n const replyExpectsReply = data.expects_reply !== false;\r\n events.onAssistantDone?.(finalReply, replyExpectsReply);\r\n if (typeof data.session_id === \"string\") {\r\n events.onSessionId?.(data.session_id as string);\r\n }\r\n finish(finalReply);\r\n return;\r\n }\r\n\r\n if (msgType === \"error\") {\r\n const errMsg = (data.error as string) || \"Agent error\";\r\n errorEmitted = true;\r\n events.onError?.(errMsg);\r\n fail(new Error(errMsg));\r\n return;\r\n }\r\n };\r\n\r\n socket.onerror = () => {\r\n errorEmitted = true;\r\n events.onError?.(\"Agent WebSocket error\");\r\n fail(new Error(\"Agent WebSocket error\"));\r\n };\r\n socket.onclose = () => finish(finalReply);\r\n });\r\n\r\n activeSocket = null;\r\n\r\n // ── 2. TTS ────────────────────────────────────────────────\r\n if (isStopped || !assistantText) {\r\n if (!isStopped) {\r\n hideAgentCursor();\r\n }\r\n return resolve();\r\n }\r\n\r\n hideAgentCursor();\r\n await collectAndPlayTtsStreamed(\r\n baseUrl, assistantText, config.voice, Boolean(config.accessibilityMode),\r\n () => isStopped,\r\n (socket) => { activeSocket = socket; },\r\n (reader) => { activeReader = reader; },\r\n events.onAudioStateChange,\r\n );\r\n\r\n resolve();\r\n } catch (err) {\r\n if (!errorEmitted) {\r\n const msg = err instanceof Error ? err.message : String(err);\r\n events.onError?.(msg);\r\n }\r\n reject(err);\r\n } finally {\r\n activeReader?.cancel().catch(() => { });\r\n if (activeSocket && activeSocket.readyState <= WebSocket.OPEN) {\r\n activeSocket.close();\r\n }\r\n activeSocket = null;\r\n }\r\n });\r\n\r\n return {\r\n stop: () => {\r\n isStopped = true;\r\n stopActiveAudioPlayback();\r\n if (activeReader) activeReader.cancel().catch(() => { });\r\n if (activeSocket && activeSocket.readyState <= WebSocket.OPEN) {\r\n activeSocket.close();\r\n }\r\n },\r\n done: donePromise,\r\n };\r\n};\r\n\r\n// ── Agent Resume Stream (after page navigation reload) ──────────────\r\n//\r\n// When a navigate tool causes a full-page reload, the agent WS is lost.\r\n// This function opens a new WS with {type: \"resume\"}, sends the\r\n// completed tool results (including the navigate result with the new\r\n// page context), and continues the agent loop from where it left off.\r\n\r\nexport const agentResumeStream = (\r\n baseUrl: string,\r\n resumeState: PendingAgentResume,\r\n pageContext: string,\r\n events: AgentVoiceChatEvents,\r\n executeTool: (call: AgentToolCallInfo) => Promise<{ call_id: string; result: string }>,\r\n): StreamController => {\r\n let isStopped = false;\r\n let activeSocket: WebSocket | null = null;\r\n let activeReader: ReadableStreamDefaultReader<Uint8Array> | undefined;\r\n let errorEmitted = false;\r\n\r\n // Build tool results for the calls that were pending when the page reloaded.\r\n // Navigate results include the new page context; other tools that couldn't\r\n // execute get a descriptive skip message.\r\n const allResults = [...resumeState.completedResults];\r\n for (const tc of resumeState.pendingToolCalls) {\r\n if (allResults.some((r) => r.call_id === tc.call_id)) continue;\r\n if (tc.tool === \"navigate\") {\r\n allResults.push({\r\n call_id: tc.call_id,\r\n result: `Navigasyon tamamlandı. Şu anki sayfa: ${typeof window !== \"undefined\" ? window.location.href : \"\"}\\nSayfa bağlamı: ${pageContext}`,\r\n });\r\n } else {\r\n allResults.push({\r\n call_id: tc.call_id,\r\n result: \"Sayfa yeniden yüklendi, bu araç çalıştırılamadı.\",\r\n });\r\n }\r\n }\r\n\r\n const donePromise = new Promise<void>(async (resolve, reject) => {\r\n try {\r\n if (isStopped) return resolve();\r\n\r\n let effectiveSessionId = resumeState.sessionId;\r\n\r\n const assistantText = await new Promise<string>((agentResolve, agentReject) => {\r\n if (isStopped) { agentResolve(\"\"); return; }\r\n\r\n const wsUrl = toWebSocketUrl(baseUrl, \"/chat/agent/ws\");\r\n const socket = new WebSocket(wsUrl);\r\n activeSocket = socket;\r\n\r\n let finalReply = \"\";\r\n let resolved = false;\r\n let accumulatedDelta = \"\";\r\n let allIntermediateText = \"\";\r\n\r\n const finish = (reply: string) => {\r\n if (resolved) return;\r\n resolved = true;\r\n agentResolve(reply);\r\n };\r\n\r\n const fail = (error: Error) => {\r\n if (resolved) return;\r\n resolved = true;\r\n agentReject(error);\r\n };\r\n\r\n socket.onopen = () => {\r\n console.info(\"[Bulut] Agent WS resume connected\");\r\n socket.send(JSON.stringify({\r\n type: \"resume\",\r\n project_id: resumeState.projectId,\r\n session_id: resumeState.sessionId,\r\n model: resumeState.model,\r\n page_context: pageContext,\r\n accessibility_mode: resumeState.accessibilityMode,\r\n accumulated_delta: resumeState.accumulatedDelta || \"\",\r\n pending_tool_calls: resumeState.pendingToolCalls,\r\n tool_results: allResults,\r\n }));\r\n };\r\n\r\n socket.onmessage = async (event) => {\r\n let data: Record<string, unknown>;\r\n try {\r\n data = JSON.parse(String(event.data));\r\n } catch { return; }\r\n\r\n const msgType = data.type as string;\r\n\r\n if (msgType === \"session\" && typeof data.session_id === \"string\") {\r\n effectiveSessionId = data.session_id as string;\r\n events.onSessionId?.(effectiveSessionId);\r\n return;\r\n }\r\n\r\n if (msgType === \"iteration\") {\r\n events.onIteration?.(\r\n data.iteration as number,\r\n data.max_iterations as number,\r\n );\r\n return;\r\n }\r\n\r\n if (msgType === \"reply_delta\" && typeof data.delta === \"string\") {\r\n accumulatedDelta += data.delta;\r\n events.onAssistantDelta?.(data.delta);\r\n return;\r\n }\r\n\r\n if (msgType === \"tool_calls\" && Array.isArray(data.calls)) {\r\n const calls = data.calls as AgentToolCallInfo[];\r\n\r\n // Speak accumulated text before running tools\r\n if (accumulatedDelta.trim()) {\r\n events.onIntermediateReply?.(accumulatedDelta.trim());\r\n allIntermediateText += accumulatedDelta;\r\n }\r\n accumulatedDelta = \"\";\r\n\r\n events.onToolCalls?.(calls);\r\n\r\n const results: { call_id: string; result: string }[] = [];\r\n for (const call of calls) {\r\n const isNavigate = call.tool === \"navigate\";\r\n if (isNavigate) {\r\n savePendingAgentResume({\r\n sessionId: effectiveSessionId,\r\n projectId: resumeState.projectId,\r\n model: resumeState.model,\r\n voice: resumeState.voice,\r\n accessibilityMode: resumeState.accessibilityMode,\r\n pendingToolCalls: calls.map((c) => ({\r\n call_id: c.call_id,\r\n tool: c.tool,\r\n args: c.args,\r\n })),\r\n completedResults: [...results],\r\n accumulatedDelta: allIntermediateText || undefined,\r\n });\r\n }\r\n\r\n const result = await executeTool(call);\r\n\r\n if (isNavigate) {\r\n clearPendingAgentResume();\r\n }\r\n\r\n events.onToolResult?.(call.call_id, call.tool, result.result);\r\n results.push(result);\r\n }\r\n\r\n if (socket.readyState === WebSocket.OPEN) {\r\n socket.send(JSON.stringify({ type: \"tool_results\", results }));\r\n }\r\n return;\r\n }\r\n\r\n if (msgType === \"agent_done\") {\r\n finalReply = (data.final_reply as string) || \"\";\r\n const replyExpectsReply = data.expects_reply !== false;\r\n events.onAssistantDone?.(finalReply, replyExpectsReply);\r\n if (typeof data.session_id === \"string\") {\r\n events.onSessionId?.(data.session_id as string);\r\n }\r\n finish(finalReply);\r\n return;\r\n }\r\n\r\n if (msgType === \"error\") {\r\n const errMsg = (data.error as string) || \"Agent error\";\r\n errorEmitted = true;\r\n events.onError?.(errMsg);\r\n fail(new Error(errMsg));\r\n return;\r\n }\r\n };\r\n\r\n socket.onerror = () => {\r\n errorEmitted = true;\r\n events.onError?.(\"Agent WebSocket error\");\r\n fail(new Error(\"Agent WebSocket error\"));\r\n };\r\n\r\n socket.onclose = () => finish(finalReply);\r\n });\r\n\r\n activeSocket = null;\r\n\r\n // ── TTS ────────────────────────────────────────────────\r\n if (isStopped || !assistantText) {\r\n if (!isStopped) {\r\n hideAgentCursor();\r\n }\r\n return resolve();\r\n }\r\n\r\n console.info(`[Bulut] TTS start mode=resume voice=${resumeState.voice}`);\r\n hideAgentCursor();\r\n await collectAndPlayTtsStreamed(\r\n baseUrl, assistantText, resumeState.voice, Boolean(resumeState.accessibilityMode),\r\n () => isStopped,\r\n (socket) => { activeSocket = socket; },\r\n (reader) => { activeReader = reader; },\r\n events.onAudioStateChange,\r\n );\r\n\r\n resolve();\r\n } catch (err) {\r\n if (!errorEmitted) {\r\n const msg = err instanceof Error ? err.message : String(err);\r\n events.onError?.(msg);\r\n }\r\n reject(err);\r\n } finally {\r\n activeReader?.cancel().catch(() => { });\r\n if (activeSocket && activeSocket.readyState <= WebSocket.OPEN) {\r\n activeSocket.close();\r\n }\r\n activeSocket = null;\r\n }\r\n });\r\n\r\n return {\r\n stop: () => {\r\n isStopped = true;\r\n stopActiveAudioPlayback();\r\n if (activeReader) activeReader.cancel().catch(() => { });\r\n if (activeSocket && activeSocket.readyState <= WebSocket.OPEN) {\r\n activeSocket.close();\r\n }\r\n },\r\n done: donePromise,\r\n };\r\n};\r\n","import {\r\n completedSfxUrl,\r\n sentSfxUrl,\r\n thinkingSfxUrl,\r\n toolCallSfxUrl,\r\n} from \"../assets\";\r\n\r\nexport type SfxName = \"sent\" | \"thinking\" | \"toolCall\" | \"completed\";\r\n\r\nconst SFX_SOURCES: Record<SfxName, string> = {\r\n sent: sentSfxUrl,\r\n thinking: thinkingSfxUrl,\r\n toolCall: toolCallSfxUrl,\r\n completed: completedSfxUrl,\r\n};\r\n\r\nconst SFX_VOLUME = 0.5;\r\n\r\nclass SfxManager {\r\n private queue: SfxName[] = [];\r\n private active = false;\r\n\r\n private playNow(name: SfxName): Promise<void> {\r\n return new Promise((resolve) => {\r\n if (typeof window === \"undefined\") {\r\n resolve();\r\n return;\r\n }\r\n\r\n const audio = new Audio(SFX_SOURCES[name]);\r\n audio.preload = \"auto\";\r\n audio.volume = SFX_VOLUME;\r\n\r\n let settled = false;\r\n const finalize = () => {\r\n if (settled) return;\r\n settled = true;\r\n audio.onended = null;\r\n audio.onerror = null;\r\n resolve();\r\n };\r\n\r\n audio.onended = finalize;\r\n audio.onerror = finalize;\r\n void audio.play().catch(() => finalize());\r\n });\r\n }\r\n\r\n private async drain(): Promise<void> {\r\n if (this.active) return;\r\n this.active = true;\r\n try {\r\n while (this.queue.length > 0) {\r\n const next = this.queue.shift();\r\n if (!next) continue;\r\n await this.playNow(next);\r\n }\r\n } finally {\r\n this.active = false;\r\n }\r\n }\r\n\r\n playCue(name: SfxName): void {\r\n if (typeof window === \"undefined\") return;\r\n this.queue.push(name);\r\n if (!this.active) {\r\n void this.drain();\r\n }\r\n }\r\n}\r\n\r\nconst sfxManager = new SfxManager();\r\n\r\nexport const playCue = (name: SfxName): void => {\r\n sfxManager.playCue(name);\r\n};\r\n","export default \"data:audio/mpeg;base64,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\"","export default \"data:audio/mpeg;base64,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VVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVQ==\"","export default \"data:audio/mpeg;base64,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qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqgU7bdtbNa5MIRBHgnj4UR9JwIgVBwG4sGQ6iUOI9A8D4gD+UB2EkchSQR4JZYNzUyKpeTJzhe5G6uhMjIwPOFopGnGihQsgHRJAooSJEExgcJJAooD/+rJs9RAqj/URY7JpgTYKAAANIAAAAQAAAaQAAAAgAAA0gAAABIWQTUkROElmHxaqlm7Oz/9nzZqWcuLUkicacUfCakiJxZZlwtGjSini42af/s7P3dtyppyij0FopETgMDMJoLRJGlFHmWpJE4sukDVJVUxBTUUzLjk5LjVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVU=\"","export default \"data:audio/mpeg;base64,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BpGoUioUhyHQcjkOIhCCIQkg1EYApIxw2dKsgSFBRY7KF9qKJlrzBofwHJWHEHg1GskL2IUxVHoaRPKh2w3AlLxBIIwjQThaxUZGCNA3myVKnEbD2UScIrTc0hRFSim+MkJEMh44vC5KlhkaDxdSdJrFSxxeE4XSqyy8Jw33Jf/6smxwIbyA+HBovGsrZIgAAA0gAAABFwmixmwxKYgAADSAAAAEk0Dbmma1Emo9lEQli6+eTKIhEQfOqTqKypYZOqL1dKlhkZKLwnSaxUZKI0E4WsVKnEbD3SvFUpueyiVUhvySEiKnDi/9pov9VVNvpoqVTEFNRTMuOTkuNVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVf/6smw7EwAP8AAAaQAAAAgAAA0gAAABAAABpAAAACAAADSAAAAETEFNRTMuOTkuNVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVTEFNRTMuOTkuNVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVQ==\"","import { useEffect, useLayoutEffect, useRef, useState } from \"preact/hooks\";\r\nimport type { JSX } from \"preact\";\r\nimport type { BulutRuntimeConfig } from \"../index\";\r\nimport {\r\n agentTextChatStream,\r\n agentVoiceChatStream,\r\n agentResumeStream,\r\n startSttWebSocketStream,\r\n stopActiveAudioPlayback,\r\n speakText,\r\n type AudioStreamState,\r\n type StreamController,\r\n type AgentToolCallInfo,\r\n type SttWsController,\r\n} from \"../api/client\";\r\nimport {\r\n executeSingleToolCall,\r\n parseAgentResponse,\r\n getPendingAgentResume,\r\n clearPendingAgentResume,\r\n type ToolCallWithId,\r\n} from \"../agent/tools\";\r\nimport { getPageContext } from \"../agent/context\";\r\nimport {\r\n WINDOW_WIDTH,\r\n WINDOW_HEIGHT,\r\n POSITION_BOTTOM,\r\n POSITION_RIGHT,\r\n COLORS,\r\n TRANSITIONS,\r\n BORDER_RADIUS,\r\n SHADOW,\r\n} from \"../styles/constants\";\r\nimport {\r\n logoContent,\r\n arrowPathIconContent,\r\n commandLineIconContent,\r\n cursorArrowRaysIconContent,\r\n faceSmileIconContent,\r\n handRaisedIconContent,\r\n mapIconContent,\r\n microphoneOutlineIconContent,\r\n queueListIconContent,\r\n stopOutlineIconContent,\r\n xMarkIconContent,\r\n} from \"../assets\";\r\nimport { StreamingJsonParser } from \"../utils/streamingJson\";\r\nimport { playCue, type SfxName } from \"../audio/sfxManager\";\r\nimport { SvgIcon } from \"./SvgIcon\";\r\n\r\nexport interface ChatWindowHandle {\r\n startRecording: () => void;\r\n cancelRecording: () => void;\r\n stopTask: () => void;\r\n}\r\n\r\ninterface ChatWindowProps {\r\n onClose: () => void;\r\n config: BulutRuntimeConfig;\r\n accessibilityMode?: boolean;\r\n onAccessibilityToggle?: () => void;\r\n hidden?: boolean;\r\n actionsRef?: { current: ChatWindowHandle | null };\r\n onRecordingChange?: (recording: boolean) => void;\r\n onBusyChange?: (busy: boolean) => void;\r\n onPreviewChange?: (text: string | null) => void;\r\n}\r\n\r\ninterface Message {\r\n id: number;\r\n text: string;\r\n isUser: boolean;\r\n /** \"message\" (default) | \"tool\" for tool call indicators */\r\n type?: \"message\" | \"tool\";\r\n toolKind?: \"context\" | \"cursor\" | \"scroll\" | \"navigate\" | \"form\" | \"interact\" | \"unknown\";\r\n toolLabel?: string;\r\n toolCount?: number;\r\n}\r\n\r\ntype RecordingMode = \"vad\" | \"press\";\r\n\r\ntype StorageLike = {\r\n removeItem: (key: string) => void;\r\n};\r\n\r\nconst STORAGE_KEY = \"bulut_chat_history\";\r\nconst TIMESTAMP_KEY = \"bulut_chat_timestamp\";\r\nconst SESSION_ID_KEY = \"bulut_session_id\";\r\nconst TTL_MS = 5 * 60 * 1000;\r\nconst VAD_THRESHOLD = 0.06;\r\nconst SILENCE_DURATION_MS = 500;\r\nconst ACCESSIBILITY_MIN_SPEECH_DURATION_MS = 1500;\r\nexport const HOLD_THRESHOLD_MS = 250;\r\n\r\nconst STATUS_LABELS = {\r\n ready: \"Hazır\",\r\n loading: \"Bir saniye\",\r\n micInitializing: \"Mikrofonu hazırlıyorum\",\r\n listening: \"Sizi dinliyorum\",\r\n accessibilityActive: \"Erişilebilirlik Aktif\",\r\n transcribing: \"Düşünüyorum\",\r\n thinking: \"Düşünüyorum\",\r\n playingAudio: \".\",\r\n runningTools: \"Siteyle ilgileniyorum\",\r\n} as const;\r\n\r\nexport const getGreetingText = (agentName: string): string =>\r\n `Merhaba, ben ${agentName}. Bu web sayfasında neler yapalım?`;\r\n\r\nexport interface StatusFlags {\r\n isBusy: boolean;\r\n isRecording: boolean;\r\n isTranscribing: boolean;\r\n isThinking: boolean;\r\n isRenderingAudio: boolean;\r\n isPlayingAudio: boolean;\r\n isRunningTools: boolean;\r\n}\r\n\r\nexport const resolveStatusText = (flags: StatusFlags): string => {\r\n if (flags.isRecording) return STATUS_LABELS.listening;\r\n if (flags.isRunningTools) return STATUS_LABELS.runningTools;\r\n if (flags.isPlayingAudio) return STATUS_LABELS.playingAudio;\r\n if (flags.isThinking) return STATUS_LABELS.thinking;\r\n if (flags.isTranscribing) return STATUS_LABELS.transcribing;\r\n if (flags.isBusy) return STATUS_LABELS.loading;\r\n return STATUS_LABELS.ready;\r\n};\r\n\r\nexport const hasActiveStatus = (\r\n flags: StatusFlags,\r\n statusOverride: string | null,\r\n): boolean =>\r\n Boolean(\r\n statusOverride\r\n || flags.isBusy\r\n || flags.isRecording\r\n || flags.isTranscribing\r\n || flags.isThinking\r\n || flags.isRenderingAudio\r\n || flags.isPlayingAudio\r\n || flags.isRunningTools,\r\n );\r\n\r\nexport const formatDurationMs = (durationMs: number): string => {\r\n const totalSeconds = Math.max(0, Math.floor(durationMs / 1000));\r\n const minutes = Math.floor(totalSeconds / 60)\r\n .toString()\r\n .padStart(2, \"0\");\r\n const seconds = (totalSeconds % 60).toString().padStart(2, \"0\");\r\n return `${minutes}:${seconds}`;\r\n};\r\n\r\nexport const classifyMicGesture = (\r\n durationMs: number,\r\n thresholdMs: number = HOLD_THRESHOLD_MS,\r\n): \"tap\" | \"hold\" => (durationMs >= thresholdMs ? \"hold\" : \"tap\");\r\n\r\nexport const createInitialMessages = (agentName: string): Message[] => [\r\n {\r\n id: 1,\r\n text: getGreetingText(agentName),\r\n isUser: false,\r\n },\r\n];\r\n\r\nexport const clearPersistedChatState = (storage: StorageLike | null): void => {\r\n if (!storage) {\r\n return;\r\n }\r\n\r\n storage.removeItem(STORAGE_KEY);\r\n storage.removeItem(TIMESTAMP_KEY);\r\n storage.removeItem(SESSION_ID_KEY);\r\n};\r\n\r\nexport const scrollElementToBottom = (\r\n element: { scrollTop: number; scrollHeight: number } | null,\r\n): void => {\r\n if (!element) {\r\n return;\r\n }\r\n\r\n element.scrollTop = element.scrollHeight;\r\n};\r\n\r\nconst normalizeError = (error: unknown) => {\r\n if (error instanceof Error) {\r\n return error.message;\r\n }\r\n return \"Bilinmeyen hata\";\r\n};\r\n\r\nconst getNextMessageId = (messages: Message[]): number => {\r\n const maxId = messages.reduce((acc, message) => Math.max(acc, message.id), 0);\r\n return maxId + 1;\r\n};\r\n\r\nexport interface AssistantPayloadResolution {\r\n displayText: string;\r\n toolCalls: ReturnType<typeof parseAgentResponse>[\"toolCalls\"];\r\n}\r\n\r\nexport const resolveAssistantPayload = (\r\n assistantText: string,\r\n): AssistantPayloadResolution => {\r\n const parsed = parseAgentResponse(assistantText);\r\n return {\r\n displayText: parsed.reply || assistantText,\r\n toolCalls: parsed.toolCalls,\r\n };\r\n};\r\n\r\nexport const shouldAutoListenAfterAudio = (\r\n accessibilityMode: boolean,\r\n expectsReply: boolean,\r\n isRecording: boolean,\r\n isBusy: boolean,\r\n): boolean => (accessibilityMode || expectsReply) && !isRecording && !isBusy;\r\n\r\nexport const shouldAcceptVadSpeech = (\r\n speechDurationMs: number,\r\n enforceMinSpeechDuration: boolean,\r\n minSpeechDurationMs: number = ACCESSIBILITY_MIN_SPEECH_DURATION_MS,\r\n): boolean => !enforceMinSpeechDuration || speechDurationMs >= minSpeechDurationMs;\r\n\r\ninterface ToolIndicatorMessage {\r\n text: string;\r\n kind: \"context\" | \"cursor\" | \"scroll\" | \"navigate\" | \"form\" | \"interact\" | \"unknown\";\r\n}\r\n\r\nconst getToolIndicatorMessage = (\r\n call: AgentToolCallInfo,\r\n): ToolIndicatorMessage => {\r\n if (call.tool === \"getPageContext\") {\r\n return { text: \"Algılama\", kind: \"context\" };\r\n }\r\n if (call.tool === \"scroll\") {\r\n return { text: \"Kaydırma\", kind: \"scroll\" };\r\n }\r\n if (call.tool === \"navigate\") {\r\n const url = typeof call.args.url === \"string\" ? call.args.url.trim() : \"\";\r\n return {\r\n text: url ? `Sayfa Geçişi: ${url}` : \"Sayfa Geçişi\",\r\n kind: \"navigate\",\r\n };\r\n }\r\n if (call.tool === \"interact\" && call.args.action === \"move\") {\r\n return { text: \"Serbest İmleç\", kind: \"cursor\" };\r\n }\r\n if (call.tool === \"interact\" && call.args.action === \"type\") {\r\n return { text: \"Form Doldurma\", kind: \"form\" };\r\n }\r\n if (call.tool === \"interact\" && call.args.action === \"submit\") {\r\n return { text: \"Form Gönderme\", kind: \"form\" };\r\n }\r\n if (call.tool === \"interact\" && call.args.action === \"click\") {\r\n return { text: \"Tıklama\", kind: \"interact\" };\r\n }\r\n if (call.tool === \"interact\") {\r\n return { text: \"Etkileşim\", kind: \"interact\" };\r\n }\r\n return {\r\n text: call.tool || \"Araç\",\r\n kind: \"unknown\",\r\n };\r\n};\r\n\r\nexport const ChatWindow = ({\r\n onClose,\r\n config,\r\n accessibilityMode = false,\r\n onAccessibilityToggle,\r\n hidden = false,\r\n actionsRef,\r\n onRecordingChange,\r\n onBusyChange,\r\n onPreviewChange,\r\n}: ChatWindowProps) => {\r\n const [messages, setMessages] = useState<Message[]>(() => {\r\n if (typeof localStorage !== \"undefined\") {\r\n const saved = localStorage.getItem(STORAGE_KEY);\r\n const timestamp = localStorage.getItem(TIMESTAMP_KEY);\r\n\r\n if (saved && timestamp) {\r\n const timePassed = Date.now() - parseInt(timestamp, 10);\r\n if (timePassed < TTL_MS) {\r\n try {\r\n return JSON.parse(saved) as Message[];\r\n } catch {\r\n // Ignore parse error and continue with default.\r\n }\r\n } else {\r\n clearPersistedChatState(localStorage);\r\n }\r\n }\r\n }\r\n\r\n return createInitialMessages(config.agentName);\r\n });\r\n\r\n const [isBusy, setIsBusy] = useState(false);\r\n const [isRecording, setIsRecording] = useState(false);\r\n const [isTranscribing, setIsTranscribing] = useState(false);\r\n const [isThinking, setIsThinking] = useState(false);\r\n const [isRenderingAudio, setIsRenderingAudio] = useState(false);\r\n const [isPlayingAudio, setIsPlayingAudio] = useState(false);\r\n const [isRunningTools, setIsRunningTools] = useState(false);\r\n const [isMicPending, setIsMicPending] = useState(false);\r\n const [recordingDurationMs, setRecordingDurationMs] = useState(0);\r\n const [statusOverride, setStatusOverride] = useState<string | null>(null);\r\n const statusFlags: StatusFlags = {\r\n isBusy,\r\n isRecording,\r\n isTranscribing,\r\n isThinking,\r\n isRenderingAudio,\r\n isPlayingAudio,\r\n isRunningTools,\r\n };\r\n const resolvedStatusText = resolveStatusText(statusFlags);\r\n const showStatus = hasActiveStatus(statusFlags, statusOverride);\r\n const statusText = showStatus ? (statusOverride ?? resolvedStatusText) : STATUS_LABELS.ready;\r\n\r\n const isBusyRef = useRef(isBusy);\r\n const isRecordingRef = useRef(isRecording);\r\n\r\n const nextMessageIdRef = useRef(getNextMessageId(messages));\r\n const recorderRef = useRef<MediaRecorder | null>(null);\r\n const streamRef = useRef<MediaStream | null>(null);\r\n const audioChunksRef = useRef<BlobPart[]>([]);\r\n const activeStreamControllerRef = useRef<StreamController | null>(null);\r\n const sessionIdRef = useRef<string | null>(\r\n typeof localStorage !== \"undefined\"\r\n ? (() => {\r\n const ts = localStorage.getItem(TIMESTAMP_KEY);\r\n if (ts && Date.now() - parseInt(ts, 10) < TTL_MS) {\r\n return localStorage.getItem(SESSION_ID_KEY);\r\n }\r\n return null;\r\n })()\r\n : null,\r\n );\r\n\r\n const silenceStartRef = useRef<number | null>(null);\r\n const vadIntervalRef = useRef<number | null>(null);\r\n const audioContextRef = useRef<AudioContext | null>(null);\r\n const sourceRef = useRef<MediaStreamAudioSourceNode | null>(null);\r\n\r\n const discardNextRecordingRef = useRef(false);\r\n\r\n const micPressStartRef = useRef<number | null>(null);\r\n const micHoldTimeoutRef = useRef<number | null>(null);\r\n const micHoldTriggeredRef = useRef(false);\r\n const recordingModeRef = useRef<RecordingMode | null>(null);\r\n const pendingStopAfterStartRef = useRef(false);\r\n const startRecordingPendingRef = useRef(false);\r\n\r\n const assistantMessageIdRef = useRef<number | null>(null);\r\n const assistantTextBufferRef = useRef(\"\");\r\n const transcriptionReceivedRef = useRef(false);\r\n const assistantDoneReceivedRef = useRef(false);\r\n\r\n const recordingStartedAtRef = useRef<number | null>(null);\r\n const recordingTimerIntervalRef = useRef<number | null>(null);\r\n\r\n const messagesContainerRef = useRef<HTMLDivElement | null>(null);\r\n const messagesContentRef = useRef<HTMLDivElement | null>(null);\r\n\r\n const pendingUserTextRef = useRef<string | null>(null);\r\n const pendingAssistantTextRef = useRef<string>(\"\");\r\n const streamingJsonParserRef = useRef<StreamingJsonParser | null>(null);\r\n const awaitingAssistantResponseRef = useRef(false);\r\n const activeSttWsRef = useRef<SttWsController | null>(null);\r\n const liveTranscriptionMessageIdRef = useRef<number | null>(null);\r\n const liveTranscriptionTextRef = useRef(\"\");\r\n const autoListenSuppressedRef = useRef(false);\r\n const expectsReplyRef = useRef(true);\r\n const requestEpochRef = useRef(0);\r\n const sttSendCuePlayedRef = useRef(false);\r\n\r\n useEffect(() => {\r\n isBusyRef.current = isBusy;\r\n }, [isBusy]);\r\n\r\n useEffect(() => {\r\n isRecordingRef.current = isRecording;\r\n }, [isRecording]);\r\n\r\n // Report state changes to parent\r\n useEffect(() => { onRecordingChange?.(isRecording); }, [isRecording]);\r\n useEffect(() => { onBusyChange?.(isBusy); }, [isBusy]);\r\n\r\n // Derive and report preview text to parent\r\n useEffect(() => {\r\n if (!onPreviewChange) return;\r\n if (isRecording) {\r\n onPreviewChange(statusOverride ?? STATUS_LABELS.listening);\r\n return;\r\n }\r\n // When audio is rendering/playing, show the actual message text\r\n if (isRenderingAudio || isPlayingAudio) {\r\n const lastAssistant = [...messages].reverse().find(m => !m.isUser && m.type !== \"tool\");\r\n onPreviewChange(lastAssistant?.text ?? getGreetingText(config.agentName));\r\n return;\r\n }\r\n if (showStatus) {\r\n const st = statusOverride ?? resolveStatusText({\r\n isBusy,\r\n isRecording,\r\n isTranscribing,\r\n isThinking,\r\n isRenderingAudio,\r\n isPlayingAudio,\r\n isRunningTools,\r\n });\r\n onPreviewChange(st);\r\n return;\r\n }\r\n // Show last assistant message (or greeting)\r\n const lastAssistant = [...messages].reverse().find(m => !m.isUser && m.type !== \"tool\");\r\n onPreviewChange(lastAssistant?.text ?? getGreetingText(config.agentName));\r\n }, [\r\n isRecording,\r\n isBusy,\r\n isTranscribing,\r\n isThinking,\r\n isRunningTools,\r\n isPlayingAudio,\r\n isRenderingAudio,\r\n statusOverride,\r\n showStatus,\r\n messages,\r\n ]);\r\n\r\n const playSfx = (name: SfxName) => {\r\n playCue(name);\r\n };\r\n\r\n const beginRequestEpoch = () => {\r\n requestEpochRef.current += 1;\r\n return requestEpochRef.current;\r\n };\r\n\r\n const invalidateRequestEpoch = () => {\r\n requestEpochRef.current += 1;\r\n };\r\n\r\n const isCurrentRequestEpoch = (epoch: number): boolean =>\r\n requestEpochRef.current === epoch;\r\n\r\n const playSttSentCueOnce = () => {\r\n if (sttSendCuePlayedRef.current) {\r\n return;\r\n }\r\n sttSendCuePlayedRef.current = true;\r\n playSfx(\"sent\");\r\n };\r\n\r\n useEffect(() => {\r\n if (typeof localStorage !== \"undefined\") {\r\n localStorage.setItem(STORAGE_KEY, JSON.stringify(messages));\r\n localStorage.setItem(TIMESTAMP_KEY, Date.now().toString());\r\n }\r\n }, [messages]);\r\n\r\n const scrollMessagesToBottom = () => {\r\n scrollElementToBottom(messagesContainerRef.current);\r\n };\r\n\r\n useLayoutEffect(() => {\r\n scrollMessagesToBottom();\r\n }, [messages, statusText, isBusy, isRecording]);\r\n\r\n useEffect(() => {\r\n const content = messagesContentRef.current;\r\n if (!content || typeof ResizeObserver === \"undefined\") {\r\n return;\r\n }\r\n\r\n const observer = new ResizeObserver(() => {\r\n scrollMessagesToBottom();\r\n });\r\n\r\n observer.observe(content);\r\n return () => observer.disconnect();\r\n }, []);\r\n\r\n const stopRecordingTimer = () => {\r\n if (recordingTimerIntervalRef.current !== null) {\r\n window.clearInterval(recordingTimerIntervalRef.current);\r\n recordingTimerIntervalRef.current = null;\r\n }\r\n recordingStartedAtRef.current = null;\r\n };\r\n\r\n const startRecordingTimer = () => {\r\n stopRecordingTimer();\r\n recordingStartedAtRef.current = Date.now();\r\n setRecordingDurationMs(0);\r\n\r\n recordingTimerIntervalRef.current = window.setInterval(() => {\r\n const startedAt = recordingStartedAtRef.current;\r\n if (startedAt === null) {\r\n setRecordingDurationMs(0);\r\n return;\r\n }\r\n setRecordingDurationMs(Date.now() - startedAt);\r\n }, 200);\r\n };\r\n\r\n const resetProcessingFlags = () => {\r\n setIsTranscribing(false);\r\n setIsThinking(false);\r\n setIsRenderingAudio(false);\r\n setIsPlayingAudio(false);\r\n setIsRunningTools(false);\r\n setStatusOverride(null);\r\n assistantMessageIdRef.current = null;\r\n assistantTextBufferRef.current = \"\";\r\n transcriptionReceivedRef.current = false;\r\n assistantDoneReceivedRef.current = false;\r\n awaitingAssistantResponseRef.current = false;\r\n pendingUserTextRef.current = null;\r\n pendingAssistantTextRef.current = \"\";\r\n };\r\n\r\n const clearMicHoldTimeout = () => {\r\n if (micHoldTimeoutRef.current !== null) {\r\n window.clearTimeout(micHoldTimeoutRef.current);\r\n micHoldTimeoutRef.current = null;\r\n }\r\n };\r\n\r\n const cleanupVAD = () => {\r\n if (vadIntervalRef.current !== null) {\r\n clearInterval(vadIntervalRef.current);\r\n vadIntervalRef.current = null;\r\n }\r\n\r\n if (sourceRef.current) {\r\n sourceRef.current.disconnect();\r\n sourceRef.current = null;\r\n }\r\n\r\n if (audioContextRef.current) {\r\n audioContextRef.current.close().catch(() => {});\r\n audioContextRef.current = null;\r\n }\r\n\r\n silenceStartRef.current = null;\r\n };\r\n\r\n const stopStreamTracks = () => {\r\n if (!streamRef.current) {\r\n return;\r\n }\r\n\r\n streamRef.current.getTracks().forEach((track) => track.stop());\r\n streamRef.current = null;\r\n };\r\n\r\n const stopActiveStream = () => {\r\n if (!activeStreamControllerRef.current) {\r\n return;\r\n }\r\n\r\n activeStreamControllerRef.current.stop();\r\n activeStreamControllerRef.current = null;\r\n };\r\n\r\n const cancelActiveSttWs = () => {\r\n const activeSttWs = activeSttWsRef.current;\r\n activeSttWsRef.current = null;\r\n activeSttWs?.cancel();\r\n liveTranscriptionMessageIdRef.current = null;\r\n liveTranscriptionTextRef.current = \"\";\r\n };\r\n\r\n useEffect(\r\n () => () => {\r\n invalidateRequestEpoch();\r\n clearMicHoldTimeout();\r\n pendingStopAfterStartRef.current = false;\r\n\r\n stopActiveStream();\r\n stopActiveAudioPlayback();\r\n cancelActiveSttWs();\r\n cleanupVAD();\r\n stopStreamTracks();\r\n stopRecordingTimer();\r\n\r\n const recorder = recorderRef.current;\r\n if (recorder) {\r\n recorder.ondataavailable = null;\r\n recorder.onstop = null;\r\n recorder.onerror = null;\r\n if (recorder.state !== \"inactive\") {\r\n recorder.stop();\r\n }\r\n recorderRef.current = null;\r\n }\r\n\r\n cancelActiveSttWs();\r\n },\r\n [],\r\n );\r\n\r\n // ── Resume agent loop after full-page navigation ────────────────\r\n useEffect(() => {\r\n const resumeState = getPendingAgentResume();\r\n if (!resumeState) return;\r\n\r\n clearPendingAgentResume();\r\n console.info(\"[Bulut] Resuming agent after navigation\");\r\n\r\n // Restore session ID from resume state\r\n if (resumeState.sessionId) {\r\n sessionIdRef.current = resumeState.sessionId;\r\n if (typeof localStorage !== \"undefined\") {\r\n localStorage.setItem(SESSION_ID_KEY, resumeState.sessionId);\r\n }\r\n }\r\n\r\n const requestEpoch = beginRequestEpoch();\r\n setIsBusy(true);\r\n isBusyRef.current = true;\r\n setIsRunningTools(true);\r\n setStatusOverride(STATUS_LABELS.thinking);\r\n\r\n const freshPageContext = getPageContext().summary;\r\n\r\n const resumeToolExec = async (\r\n call: AgentToolCallInfo,\r\n ): Promise<{ call_id: string; result: string }> => {\r\n const toolCall: ToolCallWithId = {\r\n tool: call.tool as \"navigate\" | \"getPageContext\" | \"interact\" | \"scroll\",\r\n call_id: call.call_id,\r\n ...call.args,\r\n } as ToolCallWithId;\r\n return executeSingleToolCall(toolCall);\r\n };\r\n\r\n const controller = agentResumeStream(\r\n config.backendBaseUrl,\r\n resumeState,\r\n freshPageContext,\r\n {\r\n onSessionId: (sid) => {\r\n if (!isCurrentRequestEpoch(requestEpoch)) return;\r\n if (sid && sid !== sessionIdRef.current) {\r\n sessionIdRef.current = sid;\r\n if (typeof localStorage !== \"undefined\") {\r\n localStorage.setItem(SESSION_ID_KEY, sid);\r\n }\r\n }\r\n },\r\n onAssistantDelta: (delta) => {\r\n if (!isCurrentRequestEpoch(requestEpoch)) return;\r\n setIsRunningTools(false);\r\n setIsThinking(true);\r\n setStatusOverride(null);\r\n\r\n pendingAssistantTextRef.current += delta;\r\n\r\n if (assistantMessageIdRef.current === null) {\r\n assistantMessageIdRef.current = appendMessage(\r\n pendingAssistantTextRef.current,\r\n false,\r\n );\r\n } else {\r\n updateMessageText(\r\n assistantMessageIdRef.current,\r\n pendingAssistantTextRef.current,\r\n );\r\n }\r\n },\r\n onAssistantDone: (assistantText, expectsReply) => {\r\n if (!isCurrentRequestEpoch(requestEpoch)) return;\r\n playSfx(\"completed\");\r\n expectsReplyRef.current = expectsReply !== false;\r\n setStatusOverride(null);\r\n setIsThinking(false);\r\n setIsRenderingAudio(true);\r\n\r\n const finalDisplayText =\r\n assistantText || pendingAssistantTextRef.current;\r\n pendingAssistantTextRef.current = finalDisplayText;\r\n\r\n if (assistantMessageIdRef.current !== null) {\r\n updateMessageText(\r\n assistantMessageIdRef.current,\r\n finalDisplayText,\r\n );\r\n } else {\r\n assistantMessageIdRef.current = appendMessage(\r\n finalDisplayText,\r\n false,\r\n );\r\n }\r\n },\r\n onIntermediateReply: (text) => {\r\n if (!isCurrentRequestEpoch(requestEpoch)) return;\r\n void speakText(\r\n config.backendBaseUrl, text, config.voice,\r\n accessibilityMode, (state) => handleAudioStateChange(state, requestEpoch),\r\n ).catch((err) => console.warn(\"[Bulut] intermediate TTS failed\", err));\r\n },\r\n onToolCalls: (calls) => {\r\n if (!isCurrentRequestEpoch(requestEpoch)) return;\r\n if (calls.length > 0) {\r\n playSfx(\"toolCall\");\r\n }\r\n setIsRunningTools(true);\r\n setStatusOverride(STATUS_LABELS.runningTools);\r\n appendToolIndicatorMessages(calls);\r\n\r\n assistantMessageIdRef.current = null;\r\n pendingAssistantTextRef.current = \"\";\r\n },\r\n onToolResult: () => {},\r\n onIteration: () => {\r\n if (!isCurrentRequestEpoch(requestEpoch)) return;\r\n playSfx(\"thinking\");\r\n setIsThinking(true);\r\n setStatusOverride(STATUS_LABELS.thinking);\r\n },\r\n onAudioStateChange: (state) => {\r\n handleAudioStateChange(state, requestEpoch);\r\n },\r\n onError: (err) => {\r\n if (!isCurrentRequestEpoch(requestEpoch)) return;\r\n setStatusOverride(null);\r\n appendMessage(`Hata: ${err}`, false);\r\n },\r\n },\r\n resumeToolExec,\r\n );\r\n\r\n activeStreamControllerRef.current = controller;\r\n\r\n controller.done\r\n .catch(() => {})\r\n .finally(() => {\r\n if (!isCurrentRequestEpoch(requestEpoch)) return;\r\n setIsBusy(false);\r\n isBusyRef.current = false;\r\n setIsRunningTools(false);\r\n setIsThinking(false);\r\n setIsRenderingAudio(false);\r\n setIsPlayingAudio(false);\r\n setStatusOverride(null);\r\n pendingAssistantTextRef.current = \"\";\r\n assistantMessageIdRef.current = null;\r\n activeStreamControllerRef.current = null;\r\n\r\n if (\r\n !autoListenSuppressedRef.current &&\r\n shouldAutoListenAfterAudio(\r\n accessibilityMode,\r\n expectsReplyRef.current,\r\n isRecordingRef.current,\r\n false,\r\n )\r\n ) {\r\n void startRecording(\"vad\");\r\n }\r\n // Reset for next turn\r\n expectsReplyRef.current = true;\r\n });\r\n }, []); // eslint-disable-line react-hooks/exhaustive-deps\r\n\r\n const appendMessage = (\r\n text: string,\r\n isUser: boolean,\r\n options?: {\r\n type?: \"message\" | \"tool\";\r\n toolKind?: Message[\"toolKind\"];\r\n toolLabel?: string;\r\n toolCount?: number;\r\n },\r\n ): number => {\r\n const id = nextMessageIdRef.current++;\r\n setMessages((previous) => [\r\n ...previous,\r\n {\r\n id,\r\n text,\r\n isUser,\r\n type: options?.type,\r\n toolKind: options?.toolKind,\r\n toolLabel: options?.toolLabel,\r\n toolCount: options?.toolCount,\r\n },\r\n ]);\r\n return id;\r\n };\r\n\r\n const appendToolIndicatorMessages = (calls: AgentToolCallInfo[]) => {\r\n setMessages((previous) => {\r\n const next = [...previous];\r\n\r\n for (const call of calls) {\r\n const indicator = getToolIndicatorMessage(call);\r\n const last = next[next.length - 1];\r\n const previousToolText = typeof last?.text === \"string\"\r\n ? last.text.replace(/\\s+\\(\\d+\\)$/, \"\")\r\n : \"\";\r\n\r\n if (\r\n last\r\n && !last.isUser\r\n && last.type === \"tool\"\r\n && previousToolText === indicator.text\r\n ) {\r\n const extractedCount = Number.parseInt(\r\n (last.text.match(/\\((\\d+)\\)\\s*$/)?.[1] ?? \"1\"),\r\n 10,\r\n );\r\n const safeCurrentCount = Number.isFinite(extractedCount) ? extractedCount : 1;\r\n const nextCount = safeCurrentCount + 1;\r\n const baseLabel = previousToolText || indicator.text;\r\n next[next.length - 1] = {\r\n ...last,\r\n toolLabel: baseLabel,\r\n toolCount: nextCount,\r\n text: `${baseLabel} (${nextCount})`,\r\n };\r\n continue;\r\n }\r\n\r\n const id = nextMessageIdRef.current++;\r\n next.push({\r\n id,\r\n text: indicator.text,\r\n isUser: false,\r\n type: \"tool\",\r\n toolKind: indicator.kind,\r\n toolLabel: indicator.text,\r\n toolCount: 1,\r\n });\r\n }\r\n\r\n // Force-persist messages to localStorage immediately so they\r\n // survive a full-page navigate that may happen next frame.\r\n if (typeof localStorage !== \"undefined\") {\r\n try {\r\n localStorage.setItem(STORAGE_KEY, JSON.stringify(next));\r\n localStorage.setItem(TIMESTAMP_KEY, Date.now().toString());\r\n } catch { /* ignore full/blocked storage */ }\r\n }\r\n\r\n return next;\r\n });\r\n };\r\n\r\n const updateMessageText = (id: number, text: string) => {\r\n setMessages((previous) =>\r\n previous.map((message) =>\r\n message.id === id ? { ...message, text } : message,\r\n ),\r\n );\r\n };\r\n\r\n const upsertLiveUserTranscription = (text: string) => {\r\n const normalized = text.trim();\r\n if (!normalized) {\r\n return;\r\n }\r\n liveTranscriptionTextRef.current = normalized;\r\n if (liveTranscriptionMessageIdRef.current === null) {\r\n liveTranscriptionMessageIdRef.current = appendMessage(normalized, true);\r\n return;\r\n }\r\n updateMessageText(liveTranscriptionMessageIdRef.current, normalized);\r\n };\r\n\r\n const clearLiveUserTranscriptionState = () => {\r\n liveTranscriptionMessageIdRef.current = null;\r\n liveTranscriptionTextRef.current = \"\";\r\n };\r\n\r\n const handleAudioStateChange = (state: AudioStreamState, requestEpoch?: number) => {\r\n if (typeof requestEpoch === \"number\" && !isCurrentRequestEpoch(requestEpoch)) {\r\n return;\r\n }\r\n\r\n if (state === \"rendering\") {\r\n setIsRenderingAudio(true);\r\n setIsPlayingAudio(false);\r\n return;\r\n }\r\n\r\n if (state === \"playing\") {\r\n setIsRenderingAudio(false);\r\n setIsPlayingAudio(true);\r\n return;\r\n }\r\n\r\n if (state === \"fallback\") {\r\n setIsRenderingAudio(true);\r\n setIsPlayingAudio(false);\r\n return;\r\n }\r\n\r\n if (state === \"done\") {\r\n setIsRenderingAudio(false);\r\n setIsPlayingAudio(false);\r\n return;\r\n }\r\n\r\n setIsRenderingAudio(false);\r\n setIsPlayingAudio(false);\r\n };\r\n\r\n const finalizeStreamCycle = (requestEpoch?: number) => {\r\n if (typeof requestEpoch === \"number\" && !isCurrentRequestEpoch(requestEpoch)) {\r\n return;\r\n }\r\n\r\n awaitingAssistantResponseRef.current = false;\r\n setStatusOverride(null);\r\n setIsBusy(false);\r\n isBusyRef.current = false;\r\n setIsTranscribing(false);\r\n setIsThinking(false);\r\n setIsRenderingAudio(false);\r\n setIsPlayingAudio(false);\r\n setIsRunningTools(false);\r\n pendingUserTextRef.current = null;\r\n pendingAssistantTextRef.current = \"\";\r\n assistantMessageIdRef.current = null;\r\n if (activeStreamControllerRef.current) {\r\n activeStreamControllerRef.current = null;\r\n }\r\n if (\r\n !autoListenSuppressedRef.current &&\r\n shouldAutoListenAfterAudio(\r\n accessibilityMode,\r\n expectsReplyRef.current,\r\n isRecordingRef.current,\r\n false,\r\n )\r\n ) {\r\n console.info(\"[Bulut] chat-window auto-listen trigger after stream completion\");\r\n void startRecording(\"vad\");\r\n }\r\n // Reset for next turn\r\n expectsReplyRef.current = true;\r\n };\r\n\r\n const runAgentForUserText = async (userText: string) => {\r\n if (!config.projectId) {\r\n appendMessage(\"Hata: Project ID yapılandırılmamış.\", false);\r\n return;\r\n }\r\n\r\n const normalizedUserText = userText.trim();\r\n if (!normalizedUserText) {\r\n appendMessage(\"Ses kaydı metne dönüştürülemedi. Lütfen tekrar deneyin.\", false);\r\n return;\r\n }\r\n\r\n const requestEpoch = beginRequestEpoch();\r\n setIsBusy(true);\r\n isBusyRef.current = true;\r\n setIsTranscribing(false);\r\n setIsThinking(true);\r\n setIsRenderingAudio(false);\r\n setIsPlayingAudio(false);\r\n setIsRunningTools(false);\r\n setStatusOverride(STATUS_LABELS.thinking);\r\n awaitingAssistantResponseRef.current = true;\r\n\r\n try {\r\n pendingUserTextRef.current = normalizedUserText;\r\n upsertLiveUserTranscription(normalizedUserText);\r\n clearLiveUserTranscriptionState();\r\n\r\n stopActiveStream();\r\n const pageContext = getPageContext().summary;\r\n\r\n const handleToolExecution = async (\r\n call: AgentToolCallInfo,\r\n ): Promise<{ call_id: string; result: string }> => {\r\n const toolCall: ToolCallWithId = {\r\n tool: call.tool as\r\n | \"navigate\"\r\n | \"getPageContext\"\r\n | \"interact\"\r\n | \"scroll\",\r\n call_id: call.call_id,\r\n ...call.args,\r\n } as ToolCallWithId;\r\n return executeSingleToolCall(toolCall);\r\n };\r\n\r\n const controller = agentTextChatStream(\r\n config.backendBaseUrl,\r\n normalizedUserText,\r\n config.projectId,\r\n sessionIdRef.current,\r\n {\r\n model: config.model,\r\n voice: config.voice,\r\n pageContext,\r\n accessibilityMode,\r\n },\r\n {\r\n onSessionId: (sid) => {\r\n if (!isCurrentRequestEpoch(requestEpoch)) return;\r\n if (sid && sid !== sessionIdRef.current) {\r\n sessionIdRef.current = sid;\r\n if (typeof localStorage !== \"undefined\") {\r\n localStorage.setItem(SESSION_ID_KEY, sid);\r\n }\r\n }\r\n },\r\n onAssistantDelta: (delta) => {\r\n if (!isCurrentRequestEpoch(requestEpoch)) return;\r\n setIsTranscribing(false);\r\n setIsThinking(true);\r\n setIsRunningTools(false);\r\n if (awaitingAssistantResponseRef.current) {\r\n awaitingAssistantResponseRef.current = false;\r\n setStatusOverride(null);\r\n }\r\n\r\n pendingAssistantTextRef.current += delta;\r\n\r\n if (assistantMessageIdRef.current === null) {\r\n assistantMessageIdRef.current = appendMessage(\r\n pendingAssistantTextRef.current,\r\n false,\r\n );\r\n } else {\r\n updateMessageText(\r\n assistantMessageIdRef.current,\r\n pendingAssistantTextRef.current,\r\n );\r\n }\r\n },\r\n onAssistantDone: (assistantText, expectsReply) => {\r\n if (!isCurrentRequestEpoch(requestEpoch)) return;\r\n playSfx(\"completed\");\r\n expectsReplyRef.current = expectsReply !== false;\r\n awaitingAssistantResponseRef.current = false;\r\n setStatusOverride(null);\r\n setIsThinking(false);\r\n setIsRenderingAudio(true);\r\n\r\n const finalDisplayText = assistantText || pendingAssistantTextRef.current;\r\n pendingAssistantTextRef.current = finalDisplayText;\r\n\r\n if (assistantMessageIdRef.current !== null) {\r\n updateMessageText(\r\n assistantMessageIdRef.current,\r\n finalDisplayText,\r\n );\r\n } else {\r\n assistantMessageIdRef.current = appendMessage(\r\n finalDisplayText,\r\n false,\r\n );\r\n }\r\n },\r\n onIntermediateReply: (text) => {\r\n if (!isCurrentRequestEpoch(requestEpoch)) return;\r\n void speakText(\r\n config.backendBaseUrl, text, config.voice,\r\n accessibilityMode, (state) => handleAudioStateChange(state, requestEpoch),\r\n ).catch((err) => console.warn(\"[Bulut] intermediate TTS failed\", err));\r\n },\r\n onToolCalls: (calls) => {\r\n if (!isCurrentRequestEpoch(requestEpoch)) return;\r\n if (calls.length > 0) {\r\n playSfx(\"toolCall\");\r\n }\r\n setIsRunningTools(true);\r\n setStatusOverride(STATUS_LABELS.runningTools);\r\n appendToolIndicatorMessages(calls);\r\n\r\n assistantMessageIdRef.current = null;\r\n pendingAssistantTextRef.current = \"\";\r\n },\r\n onToolResult: () => {},\r\n onIteration: () => {\r\n if (!isCurrentRequestEpoch(requestEpoch)) return;\r\n playSfx(\"thinking\");\r\n setIsThinking(true);\r\n setStatusOverride(STATUS_LABELS.thinking);\r\n },\r\n onAudioStateChange: (state) => {\r\n handleAudioStateChange(state, requestEpoch);\r\n },\r\n onError: (err) => {\r\n if (!isCurrentRequestEpoch(requestEpoch)) return;\r\n awaitingAssistantResponseRef.current = false;\r\n setStatusOverride(null);\r\n appendMessage(`Hata: ${err}`, false);\r\n },\r\n },\r\n handleToolExecution,\r\n );\r\n\r\n activeStreamControllerRef.current = controller;\r\n await controller.done;\r\n } catch (error) {\r\n if (!isCurrentRequestEpoch(requestEpoch)) return;\r\n awaitingAssistantResponseRef.current = false;\r\n setStatusOverride(null);\r\n if (error instanceof Error) {\r\n appendMessage(`Hata: ${error.message}`, false);\r\n }\r\n } finally {\r\n finalizeStreamCycle(requestEpoch);\r\n }\r\n };\r\n\r\n const handleAudioBlob = async (blob: Blob) => {\r\n if (!config.projectId) {\r\n appendMessage(\"Hata: Project ID yapılandırılmamış.\", false);\r\n return;\r\n }\r\n\r\n const requestEpoch = beginRequestEpoch();\r\n setIsBusy(true);\r\n isBusyRef.current = true;\r\n setIsTranscribing(true);\r\n setIsThinking(false);\r\n setIsRenderingAudio(false);\r\n setIsPlayingAudio(false);\r\n setIsRunningTools(false);\r\n resetProcessingFlags(); // Start fresh\r\n setStatusOverride(STATUS_LABELS.thinking);\r\n awaitingAssistantResponseRef.current = true;\r\n\r\n try {\r\n const fileType = blob.type || \"audio/webm\";\r\n const extension = fileType.includes(\"ogg\")\r\n ? \"ogg\"\r\n : fileType.includes(\"wav\")\r\n ? \"wav\"\r\n : fileType.includes(\"mpeg\") || fileType.includes(\"mp3\")\r\n ? \"mp3\"\r\n : \"webm\";\r\n const file = new File([blob], `voice-input.${extension}`, {\r\n type: fileType,\r\n });\r\n\r\n stopActiveStream();\r\n\r\n const pageContext = getPageContext().summary;\r\n\r\n // Helper: bridge an AgentToolCallInfo to a ToolCallWithId\r\n const handleToolExecution = async (\r\n call: AgentToolCallInfo,\r\n ): Promise<{ call_id: string; result: string }> => {\r\n const toolCall: ToolCallWithId = {\r\n tool: call.tool as\r\n | \"navigate\"\r\n | \"getPageContext\"\r\n | \"interact\"\r\n | \"scroll\",\r\n call_id: call.call_id,\r\n ...call.args,\r\n } as ToolCallWithId;\r\n return executeSingleToolCall(toolCall);\r\n };\r\n\r\n const controller = agentVoiceChatStream(\r\n config.backendBaseUrl,\r\n file,\r\n config.projectId,\r\n sessionIdRef.current,\r\n {\r\n model: config.model,\r\n voice: config.voice,\r\n pageContext,\r\n accessibilityMode,\r\n },\r\n {\r\n onSttRequestSent: () => {\r\n if (!isCurrentRequestEpoch(requestEpoch)) return;\r\n playSttSentCueOnce();\r\n },\r\n onTranscription: (data) => {\r\n if (!isCurrentRequestEpoch(requestEpoch)) return;\r\n if (data.session_id && data.session_id !== sessionIdRef.current) {\r\n sessionIdRef.current = data.session_id;\r\n if (typeof localStorage !== \"undefined\") {\r\n localStorage.setItem(SESSION_ID_KEY, data.session_id);\r\n }\r\n }\r\n\r\n const normalized = data.user_text.trim();\r\n if (normalized) {\r\n const previousUserText = pendingUserTextRef.current;\r\n pendingUserTextRef.current = normalized;\r\n if (liveTranscriptionMessageIdRef.current !== null) {\r\n updateMessageText(liveTranscriptionMessageIdRef.current, normalized);\r\n clearLiveUserTranscriptionState();\r\n } else if (previousUserText !== normalized) {\r\n appendMessage(normalized, true);\r\n }\r\n }\r\n\r\n setIsTranscribing(false);\r\n setIsThinking(true);\r\n setStatusOverride(STATUS_LABELS.thinking);\r\n },\r\n onSessionId: (sid) => {\r\n if (!isCurrentRequestEpoch(requestEpoch)) return;\r\n if (sid && sid !== sessionIdRef.current) {\r\n sessionIdRef.current = sid;\r\n if (typeof localStorage !== \"undefined\") {\r\n localStorage.setItem(SESSION_ID_KEY, sid);\r\n }\r\n }\r\n },\r\n onAssistantDelta: (delta) => {\r\n if (!isCurrentRequestEpoch(requestEpoch)) return;\r\n setIsTranscribing(false);\r\n setIsThinking(true);\r\n setIsRunningTools(false);\r\n if (awaitingAssistantResponseRef.current) {\r\n awaitingAssistantResponseRef.current = false;\r\n setStatusOverride(null);\r\n }\r\n\r\n // Agent returns plain text (not JSON), stream it directly\r\n pendingAssistantTextRef.current += delta;\r\n\r\n if (assistantMessageIdRef.current === null) {\r\n assistantMessageIdRef.current = appendMessage(\r\n pendingAssistantTextRef.current,\r\n false,\r\n );\r\n } else {\r\n updateMessageText(\r\n assistantMessageIdRef.current,\r\n pendingAssistantTextRef.current,\r\n );\r\n }\r\n },\r\n onAssistantDone: (assistantText, expectsReply) => {\r\n if (!isCurrentRequestEpoch(requestEpoch)) return;\r\n playSfx(\"completed\");\r\n expectsReplyRef.current = expectsReply !== false;\r\n awaitingAssistantResponseRef.current = false;\r\n setStatusOverride(null);\r\n setIsThinking(false);\r\n setIsRenderingAudio(true);\r\n\r\n const finalDisplayText =\r\n assistantText || pendingAssistantTextRef.current;\r\n\r\n streamingJsonParserRef.current = null;\r\n pendingAssistantTextRef.current = finalDisplayText;\r\n\r\n if (assistantMessageIdRef.current !== null) {\r\n updateMessageText(\r\n assistantMessageIdRef.current,\r\n finalDisplayText,\r\n );\r\n } else {\r\n assistantMessageIdRef.current = appendMessage(\r\n finalDisplayText,\r\n false,\r\n );\r\n }\r\n },\r\n onIntermediateReply: (text) => {\r\n if (!isCurrentRequestEpoch(requestEpoch)) return;\r\n void speakText(\r\n config.backendBaseUrl, text, config.voice,\r\n accessibilityMode, (state) => handleAudioStateChange(state, requestEpoch),\r\n ).catch((err) => console.warn(\"[Bulut] intermediate TTS failed\", err));\r\n },\r\n onToolCalls: (calls) => {\r\n if (!isCurrentRequestEpoch(requestEpoch)) return;\r\n if (calls.length > 0) {\r\n playSfx(\"toolCall\");\r\n }\r\n setIsRunningTools(true);\r\n setStatusOverride(STATUS_LABELS.runningTools);\r\n appendToolIndicatorMessages(calls);\r\n assistantMessageIdRef.current = null;\r\n pendingAssistantTextRef.current = \"\";\r\n },\r\n onToolResult: (_callId, _toolName, _result) => {\r\n // Tool result sent back to agent automatically.\r\n // Could display detailed result here if needed.\r\n },\r\n onIteration: (_iteration, _maxIterations) => {\r\n if (!isCurrentRequestEpoch(requestEpoch)) return;\r\n // Agent started a new reasoning iteration\r\n playSfx(\"thinking\");\r\n setIsThinking(true);\r\n setStatusOverride(STATUS_LABELS.thinking);\r\n },\r\n onAudioStateChange: (state) => {\r\n handleAudioStateChange(state, requestEpoch);\r\n },\r\n onError: (err) => {\r\n if (!isCurrentRequestEpoch(requestEpoch)) return;\r\n awaitingAssistantResponseRef.current = false;\r\n setStatusOverride(null);\r\n appendMessage(`Hata: ${err}`, false);\r\n },\r\n },\r\n handleToolExecution,\r\n );\r\n\r\n activeStreamControllerRef.current = controller;\r\n await controller.done;\r\n\r\n // Safety: Ensure messages are flushed if not already\r\n // (e.g. if audio 'done' event didn't fire for some reason or there was no audio)\r\n /* if (pendingUserTextRef.current || pendingAssistantTextRef.current) {\r\n // flushPendingMessages(); // Removed as we stream now\r\n } */\r\n } catch (error) {\r\n if (!isCurrentRequestEpoch(requestEpoch)) return;\r\n // Error already shown via onError callback — don't duplicate\r\n awaitingAssistantResponseRef.current = false;\r\n setStatusOverride(null);\r\n } finally {\r\n finalizeStreamCycle(requestEpoch);\r\n }\r\n };\r\n\r\n const stopRecording = (options?: { discard?: boolean }) => {\r\n const recorder = recorderRef.current;\r\n if (!recorder || recorder.state === \"inactive\") {\r\n return;\r\n }\r\n\r\n if (options?.discard) {\r\n discardNextRecordingRef.current = true;\r\n }\r\n\r\n cleanupVAD();\r\n recorder.stop();\r\n };\r\n\r\n const setupVAD = (stream: MediaStream, recorder: MediaRecorder) => {\r\n const AudioCtx =\r\n window.AudioContext ||\r\n (window as Window & { webkitAudioContext?: typeof AudioContext })\r\n .webkitAudioContext;\r\n\r\n if (!AudioCtx) {\r\n return;\r\n }\r\n\r\n const context = new AudioCtx();\r\n audioContextRef.current = context;\r\n\r\n const analyser = context.createAnalyser();\r\n analyser.fftSize = 256;\r\n\r\n const source = context.createMediaStreamSource(stream);\r\n sourceRef.current = source;\r\n source.connect(analyser);\r\n\r\n const dataArray = new Uint8Array(analyser.frequencyBinCount);\r\n silenceStartRef.current = null;\r\n let speechDetected = false;\r\n let speechStartedAt: number | null = null;\r\n const enforceMinSpeechDuration = accessibilityMode;\r\n\r\n vadIntervalRef.current = window.setInterval(() => {\r\n if (!isRecordingRef.current || recorder.state === \"inactive\") {\r\n cleanupVAD();\r\n return;\r\n }\r\n\r\n analyser.getByteFrequencyData(dataArray);\r\n\r\n let sum = 0;\r\n for (const value of dataArray) {\r\n sum += value;\r\n }\r\n const average = sum / dataArray.length;\r\n const volume = average / 255;\r\n\r\n if (volume < VAD_THRESHOLD) {\r\n if (!speechDetected) {\r\n speechStartedAt = null;\r\n silenceStartRef.current = null;\r\n return;\r\n }\r\n\r\n if (silenceStartRef.current === null) {\r\n silenceStartRef.current = Date.now();\r\n return;\r\n }\r\n\r\n const silenceDuration = Date.now() - silenceStartRef.current;\r\n if (speechDetected && silenceDuration > SILENCE_DURATION_MS) {\r\n stopRecording();\r\n }\r\n return;\r\n }\r\n\r\n silenceStartRef.current = null;\r\n if (speechStartedAt === null) {\r\n speechStartedAt = Date.now();\r\n }\r\n\r\n if (!speechDetected) {\r\n const speechDuration = Date.now() - speechStartedAt;\r\n if (shouldAcceptVadSpeech(speechDuration, enforceMinSpeechDuration)) {\r\n speechDetected = true;\r\n if (enforceMinSpeechDuration) {\r\n setStatusOverride(STATUS_LABELS.listening);\r\n }\r\n }\r\n }\r\n }, 50);\r\n };\r\n\r\n const startRecording = async (mode: RecordingMode) => {\r\n if (\r\n isBusyRef.current ||\r\n isRecordingRef.current ||\r\n startRecordingPendingRef.current\r\n ) {\r\n return;\r\n }\r\n\r\n setStatusOverride(STATUS_LABELS.micInitializing);\r\n setIsMicPending(true);\r\n\r\n if (!navigator.mediaDevices?.getUserMedia) {\r\n setStatusOverride(null);\r\n setIsMicPending(false);\r\n appendMessage(\"Bu tarayıcıda mikrofon kullanılamıyor.\", false);\r\n return;\r\n }\r\n\r\n if (typeof MediaRecorder === \"undefined\") {\r\n setStatusOverride(null);\r\n setIsMicPending(false);\r\n appendMessage(\"Bu tarayıcıda MediaRecorder desteklenmiyor.\", false);\r\n return;\r\n }\r\n\r\n startRecordingPendingRef.current = true;\r\n\r\n try {\r\n const stream = await navigator.mediaDevices.getUserMedia({ audio: true });\r\n streamRef.current = stream;\r\n\r\n // Use low bitrate for speech — opus handles voice well at 16-24 kbps\r\n // and produces ~4-5x smaller payloads, speeding up the upload to fal.\r\n const recorderOptions: MediaRecorderOptions = {\r\n audioBitsPerSecond: 16_000,\r\n };\r\n\r\n // Prefer opus-in-ogg (smaller container) → opus-in-webm → browser default\r\n const preferredMimeTypes = [\r\n \"audio/ogg;codecs=opus\",\r\n \"audio/webm;codecs=opus\",\r\n \"audio/webm\",\r\n ];\r\n for (const mime of preferredMimeTypes) {\r\n if (MediaRecorder.isTypeSupported(mime)) {\r\n recorderOptions.mimeType = mime;\r\n break;\r\n }\r\n }\r\n\r\n const recorder = new MediaRecorder(stream, recorderOptions);\r\n recorderRef.current = recorder;\r\n audioChunksRef.current = [];\r\n clearLiveUserTranscriptionState();\r\n sttSendCuePlayedRef.current = false;\r\n\r\n const sttMimeType = (recorder.mimeType || recorderOptions.mimeType || \"audio/webm\")\r\n .split(\";\")[0]\r\n .trim() || \"audio/webm\";\r\n\r\n const sttWsController = startSttWebSocketStream(\r\n config.backendBaseUrl,\r\n {\r\n projectId: config.projectId,\r\n sessionId: sessionIdRef.current,\r\n language: \"tr\",\r\n mimeType: sttMimeType,\r\n },\r\n {\r\n onSessionId: (sid) => {\r\n if (!sid || sid === sessionIdRef.current) {\r\n return;\r\n }\r\n sessionIdRef.current = sid;\r\n if (typeof localStorage !== \"undefined\") {\r\n localStorage.setItem(SESSION_ID_KEY, sid);\r\n }\r\n },\r\n onPartial: ({ text }) => {\r\n if (!text.trim()) {\r\n return;\r\n }\r\n upsertLiveUserTranscription(text);\r\n },\r\n },\r\n );\r\n activeSttWsRef.current = sttWsController;\r\n\r\n recorder.ondataavailable = (event) => {\r\n if (event.data.size > 0) {\r\n audioChunksRef.current.push(event.data);\r\n if (activeSttWsRef.current) {\r\n void activeSttWsRef.current.pushChunk(event.data).catch((error) => {\r\n console.warn(\r\n `[Bulut] STT WS chunk send failed: ${error instanceof Error ? error.message : String(error)}`,\r\n );\r\n });\r\n }\r\n }\r\n };\r\n\r\n recorder.onerror = () => {\r\n appendMessage(\"Mikrofon kaydı sırasında bir hata oluştu.\", false);\r\n };\r\n\r\n recorder.onstop = async () => {\r\n setIsRecording(false);\r\n isRecordingRef.current = false;\r\n recordingModeRef.current = null;\r\n stopRecordingTimer();\r\n\r\n cleanupVAD();\r\n stopStreamTracks();\r\n\r\n const shouldDiscard = discardNextRecordingRef.current;\r\n discardNextRecordingRef.current = false;\r\n\r\n const blob = new Blob(audioChunksRef.current, {\r\n type: recorder.mimeType || \"audio/webm\",\r\n });\r\n audioChunksRef.current = [];\r\n\r\n const currentSttWs = activeSttWsRef.current;\r\n activeSttWsRef.current = null;\r\n\r\n if (shouldDiscard) {\r\n currentSttWs?.cancel();\r\n clearLiveUserTranscriptionState();\r\n setStatusOverride(null);\r\n return;\r\n }\r\n\r\n if (blob.size === 0) {\r\n currentSttWs?.cancel();\r\n clearLiveUserTranscriptionState();\r\n setStatusOverride(null);\r\n appendMessage(\"Ses kaydı alınamadı. Lütfen tekrar deneyin.\", false);\r\n return;\r\n }\r\n\r\n setIsTranscribing(true);\r\n setStatusOverride(STATUS_LABELS.transcribing);\r\n\r\n try {\r\n if (currentSttWs) {\r\n playSttSentCueOnce();\r\n const sttResult = await currentSttWs.stop();\r\n if (sttResult.session_id && sttResult.session_id !== sessionIdRef.current) {\r\n sessionIdRef.current = sttResult.session_id;\r\n if (typeof localStorage !== \"undefined\") {\r\n localStorage.setItem(SESSION_ID_KEY, sttResult.session_id);\r\n }\r\n }\r\n if (sttResult.text.trim()) {\r\n upsertLiveUserTranscription(sttResult.text);\r\n setStatusOverride(STATUS_LABELS.thinking);\r\n await runAgentForUserText(sttResult.text);\r\n return;\r\n }\r\n }\r\n } catch (error) {\r\n console.warn(\r\n `[Bulut] STT WS finalization failed, falling back to HTTP POST /chat/stt: ${error instanceof Error ? error.message : String(error)}`,\r\n );\r\n } finally {\r\n clearLiveUserTranscriptionState();\r\n }\r\n\r\n console.info(\"[Bulut] Using HTTP POST fallback for STT (streaming WS did not succeed)\");\r\n setStatusOverride(STATUS_LABELS.thinking);\r\n await handleAudioBlob(blob);\r\n };\r\n\r\n if (mode === \"vad\") {\r\n setupVAD(stream, recorder);\r\n }\r\n\r\n recorder.start(200);\r\n recordingModeRef.current = mode;\r\n setIsRecording(true);\r\n isRecordingRef.current = true;\r\n startRecordingTimer();\r\n\r\n setStatusOverride(\r\n accessibilityMode && mode === \"vad\"\r\n ? STATUS_LABELS.accessibilityActive\r\n : STATUS_LABELS.listening,\r\n );\r\n\r\n if (pendingStopAfterStartRef.current) {\r\n pendingStopAfterStartRef.current = false;\r\n stopRecording();\r\n }\r\n } catch (error) {\r\n const errMsg = normalizeError(error);\r\n if (errMsg.toLowerCase().includes(\"permission\") || errMsg.toLowerCase().includes(\"denied\")) {\r\n autoListenSuppressedRef.current = true;\r\n }\r\n cancelActiveSttWs();\r\n setStatusOverride(null);\r\n appendMessage(`Mikrofon hatası: ${errMsg}`, false);\r\n cleanupVAD();\r\n stopStreamTracks();\r\n pendingStopAfterStartRef.current = false;\r\n setIsRecording(false);\r\n isRecordingRef.current = false;\r\n stopRecordingTimer();\r\n } finally {\r\n if (!isRecordingRef.current && !isBusyRef.current) {\r\n setStatusOverride(null);\r\n }\r\n startRecordingPendingRef.current = false;\r\n setIsMicPending(false);\r\n }\r\n };\r\n\r\n const resetMicGesture = () => {\r\n micPressStartRef.current = null;\r\n micHoldTriggeredRef.current = false;\r\n clearMicHoldTimeout();\r\n };\r\n\r\n const handleMicPointerDown = (\r\n event: JSX.TargetedPointerEvent<HTMLButtonElement>,\r\n ) => {\r\n event.preventDefault();\r\n\r\n if (isBusyRef.current) {\r\n return;\r\n }\r\n\r\n if (isRecordingRef.current) {\r\n // In VAD mode, tapping the button cancels; in press mode, it sends\r\n if (recordingModeRef.current === \"vad\") {\r\n stopRecording({ discard: true });\r\n } else {\r\n stopRecording();\r\n }\r\n return;\r\n }\r\n\r\n micPressStartRef.current = Date.now();\r\n micHoldTriggeredRef.current = false;\r\n clearMicHoldTimeout();\r\n\r\n if (event.currentTarget.setPointerCapture) {\r\n try {\r\n event.currentTarget.setPointerCapture(event.pointerId);\r\n } catch {\r\n // No-op.\r\n }\r\n }\r\n\r\n micHoldTimeoutRef.current = window.setTimeout(() => {\r\n if (\r\n micPressStartRef.current === null ||\r\n isBusyRef.current ||\r\n isRecordingRef.current\r\n ) {\r\n return;\r\n }\r\n\r\n micHoldTriggeredRef.current = true;\r\n void startRecording(\"press\");\r\n }, HOLD_THRESHOLD_MS);\r\n };\r\n\r\n const handleMicPointerUp = (\r\n event: JSX.TargetedPointerEvent<HTMLButtonElement>,\r\n ) => {\r\n event.preventDefault();\r\n\r\n if (event.currentTarget.releasePointerCapture) {\r\n try {\r\n event.currentTarget.releasePointerCapture(event.pointerId);\r\n } catch {\r\n // No-op.\r\n }\r\n }\r\n\r\n const startedAt = micPressStartRef.current;\r\n const wasHold = micHoldTriggeredRef.current;\r\n resetMicGesture();\r\n\r\n if (startedAt === null) {\r\n return;\r\n }\r\n\r\n if (wasHold) {\r\n if (isRecordingRef.current) {\r\n stopRecording();\r\n } else if (startRecordingPendingRef.current) {\r\n pendingStopAfterStartRef.current = true;\r\n }\r\n return;\r\n }\r\n\r\n const duration = Date.now() - startedAt;\r\n if (classifyMicGesture(duration) === \"tap\") {\r\n void startRecording(\"vad\");\r\n }\r\n };\r\n\r\n const handleMicPointerCancel = (\r\n event: JSX.TargetedPointerEvent<HTMLButtonElement>,\r\n ) => {\r\n handleMicPointerUp(event);\r\n };\r\n\r\n const handleRestart = () => {\r\n invalidateRequestEpoch();\r\n sttSendCuePlayedRef.current = false;\r\n resetMicGesture();\r\n pendingStopAfterStartRef.current = false;\r\n\r\n stopActiveStream();\r\n stopActiveAudioPlayback();\r\n cancelActiveSttWs();\r\n\r\n if (recorderRef.current && recorderRef.current.state !== \"inactive\") {\r\n stopRecording({ discard: true });\r\n } else {\r\n discardNextRecordingRef.current = false;\r\n cleanupVAD();\r\n stopStreamTracks();\r\n }\r\n\r\n stopRecordingTimer();\r\n setRecordingDurationMs(0);\r\n\r\n clearPersistedChatState(\r\n typeof localStorage !== \"undefined\" ? localStorage : null,\r\n );\r\n\r\n sessionIdRef.current = null;\r\n const initialMessages = createInitialMessages(config.agentName);\r\n nextMessageIdRef.current = getNextMessageId(initialMessages);\r\n setMessages(initialMessages);\r\n\r\n setIsBusy(false);\r\n isBusyRef.current = false;\r\n setIsRecording(false);\r\n isRecordingRef.current = false;\r\n resetProcessingFlags();\r\n };\r\n\r\n // Auto-listen when accessibility mode is activated (initial trigger)\r\n useEffect(() => {\r\n if (!accessibilityMode || autoListenSuppressedRef.current) return;\r\n const timer = window.setTimeout(() => {\r\n if (!isRecordingRef.current && !isBusyRef.current && !startRecordingPendingRef.current && !autoListenSuppressedRef.current) {\r\n void startRecording(\"vad\");\r\n }\r\n }, 500);\r\n return () => window.clearTimeout(timer);\r\n }, [accessibilityMode]); // eslint-disable-line react-hooks/exhaustive-deps\r\n\r\n const stopTask = () => {\r\n invalidateRequestEpoch();\r\n sttSendCuePlayedRef.current = false;\r\n stopActiveStream();\r\n stopActiveAudioPlayback();\r\n cancelActiveSttWs();\r\n stopRecording({ discard: true });\r\n cleanupVAD();\r\n stopStreamTracks();\r\n resetProcessingFlags();\r\n setIsBusy(false);\r\n isBusyRef.current = false;\r\n };\r\n\r\n // Expose recording actions to parent via actionsRef\r\n if (actionsRef) {\r\n actionsRef.current = {\r\n startRecording: () => {\r\n autoListenSuppressedRef.current = false;\r\n void startRecording(\"vad\");\r\n },\r\n cancelRecording: () => {\r\n stopActiveAudioPlayback();\r\n cancelActiveSttWs();\r\n const recorder = recorderRef.current;\r\n if (recorder && recorder.state !== \"inactive\") {\r\n stopRecording({ discard: true });\r\n } else {\r\n cleanupVAD();\r\n stopStreamTracks();\r\n }\r\n },\r\n stopTask,\r\n };\r\n }\r\n\r\n const windowStyle: { [key: string]: string } = {\r\n position: \"fixed\",\r\n bottom: `${POSITION_BOTTOM}px`,\r\n right: `${POSITION_RIGHT}px`,\r\n width: `${WINDOW_WIDTH}px`,\r\n maxHeight: `${WINDOW_HEIGHT}px`,\r\n backgroundColor: \"hsla(0, 0%, 100%, 1)\",\r\n borderRadius: BORDER_RADIUS.window,\r\n display: hidden ? \"none\" : \"flex\",\r\n flexDirection: \"column\",\r\n overflow: \"hidden\",\r\n zIndex: \"10000\",\r\n animation: hidden ? \"none\" : `slideIn ${TRANSITIONS.medium}`,\r\n boxShadow: accessibilityMode\r\n ? `inset 0 0 0 2px ${COLORS.primary}, ${SHADOW}`\r\n : SHADOW,\r\n fontFamily: \"\\\"Geist\\\", sans-serif\",\r\n };\r\n\r\n const headerStyle: { [key: string]: string } = {\r\n padding: \"14px 16px\",\r\n display: \"flex\",\r\n justifyContent: \"space-between\",\r\n alignItems: \"center\",\r\n };\r\n\r\n const headerActionsStyle: { [key: string]: string } = {\r\n display: \"flex\",\r\n alignItems: \"center\",\r\n gap: \"6px\",\r\n };\r\n\r\n const headerButtonStyle: { [key: string]: string } = {\r\n background: \"none\",\r\n border: \"none\",\r\n cursor: \"pointer\",\r\n padding: \"4px\",\r\n borderRadius: \"6px\",\r\n color: COLORS.text,\r\n display: \"flex\",\r\n alignItems: \"center\",\r\n justifyContent: \"center\",\r\n transition: `color ${TRANSITIONS.fast}, background-color ${TRANSITIONS.fast}`,\r\n };\r\n\r\n const messagesContainerStyle: { [key: string]: string } = {\r\n padding: \"0px 16px\",\r\n overflowY: \"auto\",\r\n flex: \"1\",\r\n minHeight: \"0\",\r\n };\r\n\r\n const messagesListStyle: { [key: string]: string } = {\r\n display: \"flex\",\r\n flexDirection: \"column\",\r\n gap: \"16px\",\r\n };\r\n\r\n const messageStyle = (isUser: boolean): JSX.CSSProperties => ({\r\n maxWidth: \"84%\",\r\n padding: isUser ? \"9px 14px\" : \"0px 0px\",\r\n borderRadius: BORDER_RADIUS.message,\r\n fontSize: \"14px\",\r\n lineHeight: \"140%\",\r\n wordWrap: \"break-word\",\r\n whiteSpace: \"pre-wrap\",\r\n alignSelf: isUser ? \"flex-end\" : \"flex-start\",\r\n backgroundColor: isUser ? COLORS.messageUser : \"\",\r\n color: isUser ? COLORS.messageUserText : \"hsla(215, 100%, 5%, 1)\",\r\n });\r\n\r\n const resolveToolIconSrc = (kind: Message[\"toolKind\"]): string => {\r\n if (kind === \"cursor\") {\r\n return cursorArrowRaysIconContent;\r\n }\r\n if (kind === \"scroll\") {\r\n return handRaisedIconContent;\r\n }\r\n if (kind === \"navigate\") {\r\n return mapIconContent;\r\n }\r\n if (kind === \"form\") {\r\n return queueListIconContent;\r\n }\r\n if (kind === \"interact\") {\r\n return handRaisedIconContent;\r\n }\r\n if (kind === \"unknown\") {\r\n return commandLineIconContent;\r\n }\r\n return faceSmileIconContent;\r\n };\r\n\r\n const footerStyle: { [key: string]: string } = {\r\n padding: \"10px 12px\",\r\n display: \"flex\",\r\n alignItems: \"center\",\r\n justifyContent: \"space-between\",\r\n gap: \"8px\",\r\n };\r\n\r\n const statusPanelStyle: { [key: string]: string } = {\r\n flex: \"1\",\r\n minHeight: \"34px\",\r\n borderRadius: \"10px\",\r\n color: COLORS.text,\r\n fontSize: \"14px\",\r\n display: \"flex\",\r\n alignItems: \"center\",\r\n padding: \"0 10px\",\r\n whiteSpace: \"nowrap\",\r\n overflow: \"hidden\",\r\n textOverflow: \"ellipsis\",\r\n opacity: \"0.7\",\r\n };\r\n\r\n const footerActionsStyle: { [key: string]: string } = {\r\n display: \"flex\",\r\n alignItems: \"center\",\r\n gap: \"8px\",\r\n flexShrink: \"0\",\r\n };\r\n\r\n const recordingTimerStyle: { [key: string]: string } = {\r\n minWidth: \"46px\",\r\n fontSize: \"12px\",\r\n fontWeight: \"700\",\r\n color: COLORS.text,\r\n textAlign: \"right\",\r\n };\r\n\r\n const micFooterButtonStyle: { [key: string]: string } = {\r\n width: \"37px\",\r\n height: \"37px\",\r\n borderRadius: \"999px\",\r\n background: \"transparent\",\r\n display: \"flex\",\r\n alignItems: \"center\",\r\n justifyContent: \"center\",\r\n cursor: \"pointer\",\r\n color: \"#ffffff\",\r\n border: \"1px solid hsla(215, 100%, 5%, 0.5)\",\r\n transition: `transform ${TRANSITIONS.fast}`,\r\n };\r\n\r\n const isVadRecording = isRecording && recordingModeRef.current === \"vad\";\r\n const showStopButton = isBusy && !isRecording;\r\n const hideMicButton = isMicPending && !isRecording;\r\n const disableMicControl = isBusy;\r\n\r\n return (\r\n <div className=\"bulut-chat-window\" style={windowStyle}>\r\n <style>{`\r\n @keyframes slideIn {\r\n from {\r\n opacity: 0;\r\n transform: translateY(10px);\r\n }\r\n to {\r\n opacity: 1;\r\n transform: translateY(0);\r\n }\r\n }\r\n\r\n .bulut-header-btn:hover:not(:disabled) {\r\n color: ${COLORS.text};\r\n }\r\n\r\n .bulut-footer-btn:hover:not(:disabled) {\r\n transform: scale(1.04);\r\n }\r\n\r\n .bulut-header-btn:disabled,\r\n .bulut-footer-btn:disabled {\r\n cursor: not-allowed;\r\n opacity: 0.5;\r\n transform: none;\r\n }\r\n\r\n @keyframes bulut-dots {\r\n 0% { content: '.'; }\r\n 33% { content: '..'; }\r\n 66% { content: '...'; }\r\n }\r\n\r\n .bulut-status-dots::after {\r\n content: '.';\r\n animation: bulut-dots 1.2s steps(1) infinite;\r\n display: inline-block;\r\n min-width: 12px;\r\n text-align: left;\r\n }\r\n\r\n /* Mobile: full-screen chat window */\r\n @media (max-width: 600px) {\r\n .bulut-chat-window {\r\n top: 0 !important;\r\n left: 0 !important;\r\n right: 0 !important;\r\n bottom: 0 !important;\r\n width: 100% !important;\r\n max-height: 100% !important;\r\n height: 100% !important;\r\n border-radius: 0 !important;\r\n }\r\n .bulut-close-btn {\r\n width: 40px !important;\r\n height: 40px !important;\r\n padding: 8px !important;\r\n }\r\n .bulut-close-btn svg {\r\n width: 26px !important;\r\n height: 26px !important;\r\n }\r\n }\r\n `}</style>\r\n\r\n <div style={headerStyle}>\r\n <div style={{ display: \"flex\", alignItems: \"center\", gap: \"6px\" }}>\r\n <SvgIcon\r\n src={logoContent}\r\n title=\"Bulut Logo\"\r\n style={{ width: \"80px\", minWidth: \"80px\", height: \"auto\", flexShrink: 0 }}\r\n stripColors={false}\r\n />\r\n <span\r\n style={{\r\n marginTop: \"7px\",\r\n fontSize: \"9px\",\r\n color: COLORS.textSecondary,\r\n opacity: 0.45,\r\n fontWeight: 400,\r\n letterSpacing: \"0.02em\",\r\n userSelect: \"none\",\r\n whiteSpace: \"nowrap\",\r\n alignSelf: \"flex-end\",\r\n }}\r\n >\r\n v{typeof __BULUT_VERSION__ !== \"undefined\" ? __BULUT_VERSION__ : \"\"}\r\n </span>\r\n </div>\r\n <div style={headerActionsStyle}>\r\n <button\r\n type=\"button\"\r\n className=\"bulut-header-btn\"\r\n style={headerButtonStyle}\r\n onClick={handleRestart}\r\n aria-label=\"Sohbeti yeniden başlat\"\r\n title=\"Sohbeti yeniden başlat\"\r\n >\r\n <SvgIcon src={arrowPathIconContent} aria-hidden=\"true\" width={22} height={22} />\r\n </button>\r\n\r\n <button\r\n type=\"button\"\r\n className=\"bulut-header-btn bulut-close-btn\"\r\n style={{\r\n ...headerButtonStyle,\r\n display: \"flex\",\r\n alignItems: \"center\",\r\n justifyContent: \"center\",\r\n }}\r\n onClick={onClose}\r\n aria-label=\"Sohbeti kapat\"\r\n title=\"Sohbeti kapat\"\r\n >\r\n <SvgIcon src={xMarkIconContent} aria-hidden=\"true\" width={22} height={22} />\r\n </button>\r\n </div>\r\n </div>\r\n\r\n <div style={messagesContainerStyle} ref={messagesContainerRef}>\r\n <div style={messagesListStyle} ref={messagesContentRef}>\r\n {messages.map((message) => {\r\n if (message.type === \"tool\") {\r\n const toolIconSrc = resolveToolIconSrc(message.toolKind);\r\n return (\r\n <div\r\n key={message.id}\r\n style={{\r\n ...messageStyle(false),\r\n opacity: \"0.7\",\r\n display: \"flex\",\r\n alignItems: \"center\",\r\n gap: \"8px\",\r\n }}\r\n >\r\n <SvgIcon\r\n src={toolIconSrc}\r\n aria-hidden=\"true\"\r\n width={20}\r\n height={20}\r\n style={{ flexShrink: 0 }}\r\n />\r\n <span>{message.text}</span>\r\n </div>\r\n );\r\n }\r\n\r\n return (\r\n <div key={message.id} style={messageStyle(message.isUser)}>\r\n {message.text}\r\n </div>\r\n );\r\n })}\r\n </div>\r\n </div>\r\n\r\n <div style={footerStyle}>\r\n <div style={{ ...statusPanelStyle, transition: \"opacity 0.2s ease-out\" }}>\r\n {showStatus ? (\r\n <span className=\"bulut-status-dots\" title={statusText}>\r\n {statusText}\r\n </span>\r\n ) : onAccessibilityToggle ? (\r\n <div\r\n style={{\r\n display: \"flex\",\r\n alignItems: \"center\",\r\n gap: \"8px\",\r\n }}\r\n >\r\n <span\r\n style={{\r\n fontSize: \"12px\",\r\n opacity: \"0.6\",\r\n whiteSpace: \"nowrap\",\r\n }}\r\n >\r\n Erişilebilirlik\r\n </span>\r\n <button\r\n type=\"button\"\r\n onClick={onAccessibilityToggle}\r\n aria-label={\r\n accessibilityMode\r\n ? \"Erişilebilirlik modunu kapat\"\r\n : \"Erişilebilirlik modunu aç\"\r\n }\r\n style={{\r\n width: \"36px\",\r\n height: \"20px\",\r\n borderRadius: \"10px\",\r\n border: \"none\",\r\n cursor: \"pointer\",\r\n padding: \"2px\",\r\n display: \"flex\",\r\n alignItems: \"center\",\r\n backgroundColor: accessibilityMode\r\n ? COLORS.primary\r\n : \"hsla(215, 10%, 75%, 1)\",\r\n transition: `background-color ${TRANSITIONS.fast}`,\r\n flexShrink: \"0\",\r\n }}\r\n >\r\n <span\r\n style={{\r\n width: \"16px\",\r\n height: \"16px\",\r\n borderRadius: \"50%\",\r\n backgroundColor: \"#ffffff\",\r\n display: \"block\",\r\n transition: `transform ${TRANSITIONS.fast}`,\r\n transform: accessibilityMode\r\n ? \"translateX(16px)\"\r\n : \"translateX(0)\",\r\n boxShadow: \"0 1px 3px rgba(0,0,0,0.2)\",\r\n }}\r\n />\r\n </button>\r\n </div>\r\n ) : null}\r\n </div>\r\n\r\n <div style={footerActionsStyle}>\r\n {isRecording ? (\r\n <span style={recordingTimerStyle}>\r\n {formatDurationMs(recordingDurationMs)}\r\n </span>\r\n ) : null}\r\n {showStopButton ? (\r\n <button\r\n type=\"button\"\r\n className=\"bulut-footer-btn\"\r\n style={micFooterButtonStyle}\r\n onClick={stopTask}\r\n aria-label=\"Görevi durdur\"\r\n title=\"Görevi durdur\"\r\n >\r\n <SvgIcon\r\n src={stopOutlineIconContent}\r\n aria-hidden=\"true\"\r\n width={22}\r\n height={22}\r\n style={{ color: \"hsla(215, 100%, 5%, 1)\" }}\r\n />\r\n </button>\r\n ) : hideMicButton ? null : (\r\n <button\r\n type=\"button\"\r\n className=\"bulut-footer-btn\"\r\n style={micFooterButtonStyle}\r\n onPointerDown={handleMicPointerDown}\r\n onPointerUp={handleMicPointerUp}\r\n onPointerCancel={handleMicPointerCancel}\r\n disabled={disableMicControl}\r\n aria-label={isVadRecording ? \"Kaydı iptal et\" : isRecording ? \"Kaydı durdur\" : \"Kaydı başlat\"}\r\n title={\r\n isVadRecording\r\n ? \"Kaydı iptal et\"\r\n : isRecording\r\n ? \"Kaydı durdur\"\r\n : \"Dokun: VAD, Basılı tut: bırakınca gönder\"\r\n }\r\n >\r\n {isVadRecording ? (\r\n <SvgIcon\r\n src={xMarkIconContent}\r\n aria-hidden=\"true\"\r\n width={22}\r\n height={22}\r\n style={{ color: \"hsla(215, 100%, 5%, 1)\"}}\r\n />\r\n ) : (\r\n <SvgIcon\r\n src={microphoneOutlineIconContent}\r\n aria-hidden=\"true\"\r\n width={22}\r\n height={22}\r\n style={{ color: \"hsla(215, 100%, 5%, 1)\" }}\r\n />\r\n )}\r\n </button>\r\n )}\r\n </div>\r\n </div>\r\n </div>\r\n );\r\n};\r\n","export default \"<svg width=\\\"2420\\\" height=\\\"438\\\" viewBox=\\\"0 0 2420 438\\\" fill=\\\"none\\\" xmlns=\\\"http://www.w3.org/2000/svg\\\">\\r\\n<path d=\\\"M251.823 0C313.458 0 366.34 37.767 388.932 91.5918C409.253 75.8883 434.678 66.5567 462.264 66.5566C528.885 66.5567 582.893 120.989 582.893 188.134C582.893 188.786 582.885 189.436 582.875 190.086C648.144 193.552 700 247.572 700 313.704C700 382.074 644.575 437.5 576.204 437.5H123.796C55.4255 437.5 7.42386e-05 382.074 0 313.704C0 250.475 47.4025 198.32 108.608 190.833C104.967 177.844 103.019 164.138 103.019 149.975C103.019 67.1461 169.641 0.000357483 251.823 0ZM234.696 141.93C218.117 134.066 199 146.158 199 164.507C199 174.32 204.744 183.225 213.684 187.271L336.761 242.985C337.971 243.533 338.748 244.738 338.748 246.066C338.748 247.394 337.971 248.6 336.761 249.147L213.684 304.861C204.744 308.908 199 317.812 199 327.625C199 345.974 218.117 358.066 234.696 350.202L364.672 288.554C375.142 283.588 381.815 273.036 381.815 261.448V230.684C381.815 219.096 375.142 208.544 364.672 203.578L234.696 141.93ZM413.877 296.146C402.078 296.146 392.513 305.711 392.513 317.511C392.513 329.31 402.078 338.875 413.877 338.875H526.636C538.435 338.875 548 329.31 548 317.511C548 305.711 538.435 296.146 526.636 296.146H413.877Z\\\" fill=\\\"#000B1A\\\"/>\\r\\n<path d=\\\"M2420 424.954H2343.35C2307.08 424.954 2278.64 416.094 2258.04 398.373C2237.43 380.652 2227.13 352.216 2227.13 313.065V55.2871H2319.86V302.556C2319.86 318.217 2323.15 328.726 2329.75 334.083C2336.75 339.028 2348.29 341.501 2364.36 341.501H2420V424.954ZM2420 191.903H2178.29V115.25H2420V191.903Z\\\" fill=\\\"#000B1A\\\"/>\\r\\n<path d=\\\"M1923.18 431.136C1894.33 431.136 1870.22 425.779 1850.85 415.064C1831.89 403.937 1817.68 389.101 1808.2 370.555C1799.13 352.01 1794.6 331.198 1794.6 308.12V115.25H1887.32V277.211C1887.32 301.938 1893.3 320.071 1905.25 331.61C1917.2 342.738 1937.81 348.301 1967.07 348.301C1997.56 348.301 2018.79 342.325 2030.74 330.374C2043.1 318.011 2049.28 298.641 2049.28 272.266L2061.03 271.648L2067.83 330.374H2050.52C2048.05 347.683 2041.87 363.962 2031.98 379.21C2022.5 394.458 2008.69 407.028 1990.56 416.918C1972.84 426.397 1950.38 431.136 1923.18 431.136ZM2142.01 424.955H2055.47V329.138L2049.28 326.047V115.25H2142.01V424.955Z\\\" fill=\\\"#000B1A\\\"/>\\r\\n<path d=\\\"M1734.32 424.955H1641.59V10.7793H1734.32V424.955Z\\\" fill=\\\"#000B1A\\\"/>\\r\\n<path d=\\\"M1362.98 431.136C1334.13 431.136 1310.03 425.779 1290.66 415.064C1271.7 403.937 1257.48 389.101 1248 370.555C1238.94 352.01 1234.4 331.198 1234.4 308.12V115.25H1327.13V277.211C1327.13 301.938 1333.1 320.071 1345.06 331.61C1357.01 342.738 1377.61 348.301 1406.87 348.301C1437.37 348.301 1458.59 342.325 1470.54 330.374C1482.91 318.011 1489.09 298.641 1489.09 272.266L1500.83 271.648L1507.63 330.374H1490.33C1487.85 347.683 1481.67 363.962 1471.78 379.21C1462.3 394.458 1448.5 407.028 1430.36 416.918C1412.64 426.397 1390.18 431.136 1362.98 431.136ZM1581.82 424.955H1495.27V329.138L1489.09 326.047V115.25H1581.82V424.955Z\\\" fill=\\\"#000B1A\\\"/>\\r\\n<path d=\\\"M1035.12 431.137C999.27 431.137 971.04 423.513 950.434 408.264C930.241 392.604 917.259 369.526 911.49 339.029H894.181L900.981 272.266H912.726C912.726 289.987 916.023 304.411 922.617 315.538C929.623 326.253 939.719 334.084 952.907 339.029C966.507 343.974 983.198 346.447 1002.98 346.447C1023.17 346.447 1039.66 343.974 1052.43 339.029C1065.21 334.084 1074.69 326.047 1080.87 314.92C1087.05 303.793 1090.14 288.957 1090.14 270.412C1090.14 251.042 1087.05 236 1080.87 225.285C1074.69 214.158 1065.21 206.122 1052.43 201.177C1039.66 196.231 1023.38 193.758 1003.6 193.758C973.513 193.758 950.847 199.322 935.598 210.449C920.35 221.576 912.726 240.533 912.726 267.321H900.981V197.467H917.671C923.029 171.504 935.392 150.28 954.762 133.796C974.543 117.311 1002.77 109.069 1039.45 109.069C1070.36 109.069 1096.53 115.663 1117.96 128.85C1139.39 142.038 1155.67 160.789 1166.79 185.104C1178.33 209.007 1184.1 237.443 1184.1 270.412C1184.1 302.969 1178.33 331.405 1166.79 355.72C1155.67 379.622 1138.98 398.168 1116.72 411.355C1094.47 424.543 1067.27 431.137 1035.12 431.137ZM905.926 424.955H820V10.7793H912.726V325.429L905.926 333.465V424.955Z\\\" fill=\\\"#000B1A\\\"/>\\r\\n</svg>\\r\\n\"","export default \"<svg xmlns=\\\"http://www.w3.org/2000/svg\\\" fill=\\\"none\\\" viewBox=\\\"0 0 24 24\\\" stroke-width=\\\"1.5\\\" stroke=\\\"currentColor\\\">\\r\\n <path stroke-linecap=\\\"round\\\" stroke-linejoin=\\\"round\\\" d=\\\"M16.023 9.348h4.992v-.001M2.985 19.644v-4.992m0 0h4.992m-4.993 0 3.181 3.183a8.25 8.25 0 0 0 13.803-3.7M4.031 9.865a8.25 8.25 0 0 1 13.803-3.7l3.181 3.182m0-4.991v4.99\\\" />\\r\\n</svg>\\r\\n\"","export default \"<svg xmlns=\\\"http://www.w3.org/2000/svg\\\" fill=\\\"none\\\" viewBox=\\\"0 0 24 24\\\" stroke-width=\\\"1.5\\\" stroke=\\\"currentColor\\\">\\r\\n <path stroke-linecap=\\\"round\\\" stroke-linejoin=\\\"round\\\" d=\\\"M15.042 21.672 13.684 16.6m0 0-2.51 2.225.569-9.47 5.227 7.917-3.286-.672ZM12 2.25V4.5m5.834.166-1.591 1.591M20.25 10.5H18M7.757 14.743l-1.59 1.59M6 10.5H3.75m4.007-4.243-1.59-1.59\\\" />\\r\\n</svg>\\r\\n\"","export default \"<svg xmlns=\\\"http://www.w3.org/2000/svg\\\" fill=\\\"none\\\" viewBox=\\\"0 0 24 24\\\" stroke-width=\\\"1.5\\\" stroke=\\\"currentColor\\\">\\r\\n <path stroke-linecap=\\\"round\\\" stroke-linejoin=\\\"round\\\" d=\\\"M9 6.75V15m6-6v8.25m.503 3.498 4.875-2.437c.381-.19.622-.58.622-1.006V4.82c0-.836-.88-1.38-1.628-1.006l-3.869 1.934c-.317.159-.69.159-1.006 0L9.503 3.252a1.125 1.125 0 0 0-1.006 0L3.622 5.689C3.24 5.88 3 6.27 3 6.695V19.18c0 .836.88 1.38 1.628 1.006l3.869-1.934c.317-.159.69-.159 1.006 0l4.994 2.497c.317.158.69.158 1.006 0Z\\\" />\\r\\n</svg>\\r\\n\"","export default \"<svg xmlns=\\\"http://www.w3.org/2000/svg\\\" fill=\\\"none\\\" viewBox=\\\"0 0 24 24\\\" stroke-width=\\\"1.5\\\" stroke=\\\"currentColor\\\">\\r\\n <path stroke-linecap=\\\"round\\\" stroke-linejoin=\\\"round\\\" d=\\\"M3.75 12h16.5m-16.5 3.75h16.5M3.75 19.5h16.5M5.625 4.5h12.75a1.875 1.875 0 0 1 0 3.75H5.625a1.875 1.875 0 0 1 0-3.75Z\\\" />\\r\\n</svg>\\r\\n\"","export default \"<svg xmlns=\\\"http://www.w3.org/2000/svg\\\" fill=\\\"none\\\" viewBox=\\\"0 0 24 24\\\" stroke-width=\\\"1.5\\\" stroke=\\\"currentColor\\\">\\r\\n <path stroke-linecap=\\\"round\\\" stroke-linejoin=\\\"round\\\" d=\\\"m6.75 7.5 3 2.25-3 2.25m4.5 0h3m-9 8.25h13.5A2.25 2.25 0 0 0 21 18V6a2.25 2.25 0 0 0-2.25-2.25H5.25A2.25 2.25 0 0 0 3 6v12a2.25 2.25 0 0 0 2.25 2.25Z\\\" />\\r\\n</svg>\\r\\n\"","export default \"<svg xmlns=\\\"http://www.w3.org/2000/svg\\\" fill=\\\"none\\\" viewBox=\\\"0 0 24 24\\\" stroke-width=\\\"1.5\\\" stroke=\\\"currentColor\\\">\\r\\n <path stroke-linecap=\\\"round\\\" stroke-linejoin=\\\"round\\\" d=\\\"M15.182 15.182a4.5 4.5 0 0 1-6.364 0M21 12a9 9 0 1 1-18 0 9 9 0 0 1 18 0ZM9.75 9.75c0 .414-.168.75-.375.75S9 10.164 9 9.75 9.168 9 9.375 9s.375.336.375.75Zm-.375 0h.008v.015h-.008V9.75Zm5.625 0c0 .414-.168.75-.375.75s-.375-.336-.375-.75.168-.75.375-.75.375.336.375.75Zm-.375 0h.008v.015h-.008V9.75Z\\\" />\\r\\n</svg>\\r\\n\"","import { useState, useEffect, useRef, useCallback } from \"preact/hooks\";\r\nimport \"./globals.css\";\r\nimport { render } from \"preact\";\r\nimport { ChatButton } from \"./components/ChatButton\";\r\nimport {\r\n ChatWindow,\r\n type ChatWindowHandle,\r\n} from \"./components/ChatWindow\";\r\nimport { COLORS } from \"./styles/constants\";\r\n\r\nexport type BulutVoice = \"alloy\" | \"zeynep\" | \"ali\";\r\n\r\nexport interface BulutOptions {\r\n containerId?: string;\r\n backendBaseUrl?: string;\r\n projectId?: string;\r\n}\r\n\r\nexport interface BulutRuntimeConfig {\r\n backendBaseUrl: string;\r\n projectId: string;\r\n model: string;\r\n voice: BulutVoice;\r\n baseColor: string;\r\n agentName: string;\r\n}\r\n\r\n/** Default LLM model — keep in sync with backend config.DEFAULT_LLM_MODEL */\r\nconst DEFAULT_LLM_MODEL = \"x-ai/grok-4.1-fast\";\r\n\r\nconst DEFAULT_AGENT_NAME = \"Bulut\";\r\n\r\nconst DEFAULT_CONFIG: BulutRuntimeConfig = {\r\n backendBaseUrl: \"https://api.bulut.lu\",\r\n projectId: \"\", // Must be provided\r\n model: DEFAULT_LLM_MODEL,\r\n voice: \"alloy\",\r\n baseColor: COLORS.primary,\r\n agentName: DEFAULT_AGENT_NAME,\r\n};\r\n\r\nconst isValidHexColor = (value: string): boolean =>\r\n /^#([0-9a-fA-F]{3}|[0-9a-fA-F]{6})$/.test(value);\r\n\r\nconst normalizeHexColor = (value: string): string => {\r\n const trimmed = value.trim();\r\n if (!isValidHexColor(trimmed)) {\r\n return DEFAULT_CONFIG.baseColor;\r\n }\r\n if (trimmed.length === 4) {\r\n const r = trimmed[1];\r\n const g = trimmed[2];\r\n const b = trimmed[3];\r\n return `#${r}${r}${g}${g}${b}${b}`.toLowerCase();\r\n }\r\n return trimmed.toLowerCase();\r\n};\r\n\r\nconst shadeHexColor = (hexColor: string, amount: number): string => {\r\n const normalized = normalizeHexColor(hexColor);\r\n const raw = normalized.slice(1);\r\n const toChannel = (start: number): number => parseInt(raw.slice(start, start + 2), 16);\r\n const clamp = (value: number): number => Math.max(0, Math.min(255, Math.round(value)));\r\n const adjust = (channel: number): number =>\r\n amount < 0 ? channel * (1 + amount) : channel + (255 - channel) * amount;\r\n const toHex = (channel: number): string => clamp(channel).toString(16).padStart(2, \"0\");\r\n\r\n const r = adjust(toChannel(0));\r\n const g = adjust(toChannel(2));\r\n const b = adjust(toChannel(4));\r\n\r\n return `#${toHex(r)}${toHex(g)}${toHex(b)}`;\r\n};\r\n\r\nconst applyTheme = (baseColor: string): void => {\r\n const normalized = normalizeHexColor(baseColor);\r\n COLORS.primary = normalized;\r\n COLORS.primaryHover = shadeHexColor(normalized, -0.15);\r\n COLORS.messageUser = normalized;\r\n};\r\n\r\ninterface RemoteProjectConfig {\r\n base_color: string;\r\n model: string;\r\n agent_name: string;\r\n voice: string;\r\n}\r\n\r\nconst fetchRemoteConfig = async (\r\n baseUrl: string,\r\n projectId: string,\r\n): Promise<RemoteProjectConfig | null> => {\r\n try {\r\n const url = baseUrl.replace(/\\/+$/, \"\");\r\n const res = await fetch(`${url}/projects/${projectId}/config`);\r\n if (!res.ok) return null;\r\n return (await res.json()) as RemoteProjectConfig;\r\n } catch {\r\n return null;\r\n }\r\n};\r\n\r\nconst resolveRuntimeConfig = (\r\n options: BulutOptions,\r\n): BulutRuntimeConfig => ({\r\n backendBaseUrl: options.backendBaseUrl || DEFAULT_CONFIG.backendBaseUrl,\r\n projectId: options.projectId || DEFAULT_CONFIG.projectId,\r\n model: DEFAULT_CONFIG.model,\r\n voice: DEFAULT_CONFIG.voice,\r\n baseColor: DEFAULT_CONFIG.baseColor,\r\n agentName: DEFAULT_CONFIG.agentName,\r\n});\r\n\r\ninterface BulutWidgetProps {\r\n config: BulutRuntimeConfig;\r\n}\r\n\r\nconst ACCESSIBILITY_MODE_KEY = \"bulut_accessibility_mode_enabled\";\r\nconst GEIST_FONT_FAMILY = \"Geist\";\r\nconst GEIST_STYLESHEET_ID = \"bulut-geist-font-stylesheet\";\r\nconst GEIST_STYLESHEET_URL =\r\n \"https://fonts.googleapis.com/css2?family=Geist:wght@100..900&display=swap\";\r\n\r\nconst ensureGeistStylesheet = (): void => {\r\n if (typeof document === \"undefined\") {\r\n return;\r\n }\r\n if (document.getElementById(GEIST_STYLESHEET_ID)) {\r\n return;\r\n }\r\n const link = document.createElement(\"link\");\r\n link.id = GEIST_STYLESHEET_ID;\r\n link.rel = \"stylesheet\";\r\n link.href = GEIST_STYLESHEET_URL;\r\n document.head.appendChild(link);\r\n};\r\n\r\nconst BulutWidget = ({ config }: BulutWidgetProps) => {\r\n // Live config that merges remote settings over initial config\r\n const [liveConfig, setLiveConfig] = useState<BulutRuntimeConfig>(config);\r\n const [configReady, setConfigReady] = useState(false);\r\n\r\n // Fetch remote project config on mount — widget stays hidden until done\r\n useEffect(() => {\r\n if (!config.projectId) {\r\n setConfigReady(true);\r\n return;\r\n }\r\n let cancelled = false;\r\n\r\n fetchRemoteConfig(config.backendBaseUrl, config.projectId).then((remote) => {\r\n if (cancelled) return;\r\n if (remote) {\r\n const merged: BulutRuntimeConfig = {\r\n ...config,\r\n baseColor: normalizeHexColor(remote.base_color || config.baseColor),\r\n model: remote.model || config.model,\r\n agentName: remote.agent_name || config.agentName,\r\n voice: (\r\n remote.voice === \"alloy\" || remote.voice === \"zeynep\" || remote.voice === \"ali\"\r\n ? remote.voice\r\n : config.voice\r\n ) as BulutVoice,\r\n };\r\n applyTheme(merged.baseColor);\r\n setLiveConfig(merged);\r\n }\r\n setConfigReady(true);\r\n });\r\n\r\n return () => { cancelled = true; };\r\n }, [config]);\r\n\r\n // Check localStorage for persisted state\r\n const [isOpen, setIsOpen] = useState(() => {\r\n if (typeof localStorage !== \"undefined\") {\r\n return localStorage.getItem(\"bulut_panel_open\") === \"true\";\r\n }\r\n return false;\r\n });\r\n\r\n const [showBubble, setShowBubble] = useState(false);\r\n const [isAccessibilityEnabled, setIsAccessibilityEnabled] = useState(() => {\r\n if (typeof localStorage === \"undefined\") {\r\n return false;\r\n }\r\n return localStorage.getItem(ACCESSIBILITY_MODE_KEY) === \"true\";\r\n });\r\n\r\n // State reported by ChatWindow\r\n const [isRecording, setIsRecording] = useState(false);\r\n const [isBusy, setIsBusy] = useState(false);\r\n const [previewMessage, setPreviewMessage] = useState<string | null>(null);\r\n const [previewDismissed, setPreviewDismissed] = useState(false);\r\n\r\n // Ref for delegating recording to ChatWindow\r\n const chatActionsRef = useRef<ChatWindowHandle | null>(null);\r\n\r\n const handlePreviewChange = useCallback((text: string | null) => {\r\n setPreviewMessage(text);\r\n if (text !== null) setPreviewDismissed(false);\r\n }, []);\r\n\r\n // Show welcome bubble once for 5 seconds\r\n useEffect(() => {\r\n if (isAccessibilityEnabled) {\r\n setShowBubble(false);\r\n return;\r\n }\r\n if (isOpen) return;\r\n if (typeof localStorage !== \"undefined\") {\r\n if (localStorage.getItem(\"bulut_bubble_shown\") === \"true\") return;\r\n }\r\n\r\n setShowBubble(true);\r\n const timer = setTimeout(() => {\r\n setShowBubble(false);\r\n if (typeof localStorage !== \"undefined\") {\r\n localStorage.setItem(\"bulut_bubble_shown\", \"true\");\r\n }\r\n }, 5000);\r\n return () => clearTimeout(timer);\r\n }, [isOpen, isAccessibilityEnabled]);\r\n\r\n const toggleWidget = () => {\r\n const newState = !isOpen;\r\n setIsOpen(newState);\r\n setShowBubble(false);\r\n if (typeof localStorage !== \"undefined\") {\r\n localStorage.setItem(\"bulut_panel_open\", String(newState));\r\n }\r\n };\r\n\r\n const toggleAccessibilityMode = () => {\r\n const next = !isAccessibilityEnabled;\r\n setIsAccessibilityEnabled(next);\r\n if (typeof localStorage !== \"undefined\") {\r\n localStorage.setItem(ACCESSIBILITY_MODE_KEY, String(next));\r\n }\r\n console.info(`[Bulut] accessibility mode toggled enabled=${next}`);\r\n };\r\n\r\n const handleClose = () => {\r\n setIsOpen(false);\r\n if (typeof localStorage !== \"undefined\") {\r\n localStorage.setItem(\"bulut_panel_open\", \"false\");\r\n }\r\n console.info(\"Bulut chat window closed.\");\r\n };\r\n\r\n // Close on escape key\r\n useEffect(() => {\r\n const handleEscape = (e: KeyboardEvent) => {\r\n if (e.key === \"Escape\" && isOpen) {\r\n setIsOpen(false);\r\n if (typeof localStorage !== \"undefined\") {\r\n localStorage.setItem(\"bulut_panel_open\", \"false\");\r\n }\r\n }\r\n };\r\n\r\n document.addEventListener(\"keydown\", handleEscape);\r\n return () => document.removeEventListener(\"keydown\", handleEscape);\r\n }, [isOpen]);\r\n\r\n if (!configReady) return null;\r\n\r\n return (\r\n <>\r\n {!isOpen && (\r\n <ChatButton\r\n onMicClick={() => chatActionsRef.current?.startRecording()}\r\n onCancelRecording={() => chatActionsRef.current?.cancelRecording()}\r\n onStopTask={() => chatActionsRef.current?.stopTask()}\r\n isRecording={isRecording}\r\n isBusy={isBusy}\r\n accessibilityMode={isAccessibilityEnabled}\r\n showBubble={showBubble}\r\n onBubbleClick={() => {\r\n setShowBubble(false);\r\n toggleWidget();\r\n }}\r\n previewMessage={previewDismissed ? null : previewMessage}\r\n onPreviewClick={() => toggleWidget()}\r\n onPreviewClose={() => setPreviewDismissed(true)}\r\n />\r\n )}\r\n <ChatWindow\r\n onClose={handleClose}\r\n config={liveConfig}\r\n accessibilityMode={isAccessibilityEnabled}\r\n onAccessibilityToggle={toggleAccessibilityMode}\r\n hidden={!isOpen}\r\n actionsRef={chatActionsRef}\r\n onRecordingChange={setIsRecording}\r\n onBusyChange={setIsBusy}\r\n onPreviewChange={handlePreviewChange}\r\n />\r\n </>\r\n );\r\n};\r\n\r\nconst SHADOW_STYLE = `\r\n :host {\r\n all: initial;\r\n contain: layout style paint;\r\n font-family: \"${GEIST_FONT_FAMILY}\", sans-serif;\r\n color: hsla(215, 100%, 5%, 1);\r\n font-size: 16px;\r\n line-height: 1.4;\r\n -webkit-font-smoothing: antialiased;\r\n text-rendering: optimizeLegibility;\r\n }\r\n\r\n #bulut-shadow-mount {\r\n all: initial;\r\n color: inherit;\r\n font-family: \"${GEIST_FONT_FAMILY}\", sans-serif;\r\n font-size: inherit;\r\n line-height: inherit;\r\n }\r\n\r\n #bulut-shadow-mount * {\r\n font-family: \"${GEIST_FONT_FAMILY}\", sans-serif !important;\r\n color: inherit;\r\n }\r\n\r\n #bulut-shadow-mount *, #bulut-shadow-mount *::before, #bulut-shadow-mount *::after {\r\n box-sizing: border-box;\r\n }\r\n`;\r\n\r\n// Container host for the widget\r\nlet widgetContainer: HTMLElement | null = null;\r\nlet widgetMountNode: HTMLElement | null = null;\r\nlet createdContainer = false;\r\nlet isInitialized = false;\r\n\r\n/**\r\n * Initialize the Bulut chat widget\r\n * @param options - Optional configuration options\r\n */\r\nexport const init = (options: BulutOptions = {}) => {\r\n if (isInitialized) {\r\n console.warn(\"Bulut is already initialized\");\r\n return;\r\n }\r\n\r\n ensureGeistStylesheet();\r\n\r\n const runtimeConfig = resolveRuntimeConfig(options);\r\n applyTheme(runtimeConfig.baseColor);\r\n\r\n // Create or find container\r\n if (options.containerId) {\r\n widgetContainer = document.getElementById(options.containerId);\r\n createdContainer = false;\r\n } else {\r\n widgetContainer = document.createElement(\"div\");\r\n widgetContainer.id = \"bulut-container\";\r\n document.body.appendChild(widgetContainer);\r\n createdContainer = true;\r\n }\r\n\r\n if (!widgetContainer) {\r\n console.error(\"Bulut: Container not found\");\r\n return;\r\n }\r\n\r\n const shadowRoot = widgetContainer.shadowRoot || widgetContainer.attachShadow({ mode: \"open\" });\r\n shadowRoot.replaceChildren();\r\n\r\n const style = document.createElement(\"style\");\r\n style.textContent = SHADOW_STYLE;\r\n\r\n const mountNode = document.createElement(\"div\");\r\n mountNode.id = \"bulut-shadow-mount\";\r\n\r\n shadowRoot.append(style, mountNode);\r\n widgetMountNode = mountNode;\r\n\r\n // Render the widget\r\n render(<BulutWidget config={runtimeConfig} />, mountNode);\r\n isInitialized = true;\r\n\r\n console.log(\"Bulut initialized successfully\");\r\n};\r\n\r\n/**\r\n * Destroy the Bulut widget\r\n */\r\nexport const destroy = () => {\r\n if (!isInitialized) {\r\n return;\r\n }\r\n\r\n if (widgetMountNode) {\r\n render(null, widgetMountNode);\r\n widgetMountNode = null;\r\n }\r\n\r\n if (widgetContainer && createdContainer) {\r\n document.body.removeChild(widgetContainer);\r\n }\r\n\r\n widgetContainer = null;\r\n createdContainer = false;\r\n isInitialized = false;\r\n console.log(\"Bulut destroyed\");\r\n};\r\n\r\n/**\r\n * Check if the widget is initialized\r\n */\r\nexport const isReady = () => isInitialized;\r\n\r\nconst Bulut = {\r\n init,\r\n destroy,\r\n isReady,\r\n};\r\n\r\nif (typeof window !== \"undefined\") {\r\n (window as Window & { Bulut?: typeof Bulut }).Bulut = Bulut;\r\n}\r\n\r\n// Export the main widget component for advanced usage\r\nexport { BulutWidget };\r\n\r\n// Export components for custom implementations\r\nexport { ChatButton, ChatWindow };\r\n\r\nexport default Bulut;\r\n"],"names":["n","l","u","i","o","r","e","f","c","s","a","p","v","y","d","Array","isArray","w","g","parentNode","removeChild","m","t","type","props","key","ref","__k","__","__b","__e","__c","constructor","__v","__i","__u","vnode","k","children","x","this","context","S","length","C","base","M","__d","push","$","__r","debounceRendering","sort","shift","__P","O","__n","namespaceURI","N","I","h","_","b","String","L","D","P","B","A","nextSibling","insertBefore","nodeType","T","setProperty","test","j","style","cssText","replace","toLowerCase","slice","addEventListener","removeEventListener","removeAttribute","setAttribute","F","event","H","prototype","render","contextType","value","__E","E","sub","state","__h","_sb","__s","getDerivedStateFromProps","componentWillMount","componentDidMount","componentWillReceiveProps","shouldComponentUpdate","some","componentWillUpdate","componentDidUpdate","getChildContext","getSnapshotBeforeUpdate","V","then","indexOf","z","localName","document","createTextNode","createElementNS","is","__m","data","call","childNodes","attributes","name","__html","innerHTML","content","q","diffed","forEach","map","current","unmount","componentWillUnmount","G","documentElement","arguments","defaultProps","firstChild","getDerivedStateFromError","setState","componentDidCatch","forceUpdate","Promise","bind","resolve","setTimeout","__source","__self","__H","__N","__f","filter","every","requestAnimationFrame","clearTimeout","cancelAnimationFrame","COLORS","primary","primaryHover","text","textSecondary","messageUser","messageUserText","BORDER_RADIUS","SHADOW","TRANSITIONS","handRaisedIconContent","microphoneOutlineIconContent","stopOutlineIconContent","xMarkIconContent","SvgIcon","src","width","height","title","stripColors","className","fill","stroke","strokeWidth","viewBox","useMemo","trimmedSrc","trim","viewBoxMatch","match","jsx","display","verticalAlign","flexShrink","xmlns","dangerouslySetInnerHTML","nextContent","fillValue","strokeValue","strokeWidthValue","ChatButton","onMicClick","onCancelRecording","onStopTask","isRecording","isBusy","accessibilityMode","showBubble","onBubbleClick","previewMessage","onPreviewClick","onPreviewClose","bgColor","popupBoxShadow","containerStyle","position","right","bottom","flexDirection","alignItems","gap","zIndex","fontFamily","buttonStyle","minWidth","minHeight","borderRadius","backgroundColor","color","border","cursor","justifyContent","transition","showStopButton","mainIconSrc","closeBtnStyle","top","background","fontSize","lineHeight","padding","renderPopup","onClick","onClose","extraClass","scrollable","jsxs","stopPropagation","paddingRight","wordBreak","maxHeight","overflowY","Fragment","onMouseEnter","Object","assign","currentTarget","transform","onMouseLeave","PAGE_CONTEXT_CACHE_KEY","NON_CONTENT_TAGS","Set","SVG_INTERNAL_TAGS","NATIVE_INTERACTIVE_TAGS","INTERACTIVE_ROLES","pageContextCache","Map","cacheHydrated","liveElementMap","getElementById","id","get","normalizeWhitespace","canonicalUrl","rawUrl","URL","href","isCacheEntry","obj","url","summary","links","interactables","capturedAt","version","parseTabIndex","parsed","Number","parseInt","isNaN","getPrimaryRole","element","getAttribute","split","persistCacheToStorage","sessionStorage","serialized","JSON","stringify","from","values","setItem","error","console","warn","buildSummaryWithHistory","recentPages","entry","historySection","compactSummary","join","isVisible","HTMLElement","hidden","window","getComputedStyle","visibility","rect","getBoundingClientRect","hasInteractiveAncestor","parent","parentElement","body","parentTag","tagName","has","parentRole","toAbsoluteUrl","location","getElementLabel","innerText","textContent","substring","ariaLabel","placeholder","HTMLInputElement","HTMLTextAreaElement","HTMLButtonElement","label","tag","alt","filename","pop","compactOuterHtml","inputType","currentValue","selectEl","selectedText","selectedOptions","html","outerHTML","closeIdx","Math","min","describeElementType","role","toUpperCase","getElementState","states","pressed","expanded","checked","hasAttribute","TEXT_CONTENT_SELECTOR","hasDirectText","child","Node","TEXT_NODE","formatSection","lines","invalidateCurrentPageContext","delete","getPageContext","forceRefresh","elementMap","raw","getItem","parse","set","size","info","hydrateCacheFromStorage","scan","sampledElements","querySelectorAll","linkSet","candidates","idCounter","order","isNativeInteractive","Boolean","isRoleInteractive","tabIndex","hasTabStop","hasPointerCursor","isContentEditable","isDisabled","startsWith","absoluteHref","line","add","elType","stateTokens","score","collectSemanticElements","cached","headings","lang","textSnippets","buildPageContextSummary","root","querySelector","snippets","seen","addSnippet","node","genericContainers","collectTextSnippets","Date","now","sorted","overflow","pruneOldestCacheEntries","AGENT_CURSOR_ID","CURSOR_MOVE_DURATION_MS","CURSOR_EASING","RESUME_STORAGE_KEY","savePendingAgentResume","localStorage","savedAt","clearPendingAgentResume","removeItem","clamp","max","animateWindowScrollTo","async","targetY","durationMs","startY","scrollY","delta","abs","raf","callback","performance","startTime","step","progress","eased","cos","PI","easeInOutSine","scrollTo","setCursorPosition","left","setCursorVisibility","visible","opacity","isVisibleElement","findAgentUiAnchorElement","roots","defaultHost","shadowRoot","allElements","el","includes","getBulutShadowRoots","panel","button","getAgentWindowTopLeft","anchor","CURSOR_DIAMETER_PX","scrollX","hideAgentCursor","cursorHoverTrackingInitialized","initializeCursorHoverTracking","parseFloat","getCursorPosition","pointerX","pageX","pointerY","pageY","hypot","moveCursor","existing","createElement","startPosition","baseColor","boxShadow","boxSizing","pointerEvents","appendChild","ensureCursor","dataset","transitionReady","waitForNextAnimationFrame","getElementCenter","CONTAINS_SELECTOR_PATTERN","findElementBySelector","selector","containsMatch","baseSelector","expectedText","candidate","fallbackError","dispatchMouseEvent","dispatchEvent","MouseEvent","bubbles","cancelable","view","clientX","clientY","typeIntoElement","focus","descriptor","getOwnPropertyDescriptor","defaultValue","setNativeInputLikeValue","Event","slowScrollElementIntoView","slowScrollElementIntoViewWithMode","forceCenter","viewportHeight","innerHeight","isRectOutsideViewport","maxScrollTop","scrollHeight","currentScrollY","rectTop","rectHeight","computeCenteredScrollTop","executeInteract","target","mapped","center","selected","resolveTarget","action","click","requestSubmit","form","parentForm","closest","submitElement","executeNavigate","targetUrl","resolvedUrl","matchingElement","parsedTarget","allLinks","HTMLAnchorElement","elUrl","pathname","search","hash","urlSegments","lastSegment","searchTerms","searchParams","entries","clickables","dataTab","term","findMatchingLinkForTarget","log","origin","isSamePageNavigation","newPath","history","pushState","PopStateEvent","executeSingleToolCall","callId","call_id","tool","result","executeScroll","msg","Error","message","TTS_WS_RETRY_DELAYS_MS","BULUT_AUDIO_STOP_EVENT","activeAudioElements","audioPlaybackGeneration","normalizeBaseUrl","baseUrl","trimmed","toWebSocketUrl","path","normalized","protocol","toString","shouldFallbackToSse","retryable","parseErrorBody","response","json","detail","statusText","sleep","ms","wasPlaybackStoppedAfter","generationAtStart","getAudioPlaybackGeneration","stopActiveAudioPlayback","active","audioElement","pause","load","base64ToUint8Array","base64","cleanBase64","binaryString","atob","bytes","Uint8Array","charCodeAt","playBufferedAudio","chunks","mimeType","sampleRate","onAudioStateChange","playbackGeneration","totalBytes","reduce","acc","byteLength","blobParts","chunk","copied","buffer","detectedMime","header","padStart","safeMimeType","finalBlobParts","ArrayBuffer","DataView","setUint32","setUint16","channels","createWavHeader","blob","Blob","Audio","objectUrl","createObjectURL","registerActiveAudioElement","preload","autoplay","play","ended","reject","watchdog","setInterval","onEnded","cleanup","onError","onForcedStop","clearInterval","waitForPlaybackEnd","err","unregisterActiveAudioElement","revokeObjectURL","parseSseEventPayload","eventBlock","dataLines","trimStart","dataStr","isAudioSsePayload","payload","audio","startSttWebSocketStream","config","events","wsUrl","socket","WebSocket","seq","finalText","finalSessionId","sessionId","stopped","settled","sendQueue","resolveStart","rejectStart","startPromise","resolveDone","rejectDone","donePromise","rejectAll","resolveDoneIfPossible","session_id","onopen","onRequestSent","send","project_id","projectId","language","mime_type","onmessage","parseSttWsEventPayload","onSessionId","close","buildError","onPartial","onerror","ev","onclose","code","reason","pushChunk","arrayBuffer","binary","fromCharCode","subarray","btoa","blobToBase64","readyState","OPEN","debug","stop","cancel","collectTtsViaWebSocket","assistantText","voice","isStopped","setSocket","onFirstBatchReady","requestId","crypto","randomUUID","random","highestSeqSeen","firstBatchFired","firstBatchTimer","fireFirstBatch","batch","splice","connectOnce","done","finalError","finalize","mode","request_id","accessibility_mode","last_seq","parseTtsWsEventPayload","incomingSeq","shouldAcceptAudioSeq","sample_rate","attempt","delay","collectAndPlayTtsStreamed","setReader","playbackGen","ttsResult","firstBatchPlayPromise","firstBatch","catch","wsErr","ttsFormData","FormData","append","ttsResponse","fetch","method","ok","reader","getReader","decoder","TextDecoder","read","decode","stream","blocks","block","format","releaseLock","collectTtsViaSse","speakText","agentVoiceChatStream","audioFile","executeTool","activeReader","activeSocket","errorEmitted","sttResult","file","formData","responsePromise","transcribeAudio","onSttRequestSent","currentSessionId","effectiveSessionId","userText","onTranscription","user_text","agentResolve","agentReject","finalReply","resolved","accumulatedDelta","allIntermediateText","finish","reply","fail","model","page_context","pageContext","msgType","onAssistantDelta","calls","onIntermediateReply","onToolCalls","results","isNavigate","pendingToolCalls","args","completedResults","onToolResult","final_reply","replyExpectsReply","expects_reply","onAssistantDone","errMsg","onIteration","iteration","max_iterations","SFX_SOURCES","sent","thinking","toolCall","completed","sfxManager","queue","playNow","volume","onended","drain","next","playCue","STORAGE_KEY","TIMESTAMP_KEY","SESSION_ID_KEY","TTL_MS","STATUS_LABELS","getGreetingText","agentName","resolveStatusText","flags","isRunningTools","isPlayingAudio","isThinking","isTranscribing","formatDurationMs","totalSeconds","floor","createInitialMessages","isUser","clearPersistedChatState","storage","getNextMessageId","messages","shouldAutoListenAfterAudio","expectsReply","getToolIndicatorMessage","kind","ChatWindow","onAccessibilityToggle","actionsRef","onRecordingChange","onBusyChange","onPreviewChange","setMessages","useState","saved","timestamp","setIsBusy","setIsRecording","setIsTranscribing","setIsThinking","isRenderingAudio","setIsRenderingAudio","setIsPlayingAudio","setIsRunningTools","isMicPending","setIsMicPending","recordingDurationMs","setRecordingDurationMs","statusOverride","setStatusOverride","statusFlags","resolvedStatusText","showStatus","hasActiveStatus","isBusyRef","useRef","isRecordingRef","nextMessageIdRef","recorderRef","streamRef","audioChunksRef","activeStreamControllerRef","sessionIdRef","ts","silenceStartRef","vadIntervalRef","audioContextRef","sourceRef","discardNextRecordingRef","micPressStartRef","micHoldTimeoutRef","micHoldTriggeredRef","recordingModeRef","pendingStopAfterStartRef","startRecordingPendingRef","assistantMessageIdRef","assistantTextBufferRef","transcriptionReceivedRef","assistantDoneReceivedRef","recordingStartedAtRef","recordingTimerIntervalRef","messagesContainerRef","messagesContentRef","pendingUserTextRef","pendingAssistantTextRef","streamingJsonParserRef","awaitingAssistantResponseRef","activeSttWsRef","liveTranscriptionMessageIdRef","liveTranscriptionTextRef","autoListenSuppressedRef","expectsReplyRef","requestEpochRef","sttSendCuePlayedRef","useEffect","lastAssistant","reverse","find","st","playSfx","beginRequestEpoch","invalidateRequestEpoch","isCurrentRequestEpoch","epoch","playSttSentCueOnce","scrollMessagesToBottom","scrollTop","ResizeObserver","observer","observe","disconnect","stopRecordingTimer","resetProcessingFlags","clearMicHoldTimeout","cleanupVAD","stopStreamTracks","getTracks","track","stopActiveStream","cancelActiveSttWs","activeSttWs","recorder","ondataavailable","onstop","resumeState","getPendingAgentResume","requestEpoch","freshPageContext","controller","allResults","tc","accumulated_delta","pending_tool_calls","tool_results","agentResumeStream","backendBaseUrl","sid","appendMessage","updateMessageText","finalDisplayText","handleAudioStateChange","appendToolIndicatorMessages","finally","startRecording","options","previous","toolKind","toolLabel","toolCount","indicator","last","previousToolText","extractedCount","nextCount","isFinite","baseLabel","upsertLiveUserTranscription","clearLiveUserTranscriptionState","finalizeStreamCycle","runAgentForUserText","normalizedUserText","handleToolExecution","agentTextChatStream","stopRecording","discard","navigator","mediaDevices","getUserMedia","MediaRecorder","recorderOptions","audioBitsPerSecond","preferredMimeTypes","mime","isTypeSupported","sttMimeType","sttWsController","shouldDiscard","currentSttWs","fileType","extension","File","previousUserText","_callId","_toolName","_result","_iteration","_maxIterations","handleAudioBlob","AudioCtx","AudioContext","webkitAudioContext","analyser","createAnalyser","fftSize","source","createMediaStreamSource","connect","dataArray","frequencyBinCount","speechDetected","speechStartedAt","enforceMinSpeechDuration","getByteFrequencyData","sum","silenceDuration","speechDurationMs","minSpeechDurationMs","shouldAcceptVadSpeech","setupVAD","start","startedAt","normalizeError","resetMicGesture","handleMicPointerUp","preventDefault","releasePointerCapture","pointerId","wasHold","thresholdMs","classifyMicGesture","timer","stopTask","cancelRecording","windowStyle","animation","headerButtonStyle","messageStyle","maxWidth","wordWrap","whiteSpace","alignSelf","statusPanelStyle","flex","textOverflow","recordingTimerStyle","fontWeight","textAlign","micFooterButtonStyle","isVadRecording","hideMicButton","disableMicControl","marginTop","letterSpacing","userSelect","initialMessages","toolIconSrc","onPointerDown","setPointerCapture","onPointerUp","onPointerCancel","disabled","DEFAULT_CONFIG","normalizeHexColor","isValidHexColor","shadeHexColor","hexColor","amount","toChannel","adjust","channel","toHex","round","applyTheme","ACCESSIBILITY_MODE_KEY","GEIST_FONT_FAMILY","GEIST_STYLESHEET_ID","BulutWidget","liveConfig","setLiveConfig","configReady","setConfigReady","cancelled","res","fetchRemoteConfig","remote","merged","base_color","agent_name","isOpen","setIsOpen","setShowBubble","isAccessibilityEnabled","setIsAccessibilityEnabled","setPreviewMessage","previewDismissed","setPreviewDismissed","chatActionsRef","handlePreviewChange","toggleWidget","newState","handleEscape","SHADOW_STYLE","widgetContainer","widgetMountNode","createdContainer","isInitialized","init","link","rel","head","ensureGeistStylesheet","runtimeConfig","resolveRuntimeConfig","containerId","attachShadow","replaceChildren","mountNode","destroy","isReady","Bulut"],"mappings":"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","x_google_ignoreList":[0,1,2]}