agentiqa 1.1.4 → 1.1.5-staging.de8a89b

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 (2) hide show
  1. package/dist/cli.js +14 -8
  2. package/package.json +1 -1
package/dist/cli.js CHANGED
@@ -1408,7 +1408,7 @@ Install manually: npx playwright install chromium
1408
1408
  Error: ${e.message}`)}}else throw r}}import{execSync as eR}from"node:child_process";function Ug(r){process.stderr.write(`[agentiqa] ${r}
1409
1409
  `)}async function Fg(){try{let{createRequire:r}=await import("node:module");r(import.meta.url).resolve("@mobilenext/mobile-mcp/lib/index.js")}catch{Ug("@mobilenext/mobile-mcp not found, installing...");try{eR("npm install -g @mobilenext/mobile-mcp @modelcontextprotocol/sdk",{stdio:["ignore","pipe","pipe"],timeout:12e4}),Ug("@mobilenext/mobile-mcp installed")}catch(r){throw new Error(`Failed to install @mobilenext/mobile-mcp.
1410
1410
  Install manually: npm install -g @mobilenext/mobile-mcp
1411
- Error: ${r.message}`)}}}import tR from"ws";function Ks(){let r=process.env.AGENTIQA_ENGINE_TOKEN;return{"Content-Type":"application/json",...r?{Authorization:`Bearer ${r}`}:{}}}async function Ea(r,e){let t=await fetch(`${r}${Wr.createSession()}`,{method:"POST",headers:Ks(),body:JSON.stringify(e)});if(!t.ok){let s=await t.text();throw new Error(`Failed to create session: ${t.status} ${s}`)}return{sessionId:(await t.json()).sessionId}}function ka(r,e){let t=r.replace(/^http/,"ws"),n=process.env.AGENTIQA_ENGINE_TOKEN,s=n?`&token=${encodeURIComponent(n)}`:"";return`${t}/ws?session=${e}${s}`}async function Rl(r,e,t){let n=await fetch(`${r}${Wr.agentMessage(e)}`,{method:"POST",headers:Ks(),body:JSON.stringify({text:t})});if(!n.ok){let s=await n.text();throw new Error(`Failed to send message: ${n.status} ${s}`)}}async function Aa(r,e,t){let n=await fetch(`${r}${Wr.addCredentials(e)}`,{method:"POST",headers:Ks(),body:JSON.stringify({credentials:t})});if(!n.ok){let s=await n.text();throw new Error(`Failed to send credentials: ${n.status} ${s}`)}}async function qg(r,e,t,n){let s=await fetch(`${r}${Wr.runTestPlan(e)}`,{method:"POST",headers:Ks(),body:JSON.stringify({testPlan:t,...n?{initialMemory:n}:{}})});if(!s.ok){let o=await s.text();throw new Error(`Failed to start run: ${s.status} ${o}`)}}async function cn(r,e){await fetch(`${r}${Wr.deleteSession(e)}`,{method:"DELETE",headers:Ks()})}function Bg(r,e,t){return new Promise((n,s)=>{let o=t?[`agentiqa.jwt.${t}`]:void 0,a=new tR(r,o);a.on("open",()=>{}),a.on("message",i=>{try{let c=JSON.parse(i.toString());switch(c.type){case"action:progress":e.onActionProgress?.(c);break;case"message:added":e.onMessageAdded?.(c);break;case"screencast:frame":e.onScreencastFrame?.(c);break;case"screencast:stopped":e.onScreencastStopped?.(c);break;case"session:stopped":e.onSessionStopped?.(c),a.close(),n();break;case"session:status-changed":(c.status==="stopped"||c.status==="idle")&&(e.onSessionStopped?.(c),a.close(),n());break;case"session:error":e.onSessionError?.(c),a.close(),n();break;case"run:completed":e.onRunCompleted?.(c);break}}catch{}}),a.on("error",i=>{e.onError?.(i),s(i)}),a.on("close",()=>{n()})})}var Ur="\x1B[1m",Fr="\x1B[2m",st="\x1B[0m",Ca="\x1B[31m",Ra="\x1B[33m",Vg="\x1B[32m",Ma="\x1B[36m";function rR(r){return r==="high"?Ca:r==="medium"?Ra:Fr}function nR(r){return r==="clean"?`${Vg}clean${st}`:r==="issues_found"?`${Ca}issues_found${st}`:r}function Hg(r,e){if(e)return JSON.stringify(r,null,2);let t=[],n=`${Fr}${"\u2501".repeat(60)}${st}`;return t.push(""),t.push(n),t.push(`${Ur}${r.title}${st}`),t.push(n),r.type==="scope"?sR(t,r.data):r.type==="findings"?aR(t,r.data):r.type==="plan"&&oR(t,r.data),t.push(""),t.join(`
1411
+ Error: ${r.message}`)}}}import tR from"ws";function Ks(r){let e=process.env.AGENTIQA_ENGINE_TOKEN;return e?{"Content-Type":"application/json",Authorization:`Bearer ${e}`}:r?{"Content-Type":"application/json","x-session-token":r}:{"Content-Type":"application/json"}}async function Ea(r,e,t){let n=await fetch(`${r}${Wr.createSession()}`,{method:"POST",headers:Ks(t),body:JSON.stringify(e)});if(!n.ok){let o=await n.text();throw new Error(`Failed to create session: ${n.status} ${o}`)}return{sessionId:(await n.json()).sessionId}}function ka(r,e){let t=r.replace(/^http/,"ws"),n=process.env.AGENTIQA_ENGINE_TOKEN,s=n?`&token=${encodeURIComponent(n)}`:"";return`${t}/ws?session=${e}${s}`}async function Rl(r,e,t,n){let s=await fetch(`${r}${Wr.agentMessage(e)}`,{method:"POST",headers:Ks(n),body:JSON.stringify({text:t})});if(!s.ok){let o=await s.text();throw new Error(`Failed to send message: ${s.status} ${o}`)}}async function Aa(r,e,t,n){let s=await fetch(`${r}${Wr.addCredentials(e)}`,{method:"POST",headers:Ks(n),body:JSON.stringify({credentials:t})});if(!s.ok){let o=await s.text();throw new Error(`Failed to send credentials: ${s.status} ${o}`)}}async function qg(r,e,t,n,s){let o=await fetch(`${r}${Wr.runTestPlan(e)}`,{method:"POST",headers:Ks(s),body:JSON.stringify({testPlan:t,...n?{initialMemory:n}:{}})});if(!o.ok){let a=await o.text();throw new Error(`Failed to start run: ${o.status} ${a}`)}}async function cn(r,e,t){await fetch(`${r}${Wr.deleteSession(e)}`,{method:"DELETE",headers:Ks(t)})}function Bg(r,e,t){return new Promise((n,s)=>{let o=t?[`agentiqa.jwt.${t}`]:void 0,a=new tR(r,o);a.on("open",()=>{}),a.on("message",i=>{try{let c=JSON.parse(i.toString());switch(c.type){case"action:progress":e.onActionProgress?.(c);break;case"message:added":e.onMessageAdded?.(c);break;case"screencast:frame":e.onScreencastFrame?.(c);break;case"screencast:stopped":e.onScreencastStopped?.(c);break;case"session:stopped":e.onSessionStopped?.(c),a.close(),n();break;case"session:status-changed":(c.status==="stopped"||c.status==="idle")&&(e.onSessionStopped?.(c),a.close(),n());break;case"session:error":e.onSessionError?.(c),a.close(),n();break;case"run:completed":e.onRunCompleted?.(c);break}}catch{}}),a.on("error",i=>{e.onError?.(i),s(i)}),a.on("close",()=>{n()})})}var Ur="\x1B[1m",Fr="\x1B[2m",st="\x1B[0m",Ca="\x1B[31m",Ra="\x1B[33m",Vg="\x1B[32m",Ma="\x1B[36m";function rR(r){return r==="high"?Ca:r==="medium"?Ra:Fr}function nR(r){return r==="clean"?`${Vg}clean${st}`:r==="issues_found"?`${Ca}issues_found${st}`:r}function Hg(r,e){if(e)return JSON.stringify(r,null,2);let t=[],n=`${Fr}${"\u2501".repeat(60)}${st}`;return t.push(""),t.push(n),t.push(`${Ur}${r.title}${st}`),t.push(n),r.type==="scope"?sR(t,r.data):r.type==="findings"?aR(t,r.data):r.type==="plan"&&oR(t,r.data),t.push(""),t.join(`
1412
1412
  `)}function sR(r,e){let t=e.areas||[];if(t.length){r.push(""),r.push(` ${Fr}# Area${" ".repeat(24)}Risk Auth URL${st}`);for(let s=0;s<t.length;s++){let o=t[s],a=(o.name||"").padEnd(28),i=rR(o.risk||"low")+(o.risk||"low").padEnd(9)+st,c=o.requires_auth?"yes":"no ",l=o.url||"";r.push(` ${String(s+1).padStart(2)} ${a}${i}${c} ${Fr}${l}${st}`)}}let n=e.needs||[];if(n.length){r.push(""),r.push(` ${Ur}Needs:${st}`);for(let s of n){let o=s.nameLabel&&s.secretLabel?` (${s.nameLabel} / ${s.secretLabel})`:"";r.push(` ${Ma}\u2022${st} ${s.description}${o}`)}}}function oR(r,e){let t=e.initial_plans||e.plans||[];if(t.length){r.push("");for(let n of t)if(!n.skip&&(r.push(` ${Ur}${n.area}${st}${n.url?` ${Fr}${n.url}${st}`:""}`),n.focus?.length))for(let s of n.focus)r.push(` ${Ma}\u2022${st} ${s}`)}}function aR(r,e){let t=e.tested_areas||[];if(t.length){r.push(""),r.push(` ${Ur}Tested Areas:${st}`);for(let a of t)r.push(` ${Ma}\u2022${st} ${a.name.padEnd(28)}${nR(a.status)}`)}let n=e.verdict;if(n){r.push("");let a=n.recommendation,i=a==="ship"?Vg:a==="do_not_ship"?Ca:Ra;r.push(` ${Ur}Verdict:${st} ${i}${a}${st}`),n.rationale&&r.push(` ${n.rationale}`)}let s=e.reported_issues||[];if(s.length){r.push(""),r.push(` ${Ur}Issues (${s.length}):${st}`);for(let a of s){let i=String(a.severity||"medium").toUpperCase(),c=i==="HIGH"?Ca:i==="MEDIUM"?Ra:Fr;r.push(` ${c}[${i}]${st} ${a.title}`)}}let o=e.suggestions||[];if(o.length){r.push(""),r.push(` ${Ur}Suggestions:${st}`);for(let a of o){let i=a.type==="test"?`${Ma}[test]${st}`:`${Ra}[ask]${st}`;r.push(` ${i} ${a.text}`)}}for(let a of e.tested_areas||[])if(a.draft_steps?.length){r.push(""),r.push(` ${Ur}Test Plan \u2014 ${a.name} (${a.draft_steps.length} steps):${st}`);for(let i=0;i<Math.min(a.draft_steps.length,10);i++){let c=a.draft_steps[i],l=c.type?`${Fr}[${c.type}]${st} `:"";r.push(` ${String(i+1).padStart(3)}. ${l}${c.text}`)}a.draft_steps.length>10&&r.push(` ${Fr} ... and ${a.draft_steps.length-10} more steps${st}`);break}}function zg(r){return(r.needs||[]).filter(t=>t.type==="credential"||t.nameLabel||t.secretLabel)}function iR({checkpoint:r,isNonInteractive:e}){return r.autoApproved?{kind:"continue"}:r.type==="findings"&&e?{kind:"stop_findings"}:e?{kind:"fail_non_interactive",reason:`Encountered interactive ${r.type} checkpoint in non-interactive mode.`}:{kind:"prompt"}}async function Wg({checkpoint:r,isNonInteractive:e,rendered:t,writeOutput:n,log:s,prompt:o,promptCredentials:a,sendMessage:i,sendCredentials:c,closeStream:l}){let u=iR({checkpoint:r,isNonInteractive:e});if(n(t+`
