@sightspool/sdk 0.3.0 → 0.4.0
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/CHANGELOG.md +15 -0
- package/README.md +111 -333
- package/SECURITY.md +16 -0
- package/dist/index.cjs +159 -1226
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +20 -41
- package/dist/index.d.ts +20 -41
- package/dist/index.js +160 -761
- package/dist/index.js.map +1 -1
- package/dist/release.json +21 -0
- package/dist/sdk.global.js +2 -59
- package/dist/sdk.global.js.map +1 -1
- package/dist/source.json +11 -0
- package/package.json +14 -12
- package/site/CNAME +1 -0
- package/site/demo.html +6 -0
- package/site/demo.js +27 -0
- package/site/index.html +74 -0
- package/site/release.js +20 -0
- package/site/releases/0.4.0/2acf3463db7571c459ca01a4516341891bb4c2ec6265962f494ca8b553cc0e9f/release.json +21 -0
- package/site/releases/0.4.0/2acf3463db7571c459ca01a4516341891bb4c2ec6265962f494ca8b553cc0e9f/sdk.global.js +3 -0
- package/site/releases/0.4.0/2acf3463db7571c459ca01a4516341891bb4c2ec6265962f494ca8b553cc0e9f/sdk.global.js.map +1 -0
- package/site/releases/0.4.0/2acf3463db7571c459ca01a4516341891bb4c2ec6265962f494ca8b553cc0e9f/source.json +11 -0
- package/site/releases/0.4.0/c21bee307a5c53e3ebb49d21f0f1ef2cce06a4483fa9824122bd6897ad6ca3ac/release.json +21 -0
- package/site/releases/0.4.0/c21bee307a5c53e3ebb49d21f0f1ef2cce06a4483fa9824122bd6897ad6ca3ac/sdk.global.js +3 -0
- package/site/releases/0.4.0/c21bee307a5c53e3ebb49d21f0f1ef2cce06a4483fa9824122bd6897ad6ca3ac/sdk.global.js.map +1 -0
- package/site/releases/0.4.0/c21bee307a5c53e3ebb49d21f0f1ef2cce06a4483fa9824122bd6897ad6ca3ac/source.json +11 -0
- package/site/styles.css +69 -0
- package/site/trust.html +36 -0
- package/dist/chunk-4PADVIIO.js +0 -41
- package/dist/chunk-4PADVIIO.js.map +0 -1
- package/dist/probe-BNGMQQ5C.js +0 -113
- package/dist/probe-BNGMQQ5C.js.map +0 -1
- package/dist/prompt-GDFYC75D.js +0 -139
- package/dist/prompt-GDFYC75D.js.map +0 -1
- package/dist/survey-CICJQ5VI.js +0 -145
- package/dist/survey-CICJQ5VI.js.map +0 -1
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/capture.ts","../src/harvest.ts","../src/egress.ts","../src/triggers.ts","../src/intervention.ts","../src/env.ts","../src/index.ts"],"names":["_a","RAGE_WINDOW_MS"],"mappings":";;;AAOA,IAAM,SAAA,GAAY,EAAA;AAClB,IAAM,aAAA,GAAgB,GAAA;AACtB,IAAM,cAAA,GAAiB,GAAA;AACvB,IAAM,UAAA,GAAa,CAAA;AAenB,SAAS,MAAA,GAAkB;AACzB,EAAA,OAAO,OAAO,MAAA,KAAW,WAAA,IAAe,OAAO,QAAA,KAAa,WAAA;AAC9D;AAEO,SAAS,cAAc,IAAA,EAIZ;AAjClB,EAAA,IAAAA,GAAAA,EAAA,EAAA;AAkCE,EAAA,MAAM,mBAAkBA,GAAAA,GAAA,IAAA,CAAK,MAAA,KAAL,IAAA,GAAAA,MAAe,EAAC;AACxC,EAAA,MAAM,cAAA,GAAA,CAAiB,EAAA,GAAA,IAAA,CAAK,KAAA,KAAL,IAAA,GAAA,EAAA,GAAc,EAAC;AACtC,EAAA,IAAI,MAAoB,EAAC;AACzB,EAAA,IAAI,SAAA;AACJ,EAAA,IAAI,OAAA,GAAU,KAAA;AACd,EAAA,MAAM,OAA0B,EAAC;AACjC,EAAA,MAAM,WAA8B,EAAC;AACrC,EAAA,IAAI,eAAyB,EAAC;AAE9B,EAAA,SAAS,MAAA,GAAS;AAChB,IAAA,KAAA,MAAW,MAAM,IAAA,EAAM;AACrB,MAAA,IAAI;AACF,QAAA,EAAA,EAAG;AAAA,MACL,CAAA,CAAA,OAAQ,CAAA,EAAA;AAAA,MAER;AAAA,IACF;AAAA,EACF;AAEA,EAAA,SAAS,IAAA,CAAK,MAAsB,KAAA,EAAgB;AAClD,IAAA,IAAI;AACF,MAAA,GAAA,CAAI,IAAA,CAAK,EAAE,CAAA,EAAG,IAAA,CAAK,GAAA,EAAI,EAAG,IAAA,EAAM,KAAA,EAAO,KAAA,GAAQ,UAAA,CAAW,KAAK,CAAA,GAAI,QAAW,CAAA;AAC9E,MAAA,IAAI,IAAI,MAAA,GAAS,SAAA,QAAiB,GAAA,CAAI,KAAA,CAAM,CAAC,SAAS,CAAA;AACtD,MAAA,IAAI,KAAK,KAAA,EAAO,OAAA,CAAQ,KAAA,CAAM,oBAAA,EAAsB,MAAM,KAAK,CAAA;AAC/D,MAAA,MAAA,EAAO;AAAA,IACT,CAAA,CAAA,OAAQ,CAAA,EAAA;AAAA,IAER;AAAA,EACF;AAEA,EAAA,SAAS,YAAA,GAAuB;AAC9B,IAAA,IAAI;AACF,MAAA,OAAO,QAAA,CAAS,WAAW,QAAA,CAAS,MAAA;AAAA,IACtC,CAAA,CAAA,OAAQ,CAAA,EAAA;AACN,MAAA,OAAO,EAAA;AAAA,IACT;AAAA,EACF;AAEA,EAAA,SAAS,YAAA,GAAuB;AAC9B,IAAA,IAAI;AACF,MAAA,OAAO,SAAS,KAAA,IAAS,EAAA;AAAA,IAC3B,CAAA,CAAA,OAAQ,CAAA,EAAA;AACN,MAAA,OAAO,EAAA;AAAA,IACT;AAAA,EACF;AAEA,EAAA,SAAS,QAAQ,EAAA,EAAgB;AAhFnC,IAAA,IAAAA,GAAAA;AAiFI,IAAA,IAAI;AACF,MAAA,MAAM,SAAS,EAAA,CAAG,MAAA;AAGlB,MAAA,IAAI,gBAAA,CAAiB,MAAA,EAAQ,cAAc,CAAA,EAAG;AAC9C,MAAA,MAAM,IAAA,GACH,MAAA,KAAA,CAAA,CAAWA,GAAAA,GAAA,MAAA,CAAO,YAAA,KAAP,gBAAAA,GAAAA,CAAA,IAAA,CAAA,MAAA,EAAsB,YAAA,CAAA,KAAiB,MAAA,CAAO,WAAA,CAAA,IAAiB,EAAA;AAG7E,MAAA,MAAM,KAAA,GAAQ,qBAAA,CAAsB,MAAA,EAAQ,eAAe,CAAA,GACvD,QAAA,GACA,IAAA,CAAK,IAAA,EAAK,CAAE,KAAA,CAAM,CAAA,EAAG,EAAE,CAAA;AAC3B,MAAA,MAAM,CAAA,GAAI,KAAK,GAAA,EAAI;AAEnB,MAAA,YAAA,GAAe,aAAa,MAAA,CAAO,CAAC,EAAA,KAAO,CAAA,GAAI,MAAM,cAAc,CAAA;AACnE,MAAA,YAAA,CAAa,KAAK,CAAC,CAAA;AACnB,MAAA,MAAM,MAAA,GAAS,aAAa,MAAA,IAAU,UAAA;AACtC,MAAA,IAAA,CAAK,MAAA,GAAS,YAAA,GAAe,OAAA,EAAS,KAAK,CAAA;AAI3C,MAAA,MAAM,cAAc,YAAA,EAAa;AACjC,MAAA,IAAI,OAAA,GAAU,KAAA;AACd,MAAA,IAAI,QAAA,GAAoC,IAAA;AACxC,MAAA,IAAI;AACF,QAAA,QAAA,GAAW,IAAI,iBAAiB,MAAM;AACpC,UAAA,OAAA,GAAU,IAAA;AAAA,QACZ,CAAC,CAAA;AACD,QAAA,QAAA,CAAS,OAAA,CAAQ,QAAA,CAAS,IAAA,EAAM,EAAE,SAAA,EAAW,MAAM,OAAA,EAAS,IAAA,EAAM,UAAA,EAAY,IAAA,EAAM,CAAA;AAAA,MACtF,CAAA,CAAA,OAAQ,CAAA,EAAA;AAAA,MAER;AACA,MAAA,MAAA,CAAO,WAAW,MAAM;AACtB,QAAA,IAAI;AACF,UAAA,QAAA,IAAA,IAAA,GAAA,KAAA,CAAA,GAAA,QAAA,CAAU,UAAA,EAAA;AACV,UAAA,IAAI,CAAC,OAAA,IAAW,YAAA,EAAa,KAAM,eAAe,KAAA,EAAO;AACvD,YAAA,IAAA,CAAK,cAAc,KAAK,CAAA;AAAA,UAC1B;AAAA,QACF,CAAA,CAAA,OAAQ,CAAA,EAAA;AAAA,QAER;AAAA,MACF,GAAG,aAAa,CAAA;AAAA,IAClB,CAAA,CAAA,OAAQ,CAAA,EAAA;AAAA,IAER;AAAA,EACF;AAEA,EAAA,SAAS,QAAQ,EAAA,EAAgB;AAC/B,IAAA,IAAI;AACF,MAAA,SAAA,GAAY,MAAA,CAAO,EAAA,CAAG,OAAA,IAAW,OAAO,CAAA;AACxC,MAAA,IAAA,CAAK,SAAS,SAAS,CAAA;AAAA,IACzB,CAAA,CAAA,OAAQ,CAAA,EAAA;AAAA,IAER;AAAA,EACF;AAEA,EAAA,SAAS,YAAY,EAAA,EAA2B;AAC9C,IAAA,IAAI;AACF,MAAA,MAAM,SAAS,EAAA,CAAG,MAAA;AAClB,MAAA,SAAA,GAAY,MAAA,YAAkB,KAAA,GAAQ,MAAA,CAAO,OAAA,GAAU,OAAO,MAAM,CAAA;AACpE,MAAA,IAAA,CAAK,SAAS,SAAS,CAAA;AAAA,IACzB,CAAA,CAAA,OAAQ,CAAA,EAAA;AAAA,IAER;AAAA,EACF;AAGA,EAAA,SAAS,oBAAA,GAAuB;AAC9B,IAAA,IAAI;AACF,MAAA,MAAM,IAAA,GAAO,MAAM,IAAA,CAAK,OAAA,EAAS,cAAc,CAAA;AAC/C,MAAA,MAAM,WAAW,OAAA,CAAQ,SAAA;AACzB,MAAA,MAAM,cAAc,OAAA,CAAQ,YAAA;AAC5B,MAAA,OAAA,CAAQ,SAAA,GAAY,YAA4B,IAAA,EAAwC;AACtF,QAAA,MAAM,CAAA,GAAI,QAAA,CAAS,KAAA,CAAM,IAAA,EAAM,IAAI,CAAA;AACnC,QAAA,IAAA,EAAK;AACL,QAAA,OAAO,CAAA;AAAA,MACT,CAAA;AACA,MAAA,OAAA,CAAQ,YAAA,GAAe,YAElB,IAAA,EACH;AACA,QAAA,MAAM,CAAA,GAAI,WAAA,CAAY,KAAA,CAAM,IAAA,EAAM,IAAI,CAAA;AACtC,QAAA,IAAA,EAAK;AACL,QAAA,OAAO,CAAA;AAAA,MACT,CAAA;AACA,MAAA,MAAA,CAAO,gBAAA,CAAiB,YAAY,IAAI,CAAA;AACxC,MAAA,QAAA,CAAS,KAAK,MAAM;AAClB,QAAA,OAAA,CAAQ,SAAA,GAAY,QAAA;AACpB,QAAA,OAAA,CAAQ,YAAA,GAAe,WAAA;AACvB,QAAA,MAAA,CAAO,mBAAA,CAAoB,YAAY,IAAI,CAAA;AAAA,MAC7C,CAAC,CAAA;AACD,MAAA,IAAA,CAAK,OAAA,EAAS,cAAc,CAAA;AAAA,IAC9B,CAAA,CAAA,OAAQ,CAAA,EAAA;AAAA,IAER;AAAA,EACF;AAGA,EAAA,SAAS,oBAAA,GAAuB;AAC9B,IAAA,IAAI;AACF,MAAA,IAAI,OAAO,MAAA,CAAO,KAAA,KAAU,UAAA,EAAY;AACxC,MAAA,MAAM,IAAA,GAAO,MAAA,CAAO,KAAA,CAAM,IAAA,CAAK,MAAM,CAAA;AACrC,MAAA,MAAA,CAAO,KAAA,GAAQ,UAAU,IAAA,KAAmC;AAC1D,QAAA,IAAI;AACF,UAAA,MAAM,GAAA,GAAM,MAAM,IAAA,CAAK,GAAG,IAAI,CAAA;AAC9B,UAAA,IAAI,CAAC,IAAI,EAAA,EAAI,IAAA,CAAK,iBAAiB,CAAA,KAAA,EAAQ,GAAA,CAAI,MAAM,CAAA,CAAE,CAAA;AACvD,UAAA,OAAO,GAAA;AAAA,QACT,SAAS,GAAA,EAAK;AACZ,UAAA,IAAA,CAAK,eAAA,EAAiB,GAAA,YAAe,KAAA,GAAQ,GAAA,CAAI,UAAU,eAAe,CAAA;AAC1E,UAAA,MAAM,GAAA;AAAA,QACR;AAAA,MACF,CAAA;AACA,MAAA,QAAA,CAAS,KAAK,MAAM;AAClB,QAAA,MAAA,CAAO,KAAA,GAAQ,IAAA;AAAA,MACjB,CAAC,CAAA;AAAA,IACH,CAAA,CAAA,OAAQ,CAAA,EAAA;AAAA,IAER;AAAA,EACF;AAEA,EAAA,OAAO;AAAA,IACL,KAAA,GAAQ;AACN,MAAA,IAAI,OAAA,IAAW,CAAC,MAAA,EAAO,EAAG;AAC1B,MAAA,OAAA,GAAU,IAAA;AACV,MAAA,IAAI;AACF,QAAA,QAAA,CAAS,gBAAA,CAAiB,OAAA,EAAS,OAAA,EAAS,IAAI,CAAA;AAChD,QAAA,MAAA,CAAO,gBAAA,CAAiB,SAAS,OAAO,CAAA;AACxC,QAAA,MAAA,CAAO,gBAAA,CAAiB,sBAAsB,WAAW,CAAA;AACzD,QAAA,QAAA,CAAS,KAAK,MAAM;AAClB,UAAA,QAAA,CAAS,mBAAA,CAAoB,OAAA,EAAS,OAAA,EAAS,IAAI,CAAA;AACnD,UAAA,MAAA,CAAO,mBAAA,CAAoB,SAAS,OAAO,CAAA;AAC3C,UAAA,MAAA,CAAO,mBAAA,CAAoB,sBAAsB,WAAW,CAAA;AAAA,QAC9D,CAAC,CAAA;AACD,QAAA,oBAAA,EAAqB;AACrB,QAAA,oBAAA,EAAqB;AAAA,MACvB,CAAA,CAAA,OAAQ,CAAA,EAAA;AAAA,MAER;AAAA,IACF,CAAA;AAAA,IACA,IAAA,GAAO;AACL,MAAA,OAAA,GAAU,KAAA;AACV,MAAA,KAAA,MAAW,CAAA,IAAK,QAAA,CAAS,MAAA,CAAO,CAAC,CAAA,EAAG;AAClC,QAAA,IAAI;AACF,UAAA,CAAA,EAAE;AAAA,QACJ,CAAA,CAAA,OAAQ,CAAA,EAAA;AAAA,QAER;AAAA,MACF;AAAA,IACF,CAAA;AAAA,IACA,KAAA,GAAQ;AACN,MAAA,OAAO,IAAI,KAAA,EAAM;AAAA,IACnB,CAAA;AAAA,IACA,KAAA,EAAO,YAAA;AAAA,IACP,KAAA,EAAO,YAAA;AAAA,IACP,KAAA,GAAQ;AACN,MAAA,OAAO,SAAA;AAAA,IACT,CAAA;AAAA,IACA,QAAQ,EAAA,EAAI;AACV,MAAA,IAAA,CAAK,KAAK,EAAE,CAAA;AAAA,IACd,CAAA;AAAA,IACA,YAAA,CAAa,OAAO,UAAA,EAAY;AAC9B,MAAA,MAAM,CAAA,GAAI,MAAM,IAAA,EAAK;AACrB,MAAA,IAAI,CAAC,CAAA,EAAG;AACR,MAAA,IAAA,CAAK,UAAA,GAAa,aAAA,GAAgB,QAAA,EAAU,CAAC,CAAA;AAAA,IAC/C;AAAA,GACF;AACF;;;AC5OA,IAAM,cAAA,GAAiB,0CAAA;AACvB,IAAM,WAAA,GAAc,GAAA;AASpB,SAAS,gBAAgB,EAAA,EAAsB;AAC7C,EAAA,IAAI;AACF,IAAA,MAAM,KAAA,GAAQ,EAAA;AACd,IAAA,IAAI,KAAA,CAAM,IAAA,KAAS,QAAA,EAAU,OAAO,IAAA;AACpC,IAAA,MAAM,IAAA,GAAO,EAAA,CAAG,YAAA,CAAa,MAAM,CAAA,IAAK,EAAA;AACxC,IAAA,IAAI,IAAA,KAAS,WAAA,IAAe,IAAA,KAAS,UAAA,EAAY,OAAO,IAAA;AACxD,IAAA,MAAM,GAAA,GAAM;AAAA,MACV,KAAA,CAAM,IAAA;AAAA,MACN,KAAA,CAAM,WAAA;AAAA,MACN,EAAA,CAAG,aAAa,YAAY,CAAA;AAAA,MAC5B,EAAA,CAAG,EAAA;AAAA,MACH,EAAA,CAAG;AAAA,KACL,CACG,MAAA,CAAO,OAAO,CAAA,CACd,KAAK,GAAG,CAAA;AACX,IAAA,OAAO,cAAA,CAAe,KAAK,GAAG,CAAA;AAAA,EAChC,CAAA,CAAA,OAAQ,CAAA,EAAA;AACN,IAAA,OAAO,KAAA;AAAA,EACT;AACF;AAEO,SAAS,aAAA,CACd,SACA,IAAA,EACe;AA7CjB,EAAA,IAAAA,GAAAA,EAAA,EAAA;AA8CE,EAAA,IAAI,IAAA;AACJ,EAAA,IAAI,KAAA,GAAuB,IAAA;AAC3B,EAAA,IAAI,OAAA,GAAU,KAAA;AACd,EAAA,MAAM,mBAAkBA,GAAAA,GAAA,IAAA,CAAK,MAAA,KAAL,IAAA,GAAAA,MAAe,EAAC;AACxC,EAAA,MAAM,cAAA,GAAA,CAAiB,EAAA,GAAA,IAAA,CAAK,KAAA,KAAL,IAAA,GAAA,EAAA,GAAc,EAAC;AAEtC,EAAA,SAAS,QAAQ,EAAA,EAAW;AAC1B,IAAA,IAAI;AACF,MAAA,MAAM,SAAS,EAAA,CAAG,MAAA;AAClB,MAAA,IAAI,CAAC,MAAA,IAAW,MAAA,CAAO,YAAY,OAAA,IAAW,MAAA,CAAO,YAAY,UAAA,EAAa;AAC9E,MAAA,IAAI,CAAC,eAAA,CAAgB,MAAM,CAAA,EAAG;AAG9B,MAAA,IAAI,iBAAiB,MAAA,EAAQ,cAAc,CAAA,IAAK,qBAAA,CAAsB,QAAQ,eAAe,CAAA;AAC3F,QAAA;AACF,MAAA,MAAM,KAAA,GAAA,CAAS,MAAA,CAAO,KAAA,IAAS,EAAA,EAAI,IAAA,EAAK;AACxC,MAAA,IAAI,KAAA,CAAM,SAAS,CAAA,EAAG;AAEtB,MAAA,IAAI,KAAA,KAAU,IAAA,EAAM,MAAA,CAAO,YAAA,CAAa,KAAK,CAAA;AAC7C,MAAA,KAAA,GAAQ,MAAA,CAAO,WAAW,MAAM;AAC9B,QAAA,IAAA,GAAO,KAAA;AACP,QAAA,OAAA,CAAQ,aAAa,KAAK,CAAA;AAC1B,QAAA,IAAI,IAAA,CAAK,KAAA,EAAO,OAAA,CAAQ,KAAA,CAAM,iCAAiC,KAAK,CAAA;AAAA,MACtE,GAAG,WAAW,CAAA;AAAA,IAChB,CAAA,CAAA,OAAQ,CAAA,EAAA;AAAA,IAER;AAAA,EACF;AAEA,EAAA,OAAO;AAAA,IACL,KAAA,GAAQ;AACN,MAAA,IAAI,OAAA,IAAW,OAAO,QAAA,KAAa,WAAA,EAAa;AAChD,MAAA,OAAA,GAAU,IAAA;AACV,MAAA,IAAI;AACF,QAAA,QAAA,CAAS,gBAAA,CAAiB,OAAA,EAAS,OAAA,EAAS,IAAI,CAAA;AAAA,MAClD,CAAA,CAAA,OAAQ,CAAA,EAAA;AAAA,MAER;AAAA,IACF,CAAA;AAAA,IACA,IAAA,GAAO;AACL,MAAA,OAAA,GAAU,KAAA;AACV,MAAA,IAAI;AACF,QAAA,QAAA,CAAS,mBAAA,CAAoB,OAAA,EAAS,OAAA,EAAS,IAAI,CAAA;AACnD,QAAA,IAAI,KAAA,KAAU,IAAA,EAAM,MAAA,CAAO,YAAA,CAAa,KAAK,CAAA;AAAA,MAC/C,CAAA,CAAA,OAAQ,CAAA,EAAA;AAAA,MAER;AAAA,IACF,CAAA;AAAA,IACA,cAAA,GAAiB;AACf,MAAA,OAAO,IAAA;AAAA,IACT;AAAA,GACF;AACF;;;AC1FA,IAAM,WAAA,GAAc,EAAA;AACpB,IAAM,iBAAA,GAAoB,IAAA;AAUnB,SAAS,aAAa,IAAA,EAIZ;AACf,EAAA,IAAI,QAA0B,EAAC;AAC/B,EAAA,IAAI,QAAA;AACJ,EAAA,IAAI,QAAA,GAA0B,IAAA;AAC9B,EAAA,IAAI,OAAA,GAAU,KAAA;AAEd,EAAA,MAAM,MAAM,CAAA,EAAG,IAAA,CAAK,SAAS,OAAA,CAAQ,MAAA,EAAQ,EAAE,CAAC,CAAA,eAAA,CAAA;AAEhD,EAAA,SAAS,KAAK,OAAA,EAA2B;AACvC,IAAA,IAAI,OAAA,CAAQ,WAAW,CAAA,EAAG;AAC1B,IAAA,MAAM,OAAmB,EAAE,GAAA,EAAK,IAAA,CAAK,GAAA,EAAK,UAAU,OAAA,EAAQ;AAC5D,IAAA,MAAM,IAAA,GAAO,IAAA,CAAK,SAAA,CAAU,IAAI,CAAA;AAChC,IAAA,IAAI;AAIF,MAAA,IAAI,OAAO,SAAA,KAAc,WAAA,IAAe,OAAO,SAAA,CAAU,eAAe,UAAA,EAAY;AAClF,QAAA,MAAM,IAAA,GAAO,IAAI,IAAA,CAAK,CAAC,IAAI,CAAA,EAAG,EAAE,IAAA,EAAM,YAAA,EAAc,CAAA;AACpD,QAAA,MAAM,EAAA,GAAK,SAAA,CAAU,UAAA,CAAW,GAAA,EAAK,IAAI,CAAA;AACzC,QAAA,IAAI,EAAA,EAAI;AACN,UAAA,IAAI,KAAK,KAAA,EAAO,OAAA,CAAQ,KAAA,CAAM,qBAAA,EAAuB,QAAQ,MAAM,CAAA;AACnE,UAAA;AAAA,QACF;AAAA,MACF;AAEA,MAAA,KAAK,MAAM,GAAA,EAAK;AAAA,QACd,MAAA,EAAQ,MAAA;AAAA,QACR,OAAA,EAAS,EAAE,cAAA,EAAgB,YAAA,EAAa;AAAA,QACxC,IAAA,EAAM,IAAA;AAAA,QACN,SAAA,EAAW,IAAA;AAAA,QACX,IAAA,EAAM,MAAA;AAAA,QACN,WAAA,EAAa;AAAA,OACd,CAAA,CAAE,KAAA,CAAM,MAAM;AAAA,MAEf,CAAC,CAAA;AAAA,IACH,CAAA,CAAA,OAAQ,CAAA,EAAA;AAAA,IAER;AAAA,EACF;AAEA,EAAA,SAAS,YAAA,GAAe;AACtB,IAAA,IAAI;AACF,MAAA,IAAI,QAAA,CAAS,eAAA,KAAoB,QAAA,EAAU,KAAA,EAAM;AAAA,IACnD,CAAA,CAAA,OAAQ,CAAA,EAAA;AAAA,IAER;AAAA,EACF;AAEA,EAAA,SAAS,KAAA,GAAQ;AACf,IAAA,IAAI,KAAA,CAAM,WAAW,CAAA,EAAG;AACxB,IAAA,MAAM,KAAA,GAAQ,KAAA;AACd,IAAA,KAAA,GAAQ,EAAC;AACT,IAAA,IAAA,CAAK,KAAK,CAAA;AAAA,EACZ;AAEA,EAAA,OAAO;AAAA,IACL,KAAA,GAAQ;AACN,MAAA,IAAI,OAAA,IAAW,OAAO,MAAA,KAAW,WAAA,EAAa;AAC9C,MAAA,OAAA,GAAU,IAAA;AACV,MAAA,IAAI;AACF,QAAA,QAAA,CAAS,gBAAA,CAAiB,oBAAoB,YAAY,CAAA;AAC1D,QAAA,MAAA,CAAO,gBAAA,CAAiB,YAAY,KAAK,CAAA;AACzC,QAAA,QAAA,GAAW,MAAA,CAAO,WAAA,CAAY,KAAA,EAAO,iBAAiB,CAAA;AAAA,MACxD,CAAA,CAAA,OAAQ,CAAA,EAAA;AAAA,MAER;AAAA,IACF,CAAA;AAAA,IACA,IAAA,GAAO;AACL,MAAA,OAAA,GAAU,KAAA;AACV,MAAA,IAAI;AACF,QAAA,QAAA,CAAS,mBAAA,CAAoB,oBAAoB,YAAY,CAAA;AAC7D,QAAA,MAAA,CAAO,mBAAA,CAAoB,YAAY,KAAK,CAAA;AAC5C,QAAA,IAAI,QAAA,KAAa,IAAA,EAAM,MAAA,CAAO,aAAA,CAAc,QAAQ,CAAA;AAAA,MACtD,CAAA,CAAA,OAAQ,CAAA,EAAA;AAAA,MAER;AACA,MAAA,KAAA,EAAM;AAAA,IACR,CAAA;AAAA,IACA,QAAQ,MAAA,EAAQ;AACd,MAAA,KAAA,CAAM,KAAK,MAAM,CAAA;AACjB,MAAA,IAAI,KAAA,CAAM,MAAA,IAAU,WAAA,EAAa,KAAA,EAAM;AAAA,IACzC,CAAA;AAAA,IACA,KAAA;AAAA,IACA,YAAY,IAAA,EAAM;AAChB,MAAA,QAAA,GAAW,IAAA;AAAA,IACb;AAAA,GACF;AACF;;;ACrGO,IAAM,gBAAA,GAAmB,CAAA;AACzB,IAAMC,eAAAA,GAAiB,GAAA;AACvB,IAAM,oBAAA,GAAuB,CAAA;AAC7B,IAAM,kBAAA,GAAqB,GAAA;AAS3B,SAAS,cAAA,CACd,KAAA,EACA,GAAA,EACA,QAAA,GAAW,kBAAA,EACU;AAzBvB,EAAA,IAAAD,GAAAA;AA0BE,EAAA,MAAM,MAAA,GAAS,MAAM,MAAA,CAAO,CAAC,MAAM,GAAA,GAAM,CAAA,CAAE,KAAK,QAAQ,CAAA;AAExD,EAAA,IAAI,MAAA,CAAO,IAAA,CAAK,CAAC,CAAA,KAAM,CAAA,CAAE,IAAA,KAAS,OAAA,IAAW,CAAA,CAAE,IAAA,KAAS,eAAe,CAAA,EAAG,OAAO,OAAA;AAEjF,EAAA,MAAM,MAAA,GAAS,MAAA,CAAO,MAAA,CAAO,CAAC,CAAA,KAAM,EAAE,IAAA,KAAS,OAAA,IAAW,CAAA,CAAE,IAAA,KAAS,YAAY,CAAA;AACjF,EAAA,KAAA,IAAS,CAAA,GAAI,CAAA,EAAG,CAAA,GAAI,MAAA,CAAO,QAAQ,CAAA,EAAA,EAAK;AACtC,IAAA,MAAM,QAAQ,MAAA,CAAO,MAAA;AAAA,MACnB,CAAC,CAAA,KAAM,CAAA,CAAE,CAAA,IAAK,MAAA,CAAO,CAAC,CAAA,CAAE,CAAA,IAAK,CAAA,CAAE,CAAA,GAAI,MAAA,CAAO,CAAC,EAAE,CAAA,IAAKC;AAAA,KACpD;AACA,IAAA,IAAI,KAAA,CAAM,MAAA,IAAU,gBAAA,EAAkB,OAAO,MAAA;AAAA,EAC/C;AAEA,EAAA,IAAI,MAAA,CAAO,KAAK,CAAC,CAAA,KAAM,EAAE,IAAA,KAAS,YAAY,GAAG,OAAO,UAAA;AAExD,EAAA,MAAM,OAAA,uBAAc,GAAA,EAAoB;AACxC,EAAA,KAAA,MAAW,KAAK,MAAA,EAAQ;AACtB,IAAA,IAAI,CAAC,EAAE,KAAA,EAAO;AACd,IAAA,MAAM,CAAA,GAAA,CAAA,CAAKD,MAAA,OAAA,CAAQ,GAAA,CAAI,EAAE,KAAK,CAAA,KAAnB,IAAA,GAAAA,GAAAA,GAAwB,CAAA,IAAK,CAAA;AACxC,IAAA,OAAA,CAAQ,GAAA,CAAI,CAAA,CAAE,KAAA,EAAO,CAAC,CAAA;AACtB,IAAA,IAAI,CAAA,IAAK,sBAAsB,OAAO,OAAA;AAAA,EACxC;AAEA,EAAA,OAAO,IAAA;AACT;AASO,IAAM,YAAA,GAA4B;AAAA,EACvC,oBAAA,EAAsB,CAAA;AAAA,EACtB,YAAY,CAAA,GAAI;AAClB,CAAA;AAQO,SAAS,SAAA,CACd,KAAA,EACA,GAAA,EACA,IAAA,GAAoB,YAAA,EACX;AACT,EAAA,IAAI,KAAA,CAAM,YAAA,IAAgB,IAAA,CAAK,oBAAA,EAAsB,OAAO,KAAA;AAC5D,EAAA,IAAI,KAAA,CAAM,iBAAiB,IAAA,IAAQ,GAAA,GAAM,MAAM,YAAA,GAAe,IAAA,CAAK,YAAY,OAAO,KAAA;AACtF,EAAA,OAAO,IAAA;AACT;;;ACtDA,IAAM,6BAAa,IAAI,GAAA,CAAI,CAAC,QAAA,EAAU,cAAc,CAAC,CAAA;AAErD,SAAS,GAAA,CAAI,GAAY,GAAA,EAAiC;AACxD,EAAA,IAAI,OAAO,CAAA,KAAM,QAAA,EAAU,OAAO,MAAA;AAClC,EAAA,MAAM,CAAA,GAAI,EAAE,IAAA,EAAK;AACjB,EAAA,OAAO,CAAA,GAAI,CAAA,CAAE,KAAA,CAAM,CAAA,EAAG,GAAG,CAAA,GAAI,MAAA;AAC/B;AAIO,SAAS,iBAAA,CACd,OACA,QAAA,EACc;AACd,EAAA,MAAM,MAAoB,EAAC;AAC3B,EAAA,MAAM,CAAA,GAAI,GAAA,CAAI,KAAA,EAAO,GAAG,CAAA;AACxB,EAAA,IAAI,CAAA,MAAO,KAAA,GAAQ,CAAA;AACnB,EAAA,MAAM,OAAA,GAAU,GAAA,CAAI,QAAA,IAAA,IAAA,GAAA,MAAA,GAAA,QAAA,CAAU,OAAA,EAAS,GAAG,CAAA;AAC1C,EAAA,IAAI,OAAA,MAAa,OAAA,GAAU,OAAA;AAC3B,EAAA,MAAM,IAAA,GAAO,GAAA,CAAI,QAAA,IAAA,IAAA,GAAA,MAAA,GAAA,QAAA,CAAU,IAAA,EAAM,EAAE,CAAA;AACnC,EAAA,IAAI,IAAA,MAAU,IAAA,GAAO,IAAA;AACrB,EAAA,OAAO,GAAA;AACT;AAKO,SAAS,gBAAgB,GAAA,EAAyC;AACvE,EAAA,IAAI,CAAC,GAAA,IAAO,OAAO,GAAA,KAAQ,UAAU,OAAO,IAAA;AAC5C,EAAA,MAAM,CAAA,GAAI,GAAA;AACV,EAAA,MAAM,EAAA,GAAK,GAAA,CAAI,CAAA,CAAE,EAAA,EAAI,EAAE,CAAA;AACvB,EAAA,MAAM,IAAA,GAAO,GAAA,CAAI,CAAA,CAAE,IAAA,EAAM,EAAE,CAAA;AAC3B,EAAA,IAAI,CAAC,MAAM,CAAC,IAAA,IAAQ,CAAC,UAAA,CAAW,GAAA,CAAI,IAAI,CAAA,EAAG,OAAO,IAAA;AAElD,EAAA,MAAM,GAAA,GACJ,EAAE,MAAA,IAAU,OAAO,EAAE,MAAA,KAAW,QAAA,GAAY,CAAA,CAAE,MAAA,GAAqC,EAAC;AAEtF,EAAA,IAAI,SAAS,cAAA,EAAgB;AAO3B,IAAA,MAAM,KAAA,GAAQ,GAAA,CAAI,GAAA,CAAI,KAAA,EAAO,GAAG,CAAA;AAChC,IAAA,MAAM,UAAA,GAAa,GAAA,CAAI,GAAA,CAAI,UAAA,EAAY,GAAG,CAAA;AAC1C,IAAA,IAAI,CAAC,KAAA,IAAS,CAAC,UAAA,EAAY,OAAO,IAAA;AAClC,IAAA,MAAM,OAAA,GAAU,GAAA,CAAI,GAAA,CAAI,IAAA,EAAM,EAAE,CAAA;AAChC,IAAA,MAAM,OAAO,OAAA,IAAW,wBAAA,CAAyB,IAAA,CAAK,OAAO,IAAI,OAAA,GAAU,MAAA;AAC3E,IAAA,OAAO,EAAE,EAAA,EAAI,IAAA,EAAM,MAAA,EAAQ,EAAE,KAAA,EAAO,UAAA,EAAY,GAAI,IAAA,GAAO,EAAE,IAAA,EAAK,GAAI,IAAI,EAAE;AAAA,EAC9E;AAEA,EAAA,MAAM,QAAA,GAAW,GAAA,CAAI,GAAA,CAAI,QAAA,EAAU,GAAG,CAAA;AACtC,EAAA,IAAI,CAAC,UAAU,OAAO,IAAA;AAEtB,EAAA,MAAM,OAAA,GAAU,KAAA,CAAM,OAAA,CAAQ,GAAA,CAAI,OAAO,CAAA,GACpC,GAAA,CAAI,OAAA,CACF,GAAA,CAAI,CAAC,CAAA,KAAM,GAAA,CAAI,CAAA,EAAG,GAAG,CAAC,CAAA,CACtB,MAAA,CAAO,CAAC,CAAA,KAAmB,CAAC,CAAC,CAAC,CAAA,CAC9B,KAAA,CAAM,CAAA,EAAG,CAAC,CAAA,GACb,MAAA;AAEJ,EAAA,MAAM,MAAA,GAAuB;AAAA,IAC3B,QAAA;AAAA,IACA,GAAI,OAAA,IAAW,OAAA,CAAQ,SAAS,EAAE,OAAA,KAAY,EAAC;AAAA,IAC/C,UAAA,EAAY,IAAI,UAAA,KAAe;AAAA,GACjC;AACA,EAAA,OAAO,EAAE,EAAA,EAAI,IAAA,EAAM,QAAA,EAAU,MAAA,EAAO;AACtC;AAKO,SAAS,iBAAA,CACd,MAAA,EACA,SAAA,EACA,UAAA,EACQ;AACR,EAAA,MAAM,GAAA,GAAM,GAAA,CAAI,MAAA,EAAQ,GAAG,CAAA;AAC3B,EAAA,IAAI,KAAK,OAAO,GAAA;AAChB,EAAA,MAAM,CAAA,GAAI,GAAA,CAAI,SAAA,EAAW,GAAG,CAAA;AAC5B,EAAA,IAAI,GAAG,OAAO,CAAA;AACd,EAAA,OAAO,UAAA;AACT;AAEA,IAAM,cAAA,GAAiB,eAAA;AAIhB,SAAS,gBAAA,CACd,UACA,UAAA,EACQ;AACR,EAAA,MAAM,GAAA,GAAM,GAAA,CAAI,QAAA,IAAA,IAAA,GAAA,MAAA,GAAA,QAAA,CAAU,MAAA,EAAQ,GAAG,CAAA;AACrC,EAAA,IAAI,KAAK,OAAO,GAAA;AAChB,EAAA,IAAI;AACF,IAAA,IAAI,CAAA,GAAI,YAAA,CAAa,OAAA,CAAQ,cAAc,CAAA;AAC3C,IAAA,IAAI,CAAC,CAAA,EAAG;AACN,MAAA,CAAA,GAAI,OAAA,GAAU,IAAA,CAAK,MAAA,EAAO,CAAE,SAAS,EAAE,CAAA,CAAE,KAAA,CAAM,CAAC,CAAA,GAAI,IAAA,CAAK,GAAA,EAAI,CAAE,SAAS,EAAE,CAAA;AAC1E,MAAA,YAAA,CAAa,OAAA,CAAQ,gBAAgB,CAAC,CAAA;AAAA,IACxC;AACA,IAAA,OAAO,iBAAA,CAAkB,KAAA,CAAA,EAAW,CAAA,EAAG,UAAU,CAAA;AAAA,EACnD,CAAA,CAAA,OAAQ,CAAA,EAAA;AACN,IAAA,OAAO,UAAA;AAAA,EACT;AACF;AAEA,SAAS,QAAA,CAAS,UAAkB,IAAA,EAAsB;AACxD,EAAA,OAAO,GAAG,QAAA,CAAS,OAAA,CAAQ,QAAQ,EAAE,CAAC,YAAY,IAAI,CAAA,CAAA;AACxD;AAKA,eAAsB,kBAAkB,IAAA,EAMD;AA/IvC,EAAA,IAAAA,GAAAA;AAgJE,EAAA,IAAI;AACF,IAAA,IAAI,OAAO,KAAA,KAAU,UAAA,EAAY,OAAO,IAAA;AACxC,IAAA,MAAM,MAAM,MAAM,KAAA,CAAM,SAAS,IAAA,CAAK,QAAA,EAAU,OAAO,CAAA,EAAG;AAAA,MACxD,MAAA,EAAQ,MAAA;AAAA,MACR,OAAA,EAAS,EAAE,cAAA,EAAgB,YAAA,EAAa;AAAA,MACxC,IAAA,EAAM,KAAK,SAAA,CAAU;AAAA,QACnB,KAAK,IAAA,CAAK,GAAA;AAAA,QACV,SAAS,IAAA,CAAK,GAAA;AAAA,QACd,gBAAgB,IAAA,CAAK;AAAA,OACtB,CAAA;AAAA,MACD,IAAA,EAAM,MAAA;AAAA,MACN,WAAA,EAAa;AAAA,KACd,CAAA;AACD,IAAA,IAAI,CAAC,GAAA,CAAI,EAAA,EAAI,OAAO,IAAA;AACpB,IAAA,MAAM,IAAA,GAAQ,MAAM,GAAA,CAAI,IAAA,EAAK;AAC7B,IAAA,MAAM,MAAA,GAAS,eAAA,CAAgB,IAAA,IAAA,IAAA,GAAA,KAAA,CAAA,GAAA,IAAA,CAAM,YAAY,CAAA;AACjD,IAAA,IAAI,IAAA,CAAK,KAAA,EAAO,OAAA,CAAQ,KAAA,CAAM,oBAAA,EAAA,CAAsBA,MAAA,MAAA,IAAA,IAAA,GAAA,KAAA,CAAA,GAAA,MAAA,CAAQ,EAAA,KAAR,IAAA,GAAAA,GAAAA,GAAc,QAAQ,CAAA;AAC1E,IAAA,OAAO,MAAA;AAAA,EACT,CAAA,CAAA,OAAQ,CAAA,EAAA;AACN,IAAA,OAAO,IAAA;AAAA,EACT;AACF;AAIO,SAAS,eAAe,IAAA,EAMtB;AACP,EAAA,IAAI;AACF,IAAA,MAAM,GAAA,GAAM,QAAA,CAAS,IAAA,CAAK,QAAA,EAAU,SAAS,CAAA;AAC7C,IAAA,MAAM,IAAA,GAAO,KAAK,SAAA,CAAU;AAAA,MAC1B,KAAK,IAAA,CAAK,GAAA;AAAA,MACV,iBAAiB,IAAA,CAAK,cAAA;AAAA,MACtB,UAAU,IAAA,CAAK,QAAA;AAAA,MACf,gBAAgB,IAAA,CAAK;AAAA,KACtB,CAAA;AACD,IAAA,IAAI,OAAO,SAAA,KAAc,WAAA,IAAe,OAAO,SAAA,CAAU,eAAe,UAAA,EAAY;AAClF,MAAA,MAAM,IAAA,GAAO,IAAI,IAAA,CAAK,CAAC,IAAI,CAAA,EAAG,EAAE,IAAA,EAAM,YAAA,EAAc,CAAA;AACpD,MAAA,IAAI,SAAA,CAAU,UAAA,CAAW,GAAA,EAAK,IAAI,CAAA,EAAG;AAAA,IACvC;AACA,IAAA,IAAI,OAAO,UAAU,UAAA,EAAY;AAC/B,MAAA,KAAK,MAAM,GAAA,EAAK;AAAA,QACd,MAAA,EAAQ,MAAA;AAAA,QACR,OAAA,EAAS,EAAE,cAAA,EAAgB,YAAA,EAAa;AAAA,QACxC,IAAA,EAAM,IAAA;AAAA,QACN,SAAA,EAAW,IAAA;AAAA,QACX,IAAA,EAAM,MAAA;AAAA,QACN,WAAA,EAAa;AAAA,OACd,CAAA,CAAE,KAAA,CAAM,MAAM;AAAA,MAEf,CAAC,CAAA;AAAA,IACH;AAAA,EACF,CAAA,CAAA,OAAQ,CAAA,EAAA;AAAA,EAER;AACF;;;ACxMA,IAAM,WAAA,uBAAkB,GAAA,CAAI,CAAC,aAAa,WAAA,EAAa,SAAA,EAAW,KAAA,EAAO,EAAE,CAAC,CAAA;AAQrE,SAAS,YAAY,QAAA,EAA8C;AACxE,EAAA,MAAM,CAAA,GAAA,CAAK,QAAA,IAAA,IAAA,GAAA,QAAA,GAAY,EAAA,EAAI,IAAA,GAAO,WAAA,EAAY;AAC9C,EAAA,IAAI,WAAA,CAAY,GAAA,CAAI,CAAC,CAAA,EAAG,OAAO,IAAA;AAC/B,EAAA,OAAO,EAAE,QAAA,CAAS,QAAQ,CAAA,IAAK,CAAA,CAAE,SAAS,YAAY,CAAA;AACxD;;;ACYA,IAAM,gBAAA,GAAmB,4BAAA;AACzB,IAAM,yBAAA,GAA4B,GAAA;AAClC,IAAM,iBAAA,GAAoB,GAAA;AAE1B,IAAM,eAAA,GAAkB,IAAA;AAGxB,IAAM,6BAAA,GAAgC,CAAA;AAuBtC,SAAS,eAAA,GAA0B;AACjC,EAAA,IAAI;AACF,IAAA,OAAO,OAAO,QAAA,KAAa,WAAA,GAAc,QAAA,CAAS,QAAA,GAAW,EAAA;AAAA,EAC/D,CAAA,CAAA,OAAQ,CAAA,EAAA;AACN,IAAA,OAAO,EAAA;AAAA,EACT;AACF;AAEA,IAAI,IAAA,GAA0B,IAAA;AAE9B,SAAS,IAAA,GAAe;AACtB,EAAA,IAAI;AACF,IAAA,IAAI,OAAO,MAAA,KAAW,WAAA,IAAe,OAAO,MAAA,CAAO,eAAe,UAAA,EAAY;AAC5E,MAAA,OAAO,OAAO,UAAA,EAAW;AAAA,IAC3B;AAAA,EACF,CAAA,CAAA,OAAQ,CAAA,EAAA;AAAA,EAER;AACA,EAAA,OAAO,IAAA,GAAO,IAAA,CAAK,MAAA,EAAO,CAAE,SAAS,EAAE,CAAA,CAAE,KAAA,CAAM,CAAC,CAAA,GAAI,IAAA,CAAK,GAAA,EAAI,CAAE,SAAS,EAAE,CAAA;AAC5E;AAIA,SAAS,iBAAiB,CAAA,EAAyB;AACjD,EAAA,MAAM,MAAgB,EAAC;AACvB,EAAA,MAAM,IAAA,GAAO,CAAA,CAAE,OAAA,CAAQ,cAAA,EAAe;AACtC,EAAA,IAAI,IAAA,EAAM,GAAA,CAAI,IAAA,CAAK,CAAA,oBAAA,EAAkB,IAAI,CAAA,MAAA,CAAG,CAAA;AAC5C,EAAA,MAAM,KAAA,GAAQ,CAAA,CAAE,OAAA,CAAQ,KAAA,EAAM;AAC9B,EAAA,IAAI,KAAA,MAAW,IAAA,CAAK,CAAA,mBAAA,EAAiB,MAAM,KAAA,CAAM,CAAA,EAAG,EAAE,CAAC,CAAA,MAAA,CAAG,CAAA;AAC1D,EAAA,OAAO,GAAA;AACT;AAEA,SAAS,WAAA,CACP,CAAA,EACA,OAAA,EACA,KAAA,GAAiC,EAAC,EAClB;AAChB,EAAA,MAAM,GAAA,GAAM,CAAA,CAAE,OAAA,CAAQ,KAAA,EAAM;AAC5B,EAAA,OAAO;AAAA,IACL,WAAA,EAAA,iBAAa,IAAI,IAAA,EAAK,EAAE,WAAA,EAAY;AAAA,IACpC,KAAA,EAAO,CAAA,CAAE,OAAA,CAAQ,KAAA,EAAM;AAAA,IACvB,YAAA,EAAc,CAAA,CAAE,OAAA,CAAQ,KAAA,EAAM;AAAA,IAC9B,KAAA,EAAO,CAAA,CAAE,OAAA,CAAQ,KAAA,EAAM;AAAA,IACvB,aAAa,CAAA,CAAE,UAAA;AAAA,IACf,OAAA;AAAA,IACA,WAAA,EAAa,CAAA,CAAE,OAAA,CAAQ,cAAA,EAAe;AAAA,IACtC,KAAA,EAAO,GAAA;AAAA,IACP,OAAA,EAAS,GAAA,IAAO,OAAA,KAAY,UAAA,GAAa,QAAA,GAAW,SAAA;AAAA,IACpD,GAAG;AAAA,GACL;AACF;AAEA,eAAe,WAAA,CAAY,GAAe,OAAA,EAAkC;AA7G5E,EAAA,IAAAA,GAAAA;AA8GE,EAAA,MAAM,GAAA,GAAM,KAAK,GAAA,EAAI;AACrB,EAAA,IAAI,SAAA,CAAU,CAAA,CAAE,OAAA,EAAS,GAAA,EAAK,YAAY,CAAA,EAAG;AAC3C,IAAA,CAAA,CAAE,QAAQ,YAAA,IAAgB,CAAA;AAC1B,IAAA,CAAA,CAAE,QAAQ,YAAA,GAAe,GAAA;AACzB,IAAA,IAAI;AACF,MAAA,MAAM,EAAE,UAAA,EAAW,GAAI,MAAM,OAAO,sBAAU,CAAA;AAC9C,MAAA,MAAM,MAAA,GAAS,MAAM,UAAA,CAAW,EAAE,YAAY,gBAAA,CAAiB,CAAC,GAAG,CAAA;AACnE,MAAA,CAAA,CAAE,MAAA,CAAO,OAAA;AAAA,QACP,WAAA,CAAY,GAAG,OAAA,EAAS;AAAA,UACtB,QAAQ,MAAA,CAAO,MAAA;AAAA,UACf,UAAU,MAAA,CAAO,QAAA;AAAA,UACjB,WAAA,EAAA,CAAaA,MAAA,MAAA,CAAO,MAAA,KAAP,OAAAA,GAAAA,GAAiB,CAAA,CAAE,QAAQ,cAAA,EAAe;AAAA,UACvD,OAAA,EAAS,MAAA,CAAO,MAAA,KAAW,KAAA,GAAQ,UAAA,GAAa;AAAA,SACjD;AAAA,OACH;AAAA,IACF,CAAA,CAAA,OAAQ,CAAA,EAAA;AAEN,MAAA,CAAA,CAAE,MAAA,CAAO,OAAA,CAAQ,WAAA,CAAY,CAAA,EAAG,OAAO,CAAC,CAAA;AAAA,IAC1C;AAAA,EACF,CAAA,MAAO;AAEL,IAAA,CAAA,CAAE,MAAA,CAAO,OAAA,CAAQ,WAAA,CAAY,CAAA,EAAG,OAAO,CAAC,CAAA;AAAA,EAC1C;AACF;AAOA,eAAe,uBAAuB,CAAA,EAAe;AACnD,EAAA,IAAI,CAAC,CAAA,CAAE,OAAA,IAAW,CAAC,CAAA,CAAE,oBAAA,IAAwB,EAAE,UAAA,EAAY;AAC3D,EAAA,IAAI,EAAE,cAAA,EAAgB;AACtB,EAAA,IAAI,CAAA,CAAE,sBAAsB,6BAAA,EAA+B;AAC3D,EAAA,MAAM,GAAA,GAAM,KAAK,GAAA,EAAI;AACrB,EAAA,IAAI,CAAA,CAAE,QAAQ,YAAA,KAAiB,IAAA,IAAQ,MAAM,CAAA,CAAE,OAAA,CAAQ,eAAe,YAAA,CAAa,UAAA;AACjF,IAAA;AAEF,EAAA,MAAM,aAAA,GAAgB,gBAAA,CAAiB,CAAA,CAAE,QAAA,EAAU,EAAE,UAAU,CAAA;AAC/D,EAAA,MAAM,MAAA,GAAS,MAAM,iBAAA,CAAkB;AAAA,IACrC,QAAA,EAAU,EAAE,MAAA,CAAO,QAAA;AAAA,IACnB,GAAA,EAAK,EAAE,MAAA,CAAO,GAAA;AAAA,IACd,KAAK,iBAAA,CAAkB,CAAA,CAAE,QAAQ,KAAA,EAAM,EAAG,EAAE,QAAQ,CAAA;AAAA,IACpD,aAAA;AAAA,IACA,KAAA,EAAO,EAAE,MAAA,CAAO;AAAA,GACjB,CAAA;AACD,EAAA,IAAI,CAAC,MAAA,IAAU,CAAC,CAAA,CAAE,OAAA,EAAS;AAE3B,EAAA,MAAM,YAAY,CAAA,CAAE,kBAAA;AACpB,EAAA,MAAM,YAAA,GAAe,EAAE,OAAA,CAAQ,YAAA;AAC/B,EAAA,CAAA,CAAE,cAAA,GAAiB,IAAA;AACnB,EAAA,CAAA,CAAE,kBAAA,IAAsB,CAAA;AACxB,EAAA,CAAA,CAAE,OAAA,CAAQ,YAAA,GAAe,IAAA,CAAK,GAAA,EAAI;AAClC,EAAA,IAAI;AACF,IAAA,IAAI,MAAA,CAAO,SAAS,cAAA,EAAgB;AAGlC,MAAA,MAAM,EAAE,SAAA,EAAU,GAAI,MAAM,OAAO,qBAAS,CAAA;AAC5C,MAAA,MAAM,MAAA,GAAS,MAAM,SAAA,CAAU,MAAA,CAAO,MAAM,CAAA;AAC5C,MAAA,IAAI,CAAC,OAAO,OAAA,EAAS;AAInB,QAAA,CAAA,CAAE,kBAAA,GAAqB,SAAA;AACvB,QAAA,CAAA,CAAE,QAAQ,YAAA,GAAe,YAAA;AAAA,MAC3B,CAAA,MAAA,IAAW,OAAO,KAAA,EAAO;AACvB,QAAA,cAAA,CAAe;AAAA,UACb,QAAA,EAAU,EAAE,MAAA,CAAO,QAAA;AAAA,UACnB,GAAA,EAAK,EAAE,MAAA,CAAO,GAAA;AAAA,UACd,gBAAgB,MAAA,CAAO,EAAA;AAAA,UACvB,QAAA,EAAU,EAAE,MAAA,EAAQ,MAAA,EAAO;AAAA,UAC3B;AAAA,SACD,CAAA;AAAA,MACH;AAAA,IACF,CAAA,MAAO;AACL,MAAA,MAAM,EAAE,UAAA,EAAW,GAAI,MAAM,OAAO,sBAAU,CAAA;AAC9C,MAAA,MAAM,MAAA,GAAS,MAAM,UAAA,CAAW,MAAA,CAAO,MAAM,CAAA;AAC7C,MAAA,IAAI,CAAC,MAAA,CAAO,SAAA,KAAc,MAAA,CAAO,MAAA,IAAU,OAAO,IAAA,CAAA,EAAO;AACvD,QAAA,cAAA,CAAe;AAAA,UACb,QAAA,EAAU,EAAE,MAAA,CAAO,QAAA;AAAA,UACnB,GAAA,EAAK,EAAE,MAAA,CAAO,GAAA;AAAA,UACd,gBAAgB,MAAA,CAAO,EAAA;AAAA,UACvB,UAAU,EAAE,MAAA,EAAQ,OAAO,MAAA,EAAQ,IAAA,EAAM,OAAO,IAAA,EAAK;AAAA,UACrD;AAAA,SACD,CAAA;AAAA,MACH;AAAA,IACF;AAAA,EACF,CAAA,CAAA,OAAQ,CAAA,EAAA;AAAA,EAER,CAAA,SAAE;AACA,IAAA,CAAA,CAAE,cAAA,GAAiB,KAAA;AAAA,EACrB;AACF;AAEA,SAAS,cAAA,GAAiB;AACxB,EAAA,MAAM,CAAA,GAAI,IAAA;AACV,EAAA,IAAI,CAAC,CAAA,IAAK,CAAC,CAAA,CAAE,OAAA,EAAS;AAGtB,EAAA,IAAI;AACF,IAAA,MAAM,KAAA,GAAQ,CAAA,CAAE,OAAA,CAAQ,KAAA,EAAM;AAC9B,IAAA,IAAI,KAAA,IAAS,KAAA,KAAU,CAAA,CAAE,cAAA,EAAgB;AACvC,MAAA,CAAA,CAAE,cAAA,GAAiB,KAAA;AACnB,MAAA,KAAK,uBAAuB,CAAC,CAAA;AAAA,IAC/B;AAAA,EACF,CAAA,CAAA,OAAQ,CAAA,EAAA;AAAA,EAER;AAEA,EAAA,IAAI,CAAA,CAAE,eAAe,IAAA,EAAM;AAC3B,EAAA,CAAA,CAAE,cAAc,OAAO,MAAA,KAAW,cAAc,MAAA,CAAO,UAAA,GAAa,YAAY,MAAM;AACpF,IAAA,CAAA,CAAE,UAAA,GAAa,IAAA;AACf,IAAA,IAAI;AACF,MAAA,MAAM,GAAA,GAAM,KAAK,GAAA,EAAI;AACrB,MAAA,IAAI,GAAA,GAAM,CAAA,CAAE,kBAAA,GAAqB,yBAAA,EAA2B;AAC5D,MAAA,MAAM,OAAO,cAAA,CAAe,CAAA,CAAE,OAAA,CAAQ,KAAA,IAAS,GAAG,CAAA;AAClD,MAAA,IAAI,CAAC,IAAA,EAAM;AACX,MAAA,CAAA,CAAE,kBAAA,GAAqB,GAAA;AACvB,MAAA,KAAK,WAAA,CAAY,GAAG,UAAU,CAAA;AAAA,IAChC,CAAA,CAAA,OAAQ,CAAA,EAAA;AAAA,IAER;AAAA,EACF,GAAG,iBAAiB,CAAA;AACtB;AAEA,SAAS,aAAa,EAAA,EAAgB;AACpC,EAAA,MAAM,CAAA,GAAI,IAAA;AACV,EAAA,IAAI,CAAC,KAAK,CAAC,CAAA,CAAE,WAAW,CAAC,CAAA,CAAE,OAAO,WAAA,EAAa;AAC/C,EAAA,IAAI;AACF,IAAA,IAAI,GAAG,OAAA,IAAW,CAAA,EAAG,KAAK,WAAA,CAAY,GAAG,UAAU,CAAA;AAAA,EACrD,CAAA,CAAA,OAAQ,CAAA,EAAA;AAAA,EAER;AACF;AAEA,SAAS,aAAa,CAAA,EAAe;AACnC,EAAA,IAAI,EAAE,OAAA,EAAS;AACf,EAAA,IAAI,EAAE,UAAA,EAAY;AAChB,IAAA,IAAI,EAAE,MAAA,CAAO,KAAA;AACX,MAAA,OAAA,CAAQ,KAAA;AAAA,QACN;AAAA,OACF;AACF,IAAA;AAAA,EACF;AACA,EAAA,CAAA,CAAE,OAAA,GAAU,IAAA;AACZ,EAAA,CAAA,CAAE,QAAQ,KAAA,EAAM;AAChB,EAAA,CAAA,CAAE,QAAQ,KAAA,EAAM;AAChB,EAAA,CAAA,CAAE,OAAO,KAAA,EAAM;AACf,EAAA,CAAA,CAAE,OAAA,CAAQ,QAAQ,cAAc,CAAA;AAChC,EAAA,IAAI;AACF,IAAA,QAAA,CAAS,gBAAA,CAAiB,YAAY,YAAY,CAAA;AAAA,EACpD,CAAA,CAAA,OAAQ,CAAA,EAAA;AAAA,EAER;AAGA,EAAA,IAAI,EAAE,oBAAA,EAAsB;AAC1B,IAAA,CAAA,CAAE,kBAAkB,MAAM;AACxB,MAAA,IAAI;AACF,QAAA,OAAO,CAAA,CAAE,QAAQ,KAAA,EAAM;AAAA,MACzB,CAAA,CAAA,OAAQ,CAAA,EAAA;AACN,QAAA,OAAO,IAAA;AAAA,MACT;AAAA,IACF,CAAA,GAAG;AACH,IAAA,CAAC,OAAO,MAAA,KAAW,WAAA,GAAc,MAAA,CAAO,UAAA,GAAa,YAAY,MAAM;AACrE,MAAA,KAAK,uBAAuB,CAAC,CAAA;AAAA,IAC/B,GAAG,eAAe,CAAA;AAAA,EACpB;AACA,EAAA,IAAI,EAAE,MAAA,CAAO,KAAA,UAAe,KAAA,CAAM,sBAAA,EAAwB,EAAE,UAAU,CAAA;AACxE;AAIO,SAAS,KAAK,MAAA,EAAgC;AACnD,EAAA,IAAI;AACF,IAAA,IAAI,CAAC,MAAA,IAAU,CAAC,MAAA,CAAO,GAAA,EAAK;AAC1B,MAAA,OAAA,CAAQ,KAAK,wCAAwC,CAAA;AACrD,MAAA;AAAA,IACF;AACA,IAAA,IAAI,IAAA,EAAM;AACV,IAAA,MAAM,QAAA,GAAW,OAAO,QAAA,IAAY,gBAAA;AACpC,IAAA,MAAM,cAAc,EAAE,MAAA,EAAQ,OAAO,MAAA,EAAQ,KAAA,EAAO,OAAO,KAAA,EAAM;AACjE,IAAA,MAAM,OAAA,GAAU,aAAA,CAAc,EAAE,KAAA,EAAO,CAAC,CAAC,MAAA,CAAO,KAAA,EAAO,GAAG,WAAA,EAAa,CAAA;AACvE,IAAA,MAAM,OAAA,GAAU,aAAA,CAAc,OAAA,EAAS,EAAE,KAAA,EAAO,CAAC,CAAC,MAAA,CAAO,KAAA,EAAO,GAAG,WAAA,EAAa,CAAA;AAChF,IAAA,MAAM,MAAA,GAAS,YAAA,CAAa,EAAE,GAAA,EAAK,MAAA,CAAO,GAAA,EAAK,QAAA,EAAU,KAAA,EAAO,CAAC,CAAC,MAAA,CAAO,KAAA,EAAO,CAAA;AAChF,IAAA,IAAA,GAAO;AAAA,MACL,MAAA,EAAQ;AAAA,QACN,GAAG,MAAA;AAAA,QACH,KAAK,MAAA,CAAO,GAAA;AAAA,QACZ,QAAA;AAAA,QACA,WAAA,EAAa,OAAO,WAAA,KAAgB,KAAA;AAAA,QACpC,KAAA,EAAO,CAAC,CAAC,MAAA,CAAO;AAAA,OAClB;AAAA,MACA,OAAA;AAAA,MACA,OAAA;AAAA,MACA,MAAA;AAAA,MACA,UAAU,EAAC;AAAA,MACX,YAAY,IAAA,EAAK;AAAA,MACjB,OAAA,EAAS,EAAE,YAAA,EAAc,CAAA,EAAG,cAAc,IAAA,EAAK;AAAA,MAC/C,kBAAA,EAAoB,CAAA;AAAA,MACpB,UAAA,EAAY,IAAA;AAAA,MACZ,OAAA,EAAS,KAAA;AAAA,MACT,YAAY,WAAA,CAAY,eAAA,EAAiB,CAAA,IAAK,OAAO,kBAAA,KAAuB,IAAA;AAAA,MAC5E,oBAAA,EAAsB,OAAO,aAAA,KAAkB,KAAA;AAAA,MAC/C,cAAA,EAAgB,IAAA;AAAA,MAChB,cAAA,EAAgB,KAAA;AAAA,MAChB,kBAAA,EAAoB;AAAA,KACtB;AACA,IAAA,IAAI,MAAA,CAAO,OAAA,KAAY,KAAA,EAAO,YAAA,CAAa,IAAI,CAAA;AAAA,EACjD,SAAS,GAAA,EAAK;AAEZ,IAAA,IAAI;AACF,MAAA,OAAA,CAAQ,IAAA,CAAK,4BAA4B,GAAG,CAAA;AAAA,IAC9C,CAAA,CAAA,OAAQ,CAAA,EAAA;AAAA,IAER;AAAA,EACF;AACF;AAEO,SAAS,QAAA,CAAS,QAAgB,MAAA,EAAoD;AAC3F,EAAA,IAAI;AACF,IAAA,IAAI,CAAC,IAAA,EAAM;AACX,IAAA,IAAA,CAAK,QAAA,GAAW,EAAE,MAAA,EAAQ,OAAA,EAAS,iCAAQ,OAAA,EAAS,IAAA,EAAM,iCAAQ,IAAA,EAAK;AACvE,IAAA,IAAA,CAAK,MAAA,CAAO,WAAA,CAAY,IAAA,CAAK,QAAQ,CAAA;AAAA,EACvC,CAAA,CAAA,OAAQ,CAAA,EAAA;AAAA,EAER;AACF;AAGO,SAAS,KAAA,GAAc;AAC5B,EAAA,IAAI;AACF,IAAA,IAAI,IAAA,eAAmB,IAAI,CAAA;AAAA,EAC7B,CAAA,CAAA,OAAQ,CAAA,EAAA;AAAA,EAER;AACF;AAOO,SAAS,QAAQ,OAAA,EAAwB;AAC9C,EAAA,IAAI;AACF,IAAA,IAAI,CAAC,IAAA,EAAM;AACX,IAAA,IAAI,OAAA,eAAsB,IAAI,CAAA;AAAA,SACzB,IAAA,EAAK;AAAA,EACZ,CAAA,CAAA,OAAQ,CAAA,EAAA;AAAA,EAER;AACF;AAGO,SAAS,IAAA,GAAa;AAC3B,EAAA,IAAI;AACF,IAAA,IAAI,CAAC,IAAA,EAAM;AACX,IAAA,IAAA,CAAK,OAAA,GAAU,KAAA;AACf,IAAA,IAAA,CAAK,QAAQ,IAAA,EAAK;AAClB,IAAA,IAAA,CAAK,QAAQ,IAAA,EAAK;AAClB,IAAA,IAAA,CAAK,OAAO,IAAA,EAAK;AACjB,IAAA,IAAI;AACF,MAAA,QAAA,CAAS,mBAAA,CAAoB,YAAY,YAAY,CAAA;AAAA,IACvD,CAAA,CAAA,OAAQ,CAAA,EAAA;AAAA,IAER;AAAA,EACF,CAAA,CAAA,OAAQ,CAAA,EAAA;AAAA,EAER;AACF;AAEA,IAAM,MAAM,EAAE,IAAA,EAAM,QAAA,EAAU,KAAA,EAAO,MAAM,OAAA,EAAQ;AACnD,IAAO,WAAA,GAAQ;AA9Xf,IAAA,EAAA;AAoYA,IAAI;AACF,EAAA,IAAI,OAAO,aAAa,WAAA,EAAa;AAGnC,IAAA,MAAM,MACH,EAAA,GAAA,QAAA,CAAS,aAAA,KAAT,IAAA,GAAA,EAAA,GACD,QAAA,CAAS,cAAiC,6BAA6B,CAAA;AACzE,IAAA,MAAM,GAAA,GAAM,yBAAI,YAAA,CAAa,qBAAA,CAAA;AAC7B,IAAA,IAAI,GAAA,EAAK;AAIP,MAAA,IAAI,QAAA,GAAA,CAAW,EAAA,IAAA,IAAA,GAAA,KAAA,CAAA,GAAA,EAAA,CAAI,YAAA,CAAa,0BAAA,CAAA,KAA+B,KAAA,CAAA;AAC/D,MAAA,IAAI,CAAC,QAAA,KAAY,EAAA,IAAA,IAAA,GAAA,KAAA,CAAA,GAAA,EAAA,CAAI,GAAA,CAAA,EAAK;AACxB,QAAA,IAAI;AACF,UAAA,QAAA,GAAW,IAAI,GAAA,CAAI,EAAA,CAAG,GAAG,CAAA,CAAE,MAAA;AAAA,QAC7B,CAAA,CAAA,OAAQ,CAAA,EAAA;AAAA,QAER;AAAA,MACF;AAGA,MAAA,MAAM,IAAA,GAAO,CAAC,IAAA,KAAuC;AACnD,QAAA,MAAM,GAAA,GAAM,yBAAI,YAAA,CAAa,IAAA,CAAA;AAC7B,QAAA,IAAI,CAAC,KAAK,OAAO,KAAA,CAAA;AACjB,QAAA,MAAM,GAAA,GAAM,GAAA,CACT,KAAA,CAAM,GAAG,CAAA,CACT,GAAA,CAAI,CAAC,CAAA,KAAM,CAAA,CAAE,IAAA,EAAM,CAAA,CACnB,OAAO,OAAO,CAAA;AACjB,QAAA,OAAO,GAAA,CAAI,SAAS,GAAA,GAAM,KAAA,CAAA;AAAA,MAC5B,CAAA;AACA,MAAA,IAAA,CAAK;AAAA,QACH,GAAA;AAAA,QACA,QAAA;AAAA,QACA,MAAA,EAAQ,KAAK,wBAAwB,CAAA;AAAA,QACrC,KAAA,EAAO,KAAK,uBAAuB,CAAA;AAAA,QACnC,kBAAA,EAAA,CAAoB,EAAA,IAAA,IAAA,GAAA,KAAA,CAAA,GAAA,EAAA,CAAI,YAAA,CAAa,mCAAA,CAAA,KAAwC,KAAA,CAAA;AAAA,QAC7E,aAAA,EAAA,CAAe,EAAA,IAAA,IAAA,GAAA,KAAA,CAAA,GAAA,EAAA,CAAI,YAAA,CAAa,kCAAA,CAAA,IAAsC,KAAA,GAAQ,KAAA,CAAA;AAAA,QAC9E,KAAA,EAAA,CAAO,EAAA,IAAA,IAAA,GAAA,KAAA,CAAA,GAAA,EAAA,CAAI,YAAA,CAAa,uBAAA,CAAA,KAA4B,KAAA;AAAA,OACrD,CAAA;AAAA,IACH;AAAA,EACF;AACF,CAAA,CAAA,OAAQ,CAAA,EAAA;AAER","file":"index.js","sourcesContent":["// Passive context capture (FR-2) — the buffer of route/click/error events the\n// rest of the runtime reads. All DOM access is guarded and wrapped: this module\n// must never throw into the host app (NFR-3).\n\nimport type { TrailEvent, TrailEventType } from \"./types\";\nimport { redactText, isIgnoredElement, matchesRedactSelector, REDACTED } from \"./privacy\";\n\nconst TRAIL_MAX = 30;\nconst DEAD_CLICK_MS = 700; // a click with no DOM/route change after this = dead-click\nconst RAGE_WINDOW_MS = 1_000;\nconst RAGE_COUNT = 3;\n\nexport type CaptureHandle = {\n start(): void;\n stop(): void;\n trail(): TrailEvent[];\n route(): string;\n label(): string;\n error(): string | undefined;\n /** Subscribe to \"a meaningful event happened\" (the trigger engine polls off this). */\n onEvent(cb: () => void): void;\n /** Called by harvest.ts when a search/filter query is typed. */\n recordSearch(query: string, zeroResult?: boolean): void;\n};\n\nfunction hasDom(): boolean {\n return typeof window !== \"undefined\" && typeof document !== \"undefined\";\n}\n\nexport function createCapture(opts: {\n debug: boolean;\n redact?: readonly string[];\n block?: readonly string[];\n}): CaptureHandle {\n const redactSelectors = opts.redact ?? [];\n const blockSelectors = opts.block ?? [];\n let buf: TrailEvent[] = [];\n let lastError: string | undefined;\n let started = false;\n const subs: Array<() => void> = [];\n const cleanups: Array<() => void> = [];\n let recentClicks: number[] = []; // timestamps, for rage detection\n\n function notify() {\n for (const cb of subs) {\n try {\n cb();\n } catch {\n /* a subscriber must never break capture */\n }\n }\n }\n\n function push(type: TrailEventType, label?: string) {\n try {\n buf.push({ t: Date.now(), type, label: label ? redactText(label) : undefined });\n if (buf.length > TRAIL_MAX) buf = buf.slice(-TRAIL_MAX);\n if (opts.debug) console.debug(\"[sightspool] event\", type, label);\n notify();\n } catch {\n /* swallow */\n }\n }\n\n function currentRoute(): string {\n try {\n return location.pathname + location.search;\n } catch {\n return \"\";\n }\n }\n\n function currentLabel(): string {\n try {\n return document.title || \"\";\n } catch {\n return \"\";\n }\n }\n\n function onClick(ev: MouseEvent) {\n try {\n const target = ev.target as Element | null;\n // Hard opt-out: a click inside [data-sightspool-ignore] or a `block` selector is\n // never recorded — not even as an unlabelled event (GOV-3).\n if (isIgnoredElement(target, blockSelectors)) return;\n const text =\n (target && (target.getAttribute?.(\"aria-label\") || target.textContent)) || \"\";\n // `redact` selectors mask the label wholesale; emails/digits in any label are\n // also masked by push() → redactText.\n const label = matchesRedactSelector(target, redactSelectors)\n ? REDACTED\n : text.trim().slice(0, 60);\n const t = Date.now();\n\n recentClicks = recentClicks.filter((ts) => t - ts <= RAGE_WINDOW_MS);\n recentClicks.push(t);\n const isRage = recentClicks.length >= RAGE_COUNT;\n push(isRage ? \"rage_click\" : \"click\", label);\n\n // dead-click: did anything change shortly after? watch for a DOM mutation or\n // a route change; if neither, record a dead_click.\n const routeBefore = currentRoute();\n let mutated = false;\n let observer: MutationObserver | null = null;\n try {\n observer = new MutationObserver(() => {\n mutated = true;\n });\n observer.observe(document.body, { childList: true, subtree: true, attributes: true });\n } catch {\n /* no MutationObserver — skip dead-click detection */\n }\n window.setTimeout(() => {\n try {\n observer?.disconnect();\n if (!mutated && currentRoute() === routeBefore && label) {\n push(\"dead_click\", label);\n }\n } catch {\n /* swallow */\n }\n }, DEAD_CLICK_MS);\n } catch {\n /* swallow */\n }\n }\n\n function onError(ev: ErrorEvent) {\n try {\n lastError = String(ev.message || \"error\");\n push(\"error\", lastError);\n } catch {\n /* swallow */\n }\n }\n\n function onRejection(ev: PromiseRejectionEvent) {\n try {\n const reason = ev.reason;\n lastError = reason instanceof Error ? reason.message : String(reason);\n push(\"error\", lastError);\n } catch {\n /* swallow */\n }\n }\n\n // Route changes: patch history.pushState/replaceState + listen for popstate.\n function installRouteTracking() {\n try {\n const fire = () => push(\"route\", currentRoute());\n const origPush = history.pushState;\n const origReplace = history.replaceState;\n history.pushState = function (this: History, ...args: Parameters<History[\"pushState\"]>) {\n const r = origPush.apply(this, args);\n fire();\n return r;\n };\n history.replaceState = function (\n this: History,\n ...args: Parameters<History[\"replaceState\"]>\n ) {\n const r = origReplace.apply(this, args);\n fire();\n return r;\n };\n window.addEventListener(\"popstate\", fire);\n cleanups.push(() => {\n history.pushState = origPush;\n history.replaceState = origReplace;\n window.removeEventListener(\"popstate\", fire);\n });\n push(\"route\", currentRoute()); // seed with the entry route\n } catch {\n /* swallow */\n }\n }\n\n // Light fetch wrapper to catch failed/4xx-5xx requests as request_error events.\n function installFetchTracking() {\n try {\n if (typeof window.fetch !== \"function\") return;\n const orig = window.fetch.bind(window);\n window.fetch = async (...args: Parameters<typeof fetch>) => {\n try {\n const res = await orig(...args);\n if (!res.ok) push(\"request_error\", `HTTP ${res.status}`);\n return res;\n } catch (err) {\n push(\"request_error\", err instanceof Error ? err.message : \"network error\");\n throw err;\n }\n };\n cleanups.push(() => {\n window.fetch = orig;\n });\n } catch {\n /* swallow */\n }\n }\n\n return {\n start() {\n if (started || !hasDom()) return;\n started = true;\n try {\n document.addEventListener(\"click\", onClick, true);\n window.addEventListener(\"error\", onError);\n window.addEventListener(\"unhandledrejection\", onRejection);\n cleanups.push(() => {\n document.removeEventListener(\"click\", onClick, true);\n window.removeEventListener(\"error\", onError);\n window.removeEventListener(\"unhandledrejection\", onRejection);\n });\n installRouteTracking();\n installFetchTracking();\n } catch {\n /* swallow */\n }\n },\n stop() {\n started = false;\n for (const c of cleanups.splice(0)) {\n try {\n c();\n } catch {\n /* swallow */\n }\n }\n },\n trail() {\n return buf.slice();\n },\n route: currentRoute,\n label: currentLabel,\n error() {\n return lastError;\n },\n onEvent(cb) {\n subs.push(cb);\n },\n recordSearch(query, zeroResult) {\n const q = query.trim();\n if (!q) return;\n push(zeroResult ? \"zero_result\" : \"search\", q);\n },\n };\n}\n","// Intent harvest (FR-3) — treat typed queries in search / filter / command-palette\n// / empty-state inputs as STATED intent (the highest-signal intent, no question\n// needed). Harvesting precedes any inference. Defensive throughout (NFR-3).\n//\n// Zero-result detection is genuinely cross-app-specific and best-effort in v1: we\n// capture the query as a search event; flagging it as zero-result reliably is a\n// follow-up (it needs per-app empty-state hints). The query itself is the value.\n\nimport type { CaptureHandle } from \"./capture\";\nimport { isIgnoredElement, matchesRedactSelector } from \"./privacy\";\n\nconst SEARCH_HINT_RE = /search|filter|find|query|command|lookup/i;\nconst DEBOUNCE_MS = 800;\n\nexport type HarvestHandle = {\n start(): void;\n stop(): void;\n /** The most recent stated intent (last search/filter query), for State-B candidates. */\n lastIntentHint(): string | undefined;\n};\n\nfunction looksLikeSearch(el: Element): boolean {\n try {\n const input = el as HTMLInputElement;\n if (input.type === \"search\") return true;\n const role = el.getAttribute(\"role\") || \"\";\n if (role === \"searchbox\" || role === \"combobox\") return true;\n const hay = [\n input.name,\n input.placeholder,\n el.getAttribute(\"aria-label\"),\n el.id,\n el.className,\n ]\n .filter(Boolean)\n .join(\" \");\n return SEARCH_HINT_RE.test(hay);\n } catch {\n return false;\n }\n}\n\nexport function createHarvest(\n capture: CaptureHandle,\n opts: { debug: boolean; redact?: readonly string[]; block?: readonly string[] },\n): HarvestHandle {\n let hint: string | undefined;\n let timer: number | null = null;\n let started = false;\n const redactSelectors = opts.redact ?? [];\n const blockSelectors = opts.block ?? [];\n\n function onInput(ev: Event) {\n try {\n const target = ev.target as HTMLInputElement | null;\n if (!target || (target.tagName !== \"INPUT\" && target.tagName !== \"TEXTAREA\")) return;\n if (!looksLikeSearch(target)) return;\n // A masked query is useless intent, so a `redact`-matched search box is treated\n // as a hard opt-out here (same as `block`/ignore): don't harvest the value at all.\n if (isIgnoredElement(target, blockSelectors) || matchesRedactSelector(target, redactSelectors))\n return;\n const value = (target.value || \"\").trim();\n if (value.length < 2) return;\n\n if (timer !== null) window.clearTimeout(timer);\n timer = window.setTimeout(() => {\n hint = value;\n capture.recordSearch(value);\n if (opts.debug) console.debug(\"[sightspool] harvested intent\", value);\n }, DEBOUNCE_MS);\n } catch {\n /* swallow */\n }\n }\n\n return {\n start() {\n if (started || typeof document === \"undefined\") return;\n started = true;\n try {\n document.addEventListener(\"input\", onInput, true);\n } catch {\n /* swallow */\n }\n },\n stop() {\n started = false;\n try {\n document.removeEventListener(\"input\", onInput, true);\n if (timer !== null) window.clearTimeout(timer);\n } catch {\n /* swallow */\n }\n },\n lastIntentHint() {\n return hint;\n },\n };\n}\n","// Egress — batch captured Signals and ship them to /api/sdk/ingest, preferring\n// navigator.sendBeacon (survives page unload) with a fetch+keepalive fallback.\n// Every path is wrapped: a failed send must never surface in the host app (NFR-3),\n// and a Signal already records its why/cost passively, so a dropped beacon just\n// loses enrichment, not the capture's value (FR-7).\n\nimport type { CapturedSignal, Identity, IngestBody } from \"./types\";\n\nconst FLUSH_BATCH = 10; // flush when this many Signals are queued\nconst FLUSH_INTERVAL_MS = 15_000;\n\nexport type EgressHandle = {\n start(): void;\n stop(): void;\n enqueue(signal: CapturedSignal): void;\n flush(): void;\n setIdentity(identity: Identity): void;\n};\n\nexport function createEgress(opts: {\n key: string;\n endpoint: string;\n debug: boolean;\n}): EgressHandle {\n let queue: CapturedSignal[] = [];\n let identity: Identity | undefined;\n let interval: number | null = null;\n let started = false;\n\n const url = `${opts.endpoint.replace(/\\/+$/, \"\")}/api/sdk/ingest`;\n\n function send(signals: CapturedSignal[]) {\n if (signals.length === 0) return;\n const body: IngestBody = { key: opts.key, identity, signals };\n const json = JSON.stringify(body);\n try {\n // text/plain is a CORS-safelisted content type, so a cross-origin beacon\n // skips the preflight entirely (the host app's domain ≠ ours). The server\n // parses the text as JSON regardless.\n if (typeof navigator !== \"undefined\" && typeof navigator.sendBeacon === \"function\") {\n const blob = new Blob([json], { type: \"text/plain\" });\n const ok = navigator.sendBeacon(url, blob);\n if (ok) {\n if (opts.debug) console.debug(\"[sightspool] beacon\", signals.length);\n return;\n }\n }\n // Fallback: fetch with keepalive so it can outlive the page.\n void fetch(url, {\n method: \"POST\",\n headers: { \"Content-Type\": \"text/plain\" },\n body: json,\n keepalive: true,\n mode: \"cors\",\n credentials: \"omit\",\n }).catch(() => {\n /* swallow — drop on failure */\n });\n } catch {\n /* swallow */\n }\n }\n\n function onVisibility() {\n try {\n if (document.visibilityState === \"hidden\") flush();\n } catch {\n /* swallow */\n }\n }\n\n function flush() {\n if (queue.length === 0) return;\n const batch = queue;\n queue = [];\n send(batch);\n }\n\n return {\n start() {\n if (started || typeof window === \"undefined\") return;\n started = true;\n try {\n document.addEventListener(\"visibilitychange\", onVisibility);\n window.addEventListener(\"pagehide\", flush);\n interval = window.setInterval(flush, FLUSH_INTERVAL_MS);\n } catch {\n /* swallow */\n }\n },\n stop() {\n started = false;\n try {\n document.removeEventListener(\"visibilitychange\", onVisibility);\n window.removeEventListener(\"pagehide\", flush);\n if (interval !== null) window.clearInterval(interval);\n } catch {\n /* swallow */\n }\n flush();\n },\n enqueue(signal) {\n queue.push(signal);\n if (queue.length >= FLUSH_BATCH) flush();\n },\n flush,\n setIdentity(next) {\n identity = next;\n },\n };\n}\n","// Trigger + fatigue logic (FR-4, NFR-2) — the make-or-break craft surface.\n//\n// Kept PURE (no DOM) so it unit-tests cleanly under `node --test` and so the\n// heuristics can be tuned against real traffic later without touching the capture\n// wiring. Detection quality is the primary failure mode (false positives that\n// pester users), so the defaults are deliberately conservative.\n\nimport type { TrailEvent } from \"./types\";\n\nexport const RAGE_CLICK_COUNT = 3; // clicks…\nexport const RAGE_WINDOW_MS = 1_000; // …within this window form a rage cluster\nexport const FRICTION_RETRY_COUNT = 3; // repeated identical actions = retry frustration\nexport const FRICTION_WINDOW_MS = 8_000; // how far back a friction scan looks\n\nexport type FrictionKind = \"error\" | \"rage\" | \"dead_end\" | \"retry\";\n\n/**\n * Scan the recent trail for a friction moment. Returns the strongest kind found,\n * or null. Order = severity: a real error beats a rage cluster beats a dead-end\n * beats repeated retries.\n */\nexport function detectFriction(\n trail: TrailEvent[],\n now: number,\n windowMs = FRICTION_WINDOW_MS,\n): FrictionKind | null {\n const recent = trail.filter((e) => now - e.t <= windowMs);\n\n if (recent.some((e) => e.type === \"error\" || e.type === \"request_error\")) return \"error\";\n\n const clicks = recent.filter((e) => e.type === \"click\" || e.type === \"rage_click\");\n for (let i = 0; i < clicks.length; i++) {\n const burst = clicks.filter(\n (e) => e.t >= clicks[i].t && e.t - clicks[i].t <= RAGE_WINDOW_MS,\n );\n if (burst.length >= RAGE_CLICK_COUNT) return \"rage\";\n }\n\n if (recent.some((e) => e.type === \"dead_click\")) return \"dead_end\";\n\n const byLabel = new Map<string, number>();\n for (const e of clicks) {\n if (!e.label) continue;\n const n = (byLabel.get(e.label) ?? 0) + 1;\n byLabel.set(e.label, n);\n if (n >= FRICTION_RETRY_COUNT) return \"retry\";\n }\n\n return null;\n}\n\n// --- Fatigue caps (NFR-2): never pester. Conservative by default. ------------\n\nexport type FatigueCaps = {\n maxPromptsPerSession: number;\n cooldownMs: number; // min gap between prompts\n};\n\nexport const DEFAULT_CAPS: FatigueCaps = {\n maxPromptsPerSession: 1,\n cooldownMs: 5 * 60_000,\n};\n\nexport type FatigueState = {\n promptsShown: number;\n lastPromptAt: number | null;\n};\n\n/** May we show a prompt right now, given how many we've shown and when? */\nexport function canPrompt(\n state: FatigueState,\n now: number,\n caps: FatigueCaps = DEFAULT_CAPS,\n): boolean {\n if (state.promptsShown >= caps.maxPromptsPerSession) return false;\n if (state.lastPromptAt !== null && now - state.lastPromptAt < caps.cooldownMs) return false;\n return true;\n}\n","// Intervention serve/respond (Wave 0005 slice B — the client half). The two-way\n// SDK: besides emitting Signals, the SDK asks \"is there anything to show this user\n// here?\" (/api/sdk/serve) and posts the answer (/api/sdk/respond). Both halves are\n// wrapped — a serve/respond failure must never surface in the host app (NFR-3); the\n// worst case is simply no survey shown.\n//\n// Pure helpers (buildServeContext / normalizeServed / pickRespondentKey) are split\n// out so the contract is unit-testable without a DOM, like triggers.ts.\n\nimport type { Identity } from \"./types\";\nimport type { SurveyConfig } from \"./survey\";\nimport type { ProbeConfig } from \"./probe\";\n\nexport type ServeContext = { route?: string; account?: string; plan?: string };\n\nexport type ServedIntervention =\n | { id: string; type: \"survey\"; config: SurveyConfig }\n | { id: string; type: \"demand_probe\"; config: ProbeConfig };\n\nexport type InterventionAnswer = { choice?: string; text?: string };\n\n// Types the SDK can actually render. Mirrors the server's RENDERABLE_TYPES; if the\n// server ever serves an un-renderable type we drop it rather than show a blank.\nconst RENDERABLE = new Set([\"survey\", \"demand_probe\"]);\n\nfunction str(v: unknown, max: number): string | undefined {\n if (typeof v !== \"string\") return undefined;\n const t = v.trim();\n return t ? t.slice(0, max) : undefined;\n}\n\n/** The serve context from the current route + the identified account/plan. Only\n * defined fields are included (an absent field = unconstrained on the server). */\nexport function buildServeContext(\n route: string | undefined,\n identity: Identity | undefined,\n): ServeContext {\n const ctx: ServeContext = {};\n const r = str(route, 500);\n if (r) ctx.route = r;\n const account = str(identity?.account, 200);\n if (account) ctx.account = account;\n const plan = str(identity?.plan, 80);\n if (plan) ctx.plan = plan;\n return ctx;\n}\n\n/** Validate + normalise what /serve returned — never trust the wire blindly. Returns\n * a clean ServedIntervention or null (unknown shape / un-renderable type /\n * incomplete config). */\nexport function normalizeServed(raw: unknown): ServedIntervention | null {\n if (!raw || typeof raw !== \"object\") return null;\n const r = raw as Record<string, unknown>;\n const id = str(r.id, 64);\n const type = str(r.type, 40);\n if (!id || !type || !RENDERABLE.has(type)) return null;\n\n const cfg =\n r.config && typeof r.config === \"object\" ? (r.config as Record<string, unknown>) : {};\n\n if (type === \"demand_probe\") {\n // The honest painted door: label = the feature as the user would want it;\n // disclosure = the fixed \"this doesn't exist yet\" copy the server always\n // injects. If the disclosure is missing we DROP the probe rather than\n // render an undisclosed fake door — the client-side belt to the server's\n // braces. `slot` (optional inline placement) is re-validated as a bare\n // token so it can never smuggle a selector.\n const label = str(cfg.label, 200);\n const disclosure = str(cfg.disclosure, 300);\n if (!label || !disclosure) return null;\n const rawSlot = str(cfg.slot, 64);\n const slot = rawSlot && /^[a-z0-9][a-z0-9_-]*$/i.test(rawSlot) ? rawSlot : undefined;\n return { id, type, config: { label, disclosure, ...(slot ? { slot } : {}) } };\n }\n\n const question = str(cfg.question, 500);\n if (!question) return null;\n\n const options = Array.isArray(cfg.options)\n ? (cfg.options as unknown[])\n .map((o) => str(o, 200))\n .filter((o): o is string => !!o)\n .slice(0, 6)\n : undefined;\n\n const config: SurveyConfig = {\n question,\n ...(options && options.length ? { options } : {}),\n allow_text: cfg.allow_text === true,\n };\n return { id, type: \"survey\", config };\n}\n\n/** Stable id for serve-time de-dup (so a tapped survey doesn't reappear). The\n * identified user wins; else a persisted anon id; else the per-session ref. Pure\n * so it's testable — the localStorage read lives in getRespondentKey. */\nexport function pickRespondentKey(\n userId: string | undefined,\n persisted: string | null,\n sessionRef: string,\n): string {\n const uid = str(userId, 200);\n if (uid) return uid;\n const p = str(persisted, 200);\n if (p) return p;\n return sessionRef;\n}\n\nconst RK_STORAGE_KEY = \"sightspool_rk\";\n\n/** Resolve the respondent key, persisting an anonymous one in localStorage so\n * de-dup survives reloads. Falls back to the session ref if storage is blocked. */\nexport function getRespondentKey(\n identity: Identity | undefined,\n sessionRef: string,\n): string {\n const uid = str(identity?.userId, 200);\n if (uid) return uid;\n try {\n let v = localStorage.getItem(RK_STORAGE_KEY);\n if (!v) {\n v = \"anon-\" + Math.random().toString(36).slice(2) + Date.now().toString(36);\n localStorage.setItem(RK_STORAGE_KEY, v);\n }\n return pickRespondentKey(undefined, v, sessionRef);\n } catch {\n return sessionRef;\n }\n}\n\nfunction serveUrl(endpoint: string, path: string): string {\n return `${endpoint.replace(/\\/+$/, \"\")}/api/sdk/${path}`;\n}\n\n/** Ask the serve endpoint for an intervention to show, or null. Uses a text/plain\n * POST (CORS-safelisted → no preflight) and reads the JSON response (the serve\n * route sets Access-Control-Allow-Origin). */\nexport async function fetchIntervention(opts: {\n endpoint: string;\n key: string;\n ctx: ServeContext;\n respondentKey: string;\n debug?: boolean;\n}): Promise<ServedIntervention | null> {\n try {\n if (typeof fetch !== \"function\") return null;\n const res = await fetch(serveUrl(opts.endpoint, \"serve\"), {\n method: \"POST\",\n headers: { \"Content-Type\": \"text/plain\" },\n body: JSON.stringify({\n key: opts.key,\n context: opts.ctx,\n respondent_key: opts.respondentKey,\n }),\n mode: \"cors\",\n credentials: \"omit\",\n });\n if (!res.ok) return null;\n const data = (await res.json()) as { intervention?: unknown };\n const served = normalizeServed(data?.intervention);\n if (opts.debug) console.debug(\"[sightspool] serve\", served?.id ?? \"(none)\");\n return served;\n } catch {\n return null;\n }\n}\n\n/** Post a user's answer. Fire-and-forget (sendBeacon, fetch+keepalive fallback) —\n * the response is a 204 we don't need to read. */\nexport function submitResponse(opts: {\n endpoint: string;\n key: string;\n interventionId: string;\n response: InterventionAnswer;\n respondentKey: string;\n}): void {\n try {\n const url = serveUrl(opts.endpoint, \"respond\");\n const json = JSON.stringify({\n key: opts.key,\n intervention_id: opts.interventionId,\n response: opts.response,\n respondent_key: opts.respondentKey,\n });\n if (typeof navigator !== \"undefined\" && typeof navigator.sendBeacon === \"function\") {\n const blob = new Blob([json], { type: \"text/plain\" });\n if (navigator.sendBeacon(url, blob)) return;\n }\n if (typeof fetch === \"function\") {\n void fetch(url, {\n method: \"POST\",\n headers: { \"Content-Type\": \"text/plain\" },\n body: json,\n keepalive: true,\n mode: \"cors\",\n credentials: \"omit\",\n }).catch(() => {\n /* swallow */\n });\n }\n } catch {\n /* swallow */\n }\n}\n","// Environment guards. Kept pure (a hostname string in, a boolean out) so the\n// no-op-on-localhost decision is unit-testable without a DOM.\n\nconst LOCAL_HOSTS = new Set([\"localhost\", \"127.0.0.1\", \"0.0.0.0\", \"::1\", \"\"]);\n\n/**\n * Is this a local-development hostname? Capture is suppressed on these by default so\n * a client's `npm run dev` traffic never pollutes their Sightspool workspace (override\n * with `captureOnLocalhost: true`). Covers the common dev hosts + the `.local` /\n * `.localhost` TLDs (e.g. `myapp.local`, `app.localhost`).\n */\nexport function isLocalhost(hostname: string | null | undefined): boolean {\n const h = (hostname ?? \"\").trim().toLowerCase();\n if (LOCAL_HOSTS.has(h)) return true;\n return h.endsWith(\".local\") || h.endsWith(\".localhost\");\n}\n","// @sightspool/sdk — the in-product capture runtime (public surface).\n//\n// Ties the pieces together: passive capture + intent harvest feed a conservative\n// trigger engine; on a friction moment or a session boundary we (fatigue\n// permitting) show the one-tap prompt, then emit one Signal via batched sendBeacon.\n// Every public method is wrapped — the SDK must never throw into the host (NFR-3).\n\nimport type { SightspoolConfig, Identity, CapturedSignal } from \"./types\";\nimport { createCapture, type CaptureHandle } from \"./capture\";\nimport { createHarvest, type HarvestHandle } from \"./harvest\";\nimport { createEgress, type EgressHandle } from \"./egress\";\nimport {\n detectFriction,\n canPrompt,\n DEFAULT_CAPS,\n type FatigueState,\n} from \"./triggers\";\nimport {\n buildServeContext,\n fetchIntervention,\n submitResponse,\n getRespondentKey,\n} from \"./intervention\";\nimport { isLocalhost } from \"./env\";\n\nexport type { SightspoolConfig, Identity } from \"./types\";\n\nconst DEFAULT_ENDPOINT = \"https://www.sightspool.com\";\nconst FRICTION_EMIT_COOLDOWN_MS = 30_000;\nconst EVENT_DEBOUNCE_MS = 600;\n// Let the page settle before the first serve check (don't race the initial render).\nconst SERVE_SETTLE_MS = 2_500;\n// Conservative client cap; the server also de-dups (answered) + targets + bounds by\n// response_target, so this just stops a dismissed survey re-nagging within a session.\nconst MAX_INTERVENTIONS_PER_SESSION = 1;\n\ntype Controller = {\n config: Required<Pick<SightspoolConfig, \"key\" | \"endpoint\" | \"boundaryAsk\" | \"debug\">> &\n SightspoolConfig;\n capture: CaptureHandle;\n harvest: HarvestHandle;\n egress: EgressHandle;\n identity: Identity;\n sessionRef: string;\n fatigue: FatigueState;\n lastFrictionEmitAt: number;\n eventTimer: number | null;\n running: boolean;\n /** Environmental kill-switch: on localhost without `captureOnLocalhost`, never start. */\n suppressed: boolean;\n // --- interventions (slice B serve loop) ---\n interventionsEnabled: boolean;\n lastServeRoute: string | null; // re-check serve when the route changes\n surveyOnScreen: boolean;\n interventionsShown: number;\n};\n\nfunction currentHostname(): string {\n try {\n return typeof location !== \"undefined\" ? location.hostname : \"\";\n } catch {\n return \"\";\n }\n}\n\nlet ctrl: Controller | null = null;\n\nfunction uuid(): string {\n try {\n if (typeof crypto !== \"undefined\" && typeof crypto.randomUUID === \"function\") {\n return crypto.randomUUID();\n }\n } catch {\n /* fall through */\n }\n return \"s-\" + Math.random().toString(36).slice(2) + Date.now().toString(36);\n}\n\n// Locally-derived candidate goals for State B (FR-5). v1 leans on harvested intent\n// (a recent search) + the page label; server-LLM enrichment is a follow-up.\nfunction deriveCandidates(c: Controller): string[] {\n const out: string[] = [];\n const hint = c.harvest.lastIntentHint();\n if (hint) out.push(`Searching for “${hint}”`);\n const label = c.capture.label();\n if (label) out.push(`Something on “${label.slice(0, 40)}”`);\n return out;\n}\n\nfunction buildSignal(\n c: Controller,\n trigger: \"boundary\" | \"friction\",\n extra: Partial<CapturedSignal> = {},\n): CapturedSignal {\n const err = c.capture.error();\n return {\n captured_at: new Date().toISOString(),\n route: c.capture.route(),\n client_label: c.capture.label(),\n trail: c.capture.trail(),\n session_ref: c.sessionRef,\n trigger,\n intent_hint: c.harvest.lastIntentHint(),\n error: err,\n outcome: err || trigger === \"friction\" ? \"failed\" : \"unknown\",\n ...extra,\n };\n}\n\nasync function maybePrompt(c: Controller, trigger: \"boundary\" | \"friction\") {\n const now = Date.now();\n if (canPrompt(c.fatigue, now, DEFAULT_CAPS)) {\n c.fatigue.promptsShown += 1;\n c.fatigue.lastPromptAt = now;\n try {\n const { showPrompt } = await import(\"./prompt\");\n const result = await showPrompt({ candidates: deriveCandidates(c) });\n c.egress.enqueue(\n buildSignal(c, trigger, {\n answer: result.answer,\n verbatim: result.verbatim,\n intent_hint: result.intent ?? c.harvest.lastIntentHint(),\n outcome: result.answer === \"yes\" ? \"achieved\" : \"failed\",\n }),\n );\n } catch {\n // Prompt failed to load/show — still emit the passive Signal (FR-7).\n c.egress.enqueue(buildSignal(c, trigger));\n }\n } else {\n // Fatigued: keep the silent-capture property — emit without asking (FR-7).\n c.egress.enqueue(buildSignal(c, trigger));\n }\n}\n\n// Ask the serve endpoint whether there's a human-approved survey to show this user\n// here, and if so render it + post the answer. Server-gated (targeting, approval,\n// de-dup, response_target); the client guards are just \"don't pester\": one on\n// screen at a time, a per-session cap, and the shared prompt cooldown so a survey\n// and the passive ask never stack back-to-back.\nasync function maybeServeIntervention(c: Controller) {\n if (!c.running || !c.interventionsEnabled || c.suppressed) return;\n if (c.surveyOnScreen) return;\n if (c.interventionsShown >= MAX_INTERVENTIONS_PER_SESSION) return;\n const now = Date.now();\n if (c.fatigue.lastPromptAt !== null && now - c.fatigue.lastPromptAt < DEFAULT_CAPS.cooldownMs)\n return;\n\n const respondentKey = getRespondentKey(c.identity, c.sessionRef);\n const served = await fetchIntervention({\n endpoint: c.config.endpoint,\n key: c.config.key,\n ctx: buildServeContext(c.capture.route(), c.identity),\n respondentKey,\n debug: c.config.debug,\n });\n if (!served || !c.running) return;\n\n const prevShown = c.interventionsShown;\n const prevPromptAt = c.fatigue.lastPromptAt;\n c.surveyOnScreen = true;\n c.interventionsShown += 1;\n c.fatigue.lastPromptAt = Date.now(); // share the cooldown with the passive prompt\n try {\n if (served.type === \"demand_probe\") {\n // The honest painted door: a vote is recorded as choice \"vote\"; the\n // widget always shows the server's fixed disclosure after the click.\n const { showProbe } = await import(\"./probe\");\n const result = await showProbe(served.config);\n if (!result.mounted) {\n // A slot probe whose anchor isn't on this page rendered NOTHING —\n // give the session its fatigue budget back so a real prompt can\n // still show later (and the probe can retry on another route).\n c.interventionsShown = prevShown;\n c.fatigue.lastPromptAt = prevPromptAt;\n } else if (result.voted) {\n submitResponse({\n endpoint: c.config.endpoint,\n key: c.config.key,\n interventionId: served.id,\n response: { choice: \"vote\" },\n respondentKey,\n });\n }\n } else {\n const { showSurvey } = await import(\"./survey\");\n const result = await showSurvey(served.config);\n if (!result.dismissed && (result.choice || result.text)) {\n submitResponse({\n endpoint: c.config.endpoint,\n key: c.config.key,\n interventionId: served.id,\n response: { choice: result.choice, text: result.text },\n respondentKey,\n });\n }\n }\n } catch {\n /* swallow — a render/import failure must not surface in the host */\n } finally {\n c.surveyOnScreen = false;\n }\n}\n\nfunction onCaptureEvent() {\n const c = ctrl;\n if (!c || !c.running) return;\n\n // Re-check for a servable intervention when the route changes (SPA navigation).\n try {\n const route = c.capture.route();\n if (route && route !== c.lastServeRoute) {\n c.lastServeRoute = route;\n void maybeServeIntervention(c);\n }\n } catch {\n /* swallow */\n }\n\n if (c.eventTimer !== null) return; // debounce a burst of events into one check\n c.eventTimer = (typeof window !== \"undefined\" ? window.setTimeout : setTimeout)(() => {\n c.eventTimer = null;\n try {\n const now = Date.now();\n if (now - c.lastFrictionEmitAt < FRICTION_EMIT_COOLDOWN_MS) return;\n const kind = detectFriction(c.capture.trail(), now);\n if (!kind) return;\n c.lastFrictionEmitAt = now;\n void maybePrompt(c, \"friction\");\n } catch {\n /* swallow */\n }\n }, EVENT_DEBOUNCE_MS) as unknown as number;\n}\n\nfunction onExitIntent(ev: MouseEvent) {\n const c = ctrl;\n if (!c || !c.running || !c.config.boundaryAsk) return;\n try {\n if (ev.clientY <= 0) void maybePrompt(c, \"boundary\");\n } catch {\n /* swallow */\n }\n}\n\nfunction startRuntime(c: Controller) {\n if (c.running) return;\n if (c.suppressed) {\n if (c.config.debug)\n console.debug(\n \"[sightspool] capture suppressed on localhost (set captureOnLocalhost:true to override)\",\n );\n return;\n }\n c.running = true;\n c.capture.start();\n c.harvest.start();\n c.egress.start();\n c.capture.onEvent(onCaptureEvent);\n try {\n document.addEventListener(\"mouseout\", onExitIntent);\n } catch {\n /* swallow */\n }\n // First serve check once the page has settled (route-change checks happen in\n // onCaptureEvent thereafter).\n if (c.interventionsEnabled) {\n c.lastServeRoute = (() => {\n try {\n return c.capture.route();\n } catch {\n return null;\n }\n })();\n (typeof window !== \"undefined\" ? window.setTimeout : setTimeout)(() => {\n void maybeServeIntervention(c);\n }, SERVE_SETTLE_MS);\n }\n if (c.config.debug) console.debug(\"[sightspool] started\", c.sessionRef);\n}\n\n// --- public API --------------------------------------------------------------\n\nexport function init(config: SightspoolConfig): void {\n try {\n if (!config || !config.key) {\n console.warn(\"[sightspool] init: a `key` is required\");\n return;\n }\n if (ctrl) return; // already initialised\n const endpoint = config.endpoint || DEFAULT_ENDPOINT;\n const privacyOpts = { redact: config.redact, block: config.block };\n const capture = createCapture({ debug: !!config.debug, ...privacyOpts });\n const harvest = createHarvest(capture, { debug: !!config.debug, ...privacyOpts });\n const egress = createEgress({ key: config.key, endpoint, debug: !!config.debug });\n ctrl = {\n config: {\n ...config,\n key: config.key,\n endpoint,\n boundaryAsk: config.boundaryAsk !== false,\n debug: !!config.debug,\n },\n capture,\n harvest,\n egress,\n identity: {},\n sessionRef: uuid(),\n fatigue: { promptsShown: 0, lastPromptAt: null },\n lastFrictionEmitAt: 0,\n eventTimer: null,\n running: false,\n suppressed: isLocalhost(currentHostname()) && config.captureOnLocalhost !== true,\n interventionsEnabled: config.interventions !== false,\n lastServeRoute: null,\n surveyOnScreen: false,\n interventionsShown: 0,\n };\n if (config.consent !== false) startRuntime(ctrl);\n } catch (err) {\n // init itself must never throw into the host.\n try {\n console.warn(\"[sightspool] init failed\", err);\n } catch {\n /* swallow */\n }\n }\n}\n\nexport function identify(userId: string, traits?: { account?: string; plan?: string }): void {\n try {\n if (!ctrl) return;\n ctrl.identity = { userId, account: traits?.account, plan: traits?.plan };\n ctrl.egress.setIdentity(ctrl.identity);\n } catch {\n /* swallow */\n }\n}\n\n/** Begin capture if init was called with { consent: false }. */\nexport function start(): void {\n try {\n if (ctrl) startRuntime(ctrl);\n } catch {\n /* swallow */\n }\n}\n\n/**\n * Runtime consent gate (a clean toggle over start()/stop()) — wire it to your cookie\n * banner: `Sightspool.consent(true)` resumes capture, `Sightspool.consent(false)`\n * pauses and flushes. Pairs with init `{ consent: false }` to stay dark until granted.\n */\nexport function consent(granted: boolean): void {\n try {\n if (!ctrl) return;\n if (granted) startRuntime(ctrl);\n else stop();\n } catch {\n /* swallow */\n }\n}\n\n/** Pause capture and flush whatever's queued. */\nexport function stop(): void {\n try {\n if (!ctrl) return;\n ctrl.running = false;\n ctrl.capture.stop();\n ctrl.harvest.stop();\n ctrl.egress.stop();\n try {\n document.removeEventListener(\"mouseout\", onExitIntent);\n } catch {\n /* swallow */\n }\n } catch {\n /* swallow */\n }\n}\n\nconst api = { init, identify, start, stop, consent };\nexport default api;\n\n// --- script-tag auto-init ----------------------------------------------------\n// The standalone <script data-sightspool-key=\"pk_…\"> install auto-boots from its\n// own tag's data attributes. (No-op for the ESM build: module scripts have no\n// document.currentScript, so bundler consumers always call init() themselves.)\ntry {\n if (typeof document !== \"undefined\") {\n // currentScript is null for async/defer/dynamically-injected scripts (e.g.\n // Next's <Script> component), so fall back to finding our tag by attribute.\n const el =\n (document.currentScript as HTMLScriptElement | null) ??\n document.querySelector<HTMLScriptElement>(\"script[data-sightspool-key]\");\n const key = el?.getAttribute(\"data-sightspool-key\");\n if (key) {\n // Default the ingest endpoint to where the bundle was served from — the app\n // serves /sdk.global.js, so a same-origin script install needs only the key.\n // An explicit data-sightspool-endpoint still wins (e.g. a CDN-hosted bundle).\n let endpoint = el?.getAttribute(\"data-sightspool-endpoint\") || undefined;\n if (!endpoint && el?.src) {\n try {\n endpoint = new URL(el.src).origin;\n } catch {\n /* keep the built-in default */\n }\n }\n // Comma-separated CSS selectors → string[] (the script-tag equivalent of the\n // init() arrays; bundler users pass arrays directly).\n const list = (attr: string): string[] | undefined => {\n const raw = el?.getAttribute(attr);\n if (!raw) return undefined;\n const out = raw\n .split(\",\")\n .map((s) => s.trim())\n .filter(Boolean);\n return out.length ? out : undefined;\n };\n init({\n key,\n endpoint,\n redact: list(\"data-sightspool-redact\"),\n block: list(\"data-sightspool-block\"),\n captureOnLocalhost: el?.hasAttribute(\"data-sightspool-capture-localhost\") || undefined,\n interventions: el?.hasAttribute(\"data-sightspool-no-interventions\") ? false : undefined,\n debug: el?.hasAttribute(\"data-sightspool-debug\") || undefined,\n });\n }\n }\n} catch {\n /* swallow */\n}\n"]}
|
|
1
|
+
{"version":3,"sources":["../src/research.ts","../src/index.ts"],"names":[],"mappings":"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","file":"index.js","sourcesContent":["export type SightspoolConfig = {\n /** Public workspace widget key from Go live (UUID, not an old pk_live key). */\n key: string;\n /** Match the approved research audience. No default that widens recruitment. */\n audience: \"all_visitors\" | \"signed_in\";\n /** Sightspool origin. Defaults to the hosted application. */\n endpoint?: string;\n};\nexport type ResearchStatus =\n | \"not_initialized\" | \"signed_out\" | \"paused\" | \"checking\"\n | \"unavailable\" | \"available\" | \"error\";\n\ntype Runtime = {\n key: string; endpoint: string; audience: SightspoolConfig[\"audience\"]; identified: boolean; paused: boolean;\n disposed: boolean; generation: number; device: string; offer: string | null;\n button: HTMLButtonElement | null; popup: Window | null;\n pending: AbortController | null; timer: number; visibility: () => void;\n status: ResearchStatus;\n};\nconst slot = Symbol.for(\"sightspool.research.runtime.v1\");\ntype Host = Window & { [slot]?: Runtime };\nconst host = (): Host | null => typeof window === \"undefined\" ? null : window as Host;\nconst current = () => host()?.[slot];\nconst eligible = (r: Runtime) => r.audience === \"all_visitors\" || r.identified;\n\nfunction remove(r: Runtime) {\n r.button?.remove(); r.button = null; r.offer = null;\n}\nfunction invalidate(r: Runtime) {\n r.generation += 1; r.pending?.abort(); r.pending = null; remove(r);\n}\nfunction status(r: Runtime, value: ResearchStatus) { r.status = value; }\n\nasync function check(r: Runtime) {\n if (r.disposed || r.paused || !eligible(r) || r.pending || document.visibilityState !== \"visible\") return;\n const generation = r.generation;\n const request = new AbortController();\n r.pending = request;\n const timeout = window.setTimeout(() => request.abort(), 10_000);\n if (!r.button) status(r, \"checking\");\n try {\n const response = await fetch(r.endpoint + \"/widget-offer\", {\n method: \"POST\", credentials: \"omit\", cache: \"no-store\", referrerPolicy: \"no-referrer\",\n headers: { \"Content-Type\": \"application/json\" },\n body: JSON.stringify({ operation: \"offer\", key: r.key, device: r.device }),\n signal: request.signal,\n });\n if (!response.ok) throw Error(\"offer unavailable\");\n const result = await response.json();\n if (r.disposed || generation !== r.generation || r.paused || !eligible(r)) return;\n if (result.available !== true || typeof result.offer !== \"string\" || !result.offer) {\n remove(r); status(r, \"unavailable\"); return;\n }\n r.offer = result.offer;\n status(r, \"available\");\n if (r.button) return;\n const button = document.createElement(\"button\");\n button.type = \"button\";\n button.textContent = \"Talk to the founder · 5 min\";\n button.setAttribute(\"aria-label\", \"Sightspool: join a five-minute user interview\");\n button.style.cssText = \"position:fixed;bottom:20px;right:20px;z-index:2147483000;padding:14px 18px;border:0;border-radius:16px;background:#171717;color:white;font:500 14px system-ui;box-shadow:0 8px 30px #0003;cursor:pointer;max-width:calc(100vw - 40px)\";\n button.onclick = () => {\n try {\n if (r.disposed || r.paused || !eligible(r) || !r.offer) return;\n if (r.popup && !r.popup.closed) { r.popup.focus(); return; }\n const hash = new URLSearchParams({ offer: r.offer, device: r.device });\n r.popup = window.open(r.endpoint + \"/interview-widget#\" + hash, \"sightspool-interview\", \"popup,width=520,height=760\");\n } catch { /* Host pages remain usable if popups are blocked. */ }\n };\n r.button = button;\n document.body.appendChild(button);\n } catch {\n if (!r.disposed && generation === r.generation) { remove(r); status(r, \"error\"); }\n } finally {\n window.clearTimeout(timeout);\n if (r.pending === request) r.pending = null;\n }\n}\n\n/** Start research for the chosen audience. Signed-in-only waits for identify(). */\nexport function init(config: SightspoolConfig): void {\n try {\n const browser = host();\n if (!browser || !config || !/^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i.test(config.key)) return;\n if (config.audience !== \"all_visitors\" && config.audience !== \"signed_in\") return;\n const url = new URL(config.endpoint || \"https://www.sightspool.com\");\n if (url.protocol !== \"https:\" && !(url.protocol === \"http:\" && [\"localhost\", \"127.0.0.1\", \"[::1]\"].includes(url.hostname))) return;\n if (url.username || url.password) return;\n const previous = current();\n if (previous && previous.key === config.key && previous.endpoint === url.origin && previous.audience === config.audience) return;\n if (previous) destroy();\n let device = \"\";\n try { device = sessionStorage.getItem(\"sightspool-widget-device:\" + config.key) || \"\"; } catch {}\n if (!/^ss_fcd_[A-Za-z0-9_-]{43}$/.test(device)) {\n const bytes = crypto.getRandomValues(new Uint8Array(32));\n device = \"ss_fcd_\" + btoa(String.fromCharCode(...bytes)).replaceAll(\"+\", \"-\").replaceAll(\"/\", \"_\").replace(/=+$/, \"\");\n try { sessionStorage.setItem(\"sightspool-widget-device:\" + config.key, device); } catch {}\n }\n const r: Runtime = {\n key: config.key, endpoint: url.origin, audience: config.audience, identified: false, paused: false,\n disposed: false, generation: 0, device, offer: null, button: null,\n popup: null, pending: null, timer: 0, visibility: () => {}, status: \"signed_out\",\n };\n browser[slot] = r;\n r.visibility = () => {\n try {\n if (document.visibilityState === \"visible\") void check(r);\n else { invalidate(r); status(r, r.paused ? \"paused\" : eligible(r) ? \"unavailable\" : \"signed_out\"); }\n } catch {}\n };\n document.addEventListener(\"visibilitychange\", r.visibility);\n r.timer = window.setInterval(() => { void check(r); }, 15_000);\n if (eligible(r)) void check(r);\n } catch { /* Never throw into the host application. */ }\n}\n\n/** Only the presence of an ID is retained. The ID itself is never stored or sent. */\nexport function identify(userId: string | null | undefined): void {\n try {\n const r = current();\n if (!r) return;\n const identified = typeof userId === \"string\" && userId.trim().length > 0;\n if (!identified && !r.identified) { if (!r.paused && eligible(r)) void check(r); return; }\n invalidate(r);\n r.identified = identified;\n status(r, r.paused ? \"paused\" : eligible(r) ? \"unavailable\" : \"signed_out\");\n if (eligible(r) && !r.paused) void check(r);\n } catch {}\n}\nexport function pause(): void {\n try { const r = current(); if (r) { r.paused = true; invalidate(r); status(r, \"paused\"); } } catch {}\n}\nexport function resume(): void {\n try { const r = current(); if (r) { r.paused = false; if (!eligible(r)) status(r, \"signed_out\"); void check(r); } } catch {}\n}\n/** Stop recruitment and remove listeners/UI. Does not end an already opened interview. */\nexport function destroy(): void {\n try {\n const r = current();\n if (!r) return;\n r.disposed = true; invalidate(r);\n window.clearInterval(r.timer);\n document.removeEventListener(\"visibilitychange\", r.visibility);\n delete host()![slot];\n } catch {}\n}\nexport function getStatus(): ResearchStatus {\n try { return current()?.status ?? \"not_initialized\"; } catch { return \"error\"; }\n}\n","// Research is the public SDK. The former capture engine is parked.\nexport { init, identify, pause, resume, destroy, getStatus } from \"./research\";\nexport type { SightspoolConfig, ResearchStatus } from \"./research\";\nimport { init, identify, pause, resume, destroy, getStatus } from \"./research\";\nexport default { init, identify, pause, resume, destroy, getStatus };\n"]}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
{
|
|
2
|
+
"schemaVersion": 1,
|
|
3
|
+
"package": "@sightspool/sdk",
|
|
4
|
+
"version": "0.4.0",
|
|
5
|
+
"sourceCommit": "7b10230d4b59aedbdac0266aef4f4df88d574509",
|
|
6
|
+
"sourceDirty": false,
|
|
7
|
+
"artifactId": "781ab339e13fe18b86b56cc9d84dd308bebf6482a885c8aae46a8b3b84801f6e",
|
|
8
|
+
"bundle": {
|
|
9
|
+
"file": "sdk.global.js",
|
|
10
|
+
"path": "releases/0.4.0/781ab339e13fe18b86b56cc9d84dd308bebf6482a885c8aae46a8b3b84801f6e/sdk.global.js",
|
|
11
|
+
"sha256": "ed80800d20ddd91aebde61c355bb15918c0c5cbd712b91e13604795f2d2a8aa9",
|
|
12
|
+
"integrity": "sha384-kfq0QJNOieKKBsyznFRRW9kAaC5fcXvDzu56zgNsSzbXCVw2aReY66mlq8Fldy6K",
|
|
13
|
+
"bytes": 4902,
|
|
14
|
+
"gzipBytes": 2238
|
|
15
|
+
},
|
|
16
|
+
"source": {
|
|
17
|
+
"file": "source.json",
|
|
18
|
+
"sha256": "563f39e79e11d55279cd9ddfb02e2d5c7c4cdc653b4d9f57ab6c36dc4874dfa4"
|
|
19
|
+
},
|
|
20
|
+
"runtimeDependencies": []
|
|
21
|
+
}
|
package/dist/sdk.global.js
CHANGED
|
@@ -1,60 +1,3 @@
|
|
|
1
|
-
var Sightspool=(function(exports){'use strict';var
|
|
2
|
-
|
|
3
|
-
.wrap { position: fixed; bottom: 20px; right: 20px; z-index: 2147483000;
|
|
4
|
-
width: 320px; max-width: calc(100vw - 32px); font-family: system-ui, -apple-system, sans-serif; }
|
|
5
|
-
.card { background: #fff; color: #18181b; border: 1px solid #e4e4e7; border-radius: 12px;
|
|
6
|
-
box-shadow: 0 10px 30px rgba(0,0,0,.12); padding: 16px; }
|
|
7
|
-
.q { font-size: 14px; font-weight: 600; margin: 0 0 12px; line-height: 1.35; }
|
|
8
|
-
.row { display: flex; gap: 8px; flex-wrap: wrap; }
|
|
9
|
-
button { font: inherit; font-size: 13px; cursor: pointer; border-radius: 8px; padding: 8px 12px;
|
|
10
|
-
border: 1px solid #e4e4e7; background: #fafafa; color: #18181b; }
|
|
11
|
-
button:hover { background: #f4f4f5; }
|
|
12
|
-
button.primary { background: #18181b; color: #fff; border-color: #18181b; }
|
|
13
|
-
.cand { display: block; width: 100%; text-align: left; margin-bottom: 6px; }
|
|
14
|
-
.disc { font-size: 11px; color: #71717a; margin: 12px 0 0; }
|
|
15
|
-
.x { position: absolute; top: 8px; right: 10px; border: none; background: none; font-size: 16px;
|
|
16
|
-
color: #a1a1aa; padding: 2px 6px; }
|
|
17
|
-
input { font: inherit; font-size: 13px; width: 100%; box-sizing: border-box; padding: 8px 10px;
|
|
18
|
-
border: 1px solid #e4e4e7; border-radius: 8px; margin-bottom: 8px; }
|
|
19
|
-
`;});var re={};H(re,{showProbe:()=>Me});function Oe(e){try{return document.querySelector(`[data-sightspool-slot="${e}"]`)}catch(t){return null}}function Me(e){return new Promise(t=>{if(typeof document=="undefined"){t({dismissed:true,mounted:false});return}let n=e.slot?Oe(e.slot):null;if(e.slot&&!n){t({mounted:false});return}let o=false,r=!!n,c=document.createElement(r?"span":"div"),l=c.attachShadow({mode:"open"});function s(){try{c.remove();}catch(i){}}function u(i,a){o||(o=true,t(i),a?(y(),setTimeout(s,3200)):s());}let p=document.createElement("style");p.textContent=r?He:Pe,l.appendChild(p);let h=document.createElement(r?"span":"div");r||(h.className="wrap"),l.appendChild(h);function g(){if(h.innerHTML="",r)return h;let i=document.createElement("div");return i.className="card",h.appendChild(i),i}function f(){let i=g();if(!r){let m=document.createElement("button");m.className="x",m.textContent="\xD7",m.setAttribute("aria-label","Dismiss"),m.onclick=()=>u({dismissed:true,mounted:true},false),i.appendChild(m);}let a=document.createElement("button");a.className="probe",a.textContent=e.label,a.onclick=()=>u({voted:true,mounted:true},true),i.appendChild(a);}function y(){let i=g(),a=document.createElement("p");a.className="done",a.textContent=e.disclosure,i.appendChild(a);}try{(n!=null?n:document.body).appendChild(c),f();}catch(i){u({dismissed:true,mounted:false},false);}})}var Pe,He,ie=I(()=>{Pe=`
|
|
20
|
-
:host { all: initial; }
|
|
21
|
-
.wrap { position: fixed; bottom: 20px; right: 20px; z-index: 2147483000;
|
|
22
|
-
width: 340px; max-width: calc(100vw - 32px); font-family: system-ui, -apple-system, sans-serif; }
|
|
23
|
-
.card { position: relative; background: #fff; color: #18181b; border: 1px solid #e4e4e7;
|
|
24
|
-
border-radius: 12px; box-shadow: 0 10px 30px rgba(0,0,0,.12); padding: 16px; }
|
|
25
|
-
.probe { font: inherit; font-size: 13px; cursor: pointer; display: block; width: 100%;
|
|
26
|
-
text-align: left; border: 1px dashed #a1a1aa; border-radius: 8px; padding: 10px 12px;
|
|
27
|
-
background: #fafafa; color: #3f3f46; }
|
|
28
|
-
.probe:hover { border-color: #18181b; color: #18181b; }
|
|
29
|
-
.x { position: absolute; top: 8px; right: 10px; border: none; background: none; font-size: 16px;
|
|
30
|
-
color: #a1a1aa; padding: 2px 6px; cursor: pointer; }
|
|
31
|
-
.done { font-size: 13px; color: #18181b; margin: 0; line-height: 1.4; }
|
|
32
|
-
`,He=`
|
|
33
|
-
:host { all: initial; display: inline-block; max-width: 100%; }
|
|
34
|
-
.probe { font: inherit; font-family: system-ui, -apple-system, sans-serif; font-size: 13px;
|
|
35
|
-
cursor: pointer; display: inline-block; text-align: left; border: 1px dashed #a1a1aa;
|
|
36
|
-
border-radius: 8px; padding: 8px 12px; background: transparent; color: #52525b; }
|
|
37
|
-
.probe:hover { border-color: #18181b; color: #18181b; }
|
|
38
|
-
.done { font-family: system-ui, -apple-system, sans-serif; font-size: 13px; color: #52525b;
|
|
39
|
-
margin: 0; line-height: 1.4; border: 1px dashed #d4d4d8; border-radius: 8px; padding: 8px 12px; }
|
|
40
|
-
`;});var se={};H(se,{showSurvey:()=>qe});function qe(e){return new Promise(t=>{if(typeof document=="undefined"){t({dismissed:true});return}let n=false,o=document.createElement("div"),r=o.attachShadow({mode:"open"});function c(){try{o.remove();}catch(i){}}function l(i,a){n||(n=true,t(i),a?(y(),setTimeout(c,1100)):c());}let s=document.createElement("style");s.textContent=De,r.appendChild(s);let u=document.createElement("div");u.className="wrap",r.appendChild(u);function p(){u.innerHTML="";let i=document.createElement("div");return i.className="card",u.appendChild(i),i}function h(i){let a=document.createElement("button");a.className="x",a.textContent="\xD7",a.setAttribute("aria-label","Dismiss"),a.onclick=()=>l({dismissed:true},false),i.appendChild(a);}function g(){var m,C,S;let i=p();h(i);let a=document.createElement("p");a.className="q",a.textContent=e.question,i.appendChild(a);for(let w of ((m=e.options)!=null?m:[]).slice(0,6)){let d=document.createElement("button");d.className="opt",d.textContent=w,d.onclick=()=>l({choice:w},true),i.appendChild(d);}if(e.allow_text){let w=document.createElement("button");w.className="opt",w.textContent=((S=(C=e.options)==null?void 0:C.length)!=null?S:0)>0?"Something else\u2026":"Answer\u2026",w.onclick=f,i.appendChild(w);}}function f(){let i=p();h(i);let a=document.createElement("p");a.className="q",a.textContent=e.question,i.appendChild(a);let m=document.createElement("input");m.type="text",m.placeholder="In your own words\u2026",i.appendChild(m);let C=document.createElement("div");C.className="row";let S=document.createElement("button");S.className="primary",S.textContent="Send";let w=()=>{let d=m.value.trim();if(!d){l({dismissed:true},false);return}l({text:d},true);};S.onclick=w,m.onkeydown=d=>{d.key==="Enter"&&w();},C.appendChild(S),i.appendChild(C);try{m.focus();}catch(d){}}function y(){let i=p(),a=document.createElement("p");a.className="done",a.textContent="Thanks \u2014 that helps.",i.appendChild(a);}try{document.body.appendChild(o),g();}catch(i){l({dismissed:true},false);}})}var De,ae=I(()=>{De=`
|
|
41
|
-
:host { all: initial; }
|
|
42
|
-
.wrap { position: fixed; bottom: 20px; right: 20px; z-index: 2147483000;
|
|
43
|
-
width: 340px; max-width: calc(100vw - 32px); font-family: system-ui, -apple-system, sans-serif; }
|
|
44
|
-
.card { position: relative; background: #fff; color: #18181b; border: 1px solid #e4e4e7;
|
|
45
|
-
border-radius: 12px; box-shadow: 0 10px 30px rgba(0,0,0,.12); padding: 16px; }
|
|
46
|
-
.q { font-size: 14px; font-weight: 600; margin: 0 0 12px; line-height: 1.35; padding-right: 16px; }
|
|
47
|
-
.row { display: flex; gap: 8px; flex-wrap: wrap; }
|
|
48
|
-
button { font: inherit; font-size: 13px; cursor: pointer; border-radius: 8px; padding: 8px 12px;
|
|
49
|
-
border: 1px solid #e4e4e7; background: #fafafa; color: #18181b; }
|
|
50
|
-
button:hover { background: #f4f4f5; }
|
|
51
|
-
button.primary { background: #18181b; color: #fff; border-color: #18181b; }
|
|
52
|
-
.opt { display: block; width: 100%; text-align: left; margin-bottom: 6px; }
|
|
53
|
-
.x { position: absolute; top: 8px; right: 10px; border: none; background: none; font-size: 16px;
|
|
54
|
-
color: #a1a1aa; padding: 2px 6px; cursor: pointer; }
|
|
55
|
-
.done { font-size: 13px; color: #18181b; margin: 0; }
|
|
56
|
-
input { font: inherit; font-size: 13px; width: 100%; box-sizing: border-box; padding: 8px 10px;
|
|
57
|
-
border: 1px solid #e4e4e7; border-radius: 8px; margin-bottom: 8px; }
|
|
58
|
-
`;});R();var W=30,ve=700,we=1e3,Ee=3;function Se(){return typeof window!="undefined"&&typeof document!="undefined"}function G(e){var S,w;let t=(S=e.redact)!=null?S:[],n=(w=e.block)!=null?w:[],o=[],r,c=false,l=[],s=[],u=[];function p(){for(let d of l)try{d();}catch(x){}}function h(d,x){try{o.push({t:Date.now(),type:d,label:x?U(x):void 0}),o.length>W&&(o=o.slice(-W)),e.debug&&console.debug("[sightspool] event",d,x),p();}catch(b){}}function g(){try{return location.pathname+location.search}catch(d){return ""}}function f(){try{return document.title||""}catch(d){return ""}}function y(d){var x;try{let b=d.target;if(A(b,n))return;let _=b&&(((x=b.getAttribute)==null?void 0:x.call(b,"aria-label"))||b.textContent)||"",k=L(b,t)?K:_.trim().slice(0,60),F=Date.now();u=u.filter(P=>F-P<=we),u.push(F);let me=u.length>=Ee;h(me?"rage_click":"click",k);let he=g(),z=!1,T=null;try{T=new MutationObserver(()=>{z=!0;}),T.observe(document.body,{childList:!0,subtree:!0,attributes:!0});}catch(P){}window.setTimeout(()=>{try{T==null||T.disconnect(),!z&&g()===he&&k&&h("dead_click",k);}catch(P){}},ve);}catch(b){}}function i(d){try{r=String(d.message||"error"),h("error",r);}catch(x){}}function a(d){try{let x=d.reason;r=x instanceof Error?x.message:String(x),h("error",r);}catch(x){}}function m(){try{let d=()=>h("route",g()),x=history.pushState,b=history.replaceState;history.pushState=function(..._){let k=x.apply(this,_);return d(),k},history.replaceState=function(..._){let k=b.apply(this,_);return d(),k},window.addEventListener("popstate",d),s.push(()=>{history.pushState=x,history.replaceState=b,window.removeEventListener("popstate",d);}),h("route",g());}catch(d){}}function C(){try{if(typeof window.fetch!="function")return;let d=window.fetch.bind(window);window.fetch=async(...x)=>{try{let b=await d(...x);return b.ok||h("request_error",`HTTP ${b.status}`),b}catch(b){throw h("request_error",b instanceof Error?b.message:"network error"),b}},s.push(()=>{window.fetch=d;});}catch(d){}}return {start(){if(!(c||!Se())){c=true;try{document.addEventListener("click",y,!0),window.addEventListener("error",i),window.addEventListener("unhandledrejection",a),s.push(()=>{document.removeEventListener("click",y,!0),window.removeEventListener("error",i),window.removeEventListener("unhandledrejection",a);}),m(),C();}catch(d){}}},stop(){c=false;for(let d of s.splice(0))try{d();}catch(x){}},trail(){return o.slice()},route:g,label:f,error(){return r},onEvent(d){l.push(d);},recordSearch(d,x){let b=d.trim();b&&h(x?"zero_result":"search",b);}}}R();var Ce=/search|filter|find|query|command|lookup/i,ke=800;function _e(e){try{let t=e;if(t.type==="search")return !0;let n=e.getAttribute("role")||"";if(n==="searchbox"||n==="combobox")return !0;let o=[t.name,t.placeholder,e.getAttribute("aria-label"),e.id,e.className].filter(Boolean).join(" ");return Ce.test(o)}catch(t){return false}}function $(e,t){var u,p;let n,o=null,r=false,c=(u=t.redact)!=null?u:[],l=(p=t.block)!=null?p:[];function s(h){try{let g=h.target;if(!g||g.tagName!=="INPUT"&&g.tagName!=="TEXTAREA"||!_e(g)||A(g,l)||L(g,c))return;let f=(g.value||"").trim();if(f.length<2)return;o!==null&&window.clearTimeout(o),o=window.setTimeout(()=>{n=f,e.recordSearch(f),t.debug&&console.debug("[sightspool] harvested intent",f);},ke);}catch(g){}}return {start(){if(!(r||typeof document=="undefined")){r=true;try{document.addEventListener("input",s,!0);}catch(h){}}},stop(){r=false;try{document.removeEventListener("input",s,!0),o!==null&&window.clearTimeout(o);}catch(h){}},lastIntentHint(){return n}}}function j(e){let t=[],n,o=null,r=false,c=`${e.endpoint.replace(/\/+$/,"")}/api/sdk/ingest`;function l(p){if(p.length===0)return;let h={key:e.key,identity:n,signals:p},g=JSON.stringify(h);try{if(typeof navigator!="undefined"&&typeof navigator.sendBeacon=="function"){let f=new Blob([g],{type:"text/plain"});if(navigator.sendBeacon(c,f)){e.debug&&console.debug("[sightspool] beacon",p.length);return}}fetch(c,{method:"POST",headers:{"Content-Type":"text/plain"},body:g,keepalive:!0,mode:"cors",credentials:"omit"}).catch(()=>{});}catch(f){}}function s(){try{document.visibilityState==="hidden"&&u();}catch(p){}}function u(){if(t.length===0)return;let p=t;t=[],l(p);}return {start(){if(!(r||typeof window=="undefined")){r=true;try{document.addEventListener("visibilitychange",s),window.addEventListener("pagehide",u),o=window.setInterval(u,15e3);}catch(p){}}},stop(){r=false;try{document.removeEventListener("visibilitychange",s),window.removeEventListener("pagehide",u),o!==null&&window.clearInterval(o);}catch(p){}u();},enqueue(p){t.push(p),t.length>=10&&u();},flush:u,setIdentity(p){n=p;}}}function Y(e,t,n=8e3){var l;let o=e.filter(s=>t-s.t<=n);if(o.some(s=>s.type==="error"||s.type==="request_error"))return "error";let r=o.filter(s=>s.type==="click"||s.type==="rage_click");for(let s=0;s<r.length;s++)if(r.filter(p=>p.t>=r[s].t&&p.t-r[s].t<=1e3).length>=3)return "rage";if(o.some(s=>s.type==="dead_click"))return "dead_end";let c=new Map;for(let s of r){if(!s.label)continue;let u=((l=c.get(s.label))!=null?l:0)+1;if(c.set(s.label,u),u>=3)return "retry"}return null}var N={maxPromptsPerSession:1,cooldownMs:5*6e4};function V(e,t,n=N){return !(e.promptsShown>=n.maxPromptsPerSession||e.lastPromptAt!==null&&t-e.lastPromptAt<n.cooldownMs)}var Te=new Set(["survey","demand_probe"]);function E(e,t){if(typeof e!="string")return;let n=e.trim();return n?n.slice(0,t):void 0}function J(e,t){let n={},o=E(e,500);o&&(n.route=o);let r=E(t==null?void 0:t.account,200);r&&(n.account=r);let c=E(t==null?void 0:t.plan,80);return c&&(n.plan=c),n}function Ie(e){if(!e||typeof e!="object")return null;let t=e,n=E(t.id,64),o=E(t.type,40);if(!n||!o||!Te.has(o))return null;let r=t.config&&typeof t.config=="object"?t.config:{};if(o==="demand_probe"){let u=E(r.label,200),p=E(r.disclosure,300);if(!u||!p)return null;let h=E(r.slot,64),g=h&&/^[a-z0-9][a-z0-9_-]*$/i.test(h)?h:void 0;return {id:n,type:o,config:{label:u,disclosure:p,...g?{slot:g}:{}}}}let c=E(r.question,500);if(!c)return null;let l=Array.isArray(r.options)?r.options.map(u=>E(u,200)).filter(u=>!!u).slice(0,6):void 0,s={question:c,...l&&l.length?{options:l}:{},allow_text:r.allow_text===true};return {id:n,type:"survey",config:s}}function Ae(e,t,n){let o=E(e,200);if(o)return o;let r=E(t,200);return r||n}var X="sightspool_rk";function Z(e,t){let n=E(e==null?void 0:e.userId,200);if(n)return n;try{let o=localStorage.getItem(X);return o||(o="anon-"+Math.random().toString(36).slice(2)+Date.now().toString(36),localStorage.setItem(X,o)),Ae(void 0,o,t)}catch(o){return t}}function Q(e,t){return `${e.replace(/\/+$/,"")}/api/sdk/${t}`}async function ee(e){var t;try{if(typeof fetch!="function")return null;let n=await fetch(Q(e.endpoint,"serve"),{method:"POST",headers:{"Content-Type":"text/plain"},body:JSON.stringify({key:e.key,context:e.ctx,respondent_key:e.respondentKey}),mode:"cors",credentials:"omit"});if(!n.ok)return null;let o=await n.json(),r=Ie(o==null?void 0:o.intervention);return e.debug&&console.debug("[sightspool] serve",(t=r==null?void 0:r.id)!=null?t:"(none)"),r}catch(n){return null}}function M(e){try{let t=Q(e.endpoint,"respond"),n=JSON.stringify({key:e.key,intervention_id:e.interventionId,response:e.response,respondent_key:e.respondentKey});if(typeof navigator!="undefined"&&typeof navigator.sendBeacon=="function"){let o=new Blob([n],{type:"text/plain"});if(navigator.sendBeacon(t,o))return}typeof fetch=="function"&&fetch(t,{method:"POST",headers:{"Content-Type":"text/plain"},body:n,keepalive:!0,mode:"cors",credentials:"omit"}).catch(()=>{});}catch(t){}}var Le=new Set(["localhost","127.0.0.1","0.0.0.0","::1",""]);function te(e){let t=(e!=null?e:"").trim().toLowerCase();return Le.has(t)?true:t.endsWith(".local")||t.endsWith(".localhost")}var Fe="https://www.sightspool.com",ze=3e4,Ue=600,Be=2500,Ke=1;function We(){try{return typeof location!="undefined"?location.hostname:""}catch(e){return ""}}var v=null;function Ge(){try{if(typeof crypto!="undefined"&&typeof crypto.randomUUID=="function")return crypto.randomUUID()}catch(e){}return "s-"+Math.random().toString(36).slice(2)+Date.now().toString(36)}function $e(e){let t=[],n=e.harvest.lastIntentHint();n&&t.push(`Searching for \u201C${n}\u201D`);let o=e.capture.label();return o&&t.push(`Something on \u201C${o.slice(0,40)}\u201D`),t}function D(e,t,n={}){let o=e.capture.error();return {captured_at:new Date().toISOString(),route:e.capture.route(),client_label:e.capture.label(),trail:e.capture.trail(),session_ref:e.sessionRef,trigger:t,intent_hint:e.harvest.lastIntentHint(),error:o,outcome:o||t==="friction"?"failed":"unknown",...n}}async function de(e,t){var o;let n=Date.now();if(V(e.fatigue,n,N)){e.fatigue.promptsShown+=1,e.fatigue.lastPromptAt=n;try{let{showPrompt:r}=await Promise.resolve().then(()=>(oe(),ne)),c=await r({candidates:$e(e)});e.egress.enqueue(D(e,t,{answer:c.answer,verbatim:c.verbatim,intent_hint:(o=c.intent)!=null?o:e.harvest.lastIntentHint(),outcome:c.answer==="yes"?"achieved":"failed"}));}catch(r){e.egress.enqueue(D(e,t));}}else e.egress.enqueue(D(e,t));}async function ue(e){if(!e.running||!e.interventionsEnabled||e.suppressed||e.surveyOnScreen||e.interventionsShown>=Ke)return;let t=Date.now();if(e.fatigue.lastPromptAt!==null&&t-e.fatigue.lastPromptAt<N.cooldownMs)return;let n=Z(e.identity,e.sessionRef),o=await ee({endpoint:e.config.endpoint,key:e.config.key,ctx:J(e.capture.route(),e.identity),respondentKey:n,debug:e.config.debug});if(!o||!e.running)return;let r=e.interventionsShown,c=e.fatigue.lastPromptAt;e.surveyOnScreen=true,e.interventionsShown+=1,e.fatigue.lastPromptAt=Date.now();try{if(o.type==="demand_probe"){let{showProbe:l}=await Promise.resolve().then(()=>(ie(),re)),s=await l(o.config);s.mounted?s.voted&&M({endpoint:e.config.endpoint,key:e.config.key,interventionId:o.id,response:{choice:"vote"},respondentKey:n}):(e.interventionsShown=r,e.fatigue.lastPromptAt=c);}else {let{showSurvey:l}=await Promise.resolve().then(()=>(ae(),se)),s=await l(o.config);!s.dismissed&&(s.choice||s.text)&&M({endpoint:e.config.endpoint,key:e.config.key,interventionId:o.id,response:{choice:s.choice,text:s.text},respondentKey:n});}}catch(l){}finally{e.surveyOnScreen=false;}}function je(){let e=v;if(!(!e||!e.running)){try{let t=e.capture.route();t&&t!==e.lastServeRoute&&(e.lastServeRoute=t,ue(e));}catch(t){}e.eventTimer===null&&(e.eventTimer=(typeof window!="undefined"?window.setTimeout:setTimeout)(()=>{e.eventTimer=null;try{let t=Date.now();if(t-e.lastFrictionEmitAt<ze||!Y(e.capture.trail(),t))return;e.lastFrictionEmitAt=t,de(e,"friction");}catch(t){}},Ue));}}function le(e){let t=v;if(!(!t||!t.running||!t.config.boundaryAsk))try{e.clientY<=0&&de(t,"boundary");}catch(n){}}function q(e){if(!e.running){if(e.suppressed){e.config.debug&&console.debug("[sightspool] capture suppressed on localhost (set captureOnLocalhost:true to override)");return}e.running=true,e.capture.start(),e.harvest.start(),e.egress.start(),e.capture.onEvent(je);try{document.addEventListener("mouseout",le);}catch(t){}e.interventionsEnabled&&(e.lastServeRoute=(()=>{try{return e.capture.route()}catch(t){return null}})(),(typeof window!="undefined"?window.setTimeout:setTimeout)(()=>{ue(e);},Be)),e.config.debug&&console.debug("[sightspool] started",e.sessionRef);}}function pe(e){try{if(!e||!e.key){console.warn("[sightspool] init: a `key` is required");return}if(v)return;let t=e.endpoint||Fe,n={redact:e.redact,block:e.block},o=G({debug:!!e.debug,...n}),r=$(o,{debug:!!e.debug,...n}),c=j({key:e.key,endpoint:t,debug:!!e.debug});v={config:{...e,key:e.key,endpoint:t,boundaryAsk:e.boundaryAsk!==!1,debug:!!e.debug},capture:o,harvest:r,egress:c,identity:{},sessionRef:Ge(),fatigue:{promptsShown:0,lastPromptAt:null},lastFrictionEmitAt:0,eventTimer:null,running:!1,suppressed:te(We())&&e.captureOnLocalhost!==!0,interventionsEnabled:e.interventions!==!1,lastServeRoute:null,surveyOnScreen:!1,interventionsShown:0},e.consent!==!1&&q(v);}catch(t){try{console.warn("[sightspool] init failed",t);}catch(n){}}}function Ye(e,t){try{if(!v)return;v.identity={userId:e,account:t==null?void 0:t.account,plan:t==null?void 0:t.plan},v.egress.setIdentity(v.identity);}catch(n){}}function Ve(){try{v&&q(v);}catch(e){}}function Xe(e){try{if(!v)return;e?q(v):fe();}catch(t){}}function fe(){try{if(!v)return;v.running=!1,v.capture.stop(),v.harvest.stop(),v.egress.stop();try{document.removeEventListener("mouseout",le);}catch(e){}}catch(e){}}var Je={init:pe,identify:Ye,start:Ve,stop:fe,consent:Xe},ht=Je,ce;try{if(typeof document!="undefined"){let e=(ce=document.currentScript)!=null?ce:document.querySelector("script[data-sightspool-key]"),t=e==null?void 0:e.getAttribute("data-sightspool-key");if(t){let n=(e==null?void 0:e.getAttribute("data-sightspool-endpoint"))||void 0;if(!n&&(e!=null&&e.src))try{n=new URL(e.src).origin;}catch(r){}let o=r=>{let c=e==null?void 0:e.getAttribute(r);if(!c)return;let l=c.split(",").map(s=>s.trim()).filter(Boolean);return l.length?l:void 0};pe({key:t,endpoint:n,redact:o("data-sightspool-redact"),block:o("data-sightspool-block"),captureOnLocalhost:(e==null?void 0:e.hasAttribute("data-sightspool-capture-localhost"))||void 0,interventions:e!=null&&e.hasAttribute("data-sightspool-no-interventions")?!1:void 0,debug:(e==null?void 0:e.hasAttribute("data-sightspool-debug"))||void 0});}}}catch(e){}
|
|
59
|
-
exports.consent=Xe;exports.default=ht;exports.identify=Ye;exports.init=pe;exports.start=Ve;exports.stop=fe;Object.defineProperty(exports,'__esModule',{value:true});return exports;})({});//# sourceMappingURL=sdk.global.js.map
|
|
1
|
+
var Sightspool=(function(exports){'use strict';var y=Symbol.for("sightspool.research.runtime.v1"),v=()=>typeof window=="undefined"?null:window,l=()=>{var e;return (e=v())==null?void 0:e[y]},a=e=>e.audience==="all_visitors"||e.identified;function h(e){var t;(t=e.button)==null||t.remove(),e.button=null,e.offer=null;}function c(e){var t;e.generation+=1,(t=e.pending)==null||t.abort(),e.pending=null,h(e);}function r(e,t){e.status=t;}async function u(e){if(e.disposed||e.paused||!a(e)||e.pending||document.visibilityState!=="visible")return;let t=e.generation,i=new AbortController;e.pending=i;let d=window.setTimeout(()=>i.abort(),1e4);e.button||r(e,"checking");try{let s=await fetch(e.endpoint+"/widget-offer",{method:"POST",credentials:"omit",cache:"no-store",referrerPolicy:"no-referrer",headers:{"Content-Type":"application/json"},body:JSON.stringify({operation:"offer",key:e.key,device:e.device}),signal:i.signal});if(!s.ok)throw Error("offer unavailable");let n=await s.json();if(e.disposed||t!==e.generation||e.paused||!a(e))return;if(n.available!==!0||typeof n.offer!="string"||!n.offer){h(e),r(e,"unavailable");return}if(e.offer=n.offer,r(e,"available"),e.button)return;let o=document.createElement("button");o.type="button",o.textContent="Talk to the founder \xB7 5 min",o.setAttribute("aria-label","Sightspool: join a five-minute user interview"),o.style.cssText="position:fixed;bottom:20px;right:20px;z-index:2147483000;padding:14px 18px;border:0;border-radius:16px;background:#171717;color:white;font:500 14px system-ui;box-shadow:0 8px 30px #0003;cursor:pointer;max-width:calc(100vw - 40px)",o.onclick=()=>{try{if(e.disposed||e.paused||!a(e)||!e.offer)return;if(e.popup&&!e.popup.closed){e.popup.focus();return}let g=new URLSearchParams({offer:e.offer,device:e.device});e.popup=window.open(e.endpoint+"/interview-widget#"+g,"sightspool-interview","popup,width=520,height=760");}catch(g){}},e.button=o,document.body.appendChild(o);}catch(s){!e.disposed&&t===e.generation&&(h(e),r(e,"error"));}finally{window.clearTimeout(d),e.pending===i&&(e.pending=null);}}function m(e){try{let t=v();if(!t||!e||!/^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i.test(e.key)||e.audience!=="all_visitors"&&e.audience!=="signed_in")return;let i=new URL(e.endpoint||"https://www.sightspool.com");if(i.protocol!=="https:"&&!(i.protocol==="http:"&&["localhost","127.0.0.1","[::1]"].includes(i.hostname))||i.username||i.password)return;let d=l();if(d&&d.key===e.key&&d.endpoint===i.origin&&d.audience===e.audience)return;d&&f();let s="";try{s=sessionStorage.getItem("sightspool-widget-device:"+e.key)||"";}catch(o){}if(!/^ss_fcd_[A-Za-z0-9_-]{43}$/.test(s)){let o=crypto.getRandomValues(new Uint8Array(32));s="ss_fcd_"+btoa(String.fromCharCode(...o)).replaceAll("+","-").replaceAll("/","_").replace(/=+$/,"");try{sessionStorage.setItem("sightspool-widget-device:"+e.key,s);}catch(g){}}let n={key:e.key,endpoint:i.origin,audience:e.audience,identified:!1,paused:!1,disposed:!1,generation:0,device:s,offer:null,button:null,popup:null,pending:null,timer:0,visibility:()=>{},status:"signed_out"};t[y]=n,n.visibility=()=>{try{document.visibilityState==="visible"?u(n):(c(n),r(n,n.paused?"paused":a(n)?"unavailable":"signed_out"));}catch(o){}},document.addEventListener("visibilitychange",n.visibility),n.timer=window.setInterval(()=>{u(n);},15e3),a(n)&&u(n);}catch(t){}}function b(e){try{let t=l();if(!t)return;let i=typeof e=="string"&&e.trim().length>0;if(!i&&!t.identified){!t.paused&&a(t)&&u(t);return}c(t),t.identified=i,r(t,t.paused?"paused":a(t)?"unavailable":"signed_out"),a(t)&&!t.paused&&u(t);}catch(t){}}function w(){try{let e=l();e&&(e.paused=!0,c(e),r(e,"paused"));}catch(e){}}function x(){try{let e=l();e&&(e.paused=!1,a(e)||r(e,"signed_out"),u(e));}catch(e){}}function f(){try{let e=l();if(!e)return;e.disposed=!0,c(e),window.clearInterval(e.timer),document.removeEventListener("visibilitychange",e.visibility),delete v()[y];}catch(e){}}function S(){var e,t;try{return (t=(e=l())==null?void 0:e.status)!=null?t:"not_initialized"}catch(i){return "error"}}var p={init:m,identify:b,pause:w,resume:x,destroy:f,getStatus:S};var A=p;try{let e=document.currentScript,t=(e==null?void 0:e.dataset.sightspoolKey)||(e==null?void 0:e.dataset.key),i=e==null?void 0:e.dataset.sightspoolAudience;t&&(i==="all_visitors"||i==="signed_in")&&(p.init({key:t,audience:i,endpoint:(e==null?void 0:e.dataset.sightspoolEndpoint)||new URL(e.src).origin}),e!=null&&e.dataset.userId&&p.identify(e.dataset.userId)),window.SightspoolResearch=p,Promise.resolve().then(()=>window.dispatchEvent(new Event("sightspool:ready")));}catch(e){}
|
|
2
|
+
exports.default=A;exports.destroy=f;exports.getStatus=S;exports.identify=b;exports.init=m;exports.pause=w;exports.resume=x;Object.defineProperty(exports,'__esModule',{value:true});return exports;})({});//# sourceMappingURL=sdk.global.js.map
|
|
60
3
|
//# sourceMappingURL=sdk.global.js.map
|