agent-device 0.10.2 → 0.10.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/src/376.js +3 -0
- package/dist/src/bin.js +74 -73
- package/dist/src/daemon.js +37 -37
- package/dist/src/index.d.ts +559 -5
- package/dist/src/index.js +3 -1
- package/package.json +2 -1
- package/skills/agent-device/SKILL.md +35 -12
- package/skills/agent-device/references/bootstrap-install.md +55 -15
- package/skills/agent-device/references/exploration.md +49 -7
- package/skills/agent-device/references/macos-desktop.md +1 -2
- package/skills/agent-device/references/remote-tenancy.md +15 -2
- package/skills/agent-device/references/verification.md +2 -3
- package/dist/src/224.js +0 -2
- package/dist/src/331.js +0 -3
- package/dist/src/425.js +0 -1
- package/dist/src/bin.d.ts +0 -1
- package/dist/src/cli-client-commands.d.ts +0 -8
- package/dist/src/cli.d.ts +0 -6
- package/dist/src/client-metro.d.ts +0 -64
- package/dist/src/client-normalizers.d.ts +0 -20
- package/dist/src/client-shared.d.ts +0 -20
- package/dist/src/client-types.d.ts +0 -269
- package/dist/src/client.d.ts +0 -5
- package/dist/src/core/app-events.d.ts +0 -8
- package/dist/src/core/batch.d.ts +0 -17
- package/dist/src/core/capabilities.d.ts +0 -3
- package/dist/src/core/click-button.d.ts +0 -20
- package/dist/src/core/dispatch-payload.d.ts +0 -1
- package/dist/src/core/dispatch-resolve.d.ts +0 -29
- package/dist/src/core/dispatch-series.d.ts +0 -7
- package/dist/src/core/dispatch.d.ts +0 -37
- package/dist/src/core/open-target.d.ts +0 -4
- package/dist/src/core/session-surface.d.ts +0 -3
- package/dist/src/core/settings-contract.d.ts +0 -9
- package/dist/src/daemon/action-utils.d.ts +0 -3
- package/dist/src/daemon/android-system-dialog.d.ts +0 -11
- package/dist/src/daemon/app-log-android.d.ts +0 -4
- package/dist/src/daemon/app-log-ios.d.ts +0 -7
- package/dist/src/daemon/app-log-process.d.ts +0 -15
- package/dist/src/daemon/app-log-stream.d.ts +0 -19
- package/dist/src/daemon/app-log.d.ts +0 -28
- package/dist/src/daemon/artifact-archive.d.ts +0 -12
- package/dist/src/daemon/artifact-download.d.ts +0 -12
- package/dist/src/daemon/artifact-materialization.d.ts +0 -17
- package/dist/src/daemon/artifact-registry.d.ts +0 -12
- package/dist/src/daemon/config.d.ts +0 -16
- package/dist/src/daemon/context.d.ts +0 -25
- package/dist/src/daemon/device-ready.d.ts +0 -6
- package/dist/src/daemon/handlers/find.d.ts +0 -40
- package/dist/src/daemon/handlers/install-source.d.ts +0 -44
- package/dist/src/daemon/handlers/interaction-common.d.ts +0 -41
- package/dist/src/daemon/handlers/interaction-flags.d.ts +0 -4
- package/dist/src/daemon/handlers/interaction-get.d.ts +0 -3
- package/dist/src/daemon/handlers/interaction-is.d.ts +0 -3
- package/dist/src/daemon/handlers/interaction-read.d.ts +0 -14
- package/dist/src/daemon/handlers/interaction-scroll.d.ts +0 -3
- package/dist/src/daemon/handlers/interaction-selector.d.ts +0 -27
- package/dist/src/daemon/handlers/interaction-snapshot.d.ts +0 -8
- package/dist/src/daemon/handlers/interaction-targeting.d.ts +0 -28
- package/dist/src/daemon/handlers/interaction-touch.d.ts +0 -45
- package/dist/src/daemon/handlers/interaction.d.ts +0 -9
- package/dist/src/daemon/handlers/lease.d.ts +0 -8
- package/dist/src/daemon/handlers/parse-utils.d.ts +0 -3
- package/dist/src/daemon/handlers/record-trace-android.d.ts +0 -18
- package/dist/src/daemon/handlers/record-trace-ios.d.ts +0 -52
- package/dist/src/daemon/handlers/record-trace-recording.d.ts +0 -32
- package/dist/src/daemon/handlers/record-trace.d.ts +0 -10
- package/dist/src/daemon/handlers/session-batch.d.ts +0 -2
- package/dist/src/daemon/handlers/session-close.d.ts +0 -31
- package/dist/src/daemon/handlers/session-deploy.d.ts +0 -37
- package/dist/src/daemon/handlers/session-device-utils.d.ts +0 -26
- package/dist/src/daemon/handlers/session-open-target.d.ts +0 -3
- package/dist/src/daemon/handlers/session-open.d.ts +0 -22
- package/dist/src/daemon/handlers/session-perf.d.ts +0 -2
- package/dist/src/daemon/handlers/session-replay-heal.d.ts +0 -8
- package/dist/src/daemon/handlers/session-replay-script.d.ts +0 -3
- package/dist/src/daemon/handlers/session-runtime-command.d.ts +0 -9
- package/dist/src/daemon/handlers/session-runtime.d.ts +0 -36
- package/dist/src/daemon/handlers/session-startup-metrics.d.ts +0 -11
- package/dist/src/daemon/handlers/session.d.ts +0 -50
- package/dist/src/daemon/handlers/snapshot-alert.d.ts +0 -13
- package/dist/src/daemon/handlers/snapshot-capture.d.ts +0 -34
- package/dist/src/daemon/handlers/snapshot-session.d.ts +0 -15
- package/dist/src/daemon/handlers/snapshot-settings.d.ts +0 -24
- package/dist/src/daemon/handlers/snapshot-wait.d.ts +0 -37
- package/dist/src/daemon/handlers/snapshot.d.ts +0 -16
- package/dist/src/daemon/http-server.d.ts +0 -26
- package/dist/src/daemon/install-source-resolution.d.ts +0 -5
- package/dist/src/daemon/is-predicates.d.ts +0 -15
- package/dist/src/daemon/lease-context.d.ts +0 -9
- package/dist/src/daemon/lease-registry.d.ts +0 -63
- package/dist/src/daemon/materialized-path-registry.d.ts +0 -15
- package/dist/src/daemon/network-log.d.ts +0 -32
- package/dist/src/daemon/record-trace-errors.d.ts +0 -6
- package/dist/src/daemon/recording-gestures.d.ts +0 -3
- package/dist/src/daemon/recording-telemetry.d.ts +0 -20
- package/dist/src/daemon/recording-timing.d.ts +0 -24
- package/dist/src/daemon/request-cancel.d.ts +0 -9
- package/dist/src/daemon/request-lock-policy.d.ts +0 -2
- package/dist/src/daemon/request-router.d.ts +0 -23
- package/dist/src/daemon/runtime-hints.d.ts +0 -19
- package/dist/src/daemon/script-utils.d.ts +0 -28
- package/dist/src/daemon/scroll-planner.d.ts +0 -12
- package/dist/src/daemon/selectors-build.d.ts +0 -5
- package/dist/src/daemon/selectors-match.d.ts +0 -6
- package/dist/src/daemon/selectors-parse.d.ts +0 -29
- package/dist/src/daemon/selectors-resolve.d.ts +0 -33
- package/dist/src/daemon/selectors.d.ts +0 -5
- package/dist/src/daemon/server-lifecycle.d.ts +0 -23
- package/dist/src/daemon/session-open-script.d.ts +0 -7
- package/dist/src/daemon/session-routing.d.ts +0 -3
- package/dist/src/daemon/session-selector.d.ts +0 -10
- package/dist/src/daemon/session-store.d.ts +0 -33
- package/dist/src/daemon/snapshot-diff.d.ts +0 -20
- package/dist/src/daemon/snapshot-processing.d.ts +0 -10
- package/dist/src/daemon/touch-reference-frame.d.ts +0 -7
- package/dist/src/daemon/transport.d.ts +0 -6
- package/dist/src/daemon/types.d.ts +0 -173
- package/dist/src/daemon/upload-registry.d.ts +0 -7
- package/dist/src/daemon/upload.d.ts +0 -5
- package/dist/src/daemon-client.d.ts +0 -40
- package/dist/src/daemon.d.ts +0 -1
- package/dist/src/platforms/android/adb.d.ts +0 -5
- package/dist/src/platforms/android/app-lifecycle.d.ts +0 -31
- package/dist/src/platforms/android/device-input-state.d.ts +0 -19
- package/dist/src/platforms/android/devices.d.ts +0 -26
- package/dist/src/platforms/android/index.d.ts +0 -8
- package/dist/src/platforms/android/input-actions.d.ts +0 -17
- package/dist/src/platforms/android/install-artifact.d.ts +0 -11
- package/dist/src/platforms/android/manifest.d.ts +0 -1
- package/dist/src/platforms/android/notifications.d.ts +0 -11
- package/dist/src/platforms/android/open-target.d.ts +0 -4
- package/dist/src/platforms/android/screenshot.d.ts +0 -16
- package/dist/src/platforms/android/sdk.d.ts +0 -2
- package/dist/src/platforms/android/settings.d.ts +0 -3
- package/dist/src/platforms/android/snapshot.d.ts +0 -7
- package/dist/src/platforms/android/ui-hierarchy.d.ts +0 -21
- package/dist/src/platforms/appearance.d.ts +0 -2
- package/dist/src/platforms/boot-diagnostics.d.ts +0 -14
- package/dist/src/platforms/install-source.d.ts +0 -29
- package/dist/src/platforms/ios/app-filter.d.ts +0 -2
- package/dist/src/platforms/ios/apps.d.ts +0 -34
- package/dist/src/platforms/ios/config.d.ts +0 -10
- package/dist/src/platforms/ios/devicectl.d.ts +0 -13
- package/dist/src/platforms/ios/devices.d.ts +0 -40
- package/dist/src/platforms/ios/ensure-simulator.d.ts +0 -18
- package/dist/src/platforms/ios/index.d.ts +0 -3
- package/dist/src/platforms/ios/install-artifact.d.ts +0 -18
- package/dist/src/platforms/ios/launch-diagnostics.d.ts +0 -11
- package/dist/src/platforms/ios/macos-apps.d.ts +0 -12
- package/dist/src/platforms/ios/macos-helper.d.ts +0 -69
- package/dist/src/platforms/ios/plist.d.ts +0 -1
- package/dist/src/platforms/ios/runner-client.d.ts +0 -38
- package/dist/src/platforms/ios/runner-errors.d.ts +0 -20
- package/dist/src/platforms/ios/runner-macos-products.d.ts +0 -3
- package/dist/src/platforms/ios/runner-session.d.ts +0 -30
- package/dist/src/platforms/ios/runner-transport.d.ts +0 -10
- package/dist/src/platforms/ios/runner-xctestrun-products.d.ts +0 -2
- package/dist/src/platforms/ios/runner-xctestrun.d.ts +0 -38
- package/dist/src/platforms/ios/screenshot-status-bar.d.ts +0 -2
- package/dist/src/platforms/ios/screenshot.d.ts +0 -14
- package/dist/src/platforms/ios/simctl.d.ts +0 -7
- package/dist/src/platforms/ios/simulator.d.ts +0 -11
- package/dist/src/platforms/permission-utils.d.ts +0 -9
- package/dist/src/recording/overlay.d.ts +0 -10
- package/dist/src/upload-client.d.ts +0 -7
- package/dist/src/utils/args.d.ts +0 -27
- package/dist/src/utils/cli-config.d.ts +0 -10
- package/dist/src/utils/cli-option-schema.d.ts +0 -19
- package/dist/src/utils/cli-options.d.ts +0 -13
- package/dist/src/utils/command-schema.d.ts +0 -123
- package/dist/src/utils/device-isolation.d.ts +0 -3
- package/dist/src/utils/device.d.ts +0 -35
- package/dist/src/utils/diagnostics.d.ts +0 -30
- package/dist/src/utils/errors.d.ts +0 -26
- package/dist/src/utils/exec.d.ts +0 -32
- package/dist/src/utils/finders.d.ts +0 -12
- package/dist/src/utils/interactors.d.ts +0 -38
- package/dist/src/utils/json-input.d.ts +0 -1
- package/dist/src/utils/keyed-lock.d.ts +0 -1
- package/dist/src/utils/output.d.ts +0 -27
- package/dist/src/utils/path-resolution.d.ts +0 -8
- package/dist/src/utils/payload-input.d.ts +0 -12
- package/dist/src/utils/process-identity.d.ts +0 -11
- package/dist/src/utils/remote-config.d.ts +0 -15
- package/dist/src/utils/remote-open.d.ts +0 -9
- package/dist/src/utils/retry.d.ts +0 -54
- package/dist/src/utils/screenshot-diff.d.ts +0 -23
- package/dist/src/utils/session-binding.d.ts +0 -18
- package/dist/src/utils/snapshot-lines.d.ts +0 -15
- package/dist/src/utils/snapshot.d.ts +0 -49
- package/dist/src/utils/text-surface.d.ts +0 -19
- package/dist/src/utils/timeouts.d.ts +0 -3
- package/dist/src/utils/version.d.ts +0 -2
- package/dist/src/utils/video.d.ts +0 -9
package/dist/src/index.d.ts
CHANGED
|
@@ -1,5 +1,559 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
1
|
+
declare type AgentDeviceClient = {
|
|
2
|
+
devices: {
|
|
3
|
+
list: (options?: AgentDeviceRequestOverrides & AgentDeviceSelectionOptions) => Promise<AgentDeviceDevice[]>;
|
|
4
|
+
};
|
|
5
|
+
sessions: {
|
|
6
|
+
list: (options?: AgentDeviceRequestOverrides) => Promise<AgentDeviceSession[]>;
|
|
7
|
+
close: (options?: AgentDeviceRequestOverrides & {
|
|
8
|
+
shutdown?: boolean;
|
|
9
|
+
}) => Promise<SessionCloseResult>;
|
|
10
|
+
};
|
|
11
|
+
simulators: {
|
|
12
|
+
ensure: (options: EnsureSimulatorOptions) => Promise<EnsureSimulatorResult>;
|
|
13
|
+
};
|
|
14
|
+
apps: {
|
|
15
|
+
install: (options: AppDeployOptions) => Promise<AppDeployResult>;
|
|
16
|
+
reinstall: (options: AppDeployOptions) => Promise<AppDeployResult>;
|
|
17
|
+
installFromSource: (options: AppInstallFromSourceOptions) => Promise<AppInstallFromSourceResult>;
|
|
18
|
+
open: (options: AppOpenOptions) => Promise<AppOpenResult>;
|
|
19
|
+
close: (options?: AppCloseOptions) => Promise<AppCloseResult>;
|
|
20
|
+
};
|
|
21
|
+
materializations: {
|
|
22
|
+
release: (options: MaterializationReleaseOptions) => Promise<MaterializationReleaseResult>;
|
|
23
|
+
};
|
|
24
|
+
metro: {
|
|
25
|
+
prepare: (options: MetroPrepareOptions) => Promise<MetroPrepareResult>;
|
|
26
|
+
};
|
|
27
|
+
capture: {
|
|
28
|
+
snapshot: (options?: CaptureSnapshotOptions) => Promise<CaptureSnapshotResult>;
|
|
29
|
+
screenshot: (options?: CaptureScreenshotOptions) => Promise<CaptureScreenshotResult>;
|
|
30
|
+
};
|
|
31
|
+
};
|
|
32
|
+
|
|
33
|
+
declare type AgentDeviceClientConfig = {
|
|
34
|
+
session?: string;
|
|
35
|
+
lockPolicy?: DaemonLockPolicy;
|
|
36
|
+
lockPlatform?: PlatformSelector;
|
|
37
|
+
requestId?: string;
|
|
38
|
+
stateDir?: string;
|
|
39
|
+
daemonBaseUrl?: string;
|
|
40
|
+
daemonAuthToken?: string;
|
|
41
|
+
daemonTransport?: DaemonTransportMode;
|
|
42
|
+
daemonServerMode?: DaemonServerMode;
|
|
43
|
+
tenant?: string;
|
|
44
|
+
sessionIsolation?: SessionIsolationMode;
|
|
45
|
+
runId?: string;
|
|
46
|
+
leaseId?: string;
|
|
47
|
+
cwd?: string;
|
|
48
|
+
debug?: boolean;
|
|
49
|
+
};
|
|
50
|
+
|
|
51
|
+
declare type AgentDeviceDaemonTransport = (req: Omit<DaemonRequest, 'token'>) => Promise<DaemonResponse>;
|
|
52
|
+
|
|
53
|
+
declare type AgentDeviceDevice = {
|
|
54
|
+
platform: Platform;
|
|
55
|
+
target: DeviceTarget;
|
|
56
|
+
kind: DeviceKind;
|
|
57
|
+
id: string;
|
|
58
|
+
name: string;
|
|
59
|
+
booted?: boolean;
|
|
60
|
+
identifiers: AgentDeviceIdentifiers;
|
|
61
|
+
ios?: {
|
|
62
|
+
udid: string;
|
|
63
|
+
};
|
|
64
|
+
android?: {
|
|
65
|
+
serial: string;
|
|
66
|
+
};
|
|
67
|
+
};
|
|
68
|
+
|
|
69
|
+
declare type AgentDeviceIdentifiers = {
|
|
70
|
+
session?: string;
|
|
71
|
+
deviceId?: string;
|
|
72
|
+
deviceName?: string;
|
|
73
|
+
udid?: string;
|
|
74
|
+
serial?: string;
|
|
75
|
+
appId?: string;
|
|
76
|
+
appBundleId?: string;
|
|
77
|
+
package?: string;
|
|
78
|
+
};
|
|
79
|
+
|
|
80
|
+
declare type AgentDeviceRequestOverrides = Pick<AgentDeviceClientConfig, 'session' | 'lockPolicy' | 'lockPlatform' | 'requestId' | 'tenant' | 'sessionIsolation' | 'runId' | 'leaseId' | 'cwd' | 'debug'>;
|
|
81
|
+
|
|
82
|
+
declare type AgentDeviceSelectionOptions = {
|
|
83
|
+
platform?: PlatformSelector;
|
|
84
|
+
target?: DeviceTarget;
|
|
85
|
+
device?: string;
|
|
86
|
+
udid?: string;
|
|
87
|
+
serial?: string;
|
|
88
|
+
iosSimulatorDeviceSet?: string;
|
|
89
|
+
androidDeviceAllowlist?: string;
|
|
90
|
+
};
|
|
91
|
+
|
|
92
|
+
declare type AgentDeviceSession = {
|
|
93
|
+
name: string;
|
|
94
|
+
createdAt: number;
|
|
95
|
+
device: AgentDeviceSessionDevice;
|
|
96
|
+
identifiers: AgentDeviceIdentifiers;
|
|
97
|
+
};
|
|
98
|
+
|
|
99
|
+
declare type AgentDeviceSessionDevice = {
|
|
100
|
+
platform: Platform;
|
|
101
|
+
target: DeviceTarget;
|
|
102
|
+
id: string;
|
|
103
|
+
name: string;
|
|
104
|
+
identifiers: AgentDeviceIdentifiers;
|
|
105
|
+
ios?: {
|
|
106
|
+
udid: string;
|
|
107
|
+
simulatorSetPath?: string | null;
|
|
108
|
+
};
|
|
109
|
+
android?: {
|
|
110
|
+
serial: string;
|
|
111
|
+
};
|
|
112
|
+
};
|
|
113
|
+
|
|
114
|
+
declare type AppCloseOptions = AgentDeviceRequestOverrides & {
|
|
115
|
+
app?: string;
|
|
116
|
+
shutdown?: boolean;
|
|
117
|
+
};
|
|
118
|
+
|
|
119
|
+
declare type AppCloseResult = {
|
|
120
|
+
session: string;
|
|
121
|
+
closedApp?: string;
|
|
122
|
+
shutdown?: Record<string, unknown>;
|
|
123
|
+
identifiers: AgentDeviceIdentifiers;
|
|
124
|
+
};
|
|
125
|
+
|
|
126
|
+
declare type AppDeployOptions = AgentDeviceRequestOverrides & AgentDeviceSelectionOptions & {
|
|
127
|
+
app: string;
|
|
128
|
+
appPath: string;
|
|
129
|
+
};
|
|
130
|
+
|
|
131
|
+
declare type AppDeployResult = {
|
|
132
|
+
app: string;
|
|
133
|
+
appPath: string;
|
|
134
|
+
platform: Platform;
|
|
135
|
+
appId?: string;
|
|
136
|
+
bundleId?: string;
|
|
137
|
+
package?: string;
|
|
138
|
+
identifiers: AgentDeviceIdentifiers;
|
|
139
|
+
};
|
|
140
|
+
|
|
141
|
+
export declare class AppError extends Error {
|
|
142
|
+
code: ErrorCode;
|
|
143
|
+
details?: AppErrorDetails;
|
|
144
|
+
cause?: unknown;
|
|
145
|
+
constructor(code: ErrorCode, message: string, details?: AppErrorDetails, cause?: unknown);
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
declare type AppErrorDetails = Record<string, unknown> & {
|
|
149
|
+
hint?: string;
|
|
150
|
+
diagnosticId?: string;
|
|
151
|
+
logPath?: string;
|
|
152
|
+
};
|
|
153
|
+
|
|
154
|
+
declare type AppInstallFromSourceOptions = AgentDeviceRequestOverrides & AgentDeviceSelectionOptions & {
|
|
155
|
+
source: DaemonInstallSource;
|
|
156
|
+
retainPaths?: boolean;
|
|
157
|
+
retentionMs?: number;
|
|
158
|
+
};
|
|
159
|
+
|
|
160
|
+
declare type AppInstallFromSourceResult = {
|
|
161
|
+
appName?: string;
|
|
162
|
+
appId?: string;
|
|
163
|
+
bundleId?: string;
|
|
164
|
+
packageName?: string;
|
|
165
|
+
launchTarget: string;
|
|
166
|
+
installablePath?: string;
|
|
167
|
+
archivePath?: string;
|
|
168
|
+
materializationId?: string;
|
|
169
|
+
materializationExpiresAt?: string;
|
|
170
|
+
identifiers: AgentDeviceIdentifiers;
|
|
171
|
+
};
|
|
172
|
+
|
|
173
|
+
declare type ApplePlatform = 'ios' | 'macos';
|
|
174
|
+
|
|
175
|
+
declare type AppOpenOptions = AgentDeviceRequestOverrides & AgentDeviceSelectionOptions & {
|
|
176
|
+
app: string;
|
|
177
|
+
url?: string;
|
|
178
|
+
activity?: string;
|
|
179
|
+
relaunch?: boolean;
|
|
180
|
+
saveScript?: boolean | string;
|
|
181
|
+
noRecord?: boolean;
|
|
182
|
+
runtime?: SessionRuntimeHints;
|
|
183
|
+
};
|
|
184
|
+
|
|
185
|
+
declare type AppOpenResult = {
|
|
186
|
+
session: string;
|
|
187
|
+
appName?: string;
|
|
188
|
+
appBundleId?: string;
|
|
189
|
+
appId?: string;
|
|
190
|
+
startup?: StartupPerfSample;
|
|
191
|
+
runtime?: SessionRuntimeHints;
|
|
192
|
+
device?: AgentDeviceSessionDevice;
|
|
193
|
+
identifiers: AgentDeviceIdentifiers;
|
|
194
|
+
};
|
|
195
|
+
|
|
196
|
+
declare type BatchStep = {
|
|
197
|
+
command: string;
|
|
198
|
+
positionals?: string[];
|
|
199
|
+
flags?: Partial<CommandFlags>;
|
|
200
|
+
runtime?: unknown;
|
|
201
|
+
};
|
|
202
|
+
|
|
203
|
+
declare type CaptureScreenshotOptions = AgentDeviceRequestOverrides & {
|
|
204
|
+
path?: string;
|
|
205
|
+
};
|
|
206
|
+
|
|
207
|
+
declare type CaptureScreenshotResult = {
|
|
208
|
+
path: string;
|
|
209
|
+
identifiers: AgentDeviceIdentifiers;
|
|
210
|
+
};
|
|
211
|
+
|
|
212
|
+
declare type CaptureSnapshotOptions = AgentDeviceRequestOverrides & AgentDeviceSelectionOptions & {
|
|
213
|
+
interactiveOnly?: boolean;
|
|
214
|
+
compact?: boolean;
|
|
215
|
+
depth?: number;
|
|
216
|
+
scope?: string;
|
|
217
|
+
raw?: boolean;
|
|
218
|
+
};
|
|
219
|
+
|
|
220
|
+
declare type CaptureSnapshotResult = {
|
|
221
|
+
nodes: SnapshotNode[];
|
|
222
|
+
truncated: boolean;
|
|
223
|
+
appName?: string;
|
|
224
|
+
appBundleId?: string;
|
|
225
|
+
identifiers: AgentDeviceIdentifiers;
|
|
226
|
+
};
|
|
227
|
+
|
|
228
|
+
declare type CliFlags = {
|
|
229
|
+
json: boolean;
|
|
230
|
+
config?: string;
|
|
231
|
+
remoteConfig?: string;
|
|
232
|
+
stateDir?: string;
|
|
233
|
+
daemonBaseUrl?: string;
|
|
234
|
+
daemonAuthToken?: string;
|
|
235
|
+
daemonTransport?: 'auto' | 'socket' | 'http';
|
|
236
|
+
daemonServerMode?: 'socket' | 'http' | 'dual';
|
|
237
|
+
tenant?: string;
|
|
238
|
+
sessionIsolation?: 'none' | 'tenant';
|
|
239
|
+
runId?: string;
|
|
240
|
+
leaseId?: string;
|
|
241
|
+
sessionLock?: 'reject' | 'strip';
|
|
242
|
+
sessionLocked?: boolean;
|
|
243
|
+
sessionLockConflicts?: 'reject' | 'strip';
|
|
244
|
+
platform?: 'ios' | 'macos' | 'android' | 'apple';
|
|
245
|
+
target?: 'mobile' | 'tv' | 'desktop';
|
|
246
|
+
device?: string;
|
|
247
|
+
udid?: string;
|
|
248
|
+
serial?: string;
|
|
249
|
+
iosSimulatorDeviceSet?: string;
|
|
250
|
+
androidDeviceAllowlist?: string;
|
|
251
|
+
out?: string;
|
|
252
|
+
session?: string;
|
|
253
|
+
runtime?: string;
|
|
254
|
+
metroHost?: string;
|
|
255
|
+
metroPort?: number;
|
|
256
|
+
metroProjectRoot?: string;
|
|
257
|
+
metroKind?: 'auto' | 'react-native' | 'expo';
|
|
258
|
+
metroPublicBaseUrl?: string;
|
|
259
|
+
metroProxyBaseUrl?: string;
|
|
260
|
+
metroBearerToken?: string;
|
|
261
|
+
metroPreparePort?: number;
|
|
262
|
+
metroListenHost?: string;
|
|
263
|
+
metroStatusHost?: string;
|
|
264
|
+
metroStartupTimeoutMs?: number;
|
|
265
|
+
metroProbeTimeoutMs?: number;
|
|
266
|
+
metroRuntimeFile?: string;
|
|
267
|
+
metroNoReuseExisting?: boolean;
|
|
268
|
+
metroNoInstallDeps?: boolean;
|
|
269
|
+
bundleUrl?: string;
|
|
270
|
+
launchUrl?: string;
|
|
271
|
+
boot?: boolean;
|
|
272
|
+
reuseExisting?: boolean;
|
|
273
|
+
verbose?: boolean;
|
|
274
|
+
snapshotInteractiveOnly?: boolean;
|
|
275
|
+
snapshotCompact?: boolean;
|
|
276
|
+
snapshotDepth?: number;
|
|
277
|
+
snapshotScope?: string;
|
|
278
|
+
snapshotRaw?: boolean;
|
|
279
|
+
baseline?: string;
|
|
280
|
+
threshold?: string;
|
|
281
|
+
appsFilter?: 'user-installed' | 'all';
|
|
282
|
+
count?: number;
|
|
283
|
+
fps?: number;
|
|
284
|
+
hideTouches?: boolean;
|
|
285
|
+
intervalMs?: number;
|
|
286
|
+
holdMs?: number;
|
|
287
|
+
jitterPx?: number;
|
|
288
|
+
doubleTap?: boolean;
|
|
289
|
+
clickButton?: 'primary' | 'secondary' | 'middle';
|
|
290
|
+
pauseMs?: number;
|
|
291
|
+
pattern?: 'one-way' | 'ping-pong';
|
|
292
|
+
activity?: string;
|
|
293
|
+
header?: string[];
|
|
294
|
+
saveScript?: boolean | string;
|
|
295
|
+
shutdown?: boolean;
|
|
296
|
+
relaunch?: boolean;
|
|
297
|
+
surface?: 'app' | 'frontmost-app' | 'desktop' | 'menubar';
|
|
298
|
+
headless?: boolean;
|
|
299
|
+
restart?: boolean;
|
|
300
|
+
noRecord?: boolean;
|
|
301
|
+
retainPaths?: boolean;
|
|
302
|
+
retentionMs?: number;
|
|
303
|
+
replayUpdate?: boolean;
|
|
304
|
+
steps?: string;
|
|
305
|
+
stepsFile?: string;
|
|
306
|
+
batchOnError?: 'stop';
|
|
307
|
+
batchMaxSteps?: number;
|
|
308
|
+
batchSteps?: Array<{
|
|
309
|
+
command: string;
|
|
310
|
+
positionals?: string[];
|
|
311
|
+
flags?: Record<string, unknown>;
|
|
312
|
+
}>;
|
|
313
|
+
help: boolean;
|
|
314
|
+
version: boolean;
|
|
315
|
+
};
|
|
316
|
+
|
|
317
|
+
declare type CommandFlags = Omit<CliFlags, 'json' | 'help' | 'version' | 'batchSteps'> & {
|
|
318
|
+
batchSteps?: BatchStep[];
|
|
319
|
+
};
|
|
320
|
+
|
|
321
|
+
export declare function createAgentDeviceClient(config?: AgentDeviceClientConfig, deps?: {
|
|
322
|
+
transport?: AgentDeviceDaemonTransport;
|
|
323
|
+
}): AgentDeviceClient;
|
|
324
|
+
|
|
325
|
+
declare type DaemonArtifact = {
|
|
326
|
+
field: string;
|
|
327
|
+
artifactId?: string;
|
|
328
|
+
fileName?: string;
|
|
329
|
+
localPath?: string;
|
|
330
|
+
path?: string;
|
|
331
|
+
};
|
|
332
|
+
|
|
333
|
+
declare type DaemonInstallSource = MaterializeInstallSource;
|
|
334
|
+
|
|
335
|
+
declare type DaemonLockPolicy = 'reject' | 'strip';
|
|
336
|
+
|
|
337
|
+
declare type DaemonRequest = {
|
|
338
|
+
token: string;
|
|
339
|
+
session: string;
|
|
340
|
+
command: string;
|
|
341
|
+
positionals: string[];
|
|
342
|
+
flags?: CommandFlags;
|
|
343
|
+
runtime?: SessionRuntimeHints;
|
|
344
|
+
meta?: {
|
|
345
|
+
requestId?: string;
|
|
346
|
+
debug?: boolean;
|
|
347
|
+
cwd?: string;
|
|
348
|
+
tenantId?: string;
|
|
349
|
+
runId?: string;
|
|
350
|
+
leaseId?: string;
|
|
351
|
+
leaseTtlMs?: number;
|
|
352
|
+
leaseBackend?: 'ios-simulator';
|
|
353
|
+
sessionIsolation?: 'none' | 'tenant';
|
|
354
|
+
uploadedArtifactId?: string;
|
|
355
|
+
clientArtifactPaths?: Record<string, string>;
|
|
356
|
+
installSource?: DaemonInstallSource;
|
|
357
|
+
retainMaterializedPaths?: boolean;
|
|
358
|
+
materializedPathRetentionMs?: number;
|
|
359
|
+
materializationId?: string;
|
|
360
|
+
lockPolicy?: DaemonLockPolicy;
|
|
361
|
+
lockPlatform?: PlatformSelector;
|
|
362
|
+
};
|
|
363
|
+
};
|
|
364
|
+
|
|
365
|
+
declare type DaemonResponse = {
|
|
366
|
+
ok: true;
|
|
367
|
+
data?: DaemonResponseData;
|
|
368
|
+
} | {
|
|
369
|
+
ok: false;
|
|
370
|
+
error: {
|
|
371
|
+
code: string;
|
|
372
|
+
message: string;
|
|
373
|
+
hint?: string;
|
|
374
|
+
diagnosticId?: string;
|
|
375
|
+
logPath?: string;
|
|
376
|
+
details?: Record<string, unknown>;
|
|
377
|
+
};
|
|
378
|
+
};
|
|
379
|
+
|
|
380
|
+
declare type DaemonResponseData = Record<string, unknown> & {
|
|
381
|
+
artifacts?: DaemonArtifact[];
|
|
382
|
+
};
|
|
383
|
+
|
|
384
|
+
declare type DaemonServerMode = 'socket' | 'http' | 'dual';
|
|
385
|
+
|
|
386
|
+
declare type DaemonTransportMode = 'auto' | 'socket' | 'http';
|
|
387
|
+
|
|
388
|
+
declare type DeviceKind = 'simulator' | 'emulator' | 'device';
|
|
389
|
+
|
|
390
|
+
declare type DeviceTarget = 'mobile' | 'tv' | 'desktop';
|
|
391
|
+
|
|
392
|
+
declare type EnsureSimulatorOptions = AgentDeviceRequestOverrides & {
|
|
393
|
+
device: string;
|
|
394
|
+
runtime?: string;
|
|
395
|
+
boot?: boolean;
|
|
396
|
+
reuseExisting?: boolean;
|
|
397
|
+
iosSimulatorDeviceSet?: string;
|
|
398
|
+
};
|
|
399
|
+
|
|
400
|
+
declare type EnsureSimulatorResult = {
|
|
401
|
+
udid: string;
|
|
402
|
+
device: string;
|
|
403
|
+
runtime: string;
|
|
404
|
+
created: boolean;
|
|
405
|
+
booted: boolean;
|
|
406
|
+
iosSimulatorDeviceSet?: string | null;
|
|
407
|
+
identifiers: AgentDeviceIdentifiers;
|
|
408
|
+
};
|
|
409
|
+
|
|
410
|
+
declare type ErrorCode = 'INVALID_ARGS' | 'DEVICE_NOT_FOUND' | 'TOOL_MISSING' | 'APP_NOT_INSTALLED' | 'UNSUPPORTED_PLATFORM' | 'UNSUPPORTED_OPERATION' | 'COMMAND_FAILED' | 'SESSION_NOT_FOUND' | 'UNAUTHORIZED' | 'UNKNOWN';
|
|
411
|
+
|
|
412
|
+
declare type MaterializationReleaseOptions = AgentDeviceRequestOverrides & {
|
|
413
|
+
materializationId: string;
|
|
414
|
+
};
|
|
415
|
+
|
|
416
|
+
declare type MaterializationReleaseResult = {
|
|
417
|
+
released: boolean;
|
|
418
|
+
materializationId: string;
|
|
419
|
+
identifiers: AgentDeviceIdentifiers;
|
|
420
|
+
};
|
|
421
|
+
|
|
422
|
+
declare type MaterializeInstallSource = {
|
|
423
|
+
kind: 'url';
|
|
424
|
+
url: string;
|
|
425
|
+
headers?: Record<string, string>;
|
|
426
|
+
} | {
|
|
427
|
+
kind: 'path';
|
|
428
|
+
path: string;
|
|
429
|
+
};
|
|
430
|
+
|
|
431
|
+
declare type MetroBridgeResult = {
|
|
432
|
+
enabled: boolean;
|
|
433
|
+
baseUrl: string;
|
|
434
|
+
statusUrl: string;
|
|
435
|
+
bundleUrl: string;
|
|
436
|
+
iosRuntime: MetroRuntimeHints;
|
|
437
|
+
androidRuntime: MetroRuntimeHints;
|
|
438
|
+
upstream: {
|
|
439
|
+
bundleUrl: string;
|
|
440
|
+
host: string;
|
|
441
|
+
port: number;
|
|
442
|
+
statusUrl: string;
|
|
443
|
+
};
|
|
444
|
+
probe: {
|
|
445
|
+
reachable: boolean;
|
|
446
|
+
statusCode: number;
|
|
447
|
+
latencyMs: number;
|
|
448
|
+
detail: string;
|
|
449
|
+
};
|
|
450
|
+
};
|
|
451
|
+
|
|
452
|
+
declare type MetroPrepareKind = 'auto' | 'react-native' | 'expo';
|
|
453
|
+
|
|
454
|
+
declare type MetroPrepareOptions = {
|
|
455
|
+
projectRoot?: string;
|
|
456
|
+
kind?: MetroPrepareKind;
|
|
457
|
+
publicBaseUrl: string;
|
|
458
|
+
proxyBaseUrl?: string;
|
|
459
|
+
bearerToken?: string;
|
|
460
|
+
port?: number;
|
|
461
|
+
listenHost?: string;
|
|
462
|
+
statusHost?: string;
|
|
463
|
+
startupTimeoutMs?: number;
|
|
464
|
+
probeTimeoutMs?: number;
|
|
465
|
+
reuseExisting?: boolean;
|
|
466
|
+
installDependenciesIfNeeded?: boolean;
|
|
467
|
+
runtimeFilePath?: string;
|
|
468
|
+
logPath?: string;
|
|
469
|
+
};
|
|
470
|
+
|
|
471
|
+
declare type MetroPrepareResult = PrepareMetroRuntimeResult;
|
|
472
|
+
|
|
473
|
+
declare type MetroRuntimeHints = {
|
|
474
|
+
platform?: 'ios' | 'android';
|
|
475
|
+
metroHost?: string;
|
|
476
|
+
metroPort?: number;
|
|
477
|
+
bundleUrl?: string;
|
|
478
|
+
launchUrl?: string;
|
|
479
|
+
};
|
|
480
|
+
|
|
481
|
+
declare type Platform = ApplePlatform | 'android';
|
|
482
|
+
|
|
483
|
+
declare type PlatformSelector = Platform | 'apple';
|
|
484
|
+
|
|
485
|
+
declare type PrepareMetroRuntimeResult = {
|
|
486
|
+
projectRoot: string;
|
|
487
|
+
kind: ResolvedMetroKind;
|
|
488
|
+
dependenciesInstalled: boolean;
|
|
489
|
+
packageManager: string | null;
|
|
490
|
+
started: boolean;
|
|
491
|
+
reused: boolean;
|
|
492
|
+
pid: number;
|
|
493
|
+
logPath: string;
|
|
494
|
+
statusUrl: string;
|
|
495
|
+
runtimeFilePath: string | null;
|
|
496
|
+
iosRuntime: MetroRuntimeHints;
|
|
497
|
+
androidRuntime: MetroRuntimeHints;
|
|
498
|
+
bridge: MetroBridgeResult | null;
|
|
499
|
+
};
|
|
500
|
+
|
|
501
|
+
declare type RawSnapshotNode = {
|
|
502
|
+
index: number;
|
|
503
|
+
type?: string;
|
|
504
|
+
role?: string;
|
|
505
|
+
subrole?: string;
|
|
506
|
+
label?: string;
|
|
507
|
+
value?: string;
|
|
508
|
+
identifier?: string;
|
|
509
|
+
rect?: Rect;
|
|
510
|
+
enabled?: boolean;
|
|
511
|
+
selected?: boolean;
|
|
512
|
+
hittable?: boolean;
|
|
513
|
+
depth?: number;
|
|
514
|
+
parentIndex?: number;
|
|
515
|
+
pid?: number;
|
|
516
|
+
bundleId?: string;
|
|
517
|
+
appName?: string;
|
|
518
|
+
windowTitle?: string;
|
|
519
|
+
surface?: string;
|
|
520
|
+
};
|
|
521
|
+
|
|
522
|
+
declare type Rect = {
|
|
523
|
+
x: number;
|
|
524
|
+
y: number;
|
|
525
|
+
width: number;
|
|
526
|
+
height: number;
|
|
527
|
+
};
|
|
528
|
+
|
|
529
|
+
declare type ResolvedMetroKind = Exclude<MetroPrepareKind, 'auto'>;
|
|
530
|
+
|
|
531
|
+
declare type SessionCloseResult = {
|
|
532
|
+
session: string;
|
|
533
|
+
shutdown?: Record<string, unknown>;
|
|
534
|
+
identifiers: AgentDeviceIdentifiers;
|
|
535
|
+
};
|
|
536
|
+
|
|
537
|
+
declare type SessionIsolationMode = 'none' | 'tenant';
|
|
538
|
+
|
|
539
|
+
declare type SessionRuntimeHints = {
|
|
540
|
+
platform?: 'ios' | 'android';
|
|
541
|
+
metroHost?: string;
|
|
542
|
+
metroPort?: number;
|
|
543
|
+
bundleUrl?: string;
|
|
544
|
+
launchUrl?: string;
|
|
545
|
+
};
|
|
546
|
+
|
|
547
|
+
declare type SnapshotNode = RawSnapshotNode & {
|
|
548
|
+
ref: string;
|
|
549
|
+
};
|
|
550
|
+
|
|
551
|
+
declare type StartupPerfSample = {
|
|
552
|
+
durationMs: number;
|
|
553
|
+
measuredAt: string;
|
|
554
|
+
method: string;
|
|
555
|
+
appTarget?: string;
|
|
556
|
+
appBundleId?: string;
|
|
557
|
+
};
|
|
558
|
+
|
|
559
|
+
export { }
|
package/dist/src/index.js
CHANGED
|
@@ -1 +1,3 @@
|
|
|
1
|
-
|
|
1
|
+
import e from"node:net";import t from"node:http";import r from"node:https";import n from"node:fs";import o from"node:path";import{AsyncLocalStorage as a}from"node:async_hooks";import i from"node:crypto";import s from"node:os";import{spawn as l,spawnSync as d}from"node:child_process";import{fileURLToPath as u}from"node:url";let c=new a,m=/(token|secret|password|authorization|cookie|api[_-]?key|access[_-]?key|private[_-]?key)/i,p=/(bearer\s+[a-z0-9._-]+|(?:api[_-]?key|token|secret|password)\s*[=:]\s*\S+)/i;function f(){return i.randomBytes(8).toString("hex")}function h(e){let t=c.getStore();if(!t)return;let r={ts:new Date().toISOString(),level:e.level??"info",phase:e.phase,session:t.session,requestId:t.requestId,command:t.command,durationMs:e.durationMs,data:e.data?function e(t,r,n){if(null==t)return t;if("string"==typeof t){var o=t,a=n;let e=o.trim();if(!e)return o;if(a&&m.test(a)||p.test(e))return"[REDACTED]";let r=function(e){try{let t=new URL(e);return t.search&&(t.search="?REDACTED"),(t.username||t.password)&&(t.username="REDACTED",t.password="REDACTED"),t.toString()}catch{return null}}(e);return r||(e.length>400?`${e.slice(0,200)}...<truncated>`:e)}if("object"!=typeof t)return t;if(r.has(t))return"[Circular]";if(r.add(t),Array.isArray(t))return t.map(t=>e(t,r));let i={};for(let[n,o]of Object.entries(t)){if(m.test(n)){i[n]="[REDACTED]";continue}i[n]=e(o,r,n)}return i}(e.data,new WeakSet):void 0};if(t.events.push(r),!t.debug)return;let o=`[agent-device][diag] ${JSON.stringify(r)}
|
|
2
|
+
`;try{t.logPath&&n.appendFile(t.logPath,o,()=>{}),t.traceLogPath&&n.appendFile(t.traceLogPath,o,()=>{}),t.logPath||t.traceLogPath||process.stderr.write(o)}catch{}}async function g(e,t,r){let n=Date.now();try{let o=await t();return h({level:"info",phase:e,durationMs:Date.now()-n,data:r}),o}catch(t){throw h({level:"error",phase:e,durationMs:Date.now()-n,data:{...r??{},error:t instanceof Error?t.message:String(t)}}),t}}class w extends Error{code;details;cause;constructor(e,t,r,n){super(t),this.code=e,this.details=r,this.cause=n}}function I(e,t,r={}){let n=d(e,t,{cwd:r.cwd,env:r.env,stdio:["pipe","pipe","pipe"],encoding:r.binaryStdout?void 0:"utf8",input:r.stdin,timeout:y(r.timeoutMs)});if(n.error){let o=n.error.code;if("ETIMEDOUT"===o)throw new w("COMMAND_FAILED",`${e} timed out after ${y(r.timeoutMs)}ms`,{cmd:e,args:t,timeoutMs:y(r.timeoutMs)},n.error);if("ENOENT"===o)throw new w("TOOL_MISSING",`${e} not found in PATH`,{cmd:e},n.error);throw new w("COMMAND_FAILED",`Failed to run ${e}`,{cmd:e,args:t},n.error)}let o=r.binaryStdout?Buffer.isBuffer(n.stdout)?n.stdout:Buffer.from(n.stdout??""):void 0,a=r.binaryStdout?"":"string"==typeof n.stdout?n.stdout:(n.stdout??"").toString(),i="string"==typeof n.stderr?n.stderr:(n.stderr??"").toString(),s=n.status??1;if(0!==s&&!r.allowFailure)throw new w("COMMAND_FAILED",`${e} exited with code ${s}`,{cmd:e,args:t,stdout:a,stderr:i,exitCode:s,processExitError:!0});return{stdout:a,stderr:i,exitCode:s,stdoutBuffer:o}}function y(e){if(!Number.isFinite(e))return;let t=Math.floor(e);if(!(t<=0))return t}function b(){let e=o.dirname(u(import.meta.url)),t=e;for(let e=0;e<6;e+=1){let e=o.join(t,"package.json");if(n.existsSync(e))return t;t=o.dirname(t)}return e}let v=[/(^|[\/\s"'=])dist\/src\/daemon\.js($|[\s"'])/,/(^|[\/\s"'=])src\/daemon\.ts($|[\s"'])/];function A(e){if(!Number.isInteger(e)||e<=0)return!1;try{return process.kill(e,0),!0}catch(e){return"EPERM"===e.code}}function D(e,t){let r;if(!A(e))return!1;if(t){let r=function(e){if(!Number.isInteger(e)||e<=0)return null;try{let t=I("ps",["-p",String(e),"-o","lstart="],{allowFailure:!0,timeoutMs:1e3});if(0!==t.exitCode)return null;let r=t.stdout.trim();return r.length>0?r:null}catch{return null}}(e);if(!r||r!==t)return!1}let n=function(e){if(!Number.isInteger(e)||e<=0)return null;try{let t=I("ps",["-p",String(e),"-o","command="],{allowFailure:!0,timeoutMs:1e3});if(0!==t.exitCode)return null;let r=t.stdout.trim();return r.length>0?r:null}catch{return null}}(e);return!!n&&!!(r=n.toLowerCase().replaceAll("\\","/")).includes("agent-device")&&v.some(e=>e.test(r))}function E(e,t){try{return process.kill(e,t),!0}catch(t){let e=t.code;if("ESRCH"===e||"EPERM"===e)return!1;throw t}}async function M(e,t){if(!A(e))return!0;let r=Date.now();for(;Date.now()-r<t;)if(await new Promise(e=>setTimeout(e,50)),!A(e))return!0;return!A(e)}async function S(e,t){!D(e,t.expectedStartTime)||!E(e,"SIGTERM")||await M(e,t.termTimeoutMs)||E(e,"SIGKILL")&&await M(e,t.killTimeoutMs)}function _(e){return e?.HOME?.trim()||s.homedir()}function P(e,t={}){return"~"===e?_(t.env):e.startsWith("~/")?o.join(_(t.env),e.slice(2)):e}function k(e,t={}){let r=P(e,t);return o.isAbsolute(r)?r:o.resolve(t.cwd??process.cwd(),r)}function T(e){let t,r=(t=(e??"").trim())?k(t):o.join(P("~"),".agent-device");return{baseDir:r,infoPath:o.join(r,"daemon.json"),lockPath:o.join(r,"daemon.lock"),logPath:o.join(r,"daemon.log"),sessionsDir:o.join(r,"sessions")}}async function N(e){let{localPath:a,baseUrl:i,token:s}=e,d=n.statSync(a).isDirectory(),u=o.basename(a),c=new URL("upload",i.endsWith("/")?i:`${i}/`),m="https:"===c.protocol?r:t,p={"x-artifact-type":d?"app-bundle":"file","x-artifact-filename":u,"transfer-encoding":"chunked"};return s&&(p.authorization=`Bearer ${s}`,p["x-agent-device-token"]=s),new Promise((e,t)=>{let r=m.request({protocol:c.protocol,host:c.hostname,port:c.port,method:"POST",path:c.pathname+c.search,headers:p},r=>{let n="";r.setEncoding("utf8"),r.on("data",e=>{n+=e}),r.on("end",()=>{clearTimeout(i);try{let r=JSON.parse(n);if(!r.ok||!r.uploadId)return void t(new w("COMMAND_FAILED",`Upload failed: ${n}`));e(r.uploadId)}catch{t(new w("COMMAND_FAILED",`Invalid upload response: ${n}`))}})}),i=setTimeout(()=>{r.destroy(),t(new w("COMMAND_FAILED","Artifact upload timed out",{timeoutMs:3e5,hint:"The upload to the remote daemon exceeded the 5-minute timeout."}))},3e5);if(r.on("error",e=>{clearTimeout(i),t(new w("COMMAND_FAILED","Failed to upload artifact to remote daemon",{hint:"Verify the remote daemon is reachable and supports artifact uploads."},e))}),d){let e=l("tar",["cf","-","-C",o.dirname(a),o.basename(a)],{stdio:["ignore","pipe","pipe"]});e.stdout.pipe(r),e.on("error",e=>{r.destroy(),t(new w("COMMAND_FAILED","Failed to create tar archive for app bundle",{},e))}),e.on("close",e=>{0!==e&&(r.destroy(),t(new w("COMMAND_FAILED",`tar failed with exit code ${e}`)))})}else{let e=n.createReadStream(a);e.pipe(r),e.on("error",e=>{r.destroy(),t(new w("COMMAND_FAILED","Failed to read local artifact",{},e))})}})}let R=function(e=process.env.AGENT_DEVICE_DAEMON_TIMEOUT_MS){if(!e)return 9e4;let t=Number(e);return Number.isFinite(t)?Math.max(1e3,Math.floor(t)):9e4}(),O=function(e=process.env.AGENT_DEVICE_DAEMON_STARTUP_TIMEOUT_MS){if(!e)return 15e3;let t=Number(e);return Number.isFinite(t)?Math.max(1e3,Math.floor(t)):15e3}(),U=function(e=process.env.AGENT_DEVICE_DAEMON_STARTUP_ATTEMPTS){if(!e)return 2;let t=Number(e);return Number.isFinite(t)?Math.min(5,Math.max(1,Math.floor(t))):2}(),C=["xcodebuild .*AgentDeviceRunnerUITests/RunnerTests/testCommand","xcodebuild .*AgentDeviceRunner\\.env\\.session-","xcodebuild build-for-testing .*ios-runner/AgentDeviceRunner/AgentDeviceRunner\\.xcodeproj"];async function x(e){let t=e.meta?.requestId??f(),r=!!(e.meta?.debug||e.flags?.verbose),n=function(e){let t,r,n=e.flags?.stateDir??process.env.AGENT_DEVICE_STATE_DIR,o=function(e){let t;if(e){try{t=new URL(e)}catch(t){throw new w("INVALID_ARGS","Invalid daemon base URL",{daemonBaseUrl:e},t instanceof Error?t:void 0)}if("http:"!==t.protocol&&"https:"!==t.protocol)throw new w("INVALID_ARGS","Daemon base URL must use http or https",{daemonBaseUrl:e});return t.toString().replace(/\/+$/,"")}}(e.flags?.daemonBaseUrl??process.env.AGENT_DEVICE_DAEMON_BASE_URL),a=e.flags?.daemonAuthToken??process.env.AGENT_DEVICE_DAEMON_AUTH_TOKEN,i=e.flags?.daemonTransport??process.env.AGENT_DEVICE_DAEMON_TRANSPORT,s="auto"===(t=(i??"").trim().toLowerCase())?"auto":"socket"===t?"socket":"http"===t?"http":"auto";if(o&&"socket"===s)throw new w("INVALID_ARGS","Remote daemon base URL only supports HTTP transport. Remove --daemon-transport socket.",{daemonBaseUrl:o});let l="http"===(r=(e.flags?.daemonServerMode??process.env.AGENT_DEVICE_DAEMON_SERVER_MODE??("dual"===i?"dual":void 0)??"").trim().toLowerCase())?"http":"dual"===r?"dual":"socket";return{paths:T(n),transportPreference:s,serverMode:l,remoteBaseUrl:o,remoteAuthToken:a}}(e),o=await g("daemon_startup",async()=>await j(n),{requestId:t,session:e.session}),a=await L(e,o),i={...e,positionals:a.positionals,flags:a.flags,token:o.token,meta:{...e.meta??{},requestId:t,debug:r,cwd:e.meta?.cwd,tenantId:e.meta?.tenantId??e.flags?.tenant,runId:e.meta?.runId??e.flags?.runId,leaseId:e.meta?.leaseId??e.flags?.leaseId,sessionIsolation:e.meta?.sessionIsolation??e.flags?.sessionIsolation,lockPolicy:e.meta?.lockPolicy,lockPlatform:e.meta?.lockPlatform,...a.uploadedArtifactId?{uploadedArtifactId:a.uploadedArtifactId}:{},...a.clientArtifactPaths?{clientArtifactPaths:a.clientArtifactPaths}:{},...a.installSource?{installSource:a.installSource}:{}}};return h({level:"info",phase:"daemon_request_prepare",data:{requestId:t,command:e.command,session:e.session}}),await g("daemon_request",async()=>await ee(o,i,n.transportPreference),{requestId:t,command:e.command})}async function L(e,t){let r,a=[...e.positionals??[]],i=e.flags?{...e.flags}:void 0,s=e.meta?.installSource,l={};if(es(t)){let n=function(e,t){if("screenshot"===e.command){let r=F(e,"path",".png");return t[0]?{field:"path",localPath:r,positionalIndex:0,positionalPath:q("screenshot",".png")}:{field:"path",localPath:r,positionalIndex:0,flagPath:q("screenshot",".png")}}if("record"===e.command&&"start"===(t[0]??"").toLowerCase()){let t=F(e,"outPath",".mp4",1);return{field:"outPath",localPath:t,positionalIndex:1,positionalPath:q("recording",o.extname(t)||".mp4")}}return null}(e,a);n&&(void 0!==n.positionalPath&&(a[n.positionalIndex]=n.positionalPath),void 0!==n.flagPath&&((i??={}).out=n.flagPath),l[n.field]=n.localPath);let d=await $(e,t);d&&(s=d.installSource,r=d.uploadedArtifactId??r)}if(!es(t)||"install"!==e.command&&"reinstall"!==e.command||a.length<2)return{positionals:a,flags:i,installSource:s,uploadedArtifactId:r,...Object.keys(l).length>0?{clientArtifactPaths:l}:{}};let d=a[1];if(d.startsWith("remote:"))return a[1]=d.slice(7),{positionals:a,flags:i,...Object.keys(l).length>0?{clientArtifactPaths:l}:{}};let u=o.isAbsolute(d)?d:o.resolve(e.meta?.cwd??process.cwd(),d);return n.existsSync(u)?{positionals:a,flags:i,installSource:s,uploadedArtifactId:r=await N({localPath:u,baseUrl:t.baseUrl,token:t.token}),...Object.keys(l).length>0?{clientArtifactPaths:l}:{}}:{positionals:a,flags:i,...Object.keys(l).length>0?{clientArtifactPaths:l}:{}}}async function $(e,t){let r=e.meta?.installSource;if("install_source"!==e.command||!r||"path"!==r.kind)return null;let a=r.path.trim();if(!a)return{installSource:r};if(a.startsWith("remote:"))return{installSource:{...r,path:a.slice(7)}};let i=o.isAbsolute(a)?a:o.resolve(e.meta?.cwd??process.cwd(),a);if(!n.existsSync(i))return{installSource:{...r,path:i}};let s=await N({localPath:i,baseUrl:t.baseUrl,token:t.token});return{installSource:{...r,path:i},uploadedArtifactId:s}}function F(e,t,r,n=0){let a=e.positionals?.[n]??e.flags?.out,i=`${"path"===t?"screenshot":"recording"}-${Date.now()}${r}`,s=a&&a.trim().length>0?a:i;return o.isAbsolute(s)?s:o.resolve(e.meta?.cwd??process.cwd(),s)}function q(e,t){let r=t.startsWith(".")?t:`.${t}`;return o.posix.join("/tmp",`agent-device-${e}-${Date.now()}-${Math.random().toString(36).slice(2,8)}${r}`)}async function j(e){let t;if(e.remoteBaseUrl){let t={transport:"http",token:e.remoteAuthToken??"",pid:0,baseUrl:e.remoteBaseUrl};if(await Y(t,"http"))return t;throw new w("COMMAND_FAILED","Remote daemon is unavailable",{daemonBaseUrl:e.remoteBaseUrl,hint:"Verify AGENT_DEVICE_DAEMON_BASE_URL points to a reachable daemon with GET /health and POST /rpc."})}let r=H(e.paths.infoPath),a=function(){try{let e=b();return JSON.parse(n.readFileSync(o.join(e,"package.json"),"utf8")).version??"0.0.0"}catch{return"0.0.0"}}(),i=function(e,t=b()){try{let r=n.statSync(e),a=o.relative(t,e)||e;return`${a}:${r.size}:${Math.trunc(r.mtimeMs)}`}catch{return"unknown"}}((t=Z()).useSrc?t.srcPath:t.distPath,t.root),s=!!r&&await Y(r,e.transportPreference);if(r&&r.version===a&&r.codeSignature===i&&s)return r;r&&(r.version!==a||r.codeSignature!==i||!s)&&(await z(r),X(e.paths.infoPath)),function(e){let t=K(e);if(!t.hasLock||t.hasInfo)return;let r=J(e.lockPath);if(!r)return X(e.lockPath);D(r.pid,r.processStartTime)||X(e.lockPath)}(e.paths);let l=0;for(let t=1;t<=U;t+=1){await Q(e);let r=await B(O,e);if(r)return r;if(await V(e.paths)){l+=1;continue}let n=K(e.paths);if(!(t<U))break;if(!n.hasInfo&&!n.hasLock){await G(150);continue}}let d=K(e.paths);throw new w("COMMAND_FAILED","Failed to start daemon",{kind:"daemon_startup_failed",infoPath:e.paths.infoPath,lockPath:e.paths.lockPath,startupTimeoutMs:O,startupAttempts:U,lockRecoveryCount:l,metadataState:d,hint:function(e,t=T(process.env.AGENT_DEVICE_STATE_DIR)){return e.hasLock&&!e.hasInfo?`Detected ${t.lockPath} without ${t.infoPath}. If no agent-device daemon process is running, delete ${t.lockPath} and retry.`:e.hasLock&&e.hasInfo?`Daemon metadata may be stale. If no agent-device daemon process is running, delete ${t.infoPath} and ${t.lockPath}, then retry.`:`Daemon metadata is missing or stale. Delete ${t.infoPath} if present and retry.`}(d,e.paths)})}async function B(e,t){let r=Date.now();for(;Date.now()-r<e;){let e=H(t.paths.infoPath);if(e&&await Y(e,t.transportPreference))return e;await new Promise(e=>setTimeout(e,100))}return null}async function G(e){await new Promise(t=>setTimeout(t,e))}async function V(e){let t=K(e);if(!t.hasLock||t.hasInfo)return!1;let r=J(e.lockPath);return r&&D(r.pid,r.processStartTime)&&await S(r.pid,{termTimeoutMs:3e3,killTimeoutMs:1e3,expectedStartTime:r.processStartTime}),X(e.lockPath),!0}async function z(e){await S(e.pid,{termTimeoutMs:3e3,killTimeoutMs:1e3,expectedStartTime:e.processStartTime})}function H(e){let t=W(e);if(!t||"object"!=typeof t)return null;let r="string"==typeof t.token&&t.token.length>0?t.token:null;if(!r)return null;let n=Number.isInteger(t.port)&&Number(t.port)>0,o=Number.isInteger(t.httpPort)&&Number(t.httpPort)>0;if(!n&&!o)return null;let a=t.transport,i="string"==typeof t.version?t.version:void 0,s="string"==typeof t.codeSignature?t.codeSignature:void 0,l="string"==typeof t.processStartTime?t.processStartTime:void 0,d=Number.isInteger(t.pid)&&Number(t.pid)>0;return{token:r,port:n?Number(t.port):void 0,httpPort:o?Number(t.httpPort):void 0,transport:"socket"===a||"http"===a||"dual"===a?a:void 0,pid:d?Number(t.pid):0,version:i,codeSignature:s,processStartTime:l}}function J(e){let t=W(e);return t&&"object"==typeof t&&Number.isInteger(t.pid)&&Number(t.pid)>0?{pid:Number(t.pid),processStartTime:"string"==typeof t.processStartTime?t.processStartTime:void 0,startedAt:"number"==typeof t.startedAt?t.startedAt:void 0}:null}function K(e){return{hasInfo:n.existsSync(e.infoPath),hasLock:n.existsSync(e.lockPath)}}function W(e){if(!n.existsSync(e))return null;try{return JSON.parse(n.readFileSync(e,"utf8"))}catch{return null}}function X(e){try{n.existsSync(e)&&n.unlinkSync(e)}catch{}}async function Y(n,o){var a;return"http"===et(n,o)?await function(e){let n=e.baseUrl?el(e.baseUrl,"health"):e.httpPort?`http://127.0.0.1:${e.httpPort}/health`:null;if(!n)return Promise.resolve(!1);let o=new URL(n),a="https:"===o.protocol?r:t,i=e.baseUrl?3e3:500;return new Promise(e=>{let t=a.request({protocol:o.protocol,host:o.hostname,port:o.port,path:o.pathname+o.search,method:"GET",timeout:i},t=>{t.resume(),e((t.statusCode??500)<500)});t.on("timeout",()=>{t.destroy(),e(!1)}),t.on("error",()=>{e(!1)}),t.end()})}(n):await ((a=n.port)?new Promise(t=>{let r=e.createConnection({host:"127.0.0.1",port:a},()=>{r.destroy(),t(!0)});r.on("error",()=>{t(!1)})}):Promise.resolve(!1))}async function Q(e){let t=Z(),r=t.useSrc?["--experimental-strip-types",t.srcPath]:[t.distPath],n={...process.env,AGENT_DEVICE_STATE_DIR:e.paths.baseDir,AGENT_DEVICE_DAEMON_SERVER_MODE:e.serverMode};!function(e,t,r={}){l(e,t,{cwd:r.cwd,env:r.env,stdio:"ignore",detached:!0}).unref()}(process.execPath,r,{env:n})}function Z(){let e=b(),t=o.join(e,"dist","src","daemon.js"),r=o.join(e,"src","daemon.ts"),a=n.existsSync(t),i=n.existsSync(r);if(!a&&!i)throw new w("COMMAND_FAILED","Daemon entry not found",{distPath:t,srcPath:r});return{root:e,distPath:t,srcPath:r,useSrc:process.execArgv.includes("--experimental-strip-types")?i:!a&&i}}async function ee(e,t,r){return"http"===et(e,r)?await eo(e,t):await en(e,t)}function et(e,t){if(e.baseUrl){if("socket"===t)throw new w("COMMAND_FAILED","Remote daemon endpoint only supports HTTP transport",{daemonBaseUrl:e.baseUrl});return"http"}if("http"===t||"socket"===t){var r=e,n=t;if(er(r,n))return n;throw new w("COMMAND_FAILED","http"===n?"Daemon HTTP endpoint is unavailable":"Daemon socket endpoint is unavailable")}let o=("socket"===e.transport||"dual"===e.transport?["socket","http"]:["http","socket"]).find(t=>er(e,t));if(o)return o;throw new w("COMMAND_FAILED","Daemon metadata has no reachable transport")}function er(e,t){return"http"===t?!!e.httpPort:!!e.port}async function en(t,r){let n=t.port;if(!n)throw new w("COMMAND_FAILED","Daemon socket endpoint is unavailable");return new Promise((o,a)=>{let i=e.createConnection({host:"127.0.0.1",port:n},()=>{i.write(`${JSON.stringify(r)}
|
|
3
|
+
`)}),s=setTimeout(()=>{i.destroy();let e=ea(),n=ei(t,T(r.flags?.stateDir??process.env.AGENT_DEVICE_STATE_DIR));h({level:"error",phase:"daemon_request_timeout",data:{timeoutMs:R,requestId:r.meta?.requestId,command:r.command,timedOutRunnerPidsTerminated:e.terminated,timedOutRunnerCleanupError:e.error,daemonPidReset:t.pid,daemonPidForceKilled:n.forcedKill}}),a(new w("COMMAND_FAILED","Daemon request timed out",{timeoutMs:R,requestId:r.meta?.requestId,hint:"Retry with --debug and check daemon diagnostics logs. Timed-out iOS runner xcodebuild processes were terminated when detected."}))},R),l="";i.setEncoding("utf8"),i.on("data",e=>{let t=(l+=e).indexOf("\n");if(-1===t)return;let n=l.slice(0,t).trim();if(n)try{let e=JSON.parse(n);i.end(),clearTimeout(s),o(e)}catch(e){clearTimeout(s),a(new w("COMMAND_FAILED","Invalid daemon response",{requestId:r.meta?.requestId,line:n},e instanceof Error?e:void 0))}}),i.on("error",e=>{clearTimeout(s),h({level:"error",phase:"daemon_request_socket_error",data:{requestId:r.meta?.requestId,message:e instanceof Error?e.message:String(e)}}),a(new w("COMMAND_FAILED","Failed to communicate with daemon",{requestId:r.meta?.requestId,hint:"Retry command. If this persists, clean stale daemon metadata and start a fresh session."},e))})})}async function eo(e,n){let o=e.baseUrl?new URL(el(e.baseUrl,"rpc")):e.httpPort?new URL(`http://127.0.0.1:${e.httpPort}/rpc`):null;if(!o)throw new w("COMMAND_FAILED","Daemon HTTP endpoint is unavailable");let a=JSON.stringify({jsonrpc:"2.0",id:n.meta?.requestId??f(),method:"agent_device.command",params:n}),i={"content-type":"application/json","content-length":Buffer.byteLength(a)};return e.baseUrl&&e.token&&(i.authorization=`Bearer ${e.token}`,i["x-agent-device-token"]=e.token),await new Promise((s,l)=>{let d=T(n.flags?.stateDir??process.env.AGENT_DEVICE_STATE_DIR),u=("https:"===o.protocol?r:t).request({protocol:o.protocol,host:o.hostname,port:o.port,method:"POST",path:o.pathname+o.search,headers:i},t=>{let r="";t.setEncoding("utf8"),t.on("data",e=>{r+=e}),t.on("end",()=>{clearTimeout(c);try{let t=JSON.parse(r);if(t.error){let e=t.error.data??{};l(new w(String(e.code??"COMMAND_FAILED"),String(e.message??t.error.message??"Daemon RPC request failed"),{..."object"==typeof e.details&&e.details?e.details:{},hint:"string"==typeof e.hint?e.hint:void 0,diagnosticId:"string"==typeof e.diagnosticId?e.diagnosticId:void 0,logPath:"string"==typeof e.logPath?e.logPath:void 0,requestId:n.meta?.requestId}));return}if(!t.result||"object"!=typeof t.result)return void l(new w("COMMAND_FAILED","Invalid daemon RPC response",{requestId:n.meta?.requestId}));if(e.baseUrl&&t.result.ok)return void ed(e,n,t.result).then(s).catch(l);s(t.result)}catch(e){clearTimeout(c),l(new w("COMMAND_FAILED","Invalid daemon response",{requestId:n.meta?.requestId,line:r},e instanceof Error?e:void 0))}})}),c=setTimeout(()=>{u.destroy();let t=es(e)?{terminated:0}:ea(),r=es(e)?{forcedKill:!1}:ei(e,d);h({level:"error",phase:"daemon_request_timeout",data:{timeoutMs:R,requestId:n.meta?.requestId,command:n.command,timedOutRunnerPidsTerminated:t.terminated,timedOutRunnerCleanupError:t.error,daemonPidReset:es(e)?void 0:e.pid,daemonPidForceKilled:es(e)?void 0:r.forcedKill,daemonBaseUrl:e.baseUrl}}),l(new w("COMMAND_FAILED","Daemon request timed out",{timeoutMs:R,requestId:n.meta?.requestId,hint:es(e)?"Retry with --debug and verify the remote daemon URL, auth token, and remote host logs.":"Retry with --debug and check daemon diagnostics logs. Timed-out iOS runner xcodebuild processes were terminated when detected."}))},R);u.on("error",t=>{clearTimeout(c),h({level:"error",phase:"daemon_request_socket_error",data:{requestId:n.meta?.requestId,message:t instanceof Error?t.message:String(t)}}),l(new w("COMMAND_FAILED","Failed to communicate with daemon",{requestId:n.meta?.requestId,hint:es(e)?"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."},t))}),u.write(a),u.end()})}function ea(){let e=0;try{for(let t of C){let r=I("pkill",["-f",t],{allowFailure:!0});0===r.exitCode&&(e+=1)}return{terminated:e}}catch(t){return{terminated:e,error:t instanceof Error?t.message:String(t)}}}function ei(e,t){let r=!1;try{D(e.pid,e.processStartTime)&&(process.kill(e.pid,"SIGKILL"),r=!0)}catch{S(e.pid,{termTimeoutMs:3e3,killTimeoutMs:1e3,expectedStartTime:e.processStartTime})}finally{X(t.infoPath),X(t.lockPath)}return{forcedKill:r}}function es(e){return"string"==typeof e.baseUrl&&e.baseUrl.length>0}function el(e,t){return new URL(t,e.endsWith("/")?e:`${e}/`).toString()}async function ed(e,t,r){let n=Array.isArray(r.data?.artifacts)?r.data.artifacts:[];if(0===n.length||!e.baseUrl)return r;let a=r.data?{...r.data}:{},i=[];for(let r of n){if(!r||"object"!=typeof r||"string"!=typeof r.artifactId){i.push(r);continue}let n=function(e,t){if(e.localPath&&e.localPath.trim().length>0)return e.localPath;let r=e.fileName?.trim()||`${e.field}-${Date.now()}`;return o.resolve(t.meta?.cwd??process.cwd(),r)}(r,t);await eu({baseUrl:e.baseUrl,token:e.token,artifactId:r.artifactId,destinationPath:n,requestId:t.meta?.requestId}),a[r.field]=n,i.push({...r,localPath:n})}return a.artifacts=i,{ok:!0,data:a}}async function eu(e){var a,i;let s,l=new URL((a=e.baseUrl,i=e.artifactId,s=a.endsWith("/")?a:`${a}/`,new URL(`upload/${encodeURIComponent(i)}`,s).toString())),d="https:"===l.protocol?r:t;await n.promises.mkdir(o.dirname(e.destinationPath),{recursive:!0}),await new Promise((t,r)=>{let o=!1,a=e.timeoutMs??R,i=a=>{if(!o){if(o=!0,clearTimeout(u),a)return void n.promises.rm(e.destinationPath,{force:!0}).finally(()=>r(a));t()}},s=d.request({protocol:l.protocol,host:l.hostname,port:l.port,method:"GET",path:l.pathname+l.search,headers:e.token?{authorization:`Bearer ${e.token}`,"x-agent-device-token":e.token}:void 0},t=>{if((t.statusCode??500)>=400){let r="";t.setEncoding("utf8"),t.on("data",e=>{r+=e}),t.on("end",()=>{i(new w("COMMAND_FAILED","Failed to download remote artifact",{artifactId:e.artifactId,statusCode:t.statusCode,requestId:e.requestId,body:r}))});return}let r=n.createWriteStream(e.destinationPath);r.on("error",e=>{i(e instanceof Error?e:Error(String(e)))}),t.on("error",e=>{i(e instanceof Error?e:Error(String(e)))}),t.on("aborted",()=>{i(new w("COMMAND_FAILED","Remote artifact download was interrupted",{artifactId:e.artifactId,requestId:e.requestId}))}),r.on("finish",()=>{r.close(()=>i())}),t.pipe(r)}),u=setTimeout(()=>{s.destroy(new w("COMMAND_FAILED","Remote artifact download timed out",{artifactId:e.artifactId,requestId:e.requestId,timeoutMs:a}))},a);s.on("error",t=>{t instanceof w?i(t):i(new w("COMMAND_FAILED","Failed to download remote artifact",{artifactId:e.artifactId,requestId:e.requestId,timeoutMs:a},t instanceof Error?t:void 0))}),s.end()})}function ec(e){return e.replace(/\/+$/,"")}function em(e){return"string"==typeof e&&e.trim()?ec(e.trim()):""}function ep(e){return"string"==typeof e&&e.trim()?e.trim():void 0}function ef(e,t,r){return k(e,{env:t,cwd:r})}function eh(e){try{return n.accessSync(e,n.constants.F_OK),!0}catch{return!1}}function eg(e,t,r){if(null==e||""===e)return t;let n=Number.parseInt(String(e),10);return Number.isInteger(n)?Math.max(n,r):t}function ew(e,t){let r;return{platform:t,bundleUrl:((r=new URL(`${ec(e)}/index.bundle`)).searchParams.set("platform",t),r.searchParams.set("dev","true"),r.searchParams.set("minify","false"),r.toString())}}function eI(e,t){return{platform:t,metroHost:ep(e?.metro_host),metroPort:e?.metro_port,bundleUrl:ep(e?.metro_bundle_url),launchUrl:ep(e?.launch_url)}}function ey(e){return`'${e.replace(/'/g,"'\"'\"'")}'`}async function eb(e){await new Promise(t=>setTimeout(t,e))}async function ev(e,t,r={}){try{let n=await fetch(e,{headers:r,signal:AbortSignal.timeout(t)});return{ok:n.ok,status:n.status,body:await n.text()}}catch(r){if(r instanceof Error&&"TimeoutError"===r.name)throw Error(`Timed out fetching ${e} after ${t}ms`);throw r}}async function eA(e,t){try{let r=await ev(e,t);return r.ok&&r.body.includes("packager-status:running")}catch{return!1}}async function eD(e){var t,r,n;let o;try{o=await fetch(`${e.baseUrl}/api/metro/bridge`,{method:"POST",headers:(t=e.baseUrl,r=e.bearerToken,{Authorization:`Bearer ${r}`,"Content-Type":"application/json",...t.includes("ngrok")?{"ngrok-skip-browser-warning":"1"}:{}}),body:JSON.stringify({ios_runtime:e.runtime,timeout_ms:e.timeoutMs}),signal:AbortSignal.timeout(e.timeoutMs)})}catch(t){if(t instanceof Error&&"TimeoutError"===t.name)throw Error(`/api/metro/bridge timed out after ${e.timeoutMs}ms calling ${e.baseUrl}/api/metro/bridge`);throw t}let a=await o.text(),i=a?JSON.parse(a):{};if(!o.ok)throw Error(`/api/metro/bridge failed (${o.status}): ${JSON.stringify(i)}`);return{enabled:(n=i.data??i).enabled,baseUrl:n.base_url,statusUrl:n.status_url,bundleUrl:n.bundle_url,iosRuntime:eI(n.ios_runtime,"ios"),androidRuntime:eI(n.android_runtime,"android"),upstream:{bundleUrl:n.upstream.bundle_url,host:n.upstream.host,port:n.upstream.port,statusUrl:n.upstream.status_url},probe:{reachable:n.probe.reachable,statusCode:n.probe.status_code,latencyMs:n.probe.latency_ms,detail:n.probe.detail}}}async function eE(e,t,r){let n=Date.now()+t;for(;Date.now()<n;){let t=Math.min(r,Math.max(n-Date.now(),1));if(await eA(e,t))return!0;let o=Math.min(500,Math.max(n-Date.now(),0));o>0&&await eb(o)}return!1}async function eM(e={}){let t=e.env??process.env,r=process.cwd(),a=ef(e.projectRoot??r,t,r),i=function(e,t){if("auto"!==t)return t;let r=function(e){let t=o.join(e,"package.json");if(!eh(t))throw new w("INVALID_ARGS",`package.json not found at ${t}`);return JSON.parse(n.readFileSync(t,"utf8"))}(e);return"string"==typeof({...r.dependencies??{},...r.devDependencies??{}}).expo?"expo":"react-native"}(a,e.kind??"auto"),s=function(e,t){if(null==e||""===e)return 8081;let r=Number.parseInt(String(e),10);if(!Number.isInteger(r)||r<1||r>65535)throw new w("INVALID_ARGS",`Invalid Metro port: ${String(e)}. Use 1-65535.`);return r}(e.metroPort??8081,0),l=ep(e.listenHost)??"0.0.0.0",d=ep(e.statusHost)??"127.0.0.1",u=em(e.publicBaseUrl),c=eg(e.startupTimeoutMs,18e4,3e4),m=eg(e.probeTimeoutMs,1e4,1e3),p=e.reuseExisting??!0,f=e.installDependenciesIfNeeded??!0,h=e.runtimeFilePath?ef(e.runtimeFilePath,t,r):null,g=ef(e.logPath??o.join(a,".agent-device","metro.log"),t,r);if(!u)throw new w("INVALID_ARGS","metro prepare requires --public-base-url <url>.");let{proxyEnabled:y,proxyBaseUrl:b,proxyBearerToken:v}=function(e,t){if(e&&!t)throw new w("INVALID_ARGS","metro prepare requires proxy auth when --proxy-base-url is provided. Pass --bearer-token or set AGENT_DEVICE_PROXY_TOKEN.");if(!e&&t)throw new w("INVALID_ARGS","metro prepare requires --proxy-base-url when proxy auth is provided.");return{proxyEnabled:!!(e&&t),proxyBaseUrl:e,proxyBearerToken:t}}(em(e.proxyBaseUrl),ep(e.proxyBearerToken)??""),A=f?function(e,t){if(function(e){try{return n.statSync(e).isDirectory()}catch{return!1}}(o.join(e,"node_modules")))return{installed:!1};let r=eh(o.join(e,"pnpm-lock.yaml"))?{command:"pnpm",installArgs:["install"]}:eh(o.join(e,"yarn.lock"))?{command:"yarn",installArgs:["install"]}:{command:"npm",installArgs:["install"]};return I(r.command,r.installArgs,{cwd:e,env:t}),{installed:!0,packageManager:r.command}}(a,t):{installed:!1},D=`http://${d}:${s}/status`,E=!1,M=!1,S=0;if(p&&await eA(D,m))M=!0;else if(E=!0,S=function(e,t,r,a,i,s){let l="expo"===t?{command:"npx",installArgs:["expo","start","--host","lan","--port",String(r)]}:{command:"npx",installArgs:["react-native","start","--host",a,"--port",String(r)]};n.mkdirSync(o.dirname(i),{recursive:!0});let d=[ey(l.command),...l.installArgs.map(ey)].join(" "),u=I("/bin/sh",["-c",`nohup ${d} >> ${ey(i)} 2>&1 < /dev/null & echo $!`],{cwd:e,env:s}),c=Number.parseInt(u.stdout.trim(),10);if(!Number.isInteger(c)||c<=0)throw Error(`Failed to start Metro. Expected a child PID in stdout, got "${u.stdout.trim()}".`);return{pid:c}}(a,i,s,l,g,t).pid,!await eE(D,c,m))throw Error(`Metro did not become ready at ${D} within ${c}ms. Check ${g}.`);let _=ew(u,"ios"),P=ew(u,"android"),k=null,T=null;if(y)try{k=await eD({baseUrl:b,bearerToken:v,runtime:{metro_bundle_url:_.bundleUrl},timeoutMs:m})}catch(e){T=e instanceof Error?e.message:String(e)}if(y&&(!k||!1===k.probe.reachable)){var N,R;let e;throw Error((N=T,R=k,e=[`Metro bridge is required for this run but could not be configured via ${b}/api/metro/bridge.`],N&&e.push(`bridgeError=${N}`),R?.probe.reachable===!1&&e.push(`bridgeProbe=${R.probe.detail||`unreachable (status ${R.probe.statusCode||0})`}`),e.join(" ")))}let O=k?.iosRuntime??_,U=k?.androidRuntime??P,C={projectRoot:a,kind:i,dependenciesInstalled:A.installed,packageManager:A.packageManager??null,started:E,reused:M,pid:S,logPath:g,statusUrl:D,runtimeFilePath:h,iosRuntime:O,androidRuntime:U,bridge:k};return h&&(n.mkdirSync(o.dirname(h),{recursive:!0}),n.writeFileSync(h,JSON.stringify(C,null,2))),C}function eS(e){let t=e.appId??e.bundleId??e.packageName;return{session:e.session,appId:t,appBundleId:e.bundleId,package:e.packageName}}function e_(e,t,r){return{deviceId:t,deviceName:r,..."android"===e?{serial:t}:"ios"===e?{udid:t}:{}}}function eP(e,t){let r=ex(e,"bundleId"),n=ex(e,"package");return{app:eC(e,"app"),appPath:eC(e,"appPath"),platform:eL(e,"platform"),appId:r??n,bundleId:r,package:n,identifiers:eS({session:t,bundleId:r,packageName:n})}}function ek(e){var t;let r=eO(e),n=eL(r,"platform"),o=eC(r,"id"),a=eC(r,"name");return{platform:n,target:e$(r,"target"),kind:eF(r,t="kind",eV,`Daemon response has invalid "${t}".`),id:o,name:a,booted:"boolean"==typeof r.booted?r.booted:void 0,identifiers:e_(n,o,a),ios:"ios"===n?{udid:o}:void 0,android:"android"===n?{serial:o}:void 0}}function eT(e){var t;let r=eO(e),n=eL(r,"platform"),o=eC(r,"id"),a=eC(r,"name"),i=e$(r,"target"),s=eC(r,"device"),l={session:a,...e_(n,o,s)};return{name:a,createdAt:eF(r,t="createdAt",eB,`Daemon response is missing numeric "${t}".`),device:{platform:n,target:i,id:o,name:s,identifiers:l,ios:"ios"===n?{udid:o,simulatorSetPath:eq(r,"ios_simulator_device_set",ej)}:void 0,android:"android"===n?{serial:o}:void 0},identifiers:l}}function eN(e,t){return t??e??"default"}function eR(e){let t={};for(let[r,n]of Object.entries(e))void 0!==n&&(t[r]=n);return t}function eO(e){if(!eU(e))throw new w("COMMAND_FAILED","Daemon returned an unexpected response shape.",{value:e});return e}function eU(e){return"object"==typeof e&&null!==e}function eC(e,t){return eF(e,t,ej,`Daemon response is missing "${t}".`)}function ex(e,t){return ej(e[t])}function eL(e,t){return eF(e,t,eG,`Daemon response has invalid "${t}".`)}function e$(e,t){return ez(e[t])??"mobile"}function eF(e,t,r,n){let o=r(e[t]);if(void 0===o)throw new w("COMMAND_FAILED",n,{response:e});return o}function eq(e,t,r){let n=e[t];return null===n?null:r(n)}function ej(e){return"string"==typeof e&&e.length>0?e:void 0}function eB(e){return"number"==typeof e&&Number.isFinite(e)?e:void 0}function eG(e){return"ios"===e||"macos"===e||"android"===e?e:void 0}function eV(e){return"simulator"===e||"emulator"===e||"device"===e?e:void 0}function ez(e){return"tv"===e||"mobile"===e||"desktop"===e?e:void 0}function eH(e={},t={}){let r=t.transport??x,n=async(t,n=[],o={})=>{let a={...e,...o},i=await r({session:eN(e.session,o.session),command:t,positionals:n,flags:eR({stateDir:a.stateDir,daemonBaseUrl:a.daemonBaseUrl,daemonAuthToken:a.daemonAuthToken,daemonTransport:a.daemonTransport,daemonServerMode:a.daemonServerMode,tenant:a.tenant,sessionIsolation:a.sessionIsolation,runId:a.runId,leaseId:a.leaseId,platform:a.platform,target:a.target,device:a.device,udid:a.udid,serial:a.serial,iosSimulatorDeviceSet:a.iosSimulatorDeviceSet,androidDeviceAllowlist:a.androidDeviceAllowlist,runtime:a.simulatorRuntimeId,boot:a.boot,reuseExisting:a.reuseExisting,activity:a.activity,relaunch:a.relaunch,shutdown:a.shutdown,saveScript:a.saveScript,noRecord:a.noRecord,metroHost:a.metroHost,metroPort:a.metroPort,bundleUrl:a.bundleUrl,launchUrl:a.launchUrl,snapshotInteractiveOnly:a.interactiveOnly,snapshotCompact:a.compact,snapshotDepth:a.depth,snapshotScope:a.scope,snapshotRaw:a.raw,verbose:a.debug}),runtime:a.runtime,meta:eR({requestId:a.requestId,cwd:a.cwd,debug:a.debug,lockPolicy:a.lockPolicy,lockPlatform:a.lockPlatform,tenantId:a.tenant,runId:a.runId,leaseId:a.leaseId,sessionIsolation:a.sessionIsolation,installSource:a.installSource,retainMaterializedPaths:a.retainMaterializedPaths,materializedPathRetentionMs:a.materializedPathRetentionMs,materializationId:a.materializationId})});if(!i.ok)throw new w(i.error.code,i.error.message,{...i.error.details??{},hint:i.error.hint,diagnosticId:i.error.diagnosticId,logPath:i.error.logPath});return i.data??{}},o=async(e={})=>{let t=await n("session_list",[],e);return(Array.isArray(t.sessions)?t.sessions:[]).map(eT)};return{devices:{list:async(e={})=>{let t=await n("devices",[],e);return(Array.isArray(t.devices)?t.devices:[]).map(ek)}},sessions:{list:async(e={})=>await o(e),close:async(t={})=>{let r=eN(e.session,t.session),o=(await n("close",[],t)).shutdown;return{session:r,shutdown:"object"==typeof o&&null!==o?o:void 0,identifiers:{session:r}}}},simulators:{ensure:async e=>{let{runtime:t,...r}=e,o=await n("ensure-simulator",[],{...r,simulatorRuntimeId:t}),a=eC(o,"udid"),i=eC(o,"device");return{udid:a,device:i,runtime:eC(o,"runtime"),created:!0===o.created,booted:!0===o.booted,iosSimulatorDeviceSet:eq(o,"ios_simulator_device_set",ej),identifiers:{deviceId:a,deviceName:i,udid:a}}}},apps:{install:async t=>eP(await n("install",[t.app,t.appPath],t),eN(e.session,t.session)),reinstall:async t=>eP(await n("reinstall",[t.app,t.appPath],t),eN(e.session,t.session)),installFromSource:async t=>(function(e,t){let r=ex(e,"bundleId"),n=ex(e,"packageName"),o=r??n??ex(e,"appId"),a=ex(e,"launchTarget")??n??r??o;if(!a)throw new w("COMMAND_FAILED",'Daemon response is missing "launchTarget".',{response:e});return{appName:ex(e,"appName"),appId:o,bundleId:r,packageName:n,launchTarget:a,installablePath:ex(e,"installablePath"),archivePath:ex(e,"archivePath"),materializationId:ex(e,"materializationId"),materializationExpiresAt:ex(e,"materializationExpiresAt"),identifiers:eS({session:t,bundleId:r,packageName:n,appId:o})}})(await n("install_source",[],{...t,installSource:t.source,retainMaterializedPaths:t.retainPaths,materializedPathRetentionMs:t.retentionMs}),eN(e.session,t.session)),open:async t=>{let r=eN(e.session,t.session),o=t.url?[t.app,t.url]:[t.app],a=await n("open",o,t),i=function(e){let t=e.platform,r=ex(e,"id"),n=ex(e,"device");if("ios"!==t&&"macos"!==t&&"android"!==t||!r||!n)return;let o=e$(e,"target"),a=e_(t,r,n);return{platform:t,target:o,id:r,name:n,identifiers:a,ios:"ios"===t?{udid:ex(e,"device_udid")??r,simulatorSetPath:eq(e,"ios_simulator_device_set",ej)}:void 0,android:"android"===t?{serial:ex(e,"serial")??r}:void 0}}(a),s=ex(a,"appBundleId");return{session:r,appName:ex(a,"appName"),appBundleId:s,appId:s,startup:function(e){if(eU(e)&&"number"==typeof e.durationMs&&"string"==typeof e.measuredAt&&"string"==typeof e.method)return{durationMs:e.durationMs,measuredAt:e.measuredAt,method:e.method,appTarget:ex(e,"appTarget"),appBundleId:ex(e,"appBundleId")}}(a.startup),runtime:function(e){if(!eU(e))return;let t=e.platform,r=ex(e,"metroHost"),n="number"==typeof e.metroPort?e.metroPort:void 0;return{platform:"ios"===t||"android"===t?t:void 0,metroHost:r,metroPort:n,bundleUrl:ex(e,"bundleUrl"),launchUrl:ex(e,"launchUrl")}}(a.runtime),device:i,identifiers:{session:r,deviceId:i?.id,deviceName:i?.name,udid:i?.ios?.udid,serial:i?.android?.serial,appId:s,appBundleId:s}}},close:async(t={})=>{let r=eN(e.session,t.session),o=(await n("close",t.app?[t.app]:[],t)).shutdown;return{session:r,closedApp:t.app,shutdown:"object"==typeof o&&null!==o?o:void 0,identifiers:{session:r}}}},materializations:{release:async e=>{var t;return{released:!0===(t=await n("release_materialized_paths",[],{...e,materializationId:e.materializationId})).released,materializationId:eC(t,"materializationId"),identifiers:{}}}},metro:{prepare:async t=>await eM({projectRoot:t.projectRoot??e.cwd,kind:t.kind,publicBaseUrl:t.publicBaseUrl,proxyBaseUrl:t.proxyBaseUrl,proxyBearerToken:t.bearerToken,metroPort:t.port,listenHost:t.listenHost,statusHost:t.statusHost,startupTimeoutMs:t.startupTimeoutMs,probeTimeoutMs:t.probeTimeoutMs,reuseExisting:t.reuseExisting,installDependenciesIfNeeded:t.installDependenciesIfNeeded,runtimeFilePath:t.runtimeFilePath,logPath:t.logPath})},capture:{snapshot:async(t={})=>{var r;let o=eN(e.session,t.session),a=await n("snapshot",[],t),i=ex(a,"appBundleId");return{nodes:Array.isArray(r=a.nodes)?r:[],truncated:!0===a.truncated,appName:ex(a,"appName"),appBundleId:i,identifiers:{session:o,appId:i,appBundleId:i}}},screenshot:async(t={})=>{let r=eN(e.session,t.session);return{path:eC(await n("screenshot",t.path?[t.path]:[],t),"path"),identifiers:{session:r}}}}}}export{eH as createAgentDeviceClient,w as AppError};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "agent-device",
|
|
3
|
-
"version": "0.10.
|
|
3
|
+
"version": "0.10.3",
|
|
4
4
|
"description": "Unified control plane for physical and virtual devices via an agent-driven CLI.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"author": "Callstack",
|
|
@@ -73,6 +73,7 @@
|
|
|
73
73
|
"pngjs": "^7.0.0"
|
|
74
74
|
},
|
|
75
75
|
"devDependencies": {
|
|
76
|
+
"@microsoft/api-extractor": "^7.52.10",
|
|
76
77
|
"@rslib/core": "0.19.4",
|
|
77
78
|
"@types/node": "^22.0.0",
|
|
78
79
|
"@types/pngjs": "^6.0.5",
|