agent-device 0.17.9 → 0.17.10
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/README.md +4 -0
- package/android-multitouch-helper/dist/{agent-device-android-multitouch-helper-0.17.9.apk → agent-device-android-multitouch-helper-0.17.10.apk} +0 -0
- package/android-multitouch-helper/dist/agent-device-android-multitouch-helper-0.17.10.apk.sha256 +1 -0
- package/android-multitouch-helper/dist/{agent-device-android-multitouch-helper-0.17.9.manifest.json → agent-device-android-multitouch-helper-0.17.10.manifest.json} +4 -4
- package/android-snapshot-helper/dist/{agent-device-android-snapshot-helper-0.17.9.apk → agent-device-android-snapshot-helper-0.17.10.apk} +0 -0
- package/android-snapshot-helper/dist/agent-device-android-snapshot-helper-0.17.10.apk.sha256 +1 -0
- package/android-snapshot-helper/dist/{agent-device-android-snapshot-helper-0.17.9.manifest.json → agent-device-android-snapshot-helper-0.17.10.manifest.json} +6 -6
- package/dist/src/2133.js +1 -1
- package/dist/src/2948.js +1 -1
- package/dist/src/9581.js +2 -2
- package/dist/src/9722.js +28 -28
- package/dist/src/9919.js +5 -5
- package/dist/src/cli-help.js +86 -27
- package/dist/src/cli.js +9 -9
- package/dist/src/internal/bin.js +1 -1
- package/package.json +1 -1
- package/server.json +2 -2
- package/skills/agent-device/SKILL.md +1 -0
- package/android-multitouch-helper/dist/agent-device-android-multitouch-helper-0.17.9.apk.sha256 +0 -1
- package/android-snapshot-helper/dist/agent-device-android-snapshot-helper-0.17.9.apk.sha256 +0 -1
package/dist/src/9919.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import e from"node:fs";import t from"node:http";import a from"node:https";import r from"node:path";import{pipeline as n}from"node:stream/promises";import i from"node:os";import{createHash as o,randomUUID as s}from"node:crypto";import{Writable as l}from"node:stream";import c from"node:net";import d from"node:fs/promises";import{toAppErrorCode as u,AppError as f}from"./733.js";import{runCmdDetachedMonitored as p,runCmd as m,runCmdSync as h}from"./8875.js";import{createRequestId as y,withDiagnosticTimer as w,emitDiagnostic as g}from"./432.js";import{isAgentDeviceDaemonProcess as b,stopProcessForTakeover as v}from"./5628.js";import{readSnapshotDiagnosticsSummary as I,consumeTextLines as A,shellQuote as S,shouldStreamRequestProgress as M,isDaemonResponseEnvelope as P,isDaemonProgressEnvelope as D,resolveDaemonPaths as _,resolveDaemonServerMode as k,computeDaemonCodeSignature as E,resolveDaemonTransportPreference as x}from"./8358.js";import{listCommandFamilyDaemonWriters as N,normalizeSession as $,readSerializedSnapshotCaptureAnnotations as T,readRequiredString as C,findCommandMetadata as U,normalizeMaterializationReleaseResult as L,colorize as O,readSnapshotNodes as R,normalizeDeployResult as F,normalizeOpenDevice as B,buildMeta as j,readOptionalString as q,resolveSessionName as V,supportsColor as H,buildRequestFlags as G,createBatchDaemonWriter as K,readMetadataCommandFlags as z,normalizeDevice as Y,normalizeStartupSample as W,readScreenshotOverlayRefs as J,normalizeRuntimeHints as X,normalizeInstallFromSourceResult as Q}from"./2948.js";import{INTERNAL_COMMANDS as Z,PUBLIC_COMMANDS as ee}from"./2133.js";import{readVersion as et,findProjectRoot as ea}from"./1404.js";import{sleep as er}from"./5560.js";import{reloadMetro as en,prepareMetroRuntime as ei}from"./8275.js";let eo="/agent-device";function es(e){return el(e,eo)}function el(e,t){let a=e.endsWith("/")?e:`${e}/`;return new URL(t.replace(/^\/+/,""),a).toString()}function ec(e){let t=e?.trim();return t?{authorization:`Bearer ${t}`,"x-agent-device-token":t}:{}}function ed(e){return new Promise((t,a)=>{let r="";e.setEncoding("utf8"),e.on("data",e=>{r+=e}),e.on("end",()=>t(r)),e.on("error",a)})}let eu="sha256";async function ef(e){let t=await ep(e.localPath,e.platform),a=e.baseUrl.endsWith("/")?e.baseUrl:`${e.baseUrl}/`;try{let r=await ew({normalizedBase:a,token:e.token,artifact:t});if(r?.kind==="cache-hit")return r.uploadId;if(r?.kind==="direct-upload")try{return await eg(t.payloadPath,r),await eA({normalizedBase:a,token:e.token,uploadId:r.uploadId})}catch{}return await ey({normalizedBase:a,token:e.token,artifact:t})}finally{t.cleanup()}}async function ep(t,a){var n,i,o;let s,l=e.statSync(t),c=r.basename(t),d=l.isDirectory(),u=("ios"===(n=a)||"android"===n?n:void 0)??(i=t,o=l,s=i.toLowerCase(),o.isDirectory()&&s.endsWith(".app")||s.endsWith(".ipa")?"ios":s.endsWith(".apk")||s.endsWith(".aab")?"android":void 0),f=[];try{let a=d?await em(t,f):t,r=e.statSync(a);return{payloadPath:a,fileName:c,artifactType:d?"app-bundle":"file",platform:u,contentType:d?"application/gzip":"application/octet-stream",sha256:await eS(a),sizeBytes:r.size,cleanup:()=>eh(f)}}catch(e){throw eh(f),e}}async function em(t,a){let n=e.mkdtempSync(r.join(i.tmpdir(),`agent-device-upload-${s()}-`));a.push(n);let o=r.join(n,`${r.basename(t)}.tar.gz`);return await m("tar",["czf",o,"-C",r.dirname(t),r.basename(t)],{env:{...process.env,COPYFILE_DISABLE:"1"}}),o}function eh(t){for(let a of t)e.rmSync(a,{recursive:!0,force:!0})}async function ey(e){let{normalizedBase:t,token:a,artifact:r}=e,n=new URL("upload",t),i={"content-type":r.contentType,"x-artifact-type":r.artifactType,"x-artifact-filename":r.fileName,"x-artifact-hash":r.sha256,"x-artifact-hash-algorithm":eu,"transfer-encoding":"chunked"};Object.assign(i,ec(a));let o=await eb({url:n,method:"POST",headers:i,payloadPath:r.payloadPath,timeoutMessage:"Artifact upload timed out",timeoutHint:"The upload to the remote daemon exceeded the 5-minute timeout.",errorMessage:"Failed to upload artifact to remote daemon",errorHint:"Verify the remote daemon is reachable and supports artifact uploads."});try{let e=JSON.parse(o.body);if(!e.ok||!e.uploadId)throw new f("COMMAND_FAILED",`Upload failed: ${o.body}`);return e.uploadId}catch(e){if(e instanceof f)throw e;throw new f("COMMAND_FAILED",`Invalid upload response: ${o.body}`)}}async function ew(e){let t=new URL("upload/preflight",e.normalizedBase),a={"content-type":"application/json"};Object.assign(a,ec(e.token));let r=await fetch(t,{method:"POST",headers:a,signal:AbortSignal.timeout(3e4),body:JSON.stringify({sha256:e.artifact.sha256,fileName:e.artifact.fileName,sizeBytes:e.artifact.sizeBytes,artifactType:e.artifact.artifactType,...e.artifact.platform?{platform:e.artifact.platform}:{},contentType:e.artifact.contentType})}).catch(()=>void 0);if(r?.ok)return function(e){var t;if(!e||"object"!=typeof e||!0!==e.ok||"string"!=typeof e.uploadId)return;if(!0===e.cacheHit)return{kind:"cache-hit",uploadId:e.uploadId};let a=e.upload;if(!a||"string"!=typeof a.url)return;let r=a.headers??{};if(!(!(t=r)||"object"!=typeof t||Array.isArray(t))&&Object.values(t).every(e=>"string"==typeof e))return{kind:"direct-upload",uploadId:e.uploadId,url:a.url,headers:r}}(await r.json().catch(()=>void 0))}async function eg(e,t){let a=await eb({url:new URL(t.url),method:"PUT",headers:t.headers,payloadPath:e,timeoutMessage:"Direct artifact upload timed out",timeoutHint:"The direct upload ticket did not accept the artifact within the timeout.",errorMessage:"Failed to upload artifact with direct upload ticket"});if(a.statusCode<200||a.statusCode>=300)throw new f("COMMAND_FAILED","Direct artifact upload failed",{statusCode:a.statusCode,statusMessage:a.statusMessage})}async function eb(e){return await ev({...e,url:e.url,redirectCount:0,startOffset:0})}async function ev(r){var i,o,s;let l="https:"===r.url.protocol?a:t,c=e.statSync(r.payloadPath).size,d=(i=r.headers,o=r.startOffset,s=c,o<=0?i:{...i,"content-length":Math.max(s-o,0),"content-range":`bytes ${o}-${s-1}/${s}`});return await new Promise((t,a)=>{let i=!1,o=l.request({protocol:r.url.protocol,host:r.url.hostname,port:r.url.port,method:r.method,path:r.url.pathname+r.url.search,headers:d},e=>{i=!0,ed(e).then(n=>{clearTimeout(s);let i=e.statusCode??500,o=e.headers.location;if(o&&[301,302,303,307,308].includes(i)){if(r.redirectCount>=5)return void a(new f("COMMAND_FAILED","Artifact upload exceeded redirect limit",{maxRedirects:5,url:r.url.toString()}));let e=new URL(o,r.url);return void ev({...r,url:e,redirectCount:r.redirectCount+1}).then(t,a)}let l=308===i?function(e,t){let a=function(e){let t=eI(e);if(void 0===t)return;let a=Number(t);return Number.isSafeInteger(a)&&a>=0?a:void 0}(e["x-upload-offset"]??e["upload-offset"]);if(void 0!==a)return Math.min(a,t);let r=eI(e.range),n=r?.match(/^bytes=0-(\d+)$/);if(!n)return;let i=Number(n[1]);if(Number.isSafeInteger(i)&&!(i<0))return Math.min(i+1,t)}(e.headers,c):void 0;void 0!==l?l>=c?t({statusCode:200,statusMessage:"Upload already complete",body:""}):l<=r.startOffset?a(new f("COMMAND_FAILED","Artifact upload resume did not advance",{offset:l,previousOffset:r.startOffset,url:r.url.toString()})):ev({...r,startOffset:l}).then(t,a):t({statusCode:i,statusMessage:e.statusMessage,body:n})}).catch(a)}),s=setTimeout(()=>{o.destroy(),a(new f("COMMAND_FAILED",r.timeoutMessage,{timeoutMs:3e5,...r.timeoutHint?{hint:r.timeoutHint}:{}}))},3e5);o.on("error",e=>{i||(clearTimeout(s),a(new f("COMMAND_FAILED",r.errorMessage,r.errorHint?{hint:r.errorHint}:{},e)))}),o.on("close",()=>clearTimeout(s)),n(e.createReadStream(r.payloadPath,{start:r.startOffset}),o).catch(e=>{i||(o.destroy(),a(new f("COMMAND_FAILED","Failed to read local artifact",{},e instanceof Error?e:Error(String(e)))))})})}function eI(e){return Array.isArray(e)?e[0]:e}async function eA(e){let t=new URL("upload/finalize",e.normalizedBase),a={"content-type":"application/json"};Object.assign(a,ec(e.token));let r=await fetch(t,{method:"POST",headers:a,signal:AbortSignal.timeout(3e4),body:JSON.stringify({uploadId:e.uploadId})}).catch(e=>{throw new f("COMMAND_FAILED","Failed to finalize direct artifact upload",{},e)});if(!r.ok)throw new f("COMMAND_FAILED","Direct artifact upload finalize failed",{status:r.status,statusText:r.statusText});let n=await r.json().catch(()=>void 0);if(!n?.ok||!n.uploadId)throw new f("COMMAND_FAILED","Invalid upload finalize response");return n.uploadId}async function eS(t){let a=o(eu),r=new l({write(e,t,r){a.update(e),r()}});return await n(e.createReadStream(t),r).catch(e=>{throw new f("COMMAND_FAILED","Failed to read local artifact",{},e instanceof Error?e:void 0)}),a.digest("hex")}async function eM(e,t){var a;let n,i=[...e.positionals??[]],o=e.flags?{...e.flags}:void 0,s=e.meta?.installSource,l={};if(!("string"==typeof(a=t).baseUrl&&a.baseUrl.length>0))return eD({positionals:i,flags:o,installSource:s,uploadedArtifactId:n,clientArtifactPaths:l});o=function(e,t,a,n){var i,o;let s=function(e,t){if("screenshot"===e.command){let a=ek(e,"path",".png");return t[0]?{field:"path",localPath:a,positionalIndex:0,positionalPath:eE("screenshot",".png")}:{field:"path",localPath:a,positionalIndex:0,flagPath:eE("screenshot",".png")}}if("record"===e.command&&"start"===(t[0]??"").toLowerCase()){let t=ek(e,"outPath",".mp4",1);return{field:"outPath",localPath:t,positionalIndex:1,positionalPath:eE("recording",r.extname(t)||".mp4")}}return null}(e,t);if(!s)return a;void 0!==s.positionalPath&&(t[s.positionalIndex]=s.positionalPath);let l=(i=a,void 0===(o=s.flagPath)?i:{...i??{},out:o});return n[s.field]=s.localPath,l}(e,i,o,l);let c=await e_(e,t);c&&(s=c.installSource,n=c.uploadedArtifactId??n);let d=()=>eD({positionals:i,flags:o,installSource:s,uploadedArtifactId:n,clientArtifactPaths:l});return"install"!==e.command&&"reinstall"!==e.command||(n=await eP(e,t,i)??n),d()}async function eP(t,a,n){var i,o;let s,l=n[1];if(void 0===l)return;if(l.startsWith("remote:")){n[1]=l.slice(7);return}let c=(i=l,o=t.meta?.cwd,s=r.isAbsolute(i)?i:r.resolve(o??process.cwd(),i),e.existsSync(s)?s:void 0);if(c)return await ef({localPath:c,baseUrl:a.baseUrl,token:a.token,platform:t.flags?.platform})}function eD(e){return{positionals:e.positionals,flags:e.flags,installSource:e.installSource,uploadedArtifactId:e.uploadedArtifactId,...Object.keys(e.clientArtifactPaths).length>0?{clientArtifactPaths:e.clientArtifactPaths}:{}}}async function e_(t,a){let n=t.meta?.installSource;if("install_source"!==t.command||!n||"path"!==n.kind)return null;let i=n.path.trim();if(!i)return{installSource:n};if(i.startsWith("remote:"))return{installSource:{...n,path:i.slice(7)}};let o=r.isAbsolute(i)?i:r.resolve(t.meta?.cwd??process.cwd(),i);if(!e.existsSync(o))return{installSource:{...n,path:o}};let s=await ef({localPath:o,baseUrl:a.baseUrl,token:a.token,platform:t.flags?.platform});return{installSource:{...n,path:o},uploadedArtifactId:s}}function ek(e,t,a,n=0){let i=e.positionals?.[n]??e.flags?.out,o=`${"path"===t?"screenshot":"recording"}-${Date.now()}${a}`,s=i&&i.trim().length>0?i:o;return r.isAbsolute(s)?s:r.resolve(e.meta?.cwd??process.cwd(),s)}function eE(e,t){let a=t.startsWith(".")?t:`.${t}`;return r.posix.join("/tmp",`agent-device-${e}-${Date.now()}-${Math.random().toString(36).slice(2,8)}${a}`)}async function ex(e,t,a){let n=Array.isArray(a.data?.artifacts)?a.data.artifacts:[];if(0===n.length||!e.baseUrl)return a;let i=a.data?{...a.data}:{},o=[];for(let a of n){if(!a||"object"!=typeof a||"string"!=typeof a.artifactId){o.push(a);continue}let n=function(e,t){if(e.localPath&&e.localPath.trim().length>0)return e.localPath;let a=t.meta?.clientArtifactPaths?.[e.field];if(a&&a.trim().length>0)return a;let n=e.fileName?.trim()||`${e.field}-${Date.now()}`;return r.resolve(t.meta?.cwd??process.cwd(),n)}(a,t);await eN({baseUrl:e.baseUrl,token:e.token,artifactId:a.artifactId,destinationPath:n,requestId:t.meta?.requestId}),i[a.field]=n,o.push({...a,localPath:n})}return i.artifacts=o,{ok:!0,data:i}}async function eN(i){var o,s;let l,c=new URL((o=i.baseUrl,s=i.artifactId,l=o.endsWith("/")?o:`${o}/`,new URL(`artifacts/${encodeURIComponent(s)}`,l).toString())),d="https:"===c.protocol?a:t;await e.promises.mkdir(r.dirname(i.destinationPath),{recursive:!0}),await new Promise((t,a)=>{let r=!1,o=i.timeoutMs??9e4,s=n=>{if(!r){if(r=!0,clearTimeout(u),n)return void e.promises.rm(i.destinationPath,{force:!0}).finally(()=>a(n));t()}},l=d.request({protocol:c.protocol,host:c.hostname,port:c.port,method:"GET",path:c.pathname+c.search,headers:ec(i.token)},t=>{if((t.statusCode??500)>=400){let e="";t.setEncoding("utf8"),t.on("data",t=>{e+=t}),t.on("end",()=>{s(new f("COMMAND_FAILED","Failed to download remote artifact",{artifactId:i.artifactId,statusCode:t.statusCode,requestId:i.requestId,body:e}))});return}t.on("aborted",()=>{s(new f("COMMAND_FAILED","Remote artifact download was interrupted",{artifactId:i.artifactId,requestId:i.requestId}))}),n(t,e.createWriteStream(i.destinationPath)).then(()=>s(),e=>s(e instanceof Error?e:Error(String(e))))}),u=setTimeout(()=>{let e=new f("COMMAND_FAILED","Remote artifact download timed out",{artifactId:i.artifactId,requestId:i.requestId,timeoutMs:o});s(e),l.destroy(e)},o);l.on("error",e=>{e instanceof f?s(e):s(new f("COMMAND_FAILED","Failed to download remote artifact",{artifactId:i.artifactId,requestId:i.requestId,timeoutMs:o},e instanceof Error?e:void 0))}),l.end()})}function e$(e){var t,a,r;let n,i,o=ej(e);if(!o||"object"!=typeof o)return null;let s="string"==typeof(t=o).token&&t.token.length>0?t.token:null;if(!s)return null;let l=(n=eC((a=o).port),i=eC(a.httpPort),void 0===n&&void 0===i?null:{port:n,httpPort:i});return l?{token:s,...l,transport:"socket"===(r=o.transport)||"http"===r||"dual"===r?r:void 0,pid:eC(o.pid)??0,version:eT(o.version),codeSignature:eT(o.codeSignature),processStartTime:eT(o.processStartTime)}:null}function eT(e){return"string"==typeof e?e:void 0}function eC(e){return Number.isInteger(e)&&Number(e)>0?Number(e):void 0}function eU(e){let t=ej(e);return t&&"object"==typeof t&&Number.isInteger(t.pid)&&Number(t.pid)>0?{pid:Number(t.pid),processStartTime:"string"==typeof t.processStartTime?t.processStartTime:void 0,startedAt:"number"==typeof t.startedAt?t.startedAt:void 0}:null}async function eL(t,a,r={}){let n=r.stopLiveProcesses??!0,i={reason:a,removedInfo:!1,removedLock:!1,stoppedInfoProcess:!1,stoppedLockProcess:!1};try{var o,s,l,c;let a=e.existsSync(t.infoPath),r=e$(t.infoPath);if(r){let e=b(r.pid,r.processStartTime);e&&!n?i.retainedInfoProcess=!0:(e&&(await eF(r),i.stoppedInfoProcess=!0),o=t.infoPath,eq(o),i.removedInfo=!0)}else a&&(s=t.infoPath,eq(s),i.removedInfo=!0);let d=e.existsSync(t.lockPath),u=eU(t.lockPath);if(u){let e=b(u.pid,u.processStartTime);e&&!n?i.retainedLockProcess=!0:(e&&(await v(u.pid,{termTimeoutMs:3e3,killTimeoutMs:1e3,expectedStartTime:u.processStartTime}),i.stoppedLockProcess=!0),l=t.lockPath,eq(l),i.removedLock=!0)}else d&&(c=t.lockPath,eq(c),i.removedLock=!0)}catch(e){i.error=e instanceof Error?e.message:String(e)}return g({level:i.error?"warn":"info",phase:"daemon_startup_metadata_cleanup",data:i}),i}function eO(t){return{hasInfo:e.existsSync(t.infoPath),hasLock:e.existsSync(t.lockPath)}}async function eR(e){let t=eO(e);if(!t.hasLock||t.hasInfo)return!1;let a=eU(e.lockPath);return!(a&&b(a.pid,a.processStartTime))&&(eq(e.lockPath),!0)}async function eF(e){await v(e.pid,{termTimeoutMs:3e3,killTimeoutMs:1e3,expectedStartTime:e.processStartTime})}function eB(e){return"string"==typeof e.baseUrl&&e.baseUrl.length>0}function ej(t){if(!e.existsSync(t))return null;try{return JSON.parse(e.readFileSync(t,"utf8"))}catch{return null}}function eq(t){try{e.existsSync(t)&&e.unlinkSync(t)}catch{}}function eV(e){let t=Math.max(0,e)/1e3;return t>=10?`${t.toFixed(1)}s`:t>=1?`${t.toFixed(2)}s`:`${t.toFixed(3).replace(/0+$/,"").replace(/\.$/,"")}s`}function eH(e){let t=eG(e),a=t.findIndex(({stop:e})=>!1===e.ok);if(a<0)return[];let r=t.slice(Math.max(0,a-2),a+1);return[e.attempts>1?`steps (attempt ${e.attempts}):`:"steps:",...r.map(({stop:e,start:t})=>eW(e,t))]}function eG(t){var a,n;let i=(a=t).artifactsDir?r.join(a.artifactsDir,`attempt-${a.attempts}`,"replay-timing.ndjson"):void 0;if(!i)return[];let o=function(t){try{return e.readFileSync(t,"utf8").split(/\r?\n/).filter(e=>e.trim().length>0).flatMap(e=>{try{let t=JSON.parse(e);return eX(t)?[t]:[]}catch{return[]}})}catch{return[]}}(i);if(0===o.length)return[];let s=[],l=[];for(let e of o){if("replay_action_start"===(n=e).type&&eK(n)&&ez(n,"line")&&eY(n,"command")&&(void 0===n.positionals||Array.isArray(n.positionals))){s.push(e);continue}(function(e){var t;return["replay_action_stop"===e.type&&eK(e)&&ez(e,"line")&&eY(e,"command"),void 0===(t=e).ok||"boolean"==typeof t.ok,ez(e,"durationMs"),eY(e,"errorCode"),void 0===e.resultTiming||eX(e.resultTiming)].every(Boolean)})(e)&&l.push({stop:e,start:function(e,t){let a=t.command,r=e.findIndex(e=>e.step===t.step&&(void 0===a||void 0===e.command||e.command===a));if(!(r<0))return e.splice(r,1)[0]}(s,e)})}return l}function eK(e){return"number"==typeof e.step}function ez(e,t){return void 0===e[t]||"number"==typeof e[t]}function eY(e,t){return void 0===e[t]||"string"==typeof e[t]}function eW(e,t){var a,r,n,i;let o,s,l=!1===e.ok?"[FAIL] ":!0===e.ok?"":"[info] ";return` ${l}${a=t,r=e,[function(e){if(!e)return"unknown";if(!e.startsWith("__maestro"))return e;let t=e.slice(9);return t.length>0?t[0].toLowerCase()+t.slice(1):e}(a?.command??r.command),...(a?.positionals??[]).map(eJ)].join(" ")}${n=e,i=t,(s=["number"==typeof(o=i?.line??n.line)?`line ${o}`:"","number"==typeof n.durationMs?eV(n.durationMs):"",n.errorCode??"",n.resultTiming?`timing ${JSON.stringify(n.resultTiming)}`:""].filter(Boolean)).length>0?` (${s.join(", ")})`:""}`}function eJ(e){return"string"==typeof e?JSON.stringify(e):"number"==typeof e||"boolean"==typeof e?String(e):JSON.stringify(e)}function eX(e){return!!e&&"object"==typeof e&&!Array.isArray(e)}function eQ(e,t){return O(e,t,{validateStream:!1})}function eZ(e){if("number"!=typeof e.shardIndex)return"";let t="number"==typeof e.shardCount?e.shardCount:"?",a="string"==typeof e.deviceId?` ${e.deviceId}`:"";return` [shard ${e.shardIndex+1}/${t}${a}]`}function e0(e){return`\r\x1b[2K${e}`}function e1(e){return"number"==typeof e&&Number.isFinite(e)&&e>0?Math.floor(e):80}function e3(e,t){let a=e1(t);return e.length<=a?e:a<=0?"":a<=3?".".repeat(a):`${e.slice(0,a-3)}...`}function e2(e){return{file:e.file,title:e.title,durationMs:e.durationMs??0,attempts:e.attempt??1,artifactsDir:e.artifactsDir,session:e.session??""}}function e5(e){return function(e={}){let t=new Set,a=!1;return{render(n){var i,o;if("replay-test-suite"===n.type){t.clear(),a=!1;return}if("replay-test"!==n.type)return;if("progress"===n.status){if(!e.liveProgress)return;return a=!0,{text:e0(function(e,t){let a=e.title?.trim(),n=r.basename(e.file),i=eZ(e),o=e.stepIndex??0,s=e.stepTotal??0,l=`${i} [${o}/${s}]`,c="⊙ ";if(!a)return e3(`${c}${n}${l}`,t.columns);let d=`${c}"`,u=`" in ${n}${l}`,f=e3(a,Math.max(0,e1(t.columns)-d.length-u.length));return e3(`${d}${f}${u}`,t.columns)}(n,e)),newline:!1}}if("pass"===(i=n).status||"skip"===i.status||"fail"===i.status&&!i.retrying){let e,a=(e="number"==typeof(o=n).shardIndex?o.shardIndex:"",[o.status,o.index,o.total,o.file,o.title??"",e].join("\0"));if(t.has(a))return;t.add(a)}let s=function(e,t={}){if("replay-test"===e.type)return function(e,t){var a,n,i,o;let s,l,c,d,u,f;if("start"===e.status||"progress"===e.status||"fail"===e.status&&e.retrying)return;let p=[(c=function(e){let t=H(process.stderr);if("pass"===e.status){let a=e.attempt&&e.attempt>1?"yellow":"green";return t?eQ("✓",a):"✓"}return"fail"===e.status?t?eQ("⨯","red"):"⨯":"progress"===e.status?"⊙":t?eQ("-","dim"):"-"}(a=e),d=(n=a,s=n.title?.trim(),l=r.basename(n.file),s?`${JSON.stringify(s)} in ${l}`:l),u=eZ(a),f=void 0!==a.durationMs?` (${eV(a.durationMs??0)})`:"",`${c} ${d}${u}${f}`)];return function(e,t,a){if(a.verbose&&"fail"===t.status)return;let r=t.message?.replace(/\s+/g," ").trim();r&&e.push(` ${"fail"===t.status?`failed at: ${r}`:r}`),"fail"===t.status&&!t.retrying&&(t.session&&e.push(` session: ${t.session}`),t.artifactsDir&&e.push(` artifacts: ${t.artifactsDir}`))}(p,e,t),t.verbose&&p.push(...("pass"===(i=e).status||"fail"===i.status)&&i.artifactsDir&&i.attempt?(function(e){if("skipped"===e.status)return[];let t=eG(e);return 0===t.length?[]:[e.attempts>1?`steps (attempt ${e.attempts}):`:"steps:",...t.map(({stop:e,start:t})=>eW(e,t))]})("pass"===i.status?{...e2(i),status:"passed",replayed:0,healed:0}:{...e2(o=i),status:"failed",error:{code:"COMMAND_FAILED",message:o.message??"Unknown test failure"}}).map(e=>` ${e}`):[]),p.join("\n")}(e,t)}(n,e);if(!s)return;let l=a?e0(s):s;return a=!1,{text:l,newline:!0}}}}({verbose:!!(e.flags?.verbose||e.meta?.debug),liveProgress:!0===process.stderr.isTTY&&!process.env.CI,columns:process.stderr.columns})}function e4(e,t){let a=t.render(e);a&&process.stderr.write(a.newline?`${a.text}
|
|
2
|
-
`:a.text)}function e8(e,t){let{info:a,req:r,resolve:n,reject:i}=t;try{var o,s,l;let t=(o=e,JSON.parse(o));if(t.error){let e;return void i((s=t.error,l=r.meta?.requestId,e=s.data??{},new f(u(null!=e.code?String(e.code):void 0,"COMMAND_FAILED"),String(e.message??s.message??"Daemon RPC request failed"),{..."object"==typeof e.details&&e.details?e.details:{},hint:"string"==typeof e.hint?e.hint:void 0,diagnosticId:"string"==typeof e.diagnosticId?e.diagnosticId:void 0,logPath:"string"==typeof e.logPath?e.logPath:void 0,requestId:l})))}if(!t.result||"object"!=typeof t.result)return void i(new f("COMMAND_FAILED","Invalid daemon RPC response",{requestId:r.meta?.requestId}));e6(a,r,t.result,n,i)}catch(t){i(new f("COMMAND_FAILED","Invalid daemon response",{requestId:r.meta?.requestId,line:e},t instanceof Error?t:void 0))}}async function e6(e,t,a,r,n){try{r(e.baseUrl&&a.ok?await
|
|
3
|
-
`)}),d=!1,u="number"==typeof r?setTimeout(()=>{d=!0,l.destroy(),o(e9(e,a,t.meta?.requestId,t.command,!1,r))},r):void 0;!function(e,t){let{req:a,isSettled:r,resolve:n,reject:i,clearTimeout:o}=t,s="",l=e5(a),c=(e,t)=>{o(),i(new f("COMMAND_FAILED","Invalid daemon response",{requestId:a.meta?.requestId,line:e},t instanceof Error?t:void 0))};e.setEncoding("utf8"),e.on("data",t=>{if(r())return;let a=A(s,t);for(let t of(s=a.buffer,a.lines))try{let a=JSON.parse(t);if(D(a)){e4(a.event,l);continue}let r=
|
|
4
|
-
`)}catch{}}(r,n,e.paths.baseDir),await eF(r),eq(e.paths.infoPath),null)}async function tw(t){let a,r,n=0,i=[];for(let o=1;o<=2;o+=1){let s;try{r={pid:(s=function(t){let a=tI(),r=a.useSrc?["--experimental-strip-types",a.srcPath]:[a.distPath],n={...process.env,AGENT_DEVICE_STATE_DIR:t.paths.baseDir,AGENT_DEVICE_DAEMON_SERVER_MODE:t.serverMode};e.mkdirSync(t.paths.baseDir,{recursive:!0});let i=e.openSync(t.paths.logPath,"a"),o=e.openSync(t.paths.logPath,"a");try{return p(process.execPath,r,{env:n,stdio:["ignore",i,o]})}finally{e.closeSync(i),e.closeSync(o)}}(t)).pid}}catch(e){if(a=e instanceof Error?e.message:String(e),i.push(await eL(t.paths,"start_error")),o<2){await er(150);continue}break}let l=await tv(15e3,t,s);if("ready"===l.kind)return{info:l.info,startedByClient:!0};if("early_exit"===l.kind){if(r=l.exit,a=tS(l.exit),i.push(await eL(t.paths,"start_error")),o<2){await er(150);continue}break}if(await eR(t.paths)){n+=1;continue}let c=eO(t.paths),d=o<2,u=await eL(t.paths,"startup_timeout",{stopLiveProcesses:!1});if(i.push(u),u.retainedInfoProcess||u.retainedLockProcess){let e=await tv(15e3,t,s);if("ready"===e.kind)return{info:e.info,startedByClient:!0};"early_exit"===e.kind&&(r=e.exit,a=tS(e.exit));break}if(!d)break;c.hasInfo||c.hasLock||await er(150)}let o=eO(t.paths),s=function(t){try{if(!e.existsSync(t))return;let a=e.statSync(t);if(a.size<=0)return;let r=Math.min(a.size,64e3),n=e.openSync(t,"r");try{let t=Buffer.alloc(r);e.readSync(n,t,0,r,a.size-r);let i=t.toString("utf8").trim();return i.length>0?i:void 0}finally{e.closeSync(n)}}catch{return}}(t.paths.logPath);throw new f("COMMAND_FAILED","Failed to start daemon",{kind:"daemon_startup_failed",stateDir:t.paths.baseDir,infoPath:t.paths.infoPath,lockPath:t.paths.lockPath,logPath:t.paths.logPath,startupTimeoutMs:15e3,startupAttempts:2,lockRecoveryCount:n,cleanupResults:i,startError:a,daemonProcess:r,...s?{daemonLogTail:s}:{},metadataState:o,hint:function(e,t=_(process.env.AGENT_DEVICE_STATE_DIR)){var a;let r=(a=t,`rm -f ${S(a.infoPath)} ${S(a.lockPath)}`);return e.hasLock&&!e.hasInfo?`agent-device attempted to clean stale daemon metadata automatically, but ${t.lockPath} still exists without ${t.infoPath}. Retry with --debug; if this persists after confirming no agent-device daemon process is running, run: ${r}`:e.hasLock&&e.hasInfo?`agent-device attempted to clean stale daemon metadata automatically, but ${t.infoPath} and ${t.lockPath} still remain. Retry with --debug; if this persists after confirming no agent-device daemon process is running, run: ${r}`:e.hasInfo?`agent-device did not observe reachable daemon metadata after retrying, and ${t.infoPath} still remains. Stale metadata was cleaned automatically when safe; retry with --debug. If this persists after confirming no agent-device daemon process is running, run: ${r}`:`agent-device did not observe reachable daemon metadata after retrying. Stale metadata was cleaned automatically when safe; retry with --debug and check daemon diagnostics logs. If stale metadata returns after confirming no agent-device daemon process is running, run: ${r}`}(o,t.paths)})}async function tg(t,a,r){if(!tb(t.command)||!a.startedByClient&&!r.ownedStateDir||eB(a.info))return;let n={pid:a.info.pid,removedInfo:!1,removedLock:!1,removedStateDir:!1,error:void 0};try{await eF(a.info)}catch(e){n.error=e instanceof Error?e.message:String(e)}finally{let t=e.existsSync(r.paths.infoPath);eq(r.paths.infoPath),n.removedInfo=t&&!e.existsSync(r.paths.infoPath);let a=e.existsSync(r.paths.lockPath);eq(r.paths.lockPath),n.removedLock=a&&!e.existsSync(r.paths.lockPath),r.ownedStateDir&&(e.rmSync(r.paths.baseDir,{recursive:!0,force:!0}),n.removedStateDir=!e.existsSync(r.paths.baseDir))}g({level:n.error?"warn":"info",phase:"daemon_replay_cleanup",data:n})}function tb(e){return e===ee.replay||e===ee.test}async function tv(e,t,a){let r,n=Date.now();for(a.exited.then(e=>{r=e});Date.now()-n<e;){if(r)return{kind:"early_exit",exit:r};let e=e$(t.paths.infoPath);if(e&&await te(e,t.transportPreference))return{kind:"ready",info:e};if(r)return{kind:"early_exit",exit:r};await er(100)}return{kind:"timeout"}}function tI(){let t=ea(),a=[r.join(t,"dist","src","internal","daemon.js"),r.join(t,"dist","src","daemon.js")],n=a[0];if(void 0===n)throw new f("COMMAND_FAILED","Daemon dist path list is empty");let i=a.find(t=>e.existsSync(t))??n,o=r.join(t,"src","daemon.ts"),s=a.some(t=>e.existsSync(t)),l=e.existsSync(o);if(!s&&!l)throw new f("COMMAND_FAILED","Daemon entry not found",{distPaths:a,srcPath:o});return{root:t,distPath:i,distPaths:a,srcPath:o,useSrc:process.execArgv.includes("--experimental-strip-types")?l:!s&&l}}function tA(){let e=tI();return E(e.useSrc?e.srcPath:e.distPath,e.root)}function tS(e){return e.error?`daemon process ${e.pid} failed to start: ${e.error}`:e.signal?`daemon process ${e.pid} exited before readiness with signal ${e.signal}`:`daemon process ${e.pid} exited before readiness with code ${e.exitCode??0}`}async function tM(e){let t=e.meta?.requestId??y(),a=!!(e.meta?.debug||e.flags?.verbose),r=tp(e),n=function(e){if(e.command!==ee.test){var t;return"number"==typeof e.flags?.timeoutMs&&((t=e.command)===ee.prepare||t===ee.replay||t===ee.snapshot)?e.flags.timeoutMs:e.command===ee.prepare?24e4:9e4}}(e),i=await w("daemon_startup",async()=>await tm(r),{requestId:t,session:e.session}),o=i.info,s=await eM(e,o),l={...e,positionals:s.positionals,flags:s.flags,token:o.token,meta:{...e.meta??{},requestId:t,debug:a,cwd:e.meta?.cwd,sessionExplicit:e.meta?.sessionExplicit,tenantId:e.meta?.tenantId??e.flags?.tenant,runId:e.meta?.runId??e.flags?.runId,leaseId:e.meta?.leaseId??e.flags?.leaseId,sessionIsolation:e.meta?.sessionIsolation??e.flags?.sessionIsolation,lockPolicy:e.meta?.lockPolicy,lockPlatform:e.meta?.lockPlatform,...s.uploadedArtifactId?{uploadedArtifactId:s.uploadedArtifactId}:{},...s.clientArtifactPaths?{clientArtifactPaths:s.clientArtifactPaths}:{},...s.installSource?{installSource:s.installSource}:{}}};g({level:"info",phase:"daemon_request_prepare",data:{requestId:t,command:e.command,session:e.session}});try{return await w("daemon_request",async()=>await tn(o,l,r.transportPreference,r.paths,n),{requestId:t,command:e.command})}finally{await tg(e,i,r)}}tf.addSubnet("127.0.0.0",8,"ipv4"),tf.addAddress("::1","ipv6"),tf.addSubnet("::ffff:127.0.0.0",104,"ipv6");let tP=/^[0-9a-fA-F-]{32,36}$/;function tD(e){if(e&&tP.test(e))return e.replaceAll("-","").toUpperCase()}function t_(e,t){return`${e.uuid}:${tk(t)}`}function tk(e){return`0x${e.toString(16)}`}function tE(e){return"string"==typeof e&&e.length>0?e:void 0}function tx(...e){for(let t of e){let e=tE(t);if(e)return e}}function tN(e){return"object"==typeof e&&null!==e}function t$(e){return tN(e)?e:void 0}function tT(e){try{let t=JSON.parse(e);return tN(t)?t:null}catch{return null}}function tC(e){if("number"==typeof e&&Number.isSafeInteger(e))return e;if("string"==typeof e){let t=e.startsWith("0x")?Number.parseInt(e,16):Number(e);return Number.isSafeInteger(t)?t:void 0}}function tU(e,t,a){var r;if(!Object.hasOwn(e,t))return;let n="bigint"==typeof(r=e[t])?r:"number"==typeof r&&Number.isSafeInteger(r)?BigInt(r):"string"!=typeof r?void 0:/^(?:0x[0-9a-fA-F]+|\d+)$/.test(r)?BigInt(r):void 0;if(void 0!==n)return n;tL(a,t)}function tL(e,t){throw new f("INVALID_ARGS",`Invalid ${e} numeric field: ${t}`,{hint:"Crash artifact numeric fields must be integer numbers or integer numeric strings."})}function tO(e){return[...new Set(e)]}let tR=/^(?:arm64e?|arm64_32|x86_64|armv7[sk]?|i386)$/;async function tF(e){return e.dsym&&e.searchPath?[tG(e.cwd,e.dsym),...await tB(tG(e.cwd,e.searchPath))]:e.dsym?[tG(e.cwd,e.dsym)]:e.searchPath?await tB(tG(e.cwd,e.searchPath)):[]}async function tB(e){let t=[],a=0;async function n(i){if(!(t.length>=200)){if((a+=1)>1e4)throw new f("COMMAND_FAILED","debug symbols search-path scan exceeded bounds.",{searchPath:e,maxEntries:1e4,hint:"Pass --dsym <App.dSYM> directly or narrow --search-path to the build products directory."});if(!(await tj(i,e)).isDirectory()){i===e&&function(e){throw new f("INVALID_ARGS",`debug symbols search path is not a directory: ${e}`,{hint:"Pass an existing build products directory to --search-path, or pass --dsym <App.dSYM> directly."})}(e);return}if(i.endsWith(".dSYM"))return void t.push(i);for(let e of(await d.readdir(i,{withFileTypes:!0})))e.isDirectory()&&await n(r.join(i,e.name))}}return await n(e),t}async function tj(e,t){try{return await d.stat(e)}catch{throw new f("INVALID_ARGS",`debug symbols search path does not exist: ${t}`,{hint:"Pass an existing build products directory to --search-path, or pass --dsym <App.dSYM> directly."})}}async function tq(e,t){let a=(await Promise.all(tO(e).map(e=>tV(e,t)))).flat();if(0===a.length)throw new f("COMMAND_FAILED","No UUIDs found in dSYM bundle.",{hint:"Verify the path points to a built .dSYM bundle with DWARF contents."});return a}async function tV(e,t){var a;await tH(e);let r=await m(t,["--uuid",e],{timeoutMs:15e3,allowFailure:!0});if(0!==r.exitCode)throw new f("COMMAND_FAILED",`Failed to inspect dSYM UUIDs: ${e}`,{stderr:r.stderr,hint:"Verify the dSYM bundle is valid and readable."});return a=e,r.stdout.split("\n").flatMap(e=>{let t=e.match(/^UUID:\s+([0-9a-fA-F-]{32,36})\s+\(([^)]+)\)\s+(.+)$/),r=tD(t?.[1]);return t&&r?[{dsymPath:a,uuid:r,arch:t[2],binaryPath:t[3].trim()}]:[]})}async function tH(e){let t=await d.stat(e).catch(()=>null);if(!(t?.isDirectory()&&e.endsWith(".dSYM")))throw new f("INVALID_ARGS",`Not a .dSYM bundle: ${e}`,{hint:"Pass the .dSYM bundle path, not the DWARF executable inside it."})}function tG(e,t){return r.resolve(e,t)}function tK(e,t){let a=`${t}:`,r=e.find(e=>e.trimStart().startsWith(a));return r&&r.slice(r.indexOf(":")+1).trim()||void 0}function tz(e,t,a,r){return{index:e,image:t.name,address:tk(a),symbol:r.get(t_(t,a))?.text}}function tY(e){var t;let a;return[(a=(t=e).topFrames.find(e=>e.symbol))?`Start with ${a.symbol} in ${a.image}; it is the first symbolicated frame captured on the crashed thread.`:t.topFrames.length>0?"No symbolicated frame was found on the crashed thread; verify matching dSYMs for the top images.":void 0,e.exceptionType?`Exception: ${e.exceptionType}`:void 0,e.terminationReason?`Termination: ${e.terminationReason}`:void 0].filter(e=>!!e).slice(0,3)}async function tW(e,t,a){let r=new Map;for(let n of(function(e,t){let a=new Map;for(let r of e){let e=t.get(r.image.uuid);if(!e)continue;let n=`${r.image.uuid}:${e.dsym.binaryPath}`,i=a.get(n)??{...e,addresses:[]};i.addresses.push(r.address),a.set(n,i)}return a})(e,t).values())for(let e of(await tJ(a,n)))r.set(t_(e.image,e.address),e);return r}async function tJ(e,t){var a,r,n,i;let o,s,l=tO(t.addresses.map(tk)),c=await m(e,(a=t,r=l,["-arch",a.image.arch??a.dsym.arch??"arm64","-o",a.dsym.binaryPath,"-l",tk(a.image.base),...r]),{timeoutMs:3e4,allowFailure:!0});return 0!==c.exitCode&&function(e){throw new f("COMMAND_FAILED","atos failed while symbolicating crash frames.",{stderr:e,hint:"Verify the crash artifact and dSYM were produced from the same build and architecture."})}(c.stderr),n=t.image,i=l,s=(""===(o=c.stdout.split(/\r?\n/)).at(-1)&&o.pop(),o),i.map((e,t)=>{let a=s[t]?.trim();return{image:n,address:BigInt(e),text:!function(e,t){if(!e)return!1;let a=e.trim().toLowerCase();return!!a&&"??"!==a&&a!==t.toLowerCase()&&!a.startsWith("0x")}(a,e)?void 0:a}})}async function tX(){return{dwarfdump:await tQ("dwarfdump"),atos:await tQ("atos")}}async function tQ(e){try{let t=await m("xcrun",["--find",e],{timeoutMs:5e3,allowFailure:!0}),a=t.stdout.trim();if(0===t.exitCode&&a.length>0)return a}catch{}throw new f("TOOL_MISSING",`Apple symbolication tool not found: ${e}`,{hint:"Install Xcode Command Line Tools and verify xcrun --find dwarfdump and xcrun --find atos succeed."})}async function tZ(e){var t,a,n,i,o,s,l,c,u,p,m,h,y,w,g,b,v,I,A,S,M,P,D,_,k,E,x;let N,$,T,C,U,L,O,R,F;if(void 0!==e.action&&"symbols"!==e.action)throw new f("INVALID_ARGS","debug supports only the symbols workflow.",{hint:"Use debug symbols --artifact <crash.ips|crash.log> --dsym <App.dSYM> or --search-path <dir> --out <path>."});let B=e.cwd??process.cwd(),j=t3(B,e.artifact),q=t3(B,e.out??(a=j,$=(N=r.extname(a))?a.slice(0,-N.length):a,`${$}-symbolicated${N||".log"}`)),V=function(e){var t;let a,n=function(e){let t=tT(e);if(t)return{payload:t};let a=e.indexOf("\n");if(-1===a)return null;let r=e.slice(0,a),n=tT(e.slice(a+1));return n?{header:r,payload:n}:null}(e);if(!n)return null;let i=(Array.isArray(n.payload.usedImages)?n.payload.usedImages:[]).flatMap((e,t)=>(function(e,t){if(!e||"object"!=typeof e)return[];let a=tD(tE(e.uuid)),n=tU(e,"base","IPS usedImages");if(!a||void 0===n)return[];let i=tE(e.path);return[{index:t,name:tE(e.name)??(i?r.basename(i):`image-${t}`),uuid:a,arch:tE(e.arch),base:n,path:i}]})(e,t));if(0===i.length)return null;let o=(t=Array.isArray(n.payload.threads)?n.payload.threads:[],a=new Map(i.map(e=>[e.index,e])),t.flatMap((e,t)=>(function(e){if(!e||"object"!=typeof e)return[];let t=e.frames;return Array.isArray(t)?t.filter(e=>tN(e)):[]})(e).flatMap((e,r)=>(function(e,t,a,r){let n=function(e,t,a){if(!Object.hasOwn(e,t))return;let r=tC(e[t]);if(void 0!==r)return r;tL(a,t)}(e,"imageIndex","IPS frame"),i=tU(e,"imageOffset","IPS frame");if(void 0===n||void 0===i)return[];let o=t.get(n);return o?[{frame:e,frameIndex:r,threadIndex:a,image:o,address:o.base+i}]:[]})(e,a,t,r))));return{format:"ips",images:i,addresses:o.map(({frame:e,...t})=>t),document:n,frameMatches:o,write:e=>(function(e,t,a){for(let e of t){let t=a.get(t_(e.image,e.address))?.text;t&&function(e,t){let a,r=(a=t.match(/^(.*) \+ (\d+)$/))?{symbol:a[1],location:Number(a[2])}:{symbol:t};e.symbol=r.symbol,void 0!==r.location&&(e.symbolLocation=r.location)}(e.frame,t)}e.payload.agentDeviceSymbolication={tool:"agent-device debug symbols",symbolicatedFrames:[...a.values()].filter(e=>e.text).length};let r=`${JSON.stringify(e.payload,null,2)}
|
|
1
|
+
import e from"node:fs";import t from"node:http";import a from"node:https";import r from"node:path";import{pipeline as n}from"node:stream/promises";import i from"node:os";import{createHash as o,randomUUID as s}from"node:crypto";import{Writable as l}from"node:stream";import c from"node:net";import d from"node:fs/promises";import{toAppErrorCode as u,AppError as f}from"./733.js";import{runCmdDetachedMonitored as p,runCmd as m,runCmdSync as h}from"./8875.js";import{createRequestId as y,withDiagnosticTimer as w,emitDiagnostic as g}from"./432.js";import{isAgentDeviceDaemonProcess as b,stopProcessForTakeover as v}from"./5628.js";import{readSnapshotDiagnosticsSummary as I,consumeTextLines as A,shellQuote as S,shouldStreamRequestProgress as M,isDaemonResponseEnvelope as _,isDaemonProgressEnvelope as D,resolveDaemonPaths as P,resolveDaemonServerMode as k,computeDaemonCodeSignature as E,resolveDaemonTransportPreference as N}from"./8358.js";import{listCommandFamilyDaemonWriters as x,normalizeSession as $,readSerializedSnapshotCaptureAnnotations as T,readRequiredString as C,findCommandMetadata as U,normalizeMaterializationReleaseResult as L,colorize as O,readSnapshotNodes as R,normalizeDeployResult as F,normalizeOpenDevice as B,buildMeta as j,readOptionalString as q,resolveSessionName as V,supportsColor as H,buildRequestFlags as G,createBatchDaemonWriter as K,readMetadataCommandFlags as z,normalizeDevice as Y,normalizeStartupSample as W,readScreenshotOverlayRefs as J,normalizeRuntimeHints as X,normalizeInstallFromSourceResult as Q}from"./2948.js";import{INTERNAL_COMMANDS as Z,PUBLIC_COMMANDS as ee}from"./2133.js";import{readVersion as et,findProjectRoot as ea}from"./1404.js";import{sleep as er}from"./5560.js";import{reloadMetro as en,prepareMetroRuntime as ei}from"./8275.js";let eo="/agent-device";function es(e){return el(e,eo)}function el(e,t){let a=e.endsWith("/")?e:`${e}/`;return new URL(t.replace(/^\/+/,""),a).toString()}function ec(e){let t=e?.trim();return t?{authorization:`Bearer ${t}`,"x-agent-device-token":t}:{}}function ed(e){return new Promise((t,a)=>{let r="";e.setEncoding("utf8"),e.on("data",e=>{r+=e}),e.on("end",()=>t(r)),e.on("error",a)})}let eu="sha256";async function ef(e){let t=await ep(e.localPath,e.platform),a=e.baseUrl.endsWith("/")?e.baseUrl:`${e.baseUrl}/`;try{let r=await ew({normalizedBase:a,token:e.token,artifact:t});if(r?.kind==="cache-hit")return r.uploadId;if(r?.kind==="direct-upload")try{return await eg(t.payloadPath,r),await eA({normalizedBase:a,token:e.token,uploadId:r.uploadId})}catch{}return await ey({normalizedBase:a,token:e.token,artifact:t})}finally{t.cleanup()}}async function ep(t,a){var n,i,o;let s,l=e.statSync(t),c=r.basename(t),d=l.isDirectory(),u=("ios"===(n=a)||"android"===n?n:void 0)??(i=t,o=l,s=i.toLowerCase(),o.isDirectory()&&s.endsWith(".app")||s.endsWith(".ipa")?"ios":s.endsWith(".apk")||s.endsWith(".aab")?"android":void 0),f=[];try{let a=d?await em(t,f):t,r=e.statSync(a);return{payloadPath:a,fileName:c,artifactType:d?"app-bundle":"file",platform:u,contentType:d?"application/gzip":"application/octet-stream",sha256:await eS(a),sizeBytes:r.size,cleanup:()=>eh(f)}}catch(e){throw eh(f),e}}async function em(t,a){let n=e.mkdtempSync(r.join(i.tmpdir(),`agent-device-upload-${s()}-`));a.push(n);let o=r.join(n,`${r.basename(t)}.tar.gz`);return await m("tar",["czf",o,"-C",r.dirname(t),r.basename(t)],{env:{...process.env,COPYFILE_DISABLE:"1"}}),o}function eh(t){for(let a of t)e.rmSync(a,{recursive:!0,force:!0})}async function ey(e){let{normalizedBase:t,token:a,artifact:r}=e,n=new URL("upload",t),i={"content-type":r.contentType,"x-artifact-type":r.artifactType,"x-artifact-filename":r.fileName,"x-artifact-hash":r.sha256,"x-artifact-hash-algorithm":eu,"transfer-encoding":"chunked"};Object.assign(i,ec(a));let o=await eb({url:n,method:"POST",headers:i,payloadPath:r.payloadPath,timeoutMessage:"Artifact upload timed out",timeoutHint:"The upload to the remote daemon exceeded the 5-minute timeout.",errorMessage:"Failed to upload artifact to remote daemon",errorHint:"Verify the remote daemon is reachable and supports artifact uploads."});try{let e=JSON.parse(o.body);if(!e.ok||!e.uploadId)throw new f("COMMAND_FAILED",`Upload failed: ${o.body}`);return e.uploadId}catch(e){if(e instanceof f)throw e;throw new f("COMMAND_FAILED",`Invalid upload response: ${o.body}`)}}async function ew(e){let t=new URL("upload/preflight",e.normalizedBase),a={"content-type":"application/json"};Object.assign(a,ec(e.token));let r=await fetch(t,{method:"POST",headers:a,signal:AbortSignal.timeout(3e4),body:JSON.stringify({sha256:e.artifact.sha256,fileName:e.artifact.fileName,sizeBytes:e.artifact.sizeBytes,artifactType:e.artifact.artifactType,...e.artifact.platform?{platform:e.artifact.platform}:{},contentType:e.artifact.contentType})}).catch(()=>void 0);if(r?.ok)return function(e){var t;if(!e||"object"!=typeof e||!0!==e.ok||"string"!=typeof e.uploadId)return;if(!0===e.cacheHit)return{kind:"cache-hit",uploadId:e.uploadId};let a=e.upload;if(!a||"string"!=typeof a.url)return;let r=a.headers??{};if(!(!(t=r)||"object"!=typeof t||Array.isArray(t))&&Object.values(t).every(e=>"string"==typeof e))return{kind:"direct-upload",uploadId:e.uploadId,url:a.url,headers:r}}(await r.json().catch(()=>void 0))}async function eg(e,t){let a=await eb({url:new URL(t.url),method:"PUT",headers:t.headers,payloadPath:e,timeoutMessage:"Direct artifact upload timed out",timeoutHint:"The direct upload ticket did not accept the artifact within the timeout.",errorMessage:"Failed to upload artifact with direct upload ticket"});if(a.statusCode<200||a.statusCode>=300)throw new f("COMMAND_FAILED","Direct artifact upload failed",{statusCode:a.statusCode,statusMessage:a.statusMessage})}async function eb(e){return await ev({...e,url:e.url,redirectCount:0,startOffset:0})}async function ev(r){var i,o,s;let l="https:"===r.url.protocol?a:t,c=e.statSync(r.payloadPath).size,d=(i=r.headers,o=r.startOffset,s=c,o<=0?i:{...i,"content-length":Math.max(s-o,0),"content-range":`bytes ${o}-${s-1}/${s}`});return await new Promise((t,a)=>{let i=!1,o=l.request({protocol:r.url.protocol,host:r.url.hostname,port:r.url.port,method:r.method,path:r.url.pathname+r.url.search,headers:d},e=>{i=!0,ed(e).then(n=>{clearTimeout(s);let i=e.statusCode??500,o=e.headers.location;if(o&&[301,302,303,307,308].includes(i)){if(r.redirectCount>=5)return void a(new f("COMMAND_FAILED","Artifact upload exceeded redirect limit",{maxRedirects:5,url:r.url.toString()}));let e=new URL(o,r.url);return void ev({...r,url:e,redirectCount:r.redirectCount+1}).then(t,a)}let l=308===i?function(e,t){let a=function(e){let t=eI(e);if(void 0===t)return;let a=Number(t);return Number.isSafeInteger(a)&&a>=0?a:void 0}(e["x-upload-offset"]??e["upload-offset"]);if(void 0!==a)return Math.min(a,t);let r=eI(e.range),n=r?.match(/^bytes=0-(\d+)$/);if(!n)return;let i=Number(n[1]);if(Number.isSafeInteger(i)&&!(i<0))return Math.min(i+1,t)}(e.headers,c):void 0;void 0!==l?l>=c?t({statusCode:200,statusMessage:"Upload already complete",body:""}):l<=r.startOffset?a(new f("COMMAND_FAILED","Artifact upload resume did not advance",{offset:l,previousOffset:r.startOffset,url:r.url.toString()})):ev({...r,startOffset:l}).then(t,a):t({statusCode:i,statusMessage:e.statusMessage,body:n})}).catch(a)}),s=setTimeout(()=>{o.destroy(),a(new f("COMMAND_FAILED",r.timeoutMessage,{timeoutMs:3e5,...r.timeoutHint?{hint:r.timeoutHint}:{}}))},3e5);o.on("error",e=>{i||(clearTimeout(s),a(new f("COMMAND_FAILED",r.errorMessage,r.errorHint?{hint:r.errorHint}:{},e)))}),o.on("close",()=>clearTimeout(s)),n(e.createReadStream(r.payloadPath,{start:r.startOffset}),o).catch(e=>{i||(o.destroy(),a(new f("COMMAND_FAILED","Failed to read local artifact",{},e instanceof Error?e:Error(String(e)))))})})}function eI(e){return Array.isArray(e)?e[0]:e}async function eA(e){let t=new URL("upload/finalize",e.normalizedBase),a={"content-type":"application/json"};Object.assign(a,ec(e.token));let r=await fetch(t,{method:"POST",headers:a,signal:AbortSignal.timeout(3e4),body:JSON.stringify({uploadId:e.uploadId})}).catch(e=>{throw new f("COMMAND_FAILED","Failed to finalize direct artifact upload",{},e)});if(!r.ok)throw new f("COMMAND_FAILED","Direct artifact upload finalize failed",{status:r.status,statusText:r.statusText});let n=await r.json().catch(()=>void 0);if(!n?.ok||!n.uploadId)throw new f("COMMAND_FAILED","Invalid upload finalize response");return n.uploadId}async function eS(t){let a=o(eu),r=new l({write(e,t,r){a.update(e),r()}});return await n(e.createReadStream(t),r).catch(e=>{throw new f("COMMAND_FAILED","Failed to read local artifact",{},e instanceof Error?e:void 0)}),a.digest("hex")}async function eM(e,t){var a;let n,i=[...e.positionals??[]],o=e.flags?{...e.flags}:void 0,s=e.meta?.installSource,l={};if(!("string"==typeof(a=t).baseUrl&&a.baseUrl.length>0))return eD({positionals:i,flags:o,installSource:s,uploadedArtifactId:n,clientArtifactPaths:l});o=function(e,t,a,n){var i,o;let s=function(e,t){if("screenshot"===e.command){let a=ek(e,"path",".png");return t[0]?{field:"path",localPath:a,positionalIndex:0,positionalPath:eE("screenshot",".png")}:{field:"path",localPath:a,positionalIndex:0,flagPath:eE("screenshot",".png")}}if("record"===e.command&&"start"===(t[0]??"").toLowerCase()){let t=ek(e,"outPath",".mp4",1);return{field:"outPath",localPath:t,positionalIndex:1,positionalPath:eE("recording",r.extname(t)||".mp4")}}return null}(e,t);if(!s)return a;void 0!==s.positionalPath&&(t[s.positionalIndex]=s.positionalPath);let l=(i=a,void 0===(o=s.flagPath)?i:{...i??{},out:o});return n[s.field]=s.localPath,l}(e,i,o,l);let c=await eP(e,t);c&&(s=c.installSource,n=c.uploadedArtifactId??n);let d=()=>eD({positionals:i,flags:o,installSource:s,uploadedArtifactId:n,clientArtifactPaths:l});return"install"!==e.command&&"reinstall"!==e.command||(n=await e_(e,t,i)??n),d()}async function e_(t,a,n){var i,o;let s,l=n[1];if(void 0===l)return;if(l.startsWith("remote:")){n[1]=l.slice(7);return}let c=(i=l,o=t.meta?.cwd,s=r.isAbsolute(i)?i:r.resolve(o??process.cwd(),i),e.existsSync(s)?s:void 0);if(c)return await ef({localPath:c,baseUrl:a.baseUrl,token:a.token,platform:t.flags?.platform})}function eD(e){return{positionals:e.positionals,flags:e.flags,installSource:e.installSource,uploadedArtifactId:e.uploadedArtifactId,...Object.keys(e.clientArtifactPaths).length>0?{clientArtifactPaths:e.clientArtifactPaths}:{}}}async function eP(t,a){let n=t.meta?.installSource;if("install_source"!==t.command||!n||"path"!==n.kind)return null;let i=n.path.trim();if(!i)return{installSource:n};if(i.startsWith("remote:"))return{installSource:{...n,path:i.slice(7)}};let o=r.isAbsolute(i)?i:r.resolve(t.meta?.cwd??process.cwd(),i);if(!e.existsSync(o))return{installSource:{...n,path:o}};let s=await ef({localPath:o,baseUrl:a.baseUrl,token:a.token,platform:t.flags?.platform});return{installSource:{...n,path:o},uploadedArtifactId:s}}function ek(e,t,a,n=0){let i=e.positionals?.[n]??e.flags?.out,o=`${"path"===t?"screenshot":"recording"}-${Date.now()}${a}`,s=i&&i.trim().length>0?i:o;return r.isAbsolute(s)?s:r.resolve(e.meta?.cwd??process.cwd(),s)}function eE(e,t){let a=t.startsWith(".")?t:`.${t}`;return r.posix.join("/tmp",`agent-device-${e}-${Date.now()}-${Math.random().toString(36).slice(2,8)}${a}`)}async function eN(e,t,a){let n=Array.isArray(a.data?.artifacts)?a.data.artifacts:[];if(0===n.length||!e.baseUrl)return a;let i=a.data?{...a.data}:{},o=[];for(let a of n){if(!a||"object"!=typeof a||"string"!=typeof a.artifactId){o.push(a);continue}let n=function(e,t){if(e.localPath&&e.localPath.trim().length>0)return e.localPath;let a=t.meta?.clientArtifactPaths?.[e.field];if(a&&a.trim().length>0)return a;let n=e.fileName?.trim()||`${e.field}-${Date.now()}`;return r.resolve(t.meta?.cwd??process.cwd(),n)}(a,t);await ex({baseUrl:e.baseUrl,token:e.token,artifactId:a.artifactId,destinationPath:n,requestId:t.meta?.requestId}),i[a.field]=n,o.push({...a,localPath:n})}return i.artifacts=o,{ok:!0,data:i}}async function ex(i){var o,s;let l,c=new URL((o=i.baseUrl,s=i.artifactId,l=o.endsWith("/")?o:`${o}/`,new URL(`artifacts/${encodeURIComponent(s)}`,l).toString())),d="https:"===c.protocol?a:t;await e.promises.mkdir(r.dirname(i.destinationPath),{recursive:!0}),await new Promise((t,a)=>{let r=!1,o=i.timeoutMs??9e4,s=n=>{if(!r){if(r=!0,clearTimeout(u),n)return void e.promises.rm(i.destinationPath,{force:!0}).finally(()=>a(n));t()}},l=d.request({protocol:c.protocol,host:c.hostname,port:c.port,method:"GET",path:c.pathname+c.search,headers:ec(i.token)},t=>{if((t.statusCode??500)>=400){let e="";t.setEncoding("utf8"),t.on("data",t=>{e+=t}),t.on("end",()=>{s(new f("COMMAND_FAILED","Failed to download remote artifact",{artifactId:i.artifactId,statusCode:t.statusCode,requestId:i.requestId,body:e}))});return}t.on("aborted",()=>{s(new f("COMMAND_FAILED","Remote artifact download was interrupted",{artifactId:i.artifactId,requestId:i.requestId}))}),n(t,e.createWriteStream(i.destinationPath)).then(()=>s(),e=>s(e instanceof Error?e:Error(String(e))))}),u=setTimeout(()=>{let e=new f("COMMAND_FAILED","Remote artifact download timed out",{artifactId:i.artifactId,requestId:i.requestId,timeoutMs:o});s(e),l.destroy(e)},o);l.on("error",e=>{e instanceof f?s(e):s(new f("COMMAND_FAILED","Failed to download remote artifact",{artifactId:i.artifactId,requestId:i.requestId,timeoutMs:o},e instanceof Error?e:void 0))}),l.end()})}function e$(e){var t,a,r;let n,i,o=ej(e);if(!o||"object"!=typeof o)return null;let s="string"==typeof(t=o).token&&t.token.length>0?t.token:null;if(!s)return null;let l=(n=eC((a=o).port),i=eC(a.httpPort),void 0===n&&void 0===i?null:{port:n,httpPort:i});return l?{token:s,...l,transport:"socket"===(r=o.transport)||"http"===r||"dual"===r?r:void 0,pid:eC(o.pid)??0,version:eT(o.version),codeSignature:eT(o.codeSignature),processStartTime:eT(o.processStartTime)}:null}function eT(e){return"string"==typeof e?e:void 0}function eC(e){return Number.isInteger(e)&&Number(e)>0?Number(e):void 0}function eU(e){let t=ej(e);return t&&"object"==typeof t&&Number.isInteger(t.pid)&&Number(t.pid)>0?{pid:Number(t.pid),processStartTime:"string"==typeof t.processStartTime?t.processStartTime:void 0,startedAt:"number"==typeof t.startedAt?t.startedAt:void 0}:null}async function eL(t,a,r={}){let n=r.stopLiveProcesses??!0,i={reason:a,removedInfo:!1,removedLock:!1,stoppedInfoProcess:!1,stoppedLockProcess:!1};try{var o,s,l,c;let a=e.existsSync(t.infoPath),r=e$(t.infoPath);if(r){let e=b(r.pid,r.processStartTime);e&&!n?i.retainedInfoProcess=!0:(e&&(await eF(r),i.stoppedInfoProcess=!0),o=t.infoPath,eq(o),i.removedInfo=!0)}else a&&(s=t.infoPath,eq(s),i.removedInfo=!0);let d=e.existsSync(t.lockPath),u=eU(t.lockPath);if(u){let e=b(u.pid,u.processStartTime);e&&!n?i.retainedLockProcess=!0:(e&&(await v(u.pid,{termTimeoutMs:3e3,killTimeoutMs:1e3,expectedStartTime:u.processStartTime}),i.stoppedLockProcess=!0),l=t.lockPath,eq(l),i.removedLock=!0)}else d&&(c=t.lockPath,eq(c),i.removedLock=!0)}catch(e){i.error=e instanceof Error?e.message:String(e)}return g({level:i.error?"warn":"info",phase:"daemon_startup_metadata_cleanup",data:i}),i}function eO(t){return{hasInfo:e.existsSync(t.infoPath),hasLock:e.existsSync(t.lockPath)}}async function eR(e){let t=eO(e);if(!t.hasLock||t.hasInfo)return!1;let a=eU(e.lockPath);return!(a&&b(a.pid,a.processStartTime))&&(eq(e.lockPath),!0)}async function eF(e){await v(e.pid,{termTimeoutMs:3e3,killTimeoutMs:1e3,expectedStartTime:e.processStartTime})}function eB(e){return"string"==typeof e.baseUrl&&e.baseUrl.length>0}function ej(t){if(!e.existsSync(t))return null;try{return JSON.parse(e.readFileSync(t,"utf8"))}catch{return null}}function eq(t){try{e.existsSync(t)&&e.unlinkSync(t)}catch{}}function eV(e){let t=Math.max(0,e)/1e3;return t>=10?`${t.toFixed(1)}s`:t>=1?`${t.toFixed(2)}s`:`${t.toFixed(3).replace(/0+$/,"").replace(/\.$/,"")}s`}function eH(e){let t=eG(e),a=t.findIndex(({stop:e})=>!1===e.ok);if(a<0)return[];let r=t.slice(Math.max(0,a-2),a+1);return[e.attempts>1?`steps (attempt ${e.attempts}):`:"steps:",...r.map(({stop:e,start:t})=>eW(e,t))]}function eG(t){var a,n;let i=(a=t).artifactsDir?r.join(a.artifactsDir,`attempt-${a.attempts}`,"replay-timing.ndjson"):void 0;if(!i)return[];let o=function(t){try{return e.readFileSync(t,"utf8").split(/\r?\n/).filter(e=>e.trim().length>0).flatMap(e=>{try{let t=JSON.parse(e);return eX(t)?[t]:[]}catch{return[]}})}catch{return[]}}(i);if(0===o.length)return[];let s=[],l=[];for(let e of o){if("replay_action_start"===(n=e).type&&eK(n)&&ez(n,"line")&&eY(n,"command")&&(void 0===n.positionals||Array.isArray(n.positionals))){s.push(e);continue}(function(e){var t;return["replay_action_stop"===e.type&&eK(e)&&ez(e,"line")&&eY(e,"command"),void 0===(t=e).ok||"boolean"==typeof t.ok,ez(e,"durationMs"),eY(e,"errorCode"),void 0===e.resultTiming||eX(e.resultTiming)].every(Boolean)})(e)&&l.push({stop:e,start:function(e,t){let a=t.command,r=e.findIndex(e=>e.step===t.step&&(void 0===a||void 0===e.command||e.command===a));if(!(r<0))return e.splice(r,1)[0]}(s,e)})}return l}function eK(e){return"number"==typeof e.step}function ez(e,t){return void 0===e[t]||"number"==typeof e[t]}function eY(e,t){return void 0===e[t]||"string"==typeof e[t]}function eW(e,t){var a,r,n,i;let o,s,l=!1===e.ok?"[FAIL] ":!0===e.ok?"":"[info] ";return` ${l}${a=t,r=e,[function(e){if(!e)return"unknown";if(!e.startsWith("__maestro"))return e;let t=e.slice(9);return t.length>0?t[0].toLowerCase()+t.slice(1):e}(a?.command??r.command),...(a?.positionals??[]).map(eJ)].join(" ")}${n=e,i=t,(s=["number"==typeof(o=i?.line??n.line)?`line ${o}`:"","number"==typeof n.durationMs?eV(n.durationMs):"",n.errorCode??"",n.resultTiming?`timing ${JSON.stringify(n.resultTiming)}`:""].filter(Boolean)).length>0?` (${s.join(", ")})`:""}`}function eJ(e){return"string"==typeof e?JSON.stringify(e):"number"==typeof e||"boolean"==typeof e?String(e):JSON.stringify(e)}function eX(e){return!!e&&"object"==typeof e&&!Array.isArray(e)}function eQ(e,t){return O(e,t,{validateStream:!1})}function eZ(e){if("number"!=typeof e.shardIndex)return"";let t="number"==typeof e.shardCount?e.shardCount:"?",a="string"==typeof e.deviceId?` ${e.deviceId}`:"";return` [shard ${e.shardIndex+1}/${t}${a}]`}function e0(e){return`\r\x1b[2K${e}`}function e1(e){return"number"==typeof e&&Number.isFinite(e)&&e>0?Math.floor(e):80}function e3(e,t){let a=e1(t);return e.length<=a?e:a<=0?"":a<=3?".".repeat(a):`${e.slice(0,a-3)}...`}function e2(e){return{file:e.file,title:e.title,durationMs:e.durationMs??0,attempts:e.attempt??1,artifactsDir:e.artifactsDir,session:e.session??""}}function e5(e){return function(e={}){let t=new Set,a=!1;return{render(n){var i,o;if("replay-test-suite"===n.type){t.clear(),a=!1;return}if("replay-test"!==n.type)return;if("progress"===n.status){if(!e.liveProgress)return;return a=!0,{text:e0(function(e,t){let a=e.title?.trim(),n=r.basename(e.file),i=eZ(e),o=e.stepIndex??0,s=e.stepTotal??0,l=`${i} [${o}/${s}]`,c="⊙ ";if(!a)return e3(`${c}${n}${l}`,t.columns);let d=`${c}"`,u=`" in ${n}${l}`,f=e3(a,Math.max(0,e1(t.columns)-d.length-u.length));return e3(`${d}${f}${u}`,t.columns)}(n,e)),newline:!1}}if("pass"===(i=n).status||"skip"===i.status||"fail"===i.status&&!i.retrying){let e,a=(e="number"==typeof(o=n).shardIndex?o.shardIndex:"",[o.status,o.index,o.total,o.file,o.title??"",e].join("\0"));if(t.has(a))return;t.add(a)}let s=function(e,t={}){if("replay-test"===e.type)return function(e,t){var a,n,i,o;let s,l,c,d,u,f;if("start"===e.status||"progress"===e.status||"fail"===e.status&&e.retrying)return;let p=[(c=function(e){let t=H(process.stderr);if("pass"===e.status){let a=e.attempt&&e.attempt>1?"yellow":"green";return t?eQ("✓",a):"✓"}return"fail"===e.status?t?eQ("⨯","red"):"⨯":"progress"===e.status?"⊙":t?eQ("-","dim"):"-"}(a=e),d=(n=a,s=n.title?.trim(),l=r.basename(n.file),s?`${JSON.stringify(s)} in ${l}`:l),u=eZ(a),f=void 0!==a.durationMs?` (${eV(a.durationMs??0)})`:"",`${c} ${d}${u}${f}`)];return function(e,t,a){if(a.verbose&&"fail"===t.status)return;let r=t.message?.replace(/\s+/g," ").trim();r&&e.push(` ${"fail"===t.status?`failed at: ${r}`:r}`),"fail"===t.status&&!t.retrying&&(t.session&&e.push(` session: ${t.session}`),t.artifactsDir&&e.push(` artifacts: ${t.artifactsDir}`))}(p,e,t),t.verbose&&p.push(...("pass"===(i=e).status||"fail"===i.status)&&i.artifactsDir&&i.attempt?(function(e){if("skipped"===e.status)return[];let t=eG(e);return 0===t.length?[]:[e.attempts>1?`steps (attempt ${e.attempts}):`:"steps:",...t.map(({stop:e,start:t})=>eW(e,t))]})("pass"===i.status?{...e2(i),status:"passed",replayed:0,healed:0}:{...e2(o=i),status:"failed",error:{code:"COMMAND_FAILED",message:o.message??"Unknown test failure"}}).map(e=>` ${e}`):[]),p.join("\n")}(e,t)}(n,e);if(!s)return;let l=a?e0(s):s;return a=!1,{text:l,newline:!0}}}}({verbose:!!(e.flags?.verbose||e.meta?.debug),liveProgress:!0===process.stderr.isTTY&&!process.env.CI,columns:process.stderr.columns})}function e4(e,t){let a=t.render(e);a&&process.stderr.write(a.newline?`${a.text}
|
|
2
|
+
`:a.text)}function e8(e,t){let{info:a,req:r,resolve:n,reject:i}=t;try{var o,s,l;let t=(o=e,JSON.parse(o));if(t.error){let e;return void i((s=t.error,l=r.meta?.requestId,e=s.data??{},new f(u(null!=e.code?String(e.code):void 0,"COMMAND_FAILED"),String(e.message??s.message??"Daemon RPC request failed"),{..."object"==typeof e.details&&e.details?e.details:{},hint:"string"==typeof e.hint?e.hint:void 0,diagnosticId:"string"==typeof e.diagnosticId?e.diagnosticId:void 0,logPath:"string"==typeof e.logPath?e.logPath:void 0,requestId:l})))}if(!t.result||"object"!=typeof t.result)return void i(new f("COMMAND_FAILED","Invalid daemon RPC response",{requestId:r.meta?.requestId}));e6(a,r,t.result,n,i)}catch(t){i(new f("COMMAND_FAILED","Invalid daemon response",{requestId:r.meta?.requestId,line:e},t instanceof Error?t:void 0))}}async function e6(e,t,a,r,n){try{r(e.baseUrl&&a.ok?await eN(e,t,a):a)}catch(e){n(e)}}let e7=["xcodebuild .*AgentDeviceRunnerUITests/RunnerTests/testCommand","xcodebuild .*AgentDeviceRunner\\.env\\.session-","xcodebuild build-for-testing .*ios-runner/AgentDeviceRunner/AgentDeviceRunner\\.xcodeproj"];function e9(e,t,a,r,n,i){let o=n?{terminated:0}:function(){let e=0;try{for(let t of e7){let a=h("pkill",["-f",t],{allowFailure:!0});0===a.exitCode&&(e+=1)}return{terminated:e}}catch(t){return{terminated:e,error:t instanceof Error?t.message:String(t)}}}(),s=!n&&"snapshot"!==r,l=s?function(e,t){let a=!1;try{b(e.pid,e.processStartTime)&&(process.kill(e.pid,"SIGKILL"),a=!0)}catch{eF(e)}finally{eq(t.infoPath),eq(t.lockPath)}return{forcedKill:a}}(e,t):{forcedKill:!1};return g({level:"error",phase:"daemon_request_timeout",data:{timeoutMs:i,requestId:a,command:r,timedOutRunnerPidsTerminated:o.terminated,timedOutRunnerCleanupError:o.error,daemonPidReset:s?e.pid:void 0,daemonPidForceKilled:s?l.forcedKill:void 0,daemonPreservedAfterTimeout:!n&&!s,daemonBaseUrl:e.baseUrl}}),new f("COMMAND_FAILED","Daemon request timed out",{timeoutMs:i,requestId:a,hint:function(e){let{remote:t,resetDaemon:a,command:r}=e;if(t)return"Retry with --debug and verify the remote daemon URL, auth token, and remote host logs.";if(!a){let e=r===ee.snapshot?" If this was the first Apple-platform snapshot on the device, run agent-device prepare ios-runner with the same --platform before snapshot/test so runner startup is handled explicitly.":"";return`Retry with --debug and check daemon diagnostics logs. The timed-out ${r??"request"} request was canceled and Apple runner work was aborted when detected; the daemon was kept alive so the session can still be closed or inspected.${e}`}return"Retry with --debug and check daemon diagnostics logs. Timed-out Apple runner xcodebuild processes were terminated when detected."}({remote:n,resetDaemon:s,command:r})})}let te="Daemon HTTP endpoint is unavailable",tt="Daemon socket endpoint is unavailable";async function ta(e,t){let a=tl(e,t);if(await tr(e,a))return!0;let r=td(e,t,a);return!!r&&await tr(e,r)}async function tr(e,t){var a;return"http"===t?await ti(e).then(e=>e.reachable):await ((a=e.port)?new Promise(e=>{let t=!1,r=c.createConnection({host:"127.0.0.1",port:a},()=>{n(!0)}),n=a=>{t||(t=!0,r.destroy(),e(a))};r.setTimeout(500),r.on("timeout",()=>{n(!1)}),r.on("error",()=>{n(!1)})}):Promise.resolve(!1))}async function tn(e){let t=await ti(e);if(!e.baseUrl||!t.reachable)return t;if("number"==typeof t.rpcProtocolVersion&&1!==t.rpcProtocolVersion)throw new f("COMMAND_FAILED","Remote daemon RPC protocol is incompatible",{daemonBaseUrl:e.baseUrl,clientVersion:et(),remoteVersion:t.version,remoteService:t.service,supportedRpcProtocolVersion:1,remoteRpcProtocolVersion:t.rpcProtocolVersion,hint:"Upgrade agent-device on the client or remote host so both support the same daemon RPC protocol."});return t}function ti(e){let r=e.baseUrl?el(e.baseUrl,"health"):e.httpPort?`http://127.0.0.1:${e.httpPort}/health`:null;if(!r)return Promise.resolve({reachable:!1});let n=new URL(r),i="https:"===n.protocol?a:t,o=e.baseUrl?3e3:500;return new Promise(t=>{let a=e.baseUrl?ec(e.token):{},r=i.request({protocol:n.protocol,host:n.hostname,port:n.port,path:n.pathname+n.search,method:"GET",timeout:o,headers:a},e=>{let a="";e.setEncoding("utf8"),e.on("data",e=>{a+=e}),e.on("end",()=>{let r=e.statusCode??500;t({reachable:r<500,statusCode:r,...function(e){try{let t=JSON.parse(e);return{service:"string"==typeof t.service?t.service:void 0,version:"string"==typeof t.version?t.version:void 0,rpcProtocolVersion:"number"==typeof t.rpcProtocolVersion?t.rpcProtocolVersion:void 0}}catch{return{}}}(a)})})});r.on("timeout",()=>{r.destroy(),t({reachable:!1})}),r.on("error",()=>{t({reachable:!1})}),r.end()})}async function to(e,t,a,r,n){let i=tl(e,a);try{return await ts(e,t,r,n,i)}catch(l){var o;let s=td(e,a,i);if(!s||(o=l,"socket"!==i||!(o instanceof f)||"COMMAND_FAILED"!==o.code||"Failed to communicate with daemon"!==o.message||o.details?.daemonSocketRequestWritten!==!1))throw l;return await ts(e,t,r,n,s)}}async function ts(e,t,a,r,n){return"http"===n?await tp(e,t,a,r):await tf(e,t,a,r)}function tl(e,t){if(e.baseUrl){if("socket"===t)throw new f("COMMAND_FAILED","Remote daemon endpoint only supports HTTP transport",{daemonBaseUrl:e.baseUrl});return"http"}if("http"===t||"socket"===t){var a=e,r=t;if(tc(a,r))return r;throw new f("COMMAND_FAILED","http"===r?te:tt)}let n=("socket"===e.transport||"dual"===e.transport?["socket","http"]:["http","socket"]).find(t=>tc(e,t));if(n)return n;throw new f("COMMAND_FAILED","Daemon metadata has no reachable transport")}function tc(e,t){return"http"===t?!!e.httpPort:!!e.port}function td(e,t,a){if("auto"!==t||e.baseUrl)return null;let r="socket"===a?"http":"socket";return tc(e,r)?r:null}function tu(e,t,a,r={}){return g({level:"error",phase:"daemon_request_socket_error",data:{requestId:t,message:e instanceof Error?e.message:String(e)}}),new f("COMMAND_FAILED","Failed to communicate with daemon",{...r,requestId:t,hint:a?"Retry command. If this persists, verify the remote daemon URL, auth token, and remote host reachability.":"Retry command. If this persists, clean stale daemon metadata and start a fresh session."},e instanceof Error?e:void 0)}async function tf(e,t,a,r){let n=e.port;if(!n)throw new f("COMMAND_FAILED",tt);return new Promise((i,o)=>{let s=!1,l=c.createConnection({host:"127.0.0.1",port:n},()=>{s=!0,l.write(`${JSON.stringify(t)}
|
|
3
|
+
`)}),d=!1,u="number"==typeof r?setTimeout(()=>{d=!0,l.destroy(),o(e9(e,a,t.meta?.requestId,t.command,!1,r))},r):void 0;!function(e,t){let{req:a,isSettled:r,resolve:n,reject:i,clearTimeout:o}=t,s="",l=e5(a),c=(e,t)=>{o(),i(new f("COMMAND_FAILED","Invalid daemon response",{requestId:a.meta?.requestId,line:e},t instanceof Error?t:void 0))};e.setEncoding("utf8"),e.on("data",t=>{if(r())return;let a=A(s,t);for(let t of(s=a.buffer,a.lines))try{let a=JSON.parse(t);if(D(a)){e4(a.event,l);continue}let r=_(a)?a.response:a;o(),n(r),e.end();return}catch(e){c(t,e);return}})}(l,{req:t,isSettled:()=>d,clearTimeout:()=>{u&&clearTimeout(u)},resolve:e=>{d=!0,i(e)},reject:e=>{d=!0,o(e)}}),l.on("error",e=>{d||(d=!0,u&&clearTimeout(u),o(tu(e,t.meta?.requestId,!1,{daemonSocketRequestWritten:s})))})})}async function tp(e,r,n,i){var o,s;let l,c=e.baseUrl?new URL(el(e.baseUrl,"rpc")):e.httpPort?new URL(`http://127.0.0.1:${e.httpPort}/rpc`):null;if(!c)throw new f("COMMAND_FAILED",te);let d=JSON.stringify((o={includeTokenParam:!e.baseUrl},l=r.meta?.requestId??y(),"lease_allocate"!==(s=r.command)&&"lease_heartbeat"!==s&&"lease_release"!==s?{jsonrpc:"2.0",id:l,method:"agent_device.command",params:r}:{jsonrpc:"2.0",id:l,method:function(e){switch(e){case"lease_allocate":return"agent_device.lease.allocate";case"lease_heartbeat":return"agent_device.lease.heartbeat";case"lease_release":return"agent_device.lease.release"}}(r.command),params:function(e,t,a){let r={...a.includeTokenParam?{token:e.token}:{},session:e.session,tenantId:e.meta?.tenantId,runId:e.meta?.runId};switch(t){case"lease_allocate":return{...r,ttlMs:e.meta?.leaseTtlMs,backend:e.meta?.leaseBackend};case"lease_heartbeat":return{...r,leaseId:e.meta?.leaseId,ttlMs:e.meta?.leaseTtlMs};case"lease_release":return{...r,leaseId:e.meta?.leaseId}}}(r,r.command,o)})),u={"content-type":"application/json","content-length":Buffer.byteLength(d)};return e.baseUrl&&Object.assign(u,ec(e.token)),await new Promise((o,s)=>{let l=("https:"===c.protocol?a:t).request({protocol:c.protocol,host:c.hostname,port:c.port,method:"POST",path:c.pathname+c.search,headers:u},t=>{var a;(a=t.headers?.["content-type"],M(r)&&String(Array.isArray(a)?a.join(","):a??"").includes("application/x-ndjson"))?function(e,t){let{req:a,handleResponseBody:r,reject:n,clearTimeout:i}=t,o="",s=!1,l=e5(a),c=e=>{try{let t=JSON.parse(e);if(D(t))return e4(t.event,l),!1;if(_(t))return s=!0,i(),r(JSON.stringify(t.response)),!0;throw Error("Missing daemon progress response envelope")}catch(t){return s=!0,i(),n(new f("COMMAND_FAILED","Invalid daemon response",{requestId:a.meta?.requestId,line:e},t instanceof Error?t:void 0)),!0}};e.setEncoding("utf8"),e.on("data",e=>{if(s)return;let t=A(o,e);for(let e of(o=t.buffer,t.lines))if(e&&c(e))return}),e.on("end",()=>{if(s)return;let e=o.trim();e&&c(e)||(s=!0,i(),n(new f("COMMAND_FAILED","Invalid daemon response",{requestId:a.meta?.requestId,line:e})))}),e.on("error",e=>{s||(s=!0,i(),n(new f("COMMAND_FAILED","Failed to read daemon response",{requestId:a.meta?.requestId},e instanceof Error?e:void 0)))})}(t,{req:r,reject:s,clearTimeout:()=>{m&&clearTimeout(m)},handleResponseBody:t=>e8(t,{info:e,req:r,resolve:o,reject:s})}):ed(t).then(t=>{m&&clearTimeout(m),e8(t,{info:e,req:r,resolve:o,reject:s})}).catch(e=>{m&&clearTimeout(m),s(new f("COMMAND_FAILED","Failed to read daemon response",{requestId:r.meta?.requestId},e instanceof Error?e:void 0))})}),p=eB(e),m="number"==typeof i?setTimeout(()=>{l.destroy(),s(e9(e,n,r.meta?.requestId,r.command,p,i))},i):void 0;l.on("error",e=>{m&&clearTimeout(m),s(tu(e,r.meta?.requestId,p))}),l.write(d),l.end()})}let tm=new c.BlockList;function th(t){var a,n,o,s,l;let d,u,p,m=(a=t,a.flags?.stateDir??process.env.AGENT_DEVICE_STATE_DIR),h=(n=t,u=function(e){let t;if(e){try{t=new URL(e)}catch(t){throw new f("INVALID_ARGS","Invalid daemon base URL",{daemonBaseUrl:e},t instanceof Error?t:void 0)}if("http:"!==t.protocol&&"https:"!==t.protocol)throw new f("INVALID_ARGS","Daemon base URL must use http or https",{daemonBaseUrl:e});return t.toString().replace(/\/+$/,"")}}(d=n.flags?.daemonBaseUrl??process.env.AGENT_DEVICE_DAEMON_BASE_URL),function(e,t){let a;if(!(!e||"localhost"===(a=new URL(e).hostname.trim().toLowerCase().replace(/^\[(.*)\]$/,"$1"))||(c.isIPv4(a)?tm.check(a,"ipv4"):!!c.isIPv6(a)&&tm.check(a,"ipv6")))&&("string"!=typeof t||!(t.trim().length>0)))throw new f("INVALID_ARGS","Remote daemon base URL for non-loopback hosts requires daemon authentication",{daemonBaseUrl:e,hint:"Provide --daemon-auth-token or AGENT_DEVICE_DAEMON_AUTH_TOKEN when using a non-loopback remote daemon URL."})}(u,p=n.flags?.daemonAuthToken??process.env.AGENT_DEVICE_DAEMON_AUTH_TOKEN),{rawBaseUrl:d,remoteBaseUrl:u,authToken:p}),y=function(e,t){let a=e.flags?.daemonTransport??process.env.AGENT_DEVICE_DAEMON_TRANSPORT,r=N(a);if(t&&"socket"===r)throw new f("INVALID_ARGS","Remote daemon base URL only supports HTTP transport. Remove --daemon-transport socket.",{daemonBaseUrl:t});return{preference:r,serverMode:k(e.flags?.daemonServerMode??process.env.AGENT_DEVICE_DAEMON_SERVER_MODE??("dual"===a?"dual":void 0))}}(t,h.remoteBaseUrl),w=(o=t,s=m,l=h.rawBaseUrl,tA(o.command)&&!s&&!l);return{paths:P(w?e.mkdtempSync(r.join(i.tmpdir(),"agent-device-replay-daemon-")):m),transportPreference:y.preference,serverMode:y.serverMode,ownedStateDir:w,remoteBaseUrl:h.remoteBaseUrl,remoteAuthToken:h.authToken}}async function ty(e){if(e.remoteBaseUrl)return await tw(e);let t=await tg(e);return t?{info:t,startedByClient:!1}:(!function(e){let t=eO(e);if(!t.hasLock||t.hasInfo)return;let a=eU(e.lockPath);if(!a)return eq(e.lockPath);b(a.pid,a.processStartTime)||eq(e.lockPath)}(e.paths),await tv(e))}async function tw(e){let t={transport:"http",token:e.remoteAuthToken??"",pid:0,baseUrl:e.remoteBaseUrl};if((await tn(t)).reachable)return{info:t,startedByClient:!1};throw new f("COMMAND_FAILED","Remote daemon is unavailable",{daemonBaseUrl:e.remoteBaseUrl,hint:"Verify AGENT_DEVICE_DAEMON_BASE_URL points to a reachable daemon with GET /health and POST /rpc."})}async function tg(e){var t,a;let r=e$(e.paths.infoPath);if(!r)return null;let n=await tb(r,e.transportPreference);return(t=r,a=n,t.version===et()&&t.codeSignature===t_()&&a)?r:(function(e,t,a){try{var r,n;let i=e.version?`pid ${e.pid}, v${e.version}`:`pid ${e.pid}`,o=(r=e,n=t,r.version!==et()?`version mismatch (client v${et()})`:r.codeSignature!==t_()?"code-signature mismatch":n?"not reusable":"unreachable");process.stderr.write(`Replacing daemon (${i}) in ${a}: ${o}
|
|
4
|
+
`)}catch{}}(r,n,e.paths.baseDir),await eF(r),eq(e.paths.infoPath),null)}async function tb(e,t){try{return await ta(e,t)}catch(e){var a;if((a=e)instanceof f&&"COMMAND_FAILED"===a.code&&(a.message===te||a.message===tt))return!1;throw e}}async function tv(t){let a,r,n=0,i=[];for(let o=1;o<=2;o+=1){let s;try{r={pid:(s=function(t){let a=tM(),r=a.useSrc?["--experimental-strip-types",a.srcPath]:[a.distPath],n={...process.env,AGENT_DEVICE_STATE_DIR:t.paths.baseDir,AGENT_DEVICE_DAEMON_SERVER_MODE:t.serverMode};e.mkdirSync(t.paths.baseDir,{recursive:!0});let i=e.openSync(t.paths.logPath,"a"),o=e.openSync(t.paths.logPath,"a");try{return p(process.execPath,r,{env:n,stdio:["ignore",i,o]})}finally{e.closeSync(i),e.closeSync(o)}}(t)).pid}}catch(e){if(a=e instanceof Error?e.message:String(e),i.push(await eL(t.paths,"start_error")),o<2){await er(150);continue}break}let l=await tS(15e3,t,s);if("ready"===l.kind)return{info:l.info,startedByClient:!0};if("early_exit"===l.kind){if(r=l.exit,a=tD(l.exit),i.push(await eL(t.paths,"start_error")),o<2){await er(150);continue}break}if(await eR(t.paths)){n+=1;continue}let c=eO(t.paths),d=o<2,u=await eL(t.paths,"startup_timeout",{stopLiveProcesses:!1});if(i.push(u),u.retainedInfoProcess||u.retainedLockProcess){let e=await tS(15e3,t,s);if("ready"===e.kind)return{info:e.info,startedByClient:!0};"early_exit"===e.kind&&(r=e.exit,a=tD(e.exit));break}if(!d)break;c.hasInfo||c.hasLock||await er(150)}let o=eO(t.paths),s=function(t){try{if(!e.existsSync(t))return;let a=e.statSync(t);if(a.size<=0)return;let r=Math.min(a.size,64e3),n=e.openSync(t,"r");try{let t=Buffer.alloc(r);e.readSync(n,t,0,r,a.size-r);let i=t.toString("utf8").trim();return i.length>0?i:void 0}finally{e.closeSync(n)}}catch{return}}(t.paths.logPath);throw new f("COMMAND_FAILED","Failed to start daemon",{kind:"daemon_startup_failed",stateDir:t.paths.baseDir,infoPath:t.paths.infoPath,lockPath:t.paths.lockPath,logPath:t.paths.logPath,startupTimeoutMs:15e3,startupAttempts:2,lockRecoveryCount:n,cleanupResults:i,startError:a,daemonProcess:r,...s?{daemonLogTail:s}:{},metadataState:o,hint:function(e,t=P(process.env.AGENT_DEVICE_STATE_DIR)){var a;let r=(a=t,`rm -f ${S(a.infoPath)} ${S(a.lockPath)}`);return e.hasLock&&!e.hasInfo?`agent-device attempted to clean stale daemon metadata automatically, but ${t.lockPath} still exists without ${t.infoPath}. Retry with --debug; if this persists after confirming no agent-device daemon process is running, run: ${r}`:e.hasLock&&e.hasInfo?`agent-device attempted to clean stale daemon metadata automatically, but ${t.infoPath} and ${t.lockPath} still remain. Retry with --debug; if this persists after confirming no agent-device daemon process is running, run: ${r}`:e.hasInfo?`agent-device did not observe reachable daemon metadata after retrying, and ${t.infoPath} still remains. Stale metadata was cleaned automatically when safe; retry with --debug. If this persists after confirming no agent-device daemon process is running, run: ${r}`:`agent-device did not observe reachable daemon metadata after retrying. Stale metadata was cleaned automatically when safe; retry with --debug and check daemon diagnostics logs. If stale metadata returns after confirming no agent-device daemon process is running, run: ${r}`}(o,t.paths)})}async function tI(t,a,r){if(!tA(t.command)||!a.startedByClient&&!r.ownedStateDir||eB(a.info))return;let n={pid:a.info.pid,removedInfo:!1,removedLock:!1,removedStateDir:!1,error:void 0};try{await eF(a.info)}catch(e){n.error=e instanceof Error?e.message:String(e)}finally{let t=e.existsSync(r.paths.infoPath);eq(r.paths.infoPath),n.removedInfo=t&&!e.existsSync(r.paths.infoPath);let a=e.existsSync(r.paths.lockPath);eq(r.paths.lockPath),n.removedLock=a&&!e.existsSync(r.paths.lockPath),r.ownedStateDir&&(e.rmSync(r.paths.baseDir,{recursive:!0,force:!0}),n.removedStateDir=!e.existsSync(r.paths.baseDir))}g({level:n.error?"warn":"info",phase:"daemon_replay_cleanup",data:n})}function tA(e){return e===ee.replay||e===ee.test}async function tS(e,t,a){let r,n=Date.now();for(a.exited.then(e=>{r=e});Date.now()-n<e;){if(r)return{kind:"early_exit",exit:r};let e=e$(t.paths.infoPath);if(e&&await ta(e,t.transportPreference))return{kind:"ready",info:e};if(r)return{kind:"early_exit",exit:r};await er(100)}return{kind:"timeout"}}function tM(){let t=ea(),a=[r.join(t,"dist","src","internal","daemon.js"),r.join(t,"dist","src","daemon.js")],n=a[0];if(void 0===n)throw new f("COMMAND_FAILED","Daemon dist path list is empty");let i=a.find(t=>e.existsSync(t))??n,o=r.join(t,"src","daemon.ts"),s=a.some(t=>e.existsSync(t)),l=e.existsSync(o);if(!s&&!l)throw new f("COMMAND_FAILED","Daemon entry not found",{distPaths:a,srcPath:o});return{root:t,distPath:i,distPaths:a,srcPath:o,useSrc:process.execArgv.includes("--experimental-strip-types")?l:!s&&l}}function t_(){let e=tM();return E(e.useSrc?e.srcPath:e.distPath,e.root)}function tD(e){return e.error?`daemon process ${e.pid} failed to start: ${e.error}`:e.signal?`daemon process ${e.pid} exited before readiness with signal ${e.signal}`:`daemon process ${e.pid} exited before readiness with code ${e.exitCode??0}`}async function tP(e){let t=e.meta?.requestId??y(),a=!!(e.meta?.debug||e.flags?.verbose),r=th(e),n=function(e){if(e.command!==ee.test){var t;return"number"==typeof e.flags?.timeoutMs&&((t=e.command)===ee.prepare||t===ee.replay||t===ee.snapshot)?e.flags.timeoutMs:e.command===ee.prepare?24e4:9e4}}(e),i=await w("daemon_startup",async()=>await ty(r),{requestId:t,session:e.session}),o=i.info,s=await eM(e,o),l={...e,positionals:s.positionals,flags:s.flags,token:o.token,meta:{...e.meta??{},requestId:t,debug:a,cwd:e.meta?.cwd,sessionExplicit:e.meta?.sessionExplicit,tenantId:e.meta?.tenantId??e.flags?.tenant,runId:e.meta?.runId??e.flags?.runId,leaseId:e.meta?.leaseId??e.flags?.leaseId,sessionIsolation:e.meta?.sessionIsolation??e.flags?.sessionIsolation,lockPolicy:e.meta?.lockPolicy,lockPlatform:e.meta?.lockPlatform,...s.uploadedArtifactId?{uploadedArtifactId:s.uploadedArtifactId}:{},...s.clientArtifactPaths?{clientArtifactPaths:s.clientArtifactPaths}:{},...s.installSource?{installSource:s.installSource}:{}}};g({level:"info",phase:"daemon_request_prepare",data:{requestId:t,command:e.command,session:e.session}});try{return await w("daemon_request",async()=>await to(o,l,r.transportPreference,r.paths,n),{requestId:t,command:e.command})}finally{await tI(e,i,r)}}tm.addSubnet("127.0.0.0",8,"ipv4"),tm.addAddress("::1","ipv6"),tm.addSubnet("::ffff:127.0.0.0",104,"ipv6");let tk=/^[0-9a-fA-F-]{32,36}$/;function tE(e){if(e&&tk.test(e))return e.replaceAll("-","").toUpperCase()}function tN(e,t){return`${e.uuid}:${tx(t)}`}function tx(e){return`0x${e.toString(16)}`}function t$(e){return"string"==typeof e&&e.length>0?e:void 0}function tT(...e){for(let t of e){let e=t$(t);if(e)return e}}function tC(e){return"object"==typeof e&&null!==e}function tU(e){return tC(e)?e:void 0}function tL(e){try{let t=JSON.parse(e);return tC(t)?t:null}catch{return null}}function tO(e){if("number"==typeof e&&Number.isSafeInteger(e))return e;if("string"==typeof e){let t=e.startsWith("0x")?Number.parseInt(e,16):Number(e);return Number.isSafeInteger(t)?t:void 0}}function tR(e,t,a){var r;if(!Object.hasOwn(e,t))return;let n="bigint"==typeof(r=e[t])?r:"number"==typeof r&&Number.isSafeInteger(r)?BigInt(r):"string"!=typeof r?void 0:/^(?:0x[0-9a-fA-F]+|\d+)$/.test(r)?BigInt(r):void 0;if(void 0!==n)return n;tF(a,t)}function tF(e,t){throw new f("INVALID_ARGS",`Invalid ${e} numeric field: ${t}`,{hint:"Crash artifact numeric fields must be integer numbers or integer numeric strings."})}function tB(e){return[...new Set(e)]}let tj=/^(?:arm64e?|arm64_32|x86_64|armv7[sk]?|i386)$/;async function tq(e){return e.dsym&&e.searchPath?[tY(e.cwd,e.dsym),...await tV(tY(e.cwd,e.searchPath))]:e.dsym?[tY(e.cwd,e.dsym)]:e.searchPath?await tV(tY(e.cwd,e.searchPath)):[]}async function tV(e){let t=[],a=0;async function n(i){if(!(t.length>=200)){if((a+=1)>1e4)throw new f("COMMAND_FAILED","debug symbols search-path scan exceeded bounds.",{searchPath:e,maxEntries:1e4,hint:"Pass --dsym <App.dSYM> directly or narrow --search-path to the build products directory."});if(!(await tH(i,e)).isDirectory()){i===e&&function(e){throw new f("INVALID_ARGS",`debug symbols search path is not a directory: ${e}`,{hint:"Pass an existing build products directory to --search-path, or pass --dsym <App.dSYM> directly."})}(e);return}if(i.endsWith(".dSYM"))return void t.push(i);for(let e of(await d.readdir(i,{withFileTypes:!0})))e.isDirectory()&&await n(r.join(i,e.name))}}return await n(e),t}async function tH(e,t){try{return await d.stat(e)}catch{throw new f("INVALID_ARGS",`debug symbols search path does not exist: ${t}`,{hint:"Pass an existing build products directory to --search-path, or pass --dsym <App.dSYM> directly."})}}async function tG(e,t){let a=(await Promise.all(tB(e).map(e=>tK(e,t)))).flat();if(0===a.length)throw new f("COMMAND_FAILED","No UUIDs found in dSYM bundle.",{hint:"Verify the path points to a built .dSYM bundle with DWARF contents."});return a}async function tK(e,t){var a;await tz(e);let r=await m(t,["--uuid",e],{timeoutMs:15e3,allowFailure:!0});if(0!==r.exitCode)throw new f("COMMAND_FAILED",`Failed to inspect dSYM UUIDs: ${e}`,{stderr:r.stderr,hint:"Verify the dSYM bundle is valid and readable."});return a=e,r.stdout.split("\n").flatMap(e=>{let t=e.match(/^UUID:\s+([0-9a-fA-F-]{32,36})\s+\(([^)]+)\)\s+(.+)$/),r=tE(t?.[1]);return t&&r?[{dsymPath:a,uuid:r,arch:t[2],binaryPath:t[3].trim()}]:[]})}async function tz(e){let t=await d.stat(e).catch(()=>null);if(!(t?.isDirectory()&&e.endsWith(".dSYM")))throw new f("INVALID_ARGS",`Not a .dSYM bundle: ${e}`,{hint:"Pass the .dSYM bundle path, not the DWARF executable inside it."})}function tY(e,t){return r.resolve(e,t)}function tW(e,t){let a=`${t}:`,r=e.find(e=>e.trimStart().startsWith(a));return r&&r.slice(r.indexOf(":")+1).trim()||void 0}function tJ(e,t,a,r){return{index:e,image:t.name,address:tx(a),symbol:r.get(tN(t,a))?.text}}function tX(e){var t;let a;return[(a=(t=e).topFrames.find(e=>e.symbol))?`Start with ${a.symbol} in ${a.image}; it is the first symbolicated frame captured on the crashed thread.`:t.topFrames.length>0?"No symbolicated frame was found on the crashed thread; verify matching dSYMs for the top images.":void 0,e.exceptionType?`Exception: ${e.exceptionType}`:void 0,e.terminationReason?`Termination: ${e.terminationReason}`:void 0].filter(e=>!!e).slice(0,3)}async function tQ(e,t,a){let r=new Map;for(let n of(function(e,t){let a=new Map;for(let r of e){let e=t.get(r.image.uuid);if(!e)continue;let n=`${r.image.uuid}:${e.dsym.binaryPath}`,i=a.get(n)??{...e,addresses:[]};i.addresses.push(r.address),a.set(n,i)}return a})(e,t).values())for(let e of(await tZ(a,n)))r.set(tN(e.image,e.address),e);return r}async function tZ(e,t){var a,r,n,i;let o,s,l=tB(t.addresses.map(tx)),c=await m(e,(a=t,r=l,["-arch",a.image.arch??a.dsym.arch??"arm64","-o",a.dsym.binaryPath,"-l",tx(a.image.base),...r]),{timeoutMs:3e4,allowFailure:!0});return 0!==c.exitCode&&function(e){throw new f("COMMAND_FAILED","atos failed while symbolicating crash frames.",{stderr:e,hint:"Verify the crash artifact and dSYM were produced from the same build and architecture."})}(c.stderr),n=t.image,i=l,s=(""===(o=c.stdout.split(/\r?\n/)).at(-1)&&o.pop(),o),i.map((e,t)=>{let a=s[t]?.trim();return{image:n,address:BigInt(e),text:!function(e,t){if(!e)return!1;let a=e.trim().toLowerCase();return!!a&&"??"!==a&&a!==t.toLowerCase()&&!a.startsWith("0x")}(a,e)?void 0:a}})}async function t0(){return{dwarfdump:await t1("dwarfdump"),atos:await t1("atos")}}async function t1(e){try{let t=await m("xcrun",["--find",e],{timeoutMs:5e3,allowFailure:!0}),a=t.stdout.trim();if(0===t.exitCode&&a.length>0)return a}catch{}throw new f("TOOL_MISSING",`Apple symbolication tool not found: ${e}`,{hint:"Install Xcode Command Line Tools and verify xcrun --find dwarfdump and xcrun --find atos succeed."})}async function t3(e){var t,a,n,i,o,s,l,c,u,p,m,h,y,w,g,b,v,I,A,S,M,_,D,P,k,E,N;let x,$,T,C,U,L,O,R,F;if(void 0!==e.action&&"symbols"!==e.action)throw new f("INVALID_ARGS","debug supports only the symbols workflow.",{hint:"Use debug symbols --artifact <crash.ips|crash.log> --dsym <App.dSYM> or --search-path <dir> --out <path>."});let B=e.cwd??process.cwd(),j=t4(B,e.artifact),q=t4(B,e.out??(a=j,$=(x=r.extname(a))?a.slice(0,-x.length):a,`${$}-symbolicated${x||".log"}`)),V=function(e){var t;let a,n=function(e){let t=tL(e);if(t)return{payload:t};let a=e.indexOf("\n");if(-1===a)return null;let r=e.slice(0,a),n=tL(e.slice(a+1));return n?{header:r,payload:n}:null}(e);if(!n)return null;let i=(Array.isArray(n.payload.usedImages)?n.payload.usedImages:[]).flatMap((e,t)=>(function(e,t){if(!e||"object"!=typeof e)return[];let a=tE(t$(e.uuid)),n=tR(e,"base","IPS usedImages");if(!a||void 0===n)return[];let i=t$(e.path);return[{index:t,name:t$(e.name)??(i?r.basename(i):`image-${t}`),uuid:a,arch:t$(e.arch),base:n,path:i}]})(e,t));if(0===i.length)return null;let o=(t=Array.isArray(n.payload.threads)?n.payload.threads:[],a=new Map(i.map(e=>[e.index,e])),t.flatMap((e,t)=>(function(e){if(!e||"object"!=typeof e)return[];let t=e.frames;return Array.isArray(t)?t.filter(e=>tC(e)):[]})(e).flatMap((e,r)=>(function(e,t,a,r){let n=function(e,t,a){if(!Object.hasOwn(e,t))return;let r=tO(e[t]);if(void 0!==r)return r;tF(a,t)}(e,"imageIndex","IPS frame"),i=tR(e,"imageOffset","IPS frame");if(void 0===n||void 0===i)return[];let o=t.get(n);return o?[{frame:e,frameIndex:r,threadIndex:a,image:o,address:o.base+i}]:[]})(e,a,t,r))));return{format:"ips",images:i,addresses:o.map(({frame:e,...t})=>t),document:n,frameMatches:o,write:e=>(function(e,t,a){for(let e of t){let t=a.get(tN(e.image,e.address))?.text;t&&function(e,t){let a,r=(a=t.match(/^(.*) \+ (\d+)$/))?{symbol:a[1],location:Number(a[2])}:{symbol:t};e.symbol=r.symbol,void 0!==r.location&&(e.symbolLocation=r.location)}(e.frame,t)}e.payload.agentDeviceSymbolication={tool:"agent-device debug symbols",symbolicatedFrames:[...a.values()].filter(e=>e.text).length};let r=`${JSON.stringify(e.payload,null,2)}
|
|
5
5
|
`;return e.header?`${e.header}
|
|
6
|
-
${r}`:r})(n,o,e)}}(t=await t0(j,"crash artifact"))??function(e){let t=e.split("\n"),a=function(e){let t=[],a=e.findIndex(e=>/^Binary Images:/i.test(e.trim()));if(-1===a)return t;for(let n of e.slice(a+1)){let e=function(e){let t=e.match(/^\s*(0x[0-9a-fA-F]+)\s*-\s*(0x[0-9a-fA-F]+)\s+\+?(.+?)\s+<([0-9a-fA-F-]{32,36})>\s+(.+)$/);if(!t)return null;let a=tD(t[4]);if(!a)return null;let n=function(e,t){let a=e.split(/\s+/),n=a.at(-1);if(n&&tR.test(n))return{name:a.slice(0,-1).join(" ").trim(),arch:n};let i=r.basename(t);return{name:e.startsWith(i)?i:e}}(t[3].trim(),t[5].trim());return{name:n.name,arch:n.arch,uuid:a,base:BigInt(t[1]),end:BigInt(t[2]),path:t[5].trim()}}(n);e&&t.push(e)}return t}(t);if(0===a.length)return null;let n=function(e,t){let a,r=[];for(let[n,i]of e.entries()){let e=i.match(/^Thread\s+(\d+)\s+Crashed:/);e?a=Number(e[1]):(0===i.trim().length||/^Thread\s+\d+/.test(i))&&(a=void 0);let o=function(e,t){let a=e.match(/^\s*\d+\s+(.+?)\s+(0x[0-9a-fA-F]+)\b/);if(!a)return null;let r=a[1].trim(),n=BigInt(a[2]),i=function(e,t,a){let r=e.filter(e=>e.name===t);return r.find(e=>{var t,r;return t=e,r=a,void 0!==t.end&&t.base<=r&&r<=t.end})??(1===r.length?r[0]:void 0)}(t,r,n);return i?{image:i,address:n}:null}(i,t),s=i.match(/^\s*(\d+)/);o&&s&&r.push({...o,frameIndex:Number(s[1]),lineIndex:n,threadIndex:a})}return r}(t,a);return{format:"text",images:a,addresses:n,lines:t,frameMatches:n,write(e){let a=new Map(n.map(e=>[e.lineIndex,e]));return t.map((t,r)=>{let n=a.get(r);if(!n)return t;let i=e.get(t_(n.image,n.address))?.text;return!i||t.includes(i)?t:`${t} // ${i}`}).join("\n")}}}(t);V||function(){throw new f("UNSUPPORTED_OPERATION","debug symbols currently supports Apple crash artifacts with Binary Images or IPS usedImages.",{hint:"For Android Java/R8 crashes, use retrace with mapping.txt. For Android native crashes, use ndk-stack or addr2line with unstripped .so symbols. Capture the crash with logs, then symbolicate externally until Android support is added."})}();let H=await tF({cwd:B,dsym:e.dsym,searchPath:e.searchPath});if(0===H.length)throw new f("INVALID_ARGS","debug symbols requires --dsym or --search-path.",{hint:"Pass a matching .dSYM bundle directly, or pass --search-path <dir> so agent-device can match crash image UUIDs to local dSYMs."});let G=await tX(),K=await tq(H,G.dwarfdump),z=function(e,t,a){let r=new Map;for(let a of e){let e=t.find(e=>e.uuid===a.uuid&&(void 0===a.arch||void 0===e.arch||e.arch===a.arch));e&&r.set(a.uuid,{image:a,dsym:e})}if(r.size>0)return r;let n=tO(e.map(e=>e.uuid)),i=tO(t.map(e=>e.uuid));throw new f("COMMAND_FAILED",a?"dSYM UUID does not match any Apple image in the crash artifact.":"No matching dSYM UUID found under search path.",{artifactUuidCount:n.length,artifactUuidSample:n.slice(0,5),dsymUuidCount:i.length,dsymUuidSample:i.slice(0,5),hint:"Use dwarfdump --uuid <App.dSYM> and compare it with the crash Binary Images or usedImages UUID, then pass the matching dSYM/search path."})}(V.images,K,!!e.dsym),Y=await tW(V.addresses,z,G.atos),W=V.write(Y);await d.mkdir(r.dirname(q),{recursive:!0}),await d.writeFile(q,W,"utf8");let J=[...z.values()].map(({image:e,dsym:t})=>({name:e.name,uuid:e.uuid,arch:e.arch??t.arch,dsymPath:t.dsymPath,binaryPath:t.binaryPath})),X=[...Y.values()].filter(e=>e.text).length,Q=V.images.length-J.length,Z=Q>0?[`${Q} Apple image${1===Q?"":"s"} had no matching dSYM and were left unchanged.`]:void 0;return{kind:"debugSymbols",platform:"apple",artifactPath:j,outPath:q,crash:"ips"===V.format?(n=V.document,i=V.frameMatches,o=Y,U=function(e){let t=tC(e.faultingThread);if(void 0!==t)return t;let a=(Array.isArray(e.threads)?e.threads:[]).findIndex(e=>t$(e)?.triggered===!0);return -1===a?void 0:a}(n.payload),{...L={format:"ips",...(T=(s=n).payload,C=(l=s.header)?tT(l):null,{appName:(c=T,u=C,tx(c.procName,u?.app_name,u?.name)),bundleId:(p=T,m=C,tx(t$(p.bundleInfo)?.CFBundleIdentifier,m?.bundleID)),version:(h=T,y=C,tx(t$(h.bundleInfo)?.CFBundleShortVersionString,y?.app_version)),incident:(w=T,g=C,tx(w.incident,g?.incident_id)),timestamp:(b=T,v=C,tx(b.captureTime,v?.timestamp)),exceptionType:(I=T.exception,tE(t$(I)?.type)),exceptionCodes:function(e){let t=t$(e);if(t)return tx(t.codes,t.rawCodes)}(T.exception),terminationReason:function(e){let t=t$(e);if(t){let e;return(e=[tE(t.namespace),tE(t.code),tE(t.reason)].filter(e=>!!e)).length>0?e.join(" "):void 0}}(T.termination)}),crashedThread:U,topFrames:(A=i,S=U,M=o,A.filter(e=>void 0===S||e.threadIndex===S).slice(0,5).map(e=>tz(e.frameIndex,e.image,e.address,M))),findings:[]},findings:tY(L)}):(P=V.lines,D=V.frameMatches,_=Y,R=function(e){let t=tK(e,"Triggered by Thread"),a=t?Number.parseInt(t,10):NaN;if(Number.isSafeInteger(a))return a;for(let t of e){let e=t.match(/^Thread\s+(\d+)\s+Crashed:/);if(e)return Number(e[1])}}(P),{...F={format:"text",appName:(O=tK(P,"Process"),O?.replace(/\s+\[\d+\]$/,"")),bundleId:tK(P,"Identifier"),version:tK(P,"Version"),incident:tK(P,"Incident Identifier"),timestamp:tK(P,"Date/Time"),exceptionType:tK(P,"Exception Type"),exceptionCodes:tK(P,"Exception Codes"),terminationReason:tK(P,"Termination Reason"),crashedThread:R,topFrames:(k=D,E=R,x=_,void 0===E?[]:k.filter(e=>e.threadIndex===E).slice(0,5).map(e=>tz(e.frameIndex,e.image,e.address,x))),findings:[]},findings:tY(F)}),matchedImages:J,symbolicatedFrames:X,skippedImages:Q,warnings:Z,message:`Symbolicated ${X} frame${1===X?"":"s"} -> ${q}`}}async function t0(e,t){await t1(e,t);try{return await d.readFile(e,"utf8")}catch(a){throw new f("INVALID_ARGS",`Failed to read ${t}: ${e}`,{message:a instanceof Error?a.message:String(a)})}}async function t1(e,t){try{let a=await d.stat(e);if(a.size<=0x4000000)return;throw new f("INVALID_ARGS",`${t} is too large: ${e}`,{actualBytes:a.size,maxBytes:0x4000000,hint:"Pass a bounded Apple .ips/.crash artifact. For very large logs, first narrow the log to the crash report, or use logs grep/tail for lead-up context."})}catch(a){if(a instanceof f)throw a;throw new f("INVALID_ARGS",`Failed to read ${t}: ${e}`,{message:a instanceof Error?a.message:String(a)})}}function t3(e,t){return r.resolve(e,t)}let t2={...N(),batch:K(function(e,t,a){let r=t2[e];if(!r)throw Error(`Missing daemon writer for batch command: ${e}`);let n=U(e);if(!n)throw Error(`Missing command metadata for batch command: ${e}`);try{return t5(r,n,n.readInput(t))}catch(r){let t=r instanceof Error?r.message:String(r);throw new f("INVALID_ARGS",`Batch step ${a} ${e} input is invalid: ${t}`,void 0,r)}})};function t5(e,t,a){let r=e(a);return{...r,...t?{metadataFlags:z(t,r.options)}:{}}}function t4(e={},t={}){let a=t.transport??tM,r=async(t,r=[],n={},i)=>{let o=t6(e,n),s=await a({session:V(o.session),command:t,positionals:r,flags:G(o,i),runtime:o.runtime,meta:j(o)});return s.ok||function(e){throw new f(u(e.code),e.message,{...e.details??{},hint:e.hint,diagnosticId:e.diagnosticId,logPath:e.logPath})}(s.error),s.data??{}},n=async(e={})=>{let t=await r(Z.sessionList,[],e);return(Array.isArray(t.sessions)?t.sessions:[]).map($)},i=async(e,t={})=>{let a=function(e,t){let a=t2[e];if(!a)throw Error(`Missing daemon writer for command: ${e}`);return t5(a,U(e),t)}(e,t);return await r(a.command,a.positionals,a.options,a.metadataFlags)},o=(t={})=>V(t6(e,t).session);return{command:{wait:async e=>await i("wait",e),alert:async(e={})=>await i("alert",e),appState:async(e={})=>await i("appstate",e),back:async(e={})=>await i("back",e),home:async(e={})=>await i("home",e),rotate:async e=>await i("rotate",e),appSwitcher:async(e={})=>await i("app-switcher",e),keyboard:async(e={})=>await i("keyboard",e),clipboard:async e=>await i("clipboard",e),reactNative:async e=>await i("react-native",e),prepare:async e=>await i("prepare",e),viewport:async e=>await i("viewport",e)},devices:{list:async(e={})=>{let t=await i("devices",e);return(Array.isArray(t.devices)?t.devices:[]).map(Y)},boot:async(e={})=>await i("boot",e),shutdown:async(e={})=>await i("shutdown",e)},sessions:{list:async(e={})=>await n(e),stateDir:async(t={})=>_(t6(e,t).stateDir??process.env.AGENT_DEVICE_STATE_DIR).baseDir,close:async(e={})=>{let t=o(e),a=(await i("close",e)).shutdown;return{session:t,shutdown:"object"==typeof a&&null!==a?a:void 0,identifiers:{session:t}}}},apps:{install:async e=>F(await i("install",e),o(e)),reinstall:async e=>F(await i("reinstall",e),o(e)),installFromSource:async e=>Q(await i("install-from-source",e),o(e)),list:async(e={})=>{let t=await i("apps",e);return Array.isArray(t.apps)?t.apps.filter(e=>"string"==typeof e):[]},open:async e=>{let t=o(e),a=await i("open",e),r=B(a),n=q(a,"appBundleId");return{session:t,sessionStateDir:q(a,"sessionStateDir"),appName:q(a,"appName"),appBundleId:n,appId:n,startup:W(a.startup),runtime:X(a.runtime),device:r,identifiers:{session:t,deviceId:r?.id,deviceName:r?.name,udid:r?.ios?.udid,serial:r?.android?.serial,appId:n,appBundleId:n}}},close:async(e={})=>{let t=o(e),a=(await i("close",e)).shutdown;return{session:t,closedApp:e.app,shutdown:"object"==typeof a&&null!==a?a:void 0,identifiers:{session:t}}},push:async e=>await i("push",e),triggerEvent:async e=>await i("trigger-app-event",e)},materializations:{release:async e=>L(await r(Z.releaseMaterializedPaths,[],{...e,materializationId:e.materializationId}))},leases:{allocate:async e=>t7(await r(Z.leaseAllocate,[],{...e,leaseId:void 0,leaseTtlMs:e.ttlMs})),heartbeat:async e=>t7(await r(Z.leaseHeartbeat,[],{...e,leaseTtlMs:e.ttlMs})),release:async e=>({released:!0===(await r(Z.leaseRelease,[],e)).released})},metro:{prepare:async t=>await ei({projectRoot:t.projectRoot??e.cwd,kind:t.kind,publicBaseUrl:t.publicBaseUrl,proxyBaseUrl:t.proxyBaseUrl,proxyBearerToken:t.bearerToken,bridgeScope:t.bridgeScope,launchUrl:t.launchUrl,companionProfileKey:t.companionProfileKey,companionConsumerKey:t.companionConsumerKey,metroPort:t.port,listenHost:t.listenHost,statusHost:t.statusHost,startupTimeoutMs:t.startupTimeoutMs,probeTimeoutMs:t.probeTimeoutMs,reuseExisting:t.reuseExisting,installDependenciesIfNeeded:t.installDependenciesIfNeeded,runtimeFilePath:t.runtimeFilePath,logPath:t.logPath}),reload:async(t={})=>await en({metroHost:t.metroHost,metroPort:t.metroPort,bundleUrl:t.bundleUrl,runtime:e.runtime,timeoutMs:t.timeoutMs})},capture:{snapshot:async(e={})=>{var t,a,r;let n,s,l,c,d=o(e);return t=await i("snapshot",e),a=d,n=q(t,"appBundleId"),{nodes:R(t.nodes),truncated:!0===t.truncated,appName:q(t,"appName"),appBundleId:n,...(s=t8((r=t).visibility),l=t8(r.unchanged),c=I(r.snapshotDiagnostics),{...s?{visibility:s}:{},...T(r),...l?{unchanged:l}:{},...c?{snapshotDiagnostics:c}:{}}),identifiers:{session:a,appId:n,appBundleId:n}}},screenshot:async(e={})=>{let t=o(e),a=await i("screenshot",e);return{path:C(a,"path"),overlayRefs:J(a),identifiers:{session:t}}},diff:async e=>await i("diff",e)},interactions:{click:async e=>await i("click",e),press:async e=>await i("press",e),longPress:async e=>await i("longpress",e),swipe:async e=>await i("swipe",e),pan:async e=>await i("gesture-pan",e),fling:async e=>await i("gesture-fling",e),swipeGesture:async e=>await i("gesture-swipe",e),focus:async e=>await i("focus",e),type:async e=>await i("type",e),fill:async e=>await i("fill",e),scroll:async e=>await i("scroll",e),pinch:async e=>await i("gesture-pinch",e),rotateGesture:async e=>await i("gesture-rotate",e),transformGesture:async e=>await i("gesture-transform",e),get:async e=>await i("get",e),is:async e=>await i("is",e),find:async e=>await i("find",e)},replay:{run:async e=>await i("replay",e),test:async e=>await i("test",e)},batch:{run:async e=>await i("batch",e)},observability:{perf:async(e={})=>await i("perf",e),logs:async(e={})=>await i("logs",e),network:async(e={})=>await i("network",e)},debug:{symbols:async t=>await tZ({cwd:t.cwd??e.cwd,...t})},recording:{record:async e=>await i("record",e),trace:async e=>await i("trace",e)},settings:{update:async e=>await i("settings",e)}}}function t8(e){return"object"==typeof e&&null!==e?e:void 0}function t6(e,t){return{...e,...t}}function t7(e){let t=e.lease;if(!t||"object"!=typeof t||Array.isArray(t))throw Error("Invalid lease response from daemon");return{leaseId:C(t,"leaseId"),tenantId:C(t,"tenantId"),runId:C(t,"runId"),backend:C(t,"backend"),createdAt:"number"==typeof t.createdAt?t.createdAt:void 0,heartbeatAt:"number"==typeof t.heartbeatAt?t.heartbeatAt:void 0,expiresAt:"number"==typeof t.expiresAt?t.expiresAt:void 0}}export{eo as DAEMON_HTTP_BASE_PATH,ec as buildDaemonHttpAuthHeaders,es as buildDaemonHttpBaseUrl,el as buildDaemonHttpUrl,t4 as createAgentDeviceClient,tm as ensureDaemon,eV as formatDurationSeconds,eH as replayTestFailureStepLines,tp as resolveClientSettings,tM as sendToDaemon};
|
|
6
|
+
${r}`:r})(n,o,e)}}(t=await t2(j,"crash artifact"))??function(e){let t=e.split("\n"),a=function(e){let t=[],a=e.findIndex(e=>/^Binary Images:/i.test(e.trim()));if(-1===a)return t;for(let n of e.slice(a+1)){let e=function(e){let t=e.match(/^\s*(0x[0-9a-fA-F]+)\s*-\s*(0x[0-9a-fA-F]+)\s+\+?(.+?)\s+<([0-9a-fA-F-]{32,36})>\s+(.+)$/);if(!t)return null;let a=tE(t[4]);if(!a)return null;let n=function(e,t){let a=e.split(/\s+/),n=a.at(-1);if(n&&tj.test(n))return{name:a.slice(0,-1).join(" ").trim(),arch:n};let i=r.basename(t);return{name:e.startsWith(i)?i:e}}(t[3].trim(),t[5].trim());return{name:n.name,arch:n.arch,uuid:a,base:BigInt(t[1]),end:BigInt(t[2]),path:t[5].trim()}}(n);e&&t.push(e)}return t}(t);if(0===a.length)return null;let n=function(e,t){let a,r=[];for(let[n,i]of e.entries()){let e=i.match(/^Thread\s+(\d+)\s+Crashed:/);e?a=Number(e[1]):(0===i.trim().length||/^Thread\s+\d+/.test(i))&&(a=void 0);let o=function(e,t){let a=e.match(/^\s*\d+\s+(.+?)\s+(0x[0-9a-fA-F]+)\b/);if(!a)return null;let r=a[1].trim(),n=BigInt(a[2]),i=function(e,t,a){let r=e.filter(e=>e.name===t);return r.find(e=>{var t,r;return t=e,r=a,void 0!==t.end&&t.base<=r&&r<=t.end})??(1===r.length?r[0]:void 0)}(t,r,n);return i?{image:i,address:n}:null}(i,t),s=i.match(/^\s*(\d+)/);o&&s&&r.push({...o,frameIndex:Number(s[1]),lineIndex:n,threadIndex:a})}return r}(t,a);return{format:"text",images:a,addresses:n,lines:t,frameMatches:n,write(e){let a=new Map(n.map(e=>[e.lineIndex,e]));return t.map((t,r)=>{let n=a.get(r);if(!n)return t;let i=e.get(tN(n.image,n.address))?.text;return!i||t.includes(i)?t:`${t} // ${i}`}).join("\n")}}}(t);V||function(){throw new f("UNSUPPORTED_OPERATION","debug symbols currently supports Apple crash artifacts with Binary Images or IPS usedImages.",{hint:"For Android Java/R8 crashes, use retrace with mapping.txt. For Android native crashes, use ndk-stack or addr2line with unstripped .so symbols. Capture the crash with logs, then symbolicate externally until Android support is added."})}();let H=await tq({cwd:B,dsym:e.dsym,searchPath:e.searchPath});if(0===H.length)throw new f("INVALID_ARGS","debug symbols requires --dsym or --search-path.",{hint:"Pass a matching .dSYM bundle directly, or pass --search-path <dir> so agent-device can match crash image UUIDs to local dSYMs."});let G=await t0(),K=await tG(H,G.dwarfdump),z=function(e,t,a){let r=new Map;for(let a of e){let e=t.find(e=>e.uuid===a.uuid&&(void 0===a.arch||void 0===e.arch||e.arch===a.arch));e&&r.set(a.uuid,{image:a,dsym:e})}if(r.size>0)return r;let n=tB(e.map(e=>e.uuid)),i=tB(t.map(e=>e.uuid));throw new f("COMMAND_FAILED",a?"dSYM UUID does not match any Apple image in the crash artifact.":"No matching dSYM UUID found under search path.",{artifactUuidCount:n.length,artifactUuidSample:n.slice(0,5),dsymUuidCount:i.length,dsymUuidSample:i.slice(0,5),hint:"Use dwarfdump --uuid <App.dSYM> and compare it with the crash Binary Images or usedImages UUID, then pass the matching dSYM/search path."})}(V.images,K,!!e.dsym),Y=await tQ(V.addresses,z,G.atos),W=V.write(Y);await d.mkdir(r.dirname(q),{recursive:!0}),await d.writeFile(q,W,"utf8");let J=[...z.values()].map(({image:e,dsym:t})=>({name:e.name,uuid:e.uuid,arch:e.arch??t.arch,dsymPath:t.dsymPath,binaryPath:t.binaryPath})),X=[...Y.values()].filter(e=>e.text).length,Q=V.images.length-J.length,Z=Q>0?[`${Q} Apple image${1===Q?"":"s"} had no matching dSYM and were left unchanged.`]:void 0;return{kind:"debugSymbols",platform:"apple",artifactPath:j,outPath:q,crash:"ips"===V.format?(n=V.document,i=V.frameMatches,o=Y,U=function(e){let t=tO(e.faultingThread);if(void 0!==t)return t;let a=(Array.isArray(e.threads)?e.threads:[]).findIndex(e=>tU(e)?.triggered===!0);return -1===a?void 0:a}(n.payload),{...L={format:"ips",...(T=(s=n).payload,C=(l=s.header)?tL(l):null,{appName:(c=T,u=C,tT(c.procName,u?.app_name,u?.name)),bundleId:(p=T,m=C,tT(tU(p.bundleInfo)?.CFBundleIdentifier,m?.bundleID)),version:(h=T,y=C,tT(tU(h.bundleInfo)?.CFBundleShortVersionString,y?.app_version)),incident:(w=T,g=C,tT(w.incident,g?.incident_id)),timestamp:(b=T,v=C,tT(b.captureTime,v?.timestamp)),exceptionType:(I=T.exception,t$(tU(I)?.type)),exceptionCodes:function(e){let t=tU(e);if(t)return tT(t.codes,t.rawCodes)}(T.exception),terminationReason:function(e){let t=tU(e);if(t){let e;return(e=[t$(t.namespace),t$(t.code),t$(t.reason)].filter(e=>!!e)).length>0?e.join(" "):void 0}}(T.termination)}),crashedThread:U,topFrames:(A=i,S=U,M=o,A.filter(e=>void 0===S||e.threadIndex===S).slice(0,5).map(e=>tJ(e.frameIndex,e.image,e.address,M))),findings:[]},findings:tX(L)}):(_=V.lines,D=V.frameMatches,P=Y,R=function(e){let t=tW(e,"Triggered by Thread"),a=t?Number.parseInt(t,10):NaN;if(Number.isSafeInteger(a))return a;for(let t of e){let e=t.match(/^Thread\s+(\d+)\s+Crashed:/);if(e)return Number(e[1])}}(_),{...F={format:"text",appName:(O=tW(_,"Process"),O?.replace(/\s+\[\d+\]$/,"")),bundleId:tW(_,"Identifier"),version:tW(_,"Version"),incident:tW(_,"Incident Identifier"),timestamp:tW(_,"Date/Time"),exceptionType:tW(_,"Exception Type"),exceptionCodes:tW(_,"Exception Codes"),terminationReason:tW(_,"Termination Reason"),crashedThread:R,topFrames:(k=D,E=R,N=P,void 0===E?[]:k.filter(e=>e.threadIndex===E).slice(0,5).map(e=>tJ(e.frameIndex,e.image,e.address,N))),findings:[]},findings:tX(F)}),matchedImages:J,symbolicatedFrames:X,skippedImages:Q,warnings:Z,message:`Symbolicated ${X} frame${1===X?"":"s"} -> ${q}`}}async function t2(e,t){await t5(e,t);try{return await d.readFile(e,"utf8")}catch(a){throw new f("INVALID_ARGS",`Failed to read ${t}: ${e}`,{message:a instanceof Error?a.message:String(a)})}}async function t5(e,t){try{let a=await d.stat(e);if(a.size<=0x4000000)return;throw new f("INVALID_ARGS",`${t} is too large: ${e}`,{actualBytes:a.size,maxBytes:0x4000000,hint:"Pass a bounded Apple .ips/.crash artifact. For very large logs, first narrow the log to the crash report, or use logs grep/tail for lead-up context."})}catch(a){if(a instanceof f)throw a;throw new f("INVALID_ARGS",`Failed to read ${t}: ${e}`,{message:a instanceof Error?a.message:String(a)})}}function t4(e,t){return r.resolve(e,t)}let t8={...x(),batch:K(function(e,t,a){let r=t8[e];if(!r)throw Error(`Missing daemon writer for batch command: ${e}`);let n=U(e);if(!n)throw Error(`Missing command metadata for batch command: ${e}`);try{return t6(r,n,n.readInput(t))}catch(r){let t=r instanceof Error?r.message:String(r);throw new f("INVALID_ARGS",`Batch step ${a} ${e} input is invalid: ${t}`,void 0,r)}})};function t6(e,t,a){let r=e(a);return{...r,...t?{metadataFlags:z(t,r.options)}:{}}}function t7(e={},t={}){let a=t.transport??tP,r=async(t,r=[],n={},i)=>{let o=ae(e,n),s=await a({session:V(o.session),command:t,positionals:r,flags:G(o,i),runtime:o.runtime,meta:j(o)});return s.ok||function(e){throw new f(u(e.code),e.message,{...e.details??{},hint:e.hint,diagnosticId:e.diagnosticId,logPath:e.logPath})}(s.error),s.data??{}},n=async(e={})=>{let t=await r(Z.sessionList,[],e);return(Array.isArray(t.sessions)?t.sessions:[]).map($)},i=async(e,t={})=>{let a=function(e,t){let a=t8[e];if(!a)throw Error(`Missing daemon writer for command: ${e}`);return t6(a,U(e),t)}(e,t);return await r(a.command,a.positionals,a.options,a.metadataFlags)},o=(t={})=>V(ae(e,t).session);return{command:{wait:async e=>await i("wait",e),alert:async(e={})=>await i("alert",e),appState:async(e={})=>await i("appstate",e),back:async(e={})=>await i("back",e),home:async(e={})=>await i("home",e),rotate:async e=>await i("rotate",e),appSwitcher:async(e={})=>await i("app-switcher",e),keyboard:async(e={})=>await i("keyboard",e),clipboard:async e=>await i("clipboard",e),reactNative:async e=>await i("react-native",e),prepare:async e=>await i("prepare",e),viewport:async e=>await i("viewport",e)},devices:{list:async(e={})=>{let t=await i("devices",e);return(Array.isArray(t.devices)?t.devices:[]).map(Y)},boot:async(e={})=>await i("boot",e),shutdown:async(e={})=>await i("shutdown",e)},sessions:{list:async(e={})=>await n(e),stateDir:async(t={})=>P(ae(e,t).stateDir??process.env.AGENT_DEVICE_STATE_DIR).baseDir,close:async(e={})=>{let t=o(e),a=(await i("close",e)).shutdown;return{session:t,shutdown:"object"==typeof a&&null!==a?a:void 0,identifiers:{session:t}}}},apps:{install:async e=>F(await i("install",e),o(e)),reinstall:async e=>F(await i("reinstall",e),o(e)),installFromSource:async e=>Q(await i("install-from-source",e),o(e)),list:async(e={})=>{let t=await i("apps",e);return Array.isArray(t.apps)?t.apps.filter(e=>"string"==typeof e):[]},open:async e=>{let t=o(e),a=await i("open",e),r=B(a),n=q(a,"appBundleId");return{session:t,sessionStateDir:q(a,"sessionStateDir"),appName:q(a,"appName"),appBundleId:n,appId:n,startup:W(a.startup),runtime:X(a.runtime),device:r,identifiers:{session:t,deviceId:r?.id,deviceName:r?.name,udid:r?.ios?.udid,serial:r?.android?.serial,appId:n,appBundleId:n}}},close:async(e={})=>{let t=o(e),a=(await i("close",e)).shutdown;return{session:t,closedApp:e.app,shutdown:"object"==typeof a&&null!==a?a:void 0,identifiers:{session:t}}},push:async e=>await i("push",e),triggerEvent:async e=>await i("trigger-app-event",e)},materializations:{release:async e=>L(await r(Z.releaseMaterializedPaths,[],{...e,materializationId:e.materializationId}))},leases:{allocate:async e=>at(await r(Z.leaseAllocate,[],{...e,leaseId:void 0,leaseTtlMs:e.ttlMs})),heartbeat:async e=>at(await r(Z.leaseHeartbeat,[],{...e,leaseTtlMs:e.ttlMs})),release:async e=>({released:!0===(await r(Z.leaseRelease,[],e)).released})},metro:{prepare:async t=>await ei({projectRoot:t.projectRoot??e.cwd,kind:t.kind,publicBaseUrl:t.publicBaseUrl,proxyBaseUrl:t.proxyBaseUrl,proxyBearerToken:t.bearerToken,bridgeScope:t.bridgeScope,launchUrl:t.launchUrl,companionProfileKey:t.companionProfileKey,companionConsumerKey:t.companionConsumerKey,metroPort:t.port,listenHost:t.listenHost,statusHost:t.statusHost,startupTimeoutMs:t.startupTimeoutMs,probeTimeoutMs:t.probeTimeoutMs,reuseExisting:t.reuseExisting,installDependenciesIfNeeded:t.installDependenciesIfNeeded,runtimeFilePath:t.runtimeFilePath,logPath:t.logPath}),reload:async(t={})=>await en({metroHost:t.metroHost,metroPort:t.metroPort,bundleUrl:t.bundleUrl,runtime:e.runtime,timeoutMs:t.timeoutMs})},capture:{snapshot:async(e={})=>{var t,a,r;let n,s,l,c,d=o(e);return t=await i("snapshot",e),a=d,n=q(t,"appBundleId"),{nodes:R(t.nodes),truncated:!0===t.truncated,appName:q(t,"appName"),appBundleId:n,...(s=t9((r=t).visibility),l=t9(r.unchanged),c=I(r.snapshotDiagnostics),{...s?{visibility:s}:{},...T(r),...l?{unchanged:l}:{},...c?{snapshotDiagnostics:c}:{}}),identifiers:{session:a,appId:n,appBundleId:n}}},screenshot:async(e={})=>{let t=o(e),a=await i("screenshot",e);return{path:C(a,"path"),overlayRefs:J(a),identifiers:{session:t}}},diff:async e=>await i("diff",e)},interactions:{click:async e=>await i("click",e),press:async e=>await i("press",e),longPress:async e=>await i("longpress",e),swipe:async e=>await i("swipe",e),pan:async e=>await i("gesture-pan",e),fling:async e=>await i("gesture-fling",e),swipeGesture:async e=>await i("gesture-swipe",e),focus:async e=>await i("focus",e),type:async e=>await i("type",e),fill:async e=>await i("fill",e),scroll:async e=>await i("scroll",e),pinch:async e=>await i("gesture-pinch",e),rotateGesture:async e=>await i("gesture-rotate",e),transformGesture:async e=>await i("gesture-transform",e),get:async e=>await i("get",e),is:async e=>await i("is",e),find:async e=>await i("find",e)},replay:{run:async e=>await i("replay",e),test:async e=>await i("test",e)},batch:{run:async e=>await i("batch",e)},observability:{perf:async(e={})=>await i("perf",e),logs:async(e={})=>await i("logs",e),network:async(e={})=>await i("network",e)},debug:{symbols:async t=>await t3({cwd:t.cwd??e.cwd,...t})},recording:{record:async e=>await i("record",e),trace:async e=>await i("trace",e)},settings:{update:async e=>await i("settings",e)}}}function t9(e){return"object"==typeof e&&null!==e?e:void 0}function ae(e,t){return{...e,...t}}function at(e){let t=e.lease;if(!t||"object"!=typeof t||Array.isArray(t))throw Error("Invalid lease response from daemon");return{leaseId:C(t,"leaseId"),tenantId:C(t,"tenantId"),runId:C(t,"runId"),backend:C(t,"backend"),createdAt:"number"==typeof t.createdAt?t.createdAt:void 0,heartbeatAt:"number"==typeof t.heartbeatAt?t.heartbeatAt:void 0,expiresAt:"number"==typeof t.expiresAt?t.expiresAt:void 0}}export{eo as DAEMON_HTTP_BASE_PATH,ec as buildDaemonHttpAuthHeaders,es as buildDaemonHttpBaseUrl,el as buildDaemonHttpUrl,t7 as createAgentDeviceClient,ty as ensureDaemon,eV as formatDurationSeconds,eH as replayTestFailureStepLines,th as resolveClientSettings,tP as sendToDaemon};
|
package/dist/src/cli-help.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import{listCliCommandNames as e}from"./2133.js";import{getCliCommandSchema as t,getCommandSchema as
|
|
1
|
+
import{listCliCommandNames as e}from"./2133.js";import{getCliCommandSchema as t,getCommandSchema as a}from"./9581.js";import{getFlagDefinitions as o,GLOBAL_FLAG_KEYS as s}from"./2948.js";let n=[{label:"help workflow",description:"Normal bootstrap, exploration, and validation loop"},{label:"help debugging",description:"Logs, network, perf memory, and traces"},{label:"help react-native",description:"React Native app automation hazards, overlays, Metro, and routing"},{label:"help react-devtools",description:"React Native performance, profiling, component tree, and renders"},{label:"help cdp",description:"React Native CDP targets, JS heap snapshots, and leak triage"},{label:"help physical-device",description:"Connected phone/tablet setup and iOS signing prerequisites"},{label:"help remote",description:"Remote/cloud config, tenants, leases, and local service tunnels"},{label:"help web",description:"Minimal browser sessions through agent-browser"},{label:"help macos",description:"Desktop, frontmost-app, and menu bar surfaces"},{label:"help dogfood",description:"Exploratory QA report workflow"}],r=["Planning output contract: when asked to plan commands, output command lines only: no prose, numbering, Markdown fences, pipes, or shell helpers.","Default loop: devices/apps -> open -> snapshot -i -> press/fill/get/is/wait/find -> verify -> close.",'Use selectors or refs as positional targets: id="submit", label="Allow", or @e12 from snapshot -i.',"Plain snapshot reads state; snapshot -i refreshes current interactive refs only.","Default snapshot text is an agent-facing, token-efficient view for planning and targeting actions.","Read-only visible/state question: use snapshot/get/is/find; use snapshot -i only when refs are needed.","Anti-pattern: snapshot -i followed by snapshot -i | grep ...; prior refs stay valid until app state changes, and --force-full is the explicit full re-read.","Truncated text/input preview: expand first with snapshot -s @e12, not get text.","React Native apps: read help react-native for Metro, DevTools routing, and RN-specific blockers; use react-native dismiss-overlay for LogBox/RedBox overlays.","React Native JS memory leaks: read help cdp; use heap usage samples for a quick signal, then snapshot diff/leak-triplet for retained object proof.","Android RN/Expo Metro: direct Android localhost URL opens with a port auto-configure host reachability.",'Expo Go/dev clients: use the provided URL when given; on iOS use open "Expo Go" <url> --platform ios, then snapshot -i --platform ios to verify project UI. Do not use plain snapshot or snapshot --diff for this recovery check. Android URL opens infer the foreground package for logs/perf when possible.',"Install flows: install/install-from-source first, then open the installed id with --relaunch.",'Text: fill \'id="field-email"\' "qa@example.com" replaces; type appends after press.','Clearing text: do not use fill <target> ""; use a visible clear/reset control or report that clearing is unsupported.',"Android IME capture: if fill says input was captured by the keyboard/IME, inspect keyboard state and switch/disable handwriting before retrying; do not loop fill/type.","Implicit default sessions are scoped to the current worktree; if a prompt names a Session, include --session <name> on every command in that flow.","Run mutating commands serially within one session; parallelize only read-only commands or separate sessions/devices.","Clipboard limits: iOS Allow Paste cannot be automated through XCUITest; prefill with clipboard write. Android non-ASCII should use fill/type, not raw adb input.","After mutation: refs are stale. If the next target is known, use its selector directly; otherwise refresh with snapshot -i, scoped with -s when a stable container is known. Do not use tap; use press or click.","Raw coordinates are fallback-only: use snapshot -i --json rects when iOS refs no-op or child refs are missing, then verify the action with diff snapshot -i or snapshot --diff.","Sparse or AX-unavailable snapshot: use screenshot for visual truth, press the visible coordinate to leave the bad screen, then retry AX with snapshot -i.","macOS context menus use click <ref> --button secondary, then snapshot -i. Longpress is for mobile hold gestures, not macOS secondary-click menus.","Direct proxy: Cloud/Linux clients can use iOS simulators through a Mac running agent-device proxy. A proxy URL/token means direct proxy mode: use --daemon-base-url plus --daemon-auth-token, or saved daemonBaseUrl/daemonAuthToken config.","Direct proxy sessions: choose one explicit --session and reuse it for open/snapshot/interactions/close; do not use connect, --remote-config, tenant, run, or lease flags.","Cloud/remote-config profiles are separate from direct proxy: use connect or --remote-config on operational commands. Do not substitute --config; --config only loads CLI defaults.",'Batch JSON steps use "command" and structured "input"; legacy "positionals"/"flags" steps still run in CLI but are deprecated until the next major version.',"Navigation: app-owned back uses back; system back uses back --system.","Web browser sessions: read help web; first slice is web setup if needed -> web doctor -> open <url> --platform web -> snapshot -i -> click/fill/get/is/find/wait/screenshot -> close.","Verification commands must name the expected text/selector; bare screenshots/snapshots are not enough.","Debug evidence: Session state contains request diagnostics and runner.log; use logs clear --restart/mark/path, trace, and network dump --include headers for app evidence.","Use agent-device commands in final plans; raw platform tools, pseudo commands, and helper prose are wrong.","Full operating guide: agent-device help workflow. Exploratory QA: agent-device help dogfood."],i=["Default config files: ~/.agent-device/config.json, ./agent-device.json","Use --config <path> or AGENT_DEVICE_CONFIG to load one explicit config file."],c=[{label:"AGENT_DEVICE_SESSION",description:"Explicit session name"},{label:"AGENT_DEVICE_PLATFORM",description:"Default platform binding"},{label:"AGENT_DEVICE_SESSION_LOCK",description:"Bound-session conflict mode"},{label:"AGENT_DEVICE_DAEMON_BASE_URL",description:"Connect to remote daemon"},{label:"AGENT_DEVICE_DAEMON_AUTH_TOKEN",description:"Remote daemon service/API token"},{label:"AGENT_DEVICE_CLOUD_BASE_URL",description:"Bridge/control-plane API origin for cloud auth and /api-keys"}],l=["agent-device open Settings --platform ios","agent-device open https://example.com --platform web","agent-device open TextEdit --platform macos","agent-device snapshot -i","agent-device react-devtools get tree --depth 3","agent-device cdp memory usage sample --gc --label baseline",'agent-device fill @e3 "test@example.com"',"agent-device replay ./session.ad","agent-device test ./suite --platform android"],d={workflow:{summary:"Normal agent-device bootstrap, exploration, and validation loop",body:`agent-device help workflow
|
|
2
2
|
|
|
3
3
|
Version-matched operating guide for normal agent-device work.
|
|
4
4
|
|
|
@@ -28,7 +28,7 @@ Bootstrap:
|
|
|
28
28
|
agent-device prepare ios-runner --platform ios --timeout 240000
|
|
29
29
|
If app id is unknown, plan devices, apps, then open <discovered-app-id>. Discovery is not enough when the task asks to open/start the app.
|
|
30
30
|
Install arguments are app/package id then artifact path. If the task says install, use install; use reinstall only when explicitly requested. Fresh runtime state is open --relaunch after install.
|
|
31
|
-
In Apple CI, run prepare ios-runner after boot/install and before replay/test. prepare ios-runner builds/reuses the XCTest runner, health-checks it with a lightweight command, and retries one stuck/non-connecting runner launch before the first snapshot pays that setup cost. If the replay/test step starts a separate daemon, run clean:daemon after prepare so the prepared runner does not keep a live lease owned by the prepare daemon.
|
|
31
|
+
In Apple CI, run prepare ios-runner after boot/install and before replay/test. prepare ios-runner builds/reuses the XCTest runner, health-checks it with a lightweight command, and retries one stuck/non-connecting runner launch before the first snapshot pays that setup cost. It is not a recovery step for "runner already owned by another agent-device daemon"; stop or clean the owning daemon on the Mac with simulator access instead. If the replay/test step starts a separate daemon, run clean:daemon after prepare so the prepared runner does not keep a live lease owned by the prepare daemon.
|
|
32
32
|
CI may cache ~/.agent-device/ios-runner/derived with an exact key that includes the agent-device package and Xcode version. Avoid broad restore-key fallbacks; prepare ios-runner already recovers bad restored runner artifacts and one retryable non-connecting runner launch. Runner build/start output is written to the session's runner.log; daemon.log is for daemon lifecycle/startup issues.
|
|
33
33
|
Do not open artifact paths or invent package ids. If apps lookup misses the target and no URL/artifact is provided, ask or stop.
|
|
34
34
|
|
|
@@ -140,7 +140,8 @@ Validation and evidence:
|
|
|
140
140
|
Android animations: settings animations off/on, not animations disable/restore.
|
|
141
141
|
Debug logs: logs clear --restart, logs mark, reproduce, then logs path; do not split clear/restart into separate stop/start commands.
|
|
142
142
|
Network headers: network dump --include headers; do not write network log headers.
|
|
143
|
-
|
|
143
|
+
Direct proxy to a Mac you control: cloud/Linux clients can still use iOS simulators through the proxied Mac. Use the printed /agent-device daemon base URL and auth token, or store them as daemonBaseUrl and daemonAuthToken in agent-device.json. Use one explicit --session across open, snapshot, interactions, and close. Do not use connect, --remote-config, tenant, run, or lease flags for direct proxy simulators.
|
|
144
|
+
Cloud/remote-config profiles: use connect to discover a cloud profile, or connect --remote-config ./remote-config.json for a local profile; then open, snapshot, disconnect.
|
|
144
145
|
Web: agent-device uses a managed, pinned agent-browser backend as an implementation detail. Use --platform web when a browser step belongs inside an agent-device session, replay, batch, MCP, or typed-client flow; use agent-browser directly for standalone web automation. Run agent-device web setup before first use, then agent-device web doctor for backend health checks. Web automation requires Node 24+.
|
|
145
146
|
agent-device web setup
|
|
146
147
|
agent-device web doctor
|
|
@@ -343,7 +344,54 @@ Example:
|
|
|
343
344
|
agent-device react-devtools profile report @c5
|
|
344
345
|
agent-device network dump --include headers
|
|
345
346
|
|
|
346
|
-
Use snapshot, screenshot, logs, network, and perf metrics for device/app runtime evidence. Use react-devtools only when component internals or React rendering behavior matters.`},
|
|
347
|
+
Use snapshot, screenshot, logs, network, and perf metrics for device/app runtime evidence. Use react-devtools only when component internals or React rendering behavior matters.`},cdp:{summary:"React Native CDP targets, JS heap snapshots, and leak triage",body:`agent-device help cdp
|
|
348
|
+
|
|
349
|
+
Use this when a React Native or Expo app exposes a CDP target through Metro and
|
|
350
|
+
the task needs JavaScript heap growth checks, heap snapshot diffs, allocation
|
|
351
|
+
hotspots, retained-object leak evidence, or a small runtime eval to confirm JS
|
|
352
|
+
state. Do not use this as the default React Native profiler.
|
|
353
|
+
|
|
354
|
+
Setup:
|
|
355
|
+
Start Metro and open the app first. For Android devices/emulators, make sure Metro is reachable from the app, typically with adb reverse tcp:8081 tcp:8081.
|
|
356
|
+
agent-device cdp target list --url http://127.0.0.1:8081
|
|
357
|
+
agent-device cdp target select <target-id>
|
|
358
|
+
|
|
359
|
+
Quick JS heap signal:
|
|
360
|
+
agent-device cdp memory usage sample --label baseline --gc
|
|
361
|
+
# perform the suspected leaking action with agent-device commands
|
|
362
|
+
agent-device cdp memory usage sample --label after-action --gc
|
|
363
|
+
agent-device cdp memory usage diff --base jm_1 --compare jm_2
|
|
364
|
+
agent-device cdp memory usage leak-signal --since jm_1
|
|
365
|
+
|
|
366
|
+
Retained-object proof:
|
|
367
|
+
agent-device cdp memory snapshot capture --name baseline --gc
|
|
368
|
+
# perform the suspected leaking action
|
|
369
|
+
agent-device cdp memory snapshot capture --name after-action --gc
|
|
370
|
+
# perform cleanup/navigation that should release the objects
|
|
371
|
+
agent-device cdp memory snapshot capture --name cleanup --gc
|
|
372
|
+
agent-device cdp memory snapshot diff --base ms_1 --compare ms_2 --limit 10
|
|
373
|
+
agent-device cdp memory snapshot leak-triplet --baseline ms_1 --action ms_2 --cleanup ms_3 --limit 10
|
|
374
|
+
agent-device cdp memory snapshot retainers --snapshot ms_3 --id <node-id> --depth 8 --limit 10
|
|
375
|
+
|
|
376
|
+
Allocation pressure:
|
|
377
|
+
Use allocation sampling to find where allocations were created, not to prove a leak:
|
|
378
|
+
agent-device cdp memory allocation start --name suspected-flow --interval 32768 --stack-depth 32
|
|
379
|
+
# perform the flow once
|
|
380
|
+
agent-device cdp memory allocation stop
|
|
381
|
+
agent-device cdp memory allocation hotspots --limit 10
|
|
382
|
+
agent-device cdp memory allocation source-maps
|
|
383
|
+
|
|
384
|
+
Recommended subset:
|
|
385
|
+
cdp dynamically runs a pinned CDP helper through npm; the first run may download the pinned package, and later runs can reuse the npm cache.
|
|
386
|
+
Every argument after cdp is passed to the CDP helper. Put agent-device global flags before cdp when you need the outer CLI to consume them.
|
|
387
|
+
Use cdp memory usage, memory snapshot, memory allocation, and targeted runtime eval.
|
|
388
|
+
Avoid cdp profile cpu, trace, network, and console by default because agent-device already has perf cpu, trace, network, logs, and react-devtools guidance for those areas.
|
|
389
|
+
|
|
390
|
+
Output contract:
|
|
391
|
+
Until cdp has a compact leak report command, synthesize one from memory usage diff, snapshot diff, leak-triplet, and retainers. Report heap deltas, top retained classes/shapes, leak-triplet rows that stayed high after cleanup, and the shortest useful retaining paths. Do not paste raw heap snapshots or large allocation profiles into the response; use exported artifacts only when the user asks for raw data.
|
|
392
|
+
|
|
393
|
+
Target caveats:
|
|
394
|
+
React Native/Hermes implements a subset of browser CDP. If a command reports an unsupported method, keep the target selected and switch to heap usage samples plus heap snapshots. Prefer react-devtools for component tree/render causes; prefer perf memory sample or perf memory snapshot for native/process memory.`},"react-native":{summary:"React Native app automation hazards and routing",body:`agent-device help react-native
|
|
347
395
|
|
|
348
396
|
Use this when the target app is React Native, Expo, or a React Native dev client.
|
|
349
397
|
This topic covers React Native-specific automation hazards and routes deeper
|
|
@@ -353,6 +401,7 @@ Choose the next help topic:
|
|
|
353
401
|
Generic navigation, selectors, refs, verification, serial commands: help workflow.
|
|
354
402
|
Logs, network, diagnostics, traces, permission dialogs, or runtime failures: help debugging.
|
|
355
403
|
Component tree, props/state/hooks, slow renders, rerenders, or render causes: help react-devtools.
|
|
404
|
+
JS heap growth, heap snapshots, allocation hotspots, or retained-object leaks: help cdp.
|
|
356
405
|
Remote/cloud config, leases, and local service tunnels: help remote.
|
|
357
406
|
|
|
358
407
|
React Native dev loop:
|
|
@@ -400,6 +449,11 @@ React DevTools routing:
|
|
|
400
449
|
Use help react-devtools for status/wait, component trees, props/state/hooks, profile windows, slow renders, rerenders, and remote bridge rules.
|
|
401
450
|
If React DevTools cannot connect, report status and continue with logs, network, perf metrics, screenshot, and trace evidence instead of blocking the whole flow.
|
|
402
451
|
|
|
452
|
+
CDP memory routing:
|
|
453
|
+
Keep the agent-device cdp prefix on every CDP command.
|
|
454
|
+
Use help cdp for JS heap usage samples, heap snapshots, snapshot diffs, leak-triplet analysis, allocation hotspots, and retained-object paths.
|
|
455
|
+
Use perf memory sample or perf memory snapshot for native/process memory; use cdp only for JavaScript heap evidence.
|
|
456
|
+
|
|
403
457
|
Slow-flow investigation:
|
|
404
458
|
Keep one session, open the app first, and snapshot -i before interacting.
|
|
405
459
|
Start React Native slow-flow plans with this ordered scaffold:
|
|
@@ -438,9 +492,21 @@ iOS physical-device prerequisites:
|
|
|
438
492
|
|
|
439
493
|
Android physical-device prerequisites:
|
|
440
494
|
Enable USB debugging and confirm the device appears in agent-device devices --platform android.
|
|
441
|
-
Android does not need the iOS runner signing setup. For React Native/Expo Metro reachability, read help react-native.`},remote:{summary:"
|
|
495
|
+
Android does not need the iOS runner signing setup. For React Native/Expo Metro reachability, read help react-native.`},remote:{summary:"Direct proxy, cloud profiles, and remote config",body:`agent-device help remote
|
|
496
|
+
|
|
497
|
+
There are two different remote modes:
|
|
498
|
+
1. Direct proxy: agent-device proxy exposes a Mac you control. A cloud/Linux client can use iOS simulators through that proxied Mac. Use --daemon-base-url plus --daemon-auth-token, or store daemonBaseUrl and daemonAuthToken in agent-device.json. Use one explicit --session across open, snapshot, interactions, and close so implicit cwd-scoped default sessions do not diverge. Do not use connect, --remote-config, tenant, run, or lease flags for this mode.
|
|
499
|
+
2. Cloud/profile: the cloud connection profile or a local --remote-config owns daemon URL, auth, tenant, run, lease, device scope, and Metro hints. Do not restate those as individual flags unless overriding intentionally.
|
|
442
500
|
|
|
443
|
-
|
|
501
|
+
Direct proxy flow for a remote Mac/simulator:
|
|
502
|
+
On the Mac with simulator/device access:
|
|
503
|
+
agent-device proxy --port 4310
|
|
504
|
+
cloudflared tunnel --url http://127.0.0.1:4310
|
|
505
|
+
On the remote client:
|
|
506
|
+
agent-device devices --daemon-base-url https://example.trycloudflare.com/agent-device --daemon-auth-token <token>
|
|
507
|
+
agent-device open Maps --session maps --platform ios --device "iPhone 17 Pro" --daemon-base-url https://example.trycloudflare.com/agent-device --daemon-auth-token <token>
|
|
508
|
+
agent-device snapshot -i --session maps --platform ios --device "iPhone 17 Pro" --daemon-base-url https://example.trycloudflare.com/agent-device --daemon-auth-token <token>
|
|
509
|
+
agent-device close --session maps --daemon-base-url https://example.trycloudflare.com/agent-device --daemon-auth-token <token>
|
|
444
510
|
|
|
445
511
|
Cloud profile flow:
|
|
446
512
|
agent-device connect
|
|
@@ -459,21 +525,14 @@ Script flow, per-command config:
|
|
|
459
525
|
agent-device snapshot --remote-config ./remote-config.json
|
|
460
526
|
agent-device disconnect --remote-config ./remote-config.json
|
|
461
527
|
|
|
462
|
-
Direct proxy flow for a remote Mac:
|
|
463
|
-
On the Mac with simulator/device access:
|
|
464
|
-
agent-device proxy --port 4310
|
|
465
|
-
cloudflared tunnel --url http://127.0.0.1:4310
|
|
466
|
-
On the remote client:
|
|
467
|
-
agent-device devices --daemon-base-url https://example.trycloudflare.com/agent-device --daemon-auth-token <token>
|
|
468
|
-
agent-device devices
|
|
469
|
-
|
|
470
528
|
Rules:
|
|
471
529
|
connect and disconnect are top-level commands. Do not write agent-device remote connect or agent-device remote disconnect.
|
|
472
530
|
Use connect without --remote-config when the cloud control plane owns the connection profile.
|
|
473
531
|
Prefer --remote-config over --daemon-base-url, --tenant, --run-id, and --lease-id when using a local profile.
|
|
474
|
-
Use agent-device proxy for direct tunnel access to a Mac you control. Copy the printed daemon base URL and daemon auth token; do not use agent-device auth for this direct proxy flow.
|
|
475
|
-
For repeated direct proxy commands, store daemonBaseUrl and daemonAuthToken in normal agent-device.json CLI config. Keep platform selection on each command or workflow
|
|
532
|
+
Use agent-device proxy for direct tunnel access to a Mac you control. Copy the printed daemon base URL and daemon auth token; do not use agent-device auth, connect, disconnect, --remote-config, tenant, run, or lease flags for this direct proxy flow.
|
|
533
|
+
For repeated direct proxy commands, store daemonBaseUrl and daemonAuthToken in normal agent-device.json CLI config. Keep platform selection on each command or workflow, and keep the same explicit --session until close.
|
|
476
534
|
Keep the proxy token secret. Anyone with the token can control the proxied daemon.
|
|
535
|
+
If iOS snapshot/interaction reports that the runner is already owned by another agent-device daemon, do not run prepare ios-runner from the remote client. Retry the original snapshot or interaction; same-proxy-state stale runner leases are reclaimed by the proxy daemon. If the conflict repeats, the Mac operator should close the owning session or clean the conflicting local daemon.
|
|
477
536
|
Do not use --config as a remote profile flag. --config loads CLI defaults; --remote-config selects remote daemon/profile settings.
|
|
478
537
|
For self-contained scripts, pass the same --remote-config to every operational command, including disconnect; a preceding connect is optional but not required.
|
|
479
538
|
For remote artifact installs, use install-from-source <url> or install-from-source --github-actions-artifact org/repo:artifact; do not download CI artifacts locally first.
|
|
@@ -605,37 +664,37 @@ Rules:
|
|
|
605
664
|
Prefer refs for exploration and selectors for deterministic replay.
|
|
606
665
|
Use logs, network, screenshot --overlay-refs, trace, perf metrics, perf frames, or react-devtools only when they add evidence to a specific issue.
|
|
607
666
|
Never delete screenshots, videos, traces, or report artifacts during a session.
|
|
608
|
-
Escalate to help debugging or help react-devtools when runtime symptoms require those tools.`}};function p(e){let t=e.endsWith("?"),
|
|
667
|
+
Escalate to help debugging or help react-devtools when runtime symptoms require those tools.`}};function p(e){let t=e.endsWith("?"),a=t?e.slice(0,-1):e;return t?`[${a}]`:`<${a}>`}function h(){let a,o,d,p,h,v,b,w;return a=`agent-device <command> [args] [--json]
|
|
609
668
|
|
|
610
669
|
CLI to control iOS and Android devices for AI agents.
|
|
611
|
-
`,
|
|
612
|
-
${
|
|
670
|
+
`,o=f("Commands:",e().map(e=>{let a=t(e);return{name:e,schema:a,usage:function(e,t){if(t.listUsageOverride)return t.listUsageOverride;let a=(t.positionalArgs??[]).map(a=>{var o,s,n;let r,i,c,l;return o=e,s=t,i=(r=(n=a).endsWith("?"))?n.slice(0,-1):n,l=(c=/^[a-z-]+(?:\|[a-z-]+)+$/i.test(i))||void 0!==s.usageOverride&&s.usageOverride.startsWith(`${o} ${i}`),r?c?`[${i}]`:l?i:`[${i}]`:l?i:`<${i}>`});return[e,...a].join(" ")}(e,a)}}).map(e=>({label:e.usage,description:e.schema.summary??e.schema.helpDescription}))),d=m("Global Flags:",u(s)),p=g("Agent Quickstart:",r),h=f("Agent Workflows:",n),v=g("Configuration:",i),b=f("Environment:",c),w=g("Examples:",l),`${a}
|
|
671
|
+
${h}
|
|
672
|
+
|
|
673
|
+
${o}
|
|
613
674
|
|
|
614
675
|
${d}
|
|
615
676
|
|
|
616
677
|
${p}
|
|
617
678
|
|
|
618
|
-
${u}
|
|
619
|
-
|
|
620
679
|
${v}
|
|
621
680
|
|
|
622
681
|
${b}
|
|
623
682
|
|
|
624
683
|
${w}
|
|
625
|
-
`}function
|
|
626
|
-
(none)`;let
|
|
684
|
+
`}function u(e){return o().filter(t=>e.has(t.key)&&void 0!==t.usageLabel&&void 0!==t.usageDescription)}function m(e,t){return f(e,t.map(e=>({label:e.usageLabel??"",description:e.usageDescription??""})))}function f(e,t){if(0===t.length)return`${e}
|
|
685
|
+
(none)`;let a=Math.max(...t.map(e=>e.label.length))+2,o=[e];for(let e of t)o.push(` ${e.label.padEnd(a)}${e.description}`);return o.join("\n")}function g(e,t){return 0===t.length?`${e}
|
|
627
686
|
(none)`:[e,...t.map(e=>` ${e}`)].join("\n")}function v(e){var t,s;let n,r=(n=d[e])?`${n.body}
|
|
628
687
|
|
|
629
688
|
Related:
|
|
630
689
|
agent-device help command list and global flags
|
|
631
690
|
agent-device help <command> command-specific flags
|
|
632
691
|
agent-device help workflow normal app automation loop
|
|
633
|
-
`:null;if(r)return r;let i=
|
|
692
|
+
`:null;if(r)return r;let i=a(e);if(!i)return null;let c=(t=e,(s=i).usageOverride?s.usageOverride:[t,...(s.positionalArgs??[]).map(p),...(s.allowedFlags??[]).flatMap(e=>{var t;return(t=e,o().filter(e=>e.key===t)).map(e=>e.usageLabel??e.names[0])}).map(e=>`[${e}]`)].join(" ")),l=u(new Set(i.allowedFlags??[])),h=[];l.length>0&&h.push(m("Command flags:",l));let f=h.length>0?`
|
|
634
693
|
|
|
635
|
-
${
|
|
694
|
+
${h.join("\n\n")}`:"";return`agent-device ${c}
|
|
636
695
|
|
|
637
696
|
${i.helpDescription}
|
|
638
697
|
|
|
639
698
|
Usage:
|
|
640
|
-
agent-device ${c}${
|
|
641
|
-
`}export{v as buildCommandUsageText,
|
|
699
|
+
agent-device ${c}${f}
|
|
700
|
+
`}export{v as buildCommandUsageText,h as buildUsageText};
|