@inkly-org/cli 0.6.1 → 0.7.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.
@@ -1,6 +1,9 @@
1
1
  #!/usr/bin/env node
2
- import vt from"mri";import{spawn as Ke,execFile as Ot}from"child_process";import{createHash as Ht,randomUUID as jt}from"crypto";import{mkdir as O,mkdtemp as Wt,open as zt,readFile as F,readdir as Vt,rm as Ze,writeFile as U}from"fs/promises";import{existsSync as de}from"fs";import{dirname as pe,isAbsolute as Zt,join as y,resolve as Je,sep as Jt}from"path";import{tmpdir as Yt,homedir as qe}from"os";import{fileURLToPath as Ye}from"url";import{unzipSync as en,zipSync as tn}from"fflate";import Xe from"ws";import sn from"sharp";import an from"subset-font";import{zipSync as At}from"fflate";import{JSDOM as dn}from"jsdom";import{randomUUID as xe}from"crypto";import{mkdir as Te,readFile as Ie,writeFile as _e}from"fs/promises";import{dirname as Ee,join as Le}from"path";import{homedir as De}from"os";import{PostHog as Ue}from"posthog-node";var ne=process.env.NEXT_PUBLIC_POSTHOG_PROJECT_TOKEN??process.env.POSTHOG_PROJECT_TOKEN??"phc_Dmh4w8YFNosi3YHD4Sv7ShHX7ccS8kmtRcm8XSVmB5jT",Re=process.env.NEXT_PUBLIC_POSTHOG_HOST??process.env.POSTHOG_HOST??"https://us.i.posthog.com",$e="@inkly-org/cli@0.5.1",V=Le(De(),".inkly","analytics.json"),te=null,$=null,re=null;function Me(){return!!ne&&process.env.INKLY_TELEMETRY_DISABLED!=="1"}function Ne(){return Me()?(te??=new Ue(ne,{host:Re,flushAt:1,flushInterval:0}),te):null}async function Oe(){try{let e=await Ie(V,"utf8");return JSON.parse(e)}catch{return{}}}async function Fe(e){await Te(Ee(V),{recursive:!0}),await _e(V,JSON.stringify(e,null,2)+`
3
- `,{encoding:"utf8",mode:384})}async function He(){return $||($=(async()=>{let e=await Oe();if(typeof e.platformUserId=="string"&&e.platformUserId&&(re=e.platformUserId),typeof e.distinctId=="string"&&e.distinctId)return e.distinctId;let r=`cli_${xe()}`;return await Fe({...e,distinctId:r}),r})(),$)}async function je(){let e=await He();return re??e}function Be(){return{surface:"cli",release:process.env.POSTHOG_RELEASE??$e,node_version:process.versions.node,platform:process.platform,arch:process.arch,ci:!!process.env.CI}}async function ie(e,r={}){let i=Ne();if(i)try{i.capture({distinctId:await je(),event:e,properties:{...Be(),...r}})}catch{}}import{mkdir as We,rename as ze,writeFile as Ve}from"fs/promises";import{dirname as Ge}from"path";async function se(e,r,i){await We(Ge(e),{recursive:!0});let t=`${e}.tmp-${process.pid}-${Date.now()}-${Math.random().toString(36).slice(2,8)}`;await Ve(t,r,i?.mode!=null?{mode:i.mode}:void 0),await ze(t,e)}var me=`Options:
2
+ import An from"mri";import{spawn as Vt,execFile as rr}from"child_process";import{createHash as sr,randomUUID as or}from"crypto";import{mkdir as Y,mkdtemp as lr,open as cr,readFile as Q,readdir as ur,rm as qt,writeFile as W}from"fs/promises";import{existsSync as Ue}from"fs";import{dirname as Oe,isAbsolute as fr,join as x,resolve as zt,sep as mr}from"path";import{tmpdir as gr,homedir as Gt}from"os";import{fileURLToPath as Kt}from"url";import{unzipSync as br,zipSync as vr}from"fflate";import Jt from"ws";import Pr from"sharp";import Ar from"subset-font";import{zipSync as Tn}from"fflate";import{JSDOM as Tr}from"jsdom";import{randomUUID as Xe}from"crypto";import{mkdir as Ye,readFile as Qe,writeFile as et}from"fs/promises";import{dirname as tt,join as nt}from"path";import{homedir as rt}from"os";import{PostHog as it}from"posthog-node";var we=process.env.NEXT_PUBLIC_POSTHOG_PROJECT_TOKEN??process.env.POSTHOG_PROJECT_TOKEN??"phc_Dmh4w8YFNosi3YHD4Sv7ShHX7ccS8kmtRcm8XSVmB5jT",st=process.env.NEXT_PUBLIC_POSTHOG_HOST??process.env.POSTHOG_HOST??"https://us.i.posthog.com",ot="@inkly-org/cli@0.5.1",se=nt(rt(),".inkly","analytics.json"),ge=null,z=null,ye=null;function at(){return!!we&&process.env.INKLY_TELEMETRY_DISABLED!=="1"}function lt(){return at()?(ge??=new it(we,{host:st,flushAt:1,flushInterval:0}),ge):null}async function ct(){try{let e=await Qe(se,"utf8");return JSON.parse(e)}catch{return{}}}async function ut(e){await Ye(tt(se),{recursive:!0}),await et(se,JSON.stringify(e,null,2)+`
3
+ `,{encoding:"utf8",mode:384})}async function dt(){return z||(z=(async()=>{let e=await ct();if(typeof e.platformUserId=="string"&&e.platformUserId&&(ye=e.platformUserId),typeof e.distinctId=="string"&&e.distinctId)return e.distinctId;let t=`cli_${Xe()}`;return await ut({...e,distinctId:t}),t})(),z)}async function pt(){let e=await dt();return ye??e}function ft(){return{surface:"cli",release:process.env.POSTHOG_RELEASE??ot,node_version:process.versions.node,platform:process.platform,arch:process.arch,ci:!!process.env.CI}}async function be(e,t={}){let n=lt();if(n)try{n.capture({distinctId:await pt(),event:e,properties:{...ft(),...t}})}catch{}}import{mkdir as mt,rename as ht,writeFile as gt}from"fs/promises";import{dirname as wt}from"path";async function ve(e,t,n){await mt(wt(e),{recursive:!0});let r=`${e}.tmp-${process.pid}-${Date.now()}-${Math.random().toString(36).slice(2,8)}`;await gt(r,t,n?.mode!=null?{mode:n.mode}:void 0),await ht(r,e)}import{Stagehand as Dt}from"@browserbasehq/stagehand";import{NodeHtmlMarkdown as Nt}from"node-html-markdown";function ke(){return{urlMap:{},xpathMap:{}}}function yt(e){if(e.startsWith("@")){let t=e.slice(1);return t.startsWith("[")&&t.endsWith("]")?t.slice(1,-1):t}return e.startsWith("[")&&e.endsWith("]")&&/^\[\d+-\d+]$/.test(e)?e.slice(1,-1):e.startsWith("ref=")?e.slice(4):/^\d+-\d+$/.test(e)?e:null}function M(e,t){let n=yt(e);if(!n)return e;let r=t.xpathMap[n];if(!r)throw new Error(`Unknown ref "${n}" - run \`inkly capture nav snapshot\` first to populate refs (have ${Object.keys(t.xpathMap).length} refs).`);return r}function oe(e,t={}){let n=e.split(`
4
+ `);return t.maxDepth!==void 0&&(n=n.filter(r=>j(r)<=t.maxDepth)),t.filter&&(n=kt(n,t.filter)),t.trim?n=Rt(n):t.compact&&(n=Ce(n)),(t.trim||t.compact)&&(n=vt(n)),n.join(`
5
+ `).trim()}function Se(e){let t=e.match(/^\s*(?:\[[\w-]+]\s*)?([A-Za-z]+)/);return t?t[1].toLowerCase():null}function bt(e){let t=e.match(/^\s*(?:\[[\w-]+]\s*)?[A-Za-z]+(?:,[^:]*)?:\s*(.*)$/);return t?t[1].trim():""}function vt(e){let r=[],i=0;for(;i<e.length;){let s=j(e[i]),o=Se(e[i]),u=i+1;if(o)for(;u<e.length&&j(e[u])===s&&Se(e[u])===o;)u+=1;let d=u-i,g=new Set;for(let c=i;c<u;c+=1)g.add(bt(e[c]));let b=g.size<=d/2;if(o&&d>=14&&b){for(let w=i;w<i+6;w+=1)r.push(e[w]);let c=" ".repeat(s*2);r.push(`${c}\u2026 (+${d-6} more ${o}, repeated)`),i=u}else r.push(e[i]),i+=1}return r}function kt(e,t){let n=St(t);return ae(e,n)}function ae(e,t){let n=new Set;for(let r=0;r<e.length;r+=1){if(!t(e[r]??""))continue;n.add(r);let i=j(e[r]??"");for(let s=r-1;s>=0;s-=1){let o=j(e[s]??"");if(o<i&&(n.add(s),i=o,o===0))break}}return e.filter((r,i)=>n.has(i))}function St(e){let t=Pt(e);if(t)return r=>t.test(r);let n=e.toLowerCase();return r=>r.toLowerCase().includes(n)}function Pt(e){let t=e.match(/^\/(.+)\/([a-z]*)$/i);if(!t)return null;try{return new RegExp(t[1]??"",t[2]??"")}catch{return null}}function Ce(e){let t=ae(e,Ct);return t.length>0?t:e}function Ct(e){return/\[\d+-\d+]/.test(e)||e.includes(": ")||/\b(button|link|textbox|checkbox|radio|combobox)\b/i.test(e)}var At=["button","link","textbox","searchbox","checkbox","radio","combobox","listbox","option","switch","slider","spinbutton","tab","menuitem","menuitemcheckbox","menuitemradio","treeitem"],xt=["navigation","main","banner","contentinfo","complementary","search","form","dialog","alertdialog","menu","menubar","tablist","region"],B="^\\s*(?:\\[[\\w-]+]\\s*)?",_t=new RegExp(`${B}(?:${At.join("|")})\\b`,"i"),Et=new RegExp(`${B}(?:${xt.join("|")})\\b`,"i"),Tt=new RegExp(`${B}heading\\b`,"i"),Mt=new RegExp(`${B}StaticText\\b`,"i");function Pe(e){return Mt.test(e)?!1:_t.test(e)||Tt.test(e)||Et.test(e)}var It=new RegExp(`${B}[\\w-]+(?:,[^:]*)?:\\s`,"i");function Lt(e){return It.test(e)}function Rt(e){let n=ae(e,Pe).filter(r=>Pe(r)||Lt(r));return n.length>0?n:Ce(e)}function j(e){let t=e.match(/^\s*/);return Math.floor((t?.[0].length??0)/2)}var $t={trim:!0},G=90,Ut=110,_e=1600,Ae=2600,Ot=1800,xe={width:1440,height:900},K=class{constructor(t,n){this.browserWsUrl=t;this.targetId=n;this.stagehand=null;this.context=null;this.refMaps=ke()}async init(){if(this.stagehand)return;let t=new Dt({disablePino:!0,env:"LOCAL",localBrowserLaunchOptions:{cdpUrl:this.browserWsUrl},verbose:0});try{await t.init()}catch(n){throw await t.close().catch(()=>{}),n}this.stagehand=t,this.context=t.context,this.selectRecorderPage()}selectRecorderPage(){if(!this.context)throw new Error("nav driver not initialized");let t=this.context.pages(),r=t.find(i=>{try{return i.targetId()===this.targetId}catch{return!1}})??this.activePageIfPresent()??t[0];if(!r)throw new Error("nav driver found no page in the attached browser");return this.context.setActivePage(r),r}activePageIfPresent(){try{return this.context?.activePage()??void 0}catch{return}}activePage(){return this.selectRecorderPage()}async snapshot(t){let n=this.activePage(),r=await n.snapshot();this.refMaps={urlMap:r.urlMap??{},xpathMap:r.xpathMap??{}};let i=oe(r.formattedTree,t);return t.includeMaps?{tree:i,url:n.url(),urlMap:r.urlMap,xpathMap:r.xpathMap}:{tree:i,url:n.url()}}async agentSnapshot(){let t=this.activePage(),n=await t.snapshot();return this.refMaps={urlMap:n.urlMap??{},xpathMap:n.xpathMap??{}},{tree:oe(n.formattedTree,$t),url:t.url()}}url(){return this.activePage().url()}resolveRef(t){return M(t,this.refMaps)}async click(t){if(!this.stagehand)throw new Error("nav driver not initialized");this.activePage();let n=M(t,this.refMaps);return await this.stagehand.act({arguments:[],description:"click element",method:"click",selector:n}),{clicked:!0,selector:n}}async fill(t,n,r){if(!this.stagehand)throw new Error("nav driver not initialized");let i=this.activePage(),s=M(t,this.refMaps);return await this.stagehand.act({arguments:[n],description:"fill element",method:"fill",selector:s}),r&&await i.keyPress("Enter"),{filled:!0,pressedEnter:r,selector:s}}async type(t,n){return await this.activePage().type(t,{delay:n}),{typed:!0}}async key(t){return await this.activePage().keyPress(t),{pressed:t}}async select(t,n){let r=this.activePage(),i=M(t,this.refMaps);return{selected:await r.deepLocator(i).selectOption(n),selector:i}}async upload(t,n){let r=this.activePage(),i=M(t,this.refMaps);return await r.deepLocator(i).setInputFiles(n.length===1?n[0]:n),{uploaded:!0,files:n,selector:i}}async get(t,n){let r=this.activePage();if(t==="url")return{url:r.url()};if(t==="title")return{title:await r.title()};let i=M(n??"body",this.refMaps),s=r.deepLocator(i);if(t==="text")return{text:await s.textContent()};if(t==="html")return{html:await s.innerHtml()};if(t==="value")return{value:await s.inputValue()};if(t==="visible")return{visible:await s.isVisible()};if(t==="checked")return{checked:await s.isChecked()};if(t==="markdown")return{markdown:Nt.translate(await s.innerHtml())};if(t==="box"){let{x:o,y:u}=await s.centroid();return{x:Math.round(o),y:Math.round(u)}}throw new Error(`unknown get target "${t}" \u2014 expected url|title|text|html|value|visible|checked|markdown|box`)}async is(t,n){let i=this.activePage().deepLocator(M(n,this.refMaps));if(t==="visible")return{visible:await i.isVisible()};if(t==="checked")return{checked:await i.isChecked()};throw new Error(`unknown is check "${t}" \u2014 expected visible|checked`)}async wait(t){let n=this.activePage();if(t.type==="load")await n.waitForLoadState(t.arg??"load",t.timeoutMs);else if(t.type==="selector"){if(!t.arg)throw new Error("nav wait selector requires a <selector> argument");await n.waitForSelector(M(t.arg,this.refMaps),{state:t.state??"visible",timeout:t.timeoutMs??3e4})}else if(t.type==="timeout"){let r=Number(t.arg);if(!Number.isInteger(r)||r<0)throw new Error("nav wait timeout requires a non-negative integer <ms>");await n.waitForTimeout(r)}else throw new Error(`unknown wait type "${t.type}" \u2014 expected load|selector|timeout`);return{waited:!0}}async back(t){let n=this.activePage();return await n.goBack(t),{navigated:!0,url:n.url()}}async forward(t){let n=this.activePage();return await n.goForward(t),{navigated:!0,url:n.url()}}async reload(t){let n=this.activePage();return await n.reload(t),{reloaded:!0,url:n.url()}}refs(){return{count:Object.keys(this.refMaps.xpathMap).length,urlMap:this.refMaps.urlMap,xpathMap:this.refMaps.xpathMap}}async mouseClick(t,n,r={}){return await this.activePage().click(t,n,r),{clicked:!0}}async mouseHover(t,n){return await this.activePage().hover(t,n),{hovered:!0}}async mouseScroll(t,n,r,i){return await this.activePage().scroll(t,n,r,i),{scrolled:!0}}async scroll(t,n){let r=this.activePage(),i=Math.round(xe.width/2),s=Math.round(xe.height/2),o=Math.max(G,Math.round(Math.abs(n))),u=t==="up"?-1:1,d=Math.ceil(o/G),g=Math.max(1,d-1),b=Math.min(Math.round(Ae/g),Math.max(Ut,Math.round(Ot/g))),c=Date.now(),w=o;for(let v=0;v<d&&!(Date.now()-c>Ae);v+=1){let S=Math.min(G,w)*u;w-=G,await r.scroll(i,s,0,S),v<d-1&&await new Promise(C=>setTimeout(C,b))}return{scrolled:!0,direction:t,amount:o}}async close(){let t=this.stagehand;this.stagehand=null,this.context=null,t&&await t.close().catch(()=>{})}};import Ft from"net";import Ht from"readline";import{rm as Ee}from"fs/promises";import{join as le}from"path";import{homedir as jt}from"os";function Bt(){return le(process.env.INKLY_CAPTURE_AGENT_HOME||le(jt(),".inkly"),"capture-agent","sessions")}function Me(e){if(!/^[a-zA-Z0-9._:-]+$/.test(e))throw new Error(`invalid session id: ${e}`);return le(Bt(),`${e}.nav.sock`)}async function Ie(e,t){let n=Ft.createServer(r=>{let i=Ht.createInterface({input:r});r.once("error",()=>{i.close(),r.destroy()}),i.once("line",s=>{Wt(s,t).then(o=>Te(r,o)).catch(o=>Te(r,{type:"error",error:o instanceof Error?o.message:String(o)})).finally(()=>{i.close(),r.end()})})});return await Ee(e,{force:!0}).catch(()=>{}),await new Promise((r,i)=>{let s=o=>i(o);n.once("error",s),n.listen(e,()=>{n.off("error",s),r()})}),{close(){return new Promise(r=>{n.close(()=>{Ee(e,{force:!0}).catch(()=>{}).finally(()=>r())})})}}}async function Wt(e,t){let n;try{n=JSON.parse(e)}catch(r){return{type:"error",error:r instanceof Error?r.message:String(r)}}if(n.type!=="command"||typeof n.command!="string")return{id:n.id,type:"error",error:"invalid nav request"};try{let r=await t(n);return{id:n.id,type:"success",data:r}}catch(r){return{id:n.id,type:"error",error:r instanceof Error?r.message:String(r)}}}function Te(e,t){e.write(`${JSON.stringify(t)}
6
+ `)}var Fe=`Options:
4
7
  --url <url> URL to open and arm for recording.
5
8
  --name <name> Demo name written into the exported ZIP.
6
9
  --session <id> Session id printed by start.
@@ -20,7 +23,7 @@ import vt from"mri";import{spawn as Ke,execFile as Ot}from"child_process";import
20
23
  done once in this profile survives, so later captures of the same site need
21
24
  no re-login. Implies --keep-profile. Run --headed the first time so the user
22
25
  can sign in; reuse can run headless.
23
- --no-unpack On stop, write only the ZIP.`,Qe=`inkly capture - capture an image/video walkthrough for an external browser agent
26
+ --no-unpack On stop, write only the ZIP.`,Zt=`inkly capture - capture an image/video walkthrough for an external browser agent
24
27
 
25
28
  Usage:
26
29
  inkly capture start --url <url> --name <name>
@@ -28,9 +31,10 @@ Usage:
28
31
  inkly capture cancel --session <id>
29
32
  inkly capture status --session <id>
30
33
  inkly capture undo --session <id>
34
+ inkly capture nav <verb> --session <id> (snapshot|click|fill|type|press|select|upload|get|is|wait|back|forward|reload|refs|mouse)
31
35
  inkly capture profiles
32
36
 
33
- ${me}
37
+ ${Fe}
34
38
  --video, --record-video Record motion segments. Enabled by default; use --no-video to disable.
35
39
  --zoom Apply click zoom/pan to screenshot steps. Enabled by default; use --no-zoom to disable.
36
40
  --compress-images Re-encode captured PNG/JPEG screenshots to WebP (smaller, near-lossless).
@@ -39,7 +43,7 @@ ${me}
39
43
  Output:
40
44
  Every subcommand prints JSON. This command does not accept prompts and does not plan or drive the page.
41
45
  For self-contained HTML snapshot capture, use \`inkly capture-html\`.
42
- `,fn=`inkly capture-html - capture a self-contained HTML walkthrough for an external browser agent
46
+ `,Dr=`inkly capture-html - capture a self-contained HTML walkthrough for an external browser agent
43
47
 
44
48
  Usage:
45
49
  inkly capture-html start --url <url> --name <name>
@@ -47,21 +51,22 @@ Usage:
47
51
  inkly capture-html cancel --session <id>
48
52
  inkly capture-html status --session <id>
49
53
  inkly capture-html undo --session <id>
54
+ inkly capture-html nav <verb> --session <id> (snapshot|click|fill|type|press|select|upload|get|is|wait|back|forward|reload|refs|mouse)
50
55
  inkly capture-html profiles
51
56
 
52
- ${me}
57
+ ${Fe}
53
58
  --block-videos Replace <video> with its poster frame instead of inlining the video.
54
59
 
55
60
  Output:
56
61
  Every subcommand prints JSON. This command does not accept prompts and does not plan or drive the page.
57
- `,oe=pe(Ye(import.meta.url));var fe=1440,ge=900;var he=4e3,M=30,ae=480,et=7e3,tt=20,nt=1200,rt=1500;function T(e){return new Promise(r=>setTimeout(r,e))}function it(e,r){if(!Object.prototype.hasOwnProperty.call(e,r))return;let i=e[r];return typeof i=="string"?i:""}function st(e){return{click_tag:e?.tag??null,has_click_label:!!e?.label,has_click_selector:!!e?.selector,has_click_alpha_id:!!e?.alphaId}}async function N(e){await ie("inkly_cli_capture_step_captured",{runtime:e.session.runtime??"cli",capture_kind:e.session.cliCaptureKind??e.stepKind,step_kind:e.stepKind,action:e.action,step_count:e.session.cliScreens?.length??null,window_width:e.session.width,window_height:e.session.height,record_video:e.session.cliRecordVideo===!0,auto_apply_zoom:e.session.autoApplyZoom!==!1,...st(e.click)})}function le(e){let r=e.cliScreens??[],i=r[r.length-1]?.kind;return i==="video"||i==="html"?i:"image"}function ot(e,r,i){let t=it(e,r);if(!t)throw new Error(`missing --${r} <value>
62
+ `,Le=Oe(Kt(import.meta.url));var He=1440,je=900;var Be=3e4,Xt=30,J=720,Yt=3e4,Qt=350,en=10,tn=1200,nn=1500,rn=1e3,sn=720,We=60,on=Math.round(sn/We);function N(e){return new Promise(t=>setTimeout(t,e))}function an(e,t){if(!Object.prototype.hasOwnProperty.call(e,t))return;let n=e[t];return typeof n=="string"?n:""}function ln(e){return{click_tag:e?.tag??null,has_click_label:!!e?.label,has_click_selector:!!e?.selector,has_click_alpha_id:!!e?.alphaId}}async function Z(e){await be("inkly_cli_capture_step_captured",{runtime:e.session.runtime??"cli",capture_kind:e.session.cliCaptureKind??e.stepKind,step_kind:e.stepKind,action:e.action,step_count:e.session.cliScreens?.length??null,window_width:e.session.width,window_height:e.session.height,record_video:e.session.cliRecordVideo===!0,auto_apply_zoom:e.session.autoApplyZoom!==!1,...ln(e.click)})}function Re(e){let t=e.cliScreens??[],n=t[t.length-1]?.kind;return n==="video"||n==="html"?n:"image"}function cn(e,t,n){let r=an(e,t);if(!r)throw new Error(`missing --${t} <value>
58
63
 
59
- ${i}`);return t}function ce(e,r){let i=Je(e);for(;;){let t=y(i,r);if(de(t))return t;let n=pe(i);if(n===i)return null;i=n}}var I=class{constructor(r){this.nextId=1;this.pending=new Map;this.listeners=new Map;this.ws=new Xe(r,{perMessageDeflate:!1,maxPayload:512*1024*1024}),this.ready=new Promise((i,t)=>{this.ws.once("open",()=>i()),this.ws.once("error",n=>t(n))}),this.ws.on("message",i=>{let t=JSON.parse(i.toString());if(typeof t.id=="number"&&this.pending.has(t.id)){let s=this.pending.get(t.id);if(this.pending.delete(t.id),!s)return;t.error?s.reject(new Error(`${t.error.message??"CDP error"}: ${JSON.stringify(t.error.data??"")}`)):s.resolve(t.result??{});return}if(!t.method)return;let n=this.listeners.get(t.method);if(n)for(let s of n)s(t.params,t.sessionId)})}async send(r,i={},t){await this.ready;let n=this.nextId;this.nextId+=1;let s={id:n,method:r,params:i};return t&&(s.sessionId=t),new Promise((o,d)=>{this.pending.set(n,{resolve:o,reject:d}),this.ws.send(JSON.stringify(s),a=>{a&&(this.pending.delete(n),d(a))})})}on(r,i){let t=this.listeners.get(r)??new Set;return t.add(i),this.listeners.set(r,t),()=>t.delete(i)}close(){try{this.ws.close()}catch{}}};async function C(e,r,i,t=3e4){let n=await e.send("Runtime.evaluate",{expression:i,awaitPromise:!0,returnByValue:!0,timeout:t,userGesture:!0},r);if(n.exceptionDetails)throw new Error(`Runtime.evaluate failed: ${JSON.stringify(n.exceptionDetails)}`);return n.result?.value}async function H(e,r){let t=(await e.send("Target.attachToTarget",{targetId:r,flatten:!0})).sessionId;if(typeof t!="string")throw new Error("Target.attachToTarget returned no sessionId");return t}async function ue(e){return((await e.send("Target.getTargets",{filter:[{type:"page"}]})).targetInfos??[]).filter(t=>t.type==="page")}async function at(e,r){let i=await C(e,r,`JSON.stringify({
64
+ ${n}`);return r}function De(e,t){let n=zt(e);for(;;){let r=x(n,t);if(Ue(r))return r;let i=Oe(n);if(i===n)return null;n=i}}var U=class{constructor(t){this.nextId=1;this.pending=new Map;this.listeners=new Map;this.ws=new Jt(t,{perMessageDeflate:!1,maxPayload:512*1024*1024}),this.ready=new Promise((n,r)=>{this.ws.once("open",()=>n()),this.ws.once("error",i=>r(i))}),this.ws.on("message",n=>{let r=JSON.parse(n.toString());if(typeof r.id=="number"&&this.pending.has(r.id)){let s=this.pending.get(r.id);if(this.pending.delete(r.id),!s)return;r.error?s.reject(new Error(`${r.error.message??"CDP error"}: ${JSON.stringify(r.error.data??"")}`)):s.resolve(r.result??{});return}if(!r.method)return;let i=this.listeners.get(r.method);if(i)for(let s of i)s(r.params,r.sessionId)})}async send(t,n={},r){await this.ready;let i=this.nextId;this.nextId+=1;let s={id:i,method:t,params:n};return r&&(s.sessionId=r),new Promise((o,u)=>{this.pending.set(i,{resolve:o,reject:u}),this.ws.send(JSON.stringify(s),d=>{d&&(this.pending.delete(i),u(d))})})}on(t,n){let r=this.listeners.get(t)??new Set;return r.add(n),this.listeners.set(t,r),()=>r.delete(n)}close(){try{this.ws.close()}catch{}}};async function I(e,t,n,r=3e4){let i=await e.send("Runtime.evaluate",{expression:n,awaitPromise:!0,returnByValue:!0,timeout:r,userGesture:!0},t);if(i.exceptionDetails)throw new Error(`Runtime.evaluate failed: ${JSON.stringify(i.exceptionDetails)}`);return i.result?.value}async function ee(e,t){let r=(await e.send("Target.attachToTarget",{targetId:t,flatten:!0})).sessionId;if(typeof r!="string")throw new Error("Target.attachToTarget returned no sessionId");return r}async function Ne(e){return((await e.send("Target.getTargets",{filter:[{type:"page"}]})).targetInfos??[]).filter(r=>r.type==="page")}async function un(e,t){let n=await I(e,t,`JSON.stringify({
60
65
  innerWidth: window.innerWidth,
61
66
  innerHeight: window.innerHeight,
62
67
  outerWidth: window.outerWidth,
63
68
  outerHeight: window.outerHeight
64
- })`,5e3),t=JSON.parse(String(i)),n={innerWidth:Number(t.innerWidth),innerHeight:Number(t.innerHeight),outerWidth:Number(t.outerWidth),outerHeight:Number(t.outerHeight)};if(!Number.isFinite(n.innerWidth)||!Number.isFinite(n.innerHeight)||!Number.isFinite(n.outerWidth)||!Number.isFinite(n.outerHeight))throw new Error(`could not measure Chrome viewport: ${JSON.stringify(t)}`);return n}async function j(e,r,i,t,n){try{let o=(await e.send("Browser.getWindowForTarget",{targetId:i})).windowId;if(typeof o!="number")throw new Error("Browser.getWindowForTarget returned no windowId");for(let d=0;d<4;d+=1){let a=await at(e,r),g=Math.max(0,a.outerWidth-a.innerWidth),p=Math.max(0,a.outerHeight-a.innerHeight),m=t+g,b=n+p;if(Math.abs(a.innerWidth-t)<=1&&Math.abs(a.innerHeight-n)<=1)return;await e.send("Browser.setWindowBounds",{windowId:o,bounds:{windowState:"normal",width:m,height:b}}),await T(250)}}catch{}await e.send("Emulation.setDeviceMetricsOverride",{width:t,height:n,deviceScaleFactor:1,mobile:!1},r).catch(()=>{}),await T(100)}function J(e){if(e.length<24)return null;let r=[137,80,78,71,13,10,26,10];for(let o=0;o<r.length;o+=1)if(e[o]!==r[o])return null;if(String.fromCharCode(e[12],e[13],e[14],e[15])!=="IHDR")return null;let t=new DataView(e.buffer,e.byteOffset,e.byteLength),n=t.getUint32(16,!1),s=t.getUint32(20,!1);return n>0&&s>0?{width:n,height:s}:null}var K=`(() => {
69
+ })`,5e3),r=JSON.parse(String(n)),i={innerWidth:Number(r.innerWidth),innerHeight:Number(r.innerHeight),outerWidth:Number(r.outerWidth),outerHeight:Number(r.outerHeight)};if(!Number.isFinite(i.innerWidth)||!Number.isFinite(i.innerHeight)||!Number.isFinite(i.outerWidth)||!Number.isFinite(i.outerHeight))throw new Error(`could not measure Chrome viewport: ${JSON.stringify(r)}`);return i}async function te(e,t,n,r,i){try{let o=(await e.send("Browser.getWindowForTarget",{targetId:n})).windowId;if(typeof o!="number")throw new Error("Browser.getWindowForTarget returned no windowId");for(let u=0;u<4;u+=1){let d=await un(e,t),g=Math.max(0,d.outerWidth-d.innerWidth),b=Math.max(0,d.outerHeight-d.innerHeight),c=r+g,w=i+b;if(Math.abs(d.innerWidth-r)<=1&&Math.abs(d.innerHeight-i)<=1)return;await e.send("Browser.setWindowBounds",{windowId:o,bounds:{windowState:"normal",width:c,height:w}}),await N(250)}}catch{}await e.send("Emulation.setDeviceMetricsOverride",{width:r,height:i,deviceScaleFactor:1,mobile:!1},t).catch(()=>{}),await N(100)}function pe(e){if(e.length<24)return null;let t=[137,80,78,71,13,10,26,10];for(let o=0;o<t.length;o+=1)if(e[o]!==t[o])return null;if(String.fromCharCode(e[12],e[13],e[14],e[15])!=="IHDR")return null;let r=new DataView(e.buffer,e.byteOffset,e.byteLength),i=r.getUint32(16,!1),s=r.getUint32(20,!1);return i>0&&s>0?{width:i,height:s}:null}var ue=`(() => {
65
70
  if (window.__inklyCliRecorderInstalled) return;
66
71
  window.__inklyCliRecorderInstalled = true;
67
72
  window.__inklyCliLastClick = null;
@@ -245,7 +250,7 @@ function selectorFor(el) {
245
250
  window.addEventListener("scroll", onMotionScroll, true);
246
251
  window.addEventListener("wheel", onMotionScroll, true);
247
252
  window.addEventListener("touchmove", onMotionScroll, true);
248
- })();`;async function B(e,r,i=!1){i&&(await e.send("Runtime.addBinding",{name:"__inklyCliCaptureEvent"},r).catch(()=>{}),await e.send("Runtime.addBinding",{name:"__inklyCliCaptureClick"},r).catch(()=>{})),await e.send("Page.addScriptToEvaluateOnNewDocument",{source:K},r),await C(e,r,K,5e3).catch(()=>{})}async function W(e,r){await C(e,r,K,5e3).catch(()=>{});let i=await C(e,r,`JSON.stringify({
253
+ })();`;async function ne(e,t,n=!1){n&&(await e.send("Runtime.addBinding",{name:"__inklyCliCaptureEvent"},t).catch(()=>{}),await e.send("Runtime.addBinding",{name:"__inklyCliCaptureClick"},t).catch(()=>{})),await e.send("Page.addScriptToEvaluateOnNewDocument",{source:ue},t),await I(e,t,ue,5e3).catch(()=>{})}async function re(e,t){await I(e,t,ue,5e3).catch(()=>{});let n=await I(e,t,`JSON.stringify({
249
254
  viewport: { width: window.innerWidth, height: window.innerHeight },
250
255
  sourceUrl: location.href,
251
256
  title: document.title || "Captured screen",
@@ -256,7 +261,7 @@ function selectorFor(el) {
256
261
  maxX: Math.max(0, document.documentElement.scrollWidth - window.innerWidth),
257
262
  maxY: Math.max(0, document.documentElement.scrollHeight - window.innerHeight)
258
263
  }
259
- })`,5e3),t=JSON.parse(String(i));return{viewport:{width:Number(t.viewport?.width)||fe,height:Number(t.viewport?.height)||ge},sourceUrl:typeof t.sourceUrl=="string"?t.sourceUrl:"",title:typeof t.title=="string"?t.title:"Captured screen",click:t.click??null,scroll:{x:Number(t.scroll?.x)||0,y:Number(t.scroll?.y)||0,maxX:Number(t.scroll?.maxX)||0,maxY:Number(t.scroll?.maxY)||0}}}function lt(){let e=y(oe,"singlefile-injected.js");if(de(e))return e;let r=ce(process.cwd(),"packages/capture-extension/dist/singlefile-injected.js"),i=ce(oe,"packages/capture-extension/dist/singlefile-injected.js"),t=r??i;if(!t)throw new Error("SingleFile bundle not found. Run `npm run extension:build` before --html capture.");return t}var ct={removeFrames:!0,removeImports:!0,blockScripts:!0,compressHTML:!1,compressCSS:!1,saveRawPage:!1,loadDeferredImages:!1,loadDeferredImagesMaxIdleTime:1500,loadDeferredImagesKeepZoomLevel:!1,loadDeferredImagesBlockCookies:!1,loadDeferredImagesBlockStorage:!1,blockMixedContent:!1,insertMetaCSP:!0,insertMetaNoIndex:!1,insertSingleFileComment:!1,removeAlternativeFonts:!0,removeAlternativeImages:!0,removeAlternativeMedias:!0,removeUnusedFonts:!0,backgroundSave:!1,removeUnusedStyles:!0,removeHiddenElements:!0,compressContent:!1},Z="__inklySingleFileFetch",ut=`(() => {
264
+ })`,5e3),r=JSON.parse(String(n));return{viewport:{width:Number(r.viewport?.width)||He,height:Number(r.viewport?.height)||je},sourceUrl:typeof r.sourceUrl=="string"?r.sourceUrl:"",title:typeof r.title=="string"?r.title:"Captured screen",click:r.click??null,scroll:{x:Number(r.scroll?.x)||0,y:Number(r.scroll?.y)||0,maxX:Number(r.scroll?.maxX)||0,maxY:Number(r.scroll?.maxY)||0}}}function dn(){let e=x(Le,"singlefile-injected.js");if(Ue(e))return e;let t=De(process.cwd(),"packages/capture-extension/dist/singlefile-injected.js"),n=De(Le,"packages/capture-extension/dist/singlefile-injected.js"),r=t??n;if(!r)throw new Error("SingleFile bundle not found. Run `npm run extension:build` before --html capture.");return r}var pn={removeFrames:!0,blockScripts:!0,compressHTML:!1,compressCSS:!1,saveRawPage:!1,loadDeferredImages:!1,loadDeferredImagesMaxIdleTime:1500,loadDeferredImagesKeepZoomLevel:!1,loadDeferredImagesBlockCookies:!1,loadDeferredImagesBlockStorage:!1,blockMixedContent:!1,insertMetaCSP:!0,insertMetaNoIndex:!1,insertSingleFileComment:!1,removeAlternativeFonts:!0,removeAlternativeImages:!0,removeAlternativeMedias:!0,removeUnusedFonts:!0,backgroundSave:!1,removeUnusedStyles:!0,removeHiddenElements:!0,compressContent:!1,groupDuplicateImages:!0,groupDuplicateStylesheets:!0},de="__inklySingleFileFetch",fn=`(() => {
260
265
  if (globalThis.__inklyFetchInstalled) return;
261
266
  globalThis.__inklyFetchInstalled = true;
262
267
  const pending = new Map();
@@ -276,7 +281,7 @@ function selectorFor(el) {
276
281
  const id = nextId++;
277
282
  pending.set(id, { resolve, reject });
278
283
  try {
279
- globalThis.${Z}(JSON.stringify({
284
+ globalThis.${de}(JSON.stringify({
280
285
  id,
281
286
  url: String(url),
282
287
  options: {
@@ -299,7 +304,7 @@ function selectorFor(el) {
299
304
  return viaNode(url, options);
300
305
  }
301
306
  };
302
- })();`;function dt(e,r){let i,t,n;try{let s=new URL(e);i=s.hostname,t=s.pathname||"/",n=s.protocol==="https:"}catch{return""}return r.filter(s=>{let o=s.domain.replace(/^\./,""),d=i===o||i.endsWith(`.${o}`),a=t.startsWith(s.path||"/"),g=!s.secure||n;return d&&a&&g}).map(s=>`${s.name}=${s.value}`).join("; ")}async function pt(e,r,i,t){let n;try{let s=JSON.parse(i);n=s.id;let o={...s.options?.headers??{}},d=dt(s.url,t);d&&(o.cookie=d),s.options?.referrer&&(o.referer=s.options.referrer);let a=await fetch(s.url,{headers:o,redirect:"follow"}),g=Buffer.from(await a.arrayBuffer()),p={};a.headers.forEach((b,v)=>{p[v]=b});let m={status:a.status,headers:p,data:g.toString("base64")};await C(e,r,`globalThis.__inklyResolveFetch(${n}, ${JSON.stringify(m)})`,2e4)}catch(s){if(n===void 0)return;await C(e,r,`globalThis.__inklyRejectFetch(${n}, ${JSON.stringify({error:String(s)})})`,2e4).catch(()=>{})}}var G=Math.max(6e4,Number(process.env.INKLY_CAPTURE_TIMEOUT_MS)||24e4);async function mt(e,r,i=!1){let t=await F(lt(),"utf8");await e.send("Network.enable",{},r).catch(()=>{}),await e.send("Runtime.addBinding",{name:Z},r).catch(()=>{});let n=[];try{n=(await e.send("Network.getAllCookies",{},r)).cookies??[]}catch{}let s=e.on("Runtime.bindingCalled",(o,d)=>{if(d!==r)return;let a=o;a.name!==Z||typeof a.payload!="string"||pt(e,r,a.payload,n)});try{await C(e,r,t,3e4),await C(e,r,ut,1e4);let o=await C(e,r,`(async () => {
307
+ })();`;function mn(e,t){let n,r,i;try{let s=new URL(e);n=s.hostname,r=s.pathname||"/",i=s.protocol==="https:"}catch{return""}return t.filter(s=>{let o=s.domain.replace(/^\./,""),u=n===o||n.endsWith(`.${o}`),d=r.startsWith(s.path||"/"),g=!s.secure||i;return u&&d&&g}).map(s=>`${s.name}=${s.value}`).join("; ")}async function hn(e,t,n,r){let i;try{let s=JSON.parse(n);i=s.id;let o={...s.options?.headers??{}},u=mn(s.url,r);u&&(o.cookie=u),s.options?.referrer&&(o.referer=s.options.referrer);let d=await fetch(s.url,{headers:o,redirect:"follow"}),g=Buffer.from(await d.arrayBuffer()),b={};d.headers.forEach((w,v)=>{b[v]=w});let c={status:d.status,headers:b,data:g.toString("base64")};await I(e,t,`globalThis.__inklyResolveFetch(${i}, ${JSON.stringify(c)})`,2e4)}catch(s){if(i===void 0)return;await I(e,t,`globalThis.__inklyRejectFetch(${i}, ${JSON.stringify({error:String(s)})})`,2e4).catch(()=>{})}}var ce=Math.max(6e4,Number(process.env.INKLY_CAPTURE_TIMEOUT_MS)||24e4);async function gn(e,t,n=!1){let r=await Q(dn(),"utf8");await e.send("Network.enable",{},t).catch(()=>{}),await e.send("Runtime.addBinding",{name:de},t).catch(()=>{});let i=[];try{i=(await e.send("Network.getAllCookies",{},t)).cookies??[]}catch{}let s=e.on("Runtime.bindingCalled",(o,u)=>{if(u!==t)return;let d=o;d.name!==de||typeof d.payload!="string"||hn(e,t,d.payload,i)});try{await I(e,t,r,3e4),await I(e,t,fn,1e4);let o=await I(e,t,`(async () => {
303
308
  const sf = globalThis.__inklySingleFile;
304
309
  if (!sf || typeof sf.getPageData !== "function") throw new Error("SingleFile not loaded");
305
310
  // initOptions (2nd arg) is forwarded to single-file-core/core/util.js
@@ -310,15 +315,22 @@ function selectorFor(el) {
310
315
  frameFetch: globalThis.__inklyPrivilegedFetch,
311
316
  };
312
317
  const data = await Promise.race([
313
- sf.getPageData(${JSON.stringify({...ct,blockVideos:i})}, initOptions),
314
- new Promise((_, reject) => setTimeout(() => reject(new Error("SingleFile getPageData exceeded ${G}ms")), ${G}))
318
+ sf.getPageData(${JSON.stringify({...pn,blockVideos:n})}, initOptions),
319
+ new Promise((_, reject) => setTimeout(() => reject(new Error("SingleFile getPageData exceeded ${ce}ms")), ${ce}))
315
320
  ]);
316
321
  if (typeof data.content === "string") return data.content;
317
322
  return new TextDecoder().decode(new Uint8Array(data.content));
318
- })()`,G+15e3);return String(o)}finally{s()}}async function ft(e,r){if(e.runtime!=="cli")throw new Error("HTML capture is only available for --runtime cli sessions");if(!e.captureDir)throw new Error("CLI capture session has no captureDir");let i=new I(e.browserWsUrl);try{let t=await H(i,e.targetId);await i.send("Page.enable",{},t).catch(()=>{}),await i.send("Runtime.enable",{},t).catch(()=>{}),await B(i,t),await j(i,t,e.targetId,e.width,e.height);let n=await W(i,t),s=await mt(i,t,e.cliBlockVideos===!0),o=(e.cliScreens?.length??0)+1,d=y(e.captureDir,`html-${String(o).padStart(3,"0")}`),a=y(d,"index.html");await O(d,{recursive:!0}),await U(a,s,"utf8");let g={...e,cliScreens:[...e.cliScreens??[],{kind:"html",pngPath:null,htmlPath:a,viewport:n.viewport,naturalSize:n.viewport,sourceUrl:n.sourceUrl,title:n.title,click:r??n.click,scroll:n.scroll,capturedAt:new Date().toISOString()}],tabUrl:n.sourceUrl};return await i.send("Target.detachFromTarget",{sessionId:t}).catch(()=>{}),await _(g),g}finally{i.close()}}async function gt(e){await new Promise((r,i)=>{let t=Ke("ffmpeg",e,{stdio:["ignore","ignore","pipe"]}),n=[];t.stderr.on("data",s=>n.push(s)),t.on("error",i),t.on("close",s=>{if(s===0){r();return}i(new Error(`ffmpeg exited ${s}: ${Buffer.concat(n).toString("utf8").slice(-2e3)}`))})})}async function ht(e){let r=[...e.frames].sort((h,k)=>h.receivedAt-k.receivedAt),i=[],t=r[0]?.receivedAt;if(t!==void 0){let h=1e3/M,k=t;for(let A of r)A.receivedAt<k&&A!==r[r.length-1]||(i.push(A),k=A.receivedAt+h)}let n=i.slice(-Math.ceil(he/1e3*M)-2),s=n[0]?.receivedAt,o=n[n.length-1]?.receivedAt,d=s!==void 0&&o!==void 0?o-s:0;if(n.length<tt||d<nt||new Set(n.map(h=>h.data)).size<=1)return null;let a=Math.ceil(rt/1e3*M),g=n.length>=a?n:n.concat(Array.from({length:a-n.length},()=>n[n.length-1])),p=y(e.captureDir,`video-${String(e.index).padStart(3,"0")}`);await Ze(p,{recursive:!0,force:!0}).catch(()=>{}),await O(p,{recursive:!0});for(let[h,k]of g.entries())await U(y(p,`frame-${String(h+1).padStart(5,"0")}.png`),Buffer.from(k.data,"base64"));let m=y(p,"poster.png");await U(m,Buffer.from(n[0].data,"base64"));let b=y(e.captureDir,`video-${String(e.index).padStart(3,"0")}.webm`);await gt(["-y","-framerate",String(M),"-i",y(p,"frame-%05d.png"),"-c:v","libvpx-vp9","-pix_fmt","yuv420p","-deadline","realtime","-cpu-used","6",b]);let v=new Uint8Array(await F(m));return{videoPath:b,posterPngPath:m,naturalSize:J(v)??{width:fe,height:ge}}}async function we(e,r,i,t){if(!e.captureDir)throw new Error("CLI capture session has no captureDir");let n=Buffer.from(r,"base64"),s=(e.cliScreens?.length??0)+1,o=y(e.captureDir,`screen-${String(s).padStart(3,"0")}.png`);await O(e.captureDir,{recursive:!0}),await U(o,n);let d=J(n)??i.viewport,a={...e,cliScreens:[...e.cliScreens??[],{kind:"image",pngPath:o,viewport:i.viewport,naturalSize:d,sourceUrl:i.sourceUrl,title:i.title,click:t,scroll:i.scroll,capturedAt:new Date().toISOString()}],tabUrl:i.sourceUrl};return await _(a),a}async function wt(e,r,i,t,n){if(e.runtime!=="cli")throw new Error("video capture is only available for --runtime cli sessions");if(!e.captureDir)throw new Error("CLI capture session has no captureDir");let s=t??null,o=null;try{if(!s){o=new I(e.browserWsUrl);let p=await H(o,e.targetId);await o.send("Page.enable",{},p).catch(()=>{}),await o.send("Runtime.enable",{},p).catch(()=>{}),await B(o,p),await j(o,p,e.targetId,e.width,e.height),s=await W(o,p),await o.send("Target.detachFromTarget",{sessionId:p}).catch(()=>{})}let d=(e.cliScreens?.length??0)+1,a=await ht({frames:r,captureDir:e.captureDir,index:d});if(!a)return n&&t?we(e,n,t,i??null):ye(e,void 0,i,"click");let g={...e,cliScreens:[...e.cliScreens??[],{kind:"video",pngPath:a.posterPngPath,videoPath:a.videoPath,posterPngPath:a.posterPngPath,viewport:s.viewport,naturalSize:a.naturalSize,sourceUrl:s.sourceUrl,title:s.title,click:i??s.click,scroll:s.scroll,capturedAt:new Date().toISOString()}],tabUrl:s.sourceUrl};return await _(g),g}finally{o?.close()}}async function ye(e,r,i,t="click"){if(e.runtime!=="cli")throw new Error("capture is only available for --runtime cli sessions");if(!e.captureDir)throw new Error("CLI capture session has no captureDir");let n=new I(e.browserWsUrl);try{let s=await H(n,e.targetId);await n.send("Page.enable",{},s).catch(()=>{}),await n.send("Runtime.enable",{},s).catch(()=>{}),await B(n,s),await j(n,s,e.targetId,e.width,e.height);let o=await W(n,s),a=(await n.send("Page.captureScreenshot",{format:"png",fromSurface:!0,captureBeyondViewport:!1},s)).data;if(typeof a!="string")throw new Error("Page.captureScreenshot returned no data");let g=Buffer.from(a,"base64"),p=(e.cliScreens?.length??0)+1,m=y(e.captureDir,`screen-${String(p).padStart(3,"0")}.png`);await O(e.captureDir,{recursive:!0}),await U(m,g);let b=J(g)??o.viewport,v=t==="click"?i??o.click:null,h=r&&t==="click"?{...v??{x:.5,y:.5},label:r}:v,k={...e,cliScreens:[...e.cliScreens??[],{kind:"image",pngPath:m,viewport:o.viewport,naturalSize:b,sourceUrl:o.sourceUrl,title:o.title,click:h,scroll:o.scroll,capturedAt:new Date().toISOString()}],tabUrl:o.sourceUrl};return await n.send("Target.detachFromTarget",{sessionId:s}).catch(()=>{}),await _(k),k}finally{n.close()}}function be(){return y(process.env.INKLY_CAPTURE_AGENT_HOME||y(qe(),".inkly"),"capture-agent","sessions")}function ve(e){if(!/^[a-zA-Z0-9._:-]+$/.test(e))throw new Error(`invalid session id: ${e}`);return y(be(),`${e}.json`)}function yt(e){return y(be(),`${e}.listener.json`)}async function bt(e){try{let r=await F(yt(e),"utf8");return JSON.parse(r)}catch{return null}}async function _(e){await se(ve(e.id),`${JSON.stringify(e,null,2)}
319
- `)}async function x(e){let r=await F(ve(e),"utf8");return JSON.parse(r)}async function ke(e){let r=ot(e,"session",Qe),i=await x(r);if(i.runtime!=="cli")throw new Error("listen subcommand is only available for cli runtime sessions");let t=await bt(r),n=new I(i.browserWsUrl),s=null,o=i.targetId,d=Promise.resolve(),a=Promise.resolve(),g=0,p=new Set,m=[],b=!1,v=null,h=null,k=!1;async function A(u){s&&(await n.send("Page.stopScreencast",{},s).catch(()=>{}),await n.send("Target.detachFromTarget",{sessionId:s}).catch(()=>{})),m=[],b=!1,v=null,h=null,o=u,s=await H(n,u),await n.send("Page.enable",{},s).catch(()=>{}),await n.send("Runtime.enable",{},s).catch(()=>{});let w=await x(r).catch(()=>i);await j(n,s,u,w.width,w.height),await B(n,s,!0),m=[],b=!1,v=null,h=null;let c=await x(r).catch(()=>w);c.cliRecordVideo&&c.cliCaptureKind!=="html"&&await n.send("Page.startScreencast",{format:"png",quality:90,maxWidth:c.width,maxHeight:c.height,everyNthFrame:1},s).catch(f=>{process.stderr.write(`capture video start failed: ${f.message}
320
- `)});let l=await x(r).catch(()=>i);await _({...l,targetId:u,cliListenerPid:l.cliListenerPid??t?.cliListenerPid??null,cliListenerLogPath:l.cliListenerLogPath??t?.cliListenerLogPath??null,cliListenerReadyAt:l.cliListenerReadyAt??new Date().toISOString()})}async function R(u){k||(k=!0,s&&(await n.send("Page.stopScreencast",{},s).catch(()=>{}),await n.send("Target.detachFromTarget",{sessionId:s}).catch(()=>{})),n.close(),process.exit(u))}process.once("SIGTERM",()=>{R(0)}),process.once("SIGINT",()=>{R(0)}),await n.send("Target.setDiscoverTargets",{discover:!0}).catch(()=>{});for(let u of await ue(n).catch(()=>[]))p.add(u.targetId);await A(i.targetId);{let u=await x(r).catch(()=>i);await _({...u,targetId:o,cliListenerPid:u.cliListenerPid??t?.cliListenerPid??null,cliListenerLogPath:u.cliListenerLogPath??t?.cliListenerLogPath??null,cliListenerReadyAt:u.cliListenerReadyAt??new Date().toISOString()})}n.on("Target.targetCreated",u=>{let c=u.targetInfo;!c||c.type!=="page"||!(c.openerId===o||Date.now()<g)||(a=a.then(async()=>{await T(250),await A(c.targetId),p.add(c.targetId)}).catch(f=>{process.stderr.write(`capture target follow failed: ${f.message}
321
- `)}))}),n.on("Page.screencastFrame",(u,w)=>{if(w!==s)return;let c=u;typeof c.sessionId=="number"&&n.send("Page.screencastFrameAck",{sessionId:c.sessionId},w).catch(()=>{}),typeof c.data=="string"&&(m.push({data:c.data,receivedAt:Date.now()}),m.length>ae&&(m=m.slice(-ae)))});async function q(){let u=await ue(n).catch(()=>[]),w=u.find(c=>c.openerId===o)??u.find(c=>c.targetId!==o&&!p.has(c.targetId));for(let c of u)p.add(c.targetId);!w||w.targetId===o||await A(w.targetId)}async function Y(u){!u||!s||await n.send("Page.navigate",{url:u},s).catch(w=>{process.stderr.write(`capture post-click navigation failed: ${w.message}
322
- `)})}n.on("Runtime.bindingCalled",(u,w)=>{if(w!==s)return;let c=u;if(c.name!=="__inklyCliCaptureEvent"&&c.name!=="__inklyCliCaptureClick"||typeof c.payload!="string")return;let l=null;try{let f=JSON.parse(c.payload);c.name==="__inklyCliCaptureClick"?l={type:"click",click:f,page:null}:l={type:f.type==="input"||f.type==="scroll"?f.type:"click",click:typeof f.click=="object"&&f.click?f.click:null,page:typeof f.page=="object"&&f.page?f.page:null}}catch{l=null}if(l){if(l.type==="click")g=Date.now()+3e3;else{let f=Date.now();v=v??f,h=f,b=!0}d=d.then(async()=>{if(l.type!=="click")return;let f=Date.now(),E=v,X=h,Ce=b&&E!==null&&X!==null&&f-X<=et;b=!1,v=null,h=null;let Ae=Math.max(E?E-250:0,f-he),Pe=E?m.filter(S=>S.receivedAt>=Ae):[...m],z=l.page?.navigationUrl??null,L=m.length?m[m.length-1].data:null,D=l.page?{viewport:l.page.viewport,sourceUrl:l.page.url,title:l.page.title,click:l.click,scroll:l.page.scroll}:null;if(s&&(D||(D=await W(n,s).catch(()=>null)),!L)){let S=await n.send("Page.captureScreenshot",{format:"png",fromSurface:!0,captureBeyondViewport:!1},s).catch(()=>null),ee=S&&S.data;L=typeof ee=="string"?ee:null}m=[];let P=await x(r).catch(()=>null);if(!P||P.runtime!=="cli"){await R(0);return}if(P.cliCaptureKind==="html"){await T(z?500:2e3);let S=await ft(P,l.click);await N({session:S,stepKind:"html",action:l.type,click:l.click}),await Y(z),await T(2e3),await a,await q();return}if(await Y(z),await T(2e3),await a,await q(),P.cliRecordVideo&&Ce){let S=await wt(P,Pe,l.click,D??void 0,L);await N({session:S,stepKind:le(S),action:l.type,click:l.click});return}if(L&&D){let S=await we(P,L,D,l.click??null);await N({session:S,stepKind:"image",action:l.type,click:l.click});return}let Q=await ye(P,void 0,l.click,"click");await N({session:Q,stepKind:le(Q),action:l.type,click:l.click})}).catch(f=>{process.stderr.write(`capture listener failed: ${f.message}
323
- `)})}});let Se=setInterval(()=>{x(r).catch(()=>{clearInterval(Se),R(0)})},1e3);return await new Promise(()=>{}),0}async function kt(){let e=vt(process.argv.slice(2));process.exit(await ke(e))}kt().catch(e=>{process.stderr.write(`capture listener failed: ${e.message}
323
+ })()`,ce+15e3);return String(o)}finally{s()}}async function wn(e,t){if(e.runtime!=="cli")throw new Error("HTML capture is only available for --runtime cli sessions");if(!e.captureDir)throw new Error("CLI capture session has no captureDir");let n=new U(e.browserWsUrl);try{let r=await ee(n,e.targetId);await n.send("Page.enable",{},r).catch(()=>{}),await n.send("Runtime.enable",{},r).catch(()=>{}),await ne(n,r),await te(n,r,e.targetId,e.width,e.height);let i=await re(n,r),s=await gn(n,r,e.cliBlockVideos===!0),o=(e.cliScreens?.length??0)+1,u=x(e.captureDir,`html-${String(o).padStart(3,"0")}`),d=x(u,"index.html");await Y(u,{recursive:!0}),await W(d,s,"utf8");let g={...e,cliScreens:[...e.cliScreens??[],{kind:"html",pngPath:null,htmlPath:d,viewport:i.viewport,naturalSize:i.viewport,sourceUrl:i.sourceUrl,title:i.title,click:t??i.click,scroll:i.scroll,capturedAt:new Date().toISOString()}],tabUrl:i.sourceUrl};return await n.send("Target.detachFromTarget",{sessionId:r}).catch(()=>{}),await O(g),g}finally{n.close()}}async function yn(e){await new Promise((t,n)=>{let r=Vt("ffmpeg",e,{stdio:["ignore","ignore","pipe"]}),i=[];r.stderr.on("data",s=>i.push(s)),r.on("error",n),r.on("close",s=>{if(s===0){t();return}n(new Error(`ffmpeg exited ${s}: ${Buffer.concat(i).toString("utf8").slice(-2e3)}`))})})}function bn(e){if(e.length<=2)return e;let t=[],n=0;for(let s=1;s<e.length;s++)e[s].receivedAt-e[s-1].receivedAt>Qt&&(t.push({start:n,end:s-1}),n=s);t.push({start:n,end:e.length-1});let r=t[0],i=e[r.end].receivedAt-e[r.start].receivedAt;for(let s of t){let o=e[s.end].receivedAt-e[s.start].receivedAt;o>=i&&(r=s,i=o)}return e.slice(r.start,r.end+1)}async function vn(e){let t=e.fps,n=[...e.frames].sort((A,P)=>A.receivedAt-P.receivedAt),r=[],i=n[0]?.receivedAt;if(i!==void 0){let A=1e3/t,P=i;for(let _ of n)_.receivedAt<P&&_!==n[n.length-1]||(r.push(_),P=_.receivedAt+A)}let s=r.slice(-Math.ceil(Be/1e3*t)-2);if(process.env.INKLY_NAV_DEBUG){let A=s.map((P,_)=>_===0?0:P.receivedAt-s[_-1].receivedAt);process.stderr.write(`[navdbg] writeVideo: raw=${n.length} sampled=${r.length} preTrim=${s.length} gaps=${JSON.stringify(A)}
324
+ `)}let o=bn(s),u=o[0]?.receivedAt,d=o[o.length-1]?.receivedAt,g=u!==void 0&&d!==void 0?d-u:0;if(o.length<en||g<tn)return process.env.INKLY_NAV_DEBUG&&process.stderr.write(`[navdbg] video reject: frames=${o.length} durationMs=${g}
325
+ `),null;if(new Set(o.map(A=>A.data)).size<=1)return process.env.INKLY_NAV_DEBUG&&process.stderr.write(`[navdbg] video reject: frozen (all ${o.length} frames identical)
326
+ `),null;let b=Math.round(rn/1e3*t),c=Array.from({length:b},()=>o[0]).concat(o),w=Math.ceil(nn/1e3*t),v=c.length>=w?c:c.concat(Array.from({length:w-c.length},()=>c[c.length-1])),S=x(e.captureDir,`video-${String(e.index).padStart(3,"0")}`);await qt(S,{recursive:!0,force:!0}).catch(()=>{}),await Y(S,{recursive:!0});for(let[A,P]of v.entries())await W(x(S,`frame-${String(A+1).padStart(5,"0")}.png`),Buffer.from(P.data,"base64"));let C=x(S,"poster.png");await W(C,Buffer.from(o[0].data,"base64"));let y=x(e.captureDir,`video-${String(e.index).padStart(3,"0")}.webm`);await yn(["-y","-framerate",String(t),"-i",x(S,"frame-%05d.png"),"-c:v","libvpx-vp9","-pix_fmt","yuv420p","-deadline","realtime","-cpu-used","6",y]);let L=new Uint8Array(await Q(C));return{videoPath:y,posterPngPath:C,naturalSize:pe(L)??{width:He,height:je}}}async function Ve(e,t,n,r){if(!e.captureDir)throw new Error("CLI capture session has no captureDir");let i=Buffer.from(t,"base64"),s=(e.cliScreens?.length??0)+1,o=x(e.captureDir,`screen-${String(s).padStart(3,"0")}.png`);await Y(e.captureDir,{recursive:!0}),await W(o,i);let u=pe(i)??n.viewport,d={...e,cliScreens:[...e.cliScreens??[],{kind:"image",pngPath:o,viewport:n.viewport,naturalSize:u,sourceUrl:n.sourceUrl,title:n.title,click:r,scroll:n.scroll,capturedAt:new Date().toISOString()}],tabUrl:n.sourceUrl};return await O(d),d}async function kn(e,t,n,r,i){if(e.runtime!=="cli")throw new Error("video capture is only available for --runtime cli sessions");if(!e.captureDir)throw new Error("CLI capture session has no captureDir");let s=r??null,o=null;try{if(!s){o=new U(e.browserWsUrl);let c=await ee(o,e.targetId);await o.send("Page.enable",{},c).catch(()=>{}),await o.send("Runtime.enable",{},c).catch(()=>{}),await ne(o,c),await te(o,c,e.targetId,e.width,e.height),s=await re(o,c),await o.send("Target.detachFromTarget",{sessionId:c}).catch(()=>{})}let u=(e.cliScreens?.length??0)+1,d=e.cliHeadless?We:Xt,g=await vn({frames:t,captureDir:e.captureDir,index:u,fps:d});if(!g)return i&&r?Ve(e,i,r,n??null):qe(e,void 0,n,"click");let b={...e,cliScreens:[...e.cliScreens??[],{kind:"video",pngPath:g.posterPngPath,videoPath:g.videoPath,posterPngPath:g.posterPngPath,viewport:s.viewport,naturalSize:g.naturalSize,sourceUrl:s.sourceUrl,title:s.title,click:n??s.click,scroll:s.scroll,capturedAt:new Date().toISOString()}],tabUrl:s.sourceUrl};return await O(b),b}finally{o?.close()}}async function qe(e,t,n,r="click"){if(e.runtime!=="cli")throw new Error("capture is only available for --runtime cli sessions");if(!e.captureDir)throw new Error("CLI capture session has no captureDir");let i=new U(e.browserWsUrl);try{let s=await ee(i,e.targetId);await i.send("Page.enable",{},s).catch(()=>{}),await i.send("Runtime.enable",{},s).catch(()=>{}),await ne(i,s),await te(i,s,e.targetId,e.width,e.height);let o=await re(i,s),d=(await i.send("Page.captureScreenshot",{format:"png",fromSurface:!0,captureBeyondViewport:!1},s)).data;if(typeof d!="string")throw new Error("Page.captureScreenshot returned no data");let g=Buffer.from(d,"base64"),b=(e.cliScreens?.length??0)+1,c=x(e.captureDir,`screen-${String(b).padStart(3,"0")}.png`);await Y(e.captureDir,{recursive:!0}),await W(c,g);let w=pe(g)??o.viewport,v=r==="click"?n??o.click:null,S=t&&r==="click"?{...v??{x:.5,y:.5},label:t}:v,C={...e,cliScreens:[...e.cliScreens??[],{kind:"image",pngPath:c,viewport:o.viewport,naturalSize:w,sourceUrl:o.sourceUrl,title:o.title,click:S,scroll:o.scroll,capturedAt:new Date().toISOString()}],tabUrl:o.sourceUrl};return await i.send("Target.detachFromTarget",{sessionId:s}).catch(()=>{}),await O(C),C}finally{i.close()}}function ze(){return x(process.env.INKLY_CAPTURE_AGENT_HOME||x(Gt(),".inkly"),"capture-agent","sessions")}function Ge(e){if(!/^[a-zA-Z0-9._:-]+$/.test(e))throw new Error(`invalid session id: ${e}`);return x(ze(),`${e}.json`)}function Sn(e){return x(ze(),`${e}.listener.json`)}async function Pn(e){try{let t=await Q(Sn(e),"utf8");return JSON.parse(t)}catch{return null}}async function O(e){await ve(Ge(e.id),`${JSON.stringify(e,null,2)}
327
+ `)}async function D(e){let t=await Q(Ge(e),"utf8");return JSON.parse(t)}async function Ke(e){let t=cn(e,"session",Zt),n=await D(t);if(n.runtime!=="cli")throw new Error("listen subcommand is only available for cli runtime sessions");let r=await Pn(t);process.stderr.write(`capture listener: session ${t} connecting to ${n.browserWsUrl}
328
+ `);let i=new U(n.browserWsUrl),s=null,o=n.targetId,u=Promise.resolve(),d=Promise.resolve(),g=0,b=new Set,c=[],w=!1,v=null,S=null,C=!1,y=null,L=null;async function A(m){s&&(await i.send("Page.stopScreencast",{},s).catch(()=>{}),await i.send("Target.detachFromTarget",{sessionId:s}).catch(()=>{})),c=[],w=!1,v=null,S=null,o=m,s=await ee(i,m),await i.send("Page.enable",{},s).catch(()=>{}),await i.send("Runtime.enable",{},s).catch(()=>{});let h=await D(t).catch(()=>n);await te(i,s,m,h.width,h.height),await ne(i,s,!0),c=[],w=!1,v=null,S=null;let a=await D(t).catch(()=>h);a.cliRecordVideo&&a.cliCaptureKind!=="html"&&await i.send("Page.startScreencast",{format:"png",quality:90,maxWidth:a.width,maxHeight:a.height,everyNthFrame:1},s).catch(l=>{process.stderr.write(`capture video start failed: ${l.message}
329
+ `)});let p=await D(t).catch(()=>n);await O({...p,targetId:m,cliListenerPid:p.cliListenerPid??r?.cliListenerPid??null,cliListenerLogPath:p.cliListenerLogPath??r?.cliListenerLogPath??null,cliListenerReadyAt:p.cliListenerReadyAt??new Date().toISOString()})}async function P(m){C||(C=!0,L&&(await L.close().catch(()=>{}),L=null),y&&(await y.close().catch(()=>{}),y=null),s&&(await i.send("Page.stopScreencast",{},s).catch(()=>{}),await i.send("Target.detachFromTarget",{sessionId:s}).catch(()=>{})),i.close(),process.exit(m))}process.once("SIGTERM",()=>{P(0)}),process.once("SIGINT",()=>{P(0)}),await i.send("Target.setDiscoverTargets",{discover:!0}).catch(()=>{});for(let m of await Ne(i).catch(()=>[]))b.add(m.targetId);await A(n.targetId);{let m=await D(t).catch(()=>n);await O({...m,targetId:o,cliListenerPid:m.cliListenerPid??r?.cliListenerPid??null,cliListenerLogPath:m.cliListenerLogPath??r?.cliListenerLogPath??null,cliListenerReadyAt:m.cliListenerReadyAt??new Date().toISOString()})}process.stderr.write(`capture listener: session ${t} armed and recording
330
+ `);let _=async m=>{let h=await i.send("Page.captureScreenshot",{format:"png"},m).catch(()=>null),a=h&&h.data;typeof a=="string"&&(c.push({data:a,receivedAt:Date.now()}),c.length>J&&(c=c.slice(-J)))};try{y=new K(n.browserWsUrl,o),await y.init(),L=await Ie(Me(t),async m=>{if(!y)throw new Error("nav driver unavailable");let h=y,a=m.params??{},p=async l=>{if(a.noSnapshot===!0)return l;try{await h.wait({type:"load",arg:"load",timeoutMs:5e3}).catch(()=>{});let f=await h.agentSnapshot();return{...l,snapshot:f}}catch{return l}};switch(m.command){case"snapshot":return y.snapshot({trim:a.full!==!0,filter:typeof a.filter=="string"?a.filter:void 0,maxDepth:typeof a.maxDepth=="number"?a.maxDepth:void 0,includeMaps:a.json===!0});case"click":{let l=a.selector;if(typeof l!="string"||!l)throw new Error("nav click requires a selector");let f=(await X(t)).steps??0;if(s){let $=s,q=n.cliHeadless?()=>_($):void 0;await Cn(i,$,h.resolveRef(l),{width:n.width,height:n.height},q).catch(()=>{})}let k=await h.click(l),E=await $e(t,f);return p({...k,steps:E.steps,lastLabel:E.lastLabel})}case"fill":{let l=a.selector,f=a.value;if(typeof l!="string"||!l)throw new Error("nav fill requires a selector");if(typeof f!="string")throw new Error("nav fill requires a value");return p(await h.fill(l,f,a.pressEnter===!0))}case"type":{let l=a.text;if(typeof l!="string")throw new Error("nav type requires text");return p(await h.type(l,typeof a.delay=="number"?a.delay:void 0))}case"key":{let l=a.key;if(typeof l!="string"||!l)throw new Error("nav press requires a key");return p(await h.key(l))}case"select":{let l=a.selector,f=a.values;if(typeof l!="string"||!l)throw new Error("nav select requires a selector");if(!Array.isArray(f)||f.some(k=>typeof k!="string"))throw new Error("nav select requires one or more string values");return p(await h.select(l,f))}case"upload":{let l=a.selector,f=a.files;if(typeof l!="string"||!l)throw new Error("nav upload requires a selector");if(!Array.isArray(f)||f.length===0||f.some(k=>typeof k!="string"))throw new Error("nav upload requires one or more file paths");return y.upload(l,f)}case"get":{let l=a.what;if(typeof l!="string"||!l)throw new Error("nav get requires a target");return y.get(l,typeof a.selector=="string"?a.selector:void 0)}case"is":{let l=a.check,f=a.selector;if(typeof l!="string"||!l)throw new Error("nav is requires a check");if(typeof f!="string"||!f)throw new Error("nav is requires a selector");return y.is(l,f)}case"wait":{let l=a.type;if(typeof l!="string"||!l)throw new Error("nav wait requires a type");return y.wait({type:l,arg:typeof a.arg=="string"?a.arg:void 0,state:typeof a.state=="string"?a.state:void 0,timeoutMs:typeof a.timeoutMs=="number"?a.timeoutMs:void 0})}case"back":return p(await h.back({waitUntil:typeof a.waitUntil=="string"?a.waitUntil:void 0,timeoutMs:typeof a.timeoutMs=="number"?a.timeoutMs:void 0}));case"forward":return p(await h.forward({waitUntil:typeof a.waitUntil=="string"?a.waitUntil:void 0,timeoutMs:typeof a.timeoutMs=="number"?a.timeoutMs:void 0}));case"reload":return p(await h.reload({waitUntil:typeof a.waitUntil=="string"?a.waitUntil:void 0,timeoutMs:typeof a.timeoutMs=="number"?a.timeoutMs:void 0}));case"scroll":{let l=a.direction==="up"?"up":"down",f=typeof a.amount=="number"&&a.amount>0?a.amount:_e;if(s){let k=s,E=n.cliHeadless?()=>_(k):void 0;await Je(i,k,l,f,{width:n.width,height:n.height},E)}else await h.scroll(l,f);return p({scrolled:!0,direction:l,amount:f})}case"refs":return y.refs();case"mouse.click":{let l=a.x,f=a.y;if(typeof l!="number"||typeof f!="number")throw new Error("nav mouse click requires numeric x and y");let k=(await X(t)).steps??0,E=await h.mouseClick(l,f,{button:typeof a.button=="string"?a.button:void 0,clickCount:typeof a.clickCount=="number"?a.clickCount:void 0}),$=await $e(t,k);return p({...E,steps:$.steps,lastLabel:$.lastLabel})}case"mouse.hover":{let l=a.x,f=a.y;if(typeof l!="number"||typeof f!="number")throw new Error("nav mouse hover requires numeric x and y");return y.mouseHover(l,f)}case"mouse.scroll":{let l=a.x,f=a.y,k=a.deltaX,E=a.deltaY;if(typeof l!="number"||typeof f!="number"||typeof k!="number"||typeof E!="number")throw new Error("nav mouse scroll requires numeric x, y, deltaX, deltaY");return p(await h.mouseScroll(l,f,k,E))}default:throw new Error(`unknown nav command: ${m.command}`)}})}catch(m){process.stderr.write(`capture nav driver init failed: ${m.message}
331
+ `),y&&(await y.close().catch(()=>{}),y=null)}i.on("Target.targetCreated",m=>{let a=m.targetInfo;!a||a.type!=="page"||!(a.openerId===o||Date.now()<g)||(d=d.then(async()=>{await N(250),await A(a.targetId),b.add(a.targetId)}).catch(l=>{process.stderr.write(`capture target follow failed: ${l.message}
332
+ `)}))}),i.on("Page.screencastFrame",(m,h)=>{if(h!==s)return;let a=m;typeof a.sessionId=="number"&&i.send("Page.screencastFrameAck",{sessionId:a.sessionId},h).catch(()=>{}),typeof a.data=="string"&&(c.push({data:a.data,receivedAt:Date.now()}),c.length>J&&(c=c.slice(-J)))});async function V(){let m=await Ne(i).catch(()=>[]),h=m.find(a=>a.openerId===o)??m.find(a=>a.targetId!==o&&!b.has(a.targetId));for(let a of m)b.add(a.targetId);!h||h.targetId===o||await A(h.targetId)}async function fe(m){!m||!s||await i.send("Page.navigate",{url:m},s).catch(h=>{process.stderr.write(`capture post-click navigation failed: ${h.message}
333
+ `)})}i.on("Runtime.bindingCalled",(m,h)=>{if(h!==s)return;let a=m;if(a.name!=="__inklyCliCaptureEvent"&&a.name!=="__inklyCliCaptureClick"||typeof a.payload!="string")return;let p=null;try{let l=JSON.parse(a.payload);a.name==="__inklyCliCaptureClick"?p={type:"click",click:l,page:null}:p={type:l.type==="input"||l.type==="scroll"?l.type:"click",click:typeof l.click=="object"&&l.click?l.click:null,page:typeof l.page=="object"&&l.page?l.page:null}}catch{p=null}if(p){if(p.type==="click")g=Date.now()+3e3;else{let l=Date.now();v=v??l,S=l,w=!0}u=u.then(async()=>{if(p.type!=="click")return;let l=Date.now(),f=v,k=S,E=w&&f!==null&&k!==null&&l-k<=Yt;w=!1,v=null,S=null;let $=Math.max(f?f-250:0,l-Be),q=f?c.filter(T=>T.receivedAt>=$):[...c],ie=p.page?.navigationUrl??null;process.env.INKLY_NAV_DEBUG&&process.stderr.write(`[navdbg] click: attachVideo=${E} hadMotion=${w} motionStart=${f} bufFrames=${c.length} segFrames=${q.length} sinceMotion=${k?l-k:"n/a"}
334
+ `);let F=c.length?c[c.length-1].data:null,H=p.page?{viewport:p.page.viewport,sourceUrl:p.page.url,title:p.page.title,click:p.click,scroll:p.page.scroll}:null;if(s&&(H||(H=await re(i,s).catch(()=>null)),!F)){let T=await i.send("Page.captureScreenshot",{format:"png",fromSurface:!0,captureBeyondViewport:!1},s).catch(()=>null),he=T&&T.data;F=typeof he=="string"?he:null}c=[];let R=await D(t).catch(()=>null);if(!R||R.runtime!=="cli"){await P(0);return}if(R.cliCaptureKind==="html"){await N(ie?500:2e3);let T=await wn(R,p.click);await Z({session:T,stepKind:"html",action:p.type,click:p.click}),await fe(ie),await N(2e3),await d,await V();return}if(await fe(ie),await N(2e3),await d,await V(),R.cliRecordVideo&&E){let T=await kn(R,q,p.click,H??void 0,F);await Z({session:T,stepKind:Re(T),action:p.type,click:p.click});return}if(F&&H){let T=await Ve(R,F,H,p.click??null);await Z({session:T,stepKind:"image",action:p.type,click:p.click});return}let me=await qe(R,void 0,p.click,"click");await Z({session:me,stepKind:Re(me),action:p.type,click:p.click})}).catch(l=>{process.stderr.write(`capture listener failed: ${l.message}
335
+ `)})}});let Ze=setInterval(()=>{D(t).catch(()=>{clearInterval(Ze),P(0)})},1e3);return await new Promise(()=>{}),0}async function X(e){let n=(await D(e).catch(()=>null))?.cliScreens??[],r=n[n.length-1];return{steps:n.length,lastLabel:r&&(r.click?.label||r.title)||null,lastKind:r?.kind??null}}async function Je(e,t,n,r,i,s){let o=!!s,u=o?on:90,d=1800,g=o?6e3:5e3,b=110,c=Math.round(i.width/2),w=Math.round(i.height/2),v=Math.max(u,Math.round(Math.abs(r))),S=n==="up"?-1:1,C=Math.ceil(v/u),y=Math.max(1,C-1),L=Math.min(Math.round(g/y),Math.max(b,Math.round(d/y)));await e.send("Input.dispatchMouseEvent",{type:"mouseMoved",x:c,y:w,button:"none"},t).catch(()=>{});let A=Date.now(),P=v;for(let _=0;_<C&&!(Date.now()-A>g);_+=1){let V=Math.min(u,P)*S;P-=u,await e.send("Input.dispatchMouseEvent",{type:"mouseWheel",x:c,y:w,deltaX:0,deltaY:V,button:"none"},t).catch(()=>{}),s&&await s(),!o&&_<C-1&&await N(L)}}async function Cn(e,t,n,r,i){if(!n.startsWith("/"))return!1;let s=`(()=>{try{const el=document.evaluate(${JSON.stringify(n)},document,null,9,null).singleNodeValue;if(!el)return null;const r=el.getBoundingClientRect();const vh=window.innerHeight||${r.height};if(r.width<=0&&r.height<=0)return null;if(r.top>=0&&r.bottom<=vh)return 0;return Math.round(r.top-vh*0.2);}catch{return null;}})()`,o=await e.send("Runtime.evaluate",{expression:s,returnByValue:!0},t).catch(()=>null),u=o&&o.result?.value;return typeof u!="number"||Math.abs(u)<48?!1:(await Je(e,t,u>0?"down":"up",Math.abs(u),r,i),!0)}async function $e(e,t,n=7e3){let r=Date.now()+n,i=await X(e);for(;(i.steps??0)<=t&&Date.now()<r;)await N(200),i=await X(e);return i}async function xn(){let e=An(process.argv.slice(2));process.exit(await Ke(e))}xn().catch(e=>{process.stderr.write(`capture listener failed: ${e.message}
324
336
  `),process.exit(1)});