1413
1413
  `),u.kind==="continue")return s("(auto-approved)"),u;if(u.kind==="stop_findings")return l(),u;if(u.kind==="fail_non_interactive")return s(u.reason),l(),u;if(r.type==="scope"){let p=zg(r.data||{});if(p.length){let f=await a(p);f.length&&(await c(f),s(`Sent ${f.length} credential(s)`))}}let h=await o(),g=h||"Approved.";return await i(g),s("Sent: "+(h?`"${h}"`:"Approved")),{kind:"prompted",approvalText:g}}function Gg(r,e){let t=[],n=0,s="",o,a,i,c;for(let h of r)if(h.type==="action:progress"&&h.action?.status==="completed"&&n++,h.type==="message:added"){let g=h.message;if(!g)continue;if(g.role==="model"||g.role==="assistant"){let p=g.text??g.content;typeof p=="string"&&p.length>0&&(g.actionName==="assistant_v2_report"||!s)&&(s=p)}if(g.actionName==="report_issue"){let p=g.actionArgs;p&&t.push({title:String(p.title??"Untitled issue"),description:String(p.description??""),severity:String(p.severity??"medium"),category:String(p.category??"logical"),confidence:typeof p.confidence=="number"?p.confidence:.5,steps:Array.isArray(p.reproSteps)?p.reproSteps.map(String):Array.isArray(p.steps_to_reproduce)?p.steps_to_reproduce.map(String):[]})}if(g.actionName==="present_checkpoint"){let p=g.actionArgs;if(p?.type==="findings"){let f=p.data;if(f?.verdict){let d=f.verdict;o={recommendation:d.recommendation,rationale:String(d.rationale??""),not_tested:Array.isArray(d.not_tested)?d.not_tested.map(y=>({area:String(y.area??""),reason:String(y.reason??"")})):void 0}}if(Array.isArray(f?.tested_areas)&&(a=f.tested_areas.map(d=>({name:String(d.name??""),status:d.status}))),Array.isArray(f?.suggestions)&&(i=f.suggestions.map(d=>({type:d.type||"test",text:String(d.text??"")}))),Array.isArray(f?.tested_areas))for(let d of f.tested_areas){let y=d.draft_steps;if(y?.length){c=y.map(v=>({text:String(v.text??""),type:String(v.type??"action"),...Array.isArray(v.criteria)?{criteria:v.criteria.map(w=>({check:String(w.check??""),strict:!!w.strict}))}:{}}));break}}}}}let l=Math.round((Date.now()-e)/1e3);return{summary:o?.rationale||s||(t.length>0?`Exploration complete. Found ${t.length} issue(s).`:"Exploration complete. No issues found."),issues:t,actionsTaken:n,durationSeconds:l,verdict:o,testedAreas:a,suggestions:i,testPlan:c}}function Yg(r){let e=[];if(e.push(r.prompt),r.feature&&e.push(`
