agent-device 0.20.5 → 0.20.6
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 -0
- package/android/ime-helper/dist/{agent-device-android-ime-helper-0.20.5.apk → agent-device-android-ime-helper-0.20.6.apk} +0 -0
- package/android/ime-helper/dist/agent-device-android-ime-helper-0.20.6.apk.sha256 +1 -0
- package/android/ime-helper/dist/{agent-device-android-ime-helper-0.20.5.manifest.json → agent-device-android-ime-helper-0.20.6.manifest.json} +4 -4
- package/android/snapshot-helper/dist/{agent-device-android-snapshot-helper-0.20.5.apk → agent-device-android-snapshot-helper-0.20.6.apk} +0 -0
- package/android/snapshot-helper/dist/agent-device-android-snapshot-helper-0.20.6.apk.sha256 +1 -0
- package/android/snapshot-helper/dist/{agent-device-android-snapshot-helper-0.20.5.manifest.json → agent-device-android-snapshot-helper-0.20.6.manifest.json} +6 -6
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunner/AgentDeviceRunnerApp.m +28 -0
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/AgentDeviceRunnerUITests-Bridging-Header.h +1 -0
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerAXSnapshotBridge.h +41 -1
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerAXSnapshotBridge.m +298 -92
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerSynthesizedGesture.m +126 -187
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerSynthesizedTextEntry.h +32 -0
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerSynthesizedTextEntry.m +212 -0
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+AXSnapshotFallback.swift +118 -8
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+CommandExecution.swift +134 -27
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+Keyboard.swift +23 -5
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+Lifecycle.swift +10 -0
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+LifecycleCacheTests.swift +0 -67
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+Models.swift +11 -1
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+ScreenRecorder.swift +2 -22
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+SnapshotCapturePlan.swift +48 -11
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+SnapshotTraversalIdentityTests.swift +0 -20
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+SynthesizedTextEntry.swift +177 -0
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+TextEntry.swift +105 -448
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+TextEntryPolicyTests.swift +4 -0
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+TextTyping.swift +587 -0
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests.swift +18 -0
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerXCTestEventBridge.h +72 -0
- package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerXCTestEventBridge.m +89 -0
- package/dist/src/agent-device-client.js +2 -2
- package/dist/src/android.js +1 -1
- package/dist/src/app-log-request-scope.js +1 -1
- package/dist/src/app-resolution.js +1 -1
- package/dist/src/apps.js +5 -5
- package/dist/src/cli-config.js +1 -1
- package/dist/src/cli-help.js +34 -24
- package/dist/src/cli-runner.js +1 -1
- package/dist/src/cli.js +15 -15
- package/dist/src/command-metadata.js +1 -1
- package/dist/src/command-schema.js +3 -3
- package/dist/src/context.js +1 -1
- package/dist/src/debug-symbols.js +1 -1
- package/dist/src/find.js +1 -1
- package/dist/src/finders.js +1 -1
- package/dist/src/generic-settle.js +1 -0
- package/dist/src/generic.js +1 -1
- package/dist/src/ime-lifecycle.js +3 -3
- package/dist/src/index.d.ts +27 -7
- package/dist/src/input-actions.js +4 -4
- package/dist/src/interaction-runtime.js +1 -0
- package/dist/src/interaction-snapshot.js +1 -1
- package/dist/src/interaction-touch-reference-frame.js +1 -0
- package/dist/src/interaction.js +1 -1
- package/dist/src/interactor.js +2 -2
- package/dist/src/interactor2.js +1 -1
- package/dist/src/internal/bin.js +2 -2
- package/dist/src/internal/daemon.js +15 -15
- package/dist/src/lease-context.js +1 -1
- package/dist/src/lease.js +1 -1
- package/dist/src/limrun.d.ts +23 -2
- package/dist/src/linux.js +1 -1
- package/dist/src/process-exit.js +1 -0
- package/dist/src/react-native.js +1 -1
- package/dist/src/record-trace.js +1 -1
- package/dist/src/register-builtins.js +1 -1
- package/dist/src/registry.js +25 -24
- package/dist/src/remote-config.js +1 -1
- package/dist/src/remote-config2.js +1 -1
- package/dist/src/reporting.js +5 -5
- package/dist/src/runner-client.js +1 -1
- package/dist/src/runner-disposal.js +1 -1
- package/dist/src/runner-lease.js +1 -1
- package/dist/src/runtime.js +3 -3
- package/dist/src/screenshot-geometry.js +1 -1
- package/dist/src/screenshot-result.js +4 -4
- package/dist/src/sdk-android-adb.d.ts +20 -2
- package/dist/src/sdk-android-adb.js +1 -1
- package/dist/src/sdk-batch-runner.js +3 -3
- package/dist/src/sdk-contracts.d.ts +17 -2
- package/dist/src/sdk-finders.d.ts +4 -20
- package/dist/src/sdk-finders.js +1 -1
- package/dist/src/{interaction.d.ts → sdk-selectors.d.ts} +98 -3
- package/dist/src/sdk-selectors.js +1 -1
- package/dist/src/selector-runtime.js +1 -1
- package/dist/src/selector-vocabulary.js +1 -1
- package/dist/src/selectors.d.ts +1 -46
- package/dist/src/selectors.js +1 -1
- package/dist/src/server.js +3 -3
- package/dist/src/session-target-evidence.js +1 -1
- package/dist/src/session.js +9 -9
- package/dist/src/snapshot2.js +1 -1
- package/dist/src/text-surface.js +1 -0
- package/dist/src/viewport-dimension.js +13 -12
- package/dist/src/web.js +1 -1
- package/package.json +41 -35
- package/server.json +3 -3
- package/android/ime-helper/dist/agent-device-android-ime-helper-0.20.5.apk.sha256 +0 -1
- package/android/snapshot-helper/dist/agent-device-android-snapshot-helper-0.20.5.apk.sha256 +0 -1
- package/dist/apple/runner/AgentDeviceRunner/RecordingScripts/recording-resize.swift +0 -225
package/dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerXCTestEventBridge.m
ADDED
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
#import "RunnerXCTestEventBridge.h"
|
|
2
|
+
|
|
3
|
+
NSString * _Nullable RunnerResolveXCTestEventBridge(
|
|
4
|
+
id application,
|
|
5
|
+
NSString *surface,
|
|
6
|
+
RunnerXCTestEventBridge *bridge
|
|
7
|
+
) {
|
|
8
|
+
Class recordClass = NSClassFromString(@"XCSynthesizedEventRecord");
|
|
9
|
+
Class pathClass = NSClassFromString(@"XCPointerEventPath");
|
|
10
|
+
SEL addPathSelector = NSSelectorFromString(@"addPointerEventPath:");
|
|
11
|
+
SEL setTargetProcessIDSelector = NSSelectorFromString(@"setTargetProcessID:");
|
|
12
|
+
SEL synthesizeSelector = NSSelectorFromString(@"synthesizeWithError:");
|
|
13
|
+
SEL processIDSelector = NSSelectorFromString(@"processID");
|
|
14
|
+
|
|
15
|
+
NSString *missing = RunnerRequireClass(recordClass, @"XCSynthesizedEventRecord", surface);
|
|
16
|
+
if (missing != nil) return missing;
|
|
17
|
+
missing = RunnerRequireClass(pathClass, @"XCPointerEventPath", surface);
|
|
18
|
+
if (missing != nil) return missing;
|
|
19
|
+
missing = RunnerRequireSelector(recordClass, addPathSelector, @"addPointerEventPath:", surface);
|
|
20
|
+
if (missing != nil) return missing;
|
|
21
|
+
missing = RunnerRequireSelector(
|
|
22
|
+
recordClass, setTargetProcessIDSelector, @"setTargetProcessID:", surface
|
|
23
|
+
);
|
|
24
|
+
if (missing != nil) return missing;
|
|
25
|
+
missing = RunnerRequireSelector(recordClass, synthesizeSelector, @"synthesizeWithError:", surface);
|
|
26
|
+
if (missing != nil) return missing;
|
|
27
|
+
missing = RunnerRequireApplicationSelector(application, processIDSelector, @"processID", surface);
|
|
28
|
+
if (missing != nil) return missing;
|
|
29
|
+
|
|
30
|
+
*bridge = (RunnerXCTestEventBridge){
|
|
31
|
+
.recordClass = recordClass,
|
|
32
|
+
.pathClass = pathClass,
|
|
33
|
+
.addPathSelector = addPathSelector,
|
|
34
|
+
.setTargetProcessIDSelector = setTargetProcessIDSelector,
|
|
35
|
+
.synthesizeSelector = synthesizeSelector,
|
|
36
|
+
.processIDSelector = processIDSelector,
|
|
37
|
+
};
|
|
38
|
+
return nil;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
NSString * _Nullable RunnerRequireClass(Class cls, NSString *className, NSString *surface) {
|
|
42
|
+
if (cls == Nil) {
|
|
43
|
+
return [NSString stringWithFormat:
|
|
44
|
+
@"private XCTest %@ synthesis unavailable: missing %@",
|
|
45
|
+
surface,
|
|
46
|
+
className
|
|
47
|
+
];
|
|
48
|
+
}
|
|
49
|
+
return nil;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
NSString * _Nullable RunnerRequireSelector(
|
|
53
|
+
Class cls,
|
|
54
|
+
SEL selector,
|
|
55
|
+
NSString *selectorName,
|
|
56
|
+
NSString *surface
|
|
57
|
+
) {
|
|
58
|
+
if (![cls instancesRespondToSelector:selector]) {
|
|
59
|
+
return [NSString stringWithFormat:
|
|
60
|
+
@"private XCTest %@ synthesis unavailable: %@ missing %@",
|
|
61
|
+
surface,
|
|
62
|
+
NSStringFromClass(cls),
|
|
63
|
+
selectorName
|
|
64
|
+
];
|
|
65
|
+
}
|
|
66
|
+
return nil;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
NSString * _Nullable RunnerRequireApplicationSelector(
|
|
70
|
+
id application,
|
|
71
|
+
SEL selector,
|
|
72
|
+
NSString *selectorName,
|
|
73
|
+
NSString *surface
|
|
74
|
+
) {
|
|
75
|
+
if (![application respondsToSelector:selector]) {
|
|
76
|
+
return [NSString stringWithFormat:
|
|
77
|
+
@"private XCTest %@ synthesis unavailable: XCUIApplication missing %@",
|
|
78
|
+
surface,
|
|
79
|
+
selectorName
|
|
80
|
+
];
|
|
81
|
+
}
|
|
82
|
+
return nil;
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
NSString *RunnerFormatXCTestException(NSException *exception, NSString *fallbackReason) {
|
|
86
|
+
NSString *name = exception.name ?: @"NSException";
|
|
87
|
+
NSString *reason = exception.reason ?: fallbackReason;
|
|
88
|
+
return [NSString stringWithFormat:@"%@: %@", name, reason];
|
|
89
|
+
}
|
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
import{o as e}from"./png-worker-contract.js";import{S as t,T as n,_ as r,a as i,w as a}from"./sdk-contracts.js";import{Ht as o,Kt as s,Ut as c,_n as l,hn as u,ln as d,qt as f,un as p}from"./viewport-dimension.js";import{tt as ee}from"./screenshot-geometry.js";import{$ as te,K as ne,Q as m,T as re,X as ie,Z as ae,et as oe,it as se,nt as h,q as g,tt as ce}from"./sdk-batch-runner.js";import{Dt as le,_t as ue,a as de,b as fe,ct as pe,d as _,f as me,ft as he,g as ge,h as _e,ht as v,i as ve,l as ye,m as be,n as xe,rt as Se,u as Ce,ut as we,vt as Te,w as Ee,x as De,y}from"./screenshot-result.js";import{a as Oe,d as ke,o as Ae,u as je}from"./sdk-device.js";import{b as Me,c as Ne,d as Pe,h as Fe,i as Ie,y as Le}from"./registry.js";import{t as Re}from"./command-metadata.js";import{A as ze,C as Be,I as Ve,j as b,v as He,x as Ue}from"./sdk-android-adb.js";import{n as x,t as We}from"./version.js";import{t as S}from"./timeouts.js";import{n as Ge,t as Ke}from"./client-metro.js";import C from"node:path";import{createHash as qe,randomUUID as Je}from"node:crypto";import w from"node:fs";import Ye from"node:os";import T from"node:http";import E from"node:https";import{pipeline as D}from"node:stream/promises";import{Transform as Xe,Writable as Ze}from"node:stream";import O from"node:net";function Qe(e,t){let n=m(e,`bundleId`),r=m(e,`package`);return{app:h(e,`app`),appPath:h(e,`appPath`),platform:ce(e,`platform`),appId:n??r,bundleId:n,package:r,identifiers:s({session:t,bundleId:n,packageName:r})}}function $e(e,t){let n=m(e,`bundleId`),i=m(e,`packageName`),a=n??i??m(e,`appId`),o=m(e,`launchTarget`)??i??n??a;if(!o)throw new r(`COMMAND_FAILED`,`Daemon response is missing "launchTarget".`,{response:e});return{appName:m(e,`appName`),appId:a,bundleId:n,packageName:i,launchTarget:o,installablePath:m(e,`installablePath`),archivePath:m(e,`archivePath`),materializationId:m(e,`materializationId`),materializationExpiresAt:m(e,`materializationExpiresAt`),identifiers:s({session:t,bundleId:n,packageName:i,appId:a})}}function et(e){return{released:e.released===!0,materializationId:h(e,`materializationId`),identifiers:{}}}function tt(e){let{record:t,platform:n,id:r,name:i,target:a}=it(e,`name`),o=rt(t);return{platform:n,target:a,kind:te(t,`kind`),id:r,name:i,booted:typeof t.booted==`boolean`?t.booted:void 0,...Ae(n)&&o?{appleOs:o}:{},identifiers:f(n,r,i),...k(n,r)}}function nt(e){let{record:t,platform:n,id:r,name:i,target:a}=it(e,`name`),o=h(t,`device`),s=rt(t),c={session:i,...f(n,r,o)};return{name:i,createdAt:oe(t,`createdAt`),sessionStateDir:m(t,`sessionStateDir`),runnerLogPath:m(t,`runnerLogPath`),device:{platform:n,target:a,id:r,name:o,...s?{appleOs:s}:{},identifiers:c,...k(n,r,{simulatorSetPath:ae(t,`ios_simulator_device_set`)})},identifiers:c}}function rt(e){let t=e.appleOs;return Oe(t)?t:void 0}function it(e,t){let n=ne(e);return{record:n,platform:ce(n,`platform`),id:h(n,`id`),name:h(n,t),target:ie(n,`target`)}}function k(e,t,n={}){if(e===`ios`)return{ios:{udid:t,...n.simulatorSetPath===void 0?{}:{simulatorSetPath:n.simulatorSetPath}}};if(!ke(e))return{};let r=n.serial??t;return e===`android`?{android:{serial:r}}:{vega:{serial:r}}}function at(e){if(!g(e))return;let t=e.platform,n=m(e,`metroHost`),r=typeof e.metroPort==`number`?e.metroPort:void 0,i=m(e,`bundleUrl`),a=m(e,`launchUrl`);return{platform:t===`ios`||t===`android`?t:void 0,metroHost:n,metroPort:r,bundleUrl:i,launchUrl:a}}function ot(e){let t=e.platform,n=m(e,`id`),r=m(e,`device`);if(!je(t)||!n||!r)return;let i=ie(e,`target`),a=ke(t)?m(e,`serial`)??n:void 0;return{platform:t,target:i,id:n,name:r,identifiers:{...f(t,n,r),...a?{serial:a}:{}},...k(t,t===`ios`?m(e,`device_udid`)??n:n,{simulatorSetPath:ae(e,`ios_simulator_device_set`),serial:a})}}function st(e){if(g(e)&&!(typeof e.durationMs!=`number`||typeof e.measuredAt!=`string`||typeof e.method!=`string`))return{durationMs:e.durationMs,measuredAt:e.measuredAt,method:e.method,appTarget:m(e,`appTarget`),appBundleId:m(e,`appBundleId`)}}function ct(e){if(!g(e)||typeof e.success!=`boolean`||typeof e.exitCode!=`number`||typeof e.stdout!=`string`||typeof e.stderr!=`string`)return;let t=lt(e.error);return{success:e.success,exitCode:e.exitCode,stdout:e.stdout,stderr:e.stderr,...t?{error:t}:{}}}function lt(e){if(g(e)&&!(typeof e.code!=`string`||typeof e.message!=`string`))return{code:e.code,message:e.message,...typeof e.hint==`string`?{hint:e.hint}:{},...typeof e.diagnosticId==`string`?{diagnosticId:e.diagnosticId}:{},...typeof e.logPath==`string`?{logPath:e.logPath}:{},...g(e.details)?{details:e.details}:{}}}function ut(e){return Array.isArray(e)?e:[]}function dt(e){let t=d(e);return se({requestId:e.requestId,cwd:e.cwd,sessionExplicit:e.session!==void 0,debug:e.debug,includeCost:e.cost,responseLevel:e.responseLevel,lockPolicy:e.lockPolicy,lockPlatform:e.lockPlatform,...l(t),sessionIsolation:e.sessionIsolation,installSource:e.installSource,retainMaterializedPaths:e.retainMaterializedPaths,materializedPathRetentionMs:e.materializedPathRetentionMs,materializationId:e.materializationId})}function A(e){return e??`default`}const ft={...Ie(),batch:Fe(pt)};function pt(e,t,n){let i=ft[e];if(!i)throw Error(`Missing daemon writer for batch command: ${e}`);let a=Re(e);if(!a)throw Error(`Missing command metadata for batch command: ${e}`);try{return ht(i,a,a.readInput(t))}catch(t){throw new r(`INVALID_ARGS`,`Batch step ${n} ${e} input is invalid: ${t instanceof Error?t.message:String(t)}`,void 0,t)}}function mt(e,t){let n=ft[e];if(!n)throw Error(`Missing daemon writer for command: ${e}`);return ht(n,Re(e),t)}function ht(e,t,n){let r=e(n);return{...r,...t?{metadataFlags:Me(t,r.options)}:{}}}async function gt(e,t){let n=w.statSync(e),r=C.basename(e),i=n.isDirectory(),a=yt(t)??vt(e,n),o=[];try{let t=i?await _t(e,o):e,n=w.statSync(t);return{payloadPath:t,fileName:r,artifactType:i?`app-bundle`:`file`,platform:a,contentType:i?`application/gzip`:`application/octet-stream`,sha256:await xt(t),sizeBytes:n.size,cleanup:()=>bt(o)}}catch(e){throw bt(o),e}}async function _t(e,t){let n=w.mkdtempSync(C.join(Ye.tmpdir(),`agent-device-upload-${Je()}-`));t.push(n);let r=C.join(n,`${C.basename(e)}.tar.gz`);return await He(`tar`,[`czf`,r,`-C`,C.dirname(e),C.basename(e)],{env:{...process.env,COPYFILE_DISABLE:`1`}}),r}function vt(e,t){let n=e.toLowerCase();if(t.isDirectory()&&n.endsWith(`.app`)||n.endsWith(`.ipa`))return`ios`;if(n.endsWith(`.apk`)||n.endsWith(`.aab`))return`android`}function yt(e){return e===`ios`||e===`android`?e:void 0}function bt(e){for(let t of e)w.rmSync(t,{recursive:!0,force:!0})}async function xt(e){let t=qe(`sha256`),n=new Ze({write(e,n,r){t.update(e),r()}});return await D(w.createReadStream(e),n).catch(e=>{throw new r(`COMMAND_FAILED`,`Failed to read local artifact`,{},e instanceof Error?e:void 0)}),t.digest(`hex`)}function St(e){let{stage:t,fileName:n,startOffset:r,totalBytes:i,onProgress:a}=e,o=r,s=Tt(i),c=Math.min(i,r+s);return new Xe({transform(e,r,l){o=Math.min(i,o+e.byteLength),o>=c&&(a?.({type:`progress`,stage:t,fileName:n,transferredBytes:o,totalBytes:i}),c=Math.min(i,o+s)),l(null,e)}})}function Ct(){if(!(process.stderr.isTTY!==!0||process.env.CI))return e=>{process.stderr.write(`${wt(e)}\n`)}}function wt(e){switch(e.type){case`start`:return`Uploading ${e.fileName} (${M(e.totalBytes)}) via ${j(e.stage)} upload`;case`resume`:return`Resuming ${e.fileName} at ${M(e.transferredBytes)} of ${M(e.totalBytes)}`;case`progress`:return`Uploaded ${M(e.transferredBytes)} of ${M(e.totalBytes)} (${Et(e.transferredBytes,e.totalBytes)})`;case`fallback`:return`Direct upload did not complete; retrying ${e.fileName} with ${j(e.to)} upload`}}function Tt(e){return Math.max(8388608,Math.ceil(e*.05))}function j(e){return e===`direct`?`direct`:`legacy`}function Et(e,t){return t<=0?`100%`:`${Math.min(100,Math.floor(e/t*100))}%`}function M(e){if(e<1024)return`${e} B`;let t=e/1024;if(t<1024)return`${t.toFixed(1)} KiB`;let n=t/1024;return n<1024?`${n.toFixed(1)} MiB`:`${(n/1024).toFixed(1)} GiB`}const Dt=300*1e3,Ot=`uploadStreamRetryable`;async function kt(e){return await N({...e,url:e.url,redirectCount:0,startOffset:0})}function At(e){return e instanceof r&&e.details?.[Ot]===!0}async function N(e){let t=e.url.protocol===`https:`?E:T,n=w.statSync(e.payloadPath).size,i=Nt(e.headers,e.startOffset,n);return Mt(e.progress,e.startOffset,n),await new Promise((a,o)=>{let s=!1,c=t.request({protocol:e.url.protocol,host:e.url.hostname,port:e.url.port,method:e.method,path:e.url.pathname+e.url.search,headers:i},t=>{s=!0,pe(t).then(i=>{clearTimeout(l);let s=t.statusCode??500,c=t.headers.location;if(c&&Pt(s)){if(e.redirectCount>=5){o(new r(`COMMAND_FAILED`,`Artifact upload exceeded redirect limit`,{maxRedirects:5,url:e.url.toString()}));return}let t=new URL(c,e.url);N({...e,url:t,redirectCount:e.redirectCount+1}).then(a,o);return}let u=Ft(s)?It(t.headers,n):void 0;if(u!==void 0){if(u>=n){a({statusCode:200,statusMessage:`Upload already complete`,body:``});return}if(u<=e.startOffset){o(new r(`COMMAND_FAILED`,`Artifact upload resume did not advance`,{offset:u,previousOffset:e.startOffset,url:e.url.toString()}));return}N({...e,startOffset:u}).then(a,o);return}a({statusCode:s,statusMessage:t.statusMessage,body:i})}).catch(o)}),l=setTimeout(()=>{c.destroy(),o(new r(`COMMAND_FAILED`,e.timeoutMessage,{timeoutMs:Dt,...e.timeoutHint?{hint:e.timeoutHint}:{},...jt(e)}))},Dt);c.on(`error`,t=>{s||(clearTimeout(l),o(new r(`COMMAND_FAILED`,e.errorMessage,{...e.errorHint?{hint:e.errorHint}:{},...jt(e)},t)))}),c.on(`close`,()=>clearTimeout(l)),D(w.createReadStream(e.payloadPath,{start:e.startOffset}),St({stage:e.progress?.stage??`legacy`,fileName:e.progress?.fileName??C.basename(e.payloadPath),startOffset:e.startOffset,totalBytes:n,onProgress:e.progress?.onProgress}),c).catch(e=>{s||(c.destroy(),o(new r(`COMMAND_FAILED`,`Failed to read local artifact`,{},e instanceof Error?e:Error(String(e)))))})})}function jt(e){return e.retryable===!0?{[Ot]:!0}:{}}function Mt(e,t,n){e?.onProgress?.({type:t>0?`resume`:`start`,stage:e.stage,fileName:e.fileName,transferredBytes:t,totalBytes:n})}function Nt(e,t,n){return t<=0?e:{...e,"content-length":Math.max(n-t,0),"content-range":`bytes ${t}-${n-1}/${n}`}}function Pt(e){return[301,302,303,307,308].includes(e)}function Ft(e){return e===308}function It(e,t){let n=Lt(e[`x-upload-offset`]??e[`upload-offset`]);if(n!==void 0)return Math.min(n,t);let r=Rt(e.range)?.match(/^bytes=0-(\d+)$/);if(!r)return;let i=Number(r[1]);if(!(!Number.isSafeInteger(i)||i<0))return Math.min(i+1,t)}function Lt(e){let t=Rt(e);if(t===void 0)return;let n=Number(t);return Number.isSafeInteger(n)&&n>=0?n:void 0}function Rt(e){return Array.isArray(e)?e[0]:e}const zt=30*1e3;async function Bt(e){let t=await gt(e.localPath,e.platform),n=e.baseUrl.endsWith(`/`)?e.baseUrl:`${e.baseUrl}/`,r=Je();try{let i=await Wt({normalizedBase:n,token:e.token,artifact:t,uploadAttemptId:r});return i?.kind===`cache-hit`?i.uploadId:i?.kind===`direct-upload`?await Vt({normalizedBase:n,token:e.token,artifact:t,preflight:i,uploadAttemptId:r,onProgress:e.onProgress})||(e.onProgress?.({type:`fallback`,from:`direct`,to:`legacy`,fileName:t.fileName}),await Ut({normalizedBase:n,token:e.token,artifact:t,onProgress:e.onProgress})):await Ut({normalizedBase:n,token:e.token,artifact:t,onProgress:e.onProgress})}finally{t.cleanup()}}async function Vt(e){let t=async t=>(await qt(e.artifact,t,e.onProgress),await Jt({normalizedBase:e.normalizedBase,token:e.token,uploadId:t.uploadId}));try{return await t(e.preflight)}catch(n){if(!Ht(n))return;let r=await Wt({normalizedBase:e.normalizedBase,token:e.token,artifact:e.artifact,uploadAttemptId:e.uploadAttemptId});if(r?.kind===`cache-hit`)return r.uploadId;if(r?.kind===`direct-upload`)try{return await t(r)}catch{return}return}}function Ht(e){return e instanceof r?At(e):!0}async function Ut(e){let{normalizedBase:t,token:n,artifact:i}=e,a=new URL(`upload`,t),o={"content-type":i.contentType,"x-artifact-type":i.artifactType,"x-artifact-filename":i.fileName,"x-artifact-hash":i.sha256,"x-artifact-hash-algorithm":`sha256`,"transfer-encoding":`chunked`};Object.assign(o,v(n));let s=await kt({url:a,method:`POST`,headers:o,payloadPath:i.payloadPath,timeoutMessage:`Artifact upload timed out`,timeoutHint:`The upload to the remote daemon exceeded the 5-minute timeout.`,errorMessage:`Failed to upload artifact to remote daemon`,errorHint:`Verify the remote daemon is reachable and supports artifact uploads.`,progress:{stage:`legacy`,fileName:i.fileName,onProgress:e.onProgress}});try{let e=JSON.parse(s.body);if(!e.ok||!e.uploadId)throw new r(`COMMAND_FAILED`,`Upload failed: ${s.body}`);return e.uploadId}catch(e){throw e instanceof r?e:new r(`COMMAND_FAILED`,`Invalid upload response: ${s.body}`)}}async function Wt(e){let t=new URL(`upload/preflight`,e.normalizedBase),n={"content-type":`application/json`};Object.assign(n,v(e.token));let r=await fetch(t,{method:`POST`,headers:n,signal:AbortSignal.timeout(zt),body:JSON.stringify({uploadAttemptId:e.uploadAttemptId,sha256:e.artifact.sha256,fileName:e.artifact.fileName,sizeBytes:e.artifact.sizeBytes,artifactType:e.artifact.artifactType,...e.artifact.platform?{platform:e.artifact.platform}:{},contentType:e.artifact.contentType})}).catch(()=>void 0);if(r?.ok)return Gt(await r.json().catch(()=>void 0))}function Gt(e){if(!e||typeof e!=`object`)return;let t=e;if(t.ok!==!0||typeof t.uploadId!=`string`)return;if(t.cacheHit===!0)return{kind:`cache-hit`,uploadId:t.uploadId};let n=t.upload;if(!n||typeof n.url!=`string`)return;let r=n.headers??{};if(Kt(r))return{kind:`direct-upload`,uploadId:t.uploadId,url:n.url,headers:r}}function Kt(e){return!e||typeof e!=`object`||Array.isArray(e)?!1:Object.values(e).every(e=>typeof e==`string`)}async function qt(e,t,n){let i=await kt({url:new URL(t.url),method:`PUT`,headers:t.headers,payloadPath:e.payloadPath,timeoutMessage:`Direct artifact upload timed out`,timeoutHint:`The direct upload ticket did not accept the artifact within the timeout.`,errorMessage:`Failed to upload artifact with direct upload ticket`,retryable:!0,progress:{stage:`direct`,fileName:e.fileName,onProgress:n}});if(i.statusCode<200||i.statusCode>=300)throw new r(`COMMAND_FAILED`,`Direct artifact upload failed`,{statusCode:i.statusCode,statusMessage:i.statusMessage})}async function Jt(e){let t=new URL(`upload/finalize`,e.normalizedBase),n={"content-type":`application/json`};Object.assign(n,v(e.token));let i=await fetch(t,{method:`POST`,headers:n,signal:AbortSignal.timeout(zt),body:JSON.stringify({uploadId:e.uploadId})}).catch(e=>{throw new r(`COMMAND_FAILED`,`Failed to finalize direct artifact upload`,{},e)});if(!i.ok)throw new r(`COMMAND_FAILED`,`Direct artifact upload finalize failed`,{status:i.status,statusText:i.statusText});let a=await i.json().catch(()=>void 0);if(!a?.ok||!a.uploadId)throw new r(`COMMAND_FAILED`,`Invalid upload finalize response`);return a.uploadId}async function Yt(e,t){let n=[...e.positionals??[]],r=e.flags?{...e.flags}:void 0,i=e.meta?.installSource,a={},o,s=Ct();if(!fn(t))return en({positionals:n,flags:r,installSource:i,uploadedArtifactId:o,clientArtifactPaths:a});r=Zt(e,n,r,a);let c=await tn(e,t,s);return c&&(i=c.installSource,o=c.uploadedArtifactId??o),e.command!==`install`&&e.command!==`reinstall`||(o=await Xt(e,t,n,s)??o),en({positionals:n,flags:r,installSource:i,uploadedArtifactId:o,clientArtifactPaths:a})}async function Xt(e,t,n,r){let i=n.length===1?0:1,a=n[i];if(a===void 0)return;if(a.startsWith(`remote:`)){n[i]=a.slice(7);return}let o=$t(a,e.meta?.cwd);if(o)return await Bt({localPath:o,baseUrl:t.baseUrl,token:t.token,platform:e.flags?.platform,onProgress:r})}function Zt(e,t,n,r){let i=nn(e,t);if(!i)return n;i.positionalPath!==void 0&&(t[i.positionalIndex]=i.positionalPath);let a=Qt(n,i.flagPath);return r[i.field]=i.localPath,a}function Qt(e,t){return t===void 0?e:{...e??{},out:t}}function $t(e,t){let n=C.isAbsolute(e)?e:C.resolve(t??process.cwd(),e);return w.existsSync(n)?n:void 0}function en(e){return{positionals:e.positionals,flags:e.flags,installSource:e.installSource,uploadedArtifactId:e.uploadedArtifactId,...Object.keys(e.clientArtifactPaths).length>0?{clientArtifactPaths:e.clientArtifactPaths}:{}}}async function tn(e,t,n){let r=e.meta?.installSource;if(e.command!==`install_source`||!r||r.kind!==`path`)return null;let i=r.path.trim();if(!i)return{installSource:r};if(i.startsWith(`remote:`))return{installSource:{...r,path:i.slice(7)}};let a=C.isAbsolute(i)?i:C.resolve(e.meta?.cwd??process.cwd(),i);if(!w.existsSync(a))return{installSource:{...r,path:a}};let o=await Bt({localPath:a,baseUrl:t.baseUrl,token:t.token,platform:e.flags?.platform,onProgress:n});return{installSource:{...r,path:a},uploadedArtifactId:o}}function nn(e,t){if(e.command===`screenshot`){let n=sn(e,`path`,`.png`);return t[0]?{field:`path`,localPath:n,positionalIndex:0,positionalPath:F(`screenshot`,`.png`)}:{field:`path`,localPath:n,positionalIndex:0,flagPath:F(`screenshot`,`.png`)}}if(e.command===`record`&&(t[0]??``).toLowerCase()===`start`){if(!an(e)&&e.flags?.platform===void 0)return null;let t=rn(e),n=on(sn(e,`outPath`,t,1),e);return{field:`outPath`,localPath:n,positionalIndex:1,positionalPath:F(`recording`,C.extname(n)||t)}}return null}function rn(e){return he(e.flags?.platform)}function an(e){return P(e.positionals?.[1])||P(e.flags?.out)}function on(e,t){return t.flags?.platform===`web`?we(e,rn(t)):e}function sn(e,t,n,r=0){let i=e.positionals?.[r]??e.flags?.out,a=`${t===`path`?`screenshot`:`recording`}-${Date.now()}${n}`,o=P(i)?i:a;return C.isAbsolute(o)?o:C.resolve(e.meta?.cwd??process.cwd(),o)}function P(e){return typeof e==`string`&&e.trim().length>0}function F(e,t){let n=t.startsWith(`.`)?t:`.${t}`;return C.posix.join(`/tmp`,`agent-device-${e}-${Date.now()}-${Math.random().toString(36).slice(2,8)}${n}`)}async function cn(e,t,n){let r=Array.isArray(n.data?.artifacts)?n.data.artifacts:[];if(r.length===0||!e.baseUrl)return n;let i=n.data?{...n.data}:{},a=[];for(let n of r){if(!n||typeof n!=`object`||typeof n.artifactId!=`string`){a.push(n);continue}let r=ln(n,t);await un({baseUrl:e.baseUrl,token:e.token,artifactId:n.artifactId,destinationPath:r,requestScope:t.meta}),i[n.field]=r,a.push({...n,localPath:r})}return i.artifacts=a,{ok:!0,data:i}}function ln(e,t){if(e.localPath&&e.localPath.trim().length>0)return e.localPath;let n=t.meta?.clientArtifactPaths?.[e.field];if(n&&n.trim().length>0)return n;let r=e.fileName?.trim()||`${e.field}-${Date.now()}`;return C.resolve(t.meta?.cwd??process.cwd(),r)}async function un(e){let t=new URL(dn(e.baseUrl,e.artifactId)),n=t.protocol===`https:`?E:T;await w.promises.mkdir(C.dirname(e.destinationPath),{recursive:!0}),await new Promise((i,a)=>{let o=!1,s=e.timeoutMs??9e4,c=t=>{if(!o){if(o=!0,clearTimeout(u),t){w.promises.rm(e.destinationPath,{force:!0}).finally(()=>a(t));return}i()}},l=n.request({protocol:t.protocol,host:t.hostname,port:t.port,method:`GET`,path:t.pathname+t.search,headers:{...v(e.token),...ue(e.requestScope?.tenantId)}},t=>{if((t.statusCode??500)>=400){let n=``;t.setEncoding(`utf8`),t.on(`data`,e=>{n+=e}),t.on(`end`,()=>{c(new r(`COMMAND_FAILED`,`Failed to download remote artifact`,{artifactId:e.artifactId,statusCode:t.statusCode,requestId:e.requestScope?.requestId,body:n}))});return}t.on(`aborted`,()=>{c(new r(`COMMAND_FAILED`,`Remote artifact download was interrupted`,{artifactId:e.artifactId,requestId:e.requestScope?.requestId}))}),D(t,w.createWriteStream(e.destinationPath)).then(()=>c(),e=>c(e instanceof Error?e:Error(String(e))))}),u=setTimeout(()=>{let t=new r(`COMMAND_FAILED`,`Remote artifact download timed out`,{artifactId:e.artifactId,requestId:e.requestScope?.requestId,timeoutMs:s});c(t),l.destroy(t)},s);l.on(`error`,t=>{if(t instanceof r){c(t);return}c(new r(`COMMAND_FAILED`,`Failed to download remote artifact`,{artifactId:e.artifactId,requestId:e.requestScope?.requestId,timeoutMs:s},t instanceof Error?t:void 0))}),l.end()})}function dn(e,t){let n=e.endsWith(`/`)?e:`${e}/`;return new URL(`artifacts/${encodeURIComponent(t)}`,n).toString()}function fn(e){return typeof e.baseUrl==`string`&&e.baseUrl.length>0}const pn=3e3,mn=1e3;function I(e){let t=Cn(e);if(!t||typeof t!=`object`)return null;let n=t,r=hn(n);if(!r)return null;let i=gn(n);return i?{token:r,...i,transport:_n(n.transport),pid:R(n.pid)??0,version:L(n.version),codeSignature:L(n.codeSignature),processStartTime:L(n.processStartTime)}:null}function hn(e){return typeof e.token==`string`&&e.token.length>0?e.token:null}function gn(e){let t=R(e.port),n=R(e.httpPort);return t===void 0&&n===void 0?null:{port:t,httpPort:n}}function _n(e){return e===`socket`||e===`http`||e===`dual`?e:void 0}function L(e){return typeof e==`string`?e:void 0}function R(e){return Number.isInteger(e)&&Number(e)>0?Number(e):void 0}function z(e){let t=Cn(e);if(!t||typeof t!=`object`)return null;let n=t;return Number.isInteger(n.pid)&&Number(n.pid)>0?{pid:Number(n.pid),processStartTime:typeof n.processStartTime==`string`?n.processStartTime:void 0,startedAt:typeof n.startedAt==`number`?n.startedAt:void 0}:null}function B(e){wn(e)}function V(e){wn(e)}function vn(e){let t=U(e);if(!t.hasLock||t.hasInfo)return;let n=z(e.lockPath);if(!n){V(e.lockPath);return}_(n.pid,n.processStartTime)||V(e.lockPath)}async function H(e,t,n={}){let r=n.stopLiveProcesses??!0,i={reason:t,removedInfo:!1,removedLock:!1,stoppedInfoProcess:!1,stoppedLockProcess:!1};try{let t=w.existsSync(e.infoPath),n=I(e.infoPath);if(n){let t=_(n.pid,n.processStartTime);t&&!r?i.retainedInfoProcess=!0:(t&&(await W(n),i.stoppedInfoProcess=!0),B(e.infoPath),i.removedInfo=!0)}else t&&(B(e.infoPath),i.removedInfo=!0);let a=w.existsSync(e.lockPath),o=z(e.lockPath);if(o){let t=_(o.pid,o.processStartTime);t&&!r?i.retainedLockProcess=!0:(t&&(await me(o.pid,{termTimeoutMs:pn,killTimeoutMs:mn,expectedStartTime:o.processStartTime}),i.stoppedLockProcess=!0),V(e.lockPath),i.removedLock=!0)}else a&&(V(e.lockPath),i.removedLock=!0)}catch(e){i.error=e instanceof Error?e.message:String(e)}return b({level:i.error?`warn`:`info`,phase:`daemon_startup_metadata_cleanup`,data:i}),i}function U(e){return{hasInfo:w.existsSync(e.infoPath),hasLock:w.existsSync(e.lockPath)}}async function yn(e){let t=U(e);if(!t.hasLock||t.hasInfo)return!1;let n=z(e.lockPath);return!n||!_(n.pid,n.processStartTime)?(V(e.lockPath),!0):!1}async function W(e){await me(e.pid,{termTimeoutMs:pn,killTimeoutMs:mn,expectedStartTime:e.processStartTime})}function bn(e){return typeof e.baseUrl==`string`&&e.baseUrl.length>0}function xn(e,t=y(process.env.AGENT_DEVICE_STATE_DIR)){let n=Sn(t);return e.hasLock&&!e.hasInfo?`agent-device attempted to clean stale daemon metadata automatically, but ${t.lockPath} still exists without ${t.infoPath}. Retry with --debug; if this persists after confirming no agent-device daemon process is running, run: ${n}`:e.hasLock&&e.hasInfo?`agent-device attempted to clean stale daemon metadata automatically, but ${t.infoPath} and ${t.lockPath} still remain. Retry with --debug; if this persists after confirming no agent-device daemon process is running, run: ${n}`:e.hasInfo?`agent-device did not observe reachable daemon metadata after retrying, and ${t.infoPath} still remains. Stale metadata was cleaned automatically when safe; retry with --debug. If this persists after confirming no agent-device daemon process is running, run: ${n}`:`agent-device did not observe reachable daemon metadata after retrying. Stale metadata was cleaned automatically when safe; retry with --debug and check daemon diagnostics logs. If stale metadata returns after confirming no agent-device daemon process is running, run: ${n}`}function Sn(e){return`rm -f ${be(e.infoPath)} ${be(e.lockPath)}`}function Cn(e){if(!w.existsSync(e))return null;try{return JSON.parse(w.readFileSync(e,`utf8`))}catch{return null}}function wn(e){try{w.existsSync(e)&&w.unlinkSync(e)}catch{}}function Tn(e,t){if(t.onProgress){t.onProgress(e);return}e.type===`command`&&(t.req.command===`doctor`&&Pe(),process.stderr.write(`${e.message}\n`))}function G(e,t,n){return new r(`COMMAND_FAILED`,`Invalid daemon response`,{requestId:e.meta?.requestId,line:t},n instanceof Error?n:void 0)}function En(e){let t=t=>(e.onError(t),!0);return{handleLine(n){let r;try{r=JSON.parse(n)}catch(r){return t(G(e.req,n,r))}if(ve(r))try{return Tn(r.event,{req:e.req,onProgress:e.onProgress}),!1}catch(e){return t(e)}return de(r)?(e.onResponse(r.response),!0):e.responseFormat===`socket-legacy`?(e.onResponse(r),!0):t(G(e.req,n,Error(`Missing daemon progress response envelope`)))}}}function Dn(e,t){return ye(e)&&String(Array.isArray(t)?t.join(`,`):t??``).includes(`application/x-ndjson`)}function On(e,t){let{req:n,isSettled:r,resolve:i,reject:a,clearTimeout:o}=t,s=``,c=En({req:n,onProgress:t.onProgress,responseFormat:`socket-legacy`,onResponse(t){o(),i(t),e.end()},onError(e){o(),a(e)}});e.setEncoding(`utf8`),e.on(`data`,e=>{if(r())return;let t=Ce(s,e);s=t.buffer;for(let e of t.lines)if(c.handleLine(e))return})}function kn(e,t){let{req:n,handleResponseBody:i,reject:a,clearTimeout:o}=t,s=``,c=!1,l=En({req:n,onProgress:t.onProgress,responseFormat:`ndjson-envelope`,onResponse(e){c=!0,o(),i(JSON.stringify(e))},onError(e){c=!0,o(),a(e)}});e.setEncoding(`utf8`),e.on(`data`,e=>{if(c)return;let t=Ce(s,e);s=t.buffer;for(let e of t.lines)if(e&&l.handleLine(e))return}),e.on(`end`,()=>{if(c)return;let e=s.trim();e&&l.handleLine(e)||(c=!0,o(),a(G(n,e)))}),e.on(`error`,e=>{c||(c=!0,o(),a(new r(`COMMAND_FAILED`,`Failed to read daemon response`,{requestId:n.meta?.requestId},e instanceof Error?e:void 0)))})}function An(e,t){let{info:n,req:i,resolve:a,reject:o}=t;try{let t=jn(e);if(t.error){o(Mn(t.error,i.meta?.requestId));return}if(!t.result||typeof t.result!=`object`){o(new r(`COMMAND_FAILED`,`Invalid daemon RPC response`,{requestId:i.meta?.requestId}));return}Nn(n,i,t.result,a,o)}catch(t){o(new r(`COMMAND_FAILED`,`Invalid daemon response`,{requestId:i.meta?.requestId,line:e},t instanceof Error?t:void 0))}}function jn(e){return JSON.parse(e)}function Mn(e,t){let i=e.data??{};return new r(n(i.code==null?void 0:String(i.code),`COMMAND_FAILED`),String(i.message??e.message??`Daemon RPC request failed`),{...typeof i.details==`object`&&i.details?i.details:{},hint:typeof i.hint==`string`?i.hint:void 0,diagnosticId:typeof i.diagnosticId==`string`?i.diagnosticId:void 0,logPath:typeof i.logPath==`string`?i.logPath:void 0,retriable:typeof i.retriable==`boolean`?i.retriable:void 0,supportedOn:typeof i.supportedOn==`string`?i.supportedOn:void 0,requestId:t})}async function Nn(e,t,n,r,i){try{r(e.baseUrl&&n.ok?await cn(e,t,n):n)}catch(e){i(e)}}function Pn(e,t){let n=e.meta?.requestId??ze();return Fn(e.command)?{jsonrpc:`2.0`,id:n,method:In(e.command),params:Ln(e,e.command,t)}:{jsonrpc:`2.0`,id:n,method:`agent_device.command`,params:e}}function Fn(e){return e===`lease_allocate`||e===`lease_heartbeat`||e===`lease_release`}function In(e){switch(e){case`lease_allocate`:return`agent_device.lease.allocate`;case`lease_heartbeat`:return`agent_device.lease.heartbeat`;case`lease_release`:return`agent_device.lease.release`}}function Ln(e,t,n){return u(p(e),t,{includeTokenParam:n.includeTokenParam,token:e.token,session:e.session})}const Rn=[`xcodebuild .*AgentDeviceRunnerUITests/RunnerTests/testCommand`,`xcodebuild .*AgentDeviceRunner\\.env\\.session-`,`xcodebuild build-for-testing .*apple/runner/AgentDeviceRunner/AgentDeviceRunner\\.xcodeproj`];function zn(e){let t=re(e.command);if(t.envelopeMs===`unbounded`)return;let n={...t,envelopeMs:t.envelopeMs};return Bn(n,e.positionals??[])??Vn(n,e.flags)??n.envelopeMs}function Bn(e,t){if(e.budget.source!==`positional-parser`)return;let n=e.budget.parser(t);return n===null?void 0:Un(e,n)}function Vn(e,t){if(e.budget.source===`flag`)return e.budget.envelope===`widen`?Hn(e,e.budget,t):typeof t?.timeoutMs==`number`?t.timeoutMs:e.envelopeMs}function Hn(e,t,n){if(n?.settle!==!0)return e.envelopeMs;let r=typeof n.timeoutMs==`number`?n.timeoutMs:t.defaultBudgetMs;return typeof r==`number`?Wn(e,r):e.envelopeMs}function Un(e,t){return Math.max(e.envelopeMs,t+Xn)}function Wn(e,t){return Math.max(e.envelopeMs,e.envelopeMs+t+Xn)}function Gn(e,t,n,i,a,o){let s=a?{terminated:0}:Jn(),c=!a&&Kn(i),l=c?Yn(e,t):{forcedKill:!1};return b({level:`error`,phase:`daemon_request_timeout`,data:{timeoutMs:o,requestId:n,command:i,timedOutRunnerPidsTerminated:s.terminated,timedOutRunnerCleanupError:s.error,daemonPidReset:c?e.pid:void 0,daemonPidForceKilled:c?l.forcedKill:void 0,daemonPreservedAfterTimeout:!a&&!c,daemonBaseUrl:e.baseUrl}}),new r(`COMMAND_FAILED`,`Daemon request timed out`,{timeoutMs:o,requestId:n,hint:qn({remote:a,resetDaemon:c,command:i})})}function Kn(e){return re(e).onTimeout===`reset-daemon`}function qn(e){let{remote:t,resetDaemon:n,command:r}=e;if(t)return`Retry with --debug and verify the remote daemon URL, auth token, and remote host logs.`;if(!n){let e=r===c.snapshot?` If this was the first Apple-platform snapshot on the device, run agent-device prepare ios-runner with the same --platform before snapshot/test so runner startup is handled explicitly.`:``;return`Retry with --debug and check daemon diagnostics logs. The timed-out ${r??`request`} request was canceled and Apple runner work was aborted when detected; the daemon was kept alive so the session can still be closed or inspected.${e}`}return`Retry with --debug and check daemon diagnostics logs. Timed-out Apple runner xcodebuild processes were terminated when detected.`}function Jn(){let e=0;try{for(let t of Rn)Be(`pkill`,[`-f`,t],{allowFailure:!0}).exitCode===0&&(e+=1);return{terminated:e}}catch(t){return{terminated:e,error:t instanceof Error?t.message:String(t)}}}function Yn(e,t){let n=!1;try{_(e.pid,e.processStartTime)&&(process.kill(e.pid,`SIGKILL`),n=!0)}catch{W(e)}finally{B(t.infoPath),V(t.lockPath)}return{forcedKill:n}}const Xn=3e4,Zn=`Daemon HTTP endpoint is unavailable`,Qn=`Daemon socket endpoint is unavailable`;async function $n(e,t){let n=cr(e,t);if(await er(e,n))return!0;let r=lr(e,t,n);return r?await er(e,r):!1}async function er(e,t){return t===`http`?await nr(e):await tr(e.port)}function tr(e){return e?new Promise(t=>{let n=!1,r=O.createConnection({host:`127.0.0.1`,port:e},()=>{i(!0)}),i=e=>{n||(n=!0,r.destroy(),t(e))};r.setTimeout(500),r.on(`timeout`,()=>{i(!1)}),r.on(`error`,()=>{i(!1)})}):Promise.resolve(!1)}function nr(e){return ir(e).then(e=>e.reachable)}async function rr(e){let t=await ir(e);if(!e.baseUrl||!t.reachable)return t;if(typeof t.rpcProtocolVersion==`number`&&t.rpcProtocolVersion!==2)throw new r(`COMMAND_FAILED`,`Remote daemon RPC protocol is incompatible`,{daemonBaseUrl:e.baseUrl,clientVersion:x(),remoteVersion:t.version,remoteService:t.service,supportedRpcProtocolVersion:2,remoteRpcProtocolVersion:t.rpcProtocolVersion,hint:`Upgrade agent-device on the client or remote host so both support the same daemon RPC protocol.`});return t}function ir(e){let t=e.baseUrl?Te(e.baseUrl,`health`):e.httpPort?`http://127.0.0.1:${e.httpPort}/health`:null;if(!t)return Promise.resolve({reachable:!1});let n=new URL(t),r=n.protocol===`https:`?E:T,i=e.baseUrl?3e3:500;return new Promise(t=>{let a=e.baseUrl?v(e.token):{},o=r.request({protocol:n.protocol,host:n.hostname,port:n.port,path:n.pathname+n.search,method:`GET`,timeout:i,headers:a},e=>{let n=``;e.setEncoding(`utf8`),e.on(`data`,e=>{n+=e}),e.on(`end`,()=>{let r=e.statusCode??500;t({reachable:r<500,statusCode:r,...ar(n)})})});o.on(`timeout`,()=>{o.destroy(),t({reachable:!1})}),o.on(`error`,()=>{t({reachable:!1})}),o.end()})}function ar(e){try{let t=JSON.parse(e);return{service:typeof t.service==`string`?t.service:void 0,version:typeof t.version==`string`?t.version:void 0,rpcProtocolVersion:typeof t.rpcProtocolVersion==`number`?t.rpcProtocolVersion:void 0}}catch{return{}}}async function or(e,t,n,r,i,a={}){let o=cr(e,n);try{return await sr(e,t,r,i,o,a)}catch(s){let c=lr(e,n,o);if(!c||!ur(s,o))throw s;return await sr(e,t,r,i,c,a)}}async function sr(e,t,n,r,i,a){return i===`http`?await mr(e,t,n,r,a):await pr(e,t,n,r,a)}function cr(e,t){if(e.baseUrl){if(t===`socket`)throw new r(`COMMAND_FAILED`,`Remote daemon endpoint only supports HTTP transport`,{daemonBaseUrl:e.baseUrl});return`http`}if(t===`http`||t===`socket`)return dr(e,t);let n=(e.transport===`socket`||e.transport===`dual`?[`socket`,`http`]:[`http`,`socket`]).find(t=>K(e,t));if(n)return n;throw new r(`COMMAND_FAILED`,`Daemon metadata has no reachable transport`)}function K(e,t){return t===`http`?!!e.httpPort:!!e.port}function lr(e,t,n){if(t!==`auto`||e.baseUrl)return null;let r=n===`socket`?`http`:`socket`;return K(e,r)?r:null}function ur(e,t){return t===`socket`&&e instanceof r&&e.code===`COMMAND_FAILED`&&e.message===`Failed to communicate with daemon`&&e.details?.daemonSocketRequestWritten===!1}function dr(e,t){if(K(e,t))return t;throw new r(`COMMAND_FAILED`,t===`http`?Zn:Qn)}function fr(e,t,n,i={}){return b({level:`error`,phase:`daemon_request_socket_error`,data:{requestId:t,message:e instanceof Error?e.message:String(e)}}),new r(`COMMAND_FAILED`,`Failed to communicate with daemon`,{...i,requestId:t,hint:n?`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 pr(e,t,n,i,a){let o=e.port;if(!o)throw new r(`COMMAND_FAILED`,Qn);return new Promise((r,s)=>{let c=!1,l=O.createConnection({host:`127.0.0.1`,port:o},()=>{c=!0,l.write(`${JSON.stringify(t)}\n`)}),u=!1,d=typeof i==`number`?setTimeout(()=>{u=!0,l.destroy(),s(Gn(e,n,t.meta?.requestId,t.command,!1,i))},i):void 0;On(l,{req:t,onProgress:a.onProgress,isSettled:()=>u,clearTimeout:()=>{d&&clearTimeout(d)},resolve:e=>{u=!0,r(e)},reject:e=>{u=!0,s(e)}}),l.on(`error`,e=>{u||(u=!0,d&&clearTimeout(d),s(fr(e,t.meta?.requestId,!1,{daemonSocketRequestWritten:c})))})})}async function mr(e,t,n,i,a){let o=e.baseUrl?new URL(Te(e.baseUrl,`rpc`)):e.httpPort?new URL(`http://127.0.0.1:${e.httpPort}/rpc`):null;if(!o)throw new r(`COMMAND_FAILED`,Zn);let s=JSON.stringify(Pn(t,{includeTokenParam:!e.baseUrl})),c={"content-type":`application/json`,"content-length":Buffer.byteLength(s)};return e.baseUrl&&Object.assign(c,v(e.token)),await new Promise((l,u)=>{let d=(o.protocol===`https:`?E:T).request({protocol:o.protocol,host:o.hostname,port:o.port,method:`POST`,path:o.pathname+o.search,headers:c},n=>{if(Dn(t,n.headers?.[`content-type`])){kn(n,{req:t,onProgress:a.onProgress,reject:u,clearTimeout:()=>{p&&clearTimeout(p)},handleResponseBody:n=>An(n,{info:e,req:t,resolve:l,reject:u})});return}pe(n).then(n=>{p&&clearTimeout(p),An(n,{info:e,req:t,resolve:l,reject:u})}).catch(e=>{p&&clearTimeout(p),u(new r(`COMMAND_FAILED`,`Failed to read daemon response`,{requestId:t.meta?.requestId},e instanceof Error?e:void 0))})}),f=bn(e),p=typeof i==`number`?setTimeout(()=>{d.destroy(),u(Gn(e,n,t.meta?.requestId,t.command,f,i))},i):void 0;d.on(`error`,e=>{p&&clearTimeout(p),u(fr(e,t.meta?.requestId,f))}),d.write(s),d.end()})}const q=15e3,J=new O.BlockList;J.addSubnet(`127.0.0.0`,8,`ipv4`),J.addAddress(`::1`,`ipv6`),J.addSubnet(`::ffff:127.0.0.0`,104,`ipv6`);function hr(e,t){let n=gr(e),r=_r(e,t),i=vr(e,r.remoteBaseUrl),a=yr(e,n,r.rawBaseUrl);return{paths:y(a?br():n),transportPreference:i.preference,serverMode:i.serverMode,ownedStateDir:a,remoteBaseUrl:r.remoteBaseUrl,remoteAuthToken:r.authToken}}function gr(e){return e.flags?.stateDir??process.env.AGENT_DEVICE_STATE_DIR}function _r(e,t){let n=e.flags?.daemonBaseUrl??process.env.AGENT_DEVICE_DAEMON_BASE_URL,r=Hr(n),i=t??process.env.AGENT_DEVICE_DAEMON_AUTH_TOKEN;return Ur(r,i),{rawBaseUrl:n,remoteBaseUrl:r,authToken:i}}function vr(e,t){let n=e.flags?.daemonTransport??process.env.AGENT_DEVICE_DAEMON_TRANSPORT,i=De(n);if(t&&i===`socket`)throw new r(`INVALID_ARGS`,`Remote daemon base URL only supports HTTP transport. Remove --daemon-transport socket.`,{daemonBaseUrl:t});return{preference:i,serverMode:fe(e.flags?.daemonServerMode??process.env.AGENT_DEVICE_DAEMON_SERVER_MODE??(n===`dual`?`dual`:void 0))}}function yr(e,t,n){return Pr(e.command)&&!t&&!n}function br(){return w.mkdtempSync(C.join(Ye.tmpdir(),`agent-device-replay-daemon-`))}async function xr(e){if(e.remoteBaseUrl)return await Sr(e);let t=await Cr(e);return t?{info:t,startedByClient:!1}:(vn(e.paths),await kr(e))}async function Sr(e){let t={transport:`http`,token:e.remoteAuthToken??``,pid:0,baseUrl:e.remoteBaseUrl};if((await rr(t)).reachable)return{info:t,startedByClient:!1};throw new r(`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. If this CLI was connected with connect proxy, run agent-device disconnect to return to the local daemon.`})}async function Cr(e){let t=I(e.paths.infoPath);if(!t)return null;let n=await wr(t,e.transportPreference);return Er(t,n)?t:(Dr(t,n,e.paths.baseDir),await W(t),B(e.paths.infoPath),null)}async function wr(e,t){try{return await $n(e,t)}catch(e){if(Tr(e))return!1;throw e}}function Tr(e){return e instanceof r&&e.code===`COMMAND_FAILED`&&(e.message===`Daemon HTTP endpoint is unavailable`||e.message===`Daemon socket endpoint is unavailable`)}function Er(e,t){return e.version===x()&&e.codeSignature===zr()&&t}function Dr(e,t,n){try{let r=e.version?`pid ${e.pid}, v${e.version}`:`pid ${e.pid}`,i=Or(e,t);process.stderr.write(`Replacing daemon (${r}) in ${n}: ${i}\n`)}catch{}}function Or(e,t){return e.version===x()?e.codeSignature===zr()?t?`not reusable`:`unreachable`:`code-signature mismatch`:`version mismatch (client v${x()})`}async function kr(e){let t=0,n=[],i,a;for(let r=1;r<=2;r+=1){let o;try{o=Rr(e),a={pid:o.pid}}catch(t){if(i=t instanceof Error?t.message:String(t),n.push(await H(e.paths,`start_error`)),r<2){await S(150);continue}break}let s=await Lr(q,e,o);if(s.kind===`ready`)return{info:s.info,startedByClient:!0};if(s.kind===`early_exit`){if(a=s.exit,i=Br(s.exit),n.push(await H(e.paths,`start_error`)),r<2){await S(150);continue}break}if(await yn(e.paths)){t+=1;continue}let c=U(e.paths),l=r<2,u=await H(e.paths,`startup_timeout`,{stopLiveProcesses:!1});if(n.push(u),u.retainedInfoProcess||u.retainedLockProcess){let t=await Lr(q,e,o);if(t.kind===`ready`)return{info:t.info,startedByClient:!0};t.kind===`early_exit`&&(a=t.exit,i=Br(t.exit));break}if(!l)break;!c.hasInfo&&!c.hasLock&&await S(150)}let o=U(e.paths),s=Vr(e.paths.logPath);throw new r(`COMMAND_FAILED`,`Failed to start daemon`,{kind:`daemon_startup_failed`,stateDir:e.paths.baseDir,infoPath:e.paths.infoPath,lockPath:e.paths.lockPath,logPath:e.paths.logPath,startupTimeoutMs:q,startupAttempts:2,lockRecoveryCount:t,cleanupResults:n,startError:i,daemonProcess:a,...s?{daemonLogTail:s}:{},metadataState:o,hint:xn(o,e.paths)})}async function Ar(e,t,n,r){if(!Pr(e.command)||!t.startedByClient&&!n.ownedStateDir||bn(t.info)||Mr(r)||Fr(e,r))return r;let i={pid:t.info.pid,removedInfo:!1,removedLock:!1,removedStateDir:!1,error:void 0},a=r;try{await W(t.info)}catch(e){i.error=e instanceof Error?e.message:String(e)}finally{let e=w.existsSync(n.paths.infoPath);B(n.paths.infoPath),i.removedInfo=e&&!w.existsSync(n.paths.infoPath);let t=w.existsSync(n.paths.lockPath);if(V(n.paths.lockPath),i.removedLock=t&&!w.existsSync(n.paths.lockPath),n.ownedStateDir){let e=Ee(n.paths.sessionsDir);e?a=jr(r,e):(w.rmSync(n.paths.baseDir,{recursive:!0,force:!0}),i.removedStateDir=!w.existsSync(n.paths.baseDir))}}return b({level:i.error?`warn`:`info`,phase:`daemon_replay_cleanup`,data:i}),a}function jr(e,n){if(e&&!e.ok)return e;let{sessionName:i,tombstone:a}=n,o=a.sourcePath?`re-run: replay ${a.sourcePath} --save-script`:`re-run your replay <script> --save-script from the start`;return{ok:!1,error:t(new r(`REPAIR_COMMIT_FAILED`,`The repair transaction for session "${i}" completed, but committing its healed script failed at teardown: ${a.commitFailure.message}. ${o}.`))}}function Mr(e){if(!e||e.ok||e.error.code!==`REPLAY_DIVERGENCE`)return!1;let t=e.error.details?.divergence;if(!t||typeof t!=`object`)return!1;let n=t.resume;return!n||typeof n!=`object`?!1:n.repairSessionHeld===!0}function Nr(e,t){let n=`This repair session's daemon was kept alive to continue the repair; pass --state-dir ${t} on your next command (press, replay --from, or close --save-script) to reach it.`,r=e.error.hint;return{...e,error:{...e.error,hint:r?`${r} ${n}`:n}}}function Pr(e){return e===c.replay||e===c.test}function Fr(e,t){return e.command!==c.replay||!t||!t.ok?!1:t.data?.sessionActive===!0}function Ir(e,t){let n=e.data??{},r=typeof n.session==`string`?n.session:void 0,i=[...t?[`--state-dir ${_e(t)}`]:[],...r?[`--session ${_e(r)}`]:[]];if(i.length===0)return e;let a=`This session's daemon was kept alive because its script left the session active; pass ${i.join(` `)} on your next command to reach it.`,o=typeof n.message==`string`?n.message:void 0;return{...e,data:{...n,hint:a,message:o?`${o} ${a}`:a}}}async function Lr(e,t,n){let r=Date.now(),i;for(n.exited.then(e=>{i=e});Date.now()-r<e;){if(i)return{kind:`early_exit`,exit:i};let e=I(t.paths.infoPath);if(e&&await $n(e,t.transportPreference))return{kind:`ready`,info:e};if(i)return{kind:`early_exit`,exit:i};await S(100)}return{kind:`timeout`}}function Rr(e){let t=Y(),n=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};w.mkdirSync(e.paths.baseDir,{recursive:!0});let i=w.openSync(e.paths.logPath,`a`),a=w.openSync(e.paths.logPath,`a`);try{return Ue(process.execPath,n,{env:r,stdio:[`ignore`,i,a]})}finally{w.closeSync(i),w.closeSync(a)}}function Y(){let e=We(),t=[C.join(e,`dist`,`src`,`internal`,`daemon.js`),C.join(e,`dist`,`src`,`daemon.js`)],n=t[0];if(n===void 0)throw new r(`COMMAND_FAILED`,`Daemon dist path list is empty`);let i=t.find(e=>w.existsSync(e))??n,a=C.join(e,`src`,`daemon.ts`),o=t.some(e=>w.existsSync(e)),s=w.existsSync(a);if(!o&&!s)throw new r(`COMMAND_FAILED`,`Daemon entry not found`,{distPaths:t,srcPath:a});return{root:e,distPath:i,distPaths:t,srcPath:a,useSrc:(process.execArgv.includes(`--experimental-strip-types`)||!o)&&s}}function zr(){let e=Y();return ge(e.useSrc?e.srcPath:e.distPath,e.root)}function Br(e){return e.error?`daemon process ${e.pid} failed to start: ${e.error}`:e.signal?`daemon process ${e.pid} exited before readiness with signal ${e.signal}`:`daemon process ${e.pid} exited before readiness with code ${e.exitCode??0}`}function Vr(e){try{if(!w.existsSync(e))return;let t=w.statSync(e);if(t.size<=0)return;let n=Math.min(t.size,64e3),r=w.openSync(e,`r`);try{let e=Buffer.alloc(n);w.readSync(r,e,0,n,t.size-n);let i=e.toString(`utf8`).trim();return i.length>0?i:void 0}finally{w.closeSync(r)}}catch{return}}function Hr(e){if(!e)return;let t;try{t=new URL(e)}catch(t){throw new r(`INVALID_ARGS`,`Invalid daemon base URL`,{daemonBaseUrl:e},t instanceof Error?t:void 0)}if(t.protocol!==`http:`&&t.protocol!==`https:`)throw new r(`INVALID_ARGS`,`Daemon base URL must use http or https`,{daemonBaseUrl:e});return t.toString().replace(/\/+$/,``)}function Ur(e,t){if(!e)return;let n=new URL(e).hostname;if(!Wr(n)&&!(typeof t==`string`&&t.trim().length>0))throw new r(`INVALID_ARGS`,`Remote daemon base URL for non-loopback hosts requires daemon authentication`,{daemonBaseUrl:e,hint:`Provide --daemon-auth-token or AGENT_DEVICE_DAEMON_AUTH_TOKEN when using a non-loopback remote daemon URL.`})}function Wr(e){let t=e.trim().toLowerCase().replace(/^\[(.*)\]$/,`$1`);return t===`localhost`?!0:O.isIPv4(t)?J.check(t,`ipv4`):O.isIPv6(t)?J.check(t,`ipv6`):!1}async function Gr(e,t={}){let n=e.meta?.requestId??ze(),r=!!(e.meta?.debug||e.flags?.verbose),i=e.flags,{daemonAuthToken:a,...o}=i??{},s=i?{...e,flags:o}:e,c=hr(s,t.authToken??a),l=zn(s),u=await Ve(`daemon_startup`,async()=>await xr(c),{requestId:n,session:e.session}),d=u.info,f=await Yt(s,d);$r(s.command);let p=Kr(s,f,d.token,n,r);return b({level:`info`,phase:`daemon_request_prepare`,data:{requestId:n,command:s.command,session:s.session}}),await Xr(s,u,c,async()=>Qr(Zr(await Ve(`daemon_request`,async()=>await or(d,p,c.transportPreference,c.paths,l,t.onProgress?{onProgress:t.onProgress}:void 0),{requestId:n,command:e.command}),c),s,c))}function Kr(e,t,n,r,i){return{...e,positionals:t.positionals,flags:t.flags,token:n,meta:qr(e,t,r,i)}}function qr(e,t,n,r){let i=e.meta??{};return{...i,requestId:n,debug:r,...Jr(i,e.flags),...Yr(t)}}function Jr(e,t){return{includeCost:e.includeCost,cwd:e.cwd,sessionExplicit:e.sessionExplicit,tenantId:e.tenantId??t?.tenant,runId:e.runId??t?.runId,leaseId:e.leaseId??t?.leaseId,sessionIsolation:e.sessionIsolation??t?.sessionIsolation,lockPolicy:e.lockPolicy,lockPlatform:e.lockPlatform}}function Yr(e){return{...e.uploadedArtifactId?{uploadedArtifactId:e.uploadedArtifactId}:{},...e.clientArtifactPaths?{clientArtifactPaths:e.clientArtifactPaths}:{},...e.installSource?{installSource:e.installSource}:{}}}async function Xr(e,t,n,i){let a,o=!1,s;try{a=await i()}catch(e){o=!0,s=e}let c=await Ar(e,t,n,a);if(o)throw s;if(!c)throw new r(`COMMAND_FAILED`,`Daemon request produced no response after cleanup`);return c}function Zr(e,t){return e.ok||!t.ownedStateDir||!Mr(e)?e:Nr(e,t.paths.baseDir)}function Qr(e,t,n){return!e.ok||!Fr(t,e)?e:Ir(e,n.ownedStateDir?n.paths.baseDir:void 0)}function $r(e){!ei(e)||process.stderr.isTTY!==!0||process.env.CI||process.stderr.write(e===c.reinstall?`Reinstalling...
|
|
1
|
+
import{o as e}from"./png-worker-contract.js";import{S as t,T as n,_ as r,a as i,w as a}from"./sdk-contracts.js";import{bt as o,ht as s}from"./screenshot-geometry.js";import{Sn as c,_n as l,bn as u,fn as d,gn as f,pn as p,vn as m,w as ee,wn as te,xn as ne,yn as re}from"./sdk-batch-runner.js";import{a as ie,d as ae,o as oe,u as se}from"./sdk-device.js";import{Cn as ce,Gt as h,Kt as g,Tn as le,_n as ue,en as de,tn as _,vn as fe}from"./viewport-dimension.js";import{_t as pe,a as me,b as he,ct as ge,d as v,f as _e,ft as ve,g as ye,h as be,ht as y,i as xe,l as Se,m as Ce,n as we,rt as Te,u as Ee,ut as De,vt as Oe,w as ke,x as Ae,y as b}from"./screenshot-result.js";import{S as je,c as Me,d as Ne,h as Pe,i as Fe,x as Ie}from"./registry.js";import{t as Le}from"./command-metadata.js";import{A as Re,C as ze,I as Be,j as x,v as Ve,x as He}from"./sdk-android-adb.js";import{n as S,t as Ue}from"./version.js";import{t as C}from"./timeouts.js";import{n as We,t as Ge}from"./client-metro.js";import w from"node:path";import{createHash as Ke,randomUUID as qe}from"node:crypto";import T from"node:fs";import Je from"node:os";import E from"node:http";import D from"node:https";import{pipeline as O}from"node:stream/promises";import{Transform as Ye,Writable as Xe}from"node:stream";import k from"node:net";function Ze(e,t){let n=m(e,`bundleId`),r=m(e,`package`);return{app:c(e,`app`),appPath:c(e,`appPath`),platform:ne(e,`platform`),appId:n??r,bundleId:n,package:r,identifiers:de({session:t,bundleId:n,packageName:r})}}function Qe(e,t){let n=m(e,`bundleId`),i=m(e,`packageName`),a=n??i??m(e,`appId`),o=m(e,`launchTarget`)??i??n??a;if(!o)throw new r(`COMMAND_FAILED`,`Daemon response is missing "launchTarget".`,{response:e});return{appName:m(e,`appName`),appId:a,bundleId:n,packageName:i,launchTarget:o,installablePath:m(e,`installablePath`),archivePath:m(e,`archivePath`),materializationId:m(e,`materializationId`),materializationExpiresAt:m(e,`materializationExpiresAt`),identifiers:de({session:t,bundleId:n,packageName:i,appId:a})}}function $e(e){return{released:e.released===!0,materializationId:c(e,`materializationId`),identifiers:{}}}function et(e){let{record:t,platform:n,id:r,name:i,target:a}=rt(e,`name`),o=nt(t);return{platform:n,target:a,kind:re(t,`kind`),id:r,name:i,booted:typeof t.booted==`boolean`?t.booted:void 0,...oe(n)&&o?{appleOs:o}:{},identifiers:_(n,r,i),...A(n,r)}}function tt(e){let{record:t,platform:n,id:r,name:i,target:a}=rt(e,`name`),o=c(t,`device`),s=nt(t),d={session:i,..._(n,r,o)};return{name:i,createdAt:u(t,`createdAt`),sessionStateDir:m(t,`sessionStateDir`),runnerLogPath:m(t,`runnerLogPath`),device:{platform:n,target:a,id:r,name:o,...s?{appleOs:s}:{},identifiers:d,...A(n,r,{simulatorSetPath:l(t,`ios_simulator_device_set`)})},identifiers:d}}function nt(e){let t=e.appleOs;return ie(t)?t:void 0}function rt(e,t){let n=d(e);return{record:n,platform:ne(n,`platform`),id:c(n,`id`),name:c(n,t),target:f(n,`target`)}}function A(e,t,n={}){if(e===`ios`)return{ios:{udid:t,...n.simulatorSetPath===void 0?{}:{simulatorSetPath:n.simulatorSetPath}}};if(!ae(e))return{};let r=n.serial??t;return e===`android`?{android:{serial:r}}:{vega:{serial:r}}}function it(e){if(!p(e))return;let t=e.platform,n=m(e,`metroHost`),r=typeof e.metroPort==`number`?e.metroPort:void 0,i=m(e,`bundleUrl`),a=m(e,`launchUrl`);return{platform:t===`ios`||t===`android`?t:void 0,metroHost:n,metroPort:r,bundleUrl:i,launchUrl:a}}function at(e){let t=e.platform,n=m(e,`id`),r=m(e,`device`);if(!se(t)||!n||!r)return;let i=f(e,`target`),a=ae(t)?m(e,`serial`)??n:void 0;return{platform:t,target:i,id:n,name:r,identifiers:{..._(t,n,r),...a?{serial:a}:{}},...A(t,t===`ios`?m(e,`device_udid`)??n:n,{simulatorSetPath:l(e,`ios_simulator_device_set`),serial:a})}}function ot(e){if(p(e)&&!(typeof e.durationMs!=`number`||typeof e.measuredAt!=`string`||typeof e.method!=`string`))return{durationMs:e.durationMs,measuredAt:e.measuredAt,method:e.method,appTarget:m(e,`appTarget`),appBundleId:m(e,`appBundleId`)}}function st(e){if(!p(e)||typeof e.success!=`boolean`||typeof e.exitCode!=`number`||typeof e.stdout!=`string`||typeof e.stderr!=`string`)return;let t=ct(e.error);return{success:e.success,exitCode:e.exitCode,stdout:e.stdout,stderr:e.stderr,...t?{error:t}:{}}}function ct(e){if(p(e)&&!(typeof e.code!=`string`||typeof e.message!=`string`))return{code:e.code,message:e.message,...typeof e.hint==`string`?{hint:e.hint}:{},...typeof e.diagnosticId==`string`?{diagnosticId:e.diagnosticId}:{},...typeof e.logPath==`string`?{logPath:e.logPath}:{},...p(e.details)?{details:e.details}:{}}}function lt(e){return Array.isArray(e)?e:[]}function ut(e){let t=ue(e);return te({requestId:e.requestId,cwd:e.cwd,sessionExplicit:e.session!==void 0,debug:e.debug,includeCost:e.cost,responseLevel:e.responseLevel,lockPolicy:e.lockPolicy,lockPlatform:e.lockPlatform,...le(t),sessionIsolation:e.sessionIsolation,installSource:e.installSource,retainMaterializedPaths:e.retainMaterializedPaths,materializedPathRetentionMs:e.materializedPathRetentionMs,materializationId:e.materializationId})}function j(e){return e??`default`}const dt={...Fe(),batch:Pe(ft)};function ft(e,t,n){let i=dt[e];if(!i)throw Error(`Missing daemon writer for batch command: ${e}`);let a=Le(e);if(!a)throw Error(`Missing command metadata for batch command: ${e}`);try{return mt(i,a,a.readInput(t))}catch(t){throw new r(`INVALID_ARGS`,`Batch step ${n} ${e} input is invalid: ${t instanceof Error?t.message:String(t)}`,void 0,t)}}function pt(e,t){let n=dt[e];if(!n)throw Error(`Missing daemon writer for command: ${e}`);return mt(n,Le(e),t)}function mt(e,t,n){let r=e(n);return{...r,...t?{metadataFlags:je(t,r.options)}:{}}}async function ht(e,t){let n=T.statSync(e),r=w.basename(e),i=n.isDirectory(),a=vt(t)??_t(e,n),o=[];try{let t=i?await gt(e,o):e,n=T.statSync(t);return{payloadPath:t,fileName:r,artifactType:i?`app-bundle`:`file`,platform:a,contentType:i?`application/gzip`:`application/octet-stream`,sha256:await bt(t),sizeBytes:n.size,cleanup:()=>yt(o)}}catch(e){throw yt(o),e}}async function gt(e,t){let n=T.mkdtempSync(w.join(Je.tmpdir(),`agent-device-upload-${qe()}-`));t.push(n);let r=w.join(n,`${w.basename(e)}.tar.gz`);return await Ve(`tar`,[`czf`,r,`-C`,w.dirname(e),w.basename(e)],{env:{...process.env,COPYFILE_DISABLE:`1`}}),r}function _t(e,t){let n=e.toLowerCase();if(t.isDirectory()&&n.endsWith(`.app`)||n.endsWith(`.ipa`))return`ios`;if(n.endsWith(`.apk`)||n.endsWith(`.aab`))return`android`}function vt(e){return e===`ios`||e===`android`?e:void 0}function yt(e){for(let t of e)T.rmSync(t,{recursive:!0,force:!0})}async function bt(e){let t=Ke(`sha256`),n=new Xe({write(e,n,r){t.update(e),r()}});return await O(T.createReadStream(e),n).catch(e=>{throw new r(`COMMAND_FAILED`,`Failed to read local artifact`,{},e instanceof Error?e:void 0)}),t.digest(`hex`)}function xt(e){let{stage:t,fileName:n,startOffset:r,totalBytes:i,onProgress:a}=e,o=r,s=wt(i),c=Math.min(i,r+s);return new Ye({transform(e,r,l){o=Math.min(i,o+e.byteLength),o>=c&&(a?.({type:`progress`,stage:t,fileName:n,transferredBytes:o,totalBytes:i}),c=Math.min(i,o+s)),l(null,e)}})}function St(){if(!(process.stderr.isTTY!==!0||process.env.CI))return e=>{process.stderr.write(`${Ct(e)}\n`)}}function Ct(e){switch(e.type){case`start`:return`Uploading ${e.fileName} (${M(e.totalBytes)}) via ${Tt(e.stage)} upload`;case`resume`:return`Resuming ${e.fileName} at ${M(e.transferredBytes)} of ${M(e.totalBytes)}`;case`progress`:return`Uploaded ${M(e.transferredBytes)} of ${M(e.totalBytes)} (${Et(e.transferredBytes,e.totalBytes)})`;case`fallback`:return`Direct upload did not complete; retrying ${e.fileName} with ${Tt(e.to)} upload`}}function wt(e){return Math.max(8388608,Math.ceil(e*.05))}function Tt(e){return e===`direct`?`direct`:`legacy`}function Et(e,t){return t<=0?`100%`:`${Math.min(100,Math.floor(e/t*100))}%`}function M(e){if(e<1024)return`${e} B`;let t=e/1024;if(t<1024)return`${t.toFixed(1)} KiB`;let n=t/1024;return n<1024?`${n.toFixed(1)} MiB`:`${(n/1024).toFixed(1)} GiB`}const Dt=300*1e3,Ot=`uploadStreamRetryable`;async function kt(e){return await N({...e,url:e.url,redirectCount:0,startOffset:0})}function At(e){return e instanceof r&&e.details?.[Ot]===!0}async function N(e){let t=e.url.protocol===`https:`?D:E,n=T.statSync(e.payloadPath).size,i=Nt(e.headers,e.startOffset,n);return Mt(e.progress,e.startOffset,n),await new Promise((a,o)=>{let s=!1,c=t.request({protocol:e.url.protocol,host:e.url.hostname,port:e.url.port,method:e.method,path:e.url.pathname+e.url.search,headers:i},t=>{s=!0,ge(t).then(i=>{clearTimeout(l);let s=t.statusCode??500,c=t.headers.location;if(c&&Pt(s)){if(e.redirectCount>=5){o(new r(`COMMAND_FAILED`,`Artifact upload exceeded redirect limit`,{maxRedirects:5,url:e.url.toString()}));return}let t=new URL(c,e.url);N({...e,url:t,redirectCount:e.redirectCount+1}).then(a,o);return}let u=Ft(s)?It(t.headers,n):void 0;if(u!==void 0){if(u>=n){a({statusCode:200,statusMessage:`Upload already complete`,body:``});return}if(u<=e.startOffset){o(new r(`COMMAND_FAILED`,`Artifact upload resume did not advance`,{offset:u,previousOffset:e.startOffset,url:e.url.toString()}));return}N({...e,startOffset:u}).then(a,o);return}a({statusCode:s,statusMessage:t.statusMessage,body:i})}).catch(o)}),l=setTimeout(()=>{c.destroy(),o(new r(`COMMAND_FAILED`,e.timeoutMessage,{timeoutMs:Dt,...e.timeoutHint?{hint:e.timeoutHint}:{},...jt(e)}))},Dt);c.on(`error`,t=>{s||(clearTimeout(l),o(new r(`COMMAND_FAILED`,e.errorMessage,{...e.errorHint?{hint:e.errorHint}:{},...jt(e)},t)))}),c.on(`close`,()=>clearTimeout(l)),O(T.createReadStream(e.payloadPath,{start:e.startOffset}),xt({stage:e.progress?.stage??`legacy`,fileName:e.progress?.fileName??w.basename(e.payloadPath),startOffset:e.startOffset,totalBytes:n,onProgress:e.progress?.onProgress}),c).catch(e=>{s||(c.destroy(),o(new r(`COMMAND_FAILED`,`Failed to read local artifact`,{},e instanceof Error?e:Error(String(e)))))})})}function jt(e){return e.retryable===!0?{[Ot]:!0}:{}}function Mt(e,t,n){e?.onProgress?.({type:t>0?`resume`:`start`,stage:e.stage,fileName:e.fileName,transferredBytes:t,totalBytes:n})}function Nt(e,t,n){return t<=0?e:{...e,"content-length":Math.max(n-t,0),"content-range":`bytes ${t}-${n-1}/${n}`}}function Pt(e){return[301,302,303,307,308].includes(e)}function Ft(e){return e===308}function It(e,t){let n=Lt(e[`x-upload-offset`]??e[`upload-offset`]);if(n!==void 0)return Math.min(n,t);let r=Rt(e.range)?.match(/^bytes=0-(\d+)$/);if(!r)return;let i=Number(r[1]);if(!(!Number.isSafeInteger(i)||i<0))return Math.min(i+1,t)}function Lt(e){let t=Rt(e);if(t===void 0)return;let n=Number(t);return Number.isSafeInteger(n)&&n>=0?n:void 0}function Rt(e){return Array.isArray(e)?e[0]:e}const zt=30*1e3;async function Bt(e){let t=await ht(e.localPath,e.platform),n=e.baseUrl.endsWith(`/`)?e.baseUrl:`${e.baseUrl}/`,r=qe();try{let i=await Wt({normalizedBase:n,token:e.token,artifact:t,uploadAttemptId:r});return i?.kind===`cache-hit`?i.uploadId:i?.kind===`direct-upload`?await Vt({normalizedBase:n,token:e.token,artifact:t,preflight:i,uploadAttemptId:r,onProgress:e.onProgress})||(e.onProgress?.({type:`fallback`,from:`direct`,to:`legacy`,fileName:t.fileName}),await Ut({normalizedBase:n,token:e.token,artifact:t,onProgress:e.onProgress})):await Ut({normalizedBase:n,token:e.token,artifact:t,onProgress:e.onProgress})}finally{t.cleanup()}}async function Vt(e){let t=async t=>(await qt(e.artifact,t,e.onProgress),await Jt({normalizedBase:e.normalizedBase,token:e.token,uploadId:t.uploadId}));try{return await t(e.preflight)}catch(n){if(!Ht(n))return;let r=await Wt({normalizedBase:e.normalizedBase,token:e.token,artifact:e.artifact,uploadAttemptId:e.uploadAttemptId});if(r?.kind===`cache-hit`)return r.uploadId;if(r?.kind===`direct-upload`)try{return await t(r)}catch{return}return}}function Ht(e){return e instanceof r?At(e):!0}async function Ut(e){let{normalizedBase:t,token:n,artifact:i}=e,a=new URL(`upload`,t),o={"content-type":i.contentType,"x-artifact-type":i.artifactType,"x-artifact-filename":i.fileName,"x-artifact-hash":i.sha256,"x-artifact-hash-algorithm":`sha256`,"transfer-encoding":`chunked`};Object.assign(o,y(n));let s=await kt({url:a,method:`POST`,headers:o,payloadPath:i.payloadPath,timeoutMessage:`Artifact upload timed out`,timeoutHint:`The upload to the remote daemon exceeded the 5-minute timeout.`,errorMessage:`Failed to upload artifact to remote daemon`,errorHint:`Verify the remote daemon is reachable and supports artifact uploads.`,progress:{stage:`legacy`,fileName:i.fileName,onProgress:e.onProgress}});try{let e=JSON.parse(s.body);if(!e.ok||!e.uploadId)throw new r(`COMMAND_FAILED`,`Upload failed: ${s.body}`);return e.uploadId}catch(e){throw e instanceof r?e:new r(`COMMAND_FAILED`,`Invalid upload response: ${s.body}`)}}async function Wt(e){let t=new URL(`upload/preflight`,e.normalizedBase),n={"content-type":`application/json`};Object.assign(n,y(e.token));let r=await fetch(t,{method:`POST`,headers:n,signal:AbortSignal.timeout(zt),body:JSON.stringify({uploadAttemptId:e.uploadAttemptId,sha256:e.artifact.sha256,fileName:e.artifact.fileName,sizeBytes:e.artifact.sizeBytes,artifactType:e.artifact.artifactType,...e.artifact.platform?{platform:e.artifact.platform}:{},contentType:e.artifact.contentType})}).catch(()=>void 0);if(r?.ok)return Gt(await r.json().catch(()=>void 0))}function Gt(e){if(!e||typeof e!=`object`)return;let t=e;if(t.ok!==!0||typeof t.uploadId!=`string`)return;if(t.cacheHit===!0)return{kind:`cache-hit`,uploadId:t.uploadId};let n=t.upload;if(!n||typeof n.url!=`string`)return;let r=n.headers??{};if(Kt(r))return{kind:`direct-upload`,uploadId:t.uploadId,url:n.url,headers:r}}function Kt(e){return!e||typeof e!=`object`||Array.isArray(e)?!1:Object.values(e).every(e=>typeof e==`string`)}async function qt(e,t,n){let i=await kt({url:new URL(t.url),method:`PUT`,headers:t.headers,payloadPath:e.payloadPath,timeoutMessage:`Direct artifact upload timed out`,timeoutHint:`The direct upload ticket did not accept the artifact within the timeout.`,errorMessage:`Failed to upload artifact with direct upload ticket`,retryable:!0,progress:{stage:`direct`,fileName:e.fileName,onProgress:n}});if(i.statusCode<200||i.statusCode>=300)throw new r(`COMMAND_FAILED`,`Direct artifact upload failed`,{statusCode:i.statusCode,statusMessage:i.statusMessage})}async function Jt(e){let t=new URL(`upload/finalize`,e.normalizedBase),n={"content-type":`application/json`};Object.assign(n,y(e.token));let i=await fetch(t,{method:`POST`,headers:n,signal:AbortSignal.timeout(zt),body:JSON.stringify({uploadId:e.uploadId})}).catch(e=>{throw new r(`COMMAND_FAILED`,`Failed to finalize direct artifact upload`,{},e)});if(!i.ok)throw new r(`COMMAND_FAILED`,`Direct artifact upload finalize failed`,{status:i.status,statusText:i.statusText});let a=await i.json().catch(()=>void 0);if(!a?.ok||!a.uploadId)throw new r(`COMMAND_FAILED`,`Invalid upload finalize response`);return a.uploadId}async function Yt(e,t){let n=[...e.positionals??[]],r=e.flags?{...e.flags}:void 0,i=e.meta?.installSource,a={},o,s=St();if(!fn(t))return en({positionals:n,flags:r,installSource:i,uploadedArtifactId:o,clientArtifactPaths:a});r=Zt(e,n,r,a);let c=await tn(e,t,s);return c&&(i=c.installSource,o=c.uploadedArtifactId??o),e.command!==`install`&&e.command!==`reinstall`||(o=await Xt(e,t,n,s)??o),en({positionals:n,flags:r,installSource:i,uploadedArtifactId:o,clientArtifactPaths:a})}async function Xt(e,t,n,r){let i=n.length===1?0:1,a=n[i];if(a===void 0)return;if(a.startsWith(`remote:`)){n[i]=a.slice(7);return}let o=$t(a,e.meta?.cwd);if(o)return await Bt({localPath:o,baseUrl:t.baseUrl,token:t.token,platform:e.flags?.platform,onProgress:r})}function Zt(e,t,n,r){let i=nn(e,t);if(!i)return n;i.positionalPath!==void 0&&(t[i.positionalIndex]=i.positionalPath);let a=Qt(n,i.flagPath);return r[i.field]=i.localPath,a}function Qt(e,t){return t===void 0?e:{...e??{},out:t}}function $t(e,t){let n=w.isAbsolute(e)?e:w.resolve(t??process.cwd(),e);return T.existsSync(n)?n:void 0}function en(e){return{positionals:e.positionals,flags:e.flags,installSource:e.installSource,uploadedArtifactId:e.uploadedArtifactId,...Object.keys(e.clientArtifactPaths).length>0?{clientArtifactPaths:e.clientArtifactPaths}:{}}}async function tn(e,t,n){let r=e.meta?.installSource;if(e.command!==`install_source`||!r||r.kind!==`path`)return null;let i=r.path.trim();if(!i)return{installSource:r};if(i.startsWith(`remote:`))return{installSource:{...r,path:i.slice(7)}};let a=w.isAbsolute(i)?i:w.resolve(e.meta?.cwd??process.cwd(),i);if(!T.existsSync(a))return{installSource:{...r,path:a}};let o=await Bt({localPath:a,baseUrl:t.baseUrl,token:t.token,platform:e.flags?.platform,onProgress:n});return{installSource:{...r,path:a},uploadedArtifactId:o}}function nn(e,t){if(e.command===`screenshot`){let n=sn(e,`path`,`.png`);return t[0]?{field:`path`,localPath:n,positionalIndex:0,positionalPath:F(`screenshot`,`.png`)}:{field:`path`,localPath:n,positionalIndex:0,flagPath:F(`screenshot`,`.png`)}}if(e.command===`record`&&(t[0]??``).toLowerCase()===`start`){if(!an(e)&&e.flags?.platform===void 0)return null;let t=rn(e),n=on(sn(e,`outPath`,t,1),e);return{field:`outPath`,localPath:n,positionalIndex:1,positionalPath:F(`recording`,w.extname(n)||t)}}return null}function rn(e){return ve(e.flags?.platform)}function an(e){return P(e.positionals?.[1])||P(e.flags?.out)}function on(e,t){return t.flags?.platform===`web`?De(e,rn(t)):e}function sn(e,t,n,r=0){let i=e.positionals?.[r]??e.flags?.out,a=`${t===`path`?`screenshot`:`recording`}-${Date.now()}${n}`,o=P(i)?i:a;return w.isAbsolute(o)?o:w.resolve(e.meta?.cwd??process.cwd(),o)}function P(e){return typeof e==`string`&&e.trim().length>0}function F(e,t){let n=t.startsWith(`.`)?t:`.${t}`;return w.posix.join(`/tmp`,`agent-device-${e}-${Date.now()}-${Math.random().toString(36).slice(2,8)}${n}`)}async function cn(e,t,n){let r=Array.isArray(n.data?.artifacts)?n.data.artifacts:[];if(r.length===0||!e.baseUrl)return n;let i=n.data?{...n.data}:{},a=[];for(let n of r){if(!n||typeof n!=`object`||typeof n.artifactId!=`string`){a.push(n);continue}let r=ln(n,t);await un({baseUrl:e.baseUrl,token:e.token,artifactId:n.artifactId,destinationPath:r,requestScope:t.meta}),i[n.field]=r,a.push({...n,localPath:r})}return i.artifacts=a,{ok:!0,data:i}}function ln(e,t){if(e.localPath&&e.localPath.trim().length>0)return e.localPath;let n=t.meta?.clientArtifactPaths?.[e.field];if(n&&n.trim().length>0)return n;let r=e.fileName?.trim()||`${e.field}-${Date.now()}`;return w.resolve(t.meta?.cwd??process.cwd(),r)}async function un(e){let t=new URL(dn(e.baseUrl,e.artifactId)),n=t.protocol===`https:`?D:E;await T.promises.mkdir(w.dirname(e.destinationPath),{recursive:!0}),await new Promise((i,a)=>{let o=!1,s=e.timeoutMs??9e4,c=t=>{if(!o){if(o=!0,clearTimeout(u),t){T.promises.rm(e.destinationPath,{force:!0}).finally(()=>a(t));return}i()}},l=n.request({protocol:t.protocol,host:t.hostname,port:t.port,method:`GET`,path:t.pathname+t.search,headers:{...y(e.token),...pe(e.requestScope?.tenantId)}},t=>{if((t.statusCode??500)>=400){let n=``;t.setEncoding(`utf8`),t.on(`data`,e=>{n+=e}),t.on(`end`,()=>{c(new r(`COMMAND_FAILED`,`Failed to download remote artifact`,{artifactId:e.artifactId,statusCode:t.statusCode,requestId:e.requestScope?.requestId,body:n}))});return}t.on(`aborted`,()=>{c(new r(`COMMAND_FAILED`,`Remote artifact download was interrupted`,{artifactId:e.artifactId,requestId:e.requestScope?.requestId}))}),O(t,T.createWriteStream(e.destinationPath)).then(()=>c(),e=>c(e instanceof Error?e:Error(String(e))))}),u=setTimeout(()=>{let t=new r(`COMMAND_FAILED`,`Remote artifact download timed out`,{artifactId:e.artifactId,requestId:e.requestScope?.requestId,timeoutMs:s});c(t),l.destroy(t)},s);l.on(`error`,t=>{if(t instanceof r){c(t);return}c(new r(`COMMAND_FAILED`,`Failed to download remote artifact`,{artifactId:e.artifactId,requestId:e.requestScope?.requestId,timeoutMs:s},t instanceof Error?t:void 0))}),l.end()})}function dn(e,t){let n=e.endsWith(`/`)?e:`${e}/`;return new URL(`artifacts/${encodeURIComponent(t)}`,n).toString()}function fn(e){return typeof e.baseUrl==`string`&&e.baseUrl.length>0}const pn=3e3,mn=1e3;function I(e){let t=Cn(e);if(!t||typeof t!=`object`)return null;let n=t,r=hn(n);if(!r)return null;let i=gn(n);return i?{token:r,...i,transport:_n(n.transport),pid:R(n.pid)??0,version:L(n.version),codeSignature:L(n.codeSignature),processStartTime:L(n.processStartTime)}:null}function hn(e){return typeof e.token==`string`&&e.token.length>0?e.token:null}function gn(e){let t=R(e.port),n=R(e.httpPort);return t===void 0&&n===void 0?null:{port:t,httpPort:n}}function _n(e){return e===`socket`||e===`http`||e===`dual`?e:void 0}function L(e){return typeof e==`string`?e:void 0}function R(e){return Number.isInteger(e)&&Number(e)>0?Number(e):void 0}function z(e){let t=Cn(e);if(!t||typeof t!=`object`)return null;let n=t;return Number.isInteger(n.pid)&&Number(n.pid)>0?{pid:Number(n.pid),processStartTime:typeof n.processStartTime==`string`?n.processStartTime:void 0,startedAt:typeof n.startedAt==`number`?n.startedAt:void 0}:null}function B(e){wn(e)}function V(e){wn(e)}function vn(e){let t=U(e);if(!t.hasLock||t.hasInfo)return;let n=z(e.lockPath);if(!n){V(e.lockPath);return}v(n.pid,n.processStartTime)||V(e.lockPath)}async function H(e,t,n={}){let r=n.stopLiveProcesses??!0,i={reason:t,removedInfo:!1,removedLock:!1,stoppedInfoProcess:!1,stoppedLockProcess:!1};try{let t=T.existsSync(e.infoPath),n=I(e.infoPath);if(n){let t=v(n.pid,n.processStartTime);t&&!r?i.retainedInfoProcess=!0:(t&&(await W(n),i.stoppedInfoProcess=!0),B(e.infoPath),i.removedInfo=!0)}else t&&(B(e.infoPath),i.removedInfo=!0);let a=T.existsSync(e.lockPath),o=z(e.lockPath);if(o){let t=v(o.pid,o.processStartTime);t&&!r?i.retainedLockProcess=!0:(t&&(await _e(o.pid,{termTimeoutMs:pn,killTimeoutMs:mn,expectedStartTime:o.processStartTime}),i.stoppedLockProcess=!0),V(e.lockPath),i.removedLock=!0)}else a&&(V(e.lockPath),i.removedLock=!0)}catch(e){i.error=e instanceof Error?e.message:String(e)}return x({level:i.error?`warn`:`info`,phase:`daemon_startup_metadata_cleanup`,data:i}),i}function U(e){return{hasInfo:T.existsSync(e.infoPath),hasLock:T.existsSync(e.lockPath)}}async function yn(e){let t=U(e);if(!t.hasLock||t.hasInfo)return!1;let n=z(e.lockPath);return!n||!v(n.pid,n.processStartTime)?(V(e.lockPath),!0):!1}async function W(e){await _e(e.pid,{termTimeoutMs:pn,killTimeoutMs:mn,expectedStartTime:e.processStartTime})}function bn(e){return typeof e.baseUrl==`string`&&e.baseUrl.length>0}function xn(e,t=b(process.env.AGENT_DEVICE_STATE_DIR)){let n=Sn(t);return e.hasLock&&!e.hasInfo?`agent-device attempted to clean stale daemon metadata automatically, but ${t.lockPath} still exists without ${t.infoPath}. Retry with --debug; if this persists after confirming no agent-device daemon process is running, run: ${n}`:e.hasLock&&e.hasInfo?`agent-device attempted to clean stale daemon metadata automatically, but ${t.infoPath} and ${t.lockPath} still remain. Retry with --debug; if this persists after confirming no agent-device daemon process is running, run: ${n}`:e.hasInfo?`agent-device did not observe reachable daemon metadata after retrying, and ${t.infoPath} still remains. Stale metadata was cleaned automatically when safe; retry with --debug. If this persists after confirming no agent-device daemon process is running, run: ${n}`:`agent-device did not observe reachable daemon metadata after retrying. Stale metadata was cleaned automatically when safe; retry with --debug and check daemon diagnostics logs. If stale metadata returns after confirming no agent-device daemon process is running, run: ${n}`}function Sn(e){return`rm -f ${Ce(e.infoPath)} ${Ce(e.lockPath)}`}function Cn(e){if(!T.existsSync(e))return null;try{return JSON.parse(T.readFileSync(e,`utf8`))}catch{return null}}function wn(e){try{T.existsSync(e)&&T.unlinkSync(e)}catch{}}function Tn(e,t){if(t.onProgress){t.onProgress(e);return}e.type===`command`&&(t.req.command===`doctor`&&Ne(),process.stderr.write(`${e.message}\n`))}function G(e,t,n){return new r(`COMMAND_FAILED`,`Invalid daemon response`,{requestId:e.meta?.requestId,line:t},n instanceof Error?n:void 0)}function En(e){let t=t=>(e.onError(t),!0);return{handleLine(n){let r;try{r=JSON.parse(n)}catch(r){return t(G(e.req,n,r))}if(xe(r))try{return Tn(r.event,{req:e.req,onProgress:e.onProgress}),!1}catch(e){return t(e)}return me(r)?(e.onResponse(r.response),!0):e.responseFormat===`socket-legacy`?(e.onResponse(r),!0):t(G(e.req,n,Error(`Missing daemon progress response envelope`)))}}}function Dn(e,t){return Se(e)&&String(Array.isArray(t)?t.join(`,`):t??``).includes(`application/x-ndjson`)}function On(e,t){let{req:n,isSettled:r,resolve:i,reject:a,clearTimeout:o}=t,s=``,c=En({req:n,onProgress:t.onProgress,responseFormat:`socket-legacy`,onResponse(t){o(),i(t),e.end()},onError(e){o(),a(e)}});e.setEncoding(`utf8`),e.on(`data`,e=>{if(r())return;let t=Ee(s,e);s=t.buffer;for(let e of t.lines)if(c.handleLine(e))return})}function kn(e,t){let{req:n,handleResponseBody:i,reject:a,clearTimeout:o}=t,s=``,c=!1,l=En({req:n,onProgress:t.onProgress,responseFormat:`ndjson-envelope`,onResponse(e){c=!0,o(),i(JSON.stringify(e))},onError(e){c=!0,o(),a(e)}});e.setEncoding(`utf8`),e.on(`data`,e=>{if(c)return;let t=Ee(s,e);s=t.buffer;for(let e of t.lines)if(e&&l.handleLine(e))return}),e.on(`end`,()=>{if(c)return;let e=s.trim();e&&l.handleLine(e)||(c=!0,o(),a(G(n,e)))}),e.on(`error`,e=>{c||(c=!0,o(),a(new r(`COMMAND_FAILED`,`Failed to read daemon response`,{requestId:n.meta?.requestId},e instanceof Error?e:void 0)))})}function An(e,t){let{info:n,req:i,resolve:a,reject:o}=t;try{let t=jn(e);if(t.error){o(Mn(t.error,i.meta?.requestId));return}if(!t.result||typeof t.result!=`object`){o(new r(`COMMAND_FAILED`,`Invalid daemon RPC response`,{requestId:i.meta?.requestId}));return}Nn(n,i,t.result,a,o)}catch(t){o(new r(`COMMAND_FAILED`,`Invalid daemon response`,{requestId:i.meta?.requestId,line:e},t instanceof Error?t:void 0))}}function jn(e){return JSON.parse(e)}function Mn(e,t){let i=e.data??{};return new r(n(i.code==null?void 0:String(i.code),`COMMAND_FAILED`),String(i.message??e.message??`Daemon RPC request failed`),{...typeof i.details==`object`&&i.details?i.details:{},hint:typeof i.hint==`string`?i.hint:void 0,diagnosticId:typeof i.diagnosticId==`string`?i.diagnosticId:void 0,logPath:typeof i.logPath==`string`?i.logPath:void 0,retriable:typeof i.retriable==`boolean`?i.retriable:void 0,supportedOn:typeof i.supportedOn==`string`?i.supportedOn:void 0,requestId:t})}async function Nn(e,t,n,r,i){try{r(e.baseUrl&&n.ok?await cn(e,t,n):n)}catch(e){i(e)}}function Pn(e,t){let n=e.meta?.requestId??Re();return Fn(e.command)?{jsonrpc:`2.0`,id:n,method:In(e.command),params:Ln(e,e.command,t)}:{jsonrpc:`2.0`,id:n,method:`agent_device.command`,params:e}}function Fn(e){return e===`lease_allocate`||e===`lease_heartbeat`||e===`lease_release`}function In(e){switch(e){case`lease_allocate`:return`agent_device.lease.allocate`;case`lease_heartbeat`:return`agent_device.lease.heartbeat`;case`lease_release`:return`agent_device.lease.release`}}function Ln(e,t,n){return ce(fe(e),t,{includeTokenParam:n.includeTokenParam,token:e.token,session:e.session})}const Rn=[`xcodebuild .*AgentDeviceRunnerUITests/RunnerTests/testCommand`,`xcodebuild .*AgentDeviceRunner\\.env\\.session-`,`xcodebuild build-for-testing .*apple/runner/AgentDeviceRunner/AgentDeviceRunner\\.xcodeproj`];function zn(e){let t=ee(e.command);if(t.envelopeMs===`unbounded`)return;let n={...t,envelopeMs:t.envelopeMs};return Bn(n,e.positionals??[])??Vn(n,e.flags)??n.envelopeMs}function Bn(e,t){if(e.budget.source!==`positional-parser`)return;let n=e.budget.parser(t);return n===null?void 0:Un(e,n)}function Vn(e,t){if(e.budget.source===`flag`)return e.budget.envelope===`widen`?Hn(e,e.budget,t):typeof t?.timeoutMs==`number`?t.timeoutMs:e.envelopeMs}function Hn(e,t,n){if(n?.settle!==!0)return e.envelopeMs;let r=typeof n.timeoutMs==`number`?n.timeoutMs:t.defaultBudgetMs;return typeof r==`number`?Wn(e,r):e.envelopeMs}function Un(e,t){return Math.max(e.envelopeMs,t+Xn)}function Wn(e,t){return Math.max(e.envelopeMs,e.envelopeMs+t+Xn)}function Gn(e,t,n,i,a,o){let s=a?{terminated:0}:Jn(),c=!a&&Kn(i),l=c?Yn(e,t):{forcedKill:!1};return x({level:`error`,phase:`daemon_request_timeout`,data:{timeoutMs:o,requestId:n,command:i,timedOutRunnerPidsTerminated:s.terminated,timedOutRunnerCleanupError:s.error,daemonPidReset:c?e.pid:void 0,daemonPidForceKilled:c?l.forcedKill:void 0,daemonPreservedAfterTimeout:!a&&!c,daemonBaseUrl:e.baseUrl}}),new r(`COMMAND_FAILED`,`Daemon request timed out`,{timeoutMs:o,requestId:n,hint:qn({remote:a,resetDaemon:c,command:i})})}function Kn(e){return ee(e).onTimeout===`reset-daemon`}function qn(e){let{remote:t,resetDaemon:n,command:r}=e;if(t)return`Retry with --debug and verify the remote daemon URL, auth token, and remote host logs.`;if(!n){let e=r===g.snapshot?` If this was the first Apple-platform snapshot on the device, run agent-device prepare ios-runner with the same --platform before snapshot/test so runner startup is handled explicitly.`:``;return`Retry with --debug and check daemon diagnostics logs. The timed-out ${r??`request`} request was canceled and Apple runner work was aborted when detected; the daemon was kept alive so the session can still be closed or inspected.${e}`}return`Retry with --debug and check daemon diagnostics logs. Timed-out Apple runner xcodebuild processes were terminated when detected.`}function Jn(){let e=0;try{for(let t of Rn)ze(`pkill`,[`-f`,t],{allowFailure:!0}).exitCode===0&&(e+=1);return{terminated:e}}catch(t){return{terminated:e,error:t instanceof Error?t.message:String(t)}}}function Yn(e,t){let n=!1;try{v(e.pid,e.processStartTime)&&(process.kill(e.pid,`SIGKILL`),n=!0)}catch{W(e)}finally{B(t.infoPath),V(t.lockPath)}return{forcedKill:n}}const Xn=3e4,Zn=`Daemon HTTP endpoint is unavailable`,Qn=`Daemon socket endpoint is unavailable`;async function $n(e,t){let n=cr(e,t);if(await er(e,n))return!0;let r=lr(e,t,n);return r?await er(e,r):!1}async function er(e,t){return t===`http`?await nr(e):await tr(e.port)}function tr(e){return e?new Promise(t=>{let n=!1,r=k.createConnection({host:`127.0.0.1`,port:e},()=>{i(!0)}),i=e=>{n||(n=!0,r.destroy(),t(e))};r.setTimeout(500),r.on(`timeout`,()=>{i(!1)}),r.on(`error`,()=>{i(!1)})}):Promise.resolve(!1)}function nr(e){return ir(e).then(e=>e.reachable)}async function rr(e){let t=await ir(e);if(!e.baseUrl||!t.reachable)return t;if(typeof t.rpcProtocolVersion==`number`&&t.rpcProtocolVersion!==2)throw new r(`COMMAND_FAILED`,`Remote daemon RPC protocol is incompatible`,{daemonBaseUrl:e.baseUrl,clientVersion:S(),remoteVersion:t.version,remoteService:t.service,supportedRpcProtocolVersion:2,remoteRpcProtocolVersion:t.rpcProtocolVersion,hint:`Upgrade agent-device on the client or remote host so both support the same daemon RPC protocol.`});return t}function ir(e){let t=e.baseUrl?Oe(e.baseUrl,`health`):e.httpPort?`http://127.0.0.1:${e.httpPort}/health`:null;if(!t)return Promise.resolve({reachable:!1});let n=new URL(t),r=n.protocol===`https:`?D:E,i=e.baseUrl?3e3:500;return new Promise(t=>{let a=e.baseUrl?y(e.token):{},o=r.request({protocol:n.protocol,host:n.hostname,port:n.port,path:n.pathname+n.search,method:`GET`,timeout:i,headers:a},e=>{let n=``;e.setEncoding(`utf8`),e.on(`data`,e=>{n+=e}),e.on(`end`,()=>{let r=e.statusCode??500;t({reachable:r<500,statusCode:r,...ar(n)})})});o.on(`timeout`,()=>{o.destroy(),t({reachable:!1})}),o.on(`error`,()=>{t({reachable:!1})}),o.end()})}function ar(e){try{let t=JSON.parse(e);return{service:typeof t.service==`string`?t.service:void 0,version:typeof t.version==`string`?t.version:void 0,rpcProtocolVersion:typeof t.rpcProtocolVersion==`number`?t.rpcProtocolVersion:void 0}}catch{return{}}}async function or(e,t,n,r,i,a={}){let o=cr(e,n);try{return await sr(e,t,r,i,o,a)}catch(s){let c=lr(e,n,o);if(!c||!ur(s,o))throw s;return await sr(e,t,r,i,c,a)}}async function sr(e,t,n,r,i,a){return i===`http`?await mr(e,t,n,r,a):await pr(e,t,n,r,a)}function cr(e,t){if(e.baseUrl){if(t===`socket`)throw new r(`COMMAND_FAILED`,`Remote daemon endpoint only supports HTTP transport`,{daemonBaseUrl:e.baseUrl});return`http`}if(t===`http`||t===`socket`)return dr(e,t);let n=(e.transport===`socket`||e.transport===`dual`?[`socket`,`http`]:[`http`,`socket`]).find(t=>K(e,t));if(n)return n;throw new r(`COMMAND_FAILED`,`Daemon metadata has no reachable transport`)}function K(e,t){return t===`http`?!!e.httpPort:!!e.port}function lr(e,t,n){if(t!==`auto`||e.baseUrl)return null;let r=n===`socket`?`http`:`socket`;return K(e,r)?r:null}function ur(e,t){return t===`socket`&&e instanceof r&&e.code===`COMMAND_FAILED`&&e.message===`Failed to communicate with daemon`&&e.details?.daemonSocketRequestWritten===!1}function dr(e,t){if(K(e,t))return t;throw new r(`COMMAND_FAILED`,t===`http`?Zn:Qn)}function fr(e,t,n,i={}){return x({level:`error`,phase:`daemon_request_socket_error`,data:{requestId:t,message:e instanceof Error?e.message:String(e)}}),new r(`COMMAND_FAILED`,`Failed to communicate with daemon`,{...i,requestId:t,hint:n?`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 pr(e,t,n,i,a){let o=e.port;if(!o)throw new r(`COMMAND_FAILED`,Qn);return new Promise((r,s)=>{let c=!1,l=k.createConnection({host:`127.0.0.1`,port:o},()=>{c=!0,l.write(`${JSON.stringify(t)}\n`)}),u=!1,d=typeof i==`number`?setTimeout(()=>{u=!0,l.destroy(),s(Gn(e,n,t.meta?.requestId,t.command,!1,i))},i):void 0;On(l,{req:t,onProgress:a.onProgress,isSettled:()=>u,clearTimeout:()=>{d&&clearTimeout(d)},resolve:e=>{u=!0,r(e)},reject:e=>{u=!0,s(e)}}),l.on(`error`,e=>{u||(u=!0,d&&clearTimeout(d),s(fr(e,t.meta?.requestId,!1,{daemonSocketRequestWritten:c})))})})}async function mr(e,t,n,i,a){let o=e.baseUrl?new URL(Oe(e.baseUrl,`rpc`)):e.httpPort?new URL(`http://127.0.0.1:${e.httpPort}/rpc`):null;if(!o)throw new r(`COMMAND_FAILED`,Zn);let s=JSON.stringify(Pn(t,{includeTokenParam:!e.baseUrl})),c={"content-type":`application/json`,"content-length":Buffer.byteLength(s)};return e.baseUrl&&Object.assign(c,y(e.token)),await new Promise((l,u)=>{let d=(o.protocol===`https:`?D:E).request({protocol:o.protocol,host:o.hostname,port:o.port,method:`POST`,path:o.pathname+o.search,headers:c},n=>{if(Dn(t,n.headers?.[`content-type`])){kn(n,{req:t,onProgress:a.onProgress,reject:u,clearTimeout:()=>{p&&clearTimeout(p)},handleResponseBody:n=>An(n,{info:e,req:t,resolve:l,reject:u})});return}ge(n).then(n=>{p&&clearTimeout(p),An(n,{info:e,req:t,resolve:l,reject:u})}).catch(e=>{p&&clearTimeout(p),u(new r(`COMMAND_FAILED`,`Failed to read daemon response`,{requestId:t.meta?.requestId},e instanceof Error?e:void 0))})}),f=bn(e),p=typeof i==`number`?setTimeout(()=>{d.destroy(),u(Gn(e,n,t.meta?.requestId,t.command,f,i))},i):void 0;d.on(`error`,e=>{p&&clearTimeout(p),u(fr(e,t.meta?.requestId,f))}),d.write(s),d.end()})}const q=15e3,J=new k.BlockList;J.addSubnet(`127.0.0.0`,8,`ipv4`),J.addAddress(`::1`,`ipv6`),J.addSubnet(`::ffff:127.0.0.0`,104,`ipv6`);function hr(e,t){let n=gr(e),r=_r(e,t),i=vr(e,r.remoteBaseUrl),a=yr(e,n,r.rawBaseUrl);return{paths:b(a?br():n),transportPreference:i.preference,serverMode:i.serverMode,ownedStateDir:a,remoteBaseUrl:r.remoteBaseUrl,remoteAuthToken:r.authToken}}function gr(e){return e.flags?.stateDir??process.env.AGENT_DEVICE_STATE_DIR}function _r(e,t){let n=e.flags?.daemonBaseUrl??process.env.AGENT_DEVICE_DAEMON_BASE_URL,r=Hr(n),i=t??process.env.AGENT_DEVICE_DAEMON_AUTH_TOKEN;return Ur(r,i),{rawBaseUrl:n,remoteBaseUrl:r,authToken:i}}function vr(e,t){let n=e.flags?.daemonTransport??process.env.AGENT_DEVICE_DAEMON_TRANSPORT,i=Ae(n);if(t&&i===`socket`)throw new r(`INVALID_ARGS`,`Remote daemon base URL only supports HTTP transport. Remove --daemon-transport socket.`,{daemonBaseUrl:t});return{preference:i,serverMode:he(e.flags?.daemonServerMode??process.env.AGENT_DEVICE_DAEMON_SERVER_MODE??(n===`dual`?`dual`:void 0))}}function yr(e,t,n){return Pr(e.command)&&!t&&!n}function br(){return T.mkdtempSync(w.join(Je.tmpdir(),`agent-device-replay-daemon-`))}async function xr(e){if(e.remoteBaseUrl)return await Sr(e);let t=await Cr(e);return t?{info:t,startedByClient:!1}:(vn(e.paths),await kr(e))}async function Sr(e){let t={transport:`http`,token:e.remoteAuthToken??``,pid:0,baseUrl:e.remoteBaseUrl};if((await rr(t)).reachable)return{info:t,startedByClient:!1};throw new r(`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. If this CLI was connected with connect proxy, run agent-device disconnect to return to the local daemon.`})}async function Cr(e){let t=I(e.paths.infoPath);if(!t)return null;let n=await wr(t,e.transportPreference);return Er(t,n)?t:(Dr(t,n,e.paths.baseDir),await W(t),B(e.paths.infoPath),null)}async function wr(e,t){try{return await $n(e,t)}catch(e){if(Tr(e))return!1;throw e}}function Tr(e){return e instanceof r&&e.code===`COMMAND_FAILED`&&(e.message===`Daemon HTTP endpoint is unavailable`||e.message===`Daemon socket endpoint is unavailable`)}function Er(e,t){return e.version===S()&&e.codeSignature===Y()&&t}function Dr(e,t,n){try{let r=e.version?`pid ${e.pid}, v${e.version}`:`pid ${e.pid}`,i=Or(e,t);process.stderr.write(`Replacing daemon (${r}) in ${n}: ${i}\n`)}catch{}}function Or(e,t){return e.version===S()?e.codeSignature===Y()?t?`not reusable`:`unreachable`:`code-signature mismatch`:`version mismatch (client v${S()})`}async function kr(e){let t=0,n=[],i,a;for(let r=1;r<=2;r+=1){let o;try{o=Rr(e),a={pid:o.pid}}catch(t){if(i=t instanceof Error?t.message:String(t),n.push(await H(e.paths,`start_error`)),r<2){await C(150);continue}break}let s=await Lr(q,e,o);if(s.kind===`ready`)return{info:s.info,startedByClient:!0};if(s.kind===`early_exit`){if(a=s.exit,i=Br(s.exit),n.push(await H(e.paths,`start_error`)),r<2){await C(150);continue}break}if(await yn(e.paths)){t+=1;continue}let c=U(e.paths),l=r<2,u=await H(e.paths,`startup_timeout`,{stopLiveProcesses:!1});if(n.push(u),u.retainedInfoProcess||u.retainedLockProcess){let t=await Lr(q,e,o);if(t.kind===`ready`)return{info:t.info,startedByClient:!0};t.kind===`early_exit`&&(a=t.exit,i=Br(t.exit));break}if(!l)break;!c.hasInfo&&!c.hasLock&&await C(150)}let o=U(e.paths),s=Vr(e.paths.logPath);throw new r(`COMMAND_FAILED`,`Failed to start daemon`,{kind:`daemon_startup_failed`,stateDir:e.paths.baseDir,infoPath:e.paths.infoPath,lockPath:e.paths.lockPath,logPath:e.paths.logPath,startupTimeoutMs:q,startupAttempts:2,lockRecoveryCount:t,cleanupResults:n,startError:i,daemonProcess:a,...s?{daemonLogTail:s}:{},metadataState:o,hint:xn(o,e.paths)})}async function Ar(e,t,n,r){if(!Pr(e.command)||!t.startedByClient&&!n.ownedStateDir||bn(t.info)||Mr(r)||Fr(e,r))return r;let i={pid:t.info.pid,removedInfo:!1,removedLock:!1,removedStateDir:!1,error:void 0},a=r;try{await W(t.info)}catch(e){i.error=e instanceof Error?e.message:String(e)}finally{let e=T.existsSync(n.paths.infoPath);B(n.paths.infoPath),i.removedInfo=e&&!T.existsSync(n.paths.infoPath);let t=T.existsSync(n.paths.lockPath);if(V(n.paths.lockPath),i.removedLock=t&&!T.existsSync(n.paths.lockPath),n.ownedStateDir){let e=ke(n.paths.sessionsDir);e?a=jr(r,e):(T.rmSync(n.paths.baseDir,{recursive:!0,force:!0}),i.removedStateDir=!T.existsSync(n.paths.baseDir))}}return x({level:i.error?`warn`:`info`,phase:`daemon_replay_cleanup`,data:i}),a}function jr(e,n){if(e&&!e.ok)return e;let{sessionName:i,tombstone:a}=n,o=a.sourcePath?`re-run: replay ${a.sourcePath} --save-script`:`re-run your replay <script> --save-script from the start`;return{ok:!1,error:t(new r(`REPAIR_COMMIT_FAILED`,`The repair transaction for session "${i}" completed, but committing its healed script failed at teardown: ${a.commitFailure.message}. ${o}.`))}}function Mr(e){if(!e||e.ok||e.error.code!==`REPLAY_DIVERGENCE`)return!1;let t=e.error.details?.divergence;if(!t||typeof t!=`object`)return!1;let n=t.resume;return!n||typeof n!=`object`?!1:n.repairSessionHeld===!0}function Nr(e,t){let n=`This repair session's daemon was kept alive to continue the repair; pass --state-dir ${t} on your next command (press, replay --from, or close --save-script) to reach it.`,r=e.error.hint;return{...e,error:{...e.error,hint:r?`${r} ${n}`:n}}}function Pr(e){return e===g.replay||e===g.test}function Fr(e,t){return e.command!==g.replay||!t||!t.ok?!1:t.data?.sessionActive===!0}function Ir(e,t){let n=e.data??{},r=typeof n.session==`string`?n.session:void 0,i=[...t?[`--state-dir ${be(t)}`]:[],...r?[`--session ${be(r)}`]:[]];if(i.length===0)return e;let a=`This session's daemon was kept alive because its script left the session active; pass ${i.join(` `)} on your next command to reach it.`,o=typeof n.message==`string`?n.message:void 0;return{...e,data:{...n,hint:a,message:o?`${o} ${a}`:a}}}async function Lr(e,t,n){let r=Date.now(),i;for(n.exited.then(e=>{i=e});Date.now()-r<e;){if(i)return{kind:`early_exit`,exit:i};let e=I(t.paths.infoPath);if(e&&await $n(e,t.transportPreference))return{kind:`ready`,info:e};if(i)return{kind:`early_exit`,exit:i};await C(100)}return{kind:`timeout`}}function Rr(e){let t=zr(),n=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};T.mkdirSync(e.paths.baseDir,{recursive:!0});let i=T.openSync(e.paths.logPath,`a`),a=T.openSync(e.paths.logPath,`a`);try{return He(process.execPath,n,{env:r,stdio:[`ignore`,i,a]})}finally{T.closeSync(i),T.closeSync(a)}}function zr(){let e=Ue(),t=[w.join(e,`dist`,`src`,`internal`,`daemon.js`),w.join(e,`dist`,`src`,`daemon.js`)],n=t[0];if(n===void 0)throw new r(`COMMAND_FAILED`,`Daemon dist path list is empty`);let i=t.find(e=>T.existsSync(e))??n,a=w.join(e,`src`,`daemon.ts`),o=t.some(e=>T.existsSync(e)),s=T.existsSync(a);if(!o&&!s)throw new r(`COMMAND_FAILED`,`Daemon entry not found`,{distPaths:t,srcPath:a});return{root:e,distPath:i,distPaths:t,srcPath:a,useSrc:(process.execArgv.includes(`--experimental-strip-types`)||!o)&&s}}function Y(){let e=zr();return ye(e.useSrc?e.srcPath:e.distPath,e.root)}function Br(e){return e.error?`daemon process ${e.pid} failed to start: ${e.error}`:e.signal?`daemon process ${e.pid} exited before readiness with signal ${e.signal}`:`daemon process ${e.pid} exited before readiness with code ${e.exitCode??0}`}function Vr(e){try{if(!T.existsSync(e))return;let t=T.statSync(e);if(t.size<=0)return;let n=Math.min(t.size,64e3),r=T.openSync(e,`r`);try{let e=Buffer.alloc(n);T.readSync(r,e,0,n,t.size-n);let i=e.toString(`utf8`).trim();return i.length>0?i:void 0}finally{T.closeSync(r)}}catch{return}}function Hr(e){if(!e)return;let t;try{t=new URL(e)}catch(t){throw new r(`INVALID_ARGS`,`Invalid daemon base URL`,{daemonBaseUrl:e},t instanceof Error?t:void 0)}if(t.protocol!==`http:`&&t.protocol!==`https:`)throw new r(`INVALID_ARGS`,`Daemon base URL must use http or https`,{daemonBaseUrl:e});return t.toString().replace(/\/+$/,``)}function Ur(e,t){if(!e)return;let n=new URL(e).hostname;if(!Wr(n)&&!(typeof t==`string`&&t.trim().length>0))throw new r(`INVALID_ARGS`,`Remote daemon base URL for non-loopback hosts requires daemon authentication`,{daemonBaseUrl:e,hint:`Provide --daemon-auth-token or AGENT_DEVICE_DAEMON_AUTH_TOKEN when using a non-loopback remote daemon URL.`})}function Wr(e){let t=e.trim().toLowerCase().replace(/^\[(.*)\]$/,`$1`);return t===`localhost`?!0:k.isIPv4(t)?J.check(t,`ipv4`):k.isIPv6(t)?J.check(t,`ipv6`):!1}async function Gr(e,t={}){let n=e.meta?.requestId??Re(),r=!!(e.meta?.debug||e.flags?.verbose),i=e.flags,{daemonAuthToken:a,...o}=i??{},s=i?{...e,flags:o}:e,c=hr(s,t.authToken??a),l=zn(s),u=await Be(`daemon_startup`,async()=>await xr(c),{requestId:n,session:e.session}),d=u.info,f=await Yt(s,d);$r(s.command);let p=Kr(s,f,d.token,n,r);return x({level:`info`,phase:`daemon_request_prepare`,data:{requestId:n,command:s.command,session:s.session}}),await Xr(s,u,c,async()=>Qr(Zr(await Be(`daemon_request`,async()=>await or(d,p,c.transportPreference,c.paths,l,t.onProgress?{onProgress:t.onProgress}:void 0),{requestId:n,command:e.command}),c),s,c))}function Kr(e,t,n,r,i){return{...e,positionals:t.positionals,flags:t.flags,token:n,meta:qr(e,t,r,i)}}function qr(e,t,n,r){let i=e.meta??{};return{...i,requestId:n,debug:r,...Jr(i,e.flags),...Yr(t)}}function Jr(e,t){return{includeCost:e.includeCost,cwd:e.cwd,sessionExplicit:e.sessionExplicit,tenantId:e.tenantId??t?.tenant,runId:e.runId??t?.runId,leaseId:e.leaseId??t?.leaseId,sessionIsolation:e.sessionIsolation??t?.sessionIsolation,lockPolicy:e.lockPolicy,lockPlatform:e.lockPlatform}}function Yr(e){return{...e.uploadedArtifactId?{uploadedArtifactId:e.uploadedArtifactId}:{},...e.clientArtifactPaths?{clientArtifactPaths:e.clientArtifactPaths}:{},...e.installSource?{installSource:e.installSource}:{}}}async function Xr(e,t,n,i){let a,o=!1,s;try{a=await i()}catch(e){o=!0,s=e}let c=await Ar(e,t,n,a);if(o)throw s;if(!c)throw new r(`COMMAND_FAILED`,`Daemon request produced no response after cleanup`);return c}function Zr(e,t){return e.ok||!t.ownedStateDir||!Mr(e)?e:Nr(e,t.paths.baseDir)}function Qr(e,t,n){return!e.ok||!Fr(t,e)?e:Ir(e,n.ownedStateDir?n.paths.baseDir:void 0)}function $r(e){!ei(e)||process.stderr.isTTY!==!0||process.env.CI||process.stderr.write(e===g.reinstall?`Reinstalling...
|
|
2
2
|
`:`Installing...
|
|
3
|
-
`)}function ei(e){return e===
|
|
3
|
+
`)}function ei(e){return e===g.install||e===g.reinstall||e===h.installSource}function X(e,t){return w.join(e,`metro-sessions`,`${Te(t)}.json`)}function ti(e){let t=X(e.stateDir,e.session);T.mkdirSync(w.dirname(t),{recursive:!0}),T.writeFileSync(t,`${JSON.stringify(e.hints,null,2)}\n`,`utf8`)}function ni(e){let t=X(e.stateDir,e.session),n;try{n=T.readFileSync(t,`utf8`)}catch{return}let r;try{r=JSON.parse(n)}catch{return}if(!r||typeof r!=`object`||Array.isArray(r))return;let i=r,a={};return typeof i.metroHost==`string`&&i.metroHost&&(a.metroHost=i.metroHost),typeof i.metroPort==`number`&&Number.isInteger(i.metroPort)&&(a.metroPort=i.metroPort),typeof i.bundleUrl==`string`&&i.bundleUrl&&(a.bundleUrl=i.bundleUrl),Object.keys(a).length>0?a:void 0}function ri(e){T.rmSync(X(e.stateDir,e.session),{force:!0})}var ii=e({createAgentDeviceClient:()=>ai});function ai(e={},t={}){let n=t.transport??Gr,o=t=>i(t.responseLevel??e.responseLevel),s=async(t,r=[],i={},o,s)=>{let c=Q(e,i),l={session:j(c.session),command:t,positionals:r,...s?{input:s}:{},flags:Ie(c,o),runtime:c.runtime,meta:ut(c)},u=await n(l,{authToken:c.daemonAuthToken});return u.ok||a(u.error),u.data??{}},l=async(e={})=>{let t=await s(h.sessionList,[],e);return(Array.isArray(t.sessions)?t.sessions:[]).map(tt)},u=async(e,t={})=>{let n=pt(e,t);return await s(n.command,n.positionals,n.options,n.metadataFlags,n.input)},d=(t={})=>j(Q(e,t).session);return{command:{wait:async e=>await u(`wait`,e),alert:async(e={})=>await u(`alert`,e),...gi(u),reactNative:async e=>await u(`react-native`,e),doctor:async(e={})=>await u(`doctor`,e),prepare:async e=>await u(`prepare`,e),viewport:async e=>await u(`viewport`,e)},devices:{list:async(e={})=>{let t=await u(`devices`,e);return(Array.isArray(t.devices)?t.devices:[]).map(et)},capabilities:async(e={})=>{let t=await u(`capabilities`,e),n=Array.isArray(t.availableCommands)?t.availableCommands.filter(e=>typeof e==`string`):[];return{device:et(t.device),availableCommands:n}},boot:async(e={})=>await u(`boot`,e),shutdown:async(e={})=>await u(`shutdown`,e)},sessions:{list:async(e={})=>await l(e),stateDir:async(t={})=>b(Q(e,t).stateDir??process.env.AGENT_DEVICE_STATE_DIR).baseDir,close:async(t={})=>{let n=d(t);try{let e=await u(`close`,t);return{session:n,shutdown:st(e.shutdown),provider:Z(e.provider),savedScript:m(e,`savedScript`),identifiers:{session:n}}}finally{xi(e,t)}},saveScript:async(e={})=>{let t=await s(h.sessionSaveScript,e.path===void 0?[]:[e.path],e,{force:e.force}),n=t.actionCount;if(typeof n!=`number`||!Number.isInteger(n)||n<0)throw new r(`COMMAND_FAILED`,`Daemon returned an invalid saved-script action count.`);let i=c(t,`session`);return{session:i,savedScript:c(t,`savedScript`),actionCount:n,identifiers:{session:i}}},artifacts:async(e={})=>await u(`artifacts`,e)},apps:{install:async e=>Ze(await u(`install`,e),d(e)),reinstall:async e=>Ze(await u(`reinstall`,e),d(e)),installFromSource:async e=>Qe(await u(`install-from-source`,e),d(e)),list:async(e={})=>{let t=await u(`apps`,e);return Array.isArray(t.apps)?t.apps.filter(e=>typeof e==`string`):[]},open:async t=>{let n=d(t),r=await u(`open`,t);bi({config:e,options:t,runtime:Q(e,t).runtime,sessionReused:r.sessionReused===!0});let i=at(r),a=m(r,`appBundleId`),o=a,s=Array.isArray(r.warnings)?r.warnings.filter(e=>typeof e==`string`):[];return{session:n,...s.length>0?{warnings:s}:{},sessionStateDir:m(r,`sessionStateDir`),runnerLogPath:m(r,`runnerLogPath`),requestLogPath:m(r,`requestLogPath`),eventLogPath:m(r,`eventLogPath`),appName:m(r,`appName`),appBundleId:a,appId:o,startup:ot(r.startup),runtime:it(r.runtime),device:i,identifiers:{session:n,deviceId:i?.id,deviceName:i?.name,udid:i?.ios?.udid,serial:i?.android?.serial,appId:o,appBundleId:a}}},close:async(e={})=>{let t=d(e),n=await u(`close`,e);return{session:t,closedApp:e.app,shutdown:st(n.shutdown),savedScript:m(n,`savedScript`),identifiers:{session:t}}},push:async e=>await u(`push`,e),triggerEvent:async e=>await u(`trigger-app-event`,e)},materializations:{release:async e=>$e(await s(h.releaseMaterializedPaths,[],{...e,materializationId:e.materializationId}))},leases:{allocate:async e=>Si(await s(h.leaseAllocate,[],{...e,leaseId:void 0})),heartbeat:async e=>Si(await s(h.leaseHeartbeat,[],e)),release:async e=>{let t=await s(h.leaseRelease,[],e);return{released:t.released===!0,provider:Z(t.provider)}}},metro:{prepare:async t=>{let n=await Ge({projectRoot:t.projectRoot??e.cwd,kind:t.kind,publicBaseUrl:t.publicBaseUrl,proxyBaseUrl:t.proxyBaseUrl,proxyBearerToken:t.bearerToken,bridgeScope:t.bridgeScope,launchUrl:t.launchUrl,companionProfileKey:t.companionProfileKey,companionConsumerKey:t.companionConsumerKey,metroPort:t.port,listenHost:t.listenHost,statusHost:t.statusHost,startupTimeoutMs:t.startupTimeoutMs,probeTimeoutMs:t.probeTimeoutMs,reuseExisting:t.reuseExisting,installDependenciesIfNeeded:t.installDependenciesIfNeeded,runtimeFilePath:t.runtimeFilePath,logPath:t.logPath});return _i(e,n),n},reload:async(t={})=>await We({metroHost:t.metroHost,metroPort:t.metroPort,bundleUrl:t.bundleUrl,runtime:e.runtime??vi(e),timeoutMs:t.timeoutMs})},capture:{snapshot:async(e={})=>{let t=d(e),n=await u(`snapshot`,e);return o(e)?n:mi(n,t)},screenshot:async(e={})=>{let t=d(e),n=await u(`screenshot`,e);if(o(e))return n;let r=we(n);return{path:c(n,`path`),width:r?.width,height:r?.height,logicalWidth:r?.logicalWidth,logicalHeight:r?.logicalHeight,pixelDensity:r?.pixelDensity,overlayRefs:r?.overlayRefs,identifiers:{session:t}}},diff:async e=>await u(`diff`,e)},interactions:{click:async e=>await u(`click`,e),press:async e=>await u(`press`,e),longPress:async e=>await u(`longpress`,e),swipe:async e=>await u(`swipe`,e),pan:async e=>await u(`gesture`,oi(e)),drag:async e=>await u(`gesture`,si(e)),fling:async e=>await u(`gesture`,ci(e)),swipeGesture:async e=>await u(`gesture`,li(e)),focus:async e=>await u(`focus`,e),type:async e=>await u(`type`,e),fill:async e=>await u(`fill`,e),scroll:async e=>await u(`scroll`,e),pinch:async e=>await u(`gesture`,ui(e)),rotateGesture:async e=>await u(`gesture`,di(e)),transformGesture:async e=>await u(`gesture`,fi(e)),get:async e=>await u(`get`,e),is:async e=>await u(`is`,e),find:async e=>await u(`find`,e)},replay:{run:async e=>await u(`replay`,e),test:async e=>await u(`test`,e)},batch:{run:async e=>await u(`batch`,e)},observability:{perf:async(e={})=>await u(`perf`,e),logs:async(e={})=>await u(`logs`,e),events:async(e={})=>await u(`events`,e),network:async(e={})=>await u(`network`,e),audio:async(e={})=>await u(`audio`,e)},debug:{symbols:async t=>{let{symbolicateCrashArtifact:n}=await import(`./debug-symbols.js`);return n({cwd:t.cwd??e.cwd,...t})}},recording:{record:async e=>await u(`record`,e),trace:async e=>await u(`trace`,e)},settings:{update:async e=>await u(`settings`,e)}}}function oi(e){let{x:t,y:n,dx:r,dy:i,...a}=e;return{...a,kind:`pan`,origin:{x:t,y:n},delta:{x:r,y:i}}}function si(e){return{...e,kind:`drag`}}function ci(e){let{x:t,y:n,...r}=e;return{...r,kind:`fling`,origin:{x:t,y:n}}}function li(e){return{...e,kind:`swipe`}}function ui(e){let{x:t,y:n,...r}=e;return pi(t,n,`pinch`),{...r,kind:`pinch`,...t===void 0&&n===void 0?{}:{origin:{x:t,y:n}}}}function di(e){let{x:t,y:n,...r}=e;return pi(t,n,`rotate`),{...r,kind:`rotate`,...t===void 0&&n===void 0?{}:{origin:{x:t,y:n}}}}function fi(e){let{x:t,y:n,dx:r,dy:i,...a}=e;return{...a,kind:`transform`,origin:{x:t,y:n},delta:{x:r,y:i}}}function pi(e,t,n){if(e===void 0!=(t===void 0))throw new r(`INVALID_ARGS`,`gesture ${n} center requires both x and y`)}function mi(e,t){let n=m(e,`appBundleId`);return{nodes:lt(e.nodes),truncated:e.truncated===!0,appName:m(e,`appName`),appBundleId:n,...hi(e),identifiers:{session:t,appId:n,appBundleId:n}}}function hi(e){let t=Z(e.visibility),n=Z(e.unchanged),r=s(e.snapshotDiagnostics);return{...t?{visibility:t}:{},...o(e),...n?{unchanged:n}:{},...r?{snapshotDiagnostics:r}:{},...typeof e.refsGeneration==`number`?{refsGeneration:e.refsGeneration}:{}}}function gi(e){let t={};for(let[n,r]of Object.entries(Me.clientCommandMethods??{}))t[n]=async(t={})=>await e(r,t);let n=t.orientation;if(!n)throw Error(`orientation client method missing from the system command family`);return t.rotate=async(e={})=>({...await n(e),action:`rotate`}),t}function Z(e){return p(e)?e:void 0}function Q(e,t){return{...e,...t}}function $(e,t={}){let n=Q(e,t);return{stateDir:b(n.stateDir??process.env.AGENT_DEVICE_STATE_DIR).baseDir,session:j(n.session)}}function _i(e,t){try{let n=new URL(t.statusUrl),r=Number.parseInt(n.port,10);if(!n.hostname||!Number.isInteger(r))return;let i=t.bridge?void 0:t.iosRuntime.bundleUrl??t.androidRuntime.bundleUrl;ti({...$(e),hints:{metroHost:n.hostname,metroPort:r,bundleUrl:i}})}catch{}}function vi(e){try{return ni($(e))}catch{return}}function yi(e){if(!e)return;let{metroHost:t,metroPort:n,bundleUrl:r}=e;if(!(t===void 0&&n===void 0&&r===void 0))return{metroHost:t,metroPort:n,bundleUrl:r}}function bi(e){try{let t=$(e.config,e.options),n=yi(e.runtime);if(n){ti({...t,hints:n});return}e.sessionReused||ri(t)}catch{}}function xi(e,t){try{ri($(e,t))}catch{}}function Si(e){let t=e.lease;if(!p(t))throw Error(`Invalid lease response from daemon`);return{leaseId:c(t,`leaseId`),tenantId:c(t,`tenantId`),runId:c(t,`runId`),backend:c(t,`backend`),leaseProvider:m(t,`leaseProvider`),clientId:m(t,`clientId`),deviceKey:m(t,`deviceKey`),createdAt:typeof t.createdAt==`number`?t.createdAt:void 0,heartbeatAt:typeof t.heartbeatAt==`number`?t.heartbeatAt:void 0,expiresAt:typeof t.expiresAt==`number`?t.expiresAt:void 0}}export{hr as a,xr as i,ai as n,Gr as r,ii as t};
|
package/dist/src/android.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
import{o as e}from"./png-worker-contract.js";import{_ as t}from"./sdk-contracts.js";import{
|
|
1
|
+
import{o as e}from"./png-worker-contract.js";import{_ as t}from"./sdk-contracts.js";import{_ as n,f as r,v as i,xt as a}from"./screenshot-geometry.js";import{I as o,d as s,n as c}from"./sdk-android-adb.js";import{t as ee}from"./timeouts.js";import{c as l,d as u,l as d,n as f}from"./app-lifecycle.js";import{a as p}from"./install-artifact.js";import{a as m,s as h}from"./device-input-state.js";import{c as g,d as te,f as _,h as v,i as y,l as b,m as x,n as S,o as C,p as w,r as T,t as E,u as D}from"./input-actions.js";import{f as O}from"./ime-lifecycle.js";import{n as k,r as A,t as j}from"./setting-state.js";import{t as M}from"./method-scope.js";import{promises as N}from"node:fs";const P=[`window_animation_scale`,`transition_animation_scale`,`animator_duration_scale`];async function F(e,i,a,o,s){switch(i.toLowerCase()){case`wifi`:await p(e,[`shell`,`svc`,`wifi`,j(a)?`enable`:`disable`]);return;case`airplane`:{let t=j(a),n=t?`1`:`0`,r=t?`true`:`false`;await p(e,[`shell`,`settings`,`put`,`global`,`airplane_mode_on`,n]),await p(e,[`shell`,`am`,`broadcast`,`-a`,`android.intent.action.AIRPLANE_MODE`,`--ez`,`state`,r]);return}case`location`:if(a.toLowerCase()===`set`){if(e.kind!==`emulator`)throw new t(`UNSUPPORTED_OPERATION`,`Android precise location coordinates are supported only on emulators.`,{deviceId:e.id,hint:`Use an Android emulator for adb emu geo fix, or configure location through device/provider tooling.`});let{latitude:n,longitude:i}=r(s);return await p(e,[`emu`,`geo`,`fix`,String(i),String(n)]),{latitude:n,longitude:i}}await p(e,[`shell`,`settings`,`put`,`secure`,`location_mode`,j(a)?`3`:`0`]);return;case`animations`:{let t=j(a)?`1`:`0`;for(let n of P)await p(e,[`shell`,`settings`,`put`,`global`,n,t]);return{scale:t,keys:[...P]}}case`appearance`:await p(e,[`shell`,`cmd`,`uimode`,`night`,await B(e,a)===`dark`?`yes`:`no`]);return;case`clear-app-state`:{if(a.toLowerCase()!==`clear`)throw new t(`INVALID_ARGS`,`settings clear-app-state only supports clear.`);if(!o)throw new t(`INVALID_ARGS`,`settings clear-app-state requires an app id or an active app session.`);let n=await u(e,o);if(n.type===`intent`)throw new t(`INVALID_ARGS`,`settings clear-app-state requires a package name, not an intent.`);await p(e,[`shell`,`am`,`force-stop`,n.value],{allowFailure:!0});let r=await p(e,[`shell`,`pm`,`clear`,n.value],{allowFailure:!0});if(r.exitCode!==0||!/\bSuccess\b/i.test(r.stdout))throw new t(`COMMAND_FAILED`,`Failed to clear Android app data for ${n.value}`,{package:n.value,stdout:r.stdout,stderr:r.stderr,exitCode:r.exitCode});return{package:n.value,cleared:!0}}case`fingerprint`:await L(e,I(a));return;case`permission`:{if(!o)throw new t(`INVALID_ARGS`,`permission setting requires an active app in session`);let r=n(a),i=H(s?.permissionTarget,s?.permissionMode);if(i.kind===`notifications`){await W(e,o,r,i);return}let c=r===`grant`?`grant`:`revoke`;if(i.type===`photos`){let t=await U(e,o,c);r===`reset`&&await G(e,o,t);return}await p(e,[`shell`,`pm`,c,o,i.value]),r===`reset`&&await G(e,o,i.value);return}default:throw new t(`INVALID_ARGS`,`Unsupported setting: ${i}`)}}function I(e){let n=e.trim().toLowerCase();if(n===`match`)return`match`;if(n===`nonmatch`)return`nonmatch`;throw new t(`INVALID_ARGS`,`Invalid fingerprint state: ${e}. Use match|nonmatch.`)}async function L(e,n){let r=R(e,n),i=[];for(let t of r){let n=await p(e,t,{allowFailure:!0});if(n.exitCode===0)return;i.push({args:t,stdout:n.stdout,stderr:n.stderr,exitCode:n.exitCode})}let a=A(i);throw i.length>0&&i.every(e=>z(e.stdout,e.stderr))?new t(`UNSUPPORTED_OPERATION`,`Android fingerprint simulation is not supported on this target/runtime.`,{deviceId:e.id,action:n,hint:`Use an Android emulator with biometric support, or a device/runtime that exposes cmd fingerprint.`,attempts:a}):new t(`COMMAND_FAILED`,`Failed to simulate Android fingerprint.`,{deviceId:e.id,action:n,attempts:a})}function R(e,t){let n=t===`match`?`1`:`9999`,r=[[`shell`,`cmd`,`fingerprint`,`touch`,n],[`shell`,`cmd`,`fingerprint`,`finger`,n]];return e.kind===`emulator`&&r.push([`emu`,`finger`,`touch`,n]),r}function z(e,t){let n=`${e}\n${t}`.toLowerCase();return n.includes(`unknown command`)||n.includes(`can't find service: fingerprint`)||n.includes(`service fingerprint was not found`)||n.includes(`fingerprint cmd unavailable`)||n.includes(`emu command is not supported`)||n.includes(`emulator console is not running`)||n.includes(`fingerprint`)&&n.includes(`not found`)}async function B(e,n){let r=k(n);if(r!==`toggle`)return r;let i=await p(e,[`shell`,`cmd`,`uimode`,`night`],{allowFailure:!0});if(i.exitCode!==0)throw c(`Failed to read current Android appearance`,i);let a=V(i.stdout,i.stderr);if(!a)throw new t(`COMMAND_FAILED`,`Unable to determine current Android appearance for toggle`,{stdout:i.stdout,stderr:i.stderr});return a===`auto`?`dark`:a===`dark`?`light`:`dark`}function V(e,t){let n=/night mode:\s*(yes|no|auto)\b/i.exec(`${e}\n${t}`);if(!n)return null;let r=n[1]?.toLowerCase();return r===`yes`?`dark`:r===`no`?`light`:r===`auto`?`auto`:null}function H(e,n){let r=i(e);if(n?.trim())throw new t(`INVALID_ARGS`,`Permission mode is only supported for photos. Received: ${n}.`);if(r===`camera`)return{kind:`pm`,value:`android.permission.CAMERA`,type:`camera`};if(r===`microphone`)return{kind:`pm`,value:`android.permission.RECORD_AUDIO`,type:`microphone`};if(r===`photos`)return{kind:`pm`,value:`android.permission.READ_MEDIA_IMAGES`,type:`photos`};if(r===`contacts`)return{kind:`pm`,value:`android.permission.READ_CONTACTS`,type:`contacts`};if(r===`notifications`)return{kind:`notifications`,appOps:`POST_NOTIFICATION`,permission:`android.permission.POST_NOTIFICATIONS`};throw new t(`INVALID_ARGS`,`Unsupported permission target on Android: ${e}. Use camera|microphone|photos|contacts|notifications.`)}async function U(e,n,r){let i=await K(e),a=i!==null&&i>=33?[`android.permission.READ_MEDIA_IMAGES`,`android.permission.READ_EXTERNAL_STORAGE`]:[`android.permission.READ_EXTERNAL_STORAGE`,`android.permission.READ_MEDIA_IMAGES`],o=[];for(let t of a){let i=await p(e,[`shell`,`pm`,r,n,t],{allowFailure:!0});if(i.exitCode===0)return t;o.push({permission:t,stderr:i.stderr,exitCode:i.exitCode})}throw new t(`COMMAND_FAILED`,`Failed to ${r} Android photos permission`,{appPackage:n,sdkInt:i,attempts:o})}async function W(e,t,n,r){let i=n===`grant`?`allow`:n===`deny`?`deny`:`default`;n===`grant`?await p(e,[`shell`,`pm`,`grant`,t,r.permission],{allowFailure:!0}):(await p(e,[`shell`,`pm`,`revoke`,t,r.permission],{allowFailure:!0}),n===`reset`&&await G(e,t,r.permission)),await p(e,[`shell`,`appops`,`set`,t,r.appOps,i])}async function G(e,t,n){await p(e,[`shell`,`pm`,`clear-permission-flags`,t,n,`user-set`],{allowFailure:!0}),await p(e,[`shell`,`pm`,`clear-permission-flags`,t,n,`user-fixed`],{allowFailure:!0})}async function K(e){let t=await p(e,[`shell`,`getprop`,`ro.build.version.sdk`],{allowFailure:!0});if(t.exitCode!==0)return null;let n=Number.parseInt(t.stdout.trim(),10);return!Number.isFinite(n)||n<=0?null:n}const q=Buffer.from([137,80,78,71,13,10,26,10]);async function J(e,t,n={}){if(n.stabilize===!1){await Z(e,t);return}await Y(e);try{await ee(1e3),await Z(e,t)}finally{await X(e).catch(()=>{})}}async function Y(e){let t=t=>p(e,[`shell`,t],{allowFailure:!0});await t(`settings put global sysui_demo_allowed 1`);let n=e=>t(`am broadcast -a com.android.systemui.demo -e command ${e}`);await n(`clock -e hhmm 0941`),await n(`notifications -e visible false`)}async function X(e){await p(e,[`shell`,`am broadcast -a com.android.systemui.demo -e command exit`],{allowFailure:!0})}async function Z(e,n){let r=await p(e,[`exec-out`,`screencap`,`-p`],{binaryStdout:!0});if(!r.stdoutBuffer)throw new t(`COMMAND_FAILED`,`Failed to capture screenshot`);let i=r.stdoutBuffer.indexOf(q);if(i<0)throw new t(`COMMAND_FAILED`,`Screenshot data does not contain a valid PNG header`);let a=Q(r.stdoutBuffer,i);if(!a)throw new t(`COMMAND_FAILED`,`Screenshot data does not contain a complete PNG payload`);await N.writeFile(n,r.stdoutBuffer.subarray(i,a))}function Q(e,t){let n=t+q.length;for(;n+8<=e.length;){let t=e.readUInt32BE(n),r=n+4,i=e.toString(`ascii`,r,r+4),a=n+12+t;if(a>e.length)return null;if(i===`IEND`)return a;n=a}return null}var ne=e({createAndroidInteractor:()=>$});function $(e,t,n){let r={open:(t,n)=>l(e,t,{activity:n?.activity,appBundleId:n?.appBundleId,launchArgs:n?.launchArgs,url:n?.url}),openDevice:()=>d(e),close:t=>f(e,t),tap:(t,n)=>b(e,t,n),doubleTap:async(t,n)=>{await b(e,t,n),await b(e,t,n)},longPress:(t,n,r)=>g(e,t,n,r),focus:(t,n)=>y(e,t,n),type:(t,n)=>w(e,t,n),fill:(t,n,r,i)=>T(e,t,n,r,i),scroll:(t,n)=>te(e,t,n),performGesture:t=>x(e,t),gestureViewport:()=>v(e),screenshot:(t,n)=>J(e,t,n),snapshot:async t=>{let r=t??{},i=await o(`snapshot_capture`,async()=>await O(e,{appBundleId:r.appBundleId,signal:r.signal??n?.signal,interactiveOnly:r.interactiveOnly,depth:r.depth,scope:r.scope,raw:r.raw,includeHiddenContentHints:r.includeHiddenContentHints,helperSessionScope:r.appBundleId?`daemon-session`:`command`}),{backend:`android`});return{nodes:i.nodes??[],truncated:i.truncated??!1,backend:`android`,...a(i)}},back:t=>S(e),home:()=>C(e),setOrientation:t=>_(e,t),appSwitcher:()=>E(e),tvRemote:(t,n)=>D(e,t,n),readClipboard:()=>m(e),writeClipboard:t=>h(e,t),setSetting:(t,n,r,i)=>F(e,t,n,r,i)};return t?M(r,n=>s(t,{serial:e.id},n)):r}export{$ as n,ne as t};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{
|
|
1
|
+
import{it as e}from"./internal/daemon.js";export{e as withAppLogProvider};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{o as e}from"./png-worker-contract.js";import{_ as t}from"./sdk-contracts.js";import{s as n}from"./sdk-batch-runner.js";import{c as r,s as i}from"./sdk-device.js";import{c as a}from"./install-artifact.js";import{n as o}from"./setting-state.js";import{i as s,r as c,s as l}from"./tool-provider.js";import{
|
|
1
|
+
import{o as e}from"./png-worker-contract.js";import{_ as t}from"./sdk-contracts.js";import{s as n}from"./sdk-batch-runner.js";import{c as r,s as i}from"./sdk-device.js";import{c as a}from"./install-artifact.js";import{n as o}from"./setting-state.js";import{i as s,r as c,s as l}from"./tool-provider.js";import{a as u,t as d}from"./physical-device-control.js";import{n as f}from"./helper.js";import p from"node:path";import{fileURLToPath as m}from"node:url";const h={settings:`com.apple.systempreferences`},g=/^[a-z0-9-]+(?:\.[a-z0-9-]+)+$/,_={platform:`macos`,deviceId:`host`,variant:`all`},v=a();function y(e){return g.test(e)}async function b(e){let n=e.trim(),r=h[n.toLowerCase()];if(r)return r;if(y(n))return n;let i=v.get(_,n);if(i)return i;let a=(await D(`all`)).filter(e=>e.name.toLowerCase()===n.toLowerCase()),o=a[0];if(o!==void 0&&a.length===1)return v.set(_,n,o.bundleId);throw a.length>1?new t(`INVALID_ARGS`,`Multiple apps matched "${e}"`,{matches:a}):new t(`APP_NOT_INSTALLED`,`No app found matching "${e}"`)}async function x(e,r,i){let a=i?.url?.trim();if(a){if(!n(a))throw new t(`INVALID_ARGS`,`open <app> <url> requires a valid URL target`);let e=i?.appBundleId??await b(r);await O().openBundle(e,a);return}let o=r.trim();if(n(o)){await O().openTarget(o);return}let s=i?.appBundleId??await b(o);await O().openBundle(s)}async function S(e,n){let r=await b(n),i=await f(r);if(!(!i.running||i.terminated||i.forceTerminated))throw new t(`COMMAND_FAILED`,`Failed to close macOS app ${n}`,{bundleId:r,running:i.running,terminated:i.terminated,forceTerminated:i.forceTerminated})}async function C(){return await O().readClipboard()}async function w(e){await O().writeClipboard(e)}async function T(){return await O().readDarkMode()}async function E(e){let t=o(e),n=t===`toggle`?!await T():t===`dark`;await O().setDarkMode(n)}async function D(e){return await O().listApps(e)}function O(){let e=c().macosHost;if(!e)throw new t(`UNSUPPORTED_OPERATION`,`macOS host provider is not available`);return e}var k=e({buildAppNotInstalledError:()=>F,findIosSimulatorInstalledApp:()=>I,invalidateIosAppResolutionCache:()=>N,listIosApps:()=>B,resolveIosApp:()=>P,resolveIosAppAlias:()=>L,resolveIosSimulatorDeepLinkBundleId:()=>R});const A={settings:`com.apple.Preferences`},j=a();function M(e){return{platform:`ios`,deviceId:e.id,variant:e.kind}}async function N(e,t){return await j.invalidateWhile(M(e),t)}async function P(e,n){if(r(e))return await b(n);let i=n.trim();if(i.includes(`.`))return i;let a=L(i);if(a!==i)return a;let o=M(e),s=j.get(o,i);if(s)return s;let c=(e.kind===`simulator`?await V(e):await d(e).listApps(e,`all`)).filter(e=>e.name.toLowerCase()===i.toLowerCase()),l=c[0];if(l!==void 0&&c.length===1)return j.set(o,i,l.bundleId);throw c.length>1?new t(`INVALID_ARGS`,`Multiple apps matched "${n}"`,{matches:c}):F(n)}function F(e){return new t(`APP_NOT_INSTALLED`,`No app found matching "${e}"`)}async function I(e,t){if(!i(e)||e.kind!==`simulator`||e.booted!==!0)return;let n=L(t.trim());if(!n)return;let r=await V(e);if(n.includes(`.`))return r.find(e=>e.bundleId===n)?.bundleId;let a=r.filter(e=>e.name.toLowerCase()===n.toLowerCase());return a.length===1?a[0]?.bundleId:void 0}function L(e){let t=e.trim();return A[t.toLowerCase()]??e}async function R(e,t){if(!i(e)||e.kind!==`simulator`)return;let n=z(t);if(!n)return;let r=await H(e),a=[];for(let e of r)e.bundleId.startsWith(`com.callstack.agentdevice.runner`)||e.path&&(await W(p.join(e.path,`Info.plist`))).has(n)&&a.push(e);let o=a.filter(e=>e.applicationType===`User`);if(o.length===1)return o[0]?.bundleId;if(!(o.length>1))return a.length===1?a[0]?.bundleId:void 0}function z(e){return/^([A-Za-z][A-Za-z0-9+.-]*):/.exec(e.trim())?.[1]?.toLowerCase()}async function B(e,t){return r(e)?await D(t):e.kind===`simulator`?l(await V(e),t):await d(e).listApps(e,t)}async function V(e){return(await H(e)).map(e=>({bundleId:e.bundleId,name:e.name}))}async function H(e){let t=(await u(e,[`listapps`,e.id],{allowFailure:!0})).stdout.trim();if(!t)return[];let n=null;if(t.startsWith(`{`))try{n=JSON.parse(t)}catch{n=null}if(!n&&t.startsWith(`{`))try{let e=await s(`plutil`,[`-convert`,`json`,`-o`,`-`,`-`],{allowFailure:!0,stdin:t});e.exitCode===0&&e.stdout.trim().startsWith(`{`)&&(n=JSON.parse(e.stdout))}catch{n=null}return n?Object.entries(n).map(([e,t])=>{let n=U(t);return{bundleId:e,name:t.CFBundleDisplayName??t.CFBundleName??e,...n?{path:n}:{},...t.ApplicationType?{applicationType:t.ApplicationType}:{}}}):[]}function U(e){if(e.Path)return e.Path;if(e.Bundle)try{return m(e.Bundle)}catch{return}}async function W(e){let t=await s(`plutil`,[`-convert`,`json`,`-o`,`-`,e],{allowFailure:!0});if(t.exitCode!==0)return new Set;try{let e=JSON.parse(t.stdout),n=new Set;for(let t of e.CFBundleURLTypes??[])if(Array.isArray(t.CFBundleURLSchemes))for(let e of t.CFBundleURLSchemes)typeof e==`string`&&e.trim()&&n.add(e.trim().toLowerCase());return n}catch{return new Set}}export{P as a,x as c,w as d,B as i,C as l,I as n,R as o,N as r,S as s,k as t,E as u};
|
package/dist/src/apps.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import{o as e}from"./png-worker-contract.js";import{_ as t}from"./sdk-contracts.js";import{
|
|
2
|
-
`).map(e=>e.trim()).filter(e=>e.length>0&&e!==`Current Status Bar Overrides:`&&!/^=+$/.test(e));for(let e of r){let r=/^DataNetworkType:\s+(\d+)$/.exec(e);if(r){let e=Number(r[1]),i=ke[e];if(!i)throw new t(`COMMAND_FAILED`,`Unsupported simulator data network type: ${e}`);n.dataNetwork=i;continue}let i=/^WiFi Mode:\s+(\d+),\s+WiFi Bars:\s+(\d+)$/.exec(e);if(i){let e=Ae[Number(i[1])];e&&(n.wifiMode=e),n.wifiBars=i[2];continue}let a=/^Cell Mode:\s+(\d+),\s+Cell Bars:\s+(\d+)$/.exec(e);if(a){let e=Number(a[1]),r=je[e];if(!r)throw new t(`COMMAND_FAILED`,`Unsupported simulator cellular mode: ${e}`);n.cellularMode=r,n.cellularBars=a[2];continue}let o=/^Operator Name:\s*(.*)$/.exec(e);if(o){n.operatorName=o[1]??``;continue}}return Object.keys(n).length===0?null:n}function Re(e){let t=[];return e.dataNetwork&&t.push(`--dataNetwork`,e.dataNetwork),e.wifiMode&&t.push(`--wifiMode`,e.wifiMode),e.wifiBars!==void 0&&(e.dataNetwork===`wifi`||e.wifiMode)&&t.push(`--wifiBars`,e.wifiBars),e.cellularMode&&t.push(`--cellularMode`,e.cellularMode),e.cellularBars!==void 0&&(e.cellularMode||ze(e.dataNetwork)||e.operatorName!==void 0)&&t.push(`--cellularBars`,e.cellularBars),e.operatorName!==void 0&&t.push(`--operatorName`,e.operatorName),t}function ze(e){return!!(e&&e!==`hide`&&e!==`wifi`)}function B(e,t,n){h({level:`warn`,phase:`ios_screenshot_status_bar_${t}`,data:{platform:e.platform,deviceKind:e.kind,deviceId:e.id,...T(n)}})}function V(e,t,n){return x(e,t,n)}const Be={ensureBooted:k,prepareStatusBarForScreenshot:Me,captureWithRetry:Ue,normalizeDensity:Ye,captureWithRunner:W,shouldFallbackToRunner:q},H=new Map,U=new Map;async function Ve(e,t,n={}){if(d(e)){await W(e,t,n.appBundleId,n.fullscreen,n.runnerOptions);return}if(e.kind===`simulator`){await He(e,t,n);return}await E(e).captureScreenshot(e,t,{appBundleId:n.appBundleId,fullscreen:n.fullscreen,runnerOptions:n.runnerOptions,runRunnerCommand:D})}async function He(e,n,r={}){if(e.kind!==`simulator`)throw new t(`UNSUPPORTED_OPERATION`,`Simulator screenshot fallback flow supports only iOS simulators`);let i={...Be,...r.deps??{}};r.skipIosSimulatorBootCheck||await i.ensureBooted(e);let a=async()=>{};if(r.normalizeStatusBar===!0)try{a=await i.prepareStatusBarForScreenshot(e)}catch(t){K(e,`prepare_failed`,t)}try{try{await i.captureWithRetry(e,n),await i.normalizeDensity(e,n,r.pixelDensity);return}catch(t){let a=t;if(r.skipIosSimulatorBootCheck&&Je(t)){await i.ensureBooted(e);try{await i.captureWithRetry(e,n),await i.normalizeDensity(e,n,r.pixelDensity);return}catch(e){a=e}}if(!i.shouldFallbackToRunner(a))throw a;Ke(e,`simctl_screenshot`,a)}await i.captureWithRunner(e,n,r.appBundleId,r.fullscreen,r.runnerOptions),await i.normalizeDensity(e,n,r.pixelDensity)}finally{await a().catch(t=>K(e,`restore_failed`,t))}}async function Ue(e,t){let n=v.fromTimeoutMs(oe);await _(async({deadline:n})=>{await V(e,[`io`,e.id,`screenshot`,t],{timeoutMs:Math.max(1e3,n?.remainingMs()??2e4)})},{maxAttempts:5,baseDelayMs:fe,maxDelayMs:le,jitter:.2,shouldRetry:e=>q(e)},{deadline:n,phase:`ios_simulator_screenshot`})}async function W(e,n,r,i,a){if(e.kind===`device`&&!d(e)){await E(e).captureScreenshot(e,n,{appBundleId:r,fullscreen:i,runnerOptions:a,preferRunner:!0,runRunnerCommand:D});return}let o=(await D(e,{command:`screenshot`,appBundleId:r,fullscreen:i,inlineScreenshot:!1},a)).message;if(!o)throw new t(`COMMAND_FAILED`,`Failed to capture iOS screenshot: runner returned no file path`);if(d(e)){await N.copyFile(o,n);return}if(e.kind===`simulator`){await We(e,o,n);return}throw new t(`COMMAND_FAILED`,`Unsupported Apple screenshot target`)}async function We(e,n,r){let i=v.fromTimeoutMs(se),a=`Unable to locate runner container for simulator screenshot`,o=U.get(e.id);if(o){let t=await G(o,n,r);if(t.copied)return;a=t.error,U.delete(e.id)}for(let t of me){let o=await V(e,[`get_app_container`,e.id,t,`data`],{allowFailure:!0,timeoutMs:Ge(i,se,`runner screenshot container lookup`)});if(o.exitCode!==0){let e=o.stderr.trim();e&&(a=e);continue}let s=o.stdout.trim();if(!s){a=`simctl get_app_container returned empty output`;continue}let c=await G(s,n,r);if(c.copied){U.set(e.id,s);return}a=c.error}throw new t(`COMMAND_FAILED`,`Failed to capture iOS screenshot: ${a}`)}async function G(e,t,n){let r=`Runner screenshot was not found in the simulator container`;for(let i of qe(e,t))try{return await N.copyFile(i,n),{copied:!0}}catch(e){r=e instanceof Error?e.message:String(e)}return{copied:!1,error:r}}function Ge(e,n,r){let i=e.remainingMs();if(i>0)return i;throw new t(`COMMAND_FAILED`,`iOS ${r} timed out after ${n}ms`,{timeoutMs:n,step:r})}function Ke(e,t,n){let r=T(n);h({level:`warn`,phase:`ios_screenshot_fallback`,data:{platform:e.platform,deviceKind:e.kind,deviceId:e.id,from:t,to:`runner`,...r}})}function K(e,t,n){h({level:`warn`,phase:`ios_screenshot_status_bar_${t}`,data:{platform:e.platform,deviceKind:e.kind,deviceId:e.id,...T(n)}})}function qe(e,t){let n=M.resolve(e),r=t.trim();if(!r)return[];let i=[],a=new Set,o=e=>{let t=M.normalize(e);a.has(t)||(a.add(t),i.push(t))},s=r.replace(/^\/+/,``),c=s.replace(/\\/g,`/`);if(s&&o(M.join(n,s)),M.isAbsolute(r)&&o(M.normalize(r)),c.startsWith(`tmp/`))o(M.join(n,c));else{let e=c.lastIndexOf(`/tmp/`);if(e>=0){let t=c.slice(e+1);o(M.join(n,t))}}let l=M.basename(r);return l&&o(M.join(n,`tmp`,l)),i}function q(e){if(!(e instanceof t)||e.code!==`COMMAND_FAILED`)return!1;let n=C(e);return n.includes(`timeout waiting for screen surfaces`)||n.includes(`nsposixerrordomain`)&&n.includes(`code=60`)&&n.includes(`screenshot`)||n.includes(`timed out`)&&n.includes(`screenshot`)}function Je(e){if(!(e instanceof t)||e.code!==`COMMAND_FAILED`)return!1;let n=C(e);return n.includes(`not booted`)||n.includes(`current state: shutdown`)||n.includes(`current state is shutdown`)||n.includes(`current state=shutdown`)||n.includes(`state: shutdown`)||n.includes(`state=shutdown`)}async function Ye(e,t,n){let r=await Xe(e),i=he(await ge(t),r,n);i&&await p(t,i.width,i.height)}async function Xe(e){let n=H.get(e.id);if(n!==void 0)return n;let r=await V(e,[`getenv`,e.id,`SIMULATOR_MAINSCREEN_SCALE`],{timeoutMs:ce}),i=Number(r.stdout.trim());if(!Number.isFinite(i)||i<=0)throw new t(`COMMAND_FAILED`,`Failed to read iOS simulator screenshot scale from SIMULATOR_MAINSCREEN_SCALE`);return H.set(e.id,i),i}function J(e){if(!(e instanceof t)||e.code!==`COMMAND_FAILED`)return!1;let n=e.details??{};if(n.exitCode!==4)return!1;let r=String(n.stderr??``).toLowerCase();return r.includes(`fbsopenapplicationserviceerrordomain`)&&r.includes(`the request to open`)}async function Ze(e,t){let n=await b(ae(e,[`get_app_container`,e.id,t]),{allowFailure:!0});if(n.exitCode!==0)return{installed:!1};let r=n.stdout.trim();if(!r)return{installed:!1};let i=await re(`plutil`,[`-extract`,`CFBundleExecutable`,`raw`,`-o`,`-`,`${r}/Info.plist`],{allowFailure:!0});if(i.exitCode!==0||!i.stdout.trim())return{installed:!0};let a=await re(`otool`,[`-l`,`${r}/${i.stdout.trim()}`],{allowFailure:!0});if(a.exitCode!==0)return{installed:!0};let o=a.stdout.toLowerCase();return{installed:!0,simulatorCompatible:o.includes(`iossimulator`)||o.includes(`platform 7`)}}function Qe(e){return e.installed?e.simulatorCompatible===!1?`ARCH_MISMATCH`:`PERSISTENT_LAUNCH_FAIL`:`APP_NOT_INSTALLED`}function $e(e){switch(e){case`ARCH_MISMATCH`:return`The app binary was not built for the simulator platform. Rebuild with a simulator destination or use a physical device.`;case`APP_NOT_INSTALLED`:return`The app bundle is not installed on this simulator. Run install before open.`;case`PERSISTENT_LAUNCH_FAIL`:return`The simulator repeatedly refused to launch the app. Inspect crash logs in Console.app or ~/Library/Logs/DiagnosticReports/ and consider reinstalling the app.`;default:return`The simulator failed to launch the app. Retry with --debug and inspect diagnostics log for details.`}}const Y=25e3;async function et(e,i,a){let o=a?.launchConsole?.trim(),s=a?.launchArgs;if(o&&(!f(e)||e.kind!==`simulator`))throw new t(`UNSUPPORTED_OPERATION`,r);if(d(e)){if(s&&s.length>0)throw new t(`UNSUPPORTED_OPERATION`,`--launch-args is not supported on macOS; launch arguments are currently iOS-only.`);await ve(e,i,a);return}let p=a?.url?.trim();if(p){if(o)throw new t(`INVALID_ARGS`,n);if(!u(p))throw new t(`INVALID_ARGS`,`open <app> <url> requires a valid URL target`);if(e.kind===`simulator`){let t=!!s||c(p);if(a?.terminateRunningApp||t){let n=a?.appBundleId??await A(e,i);t?await it(e,n,{...s?{launchArgs:s}:{},...a?.terminateRunningApp?{terminateRunningApp:!0}:{}}):await rt(e,n)}await X(e,p,void 0);return}let r=l(a?.appBundleId??await A(e,i),p);if(!r)throw new t(`INVALID_ARGS`,`Deep link open on iOS devices requires an active app bundle ID. Open the app first, then open the URL.`);await Z(e,r,{payloadUrl:p,launchArgs:s,runnerOptions:a?.runnerOptions});return}let m=i.trim();if(u(m)){if(o)throw new t(`INVALID_ARGS`,n);if(e.kind===`simulator`){await X(e,m,s);return}let r=l(a?.appBundleId,m);if(!r)throw new t(`INVALID_ARGS`,`Deep link open on iOS devices requires an active app bundle ID. Open the app first, then open the URL.`);await Z(e,r,{payloadUrl:m,launchArgs:s,runnerOptions:a?.runnerOptions});return}let h=a?.appBundleId??await A(e,i);if(e.kind===`simulator`){await it(e,h,{...o?{launchConsole:o}:{},...s?{launchArgs:s}:{},...a?.terminateRunningApp?{terminateRunningApp:!0}:{}});return}await Z(e,h,{launchArgs:s,runnerOptions:a?.runnerOptions})}async function X(e,n,r){if(r&&r.length>0)throw new t(`INVALID_ARGS`,`--launch-args is not supported with iOS simulator URL opens (simctl openurl ignores launch args). Launch the app first with --launch-args, then issue the URL open in a separate call.`);await k(e),await S(e,[`openurl`,e.id,n])}async function tt(e){d(e)||e.kind===`simulator`&&await _e(e)!==`Booted`&&await k(e)}async function nt(e,t,n){if(d(e)){await we(e,t);return}let r=await A(e,t);if(e.kind===`simulator`){await rt(e,r);return}await E(e).terminateApp(e,r,{runnerOptions:n,runRunnerCommand:D})}async function rt(e,n){await k(e);let r=w(e,[`terminate`,e.id,n]),i=await b(r,{allowFailure:!0,timeoutMs:pe});if(i.exitCode!==0&&!i.stderr.toLowerCase().includes(`found nothing to terminate`))throw new t(`COMMAND_FAILED`,`xcrun exited with code ${i.exitCode}`,g(i,{cmd:`xcrun`,args:r}))}async function it(e,n,r){await k(e);let i=0,a=v.fromTimeoutMs(de);try{await _(async({deadline:i})=>{if(i?.isExpired())throw new t(`COMMAND_FAILED`,`App launch deadline exceeded`,{timeoutMs:de});let a=w(e,at(e.id,n,r)),o=r?.launchConsole?await ot(a,r.launchConsole):await b(a,{allowFailure:!0});if(o.exitCode!==0)throw new t(`COMMAND_FAILED`,`xcrun exited with code ${o.exitCode}`,g(o,{cmd:`xcrun`,args:a}))},{maxAttempts:10,baseDelayMs:1e3,maxDelayMs:5e3,jitter:.2,shouldRetry(e){return J(e)?(i+=1,i<3):!1}},{deadline:a})}catch(t){if(J(t)){let r=t,i=Qe(await Ze(e,n));r.details={...r.details,hint:$e(i)}}throw t}}function at(e,t,n){let r=[`launch`];return n?.launchConsole&&r.push(`--console-pty`),n?.terminateRunningApp&&r.push(`--terminate-running-process`),r.push(e,t),n?.launchArgs&&n.launchArgs.length>0&&r.push(...n.launchArgs),r}async function ot(e,n){await N.mkdir(M.dirname(n),{recursive:!0});try{let t=await b(e,{allowFailure:!0,timeoutMs:Y});return await st(n,t.stdout,t.stderr),t}catch(e){let r=(e instanceof t?e:void 0)?.details;if(r?.timeoutMs===Y){let e=typeof r.stdout==`string`?r.stdout:``,t=typeof r.stderr==`string`?r.stderr:``;return await st(n,e,t),h({level:`warn`,phase:`ios_simulator_launch_console_capture_timeout`,data:{timeoutMs:Y,logPath:n,stdoutBytes:Buffer.byteLength(e),stderrBytes:Buffer.byteLength(t)}}),{stdout:e,stderr:t,exitCode:0}}throw e}}async function st(e,t,n){await N.writeFile(e,ct(t,n),`utf8`)}function ct(e,t){return!e||!t||e.endsWith(`
|
|
3
|
-
`)||e.endsWith(`\r`)?`${e}${t}`:`${e}\n${t}`}async function
|
|
4
|
-
`).replace(/\n$/,``))}async function pt(e,t){if(
|
|
5
|
-
`)){let e=r.trim();if(!e)continue;if(e===`service`){n=!0;continue}if(!n)continue;if(e.startsWith(`bundle identifier`))break;let i=/^([a-z-]+)\s+-\s+/.exec(e)?.[1];i!==void 0&&t.add(i)}return t}function Dt(e,n){let r=
|
|
1
|
+
import{o as e}from"./png-worker-contract.js";import{_ as t}from"./sdk-contracts.js";import{_ as n,f as r,h as i,v as a}from"./screenshot-geometry.js";import{c as o,l as s,s as c}from"./sdk-batch-runner.js";import{c as l,s as u}from"./sdk-device.js";import{Ht as ee,Vt as d}from"./viewport-dimension.js";import{o as f}from"./runtime.js";import{h as p,j as m,p as h}from"./sdk-android-adb.js";import{l as g,o as te,s as _}from"./boot-diagnostics.js";import{n as ne,r as re,t as v}from"./setting-state.js";import{a as y,i as b}from"./tool-provider.js";import{L as ie,R as ae,_ as oe,a as x,d as S,g as se,h as ce,i as le,l as ue,m as de,n as C,o as w,r as T,t as E,v as fe,y as pe}from"./physical-device-control.js";import{a as me}from"./helper.js";import{a as D}from"./runner-client.js";import{Mt as he,jt as ge}from"./internal/daemon.js";import{i as O,n as _e,t as k}from"./simulator.js";import{a as A,c as ve,d as ye,i as be,l as xe,n as Se,o as Ce,r as j,s as we,u as Te}from"./app-resolution.js";import{n as Ee}from"./install-artifact2.js";import M from"node:path";import{promises as N}from"node:fs";import De from"node:os";const Oe=[`--time`,`9:41`,`--dataNetwork`,`wifi`,`--wifiMode`,`active`,`--wifiBars`,`3`,`--batteryState`,`charged`,`--batteryLevel`,`100`],ke={0:`hide`,1:`wifi`,6:`3g`,7:`4g`,8:`lte`,9:`lte-a`,10:`lte+`,11:`5g`,12:`5g+`,13:`5g-uwb`,14:`5g-uc`},Ae={1:`searching`,2:`failed`,3:`active`},je={0:`notSupported`,1:`searching`,2:`failed`,3:`active`};function P(e,t,n){return ae(e,t,n)}const F=new Set;async function Me(e){let t=null,n=!1;if(Fe(e))n=!0;else try{t=await Ie(e),n=!0}catch(t){B(e,`snapshot_failed`,t)}try{(!n||t)&&await R(e),await z(e,Oe)}catch(t){B(e,`prepare_failed`,t)}return async()=>{await Ne(e,n?t:null)}}async function Ne(e,t){if(await R(e),!t){Pe(e);return}await z(e,Re(t)),I(e)}function I(e){F.delete(L(e))}function Pe(e){F.add(L(e))}function Fe(e){return F.has(L(e))}function L(e){return`${e.platform}:${e.kind}:${e.id}`}async function Ie(e){return Le(p(await P(e,[`status_bar`,e.id,`list`],{allowFailure:!0}),`Failed to read simulator status bar overrides`).stdout)}async function R(e){await P(e,[`status_bar`,e.id,`clear`])}async function z(e,t){t.length!==0&&await P(e,[`status_bar`,e.id,`override`,...t])}function Le(e){let n={},r=e.split(`
|
|
2
|
+
`).map(e=>e.trim()).filter(e=>e.length>0&&e!==`Current Status Bar Overrides:`&&!/^=+$/.test(e));for(let e of r){let r=/^DataNetworkType:\s+(\d+)$/.exec(e);if(r){let e=Number(r[1]),i=ke[e];if(!i)throw new t(`COMMAND_FAILED`,`Unsupported simulator data network type: ${e}`);n.dataNetwork=i;continue}let i=/^WiFi Mode:\s+(\d+),\s+WiFi Bars:\s+(\d+)$/.exec(e);if(i){let e=Ae[Number(i[1])];e&&(n.wifiMode=e),n.wifiBars=i[2];continue}let a=/^Cell Mode:\s+(\d+),\s+Cell Bars:\s+(\d+)$/.exec(e);if(a){let e=Number(a[1]),r=je[e];if(!r)throw new t(`COMMAND_FAILED`,`Unsupported simulator cellular mode: ${e}`);n.cellularMode=r,n.cellularBars=a[2];continue}let o=/^Operator Name:\s*(.*)$/.exec(e);if(o){n.operatorName=o[1]??``;continue}}return Object.keys(n).length===0?null:n}function Re(e){let t=[];return e.dataNetwork&&t.push(`--dataNetwork`,e.dataNetwork),e.wifiMode&&t.push(`--wifiMode`,e.wifiMode),e.wifiBars!==void 0&&(e.dataNetwork===`wifi`||e.wifiMode)&&t.push(`--wifiBars`,e.wifiBars),e.cellularMode&&t.push(`--cellularMode`,e.cellularMode),e.cellularBars!==void 0&&(e.cellularMode||ze(e.dataNetwork)||e.operatorName!==void 0)&&t.push(`--cellularBars`,e.cellularBars),e.operatorName!==void 0&&t.push(`--operatorName`,e.operatorName),t}function ze(e){return!!(e&&e!==`hide`&&e!==`wifi`)}function B(e,t,n){m({level:`warn`,phase:`ios_screenshot_status_bar_${t}`,data:{platform:e.platform,deviceKind:e.kind,deviceId:e.id,...T(n)}})}function V(e,t,n){return ae(e,t,n)}const Be={ensureBooted:k,prepareStatusBarForScreenshot:Me,captureWithRetry:Ue,normalizeDensity:Ye,captureWithRunner:W,shouldFallbackToRunner:q},H=new Map,U=new Map;async function Ve(e,t,n={}){if(l(e)){await W(e,t,n.appBundleId,n.fullscreen,n.runnerOptions);return}if(e.kind===`simulator`){await He(e,t,n);return}await E(e).captureScreenshot(e,t,{appBundleId:n.appBundleId,fullscreen:n.fullscreen,runnerOptions:n.runnerOptions,runRunnerCommand:D})}async function He(e,n,r={}){if(e.kind!==`simulator`)throw new t(`UNSUPPORTED_OPERATION`,`Simulator screenshot fallback flow supports only iOS simulators`);let i={...Be,...r.deps??{}};r.skipIosSimulatorBootCheck||await i.ensureBooted(e);let a=async()=>{};if(r.normalizeStatusBar===!0)try{a=await i.prepareStatusBarForScreenshot(e)}catch(t){K(e,`prepare_failed`,t)}try{try{await i.captureWithRetry(e,n),await i.normalizeDensity(e,n,r.pixelDensity);return}catch(t){let a=t;if(r.skipIosSimulatorBootCheck&&Je(t)){await i.ensureBooted(e);try{await i.captureWithRetry(e,n),await i.normalizeDensity(e,n,r.pixelDensity);return}catch(e){a=e}}if(!i.shouldFallbackToRunner(a))throw a;Ke(e,`simctl_screenshot`,a)}await i.captureWithRunner(e,n,r.appBundleId,r.fullscreen,r.runnerOptions),await i.normalizeDensity(e,n,r.pixelDensity)}finally{await a().catch(t=>K(e,`restore_failed`,t))}}async function Ue(e,t){let n=_.fromTimeoutMs(oe);await g(async({deadline:n})=>{await V(e,[`io`,e.id,`screenshot`,t],{timeoutMs:Math.max(1e3,n?.remainingMs()??2e4)})},{maxAttempts:5,baseDelayMs:de,maxDelayMs:ce,jitter:.2,shouldRetry:e=>q(e)},{deadline:n,phase:`ios_simulator_screenshot`})}async function W(e,n,r,i,a){if(e.kind===`device`&&!l(e)){await E(e).captureScreenshot(e,n,{appBundleId:r,fullscreen:i,runnerOptions:a,preferRunner:!0,runRunnerCommand:D});return}let o=(await D(e,{command:`screenshot`,appBundleId:r,fullscreen:i,inlineScreenshot:!1},a)).message;if(!o)throw new t(`COMMAND_FAILED`,`Failed to capture iOS screenshot: runner returned no file path`);if(l(e)){await N.copyFile(o,n);return}if(e.kind===`simulator`){await We(e,o,n);return}throw new t(`COMMAND_FAILED`,`Unsupported Apple screenshot target`)}async function We(e,n,r){let i=_.fromTimeoutMs(S),a=`Unable to locate runner container for simulator screenshot`,o=U.get(e.id);if(o){let t=await G(o,n,r);if(t.copied)return;a=t.error,U.delete(e.id)}for(let t of pe){let o=await V(e,[`get_app_container`,e.id,t,`data`],{allowFailure:!0,timeoutMs:Ge(i,S,`runner screenshot container lookup`)});if(o.exitCode!==0){let e=o.stderr.trim();e&&(a=e);continue}let s=o.stdout.trim();if(!s){a=`simctl get_app_container returned empty output`;continue}let c=await G(s,n,r);if(c.copied){U.set(e.id,s);return}a=c.error}throw new t(`COMMAND_FAILED`,`Failed to capture iOS screenshot: ${a}`)}async function G(e,t,n){let r=`Runner screenshot was not found in the simulator container`;for(let i of qe(e,t))try{return await N.copyFile(i,n),{copied:!0}}catch(e){r=e instanceof Error?e.message:String(e)}return{copied:!1,error:r}}function Ge(e,n,r){let i=e.remainingMs();if(i>0)return i;throw new t(`COMMAND_FAILED`,`iOS ${r} timed out after ${n}ms`,{timeoutMs:n,step:r})}function Ke(e,t,n){let r=T(n);m({level:`warn`,phase:`ios_screenshot_fallback`,data:{platform:e.platform,deviceKind:e.kind,deviceId:e.id,from:t,to:`runner`,...r}})}function K(e,t,n){m({level:`warn`,phase:`ios_screenshot_status_bar_${t}`,data:{platform:e.platform,deviceKind:e.kind,deviceId:e.id,...T(n)}})}function qe(e,t){let n=M.resolve(e),r=t.trim();if(!r)return[];let i=[],a=new Set,o=e=>{let t=M.normalize(e);a.has(t)||(a.add(t),i.push(t))},s=r.replace(/^\/+/,``),c=s.replace(/\\/g,`/`);if(s&&o(M.join(n,s)),M.isAbsolute(r)&&o(M.normalize(r)),c.startsWith(`tmp/`))o(M.join(n,c));else{let e=c.lastIndexOf(`/tmp/`);if(e>=0){let t=c.slice(e+1);o(M.join(n,t))}}let l=M.basename(r);return l&&o(M.join(n,`tmp`,l)),i}function q(e){if(!(e instanceof t)||e.code!==`COMMAND_FAILED`)return!1;let n=C(e);return n.includes(`timeout waiting for screen surfaces`)||n.includes(`nsposixerrordomain`)&&n.includes(`code=60`)&&n.includes(`screenshot`)||n.includes(`timed out`)&&n.includes(`screenshot`)}function Je(e){if(!(e instanceof t)||e.code!==`COMMAND_FAILED`)return!1;let n=C(e);return n.includes(`not booted`)||n.includes(`current state: shutdown`)||n.includes(`current state is shutdown`)||n.includes(`current state=shutdown`)||n.includes(`state: shutdown`)||n.includes(`state=shutdown`)}async function Ye(e,t,n){let r=await Xe(e),i=ge(await he(t),r,n);i&&await f(t,i.width,i.height)}async function Xe(e){let n=H.get(e.id);if(n!==void 0)return n;let r=await V(e,[`getenv`,e.id,`SIMULATOR_MAINSCREEN_SCALE`],{timeoutMs:se}),i=Number(r.stdout.trim());if(!Number.isFinite(i)||i<=0)throw new t(`COMMAND_FAILED`,`Failed to read iOS simulator screenshot scale from SIMULATOR_MAINSCREEN_SCALE`);return H.set(e.id,i),i}function J(e){if(!(e instanceof t)||e.code!==`COMMAND_FAILED`)return!1;let n=e.details??{};if(n.exitCode!==4)return!1;let r=String(n.stderr??``).toLowerCase();return r.includes(`fbsopenapplicationserviceerrordomain`)&&r.includes(`the request to open`)}async function Ze(e,t){let n=await y(ie(e,[`get_app_container`,e.id,t]),{allowFailure:!0});if(n.exitCode!==0)return{installed:!1};let r=n.stdout.trim();if(!r)return{installed:!1};let i=await b(`plutil`,[`-extract`,`CFBundleExecutable`,`raw`,`-o`,`-`,`${r}/Info.plist`],{allowFailure:!0});if(i.exitCode!==0||!i.stdout.trim())return{installed:!0};let a=await b(`otool`,[`-l`,`${r}/${i.stdout.trim()}`],{allowFailure:!0});if(a.exitCode!==0)return{installed:!0};let o=a.stdout.toLowerCase();return{installed:!0,simulatorCompatible:o.includes(`iossimulator`)||o.includes(`platform 7`)}}function Qe(e){return e.installed?e.simulatorCompatible===!1?`ARCH_MISMATCH`:`PERSISTENT_LAUNCH_FAIL`:`APP_NOT_INSTALLED`}function $e(e){switch(e){case`ARCH_MISMATCH`:return`The app binary was not built for the simulator platform. Rebuild with a simulator destination or use a physical device.`;case`APP_NOT_INSTALLED`:return`The app bundle is not installed on this simulator. Run install before open.`;case`PERSISTENT_LAUNCH_FAIL`:return`The simulator repeatedly refused to launch the app. Inspect crash logs in Console.app or ~/Library/Logs/DiagnosticReports/ and consider reinstalling the app.`;default:return`The simulator failed to launch the app. Retry with --debug and inspect diagnostics log for details.`}}const Y=25e3;async function et(e,n,r){let i=r?.launchConsole?.trim(),a=r?.launchArgs;if(i&&(!u(e)||e.kind!==`simulator`))throw new t(`UNSUPPORTED_OPERATION`,ee);if(l(e)){if(a&&a.length>0)throw new t(`UNSUPPORTED_OPERATION`,`--launch-args is not supported on macOS; launch arguments are currently iOS-only.`);await ve(e,n,r);return}let f=r?.url?.trim();if(f){if(i)throw new t(`INVALID_ARGS`,d);if(!c(f))throw new t(`INVALID_ARGS`,`open <app> <url> requires a valid URL target`);if(e.kind===`simulator`){let t=!!a||o(f);if(r?.terminateRunningApp||t){let i=r?.appBundleId??await A(e,n);t?await rt(e,i,{...a?{launchArgs:a}:{},...r?.terminateRunningApp?{terminateRunningApp:!0}:{}}):await nt(e,i)}await X(e,f,void 0);return}let l=s(r?.appBundleId??await A(e,n),f);if(!l)throw new t(`INVALID_ARGS`,`Deep link open on iOS devices requires an active app bundle ID. Open the app first, then open the URL.`);await Q(e,l,{payloadUrl:f,launchArgs:a,runnerOptions:r?.runnerOptions});return}let p=n.trim();if(c(p)){if(i)throw new t(`INVALID_ARGS`,d);if(e.kind===`simulator`){await X(e,p,a);return}let n=s(r?.appBundleId,p);if(!n)throw new t(`INVALID_ARGS`,`Deep link open on iOS devices requires an active app bundle ID. Open the app first, then open the URL.`);await Q(e,n,{payloadUrl:p,launchArgs:a,runnerOptions:r?.runnerOptions});return}let m=r?.appBundleId??await A(e,n);if(e.kind===`simulator`){await rt(e,m,{...i?{launchConsole:i}:{},...a?{launchArgs:a}:{},...r?.terminateRunningApp?{terminateRunningApp:!0}:{}});return}await Q(e,m,{launchArgs:a,runnerOptions:r?.runnerOptions})}async function X(e,n,r){if(r&&r.length>0)throw new t(`INVALID_ARGS`,`--launch-args is not supported with iOS simulator URL opens (simctl openurl ignores launch args). Launch the app first with --launch-args, then issue the URL open in a separate call.`);await k(e),await x(e,[`openurl`,e.id,n])}async function tt(e){l(e)||e.kind===`simulator`&&await _e(e)!==`Booted`&&await k(e)}async function Z(e,t,n){if(l(e)){await we(e,t);return}let r=await A(e,t);if(e.kind===`simulator`){await nt(e,r);return}await E(e).terminateApp(e,r,{runnerOptions:n,runRunnerCommand:D})}async function nt(e,n){await k(e);let r=w(e,[`terminate`,e.id,n]),i=await y(r,{allowFailure:!0,timeoutMs:fe});if(i.exitCode!==0&&!i.stderr.toLowerCase().includes(`found nothing to terminate`))throw new t(`COMMAND_FAILED`,`xcrun exited with code ${i.exitCode}`,h(i,{cmd:`xcrun`,args:r}))}async function rt(e,n,r){await k(e);let i=0,a=_.fromTimeoutMs(ue);try{await g(async({deadline:i})=>{if(i?.isExpired())throw new t(`COMMAND_FAILED`,`App launch deadline exceeded`,{timeoutMs:ue});let a=w(e,it(e.id,n,r)),o=r?.launchConsole?await at(a,r.launchConsole):await y(a,{allowFailure:!0});if(o.exitCode!==0)throw new t(`COMMAND_FAILED`,`xcrun exited with code ${o.exitCode}`,h(o,{cmd:`xcrun`,args:a}))},{maxAttempts:10,baseDelayMs:1e3,maxDelayMs:5e3,jitter:.2,shouldRetry(e){return J(e)?(i+=1,i<3):!1}},{deadline:a})}catch(t){if(J(t)){let r=t,i=Qe(await Ze(e,n));r.details={...r.details,hint:$e(i)}}throw t}}function it(e,t,n){let r=[`launch`];return n?.launchConsole&&r.push(`--console-pty`),n?.terminateRunningApp&&r.push(`--terminate-running-process`),r.push(e,t),n?.launchArgs&&n.launchArgs.length>0&&r.push(...n.launchArgs),r}async function at(e,n){await N.mkdir(M.dirname(n),{recursive:!0});try{let t=await y(e,{allowFailure:!0,timeoutMs:Y});return await ot(n,t.stdout,t.stderr),t}catch(e){let r=(e instanceof t?e:void 0)?.details;if(r?.timeoutMs===Y){let e=typeof r.stdout==`string`?r.stdout:``,t=typeof r.stderr==`string`?r.stderr:``;return await ot(n,e,t),m({level:`warn`,phase:`ios_simulator_launch_console_capture_timeout`,data:{timeoutMs:Y,logPath:n,stdoutBytes:Buffer.byteLength(e),stderrBytes:Buffer.byteLength(t)}}),{stdout:e,stderr:t,exitCode:0}}throw e}}async function ot(e,t,n){await N.writeFile(e,st(t,n),`utf8`)}function st(e,t){return!e||!t||e.endsWith(`
|
|
3
|
+
`)||e.endsWith(`\r`)?`${e}${t}`:`${e}\n${t}`}async function Q(e,t,n){await E(e).launchApp(e,t,{...n,runRunnerCommand:D})}async function ct(e,n){return await j(e,async()=>{let r=await A(e,n);if(e.kind!==`simulator`)return await E(e).uninstallApp(e,r),{bundleId:r};await k(e);let i=await x(e,[`uninstall`,e.id,r],{allowFailure:!0});if(i.exitCode!==0&&!le(`${i.stdout}\n${i.stderr}`.toLowerCase()))throw new t(`COMMAND_FAILED`,`simctl uninstall failed for ${r}`,h(i));return{bundleId:r}})}async function lt(e,t,n){e.kind!==`simulator`&&E(e).assertAppInstallationSupported(e);let r=await Ee({kind:`path`,path:t},n);try{return await dt(e,r.installablePath),{archivePath:r.archivePath,installablePath:r.installablePath,bundleId:r.bundleId,appName:r.appName,launchTarget:r.bundleId}}finally{await r.cleanup()}}async function ut(e,t,n){return e.kind!==`simulator`&&E(e).assertAppInstallationSupported(e),await j(e,async()=>{let{bundleId:r}=await ct(e,t);return await lt(e,n,{appIdentifierHint:t}),{bundleId:r}})}async function dt(e,t){await j(e,async()=>{if(e.kind!==`simulator`){await E(e).installApp(e,t);return}await k(e),await x(e,[`install`,e.id,t])})}async function ft(e){return l(e)?await xe():(O(e,`clipboard`),await k(e),p(await x(e,[`pbpaste`,e.id],{allowFailure:!0}),`Failed to read iOS simulator clipboard`).stdout.replace(/\r\n/g,`
|
|
4
|
+
`).replace(/\n$/,``))}async function pt(e,t){if(l(e)){await ye(t);return}O(e,`clipboard`),await k(e),p(await x(e,[`pbcopy`,e.id],{allowFailure:!0,stdin:t}),`Failed to write iOS simulator clipboard`)}async function mt(e,t,n){O(e,`push`),await k(e);let r=await N.mkdtemp(M.join(De.tmpdir(),`agent-device-ios-push-`)),i=M.join(r,`payload.apns`);try{await N.writeFile(i,`${JSON.stringify(n)}\n`,`utf8`),await x(e,[`push`,e.id,t,i])}finally{await N.rm(r,{recursive:!0,force:!0})}}let $=null,ht;async function gt(e,a,o,s,c){if(l(e)){let e=a.toLowerCase();if(e===`appearance`){await Te(o);return}if(e===`permission`){let e=n(o);if(e===`deny`)throw new t(`INVALID_ARGS`,i(`permission`));return await me(e,vt(c?.permissionTarget))}throw new t(`INVALID_ARGS`,i(a))}O(e,`settings`),await k(e);let u=a.toLowerCase();switch(u){case`clear-app-state`:{if(o.toLowerCase()!==`clear`)throw new t(`INVALID_ARGS`,`settings clear-app-state only supports clear.`);if(!s)throw new t(`INVALID_ARGS`,`settings clear-app-state requires an app id or an active app session.`);let n=await _t(e,s);return{bundleId:n.bundleId,containerPath:n.containerPath,cleared:!0}}case`wifi`:{let t=v(o)?`active`:`failed`;await x(e,[`status_bar`,e.id,`override`,`--wifiMode`,t]),I(e);return}case`airplane`:v(o)?(await x(e,[`status_bar`,e.id,`override`,`--dataNetwork`,`hide`,`--wifiMode`,`failed`,`--wifiBars`,`0`,`--cellularMode`,`failed`,`--cellularBars`,`0`,`--operatorName`,``]),I(e)):(await x(e,[`status_bar`,e.id,`clear`]),Pe(e));return;case`location`:{if(o.toLowerCase()===`set`){let{latitude:t,longitude:n}=r(c);return await x(e,[`location`,e.id,`set`,`${t},${n}`]),{latitude:t,longitude:n}}let n=v(o);if(!s)throw new t(`INVALID_ARGS`,`location setting requires an active app in session`);let i=n?`grant`:`revoke`;await x(e,[`privacy`,e.id,i,`location`,s]);return}case`faceid`:case`touchid`:{let t=u,n=xt[t];await kt(e,Ot(o,t),{settingName:t,label:n.label,modalityAliases:n.modalityAliases});return}case`appearance`:{let t=await yt(e,o);await x(e,[`ui`,e.id,`appearance`,t]);return}case`permission`:if(!s)throw new t(`INVALID_ARGS`,`permission setting requires an active app in session`);await Ct(e,St(n(o)),Dt(c?.permissionTarget,c?.permissionMode),s);return;default:throw new t(`INVALID_ARGS`,`Unsupported setting: ${a}`)}}async function _t(e,n){if(!u(e)||e.kind!==`simulator`)throw new t(`UNSUPPORTED_OPERATION`,`Clearing app state is currently supported only on iOS simulators.`);let r=await A(e,n);await k(e),await Z(e,r);let i=p(await x(e,[`get_app_container`,e.id,r,`data`],{allowFailure:!0}),`simctl get_app_container failed for ${r}`).stdout.trim();if(!i)throw new t(`COMMAND_FAILED`,`simctl get_app_container returned an empty data container path for ${r}`);let a=await N.readdir(i);return await Promise.all(a.map(e=>N.rm(M.join(i,e),{recursive:!0,force:!0}))),{bundleId:r,containerPath:i}}function vt(e){let n=e?.trim().toLowerCase();if(n===`accessibility`||n===`screen-recording`||n===`input-monitoring`)return n;throw new t(`INVALID_ARGS`,`Unsupported macOS permission target. Use accessibility|screen-recording|input-monitoring.`)}async function yt(e,n){let r=ne(n);if(r!==`toggle`)return r;let i=p(await x(e,[`ui`,e.id,`appearance`],{allowFailure:!0}),`Failed to read current iOS appearance`),a=bt(i.stdout,i.stderr);if(!a)throw new t(`COMMAND_FAILED`,`Unable to determine current iOS appearance for toggle`,{stdout:i.stdout,stderr:i.stderr});return a===`dark`?`light`:`dark`}function bt(e,t){let n=/\b(light|dark|unsupported|unknown)\b/i.exec(`${e}\n${t}`);if(!n)return null;let r=n[1]?.toLowerCase();return r===`dark`?`dark`:r===`light`?`light`:null}const xt={faceid:{label:`Face ID`,modalityAliases:[`face`]},touchid:{label:`Touch ID`,modalityAliases:[`finger`,`touch`]}};function St(e){return e===`deny`?`revoke`:e}async function Ct(e,n,r,i){let a=await Tt(e);if(!a.has(r))throw new t(`UNSUPPORTED_OPERATION`,`iOS simctl privacy does not support service "${r}" on this runtime.`,{deviceId:e.id,appBundleId:i,hint:`Supported services: ${Array.from(a).sort().join(`, `)}`});let o=[`privacy`,e.id,n,r,i],s=r===`notifications`;if(!(n===`reset`&&s))try{await x(e,o);return}catch(n){throw s&&wt(n)?new t(`UNSUPPORTED_OPERATION`,`iOS simulator does not support setting notifications permission via simctl privacy on this runtime.`,{deviceId:e.id,appBundleId:i,hint:`Use reset notifications for reprompt behavior, or toggle notifications manually in Settings.`}):n}try{await x(e,o);return}catch(e){if(!wt(e))throw e}try{await x(e,[`privacy`,e.id,`reset`,`all`,i])}catch(n){throw new t(`COMMAND_FAILED`,`iOS simulator blocked direct notifications reset. Fallback reset-all also failed.`,{deviceId:e.id,appBundleId:i,hint:`Use reinstall to force a fresh notifications prompt, or reset simulator content and settings.`},n instanceof Error?n:void 0)}}function wt(e){if(!(e instanceof t)||e.code!==`COMMAND_FAILED`)return!1;let n=String(e.details?.stderr??``).toLowerCase();return(n.includes(`failed to grant access`)||n.includes(`failed to revoke access`)||n.includes(`failed to reset access`))&&n.includes(`operation not permitted`)}async function Tt(e){let n=te(e.simulatorSetPath),r=`${process.env.PATH??``}::${n??``}`;if($&&ht===r)return $;let i=await x(e,[`privacy`,`help`],{allowFailure:!0}),a=Et(`${i.stdout}\n${i.stderr}`);if(a.size===0)throw new t(`COMMAND_FAILED`,`Unable to determine supported simctl privacy services`,{stdout:i.stdout,stderr:i.stderr,exitCode:i.exitCode,hint:"Run `xcrun simctl privacy help` manually to verify available services for this runtime."});return $=a,ht=r,a}function Et(e){let t=new Set,n=!1;for(let r of e.split(`
|
|
5
|
+
`)){let e=r.trim();if(!e)continue;if(e===`service`){n=!0;continue}if(!n)continue;if(e.startsWith(`bundle identifier`))break;let i=/^([a-z-]+)\s+-\s+/.exec(e)?.[1];i!==void 0&&t.add(i)}return t}function Dt(e,n){let r=a(e);if(r!==`photos`&&n?.trim())throw new t(`INVALID_ARGS`,`Permission mode is only supported for photos. Received: ${n}.`);if(r===`camera`)return`camera`;if(r===`microphone`)return`microphone`;if(r===`contacts`)return`contacts`;if(r===`contacts-limited`)return`contacts-limited`;if(r===`notifications`)return`notifications`;if(r===`calendar`)return`calendar`;if(r===`location`)return`location`;if(r===`location-always`)return`location-always`;if(r===`media-library`)return`media-library`;if(r===`motion`)return`motion`;if(r===`reminders`)return`reminders`;if(r===`siri`)return`siri`;if(r===`photos`){let e=n?.trim().toLowerCase();if(!e||e===`full`)return`photos`;if(e===`limited`)return`photos-add`;throw new t(`INVALID_ARGS`,`Invalid photos mode: ${n}. Use full|limited.`)}throw new t(`INVALID_ARGS`,`Unsupported permission target: ${e}. Use camera|microphone|photos|contacts|contacts-limited|notifications|calendar|location|location-always|media-library|motion|reminders|siri.`)}function Ot(e,n){let r=e.trim().toLowerCase();if(r===`match`)return`match`;if(r===`nonmatch`)return`nonmatch`;if(r===`enroll`)return`enroll`;if(r===`unenroll`)return`unenroll`;throw new t(`INVALID_ARGS`,`Invalid ${n} state: ${e}. Use match|nonmatch|enroll|unenroll.`)}async function kt(e,n,r){let i=At(e.id,n,r.modalityAliases),a=[];for(let t of i){let n=w(e,t),r=await y(n,{allowFailure:!0});if(r.exitCode===0)return;a.push({args:n,stderr:r.stderr,stdout:r.stdout,exitCode:r.exitCode})}let o=re(a);throw a.length>0&&a.every(e=>jt(e.stdout,e.stderr))?new t(`UNSUPPORTED_OPERATION`,`${r.label} simulation is not supported on this simulator runtime.`,{deviceId:e.id,action:n,setting:r.settingName,attempts:o}):new t(`COMMAND_FAILED`,`Failed to simulate ${r.settingName}.`,{deviceId:e.id,action:n,setting:r.settingName,attempts:o})}function At(e,t,n){let r=n.length>0?n:[`face`];switch(t){case`match`:return r.flatMap(t=>[[`biometric`,e,`match`,t],[`biometric`,`match`,e,t]]);case`nonmatch`:return r.flatMap(t=>[[`biometric`,e,`nonmatch`,t],[`biometric`,e,`nomatch`,t],[`biometric`,`nonmatch`,e,t],[`biometric`,`nomatch`,e,t]]);case`enroll`:return[[`biometric`,e,`enroll`,`yes`],[`biometric`,e,`enroll`,`1`],[`biometric`,`enroll`,e,`yes`],[`biometric`,`enroll`,e,`1`]];case`unenroll`:return[[`biometric`,e,`enroll`,`no`],[`biometric`,e,`enroll`,`0`],[`biometric`,`enroll`,e,`no`],[`biometric`,`enroll`,e,`0`]]}}function jt(e,t){let n=`${e}\n${t}`.toLowerCase();return n.includes(`unrecognized subcommand`)||n.includes(`unknown subcommand`)||n.includes(`not supported`)||n.includes(`unavailable`)||n.includes(`biometric`)&&n.includes(`invalid`)}var Mt=e({findIosSimulatorInstalledApp:()=>Se,installIosApp:()=>lt,installIosInstallablePath:()=>dt,listIosApps:()=>be,pushIosNotification:()=>mt,reinstallIosApp:()=>ut,resolveIosApp:()=>A,resolveIosSimulatorDeepLinkBundleId:()=>Ce});export{Z as a,W as c,pt as i,Ve as l,gt as n,et as o,ft as r,tt as s,Mt as t};
|
package/dist/src/cli-config.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
import{_ as e}from"./sdk-contracts.js";import{
|
|
1
|
+
import{_ as e}from"./sdk-contracts.js";import{St as t}from"./screenshot-geometry.js";import{Jt as n}from"./viewport-dimension.js";import{p as r,t as i,u as a,w as o}from"./registry.js";import{E as s,O as c}from"./sdk-android-adb.js";import{n as l,t as u}from"./path-resolution.js";import{r as d}from"./command-schema.js";import f from"node:path";import p from"node:fs";function m(e,t){for(let[n,r]of Object.entries(t))r!==void 0&&(e[n]=r);return e}const h=new Set([`config`,`remoteConfig`,`help`,`version`,`batchSteps`,`githubActionsArtifact`]),g=new Set([`appsFilter`,`iosSimulatorDeviceSet`]),_=C(),v=new Map(_.map(e=>[e.key,e]));function y(e){return v.get(e)}function b(e){return _.filter(t=>t.configurable&&t.supportsCommand(e))}function x(e,t){return y(e)?.supportsCommand(t)??!1}function S(e,t,n,r){return c(T(e),t,n,r)}function C(){let e=new Map;for(let t of o()){let n=e.get(t.key);n?n.push(t):e.set(t.key,[t])}let t=new Map;for(let e of r)t.set(e,new Set([`*`]));for(let e of n()){let n=d(e);for(let r of[...n.allowedFlags??[],...n.supportedFlags??[]]){let n=t.get(r);n&&n.has(`*`)||(n?n.add(e):t.set(r,new Set([e])))}}return[...e.entries()].map(([e,n])=>({key:e,flagDefinitions:n,configurable:!h.has(e),env:{names:g.has(e)?[]:[s(e)]},supportsCommand(n){let r=t.get(e);return r?r.has(`*`)?!0:n?r.has(n):!1:!1}})).sort((e,t)=>e.key.localeCompare(t.key))}function w(e){let t=e.flagDefinitions[0];if(!t)throw Error(`Missing flag definition for option ${e.key}`);return t}function T(e){let t=e.flagDefinitions.find(e=>e.setValue===void 0);if(t)return t;let n=w(e);if(n.type===`enum`){let t=n.enumValues??e.flagDefinitions.map(e=>e.setValue).filter(e=>e!==void 0);return{...n,setValue:void 0,enumValues:t}}return n}const E=i();function D(e){return E[e.name]?.({input:e.input??{},result:e.result})}function O(e){let t=e.env??process.env;return m(m({},N(A(e.cwd,e.cliFlags.config,t))),L(t,e.command))}const k=new Set(`json.platform.target.device.udid.serial.session.sessionLock.activity.launchArgs.launchUrl.remote.deviceHub.testIme.appsFilter.clean.force.stale.relaunch.shutdown.surface.headless.restart.noRecord.record.recordAs.snapshotInteractiveOnly.snapshotDiff.snapshotDepth.snapshotScope.snapshotRaw.snapshotForceFull.screenshotPixelDensity.screenshotFullscreen.screenshotScale.screenshotNoStabilize.screenshotNormalizeStatusBar.overlayRefs.networkInclude.baseline.threshold.count.pointerCount.fps.quality.hideTouches.recordingScope.intervalMs.delayMs.durationMs.holdMs.jitterPx.pixels.doubleTap.verify.settle.settleQuietMs.clickButton.backMode.pauseMs.pattern.kind.perfTemplate.responseLevel.verbose.cost.timeoutMs.retries.failFast.recordVideo.replayUpdate.replayMaestro.replayFrom.replayPlanDigest.replayKeepSession.findFirst.findLast.batchOnError.batchMaxSteps.retainPaths.retentionMs.shardAll.shardSplit.noLogin`.split(`.`));function A(e,t,n){let r=t??n.AGENT_DEVICE_CONFIG;return r?[{path:M(r,e,n),required:!0,source:`explicit`}]:[{path:j(n),required:!1,source:`user`},{path:f.resolve(e,`agent-device.json`),required:!1,source:`project`}]}function j(e){return f.join(u(`~`,{env:e}),`.agent-device`,`config.json`)}function M(e,t,n){return l(e,{cwd:t,env:n})}function N(e){let t={};for(let n of e)m(t,P(n));return t}function P(t){let{path:n,required:r}=t;if(!p.existsSync(n)){if(r)throw new e(`INVALID_ARGS`,`Config file not found: ${n}`);return{}}let i;try{i=p.readFileSync(n,`utf8`)}catch(t){throw new e(`INVALID_ARGS`,`Failed to read config file: ${n}`,{cause:t instanceof Error?t.message:String(t)})}let a;try{a=JSON.parse(i)}catch(t){throw new e(`INVALID_ARGS`,`Invalid JSON in config file: ${n}`,{cause:t instanceof Error?t.message:String(t)})}if(!a||typeof a!=`object`||Array.isArray(a))throw new e(`INVALID_ARGS`,`Config file must contain a JSON object: ${n}`);return F(a,{source:t.source,label:`${t.source===`project`?`project `:``}config file ${n}`})}function F(n,r){let i={};for(let[o,s]of Object.entries(n)){let n=o,c=y(n);if(!c)throw o===t.flagKey?new e(`INVALID_ARGS`,`Config key "${o}" in ${r.label} was removed; use "screenshotScale" (0.01-1) to downscale screenshots. Recordings capture at native resolution.`):new e(`INVALID_ARGS`,`Unknown config key "${o}" in ${r.label}.`);if(!c.configurable)throw new e(`INVALID_ARGS`,`Config key "${o}" is not allowed in ${r.label}. This key is not supported in config files.`);if(r.source===`project`&&!k.has(n))throw new e(`INVALID_ARGS`,`Config key "${o}" is not allowed in ${r.label}. Move it to ~/.agent-device/config.json, pass it with --config or AGENT_DEVICE_CONFIG, or provide it through CLI flags/environment variables.`);if(n===`installSource`){i.installSource=a(s,r.label);continue}i[n]=S(c,s,r.label,o)}return i}const I=new Set([`screenshot`,`record`]);function L(n,r){let i=n[t.envVar];if(r!==null&&I.has(r)&&typeof i==`string`&&i.trim().length>0)throw new e(`INVALID_ARGS`,`${t.envVar} was removed. ${t.migration[r===`record`?`record`:`screenshot`]}`);let a={};for(let e of b(r)){if(e.key===`installSource`)continue;let t=e.env.names.map(e=>({name:e,value:n[e]})).find(e=>typeof e.value==`string`&&e.value.trim().length>0);t&&(a[e.key]=S(e,t.value,`environment variable ${t.name}`,t.name))}return a}export{m as i,D as n,x as r,O as t};
|