repoburg 1.3.255 → 1.3.257

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.
Files changed (75) hide show
  1. package/daemon/dist/index.js +61 -3
  2. package/daemon/dist/staticServing.js +2 -2
  3. package/daemon/dist/tabtape/api/follow.js +174 -0
  4. package/daemon/dist/tabtape/api/http.js +221 -0
  5. package/daemon/dist/tabtape/api/record.js +149 -0
  6. package/daemon/dist/tabtape/api/router.js +519 -0
  7. package/daemon/dist/tabtape/api/router.spec.js +604 -0
  8. package/daemon/dist/tabtape/api/static.js +70 -0
  9. package/daemon/dist/tabtape/api/ws.js +166 -0
  10. package/daemon/dist/tabtape/buffer/buffer.js +347 -0
  11. package/daemon/dist/tabtape/buffer/buffer.spec.js +137 -0
  12. package/daemon/dist/tabtape/config.js +108 -0
  13. package/daemon/dist/tabtape/e2e-server.js +96 -0
  14. package/daemon/dist/tabtape/errors.js +77 -0
  15. package/daemon/dist/tabtape/export/export.js +331 -0
  16. package/daemon/dist/tabtape/export/export.spec.js +262 -0
  17. package/daemon/dist/tabtape/har/gostd.js +395 -0
  18. package/daemon/dist/tabtape/har/gostd.spec.js +139 -0
  19. package/daemon/dist/tabtape/har/har.js +582 -0
  20. package/daemon/dist/tabtape/har/har.spec.js +325 -0
  21. package/daemon/dist/tabtape/index.js +134 -0
  22. package/daemon/dist/tabtape/index.spec.js +104 -0
  23. package/daemon/dist/tabtape/lock.js +67 -0
  24. package/daemon/dist/tabtape/log.js +32 -0
  25. package/daemon/dist/tabtape/mcp/definitions.js +362 -0
  26. package/daemon/dist/tabtape/mcp/gofmt.js +227 -0
  27. package/daemon/dist/tabtape/mcp/params.js +345 -0
  28. package/daemon/dist/tabtape/mcp/params.spec.js +172 -0
  29. package/daemon/dist/tabtape/mcp/recordLink.js +122 -0
  30. package/daemon/dist/tabtape/mcp/server.js +411 -0
  31. package/daemon/dist/tabtape/mcp/server.spec.js +722 -0
  32. package/daemon/dist/tabtape/mcp/tools.js +1085 -0
  33. package/daemon/dist/tabtape/query/format.js +195 -0
  34. package/daemon/dist/tabtape/query/network.js +133 -0
  35. package/daemon/dist/tabtape/query/perf.js +93 -0
  36. package/daemon/dist/tabtape/query/query.spec.js +233 -0
  37. package/daemon/dist/tabtape/query/reader.js +602 -0
  38. package/daemon/dist/tabtape/query/types.js +274 -0
  39. package/daemon/dist/tabtape/redact.js +37 -0
  40. package/daemon/dist/tabtape/repro/lang.js +95 -0
  41. package/daemon/dist/tabtape/repro/repro.js +422 -0
  42. package/daemon/dist/tabtape/repro/repro.spec.js +210 -0
  43. package/daemon/dist/tabtape/sink.js +24 -0
  44. package/daemon/dist/tabtape/store/record.js +99 -0
  45. package/daemon/dist/tabtape/store/segment.js +267 -0
  46. package/daemon/dist/tabtape/store/store.js +846 -0
  47. package/daemon/dist/tabtape/store/store.spec.js +485 -0
  48. package/daemon/dist/tabtape/testing/querytest.js +119 -0
  49. package/daemon/dist/tabtape/testing/tmp.js +33 -0
  50. package/package.json +3 -2
  51. package/tabtape/extension/dist/background.js +8 -0
  52. package/tabtape/extension/dist/background.js.map +7 -0
  53. package/tabtape/extension/dist/bridge.js +3 -0
  54. package/tabtape/extension/dist/bridge.js.map +7 -0
  55. package/tabtape/extension/dist/icons/128.png +0 -0
  56. package/tabtape/extension/dist/icons/16.png +0 -0
  57. package/tabtape/extension/dist/icons/32.png +0 -0
  58. package/tabtape/extension/dist/icons/48.png +0 -0
  59. package/tabtape/extension/dist/manifest.json +28 -0
  60. package/tabtape/extension/dist/popup.css +62 -0
  61. package/tabtape/extension/dist/popup.html +34 -0
  62. package/tabtape/extension/dist/popup.js +4 -0
  63. package/tabtape/extension/dist/popup.js.map +7 -0
  64. package/tabtape/extension/dist/recorder.js +133 -0
  65. package/tabtape/extension/dist/recorder.js.map +1 -0
  66. package/tabtape/extension/dist/state.js +2 -0
  67. package/tabtape/extension/dist/state.js.map +1 -0
  68. package/tabtape/playwright/mcp.mjs +58 -0
  69. package/tabtape/playwright/tabtape.d.mts +37 -0
  70. package/tabtape/playwright/tabtape.mjs +146 -0
  71. package/tabtape/ui/dist/app/assets/index-Canv3Ljk.css +1 -0
  72. package/tabtape/ui/dist/app/assets/index-iWNSSrAE.js +145 -0
  73. package/tabtape/ui/dist/app/index.html +14 -0
  74. package/tabtape/ui/dist/export/viewer.css +2 -0
  75. package/tabtape/ui/dist/export/viewer.js +143 -0