1414
1414
  Feature under test: ${r.feature}`),r.test_hints?.length){e.push(`
@@ -1418,7 +1418,7 @@ Known limitations (do NOT report these as issues):`);for(let t of r.known_issues
1418
1418
  `)){let s=n.match(/^(\S+)\s+device$/);s&&r.push({id:s[1],platform:"android",name:s[1]})}let t=await Jg("xcrun",["simctl","list","devices","booted","-j"]);if(t)try{let n=JSON.parse(t);for(let[,s]of Object.entries(n.devices||{}))for(let o of s)o.state==="Booted"&&r.push({id:o.udid,platform:"ios",name:o.name})}catch{}return r}import{readFileSync as Pa,writeFileSync as Oa,existsSync as Yn,mkdirSync as cR,appendFileSync as uR}from"node:fs";import{homedir as dR}from"node:os";import{join as Jn}from"node:path";import{randomUUID as ey}from"node:crypto";var un=Jn(dR(),".agentiqa"),Cl=Jn(un,"analytics.json"),Xs=Jn(un,"events-queue.ndjson"),Xg=Jn(un,".installed"),Qg=Jn(un,"config.json"),Zg=Jn(un,"credentials.json");function Ml(){try{Yn(un)||cR(un,{recursive:!0})}catch{}}function ty(){if(process.env.DO_NOT_TRACK==="1"||process.env.AGENTIQA_TELEMETRY==="0")return!0;try{if(Yn(Qg)&&JSON.parse(Pa(Qg,"utf-8")).telemetry===!1)return!0}catch{}return!1}function Na(){return process.env.CI==="true"||!!process.env.GITHUB_ACTIONS||!!process.env.BUILDKITE||!!process.env.GITLAB_CI||!!process.env.CIRCLECI}function pR(r){if(r)return r;Ml();try{if(Yn(Cl)){let t=JSON.parse(Pa(Cl,"utf-8"));if(t.distinct_id)return t.distinct_id}}catch{}let e=ey();try{Oa(Cl,JSON.stringify({distinct_id:e}))}catch{}return e}function mR(){return process.env.AGENTIQA_ANALYTICS_ENDPOINT?process.env.AGENTIQA_ANALYTICS_ENDPOINT:`${(process.env.AGENTIQA_API_URL||"https://agentiqa.com").replace(/\/+$/,"")}/api/t`}function hR(){try{return Yn(Zg)?JSON.parse(Pa(Zg,"utf-8")).token:void 0}catch{return}}function fR(r,e,t){return{id:ey(),name:r,distinctId:pR(t.userId),client:"cli",...t.sessionId?{sessionId:t.sessionId}:{},occurredAt:new Date().toISOString(),properties:e}}var gR=1e3;async function ry(r){let e=hR(),t=new AbortController,n=setTimeout(()=>t.abort(),gR);try{let s=await fetch(mR(),{method:"POST",headers:_r({"content-type":"application/json",...e?{authorization:`Bearer ${e}`}:{}}),body:JSON.stringify(r),signal:t.signal});if(!s.ok&&s.status!==204)throw new Error(`status ${s.status}`)}finally{clearTimeout(n)}}function yR(r){try{Ml(),uR(Xs,JSON.stringify(r)+`
1419
1419
  `)}catch{}}async function Dt(r,e={},t={}){if(ty()||Na())return;let n=fR(r,e,t);try{await ry(n)}catch{yR(n)}}async function ny(){if(ty()||Na()||!Yn(Xs))return;let r;try{r=Pa(Xs,"utf-8").split(`
1420
1420
  `).filter(Boolean)}catch{return}if(r.length===0)return;let e;try{e=r.map(n=>JSON.parse(n))}catch{try{Oa(Xs,"")}catch{}return}let t=[];for(let n=0;n<e.length;n+=100)t.push(e.slice(n,n+100));try{for(let n of t)await ry(n);Oa(Xs,"")}catch{}}async function sy(){if(!Yn(Xg)){Ml();try{Oa(Xg,new Date().toISOString())}catch{return}await Dt("cli_installed",{node_version:process.version,os:process.platform})}}function ar(r){if(!r)return"none";let e;try{e=new URL(r).hostname.toLowerCase()}catch{return"none"}return e.endsWith(".vercel.app")||e==="vercel.app"?"vercel":e.endsWith(".bolt.new")||e==="bolt.new"?"bolt":e.endsWith(".lovable.app")||e==="lovable.app"?"lovable":e.endsWith(".replit.app")||e.endsWith(".replit.dev")?"replit":"none"}function ir(r){if(r)try{return new URL(r).hostname}catch{return}}import{spawn as cy}from"node:child_process";import{copyFileSync as vR,existsSync as bR,mkdirSync as uy,readFileSync as _R,statSync as wR,writeFileSync as dy}from"node:fs";import{tmpdir as SR}from"node:os";import Qs from"node:path";function xR(r,e){if(e.planId){let t=r.filter(n=>n.id===e.planId);if(t.length===0)throw new Error(`Plan not found: ${e.planId}`);return t}if(e.labelIds&&e.labelIds.length>0){let t=new Set(e.labelIds),n=r.filter(s=>(s.labels??[]).some(o=>t.has(o)));if(n.length===0)throw new Error(`No plans found with label ids: ${e.labelIds.join(",")}`);return n}return r}function TR(r,e){let t=Vl({labelIds:e.labelIds})??"_global",n=Hl(t);return[...r].sort((s,o)=>n({id:s.id,title:s.title,createdAt:s.createdAt??0,sortIndices:s.sortIndices},{id:o.id,title:o.title,createdAt:o.createdAt??0,sortIndices:o.sortIndices}))}function it(r){process.stderr.write(`[agentiqa] ${r}
1421
- `)}var py="https://agentiqa.com",oy=2;async function IR(r){return new Promise(e=>{let t=cy(r,["-version"],{stdio:["ignore","ignore","ignore"]});t.on("error",()=>e(!1)),t.on("close",n=>e(n===0))})}async function Ol(r,e=IR){return r.noArtifacts?{ok:!0,noArtifacts:!0}:await e("ffmpeg")?{ok:!0,noArtifacts:!1}:{ok:!0,noArtifacts:!0,warning:"ffmpeg not found \u2014 proceeding without local video artifacts. Install ffmpeg (`sudo apt-get install -y ffmpeg` on Ubuntu, `brew install ffmpeg` on macOS) and rerun to capture an mp4 of the session, or pass `--no-artifacts` to silence this message."}}async function ER(r,e){let t=process.env.AGENTIQA_API_URL||py,n=await fetch(`${t}/api/sync/entities/credentials?projectId=${encodeURIComponent(e)}`,{headers:_r({Authorization:`Bearer ${r}`})});return n.ok?(await n.json()).items??[]:(it(`Warning: failed to fetch project credentials (${n.status}) \u2014 running without`),[])}async function kR(r,e,t){let n=process.env.AGENTIQA_API_URL||py,s=await fetch(`${n}/api/sync/entities/test-plans?projectId=${encodeURIComponent(e)}`,{headers:_r({Authorization:`Bearer ${r}`})});if(!s.ok)throw new Error(`Failed to fetch test plans: ${s.status} ${s.statusText}`);let o=await s.json(),a=xR(o.items,t);return TR(a,t)}function Pl(r){if(typeof r!="string")return;let e=r.replace(/\s+/g," ").trim();return e.length>0?e:void 0}function AR(r,e){let t=[`Test run completed in ${r}s.`];e?.status&&t.push(` Status: ${e.status}`);let n=Pl(e?.summary);return n&&t.push(` Summary: ${n}`),t}function RR(){let r=new Set,e=!1;return t=>{let n=typeof t?.id=="string"&&t.id.trim()?t.id:void 0;return n?r.has(n)?!1:(r.add(n),!0):e?!1:(e=!0,!0)}}function ay(r){if(!r||typeof r!="object"||Array.isArray(r))return;let e={};for(let[t,n]of Object.entries(r))typeof n=="string"&&(e[t]=n);return e}function CR(r){if(!r||typeof r!="object")return;let e=r;return ay(e.runMemory)??ay(e.run?.runMemory)}function MR(r=new Date){return r.toISOString().replace(/[:.]/g,"-")}function OR(r){return r.toLowerCase().replace(/[^a-z0-9]+/g,"-").replace(/^-+|-+$/g,"").slice(0,80)||"plan"}function PR(r,e){return String(Math.max(0,Math.trunc(r))).padStart(e,"0")}function iy(r){let e=r??Qs.join(SR(),`agentiqa-run-${MR()}`);return uy(e,{recursive:!0}),e}async function NR(r,e){if(!r)return{};let t=Qs.join(e,"video.mp4");try{if(r.startsWith("file://"))return vR(new URL(r),t),{videoPath:t};if(!/^https?:\/\//i.test(r))return{error:`Unsupported video URL: ${r}`};let n=await fetch(r);return n.ok?(dy(t,Buffer.from(await n.arrayBuffer())),{videoPath:t}):{error:`Failed to download video: ${n.status}`}}catch(n){return{error:n instanceof Error?n.message:String(n)}}}function DR(r){let e=PR(r.planIndex,3),t=Qs.join(r.rootDir,`${e}-${OR(r.planTitle)}`);uy(t,{recursive:!0});let n,s=null,o=null,a,i=Qs.join(t,"video.mp4"),c=()=>s||(s=cy("ffmpeg",["-f","image2pipe","-framerate",String(oy),"-i","-","-c:v","libx264","-pix_fmt","yuv420p","-preset","ultrafast","-movflags","+faststart","-y","-f","mp4",i],{stdio:["pipe","ignore","ignore"]}),s.on("error",h=>{a=h.message}),o=new Promise(h=>{s?.on("close",g=>h(g)),s?.on("error",()=>h(null))}),s),l=jr({framesPerSecond:oy,writeFrame(h){let g=c();if(g?.stdin?.writable)try{g.stdin.write(h)}catch(p){a=p instanceof Error?p.message:String(p)}}}),u=async()=>{if(l.flush(),!s)return{};let h=s;s=null,h.stdin?.end();let g=o??Promise.resolve(null),p=await Promise.race([g,new Promise(f=>{setTimeout(()=>{h.kill("SIGKILL"),f(null)},3e4)})]);return bR(i)&&wR(i).size>0?{videoPath:i}:a?{error:a}:p!==0?{error:`ffmpeg exited with code ${p}`}:{error:"ffmpeg did not produce a video file"}};return{rootDir:r.rootDir,planDir:t,saveFrame(h){typeof h.data!="string"||h.data.length===0||l.addFrame(Buffer.from(h.data,"base64"),h.timestamp)},recordScreencastStopped(h){typeof h.videoUrl=="string"&&h.videoUrl.trim()&&(n=h.videoUrl)},async finalize(h){let g=await u(),p=g.videoPath?{}:await NR(n,t);return{rootDir:r.rootDir,planDir:t,...p.videoPath||g.videoPath?{videoPath:p.videoPath??g.videoPath}:{},...n?{videoUrl:n}:{},...p.error?{videoDownloadError:p.error}:{},...g.error?{videoRenderError:g.error}:{}}}}}async function ly(r){let{plan:e,url:t,engineUrl:n,token:s,wsToken:o,projectCredentials:a,initialMemory:i,artifactsRootDir:c,planIndex:l}=r,u=e.title??"Unnamed plan",h=c?DR({rootDir:c,planIndex:l??1,planTitle:u}):null,g=s?null:or(),p=s??g?.token,{sessionId:f}=await Ea(n,{engineSessionKind:"runner",platform:"cli",initialUrl:t,...p?{userToken:p}:{}});a?.length&&await Aa(n,f,a);let d=0,y=0,v=Date.now(),w="unknown",b={},T,S=RR(),R=ka(n,f),_=Bg(R,{onActionProgress:k=>{let A=k.action;A?.status==="started"&&it(` [${A.stepIndex??"-"}] ${A.actionName}${A.intent?` \u2014 ${A.intent}`:""}`)},onScreencastFrame:k=>{h?.saveFrame(k)},onScreencastStopped:k=>{h?.recordScreencastStopped(k)},onMessageAdded:k=>{if(k.screenshotBase64&&h){y++;let A=Qs.join(h.planDir,`screenshot-${String(y).padStart(3,"0")}.png`);dy(A,Buffer.from(k.screenshotBase64,"base64"))}},onRunCompleted:k=>{let A=k.run,j=((Date.now()-v)/1e3).toFixed(1);(A?.status==="failed"||A?.status==="error"||A?.status==="blocked")&&(d=1),A?.status&&(w=A.status),T=Pl(A?.summary)??T;let Q=CR(k);if(Q&&(b=Q),!!S(A))for(let N of AR(j,A))it(N)},onSessionStopped:()=>{w==="unknown"&&(w="stopped")},onSessionError:k=>{it(`Error: ${k.error}`),d=1,w="error"},onError:k=>{it(`WebSocket error: ${k.message}`),d=1,w="error"}},o??p);await qg(n,f,e,i),await _,await cn(n,f);let C={title:u,outcome:w,durationSec:Math.round((Date.now()-v)/1e3),exitCode:d,summary:T,runMemory:b};return h&&(C.artifacts=await h.finalize(C)),C}function jR(r){let e=(o,a)=>o.padEnd(a),t=`
1421
+ `)}var py="https://agentiqa.com",oy=2;async function IR(r){return new Promise(e=>{let t=cy(r,["-version"],{stdio:["ignore","ignore","ignore"]});t.on("error",()=>e(!1)),t.on("close",n=>e(n===0))})}async function Ol(r,e=IR){return r.noArtifacts?{ok:!0,noArtifacts:!0}:await e("ffmpeg")?{ok:!0,noArtifacts:!1}:{ok:!0,noArtifacts:!0,warning:"ffmpeg not found \u2014 proceeding without local video artifacts. Install ffmpeg (`sudo apt-get install -y ffmpeg` on Ubuntu, `brew install ffmpeg` on macOS) and rerun to capture an mp4 of the session, or pass `--no-artifacts` to silence this message."}}async function ER(r,e){let t=process.env.AGENTIQA_API_URL||py,n=await fetch(`${t}/api/sync/entities/credentials?projectId=${encodeURIComponent(e)}`,{headers:_r({Authorization:`Bearer ${r}`})});return n.ok?(await n.json()).items??[]:(it(`Warning: failed to fetch project credentials (${n.status}) \u2014 running without`),[])}async function kR(r,e,t){let n=process.env.AGENTIQA_API_URL||py,s=await fetch(`${n}/api/sync/entities/test-plans?projectId=${encodeURIComponent(e)}`,{headers:_r({Authorization:`Bearer ${r}`})});if(!s.ok)throw new Error(`Failed to fetch test plans: ${s.status} ${s.statusText}`);let o=await s.json(),a=xR(o.items,t);return TR(a,t)}function Pl(r){if(typeof r!="string")return;let e=r.replace(/\s+/g," ").trim();return e.length>0?e:void 0}function AR(r,e){let t=[`Test run completed in ${r}s.`];e?.status&&t.push(` Status: ${e.status}`);let n=Pl(e?.summary);return n&&t.push(` Summary: ${n}`),t}function RR(){let r=new Set,e=!1;return t=>{let n=typeof t?.id=="string"&&t.id.trim()?t.id:void 0;return n?r.has(n)?!1:(r.add(n),!0):e?!1:(e=!0,!0)}}function ay(r){if(!r||typeof r!="object"||Array.isArray(r))return;let e={};for(let[t,n]of Object.entries(r))typeof n=="string"&&(e[t]=n);return e}function CR(r){if(!r||typeof r!="object")return;let e=r;return ay(e.runMemory)??ay(e.run?.runMemory)}function MR(r=new Date){return r.toISOString().replace(/[:.]/g,"-")}function OR(r){return r.toLowerCase().replace(/[^a-z0-9]+/g,"-").replace(/^-+|-+$/g,"").slice(0,80)||"plan"}function PR(r,e){return String(Math.max(0,Math.trunc(r))).padStart(e,"0")}function iy(r){let e=r??Qs.join(SR(),`agentiqa-run-${MR()}`);return uy(e,{recursive:!0}),e}async function NR(r,e){if(!r)return{};let t=Qs.join(e,"video.mp4");try{if(r.startsWith("file://"))return vR(new URL(r),t),{videoPath:t};if(!/^https?:\/\//i.test(r))return{error:`Unsupported video URL: ${r}`};let n=await fetch(r);return n.ok?(dy(t,Buffer.from(await n.arrayBuffer())),{videoPath:t}):{error:`Failed to download video: ${n.status}`}}catch(n){return{error:n instanceof Error?n.message:String(n)}}}function DR(r){let e=PR(r.planIndex,3),t=Qs.join(r.rootDir,`${e}-${OR(r.planTitle)}`);uy(t,{recursive:!0});let n,s=null,o=null,a,i=Qs.join(t,"video.mp4"),c=()=>s||(s=cy("ffmpeg",["-f","image2pipe","-framerate",String(oy),"-i","-","-c:v","libx264","-pix_fmt","yuv420p","-preset","ultrafast","-movflags","+faststart","-y","-f","mp4",i],{stdio:["pipe","ignore","ignore"]}),s.on("error",h=>{a=h.message}),o=new Promise(h=>{s?.on("close",g=>h(g)),s?.on("error",()=>h(null))}),s),l=jr({framesPerSecond:oy,writeFrame(h){let g=c();if(g?.stdin?.writable)try{g.stdin.write(h)}catch(p){a=p instanceof Error?p.message:String(p)}}}),u=async()=>{if(l.flush(),!s)return{};let h=s;s=null,h.stdin?.end();let g=o??Promise.resolve(null),p=await Promise.race([g,new Promise(f=>{setTimeout(()=>{h.kill("SIGKILL"),f(null)},3e4)})]);return bR(i)&&wR(i).size>0?{videoPath:i}:a?{error:a}:p!==0?{error:`ffmpeg exited with code ${p}`}:{error:"ffmpeg did not produce a video file"}};return{rootDir:r.rootDir,planDir:t,saveFrame(h){typeof h.data!="string"||h.data.length===0||l.addFrame(Buffer.from(h.data,"base64"),h.timestamp)},recordScreencastStopped(h){typeof h.videoUrl=="string"&&h.videoUrl.trim()&&(n=h.videoUrl)},async finalize(h){let g=await u(),p=g.videoPath?{}:await NR(n,t);return{rootDir:r.rootDir,planDir:t,...p.videoPath||g.videoPath?{videoPath:p.videoPath??g.videoPath}:{},...n?{videoUrl:n}:{},...p.error?{videoDownloadError:p.error}:{},...g.error?{videoRenderError:g.error}:{}}}}}async function ly(r){let{plan:e,url:t,engineUrl:n,token:s,wsToken:o,projectCredentials:a,initialMemory:i,artifactsRootDir:c,planIndex:l}=r,u=e.title??"Unnamed plan",h=c?DR({rootDir:c,planIndex:l??1,planTitle:u}):null,g=s?null:or(),p=s??g?.token,{sessionId:f}=await Ea(n,{engineSessionKind:"runner",platform:"cli",initialUrl:t,...p?{userToken:p}:{}},o);a?.length&&await Aa(n,f,a,o);let d=0,y=0,v=Date.now(),w="unknown",b={},T,S=RR(),R=ka(n,f),_=Bg(R,{onActionProgress:k=>{let A=k.action;A?.status==="started"&&it(` [${A.stepIndex??"-"}] ${A.actionName}${A.intent?` \u2014 ${A.intent}`:""}`)},onScreencastFrame:k=>{h?.saveFrame(k)},onScreencastStopped:k=>{h?.recordScreencastStopped(k)},onMessageAdded:k=>{if(k.screenshotBase64&&h){y++;let A=Qs.join(h.planDir,`screenshot-${String(y).padStart(3,"0")}.png`);dy(A,Buffer.from(k.screenshotBase64,"base64"))}},onRunCompleted:k=>{let A=k.run,j=((Date.now()-v)/1e3).toFixed(1);(A?.status==="failed"||A?.status==="error"||A?.status==="blocked")&&(d=1),A?.status&&(w=A.status),T=Pl(A?.summary)??T;let Q=CR(k);if(Q&&(b=Q),!!S(A))for(let N of AR(j,A))it(N)},onSessionStopped:()=>{w==="unknown"&&(w="stopped")},onSessionError:k=>{it(`Error: ${k.error}`),d=1,w="error"},onError:k=>{it(`WebSocket error: ${k.message}`),d=1,w="error"}},o??p);await qg(n,f,e,i,o),await _,await cn(n,f,o);let C={title:u,outcome:w,durationSec:Math.round((Date.now()-v)/1e3),exitCode:d,summary:T,runMemory:b};return h&&(C.artifacts=await h.finalize(C)),C}function jR(r){let e=(o,a)=>o.padEnd(a),t=`
1422
1422
  [agentiqa] Results:
1423
1423
  `;t+=` ${e("Plan",40)} ${e("Outcome",12)} Duration
1424
1424
  `,t+=` ${"-".repeat(66)}
@@ -1499,17 +1499,23 @@ Common flags:
1499
1499
  --engine <url> Engine URL (default: auto-start in-process).
1500
1500
  When set, Playwright/Chromium and ffmpeg are not
1501
1501
  installed locally \u2014 the remote engine drives the
1502
- browser. Pair with AGENTIQA_ENGINE_TOKEN if the
1503
- engine requires a bearer token.
1502
+ browser. Customer-facing usage authenticates via
1503
+ AGENTIQA_SERVICE_KEY alone (a short-lived engine
1504
+ credential is minted automatically). Setting
1505
+ AGENTIQA_ENGINE_TOKEN is only required for
1506
+ internal flows that bypass the service-key
1507
+ exchange.
1504
1508
 
1505
1509
  Environment variables:
1506
- AGENTIQA_ENGINE_TOKEN Bearer token sent on engine HTTP + WebSocket
1507
- calls. Required for hosted engines that gate
1508
- access (staging/prod orchestrator).
1509
1510
  AGENTIQA_API_URL Override the Agentiqa control-plane API
1510
1511
  (default: https://agentiqa.com).
1511
1512
  AGENTIQA_SERVICE_KEY Service key for unattended runs (CI). Replaces
1512
- interactive login.
1513
+ interactive login and unlocks hosted engine
1514
+ access \u2014 no separate engine token required.
1515
+ AGENTIQA_ENGINE_TOKEN Optional internal bearer override for hosted
1516
+ engine HTTP + WebSocket calls. Only needed for
1517
+ internal infra; customer-facing CI should rely
1518
+ on AGENTIQA_SERVICE_KEY instead.
1513
1519
  GEMINI_API_KEY BYOK Gemini key. Only needed for the in-process
1514
1520
  engine (no --engine).
1515
1521
  `)}async function mC(){let{command:r,positional:e,flags:t,arrays:n}=pC();switch(sy(),ny(),Dt("cli_invoked",{command:r||"unknown",version:dC,node_version:process.version,os:process.platform,ci_detected:Na()}),r){case"explore":{let s=e[0]||t.prompt;!s&&!t["dry-run"]&&(process.stderr.write(`Error: prompt is required for explore
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "agentiqa",
3
- "version": "1.1.4",
3
+ "version": "1.1.5-staging.de8a89b",
4
4
  "description": "AI-powered testing for web and mobile apps",
5
5
  "type": "module",
6
6
  "bin": "dist/cli.js",