@agentstats/sdk 0.4.1 → 0.5.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 +10 -0
- package/dist/bots.cjs +1022 -0
- package/dist/bots.d.cts +265 -0
- package/dist/bots.d.ts +265 -0
- package/dist/bots.js +1010 -0
- package/dist/browser.iife.js +1 -1
- package/dist/index.cjs +182 -16
- package/dist/index.d.cts +3 -5
- package/dist/index.d.ts +3 -5
- package/dist/index.js +182 -16
- package/dist/lite.iife.js +1 -1
- package/dist/server.cjs +293 -204
- package/dist/server.d.cts +76 -18
- package/dist/server.d.ts +76 -18
- package/dist/server.js +293 -204
- package/package.json +21 -12
package/dist/browser.iife.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
var AgentStatsSDK=(function(e){Object.defineProperty(e,Symbol.toStringTag,{value:`Module`});let t=`agentstats:locationchange`,n=Symbol.for(`agentstats.patched`),r=`pdf.xlsx.docx.txt.rtf.csv.exe.key.pps.ppt.pptx.7z.pkg.rar.gz.zip.avi.mov.mp4.mpeg.wmv.midi.mp3.wav.wma.dmg.iso.msi`.split(`.`);function i(e){try{return document.cookie.match(RegExp(`(?:^|; )${e}=([\\w-]{8,64})`))?.[1]}catch{return}}function a(){if(typeof document>`u`||typeof navigator>`u`)return null;if(document.querySelector?.(`#claude-agent-stop-container`))return{name:`claude-in-chrome`,via:`dom`};let e=String(navigator.userAgent??``);return/\bClaude\/\d/.test(e)?{name:`claude-browser`,via:`user-agent`}:i(`_al_v`)?{name:`verified-visit`,via:`visit`}:navigator.webdriver===!0||/HeadlessChrome/.test(e)?{name:`automation`,via:`webdriver`}:null}function o(){if(!(typeof history>`u`))for(let e of[`pushState`,`replaceState`]){let r=history[e];if(typeof r!=`function`||r[n])continue;let i=function(...e){let n=r.apply(this,e);return window.dispatchEvent(new Event(t)),n};Object.defineProperty(i,n,{value:!0}),history[e]=i}}function s(e){let n={pageview(){},track(){},stop(){}};if(typeof window>`u`||typeof document>`u`)return n;let i=(...t)=>e.debug&&console.debug(`[agentstats]`,...t),s=/^localhost$|^127(\.\d+){3}$|^\[::1?\]$|\.local$|^$/.test(location.hostname)||location.protocol===`file:`,c=!1;try{c=localStorage.getItem(`agentstats_ignore`)===`true`}catch{}let l=(t,n)=>{if(c)return i(`ignored: agentstats_ignore is set`);if(s&&!e.allowLocalhost)return i(`ignored on localhost:`,t);let r=JSON.stringify({k:e.key,n:t,u:location.href,r:document.referrer||null,w:window.innerWidth,p:n,a:a()?.name,h:e.hashRouting?1:void 0});i(`send`,t,n??``);try{if(navigator.sendBeacon?.(e.endpoint,r))return}catch{}fetch(e.endpoint,{method:`POST`,body:r,keepalive:!0,headers:{"Content-Type":`text/plain`}}).catch(()=>{})},u=new AbortController,d={signal:u.signal},f=``,p=()=>{if(u.signal.aborted)return;let t=location.pathname+(e.hashRouting?location.hash:``);t!==f&&(f=t,l(`pageview`))};(()=>{if(document.visibilityState!==`prerender`)return p();document.addEventListener(`visibilitychange`,function e(){document.visibilityState!==`prerender`&&(document.removeEventListener(`visibilitychange`,e),p())},d)})(),o();let m=()=>setTimeout(p,0);if(window.addEventListener(t,m,d),window.addEventListener(`popstate`,m,d),e.hashRouting&&window.addEventListener(`hashchange`,m,d),e.outboundLinks||e.fileDownloads){let t=Array.isArray(e.fileDownloads)?e.fileDownloads:e.fileDownloads?r:[],n=n=>{if(n.type===`auxclick`&&n.button!==1)return;let r=n.target?.closest?.(`a[href]`);if(!r)return;let i;try{i=new URL(r.href,location.href)}catch{return}let a=i.pathname.split(`.`).pop()?.toLowerCase()??``;t.includes(a)?l(`File Download`,{url:i.href.split(`?`)[0]}):e.outboundLinks&&/^https?:$/.test(i.protocol)&&i.host!==location.host&&l(`Outbound Link: Click`,{url:i.href.split(`?`)[0]})};document.addEventListener(`click`,n,{capture:!0,signal:u.signal}),document.addEventListener(`auxclick`,n,{capture:!0,signal:u.signal})}return{pageview:p,track:(e,t)=>l(String(e),t),stop:()=>u.abort()}}let c=`0.4.1`;function l(){let e=globalThis.crypto;return e?.randomUUID?e.randomUUID():`xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx`.replace(/[xy]/g,e=>{let t=Math.random()*16|0;return(e===`x`?t:t&3|8).toString(16)})}function u(){return Date.now()}function d(){return typeof performance<`u`&&performance.now?performance.now():Date.now()}function f(e){return!!e&&typeof e==`object`&&e.name===`AbortError`}function p(e,t,n=0){if(n>6)return`[depth]`;if(Array.isArray(e))return e.slice(0,100).map(e=>p(e,t,n+1));if(e&&typeof e==`object`){let r={};for(let[i,a]of Object.entries(e)){let e=i.toLowerCase();r[i]=t.some(t=>e.includes(t))?`[redacted]`:p(a,t,n+1)}return r}return typeof e==`string`&&e.length>1e3?e.slice(0,1e3)+`…`:e}function m(e,t){let n;try{n=typeof e==`string`?e:JSON.stringify(e)}catch{n=String(e)}return n===void 0&&(n=``),n.length>t?n.slice(0,t)+`…`:n}function h(e){try{return JSON.stringify(e)?.length??0}catch{return 0}}function g(e){let t={name:String(e.name??``)};return e.title&&(t.title=String(e.title)),e.description&&(t.description=String(e.description)),e.inputSchema!==void 0&&(t.inputSchema=e.inputSchema),e.annotations&&(t.annotations={...e.annotations}),e.origin&&(t.origin=String(e.origin)),t}function _(){if(typeof document<`u`){let e=document.currentScript;if(e?.src)try{return new URL(`/api/ingest`,e.src).toString()}catch{}}return`https://agentstats.io/api/ingest`}let v=/(^|\.)(chatgpt\.com|chat\.openai\.com|perplexity\.ai|claude\.ai|gemini\.google\.com|bard\.google\.com|copilot\.microsoft\.com|copilot\.cloud\.microsoft|copilot\.com|meta\.ai|deepseek\.com|grok\.com|chat\.mistral\.ai|you\.com|phind\.com|poe\.com|duck\.ai|chat\.qwen\.ai|kimi\.com|kimi\.ai|doubao\.com)$/i,y=/[?&]utm_source=(chatgpt(\.com)?|openai|perplexity(\.ai)?|claude(\.ai)?|gemini|copilot(\.com)?|meta\.?ai|deepseek|grok|mistral|le-?chat)(&|$)/i,b=Symbol.for(`agentstats.patched`),x=Symbol.for(`agentstats.wrapped`);var S=class{constructor(e){if(this.queue=[],this.timer=null,this.snapshotTimer=null,this.pollTimer=null,this.sessionId=``,this.lastActivity=0,this.lastSnapshotHash=``,this.inflight=Promise.resolve(),this.web=null,this.agentPage=``,this.controlStarted=0,!e||!e.key)throw Error("[agentstats] `key` is required");if(this.options={endpoint:_(),captureArgs:!0,captureResults:!1,captureErrors:!0,redactKeys:[],sessionTimeoutMs:18e5,flushIntervalMs:2e3,maxBatchSize:25,autoInstrument:!0,trackAgentBrowsers:!0,trackPageviews:!0,debug:!1,disabled:!1,...Object.fromEntries(Object.entries(e).filter(([,e])=>e!==void 0))},this._fetch=e.fetch??(typeof fetch<`u`?fetch.bind(globalThis):(()=>Promise.reject(Error(`no fetch`)))),this.sessionId=this.loadSession(),!this.options.disabled&&(this.options.autoInstrument&&this.instrument(),this.bindLifecycle(),this.reportReferral(),this.options.trackAgentBrowsers&&this.watchAgentBrowsers(),this.options.trackPageviews)){let e=this.options;this.web=s({key:e.key,endpoint:`${e.endpoint.replace(/\/+$/,``)}/web`,hashRouting:e.hashRouting,outboundLinks:e.outboundLinks,fileDownloads:e.fileDownloads,allowLocalhost:e.allowLocalhost,debug:e.debug})}this.log(`initialised`,{endpoint:this.options.endpoint,session:this.sessionId})}wrap(e){if(!e||typeof e.execute!=`function`||e[x])return e;let t=e.execute,n=String(e.name),r=this,i=async function(e,i){let a=d(),o=i?.signal;try{let s=await t.call(this,e,i);return r.recordCall(n,`success`,d()-a,e,s,void 0,o),s}catch(t){let i=o?.aborted||f(t);throw r.recordCall(n,i?`cancelled`:`error`,d()-a,e,void 0,t,o),t}};Object.defineProperty(i,x,{value:!0});let a=Object.assign({},e,{execute:i});return Object.defineProperty(a,x,{value:!0}),a}track(e,t){let n=t?p(t,this.redactKeys()):void 0;this.enqueue({type:`custom`,id:l(),ts:u(),name:e,props:n,url:this.url()}),this.web?.track(e,n)}pageview(){this.web?.pageview()}async snapshot(){let e=this.modelContext();if(!e?.getTools)return[];let t=[];try{t=(await e.getTools()??[]).map(e=>g(e))}catch(e){return this.log(`getTools failed`,e),[]}let n=m(t.map(e=>[e.name,e.description,e.inputSchema,e.annotations]),1e7);return n!==this.lastSnapshotHash&&(this.lastSnapshotHash=n,this.enqueue({type:`tools_snapshot`,id:l(),ts:u(),tools:t,url:this.url()})),t}flush(e=!1){if(this.timer&&=(clearTimeout(this.timer),null),!this.queue.length)return this.inflight;let t=this.queue.splice(0,this.queue.length),n={key:this.options.key,sdk:`js/${c}`,session_id:this.sessionId,sent_at:u(),metadata:this.options.metadata,visit:typeof document<`u`?i(`_al_v`):void 0,client:this.clientHints(),events:t},r=JSON.stringify(n);if(this.log(`flush`,t.length,`events`),e&&typeof navigator<`u`&&navigator.sendBeacon)try{if(navigator.sendBeacon(this.options.endpoint,new Blob([r],{type:`text/plain`})))return Promise.resolve()}catch{}let a=this._fetch(this.options.endpoint,{method:`POST`,body:r,keepalive:!0,headers:{"Content-Type":`text/plain`}}).then(async e=>{e.ok||this.log(`ingest responded`,e.status)}).catch(e=>{this.log(`ingest failed`,e)});return this.inflight=a,a}destroy(){this.timer&&clearTimeout(this.timer),this.snapshotTimer&&clearTimeout(this.snapshotTimer),this.pollTimer&&clearInterval(this.pollTimer),this.timer=this.snapshotTimer=this.pollTimer=null,this.web?.stop(),this.web=null}get session(){return this.sessionId}log(...e){this.options.debug&&console.debug(`[agentstats]`,...e)}url(){return typeof location<`u`?location.href:void 0}redactKeys(){return(this.options.redactKeys??[]).map(e=>e.toLowerCase()).filter(Boolean)}modelContext(){let e=globalThis;return e.document?.modelContext??e.navigator?.modelContext}captureArgs(e,t){let n=this.options.captureArgs;if(n===!1)return;let r=typeof n==`function`?this.callOption(`captureArgs`,()=>n(e,t)):p(t,this.redactKeys());return r!==void 0&&h(r)>8192&&(r={_truncated:!0,preview:m(r,1e3)}),r}captureResult(e,t){let n=this.options.captureResults;if(!n||t===void 0)return;let r=typeof n==`function`?this.callOption(`captureResults`,()=>n(e,t)):t;return r===void 0?void 0:m(r,2048)}captureError(e,t){let n=this.options.captureErrors;if(n===!1)return;let r=t,i=typeof r?.message==`string`?r.message:m(t,1e3);if(typeof n!=`function`)return m(i,1e3);let a=typeof r?.code==`string`||typeof r?.code==`number`?r.code:null,o=this.callOption(`captureErrors`,()=>n({tool:e,message:i,name:typeof r?.name==`string`?r.name:null,code:a,error:t}));return typeof o==`string`&&o?m(o,1e3):void 0}callOption(e,t){try{return t()}catch(t){this.log(`${e} threw`,t);return}}recordCall(e,t,n,r,i,a,o){let s={type:`tool_call`,id:l(),ts:u(),tool:e,status:t,duration_ms:Math.round(n*100)/100,url:this.url()},c=this.captureArgs(e,r);c!==void 0&&(s.args=c);let d=this.captureResult(e,i);if(d!==void 0&&(s.result=d),a!==void 0){let t=this.captureError(e,a);t!==void 0&&(s.error=t);let n=a?.name;n&&(s.error_name=String(n).slice(0,100))}this.enqueue(s)}enqueue(e){this.options.disabled||(this.touchSession(),this.queue.push(e),this.log(`event`,e.type,e.tool??e.name??``),this.queue.length>=this.options.maxBatchSize?this.flush():this.timer||=setTimeout(()=>void this.flush(),this.options.flushIntervalMs))}scheduleSnapshot(e=250){this.snapshotTimer&&clearTimeout(this.snapshotTimer),this.snapshotTimer=setTimeout(()=>{this.snapshotTimer=null,this.snapshot()},e)}instrument(){let e=()=>{let e=this.modelContext();return e?(this.patch(e),!0):!1};if(e())return;let t=0;this.pollTimer=setInterval(()=>{t++,(e()||t>40)&&(this.pollTimer&&clearInterval(this.pollTimer),this.pollTimer=null)},250)}patch(e){if(e[b]){this.log(`modelContext already patched`),this.scheduleSnapshot(0);return}Object.defineProperty(e,b,{value:!0});let t=this;if(typeof e.registerTool==`function`){let n=e.registerTool;e.registerTool=function(e,r){let i=t.wrap(e);return t.enqueue({type:`tool_registered`,id:l(),ts:u(),tool:String(e?.name),descriptor:g(e),url:t.url()}),t.scheduleSnapshot(),n.call(this,i,r)}}if(typeof e.provideContext==`function`){let n=e.provideContext;e.provideContext=function(e){let r=(e?.tools??[]).map(e=>(t.enqueue({type:`tool_registered`,id:l(),ts:u(),tool:String(e?.name),descriptor:g(e),url:t.url()}),t.wrap(e)));return t.scheduleSnapshot(),n.call(this,{...e,tools:r})}}if(typeof e.unregisterTool==`function`){let n=e.unregisterTool;e.unregisterTool=function(e){return t.enqueue({type:`tool_unregistered`,id:l(),ts:u(),tool:String(e),url:t.url()}),t.scheduleSnapshot(),n.call(this,e)}}if(typeof e.clearContext==`function`){let n=e.clearContext;e.clearContext=function(){return t.scheduleSnapshot(),n.call(this)}}if(typeof e.addEventListener==`function`)try{e.addEventListener(`toolchange`,()=>t.scheduleSnapshot())}catch{}this.log(`modelContext patched`),this.scheduleSnapshot(0)}bindLifecycle(){if(typeof window>`u`||typeof window.addEventListener!=`function`)return;let e=()=>void this.flush(!0);window.addEventListener(`pagehide`,e),document.addEventListener(`visibilitychange`,()=>{document.visibilityState===`hidden`&&e()})}clientHints(){if(typeof navigator>`u`)return;let e=String(navigator.userAgent??``).slice(0,1e3),t=navigator.webdriver===!0;return e||t?{ua:e||void 0,webdriver:t||void 0}:void 0}detectAgentBrowser(){return a()}watchAgentBrowsers(){if(typeof document>`u`||typeof window>`u`)return;let e=()=>{let e=this.detectAgentBrowser(),t=this.url();e&&t!==this.agentPage&&(this.agentPage=t??``,this.enqueue({type:`agent_pageview`,id:l(),ts:u(),name:e.name,props:{via:e.via},url:t}))},n=()=>{e(),!(typeof MutationObserver>`u`||!document.body)&&new MutationObserver(()=>{let t=!!document.querySelector(`#claude-agent-stop-container`);if(t&&!this.controlStarted)this.controlStarted=d(),this.enqueue({type:`agent_control`,id:l(),ts:u(),name:`claude-in-chrome`,props:{via:`dom`,phase:`start`},url:this.url()}),e();else if(!t&&this.controlStarted){let e=Math.round(d()-this.controlStarted);this.controlStarted=0,this.enqueue({type:`agent_control`,id:l(),ts:u(),name:`claude-in-chrome`,props:{via:`dom`,phase:`stop`,duration_ms:e},url:this.url()})}}).observe(document.body,{childList:!0})};document.readyState===`loading`?document.addEventListener(`DOMContentLoaded`,n,{once:!0}):n();let r=()=>setTimeout(e,0);window.addEventListener(`popstate`,r),window.addEventListener(t,r),o()}reportReferral(){if(typeof document>`u`||typeof location>`u`)return;let e=``;try{e=document.referrer?new URL(document.referrer).hostname.replace(/^www\./,``):``}catch{}if(!(e&&v.test(e))&&!y.test(location.search))return;let t=`__agentstats_ref_${this.sessionId}`;try{if(sessionStorage.getItem(t))return;sessionStorage.setItem(t,`1`)}catch{}this.enqueue({type:`referral`,id:l(),ts:u(),url:this.url()??location.href,referrer:e?`https://${e}/`:null})}loadSession(){try{let e=sessionStorage.getItem(`__agentstats_session`);if(e){let t=JSON.parse(e);if(t?.id&&u()-t.last<this.options.sessionTimeoutMs)return this.lastActivity=t.last,t.id}}catch{}return l()}touchSession(){let e=u();this.lastActivity&&e-this.lastActivity>this.options.sessionTimeoutMs&&(this.sessionId=l(),this.lastSnapshotHash=``,this.log(`new session`,this.sessionId)),this.lastActivity=e;try{sessionStorage.setItem(`__agentstats_session`,JSON.stringify({id:this.sessionId,last:e}))}catch{}}};let C=null;function w(e){return C&&C.destroy(),C=new S(e),C}function T(){return C}function E(e,t){C?.track(e,t)}function D(e){return C?C.wrap(e):e}function O(){return C?.flush()??Promise.resolve()}function k(){return C?.snapshot()??Promise.resolve([])}function A(){C?.pageview()}let j={init:w,track:E,pageview:A,wrap:D,flush:O,snapshot:k,getClient:T,version:c};window.AgentStats=j;let M=document.currentScript,N=M?.dataset.key,P=e=>e!==void 0&&e!==`false`,F=M?.dataset.fileDownloads;return N&&j.init({key:N,endpoint:M?.dataset.endpoint,debug:M?.dataset.debug===`true`,captureArgs:M?.dataset.captureArgs!==`false`,captureErrors:M?.dataset.captureErrors!==`false`,captureResults:M?.dataset.captureResults===`true`,redactKeys:M?.dataset.redactKeys?.split(`,`).map(e=>e.trim()).filter(Boolean),trackPageviews:M?.dataset.pageviews!==`false`,hashRouting:P(M?.dataset.hashRouting),outboundLinks:P(M?.dataset.outboundLinks),fileDownloads:F&&![``,`true`,`false`].includes(F)?F.split(`,`).map(e=>e.trim()):P(F),allowLocalhost:P(M?.dataset.allowLocalhost)}),e.AgentStats=j,e})({});
|
|
1
|
+
var AgentStatsSDK=(function(e){Object.defineProperty(e,Symbol.toStringTag,{value:`Module`});let t=[10,40,100,250],n=[1,2,6,21],r=(e,t)=>{let n=0;for(;n<t.length&&e>=t[n];)n++;return n},i=e=>!!e&&(e.isContentEditable||e.tagName===`TEXTAREA`||e.tagName===`INPUT`&&/^(text|search|email|url|tel|password|number|)$/.test(e.type)),a=e=>!!e&&(e.isContentEditable||/^(INPUT|TEXTAREA|SELECT)$/.test(e.tagName)),o=e=>{try{return e.matches(`:autofill`)}catch{return!1}};function s(){let e={take:()=>null,stop(){}};if(typeof document>`u`||typeof performance>`u`)return e;let s=()=>performance.now(),c=()=>document.visibilityState===`hidden`||!document.hasFocus(),l=[],u=0,d=0,f=-1e9,p=-1e9,m=-1e9,h=-1e9,g=/* @__PURE__ */ new Map,_=()=>{l=Array.from({length:29},()=>0),l[0]=1,u=s(),d=0};_();let v=e=>{l[2]||(l[2]=Math.max(1,Math.round(e-u)))},y=new AbortController,b=(e,t)=>document.addEventListener(e,t,{capture:!0,passive:!0,signal:y.signal});b(`pointermove`,e=>{e.isTrusted&&(l[3]++,d++)}),b(`pointerdown`,e=>{e.isTrusted&&(m=s(),v(m))}),b(`click`,e=>{if(!e.isTrusted)return void l[26]++;v(s()),c()&&l[27]++,e.detail===0?l[10]++:e.pointerType===`touch`||e.pointerType===`pen`?l[9]++:e.detail===1&&l[4+r(d,n)]++,d=0}),b(`keydown`,e=>{if(!e.isTrusted)return void l[26]++;let n=s();v(n),m=p=n,c()&&l[27]++,e.repeat||e.target?.type===`password`||(n-f<2e3&&l[16+r(n-f,t)]++,f=n,g.set(e.code||e.key,n))}),b(`keyup`,e=>{let n=g.get(e.code||e.key);e.isTrusted&&n!==void 0&&(g.delete(e.code||e.key),l[11+r(s()-n,t)]++)});for(let e of[`paste`,`drop`,`compositionend`])b(e,()=>{p=s()});for(let e of[`wheel`,`touchstart`])b(e,()=>{m=s()});return b(`change`,e=>{!e.isTrusted&&a(e.target)&&l[28]++}),b(`input`,e=>{if(!e.isTrusted)return void(a(e.target)&&l[28]++);if(!i(e.target)||o(e.target))return;let t=s();v(t),c()&&l[27]++;let n=t-p;l[n<100?21:n<1e3?22:23]++}),b(`scroll`,()=>{let e=s();e-h>150&&(l[24]++,e-m>500&&l[25]++),h=e}),{take(){let e=l.slice(3).some(Boolean)?l:null;return e&&(e[1]=Math.min(2**31,Math.round(s()-u))),_(),e},stop:()=>y.abort()}}let c=`agentstats:locationchange`,l=Symbol.for(`agentstats.patched`),u=/* @__PURE__ */ `pdf.xlsx.docx.txt.rtf.csv.exe.key.pps.ppt.pptx.7z.pkg.rar.gz.zip.avi.mov.mp4.mpeg.wmv.midi.mp3.wav.wma.dmg.iso.msi`.split(`.`);function d(e){try{return document.cookie.match(RegExp(`(?:^|; )${e}=([\\w-]{8,64})`))?.[1]}catch{return}}function f(){if(typeof document>`u`||typeof navigator>`u`)return null;if(document.querySelector?.(`#claude-agent-stop-container`))return{name:`claude-in-chrome`,via:`dom`};let e=String(navigator.userAgent??``);return/\bClaude\/\d/.test(e)?{name:`claude-browser`,via:`user-agent`}:d(`_al_v`)?{name:`verified-visit`,via:`visit`}:navigator.webdriver===!0||/HeadlessChrome/.test(e)?{name:`automation`,via:`webdriver`}:null}function p(){if(typeof history<`u`)for(let e of[`pushState`,`replaceState`]){let t=history[e];if(typeof t!=`function`||t[l])continue;let n=function(...e){let n=t.apply(this,e);return window.dispatchEvent(new Event(c)),n};Object.defineProperty(n,l,{value:!0}),history[e]=n}}function m(e){let t={pageview(){},track(){},stop(){}};if(typeof window>`u`||typeof document>`u`)return t;let n=(...t)=>e.debug&&console.debug(`[agentstats]`,...t),r=/^localhost$|^127(\.\d+){3}$|^\[::1?\]$|\.local$|^$/.test(location.hostname)||location.protocol===`file:`,i=!1;try{i=localStorage.getItem(`agentstats_ignore`)===`true`}catch{}let a=(t,a)=>{if(i)return n(`ignored: agentstats_ignore is set`);if(r&&!e.allowLocalhost)return n(`ignored on localhost:`,t);let o=JSON.stringify({k:e.key,...a,a:f()?.name});n(`send`,t);try{if(navigator.sendBeacon?.(e.endpoint,o))return}catch{}fetch(e.endpoint,{method:`POST`,body:o,keepalive:!0,headers:{"Content-Type":`text/plain`}}).catch(()=>{})},o=(t,n)=>a(t,{n:t,u:location.href,r:document.referrer||null,w:window.innerWidth,p:n,h:e.hashRouting?1:void 0}),l=e.agentSignals===!1?null:s(),d=location.href,m=()=>{let e=l?.take();e&&a(`signals`,{t:`s`,u:d,s:e})},h=new AbortController,g={signal:h.signal},_=``,v=()=>{if(h.signal.aborted)return;let t=location.pathname+(e.hashRouting?location.hash:``);t!==_&&(_&&m(),_=t,d=location.href,o(`pageview`))};(()=>{if(document.visibilityState!==`prerender`)return v();document.addEventListener(`visibilitychange`,function e(){document.visibilityState!==`prerender`&&(document.removeEventListener(`visibilitychange`,e),v())},g)})(),p();let y=()=>setTimeout(v,0);if(window.addEventListener(c,y,g),window.addEventListener(`popstate`,y,g),e.hashRouting&&window.addEventListener(`hashchange`,y,g),e.outboundLinks||e.fileDownloads){let t=Array.isArray(e.fileDownloads)?e.fileDownloads:e.fileDownloads?u:[],n=n=>{if(n.type===`auxclick`&&n.button!==1)return;let r=n.target?.closest?.(`a[href]`);if(!r)return;let i;try{i=new URL(r.href,location.href)}catch{return}let a=i.pathname.split(`.`).pop()?.toLowerCase()??``;t.includes(a)?o(`File Download`,{url:i.href.split(`?`)[0]}):e.outboundLinks&&/^https?:$/.test(i.protocol)&&i.host!==location.host&&o(`Outbound Link: Click`,{url:i.href.split(`?`)[0]})};document.addEventListener(`click`,n,{capture:!0,signal:h.signal}),document.addEventListener(`auxclick`,n,{capture:!0,signal:h.signal})}return l&&(window.addEventListener(`pagehide`,m,g),document.addEventListener(`visibilitychange`,()=>document.visibilityState===`hidden`&&m(),g)),{pageview:v,track:(e,t)=>o(String(e),t),stop:()=>{h.signal.aborted||(m(),l?.stop(),h.abort())}}}let h=`0.5.1`;function g(){let e=globalThis.crypto;return e?.randomUUID?e.randomUUID():`xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx`.replace(/[xy]/g,e=>{let t=Math.random()*16|0;return(e===`x`?t:t&3|8).toString(16)})}function _(){return Date.now()}function v(){return typeof performance<`u`&&performance.now?performance.now():Date.now()}function y(e){return!!e&&typeof e==`object`&&e.name===`AbortError`}function b(e,t,n=0){if(n>6)return`[depth]`;if(Array.isArray(e))return e.slice(0,100).map(e=>b(e,t,n+1));if(e&&typeof e==`object`){let r={};for(let[i,a]of Object.entries(e)){let e=i.toLowerCase();r[i]=t.some(t=>e.includes(t))?`[redacted]`:b(a,t,n+1)}return r}return typeof e==`string`&&e.length>1e3?e.slice(0,1e3)+`…`:e}function x(e,t){let n;try{n=typeof e==`string`?e:JSON.stringify(e)}catch{n=String(e)}return n===void 0&&(n=``),n.length>t?n.slice(0,t)+`…`:n}function S(e){try{return JSON.stringify(e)?.length??0}catch{return 0}}function C(e){let t={name:String(e.name??``)};return e.title&&(t.title=String(e.title)),e.description&&(t.description=String(e.description)),e.inputSchema!==void 0&&(t.inputSchema=e.inputSchema),e.annotations&&(t.annotations={...e.annotations}),e.origin&&(t.origin=String(e.origin)),t}function w(){if(typeof document<`u`){let e=document.currentScript;if(e?.src)try{return new URL(`/api/ingest`,e.src).toString()}catch{}}return`https://agentstats.io/api/ingest`}let T=/(^|\.)(chatgpt\.com|chat\.openai\.com|perplexity\.ai|claude\.ai|gemini\.google\.com|bard\.google\.com|copilot\.microsoft\.com|copilot\.cloud\.microsoft|copilot\.com|meta\.ai|deepseek\.com|grok\.com|chat\.mistral\.ai|you\.com|phind\.com|poe\.com|duck\.ai|chat\.qwen\.ai|kimi\.com|kimi\.ai|doubao\.com)$/i,E=/[?&]utm_source=(chatgpt(\.com)?|openai|perplexity(\.ai)?|claude(\.ai)?|gemini|copilot(\.com)?|meta\.?ai|deepseek|grok|mistral|le-?chat)(&|$)/i,D=Symbol.for(`agentstats.patched`),O=Symbol.for(`agentstats.wrapped`);var k=class{constructor(e){if(this.queue=[],this.timer=null,this.snapshotTimer=null,this.pollTimer=null,this.sessionId=``,this.lastActivity=0,this.lastSnapshotHash=``,this.inflight=Promise.resolve(),this.web=null,this.agentPage=``,this.controlStarted=0,!e||!e.key)throw Error("[agentstats] `key` is required");if(this.options={endpoint:w(),captureArgs:!0,captureResults:!1,captureErrors:!0,redactKeys:[],sessionTimeoutMs:18e5,flushIntervalMs:2e3,maxBatchSize:25,autoInstrument:!0,trackAgentBrowsers:!0,trackPageviews:!0,debug:!1,disabled:!1,...Object.fromEntries(Object.entries(e).filter(([,e])=>e!==void 0))},this._fetch=e.fetch??(typeof fetch<`u`?fetch.bind(globalThis):(()=>Promise.reject(/* @__PURE__ */ Error(`no fetch`)))),this.sessionId=this.loadSession(),!this.options.disabled&&(this.options.autoInstrument&&this.instrument(),this.bindLifecycle(),this.reportReferral(),this.options.trackAgentBrowsers&&this.watchAgentBrowsers(),this.options.trackPageviews)){let e=this.options;this.web=m({key:e.key,endpoint:`${e.endpoint.replace(/\/+$/,``)}/web`,hashRouting:e.hashRouting,outboundLinks:e.outboundLinks,fileDownloads:e.fileDownloads,allowLocalhost:e.allowLocalhost,agentSignals:e.agentSignals,debug:e.debug})}this.log(`initialised`,{endpoint:this.options.endpoint,session:this.sessionId})}wrap(e){if(!e||typeof e.execute!=`function`||e[O])return e;let t=e.execute,n=String(e.name),r=this,i=async function(e,i){let a=v(),o=i?.signal;try{let s=await t.call(this,e,i);return r.recordCall(n,`success`,v()-a,e,s,void 0,o),s}catch(t){let i=o?.aborted||y(t);throw r.recordCall(n,i?`cancelled`:`error`,v()-a,e,void 0,t,o),t}};Object.defineProperty(i,O,{value:!0});let a=Object.assign({},e,{execute:i});return Object.defineProperty(a,O,{value:!0}),a}track(e,t){let n=t?b(t,this.redactKeys()):void 0;this.enqueue({type:`custom`,id:g(),ts:_(),name:e,props:n,url:this.url()}),this.web?.track(e,n)}pageview(){this.web?.pageview()}async snapshot(){let e=this.modelContext();if(!e?.getTools)return[];let t=[];try{t=(await e.getTools()??[]).map(e=>C(e))}catch(e){return this.log(`getTools failed`,e),[]}let n=x(t.map(e=>[e.name,e.description,e.inputSchema,e.annotations]),1e7);return n!==this.lastSnapshotHash&&(this.lastSnapshotHash=n,this.enqueue({type:`tools_snapshot`,id:g(),ts:_(),tools:t,url:this.url()})),t}flush(e=!1){if(this.timer&&=(clearTimeout(this.timer),null),!this.queue.length)return this.inflight;let t=this.queue.splice(0,this.queue.length),n={key:this.options.key,sdk:`js/${h}`,session_id:this.sessionId,sent_at:_(),metadata:this.options.metadata,visit:typeof document<`u`?d(`_al_v`):void 0,client:this.clientHints(),events:t},r=JSON.stringify(n);if(this.log(`flush`,t.length,`events`),e&&typeof navigator<`u`&&navigator.sendBeacon)try{if(navigator.sendBeacon(this.options.endpoint,new Blob([r],{type:`text/plain`})))return Promise.resolve()}catch{}let i=this._fetch(this.options.endpoint,{method:`POST`,body:r,keepalive:!0,headers:{"Content-Type":`text/plain`}}).then(async e=>{e.ok||this.log(`ingest responded`,e.status)}).catch(e=>{this.log(`ingest failed`,e)});return this.inflight=i,i}destroy(){this.timer&&clearTimeout(this.timer),this.snapshotTimer&&clearTimeout(this.snapshotTimer),this.pollTimer&&clearInterval(this.pollTimer),this.timer=this.snapshotTimer=this.pollTimer=null,this.web?.stop(),this.web=null}get session(){return this.sessionId}log(...e){this.options.debug&&console.debug(`[agentstats]`,...e)}url(){return typeof location<`u`?location.href:void 0}redactKeys(){return(this.options.redactKeys??[]).map(e=>e.toLowerCase()).filter(Boolean)}modelContext(){let e=globalThis;return e.document?.modelContext??e.navigator?.modelContext}captureArgs(e,t){let n=this.options.captureArgs;if(n===!1)return;let r=typeof n==`function`?this.callOption(`captureArgs`,()=>n(e,t)):b(t,this.redactKeys());return r!==void 0&&S(r)>8192&&(r={_truncated:!0,preview:x(r,1e3)}),r}captureResult(e,t){let n=this.options.captureResults;if(!n||t===void 0)return;let r=typeof n==`function`?this.callOption(`captureResults`,()=>n(e,t)):t;return r===void 0?void 0:x(r,2048)}captureError(e,t){let n=this.options.captureErrors;if(n===!1)return;let r=t,i=typeof r?.message==`string`?r.message:x(t,1e3);if(typeof n!=`function`)return x(i,1e3);let a=typeof r?.code==`string`||typeof r?.code==`number`?r.code:null,o=this.callOption(`captureErrors`,()=>n({tool:e,message:i,name:typeof r?.name==`string`?r.name:null,code:a,error:t}));return typeof o==`string`&&o?x(o,1e3):void 0}callOption(e,t){try{return t()}catch(t){this.log(`${e} threw`,t);return}}recordCall(e,t,n,r,i,a,o){let s={type:`tool_call`,id:g(),ts:_(),tool:e,status:t,duration_ms:Math.round(n*100)/100,url:this.url()},c=this.captureArgs(e,r);c!==void 0&&(s.args=c);let l=this.captureResult(e,i);if(l!==void 0&&(s.result=l),a!==void 0){let t=this.captureError(e,a);t!==void 0&&(s.error=t);let n=a?.name;n&&(s.error_name=String(n).slice(0,100))}this.enqueue(s)}enqueue(e){this.options.disabled||(this.touchSession(),this.queue.push(e),this.log(`event`,e.type,e.tool??e.name??``),this.queue.length>=this.options.maxBatchSize?this.flush():this.timer||=setTimeout(()=>void this.flush(),this.options.flushIntervalMs))}scheduleSnapshot(e=250){this.snapshotTimer&&clearTimeout(this.snapshotTimer),this.snapshotTimer=setTimeout(()=>{this.snapshotTimer=null,this.snapshot()},e)}instrument(){let e=()=>{let e=this.modelContext();return e?(this.patch(e),!0):!1};if(e())return;let t=0;this.pollTimer=setInterval(()=>{t++,(e()||t>40)&&(this.pollTimer&&clearInterval(this.pollTimer),this.pollTimer=null)},250)}patch(e){if(e[D]){this.log(`modelContext already patched`),this.scheduleSnapshot(0);return}Object.defineProperty(e,D,{value:!0});let t=this;if(typeof e.registerTool==`function`){let n=e.registerTool;e.registerTool=function(e,r){let i=t.wrap(e);return t.enqueue({type:`tool_registered`,id:g(),ts:_(),tool:String(e?.name),descriptor:C(e),url:t.url()}),t.scheduleSnapshot(),n.call(this,i,r)}}if(typeof e.provideContext==`function`){let n=e.provideContext;e.provideContext=function(e){let r=(e?.tools??[]).map(e=>(t.enqueue({type:`tool_registered`,id:g(),ts:_(),tool:String(e?.name),descriptor:C(e),url:t.url()}),t.wrap(e)));return t.scheduleSnapshot(),n.call(this,{...e,tools:r})}}if(typeof e.unregisterTool==`function`){let n=e.unregisterTool;e.unregisterTool=function(e){return t.enqueue({type:`tool_unregistered`,id:g(),ts:_(),tool:String(e),url:t.url()}),t.scheduleSnapshot(),n.call(this,e)}}if(typeof e.clearContext==`function`){let n=e.clearContext;e.clearContext=function(){return t.scheduleSnapshot(),n.call(this)}}if(typeof e.addEventListener==`function`)try{e.addEventListener(`toolchange`,()=>t.scheduleSnapshot())}catch{}this.log(`modelContext patched`),this.scheduleSnapshot(0)}bindLifecycle(){if(typeof window>`u`||typeof window.addEventListener!=`function`)return;let e=()=>void this.flush(!0);window.addEventListener(`pagehide`,e),document.addEventListener(`visibilitychange`,()=>{document.visibilityState===`hidden`&&e()})}clientHints(){if(typeof navigator>`u`)return;let e=String(navigator.userAgent??``).slice(0,1e3),t=navigator.webdriver===!0;return e||t?{ua:e||void 0,webdriver:t||void 0}:void 0}detectAgentBrowser(){return f()}watchAgentBrowsers(){if(typeof document>`u`||typeof window>`u`)return;let e=()=>{let e=this.detectAgentBrowser(),t=this.url();e&&t!==this.agentPage&&(this.agentPage=t??``,this.enqueue({type:`agent_pageview`,id:g(),ts:_(),name:e.name,props:{via:e.via},url:t}))},t=()=>{e(),typeof MutationObserver<`u`&&document.body&&new MutationObserver(()=>{let t=!!document.querySelector(`#claude-agent-stop-container`);if(t&&!this.controlStarted)this.controlStarted=v(),this.enqueue({type:`agent_control`,id:g(),ts:_(),name:`claude-in-chrome`,props:{via:`dom`,phase:`start`},url:this.url()}),e();else if(!t&&this.controlStarted){let e=Math.round(v()-this.controlStarted);this.controlStarted=0,this.enqueue({type:`agent_control`,id:g(),ts:_(),name:`claude-in-chrome`,props:{via:`dom`,phase:`stop`,duration_ms:e},url:this.url()})}}).observe(document.body,{childList:!0})};document.readyState===`loading`?document.addEventListener(`DOMContentLoaded`,t,{once:!0}):t();let n=()=>setTimeout(e,0);window.addEventListener(`popstate`,n),window.addEventListener(c,n),p()}reportReferral(){if(typeof document>`u`||typeof location>`u`)return;let e=``;try{e=document.referrer?new URL(document.referrer).hostname.replace(/^www\./,``):``}catch{}if(!(e&&T.test(e))&&!E.test(location.search))return;let t=`__agentstats_ref_${this.sessionId}`;try{if(sessionStorage.getItem(t))return;sessionStorage.setItem(t,`1`)}catch{}this.enqueue({type:`referral`,id:g(),ts:_(),url:this.url()??location.href,referrer:e?`https://${e}/`:null})}loadSession(){try{let e=sessionStorage.getItem(`__agentstats_session`);if(e){let t=JSON.parse(e);if(t?.id&&_()-t.last<this.options.sessionTimeoutMs)return this.lastActivity=t.last,t.id}}catch{}return g()}touchSession(){let e=_();this.lastActivity&&e-this.lastActivity>this.options.sessionTimeoutMs&&(this.sessionId=g(),this.lastSnapshotHash=``,this.log(`new session`,this.sessionId)),this.lastActivity=e;try{sessionStorage.setItem(`__agentstats_session`,JSON.stringify({id:this.sessionId,last:e}))}catch{}}};let A=null;function j(e){return A&&A.destroy(),A=new k(e),A}function M(){return A}function N(e,t){A?.track(e,t)}function P(e){return A?A.wrap(e):e}function F(){return A?.flush()??Promise.resolve()}function I(){return A?.snapshot()??Promise.resolve([])}function L(){A?.pageview()}let R={init:j,track:N,pageview:L,wrap:P,flush:F,snapshot:I,getClient:M,version:h};window.AgentStats=R;let z=document.currentScript,B=z?.dataset.key,V=e=>e!==void 0&&e!==`false`,H=z?.dataset.fileDownloads;return B&&R.init({key:B,endpoint:z?.dataset.endpoint,debug:z?.dataset.debug===`true`,captureArgs:z?.dataset.captureArgs!==`false`,captureErrors:z?.dataset.captureErrors!==`false`,captureResults:z?.dataset.captureResults===`true`,redactKeys:z?.dataset.redactKeys?.split(`,`).map(e=>e.trim()).filter(Boolean),trackPageviews:z?.dataset.pageviews!==`false`,hashRouting:V(z?.dataset.hashRouting),outboundLinks:V(z?.dataset.outboundLinks),fileDownloads:H&&![``,`true`,`false`].includes(H)?H.split(`,`).map(e=>e.trim()):V(H),allowLocalhost:V(z?.dataset.allowLocalhost),agentSignals:z?.dataset.agentSignals!==`false`}),e.AgentStats=R,e})({});
|
package/dist/index.cjs
CHANGED
|
@@ -2,7 +2,150 @@ Object.defineProperties(exports, {
|
|
|
2
2
|
__esModule: { value: true },
|
|
3
3
|
[Symbol.toStringTag]: { value: "Module" }
|
|
4
4
|
});
|
|
5
|
-
|
|
5
|
+
const SIZE = 29;
|
|
6
|
+
const TIMES = [
|
|
7
|
+
10,
|
|
8
|
+
40,
|
|
9
|
+
100,
|
|
10
|
+
250
|
|
11
|
+
];
|
|
12
|
+
const MOVES = [
|
|
13
|
+
1,
|
|
14
|
+
2,
|
|
15
|
+
6,
|
|
16
|
+
21
|
|
17
|
+
];
|
|
18
|
+
const bucket = (x, bounds) => {
|
|
19
|
+
let i = 0;
|
|
20
|
+
while (i < bounds.length && x >= bounds[i]) i++;
|
|
21
|
+
return i;
|
|
22
|
+
};
|
|
23
|
+
const textEntry = (t) => !!t && (t.isContentEditable || t.tagName === "TEXTAREA" || t.tagName === "INPUT" && /^(text|search|email|url|tel|password|number|)$/.test(t.type));
|
|
24
|
+
const formField = (t) => !!t && (t.isContentEditable || /^(INPUT|TEXTAREA|SELECT)$/.test(t.tagName));
|
|
25
|
+
const autofilled = (t) => {
|
|
26
|
+
try {
|
|
27
|
+
return t.matches(":autofill");
|
|
28
|
+
} catch {
|
|
29
|
+
return false;
|
|
30
|
+
}
|
|
31
|
+
};
|
|
32
|
+
function watchSignals() {
|
|
33
|
+
const noop = {
|
|
34
|
+
take: () => null,
|
|
35
|
+
stop() {}
|
|
36
|
+
};
|
|
37
|
+
if (typeof document === "undefined" || typeof performance === "undefined") return noop;
|
|
38
|
+
const now = () => performance.now();
|
|
39
|
+
const away = () => document.visibilityState === "hidden" || !document.hasFocus();
|
|
40
|
+
let v = [];
|
|
41
|
+
let start = 0;
|
|
42
|
+
let moves = 0;
|
|
43
|
+
let lastKey = -1e9;
|
|
44
|
+
let editCause = -1e9;
|
|
45
|
+
let intent = -1e9;
|
|
46
|
+
let lastScroll = -1e9;
|
|
47
|
+
const holds = /* @__PURE__ */ new Map();
|
|
48
|
+
const reset = () => {
|
|
49
|
+
v = Array.from({ length: SIZE }, () => 0);
|
|
50
|
+
v[0] = 1;
|
|
51
|
+
start = now();
|
|
52
|
+
moves = 0;
|
|
53
|
+
};
|
|
54
|
+
reset();
|
|
55
|
+
const acted = (t) => {
|
|
56
|
+
if (!v[2]) v[2] = Math.max(1, Math.round(t - start));
|
|
57
|
+
};
|
|
58
|
+
const ctl = new AbortController();
|
|
59
|
+
const on = (type, f) => document.addEventListener(type, f, {
|
|
60
|
+
capture: true,
|
|
61
|
+
passive: true,
|
|
62
|
+
signal: ctl.signal
|
|
63
|
+
});
|
|
64
|
+
on("pointermove", (e) => {
|
|
65
|
+
if (!e.isTrusted) return;
|
|
66
|
+
v[3]++;
|
|
67
|
+
moves++;
|
|
68
|
+
});
|
|
69
|
+
on("pointerdown", (e) => {
|
|
70
|
+
if (!e.isTrusted) return;
|
|
71
|
+
intent = now();
|
|
72
|
+
acted(intent);
|
|
73
|
+
});
|
|
74
|
+
on("click", (e) => {
|
|
75
|
+
if (!e.isTrusted) return void v[26]++;
|
|
76
|
+
acted(now());
|
|
77
|
+
if (away()) v[27]++;
|
|
78
|
+
if (e.detail === 0) v[10]++;
|
|
79
|
+
else if (e.pointerType === "touch" || e.pointerType === "pen") v[9]++;
|
|
80
|
+
else if (e.detail === 1) v[4 + bucket(moves, MOVES)]++;
|
|
81
|
+
moves = 0;
|
|
82
|
+
});
|
|
83
|
+
on("keydown", (e) => {
|
|
84
|
+
if (!e.isTrusted) return void v[26]++;
|
|
85
|
+
const t = now();
|
|
86
|
+
acted(t);
|
|
87
|
+
intent = editCause = t;
|
|
88
|
+
if (away()) v[27]++;
|
|
89
|
+
if (e.repeat || e.target?.type === "password") return;
|
|
90
|
+
if (t - lastKey < 2e3) v[16 + bucket(t - lastKey, TIMES)]++;
|
|
91
|
+
lastKey = t;
|
|
92
|
+
holds.set(e.code || e.key, t);
|
|
93
|
+
});
|
|
94
|
+
on("keyup", (e) => {
|
|
95
|
+
const down = holds.get(e.code || e.key);
|
|
96
|
+
if (!e.isTrusted || down === void 0) return;
|
|
97
|
+
holds.delete(e.code || e.key);
|
|
98
|
+
v[11 + bucket(now() - down, TIMES)]++;
|
|
99
|
+
});
|
|
100
|
+
for (const type of [
|
|
101
|
+
"paste",
|
|
102
|
+
"drop",
|
|
103
|
+
"compositionend"
|
|
104
|
+
]) on(type, () => {
|
|
105
|
+
editCause = now();
|
|
106
|
+
});
|
|
107
|
+
for (const type of ["wheel", "touchstart"]) on(type, () => {
|
|
108
|
+
intent = now();
|
|
109
|
+
});
|
|
110
|
+
on("change", (e) => {
|
|
111
|
+
if (!e.isTrusted && formField(e.target)) v[28]++;
|
|
112
|
+
});
|
|
113
|
+
on("input", (e) => {
|
|
114
|
+
if (!e.isTrusted) return void (formField(e.target) && v[28]++);
|
|
115
|
+
if (!textEntry(e.target) || autofilled(e.target)) return;
|
|
116
|
+
const t = now();
|
|
117
|
+
acted(t);
|
|
118
|
+
if (away()) v[27]++;
|
|
119
|
+
const since = t - editCause;
|
|
120
|
+
v[since < 100 ? 21 : since < 1e3 ? 22 : 23]++;
|
|
121
|
+
});
|
|
122
|
+
on("scroll", () => {
|
|
123
|
+
const t = now();
|
|
124
|
+
if (t - lastScroll > 150) {
|
|
125
|
+
v[24]++;
|
|
126
|
+
if (t - intent > 500) v[25]++;
|
|
127
|
+
}
|
|
128
|
+
lastScroll = t;
|
|
129
|
+
});
|
|
130
|
+
return {
|
|
131
|
+
take() {
|
|
132
|
+
const out = v.slice(3).some(Boolean) ? v : null;
|
|
133
|
+
if (out) out[1] = Math.min(2 ** 31, Math.round(now() - start));
|
|
134
|
+
reset();
|
|
135
|
+
return out;
|
|
136
|
+
},
|
|
137
|
+
stop: () => ctl.abort()
|
|
138
|
+
};
|
|
139
|
+
}
|
|
140
|
+
// src/web.ts
|
|
141
|
+
/**
|
|
142
|
+
* Visitors: privacy-friendly web analytics for people. One small request per pageview or custom
|
|
143
|
+
* event, no cookies, nothing stored in the browser. The server counts unique visitors from a
|
|
144
|
+
* daily-salted hash of the IP and user agent, the way Plausible does, and keeps neither.
|
|
145
|
+
*
|
|
146
|
+
* Used by the full SDK (on by default, `trackPageviews: false` turns it off) and on its own by
|
|
147
|
+
* the lite script (`/sdk/lite.js`) for sites without WebMCP tools.
|
|
148
|
+
*/
|
|
6
149
|
const VISIT_COOKIE = "_al_v";
|
|
7
150
|
/** What Claude in Chrome puts on the page while it's in control (its stop button). */
|
|
8
151
|
const AGENT_CONTROL_MARKER = "#claude-agent-stop-container";
|
|
@@ -96,20 +239,15 @@ function webAnalytics(o) {
|
|
|
96
239
|
try {
|
|
97
240
|
ignored = localStorage.getItem("agentstats_ignore") === "true";
|
|
98
241
|
} catch {}
|
|
99
|
-
const
|
|
242
|
+
const post = (what, data) => {
|
|
100
243
|
if (ignored) return log("ignored: agentstats_ignore is set");
|
|
101
|
-
if (local && !o.allowLocalhost) return log("ignored on localhost:",
|
|
244
|
+
if (local && !o.allowLocalhost) return log("ignored on localhost:", what);
|
|
102
245
|
const body = JSON.stringify({
|
|
103
246
|
k: o.key,
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
r: document.referrer || null,
|
|
107
|
-
w: window.innerWidth,
|
|
108
|
-
p: props,
|
|
109
|
-
a: agentInBrowser()?.name,
|
|
110
|
-
h: o.hashRouting ? 1 : void 0
|
|
247
|
+
...data,
|
|
248
|
+
a: agentInBrowser()?.name
|
|
111
249
|
});
|
|
112
|
-
log("send",
|
|
250
|
+
log("send", what);
|
|
113
251
|
try {
|
|
114
252
|
if (navigator.sendBeacon?.(o.endpoint, body)) return;
|
|
115
253
|
} catch {}
|
|
@@ -120,6 +258,24 @@ function webAnalytics(o) {
|
|
|
120
258
|
headers: { "Content-Type": "text/plain" }
|
|
121
259
|
}).catch(() => {});
|
|
122
260
|
};
|
|
261
|
+
const send = (name, props) => post(name, {
|
|
262
|
+
n: name,
|
|
263
|
+
u: location.href,
|
|
264
|
+
r: document.referrer || null,
|
|
265
|
+
w: window.innerWidth,
|
|
266
|
+
p: props,
|
|
267
|
+
h: o.hashRouting ? 1 : void 0
|
|
268
|
+
});
|
|
269
|
+
const signals = o.agentSignals === false ? null : watchSignals();
|
|
270
|
+
let signalsUrl = location.href;
|
|
271
|
+
const sendSignals = () => {
|
|
272
|
+
const s = signals?.take();
|
|
273
|
+
if (s) post("signals", {
|
|
274
|
+
t: "s",
|
|
275
|
+
u: signalsUrl,
|
|
276
|
+
s
|
|
277
|
+
});
|
|
278
|
+
};
|
|
123
279
|
const ctl = new AbortController();
|
|
124
280
|
const on = { signal: ctl.signal };
|
|
125
281
|
let last = "";
|
|
@@ -127,7 +283,9 @@ function webAnalytics(o) {
|
|
|
127
283
|
if (ctl.signal.aborted) return;
|
|
128
284
|
const page = location.pathname + (o.hashRouting ? location.hash : "");
|
|
129
285
|
if (page === last) return;
|
|
286
|
+
if (last) sendSignals();
|
|
130
287
|
last = page;
|
|
288
|
+
signalsUrl = location.href;
|
|
131
289
|
send("pageview");
|
|
132
290
|
};
|
|
133
291
|
const start = () => {
|
|
@@ -169,14 +327,22 @@ function webAnalytics(o) {
|
|
|
169
327
|
signal: ctl.signal
|
|
170
328
|
});
|
|
171
329
|
}
|
|
330
|
+
if (signals) {
|
|
331
|
+
window.addEventListener("pagehide", sendSignals, on);
|
|
332
|
+
document.addEventListener("visibilitychange", () => document.visibilityState === "hidden" && sendSignals(), on);
|
|
333
|
+
}
|
|
172
334
|
return {
|
|
173
335
|
pageview,
|
|
174
336
|
track: (name, props) => send(String(name), props),
|
|
175
|
-
stop: () =>
|
|
337
|
+
stop: () => {
|
|
338
|
+
if (ctl.signal.aborted) return;
|
|
339
|
+
sendSignals();
|
|
340
|
+
signals?.stop();
|
|
341
|
+
ctl.abort();
|
|
342
|
+
}
|
|
176
343
|
};
|
|
177
344
|
}
|
|
178
|
-
|
|
179
|
-
//#region src/index.ts
|
|
345
|
+
// src/index.ts
|
|
180
346
|
/**
|
|
181
347
|
* AgentStats SDK — analytics for WebMCP tool calls, and for the people visiting the site.
|
|
182
348
|
*
|
|
@@ -188,7 +354,7 @@ function webAnalytics(o) {
|
|
|
188
354
|
* It also records pageviews (Visitors, see ./web.ts): no cookies, no personal data. Turn that
|
|
189
355
|
* off with `trackPageviews: false`.
|
|
190
356
|
*/
|
|
191
|
-
const SDK_VERSION = "0.
|
|
357
|
+
const SDK_VERSION = "0.5.1";
|
|
192
358
|
const MAX_ARG_BYTES = 8192;
|
|
193
359
|
const MAX_RESULT_CHARS = 2048;
|
|
194
360
|
function uuid() {
|
|
@@ -307,6 +473,7 @@ var AgentStatsClient = class {
|
|
|
307
473
|
outboundLinks: o.outboundLinks,
|
|
308
474
|
fileDownloads: o.fileDownloads,
|
|
309
475
|
allowLocalhost: o.allowLocalhost,
|
|
476
|
+
agentSignals: o.agentSignals,
|
|
310
477
|
debug: o.debug
|
|
311
478
|
});
|
|
312
479
|
}
|
|
@@ -786,7 +953,6 @@ const AgentStats = {
|
|
|
786
953
|
getClient,
|
|
787
954
|
version: SDK_VERSION
|
|
788
955
|
};
|
|
789
|
-
//#endregion
|
|
790
956
|
exports.AgentStats = AgentStats;
|
|
791
957
|
exports.default = AgentStats;
|
|
792
958
|
exports.AgentStatsClient = AgentStatsClient;
|
package/dist/index.d.cts
CHANGED
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
//#region src/web.d.ts
|
|
2
1
|
/**
|
|
3
2
|
* Visitors: privacy-friendly web analytics for people. One small request per pageview or custom
|
|
4
3
|
* event, no cookies, nothing stored in the browser. The server counts unique visitors from a
|
|
@@ -8,9 +7,7 @@
|
|
|
8
7
|
* the lite script (`/sdk/lite.js`) for sites without WebMCP tools.
|
|
9
8
|
*/
|
|
10
9
|
type EventProps = Record<string, string | number | boolean>;
|
|
11
|
-
|
|
12
|
-
//#region src/index.d.ts
|
|
13
|
-
export declare const SDK_VERSION = "0.4.1";
|
|
10
|
+
export declare const SDK_VERSION = "0.5.1";
|
|
14
11
|
export type ToolStatus = 'success' | 'error' | 'cancelled';
|
|
15
12
|
export interface ToolAnnotations {
|
|
16
13
|
readOnlyHint?: boolean;
|
|
@@ -103,6 +100,8 @@ export interface AgentStatsOptions {
|
|
|
103
100
|
fileDownloads?: boolean | string[];
|
|
104
101
|
/** Record pageviews on localhost too. Default `false`. */
|
|
105
102
|
allowLocalhost?: boolean;
|
|
103
|
+
/** With Visitors, send page interaction counts and timings (no content, positions or elements). Default `true`. */
|
|
104
|
+
agentSignals?: boolean;
|
|
106
105
|
/** Log to console. */
|
|
107
106
|
debug?: boolean;
|
|
108
107
|
/** Do nothing (useful in dev/test). */
|
|
@@ -265,5 +264,4 @@ export declare const AgentStats: {
|
|
|
265
264
|
getClient: typeof getClient;
|
|
266
265
|
version: string;
|
|
267
266
|
};
|
|
268
|
-
//#endregion
|
|
269
267
|
export { AgentStats as default, type EventProps };
|
package/dist/index.d.ts
CHANGED
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
//#region src/web.d.ts
|
|
2
1
|
/**
|
|
3
2
|
* Visitors: privacy-friendly web analytics for people. One small request per pageview or custom
|
|
4
3
|
* event, no cookies, nothing stored in the browser. The server counts unique visitors from a
|
|
@@ -8,9 +7,7 @@
|
|
|
8
7
|
* the lite script (`/sdk/lite.js`) for sites without WebMCP tools.
|
|
9
8
|
*/
|
|
10
9
|
type EventProps = Record<string, string | number | boolean>;
|
|
11
|
-
|
|
12
|
-
//#region src/index.d.ts
|
|
13
|
-
export declare const SDK_VERSION = "0.4.1";
|
|
10
|
+
export declare const SDK_VERSION = "0.5.1";
|
|
14
11
|
export type ToolStatus = 'success' | 'error' | 'cancelled';
|
|
15
12
|
export interface ToolAnnotations {
|
|
16
13
|
readOnlyHint?: boolean;
|
|
@@ -103,6 +100,8 @@ export interface AgentStatsOptions {
|
|
|
103
100
|
fileDownloads?: boolean | string[];
|
|
104
101
|
/** Record pageviews on localhost too. Default `false`. */
|
|
105
102
|
allowLocalhost?: boolean;
|
|
103
|
+
/** With Visitors, send page interaction counts and timings (no content, positions or elements). Default `true`. */
|
|
104
|
+
agentSignals?: boolean;
|
|
106
105
|
/** Log to console. */
|
|
107
106
|
debug?: boolean;
|
|
108
107
|
/** Do nothing (useful in dev/test). */
|
|
@@ -265,5 +264,4 @@ export declare const AgentStats: {
|
|
|
265
264
|
getClient: typeof getClient;
|
|
266
265
|
version: string;
|
|
267
266
|
};
|
|
268
|
-
//#endregion
|
|
269
267
|
export { AgentStats as default, type EventProps };
|
package/dist/index.js
CHANGED
|
@@ -1,4 +1,147 @@
|
|
|
1
|
-
|
|
1
|
+
const SIZE = 29;
|
|
2
|
+
const TIMES = [
|
|
3
|
+
10,
|
|
4
|
+
40,
|
|
5
|
+
100,
|
|
6
|
+
250
|
|
7
|
+
];
|
|
8
|
+
const MOVES = [
|
|
9
|
+
1,
|
|
10
|
+
2,
|
|
11
|
+
6,
|
|
12
|
+
21
|
|
13
|
+
];
|
|
14
|
+
const bucket = (x, bounds) => {
|
|
15
|
+
let i = 0;
|
|
16
|
+
while (i < bounds.length && x >= bounds[i]) i++;
|
|
17
|
+
return i;
|
|
18
|
+
};
|
|
19
|
+
const textEntry = (t) => !!t && (t.isContentEditable || t.tagName === "TEXTAREA" || t.tagName === "INPUT" && /^(text|search|email|url|tel|password|number|)$/.test(t.type));
|
|
20
|
+
const formField = (t) => !!t && (t.isContentEditable || /^(INPUT|TEXTAREA|SELECT)$/.test(t.tagName));
|
|
21
|
+
const autofilled = (t) => {
|
|
22
|
+
try {
|
|
23
|
+
return t.matches(":autofill");
|
|
24
|
+
} catch {
|
|
25
|
+
return false;
|
|
26
|
+
}
|
|
27
|
+
};
|
|
28
|
+
function watchSignals() {
|
|
29
|
+
const noop = {
|
|
30
|
+
take: () => null,
|
|
31
|
+
stop() {}
|
|
32
|
+
};
|
|
33
|
+
if (typeof document === "undefined" || typeof performance === "undefined") return noop;
|
|
34
|
+
const now = () => performance.now();
|
|
35
|
+
const away = () => document.visibilityState === "hidden" || !document.hasFocus();
|
|
36
|
+
let v = [];
|
|
37
|
+
let start = 0;
|
|
38
|
+
let moves = 0;
|
|
39
|
+
let lastKey = -1e9;
|
|
40
|
+
let editCause = -1e9;
|
|
41
|
+
let intent = -1e9;
|
|
42
|
+
let lastScroll = -1e9;
|
|
43
|
+
const holds = /* @__PURE__ */ new Map();
|
|
44
|
+
const reset = () => {
|
|
45
|
+
v = Array.from({ length: SIZE }, () => 0);
|
|
46
|
+
v[0] = 1;
|
|
47
|
+
start = now();
|
|
48
|
+
moves = 0;
|
|
49
|
+
};
|
|
50
|
+
reset();
|
|
51
|
+
const acted = (t) => {
|
|
52
|
+
if (!v[2]) v[2] = Math.max(1, Math.round(t - start));
|
|
53
|
+
};
|
|
54
|
+
const ctl = new AbortController();
|
|
55
|
+
const on = (type, f) => document.addEventListener(type, f, {
|
|
56
|
+
capture: true,
|
|
57
|
+
passive: true,
|
|
58
|
+
signal: ctl.signal
|
|
59
|
+
});
|
|
60
|
+
on("pointermove", (e) => {
|
|
61
|
+
if (!e.isTrusted) return;
|
|
62
|
+
v[3]++;
|
|
63
|
+
moves++;
|
|
64
|
+
});
|
|
65
|
+
on("pointerdown", (e) => {
|
|
66
|
+
if (!e.isTrusted) return;
|
|
67
|
+
intent = now();
|
|
68
|
+
acted(intent);
|
|
69
|
+
});
|
|
70
|
+
on("click", (e) => {
|
|
71
|
+
if (!e.isTrusted) return void v[26]++;
|
|
72
|
+
acted(now());
|
|
73
|
+
if (away()) v[27]++;
|
|
74
|
+
if (e.detail === 0) v[10]++;
|
|
75
|
+
else if (e.pointerType === "touch" || e.pointerType === "pen") v[9]++;
|
|
76
|
+
else if (e.detail === 1) v[4 + bucket(moves, MOVES)]++;
|
|
77
|
+
moves = 0;
|
|
78
|
+
});
|
|
79
|
+
on("keydown", (e) => {
|
|
80
|
+
if (!e.isTrusted) return void v[26]++;
|
|
81
|
+
const t = now();
|
|
82
|
+
acted(t);
|
|
83
|
+
intent = editCause = t;
|
|
84
|
+
if (away()) v[27]++;
|
|
85
|
+
if (e.repeat || e.target?.type === "password") return;
|
|
86
|
+
if (t - lastKey < 2e3) v[16 + bucket(t - lastKey, TIMES)]++;
|
|
87
|
+
lastKey = t;
|
|
88
|
+
holds.set(e.code || e.key, t);
|
|
89
|
+
});
|
|
90
|
+
on("keyup", (e) => {
|
|
91
|
+
const down = holds.get(e.code || e.key);
|
|
92
|
+
if (!e.isTrusted || down === void 0) return;
|
|
93
|
+
holds.delete(e.code || e.key);
|
|
94
|
+
v[11 + bucket(now() - down, TIMES)]++;
|
|
95
|
+
});
|
|
96
|
+
for (const type of [
|
|
97
|
+
"paste",
|
|
98
|
+
"drop",
|
|
99
|
+
"compositionend"
|
|
100
|
+
]) on(type, () => {
|
|
101
|
+
editCause = now();
|
|
102
|
+
});
|
|
103
|
+
for (const type of ["wheel", "touchstart"]) on(type, () => {
|
|
104
|
+
intent = now();
|
|
105
|
+
});
|
|
106
|
+
on("change", (e) => {
|
|
107
|
+
if (!e.isTrusted && formField(e.target)) v[28]++;
|
|
108
|
+
});
|
|
109
|
+
on("input", (e) => {
|
|
110
|
+
if (!e.isTrusted) return void (formField(e.target) && v[28]++);
|
|
111
|
+
if (!textEntry(e.target) || autofilled(e.target)) return;
|
|
112
|
+
const t = now();
|
|
113
|
+
acted(t);
|
|
114
|
+
if (away()) v[27]++;
|
|
115
|
+
const since = t - editCause;
|
|
116
|
+
v[since < 100 ? 21 : since < 1e3 ? 22 : 23]++;
|
|
117
|
+
});
|
|
118
|
+
on("scroll", () => {
|
|
119
|
+
const t = now();
|
|
120
|
+
if (t - lastScroll > 150) {
|
|
121
|
+
v[24]++;
|
|
122
|
+
if (t - intent > 500) v[25]++;
|
|
123
|
+
}
|
|
124
|
+
lastScroll = t;
|
|
125
|
+
});
|
|
126
|
+
return {
|
|
127
|
+
take() {
|
|
128
|
+
const out = v.slice(3).some(Boolean) ? v : null;
|
|
129
|
+
if (out) out[1] = Math.min(2 ** 31, Math.round(now() - start));
|
|
130
|
+
reset();
|
|
131
|
+
return out;
|
|
132
|
+
},
|
|
133
|
+
stop: () => ctl.abort()
|
|
134
|
+
};
|
|
135
|
+
}
|
|
136
|
+
// src/web.ts
|
|
137
|
+
/**
|
|
138
|
+
* Visitors: privacy-friendly web analytics for people. One small request per pageview or custom
|
|
139
|
+
* event, no cookies, nothing stored in the browser. The server counts unique visitors from a
|
|
140
|
+
* daily-salted hash of the IP and user agent, the way Plausible does, and keeps neither.
|
|
141
|
+
*
|
|
142
|
+
* Used by the full SDK (on by default, `trackPageviews: false` turns it off) and on its own by
|
|
143
|
+
* the lite script (`/sdk/lite.js`) for sites without WebMCP tools.
|
|
144
|
+
*/
|
|
2
145
|
const VISIT_COOKIE = "_al_v";
|
|
3
146
|
/** What Claude in Chrome puts on the page while it's in control (its stop button). */
|
|
4
147
|
const AGENT_CONTROL_MARKER = "#claude-agent-stop-container";
|
|
@@ -92,20 +235,15 @@ function webAnalytics(o) {
|
|
|
92
235
|
try {
|
|
93
236
|
ignored = localStorage.getItem("agentstats_ignore") === "true";
|
|
94
237
|
} catch {}
|
|
95
|
-
const
|
|
238
|
+
const post = (what, data) => {
|
|
96
239
|
if (ignored) return log("ignored: agentstats_ignore is set");
|
|
97
|
-
if (local && !o.allowLocalhost) return log("ignored on localhost:",
|
|
240
|
+
if (local && !o.allowLocalhost) return log("ignored on localhost:", what);
|
|
98
241
|
const body = JSON.stringify({
|
|
99
242
|
k: o.key,
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
r: document.referrer || null,
|
|
103
|
-
w: window.innerWidth,
|
|
104
|
-
p: props,
|
|
105
|
-
a: agentInBrowser()?.name,
|
|
106
|
-
h: o.hashRouting ? 1 : void 0
|
|
243
|
+
...data,
|
|
244
|
+
a: agentInBrowser()?.name
|
|
107
245
|
});
|
|
108
|
-
log("send",
|
|
246
|
+
log("send", what);
|
|
109
247
|
try {
|
|
110
248
|
if (navigator.sendBeacon?.(o.endpoint, body)) return;
|
|
111
249
|
} catch {}
|
|
@@ -116,6 +254,24 @@ function webAnalytics(o) {
|
|
|
116
254
|
headers: { "Content-Type": "text/plain" }
|
|
117
255
|
}).catch(() => {});
|
|
118
256
|
};
|
|
257
|
+
const send = (name, props) => post(name, {
|
|
258
|
+
n: name,
|
|
259
|
+
u: location.href,
|
|
260
|
+
r: document.referrer || null,
|
|
261
|
+
w: window.innerWidth,
|
|
262
|
+
p: props,
|
|
263
|
+
h: o.hashRouting ? 1 : void 0
|
|
264
|
+
});
|
|
265
|
+
const signals = o.agentSignals === false ? null : watchSignals();
|
|
266
|
+
let signalsUrl = location.href;
|
|
267
|
+
const sendSignals = () => {
|
|
268
|
+
const s = signals?.take();
|
|
269
|
+
if (s) post("signals", {
|
|
270
|
+
t: "s",
|
|
271
|
+
u: signalsUrl,
|
|
272
|
+
s
|
|
273
|
+
});
|
|
274
|
+
};
|
|
119
275
|
const ctl = new AbortController();
|
|
120
276
|
const on = { signal: ctl.signal };
|
|
121
277
|
let last = "";
|
|
@@ -123,7 +279,9 @@ function webAnalytics(o) {
|
|
|
123
279
|
if (ctl.signal.aborted) return;
|
|
124
280
|
const page = location.pathname + (o.hashRouting ? location.hash : "");
|
|
125
281
|
if (page === last) return;
|
|
282
|
+
if (last) sendSignals();
|
|
126
283
|
last = page;
|
|
284
|
+
signalsUrl = location.href;
|
|
127
285
|
send("pageview");
|
|
128
286
|
};
|
|
129
287
|
const start = () => {
|
|
@@ -165,14 +323,22 @@ function webAnalytics(o) {
|
|
|
165
323
|
signal: ctl.signal
|
|
166
324
|
});
|
|
167
325
|
}
|
|
326
|
+
if (signals) {
|
|
327
|
+
window.addEventListener("pagehide", sendSignals, on);
|
|
328
|
+
document.addEventListener("visibilitychange", () => document.visibilityState === "hidden" && sendSignals(), on);
|
|
329
|
+
}
|
|
168
330
|
return {
|
|
169
331
|
pageview,
|
|
170
332
|
track: (name, props) => send(String(name), props),
|
|
171
|
-
stop: () =>
|
|
333
|
+
stop: () => {
|
|
334
|
+
if (ctl.signal.aborted) return;
|
|
335
|
+
sendSignals();
|
|
336
|
+
signals?.stop();
|
|
337
|
+
ctl.abort();
|
|
338
|
+
}
|
|
172
339
|
};
|
|
173
340
|
}
|
|
174
|
-
|
|
175
|
-
//#region src/index.ts
|
|
341
|
+
// src/index.ts
|
|
176
342
|
/**
|
|
177
343
|
* AgentStats SDK — analytics for WebMCP tool calls, and for the people visiting the site.
|
|
178
344
|
*
|
|
@@ -184,7 +350,7 @@ function webAnalytics(o) {
|
|
|
184
350
|
* It also records pageviews (Visitors, see ./web.ts): no cookies, no personal data. Turn that
|
|
185
351
|
* off with `trackPageviews: false`.
|
|
186
352
|
*/
|
|
187
|
-
const SDK_VERSION = "0.
|
|
353
|
+
const SDK_VERSION = "0.5.1";
|
|
188
354
|
const MAX_ARG_BYTES = 8192;
|
|
189
355
|
const MAX_RESULT_CHARS = 2048;
|
|
190
356
|
function uuid() {
|
|
@@ -303,6 +469,7 @@ var AgentStatsClient = class {
|
|
|
303
469
|
outboundLinks: o.outboundLinks,
|
|
304
470
|
fileDownloads: o.fileDownloads,
|
|
305
471
|
allowLocalhost: o.allowLocalhost,
|
|
472
|
+
agentSignals: o.agentSignals,
|
|
306
473
|
debug: o.debug
|
|
307
474
|
});
|
|
308
475
|
}
|
|
@@ -782,5 +949,4 @@ const AgentStats = {
|
|
|
782
949
|
getClient,
|
|
783
950
|
version: SDK_VERSION
|
|
784
951
|
};
|
|
785
|
-
//#endregion
|
|
786
952
|
export { AgentStats, AgentStats as default, AgentStatsClient, SDK_VERSION, flush, getClient, init, pageview, snapshot, track, wrap };
|