@coframe-gtm/annotations 1.0.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.
- package/README.md +48 -0
- package/package.json +43 -0
- package/src/README.md +79 -0
- package/src/api.test.ts +253 -0
- package/src/api.ts +264 -0
- package/src/bundle.ts +69 -0
- package/src/capture.test.ts +88 -0
- package/src/capture.ts +345 -0
- package/src/index.ts +45 -0
- package/src/inject/build.ts +52 -0
- package/src/inject/bundle-source.generated.ts +5 -0
- package/src/inject/install.test.ts +84 -0
- package/src/inject/install.ts +126 -0
- package/src/output.ts +171 -0
- package/src/picker.ts +203 -0
- package/src/server/index.ts +28 -0
- package/src/server/ingest.test.ts +144 -0
- package/src/server/ingest.ts +175 -0
- package/src/server/run-store.test.ts +51 -0
- package/src/server/run-store.ts +155 -0
- package/src/shadow.ts +84 -0
- package/src/store.ts +79 -0
- package/src/types.ts +154 -0
- package/src/ui/App.ts +516 -0
- package/src/ui/styles.ts +283 -0
- package/src/ulid.ts +21 -0
- package/src/webhook.ts +33 -0
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
/* eslint-disable */
|
|
2
|
+
// This file is generated by `pnpm build`.
|
|
3
|
+
// Do not edit by hand. Regenerate by running the build script.
|
|
4
|
+
export const ANNOTATIONS_V1_BUNDLE_SOURCE: string =
|
|
5
|
+
"\"use strict\";(()=>{var de,m,it,Ie,H,tt,at,st,$e,se,Q,lt,Le,Pe,Me,an,ce={},ue=[],sn=/acit|ex(?:s|g|n|p|$)|rph|grid|ows|mnc|ntw|ine[ch]|zoo|^ord|itera/i,pe=Array.isArray;function U(e,t){for(var n in t)e[n]=t[n];return e}function Be(e){e&&e.parentNode&&e.parentNode.removeChild(e)}function d(e,t,n){var o,r,i,s={};for(i in t)i==\"key\"?o=t[i]:i==\"ref\"?r=t[i]:s[i]=t[i];if(arguments.length>2&&(s.children=arguments.length>3?de.call(arguments,2):n),typeof e==\"function\"&&e.defaultProps!=null)for(i in e.defaultProps)s[i]===void 0&&(s[i]=e.defaultProps[i]);return le(e,s,o,r,null)}function le(e,t,n,o,r){var i={type:e,props:t,key:n,ref:o,__k:null,__:null,__b:0,__e:null,__c:null,constructor:void 0,__v:r??++it,__i:-1,__u:0};return r==null&&m.vnode!=null&&m.vnode(i),i}function V(e){return e.children}function q(e,t){this.props=e,this.context=t}function K(e,t){if(t==null)return e.__?K(e.__,e.__i+1):null;for(var n;t<e.__k.length;t++)if((n=e.__k[t])!=null&&n.__e!=null)return n.__e;return typeof e.type==\"function\"?K(e):null}function ln(e){if(e.__P&&e.__d){var t=e.__v,n=t.__e,o=[],r=[],i=U({},t);i.__v=t.__v+1,m.vnode&&m.vnode(i),Re(e.__P,i,t,e.__n,e.__P.namespaceURI,32&t.__u?[n]:null,o,n??K(t),!!(32&t.__u),r),i.__v=t.__v,i.__.__k[i.__i]=i,dt(o,i,r),t.__e=t.__=null,i.__e!=n&&ct(i)}}function ct(e){if((e=e.__)!=null&&e.__c!=null)return e.__e=e.__c.base=null,e.__k.some(function(t){if(t!=null&&t.__e!=null)return e.__e=e.__c.base=t.__e}),ct(e)}function nt(e){(!e.__d&&(e.__d=!0)&&H.push(e)&&!fe.__r++||tt!=m.debounceRendering)&&((tt=m.debounceRendering)||at)(fe)}function fe(){try{for(var e,t=1;H.length;)H.length>t&&H.sort(st),e=H.shift(),t=H.length,ln(e)}finally{H.length=fe.__r=0}}function ut(e,t,n,o,r,i,s,c,f,l,u){var a,_,p,C,M,S,v,h=o&&o.__k||ue,D=t.length;for(f=cn(n,t,h,f,D),a=0;a<D;a++)(p=n.__k[a])!=null&&(_=p.__i!=-1&&h[p.__i]||ce,p.__i=a,S=Re(e,p,_,r,i,s,c,f,l,u),C=p.__e,p.ref&&_.ref!=p.ref&&(_.ref&&Ue(_.ref,null,p),u.push(p.ref,p.__c||C,p)),M==null&&C!=null&&(M=C),(v=!!(4&p.__u))||_.__k===p.__k?(f=ft(p,f,e,v),v&&_.__e&&(_.__e=null)):typeof p.type==\"function\"&&S!==void 0?f=S:C&&(f=C.nextSibling),p.__u&=-7);return n.__e=M,f}function cn(e,t,n,o,r){var i,s,c,f,l,u=n.length,a=u,_=0;for(e.__k=new Array(r),i=0;i<r;i++)(s=t[i])!=null&&typeof s!=\"boolean\"&&typeof s!=\"function\"?(typeof s==\"string\"||typeof s==\"number\"||typeof s==\"bigint\"||s.constructor==String?s=e.__k[i]=le(null,s,null,null,null):pe(s)?s=e.__k[i]=le(V,{children:s},null,null,null):s.constructor===void 0&&s.__b>0?s=e.__k[i]=le(s.type,s.props,s.key,s.ref?s.ref:null,s.__v):e.__k[i]=s,f=i+_,s.__=e,s.__b=e.__b+1,c=null,(l=s.__i=un(s,n,f,a))!=-1&&(a--,(c=n[l])&&(c.__u|=2)),c==null||c.__v==null?(l==-1&&(r>u?_--:r<u&&_++),typeof s.type!=\"function\"&&(s.__u|=4)):l!=f&&(l==f-1?_--:l==f+1?_++:(l>f?_--:_++,s.__u|=4))):e.__k[i]=null;if(a)for(i=0;i<u;i++)(c=n[i])!=null&&(2&c.__u)==0&&(c.__e==o&&(o=K(c)),_t(c,c));return o}function ft(e,t,n,o){var r,i;if(typeof e.type==\"function\"){for(r=e.__k,i=0;r&&i<r.length;i++)r[i]&&(r[i].__=e,t=ft(r[i],t,n,o));return t}e.__e!=t&&(o&&(t&&e.type&&!t.parentNode&&(t=K(e)),n.insertBefore(e.__e,t||null)),t=e.__e);do t=t&&t.nextSibling;while(t!=null&&t.nodeType==8);return t}function un(e,t,n,o){var r,i,s,c=e.key,f=e.type,l=t[n],u=l!=null&&(2&l.__u)==0;if(l===null&&c==null||u&&c==l.key&&f==l.type)return n;if(o>(u?1:0)){for(r=n-1,i=n+1;r>=0||i<t.length;)if((l=t[s=r>=0?r--:i++])!=null&&(2&l.__u)==0&&c==l.key&&f==l.type)return s}return-1}function ot(e,t,n){t[0]==\"-\"?e.setProperty(t,n??\"\"):e[t]=n==null?\"\":typeof n!=\"number\"||sn.test(t)?n:n+\"px\"}function ae(e,t,n,o,r){var i,s;e:if(t==\"style\")if(typeof n==\"string\")e.style.cssText=n;else{if(typeof o==\"string\"&&(e.style.cssText=o=\"\"),o)for(t in o)n&&t in n||ot(e.style,t,\"\");if(n)for(t in n)o&&n[t]==o[t]||ot(e.style,t,n[t])}else if(t[0]==\"o\"&&t[1]==\"n\")i=t!=(t=t.replace(lt,\"$1\")),s=t.toLowerCase(),t=s in e||t==\"onFocusOut\"||t==\"onFocusIn\"?s.slice(2):t.slice(2),e.l||(e.l={}),e.l[t+i]=n,n?o?n[Q]=o[Q]:(n[Q]=Le,e.addEventListener(t,i?Me:Pe,i)):e.removeEventListener(t,i?Me:Pe,i);else{if(r==\"http://www.w3.org/2000/svg\")t=t.replace(/xlink(H|:h)/,\"h\").replace(/sName$/,\"s\");else if(t!=\"width\"&&t!=\"height\"&&t!=\"href\"&&t!=\"list\"&&t!=\"form\"&&t!=\"tabIndex\"&&t!=\"download\"&&t!=\"rowSpan\"&&t!=\"colSpan\"&&t!=\"role\"&&t!=\"popover\"&&t in e)try{e[t]=n??\"\";break e}catch{}typeof n==\"function\"||(n==null||n===!1&&t[4]!=\"-\"?e.removeAttribute(t):e.setAttribute(t,t==\"popover\"&&n==1?\"\":n))}}function rt(e){return function(t){if(this.l){var n=this.l[t.type+e];if(t[se]==null)t[se]=Le++;else if(t[se]<n[Q])return;return n(m.event?m.event(t):t)}}}function Re(e,t,n,o,r,i,s,c,f,l){var u,a,_,p,C,M,S,v,h,D,O,J,et,ie,Te,I=t.type;if(t.constructor!==void 0)return null;128&n.__u&&(f=!!(32&n.__u),i=[c=t.__e=n.__e]),(u=m.__b)&&u(t);e:if(typeof I==\"function\")try{if(v=t.props,h=I.prototype&&I.prototype.render,D=(u=I.contextType)&&o[u.__c],O=u?D?D.props.value:u.__:o,n.__c?S=(a=t.__c=n.__c).__=a.__E:(h?t.__c=a=new I(v,O):(t.__c=a=new q(v,O),a.constructor=I,a.render=dn),D&&D.sub(a),a.state||(a.state={}),a.__n=o,_=a.__d=!0,a.__h=[],a._sb=[]),h&&a.__s==null&&(a.__s=a.state),h&&I.getDerivedStateFromProps!=null&&(a.__s==a.state&&(a.__s=U({},a.__s)),U(a.__s,I.getDerivedStateFromProps(v,a.__s))),p=a.props,C=a.state,a.__v=t,_)h&&I.getDerivedStateFromProps==null&&a.componentWillMount!=null&&a.componentWillMount(),h&&a.componentDidMount!=null&&a.__h.push(a.componentDidMount);else{if(h&&I.getDerivedStateFromProps==null&&v!==p&&a.componentWillReceiveProps!=null&&a.componentWillReceiveProps(v,O),t.__v==n.__v||!a.__e&&a.shouldComponentUpdate!=null&&a.shouldComponentUpdate(v,a.__s,O)===!1){t.__v!=n.__v&&(a.props=v,a.state=a.__s,a.__d=!1),t.__e=n.__e,t.__k=n.__k,t.__k.some(function(Y){Y&&(Y.__=t)}),ue.push.apply(a.__h,a._sb),a._sb=[],a.__h.length&&s.push(a);break e}a.componentWillUpdate!=null&&a.componentWillUpdate(v,a.__s,O),h&&a.componentDidUpdate!=null&&a.__h.push(function(){a.componentDidUpdate(p,C,M)})}if(a.context=O,a.props=v,a.__P=e,a.__e=!1,J=m.__r,et=0,h)a.state=a.__s,a.__d=!1,J&&J(t),u=a.render(a.props,a.state,a.context),ue.push.apply(a.__h,a._sb),a._sb=[];else do a.__d=!1,J&&J(t),u=a.render(a.props,a.state,a.context),a.state=a.__s;while(a.__d&&++et<25);a.state=a.__s,a.getChildContext!=null&&(o=U(U({},o),a.getChildContext())),h&&!_&&a.getSnapshotBeforeUpdate!=null&&(M=a.getSnapshotBeforeUpdate(p,C)),ie=u!=null&&u.type===V&&u.key==null?pt(u.props.children):u,c=ut(e,pe(ie)?ie:[ie],t,n,o,r,i,s,c,f,l),a.base=t.__e,t.__u&=-161,a.__h.length&&s.push(a),S&&(a.__E=a.__=null)}catch(Y){if(t.__v=null,f||i!=null)if(Y.then){for(t.__u|=f?160:128;c&&c.nodeType==8&&c.nextSibling;)c=c.nextSibling;i[i.indexOf(c)]=null,t.__e=c}else{for(Te=i.length;Te--;)Be(i[Te]);Ne(t)}else t.__e=n.__e,t.__k=n.__k,Y.then||Ne(t);m.__e(Y,t,n)}else i==null&&t.__v==n.__v?(t.__k=n.__k,t.__e=n.__e):c=t.__e=fn(n.__e,t,n,o,r,i,s,f,l);return(u=m.diffed)&&u(t),128&t.__u?void 0:c}function Ne(e){e&&(e.__c&&(e.__c.__e=!0),e.__k&&e.__k.some(Ne))}function dt(e,t,n){for(var o=0;o<n.length;o++)Ue(n[o],n[++o],n[++o]);m.__c&&m.__c(t,e),e.some(function(r){try{e=r.__h,r.__h=[],e.some(function(i){i.call(r)})}catch(i){m.__e(i,r.__v)}})}function pt(e){return typeof e!=\"object\"||e==null||e.__b>0?e:pe(e)?e.map(pt):e.constructor!==void 0?null:U({},e)}function fn(e,t,n,o,r,i,s,c,f){var l,u,a,_,p,C,M,S=n.props||ce,v=t.props,h=t.type;if(h==\"svg\"?r=\"http://www.w3.org/2000/svg\":h==\"math\"?r=\"http://www.w3.org/1998/Math/MathML\":r||(r=\"http://www.w3.org/1999/xhtml\"),i!=null){for(l=0;l<i.length;l++)if((p=i[l])&&\"setAttribute\"in p==!!h&&(h?p.localName==h:p.nodeType==3)){e=p,i[l]=null;break}}if(e==null){if(h==null)return document.createTextNode(v);e=document.createElementNS(r,h,v.is&&v),c&&(m.__m&&m.__m(t,i),c=!1),i=null}if(h==null)S===v||c&&e.data==v||(e.data=v);else{if(i=h==\"textarea\"&&v.defaultValue!=null?null:i&&de.call(e.childNodes),!c&&i!=null)for(S={},l=0;l<e.attributes.length;l++)S[(p=e.attributes[l]).name]=p.value;for(l in S)p=S[l],l==\"dangerouslySetInnerHTML\"?a=p:l==\"children\"||l in v||l==\"value\"&&\"defaultValue\"in v||l==\"checked\"&&\"defaultChecked\"in v||ae(e,l,null,p,r);for(l in v)p=v[l],l==\"children\"?_=p:l==\"dangerouslySetInnerHTML\"?u=p:l==\"value\"?C=p:l==\"checked\"?M=p:c&&typeof p!=\"function\"||S[l]===p||ae(e,l,p,S[l],r);if(u)c||a&&(u.__html==a.__html||u.__html==e.innerHTML)||(e.innerHTML=u.__html),t.__k=[];else if(a&&(e.innerHTML=\"\"),ut(t.type==\"template\"?e.content:e,pe(_)?_:[_],t,n,o,h==\"foreignObject\"?\"http://www.w3.org/1999/xhtml\":r,i,s,i?i[0]:n.__k&&K(n,0),c,f),i!=null)for(l=i.length;l--;)Be(i[l]);c&&h!=\"textarea\"||(l=\"value\",h==\"progress\"&&C==null?e.removeAttribute(\"value\"):C!=null&&(C!==e[l]||h==\"progress\"&&!C||h==\"option\"&&C!=S[l])&&ae(e,l,C,S[l],r),l=\"checked\",M!=null&&M!=e[l]&&ae(e,l,M,S[l],r))}return e}function Ue(e,t,n){try{if(typeof e==\"function\"){var o=typeof e.__u==\"function\";o&&e.__u(),o&&t==null||(e.__u=e(t))}else e.current=t}catch(r){m.__e(r,n)}}function _t(e,t,n){var o,r;if(m.unmount&&m.unmount(e),(o=e.ref)&&(o.current&&o.current!=e.__e||Ue(o,null,t)),(o=e.__c)!=null){if(o.componentWillUnmount)try{o.componentWillUnmount()}catch(i){m.__e(i,t)}o.base=o.__P=null}if(o=e.__k)for(r=0;r<o.length;r++)o[r]&&_t(o[r],t,n||typeof e.type!=\"function\");n||Be(e.__e),e.__c=e.__=e.__e=void 0}function dn(e,t,n){return this.constructor(e,n)}function mt(e,t,n){var o,r,i,s;t==document&&(t=document.documentElement),m.__&&m.__(e,t),r=(o=typeof n==\"function\")?null:n&&n.__k||t.__k,i=[],s=[],Re(t,e=(!o&&n||t).__k=d(V,null,[e]),r||ce,ce,t.namespaceURI,!o&&n?[n]:r?null:t.firstChild?de.call(t.childNodes):null,i,!o&&n?n:r?r.__e:t.firstChild,o,s),dt(i,e,s)}de=ue.slice,m={__e:function(e,t,n,o){for(var r,i,s;t=t.__;)if((r=t.__c)&&!r.__)try{if((i=r.constructor)&&i.getDerivedStateFromError!=null&&(r.setState(i.getDerivedStateFromError(e)),s=r.__d),r.componentDidCatch!=null&&(r.componentDidCatch(e,o||{}),s=r.__d),s)return r.__E=r}catch(c){e=c}throw e}},it=0,Ie=function(e){return e!=null&&e.constructor===void 0},q.prototype.setState=function(e,t){var n;n=this.__s!=null&&this.__s!=this.state?this.__s:this.__s=U({},this.state),typeof e==\"function\"&&(e=e(U({},n),this.props)),e&&U(n,e),e!=null&&this.__v&&(t&&this._sb.push(t),nt(this))},q.prototype.forceUpdate=function(e){this.__v&&(this.__e=!0,e&&this.__h.push(e),nt(this))},q.prototype.render=V,H=[],at=typeof Promise==\"function\"?Promise.prototype.then.bind(Promise.resolve()):setTimeout,st=function(e,t){return e.__v.__b-t.__v.__b},fe.__r=0,$e=Math.random().toString(8),se=\"__d\"+$e,Q=\"__a\"+$e,lt=/(PointerCapture)$|Capture$/i,Le=0,Pe=rt(!1),Me=rt(!0),an=0;var ht=\"0123456789ABCDEFGHJKMNPQRSTVWXYZ\";function _e(e=Date.now()){let t=e,n=\"\";for(let r=0;r<10;r++)n=ht[t&31]+n,t=Math.floor(t/32);let o=\"\";for(let r=0;r<16;r++)o+=ht[Math.floor(Math.random()*32)];return n+o}var he,y,Fe,vt,De=0,St=[],k=m,gt=k.__b,yt=k.__r,bt=k.diffed,xt=k.__c,kt=k.unmount,wt=k.__;function At(e,t){k.__h&&k.__h(y,e,De||t),De=0;var n=y.__H||(y.__H={__:[],__h:[]});return e>=n.__.length&&n.__.push({}),n.__[e]}function ee(e){return De=1,pn(Et,e)}function pn(e,t,n){var o=At(he++,2);if(o.t=e,!o.__c&&(o.__=[n?n(t):Et(void 0,t),function(c){var f=o.__N?o.__N[0]:o.__[0],l=o.t(f,c);f!==l&&(o.__N=[l,o.__[1]],o.__c.setState({}))}],o.__c=y,!y.__f)){var r=function(c,f,l){if(!o.__c.__H)return!0;var u=o.__c.__H.__.filter(function(_){return _.__c});if(u.every(function(_){return!_.__N}))return!i||i.call(this,c,f,l);var a=o.__c.props!==c;return u.some(function(_){if(_.__N){var p=_.__[0];_.__=_.__N,_.__N=void 0,p!==_.__[0]&&(a=!0)}}),i&&i.call(this,c,f,l)||a};y.__f=!0;var i=y.shouldComponentUpdate,s=y.componentWillUpdate;y.componentWillUpdate=function(c,f,l){if(this.__e){var u=i;i=void 0,r(c,f,l),i=u}s&&s.call(this,c,f,l)},y.shouldComponentUpdate=r}return o.__N||o.__}function Oe(e,t){var n=At(he++,7);return hn(n.__H,t)&&(n.__=e(),n.__H=t,n.__h=e),n.__}function _n(){for(var e;e=St.shift();){var t=e.__H;if(e.__P&&t)try{t.__h.some(me),t.__h.some(He),t.__h=[]}catch(n){t.__h=[],k.__e(n,e.__v)}}}k.__b=function(e){y=null,gt&>(e)},k.__=function(e,t){e&&t.__k&&t.__k.__m&&(e.__m=t.__k.__m),wt&&wt(e,t)},k.__r=function(e){yt&&yt(e),he=0;var t=(y=e.__c).__H;t&&(Fe===y?(t.__h=[],y.__h=[],t.__.some(function(n){n.__N&&(n.__=n.__N),n.u=n.__N=void 0})):(t.__h.some(me),t.__h.some(He),t.__h=[],he=0)),Fe=y},k.diffed=function(e){bt&&bt(e);var t=e.__c;t&&t.__H&&(t.__H.__h.length&&(St.push(t)!==1&&vt===k.requestAnimationFrame||((vt=k.requestAnimationFrame)||mn)(_n)),t.__H.__.some(function(n){n.u&&(n.__H=n.u),n.u=void 0})),Fe=y=null},k.__c=function(e,t){t.some(function(n){try{n.__h.some(me),n.__h=n.__h.filter(function(o){return!o.__||He(o)})}catch(o){t.some(function(r){r.__h&&(r.__h=[])}),t=[],k.__e(o,n.__v)}}),xt&&xt(e,t)},k.unmount=function(e){kt&&kt(e);var t,n=e.__c;n&&n.__H&&(n.__H.__.some(function(o){try{me(o)}catch(r){t=r}}),n.__H=void 0,t&&k.__e(t,n.__v))};var Ct=typeof requestAnimationFrame==\"function\";function mn(e){var t,n=function(){clearTimeout(o),Ct&&cancelAnimationFrame(t),setTimeout(e)},o=setTimeout(n,35);Ct&&(t=requestAnimationFrame(n))}function me(e){var t=y,n=e.__c;typeof n==\"function\"&&(e.__c=void 0,n()),y=t}function He(e){var t=y;e.__c=e.__(),y=t}function hn(e,t){return!e||e.length!==t.length||t.some(function(n,o){return n!==e[o]})}function Et(e,t){return typeof t==\"function\"?t(e):t}var vn=Symbol.for(\"preact-signals\");function be(){if(F>1)F--;else{var e,t=!1;for((function(){var r=ge;for(ge=void 0;r!==void 0;)r.S.v===r.v&&(r.S.i=r.i),r=r.o})();te!==void 0;){var n=te;for(te=void 0,ve++;n!==void 0;){var o=n.u;if(n.u=void 0,n.f&=-3,!(8&n.f)&&Pt(n))try{n.c()}catch(r){t||(e=r,t=!0)}n=o}}if(ve=0,F--,t)throw e}}function ze(e){if(F>0)return e();je=++gn,F++;try{return e()}finally{be()}}var g=void 0;function xe(e){var t=g;g=void 0;try{return e()}finally{g=t}}var Tt,te=void 0,F=0,ve=0,gn=0,je=0,ge=void 0,ye=0;function $t(e){if(g!==void 0){var t=e.n;if(t===void 0||t.t!==g)return t={i:0,S:e,p:g.s,n:void 0,t:g,e:void 0,x:void 0,r:t},g.s!==void 0&&(g.s.n=t),g.s=t,e.n=t,32&g.f&&e.S(t),t;if(t.i===-1)return t.i=0,t.n!==void 0&&(t.n.p=t.p,t.p!==void 0&&(t.p.n=t.n),t.p=g.s,t.n=void 0,g.s.n=t,g.s=t),t}}function w(e,t){this.v=e,this.i=0,this.n=void 0,this.t=void 0,this.l=0,this.W=t?.watched,this.Z=t?.unwatched,this.name=t?.name}w.prototype.brand=vn;w.prototype.h=function(){return!0};w.prototype.S=function(e){var t=this,n=this.t;n!==e&&e.e===void 0&&(e.x=n,this.t=e,n!==void 0?n.e=e:xe(function(){var o;(o=t.W)==null||o.call(t)}))};w.prototype.U=function(e){var t=this;if(this.t!==void 0){var n=e.e,o=e.x;n!==void 0&&(n.x=o,e.e=void 0),o!==void 0&&(o.e=n,e.x=void 0),e===this.t&&(this.t=o,o===void 0&&xe(function(){var r;(r=t.Z)==null||r.call(t)}))}};w.prototype.subscribe=function(e){var t=this;return z(function(){var n=t.value,o=g;g=void 0;try{e(n)}finally{g=o}},{name:\"sub\"})};w.prototype.valueOf=function(){return this.value};w.prototype.toString=function(){return this.value+\"\"};w.prototype.toJSON=function(){return this.value};w.prototype.peek=function(){var e=this;return xe(function(){return e.value})};Object.defineProperty(w.prototype,\"value\",{get:function(){var e=$t(this);return e!==void 0&&(e.i=this.i),this.v},set:function(e){if(e!==this.v){if(ve>100)throw new Error(\"Cycle detected\");(function(n){F!==0&&ve===0&&n.l!==je&&(n.l=je,ge={S:n,v:n.v,i:n.i,o:ge})})(this),this.v=e,this.i++,ye++,F++;try{for(var t=this.t;t!==void 0;t=t.x)t.t.N()}finally{be()}}}});function b(e,t){return new w(e,t)}function Pt(e){for(var t=e.s;t!==void 0;t=t.n)if(t.S.i!==t.i||!t.S.h()||t.S.i!==t.i)return!0;return!1}function Mt(e){for(var t=e.s;t!==void 0;t=t.n){var n=t.S.n;if(n!==void 0&&(t.r=n),t.S.n=t,t.i=-1,t.n===void 0){e.s=t;break}}}function Nt(e){for(var t=e.s,n=void 0;t!==void 0;){var o=t.p;t.i===-1?(t.S.U(t),o!==void 0&&(o.n=t.n),t.n!==void 0&&(t.n.p=o)):n=t,t.S.n=t.r,t.r!==void 0&&(t.r=void 0),t=o}e.s=n}function j(e,t){w.call(this,void 0),this.x=e,this.s=void 0,this.g=ye-1,this.f=4,this.W=t?.watched,this.Z=t?.unwatched,this.name=t?.name}j.prototype=new w;j.prototype.h=function(){if(this.f&=-3,1&this.f)return!1;if((36&this.f)==32||(this.f&=-5,this.g===ye))return!0;if(this.g=ye,this.f|=1,this.i>0&&!Pt(this))return this.f&=-2,!0;var e=g;try{Mt(this),g=this;var t=this.x();(16&this.f||this.v!==t||this.i===0)&&(this.v=t,this.f&=-17,this.i++)}catch(n){this.v=n,this.f|=16,this.i++}return g=e,Nt(this),this.f&=-2,!0};j.prototype.S=function(e){if(this.t===void 0){this.f|=36;for(var t=this.s;t!==void 0;t=t.n)t.S.S(t)}w.prototype.S.call(this,e)};j.prototype.U=function(e){if(this.t!==void 0&&(w.prototype.U.call(this,e),this.t===void 0)){this.f&=-33;for(var t=this.s;t!==void 0;t=t.n)t.S.U(t)}};j.prototype.N=function(){if(!(2&this.f)){this.f|=6;for(var e=this.t;e!==void 0;e=e.x)e.t.N()}};Object.defineProperty(j.prototype,\"value\",{get:function(){if(1&this.f)throw new Error(\"Cycle detected\");var e=$t(this);if(this.h(),e!==void 0&&(e.i=this.i),16&this.f)throw this.v;return this.v}});function ke(e,t){return new j(e,t)}function It(e){var t=e.m;if(e.m=void 0,typeof t==\"function\"){F++;var n=g;g=void 0;try{t()}catch(o){throw e.f&=-2,e.f|=8,We(e),o}finally{g=n,be()}}}function We(e){for(var t=e.s;t!==void 0;t=t.n)t.S.U(t);e.x=void 0,e.s=void 0,It(e)}function yn(e){if(g!==this)throw new Error(\"Out-of-order effect\");Nt(this),g=e,this.f&=-2,8&this.f&&We(this),be()}function X(e,t){this.x=e,this.m=void 0,this.s=void 0,this.u=void 0,this.f=32,this.name=t?.name,Tt&&Tt.push(this)}X.prototype.c=function(){var e=this.S();try{if(8&this.f||this.x===void 0)return;var t=this.x();typeof t==\"function\"&&(this.m=t)}finally{e()}};X.prototype.S=function(){if(1&this.f)throw new Error(\"Cycle detected\");this.f|=1,this.f&=-9,It(this),Mt(this),F++;var e=g;return g=this,yn.bind(this,e)};X.prototype.N=function(){2&this.f||(this.f|=2,this.u=te,te=this)};X.prototype.d=function(){this.f|=8,1&this.f||We(this)};X.prototype.dispose=function(){this.d()};function z(e,t){var n=new X(e,t);try{n.c()}catch(r){throw n.d(),r}var o=n.d.bind(n);return o[Symbol.dispose]=o,o}var Lt,Ye,we,bn=typeof window<\"u\"&&!!window.__PREACT_SIGNALS_DEVTOOLS__;var Bt=[];z(function(){Lt=this.N})();function Z(e,t){m[e]=t.bind(null,m[e]||function(){})}function Ce(e){if(we){var t=we;we=void 0,t()}we=e&&e.S()}function Rt(e){var t=this,n=e.data,o=kn(n);o.value=n;var r=Oe(function(){for(var c=t,f=t.__v;f=f.__;)if(f.__c){f.__c.__$f|=4;break}var l=ke(function(){var p=o.value.value;return p===0?0:p===!0?\"\":p||\"\"}),u=ke(function(){return!Array.isArray(l.value)&&!Ie(l.value)}),a=z(function(){if(this.N=Ut,u.value){var p=l.value;c.__v&&c.__v.__e&&c.__v.__e.nodeType===3&&(c.__v.__e.data=p)}}),_=t.__$u.d;return t.__$u.d=function(){a(),_.call(this)},[u,l]},[]),i=r[0],s=r[1];return i.value?s.peek():s.value}Rt.displayName=\"ReactiveTextNode\";Object.defineProperties(w.prototype,{constructor:{configurable:!0,value:void 0},type:{configurable:!0,value:Rt},props:{configurable:!0,get:function(){var e=this;return{data:{get value(){return e.value}}}}},__b:{configurable:!0,value:1}});Z(\"__b\",function(e,t){if(typeof t.type==\"string\"){var n,o=t.props;for(var r in o)if(r!==\"children\"){var i=o[r];i instanceof w&&(n||(t.__np=n={}),n[r]=i,o[r]=i.peek())}}e(t)});Z(\"__r\",function(e,t){if(e(t),t.type!==V){Ce();var n,o=t.__c;o&&(o.__$f&=-2,(n=o.__$u)===void 0&&(o.__$u=n=(function(r,i){var s;return z(function(){s=this},{name:i}),s.c=r,s})(function(){var r;bn&&((r=n.y)==null||r.call(n)),o.__$f|=1,o.setState({})},typeof t.type==\"function\"?t.type.displayName||t.type.name:\"\"))),Ye=o,Ce(n)}});Z(\"__e\",function(e,t,n,o){Ce(),Ye=void 0,e(t,n,o)});Z(\"diffed\",function(e,t){Ce(),Ye=void 0;var n;if(typeof t.type==\"string\"&&(n=t.__e)){var o=t.__np,r=t.props;if(o){var i=n.U;if(i)for(var s in i){var c=i[s];c!==void 0&&!(s in o)&&(c.d(),i[s]=void 0)}else i={},n.U=i;for(var f in o){var l=i[f],u=o[f];l===void 0?(l=xn(n,f,u),i[f]=l):l.o(u,r)}}}e(t)});function xn(e,t,n,o){var r=t in e&&e.ownerSVGElement===void 0,i=b(n),s=n.peek();return{o:function(c,f){i.value=c,s=c.peek()},d:z(function(){this.N=Ut;var c=i.value.value;s!==c?(s=void 0,r?e[t]=c:c!=null&&(c!==!1||t[4]===\"-\")?e.setAttribute(t,c):e.removeAttribute(t)):s=void 0})}}Z(\"unmount\",function(e,t){if(typeof t.type==\"string\"){var n=t.__e;if(n){var o=n.U;if(o){n.U=void 0;for(var r in o){var i=o[r];i&&i.d()}}}var s=t.__np;if(s){var c=t.props;for(var f in s)c[f]=s[f]}t.__np=void 0}else{var l=t.__c;if(l){var u=l.__$u;u&&(l.__$u=void 0,u.d())}}e(t)});Z(\"__h\",function(e,t,n,o){(o<3||o===9)&&(t.__$f|=2),e(t,n,o)});q.prototype.shouldComponentUpdate=function(e,t){if(this.__R)return!0;var n=this.__$u,o=n&&n.s!==void 0;for(var r in t)return!0;if(this.__f||typeof this.u==\"boolean\"&&this.u===!0){var i=2&this.__$f;if(!(o||i||4&this.__$f)||1&this.__$f)return!0}else if(!(o||4&this.__$f)||3&this.__$f)return!0;for(var s in e)if(s!==\"__source\"&&e[s]!==this.props[s])return!0;for(var c in this.props)if(!(c in e))return!0;return!1};function kn(e,t){return Oe(function(){return b(e,t)},[])}var wn=function(e){queueMicrotask(function(){queueMicrotask(e)})};function Cn(){ze(function(){for(var e;e=Bt.shift();)Lt.call(e)})}function Ut(){Bt.push(this)===1&&(m.requestAnimationFrame||wn)(Cn)}var x=b([]),A=b(\"view\"),W=b(\"dark\"),Se=b(null),ne=b(\"\"),Ft=b(0),Dt=b(!1),L=b({kind:\"human\",id:\"human\",displayName:\"You\"}),E=b(\"element\"),T=b(null),$=b(null),P=b([]),B=b(null),Ae=b(0),N=b([]);function R(e,t){let n=Se.value,o={type:e,timestamp:new Date().toISOString(),sessionId:ne.value,sequence:++Ft.value,payload:t};if(n)try{fetch(n,{method:\"POST\",headers:{\"Content-Type\":\"application/json\"},body:JSON.stringify(o),keepalive:!0}).catch(r=>console.warn(\"[annotations] webhook emit failed\",r))}catch(r){console.warn(\"[annotations] webhook emit threw synchronously\",r)}}var G={version:\"0.1.0\",schema:\"afs-1.1\",addAnnotation(e){let t=e.id??`ann_${_e().slice(-12).toLowerCase()}`,n=Date.now(),o={id:t,comment:e.comment,elementPath:e.elementPath,element:e.element,x:e.x,y:e.y,timestamp:e.timestamp??n,url:e.url,boundingBox:e.boundingBox,reactComponents:e.reactComponents,cssClasses:e.cssClasses,computedStyles:e.computedStyles,accessibility:e.accessibility,nearbyText:e.nearbyText,selectedText:e.selectedText,isFixed:e.isFixed,isMultiSelect:e.isMultiSelect,fullPath:e.fullPath,nearbyElements:e.nearbyElements,elementBoundingBoxes:e.elementBoundingBoxes,intent:e.intent,severity:e.severity,kind:e.kind??\"feedback\",placement:e.placement,rearrange:e.rearrange,status:e.status??\"pending\",thread:[],author:e.author??{kind:\"agent\",id:\"agent\",displayName:\"Agent\"},createdAt:new Date(n).toISOString(),updatedAt:new Date(n).toISOString()};return x.value=[...x.value,o],R(\"annotation.created\",o),t},replyToAnnotation(e,t){if(!x.value.find(r=>r.id===e))return null;let o={id:`msg_${_e().slice(-10).toLowerCase()}`,role:t.role,content:t.content,timestamp:Date.now()};return x.value=x.value.map(r=>r.id===e?{...r,thread:[...r.thread??[],o],updatedAt:new Date().toISOString()}:r),R(\"thread.message\",{annotationId:e,message:o}),o.id},updateAnnotation(e,t){let n=!1;return x.value=x.value.map(o=>o.id!==e?o:(n=!0,{...o,...t,updatedAt:new Date().toISOString()})),n&&R(\"annotation.updated\",{id:e,patch:t}),n},acknowledgeAnnotation(e){return this.updateAnnotation(e,{status:\"acknowledged\"})},resolveAnnotation(e,t=\"agent\"){return this.updateAnnotation(e,{status:\"resolved\",resolvedAt:new Date().toISOString(),resolvedBy:t})},dismissAnnotation(e){return this.updateAnnotation(e,{status:\"dismissed\"})},removeAnnotation(e){let t=x.value.length;x.value=x.value.filter(o=>o.id!==e);let n=x.value.length<t;return n&&R(\"annotation.deleted\",{id:e}),n},clearAnnotations(){let e=x.value.length;return x.value=[],B.value=null,R(\"session.updated\",{cleared:e}),e},focusAnnotation(e){let t=x.value.some(n=>n.id===e);return t&&(B.value=e),t},closeThread(){B.value=null},setCursors(e){N.value=e},setCursor(e){let t=N.value.filter(n=>n.id!==e.id);N.value=[...t,e]},removeCursor(e){let t=N.value.length;return N.value=N.value.filter(n=>n.id!==e),N.value.length<t},clearCursors(){N.value=[]},setMode(e){A.value!==e&&(A.value=e,R(\"session.updated\",{mode:e}))},setTheme(e){W.value=e},getAnnotations(){return x.value}};function Ht(e){e.webhookUrl!==void 0&&(Se.value=e.webhookUrl),ne.value=e.sessionId??`cf_${_e().slice(-12).toLowerCase()}`,R(\"session.created\",{sessionId:ne.value,pageUrl:typeof location<\"u\"?location.href:\"\"})}var Sn=[\"display\",\"position\",\"width\",\"height\",\"margin\",\"padding\",\"color\",\"background-color\",\"background\",\"font-family\",\"font-size\",\"font-weight\",\"line-height\",\"border\",\"border-radius\",\"box-shadow\",\"flex-direction\",\"justify-content\",\"align-items\",\"gap\",\"grid-template-columns\",\"z-index\",\"opacity\",\"text-align\"],An=[\"role\",\"aria-label\",\"aria-labelledby\",\"aria-describedby\",\"aria-hidden\",\"aria-expanded\",\"aria-checked\",\"aria-selected\",\"alt\",\"title\",\"tabindex\",\"type\",\"name\",\"for\",\"href\"];function Ee(e){let t=e.getBoundingClientRect(),n=Un(e),o=window.scrollX,r=window.scrollY,i={x:t.left+(n?0:o),y:t.top+(n?0:r),width:t.width,height:t.height};return{element:e.tagName.toLowerCase(),elementPath:En(e),fullPath:Tn(e),x:Fn((t.left+t.width/2)/window.innerWidth*100),y:n?t.top:t.top+r,url:location.href,boundingBox:i,isFixed:n,cssClasses:$n(e),computedStyles:Pn(e),accessibility:Mn(e),nearbyText:Nn(e),nearbyElements:In(e),reactComponents:Bn(e)}}function En(e){if(e.id&&Ot(e.id))return`#${Ke(e.id)}`;let t=e.getAttribute(\"data-testid\");if(t)return`[data-testid=\"${t}\"]`;let n=e.tagName.toLowerCase(),o=jt(e);return o?`${n}.${Ke(o)}`:n}function Tn(e){let t=[],n=e;for(;n&&n.nodeType===1&&n.tagName.toLowerCase()!==\"html\";){if(n.id&&Ot(n.id)){t.unshift(`#${Ke(n.id)}`);break}let o=n.tagName.toLowerCase(),r=n.parentElement;if(r){let i=Array.from(r.children).filter(s=>s.tagName===n.tagName);i.length>1&&(o+=`:nth-of-type(${i.indexOf(n)+1})`)}t.unshift(o),n=r}return t.join(\" > \")}function Ve(e){if(!e)return null;try{return document.querySelector(e)}catch{return null}}function Ot(e){return!(e.length>40||/^[:]?r[a-z0-9]+[:]?$/i.test(e)||/^(radix|headlessui|mui|react-aria)[-:]/i.test(e))}function jt(e){for(let t of Array.from(e.classList))if(!(/^[a-z0-9_-]*[a-f0-9]{6,}$/i.test(t)&&/\\d/.test(t))&&!t.startsWith(\"cf-\"))return t;return e.classList[0]??null}function Ke(e){return typeof CSS<\"u\"&&typeof CSS.escape==\"function\"?CSS.escape(e):e.replace(/([^\\w-])/g,\"\\\\$1\")}function $n(e){let t=Array.from(e.classList).filter(n=>!n.startsWith(\"cf-\"));return t.length?t.join(\" \"):void 0}function Pn(e){let t=window.getComputedStyle(e),n=[];for(let o of Sn){let r=t.getPropertyValue(o);r&&r!==\"none\"&&r!==\"normal\"&&r!==\"auto\"&&n.push(`${o}: ${r};`)}return n.length?n.join(`\n`):void 0}function Mn(e){let t=[];for(let o of An){let r=e.getAttribute(o);r!==null&&r!==\"\"&&t.push(`${o}=\"${r}\"`)}let n=Ln(e);return n&&t.push(`text=\"${Xe(n,60)}\"`),t.length?t.join(\" \"):void 0}function Nn(e){let t=(e.textContent??\"\").replace(/\\s+/g,\" \").trim();if(t)return Xe(t,200)}function In(e){let t=[];e.parentElement&&t.push(`parent: ${qe(e.parentElement)}`);let n=e.previousElementSibling;n&&t.push(`prev: ${qe(n)}`);let o=e.nextElementSibling;return o&&t.push(`next: ${qe(o)}`),t.length?t.join(\" | \"):void 0}function qe(e){let t=e.tagName.toLowerCase(),n=jt(e),o=(e.textContent??\"\").replace(/\\s+/g,\" \").trim().slice(0,30);return`${t}${n?`.${n}`:\"\"}${o?` \"${o}\"`:\"\"}`}function Ln(e){let t=\"\";for(let n of Array.from(e.childNodes))n.nodeType===3&&(t+=n.textContent??\"\");return t.replace(/\\s+/g,\" \").trim()}function Bn(e){let t=Object.keys(e).find(f=>f.startsWith(\"__reactFiber$\")||f.startsWith(\"__reactInternalInstance$\"));if(!t)return;let n=e[t],o=[],r,i=0;for(;n&&i<30;){let f=n.type,l=typeof f==\"function\"?f.displayName??f.name:void 0;if(l&&/^[A-Z]/.test(l)&&!o.includes(l)&&(o.push(l),!r&&n.memoizedProps&&(r=n.memoizedProps),o.length>=3))break;n=n.return,i++}if(!o.length)return;let s=o[0],c=r?Rn(r):\"\";return c?`${s} (${c})`:s}function Rn(e){let t=[];for(let[n,o]of Object.entries(e))if(n!==\"children\"&&(typeof o==\"string\"?t.push(`${n}=${JSON.stringify(Xe(o,40))}`):(typeof o==\"number\"||typeof o==\"boolean\")&&t.push(`${n}=${o}`),t.length>=5))break;return t.join(\", \")}function Un(e){let t=e,n=0;for(;t&&n<20;){if(window.getComputedStyle(t).position===\"fixed\")return!0;t=t.parentElement,n++}return!1}function Xe(e,t){return e.length>t?`${e.slice(0,t-1)}\\u2026`:e}function Fn(e){return Math.max(0,Math.min(100,Math.round(e*10)/10))}var Ze=null,zt=!1,Wt=0;function Dn(e){let t=Date.now();t-Wt<120||(Wt=t,R(\"presence.cursor\",{id:L.value.id??\"human\",label:L.value.displayName??\"You\",kind:L.value.kind,x:e.clientX/window.innerWidth*100,y:e.clientY+window.scrollY}))}function Yt(e){Ze=e}function Ge(e){return Ze?e.composedPath().includes(Ze):!1}function qt(e){return!(e instanceof Element)||e.tagName===\"HTML\"||e.tagName===\"BODY\"?null:e}function Hn(e){if(Ge(e)||Dn(e),A.value!==\"feedback\"||$.value){T.value=null;return}if(Ge(e)){T.value=null;return}if(E.value===\"text\"){T.value=null;return}let t=qt(e.target);if(!t){T.value=null;return}let n=t.getBoundingClientRect();T.value={top:n.top,left:n.left,width:n.width,height:n.height}}function On(e){if(A.value!==\"feedback\"||Ge(e)||E.value===\"text\"||$.value)return;let t=qt(e.target);if(t){if(e.preventDefault(),e.stopPropagation(),E.value===\"multi\"){Wn(t);return}Je(Ee(t))}}function jn(){if(A.value!==\"feedback\"||E.value!==\"text\"||$.value)return;let e=window.getSelection(),t=e?.toString().trim();if(!t||!e||e.rangeCount===0)return;let n=e.getRangeAt(0),o=n.commonAncestorContainer.nodeType===1?n.commonAncestorContainer:n.commonAncestorContainer.parentElement;if(!o)return;let r=Ee(o);Je({...r,selectedText:t})}function zn(e){if(e.key===\"Escape\"){if($.value){$.value=null;return}if(P.value.length){P.value=[],T.value=null;return}A.value===\"feedback\"&&(A.value=\"view\",T.value=null)}}function Wn(e){let t=P.value;P.value=t.includes(e)?t.filter(n=>n!==e):[...t,e]}function Kt(){let e=P.value;if(!e.length)return;let t=Ee(e[0]),n=e.map(r=>{let i=r.getBoundingClientRect();return{x:i.left+window.scrollX,y:i.top+window.scrollY,width:i.width,height:i.height}}),o=e.map(r=>r.tagName.toLowerCase()).join(\", \");Je({...t,isMultiSelect:!0,elementBoundingBoxes:n,nearbyElements:`${e.length} elements: ${o}`})}function Je(e){P.value=[],T.value=null,$.value=e}function Vt(){zt||(zt=!0,document.addEventListener(\"mousemove\",Hn,!0),document.addEventListener(\"click\",On,!0),document.addEventListener(\"mouseup\",jn,!0),document.addEventListener(\"keydown\",zn,!0))}var Xt=\"annotations-v1-host\",Yn=`\n:host {\n all: initial;\n contain: layout style;\n font-family: -apple-system, \"SF Pro Text\", system-ui, sans-serif;\n font-size: 14px;\n line-height: 1.45;\n color: #f4f4f4;\n}\n*, *::before, *::after { box-sizing: border-box; }\nbutton { font: inherit; cursor: pointer; }\n[hidden] { display: none !important; }\n`,oe=null;function Zt(){if(oe&&document.contains(oe.host))return oe;let e=document.getElementById(Xt);e&&e.remove();let t=document.createElement(\"div\");t.id=Xt,t.style.cssText=[\"all: initial\",\"position: fixed\",\"inset: 0\",\"pointer-events: none\",\"z-index: 2147483647\"].join(\";\");let n=t.attachShadow({mode:\"closed\"}),o=document.createElement(\"style\");o.textContent=Yn,n.appendChild(o);let r=document.createElement(\"div\");return r.id=\"cf-app\",r.style.cssText=\"pointer-events: auto;\",n.appendChild(r),document.documentElement.appendChild(t),oe={host:t,shadow:n,appRoot:r},oe}var Gt=`\n.cf-overlay {\n position: fixed;\n inset: 0;\n pointer-events: none;\n font-family: -apple-system, \"SF Pro Text\", system-ui, sans-serif;\n font-size: 13px;\n color: #f4f4f5;\n --cf-bg: rgba(18, 18, 22, 0.96);\n --cf-border: rgba(255, 255, 255, 0.1);\n --cf-muted: rgba(255, 255, 255, 0.55);\n --cf-accent: #a78bfa;\n}\n.cf-overlay[data-theme=\"light\"] {\n color: #18181b;\n --cf-bg: rgba(252, 252, 253, 0.97);\n --cf-border: rgba(0, 0, 0, 0.1);\n --cf-muted: rgba(0, 0, 0, 0.5);\n}\n\n/* Hover highlight + multi-select boxes */\n.cf-hover {\n position: fixed;\n pointer-events: none;\n border: 2px solid var(--cf-accent);\n background: rgba(167, 139, 250, 0.1);\n border-radius: 4px;\n box-shadow: 0 0 0 1px rgba(167, 139, 250, 0.4);\n transition: top .06s ease, left .06s ease, width .06s ease, height .06s ease;\n z-index: 1;\n}\n.cf-multi-box {\n position: fixed;\n pointer-events: none;\n border: 2px solid #3ecf8e;\n background: rgba(62, 207, 142, 0.12);\n border-radius: 4px;\n z-index: 1;\n animation: cf-multi-pulse 1.4s ease-in-out infinite;\n}\n@keyframes cf-multi-pulse {\n 0%, 100% { box-shadow: 0 0 0 0 rgba(62,207,142,0.0); }\n 50% { box-shadow: 0 0 0 3px rgba(62,207,142,0.25); }\n}\n\n/* Live presence cursors (multi-cursor collaboration) */\n.cf-cursor {\n position: fixed;\n z-index: 6;\n pointer-events: none;\n display: flex;\n align-items: flex-start;\n gap: 4px;\n /* Glide to new positions so multiple actors read as \"live\". */\n transition: top .12s ease, left .12s ease;\n will-change: top, left;\n}\n.cf-cursor-arrow { display: block; filter: drop-shadow(0 1px 2px rgba(0,0,0,0.4)); }\n.cf-cursor-label {\n transform: translateY(2px);\n background: var(--cf-cursor, #a78bfa);\n color: #0b0b0f;\n font: 700 11px -apple-system, system-ui;\n padding: 2px 7px;\n border-radius: 8px;\n white-space: nowrap;\n box-shadow: 0 2px 8px rgba(0,0,0,0.35);\n}\n.cf-cursor-human .cf-cursor-label { color: #18181b; }\n.cf-cursor-agent .cf-cursor-label { color: #0b0b0f; }\n\n/* Pins */\n.cf-pin {\n position: fixed;\n width: 22px; height: 22px;\n border-radius: 50% 50% 50% 2px;\n background: var(--cf-pin, #a78bfa);\n color: #fff;\n border: 2px solid rgba(255,255,255,0.9);\n font: 700 11px -apple-system, system-ui;\n display: flex; align-items: center; justify-content: center;\n cursor: pointer;\n pointer-events: auto;\n box-shadow: 0 2px 8px rgba(0,0,0,0.35);\n z-index: 3;\n transition: transform .12s cubic-bezier(.34,1.56,.64,1);\n padding: 0;\n /* Pop in when a pin first renders so new annotations are obvious. */\n animation: cf-pin-pop .32s cubic-bezier(.34,1.56,.64,1) both;\n}\n.cf-pin:hover { transform: scale(1.2); }\n.cf-pin.resolved { opacity: 0.45; }\n/* Agent-pushed pins pulse a ring so reviewers spot what the agent added. */\n.cf-pin.agent { border-style: dashed; }\n.cf-pin.agent::after {\n content: \"\";\n position: absolute; inset: -4px;\n border-radius: inherit;\n border: 2px solid var(--cf-pin, #a78bfa);\n animation: cf-pin-ring 1.6s ease-out 3;\n pointer-events: none;\n}\n\n@keyframes cf-pin-pop {\n 0% { transform: scale(0); opacity: 0; }\n 60% { transform: scale(1.25); opacity: 1; }\n 100% { transform: scale(1); opacity: 1; }\n}\n@keyframes cf-pin-ring {\n 0% { transform: scale(1); opacity: .7; }\n 100% { transform: scale(2.4); opacity: 0; }\n}\n\n/* Toolbar */\n.cf-toolbar {\n position: fixed;\n left: 16px; bottom: 16px;\n pointer-events: auto;\n background: var(--cf-bg);\n border: 1px solid var(--cf-border);\n border-radius: 14px;\n padding: 10px;\n display: flex; flex-direction: column; gap: 8px;\n backdrop-filter: blur(16px) saturate(140%);\n box-shadow: 0 16px 48px rgba(0,0,0,0.5);\n min-width: 220px;\n z-index: 4;\n}\n.cf-toolbar-head {\n display: flex; align-items: center; gap: 7px;\n font-weight: 700; letter-spacing: 0.02em;\n}\n.cf-logo-dot {\n width: 8px; height: 8px; border-radius: 50%;\n background: var(--cf-accent);\n box-shadow: 0 0 10px var(--cf-accent);\n}\n.cf-count {\n margin-left: auto;\n font: 700 11px -apple-system, system-ui;\n color: var(--cf-muted);\n background: rgba(255,255,255,0.08);\n padding: 1px 7px; border-radius: 8px;\n}\n.cf-overlay[data-theme=\"light\"] .cf-count { background: rgba(0,0,0,0.06); }\n\n.cf-seg {\n display: flex; gap: 2px;\n background: rgba(255,255,255,0.06);\n border-radius: 9px; padding: 2px;\n}\n.cf-overlay[data-theme=\"light\"] .cf-seg { background: rgba(0,0,0,0.05); }\n.cf-seg-btn {\n flex: 1; border: none; background: transparent; color: var(--cf-muted);\n padding: 5px 10px; border-radius: 7px; font: 600 12px -apple-system, system-ui;\n}\n.cf-seg-btn.on {\n background: var(--cf-accent); color: #fff;\n box-shadow: 0 1px 4px rgba(0,0,0,0.3);\n}\n.cf-tools .cf-seg-btn.on { background: rgba(255,255,255,0.16); color: #fff; }\n.cf-overlay[data-theme=\"light\"] .cf-tools .cf-seg-btn.on { background: rgba(0,0,0,0.12); color: #111; }\n.cf-hint { font-size: 11px; color: var(--cf-muted); padding: 0 2px; }\n.cf-commit { width: 100%; }\n\n/* Buttons */\n.cf-btn {\n border: 1px solid var(--cf-border); background: transparent; color: inherit;\n padding: 6px 12px; border-radius: 8px; font: 600 12px -apple-system, system-ui;\n}\n.cf-btn:hover { background: rgba(255,255,255,0.06); }\n.cf-overlay[data-theme=\"light\"] .cf-btn:hover { background: rgba(0,0,0,0.04); }\n.cf-btn-primary {\n background: var(--cf-accent); border-color: var(--cf-accent); color: #fff;\n}\n.cf-btn-primary:hover { background: #9173f0; }\n.cf-btn-primary:disabled { opacity: 0.4; cursor: not-allowed; }\n.cf-btn-ghost { border-color: transparent; color: var(--cf-muted); }\n\n/* Popups (composer + thread) */\n.cf-popup {\n position: fixed;\n left: 16px; bottom: 92px;\n width: 320px;\n pointer-events: auto;\n background: var(--cf-bg);\n border: 1px solid var(--cf-border);\n border-radius: 14px;\n padding: 12px;\n display: flex; flex-direction: column; gap: 10px;\n backdrop-filter: blur(16px) saturate(140%);\n box-shadow: 0 16px 48px rgba(0,0,0,0.55);\n z-index: 5;\n animation: cf-rise .2s cubic-bezier(.16,1,.3,1) both;\n}\n@keyframes cf-rise {\n from { transform: translateY(10px); opacity: 0; }\n to { transform: translateY(0); opacity: 1; }\n}\n.cf-popup-head {\n display: flex; align-items: center; gap: 8px;\n}\n.cf-popup-target {\n font: 600 12px ui-monospace, \"SF Mono\", monospace;\n color: var(--cf-accent);\n overflow: hidden; text-overflow: ellipsis; white-space: nowrap;\n}\n.cf-icon-btn {\n margin-left: auto; border: none; background: transparent;\n color: var(--cf-muted); font-size: 13px; cursor: pointer;\n width: 22px; height: 22px; border-radius: 6px;\n}\n.cf-icon-btn:hover { background: rgba(255,255,255,0.08); }\n\n.cf-textarea {\n width: 100%; min-height: 72px; resize: vertical;\n background: rgba(255,255,255,0.04);\n border: 1px solid var(--cf-border); border-radius: 9px;\n padding: 8px 10px; color: inherit; font: 400 13px -apple-system, system-ui;\n line-height: 1.45;\n}\n.cf-overlay[data-theme=\"light\"] .cf-textarea { background: rgba(0,0,0,0.03); }\n.cf-textarea:focus { outline: none; border-color: var(--cf-accent); }\n.cf-textarea-sm { min-height: 48px; }\n\n.cf-field { display: flex; flex-direction: column; gap: 5px; }\n.cf-field-label {\n font: 700 10px -apple-system, system-ui; letter-spacing: 0.06em;\n text-transform: uppercase; color: var(--cf-muted);\n}\n.cf-chipset { display: flex; flex-wrap: wrap; gap: 5px; }\n.cf-chip {\n border: 1px solid var(--cf-border); background: transparent; color: var(--cf-muted);\n padding: 4px 10px; border-radius: 20px; font: 600 11px -apple-system, system-ui;\n text-transform: capitalize;\n}\n.cf-chip.on {\n background: var(--cf-chip, var(--cf-accent));\n border-color: var(--cf-chip, var(--cf-accent));\n color: #fff;\n}\n.cf-popup-actions { display: flex; gap: 8px; justify-content: flex-end; }\n\n/* Thread */\n.cf-thread-body {\n display: flex; flex-direction: column; gap: 12px;\n max-height: 280px; overflow-y: auto; padding-right: 2px;\n}\n.cf-msg { display: flex; flex-direction: column; gap: 3px; }\n.cf-msg-meta { display: flex; align-items: center; gap: 6px; }\n.cf-avatar { font-size: 12px; }\n.cf-msg-name {\n font: 700 11px -apple-system, system-ui; color: var(--cf-muted);\n}\n.cf-msg-body {\n font-size: 13px; line-height: 1.5; white-space: pre-wrap; word-break: break-word;\n background: rgba(255,255,255,0.04); border-radius: 9px; padding: 7px 10px;\n}\n.cf-overlay[data-theme=\"light\"] .cf-msg-body { background: rgba(0,0,0,0.03); }\n.cf-msg-agent .cf-msg-body { border-left: 2px solid var(--cf-accent); }\n.cf-thread-compose { display: flex; flex-direction: column; gap: 8px; }\n.cf-thread-actions { display: flex; gap: 8px; align-items: center; }\n.cf-thread-actions .cf-btn-primary { margin-left: auto; }\n.cf-resolved-tag { font: 600 11px -apple-system, system-ui; color: #3ecf8e; }\n.cf-tag {\n font: 700 9px -apple-system, system-ui; text-transform: uppercase;\n letter-spacing: 0.05em; padding: 2px 6px; border-radius: 5px;\n background: var(--cf-tag, var(--cf-accent)); color: #fff;\n}\n\n/* Respect reduced-motion: keep the UI usable, drop the motion. */\n@media (prefers-reduced-motion: reduce) {\n .cf-pin, .cf-popup, .cf-multi-box { animation: none !important; }\n .cf-pin.agent::after { display: none; }\n}\n`;var Qe={blocking:\"#ef4444\",important:\"#f59e0b\",suggestion:\"#3ecf8e\"},qn=\"#a78bfa\",Kn=[\"fix\",\"change\",\"question\",\"approve\"],Vn=[\"blocking\",\"important\",\"suggestion\"];function tn(){let e=W.value===\"auto\"?\"dark\":W.value;return Ae.value,d(\"div\",{class:\"cf-overlay\",\"data-theme\":e},[d(\"style\",{key:\"styles\"},Gt),T.value&&!$.value?d(\"div\",{key:\"hover\",class:\"cf-hover\",style:nn(T.value)}):null,...P.value.map((t,n)=>Qn(t,n)),d(\"div\",{key:\"pins\"},x.value.map((t,n)=>Gn(t,n+1))),d(\"div\",{key:\"cursors\"},N.value.map(t=>eo(t))),Xn(),$.value?d(no,{key:\"composer\",target:$.value}):null,B.value?d(ro,{key:\"thread\",id:B.value}):null])}function Xn(){let e=A.value===\"feedback\",t=x.value.length,n=P.value.length;return d(\"div\",{key:\"toolbar\",class:\"cf-toolbar\"},[d(\"div\",{key:\"head\",class:\"cf-toolbar-head\"},[d(\"span\",{key:\"dot\",class:\"cf-logo-dot\"}),d(\"span\",{key:\"label\"},\"Annotations\"),d(\"span\",{key:\"count\",class:\"cf-count\"},String(t))]),d(\"div\",{key:\"modes\",class:\"cf-seg\"},[re(\"View\",A.value===\"view\",()=>{A.value=\"view\",T.value=null,P.value=[]}),re(\"Comment\",e,()=>{A.value=\"feedback\"})]),e?d(\"div\",{key:\"tools\",class:\"cf-seg cf-tools\"},[re(\"Element\",E.value===\"element\",()=>{E.value=\"element\",P.value=[]}),re(\"Text\",E.value===\"text\",()=>{E.value=\"text\",P.value=[]}),re(\"Multi\",E.value===\"multi\",()=>{E.value=\"multi\"})]):null,e&&E.value===\"multi\"&&n?d(\"button\",{key:\"commit\",class:\"cf-btn cf-btn-primary cf-commit\",onClick:Kt},`Comment ${n} element${n===1?\"\":\"s\"}`):null,e?d(\"div\",{key:\"hint\",class:\"cf-hint\"},Zn(E.value)):null])}function Zn(e){return e===\"text\"?\"Select text on the page to annotate it.\":e===\"multi\"?\"Click elements to group them, then commit.\":\"Click any element to comment. Esc to exit.\"}function re(e,t,n){return d(\"button\",{key:e,class:`cf-seg-btn${t?\" on\":\"\"}`,onClick:n},e)}function Gn(e,t){let n=Jn(e);if(!n)return null;let o=e.severity?Qe[e.severity]:qn,r=e.status===\"resolved\"||e.status===\"dismissed\";return d(\"button\",{key:e.id,class:`cf-pin${r?\" resolved\":\"\"}${e.author?.kind===\"agent\"?\" agent\":\"\"}`,style:`top:${n.top}px;left:${n.left}px;--cf-pin:${o};`,title:io(e.comment),onClick:()=>{B.value=B.value===e.id?null:e.id}},e.author?.kind===\"agent\"?\"\\u2605\":String(t))}function Jn(e){let t=Ve(e.fullPath??\"\")??Ve(e.elementPath??\"\");if(t){let n=t.getBoundingClientRect();return{top:n.top-11,left:n.left-11}}return e.boundingBox?{top:e.boundingBox.y-(e.isFixed?0:window.scrollY)-11,left:e.boundingBox.x-(e.isFixed?0:window.scrollX)-11}:null}function Qn(e,t){let n=e.getBoundingClientRect();return d(\"div\",{key:`multi-${t}`,class:\"cf-multi-box\",style:nn({top:n.top,left:n.left,width:n.width,height:n.height})})}var Jt=[\"#a78bfa\",\"#3ecf8e\",\"#f59e0b\",\"#38bdf8\",\"#f472b6\"];function eo(e){let t=e.x/100*window.innerWidth,n=e.y-window.scrollY,o=e.color??(e.kind===\"agent\"?Jt[Math.abs(to(e.id))%Jt.length]:\"#ffffff\");return d(\"div\",{key:`cursor-${e.id}`,class:`cf-cursor cf-cursor-${e.kind}`,style:`top:${n}px;left:${t}px;--cf-cursor:${o};`},[d(\"svg\",{key:\"arrow\",width:\"18\",height:\"18\",viewBox:\"0 0 18 18\",class:\"cf-cursor-arrow\"},d(\"path\",{d:\"M2 2 L2 14 L6 10 L9 16 L11 15 L8 9 L14 9 Z\",fill:o,stroke:\"rgba(0,0,0,0.35)\",\"stroke-width\":\"0.75\"})),d(\"span\",{key:\"label\",class:\"cf-cursor-label\"},`${e.kind===\"agent\"?\"\\u{1F916} \":\"\"}${e.label}`)])}function to(e){let t=0;for(let n=0;n<e.length;n++)t=(t<<5)-t+e.charCodeAt(n);return t}function no({target:e}){let[t,n]=ee(\"\"),[o,r]=ee(\"change\"),[i,s]=ee(\"important\"),c=()=>{let u=t.trim();u&&(G.addAnnotation({...e,comment:u,intent:o,severity:i,kind:\"feedback\",author:L.value}),$.value=null)},f=()=>{$.value=null},l=e.isMultiSelect?`${e.elementBoundingBoxes?.length??0} elements`:e.selectedText?`\"${ao(e.selectedText,40)}\"`:`<${e.element}>`;return d(\"div\",{class:\"cf-popup cf-composer\"},[d(\"div\",{key:\"head\",class:\"cf-popup-head\"},[d(\"span\",{key:\"t\",class:\"cf-popup-target\"},l),d(\"button\",{key:\"x\",class:\"cf-icon-btn\",onClick:f,title:\"Cancel\"},\"\\u2715\")]),d(\"textarea\",{key:\"ta\",class:\"cf-textarea\",placeholder:\"Describe the change\\u2026 (Markdown supported)\",autofocus:!0,value:t,onInput:u=>n(u.target.value),onKeyDown:u=>{(u.metaKey||u.ctrlKey)&&u.key===\"Enter\"&&c()}}),d(\"div\",{key:\"intent\",class:\"cf-field\"},[d(\"span\",{key:\"l\",class:\"cf-field-label\"},\"Intent\"),d(\"div\",{key:\"g\",class:\"cf-chipset\"},Kn.map(u=>Qt(u,o===u,oo,()=>r(u))))]),d(\"div\",{key:\"sev\",class:\"cf-field\"},[d(\"span\",{key:\"l\",class:\"cf-field-label\"},\"Severity\"),d(\"div\",{key:\"g\",class:\"cf-chipset\"},Vn.map(u=>Qt(u,i===u,Qe[u],()=>s(u))))]),d(\"div\",{key:\"actions\",class:\"cf-popup-actions\"},[d(\"button\",{key:\"c\",class:\"cf-btn\",onClick:f},\"Cancel\"),d(\"button\",{key:\"s\",class:\"cf-btn cf-btn-primary\",disabled:!t.trim(),onClick:c},\"Comment\")])])}var oo=\"#8b94a3\";function Qt(e,t,n,o){return d(\"button\",{key:e,class:`cf-chip${t?\" on\":\"\"}`,style:t?`--cf-chip:${n};`:void 0,onClick:o},e)}function ro({id:e}){let[t,n]=ee(\"\"),o=x.value.find(i=>i.id===e);if(!o)return null;let r=()=>{let i=t.trim();i&&(G.replyToAnnotation(e,{role:L.value.kind,content:i}),n(\"\"))};return d(\"div\",{class:\"cf-popup cf-thread\"},[d(\"div\",{key:\"head\",class:\"cf-popup-head\"},[d(\"span\",{key:\"t\",class:\"cf-popup-target\"},`<${o.element}>`),o.severity?d(\"span\",{key:\"sev\",class:\"cf-tag\",style:`--cf-tag:${Qe[o.severity]};`},o.severity):null,d(\"button\",{key:\"x\",class:\"cf-icon-btn\",onClick:()=>B.value=null,title:\"Close\"},\"\\u2715\")]),d(\"div\",{key:\"body\",class:\"cf-thread-body\"},[en(o.author?.kind??\"human\",o.author?.displayName??\"You\",o.comment,\"root\"),...(o.thread??[]).map(i=>en(i.role,i.role===\"agent\"?\"Agent\":\"You\",i.content,i.id))]),d(\"div\",{key:\"compose\",class:\"cf-thread-compose\"},[d(\"textarea\",{key:\"ta\",class:\"cf-textarea cf-textarea-sm\",placeholder:\"Reply\\u2026\",value:t,onInput:i=>n(i.target.value),onKeyDown:i=>{(i.metaKey||i.ctrlKey)&&i.key===\"Enter\"&&r()}}),d(\"div\",{key:\"row\",class:\"cf-thread-actions\"},[o.status!==\"resolved\"?d(\"button\",{key:\"resolve\",class:\"cf-btn cf-btn-ghost\",onClick:()=>G.resolveAnnotation(e,L.value.kind)},\"Resolve\"):d(\"span\",{key:\"resolved\",class:\"cf-resolved-tag\"},\"\\u2713 resolved\"),d(\"button\",{key:\"send\",class:\"cf-btn cf-btn-primary\",disabled:!t.trim(),onClick:r},\"Reply\")])])])}function en(e,t,n,o){return d(\"div\",{key:o,class:`cf-msg cf-msg-${e}`},[d(\"div\",{key:\"meta\",class:\"cf-msg-meta\"},[d(\"span\",{key:\"av\",class:`cf-avatar cf-avatar-${e}`},e===\"agent\"?\"\\u{1F916}\":\"\\u{1F9D1}\"),d(\"span\",{key:\"n\",class:\"cf-msg-name\"},t)]),d(\"div\",{key:\"c\",class:\"cf-msg-body\"},n)])}function nn(e){return`top:${e.top}px;left:${e.left}px;width:${e.width}px;height:${e.height}px;`}function io(e){let t=e.trim(),n=t.indexOf(`\n`);return n>0?t.slice(0,n):t}function ao(e,t){return e.length>t?`${e.slice(0,t-1)}\\u2026`:e}var on=!1;function rn(e={}){if(Ht(e),e.author&&(L.value=e.author),e.mode&&(A.value=e.mode),e.theme&&(W.value=e.theme),!on){on=!0;let{host:t,appRoot:n}=Zt();Yt(t),Vt(),mt(d(tn,{}),n);let o=()=>{Ae.value++};window.addEventListener(\"scroll\",o,{passive:!0,capture:!0}),window.addEventListener(\"resize\",o,{passive:!0})}Dt.value=!0,console.info(\"[annotations v1] ready on\",location.href)}var so=Object.assign({__init:rn},G);window.__annotations=so;rn();})();\n";
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Install-helper tests: the CDP injectors emit the bundle + a fully
|
|
3
|
+
* populated `__init` call, and the combined-overlay helper hits both
|
|
4
|
+
* CDP methods. Exercised with a fake CdpSession that records calls.
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
import { describe, expect, it } from "vitest";
|
|
8
|
+
|
|
9
|
+
import {
|
|
10
|
+
buildAnnotationsInstallSource,
|
|
11
|
+
buildInitCall,
|
|
12
|
+
installAnnotationsOverlay,
|
|
13
|
+
installOnNewDocument,
|
|
14
|
+
type CdpSession,
|
|
15
|
+
} from "./install.js";
|
|
16
|
+
|
|
17
|
+
const BUNDLE = "/*bundle*/window.__annotations={};";
|
|
18
|
+
const OPTS = {
|
|
19
|
+
bundleSource: BUNDLE,
|
|
20
|
+
webhookUrl: "https://worker.example/api/sessions/sid/annotations/webhook",
|
|
21
|
+
sessionId: "cf_sid",
|
|
22
|
+
author: { kind: "human" as const, id: "human", displayName: "You" },
|
|
23
|
+
mode: "feedback" as const,
|
|
24
|
+
};
|
|
25
|
+
|
|
26
|
+
function fakeCdp() {
|
|
27
|
+
const calls: Array<{ method: string; params: unknown }> = [];
|
|
28
|
+
const cdp: CdpSession = {
|
|
29
|
+
async send(method, params) {
|
|
30
|
+
calls.push({ method, params });
|
|
31
|
+
return { identifier: "id-1" };
|
|
32
|
+
},
|
|
33
|
+
};
|
|
34
|
+
return { cdp, calls };
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
describe("buildInitCall", () => {
|
|
38
|
+
it("serializes every provided session field", () => {
|
|
39
|
+
const s = buildInitCall(OPTS);
|
|
40
|
+
expect(s).toContain("__init(");
|
|
41
|
+
expect(s).toContain(OPTS.webhookUrl);
|
|
42
|
+
expect(s).toContain("cf_sid");
|
|
43
|
+
expect(s).toContain('"author"');
|
|
44
|
+
expect(s).toContain("feedback");
|
|
45
|
+
// Guarded so a bare re-inject doesn't throw.
|
|
46
|
+
expect(s.startsWith(";if(window.__annotations)")).toBe(true);
|
|
47
|
+
});
|
|
48
|
+
|
|
49
|
+
it("omits absent fields", () => {
|
|
50
|
+
expect(buildInitCall({ bundleSource: BUNDLE })).not.toContain("sessionId");
|
|
51
|
+
});
|
|
52
|
+
});
|
|
53
|
+
|
|
54
|
+
describe("buildAnnotationsInstallSource", () => {
|
|
55
|
+
it("appends the init call to the bundle", () => {
|
|
56
|
+
const src = buildAnnotationsInstallSource(OPTS);
|
|
57
|
+
expect(src.startsWith(BUNDLE)).toBe(true);
|
|
58
|
+
expect(src).toContain("__init(");
|
|
59
|
+
});
|
|
60
|
+
});
|
|
61
|
+
|
|
62
|
+
describe("installAnnotationsOverlay", () => {
|
|
63
|
+
it("registers on new document AND evaluates in the current one", async () => {
|
|
64
|
+
const { cdp, calls } = fakeCdp();
|
|
65
|
+
await installAnnotationsOverlay(cdp, OPTS);
|
|
66
|
+
expect(calls.map((c) => c.method)).toEqual([
|
|
67
|
+
"Page.addScriptToEvaluateOnNewDocument",
|
|
68
|
+
"Runtime.evaluate",
|
|
69
|
+
]);
|
|
70
|
+
for (const c of calls) {
|
|
71
|
+
const params = c.params as { source?: string; expression?: string };
|
|
72
|
+
const payload = params.source ?? params.expression ?? "";
|
|
73
|
+
expect(payload).toContain("cf_sid");
|
|
74
|
+
}
|
|
75
|
+
});
|
|
76
|
+
});
|
|
77
|
+
|
|
78
|
+
describe("installOnNewDocument", () => {
|
|
79
|
+
it("returns the script identifier from CDP", async () => {
|
|
80
|
+
const { cdp } = fakeCdp();
|
|
81
|
+
const result = await installOnNewDocument(cdp, OPTS);
|
|
82
|
+
expect(result.identifier).toBe("id-1");
|
|
83
|
+
});
|
|
84
|
+
});
|
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* CDP install helpers.
|
|
3
|
+
*
|
|
4
|
+
* `ANNOTATIONS_V1_BUNDLE_SOURCE` is the actual minified IIFE source,
|
|
5
|
+
* generated by `build:v1` into `./bundle-source.generated.ts` and
|
|
6
|
+
* re-exported here so every consumer (overlay install,
|
|
7
|
+
* Storybook demo, tests) gets the real bundle — not an empty string.
|
|
8
|
+
* Regenerate with `pnpm build`.
|
|
9
|
+
*
|
|
10
|
+
* The `Page.addScriptToEvaluateOnNewDocument` + `Runtime.evaluate`
|
|
11
|
+
* combo is the one piece of the architecture inspired by agentation;
|
|
12
|
+
* clean-room rewrite below.
|
|
13
|
+
*/
|
|
14
|
+
|
|
15
|
+
import { ANNOTATIONS_V1_BUNDLE_SOURCE } from "./bundle-source.generated.js";
|
|
16
|
+
|
|
17
|
+
export { ANNOTATIONS_V1_BUNDLE_SOURCE };
|
|
18
|
+
|
|
19
|
+
export interface InstallOptions {
|
|
20
|
+
/** The minified IIFE source. Override the build-time default. */
|
|
21
|
+
bundleSource?: string;
|
|
22
|
+
/** Webhook URL the library POSTs events to. */
|
|
23
|
+
webhookUrl?: string;
|
|
24
|
+
/** Stable session id so the host can correlate events. */
|
|
25
|
+
sessionId?: string;
|
|
26
|
+
/** Identity stamped on annotations + replies authored in-page. */
|
|
27
|
+
author?: { kind: "human" | "agent"; id?: string; displayName?: string };
|
|
28
|
+
/** Initial UI mode. */
|
|
29
|
+
mode?: "view" | "feedback" | "layout";
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
/**
|
|
33
|
+
* Minimal CDP session shape. The variants-editor worker uses the
|
|
34
|
+
* raw chrome-remote-interface client; the kernel browser exposes
|
|
35
|
+
* an equivalent `.send(method, params)` surface (with an optional
|
|
36
|
+
* third options arg, which this interface tolerates).
|
|
37
|
+
*/
|
|
38
|
+
export interface CdpSession {
|
|
39
|
+
send(method: string, params?: unknown, options?: unknown): Promise<unknown>;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
/** The `__init({...})` call appended after the bundle source. */
|
|
43
|
+
export function buildInitCall(opts: InstallOptions): string {
|
|
44
|
+
const initOpts: {
|
|
45
|
+
webhookUrl?: string;
|
|
46
|
+
sessionId?: string;
|
|
47
|
+
author?: InstallOptions["author"];
|
|
48
|
+
mode?: InstallOptions["mode"];
|
|
49
|
+
} = {};
|
|
50
|
+
if (opts.webhookUrl) initOpts.webhookUrl = opts.webhookUrl;
|
|
51
|
+
if (opts.sessionId) initOpts.sessionId = opts.sessionId;
|
|
52
|
+
if (opts.author) initOpts.author = opts.author;
|
|
53
|
+
if (opts.mode) initOpts.mode = opts.mode;
|
|
54
|
+
// Defensive: only re-init if the bundle is already loaded.
|
|
55
|
+
return `;if(window.__annotations){window.__annotations.__init(${JSON.stringify(initOpts)});}`;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
/**
|
|
59
|
+
* The full string a host evaluates to install + initialise the
|
|
60
|
+
* overlay: the IIFE bundle followed by the `__init` call. Exposed so
|
|
61
|
+
* hosts (e.g. the host app) can build the source once and inject it via
|
|
62
|
+
* their own CDP transport without importing the bundle separately —
|
|
63
|
+
* keeping intermediate packages free of an `@coframe-gtm/annotations`
|
|
64
|
+
* dependency.
|
|
65
|
+
*/
|
|
66
|
+
export function buildAnnotationsInstallSource(opts: InstallOptions = {}): string {
|
|
67
|
+
return combinedSource(opts);
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
function combinedSource(opts: InstallOptions): string {
|
|
71
|
+
const src = opts.bundleSource ?? ANNOTATIONS_V1_BUNDLE_SOURCE;
|
|
72
|
+
if (!src) {
|
|
73
|
+
throw new Error(
|
|
74
|
+
"ANNOTATIONS_V1_BUNDLE_SOURCE is empty. Build the bundle first " +
|
|
75
|
+
"(`pnpm build`) or " +
|
|
76
|
+
"pass `bundleSource` explicitly.",
|
|
77
|
+
);
|
|
78
|
+
}
|
|
79
|
+
return `${src}\n${buildInitCall(opts)}`;
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
/**
|
|
83
|
+
* Run the bundle once in the current document. Idempotent — the
|
|
84
|
+
* library's own init checks already short-circuit re-mounts.
|
|
85
|
+
*/
|
|
86
|
+
export async function installInCurrentDocument(
|
|
87
|
+
cdp: CdpSession,
|
|
88
|
+
opts: InstallOptions = {},
|
|
89
|
+
): Promise<void> {
|
|
90
|
+
await cdp.send("Runtime.evaluate", {
|
|
91
|
+
expression: combinedSource(opts),
|
|
92
|
+
awaitPromise: false,
|
|
93
|
+
});
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
/**
|
|
97
|
+
* Run the bundle on every subsequent document load — for kernel
|
|
98
|
+
* sessions that navigate between pages and need the library to
|
|
99
|
+
* re-attach.
|
|
100
|
+
*/
|
|
101
|
+
export async function installOnNewDocument(
|
|
102
|
+
cdp: CdpSession,
|
|
103
|
+
opts: InstallOptions = {},
|
|
104
|
+
): Promise<{ identifier: string }> {
|
|
105
|
+
const result = (await cdp.send("Page.addScriptToEvaluateOnNewDocument", {
|
|
106
|
+
source: combinedSource(opts),
|
|
107
|
+
})) as { identifier: string };
|
|
108
|
+
return result;
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
/**
|
|
112
|
+
* Install both ways in one call: register on every future document
|
|
113
|
+
* (cross-navigation persistence) AND run once in the current document
|
|
114
|
+
* so the overlay appears immediately. This is the path kernel hosts
|
|
115
|
+
* use when a browser session opens. Both calls share the
|
|
116
|
+
* same combined source, so re-running is idempotent (the bundle's own
|
|
117
|
+
* mount + `__init` guards short-circuit a double mount).
|
|
118
|
+
*/
|
|
119
|
+
export async function installAnnotationsOverlay(
|
|
120
|
+
cdp: CdpSession,
|
|
121
|
+
opts: InstallOptions = {},
|
|
122
|
+
): Promise<void> {
|
|
123
|
+
const source = combinedSource(opts);
|
|
124
|
+
await cdp.send("Page.addScriptToEvaluateOnNewDocument", { source });
|
|
125
|
+
await cdp.send("Runtime.evaluate", { expression: source, awaitPromise: false });
|
|
126
|
+
}
|
package/src/output.ts
ADDED
|
@@ -0,0 +1,171 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* AFS-compatible Markdown output formatters.
|
|
3
|
+
*
|
|
4
|
+
* Four detail levels mirroring agentation.com/output:
|
|
5
|
+
*
|
|
6
|
+
* - `compact` — Element, path, comment. Bare minimum for chat.
|
|
7
|
+
* - `standard` — Adds bounding box, React tree, severity, intent.
|
|
8
|
+
* - `detailed` — Adds nearby text, CSS classes, accessibility,
|
|
9
|
+
* selected text, thread digest.
|
|
10
|
+
* - `forensic` — Everything: computed styles, fullPath, nearby
|
|
11
|
+
* elements, isFixed/isMultiSelect, layout-mode
|
|
12
|
+
* placement/rearrange blobs, every thread message.
|
|
13
|
+
*
|
|
14
|
+
* `forensic` is the recommended default for piping into an agent so
|
|
15
|
+
* the agent has every possible disambiguator when locating the
|
|
16
|
+
* referenced element in source.
|
|
17
|
+
*/
|
|
18
|
+
|
|
19
|
+
import type {
|
|
20
|
+
Annotation,
|
|
21
|
+
AnnotationIntent,
|
|
22
|
+
AnnotationSeverity,
|
|
23
|
+
BoundingBox,
|
|
24
|
+
ThreadMessage,
|
|
25
|
+
} from "./types.js";
|
|
26
|
+
|
|
27
|
+
export type OutputDetail = "compact" | "standard" | "detailed" | "forensic";
|
|
28
|
+
|
|
29
|
+
const SEVERITY_ICON: Record<AnnotationSeverity, string> = {
|
|
30
|
+
blocking: "🔴",
|
|
31
|
+
important: "🟠",
|
|
32
|
+
suggestion: "🟡",
|
|
33
|
+
};
|
|
34
|
+
|
|
35
|
+
const INTENT_VERB: Record<AnnotationIntent, string> = {
|
|
36
|
+
fix: "Fix",
|
|
37
|
+
change: "Change",
|
|
38
|
+
question: "Question",
|
|
39
|
+
approve: "Approve",
|
|
40
|
+
};
|
|
41
|
+
|
|
42
|
+
export interface FormatOptions {
|
|
43
|
+
detail?: OutputDetail;
|
|
44
|
+
/** Heading level for the annotation block. Defaults to 2 (##). */
|
|
45
|
+
headingLevel?: number;
|
|
46
|
+
/** Annotation index used in the heading ("#1", "#2"). */
|
|
47
|
+
index?: number;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
export function formatAnnotation(a: Annotation, opts: FormatOptions = {}): string {
|
|
51
|
+
const detail = opts.detail ?? "forensic";
|
|
52
|
+
const level = opts.headingLevel ?? 2;
|
|
53
|
+
const idx = opts.index;
|
|
54
|
+
const heading = `${"#".repeat(level)} Annotation${idx !== undefined ? ` #${idx}` : ""}`;
|
|
55
|
+
const lines: string[] = [heading];
|
|
56
|
+
|
|
57
|
+
// The compact tier always carries these.
|
|
58
|
+
lines.push(...kvLine("Element", a.element));
|
|
59
|
+
lines.push(...kvLine("Path", a.elementPath));
|
|
60
|
+
if (a.url) lines.push(...kvLine("URL", a.url));
|
|
61
|
+
|
|
62
|
+
if (a.severity) lines.push(...kvLine("Severity", `${SEVERITY_ICON[a.severity]} ${a.severity}`));
|
|
63
|
+
if (a.intent) lines.push(...kvLine("Intent", INTENT_VERB[a.intent]));
|
|
64
|
+
if (a.status) lines.push(...kvLine("Status", a.status));
|
|
65
|
+
|
|
66
|
+
if (detail !== "compact") {
|
|
67
|
+
if (a.reactComponents) lines.push(...kvLine("React", a.reactComponents));
|
|
68
|
+
if (a.boundingBox) lines.push(...kvLine("Position", formatBox(a.boundingBox)));
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
if (detail === "detailed" || detail === "forensic") {
|
|
72
|
+
if (a.selectedText) lines.push(...kvLine("Selected text", quote(a.selectedText)));
|
|
73
|
+
if (a.nearbyText) lines.push(...kvLine("Nearby text", quote(a.nearbyText)));
|
|
74
|
+
if (a.cssClasses) lines.push(...kvLine("Classes", a.cssClasses));
|
|
75
|
+
if (a.accessibility) lines.push(...kvLine("Accessibility", a.accessibility));
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
if (detail === "forensic") {
|
|
79
|
+
if (a.isFixed) lines.push(...kvLine("Fixed positioning", "yes"));
|
|
80
|
+
if (a.isMultiSelect) lines.push(...kvLine("Multi-select", "yes"));
|
|
81
|
+
if (a.fullPath) lines.push(...kvLine("Full path", a.fullPath));
|
|
82
|
+
if (a.nearbyElements) lines.push(...kvLine("Nearby elements", a.nearbyElements));
|
|
83
|
+
if (a.computedStyles) {
|
|
84
|
+
lines.push("**Computed styles:**");
|
|
85
|
+
lines.push("```");
|
|
86
|
+
lines.push(a.computedStyles);
|
|
87
|
+
lines.push("```");
|
|
88
|
+
}
|
|
89
|
+
if (a.elementBoundingBoxes?.length) {
|
|
90
|
+
lines.push("**Per-element boxes:**");
|
|
91
|
+
for (const b of a.elementBoundingBoxes) lines.push(`- ${formatBox(b)}`);
|
|
92
|
+
}
|
|
93
|
+
if (a.kind === "placement" && a.placement) {
|
|
94
|
+
lines.push("**Placement:**");
|
|
95
|
+
lines.push("```json");
|
|
96
|
+
lines.push(JSON.stringify(a.placement, null, 2));
|
|
97
|
+
lines.push("```");
|
|
98
|
+
}
|
|
99
|
+
if (a.kind === "rearrange" && a.rearrange) {
|
|
100
|
+
lines.push("**Rearrange:**");
|
|
101
|
+
lines.push("```json");
|
|
102
|
+
lines.push(JSON.stringify(a.rearrange, null, 2));
|
|
103
|
+
lines.push("```");
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
lines.push("");
|
|
108
|
+
lines.push("**Comment:**");
|
|
109
|
+
lines.push("");
|
|
110
|
+
lines.push(a.comment.trim());
|
|
111
|
+
|
|
112
|
+
if (a.thread?.length) {
|
|
113
|
+
lines.push("");
|
|
114
|
+
lines.push("**Thread:**");
|
|
115
|
+
const slice = detail === "forensic" ? a.thread : a.thread.slice(-3);
|
|
116
|
+
for (const msg of slice) lines.push(formatThreadMessage(msg));
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
return lines.join("\n");
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
export interface BundleOptions extends FormatOptions {
|
|
123
|
+
/** Page URL to surface in the bundle header. */
|
|
124
|
+
pageUrl?: string;
|
|
125
|
+
/** Optional session id. */
|
|
126
|
+
sessionId?: string;
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
export function formatAnnotationBundle(
|
|
130
|
+
annotations: Annotation[],
|
|
131
|
+
opts: BundleOptions = {},
|
|
132
|
+
): string {
|
|
133
|
+
const detail = opts.detail ?? "forensic";
|
|
134
|
+
const header: string[] = [
|
|
135
|
+
`# Annotations`,
|
|
136
|
+
"",
|
|
137
|
+
opts.pageUrl ? `URL: ${opts.pageUrl}` : "",
|
|
138
|
+
opts.sessionId ? `Session: ${opts.sessionId}` : "",
|
|
139
|
+
`Detail: ${detail}`,
|
|
140
|
+
`Count: ${annotations.length}`,
|
|
141
|
+
`Captured: ${new Date().toISOString()}`,
|
|
142
|
+
"",
|
|
143
|
+
"---",
|
|
144
|
+
"",
|
|
145
|
+
].filter(Boolean);
|
|
146
|
+
|
|
147
|
+
const blocks = annotations.map((a, i) =>
|
|
148
|
+
formatAnnotation(a, { ...opts, index: i + 1 }),
|
|
149
|
+
);
|
|
150
|
+
|
|
151
|
+
return [...header, blocks.join("\n\n---\n\n")].join("\n");
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
function kvLine(key: string, value: string): string[] {
|
|
155
|
+
return [`**${key}:** ${value}`];
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
function formatBox(b: BoundingBox): string {
|
|
159
|
+
return `${Math.round(b.x)}px, ${Math.round(b.y)}px (${Math.round(b.width)}×${Math.round(b.height)}px)`;
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
function quote(text: string): string {
|
|
163
|
+
const max = 240;
|
|
164
|
+
const t = text.length > max ? `${text.slice(0, max - 1)}…` : text;
|
|
165
|
+
return `"${t.replace(/\s+/g, " ").trim()}"`;
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
function formatThreadMessage(msg: ThreadMessage): string {
|
|
169
|
+
const author = msg.role === "agent" ? "🤖 agent" : "🧑 human";
|
|
170
|
+
return `- _${author}_: ${msg.content.trim()}`;
|
|
171
|
+
}
|