@inkly-org/cli 0.5.3 → 0.5.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/capture-listener.js +16 -16
- package/dist/singlefile-injected.js +15136 -0
- package/package.json +1 -1
package/dist/capture-listener.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import vt from"mri";import{spawn as
|
|
3
|
-
`,{encoding:"utf8",mode:384})}async function
|
|
2
|
+
import vt from"mri";import{spawn as Ze}from"child_process";import{createHash as Ft,randomUUID as Ht}from"crypto";import{mkdir as O,mkdtemp as Bt,open as Wt,readFile as F,readdir as zt,rm as Ke,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 Kt}from"path";import{tmpdir as qt,homedir as qe}from"os";import{fileURLToPath as Ye}from"url";import{unzipSync as Qt,zipSync as en}from"fflate";import Xe from"ws";import rn from"sharp";import on from"subset-font";import{zipSync as At}from"fflate";import{JSDOM as un}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 De}from"path";import{homedir as Le}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=De(Le(),".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:
|
|
4
4
|
--url <url> URL to open and arm for recording.
|
|
5
5
|
--name <name> Demo name written into the exported ZIP.
|
|
6
6
|
--session <id> Session id printed by start.
|
|
@@ -20,7 +20,7 @@ import vt from"mri";import{spawn as Ve}from"child_process";import{createHash as
|
|
|
20
20
|
done once in this profile survives, so later captures of the same site need
|
|
21
21
|
no re-login. Implies --keep-profile. Run --headed the first time so the user
|
|
22
22
|
can sign in; reuse can run headless.
|
|
23
|
-
--no-unpack On stop, write only the ZIP.`,
|
|
23
|
+
--no-unpack On stop, write only the ZIP.`,Qe=`inkly capture - capture an image/video walkthrough for an external browser agent
|
|
24
24
|
|
|
25
25
|
Usage:
|
|
26
26
|
inkly capture start --url <url> --name <name>
|
|
@@ -28,7 +28,7 @@ Usage:
|
|
|
28
28
|
inkly capture cancel --session <id>
|
|
29
29
|
inkly capture profiles
|
|
30
30
|
|
|
31
|
-
${
|
|
31
|
+
${me}
|
|
32
32
|
--video, --record-video Record motion segments. Enabled by default; use --no-video to disable.
|
|
33
33
|
--zoom Apply click zoom/pan to screenshot steps. Enabled by default; use --no-zoom to disable.
|
|
34
34
|
--compress-images Re-encode captured PNG/JPEG screenshots to WebP (smaller, near-lossless).
|
|
@@ -45,19 +45,19 @@ Usage:
|
|
|
45
45
|
inkly capture-html cancel --session <id>
|
|
46
46
|
inkly capture-html profiles
|
|
47
47
|
|
|
48
|
-
${
|
|
48
|
+
${me}
|
|
49
49
|
--block-videos Replace <video> with its poster frame instead of inlining the video.
|
|
50
50
|
|
|
51
51
|
Output:
|
|
52
52
|
Every subcommand prints JSON. This command does not accept prompts and does not plan or drive the page.
|
|
53
|
-
`,
|
|
53
|
+
`,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>
|
|
54
54
|
|
|
55
|
-
${i}`);return
|
|
55
|
+
${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 S(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 S(e,r,`JSON.stringify({
|
|
56
56
|
innerWidth: window.innerWidth,
|
|
57
57
|
innerHeight: window.innerHeight,
|
|
58
58
|
outerWidth: window.outerWidth,
|
|
59
59
|
outerHeight: window.outerHeight
|
|
60
|
-
})`,5e3),
|
|
60
|
+
})`,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 Z=`(() => {
|
|
61
61
|
if (window.__inklyCliRecorderInstalled) return;
|
|
62
62
|
window.__inklyCliRecorderInstalled = true;
|
|
63
63
|
window.__inklyCliLastClick = null;
|
|
@@ -252,7 +252,7 @@ function selectorFor(el) {
|
|
|
252
252
|
maxX: Math.max(0, document.documentElement.scrollWidth - window.innerWidth),
|
|
253
253
|
maxY: Math.max(0, document.documentElement.scrollHeight - window.innerHeight)
|
|
254
254
|
}
|
|
255
|
-
})`,5e3),
|
|
255
|
+
})`,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},K="__inklySingleFileFetch",ut=`(() => {
|
|
256
256
|
if (globalThis.__inklyFetchInstalled) return;
|
|
257
257
|
globalThis.__inklyFetchInstalled = true;
|
|
258
258
|
const pending = new Map();
|
|
@@ -295,7 +295,7 @@ function selectorFor(el) {
|
|
|
295
295
|
return viaNode(url, options);
|
|
296
296
|
}
|
|
297
297
|
};
|
|
298
|
-
})();`;function dt(e,r){let i,n
|
|
298
|
+
})();`;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 S(e,r,`globalThis.__inklyResolveFetch(${n}, ${JSON.stringify(m)})`,2e4)}catch(s){if(n===void 0)return;await S(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:K},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!==K||typeof a.payload!="string"||pt(e,r,a.payload,n)});try{await S(e,r,t,3e4),await S(e,r,ut,1e4);let o=await S(e,r,`(async () => {
|
|
299
299
|
const sf = globalThis.__inklySingleFile;
|
|
300
300
|
if (!sf || typeof sf.getPageData !== "function") throw new Error("SingleFile not loaded");
|
|
301
301
|
// initOptions (2nd arg) is forwarded to single-file-core/core/util.js
|
|
@@ -311,10 +311,10 @@ function selectorFor(el) {
|
|
|
311
311
|
]);
|
|
312
312
|
if (typeof data.content === "string") return data.content;
|
|
313
313
|
return new TextDecoder().decode(new Uint8Array(data.content));
|
|
314
|
-
})()`,G+15e3);return String(
|
|
315
|
-
`)}async function x(e){let r=await F(
|
|
316
|
-
`)});let l=await x(r).catch(()=>i);await _({...l,targetId:u,cliListenerPid:l.cliListenerPid??
|
|
317
|
-
`)}))}),
|
|
318
|
-
`)})}
|
|
319
|
-
`)})}});let
|
|
314
|
+
})()`,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=Ze("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 Ke(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)}
|
|
315
|
+
`)}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}
|
|
316
|
+
`)});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}
|
|
317
|
+
`)}))}),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}
|
|
318
|
+
`)})}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,Se=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(C=>C.receivedAt>=Ae):[...m],z=l.page?.navigationUrl??null,D=m.length?m[m.length-1].data:null,L=l.page?{viewport:l.page.viewport,sourceUrl:l.page.url,title:l.page.title,click:l.click,scroll:l.page.scroll}:null;if(s&&(L||(L=await W(n,s).catch(()=>null)),!D)){let C=await n.send("Page.captureScreenshot",{format:"png",fromSurface:!0,captureBeyondViewport:!1},s).catch(()=>null),ee=C&&C.data;D=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 C=await ft(P,l.click);await N({session:C,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&&Se){let C=await wt(P,Pe,l.click,L??void 0,D);await N({session:C,stepKind:le(C),action:l.type,click:l.click});return}if(D&&L){let C=await we(P,D,L,l.click??null);await N({session:C,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}
|
|
319
|
+
`)})}});let Ce=setInterval(()=>{x(r).catch(()=>{clearInterval(Ce),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}
|
|
320
320
|
`),process.exit(1)});
|