@@ -0,0 +1,8 @@
1
+ var Ce=JSON.stringify,Pe=JSON.parse;var N="********",Ct=/passw(or)?d|^pwd$|^pass$/i,Z=/json|text\/|xml|javascript|ecmascript|graphql|x-www-form-urlencoded|csv|yaml/i;var _=r=>Math.round(r*10)/10;function L(r){return Ct.test(r)}function ee(r){let e=new URLSearchParams(r),t=!1;for(let n of new Set(e.keys()))L(n)&&(e.set(n,N),t=!0);return t?e.toString():r}function I(r){let e=r.indexOf("?");if(e<0)return r;let t=r.indexOf("#",e),n=r.slice(e+1,t<0?void 0:t),s=ee(n);return s===n?r:r.slice(0,e+1)+s+(t<0?"":r.slice(t))}function A(r){let e=!1;if(Array.isArray(r))for(let t of r)e=A(t)||e;else if(r&&typeof r=="object"){let t=r;for(let n of Object.keys(t)){let s=t[n];L(n)&&(typeof s=="string"||typeof s=="number")?(t[n]=N,e=!0):e=A(s)||e}}return e}var qe=/^[\w.%[\]-]+=[^&]*(&[\w.%[\]-]+=[^&]*)*$/,Pt=/multipart\/form-data/i,qt=/^--[^\r\n]{1,200}\r?\ncontent-disposition:\s*form-data/i;function Be(r,e=""){let t=r.trimStart();if(t.startsWith("{")||t.startsWith("["))try{let n=Pe(r);return A(n)?Ce(n):r}catch{return r}return Pt.test(e)||qt.test(t)?Bt(r,e):/x-www-form-urlencoded/i.test(e)||t.length<1e5&&qe.test(t)?ee(r):r}function Bt(r,e=""){let t=/boundary=(?:"([^"]+)"|([^;,\s]+))/i.exec(e),n=t?.[1]??t?.[2]??/^--([^\r\n]+)/.exec(r.trimStart())?.[1];if(!n)return r;let s=`--${n}`,i=r.split(s),o=!1;for(let d=1;d<i.length;d++){let c=i[d],a=/\r?\n\r?\n/.exec(c);if(!a)continue;let u=c.slice(0,a.index);if(/;\s*filename\*?=/i.test(u))continue;let f=/;\s*name="([^"]*)"/i.exec(u)?.[1]??/;\s*name=([^;\s]+)/i.exec(u)?.[1];if(f===void 0||!L(f))continue;let h=a.index+a[0].length,b=c.endsWith(`\r
2
+ `)?c.length-2:c.endsWith(`
3
+ `)?c.length-1:c.length;i[d]=c.slice(0,h)+N+c.slice(Math.max(h,b)),o=!0}return o?i.join(s):r}var Dt=/("([^"\\]*)"\s*:\s*)("(?:[^"\\]|\\.)*"|-?\d+(?:\.\d+)?(?:[eE][+-]?\d+)?)/g;function De(r){let e=r.trimStart();if(e.startsWith("{")||e.startsWith("["))try{let t=Pe(r);return A(t)?Ce(t):r}catch{}return/pass|pwd/i.test(r)?e.length<1e5&&qe.test(e)?ee(r):r.replace(Dt,(t,n,s)=>L(s)?`${n}"${N}"`:t):r}var W={framesPerSecond:200,dataBytesPerSecond:1e6,messageBytes:65536},O=class{constructor(e=W.framesPerSecond,t=W.dataBytesPerSecond,n=1e3){this.maxFrames=e;this.maxBytes=t;this.windowMs=n}maxFrames;maxBytes;windowMs;start=Number.NEGATIVE_INFINITY;frames=0;bytes=0;full=!1;dropped=0;admit(e){return(e-this.start>=this.windowMs||e<this.start)&&(this.start=e,this.frames=0,this.bytes=0,this.full=!1),this.frames>=this.maxFrames?(this.dropped++,!1):(this.frames++,!0)}fits(e){return this.full||this.bytes+e>this.maxBytes?(this.full=!0,!1):(this.bytes+=e,!0)}takeDropped(){let e=this.dropped;return this.dropped=0,e}};function U(r){let e=0;for(let t=0;t<r.length;t++){let n=r.charCodeAt(t);n<128?e+=1:n<2048?e+=2:Ae(r,t,n)?(e+=4,t++):e+=3}return e}function Me(r,e){let t=0;for(let n=0;n<r.length;n++){let s=r.charCodeAt(n),i=s>=2048&&Ae(r,n,s),o=s<128?1:s<2048?2:i?4:3;if(t+o>e)return{text:r.slice(0,n),bytes:t,truncated:!0};t+=o,i&&n++}return{text:r,bytes:t,truncated:!1}}function Ae(r,e,t){return t>=55296&&t<=56319&&e+1<r.length&&(r.charCodeAt(e+1)&64512)===56320}function Ne(r){let e=r.length;if(!e)return 0;let t=r.endsWith("==")?2:r.endsWith("=")?1:0;return Math.floor(e*3/4)-t}function $(r){let e=atob(r),t=new Uint8Array(e.length);for(let n=0;n<e.length;n++)t[n]=e.charCodeAt(n);return t}function te(r,e){try{return new TextDecoder(e||"utf-8").decode(r)}catch{return new TextDecoder().decode(r)}}var ne=r=>Math.round(r*10)/10;function _e(r){let{issueTime:e}=r,t=r.timing&&r.timing.requestTime>0?r.timing:void 0,n=r.responseTime??-1;if(t){let d=t.requestTime+t.receiveHeadersEnd/1e3;(n<0||n>d)&&(n=d),t.requestTime>n&&(n=t.requestTime)}let s=r.endTime??-1;r.endTime!==void 0&&(t?s=Math.max(s,n):n>s&&(n=s));let i={};n>=0&&(i.ttfb=ne(Math.max(0,(n-e)*1e3))),s>=0&&(i.duration=ne(Math.max(0,(s-e)*1e3)));let o=Mt(e,t,n,s);return o&&(i.timing=o),i}function Mt(r,e,t,n){let s=M=>M*1e3;if(!e){if(t<0)return n>=0?re({blocked:s(n-r),send:0,wait:0,receive:0}):void 0;let M=s(t-r);return re({send:0,wait:M,receive:n>=0?Math.max(s(n-r)-M,0):-1})}let i=r<e.requestTime?s(e.requestTime-r):0,o=At([e.dnsStart,e.connectStart,e.sendStart]),d=o===1/0?0:o,c=i+d,a=e.proxyEnd!==-1?e.proxyEnd-e.proxyStart:0;a>c&&(c=a);let u=e.dnsEnd>=0?e.dnsEnd:-1,f=e.dnsEnd>=0?e.dnsEnd-d:-1,h=e.sslEnd>0?e.sslEnd:-1,b=e.sslEnd>0?e.sslEnd-e.sslStart:-1,R=e.connectEnd>=0?e.connectEnd:-1,D=e.connectEnd>=0?e.connectEnd-Math.max(u,d):-1,Tt=e.sendEnd>=0?e.sendEnd:0,xt=e.sendEnd>=0?Math.max(e.sendEnd-Math.max(R,u,d),0):0,Et=Math.max(Tt,R,h,u,d,0),Ie=s(t-e.requestTime),Rt=Math.max(Ie-Et,0),It=n>=0?Math.max(s(n-e.requestTime)-Ie,0):-1;return re({blocked:c,dns:f,connect:D,ssl:b,send:xt,wait:Rt,receive:It})}function At(r){return r.reduce((e,t)=>t>=0&&t<e?t:e,1/0)}function re(r){let e={};for(let[t,n]of Object.entries(r))n!==void 0&&n>=0&&Number.isFinite(n)&&(e[t]=ne(n));return e}var Nt=1e3,_t=200,Lt=1e4,Le=5e3,Wt=new Set([101,204,205,304]),Ot=/^(data|chrome-extension|chrome|devtools):/i,Ut=new Set(["DomainMismatch","NotOnPath","PortMismatch"]),$t=new Set(["referer","location","content-location",":path"]),Ht=/multipart\/form-data/i,We="not captured: deep network mode stopped",Oe=1e4,F=class{constructor(e){this.opts=e}opts;entries=new Map;workers=new Map;clocks=new Map;building=new Set;jobs=new Set;iframes=new Set;mainFrame;httpSeq=0;wsSeq=0;lastExpiry=0;closed=!1;setMainFrame(e){this.mainFrame=e}iframeAttached(e){if(!this.closed){this.iframes.add(e);for(let t of[...this.entries.values()]){let n=t.hops.at(-1);n?.state==="open"&&n.response&&this.endWithResponse(n)}}}iframeDetached(e){this.iframes.delete(e)}addWorker(e,t){this.workers.set(e,{type:t.type,url:I(t.url)})}handle(e,t,n){if(!(this.closed||!t||typeof t!="object")&&typeof t.requestId=="string"){try{switch(e){case"Network.requestWillBeSent":this.onRequest(t,n);break;case"Network.requestWillBeSentExtraInfo":this.onRequestExtra(t);break;case"Network.responseReceived":this.onResponse(t,n);break;case"Network.responseReceivedExtraInfo":this.onResponseExtra(t);break;case"Network.requestServedFromCache":{let s=this.openHop(t.requestId);s&&(s.memoryCache=!0);break}case"Network.dataReceived":{let s=t,i=this.openHop(s.requestId);i&&typeof s.dataLength=="number"&&s.dataLength>0&&(i.dataLength+=s.dataLength);break}case"Network.loadingFinished":this.onFinished(t,n);break;case"Network.loadingFailed":this.onFailed(t);break;case"Network.webSocketCreated":this.onWsCreated(t,n);break;case"Network.webSocketWillSendHandshakeRequest":this.onWsHandshakeRequest(t,n);break;case"Network.webSocketHandshakeResponseReceived":this.onWsHandshakeResponse(t);break;case"Network.webSocketFrameSent":this.onWsFrame(t,n,"send");break;case"Network.webSocketFrameReceived":this.onWsFrame(t,n,"recv");break;case"Network.webSocketFrameError":this.onWsError(t,n);break;case"Network.webSocketClosed":this.onWsClosed(t,n);break}}catch{}this.expire()}}endSession(e,t="the worker ended"){if(this.closed)return;let n=e??"";for(let s of[...this.building])(s.entry.sessionId??"")!==n&&this.bodySession(s)!==e||(s.data&&s.awaiting.req&&(s.data.reqBodyNote=`not available: ${t}`),s.data&&s.awaiting.res&&(s.data.resBodyNote=`not available: ${t}`),this.finish(s));for(let s of[...this.entries.values()])s.sessionId===e&&this.flushEntry(s);e!==void 0&&(this.workers.delete(e),this.clocks.delete(e))}async stop(e){if(!this.closed){this.closed=!0;for(let t of[...this.entries.values()])this.flushEntry(t);if(this.jobs.size){let t;await Promise.race([Promise.all(this.jobs),new Promise(n=>t=setTimeout(n,e))]),clearTimeout(t)}for(let t of[...this.building])t.data&&t.awaiting.req&&(t.data.reqBodyNote=We),t.data&&t.awaiting.res&&(t.data.resBodyNote=We),this.finish(t);this.entries.clear()}}onRequest(e,t){let n=e.request;if(!n||typeof n.url!="string")return;this.learnClock(t,e.timestamp,e.wallTime);let s=this.entries.get(e.requestId),i=s?.hops.at(-1);if(i?.state==="open"){if(!e.redirectResponse)return;i.response=e.redirectResponse,i.responseTime=e.timestamp,i.hasExtraInfo=e.redirectHasExtraInfo,i.endTime=e.timestamp;let c=e.redirectResponse.encodedDataLength;typeof c=="number"&&c>0&&(i.encodedDataLength=c),i.redirected=!0,this.complete(i)}else s&&i&&(this.entries.delete(e.requestId),s=void 0);s??=this.newEntry(e.requestId),Ue(s,t);let o=n.url+(n.urlFragment??""),d=Ot.test(o)||!!this.opts.ignore?.({url:o,documentURL:e.documentURL});s.hops.push({entry:s,index:s.hops.length,id:d?"":`cdp-${++this.httpSeq}`,skip:d,url:o,ts:typeof e.wallTime=="number"?Math.round(e.wallTime*1e3):this.epochMs(t,e.timestamp),issueTime:e.timestamp,request:n,type:e.type,frameId:e.frameId,dataLength:0,state:"open",awaiting:{req:!1,res:!1}})}onRequestExtra(e){let t=this.entryFor(e.requestId);t.reqExtras.push({headers:e.headers,blockedCookies:jt(e.associatedCookies??e.blockedCookies)}),this.extraArrived(t.hops[t.reqExtras.length-1])}onResponseExtra(e){let t=this.entryFor(e.requestId);t.resExtras.push({headers:e.headers,status:typeof e.statusCode=="number"&&e.statusCode>0?e.statusCode:void 0,statusText:Xt(e.headersText),blockedSetCookies:zt(e.blockedCookies)}),this.extraArrived(t.hops[t.resExtras.length-1])}onResponse(e,t){let n=this.openHop(e.requestId);!n||!e.response||(n.response=e.response,n.responseTime=e.timestamp,n.hasExtraInfo=e.hasExtraInfo,n.dataSession=t??"",e.type&&(n.type=e.type),this.endWithResponse(n))}endWithResponse(e){e.type!=="Document"||e.frameId===void 0||!this.iframes.has(e.frameId)||(e.endTime=e.responseTime,this.complete(e))}onFinished(e,t){let n=this.openHop(e.requestId);n&&(n.endTime=e.timestamp,n.dataSession=t??"",typeof e.encodedDataLength=="number"&&e.encodedDataLength>0&&(n.encodedDataLength=e.encodedDataLength),this.complete(n))}onFailed(e){let t=this.openHop(e.requestId);if(!t)return;t.endTime=e.timestamp,t.error=e.errorText||(e.canceled?"canceled":"failed"),e.blockedReason&&(t.blockedReason=e.blockedReason);let n=e.corsErrorStatus;n?.corsError&&(t.corsErrorStatus=n.failedParameter?{corsError:n.corsError,failedParameter:n.failedParameter}:{corsError:n.corsError}),e.type&&(t.type=e.type),this.complete(t)}complete(e){e.state="waiting";let t=this.extraWait(e);t>0?e.timer=setTimeout(()=>this.build(e,!1),t):this.build(e,!1)}extraWait(e){let t=e.entry,n=t.reqExtras[e.index]!==void 0,s=t.resExtras[e.index]!==void 0;return e.hasExtraInfo?n&&s?0:Nt:e.corsErrorStatus&&!s?_t:0}extraArrived(e){e?.state==="waiting"&&this.extraWait(e)===0&&this.build(e,!1)}build(e,t){if(e.state==="building"||e.state==="done")return;if(clearTimeout(e.timer),e.skip){e.state="done",this.release(e);return}e.state="building";let n=this.describe(e,t);e.data=n;let s=this.opts.captureBodies?this.bodies(e,n,t):void 0;if(!s){this.finish(e);return}this.building.add(e);let i=s.catch(()=>{}).then(()=>{this.jobs.delete(i),this.finish(e)});this.jobs.add(i)}finish(e){let t=e.data;e.state!=="building"||!t||(e.state="done",e.data=void 0,this.building.delete(e),this.emit({ts:e.ts,type:"network",data:t}),this.release(e))}release(e){let t=e.entry;t.ws||t.hops.at(-1)?.redirected||!t.hops.every(n=>n.state==="done")||this.entries.get(t.requestId)===t&&this.entries.delete(t.requestId)}describe(e,t){let n=e.entry,s=n.reqExtras[e.index],i=n.resExtras[e.index],o=e.response,d=(e.type||"Other").toLowerCase(),c=this.kindOf(e),a={id:e.id,kind:c,method:e.request.method||"GET",url:I(e.url)};o?.status&&(a.status=o.status),o?.statusText&&(a.statusText=o.statusText),i?.status&&i.status!==a.status&&(a.status=i.status,i.statusText?a.statusText=i.statusText:delete a.statusText);let u=_e({issueTime:e.issueTime,timing:e.memoryCache?void 0:o?.timing,responseTime:o?e.responseTime:void 0,endTime:t?void 0:e.endTime});t?a.duration=_(Math.max(0,Date.now()-e.ts)):u.duration!==void 0&&(a.duration=u.duration),u.ttfb!==void 0&&(a.ttfb=u.ttfb);let f=H(s?.headers??o?.requestHeaders??e.request.headers);f&&(a.reqHeaders=f);let h=H(i?.headers??o?.headers);h&&(a.resHeaders=h),e.dataLength>0&&(a.resSize=e.dataLength),e.encodedDataLength&&(a.transferSize=e.encodedDataLength),o?.mimeType&&(a.mime=o.mimeType),e.error&&(a.error=e.error),t&&(a.pending=!0),c==="resource"&&(a.initiator=d),a.source="cdp",a.resourceType=d,u.timing&&(a.timing=u.timing),o?.protocol&&(a.protocol=o.protocol);let b=Ft(o);b&&(a.remoteAddress=b);let R=e.memoryCache?"memory":o?.fromDiskCache?"disk":o?.fromPrefetchCache?"prefetch":void 0;R&&(a.cache=R),o?.fromServiceWorker&&(a.fromServiceWorker=!0),o?.serviceWorkerResponseSource&&(a.swSource=o.serviceWorkerResponseSource),e.blockedReason&&(a.blockedReason=e.blockedReason),e.corsErrorStatus&&(a.corsErrorStatus=e.corsErrorStatus),s?.blockedCookies&&(a.blockedCookies=s.blockedCookies),i?.blockedSetCookies&&(a.blockedSetCookies=i.blockedSetCookies);let D=this.workerOf(n.sessionId);return D&&(a.worker=D),a}kindOf(e){switch(e.type){case"Fetch":return"fetch";case"XHR":return"xhr";case"Ping":return"beacon";case"Document":if(e.entry.sessionId===void 0&&(this.mainFrame===void 0||e.frameId===void 0||e.frameId===this.mainFrame))return"navigation"}return"resource"}bodies(e,t,n){let s=[];if(t.kind==="fetch"||t.kind==="xhr"||t.kind==="beacon"){let i=this.requestBody(e,t);i&&s.push(i)}if(!n&&(t.kind==="fetch"||t.kind==="xhr")){let i=this.responseBody(e,t);i&&s.push(i)}return s.length?Promise.all(s).then(()=>{}):void 0}requestBody(e,t){let n=e.request,s=t.reqHeaders?.["content-type"]??"";if(typeof n.postData=="string"){this.setRequestBody(t,n.postData,s);return}let i=Jt(n.postDataEntries);if(i){this.setRequestBytes(t,i,s);return}if(n.hasPostData)return e.awaiting.req=!0,He(this.opts.getRequestPostData(e.entry.sessionId,e.entry.requestId),Oe).then(o=>{e.state==="building"&&(o.base64Encoded?this.setRequestBytes(t,$(o.postData),s):this.setRequestBody(t,String(o.postData??""),s))},o=>{e.state==="building"&&(t.reqBodyNote=`not available: ${je(o)}`)}).finally(()=>{e.awaiting.req=!1})}setRequestBytes(e,t,n){n&&$e(n)?e.reqBodyNote=`binary (${n}), ${t.length} bytes`:this.setRequestBody(e,te(t),n,t.length)}setRequestBody(e,t,n,s){if(n?$e(n):/[\u0000�]/.test(t.slice(0,4096))){e.reqBodyNote=`binary${n?` (${n})`:""}, ${s??U(t)} bytes`;return}let o=Fe(Be(t,n),this.opts.maxBodyChars);e.reqBody=o.text,o.truncated&&(e.reqBodyTruncated=!0)}responseBody(e,t){let n=e.response;if(!n||e.error||e.redirected||t.method==="HEAD"||Wt.has(n.status??0))return;let s=n.mimeType??"";if(/event-stream/i.test(s)){t.resBodyNote="event stream, not captured";return}if(s&&!Z.test(s)){t.resBodyNote=`binary (${s}${t.resSize?`, ${t.resSize} bytes`:""})`;return}return e.awaiting.res=!0,He(this.opts.getResponseBody(this.bodySession(e),e.entry.requestId),Oe).then(i=>{if(e.state!=="building")return;let o=String(i.body??""),d;if(i.base64Encoded){let a=$(o);d=a.length,o=te(a,n.charset)}t.resSize??=d??U(o);let c=Fe(o,this.opts.maxBodyChars);t.resBody=c.text,c.truncated&&(t.resBodyTruncated=!0)},i=>{e.state==="building"&&(t.resBodyNote=`not available: ${je(i)}`)}).finally(()=>{e.awaiting.res=!1})}onWsCreated(e,t){if(typeof e.url!="string")return;let n=this.entryFor(e.requestId);n.ws||(Ue(n,t),n.ws={entry:n,id:`ws-${++this.wsSeq}`,url:I(e.url),seenAt:Date.now(),counts:{sent:0,received:0,sentBytes:0,receivedBytes:0},dropped:0,dataOmitted:0,limiter:new O,emitted:!1})}onWsHandshakeRequest(e,t){this.learnClock(t,e.timestamp,e.wallTime);let n=this.conn(e.requestId);n&&(typeof e.wallTime=="number"&&(n.ts=Math.round(e.wallTime*1e3)),typeof e.timestamp=="number"&&(n.t0=e.timestamp),n.handshakeHeaders=e.request?.headers)}onWsHandshakeResponse(e){let t=this.conn(e.requestId);!t||!e.response||(t.response=e.response,t.responseTime=e.timestamp)}onWsFrame(e,t,n){let s=this.conn(e.requestId);if(!s)return;let i=typeof e.response?.opcode=="number"?e.response.opcode:0,o=typeof e.response?.payloadData=="string"?e.response.payloadData:"",d=i===1,c=d?U(o):Ne(o),a=s.counts;if(n==="send"?(a.sent++,a.sentBytes+=c):(a.received++,a.receivedBytes+=c),!s.limiter.admit(typeof e.timestamp=="number"?e.timestamp*1e3:Date.now())){s.dropped++;return}let u={conn:s.id,dir:n,opcode:i,size:c};if(d){let f=Me(De(o),W.messageBytes);s.limiter.fits(f.bytes)?(u.data=f.text,f.truncated&&(u.truncated=!0)):(u.dataOmitted=!0,s.dataOmitted++)}this.emitFrame(s,u,t,e.timestamp)}onWsError(e,t){let n=this.conn(e.requestId);if(!n)return;let s=typeof e.errorMessage=="string"&&e.errorMessage?e.errorMessage:"WebSocket error";n.error??=s,this.emitFrame(n,{conn:n.id,dir:"recv",opcode:0,size:0,error:s},t,e.timestamp)}onWsClosed(e,t){let n=this.conn(e.requestId);n&&(n.closedAt=this.epochMs(t,e.timestamp),this.emitConn(n))}emitFrame(e,t,n,s){let i=e.limiter.takeDropped();i&&(t.dropped=i),this.emit({ts:this.epochMs(n,s),type:"ws",data:t})}emitConn(e){if(e.emitted)return;e.emitted=!0;let t=e.entry,n=t.reqExtras[0],s=t.resExtras[0],i=e.response,o=e.ts??e.seenAt,d={id:e.id,kind:"websocket",method:"GET",url:e.url},c=i?.status||s?.status;c&&(d.status=c);let a=i?.status?i.statusText:s?.statusText;a&&(d.statusText=a),d.duration=_(Math.max(0,(e.closedAt??Date.now())-o)),i&&e.t0!==void 0&&typeof e.responseTime=="number"&&(d.ttfb=_(Math.max(0,(e.responseTime-e.t0)*1e3)));let u=H(n?.headers??i?.requestHeaders??e.handshakeHeaders);u&&(d.reqHeaders=u);let f=H(s?.headers??i?.headers);f&&(d.resHeaders=f),e.error&&(d.error=e.error),e.closedAt===void 0&&(d.pending=!0),d.source="cdp",d.resourceType="websocket",n?.blockedCookies&&(d.blockedCookies=n.blockedCookies),s?.blockedSetCookies&&(d.blockedSetCookies=s.blockedSetCookies);let h=this.workerOf(t.sessionId);h&&(d.worker=h),e.closedAt!==void 0&&(d.closedAt=e.closedAt);let b={...e.counts};e.dropped&&(b.dropped=e.dropped),e.dataOmitted&&(b.dataOmitted=e.dataOmitted),d.frames=b,this.emit({ts:o,type:"network",data:d}),!t.hops.length&&this.entries.get(t.requestId)===t&&this.entries.delete(t.requestId)}conn(e){let t=this.entries.get(e)?.ws;return t&&!t.emitted?t:void 0}flushEntry(e){for(let t of e.hops)t.state==="open"?this.build(t,!0):t.state==="waiting"&&this.build(t,!1);e.ws&&this.emitConn(e.ws)}bodySession(e){return e.dataSession!==void 0?e.dataSession||void 0:e.entry.sessionId}openHop(e){let t=this.entries.get(e)?.hops.at(-1);return t?.state==="open"?t:void 0}entryFor(e){return this.entries.get(e)??this.newEntry(e)}newEntry(e){this.entries.size>=Le&&this.makeRoom();let t={requestId:e,hops:[],reqExtras:[],resExtras:[],seenAt:Date.now()};return this.entries.set(e,t),t}makeRoom(){let e=Date.now();for(let[t,n]of this.entries)!n.hops.length&&!n.ws&&e-n.seenAt>1e3&&this.entries.delete(t);if(!(this.entries.size<Le)){for(let t of this.entries.values())if(!t.ws){this.entries.delete(t.requestId),this.flushEntry(t);return}}}expire(){let e=Date.now();if(!(e-this.lastExpiry<1e3)){this.lastExpiry=e;for(let[t,n]of this.entries)!n.hops.length&&!n.ws&&e-n.seenAt>Lt&&this.entries.delete(t)}}workerOf(e){let t=e!==void 0?this.workers.get(e):void 0;return t?{...t}:void 0}learnClock(e,t,n){typeof t=="number"&&typeof n=="number"&&n>0&&this.clocks.set(e??"",n-t)}epochMs(e,t){let n=this.clocks.get(e??"")??this.clocks.get("");return typeof t=="number"&&n!==void 0?Math.round((t+n)*1e3):Date.now()}emit(e){try{this.opts.emit(e)}catch{}}};function Ue(r,e){e===void 0?delete r.sessionId:r.sessionId=e}function H(r){if(!r||typeof r!="object")return;let e={};for(let[t,n]of Object.entries(r)){let s=t.toLowerCase(),i=$t.has(s)?I(String(n)):String(n);e[s]=Object.hasOwn(e,s)?`${e[s]}
4
+ ${i}`:i}return Object.keys(e).length?e:void 0}function Ft(r){if(!r?.remoteIPAddress)return;let e=r.remoteIPAddress,t=e.includes(":")&&!e.startsWith("[")?`[${e}]`:e;return r.remotePort?`${t}:${r.remotePort}`:t}function ze(r){return Array.isArray(r)?r.filter(e=>typeof e=="string"):[]}function Ke(r,e,t){let n={name:r,reasons:e};return t?.domain&&(n.domain=t.domain),t?.path&&(n.path=t.path),n}function jt(r){if(!Array.isArray(r))return;let e=[];for(let t of r){let n=ze(t?.blockedReasons);!n.length||n.some(s=>Ut.has(s))||typeof t.cookie?.name!="string"||e.push(Ke(t.cookie.name,n,t.cookie))}return e.length?e:void 0}function zt(r){if(!Array.isArray(r))return;let e=[];for(let t of r){let n=ze(t?.blockedReasons);n.length&&e.push(Ke(typeof t.cookie?.name=="string"?t.cookie.name:Kt(t.cookieLine),n,t.cookie))}return e.length?e:void 0}function Kt(r){if(typeof r!="string")return"";let e=r.indexOf("="),t=r.indexOf(";");return e<0||t>=0&&t<e?"":r.slice(0,e).trim()}function Xt(r){if(typeof r=="string")return/^HTTP\/\S+[ \t]+\d{3}[ \t]+([^\r\n]+)/.exec(r)?.[1]?.trim()||void 0}function $e(r){return!Z.test(r)&&!Ht.test(r)}function Jt(r){if(!r?.length||!r.every(s=>typeof s?.bytes=="string"))return;let e=r.map(s=>$(s.bytes)),t=new Uint8Array(e.reduce((s,i)=>s+i.length,0)),n=0;for(let s of e)t.set(s,n),n+=s.length;return t}function He(r,e){let t,n=new Promise((s,i)=>t=setTimeout(()=>i(new Error("Chrome did not answer")),e));return Promise.race([r,n]).finally(()=>clearTimeout(t))}function Fe(r,e){return r.length>e?{text:r.slice(0,e),truncated:!0}:{text:r,truncated:!1}}function je(r){let e=r instanceof Error?r.message:String(r);if(!e.startsWith("{"))return e;try{let t=JSON.parse(e).message;return typeof t=="string"&&t?t:e}catch{return e}}var Yt="1.3",Xe={maxTotalBufferSize:64e6,maxResourceBufferSize:16e6,maxPostDataSize:65536},Vt={autoAttach:!0,waitForDebuggerOnStart:!0,flatten:!0},Gt=new Set(["worker","shared_worker","service_worker"]),Qt=1e3,Je=1500,Zt=1e6,se=class{constructor(e){this.opts=e;this.net=new F({captureBodies:e.captureBodies,maxBodyChars:e.maxBodyChars,emit:t=>this.push(t),getResponseBody:(t,n)=>this.send("Network.getResponseBody",{requestId:n},t),getRequestPostData:(t,n)=>this.send("Network.getRequestPostData",{requestId:n},t),ignore:e.ignore})}opts;net;ending=!1;detached=!1;lines=[];bytes=0;timer;disposed=!1;get tabId(){return this.opts.tabId}send(e,t,n){if(this.detached)return Promise.reject(new Error("deep network mode stopped"));try{let s=n?{tabId:this.tabId,sessionId:n}:{tabId:this.tabId};return t?chrome.debugger.sendCommand(s,e,t):chrome.debugger.sendCommand(s,e)}catch(s){return Promise.reject(s)}}onEvent(e,t,n){if(e==="Target.attachedToTarget")this.onAttached(t);else if(e.startsWith("Network."))this.net.handle(e,t,n);else if(e==="Target.detachedFromTarget"){let s=t;typeof s?.sessionId=="string"&&this.net.endSession(s.sessionId),typeof s?.targetId=="string"&&this.net.iframeDetached(s.targetId)}else e==="Inspector.targetCrashed"&&n===void 0&&this.net.endSession(void 0,"the page crashed")}onAttached(e){let t=e??{};if(typeof t.sessionId!="string")return;let n=t.sessionId,s=()=>{t.waitingForDebugger===!0&&this.send("Runtime.runIfWaitingForDebugger",void 0,n).catch(()=>{})},i=typeof t.targetInfo?.type=="string"?t.targetInfo.type:"";if(!Gt.has(i)||this.ending){s(),i==="iframe"&&typeof t.targetInfo?.targetId=="string"&&this.net.iframeAttached(t.targetInfo.targetId);return}this.net.addWorker(n,{type:i,url:typeof t.targetInfo?.url=="string"?t.targetInfo.url:""});let o;Promise.race([this.send("Network.enable",Xe,n),new Promise(d=>o=setTimeout(d,Qt))]).catch(()=>{}).finally(()=>{clearTimeout(o),s()})}push(e){if(this.disposed)return;let t;try{t=JSON.stringify(e)}catch{return}this.lines.push(t),this.bytes+=t.length,this.bytes>=Zt?this.flush():this.timer??=setTimeout(()=>this.flush(),this.opts.flushMs())}flush(){if(clearTimeout(this.timer),this.timer=void 0,!this.lines.length)return;let e=this.lines.join(`
5
+ `);this.lines=[],this.bytes=0;try{this.opts.post(e)}catch(t){console.warn("tabtape: deep mode lines dropped",t)}}dispose(e=!1){e||this.flush(),clearTimeout(this.timer),this.timer=void 0,this.lines=[],this.disposed=!0}},l=null,C=new Map,ie=()=>{};function x(r){C.get(r.tabId)===r&&C.delete(r.tabId)}function Ye(r){ie=r,chrome.debugger.onEvent.addListener((e,t,n)=>{let s=e.tabId!==void 0?C.get(e.tabId):void 0;if(s)try{s.onEvent(t,n,e.sessionId)}catch(i){console.warn("tabtape: deep mode event",t,i)}}),chrome.debugger.onDetach.addListener((e,t)=>{let n=e.tabId!==void 0?C.get(e.tabId):void 0;n&&(x(n),n.detached=!0,!(n.ending||n!==l)&&Promise.resolve().then(()=>ie(n.tabId,t)).catch(s=>console.warn("tabtape: deep mode end",s)))})}function oe(){return l?.tabId}async function ae(r,e=!1){await de();let t={tabId:r.tabId};e||await chrome.debugger.attach(t,Yt);let n=new se(r);l=n,C.set(r.tabId,n);try{n.net.setMainFrame(await er(n)),await n.send("Network.enable",Xe)}catch(s){throw l===n&&(l=null),n.ending=!0,n.net.stop(0),n.dispose(!0),await chrome.debugger.detach(t).catch(()=>{}),x(n),n.detached=!0,s}await n.send("Target.setAutoAttach",Vt).catch(s=>console.warn("tabtape: deep mode cannot follow workers:",s))}async function er(r){try{let e=await r.send("Page.getFrameTree");if(e?.frameTree?.frame?.id)return e.frameTree.frame.id}catch{}try{return(await chrome.debugger.getTargets()).find(e=>e.tabId===r.tabId&&e.type==="page")?.id}catch{return}}async function de(){let r=l;r&&(l=null,r.ending=!0,await r.net.stop(Je),await chrome.debugger.detach({tabId:r.tabId}).catch(()=>{}),x(r),r.detached=!0,r.dispose())}async function Ve(r){let e=l;!e||e.tabId!==r||(l=null,e.detached=!0,x(e),await e.net.stop(Je),e.dispose())}async function Ge(){let r=l;r&&(l=null,r.ending=!0,r.net.stop(0),r.dispose(!0),await chrome.debugger.detach({tabId:r.tabId}).catch(()=>{}),x(r),r.detached=!0)}async function Qe(r){let e=l;return e?(e.ending=!0,await chrome.debugger.detach({tabId:e.tabId}).catch(()=>{}),x(e),e.detached=!0,await ie(e.tabId,r),!0):!1}var Ze=/^(\*|https?|file):\/\/(\*|\*\.[^/*:]+|[^/*:]+)?(?::(\d+|\*))?(\/.*)$/;function et(r){return r==="<all_urls>"||Ze.test(r.trim())}function tr(r,e){let t;try{t=new URL(e)}catch{return!1}let n=t.protocol.slice(0,-1);if(r==="<all_urls>")return n==="http"||n==="https"||n==="file";let s=Ze.exec(r.trim());if(!s)return!1;let[,i,o="",d,c]=s;if(i==="*"?n!=="http"&&n!=="https":i!==n)return!1;if(o&&o!=="*"){if(o.startsWith("*.")){let a=o.slice(2).toLowerCase();if(t.hostname!==a&&!t.hostname.endsWith(`.${a}`))return!1}else if(t.hostname!==o.toLowerCase())return!1}return d&&d!=="*"&&(t.port||(n==="https"?"443":"80"))!==d?!1:nr(c,t.pathname+t.search)}function ce(r,e){return r.some(t=>tr(t,e))}function ue(r){return!r||!/^(https?|file):/.test(r)?!1:!/^https:\/\/(chromewebstore\.google\.com|chrome\.google\.com\/webstore)/.test(r)}var rr=new Set(["localhost","127.0.0.1","[::1]"]);function w(r,e){if(!r||!e)return!1;let t,n;try{t=new URL(r),n=new URL(e)}catch{return!1}if(t.protocol!==n.protocol)return!1;let s=c=>c.port||(c.protocol==="https:"?"443":"80"),i=c=>rr.has(c.hostname)?"loopback":c.hostname;if(s(t)!==s(n)||i(t)!==i(n))return!1;let o=fe(n).toLowerCase(),d=t.pathname.toLowerCase();return!o||d===o||d.startsWith(`${o}/`)}function fe(r){return r.pathname.replace(/\/+$/,"")}function nr(r,e){return new RegExp(`^${r.split("*").map(sr).join(".*")}$`).test(e)}function sr(r){return r.replace(/[.+?^${}()|[\]\\]/g,"\\$&")}var ir=200;function tt(r,e){if(!r||!e||!w(r,e))return null;let t=new URL(r),n=t.searchParams.get("token");if(!n)return null;let s=`${fe(new URL(e))}/record`;return t.pathname===`${s}/stop`?{action:"stop",token:n}:t.pathname!==s?null:{action:"start",token:n,name:le(t.searchParams.get("name")),url:t.searchParams.get("url")?.trim()||void 0}}function le(r){return typeof r=="string"&&r.trim().slice(0,ir)||void 0}var j={normal:1e3,live:250},rt={serverUrl:"http://127.0.0.1:9998/tabtape",captureBodies:!0,checkoutMinutes:5,bufferEnabled:!1,bufferSites:["http://localhost/*","http://127.0.0.1/*"],bufferMinutes:2,startWithBuffer:!0,recordState:!0},or="http://127.0.0.1:7777";function nt(r){let e={...rt,...r},t=typeof e.serverUrl=="string"?e.serverUrl.trim().replace(/\/+$/,""):"";return e.serverUrl=!t||t===or?rt.serverUrl:t,e}var me={min:1,max:10};function st(r){return Math.min(Math.max(r/4,15e3),6e4)}var z=1e6;var be=["tabtape-bridge","tabtape-recorder"];function ar(r){let e={matches:["<all_urls>"],runAt:"document_start",allFrames:!1,persistAcrossSessions:!1};return[{...e,id:be[0],js:["bridge.js"],world:"ISOLATED"},{...e,id:be[1],js:ve(r),world:"MAIN"}]}function ve(r){return r.recordState?["state.js","recorder.js"]:["recorder.js"]}var ge=["tabtape-buffer-bridge","tabtape-buffer-recorder"],we={rec:"#e5484d",buf:"#71717a"},dr=5e7,cr=5e3,at=/^[A-Za-z0-9][A-Za-z0-9_-]{0,63}$/;async function g(){let{recording:r}=await chrome.storage.session.get("recording");return r??null}async function q(r){r?await chrome.storage.session.set({recording:r}):await chrome.storage.session.remove("recording")}async function p(){let{settings:r}=await chrome.storage.local.get("settings"),e=nt(r);return e.bufferMinutes=Math.min(Math.max(Math.round(e.bufferMinutes)||2,me.min),me.max),e.bufferSites=e.bufferSites.filter(et),e}async function T(){let{bufferTabs:r}=await chrome.storage.session.get("bufferTabs");return r??{}}var it=Promise.resolve();function Se(r){let e=it.then(async()=>{let t=await T(),n=r(t);return await chrome.storage.session.set({bufferTabs:t}),n});return it=e.catch(()=>{}),e}var J=class extends Error{constructor(t,n){super(n);this.status=t}status},S=[],P=0,X=null,v={lines:0,bytes:0,dropped:0,lastError:void 0};function dt(r){for(S.push(r),P+=r.body.length;P>dr&&S.length>1;){let e=S.shift();P-=e.body.length,v.dropped++}return ct()}function ct(){return!X&&S.length&&(X=ur()),X??Promise.resolve()}async function ur(){let r=500;try{for(;S.length;){let e=S[0];try{await ut(e),v.lastError=void 0,r=500}catch(t){if(v.lastError=m(t),!(t instanceof J&&t.status>=400&&t.status<500&&t.status!==408&&t.status!==429)){await Re(r),r=Math.min(r*2,5e3);continue}v.dropped++}S.shift(),P-=e.body.length}}finally{X=null}}async function ut(r){let e=await fetch(r.url,{method:"POST",headers:{"Content-Type":r.contentType,"X-Tabtape-Client":"extension"},body:r.body});if(!e.ok)throw new J(e.status,`HTTP ${e.status}: ${(await e.text()).trim()}`);if(r.lines&&(v.lines+=r.lines,v.bytes+=r.body.length),r.sessionId){let t=await e.json().catch(()=>null);fr(r.sessionId,t?.followers)}}var k=null;function fr(r,e){let t=typeof e=="number"&&e>0?j.live:j.normal;k?.sessionId===r&&k.ms===t||(k={sessionId:r,ms:t},(async()=>{let n=await g();n?.sessionId===r&&await chrome.tabs.sendMessage(n.tabId,{type:"flush-interval",ms:t},{frameId:0})})().catch(()=>{}))}var ye=Promise.resolve();function lr(r,e){r?.kind==="session"?V(r.id,e):r?.kind==="buffer"&&ft(r.key,r.windowMs,e)}var ke;async function ft(r,e,t){if(!at.test(r)||!t)return;let{serverUrl:n}=await p();try{let s=await fetch(`${n}/api/buffers/${r}/events?window=${Math.round(e)}`,{method:"POST",headers:{"Content-Type":"application/x-ndjson","X-Tabtape-Client":"extension"},body:t});if(!s.ok)throw new Error(`HTTP ${s.status}: ${(await s.text()).trim()}`);ke=void 0}catch(s){ke=m(s)}}function V(r,e){!at.test(r)||!e||(ye=ye.then(async()=>{let t=await g(),n=t?.sessionId===r?t.serverUrl:(await p()).serverUrl;dt({url:`${n}/api/sessions/${r}/events`,contentType:"application/x-ndjson",body:e,lines:Sr(e),sessionId:r})}).catch(t=>console.warn("tabtape: batch dropped",t)))}var ot=Promise.resolve();function y(r){let e=ot.then(r,r);return ot=e.catch(()=>{}),e}async function G(r,e={}){await g()&&await E();let t=await chrome.tabs.get(r),n=await p();if(!e.nextPage){if(!ue(t.url))throw new Error("Browser pages (chrome://, Web Store, \u2026) cannot be recorded.");if(w(t.url,n.serverUrl))throw new Error("tabtape\u2019s own pages (replay, live view) are never recorded.")}if(!(await wt(n.serverUrl)).ok)throw new Error(vt(n.serverUrl));let i=!e.nextPage&&n.bufferEnabled&&n.startWithBuffer?(await T())[r]:void 0,o=null;i?.active&&(o=await lt(r,i.key,n,!0).catch(()=>null));let d=e.nextPage?void 0:t,c={sessionId:o??vr(),tabId:r,startedAt:Date.now(),serverUrl:n.serverUrl,title:e.name??d?.title,url:d?.url};o||await ut({url:`${c.serverUrl}/api/sessions`,contentType:"application/json",body:JSON.stringify({id:c.sessionId,startedAt:c.startedAt,url:c.url,title:c.title,userAgent:navigator.userAgent,source:e.source})});let a;if(e.deep)try{await ae(mt(c,n)),c.deep={state:"on"}}catch(u){a=`Deep network mode could not start: ${m(u)}`}await q(c),Object.assign(v,{lines:0,bytes:0,dropped:0,lastError:void 0});try{await ht(n),e.nextPage||await Y(r,n)}catch(u){throw c.deep&&await Ge(),await q(null),await Q(),await fetch(`${c.serverUrl}/api/sessions/${c.sessionId}`,{method:"DELETE",headers:{"X-Tabtape-Client":"extension"}}).catch(()=>{}),new Error(`Could not inject the recorder: ${m(u)}`)}return a&&gt(c.sessionId,a),await Ee(c),a?{...c,warning:a}:c}async function lt(r,e,t,n){try{let o=await chrome.tabs.sendMessage(r,{type:"take"},{frameId:0});o?.lines&&await ft(e,t.bufferMinutes*6e4,o.lines)}catch{}let s=await fetch(`${t.serverUrl}/api/buffers/${e}/save`,{method:"POST",headers:{"Content-Type":"application/json","X-Tabtape-Client":"extension"},body:JSON.stringify({minutes:t.bufferMinutes,continue:n})});if(!s.ok)throw new Error(s.status===404?"Nothing buffered yet for this tab.":`HTTP ${s.status}: ${(await s.text()).trim()}`);return(await s.json()).id}async function Te(r){let e=await p(),t=(await T())[r];if(!e.bufferEnabled||!t)throw new Error("This tab is not in buffer mode. Add the site to the buffer list in Settings.");let s={sessionId:await lt(r,t.key,e,!1),serverUrl:e.serverUrl};return await chrome.storage.session.set({lastSession:s,lastBufferSave:{...s,tabId:r,at:Date.now()}}),s}async function E(){let r=await g();if(!r)return null;oe()!==void 0?await de():r.deep?.state==="on"&&await chrome.debugger.detach({tabId:r.tabId}).catch(()=>{}),await q(null),await Q().catch(()=>{});try{let e=await chrome.tabs.sendMessage(r.tabId,{type:"stop"},{frameId:0});e?.lines&&V(r.sessionId,e.lines)}catch{}return await ye,dt({url:`${r.serverUrl}/api/sessions/${r.sessionId}/end`,contentType:"application/json",body:JSON.stringify({endedAt:Date.now()})}),await Promise.race([ct(),Re(cr)]),k?.sessionId===r.sessionId&&(k=null),await chrome.storage.session.set({lastSession:{sessionId:r.sessionId,serverUrl:r.serverUrl}}),await Ee(null),(await T())[r.tabId]&&await Y(r.tabId,await p()).catch(()=>{}),{sessionId:r.sessionId,serverUrl:r.serverUrl}}function mt(r,e){return{tabId:r.tabId,captureBodies:e.captureBodies,maxBodyChars:z,post:t=>V(r.sessionId,t),flushMs:()=>k?.sessionId===r.sessionId?k.ms:j.normal,ignore:({documentURL:t})=>w(t,r.serverUrl)||w(t,e.serverUrl)}}var mr={canceled_by_user:"canceled in Chrome's debugging bar",target_closed:"the page closed or crashed",restarted:"the extension restarted"};function gt(r,e){V(r,JSON.stringify({ts:Date.now(),type:"event",data:{name:"marker",label:e}}))}async function pt(r,e){let t=mr[e]??e;gt(r.sessionId,`Deep network mode stopped: ${t}`),await q({...r,deep:{state:"ended",reason:t}}),await chrome.tabs.sendMessage(r.tabId,{type:"redecide"},{frameId:0}).catch(()=>{})}async function gr(r,e){let t=Ve(r);try{await y(async()=>{let n=await g();n?.tabId===r&&n.deep?.state==="on"&&await pt(n,e)}),await t}catch(n){console.warn("tabtape: deep mode end",m(n))}}async function pr(){let r=await g();if(!(r?.deep?.state!=="on"||oe()===r.tabId))try{await ae(mt(r,await p()),!0)}catch{await pt(r,"restarted")}}async function ht(r){await Q(),await chrome.scripting.registerContentScripts(ar(r))}async function Q(){let r=await chrome.scripting.getRegisteredContentScripts({ids:be});r.length&&await chrome.scripting.unregisterContentScripts({ids:r.map(e=>e.id)})}async function Y(r,e){await chrome.scripting.executeScript({target:{tabId:r},files:["bridge.js"],world:"ISOLATED",injectImmediately:!0}),await chrome.scripting.executeScript({target:{tabId:r},files:ve(e),world:"MAIN",injectImmediately:!0})}async function hr(r){let e=r.tab?.id;if(e===void 0||(r.frameId??0)!==0)return{record:!1};let[t,n]=await Promise.all([g(),p()]),s=r.url??r.tab?.url??"",i=w(s,n.serverUrl)||w(s,t?.serverUrl);if(t?.tabId===e&&!i)return{record:!0,target:{kind:"session",id:t.sessionId},options:{captureBodies:n.captureBodies,maxBodyChars:z,checkoutEveryNms:Math.max(0,n.checkoutMinutes)*6e4,inPageNetwork:t.deep?.state!=="on",recordState:n.recordState},flushMs:k?.sessionId===t.sessionId?k.ms:void 0};let o=!i&&n.bufferEnabled&&ce(n.bufferSites,s),d=await Se(a=>{let u=a[e];return o?a[e]={key:u?.key??br(e),active:!0,url:s}:u&&(u.active=!1),a[e]?.key});if(await B(e,t),!o||!d)return{record:!1};let c=n.bufferMinutes*6e4;return{record:!0,target:{kind:"buffer",key:d,windowMs:c},options:{captureBodies:n.captureBodies,maxBodyChars:z,checkoutEveryNms:st(c),inPageNetwork:!0,recordState:n.recordState}}}function br(r){let e=Array.from(crypto.getRandomValues(new Uint8Array(3)),t=>t.toString(16).padStart(2,"0")).join("");return`tab${r}-${e}`}async function xe(){let r=await p(),e=await chrome.scripting.getRegisteredContentScripts({ids:ge});if(e.length&&await chrome.scripting.unregisterContentScripts({ids:e.map(n=>n.id)}),!r.bufferEnabled||!r.bufferSites.length){let n=await Se(s=>{let i={...s};for(let o of Object.keys(s))delete s[o];return i});for(let[s,i]of Object.entries(n))bt(i.key,r.serverUrl),await Y(Number(s),r).catch(()=>{}),await B(Number(s),await g());return}let t={matches:r.bufferSites,runAt:"document_start",allFrames:!1,persistAcrossSessions:!0};await chrome.scripting.registerContentScripts([{...t,id:ge[0],js:["bridge.js"],world:"ISOLATED"},{...t,id:ge[1],js:ve(r),world:"MAIN"}]);for(let n of await chrome.tabs.query({}))n.id===void 0||!n.url||w(n.url,r.serverUrl)||ce(r.bufferSites,n.url)&&await Y(n.id,r).catch(()=>{})}function bt(r,e){return fetch(`${e}/api/buffers/${r}`,{method:"DELETE",headers:{"X-Tabtape-Client":"extension"}}).catch(()=>{})}async function wt(r){try{let e=await fetch(`${r}/api/health`,{signal:AbortSignal.timeout(1500)});if(!e.ok)return{ok:!1,url:r,error:`HTTP ${e.status}`};let t=await e.json();return{ok:!0,url:r,version:t.version}}catch{return{ok:!1,url:r,error:"not reachable"}}}async function yt(r){let[e,t,{lastSession:n},s]=await Promise.all([g(),p(),chrome.storage.session.get("lastSession"),T()]);return{recording:e,lastSession:n??null,server:await wt(e?.serverUrl??t.serverUrl),stats:{...v,queuedBytes:P},buffer:{enabled:t.bufferEnabled,minutes:t.bufferMinutes,tab:r!==void 0?s[r]??null:null,error:t.bufferEnabled?ke:void 0}}}async function Ee(r){await chrome.action.setBadgeText({text:r?"REC":""}),await chrome.action.setBadgeBackgroundColor({color:we.rec}),await chrome.action.setBadgeTextColor({color:"#ffffff"}),await chrome.action.setTitle({title:r?`tabtape: recording \u201C${r.title??r.url??""}\u201D`:"tabtape: record this tab"});for(let e of Object.keys(await T()))await B(Number(e),r);r&&await B(r.tabId,r)}async function B(r,e){let t=(await T())[r]?.active;try{e?.tabId===r?(await chrome.action.setBadgeText({tabId:r,text:"REC"}),await chrome.action.setBadgeBackgroundColor({tabId:r,color:we.rec})):t?(await chrome.action.setBadgeText({tabId:r,text:"BUF"}),await chrome.action.setBadgeBackgroundColor({tabId:r,color:we.buf})):await chrome.action.setBadgeText({tabId:r,text:null})}catch{}}chrome.runtime.onMessage.addListener((r,e,t)=>{let n=e.id===chrome.runtime.id&&!!e.url?.startsWith(chrome.runtime.getURL(""));switch(r?.type){case"hello":return hr(e).then(t,()=>t({record:!1})),!0;case"batch":return lr(r.target,r.lines),t({ok:!0}),!1;case"status":return n?(yt(r.tabId).then(t,s=>t({ok:!1,error:m(s)})),!0):!1;case"save-buffer":return n?(K(Te(r.tabId),t),!0):!1;case"settings-changed":return n?(K((async()=>(await xe(),await g()&&await ht(await p()),{}))(),t),!0):!1;case"start":return n?(K(y(()=>G(r.tabId,{deep:r.deep===!0})),t),!0):!1;case"stop":return n?(K(y(()=>E()),t),!0):!1}return!1});chrome.tabs.onRemoved.addListener(r=>{y(async()=>{(await g())?.tabId===r&&await E()}),(async()=>{let e=await Se(t=>{let n=t[r];return delete t[r],n});e&&await bt(e.key,(await p()).serverUrl)})()});chrome.webNavigation.onCommitted.addListener(r=>{r.frameId===0&&!r.transitionQualifiers.includes("forward_back")&&kt(r.tabId,r.url)},{url:["127.0.0.1","localhost","[::1]"].map(r=>({schemes:["http","https"],hostEquals:r,pathContains:"/record"}))});chrome.tabs.query({}).then(r=>{for(let e of r)e.id!==void 0&&e.url&&kt(e.id,e.url)});var wr=300,pe=new Set;async function kt(r,e){if(!e.includes("/record"))return;let t=await p(),n=tt(e,t.serverUrl);if(!(!n||pe.has(r))){pe.add(r);try{if((await chrome.tabs.get(r).catch(()=>{}))?.url!==e)return;await yr(r,e,n,t)}finally{pe.delete(r)}}}async function he(r,e,t){if(!t.startsWith("file:"))try{await chrome.scripting.executeScript({target:{tabId:r},injectImmediately:!0,func:(n,s)=>{location.href===n&&location.replace(s)},args:[e,t]});return}catch{}(await chrome.tabs.get(r)).url===e&&await chrome.tabs.update(r,{url:t})}async function yr(r,e,t,n){let s=i=>`${n.serverUrl}/record?${new URLSearchParams(i)}`;try{if(await kr(n.serverUrl,t.token),t.action==="start"){if(t.url!==void 0&&(!ue(t.url)||w(t.url,n.serverUrl)))throw new Error(`${t.url} cannot be recorded: only http, https and file pages can.`);let o={started:(await y(()=>G(r,{name:t.name,source:"automation",nextPage:!0}))).sessionId};t.name&&(o.name=t.name),await he(r,e,t.url??s(o))}else{await Re(wr);let i=await y(()=>E());await he(r,e,s(i?{stopped:i.sessionId}:{error:"Nothing was being recorded."}))}}catch(i){await he(r,e,s({error:m(i)})).catch(()=>{})}}async function kr(r,e){let t;try{t=await fetch(`${r}/api/record/verify`,{method:"POST",headers:{"Content-Type":"application/json","X-Tabtape-Client":"extension"},body:JSON.stringify({token:e}),signal:AbortSignal.timeout(3e3)})}catch{throw new Error(vt(r))}if(t.status===403)throw new Error("This record link is not valid (did the Repoburg daemon restart?): get a new one from get_record_link.");if(!t.ok)throw new Error(`HTTP ${t.status}: ${(await t.text()).trim()}`)}function vt(r){return`tabtape is not reachable at ${r}. It runs inside the Repoburg daemon: start it with "repoburg-daemon".`}chrome.commands.onCommand.addListener((r,e)=>{if(r==="save-buffer"){(async()=>{let t=e?.id!==void 0?e:(await chrome.tabs.query({active:!0,currentWindow:!0}))[0];if(t?.id!==void 0)try{let n=await Te(t.id);await chrome.action.setBadgeText({tabId:t.id,text:"SAVED"}),setTimeout(()=>{B(t.id,null)},2500),console.info("tabtape: saved buffer as",n.sessionId)}catch(n){console.warn("tabtape:",m(n))}})();return}r==="toggle-recording"&&y(async()=>{if(await g()){await E();return}let t=e?.id!==void 0?e:(await chrome.tabs.query({active:!0,currentWindow:!0}))[0];t?.id!==void 0&&await G(t.id)}).catch(t=>console.warn("tabtape:",m(t)))});async function St(){await q(null),await Q(),await chrome.storage.session.remove("bufferTabs"),await xe().catch(r=>console.warn("tabtape: buffer scripts",m(r))),await Ee(null)}chrome.runtime.onStartup.addListener(()=>{St()});chrome.runtime.onInstalled.addListener(()=>{St()});Ye(gr);y(pr).catch(r=>console.warn("tabtape: deep mode after restart",m(r)));Object.assign(globalThis,{tabtape:{start:(r,e={})=>y(async()=>{let t=await chrome.tabs.get(r),n=!t.url||t.url==="about:blank";return G(r,{deep:e.deep===!0,name:le(e.name),source:"automation",nextPage:n})}),stop:()=>y(()=>E()),status:yt,saveBuffer:Te,syncBufferScripts:xe,simulateDetach:r=>Qe(r)}});function K(r,e){r.then(t=>e({ok:!0,...t}),t=>e({ok:!1,error:m(t)}))}function vr(){let r=new Date,e=n=>String(n).padStart(2,"0"),t=Array.from(crypto.getRandomValues(new Uint8Array(3)),n=>n.toString(16).padStart(2,"0")).join("");return`${r.getFullYear()}${e(r.getMonth()+1)}${e(r.getDate())}-${e(r.getHours())}${e(r.getMinutes())}${e(r.getSeconds())}-${t}`}function Sr(r){let e=1;for(let t=r.indexOf(`
6
+ `);t>=0;t=r.indexOf(`
7
+ `,t+1))e++;return e}function m(r){return r instanceof Error?r.message:String(r)}function Re(r){return new Promise(e=>setTimeout(e,r))}
8
+ //# sourceMappingURL=background.js.map