agent-device 0.11.16 → 0.12.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +2 -2
- package/dist/src/155.js +34 -34
- package/dist/src/818.js +1 -1
- package/dist/src/974.js +2 -2
- package/dist/src/bin.js +30 -31
- package/dist/src/daemon.js +15 -15
- package/dist/src/index.d.ts +9 -168
- package/dist/src/index.js +3 -3
- package/dist/src/metro.js +1 -1
- package/package.json +1 -17
- package/skills/agent-device/SKILL.md +1 -1
- package/skills/agent-device/references/exploration.md +19 -5
- package/skills/agent-device/references/macos-desktop.md +1 -0
- package/dist/src/164.js +0 -1
- package/dist/src/556.js +0 -1
- package/dist/src/940.js +0 -1
- package/dist/src/artifacts.d.ts +0 -3
- package/dist/src/artifacts.js +0 -1
- package/dist/src/finders.d.ts +0 -75
- package/dist/src/finders.js +0 -1
- package/dist/src/install-source.d.ts +0 -40
- package/dist/src/install-source.js +0 -1
- package/dist/src/selectors.d.ts +0 -110
- package/dist/src/selectors.js +0 -1
package/dist/src/index.d.ts
CHANGED
|
@@ -43,7 +43,6 @@ export declare type AgentDeviceClient = {
|
|
|
43
43
|
type: (options: TypeTextOptions) => Promise<CommandRequestResult>;
|
|
44
44
|
fill: (options: FillOptions) => Promise<CommandRequestResult>;
|
|
45
45
|
scroll: (options: ScrollOptions_2) => Promise<CommandRequestResult>;
|
|
46
|
-
scrollIntoView: (options: ScrollIntoViewOptions_2) => Promise<CommandRequestResult>;
|
|
47
46
|
pinch: (options: PinchOptions) => Promise<CommandRequestResult>;
|
|
48
47
|
get: (options: GetOptions) => Promise<CommandRequestResult>;
|
|
49
48
|
is: (options: IsOptions) => Promise<CommandRequestResult>;
|
|
@@ -307,13 +306,6 @@ export declare type BatchStep = {
|
|
|
307
306
|
flags?: Record<string, unknown>;
|
|
308
307
|
};
|
|
309
308
|
|
|
310
|
-
declare type BatchStep_2 = {
|
|
311
|
-
command: string;
|
|
312
|
-
positionals?: string[];
|
|
313
|
-
flags?: Partial<CommandFlags>;
|
|
314
|
-
runtime?: unknown;
|
|
315
|
-
};
|
|
316
|
-
|
|
317
309
|
export declare type CaptureDiffOptions = ClientCommandBaseOptions & Pick<CaptureSnapshotOptions, 'interactiveOnly' | 'compact' | 'depth' | 'scope' | 'raw'> & {
|
|
318
310
|
kind: 'snapshot';
|
|
319
311
|
out?: string;
|
|
@@ -357,110 +349,6 @@ export declare type ClickOptions = ClientCommandBaseOptions & SelectorSnapshotCo
|
|
|
357
349
|
|
|
358
350
|
declare type ClientCommandBaseOptions = AgentDeviceRequestOverrides & AgentDeviceSelectionOptions;
|
|
359
351
|
|
|
360
|
-
declare type CliFlags = {
|
|
361
|
-
json: boolean;
|
|
362
|
-
config?: string;
|
|
363
|
-
remoteConfig?: string;
|
|
364
|
-
stateDir?: string;
|
|
365
|
-
daemonBaseUrl?: string;
|
|
366
|
-
daemonAuthToken?: string;
|
|
367
|
-
daemonTransport?: 'auto' | 'socket' | 'http';
|
|
368
|
-
daemonServerMode?: 'socket' | 'http' | 'dual';
|
|
369
|
-
tenant?: string;
|
|
370
|
-
sessionIsolation?: 'none' | 'tenant';
|
|
371
|
-
runId?: string;
|
|
372
|
-
leaseId?: string;
|
|
373
|
-
sessionLock?: 'reject' | 'strip';
|
|
374
|
-
sessionLocked?: boolean;
|
|
375
|
-
sessionLockConflicts?: 'reject' | 'strip';
|
|
376
|
-
platform?: 'ios' | 'macos' | 'android' | 'linux' | 'apple';
|
|
377
|
-
target?: 'mobile' | 'tv' | 'desktop';
|
|
378
|
-
device?: string;
|
|
379
|
-
udid?: string;
|
|
380
|
-
serial?: string;
|
|
381
|
-
iosSimulatorDeviceSet?: string;
|
|
382
|
-
androidDeviceAllowlist?: string;
|
|
383
|
-
out?: string;
|
|
384
|
-
session?: string;
|
|
385
|
-
runtime?: string;
|
|
386
|
-
metroHost?: string;
|
|
387
|
-
metroPort?: number;
|
|
388
|
-
metroProjectRoot?: string;
|
|
389
|
-
metroKind?: 'auto' | 'react-native' | 'expo';
|
|
390
|
-
metroPublicBaseUrl?: string;
|
|
391
|
-
metroProxyBaseUrl?: string;
|
|
392
|
-
metroBearerToken?: string;
|
|
393
|
-
metroPreparePort?: number;
|
|
394
|
-
metroListenHost?: string;
|
|
395
|
-
metroStatusHost?: string;
|
|
396
|
-
metroStartupTimeoutMs?: number;
|
|
397
|
-
metroProbeTimeoutMs?: number;
|
|
398
|
-
metroRuntimeFile?: string;
|
|
399
|
-
metroNoReuseExisting?: boolean;
|
|
400
|
-
metroNoInstallDeps?: boolean;
|
|
401
|
-
bundleUrl?: string;
|
|
402
|
-
launchUrl?: string;
|
|
403
|
-
boot?: boolean;
|
|
404
|
-
reuseExisting?: boolean;
|
|
405
|
-
verbose?: boolean;
|
|
406
|
-
snapshotInteractiveOnly?: boolean;
|
|
407
|
-
snapshotDiff?: boolean;
|
|
408
|
-
snapshotCompact?: boolean;
|
|
409
|
-
snapshotDepth?: number;
|
|
410
|
-
snapshotScope?: string;
|
|
411
|
-
snapshotRaw?: boolean;
|
|
412
|
-
networkInclude?: 'summary' | 'headers' | 'body' | 'all';
|
|
413
|
-
overlayRefs?: boolean;
|
|
414
|
-
screenshotFullscreen?: boolean;
|
|
415
|
-
baseline?: string;
|
|
416
|
-
threshold?: string;
|
|
417
|
-
appsFilter?: 'user-installed' | 'all';
|
|
418
|
-
count?: number;
|
|
419
|
-
fps?: number;
|
|
420
|
-
hideTouches?: boolean;
|
|
421
|
-
intervalMs?: number;
|
|
422
|
-
delayMs?: number;
|
|
423
|
-
holdMs?: number;
|
|
424
|
-
jitterPx?: number;
|
|
425
|
-
pixels?: number;
|
|
426
|
-
doubleTap?: boolean;
|
|
427
|
-
clickButton?: 'primary' | 'secondary' | 'middle';
|
|
428
|
-
backMode?: 'in-app' | 'system';
|
|
429
|
-
pauseMs?: number;
|
|
430
|
-
pattern?: 'one-way' | 'ping-pong';
|
|
431
|
-
maxScrolls?: number;
|
|
432
|
-
activity?: string;
|
|
433
|
-
header?: string[];
|
|
434
|
-
saveScript?: boolean | string;
|
|
435
|
-
shutdown?: boolean;
|
|
436
|
-
relaunch?: boolean;
|
|
437
|
-
surface?: 'app' | 'frontmost-app' | 'desktop' | 'menubar';
|
|
438
|
-
headless?: boolean;
|
|
439
|
-
restart?: boolean;
|
|
440
|
-
noRecord?: boolean;
|
|
441
|
-
retainPaths?: boolean;
|
|
442
|
-
retentionMs?: number;
|
|
443
|
-
replayUpdate?: boolean;
|
|
444
|
-
failFast?: boolean;
|
|
445
|
-
timeoutMs?: number;
|
|
446
|
-
retries?: number;
|
|
447
|
-
artifactsDir?: string;
|
|
448
|
-
reportJunit?: string;
|
|
449
|
-
steps?: string;
|
|
450
|
-
stepsFile?: string;
|
|
451
|
-
findFirst?: boolean;
|
|
452
|
-
findLast?: boolean;
|
|
453
|
-
batchOnError?: 'stop';
|
|
454
|
-
batchMaxSteps?: number;
|
|
455
|
-
batchSteps?: Array<{
|
|
456
|
-
command: string;
|
|
457
|
-
positionals?: string[];
|
|
458
|
-
flags?: Record<string, unknown>;
|
|
459
|
-
}>;
|
|
460
|
-
help: boolean;
|
|
461
|
-
version: boolean;
|
|
462
|
-
};
|
|
463
|
-
|
|
464
352
|
export declare type ClipboardCommandOptions = (DeviceCommandBaseOptions & {
|
|
465
353
|
action: 'read';
|
|
466
354
|
}) | (DeviceCommandBaseOptions & {
|
|
@@ -480,10 +368,6 @@ declare type CommandActionResult<T extends string> = DaemonResponseData & {
|
|
|
480
368
|
action?: T;
|
|
481
369
|
};
|
|
482
370
|
|
|
483
|
-
declare type CommandFlags = Omit<CliFlags, 'json' | 'help' | 'version' | 'batchSteps'> & {
|
|
484
|
-
batchSteps?: BatchStep_2[];
|
|
485
|
-
};
|
|
486
|
-
|
|
487
371
|
export declare type CommandRequestResult = DaemonResponseData;
|
|
488
372
|
|
|
489
373
|
export declare function createAgentDeviceClient(config?: AgentDeviceClientConfig, deps?: {
|
|
@@ -507,9 +391,7 @@ declare type DaemonError = {
|
|
|
507
391
|
details?: Record<string, unknown>;
|
|
508
392
|
};
|
|
509
393
|
|
|
510
|
-
declare type DaemonInstallSource =
|
|
511
|
-
|
|
512
|
-
declare type DaemonInstallSource_2 = {
|
|
394
|
+
declare type DaemonInstallSource = {
|
|
513
395
|
kind: 'url';
|
|
514
396
|
url: string;
|
|
515
397
|
headers?: Record<string, string>;
|
|
@@ -520,20 +402,13 @@ declare type DaemonInstallSource_2 = {
|
|
|
520
402
|
|
|
521
403
|
declare type DaemonLockPolicy = 'reject' | 'strip';
|
|
522
404
|
|
|
523
|
-
declare type DaemonRequest =
|
|
524
|
-
token: string;
|
|
525
|
-
session: string;
|
|
526
|
-
flags?: CommandFlags;
|
|
527
|
-
meta?: DaemonRequestMeta_2;
|
|
528
|
-
};
|
|
529
|
-
|
|
530
|
-
declare type DaemonRequest_2 = {
|
|
405
|
+
declare type DaemonRequest = {
|
|
531
406
|
token?: string;
|
|
532
407
|
session?: string;
|
|
533
408
|
command: string;
|
|
534
409
|
positionals: string[];
|
|
535
410
|
flags?: Record<string, unknown>;
|
|
536
|
-
runtime?:
|
|
411
|
+
runtime?: SessionRuntimeHints;
|
|
537
412
|
meta?: DaemonRequestMeta;
|
|
538
413
|
};
|
|
539
414
|
|
|
@@ -549,7 +424,7 @@ declare type DaemonRequestMeta = {
|
|
|
549
424
|
sessionIsolation?: 'none' | 'tenant';
|
|
550
425
|
uploadedArtifactId?: string;
|
|
551
426
|
clientArtifactPaths?: Record<string, string>;
|
|
552
|
-
installSource?:
|
|
427
|
+
installSource?: DaemonInstallSource;
|
|
553
428
|
retainMaterializedPaths?: boolean;
|
|
554
429
|
materializedPathRetentionMs?: number;
|
|
555
430
|
materializationId?: string;
|
|
@@ -557,25 +432,15 @@ declare type DaemonRequestMeta = {
|
|
|
557
432
|
lockPlatform?: 'ios' | 'macos' | 'android' | 'linux' | 'apple';
|
|
558
433
|
};
|
|
559
434
|
|
|
560
|
-
declare type
|
|
561
|
-
installSource?: DaemonInstallSource;
|
|
562
|
-
lockPlatform?: PlatformSelector;
|
|
563
|
-
leaseBackend?: 'ios-simulator';
|
|
564
|
-
};
|
|
565
|
-
|
|
566
|
-
declare type DaemonResponse = DaemonResponse_2;
|
|
567
|
-
|
|
568
|
-
declare type DaemonResponse_2 = {
|
|
435
|
+
declare type DaemonResponse = {
|
|
569
436
|
ok: true;
|
|
570
|
-
data?:
|
|
437
|
+
data?: DaemonResponseData;
|
|
571
438
|
} | {
|
|
572
439
|
ok: false;
|
|
573
440
|
error: DaemonError;
|
|
574
441
|
};
|
|
575
442
|
|
|
576
|
-
declare type DaemonResponseData =
|
|
577
|
-
|
|
578
|
-
declare type DaemonResponseData_2 = Record<string, unknown> & {
|
|
443
|
+
declare type DaemonResponseData = Record<string, unknown> & {
|
|
579
444
|
artifacts?: DaemonArtifact[];
|
|
580
445
|
};
|
|
581
446
|
|
|
@@ -708,15 +573,6 @@ export declare type MaterializationReleaseResult = {
|
|
|
708
573
|
identifiers: AgentDeviceIdentifiers;
|
|
709
574
|
};
|
|
710
575
|
|
|
711
|
-
declare type MaterializeInstallSource = {
|
|
712
|
-
kind: 'url';
|
|
713
|
-
url: string;
|
|
714
|
-
headers?: Record<string, string>;
|
|
715
|
-
} | {
|
|
716
|
-
kind: 'path';
|
|
717
|
-
path: string;
|
|
718
|
-
};
|
|
719
|
-
|
|
720
576
|
declare type MetroBridgeResult = {
|
|
721
577
|
enabled: boolean;
|
|
722
578
|
baseUrl: string;
|
|
@@ -763,7 +619,7 @@ export declare type MetroPrepareOptions = {
|
|
|
763
619
|
export declare type MetroPrepareResult = PrepareMetroRuntimeResult;
|
|
764
620
|
|
|
765
621
|
/** Re-export of {@link SessionRuntimeHints} under the Metro-specific alias used by public API consumers. */
|
|
766
|
-
declare type MetroRuntimeHints =
|
|
622
|
+
declare type MetroRuntimeHints = SessionRuntimeHints;
|
|
767
623
|
|
|
768
624
|
export declare type NetworkOptions = AgentDeviceRequestOverrides & {
|
|
769
625
|
action?: 'dump' | 'log';
|
|
@@ -902,19 +758,6 @@ export declare type ScreenshotOverlayRef = {
|
|
|
902
758
|
center: Point;
|
|
903
759
|
};
|
|
904
760
|
|
|
905
|
-
declare type ScrollIntoViewOptions_2 = ClientCommandBaseOptions & ({
|
|
906
|
-
text: string;
|
|
907
|
-
ref?: never;
|
|
908
|
-
label?: never;
|
|
909
|
-
} | {
|
|
910
|
-
ref: string;
|
|
911
|
-
label?: string;
|
|
912
|
-
text?: never;
|
|
913
|
-
}) & {
|
|
914
|
-
maxScrolls?: number;
|
|
915
|
-
};
|
|
916
|
-
export { ScrollIntoViewOptions_2 as ScrollIntoViewOptions }
|
|
917
|
-
|
|
918
761
|
declare type ScrollOptions_2 = ClientCommandBaseOptions & {
|
|
919
762
|
direction: 'up' | 'down' | 'left' | 'right';
|
|
920
763
|
amount?: number;
|
|
@@ -940,9 +783,7 @@ export declare type SessionCloseResult = {
|
|
|
940
783
|
|
|
941
784
|
declare type SessionIsolationMode = 'none' | 'tenant';
|
|
942
785
|
|
|
943
|
-
declare type SessionRuntimeHints =
|
|
944
|
-
|
|
945
|
-
declare type SessionRuntimeHints_2 = {
|
|
786
|
+
declare type SessionRuntimeHints = {
|
|
946
787
|
platform?: 'ios' | 'android';
|
|
947
788
|
metroHost?: string;
|
|
948
789
|
metroPort?: number;
|
package/dist/src/index.js
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
import e from"node:net";import t from"node:http";import
|
|
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};
|
|
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{AsyncLocalStorage as i}from"node:async_hooks";import s,{createHash as l}from"node:crypto";import"node:os";import{spawn as c}from"node:child_process";import{redactDiagnosticData as d,AppError as u}from"./152.js";import{resolveUserPath as p,expandUserHomePath as m}from"./267.js";import{stopProcessForTakeover as f,prepareMetroRuntime as h,runCmdSync as w,isAgentDeviceDaemonProcess as y,runCmdDetached as v}from"./974.js";import{REMOTE_CONFIG_FIELD_SPECS as g,resolveRemoteConfigProfile as I,REMOTE_OPEN_PROFILE_KEYS as A}from"./924.js";function b(){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}let S=new i;function _(){return s.randomBytes(8).toString("hex")}function D(e){let t=S.getStore();if(!t)return;let r={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?d(e.data):void 0};if(t.events.push(r),!t.debug)return;let n=`[agent-device][diag] ${JSON.stringify(r)}
|
|
2
|
+
`;try{t.logPath&&a.appendFile(t.logPath,n,()=>{}),t.traceLogPath&&a.appendFile(t.traceLogPath,n,()=>{}),t.logPath||t.traceLogPath||process.stderr.write(n)}catch{}}async function M(e,t,r){let a=Date.now();try{let n=await t();return D({level:"info",phase:e,durationMs:Date.now()-a,data:r}),n}catch(t){throw D({level:"error",phase:e,durationMs:Date.now()-a,data:{...r??{},error:t instanceof Error?t.message:String(t)}}),t}}function P(e){let t,r=(t=(e??"").trim())?p(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 E="sha256";async function k(e){let{localPath:o,baseUrl:i,token:s}=e,l=a.statSync(o),d=l.isDirectory(),p=n.basename(o),m=d?"app-bundle":"file",f=i.endsWith("/")?i:`${i}/`,h=d?void 0:await T(o);if(h){let e=await N({normalizedBase:f,token:s,hash:h,filename:p,sizeBytes:l.size,artifactType:m});if(e)return e}let w=new URL("upload",f),y="https:"===w.protocol?r: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"]=E),s&&(v.authorization=`Bearer ${s}`,v["x-agent-device-token"]=s),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(i);try{let r=JSON.parse(a);if(!r.ok||!r.uploadId)return void t(new u("COMMAND_FAILED",`Upload failed: ${a}`));e(r.uploadId)}catch{t(new u("COMMAND_FAILED",`Invalid upload response: ${a}`))}})}),i=setTimeout(()=>{r.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(r.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))}),d){let e=c("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 u("COMMAND_FAILED","Failed to create tar archive for app bundle",{},e))}),e.on("close",e=>{0!==e&&(r.destroy(),t(new u("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 u("COMMAND_FAILED","Failed to read local artifact",{},e))})}})}async function N(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:E,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 T(e){let t=l(E);return await new Promise((r,n)=>{a.createReadStream(e).on("data",e=>t.update(e)).on("error",e=>{n(new u("COMMAND_FAILED","Failed to read local artifact",{},e))}).on("end",r)}),t.digest("hex")}let x=/(?:^|[^\w$.])(?:import|export)\s+(?:type\s+)?(?:[^'"`]*?\s+from\s+)?['"]([^'"]+)['"]/gm,R=/import\(\s*['"]([^'"]+)['"]\s*\)/gm,C=[".ts",".tsx",".js",".jsx",".mjs",".cjs"];function L(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 U(e){try{return a.statSync(e).isFile()?e:null}catch{return null}}let O=ey(),F=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}(),$=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}(),j=["xcodebuild .*AgentDeviceRunnerUITests/RunnerTests/testCommand","xcodebuild .*AgentDeviceRunner\\.env\\.session-","xcodebuild build-for-testing .*ios-runner/AgentDeviceRunner/AgentDeviceRunner\\.xcodeproj"],q=new e.BlockList;async function B(t){let r=t.meta?.requestId??_(),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 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,c=s;if(!(!l||"localhost"===(r=new URL(l).hostname.trim().toLowerCase().replace(/^\[(.*)\]$/,"$1"))||(e.isIPv4(r)?q.check(r,"ipv4"):!!e.isIPv6(r)&&q.check(r,"ipv6")))&&("string"!=typeof c||!(c.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 d=t.flags?.daemonTransport??process.env.AGENT_DEVICE_DAEMON_TRANSPORT,p="auto"===(a=(d??"").trim().toLowerCase())?"auto":"socket"===a?"socket":"http"===a?"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"===(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:P(o),transportPreference:p,serverMode:m,remoteBaseUrl:i,remoteAuthToken:s}}(t),o=function(e,t=process.env.AGENT_DEVICE_DAEMON_TIMEOUT_MS){if("test"!==e)return ey(t)}(t.command),i=await M("daemon_startup",async()=>await H(n),{requestId:r,session:t.session}),s=await G(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 D({level:"info",phase:"daemon_request_prepare",data:{requestId:r,command:t.command,session:t.session}}),await M("daemon_request",async()=>await ei(i,l,n.transportPreference,o),{requestId:r,command:t.command})}async function G(e,t){let r,o=[...e.positionals??[]],i=e.flags?{...e.flags}:void 0,s=e.meta?.installSource,l={};if(em(t)){let a=function(e,t){if("screenshot"===e.command){let r=z(e,"path",".png");return t[0]?{field:"path",localPath:r,positionalIndex:0,positionalPath:K("screenshot",".png")}:{field:"path",localPath:r,positionalIndex:0,flagPath:K("screenshot",".png")}}if("record"===e.command&&"start"===(t[0]??"").toLowerCase()){let t=z(e,"outPath",".mp4",1);return{field:"outPath",localPath:t,positionalIndex:1,positionalPath:K("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 V(e,t);c&&(s=c.installSource,r=c.uploadedArtifactId??r)}if(!em(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 k({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 V(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 k({localPath:i,baseUrl:t.baseUrl,token:t.token});return{installSource:{...r,path:i},uploadedArtifactId:s}}function z(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 K(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 H(e){let t;if(e.remoteBaseUrl){let t={transport:"http",token:e.remoteAuthToken??"",pid:0,baseUrl:e.remoteBaseUrl};if(await ea(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 r=Y(e.paths.infoPath),o=function(){try{let e=b();return JSON.parse(a.readFileSync(n.join(e,"package.json"),"utf8")).version??"0.0.0"}catch{return"0.0.0"}}(),i=function(e,t=b()){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 L(e,x,t),L(e,R,t),[...t]}(c)){let r=function(e,t){let r=n.resolve(n.dirname(e),t),a=U(r);if(a)return a;for(let e of C){let t=U(`${r}${e}`);if(t)return t}for(let e of C){let t=U(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=eo()).useSrc?t.srcPath:t.distPath,t.root),l=!!r&&await ea(r,e.transportPreference);if(r&&r.version===o&&r.codeSignature===i&&l)return r;r&&(r.version!==o||r.codeSignature!==i||!l)&&(await X(r),er(e.paths.infoPath)),function(e){let t=ee(e);if(!t.hasLock||t.hasInfo)return;let r=Z(e.lockPath);if(!r)return er(e.lockPath);y(r.pid,r.processStartTime)||er(e.lockPath)}(e.paths);let c=0;for(let t=1;t<=$;t+=1){await en(e);let r=await J(F,e);if(r)return r;if(await Q(e.paths)){c+=1;continue}let a=ee(e.paths);if(!(t<$))break;if(!a.hasInfo&&!a.hasLock){await W(150);continue}}let d=ee(e.paths);throw new u("COMMAND_FAILED","Failed to start daemon",{kind:"daemon_startup_failed",infoPath:e.paths.infoPath,lockPath:e.paths.lockPath,startupTimeoutMs:F,startupAttempts:$,lockRecoveryCount:c,metadataState:d,hint:function(e,t=P(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 J(e,t){let r=Date.now();for(;Date.now()-r<e;){let e=Y(t.paths.infoPath);if(e&&await ea(e,t.transportPreference))return e;await new Promise(e=>setTimeout(e,100))}return null}async function W(e){await new Promise(t=>setTimeout(t,e))}async function Q(e){let t=ee(e);if(!t.hasLock||t.hasInfo)return!1;let r=Z(e.lockPath);return r&&y(r.pid,r.processStartTime)&&await f(r.pid,{termTimeoutMs:3e3,killTimeoutMs:1e3,expectedStartTime:r.processStartTime}),er(e.lockPath),!0}async function X(e){await f(e.pid,{termTimeoutMs:3e3,killTimeoutMs:1e3,expectedStartTime:e.processStartTime})}function Y(e){let t=et(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 Z(e){let t=et(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}q.addSubnet("127.0.0.0",8,"ipv4"),q.addAddress("::1","ipv6"),q.addSubnet("::ffff:127.0.0.0",104,"ipv6");function ee(e){return{hasInfo:a.existsSync(e.infoPath),hasLock:a.existsSync(e.lockPath)}}function et(e){if(!a.existsSync(e))return null;try{return JSON.parse(a.readFileSync(e,"utf8"))}catch{return null}}function er(e){try{a.existsSync(e)&&a.unlinkSync(e)}catch{}}async function ea(a,n){var o;return"http"===es(a,n)?await function(e){let a=e.baseUrl?ef(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 en(e){let t=eo(),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};v(process.execPath,r,{env:a})}function eo(){let e=b(),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 u("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 ei(e,t,r,a){return"http"===es(e,r)?await ep(e,t,a):await eu(e,t,a)}function es(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 r=e,a=t;if(el(r,a))return a;throw new u("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=>el(e,t));if(n)return n;throw new u("COMMAND_FAILED","Daemon metadata has no reachable transport")}function el(e,t){return"http"===t?!!e.httpPort:!!e.port}function ec(e,t,r,a,n,o){let i=n?{terminated:0}:function(){let e=0;try{for(let t of j){let r=w("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{y(e.pid,e.processStartTime)&&(process.kill(e.pid,"SIGKILL"),r=!0)}catch{f(e.pid,{termTimeoutMs:3e3,killTimeoutMs:1e3,expectedStartTime:e.processStartTime})}finally{er(t.infoPath),er(t.lockPath)}return{forcedKill:r}}(e,t);return D({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 u("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 ed(e,t,r){return D({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: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 eu(t,r,a){let n=t.port;if(!n)throw new u("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)}
|
|
3
|
+
`)}),l=P(r.flags?.stateDir??process.env.AGENT_DEVICE_STATE_DIR),c="number"==typeof a?setTimeout(()=>{s.destroy(),i(ec(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 u("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(ed(e,r.meta?.requestId,!1))})})}async function ep(e,a,n){let o=e.baseUrl?new URL(ef(e.baseUrl,"rpc")):e.httpPort?new URL(`http://127.0.0.1:${e.httpPort}/rpc`):null;if(!o)throw new u("COMMAND_FAILED","Daemon HTTP endpoint is unavailable");let i=JSON.stringify({jsonrpc:"2.0",id:a.meta?.requestId??_(),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=P(a.flags?.stateDir??process.env.AGENT_DEVICE_STATE_DIR),p=("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",()=>{f&&clearTimeout(f);try{let t=JSON.parse(r);if(t.error){let e=t.error.data??{};c(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:a.meta?.requestId}));return}if(!t.result||"object"!=typeof t.result)return void c(new u("COMMAND_FAILED","Invalid daemon RPC response",{requestId:a.meta?.requestId}));if(e.baseUrl&&t.result.ok)return void eh(e,a,t.result).then(l).catch(c);l(t.result)}catch(e){f&&clearTimeout(f),c(new u("COMMAND_FAILED","Invalid daemon response",{requestId:a.meta?.requestId,line:r},e instanceof Error?e:void 0))}})}),m=em(e),f="number"==typeof n?setTimeout(()=>{p.destroy(),c(ec(e,d,a.meta?.requestId,a.command,m,n))},n):void 0;p.on("error",e=>{f&&clearTimeout(f),c(ed(e,a.meta?.requestId,m))}),p.write(i),p.end()})}function em(e){return"string"==typeof e.baseUrl&&e.baseUrl.length>0}function ef(e,t){return new URL(t,e.endsWith("/")?e:`${e}/`).toString()}async function eh(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 ew({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 ew(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??O,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 u("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 u("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 u("COMMAND_FAILED","Remote artifact download timed out",{artifactId:e.artifactId,requestId:e.requestId,timeoutMs:o}))},o);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:o},t instanceof Error?t:void 0))}),s.end()})}function ey(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 ev="clipboard",eg="wait",eI=new Set(["id","role","text","label","value","appname","windowtitle"]),eA=new Set(["visible","hidden","editable","selected","enabled","hittable"]),eb=new Set([...eI,...eA]);function eS(e){let t=e.trim();if(!t)throw new u("INVALID_ARGS","Empty selector term");let r=t.indexOf("=");if(-1===r){let r=t.toLowerCase();if(!eA.has(r))throw new u("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(!eb.has(a))throw new u("INVALID_ARGS",`Unknown selector key: ${a}`);if(!n)throw new u("INVALID_ARGS",`Missing selector value for key: ${a}`);if(eA.has(a)){let e,t="true"===(e=eD(n).toLowerCase())||"false"!==e&&null;if(null===t)throw new u("INVALID_ARGS",`Invalid boolean value for ${a}: ${n}`);return{key:a,value:t}}return{key:a,value:eD(n)}}function e_(e,t){return e?e===t?null:e:t}function eD(e){let t=e.trim();return t.startsWith('"')&&t.endsWith('"')||t.startsWith("'")&&t.endsWith("'")?t.slice(1,-1).replace(/\\(["'])/g,"$1"):t}function eM(e,t){let r=0;for(let a=t-1;a>=0&&"\\"===e[a];a-=1)r+=1;return r%2==1}let eP=g.map(e=>e.key);function eE(e){let t=e.appId??e.bundleId??e.packageName;return{session:e.session,appId:t,appBundleId:e.bundleId,package:e.packageName}}function ek(e,t,r){return{deviceId:t,deviceName:r,..."android"===e?{serial:t}:"ios"===e?{udid:t}:{}}}function eN(e,t,r,a){let n=r(e[t]);if(void 0===n)throw new u("COMMAND_FAILED",a,{response:e});return n}[...A];function eT(e,t){return eN(e,t,eO,`Daemon response is missing "${t}".`)}function ex(e,t){return eO(e[t])}function eR(e,t){var r;let a;return r=eO,null===(a=e[t])?null:r(a)}function eC(e,t){return eN(e,t,e$,`Daemon response has invalid "${t}".`)}function eL(e,t){return function(e){return"tv"===e||"mobile"===e||"desktop"===e?e:void 0}(e[t])??"mobile"}function eU(e,t){let r=e[t];if(!eB(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 eO(e){return"string"==typeof e&&e.length>0?e:void 0}function eF(e){return"number"==typeof e&&Number.isFinite(e)?e:void 0}function e$(e){return"ios"===e||"macos"===e||"android"===e?e:void 0}function ej(e){return"simulator"===e||"emulator"===e||"device"===e?e:void 0}function eq(e){if(!eB(e))throw new u("COMMAND_FAILED","Daemon returned an unexpected response shape.",{value:e});return e}function eB(e){return"object"==typeof e&&null!==e}function eG(e){let t={};for(let[r,a]of Object.entries(e))void 0!==a&&(t[r]=a);return t}function eV(e,t){let r=ex(e,"bundleId"),a=ex(e,"package");return{app:eT(e,"app"),appPath:eT(e,"appPath"),platform:eC(e,"platform"),appId:r??a,bundleId:r,package:a,identifiers:eE({session:t,bundleId:r,packageName:a})}}function ez(e){let t=eq(e),r=eC(t,"platform"),a=eT(t,"id"),n=eT(t,"name");return{platform:r,target:eL(t,"target"),kind:eN(t,"kind",ej,'Daemon response has invalid "kind".'),id:a,name:n,booted:"boolean"==typeof t.booted?t.booted:void 0,identifiers:ek(r,a,n),ios:"ios"===r?{udid:a}:void 0,android:"android"===r?{serial:a}:void 0}}function eK(e){let t=eq(e),r=eC(t,"platform"),a=eT(t,"id"),n=eT(t,"name"),o=eL(t,"target"),i=eT(t,"device"),s={session:n,...ek(r,a,i)};return{name:n,createdAt:eN(t,"createdAt",eF,'Daemon response is missing numeric "createdAt".'),device:{platform:r,target:o,id:a,name:i,identifiers:s,ios:"ios"===r?{udid:a,simulatorSetPath:eR(t,"ios_simulator_device_set")}:void 0,android:"android"===r?{serial:a}:void 0},identifiers:s}}function eH(e){return e??"default"}function eJ(e={},t={}){var r;let a,n=t.transport??B,o=eZ(e),i=async(t,r=[],a={})=>{let i=eY(e,o,a),s=await n({session:eH(i.session),command:t,positionals:r,flags:eG({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,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:eG({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(eK)},l=async(e,t=[],r={})=>await i(e,t,r),c=(t={})=>eH(eY(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 u("INVALID_ARGS","wait command requires exactly one of durationMs, text, ref, or selector.");if(void 0!==e.durationMs)return{command:eg,positionals:[String(e.durationMs)],options:e};let t=void 0!==e.timeoutMs?[String(e.timeoutMs)]:[];if(void 0!==e.text)return{command:eg,positionals:["text",e.text,...t],options:e};if(void 0!==e.ref)return{command:eg,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 u("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)&&!eM(e,n)){a=e_(a,o),r+=o;continue}if(!a&&"|"===o&&"|"===e[n+1]){let a=r.trim();if(!a)throw new u("INVALID_ARGS",`Invalid selector fallback expression: ${e}`);t.push(a),r="",n+=1;continue}r+=o}let n=r.trim();if(!n)throw new u("INVALID_ARGS",`Invalid selector fallback expression: ${e}`);return t.push(n),t}(t);if(0===r.length)throw new u("INVALID_ARGS","Selector expression cannot be empty");return{raw:t,selectors:r.map(e=>(function(e){let t=e.trim();if(!t)throw new u("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)&&!eM(e,n)){a=e_(a,o),r+=o;continue}if(!a&&/\s/.test(o)){r.trim()&&t.push(r.trim()),r="";continue}r+=o}if(a)throw new u("INVALID_ARGS",`Unclosed quote in selector: ${e}`);return r.trim()&&t.push(r.trim()),t}(t);if(0===r.length)throw new u("INVALID_ARGS",`Invalid selector segment: ${e}`);return{raw:t,terms:r.map(eS)}})(e))}}catch{return null}}(e))throw new u("INVALID_ARGS",`Invalid wait selector: ${e}`)}(r),{command:eg,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:ev,positionals:["read"],options:t}:{command:ev,positionals:["write",t.text],options:t})}}),devices:{list:async(e={})=>{let t=await i("devices",[],e);return(Array.isArray(t.devices)?t.devices:[]).map(ez)},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=eT(a,"udid"),o=eT(a,"device");return{udid:n,device:o,runtime:eT(a,"runtime"),created:!0===a.created,booted:!0===a.booted,iosSimulatorDeviceSet:eR(a,"ios_simulator_device_set"),identifiers:{deviceId:n,deviceName:o,udid:n}}}},apps:{install:async e=>eV(await i("install",[e.app,e.appPath],e),c(e)),reinstall:async e=>eV(await i("reinstall",[e.app,e.appPath],e),c(e)),installFromSource:async e=>(function(e,t){let r=ex(e,"bundleId"),a=ex(e,"packageName"),n=r??a??ex(e,"appId"),o=ex(e,"launchTarget")??a??r??n;if(!o)throw new u("COMMAND_FAILED",'Daemon response is missing "launchTarget".',{response:e});return{appName:ex(e,"appName"),appId:n,bundleId:r,packageName:a,launchTarget:o,installablePath:ex(e,"installablePath"),archivePath:ex(e,"archivePath"),materializationId:ex(e,"materializationId"),materializationExpiresAt:ex(e,"materializationExpiresAt"),identifiers:eE({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=ex(e,"id"),a=ex(e,"device");if("ios"!==t&&"macos"!==t&&"android"!==t||!r||!a)return;let n=eL(e,"target"),o=ek(t,r,a);return{platform:t,target:n,id:r,name:a,identifiers:o,ios:"ios"===t?{udid:ex(e,"device_udid")??r,simulatorSetPath:eR(e,"ios_simulator_device_set")}:void 0,android:"android"===t?{serial:ex(e,"serial")??r}:void 0}}(a),o=ex(a,"appBundleId");return{session:t,appName:ex(a,"appName"),appBundleId:o,appId:o,startup:function(e){if(eB(e)&&"number"==typeof e.durationMs&&"string"==typeof e.measuredAt&&"string"==typeof e.method)return{durationMs:e.durationMs,measuredAt:e.measuredAt,method:e.method,appTarget:ex(e,"appTarget"),appBundleId:ex(e,"appBundleId")}}(a.startup),runtime:function(e){if(!eB(e))return;let t=e.platform,r=ex(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:ex(e,"bundleUrl"),launchUrl:ex(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:eT(t,"materializationId"),identifiers:{}}}},metro:{prepare:async t=>await h({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=ex(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:ex(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:eT(r,"path"),overlayRefs:function(e){let t=e.overlayRefs;if(!Array.isArray(t))return;let r=[];for(let e of t){if(!eB(e))continue;let t=ex(e,"ref"),a=eU(e,"rect"),n=eU(e,"overlayRect"),o=function(e,t){let r=e[t];if(!eB(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:ex(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",eW(e),{...e,clickButton:e.button}),press:async e=>await l("press",eW(e),e),longPress:async e=>await l("longpress",[String(e.x),String(e.y),...eX(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),...eX(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",[...eW(e),e.text],e),scroll:async e=>await l("scroll",[e.direction,...eX(e.amount)],e),pinch:async e=>await l("pinch",[String(e.scale),...eX(e.x),...eX(e.y)],e),get:async e=>{var t;return await l("get",[e.format,...void 0!==(t=e).ref?[t.ref,...eQ(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",...eX(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",...eQ(t.message)],e)},network:async(e={})=>{var t;return await l("network",[...(t=e).action?[t.action]:[],...eX(t.limit)],{...e,networkInclude:e.include})}},recording:{record:async e=>await l("record",[e.action,...eQ(e.path)],e),trace:async e=>await l("trace",[e.action,...eQ(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 eW(e){return void 0!==e.ref?[e.ref,...eQ(e.label)]:void 0!==e.selector?[e.selector]:[String(e.x),String(e.y)]}function eQ(e){return void 0===e?[]:[e]}function eX(e){return void 0===e?[]:[String(e)]}function eY(e,t,r){return r.remoteConfig&&r.remoteConfig!==e.remoteConfig?{...eZ({...e,...r}),...e,...r}:{...t,...e,...r}}function eZ(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 eP){let a=e[r];void 0!==a&&(t[r]=a)}return t}(I({configPath:t.remoteConfig,cwd:t.cwd,env:t.env}).profile),remoteConfig:t.remoteConfig}:{};return a}export{AppError}from"./152.js";export{centerOfRect}from"./57.js";export{eJ as createAgentDeviceClient};
|
package/dist/src/metro.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
import{URL as t}from"node:url";import"
|
|
1
|
+
import{URL as t}from"node:url";import"node:fs";import"node:os";import e from"node:path";import{buildMetroRuntimeHints as o,ensureMetroCompanion as r,stopMetroCompanion as n,prepareMetroRuntime as i}from"./974.js";import{AppError as s}from"./152.js";function l(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 a(e){return function(e){if(!e)return;let o=l(e.metroHost),r=u(e.metroPort),n="http",i=l(e.bundleUrl);if(i){var a;let e;try{e=new t(i)}catch(t){throw new s("INVALID_ARGS",`Invalid runtime bundle URL: ${i}`,{},t)}("http:"===e.protocol||"https:"===e.protocol)&&(o??=l(e.hostname),r??=u(e.port.length>0?Number(e.port):"https:"===(a=e.protocol)?443:"http:"===a?80:void 0),n="https:"===e.protocol?"https":"http")}if(o&&r)return{host:o,port:r,scheme:n}}(e)}async function p(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 d(t){let e=await r(t);return{pid:e.pid,started:e.spawned,logPath:e.logPath}}async function m(t){await n(t)}function c(t){return o(t,"ios")}function h(t){return o(t,"android")}e.join("cmdline-tools","latest","bin"),e.join("cmdline-tools","tools","bin");export{buildBundleUrl,normalizeBaseUrl}from"./974.js";export{h as buildAndroidRuntimeHints,c as buildIosRuntimeHints,d as ensureMetroTunnel,p as prepareRemoteMetro,a as resolveRuntimeTransport,m as stopMetroTunnel};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "agent-device",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.12.0",
|
|
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,10 +12,6 @@
|
|
|
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
|
-
},
|
|
19
15
|
"./metro": {
|
|
20
16
|
"import": "./dist/src/metro.js",
|
|
21
17
|
"types": "./dist/src/metro.d.ts"
|
|
@@ -24,21 +20,9 @@
|
|
|
24
20
|
"import": "./dist/src/remote-config.js",
|
|
25
21
|
"types": "./dist/src/remote-config.d.ts"
|
|
26
22
|
},
|
|
27
|
-
"./install-source": {
|
|
28
|
-
"import": "./dist/src/install-source.js",
|
|
29
|
-
"types": "./dist/src/install-source.d.ts"
|
|
30
|
-
},
|
|
31
23
|
"./contracts": {
|
|
32
24
|
"import": "./dist/src/contracts.js",
|
|
33
25
|
"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"
|
|
42
26
|
}
|
|
43
27
|
},
|
|
44
28
|
"engines": {
|
|
@@ -18,7 +18,7 @@ Use this skill as a router with mandatory defaults. Read this file first. For no
|
|
|
18
18
|
- In React Native dev or debug builds, check early for visible warning or error overlays, tooltips, and toasts that can steal focus or intercept taps. If they are not part of the requested behavior, dismiss them and continue. If you saw them, report them in the final summary.
|
|
19
19
|
- Do not browse the web or use external sources unless the user explicitly asks.
|
|
20
20
|
- Re-snapshot after meaningful UI changes instead of reusing stale refs.
|
|
21
|
-
- Treat refs in default snapshot output as actionable-now, not durable identities. If a target
|
|
21
|
+
- Treat refs in default snapshot output as actionable-now, not durable identities. If a target appears only in an off-screen summary, use `scroll <direction>` and re-snapshot until the target is visible.
|
|
22
22
|
- Prefer `@ref` or selector targeting over raw coordinates.
|
|
23
23
|
- Ensure the correct target is pinned and an app session is open before interacting.
|
|
24
24
|
- Keep the loop short: `open` -> inspect/act -> verify if needed -> `close`.
|
|
@@ -38,7 +38,7 @@ Open this file when the app or screen is already running and you need to discove
|
|
|
38
38
|
- `press`
|
|
39
39
|
- `fill`
|
|
40
40
|
- `type`
|
|
41
|
-
- `
|
|
41
|
+
- `scroll`
|
|
42
42
|
- `wait`
|
|
43
43
|
- `keyboard dismiss` when the keyboard obscures the next target
|
|
44
44
|
|
|
@@ -115,10 +115,10 @@ App: com.apple.Preferences
|
|
|
115
115
|
## Refs vs selectors
|
|
116
116
|
|
|
117
117
|
- Use refs for discovery, debugging, and short local loops.
|
|
118
|
-
-
|
|
119
|
-
-
|
|
118
|
+
- When a target appears only in a visible-first off-screen summary, such as `[off-screen below] ... "Battery"`, use `scroll down` and then `snapshot -i`. For `[off-screen above]`, use `scroll up` and then `snapshot -i`.
|
|
119
|
+
- For more than two repeated scroll checks, create a short shell loop instead of issuing each command by hand. Stop when the label appears or the snapshot stops changing.
|
|
120
120
|
- Visible-first off-screen summaries are intentionally compact. If you need the full off-screen tree instead of a short summary, retry with `snapshot --raw`.
|
|
121
|
-
- Cap long searches
|
|
121
|
+
- Cap long searches in the loop when the list may be unbounded or the target may not exist.
|
|
122
122
|
- Use selectors for deterministic scripts, assertions, and replay-friendly actions.
|
|
123
123
|
- Prefer selector or `@ref` targeting over raw coordinates.
|
|
124
124
|
- For tap interactions, `press` is canonical and `click` is an equivalent alias.
|
|
@@ -132,11 +132,25 @@ agent-device press 'id="camera_row" || label="Camera" role=button'
|
|
|
132
132
|
agent-device is visible 'id="camera_settings_anchor"'
|
|
133
133
|
```
|
|
134
134
|
|
|
135
|
+
Example loop:
|
|
136
|
+
|
|
137
|
+
```bash
|
|
138
|
+
previous=''
|
|
139
|
+
for _ in 1 2 3 4 5 6; do
|
|
140
|
+
current="$(agent-device snapshot -i)"
|
|
141
|
+
printf '%s\n' "$current"
|
|
142
|
+
printf '%s\n' "$current" | grep -q 'Battery' && break
|
|
143
|
+
[ "$current" = "$previous" ] && break
|
|
144
|
+
previous="$current"
|
|
145
|
+
agent-device scroll down 0.5 >/dev/null
|
|
146
|
+
done
|
|
147
|
+
```
|
|
148
|
+
|
|
135
149
|
## Interaction fallbacks
|
|
136
150
|
|
|
137
151
|
When `press @ref` fails:
|
|
138
152
|
|
|
139
|
-
1. If the error says the ref is off-screen,
|
|
153
|
+
1. If the error says the ref is off-screen, use the off-screen summary direction to run `scroll <direction>`, then take a fresh `snapshot -i`.
|
|
140
154
|
2. Re-snapshot if the UI may have changed.
|
|
141
155
|
3. Retry `press @ref` or a selector-based `press`.
|
|
142
156
|
4. If `screenshot --overlay-refs --json` returned a reliable `overlayRefs[].center`, use `agent-device press <x> <y>`.
|
|
@@ -85,3 +85,4 @@ Troubleshooting:
|
|
|
85
85
|
- If `menubar` is missing the expected menu, retry with `open <app> --platform macos --surface menubar` for menu bar apps, or make the app frontmost first and retry the generic menubar surface.
|
|
86
86
|
- If the wrong menu opened, retry secondary-clicking the row or cell wrapper rather than the nested text node.
|
|
87
87
|
- If the app has multiple windows, make the correct window frontmost before relying on refs.
|
|
88
|
+
- If overriding the local helper, set `AGENT_DEVICE_MACOS_HELPER_BIN` to an absolute executable path; relative helper paths are rejected.
|
package/dist/src/164.js
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
import"node:fs";import o from"node:os";import t from"node:path";function e(n=process.env){let r=n.ANDROID_SDK_ROOT?.trim(),i=n.ANDROID_HOME?.trim(),d=n.HOME?.trim()||o.homedir();return function(o){let t=new Set,e=[];for(let n of o){let o=n.trim();!o||t.has(o)||(t.add(o),e.push(o))}return e}([r??"",i??"",d?t.join(d,"Android","Sdk"):""])}t.join("cmdline-tools","latest","bin"),t.join("cmdline-tools","tools","bin");export{e as resolveAndroidSdkRoots};
|
package/dist/src/556.js
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
import{AppError as e}from"./152.js";function t(e,l,o,u={}){let c=i(o);if(!c)return{matches:[],score:0};let a=0,s=[];for(let t of e){if(u.requireRect&&!t.rect)continue;let e=function(e,t,i){switch(t){case"role":return function(e,t){let r=n(e??"");return r?r===t?2:+!!r.includes(t):0}(e.type,i);case"label":return r(e.label,i);case"value":return r(e.value,i);case"id":return r(e.identifier,i);default:return Math.max(r(e.label,i),r(e.value,i),r(e.identifier,i))}}(t,l,c);if(!(e<=0)){if(e>a){a=e,s.length=0,s.push(t);continue}e===a&&s.push(t)}}return{matches:s,score:a}}function r(e,t){let r=i(e??"");return r?r===t?2:+!!r.includes(t):0}function i(e){return e.trim().toLowerCase().replace(/\s+/g," ")}function n(e){let t=e.trim();return t?t=(t.split(".").pop()??t).replace(/XCUIElementType/gi,"").toLowerCase():""}function l(t){let r="any",i=0;["text","label","value","role","id"].includes(t[0])&&(r=t[0],i=1);let n=t[i]??"",l=t.slice(i+1);if(0===l.length)return{locator:r,query:n,action:"click"};let o=l[0].toLowerCase();if("get"===o){let t=l[1]?.toLowerCase();if("text"===t)return{locator:r,query:n,action:"get_text"};if("attrs"===t)return{locator:r,query:n,action:"get_attrs"};throw new e("INVALID_ARGS","find get only supports text or attrs")}if("wait"===o)return{locator:r,query:n,action:"wait",timeoutMs:function(e){if(!e)return null;let t=Number(e);return Number.isFinite(t)?t:null}(l[1])??void 0};if("exists"===o)return{locator:r,query:n,action:"exists"};if("click"===o)return{locator:r,query:n,action:"click"};if("focus"===o)return{locator:r,query:n,action:"focus"};if("fill"===o)return{locator:r,query:n,action:"fill",value:l.slice(1).join(" ")};if("type"===o)return{locator:r,query:n,action:"type",value:l.slice(1).join(" ")};throw new e("INVALID_ARGS",`Unsupported find action: ${l[0]}`)}export{t as findBestMatchesByLocator,n as normalizeRole,i as normalizeText,l as parseFindArgs};
|
package/dist/src/940.js
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
import{AppError as e}from"./152.js";import{normalizeText as t}from"./556.js";let r=new Set(["id","role","text","label","value","appname","windowtitle"]),n=new Set(["visible","hidden","editable","selected","enabled","hittable"]),l=new Set([...r,...n]);function i(t){let r=t.trim();if(!r)throw new e("INVALID_ARGS","Selector expression cannot be empty");let n=function(t){let r=[],n="",l=null;for(let i=0;i<t.length;i+=1){let u=t[i];if(('"'===u||"'"===u)&&!f(t,i)){l=c(l,u),n+=u;continue}if(!l&&"|"===u&&"|"===t[i+1]){let l=n.trim();if(!l)throw new e("INVALID_ARGS",`Invalid selector fallback expression: ${t}`);r.push(l),n="",i+=1;continue}n+=u}let i=n.trim();if(!i)throw new e("INVALID_ARGS",`Invalid selector fallback expression: ${t}`);return r.push(i),r}(r);if(0===n.length)throw new e("INVALID_ARGS","Selector expression cannot be empty");return{raw:r,selectors:n.map(t=>(function(t){let r=t.trim();if(!r)throw new e("INVALID_ARGS","Selector segment cannot be empty");let n=function(t){let r=[],n="",l=null;for(let e=0;e<t.length;e+=1){let i=t[e];if(('"'===i||"'"===i)&&!f(t,e)){l=c(l,i),n+=i;continue}if(!l&&/\s/.test(i)){n.trim()&&r.push(n.trim()),n="";continue}n+=i}if(l)throw new e("INVALID_ARGS",`Unclosed quote in selector: ${t}`);return n.trim()&&r.push(n.trim()),r}(r);if(0===n.length)throw new e("INVALID_ARGS",`Invalid selector segment: ${t}`);return{raw:r,terms:n.map(a)}})(t))}}function u(e){try{return i(e)}catch{return null}}function o(e){let t=e.trim();if(!t)return!1;if("||"===t)return!0;let r=t.indexOf("=");if(-1!==r){let e=t.slice(0,r).trim().toLowerCase();return l.has(e)}return l.has(t.toLowerCase())}function a(t){let r=t.trim();if(!r)throw new e("INVALID_ARGS","Empty selector term");let i=r.indexOf("=");if(-1===i){let l=r.toLowerCase();if(!n.has(l))throw new e("INVALID_ARGS",`Invalid selector term "${t}", expected key=value`);return{key:l,value:!0}}let u=r.slice(0,i).trim().toLowerCase(),o=r.slice(i+1).trim();if(!l.has(u))throw new e("INVALID_ARGS",`Unknown selector key: ${u}`);if(!o)throw new e("INVALID_ARGS",`Missing selector value for key: ${u}`);if(n.has(u)){let t,r="true"===(t=s(o).toLowerCase())||"false"!==t&&null;if(null===r)throw new e("INVALID_ARGS",`Invalid boolean value for ${u}: ${o}`);return{key:u,value:r}}return{key:u,value:s(o)}}function c(e,t){return e?e===t?null:e:t}function s(e){let t=e.trim();return t.startsWith('"')&&t.endsWith('"')||t.startsWith("'")&&t.endsWith("'")?t.slice(1,-1).replace(/\\(["'])/g,"$1"):t}function f(e,t){let r=0;for(let n=t-1;n>=0&&"\\"===e[n];n-=1)r+=1;return r%2==1}function d(e){let t=e.trim().replace(/XCUIElementType/gi,"");t.startsWith("AX")&&(t=t.slice(2));let r=Math.max((t=t.toLowerCase()).lastIndexOf("."),t.lastIndexOf("/"));return -1!==r&&(t=t.slice(r+1)),t}function h(e,t,r){return t.terms.every(t=>(function(e,t,r){switch(t.key){case"id":return p(e.identifier,String(t.value));case"role":return p(d(e.type??""),String(t.value));case"label":return p(e.label,String(t.value));case"value":return p(e.value,String(t.value));case"text":return p([e.label,e.value,e.identifier].map(e=>"string"==typeof e?e.trim():"").filter(e=>e.length>0)[0]??"",String(t.value));case"appname":return p(e.appName,String(t.value));case"windowtitle":return p(e.windowTitle,String(t.value));case"visible":return m(e)===!!t.value;case"hidden":return!m(e)==!!t.value;case"editable":return w(e,r)===!!t.value;case"selected":return!0===e.selected==!!t.value;case"enabled":return!1!==e.enabled==!!t.value;case"hittable":return!0===e.hittable==!!t.value;default:return!1}})(e,t,r))}function m(e){return!0===e.hittable||!!e.rect&&e.rect.width>0&&e.rect.height>0}function w(e,t){var r;let n;return r=e.type??"",(!(n=d(r))||("android"===t?n.includes("edittext")||n.includes("autocompletetextview"):n.includes("textfield")||n.includes("securetextfield")||n.includes("searchfield")||n.includes("textview")||n.includes("textarea")||"search"===n))&&!1!==e.enabled}function p(e,r){return t(e??"")===t(r)}function S(e,t,r){let n=r.requireRect??!1,l=r.requireUnique??!0,i=[];for(let u=0;u<t.selectors.length;u+=1){let o=t.selectors[u],a=function(e,t,r,n){let l=0,i=null,u=null,o=!1;for(let a of e){if(n&&!a.rect||!h(a,t,r))continue;if(l+=1,i??=a,!u){u=a;continue}let e=function(e,t){let r=e.depth??0,n=t.depth??0;if(r!==n)return r>n?1:-1;let l=b(e),i=b(t);return l!==i?l<i?1:-1:0}(a,u);e>0?(u=a,o=!1):0===e&&(o=!0)}return{count:l,firstNode:i,disambiguated:o?null:u}}(e,o,r.platform,n);if(i.push({selector:o.raw,matches:a.count}),0!==a.count&&a.firstNode){if(l&&1!==a.count){if(!r.disambiguateAmbiguous||!a.disambiguated)continue;return{node:a.disambiguated,selector:o,selectorIndex:u,matches:a.count,diagnostics:i}}return{node:a.firstNode,selector:o,selectorIndex:u,matches:a.count,diagnostics:i}}}return null}function v(e,t,r){let n=r.requireRect??!1,l=[];for(let i=0;i<t.selectors.length;i+=1){let u=t.selectors[i],o=function(e,t,r,n){let l=0;for(let i of e)(!n||i.rect)&&h(i,t,r)&&(l+=1);return l}(e,u,r.platform,n);if(l.push({selector:u.raw,matches:o}),o>0)return{selectorIndex:i,selector:u,matches:o,diagnostics:l}}return null}function I(e,t,r){if(0===t.length)return`Selector did not match: ${e.raw}`;let n=t.map(e=>`${e.selector} -> ${e.matches}`).join(", ");return r.unique??!0?`Selector did not resolve uniquely (${n})`:`Selector did not match (${n})`}function b(e){return e.rect?e.rect.width*e.rect.height:1/0}export{v as findSelectorChainMatch,I as formatSelectorFailure,w as isNodeEditable,o as isSelectorToken,i as parseSelectorChain,S as resolveSelectorChain,m as isNodeVisible,u as tryParseSelectorChain};
|