agent-device 0.11.15 → 0.11.16
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/src/152.js +1 -0
- package/dist/src/155.js +38 -0
- package/dist/src/164.js +1 -0
- package/dist/src/267.js +1 -0
- package/dist/src/556.js +1 -0
- package/dist/src/57.js +1 -0
- package/dist/src/818.js +1 -3
- package/dist/src/924.js +1 -1
- package/dist/src/940.js +1 -0
- package/dist/src/974.js +2 -2
- package/dist/src/artifacts.d.ts +3 -0
- package/dist/src/artifacts.js +1 -0
- package/dist/src/bin.js +23 -23
- package/dist/src/contracts.d.ts +59 -0
- package/dist/src/contracts.js +1 -1
- package/dist/src/daemon.js +15 -18
- package/dist/src/finders.d.ts +75 -0
- package/dist/src/finders.js +1 -0
- package/dist/src/index.d.ts +6 -4
- package/dist/src/index.js +3 -2
- package/dist/src/install-source.d.ts +40 -0
- package/dist/src/install-source.js +1 -0
- package/dist/src/metro.d.ts +6 -0
- package/dist/src/metro.js +1 -1
- package/dist/src/selectors.d.ts +110 -0
- package/dist/src/selectors.js +1 -0
- package/package.json +17 -1
- package/dist/src/760.js +0 -33
- package/dist/src/957.js +0 -2
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
declare type FindAction = {
|
|
2
|
+
kind: 'click';
|
|
3
|
+
} | {
|
|
4
|
+
kind: 'focus';
|
|
5
|
+
} | {
|
|
6
|
+
kind: 'fill';
|
|
7
|
+
value: string;
|
|
8
|
+
} | {
|
|
9
|
+
kind: 'type';
|
|
10
|
+
value: string;
|
|
11
|
+
} | {
|
|
12
|
+
kind: 'get_text';
|
|
13
|
+
} | {
|
|
14
|
+
kind: 'get_attrs';
|
|
15
|
+
} | {
|
|
16
|
+
kind: 'exists';
|
|
17
|
+
} | {
|
|
18
|
+
kind: 'wait';
|
|
19
|
+
timeoutMs?: number;
|
|
20
|
+
};
|
|
21
|
+
|
|
22
|
+
export declare function findBestMatchesByLocator(nodes: SnapshotNode[], locator: FindLocator, query: string, requireRect?: boolean): {
|
|
23
|
+
matches: SnapshotNode[];
|
|
24
|
+
score: number;
|
|
25
|
+
};
|
|
26
|
+
|
|
27
|
+
export declare type FindLocator = 'any' | 'text' | 'label' | 'value' | 'role' | 'id';
|
|
28
|
+
|
|
29
|
+
export declare function normalizeRole(value: string): string;
|
|
30
|
+
|
|
31
|
+
export declare function normalizeText(value: string): string;
|
|
32
|
+
|
|
33
|
+
export declare function parseFindArgs(args: string[]): {
|
|
34
|
+
locator: FindLocator;
|
|
35
|
+
query: string;
|
|
36
|
+
action: FindAction['kind'];
|
|
37
|
+
value?: string;
|
|
38
|
+
timeoutMs?: number;
|
|
39
|
+
};
|
|
40
|
+
|
|
41
|
+
declare type RawSnapshotNode = {
|
|
42
|
+
index: number;
|
|
43
|
+
type?: string;
|
|
44
|
+
role?: string;
|
|
45
|
+
subrole?: string;
|
|
46
|
+
label?: string;
|
|
47
|
+
value?: string;
|
|
48
|
+
identifier?: string;
|
|
49
|
+
rect?: Rect;
|
|
50
|
+
enabled?: boolean;
|
|
51
|
+
selected?: boolean;
|
|
52
|
+
hittable?: boolean;
|
|
53
|
+
depth?: number;
|
|
54
|
+
parentIndex?: number;
|
|
55
|
+
pid?: number;
|
|
56
|
+
bundleId?: string;
|
|
57
|
+
appName?: string;
|
|
58
|
+
windowTitle?: string;
|
|
59
|
+
surface?: string;
|
|
60
|
+
hiddenContentAbove?: boolean;
|
|
61
|
+
hiddenContentBelow?: boolean;
|
|
62
|
+
};
|
|
63
|
+
|
|
64
|
+
declare type Rect = {
|
|
65
|
+
x: number;
|
|
66
|
+
y: number;
|
|
67
|
+
width: number;
|
|
68
|
+
height: number;
|
|
69
|
+
};
|
|
70
|
+
|
|
71
|
+
declare type SnapshotNode = RawSnapshotNode & {
|
|
72
|
+
ref: string;
|
|
73
|
+
};
|
|
74
|
+
|
|
75
|
+
export { }
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{findBestMatchesByLocator as o}from"./556.js";function r(r,e,t,_){return o(r,e,t,{requireRect:_})}export{normalizeRole,normalizeText,parseFindArgs}from"./556.js";export{r as findBestMatchesByLocator};
|
package/dist/src/index.d.ts
CHANGED
|
@@ -199,12 +199,14 @@ export declare type AppDeployResult = {
|
|
|
199
199
|
};
|
|
200
200
|
|
|
201
201
|
export declare class AppError extends Error {
|
|
202
|
-
code:
|
|
202
|
+
code: AppErrorCode;
|
|
203
203
|
details?: AppErrorDetails;
|
|
204
204
|
cause?: unknown;
|
|
205
|
-
constructor(code:
|
|
205
|
+
constructor(code: AppErrorCode, message: string, details?: AppErrorDetails, cause?: unknown);
|
|
206
206
|
}
|
|
207
207
|
|
|
208
|
+
declare type AppErrorCode = 'INVALID_ARGS' | 'DEVICE_NOT_FOUND' | 'TOOL_MISSING' | 'APP_NOT_INSTALLED' | 'UNSUPPORTED_PLATFORM' | 'UNSUPPORTED_OPERATION' | 'COMMAND_FAILED' | 'SESSION_NOT_FOUND' | 'UNAUTHORIZED' | 'UNKNOWN';
|
|
209
|
+
|
|
208
210
|
declare type AppErrorDetails = Record<string, unknown> & {
|
|
209
211
|
hint?: string;
|
|
210
212
|
diagnosticId?: string;
|
|
@@ -347,6 +349,8 @@ export declare type CaptureSnapshotResult = {
|
|
|
347
349
|
identifiers: AgentDeviceIdentifiers;
|
|
348
350
|
};
|
|
349
351
|
|
|
352
|
+
export declare function centerOfRect(rect: Rect): Point;
|
|
353
|
+
|
|
350
354
|
export declare type ClickOptions = ClientCommandBaseOptions & SelectorSnapshotCommandOptions & InteractionTarget & RepeatedPressOptions & {
|
|
351
355
|
button?: 'primary' | 'secondary' | 'middle';
|
|
352
356
|
};
|
|
@@ -609,8 +613,6 @@ export declare type EnsureSimulatorResult = {
|
|
|
609
613
|
identifiers: AgentDeviceIdentifiers;
|
|
610
614
|
};
|
|
611
615
|
|
|
612
|
-
declare type ErrorCode = 'INVALID_ARGS' | 'DEVICE_NOT_FOUND' | 'TOOL_MISSING' | 'APP_NOT_INSTALLED' | 'UNSUPPORTED_PLATFORM' | 'UNSUPPORTED_OPERATION' | 'COMMAND_FAILED' | 'SESSION_NOT_FOUND' | 'UNAUTHORIZED' | 'UNKNOWN';
|
|
613
|
-
|
|
614
616
|
export declare type FillOptions = ClientCommandBaseOptions & SelectorSnapshotCommandOptions & InteractionTarget & {
|
|
615
617
|
text: string;
|
|
616
618
|
delayMs?: number;
|
package/dist/src/index.js
CHANGED
|
@@ -1,2 +1,3 @@
|
|
|
1
|
-
import e from"node:net";import t from"node:http";import r from"node:https";import a from"node:fs";import n from"node:path";import{fileURLToPath as o}from"node:url";import{spawn as i}from"node:child_process";import s,{createHash as l}from"node:crypto";import{resolveUserPath as c,createRequestId as d,emitDiagnostic as u,withDiagnosticTimer as p,expandUserHomePath as m,AppError as f}from"./957.js";import{stopProcessForTakeover as h,prepareMetroRuntime as w,runCmdSync as y,isAgentDeviceDaemonProcess as v,runCmdDetached as I}from"./974.js";import{REMOTE_CONFIG_FIELD_SPECS as g,resolveRemoteConfigProfile as A,REMOTE_OPEN_PROFILE_KEYS as b}from"./924.js";function S(){let e=n.dirname(o(import.meta.url)),t=e;for(let e=0;e<6;e+=1){let e=n.join(t,"package.json");if(a.existsSync(e))return t;t=n.dirname(t)}return e}function D(e){let t,r=(t=(e??"").trim())?c(t):n.join(m("~"),".agent-device");return{baseDir:r,infoPath:n.join(r,"daemon.json"),lockPath:n.join(r,"daemon.lock"),logPath:n.join(r,"daemon.log"),sessionsDir:n.join(r,"sessions")}}let _="sha256";async function M(e){let{localPath:o,baseUrl:s,token:l}=e,c=a.statSync(o),d=c.isDirectory(),u=n.basename(o),p=d?"app-bundle":"file",m=s.endsWith("/")?s:`${s}/`,h=d?void 0:await E(o);if(h){let e=await k({normalizedBase:m,token:l,hash:h,filename:u,sizeBytes:c.size,artifactType:p});if(e)return e}let w=new URL("upload",m),y="https:"===w.protocol?r:t,v={"x-artifact-type":p,"x-artifact-filename":u,"transfer-encoding":"chunked"};return h&&(v["x-artifact-hash"]=h,v["x-artifact-hash-algorithm"]=_),l&&(v.authorization=`Bearer ${l}`,v["x-agent-device-token"]=l),new Promise((e,t)=>{let r=y.request({protocol:w.protocol,host:w.hostname,port:w.port,method:"POST",path:w.pathname+w.search,headers:v},r=>{let a="";r.setEncoding("utf8"),r.on("data",e=>{a+=e}),r.on("end",()=>{clearTimeout(s);try{let r=JSON.parse(a);if(!r.ok||!r.uploadId)return void t(new f("COMMAND_FAILED",`Upload failed: ${a}`));e(r.uploadId)}catch{t(new f("COMMAND_FAILED",`Invalid upload response: ${a}`))}})}),s=setTimeout(()=>{r.destroy(),t(new f("COMMAND_FAILED","Artifact upload timed out",{timeoutMs:3e5,hint:"The upload to the remote daemon exceeded the 5-minute timeout."}))},3e5);if(r.on("error",e=>{clearTimeout(s),t(new f("COMMAND_FAILED","Failed to upload artifact to remote daemon",{hint:"Verify the remote daemon is reachable and supports artifact uploads."},e))}),d){let e=i("tar",["cf","-","-C",n.dirname(o),n.basename(o)],{stdio:["ignore","pipe","pipe"]});e.stdout.pipe(r),e.on("error",e=>{r.destroy(),t(new f("COMMAND_FAILED","Failed to create tar archive for app bundle",{},e))}),e.on("close",e=>{0!==e&&(r.destroy(),t(new f("COMMAND_FAILED",`tar failed with exit code ${e}`)))})}else{let e=a.createReadStream(o);e.pipe(r),e.on("error",e=>{r.destroy(),t(new f("COMMAND_FAILED","Failed to read local artifact",{},e))})}})}async function k(e){var t;let r=new URL("upload/preflight",e.normalizedBase),a={"content-type":"application/json"};e.token&&(a.authorization=`Bearer ${e.token}`,a["x-agent-device-token"]=e.token);let n=await fetch(r,{method:"POST",headers:a,signal:AbortSignal.timeout(3e4),body:JSON.stringify({hash:e.hash,hashAlgorithm:_,fileName:e.filename,sizeBytes:e.sizeBytes,artifactType:e.artifactType})}).catch(()=>void 0);if(!n?.ok)return;let o=await n.json().catch(()=>void 0);return(t=o)&&"object"==typeof t&&!0===t.ok&&!0===t.cacheHit&&"string"==typeof t.uploadId?o.uploadId:void 0}async function E(e){let t=l(_);return await new Promise((r,n)=>{a.createReadStream(e).on("data",e=>t.update(e)).on("error",e=>{n(new f("COMMAND_FAILED","Failed to read local artifact",{},e))}).on("end",r)}),t.digest("hex")}let P=/(?:^|[^\w$.])(?:import|export)\s+(?:type\s+)?(?:[^'"`]*?\s+from\s+)?['"]([^'"]+)['"]/gm,N=/import\(\s*['"]([^'"]+)['"]\s*\)/gm,T=[".ts",".tsx",".js",".jsx",".mjs",".cjs"];function x(e,t,r){t.lastIndex=0;let a=null;for(;null!==(a=t.exec(e));){let e=a[1]?.trim();e?.startsWith(".")&&r.add(e)}}function R(e){try{return a.statSync(e).isFile()?e:null}catch{return null}}let C=ef(),U=function(e=process.env.AGENT_DEVICE_DAEMON_STARTUP_TIMEOUT_MS){if(!e)return 15e3;let t=Number(e);return Number.isFinite(t)?Math.max(1e3,Math.floor(t)):15e3}(),L=function(e=process.env.AGENT_DEVICE_DAEMON_STARTUP_ATTEMPTS){if(!e)return 2;let t=Number(e);return Number.isFinite(t)?Math.min(5,Math.max(1,Math.floor(t))):2}(),O=["xcodebuild .*AgentDeviceRunnerUITests/RunnerTests/testCommand","xcodebuild .*AgentDeviceRunner\\.env\\.session-","xcodebuild build-for-testing .*ios-runner/AgentDeviceRunner/AgentDeviceRunner\\.xcodeproj"],F=new e.BlockList;async function $(t){let r=t.meta?.requestId??d(),a=!!(t.meta?.debug||t.flags?.verbose),n=function(t){let r,a,n,o=t.flags?.stateDir??process.env.AGENT_DEVICE_STATE_DIR,i=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(/\/+$/,"")}}(t.flags?.daemonBaseUrl??process.env.AGENT_DEVICE_DAEMON_BASE_URL),s=t.flags?.daemonAuthToken??process.env.AGENT_DEVICE_DAEMON_AUTH_TOKEN;var l=i,c=s;if(!(!l||"localhost"===(r=new URL(l).hostname.trim().toLowerCase().replace(/^\[(.*)\]$/,"$1"))||(e.isIPv4(r)?F.check(r,"ipv4"):!!e.isIPv6(r)&&F.check(r,"ipv6")))&&("string"!=typeof c||!(c.trim().length>0)))throw new f("INVALID_ARGS","Remote daemon base URL for non-loopback hosts requires daemon authentication",{daemonBaseUrl:l,hint:"Provide --daemon-auth-token or AGENT_DEVICE_DAEMON_AUTH_TOKEN when using a non-loopback remote daemon URL."});let d=t.flags?.daemonTransport??process.env.AGENT_DEVICE_DAEMON_TRANSPORT,u="auto"===(a=(d??"").trim().toLowerCase())?"auto":"socket"===a?"socket":"http"===a?"http":"auto";if(i&&"socket"===u)throw new f("INVALID_ARGS","Remote daemon base URL only supports HTTP transport. Remove --daemon-transport socket.",{daemonBaseUrl:i});let p="http"===(n=(t.flags?.daemonServerMode??process.env.AGENT_DEVICE_DAEMON_SERVER_MODE??("dual"===d?"dual":void 0)??"").trim().toLowerCase())?"http":"dual"===n?"dual":"socket";return{paths:D(o),transportPreference:u,serverMode:p,remoteBaseUrl:i,remoteAuthToken:s}}(t),o=function(e,t=process.env.AGENT_DEVICE_DAEMON_TIMEOUT_MS){if("test"!==e)return ef(t)}(t.command),i=await p("daemon_startup",async()=>await G(n),{requestId:r,session:t.session}),s=await j(t,i),l={...t,positionals:s.positionals,flags:s.flags,token:i.token,meta:{...t.meta??{},requestId:r,debug:a,cwd:t.meta?.cwd,tenantId:t.meta?.tenantId??t.flags?.tenant,runId:t.meta?.runId??t.flags?.runId,leaseId:t.meta?.leaseId??t.flags?.leaseId,sessionIsolation:t.meta?.sessionIsolation??t.flags?.sessionIsolation,lockPolicy:t.meta?.lockPolicy,lockPlatform:t.meta?.lockPlatform,...s.uploadedArtifactId?{uploadedArtifactId:s.uploadedArtifactId}:{},...s.clientArtifactPaths?{clientArtifactPaths:s.clientArtifactPaths}:{},...s.installSource?{installSource:s.installSource}:{}}};return u({level:"info",phase:"daemon_request_prepare",data:{requestId:r,command:t.command,session:t.session}}),await p("daemon_request",async()=>await ea(i,l,n.transportPreference,o),{requestId:r,command:t.command})}async function j(e,t){let r,o=[...e.positionals??[]],i=e.flags?{...e.flags}:void 0,s=e.meta?.installSource,l={};if(ed(t)){let a=function(e,t){if("screenshot"===e.command){let r=B(e,"path",".png");return t[0]?{field:"path",localPath:r,positionalIndex:0,positionalPath:V("screenshot",".png")}:{field:"path",localPath:r,positionalIndex:0,flagPath:V("screenshot",".png")}}if("record"===e.command&&"start"===(t[0]??"").toLowerCase()){let t=B(e,"outPath",".mp4",1);return{field:"outPath",localPath:t,positionalIndex:1,positionalPath:V("recording",n.extname(t)||".mp4")}}return null}(e,o);a&&(void 0!==a.positionalPath&&(o[a.positionalIndex]=a.positionalPath),void 0!==a.flagPath&&((i??={}).out=a.flagPath),l[a.field]=a.localPath);let c=await q(e,t);c&&(s=c.installSource,r=c.uploadedArtifactId??r)}if(!ed(t)||"install"!==e.command&&"reinstall"!==e.command||o.length<2)return{positionals:o,flags:i,installSource:s,uploadedArtifactId:r,...Object.keys(l).length>0?{clientArtifactPaths:l}:{}};let c=o[1];if(c.startsWith("remote:"))return o[1]=c.slice(7),{positionals:o,flags:i,...Object.keys(l).length>0?{clientArtifactPaths:l}:{}};let d=n.isAbsolute(c)?c:n.resolve(e.meta?.cwd??process.cwd(),c);return a.existsSync(d)?{positionals:o,flags:i,installSource:s,uploadedArtifactId:r=await M({localPath:d,baseUrl:t.baseUrl,token:t.token}),...Object.keys(l).length>0?{clientArtifactPaths:l}:{}}:{positionals:o,flags:i,...Object.keys(l).length>0?{clientArtifactPaths:l}:{}}}async function q(e,t){let r=e.meta?.installSource;if("install_source"!==e.command||!r||"path"!==r.kind)return null;let o=r.path.trim();if(!o)return{installSource:r};if(o.startsWith("remote:"))return{installSource:{...r,path:o.slice(7)}};let i=n.isAbsolute(o)?o:n.resolve(e.meta?.cwd??process.cwd(),o);if(!a.existsSync(i))return{installSource:{...r,path:i}};let s=await M({localPath:i,baseUrl:t.baseUrl,token:t.token});return{installSource:{...r,path:i},uploadedArtifactId:s}}function B(e,t,r,a=0){let o=e.positionals?.[a]??e.flags?.out,i=`${"path"===t?"screenshot":"recording"}-${Date.now()}${r}`,s=o&&o.trim().length>0?o:i;return n.isAbsolute(s)?s:n.resolve(e.meta?.cwd??process.cwd(),s)}function V(e,t){let r=t.startsWith(".")?t:`.${t}`;return n.posix.join("/tmp",`agent-device-${e}-${Date.now()}-${Math.random().toString(36).slice(2,8)}${r}`)}async function G(e){let t;if(e.remoteBaseUrl){let t={transport:"http",token:e.remoteAuthToken??"",pid:0,baseUrl:e.remoteBaseUrl};if(await ee(t,"http"))return t;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."})}let r=W(e.paths.infoPath),o=function(){try{let e=S();return JSON.parse(a.readFileSync(n.join(e,"package.json"),"utf8")).version??"0.0.0"}catch{return"0.0.0"}}(),i=function(e,t=S()){try{let r=n.resolve(t),o=[n.resolve(e)],i=new Set,l=[];for(;o.length>0;){let e=o.pop();if(!e||i.has(e))continue;i.add(e);let t=a.statSync(e);if(!t.isFile())continue;let s=n.relative(r,e)||e;l.push(`${s}:${t.size}:${Math.trunc(t.mtimeMs)}`);let c=a.readFileSync(e,"utf8");for(let t of function(e){let t=new Set;return x(e,P,t),x(e,N,t),[...t]}(c)){let r=function(e,t){let r=n.resolve(n.dirname(e),t),a=R(r);if(a)return a;for(let e of T){let t=R(`${r}${e}`);if(t)return t}for(let e of T){let t=R(n.join(r,`index${e}`));if(t)return t}return null}(e,t);r&&o.push(r)}}let c=l.sort().join("|"),d=s.createHash("sha1").update(c).digest("hex");return`graph:${l.length}:${d}`}catch{return"unknown"}}((t=er()).useSrc?t.srcPath:t.distPath,t.root),l=!!r&&await ee(r,e.transportPreference);if(r&&r.version===o&&r.codeSignature===i&&l)return r;r&&(r.version!==o||r.codeSignature!==i||!l)&&(await J(r),Z(e.paths.infoPath)),function(e){let t=X(e);if(!t.hasLock||t.hasInfo)return;let r=Q(e.lockPath);if(!r)return Z(e.lockPath);v(r.pid,r.processStartTime)||Z(e.lockPath)}(e.paths);let c=0;for(let t=1;t<=L;t+=1){await et(e);let r=await z(U,e);if(r)return r;if(await K(e.paths)){c+=1;continue}let a=X(e.paths);if(!(t<L))break;if(!a.hasInfo&&!a.hasLock){await H(150);continue}}let d=X(e.paths);throw new f("COMMAND_FAILED","Failed to start daemon",{kind:"daemon_startup_failed",infoPath:e.paths.infoPath,lockPath:e.paths.lockPath,startupTimeoutMs:U,startupAttempts:L,lockRecoveryCount:c,metadataState:d,hint:function(e,t=D(process.env.AGENT_DEVICE_STATE_DIR)){return e.hasLock&&!e.hasInfo?`Detected ${t.lockPath} without ${t.infoPath}. If no agent-device daemon process is running, delete ${t.lockPath} and retry.`:e.hasLock&&e.hasInfo?`Daemon metadata may be stale. If no agent-device daemon process is running, delete ${t.infoPath} and ${t.lockPath}, then retry.`:`Daemon metadata is missing or stale. Delete ${t.infoPath} if present and retry.`}(d,e.paths)})}async function z(e,t){let r=Date.now();for(;Date.now()-r<e;){let e=W(t.paths.infoPath);if(e&&await ee(e,t.transportPreference))return e;await new Promise(e=>setTimeout(e,100))}return null}async function H(e){await new Promise(t=>setTimeout(t,e))}async function K(e){let t=X(e);if(!t.hasLock||t.hasInfo)return!1;let r=Q(e.lockPath);return r&&v(r.pid,r.processStartTime)&&await h(r.pid,{termTimeoutMs:3e3,killTimeoutMs:1e3,expectedStartTime:r.processStartTime}),Z(e.lockPath),!0}async function J(e){await h(e.pid,{termTimeoutMs:3e3,killTimeoutMs:1e3,expectedStartTime:e.processStartTime})}function W(e){let t=Y(e);if(!t||"object"!=typeof t)return null;let r="string"==typeof t.token&&t.token.length>0?t.token:null;if(!r)return null;let a=Number.isInteger(t.port)&&Number(t.port)>0,n=Number.isInteger(t.httpPort)&&Number(t.httpPort)>0;if(!a&&!n)return null;let o=t.transport,i="string"==typeof t.version?t.version:void 0,s="string"==typeof t.codeSignature?t.codeSignature:void 0,l="string"==typeof t.processStartTime?t.processStartTime:void 0,c=Number.isInteger(t.pid)&&Number(t.pid)>0;return{token:r,port:a?Number(t.port):void 0,httpPort:n?Number(t.httpPort):void 0,transport:"socket"===o||"http"===o||"dual"===o?o:void 0,pid:c?Number(t.pid):0,version:i,codeSignature:s,processStartTime:l}}function Q(e){let t=Y(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}F.addSubnet("127.0.0.0",8,"ipv4"),F.addAddress("::1","ipv6"),F.addSubnet("::ffff:127.0.0.0",104,"ipv6");function X(e){return{hasInfo:a.existsSync(e.infoPath),hasLock:a.existsSync(e.lockPath)}}function Y(e){if(!a.existsSync(e))return null;try{return JSON.parse(a.readFileSync(e,"utf8"))}catch{return null}}function Z(e){try{a.existsSync(e)&&a.unlinkSync(e)}catch{}}async function ee(a,n){var o;return"http"===en(a,n)?await function(e){let a=e.baseUrl?eu(e.baseUrl,"health"):e.httpPort?`http://127.0.0.1:${e.httpPort}/health`:null;if(!a)return Promise.resolve(!1);let n=new URL(a),o="https:"===n.protocol?r:t,i=e.baseUrl?3e3:500;return new Promise(e=>{let t=o.request({protocol:n.protocol,host:n.hostname,port:n.port,path:n.pathname+n.search,method:"GET",timeout:i},t=>{t.resume(),e((t.statusCode??500)<500)});t.on("timeout",()=>{t.destroy(),e(!1)}),t.on("error",()=>{e(!1)}),t.end()})}(a):await ((o=a.port)?new Promise(t=>{let r=e.createConnection({host:"127.0.0.1",port:o},()=>{r.destroy(),t(!0)});r.on("error",()=>{t(!1)})}):Promise.resolve(!1))}async function et(e){let t=er(),r=t.useSrc?["--experimental-strip-types",t.srcPath]:[t.distPath],a={...process.env,AGENT_DEVICE_STATE_DIR:e.paths.baseDir,AGENT_DEVICE_DAEMON_SERVER_MODE:e.serverMode};I(process.execPath,r,{env:a})}function er(){let e=S(),t=n.join(e,"dist","src","daemon.js"),r=n.join(e,"src","daemon.ts"),o=a.existsSync(t),i=a.existsSync(r);if(!o&&!i)throw new f("COMMAND_FAILED","Daemon entry not found",{distPath:t,srcPath:r});return{root:e,distPath:t,srcPath:r,useSrc:process.execArgv.includes("--experimental-strip-types")?i:!o&&i}}async function ea(e,t,r,a){return"http"===en(e,r)?await ec(e,t,a):await el(e,t,a)}function en(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 r=e,a=t;if(eo(r,a))return a;throw new f("COMMAND_FAILED","http"===a?"Daemon HTTP endpoint is unavailable":"Daemon socket endpoint is unavailable")}let n=("socket"===e.transport||"dual"===e.transport?["socket","http"]:["http","socket"]).find(t=>eo(e,t));if(n)return n;throw new f("COMMAND_FAILED","Daemon metadata has no reachable transport")}function eo(e,t){return"http"===t?!!e.httpPort:!!e.port}function ei(e,t,r,a,n,o){let i=n?{terminated:0}:function(){let e=0;try{for(let t of O){let r=y("pkill",["-f",t],{allowFailure:!0});0===r.exitCode&&(e+=1)}return{terminated:e}}catch(t){return{terminated:e,error:t instanceof Error?t.message:String(t)}}}(),s=n?{forcedKill:!1}:function(e,t){let r=!1;try{v(e.pid,e.processStartTime)&&(process.kill(e.pid,"SIGKILL"),r=!0)}catch{h(e.pid,{termTimeoutMs:3e3,killTimeoutMs:1e3,expectedStartTime:e.processStartTime})}finally{Z(t.infoPath),Z(t.lockPath)}return{forcedKill:r}}(e,t);return u({level:"error",phase:"daemon_request_timeout",data:{timeoutMs:o,requestId:r,command:a,timedOutRunnerPidsTerminated:i.terminated,timedOutRunnerCleanupError:i.error,daemonPidReset:n?void 0:e.pid,daemonPidForceKilled:n?void 0:s.forcedKill,daemonBaseUrl:e.baseUrl}}),new f("COMMAND_FAILED","Daemon request timed out",{timeoutMs:o,requestId:r,hint:n?"Retry with --debug and verify the remote daemon URL, auth token, and remote host logs.":"Retry with --debug and check daemon diagnostics logs. Timed-out iOS runner xcodebuild processes were terminated when detected."})}function es(e,t,r){return u({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",{requestId:t,hint:r?"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 el(t,r,a){let n=t.port;if(!n)throw new f("COMMAND_FAILED","Daemon socket endpoint is unavailable");return new Promise((o,i)=>{let s=e.createConnection({host:"127.0.0.1",port:n},()=>{s.write(`${JSON.stringify(r)}
|
|
2
|
-
`)}),l=D(r.flags?.stateDir??process.env.AGENT_DEVICE_STATE_DIR),c="number"==typeof a?setTimeout(()=>{s.destroy(),i(ei(t,l,r.meta?.requestId,r.command,!1,a))},a):void 0,d="";s.setEncoding("utf8"),s.on("data",e=>{let t=(d+=e).indexOf("\n");if(-1===t)return;let a=d.slice(0,t).trim();if(a)try{let e=JSON.parse(a);s.end(),c&&clearTimeout(c),o(e)}catch(e){c&&clearTimeout(c),i(new f("COMMAND_FAILED","Invalid daemon response",{requestId:r.meta?.requestId,line:a},e instanceof Error?e:void 0))}}),s.on("error",e=>{c&&clearTimeout(c),i(es(e,r.meta?.requestId,!1))})})}async function ec(e,a,n){let o=e.baseUrl?new URL(eu(e.baseUrl,"rpc")):e.httpPort?new URL(`http://127.0.0.1:${e.httpPort}/rpc`):null;if(!o)throw new f("COMMAND_FAILED","Daemon HTTP endpoint is unavailable");let i=JSON.stringify({jsonrpc:"2.0",id:a.meta?.requestId??d(),method:"agent_device.command",params:a}),s={"content-type":"application/json","content-length":Buffer.byteLength(i)};return e.baseUrl&&e.token&&(s.authorization=`Bearer ${e.token}`,s["x-agent-device-token"]=e.token),await new Promise((l,c)=>{let d=D(a.flags?.stateDir??process.env.AGENT_DEVICE_STATE_DIR),u=("https:"===o.protocol?r:t).request({protocol:o.protocol,host:o.hostname,port:o.port,method:"POST",path:o.pathname+o.search,headers:s},t=>{let r="";t.setEncoding("utf8"),t.on("data",e=>{r+=e}),t.on("end",()=>{m&&clearTimeout(m);try{let t=JSON.parse(r);if(t.error){let e=t.error.data??{};c(new f(String(e.code??"COMMAND_FAILED"),String(e.message??t.error.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:a.meta?.requestId}));return}if(!t.result||"object"!=typeof t.result)return void c(new f("COMMAND_FAILED","Invalid daemon RPC response",{requestId:a.meta?.requestId}));if(e.baseUrl&&t.result.ok)return void ep(e,a,t.result).then(l).catch(c);l(t.result)}catch(e){m&&clearTimeout(m),c(new f("COMMAND_FAILED","Invalid daemon response",{requestId:a.meta?.requestId,line:r},e instanceof Error?e:void 0))}})}),p=ed(e),m="number"==typeof n?setTimeout(()=>{u.destroy(),c(ei(e,d,a.meta?.requestId,a.command,p,n))},n):void 0;u.on("error",e=>{m&&clearTimeout(m),c(es(e,a.meta?.requestId,p))}),u.write(i),u.end()})}function ed(e){return"string"==typeof e.baseUrl&&e.baseUrl.length>0}function eu(e,t){return new URL(t,e.endsWith("/")?e:`${e}/`).toString()}async function ep(e,t,r){let a=Array.isArray(r.data?.artifacts)?r.data.artifacts:[];if(0===a.length||!e.baseUrl)return r;let o=r.data?{...r.data}:{},i=[];for(let r of a){if(!r||"object"!=typeof r||"string"!=typeof r.artifactId){i.push(r);continue}let a=function(e,t){if(e.localPath&&e.localPath.trim().length>0)return e.localPath;let r=e.fileName?.trim()||`${e.field}-${Date.now()}`;return n.resolve(t.meta?.cwd??process.cwd(),r)}(r,t);await em({baseUrl:e.baseUrl,token:e.token,artifactId:r.artifactId,destinationPath:a,requestId:t.meta?.requestId}),o[r.field]=a,i.push({...r,localPath:a})}return o.artifacts=i,{ok:!0,data:o}}async function em(e){var o,i;let s,l=new URL((o=e.baseUrl,i=e.artifactId,s=o.endsWith("/")?o:`${o}/`,new URL(`upload/${encodeURIComponent(i)}`,s).toString())),c="https:"===l.protocol?r:t;await a.promises.mkdir(n.dirname(e.destinationPath),{recursive:!0}),await new Promise((t,r)=>{let n=!1,o=e.timeoutMs??C,i=o=>{if(!n){if(n=!0,clearTimeout(d),o)return void a.promises.rm(e.destinationPath,{force:!0}).finally(()=>r(o));t()}},s=c.request({protocol:l.protocol,host:l.hostname,port:l.port,method:"GET",path:l.pathname+l.search,headers:e.token?{authorization:`Bearer ${e.token}`,"x-agent-device-token":e.token}:void 0},t=>{if((t.statusCode??500)>=400){let r="";t.setEncoding("utf8"),t.on("data",e=>{r+=e}),t.on("end",()=>{i(new f("COMMAND_FAILED","Failed to download remote artifact",{artifactId:e.artifactId,statusCode:t.statusCode,requestId:e.requestId,body:r}))});return}let r=a.createWriteStream(e.destinationPath);r.on("error",e=>{i(e instanceof Error?e:Error(String(e)))}),t.on("error",e=>{i(e instanceof Error?e:Error(String(e)))}),t.on("aborted",()=>{i(new f("COMMAND_FAILED","Remote artifact download was interrupted",{artifactId:e.artifactId,requestId:e.requestId}))}),r.on("finish",()=>{r.close(()=>i())}),t.pipe(r)}),d=setTimeout(()=>{s.destroy(new f("COMMAND_FAILED","Remote artifact download timed out",{artifactId:e.artifactId,requestId:e.requestId,timeoutMs:o}))},o);s.on("error",t=>{t instanceof f?i(t):i(new f("COMMAND_FAILED","Failed to download remote artifact",{artifactId:e.artifactId,requestId:e.requestId,timeoutMs:o},t instanceof Error?t:void 0))}),s.end()})}function ef(e=process.env.AGENT_DEVICE_DAEMON_TIMEOUT_MS){if(!e)return 9e4;let t=Number(e);return Number.isFinite(t)?Math.max(1e3,Math.floor(t)):9e4}let eh="clipboard",ew="wait",ey=new Set(["id","role","text","label","value","appname","windowtitle"]),ev=new Set(["visible","hidden","editable","selected","enabled","hittable"]),eI=new Set([...ey,...ev]);function eg(e){let t=e.trim();if(!t)throw new f("INVALID_ARGS","Empty selector term");let r=t.indexOf("=");if(-1===r){let r=t.toLowerCase();if(!ev.has(r))throw new f("INVALID_ARGS",`Invalid selector term "${e}", expected key=value`);return{key:r,value:!0}}let a=t.slice(0,r).trim().toLowerCase(),n=t.slice(r+1).trim();if(!eI.has(a))throw new f("INVALID_ARGS",`Unknown selector key: ${a}`);if(!n)throw new f("INVALID_ARGS",`Missing selector value for key: ${a}`);if(ev.has(a)){let e,t="true"===(e=eb(n).toLowerCase())||"false"!==e&&null;if(null===t)throw new f("INVALID_ARGS",`Invalid boolean value for ${a}: ${n}`);return{key:a,value:t}}return{key:a,value:eb(n)}}function eA(e,t){return e?e===t?null:e:t}function eb(e){let t=e.trim();return t.startsWith('"')&&t.endsWith('"')||t.startsWith("'")&&t.endsWith("'")?t.slice(1,-1).replace(/\\(["'])/g,"$1"):t}function eS(e,t){let r=0;for(let a=t-1;a>=0&&"\\"===e[a];a-=1)r+=1;return r%2==1}let eD=g.map(e=>e.key);function e_(e){let t=e.appId??e.bundleId??e.packageName;return{session:e.session,appId:t,appBundleId:e.bundleId,package:e.packageName}}function eM(e,t,r){return{deviceId:t,deviceName:r,..."android"===e?{serial:t}:"ios"===e?{udid:t}:{}}}function ek(e,t,r,a){let n=r(e[t]);if(void 0===n)throw new f("COMMAND_FAILED",a,{response:e});return n}[...b];function eE(e,t){return ek(e,t,eC,`Daemon response is missing "${t}".`)}function eP(e,t){return eC(e[t])}function eN(e,t){var r;let a;return r=eC,null===(a=e[t])?null:r(a)}function eT(e,t){return ek(e,t,eL,`Daemon response has invalid "${t}".`)}function ex(e,t){return function(e){return"tv"===e||"mobile"===e||"desktop"===e?e:void 0}(e[t])??"mobile"}function eR(e,t){let r=e[t];if(!e$(r))return;let a="number"==typeof r.x?r.x:void 0,n="number"==typeof r.y?r.y:void 0,o="number"==typeof r.width?r.width:void 0,i="number"==typeof r.height?r.height:void 0;if(void 0!==a&&void 0!==n&&void 0!==o&&void 0!==i)return{x:a,y:n,width:o,height:i}}function eC(e){return"string"==typeof e&&e.length>0?e:void 0}function eU(e){return"number"==typeof e&&Number.isFinite(e)?e:void 0}function eL(e){return"ios"===e||"macos"===e||"android"===e?e:void 0}function eO(e){return"simulator"===e||"emulator"===e||"device"===e?e:void 0}function eF(e){if(!e$(e))throw new f("COMMAND_FAILED","Daemon returned an unexpected response shape.",{value:e});return e}function e$(e){return"object"==typeof e&&null!==e}function ej(e){let t={};for(let[r,a]of Object.entries(e))void 0!==a&&(t[r]=a);return t}function eq(e,t){let r=eP(e,"bundleId"),a=eP(e,"package");return{app:eE(e,"app"),appPath:eE(e,"appPath"),platform:eT(e,"platform"),appId:r??a,bundleId:r,package:a,identifiers:e_({session:t,bundleId:r,packageName:a})}}function eB(e){let t=eF(e),r=eT(t,"platform"),a=eE(t,"id"),n=eE(t,"name");return{platform:r,target:ex(t,"target"),kind:ek(t,"kind",eO,'Daemon response has invalid "kind".'),id:a,name:n,booted:"boolean"==typeof t.booted?t.booted:void 0,identifiers:eM(r,a,n),ios:"ios"===r?{udid:a}:void 0,android:"android"===r?{serial:a}:void 0}}function eV(e){let t=eF(e),r=eT(t,"platform"),a=eE(t,"id"),n=eE(t,"name"),o=ex(t,"target"),i=eE(t,"device"),s={session:n,...eM(r,a,i)};return{name:n,createdAt:ek(t,"createdAt",eU,'Daemon response is missing numeric "createdAt".'),device:{platform:r,target:o,id:a,name:i,identifiers:s,ios:"ios"===r?{udid:a,simulatorSetPath:eN(t,"ios_simulator_device_set")}:void 0,android:"android"===r?{serial:a}:void 0},identifiers:s}}function eG(e){return e??"default"}function ez(e={},t={}){var r;let a,n=t.transport??$,o=eQ(e),i=async(t,r=[],a={})=>{let i=eW(e,o,a),s=await n({session:eG(i.session),command:t,positionals:r,flags:ej({stateDir:i.stateDir,daemonBaseUrl:i.daemonBaseUrl,daemonAuthToken:i.daemonAuthToken,daemonTransport:i.daemonTransport,daemonServerMode:i.daemonServerMode,tenant:i.tenant,sessionIsolation:i.sessionIsolation,runId:i.runId,leaseId:i.leaseId,platform:i.platform,target:i.target,device:i.device,udid:i.udid,serial:i.serial,iosSimulatorDeviceSet:i.iosSimulatorDeviceSet,androidDeviceAllowlist:i.androidDeviceAllowlist,runtime:i.simulatorRuntimeId,boot:i.boot,reuseExisting:i.reuseExisting,surface:i.surface,activity:i.activity,relaunch:i.relaunch,shutdown:i.shutdown,saveScript:i.saveScript,noRecord:i.noRecord,backMode:i.backMode,metroHost:i.metroHost,metroPort:i.metroPort,bundleUrl:i.bundleUrl,launchUrl:i.launchUrl,snapshotInteractiveOnly:i.interactiveOnly,snapshotCompact:i.compact,snapshotDepth:i.depth,snapshotScope:i.scope,snapshotRaw:i.raw,screenshotFullscreen:i.screenshotFullscreen,overlayRefs:i.overlayRefs,appsFilter:i.appsFilter,out:i.out,count:i.count,fps:i.fps,hideTouches:i.hideTouches,intervalMs:i.intervalMs,delayMs:i.delayMs,holdMs:i.holdMs,jitterPx:i.jitterPx,pixels:i.pixels,doubleTap:i.doubleTap,clickButton:i.clickButton,pauseMs:i.pauseMs,pattern:i.pattern,maxScrolls:i.maxScrolls,headless:i.headless,restart:i.restart,replayUpdate:i.replayUpdate,failFast:i.failFast,timeoutMs:i.timeoutMs,retries:i.retries,artifactsDir:i.artifactsDir,reportJunit:i.reportJunit,findFirst:i.findFirst,findLast:i.findLast,networkInclude:i.networkInclude,batchOnError:i.batchOnError,batchMaxSteps:i.batchMaxSteps,batchSteps:i.batchSteps,verbose:i.debug}),runtime:i.runtime,meta:ej({requestId:i.requestId,cwd:i.cwd,debug:i.debug,lockPolicy:i.lockPolicy,lockPlatform:i.lockPlatform,tenantId:i.tenant,runId:i.runId,leaseId:i.leaseId,sessionIsolation:i.sessionIsolation,installSource:i.installSource,retainMaterializedPaths:i.retainMaterializedPaths,materializedPathRetentionMs:i.materializedPathRetentionMs,materializationId:i.materializationId})});return s.ok||function(e){throw new f(e.code,e.message,{...e.details??{},hint:e.hint,diagnosticId:e.diagnosticId,logPath:e.logPath})}(s.error),s.data??{}},s=async(e={})=>{let t=await i("session_list",[],e);return(Array.isArray(t.sessions)?t.sessions:[]).map(eV)},l=async(e,t=[],r={})=>await i(e,t,r),c=(t={})=>eG(eW(e,o,t).session);return{command:(r=async e=>await i(e.command,e.positionals,e.options),a=async e=>await r(e),{wait:async e=>await a(function(e){if(1!==[void 0!==e.durationMs?"durationMs":void 0,void 0!==e.text?"text":void 0,void 0!==e.ref?"ref":void 0,void 0!==e.selector?"selector":void 0].filter(Boolean).length)throw new f("INVALID_ARGS","wait command requires exactly one of durationMs, text, ref, or selector.");if(void 0!==e.durationMs)return{command:ew,positionals:[String(e.durationMs)],options:e};let t=void 0!==e.timeoutMs?[String(e.timeoutMs)]:[];if(void 0!==e.text)return{command:ew,positionals:["text",e.text,...t],options:e};if(void 0!==e.ref)return{command:ew,positionals:[e.ref,...t],options:e};let r=e.selector;return function(e){if(!function(e){try{let t=e.trim();if(!t)throw new f("INVALID_ARGS","Selector expression cannot be empty");let r=function(e){let t=[],r="",a=null;for(let n=0;n<e.length;n+=1){let o=e[n];if(('"'===o||"'"===o)&&!eS(e,n)){a=eA(a,o),r+=o;continue}if(!a&&"|"===o&&"|"===e[n+1]){let a=r.trim();if(!a)throw new f("INVALID_ARGS",`Invalid selector fallback expression: ${e}`);t.push(a),r="",n+=1;continue}r+=o}let n=r.trim();if(!n)throw new f("INVALID_ARGS",`Invalid selector fallback expression: ${e}`);return t.push(n),t}(t);if(0===r.length)throw new f("INVALID_ARGS","Selector expression cannot be empty");return{raw:t,selectors:r.map(e=>(function(e){let t=e.trim();if(!t)throw new f("INVALID_ARGS","Selector segment cannot be empty");let r=function(e){let t=[],r="",a=null;for(let n=0;n<e.length;n+=1){let o=e[n];if(('"'===o||"'"===o)&&!eS(e,n)){a=eA(a,o),r+=o;continue}if(!a&&/\s/.test(o)){r.trim()&&t.push(r.trim()),r="";continue}r+=o}if(a)throw new f("INVALID_ARGS",`Unclosed quote in selector: ${e}`);return r.trim()&&t.push(r.trim()),t}(t);if(0===r.length)throw new f("INVALID_ARGS",`Invalid selector segment: ${e}`);return{raw:t,terms:r.map(eg)}})(e))}}catch{return null}}(e))throw new f("INVALID_ARGS",`Invalid wait selector: ${e}`)}(r),{command:ew,positionals:[r,...t],options:e}}(e)),alert:async(e={})=>{var t;return await a({command:"alert",positionals:[(t=e).action??"get",...void 0!==t.timeoutMs?[String(t.timeoutMs)]:[]],options:t})},appState:async(e={})=>await a({command:"appstate",positionals:[],options:e}),back:async(e={})=>await a({command:"back",positionals:[],options:{...e,backMode:e.mode}}),home:async(e={})=>await a({command:"home",positionals:[],options:e}),rotate:async e=>await a({command:"rotate",positionals:[e.orientation],options:e}),appSwitcher:async(e={})=>await a({command:"app-switcher",positionals:[],options:e}),keyboard:async(e={})=>await a({command:"keyboard",positionals:e.action?[e.action]:[],options:e}),clipboard:async e=>{var t;return await a("read"===(t=e).action?{command:eh,positionals:["read"],options:t}:{command:eh,positionals:["write",t.text],options:t})}}),devices:{list:async(e={})=>{let t=await i("devices",[],e);return(Array.isArray(t.devices)?t.devices:[]).map(eB)},boot:async(e={})=>await l("boot",[],e)},sessions:{list:async(e={})=>await s(e),close:async(e={})=>{let t=c(e),r=(await i("close",[],e)).shutdown;return{session:t,shutdown:"object"==typeof r&&null!==r?r:void 0,identifiers:{session:t}}}},simulators:{ensure:async e=>{let{runtime:t,...r}=e,a=await i("ensure-simulator",[],{...r,simulatorRuntimeId:t}),n=eE(a,"udid"),o=eE(a,"device");return{udid:n,device:o,runtime:eE(a,"runtime"),created:!0===a.created,booted:!0===a.booted,iosSimulatorDeviceSet:eN(a,"ios_simulator_device_set"),identifiers:{deviceId:n,deviceName:o,udid:n}}}},apps:{install:async e=>eq(await i("install",[e.app,e.appPath],e),c(e)),reinstall:async e=>eq(await i("reinstall",[e.app,e.appPath],e),c(e)),installFromSource:async e=>(function(e,t){let r=eP(e,"bundleId"),a=eP(e,"packageName"),n=r??a??eP(e,"appId"),o=eP(e,"launchTarget")??a??r??n;if(!o)throw new f("COMMAND_FAILED",'Daemon response is missing "launchTarget".',{response:e});return{appName:eP(e,"appName"),appId:n,bundleId:r,packageName:a,launchTarget:o,installablePath:eP(e,"installablePath"),archivePath:eP(e,"archivePath"),materializationId:eP(e,"materializationId"),materializationExpiresAt:eP(e,"materializationExpiresAt"),identifiers:e_({session:t,bundleId:r,packageName:a,appId:n})}})(await i("install_source",[],{...e,installSource:e.source,retainMaterializedPaths:e.retainPaths,materializedPathRetentionMs:e.retentionMs}),c(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=c(e),r=e.app?e.url?[e.app,e.url]:[e.app]:[],a=await i("open",r,e),n=function(e){let t=e.platform,r=eP(e,"id"),a=eP(e,"device");if("ios"!==t&&"macos"!==t&&"android"!==t||!r||!a)return;let n=ex(e,"target"),o=eM(t,r,a);return{platform:t,target:n,id:r,name:a,identifiers:o,ios:"ios"===t?{udid:eP(e,"device_udid")??r,simulatorSetPath:eN(e,"ios_simulator_device_set")}:void 0,android:"android"===t?{serial:eP(e,"serial")??r}:void 0}}(a),o=eP(a,"appBundleId");return{session:t,appName:eP(a,"appName"),appBundleId:o,appId:o,startup:function(e){if(e$(e)&&"number"==typeof e.durationMs&&"string"==typeof e.measuredAt&&"string"==typeof e.method)return{durationMs:e.durationMs,measuredAt:e.measuredAt,method:e.method,appTarget:eP(e,"appTarget"),appBundleId:eP(e,"appBundleId")}}(a.startup),runtime:function(e){if(!e$(e))return;let t=e.platform,r=eP(e,"metroHost"),a="number"==typeof e.metroPort?e.metroPort:void 0;return{platform:"ios"===t||"android"===t?t:void 0,metroHost:r,metroPort:a,bundleUrl:eP(e,"bundleUrl"),launchUrl:eP(e,"launchUrl")}}(a.runtime),device:n,identifiers:{session:t,deviceId:n?.id,deviceName:n?.name,udid:n?.ios?.udid,serial:n?.android?.serial,appId:o,appBundleId:o}}},close:async(e={})=>{let t=c(e),r=(await i("close",e.app?[e.app]:[],e)).shutdown;return{session:t,closedApp:e.app,shutdown:"object"==typeof r&&null!==r?r:void 0,identifiers:{session:t}}},push:async e=>{var t;return await l("push",[e.app,"string"==typeof(t=e.payload)?t:JSON.stringify(t)],e)},triggerEvent:async e=>{var t;return await l("trigger-app-event",[(t=e).event,...t.payload?[JSON.stringify(t.payload)]:[]],e)}},materializations:{release:async e=>{var t;return{released:!0===(t=await i("release_materialized_paths",[],{...e,materializationId:e.materializationId})).released,materializationId:eE(t,"materializationId"),identifiers:{}}}},metro:{prepare:async t=>await w({projectRoot:t.projectRoot??e.cwd,kind:t.kind,publicBaseUrl:t.publicBaseUrl,proxyBaseUrl:t.proxyBaseUrl,proxyBearerToken:t.bearerToken,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})},capture:{snapshot:async(e={})=>{var t;let r=c(e),a=await i("snapshot",[],e),n=eP(a,"appBundleId"),o="object"==typeof a.visibility&&null!==a.visibility?a.visibility:void 0;return{nodes:Array.isArray(t=a.nodes)?t:[],truncated:!0===a.truncated,appName:eP(a,"appName"),appBundleId:n,...o?{visibility:o}:{},warnings:Array.isArray(a.warnings)?a.warnings.filter(e=>"string"==typeof e):void 0,identifiers:{session:r,appId:n,appBundleId:n}}},screenshot:async(e={})=>{let t=c(e),r=await i("screenshot",e.path?[e.path]:[],{...e,screenshotFullscreen:e.fullscreen});return{path:eE(r,"path"),overlayRefs:function(e){let t=e.overlayRefs;if(!Array.isArray(t))return;let r=[];for(let e of t){if(!e$(e))continue;let t=eP(e,"ref"),a=eR(e,"rect"),n=eR(e,"overlayRect"),o=function(e,t){let r=e[t];if(!e$(r))return;let a="number"==typeof r.x?r.x:void 0,n="number"==typeof r.y?r.y:void 0;if(void 0!==a&&void 0!==n)return{x:a,y:n}}(e,"center");t&&a&&n&&o&&r.push({ref:t,label:eP(e,"label"),rect:a,overlayRect:n,center:o})}return r}(r),identifiers:{session:t}}},diff:async e=>await l("diff",[e.kind],{...e,interactiveOnly:e.interactiveOnly,compact:e.compact,depth:e.depth,scope:e.scope,raw:e.raw})},interactions:{click:async e=>await l("click",eH(e),{...e,clickButton:e.button}),press:async e=>await l("press",eH(e),e),longPress:async e=>await l("longpress",[String(e.x),String(e.y),...eJ(e.durationMs)],e),swipe:async e=>await l("swipe",[String(e.from.x),String(e.from.y),String(e.to.x),String(e.to.y),...eJ(e.durationMs)],e),focus:async e=>await l("focus",[String(e.x),String(e.y)],e),type:async e=>await l("type",[e.text],e),fill:async e=>await l("fill",[...eH(e),e.text],e),scroll:async e=>await l("scroll",[e.direction,...eJ(e.amount)],e),scrollIntoView:async e=>{var t;return await l("scrollintoview",void 0!==(t=e).ref?[t.ref,...eK(t.label)]:[t.text??""],e)},pinch:async e=>await l("pinch",[String(e.scale),...eJ(e.x),...eJ(e.y)],e),get:async e=>{var t;return await l("get",[e.format,...void 0!==(t=e).ref?[t.ref,...eK(t.label)]:[t.selector]],e)},is:async e=>await l("is",[e.predicate,e.selector,..."text"===e.predicate?[e.value]:[]],e),find:async e=>await l("find",function(e){let t=e.locator&&"any"!==e.locator?[e.locator,e.query]:[e.query];switch(e.action){case void 0:case"click":case"focus":case"exists":return e.action?[...t,e.action]:t;case"getText":return[...t,"get","text"];case"getAttrs":return[...t,"get","attrs"];case"wait":return[...t,"wait",...eJ(e.timeoutMs)];case"fill":case"type":return[...t,e.action,e.value]}}(e),{...e,findFirst:e.first,findLast:e.last})},replay:{run:async e=>await l("replay",[e.path],{...e,replayUpdate:e.update}),test:async e=>await l("test",e.paths,{...e,replayUpdate:e.update})},batch:{run:async e=>await l("batch",[],{...e,batchSteps:e.steps,batchOnError:e.onError,batchMaxSteps:e.maxSteps})},observability:{perf:async(e={})=>await l("perf",[],e),logs:async(e={})=>{var t;return await l("logs",[(t=e).action??"path",...eK(t.message)],e)},network:async(e={})=>{var t;return await l("network",[...(t=e).action?[t.action]:[],...eJ(t.limit)],{...e,networkInclude:e.include})}},recording:{record:async e=>await l("record",[e.action,...eK(e.path)],e),trace:async e=>await l("trace",[e.action,...eK(e.path)],e)},settings:{update:async e=>await l("settings",[e.setting,e.state,..."permission"in e?[e.permission]:[],..."mode"in e&&e.mode?[e.mode]:[]],e)}}}function eH(e){return void 0!==e.ref?[e.ref,...eK(e.label)]:void 0!==e.selector?[e.selector]:[String(e.x),String(e.y)]}function eK(e){return void 0===e?[]:[e]}function eJ(e){return void 0===e?[]:[String(e)]}function eW(e,t,r){return r.remoteConfig&&r.remoteConfig!==e.remoteConfig?{...eQ({...e,...r}),...e,...r}:{...t,...e,...r}}function eQ(e){var t;if(!e.remoteConfig)return{};let{runtime:r,...a}=(t={remoteConfig:e.remoteConfig,cwd:e.cwd??process.cwd(),env:process.env}).remoteConfig?{...function(e){let t={};for(let r of eD){let a=e[r];void 0!==a&&(t[r]=a)}return t}(A({configPath:t.remoteConfig,cwd:t.cwd,env:t.env}).profile),remoteConfig:t.remoteConfig}:{};return a}export{AppError}from"./957.js";export{ez as createAgentDeviceClient};
|
|
1
|
+
import e from"node:net";import t from"node:http";import a from"node:https";import r from"node:fs";import o from"node:path";import{fileURLToPath as n}from"node:url";import{AsyncLocalStorage as i}from"node:async_hooks";import s,{createHash as l}from"node:crypto";import"node:os";import{spawn as d}from"node:child_process";import{redactDiagnosticData as c,AppError as u}from"./152.js";import{resolveUserPath as p,expandUserHomePath as m}from"./267.js";import{runCmdDetached as f,runCmdSync as h}from"./818.js";import{prepareMetroRuntime as y,isAgentDeviceDaemonProcess as w,stopProcessForTakeover as v}from"./974.js";import{tryParseSelectorChain as g}from"./940.js";import{REMOTE_CONFIG_FIELD_SPECS as I,resolveRemoteConfigProfile as A,REMOTE_OPEN_PROFILE_KEYS as b}from"./924.js";function S(){let e=o.dirname(n(import.meta.url)),t=e;for(let e=0;e<6;e+=1){let e=o.join(t,"package.json");if(r.existsSync(e))return t;t=o.dirname(t)}return e}let _=new i;function M(){return s.randomBytes(8).toString("hex")}function P(e){let t=_.getStore();if(!t)return;let a={ts:new Date().toISOString(),level:e.level??"info",phase:e.phase,session:t.session,requestId:t.requestId,command:t.command,durationMs:e.durationMs,data:e.data?c(e.data):void 0};if(t.events.push(a),!t.debug)return;let o=`[agent-device][diag] ${JSON.stringify(a)}
|
|
2
|
+
`;try{t.logPath&&r.appendFile(t.logPath,o,()=>{}),t.traceLogPath&&r.appendFile(t.traceLogPath,o,()=>{}),t.logPath||t.traceLogPath||process.stderr.write(o)}catch{}}async function D(e,t,a){let r=Date.now();try{let o=await t();return P({level:"info",phase:e,durationMs:Date.now()-r,data:a}),o}catch(t){throw P({level:"error",phase:e,durationMs:Date.now()-r,data:{...a??{},error:t instanceof Error?t.message:String(t)}}),t}}function E(e){let t,a=(t=(e??"").trim())?p(t):o.join(m("~"),".agent-device");return{baseDir:a,infoPath:o.join(a,"daemon.json"),lockPath:o.join(a,"daemon.lock"),logPath:o.join(a,"daemon.log"),sessionsDir:o.join(a,"sessions")}}let k="sha256";async function T(e){let{localPath:n,baseUrl:i,token:s}=e,l=r.statSync(n),c=l.isDirectory(),p=o.basename(n),m=c?"app-bundle":"file",f=i.endsWith("/")?i:`${i}/`,h=c?void 0:await x(n);if(h){let e=await N({normalizedBase:f,token:s,hash:h,filename:p,sizeBytes:l.size,artifactType:m});if(e)return e}let y=new URL("upload",f),w="https:"===y.protocol?a:t,v={"x-artifact-type":m,"x-artifact-filename":p,"transfer-encoding":"chunked"};return h&&(v["x-artifact-hash"]=h,v["x-artifact-hash-algorithm"]=k),s&&(v.authorization=`Bearer ${s}`,v["x-agent-device-token"]=s),new Promise((e,t)=>{let a=w.request({protocol:y.protocol,host:y.hostname,port:y.port,method:"POST",path:y.pathname+y.search,headers:v},a=>{let r="";a.setEncoding("utf8"),a.on("data",e=>{r+=e}),a.on("end",()=>{clearTimeout(i);try{let a=JSON.parse(r);if(!a.ok||!a.uploadId)return void t(new u("COMMAND_FAILED",`Upload failed: ${r}`));e(a.uploadId)}catch{t(new u("COMMAND_FAILED",`Invalid upload response: ${r}`))}})}),i=setTimeout(()=>{a.destroy(),t(new u("COMMAND_FAILED","Artifact upload timed out",{timeoutMs:3e5,hint:"The upload to the remote daemon exceeded the 5-minute timeout."}))},3e5);if(a.on("error",e=>{clearTimeout(i),t(new u("COMMAND_FAILED","Failed to upload artifact to remote daemon",{hint:"Verify the remote daemon is reachable and supports artifact uploads."},e))}),c){let e=d("tar",["cf","-","-C",o.dirname(n),o.basename(n)],{stdio:["ignore","pipe","pipe"]});e.stdout.pipe(a),e.on("error",e=>{a.destroy(),t(new u("COMMAND_FAILED","Failed to create tar archive for app bundle",{},e))}),e.on("close",e=>{0!==e&&(a.destroy(),t(new u("COMMAND_FAILED",`tar failed with exit code ${e}`)))})}else{let e=r.createReadStream(n);e.pipe(a),e.on("error",e=>{a.destroy(),t(new u("COMMAND_FAILED","Failed to read local artifact",{},e))})}})}async function N(e){var t;let a=new URL("upload/preflight",e.normalizedBase),r={"content-type":"application/json"};e.token&&(r.authorization=`Bearer ${e.token}`,r["x-agent-device-token"]=e.token);let o=await fetch(a,{method:"POST",headers:r,signal:AbortSignal.timeout(3e4),body:JSON.stringify({hash:e.hash,hashAlgorithm:k,fileName:e.filename,sizeBytes:e.sizeBytes,artifactType:e.artifactType})}).catch(()=>void 0);if(!o?.ok)return;let n=await o.json().catch(()=>void 0);return(t=n)&&"object"==typeof t&&!0===t.ok&&!0===t.cacheHit&&"string"==typeof t.uploadId?n.uploadId:void 0}async function x(e){let t=l(k);return await new Promise((a,o)=>{r.createReadStream(e).on("data",e=>t.update(e)).on("error",e=>{o(new u("COMMAND_FAILED","Failed to read local artifact",{},e))}).on("end",a)}),t.digest("hex")}let C=/(?:^|[^\w$.])(?:import|export)\s+(?:type\s+)?(?:[^'"`]*?\s+from\s+)?['"]([^'"]+)['"]/gm,U=/import\(\s*['"]([^'"]+)['"]\s*\)/gm,R=[".ts",".tsx",".js",".jsx",".mjs",".cjs"];function O(e,t,a){t.lastIndex=0;let r=null;for(;null!==(r=t.exec(e));){let e=r[1]?.trim();e?.startsWith(".")&&a.add(e)}}function L(e){try{return r.statSync(e).isFile()?e:null}catch{return null}}let F=ev(),$=function(e=process.env.AGENT_DEVICE_DAEMON_STARTUP_TIMEOUT_MS){if(!e)return 15e3;let t=Number(e);return Number.isFinite(t)?Math.max(1e3,Math.floor(t)):15e3}(),j=function(e=process.env.AGENT_DEVICE_DAEMON_STARTUP_ATTEMPTS){if(!e)return 2;let t=Number(e);return Number.isFinite(t)?Math.min(5,Math.max(1,Math.floor(t))):2}(),q=["xcodebuild .*AgentDeviceRunnerUITests/RunnerTests/testCommand","xcodebuild .*AgentDeviceRunner\\.env\\.session-","xcodebuild build-for-testing .*ios-runner/AgentDeviceRunner/AgentDeviceRunner\\.xcodeproj"],B=new e.BlockList;async function z(t){let a=t.meta?.requestId??M(),r=!!(t.meta?.debug||t.flags?.verbose),o=function(t){let a,r,o,n=t.flags?.stateDir??process.env.AGENT_DEVICE_STATE_DIR,i=function(e){let t;if(e){try{t=new URL(e)}catch(t){throw new u("INVALID_ARGS","Invalid daemon base URL",{daemonBaseUrl:e},t instanceof Error?t:void 0)}if("http:"!==t.protocol&&"https:"!==t.protocol)throw new u("INVALID_ARGS","Daemon base URL must use http or https",{daemonBaseUrl:e});return t.toString().replace(/\/+$/,"")}}(t.flags?.daemonBaseUrl??process.env.AGENT_DEVICE_DAEMON_BASE_URL),s=t.flags?.daemonAuthToken??process.env.AGENT_DEVICE_DAEMON_AUTH_TOKEN;var l=i,d=s;if(!(!l||"localhost"===(a=new URL(l).hostname.trim().toLowerCase().replace(/^\[(.*)\]$/,"$1"))||(e.isIPv4(a)?B.check(a,"ipv4"):!!e.isIPv6(a)&&B.check(a,"ipv6")))&&("string"!=typeof d||!(d.trim().length>0)))throw new u("INVALID_ARGS","Remote daemon base URL for non-loopback hosts requires daemon authentication",{daemonBaseUrl:l,hint:"Provide --daemon-auth-token or AGENT_DEVICE_DAEMON_AUTH_TOKEN when using a non-loopback remote daemon URL."});let c=t.flags?.daemonTransport??process.env.AGENT_DEVICE_DAEMON_TRANSPORT,p="auto"===(r=(c??"").trim().toLowerCase())?"auto":"socket"===r?"socket":"http"===r?"http":"auto";if(i&&"socket"===p)throw new u("INVALID_ARGS","Remote daemon base URL only supports HTTP transport. Remove --daemon-transport socket.",{daemonBaseUrl:i});let m="http"===(o=(t.flags?.daemonServerMode??process.env.AGENT_DEVICE_DAEMON_SERVER_MODE??("dual"===c?"dual":void 0)??"").trim().toLowerCase())?"http":"dual"===o?"dual":"socket";return{paths:E(n),transportPreference:p,serverMode:m,remoteBaseUrl:i,remoteAuthToken:s}}(t),n=function(e,t=process.env.AGENT_DEVICE_DAEMON_TIMEOUT_MS){if("test"!==e)return ev(t)}(t.command),i=await D("daemon_startup",async()=>await J(o),{requestId:a,session:t.session}),s=await V(t,i),l={...t,positionals:s.positionals,flags:s.flags,token:i.token,meta:{...t.meta??{},requestId:a,debug:r,cwd:t.meta?.cwd,tenantId:t.meta?.tenantId??t.flags?.tenant,runId:t.meta?.runId??t.flags?.runId,leaseId:t.meta?.leaseId??t.flags?.leaseId,sessionIsolation:t.meta?.sessionIsolation??t.flags?.sessionIsolation,lockPolicy:t.meta?.lockPolicy,lockPlatform:t.meta?.lockPlatform,...s.uploadedArtifactId?{uploadedArtifactId:s.uploadedArtifactId}:{},...s.clientArtifactPaths?{clientArtifactPaths:s.clientArtifactPaths}:{},...s.installSource?{installSource:s.installSource}:{}}};return P({level:"info",phase:"daemon_request_prepare",data:{requestId:a,command:t.command,session:t.session}}),await D("daemon_request",async()=>await es(i,l,o.transportPreference,n),{requestId:a,command:t.command})}async function V(e,t){let a,n=[...e.positionals??[]],i=e.flags?{...e.flags}:void 0,s=e.meta?.installSource,l={};if(ef(t)){let r=function(e,t){if("screenshot"===e.command){let a=K(e,"path",".png");return t[0]?{field:"path",localPath:a,positionalIndex:0,positionalPath:H("screenshot",".png")}:{field:"path",localPath:a,positionalIndex:0,flagPath:H("screenshot",".png")}}if("record"===e.command&&"start"===(t[0]??"").toLowerCase()){let t=K(e,"outPath",".mp4",1);return{field:"outPath",localPath:t,positionalIndex:1,positionalPath:H("recording",o.extname(t)||".mp4")}}return null}(e,n);r&&(void 0!==r.positionalPath&&(n[r.positionalIndex]=r.positionalPath),void 0!==r.flagPath&&((i??={}).out=r.flagPath),l[r.field]=r.localPath);let d=await G(e,t);d&&(s=d.installSource,a=d.uploadedArtifactId??a)}if(!ef(t)||"install"!==e.command&&"reinstall"!==e.command||n.length<2)return{positionals:n,flags:i,installSource:s,uploadedArtifactId:a,...Object.keys(l).length>0?{clientArtifactPaths:l}:{}};let d=n[1];if(d.startsWith("remote:"))return n[1]=d.slice(7),{positionals:n,flags:i,...Object.keys(l).length>0?{clientArtifactPaths:l}:{}};let c=o.isAbsolute(d)?d:o.resolve(e.meta?.cwd??process.cwd(),d);return r.existsSync(c)?{positionals:n,flags:i,installSource:s,uploadedArtifactId:a=await T({localPath:c,baseUrl:t.baseUrl,token:t.token}),...Object.keys(l).length>0?{clientArtifactPaths:l}:{}}:{positionals:n,flags:i,...Object.keys(l).length>0?{clientArtifactPaths:l}:{}}}async function G(e,t){let a=e.meta?.installSource;if("install_source"!==e.command||!a||"path"!==a.kind)return null;let n=a.path.trim();if(!n)return{installSource:a};if(n.startsWith("remote:"))return{installSource:{...a,path:n.slice(7)}};let i=o.isAbsolute(n)?n:o.resolve(e.meta?.cwd??process.cwd(),n);if(!r.existsSync(i))return{installSource:{...a,path:i}};let s=await T({localPath:i,baseUrl:t.baseUrl,token:t.token});return{installSource:{...a,path:i},uploadedArtifactId:s}}function K(e,t,a,r=0){let n=e.positionals?.[r]??e.flags?.out,i=`${"path"===t?"screenshot":"recording"}-${Date.now()}${a}`,s=n&&n.trim().length>0?n:i;return o.isAbsolute(s)?s:o.resolve(e.meta?.cwd??process.cwd(),s)}function H(e,t){let a=t.startsWith(".")?t:`.${t}`;return o.posix.join("/tmp",`agent-device-${e}-${Date.now()}-${Math.random().toString(36).slice(2,8)}${a}`)}async function J(e){let t;if(e.remoteBaseUrl){let t={transport:"http",token:e.remoteAuthToken??"",pid:0,baseUrl:e.remoteBaseUrl};if(await eo(t,"http"))return t;throw new u("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."})}let a=Z(e.paths.infoPath),n=function(){try{let e=S();return JSON.parse(r.readFileSync(o.join(e,"package.json"),"utf8")).version??"0.0.0"}catch{return"0.0.0"}}(),i=function(e,t=S()){try{let a=o.resolve(t),n=[o.resolve(e)],i=new Set,l=[];for(;n.length>0;){let e=n.pop();if(!e||i.has(e))continue;i.add(e);let t=r.statSync(e);if(!t.isFile())continue;let s=o.relative(a,e)||e;l.push(`${s}:${t.size}:${Math.trunc(t.mtimeMs)}`);let d=r.readFileSync(e,"utf8");for(let t of function(e){let t=new Set;return O(e,C,t),O(e,U,t),[...t]}(d)){let a=function(e,t){let a=o.resolve(o.dirname(e),t),r=L(a);if(r)return r;for(let e of R){let t=L(`${a}${e}`);if(t)return t}for(let e of R){let t=L(o.join(a,`index${e}`));if(t)return t}return null}(e,t);a&&n.push(a)}}let d=l.sort().join("|"),c=s.createHash("sha1").update(d).digest("hex");return`graph:${l.length}:${c}`}catch{return"unknown"}}((t=ei()).useSrc?t.srcPath:t.distPath,t.root),l=!!a&&await eo(a,e.transportPreference);if(a&&a.version===n&&a.codeSignature===i&&l)return a;a&&(a.version!==n||a.codeSignature!==i||!l)&&(await Y(a),er(e.paths.infoPath)),function(e){let t=et(e);if(!t.hasLock||t.hasInfo)return;let a=ee(e.lockPath);if(!a)return er(e.lockPath);w(a.pid,a.processStartTime)||er(e.lockPath)}(e.paths);let d=0;for(let t=1;t<=j;t+=1){await en(e);let a=await W($,e);if(a)return a;if(await X(e.paths)){d+=1;continue}let r=et(e.paths);if(!(t<j))break;if(!r.hasInfo&&!r.hasLock){await Q(150);continue}}let c=et(e.paths);throw new u("COMMAND_FAILED","Failed to start daemon",{kind:"daemon_startup_failed",infoPath:e.paths.infoPath,lockPath:e.paths.lockPath,startupTimeoutMs:$,startupAttempts:j,lockRecoveryCount:d,metadataState:c,hint:function(e,t=E(process.env.AGENT_DEVICE_STATE_DIR)){return e.hasLock&&!e.hasInfo?`Detected ${t.lockPath} without ${t.infoPath}. If no agent-device daemon process is running, delete ${t.lockPath} and retry.`:e.hasLock&&e.hasInfo?`Daemon metadata may be stale. If no agent-device daemon process is running, delete ${t.infoPath} and ${t.lockPath}, then retry.`:`Daemon metadata is missing or stale. Delete ${t.infoPath} if present and retry.`}(c,e.paths)})}async function W(e,t){let a=Date.now();for(;Date.now()-a<e;){let e=Z(t.paths.infoPath);if(e&&await eo(e,t.transportPreference))return e;await new Promise(e=>setTimeout(e,100))}return null}async function Q(e){await new Promise(t=>setTimeout(t,e))}async function X(e){let t=et(e);if(!t.hasLock||t.hasInfo)return!1;let a=ee(e.lockPath);return a&&w(a.pid,a.processStartTime)&&await v(a.pid,{termTimeoutMs:3e3,killTimeoutMs:1e3,expectedStartTime:a.processStartTime}),er(e.lockPath),!0}async function Y(e){await v(e.pid,{termTimeoutMs:3e3,killTimeoutMs:1e3,expectedStartTime:e.processStartTime})}function Z(e){let t=ea(e);if(!t||"object"!=typeof t)return null;let a="string"==typeof t.token&&t.token.length>0?t.token:null;if(!a)return null;let r=Number.isInteger(t.port)&&Number(t.port)>0,o=Number.isInteger(t.httpPort)&&Number(t.httpPort)>0;if(!r&&!o)return null;let n=t.transport,i="string"==typeof t.version?t.version:void 0,s="string"==typeof t.codeSignature?t.codeSignature:void 0,l="string"==typeof t.processStartTime?t.processStartTime:void 0,d=Number.isInteger(t.pid)&&Number(t.pid)>0;return{token:a,port:r?Number(t.port):void 0,httpPort:o?Number(t.httpPort):void 0,transport:"socket"===n||"http"===n||"dual"===n?n:void 0,pid:d?Number(t.pid):0,version:i,codeSignature:s,processStartTime:l}}function ee(e){let t=ea(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}B.addSubnet("127.0.0.0",8,"ipv4"),B.addAddress("::1","ipv6"),B.addSubnet("::ffff:127.0.0.0",104,"ipv6");function et(e){return{hasInfo:r.existsSync(e.infoPath),hasLock:r.existsSync(e.lockPath)}}function ea(e){if(!r.existsSync(e))return null;try{return JSON.parse(r.readFileSync(e,"utf8"))}catch{return null}}function er(e){try{r.existsSync(e)&&r.unlinkSync(e)}catch{}}async function eo(r,o){var n;return"http"===el(r,o)?await function(e){let r=e.baseUrl?eh(e.baseUrl,"health"):e.httpPort?`http://127.0.0.1:${e.httpPort}/health`:null;if(!r)return Promise.resolve(!1);let o=new URL(r),n="https:"===o.protocol?a:t,i=e.baseUrl?3e3:500;return new Promise(e=>{let t=n.request({protocol:o.protocol,host:o.hostname,port:o.port,path:o.pathname+o.search,method:"GET",timeout:i},t=>{t.resume(),e((t.statusCode??500)<500)});t.on("timeout",()=>{t.destroy(),e(!1)}),t.on("error",()=>{e(!1)}),t.end()})}(r):await ((n=r.port)?new Promise(t=>{let a=e.createConnection({host:"127.0.0.1",port:n},()=>{a.destroy(),t(!0)});a.on("error",()=>{t(!1)})}):Promise.resolve(!1))}async function en(e){let t=ei(),a=t.useSrc?["--experimental-strip-types",t.srcPath]:[t.distPath],r={...process.env,AGENT_DEVICE_STATE_DIR:e.paths.baseDir,AGENT_DEVICE_DAEMON_SERVER_MODE:e.serverMode};f(process.execPath,a,{env:r})}function ei(){let e=S(),t=o.join(e,"dist","src","daemon.js"),a=o.join(e,"src","daemon.ts"),n=r.existsSync(t),i=r.existsSync(a);if(!n&&!i)throw new u("COMMAND_FAILED","Daemon entry not found",{distPath:t,srcPath:a});return{root:e,distPath:t,srcPath:a,useSrc:process.execArgv.includes("--experimental-strip-types")?i:!n&&i}}async function es(e,t,a,r){return"http"===el(e,a)?await em(e,t,r):await ep(e,t,r)}function el(e,t){if(e.baseUrl){if("socket"===t)throw new u("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(ed(a,r))return r;throw new u("COMMAND_FAILED","http"===r?"Daemon HTTP endpoint is unavailable":"Daemon socket endpoint is unavailable")}let o=("socket"===e.transport||"dual"===e.transport?["socket","http"]:["http","socket"]).find(t=>ed(e,t));if(o)return o;throw new u("COMMAND_FAILED","Daemon metadata has no reachable transport")}function ed(e,t){return"http"===t?!!e.httpPort:!!e.port}function ec(e,t,a,r,o,n){let i=o?{terminated:0}:function(){let e=0;try{for(let t of q){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=o?{forcedKill:!1}:function(e,t){let a=!1;try{w(e.pid,e.processStartTime)&&(process.kill(e.pid,"SIGKILL"),a=!0)}catch{v(e.pid,{termTimeoutMs:3e3,killTimeoutMs:1e3,expectedStartTime:e.processStartTime})}finally{er(t.infoPath),er(t.lockPath)}return{forcedKill:a}}(e,t);return P({level:"error",phase:"daemon_request_timeout",data:{timeoutMs:n,requestId:a,command:r,timedOutRunnerPidsTerminated:i.terminated,timedOutRunnerCleanupError:i.error,daemonPidReset:o?void 0:e.pid,daemonPidForceKilled:o?void 0:s.forcedKill,daemonBaseUrl:e.baseUrl}}),new u("COMMAND_FAILED","Daemon request timed out",{timeoutMs:n,requestId:a,hint:o?"Retry with --debug and verify the remote daemon URL, auth token, and remote host logs.":"Retry with --debug and check daemon diagnostics logs. Timed-out iOS runner xcodebuild processes were terminated when detected."})}function eu(e,t,a){return P({level:"error",phase:"daemon_request_socket_error",data:{requestId:t,message:e instanceof Error?e.message:String(e)}}),new u("COMMAND_FAILED","Failed to communicate with daemon",{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 ep(t,a,r){let o=t.port;if(!o)throw new u("COMMAND_FAILED","Daemon socket endpoint is unavailable");return new Promise((n,i)=>{let s=e.createConnection({host:"127.0.0.1",port:o},()=>{s.write(`${JSON.stringify(a)}
|
|
3
|
+
`)}),l=E(a.flags?.stateDir??process.env.AGENT_DEVICE_STATE_DIR),d="number"==typeof r?setTimeout(()=>{s.destroy(),i(ec(t,l,a.meta?.requestId,a.command,!1,r))},r):void 0,c="";s.setEncoding("utf8"),s.on("data",e=>{let t=(c+=e).indexOf("\n");if(-1===t)return;let r=c.slice(0,t).trim();if(r)try{let e=JSON.parse(r);s.end(),d&&clearTimeout(d),n(e)}catch(e){d&&clearTimeout(d),i(new u("COMMAND_FAILED","Invalid daemon response",{requestId:a.meta?.requestId,line:r},e instanceof Error?e:void 0))}}),s.on("error",e=>{d&&clearTimeout(d),i(eu(e,a.meta?.requestId,!1))})})}async function em(e,r,o){let n=e.baseUrl?new URL(eh(e.baseUrl,"rpc")):e.httpPort?new URL(`http://127.0.0.1:${e.httpPort}/rpc`):null;if(!n)throw new u("COMMAND_FAILED","Daemon HTTP endpoint is unavailable");let i=JSON.stringify({jsonrpc:"2.0",id:r.meta?.requestId??M(),method:"agent_device.command",params:r}),s={"content-type":"application/json","content-length":Buffer.byteLength(i)};return e.baseUrl&&e.token&&(s.authorization=`Bearer ${e.token}`,s["x-agent-device-token"]=e.token),await new Promise((l,d)=>{let c=E(r.flags?.stateDir??process.env.AGENT_DEVICE_STATE_DIR),p=("https:"===n.protocol?a:t).request({protocol:n.protocol,host:n.hostname,port:n.port,method:"POST",path:n.pathname+n.search,headers:s},t=>{let a="";t.setEncoding("utf8"),t.on("data",e=>{a+=e}),t.on("end",()=>{f&&clearTimeout(f);try{let t=JSON.parse(a);if(t.error){let e=t.error.data??{};d(new u(String(e.code??"COMMAND_FAILED"),String(e.message??t.error.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:r.meta?.requestId}));return}if(!t.result||"object"!=typeof t.result)return void d(new u("COMMAND_FAILED","Invalid daemon RPC response",{requestId:r.meta?.requestId}));if(e.baseUrl&&t.result.ok)return void ey(e,r,t.result).then(l).catch(d);l(t.result)}catch(e){f&&clearTimeout(f),d(new u("COMMAND_FAILED","Invalid daemon response",{requestId:r.meta?.requestId,line:a},e instanceof Error?e:void 0))}})}),m=ef(e),f="number"==typeof o?setTimeout(()=>{p.destroy(),d(ec(e,c,r.meta?.requestId,r.command,m,o))},o):void 0;p.on("error",e=>{f&&clearTimeout(f),d(eu(e,r.meta?.requestId,m))}),p.write(i),p.end()})}function ef(e){return"string"==typeof e.baseUrl&&e.baseUrl.length>0}function eh(e,t){return new URL(t,e.endsWith("/")?e:`${e}/`).toString()}async function ey(e,t,a){let r=Array.isArray(a.data?.artifacts)?a.data.artifacts:[];if(0===r.length||!e.baseUrl)return a;let n=a.data?{...a.data}:{},i=[];for(let a of r){if(!a||"object"!=typeof a||"string"!=typeof a.artifactId){i.push(a);continue}let r=function(e,t){if(e.localPath&&e.localPath.trim().length>0)return e.localPath;let a=e.fileName?.trim()||`${e.field}-${Date.now()}`;return o.resolve(t.meta?.cwd??process.cwd(),a)}(a,t);await ew({baseUrl:e.baseUrl,token:e.token,artifactId:a.artifactId,destinationPath:r,requestId:t.meta?.requestId}),n[a.field]=r,i.push({...a,localPath:r})}return n.artifacts=i,{ok:!0,data:n}}async function ew(e){var n,i;let s,l=new URL((n=e.baseUrl,i=e.artifactId,s=n.endsWith("/")?n:`${n}/`,new URL(`upload/${encodeURIComponent(i)}`,s).toString())),d="https:"===l.protocol?a:t;await r.promises.mkdir(o.dirname(e.destinationPath),{recursive:!0}),await new Promise((t,a)=>{let o=!1,n=e.timeoutMs??F,i=n=>{if(!o){if(o=!0,clearTimeout(c),n)return void r.promises.rm(e.destinationPath,{force:!0}).finally(()=>a(n));t()}},s=d.request({protocol:l.protocol,host:l.hostname,port:l.port,method:"GET",path:l.pathname+l.search,headers:e.token?{authorization:`Bearer ${e.token}`,"x-agent-device-token":e.token}:void 0},t=>{if((t.statusCode??500)>=400){let a="";t.setEncoding("utf8"),t.on("data",e=>{a+=e}),t.on("end",()=>{i(new u("COMMAND_FAILED","Failed to download remote artifact",{artifactId:e.artifactId,statusCode:t.statusCode,requestId:e.requestId,body:a}))});return}let a=r.createWriteStream(e.destinationPath);a.on("error",e=>{i(e instanceof Error?e:Error(String(e)))}),t.on("error",e=>{i(e instanceof Error?e:Error(String(e)))}),t.on("aborted",()=>{i(new u("COMMAND_FAILED","Remote artifact download was interrupted",{artifactId:e.artifactId,requestId:e.requestId}))}),a.on("finish",()=>{a.close(()=>i())}),t.pipe(a)}),c=setTimeout(()=>{s.destroy(new u("COMMAND_FAILED","Remote artifact download timed out",{artifactId:e.artifactId,requestId:e.requestId,timeoutMs:n}))},n);s.on("error",t=>{t instanceof u?i(t):i(new u("COMMAND_FAILED","Failed to download remote artifact",{artifactId:e.artifactId,requestId:e.requestId,timeoutMs:n},t instanceof Error?t:void 0))}),s.end()})}function ev(e=process.env.AGENT_DEVICE_DAEMON_TIMEOUT_MS){if(!e)return 9e4;let t=Number(e);return Number.isFinite(t)?Math.max(1e3,Math.floor(t)):9e4}let eg="clipboard",eI="wait",eA=I.map(e=>e.key);function eb(e){let t=e.appId??e.bundleId??e.packageName;return{session:e.session,appId:t,appBundleId:e.bundleId,package:e.packageName}}function eS(e,t,a){return{deviceId:t,deviceName:a,..."android"===e?{serial:t}:"ios"===e?{udid:t}:{}}}function e_(e,t,a,r){let o=a(e[t]);if(void 0===o)throw new u("COMMAND_FAILED",r,{response:e});return o}[...b];function eM(e,t){return e_(e,t,eN,`Daemon response is missing "${t}".`)}function eP(e,t){return eN(e[t])}function eD(e,t){var a;let r;return a=eN,null===(r=e[t])?null:a(r)}function eE(e,t){return e_(e,t,eC,`Daemon response has invalid "${t}".`)}function ek(e,t){return function(e){return"tv"===e||"mobile"===e||"desktop"===e?e:void 0}(e[t])??"mobile"}function eT(e,t){let a=e[t];if(!eO(a))return;let r="number"==typeof a.x?a.x:void 0,o="number"==typeof a.y?a.y:void 0,n="number"==typeof a.width?a.width:void 0,i="number"==typeof a.height?a.height:void 0;if(void 0!==r&&void 0!==o&&void 0!==n&&void 0!==i)return{x:r,y:o,width:n,height:i}}function eN(e){return"string"==typeof e&&e.length>0?e:void 0}function ex(e){return"number"==typeof e&&Number.isFinite(e)?e:void 0}function eC(e){return"ios"===e||"macos"===e||"android"===e?e:void 0}function eU(e){return"simulator"===e||"emulator"===e||"device"===e?e:void 0}function eR(e){if(!eO(e))throw new u("COMMAND_FAILED","Daemon returned an unexpected response shape.",{value:e});return e}function eO(e){return"object"==typeof e&&null!==e}function eL(e){let t={};for(let[a,r]of Object.entries(e))void 0!==r&&(t[a]=r);return t}function eF(e,t){let a=eP(e,"bundleId"),r=eP(e,"package");return{app:eM(e,"app"),appPath:eM(e,"appPath"),platform:eE(e,"platform"),appId:a??r,bundleId:a,package:r,identifiers:eb({session:t,bundleId:a,packageName:r})}}function e$(e){let t=eR(e),a=eE(t,"platform"),r=eM(t,"id"),o=eM(t,"name");return{platform:a,target:ek(t,"target"),kind:e_(t,"kind",eU,'Daemon response has invalid "kind".'),id:r,name:o,booted:"boolean"==typeof t.booted?t.booted:void 0,identifiers:eS(a,r,o),ios:"ios"===a?{udid:r}:void 0,android:"android"===a?{serial:r}:void 0}}function ej(e){let t=eR(e),a=eE(t,"platform"),r=eM(t,"id"),o=eM(t,"name"),n=ek(t,"target"),i=eM(t,"device"),s={session:o,...eS(a,r,i)};return{name:o,createdAt:e_(t,"createdAt",ex,'Daemon response is missing numeric "createdAt".'),device:{platform:a,target:n,id:r,name:i,identifiers:s,ios:"ios"===a?{udid:r,simulatorSetPath:eD(t,"ios_simulator_device_set")}:void 0,android:"android"===a?{serial:r}:void 0},identifiers:s}}function eq(e){return e??"default"}function eB(e={},t={}){var a;let r,o=t.transport??z,n=eH(e),i=async(t,a=[],r={})=>{let i=eK(e,n,r),s=await o({session:eq(i.session),command:t,positionals:a,flags:eL({stateDir:i.stateDir,daemonBaseUrl:i.daemonBaseUrl,daemonAuthToken:i.daemonAuthToken,daemonTransport:i.daemonTransport,daemonServerMode:i.daemonServerMode,tenant:i.tenant,sessionIsolation:i.sessionIsolation,runId:i.runId,leaseId:i.leaseId,platform:i.platform,target:i.target,device:i.device,udid:i.udid,serial:i.serial,iosSimulatorDeviceSet:i.iosSimulatorDeviceSet,androidDeviceAllowlist:i.androidDeviceAllowlist,runtime:i.simulatorRuntimeId,boot:i.boot,reuseExisting:i.reuseExisting,surface:i.surface,activity:i.activity,relaunch:i.relaunch,shutdown:i.shutdown,saveScript:i.saveScript,noRecord:i.noRecord,backMode:i.backMode,metroHost:i.metroHost,metroPort:i.metroPort,bundleUrl:i.bundleUrl,launchUrl:i.launchUrl,snapshotInteractiveOnly:i.interactiveOnly,snapshotCompact:i.compact,snapshotDepth:i.depth,snapshotScope:i.scope,snapshotRaw:i.raw,screenshotFullscreen:i.screenshotFullscreen,overlayRefs:i.overlayRefs,appsFilter:i.appsFilter,out:i.out,count:i.count,fps:i.fps,hideTouches:i.hideTouches,intervalMs:i.intervalMs,delayMs:i.delayMs,holdMs:i.holdMs,jitterPx:i.jitterPx,pixels:i.pixels,doubleTap:i.doubleTap,clickButton:i.clickButton,pauseMs:i.pauseMs,pattern:i.pattern,maxScrolls:i.maxScrolls,headless:i.headless,restart:i.restart,replayUpdate:i.replayUpdate,failFast:i.failFast,timeoutMs:i.timeoutMs,retries:i.retries,artifactsDir:i.artifactsDir,reportJunit:i.reportJunit,findFirst:i.findFirst,findLast:i.findLast,networkInclude:i.networkInclude,batchOnError:i.batchOnError,batchMaxSteps:i.batchMaxSteps,batchSteps:i.batchSteps,verbose:i.debug}),runtime:i.runtime,meta:eL({requestId:i.requestId,cwd:i.cwd,debug:i.debug,lockPolicy:i.lockPolicy,lockPlatform:i.lockPlatform,tenantId:i.tenant,runId:i.runId,leaseId:i.leaseId,sessionIsolation:i.sessionIsolation,installSource:i.installSource,retainMaterializedPaths:i.retainMaterializedPaths,materializedPathRetentionMs:i.materializedPathRetentionMs,materializationId:i.materializationId})});return s.ok||function(e){throw new u(e.code,e.message,{...e.details??{},hint:e.hint,diagnosticId:e.diagnosticId,logPath:e.logPath})}(s.error),s.data??{}},s=async(e={})=>{let t=await i("session_list",[],e);return(Array.isArray(t.sessions)?t.sessions:[]).map(ej)},l=async(e,t=[],a={})=>await i(e,t,a),d=(t={})=>eq(eK(e,n,t).session);return{command:(a=async e=>await i(e.command,e.positionals,e.options),r=async e=>await a(e),{wait:async e=>await r(function(e){if(1!==[void 0!==e.durationMs?"durationMs":void 0,void 0!==e.text?"text":void 0,void 0!==e.ref?"ref":void 0,void 0!==e.selector?"selector":void 0].filter(Boolean).length)throw new u("INVALID_ARGS","wait command requires exactly one of durationMs, text, ref, or selector.");if(void 0!==e.durationMs)return{command:eI,positionals:[String(e.durationMs)],options:e};let t=void 0!==e.timeoutMs?[String(e.timeoutMs)]:[];if(void 0!==e.text)return{command:eI,positionals:["text",e.text,...t],options:e};if(void 0!==e.ref)return{command:eI,positionals:[e.ref,...t],options:e};let a=e.selector;return function(e){if(!g(e))throw new u("INVALID_ARGS",`Invalid wait selector: ${e}`)}(a),{command:eI,positionals:[a,...t],options:e}}(e)),alert:async(e={})=>{var t;return await r({command:"alert",positionals:[(t=e).action??"get",...void 0!==t.timeoutMs?[String(t.timeoutMs)]:[]],options:t})},appState:async(e={})=>await r({command:"appstate",positionals:[],options:e}),back:async(e={})=>await r({command:"back",positionals:[],options:{...e,backMode:e.mode}}),home:async(e={})=>await r({command:"home",positionals:[],options:e}),rotate:async e=>await r({command:"rotate",positionals:[e.orientation],options:e}),appSwitcher:async(e={})=>await r({command:"app-switcher",positionals:[],options:e}),keyboard:async(e={})=>await r({command:"keyboard",positionals:e.action?[e.action]:[],options:e}),clipboard:async e=>{var t;return await r("read"===(t=e).action?{command:eg,positionals:["read"],options:t}:{command:eg,positionals:["write",t.text],options:t})}}),devices:{list:async(e={})=>{let t=await i("devices",[],e);return(Array.isArray(t.devices)?t.devices:[]).map(e$)},boot:async(e={})=>await l("boot",[],e)},sessions:{list:async(e={})=>await s(e),close:async(e={})=>{let t=d(e),a=(await i("close",[],e)).shutdown;return{session:t,shutdown:"object"==typeof a&&null!==a?a:void 0,identifiers:{session:t}}}},simulators:{ensure:async e=>{let{runtime:t,...a}=e,r=await i("ensure-simulator",[],{...a,simulatorRuntimeId:t}),o=eM(r,"udid"),n=eM(r,"device");return{udid:o,device:n,runtime:eM(r,"runtime"),created:!0===r.created,booted:!0===r.booted,iosSimulatorDeviceSet:eD(r,"ios_simulator_device_set"),identifiers:{deviceId:o,deviceName:n,udid:o}}}},apps:{install:async e=>eF(await i("install",[e.app,e.appPath],e),d(e)),reinstall:async e=>eF(await i("reinstall",[e.app,e.appPath],e),d(e)),installFromSource:async e=>(function(e,t){let a=eP(e,"bundleId"),r=eP(e,"packageName"),o=a??r??eP(e,"appId"),n=eP(e,"launchTarget")??r??a??o;if(!n)throw new u("COMMAND_FAILED",'Daemon response is missing "launchTarget".',{response:e});return{appName:eP(e,"appName"),appId:o,bundleId:a,packageName:r,launchTarget:n,installablePath:eP(e,"installablePath"),archivePath:eP(e,"archivePath"),materializationId:eP(e,"materializationId"),materializationExpiresAt:eP(e,"materializationExpiresAt"),identifiers:eb({session:t,bundleId:a,packageName:r,appId:o})}})(await i("install_source",[],{...e,installSource:e.source,retainMaterializedPaths:e.retainPaths,materializedPathRetentionMs:e.retentionMs}),d(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=d(e),a=e.app?e.url?[e.app,e.url]:[e.app]:[],r=await i("open",a,e),o=function(e){let t=e.platform,a=eP(e,"id"),r=eP(e,"device");if("ios"!==t&&"macos"!==t&&"android"!==t||!a||!r)return;let o=ek(e,"target"),n=eS(t,a,r);return{platform:t,target:o,id:a,name:r,identifiers:n,ios:"ios"===t?{udid:eP(e,"device_udid")??a,simulatorSetPath:eD(e,"ios_simulator_device_set")}:void 0,android:"android"===t?{serial:eP(e,"serial")??a}:void 0}}(r),n=eP(r,"appBundleId");return{session:t,appName:eP(r,"appName"),appBundleId:n,appId:n,startup:function(e){if(eO(e)&&"number"==typeof e.durationMs&&"string"==typeof e.measuredAt&&"string"==typeof e.method)return{durationMs:e.durationMs,measuredAt:e.measuredAt,method:e.method,appTarget:eP(e,"appTarget"),appBundleId:eP(e,"appBundleId")}}(r.startup),runtime:function(e){if(!eO(e))return;let t=e.platform,a=eP(e,"metroHost"),r="number"==typeof e.metroPort?e.metroPort:void 0;return{platform:"ios"===t||"android"===t?t:void 0,metroHost:a,metroPort:r,bundleUrl:eP(e,"bundleUrl"),launchUrl:eP(e,"launchUrl")}}(r.runtime),device:o,identifiers:{session:t,deviceId:o?.id,deviceName:o?.name,udid:o?.ios?.udid,serial:o?.android?.serial,appId:n,appBundleId:n}}},close:async(e={})=>{let t=d(e),a=(await i("close",e.app?[e.app]:[],e)).shutdown;return{session:t,closedApp:e.app,shutdown:"object"==typeof a&&null!==a?a:void 0,identifiers:{session:t}}},push:async e=>{var t;return await l("push",[e.app,"string"==typeof(t=e.payload)?t:JSON.stringify(t)],e)},triggerEvent:async e=>{var t;return await l("trigger-app-event",[(t=e).event,...t.payload?[JSON.stringify(t.payload)]:[]],e)}},materializations:{release:async e=>{var t;return{released:!0===(t=await i("release_materialized_paths",[],{...e,materializationId:e.materializationId})).released,materializationId:eM(t,"materializationId"),identifiers:{}}}},metro:{prepare:async t=>await y({projectRoot:t.projectRoot??e.cwd,kind:t.kind,publicBaseUrl:t.publicBaseUrl,proxyBaseUrl:t.proxyBaseUrl,proxyBearerToken:t.bearerToken,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})},capture:{snapshot:async(e={})=>{var t;let a=d(e),r=await i("snapshot",[],e),o=eP(r,"appBundleId"),n="object"==typeof r.visibility&&null!==r.visibility?r.visibility:void 0;return{nodes:Array.isArray(t=r.nodes)?t:[],truncated:!0===r.truncated,appName:eP(r,"appName"),appBundleId:o,...n?{visibility:n}:{},warnings:Array.isArray(r.warnings)?r.warnings.filter(e=>"string"==typeof e):void 0,identifiers:{session:a,appId:o,appBundleId:o}}},screenshot:async(e={})=>{let t=d(e),a=await i("screenshot",e.path?[e.path]:[],{...e,screenshotFullscreen:e.fullscreen});return{path:eM(a,"path"),overlayRefs:function(e){let t=e.overlayRefs;if(!Array.isArray(t))return;let a=[];for(let e of t){if(!eO(e))continue;let t=eP(e,"ref"),r=eT(e,"rect"),o=eT(e,"overlayRect"),n=function(e,t){let a=e[t];if(!eO(a))return;let r="number"==typeof a.x?a.x:void 0,o="number"==typeof a.y?a.y:void 0;if(void 0!==r&&void 0!==o)return{x:r,y:o}}(e,"center");t&&r&&o&&n&&a.push({ref:t,label:eP(e,"label"),rect:r,overlayRect:o,center:n})}return a}(a),identifiers:{session:t}}},diff:async e=>await l("diff",[e.kind],{...e,interactiveOnly:e.interactiveOnly,compact:e.compact,depth:e.depth,scope:e.scope,raw:e.raw})},interactions:{click:async e=>await l("click",ez(e),{...e,clickButton:e.button}),press:async e=>await l("press",ez(e),e),longPress:async e=>await l("longpress",[String(e.x),String(e.y),...eG(e.durationMs)],e),swipe:async e=>await l("swipe",[String(e.from.x),String(e.from.y),String(e.to.x),String(e.to.y),...eG(e.durationMs)],e),focus:async e=>await l("focus",[String(e.x),String(e.y)],e),type:async e=>await l("type",[e.text],e),fill:async e=>await l("fill",[...ez(e),e.text],e),scroll:async e=>await l("scroll",[e.direction,...eG(e.amount)],e),scrollIntoView:async e=>{var t;return await l("scrollintoview",void 0!==(t=e).ref?[t.ref,...eV(t.label)]:[t.text??""],e)},pinch:async e=>await l("pinch",[String(e.scale),...eG(e.x),...eG(e.y)],e),get:async e=>{var t;return await l("get",[e.format,...void 0!==(t=e).ref?[t.ref,...eV(t.label)]:[t.selector]],e)},is:async e=>await l("is",[e.predicate,e.selector,..."text"===e.predicate?[e.value]:[]],e),find:async e=>await l("find",function(e){let t=e.locator&&"any"!==e.locator?[e.locator,e.query]:[e.query];switch(e.action){case void 0:case"click":case"focus":case"exists":return e.action?[...t,e.action]:t;case"getText":return[...t,"get","text"];case"getAttrs":return[...t,"get","attrs"];case"wait":return[...t,"wait",...eG(e.timeoutMs)];case"fill":case"type":return[...t,e.action,e.value]}}(e),{...e,findFirst:e.first,findLast:e.last})},replay:{run:async e=>await l("replay",[e.path],{...e,replayUpdate:e.update}),test:async e=>await l("test",e.paths,{...e,replayUpdate:e.update})},batch:{run:async e=>await l("batch",[],{...e,batchSteps:e.steps,batchOnError:e.onError,batchMaxSteps:e.maxSteps})},observability:{perf:async(e={})=>await l("perf",[],e),logs:async(e={})=>{var t;return await l("logs",[(t=e).action??"path",...eV(t.message)],e)},network:async(e={})=>{var t;return await l("network",[...(t=e).action?[t.action]:[],...eG(t.limit)],{...e,networkInclude:e.include})}},recording:{record:async e=>await l("record",[e.action,...eV(e.path)],e),trace:async e=>await l("trace",[e.action,...eV(e.path)],e)},settings:{update:async e=>await l("settings",[e.setting,e.state,..."permission"in e?[e.permission]:[],..."mode"in e&&e.mode?[e.mode]:[]],e)}}}function ez(e){return void 0!==e.ref?[e.ref,...eV(e.label)]:void 0!==e.selector?[e.selector]:[String(e.x),String(e.y)]}function eV(e){return void 0===e?[]:[e]}function eG(e){return void 0===e?[]:[String(e)]}function eK(e,t,a){return a.remoteConfig&&a.remoteConfig!==e.remoteConfig?{...eH({...e,...a}),...e,...a}:{...t,...e,...a}}function eH(e){var t;if(!e.remoteConfig)return{};let{runtime:a,...r}=(t={remoteConfig:e.remoteConfig,cwd:e.cwd??process.cwd(),env:process.env}).remoteConfig?{...function(e){let t={};for(let a of eA){let r=e[a];void 0!==r&&(t[a]=r)}return t}(A({configPath:t.remoteConfig,cwd:t.cwd,env:t.env}).profile),remoteConfig:t.remoteConfig}:{};return r}export{AppError}from"./152.js";export{centerOfRect}from"./57.js";export{eB as createAgentDeviceClient};
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
export declare const ARCHIVE_EXTENSIONS: readonly [".zip", ".tar", ".tar.gz", ".tgz"];
|
|
2
|
+
|
|
3
|
+
export declare function isBlockedIpAddress(address: string): boolean;
|
|
4
|
+
|
|
5
|
+
export declare function isBlockedSourceHostname(hostname: string): boolean;
|
|
6
|
+
|
|
7
|
+
export declare function isTrustedInstallSourceUrl(sourceUrl: string | URL): boolean;
|
|
8
|
+
|
|
9
|
+
export declare type MaterializedInstallable = {
|
|
10
|
+
archivePath?: string;
|
|
11
|
+
installablePath: string;
|
|
12
|
+
cleanup: () => Promise<void>;
|
|
13
|
+
};
|
|
14
|
+
|
|
15
|
+
declare type MaterializeInstallableOptions = {
|
|
16
|
+
source: MaterializeInstallSource;
|
|
17
|
+
isInstallablePath: (candidatePath: string, stat: {
|
|
18
|
+
isFile(): boolean;
|
|
19
|
+
isDirectory(): boolean;
|
|
20
|
+
}) => boolean;
|
|
21
|
+
installableLabel: string;
|
|
22
|
+
allowArchiveExtraction?: boolean;
|
|
23
|
+
signal?: AbortSignal;
|
|
24
|
+
downloadTimeoutMs?: number;
|
|
25
|
+
};
|
|
26
|
+
|
|
27
|
+
export declare function materializeInstallablePath(options: MaterializeInstallableOptions): Promise<MaterializedInstallable>;
|
|
28
|
+
|
|
29
|
+
export declare type MaterializeInstallSource = {
|
|
30
|
+
kind: 'url';
|
|
31
|
+
url: string;
|
|
32
|
+
headers?: Record<string, string>;
|
|
33
|
+
} | {
|
|
34
|
+
kind: 'path';
|
|
35
|
+
path: string;
|
|
36
|
+
};
|
|
37
|
+
|
|
38
|
+
export declare function validateDownloadSourceUrl(parsedUrl: URL): Promise<void>;
|
|
39
|
+
|
|
40
|
+
export { }
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import t from"node:dns/promises";import e from"node:net";import{promises as a}from"node:fs";import r from"node:os";import o from"node:path";import{AppError as i}from"./152.js";import{runCmd as n}from"./818.js";import{expandUserHomePath as s}from"./267.js";let l=[".zip",".tar",".tar.gz",".tgz"],c=Object.freeze([...l]),h=function(t){if(!t)return 12e4;let e=Number(t);return Number.isFinite(e)?Math.max(1e3,Math.floor(e)):12e4}(process.env.AGENT_DEVICE_SOURCE_DOWNLOAD_TIMEOUT_MS),u=["1","true","yes","on"];async function d(t){let e=[];try{let a=await w(t.source,{signal:t.signal,downloadTimeoutMs:t.downloadTimeoutMs});e.push(a.cleanup);let r=await _(a.localPath,{archivePath:void 0,isInstallablePath:t.isInstallablePath,installableLabel:t.installableLabel,allowArchiveExtraction:!1!==t.allowArchiveExtraction,registerCleanup:t=>{e.push(t)}});return{archivePath:r.archivePath,installablePath:r.installablePath,cleanup:async()=>{await E(e)}}}catch(t){throw await E(e),t}}async function w(t,e){if("path"===t.kind)return{localPath:s(t.path),cleanup:async()=>{}};let i=await a.mkdtemp(o.join(r.tmpdir(),"agent-device-source-"));try{return{localPath:await p(i,t.url,t.headers,e),cleanup:async()=>{await a.rm(i,{recursive:!0,force:!0})}}}catch(t){throw await a.rm(i,{recursive:!0,force:!0}),t}}async function p(t,e,r,n){let s;try{s=new URL(e)}catch{throw new i("INVALID_ARGS",`Invalid source URL: ${e}`)}await f(s);let l=n?.signal;if(l?.aborted)throw new i("COMMAND_FAILED","request canceled",{reason:"request_canceled"});let c=new AbortController,u=()=>{c.abort(l?.reason)};l?.addEventListener("abort",u,{once:!0});let d=n?.downloadTimeoutMs??h,w=setTimeout(()=>{c.abort(Error("download timeout"))},d);try{let e=await fetch(s,{headers:r,redirect:"follow",signal:c.signal});if(!e.ok)throw new i("COMMAND_FAILED",`Failed to download app source: ${e.status} ${e.statusText}`,{status:e.status,statusText:e.statusText,url:s.toString()});let n=function(t,e){let a=t.headers.get("content-disposition"),r=a?.match(/filename\*?=(?:UTF-8'')?"?([^";]+)"?/i),i=r?.[1]?.trim();if(i)return o.basename(i);let n=o.basename(e.pathname);return n||"downloaded-artifact.bin"}(e,s),l=o.join(t,n),h=e.body;if(!h)throw new i("COMMAND_FAILED","Download response body was empty",{url:s.toString()});let u=await a.open(l,"w");try{for await(let t of h)await u.write(t)}finally{await u.close()}return l}catch(t){if(l?.aborted)throw new i("COMMAND_FAILED","request canceled",{reason:"request_canceled"},t);if(c.signal.aborted)throw new i("COMMAND_FAILED",`App source download timed out after ${d}ms`,{timeoutMs:d,url:s.toString()},t);throw t}finally{l?.removeEventListener("abort",u),clearTimeout(w)}}async function f(e){if("http:"!==e.protocol&&"https:"!==e.protocol)throw new i("INVALID_ARGS",`Unsupported source URL protocol: ${e.protocol}`);if(!u.includes((process.env.AGENT_DEVICE_ALLOW_PRIVATE_SOURCE_URLS??"").toLowerCase())){if(A(e.hostname.toLowerCase()))throw new i("INVALID_ARGS",`Source URL host is not allowed: ${e.hostname}`,{hint:"Use a public artifact URL, or set AGENT_DEVICE_ALLOW_PRIVATE_SOURCE_URLS=1 for trusted private-network daemons."});if((await t.lookup(e.hostname,{all:!0,verbatim:!0}).catch(()=>[])).some(t=>L(t.address)))throw new i("INVALID_ARGS",`Source URL host resolved to a private or loopback address: ${e.hostname}`,{hint:"Use a public artifact URL, or set AGENT_DEVICE_ALLOW_PRIVATE_SOURCE_URLS=1 for trusted private-network daemons."})}}function m(t){var e,a,r,o;let i=t instanceof URL?t:new URL(t),n=i.hostname.toLowerCase();if(!n)return!1;let s=i.pathname;return e=n,a=s,("api.github.com"===e?/^\/repos\/[^/]+\/[^/]+\/actions\/artifacts\/\d+\/zip$/i.test(a):"github.com"===e&&/^\/[^/]+\/[^/]+\/(?:actions\/runs\/\d+\/artifacts\/\d+|suites\/\d+\/artifacts\/\d+)$/i.test(a))||(r=n,o=s,("expo.dev"===r||!!r.endsWith(".expo.dev"))&&/^\/(?:artifacts\/eas\/|accounts\/[^/]+\/projects\/[^/]+\/builds\/)/i.test(o))}function A(t){return!!(!t||"localhost"===t||t.endsWith(".localhost"))||L(t)}function L(t){let a,r=e.isIP(t);return 4===r?function(t){let e=t.split(".").map(t=>Number.parseInt(t,10));if(4!==e.length||e.some(t=>Number.isNaN(t)||t<0||t>255))return!1;let[a,r]=e;return 10===a||127===a||169===a&&254===r||172===a&&!!(r>=16)&&!!(r<=31)||192===a&&168===r}(t):6===r&&!!("::1"===(a=t.toLowerCase())||a.startsWith("fc")||a.startsWith("fd")||a.startsWith("fe80:"))}async function _(t,e){let r=await a.stat(t).catch(()=>null);if(!r)throw new i("INVALID_ARGS",`App source not found: ${t}`);if(e.isInstallablePath(t,r))return{archivePath:e.archivePath,installablePath:t};if(r.isFile()&&v(t)){if(!e.allowArchiveExtraction)throw new i("INVALID_ARGS",`URL sources must point directly to a ${e.installableLabel}; archive extraction is not allowed`,{path:t});let a=await I(t);return e.registerCleanup(a.cleanup),await _(a.outputPath,{...e,archivePath:e.archivePath??t})}if(r.isDirectory()){let a=await b(t,e.isInstallablePath);if(1===a.length)return{archivePath:e.archivePath,installablePath:a[0]};if(a.length>1)throw new i("INVALID_ARGS",`Found multiple ${e.installableLabel} candidates under ${t}`,{matches:a});let r=await b(t,(t,e)=>e.isFile()&&v(t));if(1===r.length){if(!e.allowArchiveExtraction)throw new i("INVALID_ARGS",`URL sources must point directly to a ${e.installableLabel}; nested archives are not allowed`,{path:r[0]});let t=await I(r[0]);return e.registerCleanup(t.cleanup),await _(t.outputPath,{...e,archivePath:e.archivePath??r[0]})}if(r.length>1)throw new i("INVALID_ARGS",`Found multiple nested archives under ${t}; expected one ${e.installableLabel} source`,{matches:r})}throw new i("INVALID_ARGS",`Expected ${e.installableLabel} source, but got ${t}`)}async function b(t,e){let r=[],i=[{path:t,depth:0}];for(;i.length>0;){let t=i.shift();if(!t)continue;let n=await a.readdir(t.path,{withFileTypes:!0});for(let a of(n.sort((t,e)=>t.name.localeCompare(e.name)),n)){let n=o.join(t.path,a.name);if(e(n,a)){r.push(n);continue}a.isDirectory()&&t.depth<5&&i.push({path:n,depth:t.depth+1})}}return r}async function I(t){let e=await a.mkdtemp(o.join(r.tmpdir(),"agent-device-archive-"));try{return t.toLowerCase().endsWith(".zip")?await n("ditto",["-x","-k",t,e]):t.toLowerCase().endsWith(".tar.gz")||t.toLowerCase().endsWith(".tgz")?await n("tar",["-xzf",t,"-C",e]):await n("tar",["-xf",t,"-C",e]),{outputPath:e,cleanup:async()=>{await a.rm(e,{recursive:!0,force:!0})}}}catch(t){throw await a.rm(e,{recursive:!0,force:!0}),t}}function v(t){let e=t.toLowerCase();return l.some(t=>e.endsWith(t))}async function E(t){for(let e=t.length-1;e>=0;e-=1)await t[e]()}export{c as ARCHIVE_EXTENSIONS,L as isBlockedIpAddress,A as isBlockedSourceHostname,m as isTrustedInstallSourceUrl,d as materializeInstallablePath,f as validateDownloadSourceUrl};
|
package/dist/src/metro.d.ts
CHANGED
|
@@ -179,6 +179,12 @@ export declare type PrepareRemoteMetroResult = {
|
|
|
179
179
|
logPath: string;
|
|
180
180
|
};
|
|
181
181
|
|
|
182
|
+
export declare function resolveRuntimeTransport(runtime: SessionRuntimeHints | undefined): {
|
|
183
|
+
host: string;
|
|
184
|
+
port: number;
|
|
185
|
+
scheme: 'http' | 'https';
|
|
186
|
+
} | undefined;
|
|
187
|
+
|
|
182
188
|
declare type SessionRuntimeHints = {
|
|
183
189
|
platform?: 'ios' | 'android';
|
|
184
190
|
metroHost?: string;
|
package/dist/src/metro.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
import{buildMetroRuntimeHints as
|
|
1
|
+
import{URL as t}from"node:url";import"./818.js";import{AppError as e}from"./152.js";import"./164.js";import{buildMetroRuntimeHints as r,ensureMetroCompanion as o,stopMetroCompanion as n,prepareMetroRuntime as i}from"./974.js";function s(t){let e=t?.trim();return e&&e.length>0?e:void 0}function u(t){if(Number.isInteger(t)&&!(t<=0)&&!(t>65535))return t}function l(r){return function(r){if(!r)return;let o=s(r.metroHost),n=u(r.metroPort),i="http",l=s(r.bundleUrl);if(l){var a;let r;try{r=new t(l)}catch(t){throw new e("INVALID_ARGS",`Invalid runtime bundle URL: ${l}`,{},t)}("http:"===r.protocol||"https:"===r.protocol)&&(o??=s(r.hostname),n??=u(r.port.length>0?Number(r.port):"https:"===(a=r.protocol)?443:"http:"===a?80:void 0),i="https:"===r.protocol?"https":"http")}if(o&&n)return{host:o,port:n,scheme:i}}(r)}async function a(t){let e=await i({projectRoot:t.projectRoot,kind:t.kind,publicBaseUrl:t.publicBaseUrl,proxyBaseUrl:t.proxyBaseUrl,proxyBearerToken:t.proxyBearerToken,launchUrl:t.launchUrl,companionProfileKey:t.profileKey,companionConsumerKey:t.consumerKey,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,env:t.env});return{iosRuntime:e.iosRuntime,androidRuntime:e.androidRuntime,bridge:e.bridge,started:e.started,reused:e.reused,logPath:e.logPath}}async function p(t){let e=await o(t);return{pid:e.pid,started:e.spawned,logPath:e.logPath}}async function d(t){await n(t)}function m(t){return r(t,"ios")}function c(t){return r(t,"android")}export{buildBundleUrl,normalizeBaseUrl}from"./974.js";export{c as buildAndroidRuntimeHints,m as buildIosRuntimeHints,p as ensureMetroTunnel,a as prepareRemoteMetro,l as resolveRuntimeTransport,d as stopMetroTunnel};
|
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
declare type ApplePlatform = 'ios' | 'macos';
|
|
2
|
+
|
|
3
|
+
export declare function findSelectorChainMatch(nodes: SnapshotState['nodes'], chain: SelectorChain, options: {
|
|
4
|
+
platform: Platform;
|
|
5
|
+
requireRect?: boolean;
|
|
6
|
+
}): {
|
|
7
|
+
selectorIndex: number;
|
|
8
|
+
selector: Selector;
|
|
9
|
+
matches: number;
|
|
10
|
+
diagnostics: SelectorDiagnostics[];
|
|
11
|
+
} | null;
|
|
12
|
+
|
|
13
|
+
export declare function formatSelectorFailure(chain: SelectorChain, diagnostics: SelectorDiagnostics[], options: {
|
|
14
|
+
unique?: boolean;
|
|
15
|
+
}): string;
|
|
16
|
+
|
|
17
|
+
export declare function isNodeEditable(node: SnapshotNode, platform: Platform): boolean;
|
|
18
|
+
|
|
19
|
+
export declare function isNodeVisible(node: SnapshotNode): boolean;
|
|
20
|
+
|
|
21
|
+
export declare function isSelectorToken(token: string): boolean;
|
|
22
|
+
|
|
23
|
+
export declare function parseSelectorChain(expression: string): SelectorChain;
|
|
24
|
+
|
|
25
|
+
declare type Platform = ApplePlatform | 'android' | 'linux';
|
|
26
|
+
|
|
27
|
+
declare type RawSnapshotNode = {
|
|
28
|
+
index: number;
|
|
29
|
+
type?: string;
|
|
30
|
+
role?: string;
|
|
31
|
+
subrole?: string;
|
|
32
|
+
label?: string;
|
|
33
|
+
value?: string;
|
|
34
|
+
identifier?: string;
|
|
35
|
+
rect?: Rect;
|
|
36
|
+
enabled?: boolean;
|
|
37
|
+
selected?: boolean;
|
|
38
|
+
hittable?: boolean;
|
|
39
|
+
depth?: number;
|
|
40
|
+
parentIndex?: number;
|
|
41
|
+
pid?: number;
|
|
42
|
+
bundleId?: string;
|
|
43
|
+
appName?: string;
|
|
44
|
+
windowTitle?: string;
|
|
45
|
+
surface?: string;
|
|
46
|
+
hiddenContentAbove?: boolean;
|
|
47
|
+
hiddenContentBelow?: boolean;
|
|
48
|
+
};
|
|
49
|
+
|
|
50
|
+
declare type Rect = {
|
|
51
|
+
x: number;
|
|
52
|
+
y: number;
|
|
53
|
+
width: number;
|
|
54
|
+
height: number;
|
|
55
|
+
};
|
|
56
|
+
|
|
57
|
+
export declare function resolveSelectorChain(nodes: SnapshotState['nodes'], chain: SelectorChain, options: {
|
|
58
|
+
platform: Platform;
|
|
59
|
+
requireRect?: boolean;
|
|
60
|
+
requireUnique?: boolean;
|
|
61
|
+
disambiguateAmbiguous?: boolean;
|
|
62
|
+
}): SelectorResolution | null;
|
|
63
|
+
|
|
64
|
+
export declare type Selector = {
|
|
65
|
+
raw: string;
|
|
66
|
+
terms: SelectorTerm[];
|
|
67
|
+
};
|
|
68
|
+
|
|
69
|
+
export declare type SelectorChain = {
|
|
70
|
+
raw: string;
|
|
71
|
+
selectors: Selector[];
|
|
72
|
+
};
|
|
73
|
+
|
|
74
|
+
export declare type SelectorDiagnostics = {
|
|
75
|
+
selector: string;
|
|
76
|
+
matches: number;
|
|
77
|
+
};
|
|
78
|
+
|
|
79
|
+
declare type SelectorKey = 'id' | 'role' | 'text' | 'label' | 'value' | 'appname' | 'windowtitle' | 'visible' | 'hidden' | 'editable' | 'selected' | 'enabled' | 'hittable';
|
|
80
|
+
|
|
81
|
+
export declare type SelectorResolution = {
|
|
82
|
+
node: SnapshotNode;
|
|
83
|
+
selector: Selector;
|
|
84
|
+
selectorIndex: number;
|
|
85
|
+
matches: number;
|
|
86
|
+
diagnostics: SelectorDiagnostics[];
|
|
87
|
+
};
|
|
88
|
+
|
|
89
|
+
declare type SelectorTerm = {
|
|
90
|
+
key: SelectorKey;
|
|
91
|
+
value: string | boolean;
|
|
92
|
+
};
|
|
93
|
+
|
|
94
|
+
declare type SnapshotBackend = 'xctest' | 'android' | 'macos-helper' | 'linux-atspi';
|
|
95
|
+
|
|
96
|
+
declare type SnapshotNode = RawSnapshotNode & {
|
|
97
|
+
ref: string;
|
|
98
|
+
};
|
|
99
|
+
|
|
100
|
+
declare type SnapshotState = {
|
|
101
|
+
nodes: SnapshotNode[];
|
|
102
|
+
createdAt: number;
|
|
103
|
+
truncated?: boolean;
|
|
104
|
+
backend?: SnapshotBackend;
|
|
105
|
+
comparisonSafe?: boolean;
|
|
106
|
+
};
|
|
107
|
+
|
|
108
|
+
export declare function tryParseSelectorChain(expression: string): SelectorChain | null;
|
|
109
|
+
|
|
110
|
+
export { }
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export{findSelectorChainMatch,formatSelectorFailure,isNodeEditable,isNodeVisible,isSelectorToken,parseSelectorChain,resolveSelectorChain,tryParseSelectorChain}from"./940.js";
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "agent-device",
|
|
3
|
-
"version": "0.11.
|
|
3
|
+
"version": "0.11.16",
|
|
4
4
|
"description": "Unified control plane for physical and virtual devices via an agent-driven CLI.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"author": "Callstack",
|
|
@@ -12,6 +12,10 @@
|
|
|
12
12
|
"import": "./dist/src/index.js",
|
|
13
13
|
"types": "./dist/src/index.d.ts"
|
|
14
14
|
},
|
|
15
|
+
"./artifacts": {
|
|
16
|
+
"import": "./dist/src/artifacts.js",
|
|
17
|
+
"types": "./dist/src/artifacts.d.ts"
|
|
18
|
+
},
|
|
15
19
|
"./metro": {
|
|
16
20
|
"import": "./dist/src/metro.js",
|
|
17
21
|
"types": "./dist/src/metro.d.ts"
|
|
@@ -20,9 +24,21 @@
|
|
|
20
24
|
"import": "./dist/src/remote-config.js",
|
|
21
25
|
"types": "./dist/src/remote-config.d.ts"
|
|
22
26
|
},
|
|
27
|
+
"./install-source": {
|
|
28
|
+
"import": "./dist/src/install-source.js",
|
|
29
|
+
"types": "./dist/src/install-source.d.ts"
|
|
30
|
+
},
|
|
23
31
|
"./contracts": {
|
|
24
32
|
"import": "./dist/src/contracts.js",
|
|
25
33
|
"types": "./dist/src/contracts.d.ts"
|
|
34
|
+
},
|
|
35
|
+
"./selectors": {
|
|
36
|
+
"import": "./dist/src/selectors.js",
|
|
37
|
+
"types": "./dist/src/selectors.d.ts"
|
|
38
|
+
},
|
|
39
|
+
"./finders": {
|
|
40
|
+
"import": "./dist/src/finders.js",
|
|
41
|
+
"types": "./dist/src/finders.d.ts"
|
|
26
42
|
}
|
|
27
43
|
},
|
|
28
44
|
"engines": {
|